mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-08-15 10:47:21 +00:00
Merge branch 'FF/Ops' into FF/OpsDev
This commit is contained in:
commit
3e30d15405
@ -3477,7 +3477,7 @@ do -- AI_A2A_DISPATCHER
|
|||||||
if Squadron.Language == "EN" and self.SetSendPlayerMessages then
|
if Squadron.Language == "EN" and self.SetSendPlayerMessages then
|
||||||
Dispatcher:MessageToPlayers( Squadron, DefenderName .. " wheels up.", DefenderGroup )
|
Dispatcher:MessageToPlayers( Squadron, DefenderName .. " wheels up.", DefenderGroup )
|
||||||
elseif Squadron.Language == "RU" and self.SetSendPlayerMessages then
|
elseif Squadron.Language == "RU" and self.SetSendPlayerMessages then
|
||||||
Dispatcher:MessageToPlayers( Squadron, DefenderName .. " колеÑ<EFBFBD>а вверх.", DefenderGroup )
|
Dispatcher:MessageToPlayers( Squadron, DefenderName .. " колёса вверх.", DefenderGroup )
|
||||||
end
|
end
|
||||||
--Fsm:__Engage( 2, DefenderTarget.Set ) -- Engage on the TargetSetUnit
|
--Fsm:__Engage( 2, DefenderTarget.Set ) -- Engage on the TargetSetUnit
|
||||||
Fsm:EngageRoute( DefenderTarget.Set ) -- Engage on the TargetSetUnit
|
Fsm:EngageRoute( DefenderTarget.Set ) -- Engage on the TargetSetUnit
|
||||||
@ -3498,7 +3498,7 @@ do -- AI_A2A_DISPATCHER
|
|||||||
if Squadron.Language == "EN" and self.SetSendPlayerMessages then
|
if Squadron.Language == "EN" and self.SetSendPlayerMessages then
|
||||||
Dispatcher:MessageToPlayers( Squadron, DefenderName .. ", intercepting bogeys at " .. Coordinate:ToStringA2A( DefenderGroup, nil, Squadron.Language ), DefenderGroup )
|
Dispatcher:MessageToPlayers( Squadron, DefenderName .. ", intercepting bogeys at " .. Coordinate:ToStringA2A( DefenderGroup, nil, Squadron.Language ), DefenderGroup )
|
||||||
elseif Squadron.Language == "RU" and self.SetSendPlayerMessages then
|
elseif Squadron.Language == "RU" and self.SetSendPlayerMessages then
|
||||||
Dispatcher:MessageToPlayers( Squadron, DefenderName .. ", перехват Ñ<>амолетов в " .. Coordinate:ToStringA2A( DefenderGroup, nil, Squadron.Language ), DefenderGroup )
|
Dispatcher:MessageToPlayers( Squadron, DefenderName .. ", перехватывая боги в " .. Coordinate:ToStringA2A( DefenderGroup, nil, Squadron.Language ), DefenderGroup )
|
||||||
elseif Squadron.Language == "DE" and self.SetSendPlayerMessages then
|
elseif Squadron.Language == "DE" and self.SetSendPlayerMessages then
|
||||||
Dispatcher:MessageToPlayers( Squadron, DefenderName .. ", Eindringlinge abfangen bei" .. Coordinate:ToStringA2A( DefenderGroup, nil, Squadron.Language ), DefenderGroup )
|
Dispatcher:MessageToPlayers( Squadron, DefenderName .. ", Eindringlinge abfangen bei" .. Coordinate:ToStringA2A( DefenderGroup, nil, Squadron.Language ), DefenderGroup )
|
||||||
end
|
end
|
||||||
@ -3520,7 +3520,7 @@ do -- AI_A2A_DISPATCHER
|
|||||||
if Squadron.Language == "EN" and self.SetSendPlayerMessages then
|
if Squadron.Language == "EN" and self.SetSendPlayerMessages then
|
||||||
Dispatcher:MessageToPlayers( Squadron, DefenderName .. ", engaging bogeys at " .. Coordinate:ToStringA2A( DefenderGroup, nil, Squadron.Language ), DefenderGroup )
|
Dispatcher:MessageToPlayers( Squadron, DefenderName .. ", engaging bogeys at " .. Coordinate:ToStringA2A( DefenderGroup, nil, Squadron.Language ), DefenderGroup )
|
||||||
elseif Squadron.Language == "RU" and self.SetSendPlayerMessages then
|
elseif Squadron.Language == "RU" and self.SetSendPlayerMessages then
|
||||||
Dispatcher:MessageToPlayers( Squadron, DefenderName .. ", захватывающие Ñ<>амолеты в " .. Coordinate:ToStringA2A( DefenderGroup, nil, Squadron.Language ), DefenderGroup )
|
Dispatcher:MessageToPlayers( Squadron, DefenderName .. ", задействуя боги в " .. Coordinate:ToStringA2A( DefenderGroup, nil, Squadron.Language ), DefenderGroup )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
self:GetParent( Fsm ).onafterEngage( self, DefenderGroup, From, Event, To, AttackSetUnit )
|
self:GetParent( Fsm ).onafterEngage( self, DefenderGroup, From, Event, To, AttackSetUnit )
|
||||||
@ -3538,7 +3538,7 @@ do -- AI_A2A_DISPATCHER
|
|||||||
if Squadron.Language == "EN" and self.SetSendPlayerMessages then
|
if Squadron.Language == "EN" and self.SetSendPlayerMessages then
|
||||||
Dispatcher:MessageToPlayers( Squadron, DefenderName .. " returning to base.", DefenderGroup )
|
Dispatcher:MessageToPlayers( Squadron, DefenderName .. " returning to base.", DefenderGroup )
|
||||||
elseif Squadron.Language == "RU" and self.SetSendPlayerMessages then
|
elseif Squadron.Language == "RU" and self.SetSendPlayerMessages then
|
||||||
Dispatcher:MessageToPlayers( Squadron, DefenderName .. ", возвращаÑ<EFBFBD>Ñ<EFBFBD>ÑŒ на базу.", DefenderGroup )
|
Dispatcher:MessageToPlayers( Squadron, DefenderName .. ", возвращение на базу.", DefenderGroup )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
Dispatcher:ClearDefenderTaskTarget( DefenderGroup )
|
Dispatcher:ClearDefenderTaskTarget( DefenderGroup )
|
||||||
@ -3569,7 +3569,7 @@ do -- AI_A2A_DISPATCHER
|
|||||||
if Squadron.Language == "EN" and self.SetSendPlayerMessages then
|
if Squadron.Language == "EN" and self.SetSendPlayerMessages then
|
||||||
Dispatcher:MessageToPlayers( Squadron, DefenderName .. " landing at base.", DefenderGroup )
|
Dispatcher:MessageToPlayers( Squadron, DefenderName .. " landing at base.", DefenderGroup )
|
||||||
elseif Squadron.Language == "RU" and self.SetSendPlayerMessages then
|
elseif Squadron.Language == "RU" and self.SetSendPlayerMessages then
|
||||||
Dispatcher:MessageToPlayers( Squadron, DefenderName .. ", захватывающие Ñ<>амолеты в поÑ<C2BE>адка на базу.", DefenderGroup )
|
Dispatcher:MessageToPlayers( Squadron, DefenderName .. ", посадка на базу.", DefenderGroup )
|
||||||
end
|
end
|
||||||
|
|
||||||
if Action and Action == "Destroy" then
|
if Action and Action == "Destroy" then
|
||||||
|
|||||||
@ -47,19 +47,21 @@ function AI_CARGO:New( Carrier, CargoSet )
|
|||||||
|
|
||||||
self:SetStartState( "Unloaded" )
|
self:SetStartState( "Unloaded" )
|
||||||
|
|
||||||
self:AddTransition( "Unloaded", "Pickup", "*" )
|
-- Board
|
||||||
|
self:AddTransition( "Unloaded", "Pickup", "Unloaded" )
|
||||||
|
self:AddTransition( "*", "Load", "*" )
|
||||||
|
self:AddTransition( "*", "Reload", "*" )
|
||||||
|
self:AddTransition( "*", "Board", "*" )
|
||||||
|
self:AddTransition( "*", "Loaded", "Loaded" )
|
||||||
|
self:AddTransition( "Loaded", "PickedUp", "Loaded" )
|
||||||
|
|
||||||
|
-- Unload
|
||||||
self:AddTransition( "Loaded", "Deploy", "*" )
|
self:AddTransition( "Loaded", "Deploy", "*" )
|
||||||
|
self:AddTransition( "*", "Unload", "*" )
|
||||||
|
self:AddTransition( "*", "Unboard", "*" )
|
||||||
|
self:AddTransition( "*", "Unloaded", "Unloaded" )
|
||||||
|
self:AddTransition( "Unloaded", "Deployed", "Unloaded" )
|
||||||
|
|
||||||
self:AddTransition( "*", "Load", "Boarding" )
|
|
||||||
self:AddTransition( "Boarding", "Board", "Boarding" )
|
|
||||||
self:AddTransition( "Loaded", "Board", "Loaded" )
|
|
||||||
self:AddTransition( "Boarding", "Loaded", "Boarding" )
|
|
||||||
self:AddTransition( "Boarding", "PickedUp", "Loaded" )
|
|
||||||
|
|
||||||
self:AddTransition( "Loaded", "Unload", "Unboarding" )
|
|
||||||
self:AddTransition( "Unboarding", "Unboard", "Unboarding" )
|
|
||||||
self:AddTransition( "Unboarding", "Unloaded", "Unboarding" )
|
|
||||||
self:AddTransition( "Unboarding", "Deployed", "Unloaded" )
|
|
||||||
|
|
||||||
--- Pickup Handler OnBefore for AI_CARGO
|
--- Pickup Handler OnBefore for AI_CARGO
|
||||||
-- @function [parent=#AI_CARGO] OnBeforePickup
|
-- @function [parent=#AI_CARGO] OnBeforePickup
|
||||||
@ -393,7 +395,7 @@ end
|
|||||||
function AI_CARGO:onafterBoard( Carrier, From, Event, To, Cargo, CarrierUnit, PickupZone )
|
function AI_CARGO:onafterBoard( Carrier, From, Event, To, Cargo, CarrierUnit, PickupZone )
|
||||||
self:F( { Carrier, From, Event, To, Cargo, CarrierUnit:GetName() } )
|
self:F( { Carrier, From, Event, To, Cargo, CarrierUnit:GetName() } )
|
||||||
|
|
||||||
if Carrier and Carrier:IsAlive() and From == "Boarding" then
|
if Carrier and Carrier:IsAlive() then
|
||||||
self:F({ IsLoaded = Cargo:IsLoaded(), Cargo:GetName(), Carrier:GetName() } )
|
self:F({ IsLoaded = Cargo:IsLoaded(), Cargo:GetName(), Carrier:GetName() } )
|
||||||
if not Cargo:IsLoaded() and not Cargo:IsDestroyed() then
|
if not Cargo:IsLoaded() and not Cargo:IsDestroyed() then
|
||||||
self:__Board( -10, Cargo, CarrierUnit, PickupZone )
|
self:__Board( -10, Cargo, CarrierUnit, PickupZone )
|
||||||
@ -509,7 +511,7 @@ end
|
|||||||
function AI_CARGO:onafterUnboard( Carrier, From, Event, To, Cargo, CarrierUnit, DeployZone, Defend )
|
function AI_CARGO:onafterUnboard( Carrier, From, Event, To, Cargo, CarrierUnit, DeployZone, Defend )
|
||||||
self:F( { Carrier, From, Event, To, Cargo:GetName(), DeployZone = DeployZone, Defend = Defend } )
|
self:F( { Carrier, From, Event, To, Cargo:GetName(), DeployZone = DeployZone, Defend = Defend } )
|
||||||
|
|
||||||
if Carrier and Carrier:IsAlive() and From == "Unboarding" then
|
if Carrier and Carrier:IsAlive() then
|
||||||
if not Cargo:IsUnLoaded() then
|
if not Cargo:IsUnLoaded() then
|
||||||
self:__Unboard( 10, Cargo, CarrierUnit, DeployZone, Defend )
|
self:__Unboard( 10, Cargo, CarrierUnit, DeployZone, Defend )
|
||||||
return
|
return
|
||||||
@ -580,4 +582,3 @@ function AI_CARGO:onafterDeployed( Carrier, From, Event, To, DeployZone, Defend
|
|||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -98,7 +98,8 @@ function AI_CARGO_APC:New( APC, CargoSet, CombatRadius )
|
|||||||
self:AddTransition( "*", "Guard", "Unloaded" )
|
self:AddTransition( "*", "Guard", "Unloaded" )
|
||||||
self:AddTransition( "*", "Home", "*" )
|
self:AddTransition( "*", "Home", "*" )
|
||||||
self:AddTransition( "*", "Reload", "Boarding" )
|
self:AddTransition( "*", "Reload", "Boarding" )
|
||||||
|
self:AddTransition( "*", "Deployed", "*" )
|
||||||
|
self:AddTransition( "*", "PickedUp", "*" )
|
||||||
self:AddTransition( "*", "Destroyed", "Destroyed" )
|
self:AddTransition( "*", "Destroyed", "Destroyed" )
|
||||||
|
|
||||||
self:SetCombatRadius( CombatRadius )
|
self:SetCombatRadius( CombatRadius )
|
||||||
|
|||||||
@ -174,8 +174,8 @@ function AI_CARGO_DISPATCHER_HELICOPTER:New( HelicopterSet, CargoSet, PickupZone
|
|||||||
self:SetPickupSpeed( 350, 150 )
|
self:SetPickupSpeed( 350, 150 )
|
||||||
self:SetDeploySpeed( 350, 150 )
|
self:SetDeploySpeed( 350, 150 )
|
||||||
|
|
||||||
self:SetPickupRadius( 0, 0 )
|
self:SetPickupRadius( 40, 12 )
|
||||||
self:SetDeployRadius( 0, 0 )
|
self:SetDeployRadius( 40, 12 )
|
||||||
|
|
||||||
self:SetPickupHeight( 500, 200 )
|
self:SetPickupHeight( 500, 200 )
|
||||||
self:SetDeployHeight( 500, 200 )
|
self:SetDeployHeight( 500, 200 )
|
||||||
@ -186,6 +186,9 @@ end
|
|||||||
|
|
||||||
function AI_CARGO_DISPATCHER_HELICOPTER:AICargo( Helicopter, CargoSet )
|
function AI_CARGO_DISPATCHER_HELICOPTER:AICargo( Helicopter, CargoSet )
|
||||||
|
|
||||||
return AI_CARGO_HELICOPTER:New( Helicopter, CargoSet )
|
local dispatcher = AI_CARGO_HELICOPTER:New( Helicopter, CargoSet )
|
||||||
|
dispatcher:SetLandingSpeedAndHeight(27, 6)
|
||||||
|
return dispatcher
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -64,20 +64,24 @@ function AI_CARGO_HELICOPTER:New( Helicopter, CargoSet )
|
|||||||
self.Zone = ZONE_GROUP:New( Helicopter:GetName(), Helicopter, 300 )
|
self.Zone = ZONE_GROUP:New( Helicopter:GetName(), Helicopter, 300 )
|
||||||
|
|
||||||
self:SetStartState( "Unloaded" )
|
self:SetStartState( "Unloaded" )
|
||||||
|
-- Boarding
|
||||||
self:AddTransition( "Unloaded", "Pickup", "*" )
|
self:AddTransition( "Unloaded", "Pickup", "Unloaded" )
|
||||||
self:AddTransition( "Loaded", "Deploy", "*" )
|
|
||||||
self:AddTransition( "*", "Loaded", "Loaded" )
|
|
||||||
self:AddTransition( "Unboarding", "Pickup", "Unloaded" )
|
|
||||||
self:AddTransition( "Unloaded", "Unboard", "Unloaded" )
|
|
||||||
self:AddTransition( "Unloaded", "Unloaded", "Unloaded" )
|
|
||||||
self:AddTransition( "*", "PickedUp", "*" )
|
|
||||||
self:AddTransition( "*", "Landed", "*" )
|
self:AddTransition( "*", "Landed", "*" )
|
||||||
|
self:AddTransition( "*", "Load", "*" )
|
||||||
|
self:AddTransition( "*", "Loaded", "Loaded" )
|
||||||
|
self:AddTransition( "Loaded", "PickedUp", "Loaded" )
|
||||||
|
|
||||||
|
-- Unboarding
|
||||||
|
self:AddTransition( "Loaded", "Deploy", "*" )
|
||||||
self:AddTransition( "*", "Queue", "*" )
|
self:AddTransition( "*", "Queue", "*" )
|
||||||
self:AddTransition( "*", "Orbit" , "*" )
|
self:AddTransition( "*", "Orbit" , "*" )
|
||||||
self:AddTransition( "*", "Home" , "*" )
|
self:AddTransition( "*", "Destroyed", "*" )
|
||||||
|
self:AddTransition( "*", "Unload", "*" )
|
||||||
|
self:AddTransition( "*", "Unloaded", "Unloaded" )
|
||||||
|
self:AddTransition( "Unloaded", "Deployed", "Unloaded" )
|
||||||
|
|
||||||
self:AddTransition( "*", "Destroyed", "Destroyed" )
|
-- RTB
|
||||||
|
self:AddTransition( "*", "Home" , "*" )
|
||||||
|
|
||||||
--- Pickup Handler OnBefore for AI_CARGO_HELICOPTER
|
--- Pickup Handler OnBefore for AI_CARGO_HELICOPTER
|
||||||
-- @function [parent=#AI_CARGO_HELICOPTER] OnBeforePickup
|
-- @function [parent=#AI_CARGO_HELICOPTER] OnBeforePickup
|
||||||
@ -207,6 +211,9 @@ function AI_CARGO_HELICOPTER:New( Helicopter, CargoSet )
|
|||||||
|
|
||||||
self:SetCarrier( Helicopter )
|
self:SetCarrier( Helicopter )
|
||||||
|
|
||||||
|
self.landingspeed = 15 -- kph
|
||||||
|
self.landingheight = 5.5 -- meter
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -255,6 +262,25 @@ function AI_CARGO_HELICOPTER:SetCarrier( Helicopter )
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Set landingspeed and -height for helicopter landings. Adjust after tracing if your helis get stuck after landing.
|
||||||
|
-- @param #AI_CARGO_HELICOPTER self
|
||||||
|
-- @param #number speed Landing speed in kph(!), e.g. 15
|
||||||
|
-- @param #number height Landing height in meters(!), e.g. 5.5
|
||||||
|
-- @return #AI_CARGO_HELICOPTER self
|
||||||
|
-- @usage If your choppers get stuck, add tracing to your script to determine if they hit the right parameters like so:
|
||||||
|
--
|
||||||
|
-- BASE:TraceOn()
|
||||||
|
-- BASE:TraceClass("AI_CARGO_HELICOPTER")
|
||||||
|
--
|
||||||
|
-- Watch the DCS.log for entries stating `Helicopter:<name>, Height = Helicopter:<number>, Velocity = Helicopter:<number>`
|
||||||
|
-- Adjust if necessary.
|
||||||
|
function AI_CARGO_HELICOPTER:SetLandingSpeedAndHeight(speed, height)
|
||||||
|
local _speed = speed or 15
|
||||||
|
local _height = height or 5.5
|
||||||
|
self.landingheight = _height
|
||||||
|
self.landingspeed = _speed
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- @param #AI_CARGO_HELICOPTER self
|
--- @param #AI_CARGO_HELICOPTER self
|
||||||
-- @param Wrapper.Group#GROUP Helicopter
|
-- @param Wrapper.Group#GROUP Helicopter
|
||||||
@ -271,13 +297,13 @@ function AI_CARGO_HELICOPTER:onafterLanded( Helicopter, From, Event, To )
|
|||||||
-- 1 - When the helo lands normally on the ground.
|
-- 1 - When the helo lands normally on the ground.
|
||||||
-- 2 - when the helo is hit and goes RTB or even when it is destroyed.
|
-- 2 - when the helo is hit and goes RTB or even when it is destroyed.
|
||||||
-- For point 2, this is an issue, the infantry may not unload in this case!
|
-- For point 2, this is an issue, the infantry may not unload in this case!
|
||||||
-- So we check if the helo is on the ground, and velocity< 5.
|
-- So we check if the helo is on the ground, and velocity< 15.
|
||||||
-- Only then the infantry can unload (and load too, for consistency)!
|
-- Only then the infantry can unload (and load too, for consistency)!
|
||||||
|
|
||||||
self:F( { Helicopter:GetName(), Height = Helicopter:GetHeight( true ), Velocity = Helicopter:GetVelocityKMH() } )
|
self:T( { Helicopter:GetName(), Height = Helicopter:GetHeight( true ), Velocity = Helicopter:GetVelocityKMH() } )
|
||||||
|
|
||||||
if self.RoutePickup == true then
|
if self.RoutePickup == true then
|
||||||
if Helicopter:GetHeight( true ) <= 5.5 and Helicopter:GetVelocityKMH() < 15 then
|
if Helicopter:GetHeight( true ) <= self.landingheight then --and Helicopter:GetVelocityKMH() < self.landingspeed then
|
||||||
--self:Load( Helicopter:GetPointVec2() )
|
--self:Load( Helicopter:GetPointVec2() )
|
||||||
self:Load( self.PickupZone )
|
self:Load( self.PickupZone )
|
||||||
self.RoutePickup = false
|
self.RoutePickup = false
|
||||||
@ -285,7 +311,7 @@ function AI_CARGO_HELICOPTER:onafterLanded( Helicopter, From, Event, To )
|
|||||||
end
|
end
|
||||||
|
|
||||||
if self.RouteDeploy == true then
|
if self.RouteDeploy == true then
|
||||||
if Helicopter:GetHeight( true ) <= 5.5 and Helicopter:GetVelocityKMH() < 15 then
|
if Helicopter:GetHeight( true ) <= self.landingheight then --and Helicopter:GetVelocityKMH() < self.landingspeed then
|
||||||
self:Unload( self.DeployZone )
|
self:Unload( self.DeployZone )
|
||||||
self.RouteDeploy = false
|
self.RouteDeploy = false
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1881,7 +1881,7 @@ do -- COORDINATE
|
|||||||
|
|
||||||
--- Big smoke and fire at the coordinate.
|
--- Big smoke and fire at the coordinate.
|
||||||
-- @param #COORDINATE self
|
-- @param #COORDINATE self
|
||||||
-- @param Utilities.Utils#BIGSMOKEPRESET preset Smoke preset (0=small smoke and fire, 1=medium smoke and fire, 2=large smoke and fire, 3=huge smoke and fire, 4=small smoke, 5=medium smoke, 6=large smoke, 7=huge smoke).
|
-- @param Utilities.Utils#BIGSMOKEPRESET preset Smoke preset (1=small smoke and fire, 2=medium smoke and fire, 3=large smoke and fire, 4=huge smoke and fire, 5=small smoke, 6=medium smoke, 7=large smoke, 8=huge smoke).
|
||||||
-- @param #number density (Optional) Smoke density. Number in [0,...,1]. Default 0.5.
|
-- @param #number density (Optional) Smoke density. Number in [0,...,1]. Default 0.5.
|
||||||
function COORDINATE:BigSmokeAndFire( preset, density )
|
function COORDINATE:BigSmokeAndFire( preset, density )
|
||||||
self:F2( { preset=preset, density=density } )
|
self:F2( { preset=preset, density=density } )
|
||||||
|
|||||||
@ -4043,6 +4043,24 @@ do -- SET_CLIENT
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Iterate the SET_CLIENT and count alive units.
|
||||||
|
-- @param #SET_CLIENT self
|
||||||
|
-- @return #number count
|
||||||
|
function SET_CLIENT:CountAlive()
|
||||||
|
|
||||||
|
local Set = self:GetSet()
|
||||||
|
|
||||||
|
local CountU = 0
|
||||||
|
for UnitID, UnitData in pairs(Set) do -- For each GROUP in SET_GROUP
|
||||||
|
if UnitData and UnitData:IsAlive() then
|
||||||
|
CountU = CountU + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
return CountU
|
||||||
|
end
|
||||||
|
|
||||||
---
|
---
|
||||||
-- @param #SET_CLIENT self
|
-- @param #SET_CLIENT self
|
||||||
-- @param Wrapper.Client#CLIENT MClient
|
-- @param Wrapper.Client#CLIENT MClient
|
||||||
@ -4790,7 +4808,7 @@ do -- SET_AIRBASE
|
|||||||
|
|
||||||
local airbaseName, airbase=self:FindInDatabase(EventData)
|
local airbaseName, airbase=self:FindInDatabase(EventData)
|
||||||
|
|
||||||
if airbase and airbase:IsShip() or airbase:IsHelipad() then
|
if airbase and (airbase:IsShip() or airbase:IsHelipad()) then
|
||||||
self:RemoveAirbasesByName(airbaseName)
|
self:RemoveAirbasesByName(airbaseName)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -422,7 +422,11 @@ function SPAWNSTATIC:_SpawnStatic(Template, CountryID)
|
|||||||
end
|
end
|
||||||
|
|
||||||
if self.InitCargo~=nil then
|
if self.InitCargo~=nil then
|
||||||
Template.isCargo=self.InitCargo
|
Template.canCargo=self.InitCargo
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.InitCargoMass~=nil then
|
||||||
|
Template.mass=self.InitCargoMass
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.InitLinkUnit then
|
if self.InitLinkUnit then
|
||||||
|
|||||||
@ -183,12 +183,12 @@ function ZONE_BASE:IsCoordinateInZone( Coordinate )
|
|||||||
return InZone
|
return InZone
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Returns if a PointVec2 is within the zone.
|
--- Returns if a PointVec2 is within the zone. (Name is misleading, actually takes a #COORDINATE)
|
||||||
-- @param #ZONE_BASE self
|
-- @param #ZONE_BASE self
|
||||||
-- @param Core.Point#POINT_VEC2 PointVec2 The PointVec2 to test.
|
-- @param Core.Point#COORDINATE PointVec2 The coordinate to test.
|
||||||
-- @return #boolean true if the PointVec2 is within the zone.
|
-- @return #boolean true if the PointVec2 is within the zone.
|
||||||
function ZONE_BASE:IsPointVec2InZone( PointVec2 )
|
function ZONE_BASE:IsPointVec2InZone( Coordinate )
|
||||||
local InZone = self:IsVec2InZone( PointVec2:GetVec2() )
|
local InZone = self:IsVec2InZone( Coordinate:GetVec2() )
|
||||||
return InZone
|
return InZone
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -1707,8 +1707,8 @@ end
|
|||||||
--- Returns the unit of a player and the player name. If the unit does not belong to a player, nil is returned.
|
--- Returns the unit of a player and the player name. If the unit does not belong to a player, nil is returned.
|
||||||
-- @param #FOX self
|
-- @param #FOX self
|
||||||
-- @param DCS#Weapon weapon The weapon.
|
-- @param DCS#Weapon weapon The weapon.
|
||||||
-- @return #number Notching heading right, i.e. missile heading +90<EFBFBD>
|
-- @return #number Notching heading right, i.e. missile heading +90°.
|
||||||
-- @return #number Notching heading left, i.e. missile heading -90<EFBFBD>.
|
-- @return #number Notching heading left, i.e. missile heading -90°.
|
||||||
function FOX:_GetNotchingHeadings(weapon)
|
function FOX:_GetNotchingHeadings(weapon)
|
||||||
|
|
||||||
if weapon then
|
if weapon then
|
||||||
|
|||||||
@ -23,9 +23,9 @@
|
|||||||
-- Date: July 2021
|
-- Date: July 2021
|
||||||
|
|
||||||
-------------------------------------------------------------------------
|
-------------------------------------------------------------------------
|
||||||
--- **MANTIS** class, extends #Core.Base#BASE
|
--- **MANTIS** class, extends Core.Base#BASE
|
||||||
-- @type MANTIS
|
-- @type MANTIS
|
||||||
-- @field #string Classname
|
-- @field #string ClassName
|
||||||
-- @field #string name Name of this Mantis
|
-- @field #string name Name of this Mantis
|
||||||
-- @field #string SAM_Templates_Prefix Prefix to build the #SET_GROUP for SAM sites
|
-- @field #string SAM_Templates_Prefix Prefix to build the #SET_GROUP for SAM sites
|
||||||
-- @field Core.Set#SET_GROUP SAM_Group The SAM #SET_GROUP
|
-- @field Core.Set#SET_GROUP SAM_Group The SAM #SET_GROUP
|
||||||
@ -59,7 +59,7 @@
|
|||||||
-- @extends Core.Base#BASE
|
-- @extends Core.Base#BASE
|
||||||
|
|
||||||
|
|
||||||
--- *The worst thing that can happen to a good cause is, not to be skillfully attacked, but to be ineptly defended.* - Frédéric Bastiat
|
--- *The worst thing that can happen to a good cause is, not to be skillfully attacked, but to be ineptly defended.* - Frédéric Bastiat
|
||||||
--
|
--
|
||||||
-- Simple Class for a more intelligent Air Defense System
|
-- Simple Class for a more intelligent Air Defense System
|
||||||
--
|
--
|
||||||
@ -197,6 +197,7 @@ MANTIS = {
|
|||||||
SamStateTracker = {},
|
SamStateTracker = {},
|
||||||
DLink = false,
|
DLink = false,
|
||||||
DLTimeStamp = 0,
|
DLTimeStamp = 0,
|
||||||
|
Padding = 10,
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Advanced state enumerator
|
--- Advanced state enumerator
|
||||||
@ -221,7 +222,8 @@ do
|
|||||||
--@param #string coaltion Coalition side of your setup, e.g. "blue", "red" or "neutral"
|
--@param #string coaltion Coalition side of your setup, e.g. "blue", "red" or "neutral"
|
||||||
--@param #boolean dynamic Use constant (true) filtering or just filter once (false, default) (optional)
|
--@param #boolean dynamic Use constant (true) filtering or just filter once (false, default) (optional)
|
||||||
--@param #string awacs Group name of your Awacs (optional)
|
--@param #string awacs Group name of your Awacs (optional)
|
||||||
--@param #boolean EmOnOff Make MANTIS switch Emissions on and off instead of changing the alarm state between RED and GREEN
|
--@param #boolean EmOnOff Make MANTIS switch Emissions on and off instead of changing the alarm state between RED and GREEN (optional)
|
||||||
|
--@param #number Padding For #SEAD - Extra number of seconds to add to radar switch-back-on time (optional)
|
||||||
--@return #MANTIS self
|
--@return #MANTIS self
|
||||||
--@usage Start up your MANTIS with a basic setting
|
--@usage Start up your MANTIS with a basic setting
|
||||||
--
|
--
|
||||||
@ -243,7 +245,7 @@ do
|
|||||||
-- `mybluemantis = MANTIS:New("bluemantis","Blue SAM","Blue EWR",nil,"blue",false,"Blue Awacs")`
|
-- `mybluemantis = MANTIS:New("bluemantis","Blue SAM","Blue EWR",nil,"blue",false,"Blue Awacs")`
|
||||||
-- `mybluemantis:Start()`
|
-- `mybluemantis:Start()`
|
||||||
--
|
--
|
||||||
function MANTIS:New(name,samprefix,ewrprefix,hq,coaltion,dynamic,awacs, EmOnOff)
|
function MANTIS:New(name,samprefix,ewrprefix,hq,coaltion,dynamic,awacs, EmOnOff, Padding)
|
||||||
|
|
||||||
-- DONE: Create some user functions for these
|
-- DONE: Create some user functions for these
|
||||||
-- DONE: Make HQ useful
|
-- DONE: Make HQ useful
|
||||||
@ -281,6 +283,7 @@ do
|
|||||||
self.state2flag = false
|
self.state2flag = false
|
||||||
self.SamStateTracker = {} -- table to hold alert states, so we don't trigger state changes twice in adv mode
|
self.SamStateTracker = {} -- table to hold alert states, so we don't trigger state changes twice in adv mode
|
||||||
self.DLink = false
|
self.DLink = false
|
||||||
|
self.Padding = Padding or 10
|
||||||
|
|
||||||
if EmOnOff then
|
if EmOnOff then
|
||||||
if EmOnOff == false then
|
if EmOnOff == false then
|
||||||
@ -596,7 +599,7 @@ do
|
|||||||
-- E.g. `mymantis:SetAdvancedMode(true, 90)`
|
-- E.g. `mymantis:SetAdvancedMode(true, 90)`
|
||||||
function MANTIS:SetAdvancedMode(onoff, ratio)
|
function MANTIS:SetAdvancedMode(onoff, ratio)
|
||||||
self:T(self.lid .. "SetAdvancedMode")
|
self:T(self.lid .. "SetAdvancedMode")
|
||||||
--self.T({onoff, ratio})
|
--self:T({onoff, ratio})
|
||||||
local onoff = onoff or false
|
local onoff = onoff or false
|
||||||
local ratio = ratio or 100
|
local ratio = ratio or 100
|
||||||
if (type(self.HQ_Template_CC) == "string") and onoff and self.dynamic then
|
if (type(self.HQ_Template_CC) == "string") and onoff and self.dynamic then
|
||||||
@ -647,10 +650,10 @@ do
|
|||||||
local hqgrp = GROUP:FindByName(hq)
|
local hqgrp = GROUP:FindByName(hq)
|
||||||
if hqgrp then
|
if hqgrp then
|
||||||
if hqgrp:IsAlive() then -- ok we're on, hq exists and as alive
|
if hqgrp:IsAlive() then -- ok we're on, hq exists and as alive
|
||||||
--self.T(self.lid.." HQ is alive!")
|
--self:T(self.lid.." HQ is alive!")
|
||||||
return true
|
return true
|
||||||
else
|
else
|
||||||
--self.T(self.lid.." HQ is dead!")
|
--self:T(self.lid.." HQ is dead!")
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -664,7 +667,7 @@ do
|
|||||||
function MANTIS:_CheckEWRState()
|
function MANTIS:_CheckEWRState()
|
||||||
self:T(self.lid .. "CheckEWRState")
|
self:T(self.lid .. "CheckEWRState")
|
||||||
local text = self.lid.." Checking EWR State"
|
local text = self.lid.." Checking EWR State"
|
||||||
--self.T(text)
|
--self:T(text)
|
||||||
local m= MESSAGE:New(text,10,"MANTIS"):ToAllIf(self.debug)
|
local m= MESSAGE:New(text,10,"MANTIS"):ToAllIf(self.debug)
|
||||||
if self.verbose then self:I(text) end
|
if self.verbose then self:I(text) end
|
||||||
-- start check
|
-- start check
|
||||||
@ -680,7 +683,7 @@ do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
--self.T(self.lid..string.format(" No of EWR alive is %d", nalive))
|
--self:T(self.lid..string.format(" No of EWR alive is %d", nalive))
|
||||||
if nalive > 0 then
|
if nalive > 0 then
|
||||||
return true
|
return true
|
||||||
else
|
else
|
||||||
@ -717,7 +720,7 @@ do
|
|||||||
local newinterval = interval + (interval * ratio) -- e.g. 30+(30*1.6) = 78
|
local newinterval = interval + (interval * ratio) -- e.g. 30+(30*1.6) = 78
|
||||||
if self.debug or self.verbose then
|
if self.debug or self.verbose then
|
||||||
local text = self.lid..string.format(" Calculated OldState/NewState/Interval: %d / %d / %d", currstate, self.adv_state, newinterval)
|
local text = self.lid..string.format(" Calculated OldState/NewState/Interval: %d / %d / %d", currstate, self.adv_state, newinterval)
|
||||||
--self.T(text)
|
--self:T(text)
|
||||||
local m=MESSAGE:New(text,10,"MANTIS"):ToAllIf(self.debug)
|
local m=MESSAGE:New(text,10,"MANTIS"):ToAllIf(self.debug)
|
||||||
if self.verbose then self:I(text) end
|
if self.verbose then self:I(text) end
|
||||||
end
|
end
|
||||||
@ -730,13 +733,13 @@ do
|
|||||||
-- @param #boolean ewr If true, will relocate EWR objects
|
-- @param #boolean ewr If true, will relocate EWR objects
|
||||||
function MANTIS:SetAutoRelocate(hq, ewr)
|
function MANTIS:SetAutoRelocate(hq, ewr)
|
||||||
self:T(self.lid .. "SetAutoRelocate")
|
self:T(self.lid .. "SetAutoRelocate")
|
||||||
--self.T({hq, ewr})
|
--self:T({hq, ewr})
|
||||||
local hqrel = hq or false
|
local hqrel = hq or false
|
||||||
local ewrel = ewr or false
|
local ewrel = ewr or false
|
||||||
if hqrel or ewrel then
|
if hqrel or ewrel then
|
||||||
self.autorelocate = true
|
self.autorelocate = true
|
||||||
self.autorelocateunits = { HQ = hqrel, EWR = ewrel }
|
self.autorelocateunits = { HQ = hqrel, EWR = ewrel }
|
||||||
--self.T({self.autorelocate, self.autorelocateunits})
|
--self:T({self.autorelocate, self.autorelocateunits})
|
||||||
end
|
end
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
@ -753,7 +756,7 @@ do
|
|||||||
local HQGroup = self.HQ_CC
|
local HQGroup = self.HQ_CC
|
||||||
if self.autorelocateunits.HQ and self.HQ_CC and HQGroup:IsAlive() then --only relocate if HQ exists
|
if self.autorelocateunits.HQ and self.HQ_CC and HQGroup:IsAlive() then --only relocate if HQ exists
|
||||||
local _hqgrp = self.HQ_CC
|
local _hqgrp = self.HQ_CC
|
||||||
--self.T(self.lid.." Relocating HQ")
|
--self:T(self.lid.." Relocating HQ")
|
||||||
local text = self.lid.." Relocating HQ"
|
local text = self.lid.." Relocating HQ"
|
||||||
--local m= MESSAGE:New(text,10,"MANTIS"):ToAll()
|
--local m= MESSAGE:New(text,10,"MANTIS"):ToAll()
|
||||||
_hqgrp:RelocateGroundRandomInRadius(20,500,true,true)
|
_hqgrp:RelocateGroundRandomInRadius(20,500,true,true)
|
||||||
@ -766,7 +769,7 @@ do
|
|||||||
local EWR_Grps = EWR_GRP.Set --table of objects in SET_GROUP
|
local EWR_Grps = EWR_GRP.Set --table of objects in SET_GROUP
|
||||||
for _,_grp in pairs (EWR_Grps) do
|
for _,_grp in pairs (EWR_Grps) do
|
||||||
if _grp:IsAlive() and _grp:IsGround() then
|
if _grp:IsAlive() and _grp:IsGround() then
|
||||||
--self.T(self.lid.." Relocating EWR ".._grp:GetName())
|
--self:T(self.lid.." Relocating EWR ".._grp:GetName())
|
||||||
local text = self.lid.." Relocating EWR ".._grp:GetName()
|
local text = self.lid.." Relocating EWR ".._grp:GetName()
|
||||||
local m= MESSAGE:New(text,10,"MANTIS"):ToAllIf(self.debug)
|
local m= MESSAGE:New(text,10,"MANTIS"):ToAllIf(self.debug)
|
||||||
if self.verbose then self:I(text) end
|
if self.verbose then self:I(text) end
|
||||||
@ -904,7 +907,7 @@ do
|
|||||||
end
|
end
|
||||||
self.SAM_Table = SAM_Tbl
|
self.SAM_Table = SAM_Tbl
|
||||||
-- make SAMs evasive
|
-- make SAMs evasive
|
||||||
local mysead = SEAD:New( SEAD_Grps )
|
local mysead = SEAD:New( SEAD_Grps, self.Padding ) -- Functional.Sead#SEAD
|
||||||
mysead:SetEngagementRange(engagerange)
|
mysead:SetEngagementRange(engagerange)
|
||||||
self.mysead = mysead
|
self.mysead = mysead
|
||||||
return self
|
return self
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
-- ## Features:
|
-- ## Features:
|
||||||
--
|
--
|
||||||
-- * Track the missiles fired at you and other players, providing bearing and range information of the missiles towards the airplanes.
|
-- * Track the missiles fired at you and other players, providing bearing and range information of the missiles towards the airplanes.
|
||||||
-- * Provide alerts of missile launches, including detailed information of the units launching, including bearing, range <20>
|
-- * Provide alerts of missile launches, including detailed information of the units launching, including bearing, range
|
||||||
-- * Provide alerts when a missile would have killed your aircraft.
|
-- * Provide alerts when a missile would have killed your aircraft.
|
||||||
-- * Provide alerts when the missile self destructs.
|
-- * Provide alerts when the missile self destructs.
|
||||||
-- * Enable / Disable and Configure the Missile Trainer using the various menu options.
|
-- * Enable / Disable and Configure the Missile Trainer using the various menu options.
|
||||||
|
|||||||
@ -5371,7 +5371,7 @@ function RAT:_ModifySpawnTemplate(waypoints, livery, spawnplace, departure, take
|
|||||||
|
|
||||||
if spawnonground then
|
if spawnonground then
|
||||||
|
|
||||||
-- Sh<EFBFBD>ps and FARPS seem to have a build in queue.
|
-- Ships and FARPS seem to have a build in queue.
|
||||||
if spawnonship or spawnonfarp or spawnonrunway or automatic then
|
if spawnonship or spawnonfarp or spawnonrunway or automatic then
|
||||||
self:T(RAT.id..string.format("RAT group %s spawning at farp, ship or runway %s.", self.alias, departure:GetName()))
|
self:T(RAT.id..string.format("RAT group %s spawning at farp, ship or runway %s.", self.alias, departure:GetName()))
|
||||||
|
|
||||||
@ -6145,4 +6145,3 @@ function RATMANAGER:_RollDice(nrat,ntot,min,alive)
|
|||||||
-- Return number of groups to be spawned.
|
-- Return number of groups to be spawned.
|
||||||
return N
|
return N
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -32,7 +32,9 @@
|
|||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ## Missions: Example missions will be added later.
|
-- ## Missions:
|
||||||
|
--
|
||||||
|
-- * [MAR - On the Range - MOOSE - SC](https://www.digitalcombatsimulator.com/en/files/3317765/) by shagrat
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
@ -2558,7 +2560,7 @@ function RANGE:_DisplayBombTargets(_unitname)
|
|||||||
-- Get elevation
|
-- Get elevation
|
||||||
local elevation=coord:GetLandHeight()
|
local elevation=coord:GetLandHeight()
|
||||||
local eltxt=string.format("%d m", elevation)
|
local eltxt=string.format("%d m", elevation)
|
||||||
if _settings:IsImperial() then
|
if not _settings:IsMetric() then
|
||||||
elevation=UTILS.MetersToFeet(elevation)
|
elevation=UTILS.MetersToFeet(elevation)
|
||||||
eltxt=string.format("%d ft", elevation)
|
eltxt=string.format("%d ft", elevation)
|
||||||
end
|
end
|
||||||
@ -2829,6 +2831,7 @@ function RANGE:_CheckInZone(_unitName)
|
|||||||
local accur=0
|
local accur=0
|
||||||
if shots>0 then
|
if shots>0 then
|
||||||
accur=_result.hits/shots*100
|
accur=_result.hits/shots*100
|
||||||
|
if accur > 100 then accur = 100 end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Message text.
|
-- Message text.
|
||||||
|
|||||||
@ -17,14 +17,15 @@
|
|||||||
--
|
--
|
||||||
-- ### Authors: **FlightControl**, **applevangelist**
|
-- ### Authors: **FlightControl**, **applevangelist**
|
||||||
--
|
--
|
||||||
-- Last Update: July 2021
|
-- Last Update: Aug 2021
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- @module Functional.Sead
|
-- @module Functional.Sead
|
||||||
-- @image SEAD.JPG
|
-- @image SEAD.JPG
|
||||||
|
|
||||||
--- @type SEAD
|
---
|
||||||
|
-- @type SEAD
|
||||||
-- @extends Core.Base#BASE
|
-- @extends Core.Base#BASE
|
||||||
|
|
||||||
--- Make SAM sites execute evasive and defensive behaviour when being fired upon.
|
--- Make SAM sites execute evasive and defensive behaviour when being fired upon.
|
||||||
@ -48,7 +49,8 @@ SEAD = {
|
|||||||
},
|
},
|
||||||
SEADGroupPrefixes = {},
|
SEADGroupPrefixes = {},
|
||||||
SuppressedGroups = {},
|
SuppressedGroups = {},
|
||||||
EngagementRange = 75 -- default 75% engagement range Feature Request #1355
|
EngagementRange = 75, -- default 75% engagement range Feature Request #1355
|
||||||
|
Padding = 10,
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Missile enumerators
|
--- Missile enumerators
|
||||||
@ -59,7 +61,7 @@ SEAD = {
|
|||||||
["AGM_122"] = "AGM_122",
|
["AGM_122"] = "AGM_122",
|
||||||
["AGM_84"] = "AGM_84",
|
["AGM_84"] = "AGM_84",
|
||||||
["AGM_45"] = "AGM_45",
|
["AGM_45"] = "AGM_45",
|
||||||
["ALARN"] = "ALARM",
|
["ALARM"] = "ALARM",
|
||||||
["LD-10"] = "LD-10",
|
["LD-10"] = "LD-10",
|
||||||
["X_58"] = "X_58",
|
["X_58"] = "X_58",
|
||||||
["X_28"] = "X_28",
|
["X_28"] = "X_28",
|
||||||
@ -68,17 +70,35 @@ SEAD = {
|
|||||||
["Kh25"] = "Kh25",
|
["Kh25"] = "Kh25",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
--- Missile enumerators - from DCS ME and Wikipedia
|
||||||
|
-- @field HarmData
|
||||||
|
SEAD.HarmData = {
|
||||||
|
-- km and mach
|
||||||
|
["AGM_88"] = { 150, 3},
|
||||||
|
["AGM_45"] = { 12, 2},
|
||||||
|
["AGM_122"] = { 16.5, 2.3},
|
||||||
|
["AGM_84"] = { 280, 0.85},
|
||||||
|
["ALARM"] = { 45, 2},
|
||||||
|
["LD-10"] = { 60, 4},
|
||||||
|
["X_58"] = { 70, 4},
|
||||||
|
["X_28"] = { 80, 2.5},
|
||||||
|
["X_25"] = { 25, 0.76},
|
||||||
|
["X_31"] = {150, 3},
|
||||||
|
["Kh25"] = {25, 0.8},
|
||||||
|
}
|
||||||
|
|
||||||
--- Creates the main object which is handling defensive actions for SA sites or moving SA vehicles.
|
--- Creates the main object which is handling defensive actions for SA sites or moving SA vehicles.
|
||||||
-- When an anti radiation missile is fired (KH-58, KH-31P, KH-31A, KH-25MPU, HARM missiles), the SA will shut down their radars and will take evasive actions...
|
-- When an anti radiation missile is fired (KH-58, KH-31P, KH-31A, KH-25MPU, HARM missiles), the SA will shut down their radars and will take evasive actions...
|
||||||
-- Chances are big that the missile will miss.
|
-- Chances are big that the missile will miss.
|
||||||
-- @param #SEAD self
|
-- @param #SEAD self
|
||||||
-- @param table{string,...}|string SEADGroupPrefixes which is a table of Prefixes of the SA Groups in the DCS mission editor on which evasive actions need to be taken.
|
-- @param #table SEADGroupPrefixes Table of #string entries or single #string, which is a table of Prefixes of the SA Groups in the DCS mission editor on which evasive actions need to be taken.
|
||||||
-- @return SEAD
|
-- @param #number Padding (Optional) Extra number of seconds to add to radar switch-back-on time
|
||||||
|
-- @return #SEAD self
|
||||||
-- @usage
|
-- @usage
|
||||||
-- -- CCCP SEAD Defenses
|
-- -- CCCP SEAD Defenses
|
||||||
-- -- Defends the Russian SA installations from SEAD attacks.
|
-- -- Defends the Russian SA installations from SEAD attacks.
|
||||||
-- SEAD_RU_SAM_Defenses = SEAD:New( { 'RU SA-6 Kub', 'RU SA-6 Defenses', 'RU MI-26 Troops', 'RU Attack Gori' } )
|
-- SEAD_RU_SAM_Defenses = SEAD:New( { 'RU SA-6 Kub', 'RU SA-6 Defenses', 'RU MI-26 Troops', 'RU Attack Gori' } )
|
||||||
function SEAD:New( SEADGroupPrefixes )
|
function SEAD:New( SEADGroupPrefixes, Padding )
|
||||||
|
|
||||||
local self = BASE:Inherit( self, BASE:New() )
|
local self = BASE:Inherit( self, BASE:New() )
|
||||||
self:F( SEADGroupPrefixes )
|
self:F( SEADGroupPrefixes )
|
||||||
@ -91,8 +111,13 @@ function SEAD:New( SEADGroupPrefixes )
|
|||||||
self.SEADGroupPrefixes[SEADGroupPrefixes] = SEADGroupPrefixes
|
self.SEADGroupPrefixes[SEADGroupPrefixes] = SEADGroupPrefixes
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local padding = Padding or 10
|
||||||
|
if padding < 10 then padding = 10 end
|
||||||
|
self.Padding = padding
|
||||||
|
|
||||||
self:HandleEvent( EVENTS.Shot, self.HandleEventShot )
|
self:HandleEvent( EVENTS.Shot, self.HandleEventShot )
|
||||||
self:I("*** SEAD - Started Version 0.2.8")
|
|
||||||
|
self:I("*** SEAD - Started Version 0.3.1")
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -102,7 +127,7 @@ end
|
|||||||
-- @return #SEAD self
|
-- @return #SEAD self
|
||||||
function SEAD:UpdateSet( SEADGroupPrefixes )
|
function SEAD:UpdateSet( SEADGroupPrefixes )
|
||||||
|
|
||||||
self:F( SEADGroupPrefixes )
|
self:T( SEADGroupPrefixes )
|
||||||
|
|
||||||
if type( SEADGroupPrefixes ) == 'table' then
|
if type( SEADGroupPrefixes ) == 'table' then
|
||||||
for SEADGroupPrefixID, SEADGroupPrefix in pairs( SEADGroupPrefixes ) do
|
for SEADGroupPrefixID, SEADGroupPrefix in pairs( SEADGroupPrefixes ) do
|
||||||
@ -118,9 +143,9 @@ end
|
|||||||
--- Sets the engagement range of the SAMs. Defaults to 75% to make it more deadly. Feature Request #1355
|
--- Sets the engagement range of the SAMs. Defaults to 75% to make it more deadly. Feature Request #1355
|
||||||
-- @param #SEAD self
|
-- @param #SEAD self
|
||||||
-- @param #number range Set the engagement range in percent, e.g. 50
|
-- @param #number range Set the engagement range in percent, e.g. 50
|
||||||
-- @return self
|
-- @return #SEAD self
|
||||||
function SEAD:SetEngagementRange(range)
|
function SEAD:SetEngagementRange(range)
|
||||||
self:F( { range } )
|
self:T( { range } )
|
||||||
range = range or 75
|
range = range or 75
|
||||||
if range < 0 or range > 100 then
|
if range < 0 or range > 100 then
|
||||||
range = 75
|
range = 75
|
||||||
@ -130,53 +155,102 @@ function SEAD:SetEngagementRange(range)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Set the padding in seconds, which extends the radar off time calculated by SEAD
|
||||||
|
-- @param #SEAD self
|
||||||
|
-- @param #number Padding Extra number of seconds to add for the switch-on
|
||||||
|
-- @return #SEAD self
|
||||||
|
function SEAD:SetPadding(Padding)
|
||||||
|
self:T( { Padding } )
|
||||||
|
local padding = Padding or 10
|
||||||
|
if padding < 10 then padding = 10 end
|
||||||
|
self.Padding = padding
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- Check if a known HARM was fired
|
--- Check if a known HARM was fired
|
||||||
-- @param #SEAD self
|
-- @param #SEAD self
|
||||||
-- @param #string WeaponName
|
-- @param #string WeaponName
|
||||||
-- @return #boolean Returns true for a match
|
-- @return #boolean Returns true for a match
|
||||||
|
-- @return #string name Name of hit in table
|
||||||
function SEAD:_CheckHarms(WeaponName)
|
function SEAD:_CheckHarms(WeaponName)
|
||||||
self:F( { WeaponName } )
|
self:T( { WeaponName } )
|
||||||
local hit = false
|
local hit = false
|
||||||
|
local name = ""
|
||||||
for _,_name in pairs (SEAD.Harms) do
|
for _,_name in pairs (SEAD.Harms) do
|
||||||
if string.find(WeaponName,_name,1) then hit = true end
|
if string.find(WeaponName,_name,1) then
|
||||||
|
hit = true
|
||||||
|
name = _name
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return hit, name
|
||||||
|
end
|
||||||
|
|
||||||
|
--- (Internal) Return distance in meters between two coordinates or -1 on error.
|
||||||
|
-- @param #SEAD self
|
||||||
|
-- @param Core.Point#COORDINATE _point1 Coordinate one
|
||||||
|
-- @param Core.Point#COORDINATE _point2 Coordinate two
|
||||||
|
-- @return #number Distance in meters
|
||||||
|
function SEAD:_GetDistance(_point1, _point2)
|
||||||
|
self:T("_GetDistance")
|
||||||
|
if _point1 and _point2 then
|
||||||
|
local distance1 = _point1:Get2DDistance(_point2)
|
||||||
|
local distance2 = _point1:DistanceFromPointVec2(_point2)
|
||||||
|
--self:T({dist1=distance1, dist2=distance2})
|
||||||
|
if distance1 and type(distance1) == "number" then
|
||||||
|
return distance1
|
||||||
|
elseif distance2 and type(distance2) == "number" then
|
||||||
|
return distance2
|
||||||
|
else
|
||||||
|
self:E("*****Cannot calculate distance!")
|
||||||
|
self:E({_point1,_point2})
|
||||||
|
return -1
|
||||||
|
end
|
||||||
|
else
|
||||||
|
self:E("******Cannot calculate distance!")
|
||||||
|
self:E({_point1,_point2})
|
||||||
|
return -1
|
||||||
end
|
end
|
||||||
return hit
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Detects if an SAM site was shot with an anti radiation missile. In this case, take evasive actions based on the skill level set within the ME.
|
--- Detects if an SAM site was shot with an anti radiation missile. In this case, take evasive actions based on the skill level set within the ME.
|
||||||
-- @see SEAD
|
-- @see SEAD
|
||||||
-- @param #SEAD
|
-- @param #SEAD
|
||||||
-- @param Core.Event#EVENTDATA EventData
|
-- @param Core.Event#EVENTDATA EventData
|
||||||
|
-- @return #SEAD self
|
||||||
function SEAD:HandleEventShot( EventData )
|
function SEAD:HandleEventShot( EventData )
|
||||||
self:T( { EventData } )
|
self:T( { EventData.id } )
|
||||||
|
local SEADPlane = EventData.IniUnit -- Wrapper.Unit#UNIT
|
||||||
|
local SEADPlanePos = SEADPlane:GetCoordinate() -- Core.Point#COORDINATE
|
||||||
local SEADUnit = EventData.IniDCSUnit
|
local SEADUnit = EventData.IniDCSUnit
|
||||||
local SEADUnitName = EventData.IniDCSUnitName
|
local SEADUnitName = EventData.IniDCSUnitName
|
||||||
local SEADWeapon = EventData.Weapon -- Identify the weapon fired
|
local SEADWeapon = EventData.Weapon -- Identify the weapon fired
|
||||||
local SEADWeaponName = EventData.WeaponName -- return weapon type
|
local SEADWeaponName = EventData.WeaponName -- return weapon type
|
||||||
|
|
||||||
self:T( "*** SEAD - Missile Launched = " .. SEADWeaponName)
|
self:T( "*** SEAD - Missile Launched = " .. SEADWeaponName)
|
||||||
self:T({ SEADWeapon })
|
--self:T({ SEADWeapon })
|
||||||
|
|
||||||
if self:_CheckHarms(SEADWeaponName) then
|
if self:_CheckHarms(SEADWeaponName) then
|
||||||
|
self:T( '*** SEAD - Weapon Match' )
|
||||||
local _targetskill = "Random"
|
local _targetskill = "Random"
|
||||||
local _targetMimgroupName = "none"
|
local _targetgroupname = "none"
|
||||||
local _evade = math.random (1,100) -- random number for chance of evading action
|
local _target = EventData.Weapon:getTarget() -- Identify target
|
||||||
local _targetMim = EventData.Weapon:getTarget() -- Identify target
|
local _targetUnit = UNIT:Find(_target) -- Wrapper.Unit#UNIT
|
||||||
local _targetUnit = UNIT:Find(_targetMim) -- Unit name by DCS Object
|
local _targetgroup = nil -- Wrapper.Group#GROUP
|
||||||
if _targetUnit and _targetUnit:IsAlive() then
|
if _targetUnit and _targetUnit:IsAlive() then
|
||||||
local _targetMimgroup = _targetUnit:GetGroup()
|
_targetgroup = _targetUnit:GetGroup()
|
||||||
local _targetMimgroupName = _targetMimgroup:GetName() -- group name
|
_targetgroupname = _targetgroup:GetName() -- group name
|
||||||
--local _targetskill = _DATABASE.Templates.Units[_targetUnit].Template.skill
|
local _targetUnitName = _targetUnit:GetName()
|
||||||
self:T( self.SEADGroupPrefixes )
|
_targetUnit:GetSkill()
|
||||||
self:T( _targetMimgroupName )
|
_targetskill = _targetUnit:GetSkill()
|
||||||
end
|
end
|
||||||
-- see if we are shot at
|
-- see if we are shot at
|
||||||
local SEADGroupFound = false
|
local SEADGroupFound = false
|
||||||
for SEADGroupPrefixID, SEADGroupPrefix in pairs( self.SEADGroupPrefixes ) do
|
for SEADGroupPrefixID, SEADGroupPrefix in pairs( self.SEADGroupPrefixes ) do
|
||||||
if string.find( _targetMimgroupName, SEADGroupPrefix, 1, true ) then
|
self:T( _targetgroupname, SEADGroupPrefix )
|
||||||
|
if string.find( _targetgroupname, SEADGroupPrefix ) then
|
||||||
SEADGroupFound = true
|
SEADGroupFound = true
|
||||||
self:T( '*** SEAD - Group Found' )
|
self:T( '*** SEAD - Group Match Found' )
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -185,45 +259,71 @@ function SEAD:HandleEventShot( EventData )
|
|||||||
local Skills = { "Average", "Good", "High", "Excellent" }
|
local Skills = { "Average", "Good", "High", "Excellent" }
|
||||||
_targetskill = Skills[ math.random(1,4) ]
|
_targetskill = Skills[ math.random(1,4) ]
|
||||||
end
|
end
|
||||||
self:T( _targetskill )
|
--self:T( _targetskill )
|
||||||
if self.TargetSkill[_targetskill] then
|
if self.TargetSkill[_targetskill] then
|
||||||
|
local _evade = math.random (1,100) -- random number for chance of evading action
|
||||||
if (_evade > self.TargetSkill[_targetskill].Evade) then
|
if (_evade > self.TargetSkill[_targetskill].Evade) then
|
||||||
|
self:T("*** SEAD - Evading")
|
||||||
self:T( string.format("*** SEAD - Evading, target skill " ..string.format(_targetskill)) )
|
-- calculate distance of attacker
|
||||||
|
local _targetpos = _targetgroup:GetCoordinate()
|
||||||
local _targetMimgroup = Unit.getGroup(Weapon.getTarget(SEADWeapon))
|
local _distance = self:_GetDistance(SEADPlanePos, _targetpos)
|
||||||
local _targetMimcont= _targetMimgroup:getController()
|
-- weapon speed
|
||||||
|
local hit, data = self:_CheckHarms(SEADWeaponName)
|
||||||
routines.groupRandomDistSelf(_targetMimgroup,300,'Diamond',250,20) -- move randomly
|
local wpnspeed = 666 -- ;)
|
||||||
|
local reach = 10
|
||||||
--tracker ID table to switch groups off and on again
|
if hit then
|
||||||
local id = {
|
local wpndata = SEAD.HarmData[data]
|
||||||
groupName = _targetMimgroup,
|
reach = wpndata[1] * 1,1
|
||||||
ctrl = _targetMimcont
|
local mach = wpndata[2]
|
||||||
}
|
wpnspeed = math.floor(mach * 340.29)
|
||||||
|
|
||||||
local function SuppressionEnd(id) --switch group back on
|
|
||||||
local range = self.EngagementRange -- Feature Request #1355
|
|
||||||
self:T(string.format("*** SEAD - Engagement Range is %d", range))
|
|
||||||
id.ctrl:setOption(AI.Option.Ground.id.ALARM_STATE,AI.Option.Ground.val.ALARM_STATE.RED)
|
|
||||||
--id.groupName:enableEmission(true)
|
|
||||||
id.ctrl:setOption(AI.Option.Ground.id.AC_ENGAGEMENT_RANGE_RESTRICTION,range) --Feature Request #1355
|
|
||||||
self.SuppressedGroups[id.groupName] = nil --delete group id from table when done
|
|
||||||
end
|
end
|
||||||
|
-- time to impact
|
||||||
|
local _tti = math.floor(_distance / wpnspeed) -- estimated impact time
|
||||||
|
if _distance > 0 then
|
||||||
|
_distance = math.floor(_distance / 1000) -- km
|
||||||
|
else
|
||||||
|
_distance = 0
|
||||||
|
end
|
||||||
|
|
||||||
|
self:T( string.format("*** SEAD - target skill %s, distance %dkm, reach %dkm, tti %dsec", _targetskill, _distance,reach,_tti ))
|
||||||
|
|
||||||
|
if reach >= _distance then
|
||||||
|
self:T("*** SEAD - Shot in Reach")
|
||||||
|
|
||||||
|
local function SuppressionStart(args)
|
||||||
|
self:T(string.format("*** SEAD - %s Radar Off & Relocating",args[2]))
|
||||||
|
local grp = args[1] -- Wrapper.Group#GROUP
|
||||||
|
grp:OptionAlarmStateGreen()
|
||||||
|
grp:RelocateGroundRandomInRadius(20,300,false,false,"Diamond")
|
||||||
|
end
|
||||||
|
|
||||||
|
local function SuppressionStop(args)
|
||||||
|
self:T(string.format("*** SEAD - %s Radar On",args[2]))
|
||||||
|
local grp = args[1] -- Wrapper.Group#GROUP
|
||||||
|
grp:OptionAlarmStateRed()
|
||||||
|
grp:OptionEngageRange(self.EngagementRange)
|
||||||
|
self.SuppressedGroups[args[2]] = false
|
||||||
|
end
|
||||||
|
|
||||||
-- randomize switch-on time
|
-- randomize switch-on time
|
||||||
local delay = math.random(self.TargetSkill[_targetskill].DelayOn[1], self.TargetSkill[_targetskill].DelayOn[2])
|
local delay = math.random(self.TargetSkill[_targetskill].DelayOn[1], self.TargetSkill[_targetskill].DelayOn[2])
|
||||||
local SuppressionEndTime = timer.getTime() + delay
|
if delay > _tti then delay = delay / 2 end -- speed up
|
||||||
--create entry
|
if _tti > (3*delay) then delay = (_tti / 2) * 0.9 end -- shot from afar
|
||||||
if self.SuppressedGroups[id.groupName] == nil then --no timer entry for this group yet
|
|
||||||
self.SuppressedGroups[id.groupName] = {
|
local SuppressionStartTime = timer.getTime() + delay
|
||||||
SuppressionEndTime = delay
|
local SuppressionEndTime = timer.getTime() + _tti + self.Padding
|
||||||
}
|
|
||||||
Controller.setOption(_targetMimcont, AI.Option.Ground.id.ALARM_STATE,AI.Option.Ground.val.ALARM_STATE.GREEN)
|
if not self.SuppressedGroups[_targetgroupname] then
|
||||||
--_targetMimgroup:enableEmission(false)
|
self:T(string.format("*** SEAD - %s | Parameters TTI %ds | Switch-Off in %ds",_targetgroupname,_tti,delay))
|
||||||
timer.scheduleFunction(SuppressionEnd, id, SuppressionEndTime) --Schedule the SuppressionEnd() function
|
timer.scheduleFunction(SuppressionStart,{_targetgroup,_targetgroupname},SuppressionStartTime)
|
||||||
|
timer.scheduleFunction(SuppressionStop,{_targetgroup,_targetgroupname},SuppressionEndTime)
|
||||||
|
self.SuppressedGroups[_targetgroupname] = true
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
return self
|
||||||
end
|
end
|
||||||
|
|||||||
@ -113,7 +113,7 @@ do
|
|||||||
["AGM_122"] = "AGM_122",
|
["AGM_122"] = "AGM_122",
|
||||||
["AGM_84"] = "AGM_84",
|
["AGM_84"] = "AGM_84",
|
||||||
["AGM_45"] = "AGM_45",
|
["AGM_45"] = "AGM_45",
|
||||||
["ALARN"] = "ALARM",
|
["ALARM"] = "ALARM",
|
||||||
["LD-10"] = "LD-10",
|
["LD-10"] = "LD-10",
|
||||||
["X_58"] = "X_58",
|
["X_58"] = "X_58",
|
||||||
["X_28"] = "X_28",
|
["X_28"] = "X_28",
|
||||||
|
|||||||
@ -32,6 +32,8 @@
|
|||||||
-- * [USS George Washington](https://en.wikipedia.org/wiki/USS_George_Washington_(CVN-73)) (CVN-73) [Super Carrier Module]
|
-- * [USS George Washington](https://en.wikipedia.org/wiki/USS_George_Washington_(CVN-73)) (CVN-73) [Super Carrier Module]
|
||||||
-- * [USS Harry S. Truman](https://en.wikipedia.org/wiki/USS_Harry_S._Truman) (CVN-75) [Super Carrier Module]
|
-- * [USS Harry S. Truman](https://en.wikipedia.org/wiki/USS_Harry_S._Truman) (CVN-75) [Super Carrier Module]
|
||||||
-- * [USS Tarawa](https://en.wikipedia.org/wiki/USS_Tarawa_(LHA-1)) (LHA-1) [**WIP**]
|
-- * [USS Tarawa](https://en.wikipedia.org/wiki/USS_Tarawa_(LHA-1)) (LHA-1) [**WIP**]
|
||||||
|
-- * [USS America](https://en.wikipedia.org/wiki/USS_America_(LHA-6)) (LHA-6) [**WIP**]
|
||||||
|
-- * [Juan Carlos I](https://en.wikipedia.org/wiki/Spanish_amphibious_assault_ship_Juan_Carlos_I) (L61) [**WIP**]
|
||||||
--
|
--
|
||||||
-- **Supported Aircraft:**
|
-- **Supported Aircraft:**
|
||||||
--
|
--
|
||||||
@ -48,8 +50,8 @@
|
|||||||
--
|
--
|
||||||
-- At the moment, optimized parameters are available for the F/A-18C Hornet (Lot 20) and A-4E community mod as aircraft and the USS John C. Stennis as carrier.
|
-- At the moment, optimized parameters are available for the F/A-18C Hornet (Lot 20) and A-4E community mod as aircraft and the USS John C. Stennis as carrier.
|
||||||
--
|
--
|
||||||
-- The AV-8B Harrier and the USS Tarawa are WIP. Those two can only be used together, i.e. the Tarawa is the only carrier the harrier is supposed to land on and
|
-- The AV-8B Harrier, the USS Tarawa, USS America and Juan Carlos I are WIP. The AV-8B harrier and the LHA's and LHD can only be used together, i.e. these ships are the only carriers the harrier is supposed to land on and
|
||||||
-- the no other fixed wing aircraft (human or AI controlled) are supposed to land on the Tarawa. Currently only Case I is supported. Case II/III take slightly steps from the CVN carrier.
|
-- no other fixed wing aircraft (human or AI controlled) are supposed to land on these ships. Currently only Case I is supported. Case II/III take slightly different steps from the CVN carrier.
|
||||||
-- However, the two Case II/III pattern are very similar so this is not a big drawback.
|
-- However, the two Case II/III pattern are very similar so this is not a big drawback.
|
||||||
--
|
--
|
||||||
-- Heatblur's mighty F-14B Tomcat has been added (March 13th 2019) as well. Same goes for the A version.
|
-- Heatblur's mighty F-14B Tomcat has been added (March 13th 2019) as well. Same goes for the A version.
|
||||||
@ -102,12 +104,13 @@
|
|||||||
-- ### Wags DCS Hornet Videos:
|
-- ### Wags DCS Hornet Videos:
|
||||||
--
|
--
|
||||||
-- * [DCS: F/A-18C Hornet - Episode 9: CASE I Carrier Landing](https://www.youtube.com/watch?v=TuigBLhtAH8)
|
-- * [DCS: F/A-18C Hornet - Episode 9: CASE I Carrier Landing](https://www.youtube.com/watch?v=TuigBLhtAH8)
|
||||||
-- * [DCS: F/A-18C Hornet – Episode 16: CASE III Introduction](https://www.youtube.com/watch?v=DvlMHnLjbDQ)
|
-- * [DCS: F/A-18C Hornet – Episode 16: CASE III Introduction](https://www.youtube.com/watch?v=DvlMHnLjbDQ)
|
||||||
-- * [DCS: F/A-18C Hornet Case I Carrier Landing Training Lesson Recording](https://www.youtube.com/watch?v=D33uM9q4xgA)
|
-- * [DCS: F/A-18C Hornet Case I Carrier Landing Training Lesson Recording](https://www.youtube.com/watch?v=D33uM9q4xgA)
|
||||||
--
|
--
|
||||||
-- ### AV-8B Harrier at USS Tarawa
|
-- ### AV-8B Harrier at USS Tarawa
|
||||||
--
|
--
|
||||||
-- * [Harrier Ship Landing Mission with Auto LSO!](https://www.youtube.com/watch?v=lqmVvpunk2c)
|
-- * [Harrier Ship Landing Mission with Auto LSO!](https://www.youtube.com/watch?v=lqmVvpunk2c)
|
||||||
|
-- * [Harrier Practice pattern USS America](https://youtu.be/99NigITYmcI)
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
@ -295,6 +298,8 @@
|
|||||||
-- 
|
-- 
|
||||||
--
|
--
|
||||||
-- Once the aircraft reaches the Initial, the landing pattern begins. The important steps of the pattern are shown in the image above.
|
-- Once the aircraft reaches the Initial, the landing pattern begins. The important steps of the pattern are shown in the image above.
|
||||||
|
-- The AV-8B Harrier pattern is very similar, the only differences are as there is no angled deck there is no wake check. from the ninety you wil fly a straight approach offset 26 ft to port (left) of the tram line.
|
||||||
|
-- The aim is to arrive abeam the landing spot in a stable hover at 120 ft with forward speed matched to the boat. From there the LSO will call "cleared to land". You then level cross to the tram line at the designated landing spot at land vertcally.
|
||||||
--
|
--
|
||||||
--
|
--
|
||||||
-- ## CASE III
|
-- ## CASE III
|
||||||
@ -919,9 +924,9 @@
|
|||||||
--
|
--
|
||||||
-- ## Sound Packs
|
-- ## Sound Packs
|
||||||
--
|
--
|
||||||
-- The AIRBOSS currently has two different "sound packs" for both LSO and Marshal radios. These contain voice overs by different actors.
|
-- The AIRBOSS currently has two different "sound packs" for LSO and three different "sound Packs" for Marshal radios. These contain voice overs by different actors.
|
||||||
-- These can be set by @{#AIRBOSS.SetVoiceOversLSOByRaynor}() and @{#AIRBOSS.SetVoiceOversMarshalByRaynor}(). These are the default settings.
|
-- These can be set by @{#AIRBOSS.SetVoiceOversLSOByRaynor}() and @{#AIRBOSS.SetVoiceOversMarshalByRaynor}(). These are the default settings.
|
||||||
-- The other sound files can be set by @{#AIRBOSS.SetVoiceOversLSOByFF}() and @{#AIRBOSS.SetVoiceOversMarshalByFF}().
|
-- The other sound files can be set by @{#AIRBOSS.SetVoiceOversLSOByFF}(), @{#AIRBOSS.SetVoiceOversMarshalByGabriella}() and @{#AIRBOSS.SetVoiceOversMarshalByFF}().
|
||||||
-- Also combinations can be used, e.g.
|
-- Also combinations can be used, e.g.
|
||||||
--
|
--
|
||||||
-- airbossStennis:SetVoiceOversLSOByFF()
|
-- airbossStennis:SetVoiceOversLSOByFF()
|
||||||
@ -1256,7 +1261,7 @@ AIRBOSS = {
|
|||||||
|
|
||||||
--- Aircraft types capable of landing on carrier (human+AI).
|
--- Aircraft types capable of landing on carrier (human+AI).
|
||||||
-- @type AIRBOSS.AircraftCarrier
|
-- @type AIRBOSS.AircraftCarrier
|
||||||
-- @field #string AV8B AV-8B Night Harrier. Works only with the USS Tarawa.
|
-- @field #string AV8B AV-8B Night Harrier. Works only with the USS Tarawa, USS America and Juan Carlos I.
|
||||||
-- @field #string A4EC A-4E Community mod.
|
-- @field #string A4EC A-4E Community mod.
|
||||||
-- @field #string HORNET F/A-18C Lot 20 Hornet by Eagle Dynamics.
|
-- @field #string HORNET F/A-18C Lot 20 Hornet by Eagle Dynamics.
|
||||||
-- @field #string F14A F-14A by Heatblur.
|
-- @field #string F14A F-14A by Heatblur.
|
||||||
@ -1292,6 +1297,8 @@ AIRBOSS.AircraftCarrier={
|
|||||||
-- @field #string TRUMAN USS Harry S. Truman (CVN-75) [Super Carrier Module]
|
-- @field #string TRUMAN USS Harry S. Truman (CVN-75) [Super Carrier Module]
|
||||||
-- @field #string VINSON USS Carl Vinson (CVN-70) [Obsolete]
|
-- @field #string VINSON USS Carl Vinson (CVN-70) [Obsolete]
|
||||||
-- @field #string TARAWA USS Tarawa (LHA-1)
|
-- @field #string TARAWA USS Tarawa (LHA-1)
|
||||||
|
-- @field #string AMERICA USS America (LHA-6)
|
||||||
|
-- @field #string JCARLOS Juan Carlos I (L61)
|
||||||
-- @field #string KUZNETSOV Admiral Kuznetsov (CV 1143.5)
|
-- @field #string KUZNETSOV Admiral Kuznetsov (CV 1143.5)
|
||||||
AIRBOSS.CarrierType={
|
AIRBOSS.CarrierType={
|
||||||
ROOSEVELT="CVN_71",
|
ROOSEVELT="CVN_71",
|
||||||
@ -1301,6 +1308,8 @@ AIRBOSS.CarrierType={
|
|||||||
STENNIS="Stennis",
|
STENNIS="Stennis",
|
||||||
VINSON="VINSON",
|
VINSON="VINSON",
|
||||||
TARAWA="LHA_Tarawa",
|
TARAWA="LHA_Tarawa",
|
||||||
|
AMERICA="USS America LHA-6",
|
||||||
|
JCARLOS="L61",
|
||||||
KUZNETSOV="KUZNECOW",
|
KUZNETSOV="KUZNECOW",
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1420,8 +1429,8 @@ AIRBOSS.PatternStep={
|
|||||||
-- @field #string IM "IM": In the middle.
|
-- @field #string IM "IM": In the middle.
|
||||||
-- @field #string IC "IC": In close.
|
-- @field #string IC "IC": In close.
|
||||||
-- @field #string AR "AR": At the ramp.
|
-- @field #string AR "AR": At the ramp.
|
||||||
-- @field #string AL "AL": Abeam landing position (Tarawa).
|
-- @field #string AL "AL": Abeam landing position (V/STOL).
|
||||||
-- @field #string LC "LC": Level crossing (Tarawa).
|
-- @field #string LC "LC": Level crossing (V/STOL).
|
||||||
-- @field #string IW "IW": In the wires.
|
-- @field #string IW "IW": In the wires.
|
||||||
AIRBOSS.GroovePos={
|
AIRBOSS.GroovePos={
|
||||||
X0="X0",
|
X0="X0",
|
||||||
@ -1486,6 +1495,7 @@ AIRBOSS.GroovePos={
|
|||||||
-- @field #AIRBOSS.RadioCall DEPARTANDREENTER "Depart and re-enter" call.
|
-- @field #AIRBOSS.RadioCall DEPARTANDREENTER "Depart and re-enter" call.
|
||||||
-- @field #AIRBOSS.RadioCall EXPECTHEAVYWAVEOFF "Expect heavy wavoff" call.
|
-- @field #AIRBOSS.RadioCall EXPECTHEAVYWAVEOFF "Expect heavy wavoff" call.
|
||||||
-- @field #AIRBOSS.RadioCall EXPECTSPOT75 "Expect spot 7.5" call.
|
-- @field #AIRBOSS.RadioCall EXPECTSPOT75 "Expect spot 7.5" call.
|
||||||
|
-- @field #AIRBOSS.RadioCall EXPECTSPOT5 "Expect spot 5" call.
|
||||||
-- @field #AIRBOSS.RadioCall FAST "You're fast" call.
|
-- @field #AIRBOSS.RadioCall FAST "You're fast" call.
|
||||||
-- @field #AIRBOSS.RadioCall FOULDECK "Foul Deck" call.
|
-- @field #AIRBOSS.RadioCall FOULDECK "Foul Deck" call.
|
||||||
-- @field #AIRBOSS.RadioCall HIGH "You're high" call.
|
-- @field #AIRBOSS.RadioCall HIGH "You're high" call.
|
||||||
@ -1970,6 +1980,12 @@ function AIRBOSS:New(carriername, alias)
|
|||||||
elseif self.carriertype==AIRBOSS.CarrierType.TARAWA then
|
elseif self.carriertype==AIRBOSS.CarrierType.TARAWA then
|
||||||
-- Tarawa parameters.
|
-- Tarawa parameters.
|
||||||
self:_InitTarawa()
|
self:_InitTarawa()
|
||||||
|
elseif self.carriertype==AIRBOSS.CarrierType.AMERICA then
|
||||||
|
-- Use America parameters.
|
||||||
|
self:_InitAmerica()
|
||||||
|
elseif self.carriertype==AIRBOSS.CarrierType.JCARLOS then
|
||||||
|
-- Use Juan Carlos parameters.
|
||||||
|
self:_InitJcarlos()
|
||||||
elseif self.carriertype==AIRBOSS.CarrierType.KUZNETSOV then
|
elseif self.carriertype==AIRBOSS.CarrierType.KUZNETSOV then
|
||||||
-- Kusnetsov parameters - maybe...
|
-- Kusnetsov parameters - maybe...
|
||||||
self:_InitStennis()
|
self:_InitStennis()
|
||||||
@ -2061,7 +2077,7 @@ function AIRBOSS:New(carriername, alias)
|
|||||||
|
|
||||||
|
|
||||||
-- Carrier specific.
|
-- Carrier specific.
|
||||||
if self.carrier:GetTypeName()~=AIRBOSS.CarrierType.TARAWA then
|
if self.carrier:GetTypeName()~=AIRBOSS.CarrierType.TARAWA or self.carrier:GetTypeName()~=AIRBOSS.CarrierType.AMERICA or self.carrier:GetTypeName()~=AIRBOSS.CarrierType.JCARLOS then
|
||||||
|
|
||||||
-- Flare wires.
|
-- Flare wires.
|
||||||
local w1=stern:Translate(self.carrierparam.wire1, FB)
|
local w1=stern:Translate(self.carrierparam.wire1, FB)
|
||||||
@ -4404,6 +4420,85 @@ function AIRBOSS:_InitTarawa()
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Init parameters for LHA-6 America carrier.
|
||||||
|
-- @param #AIRBOSS self
|
||||||
|
function AIRBOSS:_InitAmerica()
|
||||||
|
|
||||||
|
-- Init Stennis as default.
|
||||||
|
self:_InitStennis()
|
||||||
|
|
||||||
|
-- Carrier Parameters.
|
||||||
|
self.carrierparam.sterndist =-125
|
||||||
|
self.carrierparam.deckheight = 20 --67 ft
|
||||||
|
|
||||||
|
-- Total size of the carrier (approx as rectangle).
|
||||||
|
self.carrierparam.totlength=257
|
||||||
|
self.carrierparam.totwidthport=11
|
||||||
|
self.carrierparam.totwidthstarboard=25
|
||||||
|
|
||||||
|
-- Landing runway.
|
||||||
|
self.carrierparam.rwyangle = 0
|
||||||
|
self.carrierparam.rwylength = 240
|
||||||
|
self.carrierparam.rwywidth = 15
|
||||||
|
|
||||||
|
-- Wires.
|
||||||
|
self.carrierparam.wire1=nil
|
||||||
|
self.carrierparam.wire2=nil
|
||||||
|
self.carrierparam.wire3=nil
|
||||||
|
self.carrierparam.wire4=nil
|
||||||
|
|
||||||
|
-- Late break.
|
||||||
|
self.BreakLate.name="Late Break"
|
||||||
|
self.BreakLate.Xmin=-UTILS.NMToMeters(1) -- Not more than 1 NM behind the boat. Last check was at 0.
|
||||||
|
self.BreakLate.Xmax= UTILS.NMToMeters(5) -- Not more than 5 NM in front of the boat. Enough for late breaks?
|
||||||
|
self.BreakLate.Zmin=-UTILS.NMToMeters(1.6) -- Not more than 1.6 NM port.
|
||||||
|
self.BreakLate.Zmax= UTILS.NMToMeters(1) -- Not more than 1 NM starboard.
|
||||||
|
self.BreakLate.LimitXmin= 0 -- Check and next step 0.8 NM port and in front of boat.
|
||||||
|
self.BreakLate.LimitXmax= nil
|
||||||
|
self.BreakLate.LimitZmin=-UTILS.NMToMeters(0.5) -- 926 m port, closer than the stennis as abeam is 0.8-1.0 rather than 1.2
|
||||||
|
self.BreakLate.LimitZmax= nil
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Init parameters for L61 Juan Carlos carrier.
|
||||||
|
-- @param #AIRBOSS self
|
||||||
|
function AIRBOSS:_InitJcarlos()
|
||||||
|
|
||||||
|
-- Init Stennis as default.
|
||||||
|
self:_InitStennis()
|
||||||
|
|
||||||
|
-- Carrier Parameters.
|
||||||
|
self.carrierparam.sterndist =-125
|
||||||
|
self.carrierparam.deckheight = 20 --67 ft
|
||||||
|
|
||||||
|
-- Total size of the carrier (approx as rectangle).
|
||||||
|
self.carrierparam.totlength=231
|
||||||
|
self.carrierparam.totwidthport=10
|
||||||
|
self.carrierparam.totwidthstarboard=22
|
||||||
|
|
||||||
|
-- Landing runway.
|
||||||
|
self.carrierparam.rwyangle = 0
|
||||||
|
self.carrierparam.rwylength = 202
|
||||||
|
self.carrierparam.rwywidth = 14
|
||||||
|
|
||||||
|
-- Wires.
|
||||||
|
self.carrierparam.wire1=nil
|
||||||
|
self.carrierparam.wire2=nil
|
||||||
|
self.carrierparam.wire3=nil
|
||||||
|
self.carrierparam.wire4=nil
|
||||||
|
|
||||||
|
-- Late break.
|
||||||
|
self.BreakLate.name="Late Break"
|
||||||
|
self.BreakLate.Xmin=-UTILS.NMToMeters(1) -- Not more than 1 NM behind the boat. Last check was at 0.
|
||||||
|
self.BreakLate.Xmax= UTILS.NMToMeters(5) -- Not more than 5 NM in front of the boat. Enough for late breaks?
|
||||||
|
self.BreakLate.Zmin=-UTILS.NMToMeters(1.6) -- Not more than 1.6 NM port.
|
||||||
|
self.BreakLate.Zmax= UTILS.NMToMeters(1) -- Not more than 1 NM starboard.
|
||||||
|
self.BreakLate.LimitXmin= 0 -- Check and next step 0.8 NM port and in front of boat.
|
||||||
|
self.BreakLate.LimitXmax= nil
|
||||||
|
self.BreakLate.LimitZmin=-UTILS.NMToMeters(0.5) -- 926 m port, closer than the stennis as abeam is 0.8-1.0 rather than 1.2
|
||||||
|
self.BreakLate.LimitZmax= nil
|
||||||
|
|
||||||
|
end
|
||||||
--- Init parameters for Marshal Voice overs *Gabriella* by HighwaymanEd.
|
--- Init parameters for Marshal Voice overs *Gabriella* by HighwaymanEd.
|
||||||
-- @param #AIRBOSS self
|
-- @param #AIRBOSS self
|
||||||
-- @param #string mizfolder (Optional) Folder within miz file where the sound files are located.
|
-- @param #string mizfolder (Optional) Folder within miz file where the sound files are located.
|
||||||
@ -4558,6 +4653,7 @@ function AIRBOSS:SetVoiceOversLSOByRaynor(mizfolder)
|
|||||||
self.LSOCall.DEPARTANDREENTER.duration=1.10
|
self.LSOCall.DEPARTANDREENTER.duration=1.10
|
||||||
self.LSOCall.EXPECTHEAVYWAVEOFF.duration=1.30
|
self.LSOCall.EXPECTHEAVYWAVEOFF.duration=1.30
|
||||||
self.LSOCall.EXPECTSPOT75.duration=1.85
|
self.LSOCall.EXPECTSPOT75.duration=1.85
|
||||||
|
self.LSOCall.EXPECTSPOT5.duration=1.3
|
||||||
self.LSOCall.FAST.duration=0.75
|
self.LSOCall.FAST.duration=0.75
|
||||||
self.LSOCall.FOULDECK.duration=0.75
|
self.LSOCall.FOULDECK.duration=0.75
|
||||||
self.LSOCall.HIGH.duration=0.65
|
self.LSOCall.HIGH.duration=0.65
|
||||||
@ -4616,6 +4712,7 @@ function AIRBOSS:SetVoiceOversLSOByFF(mizfolder)
|
|||||||
self.LSOCall.DEPARTANDREENTER.duration=1.10
|
self.LSOCall.DEPARTANDREENTER.duration=1.10
|
||||||
self.LSOCall.EXPECTHEAVYWAVEOFF.duration=1.20
|
self.LSOCall.EXPECTHEAVYWAVEOFF.duration=1.20
|
||||||
self.LSOCall.EXPECTSPOT75.duration=2.00
|
self.LSOCall.EXPECTSPOT75.duration=2.00
|
||||||
|
self.LSOCall.EXPECTSPOT5.duration=1.3
|
||||||
self.LSOCall.FAST.duration=0.70
|
self.LSOCall.FAST.duration=0.70
|
||||||
self.LSOCall.FOULDECK.duration=0.62
|
self.LSOCall.FOULDECK.duration=0.62
|
||||||
self.LSOCall.HIGH.duration=0.65
|
self.LSOCall.HIGH.duration=0.65
|
||||||
@ -4883,6 +4980,14 @@ function AIRBOSS:_InitVoiceOvers()
|
|||||||
subtitle="Expect spot 7.5",
|
subtitle="Expect spot 7.5",
|
||||||
duration=2.0,
|
duration=2.0,
|
||||||
subduration=5,
|
subduration=5,
|
||||||
|
},
|
||||||
|
EXPECTSPOT5={
|
||||||
|
file="LSO-ExpectSpot5",
|
||||||
|
suffix="ogg",
|
||||||
|
loud=false,
|
||||||
|
subtitle="Expect spot 5",
|
||||||
|
duration=1.3,
|
||||||
|
subduration=5,
|
||||||
},
|
},
|
||||||
STABILIZED={
|
STABILIZED={
|
||||||
file="LSO-Stabilized",
|
file="LSO-Stabilized",
|
||||||
@ -5543,14 +5648,14 @@ function AIRBOSS:_GetAircraftAoA(playerData)
|
|||||||
aoa.Fast = 8.25 --=17.5/2
|
aoa.Fast = 8.25 --=17.5/2
|
||||||
aoa.FAST = 8.00 --=16.5/2
|
aoa.FAST = 8.00 --=16.5/2
|
||||||
elseif harrier then
|
elseif harrier then
|
||||||
-- AV-8B Harrier parameters. This might need further tuning.
|
-- AV-8B Harrier parameters. Tuning done on the Fast AoA to allow for abeam and ninety at Nozzles 60 - 73.
|
||||||
aoa.SLOW = 14.0
|
aoa.SLOW = 14.0
|
||||||
aoa.Slow = 13.0
|
aoa.Slow = 13.0
|
||||||
aoa.OnSpeedMax = 12.0
|
aoa.OnSpeedMax = 12.0
|
||||||
aoa.OnSpeed = 11.0
|
aoa.OnSpeed = 11.0
|
||||||
aoa.OnSpeedMin = 10.0
|
aoa.OnSpeedMin = 10.0
|
||||||
aoa.Fast = 9.0
|
aoa.Fast = 8.0
|
||||||
aoa.FAST = 8.0
|
aoa.FAST = 7.5
|
||||||
end
|
end
|
||||||
|
|
||||||
return aoa
|
return aoa
|
||||||
@ -5810,7 +5915,7 @@ function AIRBOSS:_GetAircraftParameters(playerData, step)
|
|||||||
alt=UTILS.FeetToMeters(300) --?
|
alt=UTILS.FeetToMeters(300) --?
|
||||||
elseif harrier then
|
elseif harrier then
|
||||||
-- 300-325 ft
|
-- 300-325 ft
|
||||||
alt=UTILS.FeetToMeters(300)
|
alt=UTILS.FeetToMeters(300)-- Need to verify
|
||||||
end
|
end
|
||||||
|
|
||||||
aoa=aoaac.OnSpeed
|
aoa=aoaac.OnSpeed
|
||||||
@ -6751,8 +6856,8 @@ function AIRBOSS:_GetMarshalAltitude(stack, case)
|
|||||||
-- Second point 1.5 NM ahead.
|
-- Second point 1.5 NM ahead.
|
||||||
p2=Carrier:Translate(UTILS.NMToMeters(1.5), hdg)
|
p2=Carrier:Translate(UTILS.NMToMeters(1.5), hdg)
|
||||||
|
|
||||||
-- Tarawa Delta pattern.
|
-- Tarawa,LHA,LHD Delta patterns.
|
||||||
if self.carriertype==AIRBOSS.CarrierType.TARAWA then
|
if self.carriertype==AIRBOSS.CarrierType.TARAWA or self.carriertype==AIRBOSS.CarrierType.AMERICA or self.carriertype==AIRBOSS.CarrierType.JCARLOS then
|
||||||
|
|
||||||
-- Pattern is directly overhead the carrier.
|
-- Pattern is directly overhead the carrier.
|
||||||
p1=Carrier:Translate(UTILS.NMToMeters(1.0), hdg+90)
|
p1=Carrier:Translate(UTILS.NMToMeters(1.0), hdg+90)
|
||||||
@ -8597,7 +8702,7 @@ function AIRBOSS:OnEventLand(EventData)
|
|||||||
self:T(self.lid..text)
|
self:T(self.lid..text)
|
||||||
|
|
||||||
-- Check carrier type.
|
-- Check carrier type.
|
||||||
if self.carriertype==AIRBOSS.CarrierType.TARAWA then
|
if self.carriertype==AIRBOSS.CarrierType.TARAWA or self.carriertype==AIRBOSS.CarrierType.AMERICA or self.carriertype==AIRBOSS.CarrierType.JCARLOS then
|
||||||
|
|
||||||
-- Power "Idle".
|
-- Power "Idle".
|
||||||
self:RadioTransmission(self.LSORadio, self.LSOCall.IDLE, false, 1, nil, true)
|
self:RadioTransmission(self.LSORadio, self.LSOCall.IDLE, false, 1, nil, true)
|
||||||
@ -8632,7 +8737,7 @@ function AIRBOSS:OnEventLand(EventData)
|
|||||||
-- AI unit landed --
|
-- AI unit landed --
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
if self.carriertype~=AIRBOSS.CarrierType.TARAWA then
|
if self.carriertype~=AIRBOSS.CarrierType.TARAWA or self.carriertype~=AIRBOSS.CarrierType.AMERICA or self.carriertype~=AIRBOSS.CarrierType.JCARLOS then
|
||||||
|
|
||||||
-- Coordinate at landing event
|
-- Coordinate at landing event
|
||||||
local coord=EventData.IniUnit:GetCoordinate()
|
local coord=EventData.IniUnit:GetCoordinate()
|
||||||
@ -9539,8 +9644,10 @@ function AIRBOSS:_Bullseye(playerData)
|
|||||||
-- Hint for player about altitude, AoA etc.
|
-- Hint for player about altitude, AoA etc.
|
||||||
self:_PlayerHint(playerData)
|
self:_PlayerHint(playerData)
|
||||||
|
|
||||||
-- LSO expect spot 7.5 call
|
-- LSO expect spot 5 or 7.5 call
|
||||||
if playerData.actype==AIRBOSS.AircraftCarrier.AV8B then
|
if playerData.actype==AIRBOSS.AircraftCarrier.AV8B and self.carriertype==AIRBOSS.CarrierType.JCARLOS then
|
||||||
|
self:RadioTransmission(self.LSORadio, self.LSOCall.EXPECTSPOT5, nil, nil, nil, true)
|
||||||
|
elseif playerData.actype==AIRBOSS.AircraftCarrier.AV8B then
|
||||||
self:RadioTransmission(self.LSORadio, self.LSOCall.EXPECTSPOT75, nil, nil, nil, true)
|
self:RadioTransmission(self.LSORadio, self.LSOCall.EXPECTSPOT75, nil, nil, nil, true)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -9676,8 +9783,8 @@ function AIRBOSS:_CheckForLongDownwind(playerData)
|
|||||||
-- 1.6 NM from carrier is too far.
|
-- 1.6 NM from carrier is too far.
|
||||||
local limit=UTILS.NMToMeters(-1.6)
|
local limit=UTILS.NMToMeters(-1.6)
|
||||||
|
|
||||||
-- For the tarawa we give a bit more space.
|
-- For the tarawa, other LHA and LHD we give a bit more space.
|
||||||
if self.carriertype==AIRBOSS.CarrierType.TARAWA then
|
if self.carriertype==AIRBOSS.CarrierType.TARAWA or self.carriertype==AIRBOSS.CarrierType.AMERICA or self.carriertype==AIRBOSS.CarrierType.JCARLOS then
|
||||||
limit=UTILS.NMToMeters(-2.0)
|
limit=UTILS.NMToMeters(-2.0)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -9722,8 +9829,10 @@ function AIRBOSS:_Abeam(playerData)
|
|||||||
-- Paddles contact.
|
-- Paddles contact.
|
||||||
self:RadioTransmission(self.LSORadio, self.LSOCall.PADDLESCONTACT, nil, nil, nil, true)
|
self:RadioTransmission(self.LSORadio, self.LSOCall.PADDLESCONTACT, nil, nil, nil, true)
|
||||||
|
|
||||||
-- LSO expect spot 7.5 call
|
-- LSO expect spot 5 or 7.5 call
|
||||||
if playerData.actype==AIRBOSS.AircraftCarrier.AV8B then
|
if playerData.actype==AIRBOSS.AircraftCarrier.AV8B and self.carriertype==AIRBOSS.CarrierType.JCARLOS then
|
||||||
|
self:RadioTransmission(self.LSORadio, self.LSOCall.EXPECTSPOT5, false, 5, nil, true)
|
||||||
|
elseif playerData.actype==AIRBOSS.AircraftCarrier.AV8B then
|
||||||
self:RadioTransmission(self.LSORadio, self.LSOCall.EXPECTSPOT75, false, 5, nil, true)
|
self:RadioTransmission(self.LSORadio, self.LSOCall.EXPECTSPOT75, false, 5, nil, true)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -9760,7 +9869,7 @@ function AIRBOSS:_Ninety(playerData)
|
|||||||
self:_PlayerHint(playerData)
|
self:_PlayerHint(playerData)
|
||||||
|
|
||||||
-- Next step: wake.
|
-- Next step: wake.
|
||||||
if self.carriertype==AIRBOSS.CarrierType.TARAWA then
|
if self.carriertype==AIRBOSS.CarrierType.TARAWA or self.carriertype==AIRBOSS.CarrierType.AMERICA or self.carriertype==AIRBOSS.CarrierType.JCARLOS then
|
||||||
-- Harrier has no wake stop. It stays port of the boat.
|
-- Harrier has no wake stop. It stays port of the boat.
|
||||||
self:_SetPlayerStep(playerData, AIRBOSS.PatternStep.FINAL)
|
self:_SetPlayerStep(playerData, AIRBOSS.PatternStep.FINAL)
|
||||||
else
|
else
|
||||||
@ -10434,7 +10543,7 @@ function AIRBOSS:_GetSternCoord()
|
|||||||
--local stern=self:GetCoordinate()
|
--local stern=self:GetCoordinate()
|
||||||
|
|
||||||
-- Stern coordinate (sterndist<0).
|
-- Stern coordinate (sterndist<0).
|
||||||
if self.carriertype==AIRBOSS.CarrierType.TARAWA then
|
if self.carriertype==AIRBOSS.CarrierType.TARAWA or self.carriertype==AIRBOSS.CarrierType.AMERICA or self.carriertype==AIRBOSS.CarrierType.JCARLOS then
|
||||||
-- Tarawa: Translate 8 meters port.
|
-- Tarawa: Translate 8 meters port.
|
||||||
self.sterncoord:Translate(self.carrierparam.sterndist, hdg, true, true):Translate(8, FB-90, true, true)
|
self.sterncoord:Translate(self.carrierparam.sterndist, hdg, true, true):Translate(8, FB-90, true, true)
|
||||||
elseif self.carriertype==AIRBOSS.CarrierType.STENNIS then
|
elseif self.carriertype==AIRBOSS.CarrierType.STENNIS then
|
||||||
@ -11177,7 +11286,7 @@ function AIRBOSS:_GetZoneHolding(case, stack)
|
|||||||
self.zoneHolding=ZONE_RADIUS:New("CASE I Holding Zone", Post:GetVec2(), self.marshalradius)
|
self.zoneHolding=ZONE_RADIUS:New("CASE I Holding Zone", Post:GetVec2(), self.marshalradius)
|
||||||
|
|
||||||
-- Delta pattern.
|
-- Delta pattern.
|
||||||
if self.carriertype==AIRBOSS.CarrierType.TARAWA then
|
if self.carriertype==AIRBOSS.CarrierType.TARAWA or self.carriertype==AIRBOSS.CarrierType.AMERICA or self.carriertype==AIRBOSS.CarrierType.JCARLOS then
|
||||||
self.zoneHolding=ZONE_RADIUS:New("CASE I Holding Zone", self.carrier:GetVec2(), UTILS.NMToMeters(5))
|
self.zoneHolding=ZONE_RADIUS:New("CASE I Holding Zone", self.carrier:GetVec2(), UTILS.NMToMeters(5))
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -11230,7 +11339,7 @@ function AIRBOSS:_GetZoneCommence(case, stack)
|
|||||||
-- Three position
|
-- Three position
|
||||||
local Three=self:GetCoordinate():Translate(D, hdg+275)
|
local Three=self:GetCoordinate():Translate(D, hdg+275)
|
||||||
|
|
||||||
if self.carriertype==AIRBOSS.CarrierType.TARAWA then
|
if self.carriertype==AIRBOSS.CarrierType.TARAWA or self.carriertype==AIRBOSS.CarrierType.AMERICA or self.carriertype==AIRBOSS.CarrierType.JCARLOS then
|
||||||
|
|
||||||
local Dx=UTILS.NMToMeters(2.25)
|
local Dx=UTILS.NMToMeters(2.25)
|
||||||
|
|
||||||
@ -11521,7 +11630,7 @@ function AIRBOSS:_GetAltCarrier(unit)
|
|||||||
return h
|
return h
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Get optimal landing position of the aircraft. Usually between second and third wire. In case of Tarawa we take the abeam landing spot 120 ft abeam the 7.5 position.
|
--- Get optimal landing position of the aircraft. Usually between second and third wire. In case of Tarawa and America we take the abeam landing spot 120 ft abeam the 7.5 position, for the Juan Carlos I it is 120 ft and abeam the 5 position.
|
||||||
-- @param #AIRBOSS self
|
-- @param #AIRBOSS self
|
||||||
-- @return Core.Point#COORDINATE Optimal landing coordinate.
|
-- @return Core.Point#COORDINATE Optimal landing coordinate.
|
||||||
function AIRBOSS:_GetOptLandingCoordinate()
|
function AIRBOSS:_GetOptLandingCoordinate()
|
||||||
@ -11541,6 +11650,23 @@ function AIRBOSS:_GetOptLandingCoordinate()
|
|||||||
self.landingcoord:UpdateFromCoordinate(self:_GetLandingSpotCoordinate()):Translate(35, FB-90, true, true)
|
self.landingcoord:UpdateFromCoordinate(self:_GetLandingSpotCoordinate()):Translate(35, FB-90, true, true)
|
||||||
--stern=self:_GetLandingSpotCoordinate():Translate(35, FB-90)
|
--stern=self:_GetLandingSpotCoordinate():Translate(35, FB-90)
|
||||||
|
|
||||||
|
-- Alitude 120 ft.
|
||||||
|
self.landingcoord:SetAltitude(UTILS.FeetToMeters(120))
|
||||||
|
elseif self.carriertype==AIRBOSS.CarrierType.AMERICA then
|
||||||
|
|
||||||
|
-- Landing 100 ft abeam, 120 ft alt. To allow adjustments to match different deck configurations.
|
||||||
|
self.landingcoord:UpdateFromCoordinate(self:_GetLandingSpotCoordinate()):Translate(35, FB-90, true, true)
|
||||||
|
--stern=self:_GetLandingSpotCoordinate():Translate(35, FB-90)
|
||||||
|
|
||||||
|
-- Alitude 120 ft.
|
||||||
|
self.landingcoord:SetAltitude(UTILS.FeetToMeters(120))
|
||||||
|
|
||||||
|
elseif self.carriertype==AIRBOSS.CarrierType.JCARLOS then
|
||||||
|
|
||||||
|
-- Landing 100 ft abeam, 120 ft alt.
|
||||||
|
self.landingcoord:UpdateFromCoordinate(self:_GetLandingSpotCoordinate()):Translate(35, FB-100, true, true)
|
||||||
|
--stern=self:_GetLandingSpotCoordinate():Translate(35, FB-100)
|
||||||
|
|
||||||
-- Alitude 120 ft.
|
-- Alitude 120 ft.
|
||||||
self.landingcoord:SetAltitude(UTILS.FeetToMeters(120))
|
self.landingcoord:SetAltitude(UTILS.FeetToMeters(120))
|
||||||
|
|
||||||
@ -11578,6 +11704,21 @@ function AIRBOSS:_GetLandingSpotCoordinate()
|
|||||||
|
|
||||||
-- Primary landing spot 7.5
|
-- Primary landing spot 7.5
|
||||||
self.landingspotcoord:Translate(57, hdg, true, true):SetAltitude(self.carrierparam.deckheight)
|
self.landingspotcoord:Translate(57, hdg, true, true):SetAltitude(self.carrierparam.deckheight)
|
||||||
|
elseif self.carriertype==AIRBOSS.CarrierType.AMERICA then
|
||||||
|
|
||||||
|
-- Landing 100 ft abeam, 120 alt.
|
||||||
|
local hdg=self:GetHeading()
|
||||||
|
|
||||||
|
-- Primary landing spot 7.5 a little further forwad on the America
|
||||||
|
self.landingspotcoord:Translate(59, hdg, true, true):SetAltitude(self.carrierparam.deckheight)
|
||||||
|
|
||||||
|
elseif self.carriertype==AIRBOSS.CarrierType.JCARLOS then
|
||||||
|
|
||||||
|
-- Landing 100 ft abeam, 120 alt.
|
||||||
|
local hdg=self:GetHeading()
|
||||||
|
|
||||||
|
-- Primary landing spot 5.0 -- TODO voice for different landing Spots.
|
||||||
|
self.landingspotcoord:Translate(89, hdg, true, true):SetAltitude(self.carrierparam.deckheight)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -12070,6 +12211,11 @@ end
|
|||||||
-- * > 24 seconds: No Grade "--"
|
-- * > 24 seconds: No Grade "--"
|
||||||
--
|
--
|
||||||
-- If you manage to be between 16.4 and and 16.6 seconds, you will even get and okay underline "\_OK\_".
|
-- If you manage to be between 16.4 and and 16.6 seconds, you will even get and okay underline "\_OK\_".
|
||||||
|
-- No groove time for Harrier on LHA, LHD set to Tgroove Unicorn as starting point to allow possible _OK_ 5.0.
|
||||||
|
-- If time in the AV-8B
|
||||||
|
--
|
||||||
|
-- * < 90 seconds: OK V/STOL
|
||||||
|
-- * > 91 Seconds: SLOW V/STOL (Early hover stop selection)
|
||||||
--
|
--
|
||||||
-- @param #AIRBOSS self
|
-- @param #AIRBOSS self
|
||||||
-- @param #AIRBOSS.PlayerData playerData Player data table.
|
-- @param #AIRBOSS.PlayerData playerData Player data table.
|
||||||
@ -12088,6 +12234,13 @@ function AIRBOSS:_EvalGrooveTime(playerData)
|
|||||||
grade="OK Groove"
|
grade="OK Groove"
|
||||||
elseif t<=24 then
|
elseif t<=24 then
|
||||||
grade="(LIG)"
|
grade="(LIG)"
|
||||||
|
-- Time in groove for AV-8B
|
||||||
|
elseif playerData.actype==AIRBOSS.AircraftCarrier.AV8B and t<55 then -- VSTOL Late Hover stop selection too fast to Abeam LDG Spot AV-8B.
|
||||||
|
grade="FAST V/STOL Groove"
|
||||||
|
elseif playerData.actype==AIRBOSS.AircraftCarrier.AV8B and t<90 then -- VSTOL Operations with AV-8B.
|
||||||
|
grade="OK V/STOL Groove"
|
||||||
|
elseif playerData.actype==AIRBOSS.AircraftCarrier.AV8B and t>=91 then -- VSTOL Early Hover stop selection slow to Abeam LDG Spot AV-8B.
|
||||||
|
grade="SLOW V/STOL Groove"
|
||||||
else
|
else
|
||||||
grade="LIG"
|
grade="LIG"
|
||||||
end
|
end
|
||||||
@ -12097,6 +12250,11 @@ function AIRBOSS:_EvalGrooveTime(playerData)
|
|||||||
grade="_OK_"
|
grade="_OK_"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- V/STOL Unicorn!
|
||||||
|
if playerData.actype==AIRBOSS.AircraftCarrier.AV8B and (t>=65.0 and t<=75.0) then
|
||||||
|
grade="_OK_ V/STOL"
|
||||||
|
end
|
||||||
|
|
||||||
return grade
|
return grade
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -12113,7 +12271,7 @@ function AIRBOSS:_LSOgrade(playerData)
|
|||||||
return select(2, string.gsub(base, pattern, ""))
|
return select(2, string.gsub(base, pattern, ""))
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Analyse flight data and conver to LSO text.
|
-- Analyse flight data and convert to LSO text.
|
||||||
local GXX,nXX=self:_Flightdata2Text(playerData, AIRBOSS.GroovePos.XX)
|
local GXX,nXX=self:_Flightdata2Text(playerData, AIRBOSS.GroovePos.XX)
|
||||||
local GIM,nIM=self:_Flightdata2Text(playerData, AIRBOSS.GroovePos.IM)
|
local GIM,nIM=self:_Flightdata2Text(playerData, AIRBOSS.GroovePos.IM)
|
||||||
local GIC,nIC=self:_Flightdata2Text(playerData, AIRBOSS.GroovePos.IC)
|
local GIC,nIC=self:_Flightdata2Text(playerData, AIRBOSS.GroovePos.IC)
|
||||||
@ -12122,25 +12280,37 @@ function AIRBOSS:_LSOgrade(playerData)
|
|||||||
-- Put everything together.
|
-- Put everything together.
|
||||||
local G=GXX.." "..GIM.." ".." "..GIC.." "..GAR
|
local G=GXX.." "..GIM.." ".." "..GIC.." "..GAR
|
||||||
|
|
||||||
-- Count number of minor, normal and major deviations.
|
-- Count number of minor, normal and major deviations. TODO - work on Harrier counts due slower approach speed.
|
||||||
local N=nXX+nIM+nIC+nAR
|
local N=nXX+nIM+nIC+nAR
|
||||||
local nL=count(G, '_')/2
|
local nL=count(G, '_')/2
|
||||||
local nS=count(G, '%(')
|
local nS=count(G, '%(')
|
||||||
local nN=N-nS-nL
|
local nN=N-nS-nL
|
||||||
|
|
||||||
-- Groove time 15-18.99 sec for a unicorn.
|
-- Groove time 15-18.99 sec for a unicorn. Or 65-70 for V/STOL unicorn.
|
||||||
local Tgroove=playerData.Tgroove
|
local Tgroove=playerData.Tgroove
|
||||||
local TgrooveUnicorn=Tgroove and (Tgroove>=15.0 and Tgroove<=18.99) or false
|
local TgrooveUnicorn=Tgroove and (Tgroove>=15.0 and Tgroove<=18.99) or false
|
||||||
|
local TgrooveVstolUnicorn=Tgroove and (Tgroove>=65.0 and Tgroove<=70.0)and playerData.actype==AIRBOSS.AircraftCarrier.AV8B or false
|
||||||
|
|
||||||
local grade
|
local grade
|
||||||
local points
|
local points
|
||||||
if N==0 and TgrooveUnicorn then
|
if N==0 and (TgrooveUnicorn or TgrooveVstolUnicorn ) then
|
||||||
-- No deviations, should be REALLY RARE!
|
-- No deviations, should be REALLY RARE!
|
||||||
grade="_OK_"
|
grade="_OK_"
|
||||||
points=5.0
|
points=5.0
|
||||||
G="Unicorn"
|
G="Unicorn"
|
||||||
else
|
else
|
||||||
if nL>0 then
|
|
||||||
|
-- Add AV-8B Harrier devation allowances due to lower groundspeed and 3x conventional groove time, this allows to maintain LSO tolerances while respecting the deviations are not unsafe. (WIP requires feedback)
|
||||||
|
-- Large devaitions still result in a No Grade, A Unicorn still requires a clean pass with no deviation.
|
||||||
|
if nL>3 and playerData.actype==AIRBOSS.AircraftCarrier.AV8B then
|
||||||
|
-- Larger deviations ==> "No grade" 2.0 points.
|
||||||
|
grade="--"
|
||||||
|
points=2.0
|
||||||
|
elseif nN>2 and playerData.actype==AIRBOSS.AircraftCarrier.AV8B then
|
||||||
|
-- Only average deviations ==> "Fair Pass" Pass with average deviations and corrections.
|
||||||
|
grade="(OK)"
|
||||||
|
points=3.0
|
||||||
|
elseif nL>0 then
|
||||||
-- Larger deviations ==> "No grade" 2.0 points.
|
-- Larger deviations ==> "No grade" 2.0 points.
|
||||||
grade="--"
|
grade="--"
|
||||||
points=2.0
|
points=2.0
|
||||||
@ -12153,7 +12323,8 @@ function AIRBOSS:_LSOgrade(playerData)
|
|||||||
grade="OK"
|
grade="OK"
|
||||||
points=4.0
|
points=4.0
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
end
|
||||||
|
|
||||||
-- Replace" )"( and "__"
|
-- Replace" )"( and "__"
|
||||||
G=G:gsub("%)%(", "")
|
G=G:gsub("%)%(", "")
|
||||||
@ -12449,7 +12620,7 @@ function AIRBOSS:_GS(step, n)
|
|||||||
if n==-1 then
|
if n==-1 then
|
||||||
gp=AIRBOSS.GroovePos.IC
|
gp=AIRBOSS.GroovePos.IC
|
||||||
elseif n==1 then
|
elseif n==1 then
|
||||||
if self.carriertype==AIRBOSS.CarrierType.TARAWA then
|
if self.carriertype==AIRBOSS.CarrierType.TARAWA or self.carriertype==AIRBOSS.CarrierType.AMERICA or self.carriertype==AIRBOSS.CarrierType.JCARLOS then
|
||||||
gp=AIRBOSS.GroovePos.AL
|
gp=AIRBOSS.GroovePos.AL
|
||||||
else
|
else
|
||||||
gp=AIRBOSS.GroovePos.IW
|
gp=AIRBOSS.GroovePos.IW
|
||||||
@ -14339,17 +14510,17 @@ function AIRBOSS:_IsCarrierAircraft(unit)
|
|||||||
-- Get aircraft type name
|
-- Get aircraft type name
|
||||||
local aircrafttype=unit:GetTypeName()
|
local aircrafttype=unit:GetTypeName()
|
||||||
|
|
||||||
-- Special case for Harrier which can only land on Tarawa.
|
-- Special case for Harrier which can only land on Tarawa, LHA and LHD.
|
||||||
if aircrafttype==AIRBOSS.AircraftCarrier.AV8B then
|
if aircrafttype==AIRBOSS.AircraftCarrier.AV8B then
|
||||||
if self.carriertype==AIRBOSS.CarrierType.TARAWA then
|
if self.carriertype==AIRBOSS.CarrierType.TARAWA or self.carriertype==AIRBOSS.CarrierType.AMERICA or self.carriertype==AIRBOSS.CarrierType.JCARLOS then
|
||||||
return true
|
return true
|
||||||
else
|
else
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Also only Harriers can land on the Tarawa.
|
-- Also only Harriers can land on the Tarawa, LHA and LHD.
|
||||||
if self.carriertype==AIRBOSS.CarrierType.TARAWA then
|
if self.carriertype==AIRBOSS.CarrierType.TARAWA or self.carriertype==AIRBOSS.CarrierType.AMERICA or self.carriertype==AIRBOSS.CarrierType.JCARLOS then
|
||||||
if aircrafttype~=AIRBOSS.AircraftCarrier.AV8B then
|
if aircrafttype~=AIRBOSS.AircraftCarrier.AV8B then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
@ -17718,8 +17889,8 @@ function AIRBOSS:_MarkCaseZones(_unitName, flare)
|
|||||||
self:_GetZoneBullseye(case):FlareZone(FLARECOLOR.Green, 45)
|
self:_GetZoneBullseye(case):FlareZone(FLARECOLOR.Green, 45)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Tarawa landing spots.
|
-- Tarawa, LHA and LHD landing spots.
|
||||||
if self.carriertype==AIRBOSS.CarrierType.TARAWA then
|
if self.carriertype==AIRBOSS.CarrierType.TARAWA or self.carriertype==AIRBOSS.CarrierType.AMERICA or self.carriertype==AIRBOSS.CarrierType.JCARLOS then
|
||||||
text=text.."\n* abeam landing stop with RED flares"
|
text=text.."\n* abeam landing stop with RED flares"
|
||||||
-- Abeam landing spot zone.
|
-- Abeam landing spot zone.
|
||||||
local ALSPT=self:_GetZoneAbeamLandingSpot()
|
local ALSPT=self:_GetZoneAbeamLandingSpot()
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
--- **Ops** -- Combat Search and Rescue.
|
--- **Ops** -- Combat Search and Rescue.
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
@ -23,7 +22,7 @@
|
|||||||
-- @module Ops.CSAR
|
-- @module Ops.CSAR
|
||||||
-- @image OPS_CSAR.jpg
|
-- @image OPS_CSAR.jpg
|
||||||
|
|
||||||
-- Date: July 2021
|
-- Date: Sep 2021
|
||||||
|
|
||||||
-------------------------------------------------------------------------
|
-------------------------------------------------------------------------
|
||||||
--- **CSAR** class, extends Core.Base#BASE, Core.Fsm#FSM
|
--- **CSAR** class, extends Core.Base#BASE, Core.Fsm#FSM
|
||||||
@ -70,6 +69,7 @@
|
|||||||
--
|
--
|
||||||
-- self.allowDownedPilotCAcontrol = false -- Set to false if you don\'t want to allow control by Combined Arms.
|
-- self.allowDownedPilotCAcontrol = false -- Set to false if you don\'t want to allow control by Combined Arms.
|
||||||
-- self.allowFARPRescue = true -- allows pilots to be rescued by landing at a FARP or Airbase. Else MASH only!
|
-- self.allowFARPRescue = true -- allows pilots to be rescued by landing at a FARP or Airbase. Else MASH only!
|
||||||
|
-- self.FARPRescueDistance = 1000 -- you need to be this close to a FARP or Airport for the pilot to be rescued.
|
||||||
-- self.autosmoke = false -- automatically smoke a downed pilot\'s location when a heli is near.
|
-- self.autosmoke = false -- automatically smoke a downed pilot\'s location when a heli is near.
|
||||||
-- self.autosmokedistance = 1000 -- distance for autosmoke
|
-- self.autosmokedistance = 1000 -- distance for autosmoke
|
||||||
-- self.coordtype = 1 -- Use Lat/Long DDM (0), Lat/Long DMS (1), MGRS (2), Bullseye imperial (3) or Bullseye metric (4) for coordinates.
|
-- self.coordtype = 1 -- Use Lat/Long DDM (0), Lat/Long DMS (1), MGRS (2), Bullseye imperial (3) or Bullseye metric (4) for coordinates.
|
||||||
@ -95,6 +95,8 @@
|
|||||||
-- self.approachdist_far = 5000 -- switch do 10 sec interval approach mode, meters
|
-- self.approachdist_far = 5000 -- switch do 10 sec interval approach mode, meters
|
||||||
-- self.approachdist_near = 3000 -- switch to 5 sec interval approach mode, meters
|
-- self.approachdist_near = 3000 -- switch to 5 sec interval approach mode, meters
|
||||||
-- self.pilotmustopendoors = false -- switch to true to enable check of open doors
|
-- self.pilotmustopendoors = false -- switch to true to enable check of open doors
|
||||||
|
-- -- (added 0.1.9)
|
||||||
|
-- self.suppressmessages = false -- switch off all messaging if you want to do your own
|
||||||
--
|
--
|
||||||
-- ## 2.1 Experimental Features
|
-- ## 2.1 Experimental Features
|
||||||
--
|
--
|
||||||
@ -214,26 +216,6 @@ CSAR = {
|
|||||||
-- @field Wrapper.Group#GROUP group Spawned group object.
|
-- @field Wrapper.Group#GROUP group Spawned group object.
|
||||||
-- @field #number timestamp Timestamp for approach process
|
-- @field #number timestamp Timestamp for approach process
|
||||||
-- @field #boolean alive Group is alive or dead/rescued
|
-- @field #boolean alive Group is alive or dead/rescued
|
||||||
--
|
|
||||||
--- Updated and sorted list of known NDB beacons (in kHz!) from the available maps.
|
|
||||||
|
|
||||||
--[[ Moved to Utils
|
|
||||||
-- @field #CSAR.SkipFrequencies
|
|
||||||
CSAR.SkipFrequencies = {
|
|
||||||
214,274,291.5,295,297.5,
|
|
||||||
300.5,304,307,309.5,311,312,312.5,316,
|
|
||||||
320,324,328,329,330,336,337,
|
|
||||||
342,343,348,351,352,353,358,
|
|
||||||
363,365,368,372.5,374,
|
|
||||||
380,381,384,389,395,396,
|
|
||||||
414,420,430,432,435,440,450,455,462,470,485,
|
|
||||||
507,515,520,525,528,540,550,560,570,577,580,602,625,641,662,670,680,682,690,
|
|
||||||
705,720,722,730,735,740,745,750,770,795,
|
|
||||||
822,830,862,866,
|
|
||||||
905,907,920,935,942,950,995,
|
|
||||||
1000,1025,1030,1050,1065,1116,1175,1182,1210
|
|
||||||
}
|
|
||||||
--]]
|
|
||||||
|
|
||||||
--- All slot / Limit settings
|
--- All slot / Limit settings
|
||||||
-- @type CSAR.AircraftType
|
-- @type CSAR.AircraftType
|
||||||
@ -251,7 +233,7 @@ CSAR.AircraftType["Mi-24V"] = 8
|
|||||||
|
|
||||||
--- CSAR class version.
|
--- CSAR class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
CSAR.version="0.1.8r3"
|
CSAR.version="0.1.10r5"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- ToDo list
|
-- ToDo list
|
||||||
@ -361,12 +343,13 @@ function CSAR:New(Coalition, Template, Alias)
|
|||||||
self.loadtimemax = 135 -- seconds
|
self.loadtimemax = 135 -- seconds
|
||||||
self.radioSound = "beacon.ogg" -- the name of the sound file to use for the Pilot radio beacons. If this isnt added to the mission BEACONS WONT WORK!
|
self.radioSound = "beacon.ogg" -- the name of the sound file to use for the Pilot radio beacons. If this isnt added to the mission BEACONS WONT WORK!
|
||||||
self.allowFARPRescue = true --allows pilot to be rescued by landing at a FARP or Airbase
|
self.allowFARPRescue = true --allows pilot to be rescued by landing at a FARP or Airbase
|
||||||
|
self.FARPRescueDistance = 1000 -- you need to be this close to a FARP or Airport for the pilot to be rescued.
|
||||||
self.max_units = 6 --max number of pilots that can be carried
|
self.max_units = 6 --max number of pilots that can be carried
|
||||||
self.useprefix = true -- Use the Prefixed defined below, Requires Unit have the Prefix defined below
|
self.useprefix = true -- Use the Prefixed defined below, Requires Unit have the Prefix defined below
|
||||||
self.csarPrefix = { "helicargo", "MEDEVAC"} -- prefixes used for useprefix=true - DON\'T use # in names!
|
self.csarPrefix = { "helicargo", "MEDEVAC"} -- prefixes used for useprefix=true - DON\'T use # in names!
|
||||||
self.template = Template or "generic" -- template for downed pilot
|
self.template = Template or "generic" -- template for downed pilot
|
||||||
self.mashprefix = {"MASH"} -- prefixes used to find MASHes
|
self.mashprefix = {"MASH"} -- prefixes used to find MASHes
|
||||||
self.mash = SET_GROUP:New():FilterCoalitions(self.coalition):FilterPrefixes(self.mashprefix):FilterOnce() -- currently only GROUP objects, maybe support STATICs also?
|
|
||||||
self.autosmoke = false -- automatically smoke location when heli is near
|
self.autosmoke = false -- automatically smoke location when heli is near
|
||||||
self.autosmokedistance = 2000 -- distance for autosmoke
|
self.autosmokedistance = 2000 -- distance for autosmoke
|
||||||
-- added 0.1.4
|
-- added 0.1.4
|
||||||
@ -378,6 +361,7 @@ function CSAR:New(Coalition, Template, Alias)
|
|||||||
self.approachdist_far = 5000 -- switch do 10 sec interval approach mode, meters
|
self.approachdist_far = 5000 -- switch do 10 sec interval approach mode, meters
|
||||||
self.approachdist_near = 3000 -- switch to 5 sec interval approach mode, meters
|
self.approachdist_near = 3000 -- switch to 5 sec interval approach mode, meters
|
||||||
self.pilotmustopendoors = false -- switch to true to enable check on open doors
|
self.pilotmustopendoors = false -- switch to true to enable check on open doors
|
||||||
|
self.suppressmessages = false
|
||||||
|
|
||||||
-- WARNING - here\'ll be dragons
|
-- WARNING - here\'ll be dragons
|
||||||
-- for this to work you need to de-sanitize your mission environment in <DCS root>\Scripts\MissionScripting.lua
|
-- for this to work you need to de-sanitize your mission environment in <DCS root>\Scripts\MissionScripting.lua
|
||||||
@ -642,7 +626,7 @@ function CSAR:_AddCsar(_coalition , _country, _point, _typeName, _unitName, _pla
|
|||||||
local _typeName = _typeName or "Pilot"
|
local _typeName = _typeName or "Pilot"
|
||||||
|
|
||||||
if not noMessage then
|
if not noMessage then
|
||||||
self:_DisplayToAllSAR("MAYDAY MAYDAY! " .. _typeName .. " is down. ", self.coalition, 10)
|
self:_DisplayToAllSAR("MAYDAY MAYDAY! " .. _typeName .. " is down. ", self.coalition, self.messageTime)
|
||||||
end
|
end
|
||||||
|
|
||||||
if _freq then
|
if _freq then
|
||||||
@ -734,7 +718,6 @@ function CSAR:SpawnCSARAtZone(Zone, Coalition, Description, RandomPoint, Nomessa
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
-- TODO: Split in functions per Event type
|
|
||||||
--- (Internal) Event handler.
|
--- (Internal) Event handler.
|
||||||
-- @param #CSAR self
|
-- @param #CSAR self
|
||||||
function CSAR:_EventHandler(EventData)
|
function CSAR:_EventHandler(EventData)
|
||||||
@ -806,8 +789,7 @@ function CSAR:_EventHandler(EventData)
|
|||||||
if self:_DoubleEjection(_unitname) then
|
if self:_DoubleEjection(_unitname) then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
self:_DisplayToAllSAR("MAYDAY MAYDAY! " .. _unit:GetTypeName() .. " shot down. No Chute!", self.coalition, 10)
|
|
||||||
--local m = MESSAGE:New("MAYDAY MAYDAY! " .. _unit:GetTypeName() .. " shot down. No Chute!",10,"Info"):ToCoalition(self.coalition)
|
|
||||||
else
|
else
|
||||||
self:T(self.lid .. " Pilot has not taken off, ignore")
|
self:T(self.lid .. " Pilot has not taken off, ignore")
|
||||||
end
|
end
|
||||||
@ -887,12 +869,14 @@ function CSAR:_EventHandler(EventData)
|
|||||||
return -- error!
|
return -- error!
|
||||||
end
|
end
|
||||||
|
|
||||||
if _place:GetCoalition() == self.coalition or _place:GetCoalition() == coalition.side.NEUTRAL then
|
-- anyone on board?
|
||||||
if self.pilotmustopendoors and not self:_IsLoadingDoorOpen(_event.IniUnitName) then
|
if self.inTransitGroups[_event.IniUnitName] == nil then
|
||||||
self:_DisplayMessageToSAR(_unit, "Open the door to let me out!", self.messageTime, true)
|
-- ignore
|
||||||
else
|
return
|
||||||
self:_RescuePilots(_unit)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if _place:GetCoalition() == self.coalition or _place:GetCoalition() == coalition.side.NEUTRAL then
|
||||||
|
self:_ScheduledSARFlight(_event.IniUnitName,_event.IniGroupName,true)
|
||||||
else
|
else
|
||||||
self:T(string.format("Airfield %d, Unit %d", _place:GetCoalition(), _unit:GetCoalition()))
|
self:T(string.format("Airfield %d, Unit %d", _place:GetCoalition(), _unit:GetCoalition()))
|
||||||
end
|
end
|
||||||
@ -912,7 +896,6 @@ end
|
|||||||
function CSAR:_InitSARForPilot(_downedGroup, _GroupName, _freq, _nomessage)
|
function CSAR:_InitSARForPilot(_downedGroup, _GroupName, _freq, _nomessage)
|
||||||
self:T(self.lid .. " _InitSARForPilot")
|
self:T(self.lid .. " _InitSARForPilot")
|
||||||
local _leader = _downedGroup:GetUnit(1)
|
local _leader = _downedGroup:GetUnit(1)
|
||||||
--local _groupName = _downedGroup:GetName()
|
|
||||||
local _groupName = _GroupName
|
local _groupName = _GroupName
|
||||||
local _freqk = _freq / 1000
|
local _freqk = _freq / 1000
|
||||||
local _coordinatesText = self:_GetPositionOfWounded(_downedGroup)
|
local _coordinatesText = self:_GetPositionOfWounded(_downedGroup)
|
||||||
@ -928,7 +911,7 @@ function CSAR:_InitSARForPilot(_downedGroup, _GroupName, _freq, _nomessage)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- trigger FSM event
|
-- trigger FSM event
|
||||||
self:__PilotDown(2,_downedGroup, _freqk, _leadername, _coordinatesText)
|
self:__PilotDown(2,_downedGroup, _freqk, _groupName, _coordinatesText)
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
@ -1098,7 +1081,6 @@ function CSAR:_PickupUnit(_heliUnit, _pilotName, _woundedGroup, _woundedGroupNam
|
|||||||
local grouptable = downedgrouptable --#CSAR.DownedPilot
|
local grouptable = downedgrouptable --#CSAR.DownedPilot
|
||||||
self.inTransitGroups[_heliName][_woundedGroupName] =
|
self.inTransitGroups[_heliName][_woundedGroupName] =
|
||||||
{
|
{
|
||||||
-- DONE: Fix with #CSAR.DownedPilot
|
|
||||||
originalUnit = grouptable.originalUnit,
|
originalUnit = grouptable.originalUnit,
|
||||||
woundedGroup = _woundedGroupName,
|
woundedGroup = _woundedGroupName,
|
||||||
side = self.coalition,
|
side = self.coalition,
|
||||||
@ -1106,7 +1088,7 @@ function CSAR:_PickupUnit(_heliUnit, _pilotName, _woundedGroup, _woundedGroupNam
|
|||||||
player = grouptable.player,
|
player = grouptable.player,
|
||||||
}
|
}
|
||||||
|
|
||||||
_woundedGroup:Destroy()
|
_woundedGroup:Destroy(false)
|
||||||
self:_RemoveNameFromDownedPilots(_woundedGroupName,true)
|
self:_RemoveNameFromDownedPilots(_woundedGroupName,true)
|
||||||
|
|
||||||
self:_DisplayMessageToSAR(_heliUnit, string.format("%s: %s I\'m in! Get to the MASH ASAP! ", _heliName, _pilotName), self.messageTime,true,true)
|
self:_DisplayMessageToSAR(_heliUnit, string.format("%s: %s I\'m in! Get to the MASH ASAP! ", _heliName, _pilotName), self.messageTime,true,true)
|
||||||
@ -1137,39 +1119,8 @@ end
|
|||||||
-- @return #boolean outcome The outcome.
|
-- @return #boolean outcome The outcome.
|
||||||
function CSAR:_IsLoadingDoorOpen( unit_name )
|
function CSAR:_IsLoadingDoorOpen( unit_name )
|
||||||
self:T(self.lid .. " _IsLoadingDoorOpen")
|
self:T(self.lid .. " _IsLoadingDoorOpen")
|
||||||
local ret_val = false
|
return UTILS.IsLoadingDoorOpen(unit_name)
|
||||||
local unit = Unit.getByName(unit_name)
|
|
||||||
if unit ~= nil then
|
|
||||||
local type_name = unit:getTypeName()
|
|
||||||
|
|
||||||
if type_name == "Mi-8MT" and unit:getDrawArgumentValue(86) == 1 or unit:getDrawArgumentValue(250) == 1 then
|
|
||||||
self:T(unit_name .. " Cargo doors are open or cargo door not present")
|
|
||||||
ret_val = true
|
|
||||||
end
|
|
||||||
|
|
||||||
if type_name == "Mi-24P" and unit:getDrawArgumentValue(38) == 1 or unit:getDrawArgumentValue(86) == 1 then
|
|
||||||
self:T(unit_name .. " a side door is open")
|
|
||||||
ret_val = true
|
|
||||||
end
|
|
||||||
|
|
||||||
if type_name == "UH-1H" and unit:getDrawArgumentValue(43) == 1 or unit:getDrawArgumentValue(44) == 1 then
|
|
||||||
self:T(unit_name .. " a side door is open ")
|
|
||||||
ret_val = true
|
|
||||||
end
|
|
||||||
|
|
||||||
if string.find(type_name, "SA342" ) and unit:getDrawArgumentValue(34) == 1 or unit:getDrawArgumentValue(38) == 1 then
|
|
||||||
self:T(unit_name .. " front door(s) are open")
|
|
||||||
ret_val = true
|
|
||||||
end
|
|
||||||
|
|
||||||
if ret_val == false then
|
|
||||||
self:T(unit_name .. " all doors are closed")
|
|
||||||
end
|
|
||||||
return ret_val
|
|
||||||
|
|
||||||
end -- nil
|
|
||||||
|
|
||||||
return false
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- (Internal) Function to check if heli is close to group.
|
--- (Internal) Function to check if heli is close to group.
|
||||||
@ -1200,14 +1151,12 @@ function CSAR:_CheckCloseWoundedGroup(_distance, _heliUnit, _heliName, _woundedG
|
|||||||
else
|
else
|
||||||
self:_DisplayMessageToSAR(_heliUnit, string.format("%s: %s. You\'re close now! Land in a safe place, I will go there ", _heliName, _pilotName), self.messageTime,false,true)
|
self:_DisplayMessageToSAR(_heliUnit, string.format("%s: %s. You\'re close now! Land in a safe place, I will go there ", _heliName, _pilotName), self.messageTime,false,true)
|
||||||
end
|
end
|
||||||
--mark as shown for THIS heli and THIS group
|
|
||||||
self.heliCloseMessage[_lookupKeyHeli] = true
|
self.heliCloseMessage[_lookupKeyHeli] = true
|
||||||
end
|
end
|
||||||
|
|
||||||
-- have we landed close enough?
|
-- have we landed close enough?
|
||||||
if not _heliUnit:InAir() then
|
if not _heliUnit:InAir() then
|
||||||
|
|
||||||
-- if you land on them, doesnt matter if they were heading to someone else as you\'re closer, you win! :)
|
|
||||||
if self.pilotRuntoExtractPoint == true then
|
if self.pilotRuntoExtractPoint == true then
|
||||||
if (_distance < self.extractDistance) then
|
if (_distance < self.extractDistance) then
|
||||||
local _time = self.landedStatus[_lookupKeyHeli]
|
local _time = self.landedStatus[_lookupKeyHeli]
|
||||||
@ -1308,7 +1257,8 @@ end
|
|||||||
-- @param #CSAR self
|
-- @param #CSAR self
|
||||||
-- @param #string heliname Heli name
|
-- @param #string heliname Heli name
|
||||||
-- @param #string groupname Group name
|
-- @param #string groupname Group name
|
||||||
function CSAR:_ScheduledSARFlight(heliname,groupname)
|
-- @param #boolean isairport If true, EVENT.Landing took place at an airport or FARP
|
||||||
|
function CSAR:_ScheduledSARFlight(heliname,groupname, isairport)
|
||||||
self:T(self.lid .. " _ScheduledSARFlight")
|
self:T(self.lid .. " _ScheduledSARFlight")
|
||||||
self:T({heliname,groupname})
|
self:T({heliname,groupname})
|
||||||
local _heliUnit = self:_GetSARHeli(heliname)
|
local _heliUnit = self:_GetSARHeli(heliname)
|
||||||
@ -1331,8 +1281,8 @@ function CSAR:_ScheduledSARFlight(heliname,groupname)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if _dist < 200 and _heliUnit:InAir() == false then
|
if ( _dist < self.FARPRescueDistance or isairport ) and _heliUnit:InAir() == false then
|
||||||
if self.pilotmustopendoors and not self:_IsLoadingDoorOpen(heliname) then
|
if self.pilotmustopendoors and self:_IsLoadingDoorOpen(heliname) == false then
|
||||||
self:_DisplayMessageToSAR(_heliUnit, "Open the door to let me out!", self.messageTime, true)
|
self:_DisplayMessageToSAR(_heliUnit, "Open the door to let me out!", self.messageTime, true)
|
||||||
else
|
else
|
||||||
self:_RescuePilots(_heliUnit)
|
self:_RescuePilots(_heliUnit)
|
||||||
@ -1341,7 +1291,7 @@ function CSAR:_ScheduledSARFlight(heliname,groupname)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--queue up
|
--queue up
|
||||||
self:__Returning(-5,heliname,_woundedGroupName)
|
self:__Returning(-5,heliname,_woundedGroupName, isairport)
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -1358,7 +1308,6 @@ function CSAR:_RescuePilots(_heliUnit)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- DONE: count saved units?
|
|
||||||
local PilotsSaved = self:_PilotsOnboard(_heliName)
|
local PilotsSaved = self:_PilotsOnboard(_heliName)
|
||||||
|
|
||||||
self.inTransitGroups[_heliName] = nil
|
self.inTransitGroups[_heliName] = nil
|
||||||
@ -1397,7 +1346,9 @@ function CSAR:_DisplayMessageToSAR(_unit, _text, _time, _clear, _speak)
|
|||||||
local group = _unit:GetGroup()
|
local group = _unit:GetGroup()
|
||||||
local _clear = _clear or nil
|
local _clear = _clear or nil
|
||||||
local _time = _time or self.messageTime
|
local _time = _time or self.messageTime
|
||||||
|
if not self.suppressmessages then
|
||||||
local m = MESSAGE:New(_text,_time,"Info",_clear):ToGroup(group)
|
local m = MESSAGE:New(_text,_time,"Info",_clear):ToGroup(group)
|
||||||
|
end
|
||||||
-- integrate SRS
|
-- integrate SRS
|
||||||
if _speak and self.useSRS then
|
if _speak and self.useSRS then
|
||||||
local srstext = SOUNDTEXT:New(_text)
|
local srstext = SOUNDTEXT:New(_text)
|
||||||
@ -1452,7 +1403,6 @@ function CSAR:_DisplayActiveSAR(_unitName)
|
|||||||
local _groupName = _value.name
|
local _groupName = _value.name
|
||||||
self:T(string.format("Display Active Pilot: %s", tostring(_groupName)))
|
self:T(string.format("Display Active Pilot: %s", tostring(_groupName)))
|
||||||
self:T({Table=_value})
|
self:T({Table=_value})
|
||||||
--local _woundedGroup = GROUP:FindByName(_groupName)
|
|
||||||
local _woundedGroup = _value.group
|
local _woundedGroup = _value.group
|
||||||
if _woundedGroup and _value.alive then
|
if _woundedGroup and _value.alive then
|
||||||
local _coordinatesText = self:_GetPositionOfWounded(_woundedGroup)
|
local _coordinatesText = self:_GetPositionOfWounded(_woundedGroup)
|
||||||
@ -1495,10 +1445,17 @@ function CSAR:_GetClosestDownedPilot(_heli)
|
|||||||
local _shortestDistance = -1
|
local _shortestDistance = -1
|
||||||
local _distance = 0
|
local _distance = 0
|
||||||
local _closestGroupInfo = nil
|
local _closestGroupInfo = nil
|
||||||
local _heliCoord = _heli:GetCoordinate()
|
local _heliCoord = _heli:GetCoordinate() or _heli:GetCoordinate()
|
||||||
|
|
||||||
|
if _heliCoord == nil then
|
||||||
|
self:E("****Error obtaining coordinate!")
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
local DownedPilotsTable = self.downedPilots
|
local DownedPilotsTable = self.downedPilots
|
||||||
for _, _groupInfo in pairs(DownedPilotsTable) do
|
|
||||||
|
for _, _groupInfo in UTILS.spairs(DownedPilotsTable) do
|
||||||
|
--for _, _groupInfo in pairs(DownedPilotsTable) do
|
||||||
local _woundedName = _groupInfo.name
|
local _woundedName = _groupInfo.name
|
||||||
local _tempWounded = _groupInfo.group
|
local _tempWounded = _groupInfo.group
|
||||||
|
|
||||||
@ -1564,14 +1521,13 @@ end
|
|||||||
-- @param #number _messagetime How long to show.
|
-- @param #number _messagetime How long to show.
|
||||||
function CSAR:_DisplayToAllSAR(_message, _side, _messagetime)
|
function CSAR:_DisplayToAllSAR(_message, _side, _messagetime)
|
||||||
self:T(self.lid .. " _DisplayToAllSAR")
|
self:T(self.lid .. " _DisplayToAllSAR")
|
||||||
|
local messagetime = _messagetime or self.messageTime
|
||||||
for _, _unitName in pairs(self.csarUnits) do
|
for _, _unitName in pairs(self.csarUnits) do
|
||||||
local _unit = self:_GetSARHeli(_unitName)
|
local _unit = self:_GetSARHeli(_unitName)
|
||||||
if _unit then
|
if _unit and not self.suppressmessages then
|
||||||
if not _messagetime then
|
|
||||||
self:_DisplayMessageToSAR(_unit, _message, _messagetime)
|
self:_DisplayMessageToSAR(_unit, _message, _messagetime)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -1741,9 +1697,20 @@ end
|
|||||||
function CSAR:_GetDistance(_point1, _point2)
|
function CSAR:_GetDistance(_point1, _point2)
|
||||||
self:T(self.lid .. " _GetDistance")
|
self:T(self.lid .. " _GetDistance")
|
||||||
if _point1 and _point2 then
|
if _point1 and _point2 then
|
||||||
local distance = _point1:DistanceFromPointVec2(_point2)
|
local distance1 = _point1:Get2DDistance(_point2)
|
||||||
return distance
|
local distance2 = _point1:DistanceFromPointVec2(_point2)
|
||||||
|
if distance1 and type(distance1) == "number" then
|
||||||
|
return distance1
|
||||||
|
elseif distance2 and type(distance2) == "number" then
|
||||||
|
return distance2
|
||||||
else
|
else
|
||||||
|
self:E("*****Cannot calculate distance!")
|
||||||
|
self:E({_point1,_point2})
|
||||||
|
return -1
|
||||||
|
end
|
||||||
|
else
|
||||||
|
self:E("******Cannot calculate distance!")
|
||||||
|
self:E({_point1,_point2})
|
||||||
return -1
|
return -1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -1752,7 +1719,6 @@ end
|
|||||||
-- @param #CSAR self
|
-- @param #CSAR self
|
||||||
function CSAR:_GenerateVHFrequencies()
|
function CSAR:_GenerateVHFrequencies()
|
||||||
self:T(self.lid .. " _GenerateVHFrequencies")
|
self:T(self.lid .. " _GenerateVHFrequencies")
|
||||||
--local _skipFrequencies = self.SkipFrequencies
|
|
||||||
|
|
||||||
local FreeVHFFrequencies = {}
|
local FreeVHFFrequencies = {}
|
||||||
FreeVHFFrequencies = UTILS.GenerateVHFrequencies()
|
FreeVHFFrequencies = UTILS.GenerateVHFrequencies()
|
||||||
@ -1792,7 +1758,6 @@ function CSAR:_GetClockDirection(_heli, _group)
|
|||||||
if _heading then
|
if _heading then
|
||||||
local Aspect = Angle - _heading
|
local Aspect = Angle - _heading
|
||||||
if Aspect == 0 then Aspect = 360 end
|
if Aspect == 0 then Aspect = 360 end
|
||||||
--clock = math.floor(Aspect / 30)
|
|
||||||
clock = math.abs(UTILS.Round((Aspect / 30),0))
|
clock = math.abs(UTILS.Round((Aspect / 30),0))
|
||||||
if clock == 0 then clock = 12 end
|
if clock == 0 then clock = 12 end
|
||||||
end
|
end
|
||||||
@ -1901,6 +1866,7 @@ function CSAR:onafterStart(From, Event, To)
|
|||||||
else
|
else
|
||||||
self.allheligroupset = SET_GROUP:New():FilterCoalitions(self.coalitiontxt):FilterCategoryHelicopter():FilterStart()
|
self.allheligroupset = SET_GROUP:New():FilterCoalitions(self.coalitiontxt):FilterCategoryHelicopter():FilterStart()
|
||||||
end
|
end
|
||||||
|
self.mash = SET_GROUP:New():FilterCoalitions(self.coalitiontxt):FilterPrefixes(self.mashprefix):FilterStart() -- currently only GROUP objects, maybe support STATICs also?
|
||||||
self:__Status(-10)
|
self:__Status(-10)
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
@ -1909,19 +1875,19 @@ end
|
|||||||
-- @param #CSAR self
|
-- @param #CSAR self
|
||||||
function CSAR:_CheckDownedPilotTable()
|
function CSAR:_CheckDownedPilotTable()
|
||||||
local pilots = self.downedPilots
|
local pilots = self.downedPilots
|
||||||
for _,_entry in pairs (pilots) do
|
local npilots = {}
|
||||||
self:T("Checking for " .. _entry.name)
|
|
||||||
self:T({entry=_entry})
|
for _ind,_entry in pairs(pilots) do
|
||||||
local group = _entry.group
|
local _group = _entry.group
|
||||||
if not group:IsAlive() then
|
if _group:IsAlive() then
|
||||||
self:T("Group is dead")
|
npilots[_ind] = _entry
|
||||||
if _entry.alive == true then
|
else
|
||||||
self:T("Switching .alive to false")
|
if _entry.alive then
|
||||||
self:__KIA(1,_entry.desc)
|
self:__KIA(1,_entry.desc)
|
||||||
self:_RemoveNameFromDownedPilots(_entry.name,true)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
self.downedPilots = npilots
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -2041,9 +2007,10 @@ end
|
|||||||
-- @param #string To To state.
|
-- @param #string To To state.
|
||||||
-- @param #string Heliname Name of the helicopter group.
|
-- @param #string Heliname Name of the helicopter group.
|
||||||
-- @param #string Woundedgroupname Name of the downed pilot\'s group.
|
-- @param #string Woundedgroupname Name of the downed pilot\'s group.
|
||||||
function CSAR:onbeforeReturning(From, Event, To, Heliname, Woundedgroupname)
|
-- @param #boolean IsAirport True if heli has landed on an AFB (from event land).
|
||||||
|
function CSAR:onbeforeReturning(From, Event, To, Heliname, Woundedgroupname, IsAirPort)
|
||||||
self:T({From, Event, To, Heliname, Woundedgroupname})
|
self:T({From, Event, To, Heliname, Woundedgroupname})
|
||||||
self:_ScheduledSARFlight(Heliname,Woundedgroupname)
|
self:_ScheduledSARFlight(Heliname,Woundedgroupname, IsAirPort)
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -162,33 +162,33 @@ RADIOSPEECH.Vocabulary.RU = {
|
|||||||
["8000"] = { "8000", 0.92 },
|
["8000"] = { "8000", 0.92 },
|
||||||
["9000"] = { "9000", 0.87 },
|
["9000"] = { "9000", 0.87 },
|
||||||
|
|
||||||
["Ñ<EFBFBD>тепени"] = { "degrees", 0.5 },
|
["градусы"] = { "degrees", 0.5 },
|
||||||
["километров"] = { "kilometers", 0.65 },
|
["километры"] = { "kilometers", 0.65 },
|
||||||
["km"] = { "kilometers", 0.65 },
|
["km"] = { "kilometers", 0.65 },
|
||||||
["миль"] = { "miles", 0.45 },
|
["мили"] = { "miles", 0.45 },
|
||||||
["mi"] = { "miles", 0.45 },
|
["mi"] = { "miles", 0.45 },
|
||||||
["метры"] = { "meters", 0.41 },
|
["метров"] = { "meters", 0.41 },
|
||||||
["m"] = { "meters", 0.41 },
|
["m"] = { "meters", 0.41 },
|
||||||
["ноги"] = { "feet", 0.37 },
|
["ноги"] = { "feet", 0.37 },
|
||||||
|
|
||||||
["br"] = { "br", 1.1 },
|
["br"] = { "br", 1.1 },
|
||||||
["bra"] = { "bra", 0.3 },
|
["bra"] = { "bra", 0.3 },
|
||||||
|
|
||||||
|
|
||||||
["возвращаÑ<EFBFBD>Ñ<EFBFBD>ÑŒ на базу"] = { "returning_to_base", 1.40 },
|
["возвращение на базу"] = { "returning_to_base", 1.40 },
|
||||||
["на пути к наземной цели"] = { "on_route_to_ground_target", 1.45 },
|
["на пути к наземной цели"] = { "on_route_to_ground_target", 1.45 },
|
||||||
["перехват Ñ<>амолетов"] = { "intercepting_bogeys", 1.22 },
|
["перехват боги"] = { "intercepting_bogeys", 1.22 },
|
||||||
["поражение наземной цели"] = { "engaging_ground_target", 1.53 },
|
["поражение наземной цели"] = { "engaging_ground_target", 1.53 },
|
||||||
["захватывающие Ñ<>амолеты"] = { "engaging_bogeys", 1.68 },
|
["привлечение болотных птиц"] = { "engaging_bogeys", 1.68 },
|
||||||
["колеÑ<EFBFBD>а вверх"] = { "wheels_up", 0.92 },
|
["колёса вверх..."] = { "wheels_up", 0.92 },
|
||||||
["поÑ<EFBFBD>адка на базу"] = { "landing at base", 1.04 },
|
["посадка на базу"] = { "landing at base", 1.04 },
|
||||||
["патрулирующий"] = { "patrolling", 0.96 },
|
["патрулирование"] = { "patrolling", 0.96 },
|
||||||
|
|
||||||
["за"] = { "for", 0.27 },
|
["для"] = { "for", 0.27 },
|
||||||
["и"] = { "and", 0.17 },
|
["и"] = { "and", 0.17 },
|
||||||
["в"] = { "at", 0.19 },
|
["на сайте"] = { "at", 0.19 },
|
||||||
["dot"] = { "dot", 0.51 },
|
["точка"] = { "dot", 0.51 },
|
||||||
["defender"] = { "defender", 0.45 },
|
["защитник"] = { "defender", 0.45 },
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Create a new RADIOSPEECH object for a given radio frequency/modulation.
|
--- Create a new RADIOSPEECH object for a given radio frequency/modulation.
|
||||||
|
|||||||
@ -507,7 +507,7 @@ UTILS.tostringLL = function( lat, lon, acc, DMS)
|
|||||||
secFrmtStr = '%0' .. width .. '.' .. acc .. 'f'
|
secFrmtStr = '%0' .. width .. '.' .. acc .. 'f'
|
||||||
end
|
end
|
||||||
|
|
||||||
-- 024<EFBFBD> 23' 12"N or 024<32> 23' 12.03"N
|
-- 024° 23' 12"N or 024° 23' 12.03"N
|
||||||
return string.format('%03d°', latDeg)..string.format('%02d', latMin)..'\''..string.format(secFrmtStr, latSec)..'"'..latHemi..' '
|
return string.format('%03d°', latDeg)..string.format('%02d', latMin)..'\''..string.format(secFrmtStr, latSec)..'"'..latHemi..' '
|
||||||
.. string.format('%03d°', lonDeg)..string.format('%02d', lonMin)..'\''..string.format(secFrmtStr, lonSec)..'"'..lonHemi
|
.. string.format('%03d°', lonDeg)..string.format('%02d', lonMin)..'\''..string.format(secFrmtStr, lonSec)..'"'..lonHemi
|
||||||
|
|
||||||
@ -923,7 +923,7 @@ function UTILS.RandomGaussian(x0, sigma, xmin, xmax, imax)
|
|||||||
local x1=math.random()
|
local x1=math.random()
|
||||||
local x2=math.random()
|
local x2=math.random()
|
||||||
|
|
||||||
-- Transform to Gaussian exp(-(x-x0)²/(2*sigma²).
|
-- Transform to Gaussian exp(-(x-x0)°/(2*sigma°).
|
||||||
r = math.sqrt(-2*sigma*sigma * math.log(x1)) * math.cos(2*math.pi * x2) + x0
|
r = math.sqrt(-2*sigma*sigma * math.log(x1)) * math.cos(2*math.pi * x2) + x0
|
||||||
|
|
||||||
i=i+1
|
i=i+1
|
||||||
@ -1615,7 +1615,7 @@ end
|
|||||||
--@return #table
|
--@return #table
|
||||||
function UTILS.ShuffleTable(t)
|
function UTILS.ShuffleTable(t)
|
||||||
if t == nil or type(t) ~= "table" then
|
if t == nil or type(t) ~= "table" then
|
||||||
BASE:I("Error in ShuffleTable: Missing or wrong tyåe of Argument")
|
BASE:I("Error in ShuffleTable: Missing or wrong type of Argument")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
math.random()
|
math.random()
|
||||||
@ -1640,7 +1640,7 @@ function UTILS.IsLoadingDoorOpen( unit_name )
|
|||||||
if unit ~= nil then
|
if unit ~= nil then
|
||||||
local type_name = unit:getTypeName()
|
local type_name = unit:getTypeName()
|
||||||
|
|
||||||
if type_name == "Mi-8MT" and unit:getDrawArgumentValue(86) == 1 or unit:getDrawArgumentValue(250) == 1 then
|
if type_name == "Mi-8MT" and unit:getDrawArgumentValue(38) == 1 or unit:getDrawArgumentValue(86) == 1 or unit:getDrawArgumentValue(250) == 1 then
|
||||||
BASE:T(unit_name .. " Cargo doors are open or cargo door not present")
|
BASE:T(unit_name .. " Cargo doors are open or cargo door not present")
|
||||||
ret_val = true
|
ret_val = true
|
||||||
end
|
end
|
||||||
@ -1803,7 +1803,7 @@ function UTILS.GenerateLaserCodes()
|
|||||||
while _code < 1777 and _count < 30 do
|
while _code < 1777 and _count < 30 do
|
||||||
while true do
|
while true do
|
||||||
_code = _code + 1
|
_code = _code + 1
|
||||||
if not self:_ContainsDigit(_code, 8)
|
if not ContainsDigit(_code, 8)
|
||||||
and not ContainsDigit(_code, 9)
|
and not ContainsDigit(_code, 9)
|
||||||
and not ContainsDigit(_code, 0) then
|
and not ContainsDigit(_code, 0) then
|
||||||
table.insert(jtacGeneratedLaserCodes, _code)
|
table.insert(jtacGeneratedLaserCodes, _code)
|
||||||
|
|||||||
@ -1134,7 +1134,7 @@ function AIRBASE:MarkParkingSpots(termtype, mark)
|
|||||||
|
|
||||||
-- Get airbase name.
|
-- Get airbase name.
|
||||||
local airbasename=self:GetName()
|
local airbasename=self:GetName()
|
||||||
self:E(string.format("Parking spots at %s for termial type %s:", airbasename, tostring(termtype)))
|
self:E(string.format("Parking spots at %s for terminal type %s:", airbasename, tostring(termtype)))
|
||||||
|
|
||||||
for _,_spot in pairs(parkingdata) do
|
for _,_spot in pairs(parkingdata) do
|
||||||
|
|
||||||
@ -1211,14 +1211,25 @@ function AIRBASE:FindFreeParkingSpotForAircraft(group, terminaltype, scanradius,
|
|||||||
parkingdata=parkingdata or self:GetParkingSpotsTable(terminaltype)
|
parkingdata=parkingdata or self:GetParkingSpotsTable(terminaltype)
|
||||||
|
|
||||||
-- Get the aircraft size, i.e. it's longest side of x,z.
|
-- Get the aircraft size, i.e. it's longest side of x,z.
|
||||||
local aircraft=group:GetUnit(1)
|
local aircraft = nil
|
||||||
local _aircraftsize, ax,ay,az=aircraft:GetObjectSize()
|
local _aircraftsize, ax,ay,az
|
||||||
|
if group and group.ClassName == "GROUP" then
|
||||||
|
aircraft=group:GetUnit(1)
|
||||||
|
_aircraftsize, ax,ay,az=aircraft:GetObjectSize()
|
||||||
|
else
|
||||||
|
-- SU27 dimensions
|
||||||
|
_aircraftsize = 23
|
||||||
|
ax = 23 -- length
|
||||||
|
ay = 7 -- height
|
||||||
|
az = 17 -- width
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Number of spots we are looking for. Note that, e.g. grouping can require a number different from the group size!
|
-- Number of spots we are looking for. Note that, e.g. grouping can require a number different from the group size!
|
||||||
local _nspots=nspots or group:GetSize()
|
local _nspots=nspots or group:GetSize()
|
||||||
|
|
||||||
-- Debug info.
|
-- Debug info.
|
||||||
self:E(string.format("%s: Looking for %d parking spot(s) for aircraft of size %.1f m (x=%.1f,y=%.1f,z=%.1f) at termial type %s.", airport, _nspots, _aircraftsize, ax, ay, az, tostring(terminaltype)))
|
self:E(string.format("%s: Looking for %d parking spot(s) for aircraft of size %.1f m (x=%.1f,y=%.1f,z=%.1f) at terminal type %s.", airport, _nspots, _aircraftsize, ax, ay, az, tostring(terminaltype)))
|
||||||
|
|
||||||
-- Table of valid spots.
|
-- Table of valid spots.
|
||||||
local validspots={}
|
local validspots={}
|
||||||
@ -1341,6 +1352,7 @@ function AIRBASE:FindFreeParkingSpotForAircraft(group, terminaltype, scanradius,
|
|||||||
|
|
||||||
-- Retrun spots we found, even if there were not enough.
|
-- Retrun spots we found, even if there were not enough.
|
||||||
return validspots
|
return validspots
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Check black and white lists.
|
--- Check black and white lists.
|
||||||
|
|||||||
@ -3777,8 +3777,9 @@ end
|
|||||||
-- @param #number radius Radius of the relocation zone, default 500
|
-- @param #number radius Radius of the relocation zone, default 500
|
||||||
-- @param #boolean onroad If true, route on road (less problems with AI way finding), default true
|
-- @param #boolean onroad If true, route on road (less problems with AI way finding), default true
|
||||||
-- @param #boolean shortcut If true and onroad is set, take a shorter route - if available - off road, default false
|
-- @param #boolean shortcut If true and onroad is set, take a shorter route - if available - off road, default false
|
||||||
|
-- @param #string formation Formation string as in the mission editor, e.g. "Vee", "Diamond", "Line abreast", etc. Defaults to "Off Road"
|
||||||
-- @return #CONTROLLABLE self
|
-- @return #CONTROLLABLE self
|
||||||
function CONTROLLABLE:RelocateGroundRandomInRadius(speed, radius, onroad, shortcut)
|
function CONTROLLABLE:RelocateGroundRandomInRadius(speed, radius, onroad, shortcut, formation)
|
||||||
self:F2( { self.ControllableName } )
|
self:F2( { self.ControllableName } )
|
||||||
|
|
||||||
local _coord = self:GetCoordinate()
|
local _coord = self:GetCoordinate()
|
||||||
@ -3789,14 +3790,14 @@ function CONTROLLABLE:RelocateGroundRandomInRadius(speed, radius, onroad, shortc
|
|||||||
local _grptsk = {}
|
local _grptsk = {}
|
||||||
local _candoroad = false
|
local _candoroad = false
|
||||||
local _shortcut = shortcut or false
|
local _shortcut = shortcut or false
|
||||||
|
local _formation = formation or "Off Road"
|
||||||
|
|
||||||
-- create a DCS Task an push it on the group
|
-- create a DCS Task an push it on the group
|
||||||
-- TaskGroundOnRoad(ToCoordinate,Speed,OffRoadFormation,Shortcut,FromCoordinate,WaypointFunction,WaypointFunctionArguments)
|
|
||||||
if onroad then
|
if onroad then
|
||||||
_grptsk, _candoroad = self:TaskGroundOnRoad(_tocoord,_speed,"Off Road",_shortcut)
|
_grptsk, _candoroad = self:TaskGroundOnRoad(_tocoord,_speed,_formation,_shortcut)
|
||||||
self:Route(_grptsk,5)
|
self:Route(_grptsk,5)
|
||||||
else
|
else
|
||||||
self:TaskRouteToVec2(_tocoord:GetVec2(),_speed,"Off Road")
|
self:TaskRouteToVec2(_tocoord:GetVec2(),_speed,_formation)
|
||||||
end
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
|
|||||||
@ -1142,6 +1142,7 @@ function GROUP:GetAmmunition()
|
|||||||
local Nshells=0
|
local Nshells=0
|
||||||
local Nrockets=0
|
local Nrockets=0
|
||||||
local Nmissiles=0
|
local Nmissiles=0
|
||||||
|
local Nbombs=0
|
||||||
|
|
||||||
if DCSControllable then
|
if DCSControllable then
|
||||||
|
|
||||||
@ -1150,18 +1151,19 @@ function GROUP:GetAmmunition()
|
|||||||
local Unit = UnitData -- Wrapper.Unit#UNIT
|
local Unit = UnitData -- Wrapper.Unit#UNIT
|
||||||
|
|
||||||
-- Get ammo of the unit
|
-- Get ammo of the unit
|
||||||
local ntot, nshells, nrockets, nmissiles = Unit:GetAmmunition()
|
local ntot, nshells, nrockets, nbombs, nmissiles = Unit:GetAmmunition()
|
||||||
|
|
||||||
Ntot=Ntot+ntot
|
Ntot=Ntot+ntot
|
||||||
Nshells=Nshells+nshells
|
Nshells=Nshells+nshells
|
||||||
Nrockets=Nrockets+nrockets
|
Nrockets=Nrockets+nrockets
|
||||||
Nmissiles=Nmissiles+nmissiles
|
Nmissiles=Nmissiles+nmissiles
|
||||||
|
Nbombs=Nbombs+nbombs
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return Ntot, Nshells, Nrockets, Nmissiles
|
return Ntot, Nshells, Nrockets, Nbombs, Nmissiles
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@ -2589,6 +2591,17 @@ function GROUP:SetCommandImmortal(switch)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Get skill from Group. Effectively gets the skill from Unit 1 as the group holds no skill value.
|
||||||
|
-- @param #GROUP self
|
||||||
|
-- @return #string Skill String of skill name.
|
||||||
|
function GROUP:GetSkill()
|
||||||
|
self:F2( self.GroupName )
|
||||||
|
local unit = self:GetUnit(1)
|
||||||
|
local name = unit:GetName()
|
||||||
|
local skill = _DATABASE.Templates.Units[name].Template.skill or "Random"
|
||||||
|
return skill
|
||||||
|
end
|
||||||
|
|
||||||
--do -- Smoke
|
--do -- Smoke
|
||||||
--
|
--
|
||||||
----- Signal a flare at the position of the GROUP.
|
----- Signal a flare at the position of the GROUP.
|
||||||
|
|||||||
@ -1517,6 +1517,7 @@ do -- Cargo
|
|||||||
["Ural-4320 APA-5D"] = 10,
|
["Ural-4320 APA-5D"] = 10,
|
||||||
["Ural-4320T"] = 14,
|
["Ural-4320T"] = 14,
|
||||||
["ZBD04A"] = 7, -- new by kappa
|
["ZBD04A"] = 7, -- new by kappa
|
||||||
|
["VAB_Mephisto"] = 8, -- new by Apple
|
||||||
}
|
}
|
||||||
|
|
||||||
local CargoBayWeightLimit = ( Weights[Desc.typeName] or 0 ) * 95
|
local CargoBayWeightLimit = ( Weights[Desc.typeName] or 0 ) * 95
|
||||||
|
|||||||
@ -637,6 +637,18 @@ function UNIT:GetAmmo()
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Sets the Unit's Internal Cargo Mass, in kg
|
||||||
|
-- @param #UNIT self
|
||||||
|
-- @param #number mass to set cargo to
|
||||||
|
-- @return #UNIT self
|
||||||
|
function UNIT:SetUnitInternalCargo(mass)
|
||||||
|
local DCSUnit = self:GetDCSObject()
|
||||||
|
if DCSUnit then
|
||||||
|
trigger.action.setUnitInternalCargo(DCSUnit:getName(), mass)
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- Get the number of ammunition and in particular the number of shells, rockets, bombs and missiles a unit currently has.
|
--- Get the number of ammunition and in particular the number of shells, rockets, bombs and missiles a unit currently has.
|
||||||
-- @param #UNIT self
|
-- @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 Total amount of ammo the unit has left. This is the sum of shells, rockets, bombs and missiles.
|
||||||
@ -1471,3 +1483,13 @@ function UNIT:EnableEmission(switch)
|
|||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Get skill from Unit.
|
||||||
|
-- @param #UNIT self
|
||||||
|
-- @return #string Skill String of skill name.
|
||||||
|
function UNIT:GetSkill()
|
||||||
|
self:F2( self.UnitName )
|
||||||
|
local name = self.UnitName
|
||||||
|
local skill = _DATABASE.Templates.Units[name].Template.skill or "Random"
|
||||||
|
return skill
|
||||||
|
end
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user