This commit is contained in:
Frank
2020-04-02 18:00:14 +02:00
parent 618b4d7ded
commit 8b9e49cfc6
8 changed files with 282 additions and 36 deletions
+6 -4
View File
@@ -113,18 +113,20 @@ end
-- @param #number dt (Optional) Time step in seconds for checking the queue. Default 0.01 sec.
-- @return #RADIOQUEUE self The RADIOQUEUE object.
function RADIOQUEUE:Start(delay, dt)
-- Delay before start.
self.delay=delay or 1
-- Time interval for queue check.
self.dt=dt or 0.01
-- Debug message.
self:I(self.lid..string.format("Starting RADIOQUEUE %s on Frequency %.2f MHz [modulation=%d] in %.1f seconds (dt=%.3f sec)", self.alias, self.frequency/1000000, self.modulation, delay, dt))
-- Start Scheduler.
if self.schedonce then
self:_CheckRadioQueueDelayed(self.delta)
self:_CheckRadioQueueDelayed(delay)
else
--self.RQid=self.scheduler:Schedule(self, self._CheckRadioQueue, {}, delay, dt)
self.RQid=self.scheduler:Schedule(nil, RADIOQUEUE._CheckRadioQueue, {self}, delay, dt)
end
@@ -3846,7 +3846,7 @@ function WAREHOUSE:onafterAddAsset(From, Event, To, group, ngroups, forceattribu
if group:IsAlive()==true then
self:_DebugMessage(string.format("Removing group %s.", group:GetName()), 5)
-- Setting parameter to false, i.e. creating NO dead or remove unit event, seems to not confuse the dispatcher logic.
-- Create a RemoveUnit event to let the FLIGHTCONTROL now, the parking is now free.
-- Create a RemoveUnit event to let the FLIGHTCONTROL know, the parking is now free.
-- TODO: Need to check if my above comment not to confuse the dispatcher logic is broken by this!
group:Destroy()
end
+7 -3
View File
@@ -1102,7 +1102,7 @@ function AIRWING:onafterNewAsset(From, Event, To, asset, assignment)
squad:GetModex(asset)
asset.terminalType=AIRBASE.TerminalType.OpenBig
--asset.terminalType=AIRBASE.TerminalType.OpenBig
-- Add asset to squadron.
table.insert(squad.assets, asset)
@@ -1143,11 +1143,15 @@ function AIRWING:onafterAssetSpawned(From, Event, To, group, asset, request)
-- Set airwing.
flightgroup:SetAirwing(self)
--flightgroup.group:OptionProhibitAfterburner(true)
-- Set asset flightgroup.
asset.flightgroup=flightgroup
local squadron=self:GetSquadronOfAsset(asset)
local Tacan=squadron:GetTACAN()
if Tacan then
flightgroup:SetTACAN(Tacan)
end
-- Not requested any more.
asset.requested=nil
+40 -1
View File
@@ -581,6 +581,43 @@ function AUFTRAG:NewCAS(OrbitCoordinate, OrbitSpeed, Heading, Leg, ZoneCAS, Targ
return mission
end
--- Create a CAS mission.
-- @param #AUFTRAG self
-- @param Core.Point#COORDINATE OrbitCoordinate Where to orbit. Altitude is also taken from the coordinate.
-- @param #number OrbitSpeed Orbit speed in knots. Default 350 kts.
-- @param #number Heading Heading of race-track pattern in degrees. Default 270 (East to West).
-- @param #number Leg Length of race-track in NM. Default 10 NM.
-- @param Core.Zone#ZONE_RADIUS ZoneCAS Circular CAS zone. Detected targets in this zone will be engaged.
-- @param #table TargetTypes Table of target types. Default {"Helicopters", "Ground Units", "Light armed ships"}.
-- @return #AUFTRAG self
function AUFTRAG:NewFACA(OrbitCoordinate, OrbitSpeed, Heading, Leg, ZoneCAS, TargetTypes)
-- Ensure given TargetTypes parameter is a table.
if TargetTypes then
if type(TargetTypes)~="table" then
TargetTypes={TargetTypes}
end
end
-- Create ORBIT first.
local mission=self:NewORBIT(OrbitCoordinate, OrbitSpeed, Heading, Leg)
-- CAS paramters.
mission.type=AUFTRAG.Type.FACA
mission.engageZone=ZoneCAS or ZONE_RADIUS:New("CAS Zone", OrbitCoordinate:GetVec2(), Leg)
mission.engageTargetTypes=TargetTypes or {"Helicopters", "Ground Units", "Light armed ships"}
mission:_SetLogID()
mission.missionTask=ENUMS.MissionTask.AFAC
mission.optionROE=ENUMS.ROE.ReturnFire
mission.optionROT=ENUMS.ROT.PassiveDefense
mission.DCStask=mission:GetDCSMissionTask()
return mission
end
--- Create a BAI mission.
@@ -2004,7 +2041,7 @@ function AUFTRAG:GetDCSMissionTask()
-- FAC Mission --
-----------------
local DCStask=CONTROLLABLE.TaskFAC_AttackGroup(nil, self.engageAsGroup, self.engageWeaponType, Designation, Datalink)
local DCStask=CONTROLLABLE.TaskFAC_AttackGroup(nil, self.engageAsGroup, self.engageWeaponType, self.facDesignation, self.facDatalink)
table.insert(DCStasks, DCStask)
@@ -2087,6 +2124,8 @@ function AUFTRAG:GetDCSMissionTask()
-----------------------
-- TODO: What?
local DCStask=CONTROLLABLE.TaskEmbarking(self,Vec2,GroupSetForEmbarking,Duration,DistributionGroupSet)
else
self:E(self.lid..string.format("ERROR: Unknown mission task!"))
@@ -1888,11 +1888,12 @@ function FLIGHTCONTROL:_LandAI(flight, parking)
self:_RemoveFlightFromQueue(self.Qholding, flight, "holding")
-- Altitude above ground for a glide slope of 3 degrees..
local alpha=math.rad(3)
local x1=UTILS.NMToMeters(10)
local x2=UTILS.NMToMeters(5)
local x1=flight.ishelo and UTILS.NMToMeters(5.0) or UTILS.NMToMeters(10)
local x2=flight.ishelo and UTILS.NMToMeters(2.5) or UTILS.NMToMeters(5)
local alpha=math.rad(3)
local h1=x1*math.tan(alpha)
local h2=x2*math.tan(alpha)
local SpeedLand=140
local SpeedTo=180
+160 -21
View File
@@ -68,8 +68,11 @@
-- @field #number TACANchannel TACAN channel.
-- @field #string TACANmode TACAN mode, i.e. "Y" (or "X").
-- @field #string TACANmorse TACAN morse code.
-- @field #number RadioFreq Default Radio frequency in MHz.
-- @field #number RadioModu Default Radio modulation `radio.modulation.AM` or `radio.modulation.FM`.
-- @field #number radioFreq Default Radio frequency in MHz.
-- @field #number radioModu Default Radio modulation `radio.modulation.AM` or `radio.modulation.FM`.
-- @field #boolean radioUse Use radio. If false, communications are turned off.
-- @field #boolean radioOn If true, radio is currently turned on.
-- @field Core.RadioQueue#RADIOQUEUE radioQueue Radio queue.
-- @field #number CallsignName Call sign name.
-- @field #number CallsignNumber Call sign number.
-- @field #boolean EPLRS If true, turn EPLRS data link on.
@@ -81,6 +84,10 @@
--
-- @field Ops.Auftrag#AUFTRAG missionpaused Paused mission.
--
-- @field Core.Point#COORDINATE position Current position of the group.
-- @field #number traveldist Distance traveled in meters. This is a lower bound!
-- @field #number fuelmass Inital fuel in kg.
--
-- @extends Core.Fsm#FSM
--- *To invent an airplane is nothing. To build one is something. To fly is everything.* -- Otto Lilienthal
@@ -213,7 +220,7 @@ FLIGHTGROUP = {
inzones = nil,
groupinitialized = nil,
ishelo = nil,
beacon = nil,
beacon = nil,
}
@@ -368,7 +375,7 @@ FLIGHTGROUP.version="0.3.8"
-- DONE: Get ammo.
-- DONE: Get pylons.
-- DONE: Fuel threshhold ==> RTB.
-- TODO: ROE
-- DONE: ROE
-- TODO: Options EPLRS, Afterburner restrict etc.
-- TODO: Add TACAN beacon.
-- NOGO: Respawn? With correct loadout, fuelstate. Solved in DCS 2.5.6!
@@ -812,6 +819,112 @@ function FLIGHTGROUP:SetParkingSpots(airbase, spots)
return self
end
--- Set TACAN parameters. AA TACANs are aleays on "Y" band.
-- @param #FLIGHTGROUP self
-- @param #number Channel TACAN channel.
-- @param #string Morse Morse code. Default "XX".
-- @return #FLIGHTGROUP self
function FLIGHTGROUP:SetTACAN(Channel, Morse)
self.TACANchannel=Channel
self.TACANmorse=Morse or "XXX"
self.TACANactive=false
self.TACANon=true
return self
end
--- Set Radio parameters.
-- @param #FLIGHTGROUP self
-- @param #number Frequency Radio frequency in MHz. Default 305 MHz.
-- @param #number Modulation Radio modulation. Default `radio.Modulation.AM`.
-- @return #FLIGHTGROUP self
function FLIGHTGROUP:SetRadio(Frequency, Modulation)
self.radioFreq=Frequency or 305
self.radioModu=Modulation or radio.modulation.AM
self.radioOn=false
self.radioUse=true
return self
end
--- Activate TACAN beacon.
-- @param #FLIGHTGROUP self
-- @return #FLIGHTGROUP self
function FLIGHTGROUP:SwitchTACANOn()
if self:IsAlive() then
local unit=self.group:GetUnit(1)
if unit and unit:IsAlive() then
-- Create a new beacon and activate TACAN.
if not self.beacon then
self.beacon=BEACON:New(unit)
end
self.beacon:ActivateTACAN(self.TACANchannel, "Y", self.TACANmorse, true)
self.TACANactive=true
end
end
return self
end
--- Deactivate TACAN beacon.
-- @param #FLIGHTGROUP self
-- @return #FLIGHTGROUP self
function FLIGHTGROUP:SwitchTACANOff()
if self.beacon then
self.beacon:StopAATACAN()
end
self.TACANactive=false
end
--- Turn radio on.
-- @param #FLIGHTGROUP self
-- @param #number Frequency Radio frequency in MHz. Default 305 MHz.
-- @param #number Modulation Radio modulation. Default `radio.Modulation.AM`.
-- @return #FLIGHTGROUP self
function FLIGHTGROUP:SwitchRadioOn()
self.group:SetOption(AI.Option.Air.id.SILENCE, false)
self.group:CommandSetFrequency(self.radioFreq, self.radioModu)
self.radioOn=true
return self
end
--- Turn radio off.
-- @param #FLIGHTGROUP self
-- @return #FLIGHTGROUP self
function FLIGHTGROUP:SwitchRadioOff()
self.group:SetOption(AI.Option.Air.id.SILENCE, true)
self.radioOn=false
return self
end
--- Set the FLIGHTCONTROL controlling this flight group.
-- @param #FLIGHTGROUP self
-- @param Ops.FlightControl#FLIGHTCONTROL flightcontrol The FLIGHTCONTROL object.
@@ -1578,8 +1691,13 @@ function FLIGHTGROUP:onafterFlightStatus(From, Event, To)
-- Fuel State
---
local position=self:GetCoordinate()
local dist=self.position:Get3DDistance(position)
self.traveldist=self.traveldist+dist
-- Only if group is in air.
if self:IsAlive() and self.group:IsAirborne() then
if self:IsAlive() and self.group:IsAirborne(true) then
local fuelmin=self:GetFuelMin()
@@ -2197,6 +2315,15 @@ function FLIGHTGROUP:onafterFlightSpawned(From, Event, To)
self.group:SetOption(AI.Option.Air.id.PROHIBIT_JETT, true)
self.group:SetOption(AI.Option.Air.id.PROHIBIT_AB, true)
self.group:SetOption(AI.Option.Air.id.RTB_ON_BINGO, false)
if self.TACANon then
self:SwitchTACANOn()
end
if self.RadioOn then
end
--self.group:SetOption(AI.Option.Air.id.RADAR_USING, AI.Option.Air.val.RADAR_USING.FOR_CONTINUOUS_SEARCH)
@@ -2743,18 +2870,19 @@ function FLIGHTGROUP:onafterRTB(From, Event, To, airbase, SpeedTo, SpeedHold, Sp
-- Defaults:
SpeedTo=SpeedTo or UTILS.KmphToKnots(self.speedmax*0.75)
SpeedHold=SpeedHold or 250
SpeedLand=SpeedLand or 170
SpeedHold=SpeedHold or (self.ishelo and 80 or 250)
SpeedLand=SpeedLand or (self.ishelo and 40 or 170)
-- Debug message.
local text=string.format("Flight group set to hold at airbase %s. SpeedTo=%d, SpeedHold=%d, SpeedLand=%d", airbase:GetName(), SpeedTo, SpeedHold, SpeedLand)
MESSAGE:New(text, 10, "DEBUG"):ToAllIf(self.Debug)
self:T(self.lid..text)
local althold=self.ishelo and 1000 or 6000
-- Holding points.
local c0=self.group:GetCoordinate()
local p0=airbase:GetZone():GetRandomCoordinate():SetAltitude(UTILS.FeetToMeters(6000))
local p0=airbase:GetZone():GetRandomCoordinate():SetAltitude(UTILS.FeetToMeters(althold))
local p1=nil
local wpap=nil
@@ -2779,7 +2907,7 @@ function FLIGHTGROUP:onafterRTB(From, Event, To, airbase, SpeedTo, SpeedHold, Sp
self.flightcontrol:_AddFlightToInboundQueue(self)
end
-- Altitude above ground for a glide slope of 3°.
-- Altitude above ground for a glide slope of 3.
local x1=self.ishelo and UTILS.NMToMeters(5.0) or UTILS.NMToMeters(10)
local x2=self.ishelo and UTILS.NMToMeters(2.5) or UTILS.NMToMeters(5)
local alpha=math.rad(3)
@@ -2876,7 +3004,7 @@ function FLIGHTGROUP:onafterWait(From, Event, To, Coord, Altitude, Speed)
end
if Tsuspend and not allowed then
self:__WAIT(Tsuspend, Coord, Altitude, Speed)
self:__Wait(Tsuspend, Coord, Altitude, Speed)
end
return allowed
@@ -2894,8 +3022,8 @@ end
function FLIGHTGROUP:onafterWait(From, Event, To, Coord, Altitude, Speed)
Coord=Coord or self.group:GetCoordinate()
Altitude=Altitude or 10000
Speed=Speed or 250
Altitude=Altitude or (self.ishelo and 1000 or 10000)
Speed=Speed or (self.ishelo and 80 or 250)
-- Debug message.
local text=string.format("Flight group set to wait/orbit at altitude %d m and speed %.1f km/h", Altitude, Speed)
@@ -2909,6 +3037,7 @@ function FLIGHTGROUP:onafterWait(From, Event, To, Coord, Altitude, Speed)
-- Set task.
self:SetTask(TaskOrbit)
end
@@ -3866,6 +3995,18 @@ function FLIGHTGROUP:_InitGroup()
-- Cruise speed: 70% of max speed but within limit.
self.speedCruise=math.min(self.speedmax*0.7, speedCruiseLimit)
-- Initial fuel mass.
self.fuelmass=self.template.pylons.fuel
self.traveldist=0
self.position=self:GetCoordinate()
-- Radio parameters from template.
-- TODO: Need to check that I don't overwrite the settings from :SetRadio()
self.radioOn=self.template.communication
self.radioFreq=self.template.frequency
self.radioModu=self.template.modulation
local unit=self.group:GetUnit(1)
if unit then
@@ -4848,20 +4989,18 @@ end
--- Set parking spot of element.
-- @param #FLIGHTGROUP self
-- @param #FLIGHTGROUP.FlightElement Element The element.
-- @param #FLIGHTGROUP.Element Element The element.
-- @param Wrapper.Airbase#AIRBASE.ParkingSpot Spot Parking Spot.
function FLIGHTGROUP:_SetElementParkingAt(Element, Spot)
-- Element is parking here.
Element.parking=Spot
if Spot then
if self.flightcontrol then
if Spot and self.flightcontrol then
-- Set parking spot to OCCUPIED.
self.flightcontrol:SetParkingOccupied(Element.parking, Element.name)
end
-- Set parking spot to OCCUPIED.
self.flightcontrol:SetParkingOccupied(Element.parking, Element.name)
end
end
@@ -4874,7 +5013,7 @@ function FLIGHTGROUP:_SetElementParkingFree(Element)
if Element.parking then
-- Set parking to FREE.
if self.flightcontrol and Element.parking then
if self.flightcontrol then
self.flightcontrol:SetParkingFree(Element.parking)
end
+35
View File
@@ -36,6 +36,9 @@
-- @field #string attribute Generalized attribute of the squadron template group.
-- @field #number tankerSystem For tanker squads, the refuel system used (boom=0 or probpe=1). Default nil.
-- @field #number refuelSystem For refuelable squads, the refuel system used (boom=0 or probpe=1). Default nil.
-- @field #number TACANmin TACAN min channel.
-- @field #number TACANmax TACAN max channel.
-- @field #table TACANused Table of used TACAN channels.
-- @extends Core.Fsm#FSM
--- Be surprised!
@@ -68,6 +71,9 @@ SQUADRON = {
engageRange = nil,
tankerSystem = nil,
refuelSystem = nil,
TACANmin = nil,
TACANmax = nil,
TACANused = {},
}
--- SQUADRON class version.
@@ -361,6 +367,35 @@ function SQUADRON:GetModex(Asset)
end
--- Get an unused TACAN channel.
-- @param #SQUADRON self
-- @param Ops.AirWing#AIRWING.SquadronAsset Asset The airwing asset.
-- @return #number TACAN channel or *nil* if no channel is free.
function SQUADRON:GetTACAN()
if self.TACANmin and self.TACANmax then
for channel=self.TACANmin, self.TACANmax do
if not self.TACANused[channel] then
self.TACANused[channel]=true
return channel
end
end
end
return nil
end
--- "Return" a used TACAN channel.
-- @param #SQUADRON self
-- @param #number channel The channel that is available again.
function SQUADRON:ReturnTACAN(channel)
self.TACANused[channel]=false
end
--- Check if squadron is "OnDuty".
-- @param #SQUADRON self
-- @return #boolean If true, squdron is in state "OnDuty".
@@ -785,13 +785,39 @@ function CONTROLLABLE:CommandEPLRS(SwitchOnOff, Delay)
if Delay and Delay>0 then
SCHEDULER:New(nil, self.CommandEPLRS, {self, SwitchOnOff}, Delay)
else
self:T(string.format("EPLRS=%s for controllable %s (id=%s)", tostring(SwitchOnOff), tostring(self:GetName()), tostring(_id)))
self:T(string.format("EPLRS=%s for controllable %s (id=%s)", tostring(SwitchOnOff), tostring(self:GetName()), tostring(self:GetID())))
self:SetCommand(CommandEPLRS)
end
return self
end
--- Set radio frequency. See [DCS command EPLRS](https://wiki.hoggitworld.com/view/DCS_command_setFrequency)
-- @param #CONTROLLABLE self
-- @param #number Frequency Radio frequency in MHz.
-- @param #number Modulation Radio modulation. Default `radio.modulation.AM`.
-- @param #number Delay (Optional) Delay in seconds before the frequncy is set. Default is immediately.
-- @return #CONTROLLABLE self
function CONTROLLABLE:CommandSetFrequency(Frequency, Modulation, Delay)
local CommandSetFrequency = {
id = 'SetFrequency',
params = {
frequency = Frequency,
modulation = Modulation or radio.modulation.AM,
}
}
if Delay and Delay>0 then
SCHEDULER:New(nil, self.CommandSetFrequency, {self, Frequency, Modulation}, Delay)
else
self:SetCommand(CommandSetFrequency)
end
return self
end
--- Set EPLRS data link on/off.
-- @param #CONTROLLABLE self
-- @param #boolean SwitchOnOff If true (or nil) switch EPLRS on. If false switch off.
@@ -1034,9 +1060,9 @@ end
--- (AIR) Move the controllable to a Vec2 Point, wait for a defined duration and embark a controllable.
-- @param #CONTROLLABLE self
-- @param DCS#Vec2 Vec2 The point where to wait. Needs to have x and y components.
-- @param Core.Set#SET_GROUP GroupSetForEmparking Set of groups to embark.
-- @param Core.Set#SET_GROUP GroupSetForEmbarking Set of groups to embark.
-- @param #number Duration (Optional) The maximum duration in seconds to wait until all groups have embarked.
-- @param Core.Set#SET_GROUP (Optional) DistributionGroupSet Set of groups identifying the groups needing to board specific helicopters.
-- @param Core.Set#SET_GROUP DistributionGroupSet (Optional) Set of groups identifying the groups needing to board specific helicopters.
-- @return DCS#Task The DCS task structure.
function CONTROLLABLE:TaskEmbarking(Vec2, GroupSetForEmbarking, Duration, DistributionGroupSet)