mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-10-29 16:58:06 +00:00
AIRBOSS v0.3.9
This commit is contained in:
parent
5e8b461478
commit
50c40cb4e9
@ -7,7 +7,7 @@
|
|||||||
-- * CASE I, II and III recoveries.
|
-- * CASE I, II and III recoveries.
|
||||||
-- * Supports human pilots as well as AI flight groups.
|
-- * Supports human pilots as well as AI flight groups.
|
||||||
-- * Automatic LSO grading.
|
-- * Automatic LSO grading.
|
||||||
-- * Different skill levels from tipps on-the-fly for students to complete ziplip for pros.
|
-- * Different skill levels from on-the-fly tipps for students to ziplip for pros.
|
||||||
-- * Recovery tanker option.
|
-- * Recovery tanker option.
|
||||||
-- * Voice overs for LSO and AIRBOSS calls. Can easily be customized by users.
|
-- * Voice overs for LSO and AIRBOSS calls. Can easily be customized by users.
|
||||||
-- * Automatic TACAN and ICLS channel setting.
|
-- * Automatic TACAN and ICLS channel setting.
|
||||||
@ -58,7 +58,6 @@
|
|||||||
-- @field #AIRBOSS.Checkpoint Wake Right behind the carrier.
|
-- @field #AIRBOSS.Checkpoint Wake Right behind the carrier.
|
||||||
-- @field #AIRBOSS.Checkpoint Groove In the groove checkpoint.
|
-- @field #AIRBOSS.Checkpoint Groove In the groove checkpoint.
|
||||||
-- @field #AIRBOSS.Checkpoint Trap Landing checkpoint.
|
-- @field #AIRBOSS.Checkpoint Trap Landing checkpoint.
|
||||||
-- @field #AIRBOSS.Checkpoint Descent4k Case II/III descent at 4000 ft/min right after leaving holding pattern.
|
|
||||||
-- @field #AIRBOSS.Checkpoint Platform Case II/III descent at 2000 ft/min at 5000 ft platform.
|
-- @field #AIRBOSS.Checkpoint Platform Case II/III descent at 2000 ft/min at 5000 ft platform.
|
||||||
-- @field #AIRBOSS.Checkpoint DirtyUp Case II/III dirty up and on speed position at 1200 ft and 10-12 NM from the carrier.
|
-- @field #AIRBOSS.Checkpoint DirtyUp Case II/III dirty up and on speed position at 1200 ft and 10-12 NM from the carrier.
|
||||||
-- @field #AIRBOSS.Checkpoint Bullseye Case III intercept glideslope and follow ICLS aka "bullseye".
|
-- @field #AIRBOSS.Checkpoint Bullseye Case III intercept glideslope and follow ICLS aka "bullseye".
|
||||||
@ -140,7 +139,6 @@ AIRBOSS = {
|
|||||||
Wake = {},
|
Wake = {},
|
||||||
Groove = {},
|
Groove = {},
|
||||||
Trap = {},
|
Trap = {},
|
||||||
Descent4k = {},
|
|
||||||
Platform = {},
|
Platform = {},
|
||||||
DirtyUp = {},
|
DirtyUp = {},
|
||||||
Bullseye = {},
|
Bullseye = {},
|
||||||
@ -220,10 +218,13 @@ AIRBOSS.CarrierType={
|
|||||||
-- @type AIRBOSS.PatternStep
|
-- @type AIRBOSS.PatternStep
|
||||||
AIRBOSS.PatternStep={
|
AIRBOSS.PatternStep={
|
||||||
UNDEFINED="Undefined",
|
UNDEFINED="Undefined",
|
||||||
|
REFUELING="Refueling",
|
||||||
|
SPINNING="Spinning",
|
||||||
COMMENCING="Commencing",
|
COMMENCING="Commencing",
|
||||||
HOLDING="Holding",
|
HOLDING="Holding",
|
||||||
DESCENT4K="Descent 4000 ft/min",
|
|
||||||
PLATFORM="Platform",
|
PLATFORM="Platform",
|
||||||
|
ARCIN="Arc Turn In",
|
||||||
|
ARCOUT="Arc Turn Out",
|
||||||
DIRTYUP="Level out and Dirty Up",
|
DIRTYUP="Level out and Dirty Up",
|
||||||
BULLSEYE="Follow Bullseye",
|
BULLSEYE="Follow Bullseye",
|
||||||
INITIAL="Initial",
|
INITIAL="Initial",
|
||||||
@ -462,7 +463,7 @@ AIRBOSS.MenuF10={}
|
|||||||
|
|
||||||
--- Airboss class version.
|
--- Airboss class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
AIRBOSS.version="0.3.7"
|
AIRBOSS.version="0.3.9"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- TODO list
|
-- TODO list
|
||||||
@ -477,7 +478,7 @@ AIRBOSS.version="0.3.7"
|
|||||||
-- TODO: Generalize parameters for other aircraft.
|
-- TODO: Generalize parameters for other aircraft.
|
||||||
-- TODO: Foul deck check.
|
-- TODO: Foul deck check.
|
||||||
-- TODO: Persistence of results.
|
-- TODO: Persistence of results.
|
||||||
-- TODO: Strike group with helo bringing cargo etc.
|
-- NOPE: Strike group with helo bringing cargo etc.
|
||||||
-- TODO: Right pattern step after bolter/wo/patternWO?
|
-- TODO: Right pattern step after bolter/wo/patternWO?
|
||||||
-- TODO: CASE II.
|
-- TODO: CASE II.
|
||||||
-- TODO: CASE III.
|
-- TODO: CASE III.
|
||||||
@ -562,7 +563,7 @@ function AIRBOSS:New(carriername, alias)
|
|||||||
self:SetHoldingOffsetAngle(30)
|
self:SetHoldingOffsetAngle(30)
|
||||||
|
|
||||||
-- Default recovery case.
|
-- Default recovery case.
|
||||||
self:SetRecoveryCase(1)
|
self:SetRecoveryCase(3)
|
||||||
|
|
||||||
-- CCA 50 NM radius zone around the carrier.
|
-- CCA 50 NM radius zone around the carrier.
|
||||||
self:SetCarrierControlledArea()
|
self:SetCarrierControlledArea()
|
||||||
@ -570,7 +571,6 @@ function AIRBOSS:New(carriername, alias)
|
|||||||
-- CCZ 5 NM radius zone around the carrier.
|
-- CCZ 5 NM radius zone around the carrier.
|
||||||
self:SetCarrierControlledZone()
|
self:SetCarrierControlledZone()
|
||||||
|
|
||||||
|
|
||||||
-- Init carrier parameters.
|
-- Init carrier parameters.
|
||||||
if self.carriertype==AIRBOSS.CarrierType.STENNIS then
|
if self.carriertype==AIRBOSS.CarrierType.STENNIS then
|
||||||
self:_InitStennis()
|
self:_InitStennis()
|
||||||
@ -593,20 +593,14 @@ function AIRBOSS:New(carriername, alias)
|
|||||||
|
|
||||||
|
|
||||||
-- Smoke zones.
|
-- Smoke zones.
|
||||||
if self.Debug then
|
if self.Debug and false then
|
||||||
--self.zoneInitial:SmokeZone(SMOKECOLOR.White, 90)
|
local case=2
|
||||||
--self.zonePlatform:SmokeZone(SMOKECOLOR.Orange, 90)
|
|
||||||
--self.zoneDirtyup:SmokeZone(SMOKECOLOR.Blue, 90)
|
|
||||||
--self.zoneBullseye:SmokeZone(SMOKECOLOR.Red, 90)
|
|
||||||
--self.zoneInitial:SmokeZone(SMOKECOLOR.White, 90)
|
|
||||||
local case=3
|
|
||||||
self:_GetZoneBullseye(case):SmokeZone(SMOKECOLOR.White, 45)
|
self:_GetZoneBullseye(case):SmokeZone(SMOKECOLOR.White, 45)
|
||||||
self:_GetZoneDirtyUp(case):SmokeZone(SMOKECOLOR.Orange, 45)
|
self:_GetZoneDirtyUp(case):SmokeZone(SMOKECOLOR.Orange, 45)
|
||||||
self:_GetZoneArcIn(case):SmokeZone(SMOKECOLOR.Blue, 45)
|
self:_GetZoneArcIn(case):SmokeZone(SMOKECOLOR.Blue, 45)
|
||||||
self:_GetZoneArcOut(case):SmokeZone(SMOKECOLOR.Blue, 45)
|
self:_GetZoneArcOut(case):SmokeZone(SMOKECOLOR.Blue, 45)
|
||||||
self:_GetZonePlatform(case):SmokeZone(SMOKECOLOR.Red, 45)
|
self:_GetZonePlatform(case):SmokeZone(SMOKECOLOR.Red, 45)
|
||||||
self:_GetZoneCorridor(case):SmokeZone(SMOKECOLOR.Green, 45)
|
self:_GetZoneCorridor(case):SmokeZone(SMOKECOLOR.Green, 45)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Init default sound files.
|
-- Init default sound files.
|
||||||
@ -837,7 +831,6 @@ function AIRBOSS:SetCarrierradio(frequency, modulation)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Set number of aircraft units which can be in the landing pattern before the pattern is full.
|
--- Set number of aircraft units which can be in the landing pattern before the pattern is full.
|
||||||
-- @param #AIRBOSS self
|
-- @param #AIRBOSS self
|
||||||
-- @param #number nmax Max number. Default 4.
|
-- @param #number nmax Max number. Default 4.
|
||||||
@ -856,7 +849,6 @@ function AIRBOSS:SetRecoveryTanker(recoverytanker)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Define warehouse associated with the carrier.
|
--- Define warehouse associated with the carrier.
|
||||||
-- @param #AIRBOSS self
|
-- @param #AIRBOSS self
|
||||||
-- @param Functional.Warehouse#WAREHOUSE warehouse Warehouse object of the carrier.
|
-- @param Functional.Warehouse#WAREHOUSE warehouse Warehouse object of the carrier.
|
||||||
@ -866,7 +858,6 @@ function AIRBOSS:SetWarehouse(warehouse)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Check if carrier is recovering aircraft.
|
--- Check if carrier is recovering aircraft.
|
||||||
-- @param #AIRBOSS self
|
-- @param #AIRBOSS self
|
||||||
-- @return #boolean If true, time slot for recovery is open.
|
-- @return #boolean If true, time slot for recovery is open.
|
||||||
@ -1066,9 +1057,6 @@ end
|
|||||||
function AIRBOSS:onbeforeCase(From, Event, To, OldCase, NewCase)
|
function AIRBOSS:onbeforeCase(From, Event, To, OldCase, NewCase)
|
||||||
|
|
||||||
self.case=NewCase
|
self.case=NewCase
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@ -1121,17 +1109,6 @@ function AIRBOSS:_InitStennis()
|
|||||||
q2:BigSmokeSmall(0.1)--:SmokeBlue()
|
q2:BigSmokeSmall(0.1)--:SmokeBlue()
|
||||||
]]
|
]]
|
||||||
|
|
||||||
-- 4k descent from holding pattern to 5k platform.
|
|
||||||
self.Descent4k.name="Descent 4k"
|
|
||||||
self.Descent4k.Xmin=-UTILS.NMToMeters(50) -- Not more than 50 NM behind the boat.
|
|
||||||
self.Descent4k.Xmax=nil -- -UTILS.NMToMeters(20) -- Not more than 20 NM closer to the boat from behind.
|
|
||||||
self.Descent4k.Zmin=-UTILS.NMToMeters(15) -- Not more than 15 NM port/left of boat.
|
|
||||||
self.Descent4k.Zmax= UTILS.NMToMeters(5) -- Not more than 5 NM starboard/right of boat.
|
|
||||||
self.Descent4k.LimitXmin=nil
|
|
||||||
self.Descent4k.LimitXmax=-UTILS.NMToMeters(21) -- Check and next step when 21 NM behind the boat.
|
|
||||||
self.Descent4k.LimitZmin=nil
|
|
||||||
self.Descent4k.LimitZmax=nil
|
|
||||||
|
|
||||||
-- Platform at 5k. Reduce descent rate to 2000 ft/min to 1200 dirty up level flight.
|
-- Platform at 5k. Reduce descent rate to 2000 ft/min to 1200 dirty up level flight.
|
||||||
self.Platform.name="Platform 5k"
|
self.Platform.name="Platform 5k"
|
||||||
self.Platform.Xmin=-UTILS.NMToMeters(22) -- Not more than 22 NM behind the boat. Last check was at 21 NM.
|
self.Platform.Xmin=-UTILS.NMToMeters(22) -- Not more than 22 NM behind the boat. Last check was at 21 NM.
|
||||||
@ -1281,11 +1258,7 @@ function AIRBOSS:_GetAircraftParameters(playerData, step)
|
|||||||
local dist
|
local dist
|
||||||
local speed
|
local speed
|
||||||
|
|
||||||
if step==AIRBOSS.PatternStep.DESCENT4K then
|
if step==AIRBOSS.PatternStep.PLATFORM then
|
||||||
|
|
||||||
speed=UTILS.KnotsToMps(250)
|
|
||||||
|
|
||||||
elseif step==AIRBOSS.PatternStep.PLATFORM then
|
|
||||||
|
|
||||||
alt=UTILS.FeetToMeters(5000)
|
alt=UTILS.FeetToMeters(5000)
|
||||||
|
|
||||||
@ -1293,7 +1266,15 @@ function AIRBOSS:_GetAircraftParameters(playerData, step)
|
|||||||
|
|
||||||
speed=UTILS.KnotsToMps(250)
|
speed=UTILS.KnotsToMps(250)
|
||||||
|
|
||||||
elseif step==AIRBOSS.PatternStep.DIRTYUP then
|
elseif step==AIRBOSS.PatternStep.ARCIN then
|
||||||
|
|
||||||
|
speed=UTILS.KnotsToMps(250)
|
||||||
|
|
||||||
|
elseif step==AIRBOSS.PatternStep.ARCOUT then
|
||||||
|
|
||||||
|
speed=UTILS.KnotsToMps(250)
|
||||||
|
|
||||||
|
elseif step==AIRBOSS.PatternStep.DIRTYUP then
|
||||||
|
|
||||||
alt=UTILS.FeetToMeters(1200)
|
alt=UTILS.FeetToMeters(1200)
|
||||||
|
|
||||||
@ -2079,6 +2060,11 @@ function AIRBOSS:_InitPlayer(playerData)
|
|||||||
playerData.landed=false
|
playerData.landed=false
|
||||||
playerData.Tlso=timer.getTime()
|
playerData.Tlso=timer.getTime()
|
||||||
|
|
||||||
|
if playerData.group:GetName():match("Groove") then
|
||||||
|
self:MessageToPlayer(playerData, "Group name contains Groove. You are supposed to test the groove.")
|
||||||
|
playerData.step=AIRBOSS.PatternStep.FINAL
|
||||||
|
end
|
||||||
|
|
||||||
return playerData
|
return playerData
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -2276,12 +2262,9 @@ function AIRBOSS:_CheckPlayerStatus()
|
|||||||
local clock=UTILS.SecondsToClock(time)
|
local clock=UTILS.SecondsToClock(time)
|
||||||
self:T3(string.format("Player status undefined. Waiting for next step. Time %s", clock))
|
self:T3(string.format("Player status undefined. Waiting for next step. Time %s", clock))
|
||||||
|
|
||||||
|
elseif playerData.step==AIRBOSS.PatternStep.REFUELING then
|
||||||
|
|
||||||
-- Jump to final/groove for testing.
|
-- Nothing to do here at the moment.
|
||||||
if self.groovedebug then
|
|
||||||
playerData.step=AIRBOSS.PatternStep.FINAL
|
|
||||||
self.groovedebug=false
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif playerData.step==AIRBOSS.PatternStep.HOLDING then
|
elseif playerData.step==AIRBOSS.PatternStep.HOLDING then
|
||||||
|
|
||||||
@ -2293,19 +2276,24 @@ function AIRBOSS:_CheckPlayerStatus()
|
|||||||
-- CASE I/II/III: New approach.
|
-- CASE I/II/III: New approach.
|
||||||
self:_Commencing(playerData)
|
self:_Commencing(playerData)
|
||||||
|
|
||||||
elseif playerData.step==AIRBOSS.PatternStep.DESCENT4K then
|
|
||||||
|
|
||||||
-- CASE II/III: Initial descent with 4000 ft/min.
|
|
||||||
self:_Descent4k(playerData)
|
|
||||||
|
|
||||||
elseif playerData.step==AIRBOSS.PatternStep.PLATFORM then
|
elseif playerData.step==AIRBOSS.PatternStep.PLATFORM then
|
||||||
|
|
||||||
-- CASE II/III: Player has reached 5k "Platform".
|
-- CASE II/III: Player has reached 5k "Platform".
|
||||||
self:_Platform(playerData)
|
self:_Platform(playerData)
|
||||||
|
|
||||||
|
elseif playerData.step==AIRBOSS.PatternStep.ARCIN then
|
||||||
|
|
||||||
|
-- Case II/III if offset.
|
||||||
|
self:_ArcInTurn(playerData)
|
||||||
|
|
||||||
|
elseif playerData.step==AIRBOSS.PatternStep.ARCOUT then
|
||||||
|
|
||||||
|
-- Case II/III if offset.
|
||||||
|
self:_ArcOutTurn(playerData)
|
||||||
|
|
||||||
elseif playerData.step==AIRBOSS.PatternStep.DIRTYUP then
|
elseif playerData.step==AIRBOSS.PatternStep.DIRTYUP then
|
||||||
|
|
||||||
-- CASE II/III: Player has descended to 1200 ft and is going level from now on.
|
-- CASE III: Player has descended to 1200 ft and is going level from now on.
|
||||||
self:_DirtyUp(playerData)
|
self:_DirtyUp(playerData)
|
||||||
|
|
||||||
elseif playerData.step==AIRBOSS.PatternStep.BULLSEYE then
|
elseif playerData.step==AIRBOSS.PatternStep.BULLSEYE then
|
||||||
@ -2374,6 +2362,10 @@ function AIRBOSS:_CheckPlayerStatus()
|
|||||||
-- Undefined status.
|
-- Undefined status.
|
||||||
playerData.step=AIRBOSS.PatternStep.UNDEFINED
|
playerData.step=AIRBOSS.PatternStep.UNDEFINED
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
self:E(self.lid..string.format("ERROR: unknown player step %s", tostring(playerData.step)))
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
@ -2438,12 +2430,9 @@ function AIRBOSS:OnEventBirth(EventData)
|
|||||||
--self:RadioTransmission(self.LSOradio, self.radiocall.LONGINGROOVE, false, 20)
|
--self:RadioTransmission(self.LSOradio, self.radiocall.LONGINGROOVE, false, 20)
|
||||||
|
|
||||||
if self.Debug then
|
if self.Debug then
|
||||||
self:_MarkCase23Zones(_unit:GetName())
|
--self:_MarkCase23Zones(_unit:GetName())
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Start in the groove for debugging.
|
|
||||||
self.groovedebug=false
|
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -2500,6 +2489,10 @@ function AIRBOSS:OnEventLand(EventData)
|
|||||||
-- Landing distance to carrier position.
|
-- Landing distance to carrier position.
|
||||||
local dist=coord:Get2DDistance(self:GetCoordinate())
|
local dist=coord:Get2DDistance(self:GetCoordinate())
|
||||||
|
|
||||||
|
if X<0 then
|
||||||
|
dist=-dist
|
||||||
|
end
|
||||||
|
|
||||||
-- TODO: check if 360 degrees correctino is necessary!
|
-- TODO: check if 360 degrees correctino is necessary!
|
||||||
local hdg=self.carrier:GetHeading()+self.carrierparam.rwyangle
|
local hdg=self.carrier:GetHeading()+self.carrierparam.rwyangle
|
||||||
|
|
||||||
@ -2527,7 +2520,7 @@ function AIRBOSS:OnEventLand(EventData)
|
|||||||
playerData.step=AIRBOSS.PatternStep.UNDEFINED
|
playerData.step=AIRBOSS.PatternStep.UNDEFINED
|
||||||
|
|
||||||
-- Call trapped function in 3 seconds to make sure we did not bolter.
|
-- Call trapped function in 3 seconds to make sure we did not bolter.
|
||||||
SCHEDULER:New(nil, self._Trapped,{self, playerData, dist}, 3)
|
SCHEDULER:New(nil, self._Trapped,{self, playerData, wire}, 3)
|
||||||
end
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
@ -2925,10 +2918,10 @@ function AIRBOSS:_GetZoneCorridor(case)
|
|||||||
local alpha=math.rad(self.holdingoffset)
|
local alpha=math.rad(self.holdingoffset)
|
||||||
|
|
||||||
-- Distance from ArcIn to ArcOut zone
|
-- Distance from ArcIn to ArcOut zone
|
||||||
local d=UTILS.NMToMeters(12)
|
local d=12
|
||||||
local y=d*math.tan(alpha)
|
local y=d*math.tan(alpha)
|
||||||
|
|
||||||
local d2=math.cos(alpha)/UTILS.NMToMeters(2)
|
local d2=math.cos(alpha)/2
|
||||||
|
|
||||||
local c={}
|
local c={}
|
||||||
c[1]=self:GetCoordinate() -- Carrier coordinate
|
c[1]=self:GetCoordinate() -- Carrier coordinate
|
||||||
@ -2939,7 +2932,7 @@ function AIRBOSS:_GetZoneCorridor(case)
|
|||||||
c[6]=c[5]:Translate( UTILS.NMToMeters( 2), offset+90) -- Back wall (angled)
|
c[6]=c[5]:Translate( UTILS.NMToMeters( 2), offset+90) -- Back wall (angled)
|
||||||
c[7]=c[6]:Translate(-UTILS.NMToMeters(10+d2), offset) -- back along X & Z
|
c[7]=c[6]:Translate(-UTILS.NMToMeters(10+d2), offset) -- back along X & Z
|
||||||
c[8]=c[7]:Translate( UTILS.NMToMeters( y), radial-90) -- back along X
|
c[8]=c[7]:Translate( UTILS.NMToMeters( y), radial-90) -- back along X
|
||||||
c[9]=c[1]:Translate(-UTILS.NMToMeters( 1), radial+90) -- 1 left of carrier
|
c[9]=c[1]:Translate( UTILS.NMToMeters( 1), radial+90) -- 1 left of carrier
|
||||||
|
|
||||||
|
|
||||||
-- Create an array of a square!
|
-- Create an array of a square!
|
||||||
@ -2992,12 +2985,15 @@ function AIRBOSS:_GetHoldingZone(playerData)
|
|||||||
else
|
else
|
||||||
-- CASE II/II
|
-- CASE II/II
|
||||||
|
|
||||||
-- TODO: Include 15 or 30 degrees offset.
|
-- Get radial.
|
||||||
local hdg=self.carrier:GetHeading()-self.holdingoffset
|
local hdg
|
||||||
|
if playerData.case==2 then
|
||||||
--TODO: case dependend radial!
|
hdg=self:GetRadialCase2(false, true)
|
||||||
local hdg=self:GetRadialCase3(false)
|
else
|
||||||
|
hdg=self:GetRadialCase3(false, true)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- TODO: This is WRONG!
|
||||||
-- Create an array of a square!
|
-- Create an array of a square!
|
||||||
local p={}
|
local p={}
|
||||||
p[1]=c1:Translate(UTILS.NMToMeters(1), hdg+90):GetVec2() --c1 is at (angels+15) NM directly behind the carrier. We translate it 1 NM starboard.
|
p[1]=c1:Translate(UTILS.NMToMeters(1), hdg+90):GetVec2() --c1 is at (angels+15) NM directly behind the carrier. We translate it 1 NM starboard.
|
||||||
@ -3033,12 +3029,12 @@ function AIRBOSS:_Commencing(playerData)
|
|||||||
-- CASE I: Player has to fly to the initial which is 3 NM DME astern of the boat.
|
-- CASE I: Player has to fly to the initial which is 3 NM DME astern of the boat.
|
||||||
playerData.step=AIRBOSS.PatternStep.INITIAL
|
playerData.step=AIRBOSS.PatternStep.INITIAL
|
||||||
else
|
else
|
||||||
-- CASE III: Player has to start the descent at 4000 ft/min.
|
-- CASE II/III: Player has to start the descent at 4000 ft/min.
|
||||||
playerData.step=AIRBOSS.PatternStep.PLATFORM
|
playerData.step=AIRBOSS.PatternStep.PLATFORM
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Start pattern when player enters the initial zone.
|
--- Start pattern when player enters the initial zone in case I/II recoveries.
|
||||||
-- @param #AIRBOSS self
|
-- @param #AIRBOSS self
|
||||||
-- @param #AIRBOSS.PlayerData playerData Player data table.
|
-- @param #AIRBOSS.PlayerData playerData Player data table.
|
||||||
function AIRBOSS:_Initial(playerData)
|
function AIRBOSS:_Initial(playerData)
|
||||||
@ -3061,28 +3057,7 @@ function AIRBOSS:_Initial(playerData)
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Descent at 4k.
|
--- Platform at 5k ft for case II/III recoveries. Descent at 2000 ft/min.
|
||||||
-- @param #AIRBOSS self
|
|
||||||
-- @param #AIRBOSS.PlayerData playerData Player data table.
|
|
||||||
function AIRBOSS:_Descent4k(playerData)
|
|
||||||
|
|
||||||
-- Get distances between carrier and player unit (parallel and perpendicular to direction of movement of carrier)
|
|
||||||
local X, Z, rho, phi=self:_GetDistances(playerData.unit)
|
|
||||||
|
|
||||||
-- Abort condition check.
|
|
||||||
if self:_CheckAbort(X, Z, self.Descent4k) then
|
|
||||||
self:_AbortPattern(playerData, X, Z, self.Descent4k)
|
|
||||||
--return
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Check if we are in front of the boat (diffX > 0).
|
|
||||||
if self:_CheckLimits(X, Z, self.Descent4k) then
|
|
||||||
-- Next step: Platform at 5k
|
|
||||||
playerData.step=AIRBOSS.PatternStep.PLATFORM
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Platform at 5k ft. Descent at 2000 ft/min.
|
|
||||||
-- @param #AIRBOSS self
|
-- @param #AIRBOSS self
|
||||||
-- @param #AIRBOSS.PlayerData playerData Player data table.
|
-- @param #AIRBOSS.PlayerData playerData Player data table.
|
||||||
function AIRBOSS:_Platform(playerData)
|
function AIRBOSS:_Platform(playerData)
|
||||||
@ -3095,7 +3070,7 @@ function AIRBOSS:_Platform(playerData)
|
|||||||
|
|
||||||
-- Issue warning.
|
-- Issue warning.
|
||||||
if invalid and not playerData.warning then
|
if invalid and not playerData.warning then
|
||||||
self:MessageToPlayer(playerData, "You left the valid pattern zone!", "AIRBOSS")
|
self:MessageToPlayer(playerData, "You left the valid approach corridor!", "AIRBOSS")
|
||||||
playerData.warning=true
|
playerData.warning=true
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -3123,17 +3098,123 @@ function AIRBOSS:_Platform(playerData)
|
|||||||
self:MessageToPlayer(playerData, hint, "MARSHAL", "")
|
self:MessageToPlayer(playerData, hint, "MARSHAL", "")
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Next step: Dirty up and level out at 1200 ft.
|
-- Next step: depends.
|
||||||
if math.abs(self.holdingoffset)>0 then
|
if math.abs(self.holdingoffset)>0 then
|
||||||
|
-- Turn to BRC (case I) or FB (case III).
|
||||||
playerData.step=AIRBOSS.PatternStep.ARCIN
|
playerData.step=AIRBOSS.PatternStep.ARCIN
|
||||||
else
|
else
|
||||||
playerData.step=AIRBOSS.PatternStep.DIRTYUP
|
if playerData.case==2 then
|
||||||
|
-- Case II: Initial zone then Case I recovery.
|
||||||
|
playerData.step=AIRBOSS.PatternStep.INITIAL
|
||||||
|
elseif playerData.case==3 then
|
||||||
|
-- CASE III: Dirty up.
|
||||||
|
playerData.step=AIRBOSS.PatternStep.DIRTYUP
|
||||||
|
end
|
||||||
end
|
end
|
||||||
playerData.warning=nil
|
playerData.warning=nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Dirty up and level out at 1200 ft.
|
|
||||||
|
--- Arc in turn for case II/III recoveries.
|
||||||
|
-- @param #AIRBOSS self
|
||||||
|
-- @param #AIRBOSS.PlayerData playerData Player data table.
|
||||||
|
function AIRBOSS:_ArcInTurn(playerData)
|
||||||
|
|
||||||
|
-- Check if player is in valid zone
|
||||||
|
local validzone=self:_GetZoneCorridor(playerData.case)
|
||||||
|
|
||||||
|
-- Check if we are inside the moving zone.
|
||||||
|
local invalid=playerData.unit:IsNotInZone(validzone)
|
||||||
|
|
||||||
|
-- Issue warning.
|
||||||
|
if invalid and not playerData.warning then
|
||||||
|
self:MessageToPlayer(playerData, "You left the valid approach corridor!", "AIRBOSS")
|
||||||
|
playerData.warning=true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check if we are inside the moving zone.
|
||||||
|
local inzone=playerData.unit:IsInZone(self:_GetZoneArcIn(playerData.case))
|
||||||
|
|
||||||
|
--if self:_CheckLimits(X, Z, self.DirtyUp) then
|
||||||
|
if inzone then
|
||||||
|
|
||||||
|
-- Debug message.
|
||||||
|
MESSAGE:New("Arc Turn In step reached", 5):ToAllIf(self.Debug)
|
||||||
|
|
||||||
|
-- Get optimal altitiude.
|
||||||
|
local altitude, aoa, distance, speed=self:_GetAircraftParameters(playerData)
|
||||||
|
|
||||||
|
-- Get speed hint.
|
||||||
|
local hintSpeed=self:_SpeedCheck(playerData, speed)
|
||||||
|
|
||||||
|
-- Message to player.
|
||||||
|
if playerData.difficulty~=AIRBOSS.Difficulty.HARD then
|
||||||
|
local hint=string.format("%s\n%s", playerData.step, hintSpeed)
|
||||||
|
self:MessageToPlayer(playerData, hint, "MARSHAL", "")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Next step: Arc Out Turn.
|
||||||
|
playerData.step=AIRBOSS.PatternStep.ARCOUT
|
||||||
|
|
||||||
|
playerData.warning=nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Arc out turn for case II/III recoveries.
|
||||||
|
-- @param #AIRBOSS self
|
||||||
|
-- @param #AIRBOSS.PlayerData playerData Player data table.
|
||||||
|
function AIRBOSS:_ArcOutTurn(playerData)
|
||||||
|
|
||||||
|
-- Check if player is in valid zone
|
||||||
|
local validzone=self:_GetZoneCorridor(playerData.case)
|
||||||
|
|
||||||
|
-- Check if we are inside the moving zone.
|
||||||
|
local invalid=playerData.unit:IsNotInZone(validzone)
|
||||||
|
|
||||||
|
-- Issue warning.
|
||||||
|
if invalid and not playerData.warning then
|
||||||
|
self:MessageToPlayer(playerData, "You left the valid approach corridor!", "AIRBOSS")
|
||||||
|
playerData.warning=true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check if we are inside the moving zone.
|
||||||
|
local inzone=playerData.unit:IsInZone(self:_GetZoneArcOut(playerData.case))
|
||||||
|
|
||||||
|
--if self:_CheckLimits(X, Z, self.DirtyUp) then
|
||||||
|
if inzone then
|
||||||
|
|
||||||
|
-- Debug message.
|
||||||
|
MESSAGE:New("Arc Turn Out step reached", 5):ToAllIf(self.Debug)
|
||||||
|
|
||||||
|
-- Get optimal altitiude.
|
||||||
|
local altitude, aoa, distance, speed=self:_GetAircraftParameters(playerData)
|
||||||
|
|
||||||
|
-- Get speed hint.
|
||||||
|
local hintSpeed=self:_SpeedCheck(playerData, speed)
|
||||||
|
|
||||||
|
-- Message to player.
|
||||||
|
if playerData.difficulty~=AIRBOSS.Difficulty.HARD then
|
||||||
|
local hint=string.format("%s\n%s", playerData.step, hintSpeed)
|
||||||
|
self:MessageToPlayer(playerData, hint, "MARSHAL", "")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Next step:
|
||||||
|
if playerData.case==2 then
|
||||||
|
-- Case II: Initial.
|
||||||
|
playerData.step=AIRBOSS.PatternStep.INITIAL
|
||||||
|
elseif playerdata.case==3 then
|
||||||
|
-- Case III: Dirty up.
|
||||||
|
playerData.step=AIRBOSS.PatternStep.DIRTYUP
|
||||||
|
else
|
||||||
|
-- ERROR!
|
||||||
|
end
|
||||||
|
|
||||||
|
playerData.warning=nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Dirty up and level out at 1200 ft for case III recovery.
|
||||||
-- @param #AIRBOSS self
|
-- @param #AIRBOSS self
|
||||||
-- @param #AIRBOSS.PlayerData playerData Player data table.
|
-- @param #AIRBOSS.PlayerData playerData Player data table.
|
||||||
function AIRBOSS:_DirtyUp(playerData)
|
function AIRBOSS:_DirtyUp(playerData)
|
||||||
@ -3146,7 +3227,7 @@ function AIRBOSS:_DirtyUp(playerData)
|
|||||||
|
|
||||||
-- Issue warning.
|
-- Issue warning.
|
||||||
if invalid and not playerData.warning then
|
if invalid and not playerData.warning then
|
||||||
self:MessageToPlayer(playerData, "You left the valid pattern zone!", "AIRBOSS")
|
self:MessageToPlayer(playerData, "You left the valid approach corridor!", "AIRBOSS")
|
||||||
playerData.warning=true
|
playerData.warning=true
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -3175,19 +3256,14 @@ function AIRBOSS:_DirtyUp(playerData)
|
|||||||
self:MessageToPlayer(playerData, hint, "MARSHAL", "")
|
self:MessageToPlayer(playerData, hint, "MARSHAL", "")
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Next step:
|
-- Next step: CASE III: Intercept glide slope and follow bullseye (ICLS).
|
||||||
if self.case==2 then
|
playerData.step=AIRBOSS.PatternStep.BULLSEYE
|
||||||
-- CASE II: Fly to the initial and perform CASE I pattern.
|
|
||||||
playerData.step=AIRBOSS.PatternStep.INITIAL
|
|
||||||
elseif self.case==3 then
|
|
||||||
-- CASE III: Intercept glide slope and follow bullseye (ICLS).
|
|
||||||
playerData.step=AIRBOSS.PatternStep.BULLSEYE
|
|
||||||
end
|
|
||||||
playerData.warning=nil
|
playerData.warning=nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Intercept glide slop and follow ICLS, aka Bullseye.
|
--- Intercept glide slop and follow ICLS, aka Bullseye for case III recovery.
|
||||||
-- @param #AIRBOSS self
|
-- @param #AIRBOSS self
|
||||||
-- @param #AIRBOSS.PlayerData playerData Player data table.
|
-- @param #AIRBOSS.PlayerData playerData Player data table.
|
||||||
function AIRBOSS:_Bullseye(playerData)
|
function AIRBOSS:_Bullseye(playerData)
|
||||||
@ -3200,7 +3276,7 @@ function AIRBOSS:_Bullseye(playerData)
|
|||||||
|
|
||||||
-- Issue warning.
|
-- Issue warning.
|
||||||
if invalid and not playerData.warning then
|
if invalid and not playerData.warning then
|
||||||
self:MessageToPlayer(playerData, "You left the valid pattern zone!", "AIRBOSS")
|
self:MessageToPlayer(playerData, "You left the valid approach corridor!", "AIRBOSS")
|
||||||
playerData.warning=true
|
playerData.warning=true
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -3231,12 +3307,13 @@ function AIRBOSS:_Bullseye(playerData)
|
|||||||
|
|
||||||
-- Next step: Groove Call the ball.
|
-- Next step: Groove Call the ball.
|
||||||
playerData.step=AIRBOSS.PatternStep.GROOVE_XX
|
playerData.step=AIRBOSS.PatternStep.GROOVE_XX
|
||||||
|
|
||||||
playerData.warning=nil
|
playerData.warning=nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Upwind leg or break entry.
|
--- Upwind leg or break entry for case I/II recoveries.
|
||||||
-- @param #AIRBOSS self
|
-- @param #AIRBOSS self
|
||||||
-- @param #AIRBOSS.PlayerData playerData Player data table.
|
-- @param #AIRBOSS.PlayerData playerData Player data table.
|
||||||
function AIRBOSS:_Upwind(playerData)
|
function AIRBOSS:_Upwind(playerData)
|
||||||
@ -3781,13 +3858,13 @@ function AIRBOSS:_GetWire(d)
|
|||||||
|
|
||||||
-- Which wire was caught? X>0 since calculated as distance!
|
-- Which wire was caught? X>0 since calculated as distance!
|
||||||
local wire
|
local wire
|
||||||
if d>math.abs(self.carrierparam.wire1+wdx) then
|
if d<self.carrierparam.wire1+wdx then
|
||||||
wire=1
|
wire=1
|
||||||
elseif d>math.abs(self.carrierparam.wire2+wdx) then
|
elseif d<self.carrierparam.wire2+wdx then
|
||||||
wire=2
|
wire=2
|
||||||
elseif d>math.abs(self.carrierparam.wire3+wdx) then
|
elseif d<self.carrierparam.wire3+wdx then
|
||||||
wire=3
|
wire=3
|
||||||
elseif d>math.abs(self.carrierparam.wire4+wdx) then
|
elseif d<self.carrierparam.wire4+wdx then
|
||||||
wire=4
|
wire=4
|
||||||
else
|
else
|
||||||
wire=99
|
wire=99
|
||||||
@ -3799,35 +3876,22 @@ end
|
|||||||
--- Trapped?
|
--- Trapped?
|
||||||
-- @param #AIRBOSS self
|
-- @param #AIRBOSS self
|
||||||
-- @param #AIRBOSS.PlayerData playerData Player data table.
|
-- @param #AIRBOSS.PlayerData playerData Player data table.
|
||||||
-- @param #number X Distance in meters wrt carrier position where player landed.
|
-- @param #number wire The wire caught.
|
||||||
function AIRBOSS:_Trapped(playerData, X)
|
function AIRBOSS:_Trapped(playerData, wire)
|
||||||
|
|
||||||
self:I(self.lid.."FF TRAPPED")
|
|
||||||
|
|
||||||
-- Get distances between carrier and player unit (parallel and perpendicular to direction of movement of carrier)
|
|
||||||
--local X, Z, rho, phi = self:_GetDistances(pos)
|
|
||||||
|
|
||||||
if playerData.unit:InAir()==false then
|
if playerData.unit:InAir()==false then
|
||||||
-- Seems we have successfully landed.
|
-- Seems we have successfully landed.
|
||||||
|
|
||||||
-- Get wire.
|
-- Message to player.
|
||||||
local wire=self:_GetWire(X)
|
|
||||||
|
|
||||||
-- Info to player.
|
|
||||||
local text=string.format("Trapped! %d-wire.", wire)
|
local text=string.format("Trapped! %d-wire.", wire)
|
||||||
self:MessageToPlayer(playerData, text, "LSO", "")
|
self:MessageToPlayer(playerData, text, "LSO", "")
|
||||||
|
|
||||||
-- Debug message.
|
|
||||||
local text=string.format("Distance X=%.1f meters resulted in a %d-wire estimate.", X, wire)
|
|
||||||
MESSAGE:New(text, 30):ToAllIf(self.Debug)
|
|
||||||
self:I(self.lid..text)
|
|
||||||
|
|
||||||
-- Debrief.
|
-- Debrief.
|
||||||
local hint = string.format("Trapped catching the %d-wire.", wire)
|
local hint = string.format("Trapped catching the %d-wire.", wire)
|
||||||
self:_AddToSummary(playerData, "Goove: IW", hint)
|
self:_AddToSummary(playerData, "Goove: IW", hint)
|
||||||
|
|
||||||
else
|
else
|
||||||
--Boltered!
|
--Still in air ==> Boltered!
|
||||||
playerData.boltered=true
|
playerData.boltered=true
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -4012,7 +4076,7 @@ function AIRBOSS:GetRadialCase2(magnetic, offset)
|
|||||||
|
|
||||||
-- Holding offset angle (+-15 or 30 degrees usually)
|
-- Holding offset angle (+-15 or 30 degrees usually)
|
||||||
if offset then
|
if offset then
|
||||||
radial=radial-self.holdingoffset
|
radial=radial+self.holdingoffset
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Adjust for negative values.
|
-- Adjust for negative values.
|
||||||
@ -4035,7 +4099,7 @@ function AIRBOSS:GetRadialCase3(magnetic, offset)
|
|||||||
|
|
||||||
-- Holding offset angle (+-15 or 30 degrees usually)
|
-- Holding offset angle (+-15 or 30 degrees usually)
|
||||||
if offset then
|
if offset then
|
||||||
radial=radial-self.holdingoffset
|
radial=radial+self.holdingoffset
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Adjust for negative values.
|
-- Adjust for negative values.
|
||||||
@ -5285,8 +5349,11 @@ function AIRBOSS:_ResetPlayerStatus(_unitName)
|
|||||||
|
|
||||||
if playerData then
|
if playerData then
|
||||||
|
|
||||||
|
-- Inform player.
|
||||||
local text="Status reset executed! You have been removed from all queues."
|
local text="Status reset executed! You have been removed from all queues."
|
||||||
|
self:MessageToPlayer(playerData, text, nil, "")
|
||||||
|
|
||||||
|
-- Remove from marhal stack can collapse stack if necessary.
|
||||||
if self:_InQueue(self.Qmarshal, playerData.group) then
|
if self:_InQueue(self.Qmarshal, playerData.group) then
|
||||||
self:_CollapseMarshalStack(playerData, true)
|
self:_CollapseMarshalStack(playerData, true)
|
||||||
end
|
end
|
||||||
@ -5294,6 +5361,9 @@ function AIRBOSS:_ResetPlayerStatus(_unitName)
|
|||||||
-- Remove flight from queues.
|
-- Remove flight from queues.
|
||||||
self:_RemoveFlight(playerData)
|
self:_RemoveFlight(playerData)
|
||||||
|
|
||||||
|
-- Initialize player data.
|
||||||
|
self:_InitPlayer(playerData)
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -5770,6 +5840,21 @@ function AIRBOSS:_DisplayCarrierInfo(_unitname)
|
|||||||
icls=string.format("%d", self.ICLSchannel)
|
icls=string.format("%d", self.ICLSchannel)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Get groups, units in queues.
|
||||||
|
local Nmarshal,nmarshal=self:_GetQueueInfo(self.Qmarshal, playerData.case)
|
||||||
|
local Npattern,npattern=self:_GetQueueInfo(self.Qpattern)
|
||||||
|
|
||||||
|
-- Get recovery times of carrier.
|
||||||
|
local recoverytimes="Recovery time slots:"
|
||||||
|
if #self.recoverytime==0 then
|
||||||
|
recoverytimes=recoverytimes.." empty"
|
||||||
|
else
|
||||||
|
for _,_rtime in pairs(self.recoverytime) do
|
||||||
|
local rtime=_rtime --#AIRBOSS.Recovery
|
||||||
|
recoverytimes=recoverytimes..string.format("\nSlot %s - %s", UTILS.SecondsToClock(rtime.START), UTILS.SecondsToClock(rtime.STOP))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- Message text.
|
-- Message text.
|
||||||
local text=string.format("%s info:\n", self.alias)
|
local text=string.format("%s info:\n", self.alias)
|
||||||
text=text..string.format("=============================================\n")
|
text=text..string.format("=============================================\n")
|
||||||
@ -5783,8 +5868,9 @@ function AIRBOSS:_DisplayCarrierInfo(_unitname)
|
|||||||
text=text..string.format("TACAN Channel %s\n", tacan)
|
text=text..string.format("TACAN Channel %s\n", tacan)
|
||||||
text=text..string.format("ICLS Channel %s\n", icls)
|
text=text..string.format("ICLS Channel %s\n", icls)
|
||||||
text=text..string.format("# A/C total %d\n", #self.flights)
|
text=text..string.format("# A/C total %d\n", #self.flights)
|
||||||
text=text..string.format("# A/C holding %d\n", #self.Qmarshal)
|
text=text..string.format("# A/C marshal %d (%d)\n", Nmarshal, nmarshal)
|
||||||
text=text..string.format("# A/C pattern %d", #self.Qpattern)
|
text=text..string.format("# A/C pattern %d (%d)\n", Npattern, npattern)
|
||||||
|
text=text..string.format(recoverytimes)
|
||||||
self:T2(self.lid..text)
|
self:T2(self.lid..text)
|
||||||
|
|
||||||
-- Send message.
|
-- Send message.
|
||||||
@ -5990,7 +6076,6 @@ function AIRBOSS:_MarkCase23Zones(_unitName, flare)
|
|||||||
case=3
|
case=3
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Initial
|
-- Initial
|
||||||
local text=string.format("Marking CASE %d zone:\n", case)
|
local text=string.format("Marking CASE %d zone:\n", case)
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user