mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-08-15 10:47:21 +00:00
AIRBOSS v0.3.1w
This commit is contained in:
parent
ba1cb61f4d
commit
e23488a723
@ -58,11 +58,11 @@
|
||||
-- @field #AIRBOSS.Checkpoint Wake Right behind the carrier.
|
||||
-- @field #AIRBOSS.Checkpoint Groove In the groove checkpoint.
|
||||
-- @field #AIRBOSS.Checkpoint Trap Landing checkpoint.
|
||||
-- @field #AIRBOSS.Checkpoint C3Descent4k Case III descent at 4000 ft/min right after leaving holding pattern.
|
||||
-- @field #AIRBOSS.Checkpoint C3Descent2k Case III descent at 2000 ft/min at 5000 ft plattform.
|
||||
-- @field #AIRBOSS.Checkpoint C3DirtyUp Case III dirty up and on speed position at 1200 ft and 10-12 NM from the carrier.
|
||||
-- @field #AIRBOSS.Checkpoint C3Descent4k Case II/III descent at 4000 ft/min right after leaving holding pattern.
|
||||
-- @field #AIRBOSS.Checkpoint C3Descent2k Case II/III descent at 2000 ft/min at 5000 ft plattform.
|
||||
-- @field #AIRBOSS.Checkpoint C3DirtyUp Case II/III dirty up and on speed position at 1200 ft and 10-12 NM from the carrier.
|
||||
-- @field #AIRBOSS.Checkpoint C3BullsEye Case III intercept glideslope and follow ICLS "bullseye".
|
||||
-- @field #number case Recovery case I or III in progress.
|
||||
-- @field #number case Recovery case I, II or III in progress.
|
||||
-- @field #table flights List of all flights in the CCA.
|
||||
-- @field #table Qmarshal Queue of marshalling aircraft groups.
|
||||
-- @field #table Qpattern Queue of aircraft groups in the landing pattern.
|
||||
@ -122,6 +122,7 @@ AIRBOSS = {
|
||||
flights = {},
|
||||
Qpattern = {},
|
||||
Qmarshal = {},
|
||||
Nmaxpattern = nil,
|
||||
rescuehelo = nil,
|
||||
tanker = nil,
|
||||
warehouse = nil,
|
||||
@ -132,15 +133,18 @@ AIRBOSS = {
|
||||
-- @type AIRBOSS.AircraftPlayer
|
||||
-- @field #string AV8B AV-8B Night Harrier.
|
||||
-- @field #string HORNET F/A-18C Lot 20 Hornet.
|
||||
-- @field #string A4EC Community A-4E-C mod.
|
||||
AIRBOSS.AircraftPlayer={
|
||||
AV8B="AV8BNA",
|
||||
HORNET="FA-18C_hornet",
|
||||
A4EC="A-4E-C", --TODO: Correct string?
|
||||
}
|
||||
|
||||
--- Aircraft types capable of landing on carrier (human+AI).
|
||||
-- @type AIRBOSS.AircraftCarrier
|
||||
-- @field #string AV8B AV-8B Night Harrier.
|
||||
-- @field #string HORNET F/A-18C Lot 20 Hornet.
|
||||
-- @field #string A4EC Community A-4E-C mod.
|
||||
-- @field #string S3B Lockheed S-3B Viking.
|
||||
-- @field #string S3BTANKER Lockheed S-3B Viking tanker.
|
||||
-- @field #string E2D Grumman E-2D Hawkeye AWACS.
|
||||
@ -149,15 +153,14 @@ AIRBOSS.AircraftPlayer={
|
||||
AIRBOSS.AircraftCarrier={
|
||||
AV8B="AV8BNA",
|
||||
HORNET="FA-18C_hornet",
|
||||
A4EC="A-4E-C", --TODO: Correct string?
|
||||
S3B="S-3B",
|
||||
S3BTANKER="S-3B Tanker",
|
||||
E2D="E-2C",
|
||||
FA18C="F/A-18C",
|
||||
F14A="F-14A",
|
||||
--TODO: Add A4-E-C
|
||||
}
|
||||
|
||||
|
||||
--- Carrier types.
|
||||
-- @type AIRBOSS.CarrierType
|
||||
-- @field #string STENNIS USS John C. Stennis (CVN-74)
|
||||
@ -181,6 +184,13 @@ AIRBOSS.CarrierType={
|
||||
-- @field #number wire3 Distance in meters from carrier position to third wire.
|
||||
-- @field #number wire4 Distance in meters from carrier position to fourth wire.
|
||||
|
||||
--- Aircraft Parameters.
|
||||
-- @type AIRBOSS.AircraftParameters
|
||||
-- @field #number AoA Onspeed Angle of Attack.
|
||||
-- @field #number Dboat Ideal distance to the carrier.
|
||||
-- @field #number
|
||||
|
||||
|
||||
--- Pattern steps.
|
||||
-- @type AIRBOSS.PatternStep
|
||||
AIRBOSS.PatternStep={
|
||||
@ -188,8 +198,8 @@ AIRBOSS.PatternStep={
|
||||
COMMENCING="Commencing",
|
||||
HOLDING="Holding",
|
||||
DESCENT4K="Descent 4000 ft/min",
|
||||
DESCENT2K="Descent 2000 ft/min",
|
||||
DIRTYUP="Leven and Dirty Up",
|
||||
DESCENT2K="Platform",
|
||||
DIRTYUP="Level out and Dirty Up",
|
||||
BULLSEYE="Follow Bullseye",
|
||||
INITIAL="Initial",
|
||||
UPWIND="Upwind",
|
||||
@ -416,6 +426,7 @@ AIRBOSS.GroovePos={
|
||||
-- @field #AIRBOSS.PlayerData player Player data for human pilots.
|
||||
-- @field #string actype Aircraft type name.
|
||||
-- @field #table onboardnumbers Onboard numbers of aircraft in the group.
|
||||
-- @field #number case Recovery case of flight.
|
||||
-- @field #table section Other human flight groups belonging to this flight. This flight is the lead.
|
||||
|
||||
--- Main radio menu.
|
||||
@ -435,12 +446,12 @@ AIRBOSS.version="0.3.1"
|
||||
-- TODO: Add radio transmission queue for LSO and airboss.
|
||||
-- TODO: Get correct wire when trapped.
|
||||
-- TODO: Add radio check (LSO, AIRBOSS) to F10 radio menu.
|
||||
-- TODO: Monitor holding of players/AI in zoneHolding.
|
||||
-- DONE: Monitor holding of players/AI in zoneHolding.
|
||||
-- TODO: Right pattern step after bolter/wo/patternWO?
|
||||
-- TODO: Handle crash event. Delete A/C from queue, send rescue helo, stop carrier?
|
||||
-- TODO: Add aircraft numbers in queue to carrier info F10 radio output.
|
||||
-- TODO: Transmission via radio.
|
||||
-- TODO: Get board numbers.
|
||||
-- DONE: Transmission via radio.
|
||||
-- DONE: Get board numbers.
|
||||
-- TODO: Get fuel state in pounds.
|
||||
-- TODO: Add user functions.
|
||||
-- TODO: Generalize parameters for other carriers.
|
||||
@ -609,7 +620,7 @@ function AIRBOSS:New(carriername, alias)
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- User functions
|
||||
-- USER API Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Set carrier controlled area (CCA).
|
||||
@ -846,7 +857,7 @@ function AIRBOSS:onafterStatus(From, Event, To)
|
||||
if time-self.Tqueue>30 then
|
||||
|
||||
local text=string.format("Status %s.", self:GetState())
|
||||
self:I(self.lid..text)
|
||||
self:I(self.lid..text)
|
||||
|
||||
-- Scan carrier zone for new aircraft.
|
||||
self:_ScanCarrierZone()
|
||||
@ -994,10 +1005,6 @@ function AIRBOSS:_InitStennis()
|
||||
self.C3Descent4k.LimitXmax=-UTILS.NMToMeters(20) --TODO: better rho dist. decrease descent 20 2000 ft/min at 5000 ft alt and user rad alt.
|
||||
self.C3Descent4k.LimitZmin=nil
|
||||
self.C3Descent4k.LimitZmax=nil
|
||||
-- TODO: alt, AoA are more aircraft functions rather than carrier
|
||||
self.C3Descent4k.Altitude=nil --UTILS.FeetToMeters(5000)
|
||||
self.C3Descent4k.AoA=nil
|
||||
self.C3Descent4k.Distance=nil
|
||||
|
||||
-- 2k descent from 5k platform to 1200 dirty up level flight.
|
||||
self.C3Descent2k.name="2k Descent"
|
||||
@ -1009,9 +1016,6 @@ function AIRBOSS:_InitStennis()
|
||||
self.C3Descent2k.LimitXmax=-UTILS.NMToMeters(12) --TODO: better rho dist! now switch to dirty up level flight 12 NM.
|
||||
self.C3Descent2k.LimitZmin=nil
|
||||
self.C3Descent2k.LimitZmax=nil
|
||||
self.C3Descent2k.Altitude=UTILS.FeetToMeters(5000)
|
||||
self.C3Descent2k.AoA=nil
|
||||
self.C3Descent2k.Distance=-UTILS.NMToMeters(20)
|
||||
|
||||
-- Level out at 1200 ft and dirty up.
|
||||
self.C3DirtyUp.name="Dirty Up"
|
||||
@ -1023,23 +1027,17 @@ function AIRBOSS:_InitStennis()
|
||||
self.C3DirtyUp.LimitXmax=-UTILS.NMToMeters(3) --TODO: better rho dist! Intercept glideslope and follow bullseye.
|
||||
self.C3DirtyUp.LimitZmin=nil
|
||||
self.C3DirtyUp.LimitZmax=nil
|
||||
self.C3DirtyUp.Altitude=UTILS.FeetToMeters(1200)
|
||||
self.C3DirtyUp.AoA=nil
|
||||
self.C3DirtyUp.Distance=-UTILS.NMToMeters(12)
|
||||
|
||||
-- Intercept glide slope and follow bullseye.
|
||||
self.C3DirtyUp.name="Bullseye"
|
||||
self.C3DirtyUp.Xmin=-UTILS.NMToMeters(4)
|
||||
self.C3DirtyUp.Xmax=nil
|
||||
self.C3DirtyUp.Zmin=-UTILS.NMToMeters(30)
|
||||
self.C3DirtyUp.Zmax= UTILS.NMToMeters(30)
|
||||
self.C3DirtyUp.LimitXmin=nil
|
||||
self.C3DirtyUp.LimitXmax=-UTILS.NMToMeters(1) --TODO: better rho dist! Call the ball.
|
||||
self.C3DirtyUp.LimitZmin=nil
|
||||
self.Bullseye.name="Bullseye"
|
||||
self.Bullseye.Xmin=-UTILS.NMToMeters(4)
|
||||
self.Bullseye.Xmax=nil
|
||||
self.Bullseye.Zmin=-UTILS.NMToMeters(30)
|
||||
self.Bullseye.Zmax= UTILS.NMToMeters(30)
|
||||
self.Bullseye.LimitXmin=nil
|
||||
self.Bullseye.LimitXmax=-UTILS.NMToMeters(1) --TODO: better rho dist! Call the ball.
|
||||
self.Bullseye.LimitZmin=nil
|
||||
self.C3DirtyUp.LimitZmax=nil
|
||||
self.C3DirtyUp.Altitude=UTILS.FeetToMeters(1200)
|
||||
self.C3DirtyUp.AoA=nil
|
||||
self.C3DirtyUp.Distance=-UTILS.NMToMeters(3)
|
||||
|
||||
-- Upwind leg
|
||||
self.Upwind.name="Upwind"
|
||||
@ -1051,9 +1049,6 @@ function AIRBOSS:_InitStennis()
|
||||
self.Upwind.LimitXmax=nil
|
||||
self.Upwind.LimitZmin=0
|
||||
self.Upwind.LimitZmax=nil
|
||||
self.Upwind.Altitude=UTILS.FeetToMeters(800)
|
||||
self.Upwind.AoA=8.1
|
||||
self.Upwind.Distance=nil
|
||||
|
||||
-- Early break
|
||||
self.BreakEarly.name="Early Break"
|
||||
@ -1065,9 +1060,6 @@ function AIRBOSS:_InitStennis()
|
||||
self.BreakEarly.LimitXmax=nil
|
||||
self.BreakEarly.LimitZmin=-370 -- 0.2 NM port of carrier
|
||||
self.BreakEarly.LimitZmax=nil
|
||||
self.BreakEarly.Altitude=UTILS.FeetToMeters(800)
|
||||
self.BreakEarly.AoA=8.1
|
||||
self.BreakEarly.Distance=nil
|
||||
|
||||
-- Late break
|
||||
self.BreakLate.name="Late Break"
|
||||
@ -1079,9 +1071,6 @@ function AIRBOSS:_InitStennis()
|
||||
self.BreakLate.LimitXmax=nil
|
||||
self.BreakLate.LimitZmin=-1470 --0.8 NM
|
||||
self.BreakLate.LimitZmax=nil
|
||||
self.BreakLate.Altitude=UTILS.FeetToMeters(800)
|
||||
self.BreakLate.AoA=8.1
|
||||
self.BreakLate.Distance=nil
|
||||
|
||||
-- Abeam position
|
||||
self.Abeam.name="Abeam Position"
|
||||
@ -1093,9 +1082,6 @@ function AIRBOSS:_InitStennis()
|
||||
self.Abeam.LimitXmax=nil
|
||||
self.Abeam.LimitZmin=nil
|
||||
self.Abeam.LimitZmax=nil
|
||||
self.Abeam.Altitude=UTILS.FeetToMeters(600)
|
||||
self.Abeam.AoA=8.1
|
||||
self.Abeam.Distance=UTILS.NMToMeters(1.2)
|
||||
|
||||
-- At the ninety
|
||||
self.Ninety.name="Ninety"
|
||||
@ -1107,9 +1093,6 @@ function AIRBOSS:_InitStennis()
|
||||
self.Ninety.LimitXmax=nil
|
||||
self.Ninety.LimitZmin=nil
|
||||
self.Ninety.LimitZmax=-1111
|
||||
self.Ninety.Altitude=UTILS.FeetToMeters(500)
|
||||
self.Ninety.AoA=8.1
|
||||
self.Ninety.Distance=nil
|
||||
|
||||
-- Wake position
|
||||
self.Wake.name="Wake"
|
||||
@ -1121,9 +1104,6 @@ function AIRBOSS:_InitStennis()
|
||||
self.Wake.LimitXmax=nil
|
||||
self.Wake.LimitZmin=0
|
||||
self.Wake.LimitZmax=nil
|
||||
self.Wake.Altitude=UTILS.FeetToMeters(370)
|
||||
self.Wake.AoA=8.1
|
||||
self.Wake.Distance=nil
|
||||
|
||||
-- In the groove
|
||||
self.Groove.name="Groove"
|
||||
@ -1135,9 +1115,6 @@ function AIRBOSS:_InitStennis()
|
||||
self.Groove.LimitXmax=nil
|
||||
self.Groove.LimitZmin=nil
|
||||
self.Groove.LimitZmax=nil
|
||||
self.Groove.Altitude=UTILS.FeetToMeters(300)
|
||||
self.Groove.AoA=8.1
|
||||
self.Groove.Distance=nil
|
||||
|
||||
-- Landing trap
|
||||
self.Trap.name="Trap"
|
||||
@ -1149,9 +1126,130 @@ function AIRBOSS:_InitStennis()
|
||||
self.Trap.LimitXmax=nil
|
||||
self.Trap.LimitZmin=nil
|
||||
self.Trap.LimitZmax=nil
|
||||
self.Trap.Altitude=nil
|
||||
self.Trap.AoA=nil
|
||||
self.Trap.Distance=nil
|
||||
|
||||
end
|
||||
|
||||
--- Get optimal aircraft flight parameters at checkpoint.
|
||||
-- @param #AIRBOSS.PlayerData playerData Player data table.
|
||||
-- @param #string step Pattern step.
|
||||
-- @return #number Altitude in meters or nil.
|
||||
-- @return #number Angle of Attack or nil.
|
||||
-- @return #number Distance to carrier in meters or nil.
|
||||
-- @return #number Speed in m/s or nil.
|
||||
function AIRBOSS:_GetAircraftParameters(playerData, step)
|
||||
|
||||
step=step or playerData.step
|
||||
local hornet=playerData.actype==AIRBOSS.AircraftCarrier.HORNET
|
||||
local skyhawk=playerData.actype==AIRBOSS.AircraftCarrier.A4EC
|
||||
|
||||
local dist
|
||||
local alt
|
||||
local aoa
|
||||
local speed
|
||||
|
||||
if step==AIRBOSS.PatternStep.DESCENT4K then
|
||||
|
||||
speed=UTILS.KnotsToMps(250)
|
||||
|
||||
elseif step==AIRBOSS.PatternStep.DESCENT2K then
|
||||
|
||||
alt=UTILS.FeetToMeters(5000)
|
||||
|
||||
dist=UTILS.NMToMeters(20)
|
||||
|
||||
speed=UTILS.KnotsToMps(250)
|
||||
|
||||
elseif step==AIRBOSS.PatternStep.DIRTYUP then
|
||||
|
||||
alt=UTILS.FeetToMeters(1200)
|
||||
|
||||
dist=UTILS.NMToMeters(12)
|
||||
|
||||
speed=UTILS.KnotsToMps(250)
|
||||
|
||||
elseif step==AIRBOSS.PatternStep.BULLSEYE then
|
||||
|
||||
alt=UTILS.FeetToMeters(1200)
|
||||
|
||||
dist=-UTILS.NMToMeters(3)
|
||||
|
||||
elseif step==AIRBOSS.PatternStep.INITIAL then
|
||||
|
||||
if hornet then
|
||||
alt=UTILS.FeetToMeters(800)
|
||||
speed=UTILS.KnotsToMps(350)
|
||||
elseif skyhawk then
|
||||
alt=UTILS.FeetToMeters(600)
|
||||
speed=UTILS.KnotsToMps(250)
|
||||
end
|
||||
|
||||
elseif step==AIRBOSS.PatternStep.UPWIND then
|
||||
|
||||
if hornet then
|
||||
alt=UTILS.FeetToMeters(800)
|
||||
elseif skyhawk then
|
||||
alt=UTILS.FeetToMeters(600)
|
||||
end
|
||||
|
||||
elseif step==AIRBOSS.PatternStep.EARLYBREAK then
|
||||
|
||||
if hornet then
|
||||
alt=UTILS.FeetToMeters(800)
|
||||
elseif skyhawk then
|
||||
alt=UTILS.FeetToMeters(600)
|
||||
end
|
||||
|
||||
elseif step==AIRBOSS.PatternStep.LATEBREAK then
|
||||
|
||||
if hornet then
|
||||
alt=UTILS.FeetToMeters(800)
|
||||
elseif skyhawk then
|
||||
alt=UTILS.FeetToMeters(600)
|
||||
end
|
||||
|
||||
elseif step==AIRBOSS.PatternStep.ABEAM then
|
||||
|
||||
if hornet then
|
||||
alt=UTILS.FeetToMeters(600)
|
||||
elseif skyhawk then
|
||||
alt=UTILS.FeetToMeters(500)
|
||||
end
|
||||
|
||||
aoa=8.1
|
||||
|
||||
dist=UTILS.NMToMeters(1.2)
|
||||
|
||||
elseif step==AIRBOSS.PatternStep.NINETY then
|
||||
|
||||
if hornet then
|
||||
alt=UTILS.FeetToMeters(500)
|
||||
elseif skyhawk then
|
||||
alt=UTILS.FeetToMeters(500)
|
||||
end
|
||||
|
||||
aoa=8.1
|
||||
|
||||
elseif step==AIRBOSS.PatternStep.WAKE then
|
||||
|
||||
if hornet then
|
||||
alt=UTILS.FeetToMeters(370)
|
||||
elseif skyhawk then
|
||||
alt=UTILS.FeetToMeters(370) --?
|
||||
end
|
||||
|
||||
aoa=8.1
|
||||
|
||||
elseif step==AIRBOSS.PatternStep.FINAL then
|
||||
|
||||
if hornet then
|
||||
alt=UTILS.FeetToMeters(300)
|
||||
elseif skyhawk then
|
||||
alt=UTILS.FeetToMeters(300) --?
|
||||
end
|
||||
|
||||
aoa=8.1
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@ -1162,20 +1260,18 @@ end
|
||||
--- Check marshal and pattern queues.
|
||||
-- @param #AIRBOSS self
|
||||
function AIRBOSS:_CheckQueue()
|
||||
|
||||
local npattern=0
|
||||
local nmarshal=#self.Qmarshal
|
||||
|
||||
for _,_flight in pairs(self.Qpattern) do
|
||||
local flight=_flight --#AIRBOSS.Flightitem
|
||||
npattern=npattern+flight.nunits
|
||||
end
|
||||
|
||||
-- Print queues.
|
||||
self:_PrintQueue(self.flights, "All Flights")
|
||||
self:_PrintQueue(self.Qmarshal, "Marshal")
|
||||
self:_PrintQueue(self.Qpattern, "Pattern")
|
||||
|
||||
-- Get number of aircraft units(!) currently in pattern.
|
||||
local _,npattern=self:_GetQueueInfo(self.Qpattern)
|
||||
|
||||
-- Get number of flight groups(!) in marshal pattern.
|
||||
local nmarshal=#self.Qmarshal
|
||||
|
||||
-- Check if there are flights in marshal strack and if the pattern is free.
|
||||
if nmarshal>0 and npattern<1 then
|
||||
|
||||
@ -1227,10 +1323,8 @@ end
|
||||
-- @param #string name Queue name.
|
||||
function AIRBOSS:_PrintQueue(queue, name)
|
||||
|
||||
local nqueue=#queue
|
||||
|
||||
local text=string.format("%s Queue:", name)
|
||||
if nqueue==0 then
|
||||
if #queue==0 then
|
||||
text=text.." empty."
|
||||
else
|
||||
for i,_flight in pairs(queue) do
|
||||
@ -1239,8 +1333,10 @@ function AIRBOSS:_PrintQueue(queue, name)
|
||||
local stack=flight.flag:Get()
|
||||
local alt=UTILS.MetersToFeet(self:_GetMarshalAltitude(stack))
|
||||
local fuel=flight.group:GetFuelMin()*100
|
||||
local case=flight.case
|
||||
local ai=tostring(flight.ai)
|
||||
text=text..string.format("\n[%d] %s*%d: alt=%d ft, stack(flag)=%d, time=%s, fuel=%d, ai=%s", i, flight.groupname, flight.nunits, alt, stack, clock, fuel, ai)
|
||||
text=text..string.format("\n[%d] %s*%d: stackalt=%d ft, flag=%d, case=%d, time=%s, fuel=%d, ai=%s",
|
||||
i, flight.groupname, flight.nunits, alt, stack, case, clock, fuel, ai)
|
||||
end
|
||||
end
|
||||
self:I(self.lid..text)
|
||||
@ -1407,6 +1503,7 @@ function AIRBOSS:_CreateFlightGroup(group)
|
||||
flight.actype=group:GetTypeName()
|
||||
flight.onboardnumbers=self:_GetOnboardNumbers(group)
|
||||
flight.section={}
|
||||
flight.case=self.case
|
||||
|
||||
if human then
|
||||
|
||||
@ -1443,29 +1540,34 @@ function AIRBOSS:_RemoveFlightGroup(group)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
--- Orbit at a specified position at a specified alititude with a specified speed.
|
||||
-- @param #AIRBOSS self
|
||||
-- @param #AIRBOSS.PlayerData playerData Player data.
|
||||
-- @param #AIRBOSS.Flightitem flight Flight group.
|
||||
function AIRBOSS:_MarshalPlayer(playerData, flight)
|
||||
|
||||
-- Number of full marshal stacks.
|
||||
local nstacks=#self.Qmarshal
|
||||
|
||||
-- Check if flight is known to the airboss already.
|
||||
if playerData and flight then
|
||||
|
||||
-- Number of flight groups in stack.
|
||||
local ngroups,nunits=self:_GetQueueInfo(self.Qmarshal, self.case)
|
||||
|
||||
-- Assign next free stack to this flight.
|
||||
local mystack=ngroups+1
|
||||
|
||||
-- Add group to marshal stack.
|
||||
self:_AddMarshallGroup(flight, nstacks+1)
|
||||
self:_AddMarshallGroup(flight, mystack)
|
||||
|
||||
-- Set step to holding.
|
||||
playerData.step=AIRBOSS.PatternStep.HOLDING
|
||||
|
||||
-- Set values for all flights in section.
|
||||
-- Set same stack for all flights in section.
|
||||
for _,_flight in pairs(flight.section) do
|
||||
local flight=_flight --#AIRBOSS.Flightitem
|
||||
flight.player.step=AIRBOSS.PatternStep.HOLDING
|
||||
flight.flag:Set(nstacks+1)
|
||||
flight.flag:Set(mystack)
|
||||
end
|
||||
|
||||
else
|
||||
@ -1553,15 +1655,19 @@ end
|
||||
--- Get marshal altitude and position.
|
||||
-- @param #AIRBOSS self
|
||||
-- @param #number stack Assigned stack number. Counting starts at one, i.e. stack=1 is the first stack.
|
||||
-- @param #number case Recovery case. Default is self.case.
|
||||
-- @return #number Holding altitude in meters.
|
||||
-- @return Core.Point#COORDINATE Holding position coordinate.
|
||||
-- @return Core.Point#COORDINATE Second holding position coordinate of racetrack pattern for CASE II/III recoveries.
|
||||
function AIRBOSS:_GetMarshalAltitude(stack)
|
||||
function AIRBOSS:_GetMarshalAltitude(stack, case)
|
||||
|
||||
-- Stack <= 0.
|
||||
if stack<=0 then
|
||||
return 0,nil,nil
|
||||
end
|
||||
|
||||
-- Recovery case.
|
||||
case=case or self.case
|
||||
|
||||
-- Carrier position.
|
||||
local Carrier=self:GetCoordinate()
|
||||
@ -1573,7 +1679,7 @@ function AIRBOSS:_GetMarshalAltitude(stack)
|
||||
local p1=nil --Core.Point#COORDINATE
|
||||
local p2=nil --Core.Point#COORDINATE
|
||||
|
||||
if self.case==1 then
|
||||
if case==1 then
|
||||
-- CASE I: Holding at 2000 ft on a circular pattern port of the carrier. Interval +1000 ft for next stack.
|
||||
angels0=2
|
||||
Dist=UTILS.NMToMeters(2.5)
|
||||
@ -1592,12 +1698,32 @@ function AIRBOSS:_GetMarshalAltitude(stack)
|
||||
return altitude, p1, p2
|
||||
end
|
||||
|
||||
--- Get next free stack.
|
||||
-- @param #AIRBOSS self
|
||||
-- @param #number case Recovery case
|
||||
-- @return #number Smalest (lowest) free stack.
|
||||
function AIRBOSS:_GetFreeStack(case)
|
||||
|
||||
case=case or self.case
|
||||
|
||||
local stack
|
||||
if case==1 then
|
||||
stack=self:_GetQueueInfo(self.Qmarshal, 1)
|
||||
else
|
||||
stack=self:_GetQueueInfo(self.Qmarshal, 23)
|
||||
end
|
||||
|
||||
return stack+1
|
||||
end
|
||||
|
||||
|
||||
--- Get number of groups and units in queue.
|
||||
-- @param #AIRBOSS self
|
||||
-- @param #table queue The queue. Can me all, marshal or pattern.
|
||||
-- @return #number Number of aircraft.
|
||||
-- @return #number Number of flight groups.
|
||||
function AIRBOSS:_GetQueueInfo(queue)
|
||||
-- @param #number case (Optional) Count only flights which are in a specific recovery case.
|
||||
-- @return #number Total Number of flight groups in queue.
|
||||
-- @return #number Total number of aircraft in queue.
|
||||
function AIRBOSS:_GetQueueInfo(queue, case)
|
||||
|
||||
local ngroup=0
|
||||
local nunits=0
|
||||
@ -1605,8 +1731,17 @@ function AIRBOSS:_GetQueueInfo(queue)
|
||||
for _,_flight in pairs(queue) do
|
||||
local flight=_flight --#AIRBOSS.Flightitem
|
||||
|
||||
ngroup=ngroup+1
|
||||
nunits=nunits+flight.nunits
|
||||
if case then
|
||||
|
||||
if flight.case==case or (case==23 and (flight.case==2 or flight.case==3)) then
|
||||
ngroup=ngroup+1
|
||||
nunits=nunits+flight.nunits
|
||||
end
|
||||
|
||||
else
|
||||
ngroup=ngroup+1
|
||||
nunits=nunits+flight.nunits
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@ -1622,6 +1757,9 @@ function AIRBOSS:_AddMarshallGroup(flight, flagvalue)
|
||||
-- Set flag value. This corresponds to the stack number which starts at 1.
|
||||
flight.flag:Set(flagvalue)
|
||||
|
||||
-- Set recovery case.
|
||||
flight.case=self.case
|
||||
|
||||
-- Pressure.
|
||||
local P=UTILS.hPa2inHg(self:GetCoordinate():GetPressure())
|
||||
|
||||
@ -1629,12 +1767,12 @@ function AIRBOSS:_AddMarshallGroup(flight, flagvalue)
|
||||
|
||||
-- TODO: Get correct board number if possible?
|
||||
local boardnumber=tostring(flight.onboardnumbers[unitname])
|
||||
local alt=UTILS.MetersToFeet(self:_GetMarshalAltitude(flagvalue))
|
||||
local alt=UTILS.MetersToFeet(self:_GetMarshalAltitude(flagvalue, flight.case))
|
||||
local brc=self:_BaseRecoveryCourse()
|
||||
|
||||
-- Marshal message.
|
||||
-- TODO: Get charlie time estimate.
|
||||
local text=string.format("%s, Case %d, BRC is %03d, hold at %d. Expected Charlie Time XX.\n", boardnumber, self.case, brc, alt)
|
||||
local text=string.format("%s, Case %d, BRC is %03d, hold at %d. Expected Charlie Time XX.\n", boardnumber, flight.case, brc, alt)
|
||||
text=text..string.format("Altimeter %.2f. Report see me.", P)
|
||||
MESSAGE:New(text, 30):ToAll()
|
||||
|
||||
@ -1647,16 +1785,16 @@ end
|
||||
-- @param #AIRBOSS self
|
||||
function AIRBOSS:_CheckCollapseMarshalStack()
|
||||
|
||||
-- First flight to enter the landing pattern.
|
||||
-- Next flight in line.
|
||||
local flight=self.Qmarshal[1] --#AIRBOSS.Flightitem
|
||||
|
||||
-- TODO: better message.
|
||||
local text=string.format("%s, you are cleared for Case %d recovery pattern!", flight.groupname, self.case)
|
||||
local text=string.format("%s, you are cleared for Case %d recovery pattern!", flight.groupname, flight.case)
|
||||
|
||||
-- Check if flight is AI or human. If AI, we collapse the stack and commence. If human, we suggest to commence.
|
||||
if flight.ai then
|
||||
-- Collapse stack and send AI to pattern.
|
||||
self:_CollapseMarshalStack()
|
||||
self:_CollapseMarshalStack(flight.case)
|
||||
else
|
||||
-- TODO only if skil is not TOPGUN
|
||||
text=text..string.format("\nUse F10 radio menu \"Commence!\" command when you are ready!")
|
||||
@ -1668,34 +1806,49 @@ end
|
||||
|
||||
--- Collapse marshal stack.
|
||||
-- @param #AIRBOSS self
|
||||
function AIRBOSS:_CollapseMarshalStack()
|
||||
-- @param #number case Recovery case.
|
||||
function AIRBOSS:_CollapseMarshalStack(case)
|
||||
|
||||
-- Decrease flag values of all flight groups in marshal stack.
|
||||
for _,_flight in pairs(self.Qmarshal) do
|
||||
local flight=_flight --#AIRBOSS.Flightitem
|
||||
|
||||
-- Get current flag/stack value.
|
||||
local flagvalue=flight.flag:Get()
|
||||
|
||||
-- Decrease by one.
|
||||
flight.flag:Set(flagvalue-1)
|
||||
|
||||
-- Also decrease flag for section members of flight.
|
||||
for _,_sec in pairs(flight.section) do
|
||||
local sec=_sec --#AIRBOSS.Flightitem
|
||||
sec.flag:Set(flagvalue-1)
|
||||
end
|
||||
-- Only collaps stack of which the flight left. CASE II/III stack is the same.
|
||||
if (case==1 and flight.case==1) or (case>1 and flight.case>1) then
|
||||
|
||||
-- Get current flag/stack value.
|
||||
local stack=flight.flag:Get()
|
||||
|
||||
-- Decrease by one.
|
||||
flight.flag:Set(stack-1)
|
||||
|
||||
-- Inform players.
|
||||
if flight.player then
|
||||
local alt=UTILS.MetersToFeet(self:_GetMarshalAltitude(stack-1,case))
|
||||
local text=string.format("descent to next lower stack at %d ft", alt)
|
||||
self:MessageToPlayer(flight.player, text, "MARSHAL", nil, 10)
|
||||
end
|
||||
|
||||
-- Also decrease flag for section members of flight.
|
||||
for _,_sec in pairs(flight.section) do
|
||||
local sec=_sec --#AIRBOSS.Flightitem
|
||||
sec.flag:Set(stack-1)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
--[[
|
||||
-- Number of marshal flight groups.
|
||||
local nmarshal=#self.Qmarshal
|
||||
|
||||
-- TODO: collapse marshal stack only from N to N-x. For example, when a group in the stack leaves (e.g. for refueling).
|
||||
for i=nmarshal,1,-1 do
|
||||
local flight=self.Qmarshal[i] --#AIRBOSS.Flightitem
|
||||
|
||||
--flight.
|
||||
end
|
||||
]]
|
||||
|
||||
-- First flight to enter the landing pattern.
|
||||
local flight=self.Qmarshal[1] --#AIRBOSS.Flightitem
|
||||
@ -2494,7 +2647,7 @@ function AIRBOSS:_BullsEye(playerData)
|
||||
return
|
||||
end
|
||||
|
||||
-- Check if we are in front of the boat (diffX > 0).
|
||||
-- Check that we reached the position.
|
||||
if self:_CheckLimits(X, Z, self.C3BullsEye) then
|
||||
|
||||
-- Get altitiude.
|
||||
@ -2532,8 +2685,7 @@ function AIRBOSS:_Upwind(playerData)
|
||||
-- Check if we are in front of the boat (diffX > 0).
|
||||
if self:_CheckLimits(X, Z, self.Upwind) then
|
||||
|
||||
-- Get altitiude.
|
||||
local altitude=playerData.unit:GetAltitude()
|
||||
local alt, aoa, dist, speed=self:_GetAircraftParameters(playerData)
|
||||
|
||||
-- Get altitude.
|
||||
local hint, debrief=self:_AltitudeCheck(playerData, self.Upwind, altitude)
|
||||
@ -2653,18 +2805,16 @@ function AIRBOSS:_Abeam(playerData)
|
||||
-- Check nest step threshold.
|
||||
if self:_CheckLimits(X, Z, self.Abeam) then
|
||||
|
||||
-- Get AoA and altitude.
|
||||
local aoa = playerData.unit:GetAoA()
|
||||
local alt = playerData.unit:GetAltitude()
|
||||
local alt, aoa, dist, speed=self:_GetAircraftParameters(playerData)
|
||||
|
||||
-- Grade Altitude.
|
||||
local hintAlt, debriefAlt=self:_AltitudeCheck(playerData, self.Abeam, alt)
|
||||
local hintAlt, debriefAlt=self:_AltitudeCheck(playerData, alt)
|
||||
|
||||
-- Grade AoA.
|
||||
local hintAoA, debriefAoA=self:_AoACheck(playerData, self.Abeam, aoa)
|
||||
local hintAoA, debriefAoA=self:_AoACheck(playerData, aoa)
|
||||
|
||||
-- Grade distance to carrier.
|
||||
local hintDist, debriefDist=self:_DistanceCheck(playerData, self.Abeam, math.abs(Z))
|
||||
local hintDist, debriefDist=self:_DistanceCheck(playerData, dist) --math.abs(Z)
|
||||
|
||||
-- Compile full hint.
|
||||
local hint=string.format("%s\n%s\n%s", hintAlt, hintAoA, hintDist)
|
||||
@ -2701,15 +2851,13 @@ function AIRBOSS:_Ninety(playerData)
|
||||
-- At the 90, i.e. 90 degrees between player heading and BRC of carrier.
|
||||
if relheading<=90 then
|
||||
|
||||
-- Get altitude and aoa.
|
||||
local alt=playerData.unit:GetAltitude()
|
||||
local aoa=playerData.unit:GetAoA()
|
||||
local alt, aoa, dist, speed=self:_GetAircraftParameters(playerData)
|
||||
|
||||
-- Grade altitude.
|
||||
local hintAlt, debriefAlt=self:_AltitudeCheck(playerData, self.Ninety, alt)
|
||||
local hintAlt, debriefAlt=self:_AltitudeCheck(playerData, alt)
|
||||
|
||||
-- Grade AoA.
|
||||
local hintAoA, debriefAoA=self:_AoACheck(playerData, self.Ninety, aoa)
|
||||
local hintAoA, debriefAoA=self:_AoACheck(playerData, aoa)
|
||||
|
||||
-- Compile full hint.
|
||||
local hint=string.format("%s\n%s", hintAlt, hintAoA)
|
||||
@ -2747,16 +2895,14 @@ function AIRBOSS:_Wake(playerData)
|
||||
|
||||
-- Right behind the wake of the carrier dZ>0.
|
||||
if self:_CheckLimits(X, Z, self.Wake) then
|
||||
|
||||
-- Get player altitude and AoA.
|
||||
local alt=playerData.unit:GetAltitude()
|
||||
local aoa=playerData.unit:GetAoA()
|
||||
|
||||
local alt, aoa, dist, speed=self:_GetAircraftParameters(playerData)
|
||||
|
||||
-- Grade altitude.
|
||||
local hintAlt, debriefAlt=self:_AltitudeCheck(playerData, self.Wake, alt)
|
||||
local hintAlt, debriefAlt=self:_AltitudeCheck(playerData, alt)
|
||||
|
||||
-- Grade AoA.
|
||||
local hintAoA, debriefAoA=self:_AoACheck(playerData, self.Wake, aoa)
|
||||
local hintAoA, debriefAoA=self:_AoACheck(playerData, aoa)
|
||||
|
||||
-- Compile full hint.
|
||||
local hint=string.format("%s\n%s", hintAlt, hintAoA)
|
||||
@ -2793,15 +2939,13 @@ function AIRBOSS:_Final(playerData)
|
||||
|
||||
if math.abs(lineup)<5 and math.abs(relhead)<10 then
|
||||
|
||||
-- Get player altitude and AoA.
|
||||
local alt = playerData.unit:GetAltitude()
|
||||
local aoa = playerData.unit:GetAoA()
|
||||
local alt, aoa, dist, speed=self:_GetAircraftParameters(playerData)
|
||||
|
||||
-- Grade altitude.
|
||||
local hintAlt, debriefAlt=self:_AltitudeCheck(playerData, self.Groove, alt)
|
||||
local hintAlt, debriefAlt=self:_AltitudeCheck(playerData, alt)
|
||||
|
||||
-- AoA feed back
|
||||
local hintAoA, debriefAoA=self:_AoACheck(playerData, self.Groove, aoa)
|
||||
local hintAoA, debriefAoA=self:_AoACheck(playerData, aoa)
|
||||
|
||||
-- Compile full hint.
|
||||
local hint=string.format("%s\n%s", hintAlt, hintAoA)
|
||||
@ -3765,16 +3909,17 @@ function AIRBOSS:_GetGoodBadScore(playerData)
|
||||
return lowscore, badscore
|
||||
end
|
||||
|
||||
|
||||
|
||||
--- Evaluate player's altitude at checkpoint.
|
||||
-- @param #AIRBOSS self
|
||||
-- @param #AIRBOSS.PlayerData playerData Player data table.
|
||||
-- @param #AIRBOSS.Checkpoint checkpoint Checkpoint.
|
||||
-- @param #number altitude Player's current altitude in meters.
|
||||
-- @param #number altopt Optimal alitude in meters.
|
||||
-- @return #string Feedback text.
|
||||
-- @return #string Debriefing text.
|
||||
function AIRBOSS:_AltitudeCheck(playerData, checkpoint, altitude)
|
||||
function AIRBOSS:_AltitudeCheck(playerData, altopt)
|
||||
|
||||
if checkpoint.Altitude==nil then
|
||||
if altopt==nil then
|
||||
return nil, nil
|
||||
end
|
||||
|
||||
@ -3785,7 +3930,7 @@ function AIRBOSS:_AltitudeCheck(playerData, checkpoint, altitude)
|
||||
local lowscore, badscore=self:_GetGoodBadScore(playerData)
|
||||
|
||||
-- Altitude error +-X%
|
||||
local _error=(altitude-checkpoint.Altitude)/checkpoint.Altitude*100
|
||||
local _error=(altitude-altopt)/altopt*100
|
||||
|
||||
local hint
|
||||
if _error>badscore then
|
||||
@ -3818,21 +3963,23 @@ end
|
||||
--- Evaluate player's altitude at checkpoint.
|
||||
-- @param #AIRBOSS self
|
||||
-- @param #AIRBOSS.PlayerData playerData Player data table.
|
||||
-- @param #AIRBOSS.Checkpoint checkpoint Checkpoint.
|
||||
-- @param #number distance Player's current distance to the boat in meters.
|
||||
-- @param #number optdist Optimal distance in meters.
|
||||
-- @return #string Feedback message text.
|
||||
-- @return #string Debriefing text.
|
||||
function AIRBOSS:_DistanceCheck(playerData, checkpoint, distance)
|
||||
function AIRBOSS:_DistanceCheck(playerData, optdist)
|
||||
|
||||
if checkpoint.Distance==nil then
|
||||
if optdist==nil then
|
||||
return nil, nil
|
||||
end
|
||||
|
||||
-- Distance to carrier.
|
||||
local distance=playerData.unit:GetCoodinate():Get2DDistance(self:GetCoordinate())
|
||||
|
||||
-- Get relative score.
|
||||
local lowscore, badscore = self:_GetGoodBadScore(playerData)
|
||||
|
||||
-- Altitude error +-X%
|
||||
local _error=(distance-checkpoint.Distance)/checkpoint.Distance*100
|
||||
local _error=(distance-optdist)/optdist*100
|
||||
|
||||
local hint
|
||||
if _error>badscore then
|
||||
@ -3865,21 +4012,23 @@ end
|
||||
--- Score for correct AoA.
|
||||
-- @param #AIRBOSS self
|
||||
-- @param #AIRBOSS.PlayerData playerData Player data.
|
||||
-- @param #AIRBOSS.Checkpoint checkpoint Checkpoint.
|
||||
-- @param #number aoa Player's current Angle of attack.
|
||||
-- @param #number optaoa Optimal AoA.
|
||||
-- @return #string Feedback message text or easy and normal difficulty level or nil for hard.
|
||||
-- @return #string Debriefing text.
|
||||
function AIRBOSS:_AoACheck(playerData, checkpoint, aoa)
|
||||
function AIRBOSS:_AoACheck(playerData, optaoa)
|
||||
|
||||
if checkpoint.AoA==nil then
|
||||
if optaoa==nil then
|
||||
return nil, nil
|
||||
end
|
||||
|
||||
-- Get relative score.
|
||||
local lowscore, badscore = self:_GetGoodBadScore(playerData)
|
||||
|
||||
-- Player AoA
|
||||
local aoa=playerData.unit:GetAoA()
|
||||
|
||||
-- Altitude error +-X%
|
||||
local _error=(aoa-checkpoint.AoA)/checkpoint.AoA*100
|
||||
local _error=(aoa-optaoa)/optaoa*100
|
||||
|
||||
local hint
|
||||
if _error>badscore then --Slow
|
||||
@ -3924,21 +4073,6 @@ end
|
||||
function AIRBOSS:_Debrief(playerData)
|
||||
self:F("Debriefing")
|
||||
|
||||
-- Debriefing text.
|
||||
local text=string.format("Debriefing:\n")
|
||||
text=text..string.format("================================\n")
|
||||
for _,_data in pairs(playerData.debrief) do
|
||||
local step=_data.step
|
||||
local comment=_data.hint
|
||||
text=text..string.format("* %s:\n",step)
|
||||
text=text..string.format("%s\n", comment)
|
||||
end
|
||||
|
||||
local text="Your detailed debriefing can now be seen in F10 radio menu."
|
||||
|
||||
-- Send debrief message to player
|
||||
self:_SendMessageToPlayer(text, 30, playerData, true, "Paddles")
|
||||
|
||||
-- LSO grade, points, and flight data analyis.
|
||||
local grade, points, analysis=self:_LSOgrade(playerData)
|
||||
|
||||
@ -3951,8 +4085,9 @@ function AIRBOSS:_Debrief(playerData)
|
||||
table.insert(playerData.grades, mygrade)
|
||||
|
||||
-- LSO grade message.
|
||||
text=string.format("%s %.1f PT - %s", grade, points, analysis)
|
||||
self:_SendMessageToPlayer(text, 10, playerData, true, "Paddles", 30)
|
||||
local text=string.format("%s %.1f PT - %s", grade, points, analysis)
|
||||
text=text..string.format("Your detailed debriefing can now be seen in F10 radio menu.")
|
||||
self:MessageToPlayer(playerData,text, "LSO","" , 30, true)
|
||||
|
||||
-- New approach.
|
||||
if playerData.boltered or playerData.waveoff or playerData.patternwo then
|
||||
@ -4068,11 +4203,11 @@ end
|
||||
-- @param #AIRBOSS self
|
||||
-- @param #AIRBOSS.PlayerData playerData Player data.
|
||||
-- @param #string message The message to send.
|
||||
-- @param #string sender The person who sends the message.
|
||||
-- @param #string receiver The person who receives the message.
|
||||
-- @param #number duration Display message duration. Default 5 sec.
|
||||
-- @param #string sender The person who sends the message or nil.
|
||||
-- @param #string receiver The person who receives the message. Default player's onboard number. Set to \"\" for no receiver.
|
||||
-- @param #number duration Display message duration. Default 10 seconds.
|
||||
-- @param #boolean clear If true, clear screen from previous messages.
|
||||
-- @param #number delay Delay in seconds, before the message is send.
|
||||
-- @param #number delay Delay in seconds, before the message is displayed.
|
||||
function AIRBOSS:MessageToPlayer(playerData, message, sender, receiver, duration, clear, delay)
|
||||
|
||||
if playerData and message and message~="" then
|
||||
@ -4472,7 +4607,7 @@ function AIRBOSS:_RequestStraightIn(_unitName)
|
||||
-- Get flight group.
|
||||
local flight=self:_GetFlightFromGroupInQueue(playerData.group, self.flights)
|
||||
|
||||
local text
|
||||
local text
|
||||
if flight then
|
||||
|
||||
-- Get stack value.
|
||||
@ -4484,7 +4619,7 @@ function AIRBOSS:_RequestStraightIn(_unitName)
|
||||
else
|
||||
|
||||
-- Number of aircraft currently in pattern.
|
||||
local npattern=self:_GetQueueInfo(self.Qpattern)
|
||||
local _,npattern=self:_GetQueueInfo(self.Qpattern)
|
||||
|
||||
-- TODO: set nmax for pattern. Should be ~6 but let's make this 4.
|
||||
if npattern>0 then
|
||||
@ -4498,7 +4633,7 @@ function AIRBOSS:_RequestStraightIn(_unitName)
|
||||
playerData.step=AIRBOSS.PatternStep.COMMENCING
|
||||
|
||||
-- Collaps marshal stack.
|
||||
self:_CollapseMarshalStack()
|
||||
self:_CollapseMarshalStack(flight.case)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user