mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-10-29 16:58:06 +00:00
Improved get destination/departuire behaviour.
This commit is contained in:
parent
0c55d4d20e
commit
c41b30adc2
@ -68,6 +68,7 @@
|
||||
-- @field #number spawndelay Delay time in seconds before first spawning happens.
|
||||
-- @field #number spawninterval Interval between spawning units/groups. Note that we add a randomization of 50%.
|
||||
-- @field #number coalition Coalition of spawn group template.
|
||||
-- @field #number country Country of spawn group template.
|
||||
-- @field #string category Category of aircarft: "plane" or "heli".
|
||||
-- @field #string friendly Possible departure/destination airport: all=blue+red+neutral, same=spawn+neutral, spawnonly=spawn, blue=blue+neutral, blueonly=blue, red=red+neutral, redonly=red.
|
||||
-- @field #table ctable Table with the valid coalitons from choice self.friendly.
|
||||
@ -107,7 +108,7 @@
|
||||
-- @field #table markerids Array with marker IDs.
|
||||
-- @field #string livery Livery of the aircraft set by user.
|
||||
-- @field #string skill Skill of AI.
|
||||
-- @field #boolean ATC Enable ATC.
|
||||
-- @field #boolean ATCswitch Enable/disable ATC if set to true/false.
|
||||
-- @extends Functional.Spawn#SPAWN
|
||||
|
||||
---# RAT class, extends @{Spawn#SPAWN}
|
||||
@ -262,6 +263,7 @@ RAT={
|
||||
spawndelay=5, -- Delay time in seconds before first spawning happens.
|
||||
spawninterval=5, -- Interval between spawning units/groups. Note that we add a randomization of 50%.
|
||||
coalition = nil, -- Coalition of spawn group template.
|
||||
country = nil, -- Country of the group template.
|
||||
category = nil, -- Category of aircarft: "plane" or "heli".
|
||||
friendly = "same", -- Possible departure/destination airport: all=blue+red+neutral, same=spawn+neutral, spawnonly=spawn, blue=blue+neutral, blueonly=blue, red=red+neutral, redonly=red.
|
||||
ctable = {}, -- Table with the valid coalitons from choice self.friendly.
|
||||
@ -281,6 +283,7 @@ RAT={
|
||||
departure_zones={}, -- Array containing the names of the departure zones.
|
||||
departure_ports={}, -- Array containing the names of the departure airports.
|
||||
destination_ports={}, -- Array containing the names of the destination airports.
|
||||
excluded_ports={}, -- Array containing the names of explicitly excluded airports.
|
||||
ratcraft={}, -- Array with the spawned RAT aircraft.
|
||||
Tinactive=300, -- Time in seconds after which inactive units will be destroyed. Default is 300 seconds.
|
||||
reportstatus=false, -- Aircraft report status.
|
||||
@ -301,7 +304,7 @@ RAT={
|
||||
markerids={}, -- Array with marker IDs.
|
||||
livery=nil, -- Livery of the aircraft.
|
||||
skill="High", -- Skill of AI.
|
||||
ATC=true, -- Enable ATC.
|
||||
ATCswitch=true, -- Enable ATC.
|
||||
}
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
@ -335,11 +338,6 @@ RAT.wp={
|
||||
RAT.coal={
|
||||
same="same",
|
||||
sameonly="sameonly",
|
||||
all="all",
|
||||
blue="blue",
|
||||
blueonly="blueonly",
|
||||
red="red",
|
||||
redonly="redonly",
|
||||
neutral="neutral",
|
||||
}
|
||||
|
||||
@ -464,16 +462,6 @@ function RAT:New(groupname, alias)
|
||||
|
||||
-- Get all airports of current map (Caucasus, NTTR, Normandy, ...).
|
||||
self:_GetAirportsOfMap()
|
||||
|
||||
-- Init RAT ATC if not already done.
|
||||
if self.ATC and not RAT.ATC.init then
|
||||
RAT:_ATCInit(self.airports_map)
|
||||
end
|
||||
|
||||
-- Create F10 main menu if it does not exists yet.
|
||||
if self.f10menu and not RAT.MenuF10 then
|
||||
RAT.MenuF10 = MENU_MISSION:New("RAT")
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
@ -489,6 +477,16 @@ function RAT:Spawn(naircraft)
|
||||
-- Number of aircraft to spawn. Default is one.
|
||||
self.ngroups=naircraft or 1
|
||||
|
||||
-- Init RAT ATC if not already done.
|
||||
if self.ATCswitch and not RAT.ATC.init then
|
||||
RAT:_ATCInit(self.airports_map)
|
||||
end
|
||||
|
||||
-- Create F10 main menu if it does not exists yet.
|
||||
if self.f10menu and not RAT.MenuF10 then
|
||||
RAT.MenuF10 = MENU_MISSION:New("RAT")
|
||||
end
|
||||
|
||||
-- Set the coalition table based on choice of self.coalition and self.friendly.
|
||||
self:_SetCoalitionTable()
|
||||
|
||||
@ -531,6 +529,7 @@ function RAT:Spawn(naircraft)
|
||||
text=text..string.format("Time inactive: %4.1f\n", self.Tinactive)
|
||||
text=text..string.format("Create F10 menu : %s\n", tostring(self.f10menu))
|
||||
text=text..string.format("F10 submenu name: %s\n", self.SubMenuName)
|
||||
text=text..string.format("ATC enabled : %s\n", tostring(self.ATCswitch))
|
||||
text=text..string.format("******************************************************\n")
|
||||
env.info(RAT.id..text)
|
||||
|
||||
@ -570,25 +569,15 @@ end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Set the friendly coalitions from which the airports can be used as departure or destination.
|
||||
--- Set the friendly coalitions from which the airports can be used as departure and destination.
|
||||
-- @param #RAT self
|
||||
-- @param #string friendly "same"=own coalition+neutral (default), "all"=neutral+red+blue", "sameonly"=own coalition only, "blue"=blue+neutral, "blueonly"=blue, "red"=red+neutral, "redonly"=red, "neutral"=neutral.
|
||||
-- @param #string friendly "same"=own coalition+neutral (default), "sameonly"=own coalition only, "neutral"=all neutral airports.
|
||||
-- Default is "same", so aircraft will use airports of the coalition their spawn template has plus all neutral airports.
|
||||
-- @usage yak:SetCoalition("all") will spawn aircraft randomly on airports of any coaliton, i.e. red, blue and neutral, regardless of its own coalition.
|
||||
-- @usage yak:SetCoalition("redonly") will spawn aircraft randomly on airports belonging to the red coalition _only_.
|
||||
-- @usage yak:SetCoalition("neutral") will spawn aircraft randomly on all neutral airports.
|
||||
-- @usage yak:SetCoalition("sameonly") will spawn aircraft randomly on airports belonging to the same coalition only as the template.
|
||||
function RAT:SetCoalition(friendly)
|
||||
if friendly:lower()=="all" then
|
||||
self.friendly=RAT.coal.all
|
||||
elseif friendly:lower()=="sameonly" then
|
||||
if friendly:lower()=="sameonly" then
|
||||
self.friendly=RAT.coal.sameonly
|
||||
elseif friendly:lower()=="blue" then
|
||||
self.friendly=RAT.coal.blue
|
||||
elseif friendly:lower()=="blueonly" then
|
||||
self.friendly=RAT.coal.blueonly
|
||||
elseif friendly:lower()=="red" then
|
||||
self.friendly=RAT.coal.red
|
||||
elseif friendly:lower()=="redonly" then
|
||||
self.friendly=RAT.coal.redonly
|
||||
elseif friendly:lower()=="neutral" then
|
||||
self.friendly=RAT.coal.neutral
|
||||
else
|
||||
@ -596,6 +585,32 @@ function RAT:SetCoalition(friendly)
|
||||
end
|
||||
end
|
||||
|
||||
--- Set coalition of RAT group. You can make red templates blue and vice versa.
|
||||
-- @param #RAT self
|
||||
-- @param #string color Color of coalition, i.e. "red" or blue".
|
||||
function RAT:SetCoalitionAircraft(color)
|
||||
if color:lower()=="blue" then
|
||||
self.coalition=coalition.side.BLUE
|
||||
if not self.country then
|
||||
self.country=country.id.USA
|
||||
end
|
||||
elseif color:lower()=="red" then
|
||||
self.coalition=coalition.side.RED
|
||||
if not self.country then
|
||||
self.country=country.id.RUSSIA
|
||||
end
|
||||
elseif color:lower()=="neutral" then
|
||||
self.coalition=coalition.side.NEUTRAL
|
||||
end
|
||||
end
|
||||
|
||||
--- Set country of RAT group. This overrules the coalition settings.
|
||||
-- @param #RAT self
|
||||
-- @param #number id DCS country enumerator ID. For example country.id.USA or country.id.RUSSIA.
|
||||
function RAT:SetCoalition2(id)
|
||||
self.country=id
|
||||
end
|
||||
|
||||
--- Set takeoff type. Starting cold at airport, starting hot at airport, starting at runway, starting in the air.
|
||||
-- Default is "takeoff-coldorhot". So there is a 50% chance that the aircraft starts with cold engines and 50% that it starts with hot engines.
|
||||
-- @param #RAT self
|
||||
@ -704,6 +719,17 @@ function RAT:SetDestination(names)
|
||||
|
||||
end
|
||||
|
||||
--- Airports, FARPs and ships explicitly excluded as departures and destinations.
|
||||
-- @param #RAT self
|
||||
-- @param #string airports Name or table of names of excluded airports.
|
||||
function RAT:Excluded(ports)
|
||||
if type(ports)=="string" then
|
||||
self.excluded_ports={ports}
|
||||
else
|
||||
self.excluded_ports=ports
|
||||
end
|
||||
end
|
||||
|
||||
--- Set livery of aircraft. If more than one livery is specified in a table, the actually used one is chosen randomly from the selection.
|
||||
-- @param #RAT self
|
||||
-- @param #string skins Name of livery or table of names of liveries.
|
||||
@ -715,7 +741,6 @@ function RAT:Livery(skins)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--- Aircraft will continue their journey from their destination. This means they are respawned at their destination and get a new random destination.
|
||||
-- @param #RAT self
|
||||
-- @param #boolean switch Turn journey on=true or off=false. If no value is given switch=true.
|
||||
@ -822,8 +847,7 @@ end
|
||||
-- @param #RAT self
|
||||
-- @param #boolean switch true=enable ATC, false=disable ATC.
|
||||
function RAT:EnableATC(switch)
|
||||
switch=switch or true
|
||||
self.ATC=switch
|
||||
self.ATCswitch=switch
|
||||
end
|
||||
|
||||
--- Set minimum distance between departure and destination. Default is 5 km.
|
||||
@ -1033,7 +1057,7 @@ function RAT:_SpawnWithRoute(_departure, _destination)
|
||||
self.alive=self.alive+1
|
||||
|
||||
-- ATC is monitoring this flight.
|
||||
if self.ATC then
|
||||
if self.ATCswitch then
|
||||
RAT:_ATCAddFlight(group:GetName(), destination:GetName())
|
||||
end
|
||||
|
||||
@ -1245,23 +1269,28 @@ function RAT:_SetRoute(takeoff, _departure, _destination)
|
||||
-- DESTINATION AIRPORT
|
||||
local destination=nil
|
||||
if _destination then
|
||||
|
||||
if self:_AirportExists(_destination) then
|
||||
destination=AIRBASE:FindByName(_destination)
|
||||
else
|
||||
local text=string.format("ERROR: Specified destination airport %s does not exist for %s!", _destination, self.alias)
|
||||
env.error(RAT.id..text)
|
||||
end
|
||||
else
|
||||
-- Get all destination airports within reach.
|
||||
local destinations=self:_GetDestinations(Pdeparture, self.mindist, math.min(self.aircraft.Reff, self.maxdist))
|
||||
|
||||
local random_destination=false
|
||||
if self.continuejourney and _departure then
|
||||
random_destination=true
|
||||
else
|
||||
|
||||
-- This handes the case where we have a journey and the first flight is done, i.e. _departure is set.
|
||||
-- If a user specified more than two destination airport explicitly, then we will stick to this.
|
||||
-- Otherwise, the route is random from now on.
|
||||
if self.continuejourney and _departure and #self.destination_ports<3 then
|
||||
self.random_destination=true
|
||||
end
|
||||
|
||||
-- Get all destination airports within reach.
|
||||
local destinations=self:_GetDestinations(departure, Pdeparture, self.mindist, math.min(self.aircraft.Reff, self.maxdist))
|
||||
|
||||
-- Pick a destination airport.
|
||||
destination=self:_PickDestination(destinations, random_destination)
|
||||
destination=self:_PickDestination(destinations)
|
||||
end
|
||||
|
||||
-- Return nil if no departure could be found.
|
||||
@ -1477,7 +1506,7 @@ end
|
||||
-- @param #RAT self
|
||||
-- @param #number takeoff Takeoff type.
|
||||
-- @return Wrapper.Airbase#AIRBASE Departure airport if spawning at airport.
|
||||
-- @return Coore.Zone#ZONE Departure zone if spawning in air.
|
||||
-- @return Core.Zone#ZONE Departure zone if spawning in air.
|
||||
function RAT:_PickDeparture(takeoff)
|
||||
|
||||
-- Array of possible departure airports or zones.
|
||||
@ -1488,19 +1517,25 @@ function RAT:_PickDeparture(takeoff)
|
||||
if self.random_departure then
|
||||
|
||||
-- Air start above a random airport.
|
||||
for _,airport in pairs(self.airports)do
|
||||
table.insert(departures, airport:GetZone())
|
||||
for _,airport in pairs(self.airports) do
|
||||
if not self:_Excluded(airport:GetName()) then
|
||||
table.insert(departures, airport:GetZone())
|
||||
end
|
||||
end
|
||||
|
||||
else
|
||||
|
||||
-- Put all specified zones in table.
|
||||
for _,name in pairs(self.departure_zones) do
|
||||
table.insert(departures, ZONE:New(name))
|
||||
if not self:_Excluded(name) then
|
||||
table.insert(departures, ZONE:New(name))
|
||||
end
|
||||
end
|
||||
-- Put all specified airport zones in table.
|
||||
for _,name in pairs(self.departure_ports) do
|
||||
table.insert(departures, AIRBASE:FindByName(name):GetZone())
|
||||
if not self:_Excluded(name) then
|
||||
table.insert(departures, AIRBASE:FindByName(name):GetZone())
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@ -1511,14 +1546,18 @@ function RAT:_PickDeparture(takeoff)
|
||||
|
||||
-- All friendly departure airports.
|
||||
for _,airport in pairs(self.airports) do
|
||||
table.insert(departures, airport)
|
||||
if not self:_Excluded(airport:GetName()) then
|
||||
table.insert(departures, airport)
|
||||
end
|
||||
end
|
||||
|
||||
else
|
||||
|
||||
-- All airports specified by user
|
||||
for _,name in pairs(self.departure_ports) do
|
||||
table.insert(departures, AIRBASE:FindByName(name))
|
||||
if not self:_Excluded(name) then
|
||||
table.insert(departures, AIRBASE:FindByName(name))
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@ -1553,27 +1592,37 @@ end
|
||||
-- @return Wrapper.Airbase#AIRBASE Destination airport.
|
||||
function RAT:_PickDestination(destinations, _random)
|
||||
|
||||
--[[
|
||||
-- Take destinations from user input.
|
||||
if not (self.random_destination or _random) then
|
||||
|
||||
destinations=nil
|
||||
destinations={}
|
||||
|
||||
-- All airports specified by user.
|
||||
for _,name in pairs(self.destination_ports) do
|
||||
table.insert(destinations, AIRBASE:FindByName(name))
|
||||
if not self:_Excluded(name) then
|
||||
table.insert(destinations, AIRBASE:FindByName(name))
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
]]
|
||||
|
||||
-- Randomly select one possible destination.
|
||||
local destination=nil
|
||||
if destinations and #destinations>0 then
|
||||
|
||||
-- Random selection.
|
||||
destination=destinations[math.random(#destinations)] -- Wrapper.Airbase#AIRBASE
|
||||
|
||||
-- Debug message.
|
||||
local text="Chosen destination airport: "..destination:GetName().." (ID "..destination:GetID()..")"
|
||||
env.info(RAT.id..text)
|
||||
if self.debug then
|
||||
MESSAGE:New(text, 30):ToAll()
|
||||
end
|
||||
|
||||
else
|
||||
env.error(RAT.id.."No destination airport found.")
|
||||
end
|
||||
@ -1581,36 +1630,58 @@ function RAT:_PickDestination(destinations, _random)
|
||||
return destination
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Get all possible destination airports depending on departure position.
|
||||
-- The list is sorted w.r.t. distance to departure position.
|
||||
-- @param #RAT self
|
||||
-- @param Wrapper.Airbase#AIRBASE departure Departure airport or zone.
|
||||
-- @param Core.Point#COORDINATE q Coordinate of the departure point.
|
||||
-- @param #number minrange Minimum range to q in meters.
|
||||
-- @param #number maxrange Maximum range to q in meters.
|
||||
-- @return #table Table with possible destination airports.
|
||||
-- @return #nil If no airports could be found.
|
||||
function RAT:_GetDestinations(q, minrange, maxrange)
|
||||
function RAT:_GetDestinations(departure, q, minrange, maxrange)
|
||||
|
||||
-- Min/max range to destination.
|
||||
minrange=minrange or self.mindist
|
||||
maxrange=maxrange or self.maxdist
|
||||
|
||||
local possible_destinations={}
|
||||
if self.random_destination then
|
||||
|
||||
-- Initialize array.
|
||||
local destinations={}
|
||||
|
||||
-- loop over all friendly airports
|
||||
for _,airport in pairs(self.airports) do
|
||||
local p=airport:GetCoordinate()
|
||||
local distance=q:Get2DDistance(p)
|
||||
-- check if distance form departure to destination is within min/max range
|
||||
if distance>=minrange and distance<=maxrange then
|
||||
table.insert(destinations, airport)
|
||||
-- Airports of friendly coalitions.
|
||||
for _,airport in pairs(self.airports) do
|
||||
local name=airport:GetName()
|
||||
if self:_IsFriendly(name) and not self:_Excluded(name) and name~=departure:GetName() then
|
||||
|
||||
-- Distance from departure to possible destination
|
||||
local distance=q:Get2DDistance(airport:GetCoordinate())
|
||||
|
||||
-- Check if distance form departure to destination is within min/max range.
|
||||
if distance>=minrange and distance<=maxrange then
|
||||
table.insert(possible_destinations, airport)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
else
|
||||
|
||||
-- Airports specified by user.
|
||||
for _,name in pairs(self.destination_ports) do
|
||||
--if self:_IsFriendly(name) and not self:_Excluded(name) and name~=departure:GetName() then
|
||||
if name~=departure:GetName() then
|
||||
local airport=AIRBASE:FindByName(name)
|
||||
--TODO: Maybe here I should check min/max distance as well? But the user explicitly specified the airports...
|
||||
table.insert(possible_destinations, airport)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
env.info(RAT.id.."Number of possible destination airports = "..#destinations)
|
||||
|
||||
if #destinations > 1 then
|
||||
-- Info message.
|
||||
env.info(RAT.id.."Number of possible destination airports = "..#possible_destinations)
|
||||
|
||||
if #possible_destinations > 0 then
|
||||
--- Compare distance of destination airports.
|
||||
-- @param Core.Point#COORDINATE a Coordinate of point a.
|
||||
-- @param Core.Point#COORDINATE b Coordinate of point b.
|
||||
@ -1620,17 +1691,45 @@ function RAT:_GetDestinations(q, minrange, maxrange)
|
||||
local qb=q:Get2DDistance(b:GetCoordinate())
|
||||
return qa < qb
|
||||
end
|
||||
table.sort(destinations, compare)
|
||||
table.sort(possible_destinations, compare)
|
||||
else
|
||||
env.error(RAT.id.."No possible destination airports found!")
|
||||
destinations=nil
|
||||
possible_destinations=nil
|
||||
end
|
||||
|
||||
-- Return table with destination airports.
|
||||
return destinations
|
||||
return possible_destinations
|
||||
|
||||
end
|
||||
|
||||
--- Check if airport is excluded from possible departures and destinations.
|
||||
-- @param #RAT self
|
||||
-- @param #string port Name of airport, FARP or ship to check.
|
||||
-- @return #boolean true if airport is excluded and false otherwise.
|
||||
function RAT:_Excluded(port)
|
||||
for _,name in pairs(self.excluded_ports) do
|
||||
if name==port then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
--- Check if airport is friendly, i.e. belongs to the right coalition.
|
||||
-- @param #RAT self
|
||||
-- @param #string port Name of airport, FARP or ship to check.
|
||||
-- @return #boolean true if airport is friendly and false otherwise.
|
||||
function RAT:_IsFriendly(port)
|
||||
for _,airport in pairs(self.airports) do
|
||||
local name=airport:GetName()
|
||||
if name==port then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Get all airports of the current map.
|
||||
-- @param #RAT self
|
||||
@ -1674,7 +1773,6 @@ function RAT:_GetAirportsOfMap()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--- Get all "friendly" airports of the current map.
|
||||
-- @param #RAT self
|
||||
function RAT:_GetAirportsOfCoalition()
|
||||
@ -1801,8 +1899,19 @@ function RAT:Status(message, forID)
|
||||
local Hp=COORDINATE:New(self.ratcraft[i].waypoints[6].x, self.ratcraft[i].waypoints[6].alt, self.ratcraft[i].waypoints[6].y)
|
||||
local Dholding=Pn:Get2DDistance(Hp)
|
||||
|
||||
-- If distance to holding point is less then 10 km we register the plane
|
||||
if self.ATC and Dholding<10000 and self.ratcraft[i].status~="Holding" then
|
||||
-- Status shortcut.
|
||||
local status=self.ratcraft[i].status
|
||||
|
||||
-- Range from holding point
|
||||
local DRholding
|
||||
if self.category==RAT.cat.plane then
|
||||
DRholding=6000
|
||||
else
|
||||
DRholding=500
|
||||
end
|
||||
|
||||
-- If distance to holding point is less then 6 km we register the plane.
|
||||
if self.ATCswitch and Dholding<=DRholding and status=="On journey (after takeoff)" then
|
||||
RAT:_ATCRegisterFlight(group:GetName(), Tnow)
|
||||
self.ratcraft[i].status="Holding"
|
||||
end
|
||||
@ -1829,7 +1938,7 @@ function RAT:Status(message, forID)
|
||||
--text=text..string.format("Speed = %i km/h\n", vel)
|
||||
text=text..string.format("Distance travelled = %6.1f km\n", self.ratcraft[i]["Distance"]/1000)
|
||||
text=text..string.format("Distance to destination = %6.1f km\n", Ddestination/1000)
|
||||
if self.ATC then
|
||||
if self.ATCswitch then
|
||||
text=text..string.format("Distance to holding point = %6.1f km", Dholding/1000)
|
||||
end
|
||||
if not airborne then
|
||||
@ -1896,7 +2005,7 @@ end
|
||||
-- @param #RAT self
|
||||
function RAT:_SetStatus(group, status)
|
||||
local index=self:GetSpawnIndexFromGroup(group)
|
||||
env.info(RAT.id.."Index for group "..group:GetName().." "..index.." status: "..status)
|
||||
env.info(RAT.id.."Status for group "..group:GetName()..": "..status)
|
||||
self.ratcraft[index].status=status
|
||||
end
|
||||
|
||||
@ -2032,7 +2141,7 @@ function RAT:_OnLand(EventData)
|
||||
self:_SetStatus(SpawnGroup, "Taxiing (after landing)")
|
||||
|
||||
-- ATC plane landed. Take it out of the queue and set runway to free.
|
||||
if self.ATC then
|
||||
if self.ATCswitch then
|
||||
RAT:_ATCFlightLanded(SpawnGroup:GetName())
|
||||
end
|
||||
|
||||
@ -2137,6 +2246,8 @@ function RAT:_OnCrash(EventData)
|
||||
|
||||
local SpawnGroup = EventData.IniGroup --Wrapper.Group#GROUP
|
||||
|
||||
env.info(string.format("%sGroup %s crashed!", RAT.id, SpawnGroup:GetName()))
|
||||
|
||||
if SpawnGroup then
|
||||
|
||||
-- Get the template name of the group. This can be nil if this was not a spawned group.
|
||||
@ -2449,9 +2560,14 @@ function RAT:_TaskHolding(P1, Altitude, Speed, Duration)
|
||||
DCSTask.id="ControlledTask"
|
||||
DCSTask.params={}
|
||||
DCSTask.params.task=Task
|
||||
local userflagname=string.format("%s#%03d", self.alias, self.SpawnIndex+1)
|
||||
env.info("ATC setting user flag name to "..userflagname)
|
||||
DCSTask.params.stopCondition={userFlag=userflagname, userFlagValue=1, duration=6000}
|
||||
|
||||
if self.ATCswitch then
|
||||
-- Set stop condition for holding. Either flag=1 or after max. 30 min holding.
|
||||
local userflagname=string.format("%s#%03d", self.alias, self.SpawnIndex+1)
|
||||
DCSTask.params.stopCondition={userFlag=userflagname, userFlagValue=1, duration=1800}
|
||||
else
|
||||
DCSTask.params.stopCondition={duration=Duration}
|
||||
end
|
||||
|
||||
return DCSTask
|
||||
end
|
||||
@ -2551,17 +2667,7 @@ end
|
||||
-- @param #RAT self
|
||||
function RAT:_SetCoalitionTable()
|
||||
-- get all possible departures/destinations depending on coalition
|
||||
if self.friendly==RAT.coal.all then
|
||||
self.ctable={coalition.side.BLUE, coalition.side.RED, coalition.side.NEUTRAL}
|
||||
elseif self.friendly==RAT.coal.blue then
|
||||
self.ctable={coalition.side.BLUE, coalition.side.NEUTRAL}
|
||||
elseif self.friendly==RAT.coal.blueonly then
|
||||
self.ctable={coalition.side.BLUE}
|
||||
elseif self.friendly==RAT.coal.red then
|
||||
self.ctable={coalition.side.RED, coalition.side.NEUTRAL}
|
||||
elseif self.friendly==RAT.coal.redonly then
|
||||
self.ctable={coalition.side.RED}
|
||||
elseif self.friendly==RAT.coal.neutral then
|
||||
if self.friendly==RAT.coal.neutral then
|
||||
self.ctable={coalition.side.NEUTRAL}
|
||||
elseif self.friendly==RAT.coal.same then
|
||||
self.ctable={self.coalition, coalition.side.NEUTRAL}
|
||||
@ -2733,36 +2839,19 @@ function RAT:_SetMarker(text, wp)
|
||||
-- Convert to coordinate.
|
||||
local vec={x=wp.x, y=wp.alt, z=wp.y}
|
||||
-- Place maker visible for all on the F10 map.
|
||||
trigger.action.markToAll(RAT.markerid, text, vec)
|
||||
local text1=string.format("%s:\n%s", self.alias, text)
|
||||
trigger.action.markToAll(RAT.markerid, text1, vec)
|
||||
end
|
||||
|
||||
--- Delete all markers on F10 map.
|
||||
-- @param #RAT self
|
||||
function RAT:_DeleteMarkers()
|
||||
--self:E({"self ids before: ", self.markerids})
|
||||
for k,v in ipairs(self.markerids) do
|
||||
--env.info("Deleting marker id v= "..v)
|
||||
trigger.action.removeMark(v)
|
||||
end
|
||||
for k,v in ipairs(self.markerids) do
|
||||
--env.info("Removing marker k= "..k)
|
||||
self.markerids[k]=nil
|
||||
end
|
||||
--self:E({"self ids after: ", self.markerids})
|
||||
end
|
||||
|
||||
--- Utility function which checks if table contains a specific value.
|
||||
-- @param #RAT self
|
||||
-- @param #table tab Table with elements to check.
|
||||
-- @param #string val The value we are looking for.
|
||||
-- @return #boolean True if element in the list, false otherwise.
|
||||
function RAT:has_value (tab, val)
|
||||
for _,value in pairs(tab) do
|
||||
if value == val then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
@ -2817,6 +2906,12 @@ function RAT:_ModifySpawnTemplate(waypoints)
|
||||
-- Onboard number.
|
||||
SpawnTemplate.units[UnitID]["onboard_num"] = self.SpawnIndex
|
||||
|
||||
-- Modify coaltion and country of template.
|
||||
SpawnTemplate.CoalitionID=self.coalition
|
||||
if self.country then
|
||||
SpawnTemplate.CountryID=self.country
|
||||
end
|
||||
|
||||
-- Parking spot.
|
||||
UnitTemplate.parking = nil
|
||||
UnitTemplate.parking_id = nil
|
||||
@ -2853,7 +2948,7 @@ end
|
||||
-- @param #table airports_map List of all airports of the map.
|
||||
function RAT:_ATCInit(airports_map)
|
||||
if not RAT.ATC.init then
|
||||
env.info("Starting RAT ATC")
|
||||
env.info(RAT.id.."Starting RAT ATC.")
|
||||
RAT.ATC.init=true
|
||||
for _,ap in pairs(airports_map) do
|
||||
local name=ap:GetName()
|
||||
@ -2861,12 +2956,26 @@ function RAT:_ATCInit(airports_map)
|
||||
RAT.ATC.airport[name].queue={}
|
||||
RAT.ATC.airport[name].busy=false
|
||||
RAT.ATC.airport[name].onfinal=nil
|
||||
RAT.ATC.airport[name].traffic=0
|
||||
end
|
||||
SCHEDULER:New(nil, RAT._ATCCheck, {self}, 5, 60)
|
||||
SCHEDULER:New(nil, RAT._ATCStatus, {self}, 5, 120)
|
||||
SCHEDULER:New(nil, RAT._ATCCheck, {self}, 5, 15)
|
||||
SCHEDULER:New(nil, RAT._ATCStatus, {self}, 5, 60)
|
||||
RAT.ATC.T0=timer.getTime()
|
||||
end
|
||||
end
|
||||
|
||||
--- Adds andd initializes a new flight after it was spawned.
|
||||
-- @param #RAT self
|
||||
-- @param #string name Group name of the flight.
|
||||
-- @param #string dest Name of the destination airport.
|
||||
function RAT:_ATCAddFlight(name, dest)
|
||||
env.info(string.format("%s%s ATC: Adding flight %s with destination %s.", RAT.id, dest, name, dest))
|
||||
RAT.ATC.flight[name]={}
|
||||
RAT.ATC.flight[name].destination=dest
|
||||
RAT.ATC.flight[name].Tarrive=-1
|
||||
RAT.ATC.flight[name].holding=-1
|
||||
RAT.ATC.flight[name].Tonfinal=-1
|
||||
end
|
||||
|
||||
--- Deletes a flight from ATC lists after it landed.
|
||||
-- @param #RAT self
|
||||
@ -2880,47 +2989,113 @@ function RAT:_ATCDelFlight(t,entry)
|
||||
end
|
||||
end
|
||||
|
||||
--- Adds andd initializes a new flight after it was spawned.
|
||||
-- @param #RAT self
|
||||
-- @param #string name Group name of the flight.
|
||||
-- @param #string dest Name of the destination airport.
|
||||
function RAT:_ATCAddFlight(name, dest)
|
||||
env.info(string.format("ATC: Adding flight %s with destination %s.", name, dest))
|
||||
RAT.ATC.flight[name]={}
|
||||
RAT.ATC.flight[name].destination=dest
|
||||
RAT.ATC.flight[name].holding=-1
|
||||
end
|
||||
|
||||
--- Registers a flight once it is near its holding point at the final destination.
|
||||
-- @param #RAT self
|
||||
-- @param #string name Group name of the flight.
|
||||
-- @param #number time Time the fight first registered.
|
||||
function RAT:_ATCRegisterFlight(name, time)
|
||||
env.info("ATC: Reg name "..name)
|
||||
env.info("ATC: Reg time "..time)
|
||||
RAT.ATC.flight[name].Tarrive=time
|
||||
RAT.ATC.flight[name].holding=0
|
||||
end
|
||||
|
||||
--- Takes care of organisational stuff after a plane has landed.
|
||||
-- @param #RAT self
|
||||
-- @param #string name Group name of flight.
|
||||
function RAT:_ATCFlightLanded(name)
|
||||
|
||||
-- Destination airport.
|
||||
local dest=RAT.ATC.flight[name].destination
|
||||
--- ATC status report about flights.
|
||||
-- @param #RAT self
|
||||
function RAT:_ATCStatus()
|
||||
|
||||
-- Current time.
|
||||
local Tnow=timer.getTime()
|
||||
|
||||
for name,_ in pairs(RAT.ATC.flight) do
|
||||
|
||||
local hold=RAT.ATC.flight[name].holding
|
||||
local dest=RAT.ATC.flight[name].destination
|
||||
|
||||
if hold >= 0 then
|
||||
|
||||
-- Some string whether the runway is busy or not.
|
||||
local busy="Runway is currently clear"
|
||||
if RAT.ATC.airport[dest].busy then
|
||||
if RAT.ATC.airport[dest].onfinal then
|
||||
busy="Runway is occupied by "..RAT.ATC.airport[dest].onfinal
|
||||
else
|
||||
busy="Runway is occupied"
|
||||
end
|
||||
end
|
||||
|
||||
-- Aircraft is holding.
|
||||
env.info(string.format("%s%s ATC: Flight %s is holding for %i:%02d. %s.", RAT.id, dest, name, hold/60, hold%60, busy))
|
||||
|
||||
elseif hold==RAT.ATC.onfinal then
|
||||
|
||||
-- Aircarft is on final approach for landing.
|
||||
local Tfinal=Tnow-RAT.ATC.flight[name].Tonfinal
|
||||
env.info(string.format("%s%s ATC: Flight %s was cleared for landing. Waiting %i:%02d for landing event.", RAT.id, dest, name, Tfinal/60, Tfinal%60))
|
||||
|
||||
--TODO: Trigger landing for another aircraft when Tfinal > x min?
|
||||
-- After five minutes we set the runway to green. ==> Increase the landing frequency a bit.
|
||||
if Tfinal>300 then
|
||||
RAT.ATC.airport[dest].busy=false
|
||||
end
|
||||
|
||||
elseif hold==RAT.ATC.unregistered then
|
||||
|
||||
-- Aircraft has not arrived at holding point.
|
||||
--env.info(string.format("%s ATC: Flight %s is not registered yet (hold %d).", dest, name, hold))
|
||||
|
||||
else
|
||||
env.error(RAT.id.."Unknown holding time in RAT:_ATCStatus().")
|
||||
end
|
||||
end
|
||||
|
||||
-- Airport is not busy any more.
|
||||
RAT.ATC.airport[dest].busy=false
|
||||
end
|
||||
|
||||
--- Main ATC function. Updates the landing queue of all airports and inceases holding time for all flights.
|
||||
-- @param #RAT self
|
||||
function RAT:_ATCCheck()
|
||||
|
||||
-- Init queue of flights at all airports.
|
||||
RAT:_ATCQueue()
|
||||
|
||||
-- No aircraft on final any more.
|
||||
RAT.ATC.airport[dest].onfinal=nil
|
||||
-- Current time.
|
||||
local Tnow=timer.getTime()
|
||||
|
||||
-- Remove this flight from list of flights.
|
||||
RAT:_ATCDelFlight(RAT.ATC.flight, name)
|
||||
for name,_ in pairs(RAT.ATC.airport) do
|
||||
|
||||
-- Debug info
|
||||
env.info(string.format("ATC: Flight %s landed at %s.", name, dest))
|
||||
|
||||
-- List of flights cleared for landing.
|
||||
local qw={}
|
||||
|
||||
for qID,flight in ipairs(RAT.ATC.airport[name].queue) do
|
||||
|
||||
-- Number of aircraft in queue.
|
||||
local nqueue=#RAT.ATC.airport[name].queue
|
||||
|
||||
if RAT.ATC.airport[name].busy then
|
||||
|
||||
-- Update holding time.
|
||||
RAT.ATC.flight[flight].holding=Tnow-RAT.ATC.flight[flight].Tarrive
|
||||
|
||||
-- Debug message.
|
||||
local text=string.format("%s ATC: Flight %s runway is busy. You are #%d of %d in landing queue. Your holding time is %i:%02d.", name, flight,qID, nqueue, RAT.ATC.flight[flight].holding/60, RAT.ATC.flight[flight].holding%60)
|
||||
env.info(text)
|
||||
|
||||
else
|
||||
|
||||
-- Clear flight for landing.
|
||||
RAT:_ATCClearForLanding(name, flight)
|
||||
table.insert(qw, qID)
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- Remove cleared flights from queue.
|
||||
for _,i in pairs(qw) do
|
||||
table.remove(RAT.ATC.airport[name].queue, i)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
--- Giving landing clearance for aircraft by setting user flag.
|
||||
@ -2934,85 +3109,60 @@ function RAT:_ATCClearForLanding(airport, flight)
|
||||
RAT.ATC.airport[airport].busy=true
|
||||
-- Flight which is landing.
|
||||
RAT.ATC.airport[airport].onfinal=flight
|
||||
-- Current time.
|
||||
RAT.ATC.flight[flight].Tonfinal=timer.getTime()
|
||||
-- Set user flag to 1 ==> stop condition for holding.
|
||||
trigger.action.setUserFlag(flight, 1)
|
||||
--local flagvalue=trigger.misc.getUserFlag(flight)
|
||||
env.info(RAT.id.."ATC: Flight "..flight.."cleared for landing.")
|
||||
local flagvalue=trigger.misc.getUserFlag(flight)
|
||||
|
||||
-- Debug message.
|
||||
local text1=string.format("%s%s ATC: Flight %s cleared for final approach (flag=%d).", RAT.id, airport, flight, flagvalue)
|
||||
local text2=string.format("%s ATC: Flight %s you are cleared for landing.", airport, flight)
|
||||
env.info(text1)
|
||||
MESSAGE:New(text2, 10):ToAll()
|
||||
end
|
||||
|
||||
--- ATC status report about flights.
|
||||
--- Takes care of organisational stuff after a plane has landed.
|
||||
-- @param #RAT self
|
||||
function RAT:_ATCStatus()
|
||||
|
||||
for name,_ in pairs(RAT.ATC.flight) do
|
||||
-- @param #string name Group name of flight.
|
||||
function RAT:_ATCFlightLanded(name)
|
||||
|
||||
local hold=RAT.ATC.flight[name].holding
|
||||
if RAT.ATC.flight[name] then
|
||||
|
||||
-- Destination airport.
|
||||
local dest=RAT.ATC.flight[name].destination
|
||||
|
||||
if hold >= 0 then
|
||||
-- Some string whether the runway is busy or not.
|
||||
local busy="free"
|
||||
if RAT.ATC.airport[dest].busy then
|
||||
busy="busy"
|
||||
end
|
||||
-- Aircraft is holding.
|
||||
env.info(string.format("%s ATC: Flight %s is holding for %d (runway is %s).",dest, name, hold, busy))
|
||||
elseif hold==RAT.ATC.onfinal then
|
||||
-- Aircarft is on final approach for landing.
|
||||
env.info(string.format("%s ATC: Flight %s was cleared for landing. Waiting for landing event.", dest, name))
|
||||
elseif hold==RAT.ATC.unregistered then
|
||||
-- Aircraft has not arrived at holding point.
|
||||
env.info(string.format("%s ATC: Flight %s is not registered yet (hold %d).", dest, name,hold))
|
||||
else
|
||||
env.info("Unknown holding time.")
|
||||
end
|
||||
-- Times for holding and final approach.
|
||||
local Tnow=timer.getTime()
|
||||
local Tfinal=Tnow-RAT.ATC.flight[name].Tonfinal
|
||||
local Thold=RAT.ATC.flight[name].Tonfinal-RAT.ATC.flight[name].Tarrive
|
||||
|
||||
-- Airport is not busy any more.
|
||||
RAT.ATC.airport[dest].busy=false
|
||||
|
||||
-- No aircraft on final any more.
|
||||
RAT.ATC.airport[dest].onfinal=nil
|
||||
|
||||
-- Remove this flight from list of flights.
|
||||
RAT:_ATCDelFlight(RAT.ATC.flight, name)
|
||||
|
||||
-- Increase landing counter to monitor traffic.
|
||||
RAT.ATC.airport[dest].traffic=RAT.ATC.airport[dest].traffic+1
|
||||
|
||||
-- Debug info
|
||||
local text1=string.format("%s%s ATC: Flight %s landed. Tholding = %i:%02d, Tfinal = %i:%02d.", RAT.id, dest, name, Thold/60, Thold%60, Tfinal/60, Tfinal%60)
|
||||
local text2=string.format("%s ATC: Flight %s landed. Welcome to %s.", dest, name, dest)
|
||||
env.info(text1)
|
||||
env.info(string.format("%s%s ATC: Number of planes landed in total %d.", RAT.id, dest, RAT.ATC.airport[dest].traffic))
|
||||
MESSAGE:New(text2, 10):ToAll()
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- Main ATC function. Updates the landing queue of all airports and inceases holding time for all flights.
|
||||
-- @param #RAT self
|
||||
function RAT:_ATCCheck()
|
||||
|
||||
-- Init queue of flights at all airports.
|
||||
RAT:_ATCQueue()
|
||||
|
||||
local Tnow=timer.getTime()
|
||||
|
||||
for name,_ in pairs(RAT.ATC.airport) do
|
||||
|
||||
-- List of finished flights
|
||||
local qw={}
|
||||
|
||||
for qID,flight in ipairs(RAT.ATC.airport[name].queue) do
|
||||
|
||||
-- Number of aircraft in queue.
|
||||
local nqueue=#RAT.ATC.airport[name].queue
|
||||
|
||||
if RAT.ATC.airport[name].busy then
|
||||
--env.info(string.format("%s ATC: Flight %s runway is busy. You are #%d of %d in landing queue.", name, flight,qID, nqueue))
|
||||
RAT.ATC.flight[flight].holding=Tnow-RAT.ATC.flight[flight].Tarrive
|
||||
else
|
||||
--env.info(string.format("%s ATC: Flight %s you are cleared for landing.", name, flight,qID))
|
||||
-- Clear flight for landing
|
||||
RAT:_ATCClearForLanding(name, flight)
|
||||
table.insert(qw, qID)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- Remove flight from queue.
|
||||
for _,i in pairs(qw) do
|
||||
table.remove(RAT.ATC.airport[name].queue, i)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
--- Creates a landing queue for all flights holding at airports. Aircraft with longest holding time gets first permission to land.
|
||||
-- @param #RAT self
|
||||
function RAT:_ATCQueue()
|
||||
--env.info("Queue:")
|
||||
|
||||
for airport,_ in pairs(RAT.ATC.airport) do
|
||||
|
||||
-- Local airport queue.
|
||||
@ -3042,7 +3192,7 @@ function RAT:_ATCQueue()
|
||||
table.insert(RAT.ATC.airport[airport].queue, v[1])
|
||||
end
|
||||
|
||||
--env.info(airport, dump(RAT.ATC.airport[airport].queue))
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
@ -1,5 +1,5 @@
|
||||
env.info( '*** MOOSE DYNAMIC INCLUDE START *** ' )
|
||||
env.info( 'Moose Generation Timestamp: 20170920_1942' )
|
||||
env.info( 'Moose Generation Timestamp: 20170924_1034' )
|
||||
|
||||
local base = _G
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user