diff --git a/Moose Development/Moose/Core/Message.lua b/Moose Development/Moose/Core/Message.lua index 843f55d0b..ad4079bc0 100644 --- a/Moose Development/Moose/Core/Message.lua +++ b/Moose Development/Moose/Core/Message.lua @@ -521,6 +521,9 @@ end function MESSAGE:ToSRS(frequency,modulation,gender,culture,voice,coalition,volume,coordinate) if _MESSAGESRS.SRSQ then _MESSAGESRS.MSRS:SetVoice(voice or _MESSAGESRS.Voice) + if coordinate then + _MESSAGESRS.MSRS:SetCoordinate(coordinate) + end _MESSAGESRS.SRSQ:NewTransmission(self.MessageText,nil,_MESSAGESRS.MSRS,nil,nil,nil,nil,nil,frequency,modulation,gender or _MESSAGESRS.Gender,culture or _MESSAGESRS.Culture,voice or _MESSAGESRS.Voice,volume,self.MessageCategory) end return self diff --git a/Moose Development/Moose/Ops/CSAR.lua b/Moose Development/Moose/Ops/CSAR.lua index 0c1950e41..becdf6ec3 100644 --- a/Moose Development/Moose/Ops/CSAR.lua +++ b/Moose Development/Moose/Ops/CSAR.lua @@ -31,6 +31,7 @@ -- @image OPS_CSAR.jpg -- Date: May 2023 +-- Last: Update Oct 2024 ------------------------------------------------------------------------- --- **CSAR** class, extends Core.Base#BASE, Core.Fsm#FSM @@ -116,21 +117,21 @@ -- mycsar.ADFRadioPwr = 1000 -- ADF Beacons sending with 1KW as default -- mycsar.PilotWeight = 80 -- Loaded pilots weigh 80kgs each -- --- ## 2.1 Experimental Features +-- ## 2.1 SRS Features and Other Features -- --- WARNING - Here\'ll be dragons! --- DANGER - For this to work you need to de-sanitize your mission environment (all three entries) in \Scripts\MissionScripting.lua --- Needs SRS => 1.9.6 to work (works on the **server** side of SRS) -- mycsar.useSRS = false -- Set true to use FF\'s SRS integration -- mycsar.SRSPath = "C:\\Progra~1\\DCS-SimpleRadio-Standalone\\" -- adjust your own path in your SRS installation -- server(!) -- mycsar.SRSchannel = 300 -- radio channel -- mycsar.SRSModulation = radio.modulation.AM -- modulation -- mycsar.SRSport = 5002 -- and SRS Server port -- mycsar.SRSCulture = "en-GB" -- SRS voice culture --- mycsar.SRSVoice = nil -- SRS voice, relevant for Google TTS +-- mycsar.SRSVoice = nil -- SRS voice for downed pilot, relevant for Google TTS -- mycsar.SRSGPathToCredentials = nil -- Path to your Google credentials json file, set this if you want to use Google TTS -- mycsar.SRSVolume = 1 -- Volume, between 0 and 1 -- mycsar.SRSGender = "male" -- male or female voice +-- mycsar.CSARVoice = MSRS.Voices.Google.Standard.en_US_Standard_A -- SRS voice for CSAR Controller, relevant for Google TTS +-- mycsar.CSARVoiceMS = MSRS.Voices.Microsoft.Hedda -- SRS voice for CSAR Controller, relevant for MS Desktop TTS +-- mycsar.coordinate -- Coordinate from which CSAR TTS is sending. Defaults to a random MASH object position -- -- -- mycsar.csarUsePara = false -- If set to true, will use the LandingAfterEjection Event instead of Ejection. Requires mycsar.enableForAI to be set to true. --shagrat -- mycsar.wetfeettemplate = "man in floating thingy" -- if you use a mod to have a pilot in a rescue float, put the template name in here for wet feet spawns. Note: in conjunction with csarUsePara this might create dual ejected pilots in edge cases. @@ -230,7 +231,7 @@ CSAR = { takenOff = {}, csarUnits = {}, -- table of unit names downedPilots = {}, - woundedGroups = {}, + -- = {}, landedStatus = {}, addedTo = {}, woundedGroups = {}, -- contains the new group of units @@ -465,7 +466,10 @@ function CSAR:New(Coalition, Template, Alias) self.SRSGPathToCredentials = nil self.SRSVolume = 1.0 -- volume 0.0 to 1.0 self.SRSGender = "male" -- male or female - + self.CSARVoice = MSRS.Voices.Google.Standard.en_US_Standard_A + self.CSARVoiceMS = MSRS.Voices.Microsoft.Hedda + self.coordinate = nil -- Core.Point#COORDINATE + local AliaS = string.gsub(self.alias," ","_") self.filename = string.format("CSAR_%s_Persist.csv",AliaS) @@ -1306,7 +1310,7 @@ end -- @param #string UnitName -- @return #string CallSign function CSAR:_GetCustomCallSign(UnitName) - local callsign = Unitname + local callsign = UnitName local unit = UNIT:FindByName(UnitName) if unit and unit:IsAlive() then local group = unit:GetGroup() @@ -1737,7 +1741,16 @@ function CSAR:_DisplayMessageToSAR(_unit, _text, _time, _clear, _speak, _overrid end -- integrate SRS if _speak and self.useSRS then - self.SRSQueue:NewTransmission(_text,nil,self.msrs,nil,2) + local coord = _unit:GetCoordinate() + if coord then + self.msrs:SetCoordinate(coord) + end + _text = string.gsub(_text,"km"," kilometer") + _text = string.gsub(_text,"nm"," nautical miles") + --self.msrs:SetVoice(self.SRSVoice) + --self.SRSQueue:NewTransmission(_text,nil,self.msrs,nil,1) + self:I("Voice = "..self.SRSVoice) + self.SRSQueue:NewTransmission(_text,duration,self.msrs,tstart,2,subgroups,subtitle,subduration,self.SRSchannel,self.SRSModulation,gender,culture,self.SRSVoice,volume,label,coord) end return self end @@ -1876,7 +1889,7 @@ function CSAR:_SignalFlare(_unitName) if _closest ~= nil and _closest.pilot ~= nil and _closest.distance > 0 and _closest.distance < smokedist then local _clockDir = self:_GetClockDirection(_heli, _closest.pilot) - local _distance = 0 + local _distance = "" if _SETTINGS:IsImperial() then _distance = string.format("%.1fnm",UTILS.MetersToNM(_closest.distance)) else @@ -1889,12 +1902,13 @@ function CSAR:_SignalFlare(_unitName) _coord:FlareRed(_clockDir) else local _distance = smokedist + local dtext = "" if _SETTINGS:IsImperial() then - _distance = string.format("%.1fnm",UTILS.MetersToNM(smokedist)) + dtext = string.format("%.1fnm",UTILS.MetersToNM(smokedist)) else - _distance = string.format("%.1fkm",smokedist/1000) + dtext = string.format("%.1fkm",smokedist/1000) end - self:_DisplayMessageToSAR(_heli, string.format("No Pilots within %s",_distance), self.messageTime, false, false, true) + self:_DisplayMessageToSAR(_heli, string.format("No Pilots within %s",dtext), self.messageTime, false, false, true) end return self end @@ -1907,6 +1921,14 @@ end function CSAR:_DisplayToAllSAR(_message, _side, _messagetime) self:T(self.lid .. " _DisplayToAllSAR") local messagetime = _messagetime or self.messageTime + if self.msrs then + local voice = self.CSARVoice or MSRS.Voices.Google.Standard.en_GB_Standard_F + if self.msrs.google == nil then + voice = self.CSARVoiceMS or MSRS.Voices.Microsoft.Hedda + end + self:I("Voice = "..voice) + self.SRSQueue:NewTransmission(_message,duration,self.msrs,tstart,2,subgroups,subtitle,subduration,self.SRSchannel,self.SRSModulation,gender,culture,voice,volume,label,self.coordinate) + end for _, _unitName in pairs(self.csarUnits) do local _unit = self:_GetSARHeli(_unitName) if _unit and not self.suppressmessages then @@ -1930,7 +1952,7 @@ function CSAR:_Reqsmoke( _unitName ) local _closest = self:_GetClosestDownedPilot(_heli) if _closest ~= nil and _closest.pilot ~= nil and _closest.distance > 0 and _closest.distance < smokedist then local _clockDir = self:_GetClockDirection(_heli, _closest.pilot) - local _distance = 0 + local _distance = string.format("%.1fkm",_closest.distance/1000) if _SETTINGS:IsImperial() then _distance = string.format("%.1fnm",UTILS.MetersToNM(_closest.distance)) else @@ -1942,7 +1964,7 @@ function CSAR:_Reqsmoke( _unitName ) local color = self.smokecolor _coord:Smoke(color) else - local _distance = 0 + local _distance = string.format("%.1fkm",smokedist/1000) if _SETTINGS:IsImperial() then _distance = string.format("%.1fnm",UTILS.MetersToNM(smokedist)) else @@ -2267,6 +2289,12 @@ function CSAR:onafterStart(From, Event, To) self.allheligroupset = SET_GROUP:New():FilterCoalitions(self.coalitiontxt):FilterCategoryHelicopter():FilterStart() end self.mash = SET_GROUP:New():FilterCoalitions(self.coalitiontxt):FilterPrefixes(self.mashprefix):FilterStart() -- currently only GROUP objects, maybe support STATICs also? + if not self.coordinate then + local csarhq = self.mash:GetRandom() + if csarhq then + self.coordinate = csarhq:GetCoordinate() + end + end if self.wetfeettemplate then self.usewetfeet = true end @@ -2274,7 +2302,7 @@ function CSAR:onafterStart(From, Event, To) local path = self.SRSPath local modulation = self.SRSModulation local channel = self.SRSchannel - self.msrs = MSRS:New(path,channel,modulation) + self.msrs = MSRS:New(path,channel,modulation) -- Sound.SRS#MSRS self.msrs:SetPort(self.SRSport) self.msrs:SetLabel("CSAR") self.msrs:SetCulture(self.SRSCulture) @@ -2286,7 +2314,7 @@ function CSAR:onafterStart(From, Event, To) end self.msrs:SetVolume(self.SRSVolume) self.msrs:SetLabel("CSAR") - self.SRSQueue = MSRSQUEUE:New("CSAR") + self.SRSQueue = MSRSQUEUE:New("CSAR") -- Sound.SRS#MSRSQUEUE end self:__Status(-10) diff --git a/Moose Development/Moose/Sound/SRS.lua b/Moose Development/Moose/Sound/SRS.lua index 05def5904..d549f512d 100644 --- a/Moose Development/Moose/Sound/SRS.lua +++ b/Moose Development/Moose/Sound/SRS.lua @@ -824,15 +824,16 @@ end -- @param #MSRS self -- @param #string Text Text message. -- @param #number Delay Delay in seconds, before the message is played. +-- @param Core.Point#COORDINATE Coordinate Coordinate. -- @return #MSRS self -function MSRS:PlayText(Text, Delay) +function MSRS:PlayText(Text, Delay, Coordinate) if Delay and Delay>0 then - self:ScheduleOnce(Delay, MSRS.PlayText, self, Text, 0) + self:ScheduleOnce(Delay, MSRS.PlayText, self, Text, nil, Coordinate) else -- Get command line. - local command=self:_GetCommand() + local command=self:_GetCommand(nil,nil,nil,nil,nil,nil,nil,nil,nil,nil,Coordinate) -- Append text. command=command..string.format(" --text=\"%s\"", tostring(Text)) @@ -856,11 +857,12 @@ end -- @param #string Voice Voice. -- @param #number Volume Volume. -- @param #string Label Label. +-- @param Core.Point#COORDINATE Coordinate Coordinate. -- @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, Coordinate) if Delay and Delay>0 then - self:ScheduleOnce(Delay, MSRS.PlayTextExt, self, Text, 0, Frequencies, Modulations, Gender, Culture, Voice, Volume, Label) + self:ScheduleOnce(Delay, MSRS.PlayTextExt, self, Text, 0, Frequencies, Modulations, Gender, Culture, Voice, Volume, Label, Coordinate) else -- Ensure table. @@ -874,7 +876,7 @@ function MSRS:PlayTextExt(Text, Delay, Frequencies, Modulations, Gender, Culture end -- Get command line. - local command=self:_GetCommand(Frequencies, Modulations, nil, Gender, Voice, Culture, Volume, nil, nil, Label) + local command=self:_GetCommand(Frequencies, Modulations, nil, Gender, Voice, Culture, Volume, nil, nil, Label, Coordinate) -- Append text. command=command..string.format(" --text=\"%s\"", tostring(Text)) @@ -1065,8 +1067,9 @@ end -- @param #number speed Speed. -- @param #number port Port. -- @param #string label Label, defaults to "ROBOT" (displayed sender name in the radio overlay of SRS) - No spaces allowed! +-- @param Core.Point#COORDINATE coordinate Coordinate. -- @return #string Command. -function MSRS:_GetCommand(freqs, modus, coal, gender, voice, culture, volume, speed, port,label) +function MSRS:_GetCommand(freqs, modus, coal, gender, voice, culture, volume, speed, port,label,coordinate) local path=self:GetPath() or STTS.DIRECTORY local exe=STTS.EXECUTABLE or "DCS-SR-ExternalAudio.exe" @@ -1080,6 +1083,7 @@ function MSRS:_GetCommand(freqs, modus, coal, gender, voice, culture, volume, sp speed=speed or self.speed port=port or self.port label=label or self.Label + coordinate=coordinate or self.coordinate -- Replace modulation modus=modus:gsub("0", "AM") @@ -1104,8 +1108,8 @@ function MSRS:_GetCommand(freqs, modus, coal, gender, voice, culture, volume, sp end -- Set coordinate. - if self.coordinate then - local lat,lon,alt=self:_GetLatLongAlt(self.coordinate) + if coordinate then + local lat,lon,alt=self:_GetLatLongAlt(coordinate) command=command..string.format(" -L %.4f -O %.4f -A %d", lat, lon, alt) end @@ -1649,6 +1653,7 @@ MSRSQUEUE = { -- @field #string voice Voice if any -- @field #number volume Volume -- @field #string label Label to be used +-- @field Core.Point#COORDINATE coordinate Coordinate for this transmission --- Create a new MSRSQUEUE object for a given radio frequency/modulation. -- @param #MSRSQUEUE self @@ -1733,8 +1738,9 @@ end -- @param #string voice Specific voice -- @param #number volume Volume setting -- @param #string label Label to be used +-- @param Core.Point#COORDINATE coordinate Coordinate to be used -- @return #MSRSQUEUE.Transmission Radio transmission table. -function MSRSQUEUE:NewTransmission(text, duration, msrs, tstart, interval, subgroups, subtitle, subduration, frequency, modulation, gender, culture, voice, volume, label) +function MSRSQUEUE:NewTransmission(text, duration, msrs, tstart, interval, subgroups, subtitle, subduration, frequency, modulation, gender, culture, voice, volume, label,coordinate) if self.TransmitOnlyWithPlayers then if self.PlayerSet and self.PlayerSet:CountAlive() == 0 then @@ -1774,7 +1780,8 @@ function MSRSQUEUE:NewTransmission(text, duration, msrs, tstart, interval, subgr transmission.voice = voice transmission.gender = volume transmission.label = label - + transmission.coordinate = coordinate + -- Add transmission to queue. self:AddTransmission(transmission) @@ -1787,9 +1794,9 @@ end function MSRSQUEUE:Broadcast(transmission) if transmission.frequency then - transmission.msrs:PlayTextExt(transmission.text, nil, transmission.frequency, transmission.modulation, transmission.gender, transmission.culture, transmission.voice, transmission.volume, transmission.label) + transmission.msrs:PlayTextExt(transmission.text, nil, transmission.frequency, transmission.modulation, transmission.gender, transmission.culture, transmission.voice, transmission.volume, transmission.label, transmission.coordinate) else - transmission.msrs:PlayText(transmission.text) + transmission.msrs:PlayText(transmission.text,nil,transmission.coordinate) end local function texttogroup(gid)