From 7084d9e084582f300f9327a5891ab5084b39eeeb Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Thu, 15 Sep 2022 13:59:16 +0200 Subject: [PATCH] #OPSGROUP * Allow for customized CallSigns #PLAYERTASK * SRS output finetuning --- Moose Development/Moose/Ops/FlightControl.lua | 97 ++++++++++++------- Moose Development/Moose/Ops/FlightGroup.lua | 4 +- Moose Development/Moose/Ops/OpsGroup.lua | 30 +++--- Moose Development/Moose/Ops/PlayerTask.lua | 26 ++++- 4 files changed, 108 insertions(+), 49 deletions(-) diff --git a/Moose Development/Moose/Ops/FlightControl.lua b/Moose Development/Moose/Ops/FlightControl.lua index 840d2e3e2..b10b2471d 100644 --- a/Moose Development/Moose/Ops/FlightControl.lua +++ b/Moose Development/Moose/Ops/FlightControl.lua @@ -327,7 +327,7 @@ FLIGHTCONTROL.FlightStatus={ --- FlightControl class version. -- @field #string version -FLIGHTCONTROL.version="0.7.2" +FLIGHTCONTROL.version="0.7.3" ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- TODO list @@ -357,8 +357,9 @@ FLIGHTCONTROL.version="0.7.2" -- @param #number Frequency Radio frequency in MHz. Default 143.00 MHz. Can also be given as a `#table` of multiple frequencies. -- @param #number Modulation Radio modulation: 0=AM (default), 1=FM. See `radio.modulation.AM` and `radio.modulation.FM` enumerators. Can also be given as a `#table` of multiple modulations. -- @param #string PathToSRS Path to the directory, where SRS is located. +-- @param #number Port Port of SRS Server, defaults to 5002 -- @return #FLIGHTCONTROL self -function FLIGHTCONTROL:New(AirbaseName, Frequency, Modulation, PathToSRS) +function FLIGHTCONTROL:New(AirbaseName, Frequency, Modulation, PathToSRS, Port) -- Inherit everything from FSM class. local self=BASE:Inherit(self, FSM:New()) -- #FLIGHTCONTROL @@ -406,15 +407,23 @@ function FLIGHTCONTROL:New(AirbaseName, Frequency, Modulation, PathToSRS) self:SetMarkHoldingPattern(true) self:SetRunwayRepairtime() + -- Set SRS Port + self:SetSRSPort(Port or 5002) + + -- Set Callsign Options + self:SetCallSignOptions(true,true) + -- Init msrs queue. self.msrsqueue=MSRSQUEUE:New(self.alias) -- SRS for Tower. self.msrsTower=MSRS:New(PathToSRS, Frequency, Modulation) + self.msrsTower:SetPort(self.Port) self:SetSRSTower() -- SRS for Pilot. self.msrsPilot=MSRS:New(PathToSRS, Frequency, Modulation) + self.msrsPilot:SetPort(self.Port) self:SetSRSPilot() -- Wait at least 10 seconds after last radio message before calling the next status update. @@ -567,6 +576,15 @@ function FLIGHTCONTROL:SetFrequency(Frequency, Modulation) return self end +--- Set the SRS server port. +-- @param #FLIGHTCONTROL self +-- @param #number Port Port to be used. Defaults to 5002. +-- @return #FLIGHTCONTROL self +function FLIGHTCONTROL:SetSRSPort(Port) + self.Port = Port or 5002 + return self +end + --- Set SRS options for a given MSRS object. -- @param #FLIGHTCONTROL self -- @param Sound.SRS#MSRS msrs Moose SRS object. @@ -576,8 +594,9 @@ end -- @param #number Volume Volume. Default 1.0. -- @param #string Label Name under which SRS transmitts. -- @param #string PathToGoogleCredentials Path to google credentials json file. +-- @param #number Port Server port for SRS -- @return #FLIGHTCONTROL self -function FLIGHTCONTROL:_SetSRSOptions(msrs, Gender, Culture, Voice, Volume, Label, PathToGoogleCredentials) +function FLIGHTCONTROL:_SetSRSOptions(msrs, Gender, Culture, Voice, Volume, Label, PathToGoogleCredentials, Port) -- Defaults: Gender=Gender or "female" @@ -592,6 +611,7 @@ function FLIGHTCONTROL:_SetSRSOptions(msrs, Gender, Culture, Voice, Volume, Labe msrs:SetLabel(Label) msrs:SetGoogle(PathToGoogleCredentials) msrs:SetCoalition(self:GetCoalition()) + msrs:SetPort(Port or self.Port or 5002) end return self @@ -981,33 +1001,6 @@ end --- On Before Update status. -- @param #FLIGHTCONTROL self function FLIGHTCONTROL:onbeforeStatusUpdate() - - --[[ - if self.Tlastmessage then - local Tnow=timer.getAbsTime() - - -- Time interval between last radio message. - local dT=Tnow-self.Tlastmessage - - if dT%d sec ago. Status update allowed", dT, self.dTmessage)) - end - end - ]] local Tqueue=self.msrsqueue:CalcTransmisstionDuration() @@ -2633,8 +2626,18 @@ function FLIGHTCONTROL:_PlayerRadioCheck(groupname) local callsign=self:_GetCallsignName(flight) -- Pilot radio check. - local text=string.format("%s, %s, radio check %.3f", self.alias, callsign, self.frequency) + local text = "" + if type(self.frequency) == "table" then + local multifreq = "" + for _,_entry in pairs(self.frequency) do + multifreq = string.format("%s%.2f, ",multifreq,_entry) + end + multifreq = string.gsub(multifreq,", $","") + text=string.format("%s, %s, radio check %s", self.alias, callsign, multifreq) + else + text=string.format("%s, %s, radio check %.3f", self.alias, callsign, self.frequency) + end -- Radio message. self:TransmissionPilot(text, flight) @@ -2713,7 +2716,17 @@ function FLIGHTCONTROL:_PlayerInfoAirbase(groupname) local text=string.format("Airbase %s Info:", self.airbasename) text=text..string.format("\nATC Status: %s", self:GetState()) - text=text..string.format("\nFrequency: %.3f %s", self.frequency, UTILS.GetModulationName(self.modulation)) + + if type(self.frequency) == "table" then + local multifreq = "" + for i=1,#self.frequency do + multifreq=string.format("%s%.2f %s, ",multifreq,self.frequency[i],UTILS.GetModulationName(self.modulation[i] or 0)) + end + text=string.gsub(text,", $","") + text=text..string.format("\nFrequencies: %s", multifreq) + else + text=text..string.format("\nFrequency: %.3f %s", self.frequency, UTILS.GetModulationName(self.modulation)) + end text=text..string.format("\nRunway Landing: %s", self:GetActiveRunwayText()) text=text..string.format("\nRunway Takeoff: %s", self:GetActiveRunwayText(true)) @@ -4458,13 +4471,31 @@ function FLIGHTCONTROL:_IsFlightOnRunway(flight) return nil end +--- [User] Set callsign options for TTS output. See @{Wrapper.Group#GROUP.GetCustomCallSign}() on how to set customized callsigns. +-- @param #FLIGHTCONTROL self +-- @param #boolean ShortCallsign If true, only call out the major flight number. Default = `true`. +-- @param #boolean Keepnumber If true, keep the **customized callsign** in the #GROUP name for players as-is, no amendments or numbers. Default = `true`. +-- @param #table CallsignTranslations (optional) Table to translate between DCS standard callsigns and bespoke ones. Does not apply if using customized +-- callsigns from playername or group name. +-- @return #FLIGHTCONTROL self +function FLIGHTCONTROL:SetCallSignOptions(ShortCallsign,Keepnumber,CallsignTranslations) + if not ShortCallsign or ShortCallsign == false then + self.ShortCallsign = false + else + self.ShortCallsign = true + end + self.Keepnumber = Keepnumber or false + self.CallsignTranslations = CallsignTranslations + return self +end + --- Get callsign name of a given flight. -- @param #FLIGHTCONTROL self -- @param Ops.FlightGroup#FLIGHTGROUP flight Flight group. -- @return #string Callsign or "Ghostrider 1-1". function FLIGHTCONTROL:_GetCallsignName(flight) - local callsign=flight:GetCallsignName() + local callsign=flight:GetCallsignName(self.ShortCallsign,self.Keepnumber,self.CallsignTranslations) --local name=string.match(callsign, "%a+") --local number=string.match(callsign, "%d+") diff --git a/Moose Development/Moose/Ops/FlightGroup.lua b/Moose Development/Moose/Ops/FlightGroup.lua index 342b34cb0..6c5d0bf2f 100644 --- a/Moose Development/Moose/Ops/FlightGroup.lua +++ b/Moose Development/Moose/Ops/FlightGroup.lua @@ -4495,8 +4495,10 @@ function FLIGHTGROUP:_PlayerSubtitles() -- Switch setting. playerData.subtitles=not playerData.subtitles + local onoff = playerData.subtitles == true and "ON" or "OFF" + -- Display message. - MESSAGE:New(string.format("%s, subtitles are now %s", playerData.name, tostring(playerData.subtitles)), 10, nil, true):ToGroup(self.group) + MESSAGE:New(string.format("%s, subtitles are now %s", playerData.name, onoff), 10, nil, true):ToGroup(self.group) else --TODO: Error diff --git a/Moose Development/Moose/Ops/OpsGroup.lua b/Moose Development/Moose/Ops/OpsGroup.lua index a8c556fd1..92fc2614e 100644 --- a/Moose Development/Moose/Ops/OpsGroup.lua +++ b/Moose Development/Moose/Ops/OpsGroup.lua @@ -10123,7 +10123,7 @@ function OPSGROUP:_CheckDamage() for _,_element in pairs(self.elements) do local element=_element --Ops.OpsGroup#OPSGROUP.Element - if element.status~=OPSGROUP.ElementStatus.DEAD and element.status~=OPSGROUP.ElementStatus.INUTERO then + if element.status~=OPSGROUP.ElementStatus.DEAD and element.status~=OPSGROUP.ElementStatus.INUTERO then -- Current life points. local life=element.unit:GetLife() @@ -10135,8 +10135,8 @@ function OPSGROUP:_CheckDamage() self:ElementDamaged(element) damaged=true end - - end + + end end @@ -11748,8 +11748,11 @@ end --- Get callsign of the first element alive. -- @param #OPSGROUP self +-- @param #boolean ShortCallsign If true, append major flight number only +-- @param #boolean Keepnumber (Player only) If true, and using a customized callsign in the #GROUP name after an #-sign, use all of that information. +-- @param #table CallsignTranslations (optional) Translation table between callsigns -- @return #string Callsign name, e.g. Uzi11, or "Ghostrider11". -function OPSGROUP:GetCallsignName() +function OPSGROUP:GetCallsignName(ShortCallsign,Keepnumber,CallsignTranslations) local element=self:GetElementAlive() @@ -11757,6 +11760,9 @@ function OPSGROUP:GetCallsignName() self:T2(self.lid..string.format("Callsign %s", tostring(element.callsign))) local name=element.callsign or "Ghostrider11" name=name:gsub("-", "") + if self.group:IsPlayer() or CallsignTranslations then + name=self.group:GetCustomCallSign(ShortCallsign,Keepnumber,CallsignTranslations) + end return name end @@ -11778,7 +11784,7 @@ function OPSGROUP:_UpdatePosition() self.positionLast=self.position or self:GetVec3() self.headingLast=self.heading or self:GetHeading() self.orientXLast=self.orientX or self:GetOrientationX() - self.velocityLast=self.velocity or self.group:GetVelocityMPS() + self.velocityLast=self.velocity or self.group:GetVelocityMPS() -- Current state. self.position=self:GetVec3() @@ -12432,18 +12438,18 @@ function OPSGROUP:GetAmmoUnit(unit, display) if ammotable then local weapons=#ammotable - - --self:I(ammotable) + + --self:I(ammotable) -- Loop over all weapons. for w=1,weapons do -- Number of current weapon. local Nammo=ammotable[w]["count"] - - -- Range in meters. Seems only to exist for missiles (not shells). - local rmin=ammotable[w]["desc"]["rangeMin"] or 0 - local rmax=ammotable[w]["desc"]["rangeMaxAltMin"] or 0 + + -- Range in meters. Seems only to exist for missiles (not shells). + local rmin=ammotable[w]["desc"]["rangeMin"] or 0 + local rmax=ammotable[w]["desc"]["rangeMaxAltMin"] or 0 -- Type name of current weapon. local Tammo=ammotable[w]["desc"]["typeName"] @@ -12707,7 +12713,7 @@ function OPSGROUP:_AddElementByName(unitname) element.gid=element.DCSunit:getNumber() element.uid=element.DCSunit:getID() --element.group=unit:GetGroup() - element.controller=element.DCSunit:getController() + element.controller=element.DCSunit:getController() element.Nhit=0 element.opsgroup=self diff --git a/Moose Development/Moose/Ops/PlayerTask.lua b/Moose Development/Moose/Ops/PlayerTask.lua index 4dbc1899b..37455242d 100644 --- a/Moose Development/Moose/Ops/PlayerTask.lua +++ b/Moose Development/Moose/Ops/PlayerTask.lua @@ -1213,7 +1213,7 @@ PLAYERTASKCONTROLLER.Messages = { --- PLAYERTASK class version. -- @field #string version -PLAYERTASKCONTROLLER.version="0.1.35" +PLAYERTASKCONTROLLER.version="0.1.36" --- Constructor -- @param #PLAYERTASKCONTROLLER self @@ -1391,7 +1391,7 @@ end --- [User] Set callsign options for TTS output. See @{Wrapper.Group#GROUP.GetCustomCallSign}() on how to set customized callsigns. -- @param #PLAYERTASKCONTROLLER self -- @param #boolean ShortCallsign If true, only call out the major flight number --- @param #boolean Keepnumber If true, keep the **customized callsign** in the #GROUP name as-is, no amendments or numbers. +-- @param #boolean Keepnumber If true, keep the **customized callsign** in the #GROUP name for players as-is, no amendments or numbers. -- @param #table CallsignTranslations (optional) Table to translate between DCS standard callsigns and bespoke ones. Does not apply if using customized -- callsigns from playername or group name. -- @return #PLAYERTASKCONTROLLER self @@ -1406,6 +1406,22 @@ function PLAYERTASKCONTROLLER:SetCallSignOptions(ShortCallsign,Keepnumber,Callsi return self end +--- [Internal] Get text for text-to-speech. +-- Numbers are spaced out, e.g. "Heading 180" becomes "Heading 1 8 0 ". +-- @param #PLAYERTASKCONTROLLER self +-- @param #string text Original text. +-- @return #string Spoken text. +function PLAYERTASKCONTROLLER:_GetTextForSpeech(text) + + -- Space out numbers. + text=string.gsub(text,"%d","%1 ") + -- get rid of leading or trailing spaces + text=string.gsub(text,"^%s*","") + text=string.gsub(text,"%s*$","") + + return text +end + --- [User] Set repetition options for tasks -- @param #PLAYERTASKCONTROLLER self -- @param #boolean OnOff Set to `true` to switch on and `false` to switch off (defaults to true) @@ -1531,7 +1547,9 @@ function PLAYERTASKCONTROLLER:_GetPlayerName(Client) if not self.customcallsigns[playername] then local playergroup = Client:GetGroup() ttsplayername = playergroup:GetCustomCallSign(self.ShortCallsign,self.Keepnumber,self.CallsignTranslations) - self.customcallsigns[playername] = ttsplayername + local newplayername = self:_GetTextForSpeech(ttsplayername) + self.customcallsigns[playername] = newplayername + ttsplayername = newplayername else ttsplayername = self.customcallsigns[playername] end @@ -1655,6 +1673,7 @@ function PLAYERTASKCONTROLLER:_EventHandler(EventData) end playername = EventData.IniGroup:GetCustomCallSign(self.ShortCallsign,self.Keepnumber) end + playername = self:_GetTextForSpeech(playername) --local text = string.format("%s, %s, switch to %s for task assignment!",EventData.IniPlayerName,self.MenuName or self.Name,freqtext) local text = string.format(switchtext,self.MenuName or self.Name,playername,freqtext) self.SRSQueue:NewTransmission(text,nil,self.SRS,timer.getAbsTime()+60,2,{EventData.IniGroup},text,30,self.BCFrequency,self.BCModulation) @@ -2289,6 +2308,7 @@ function PLAYERTASKCONTROLLER:_JoinTask(Group, Client, Task) --local m=MESSAGE:New(text,"10","Tasking"):ToAll() end if self.UseSRS then + self:I(self.lid..text) self.SRSQueue:NewTransmission(text,nil,self.SRS,nil,2) end self.TasksPerPlayer:Push(Task,playername)