diff --git a/Moose Development/Moose/Core/Spawn.lua b/Moose Development/Moose/Core/Spawn.lua index d65aae7a2..7b25c5367 100644 --- a/Moose Development/Moose/Core/Spawn.lua +++ b/Moose Development/Moose/Core/Spawn.lua @@ -1472,10 +1472,19 @@ function SPAWN:SpawnAtAirbase( SpawnAirbase, Takeoff, TakeoffAltitude, TerminalT -- Template group, unit and its attributes. local TemplateGroup = GROUP:FindByName(self.SpawnTemplatePrefix) local TemplateUnit=TemplateGroup:GetUnit(1) + + --local ishelo=TemplateUnit:HasAttribute("Helicopters") + --local isbomber=TemplateUnit:HasAttribute("Bombers") + --local istransport=TemplateUnit:HasAttribute("Transports") + --local isfighter=TemplateUnit:HasAttribute("Battleplanes") + + local group=TemplateGroup + local istransport=group:HasAttribute("Transports") and group:HasAttribute("Planes") + local isawacs=group:HasAttribute("AWACS") + local isfighter=group:HasAttribute("Fighters") or group:HasAttribute("Interceptors") or group:HasAttribute("Multirole fighters") or (group:HasAttribute("Bombers") and not group:HasAttribute("Strategic bombers")) + local isbomber=group:HasAttribute("Strategic bombers") + local istanker=group:HasAttribute("Tankers") local ishelo=TemplateUnit:HasAttribute("Helicopters") - local isbomber=TemplateUnit:HasAttribute("Bombers") - local istransport=TemplateUnit:HasAttribute("Transports") - local isfighter=TemplateUnit:HasAttribute("Battleplanes") -- Number of units in the group. With grouping this can actually differ from the template group size! local nunits=#SpawnTemplate.units @@ -1585,10 +1594,7 @@ function SPAWN:SpawnAtAirbase( SpawnAirbase, Takeoff, TakeoffAltitude, TerminalT else -- Fixed wing aircraft is spawned. if termtype==nil then - --TODO: Add some default cases for transport, bombers etc. if no explicit terminal type is provided. - --TODO: We don't want Bombers to spawn in shelters. But I don't know a good attribute for just fighers. - --TODO: Some attributes are "Helicopters", "Bombers", "Transports", "Battleplanes". Need to check it out. - if isbomber or istransport then + if isbomber or istransport or istanker or isawacs then -- First we fill the potentially bigger spots. self:T(string.format("Transport/bomber group %s is at %s using terminal type %d.", self.SpawnTemplatePrefix, SpawnAirbase:GetName(), AIRBASE.TerminalType.OpenBig)) spots=SpawnAirbase:FindFreeParkingSpotForAircraft(TemplateGroup, AIRBASE.TerminalType.OpenBig, scanradius, scanunits, scanstatics, scanscenery, verysafe, nunits) diff --git a/Moose Development/Moose/Ops/Airboss.lua b/Moose Development/Moose/Ops/Airboss.lua index 8d18d4e53..5fe985d33 100644 --- a/Moose Development/Moose/Ops/Airboss.lua +++ b/Moose Development/Moose/Ops/Airboss.lua @@ -376,6 +376,9 @@ -- -- All section members are supposed to follow. Player (or section lead) is removed from all other queues and automatically added to the landing pattern queue. -- +-- If this command is called while the player is currently on the carrier, he will be put in the bolter pattern. So the next expected step after take of +-- is the abeam position. This allows for quick landing training exercises without having to go through the whole pattern. +-- -- The mission designer can forbid this option my setting @{#AIRBOSS.SetEmergencyLandings}(false) in the script. -- -- ### [Reset My Status] @@ -1664,7 +1667,7 @@ AIRBOSS.MenuF10Root=nil --- Airboss class version. -- @field #string version -AIRBOSS.version="0.9.9.6" +AIRBOSS.version="0.9.9.7" ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- TODO list @@ -4068,6 +4071,69 @@ function AIRBOSS:_InitTarawa() end +--- Init parameters for Marshal Voice overs *Gabriella* by HighwaymanEd. +-- @param #AIRBOSS self +-- @param #string mizfolder (Optional) Folder within miz file where the sound files are located. +function AIRBOSS:SetVoiceOversMarshalByGabriella(mizfolder) + + -- Set sound files folder. + if mizfolder then + local lastchar=string.sub(mizfolder, -1) + if lastchar~="/" then + mizfolder=mizfolder.."/" + end + self.soundfolderMSH=mizfolder + else + -- Default is the general folder. + self.soundfolderMSH=self.soundfolder + end + + -- Report for duty. + self:I(self.lid..string.format("Marshal Gabriella reporting for duty! Soundfolder=%s", tostring(self.soundfolderMSH))) + + self.MarshalCall.AFFIRMATIVE.duration=0.65 + self.MarshalCall.ALTIMETER.duration=0.60 + self.MarshalCall.BRC.duration=0.67 + self.MarshalCall.CARRIERTURNTOHEADING.duration=1.62 + self.MarshalCall.CASE.duration=0.30 + self.MarshalCall.CHARLIETIME.duration=0.77 + self.MarshalCall.CLEAREDFORRECOVERY.duration=0.93 + self.MarshalCall.DECKCLOSED.duration=0.73 + self.MarshalCall.DEGREES.duration=0.48 + self.MarshalCall.EXPECTED.duration=0.50 + self.MarshalCall.FLYNEEDLES.duration=0.89 + self.MarshalCall.HOLDATANGELS.duration=0.81 + self.MarshalCall.HOURS.duration=0.41 + self.MarshalCall.MARSHALRADIAL.duration=0.95 + self.MarshalCall.N0.duration=0.41 + self.MarshalCall.N1.duration=0.30 + self.MarshalCall.N2.duration=0.34 + self.MarshalCall.N3.duration=0.31 + self.MarshalCall.N4.duration=0.34 + self.MarshalCall.N5.duration=0.30 + self.MarshalCall.N6.duration=0.33 + self.MarshalCall.N7.duration=0.38 + self.MarshalCall.N8.duration=0.35 + self.MarshalCall.N9.duration=0.35 + self.MarshalCall.NEGATIVE.duration=0.60 + self.MarshalCall.NEWFB.duration=0.95 + self.MarshalCall.OPS.duration=0.23 + self.MarshalCall.POINT.duration=0.38 + self.MarshalCall.RADIOCHECK.duration=1.27 + self.MarshalCall.RECOVERY.duration=0.60 + self.MarshalCall.RECOVERYOPSSTOPPED.duration=1.25 + self.MarshalCall.RECOVERYPAUSEDNOTICE.duration=2.55 + self.MarshalCall.RECOVERYPAUSEDRESUMED.duration=2.55 + self.MarshalCall.REPORTSEEME.duration=0.87 + self.MarshalCall.RESUMERECOVERY.duration=1.55 + self.MarshalCall.ROGER.duration=0.50 + self.MarshalCall.SAYNEEDLES.duration=0.82 + self.MarshalCall.STACKFULL.duration=5.70 + self.MarshalCall.STARTINGRECOVERY.duration=1.61 + +end + + --- Init parameters for Marshal Voice overs by *Raynor*. -- @param #AIRBOSS self @@ -5423,7 +5489,15 @@ function AIRBOSS:_GetNextMarshalFight() -- Check if conditions are right. if stack==1 and flight.holding~=nil and Tmarshal>=TmarshalMin then - return flight + if flight.ai then + -- Return AI flight. + return flight + else + -- Check for human player if they are already commencing. + if flight.step~=AIRBOSS.PatternStep.COMMENCING then + return flight + end + end end end @@ -5592,16 +5666,22 @@ function AIRBOSS:_ClearForLanding(flight) self:_RemoveFlightFromMarshalQueue(flight, false) self:_LandAI(flight) + -- Cleared for Case X recovery. + self:_MarshalCallClearedForRecovery(flight.onboard, flight.case) + else + + -- Cleared for Case X recovery. + if flight.step~=AIRBOSS.PatternStep.COMMENCING then + self:_MarshalCallClearedForRecovery(flight.onboard, flight.case) + flight.time=timer.getAbsTime() + end -- Set step to commencing. This will trigger the zone check until the player is in the right place. self:_SetPlayerStep(flight, AIRBOSS.PatternStep.COMMENCING, 3) - + end - - -- Cleared for Case X recovery. - self:_MarshalCallClearedForRecovery(flight.onboard, flight.case) - + end --- Set player step. Any warning is erased and next step hint shown. @@ -8703,6 +8783,14 @@ function AIRBOSS:_Commencing(playerData, zonecheck) -- Skip the rest if not in the zone yet. if not inzone then + + -- Friendly reminder. + if timer.getAbsTime()-playerData.time>180 then + self:_MarshalCallClearedForRecovery(playerData.onboard, playerData.case) + playerData.time=timer.getAbsTime() + end + + -- Skip the rest. return end @@ -8931,11 +9019,11 @@ function AIRBOSS:_DirtyUp(playerData) self:_PlayerHint(playerData) -- Radio call "Say/Fly needles". Delayed by 10/15 seconds. - if playerData.actype==AIRBOSS.AircraftCarrier.HORNET then + if playerData.actype==AIRBOSS.AircraftCarrier.HORNET or playerData.actype==AIRBOSS.AircraftCarrier.F14A or playerData.actype==AIRBOSS.AircraftCarrier.F14B then local callsay=self:_NewRadioCall(self.MarshalCall.SAYNEEDLES, nil, nil, 5, playerData.onboard) local callfly=self:_NewRadioCall(self.MarshalCall.FLYNEEDLES, nil, nil, 5, playerData.onboard) - self:RadioTransmission(self.MarshalRadio, callsay, false, 50, nil, true) - self:RadioTransmission(self.MarshalRadio, callfly, false, 55, nil, true) + self:RadioTransmission(self.MarshalRadio, callsay, false, 55, nil, true) + self:RadioTransmission(self.MarshalRadio, callfly, false, 60, nil, true) end -- TODO: Make Fly Bullseye call if no automatic ICLS is active. @@ -9059,9 +9147,24 @@ function AIRBOSS:_Break(playerData, part) self:_AbortPattern(playerData, X, Z, breakpoint, true) return end + + -- Player made a very tight turn and did not trigger the latebreak threshold at 0.8 NM. + local tooclose=false + if part==AIRBOSS.PatternStep.LATEBREAK then + local close=0.8 + if playerData.actype==AIRBOSS.AircraftCarrier.AV8B then + close=0.5 + end + if X<0 and Zcwp then - s=p:Get2DDistance(self.waypoints[cwp+1]) - end + local s=p:Get2DDistance(nextWP) + + -- Distance to next waypoint. + --local s=0 + --if #self.waypoints>cwp then + -- s=p:Get2DDistance(self.waypoints[cwp+1]) + --end -- v=s/t <==> t=s/v local t=s/v @@ -15225,10 +15384,46 @@ function AIRBOSS:_RequestEmergency(_unitName) -- Mission designer did not allow emergency landing. text="negative, no emergency landings on my carrier. We are currently busy. See how you get along!" - elseif not _unit:InAir() then + elseif not _unit:InAir() then + + -- Carrier zone. + local zone=self:_GetZoneCarrierBox() + + -- Check if player is on the carrier. + if playerData.unit:IsInZone(zone) then + + -- Bolter pattern. + text="roger, you are now technically in the bolter pattern. Your next step after takeoff is abeam!" + + -- Get flight lead. + local lead=self:_GetFlightLead(playerData) + + -- Set set for lead. + self:_SetPlayerStep(lead, AIRBOSS.PatternStep.BOLTER) + + -- Also set bolter pattern for all members. + for _,sec in pairs(lead.section) do + local sectionmember=sec --#AIRBOSS.PlayerData + self:_SetPlayerStep(sectionmember, AIRBOSS.PatternStep.BOLTER) + end + + -- Remove flight from waiting queue just in case. + self:_RemoveFlightFromQueue(self.Qwaiting, lead) + + if self:_InQueue(self.Qmarshal, lead.group) then + -- Remove flight from Marshal queue and add to pattern. + self:_RemoveFlightFromMarshalQueue(lead) + else + -- Add flight to pattern if he was not. + if not self:_InQueue(self.Qpattern, lead.group) then + self:_AddFlightToPatternQueue(lead) + end + end - -- Flight group is not in air - text=string.format("negative, you are not airborne. Request denied!") + else + -- Flight group is not in air. + text=string.format("negative, you are not airborne. Request denied!") + end else @@ -15249,8 +15444,7 @@ function AIRBOSS:_RequestEmergency(_unitName) -- Remove flight from spinning queue just in case (everone can spin on his own). self:_RemoveFlightFromQueue(self.Qspinning, sectionmember) end - - + -- Remove flight from waiting queue just in case. self:_RemoveFlightFromQueue(self.Qwaiting, lead)