From dd7b87e9cd6f38aced7935d38ce74804c182199c Mon Sep 17 00:00:00 2001 From: shaji Date: Wed, 23 Apr 2025 13:39:55 +0200 Subject: [PATCH] [ADDED] AIRBOSS:SetMaxSectionDistance --- Moose Development/Moose/Ops/Airboss.lua | 161 +++++++++++++----------- 1 file changed, 90 insertions(+), 71 deletions(-) diff --git a/Moose Development/Moose/Ops/Airboss.lua b/Moose Development/Moose/Ops/Airboss.lua index 5ef25bdc7..5e6f70443 100644 --- a/Moose Development/Moose/Ops/Airboss.lua +++ b/Moose Development/Moose/Ops/Airboss.lua @@ -1731,10 +1731,10 @@ AIRBOSS.Difficulty = { -- @field #table trapsheet Groove data table recorded every 0.5 seconds. -- @field #boolean trapon If true, save trap sheets. -- @field #string debriefschedulerID Debrief scheduler ID. --- +-- -- @field Sound.SRS#MSRS SRS -- @field Sound.SRS#MSRSQUEUE SRSQ --- +-- -- @extends #AIRBOSS.FlightGroup --- Main group level radio menu: F10 Other/Airboss. @@ -1912,6 +1912,9 @@ function AIRBOSS:New( carriername, alias ) -- Set max section members. Default 2. self:SetMaxSectionSize() + -- Set max section distance. Default 100 meters. + self:SetMaxSectionDistance() + -- Set max flights per stack. Default is 2. self:SetMaxFlightsPerStack() @@ -2539,7 +2542,7 @@ function AIRBOSS:AddRecoveryWindow( starttime, stoptime, case, holdingoffset, tu return self end if Tstop <= Tnow then - string.format( "WARNING: Recovery stop time %s already over. Tnow=%s! Recovery window rejected.", UTILS.SecondsToClock( Tstop ), UTILS.SecondsToClock( Tnow ) ) + string.format( "WARNING: Recovery stop time %s already over. Tnow=%s! Recovery window rejected.", UTILS.SecondsToClock( Tstop ), UTILS.SecondsToClock( Tnow ) ) return self end @@ -3066,7 +3069,7 @@ end -- @param #number Port Port of the SRS server, defaults to 5002. -- @param #string Culture (Optional, Airboss Culture) Culture, defaults to "en-US". -- @param #string Gender (Optional, Airboss Gender) Gender, e.g. "male" or "female". Defaults to "male". --- @param #string Voice (Optional, Airboss Voice) Set to use a specific voice. Will **override gender and culture** settings. +-- @param #string Voice (Optional, Airboss Voice) Set to use a specific voice. Will **override gender and culture** settings. -- @param #string GoogleCreds (Optional) Path to Google credentials, e.g. "C:\\Program Files\\DCS-SimpleRadio-Standalone\\yourgooglekey.json". -- @param #number Volume (Optional) E.g. 0.75. Defaults to 1.0 (loudest). -- @param #table AltBackend (Optional) See MSRS for details. @@ -3097,10 +3100,10 @@ function AIRBOSS:EnableSRS(PathToSRS,Port,Culture,Gender,Voice,GoogleCreds,Volum -- SRSQUEUE self.SRSQ = MSRSQUEUE:New("AIRBOSS") self.SRSQ:SetTransmitOnlyWithPlayers(true) - if not self.PilotRadio then + if not self.PilotRadio then self:SetSRSPilotVoice() end - return self + return self end --- Set LSO radio frequency and modulation. Default frequency is 264 MHz AM. @@ -3343,6 +3346,22 @@ function AIRBOSS:SetMaxSectionSize( nmax ) return self end +--- Set maximum distance up to which section members are allowed (default: 100 meters). +-- @param #AIRBOSS self +-- @param #number dmax Max distance in meters (default 100 m). Minimum is 10 m, maximum is 5000 m. +-- @return #AIRBOSS self +function AIRBOSS:SetMaxSectionDistance( dmax ) + if dmax then + if dmax < 10 then + dmax = 10 + elseif dmax > 5000 then + dmax = 5000 + end + end + self.maxsectiondistance = dmax or 100 + return self +end + --- Set max number of flights per stack. All members of a section count as one "flight". -- @param #AIRBOSS self -- @param #number nmax Number of max allowed flights per stack. Default is two. Minimum is one, maximum is 4. @@ -11596,7 +11615,7 @@ function AIRBOSS:GetHeadingIntoWind_old( vdeck, magnetic, coord ) local function adjustDegreesForWindSpeed(windSpeed) local degreesAdjustment = 0 -- the windspeeds are in m/s - + -- +0 degrees at 15m/s = 37kts -- +0 degrees at 14m/s = 35kts -- +0 degrees at 13m/s = 33kts @@ -11611,7 +11630,7 @@ function AIRBOSS:GetHeadingIntoWind_old( vdeck, magnetic, coord ) -- +20 degrees at 4m/s = 26kts -- +20 degrees at 3m/s = 26kts -- +30 degrees at 2m/s = 26kts 1s - + if windSpeed > 0 and windSpeed < 3 then degreesAdjustment = 30 elseif windSpeed >= 3 and windSpeed < 5 then @@ -11623,7 +11642,7 @@ function AIRBOSS:GetHeadingIntoWind_old( vdeck, magnetic, coord ) elseif windSpeed >= 13 then degreesAdjustment = 0 end - + return degreesAdjustment end @@ -11682,60 +11701,60 @@ function AIRBOSS:GetHeadingIntoWind_new( vdeck, magnetic, coord ) local h=self:GetHeading(magnetic) return h, math.min(vdeck, Vmax) end - + -- Convert wind speed to knots. vwind=UTILS.MpsToKnots(vwind) - + -- Wind to in knots. local windto=(windfrom+180)%360 - + -- Offset angle in rad. We also define the rotation to be clock-wise, which requires a minus sign. local alpha=math.rad(-Offset) - + -- Constant. local C = math.sqrt(math.cos(alpha)^2 / math.sin(alpha)^2 + 1) - + -- Upper limit of desired speed due to max boat speed. local vdeckMax=vwind + math.cos(alpha) * Vmax - + -- Lower limit of desired speed due to min boat speed. local vdeckMin=vwind + math.cos(alpha) * Vmin - - + + -- Speed of ship so it matches the desired speed. local v=0 - - -- Angle wrt. to wind TO-direction + + -- Angle wrt. to wind TO-direction local theta=0 if vdeck>vdeckMax then -- Boat cannot go fast enough - + -- Set max speed. v=Vmax - + -- Calculate theta. theta = math.asin(v/(vwind*C)) - math.asin(-1/C) - + elseif vdeckvwind then -- Too little wind - + -- Set theta to 90° theta=math.pi/2 - + -- Set speed. v = math.sqrt(vdeck^2 - vwind^2) - + else -- Normal case theta = math.asin(vdeck * math.sin(alpha) / vwind) @@ -11744,9 +11763,9 @@ function AIRBOSS:GetHeadingIntoWind_new( vdeck, magnetic, coord ) -- Magnetic heading. local magvar= magnetic and self.magvar or 0 - + -- Ship heading so cross wind is min for the given wind. - local intowind = (540 + (windto - magvar + math.deg(theta) )) % 360 + local intowind = (540 + (windto - magvar + math.deg(theta) )) % 360 return intowind, v end @@ -12204,7 +12223,7 @@ function AIRBOSS:_LSOgrade( playerData ) -- Normal laning part at the beginning local Gb = GXX .. " " .. GIM - -- Number of deviations that occurred at the the beginning of the landing (XX or IM). These are graded like in non-VTOL landings, i.e. on deviations is + -- Number of deviations that occurred at the the beginning of the landing (XX or IM). These are graded like in non-VTOL landings, i.e. on deviations is local N=nXX+nIM local nL=count(Gb, '_')/2 local nS=count(Gb, '%(') @@ -12222,7 +12241,7 @@ function AIRBOSS:_LSOgrade( playerData ) if nL>0 or nLv>1 then -- Larger deviations at XX or IM or at least one larger deviation IC or AR==> "No grade" 2.0 points. - -- In other words, we allow one larger deviation at IC+AR + -- In other words, we allow one larger deviation at IC+AR grade="--" points=2.0 elseif nN>0 or nNv>1 or nLv==1 then @@ -13718,7 +13737,7 @@ function AIRBOSS:CarrierTurnIntoWind( time, vdeck, uturn ) local deltaH = self:_GetDeltaHeading( hdg, hiw ) -- Debug output - self:I( self.lid .. string.format( "Carrier steaming into the wind (%.1f kts). Heading=%03d-->%03d (Delta=%.1f), Speed=%.1f knots, Distance=%.1f NM, Time=%d sec", + self:I( self.lid .. string.format( "Carrier steaming into the wind (%.1f kts). Heading=%03d-->%03d (Delta=%.1f), Speed=%.1f knots, Distance=%.1f NM, Time=%d sec", UTILS.MpsToKnots( vwind ), hdg, hiw, deltaH, speedknots, distNM, speedknots, time ) ) -- Current coordinate. @@ -14930,12 +14949,12 @@ function AIRBOSS:RadioTransmission( radio, call, loud, delay, interval, click, p if radio == nil or call == nil then return end - + if not self.SRS then - + -- Create a new radio transmission item. local transmission = {} -- #AIRBOSS.Radioitem - + transmission.radio = radio transmission.call = call transmission.Tplay = timer.getAbsTime() + (delay or 0) @@ -14943,49 +14962,49 @@ function AIRBOSS:RadioTransmission( radio, call, loud, delay, interval, click, p transmission.isplaying = false transmission.Tstarted = nil transmission.loud = loud and call.loud - + -- Player onboard number if sender has one. if self:_IsOnboard( call.modexsender ) then self:_Number2Radio( radio, call.modexsender, delay, 0.3, pilotcall ) end - + -- Play onboard number if receiver has one. if self:_IsOnboard( call.modexreceiver ) then self:_Number2Radio( radio, call.modexreceiver, delay, 0.3, pilotcall ) end - + -- Add transmission to the right queue. local caller = "" if radio.alias == "LSO" then - + table.insert( self.RQLSO, transmission ) - + caller = "LSOCall" - + -- Schedule radio queue checks. if not self.RQLid then self:T( self.lid .. string.format( "Starting LSO radio queue." ) ) self.RQLid = self.radiotimer:Schedule( nil, AIRBOSS._CheckRadioQueue, { self, self.RQLSO, "LSO" }, 0.02, 0.05 ) end - + elseif radio.alias == "MARSHAL" then - + table.insert( self.RQMarshal, transmission ) - + caller = "MarshalCall" - + if not self.RQMid then self:T( self.lid .. string.format( "Starting Marhal radio queue." ) ) self.RQMid = self.radiotimer:Schedule( nil, AIRBOSS._CheckRadioQueue, { self, self.RQMarshal, "MARSHAL" }, 0.02, 0.05 ) end - + end - + -- Append radio click sound at the end of the transmission. if click then self:RadioTransmission( radio, self[caller].CLICK, false, delay ) end - + else -- SRS transmission @@ -14996,7 +15015,7 @@ function AIRBOSS:RadioTransmission( radio, call, loud, delay, interval, click, p local voice = nil local gender = nil local culture = nil - + if radio.alias == "AIRBOSS" then frequency = self.AirbossRadio.frequency modulation = self.AirbossRadio.modulation @@ -15004,13 +15023,13 @@ function AIRBOSS:RadioTransmission( radio, call, loud, delay, interval, click, p gender = self.AirbossRadio.gender culture = self.AirbossRadio.culture end - + if radio.alias == "MARSHAL" then voice = self.MarshalRadio.voice gender = self.MarshalRadio.gender culture = self.MarshalRadio.culture end - + if radio.alias == "LSO" then frequency = self.LSORadio.frequency modulation = self.LSORadio.modulation @@ -15018,7 +15037,7 @@ function AIRBOSS:RadioTransmission( radio, call, loud, delay, interval, click, p gender = self.LSORadio.gender culture = self.LSORadio.culture end - + if pilotcall then voice = self.PilotRadio.voice gender = self.PilotRadio.gender @@ -15032,16 +15051,16 @@ function AIRBOSS:RadioTransmission( radio, call, loud, delay, interval, click, p modulation = self.AirbossRadio.modulation radio.alias = "AIRBOSS" end - + local volume = nil - + if loud then volume = 1.0 end - + --local text = tostring(call.modexreceiver).."; "..radio.alias.."; "..call.subtitle local text = call.subtitle - self:T(self.lid..text) + self:T(self.lid..text) local srstext = self:_GetNiceSRSText(text) self.SRSQ:NewTransmission(srstext, call.duration, self.SRS, nil, 0.1, nil, call.subtitle, call.subduration, frequency, modulation, gender, culture, voice, volume, radio.alias) end @@ -15061,11 +15080,11 @@ function AIRBOSS:SetSRSPilotVoice( Voice, Gender, Culture ) self.PilotRadio.voice = Voice or MSRS.Voices.Microsoft.David self.PilotRadio.gender = Gender or "male" self.PilotRadio.culture = Culture or "en-US" - + if (not Voice) and self.SRS and self.SRS:GetProvider() == MSRS.Provider.GOOGLE then self.PilotRadio.voice = MSRS.Voices.Google.Standard.en_US_Standard_J end - + return self end @@ -15379,44 +15398,44 @@ function AIRBOSS:MessageToPlayer( playerData, message, sender, receiver, duratio -- SCHEDULER:New(nil, self.MessageToPlayer, {self, playerData, message, sender, receiver, duration, clear}, delay) self:ScheduleOnce( delay, self.MessageToPlayer, self, playerData, message, sender, receiver, duration, clear ) else - + if not self.SRS then -- Wait until previous sound finished. local wait = 0 - + -- Onboard number to get the attention. if receiver == playerData.onboard then - + -- Which voice over number to use. if sender and (sender == "LSO" or sender == "MARSHAL" or sender == "AIRBOSS") then - + -- User sound of board number. wait = wait + self:_Number2Sound( playerData, sender, receiver ) - + end end - + -- Negative. if string.find( text:lower(), "negative" ) then local filename = self:_RadioFilename( self.MarshalCall.NEGATIVE, false, "MARSHAL" ) USERSOUND:New( filename ):ToGroup( playerData.group, wait ) wait = wait + self.MarshalCall.NEGATIVE.duration end - + -- Affirm. if string.find( text:lower(), "affirm" ) then local filename = self:_RadioFilename( self.MarshalCall.AFFIRMATIVE, false, "MARSHAL" ) USERSOUND:New( filename ):ToGroup( playerData.group, wait ) wait = wait + self.MarshalCall.AFFIRMATIVE.duration end - + -- Roger. if string.find( text:lower(), "roger" ) then local filename = self:_RadioFilename( self.MarshalCall.ROGER, false, "MARSHAL" ) USERSOUND:New( filename ):ToGroup( playerData.group, wait ) wait = wait + self.MarshalCall.ROGER.duration end - + -- Play click sound to end message. if wait > 0 then local filename = self:_RadioFilename( self.MarshalCall.CLICK ) @@ -15429,7 +15448,7 @@ function AIRBOSS:MessageToPlayer( playerData, message, sender, receiver, duratio local voice = self.MarshalRadio.voice local gender = self.MarshalRadio.gender local culture = self.MarshalRadio.culture - + if not sender then sender = "AIRBOSS" end if string.find(sender,"AIRBOSS" ) then @@ -17047,7 +17066,7 @@ function AIRBOSS:_RemoveSectionMember( playerData, sectionmember ) return false end ---- Set all flights within 100 meters to be part of my section. +--- Set all flights within maxsectiondistance meters to be part of my section (default: 100 meters). -- @param #AIRBOSS self -- @param #string _unitName Name of the player unit. function AIRBOSS:_SetSection( _unitName ) @@ -17065,7 +17084,7 @@ function AIRBOSS:_SetSection( _unitName ) local mycoord = _unit:GetCoordinate() -- Max distance up to which section members are allowed. - local dmax = 100 + local dmax = self.maxsectiondistance -- Check if player is in Marshal or pattern queue already. local text