diff --git a/Moose Development/Moose/AI/AI_A2A_Dispatcher.lua b/Moose Development/Moose/AI/AI_A2A_Dispatcher.lua index 26da1d54c..b780591fe 100644 --- a/Moose Development/Moose/AI/AI_A2A_Dispatcher.lua +++ b/Moose Development/Moose/AI/AI_A2A_Dispatcher.lua @@ -3045,8 +3045,7 @@ do -- AI_A2A_DISPATCHER if DefenderTask.Type == "CAP" or DefenderTask.Type == "GCI" then -- If there is no target, then add the AIGroup to the ResultAIGroups for Engagement to the AttackerSet if DefenderTask.Target == nil then - if DefenderTask.Fsm:Is( "Returning" ) - or DefenderTask.Fsm:Is( "Patrolling" ) then + if DefenderTask.Fsm:Is( "Returning" ) or DefenderTask.Fsm:Is( "Patrolling" ) then Friendlies = Friendlies or {} Friendlies[Friendly] = Friendly DefenderCount = DefenderCount + Friendly:GetSize() @@ -3315,19 +3314,20 @@ do -- AI_A2A_DISPATCHER -- @param Functional.Detection#DETECTION_BASE.DetectedItem AttackerDetection Detected item. -- @param #table Defenders Defenders table. function AI_A2A_DISPATCHER:onafterENGAGE( From, Event, To, AttackerDetection, Defenders ) - - self:F("ENGAGING "..tostring(AttackerDetection.Name)) + self:F("ENGAGING Detection ID="..tostring(AttackerDetection.ID)) if Defenders then for DefenderID, Defender in pairs( Defenders ) do local Fsm = self:GetDefenderTaskFsm( Defender ) + Fsm:EngageRoute( AttackerDetection.Set ) -- Engage on the TargetSetUnit - + self:SetDefenderTaskTarget( Defender, AttackerDetection ) end + end end @@ -3341,7 +3341,7 @@ do -- AI_A2A_DISPATCHER -- @param #table DefenderFriendlies Friendly defenders. function AI_A2A_DISPATCHER:onafterGCI( From, Event, To, AttackerDetection, DefendersMissing, DefenderFriendlies ) - self:F("GCI "..tostring(AttackerDetection.Name)) + self:F("GCI Detection ID="..tostring(AttackerDetection.ID)) self:F( { From, Event, To, AttackerDetection.Index, DefendersMissing, DefenderFriendlies } ) @@ -3606,8 +3606,7 @@ do -- AI_A2A_DISPATCHER -- 2. There is sufficient fuel -- 3. There is sufficient ammo -- 4. The plane is not damaged - if DefenderGroups and DetectedItem.IsDetected == true then - + if DefenderGroups and DetectedItem.IsDetected == true then return DefenderGroups end @@ -3686,13 +3685,13 @@ do -- AI_A2A_DISPATCHER local TaskReport = REPORT:New() - local Report = REPORT:New( "Tactical Overviews" ) + local Report = REPORT:New( "Tactical Overview:" ) local DefenderGroupCount = 0 -- Now that all obsolete tasks are removed, loop through the detected targets. --for DetectedItemID, DetectedItem in pairs( Detection:GetDetectedItems() ) do - for DetectedItemID, DetectedItem in UTILS.spairs( Detection:GetDetectedItems(), function( t, a, b ) return self:Order(t[a]) < self:Order(t[b]) end ) do + for DetectedItemID, DetectedItem in UTILS.spairs( Detection:GetDetectedItems(), function( t, a, b ) return self:Order(t[a]) < self:Order(t[b]) end ) do local DetectedItem = DetectedItem -- Functional.Detection#DETECTION_BASE.DetectedItem local DetectedSet = DetectedItem.Set -- Core.Set#SET_UNIT diff --git a/Moose Development/Moose/AI/AI_Air_Engage.lua b/Moose Development/Moose/AI/AI_Air_Engage.lua index bbfd82497..806376f83 100644 --- a/Moose Development/Moose/AI/AI_Air_Engage.lua +++ b/Moose Development/Moose/AI/AI_Air_Engage.lua @@ -334,9 +334,8 @@ end -- @param #string Event The Event string. -- @param #string To The To State string. function AI_AIR_ENGAGE:onafterEngage( AIGroup, From, Event, To ) - + -- TODO: This function is overwritten below! self:HandleEvent( EVENTS.Dead ) - end -- todo: need to fix this global function @@ -349,10 +348,10 @@ end -- @param #string Event The Event string. -- @param #string To The To State string. function AI_AIR_ENGAGE:onbeforeEngage( AIGroup, From, Event, To ) - if self.Accomplished == true then return false - end + end + return true end --- onafter event handler for Abort event. @@ -405,14 +404,10 @@ end --- @param Wrapper.Group#GROUP AIControllable function AI_AIR_ENGAGE.___EngageRoute( AIGroup, Fsm, AttackSetUnit ) - - Fsm:I( { "AI_AIR_ENGAGE.___EngageRoute:", AIGroup:GetName() } ) + Fsm:I(string.format("AI_AIR_ENGAGE.___EngageRoute: %s", tostring(AIGroup:GetName()))) - if AIGroup:IsAlive() then - Fsm:__EngageRoute( Fsm.TaskDelay, AttackSetUnit ) - - --local Task = AIGroup:TaskOrbitCircle( 4000, 400 ) - --AIGroup:SetTask( Task ) + if AIGroup and AIGroup:IsAlive() then + Fsm:__EngageRoute( Fsm.TaskDelay or 0.1, AttackSetUnit ) end end @@ -423,7 +418,6 @@ end -- @param #string Event The Event string. -- @param #string To The To State string. function AI_AIR_ENGAGE:onafterEngageRoute( DefenderGroup, From, Event, To, AttackSetUnit ) - self:I( { DefenderGroup, From, Event, To, AttackSetUnit } ) local DefenderGroupName = DefenderGroup:GetName() @@ -450,39 +444,33 @@ function AI_AIR_ENGAGE:onafterEngageRoute( DefenderGroup, From, Event, To, Attac TargetCoord:SetY( EngageAltitude ) -- Ground targets don't have an altitude. local TargetDistance = DefenderCoord:Get2DDistance( TargetCoord ) - local EngageDistance = ( DefenderGroup:IsHelicopter() and 5000 ) or ( DefenderGroup:IsAirPlane() and 10000 ) + local EngageDistance = ( DefenderGroup:IsHelicopter() and 5000 ) or ( DefenderGroup:IsAirPlane() and 10000 ) - if TargetDistance <= EngageDistance * 3 then + -- TODO: A factor of * 3 is way too close. This causes the AI not to engange until merged sometimes! + if TargetDistance <= EngageDistance * 9 then + self:I(string.format("AI_AIR_ENGAGE onafterEngageRoute ==> __Engage - target distance = %.1f km", TargetDistance/1000)) self:__Engage( 0.1, AttackSetUnit ) else + + self:I(string.format("FF AI_AIR_ENGAGE onafterEngageRoute ==> Routing - target distance = %.1f km", TargetDistance/1000)) local EngageRoute = {} local AttackTasks = {} --- Calculate the target route point. - local FromWP = DefenderCoord:WaypointAir( - self.PatrolAltType or "RADIO", - POINT_VEC3.RoutePointType.TurningPoint, - POINT_VEC3.RoutePointAction.TurningPoint, - EngageSpeed, - true - ) + local FromWP = DefenderCoord:WaypointAir(self.PatrolAltType or "RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, EngageSpeed, true) EngageRoute[#EngageRoute+1] = FromWP self:SetTargetDistance( TargetCoord ) -- For RTB status check local FromEngageAngle = DefenderCoord:GetAngleDegrees( DefenderCoord:GetDirectionVec3( TargetCoord ) ) - local ToWP = DefenderCoord:Translate( EngageDistance, FromEngageAngle, true ):WaypointAir( - self.PatrolAltType or "RADIO", - POINT_VEC3.RoutePointType.TurningPoint, - POINT_VEC3.RoutePointAction.TurningPoint, - EngageSpeed, - true - ) + local ToCoord=DefenderCoord:Translate( EngageDistance, FromEngageAngle, true ) + + local ToWP = ToCoord:WaypointAir(self.PatrolAltType or "RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, EngageSpeed, true) EngageRoute[#EngageRoute+1] = ToWP @@ -492,11 +480,12 @@ function AI_AIR_ENGAGE:onafterEngageRoute( DefenderGroup, From, Event, To, Attac DefenderGroup:OptionROEReturnFire() DefenderGroup:OptionROTEvadeFire() - DefenderGroup:Route( EngageRoute, self.TaskDelay ) + DefenderGroup:Route( EngageRoute, self.TaskDelay or 0.1 ) end end else + -- TODO: This will make an A2A Dispatcher CAP flight to return rather than going back to patrolling! self:I( DefenderGroupName .. ": No targets found -> Going RTB") self:Return() end @@ -506,10 +495,11 @@ end --- @param Wrapper.Group#GROUP AIControllable function AI_AIR_ENGAGE.___Engage( AIGroup, Fsm, AttackSetUnit ) - Fsm:I( { "AI_AIR_ENGAGE.___Engage:", AIGroup:GetName() } ) + Fsm:I(string.format("AI_AIR_ENGAGE.___Engage: %s", tostring(AIGroup:GetName()))) - if AIGroup:IsAlive() then - Fsm:__Engage( Fsm.TaskDelay, AttackSetUnit ) + if AIGroup and AIGroup:IsAlive() then + local delay=Fsm.TaskDelay or 0.1 + Fsm:__Engage(delay, AttackSetUnit) end end @@ -520,7 +510,6 @@ end -- @param #string Event The Event string. -- @param #string To The To State string. function AI_AIR_ENGAGE:onafterEngage( DefenderGroup, From, Event, To, AttackSetUnit ) - self:F( { DefenderGroup, From, Event, To, AttackSetUnit} ) local DefenderGroupName = DefenderGroup:GetName() @@ -532,7 +521,7 @@ function AI_AIR_ENGAGE:onafterEngage( DefenderGroup, From, Event, To, AttackSetU if AttackCount > 0 then - if DefenderGroup:IsAlive() then + if DefenderGroup and DefenderGroup:IsAlive() then local EngageAltitude = math.random( self.EngageFloorAltitude or 500, self.EngageCeilingAltitude or 1000 ) local EngageSpeed = math.random( self.EngageMinSpeed, self.EngageMaxSpeed ) @@ -544,33 +533,25 @@ function AI_AIR_ENGAGE:onafterEngage( DefenderGroup, From, Event, To, AttackSetU TargetCoord:SetY( EngageAltitude ) -- Ground targets don't have an altitude. local TargetDistance = DefenderCoord:Get2DDistance( TargetCoord ) + local EngageDistance = ( DefenderGroup:IsHelicopter() and 5000 ) or ( DefenderGroup:IsAirPlane() and 10000 ) local EngageRoute = {} local AttackTasks = {} - local FromWP = DefenderCoord:WaypointAir( - self.EngageAltType or "RADIO", - POINT_VEC3.RoutePointType.TurningPoint, - POINT_VEC3.RoutePointAction.TurningPoint, - EngageSpeed, - true - ) + local FromWP = DefenderCoord:WaypointAir(self.EngageAltType or "RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, EngageSpeed, true) EngageRoute[#EngageRoute+1] = FromWP self:SetTargetDistance( TargetCoord ) -- For RTB status check local FromEngageAngle = DefenderCoord:GetAngleDegrees( DefenderCoord:GetDirectionVec3( TargetCoord ) ) - local ToWP = DefenderCoord:Translate( EngageDistance, FromEngageAngle, true ):WaypointAir( - self.EngageAltType or "RADIO", - POINT_VEC3.RoutePointType.TurningPoint, - POINT_VEC3.RoutePointAction.TurningPoint, - EngageSpeed, - true - ) + local ToCoord=DefenderCoord:Translate( EngageDistance, FromEngageAngle, true ) + + local ToWP = ToCoord:WaypointAir(self.EngageAltType or "RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, EngageSpeed, true) EngageRoute[#EngageRoute+1] = ToWP - if TargetDistance <= EngageDistance * 3 then + -- TODO: A factor of * 3 this way too low. This causes the AI NOT to engage until very close or even merged sometimes. Some A2A missiles have a much longer range! Needs more frequent updates of the task! + if TargetDistance <= EngageDistance * 9 then local AttackUnitTasks = self:CreateAttackUnitTasks( AttackSetUnit, DefenderGroup, EngageAltitude ) -- Polymorphic @@ -579,7 +560,8 @@ function AI_AIR_ENGAGE:onafterEngage( DefenderGroup, From, Event, To, AttackSetU self:Return() return else - self:I( DefenderGroupName .. ": Engaging targets " ) + local text=string.format("%s: Engaging targets at distance %.2f NM", DefenderGroupName, UTILS.MetersToNM(TargetDistance)) + self:I(text) DefenderGroup:OptionROEOpenFire() DefenderGroup:OptionROTEvadeFire() DefenderGroup:OptionKeepWeaponsOnThreat() @@ -591,10 +573,11 @@ function AI_AIR_ENGAGE:onafterEngage( DefenderGroup, From, Event, To, AttackSetU AttackTasks[#AttackTasks+1] = DefenderGroup:TaskFunction( "AI_AIR_ENGAGE.___Engage", self, AttackSetUnit ) EngageRoute[#EngageRoute].task = DefenderGroup:TaskCombo( AttackTasks ) - DefenderGroup:Route( EngageRoute, self.TaskDelay ) + DefenderGroup:Route( EngageRoute, self.TaskDelay or 0.1 ) end else + -- TODO: This will make an A2A Dispatcher CAP flight to return rather than going back to patrolling! self:I( DefenderGroupName .. ": No targets found -> returning.") self:Return() return @@ -605,9 +588,9 @@ end function AI_AIR_ENGAGE.Resume( AIEngage, Fsm ) AIEngage:F( { "Resume:", AIEngage:GetName() } ) - if AIEngage:IsAlive() then - Fsm:__Reset( Fsm.TaskDelay ) - Fsm:__EngageRoute( Fsm.TaskDelay, Fsm.AttackSetUnit ) + if AIEngage and AIEngage:IsAlive() then + Fsm:__Reset( Fsm.TaskDelay or 0.1 ) + Fsm:__EngageRoute( Fsm.TaskDelay or 0.2, Fsm.AttackSetUnit ) end end diff --git a/Moose Development/Moose/AI/AI_CAP.lua b/Moose Development/Moose/AI/AI_CAP.lua index 1ffdbc23b..5366db4b4 100644 --- a/Moose Development/Moose/AI/AI_CAP.lua +++ b/Moose Development/Moose/AI/AI_CAP.lua @@ -421,7 +421,7 @@ end -- @param #string To The To State string. function AI_CAP_ZONE:onafterEngage( Controllable, From, Event, To ) - if Controllable:IsAlive() then + if Controllable and Controllable:IsAlive() then local EngageRoute = {} diff --git a/Moose Development/Moose/Functional/Fox.lua b/Moose Development/Moose/Functional/Fox.lua index 47faf90bf..1963afd83 100644 --- a/Moose Development/Moose/Functional/Fox.lua +++ b/Moose Development/Moose/Functional/Fox.lua @@ -198,7 +198,7 @@ FOX.MenuF10Root=nil --- FOX class version. -- @field #string version -FOX.version="0.6.0" +FOX.version="0.6.1" ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- ToDo list @@ -243,6 +243,7 @@ function FOX:New() self:AddTransition("*", "MissileDestroyed", "*") -- Missile was destroyed before impact. self:AddTransition("*", "EnterSafeZone", "*") -- Player enters a safe zone. self:AddTransition("*", "ExitSafeZone", "*") -- Player exists a safe zone. + self:AddTransition("Running", "Stop", "Stopped") -- Stop FOX script. ------------------------ --- Pseudo Functions --- diff --git a/Moose Development/Moose/Functional/Suppression.lua b/Moose Development/Moose/Functional/Suppression.lua index 3df26be6d..1c8c56092 100644 --- a/Moose Development/Moose/Functional/Suppression.lua +++ b/Moose Development/Moose/Functional/Suppression.lua @@ -5,6 +5,10 @@ -- ## Features: -- -- * Hold fire of attacked units when being fired upon. +-- * Retreat to a user defined zone. +-- * Fall back on hits. +-- * Take cover on hits. +-- * Gaussian distribution of suppression time. -- -- === -- @@ -44,6 +48,7 @@ -- @type SUPPRESSION -- @field #string ClassName Name of the class. -- @field #boolean Debug Write Debug messages to DCS log file and send Debug messages to all players. +-- @field #string lid String for DCS log file. -- @field #boolean flare Flare units when they get hit or die. -- @field #boolean smoke Smoke places to which the group retreats, falls back or hides. -- @field #list DCSdesc Table containing all DCS descriptors of the group. @@ -222,41 +227,42 @@ -- -- @field #SUPPRESSION SUPPRESSION={ - ClassName = "SUPPRESSION", - Debug = false, - flare = false, - smoke = false, - DCSdesc = nil, - Type = nil, - IsInfantry=nil, - SpeedMax = nil, - Tsuppress_ave = 15, - Tsuppress_min = 5, - Tsuppress_max = 25, - TsuppressOver = nil, - IniGroupStrength = nil, - Nhit = 0, - Formation = "Off road", - Speed = 4, - MenuON = false, - FallbackON = false, - FallbackWait = 60, - FallbackDist = 100, - FallbackHeading = nil, - TakecoverON = false, - TakecoverWait = 120, - TakecoverRange = 300, - hideout = nil, - PminFlee = 10, - PmaxFlee = 90, - RetreatZone = nil, - RetreatDamage = nil, - RetreatWait = 7200, + ClassName = "SUPPRESSION", + Debug = false, + lid = nil, + flare = false, + smoke = false, + DCSdesc = nil, + Type = nil, + IsInfantry = nil, + SpeedMax = nil, + Tsuppress_ave = 15, + Tsuppress_min = 5, + Tsuppress_max = 25, + TsuppressOver = nil, + IniGroupStrength = nil, + Nhit = 0, + Formation = "Off road", + Speed = 4, + MenuON = false, + FallbackON = false, + FallbackWait = 60, + FallbackDist = 100, + FallbackHeading = nil, + TakecoverON = false, + TakecoverWait = 120, + TakecoverRange = 300, + hideout = nil, + PminFlee = 10, + PmaxFlee = 90, + RetreatZone = nil, + RetreatDamage = nil, + RetreatWait = 7200, CurrentAlarmState = "unknown", - CurrentROE = "unknown", + CurrentROE = "unknown", DefaultAlarmState = "Auto", - DefaultROE = "Weapon Free", - eventmoose = true, + DefaultROE = "Weapon Free", + eventmoose = true, } --- Enumerator of possible rules of engagement. @@ -279,13 +285,9 @@ SUPPRESSION.AlarmState={ -- @field #string MenuF10 SUPPRESSION.MenuF10=nil ---- Some ID to identify who we are in output of the DCS.log file. --- @field #string id -SUPPRESSION.id="SUPPRESSION | " - --- PSEUDOATC version. -- @field #number version -SUPPRESSION.version="0.9.0" +SUPPRESSION.version="0.9.1" ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -302,22 +304,22 @@ SUPPRESSION.version="0.9.0" -- @return #SUPPRESSION SUPPRESSION object. -- @return nil If group does not exist or is not a ground group. function SUPPRESSION:New(group) - BASE:F2(group) -- Inherits from FSM_CONTROLLABLE local self=BASE:Inherit(self, FSM_CONTROLLABLE:New()) -- #SUPPRESSION -- Check that group is present. if group then - self:T(SUPPRESSION.id..string.format("SUPPRESSION version %s. Activating suppressive fire for group %s", SUPPRESSION.version, group:GetName())) + self.lid=string.format("SUPPRESSION %s | ", tostring(group:GetName())) + self:T(self.lid..string.format("SUPPRESSION version %s. Activating suppressive fire for group %s", SUPPRESSION.version, group:GetName())) else - self:E(SUPPRESSION.id.."Suppressive fire: Requested group does not exist! (Has to be a MOOSE group.)") + self:E(self.lid.."SUPPRESSION | Requested group does not exist! (Has to be a MOOSE group.)") return nil end -- Check that we actually have a GROUND group. if group:IsGround()==false then - self:E(SUPPRESSION.id..string.format("SUPPRESSION fire group %s has to be a GROUND group!", group:GetName())) + self:E(self.lid..string.format("SUPPRESSION fire group %s has to be a GROUND group!", group:GetName())) return nil end @@ -350,6 +352,7 @@ function SUPPRESSION:New(group) -- Transitions self:AddTransition("*", "Start", "CombatReady") + self:AddTransition("*", "Status", "*") self:AddTransition("CombatReady", "Hit", "Suppressed") self:AddTransition("Suppressed", "Hit", "Suppressed") self:AddTransition("Suppressed", "Recovered", "CombatReady") @@ -364,6 +367,38 @@ function SUPPRESSION:New(group) self:AddTransition("TakingCover", "Hit", "TakingCover") self:AddTransition("FallingBack", "Hit", "FallingBack") + + --- Trigger "Status" event. + -- @function [parent=#SUPPRESSION] Status + -- @param #SUPPRESSION self + + --- Trigger "Status" event after a delay. + -- @function [parent=#SUPPRESSION] __Status + -- @param #SUPPRESSION self + -- @param #number Delay Delay in seconds. + + --- User function for OnAfter "Status" event. + -- @function [parent=#SUPPRESSION] OnAfterStatus + -- @param #SUPPRESSION self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable Controllable of the group. + -- @param #string From From state. + -- @param #string Event Event. + -- @param #string To To state. + + + --- Trigger "Hit" event. + -- @function [parent=#SUPPRESSION] Hit + -- @param #SUPPRESSION self + -- @param Wrapper.Unit#UNIT Unit Unit that was hit. + -- @param Wrapper.Unit#UNIT AttackUnit Unit that attacked. + + --- Trigger "Hit" event after a delay. + -- @function [parent=#SUPPRESSION] __Hit + -- @param #SUPPRESSION self + -- @param #number Delay Delay in seconds. + -- @param Wrapper.Unit#UNIT Unit Unit that was hit. + -- @param Wrapper.Unit#UNIT AttackUnit Unit that attacked. + --- User function for OnBefore "Hit" event. -- @function [parent=#SUPPRESSION] OnBeforeHit -- @param #SUPPRESSION self @@ -375,7 +410,7 @@ function SUPPRESSION:New(group) -- @param Wrapper.Unit#UNIT AttackUnit Unit that attacked. -- @return #boolean - --- User function for OnAfer "Hit" event. + --- User function for OnAfter "Hit" event. -- @function [parent=#SUPPRESSION] OnAfterHit -- @param #SUPPRESSION self -- @param Wrapper.Controllable#CONTROLLABLE Controllable Controllable of the group. @@ -384,7 +419,16 @@ function SUPPRESSION:New(group) -- @param #string To To state. -- @param Wrapper.Unit#UNIT Unit Unit that was hit. -- @param Wrapper.Unit#UNIT AttackUnit Unit that attacked. + + --- Trigger "Recovered" event. + -- @function [parent=#SUPPRESSION] Recovered + -- @param #SUPPRESSION self + + --- Trigger "Recovered" event after a delay. + -- @function [parent=#SUPPRESSION] Recovered + -- @param #number Delay Delay in seconds. + -- @param #SUPPRESSION self --- User function for OnBefore "Recovered" event. -- @function [parent=#SUPPRESSION] OnBeforeRecovered @@ -404,6 +448,17 @@ function SUPPRESSION:New(group) -- @param #string To To state. + --- Trigger "TakeCover" event. + -- @function [parent=#SUPPRESSION] TakeCover + -- @param #SUPPRESSION self + -- @param Core.Point#COORDINATE Hideout Place where the group will hide. + + --- Trigger "TakeCover" event after a delay. + -- @function [parent=#SUPPRESSION] __TakeCover + -- @param #SUPPRESSION self + -- @param #number Delay Delay in seconds. + -- @param Core.Point#COORDINATE Hideout Place where the group will hide. + --- User function for OnBefore "TakeCover" event. -- @function [parent=#SUPPRESSION] OnBeforeTakeCover -- @param #SUPPRESSION self @@ -424,6 +479,17 @@ function SUPPRESSION:New(group) -- @param Core.Point#COORDINATE Hideout Place where the group will hide. + --- Trigger "FallBack" event. + -- @function [parent=#SUPPRESSION] FallBack + -- @param #SUPPRESSION self + -- @param Wrapper.Unit#UNIT AttackUnit Attacking unit. We will move away from this. + + --- Trigger "FallBack" event after a delay. + -- @function [parent=#SUPPRESSION] __FallBack + -- @param #SUPPRESSION self + -- @param #number Delay Delay in seconds. + -- @param Wrapper.Unit#UNIT AttackUnit Attacking unit. We will move away from this. + --- User function for OnBefore "FallBack" event. -- @function [parent=#SUPPRESSION] OnBeforeFallBack -- @param #SUPPRESSION self @@ -444,6 +510,15 @@ function SUPPRESSION:New(group) -- @param Wrapper.Unit#UNIT AttackUnit Attacking unit. We will move away from this. + --- Trigger "Retreat" event. + -- @function [parent=#SUPPRESSION] Retreat + -- @param #SUPPRESSION self + + --- Trigger "Retreat" event after a delay. + -- @function [parent=#SUPPRESSION] __Retreat + -- @param #SUPPRESSION self + -- @param #number Delay Delay in seconds. + --- User function for OnBefore "Retreat" event. -- @function [parent=#SUPPRESSION] OnBeforeRetreat -- @param #SUPPRESSION self @@ -462,6 +537,15 @@ function SUPPRESSION:New(group) -- @param #string To To state. + --- Trigger "Retreated" event. + -- @function [parent=#SUPPRESSION] Retreated + -- @param #SUPPRESSION self + + --- Trigger "Retreated" event after a delay. + -- @function [parent=#SUPPRESSION] __Retreated + -- @param #SUPPRESSION self + -- @param #number Delay Delay in seconds. + --- User function for OnBefore "Retreated" event. -- @function [parent=#SUPPRESSION] OnBeforeRetreated -- @param #SUPPRESSION self @@ -480,6 +564,15 @@ function SUPPRESSION:New(group) -- @param #string To To state. + --- Trigger "FightBack" event. + -- @function [parent=#SUPPRESSION] FightBack + -- @param #SUPPRESSION self + + --- Trigger "FightBack" event after a delay. + -- @function [parent=#SUPPRESSION] __FightBack + -- @param #SUPPRESSION self + -- @param #number Delay Delay in seconds. + --- User function for OnBefore "FlightBack" event. -- @function [parent=#SUPPRESSION] OnBeforeFightBack -- @param #SUPPRESSION self @@ -498,6 +591,23 @@ function SUPPRESSION:New(group) -- @param #string To To state. + --- Trigger "Dead" event. + -- @function [parent=#SUPPRESSION] Dead + -- @param #SUPPRESSION self + + --- Trigger "Dead" event after a delay. + -- @function [parent=#SUPPRESSION] __Dead + -- @param #SUPPRESSION self + -- @param #number Delay Delay in seconds. + + --- User function for OnAfter "Dead" event. + -- @function [parent=#SUPPRESSION] OnAfterDead + -- @param #SUPPRESSION self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable Controllable of the group. + -- @param #string From From state. + -- @param #string Event Event. + -- @param #string To To state. + return self end @@ -524,9 +634,9 @@ function SUPPRESSION:SetSuppressionTime(Tave, Tmin, Tmax) self.Tsuppress_ave=math.max(self.Tsuppress_min) self.Tsuppress_ave=math.min(self.Tsuppress_max) - self:T(SUPPRESSION.id..string.format("Set ave suppression time to %d seconds.", self.Tsuppress_ave)) - self:T(SUPPRESSION.id..string.format("Set min suppression time to %d seconds.", self.Tsuppress_min)) - self:T(SUPPRESSION.id..string.format("Set max suppression time to %d seconds.", self.Tsuppress_max)) + self:T(self.lid..string.format("Set ave suppression time to %d seconds.", self.Tsuppress_ave)) + self:T(self.lid..string.format("Set min suppression time to %d seconds.", self.Tsuppress_min)) + self:T(self.lid..string.format("Set max suppression time to %d seconds.", self.Tsuppress_max)) end --- Set the zone to which a group retreats after being damaged too much. @@ -756,13 +866,14 @@ end --- Status of group. Current ROE, alarm state, life. -- @param #SUPPRESSION self -- @param #boolean message Send message to all players. -function SUPPRESSION:Status(message) +function SUPPRESSION:StatusReport(message) local name=self.Controllable:GetName() local nunits=#self.Controllable:GetUnits() local roe=self.CurrentROE local state=self.CurrentAlarmState local life_min, life_max, life_ave, life_ave0, groupstrength=self:_GetLife() + local at=self.Controllable:GetAmmunition() local text=string.format("Status of group %s\n", name) text=text..string.format("Number of units: %d of %d\n", nunits, self.IniGroupStrength) @@ -774,10 +885,11 @@ function SUPPRESSION:Status(message) text=text..string.format("Life max: %3.0f\n", life_max) text=text..string.format("Life ave: %3.0f\n", life_ave) text=text..string.format("Life ave0: %3.0f\n", life_ave0) + text=text..string.format("Ammo tot: %d\n", at) text=text..string.format("Group strength: %3.0f", groupstrength) MESSAGE:New(text, 10):ToAllIf(message or self.Debug) - self:T(SUPPRESSION.id.."\n"..text) + self:I(self.lid.."\n"..text) end ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -794,6 +906,7 @@ function SUPPRESSION:onafterStart(Controllable, From, Event, To) self:_EventFromTo("onafterStart", Event, From, To) local text=string.format("Started SUPPRESSION for group %s.", Controllable:GetName()) + self:I(self.lid..text) MESSAGE:New(text, 10):ToAllIf(self.Debug) local rzone="not defined" @@ -854,7 +967,7 @@ function SUPPRESSION:onafterStart(Controllable, From, Event, To) text=text..string.format("Speed max = %5.1f km/h\n", self.SpeedMax) text=text..string.format("Formation = %s\n", self.Formation) text=text..string.format("******************************************************\n") - self:T(SUPPRESSION.id..text) + self:T(self.lid..text) -- Add event handler. if self.eventmoose then @@ -863,9 +976,37 @@ function SUPPRESSION:onafterStart(Controllable, From, Event, To) else world.addEventHandler(self) end - + + + self:__Status(-1) end +--- After "Status" event. +-- @param #SUPPRESSION self +-- @param Wrapper.Controllable#CONTROLLABLE Controllable Controllable of the group. +-- @param #string From From state. +-- @param #string Event Event. +-- @param #string To To state. +function SUPPRESSION:onafterStatus(Controllable, From, Event, To) + + --local text=string.format("State=%s, ROE %d, Life=%.1f", Controllable:GetName()) + --MESSAGE:New(text, 10):ToAllIf(self.Debug) + + local group=self.Controllable --Wrapper.Group#GROUP + + local n=group:GetAmmunition() + + self:StatusReport(false) + + -- Retreat if completely out of ammo and retreat zone defined. + if n==0 and self.RetreatZone then + + self:Retreat() + + end + + self:__Status(-30) +end ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --- Before "Hit" event. (Of course, this is not really before the group got hit.) @@ -881,7 +1022,7 @@ function SUPPRESSION:onbeforeHit(Controllable, From, Event, To, Unit, AttackUnit self:_EventFromTo("onbeforeHit", Event, From, To) --local Tnow=timer.getTime() - --env.info(SUPPRESSION.id..string.format("Last hit = %s %s", tostring(self.LastHit), tostring(Tnow))) + --env.info(self.lid..string.format("Last hit = %s %s", tostring(self.LastHit), tostring(Tnow))) return true end @@ -925,7 +1066,7 @@ function SUPPRESSION:onafterHit(Controllable, From, Event, To, Unit, AttackUnit) text=string.format("\nGroup %s: Life min=%5.1f, max=%5.1f, ave=%5.1f, ave0=%5.1f group=%5.1f\n", Controllable:GetName(), life_min, life_max, life_ave, life_ave0, groupstrength) text=string.format("Group %s: Damage = %8.4f (%8.4f retreat threshold).\n", Controllable:GetName(), Damage, self.RetreatDamage) text=string.format("Group %s: P_Flee = %5.1f %5.1f=P_rand (P_Flee > Prand ==> Flee)\n", Controllable:GetName(), Pflee, P) - self:T(SUPPRESSION.id..text) + self:T(self.lid..text) -- Group is obviously destroyed. if Damage >= 99.9 then @@ -957,11 +1098,6 @@ function SUPPRESSION:onafterHit(Controllable, From, Event, To, Unit, AttackUnit) end end - -- Give info on current status. - if self.Debug then - self:Status() - end - end ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -980,7 +1116,7 @@ function SUPPRESSION:onbeforeRecovered(Controllable, From, Event, To) local Tnow=timer.getTime() -- Debug info - self:T(SUPPRESSION.id..string.format("onbeforeRecovered: Time now: %d - Time over: %d", Tnow, self.TsuppressionOver)) + self:T(self.lid..string.format("onbeforeRecovered: Time now: %d - Time over: %d", Tnow, self.TsuppressionOver)) -- Recovery is only possible if enough time since the last hit has passed. if Tnow >= self.TsuppressionOver then @@ -1005,7 +1141,7 @@ function SUPPRESSION:onafterRecovered(Controllable, From, Event, To) -- Debug message. local text=string.format("Group %s has recovered!", Controllable:GetName()) MESSAGE:New(text, 10):ToAllIf(self.Debug) - self:T(SUPPRESSION.id..text) + self:T(self.lid..text) -- Set ROE back to default. self:_SetROE() @@ -1066,7 +1202,7 @@ function SUPPRESSION:onafterFallBack(Controllable, From, Event, To, AttackUnit) self:_EventFromTo("onafterFallback", Event, From, To) -- Debug info - self:T(SUPPRESSION.id..string.format("Group %s is falling back after %d hits.", Controllable:GetName(), self.Nhit)) + self:T(self.lid..string.format("Group %s is falling back after %d hits.", Controllable:GetName(), self.Nhit)) -- Coordinate of the attacker and attacked unit. local ACoord=AttackUnit:GetCoordinate() @@ -1174,8 +1310,8 @@ function SUPPRESSION:onbeforeRetreat(Controllable, From, Event, To) self:_EventFromTo("onbeforeRetreat", Event, From, To) if From=="Retreating" then - local text=string.format("Group %s is already retreating.") - self:T2(SUPPRESSION.id..text) + local text=string.format("Group %s is already retreating.", tostring(Controllable:GetName())) + self:T2(self.lid..text) return false else return true @@ -1195,7 +1331,7 @@ function SUPPRESSION:onafterRetreat(Controllable, From, Event, To) -- Route the group to a zone. local text=string.format("Group %s is retreating! Alarm state green.", Controllable:GetName()) MESSAGE:New(text, 10):ToAllIf(self.Debug) - self:T(SUPPRESSION.id..text) + self:T(self.lid..text) -- Get a random point in the retreat zone. local ZoneCoord=self.RetreatZone:GetRandomCoordinate() -- Core.Point#COORDINATE @@ -1272,11 +1408,11 @@ function SUPPRESSION:onafterDead(Controllable, From, Event, To) local text=string.format("Group %s: One of our units just died! %d units left.", self.Controllable:GetName(), nunits) MESSAGE:New(text, 10):ToAllIf(self.Debug) - self:T(SUPPRESSION.id..text) + self:T(self.lid..text) -- Go to stop state. if nunits==0 then - self:T(SUPPRESSION.id..string.format("Stopping SUPPRESSION for group %s.", Controllable:GetName())) + self:T(self.lid..string.format("Stopping SUPPRESSION for group %s.", Controllable:GetName())) self:Stop() if self.mooseevents then self:UnHandleEvent(EVENTS.Dead) @@ -1348,7 +1484,7 @@ function SUPPRESSION:_OnEventHit(EventData) -- Check that correct group was hit. if GroupNameTgt == GroupNameSelf then - self:T(SUPPRESSION.id..string.format("Hit event at t = %5.1f", timer.getTime())) + self:T(self.lid..string.format("Hit event at t = %5.1f", timer.getTime())) -- Flare unit that was hit. if self.flare or self.Debug then @@ -1359,11 +1495,11 @@ function SUPPRESSION:_OnEventHit(EventData) self.Nhit=self.Nhit+1 -- Info on hit times. - self:T(SUPPRESSION.id..string.format("Group %s has just been hit %d times.", self.Controllable:GetName(), self.Nhit)) + self:T(self.lid..string.format("Group %s has just been hit %d times.", self.Controllable:GetName(), self.Nhit)) --self:Status() local life=tgt:getLife()/(tgt:getLife0()+1)*100 - self:T2(SUPPRESSION.id..string.format("Target unit life = %5.1f", life)) + self:T2(self.lid..string.format("Target unit life = %5.1f", life)) -- FSM Hit event. self:__Hit(3, TgtUnit, IniUnit) @@ -1380,35 +1516,35 @@ function SUPPRESSION:_OnEventDead(EventData) local GroupNameIni=EventData.IniGroupName -- Check for correct group. - if GroupNameIni== GroupNameSelf then + if GroupNameIni==GroupNameSelf then -- Dead Unit. local IniUnit=EventData.IniUnit --Wrapper.Unit#UNIT local IniUnitName=EventData.IniUnitName if EventData.IniUnit then - self:T2(SUPPRESSION.id..string.format("Group %s: Dead MOOSE unit DOES exist! Unit name %s.", GroupNameIni, IniUnitName)) + self:T2(self.lid..string.format("Group %s: Dead MOOSE unit DOES exist! Unit name %s.", GroupNameIni, IniUnitName)) else - self:T2(SUPPRESSION.id..string.format("Group %s: Dead MOOSE unit DOES NOT not exist! Unit name %s.", GroupNameIni, IniUnitName)) + self:T2(self.lid..string.format("Group %s: Dead MOOSE unit DOES NOT not exist! Unit name %s.", GroupNameIni, IniUnitName)) end if EventData.IniDCSUnit then - self:T2(SUPPRESSION.id..string.format("Group %s: Dead DCS unit DOES exist! Unit name %s.", GroupNameIni, IniUnitName)) + self:T2(self.lid..string.format("Group %s: Dead DCS unit DOES exist! Unit name %s.", GroupNameIni, IniUnitName)) else - self:T2(SUPPRESSION.id..string.format("Group %s: Dead DCS unit DOES NOT exist! Unit name %s.", GroupNameIni, IniUnitName)) + self:T2(self.lid..string.format("Group %s: Dead DCS unit DOES NOT exist! Unit name %s.", GroupNameIni, IniUnitName)) end -- Flare unit that died. if IniUnit and (self.flare or self.Debug) then IniUnit:FlareWhite() - self:T(SUPPRESSION.id..string.format("Flare Dead MOOSE unit.")) + self:T(self.lid..string.format("Flare Dead MOOSE unit.")) end -- Flare unit that died. if EventData.IniDCSUnit and (self.flare or self.Debug) then local p=EventData.IniDCSUnit:getPosition().p trigger.action.signalFlare(p, trigger.flareColor.Yellow , 0) - self:T(SUPPRESSION.id..string.format("Flare Dead DCS unit.")) + self:T(self.lid..string.format("Flare Dead DCS unit.")) end -- Get status. @@ -1462,7 +1598,7 @@ function SUPPRESSION:_Suppress() -- Debug message. local text=string.format("Group %s is suppressed for %d seconds. Suppression ends at %d:%02d.", Controllable:GetName(), Tsuppress, self.TsuppressionOver/60, self.TsuppressionOver%60) MESSAGE:New(text, 10):ToAllIf(self.Debug) - self:T(SUPPRESSION.id..text) + self:T(self.lid..text) end @@ -1520,7 +1656,7 @@ function SUPPRESSION:_Run(fin, speed, formation, wait) local MarkerID=ini:MarkToAll(string.format("Waypoing %d of group %s (initial)", #wp, self.Controllable:GetName())) end - self:T2(SUPPRESSION.id..string.format("Number of waypoints %d", nx)) + self:T2(self.lid..string.format("Number of waypoints %d", nx)) for i=1,nx-2 do local x=dx*i @@ -1529,13 +1665,13 @@ function SUPPRESSION:_Run(fin, speed, formation, wait) wp[#wp+1]=coord:WaypointGround(speed, formation) tasks[#tasks+1]=group:TaskFunction("SUPPRESSION._Passing_Waypoint", self, #wp, false) - self:T2(SUPPRESSION.id..string.format("%d x = %4.1f", i, x)) + self:T2(self.lid..string.format("%d x = %4.1f", i, x)) if self.Debug then local MarkerID=coord:MarkToAll(string.format("Waypoing %d of group %s", #wp, self.Controllable:GetName())) end end - self:T2(SUPPRESSION.id..string.format("Total distance: %4.1f", dist)) + self:T2(self.lid..string.format("Total distance: %4.1f", dist)) -- Final waypoint. wp[#wp+1]=fin:WaypointGround(speed, formation) @@ -1584,7 +1720,7 @@ function SUPPRESSION._Passing_Waypoint(group, Fsm, i, final) local text=string.format("Group %s passing waypoint %d (final=%s)", group:GetName(), i, tostring(final)) MESSAGE:New(text,10):ToAllIf(Fsm.Debug) if Fsm.Debug then - env.info(SUPPRESSION.id..text) + env.info(self.lid..text) end if final then @@ -1629,7 +1765,7 @@ function SUPPRESSION:_SearchHideout() -- Place markers on every possible scenery object. local MarkerID=SceneryObject:GetCoordinate():MarkToAll(string.format("%s scenery object %s", self.Controllable:GetName(),SceneryObject:GetTypeName())) local text=string.format("%s scenery: %s, Coord %s", self.Controllable:GetName(), SceneryObject:GetTypeName(), SceneryObject:GetCoordinate():ToStringLLDMS()) - self:T2(SUPPRESSION.id..text) + self:T2(self.lid..text) end -- Add to table. @@ -1642,7 +1778,7 @@ function SUPPRESSION:_SearchHideout() if #hideouts>0 then -- Debug info. - self:T(SUPPRESSION.id.."Number of hideouts "..#hideouts) + self:T(self.lid.."Number of hideouts "..#hideouts) -- Sort results table wrt number of hits. local _sort = function(a,b) return a.distance < b.distance end @@ -1655,7 +1791,7 @@ function SUPPRESSION:_SearchHideout() Hideout=hideouts[1].object:GetCoordinate() else - self:E(SUPPRESSION.id.."No hideouts found!") + self:E(self.lid.."No hideouts found!") end return Hideout @@ -1685,7 +1821,7 @@ function SUPPRESSION:_GetLife() local groupstrength=#units/self.IniGroupStrength*100 - self.T2(SUPPRESSION.id..string.format("Group %s _GetLife nunits = %d", self.Controllable:GetName(), #units)) + self.T2(self.lid..string.format("Group %s _GetLife nunits = %d", self.Controllable:GetName(), #units)) for _,unit in pairs(units) do @@ -1702,7 +1838,7 @@ function SUPPRESSION:_GetLife() life_ave=life_ave+life if self.Debug then local text=string.format("n=%02d: Life = %3.1f, Life0 = %3.1f, min=%3.1f, max=%3.1f, ave=%3.1f, group=%3.1f", n, unit:GetLife(), unit:GetLife0(), life_min, life_max, life_ave/n,groupstrength) - self:T2(SUPPRESSION.id..text) + self:T2(self.lid..text) end end @@ -1795,13 +1931,13 @@ function SUPPRESSION:_SetROE(roe) elseif roe==SUPPRESSION.ROE.Return then group:OptionROEReturnFire() else - self:E(SUPPRESSION.id.."Unknown ROE requested: "..tostring(roe)) + self:E(self.lid.."Unknown ROE requested: "..tostring(roe)) group:OptionROEOpenFire() self.CurrentROE=SUPPRESSION.ROE.Free end local text=string.format("Group %s now has ROE %s.", self.Controllable:GetName(), self.CurrentROE) - self:T(SUPPRESSION.id..text) + self:T(self.lid..text) end --- Sets the alarm state of the group and updates the current alarm state variable. @@ -1824,13 +1960,13 @@ function SUPPRESSION:_SetAlarmState(state) elseif state==SUPPRESSION.AlarmState.Red then group:OptionAlarmStateRed() else - self:E(SUPPRESSION.id.."Unknown alarm state requested: "..tostring(state)) + self:E(self.lid.."Unknown alarm state requested: "..tostring(state)) group:OptionAlarmStateAuto() self.CurrentAlarmState=SUPPRESSION.AlarmState.Auto end local text=string.format("Group %s now has Alarm State %s.", self.Controllable:GetName(), self.CurrentAlarmState) - self:T(SUPPRESSION.id..text) + self:T(self.lid..text) end --- Print event-from-to string to DCS log file. @@ -1841,7 +1977,7 @@ end -- @param #string To To state. function SUPPRESSION:_EventFromTo(BA, Event, From, To) local text=string.format("\n%s: %s EVENT %s: %s --> %s", BA, self.Controllable:GetName(), Event, From, To) - self:T2(SUPPRESSION.id..text) + self:T2(self.lid..text) end ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- diff --git a/Moose Development/Moose/Wrapper/Group.lua b/Moose Development/Moose/Wrapper/Group.lua index 8c855be45..b85d519b2 100644 --- a/Moose Development/Moose/Wrapper/Group.lua +++ b/Moose Development/Moose/Wrapper/Group.lua @@ -1046,6 +1046,45 @@ function GROUP:GetFuel() end +--- Get the number of shells, rockets, bombs and missiles the whole group currently has. +-- @param #GROUP self +-- @return #number Total amount of ammo the group has left. This is the sum of shells, rockets, bombs and missiles of all units. +-- @return #number Number of shells left. +-- @return #number Number of rockets left. +-- @return #number Number of bombs left. +-- @return #number Number of missiles left. +function GROUP:GetAmmunition() + self:F( self.ControllableName ) + + local DCSControllable = self:GetDCSObject() + + local Ntot=0 + local Nshells=0 + local Nrockets=0 + local Nmissiles=0 + + if DCSControllable then + + -- Loop over units. + for UnitID, UnitData in pairs( self:GetUnits() ) do + local Unit = UnitData -- Wrapper.Unit#UNIT + + -- Get ammo of the unit + local ntot, nshells, nrockets, nmissiles = Unit:GetAmmunition() + + Ntot=Ntot+ntot + Nshells=Nshells+nshells + Nrockets=Nrockets+nrockets + Nmissiles=Nmissiles+nmissiles + + end + + end + + return Ntot, Nshells, Nrockets, Nmissiles +end + + do -- Is Zone methods --- Returns true if all units of the group are within a @{Zone}. diff --git a/Moose Development/Moose/Wrapper/Unit.lua b/Moose Development/Moose/Wrapper/Unit.lua index 6987e5ad5..7f974be19 100644 --- a/Moose Development/Moose/Wrapper/Unit.lua +++ b/Moose Development/Moose/Wrapper/Unit.lua @@ -493,6 +493,94 @@ function UNIT:GetAmmo() return nil end +--- Get the number of ammunition and in particular the number of shells, rockets, bombs and missiles a unit currently has. +-- @param #UNIT self +-- @return #number Total amount of ammo the unit has left. This is the sum of shells, rockets, bombs and missiles. +-- @return #number Number of shells left. +-- @return #number Number of rockets left. +-- @return #number Number of bombs left. +-- @return #number Number of missiles left. +function UNIT:GetAmmunition() + + -- Init counter. + local nammo=0 + local nshells=0 + local nrockets=0 + local nmissiles=0 + local nbombs=0 + + local unit=self + + -- Get ammo table. + local ammotable=unit:GetAmmo() + + if ammotable then + + local weapons=#ammotable + + -- Loop over all weapons. + for w=1,weapons do + + -- Number of current weapon. + local Nammo=ammotable[w]["count"] + + -- Type name of current weapon. + local Tammo=ammotable[w]["desc"]["typeName"] + + local _weaponString = UTILS.Split(Tammo,"%.") + local _weaponName = _weaponString[#_weaponString] + + -- Get the weapon category: shell=0, missile=1, rocket=2, bomb=3 + local Category=ammotable[w].desc.category + + -- Get missile category: Weapon.MissileCategory AAM=1, SAM=2, BM=3, ANTI_SHIP=4, CRUISE=5, OTHER=6 + local MissileCategory=nil + if Category==Weapon.Category.MISSILE then + MissileCategory=ammotable[w].desc.missileCategory + end + + -- We are specifically looking for shells or rockets here. + if Category==Weapon.Category.SHELL then + + -- Add up all shells. + nshells=nshells+Nammo + + elseif Category==Weapon.Category.ROCKET then + + -- Add up all rockets. + nrockets=nrockets+Nammo + + elseif Category==Weapon.Category.BOMB then + + -- Add up all rockets. + nbombs=nbombs+Nammo + + elseif Category==Weapon.Category.MISSILE then + + -- Add up all cruise missiles (category 5) + if MissileCategory==Weapon.MissileCategory.AAM then + nmissiles=nmissiles+Nammo + elseif MissileCategory==Weapon.MissileCategory.ANTI_SHIP then + nmissiles=nmissiles+Nammo + elseif MissileCategory==Weapon.MissileCategory.BM then + nmissiles=nmissiles+Nammo + elseif MissileCategory==Weapon.MissileCategory.OTHER then + nmissiles=nmissiles+Nammo + end + + end + + end + end + + -- Total amount of ammunition. + nammo=nshells+nrockets+nmissiles+nbombs + + return nammo, nshells, nrockets, nbombs, nmissiles +end + + + --- Returns the unit sensors. -- @param #UNIT self -- @return DCS#Unit.Sensors