From 4c91880a858c1936985e5b08af4160f8278db36e Mon Sep 17 00:00:00 2001 From: Sven Van de Velde Date: Sun, 25 Mar 2018 20:27:18 +0200 Subject: [PATCH 01/14] Improved dynamic loader process --- .../Moose/{Moose.lua => Globals.lua} | 0 Moose Setup/Moose_Create.lua | 19 +++++++++++-------- 2 files changed, 11 insertions(+), 8 deletions(-) rename Moose Development/Moose/{Moose.lua => Globals.lua} (100%) diff --git a/Moose Development/Moose/Moose.lua b/Moose Development/Moose/Globals.lua similarity index 100% rename from Moose Development/Moose/Moose.lua rename to Moose Development/Moose/Globals.lua diff --git a/Moose Setup/Moose_Create.lua b/Moose Setup/Moose_Create.lua index 500a56965..5bfd2ed6d 100644 --- a/Moose Setup/Moose_Create.lua +++ b/Moose Setup/Moose_Create.lua @@ -17,10 +17,10 @@ local MooseFilePath = MooseTargetPath.."/Moose.lua" print( "Reading Moose source list : " .. MooseSourcesFilePath ) -local MooseFile = io.open( MooseFilePath, "w" ) +local LoaderFile = io.open( MooseFilePath, "w" ) if MooseDynamicStatic == "S" then - MooseFile:write( "env.info( '*** MOOSE GITHUB Commit Hash ID: " .. MooseCommitHash .. " ***' )\n" ) + LoaderFile:write( "env.info( '*** MOOSE GITHUB Commit Hash ID: " .. MooseCommitHash .. " ***' )\n" ) end local MooseLoaderPath @@ -31,12 +31,14 @@ if MooseDynamicStatic == "S" then MooseLoaderPath = MooseSetupPath .. "/Moose Templates/Moose_Static_Loader.lua" end +local MooseFile = io.open( MooseFilePath, "w" ) + local MooseLoader = io.open( MooseLoaderPath, "r" ) local MooseLoaderText = MooseLoader:read( "*a" ) MooseLoader:close() -MooseFile:write( MooseLoaderText ) - +LoaderFile:write( MooseLoaderText ) +LoaderFile:write( "__Moose.Include( 'Scripts/Moose/Moose.lua'\n" ) local MooseSourcesFile = io.open( MooseSourcesFilePath, "r" ) local MooseSource = MooseSourcesFile:read("*l") @@ -55,7 +57,7 @@ while( MooseSource ) do local MooseSourceFileText = MooseSourceFile:read( "*a" ) MooseSourceFile:close() - MooseFile:write( MooseSourceFileText ) + LoaderFile:write( MooseSourceFileText ) end end @@ -63,13 +65,14 @@ while( MooseSource ) do end if MooseDynamicStatic == "D" then - MooseFile:write( "BASE:TraceOnOff( true )\n" ) + LoaderFile:write( "BASE:TraceOnOff( true )\n" ) end if MooseDynamicStatic == "S" then - MooseFile:write( "BASE:TraceOnOff( false )\n" ) + LoaderFile:write( "BASE:TraceOnOff( false )\n" ) end -MooseFile:write( "env.info( '*** MOOSE INCLUDE END *** ' )\n" ) +LoaderFile:write( "env.info( '*** MOOSE INCLUDE END *** ' )\n" ) MooseSourcesFile:close() +LoaderFile:close() MooseFile:close() From 856bd56cdef97ebd15cd7ac428e2b5b5b210c169 Mon Sep 17 00:00:00 2001 From: Sven Van de Velde Date: Sun, 25 Mar 2018 20:33:43 +0200 Subject: [PATCH 02/14] Improved dynamic loading --- Moose Setup/Moose.files | 2 +- Moose Setup/Moose_Create.lua | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Moose Setup/Moose.files b/Moose Setup/Moose.files index 1e575f0f2..4459578ec 100644 --- a/Moose Setup/Moose.files +++ b/Moose Setup/Moose.files @@ -79,4 +79,4 @@ Tasking/Task_A2A.lua Tasking/Task_Cargo.lua Tasking/TaskZoneCapture.lua -Moose.lua +Globals.lua diff --git a/Moose Setup/Moose_Create.lua b/Moose Setup/Moose_Create.lua index 5bfd2ed6d..5a15f59ef 100644 --- a/Moose Setup/Moose_Create.lua +++ b/Moose Setup/Moose_Create.lua @@ -13,11 +13,12 @@ print( "Moose setup path : " .. MooseSetupPath ) print( "Moose target path : " .. MooseTargetPath ) local MooseSourcesFilePath = MooseSetupPath .. "/Moose.files" -local MooseFilePath = MooseTargetPath.."/Moose.lua" +local LoaderFilePath = MooseTargetPath.."/Moose.lua" +local MooseFilePath = MooseDevelopmentPath .. "/Moose.lua" print( "Reading Moose source list : " .. MooseSourcesFilePath ) -local LoaderFile = io.open( MooseFilePath, "w" ) +local LoaderFile = io.open( LoaderFilePath, "w" ) if MooseDynamicStatic == "S" then LoaderFile:write( "env.info( '*** MOOSE GITHUB Commit Hash ID: " .. MooseCommitHash .. " ***' )\n" ) From 74d2ee94307af6b8611c635f1e255da9b05b30ed Mon Sep 17 00:00:00 2001 From: Sven Van de Velde Date: Sun, 25 Mar 2018 20:49:49 +0200 Subject: [PATCH 03/14] Improvements --- Moose Setup/Moose_Create.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Moose Setup/Moose_Create.lua b/Moose Setup/Moose_Create.lua index 5a15f59ef..b076b8d87 100644 --- a/Moose Setup/Moose_Create.lua +++ b/Moose Setup/Moose_Create.lua @@ -14,7 +14,7 @@ print( "Moose target path : " .. MooseTargetPath ) local MooseSourcesFilePath = MooseSetupPath .. "/Moose.files" local LoaderFilePath = MooseTargetPath.."/Moose.lua" -local MooseFilePath = MooseDevelopmentPath .. "/Moose.lua" +local MooseFilePath = MooseTargetPath .. "/Loader.lua" print( "Reading Moose source list : " .. MooseSourcesFilePath ) From d098930351c2aaef2a9f05bc4e7735ab47792633 Mon Sep 17 00:00:00 2001 From: FlightControl Date: Tue, 11 Dec 2018 19:20:11 +0100 Subject: [PATCH 04/14] -- New SEAD, BAI and CAS files. -- Correct handling of task assignments. -- Added Weapon stuff in DCS.lua. -- Dispatcher optimizations. --- Moose Development/Moose/AI/AI_A2A.lua | 2 +- Moose Development/Moose/AI/AI_A2G_BAI.lua | 172 ++++++++++++++ Moose Development/Moose/AI/AI_A2G_CAS.lua | 173 ++++++++++++++ .../Moose/AI/AI_A2G_Dispatcher.lua | 36 ++- Moose Development/Moose/AI/AI_A2G_Engage.lua | 78 +------ Moose Development/Moose/AI/AI_A2G_Patrol.lua | 3 +- Moose Development/Moose/AI/AI_A2G_SEAD.lua | 218 ++++++++++++++++++ Moose Development/Moose/AI/AI_Air.lua | 6 +- Moose Development/Moose/DCS.lua | 122 ++++++++++ .../Moose/Wrapper/Controllable.lua | 55 ++++- Moose Setup/Moose.files | 3 + 11 files changed, 775 insertions(+), 93 deletions(-) create mode 100644 Moose Development/Moose/AI/AI_A2G_BAI.lua create mode 100644 Moose Development/Moose/AI/AI_A2G_CAS.lua create mode 100644 Moose Development/Moose/AI/AI_A2G_SEAD.lua diff --git a/Moose Development/Moose/AI/AI_A2A.lua b/Moose Development/Moose/AI/AI_A2A.lua index c96fa4e43..14c137dc2 100644 --- a/Moose Development/Moose/AI/AI_A2A.lua +++ b/Moose Development/Moose/AI/AI_A2A.lua @@ -489,7 +489,7 @@ function AI_A2A:onafterStatus() not self:Is( "Fuel" ) and not self:Is( "Damaged" ) and not self:Is( "Home" ) then - if self.IdleCount >= 2 then + if self.IdleCount >= 3 then if Damage ~= InitialLife then self:Damaged() else diff --git a/Moose Development/Moose/AI/AI_A2G_BAI.lua b/Moose Development/Moose/AI/AI_A2G_BAI.lua new file mode 100644 index 000000000..fb72297d9 --- /dev/null +++ b/Moose Development/Moose/AI/AI_A2G_BAI.lua @@ -0,0 +1,172 @@ +--- **AI** -- Models the process of air to ground BAI engagement for airplanes and helicopters. +-- +-- This is a class used in the @{AI_A2G_Dispatcher}. +-- +-- === +-- +-- ### Author: **FlightControl** +-- +-- === +-- +-- @module AI.AI_A2G_BAI +-- @image AI_Air_To_Ground_Engage.JPG + + + +--- @type AI_A2G_BAI +-- @extends AI.AI_A2A_Engage#AI_A2A_Engage + + +--- Implements the core functions to intercept intruders. Use the Engage trigger to intercept intruders. +-- +-- === +-- +-- @field #AI_A2G_BAI +AI_A2G_BAI = { + ClassName = "AI_A2G_BAI", +} + + + +--- Creates a new AI_A2G_BAI object +-- @param #AI_A2G_BAI self +-- @param Wrapper.Group#GROUP AIGroup +-- @return #AI_A2G_BAI +function AI_A2G_BAI:New( AIGroup, EngageMinSpeed, EngageMaxSpeed ) + + -- Inherits from BASE + local self = BASE:Inherit( self, AI_A2G_ENGAGE:New( AIGroup, EngageMinSpeed, EngageMaxSpeed ) ) -- #AI_A2G_BAI + + return self +end + +--- onafter event handler for Start event. +-- @param #AI_A2G_BAI self +-- @param Wrapper.Group#GROUP AIGroup The AI group 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 AI_A2G_BAI:onafterStart( AIGroup, From, Event, To ) + + self:GetParent( self ).onafterStart( self, AIGroup, From, Event, To ) + AIGroup:HandleEvent( EVENTS.Takeoff, nil, self ) + +end + + + +--- @param #AI_A2G_BAI self +-- @param Wrapper.Group#GROUP DefenderGroup The GroupGroup 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 AI_A2G_BAI:onafterEngage( DefenderGroup, From, Event, To, AttackSetUnit ) + + self:F( { DefenderGroup, From, Event, To, AttackSetUnit} ) + + local DefenderGroupName = DefenderGroup:GetName() + + self.AttackSetUnit = AttackSetUnit or self.AttackSetUnit -- Core.Set#SET_UNIT + + local AttackCount = self.AttackSetUnit:Count() + + if AttackCount > 0 then + + if DefenderGroup:IsAlive() then + + -- Determine the distance to the target. + -- If it is less than 10km, then attack without a route. + -- Otherwise perform a route attack. + + local DefenderCoord = DefenderGroup:GetCoordinate() + local TargetCoord = self.AttackSetUnit:GetFirst():GetCoordinate() + + local TargetDistance = DefenderCoord:Get2DDistance( TargetCoord ) + + if TargetDistance >= 50000 then + + local EngageRoute = {} + + local ToTargetSpeed = math.random( self.EngageMinSpeed, self.EngageMaxSpeed ) + + --- Calculate the target route point. + + local FromWP = DefenderCoord:WaypointAir( + self.PatrolAltType, + POINT_VEC3.RoutePointType.TurningPoint, + POINT_VEC3.RoutePointAction.TurningPoint, + ToTargetSpeed, + true + ) + + EngageRoute[#EngageRoute+1] = FromWP + + local ToCoord = self.AttackSetUnit:GetFirst():GetCoordinate() + self:SetTargetDistance( ToCoord ) -- For RTB status check + + local FromEngageAngle = ToCoord:GetAngleDegrees( ToCoord:GetDirectionVec3( DefenderCoord ) ) + + --- Create a route point of type air. + local ToWP = ToCoord:Translate( 50000, FromEngageAngle ):WaypointAir( + self.PatrolAltType, + POINT_VEC3.RoutePointType.TurningPoint, + POINT_VEC3.RoutePointAction.TurningPoint, + ToTargetSpeed, + true + ) + + self:F( { Angle = FromEngageAngle, ToTargetSpeed = ToTargetSpeed } ) + self:F( { self.EngageMinSpeed, self.EngageMaxSpeed, ToTargetSpeed } ) + + EngageRoute[#EngageRoute+1] = ToWP + + local AttackTasks = {} + + for AttackUnitID, AttackUnit in pairs( self.AttackSetUnit:GetSet() ) do + if AttackUnit:IsAlive() and AttackUnit:IsGround() then + self:T( { "Engage Unit evaluation:", AttackUnit:GetName(), AttackUnit:IsAlive(), AttackUnit:IsGround() } ) + local HasRadar = AttackUnit:HasSEAD() + if HasRadar then + self:T( { "Eliminating Unit:", AttackUnit:GetName() } ) + AttackTasks[#AttackTasks+1] = DefenderGroup:TaskAttackUnit( AttackUnit ) + end + end + end + + if #AttackTasks == 0 then + self:E( DefenderGroupName .. ": No targets found -> Going RTB") + self:Return() + self:__RTB( 0.5 ) + else + DefenderGroup:OptionROEOpenFire() + DefenderGroup:OptionROTEvadeFire() + + AttackTasks[#AttackTasks+1] = DefenderGroup:TaskFunction( "AI_A2G_ENGAGE.EngageRoute", self ) + EngageRoute[#EngageRoute].task = DefenderGroup:TaskCombo( AttackTasks ) + end + + DefenderGroup:Route( EngageRoute, 0 ) + + else + local AttackTasks = {} + --local AttackUnit = self.AttackSetUnit:GetRandom() -- Wrapper.Unit#UNIT + for AttackUnitID, AttackUnit in pairs( self.AttackSetUnit:GetSet() ) do + if AttackUnit:IsAlive() and AttackUnit:IsGround() then + local HasRadar = AttackUnit:HasSEAD() + if HasRadar then + self:T( { "Eliminating Unit:", AttackUnit:GetName(), AttackUnit:IsAlive(), AttackUnit:IsGround() } ) + AttackTasks[#AttackTasks+1] = DefenderGroup:TaskAttackUnit( AttackUnit ) + end + end + end + AttackTasks[#AttackTasks+1] = DefenderGroup:TaskFunction( "AI_A2G_ENGAGE.EngageRoute", self ) + local DefenderTask = DefenderGroup:TaskCombo( AttackTasks ) + DefenderGroup:SetTask( DefenderTask, 0 ) + end + end + else + self:E( DefenderGroupName .. ": No targets found -> Going RTB") + self:Return() + self:__RTB( 0.5 ) + end +end diff --git a/Moose Development/Moose/AI/AI_A2G_CAS.lua b/Moose Development/Moose/AI/AI_A2G_CAS.lua new file mode 100644 index 000000000..85a1e1d8a --- /dev/null +++ b/Moose Development/Moose/AI/AI_A2G_CAS.lua @@ -0,0 +1,173 @@ +--- **AI** -- Models the process of air to ground engagement for airplanes and helicopters. +-- +-- This is a class used in the @{AI_A2G_Dispatcher}. +-- +-- === +-- +-- ### Author: **FlightControl** +-- +-- === +-- +-- @module AI.AI_A2G_CAS +-- @image AI_Air_To_Ground_Engage.JPG + + + +--- @type AI_A2G_CAS +-- @extends AI.AI_A2G_Engage#AI_A2G_Engage + + +--- Implements the core functions to intercept intruders. Use the Engage trigger to intercept intruders. +-- +-- === +-- +-- @field #AI_A2G_CAS +AI_A2G_CAS = { + ClassName = "AI_A2G_CAS", +} + + + +--- Creates a new AI_A2G_CAS object +-- @param #AI_A2G_CAS self +-- @param Wrapper.Group#GROUP AIGroup +-- @return #AI_A2G_CAS +function AI_A2G_CAS:New( AIGroup, EngageMinSpeed, EngageMaxSpeed ) + + -- Inherits from BASE + local self = BASE:Inherit( self, AI_A2G_ENGAGE:New( AIGroup, EngageMinSpeed, EngageMaxSpeed ) ) -- #AI_A2G_CAS + + return self +end + +--- onafter event handler for Start event. +-- @param #AI_A2G_CAS self +-- @param Wrapper.Group#GROUP AIGroup The AI group 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 AI_A2G_CAS:onafterStart( AIGroup, From, Event, To ) + + self:GetParent( self ).onafterStart( self, AIGroup, From, Event, To ) + AIGroup:HandleEvent( EVENTS.Takeoff, nil, self ) + +end + + + +--- @param #AI_A2G_CAS self +-- @param Wrapper.Group#GROUP DefenderGroup The GroupGroup 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 AI_A2G_CAS:onafterEngage( DefenderGroup, From, Event, To, AttackSetUnit ) + + self:F( { DefenderGroup, From, Event, To, AttackSetUnit} ) + + local DefenderGroupName = DefenderGroup:GetName() + + self.AttackSetUnit = AttackSetUnit or self.AttackSetUnit -- Core.Set#SET_UNIT + + local AttackCount = self.AttackSetUnit:Count() + + if AttackCount > 0 then + + if DefenderGroup:IsAlive() then + + -- Determine the distance to the target. + -- If it is less than 10km, then attack without a route. + -- Otherwise perform a route attack. + + local DefenderCoord = DefenderGroup:GetCoordinate() + local TargetCoord = self.AttackSetUnit:GetFirst():GetCoordinate() + + local TargetDistance = DefenderCoord:Get2DDistance( TargetCoord ) + + if TargetDistance >= 50000 then + + local EngageRoute = {} + + local ToTargetSpeed = math.random( self.EngageMinSpeed, self.EngageMaxSpeed ) + + --- Calculate the target route point. + + local FromWP = DefenderCoord:WaypointAir( + self.PatrolAltType, + POINT_VEC3.RoutePointType.TurningPoint, + POINT_VEC3.RoutePointAction.TurningPoint, + ToTargetSpeed, + true + ) + + EngageRoute[#EngageRoute+1] = FromWP + + local ToCoord = self.AttackSetUnit:GetFirst():GetCoordinate() + self:SetTargetDistance( ToCoord ) -- For RTB status check + + local FromEngageAngle = ToCoord:GetAngleDegrees( ToCoord:GetDirectionVec3( DefenderCoord ) ) + + --- Create a route point of type air. + local ToWP = ToCoord:Translate( 50000, FromEngageAngle ):WaypointAir( + self.PatrolAltType, + POINT_VEC3.RoutePointType.TurningPoint, + POINT_VEC3.RoutePointAction.TurningPoint, + ToTargetSpeed, + true + ) + + self:F( { Angle = FromEngageAngle, ToTargetSpeed = ToTargetSpeed } ) + self:F( { self.EngageMinSpeed, self.EngageMaxSpeed, ToTargetSpeed } ) + + EngageRoute[#EngageRoute+1] = ToWP + + local AttackTasks = {} + + for AttackUnitID, AttackUnit in pairs( self.AttackSetUnit:GetSet() ) do + if AttackUnit:IsAlive() and AttackUnit:IsGround() then + self:T( { "Engage Unit evaluation:", AttackUnit:GetName(), AttackUnit:IsAlive(), AttackUnit:IsGround() } ) + local HasRadar = AttackUnit:HasSEAD() + if HasRadar then + self:T( { "Eliminating Unit:", AttackUnit:GetName() } ) + AttackTasks[#AttackTasks+1] = DefenderGroup:TaskAttackUnit( AttackUnit ) + end + end + end + + if #AttackTasks == 0 then + self:E( DefenderGroupName .. ": No targets found -> Going RTB") + self:Return() + self:__RTB( 0.5 ) + else + DefenderGroup:OptionROEOpenFire() + DefenderGroup:OptionROTEvadeFire() + + AttackTasks[#AttackTasks+1] = DefenderGroup:TaskFunction( "AI_A2G_ENGAGE.EngageRoute", self ) + EngageRoute[#EngageRoute].task = DefenderGroup:TaskCombo( AttackTasks ) + end + + DefenderGroup:Route( EngageRoute, 0 ) + + else + local AttackTasks = {} + --local AttackUnit = self.AttackSetUnit:GetRandom() -- Wrapper.Unit#UNIT + for AttackUnitID, AttackUnit in pairs( self.AttackSetUnit:GetSet() ) do + if AttackUnit:IsAlive() and AttackUnit:IsGround() then + local HasRadar = AttackUnit:HasSEAD() + if HasRadar then + self:T( { "Eliminating Unit:", AttackUnit:GetName(), AttackUnit:IsAlive(), AttackUnit:IsGround() } ) + AttackTasks[#AttackTasks+1] = DefenderGroup:TaskAttackUnit( AttackUnit ) + end + end + end + AttackTasks[#AttackTasks+1] = DefenderGroup:TaskFunction( "AI_A2G_ENGAGE.EngageRoute", self ) + local DefenderTask = DefenderGroup:TaskCombo( AttackTasks ) + DefenderGroup:SetTask( DefenderTask, 0 ) + end + end + else + self:E( DefenderGroupName .. ": No targets found -> Going RTB") + self:Return() + self:__RTB( 0.5 ) + end +end + diff --git a/Moose Development/Moose/AI/AI_A2G_Dispatcher.lua b/Moose Development/Moose/AI/AI_A2G_Dispatcher.lua index fde91d028..76cf4be62 100644 --- a/Moose Development/Moose/AI/AI_A2G_Dispatcher.lua +++ b/Moose Development/Moose/AI/AI_A2G_Dispatcher.lua @@ -810,6 +810,7 @@ do -- AI_A2G_DISPATCHER if Squadron then self:F( { SquadronName = Squadron.Name } ) local LandingMethod = self:GetSquadronLanding( Squadron.Name ) + if LandingMethod == AI_A2G_DISPATCHER.Landing.AtRunway then local DefenderSize = Defender:GetSize() if DefenderSize == 1 then @@ -1395,6 +1396,8 @@ do -- AI_A2G_DISPATCHER local DefenderSquadron = self:GetSquadron( SquadronName ) DefenderSquadron.Uncontrolled = true + self:SetSquadronTakeoffFromParkingCold( SquadronName ) + self:SetSquadronLandingAtEngineShutdown( SquadronName ) for SpawnTemplate, DefenderSpawn in pairs( self.DefenderSpawns ) do DefenderSpawn:InitUnControlled() @@ -2856,13 +2859,16 @@ do -- AI_A2G_DISPATCHER if DefenderUnitIndex == 1 then DefenderPatrolTemplate = UTILS.DeepCopy( DefenderTemplate ) self.DefenderPatrolIndex = self.DefenderPatrolIndex + 1 - DefenderPatrolTemplate.name = SquadronName .. "#" .. self.DefenderPatrolIndex .. "#" .. GroupName + --DefenderPatrolTemplate.name = SquadronName .. "#" .. self.DefenderPatrolIndex .. "#" .. GroupName + DefenderPatrolTemplate.name = GroupName DefenderName = DefenderPatrolTemplate.name else -- Add the unit in the template to the DefenderPatrolTemplate. local DefenderUnitTemplate = DefenderTemplate.units[1] DefenderPatrolTemplate.units[DefenderUnitIndex] = DefenderUnitTemplate end + DefenderPatrolTemplate.units[DefenderUnitIndex].name = string.format( DefenderPatrolTemplate.name .. '-%02d', DefenderUnitIndex ) + DefenderPatrolTemplate.units[DefenderUnitIndex].unitId = nil DefenderUnitIndex = DefenderUnitIndex + 1 DefenderSquadron.Resources[TemplateID][GroupName] = nil if DefenderUnitIndex > DefenderGrouping then @@ -2880,8 +2886,8 @@ do -- AI_A2G_DISPATCHER DefenderPatrolTemplate.route.points[1].type = GROUPTEMPLATE.Takeoff[Takeoff][1] -- type DefenderPatrolTemplate.route.points[1].action = GROUPTEMPLATE.Takeoff[Takeoff][2] -- action local Defender = _DATABASE:Spawn( DefenderPatrolTemplate ) - self:AddDefenderToSquadron( DefenderSquadron, Defender, DefenderGrouping ) + Defender:Activate() return Defender, DefenderGrouping end else @@ -2993,6 +2999,8 @@ do -- AI_A2G_DISPATCHER self:F( { From, Event, To, AttackerDetection.Index, DefendersEngaged = DefendersEngaged, DefendersMissing = DefendersMissing, DefenderFriendlies = DefenderFriendlies } ) + AttackerDetection.Type = DefenseTaskType -- This is set to report the task type in the status panel. + local AttackerSet = AttackerDetection.Set local AttackerUnit = AttackerSet:GetFirst() @@ -3103,7 +3111,9 @@ do -- AI_A2G_DISPATCHER DefenderCount = DefenderCount - DefenderGrouping / DefenderOverhead - local Fsm = AI_A2G_ENGAGE:New( DefenderGroup, Defense.EngageMinSpeed, Defense.EngageMaxSpeed ) + local AI_A2G_ENGAGE = { SEAD = AI_A2G_SEAD, BAI = AI_A2G_BAI, CAS = AI_A2G_CAS } + + local Fsm = AI_A2G_ENGAGE[DefenseTaskType]:New( DefenderGroup, Defense.EngageMinSpeed, Defense.EngageMaxSpeed ) -- AI.AI_A2G_ENGAGE Fsm:SetDispatcher( self ) Fsm:SetHomeAirbase( DefenderSquadron.Airbase ) Fsm:SetFuelThreshold( DefenderSquadron.FuelThreshold or self.DefenderDefault.FuelThreshold, 60 ) @@ -3121,6 +3131,8 @@ do -- AI_A2G_DISPATCHER local Squadron = Dispatcher:GetSquadronFromDefender( Defender ) local DefenderTarget = Dispatcher:GetDefenderTaskTarget( Defender ) + self:F( { DefenderTarget = DefenderTarget } ) + if DefenderTarget then Fsm:__Engage( 2, DefenderTarget.Set ) -- Engage on the TargetSetUnit end @@ -3141,10 +3153,10 @@ do -- AI_A2G_DISPATCHER local Dispatcher = Fsm:GetDispatcher() -- #AI_A2G_DISPATCHER local Squadron = Dispatcher:GetSquadronFromDefender( Defender ) - if Defender:IsAboveRunway() then - Dispatcher:RemoveDefenderFromSquadron( Squadron, Defender ) - Defender:Destroy() - end + --if Defender:IsAboveRunway() then + --Dispatcher:RemoveDefenderFromSquadron( Squadron, Defender ) + --Defender:Destroy() + --end end --- @param #AI_A2G_DISPATCHER self @@ -3298,8 +3310,8 @@ do -- AI_A2G_DISPATCHER for DefenderGroup, DefenderTask in pairs( self:GetDefenderTasks() ) do local DefenderGroup = DefenderGroup -- Wrapper.Group#GROUP + local DefenderTaskFsm = self:GetDefenderTaskFsm( DefenderGroup ) if not DefenderGroup:IsAlive() then - local DefenderTaskFsm = self:GetDefenderTaskFsm( DefenderGroup ) self:F( { Defender = DefenderGroup:GetName(), DefenderState = DefenderTaskFsm:GetState() } ) if not DefenderTaskFsm:Is( "Started" ) then self:ClearDefenderTask( DefenderGroup ) @@ -3312,10 +3324,10 @@ do -- AI_A2G_DISPATCHER self:ClearDefenderTaskTarget( DefenderGroup ) else if DefenderTask.Target.Set then - local AttackerCount = DefenderTask.Target.Set:Count() - if AttackerCount == 0 then + local TargetCount = DefenderTask.Target.Set:Count() + if TargetCount == 0 then self:F( { "All Targets destroyed in Target, removing:", DefenderTask.Target.Index } ) - self:ClearDefenderTaskTarget( DefenderGroup ) + self:ClearDefenderTask( DefenderGroup ) end end end @@ -3410,7 +3422,7 @@ do -- AI_A2G_DISPATCHER if self.TacticalDisplay then -- Show tactical situation - Report:Add( string.format( "\n - Target %s ( %s ): ( #%d ) %s" , DetectedItem.ItemID, DetectedItem.Index, DetectedItem.Set:Count(), DetectedItem.Set:GetObjectNames() ) ) + Report:Add( string.format( "\n - %s %s ( %s ): ( #%d ) %s" , DetectedItem.Type or " --- ", DetectedItem.ItemID, DetectedItem.Index, DetectedItem.Set:Count(), DetectedItem.Set:GetObjectNames() ) ) for Defender, DefenderTask in pairs( self:GetDefenderTasks() ) do local Defender = Defender -- Wrapper.Group#GROUP if DefenderTask.Target and DefenderTask.Target.Index == DetectedItem.Index then diff --git a/Moose Development/Moose/AI/AI_A2G_Engage.lua b/Moose Development/Moose/AI/AI_A2G_Engage.lua index 2cc6845b1..a0513933f 100644 --- a/Moose Development/Moose/AI/AI_A2G_Engage.lua +++ b/Moose Development/Moose/AI/AI_A2G_Engage.lua @@ -14,7 +14,7 @@ --- @type AI_A2G_ENGAGE --- @extends AI.AI_A2A#AI_A2A +-- @extends AI.AI_A2G#AI_A2G --- Implements the core functions to intercept intruders. Use the Engage trigger to intercept intruders. @@ -266,7 +266,8 @@ end -- @param #string To The To State string. function AI_A2G_ENGAGE:onafterStart( AIGroup, From, Event, To ) - self:GetParent( self ).onafterStart( self, AIGroup, From, Event, To ) + self:GetParent( self, AI_A2G_ENGAGE ).onafterStart( self, AIGroup, From, Event, To ) + AIGroup:HandleEvent( EVENTS.Takeoff, nil, self ) end @@ -327,81 +328,14 @@ end --- @param #AI_A2G_ENGAGE self --- @param Wrapper.Group#GROUP AIGroup The GroupGroup managed by the FSM. +-- @param Wrapper.Group#GROUP DefenderGroup The GroupGroup 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 AI_A2G_ENGAGE:onafterEngage( AIGroup, From, Event, To, AttackSetUnit ) +function AI_A2G_ENGAGE:onafterEngage( DefenderGroup, From, Event, To, AttackSetUnit ) - self:F( { AIGroup, From, Event, To, AttackSetUnit} ) - - self.AttackSetUnit = AttackSetUnit or self.AttackSetUnit -- Core.Set#SET_UNIT + self:F( { DefenderGroup, From, Event, To, AttackSetUnit} ) - local FirstAttackUnit = self.AttackSetUnit:GetFirst() - - if FirstAttackUnit and FirstAttackUnit:IsAlive() then - - if AIGroup:IsAlive() then - - local EngageRoute = {} - - local CurrentCoord = AIGroup:GetCoordinate() - - --- Calculate the target route point. - - local CurrentCoord = AIGroup:GetCoordinate() - - local ToTargetCoord = self.AttackSetUnit:GetFirst():GetCoordinate() - self:SetTargetDistance( ToTargetCoord ) -- For RTB status check - - local ToTargetSpeed = math.random( self.EngageMinSpeed, self.EngageMaxSpeed ) - local ToEngageAngle = CurrentCoord:GetAngleDegrees( CurrentCoord:GetDirectionVec3( ToTargetCoord ) ) - - --- Create a route point of type air. - local ToPatrolRoutePoint = CurrentCoord:Translate( 15000, ToEngageAngle ):WaypointAir( - self.PatrolAltType, - POINT_VEC3.RoutePointType.TurningPoint, - POINT_VEC3.RoutePointAction.TurningPoint, - ToTargetSpeed, - true - ) - - self:F( { Angle = ToEngageAngle, ToTargetSpeed = ToTargetSpeed } ) - self:F( { self.EngageMinSpeed, self.EngageMaxSpeed, ToTargetSpeed } ) - - EngageRoute[#EngageRoute+1] = ToPatrolRoutePoint - EngageRoute[#EngageRoute+1] = ToPatrolRoutePoint - - local AttackTasks = {} - - for AttackUnitID, AttackUnit in pairs( self.AttackSetUnit:GetSet() ) do - local AttackUnit = AttackUnit -- Wrapper.Unit#UNIT - if AttackUnit:IsAlive() and AttackUnit:IsGround() then - self:T( { "Eliminating Unit:", AttackUnit:GetName(), AttackUnit:IsAlive(), AttackUnit:IsGround() } ) - AttackTasks[#AttackTasks+1] = AIGroup:TaskAttackUnit( AttackUnit ) - end - end - - if #AttackTasks == 0 then - self:E("No targets found -> Going RTB") - self:Return() - self:__RTB( 0.5 ) - else - AIGroup:OptionROEOpenFire() - AIGroup:OptionROTEvadeFire() - - AttackTasks[#AttackTasks+1] = AIGroup:TaskFunction( "AI_A2G_ENGAGE.EngageRoute", self ) - EngageRoute[#EngageRoute].task = AIGroup:TaskCombo( AttackTasks ) - end - - AIGroup:Route( EngageRoute, 0.5 ) - - end - else - self:E("No targets found -> Going RTB") - self:Return() - self:__RTB( 0.5 ) - end end --- @param #AI_A2G_ENGAGE self diff --git a/Moose Development/Moose/AI/AI_A2G_Patrol.lua b/Moose Development/Moose/AI/AI_A2G_Patrol.lua index bf4a97dba..9a667b5cc 100644 --- a/Moose Development/Moose/AI/AI_A2G_Patrol.lua +++ b/Moose Development/Moose/AI/AI_A2G_Patrol.lua @@ -112,7 +112,7 @@ AI_A2G_PATROL = { function AI_A2G_PATROL:New( AIPatrol, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, EngageMinSpeed, EngageMaxSpeed, PatrolAltType ) -- Inherits from BASE - local self = BASE:Inherit( self, AI_A2A_PATROL:New( AIPatrol, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType ) ) -- #AI_A2G_PATROL + local self = BASE:Inherit( self, AI_A2G:New( AIPatrol ) ) -- #AI_A2G_PATROL self.Accomplished = false self.Engaging = false @@ -290,7 +290,6 @@ end -- @param #string To The To State string. function AI_A2G_PATROL:onafterStart( AIPatrol, From, Event, To ) - self:GetParent( self ).onafterStart( self, AIPatrol, From, Event, To ) AIPatrol:HandleEvent( EVENTS.Takeoff, nil, self ) end diff --git a/Moose Development/Moose/AI/AI_A2G_SEAD.lua b/Moose Development/Moose/AI/AI_A2G_SEAD.lua new file mode 100644 index 000000000..c0db300d4 --- /dev/null +++ b/Moose Development/Moose/AI/AI_A2G_SEAD.lua @@ -0,0 +1,218 @@ +--- **AI** -- Models the process of air to ground SEAD engagement for airplanes and helicopters. +-- +-- This is a class used in the @{AI_A2G_Dispatcher}. +-- +-- === +-- +-- ### Author: **FlightControl** +-- +-- === +-- +-- @module AI.AI_A2G_SEAD +-- @image AI_Air_To_Ground_Engage.JPG + + + +--- @type AI_A2G_SEAD +-- @extends AI.AI_A2G_Engage#AI_A2G_Engage + + +--- Implements the core functions to SEAD intruders. Use the Engage trigger to intercept intruders. +-- +-- ![Process](..\Presentations\AI_GCI\Dia3.JPG) +-- +-- The AI_A2G_SEAD is assigned a @{Wrapper.Group} and this must be done before the AI_A2G_SEAD process can be started using the **Start** event. +-- +-- ![Process](..\Presentations\AI_GCI\Dia4.JPG) +-- +-- The AI will fly towards the random 3D point within the patrol zone, using a random speed within the given altitude and speed limits. +-- Upon arrival at the 3D point, a new random 3D point will be selected within the patrol zone using the given limits. +-- +-- ![Process](..\Presentations\AI_GCI\Dia5.JPG) +-- +-- This cycle will continue. +-- +-- ![Process](..\Presentations\AI_GCI\Dia6.JPG) +-- +-- During the patrol, the AI will detect enemy targets, which are reported through the **Detected** event. +-- +-- ![Process](..\Presentations\AI_GCI\Dia9.JPG) +-- +-- When enemies are detected, the AI will automatically engage the enemy. +-- +-- ![Process](..\Presentations\AI_GCI\Dia10.JPG) +-- +-- Until a fuel or damage treshold has been reached by the AI, or when the AI is commanded to RTB. +-- When the fuel treshold has been reached, the airplane will fly towards the nearest friendly airbase and will land. +-- +-- ![Process](..\Presentations\AI_GCI\Dia13.JPG) +-- +-- ## 1. AI_A2G_SEAD constructor +-- +-- * @{#AI_A2G_SEAD.New}(): Creates a new AI_A2G_SEAD object. +-- +-- ## 3. Set the Range of Engagement +-- +-- ![Range](..\Presentations\AI_GCI\Dia11.JPG) +-- +-- An optional range can be set in meters, +-- that will define when the AI will engage with the detected airborne enemy targets. +-- The range can be beyond or smaller than the range of the Patrol Zone. +-- The range is applied at the position of the AI. +-- Use the method @{AI.AI_GCI#AI_A2G_SEAD.SetEngageRange}() to define that range. +-- +-- ## 4. Set the Zone of Engagement +-- +-- ![Zone](..\Presentations\AI_GCI\Dia12.JPG) +-- +-- An optional @{Zone} can be set, +-- that will define when the AI will engage with the detected airborne enemy targets. +-- Use the method @{AI.AI_Cap#AI_A2G_SEAD.SetEngageZone}() to define that Zone. +-- +-- === +-- +-- @field #AI_A2G_SEAD +AI_A2G_SEAD = { + ClassName = "AI_A2G_SEAD", +} + + + +--- Creates a new AI_A2G_SEAD object +-- @param #AI_A2G_SEAD self +-- @param Wrapper.Group#GROUP AIGroup +-- @return #AI_A2G_SEAD +function AI_A2G_SEAD:New( AIGroup, EngageMinSpeed, EngageMaxSpeed ) + + -- Inherits from BASE + local self = BASE:Inherit( self, AI_A2G_ENGAGE:New( AIGroup, EngageMinSpeed, EngageMaxSpeed ) ) -- #AI_A2G_SEAD + + return self +end + + + +--- @param #AI_A2G_SEAD self +-- @param Wrapper.Group#GROUP DefenderGroup The GroupGroup 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 AI_A2G_SEAD:onafterEngage( DefenderGroup, From, Event, To, AttackSetUnit ) + + self:F( { DefenderGroup, From, Event, To, AttackSetUnit} ) + + local DefenderGroupName = DefenderGroup:GetName() + + self.AttackSetUnit = AttackSetUnit or self.AttackSetUnit -- Core.Set#SET_UNIT + + local AttackCount = self.AttackSetUnit:Count() + + if AttackCount > 0 then + + if DefenderGroup:IsAlive() then + + -- Determine the distance to the target. + -- If it is less than 50km, then attack without a route. + -- Otherwise perform a route attack. + + local DefenderCoord = DefenderGroup:GetCoordinate() + local TargetCoord = self.AttackSetUnit:GetFirst():GetCoordinate() + + local TargetDistance = DefenderCoord:Get2DDistance( TargetCoord ) + +-- if TargetDistance >= 50000 then + + local EngageRoute = {} + + local ToTargetSpeed = math.random( self.EngageMinSpeed, self.EngageMaxSpeed ) + + --- Calculate the target route point. + + local FromWP = DefenderCoord:WaypointAir( + self.PatrolAltType, + POINT_VEC3.RoutePointType.TurningPoint, + POINT_VEC3.RoutePointAction.TurningPoint, + ToTargetSpeed, + true + ) + + EngageRoute[#EngageRoute+1] = FromWP + + local ToCoord = self.AttackSetUnit:GetFirst():GetCoordinate() + self:SetTargetDistance( ToCoord ) -- For RTB status check + + local FromEngageAngle = ToCoord:GetAngleDegrees( ToCoord:GetDirectionVec3( DefenderCoord ) ) + + --- Create a route point of type air, 50km from the center of the attack point. + local ToWP = ToCoord:Translate( 50000, FromEngageAngle ):WaypointAir( + self.PatrolAltType, + POINT_VEC3.RoutePointType.TurningPoint, + POINT_VEC3.RoutePointAction.TurningPoint, + ToTargetSpeed, + true + ) + + self:F( { Angle = FromEngageAngle, ToTargetSpeed = ToTargetSpeed } ) + self:F( { self.EngageMinSpeed, self.EngageMaxSpeed, ToTargetSpeed } ) + + EngageRoute[#EngageRoute+1] = ToWP + + local AttackTasks = {} + + for AttackUnitID, AttackUnit in pairs( self.AttackSetUnit:GetSet() ) do + if AttackUnit:IsAlive() and AttackUnit:IsGround() then + self:T( { "Engage Unit evaluation:", AttackUnit:GetName(), AttackUnit:IsAlive(), AttackUnit:IsGround() } ) + local HasRadar = AttackUnit:HasSEAD() + if HasRadar then + self:T( { "Eliminating Unit:", AttackUnit:GetName() } ) + AttackTasks[#AttackTasks+1] = DefenderGroup:TaskAttackUnit( AttackUnit ) + end + end + end + + if #AttackTasks == 0 then + self:E( DefenderGroupName .. ": No targets found -> Going RTB") + self:Return() + self:__RTB( 0.5 ) + else + DefenderGroup:OptionROEOpenFire() + DefenderGroup:OptionROTVertical() + DefenderGroup:OptionKeepWeaponsOnThreat() + --DefenderGroup:OptionRTBAmmo( Weapon.flag.AnyASM ) + + AttackTasks[#AttackTasks+1] = DefenderGroup:TaskFunction( "AI_A2G_ENGAGE.EngageRoute", self ) + EngageRoute[#EngageRoute].task = DefenderGroup:TaskCombo( AttackTasks ) + end + + DefenderGroup:Route( EngageRoute, 2 ) + +-- else +-- local AttackTasks = {} +-- --local AttackUnit = self.AttackSetUnit:GetRandom() -- Wrapper.Unit#UNIT +-- for AttackUnitID, AttackUnit in pairs( self.AttackSetUnit:GetSet() ) do +-- if AttackUnit:IsAlive() and AttackUnit:IsGround() then +-- local HasRadar = AttackUnit:HasSEAD() +-- if HasRadar then +-- self:T( { "Eliminating Unit:", AttackUnit:GetName(), AttackUnit:IsAlive(), AttackUnit:IsGround() } ) +-- AttackTasks[#AttackTasks+1] = DefenderGroup:TaskAttackUnit( AttackUnit ) +-- AttackTasks[#AttackTasks+1] = DefenderGroup:TaskFunction( "AI_A2G_ENGAGE.EngageRoute", self ) +-- end +-- end +-- end +-- local DefenderTask = DefenderGroup:TaskCombo( AttackTasks ) +-- +-- DefenderGroup:OptionROEOpenFire() +-- DefenderGroup:OptionROTVertical() +-- DefenderGroup:OptionKeepWeaponsOnThreat() +-- DefenderGroup:OptionRTBAmmo( Weapon.flag.AnyASM ) +-- +-- DefenderGroup:SetTask( DefenderTask, 0 ) +-- end + end + else + self:E( DefenderGroupName .. ": No targets found -> Going RTB") + self:Return() + self:__RTB( 0.5 ) + end +end + diff --git a/Moose Development/Moose/AI/AI_Air.lua b/Moose Development/Moose/AI/AI_Air.lua index 80a58bf7f..8425159cf 100644 --- a/Moose Development/Moose/AI/AI_Air.lua +++ b/Moose Development/Moose/AI/AI_Air.lua @@ -475,7 +475,7 @@ function AI_AIR:onafterStatus() RTB = true self:SetStatusOff() end - + -- Check if planes went RTB and are out of control. -- We only check if planes are out of control, when they are in duty. if self.Controllable:HasTask() == false then @@ -484,7 +484,7 @@ function AI_AIR:onafterStatus() not self:Is( "Fuel" ) and not self:Is( "Damaged" ) and not self:Is( "Home" ) then - if self.IdleCount >= 2 then + if self.IdleCount >= 10 then if Damage ~= InitialLife then self:Damaged() else @@ -547,7 +547,7 @@ function AI_AIR:onafterRTB( AIGroup, From, Event, To ) self:E( "Group " .. AIGroup:GetName() .. " ... RTB! ( " .. self:GetState() .. " )" ) self:ClearTargetDistance() - AIGroup:ClearTasks() + --AIGroup:ClearTasks() local EngageRoute = {} diff --git a/Moose Development/Moose/DCS.lua b/Moose Development/Moose/DCS.lua index d4af6e979..002ea566d 100644 --- a/Moose Development/Moose/DCS.lua +++ b/Moose Development/Moose/DCS.lua @@ -430,6 +430,8 @@ do -- Types end -- + + do -- Object --- [DCS Class Object](https://wiki.hoggitworld.com/view/DCS_Class_Object) @@ -527,6 +529,126 @@ do -- CoalitionObject end -- CoalitionObject +do -- Weapon + + --- [DCS Class Weapon](https://wiki.hoggitworld.com/view/DCS_Class_Weapon) + -- @type Weapon + -- @extends #CoalitionObject + -- @field #Weapon.flag flag enum stores weapon flags. Some of them are combination of another flags. + -- @field #Weapon.Category Category enum that stores weapon categories. + -- @field #Weapon.GuidanceType GuidanceType enum that stores guidance methods. Available only for guided weapon (Weapon.Category.MISSILE and some Weapon.Category.BOMB). + -- @field #Weapon.MissileCategory MissileCategory enum that stores missile category. Available only for missiles (Weapon.Category.MISSILE). + -- @field #Weapon.WarheadType WarheadType enum that stores warhead types. + -- @field #Weapon.Desc Desc The descriptor of a weapon. + + --- enum stores weapon flags. Some of them are combination of another flags. + -- @type Weapon.flag + -- @field LGB + -- @field TvGB + -- @field SNSGB + -- @field HEBomb + -- @field Penetrator + -- @field NapalmBomb + -- @field FAEBomb + -- @field ClusterBomb + -- @field Dispencer + -- @field CandleBomb + -- @field ParachuteBomb + -- @field GuidedBomb = LGB + TvGB + SNSGB + -- @field AnyUnguidedBomb = HEBomb + Penetrator + NapalmBomb + FAEBomb + ClusterBomb + Dispencer + CandleBomb + ParachuteBomb + -- @field AnyBomb = GuidedBomb + AnyUnguidedBomb + -- @field LightRocket + -- @field MarkerRocket + -- @field CandleRocket + -- @field HeavyRocket + -- @field AnyRocket = LightRocket + HeavyRocket + MarkerRocket + CandleRocket + -- @field AntiRadarMissile + -- @field AntiShipMissile + -- @field AntiTankMissile + -- @field FireAndForgetASM + -- @field LaserASM + -- @field TeleASM + -- @field CruiseMissile + -- @field GuidedASM = LaserASM + TeleASM + -- @field TacticASM = GuidedASM + FireAndForgetASM + -- @field AnyASM = AntiRadarMissile + AntiShipMissile + AntiTankMissile + FireAndForgetASM + GuidedASM + CruiseMissile + -- @field SRAAM + -- @field MRAAM + -- @field LRAAM + -- @field IR_AAM + -- @field SAR_AAM + -- @field AR_AAM + -- @field AnyAAM = IR_AAM + SAR_AAM + AR_AAM + SRAAM + MRAAM + LRAAM + -- @field AnyMissile = AnyASM + AnyAAM + -- @field AnyAutonomousMissile = IR_AAM + AntiRadarMissile + AntiShipMissile + FireAndForgetASM + CruiseMissile + -- @field GUN_POD + -- @field BuiltInCannon + -- @field Cannons = GUN_POD + BuiltInCannon + -- @field AnyAGWeapon = BuiltInCannon + GUN_POD + AnyBomb + AnyRocket + AnyASM + -- @field AnyAAWeapon = BuiltInCannon + GUN_POD + AnyAAM + -- @field UnguidedWeapon = Cannons + BuiltInCannon + GUN_POD + AnyUnguidedBomb + AnyRocket + -- @field GuidedWeapon = GuidedBomb + AnyASM + AnyAAM + -- @field AnyWeapon = AnyBomb + AnyRocket + AnyMissile + Cannons + -- @field MarkerWeapon = MarkerRocket + CandleRocket + CandleBomb + -- @field ArmWeapon = AnyWeapon - MarkerWeapon + + --- Weapon.Category enum that stores weapon categories. + -- @type Weapon.Category + -- @field SHELL + -- @field MISSILE + -- @field ROCKET + -- @field BOMB + + + --- Weapon.GuidanceType enum that stores guidance methods. Available only for guided weapon (Weapon.Category.MISSILE and some Weapon.Category.BOMB). + -- @type Weapon.GuidanceType + -- @field INS + -- @field IR + -- @field RADAR_ACTIVE + -- @field RADAR_SEMI_ACTIVE + -- @field RADAR_PASSIVE + -- @field TV + -- @field LASER + -- @field TELE + + + --- Weapon.MissileCategory enum that stores missile category. Available only for missiles (Weapon.Category.MISSILE). + -- @type Weapon.MissileCategory + -- @field AAM + -- @field SAM + -- @field BM + -- @field ANTI_SHIP + -- @field CRUISE + -- @field OTHER + + --- Weapon.WarheadType enum that stores warhead types. + -- @type Weapon.WarheadType + -- @field AP + -- @field HE + -- @field SHAPED_EXPLOSIVE + + --- Returns the unit that launched the weapon. + -- @function [parent=#Weapon] getLauncher + -- @param #Weapon self + -- @return #Unit + + --- returns target of the guided weapon. Unguided weapons and guided weapon that is targeted at the point on the ground will return nil. + -- @function [parent=#Weapon] getTarget + -- @param #Weapon self + -- @return #Object + + --- returns weapon descriptor. Descriptor type depends on weapon category. + -- @function [parent=#Weapon] getDesc + -- @param #Weapon self + -- @return #Weapon.Desc + + + + Weapon = {} --#Weapon + +end -- Weapon + + do -- Airbase --- [DCS Class Airbase](https://wiki.hoggitworld.com/view/DCS_Class_Airbase) diff --git a/Moose Development/Moose/Wrapper/Controllable.lua b/Moose Development/Moose/Wrapper/Controllable.lua index 1fb50baa5..f917d2535 100644 --- a/Moose Development/Moose/Wrapper/Controllable.lua +++ b/Moose Development/Moose/Wrapper/Controllable.lua @@ -168,6 +168,11 @@ -- * @{#CONTROLLABLE.OptionAlarmStateGreen} -- * @{#CONTROLLABLE.OptionAlarmStateRed} -- +-- ## 5.4) Jettison weapons: +-- +-- * @{#CONTROLLABLE.OptionAllowJettisonWeaponsOnThreat} +-- * @{#CONTROLLABLE.OptionKeepWeaponsOnThreat} +-- -- @field #CONTROLLABLE CONTROLLABLE = { ClassName = "CONTROLLABLE", @@ -302,7 +307,7 @@ end -- @param #CONTROLLABLE self -- @return #CONTROLLABLE function CONTROLLABLE:ClearTasks() - self:F2() + self:E( "ClearTasks" ) local DCSControllable = self:GetDCSObject() @@ -366,13 +371,15 @@ end -- @param #number WaitTime Time in seconds, before the task is set. -- @return Wrapper.Controllable#CONTROLLABLE self function CONTROLLABLE:SetTask( DCSTask, WaitTime ) - self:F2( { DCSTask = DCSTask } ) + self:E( { "SetTask", WaitTime, DCSTask = DCSTask } ) local DCSControllable = self:GetDCSObject() if DCSControllable then local DCSControllableName = self:GetName() + + self:E( "Controllable Name = " .. DCSControllableName ) -- When a controllable SPAWNs, it takes about a second to get the controllable in the simulator. Setting tasks to unspawned controllables provides unexpected results. -- Therefore we schedule the functions to set the mission and options for the Controllable. @@ -1659,6 +1666,7 @@ function CONTROLLABLE:TaskFunction( FunctionString, ... ) local DCSScript = {} DCSScript[#DCSScript+1] = "local MissionControllable = GROUP:Find( ... ) " + DCSScript[#DCSScript+1] = "env.info( 'TaskFunction: ' .. ( MissionControllable and MissionControllable:GetName() ) or 'No Group' )" if arg and arg.n > 0 then local ArgumentKey = '_' .. tostring( arg ):match("table: (.*)") @@ -2922,7 +2930,7 @@ function CONTROLLABLE:OptionRTBAmmo( WeaponsFlag ) local Controller = self:_GetController() if self:IsAir() then - Controller:setOption( AI.Option.GROUND.id.RTB_ON_OUT_OF_AMMO, WeaponsFlag ) + Controller:setOption( AI.Option.Air.id.RTB_ON_OUT_OF_AMMO, WeaponsFlag ) end return self @@ -2932,6 +2940,47 @@ function CONTROLLABLE:OptionRTBAmmo( WeaponsFlag ) end +--- Allow to Jettison of weapons upon threat. +-- @param #CONTROLLABLE self +-- @return #CONTROLLABLE self +function CONTROLLABLE:OptionAllowJettisonWeaponsOnThreat() + self:F2( { self.ControllableName } ) + + local DCSControllable = self:GetDCSObject() + if DCSControllable then + local Controller = self:_GetController() + + if self:IsAir() then + Controller:setOption( AI.Option.Air.id.PROHIBIT_JETT, false ) + end + + return self + end + + return nil +end + + +--- Keep weapons upon threat. +-- @param #CONTROLLABLE self +-- @return #CONTROLLABLE self +function CONTROLLABLE:OptionKeepWeaponsOnThreat() + self:F2( { self.ControllableName } ) + + local DCSControllable = self:GetDCSObject() + if DCSControllable then + local Controller = self:_GetController() + + if self:IsAir() then + Controller:setOption( AI.Option.Air.id.PROHIBIT_JETT, true ) + end + + return self + end + + return nil +end + diff --git a/Moose Setup/Moose.files b/Moose Setup/Moose.files index 231861fe0..11d2da7db 100644 --- a/Moose Setup/Moose.files +++ b/Moose Setup/Moose.files @@ -68,6 +68,9 @@ AI/AI_A2A_Gci.lua AI/AI_A2A_Dispatcher.lua AI/AI_A2G.lua AI/AI_A2G_Engage.lua +AI/AI_A2G_BAI.lua +AI/AI_A2G_CAS.lua +AI/AI_A2G_SEAD.lua AI/AI_A2G_Patrol.lua AI/AI_A2G_Dispatcher.lua AI/AI_Patrol.lua From 810cebfe0a1b204268dadbd2d6ba18a57d9977c0 Mon Sep 17 00:00:00 2001 From: FlightControl Date: Wed, 12 Dec 2018 07:31:08 +0100 Subject: [PATCH 05/14] Optimizations --- Moose Development/Moose/AI/AI_A2G_BAI.lua | 146 +++++++----------- Moose Development/Moose/AI/AI_A2G_CAS.lua | 145 +++++++---------- .../Moose/AI/AI_A2G_Dispatcher.lua | 5 +- Moose Development/Moose/AI/AI_Air.lua | 13 +- Moose Development/Moose/Wrapper/Group.lua | 2 +- Moose Development/Moose/Wrapper/Unit.lua | 4 +- 6 files changed, 126 insertions(+), 189 deletions(-) diff --git a/Moose Development/Moose/AI/AI_A2G_BAI.lua b/Moose Development/Moose/AI/AI_A2G_BAI.lua index fb72297d9..5c91e4027 100644 --- a/Moose Development/Moose/AI/AI_A2G_BAI.lua +++ b/Moose Development/Moose/AI/AI_A2G_BAI.lua @@ -40,20 +40,6 @@ function AI_A2G_BAI:New( AIGroup, EngageMinSpeed, EngageMaxSpeed ) return self end ---- onafter event handler for Start event. --- @param #AI_A2G_BAI self --- @param Wrapper.Group#GROUP AIGroup The AI group 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 AI_A2G_BAI:onafterStart( AIGroup, From, Event, To ) - - self:GetParent( self ).onafterStart( self, AIGroup, From, Event, To ) - AIGroup:HandleEvent( EVENTS.Takeoff, nil, self ) - -end - - --- @param #AI_A2G_BAI self -- @param Wrapper.Group#GROUP DefenderGroup The GroupGroup managed by the FSM. @@ -83,86 +69,64 @@ function AI_A2G_BAI:onafterEngage( DefenderGroup, From, Event, To, AttackSetUnit local TargetDistance = DefenderCoord:Get2DDistance( TargetCoord ) - if TargetDistance >= 50000 then - - local EngageRoute = {} - - local ToTargetSpeed = math.random( self.EngageMinSpeed, self.EngageMaxSpeed ) - - --- Calculate the target route point. - - local FromWP = DefenderCoord:WaypointAir( - self.PatrolAltType, - POINT_VEC3.RoutePointType.TurningPoint, - POINT_VEC3.RoutePointAction.TurningPoint, - ToTargetSpeed, - true - ) - - EngageRoute[#EngageRoute+1] = FromWP - - local ToCoord = self.AttackSetUnit:GetFirst():GetCoordinate() - self:SetTargetDistance( ToCoord ) -- For RTB status check - - local FromEngageAngle = ToCoord:GetAngleDegrees( ToCoord:GetDirectionVec3( DefenderCoord ) ) - - --- Create a route point of type air. - local ToWP = ToCoord:Translate( 50000, FromEngageAngle ):WaypointAir( - self.PatrolAltType, - POINT_VEC3.RoutePointType.TurningPoint, - POINT_VEC3.RoutePointAction.TurningPoint, - ToTargetSpeed, - true - ) - - self:F( { Angle = FromEngageAngle, ToTargetSpeed = ToTargetSpeed } ) - self:F( { self.EngageMinSpeed, self.EngageMaxSpeed, ToTargetSpeed } ) - - EngageRoute[#EngageRoute+1] = ToWP - - local AttackTasks = {} - - for AttackUnitID, AttackUnit in pairs( self.AttackSetUnit:GetSet() ) do - if AttackUnit:IsAlive() and AttackUnit:IsGround() then - self:T( { "Engage Unit evaluation:", AttackUnit:GetName(), AttackUnit:IsAlive(), AttackUnit:IsGround() } ) - local HasRadar = AttackUnit:HasSEAD() - if HasRadar then - self:T( { "Eliminating Unit:", AttackUnit:GetName() } ) - AttackTasks[#AttackTasks+1] = DefenderGroup:TaskAttackUnit( AttackUnit ) - end - end - end - - if #AttackTasks == 0 then - self:E( DefenderGroupName .. ": No targets found -> Going RTB") - self:Return() - self:__RTB( 0.5 ) - else - DefenderGroup:OptionROEOpenFire() - DefenderGroup:OptionROTEvadeFire() - - AttackTasks[#AttackTasks+1] = DefenderGroup:TaskFunction( "AI_A2G_ENGAGE.EngageRoute", self ) - EngageRoute[#EngageRoute].task = DefenderGroup:TaskCombo( AttackTasks ) - end - - DefenderGroup:Route( EngageRoute, 0 ) + local EngageRoute = {} + + local ToTargetSpeed = math.random( self.EngageMinSpeed, self.EngageMaxSpeed ) - else - local AttackTasks = {} - --local AttackUnit = self.AttackSetUnit:GetRandom() -- Wrapper.Unit#UNIT - for AttackUnitID, AttackUnit in pairs( self.AttackSetUnit:GetSet() ) do - if AttackUnit:IsAlive() and AttackUnit:IsGround() then - local HasRadar = AttackUnit:HasSEAD() - if HasRadar then - self:T( { "Eliminating Unit:", AttackUnit:GetName(), AttackUnit:IsAlive(), AttackUnit:IsGround() } ) - AttackTasks[#AttackTasks+1] = DefenderGroup:TaskAttackUnit( AttackUnit ) - end - end + --- Calculate the target route point. + + local FromWP = DefenderCoord:WaypointAir( + self.PatrolAltType, + POINT_VEC3.RoutePointType.TurningPoint, + POINT_VEC3.RoutePointAction.TurningPoint, + ToTargetSpeed, + true + ) + + EngageRoute[#EngageRoute+1] = FromWP + + local ToCoord = self.AttackSetUnit:GetFirst():GetCoordinate() + self:SetTargetDistance( ToCoord ) -- For RTB status check + + local FromEngageAngle = ToCoord:GetAngleDegrees( ToCoord:GetDirectionVec3( DefenderCoord ) ) + + --- Create a route point of type air. + local ToWP = ToCoord:Translate( 10000, FromEngageAngle ):WaypointAir( + self.PatrolAltType, + POINT_VEC3.RoutePointType.TurningPoint, + POINT_VEC3.RoutePointAction.TurningPoint, + ToTargetSpeed, + true + ) + + self:F( { Angle = FromEngageAngle, ToTargetSpeed = ToTargetSpeed } ) + self:F( { self.EngageMinSpeed, self.EngageMaxSpeed, ToTargetSpeed } ) + + EngageRoute[#EngageRoute+1] = ToWP + + local AttackTasks = {} + + for AttackUnitID, AttackUnit in pairs( self.AttackSetUnit:GetSet() ) do + if AttackUnit:IsAlive() and AttackUnit:IsGround() then + self:T( { "Engage Unit evaluation:", AttackUnit:GetName(), AttackUnit:IsAlive(), AttackUnit:IsGround() } ) + self:T( { "Eliminating Unit:", AttackUnit:GetName() } ) + AttackTasks[#AttackTasks+1] = DefenderGroup:TaskAttackUnit( AttackUnit ) end + end + + if #AttackTasks == 0 then + self:E( DefenderGroupName .. ": No targets found -> Going RTB") + self:Return() + self:__RTB( 0.5 ) + else + DefenderGroup:OptionROEOpenFire() + DefenderGroup:OptionROTEvadeFire() + AttackTasks[#AttackTasks+1] = DefenderGroup:TaskFunction( "AI_A2G_ENGAGE.EngageRoute", self ) - local DefenderTask = DefenderGroup:TaskCombo( AttackTasks ) - DefenderGroup:SetTask( DefenderTask, 0 ) - end + EngageRoute[#EngageRoute].task = DefenderGroup:TaskCombo( AttackTasks ) + end + + DefenderGroup:Route( EngageRoute, 0.5 ) end else self:E( DefenderGroupName .. ": No targets found -> Going RTB") diff --git a/Moose Development/Moose/AI/AI_A2G_CAS.lua b/Moose Development/Moose/AI/AI_A2G_CAS.lua index 85a1e1d8a..4177b38ed 100644 --- a/Moose Development/Moose/AI/AI_A2G_CAS.lua +++ b/Moose Development/Moose/AI/AI_A2G_CAS.lua @@ -40,20 +40,6 @@ function AI_A2G_CAS:New( AIGroup, EngageMinSpeed, EngageMaxSpeed ) return self end ---- onafter event handler for Start event. --- @param #AI_A2G_CAS self --- @param Wrapper.Group#GROUP AIGroup The AI group 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 AI_A2G_CAS:onafterStart( AIGroup, From, Event, To ) - - self:GetParent( self ).onafterStart( self, AIGroup, From, Event, To ) - AIGroup:HandleEvent( EVENTS.Takeoff, nil, self ) - -end - - --- @param #AI_A2G_CAS self -- @param Wrapper.Group#GROUP DefenderGroup The GroupGroup managed by the FSM. @@ -83,86 +69,63 @@ function AI_A2G_CAS:onafterEngage( DefenderGroup, From, Event, To, AttackSetUnit local TargetDistance = DefenderCoord:Get2DDistance( TargetCoord ) - if TargetDistance >= 50000 then - - local EngageRoute = {} - - local ToTargetSpeed = math.random( self.EngageMinSpeed, self.EngageMaxSpeed ) - - --- Calculate the target route point. - - local FromWP = DefenderCoord:WaypointAir( - self.PatrolAltType, - POINT_VEC3.RoutePointType.TurningPoint, - POINT_VEC3.RoutePointAction.TurningPoint, - ToTargetSpeed, - true - ) - - EngageRoute[#EngageRoute+1] = FromWP - - local ToCoord = self.AttackSetUnit:GetFirst():GetCoordinate() - self:SetTargetDistance( ToCoord ) -- For RTB status check - - local FromEngageAngle = ToCoord:GetAngleDegrees( ToCoord:GetDirectionVec3( DefenderCoord ) ) - - --- Create a route point of type air. - local ToWP = ToCoord:Translate( 50000, FromEngageAngle ):WaypointAir( - self.PatrolAltType, - POINT_VEC3.RoutePointType.TurningPoint, - POINT_VEC3.RoutePointAction.TurningPoint, - ToTargetSpeed, - true - ) - - self:F( { Angle = FromEngageAngle, ToTargetSpeed = ToTargetSpeed } ) - self:F( { self.EngageMinSpeed, self.EngageMaxSpeed, ToTargetSpeed } ) - - EngageRoute[#EngageRoute+1] = ToWP - - local AttackTasks = {} - - for AttackUnitID, AttackUnit in pairs( self.AttackSetUnit:GetSet() ) do - if AttackUnit:IsAlive() and AttackUnit:IsGround() then - self:T( { "Engage Unit evaluation:", AttackUnit:GetName(), AttackUnit:IsAlive(), AttackUnit:IsGround() } ) - local HasRadar = AttackUnit:HasSEAD() - if HasRadar then - self:T( { "Eliminating Unit:", AttackUnit:GetName() } ) - AttackTasks[#AttackTasks+1] = DefenderGroup:TaskAttackUnit( AttackUnit ) - end - end - end - - if #AttackTasks == 0 then - self:E( DefenderGroupName .. ": No targets found -> Going RTB") - self:Return() - self:__RTB( 0.5 ) - else - DefenderGroup:OptionROEOpenFire() - DefenderGroup:OptionROTEvadeFire() - - AttackTasks[#AttackTasks+1] = DefenderGroup:TaskFunction( "AI_A2G_ENGAGE.EngageRoute", self ) - EngageRoute[#EngageRoute].task = DefenderGroup:TaskCombo( AttackTasks ) - end - - DefenderGroup:Route( EngageRoute, 0 ) + local EngageRoute = {} + + local ToTargetSpeed = math.random( self.EngageMinSpeed, self.EngageMaxSpeed ) - else - local AttackTasks = {} - --local AttackUnit = self.AttackSetUnit:GetRandom() -- Wrapper.Unit#UNIT - for AttackUnitID, AttackUnit in pairs( self.AttackSetUnit:GetSet() ) do - if AttackUnit:IsAlive() and AttackUnit:IsGround() then - local HasRadar = AttackUnit:HasSEAD() - if HasRadar then - self:T( { "Eliminating Unit:", AttackUnit:GetName(), AttackUnit:IsAlive(), AttackUnit:IsGround() } ) - AttackTasks[#AttackTasks+1] = DefenderGroup:TaskAttackUnit( AttackUnit ) - end - end + --- Calculate the target route point. + + local FromWP = DefenderCoord:WaypointAir( + self.PatrolAltType, + POINT_VEC3.RoutePointType.TurningPoint, + POINT_VEC3.RoutePointAction.TurningPoint, + ToTargetSpeed, + true + ) + + EngageRoute[#EngageRoute+1] = FromWP + + local ToCoord = self.AttackSetUnit:GetFirst():GetCoordinate() + self:SetTargetDistance( ToCoord ) -- For RTB status check + + local FromEngageAngle = ToCoord:GetAngleDegrees( ToCoord:GetDirectionVec3( DefenderCoord ) ) + + --- Create a route point of type air. + local ToWP = ToCoord:Translate( 10000, FromEngageAngle ):WaypointAir( + self.PatrolAltType, + POINT_VEC3.RoutePointType.TurningPoint, + POINT_VEC3.RoutePointAction.TurningPoint, + ToTargetSpeed, + true + ) + + self:F( { Angle = FromEngageAngle, ToTargetSpeed = ToTargetSpeed } ) + self:F( { self.EngageMinSpeed, self.EngageMaxSpeed, ToTargetSpeed } ) + + EngageRoute[#EngageRoute+1] = ToWP + + local AttackTasks = {} + + for AttackUnitID, AttackUnit in pairs( self.AttackSetUnit:GetSet() ) do + if AttackUnit:IsAlive() and AttackUnit:IsGround() then + self:T( { "Eliminating Unit:", AttackUnit:GetName() } ) + AttackTasks[#AttackTasks+1] = DefenderGroup:TaskAttackUnit( AttackUnit ) end + end + + if #AttackTasks == 0 then + self:E( DefenderGroupName .. ": No targets found -> Going RTB") + self:Return() + self:__RTB( 0.5 ) + else + DefenderGroup:OptionROEOpenFire() + DefenderGroup:OptionROTEvadeFire() + AttackTasks[#AttackTasks+1] = DefenderGroup:TaskFunction( "AI_A2G_ENGAGE.EngageRoute", self ) - local DefenderTask = DefenderGroup:TaskCombo( AttackTasks ) - DefenderGroup:SetTask( DefenderTask, 0 ) - end + EngageRoute[#EngageRoute].task = DefenderGroup:TaskCombo( AttackTasks ) + end + + DefenderGroup:Route( EngageRoute, 0.5 ) end else self:E( DefenderGroupName .. ": No targets found -> Going RTB") diff --git a/Moose Development/Moose/AI/AI_A2G_Dispatcher.lua b/Moose Development/Moose/AI/AI_A2G_Dispatcher.lua index 76cf4be62..13c6767d5 100644 --- a/Moose Development/Moose/AI/AI_A2G_Dispatcher.lua +++ b/Moose Development/Moose/AI/AI_A2G_Dispatcher.lua @@ -3175,7 +3175,7 @@ do -- AI_A2G_DISPATCHER if Dispatcher:GetSquadronLanding( Squadron.Name ) == AI_A2G_DISPATCHER.Landing.NearAirbase then Dispatcher:RemoveDefenderFromSquadron( Squadron, Defender ) Defender:Destroy() - self:ParkDefender( Squadron, Defender ) + Dispatcher:ParkDefender( Squadron, Defender ) end end end -- if DefenderGCI then @@ -3311,6 +3311,9 @@ do -- AI_A2G_DISPATCHER for DefenderGroup, DefenderTask in pairs( self:GetDefenderTasks() ) do local DefenderGroup = DefenderGroup -- Wrapper.Group#GROUP local DefenderTaskFsm = self:GetDefenderTaskFsm( DefenderGroup ) + if DefenderTaskFsm:Is( "LostControl" ) then + self:ClearDefenderTask( DefenderGroup ) + end if not DefenderGroup:IsAlive() then self:F( { Defender = DefenderGroup:GetName(), DefenderState = DefenderTaskFsm:GetState() } ) if not DefenderTaskFsm:Is( "Started" ) then diff --git a/Moose Development/Moose/AI/AI_Air.lua b/Moose Development/Moose/AI/AI_Air.lua index 8425159cf..85d125384 100644 --- a/Moose Development/Moose/AI/AI_Air.lua +++ b/Moose Development/Moose/AI/AI_Air.lua @@ -425,7 +425,6 @@ function AI_AIR:onafterStatus() if not self:Is( "Holding" ) and not self:Is( "Returning" ) then local DistanceFromHomeBase = self.HomeAirbase:GetCoordinate():Get2DDistance( self.Controllable:GetCoordinate() ) - self:F({DistanceFromHomeBase=DistanceFromHomeBase}) if DistanceFromHomeBase > self.DisengageRadius then self:E( self.Controllable:GetName() .. " is too far from home base, RTB!" ) @@ -444,9 +443,13 @@ function AI_AIR:onafterStatus() if not self:Is( "Fuel" ) and not self:Is( "Home" ) then + local Fuel = self.Controllable:GetFuelMin() - self:F({Fuel=Fuel, FuelThresholdPercentage=self.FuelThresholdPercentage}) + + -- If the fuel in the controllable is below the treshold percentage, + -- then send for refuel in case of a tanker, otherwise RTB. if Fuel < self.FuelThresholdPercentage then + if self.TankerName then self:E( self.Controllable:GetName() .. " is out of fuel: " .. Fuel .. " ... Refuelling at Tanker!" ) self:Refuel() @@ -468,7 +471,10 @@ function AI_AIR:onafterStatus() -- TODO: Check GROUP damage function. local Damage = self.Controllable:GetLife() local InitialLife = self.Controllable:GetLife0() - self:F( { Damage = Damage, InitialLife = InitialLife, DamageThreshold = self.PatrolDamageThreshold } ) + + -- If the group is damaged, then RTB. + -- Note that a group can consist of more units, so if one unit is damaged of a group, the mission may continue. + -- The damaged unit will RTB due to DCS logic, and the others will continue to engage. if ( Damage / InitialLife ) < self.PatrolDamageThreshold then self:E( self.Controllable:GetName() .. " is damaged: " .. Damage .. " ... RTB!" ) self:Damaged() @@ -489,6 +495,7 @@ function AI_AIR:onafterStatus() self:Damaged() else self:E( self.Controllable:GetName() .. " control lost! " ) + self:LostControl() end else diff --git a/Moose Development/Moose/Wrapper/Group.lua b/Moose Development/Moose/Wrapper/Group.lua index e6c6648fd..e67d61605 100644 --- a/Moose Development/Moose/Wrapper/Group.lua +++ b/Moose Development/Moose/Wrapper/Group.lua @@ -934,7 +934,7 @@ end -- @return #number The fuel state of the unit with the least amount of fuel -- @return #Unit reference to #Unit object for further processing function GROUP:GetFuelMin() - self:F(self.ControllableName) + self:F3(self.ControllableName) if not self:GetDCSObject() then BASE:E( { "Cannot GetFuel", Group = self, Alive = self:IsAlive() } ) diff --git a/Moose Development/Moose/Wrapper/Unit.lua b/Moose Development/Moose/Wrapper/Unit.lua index d24a0b0b0..f1e5ee77c 100644 --- a/Moose Development/Moose/Wrapper/Unit.lua +++ b/Moose Development/Moose/Wrapper/Unit.lua @@ -555,7 +555,7 @@ end -- @return #number The relative amount of fuel (from 0.0 to 1.0). -- @return #nil The DCS Unit is not existing or alive. function UNIT:GetFuel() - self:F( self.UnitName ) + self:F3( self.UnitName ) local DCSUnit = self:GetDCSObject() @@ -571,7 +571,7 @@ end -- @param #UNIT self -- @return #list A list of one @{Wrapper.Unit}. function UNIT:GetUnits() - self:F2( { self.UnitName } ) + self:F3( { self.UnitName } ) local DCSUnit = self:GetDCSObject() local Units = {} From cfc9c655c5e105079c06bbf9f0d2ddee96fdcc92 Mon Sep 17 00:00:00 2001 From: FlightControl Date: Mon, 17 Dec 2018 19:39:23 +0100 Subject: [PATCH 06/14] Fixes for patrol. --- Moose Development/Moose/AI/AI_A2G_BAI.lua | 12 +- Moose Development/Moose/AI/AI_A2G_CAS.lua | 12 +- .../Moose/AI/AI_A2G_Dispatcher.lua | 14 +- Moose Development/Moose/AI/AI_A2G_Engage.lua | 2 +- Moose Development/Moose/AI/AI_A2G_Patrol.lua | 365 +++++------------- Moose Development/Moose/AI/AI_A2G_SEAD.lua | 12 +- Moose Development/Moose/AI/AI_Air.lua | 2 +- 7 files changed, 138 insertions(+), 281 deletions(-) diff --git a/Moose Development/Moose/AI/AI_A2G_BAI.lua b/Moose Development/Moose/AI/AI_A2G_BAI.lua index 5c91e4027..2806852a1 100644 --- a/Moose Development/Moose/AI/AI_A2G_BAI.lua +++ b/Moose Development/Moose/AI/AI_A2G_BAI.lua @@ -31,11 +31,19 @@ AI_A2G_BAI = { --- Creates a new AI_A2G_BAI object -- @param #AI_A2G_BAI self -- @param Wrapper.Group#GROUP AIGroup +-- @param DCS#Speed EngageMinSpeed The minimum speed of the @{Wrapper.Group} in km/h when engaging a target. +-- @param DCS#Speed EngageMaxSpeed The maximum speed of the @{Wrapper.Group} in km/h when engaging a target. +-- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed. +-- @param DCS#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol. +-- @param DCS#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol. +-- @param DCS#Speed PatrolMinSpeed The minimum speed of the @{Wrapper.Group} in km/h. +-- @param DCS#Speed PatrolMaxSpeed The maximum speed of the @{Wrapper.Group} in km/h. +-- @param DCS#AltitudeType PatrolAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to RADIO -- @return #AI_A2G_BAI -function AI_A2G_BAI:New( AIGroup, EngageMinSpeed, EngageMaxSpeed ) +function AI_A2G_BAI:New( AIGroup, EngageMinSpeed, EngageMaxSpeed, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType ) -- Inherits from BASE - local self = BASE:Inherit( self, AI_A2G_ENGAGE:New( AIGroup, EngageMinSpeed, EngageMaxSpeed ) ) -- #AI_A2G_BAI + local self = BASE:Inherit( self, AI_A2G_PATROL:New( AIGroup, EngageMinSpeed, EngageMaxSpeed, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType ) ) -- #AI_A2G_BAI return self end diff --git a/Moose Development/Moose/AI/AI_A2G_CAS.lua b/Moose Development/Moose/AI/AI_A2G_CAS.lua index 4177b38ed..e2465d572 100644 --- a/Moose Development/Moose/AI/AI_A2G_CAS.lua +++ b/Moose Development/Moose/AI/AI_A2G_CAS.lua @@ -31,11 +31,19 @@ AI_A2G_CAS = { --- Creates a new AI_A2G_CAS object -- @param #AI_A2G_CAS self -- @param Wrapper.Group#GROUP AIGroup +-- @param DCS#Speed EngageMinSpeed The minimum speed of the @{Wrapper.Group} in km/h when engaging a target. +-- @param DCS#Speed EngageMaxSpeed The maximum speed of the @{Wrapper.Group} in km/h when engaging a target. +-- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed. +-- @param DCS#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol. +-- @param DCS#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol. +-- @param DCS#Speed PatrolMinSpeed The minimum speed of the @{Wrapper.Group} in km/h. +-- @param DCS#Speed PatrolMaxSpeed The maximum speed of the @{Wrapper.Group} in km/h. +-- @param DCS#AltitudeType PatrolAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to RADIO -- @return #AI_A2G_CAS -function AI_A2G_CAS:New( AIGroup, EngageMinSpeed, EngageMaxSpeed ) +function AI_A2G_CAS:New( AIGroup, EngageMinSpeed, EngageMaxSpeed, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType ) -- Inherits from BASE - local self = BASE:Inherit( self, AI_A2G_ENGAGE:New( AIGroup, EngageMinSpeed, EngageMaxSpeed ) ) -- #AI_A2G_CAS + local self = BASE:Inherit( self, AI_A2G_PATROL:New( AIGroup, EngageMinSpeed, EngageMaxSpeed, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType ) ) -- #AI_A2G_CAS return self end diff --git a/Moose Development/Moose/AI/AI_A2G_Dispatcher.lua b/Moose Development/Moose/AI/AI_A2G_Dispatcher.lua index 13c6767d5..0070e3c6e 100644 --- a/Moose Development/Moose/AI/AI_A2G_Dispatcher.lua +++ b/Moose Development/Moose/AI/AI_A2G_Dispatcher.lua @@ -2761,7 +2761,7 @@ do -- AI_A2G_DISPATCHER -- Count the total of defenders on the battlefield. --local DefenderSize = Defender:GetInitialSize() if DefenderTask.Target then - --if DefenderTask.Fsm:Is( "Engaging" ) then + if DefenderTask.Fsm:Is( "Engaging" ) then self:F( "Defender Group Name: " .. Defender:GetName() .. ", Size: " .. DefenderSize ) DefendersTotal = DefendersTotal + DefenderSize if DefenderTaskTarget and DefenderTaskTarget.Index == AttackerDetection.Index then @@ -2775,7 +2775,7 @@ do -- AI_A2G_DISPATCHER DefendersEngaged = 0 end end - --end + end end @@ -2921,7 +2921,9 @@ do -- AI_A2G_DISPATCHER if DefenderPatrol then - local Fsm = AI_A2G_PATROL:New( DefenderPatrol, Patrol.Zone, Patrol.FloorAltitude, Patrol.CeilingAltitude, Patrol.PatrolMinSpeed, Patrol.PatrolMaxSpeed, Patrol.EngageMinSpeed, Patrol.EngageMaxSpeed, Patrol.AltType ) + local AI_A2G_PATROL = { SEAD = AI_A2G_SEAD, BAI = AI_A2G_BAI, CAS = AI_A2G_CAS } + + local Fsm = AI_A2G_PATROL[DefenseTaskType]:New( DefenderPatrol, Patrol.EngageMinSpeed, Patrol.EngageMaxSpeed, Patrol.Zone, Patrol.FloorAltitude, Patrol.CeilingAltitude, Patrol.PatrolMinSpeed, Patrol.PatrolMaxSpeed, Patrol.AltType ) Fsm:SetDispatcher( self ) Fsm:SetHomeAirbase( DefenderSquadron.Airbase ) Fsm:SetFuelThreshold( DefenderSquadron.FuelThreshold or self.DefenderDefault.FuelThreshold, 60 ) @@ -2930,7 +2932,7 @@ do -- AI_A2G_DISPATCHER Fsm:SetTanker( DefenderSquadron.TankerName or self.DefenderDefault.TankerName ) Fsm:Start() - self:SetDefenderTask( SquadronName, DefenderPatrol, DefenseTaskType, Fsm ) + self:SetDefenderTask( SquadronName, DefenderPatrol, DefenseTaskType, Fsm, nil, DefenderGrouping ) function Fsm:onafterTakeoff( Defender, From, Event, To ) self:F({"Patrol Birth", Defender:GetName()}) @@ -2967,7 +2969,7 @@ do -- AI_A2G_DISPATCHER if Dispatcher:GetSquadronLanding( Squadron.Name ) == AI_A2G_DISPATCHER.Landing.NearAirbase then Dispatcher:RemoveDefenderFromSquadron( Squadron, Defender ) Defender:Destroy() - self:ParkDefender( Squadron, Defender ) + Dispatcher:ParkDefender( Squadron, Defender ) end end end @@ -3425,7 +3427,7 @@ do -- AI_A2G_DISPATCHER if self.TacticalDisplay then -- Show tactical situation - Report:Add( string.format( "\n - %s %s ( %s ): ( #%d ) %s" , DetectedItem.Type or " --- ", DetectedItem.ItemID, DetectedItem.Index, DetectedItem.Set:Count(), DetectedItem.Set:GetObjectNames() ) ) + Report:Add( string.format( "\n - %4s %s ( %s ): ( #%d ) %s" , DetectedItem.Type or " --- ", DetectedItem.ItemID, DetectedItem.Index, DetectedItem.Set:Count(), DetectedItem.Set:GetObjectNames() ) ) for Defender, DefenderTask in pairs( self:GetDefenderTasks() ) do local Defender = Defender -- Wrapper.Group#GROUP if DefenderTask.Target and DefenderTask.Target.Index == DetectedItem.Index then diff --git a/Moose Development/Moose/AI/AI_A2G_Engage.lua b/Moose Development/Moose/AI/AI_A2G_Engage.lua index a0513933f..7c09d1b56 100644 --- a/Moose Development/Moose/AI/AI_A2G_Engage.lua +++ b/Moose Development/Moose/AI/AI_A2G_Engage.lua @@ -97,7 +97,7 @@ function AI_A2G_ENGAGE:New( AIGroup, EngageMinSpeed, EngageMaxSpeed ) self.PatrolAltType = "RADIO" - self:AddTransition( { "Started", "Engaging", "Returning", "Airborne" }, "Engage", "Engaging" ) -- FSM_CONTROLLABLE Transition for type #AI_A2G_ENGAGE. + self:AddTransition( { "Started", "Engaging", "Returning", "Airborne", "Patrolling" }, "Engage", "Engaging" ) -- FSM_CONTROLLABLE Transition for type #AI_A2G_ENGAGE. --- OnBefore Transition Handler for Event Engage. -- @function [parent=#AI_A2G_ENGAGE] OnBeforeEngage diff --git a/Moose Development/Moose/AI/AI_A2G_Patrol.lua b/Moose Development/Moose/AI/AI_A2G_Patrol.lua index 9a667b5cc..185c4a02c 100644 --- a/Moose Development/Moose/AI/AI_A2G_Patrol.lua +++ b/Moose Development/Moose/AI/AI_A2G_Patrol.lua @@ -10,7 +10,7 @@ -- @image AI_Air_To_Ground_Patrol.JPG --- @type AI_A2G_PATROL --- @extends AI.AI_A2A_Patrol#AI_A2A_PATROL +-- @extends AI.AI_A2G_Engage#AI_A2G_ENGAGE --- The AI_A2G_PATROL class implements the core functions to patrol a @{Zone} by an AI @{Wrapper.Group} or @{Wrapper.Group} @@ -100,30 +100,33 @@ AI_A2G_PATROL = { --- Creates a new AI_A2G_PATROL object -- @param #AI_A2G_PATROL self -- @param Wrapper.Group#GROUP AIPatrol +-- @param DCS#Speed EngageMinSpeed The minimum speed of the @{Wrapper.Group} in km/h when engaging a target. +-- @param DCS#Speed EngageMaxSpeed The maximum speed of the @{Wrapper.Group} in km/h when engaging a target. -- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed. -- @param DCS#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol. -- @param DCS#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol. -- @param DCS#Speed PatrolMinSpeed The minimum speed of the @{Wrapper.Group} in km/h. -- @param DCS#Speed PatrolMaxSpeed The maximum speed of the @{Wrapper.Group} in km/h. --- @param DCS#Speed EngageMinSpeed The minimum speed of the @{Wrapper.Group} in km/h when engaging a target. --- @param DCS#Speed EngageMaxSpeed The maximum speed of the @{Wrapper.Group} in km/h when engaging a target. -- @param DCS#AltitudeType PatrolAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to RADIO -- @return #AI_A2G_PATROL -function AI_A2G_PATROL:New( AIPatrol, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, EngageMinSpeed, EngageMaxSpeed, PatrolAltType ) +function AI_A2G_PATROL:New( AIPatrol, EngageMinSpeed, EngageMaxSpeed, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType ) -- Inherits from BASE - local self = BASE:Inherit( self, AI_A2G:New( AIPatrol ) ) -- #AI_A2G_PATROL + local self = BASE:Inherit( self, AI_A2G_ENGAGE:New( AIPatrol, EngageMinSpeed, EngageMaxSpeed ) ) -- #AI_A2G_PATROL - self.Accomplished = false - self.Engaging = false + self.PatrolZone = PatrolZone + self.PatrolFloorAltitude = PatrolFloorAltitude + self.PatrolCeilingAltitude = PatrolCeilingAltitude + self.PatrolMinSpeed = PatrolMinSpeed + self.PatrolMaxSpeed = PatrolMaxSpeed - self.EngageMinSpeed = EngageMinSpeed - self.EngageMaxSpeed = EngageMaxSpeed + -- defafult PatrolAltType to "RADIO" if not specified + self.PatrolAltType = PatrolAltType or "RADIO" - self:AddTransition( { "Patrolling", "Engaging", "Returning", "Airborne" }, "Engage", "Engaging" ) -- FSM_CONTROLLABLE Transition for type #AI_A2G_PATROL. + self:AddTransition( { "Started", "Airborne", "Refuelling" }, "Patrol", "Patrolling" ) - --- OnBefore Transition Handler for Event Engage. - -- @function [parent=#AI_A2G_PATROL] OnBeforeEngage + --- OnBefore Transition Handler for Event Patrol. + -- @function [parent=#AI_A2G_PATROL] OnBeforePatrol -- @param #AI_A2G_PATROL self -- @param Wrapper.Group#GROUP AIPatrol The Group Object managed by the FSM. -- @param #string From The From State string. @@ -131,44 +134,25 @@ function AI_A2G_PATROL:New( AIPatrol, PatrolZone, PatrolFloorAltitude, PatrolCei -- @param #string To The To State string. -- @return #boolean Return false to cancel Transition. - --- OnAfter Transition Handler for Event Engage. - -- @function [parent=#AI_A2G_PATROL] OnAfterEngage + --- OnAfter Transition Handler for Event Patrol. + -- @function [parent=#AI_A2G_PATROL] OnAfterPatrol -- @param #AI_A2G_PATROL self -- @param Wrapper.Group#GROUP AIPatrol The Group 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 Engage. - -- @function [parent=#AI_A2G_PATROL] Engage + + --- Synchronous Event Trigger for Event Patrol. + -- @function [parent=#AI_A2G_PATROL] Patrol -- @param #AI_A2G_PATROL self - --- Asynchronous Event Trigger for Event Engage. - -- @function [parent=#AI_A2G_PATROL] __Engage + --- Asynchronous Event Trigger for Event Patrol. + -- @function [parent=#AI_A2G_PATROL] __Patrol -- @param #AI_A2G_PATROL self -- @param #number Delay The delay in seconds. - ---- OnLeave Transition Handler for State Engaging. --- @function [parent=#AI_A2G_PATROL] OnLeaveEngaging --- @param #AI_A2G_PATROL self --- @param Wrapper.Group#GROUP AIPatrol The Group 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 Engaging. --- @function [parent=#AI_A2G_PATROL] OnEnterEngaging --- @param #AI_A2G_PATROL self --- @param Wrapper.Group#GROUP AIPatrol The Group 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. - - self:AddTransition( "Engaging", "Fired", "Engaging" ) -- FSM_CONTROLLABLE Transition for type #AI_A2G_PATROL. - --- OnBefore Transition Handler for Event Fired. - -- @function [parent=#AI_A2G_PATROL] OnBeforeFired + --- OnLeave Transition Handler for State Patrolling. + -- @function [parent=#AI_A2G_PATROL] OnLeavePatrolling -- @param #AI_A2G_PATROL self -- @param Wrapper.Group#GROUP AIPatrol The Group Object managed by the FSM. -- @param #string From The From State string. @@ -176,27 +160,18 @@ function AI_A2G_PATROL:New( AIPatrol, PatrolZone, PatrolFloorAltitude, PatrolCei -- @param #string To The To State string. -- @return #boolean Return false to cancel Transition. - --- OnAfter Transition Handler for Event Fired. - -- @function [parent=#AI_A2G_PATROL] OnAfterFired + --- OnEnter Transition Handler for State Patrolling. + -- @function [parent=#AI_A2G_PATROL] OnEnterPatrolling -- @param #AI_A2G_PATROL self -- @param Wrapper.Group#GROUP AIPatrol The Group 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 Fired. - -- @function [parent=#AI_A2G_PATROL] Fired - -- @param #AI_A2G_PATROL self - --- Asynchronous Event Trigger for Event Fired. - -- @function [parent=#AI_A2G_PATROL] __Fired - -- @param #AI_A2G_PATROL self - -- @param #number Delay The delay in seconds. - - self:AddTransition( "*", "Destroy", "*" ) -- FSM_CONTROLLABLE Transition for type #AI_A2G_PATROL. - - --- OnBefore Transition Handler for Event Destroy. - -- @function [parent=#AI_A2G_PATROL] OnBeforeDestroy + self:AddTransition( "Patrolling", "Route", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_A2G_PATROL. + + --- OnBefore Transition Handler for Event Route. + -- @function [parent=#AI_A2G_PATROL] OnBeforeRoute -- @param #AI_A2G_PATROL self -- @param Wrapper.Group#GROUP AIPatrol The Group Object managed by the FSM. -- @param #string From The From State string. @@ -204,110 +179,30 @@ function AI_A2G_PATROL:New( AIPatrol, PatrolZone, PatrolFloorAltitude, PatrolCei -- @param #string To The To State string. -- @return #boolean Return false to cancel Transition. - --- OnAfter Transition Handler for Event Destroy. - -- @function [parent=#AI_A2G_PATROL] OnAfterDestroy + --- OnAfter Transition Handler for Event Route. + -- @function [parent=#AI_A2G_PATROL] OnAfterRoute -- @param #AI_A2G_PATROL self -- @param Wrapper.Group#GROUP AIPatrol The Group 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 Destroy. - -- @function [parent=#AI_A2G_PATROL] Destroy + + --- Synchronous Event Trigger for Event Route. + -- @function [parent=#AI_A2G_PATROL] Route -- @param #AI_A2G_PATROL self - --- Asynchronous Event Trigger for Event Destroy. - -- @function [parent=#AI_A2G_PATROL] __Destroy + --- Asynchronous Event Trigger for Event Route. + -- @function [parent=#AI_A2G_PATROL] __Route -- @param #AI_A2G_PATROL self -- @param #number Delay The delay in seconds. - self:AddTransition( "Engaging", "Abort", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_A2G_PATROL. - - --- OnBefore Transition Handler for Event Abort. - -- @function [parent=#AI_A2G_PATROL] OnBeforeAbort - -- @param #AI_A2G_PATROL self - -- @param Wrapper.Group#GROUP AIPatrol The Group 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 Abort. - -- @function [parent=#AI_A2G_PATROL] OnAfterAbort - -- @param #AI_A2G_PATROL self - -- @param Wrapper.Group#GROUP AIPatrol The Group 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 Abort. - -- @function [parent=#AI_A2G_PATROL] Abort - -- @param #AI_A2G_PATROL self - - --- Asynchronous Event Trigger for Event Abort. - -- @function [parent=#AI_A2G_PATROL] __Abort - -- @param #AI_A2G_PATROL self - -- @param #number Delay The delay in seconds. - - self:AddTransition( "Engaging", "Accomplish", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_A2G_PATROL. - - --- OnBefore Transition Handler for Event Accomplish. - -- @function [parent=#AI_A2G_PATROL] OnBeforeAccomplish - -- @param #AI_A2G_PATROL self - -- @param Wrapper.Group#GROUP AIPatrol The Group 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 Accomplish. - -- @function [parent=#AI_A2G_PATROL] OnAfterAccomplish - -- @param #AI_A2G_PATROL self - -- @param Wrapper.Group#GROUP AIPatrol The Group 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 Accomplish. - -- @function [parent=#AI_A2G_PATROL] Accomplish - -- @param #AI_A2G_PATROL self - - --- Asynchronous Event Trigger for Event Accomplish. - -- @function [parent=#AI_A2G_PATROL] __Accomplish - -- @param #AI_A2G_PATROL self - -- @param #number Delay The delay in seconds. + self:AddTransition( "*", "Reset", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_A2G_PATROL. return self end ---- onafter State Transition for Event Patrol. --- @param #AI_A2G_PATROL self --- @param Wrapper.Group#GROUP AIPatrol The AI Group 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 AI_A2G_PATROL:onafterStart( AIPatrol, From, Event, To ) - - AIPatrol:HandleEvent( EVENTS.Takeoff, nil, self ) - -end - ---- Set the Engage Zone which defines where the AI will engage bogies. --- @param #AI_A2G_PATROL self --- @param Core.Zone#ZONE EngageZone The zone where the AI is performing CAP. --- @return #AI_A2G_PATROL self -function AI_A2G_PATROL:SetEngageZone( EngageZone ) - self:F2() - - if EngageZone then - self.EngageZone = EngageZone - else - self.EngageZone = nil - end -end - --- Set the Engage Range when the AI will engage with airborne enemies. -- @param #AI_A2G_PATROL self -- @param #number EngageRange The Engage Range. @@ -322,157 +217,93 @@ function AI_A2G_PATROL:SetEngageRange( EngageRange ) end end ---- onafter State Transition for Event Patrol. +--- Defines a new patrol route using the @{Process_PatrolZone} parameters and settings. -- @param #AI_A2G_PATROL self --- @param Wrapper.Group#GROUP AIPatrol The AI Group managed by the FSM. +-- @return #AI_A2G_PATROL self +-- @param Wrapper.Group#GROUP AIPatrol The Group 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 AI_A2G_PATROL:onafterPatrol( AIPatrol, From, Event, To ) + self:F2() - -- Call the parent Start event handler - self:GetParent(self).onafterPatrol( self, AIPatrol, From, Event, To ) - self:HandleEvent( EVENTS.Dead ) + self:ClearTargetDistance() + self:__Route( 1 ) + + AIPatrol:OnReSpawn( + function( PatrolGroup ) + self:__Reset( 1 ) + self:__Route( 5 ) + end + ) end --- todo: need to fix this global function - --- @param Wrapper.Group#GROUP AIPatrol -function AI_A2G_PATROL.AttackRoute( AIPatrol, Fsm ) +-- This statis method is called from the route path within the last task at the last waaypoint of the AIPatrol. +-- Note that this method is required, as triggers the next route when patrolling for the AIPatrol. +function AI_A2G_PATROL.PatrolRoute( AIPatrol, Fsm ) - AIPatrol:F( { "AI_A2G_PATROL.AttackRoute:", AIPatrol:GetName() } ) + AIPatrol:F( { "AI_A2G_PATROL.PatrolRoute:", AIPatrol:GetName() } ) if AIPatrol:IsAlive() then - Fsm:__Engage( 0.5 ) + Fsm:Route() end + end ---- @param #AI_A2G_PATROL self --- @param Wrapper.Group#GROUP AIPatrol The Group Object managed by the FSM. +--- Defines a new patrol route using the @{Process_PatrolZone} parameters and settings. +-- @param #AI_A2G_PATROL self +-- @param Wrapper.Group#GROUP AIPatrol The Group 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 AI_A2G_PATROL:onbeforeEngage( AIPatrol, From, Event, To ) - - if self.Accomplished == true then - return false +function AI_A2G_PATROL:onafterRoute( AIPatrol, From, Event, To ) + + self:F2() + + -- When RTB, don't allow anymore the routing. + if From == "RTB" then + return end -end ---- @param #AI_A2G_PATROL self --- @param Wrapper.Group#GROUP AIPatrol The AI Group 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 AI_A2G_PATROL:onafterAbort( AIPatrol, From, Event, To ) - AIPatrol:ClearTasks() - self:__Route( 0.5 ) -end - - ---- @param #AI_A2G_PATROL self --- @param Wrapper.Group#GROUP AIPatrol The AIPatrol 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 AI_A2G_PATROL:onafterEngage( AIPatrol, From, Event, To, AttackSetUnit ) - - self:F( { AIPatrol, From, Event, To, AttackSetUnit} ) - - self.AttackSetUnit = AttackSetUnit or self.AttackSetUnit -- Core.Set#SET_UNIT - local FirstAttackUnit = self.AttackSetUnit:GetFirst() -- Wrapper.Unit#UNIT - - if FirstAttackUnit and FirstAttackUnit:IsAlive() then -- If there is no attacker anymore, stop the engagement. - - if AIPatrol:IsAlive() then + if AIPatrol:IsAlive() then + + local PatrolRoute = {} - local EngageRoute = {} + --- Calculate the target route point. + + local CurrentCoord = AIPatrol:GetCoordinate() + + local ToTargetCoord = self.PatrolZone:GetRandomPointVec2() + ToTargetCoord:SetAlt( math.random( self.PatrolFloorAltitude, self.PatrolCeilingAltitude ) ) + self:SetTargetDistance( ToTargetCoord ) -- For RTB status check + + local ToTargetSpeed = math.random( self.PatrolMinSpeed, self.PatrolMaxSpeed ) + + --- Create a route point of type air. + local ToPatrolRoutePoint = ToTargetCoord:WaypointAir( + self.PatrolAltType, + POINT_VEC3.RoutePointType.TurningPoint, + POINT_VEC3.RoutePointAction.TurningPoint, + ToTargetSpeed, + true + ) - --- Calculate the target route point. - local CurrentCoord = AIPatrol:GetCoordinate() - local ToTargetCoord = self.AttackSetUnit:GetFirst():GetCoordinate() - local ToTargetSpeed = math.random( self.EngageMinSpeed, self.EngageMaxSpeed ) - local ToInterceptAngle = CurrentCoord:GetAngleDegrees( CurrentCoord:GetDirectionVec3( ToTargetCoord ) ) - - --- Create a route point of type air. - local ToPatrolRoutePoint = CurrentCoord:Translate( 5000, ToInterceptAngle ):WaypointAir( - self.PatrolAltType, - POINT_VEC3.RoutePointType.TurningPoint, - POINT_VEC3.RoutePointAction.TurningPoint, - ToTargetSpeed, - true - ) - - self:F( { Angle = ToInterceptAngle, ToTargetSpeed = ToTargetSpeed } ) - self:T2( { self.MinSpeed, self.MaxSpeed, ToTargetSpeed } ) - - EngageRoute[#EngageRoute+1] = ToPatrolRoutePoint - EngageRoute[#EngageRoute+1] = ToPatrolRoutePoint + PatrolRoute[#PatrolRoute+1] = ToPatrolRoutePoint + PatrolRoute[#PatrolRoute+1] = ToPatrolRoutePoint + + local Tasks = {} + Tasks[#Tasks+1] = AIPatrol:TaskFunction( "AI_A2G_PATROL.PatrolRoute", self ) + PatrolRoute[#PatrolRoute].task = AIPatrol:TaskCombo( Tasks ) + + AIPatrol:OptionROEReturnFire() + AIPatrol:OptionROTEvadeFire() - local AttackTasks = {} - - for AttackUnitID, AttackUnit in pairs( self.AttackSetUnit:GetSet() ) do - local AttackUnit = AttackUnit -- Wrapper.Unit#UNIT - self:T( { "Attacking Unit:", AttackUnit:GetName(), AttackUnit:IsAlive(), AttackUnit:IsAir() } ) - if AttackUnit:IsAlive() and AttackUnit:IsGround() then - AttackTasks[#AttackTasks+1] = AIPatrol:TaskAttackUnit( AttackUnit ) - end - end - - if #AttackTasks == 0 then - self:E("No targets found -> Going back to Patrolling") - self:__Abort( 0.5 ) - else - AIPatrol:OptionROEOpenFire() - AIPatrol:OptionROTEvadeFire() - - AttackTasks[#AttackTasks+1] = AIPatrol:TaskFunction( "AI_A2G_PATROL.AttackRoute", self ) - EngageRoute[#EngageRoute].task = AIPatrol:TaskCombo( AttackTasks ) - end - - AIPatrol:Route( EngageRoute, 0.5 ) - end - else - self:E("No targets found -> Going back to Patrolling") - self:__Abort( 0.5 ) + AIPatrol:Route( PatrolRoute, 0.5 ) end -end ---- @param #AI_A2G_PATROL self --- @param Wrapper.Group#GROUP AIPatrol The Group 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 AI_A2G_PATROL:onafterAccomplish( AIPatrol, From, Event, To ) - self.Accomplished = true - self:SetDetectionOff() -end - ---- @param #AI_A2G_PATROL self --- @param Wrapper.Group#GROUP AIPatrol The Group 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. --- @param Core.Event#EVENTDATA EventData -function AI_A2G_PATROL:onafterDestroy( AIPatrol, From, Event, To, EventData ) - - if EventData.IniUnit then - self.AttackUnits[EventData.IniUnit] = nil - end -end - ---- @param #AI_A2G_PATROL self --- @param Core.Event#EVENTDATA EventData -function AI_A2G_PATROL:OnEventDead( EventData ) - self:F( { "EventDead", EventData } ) - - if EventData.IniDCSUnit then - if self.AttackUnits and self.AttackUnits[EventData.IniUnit] then - self:__Destroy( 1, EventData ) - end - end end --- @param Wrapper.Group#GROUP AIPatrol diff --git a/Moose Development/Moose/AI/AI_A2G_SEAD.lua b/Moose Development/Moose/AI/AI_A2G_SEAD.lua index c0db300d4..dfaf89b34 100644 --- a/Moose Development/Moose/AI/AI_A2G_SEAD.lua +++ b/Moose Development/Moose/AI/AI_A2G_SEAD.lua @@ -81,11 +81,19 @@ AI_A2G_SEAD = { --- Creates a new AI_A2G_SEAD object -- @param #AI_A2G_SEAD self -- @param Wrapper.Group#GROUP AIGroup +-- @param DCS#Speed EngageMinSpeed The minimum speed of the @{Wrapper.Group} in km/h when engaging a target. +-- @param DCS#Speed EngageMaxSpeed The maximum speed of the @{Wrapper.Group} in km/h when engaging a target. +-- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed. +-- @param DCS#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol. +-- @param DCS#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol. +-- @param DCS#Speed PatrolMinSpeed The minimum speed of the @{Wrapper.Group} in km/h. +-- @param DCS#Speed PatrolMaxSpeed The maximum speed of the @{Wrapper.Group} in km/h. +-- @param DCS#AltitudeType PatrolAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to RADIO -- @return #AI_A2G_SEAD -function AI_A2G_SEAD:New( AIGroup, EngageMinSpeed, EngageMaxSpeed ) +function AI_A2G_SEAD:New( AIGroup, EngageMinSpeed, EngageMaxSpeed, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType ) -- Inherits from BASE - local self = BASE:Inherit( self, AI_A2G_ENGAGE:New( AIGroup, EngageMinSpeed, EngageMaxSpeed ) ) -- #AI_A2G_SEAD + local self = BASE:Inherit( self, AI_A2G_PATROL:New( AIGroup, EngageMinSpeed, EngageMaxSpeed, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType ) ) -- #AI_A2G_SEAD return self end diff --git a/Moose Development/Moose/AI/AI_Air.lua b/Moose Development/Moose/AI/AI_Air.lua index 85d125384..3c808beaa 100644 --- a/Moose Development/Moose/AI/AI_Air.lua +++ b/Moose Development/Moose/AI/AI_Air.lua @@ -511,7 +511,7 @@ function AI_AIR:onafterStatus() end if not self:Is("Home") then - self:__Status( 10 ) + self:__Status( 30 ) end end From 6c4bde4ceb294ddbba535b20444e7725e31bbf69 Mon Sep 17 00:00:00 2001 From: FlightControl Date: Mon, 17 Dec 2018 20:59:58 +0100 Subject: [PATCH 07/14] Fixes --- Moose Development/Moose/AI/AI_A2G.lua | 2 +- Moose Development/Moose/AI/AI_A2G_CAS.lua | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Moose Development/Moose/AI/AI_A2G.lua b/Moose Development/Moose/AI/AI_A2G.lua index 2f6a8f500..b80eb8796 100644 --- a/Moose Development/Moose/AI/AI_A2G.lua +++ b/Moose Development/Moose/AI/AI_A2G.lua @@ -61,7 +61,7 @@ function AI_A2G:New( AIGroup ) local self = BASE:Inherit( self, AI_AIR:New( AIGroup ) ) -- #AI_A2G self:SetFuelThreshold( .2, 60 ) - self:SetDamageThreshold( 0.4 ) + self:SetDamageThreshold( 0.95 ) self:SetDisengageRadius( 70000 ) return self diff --git a/Moose Development/Moose/AI/AI_A2G_CAS.lua b/Moose Development/Moose/AI/AI_A2G_CAS.lua index e2465d572..e3ef10419 100644 --- a/Moose Development/Moose/AI/AI_A2G_CAS.lua +++ b/Moose Development/Moose/AI/AI_A2G_CAS.lua @@ -98,8 +98,10 @@ function AI_A2G_CAS:onafterEngage( DefenderGroup, From, Event, To, AttackSetUnit local FromEngageAngle = ToCoord:GetAngleDegrees( ToCoord:GetDirectionVec3( DefenderCoord ) ) + local EngageDistance = ( DefenderGroup:IsHelicopter() and 5000 ) or ( DefenderGroup:IsAirPlane() and 10000 ) + --- Create a route point of type air. - local ToWP = ToCoord:Translate( 10000, FromEngageAngle ):WaypointAir( + local ToWP = ToCoord:Translate( EngageDistance, FromEngageAngle ):WaypointAir( self.PatrolAltType, POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, From e91a744bd9a98acaae7e4cf41bfb60ca0348040b Mon Sep 17 00:00:00 2001 From: FlightControl Date: Wed, 19 Dec 2018 07:24:01 +0100 Subject: [PATCH 08/14] Fixed for A2G. Default parameters and proper amount of spawnings. Now also altitude is added for engage. And RTB has min and max speed set. Defaults of speed between 50% and 75% of maximum speed of group. And altitude defaults to 1000 and 1500 meters. --- Moose Development/Moose/AI/AI_A2G_BAI.lua | 17 ++-- Moose Development/Moose/AI/AI_A2G_CAS.lua | 30 +++--- .../Moose/AI/AI_A2G_Dispatcher.lua | 92 +++++++++++-------- Moose Development/Moose/AI/AI_A2G_Engage.lua | 16 ++-- Moose Development/Moose/AI/AI_A2G_Patrol.lua | 33 ++++--- Moose Development/Moose/AI/AI_A2G_SEAD.lua | 19 ++-- Moose Development/Moose/AI/AI_Air.lua | 20 +++- 7 files changed, 141 insertions(+), 86 deletions(-) diff --git a/Moose Development/Moose/AI/AI_A2G_BAI.lua b/Moose Development/Moose/AI/AI_A2G_BAI.lua index 2806852a1..59da48bd8 100644 --- a/Moose Development/Moose/AI/AI_A2G_BAI.lua +++ b/Moose Development/Moose/AI/AI_A2G_BAI.lua @@ -33,6 +33,8 @@ AI_A2G_BAI = { -- @param Wrapper.Group#GROUP AIGroup -- @param DCS#Speed EngageMinSpeed The minimum speed of the @{Wrapper.Group} in km/h when engaging a target. -- @param DCS#Speed EngageMaxSpeed The maximum speed of the @{Wrapper.Group} in km/h when engaging a target. +-- @param DCS#Altitude EngageFloorAltitude The lowest altitude in meters where to execute the engagement. +-- @param DCS#Altitude EngageCeilingAltitude The highest altitude in meters where to execute the engagement. -- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed. -- @param DCS#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol. -- @param DCS#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol. @@ -40,10 +42,10 @@ AI_A2G_BAI = { -- @param DCS#Speed PatrolMaxSpeed The maximum speed of the @{Wrapper.Group} in km/h. -- @param DCS#AltitudeType PatrolAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to RADIO -- @return #AI_A2G_BAI -function AI_A2G_BAI:New( AIGroup, EngageMinSpeed, EngageMaxSpeed, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType ) +function AI_A2G_BAI:New( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType ) -- Inherits from BASE - local self = BASE:Inherit( self, AI_A2G_PATROL:New( AIGroup, EngageMinSpeed, EngageMaxSpeed, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType ) ) -- #AI_A2G_BAI + local self = BASE:Inherit( self, AI_A2G_PATROL:New( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType ) ) -- #AI_A2G_BAI return self end @@ -72,8 +74,11 @@ function AI_A2G_BAI:onafterEngage( DefenderGroup, From, Event, To, AttackSetUnit -- If it is less than 10km, then attack without a route. -- Otherwise perform a route attack. - local DefenderCoord = DefenderGroup:GetCoordinate() - local TargetCoord = self.AttackSetUnit:GetFirst():GetCoordinate() + local DefenderCoord = DefenderGroup:GetPointVec3() + DefenderCoord:SetY( math.random( self.EngageFloorAltitude, self.EngageCeilingAltitude ) ) -- Ground targets don't have an altitude. + + local TargetCoord = self.AttackSetUnit:GetFirst():GetPointVec3() + TargetCoord:SetY( math.random( self.EngageFloorAltitude, self.EngageCeilingAltitude ) ) -- Ground targets don't have an altitude. local TargetDistance = DefenderCoord:Get2DDistance( TargetCoord ) @@ -84,7 +89,7 @@ function AI_A2G_BAI:onafterEngage( DefenderGroup, From, Event, To, AttackSetUnit --- Calculate the target route point. local FromWP = DefenderCoord:WaypointAir( - self.PatrolAltType, + self.PatrolAltType or "RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, ToTargetSpeed, @@ -100,7 +105,7 @@ function AI_A2G_BAI:onafterEngage( DefenderGroup, From, Event, To, AttackSetUnit --- Create a route point of type air. local ToWP = ToCoord:Translate( 10000, FromEngageAngle ):WaypointAir( - self.PatrolAltType, + self.PatrolAltType or "RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, ToTargetSpeed, diff --git a/Moose Development/Moose/AI/AI_A2G_CAS.lua b/Moose Development/Moose/AI/AI_A2G_CAS.lua index e3ef10419..63562487b 100644 --- a/Moose Development/Moose/AI/AI_A2G_CAS.lua +++ b/Moose Development/Moose/AI/AI_A2G_CAS.lua @@ -14,7 +14,7 @@ --- @type AI_A2G_CAS --- @extends AI.AI_A2G_Engage#AI_A2G_Engage +-- @extends AI.AI_A2G_Patrol#AI_A2G_PATROL --- Implements the core functions to intercept intruders. Use the Engage trigger to intercept intruders. @@ -33,6 +33,8 @@ AI_A2G_CAS = { -- @param Wrapper.Group#GROUP AIGroup -- @param DCS#Speed EngageMinSpeed The minimum speed of the @{Wrapper.Group} in km/h when engaging a target. -- @param DCS#Speed EngageMaxSpeed The maximum speed of the @{Wrapper.Group} in km/h when engaging a target. +-- @param DCS#Altitude EngageFloorAltitude The lowest altitude in meters where to execute the engagement. +-- @param DCS#Altitude EngageCeilingAltitude The highest altitude in meters where to execute the engagement. -- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed. -- @param DCS#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol. -- @param DCS#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol. @@ -40,10 +42,14 @@ AI_A2G_CAS = { -- @param DCS#Speed PatrolMaxSpeed The maximum speed of the @{Wrapper.Group} in km/h. -- @param DCS#AltitudeType PatrolAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to RADIO -- @return #AI_A2G_CAS -function AI_A2G_CAS:New( AIGroup, EngageMinSpeed, EngageMaxSpeed, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType ) +function AI_A2G_CAS:New( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType ) -- Inherits from BASE - local self = BASE:Inherit( self, AI_A2G_PATROL:New( AIGroup, EngageMinSpeed, EngageMaxSpeed, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType ) ) -- #AI_A2G_CAS + local self = BASE:Inherit( self, AI_A2G_PATROL:New( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType ) ) -- #AI_A2G_CAS + + local RTBSpeedMax = AIGroup:GetSpeedMax() + + self:SetRTBSpeed( RTBSpeedMax * 0.50, RTBSpeedMax * 0.75 ) return self end @@ -72,8 +78,11 @@ function AI_A2G_CAS:onafterEngage( DefenderGroup, From, Event, To, AttackSetUnit -- If it is less than 10km, then attack without a route. -- Otherwise perform a route attack. - local DefenderCoord = DefenderGroup:GetCoordinate() - local TargetCoord = self.AttackSetUnit:GetFirst():GetCoordinate() + local DefenderCoord = DefenderGroup:GetPointVec3() + DefenderCoord:SetY( math.random( self.EngageFloorAltitude, self.EngageCeilingAltitude ) ) -- Ground targets don't have an altitude. + + local TargetCoord = self.AttackSetUnit:GetFirst():GetPointVec3() + TargetCoord:SetY( math.random( self.EngageFloorAltitude, self.EngageCeilingAltitude ) ) -- Ground targets don't have an altitude. local TargetDistance = DefenderCoord:Get2DDistance( TargetCoord ) @@ -84,7 +93,7 @@ function AI_A2G_CAS:onafterEngage( DefenderGroup, From, Event, To, AttackSetUnit --- Calculate the target route point. local FromWP = DefenderCoord:WaypointAir( - self.PatrolAltType, + self.PatrolAltType or "RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, ToTargetSpeed, @@ -93,16 +102,15 @@ function AI_A2G_CAS:onafterEngage( DefenderGroup, From, Event, To, AttackSetUnit EngageRoute[#EngageRoute+1] = FromWP - local ToCoord = self.AttackSetUnit:GetFirst():GetCoordinate() - self:SetTargetDistance( ToCoord ) -- For RTB status check + self:SetTargetDistance( TargetCoord ) -- For RTB status check - local FromEngageAngle = ToCoord:GetAngleDegrees( ToCoord:GetDirectionVec3( DefenderCoord ) ) + local FromEngageAngle = TargetCoord:GetAngleDegrees( TargetCoord:GetDirectionVec3( DefenderCoord ) ) local EngageDistance = ( DefenderGroup:IsHelicopter() and 5000 ) or ( DefenderGroup:IsAirPlane() and 10000 ) --- Create a route point of type air. - local ToWP = ToCoord:Translate( EngageDistance, FromEngageAngle ):WaypointAir( - self.PatrolAltType, + local ToWP = TargetCoord:Translate( EngageDistance, FromEngageAngle ):WaypointAir( + self.PatrolAltType or "RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, ToTargetSpeed, diff --git a/Moose Development/Moose/AI/AI_A2G_Dispatcher.lua b/Moose Development/Moose/AI/AI_A2G_Dispatcher.lua index 0070e3c6e..facc45a66 100644 --- a/Moose Development/Moose/AI/AI_A2G_Dispatcher.lua +++ b/Moose Development/Moose/AI/AI_A2G_Dispatcher.lua @@ -1656,8 +1656,10 @@ do -- AI_A2G_DISPATCHER --- -- @param #AI_A2G_DISPATCHER self -- @param #string SquadronName The squadron name. - -- @param #number EngageMinSpeed The minimum speed at which the SEAD task can be executed. - -- @param #number EngageMaxSpeed The maximum speed at which the SEAD task can be executed. + -- @param #number EngageMinSpeed (optional, default = 50% of max speed) The minimum speed at which the SEAD task can be executed. + -- @param #number EngageMaxSpeed (optional, default = 75% of max speed) The maximum speed at which the SEAD task can be executed. + -- @param DCS#Altitude EngageFloorAltitude (optional, default = 1000m ) The lowest altitude in meters where to execute the engagement. + -- @param DCS#Altitude EngageCeilingAltitude (optional, default = 1500m ) The highest altitude in meters where to execute the engagement. -- @usage -- -- -- SEAD Squadron execution. @@ -1666,7 +1668,7 @@ do -- AI_A2G_DISPATCHER -- A2GDispatcher:SetSquadronSead( "Maykop", 900, 1200 ) -- -- @return #AI_A2G_DISPATCHER - function AI_A2G_DISPATCHER:SetSquadronSead( SquadronName, EngageMinSpeed, EngageMaxSpeed ) + function AI_A2G_DISPATCHER:SetSquadronSead( SquadronName, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude ) local DefenderSquadron = self:GetSquadron( SquadronName ) @@ -1676,6 +1678,8 @@ do -- AI_A2G_DISPATCHER Sead.Name = SquadronName Sead.EngageMinSpeed = EngageMinSpeed Sead.EngageMaxSpeed = EngageMaxSpeed + Sead.EngageFloorAltitude = EngageFloorAltitude + Sead.EngageCeilingAltitude = EngageCeilingAltitude Sead.Defend = true self:F( { Sead = Sead } ) @@ -1706,12 +1710,12 @@ do -- AI_A2G_DISPATCHER -- @param #AI_A2G_DISPATCHER self -- @param #string SquadronName The squadron name. -- @param Core.Zone#ZONE_BASE Zone The @{Zone} object derived from @{Core.Zone#ZONE_BASE} that defines the zone wherein the Patrol will be executed. - -- @param #number FloorAltitude The minimum altitude at which the cap can be executed. - -- @param #number CeilingAltitude the maximum altitude at which the cap can be executed. - -- @param #number PatrolMinSpeed The minimum speed at which the cap can be executed. - -- @param #number PatrolMaxSpeed The maximum speed at which the cap can be executed. - -- @param #number EngageMinSpeed The minimum speed at which the engage can be executed. - -- @param #number EngageMaxSpeed The maximum speed at which the engage can be executed. + -- @param #number FloorAltitude (optional, default = 1000m ) The minimum altitude at which the cap can be executed. + -- @param #number CeilingAltitude (optional, default = 1500m ) The maximum altitude at which the cap can be executed. + -- @param #number PatrolMinSpeed (optional, default = 50% of max speed) The minimum speed at which the cap can be executed. + -- @param #number PatrolMaxSpeed (optional, default = 75% of max speed) The maximum speed at which the cap can be executed. + -- @param #number EngageMinSpeed (optional, default = 50% of max speed) The minimum speed at which the engage can be executed. + -- @param #number EngageMaxSpeed (optional, default = 75% of max speed) The maximum speed at which the engage can be executed. -- @param #number AltType The altitude type, which is a string "BARO" defining Barometric or "RADIO" defining radio controlled altitude. -- @return #AI_A2G_DISPATCHER -- @usage @@ -1729,8 +1733,10 @@ do -- AI_A2G_DISPATCHER local SeadPatrol = DefenderSquadron.SEAD SeadPatrol.Name = SquadronName SeadPatrol.Zone = Zone - SeadPatrol.FloorAltitude = FloorAltitude - SeadPatrol.CeilingAltitude = CeilingAltitude + SeadPatrol.PatrolFloorAltitude = FloorAltitude + SeadPatrol.PatrolCeilingAltitude = CeilingAltitude + SeadPatrol.EngageFloorAltitude = FloorAltitude + SeadPatrol.EngageCeilingAltitude = CeilingAltitude SeadPatrol.PatrolMinSpeed = PatrolMinSpeed SeadPatrol.PatrolMaxSpeed = PatrolMaxSpeed SeadPatrol.EngageMinSpeed = EngageMinSpeed @@ -1747,8 +1753,10 @@ do -- AI_A2G_DISPATCHER --- -- @param #AI_A2G_DISPATCHER self -- @param #string SquadronName The squadron name. - -- @param #number EngageMinSpeed The minimum speed at which the CAS task can be executed. - -- @param #number EngageMaxSpeed The maximum speed at which the CAS task can be executed. + -- @param #number EngageMinSpeed (optional, default = 50% of max speed) The minimum speed at which the CAS task can be executed. + -- @param #number EngageMaxSpeed (optional, default = 75% of max speed) The maximum speed at which the CAS task can be executed. + -- @param DCS#Altitude EngageFloorAltitude (optional, default = 1000m ) The lowest altitude in meters where to execute the engagement. + -- @param DCS#Altitude EngageCeilingAltitude (optional, default = 1500m ) The highest altitude in meters where to execute the engagement. -- @usage -- -- -- CAS Squadron execution. @@ -1757,7 +1765,7 @@ do -- AI_A2G_DISPATCHER -- A2GDispatcher:SetSquadronCas( "Maykop", 900, 1200 ) -- -- @return #AI_A2G_DISPATCHER - function AI_A2G_DISPATCHER:SetSquadronCas( SquadronName, EngageMinSpeed, EngageMaxSpeed ) + function AI_A2G_DISPATCHER:SetSquadronCas( SquadronName, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude ) local DefenderSquadron = self:GetSquadron( SquadronName ) @@ -1767,6 +1775,8 @@ do -- AI_A2G_DISPATCHER Cas.Name = SquadronName Cas.EngageMinSpeed = EngageMinSpeed Cas.EngageMaxSpeed = EngageMaxSpeed + Cas.EngageFloorAltitude = EngageFloorAltitude + Cas.EngageCeilingAltitude = EngageCeilingAltitude Cas.Defend = true self:F( { Cas = Cas } ) @@ -1798,12 +1808,12 @@ do -- AI_A2G_DISPATCHER -- @param #AI_A2G_DISPATCHER self -- @param #string SquadronName The squadron name. -- @param Core.Zone#ZONE_BASE Zone The @{Zone} object derived from @{Core.Zone#ZONE_BASE} that defines the zone wherein the Patrol will be executed. - -- @param #number FloorAltitude The minimum altitude at which the cap can be executed. - -- @param #number CeilingAltitude the maximum altitude at which the cap can be executed. - -- @param #number PatrolMinSpeed The minimum speed at which the cap can be executed. - -- @param #number PatrolMaxSpeed The maximum speed at which the cap can be executed. - -- @param #number EngageMinSpeed The minimum speed at which the engage can be executed. - -- @param #number EngageMaxSpeed The maximum speed at which the engage can be executed. + -- @param #number FloorAltitude (optional, default = 1000m ) The minimum altitude at which the cap can be executed. + -- @param #number CeilingAltitude (optional, default = 1500m ) The maximum altitude at which the cap can be executed. + -- @param #number PatrolMinSpeed (optional, default = 50% of max speed) The minimum speed at which the cap can be executed. + -- @param #number PatrolMaxSpeed (optional, default = 75% of max speed) The maximum speed at which the cap can be executed. + -- @param #number EngageMinSpeed (optional, default = 50% of max speed) The minimum speed at which the engage can be executed. + -- @param #number EngageMaxSpeed (optional, default = 75% of max speed) The maximum speed at which the engage can be executed. -- @param #number AltType The altitude type, which is a string "BARO" defining Barometric or "RADIO" defining radio controlled altitude. -- @return #AI_A2G_DISPATCHER -- @usage @@ -1821,8 +1831,10 @@ do -- AI_A2G_DISPATCHER local CasPatrol = DefenderSquadron.CAS CasPatrol.Name = SquadronName CasPatrol.Zone = Zone - CasPatrol.FloorAltitude = FloorAltitude - CasPatrol.CeilingAltitude = CeilingAltitude + CasPatrol.PatrolFloorAltitude = FloorAltitude + CasPatrol.PatrolCeilingAltitude = CeilingAltitude + CasPatrol.EngageFloorAltitude = FloorAltitude + CasPatrol.EngageCeilingAltitude = CeilingAltitude CasPatrol.PatrolMinSpeed = PatrolMinSpeed CasPatrol.PatrolMaxSpeed = PatrolMaxSpeed CasPatrol.EngageMinSpeed = EngageMinSpeed @@ -1839,8 +1851,10 @@ do -- AI_A2G_DISPATCHER --- -- @param #AI_A2G_DISPATCHER self -- @param #string SquadronName The squadron name. - -- @param #number EngageMinSpeed The minimum speed at which the BAI task can be executed. - -- @param #number EngageMaxSpeed The maximum speed at which the BAI task can be executed. + -- @param #number EngageMinSpeed (optional, default = 50% of max speed) The minimum speed at which the BAI task can be executed. + -- @param #number EngageMaxSpeed (optional, default = 75% of max speed) The maximum speed at which the BAI task can be executed. + -- @param DCS#Altitude EngageFloorAltitude (optional, default = 1000m ) The lowest altitude in meters where to execute the engagement. + -- @param DCS#Altitude EngageCeilingAltitude (optional, default = 1500m ) The highest altitude in meters where to execute the engagement. -- @usage -- -- -- BAI Squadron execution. @@ -1849,7 +1863,7 @@ do -- AI_A2G_DISPATCHER -- A2GDispatcher:SetSquadronBai( "Maykop", 900, 1200 ) -- -- @return #AI_A2G_DISPATCHER - function AI_A2G_DISPATCHER:SetSquadronBai( SquadronName, EngageMinSpeed, EngageMaxSpeed ) + function AI_A2G_DISPATCHER:SetSquadronBai( SquadronName, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude ) local DefenderSquadron = self:GetSquadron( SquadronName ) @@ -1859,6 +1873,8 @@ do -- AI_A2G_DISPATCHER Bai.Name = SquadronName Bai.EngageMinSpeed = EngageMinSpeed Bai.EngageMaxSpeed = EngageMaxSpeed + Bai.EngageFloorAltitude = EngageFloorAltitude + Bai.EngageCeilingAltitude = EngageCeilingAltitude Bai.Defend = true self:F( { Bai = Bai } ) @@ -1888,12 +1904,12 @@ do -- AI_A2G_DISPATCHER -- @param #AI_A2G_DISPATCHER self -- @param #string SquadronName The squadron name. -- @param Core.Zone#ZONE_BASE Zone The @{Zone} object derived from @{Core.Zone#ZONE_BASE} that defines the zone wherein the Patrol will be executed. - -- @param #number FloorAltitude The minimum altitude at which the cap can be executed. - -- @param #number CeilingAltitude the maximum altitude at which the cap can be executed. - -- @param #number PatrolMinSpeed The minimum speed at which the cap can be executed. - -- @param #number PatrolMaxSpeed The maximum speed at which the cap can be executed. - -- @param #number EngageMinSpeed The minimum speed at which the engage can be executed. - -- @param #number EngageMaxSpeed The maximum speed at which the engage can be executed. + -- @param #number FloorAltitude (optional, default = 1000m ) The minimum altitude at which the cap can be executed. + -- @param #number CeilingAltitude (optional, default = 1500m ) The maximum altitude at which the cap can be executed. + -- @param #number PatrolMinSpeed (optional, default = 50% of max speed) The minimum speed at which the cap can be executed. + -- @param #number PatrolMaxSpeed (optional, default = 75% of max speed) The maximum speed at which the cap can be executed. + -- @param #number EngageMinSpeed (optional, default = 50% of max speed) The minimum speed at which the engage can be executed. + -- @param #number EngageMaxSpeed (optional, default = 75% of max speed) The maximum speed at which the engage can be executed. -- @param #number AltType The altitude type, which is a string "BARO" defining Barometric or "RADIO" defining radio controlled altitude. -- @return #AI_A2G_DISPATCHER -- @usage @@ -1911,8 +1927,10 @@ do -- AI_A2G_DISPATCHER local BaiPatrol = DefenderSquadron.BAI BaiPatrol.Name = SquadronName BaiPatrol.Zone = Zone - BaiPatrol.FloorAltitude = FloorAltitude - BaiPatrol.CeilingAltitude = CeilingAltitude + BaiPatrol.PatrolFloorAltitude = FloorAltitude + BaiPatrol.PatrolCeilingAltitude = CeilingAltitude + BaiPatrol.EngageFloorAltitude = FloorAltitude + BaiPatrol.EngageCeilingAltitude = CeilingAltitude BaiPatrol.PatrolMinSpeed = PatrolMinSpeed BaiPatrol.PatrolMaxSpeed = PatrolMaxSpeed BaiPatrol.EngageMinSpeed = EngageMinSpeed @@ -2761,7 +2779,7 @@ do -- AI_A2G_DISPATCHER -- Count the total of defenders on the battlefield. --local DefenderSize = Defender:GetInitialSize() if DefenderTask.Target then - if DefenderTask.Fsm:Is( "Engaging" ) then + --if DefenderTask.Fsm:Is( "Engaging" ) then self:F( "Defender Group Name: " .. Defender:GetName() .. ", Size: " .. DefenderSize ) DefendersTotal = DefendersTotal + DefenderSize if DefenderTaskTarget and DefenderTaskTarget.Index == AttackerDetection.Index then @@ -2775,7 +2793,7 @@ do -- AI_A2G_DISPATCHER DefendersEngaged = 0 end end - end + --end end @@ -2923,7 +2941,7 @@ do -- AI_A2G_DISPATCHER local AI_A2G_PATROL = { SEAD = AI_A2G_SEAD, BAI = AI_A2G_BAI, CAS = AI_A2G_CAS } - local Fsm = AI_A2G_PATROL[DefenseTaskType]:New( DefenderPatrol, Patrol.EngageMinSpeed, Patrol.EngageMaxSpeed, Patrol.Zone, Patrol.FloorAltitude, Patrol.CeilingAltitude, Patrol.PatrolMinSpeed, Patrol.PatrolMaxSpeed, Patrol.AltType ) + local Fsm = AI_A2G_PATROL[DefenseTaskType]:New( DefenderPatrol, Patrol.EngageMinSpeed, Patrol.EngageMaxSpeed, Patrol.EngageFloorAltitude, Patrol.EngageCeilingAltitude, Patrol.Zone, Patrol.PatrolFloorAltitude, Patrol.PatrolCeilingAltitude, Patrol.PatrolMinSpeed, Patrol.PatrolMaxSpeed, Patrol.AltType ) Fsm:SetDispatcher( self ) Fsm:SetHomeAirbase( DefenderSquadron.Airbase ) Fsm:SetFuelThreshold( DefenderSquadron.FuelThreshold or self.DefenderDefault.FuelThreshold, 60 ) @@ -3115,7 +3133,7 @@ do -- AI_A2G_DISPATCHER local AI_A2G_ENGAGE = { SEAD = AI_A2G_SEAD, BAI = AI_A2G_BAI, CAS = AI_A2G_CAS } - local Fsm = AI_A2G_ENGAGE[DefenseTaskType]:New( DefenderGroup, Defense.EngageMinSpeed, Defense.EngageMaxSpeed ) -- AI.AI_A2G_ENGAGE + local Fsm = AI_A2G_ENGAGE[DefenseTaskType]:New( DefenderGroup, Defense.EngageMinSpeed, Defense.EngageMaxSpeed, Defense.EngageFloorAltitude, Defense.EngageCeilingAltitude ) -- AI.AI_A2G_ENGAGE Fsm:SetDispatcher( self ) Fsm:SetHomeAirbase( DefenderSquadron.Airbase ) Fsm:SetFuelThreshold( DefenderSquadron.FuelThreshold or self.DefenderDefault.FuelThreshold, 60 ) diff --git a/Moose Development/Moose/AI/AI_A2G_Engage.lua b/Moose Development/Moose/AI/AI_A2G_Engage.lua index 7c09d1b56..e6be845c3 100644 --- a/Moose Development/Moose/AI/AI_A2G_Engage.lua +++ b/Moose Development/Moose/AI/AI_A2G_Engage.lua @@ -81,8 +81,12 @@ AI_A2G_ENGAGE = { --- Creates a new AI_A2G_ENGAGE object -- @param #AI_A2G_ENGAGE self -- @param Wrapper.Group#GROUP AIGroup +-- @param DCS#Speed EngageMinSpeed (optional, default = 50% of max speed) The minimum speed of the @{Wrapper.Group} in km/h when engaging a target. +-- @param DCS#Speed EngageMaxSpeed (optional, default = 75% of max speed) The maximum speed of the @{Wrapper.Group} in km/h when engaging a target. +-- @param DCS#Altitude EngageFloorAltitude (optional, default = 1000m ) The lowest altitude in meters where to execute the engagement. +-- @param DCS#Altitude EngageCeilingAltitude (optional, default = 1500m ) The highest altitude in meters where to execute the engagement. -- @return #AI_A2G_ENGAGE -function AI_A2G_ENGAGE:New( AIGroup, EngageMinSpeed, EngageMaxSpeed ) +function AI_A2G_ENGAGE:New( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude ) -- Inherits from BASE local self = BASE:Inherit( self, AI_A2G:New( AIGroup ) ) -- #AI_A2G_ENGAGE @@ -90,12 +94,12 @@ function AI_A2G_ENGAGE:New( AIGroup, EngageMinSpeed, EngageMaxSpeed ) self.Accomplished = false self.Engaging = false - self.EngageMinSpeed = EngageMinSpeed - self.EngageMaxSpeed = EngageMaxSpeed - self.PatrolMinSpeed = EngageMinSpeed - self.PatrolMaxSpeed = EngageMaxSpeed + local SpeedMax = AIGroup:GetSpeedMax() - self.PatrolAltType = "RADIO" + self.EngageMinSpeed = EngageMinSpeed or SpeedMax * 0.5 + self.EngageMaxSpeed = EngageMaxSpeed or SpeedMax * 0.75 + self.EngageFloorAltitude = EngageFloorAltitude or 1000 + self.EngageCeilingAltitude = EngageCeilingAltitude or 1500 self:AddTransition( { "Started", "Engaging", "Returning", "Airborne", "Patrolling" }, "Engage", "Engaging" ) -- FSM_CONTROLLABLE Transition for type #AI_A2G_ENGAGE. diff --git a/Moose Development/Moose/AI/AI_A2G_Patrol.lua b/Moose Development/Moose/AI/AI_A2G_Patrol.lua index 185c4a02c..dd9e0342a 100644 --- a/Moose Development/Moose/AI/AI_A2G_Patrol.lua +++ b/Moose Development/Moose/AI/AI_A2G_Patrol.lua @@ -99,26 +99,31 @@ AI_A2G_PATROL = { --- Creates a new AI_A2G_PATROL object -- @param #AI_A2G_PATROL self --- @param Wrapper.Group#GROUP AIPatrol --- @param DCS#Speed EngageMinSpeed The minimum speed of the @{Wrapper.Group} in km/h when engaging a target. --- @param DCS#Speed EngageMaxSpeed The maximum speed of the @{Wrapper.Group} in km/h when engaging a target. +-- @param Wrapper.Group#GROUP AIGroup +-- @param DCS#Speed EngageMinSpeed (optional, default = 50% of max speed) The minimum speed of the @{Wrapper.Group} in km/h when engaging a target. +-- @param DCS#Speed EngageMaxSpeed (optional, default = 75% of max speed) The maximum speed of the @{Wrapper.Group} in km/h when engaging a target. +-- @param DCS#Altitude EngageFloorAltitude (optional, default = 1000m ) The lowest altitude in meters where to execute the engagement. +-- @param DCS#Altitude EngageCeilingAltitude (optional, default = 1500m ) The highest altitude in meters where to execute the engagement. -- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed. --- @param DCS#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol. --- @param DCS#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol. --- @param DCS#Speed PatrolMinSpeed The minimum speed of the @{Wrapper.Group} in km/h. --- @param DCS#Speed PatrolMaxSpeed The maximum speed of the @{Wrapper.Group} in km/h. --- @param DCS#AltitudeType PatrolAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to RADIO +-- @param DCS#Altitude PatrolFloorAltitude (optional, default = 1000m ) The lowest altitude in meters where to execute the patrol. +-- @param DCS#Altitude PatrolCeilingAltitude (optional, default = 1500m ) The highest altitude in meters where to execute the patrol. +-- @param DCS#Speed PatrolMinSpeed (optional, default = 50% of max speed) The minimum speed of the @{Wrapper.Group} in km/h. +-- @param DCS#Speed PatrolMaxSpeed (optional, default = 75% of max speed) The maximum speed of the @{Wrapper.Group} in km/h. +-- @param DCS#AltitudeType PatrolAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to RADIO. -- @return #AI_A2G_PATROL -function AI_A2G_PATROL:New( AIPatrol, EngageMinSpeed, EngageMaxSpeed, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType ) +function AI_A2G_PATROL:New( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType ) -- Inherits from BASE - local self = BASE:Inherit( self, AI_A2G_ENGAGE:New( AIPatrol, EngageMinSpeed, EngageMaxSpeed ) ) -- #AI_A2G_PATROL + local self = BASE:Inherit( self, AI_A2G_ENGAGE:New( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude ) ) -- #AI_A2G_PATROL + local SpeedMax = AIGroup:GetSpeedMax() + self.PatrolZone = PatrolZone - self.PatrolFloorAltitude = PatrolFloorAltitude - self.PatrolCeilingAltitude = PatrolCeilingAltitude - self.PatrolMinSpeed = PatrolMinSpeed - self.PatrolMaxSpeed = PatrolMaxSpeed + + self.PatrolFloorAltitude = PatrolFloorAltitude or 1000 + self.PatrolCeilingAltitude = PatrolCeilingAltitude or 1500 + self.PatrolMinSpeed = PatrolMinSpeed or SpeedMax * 0.5 + self.PatrolMaxSpeed = PatrolMaxSpeed or SpeedMax * 0.75 -- defafult PatrolAltType to "RADIO" if not specified self.PatrolAltType = PatrolAltType or "RADIO" diff --git a/Moose Development/Moose/AI/AI_A2G_SEAD.lua b/Moose Development/Moose/AI/AI_A2G_SEAD.lua index dfaf89b34..2da77818a 100644 --- a/Moose Development/Moose/AI/AI_A2G_SEAD.lua +++ b/Moose Development/Moose/AI/AI_A2G_SEAD.lua @@ -14,7 +14,7 @@ --- @type AI_A2G_SEAD --- @extends AI.AI_A2G_Engage#AI_A2G_Engage +-- @extends AI.AI_A2G_Patrol#AI_A2G_PATROL --- Implements the core functions to SEAD intruders. Use the Engage trigger to intercept intruders. @@ -83,6 +83,8 @@ AI_A2G_SEAD = { -- @param Wrapper.Group#GROUP AIGroup -- @param DCS#Speed EngageMinSpeed The minimum speed of the @{Wrapper.Group} in km/h when engaging a target. -- @param DCS#Speed EngageMaxSpeed The maximum speed of the @{Wrapper.Group} in km/h when engaging a target. +-- @param DCS#Altitude EngageFloorAltitude The lowest altitude in meters where to execute the engagement. +-- @param DCS#Altitude EngageCeilingAltitude The highest altitude in meters where to execute the engagement. -- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed. -- @param DCS#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol. -- @param DCS#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol. @@ -90,10 +92,10 @@ AI_A2G_SEAD = { -- @param DCS#Speed PatrolMaxSpeed The maximum speed of the @{Wrapper.Group} in km/h. -- @param DCS#AltitudeType PatrolAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to RADIO -- @return #AI_A2G_SEAD -function AI_A2G_SEAD:New( AIGroup, EngageMinSpeed, EngageMaxSpeed, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType ) +function AI_A2G_SEAD:New( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType ) -- Inherits from BASE - local self = BASE:Inherit( self, AI_A2G_PATROL:New( AIGroup, EngageMinSpeed, EngageMaxSpeed, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType ) ) -- #AI_A2G_SEAD + local self = BASE:Inherit( self, AI_A2G_PATROL:New( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType ) ) -- #AI_A2G_SEAD return self end @@ -123,8 +125,11 @@ function AI_A2G_SEAD:onafterEngage( DefenderGroup, From, Event, To, AttackSetUni -- If it is less than 50km, then attack without a route. -- Otherwise perform a route attack. - local DefenderCoord = DefenderGroup:GetCoordinate() - local TargetCoord = self.AttackSetUnit:GetFirst():GetCoordinate() + local DefenderCoord = DefenderGroup:GetPointVec3() + DefenderCoord:SetY( math.random( self.EngageFloorAltitude, self.EngageCeilingAltitude ) ) -- Ground targets don't have an altitude. + + local TargetCoord = self.AttackSetUnit:GetFirst():GetPointVec3() + TargetCoord:SetY( math.random( self.EngageFloorAltitude, self.EngageCeilingAltitude ) ) -- Ground targets don't have an altitude. local TargetDistance = DefenderCoord:Get2DDistance( TargetCoord ) @@ -137,7 +142,7 @@ function AI_A2G_SEAD:onafterEngage( DefenderGroup, From, Event, To, AttackSetUni --- Calculate the target route point. local FromWP = DefenderCoord:WaypointAir( - self.PatrolAltType, + self.PatrolAltType or "RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, ToTargetSpeed, @@ -153,7 +158,7 @@ function AI_A2G_SEAD:onafterEngage( DefenderGroup, From, Event, To, AttackSetUni --- Create a route point of type air, 50km from the center of the attack point. local ToWP = ToCoord:Translate( 50000, FromEngageAngle ):WaypointAir( - self.PatrolAltType, + self.PatrolAltType or "RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, ToTargetSpeed, diff --git a/Moose Development/Moose/AI/AI_Air.lua b/Moose Development/Moose/AI/AI_Air.lua index 3c808beaa..bbfadc5a0 100644 --- a/Moose Development/Moose/AI/AI_Air.lua +++ b/Moose Development/Moose/AI/AI_Air.lua @@ -298,6 +298,19 @@ function AI_AIR:SetSpeed( PatrolMinSpeed, PatrolMaxSpeed ) end +--- Sets (modifies) the minimum and maximum RTB speed of the patrol. +-- @param #AI_AIR self +-- @param DCS#Speed RTBMinSpeed The minimum speed of the @{Wrapper.Controllable} in km/h. +-- @param DCS#Speed RTBMaxSpeed The maximum speed of the @{Wrapper.Controllable} in km/h. +-- @return #AI_AIR self +function AI_AIR:SetRTBSpeed( RTBMinSpeed, RTBMaxSpeed ) + self:F2( { RTBMinSpeed, RTBMaxSpeed } ) + + self.RTBMinSpeed = RTBMinSpeed + self.RTBMaxSpeed = RTBMaxSpeed +end + + --- Sets the floor and ceiling altitude of the patrol. -- @param #AI_AIR self -- @param DCS#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol. @@ -511,7 +524,7 @@ function AI_AIR:onafterStatus() end if not self:Is("Home") then - self:__Status( 30 ) + self:__Status( 10 ) end end @@ -562,7 +575,7 @@ function AI_AIR:onafterRTB( AIGroup, From, Event, To ) local CurrentCoord = AIGroup:GetCoordinate() local ToTargetCoord = self.HomeAirbase:GetCoordinate() - local ToTargetSpeed = math.random( self.PatrolMinSpeed, self.PatrolMaxSpeed ) + local ToTargetSpeed = math.random( self.RTBMinSpeed, self.RTBMaxSpeed ) local ToAirbaseAngle = CurrentCoord:GetAngleDegrees( CurrentCoord:GetDirectionVec3( ToTargetCoord ) ) local Distance = CurrentCoord:Get2DDistance( ToTargetCoord ) @@ -582,9 +595,6 @@ function AI_AIR:onafterRTB( AIGroup, From, Event, To ) true ) - self:F( { Angle = ToAirbaseAngle, ToTargetSpeed = ToTargetSpeed } ) - self:T2( { self.MinSpeed, self.MaxSpeed, ToTargetSpeed } ) - EngageRoute[#EngageRoute+1] = ToRTBRoutePoint EngageRoute[#EngageRoute+1] = ToRTBRoutePoint From ea93e3863be818413498c841dbc588967afc5192 Mon Sep 17 00:00:00 2001 From: FlightControl Date: Wed, 26 Dec 2018 07:42:47 +0100 Subject: [PATCH 09/14] Loader --- Moose Setup/Moose_Create.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Moose Setup/Moose_Create.lua b/Moose Setup/Moose_Create.lua index b076b8d87..69979ba86 100644 --- a/Moose Setup/Moose_Create.lua +++ b/Moose Setup/Moose_Create.lua @@ -14,7 +14,7 @@ print( "Moose target path : " .. MooseTargetPath ) local MooseSourcesFilePath = MooseSetupPath .. "/Moose.files" local LoaderFilePath = MooseTargetPath.."/Moose.lua" -local MooseFilePath = MooseTargetPath .. "/Loader.lua" +local MooseFilePath = MooseTargetPath .. "/Modules.lua" print( "Reading Moose source list : " .. MooseSourcesFilePath ) @@ -39,7 +39,7 @@ local MooseLoaderText = MooseLoader:read( "*a" ) MooseLoader:close() LoaderFile:write( MooseLoaderText ) -LoaderFile:write( "__Moose.Include( 'Scripts/Moose/Moose.lua'\n" ) +LoaderFile:write( "__Moose.Include( 'Scripts/Moose/Modules.lua' ) \n" ) local MooseSourcesFile = io.open( MooseSourcesFilePath, "r" ) local MooseSource = MooseSourcesFile:read("*l") From 610938b6e89ba82023fbf7a5eb7b684e1a7890b9 Mon Sep 17 00:00:00 2001 From: FlightControl Date: Wed, 26 Dec 2018 09:06:16 +0100 Subject: [PATCH 10/14] Changes --- Moose Development/Moose/Modules.lua | 75 +++++++++++++++++++++++++ Moose Development/Moose/Moose.lua | 23 ++++++++ Moose Setup/Eclipse/Moose Loader.launch | 6 ++ 3 files changed, 104 insertions(+) create mode 100644 Moose Development/Moose/Modules.lua create mode 100644 Moose Development/Moose/Moose.lua create mode 100644 Moose Setup/Eclipse/Moose Loader.launch diff --git a/Moose Development/Moose/Modules.lua b/Moose Development/Moose/Modules.lua new file mode 100644 index 000000000..75f82b6a3 --- /dev/null +++ b/Moose Development/Moose/Modules.lua @@ -0,0 +1,75 @@ +__Moose.Include( 'Scripts/Moose/Utilities/Routines.lua' ) +__Moose.Include( 'Scripts/Moose/Utilities/Utils.lua' ) +__Moose.Include( 'Scripts/Moose/Core/Base.lua' ) +__Moose.Include( 'Scripts/Moose/Core/UserFlag.lua' ) +__Moose.Include( 'Scripts/Moose/Core/UserSound.lua' ) +__Moose.Include( 'Scripts/Moose/Core/Report.lua' ) +__Moose.Include( 'Scripts/Moose/Core/Scheduler.lua' ) +__Moose.Include( 'Scripts/Moose/Core/ScheduleDispatcher.lua' ) +__Moose.Include( 'Scripts/Moose/Core/Event.lua' ) +__Moose.Include( 'Scripts/Moose/Core/Settings.lua' ) +__Moose.Include( 'Scripts/Moose/Core/Menu.lua' ) +__Moose.Include( 'Scripts/Moose/Core/Zone.lua' ) +__Moose.Include( 'Scripts/Moose/Core/Database.lua' ) +__Moose.Include( 'Scripts/Moose/Core/Set.lua' ) +__Moose.Include( 'Scripts/Moose/Core/Point.lua' ) +__Moose.Include( 'Scripts/Moose/Core/Velocity.lua' ) +__Moose.Include( 'Scripts/Moose/Core/Message.lua' ) +__Moose.Include( 'Scripts/Moose/Core/Fsm.lua' ) +__Moose.Include( 'Scripts/Moose/Core/Radio.lua' ) +__Moose.Include( 'Scripts/Moose/Core/Spawn.lua' ) +__Moose.Include( 'Scripts/Moose/Core/SpawnStatic.lua' ) +__Moose.Include( 'Scripts/Moose/Core/Goal.lua' ) +__Moose.Include( 'Scripts/Moose/Core/Cargo.lua' ) +__Moose.Include( 'Scripts/Moose/Core/Spot.lua' ) +__Moose.Include( 'Scripts/Moose/Wrapper/Object.lua' ) +__Moose.Include( 'Scripts/Moose/Wrapper/Identifiable.lua' ) +__Moose.Include( 'Scripts/Moose/Wrapper/Positionable.lua' ) +__Moose.Include( 'Scripts/Moose/Wrapper/Controllable.lua' ) +__Moose.Include( 'Scripts/Moose/Wrapper/Group.lua' ) +__Moose.Include( 'Scripts/Moose/Wrapper/Unit.lua' ) +__Moose.Include( 'Scripts/Moose/Wrapper/Client.lua' ) +__Moose.Include( 'Scripts/Moose/Wrapper/Static.lua' ) +__Moose.Include( 'Scripts/Moose/Wrapper/Airbase.lua' ) +__Moose.Include( 'Scripts/Moose/Wrapper/Scenery.lua' ) +__Moose.Include( 'Scripts/Moose/Functional/Scoring.lua' ) +__Moose.Include( 'Scripts/Moose/Functional/CleanUp.lua' ) +__Moose.Include( 'Scripts/Moose/Functional/Movement.lua' ) +__Moose.Include( 'Scripts/Moose/Functional/Sead.lua' ) +__Moose.Include( 'Scripts/Moose/Functional/Escort.lua' ) +__Moose.Include( 'Scripts/Moose/Functional/MissileTrainer.lua' ) +__Moose.Include( 'Scripts/Moose/Functional/ATC_Ground.lua' ) +__Moose.Include( 'Scripts/Moose/Functional/Detection.lua' ) +__Moose.Include( 'Scripts/Moose/Functional/Designate.lua' ) +__Moose.Include( 'Scripts/Moose/Functional/RAT.lua' ) +__Moose.Include( 'Scripts/Moose/Functional/Range.lua' ) +__Moose.Include( 'Scripts/Moose/Functional/ZoneGoal.lua' ) +__Moose.Include( 'Scripts/Moose/Functional/ZoneGoalCoalition.lua' ) +__Moose.Include( 'Scripts/Moose/Functional/ZoneCaptureCoalition.lua' ) +__Moose.Include( 'Scripts/Moose/AI/AI_Balancer.lua' ) +__Moose.Include( 'Scripts/Moose/AI/AI_A2A.lua' ) +__Moose.Include( 'Scripts/Moose/AI/AI_A2A_Patrol.lua' ) +__Moose.Include( 'Scripts/Moose/AI/AI_A2A_Cap.lua' ) +__Moose.Include( 'Scripts/Moose/AI/AI_A2A_Gci.lua' ) +__Moose.Include( 'Scripts/Moose/AI/AI_A2A_Dispatcher.lua' ) +__Moose.Include( 'Scripts/Moose/AI/AI_Patrol.lua' ) +__Moose.Include( 'Scripts/Moose/AI/AI_Cap.lua' ) +__Moose.Include( 'Scripts/Moose/AI/AI_Cas.lua' ) +__Moose.Include( 'Scripts/Moose/AI/AI_Bai.lua' ) +__Moose.Include( 'Scripts/Moose/AI/AI_Formation.lua' ) +__Moose.Include( 'Scripts/Moose/Actions/Act_Assign.lua' ) +__Moose.Include( 'Scripts/Moose/Actions/Act_Route.lua' ) +__Moose.Include( 'Scripts/Moose/Actions/Act_Account.lua' ) +__Moose.Include( 'Scripts/Moose/Actions/Act_Assist.lua' ) +__Moose.Include( 'Scripts/Moose/Tasking/CommandCenter.lua' ) +__Moose.Include( 'Scripts/Moose/Tasking/Mission.lua' ) +__Moose.Include( 'Scripts/Moose/Tasking/Task.lua' ) +__Moose.Include( 'Scripts/Moose/Tasking/TaskInfo.lua' ) +__Moose.Include( 'Scripts/Moose/Tasking/DetectionManager.lua' ) +__Moose.Include( 'Scripts/Moose/Tasking/Task_A2G_Dispatcher.lua' ) +__Moose.Include( 'Scripts/Moose/Tasking/Task_A2G.lua' ) +__Moose.Include( 'Scripts/Moose/Tasking/Task_A2A_Dispatcher.lua' ) +__Moose.Include( 'Scripts/Moose/Tasking/Task_A2A.lua' ) +__Moose.Include( 'Scripts/Moose/Tasking/Task_Cargo.lua' ) +__Moose.Include( 'Scripts/Moose/Tasking/TaskZoneCapture.lua' ) +__Moose.Include( 'Scripts/Moose/Globals.lua' ) diff --git a/Moose Development/Moose/Moose.lua b/Moose Development/Moose/Moose.lua new file mode 100644 index 000000000..156f8143d --- /dev/null +++ b/Moose Development/Moose/Moose.lua @@ -0,0 +1,23 @@ +env.info( '*** MOOSE DYNAMIC INCLUDE START *** ' ) + +local base = _G + +__Moose = {} + +__Moose.Include = function( IncludeFile ) + if not __Moose.Includes[ IncludeFile ] then + __Moose.Includes[IncludeFile] = IncludeFile + local f = assert( base.loadfile( IncludeFile ) ) + if f == nil then + error ("Moose: Could not load Moose file " .. IncludeFile ) + else + env.info( "Moose: " .. IncludeFile .. " dynamically loaded." ) + return f() + end + end +end + +__Moose.Includes = {} +__Moose.Include( 'Scripts/Moose/Modules.lua' ) +BASE:TraceOnOff( true ) +env.info( '*** MOOSE INCLUDE END *** ' ) diff --git a/Moose Setup/Eclipse/Moose Loader.launch b/Moose Setup/Eclipse/Moose Loader.launch new file mode 100644 index 000000000..006a2ce77 --- /dev/null +++ b/Moose Setup/Eclipse/Moose Loader.launch @@ -0,0 +1,6 @@ + + + + + + From 32c064a1bef346d4ff654eaea2de3ddac6579da1 Mon Sep 17 00:00:00 2001 From: FlightControl Date: Wed, 26 Dec 2018 09:10:03 +0100 Subject: [PATCH 11/14] Remove Moose.lua --- Moose Development/Moose/Moose.lua | 23 ----------------------- 1 file changed, 23 deletions(-) delete mode 100644 Moose Development/Moose/Moose.lua diff --git a/Moose Development/Moose/Moose.lua b/Moose Development/Moose/Moose.lua deleted file mode 100644 index 156f8143d..000000000 --- a/Moose Development/Moose/Moose.lua +++ /dev/null @@ -1,23 +0,0 @@ -env.info( '*** MOOSE DYNAMIC INCLUDE START *** ' ) - -local base = _G - -__Moose = {} - -__Moose.Include = function( IncludeFile ) - if not __Moose.Includes[ IncludeFile ] then - __Moose.Includes[IncludeFile] = IncludeFile - local f = assert( base.loadfile( IncludeFile ) ) - if f == nil then - error ("Moose: Could not load Moose file " .. IncludeFile ) - else - env.info( "Moose: " .. IncludeFile .. " dynamically loaded." ) - return f() - end - end -end - -__Moose.Includes = {} -__Moose.Include( 'Scripts/Moose/Modules.lua' ) -BASE:TraceOnOff( true ) -env.info( '*** MOOSE INCLUDE END *** ' ) From 5e01db88097593caa95f2e290968f98afd970d8c Mon Sep 17 00:00:00 2001 From: FlightControl Date: Thu, 27 Dec 2018 07:33:51 +0100 Subject: [PATCH 12/14] New stuff --- ...der.launch => Moose Loader Dynamic.launch} | 2 +- .../Eclipse/Moose Loader Static.launch | 6 +++++ .../Moose Templates/Moose_Dynamic_Loader.lua | 2 ++ Moose Setup/Moose.lua | 22 +++++++++++++++++++ Moose Setup/Moose_Create.lua | 22 ++++++++----------- 5 files changed, 40 insertions(+), 14 deletions(-) rename Moose Setup/Eclipse/{Moose Loader.launch => Moose Loader Dynamic.launch} (91%) create mode 100644 Moose Setup/Eclipse/Moose Loader Static.launch create mode 100644 Moose Setup/Moose.lua diff --git a/Moose Setup/Eclipse/Moose Loader.launch b/Moose Setup/Eclipse/Moose Loader Dynamic.launch similarity index 91% rename from Moose Setup/Eclipse/Moose Loader.launch rename to Moose Setup/Eclipse/Moose Loader Dynamic.launch index 006a2ce77..60d840ca2 100644 --- a/Moose Setup/Eclipse/Moose Loader.launch +++ b/Moose Setup/Eclipse/Moose Loader Dynamic.launch @@ -1,6 +1,6 @@ - + diff --git a/Moose Setup/Eclipse/Moose Loader Static.launch b/Moose Setup/Eclipse/Moose Loader Static.launch new file mode 100644 index 000000000..20723f471 --- /dev/null +++ b/Moose Setup/Eclipse/Moose Loader Static.launch @@ -0,0 +1,6 @@ + + + + + + diff --git a/Moose Setup/Moose Templates/Moose_Dynamic_Loader.lua b/Moose Setup/Moose Templates/Moose_Dynamic_Loader.lua index 24ba37689..d63555297 100644 --- a/Moose Setup/Moose Templates/Moose_Dynamic_Loader.lua +++ b/Moose Setup/Moose Templates/Moose_Dynamic_Loader.lua @@ -18,3 +18,5 @@ __Moose.Include = function( IncludeFile ) end __Moose.Includes = {} + +__Moose.Include( 'Scripts/Moose/Modules.lua' ) diff --git a/Moose Setup/Moose.lua b/Moose Setup/Moose.lua new file mode 100644 index 000000000..0ecf84e0f --- /dev/null +++ b/Moose Setup/Moose.lua @@ -0,0 +1,22 @@ +env.info( '*** MOOSE DYNAMIC INCLUDE START *** ' ) + +local base = _G + +__Moose = {} + +__Moose.Include = function( IncludeFile ) + if not __Moose.Includes[ IncludeFile ] then + __Moose.Includes[IncludeFile] = IncludeFile + local f = assert( base.loadfile( IncludeFile ) ) + if f == nil then + error ("Moose: Could not load Moose file " .. IncludeFile ) + else + env.info( "Moose: " .. IncludeFile .. " dynamically loaded." ) + return f() + end + end +end + +__Moose.Includes = {} + +__Moose.Include( "Modules.lua" ) diff --git a/Moose Setup/Moose_Create.lua b/Moose Setup/Moose_Create.lua index 69979ba86..1b5d6a201 100644 --- a/Moose Setup/Moose_Create.lua +++ b/Moose Setup/Moose_Create.lua @@ -10,13 +10,11 @@ print( "Moose (D)ynamic (S)tatic : " .. MooseDynamicStatic ) print( "Commit Hash ID : " .. MooseCommitHash ) print( "Moose development path : " .. MooseDevelopmentPath ) print( "Moose setup path : " .. MooseSetupPath ) -print( "Moose target path : " .. MooseTargetPath ) -local MooseSourcesFilePath = MooseSetupPath .. "/Moose.files" -local LoaderFilePath = MooseTargetPath.."/Moose.lua" -local MooseFilePath = MooseTargetPath .. "/Modules.lua" +local MooseModulesFilePath = MooseDevelopmentPath .. "/Modules.lua" +local LoaderFilePath = MooseSetupPath .. "/Moose.lua" -print( "Reading Moose source list : " .. MooseSourcesFilePath ) +print( "Reading Moose source list : " .. MooseModulesFilePath ) local LoaderFile = io.open( LoaderFilePath, "w" ) @@ -32,28 +30,26 @@ if MooseDynamicStatic == "S" then MooseLoaderPath = MooseSetupPath .. "/Moose Templates/Moose_Static_Loader.lua" end -local MooseFile = io.open( MooseFilePath, "w" ) - local MooseLoader = io.open( MooseLoaderPath, "r" ) local MooseLoaderText = MooseLoader:read( "*a" ) MooseLoader:close() LoaderFile:write( MooseLoaderText ) -LoaderFile:write( "__Moose.Include( 'Scripts/Moose/Modules.lua' ) \n" ) -local MooseSourcesFile = io.open( MooseSourcesFilePath, "r" ) +local MooseSourcesFile = io.open( MooseModulesFilePath, "r" ) local MooseSource = MooseSourcesFile:read("*l") +_, _, MooseSource = string.find( MooseSource, "Scripts/Moose/(.+)'" ) + while( MooseSource ) do if MooseSource ~= "" then local MooseFilePath = MooseDevelopmentPath .. "/" .. MooseSource if MooseDynamicStatic == "D" then - print( "Load dynamic: " .. MooseSource ) - MooseFile:write( "__Moose.Include( 'Scripts/Moose/" .. MooseSource .. "' )\n" ) + print( "Load dynamic: " .. MooseFilePath ) end if MooseDynamicStatic == "S" then - print( "Load static: " .. MooseSource ) + print( "Load static: " .. MooseFilePath ) local MooseSourceFile = io.open( MooseFilePath, "r" ) local MooseSourceFileText = MooseSourceFile:read( "*a" ) MooseSourceFile:close() @@ -63,6 +59,7 @@ while( MooseSource ) do end MooseSource = MooseSourcesFile:read("*l") + _, _, MooseSource = string.find( MooseSource, "Scripts/Moose/(.+)'" ) end if MooseDynamicStatic == "D" then @@ -76,4 +73,3 @@ LoaderFile:write( "env.info( '*** MOOSE INCLUDE END *** ' )\n" ) MooseSourcesFile:close() LoaderFile:close() -MooseFile:close() From df6a10862e7a6c8224f3372d60d53aa6619718e7 Mon Sep 17 00:00:00 2001 From: FlightControl Date: Fri, 28 Dec 2018 09:29:33 +0100 Subject: [PATCH 13/14] New dynamic loader and adapted Moose.lua creation from Modules.lua in the MOOSE root directory. --- Moose Development/Moose/Modules.lua | 42 ++++++++++++++++++- .../Eclipse/Moose Loader Dynamic.launch | 2 +- Moose Setup/Moose.lua | 22 ---------- Moose Setup/Moose_Create.lua | 3 +- 4 files changed, 44 insertions(+), 25 deletions(-) delete mode 100644 Moose Setup/Moose.lua diff --git a/Moose Development/Moose/Modules.lua b/Moose Development/Moose/Modules.lua index 75f82b6a3..d0614bbfe 100644 --- a/Moose Development/Moose/Modules.lua +++ b/Moose Development/Moose/Modules.lua @@ -1,5 +1,6 @@ __Moose.Include( 'Scripts/Moose/Utilities/Routines.lua' ) __Moose.Include( 'Scripts/Moose/Utilities/Utils.lua' ) + __Moose.Include( 'Scripts/Moose/Core/Base.lua' ) __Moose.Include( 'Scripts/Moose/Core/UserFlag.lua' ) __Moose.Include( 'Scripts/Moose/Core/UserSound.lua' ) @@ -20,8 +21,8 @@ __Moose.Include( 'Scripts/Moose/Core/Radio.lua' ) __Moose.Include( 'Scripts/Moose/Core/Spawn.lua' ) __Moose.Include( 'Scripts/Moose/Core/SpawnStatic.lua' ) __Moose.Include( 'Scripts/Moose/Core/Goal.lua' ) -__Moose.Include( 'Scripts/Moose/Core/Cargo.lua' ) __Moose.Include( 'Scripts/Moose/Core/Spot.lua' ) + __Moose.Include( 'Scripts/Moose/Wrapper/Object.lua' ) __Moose.Include( 'Scripts/Moose/Wrapper/Identifiable.lua' ) __Moose.Include( 'Scripts/Moose/Wrapper/Positionable.lua' ) @@ -32,6 +33,13 @@ __Moose.Include( 'Scripts/Moose/Wrapper/Client.lua' ) __Moose.Include( 'Scripts/Moose/Wrapper/Static.lua' ) __Moose.Include( 'Scripts/Moose/Wrapper/Airbase.lua' ) __Moose.Include( 'Scripts/Moose/Wrapper/Scenery.lua' ) + +__Moose.Include( 'Scripts/Moose/Cargo/Cargo.lua' ) +__Moose.Include( 'Scripts/Moose/Cargo/CargoUnit.lua' ) +__Moose.Include( 'Scripts/Moose/Cargo/CargoSlingload.lua' ) +__Moose.Include( 'Scripts/Moose/Cargo/CargoCrate.lua' ) +__Moose.Include( 'Scripts/Moose/Cargo/CargoGroup.lua' ) + __Moose.Include( 'Scripts/Moose/Functional/Scoring.lua' ) __Moose.Include( 'Scripts/Moose/Functional/CleanUp.lua' ) __Moose.Include( 'Scripts/Moose/Functional/Movement.lua' ) @@ -46,30 +54,62 @@ __Moose.Include( 'Scripts/Moose/Functional/Range.lua' ) __Moose.Include( 'Scripts/Moose/Functional/ZoneGoal.lua' ) __Moose.Include( 'Scripts/Moose/Functional/ZoneGoalCoalition.lua' ) __Moose.Include( 'Scripts/Moose/Functional/ZoneCaptureCoalition.lua' ) +__Moose.Include( 'Scripts/Moose/Functional/Artillery.lua' ) +__Moose.Include( 'Scripts/Moose/Functional/Suppression.lua' ) +__Moose.Include( 'Scripts/Moose/Functional/PseudoATC.lua' ) +__Moose.Include( 'Scripts/Moose/Functional/Warehouse.lua' ) + +__Moose.Include( 'Scripts/Moose/Ops/Airboss.lua' ) +__Moose.Include( 'Scripts/Moose/Ops/RecoveryTanker.lua' ) +__Moose.Include( 'Scripts/Moose/Ops/RescueHelo.lua' ) + __Moose.Include( 'Scripts/Moose/AI/AI_Balancer.lua' ) +__Moose.Include( 'Scripts/Moose/AI/AI_Air.lua' ) __Moose.Include( 'Scripts/Moose/AI/AI_A2A.lua' ) __Moose.Include( 'Scripts/Moose/AI/AI_A2A_Patrol.lua' ) __Moose.Include( 'Scripts/Moose/AI/AI_A2A_Cap.lua' ) __Moose.Include( 'Scripts/Moose/AI/AI_A2A_Gci.lua' ) __Moose.Include( 'Scripts/Moose/AI/AI_A2A_Dispatcher.lua' ) +__Moose.Include( 'Scripts/Moose/AI/AI_A2G.lua' ) +__Moose.Include( 'Scripts/Moose/AI/AI_A2G_Engage.lua' ) +__Moose.Include( 'Scripts/Moose/AI/AI_A2G_BAI.lua' ) +__Moose.Include( 'Scripts/Moose/AI/AI_A2G_CAS.lua' ) +__Moose.Include( 'Scripts/Moose/AI/AI_A2G_SEAD.lua' ) +__Moose.Include( 'Scripts/Moose/AI/AI_A2G_Patrol.lua' ) +__Moose.Include( 'Scripts/Moose/AI/AI_A2G_Dispatcher.lua' ) __Moose.Include( 'Scripts/Moose/AI/AI_Patrol.lua' ) __Moose.Include( 'Scripts/Moose/AI/AI_Cap.lua' ) __Moose.Include( 'Scripts/Moose/AI/AI_Cas.lua' ) __Moose.Include( 'Scripts/Moose/AI/AI_Bai.lua' ) __Moose.Include( 'Scripts/Moose/AI/AI_Formation.lua' ) +__Moose.Include( 'Scripts/Moose/AI/AI_Cargo.lua' ) +__Moose.Include( 'Scripts/Moose/AI/AI_Cargo_APC.lua' ) +__Moose.Include( 'Scripts/Moose/AI/AI_Cargo_Helicopter.lua' ) +__Moose.Include( 'Scripts/Moose/AI/AI_Cargo_Airplane.lua' ) +__Moose.Include( 'Scripts/Moose/AI/AI_Cargo_Dispatcher.lua' ) +__Moose.Include( 'Scripts/Moose/AI/AI_Cargo_Dispatcher_APC.lua' ) +__Moose.Include( 'Scripts/Moose/AI/AI_Cargo_Dispatcher_Helicopter.lua' ) +__Moose.Include( 'Scripts/Moose/AI/AI_Cargo_Dispatcher_Airplane.lua' ) + __Moose.Include( 'Scripts/Moose/Actions/Act_Assign.lua' ) __Moose.Include( 'Scripts/Moose/Actions/Act_Route.lua' ) __Moose.Include( 'Scripts/Moose/Actions/Act_Account.lua' ) __Moose.Include( 'Scripts/Moose/Actions/Act_Assist.lua' ) + __Moose.Include( 'Scripts/Moose/Tasking/CommandCenter.lua' ) __Moose.Include( 'Scripts/Moose/Tasking/Mission.lua' ) __Moose.Include( 'Scripts/Moose/Tasking/Task.lua' ) __Moose.Include( 'Scripts/Moose/Tasking/TaskInfo.lua' ) +__Moose.Include( 'Scripts/Moose/Tasking/Task_Manager.lua' ) __Moose.Include( 'Scripts/Moose/Tasking/DetectionManager.lua' ) __Moose.Include( 'Scripts/Moose/Tasking/Task_A2G_Dispatcher.lua' ) __Moose.Include( 'Scripts/Moose/Tasking/Task_A2G.lua' ) __Moose.Include( 'Scripts/Moose/Tasking/Task_A2A_Dispatcher.lua' ) __Moose.Include( 'Scripts/Moose/Tasking/Task_A2A.lua' ) __Moose.Include( 'Scripts/Moose/Tasking/Task_Cargo.lua' ) +__Moose.Include( 'Scripts/Moose/Tasking/Task_Cargo_Transport.lua' ) +__Moose.Include( 'Scripts/Moose/Tasking/Task_Cargo_CSAR.lua' ) +__Moose.Include( 'Scripts/Moose/Tasking/Task_Cargo_Dispatcher.lua' ) __Moose.Include( 'Scripts/Moose/Tasking/TaskZoneCapture.lua' ) + __Moose.Include( 'Scripts/Moose/Globals.lua' ) diff --git a/Moose Setup/Eclipse/Moose Loader Dynamic.launch b/Moose Setup/Eclipse/Moose Loader Dynamic.launch index 60d840ca2..5efaf2485 100644 --- a/Moose Setup/Eclipse/Moose Loader Dynamic.launch +++ b/Moose Setup/Eclipse/Moose Loader Dynamic.launch @@ -1,6 +1,6 @@ - + diff --git a/Moose Setup/Moose.lua b/Moose Setup/Moose.lua deleted file mode 100644 index 0ecf84e0f..000000000 --- a/Moose Setup/Moose.lua +++ /dev/null @@ -1,22 +0,0 @@ -env.info( '*** MOOSE DYNAMIC INCLUDE START *** ' ) - -local base = _G - -__Moose = {} - -__Moose.Include = function( IncludeFile ) - if not __Moose.Includes[ IncludeFile ] then - __Moose.Includes[IncludeFile] = IncludeFile - local f = assert( base.loadfile( IncludeFile ) ) - if f == nil then - error ("Moose: Could not load Moose file " .. IncludeFile ) - else - env.info( "Moose: " .. IncludeFile .. " dynamically loaded." ) - return f() - end - end -end - -__Moose.Includes = {} - -__Moose.Include( "Modules.lua" ) diff --git a/Moose Setup/Moose_Create.lua b/Moose Setup/Moose_Create.lua index 1b5d6a201..7d507b269 100644 --- a/Moose Setup/Moose_Create.lua +++ b/Moose Setup/Moose_Create.lua @@ -10,9 +10,10 @@ print( "Moose (D)ynamic (S)tatic : " .. MooseDynamicStatic ) print( "Commit Hash ID : " .. MooseCommitHash ) print( "Moose development path : " .. MooseDevelopmentPath ) print( "Moose setup path : " .. MooseSetupPath ) +print( "Moose target path : " .. MooseTargetPath ) local MooseModulesFilePath = MooseDevelopmentPath .. "/Modules.lua" -local LoaderFilePath = MooseSetupPath .. "/Moose.lua" +local LoaderFilePath = MooseTargetPath .. "/Moose.lua" print( "Reading Moose source list : " .. MooseModulesFilePath ) From bd25a8ccb46666a8748ef309f28961ecb8de591e Mon Sep 17 00:00:00 2001 From: FlightControl Date: Sat, 29 Dec 2018 23:49:52 +0100 Subject: [PATCH 14/14] Fixing too small static Moose.lua --- Moose Setup/Eclipse/Moose Loader Static.launch | 2 +- Moose Setup/Moose_Create.lua | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Moose Setup/Eclipse/Moose Loader Static.launch b/Moose Setup/Eclipse/Moose Loader Static.launch index 20723f471..4ee25e04a 100644 --- a/Moose Setup/Eclipse/Moose Loader Static.launch +++ b/Moose Setup/Eclipse/Moose Loader Static.launch @@ -1,6 +1,6 @@ - + diff --git a/Moose Setup/Moose_Create.lua b/Moose Setup/Moose_Create.lua index 7d507b269..42a3213aa 100644 --- a/Moose Setup/Moose_Create.lua +++ b/Moose Setup/Moose_Create.lua @@ -40,11 +40,10 @@ LoaderFile:write( MooseLoaderText ) local MooseSourcesFile = io.open( MooseModulesFilePath, "r" ) local MooseSource = MooseSourcesFile:read("*l") -_, _, MooseSource = string.find( MooseSource, "Scripts/Moose/(.+)'" ) - while( MooseSource ) do if MooseSource ~= "" then + MooseSource = string.match( MooseSource, "Scripts/Moose/(.+)'" ) local MooseFilePath = MooseDevelopmentPath .. "/" .. MooseSource if MooseDynamicStatic == "D" then print( "Load dynamic: " .. MooseFilePath ) @@ -60,7 +59,6 @@ while( MooseSource ) do end MooseSource = MooseSourcesFile:read("*l") - _, _, MooseSource = string.find( MooseSource, "Scripts/Moose/(.+)'" ) end if MooseDynamicStatic == "D" then