- Improved taxi phrases
This commit is contained in:
Frank 2023-09-20 11:52:14 +02:00
parent 1116b19b00
commit cbdbf36f32
2 changed files with 280 additions and 101 deletions

View File

@ -92,9 +92,9 @@ PATHLINE.version="0.3.0"
-- TODO list
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO: A lot...
-- TODO: Read/write to JSON file
-- TODO: Translate/rotate pathline
-- TODO: Add color.
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Constructor
@ -111,7 +111,7 @@ function PATHLINE:New(Name)
self.name=Name or "Unknown Path"
self.lid=string.format("PATHLINE %s | ", Name)
self.lid=string.format("PATHLINE %s | ", self.name)
return self
end
@ -570,7 +570,8 @@ end
--- Write PATHLINE to JSON file.
-- **NOTE**: Requires `io` and `lfs` to be de-sanitized!
-- @param #PATHLINE self
-- @param #string FileName Name of the file.
-- @param #string FileName Name of the file. Default is the name of the pathline.
-- @return #PATHLINE self
function PATHLINE:WriteJSON(FileName)
if io and lfs then
@ -580,18 +581,19 @@ function PATHLINE:WriteJSON(FileName)
local data={}
data.name=self.name
-- We store the name and the points.
data.name=self.name
data.points=self.points
for i,_point in pairs(self.points) do
local point=_point --#PATHLINE.Point
--point.markerID=nil
end
-- Encode data to raw JSON.
-- Encode data to raw JSON. Encode converts a lua table into JSON string that can be written to file.
local raw_json=json:encode(data)
self:I(data)
-- Debug data.
self:T(data)
-- Write in "User/Saved Games/" Folder.
local filepath=lfs.writedir() .. FileName
@ -601,7 +603,7 @@ function PATHLINE:WriteJSON(FileName)
if f then
f:write(raw_json)
f:close()
self:I(self.lid .. string.format("FF Saving PATHLINE %s file %s", self.name, tostring(filepath)))
self:T(self.lid .. string.format("Saving PATHLINE %s file %s", self.name, tostring(filepath)))
else
self:E(self.lid .. string.format( "ERROR: Could not save PATHLINE to file %s", tostring(filepath)))
end
@ -619,7 +621,6 @@ end
-- @return #PATHLINE self
function PATHLINE:NewFromJSON(FileName)
if io and lfs then
-- JSON script.
@ -630,38 +631,47 @@ function PATHLINE:NewFromJSON(FileName)
-- Write in "User/Saved Games/" Folder.
local filepath=lfs.writedir() .. FileName
env.info(filepath)
--env.info(filepath)
local f = io.open( filepath, "rb" )
-- Open file in binary mode for reading.
local f = io.open(filepath, "rb")
if f then
-- self:I(self.lid..string.format("Loading player results from file %s", tostring(filename)))
data = f:read("*all")
f:close()
f:close()
else
env.info(string.format( "WARNING: Could not load player results from file %s. File might not exist just yet.", tostring( filepath ) ) )
env.info(string.format("WARNING: Could not load PATHLINE from file %s!", tostring(filepath)))
return nil
end
BASE:I(data)
-- Decode JSON data to get a lua table.
local data=json:decode(data)
local _data=json:decode(data)
BASE:I(_data)
if data and data.name then
local self=PATHLINE:New(data.name)
for i=1,#data.points do
local point=data.points[i] --#PATHLINE.Point
local p=pathline:AddPointFromVec3(point.vec3)
p.name=point.name
p.markerID=nil
-- Create a new pathline instance.
local self=PATHLINE:New(data.name)
for i=1,#data.points do
local point=data.points[i] --#PATHLINE.Point
-- Create new point from data.
local p=self:AddPointFromVec3(point.vec3)
-- Set name.
p.name=point.name
-- Remove marker ID.
p.markerID=nil
end
return self
else
BASE:E("ERROR: Cannot find pathline name in data from JSON file. File may be corrupted!")
end
return self
else
BASE:E("ERROR: IO and/or LFS not de-sanitized! Cannot read file.")
end
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

View File

@ -333,17 +333,20 @@ FLIGHTCONTROL.FlightStatus={
--- Violations
-- @type FLIGHTCONTROL.Violation
-- @field #string Speeding Speed violation while taxiing.
-- @field #string Altitude Altitude deviation (300 ft from assigned).
-- @field #string Runway Runway incursion.
FLIGHTCONTROL.Violation={
Speeding="Speeding",
AltitudeDeviation="Altitude Deviation", --300 feet from assigned alt.
RunwayIncursion="Runway Incursion",
Altitude="Altitude Deviation", --300 feet from assigned alt.
Runway="Runway Incursion",
}
--- Warning.
-- @type FLIGHTCONTROL.Warning
-- @field Ops.FlightGroup#FLIGHTGROUP flight The flight group.
-- @field #string type Type of warning.
-- @field #number time Time stamp when warning was issued.
-- @field #number time Abs. time stamp when warning was issued.
--- FlightControl class version.
-- @field #string version
@ -1501,7 +1504,7 @@ function FLIGHTCONTROL:_CheckQueues()
-- Get taxi way text.
local taxiroute=self:_GetTaxiwayText(taxipath, false)
text=text.." via "..taxiroute
text=text.." via "..taxiroute
end
-- Hold short instructions.
@ -1522,20 +1525,25 @@ function FLIGHTCONTROL:_CheckQueues()
---
-- Read back runway.
local text=string.format("Runway %s, ", runway)
local text=string.format("Runway %s", runway)
-- Read back taxi ways (if available).
if flight.taxipath then
text=text..string.format(" via %s", self:_GetTaxiwayText(flight.taxipath))
end
-- Start uncontrolled aircraft.
if flight:IsUncontrolled() then
-- Message.
text=text..string.format("starting engines, ")
text=text..string.format(", starting engines")
-- Start uncontrolled aircraft.
flight:StartUncontrolled()
end
-- Append call sign.
text=text..callsign
text=text..string.format(", %s.", callsign)
-- Transmit message.
self:TransmissionPilot(text, flight, 10)
@ -3608,18 +3616,28 @@ function FLIGHTCONTROL:_PlayerConfirmTaxi(groupname)
-- Get callsign.
local callsign=self:_GetCallsignName(flight)
-- Runway for takeoff.
local runway=self:GetActiveRunwayText(true)
-- Runway for takeoff.
local runway=self:GetActiveRunwayText(true)
-- Tell pilot to wait until cleared.
local text=string.format("Taxi to runway %s, %s", runway, callsign)
self:TransmissionPilot(text, flight)
-- Read back runway.
local text=string.format("Taxi to runway %s", runway)
-- Read back taxi ways (if available).
if flight.taxipath then
text=text..string.format(" via %s", self:_GetTaxiwayText(flight.taxipath))
end
-- Append call sign.
text=text..string.format(", %s.", callsign)
-- Transmission.
self:TransmissionPilot(text, flight)
-- Taxi out.
self:SetFlightStatus(flight, FLIGHTCONTROL.FlightStatus.TAXIOUT)
-- Taxi out.
self:SetFlightStatus(flight, FLIGHTCONTROL.FlightStatus.TAXIOUT)
end
end
--- Player aborts taxi.
@ -4173,8 +4191,6 @@ function FLIGHTCONTROL:_CheckFlights()
-- Current flight status.
local flightstatus=self:GetFlightStatus(flight)
---
-- Track flight
---
@ -4219,86 +4235,131 @@ function FLIGHTCONTROL:_CheckFlights()
end
if not flight.isAI then
-- Check if speeding while taxiing.
if (flightstatus==FLIGHTCONTROL.FlightStatus.TAXIINB or flightstatus==FLIGHTCONTROL.FlightStatus.TAXIOUT) then
if flightstatus==FLIGHTCONTROL.FlightStatus.PARKING then
-- Check if still on parking spot!
elseif flightstatus==FLIGHTCONTROL.FlightStatus.READYTX then
-- Flight is ready to taxi to the runway: ?
elseif flightstatus==FLIGHTCONTROL.FlightStatus.TAXIOUT then
if self.speedLimitTaxi then
self:_CheckFlightSpeeding(flight)
end
end
end
if (flightstatus==FLIGHTCONTROL.FlightStatus.TAXIINB or flightstatus==FLIGHTCONTROL.FlightStatus.TAXIOUT) then
end
elseif flightstatus==FLIGHTCONTROL.FlightStatus.READYTO then
if (flightstatus==FLIGHTCONTROL.FlightStatus.LANDING) then
--Talk down
end
-- Flight is ready for taking-off: ?
elseif flightstatus==FLIGHTCONTROL.FlightStatus.TAKEOFF then
-- Flight is taking-off: Check correct runway
elseif flightstatus==FLIGHTCONTROL.FlightStatus.INBOUND then
-- Flight is inbound to holding pattern: Nothing to do!
elseif flightstatus==FLIGHTCONTROL.FlightStatus.HOLDING then
if (flightstatus==FLIGHTCONTROL.FlightStatus.PARKING) then
--Check if still on parking spot!
end
if (flightstatus==FLIGHTCONTROL.FlightStatus.HOLDING) then
--Check altitude and position
local stack=flight.stack
if stack then
local altitude=stack.angels
local altitude=stack.angels*1000
local alt=flight:GetAltitude()
local alt=UTILS.MetersToFeet(flight:GetAltitude())
local diff=alt-altitude
local callsign=self:_GetCallsignName(flight)
-- TODO: issue warning and keep track. otherwise this will repeat unncessarily
-- TODO: make a good warning structure and save it in the flightgroup or here.
-- needs the kind of warning and the time stamp at least
--
if diff<300 then
local timestamp=self:_GetLastWarning(WARNING.Type.AltitudeLow)
if timestamp==nil or timer.getAbsTime()-timestamp>5*60 then
end
-- Get number of warnings issued in the last 30 min.
local N=self:_GetWarnings(WARNING.Type.AltitudeLow, Tstart, Tend)
if N>1 then
elseif N>5 then
--Possible pilot deviation.
end
local text=string.format("%s, you are too low. Climb to the assigned altitude!")
self:TransmissionTower(text, flight)
elseif diff>300 then
local text=string.format("%s, you are too high. Descent to the assigned altitude!")
self:TransmissionTower(text, flight)
-- Check if absolute difference > 300 ft (lower or higher).
if math.abs(diff)>300 then
end
end
-- Get last altitude warning.
local warningAlt=self:_WarningGetLast(flight, FLIGHTCONTROL.Violation.Altitude)
-- Check if no warning so far or last warning more than 5 min ago.
if warningAlt==nil or timer.getAbsTime()-warningAlt.time>5*60 then
-- Number of warnings.
local N=self:_WarningCount(flight, FLIGHTCONTROL.Violation.Altitude)
end
if (flightstatus==FLIGHTCONTROL.FlightStatus.ARRIVED) then
local text=string.format("%s, you are ", callsign)
if diff<300 then
-- Get number of warnings issued in the last 30 min.
if N==0 then
text=text..string.format("too low. Climb to the assigned altitude.")
elseif N==1 then
text=text..string.format("still too low. Climb to the assigned altitude!")
elseif N==2 then
text=text..string.format("still too low. Climb to the assigned altitude immediately!")
end
elseif diff>300 then
if N==0 then
text=text..string.format("you are too high. Descent to the assigned altitude!")
elseif N==1 then
text=text..string.format("still too high. Descent to the assigned altitude!")
elseif N==2 then
text=text..string.format("still too high. Descent to the assigned altitude immediately!")
end
end
if N==1 then
text=text..string.format("This was your second warning for an altitude deviation!")
elseif N==2 then
text=text..string.format("This was your third and last warning.")
elseif N==3 then
text=text..string.format("Possible pilot deviation. Call 5 5 5 - 1 2 3 4 5")
else
text=nil
end
-- Transmission.
if text then
self:TransmissionTower(text, flight)
end
-- Issue another warning.
self:_WarningIssue(flight, FLIGHTCONTROL.Violation.Altitude)
end -- No warning or warning more then threshold
end -- Alt diff > 300 ft
end -- Stack~=nil
elseif flightstatus==FLIGHTCONTROL.FlightStatus.LANDING then
--Talk down if on final
elseif flightstatus==FLIGHTCONTROL.FlightStatus.TAXIINB then
if self.speedLimitTaxi then
self:_CheckFlightSpeeding(flight)
end
elseif flightstatus==FLIGHTCONTROL.FlightStatus.ARRIVED then
--Check if still on correct parking spot!
end
if (flightstatus==FLIGHTCONTROL.FlightStatus.READYTX) then
-- ?
elseif flightstatus==FLIGHTCONTROL.FlightStatus.UNKNOWN then
-- Status Unknown: Nothing to do!
else
self:E(self.lid..string.format("ERROR: Unknown flight status!"))
end
if (flightstatus==FLIGHTCONTROL.FlightStatus.READYTO) then
-- ?
end
end
end
@ -4340,6 +4401,9 @@ function FLIGHTCONTROL:_CheckFlightSpeeding(flight)
-- Get player data.
local PlayerData=flight:_GetPlayerData()
-- Issue warning.
local warning=self:_WarningIssue(flight, FLIGHTCONTROL.Violation.Speeding)
-- Trigger FSM speeding event.
self:PlayerSpeeding(PlayerData)
@ -4510,6 +4574,111 @@ function FLIGHTCONTROL:_FlightOnFinal(flight)
return self
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Warning Functions
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Issue a warning to a flight for a given violation.
-- @param #FLIGHTCONTROL self
-- @param Ops.Flightgroup#FLIGHTGROUP Flight The flight group.
-- @param #string Violation Violation of flight.
-- @return #FLIGHTCONTROL.Warning The warning data that was issued.
function FLIGHTCONTROL:_WarningIssue(Flight, Violation)
--TODO: Violation should be issued for a player not the flight.
-- AI gets no violations
local name=Flight:GetName()
self.warnings[name]=self.warnings[name] or {}
-- Create a new warning.
local warning={} --#FLIGHTCONTROL.Warning
warning.flight=Flight
warning.type=Violation
warning.time=timer.getAbsTime()
table.insert(self.warnings[name], warning)
return warning
end
--- Get last warning of a given flight.
-- @param #FLIGHTCONTROL self
-- @param Ops.Flightgroup#FLIGHTGROUP Flight The flight group.
-- @param #string Violation Violation of flight. If not specified, the last violation independent of type is returned.
-- @return #FLIGHTCONTROL.Warning Last warning data or `nil` if no warning was issued so far.
function FLIGHTCONTROL:_WarningGetLast(Flight, Violation)
-- Get flight name.
local name=Flight:GetName()
-- All warnings of flight
local warnings=self.warnings[name] or {}
-- Go backwards because the warnings are appended, so the last warning is at the end of the table.
for i=#warnings,1,-1 do
local warning=warnings[i] --#FLIGHTCONTROL.Warning
if Violation==nil or warning.type==Violation then
return warning
end
end
return nil
end
--- Count warnings of a given flight.
-- @param #FLIGHTCONTROL self
-- @param Ops.Flightgroup#FLIGHTGROUP Flight The flight group.
-- @param #string Violation Violation of flight. If not specified, all violations independent of type are counted.
-- @return #number Numer of warnings.
function FLIGHTCONTROL:_WarningCount(Flight, Violation)
-- Get flight name.
local name=Flight:GetName()
-- All warnings of flight
local warnings=self.warnings[name] or {}
-- Init counter.
local N=0
-- Go backwards because the warnings are appended, so the last warning is at the end of the table.
for i=#warnings,1,-1 do
local warning=warnings[i] --#FLIGHTCONTROL.Warning
if Violation==nil or warning.type==Violation then
N=N+1
end
end
return N
end
--- Clear all warnings of a given flight.
-- @param #FLIGHTCONTROL self
-- @param Ops.Flightgroup#FLIGHTGROUP Flight The flight group.
-- @param #string Violation Violation of flight. If not specified, all violations independent of type are cleared.
function FLIGHTCONTROL:_WarningClear(Flight, Violation)
-- Get flight name.
local name=Flight:GetName()
-- All warnings of flight
local warnings=self.warnings[name] or {}
-- Go backwards because otherwise remove by index gets confused.
for i=#warnings,1,-1 do
local warning=warnings[i] --#FLIGHTCONTROL.Warning
if Violation==nil or warning.type==Violation then
table.remove(warnings, i)
end
end
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Radio Functions
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------