mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-10-29 16:58:06 +00:00
RAT improvements.
This commit is contained in:
parent
e41b038730
commit
3b3017aa1d
@ -80,7 +80,8 @@
|
||||
-- @field #number AlphaDescent Default angle of descenti in degrees. A value of 3.6 follows the 3:1 rule of 3 miles of travel and 1000 ft descent.
|
||||
-- @field #string roe ROE of spawned groups, default is weapon hold (this is a peaceful class for civil aircraft or ferry missions). Possible: "hold", "return", "free".
|
||||
-- @field #string rot ROT of spawned groups, default is no reaction. Possible: "noreaction", "passive", "evade".
|
||||
-- @field #string takeoff Takeoff type. 0=coldorhot.
|
||||
-- @field #number takeoff Takeoff type. 0=coldorhot.
|
||||
-- @field #number landing Landing type. Determines if we actually land at an airport or treat it as zone.
|
||||
-- @field #number mindist Min distance from departure to destination in meters. Default 5 km.
|
||||
-- @field #number maxdist Max distance from departure to destination in meters. Default 5000 km.
|
||||
-- @field #table airports_map All airports available on current map (Caucasus, Nevada, Normandy, ...).
|
||||
@ -286,7 +287,7 @@ RAT={
|
||||
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.
|
||||
friendly = "same", -- Possible departure/destination airport: same=spawn+neutral, spawnonly=spawn, blue=blue+neutral, blueonly=blue, red=red+neutral, redonly=red, neutral.
|
||||
ctable = {}, -- Table with the valid coalitons from choice self.friendly.
|
||||
aircraft = {}, -- Table which holds the basic aircraft properties (speed, range, ...).
|
||||
Vcruisemax=nil, -- Max cruise speed in set by user.
|
||||
@ -295,6 +296,7 @@ RAT={
|
||||
roe = "hold", -- ROE of spawned groups, default is weapon hold (this is a peaceful class for civil aircraft or ferry missions). Possible: "hold", "return", "free".
|
||||
rot = "noreaction", -- ROT of spawned groups, default is no reaction. Possible: "noreaction", "passive", "evade".
|
||||
takeoff = 0, -- Takeoff type. 0=coldorhot.
|
||||
landing = 9, -- Landing type. 9=landing.
|
||||
mindist = 5000, -- Min distance from departure to destination in meters. Default 5 km.
|
||||
maxdist = 500000, -- Max distance from departure to destination in meters. Default 5000 km.
|
||||
airports_map={}, -- All airports available on current map (Caucasus, Nevada, Normandy, ...).
|
||||
@ -386,12 +388,12 @@ RAT.status={
|
||||
Destination="Arrived at destination",
|
||||
-- Event states.
|
||||
EventBirthAir="Born in air",
|
||||
EventBirth="Born on ground",
|
||||
EventBirth="Ready and starting engines",
|
||||
EventEngineStartAir="Started engines (in air)",
|
||||
EventEngineStart="Started engines",
|
||||
EventTakeoff="Took off",
|
||||
EventLand="Landed",
|
||||
EventEngineShutdown="Engines shut down",
|
||||
EventEngineStart="Started engines and taxiing",
|
||||
EventTakeoff="Airborn after take-off",
|
||||
EventLand="Landed and taxiing",
|
||||
EventEngineShutdown="Engines off",
|
||||
EventDead="Dead",
|
||||
EventCrash="Crashed",
|
||||
}
|
||||
@ -547,7 +549,7 @@ function RAT:Spawn(naircraft)
|
||||
env.error("Spawn function should only be called once per RAT object! Exiting and returning nil.")
|
||||
return nil
|
||||
else
|
||||
self.spawninitialized=false
|
||||
self.spawninitialized=true
|
||||
end
|
||||
|
||||
-- Number of aircraft to spawn. Default is one.
|
||||
@ -591,23 +593,24 @@ function RAT:Spawn(naircraft)
|
||||
env.error(RAT.id.."Destination zone _and_ return to zone not possible! Disabling return to zone.")
|
||||
self.returnzone=false
|
||||
end
|
||||
-- Return zone should not be used together with air start. Why actually?
|
||||
-- If returning to a zone, we set the landing type to the takeoff type. Default landing is ground.
|
||||
-- But if we start in air we want to end in air.
|
||||
if self.returnzone and self.takeoff==RAT.wp.air then
|
||||
env.error(RAT.id.."Combination return zone _and_ air start not possible! Falling back to destination zone instead.")
|
||||
self.returnzone=false
|
||||
self.destinationzone=true
|
||||
self.landing=self.takeoff
|
||||
end
|
||||
-- Return zone and commute does not make sense.
|
||||
-- Return zone and commute does not make sense.
|
||||
-- TODO: Actually it makes sense if the departure airport should stay the same.
|
||||
-- We could achive the same by setting only one departure or destination but this is generally not the case!
|
||||
if self.returnzone and self.continuejourney then
|
||||
env.error(RAT.id.."Combination return zone _and_ commute does not make sense! Disabling commute.")
|
||||
self.commute=false
|
||||
--env.error(RAT.id.."Combination return zone _and_ commute does not make sense! Disabling commute.")
|
||||
--self.commute=false
|
||||
end
|
||||
|
||||
-- Return zone and commute does not make sense.
|
||||
-- if self.returnzone and self.commute then
|
||||
if self.returnzone and self.commute then
|
||||
-- env.error(RAT.id.."Combination return zone _and_ commute does not make sense! Disabling commute.")
|
||||
-- self.commute=false
|
||||
-- end
|
||||
end
|
||||
|
||||
|
||||
-- Settings info
|
||||
@ -621,6 +624,7 @@ function RAT:Spawn(naircraft)
|
||||
text=text..string.format("Min dist to destination: %4.1f\n", self.mindist)
|
||||
text=text..string.format("Max dist to destination: %4.1f\n", self.maxdist)
|
||||
text=text..string.format("Takeoff type: %i\n", self.takeoff)
|
||||
text=text..string.format("Landing type: %i\n", self.landing)
|
||||
text=text..string.format("Commute: %s\n", tostring(self.commute))
|
||||
text=text..string.format("Journey: %s\n", tostring(self.continuejourney))
|
||||
text=text..string.format("Destination Zone: %s\n", tostring(self.destinationzone))
|
||||
@ -757,173 +761,108 @@ end
|
||||
|
||||
--- Set possible departure ports. This can be an airport or a zone defined in the mission editor.
|
||||
-- @param #RAT self
|
||||
-- @param #string names Name or table of names of departure airports or zones.
|
||||
-- @param #string departurenames Name or table of names of departure airports or zones.
|
||||
-- @usage RAT:SetDeparture("Sochi-Adler") will spawn RAT objects at Sochi-Adler airport.
|
||||
-- @usage RAT:SetDeparture({"Sochi-Adler", "Gudauta"}) will spawn RAT aircraft radomly at Sochi-Adler or Gudauta airport.
|
||||
-- @usage RAT:SetDeparture({"Zone A", "Gudauta"}) will spawn RAT aircraft in air randomly within Zone A, which has to be defined in the mission editor, or within a zone around Gudauta airport. Note that this also requires RAT:takeoff("air") to be set.
|
||||
function RAT:SetDeparture(names)
|
||||
function RAT:SetDeparture(departurenames)
|
||||
|
||||
-- Random departure is deactivated now that user specified departure ports.
|
||||
self.random_departure=false
|
||||
|
||||
if type(names)=="table" then
|
||||
|
||||
-- we did get a table of names
|
||||
for _,name in pairs(names) do
|
||||
|
||||
if self:_AirportExists(name) then
|
||||
-- If an airport with this name exists, we put it in the ports array.
|
||||
table.insert(self.departure_ports, name)
|
||||
else
|
||||
-- If it is not an airport, we assume it is a zone.
|
||||
-- We need the DCS call to determine if it's really a zone. Otherwise code will crash at some point.
|
||||
local z=trigger.misc.getZone(name)
|
||||
if z then
|
||||
table.insert(self.departure_zones, name)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
elseif type(names)=="string" then
|
||||
|
||||
if self:_AirportExists(names) then
|
||||
-- If an airport with this name exists, we put it in the ports array.
|
||||
table.insert(self.departure_ports, names)
|
||||
else
|
||||
-- If it is not an airport, we assume it is a zone.
|
||||
table.insert(self.departure_zones, names)
|
||||
end
|
||||
|
||||
-- Convert input to table.
|
||||
local names
|
||||
if type(departurenames)=="table" then
|
||||
names=departurenames
|
||||
elseif type(departurenames)=="string" then
|
||||
names={departurenames}
|
||||
else
|
||||
-- error message
|
||||
env.error("Input parameter must be a string or a table!")
|
||||
end
|
||||
|
||||
-- Put names into arrays.
|
||||
for _,name in pairs(names) do
|
||||
|
||||
if self:_AirportExists(name) then
|
||||
-- If an airport with this name exists, we put it in the ports array.
|
||||
table.insert(self.departure_ports, name)
|
||||
elseif self:_ZoneExists(name) then
|
||||
-- If it is not an airport, we assume it is a zone.
|
||||
table.insert(self.departure_zones, name)
|
||||
else
|
||||
env.error(RAT.id.."ERROR! No departure airport or zone found with name "..name)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- Set name of destination airport for the AI aircraft. If no name is given an airport from the friendly coalition(s) is chosen randomly.
|
||||
--- Set name of destination airports or zones for the AI aircraft.
|
||||
-- @param #RAT self
|
||||
-- @param #string names Name of the destination airport or table of destination airports.
|
||||
-- @param #string destinationnames Name of the destination airport or table of destination airports.
|
||||
-- @usage RAT:SetDestination("Krymsk") makes all aircraft of this RAT oject fly to Krymsk airport.
|
||||
function RAT:SetDestination(names)
|
||||
function RAT:SetDestination(destinationnames)
|
||||
|
||||
-- Random departure is deactivated now that user specified departure ports.
|
||||
self.random_destination=false
|
||||
|
||||
if type(names)=="table" then
|
||||
|
||||
for _,name in pairs(names) do
|
||||
if self:_AirportExists(name) then
|
||||
table.insert(self.destination_ports, name)
|
||||
else
|
||||
local text=string.format("Airport %s does not exist on map!", name)
|
||||
env.error(text)
|
||||
end
|
||||
end
|
||||
|
||||
elseif type(names)=="string" then
|
||||
|
||||
if self:_AirportExists(names) then
|
||||
self.destination_ports={names}
|
||||
else
|
||||
local text=string.format("Airport %s does not exist on map!", names)
|
||||
env.error(text)
|
||||
end
|
||||
|
||||
-- Convert input to table
|
||||
local names
|
||||
if type(destinationnames)=="table" then
|
||||
names=destinationnames
|
||||
elseif type(destinationnames)=="string" then
|
||||
names={destinationnames}
|
||||
else
|
||||
-- Error message.
|
||||
env.error("Input parameter must be a string or a table!")
|
||||
end
|
||||
|
||||
-- Put names into arrays.
|
||||
for _,name in pairs(names) do
|
||||
|
||||
if self:_AirportExists(name) then
|
||||
-- If an airport with this name exists, we put it in the ports array.
|
||||
table.insert(self.destination_ports, name)
|
||||
elseif self:_ZoneExists(name) then
|
||||
-- If it is not an airport, we assume it is a zone.
|
||||
table.insert(self.destination_ports, name)
|
||||
else
|
||||
env.error(RAT.id.."ERROR! No destination airport or zone found with name "..name)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- Set name of destination zones for the AI aircraft. If multiple names are given as a table, one zone is picked randomly as destination.
|
||||
--- Destinations are treated as zones. Aircraft will not land but rather be despawned when they reach a random point in the zone.
|
||||
-- @param #RAT self
|
||||
-- @param #string zonenames Name or table of names of zones defined in the mission editor or names of airports on the map.
|
||||
function RAT:SetDestinationZone(zonenames)
|
||||
function RAT:DestinationZone()
|
||||
|
||||
-- Random destination is deactivated now that user specified destination zone(s).
|
||||
self.random_destination=false
|
||||
|
||||
-- Destination is a zone. Needs special care.
|
||||
self.destinationzone=true
|
||||
|
||||
-- Landing type is "air" because we don't actually land at the airport
|
||||
self.landing=RAT.wp.air
|
||||
|
||||
-- No ATC required.
|
||||
self.ATCswitch=false
|
||||
|
||||
local names
|
||||
if type(zonenames)=="table" then
|
||||
names=zonenames
|
||||
elseif type(zonenames)=="string" then
|
||||
names={zonenames}
|
||||
else
|
||||
-- Error message.
|
||||
env.error("Input parameter must be a string or a table!")
|
||||
end
|
||||
|
||||
for _,name in pairs(names) do
|
||||
if self:_AirportExists(name) then
|
||||
-- Take airport as zone.
|
||||
local airportzone=AIRBASE:FindByName(name):GetZone()
|
||||
table.insert(self.destination_zones, airportzone)
|
||||
else
|
||||
-- If it is not an airport, we assume it is a zone.
|
||||
-- We need the DCS call to determine if it's really a zone. Otherwise code will crash at some point.
|
||||
local z=trigger.misc.getZone(name)
|
||||
if z then
|
||||
table.insert(self.destination_zones, ZONE:New(name))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- Set name of "return" zones for the AI aircraft. If multiple names are given as a table, one zone is picked randomly as destination.
|
||||
--- Aircraft will fly to a random point within a zone and then return to its departure airport or zone.
|
||||
-- @param #RAT self
|
||||
-- @param #string zonenames Name or table of names of zones defined in the mission editor.
|
||||
function RAT:SetReturnZone(zonenames)
|
||||
function RAT:ReturnZone()
|
||||
|
||||
-- Random destination is deactivated now that user specified destination zone(s).
|
||||
self.random_destination=false
|
||||
|
||||
-- Destination is a zone. Needs special care.
|
||||
self.returnzone=true
|
||||
|
||||
--[[
|
||||
if type(names)=="table" then
|
||||
|
||||
for _,name in pairs(names) do
|
||||
table.insert(self.destination_zones, ZONE:New(name))
|
||||
end
|
||||
|
||||
elseif type(names)=="string" then
|
||||
|
||||
table.insert(self.destination_zones, ZONE:New(names))
|
||||
|
||||
else
|
||||
-- Error message.
|
||||
env.error("Input parameter must be a string or a table!")
|
||||
end
|
||||
]]
|
||||
|
||||
local names
|
||||
if type(zonenames)=="table" then
|
||||
names=zonenames
|
||||
elseif type(zonenames)=="string" then
|
||||
names={zonenames}
|
||||
else
|
||||
-- Error message.
|
||||
env.error("Input parameter must be a string or a table!")
|
||||
end
|
||||
|
||||
for _,name in pairs(names) do
|
||||
if self:_AirportExists(name) then
|
||||
table.insert(self.destination_zones, AIRBASE:FindByName(name):GetZone())
|
||||
elseif self:_ZoneExists(name) then
|
||||
table.insert(self.destination_zones, ZONE:New(name))
|
||||
else
|
||||
env.error(RAT.id.."Specified airport or zone "..name.." does not exist in mission editor!")
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
@ -1331,20 +1270,28 @@ end
|
||||
-- @param #string _departure (Optional) Name of departure airbase.
|
||||
-- @param #string _destination (Optional) Name of destination airbase.
|
||||
-- @param #number _takeoff Takeoff type id.
|
||||
function RAT:_SpawnWithRoute(_departure, _destination, _takeoff)
|
||||
function RAT:_SpawnWithRoute(_departure, _destination, _takeoff, _landing)
|
||||
|
||||
-- Set takeoff type.
|
||||
local takeoff=self.takeoff
|
||||
local landing=self.landing
|
||||
|
||||
-- Random choice between cold and hot.
|
||||
if self.takeoff==RAT.wp.coldorhot then
|
||||
local temp={RAT.wp.cold, RAT.wp.hot}
|
||||
takeoff=temp[math.random(2)]
|
||||
end
|
||||
|
||||
-- Overrule takeoff/landing by what comes in.
|
||||
if _takeoff then
|
||||
takeoff=_takeoff
|
||||
end
|
||||
if _landing then
|
||||
landing=_landing
|
||||
end
|
||||
|
||||
-- Set flight plan.
|
||||
local departure, destination, waypoints = self:_SetRoute(takeoff, _departure, _destination)
|
||||
local departure, destination, waypoints = self:_SetRoute(takeoff, landing, _departure, _destination)
|
||||
|
||||
-- Return nil if we could not find a departure destination or waypoints
|
||||
if not (departure and destination and waypoints) then
|
||||
@ -1358,9 +1305,13 @@ function RAT:_SpawnWithRoute(_departure, _destination, _takeoff)
|
||||
local group=self:SpawnWithIndex(self.SpawnIndex) -- Wrapper.Group#GROUP
|
||||
self.alive=self.alive+1
|
||||
|
||||
-- ATC is monitoring this flight.
|
||||
if self.ATCswitch then
|
||||
RAT:_ATCAddFlight(group:GetName(), destination:GetName())
|
||||
-- ATC is monitoring this flight (if it supposed to land).
|
||||
if self.ATCswitch and landing==RAT.wp.landing then
|
||||
if self.returnzone then
|
||||
RAT:_ATCAddFlight(group:GetName(), departure:GetName())
|
||||
else
|
||||
RAT:_ATCAddFlight(group:GetName(), destination:GetName())
|
||||
end
|
||||
end
|
||||
|
||||
-- Set ROE, default is "weapon hold".
|
||||
@ -1392,8 +1343,11 @@ function RAT:_SpawnWithRoute(_departure, _destination, _takeoff)
|
||||
self.ratcraft[self.SpawnIndex]["Pnow"]=group:GetCoordinate()
|
||||
self.ratcraft[self.SpawnIndex]["Distance"]=0
|
||||
|
||||
-- Each aircraft gets its own takeoff type. unused?
|
||||
self.ratcraft[self.SpawnIndex]["takeoff"]=_takeoff
|
||||
-- Each aircraft gets its own takeoff type.
|
||||
self.ratcraft[self.SpawnIndex].takeoff=takeoff
|
||||
self.ratcraft[self.SpawnIndex].landing=landing
|
||||
|
||||
-- If this switch is set to true, the aircraft will be despawned the next time the status function is called.
|
||||
self.ratcraft[self.SpawnIndex].despawnme=false
|
||||
|
||||
|
||||
@ -1443,28 +1397,97 @@ function RAT:_Respawn(group)
|
||||
-- Get departure and destination from previous journey.
|
||||
local departure=self.ratcraft[index].departure
|
||||
local destination=self.ratcraft[index].destination
|
||||
local takeoff=self.ratcraft[index].takeoff
|
||||
local landing=self.ratcraft[index].landing
|
||||
|
||||
local _departure=nil
|
||||
local _destination=nil
|
||||
local _takeoff=nil
|
||||
local _landing=nil
|
||||
|
||||
if self.continuejourney then
|
||||
|
||||
-- We continue our journey from the old departure airport.
|
||||
_departure=destination:GetName()
|
||||
|
||||
if self.destinationzone then
|
||||
|
||||
-- Case: X --> Zone --> Zone --> Zone
|
||||
_takeoff=RAT.wp.air
|
||||
|
||||
-- We should also take case that the destination is set correctly
|
||||
|
||||
elseif self.returnzone then
|
||||
|
||||
-- Case: X --> Zone --> X, X --> Zone --> X
|
||||
-- We flew to a zone and back. Takeoff type does not
|
||||
_takeoff=self.takeoff
|
||||
_landing=self.takeoff
|
||||
|
||||
-- Departure stays the same.
|
||||
_departure=departure:GetName()
|
||||
|
||||
else
|
||||
|
||||
_takeoff=self.takeoff
|
||||
_landing=self.landing
|
||||
|
||||
end
|
||||
|
||||
elseif self.commute then
|
||||
|
||||
-- We commute between departure and destination.
|
||||
_departure=destination:GetName()
|
||||
_destination=departure:GetName()
|
||||
end
|
||||
|
||||
-- Handle takeoff type.
|
||||
if self.destinationzone then
|
||||
-- self.takeoff is either RAT.wp.air or RAT.wp.cold
|
||||
-- self.landing is RAT.wp.Air
|
||||
|
||||
if self.takeoff==RAT.wp.air then
|
||||
|
||||
-- Case: Zone <--> Zone (both have takeoff air)
|
||||
_takeoff=RAT.wp.air -- = self.takeoff
|
||||
_landing=RAT.wp.air -- = self.landing
|
||||
|
||||
else
|
||||
|
||||
-- Case: Airport <--> Zone
|
||||
if takeoff==RAT.wp.air then
|
||||
-- Last takeoff was air so we are at the airport now, takeoff is from ground.
|
||||
_takeoff=self.takeoff -- must be either hot/cold/runway/hotcold
|
||||
_landing=self.landing -- must be air
|
||||
else
|
||||
-- Last takeoff was on ground so we are at a zone now ==> takeoff in air, landing at zone.
|
||||
_takeoff=RAT.wp.air
|
||||
_landing=RAT.wp.landing
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
elseif self.returnzone then
|
||||
|
||||
-- We flew to a zone and back. No need to swap departure and destination.
|
||||
_departure=departure:GetName()
|
||||
_destination=destination:GetName()
|
||||
|
||||
-- Takeoff and landing should also not change.
|
||||
_takeoff=self.takeoff
|
||||
_landing=self.landing
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
env.info(RAT.id..string.format("self.takeoff, takeoff, _takeoff = %d, %d, %d", self.takeoff, takeoff, _takeoff))
|
||||
env.info(RAT.id..string.format("self.landing, landing, _landing = %d, %d, %d", self.landing, landing, _landing))
|
||||
|
||||
-- Spawn new group.
|
||||
if self.respawn_delay then
|
||||
SCHEDULER:New(nil, self._SpawnWithRoute, {self, _departure, _destination, _takeoff}, self.respawn_delay)
|
||||
SCHEDULER:New(nil, self._SpawnWithRoute, {self, _departure, _destination, _takeoff, _landing}, self.respawn_delay)
|
||||
else
|
||||
self:_SpawnWithRoute(_departure, _destination, _takeoff)
|
||||
self:_SpawnWithRoute(_departure, _destination, _takeoff, _landing)
|
||||
end
|
||||
|
||||
end
|
||||
@ -1473,14 +1496,15 @@ end
|
||||
|
||||
--- Set the route of the AI plane. Due to DCS landing bug, this has to be done before the unit is spawned.
|
||||
-- @param #RAT self
|
||||
-- @param takeoff #RAT.wp Takeoff type.
|
||||
-- @param takeoff #RAT.wp Takeoff type. Could also be air start.
|
||||
-- @param landing #RAT.wp Landing type. Could also be a destination in air.
|
||||
-- @param Wrapper.Airport#AIRBASE _departure (Optional) Departure airbase.
|
||||
-- @param Wrapper.Airport#AIRBASE _destination (Optional) Destination airbase.
|
||||
-- @return Wrapper.Airport#AIRBASE Departure airbase.
|
||||
-- @return Wrapper.Airport#AIRBASE Destination airbase.
|
||||
-- @return #table Table of flight plan waypoints.
|
||||
-- @return #nil If no valid departure or destination airport could be found.
|
||||
function RAT:_SetRoute(takeoff, _departure, _destination)
|
||||
function RAT:_SetRoute(takeoff, landing, _departure, _destination)
|
||||
|
||||
-- Max cruise speed.
|
||||
local VxCruiseMax
|
||||
@ -1531,36 +1555,17 @@ function RAT:_SetRoute(takeoff, _departure, _destination)
|
||||
if self:_AirportExists(_departure) then
|
||||
-- Check if new departure is an airport.
|
||||
departure=AIRBASE:FindByName(_departure)
|
||||
-- If we spawn in air, we convert departure to a zone.
|
||||
if takeoff == RAT.wp.air then
|
||||
departure=departure:GetZone()
|
||||
end
|
||||
elseif self:_ZoneExists(_departure) then
|
||||
-- If it's not an airport, check whether it's a zone.
|
||||
departure=ZONE:New(_departure)
|
||||
else
|
||||
local text=string.format("ERROR: Specified departure airport %s does not exist for %s!", _departure, self.alias)
|
||||
env.error(RAT.id..text)
|
||||
end
|
||||
|
||||
if self.commute then
|
||||
if returnzone then
|
||||
-- should not be a problem because we flew back to the departure. Departure=destination ==> nothing really changes.
|
||||
-- Just that the next departure is not random but the same airport we started first.
|
||||
elseif destinationzone then
|
||||
-- We initially flew to a zone.
|
||||
if self.takeoff==RAT.wp.air then
|
||||
-- We initially came from a zone, i.e. airstart.
|
||||
if takeoff==RAT.wp.air then
|
||||
-- Now we also fly to zone.
|
||||
else
|
||||
-- Now we fly to an airport where we land
|
||||
end
|
||||
else
|
||||
-- We initally
|
||||
end
|
||||
end
|
||||
elseif self.continuejourney then
|
||||
|
||||
departure=departure:GetZone()
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
else
|
||||
departure=self:_PickDeparture(takeoff)
|
||||
@ -1611,15 +1616,14 @@ function RAT:_SetRoute(takeoff, _departure, _destination)
|
||||
if _destination then
|
||||
|
||||
if self:_AirportExists(_destination) then
|
||||
|
||||
destination=AIRBASE:FindByName(_destination)
|
||||
if self.destinationzone then
|
||||
if landing==RAT.wp.air or self.returnzone then
|
||||
destination=destination:GetZone()
|
||||
end
|
||||
|
||||
elseif self:_ZoneExists(_destination) then
|
||||
destination=ZONE:New(_destination)
|
||||
if not self.returnzone then
|
||||
self.destinationzone=true
|
||||
end
|
||||
else
|
||||
local text=string.format("ERROR: Specified destination airport/zone %s does not exist for %s!", _destination, self.alias)
|
||||
env.error(RAT.id..text)
|
||||
@ -1627,15 +1631,24 @@ function RAT:_SetRoute(takeoff, _departure, _destination)
|
||||
|
||||
else
|
||||
|
||||
-- This handes the case where we have a journey and the first flight is done, i.e. _departure is set.
|
||||
-- This handles 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.
|
||||
local random=self.random_destination
|
||||
if self.continuejourney and _departure and #self.destination_ports<3 then
|
||||
self.random_destination=true
|
||||
random=true
|
||||
end
|
||||
|
||||
-- In case of a returnzone the destination (i.e. return point) is always a zone.
|
||||
local mylanding
|
||||
if self.returnzone then
|
||||
mylanding=RAT.wp.air
|
||||
else
|
||||
mylanding=landing
|
||||
end
|
||||
|
||||
-- Get all destination airports within reach.
|
||||
local destinations=self:_GetDestinations(departure, Pdeparture, self.mindist, math.min(self.aircraft.Reff, self.maxdist))
|
||||
local destinations=self:_GetDestinations(departure, Pdeparture, self.mindist, math.min(self.aircraft.Reff, self.maxdist), random, mylanding)
|
||||
|
||||
-- Pick a destination airport.
|
||||
destination=self:_PickDestination(destinations)
|
||||
@ -1651,11 +1664,12 @@ function RAT:_SetRoute(takeoff, _departure, _destination)
|
||||
|
||||
-- Check that departure and destination are not the same. Should not happen due to mindist.
|
||||
if destination:GetName()==departure:GetName() then
|
||||
local text=string.format("%s: Destination and departure airport are identical. Airport %s.", self.alias, destination:GetName())
|
||||
local text=string.format("%s: Destination and departure are identical. Airport/zone %s.", self.alias, destination:GetName())
|
||||
MESSAGE:New(text, 30):ToAll()
|
||||
env.error(RAT.id..text)
|
||||
end
|
||||
|
||||
--[[
|
||||
-- Coordinates of destination airport.
|
||||
local Pdestination
|
||||
local Preturn
|
||||
@ -1666,13 +1680,40 @@ function RAT:_SetRoute(takeoff, _departure, _destination)
|
||||
elseif self.returnzone then
|
||||
-- We fly to a random point within a zone and back to the departure airport.
|
||||
Pdestination=departure:GetCoordinate()
|
||||
-- Get a random point inside zone return zone.
|
||||
local vec2=destination:GetRandomVec2()
|
||||
Preturn=COORDINATE:NewFromVec2(vec2)
|
||||
-- Set departure to destination.
|
||||
destination=departure
|
||||
else
|
||||
Pdestination=destination:GetCoordinate()
|
||||
end
|
||||
-- Height ASL of destination airport.
|
||||
]]
|
||||
|
||||
-- Get a random point inside zone return zone.
|
||||
local Preturn
|
||||
local destination_returnzone
|
||||
if self.returnzone then
|
||||
-- Get a random point inside zone return zone.
|
||||
local vec2=destination:GetRandomVec2()
|
||||
Preturn=COORDINATE:NewFromVec2(vec2)
|
||||
destination_returnzone=destination
|
||||
env.info(RAT.id.."Destination r zone = "..destination_returnzone:GetName())
|
||||
-- Set departure to destination.
|
||||
destination=departure
|
||||
env.info(RAT.id.."Destination r zone = "..destination_returnzone:GetName())
|
||||
end
|
||||
|
||||
-- Get destination coordinate. Either in a zone or exactly at the airport.
|
||||
local Pdestination
|
||||
if landing==RAT.wp.air then
|
||||
local vec2=destination:GetRandomVec2()
|
||||
Pdestination=COORDINATE:NewFromVec2(vec2)
|
||||
else
|
||||
Pdestination=destination:GetCoordinate()
|
||||
end
|
||||
|
||||
-- Height ASL of destination airport/zone.
|
||||
local H_destination=Pdestination.y
|
||||
|
||||
-- DESCENT/HOLDING POINT
|
||||
@ -1723,11 +1764,11 @@ function RAT:_SetRoute(takeoff, _departure, _destination)
|
||||
d_total=Pdeparture:Get2DDistance(Pholding)
|
||||
end
|
||||
|
||||
-- max height if we only would descent to holding point for the given distance
|
||||
-- Max height if we only would descent to holding point for the given distance.
|
||||
-- TODO: Add case for destination zone. We could allow a higher max because no descent is necessary.
|
||||
if takeoff==RAT.wp.air then
|
||||
local H_departure_max
|
||||
if self.destinationzone then
|
||||
if landing==RAT.wp.air then
|
||||
H_departure_max = H_departure
|
||||
else
|
||||
H_departure_max = d_total * math.tan(AlphaDescent) + H_holding + h_holding
|
||||
@ -1924,7 +1965,7 @@ function RAT:_SetRoute(takeoff, _departure, _destination)
|
||||
if takeoff==RAT.wp.air then
|
||||
|
||||
-- Air start.
|
||||
if d_climb < 1000 or d_cruise < 1000 then
|
||||
if d_climb < 20000 or d_cruise < 20000 then
|
||||
-- We omit the climb phase completely and add it to the cruise part.
|
||||
d_cruise=d_cruise+d_climb
|
||||
else
|
||||
@ -1953,23 +1994,28 @@ function RAT:_SetRoute(takeoff, _departure, _destination)
|
||||
end
|
||||
|
||||
-- Cruise
|
||||
if self.destinationzone then
|
||||
|
||||
-- First add the little bit from begin of cruise to the return point.
|
||||
if self.returnzone then
|
||||
c[#c+1]=Preturn
|
||||
wp[#wp+1]=self:_Waypoint(#wp+1, RAT.wp.cruise, c[#wp+1], VxCruise, FLcruise)
|
||||
self.waypointdescriptions[#wp]="Return Zone"
|
||||
self.waypointstatus[#wp]=RAT.status.Uturn
|
||||
end
|
||||
|
||||
if landing==RAT.wp.air then
|
||||
|
||||
-- Next waypoint is already the final destination.
|
||||
c[#c+1]=Pdestination
|
||||
--TODO: change RAT.wp.finalwp to "landing"
|
||||
wp[#wp+1]=self:_Waypoint(#wp+1, RAT.wp.finalwp, c[#wp+1], VxCruise, FLcruise)
|
||||
self.waypointdescriptions[#wp]="Final Destination"
|
||||
self.waypointstatus[#wp]=RAT.status.Destination
|
||||
|
||||
elseif self.returnzone then
|
||||
|
||||
c[#c+1]=Preturn
|
||||
c[#c+1]=c[#c]:Translate(d_cruise/2, heading-180)
|
||||
|
||||
wp[#wp+1]=self:_Waypoint(#wp+1, RAT.wp.cruise, c[#wp+1], VxCruise, FLcruise)
|
||||
self.waypointdescriptions[#wp]="Return Zone"
|
||||
self.waypointstatus[#wp]=RAT.status.Uturn
|
||||
|
||||
-- The little bit back to end of cruise.
|
||||
c[#c+1]=c[#c]:Translate(d_cruise/2, heading-180)
|
||||
wp[#wp+1]=self:_Waypoint(#wp+1, RAT.wp.cruise, c[#wp+1], VxCruise, FLcruise)
|
||||
self.waypointdescriptions[#wp]="End of Cruise"
|
||||
self.waypointstatus[#wp]=RAT.status.Descent
|
||||
@ -1980,38 +2026,40 @@ function RAT:_SetRoute(takeoff, _departure, _destination)
|
||||
wp[#wp+1]=self:_Waypoint(#wp+1, RAT.wp.cruise, c[#wp+1], VxCruise, FLcruise)
|
||||
self.waypointdescriptions[#wp]="End of Cruise"
|
||||
self.waypointstatus[#wp]=RAT.status.Descent
|
||||
|
||||
end
|
||||
|
||||
-- Descent
|
||||
if self.destinationzone then
|
||||
-- Nothing to do.
|
||||
elseif self.returnzone then
|
||||
c[#c+1]=c[#c]:Translate(d_descent/2, heading-180)
|
||||
wp[#wp+1]=self:_Waypoint(#wp+1, RAT.wp.descent, c[#wp+1], VxDescent, FLcruise-(FLcruise-(h_holding+H_holding))/2)
|
||||
self.waypointdescriptions[#wp]="Descent"
|
||||
self.waypointstatus[#wp]=RAT.status.DescentHolding
|
||||
else
|
||||
c[#c+1]=c[#c]:Translate(d_descent/2, heading)
|
||||
wp[#wp+1]=self:_Waypoint(#wp+1, RAT.wp.descent, c[#wp+1], VxDescent, FLcruise-(FLcruise-(h_holding+H_holding))/2)
|
||||
self.waypointdescriptions[#wp]="Descent"
|
||||
self.waypointstatus[#wp]=RAT.status.DescentHolding
|
||||
-- Descent (only if we acually want to land)
|
||||
if landing==RAT.wp.landing then
|
||||
if self.returnzone then
|
||||
c[#c+1]=c[#c]:Translate(d_descent/2, heading-180)
|
||||
wp[#wp+1]=self:_Waypoint(#wp+1, RAT.wp.descent, c[#wp+1], VxDescent, FLcruise-(FLcruise-(h_holding+H_holding))/2)
|
||||
self.waypointdescriptions[#wp]="Descent"
|
||||
self.waypointstatus[#wp]=RAT.status.DescentHolding
|
||||
else
|
||||
c[#c+1]=c[#c]:Translate(d_descent/2, heading)
|
||||
wp[#wp+1]=self:_Waypoint(#wp+1, RAT.wp.descent, c[#wp+1], VxDescent, FLcruise-(FLcruise-(h_holding+H_holding))/2)
|
||||
self.waypointdescriptions[#wp]="Descent"
|
||||
self.waypointstatus[#wp]=RAT.status.DescentHolding
|
||||
end
|
||||
end
|
||||
|
||||
-- Holding and final destination.
|
||||
if self.destinationzone then
|
||||
-- Nothing to do.
|
||||
else
|
||||
c[#c+1]=Pholding
|
||||
c[#c+1]=Pdestination
|
||||
|
||||
if landing==RAT.wp.landing then
|
||||
|
||||
-- Holding point
|
||||
c[#c+1]=Pholding
|
||||
wp[#wp+1]=self:_Waypoint(#wp+1, RAT.wp.holding, c[#wp+1], VxHolding, H_holding+h_holding)
|
||||
self.waypointdescriptions[#wp]="Holding Point"
|
||||
self.waypointstatus[#wp]=RAT.status.Holding
|
||||
self.wp_holding=#wp
|
||||
|
||||
wp[#wp+1]=self:_Waypoint(#wp+1, RAT.wp.landing, c[#wp+1], VxFinal, H_destination, destination)
|
||||
|
||||
-- Final destination.
|
||||
c[#c+1]=Pdestination
|
||||
wp[#wp+1]=self:_Waypoint(#wp+1, landing, c[#wp+1], VxFinal, H_destination, destination)
|
||||
self.waypointdescriptions[#wp]="Destination"
|
||||
self.waypointstatus[#wp]=RAT.status.Destination
|
||||
|
||||
end
|
||||
|
||||
-- Final Waypoint
|
||||
@ -2032,7 +2080,12 @@ function RAT:_SetRoute(takeoff, _departure, _destination)
|
||||
self:_Routeinfo(waypoints, "Waypoint info in set_route:")
|
||||
|
||||
-- return departure, destination and waypoints
|
||||
return departure, destination, waypoints
|
||||
if self.returnzone then
|
||||
-- We return the actual zone here because returning the departure leads to problems with commute.
|
||||
return departure, destination_returnzone, waypoints
|
||||
else
|
||||
return departure, destination, waypoints
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@ -2125,9 +2178,8 @@ end
|
||||
--- Pick destination airport. If no airport name is given an airport from the coalition is chosen randomly.
|
||||
-- @param #RAT self
|
||||
-- @param #table destinations Table with destination airports.
|
||||
-- @param #boolean _random (Optional) Switch to activate a random selection of airports.
|
||||
-- @return Wrapper.Airbase#AIRBASE Destination airport.
|
||||
function RAT:_PickDestination(destinations, _random)
|
||||
function RAT:_PickDestination(destinations)
|
||||
|
||||
-- Randomly select one possible destination.
|
||||
local destination=nil
|
||||
@ -2163,16 +2215,17 @@ end
|
||||
-- @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(departure, q, minrange, maxrange)
|
||||
-- @param #booleean random Destination is randomly selected from friendly airport (true) or from destinations specified by user input (false).
|
||||
-- @param #number Number indicating whether we land at a destination or return a zone object.
|
||||
-- @return #table Table with possible destination airports or zones.
|
||||
function RAT:_GetDestinations(departure, q, minrange, maxrange, random, landing)
|
||||
|
||||
-- Min/max range to destination.
|
||||
minrange=minrange or self.mindist
|
||||
maxrange=maxrange or self.maxdist
|
||||
|
||||
local possible_destinations={}
|
||||
if self.random_destination then
|
||||
if random then
|
||||
|
||||
-- Airports of friendly coalitions.
|
||||
for _,airport in pairs(self.airports) do
|
||||
@ -2184,49 +2237,48 @@ function RAT:_GetDestinations(departure, q, minrange, maxrange)
|
||||
|
||||
-- Check if distance form departure to destination is within min/max range.
|
||||
if distance>=minrange and distance<=maxrange then
|
||||
table.insert(possible_destinations, airport)
|
||||
if landing==RAT.wp.air then
|
||||
table.insert(possible_destinations, airport:GetZone()) -- insert zone object.
|
||||
else
|
||||
table.insert(possible_destinations, airport) -- insert airport object.
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
else
|
||||
|
||||
if self.destinationzone or self.returnzone then
|
||||
|
||||
-- Destination or return zones specified by user.
|
||||
for _,zone in pairs(self.destination_zones) do
|
||||
if zone:GetName() ~= departure:GetName() then
|
||||
|
||||
-- Destination airports or zones specified by user.
|
||||
for _,name in pairs(self.destination_ports) do
|
||||
|
||||
-- Distance from departure to possible destination
|
||||
local distance=q:Get2DDistance(zone:GetCoordinate())
|
||||
|
||||
-- Add as possible destination if zone is within range.
|
||||
if distance>=minrange and distance<=maxrange then
|
||||
table.insert(possible_destinations, zone)
|
||||
-- Make sure departure and destination are not identical.
|
||||
if name ~= departure:GetName() then
|
||||
|
||||
local dest
|
||||
if self:_AirportExists(name) then
|
||||
if landing==RAT.wp.air then
|
||||
dest=AIRBASE:FindByName(name):GetZone()
|
||||
else
|
||||
dest=AIRBASE:FindByName(name)
|
||||
end
|
||||
elseif self:_ZoneExists(name) then
|
||||
dest=ZONE:New(name)
|
||||
else
|
||||
env.error(RAT.id.."No airport or zone found with name "..name)
|
||||
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)
|
||||
|
||||
-- Distance from departure to possible destination
|
||||
local distance=q:Get2DDistance(airport:GetCoordinate())
|
||||
|
||||
-- Add as possible destination if airport is within range.
|
||||
if distance>=minrange and distance<=maxrange then
|
||||
table.insert(possible_destinations, airport)
|
||||
end
|
||||
-- Distance from departure to possible destination
|
||||
local distance=q:Get2DDistance(dest:GetCoordinate())
|
||||
|
||||
-- Add as possible destination if zone is within range.
|
||||
if distance>=minrange and distance<=maxrange then
|
||||
table.insert(possible_destinations, dest)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
-- Info message.
|
||||
@ -3018,9 +3070,7 @@ function RAT:_Waypoint(index, Type, Coord, Speed, Altitude, Airport)
|
||||
-- waypoint name (only for the mission editor)
|
||||
RoutePoint.name="RAT waypoint"
|
||||
|
||||
if (Airport~=nil) and Type~=RAT.wp.air then
|
||||
env.info(RAT.id.."Airport = "..Airport:GetName())
|
||||
env.info(RAT.id.."Type = "..Type)
|
||||
if (Airport~=nil) and (Type~=RAT.wp.air) then
|
||||
local AirbaseID = Airport:GetID()
|
||||
local AirbaseCategory = Airport:GetDesc().category
|
||||
if AirbaseCategory == Airbase.Category.SHIP then
|
||||
@ -3179,6 +3229,7 @@ function RAT._WaypointFunction(group, rat, wp)
|
||||
-- Departure and destination names.
|
||||
local departure=rat.ratcraft[sdx].departure:GetName()
|
||||
local destination=rat.ratcraft[sdx].destination:GetName()
|
||||
local landing=rat.ratcraft[sdx].landing
|
||||
|
||||
-- For messages
|
||||
local text
|
||||
@ -3211,7 +3262,7 @@ function RAT._WaypointFunction(group, rat, wp)
|
||||
MESSAGE:New(text, 10):ToAllIf(rat.reportstatus)
|
||||
env.info(RAT.id..text)
|
||||
|
||||
if rat.destinationzone then
|
||||
if landing==RAT.wp.air then
|
||||
text=string.format("Activating despawn switch for flight %s! Group will be detroyed soon.", group:GetName())
|
||||
MESSAGE:New(text, 30):ToAllIf(rat.debug)
|
||||
env.info(RAT.id..text)
|
||||
@ -3923,3 +3974,5 @@ function RAT:_ATCQueue()
|
||||
end
|
||||
end
|
||||
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user