mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-10-29 16:58:06 +00:00
Merge pull request #1244 from FlightControl-Master/FF/Develop
A2A Dispatcher and other fixes/improvements
This commit is contained in:
commit
a193d342d7
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 = {}
|
||||
|
||||
|
||||
@ -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 ---
|
||||
|
||||
@ -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
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
@ -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}.
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user