Merge pull request #1754 from FlightControl-Master/FF/Ops

Updates
This commit is contained in:
Frank 2022-08-03 09:14:12 +02:00 committed by GitHub
commit 7affd05247
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 511 additions and 128 deletions

View File

@ -979,13 +979,15 @@ function DATABASE:_RegisterClients()
for ClientName, ClientTemplate in pairs( self.Templates.ClientsByName ) do for ClientName, ClientTemplate in pairs( self.Templates.ClientsByName ) do
self:I(string.format("Register Client: %s", tostring(ClientName))) self:I(string.format("Register Client: %s", tostring(ClientName)))
self:AddClient( ClientName ) local client=self:AddClient( ClientName )
client.SpawnCoord=COORDINATE:New(ClientTemplate.x, ClientTemplate.alt, ClientTemplate.y)
end end
return self return self
end end
--- @param #DATABASE self --- Private method that registeres all static objects.
-- @param #DATABASE self
function DATABASE:_RegisterStatics() function DATABASE:_RegisterStatics()
local CoalitionsData={GroupsRed=coalition.getStaticObjects(coalition.side.RED), GroupsBlue=coalition.getStaticObjects(coalition.side.BLUE), GroupsNeutral=coalition.getStaticObjects(coalition.side.NEUTRAL)} local CoalitionsData={GroupsRed=coalition.getStaticObjects(coalition.side.RED), GroupsBlue=coalition.getStaticObjects(coalition.side.BLUE), GroupsNeutral=coalition.getStaticObjects(coalition.side.NEUTRAL)}
@ -1036,11 +1038,6 @@ function DATABASE:_RegisterAirbases()
text=text.."]" text=text.."]"
self:I(text) self:I(text)
-- Check for DCS bug IDs.
if airbaseID~=airbase:GetID() then
--self:E("WARNING: :getID does NOT match :GetID!")
end
end end
return self return self

View File

@ -398,7 +398,7 @@ end
-- @param #ZONE_BASE self -- @param #ZONE_BASE self
-- @return #table Table with four entries, e.g. {1, 0, 0, 0.15}. First three are RGB color code. Fourth is the transparency Alpha value. -- @return #table Table with four entries, e.g. {1, 0, 0, 0.15}. First three are RGB color code. Fourth is the transparency Alpha value.
function ZONE_BASE:GetColor() function ZONE_BASE:GetColor()
return self.Color return self.Color or {1, 0, 0, 0.15}
end end
--- Get RGB color of zone. --- Get RGB color of zone.
@ -406,9 +406,10 @@ end
-- @return #table Table with three entries, e.g. {1, 0, 0}, which is the RGB color code. -- @return #table Table with three entries, e.g. {1, 0, 0}, which is the RGB color code.
function ZONE_BASE:GetColorRGB() function ZONE_BASE:GetColorRGB()
local rgb={} local rgb={}
rgb[1]=self.Color[1] local Color=self:GetColor()
rgb[2]=self.Color[2] rgb[1]=Color[1]
rgb[3]=self.Color[3] rgb[2]=Color[2]
rgb[3]=Color[3]
return rgb return rgb
end end
@ -416,7 +417,8 @@ end
-- @param #ZONE_BASE self -- @param #ZONE_BASE self
-- @return #number Alpha value. -- @return #number Alpha value.
function ZONE_BASE:GetColorAlpha() function ZONE_BASE:GetColorAlpha()
local alpha=self.Color[4] local Color=self:GetColor()
local alpha=Color[4]
return alpha return alpha
end end
@ -443,7 +445,7 @@ end
-- @param #ZONE_BASE self -- @param #ZONE_BASE self
-- @return #table Table with four entries, e.g. {1, 0, 0, 0.15}. First three are RGB color code. Fourth is the transparency Alpha value. -- @return #table Table with four entries, e.g. {1, 0, 0, 0.15}. First three are RGB color code. Fourth is the transparency Alpha value.
function ZONE_BASE:GetFillColor() function ZONE_BASE:GetFillColor()
return self.FillColor return self.FillColor or {1, 0, 0, 0.15}
end end
--- Get RGB fill color of zone. --- Get RGB fill color of zone.
@ -451,9 +453,10 @@ end
-- @return #table Table with three entries, e.g. {1, 0, 0}, which is the RGB color code. -- @return #table Table with three entries, e.g. {1, 0, 0}, which is the RGB color code.
function ZONE_BASE:GetFillColorRGB() function ZONE_BASE:GetFillColorRGB()
local rgb={} local rgb={}
rgb[1]=self.FillColor[1] local FillColor=self:GetFillColor()
rgb[2]=self.FillColor[2] rgb[1]=FillColor[1]
rgb[3]=self.FillColor[3] rgb[2]=FillColor[2]
rgb[3]=FillColor[3]
return rgb return rgb
end end
@ -461,7 +464,8 @@ end
-- @param #ZONE_BASE self -- @param #ZONE_BASE self
-- @return #number Alpha value. -- @return #number Alpha value.
function ZONE_BASE:GetFillColorAlpha() function ZONE_BASE:GetFillColorAlpha()
local alpha=self.FillColor[4] local FillColor=self:GetFillColor()
local alpha=FillColor[4]
return alpha return alpha
end end
@ -1683,7 +1687,7 @@ end
--- @type ZONE_POLYGON_BASE --- @type ZONE_POLYGON_BASE
-- --@field #ZONE_POLYGON_BASE.ListVec2 Polygon The polygon defined by an array of @{DCS#Vec2}. -- @field #ZONE_POLYGON_BASE.ListVec2 Polygon The polygon defined by an array of @{DCS#Vec2}.
-- @extends #ZONE_BASE -- @extends #ZONE_BASE
@ -2387,8 +2391,8 @@ do -- ZONE_ELASTIC
--- Update the convex hull of the polygon. --- Update the convex hull of the polygon.
-- This uses the [Graham scan](https://en.wikipedia.org/wiki/Graham_scan). -- This uses the [Graham scan](https://en.wikipedia.org/wiki/Graham_scan).
-- @param #ZONE_ELASTIC self -- @param #ZONE_ELASTIC self
-- @field #number Delay Delay in seconds before the zone is updated. Default 0. -- @param #number Delay Delay in seconds before the zone is updated. Default 0.
-- @field #boolean Draw Draw the zone. Default `nil`. -- @param #boolean Draw Draw the zone. Default `nil`.
-- @return #ZONE_ELASTIC self -- @return #ZONE_ELASTIC self
function ZONE_ELASTIC:Update(Delay, Draw) function ZONE_ELASTIC:Update(Delay, Draw)
@ -2420,6 +2424,7 @@ do -- ZONE_ELASTIC
end end
end end
return self
end end
--- Start the updating scheduler. --- Start the updating scheduler.
@ -2427,7 +2432,7 @@ do -- ZONE_ELASTIC
-- @param #number Tstart Time in seconds before the updating starts. -- @param #number Tstart Time in seconds before the updating starts.
-- @param #number dT Time interval in seconds between updates. Default 60 sec. -- @param #number dT Time interval in seconds between updates. Default 60 sec.
-- @param #number Tstop Time in seconds after which the updating stops. Default `nil`. -- @param #number Tstop Time in seconds after which the updating stops. Default `nil`.
-- @field #boolean Draw Draw the zone. Default `nil`. -- @param #boolean Draw Draw the zone. Default `nil`.
-- @return #ZONE_ELASTIC self -- @return #ZONE_ELASTIC self
function ZONE_ELASTIC:StartUpdate(Tstart, dT, Tstop, Draw) function ZONE_ELASTIC:StartUpdate(Tstart, dT, Tstop, Draw)

View File

@ -792,7 +792,7 @@ function FOX:onafterMissileLaunch(From, Event, To, missile)
local text=string.format("Missile launch detected! Distance %.1f NM, bearing %03d°.", UTILS.MetersToNM(distance), bearing) local text=string.format("Missile launch detected! Distance %.1f NM, bearing %03d°.", UTILS.MetersToNM(distance), bearing)
-- Say notching headings. -- Say notching headings.
BASE:ScheduleOnce(5, FOX._SayNotchingHeadings, self, player, missile.weapon) self:ScheduleOnce(5, FOX._SayNotchingHeadings, self, player, missile.weapon)
--TODO: ALERT or INFO depending on whether this is a direct target. --TODO: ALERT or INFO depending on whether this is a direct target.
--TODO: lauchalertall option. --TODO: lauchalertall option.
@ -1114,6 +1114,13 @@ end
-- Event Functions -- Event Functions
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- FOX event handler for event birth.
-- @param #FOX self
-- @param Core.Event#EVENTDATA EventData
function FOX:OnEventPlayerEnterAircraft(EventData)
end
--- FOX event handler for event birth. --- FOX event handler for event birth.
-- @param #FOX self -- @param #FOX self
-- @param Core.Event#EVENTDATA EventData -- @param Core.Event#EVENTDATA EventData
@ -1155,7 +1162,7 @@ function FOX:OnEventBirth(EventData)
-- Add F10 radio menu for player. -- Add F10 radio menu for player.
if not self.menudisabled then if not self.menudisabled then
SCHEDULER:New(nil, self._AddF10Commands, {self,_unitName}, 0.1) self:ScheduleOnce(0.1, FOX._AddF10Commands, self, _unitname)
end end
-- Player data. -- Player data.

View File

@ -1978,7 +1978,8 @@ function AIRBOSS:New( carriername, alias )
-- Init carrier parameters. -- Init carrier parameters.
if self.carriertype == AIRBOSS.CarrierType.STENNIS then if self.carriertype == AIRBOSS.CarrierType.STENNIS then
self:_InitStennis() --self:_InitStennis()
self:_InitNimitz()
elseif self.carriertype == AIRBOSS.CarrierType.ROOSEVELT then elseif self.carriertype == AIRBOSS.CarrierType.ROOSEVELT then
self:_InitNimitz() self:_InitNimitz()
elseif self.carriertype == AIRBOSS.CarrierType.LINCOLN then elseif self.carriertype == AIRBOSS.CarrierType.LINCOLN then

View File

@ -51,6 +51,7 @@
-- @field Core.Spawn#SPAWN parkingGuard Parking guard spawner. -- @field Core.Spawn#SPAWN parkingGuard Parking guard spawner.
-- @field #table holdingpatterns Holding points. -- @field #table holdingpatterns Holding points.
-- @field #number hpcounter Counter for holding zones. -- @field #number hpcounter Counter for holding zones.
-- @field Sound.SRS#MSRSQUEUE msrsqueue Queue for TTS transmissions using MSRS class.
-- @field Sound.SRS#MSRS msrsTower Moose SRS wrapper. -- @field Sound.SRS#MSRS msrsTower Moose SRS wrapper.
-- @field Sound.SRS#MSRS msrsPilot Moose SRS wrapper. -- @field Sound.SRS#MSRS msrsPilot Moose SRS wrapper.
-- @field #number Tlastmessage Time stamp (abs.) of last radio transmission. -- @field #number Tlastmessage Time stamp (abs.) of last radio transmission.
@ -326,7 +327,7 @@ FLIGHTCONTROL.FlightStatus={
--- FlightControl class version. --- FlightControl class version.
-- @field #string version -- @field #string version
FLIGHTCONTROL.version="0.7.0" FLIGHTCONTROL.version="0.7.1"
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO list -- TODO list
@ -405,6 +406,9 @@ function FLIGHTCONTROL:New(AirbaseName, Frequency, Modulation, PathToSRS)
self:SetMarkHoldingPattern(true) self:SetMarkHoldingPattern(true)
self:SetRunwayRepairtime() self:SetRunwayRepairtime()
-- Init msrs queue.
self.msrsqueue=MSRSQUEUE:New(self.alias)
-- SRS for Tower. -- SRS for Tower.
self.msrsTower=MSRS:New(PathToSRS, Frequency, Modulation) self.msrsTower=MSRS:New(PathToSRS, Frequency, Modulation)
self:SetSRSTower() self:SetSRSTower()
@ -977,6 +981,7 @@ end
-- @param #FLIGHTCONTROL self -- @param #FLIGHTCONTROL self
function FLIGHTCONTROL:onbeforeStatusUpdate() function FLIGHTCONTROL:onbeforeStatusUpdate()
--[[
if self.Tlastmessage then if self.Tlastmessage then
local Tnow=timer.getAbsTime() local Tnow=timer.getAbsTime()
@ -1001,6 +1006,21 @@ function FLIGHTCONTROL:onbeforeStatusUpdate()
self:T2(self.lid..string.format("Last radio sent %d>%d sec ago. Status update allowed", dT, self.dTmessage)) self:T2(self.lid..string.format("Last radio sent %d>%d sec ago. Status update allowed", dT, self.dTmessage))
end end
end end
]]
local Tqueue=self.msrsqueue:CalcTransmisstionDuration()
if Tqueue>0 then
-- Debug info.
local text=string.format("Still got %d messages in the radio queue. Will call status again in %.1f sec", #self.msrsqueue, Tqueue)
self:I(self.lid..text)
-- Call status again in dt seconds.
self:__StatusUpdate(-Tqueue)
-- Deny transition.
return false
end
return true return true
end end
@ -3274,7 +3294,9 @@ function FLIGHTCONTROL:_PlayerAbortLanding(groupname)
if flight then if flight then
if flight:IsLanding() and self:IsControlling(flight) then local flightstatus=self:GetFlightStatus(flight)
if (flight:IsLanding() or flightstatus==FLIGHTCONTROL.FlightStatus.LANDING) and self:IsControlling(flight) then
-- Call sign. -- Call sign.
local callsign=self:_GetCallsignName(flight) local callsign=self:_GetCallsignName(flight)
@ -3358,8 +3380,11 @@ function FLIGHTCONTROL:_PlayerRequestDirectLanding(groupname)
else else
-- Runway.
local runway=self:GetActiveRunwayText()
-- Message text. -- Message text.
local text=string.format("%s, affirmative! Confirm approach", callsign) local text=string.format("%s, affirmative, runway %s. Confirm approach!", callsign, runway)
-- Send message. -- Send message.
self:TransmissionTower(text, flight, 10) self:TransmissionTower(text, flight, 10)
@ -4025,12 +4050,15 @@ function FLIGHTCONTROL:_CheckFlights()
local onRunway=self:IsCoordinateRunway(coord) local onRunway=self:IsCoordinateRunway(coord)
-- Debug output. -- Debug output.
self:I(self.lid..string.format("Player %s speed %.1f knots (max=%.1f) onRunway=%s", playerElement.playerName, UTILS.MpsToKnots(speed), UTILS.MpsToKnots(self.speedLimitTaxi), tostring(onRunway))) self:T(self.lid..string.format("Player %s speed %.1f knots (max=%.1f) onRunway=%s", playerElement.playerName, UTILS.MpsToKnots(speed), UTILS.MpsToKnots(self.speedLimitTaxi), tostring(onRunway)))
if speed and speed>self.speedLimitTaxi and not onRunway then if speed and speed>self.speedLimitTaxi and not onRunway then
-- Callsign.
local callsign=self:_GetCallsignName(flight)
-- Radio text. -- Radio text.
local text="Slow down, you are taxiing too fast!" local text=string.format("%s, slow down, you are taxiing too fast!", callsign)
-- Radio message to player. -- Radio message to player.
self:TransmissionTower(text, flight) self:TransmissionTower(text, flight)
@ -4228,17 +4256,19 @@ function FLIGHTCONTROL:TransmissionTower(Text, Flight, Delay)
-- Spoken text. -- Spoken text.
local text=self:_GetTextForSpeech(Text) local text=self:_GetTextForSpeech(Text)
-- Tower radio call.
self.msrsTower:PlayText(text, Delay)
-- "Subtitle". -- "Subtitle".
local subgroups=nil
if Flight and not Flight.isAI then if Flight and not Flight.isAI then
local playerData=Flight:_GetPlayerData() local playerData=Flight:_GetPlayerData()
if playerData.subtitles then if playerData.subtitles then
self:TextMessageToFlight(Text, Flight, 5, false, Delay) subgroups=subgroups or {}
table.insert(subgroups, Flight.group)
end end
end end
-- New transmission.
local transmission=self.msrsqueue:NewTransmission(text, nil, self.msrsTower, nil, 1, subgroups, Text)
-- Set time stamp. Can be in the future. -- Set time stamp. Can be in the future.
self.Tlastmessage=timer.getAbsTime() + (Delay or 0) self.Tlastmessage=timer.getAbsTime() + (Delay or 0)
@ -4263,23 +4293,29 @@ function FLIGHTCONTROL:TransmissionPilot(Text, Flight, Delay)
-- Spoken text. -- Spoken text.
local text=self:_GetTextForSpeech(Text) local text=self:_GetTextForSpeech(Text)
-- MSRS instance to use.
local msrs=self.msrsPilot
if Flight.useSRS and Flight.msrs then if Flight.useSRS and Flight.msrs then
-- Pilot radio call using settings of the FLIGHTGROUP. We just overwrite the frequency. -- Pilot radio call using settings of the FLIGHTGROUP. We just overwrite the frequency.
Flight.msrs:PlayTextExt(text, Delay, self.frequency, self.modulation, Gender, Culture, Voice, Volume, Label) msrs=Flight.msrs
else
-- Pilot radio call using the default settings.
self.msrsPilot:PlayText(text, Delay)
end end
-- "Subtitle". -- "Subtitle".
local subgroups=nil
if Flight and not Flight.isAI then if Flight and not Flight.isAI then
self:TextMessageToFlight(Text, Flight, 5, false, Delay) local playerData=Flight:_GetPlayerData()
if playerData.subtitles then
subgroups=subgroups or {}
table.insert(subgroups, Flight.group)
end
end end
-- Add transmission to msrsqueue.
self.msrsqueue:NewTransmission(text, nil, msrs, nil, 1, subgroups, Text, nil, self.frequency, self.modulation)
end end
-- Set time stamp. -- Set time stamp.
@ -4439,7 +4475,7 @@ end
--- Get text for text-to-speech. --- Get text for text-to-speech.
-- Numbers are spaced out, e.g. "Heading 180" becomes "Heading 1 8 0 ". -- Numbers are spaced out, e.g. "Heading 180" becomes "Heading 1 8 0 ".
-- @param #FLIGHTCONTROL self -- @param #FLIGHTCONTROL self
-- @param #string text -- @param #string text Original text.
-- @return #string Spoken text. -- @return #string Spoken text.
function FLIGHTCONTROL:_GetTextForSpeech(text) function FLIGHTCONTROL:_GetTextForSpeech(text)

View File

@ -576,10 +576,11 @@ end
-- @param Ops.OpsGroup#OPSGROUP.Element Element (Optional) Only check status for given element. -- @param Ops.OpsGroup#OPSGROUP.Element Element (Optional) Only check status for given element.
-- @return #boolean If true, flight is parking after spawned. -- @return #boolean If true, flight is parking after spawned.
function FLIGHTGROUP:IsParking(Element) function FLIGHTGROUP:IsParking(Element)
local is=self:Is("Parking")
if Element then if Element then
return Element.status==OPSGROUP.ElementStatus.PARKING is=Element.status==OPSGROUP.ElementStatus.PARKING
end end
return self:Is("Parking") return is
end end
--- Check if is taxiing to the runway. --- Check if is taxiing to the runway.
@ -587,10 +588,11 @@ end
-- @param Ops.OpsGroup#OPSGROUP.Element Element (Optional) Only check status for given element. -- @param Ops.OpsGroup#OPSGROUP.Element Element (Optional) Only check status for given element.
-- @return #boolean If true, flight is taxiing after engine start up. -- @return #boolean If true, flight is taxiing after engine start up.
function FLIGHTGROUP:IsTaxiing(Element) function FLIGHTGROUP:IsTaxiing(Element)
local is=self:Is("Taxiing")
if Element then if Element then
return Element.status==OPSGROUP.ElementStatus.TAXIING is=Element.status==OPSGROUP.ElementStatus.TAXIING
end end
return self:Is("Taxiing") return is
end end
--- Check if flight is airborne or cruising. --- Check if flight is airborne or cruising.
@ -598,17 +600,19 @@ end
-- @param Ops.OpsGroup#OPSGROUP.Element Element (Optional) Only check status for given element. -- @param Ops.OpsGroup#OPSGROUP.Element Element (Optional) Only check status for given element.
-- @return #boolean If true, flight is airborne. -- @return #boolean If true, flight is airborne.
function FLIGHTGROUP:IsAirborne(Element) function FLIGHTGROUP:IsAirborne(Element)
local is=self:Is("Airborne") or self:Is("Cruising")
if Element then if Element then
return Element.status==OPSGROUP.ElementStatus.AIRBORNE is=Element.status==OPSGROUP.ElementStatus.AIRBORNE
end end
return self:Is("Airborne") or self:Is("Cruising") return is
end end
--- Check if flight is airborne or cruising. --- Check if flight is airborne or cruising.
-- @param #FLIGHTGROUP self -- @param #FLIGHTGROUP self
-- @return #boolean If true, flight is airborne. -- @return #boolean If true, flight is airborne.
function FLIGHTGROUP:IsCruising() function FLIGHTGROUP:IsCruising()
return self:Is("Cruising") local is=self:Is("Cruising")
return is
end end
--- Check if flight is landing. --- Check if flight is landing.
@ -616,10 +620,11 @@ end
-- @param Ops.OpsGroup#OPSGROUP.Element Element (Optional) Only check status for given element. -- @param Ops.OpsGroup#OPSGROUP.Element Element (Optional) Only check status for given element.
-- @return #boolean If true, flight is landing, i.e. on final approach. -- @return #boolean If true, flight is landing, i.e. on final approach.
function FLIGHTGROUP:IsLanding(Element) function FLIGHTGROUP:IsLanding(Element)
local is=self:Is("Landing")
if Element then if Element then
return Element.status==OPSGROUP.ElementStatus.LANDING is=Element.status==OPSGROUP.ElementStatus.LANDING
end end
return self:Is("Landing") return is
end end
--- Check if flight has landed and is now taxiing to its parking spot. --- Check if flight has landed and is now taxiing to its parking spot.
@ -627,10 +632,11 @@ end
-- @param Ops.OpsGroup#OPSGROUP.Element Element (Optional) Only check status for given element. -- @param Ops.OpsGroup#OPSGROUP.Element Element (Optional) Only check status for given element.
-- @return #boolean If true, flight has landed -- @return #boolean If true, flight has landed
function FLIGHTGROUP:IsLanded(Element) function FLIGHTGROUP:IsLanded(Element)
local is=self:Is("Landed")
if Element then if Element then
return Element.status==OPSGROUP.ElementStatus.LANDED is=Element.status==OPSGROUP.ElementStatus.LANDED
end end
return self:Is("Landed") return is
end end
--- Check if flight has arrived at its destination parking spot. --- Check if flight has arrived at its destination parking spot.
@ -638,45 +644,51 @@ end
-- @param Ops.OpsGroup#OPSGROUP.Element Element (Optional) Only check status for given element. -- @param Ops.OpsGroup#OPSGROUP.Element Element (Optional) Only check status for given element.
-- @return #boolean If true, flight has arrived at its destination and is parking. -- @return #boolean If true, flight has arrived at its destination and is parking.
function FLIGHTGROUP:IsArrived(Element) function FLIGHTGROUP:IsArrived(Element)
local is=self:Is("Arrived")
if Element then if Element then
return Element.status==OPSGROUP.ElementStatus.ARRIVED is=Element.status==OPSGROUP.ElementStatus.ARRIVED
end end
return self:Is("Arrived") return is
end end
--- Check if flight is inbound and traveling to holding pattern. --- Check if flight is inbound and traveling to holding pattern.
-- @param #FLIGHTGROUP self -- @param #FLIGHTGROUP self
-- @return #boolean If true, flight is holding. -- @return #boolean If true, flight is holding.
function FLIGHTGROUP:IsInbound() function FLIGHTGROUP:IsInbound()
return self:Is("Inbound") local is=self:Is("Inbound")
return is
end end
--- Check if flight is holding and waiting for landing clearance. --- Check if flight is holding and waiting for landing clearance.
-- @param #FLIGHTGROUP self -- @param #FLIGHTGROUP self
-- @return #boolean If true, flight is holding. -- @return #boolean If true, flight is holding.
function FLIGHTGROUP:IsHolding() function FLIGHTGROUP:IsHolding()
return self:Is("Holding") local is=self:Is("Holding")
return is
end end
--- Check if flight is going for fuel. --- Check if flight is going for fuel.
-- @param #FLIGHTGROUP self -- @param #FLIGHTGROUP self
-- @return #boolean If true, flight is refueling. -- @return #boolean If true, flight is refueling.
function FLIGHTGROUP:IsGoing4Fuel() function FLIGHTGROUP:IsGoing4Fuel()
return self:Is("Going4Fuel") local is=self:Is("Going4Fuel")
return is
end end
--- Check if helo(!) flight is ordered to land at a specific point. --- Check if helo(!) flight is ordered to land at a specific point.
-- @param #FLIGHTGROUP self -- @param #FLIGHTGROUP self
-- @return #boolean If true, group has task to land somewhere. -- @return #boolean If true, group has task to land somewhere.
function FLIGHTGROUP:IsLandingAt() function FLIGHTGROUP:IsLandingAt()
return self:Is("LandingAt") local is=self:Is("LandingAt")
return is
end end
--- Check if helo(!) flight has landed at a specific point. --- Check if helo(!) flight has landed at a specific point.
-- @param #FLIGHTGROUP self -- @param #FLIGHTGROUP self
-- @return #boolean If true, has landed somewhere. -- @return #boolean If true, has landed somewhere.
function FLIGHTGROUP:IsLandedAt() function FLIGHTGROUP:IsLandedAt()
return self:Is("LandedAt") is=self:Is("LandedAt")
return is
end end
--- Check if flight is low on fuel. --- Check if flight is low on fuel.

View File

@ -52,8 +52,6 @@
-- --
-- === -- ===
-- --
-- ![Banner Image](..\Presentations\ATIS\ATIS_Main.png)
--
-- # The MSRS Concept -- # The MSRS Concept
-- --
-- This class allows to broadcast sound files or text via Simple Radio Standalone (SRS). -- This class allows to broadcast sound files or text via Simple Radio Standalone (SRS).
@ -143,7 +141,7 @@ MSRS = {
--- MSRS class version. --- MSRS class version.
-- @field #string version -- @field #string version
MSRS.version="0.0.6" MSRS.version="0.1.0"
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO list -- TODO list
@ -181,7 +179,7 @@ function MSRS:New(PathToSRS, Frequency, Modulation, Volume)
self:SetCoalition() self:SetCoalition()
self:SetLabel() self:SetLabel()
self:SetVolume() self:SetVolume()
self.lid = string.format("%s-%s | ",self.name,self.version) self.lid = string.format("%s-%s | ", self.name, self.version)
if not io or not os then if not io or not os then
self:E(self.lid.."***** ERROR - io or os NOT desanitized! MSRS will not work!") self:E(self.lid.."***** ERROR - io or os NOT desanitized! MSRS will not work!")
@ -455,20 +453,9 @@ function MSRS:PlaySoundFile(Soundfile, Delay)
-- Append file. -- Append file.
command=command..' --file="'..tostring(soundfile)..'"' command=command..' --file="'..tostring(soundfile)..'"'
-- Execute command.
self:_ExecCommand(command) self:_ExecCommand(command)
--[[
command=command.." > bla.txt"
-- Debug output.
self:I(string.format("MSRS PlaySoundfile command=%s", command))
-- Execute SRS command.
local x=os.execute(command)
]]
end end
return self return self
@ -494,16 +481,6 @@ function MSRS:PlaySoundText(SoundText, Delay)
-- Execute command. -- Execute command.
self:_ExecCommand(command) self:_ExecCommand(command)
--[[
command=command.." > bla.txt"
-- Debug putput.
self:I(string.format("MSRS PlaySoundfile command=%s", command))
-- Execute SRS command.
local x=os.execute(command)
]]
end end
return self return self
@ -538,6 +515,13 @@ end
-- @param #MSRS self -- @param #MSRS self
-- @param #string Text Text message. -- @param #string Text Text message.
-- @param #number Delay Delay in seconds, before the message is played. -- @param #number Delay Delay in seconds, before the message is played.
-- @param #table Frequencies Radio frequencies.
-- @param #table Modulations Radio modulations.
-- @param #string Gender Gender.
-- @param #string Culture Culture.
-- @param #string Voice Voice.
-- @param #number Volume Volume.
-- @param #string Label Label.
-- @return #MSRS self -- @return #MSRS self
function MSRS:PlayTextExt(Text, Delay, Frequencies, Modulations, Gender, Culture, Voice, Volume, Label) function MSRS:PlayTextExt(Text, Delay, Frequencies, Modulations, Gender, Culture, Voice, Volume, Label)
@ -765,5 +749,354 @@ function MSRS:_GetCommand(freqs, modus, coal, gender, voice, culture, volume, sp
end end
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Manages radio transmissions.
--
-- The purpose of the MSRSQUEUE class is to manage SRS text-to-speech (TTS) messages using the MSRS class.
-- This can be used to submit multiple TTS messages and the class takes care that they are transmitted one after the other (and not overlapping).
--
-- @type MSRSQUEUE
-- @field #string ClassName Name of the class "MSRSQUEUE".
-- @field #string lid ID for dcs.log.
-- @field #table queue The queue of transmissions.
-- @field #string alias Name of the radio queue.
-- @field #number dt Time interval in seconds for checking the radio queue.
-- @field #number Tlast Time (abs) when the last transmission finished.
-- @field #boolean checking If `true`, the queue update function is scheduled to be called again.
-- @extends Core.Base#BASE
MSRSQUEUE = {
ClassName = "MSRSQUEUE",
Debugmode = nil,
lid = nil,
queue = {},
alias = nil,
dt = nil,
Tlast = nil,
checking = nil,
}
--- Radio queue transmission data.
-- @type MSRSQUEUE.Transmission
-- @field #string text Text to be transmitted.
-- @field Sound.SRS#MSRS msrs MOOSE SRS object.
-- @field #number duration Duration in seconds.
-- @field #table subgroups Groups to send subtitle to.
-- @field #string subtitle Subtitle of the transmission.
-- @field #number subduration Duration of the subtitle being displayed.
-- @field #number frequency Frequency.
-- @field #number modulation Modulation.
-- @field #number Tstarted Mission time (abs) in seconds when the transmission started.
-- @field #boolean isplaying If true, transmission is currently playing.
-- @field #number Tplay Mission time (abs) in seconds when the transmission should be played.
-- @field #number interval Interval in seconds before next transmission.
--- Create a new MSRSQUEUE object for a given radio frequency/modulation.
-- @param #MSRSQUEUE self
-- @param #string alias (Optional) Name of the radio queue.
-- @return #MSRSQUEUE self The MSRSQUEUE object.
function MSRSQUEUE:New(alias)
-- Inherit base
local self=BASE:Inherit(self, BASE:New()) --#MSRSQUEUE
self.alias=alias or "My Radio"
self.dt=1.0
self.lid=string.format("MSRSQUEUE %s | ", self.alias)
return self
end
--- Clear the radio queue.
-- @param #MSRSQUEUE self
-- @return #MSRSQUEUE self The MSRSQUEUE object.
function MSRSQUEUE:Clear()
self:I(self.lid.."Clearning MSRSQUEUE")
self.queue={}
return self
end
--- Add a transmission to the radio queue.
-- @param #MSRSQUEUE self
-- @param #MSRSQUEUE.Transmission transmission The transmission data table.
-- @return #MSRSQUEUE self
function MSRSQUEUE:AddTransmission(transmission)
-- Init.
transmission.isplaying=false
transmission.Tstarted=nil
-- Add to queue.
table.insert(self.queue, transmission)
-- Start checking.
if not self.checking then
self:_CheckRadioQueue()
end
return self
end
--- Create a new transmission and add it to the radio queue.
-- @param #MSRSQUEUE self
-- @param #string text Text to play.
-- @param #number duration Duration in seconds the file lasts. Default is determined by number of characters of the text message.
-- @param Sound.SRS#MSRS msrs MOOSE SRS object.
-- @param #number tstart Start time (abs) seconds. Default now.
-- @param #number interval Interval in seconds after the last transmission finished.
-- @param #table subgroups Groups that should receive the subtiltle.
-- @param #string subtitle Subtitle displayed when the message is played.
-- @param #number subduration Duration [sec] of the subtitle being displayed. Default 5 sec.
-- @param #number frequency Radio frequency if other than MSRS default.
-- @param #number modulation Radio modulation if other then MSRS default.
-- @return #MSRSQUEUE.Transmission Radio transmission table.
function MSRSQUEUE:NewTransmission(text, duration, msrs, tstart, interval, subgroups, subtitle, subduration, frequency, modulation)
-- Sanity checks.
if not text then
self:E(self.lid.."ERROR: No text specified.")
return nil
end
if type(text)~="string" then
self:E(self.lid.."ERROR: Text specified is NOT a string.")
return nil
end
-- Create a new transmission object.
local transmission={} --#MSRSQUEUE.Transmission
transmission.text=text
transmission.duration=duration or STTS.getSpeechTime(text)
transmission.msrs=msrs
transmission.Tplay=tstart or timer.getAbsTime()
transmission.subtitle=subtitle
transmission.interval=interval or 0
transmission.frequency=frequency
transmission.modulation=modulation
transmission.subgroups=subgroups
if transmission.subtitle then
transmission.subduration=subduration or transmission.duration
else
transmission.subduration=0 --nil
end
-- Add transmission to queue.
self:AddTransmission(transmission)
return transmission
end
--- Broadcast radio message.
-- @param #MSRSQUEUE self
-- @param #MSRSQUEUE.Transmission transmission The transmission.
function MSRSQUEUE:Broadcast(transmission)
if transmission.frequency then
transmission.msrs:PlayTextExt(transmission.text, nil, transmission.frequency, transmission.modulation, Gender, Culture, Voice, Volume, Label)
else
transmission.msrs:PlayText(transmission.text)
end
local function texttogroup(gid)
-- Text to group.
trigger.action.outTextForGroup(gid, transmission.subtitle, transmission.subduration, true)
end
if transmission.subgroups and #transmission.subgroups>0 then
for _,_group in pairs(transmission.subgroups) do
local group=_group --Wrapper.Group#GROUP
if group and group:IsAlive() then
local gid=group:GetID()
self:ScheduleOnce(4, texttogroup, gid)
end
end
end
end
--- Calculate total transmission duration of all transmission in the queue.
-- @param #MSRSQUEUE self
-- @return #number Total transmission duration.
function MSRSQUEUE:CalcTransmisstionDuration()
local Tnow=timer.getAbsTime()
local T=0
for _,_transmission in pairs(self.queue) do
local transmission=_transmission --#MSRSQUEUE.Transmission
if transmission.isplaying then
-- Playing for dt seconds.
local dt=Tnow-transmission.Tstarted
T=T+transmission.duration-dt
else
T=T+transmission.duration
end
end
return T
end
--- Check radio queue for transmissions to be broadcasted.
-- @param #MSRSQUEUE self
-- @param #number delay Delay in seconds before checking.
function MSRSQUEUE:_CheckRadioQueue(delay)
-- Transmissions in queue.
local N=#self.queue
-- Debug info.
self:T2(self.lid..string.format("Check radio queue %s: delay=%.3f sec, N=%d, checking=%s", self.alias, delay or 0, N, tostring(self.checking)))
if delay and delay>0 then
-- Delayed call.
self:ScheduleOnce(delay, MSRSQUEUE._CheckRadioQueue, self)
-- Checking on.
self.checking=true
else
-- Check if queue is empty.
if N==0 then
-- Debug info.
self:T(self.lid..string.format("Check radio queue %s empty ==> disable checking", self.alias))
-- Queue is now empty. Nothing to else to do. We start checking again, if a transmission is added.
self.checking=false
return
end
-- Get current abs time.
local time=timer.getAbsTime()
-- Checking on.
self.checking=true
-- Set dt.
local dt=self.dt
local playing=false
local next=nil --#MSRSQUEUE.Transmission
local remove=nil
for i,_transmission in ipairs(self.queue) do
local transmission=_transmission --#MSRSQUEUE.Transmission
-- Check if transmission time has passed.
if time>=transmission.Tplay then
-- Check if transmission is currently playing.
if transmission.isplaying then
-- Check if transmission is finished.
if time>=transmission.Tstarted+transmission.duration then
-- Transmission over.
transmission.isplaying=false
-- Remove ith element in queue.
remove=i
-- Store time last transmission finished.
self.Tlast=time
else -- still playing
-- Transmission is still playing.
playing=true
dt=transmission.duration-(time-transmission.Tstarted)
end
else -- not playing yet
local Tlast=self.Tlast
if transmission.interval==nil then
-- Not playing ==> this will be next.
if next==nil then
next=transmission
end
else
if Tlast==nil or time-Tlast>=transmission.interval then
next=transmission
else
end
end
-- We got a transmission or one with an interval that is not due yet. No need for anything else.
if next or Tlast then
break
end
end
else
-- Transmission not due yet.
end
end
-- Found a new transmission.
if next~=nil and not playing then
-- Debug info.
self:T(self.lid..string.format("Broadcasting text=\"%s\" at T=%.3f", next.text, time))
-- Call SRS.
self:Broadcast(next)
next.isplaying=true
next.Tstarted=time
dt=next.duration
end
-- Remove completed call from queue.
if remove then
-- Remove from queue.
table.remove(self.queue, remove)
N=N-1
-- Check if queue is empty.
if #self.queue==0 then
-- Debug info.
self:T(self.lid..string.format("Check radio queue %s empty ==> disable checking", self.alias))
self.checking=false
return
end
end
-- Check queue.
self:_CheckRadioQueue(dt)
end
end
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

View File

@ -20,11 +20,11 @@ do
-- @type FIFO -- @type FIFO
-- @field #string ClassName Name of the class. -- @field #string ClassName Name of the class.
-- @field #string lid Class id string for output to DCS log file. -- @field #string lid Class id string for output to DCS log file.
-- @field #string version Version of FiFo -- @field #string version Version of FiFo.
-- @field #number counter -- @field #number counter Counter.
-- @field #number pointer -- @field #number pointer Pointer.
-- @field #table stackbypointer -- @field #table stackbypointer Stack by pointer.
-- @field #table stackbyid -- @field #table stackbyid Stack by ID.
-- @extends Core.Base#BASE -- @extends Core.Base#BASE
--- ---
@ -45,12 +45,12 @@ FIFO = {
stackbyid = {} stackbyid = {}
} }
--- Instantiate a new FIFO Stack --- Instantiate a new FIFO Stack.
-- @param #FIFO self -- @param #FIFO self
-- @return #FIFO self -- @return #FIFO self
function FIFO:New() function FIFO:New()
-- Inherit everything from BASE class. -- Inherit everything from BASE class.
local self=BASE:Inherit(self, BASE:New()) local self=BASE:Inherit(self, BASE:New()) --#FIFO
self.pointer = 0 self.pointer = 0
self.counter = 0 self.counter = 0
self.stackbypointer = {} self.stackbypointer = {}
@ -62,7 +62,7 @@ function FIFO:New()
return self return self
end end
--- Empty FIFO Stack --- Empty FIFO Stack.
-- @param #FIFO self -- @param #FIFO self
-- @return #FIFO self -- @return #FIFO self
function FIFO:Clear() function FIFO:Clear()
@ -77,7 +77,7 @@ function FIFO:Clear()
return self return self
end end
--- FIFO Push Object to Stack --- FIFO Push Object to Stack.
-- @param #FIFO self -- @param #FIFO self
-- @param #table Object -- @param #table Object
-- @param #string UniqueID (optional) - will default to current pointer + 1. Note - if you intend to use `FIFO:GetIDStackSorted()` keep the UniqueID numerical! -- @param #string UniqueID (optional) - will default to current pointer + 1. Note - if you intend to use `FIFO:GetIDStackSorted()` keep the UniqueID numerical!
@ -97,7 +97,7 @@ function FIFO:Push(Object,UniqueID)
return self return self
end end
--- FIFO Pull Object from Stack --- FIFO Pull Object from Stack.
-- @param #FIFO self -- @param #FIFO self
-- @return #table Object or nil if stack is empty -- @return #table Object or nil if stack is empty
function FIFO:Pull() function FIFO:Pull()

View File

@ -154,7 +154,7 @@ function STTS.getSpeechTime(length,speed,isGoogle)
length = string.len(length) length = string.len(length)
end end
return math.ceil(length/cps) return length/cps --math.ceil(length/cps)
end end
--- Text to speech function. --- Text to speech function.

View File

@ -1081,12 +1081,10 @@ function AIRBASE:_InitParkingSpots()
-- Get client coordinates. -- Get client coordinates.
local function isClient(coord) local function isClient(coord)
local clients=_DATABASE.CLIENTS local clients=_DATABASE.CLIENTS
for clientname, client in pairs(clients) do for clientname, _client in pairs(clients) do
local template=_DATABASE:GetGroupTemplateFromUnitName(clientname) local client=_client --Wrapper.Client#CLIENT
local units=template.units if client and client.SpawnCoord then
for i,unit in pairs(units) do local dist=client.SpawnCoord:Get2DDistance(coord)
local Coord=COORDINATE:New(unit.x, unit.alt, unit.y)
local dist=Coord:Get2DDistance(coord)
if dist<2 then if dist<2 then
return true, clientname return true, clientname
end end
@ -1743,16 +1741,6 @@ function AIRBASE:_InitRunways(IncludeInverse)
return ((b.z - a.z)*(c.x - a.x) - (b.x - a.x)*(c.z - a.z)) > 0 return ((b.z - a.z)*(c.x - a.x) - (b.x - a.x)*(c.z - a.z)) > 0
end end
--[[
local a={x=1, y=0, z=0}
local A={x=0, y=0, z=0}
local b={x=0, y=0, z=1}
local c={x=0, y=0, z=-1}
local bl=isLeft(A, a, b)
local cl=isLeft(A, a, c)
env.info(string.format("b left=%s, c left=%s", tostring(bl), tostring(cl)))
]]
for i,j in pairs(rpairs) do for i,j in pairs(rpairs) do
local ri=Runways[i] --#AIRBASE.Runway local ri=Runways[i] --#AIRBASE.Runway
local rj=Runways[j] --#AIRBASE.Runway local rj=Runways[j] --#AIRBASE.Runway
@ -1769,13 +1757,6 @@ function AIRBASE:_InitRunways(IncludeInverse)
local b=UTILS.VecSubstract(rj.center, ri.center) local b=UTILS.VecSubstract(rj.center, ri.center)
b=UTILS.VecAdd(ri.center, b) b=UTILS.VecAdd(ri.center, b)
--[[
local ca=COORDINATE:NewFromVec3(a)
local cb=COORDINATE:NewFromVec3(b)
c0:ArrowToAll(ca, nil , {0,1,0})
c0:ArrowToAll(cb, nil , {0,0,1})
]]
-- Check if rj is left of ri. -- Check if rj is left of ri.
local left=isLeft(c0, a, b) local left=isLeft(c0, a, b)
@ -1992,7 +1973,7 @@ function AIRBASE:SetActiveRunwayLanding(Name, PreferLeft)
end end
if runway then if runway then
self:I("Setting active runway for landing as "..self:GetRunwayName(runway)) self:I(string.format("%s: Setting active runway for landing as %s", self.AirbaseName, self:GetRunwayName(runway)))
else else
self:E("ERROR: Could not set the runway for landing!") self:E("ERROR: Could not set the runway for landing!")
end end
@ -2040,7 +2021,7 @@ function AIRBASE:SetActiveRunwayTakeoff(Name, PreferLeft)
end end
if runway then if runway then
self:I("Setting active runway for takeoff as "..self:GetRunwayName(runway)) self:I(string.format("%s: Setting active runway for takeoff as %s", self.AirbaseName, self:GetRunwayName(runway)))
else else
self:E("ERROR: Could not set the runway for takeoff!") self:E("ERROR: Could not set the runway for takeoff!")
end end

View File

@ -13,6 +13,17 @@
--- The CLIENT class --- The CLIENT class
-- @type CLIENT -- @type CLIENT
-- @field #string ClassName Name of the class.
-- @field #string ClientName Name of the client.
-- @field #string ClientBriefing Briefing.
-- @field #function ClientCallBack Callback function.
-- @field #table ClientParameters Parameters of the callback function.
-- @field #number ClientGroupID Group ID of the client.
-- @field #string ClientGroupName Group name.
-- @field #boolean ClientAlive Client alive.
-- @field #boolean ClientAlive2 Client alive 2.
-- @field #table Players Player table.
-- @field Core.Point#COORDINATE SpawnCoord Spawn coordinate from the template.
-- @extends Wrapper.Unit#UNIT -- @extends Wrapper.Unit#UNIT