mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-08-15 10:47:21 +00:00
AIRBOSS v0.3.0
RESCUEHELO v0.9.2 RECOVERYTANKER v0.9.2
This commit is contained in:
parent
2feb293c12
commit
51a1f56011
@ -906,7 +906,7 @@ function AI_FORMATION:SetFlightRandomization( FlightRandomization ) --R2.1
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Follow event fuction. Check if coming from state "stopped". If so the transition is rejected.
|
--- Stop function. Formation will not be updated any more.
|
||||||
-- @param #AI_FORMATION self
|
-- @param #AI_FORMATION self
|
||||||
-- @param Core.Set#SET_GROUP FollowGroupSet The following set of groups.
|
-- @param Core.Set#SET_GROUP FollowGroupSet The following set of groups.
|
||||||
-- @param #string From From state.
|
-- @param #string From From state.
|
||||||
|
|||||||
@ -1132,7 +1132,7 @@ do -- COORDINATE
|
|||||||
-- HeliGroup:Route( { LandWaypoint }, 1 ) -- Start landing the helicopter in one second.
|
-- HeliGroup:Route( { LandWaypoint }, 1 ) -- Start landing the helicopter in one second.
|
||||||
--
|
--
|
||||||
function COORDINATE:WaypointAirLanding( Speed, airbase, DCSTasks, description )
|
function COORDINATE:WaypointAirLanding( Speed, airbase, DCSTasks, description )
|
||||||
return self:WaypointAir( nil, COORDINATE.WaypointType.Land, COORDINATE.WaypointAction.Landing, Speed, airbase, DCSTasks, description )
|
return self:WaypointAir(nil, COORDINATE.WaypointType.Land, COORDINATE.WaypointAction.Landing, Speed, nil, airbase, DCSTasks, description)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1790,7 +1790,7 @@ WAREHOUSE.version="0.6.6"
|
|||||||
|
|
||||||
--- The WAREHOUSE constructor. Creates a new WAREHOUSE object from a static object. Parameters like the coalition and country are taken from the static object structure.
|
--- The WAREHOUSE constructor. Creates a new WAREHOUSE object from a static object. Parameters like the coalition and country are taken from the static object structure.
|
||||||
-- @param #WAREHOUSE self
|
-- @param #WAREHOUSE self
|
||||||
-- @param Wrapper.Static#STATIC warehouse The physical structure of the warehouse.
|
-- @param Wrapper.Static#STATIC warehouse The physical structure representing the warehouse.
|
||||||
-- @param #string alias (Optional) Alias of the warehouse, i.e. the name it will be called when sending messages etc. Default is the name of the static
|
-- @param #string alias (Optional) Alias of the warehouse, i.e. the name it will be called when sending messages etc. Default is the name of the static
|
||||||
-- @return #WAREHOUSE self
|
-- @return #WAREHOUSE self
|
||||||
function WAREHOUSE:New(warehouse, alias)
|
function WAREHOUSE:New(warehouse, alias)
|
||||||
@ -1798,8 +1798,9 @@ function WAREHOUSE:New(warehouse, alias)
|
|||||||
|
|
||||||
-- Check if just a string was given and convert to static.
|
-- Check if just a string was given and convert to static.
|
||||||
if type(warehouse)=="string" then
|
if type(warehouse)=="string" then
|
||||||
warehouse=GROUP:FindByName(warehouse)
|
warehouse=UNIT:FindByName(warehouse)
|
||||||
if warehouse==nil then
|
if warehouse==nil then
|
||||||
|
env.info(string.format("FF no warehouse unit with name %s found trying static.", warehouse))
|
||||||
warehouse=STATIC:FindByName(warehouse, true)
|
warehouse=STATIC:FindByName(warehouse, true)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -10,11 +10,11 @@
|
|||||||
-- * Different skill levels from tipps on-the-fly for students to complete ziplip for pros.
|
-- * Different skill levels from tipps on-the-fly for students to complete ziplip for pros.
|
||||||
-- * Rescue helo option.
|
-- * Rescue helo option.
|
||||||
-- * Recovery tanker option.
|
-- * Recovery tanker option.
|
||||||
-- * Voice overs for LSO and AIRBOSS calls. Can easily customized by users.
|
-- * Voice overs for LSO and AIRBOSS calls. Can easily be customized by users.
|
||||||
-- * Automatic TACAN and ICLS channel setting.
|
-- * Automatic TACAN and ICLS channel setting.
|
||||||
-- * Different radio channels for LSO and airboss calls.
|
-- * Different radio channels for LSO and airboss calls.
|
||||||
-- * F10 radio menu including carrier info (weather, radio frequencies, TACAN/ICLS channels, LSO grades).
|
-- * F10 radio menu including carrier info (weather, radio frequencies, TACAN/ICLS channels, LSO grades).
|
||||||
-- * Multiple carriers supported.
|
-- * Multiple carriers supported (due to object oriented approach).
|
||||||
--
|
--
|
||||||
-- **PLEASE NOTE** that his class is work in progress and in an **alpha** stage.
|
-- **PLEASE NOTE** that his class is work in progress and in an **alpha** stage.
|
||||||
-- At the moment training parameters are optimized for F/A-18C Hornet as aircraft and USS John C. Stennis as carrier.
|
-- At the moment training parameters are optimized for F/A-18C Hornet as aircraft and USS John C. Stennis as carrier.
|
||||||
@ -68,6 +68,7 @@
|
|||||||
-- @field #table Qpattern Queue of aircraft groups in the landing pattern.
|
-- @field #table Qpattern Queue of aircraft groups in the landing pattern.
|
||||||
-- @field Ops.RescueHelo#RESCUEHELO rescuehelo Rescue helo flying in close formation with the carrier.
|
-- @field Ops.RescueHelo#RESCUEHELO rescuehelo Rescue helo flying in close formation with the carrier.
|
||||||
-- @field Ops.RecoveryTanker#RECOVERYTANKER tanker Recovery tanker flying overhead of carrier.
|
-- @field Ops.RecoveryTanker#RECOVERYTANKER tanker Recovery tanker flying overhead of carrier.
|
||||||
|
-- @field Functional.Warehouse#WAREHOUSE warehouse Warehouse object of the carrier.
|
||||||
-- @field #table recoverytime List of time intervals when aircraft are recovered.
|
-- @field #table recoverytime List of time intervals when aircraft are recovered.
|
||||||
-- @extends Core.Fsm#FSM
|
-- @extends Core.Fsm#FSM
|
||||||
|
|
||||||
@ -123,6 +124,7 @@ AIRBOSS = {
|
|||||||
Qmarshal = {},
|
Qmarshal = {},
|
||||||
rescuehelo = nil,
|
rescuehelo = nil,
|
||||||
tanker = nil,
|
tanker = nil,
|
||||||
|
warehouse = nil,
|
||||||
recoverytime = {},
|
recoverytime = {},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,6 +139,8 @@ AIRBOSS.AircraftPlayer={
|
|||||||
|
|
||||||
--- Aircraft types capable of landing on carrier (human+AI).
|
--- Aircraft types capable of landing on carrier (human+AI).
|
||||||
-- @type AIRBOSS.AircraftCarrier
|
-- @type AIRBOSS.AircraftCarrier
|
||||||
|
-- @field #string AV8B AV-8B Night Harrier.
|
||||||
|
-- @field #string HORNET F/A-18C Lot 20 Hornet.
|
||||||
-- @field #string S3B Lockheed S-3B Viking.
|
-- @field #string S3B Lockheed S-3B Viking.
|
||||||
-- @field #string S3BTANKER Lockheed S-3B Viking tanker.
|
-- @field #string S3BTANKER Lockheed S-3B Viking tanker.
|
||||||
-- @field #string E2D Grumman E-2D Hawkeye AWACS.
|
-- @field #string E2D Grumman E-2D Hawkeye AWACS.
|
||||||
@ -150,7 +154,7 @@ AIRBOSS.AircraftCarrier={
|
|||||||
E2D="E-2C",
|
E2D="E-2C",
|
||||||
FA18C="F/A-18C",
|
FA18C="F/A-18C",
|
||||||
F14A="F-14A",
|
F14A="F-14A",
|
||||||
--TODO: Add A-A4-E-C
|
--TODO: Add A4-E-C
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -417,12 +421,13 @@ AIRBOSS.MenuF10={}
|
|||||||
|
|
||||||
--- Airboss class version.
|
--- Airboss class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
AIRBOSS.version="0.2.9"
|
AIRBOSS.version="0.3.0"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- TODO list
|
-- TODO list
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-- TODO: Set case II and III times.
|
||||||
-- TODO: Get an _OK_ pass if long in groove. Possible other pattern wave offs as well?!
|
-- TODO: Get an _OK_ pass if long in groove. Possible other pattern wave offs as well?!
|
||||||
-- TODO: Add radio transmission queue for LSO and airboss.
|
-- TODO: Add radio transmission queue for LSO and airboss.
|
||||||
-- TODO: Get correct wire when trapped.
|
-- TODO: Get correct wire when trapped.
|
||||||
@ -459,7 +464,10 @@ AIRBOSS.version="0.2.9"
|
|||||||
function AIRBOSS:New(carriername, alias)
|
function AIRBOSS:New(carriername, alias)
|
||||||
|
|
||||||
-- Inherit everthing from FSM class.
|
-- Inherit everthing from FSM class.
|
||||||
local self = BASE:Inherit(self, FSM:New()) -- #AIRBOSS
|
local self=BASE:Inherit(self, FSM:New()) -- #AIRBOSS
|
||||||
|
|
||||||
|
-- Debug.
|
||||||
|
self:F2({carriername=carriername, alias=alias})
|
||||||
|
|
||||||
-- Set carrier unit.
|
-- Set carrier unit.
|
||||||
self.carrier=UNIT:FindByName(carriername)
|
self.carrier=UNIT:FindByName(carriername)
|
||||||
@ -515,8 +523,8 @@ function AIRBOSS:New(carriername, alias)
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Zone 3 NM astern and 100 m starboard of the carrier with radius of 2.0 km.
|
-- Zone 3 NM astern and 100 m starboard of the carrier with radius of 0.5 km.
|
||||||
self.zoneInitial=ZONE_UNIT:New("Initial Zone", self.carrier, 2.0*1000, {dx=-UTILS.NMToMeters(3), dy=100, relative_to_unit=true})
|
self.zoneInitial=ZONE_UNIT:New("Initial Zone", self.carrier, 0.5*1000, {dx=-UTILS.NMToMeters(3), dy=100, relative_to_unit=true})
|
||||||
|
|
||||||
-- CCA 50 NM radius zone around the carrier.
|
-- CCA 50 NM radius zone around the carrier.
|
||||||
self:SetCarrierControlledArea()
|
self:SetCarrierControlledArea()
|
||||||
@ -729,6 +737,35 @@ function AIRBOSS:SetCarrierradio(frequency, modulation)
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Define rescue helicopter associated with the carrier.
|
||||||
|
-- @param #AIRBOSS self
|
||||||
|
-- @param Ops.RescueHelo#RESCUEHELO rescuehelo Rescue helo object.
|
||||||
|
-- @return #ARIBOSS self
|
||||||
|
function AIRBOSS:SetRescueHelo(rescuehelo)
|
||||||
|
self.rescuehelo=rescuehelo
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Define recovery tanker associated with the carrier.
|
||||||
|
-- @param #AIRBOSS self
|
||||||
|
-- @param Ops.RecoveryTanker#RECOVERYTANKER recoverytanker Recovery tanker object.
|
||||||
|
-- @return #ARIBOSS self
|
||||||
|
function AIRBOSS:SetRecoveryTanker(recoverytanker)
|
||||||
|
self.tanker=recoverytanker
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Define warehouse associated with the carrier.
|
||||||
|
-- @param #AIRBOSS self
|
||||||
|
-- @param Functional.Warehouse#WAREHOUSE warehouse Warehouse object of the carrier.
|
||||||
|
-- @return #ARIBOSS self
|
||||||
|
function AIRBOSS:SetWarehouse(warehouse)
|
||||||
|
self.warehouse=warehouse
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Check if carrier is recovering aircraft.
|
--- Check if carrier is recovering aircraft.
|
||||||
-- @param #AIRBOSS self
|
-- @param #AIRBOSS self
|
||||||
-- @return #boolean If true, time slot for recovery is open.
|
-- @return #boolean If true, time slot for recovery is open.
|
||||||
@ -805,8 +842,8 @@ function AIRBOSS:onafterStatus(From, Event, To)
|
|||||||
-- Update marshal and pattern queue every 30 seconds.
|
-- Update marshal and pattern queue every 30 seconds.
|
||||||
if time-self.Tqueue>30 then
|
if time-self.Tqueue>30 then
|
||||||
|
|
||||||
local text=string.format("AIRBOSS %s: Status %s.", self.alias, self:GetState())
|
local text=string.format("Status %s.", self:GetState())
|
||||||
self:I(text)
|
self:I(self.lid..text)
|
||||||
|
|
||||||
-- Scan carrier zone for new aircraft.
|
-- Scan carrier zone for new aircraft.
|
||||||
self:_ScanCarrierZone()
|
self:_ScanCarrierZone()
|
||||||
@ -946,14 +983,15 @@ function AIRBOSS:_InitStennis()
|
|||||||
|
|
||||||
-- 4k descent from holding pattern to 5k platform
|
-- 4k descent from holding pattern to 5k platform
|
||||||
self.C3Descent4k.name="4k Descent"
|
self.C3Descent4k.name="4k Descent"
|
||||||
self.C3Descent4k.Xmin=-UTILS.NMToMeters(35)
|
self.C3Descent4k.Xmin=-UTILS.NMToMeters(50)
|
||||||
self.C3Descent4k.Xmax=-UTILS.NMToMeters(20)
|
self.C3Descent4k.Xmax=-UTILS.NMToMeters(20)
|
||||||
self.C3Descent4k.Zmin=-UTILS.NMToMeters(30)
|
self.C3Descent4k.Zmin=-UTILS.NMToMeters(10)
|
||||||
self.C3Descent4k.Zmax= UTILS.NMToMeters(30)
|
self.C3Descent4k.Zmax= UTILS.NMToMeters(3)
|
||||||
self.C3Descent4k.LimitXmin=nil
|
self.C3Descent4k.LimitXmin=nil
|
||||||
self.C3Descent4k.LimitXmax=-UTILS.NMToMeters(20) --TODO: better rho dist. decrease descent 20 2000 ft/min at 5000 ft alt and user rad alt.
|
self.C3Descent4k.LimitXmax=-UTILS.NMToMeters(20) --TODO: better rho dist. decrease descent 20 2000 ft/min at 5000 ft alt and user rad alt.
|
||||||
self.C3Descent4k.LimitZmin=nil
|
self.C3Descent4k.LimitZmin=nil
|
||||||
self.C3Descent4k.LimitZmax=nil
|
self.C3Descent4k.LimitZmax=nil
|
||||||
|
-- TODO: alt, AoA are more aircraft functions rather than carrier
|
||||||
self.C3Descent4k.Altitude=nil --UTILS.FeetToMeters(5000)
|
self.C3Descent4k.Altitude=nil --UTILS.FeetToMeters(5000)
|
||||||
self.C3Descent4k.AoA=nil
|
self.C3Descent4k.AoA=nil
|
||||||
self.C3Descent4k.Distance=nil
|
self.C3Descent4k.Distance=nil
|
||||||
@ -1004,7 +1042,7 @@ function AIRBOSS:_InitStennis()
|
|||||||
self.Upwind.name="Upwind"
|
self.Upwind.name="Upwind"
|
||||||
self.Upwind.Xmin=-UTILS.NMToMeters(4)
|
self.Upwind.Xmin=-UTILS.NMToMeters(4)
|
||||||
self.Upwind.Xmax=nil
|
self.Upwind.Xmax=nil
|
||||||
self.Upwind.Zmin=0
|
self.Upwind.Zmin=-100
|
||||||
self.Upwind.Zmax=1000
|
self.Upwind.Zmax=1000
|
||||||
self.Upwind.LimitXmin=0
|
self.Upwind.LimitXmin=0
|
||||||
self.Upwind.LimitXmax=nil
|
self.Upwind.LimitXmax=nil
|
||||||
@ -1018,8 +1056,8 @@ function AIRBOSS:_InitStennis()
|
|||||||
self.BreakEarly.name="Early Break"
|
self.BreakEarly.name="Early Break"
|
||||||
self.BreakEarly.Xmin=-500
|
self.BreakEarly.Xmin=-500
|
||||||
self.BreakEarly.Xmax=UTILS.NMToMeters(5)
|
self.BreakEarly.Xmax=UTILS.NMToMeters(5)
|
||||||
self.BreakEarly.Zmin=-3700
|
self.BreakEarly.Zmin=-UTILS.NMToMeters(2)
|
||||||
self.BreakEarly.Zmax=1500
|
self.BreakEarly.Zmax=UTILS.NMToMeters(1)
|
||||||
self.BreakEarly.LimitXmin=0
|
self.BreakEarly.LimitXmin=0
|
||||||
self.BreakEarly.LimitXmax=nil
|
self.BreakEarly.LimitXmax=nil
|
||||||
self.BreakEarly.LimitZmin=-370 -- 0.2 NM port of carrier
|
self.BreakEarly.LimitZmin=-370 -- 0.2 NM port of carrier
|
||||||
@ -1032,8 +1070,8 @@ function AIRBOSS:_InitStennis()
|
|||||||
self.BreakLate.name="Late Break"
|
self.BreakLate.name="Late Break"
|
||||||
self.BreakLate.Xmin=-500
|
self.BreakLate.Xmin=-500
|
||||||
self.BreakLate.Xmax=UTILS.NMToMeters(5)
|
self.BreakLate.Xmax=UTILS.NMToMeters(5)
|
||||||
self.BreakLate.Zmin=-3700
|
self.BreakLate.Zmin=-UTILS.NMToMeters(2)
|
||||||
self.BreakLate.Zmax=1500
|
self.BreakLate.Zmax=UTILS.NMToMeters(1)
|
||||||
self.BreakLate.LimitXmin=0
|
self.BreakLate.LimitXmin=0
|
||||||
self.BreakLate.LimitXmax=nil
|
self.BreakLate.LimitXmax=nil
|
||||||
self.BreakLate.LimitZmin=-1470 --0.8 NM
|
self.BreakLate.LimitZmin=-1470 --0.8 NM
|
||||||
@ -1156,6 +1194,8 @@ function AIRBOSS:_CheckQueue()
|
|||||||
local TpatternMin=120
|
local TpatternMin=120
|
||||||
if self.case==1 then
|
if self.case==1 then
|
||||||
TpatternMin=45
|
TpatternMin=45
|
||||||
|
else
|
||||||
|
TpatternMin=120
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Min time in marshal before send to landing pattern.
|
-- Min time in marshal before send to landing pattern.
|
||||||
@ -1417,6 +1457,12 @@ function AIRBOSS:_MarshalAI(flight)
|
|||||||
local group=flight.group
|
local group=flight.group
|
||||||
local groupname=flight.groupname
|
local groupname=flight.groupname
|
||||||
|
|
||||||
|
-- Check that we do not add a recovery tanker for marshaling.
|
||||||
|
-- TODO: Fix group name.
|
||||||
|
if self.tanker and self.tanker.tanker:GetName()==groupname then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
-- Number of already full marshal stacks.
|
-- Number of already full marshal stacks.
|
||||||
local nstacks=#self.Qmarshal
|
local nstacks=#self.Qmarshal
|
||||||
|
|
||||||
@ -1499,7 +1545,7 @@ function AIRBOSS:_GetMarshalAltitude(stack)
|
|||||||
Dist=UTILS.NMToMeters(2.5)
|
Dist=UTILS.NMToMeters(2.5)
|
||||||
p1=Carrier:Translate(Dist, hdg-70)
|
p1=Carrier:Translate(Dist, hdg-70)
|
||||||
else
|
else
|
||||||
-- CASE III: Holding at 6000 ft on a racetrack pattern astern the carrier.
|
-- CASE II/III: Holding at 6000 ft on a racetrack pattern astern the carrier.
|
||||||
angels0=6
|
angels0=6
|
||||||
Dist=UTILS.NMToMeters((stack-1)*angels0+15)
|
Dist=UTILS.NMToMeters((stack-1)*angels0+15)
|
||||||
p1=Carrier:Translate(-Dist, hdg)
|
p1=Carrier:Translate(-Dist, hdg)
|
||||||
@ -1688,10 +1734,8 @@ function AIRBOSS:_CheckPlayerStatus()
|
|||||||
-- Status undefined.
|
-- Status undefined.
|
||||||
local time=timer.getAbsTime()
|
local time=timer.getAbsTime()
|
||||||
local clock=UTILS.SecondsToClock(time)
|
local clock=UTILS.SecondsToClock(time)
|
||||||
self:I(string.format("Player status undefined. Waiting for next step. Time %s", clock))
|
self:T3(string.format("Player status undefined. Waiting for next step. Time %s", clock))
|
||||||
|
|
||||||
-- Jump directly to CASE I straight in approach.
|
|
||||||
--playerData.step=AIRBOSS.PatternStep.COMMENCING
|
|
||||||
|
|
||||||
-- Jump to final/groove for testing.
|
-- Jump to final/groove for testing.
|
||||||
if self.groovedebug then
|
if self.groovedebug then
|
||||||
@ -1853,7 +1897,7 @@ function AIRBOSS:OnEventBirth(EventData)
|
|||||||
--self:RadioTransmission(self.LSOradio, self.radiocall.LONGINGROOVE, false, 20)
|
--self:RadioTransmission(self.LSOradio, self.radiocall.LONGINGROOVE, false, 20)
|
||||||
|
|
||||||
-- Start in the groove for debugging.
|
-- Start in the groove for debugging.
|
||||||
self.groovedebug=false
|
self.groovedebug=true
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -1887,6 +1931,7 @@ function AIRBOSS:OnEventLand(EventData)
|
|||||||
self:T3(self.lid.."LAND: player = "..tostring(_playername))
|
self:T3(self.lid.."LAND: player = "..tostring(_playername))
|
||||||
|
|
||||||
if _unit and _playername then
|
if _unit and _playername then
|
||||||
|
-- Human Player landed.
|
||||||
|
|
||||||
local _uid=_unit:GetID()
|
local _uid=_unit:GetID()
|
||||||
local _group=_unit:GetGroup()
|
local _group=_unit:GetGroup()
|
||||||
@ -1935,8 +1980,8 @@ function AIRBOSS:OnEventLand(EventData)
|
|||||||
end
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
|
-- AI unit landed.
|
||||||
|
|
||||||
-- TODO: Get landing coodinates of AI hornet for perfect _OK_ 3-wire pass!
|
|
||||||
-- Coordinate at landing event
|
-- Coordinate at landing event
|
||||||
local coord=EventData.IniUnit:GetCoordinate()
|
local coord=EventData.IniUnit:GetCoordinate()
|
||||||
|
|
||||||
@ -1974,6 +2019,7 @@ function AIRBOSS:OnEventCrash(EventData)
|
|||||||
|
|
||||||
|
|
||||||
-- TODO: Update queues!
|
-- TODO: Update queues!
|
||||||
|
-- TODO: decrease number of units in group
|
||||||
if _unit and _playername then
|
if _unit and _playername then
|
||||||
self:I(self.lid.."Player %s crashed!",_playername)
|
self:I(self.lid.."Player %s crashed!",_playername)
|
||||||
else
|
else
|
||||||
@ -2056,16 +2102,25 @@ function AIRBOSS:_InitPlayer(playerData)
|
|||||||
return playerData
|
return playerData
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local _bla=true
|
||||||
|
|
||||||
--- Holding.
|
--- Holding.
|
||||||
-- @param #AIRBOSS self
|
-- @param #AIRBOSS self
|
||||||
-- @param #AIRBOSS.PlayerData playerData Player data.
|
-- @param #AIRBOSS.PlayerData playerData Player data.
|
||||||
function AIRBOSS:_Holding(playerData)
|
function AIRBOSS:_Holding(playerData)
|
||||||
|
|
||||||
|
-- Player unit and flight.
|
||||||
local unit=playerData.unit
|
local unit=playerData.unit
|
||||||
local flight=self:_GetFlightFromGroupInQueue(playerData.group, self.flights)
|
local flight=self:_GetFlightFromGroupInQueue(playerData.group, self.flights)
|
||||||
|
|
||||||
|
-- Current stack.
|
||||||
local stack=flight.flag:Get()
|
local stack=flight.flag:Get()
|
||||||
|
|
||||||
local alt, c1, c2=self:_GetMarshalAltitude(stack)
|
-- Pattern alitude.
|
||||||
|
local patternalt, c1, c2=self:_GetMarshalAltitude(stack)
|
||||||
|
|
||||||
|
-- Player altitude.
|
||||||
|
local playeralt=unit:GetAltitude()
|
||||||
|
|
||||||
-- Create a holding zone depending on recovery case.
|
-- Create a holding zone depending on recovery case.
|
||||||
local zoneHolding --Core.Zone#ZONE
|
local zoneHolding --Core.Zone#ZONE
|
||||||
@ -2082,52 +2137,87 @@ function AIRBOSS:_Holding(playerData)
|
|||||||
|
|
||||||
-- Create an array of a square!
|
-- Create an array of a square!
|
||||||
local p={}
|
local p={}
|
||||||
p[1]=c1:GetVec2()
|
p[1]=c1:Translate(UTILS.NMToMeters(1), hdg+90):GetVec2() --c1 is at (angels+15) NM directly behind the carrier. We translate it 1 NM starboard.
|
||||||
p[2]=c2:GetVec2()
|
p[2]=c2:Translate(UTILS.NMToMeters(1), hdg+90):GetVec2() --c2 is 10 NM further behind. Also translated 1 NM starboard.
|
||||||
p[3]=c2:Translate(UTILS.NMToMeters(5), hdg-90):GetVec2()
|
p[3]=c2:Translate(UTILS.NMToMeters(7), hdg-90):GetVec2() --p3 6 NM port of carrier.
|
||||||
p[4]=c1:Translate(UTILS.NMToMeters(5), hdg-90):GetVec2()
|
p[4]=c1:Translate(UTILS.NMToMeters(7), hdg-90):GetVec2() --p4 6 NM port of carrier.
|
||||||
|
|
||||||
|
-- Square zone length=10NM width=6 NM behind the carrier starting at angels+15 NM behind the carrier.
|
||||||
|
-- So stay 0-5 NM (+1 NM error margin) port of carrier.
|
||||||
zoneHolding=ZONE_POLYGON_BASE:New("CASE II/III Holding Zone", p)
|
zoneHolding=ZONE_POLYGON_BASE:New("CASE II/III Holding Zone", p)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--if bla then
|
if _bla then
|
||||||
-- zoneHolding:SmokeZone(SMOKECOLOR.Green)
|
zoneHolding:SmokeZone(SMOKECOLOR.Green)
|
||||||
-- bla=false
|
_bla=false
|
||||||
--end
|
end
|
||||||
|
|
||||||
-- Check if player is in holding zone.
|
-- Check if player is in holding zone.
|
||||||
local inholdingzone=unit:IsInZone(zoneHolding)
|
local inholdingzone=unit:IsInZone(zoneHolding)
|
||||||
|
|
||||||
|
-- Check player alt is +-500 feet of assigned pattern alt.
|
||||||
|
local altdiff=playeralt-patternalt
|
||||||
|
local goodalt=math.abs(altdiff)<UTILS.MetersToFeet(500)
|
||||||
|
|
||||||
|
-- TODO: check if player is flying counter clockwise. AOB<0.
|
||||||
|
|
||||||
|
local text=""
|
||||||
|
|
||||||
-- Different cases
|
-- Different cases
|
||||||
if playerData.holding==true then
|
if playerData.holding==true then
|
||||||
-- Player was in holding zone last time we checked.
|
-- Player was in holding zone last time we checked.
|
||||||
|
|
||||||
if inholdingzone then
|
if inholdingzone then
|
||||||
-- Player is still in holding zone.
|
-- Player is still in holding zone.
|
||||||
self:I("Player is still in the holding zone. Good job.")
|
self:I("Player is still in the holding zone. Good job.")
|
||||||
else
|
else
|
||||||
-- Player left the holding zone.
|
-- Player left the holding zone.
|
||||||
self:I("Player just left the holding zone. Come back!")
|
self:I("Player just left the holding zone. Come back!")
|
||||||
|
text=text..string.format("You just left the holding zone. Watch your numbers!")
|
||||||
|
playerData.holding=false
|
||||||
end
|
end
|
||||||
|
|
||||||
elseif playerData.holding==false then
|
elseif playerData.holding==false then
|
||||||
|
|
||||||
-- Player left holding zone
|
-- Player left holding zone
|
||||||
if inholdingzone then
|
if inholdingzone then
|
||||||
-- Player is back in the holding zone.
|
-- Player is back in the holding zone.
|
||||||
self:I("Player is back in the holding zone after leaving it.")
|
self:I("Player is back in the holding zone after leaving it.")
|
||||||
|
text=text..string.format("You are back in the holding zone. Now stay there!")
|
||||||
|
playerData.holding=true
|
||||||
else
|
else
|
||||||
-- Player is still outside the holding zone.
|
-- Player is still outside the holding zone.
|
||||||
self:I("Player still outside the holding zone. What are you doing man?!")
|
self:I("Player still outside the holding zone. What are you doing man?!")
|
||||||
end
|
end
|
||||||
|
|
||||||
elseif playerData.holding==nil then
|
elseif playerData.holding==nil then
|
||||||
-- Player never entered the holding zone
|
-- Player did not entered the holding zone yet.
|
||||||
|
|
||||||
if inholdingzone then
|
if inholdingzone then
|
||||||
-- Player arrived in holding zone.
|
-- Player arrived in holding zone.
|
||||||
playerData.holding=true
|
playerData.holding=true
|
||||||
self:I("Player entered the holding zone for the first time.")
|
self:I("Player entered the holding zone for the first time.")
|
||||||
|
text=text..string.format("You arrived at the holding zone.")
|
||||||
|
if goodalt then
|
||||||
|
text=text..string.format(" Now stay at that altitude.")
|
||||||
|
else
|
||||||
|
if altdiff<0 then
|
||||||
|
text=text..string.format(" But you are too low.")
|
||||||
|
else
|
||||||
|
text=text..string.format(" But you are too high.")
|
||||||
|
end
|
||||||
|
text=text..string.format(" Currently assigned altitude is %d ft.", UTILS.MetersToFeet(patternalt))
|
||||||
|
end
|
||||||
else
|
else
|
||||||
-- Player did not yet arrive in holding zone.
|
-- Player did not yet arrive in holding zone.
|
||||||
self:I("Waiting for player to arrive in the holding zone.")
|
self:I("Waiting for player to arrive in the holding zone.")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
if text~="" then
|
||||||
|
self:_SendMessageToPlayer(text, 5, playerData, false, "AIRBOSS")
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
@ -2276,9 +2366,15 @@ function AIRBOSS:_DirtyUp(playerData)
|
|||||||
-- Debrief.
|
-- Debrief.
|
||||||
self:_AddToSummary(playerData, "Dirty Up", debrief)
|
self:_AddToSummary(playerData, "Dirty Up", debrief)
|
||||||
|
|
||||||
-- Next step: Early Break.
|
-- Next step:
|
||||||
|
if self.case==2 then
|
||||||
|
-- CASE II: Fly to the initial and perform CASE I pattern.
|
||||||
|
playerData.step=AIRBOSS.PatternStep.INITIAL
|
||||||
|
elseif self.case==3 then
|
||||||
|
-- CASE III: Intercept glide slope and follow bullseye (ICLS).
|
||||||
playerData.step=AIRBOSS.PatternStep.BULLSEYE
|
playerData.step=AIRBOSS.PatternStep.BULLSEYE
|
||||||
end
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Bulls eye.
|
--- Bulls eye.
|
||||||
@ -2429,6 +2525,7 @@ function AIRBOSS:_CheckForLongDownwind(playerData)
|
|||||||
|
|
||||||
--grade="LIG PATTERN WAVE OFF - CUT 1 PT"
|
--grade="LIG PATTERN WAVE OFF - CUT 1 PT"
|
||||||
playerData.lig=true
|
playerData.lig=true
|
||||||
|
playerData.patternwo=true
|
||||||
|
|
||||||
-- Next step: Debriefing.
|
-- Next step: Debriefing.
|
||||||
playerData.step=AIRBOSS.PatternStep.DEBRIEF
|
playerData.step=AIRBOSS.PatternStep.DEBRIEF
|
||||||
@ -2527,6 +2624,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:_SendMessageToPlayer("You are already at the wake and have not passed the 90! Turn faster next time!", 10, playerData)
|
||||||
|
--TODO: pattern WO?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -4063,6 +4161,8 @@ function AIRBOSS:_RequestStraightIn(_unitName)
|
|||||||
local playerData=self.players[_playername] --#AIRBOSS.PlayerData
|
local playerData=self.players[_playername] --#AIRBOSS.PlayerData
|
||||||
|
|
||||||
if playerData then
|
if playerData then
|
||||||
|
-- TODO: check if landing pattern is full. If so, display message "AIRBOSS: "Pattern is full." and deny step!
|
||||||
|
-- TODO: check if in marshal stack and flag is 0. If not, give message "AIRBOSS: It's not your turn yet!" and deny step!
|
||||||
playerData.step=AIRBOSS.PatternStep.COMMENCING
|
playerData.step=AIRBOSS.PatternStep.COMMENCING
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -4338,4 +4438,3 @@ end
|
|||||||
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|||||||
@ -5,9 +5,8 @@
|
|||||||
-- Features:
|
-- Features:
|
||||||
--
|
--
|
||||||
-- * Regular pattern update with respect to carrier positon.
|
-- * Regular pattern update with respect to carrier positon.
|
||||||
-- * Automatic respawning when tanker runs out of fuel.
|
-- * Automatic respawning when tanker runs out of fuel for 24/7 operations.
|
||||||
-- * Tanker can be spawned cold or hot on the carrier or any other airbase or directly in air.
|
-- * Tanker can be spawned cold or hot on the carrier or at any other airbase or directly in air.
|
||||||
-- * Tanker can operate 24/7.
|
|
||||||
--
|
--
|
||||||
-- Please not that his class is work in progress and in an **alpha** stage.
|
-- Please not that his class is work in progress and in an **alpha** stage.
|
||||||
--
|
--
|
||||||
@ -34,6 +33,9 @@
|
|||||||
-- @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.
|
||||||
|
-- @field #boolean respawn If true, tanker be respawned (default). If false, no respawning will happen.
|
||||||
|
-- @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.
|
||||||
-- @extends Core.Fsm#FSM
|
-- @extends Core.Fsm#FSM
|
||||||
|
|
||||||
--- Recovery Tanker.
|
--- Recovery Tanker.
|
||||||
@ -62,21 +64,24 @@ RECOVERYTANKER = {
|
|||||||
Tupdate = nil,
|
Tupdate = nil,
|
||||||
takeoff = nil,
|
takeoff = nil,
|
||||||
lowfuel = nil,
|
lowfuel = nil,
|
||||||
|
respawn = nil,
|
||||||
|
respawninair = nil,
|
||||||
|
uncontrolledac = nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
--- Class version.
|
--- Class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
RECOVERYTANKER.version="0.9.1"
|
RECOVERYTANKER.version="0.9.2"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- TODO list
|
-- TODO list
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
-- TODO: Possibility to add already present/spawned aircraft, e.g. for warehouse.
|
|
||||||
-- TODO: Write documenation.
|
|
||||||
-- TODO: Smarter pattern update function. E.g. (small) zone around carrier. Only update position when carrier leaves zone or changes heading?
|
-- TODO: Smarter pattern update function. E.g. (small) zone around carrier. Only update position when carrier leaves zone or changes heading?
|
||||||
-- TODO: Maybe rework pattern update implementation altogether to make it smoother.
|
-- TODO: Write documenation.
|
||||||
|
-- DONE: Add refueling event/state.
|
||||||
|
-- DONE: Possibility to add already present/spawned aircraft, e.g. for warehouse.
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- Constructor
|
-- Constructor
|
||||||
@ -104,7 +109,7 @@ function RECOVERYTANKER:New(carrierunit, tankergroupname)
|
|||||||
-- Tanker group name.
|
-- Tanker group name.
|
||||||
self.tankergroupname=tankergroupname
|
self.tankergroupname=tankergroupname
|
||||||
|
|
||||||
-- Default parameters.
|
-- Init default parameters.
|
||||||
self:SetPatternUpdateInterval()
|
self:SetPatternUpdateInterval()
|
||||||
self:SetAltitude()
|
self:SetAltitude()
|
||||||
self:SetSpeed()
|
self:SetSpeed()
|
||||||
@ -112,6 +117,7 @@ function RECOVERYTANKER:New(carrierunit, tankergroupname)
|
|||||||
self:SetHomeBase(AIRBASE:FindByName(self.carrier:GetName()))
|
self:SetHomeBase(AIRBASE:FindByName(self.carrier:GetName()))
|
||||||
self:SetTakeoffAir()
|
self:SetTakeoffAir()
|
||||||
self:SetLowFuelThreshold()
|
self:SetLowFuelThreshold()
|
||||||
|
self:SetRespawnOnOff()
|
||||||
|
|
||||||
-----------------------
|
-----------------------
|
||||||
--- FSM Transitions ---
|
--- FSM Transitions ---
|
||||||
@ -123,10 +129,11 @@ 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")
|
self:AddTransition("Stopped", "Start", "Running")
|
||||||
|
self:AddTransition("*", "Refuel", "Refueling")
|
||||||
|
self:AddTransition("*", "Run", "Running")
|
||||||
self:AddTransition("Running", "RTB", "Returning")
|
self:AddTransition("Running", "RTB", "Returning")
|
||||||
self:AddTransition("Running", "Status", "*")
|
self:AddTransition("*", "Status", "*")
|
||||||
self:AddTransition("Returning", "Status", "*")
|
self:AddTransition("*", "Stop", "Stopped")
|
||||||
self:AddTransition("Running", "Stop", "Stopped")
|
|
||||||
|
|
||||||
|
|
||||||
--- Triggers the FSM event "Start" that starts the recovery tanker. Initializes parameters and starts event handlers.
|
--- Triggers the FSM event "Start" that starts the recovery tanker. Initializes parameters and starts event handlers.
|
||||||
@ -138,6 +145,29 @@ function RECOVERYTANKER:New(carrierunit, tankergroupname)
|
|||||||
-- @param #RECOVERYTANKER self
|
-- @param #RECOVERYTANKER self
|
||||||
-- @param #number delay Delay in seconds.
|
-- @param #number delay Delay in seconds.
|
||||||
|
|
||||||
|
|
||||||
|
--- Triggers the FSM event "Refuel" when the tanker is refueling another aircraft.
|
||||||
|
-- @function [parent=#RECOVERYTANKER] Refuel
|
||||||
|
-- @param Wrapper.Unit#UNIT receiver Unit receiving fuel from the tanker.
|
||||||
|
-- @param #RECOVERYTANKER self
|
||||||
|
|
||||||
|
--- Triggers delayed the FSM event "Refuel" when the tanker is refueling another aircraft.
|
||||||
|
-- @function [parent=#RECOVERYTANKER] __Refuel
|
||||||
|
-- @param #RECOVERYTANKER self
|
||||||
|
-- @param #number delay Delay in seconds.
|
||||||
|
-- @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.
|
||||||
|
-- @function [parent=#RECOVERYTANKER] Run
|
||||||
|
-- @param #RECOVERYTANKER self
|
||||||
|
|
||||||
|
--- Triggers delayed the FSM event "Run". Simply puts the group into "Running" state, e.g. after refueling ended.
|
||||||
|
-- @function [parent=#RECOVERYTANKER] __Run
|
||||||
|
-- @param #RECOVERYTANKER self
|
||||||
|
-- @param #number delay Delay in seconds.
|
||||||
|
|
||||||
|
|
||||||
--- Triggers the FSM event "RTB" that sends the tanker home.
|
--- Triggers the FSM event "RTB" that sends the tanker home.
|
||||||
-- @function [parent=#RECOVERYTANKER] RTB
|
-- @function [parent=#RECOVERYTANKER] RTB
|
||||||
-- @param #RECOVERYTANKER self
|
-- @param #RECOVERYTANKER self
|
||||||
@ -147,6 +177,7 @@ function RECOVERYTANKER:New(carrierunit, tankergroupname)
|
|||||||
-- @param #RECOVERYTANKER self
|
-- @param #RECOVERYTANKER self
|
||||||
-- @param #number delay Delay in seconds.
|
-- @param #number delay Delay in seconds.
|
||||||
|
|
||||||
|
|
||||||
--- 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
|
||||||
-- @param #RECOVERYTANKER self
|
-- @param #RECOVERYTANKER self
|
||||||
@ -254,6 +285,55 @@ function RECOVERYTANKER:SetTakeoffAir()
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Enable respawning of tanker. Note that this is the default behaviour.
|
||||||
|
-- @param #RECOVERYTANKER self
|
||||||
|
-- @return #RECOVERYTANKER self
|
||||||
|
function RECOVERYTANKER:SetRespawnOn()
|
||||||
|
self.respawn=true
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Disable respawning of tanker.
|
||||||
|
-- @param #RECOVERYTANKER self
|
||||||
|
-- @return #RECOVERYTANKER self
|
||||||
|
function RECOVERYTANKER:SetRespawnOff()
|
||||||
|
self.respawn=false
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set whether tanker shall be respawned or not.
|
||||||
|
-- @param #RECOVERYTANKER self
|
||||||
|
-- @param #boolean switch If true (or nil), tanker will be respawned. If false, tanker will not be respawned.
|
||||||
|
-- @return #RECOVERYTANKER self
|
||||||
|
function RECOVERYTANKER:SetRespawnOnOff(switch)
|
||||||
|
if switch==nil or switch==true then
|
||||||
|
self.respawn=true
|
||||||
|
else
|
||||||
|
self.respawn=false
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Tanker will be respawned in air, even it was initially spawned on the carrier.
|
||||||
|
-- So only the first spawn will be on the carrier while all subsequent spawns will happen in air.
|
||||||
|
-- This allows for undisrupted operations and less problems on the carrier deck.
|
||||||
|
-- @param #RECOVERYTANKER self
|
||||||
|
-- @return #RECOVERYTANKER self
|
||||||
|
function RECOVERYTANKER:SetRespawnInAir()
|
||||||
|
self.respawninair=true
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Use an uncontrolled aircraft already present in the mission rather than spawning a new tanker as initial recovery thanker.
|
||||||
|
-- This can be useful when interfaced with, e.g., a warehouse.
|
||||||
|
-- The group name is the one specified in the @{#RECOVERYTANKER.New} function.
|
||||||
|
-- @param #RECOVERYTANKER self
|
||||||
|
-- @return #RECOVERYTANKER self
|
||||||
|
function RECOVERYTANKER:SetUseUncontrolledAircraft()
|
||||||
|
self.uncontrolledac=true
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- Check if tanker is returning to base.
|
--- Check if tanker is returning to base.
|
||||||
-- @param #RECOVERYTANKER self
|
-- @param #RECOVERYTANKER self
|
||||||
-- @return #boolean If true, tanker is returning to base.
|
-- @return #boolean If true, tanker is returning to base.
|
||||||
@ -284,7 +364,9 @@ function RECOVERYTANKER:onafterStart(From, Event, To)
|
|||||||
|
|
||||||
-- Handle events.
|
-- Handle events.
|
||||||
self:HandleEvent(EVENTS.EngineShutdown)
|
self:HandleEvent(EVENTS.EngineShutdown)
|
||||||
--TODO: Handle event crash and respawn.
|
self:HandleEvent(EVENTS.Refueling)
|
||||||
|
self:HandleEvent(EVENTS.RefuelingStop)
|
||||||
|
self:HandleEvent(EVENTS.Crash)
|
||||||
|
|
||||||
-- Spawn tanker.
|
-- Spawn tanker.
|
||||||
local Spawn=SPAWN:New(self.tankergroupname):InitUnControlled(false)
|
local Spawn=SPAWN:New(self.tankergroupname):InitUnControlled(false)
|
||||||
@ -295,6 +377,7 @@ function RECOVERYTANKER:onafterStart(From, Event, To)
|
|||||||
-- Carrier heading
|
-- Carrier heading
|
||||||
local hdg=self.carrier:GetHeading()
|
local hdg=self.carrier:GetHeading()
|
||||||
|
|
||||||
|
-- Spawn distance behind the carrier.
|
||||||
local dist=UTILS.NMToMeters(20)
|
local dist=UTILS.NMToMeters(20)
|
||||||
|
|
||||||
-- Coordinate behind the carrier
|
-- Coordinate behind the carrier
|
||||||
@ -306,11 +389,32 @@ 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, 2)
|
self:_InitRoute(15, 1, 2)
|
||||||
|
else
|
||||||
|
|
||||||
|
-- Check if an uncontrolled tanker group was requested.
|
||||||
|
if self.useuncontrolled then
|
||||||
|
|
||||||
|
-- Use an uncontrolled aircraft group.
|
||||||
|
self.tanker=GROUP:FindByName(self.tankergroupname)
|
||||||
|
|
||||||
|
if self.tanker:IsAlive() then
|
||||||
|
-- Start uncontrolled group.
|
||||||
|
self.tanker:StartUncontrolled()
|
||||||
|
else
|
||||||
|
self:E(string.format("ERROR: No uncontrolled (alive) tanker group with name %s could be found!", self.tankergroupname))
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
-- Spawn tanker at airbase.
|
-- Spawn tanker at airbase.
|
||||||
self.tanker=Spawn:SpawnAtAirbase(self.airbase, self.takeoff)
|
self.tanker=Spawn:SpawnAtAirbase(self.airbase, self.takeoff)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Initialize route.
|
||||||
self:_InitRoute(30, 10, 1)
|
self:_InitRoute(30, 10, 1)
|
||||||
|
|
||||||
end
|
end
|
||||||
@ -331,10 +435,11 @@ 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("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:I(text)
|
||||||
|
|
||||||
|
|
||||||
|
-- Check if tanker is running and not RTBing.
|
||||||
if self:IsRunning() then
|
if self:IsRunning() then
|
||||||
|
|
||||||
-- Check fuel.
|
-- Check fuel.
|
||||||
@ -350,6 +455,7 @@ function RECOVERYTANKER:onafterStatus(From, Event, To)
|
|||||||
--Time since last pattern update.
|
--Time since last pattern update.
|
||||||
local dt=time-self.Tupdate
|
local dt=time-self.Tupdate
|
||||||
|
|
||||||
|
-- Update pattern.
|
||||||
if dt>self.dTupdate then
|
if dt>self.dTupdate then
|
||||||
self:_PatternUpdate()
|
self:_PatternUpdate()
|
||||||
end
|
end
|
||||||
@ -363,16 +469,6 @@ function RECOVERYTANKER:onafterStatus(From, Event, To)
|
|||||||
self:__Status(-60)
|
self:__Status(-60)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- On after Stop event. Unhandle events and stop status updates.
|
|
||||||
-- @param #RECOVERYTANKER self
|
|
||||||
-- @param #string From From state.
|
|
||||||
-- @param #string Event Event.
|
|
||||||
-- @param #string To To state.
|
|
||||||
function RECOVERYTANKER:onafterStop(From, Event, To)
|
|
||||||
self:UnHandleEvent(EVENTS.EngineShutdown)
|
|
||||||
--self:UnHandleEvent(EVENTS.Land)
|
|
||||||
end
|
|
||||||
|
|
||||||
--- On before RTB event. Check if takeoff type is air and if so respawn the tanker and deny RTB transition.
|
--- On before RTB event. Check if takeoff type is air and if so respawn the tanker and deny RTB transition.
|
||||||
-- @param #RECOVERYTANKER self
|
-- @param #RECOVERYTANKER self
|
||||||
-- @param #string From From state.
|
-- @param #string From From state.
|
||||||
@ -381,8 +477,12 @@ end
|
|||||||
-- @return #boolean If true, transition is allowed.
|
-- @return #boolean If true, transition is allowed.
|
||||||
function RECOVERYTANKER:onbeforeRTB(From, Event, To)
|
function RECOVERYTANKER:onbeforeRTB(From, Event, To)
|
||||||
|
|
||||||
|
-- Check if spawn in air is activated.
|
||||||
if self.takeoff==SPAWN.Takeoff.Air then
|
if self.takeoff==SPAWN.Takeoff.Air then
|
||||||
|
|
||||||
|
-- Check that respawn should happen.
|
||||||
|
if self.respawn then
|
||||||
|
|
||||||
-- Debug message.
|
-- Debug message.
|
||||||
local text=string.format("Respawning tanker %s.", self.tanker:GetName())
|
local text=string.format("Respawning tanker %s.", self.tanker:GetName())
|
||||||
self:I(text)
|
self:I(text)
|
||||||
@ -397,11 +497,12 @@ function RECOVERYTANKER:onbeforeRTB(From, Event, To)
|
|||||||
-- Deny transition to RTB.
|
-- Deny transition to RTB.
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
--- On after RTB event. Send tanker back to carrier.
|
--- On after "RTB" event. Send tanker back to carrier.
|
||||||
-- @param #RECOVERYTANKER self
|
-- @param #RECOVERYTANKER self
|
||||||
-- @param #string From From state.
|
-- @param #string From From state.
|
||||||
-- @param #string Event Event.
|
-- @param #string Event Event.
|
||||||
@ -412,17 +513,28 @@ function RECOVERYTANKER:onafterRTB(From, Event, To)
|
|||||||
local text=string.format("Tanker %s returning to airbase %s.", self.tanker:GetName(), self.airbase:GetName())
|
local text=string.format("Tanker %s returning to airbase %s.", self.tanker:GetName(), self.airbase:GetName())
|
||||||
self:I(text)
|
self:I(text)
|
||||||
|
|
||||||
local waypoints={}
|
-- Waypoint array.
|
||||||
|
local wp={}
|
||||||
|
|
||||||
-- Set landingwaypoint
|
-- Set landing waypoint.
|
||||||
local wp=self.carrier:GetCoordinate():WaypointAirLanding(300, self.airbase, nil, "Landing")
|
wp[1]=self.tanker:GetCoordinate():WaypointAirTurningPoint(nil, 300, {}, "Current Position")
|
||||||
table.insert(waypoints, wp)
|
wp[2]=self.carrier:GetCoordinate():WaypointAirLanding(300, self.airbase, nil, "Landing on Carrier")
|
||||||
|
|
||||||
-- Initialize WP and route tanker.
|
-- Initialize WP and route tanker.
|
||||||
self.tanker:WayPointInitialize(waypoints)
|
self.tanker:WayPointInitialize(wp)
|
||||||
|
|
||||||
-- Set task.
|
-- Set task.
|
||||||
self.tanker:Route(waypoints, 1)
|
self.tanker:Route(wp, 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- On after Stop event. Unhandle events and stop status updates.
|
||||||
|
-- @param #RECOVERYTANKER self
|
||||||
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To To state.
|
||||||
|
function RECOVERYTANKER:onafterStop(From, Event, To)
|
||||||
|
self:UnHandleEvent(EVENTS.EngineShutdown)
|
||||||
|
--self:UnHandleEvent(EVENTS.Land)
|
||||||
end
|
end
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
@ -437,7 +549,8 @@ function RECOVERYTANKER:OnEventEngineShutdown(EventData)
|
|||||||
|
|
||||||
local group=EventData.IniGroup --Wrapper.Group#GROUP
|
local group=EventData.IniGroup --Wrapper.Group#GROUP
|
||||||
|
|
||||||
if group:IsAlive() then
|
-- Check if group is alive and should be respawned.
|
||||||
|
if group:IsAlive() and self.respawn then
|
||||||
|
|
||||||
-- Group name. When spawning it will have #001 attached.
|
-- Group name. When spawning it will have #001 attached.
|
||||||
local groupname=group:GetName()
|
local groupname=group:GetName()
|
||||||
@ -450,8 +563,6 @@ function RECOVERYTANKER:OnEventEngineShutdown(EventData)
|
|||||||
-- Respawn tanker.
|
-- Respawn tanker.
|
||||||
self.tanker=group:RespawnAtCurrentAirbase()
|
self.tanker=group:RespawnAtCurrentAirbase()
|
||||||
|
|
||||||
--group:StartUncontrolled(60)
|
|
||||||
|
|
||||||
-- Initial route.
|
-- Initial route.
|
||||||
self:_InitRoute()
|
self:_InitRoute()
|
||||||
end
|
end
|
||||||
@ -459,6 +570,57 @@ function RECOVERYTANKER:OnEventEngineShutdown(EventData)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Event handler for refueling started.
|
||||||
|
-- @param #RECOVERYTANKER self
|
||||||
|
-- @param Core.Event#EVENTDATA EventData Event data.
|
||||||
|
function RECOVERYTANKER:OnEventRefuel(EventData)
|
||||||
|
|
||||||
|
if EventData and EventData.IniUnit and EventData.IniUnit:IsAlive() then
|
||||||
|
|
||||||
|
-- Unit receiving fuel.
|
||||||
|
local unit=EventData.IniUnit
|
||||||
|
|
||||||
|
-- Get distance to tanker to check that unit is receiving fuel from this tanker.
|
||||||
|
local dist=unit:GetCoordinate():Get2DDistance(self.tanker:GetCoordinate())
|
||||||
|
|
||||||
|
-- If distance > 100 meters, this should be another tanker.
|
||||||
|
if dist>100 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Info message.
|
||||||
|
self:I(string.format("Recovery tanker %s started refueling unit %s", self.tanker:GetName(), unit:GetName()))
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Event handler for refueling stopped.
|
||||||
|
-- @param #RECOVERYTANKER self
|
||||||
|
-- @param Core.Event#EVENTDATA EventData Event data.
|
||||||
|
function RECOVERYTANKER:OnEventRefuelStop(EventData)
|
||||||
|
|
||||||
|
if EventData and EventData.IniUnit and EventData.IniUnit:IsAlive() then
|
||||||
|
|
||||||
|
-- Unit receiving fuel.
|
||||||
|
local unit=EventData.IniUnit
|
||||||
|
|
||||||
|
-- Get distance to tanker to check that unit is receiving fuel from this tanker.
|
||||||
|
local dist=unit:GetCoordinate():Get2DDistance(self.tanker:GetCoordinate())
|
||||||
|
|
||||||
|
-- If distance > 100 meters, this should be another tanker.
|
||||||
|
if dist>100 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Info message.
|
||||||
|
self:I(string.format("Recovery tanker %s stopped refueling unit %s", self.tanker:GetName(), unit:GetName()))
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- ROUTE functions
|
-- ROUTE functions
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
@ -476,7 +638,7 @@ function RECOVERYTANKER:_InitRoute(dist, Tstart, delay)
|
|||||||
delay=delay or 1
|
delay=delay or 1
|
||||||
|
|
||||||
-- Debug message.
|
-- Debug message.
|
||||||
self:I(string.format("Initializing route for tanker %s.", self.tanker:GetName()))
|
self:I(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()
|
||||||
@ -510,6 +672,9 @@ end
|
|||||||
-- @param #RECOVERYTANKER self
|
-- @param #RECOVERYTANKER self
|
||||||
function RECOVERYTANKER:_PatternUpdate()
|
function RECOVERYTANKER:_PatternUpdate()
|
||||||
|
|
||||||
|
-- Debug message.
|
||||||
|
self:I(string.format("Updating recovery tanker %s orbit.", self.tanker:GetName()))
|
||||||
|
|
||||||
-- Carrier heading.
|
-- Carrier heading.
|
||||||
local hdg=self.carrier:GetHeading()
|
local hdg=self.carrier:GetHeading()
|
||||||
|
|
||||||
@ -517,38 +682,34 @@ function RECOVERYTANKER:_PatternUpdate()
|
|||||||
local Carrier=self.carrier:GetCoordinate()
|
local Carrier=self.carrier:GetCoordinate()
|
||||||
|
|
||||||
-- Define race-track pattern.
|
-- Define race-track pattern.
|
||||||
|
local p0=self.tanker:GetCoordinate():Translate(1000, self.tanker:GetHeading())
|
||||||
local p1=Carrier:SetAltitude(self.altitude):Translate(self.distStern, hdg)
|
local p1=Carrier:SetAltitude(self.altitude):Translate(self.distStern, hdg)
|
||||||
local p2=Carrier:SetAltitude(self.altitude):Translate(self.distBow, hdg)
|
local p2=Carrier:SetAltitude(self.altitude):Translate(self.distBow, hdg)
|
||||||
|
|
||||||
-- Set orbit task.
|
-- Set orbit task.
|
||||||
local taskorbit=self.tanker:TaskOrbit(p1, self.altitude, self.speed, p2)
|
local taskorbit=self.tanker:TaskOrbit(p1, self.altitude, self.speed, p2)
|
||||||
|
|
||||||
-- New waypoint.
|
|
||||||
local p0=self.tanker:GetCoordinate():Translate(1000, self.tanker:GetHeading())
|
|
||||||
|
|
||||||
-- Debug markers.
|
-- Debug markers.
|
||||||
if self.Debug then
|
if self.Debug then
|
||||||
p0:MarkToAll("p0")
|
p0:MarkToAll("Waypoint P0 " ..self.tanker:GetName())
|
||||||
p1:MarkToAll("p1")
|
p1:MarkToAll("Racetrack P1 "..self.tanker:GetName())
|
||||||
p2:MarkToAll("p2")
|
p2:MarkToAll("Racetrack P2 "..self.tanker:GetName())
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Debug message.
|
|
||||||
self:I(string.format("Updating tanker %s orbit.", self.tanker:GetName()))
|
|
||||||
|
|
||||||
-- Waypoints array.
|
-- Waypoints array.
|
||||||
local waypoints={}
|
local wp={}
|
||||||
|
|
||||||
-- New waypoint with orbit pattern task.
|
-- New waypoint with orbit pattern task.
|
||||||
local wp=p0:WaypointAirTurningPoint(nil, self.speed, {taskorbit}, "Tanker Orbit")
|
wp[1]=self.tanker:GetCoordinate():WaypointAirTurningPoint(nil , self.speed, {}, "Current Position")
|
||||||
waypoints[1]=wp
|
wp[2]=p0:WaypointAirTurningPoint(nil, self.speed, {taskorbit}, "Tanker Orbit")
|
||||||
|
|
||||||
-- Initialize WP and route tanker.
|
-- Initialize WP and route tanker.
|
||||||
self.tanker:WayPointInitialize(waypoints)
|
self.tanker:WayPointInitialize(wp)
|
||||||
|
|
||||||
-- Task combo.
|
-- Task combo.
|
||||||
local tasktanker = self.tanker:EnRouteTaskTanker()
|
local tasktanker = self.tanker:EnRouteTaskTanker()
|
||||||
local taskroute = self.tanker:TaskRoute(waypoints)
|
local taskroute = self.tanker:TaskRoute(wp)
|
||||||
|
-- Note that tasktanker has to come first. Otherwise it does not work!
|
||||||
local taskcombo = self.tanker:TaskCombo({tasktanker, taskroute})
|
local taskcombo = self.tanker:TaskCombo({tasktanker, taskroute})
|
||||||
|
|
||||||
-- Set task.
|
-- Set task.
|
||||||
|
|||||||
@ -1,11 +1,13 @@
|
|||||||
--- **Functional** - (R2.5) - Rescue helo.
|
--- **Functional** - (R2.5) - Rescue helo.
|
||||||
--
|
--
|
||||||
-- Recue helicopter on an aircraft carrier.
|
-- Recue helicopter for carrier operations.
|
||||||
--
|
--
|
||||||
-- Features:
|
-- Features:
|
||||||
--
|
--
|
||||||
-- * Formation with carrier.
|
-- * Close formation with carrier.
|
||||||
-- * Automatic respawning on empty fuel.
|
-- * Carrier can have any number of waypoints.
|
||||||
|
-- * Automatic respawning on empty fuel for 24/7 operations.
|
||||||
|
-- * Automatic rescuing of crashed or ejected units in the vicinity.
|
||||||
--
|
--
|
||||||
-- Please not that his class is work in progress and in an **alpha** stage.
|
-- Please not that his class is work in progress and in an **alpha** stage.
|
||||||
--
|
--
|
||||||
@ -24,13 +26,14 @@
|
|||||||
-- @field #string helogroupname Name of the late activated helo template group.
|
-- @field #string helogroupname Name of the late activated helo template group.
|
||||||
-- @field Wrapper.Group#GROUP helo Helo group.
|
-- @field Wrapper.Group#GROUP helo Helo group.
|
||||||
-- @field #number takeoff Takeoff type.
|
-- @field #number takeoff Takeoff type.
|
||||||
-- @field Wrapper.Airbase#AIRBASE airbase The airbase object of the carrier.
|
-- @field Wrapper.Airbase#AIRBASE airbase The airbase object acting as home base of the helo.
|
||||||
-- @field Core.Set#SET_GROUP followset Follow group set.
|
-- @field Core.Set#SET_GROUP followset Follow group set.
|
||||||
-- @field AI.AI_Formation#AI_FORMATION formation AI_FORMATION object.
|
-- @field AI.AI_Formation#AI_FORMATION formation AI_FORMATION object.
|
||||||
-- @field #number lowfuel Low fuel threshold of helo in percent.
|
-- @field #number lowfuel Low fuel threshold of helo in percent.
|
||||||
-- @field #number altitude Altitude of helo in meters.
|
-- @field #number altitude Altitude of helo in meters.
|
||||||
-- @field #number offsetX Offset in meters to carrier in longitudinal direction.
|
-- @field #number offsetX Offset in meters to carrier in longitudinal direction.
|
||||||
-- @field #number offsetZ Offset in meters to carrier in latitudinal direction.
|
-- @field #number offsetZ Offset in meters to carrier in latitudinal direction.
|
||||||
|
-- @field Core.Zone#ZONE_RADIUS rescuezone Zone around the carrier in which helo will rescue crashed or ejected units.
|
||||||
-- @extends Core.Fsm#FSM
|
-- @extends Core.Fsm#FSM
|
||||||
|
|
||||||
--- Rescue Helo
|
--- Rescue Helo
|
||||||
@ -58,20 +61,22 @@ RESCUEHELO = {
|
|||||||
altitude = nil,
|
altitude = nil,
|
||||||
offsetX = nil,
|
offsetX = nil,
|
||||||
offsetZ = nil,
|
offsetZ = nil,
|
||||||
|
rescuezone = nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Class version.
|
--- Class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
RESCUEHELO.version="0.9.1"
|
RESCUEHELO.version="0.9.2"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- TODO list
|
-- TODO list
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-- TODO: Add option to stop carrier while rescue operation is in progress.
|
||||||
-- TODO: Possibility to add already present/spawned aircraft, e.g. for warehouse.
|
-- TODO: Possibility to add already present/spawned aircraft, e.g. for warehouse.
|
||||||
-- TODO: Write documenation.
|
-- TODO: Write documenation.
|
||||||
-- TODO: Add rescue event when aircraft crashes.
|
-- DONE: Add rescue event when aircraft crashes.
|
||||||
-- TODO: Make offset input parameter.
|
-- DONE: Make offset input parameter.
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- Constructor
|
-- Constructor
|
||||||
@ -87,6 +92,7 @@ function RESCUEHELO:New(carrierunit, helogroupname)
|
|||||||
-- Inherit everthing from FSM class.
|
-- Inherit everthing from FSM class.
|
||||||
local self = BASE:Inherit(self, FSM:New()) -- #RESCUEHELO
|
local self = BASE:Inherit(self, FSM:New()) -- #RESCUEHELO
|
||||||
|
|
||||||
|
-- Catch case when just the unit name is passed.
|
||||||
if type(carrierunit)=="string" then
|
if type(carrierunit)=="string" then
|
||||||
self.carrier=UNIT:FindByName(carrierunit)
|
self.carrier=UNIT:FindByName(carrierunit)
|
||||||
else
|
else
|
||||||
@ -99,9 +105,6 @@ function RESCUEHELO:New(carrierunit, helogroupname)
|
|||||||
-- Helo group name.
|
-- Helo group name.
|
||||||
self.helogroupname=helogroupname
|
self.helogroupname=helogroupname
|
||||||
|
|
||||||
-- Home airbase of helo
|
|
||||||
self.airbase=AIRBASE:FindByName(self.carrier:GetName())
|
|
||||||
|
|
||||||
-- Init defaults.
|
-- Init defaults.
|
||||||
self:SetHomeBase(AIRBASE:FindByName(self.carrier:GetName()))
|
self:SetHomeBase(AIRBASE:FindByName(self.carrier:GetName()))
|
||||||
self:SetTakeoffHot()
|
self:SetTakeoffHot()
|
||||||
@ -109,6 +112,7 @@ function RESCUEHELO:New(carrierunit, helogroupname)
|
|||||||
self:SetAltitude()
|
self:SetAltitude()
|
||||||
self:SetOffsetX()
|
self:SetOffsetX()
|
||||||
self:SetOffsetZ()
|
self:SetOffsetZ()
|
||||||
|
self:SetRescueZone()
|
||||||
|
|
||||||
-----------------------
|
-----------------------
|
||||||
--- FSM Transitions ---
|
--- FSM Transitions ---
|
||||||
@ -120,10 +124,11 @@ function RESCUEHELO:New(carrierunit, helogroupname)
|
|||||||
-- Add FSM transitions.
|
-- Add FSM transitions.
|
||||||
-- From State --> Event --> To State
|
-- From State --> Event --> To State
|
||||||
self:AddTransition("Stopped", "Start", "Running")
|
self:AddTransition("Stopped", "Start", "Running")
|
||||||
|
self:AddTransition("Running", "Rescue", "Rescuing")
|
||||||
self:AddTransition("Running", "RTB", "Returning")
|
self:AddTransition("Running", "RTB", "Returning")
|
||||||
self:AddTransition("Returning", "Status", "*")
|
self:AddTransition("*", "Run", "Running")
|
||||||
self:AddTransition("Running", "Status", "*")
|
self:AddTransition("*", "Status", "*")
|
||||||
self:AddTransition("Running", "Stop", "Stopped")
|
self:AddTransition("*", "Stop", "Stopped")
|
||||||
|
|
||||||
|
|
||||||
--- Triggers the FSM event "Start" that starts the rescue helo. Initializes parameters and starts event handlers.
|
--- Triggers the FSM event "Start" that starts the rescue helo. Initializes parameters and starts event handlers.
|
||||||
@ -135,6 +140,17 @@ function RESCUEHELO:New(carrierunit, helogroupname)
|
|||||||
-- @param #RESCUEHELO self
|
-- @param #RESCUEHELO self
|
||||||
-- @param #number delay Delay in seconds.
|
-- @param #number delay Delay in seconds.
|
||||||
|
|
||||||
|
--- Triggers the FSM event "Rescue" that sends the helo on a rescue mission to a specifc coordinate.
|
||||||
|
-- @function [parent=#RESCUEHELO] Rescue
|
||||||
|
-- @param #RESCUEHELO self
|
||||||
|
-- @param Core.Point#COORDINATE RescueCoord Coordinate where the resue mission takes place.
|
||||||
|
|
||||||
|
--- Triggers the delayed FSM event "Rescue" that sends the helo on a rescue mission to a specifc coordinate.
|
||||||
|
-- @function [parent=#RESCUEHELO] __Rescue
|
||||||
|
-- @param #RESCUEHELO self
|
||||||
|
-- @param #number delay Delay in seconds.
|
||||||
|
-- @param Core.Point#COORDINATE RescueCoord Coordinate where the resue mission takes place.
|
||||||
|
|
||||||
--- Triggers the FSM event "RTB" that sends the helo home.
|
--- Triggers the FSM event "RTB" that sends the helo home.
|
||||||
-- @function [parent=#RESCUEHELO] RTB
|
-- @function [parent=#RESCUEHELO] RTB
|
||||||
-- @param #RESCUEHELO self
|
-- @param #RESCUEHELO self
|
||||||
@ -144,6 +160,15 @@ function RESCUEHELO:New(carrierunit, helogroupname)
|
|||||||
-- @param #RESCUEHELO self
|
-- @param #RESCUEHELO self
|
||||||
-- @param #number delay Delay in seconds.
|
-- @param #number delay Delay in seconds.
|
||||||
|
|
||||||
|
--- Triggers the FSM event "Run".
|
||||||
|
-- @function [parent=#RESCUEHELO] Run
|
||||||
|
-- @param #RESCUEHELO self
|
||||||
|
|
||||||
|
--- Triggers the delayed FSM event "Run".
|
||||||
|
-- @function [parent=#RESCUEHELO] __Run
|
||||||
|
-- @param #RESCUEHELO self
|
||||||
|
-- @param #number delay Delay in seconds.
|
||||||
|
|
||||||
--- Triggers the FSM event "Stop" that stops the rescue helo. Event handlers are stopped.
|
--- Triggers the FSM event "Stop" that stops the rescue helo. Event handlers are stopped.
|
||||||
-- @function [parent=#RESCUEHELO] Stop
|
-- @function [parent=#RESCUEHELO] Stop
|
||||||
-- @param #RESCUEHELO self
|
-- @param #RESCUEHELO self
|
||||||
@ -178,12 +203,21 @@ function RESCUEHELO:SetHomeBase(airbase)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Set rescue zone radius. Crashed or ejected units inside this radius of the carrier will be rescued.
|
||||||
|
-- @param #RESCUEHELO self
|
||||||
|
-- @param #number radius Radius of rescue zone in meters. Default is 100000 m = 100 km.
|
||||||
|
-- @return #RESCUEHELO self
|
||||||
|
function RESCUEHELO:SetRescueZone(radius)
|
||||||
|
self.rescuezone=ZONE_UNIT:New("Rescue Zone", self.carrier, radius or 100000)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- Set takeoff type.
|
--- Set takeoff type.
|
||||||
-- @param #RESCUEHELO self
|
-- @param #RESCUEHELO self
|
||||||
-- @param #number takeofftype Takeoff type.
|
-- @param #number takeofftype Takeoff type. Default SPAWN.Takeoff.Hot.
|
||||||
-- @return #RESCUEHELO self
|
-- @return #RESCUEHELO self
|
||||||
function RESCUEHELO:SetTakeoff(takeofftype)
|
function RESCUEHELO:SetTakeoff(takeofftype)
|
||||||
self.takeoff=takeofftype
|
self.takeoff=takeofftype or SPAWN.Takeoff.Hot
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -239,20 +273,109 @@ function RESCUEHELO:SetOffsetZ(distance)
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Check if tanker is returning to base.
|
--- Check if helo is returning to base.
|
||||||
-- @param #RESCUEHELO self
|
-- @param #RESCUEHELO self
|
||||||
-- @return #boolean If true, helo is returning to base.
|
-- @return #boolean If true, helo is returning to base.
|
||||||
function RESCUEHELO:IsReturning()
|
function RESCUEHELO:IsReturning()
|
||||||
return self:is("Returning")
|
return self:is("Returning")
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Check if tanker is operating.
|
--- Check if helo is operating.
|
||||||
-- @param #RESCUEHELO self
|
-- @param #RESCUEHELO self
|
||||||
-- @return #boolean If true, helo is operating.
|
-- @return #boolean If true, helo is operating.
|
||||||
function RESCUEHELO:IsRunning()
|
function RESCUEHELO:IsRunning()
|
||||||
return self:is("Running")
|
return self:is("Running")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Check if helo is on a rescue mission.
|
||||||
|
-- @param #RESCUEHELO self
|
||||||
|
-- @return #boolean If true, helo is rescuing somebody.
|
||||||
|
function RESCUEHELO:IsRescuing()
|
||||||
|
return self:is("Rescuing")
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-- EVENT functions
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- Handle landing event of rescue helo.
|
||||||
|
-- @param #RESCUEHELO self
|
||||||
|
-- @param Core.Event#EVENTDATA EventData Event data.
|
||||||
|
function RESCUEHELO:OnEventLand(EventData)
|
||||||
|
local group=EventData.IniGroup --Wrapper.Group#GROUP
|
||||||
|
|
||||||
|
if group:IsAlive() then
|
||||||
|
local groupname=group:GetName()
|
||||||
|
|
||||||
|
if groupname:match(self.helogroupname) then
|
||||||
|
|
||||||
|
-- Respawn the Helo.
|
||||||
|
self:I(string.format("Respawning rescue helo group %s at home base.", groupname))
|
||||||
|
|
||||||
|
if self.takeoff==SPAWN.Takeoff.Air then
|
||||||
|
|
||||||
|
self:E("ERROR: Rescue helo %s landed. This should not happen for Takeoff=Air!", groupname)
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
-- Respawn helo at current airbase.
|
||||||
|
self.helo=group:RespawnAtCurrentAirbase()
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Restart the formation.
|
||||||
|
self:__Run(10)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- A unit crashed or a player ejected.
|
||||||
|
-- @param #RESCUEHELO self
|
||||||
|
-- @param Core.Event#EVENTDATA EventData Event data.
|
||||||
|
function RESCUEHELO:_OnEventCrashOrEject(EventData)
|
||||||
|
self:F2({eventdata=EventData})
|
||||||
|
|
||||||
|
-- NOTE: Careful here. Eject and crash events will probably happen for the same unit!
|
||||||
|
|
||||||
|
-- Check that there is an initiating unit in the event data.
|
||||||
|
if EventData and EventData.IniUnit then
|
||||||
|
|
||||||
|
-- Crashed or ejected unit.
|
||||||
|
local unit=EventData.IniUnit
|
||||||
|
local unitname=tostring(EventData.IniUnitName)
|
||||||
|
|
||||||
|
-- Check that it was not the rescue helo itself that crashed.
|
||||||
|
if EventData.IniGroupName~=self.helo:GetName() then
|
||||||
|
|
||||||
|
-- Debug.
|
||||||
|
self:T(string.format("Unit %s crashed or ejected.", unitname))
|
||||||
|
|
||||||
|
-- Unit "alive" and in our rescue zone.
|
||||||
|
if unit:IsAlive() and unit:IsInZone(self.rescuezone) then
|
||||||
|
|
||||||
|
-- Get coordinate of crashed unit.
|
||||||
|
local coord=unit:GetCoordinate()
|
||||||
|
|
||||||
|
-- Debug mark on map.
|
||||||
|
coord:MarkToCoalition(string.format("Crash site of unit %s.", unitname), self.helo:GetCoalition())
|
||||||
|
|
||||||
|
-- Only rescue if helo is "running" and not, e.g., rescuing already.
|
||||||
|
if self:IsRunning() then
|
||||||
|
self:Rescue(coord)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
self:I(string.format("Rescue helo %s crashed!", unitname))
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- FSM states
|
-- FSM states
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
@ -270,7 +393,8 @@ function RESCUEHELO:onafterStart(From, Event, To)
|
|||||||
-- Handle events.
|
-- Handle events.
|
||||||
--self:HandleEvent(EVENTS.Birth)
|
--self:HandleEvent(EVENTS.Birth)
|
||||||
self:HandleEvent(EVENTS.Land)
|
self:HandleEvent(EVENTS.Land)
|
||||||
--self:HandleEvent(EVENTS.Crash)
|
self:HandleEvent(EVENTS.Crash, self._OnEventCrashOrEject)
|
||||||
|
self:HandleEvent(EVENTS.Ejection, self._OnEventCrashOrEject)
|
||||||
|
|
||||||
-- Delay before formation is started.
|
-- Delay before formation is started.
|
||||||
local delay=120
|
local delay=120
|
||||||
@ -356,7 +480,7 @@ function RESCUEHELO:onafterStatus(From, Event, To)
|
|||||||
self:I(text)
|
self:I(text)
|
||||||
|
|
||||||
-- If fuel < threshold ==> send helo to home base!
|
-- If fuel < threshold ==> send helo to home base!
|
||||||
if fuel<self.lowfuel then
|
if fuel<self.lowfuel and self:IsRunning() then
|
||||||
self:RTB()
|
self:RTB()
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -364,47 +488,60 @@ function RESCUEHELO:onafterStatus(From, Event, To)
|
|||||||
self:__Status(-60)
|
self:__Status(-60)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- On after Stop event. Unhandle events and stop status updates.
|
--- On after "Run" event. FSM will go to "Running" state. If formation is topped, it will be started again.
|
||||||
-- @param #RESCUEHELO self
|
-- @param #RESCUEHELO self
|
||||||
-- @param #string From From state.
|
-- @param #string From From state.
|
||||||
-- @param #string Event Event.
|
-- @param #string Event Event.
|
||||||
-- @param #string To To state.
|
-- @param #string To To state.
|
||||||
function RESCUEHELO:onafterStop(From, Event, To)
|
function RESCUEHELO:onafterRun(From, Event, To)
|
||||||
--self:UnHandleEvent(EVENTS.Birth)
|
|
||||||
self:UnHandleEvent(EVENTS.Land)
|
-- Restart formation if stopped.
|
||||||
|
if self.formation:Is("Stopped") then
|
||||||
|
self.formation:Start()
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Handle landing event of rescue helo.
|
--- On after "Rescue" event. Helo will fly to the given coordinate, orbit there for 5 minutes and then return to the carrier.
|
||||||
-- @param #RESCUEHELO self
|
-- @param #RESCUEHELO self
|
||||||
-- @param Core.Event#EVENTDATA EventData Event data.
|
-- @param #string From From state.
|
||||||
function RESCUEHELO:OnEventLand(EventData)
|
-- @param #string Event Event.
|
||||||
local group=EventData.IniGroup --Wrapper.Group#GROUP
|
-- @param #string To To state.
|
||||||
|
-- @param Core.Point#COORDINATE RescueCoord Coordinate where the rescue should happen
|
||||||
|
function RESCUEHELO:onafterRescue(From, Event, To, RescueCoord)
|
||||||
|
|
||||||
if group:IsAlive() then
|
-- Debug message.
|
||||||
local groupname=group:GetName()
|
local text=string.format("Helo %s is send to rescue mission.", self.helo:GetName())
|
||||||
|
self:I(text)
|
||||||
|
|
||||||
if groupname:match(self.helogroupname) then
|
-- Waypoint array.
|
||||||
|
local wp={}
|
||||||
|
|
||||||
-- Respawn the Helo.
|
--local RescueTask=self.helo:TaskControlled(self.helo:TaskOrbitCircle(20, 2, RescueCoord), self.helo:TaskCondition(nil, nil, nil, nil, 5*60, nil))
|
||||||
self:I(string.format("Respawning rescue helo group group %s at home base.", groupname))
|
|
||||||
|
|
||||||
if self.takeoff==SPAWN.Takeoff.Air then
|
-- Rescue task: Orbit at crash site for 5 minutes.
|
||||||
|
local RescueTask={}
|
||||||
|
RescueTask.id="ControlledTask"
|
||||||
|
RescueTask.params={}
|
||||||
|
RescueTask.params.task=self.helo:TaskOrbit(RescueCoord, 20, 2)
|
||||||
|
RescueTask.params.stopCondition={duration=300}
|
||||||
|
|
||||||
self:E("ERROR: Rescue helo %s landed. This should not happen for Takeoff=Air!", groupname)
|
-- Set Waypoints.
|
||||||
|
wp[1]=self.helo:GetCoordinate():WaypointAirTurningPoint(nil, 200, {}, "Current Position")
|
||||||
|
wp[2]=RescueCoord:SetAltitude(50):WaypointAirTurningPoint(nil, 200, {RescueTask}, "Crash Site")
|
||||||
|
wp[3]=self.airbase:GetCoordinate():SetAltitude(70):WaypointAirLanding(200, self.airbase, {}, "Land at Home Base")
|
||||||
|
|
||||||
else
|
-- Initialize WP and route tanker.
|
||||||
|
self.helo:WayPointInitialize(wp)
|
||||||
|
|
||||||
-- Respawn helo at current airbase.
|
-- Set task.
|
||||||
self.helo=group:RespawnAtCurrentAirbase()
|
self.helo:Route(wp, 1)
|
||||||
|
|
||||||
end
|
-- Stop formation.
|
||||||
|
self.formation:Stop()
|
||||||
-- Restart the formation.
|
|
||||||
self.formation:__Start(10)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- On before RTB event. Check if takeoff type is air and if so respawn the helo and deny RTB transition.
|
--- On before RTB event. Check if takeoff type is air and if so respawn the helo and deny RTB transition.
|
||||||
-- @param #RESCUEHELO self
|
-- @param #RESCUEHELO self
|
||||||
-- @param #string From From state.
|
-- @param #string From From state.
|
||||||
@ -414,6 +551,7 @@ end
|
|||||||
function RESCUEHELO:onbeforeRTB(From, Event, To)
|
function RESCUEHELO:onbeforeRTB(From, Event, To)
|
||||||
|
|
||||||
if self.takeoff==SPAWN.Takeoff.Air then
|
if self.takeoff==SPAWN.Takeoff.Air then
|
||||||
|
-- For takeoff in air, we just respawn the helo with full fuel.
|
||||||
|
|
||||||
-- Debug message.
|
-- Debug message.
|
||||||
local text=string.format("Respawning rescue helo group %s in air.", self.helo:GetName())
|
local text=string.format("Respawning rescue helo group %s in air.", self.helo:GetName())
|
||||||
@ -438,25 +576,38 @@ end
|
|||||||
function RESCUEHELO:onafterRTB(From, Event, To)
|
function RESCUEHELO:onafterRTB(From, Event, To)
|
||||||
|
|
||||||
-- Debug message.
|
-- Debug message.
|
||||||
local text=string.format("Helo %s returning to airbase %s.", self.helo:GetName(), self.airbase:GetName())
|
local text=string.format("Rescue helo %s is returning to airbase %s.", self.helo:GetName(), self.airbase:GetName())
|
||||||
self:I(text)
|
self:I(text)
|
||||||
|
|
||||||
local waypoints={}
|
-- Waypoint array.
|
||||||
|
local wp={}
|
||||||
|
|
||||||
-- Set landingwaypoint
|
-- Set landing waypoint at home base.
|
||||||
local wp=self.carrier:GetCoordinate():WaypointAirLanding(300, self.airbase, nil, "Landing")
|
wp[1]=self.helo:GetCoordinate():WaypointAirTurningPoint(nil, 300, {}, "Current Position")
|
||||||
table.insert(waypoints, wp)
|
wp[2]=self.airbase:GetCoordinate():SetAltitude(70):WaypointAirLanding(300, self.airbase, {}, "Landing at Home Base")
|
||||||
|
|
||||||
-- Initialize WP and route tanker.
|
-- Initialize WP and route tanker.
|
||||||
self.helo:WayPointInitialize(waypoints)
|
self.helo:WayPointInitialize(wp)
|
||||||
|
|
||||||
-- Set task.
|
-- Set task.
|
||||||
self.helo:Route(waypoints, 1)
|
self.helo:Route(wp, 1)
|
||||||
|
|
||||||
-- Stop formation.
|
-- Stop formation.
|
||||||
self.formation:Stop()
|
self.formation:Stop()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- On after Stop event. Unhandle events and stop status updates.
|
||||||
|
-- @param #RESCUEHELO self
|
||||||
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To To state.
|
||||||
|
function RESCUEHELO:onafterStop(From, Event, To)
|
||||||
|
self:UnHandleEvent(EVENTS.Land)
|
||||||
|
self:UnHandleEvent(EVENTS.Crash)
|
||||||
|
self:UnHandleEvent(EVENTS.Ejection)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user