mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-08-15 10:47:21 +00:00
AIRBOSS v0.3.5w
This commit is contained in:
parent
58886dc42d
commit
6b24673b6f
@ -432,6 +432,7 @@ AIRBOSS.GroovePos={
|
|||||||
-- @field #string onboard Onboard number.
|
-- @field #string onboard Onboard number.
|
||||||
-- @field #string difficulty Difficulty level.
|
-- @field #string difficulty Difficulty level.
|
||||||
-- @field #string step Coming pattern step.
|
-- @field #string step Coming pattern step.
|
||||||
|
-- @field #boolean warning Set true once the player got a warning.
|
||||||
-- @field #number passes Number of passes.
|
-- @field #number passes Number of passes.
|
||||||
-- @field #boolean attitudemonitor If true, display aircraft attitude and other parameters constantly.
|
-- @field #boolean attitudemonitor If true, display aircraft attitude and other parameters constantly.
|
||||||
-- @field #table debrief Debrief analysis of the current step of this pass.
|
-- @field #table debrief Debrief analysis of the current step of this pass.
|
||||||
@ -455,7 +456,7 @@ AIRBOSS.MenuF10={}
|
|||||||
|
|
||||||
--- Airboss class version.
|
--- Airboss class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
AIRBOSS.version="0.3.5"
|
AIRBOSS.version="0.3.5w"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- TODO list
|
-- TODO list
|
||||||
@ -1212,6 +1213,8 @@ function AIRBOSS:_GetAircraftParameters(playerData, step)
|
|||||||
|
|
||||||
dist=-UTILS.NMToMeters(3)
|
dist=-UTILS.NMToMeters(3)
|
||||||
|
|
||||||
|
aoa=8.1
|
||||||
|
|
||||||
elseif step==AIRBOSS.PatternStep.INITIAL then
|
elseif step==AIRBOSS.PatternStep.INITIAL then
|
||||||
|
|
||||||
if hornet then
|
if hornet then
|
||||||
@ -1226,8 +1229,10 @@ function AIRBOSS:_GetAircraftParameters(playerData, step)
|
|||||||
|
|
||||||
if hornet then
|
if hornet then
|
||||||
alt=UTILS.FeetToMeters(800)
|
alt=UTILS.FeetToMeters(800)
|
||||||
|
speed=UTILS.KnotsToMps(350)
|
||||||
elseif skyhawk then
|
elseif skyhawk then
|
||||||
alt=UTILS.FeetToMeters(600)
|
alt=UTILS.FeetToMeters(600)
|
||||||
|
speed=UTILS.KnotsToMps(250)
|
||||||
end
|
end
|
||||||
|
|
||||||
elseif step==AIRBOSS.PatternStep.EARLYBREAK then
|
elseif step==AIRBOSS.PatternStep.EARLYBREAK then
|
||||||
@ -1971,6 +1976,7 @@ function AIRBOSS:_InitPlayer(playerData)
|
|||||||
playerData.step=AIRBOSS.PatternStep.UNDEFINED
|
playerData.step=AIRBOSS.PatternStep.UNDEFINED
|
||||||
playerData.groove={}
|
playerData.groove={}
|
||||||
playerData.debrief={}
|
playerData.debrief={}
|
||||||
|
playerData.warning=nil
|
||||||
playerData.holding=nil
|
playerData.holding=nil
|
||||||
playerData.lig=false
|
playerData.lig=false
|
||||||
playerData.patternwo=false
|
playerData.patternwo=false
|
||||||
@ -2123,18 +2129,19 @@ end
|
|||||||
|
|
||||||
--- Remove a flight from all queues. Also set player step to undefined if applicable.
|
--- Remove a flight from all queues. Also set player step to undefined if applicable.
|
||||||
-- @param #AIRBOSS self
|
-- @param #AIRBOSS self
|
||||||
-- @param #AIRBOSS.Flightitem flight The flight to be removed.
|
-- @param #AIRBOSS.PlayerData flight The flight to be removed.
|
||||||
function AIRBOSS:_RemoveFlight(flight)
|
function AIRBOSS:_RemoveFlight(flight)
|
||||||
|
|
||||||
-- Remove flight from all queues.
|
-- Remove flight from all queues.
|
||||||
self:_RemoveFlightFromQueue(self.Qmarshal, flight)
|
self:_RemoveFlightFromQueue(self.Qmarshal, flight)
|
||||||
self:_RemoveFlightFromQueue(self.Qpattern, flight)
|
self:_RemoveFlightFromQueue(self.Qpattern, flight)
|
||||||
|
|
||||||
-- Set Playerstep to undefined.
|
-- Check if player or AI
|
||||||
if flight.player then
|
if flight.player then
|
||||||
|
-- Set Playerstep to undefined.
|
||||||
flight.step=AIRBOSS.PatternStep.UNDEFINED
|
flight.step=AIRBOSS.PatternStep.UNDEFINED
|
||||||
else
|
else
|
||||||
-- Remove flight completely
|
-- Remove AI flight completely.
|
||||||
self:_RemoveFlightFromQueue(self.flights, flight)
|
self:_RemoveFlightFromQueue(self.flights, flight)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -2668,10 +2675,10 @@ function AIRBOSS:_Commencing(playerData)
|
|||||||
self:_InitPlayer(playerData)
|
self:_InitPlayer(playerData)
|
||||||
|
|
||||||
-- Commence
|
-- Commence
|
||||||
local text=string.format("Commencing. Case %d.", self.case)
|
local text=string.format("Commencing. (Case %d)", self.case)
|
||||||
|
|
||||||
-- Message to player.
|
-- Message to all players.
|
||||||
self:_SendMessageToPlayer(text, 10, playerData)
|
self:MessageToAll(text, playerData.onboard, "", 5)
|
||||||
|
|
||||||
-- Next step: depends on case recovery.
|
-- Next step: depends on case recovery.
|
||||||
if self.case==1 then
|
if self.case==1 then
|
||||||
@ -2694,11 +2701,11 @@ function AIRBOSS:_Initial(playerData)
|
|||||||
-- Inform player.
|
-- Inform player.
|
||||||
local hint=string.format("Entering the pattern.")
|
local hint=string.format("Entering the pattern.")
|
||||||
if playerData.difficulty==AIRBOSS.Difficulty.EASY then
|
if playerData.difficulty==AIRBOSS.Difficulty.EASY then
|
||||||
hint=hint.."Aim for 800 feet and 350 kts at the break entry."
|
hint=hint.."\nAim for 800 feet and 350 kts at the break entry."
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Send message.
|
-- Send message.
|
||||||
self:_SendMessageToPlayer(hint, 10, playerData)
|
self:MessageToPlayer(playerData, hint, "MARSHAL")
|
||||||
|
|
||||||
-- Next step: upwind.
|
-- Next step: upwind.
|
||||||
playerData.step=AIRBOSS.PatternStep.UPWIND
|
playerData.step=AIRBOSS.PatternStep.UPWIND
|
||||||
@ -2722,23 +2729,6 @@ function AIRBOSS:_Descent4k(playerData)
|
|||||||
|
|
||||||
-- Check if we are in front of the boat (diffX > 0).
|
-- Check if we are in front of the boat (diffX > 0).
|
||||||
if self:_CheckLimits(X, Z, self.Descent4k) then
|
if self:_CheckLimits(X, Z, self.Descent4k) then
|
||||||
|
|
||||||
-- Get optimal altitude, distance and speed.
|
|
||||||
local altitude=self:_GetAircraftParameters(playerData)
|
|
||||||
|
|
||||||
-- TODO: only speed is checked here!
|
|
||||||
|
|
||||||
MESSAGE:New("Descent 4k step reached", 5):ToAllIf(self.Debug)
|
|
||||||
|
|
||||||
-- Get altitude.
|
|
||||||
local hint, debrief=self:_AltitudeCheck(playerData, altitude)
|
|
||||||
|
|
||||||
-- Message to player
|
|
||||||
self:_SendMessageToPlayer(hint, 10, playerData)
|
|
||||||
|
|
||||||
-- Debrief.
|
|
||||||
self:_AddToSummary(playerData, "Descent 4k", debrief)
|
|
||||||
|
|
||||||
-- Next step: Platform at 5k
|
-- Next step: Platform at 5k
|
||||||
playerData.step=AIRBOSS.PatternStep.PLATFORM
|
playerData.step=AIRBOSS.PatternStep.PLATFORM
|
||||||
end
|
end
|
||||||
@ -2749,13 +2739,16 @@ end
|
|||||||
-- @param #AIRBOSS.PlayerData playerData Player data table.
|
-- @param #AIRBOSS.PlayerData playerData Player data table.
|
||||||
function AIRBOSS:_Platform(playerData)
|
function AIRBOSS:_Platform(playerData)
|
||||||
|
|
||||||
-- Get distances between carrier and player unit (parallel and perpendicular to direction of movement of carrier)
|
-- Check if player is in valid zone
|
||||||
local X, Z, rho, phi=self:_GetDistances(playerData.unit)
|
local validzone=self:_GetCase23ValidZone()
|
||||||
|
|
||||||
-- Abort condition check.
|
-- Check if we are inside the moving zone.
|
||||||
if self:_CheckAbort(X, Z, self.Platform) then
|
local invalid=playerData.unit:IsNotInZone(validzone)
|
||||||
self:_AbortPattern(playerData, X, Z, self.Platform)
|
|
||||||
--return
|
-- Issue warning.
|
||||||
|
if invalid and not playerData.warning then
|
||||||
|
self:MessageToPlayer(playerData, "You left the valid pattern zone!", "AIRBOSS")
|
||||||
|
playerData.warning=true
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Check if we are inside the moving zone.
|
-- Check if we are inside the moving zone.
|
||||||
@ -2764,27 +2757,27 @@ function AIRBOSS:_Platform(playerData)
|
|||||||
-- Check if we are in zone.
|
-- Check if we are in zone.
|
||||||
if inzone then
|
if inzone then
|
||||||
|
|
||||||
|
-- Debug message.
|
||||||
MESSAGE:New("Platform step reached", 5):ToAllIf(self.Debug)
|
MESSAGE:New("Platform step reached", 5):ToAllIf(self.Debug)
|
||||||
|
|
||||||
-- Get optimal altitiude.
|
-- Get optimal altitiude.
|
||||||
local altitude, aoa, distance, speed =self:_GetAircraftParameters(playerData)
|
local altitude, aoa, distance, speed =self:_GetAircraftParameters(playerData)
|
||||||
|
|
||||||
--TODO: check speed.
|
-- Get altitude hint.
|
||||||
|
local hintAlt=self:_AltitudeCheck(playerData, altitude)
|
||||||
|
|
||||||
-- Get altitude hint.
|
-- Get altitude hint.
|
||||||
local hintAlt, debriefAlt=self:_AltitudeCheck(playerData, altitude)
|
local hintSpeed=self:_SpeedCheck(playerData, speed)
|
||||||
|
|
||||||
-- Get altitude hint.
|
-- Message to player.
|
||||||
local hintSpeed, debriefSpeed=self:_AltitudeCheck(playerData, altitude)
|
if playerData.difficulty~=AIRBOSS.Difficulty.HARD then
|
||||||
|
local hint=string.format("%s\n%s\n%s", playerData.step, hintAlt, hintSpeed)
|
||||||
-- Message to player
|
self:MessageToPlayer(playerData, hint, "MARSHAL", "")
|
||||||
self:_SendMessageToPlayer(hint, 10, playerData)
|
end
|
||||||
|
|
||||||
-- Debrief.
|
|
||||||
--self:_AddToSummary(playerData, "Platform 5k", debrief)
|
|
||||||
|
|
||||||
-- Next step: Dirty up and level out at 1200 ft.
|
-- Next step: Dirty up and level out at 1200 ft.
|
||||||
playerData.step=AIRBOSS.PatternStep.DIRTYUP
|
playerData.step=AIRBOSS.PatternStep.DIRTYUP
|
||||||
|
playerData.warning=nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -2793,13 +2786,16 @@ end
|
|||||||
-- @param #AIRBOSS.PlayerData playerData Player data table.
|
-- @param #AIRBOSS.PlayerData playerData Player data table.
|
||||||
function AIRBOSS:_DirtyUp(playerData)
|
function AIRBOSS:_DirtyUp(playerData)
|
||||||
|
|
||||||
-- Get distances between carrier and player unit (parallel and perpendicular to direction of movement of carrier)
|
-- Check if player is in valid zone
|
||||||
local X, Z, rho, phi=self:_GetDistances(playerData.unit)
|
local validzone=self:_GetCase23ValidZone()
|
||||||
|
|
||||||
-- Abort condition check.
|
-- Check if we are inside the moving zone.
|
||||||
if self:_CheckAbort(X, Z, self.DirtyUp) then
|
local invalid=playerData.unit:IsNotInZone(validzone)
|
||||||
self:_AbortPattern(playerData, X, Z, self.DirtyUp)
|
|
||||||
--return
|
-- Issue warning.
|
||||||
|
if invalid and not playerData.warning then
|
||||||
|
self:MessageToPlayer(playerData, "You left the valid pattern zone!", "AIRBOSS")
|
||||||
|
playerData.warning=true
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Check if we are inside the moving zone.
|
-- Check if we are inside the moving zone.
|
||||||
@ -2808,21 +2804,24 @@ function AIRBOSS:_DirtyUp(playerData)
|
|||||||
--if self:_CheckLimits(X, Z, self.DirtyUp) then
|
--if self:_CheckLimits(X, Z, self.DirtyUp) then
|
||||||
if inzone then
|
if inzone then
|
||||||
|
|
||||||
|
-- Debug message.
|
||||||
MESSAGE:New("Dirty up step reached", 5):ToAllIf(self.Debug)
|
MESSAGE:New("Dirty up step reached", 5):ToAllIf(self.Debug)
|
||||||
|
|
||||||
--TODO: speed check
|
|
||||||
|
|
||||||
-- Get optimal altitiude.
|
-- Get optimal altitiude.
|
||||||
local altitude=self:_GetAircraftParameters(playerData)
|
local altitude, aoa, distance, speed=self:_GetAircraftParameters(playerData)
|
||||||
|
|
||||||
-- Get altitude.
|
-- Get altitude hint.
|
||||||
local hint, debrief=self:_AltitudeCheck(playerData, altitude)
|
local hintAlt, debrief=self:_AltitudeCheck(playerData, altitude)
|
||||||
|
|
||||||
-- Message to player
|
-- Get speed hint.
|
||||||
self:_SendMessageToPlayer(hint, 10, playerData)
|
-- TODO: Not sure if we already need to be onspeed AoA at this point?
|
||||||
|
local hintSpeed=self:_SpeedCheck(playerData, speed)
|
||||||
|
|
||||||
-- Debrief.
|
-- Message to player.
|
||||||
self:_AddToSummary(playerData, "Dirty Up", debrief)
|
if playerData.difficulty~=AIRBOSS.Difficulty.HARD then
|
||||||
|
local hint=string.format("%s\n%s\n%s", playerData.step, hintAlt, hintSpeed)
|
||||||
|
self:MessageToPlayer(playerData, hint, "MARSHAL", "")
|
||||||
|
end
|
||||||
|
|
||||||
-- Next step:
|
-- Next step:
|
||||||
if self.case==2 then
|
if self.case==2 then
|
||||||
@ -2832,6 +2831,7 @@ function AIRBOSS:_DirtyUp(playerData)
|
|||||||
-- CASE III: Intercept glide slope and follow bullseye (ICLS).
|
-- CASE III: Intercept glide slope and follow bullseye (ICLS).
|
||||||
playerData.step=AIRBOSS.PatternStep.BULLSEYE
|
playerData.step=AIRBOSS.PatternStep.BULLSEYE
|
||||||
end
|
end
|
||||||
|
playerData.warning=nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -2840,13 +2840,16 @@ end
|
|||||||
-- @param #AIRBOSS.PlayerData playerData Player data table.
|
-- @param #AIRBOSS.PlayerData playerData Player data table.
|
||||||
function AIRBOSS:_Bullseye(playerData)
|
function AIRBOSS:_Bullseye(playerData)
|
||||||
|
|
||||||
-- Get distances between carrier and player unit (parallel and perpendicular to direction of movement of carrier)
|
-- Check if player is in valid zone
|
||||||
local X, Z, rho, phi=self:_GetDistances(playerData.unit)
|
local validzone=self:_GetCase23ValidZone()
|
||||||
|
|
||||||
-- Abort condition check.
|
-- Check if we are inside the moving zone.
|
||||||
if self:_CheckAbort(X, Z, self.Bullseye) then
|
local invalid=playerData.unit:IsNotInZone(validzone)
|
||||||
self:_AbortPattern(playerData, X, Z, self.Bullseye)
|
|
||||||
--return
|
-- Issue warning.
|
||||||
|
if invalid and not playerData.warning then
|
||||||
|
self:MessageToPlayer(playerData, "You left the valid pattern zone!", "AIRBOSS")
|
||||||
|
playerData.warning=true
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Check if we are inside the moving zone.
|
-- Check if we are inside the moving zone.
|
||||||
@ -2856,24 +2859,27 @@ function AIRBOSS:_Bullseye(playerData)
|
|||||||
--if self:_CheckLimits(X, Z, self.Bullseye) then
|
--if self:_CheckLimits(X, Z, self.Bullseye) then
|
||||||
if inzone then
|
if inzone then
|
||||||
|
|
||||||
|
-- Debug message.
|
||||||
MESSAGE:New("Bullseye step reached", 5):ToAllIf(self.Debug)
|
MESSAGE:New("Bullseye step reached", 5):ToAllIf(self.Debug)
|
||||||
|
|
||||||
-- Get optimal altitiude.
|
-- Get optimal altitiude.
|
||||||
local altitude=self:_GetAircraftParameters(playerData)
|
local altitude, aoa, distance, speed=self:_GetAircraftParameters(playerData)
|
||||||
|
|
||||||
-- Get altitude.
|
-- Get altitude hint.
|
||||||
local hint, debrief=self:_AltitudeCheck(playerData, altitude)
|
local hintAlt=self:_AltitudeCheck(playerData, altitude)
|
||||||
|
|
||||||
-- Message to player
|
-- Get altitude hint.
|
||||||
self:_SendMessageToPlayer(hint, 10, playerData)
|
local hintAoA=self:_AoACheck(playerData, aoa)
|
||||||
|
|
||||||
-- Debrief.
|
-- Message to player.
|
||||||
self:_AddToSummary(playerData, "Bullseye", debrief)
|
if playerData.difficulty~=AIRBOSS.Difficulty.HARD then
|
||||||
|
local hint=string.format("%s\n%s\n%s", playerData.step, hintAlt, hintAoA)
|
||||||
|
self:MessageToPlayer(playerData, hint, "MARSHAL", "")
|
||||||
|
end
|
||||||
|
|
||||||
-- Next step: Final approach in the groove.
|
|
||||||
--playerData.step=AIRBOSS.PatternStep.FINAL
|
|
||||||
-- 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
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -2898,14 +2904,20 @@ function AIRBOSS:_Upwind(playerData)
|
|||||||
-- Get optimal altitude, distance and speed.
|
-- Get optimal altitude, distance and speed.
|
||||||
local alt, aoa, dist, speed=self:_GetAircraftParameters(playerData)
|
local alt, aoa, dist, speed=self:_GetAircraftParameters(playerData)
|
||||||
|
|
||||||
-- Get altitude.
|
-- Get altitude hint.
|
||||||
local hint, debrief=self:_AltitudeCheck(playerData, alt)
|
local hintAlt=self:_AltitudeCheck(playerData, alt)
|
||||||
|
|
||||||
-- Message to player
|
-- Get speed hint.
|
||||||
self:_SendMessageToPlayer(hint, 10, playerData)
|
local hintSpeed=self:_AltitudeCheck(playerData, speed)
|
||||||
|
|
||||||
|
-- Message to player.
|
||||||
|
if playerData.difficulty~=AIRBOSS.Difficulty.HARD then
|
||||||
|
local hint=string.format("%s\n%s\n%s", playerData.step, hintAlt, hintSpeed)
|
||||||
|
self:MessageToPlayer(playerData, hint, "MARSHAL", "")
|
||||||
|
end
|
||||||
|
|
||||||
-- Debrief.
|
-- Debrief.
|
||||||
self:_AddToSummary(playerData, "Entering the Break", debrief)
|
--self:_AddToSummary(playerData, "Entering the Break", debrief)
|
||||||
|
|
||||||
-- Next step: Early Break.
|
-- Next step: Early Break.
|
||||||
playerData.step=AIRBOSS.PatternStep.EARLYBREAK
|
playerData.step=AIRBOSS.PatternStep.EARLYBREAK
|
||||||
@ -2943,8 +2955,11 @@ function AIRBOSS:_Break(playerData, part)
|
|||||||
-- Grade altitude.
|
-- Grade altitude.
|
||||||
local hint, debrief=self:_AltitudeCheck(playerData, altitude)
|
local hint, debrief=self:_AltitudeCheck(playerData, altitude)
|
||||||
|
|
||||||
-- Send message to player.
|
-- Message to player.
|
||||||
self:_SendMessageToPlayer(hint, 10, playerData)
|
if playerData.difficulty~=AIRBOSS.Difficulty.HARD then
|
||||||
|
local hint=string.format("%s %s", playerData.step, hint)
|
||||||
|
self:MessageToPlayer(playerData, hint, "MARSHAL", "")
|
||||||
|
end
|
||||||
|
|
||||||
-- Debrief
|
-- Debrief
|
||||||
if part=="early" then
|
if part=="early" then
|
||||||
@ -2980,7 +2995,7 @@ function AIRBOSS:_CheckForLongDownwind(playerData)
|
|||||||
self:RadioTransmission(self.LSOradio, self.radiocall.LONGINGROOVE)
|
self:RadioTransmission(self.LSOradio, self.radiocall.LONGINGROOVE)
|
||||||
|
|
||||||
-- Debrief.
|
-- Debrief.
|
||||||
self:_AddToSummary(playerData, "Downwind", "Long in the groove.")
|
self:_AddToSummary(playerData, "Downwind", "Long in the groove - Pattern Wave Off!")
|
||||||
|
|
||||||
--grade="LIG PATTERN WAVE OFF - CUT 1 PT"
|
--grade="LIG PATTERN WAVE OFF - CUT 1 PT"
|
||||||
playerData.lig=true
|
playerData.lig=true
|
||||||
@ -3021,12 +3036,18 @@ function AIRBOSS:_Abeam(playerData)
|
|||||||
-- Grade distance to carrier.
|
-- Grade distance to carrier.
|
||||||
local hintDist, debriefDist=self:_DistanceCheck(playerData, dist) --math.abs(Z)
|
local hintDist, debriefDist=self:_DistanceCheck(playerData, dist) --math.abs(Z)
|
||||||
|
|
||||||
-- Compile full hint.
|
-- Paddles contact.
|
||||||
local hint=string.format("%s\n%s\n%s", hintAlt, hintAoA, hintDist)
|
-- TODO: radio message.
|
||||||
local debrief=string.format("%s\n%s\n%s", debriefAlt, debriefAoA, debriefDist)
|
self:MessageToPlayer(playerData, "Paddles, contact.", "LSO", "")
|
||||||
|
|
||||||
-- Send message to playerr.
|
-- Message to player.
|
||||||
self:_SendMessageToPlayer(hint, 10, playerData)
|
if playerData.difficulty~=AIRBOSS.Difficulty.HARD then
|
||||||
|
local hint=string.format("%s\n%s\n%s\n%s", playerData.step, hintAlt, hintAoA, hintDist)
|
||||||
|
self:MessageToPlayer(playerData, hint, "LSO", "")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Compile full hint.
|
||||||
|
local debrief=string.format("%s\n%s\n%s", debriefAlt, debriefAoA, debriefDist)
|
||||||
|
|
||||||
-- Add to debrief.
|
-- Add to debrief.
|
||||||
self:_AddToSummary(playerData, "Abeam Position", debrief)
|
self:_AddToSummary(playerData, "Abeam Position", debrief)
|
||||||
@ -3065,12 +3086,14 @@ function AIRBOSS:_Ninety(playerData)
|
|||||||
-- Grade AoA.
|
-- Grade AoA.
|
||||||
local hintAoA, debriefAoA=self:_AoACheck(playerData, aoa)
|
local hintAoA, debriefAoA=self:_AoACheck(playerData, aoa)
|
||||||
|
|
||||||
-- Compile full hint.
|
|
||||||
local hint=string.format("%s\n%s", hintAlt, hintAoA)
|
|
||||||
local debrief=string.format("%s\n%s", debriefAlt, debriefAoA)
|
|
||||||
|
|
||||||
-- Message to player.
|
-- Message to player.
|
||||||
self:_SendMessageToPlayer(hint, 10, playerData)
|
if playerData.difficulty~=AIRBOSS.Difficulty.HARD then
|
||||||
|
local hint=string.format("%s\n%s\n%s", playerData.step, hintAlt, hintAoA)
|
||||||
|
self:MessageToPlayer(playerData, hint, "LSO", "")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Debrief.
|
||||||
|
local debrief=string.format("%s\n%s", debriefAlt, debriefAoA)
|
||||||
|
|
||||||
-- Add to debrief.
|
-- Add to debrief.
|
||||||
self:_AddToSummary(playerData, "At the 90", debrief)
|
self:_AddToSummary(playerData, "At the 90", debrief)
|
||||||
@ -3080,7 +3103,7 @@ function AIRBOSS:_Ninety(playerData)
|
|||||||
|
|
||||||
elseif relheading>90 and self:_CheckLimits(X, Z, self.Wake) then
|
elseif relheading>90 and self:_CheckLimits(X, Z, self.Wake) then
|
||||||
-- Message to player.
|
-- Message to player.
|
||||||
self:_SendMessageToPlayer("You are already at the wake and have not passed the 90! Turn faster next time!", 10, playerData)
|
self:MessageToPlayer(playerData, "You are already at the wake and have not passed the 90! Turn faster next time!", "LSO", "")
|
||||||
--TODO: pattern WO?
|
--TODO: pattern WO?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -3111,12 +3134,14 @@ function AIRBOSS:_Wake(playerData)
|
|||||||
-- Grade AoA.
|
-- Grade AoA.
|
||||||
local hintAoA, debriefAoA=self:_AoACheck(playerData, aoa)
|
local hintAoA, debriefAoA=self:_AoACheck(playerData, aoa)
|
||||||
|
|
||||||
-- Compile full hint.
|
|
||||||
local hint=string.format("%s\n%s", hintAlt, hintAoA)
|
|
||||||
local debrief=string.format("%s\n%s", debriefAlt, debriefAoA)
|
|
||||||
|
|
||||||
-- Message to player.
|
-- Message to player.
|
||||||
self:_SendMessageToPlayer(hint, 10, playerData)
|
if playerData.difficulty~=AIRBOSS.Difficulty.HARD then
|
||||||
|
local hint=string.format("%s\n%s\n%s", playerData.step, hintAlt, hintAoA)
|
||||||
|
self:MessageToPlayer(playerData, hint, "LSO", "")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Debrief.
|
||||||
|
local debrief=string.format("%s\n%s", debriefAlt, debriefAoA)
|
||||||
|
|
||||||
-- Add to debrief.
|
-- Add to debrief.
|
||||||
self:_AddToSummary(playerData, "At the Wake", debrief)
|
self:_AddToSummary(playerData, "At the Wake", debrief)
|
||||||
@ -3161,14 +3186,14 @@ function AIRBOSS:_Final(playerData)
|
|||||||
-- AoA feed back
|
-- AoA feed back
|
||||||
local hintAoA, debriefAoA=self:_AoACheck(playerData, aoa)
|
local hintAoA, debriefAoA=self:_AoACheck(playerData, aoa)
|
||||||
|
|
||||||
-- Compile full hint.
|
|
||||||
local hint=string.format("%s\n%s", hintAlt, hintAoA)
|
|
||||||
local debrief=string.format("%s\n%s", debriefAlt, debriefAoA)
|
|
||||||
|
|
||||||
-- Message to player.
|
-- Message to player.
|
||||||
self:_SendMessageToPlayer(hint, 10, playerData)
|
if playerData.difficulty~=AIRBOSS.Difficulty.HARD then
|
||||||
|
local hint=string.format("%s\n%s\n%s", playerData.step, hintAlt, hintAoA)
|
||||||
|
self:MessageToPlayer(playerData, hint, "LSO", "")
|
||||||
|
end
|
||||||
|
|
||||||
-- Add to debrief.
|
-- Add to debrief.
|
||||||
|
local debrief=string.format("%s\n%s", debriefAlt, debriefAoA)
|
||||||
self:_AddToSummary(playerData, "Enter Groove", debrief)
|
self:_AddToSummary(playerData, "Enter Groove", debrief)
|
||||||
|
|
||||||
-- Gather pilot data.
|
-- Gather pilot data.
|
||||||
@ -3266,7 +3291,8 @@ function AIRBOSS:_Groove(playerData)
|
|||||||
elseif rho<=RIM and playerData.step==AIRBOSS.PatternStep.GROOVE_IM then
|
elseif rho<=RIM and playerData.step==AIRBOSS.PatternStep.GROOVE_IM then
|
||||||
|
|
||||||
-- Debug.
|
-- Debug.
|
||||||
self:_SendMessageToPlayer("IM", 5, playerData)
|
local text=string.format("FF IM=%d", rho)
|
||||||
|
MESSAGE:New(text, 5):ToAllIf(self.Debug)
|
||||||
self:I(self.lid..string.format("FF IM=%d", rho))
|
self:I(self.lid..string.format("FF IM=%d", rho))
|
||||||
|
|
||||||
-- Store data.
|
-- Store data.
|
||||||
@ -3281,8 +3307,9 @@ function AIRBOSS:_Groove(playerData)
|
|||||||
if playerData.waveoff==false then
|
if playerData.waveoff==false then
|
||||||
|
|
||||||
-- Debug
|
-- Debug
|
||||||
self:_SendMessageToPlayer("IC", 5, playerData)
|
local text=string.format("FF IC=%d", rho)
|
||||||
self:I(self.lid..string.format("FF IC=%d", rho))
|
MESSAGE:New(text, 5):ToAllIf(self.Debug)
|
||||||
|
self:I(self.lid..text)
|
||||||
|
|
||||||
-- Store data.
|
-- Store data.
|
||||||
playerData.groove.IC=groovedata
|
playerData.groove.IC=groovedata
|
||||||
@ -3311,8 +3338,9 @@ function AIRBOSS:_Groove(playerData)
|
|||||||
elseif rho<=RAR and playerData.step==AIRBOSS.PatternStep.GROOVE_AR then
|
elseif rho<=RAR and playerData.step==AIRBOSS.PatternStep.GROOVE_AR then
|
||||||
|
|
||||||
-- Debug.
|
-- Debug.
|
||||||
self:_SendMessageToPlayer("AR", 8, playerData)
|
local text=string.format("FF AR=%d", rho)
|
||||||
self:I(self.lid..string.format("FF AR=%d", rho))
|
MESSAGE:New(text, 5):ToAllIf(self.Debug)
|
||||||
|
self:I(self.lid..text)
|
||||||
|
|
||||||
-- Store data.
|
-- Store data.
|
||||||
playerData.groove.AR=groovedata
|
playerData.groove.AR=groovedata
|
||||||
@ -3435,14 +3463,16 @@ function AIRBOSS:_Trapped(playerData, X)
|
|||||||
|
|
||||||
-- Info to player.
|
-- Info to player.
|
||||||
local text=string.format("Trapped! %d-wire.", wire)
|
local text=string.format("Trapped! %d-wire.", wire)
|
||||||
self:_SendMessageToPlayer(text, 10, playerData)
|
self:MessageToPlayer(playerData, text, "LSO", "")
|
||||||
|
|
||||||
local text2=string.format("Distance X=%.1f meters resulted in a %d-wire estimate.", X, wire)
|
-- Debug message.
|
||||||
MESSAGE:New(text,30):ToAllIf(self.Debug)
|
local text=string.format("Distance X=%.1f meters resulted in a %d-wire estimate.", X, wire)
|
||||||
self:I(self.lid..text2)
|
MESSAGE:New(text, 30):ToAllIf(self.Debug)
|
||||||
|
self:I(self.lid..text)
|
||||||
|
|
||||||
|
-- Debrief.
|
||||||
local hint = string.format("Trapped catching the %d-wire.", wire)
|
local hint = string.format("Trapped catching the %d-wire.", wire)
|
||||||
self:_AddToSummary(playerData, "Recovered", hint)
|
self:_AddToSummary(playerData, "Goove: IW", hint)
|
||||||
|
|
||||||
else
|
else
|
||||||
--Boltered!
|
--Boltered!
|
||||||
@ -3868,11 +3898,9 @@ function AIRBOSS:_LSOadvice(playerData, glideslopeError, lineupError)
|
|||||||
text=text.."Unknown AoA state."
|
text=text.."Unknown AoA state."
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Text not used.
|
||||||
text=text..string.format(" AoA = %.1f", aoa)
|
text=text..string.format(" AoA = %.1f", aoa)
|
||||||
|
|
||||||
-- LSO Message to player.
|
|
||||||
--self:_SendMessageToPlayer(text, 5, playerData, false)
|
|
||||||
|
|
||||||
-- Set last time.
|
-- Set last time.
|
||||||
playerData.Tlso=timer.getTime()
|
playerData.Tlso=timer.getTime()
|
||||||
end
|
end
|
||||||
@ -4266,13 +4294,13 @@ function AIRBOSS:_AltitudeCheck(playerData, altopt)
|
|||||||
|
|
||||||
local hint
|
local hint
|
||||||
if _error>badscore then
|
if _error>badscore then
|
||||||
hint=string.format("You're high. ")
|
hint=string.format("You're high.")
|
||||||
elseif _error>lowscore then
|
elseif _error>lowscore then
|
||||||
hint= string.format("You're slightly high. ")
|
hint= string.format("You're slightly high.")
|
||||||
elseif _error<-badscore then
|
elseif _error<-badscore then
|
||||||
hint=string.format("You're low. ")
|
hint=string.format("You're low. ")
|
||||||
elseif _error<-lowscore then
|
elseif _error<-lowscore then
|
||||||
hint=string.format("You're slightly low. ")
|
hint=string.format("You're slightly low.")
|
||||||
else
|
else
|
||||||
hint=string.format("Good altitude. ")
|
hint=string.format("Good altitude. ")
|
||||||
end
|
end
|
||||||
@ -4315,15 +4343,15 @@ function AIRBOSS:_DistanceCheck(playerData, optdist)
|
|||||||
|
|
||||||
local hint
|
local hint
|
||||||
if _error>badscore then
|
if _error>badscore then
|
||||||
hint=string.format("You're too far from the boat! ")
|
hint=string.format("You're too far from the boat!")
|
||||||
elseif _error>lowscore then
|
elseif _error>lowscore then
|
||||||
hint=string.format("You're slightly too far from the boat. ")
|
hint=string.format("You're slightly too far from the boat.")
|
||||||
elseif _error<-badscore then
|
elseif _error<-badscore then
|
||||||
hint=string.format( "You're too close to the boat! ")
|
hint=string.format( "You're too close to the boat!")
|
||||||
elseif _error<-lowscore then
|
elseif _error<-lowscore then
|
||||||
hint=string.format("You're slightly too far from the boat. ")
|
hint=string.format("You're slightly too far from the boat.")
|
||||||
else
|
else
|
||||||
hint=string.format("Perfect distance to the boat. ")
|
hint=string.format("Good distance to the boat.")
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Extend or decrease depending on skill.
|
-- Extend or decrease depending on skill.
|
||||||
@ -4583,10 +4611,7 @@ function AIRBOSS:RadioTransmission(radio, call, loud, delay)
|
|||||||
radio:Broadcast(true)
|
radio:Broadcast(true)
|
||||||
|
|
||||||
-- "Subtitle".
|
-- "Subtitle".
|
||||||
for _,_player in pairs(self.players) do
|
self:MessageToAll(call.subtitle, radio:GetAlias(), "", call.duration)
|
||||||
local playerData=_player --#AIRBOSS.PlayerData
|
|
||||||
self:_SendMessageToPlayer(call.subtitle, call.duration, playerData)
|
|
||||||
end
|
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
@ -4604,34 +4629,6 @@ function AIRBOSS:RadioTransmission(radio, call, loud, delay)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Send message to player client.
|
|
||||||
-- @param #AIRBOSS self
|
|
||||||
-- @param #string message The message to send.
|
|
||||||
-- @param #number duration Display message duration.
|
|
||||||
-- @param #AIRBOSS.PlayerData playerData Player data.
|
|
||||||
-- @param #boolean clear If true, clear screen from previous messages.
|
|
||||||
-- @param #string sender The person who sends the message. Default is carrier alias.
|
|
||||||
-- @param #number delay Delay in seconds, before the message is send.
|
|
||||||
function AIRBOSS:_SendMessageToPlayer(message, duration, playerData, clear, sender, delay)
|
|
||||||
|
|
||||||
if playerData and message and message~="" then
|
|
||||||
|
|
||||||
-- Format message.
|
|
||||||
local text=string.format("%s, %s", playerData.callsign, message)
|
|
||||||
self:I(self.lid..text)
|
|
||||||
|
|
||||||
if delay and delay>0 then
|
|
||||||
SCHEDULER:New(nil, self._SendMessageToPlayer, {self, message, duration, playerData, clear, sender}, delay)
|
|
||||||
else
|
|
||||||
if playerData.client then
|
|
||||||
MESSAGE:New(text, duration, sender, clear):ToClient(playerData.client)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Send text message to player client.
|
--- Send text message to player client.
|
||||||
-- Message format will be "SENDER: RECCEIVER, MESSAGE".
|
-- Message format will be "SENDER: RECCEIVER, MESSAGE".
|
||||||
-- @param #AIRBOSS self
|
-- @param #AIRBOSS self
|
||||||
@ -4671,6 +4668,26 @@ function AIRBOSS:MessageToPlayer(playerData, message, sender, receiver, duration
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Send text message to all players in the CCA.
|
||||||
|
-- Message format will be "SENDER: RECCEIVER, MESSAGE".
|
||||||
|
-- @param #AIRBOSS self
|
||||||
|
-- @param #string message The message to send.
|
||||||
|
-- @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 displayed.
|
||||||
|
function AIRBOSS:MessageToAll(message, sender, receiver, duration, clear, delay)
|
||||||
|
|
||||||
|
for _,_player in pairs(self.players) do
|
||||||
|
local player=_player --#AIRBOSS.PlayerData
|
||||||
|
if player.unit:IsInZone(self.zoneCCA) then
|
||||||
|
self:MessageToPlayer(player,message,sender,receiver,duration,clear,delay)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
--- Check if aircraft is capable of landing on an aircraft carrier.
|
--- Check if aircraft is capable of landing on an aircraft carrier.
|
||||||
-- @param #AIRBOSS self
|
-- @param #AIRBOSS self
|
||||||
-- @param Wrapper.Unit#UNIT unit Aircraft unit. (Will also work with groups as given parameter.)
|
-- @param Wrapper.Unit#UNIT unit Aircraft unit. (Will also work with groups as given parameter.)
|
||||||
|
|||||||
@ -35,7 +35,9 @@
|
|||||||
-- @field #number altitude Tanker orbit pattern altitude.
|
-- @field #number altitude Tanker orbit pattern altitude.
|
||||||
-- @field #number distStern Race-track distance astern.
|
-- @field #number distStern Race-track distance astern.
|
||||||
-- @field #number distBow Race-track distance bow.
|
-- @field #number distBow Race-track distance bow.
|
||||||
-- @field #number dTupdate Time interval for updating pattern position wrt new tanker position.
|
-- @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 dTupdate Minimum time interval in seconds before the next pattern update can happen.
|
||||||
-- @field #number Tupdate Last time the pattern was updated.
|
-- @field #number Tupdate Last time the pattern was updated.
|
||||||
-- @field #number takeoff Takeoff type (cold, hot, air).
|
-- @field #number takeoff Takeoff type (cold, hot, air).
|
||||||
-- @field #number lowfuel Low fuel threshold in percent.
|
-- @field #number lowfuel Low fuel threshold in percent.
|
||||||
@ -58,11 +60,11 @@
|
|||||||
--
|
--
|
||||||
-- # Simple Script
|
-- # Simple Script
|
||||||
--
|
--
|
||||||
-- In the mission editor you have to set up a carrier unit, which will act as "mother". In the following, this unit will be named "USS Stennis".
|
-- In the mission editor you have to set up a carrier unit, which will act as "mother". In the following, this unit will be named **"USS Stennis"**.
|
||||||
--
|
--
|
||||||
-- Secondly, you need to define a recovery tanker group in the mission editor and set it to "LATE ACTIVATED". The name of the group we'll use is "Texaco".
|
-- Secondly, you need to define a recovery tanker group in the mission editor and set it to **"LATE ACTIVATED"**. The name of the group we'll use is **"Texaco"**.
|
||||||
--
|
--
|
||||||
-- The basic script is very simple and consists of only two lines.
|
-- The basic script is very simple and consists of only two lines:
|
||||||
--
|
--
|
||||||
-- TexacoStennis=RECOVERYTANKER:New(UNIT:FindByName("USS Stennis"), "Texaco")
|
-- TexacoStennis=RECOVERYTANKER:New(UNIT:FindByName("USS Stennis"), "Texaco")
|
||||||
-- TexacoStennis:Start()
|
-- TexacoStennis:Start()
|
||||||
@ -78,11 +80,11 @@
|
|||||||
--
|
--
|
||||||
-- Once the tanker runs out of fuel itself, it will return to the carrier and be respawned.
|
-- Once the tanker runs out of fuel itself, it will return to the carrier and be respawned.
|
||||||
--
|
--
|
||||||
-- # Fine Tuning
|
-- # Options and Fine Tuning
|
||||||
--
|
--
|
||||||
-- Several parameters can be customized by the mission designer.
|
-- Several parameters can be customized by the mission designer.
|
||||||
--
|
--
|
||||||
-- ## Adjusting the Takeoff Type
|
-- ## Takeoff Type
|
||||||
--
|
--
|
||||||
-- By default, the tanker is spawned with running engies on the carrier. The mission designer has set option to set the take off type via the @{#RECOVERYTANKER.SetTakeoff} function.
|
-- By default, the tanker is spawned with running engies on the carrier. The mission designer has set option to set the take off type via the @{#RECOVERYTANKER.SetTakeoff} function.
|
||||||
-- Or via shortcuts
|
-- Or via shortcuts
|
||||||
@ -104,9 +106,9 @@
|
|||||||
-- If only the first spawning should happen on the carrier, one use the @{#RECOVERYTANKER.SetRespawnInAir}() function to command that all subsequent spawning
|
-- If only the first spawning should happen on the carrier, one use the @{#RECOVERYTANKER.SetRespawnInAir}() function to command that all subsequent spawning
|
||||||
-- will happen in air.
|
-- will happen in air.
|
||||||
--
|
--
|
||||||
-- If the helo should no be respawned at all, one can set @{#RECOVERYTANKER.SetRespawnOff}().
|
-- If the helo should not be respawned at all, one can set @{#RECOVERYTANKER.SetRespawnOff}().
|
||||||
--
|
--
|
||||||
-- ## Adjusting the Pattern
|
-- ## Pattern Parameters
|
||||||
--
|
--
|
||||||
-- The racetrack pattern parameters can be fine tuned via the following functions:
|
-- The racetrack pattern parameters can be fine tuned via the following functions:
|
||||||
--
|
--
|
||||||
@ -114,10 +116,69 @@
|
|||||||
-- * @{#RECOVERYTANKER.SetSpeed}(*speed*), where *speed* is the pattern speed in knots. Default is 272 knots.
|
-- * @{#RECOVERYTANKER.SetSpeed}(*speed*), where *speed* is the pattern speed in knots. Default is 272 knots.
|
||||||
-- * @{#RECOVERYTANKER.SetRacetrackDistances}(*distbow*, *diststern*), where *distbow* and *diststern* are the distances ahead and astern the boat, respectively.
|
-- * @{#RECOVERYTANKER.SetRacetrackDistances}(*distbow*, *diststern*), where *distbow* and *diststern* are the distances ahead and astern the boat, respectively.
|
||||||
--
|
--
|
||||||
|
-- ## TACAN
|
||||||
|
--
|
||||||
|
-- A TACAN beacon for the tanker can be activated via scripting, i.e. no need to do this within the mission editor.
|
||||||
|
--
|
||||||
|
-- The beacon is create with the @{#RECOVERYTANKER.SetTACAN}(*channel*, *mode*, *morse*) function, where *channel* is the TACAN channel (a number), *mode* the TACAN mode (either "X"
|
||||||
|
-- or "Y") and *morse* a three letter string that is send as morse code to identify the tanker:
|
||||||
|
--
|
||||||
|
-- TexacoStennis:SetTACAN(10, "Y", "TKR")
|
||||||
|
--
|
||||||
|
-- will activate a TACAN beacon 10Y with more code "TKR".
|
||||||
|
--
|
||||||
|
-- If you do not set a TACAN beacon explicitly, it is automatically create on channel 1, mode "Y" and morse code "TKR".
|
||||||
|
--
|
||||||
|
-- In order to completely disable the TACAN beacon, you can use the @{#RECOVERYTANKER.SetTACANoff}() function in your script.
|
||||||
|
--
|
||||||
|
-- Note to self, I am not sure, if an AA TACAN station *must* be of mode "Y" in order to work. It seems that this was the case in earlier DCS versions.
|
||||||
|
--
|
||||||
|
-- ## Pattern Update
|
||||||
|
--
|
||||||
|
-- The pattern of the tanker is updated if at least one of the two following conditions apply:
|
||||||
|
--
|
||||||
|
-- * The aircraft carrier changes its position by more than ~10 km (see @{#RECOVERYTANKER.SetPatternUpdateDistance}) and/or
|
||||||
|
-- * The aircraft carrier changes its heading by more than 5 degrees (see @{#RECOVERYTANKER.SetPatternUpdateHeading})
|
||||||
|
--
|
||||||
|
-- **Note** that updating the pattern always leads to a small disruption in the perfect racetrack pattern of the tanker. This is because a new waypoint and new racetrack points
|
||||||
|
-- need to be set as DCS task. This is also the reason why the pattern is not contantly updated but rather when the position or heading of the carrier changes significantly.
|
||||||
|
--
|
||||||
|
-- The maximum update frequency is set to 15 minutes. You can adjust this by @{#RECOVERYTANKER.SetPatternUpdateInterval}.
|
||||||
|
--
|
||||||
|
-- # Finite State Model
|
||||||
|
--
|
||||||
|
-- The implementation uses a Finite State Model (FSM). This allows the mission designer to hook in to certain events.
|
||||||
|
--
|
||||||
|
-- * @{#RECOVERYTANKER.Start}: This event starts the FMS process and initialized parameters and spawns the tanker. DCS event handling is started.
|
||||||
|
-- * @{#RECOVERYTANKER.Status}: This event is called in regular intervals (~60 seconds) and checks the status of the tanker and carrier. It triggers other events if necessary.
|
||||||
|
-- * @{#RECOVERYTANKER.PatternUpdate}: This event commands the tanker to update its pattern
|
||||||
|
-- * @{#RECOVERYTANKER.RTB}: This events sends the tanker to its home base (usually the carrier). This is called once the tanker runs low on gas.
|
||||||
|
-- * @{#RECOVERYTANKER.RefuelStart}: This event is called when a tanker starts to refuel another unit.
|
||||||
|
-- * @{#RECOVERYTANKER.RefuelStop}: This event is called when a tanker stopped to refuel another unit.
|
||||||
|
-- * @{#RECOVERYTANKER.Run}: This event is called when the tanker resumes normal operations, e.g. after refueling stopped or tanker finished refueling.
|
||||||
|
-- * @{#RECOVERYTANKER.Stop}: This event stops the FSM by unhandling DCS events.
|
||||||
|
--
|
||||||
|
-- The mission designer can capture these events by RECOVERYTANKER.OnAfter*Eventname* functions, e.g. @{#RECOVERYTANKER.OnAfterPatternUpdate}.
|
||||||
|
--
|
||||||
|
-- # Debugging
|
||||||
|
--
|
||||||
|
-- In case you have problems, it is always a good idea to have a look at your DCS log file. You find it in your "Saved Games" folder, so for example in
|
||||||
|
-- C:\Users\<yourname>\Saved Games\DCS\Logs\dcs.log
|
||||||
|
-- All output concerning the @{#RECOVERYTANKER} class should have the string "RECOVERYTANKER" in the corresponding line.
|
||||||
|
-- Searching for lines that contain the string "error" or "nil" can also give you a hint what's wrong.
|
||||||
|
--
|
||||||
|
-- The verbosity of the output can be increased by adding the following lines to your script:
|
||||||
|
--
|
||||||
|
-- BASE:TraceOnOff(true)
|
||||||
|
-- BASE:TraceLevel(1)
|
||||||
|
-- BASE:TraceClass("RECOVERYTANKER")
|
||||||
|
--
|
||||||
|
-- To get even more output you can increase the trace level to 2 or even 3, c.f. @{Core.Base#BASE} for more details.
|
||||||
|
--
|
||||||
-- @field #RECOVERYTANKER
|
-- @field #RECOVERYTANKER
|
||||||
RECOVERYTANKER = {
|
RECOVERYTANKER = {
|
||||||
ClassName = "RECOVERYTANKER",
|
ClassName = "RECOVERYTANKER",
|
||||||
Debug = true,
|
Debug = false,
|
||||||
carrier = nil,
|
carrier = nil,
|
||||||
carriertype = nil,
|
carriertype = nil,
|
||||||
tankergroupname = nil,
|
tankergroupname = nil,
|
||||||
@ -133,6 +194,8 @@ RECOVERYTANKER = {
|
|||||||
distStern = nil,
|
distStern = nil,
|
||||||
distBow = nil,
|
distBow = nil,
|
||||||
dTupdate = nil,
|
dTupdate = nil,
|
||||||
|
Dupdate = nil,
|
||||||
|
Hupdate = nil,
|
||||||
Tupdate = nil,
|
Tupdate = nil,
|
||||||
takeoff = nil,
|
takeoff = nil,
|
||||||
lowfuel = nil,
|
lowfuel = nil,
|
||||||
@ -145,16 +208,18 @@ RECOVERYTANKER = {
|
|||||||
|
|
||||||
--- Class version.
|
--- Class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
RECOVERYTANKER.version="0.9.4"
|
RECOVERYTANKER.version="0.9.4w"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- TODO list
|
-- TODO list
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-- TODO: Check if TACAN mode "X" is allowed for AA TACAN stations.
|
||||||
|
-- TODO: Check if tanker is going back to "Running" state after RTB and respawn.
|
||||||
-- TODO: Is alive check for tanker.
|
-- TODO: Is alive check for tanker.
|
||||||
-- TODO: Trace functions self:T instead of self:I for less output.
|
-- DONE: Write documenation.
|
||||||
-- TODO: Make pattern update parameters (distance, orientation) input parameters.
|
-- DONE: Trace functions self:T instead of self:I for less output.
|
||||||
-- TODO: Write documenation.
|
-- DONE: Make pattern update parameters (distance, orientation) input parameters.
|
||||||
-- DONE: Add FSM event for pattern update.
|
-- DONE: Add FSM event for pattern update.
|
||||||
-- DONE: Smarter pattern update function. E.g. (small) zone around carrier. Only update position when carrier leaves zone or changes heading?
|
-- DONE: Smarter pattern update function. E.g. (small) zone around carrier. Only update position when carrier leaves zone or changes heading?
|
||||||
-- DONE: Set AA TACAN.
|
-- DONE: Set AA TACAN.
|
||||||
@ -191,7 +256,6 @@ function RECOVERYTANKER:New(carrierunit, tankergroupname)
|
|||||||
self.carrier:SetState(self.carrier, "RECOVERYTANKER", self)
|
self.carrier:SetState(self.carrier, "RECOVERYTANKER", self)
|
||||||
|
|
||||||
-- Init default parameters.
|
-- Init default parameters.
|
||||||
self:SetPatternUpdateInterval()
|
|
||||||
self:SetAltitude()
|
self:SetAltitude()
|
||||||
self:SetSpeed()
|
self:SetSpeed()
|
||||||
self:SetRacetrackDistances(6, 8)
|
self:SetRacetrackDistances(6, 8)
|
||||||
@ -200,6 +264,9 @@ function RECOVERYTANKER:New(carrierunit, tankergroupname)
|
|||||||
self:SetLowFuelThreshold()
|
self:SetLowFuelThreshold()
|
||||||
self:SetRespawnOnOff()
|
self:SetRespawnOnOff()
|
||||||
self:SetTACAN()
|
self:SetTACAN()
|
||||||
|
self:SetPatternUpdateDistance()
|
||||||
|
self:SetPatternUpdateHeading()
|
||||||
|
self:SetPatternUpdateInterval()
|
||||||
|
|
||||||
-----------------------
|
-----------------------
|
||||||
--- FSM Transitions ---
|
--- FSM Transitions ---
|
||||||
@ -211,7 +278,8 @@ function RECOVERYTANKER:New(carrierunit, tankergroupname)
|
|||||||
-- Add FSM transitions.
|
-- Add FSM transitions.
|
||||||
-- From State --> Event --> To State
|
-- From State --> Event --> To State
|
||||||
self:AddTransition("Stopped", "Start", "Running") -- Start the FSM.
|
self:AddTransition("Stopped", "Start", "Running") -- Start the FSM.
|
||||||
self:AddTransition("*", "Refuel", "Refueling") -- Tanker starts to refuel.
|
self:AddTransition("*", "RefuelStart", "Refueling") -- Tanker has started to refuel another unit.
|
||||||
|
self:AddTransition("*", "RefuelStop", "Running") -- Tanker starts to refuel.
|
||||||
self:AddTransition("*", "Run", "Running") -- Tanker starts normal operation again.
|
self:AddTransition("*", "Run", "Running") -- Tanker starts normal operation again.
|
||||||
self:AddTransition("Running", "RTB", "Returning") -- Tanker is returning to base (for fuel).
|
self:AddTransition("Running", "RTB", "Returning") -- Tanker is returning to base (for fuel).
|
||||||
self:AddTransition("*", "Status", "*") -- Status update.
|
self:AddTransition("*", "Status", "*") -- Status update.
|
||||||
@ -229,23 +297,39 @@ function RECOVERYTANKER:New(carrierunit, tankergroupname)
|
|||||||
-- @param #number delay Delay in seconds.
|
-- @param #number delay Delay in seconds.
|
||||||
|
|
||||||
|
|
||||||
--- Triggers the FSM event "Refuel" when the tanker is refueling another aircraft.
|
--- Triggers the FSM event "RefuelStart" when the tanker starts refueling another aircraft.
|
||||||
-- @function [parent=#RECOVERYTANKER] Refuel
|
-- @function [parent=#RECOVERYTANKER] RefuelStart
|
||||||
-- @param #RECOVERYTANKER self
|
-- @param #RECOVERYTANKER self
|
||||||
-- @param Wrapper.Unit#UNIT receiver Unit receiving fuel from the tanker.
|
-- @param Wrapper.Unit#UNIT receiver Unit receiving fuel from the tanker.
|
||||||
|
|
||||||
--- Triggers delayed the FSM event "Refuel" when the tanker is refueling another aircraft.
|
--- On after "RefuelStart" event user function. Called when a the the tanker started to refuel another unit.
|
||||||
-- @function [parent=#RECOVERYTANKER] __Refuel
|
-- @function [parent=#RECOVERYTANKER] OnAfterRefuelStart
|
||||||
-- @param #RECOVERYTANKER self
|
-- @param #RECOVERYTANKER self
|
||||||
-- @param #number delay Delay in seconds.
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To To state.
|
||||||
-- @param Wrapper.Unit#UNIT receiver Unit receiving fuel from the tanker.
|
-- @param Wrapper.Unit#UNIT receiver Unit receiving fuel from the tanker.
|
||||||
|
|
||||||
|
|
||||||
--- Triggers the FSM event "Run". Simply puts the group into "Running" state, e.g. after refueling ended.
|
--- Triggers the FSM event "RefuelStop" when the tanker stops refueling another aircraft.
|
||||||
|
-- @function [parent=#RECOVERYTANKER] RefuelStop
|
||||||
|
-- @param #RECOVERYTANKER self
|
||||||
|
-- @param Wrapper.Unit#UNIT receiver Unit stoped receiving fuel from the tanker.
|
||||||
|
|
||||||
|
--- On after "RefuelStop" event user function. Called when a the the tanker stopped to refuel another unit.
|
||||||
|
-- @function [parent=#RECOVERYTANKER] OnAfterRefuelStop
|
||||||
|
-- @param #RECOVERYTANKER self
|
||||||
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To To state.
|
||||||
|
-- @param Wrapper.Unit#UNIT receiver Unit that received fuel from the tanker.
|
||||||
|
|
||||||
|
|
||||||
|
--- Triggers the FSM event "Run". Simply puts the group into "Running" state.
|
||||||
-- @function [parent=#RECOVERYTANKER] Run
|
-- @function [parent=#RECOVERYTANKER] Run
|
||||||
-- @param #RECOVERYTANKER self
|
-- @param #RECOVERYTANKER self
|
||||||
|
|
||||||
--- Triggers delayed the FSM event "Run". Simply puts the group into "Running" state, e.g. after refueling ended.
|
--- Triggers delayed the FSM event "Run". Simply puts the group into "Running" state.
|
||||||
-- @function [parent=#RECOVERYTANKER] __Run
|
-- @function [parent=#RECOVERYTANKER] __Run
|
||||||
-- @param #RECOVERYTANKER self
|
-- @param #RECOVERYTANKER self
|
||||||
-- @param #number delay Delay in seconds.
|
-- @param #number delay Delay in seconds.
|
||||||
@ -262,6 +346,14 @@ function RECOVERYTANKER:New(carrierunit, tankergroupname)
|
|||||||
-- @param #number delay Delay in seconds.
|
-- @param #number delay Delay in seconds.
|
||||||
-- @param Wrapper.Airbase#AIRBASE airbase The airbase where the tanker should return to.
|
-- @param Wrapper.Airbase#AIRBASE airbase The airbase where the tanker should return to.
|
||||||
|
|
||||||
|
--- On after "RTB" event user function. Called when a the the tanker returns to its home base.
|
||||||
|
-- @function [parent=#RECOVERYTANKER] OnAfterPatternUpdate
|
||||||
|
-- @param #RECOVERYTANKER self
|
||||||
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To To state.
|
||||||
|
-- @param Wrapper.Airbase#AIRBASE airbase The airbase where the tanker should return to.
|
||||||
|
|
||||||
|
|
||||||
--- Triggers the FSM event "Status" that updates the tanker status.
|
--- Triggers the FSM event "Status" that updates the tanker status.
|
||||||
-- @function [parent=#RECOVERYTANKER] Status
|
-- @function [parent=#RECOVERYTANKER] Status
|
||||||
@ -282,6 +374,13 @@ function RECOVERYTANKER:New(carrierunit, tankergroupname)
|
|||||||
-- @param #RECOVERYTANKER self
|
-- @param #RECOVERYTANKER self
|
||||||
-- @param #number delay Delay in seconds.
|
-- @param #number delay Delay in seconds.
|
||||||
|
|
||||||
|
--- On after "PatternEvent" event user function. Called when a the pattern of the tanker is updated.
|
||||||
|
-- @function [parent=#RECOVERYTANKER] OnAfterPatternUpdate
|
||||||
|
-- @param #RECOVERYTANKER self
|
||||||
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To To state.
|
||||||
|
|
||||||
|
|
||||||
--- Triggers the FSM event "Stop" that stops the recovery tanker. Event handlers are stopped.
|
--- Triggers the FSM event "Stop" that stops the recovery tanker. Event handlers are stopped.
|
||||||
-- @function [parent=#RECOVERYTANKER] Stop
|
-- @function [parent=#RECOVERYTANKER] Stop
|
||||||
@ -328,22 +427,39 @@ function RECOVERYTANKER:SetRacetrackDistances(distbow, diststern)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Set pattern update interval. Note that this update causes a slight disruption in the race track pattern.
|
--- Set minimum pattern update interval. After a pattern update this time interval has to pass before the next update is allowed.
|
||||||
-- Therefore, the interval should be as long as possible but short enough to keep the tanker overhead the carrier.
|
|
||||||
-- @param #RECOVERYTANKER self
|
-- @param #RECOVERYTANKER self
|
||||||
-- @param #number interval Interval in minutes. Default is every 30 minutes.
|
-- @param #number interval Min interval in minutes. Default is 15 minutes.
|
||||||
-- @return #RECOVERYTANKER self
|
-- @return #RECOVERYTANKER self
|
||||||
function RECOVERYTANKER:SetPatternUpdateInterval(interval)
|
function RECOVERYTANKER:SetPatternUpdateInterval(interval)
|
||||||
self.dTupdate=(interval or 30)*60
|
self.dTupdate=(interval or 15)*60
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set pattern update distance. Tanker will update its pattern when the carrier changes its position by more than this distance.
|
||||||
|
-- @param #RECOVERYTANKER self
|
||||||
|
-- @param #number distancechange Distance threshold in km. Default 9.62 km (= 5 NM).
|
||||||
|
-- @return #RECOVERYTANKER self
|
||||||
|
function RECOVERYTANKER:SetPatternUpdateDistance(distancechange)
|
||||||
|
self.Dupdate=(distancechange or 9.62)*1000
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set pattern update heading. Tanker will update its pattern when the carrier changes its heading by more than this value.
|
||||||
|
-- @param #RECOVERYTANKER self
|
||||||
|
-- @param #number headingchange Heading threshold in degrees. Default 5 degrees.
|
||||||
|
-- @return #RECOVERYTANKER self
|
||||||
|
function RECOVERYTANKER:SetPatternUpdateHeading(headingchange)
|
||||||
|
self.Hupdate=headingchange or 5
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Set low fuel state of tanker. When fuel is below this threshold, the tanker will RTB or be respawned if takeoff type is in air.
|
--- Set low fuel state of tanker. When fuel is below this threshold, the tanker will RTB or be respawned if takeoff type is in air.
|
||||||
-- @param #RECOVERYTANKER self
|
-- @param #RECOVERYTANKER self
|
||||||
-- @param #number threshold Low fuel threshold in percent. Default 10.
|
-- @param #number fuelthreshold Low fuel threshold in percent. Default 10 %.
|
||||||
-- @return #RECOVERYTANKER self
|
-- @return #RECOVERYTANKER self
|
||||||
function RECOVERYTANKER:SetLowFuelThreshold(threshold)
|
function RECOVERYTANKER:SetLowFuelThreshold(fuelthreshold)
|
||||||
self.lowfuel=threshold or 10
|
self.lowfuel=fuelthreshold or 10
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -381,7 +497,7 @@ function RECOVERYTANKER:SetTakeoffCold()
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Set takeoff in air at pattern altitude 30 NM behind the carrier.
|
--- Set takeoff in air at the defined pattern altitude and 20 NM astern the carrier.
|
||||||
-- @param #RECOVERYTANKER self
|
-- @param #RECOVERYTANKER self
|
||||||
-- @return #RECOVERYTANKER self
|
-- @return #RECOVERYTANKER self
|
||||||
function RECOVERYTANKER:SetTakeoffAir()
|
function RECOVERYTANKER:SetTakeoffAir()
|
||||||
@ -389,7 +505,6 @@ function RECOVERYTANKER:SetTakeoffAir()
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Enable respawning of tanker. Note that this is the default behaviour.
|
--- Enable respawning of tanker. Note that this is the default behaviour.
|
||||||
-- @param #RECOVERYTANKER self
|
-- @param #RECOVERYTANKER self
|
||||||
-- @return #RECOVERYTANKER self
|
-- @return #RECOVERYTANKER self
|
||||||
@ -483,6 +598,13 @@ function RECOVERYTANKER:IsRefueling()
|
|||||||
return self:is("Refueling")
|
return self:is("Refueling")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Check if FMS was stopped.
|
||||||
|
-- @param #RECOVERYTANKER self
|
||||||
|
-- @return #boolean If true, is stopped.
|
||||||
|
function RECOVERYTANKER:IsStopped()
|
||||||
|
return self:is("Stopped")
|
||||||
|
end
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- FSM states
|
-- FSM states
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
@ -524,8 +646,6 @@ function RECOVERYTANKER:onafterStart(From, Event, To)
|
|||||||
-- Spawn at coordinate.
|
-- Spawn at coordinate.
|
||||||
self.tanker=Spawn:SpawnFromCoordinate(Carrier)
|
self.tanker=Spawn:SpawnFromCoordinate(Carrier)
|
||||||
|
|
||||||
-- Initial route.
|
|
||||||
self:_InitRoute(15, 1)
|
|
||||||
else
|
else
|
||||||
|
|
||||||
-- Check if an uncontrolled tanker group was requested.
|
-- Check if an uncontrolled tanker group was requested.
|
||||||
@ -552,11 +672,11 @@ function RECOVERYTANKER:onafterStart(From, Event, To)
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
-- Initialize route.
|
-- Initialize route.
|
||||||
self:_InitRoute(15, 1)
|
self:_InitRoute(15, 1)
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Create tanker beacon.
|
-- Create tanker beacon.
|
||||||
if self.TACANon then
|
if self.TACANon then
|
||||||
self:_ActivateTACAN(2)
|
self:_ActivateTACAN(2)
|
||||||
@ -566,7 +686,7 @@ function RECOVERYTANKER:onafterStart(From, Event, To)
|
|||||||
self.orientation=self.carrier:GetOrientationX()
|
self.orientation=self.carrier:GetOrientationX()
|
||||||
self.position=self.carrier:GetCoordinate()
|
self.position=self.carrier:GetCoordinate()
|
||||||
|
|
||||||
-- Init status check.
|
-- Init status updates in 10 seconds.
|
||||||
self:__Status(10)
|
self:__Status(10)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -584,7 +704,7 @@ function RECOVERYTANKER:onafterStatus(From, Event, To)
|
|||||||
-- Get fuel of tanker.
|
-- Get fuel of tanker.
|
||||||
local fuel=self.tanker:GetFuel()*100
|
local fuel=self.tanker:GetFuel()*100
|
||||||
local text=string.format("Recovery tanker %s: state=%s fuel=%.1f", self.tanker:GetName(), self:GetState(), fuel)
|
local text=string.format("Recovery tanker %s: state=%s fuel=%.1f", self.tanker:GetName(), self:GetState(), fuel)
|
||||||
self:I(text)
|
self:T(text)
|
||||||
|
|
||||||
-- Check if tanker is running and not RTBing or refueling.
|
-- Check if tanker is running and not RTBing or refueling.
|
||||||
if self:IsRunning() then
|
if self:IsRunning() then
|
||||||
@ -599,8 +719,8 @@ function RECOVERYTANKER:onafterStatus(From, Event, To)
|
|||||||
if self.respawn then
|
if self.respawn then
|
||||||
|
|
||||||
-- Debug message.
|
-- Debug message.
|
||||||
local text=string.format("Respawning tanker %s.", self.tanker:GetName())
|
local text=string.format("Respawning recovery tanker %s in air.", self.tanker:GetName())
|
||||||
self:I(text)
|
self:T(text)
|
||||||
|
|
||||||
-- Respawn tanker.
|
-- Respawn tanker.
|
||||||
self.tanker:InitHeading(self.tanker:GetHeading())
|
self.tanker:InitHeading(self.tanker:GetHeading())
|
||||||
@ -643,7 +763,9 @@ function RECOVERYTANKER:onafterStatus(From, Event, To)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Call status again in 1 minute.
|
-- Call status again in 1 minute.
|
||||||
|
if not self:IsStopped() then
|
||||||
self:__Status(-60)
|
self:__Status(-60)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- On after "PatternUpdate" event. Updates the racetrack pattern of the tanker wrt the carrier position.
|
--- On after "PatternUpdate" event. Updates the racetrack pattern of the tanker wrt the carrier position.
|
||||||
@ -654,7 +776,7 @@ end
|
|||||||
function RECOVERYTANKER:onafterPatternUpdate(From, Event, To)
|
function RECOVERYTANKER:onafterPatternUpdate(From, Event, To)
|
||||||
|
|
||||||
-- Debug message.
|
-- Debug message.
|
||||||
self:I(string.format("Updating recovery tanker %s orbit.", self.tanker:GetName()))
|
self:T(string.format("Updating recovery tanker %s orbit.", self.tanker:GetName()))
|
||||||
|
|
||||||
-- Carrier heading.
|
-- Carrier heading.
|
||||||
local hdg=self.carrier:GetHeading()
|
local hdg=self.carrier:GetHeading()
|
||||||
@ -675,7 +797,6 @@ function RECOVERYTANKER:onafterPatternUpdate(From, Event, To)
|
|||||||
p0:MarkToAll("Waypoint P0 " ..self.tanker:GetName())
|
p0:MarkToAll("Waypoint P0 " ..self.tanker:GetName())
|
||||||
p1:MarkToAll("Racetrack P1 "..self.tanker:GetName())
|
p1:MarkToAll("Racetrack P1 "..self.tanker:GetName())
|
||||||
p2:MarkToAll("Racetrack P2 "..self.tanker:GetName())
|
p2:MarkToAll("Racetrack P2 "..self.tanker:GetName())
|
||||||
self.tanker:SmokeRed()
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Waypoints array.
|
-- Waypoints array.
|
||||||
@ -713,15 +834,15 @@ function RECOVERYTANKER:onafterRTB(From, Event, To, airbase)
|
|||||||
airbase=airbase or self.airbase
|
airbase=airbase or self.airbase
|
||||||
|
|
||||||
-- Debug message.
|
-- Debug message.
|
||||||
local text=string.format("Tanker %s returning to airbase %s.", self.tanker:GetName(), airbase:GetName())
|
local text=string.format("Recoery tanker %s returning to airbase %s.", self.tanker:GetName(), airbase:GetName())
|
||||||
self:I(text)
|
self:T(text)
|
||||||
|
|
||||||
-- Waypoint array.
|
-- Waypoint array.
|
||||||
local wp={}
|
local wp={}
|
||||||
|
|
||||||
-- Set landing waypoint.
|
-- Set landing waypoint.
|
||||||
wp[1]=self.tanker:GetCoordinate():WaypointAirTurningPoint(nil, 300, {}, "Current Position")
|
wp[1]=self.tanker:GetCoordinate():WaypointAirTurningPoint(nil, 300, {}, "Current Position")
|
||||||
wp[2]=airbase:GetCoordinate():WaypointAirLanding(300, airbase, nil, "Land at airbase")
|
wp[2]=airbase:GetCoordinate():SetAltitude(500):WaypointAirLanding(300, airbase, nil, "Land at airbase")
|
||||||
|
|
||||||
-- Initialize WP and route tanker.
|
-- Initialize WP and route tanker.
|
||||||
self.tanker:WayPointInitialize(wp)
|
self.tanker:WayPointInitialize(wp)
|
||||||
@ -763,7 +884,7 @@ function RECOVERYTANKER:OnEventEngineShutdown(EventData)
|
|||||||
if groupname:match(self.tankergroupname) then
|
if groupname:match(self.tankergroupname) then
|
||||||
|
|
||||||
-- Debug info.
|
-- Debug info.
|
||||||
self:I(string.format("Respawning recovery tanker group %s.", group:GetName()))
|
self:T(string.format("Respawning recovery tanker group %s.", group:GetName()))
|
||||||
|
|
||||||
-- Respawn tanker.
|
-- Respawn tanker.
|
||||||
self.tanker=group:RespawnAtCurrentAirbase()
|
self.tanker=group:RespawnAtCurrentAirbase()
|
||||||
@ -799,10 +920,10 @@ function RECOVERYTANKER:_RefuelingStart(EventData)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Info message.
|
-- Info message.
|
||||||
self:I(string.format("Recovery tanker %s started refueling unit %s", self.tanker:GetName(), unit:GetName()))
|
self:T(string.format("Recovery tanker %s started refueling unit %s", self.tanker:GetName(), unit:GetName()))
|
||||||
|
|
||||||
-- FMS state "Refueling".
|
-- FMS state "Refueling".
|
||||||
self:Refuel(unit)
|
self:RefuelStart(receiver)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -827,10 +948,10 @@ function RECOVERYTANKER:_RefuelingStop(EventData)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Info message.
|
-- Info message.
|
||||||
self:I(string.format("Recovery tanker %s stopped refueling unit %s", self.tanker:GetName(), unit:GetName()))
|
self:T(string.format("Recovery tanker %s stopped refueling unit %s", self.tanker:GetName(), unit:GetName()))
|
||||||
|
|
||||||
-- FSM state "Running".
|
-- FSM state "Running".
|
||||||
self:Run()
|
self:RefuelStop(unit)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
@ -871,7 +992,7 @@ function RECOVERYTANKER:_InitRoute(dist, delay)
|
|||||||
delay=delay or 1
|
delay=delay or 1
|
||||||
|
|
||||||
-- Debug message.
|
-- Debug message.
|
||||||
self:I(string.format("Initializing route for recovery tanker %s.", self.tanker:GetName()))
|
self:T(string.format("Initializing route for recovery tanker %s.", self.tanker:GetName()))
|
||||||
|
|
||||||
-- Carrier position.
|
-- Carrier position.
|
||||||
local Carrier=self.carrier:GetCoordinate()
|
local Carrier=self.carrier:GetCoordinate()
|
||||||
@ -902,6 +1023,9 @@ function RECOVERYTANKER:_InitRoute(dist, delay)
|
|||||||
-- Set route.
|
-- Set route.
|
||||||
self.tanker:Route(wp, delay)
|
self.tanker:Route(wp, delay)
|
||||||
|
|
||||||
|
-- Set state to Running. Necessary when tanker was RTB and respawned since it is probably in state "Returning".
|
||||||
|
self:__Run(1)
|
||||||
|
|
||||||
-- No update yet, wait until the function is called (avoids checks if pattern update is needed).
|
-- No update yet, wait until the function is called (avoids checks if pattern update is needed).
|
||||||
self.Tupdate=nil
|
self.Tupdate=nil
|
||||||
end
|
end
|
||||||
@ -920,7 +1044,7 @@ function RECOVERYTANKER:_CheckPatternUpdate(dt)
|
|||||||
local vC=self.carrier:GetOrientationX()
|
local vC=self.carrier:GetOrientationX()
|
||||||
|
|
||||||
-- Check if tanker is running and last updated is more than 10 minutes ago.
|
-- Check if tanker is running and last updated is more than 10 minutes ago.
|
||||||
if self:IsRunning() and dt>10*60 then
|
if self:IsRunning() and dt>self.dTupdate then
|
||||||
|
|
||||||
-- Last saved orientation of carrier.
|
-- Last saved orientation of carrier.
|
||||||
local vP=self.orientation
|
local vP=self.orientation
|
||||||
@ -932,19 +1056,17 @@ function RECOVERYTANKER:_CheckPatternUpdate(dt)
|
|||||||
local rhdg=math.deg(math.acos(UTILS.VecDot(vC,vP)/UTILS.VecNorm(vC)/UTILS.VecNorm(vP)))
|
local rhdg=math.deg(math.acos(UTILS.VecDot(vC,vP)/UTILS.VecNorm(vC)/UTILS.VecNorm(vP)))
|
||||||
|
|
||||||
-- Check if orientation changed.
|
-- Check if orientation changed.
|
||||||
-- TODO: make 5 deg input variable.
|
if math.abs(rhdg)>self.Hupdate then
|
||||||
if math.abs(rhdg)>5 then
|
self:T(string.format("Carrier heading changed by %d degrees. Updating recovery tanker pattern.", rhdg))
|
||||||
self:I(string.format("Carrier heading changed by %d degrees. Updating recovery tanker pattern.", rhdg))
|
|
||||||
update=true
|
update=true
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Get distance to saved position.
|
-- Get distance to saved position.
|
||||||
local dist=pos:Get2DDistance(self.position)
|
local dist=pos:Get2DDistance(self.position)
|
||||||
|
|
||||||
-- Check if carrier moved more than 10 km.
|
-- Check if carrier moved more than ~10 km.
|
||||||
-- TODO: make 10 km input variable.
|
if dist>self.Dupdate then
|
||||||
if dist/1000>10 then
|
self:T(string.format("Carrier position changed by %.1f km. Updating recovery tanker pattern.", dist/1000))
|
||||||
self:I(string.format("Carrier position changed by %.1f km. Updating recovery tanker pattern.", dist/1000))
|
|
||||||
update=true
|
update=true
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -979,7 +1101,7 @@ function RECOVERYTANKER:_ActivateTACAN(delay)
|
|||||||
if unit:IsAlive() then
|
if unit:IsAlive() then
|
||||||
|
|
||||||
-- Debug message.
|
-- Debug message.
|
||||||
self:I(string.format("Activating recovery tanker TACAN beacon: channel=%d mode=%s, morse=%s.", self.TACANchannel, self.TACANmode, self.TACANmorse))
|
self:T(string.format("Activating recovery tanker TACAN beacon: channel=%d mode=%s, morse=%s.", self.TACANchannel, self.TACANmode, self.TACANmorse))
|
||||||
|
|
||||||
-- Create a new beacon and activate TACAN.
|
-- Create a new beacon and activate TACAN.
|
||||||
self.beacon=BEACON:New(unit)
|
self.beacon=BEACON:New(unit)
|
||||||
|
|||||||
@ -84,7 +84,7 @@
|
|||||||
--
|
--
|
||||||
-- The implementation allows to customize quite a few settings easily
|
-- The implementation allows to customize quite a few settings easily
|
||||||
--
|
--
|
||||||
-- ## Adjusting the Takeoff Type
|
-- ## Takeoff Type
|
||||||
--
|
--
|
||||||
-- By default, the helo is spawned with running engies on the carrier. The mission designer has set option to set the take off type via the @{#RESCUEHELO.SetTakeoff} function.
|
-- By default, the helo is spawned with running engies on the carrier. The mission designer has set option to set the take off type via the @{#RESCUEHELO.SetTakeoff} function.
|
||||||
-- Or via shortcuts
|
-- Or via shortcuts
|
||||||
@ -108,7 +108,7 @@
|
|||||||
--
|
--
|
||||||
-- If the helo should no be respawned at all, one can set @{#RESCUEHELO.SetRespawnOff}().
|
-- If the helo should no be respawned at all, one can set @{#RESCUEHELO.SetRespawnOff}().
|
||||||
--
|
--
|
||||||
-- ## Setting a Home Base
|
-- ## Home Base
|
||||||
--
|
--
|
||||||
-- It is possible to define a "home base" other than the aircaft carrier. For example, one could imagine a strike group, and the helo will be spawned from
|
-- It is possible to define a "home base" other than the aircaft carrier. For example, one could imagine a strike group, and the helo will be spawned from
|
||||||
-- another ship which has a helo pad.
|
-- another ship which has a helo pad.
|
||||||
@ -123,7 +123,7 @@
|
|||||||
-- Once the helo runs out of fuel, it will return to the USS Normandy and not the Stennis for respawning.
|
-- Once the helo runs out of fuel, it will return to the USS Normandy and not the Stennis for respawning.
|
||||||
--
|
--
|
||||||
--
|
--
|
||||||
-- # Adjusting the Formation Positon
|
-- ## Formation Positon
|
||||||
--
|
--
|
||||||
-- The position of the helo relative to the mother ship can be tuned via the functions
|
-- The position of the helo relative to the mother ship can be tuned via the functions
|
||||||
--
|
--
|
||||||
@ -162,14 +162,14 @@ RESCUEHELO = {
|
|||||||
|
|
||||||
--- Class version.
|
--- Class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
RESCUEHELO.version="0.9.4"
|
RESCUEHELO.version="0.9.4w"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- TODO list
|
-- TODO list
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
-- TODO: Add option to stop carrier while rescue operation is in progress?
|
|
||||||
-- TODO: Write documenation.
|
-- TODO: Write documenation.
|
||||||
|
-- TODO: Add option to stop carrier while rescue operation is in progress? Done but NOT working!
|
||||||
-- DONE: Add option to deactivate the rescueing.
|
-- DONE: Add option to deactivate the rescueing.
|
||||||
-- DONE: Possibility to add already present/spawned aircraft, e.g. for warehouse.
|
-- DONE: Possibility to add already present/spawned aircraft, e.g. for warehouse.
|
||||||
-- DONE: Add rescue event when aircraft crashes.
|
-- DONE: Add rescue event when aircraft crashes.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user