mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-08-15 10:47:21 +00:00
AIRBOSS v0.4.8w
This commit is contained in:
parent
96b60d8ac0
commit
5a327b1d6b
@ -2878,7 +2878,7 @@ function ARTY:onafterCeaseFire(Controllable, From, Event, To, target)
|
||||
self.Controllable:ClearTasks()
|
||||
|
||||
else
|
||||
self:E(ARTY.id.."ERROR: No target in cease fire for group %s.", self.groupname)
|
||||
self:E(ARTY.id..string.format("ERROR: No target in cease fire for group %s.", self.groupname))
|
||||
end
|
||||
|
||||
-- Set number of shots to zero.
|
||||
|
||||
@ -73,7 +73,11 @@
|
||||
-- @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 Bullseye Case III intercept glideslope and follow ICLS aka "bullseye".
|
||||
-- @field #number case Recovery case I, II or III in progress.
|
||||
-- @field #number defaultcase Default recovery case. This is the case used if not specified otherwise.
|
||||
-- @field #number case Recovery case I, II or III currently in progress.
|
||||
-- @field #table recoverytimes List of time windows when aircraft are recovered including the recovery case and holding offset.
|
||||
-- @field #number defaultoffset Default holding pattern update if not specified otherwise.
|
||||
-- @field #number holdingoffset Offset [degrees] of Case II/III holding pattern.
|
||||
-- @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.
|
||||
@ -82,8 +86,6 @@
|
||||
-- @field #number Nmaxpattern Max number of aircraft in landing pattern.
|
||||
-- @field Ops.RecoveryTanker#RECOVERYTANKER tanker Recovery tanker flying overhead of carrier.
|
||||
-- @field Functional.Warehouse#WAREHOUSE warehouse Warehouse object of the carrier.
|
||||
-- @field #table recoverytimes List of time windows when aircraft are recovered including the recovery case.
|
||||
-- @field #number holdingoffset Offset [degrees] of Case II/III holding pattern. Default 0 degrees.
|
||||
-- @extends Core.Fsm#FSM
|
||||
|
||||
--- The boss!
|
||||
@ -163,7 +165,11 @@ AIRBOSS = {
|
||||
Platform = {},
|
||||
DirtyUp = {},
|
||||
Bullseye = {},
|
||||
case = 1,
|
||||
defaultcase = nil,
|
||||
case = nil,
|
||||
defaultoffset = nil,
|
||||
holdingoffset = nil,
|
||||
recoverytimes = {},
|
||||
flights = {},
|
||||
Qpattern = {},
|
||||
Qmarshal = {},
|
||||
@ -172,8 +178,6 @@ AIRBOSS = {
|
||||
Nmaxpattern = nil,
|
||||
tanker = nil,
|
||||
warehouse = nil,
|
||||
recoverytimes = {},
|
||||
holdingoffset = nil,
|
||||
}
|
||||
|
||||
--- Player aircraft types capable of landing on carriers.
|
||||
@ -235,9 +239,9 @@ AIRBOSS.CarrierType={
|
||||
-- @type AIRBOSS.AircraftAoA
|
||||
-- @field #number OnSpeedMin Minimum on speed AoA. Values below are fast
|
||||
-- @field #number OnSpeedMax Maximum on speed AoA. Values above are slow.
|
||||
-- @field #number OnSpeed Optimal AoA.
|
||||
-- @field #number OnSpeed Optimal on-speed AoA.
|
||||
-- @field #number Fast Fast AoA threshold. Smaller means faster.
|
||||
-- @field #number Slow Slow AoA threshold. Larger means slower
|
||||
-- @field #number Slow Slow AoA threshold. Larger means slower.
|
||||
|
||||
--- Pattern steps.
|
||||
-- @type AIRBOSS.PatternStep
|
||||
@ -270,7 +274,7 @@ AIRBOSS.PatternStep={
|
||||
}
|
||||
|
||||
--- Radio sound file and subtitle.
|
||||
-- @type AIRBOSS.RadioSound
|
||||
-- @type AIRBOSS.RadioCall
|
||||
-- @field #string file Sound file name without suffix.
|
||||
-- @field #string suffix File suffix/extention, e.g. "ogg".
|
||||
-- @field #boolean loud Loud version of sound file available.
|
||||
@ -279,31 +283,39 @@ AIRBOSS.PatternStep={
|
||||
|
||||
--- LSO radio calls.
|
||||
-- @type AIRBOSS.LSOCall
|
||||
-- @field #AIRBOSS.RadioSound RIGHTFORLINEUP "Right for line up" call.
|
||||
-- @field #AIRBOSS.RadioSound COMELEFT "Come left" call.
|
||||
-- @field #AIRBOSS.RadioSound HIGH "You're high" call.
|
||||
-- @field #AIRBOSS.RadioSound LOW "You're low" call.
|
||||
-- @field #AIRBOSS.RadioSound POWER "Power" call.
|
||||
-- @field #AIRBOSS.RadioSound FAST "You're fast" call.
|
||||
-- @field #AIRBOSS.RadioSound SLOW "You're slow" call.
|
||||
-- @field #AIRBOSS.RadioSound PADDLESCONTACT "Paddles, contact" call.
|
||||
-- @field #AIRBOSS.RadioSound CALLTHEBALL "Call the Ball"
|
||||
-- @field #AIRBOSS.RadioSound ROGERBALL "Roger ball" call.
|
||||
-- @field #AIRBOSS.RadioSound WAVEOFF "Wafe off" call
|
||||
-- @field #AIRBOSS.RadioSound BOLTER "Bolter, Bolter" call
|
||||
-- @field #AIRBOSS.RadioSound LONGINGROOVE "You're long in the groove. Depart and re-enter." call.
|
||||
-- @field #AIRBOSS.RadioSound DEPARTANDREENTER "Depart and re-enter" call.
|
||||
-- @field #AIRBOSS.RadioSound N1 "One" call.
|
||||
-- @field #AIRBOSS.RadioSound N2 "Two" call.
|
||||
-- @field #AIRBOSS.RadioSound N3 "Three" call.
|
||||
-- @field #AIRBOSS.RadioSound N4 "Four" call.
|
||||
-- @field #AIRBOSS.RadioSound N5 "Five" call.
|
||||
-- @field #AIRBOSS.RadioSound N6 "Six" call.
|
||||
-- @field #AIRBOSS.RadioSound N7 "Seven" call.
|
||||
-- @field #AIRBOSS.RadioSound N8 "Eight" call.
|
||||
-- @field #AIRBOSS.RadioSound N9 "Nine" call.
|
||||
-- @field #AIRBOSS.RadioSound N0 "Zero" call.
|
||||
-- @field #AIRBOSS.RadioCall RADIOCHECK "Paddles, radio check" call.
|
||||
-- @field #AIRBOSS.RadioCall RIGHTFORLINEUP "Right for line up" call.
|
||||
-- @field #AIRBOSS.RadioCall COMELEFT "Come left" call.
|
||||
-- @field #AIRBOSS.RadioCall HIGH "You're high" call.
|
||||
-- @field #AIRBOSS.RadioCall LOW "You're low" call.
|
||||
-- @field #AIRBOSS.RadioCall POWER "Power" call.
|
||||
-- @field #AIRBOSS.RadioCall FAST "You're fast" call.
|
||||
-- @field #AIRBOSS.RadioCall SLOW "You're slow" call.
|
||||
-- @field #AIRBOSS.RadioCall PADDLESCONTACT "Paddles, contact" call.
|
||||
-- @field #AIRBOSS.RadioCall CALLTHEBALL "Call the Ball"
|
||||
-- @field #AIRBOSS.RadioCall ROGERBALL "Roger ball" call.
|
||||
-- @field #AIRBOSS.RadioCall WAVEOFF "Wafe off" call
|
||||
-- @field #AIRBOSS.RadioCall BOLTER "Bolter, Bolter" call
|
||||
-- @field #AIRBOSS.RadioCall LONGINGROOVE "You're long in the groove. Depart and re-enter." call.
|
||||
-- @field #AIRBOSS.RadioCall DEPARTANDREENTER "Depart and re-enter" call.
|
||||
-- @field #AIRBOSS.RadioCall N0 "Zero" call.
|
||||
-- @field #AIRBOSS.RadioCall N1 "One" call.
|
||||
-- @field #AIRBOSS.RadioCall N2 "Two" call.
|
||||
-- @field #AIRBOSS.RadioCall N3 "Three" call.
|
||||
-- @field #AIRBOSS.RadioCall N4 "Four" call.
|
||||
-- @field #AIRBOSS.RadioCall N5 "Five" call.
|
||||
-- @field #AIRBOSS.RadioCall N6 "Six" call.
|
||||
-- @field #AIRBOSS.RadioCall N7 "Seven" call.
|
||||
-- @field #AIRBOSS.RadioCall N8 "Eight" call.
|
||||
-- @field #AIRBOSS.RadioCall N9 "Nine" call.
|
||||
AIRBOSS.LSOCall={
|
||||
RADIOCHECK={
|
||||
file="LSO-RadioCheck",
|
||||
suffix="ogg",
|
||||
louder=false,
|
||||
subtitle="Paddles, radio check",
|
||||
duration=1.1,
|
||||
},
|
||||
RIGHTFORLINEUP={
|
||||
file="LSO-RightForLineup",
|
||||
suffix="ogg",
|
||||
@ -402,13 +414,6 @@ AIRBOSS.LSOCall={
|
||||
subtitle="Paddles, contact",
|
||||
duration=1.0,
|
||||
},
|
||||
RADIOCHECK={
|
||||
file="LSO-RadioCheck",
|
||||
suffix="ogg",
|
||||
louder=false,
|
||||
subtitle="Paddles, radio check",
|
||||
duration=1.1,
|
||||
},
|
||||
N0={
|
||||
file="LSO-N0",
|
||||
suffix="ogg",
|
||||
@ -483,16 +488,17 @@ AIRBOSS.LSOCall={
|
||||
|
||||
--- Marshal radio calls.
|
||||
-- @type AIRBOSS.MarshalCall
|
||||
-- @field #AIRBOSS.RadioSound N1 "One" call.
|
||||
-- @field #AIRBOSS.RadioSound N2 "Two" call.
|
||||
-- @field #AIRBOSS.RadioSound N3 "Three" call.
|
||||
-- @field #AIRBOSS.RadioSound N4 "Four" call.
|
||||
-- @field #AIRBOSS.RadioSound N5 "Five" call.
|
||||
-- @field #AIRBOSS.RadioSound N6 "Six" call.
|
||||
-- @field #AIRBOSS.RadioSound N7 "Seven" call.
|
||||
-- @field #AIRBOSS.RadioSound N8 "Eight" call.
|
||||
-- @field #AIRBOSS.RadioSound N9 "Nine" call.
|
||||
-- @field #AIRBOSS.RadioSound N0 "Zero" call.
|
||||
-- @field #AIRBOSS.RadioCall RADIOCHECK "Marshal, radio check" call.
|
||||
-- @field #AIRBOSS.RadioCall N0 "Zero" call.
|
||||
-- @field #AIRBOSS.RadioCall N1 "One" call.
|
||||
-- @field #AIRBOSS.RadioCall N2 "Two" call.
|
||||
-- @field #AIRBOSS.RadioCall N3 "Three" call.
|
||||
-- @field #AIRBOSS.RadioCall N4 "Four" call.
|
||||
-- @field #AIRBOSS.RadioCall N5 "Five" call.
|
||||
-- @field #AIRBOSS.RadioCall N6 "Six" call.
|
||||
-- @field #AIRBOSS.RadioCall N7 "Seven" call.
|
||||
-- @field #AIRBOSS.RadioCall N8 "Eight" call.
|
||||
-- @field #AIRBOSS.RadioCall N9 "Nine" call.
|
||||
AIRBOSS.MarshalCall={
|
||||
RADIOCHECK={
|
||||
file="MARSHAL-RadioCheck",
|
||||
@ -585,11 +591,12 @@ AIRBOSS.Difficulty={
|
||||
HARD="TOPGUN Graduate",
|
||||
}
|
||||
|
||||
--- Recovery time.
|
||||
--- Recovery window parameters.
|
||||
-- @type AIRBOSS.Recovery
|
||||
-- @field #number START Start of recovery in seconds of abs time.
|
||||
-- @field #number STOP End of recovery in seconds of abs time.
|
||||
-- @field #number CASE Recovery case (1-3) of that time slot.
|
||||
-- @field #number OFFSET Angle offset of the holding pattern in degrees. Usually 0, +-15, or +-30 degrees.
|
||||
|
||||
--- Groove position.
|
||||
-- @type AIRBOSS.GroovePos
|
||||
@ -641,11 +648,6 @@ AIRBOSS.GroovePos={
|
||||
-- @field #number LimitXmax Latitudal threshold for triggering the next step if X>Xmax.
|
||||
-- @field #number LimitZmin Latitudal threshold for triggering the next step if Z<Zmin.
|
||||
-- @field #number LimitZmax Latitudal threshold for triggering the next step if Z>Zmax.
|
||||
-- @field #number Altitude Optimal altitude at this point.
|
||||
-- @field #number AoA Optimal AoA at this point.
|
||||
-- @field #number Distance Optimal distance at this point.
|
||||
-- @field #number Speed Optimal speed at this point.
|
||||
-- @field #table Checklist Table of checklist text items to display at this point.
|
||||
|
||||
--- Parameters of a flight group.
|
||||
-- @type AIRBOSS.Flightitem
|
||||
@ -694,7 +696,7 @@ AIRBOSS.MenuF10={}
|
||||
|
||||
--- Airboss class version.
|
||||
-- @field #string version
|
||||
AIRBOSS.version="0.4.8"
|
||||
AIRBOSS.version="0.4.8w"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- TODO list
|
||||
@ -706,7 +708,7 @@ AIRBOSS.version="0.4.8"
|
||||
-- TODO: Option to turn AI handling off.
|
||||
-- TODO: Check distance to players during approach. PWO if too close.
|
||||
-- TODO: Spin pattern. Add radio menu entry. Not sure what to add though?!
|
||||
-- TODO: Add radio check (LSO, AIRBOSS) to F10 radio menu.
|
||||
-- DONE: Add radio check (LSO, AIRBOSS) to F10 radio menu.
|
||||
-- TODO: Add user functions.
|
||||
-- TODO: Generalize parameters for other carriers.
|
||||
-- TODO: Generalize parameters for other aircraft.
|
||||
@ -799,11 +801,11 @@ function AIRBOSS:New(carriername, alias)
|
||||
-- Set max aircraft in landing pattern.
|
||||
self:SetMaxLandingPattern(2)
|
||||
|
||||
-- Set holding offset to 0 degrees.
|
||||
self:SetHoldingOffsetAngle(15)
|
||||
|
||||
-- Default recovery case.
|
||||
-- Default recovery case. This sets self.defaultcase and self.case.
|
||||
self:SetRecoveryCase(1)
|
||||
|
||||
-- Set holding offset to 0 degrees. This set self.defaultoffset and self.holdingoffset.
|
||||
self:SetHoldingOffsetAngle(15)
|
||||
|
||||
-- CCA 50 NM radius zone around the carrier.
|
||||
self:SetCarrierControlledArea()
|
||||
@ -845,7 +847,7 @@ function AIRBOSS:New(carriername, alias)
|
||||
--[[
|
||||
-- Init default sound files.
|
||||
for _name,_sound in pairs(AIRBOSS.LSOCall) do
|
||||
local sound=_sound --#AIRBOSS.RadioSound
|
||||
local sound=_sound --#AIRBOSS.RadioCall
|
||||
local text=string.format()
|
||||
sound.subtitle=1
|
||||
sound.louder=1
|
||||
@ -901,12 +903,14 @@ function AIRBOSS:New(carriername, alias)
|
||||
-- @function [parent=#AIRBOSS] RecoveryStart
|
||||
-- @param #AIRBOSS self
|
||||
-- @param #number Case Recovery case (1, 2 or 3) that is started.
|
||||
-- @param #number Offset Holding pattern offset angle in degrees for CASE II/III recoveries.
|
||||
|
||||
--- Triggers the FSM delayed event "RecoveryStart" that starts the recovery of aircraft. Marshalling aircraft are send to the landing pattern.
|
||||
-- @function [parent=#AIRBOSS] __RecoveryStart
|
||||
-- @param #number delay Delay in seconds.
|
||||
-- @param #AIRBOSS self
|
||||
-- @param #number Case Recovery case (1, 2 or 3) that is started.
|
||||
-- @param #number delay Delay in seconds.
|
||||
-- @param #number Offset Holding pattern offset angle in degrees for CASE II/III recoveries.
|
||||
|
||||
|
||||
--- Triggers the FSM event "RecoveryStop" that stops the recovery of aircraft.
|
||||
@ -923,12 +927,14 @@ function AIRBOSS:New(carriername, alias)
|
||||
-- @function [parent=#AIRBOSS] RecoveryCase
|
||||
-- @param #AIRBOSS self
|
||||
-- @param #number Case The new recovery case (1, 2 or 3).
|
||||
-- @param #number Offset Holding pattern offset angle in degrees for CASE II/III recoveries.
|
||||
|
||||
--- Triggers the delayed FSM event "RecoveryCase" that sets the used aircraft recovery case.
|
||||
-- @function [parent=#AIRBOSS] __Case
|
||||
-- @param #AIRBOSS self
|
||||
-- @param #number delay Delay in seconds.
|
||||
-- @param #number Case The new recovery case (1, 2 or 3).
|
||||
-- @param #number Offset Holding pattern offset angle in degrees for CASE II/III recoveries.
|
||||
|
||||
|
||||
--- Triggers the FSM event "Stop" that stops the airboss. Event handlers are stopped.
|
||||
@ -975,14 +981,16 @@ function AIRBOSS:SetCarrierControlledZone(radius)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set recovery case pattern.
|
||||
--- Set the default recovery case.
|
||||
-- @param #AIRBOSS self
|
||||
-- @param #number case Case of recovery. Either 1 or 3. Default 1.
|
||||
-- @param #number case Case of recovery. Either 1, 2 or 3. Default 1.
|
||||
-- @return #AIRBOSS self
|
||||
function AIRBOSS:SetRecoveryCase(case)
|
||||
|
||||
self.case=case or 1
|
||||
|
||||
self.defaultcase=case or 1
|
||||
|
||||
self.case=self.defaultcase
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
@ -993,8 +1001,11 @@ end
|
||||
-- @return #AIRBOSS self
|
||||
function AIRBOSS:SetHoldingOffsetAngle(offset)
|
||||
|
||||
self.holdingoffset=offset or 0
|
||||
|
||||
self.defaultoffset=offset or 0
|
||||
|
||||
self.holdingoffset=self.defaultoffset
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
@ -1002,9 +1013,10 @@ end
|
||||
-- @param #AIRBOSS self
|
||||
-- @param #string starttime Start time, e.g. "8:00" for eight o'clock. Default now.
|
||||
-- @param #string stoptime Stop time, e.g. "9:00" for nine o'clock. Default 90 minutes after start time.
|
||||
-- @param #number case Recovery case for that time slot. Number between one and three. Default 1.
|
||||
-- @param #number case Recovery case for that time slot. Number between one and three.
|
||||
-- @param #number holdingoffset Only for CASE II/III: Angle in degrees the holding pattern is offset.
|
||||
-- @return #AIRBOSS self
|
||||
function AIRBOSS:AddRecoveryTime(starttime, stoptime, case)
|
||||
function AIRBOSS:AddRecoveryTime(starttime, stoptime, case, holdingoffset)
|
||||
|
||||
-- Set start time.
|
||||
local Tstart=UTILS.ClockToSeconds(starttime or UTILS.SecondsToClock(timer.getAbsTime()))
|
||||
@ -1018,17 +1030,22 @@ function AIRBOSS:AddRecoveryTime(starttime, stoptime, case)
|
||||
return self
|
||||
end
|
||||
|
||||
-- Default is Case 1 recovery.
|
||||
case=case or 1
|
||||
-- Case or default value.
|
||||
case=case or self.defaultcase
|
||||
|
||||
-- Holding offset or default value.
|
||||
holdingoffset=holdingoffset or self.defaultoffset
|
||||
|
||||
|
||||
-- Recovery window.
|
||||
local rtime={} --#AIRBOSS.Recovery
|
||||
rtime.START=Tstart
|
||||
rtime.STOP=Tstop
|
||||
rtime.CASE=case
|
||||
local recovery={} --#AIRBOSS.Recovery
|
||||
recovery.START=Tstart
|
||||
recovery.STOP=Tstop
|
||||
recovery.CASE=case
|
||||
recovery.OFFSET=holdingoffset
|
||||
|
||||
-- Add to table
|
||||
table.insert(self.recoverytimes, rtime)
|
||||
table.insert(self.recoverytimes, recovery)
|
||||
|
||||
return self
|
||||
end
|
||||
@ -1066,7 +1083,7 @@ end
|
||||
--- Set ICLS channel of carrier.
|
||||
-- @param #AIRBOSS self
|
||||
-- @param #number channel ICLS channel. Default 1.
|
||||
-- @param #string morsecode Morse code identifier. Three letters, e.g. "STN".
|
||||
-- @param #string morsecode Morse code identifier. Three letters, e.g. "STN". Default "STN".
|
||||
-- @return #AIRBOSS self
|
||||
function AIRBOSS:SetICLS(channel, morsecode)
|
||||
|
||||
@ -1262,6 +1279,13 @@ function AIRBOSS:_CheckRecoveryTimes()
|
||||
text=" none!"
|
||||
end
|
||||
|
||||
-- Sort windows wrt to start time.
|
||||
local _sort=function(a, b) return a.START<b.START end
|
||||
table.sort(self.recoverytimes,_sort)
|
||||
|
||||
-- Next recovery case in the future.
|
||||
local nextwindow=nil --#AIRBOSS.Recovery
|
||||
|
||||
-- Loop over all slots.
|
||||
for _,_recovery in pairs(self.recoverytimes) do
|
||||
local recovery=_recovery --#AIRBOSS.Recovery
|
||||
@ -1307,14 +1331,34 @@ function AIRBOSS:_CheckRecoveryTimes()
|
||||
else
|
||||
-- This recovery is in the future.
|
||||
state="in the future"
|
||||
|
||||
-- This is the next to come.
|
||||
if nextwindow==nil then
|
||||
nextwindow=recovery
|
||||
state="next to come"
|
||||
end
|
||||
end
|
||||
|
||||
-- Debug text.
|
||||
text=text..string.format("\n- Start=%s Stop=%s Case=%d Status=\"%s\"", Cstart, Cstop, recovery.CASE, state)
|
||||
text=text..string.format("\n- Start=%s Stop=%s Case=%d Offset=%d Status=\"%s\"", Cstart, Cstop, recovery.CASE, recovery.OFFSET, state)
|
||||
end
|
||||
|
||||
-- Debug output.
|
||||
self:I(self.lid..text)
|
||||
|
||||
-- Carrier is idle. We need to make sure that incoming flights get the correct recovery info of the next window.
|
||||
if self:IsIdle() then
|
||||
-- Check if there is a next windows defined.
|
||||
if nextwindow then
|
||||
-- Set case and offset of the next window.
|
||||
self.case=nextwindow.CASE
|
||||
self.holdingoffset=nextwindow.OFFSET
|
||||
else
|
||||
-- No next window. Set default values.
|
||||
self.case=self.defaultcase
|
||||
self.holdingoffset=self.defaultoffset
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@ -1324,13 +1368,28 @@ end
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param #number Case The recovery case (1, 2 or 3) to switch to.
|
||||
function AIRBOSS:onafterRecoveryCase(From, Event, To, Case)
|
||||
-- @param #number Offset Holding pattern offset angle in degrees for CASE II/III recoveries.
|
||||
function AIRBOSS:onafterRecoveryCase(From, Event, To, Case, Offset)
|
||||
|
||||
-- Input or default value.
|
||||
Case=Case or self.defaultcase
|
||||
|
||||
-- Input or default value
|
||||
Offset=Offset or self.defaultoffset
|
||||
|
||||
-- Debug output.
|
||||
self:I(self.lid..string.format("Switching to recovery case %d.", Case))
|
||||
local text=string.format("Switching to recovery case %d.", Case)
|
||||
if Case>1 then
|
||||
text=text..string.format(" Holding offset angle %d degrees.", Offset)
|
||||
end
|
||||
MESSAGE:New(text, 20, self.alias):ToAllIf(self.Debug)
|
||||
self:I(self.lid..text)
|
||||
|
||||
-- Set new recovery case.
|
||||
self.case=Case
|
||||
|
||||
-- Set holding offset.
|
||||
self.holdingoffset=Offset
|
||||
end
|
||||
|
||||
--- On after "RecoveryStart" event. Recovery of aircraft is started and carrier switches to state "Recovering".
|
||||
@ -1339,14 +1398,26 @@ end
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param #number Case The recovery case (1, 2 or 3) to start.
|
||||
function AIRBOSS:onafterRecoveryStart(From, Event, To, Case)
|
||||
-- @param #number Offset Holding pattern offset angle in degrees for CASE II/III recoveries.
|
||||
function AIRBOSS:onafterRecoveryStart(From, Event, To, Case, Offset)
|
||||
|
||||
-- Input or default value.
|
||||
Case=Case or self.defaultcase
|
||||
|
||||
-- Input or default value.
|
||||
Offset=Offset or self.defaultoffset
|
||||
|
||||
-- Debug output.
|
||||
self:I(self.lid..string.format("Starting aircraft recovery in case %d.", Case))
|
||||
local text=string.format("Starting aircraft recovery case %d.", Case)
|
||||
if Case>1 then
|
||||
text=text..string.format(" Holding offset angle %d degrees.", Offset)
|
||||
end
|
||||
MESSAGE:New(text, 20, self.alias):ToAllIf(self.Debug)
|
||||
self:I(self.lid..text)
|
||||
|
||||
-- Switch to case.
|
||||
self:RecoveryCase(Case)
|
||||
|
||||
self:RecoveryCase(Case, Offset)
|
||||
|
||||
end
|
||||
|
||||
--- On after "RecoveryStop" event. Recovery of aircraft is stopped and carrier switches to state "Idle".
|
||||
@ -1357,10 +1428,7 @@ end
|
||||
function AIRBOSS:onafterRecoveryStop(From, Event, To)
|
||||
|
||||
-- Debug output.
|
||||
self:I(self.lid..string.format("Stopping aircraft recovery."))
|
||||
|
||||
-- Switch to idle state.
|
||||
self:Idle()
|
||||
self:I(self.lid..string.format("Stopping aircraft recovery. Carrier goes to state idle."))
|
||||
|
||||
end
|
||||
|
||||
@ -1741,11 +1809,15 @@ function AIRBOSS:_CheckQueue()
|
||||
-- Time (last) flight has entered landing pattern.
|
||||
local Tpattern=9999
|
||||
local npunits=1
|
||||
local pcase=1
|
||||
if npattern>0 then
|
||||
|
||||
-- Last flight group send to pattern.
|
||||
local patternflight=self.Qpattern[#self.Qpattern] --#AIRBOSS.Flightitem
|
||||
|
||||
-- Recovery case of pattern flight.
|
||||
pcase=patternflight.case
|
||||
|
||||
-- Number of aircraft in this group.
|
||||
local npunits=patternflight.nunits
|
||||
|
||||
@ -1756,7 +1828,7 @@ function AIRBOSS:_CheckQueue()
|
||||
|
||||
-- Min time in pattern before next aircraft is allowed.
|
||||
local TpatternMin
|
||||
if self.case==1 then
|
||||
if pcase==1 then
|
||||
TpatternMin=45*npunits -- 45 seconds interval per plane!
|
||||
else
|
||||
TpatternMin=120*npunits -- 120 seconds interval per plane!
|
||||
@ -1781,6 +1853,7 @@ function AIRBOSS:_ScanCarrierZone()
|
||||
-- Carrier position.
|
||||
local coord=self:GetCoordinate()
|
||||
|
||||
-- Scan radius.
|
||||
local Rout=UTILS.NMToMeters(50)
|
||||
|
||||
-- Scan units in carrier zone.
|
||||
@ -1890,12 +1963,9 @@ function AIRBOSS:_MarshalPlayer(playerData)
|
||||
|
||||
-- Check if flight is known to the airboss already.
|
||||
if playerData 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
|
||||
|
||||
-- Get free stack.
|
||||
local mystack=self:_GetFreeStack(self.case)
|
||||
|
||||
-- Add group to marshal stack.
|
||||
self:_AddMarshalGroup(playerData, mystack)
|
||||
@ -1963,13 +2033,15 @@ function AIRBOSS:_MarshalAI(flight, nstack)
|
||||
-- Set up waypoints including collapsing the stack.
|
||||
for stack=nstack, 1, -1 do
|
||||
|
||||
-- TODO: skip stack 6 if recoverytanker (or at whatever angels the tanker orbits).
|
||||
|
||||
-- Get altitude and positions.
|
||||
local Altitude, p1, p2=self:_GetMarshalAltitude(stack)
|
||||
|
||||
local p1=p1 --Core.Point#COORDINATE
|
||||
local Dist=p1:Get2DDistance(self:GetCoordinate())
|
||||
|
||||
-- Orbit task.
|
||||
-- Task: orbit at specified position, altitude and speed until flag=stack-1
|
||||
local TaskOrbit=_taskorbit(p1, Altitude, Speed, stack-1, p2)
|
||||
|
||||
-- Waypoint description.
|
||||
@ -1981,7 +2053,7 @@ function AIRBOSS:_MarshalAI(flight, nstack)
|
||||
end
|
||||
|
||||
-- Landing waypoint.
|
||||
wp[#wp+1]=Carrier:WaypointAirLanding(Speed, self.airbase, nil, "Landing")
|
||||
wp[#wp+1]=Carrier:SetAltitude(250):WaypointAirLanding(Speed, self.airbase, nil, "Landing")
|
||||
|
||||
-- Reinit waypoints.
|
||||
group:WayPointInitialize(wp)
|
||||
@ -2112,7 +2184,7 @@ function AIRBOSS:_CheckCollapseMarshalStack(flight)
|
||||
|
||||
-- Hint for easy skill.
|
||||
if playerData.difficulty==AIRBOSS.Difficulty.EASY then
|
||||
self:MessageToPlayer(flight, string.format("Use F10 radio menu \"Commence!\" command when you are ready!"), nil, "", 5)
|
||||
self:MessageToPlayer(flight, string.format("Use F10 radio menu \"Request Commence\" command when ready!"), nil, "", 5)
|
||||
end
|
||||
end
|
||||
|
||||
@ -2147,6 +2219,7 @@ function AIRBOSS:_CollapseMarshalStack(flight, nopattern)
|
||||
if stack>0 and mstack>stack then
|
||||
|
||||
-- Decrease stack/flag by one ==> AI will go lower.
|
||||
-- TODO: If we include the recovery tanker, this needs to be generalized.
|
||||
mflight.flag:Set(mstack-1)
|
||||
|
||||
-- Inform players.
|
||||
@ -2216,16 +2289,32 @@ function AIRBOSS:_GetFreeStack(case)
|
||||
case=case or self.case
|
||||
|
||||
-- Get stack
|
||||
local stack
|
||||
local nfull
|
||||
if case==1 then
|
||||
-- Lowest Case I stack.
|
||||
stack=self:_GetQueueInfo(self.Qmarshal, 1)
|
||||
nfull=self:_GetQueueInfo(self.Qmarshal, 1)
|
||||
else
|
||||
-- Lowest Case II or III stack.
|
||||
stack=self:_GetQueueInfo(self.Qmarshal, 23)
|
||||
nfull=self:_GetQueueInfo(self.Qmarshal, 23)
|
||||
end
|
||||
|
||||
return stack+1
|
||||
-- Get recovery tanker stack.
|
||||
local tankerstack=9999
|
||||
if self.tanker and case==1 then
|
||||
tankerstack=self:_GetAngels(self.tanker.altitude)
|
||||
end
|
||||
|
||||
local nfree
|
||||
if nfull<tankerstack-1 then
|
||||
-- Free stack is simply the next.
|
||||
nfree=nfull+1
|
||||
else
|
||||
-- Here one more because of the tanker.
|
||||
nfree=nfull+2
|
||||
end
|
||||
|
||||
|
||||
return nfree
|
||||
end
|
||||
|
||||
|
||||
@ -2356,7 +2445,7 @@ function AIRBOSS:_CreateFlightGroup(group)
|
||||
flight.seclead=flight.group:GetUnit(1):GetName() -- Sec lead is first unitname of group but player name for players.
|
||||
flight.section={}
|
||||
|
||||
-- Note, this should be set elsewhere.
|
||||
-- Note, this should be re-set elsewhere!
|
||||
flight.case=self.case
|
||||
|
||||
-- Onboard
|
||||
@ -3445,10 +3534,7 @@ function AIRBOSS:_Upwind(playerData)
|
||||
local hint=string.format("%s\n%s\n%s", playerData.step, hintAlt, hintSpeed)
|
||||
self:MessageToPlayer(playerData, hint, "MARSHAL", "")
|
||||
end
|
||||
|
||||
-- Debrief.
|
||||
--self:_AddToDebrief(playerData, debrief)
|
||||
|
||||
|
||||
-- Next step: Early Break.
|
||||
playerData.step=AIRBOSS.PatternStep.EARLYBREAK
|
||||
playerData.warning=nil
|
||||
@ -4749,20 +4835,26 @@ function AIRBOSS:_LSOadvice(playerData, glideslopeError, lineupError)
|
||||
-- Player group.
|
||||
local player=playerData.unit:GetGroup()
|
||||
|
||||
local advice=0
|
||||
|
||||
-- Glideslope high/low calls.
|
||||
local text=""
|
||||
if glideslopeError>1 then
|
||||
-- "You're high!"
|
||||
self:RadioTransmission(self.LSOradio, AIRBOSS.LSOCall.HIGH, true)
|
||||
advice=advice+AIRBOSS.LSOCall.HIGH.duration
|
||||
elseif glideslopeError>0.5 then
|
||||
-- "You're a little high."
|
||||
self:RadioTransmission(self.LSOradio, AIRBOSS.LSOCall.HIGH, false)
|
||||
advice=advice+AIRBOSS.LSOCall.HIGH.duration
|
||||
elseif glideslopeError<-1.0 then
|
||||
-- "Power!"
|
||||
self:RadioTransmission(self.LSOradio, AIRBOSS.LSOCall.POWER, true)
|
||||
advice=advice+AIRBOSS.LSOCall.POWER.duration
|
||||
elseif glideslopeError<-0.5 then
|
||||
-- "You're a little low."
|
||||
self:RadioTransmission(self.LSOradio, AIRBOSS.LSOCall.POWER, false)
|
||||
advice=advice+AIRBOSS.LSOCall.POWER.duration
|
||||
else
|
||||
text="Good altitude."
|
||||
end
|
||||
@ -4774,15 +4866,19 @@ function AIRBOSS:_LSOadvice(playerData, glideslopeError, lineupError)
|
||||
if lineupError<-3 then
|
||||
-- "Come left!"
|
||||
self:RadioTransmission(self.LSOradio, AIRBOSS.LSOCall.COMELEFT, true)
|
||||
advice=advice+AIRBOSS.LSOCall.COMELEFT.duration
|
||||
elseif lineupError<-1 then
|
||||
-- "Come left."
|
||||
self:RadioTransmission(self.LSOradio, AIRBOSS.LSOCall.COMELEFT, false)
|
||||
self:RadioTransmission(self.LSOradio, AIRBOSS.LSOCall.COMELEFT, false)
|
||||
advice=advice+AIRBOSS.LSOCall.COMELEFT.duration
|
||||
elseif lineupError>3 then
|
||||
-- "Right for lineup!"
|
||||
self:RadioTransmission(self.LSOradio, AIRBOSS.LSOCall.RIGHTFORLINEUP, true)
|
||||
self:RadioTransmission(self.LSOradio, AIRBOSS.LSOCall.RIGHTFORLINEUP, true)
|
||||
advice=advice+AIRBOSS.LSOCall.RIGHTFORLINEUP.duration
|
||||
elseif lineupError>1 then
|
||||
-- "Right for lineup."
|
||||
self:RadioTransmission(self.LSOradio, AIRBOSS.LSOCall.RIGHTFORLINEUP, false)
|
||||
advice=advice+AIRBOSS.LSOCall.RIGHTFORLINEUP.duration
|
||||
else
|
||||
text=text.."Good lineup."
|
||||
end
|
||||
@ -4798,18 +4894,22 @@ function AIRBOSS:_LSOadvice(playerData, glideslopeError, lineupError)
|
||||
-- Rate aoa.
|
||||
if aoa>=aircraftaoa.Slow then
|
||||
-- "Your're slow!"
|
||||
self:RadioTransmission(self.LSOradio, AIRBOSS.LSOCall.SLOW, true)
|
||||
self:RadioTransmission(self.LSOradio, AIRBOSS.LSOCall.SLOW, true)
|
||||
advice=advice+AIRBOSS.LSOCall.SLOW.duration
|
||||
elseif aoa>=aircraftaoa.OnSpeedMax and aoa<aircraftaoa.Slow then
|
||||
-- "Your're a little slow."
|
||||
self:RadioTransmission(self.LSOradio, AIRBOSS.LSOCall.SLOW, false)
|
||||
self:RadioTransmission(self.LSOradio, AIRBOSS.LSOCall.SLOW, false)
|
||||
advice=advice+AIRBOSS.LSOCall.SLOW.duration
|
||||
elseif aoa>=aircraftaoa.OnSpeedMin and aoa<aircraftaoa.OnSpeedMax then
|
||||
text=text.."You're on speed."
|
||||
elseif aoa>=aircraftaoa.Fast and aoa<aircraftaoa.OnSpeedMin then
|
||||
-- "You're a little fast."
|
||||
self:RadioTransmission(self.LSOradio, AIRBOSS.LSOCall.FAST, false)
|
||||
advice=advice+AIRBOSS.LSOCall.FAST.duration
|
||||
elseif aoa<aircraftaoa.Fast then
|
||||
-- "You're fast!"
|
||||
self:RadioTransmission(self.LSOradio, AIRBOSS.LSOCall.FAST, true)
|
||||
self:RadioTransmission(self.LSOradio, AIRBOSS.LSOCall.FAST, true)
|
||||
advice=advice+AIRBOSS.LSOCall.FAST.duration
|
||||
else
|
||||
text=text.."Unknown AoA state."
|
||||
end
|
||||
@ -4818,7 +4918,7 @@ function AIRBOSS:_LSOadvice(playerData, glideslopeError, lineupError)
|
||||
text=text..string.format(" AoA = %.1f", aoa)
|
||||
|
||||
-- Set last time.
|
||||
playerData.Tlso=timer.getTime()
|
||||
playerData.Tlso=timer.getTime()
|
||||
end
|
||||
|
||||
--- Grade approach.
|
||||
@ -5209,7 +5309,7 @@ function AIRBOSS:_AltitudeCheck(playerData, altopt)
|
||||
-- Altitude error +-X%
|
||||
local _error=(altitude-altopt)/altopt*100
|
||||
|
||||
local radiocall={} --#AIRBOSS.RadioSound
|
||||
local radiocall={} --#AIRBOSS.RadioCall
|
||||
|
||||
local hint
|
||||
if _error>badscore then
|
||||
@ -5613,15 +5713,13 @@ function AIRBOSS:_GetFuelState(unit)
|
||||
return UTILS.kg2lbs(fuelstate)
|
||||
end
|
||||
|
||||
--- Get altitude in angels.
|
||||
--- Convert altitude from meters to angels (thousands of feet).
|
||||
-- @param #AIRBOSS self
|
||||
-- @param Wrapper.Unit#UNIT unit The unit for which the mass is determined.
|
||||
-- @return #number Altitude of unit in Anglels = thouthands of feet.
|
||||
function AIRBOSS:_GetAngels(unit)
|
||||
-- @param alt Alitude in meters.
|
||||
-- @return #number Altitude in Anglels = thousands of feet using math.floor().
|
||||
function AIRBOSS:_GetAngels(alt)
|
||||
|
||||
local alt=unit:GetAltitude()
|
||||
|
||||
local angels=math.floor(UTILS.MetersToFeet(alt))/1000
|
||||
local angels=math.floor(UTILS.MetersToFeet(alt)/1000)
|
||||
|
||||
return angels
|
||||
end
|
||||
@ -5777,7 +5875,7 @@ end
|
||||
-- @field #number prio Priority 0-100.
|
||||
-- @field #boolean isplaying Currently playing.
|
||||
-- @field Core.Beacon#RADIO radio Radio object.
|
||||
-- @field #AIRBOSS.RadioSound call Radio sound.
|
||||
-- @field #AIRBOSS.RadioCall call Radio sound.
|
||||
|
||||
--- Check radio queue for transmissions to be broadcasted.
|
||||
-- @param #AIRBOSS self
|
||||
@ -5862,7 +5960,7 @@ end
|
||||
--- Add Radio transmission to radio queue
|
||||
-- @param #AIRBOSS self
|
||||
-- @param Core.Radio#RADIO radio sending transmission.
|
||||
-- @param #AIRBOSS.RadioSound call Radio sound files and subtitles.
|
||||
-- @param #AIRBOSS.RadioCall call Radio sound files and subtitles.
|
||||
-- @param #boolean loud If true, play loud sound file version.
|
||||
-- @param #number delay Delay in seconds, before the message is broadcasted.
|
||||
function AIRBOSS:RadioTransmission(radio, call, loud, delay)
|
||||
@ -5893,7 +5991,7 @@ end
|
||||
--- Transmission radio message.
|
||||
-- @param #AIRBOSS self
|
||||
-- @param Core.Radio#RADIO radio sending transmission.
|
||||
-- @param #AIRBOSS.RadioSound call Radio sound files and subtitles.
|
||||
-- @param #AIRBOSS.RadioCall call Radio sound files and subtitles.
|
||||
-- @param #boolean loud If true, play loud sound file version.
|
||||
-- @param #number delay Delay in seconds, before the message is broadcasted.
|
||||
function AIRBOSS:RadioTransmit(radio, call, loud, delay)
|
||||
|
||||
@ -36,7 +36,8 @@
|
||||
-- @field #number distStern Race-track distance astern.
|
||||
-- @field #number distBow Race-track distance bow.
|
||||
-- @field #number Dupdate Pattern update when carrier changes its position by more than this distance (meters).
|
||||
-- @field #number Hupdate Pattern update when carrier changes its heading by more than this number (degrees).
|
||||
-- @field #number Hupdate Pattern update when carrier changes its heading by more than this number (degrees).
|
||||
-- @field #boolean turning If true, carrier is turning.
|
||||
-- @field #number dTupdate Minimum time interval in seconds before the next pattern update can happen.
|
||||
-- @field #number Tupdate Last time the pattern was updated.
|
||||
-- @field #number takeoff Takeoff type (cold, hot, air).
|
||||
@ -45,6 +46,7 @@
|
||||
-- @field #boolean respawninair If true, tanker will always be respawned in air. This has no impact on the initial spawn setting.
|
||||
-- @field #boolean uncontrolledac If true, use and uncontrolled tanker group already present in the mission.
|
||||
-- @field DCS#Vec3 orientation Orientation of the carrier. Used to monitor changes and update the pattern if heading changes significantly.
|
||||
-- @field DCS#Vec3 orientlast Orientation of the carrier for checking if carrier is currently turning.
|
||||
-- @field Core.Point#COORDINATE position Positon of carrier. Used to monitor if carrier significantly changed its position and then update the tanker pattern.
|
||||
-- @field Core.Zone#ZONE_UNIT zoneUpdate Moving zone relative to carrier. Each time the tanker is in this zone, its pattern is updated.
|
||||
-- @extends Core.Fsm#FSM
|
||||
@ -197,6 +199,7 @@ RECOVERYTANKER = {
|
||||
dTupdate = nil,
|
||||
Dupdate = nil,
|
||||
Hupdate = nil,
|
||||
turning = nil,
|
||||
Tupdate = nil,
|
||||
takeoff = nil,
|
||||
lowfuel = nil,
|
||||
@ -204,13 +207,14 @@ RECOVERYTANKER = {
|
||||
respawninair = nil,
|
||||
uncontrolledac = nil,
|
||||
orientation = nil,
|
||||
orientlast = nil,
|
||||
position = nil,
|
||||
zoneUpdate = nil,
|
||||
}
|
||||
|
||||
--- Class version.
|
||||
-- @field #string version
|
||||
RECOVERYTANKER.version="0.9.6"
|
||||
RECOVERYTANKER.version="0.9.6w"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- TODO list
|
||||
@ -274,7 +278,7 @@ function RECOVERYTANKER:New(carrierunit, tankergroupname)
|
||||
-- Moving zone: Zone 1 NM astern the carrier with radius of 1 NM.
|
||||
self.zoneUpdate=ZONE_UNIT:New("Pattern Update Zone", self.carrier, UTILS.NMToMeters(1), {dx=-UTILS.NMToMeters(1), dy=0, relative_to_unit=true})
|
||||
|
||||
self.zoneUpdate:SmokeZone(SMOKECOLOR.White, 45)
|
||||
--self.zoneUpdate:SmokeZone(SMOKECOLOR.White, 45)
|
||||
|
||||
-----------------------
|
||||
--- FSM Transitions ---
|
||||
@ -691,7 +695,9 @@ function RECOVERYTANKER:onafterStart(From, Event, To)
|
||||
|
||||
-- Get initial orientation and position of carrier.
|
||||
self.orientation=self.carrier:GetOrientationX()
|
||||
self.orientlast=self.carrier:GetOrientationX()
|
||||
self.position=self.carrier:GetCoordinate()
|
||||
self.turning=false
|
||||
|
||||
-- Init status updates in 10 seconds.
|
||||
self:__Status(10)
|
||||
@ -1098,45 +1104,65 @@ function RECOVERYTANKER:_CheckPatternUpdate(dt)
|
||||
|
||||
-- Assume no update necessary.
|
||||
local update=false
|
||||
|
||||
local Hchange=false
|
||||
local Dchange=false
|
||||
local turning=false
|
||||
|
||||
-- Get current position and orientation of carrier.
|
||||
local pos=self.carrier:GetCoordinate()
|
||||
local vC=self.carrier:GetOrientationX()
|
||||
local vNew=self.carrier:GetOrientationX()
|
||||
|
||||
-- Check if tanker is running and last updated is more than 10 minutes ago.
|
||||
if self:IsRunning() and dt>self.dTupdate then
|
||||
|
||||
-- Last saved orientation of carrier.
|
||||
local vP=self.orientation
|
||||
|
||||
-- We only need the X-Z plane.
|
||||
vC.y=0 ; vP.y=0
|
||||
|
||||
-- Get angle between the two orientation vectors in rad.
|
||||
local rhdg=math.deg(math.acos(UTILS.VecDot(vC,vP)/UTILS.VecNorm(vC)/UTILS.VecNorm(vP)))
|
||||
-- Reference orientation of carrier after the last update
|
||||
local vOld=self.orientation
|
||||
|
||||
-- Check if orientation changed.
|
||||
if math.abs(rhdg)>self.Hupdate then
|
||||
self:T(string.format("Carrier heading changed by %d degrees. Updating recovery tanker pattern.", rhdg))
|
||||
update=true
|
||||
end
|
||||
|
||||
-- Get distance to saved position.
|
||||
local dist=pos:Get2DDistance(self.position)
|
||||
|
||||
-- Check if carrier moved more than ~10 km.
|
||||
if dist>self.Dupdate then
|
||||
self:T(string.format("Carrier position changed by %.1f km. Updating recovery tanker pattern.", dist/1000))
|
||||
update=true
|
||||
end
|
||||
|
||||
-- Last orientation from 30 seconds ago.
|
||||
local vLast=self.orientlast
|
||||
|
||||
-- We only need the X-Z plane.
|
||||
vNew.y=0 ; vOld.y=0
|
||||
|
||||
-- Get angle between old and new orientation vectors in rad and convert to degrees.
|
||||
local deltaHeading=math.deg(math.acos(UTILS.VecDot(vNew,vOld)/UTILS.VecNorm(vNew)/UTILS.VecNorm(vOld)))
|
||||
|
||||
-- Angle between current heading and last time we checked ~30 seconds ago.
|
||||
local deltaLast=math.deg(math.acos(UTILS.VecDot(vNew,vLast)/UTILS.VecNorm(vNew)/UTILS.VecNorm(vLast)))
|
||||
|
||||
-- Last orientation becomes new orientation
|
||||
self.orientlast=vNew
|
||||
|
||||
-- Carrier is turning
|
||||
local turning=deltaLast>=1
|
||||
|
||||
-- Check if orientation changed.
|
||||
if math.abs(deltaHeading)>self.Hupdate then
|
||||
self:T(string.format("Carrier heading changed by %d degrees. Turning=%s.", deltaHeading, tostring(turning)))
|
||||
Hchange=true
|
||||
end
|
||||
|
||||
-- If pattern is updated then update orientation AND positon.
|
||||
-- But only if last update is less then 10 minutes ago.
|
||||
if update then
|
||||
self.orientation=vC
|
||||
self.position=pos
|
||||
-- Get distance to saved position.
|
||||
local dist=pos:Get2DDistance(self.position)
|
||||
|
||||
-- Check if carrier moved more than ~10 km.
|
||||
if dist>self.Dupdate then
|
||||
self:T(string.format("Carrier position changed by %.1f km. Turning=%s.", dist/1000, tostring(turning)))
|
||||
Dchange=true
|
||||
end
|
||||
|
||||
-- Assume no update necessary.
|
||||
local update=false
|
||||
|
||||
-- No update if currently turning! Also must be running (nor RTB or refuelling) and T>~10 min.
|
||||
if self:IsRunning() and dt>self.dTupdate and not turning then
|
||||
|
||||
-- Update if heading or distance changed.
|
||||
if Hchange or Dchange then
|
||||
self.orientation=vNew
|
||||
self.position=pos
|
||||
update=true
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
return update
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user