diff --git a/Moose Development/Moose/Functional/Warehouse.lua b/Moose Development/Moose/Functional/Warehouse.lua index ce48be657..3ea75cd03 100644 --- a/Moose Development/Moose/Functional/Warehouse.lua +++ b/Moose Development/Moose/Functional/Warehouse.lua @@ -8441,7 +8441,7 @@ end -- @return #string Text about warehouse stock function WAREHOUSE:_UpdateWarehouseMarkText() - if self.makerOn then + if self.markerOn then -- Create a mark with the current assets in stock. if self.markerid~=nil then diff --git a/Moose Development/Moose/Ops/FlightControl.lua b/Moose Development/Moose/Ops/FlightControl.lua index 42e4afe4b..e6cdd62e1 100644 --- a/Moose Development/Moose/Ops/FlightControl.lua +++ b/Moose Development/Moose/Ops/FlightControl.lua @@ -44,6 +44,7 @@ -- @field #number Nlanding Max number of aircraft groups in the landing pattern. -- @field #number dTlanding Time interval in seconds between landing clearance. -- @field #number Nparkingspots Total number of parking spots. +-- @field Core.Spawn#SPAWN parkingGuard Parking guard spawner. -- @extends Core.Fsm#FSM --- **Ground Control**: Airliner X, Good news, you are clear to taxi to the active. @@ -106,8 +107,7 @@ FLIGHTCONTROL = { --- Parking spot data. -- @type FLIGHTCONTROL.ParkingSpot --- @field #boolean reserved If true, reserved. --- @field #number markerid ID of the marker. +-- @field Wrapper.Group#GROUP ParkingGuard Parking guard for this spot. -- @extends Wrapper.Airbase#AIRBASE.ParkingSpot --- Parking spot data. @@ -140,6 +140,19 @@ FLIGHTCONTROL.FlightStatus={ -- @field #number width Width of runway in meters. -- @field Core.Point#COORDINATE position Position of runway start. + +--- Sound file data. +-- @type FLIGHTCONTROL.Soundfile +-- @field #string filename Name of the file +-- @field #number duration Duration in seconds. + +--- Sound files. +-- @type FLIGHTCONTROL.Sound +-- @field #FLIGHTCONTROL.Soundfile ActiveRunway +FLIGHTCONTROL.Sound = { + ActiveRunway={filename="ActiveRunway.ogg", duration=0.99}, +} + --- FlightControl class version. -- @field #string version FLIGHTCONTROL.version="0.3.0" @@ -298,6 +311,18 @@ function FLIGHTCONTROL:SetActiveRunwayNumber(no) return self end + +--- Set the parking guard group. +-- @param #FLIGHTCONTROL self +-- @param #string TemplateGroupName Name of the template group. +-- @return #FLIGHTCONTROL self +function FLIGHTCONTROL:SetParkingGuard(TemplateGroupName) + + self.parkingGuard=SPAWN:New(TemplateGroupName) + + return self +end + ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- Status ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -410,10 +435,19 @@ function FLIGHTCONTROL:OnEventBirth(EventData) self:I(self.lid..string.format("BIRTH: unit = %s", tostring(EventData.IniUnitName))) self:T2(self.lid..string.format("BIRTH: group = %s", tostring(EventData.IniGroupName))) + -- Unit that was born. + local unit=EventData.IniUnit -- We delay this, to have all elements of the group in the game. - if EventData.IniUnit:IsAir() then + if unit:IsAir() then + + -- Coordinate. + local coordinate=unit:GetCoordinate() + self:ScheduleOnce(0.1, self._CreateFlightGroup, self, EventData.IniGroup) + + self:SpawnParkingGuard(unit) + end end @@ -591,18 +625,30 @@ function FLIGHTCONTROL:_CheckQueues() MESSAGE:New(text, 5, "FLIGHTCONTROL"):ToAll() -- Start uncontrolled aircraft. - -- TODO: handle case with engines hot. That does not trigger a ENGINE_START event. More a FLIGHTGROUP issue. - flight.group:StartUncontrolled() + if flight:IsUncontrolled() then + flight:StartUncontrolled() + end -- Add flight to takeoff queue. self:SetFlightStatus(flight, FLIGHTCONTROL.FlightStatus.TAKEOFF) else + local text=string.format("HUMAN Flight %s, you are cleared for takeoff.", flight.groupname) self:I(self.lid..text) MESSAGE:New(text, 5, "FLIGHTCONTROL"):ToAll() end + + -- Remove parking guards. + for _,_element in pairs(flight.elements) do + local element=_element --Ops.FlightGroup#FLIGHTGROUP.Element + if element and element.parking then + local spot=self:GetParkingSpotByID(element.parking.TerminalID) + self:RemoveParkingGuard(spot) + end + end + else self:I(self.lid..string.format("FYI: Take of for flight %s denied as other flights are taking off (N=%d) or landing (N=%d).", flight.groupname, ntakeoff, nlanding)) end @@ -739,6 +785,9 @@ function FLIGHTCONTROL:_GetNextFightParking() -- First come, first serve. return Qtaxiout[1] + + else + return nil end local Qparking=self:GetFlights(FLIGHTCONTROL.FlightStatus.PARKING) @@ -1034,7 +1083,7 @@ end --- Get parking spot by its Terminal ID. -- @param #FLIGHTCONTROL self -- @param #number TerminalID --- @return Wrapper.Airbase#AIRBASE.ParkingSpot Parking spot data table. +-- @return #FLIGHTCONTROL.ParkingSpot Parking spot data table. function FLIGHTCONTROL:GetParkingSpotByID(TerminalID) return self.parking[TerminalID] end @@ -1117,7 +1166,7 @@ function FLIGHTCONTROL:UpdateParkingMarker(spot) else - spot.Marker=MARKER:New(spot.Coordinate, text):ToAll(Delay) + spot.Marker=MARKER:New(spot.Coordinate, text):ToAll() end @@ -1202,7 +1251,7 @@ end -- @param Core.Point#COORDINATE coordinate Reference coordinate. -- @param #number terminaltype (Optional) Check only this terminal type. -- @param #boolean free (Optional) If true, check only free spots. --- @return Wrapper.Airbase#AIRBASE.ParkingSpot Closest parking spot. +-- @return #FLIGHTCONTROL.ParkingSpot Closest parking spot. function FLIGHTCONTROL:GetClosestParkingSpot(coordinate, terminaltype, free) local distmin=math.huge @@ -1348,10 +1397,10 @@ function FLIGHTCONTROL:_PlayerRequestParking(groupname) MESSAGE:New(text, 10, "FLIGHCONTROL", true):ToAll() -- Create mark on F10 map. - if spot.MarkerID then - coord:RemoveMark(spot.MarkerID) + if spot.Marker then + spot.Marker:Remove() end - spot.MarkerID=spot.Coordinate:MarkToGroup("Your assigned parking spot!", group) + spot.Marker:SetText("Your assigned parking spot!"):ToGroup(group) -- TODO: get element of human player. local element=flight.elements[1] --Ops.FlightGroup#FLIGHTGROUP.Element @@ -1880,10 +1929,71 @@ function FLIGHTCONTROL:_GetHoldingpoint(flight) return holdingpoint end +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +-- Radio Functions +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +--- Transmission via RADIOQUEUE. +-- @param #FLIGHTCONTROL self +-- @param #FLIGHTCONTROL.Soundfile sound FLIGHTCONTROL sound object. +-- @param #number interval Interval in seconds after the last transmission finished. +-- @param #string subtitle Subtitle of the transmission. +-- @param #string path Path to sound file. Default self.soundpath. +function FLIGHTCONTROL:Transmission(sound, interval, subtitle, path) + self.radioqueue:NewTransmission(sound.filename, sound.duration, path or self.soundpath, nil, interval, subtitle, self.subduration) +end + ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- Misc Functions ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +--- Add parking guard in front of a parking aircraft. +-- @param #FLIGHTCONTROL self +-- @param Wrapper.Unit#UNIT Unit The aircraft. +function FLIGHTCONTROL:SpawnParkingGuard(unit) + + if unit and self.parkingGuard then + + local coordinate=unit:GetCoordinate() + + -- Parking spot. + local spot=self:GetClosestParkingSpot(coordinate) + + -- Current heading of the unit. + local heading=unit:GetHeading() + + -- Length of the unit + 3 meters. + local _,distance=unit:GetObjectSize()+3 + + -- Coordinate for the guard. + local Coordinate=coordinate:Translate(distance, heading) + + -- Let him face the aircraft. + local lookat=heading-180 + + -- Set heading and AI off to save resources. + self.parkingGuard:InitHeading(lookat,lookat):InitAIOff() + + -- Group that is spawned. + spot.ParkingGuard=self.parkingGuard:SpawnFromCoordinate(Coordinate) + + end + +end + +--- Remove parking guard. +-- @param #FLIGHTCONTROL self +-- @param #FLIGHTCONTROL.ParkingSpot spot +function FLIGHTCONTROL:RemoveParkingGuard(spot) + + if spot.ParkingGuard then + spot.ParkingGuard:Destroy() + spot.ParkingGuard=nil + end + +end + + --- Get coordinate of the airbase. -- @param #FLIGHTCONTROL self -- @return Core.Point#COORDINATE Coordinate of the airbase. diff --git a/Moose Development/Moose/Ops/FlightGroup.lua b/Moose Development/Moose/Ops/FlightGroup.lua index 24a75b41c..a96bf543a 100644 --- a/Moose Development/Moose/Ops/FlightGroup.lua +++ b/Moose Development/Moose/Ops/FlightGroup.lua @@ -4680,14 +4680,14 @@ end --- Check if this group is currently "late activated" and needs to be "activated" to appear in the mission. -- @param #FLIGHTGROUP self --- @return #boolean Hot start? +-- @return #boolean Is this the group late activated? function FLIGHTGROUP:IsLateActivated() return self.isLateActivated end --- Check if this group is currently "uncontrolled" and needs to be "started" to begin its route. -- @param #FLIGHTGROUP self --- @return #boolean Hot start? +-- @return #boolean If this group uncontrolled. function FLIGHTGROUP:IsUncontrolled() return self.isUncontrolled end @@ -5835,7 +5835,7 @@ end --- Get number of elements alive. -- @param #FLIGHTGROUP self -- @param #string status (Optional) Only count number, which are in a special status. --- @return #number Holding time in seconds or -1 if flight is not holding. +-- @return #number Number of elements. function FLIGHTGROUP:GetNelements(status) local n=0 diff --git a/Moose Development/Moose/Wrapper/Marker.lua b/Moose Development/Moose/Wrapper/Marker.lua index 7148578d5..fd0cd71ed 100644 --- a/Moose Development/Moose/Wrapper/Marker.lua +++ b/Moose Development/Moose/Wrapper/Marker.lua @@ -344,6 +344,11 @@ function MARKER:ToAll(Delay) else self.toall=true + self.tocoaliton=nil + self.coalition=nil + self.togroup=nil + self.groupname=nil + self.groupid=nil -- First remove an existing mark. if self.shown then @@ -374,6 +379,10 @@ function MARKER:ToCoalition(Coalition, Delay) self.coalition=Coalition self.tocoaliton=true + self.toall=false + self.togroup=false + self.groupname=nil + self.groupid=nil -- First remove an existing mark. if self.shown then @@ -439,6 +448,9 @@ function MARKER:ToGroup(Group, Delay) self.groupname=Group:GetName() self.togroup=true + self.tocoaliton=nil + self.coalition=nil + self.toall=nil -- First remove an existing mark. if self.shown then @@ -480,6 +492,7 @@ function MARKER:UpdateText(Text, Delay) end + return self end --- Update the coordinate where the marker is displayed. @@ -501,6 +514,7 @@ function MARKER:UpdateCoordinate(Coordinate, Delay) end + return self end --- Refresh the marker. @@ -533,6 +547,7 @@ function MARKER:Refresh(Delay) end + return self end --- Remove a marker. @@ -550,6 +565,7 @@ function MARKER:Remove(Delay) end + return self end --- Get position of the marker. @@ -559,13 +575,22 @@ function MARKER:GetCoordinate() return self.coordinate end ---- Get text that is dispayed in the marker panal. +--- Get text that is displayed in the marker panel. -- @param #MARKER self -- @return #string Marker text. function MARKER:GetText() return self.text end +--- Set text that is displayed in the marker panel. Note this does not show the marker. +-- @param #MARKER self +-- @param #string Text Marker text. +-- @return #MARKER self +function MARKER:SetText(Text) + self.text=tostring(Text) + return self +end + --- Check if marker is currently visible on the F10 map. -- @param #MARKER self