mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-10-29 16:58:06 +00:00
RAT
- Improved respawn/despawn - Added stuck check
This commit is contained in:
parent
a5632ec3a4
commit
1fdb3b7daa
@ -43,8 +43,6 @@
|
|||||||
--
|
--
|
||||||
-- ### Author: **funkyfranky**
|
-- ### Author: **funkyfranky**
|
||||||
--
|
--
|
||||||
-- ### Contributions: FlightControl
|
|
||||||
--
|
|
||||||
-- ===
|
-- ===
|
||||||
-- @module Functional.RAT
|
-- @module Functional.RAT
|
||||||
-- @image RAT.JPG
|
-- @image RAT.JPG
|
||||||
@ -589,6 +587,8 @@ RAT.version={
|
|||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
--TODO list:
|
--TODO list:
|
||||||
|
--TODO: Add max number of spawns
|
||||||
|
--TODO: Add Stop function
|
||||||
--TODO: Integrate FLIGHTGROUP
|
--TODO: Integrate FLIGHTGROUP
|
||||||
--DONE: Add scheduled spawn.
|
--DONE: Add scheduled spawn.
|
||||||
--DONE: Add possibility to spawn in air.
|
--DONE: Add possibility to spawn in air.
|
||||||
@ -635,7 +635,6 @@ RAT.version={
|
|||||||
-- @usage yak1:RAT("RAT_YAK") will create a RAT object called "yak1". The template group in the mission editor must have the name "RAT_YAK".
|
-- @usage yak1:RAT("RAT_YAK") will create a RAT object called "yak1". The template group in the mission editor must have the name "RAT_YAK".
|
||||||
-- @usage yak2:RAT("RAT_YAK", "Yak2") will create a RAT object "yak2". The template group in the mission editor must have the name "RAT_YAK" but the group will be called "Yak2" in e.g. the F10 menu.
|
-- @usage yak2:RAT("RAT_YAK", "Yak2") will create a RAT object "yak2". The template group in the mission editor must have the name "RAT_YAK" but the group will be called "Yak2" in e.g. the F10 menu.
|
||||||
function RAT:New(groupname, alias)
|
function RAT:New(groupname, alias)
|
||||||
BASE:F({groupname=groupname, alias=alias})
|
|
||||||
|
|
||||||
-- Inherit SPAWN class.
|
-- Inherit SPAWN class.
|
||||||
self=BASE:Inherit(self, SPAWN:NewWithAlias(groupname, alias)) -- #RAT
|
self=BASE:Inherit(self, SPAWN:NewWithAlias(groupname, alias)) -- #RAT
|
||||||
@ -685,6 +684,12 @@ function RAT:New(groupname, alias)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Stop RAT spawning by unhandling events, stoping schedulers etc.
|
||||||
|
-- @param #RAT self
|
||||||
|
function RAT:Stop()
|
||||||
|
-- TODO
|
||||||
|
end
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- Spawn function
|
-- Spawn function
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
@ -880,6 +885,8 @@ function RAT:Spawn(naircraft)
|
|||||||
|
|
||||||
-- Start scheduled spawning.
|
-- Start scheduled spawning.
|
||||||
SCHEDULER:New(nil, self._SpawnWithRoute, {self}, Tstart, dt, 0.0, Tstop)
|
SCHEDULER:New(nil, self._SpawnWithRoute, {self}, Tstart, dt, 0.0, Tstop)
|
||||||
|
|
||||||
|
--self.sid_spawn=self.Scheduler:Schedule(MasterObject,SchedulerFunction,SchedulerArguments,Start,Repeat,RandomizeFactor,Stop,TraceLevel,Fsm)
|
||||||
|
|
||||||
-- Start scheduled activation of uncontrolled groups.
|
-- Start scheduled activation of uncontrolled groups.
|
||||||
if self.uncontrolled and self.activate_uncontrolled then
|
if self.uncontrolled and self.activate_uncontrolled then
|
||||||
@ -914,7 +921,7 @@ function RAT:_CheckConsistency()
|
|||||||
-- Only zones but not takeoff air == > Enable takeoff air.
|
-- Only zones but not takeoff air == > Enable takeoff air.
|
||||||
if self.Ndeparture_Zones>0 and self.takeoff~=RAT.wp.air then
|
if self.Ndeparture_Zones>0 and self.takeoff~=RAT.wp.air then
|
||||||
self.takeoff=RAT.wp.air
|
self.takeoff=RAT.wp.air
|
||||||
self:E(self.lid..string.format("ERROR: At least one zone defined as departure and takeoff is NOT set to air. Enabling air start for RAT group %s!", self.alias))
|
self:E(self.lid..string.format("WARNING: At least one zone defined as departure and takeoff is NOT set to air. Enabling air start for RAT group %s!", self.alias))
|
||||||
end
|
end
|
||||||
-- No airport and no zone specified.
|
-- No airport and no zone specified.
|
||||||
if self.Ndeparture_Airports==0 and self.Ndeparture_Zone==0 then
|
if self.Ndeparture_Airports==0 and self.Ndeparture_Zone==0 then
|
||||||
@ -942,7 +949,7 @@ function RAT:_CheckConsistency()
|
|||||||
if self.Ndestination_Zones>0 and self.landing~=RAT.wp.air and not self.returnzone then
|
if self.Ndestination_Zones>0 and self.landing~=RAT.wp.air and not self.returnzone then
|
||||||
self.landing=RAT.wp.air
|
self.landing=RAT.wp.air
|
||||||
self.destinationzone=true
|
self.destinationzone=true
|
||||||
self:E(self.lid.."ERROR: At least one zone defined as destination and landing is NOT set to air. Enabling destination zone!")
|
self:E(self.lid.."WARNING: At least one zone defined as destination and landing is NOT set to air. Enabling destination zone!")
|
||||||
end
|
end
|
||||||
-- No specified airport and no zone found at all.
|
-- No specified airport and no zone found at all.
|
||||||
if self.Ndestination_Airports==0 and self.Ndestination_Zones==0 then
|
if self.Ndestination_Airports==0 and self.Ndestination_Zones==0 then
|
||||||
@ -1525,7 +1532,8 @@ function RAT:SetMaxRespawnTriedWhenSpawnedOnRunway(n)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Aircraft will be respawned directly after take-off.
|
--- A new aircraft is spawned directly after the last one took off. This creates a lot of outbound traffic. Aircraft are not respawned after they reached their destination.
|
||||||
|
-- Therefore, this option is not to be used with the "commute" or "continue journey" options.
|
||||||
-- @param #RAT self
|
-- @param #RAT self
|
||||||
-- @return #RAT RAT self object.
|
-- @return #RAT RAT self object.
|
||||||
function RAT:RespawnAfterTakeoff()
|
function RAT:RespawnAfterTakeoff()
|
||||||
@ -1600,15 +1608,6 @@ function RAT:CheckOnTop(switch, radius)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Put parking spot coordinates in a data base for future use of aircraft. (Obsolete! API function will be removed soon.)
|
|
||||||
-- @param #RAT self
|
|
||||||
-- @param #boolean switch If true, parking spots are memorized. This is also the default setting.
|
|
||||||
-- @return #RAT RAT self object.
|
|
||||||
function RAT:ParkingSpotDB(switch)
|
|
||||||
self:E("RAT ParkingSpotDB function is obsolete and will be removed soon!")
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Enable Radio. Overrules the ME setting.
|
--- Enable Radio. Overrules the ME setting.
|
||||||
-- @param #RAT self
|
-- @param #RAT self
|
||||||
-- @return #RAT RAT self object.
|
-- @return #RAT RAT self object.
|
||||||
@ -2199,23 +2198,33 @@ function RAT:_SpawnWithRoute(_departure, _destination, _takeoff, _landing, _live
|
|||||||
-- Create a flightgroup object.
|
-- Create a flightgroup object.
|
||||||
local flightgroup=FLIGHTGROUP:New(group)
|
local flightgroup=FLIGHTGROUP:New(group)
|
||||||
|
|
||||||
-- Setting holding time to nil
|
-- Setting holding time to nil so that flight never gets landing clearance.
|
||||||
|
-- TODO: Make this dependent on ATC switch.
|
||||||
flightgroup.holdtime=nil
|
flightgroup.holdtime=nil
|
||||||
|
|
||||||
local _self=self
|
-- No automatic despawning if group gets stuck.
|
||||||
|
flightgroup.stuckDespawn=false
|
||||||
|
|
||||||
|
|
||||||
--- Function called when passing a waypoint.
|
--- Function called when passing a waypoint.
|
||||||
function flightgroup.OnAfterPassingWaypoint(flightgroup, From, Event, To, Waypoint)
|
function flightgroup.OnAfterPassingWaypoint(Flightgroup, From, Event, To, Waypoint)
|
||||||
local waypoint=Waypoint --Ops.OpsGroup#OPSGROUP.Waypoint
|
local waypoint=Waypoint --Ops.OpsGroup#OPSGROUP.Waypoint
|
||||||
|
local flightgroup=Flightgroup --Ops.FlightGroup#FLIGHTGROUP
|
||||||
|
|
||||||
|
local wp=waypoint.uid
|
||||||
|
|
||||||
-- Debug info.
|
-- Debug info.
|
||||||
self:T(self.lid..string.format("RAT passed waypoint %s [uid=%d]", waypoint.name, waypoint.uid))
|
self:T(self.lid..string.format("RAT passed waypoint %s [uid=%d]: %s", waypoint.name, waypoint.uid, tostring(self.waypointdescriptions[wp])))
|
||||||
|
|
||||||
-- Call RAT waypoint function.
|
-- Call RAT waypoint function.
|
||||||
-- * calls _ATCRegisterFlight at holding waypoint ==> now in OnAfterHolding
|
-- * calls _ATCRegisterFlight at holding waypoint ==> now in OnAfterHolding
|
||||||
-- * sets despawnme switch at final waypoint if landing=air
|
-- * sets despawnme switch at final waypoint if landing=air
|
||||||
-- * sets status
|
-- * sets status
|
||||||
RAT._WaypointFunction(group, self, waypoint.uid)
|
RAT._WaypointFunction(group, self, waypoint.uid)
|
||||||
|
|
||||||
|
if waypoint.uid==3 then
|
||||||
|
--flightgroup:SelfDestruction(Delay,ExplosionPower,ElementName)
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -2241,9 +2250,25 @@ function RAT:_SpawnWithRoute(_departure, _destination, _takeoff, _landing, _live
|
|||||||
MENU_MISSION_COMMAND:New("Clear for landing", self.Menu[self.SubMenuName].groups[self.SpawnIndex], self.ClearForLanding, self, groupname)
|
MENU_MISSION_COMMAND:New("Clear for landing", self.Menu[self.SubMenuName].groups[self.SpawnIndex], self.ClearForLanding, self, groupname)
|
||||||
end
|
end
|
||||||
self:_ATCRegisterFlight(groupname, timer.getTime())
|
self:_ATCRegisterFlight(groupname, timer.getTime())
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function flightgroup.OnAfterLandAtAirbase(Flightgroup, From, Event, To, Airport)
|
||||||
|
self:T(self.lid..string.format("RAT group landed at airbase"))
|
||||||
|
end
|
||||||
|
|
||||||
|
function flightgroup.OnAfterArrived(Flightgroup, From, Event, To)
|
||||||
|
self:T(self.lid..string.format("RAT group arrived"))
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Function called when a group got stuck.
|
||||||
|
function flightgroup.OnAfterStuck(Flightgroup, From, Event, To, Stucktime)
|
||||||
|
local flightgroup=Flightgroup --Ops.FlightGroup#FLIGHTGROUP
|
||||||
|
self:T(self.lid..string.format("Group %s got stuck for %d seconds", flightgroup:GetName(), Stucktime))
|
||||||
|
if Stucktime>10*60 then
|
||||||
|
self:_Respawn(flightgroup.group)
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Increase counter of alive groups (also uncontrolled ones).
|
-- Increase counter of alive groups (also uncontrolled ones).
|
||||||
@ -2297,24 +2322,8 @@ function RAT:_SpawnWithRoute(_departure, _destination, _takeoff, _landing, _live
|
|||||||
ratcraft.waypoints=waypoints
|
ratcraft.waypoints=waypoints
|
||||||
ratcraft.airborne=group:InAir()
|
ratcraft.airborne=group:InAir()
|
||||||
ratcraft.nunits=group:GetInitialSize()
|
ratcraft.nunits=group:GetInitialSize()
|
||||||
-- Time and position on ground. For check if aircraft is stuck somewhere.
|
|
||||||
if group:InAir() then
|
|
||||||
ratcraft.Tground=nil
|
|
||||||
ratcraft.Pground=nil
|
|
||||||
ratcraft.Uground=nil
|
|
||||||
ratcraft.Tlastcheck=nil
|
|
||||||
else
|
|
||||||
ratcraft.Tground=timer.getTime()
|
|
||||||
ratcraft.Pground=group:GetCoordinate()
|
|
||||||
ratcraft.Uground={}
|
|
||||||
for _,_unit in pairs(group:GetUnits()) do
|
|
||||||
local _unitname=_unit:GetName()
|
|
||||||
ratcraft.Uground[_unitname]=_unit:GetCoordinate()
|
|
||||||
end
|
|
||||||
ratcraft.Tlastcheck=timer.getTime()
|
|
||||||
end
|
|
||||||
-- Initial and current position. For calculating the travelled distance.
|
-- Initial and current position. For calculating the travelled distance.
|
||||||
ratcraft.P0=group:GetCoordinate()
|
|
||||||
ratcraft.Pnow=group:GetCoordinate()
|
ratcraft.Pnow=group:GetCoordinate()
|
||||||
ratcraft.Distance=0
|
ratcraft.Distance=0
|
||||||
|
|
||||||
@ -2376,26 +2385,34 @@ function RAT:ClearForLanding(name)
|
|||||||
self:T(self.lid.."ATC: User flag value (landing) for "..name.." set to "..flagvalue)
|
self:T(self.lid.."ATC: User flag value (landing) for "..name.." set to "..flagvalue)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Respawn a group.
|
--- Respawn a group. The original group is despawned and a new group is spawed.
|
||||||
-- @param #RAT self
|
-- @param #RAT self
|
||||||
-- @param #number index Spawn index.
|
-- @param Wrapper.Group#GROUP group The group that should be respawned.
|
||||||
-- @param Core.Point#COORDINATE lastpos Last known position of the group.
|
-- @param Core.Point#COORDINATE lastpos Last known position of the group.
|
||||||
-- @param #number delay Delay before respawn
|
-- @param #number delay Delay before respawn in seconds.
|
||||||
function RAT:_Respawn(index, lastpos, delay)
|
function RAT:_Respawn(group, lastpos, delay)
|
||||||
|
|
||||||
if delay and delay>0 then
|
if delay and delay>0 then
|
||||||
|
|
||||||
self:ScheduleOnce(delay, RAT._Respawn, self, index, lastpos, 0)
|
self:ScheduleOnce(delay, RAT._Respawn, self, group, lastpos, 0)
|
||||||
|
|
||||||
else
|
else
|
||||||
self:T(self.lid..string.format("Respawning ratcraft with index=%d", index))
|
if group then
|
||||||
|
self:T(self.lid..string.format("Respawning ratcraft from group %s", group:GetName()))
|
||||||
-- Ratcraft object
|
else
|
||||||
local ratcraft=self.ratcraft[index] --#RAT.RatCraft
|
self:E(self.lid..string.format("ERROR: group is nil in _Respawn!"))
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Get ratcraft from group.
|
||||||
|
local ratcraft=self:_GetRatcraftFromGroup(group)
|
||||||
|
|
||||||
|
-- Get last known position.
|
||||||
|
lastpos=lastpos or group:GetCoordinate()
|
||||||
|
|
||||||
-- Get departure and destination from previous journey.
|
-- Get departure and destination from previous journey.
|
||||||
local departure=ratcraft.departure
|
local departure=ratcraft.departure
|
||||||
local destination=ratcraft.destination
|
local destination=ratcraft.destination --Wrapper.Airbase#AIRBASE
|
||||||
local takeoff=ratcraft.takeoff
|
local takeoff=ratcraft.takeoff
|
||||||
local landing=ratcraft.landing
|
local landing=ratcraft.landing
|
||||||
local livery=ratcraft.livery
|
local livery=ratcraft.livery
|
||||||
@ -2403,35 +2420,31 @@ function RAT:_Respawn(index, lastpos, delay)
|
|||||||
local flightgroup=ratcraft.flightgroup
|
local flightgroup=ratcraft.flightgroup
|
||||||
|
|
||||||
|
|
||||||
|
-- In case we stay at the same airport, we save the parking data to respawn at the same spot.
|
||||||
local parkingdata=nil
|
local parkingdata=nil
|
||||||
for _,_element in pairs(flightgroup.elements) do
|
if self.continuejourney or self.commute then
|
||||||
local element=_element --Ops.OpsGroup#OPSGROUP.Element
|
for _,_element in pairs(flightgroup.elements) do
|
||||||
|
local element=_element --Ops.OpsGroup#OPSGROUP.Element
|
||||||
|
|
||||||
|
if element.parking then
|
||||||
|
-- Init table.
|
||||||
|
if parkingdata==nil then
|
||||||
|
parkingdata={}
|
||||||
|
end
|
||||||
|
|
||||||
if element.parking then
|
self:T(self.lid..string.format("Element %s was parking at spot id=%d", element.name, element.parking.TerminalID))
|
||||||
-- Init table.
|
table.insert(parkingdata, UTILS.DeepCopy(element.parking))
|
||||||
if parkingdata==nil then
|
else
|
||||||
parkingdata={}
|
self:E(self.lid..string.format("WARNING: Element %s did NOT have a not parking spot!", tostring(element.name)))
|
||||||
end
|
end
|
||||||
|
|
||||||
self:T(self.lid..string.format("Element %s was parking at spot id=%d", element.name, element.parking.TerminalID))
|
|
||||||
table.insert(parkingdata, UTILS.DeepCopy(element.parking))
|
|
||||||
else
|
|
||||||
self:E(self.lid..string.format("WARNING: Element %s did NOT have a not parking spot!", tostring(element.name)))
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Despawn flight group
|
|
||||||
flightgroup:Despawn(0, true)
|
|
||||||
flightgroup:__Stop(0.1)
|
|
||||||
|
|
||||||
|
|
||||||
-- This is usually done in _Despawn
|
-- Despawn old group.
|
||||||
ratcraft.group=nil
|
self:_Despawn(ratcraft.group)
|
||||||
ratcraft.status="Dead"
|
|
||||||
self.ratcraft[index]=nil
|
|
||||||
|
|
||||||
local _departure=nil
|
local _departure=nil
|
||||||
local _destination=nil
|
local _destination=nil --Wrapper.Airbase#AIRBASE
|
||||||
local _takeoff=nil
|
local _takeoff=nil
|
||||||
local _landing=nil
|
local _landing=nil
|
||||||
local _livery=nil
|
local _livery=nil
|
||||||
@ -2585,6 +2598,76 @@ function RAT:_Respawn(index, lastpos, delay)
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Despawn group. The `FLIGHTGROUP` is despawned and stopped. The ratcraft is removed from the self.ratcraft table. Menues are removed.
|
||||||
|
-- @param #RAT self
|
||||||
|
-- @param Wrapper.Group#GROUP group Group to be despawned.
|
||||||
|
-- @param #number delay Delay in seconds before the despawn happens. Default is `self.respawn_delay`.
|
||||||
|
function RAT:_Despawn(group, delay)
|
||||||
|
|
||||||
|
delay=delay or self.respawn_delay
|
||||||
|
|
||||||
|
if delay and delay>0 then
|
||||||
|
-- Delayed call.
|
||||||
|
self:ScheduleOnce(delay, RAT._Despawn, self, group, 0)
|
||||||
|
else
|
||||||
|
|
||||||
|
if group then
|
||||||
|
|
||||||
|
-- Get spawnindex of group.
|
||||||
|
local index=self:GetSpawnIndexFromGroup(group)
|
||||||
|
|
||||||
|
if index then
|
||||||
|
|
||||||
|
-- Debug info.
|
||||||
|
self:T(self.lid..string.format("Despawning group %s (index=%d)", group:GetName(), index))
|
||||||
|
|
||||||
|
-- Get ratcraft.
|
||||||
|
local ratcraft=self.ratcraft[index] --#RAT.RatCraft
|
||||||
|
|
||||||
|
self.ratcraft[index].group=nil
|
||||||
|
self.ratcraft[index]["status"]="Dead"
|
||||||
|
|
||||||
|
--TODO: Maybe here could be some more arrays deleted? Somehow this causes issues!
|
||||||
|
--[[
|
||||||
|
--self.ratcraft[index]["group"]=group
|
||||||
|
self.ratcraft[index]["destination"]=nil
|
||||||
|
self.ratcraft[index]["departure"]=nil
|
||||||
|
self.ratcraft[index]["waypoints"]=nil
|
||||||
|
self.ratcraft[index]["airborne"]=nil
|
||||||
|
self.ratcraft[index]["Tground"]=nil
|
||||||
|
self.ratcraft[index]["Pground"]=nil
|
||||||
|
self.ratcraft[index]["Tlastcheck"]=nil
|
||||||
|
self.ratcraft[index]["P0"]=nil
|
||||||
|
self.ratcraft[index]["Pnow"]=nil
|
||||||
|
self.ratcraft[index]["Distance"]=nil
|
||||||
|
self.ratcraft[index].takeoff=nil
|
||||||
|
self.ratcraft[index].landing=nil
|
||||||
|
self.ratcraft[index].wpholding=nil
|
||||||
|
self.ratcraft[index].wpfinal=nil
|
||||||
|
self.ratcraft[index].active=false
|
||||||
|
self.ratcraft[index]["status"]=nil
|
||||||
|
self.ratcraft[index].livery=nil
|
||||||
|
self.ratcraft[index].despawnme=nil
|
||||||
|
self.ratcraft[index].nrespawn=nil
|
||||||
|
]]
|
||||||
|
|
||||||
|
--ratcraft.flightgroup:Destroy(0)
|
||||||
|
ratcraft.flightgroup:Despawn()
|
||||||
|
ratcraft.flightgroup:__Stop(0.1)
|
||||||
|
|
||||||
|
|
||||||
|
self.ratcraft[index]=nil
|
||||||
|
|
||||||
|
-- Remove submenu for this group.
|
||||||
|
if self.f10menu and self.SubMenuName ~= nil then
|
||||||
|
self.Menu[self.SubMenuName]["groups"][index]:Remove()
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
--- Set the route of the AI plane. Due to DCS landing bug, this has to be done before the unit is spawned.
|
--- Set the route of the AI plane. Due to DCS landing bug, this has to be done before the unit is spawned.
|
||||||
@ -3582,14 +3665,6 @@ function RAT:Status(message, forID)
|
|||||||
|
|
||||||
self:T(self.lid.."Checking status")
|
self:T(self.lid.."Checking status")
|
||||||
|
|
||||||
-- Optional arguments.
|
|
||||||
if message==nil then
|
|
||||||
message=false
|
|
||||||
end
|
|
||||||
if forID==nil then
|
|
||||||
forID=false
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Current time.
|
-- Current time.
|
||||||
local Tnow=timer.getTime()
|
local Tnow=timer.getTime()
|
||||||
|
|
||||||
@ -3597,14 +3672,15 @@ function RAT:Status(message, forID)
|
|||||||
local nalive=0
|
local nalive=0
|
||||||
|
|
||||||
-- Loop over all ratcraft.
|
-- Loop over all ratcraft.
|
||||||
for spawnindex,ratcraft in pairs(self.ratcraft) do
|
for spawnindex,_ratcraft in pairs(self.ratcraft) do
|
||||||
|
local ratcraft=_ratcraft --#RAT.RatCraft
|
||||||
|
|
||||||
self:T(self.lid..string.format("Ratcraft Index=%s", tostring(spawnindex)))
|
self:T(self.lid..string.format("Ratcraft Index=%s", tostring(spawnindex)))
|
||||||
|
|
||||||
-- Get group.
|
-- Get group.
|
||||||
local group=ratcraft.group --Wrapper.Group#GROUP
|
local group=ratcraft.group --Wrapper.Group#GROUP
|
||||||
|
|
||||||
if group and group:IsAlive() and (group:GetCoordinate() or group:GetVec3()) then
|
if group and group:IsAlive() then
|
||||||
nalive=nalive+1
|
nalive=nalive+1
|
||||||
|
|
||||||
self:T(self.lid..string.format("Ratcraft Index=%s is ALIVE", tostring(spawnindex)))
|
self:T(self.lid..string.format("Ratcraft Index=%s is ALIVE", tostring(spawnindex)))
|
||||||
@ -3614,104 +3690,26 @@ function RAT:Status(message, forID)
|
|||||||
local life=self:_GetLife(group)
|
local life=self:_GetLife(group)
|
||||||
local fuel=group:GetFuel()*100.0
|
local fuel=group:GetFuel()*100.0
|
||||||
local airborne=group:InAir()
|
local airborne=group:InAir()
|
||||||
local coords=group:GetCoordinate() or group:GetVec3()
|
local coords=group:GetCoordinate()
|
||||||
local alt=1000
|
local alt=coords~=nil and coords.y or 1000
|
||||||
if coords then
|
|
||||||
alt=coords.y or 1000
|
|
||||||
end
|
|
||||||
--local vel=group:GetVelocityKMH()
|
|
||||||
local departure=ratcraft.departure:GetName()
|
local departure=ratcraft.departure:GetName()
|
||||||
local destination=ratcraft.destination:GetName()
|
local destination=ratcraft.destination:GetName()
|
||||||
local type=self.aircraft.type
|
local type=self.aircraft.type
|
||||||
local status=ratcraft.status
|
local status=ratcraft.status
|
||||||
local active=ratcraft.active
|
local active=ratcraft.active
|
||||||
local Nunits=ratcraft.nunits -- group:GetSize()
|
local Nunits=ratcraft.nunits
|
||||||
local N0units=group:GetInitialSize()
|
local N0units=group:GetInitialSize()
|
||||||
|
|
||||||
-- Monitor time and distance on ground.
|
|
||||||
local Tg=0
|
|
||||||
local Dg=0
|
|
||||||
local dTlast=0
|
|
||||||
local stationary=false --lets assume, we did move
|
|
||||||
if airborne then
|
|
||||||
-- Aircraft is airborne.
|
|
||||||
ratcraft["Tground"]=nil
|
|
||||||
ratcraft["Pground"]=nil
|
|
||||||
ratcraft["Uground"]=nil
|
|
||||||
ratcraft["Tlastcheck"]=nil
|
|
||||||
else
|
|
||||||
--Aircraft is on ground.
|
|
||||||
if ratcraft["Tground"] then
|
|
||||||
-- Aircraft was already on ground. Calculate total time on ground.
|
|
||||||
Tg=Tnow-ratcraft["Tground"]
|
|
||||||
|
|
||||||
-- Distance on ground since last check.
|
|
||||||
Dg=coords:Get2DDistance(ratcraft["Pground"])
|
|
||||||
|
|
||||||
-- Time interval since last check.
|
|
||||||
dTlast=Tnow-ratcraft["Tlastcheck"]
|
|
||||||
|
|
||||||
-- If more than Tinactive seconds passed since last check ==> check how much we moved meanwhile.
|
|
||||||
if dTlast > self.Tinactive then
|
|
||||||
|
|
||||||
--[[
|
|
||||||
if Dg<50 and active and status~=RAT.status.EventBirth then
|
|
||||||
stationary=true
|
|
||||||
end
|
|
||||||
]]
|
|
||||||
|
|
||||||
-- Loop over all units.
|
|
||||||
for _,_unit in pairs(group:GetUnits()) do
|
|
||||||
|
|
||||||
if _unit and _unit:IsAlive() then
|
|
||||||
|
|
||||||
-- Unit name, coord and distance since last check.
|
|
||||||
local unitname=_unit:GetName()
|
|
||||||
local unitcoord=_unit:GetCoordinate()
|
|
||||||
local Ug=unitcoord:Get2DDistance(ratcraft.Uground[unitname])
|
|
||||||
|
|
||||||
-- Debug info
|
|
||||||
self:T2(self.lid..string.format("Unit %s travelled distance on ground %.1f m since %d seconds.", unitname, Ug, dTlast))
|
|
||||||
|
|
||||||
-- If aircraft did not move more than 50 m since last check, we call it stationary and despawn it.
|
|
||||||
-- Aircraft which are spawned uncontrolled or starting their engines are not counted.
|
|
||||||
if Ug<50 and active and status~=RAT.status.EventBirth then
|
|
||||||
stationary=true
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Update coords.
|
|
||||||
ratcraft["Uground"][unitname]=unitcoord
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Set the current time to know when the next check is necessary.
|
|
||||||
ratcraft["Tlastcheck"]=Tnow
|
|
||||||
ratcraft["Pground"]=coords
|
|
||||||
end
|
|
||||||
|
|
||||||
else
|
|
||||||
-- First time we see that the aircraft is on ground. Initialize the times and position.
|
|
||||||
ratcraft["Tground"]=Tnow
|
|
||||||
ratcraft["Tlastcheck"]=Tnow
|
|
||||||
ratcraft["Pground"]=coords
|
|
||||||
ratcraft["Uground"]={}
|
|
||||||
for _,_unit in pairs(group:GetUnits()) do
|
|
||||||
local unitname=_unit:GetName()
|
|
||||||
ratcraft.Uground[unitname]=_unit:GetCoordinate()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Monitor travelled distance since last check.
|
-- Monitor travelled distance since last check.
|
||||||
local Pn=coords
|
local Pnow=coords
|
||||||
local Dtravel=Pn:Get2DDistance(ratcraft["Pnow"])
|
local Dtravel=Pnow:Get2DDistance(ratcraft.Pnow)
|
||||||
ratcraft["Pnow"]=Pn
|
ratcraft.Pnow=Pnow
|
||||||
|
|
||||||
-- Add up the travelled distance.
|
-- Add up the travelled distance.
|
||||||
ratcraft["Distance"]=ratcraft["Distance"]+Dtravel
|
ratcraft.Distance=ratcraft.Distance+Dtravel
|
||||||
|
|
||||||
-- Distance remaining to destination.
|
-- Distance remaining to destination.
|
||||||
local Ddestination=Pn:Get2DDistance(ratcraft.destination:GetCoordinate())
|
local Ddestination=Pnow:Get2DDistance(ratcraft.destination:GetCoordinate())
|
||||||
|
|
||||||
-- Status report.
|
-- Status report.
|
||||||
if (forID and spawnindex==forID) or (not forID) then
|
if (forID and spawnindex==forID) or (not forID) then
|
||||||
@ -3734,60 +3732,36 @@ function RAT:Status(message, forID)
|
|||||||
else
|
else
|
||||||
text=text.." [on ground]\n"
|
text=text.." [on ground]\n"
|
||||||
end
|
end
|
||||||
text=text..string.format("Fuel = %3.0f %%\n", fuel)
|
text=text..string.format("Fuel = %3.0f %%\n", fuel)
|
||||||
text=text..string.format("Life = %3.0f %%\n", life)
|
text=text..string.format("Life = %3.0f %%\n", life)
|
||||||
text=text..string.format("FL%03d = %i m ASL\n", alt/RAT.unit.FL2m, alt)
|
text=text..string.format("FL%03d = %i m ASL\n", alt/RAT.unit.FL2m, alt)
|
||||||
--text=text..string.format("Speed = %i km/h\n", vel)
|
text=text..string.format("Distance travelled = %6.1f km\n", ratcraft["Distance"]/1000)
|
||||||
text=text..string.format("Distance travelled = %6.1f km\n", ratcraft["Distance"]/1000)
|
text=text..string.format("Distance to dest = %6.1f km", Ddestination/1000)
|
||||||
text=text..string.format("Distance to destination = %6.1f km", Ddestination/1000)
|
|
||||||
if not airborne then
|
|
||||||
text=text..string.format("\nTime on ground = %6.0f seconds\n", Tg)
|
|
||||||
text=text..string.format("Position change = %8.1f m since %3.0f seconds.", Dg, dTlast)
|
|
||||||
end
|
|
||||||
self:T(self.lid..text)
|
self:T(self.lid..text)
|
||||||
if message then
|
if message then
|
||||||
MESSAGE:New(text, 20):ToAll()
|
MESSAGE:New(text, 20):ToAll()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Despawn groups if they are on ground and don't move or are damaged.
|
|
||||||
if not airborne then
|
|
||||||
|
|
||||||
-- Despawn unit if it did not move more then 50 m in the last 180 seconds.
|
|
||||||
if stationary then
|
|
||||||
local text=string.format("Group %s is despawned after being %d seconds inaktive on ground.", self.alias, dTlast)
|
|
||||||
self:T(self.lid..text)
|
|
||||||
self:_Despawn(group)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Despawn group if life is < 10% and distance travelled < 100 m.
|
|
||||||
if life<10 and Dtravel<100 then
|
|
||||||
local text=string.format("Damaged group %s is despawned. Life = %3.0f", self.alias, life)
|
|
||||||
self:T(self.lid..text)
|
|
||||||
self:_Despawn(group)
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Despawn groups after they have reached their destination zones.
|
-- Despawn groups after they have reached their destination zones.
|
||||||
if ratcraft.despawnme then
|
if ratcraft.despawnme then
|
||||||
|
|
||||||
local text=string.format("Flight %s will be despawned NOW!", self.alias)
|
if self.norespawn or self.respawn_after_takeoff then
|
||||||
self:T(self.lid..text)
|
|
||||||
|
|
||||||
-- Respawn group
|
|
||||||
if (not self.norespawn) and (not self.respawn_after_takeoff) then
|
|
||||||
local idx=self:GetSpawnIndexFromGroup(group)
|
|
||||||
local coord=group:GetCoordinate()
|
|
||||||
self:_Respawn(idx, coord, 0)
|
|
||||||
else
|
|
||||||
-- Despawn old group.
|
-- Despawn old group.
|
||||||
if self.despawnair then
|
if self.despawnair then
|
||||||
|
self:T(self.lid..string.format("[STATUS despawnme] Flight %s will be despawned NOW and NO new group is created!", self.alias))
|
||||||
self:_Despawn(group, 0)
|
self:_Despawn(group, 0)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
-- Despawn old group and respawn a new one.
|
||||||
|
self:T(self.lid..string.format("[STATUS despawnme] Flight %s will be despawned NOW and a new group is respawned!", self.alias))
|
||||||
|
self:_Respawn(group)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
@ -4164,9 +4138,7 @@ function RAT:_OnLand(EventData)
|
|||||||
self:T(self.lid..text)
|
self:T(self.lid..text)
|
||||||
|
|
||||||
-- Respawn group.
|
-- Respawn group.
|
||||||
local idx=self:GetSpawnIndexFromGroup(SpawnGroup)
|
self:_Respawn(SpawnGroup)
|
||||||
local coord=SpawnGroup:GetCoordinate()
|
|
||||||
self:_Respawn(idx, coord)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
@ -4215,9 +4187,7 @@ function RAT:_OnEngineShutdown(EventData)
|
|||||||
self:T(self.lid..text)
|
self:T(self.lid..text)
|
||||||
|
|
||||||
-- Respawn group.
|
-- Respawn group.
|
||||||
local idx=self:GetSpawnIndexFromGroup(SpawnGroup)
|
self:_Respawn(SpawnGroup, nil, 3)
|
||||||
local coord=SpawnGroup:GetCoordinate()
|
|
||||||
self:_Respawn(idx, coord, 3)
|
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
@ -4382,13 +4352,9 @@ function RAT:_OnCrash(EventData)
|
|||||||
|
|
||||||
-- Debug info.
|
-- Debug info.
|
||||||
self:T(self.lid..string.format("No units left of group %s. Group will be respawned now.", SpawnGroup:GetName()))
|
self:T(self.lid..string.format("No units left of group %s. Group will be respawned now.", SpawnGroup:GetName()))
|
||||||
|
|
||||||
-- Get spawn index
|
|
||||||
local idx=self:GetSpawnIndexFromGroup(SpawnGroup)
|
|
||||||
local coord=SpawnGroup:GetCoordinate()
|
|
||||||
|
|
||||||
-- Respawn group.
|
-- Respawn group.
|
||||||
self:_Respawn(idx, coord)
|
self:_Respawn(SpawnGroup)
|
||||||
end
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
@ -4404,117 +4370,6 @@ function RAT:_OnCrash(EventData)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Despawn unit. Unit gets destoyed and group is set to nil.
|
|
||||||
-- Index of ratcraft array is taken from spawned group name.
|
|
||||||
-- @param #RAT self
|
|
||||||
-- @param Wrapper.Group#GROUP group Group to be despawned.
|
|
||||||
-- @param #number delay Delay in seconds before the despawn happens.
|
|
||||||
function RAT:_Despawn(group, delay)
|
|
||||||
|
|
||||||
if group ~= nil then
|
|
||||||
|
|
||||||
-- Get spawnindex of group.
|
|
||||||
local index=self:GetSpawnIndexFromGroup(group)
|
|
||||||
|
|
||||||
if index ~= nil then
|
|
||||||
|
|
||||||
local ratcraft=self.ratcraft[index]
|
|
||||||
|
|
||||||
self.ratcraft[index].group=nil
|
|
||||||
self.ratcraft[index]["status"]="Dead"
|
|
||||||
|
|
||||||
--TODO: Maybe here could be some more arrays deleted?
|
|
||||||
--TODO: Somehow this causes issues.
|
|
||||||
--[[
|
|
||||||
--self.ratcraft[index]["group"]=group
|
|
||||||
self.ratcraft[index]["destination"]=nil
|
|
||||||
self.ratcraft[index]["departure"]=nil
|
|
||||||
self.ratcraft[index]["waypoints"]=nil
|
|
||||||
self.ratcraft[index]["airborne"]=nil
|
|
||||||
self.ratcraft[index]["Tground"]=nil
|
|
||||||
self.ratcraft[index]["Pground"]=nil
|
|
||||||
self.ratcraft[index]["Tlastcheck"]=nil
|
|
||||||
self.ratcraft[index]["P0"]=nil
|
|
||||||
self.ratcraft[index]["Pnow"]=nil
|
|
||||||
self.ratcraft[index]["Distance"]=nil
|
|
||||||
self.ratcraft[index].takeoff=nil
|
|
||||||
self.ratcraft[index].landing=nil
|
|
||||||
self.ratcraft[index].wpholding=nil
|
|
||||||
self.ratcraft[index].wpfinal=nil
|
|
||||||
self.ratcraft[index].active=false
|
|
||||||
self.ratcraft[index]["status"]=nil
|
|
||||||
self.ratcraft[index].livery=nil
|
|
||||||
self.ratcraft[index].despawnme=nil
|
|
||||||
self.ratcraft[index].nrespawn=nil
|
|
||||||
]]
|
|
||||||
|
|
||||||
-- We should give it at least 3 sec since this seems to be the time until free parking spots after despawn are available again (Sirri Island test).
|
|
||||||
local despawndelay=0
|
|
||||||
if delay then
|
|
||||||
-- Explicitly requested delay time.
|
|
||||||
despawndelay=delay
|
|
||||||
elseif self.respawn_delay then
|
|
||||||
-- Despawn afer respawn_delay. Actual respawn happens in +3 seconds to allow for free parking.
|
|
||||||
despawndelay=self.respawn_delay
|
|
||||||
end
|
|
||||||
|
|
||||||
-- This will destroy the DCS group and create a single DEAD event.
|
|
||||||
--if despawndelay>0.5 then
|
|
||||||
self:T(self.lid..string.format("%s delayed despawn in %.1f seconds.", self.alias, despawndelay))
|
|
||||||
SCHEDULER:New(nil, self._Destroy, {self, group}, despawndelay)
|
|
||||||
--else
|
|
||||||
--self:_Destroy(group)
|
|
||||||
--end
|
|
||||||
|
|
||||||
-- Remove submenu for this group.
|
|
||||||
if self.f10menu and self.SubMenuName ~= nil then
|
|
||||||
self.Menu[self.SubMenuName]["groups"][index]:Remove()
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Destroys the RAT DCS group and all of its DCS units.
|
|
||||||
-- Note that this raises a DEAD event at run-time.
|
|
||||||
-- So all event listeners will catch the DEAD event of this DCS group.
|
|
||||||
-- @param #RAT self
|
|
||||||
-- @param Wrapper.Group#GROUP group The RAT group to be destroyed.
|
|
||||||
function RAT:_Destroy(group)
|
|
||||||
self:F2(group)
|
|
||||||
|
|
||||||
local DCSGroup = group:GetDCSObject() -- DCS#Group
|
|
||||||
|
|
||||||
if DCSGroup and DCSGroup:isExist() then
|
|
||||||
|
|
||||||
-- -- Cread one single Dead event and delete units from database.
|
|
||||||
-- local triggerdead=true
|
|
||||||
-- for _,DCSUnit in pairs(DCSGroup:getUnits()) do
|
|
||||||
--
|
|
||||||
-- -- Dead event.
|
|
||||||
-- if DCSUnit then
|
|
||||||
-- if triggerdead then
|
|
||||||
-- self:_CreateEventDead(timer.getTime(), DCSUnit)
|
|
||||||
-- triggerdead=false
|
|
||||||
-- end
|
|
||||||
--
|
|
||||||
-- -- Delete from data base.
|
|
||||||
-- _DATABASE:DeleteUnit(DCSUnit:getName())
|
|
||||||
-- end
|
|
||||||
-- end
|
|
||||||
|
|
||||||
local ratcraft=self:_GetRatcraftFromGroup(group)
|
|
||||||
|
|
||||||
ratcraft.flightgroup:Destroy(0)
|
|
||||||
ratcraft.flightgroup:__Stop(0.1)
|
|
||||||
|
|
||||||
-- Destroy DCS group.
|
|
||||||
--DCSGroup:destroy()
|
|
||||||
DCSGroup = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Create a Dead event.
|
--- Create a Dead event.
|
||||||
-- @param #RAT self
|
-- @param #RAT self
|
||||||
@ -4673,30 +4528,37 @@ function RAT:_Waypoint(index, description, Type, Coord, Speed, Altitude, Airport
|
|||||||
self:T(self.lid.."Unknown Airport category in _Waypoint()!")
|
self:T(self.lid.."Unknown Airport category in _Waypoint()!")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
-- properties
|
|
||||||
RoutePoint.properties = {
|
if false then
|
||||||
["vnav"] = 1,
|
|
||||||
["scale"] = 0,
|
-- TODO: Disable the tasks as this is done by FLIGHTGROUP now. Delete when working
|
||||||
["angle"] = 0,
|
|
||||||
["vangle"] = 0,
|
-- properties
|
||||||
["steer"] = 2,
|
RoutePoint.properties = {
|
||||||
}
|
["vnav"] = 1,
|
||||||
-- tasks
|
["scale"] = 0,
|
||||||
local TaskCombo = {}
|
["angle"] = 0,
|
||||||
local TaskHolding = self:_TaskHolding({x=Coord.x, y=Coord.z}, Altitude, Speed, self:_Randomize(90,0.9))
|
["vangle"] = 0,
|
||||||
local TaskWaypoint = self:_TaskFunction("RAT._WaypointFunction", self, index)
|
["steer"] = 2,
|
||||||
|
}
|
||||||
RoutePoint.task = {}
|
-- tasks
|
||||||
RoutePoint.task.id = "ComboTask"
|
local TaskCombo = {}
|
||||||
RoutePoint.task.params = {}
|
local TaskHolding = self:_TaskHolding({x=Coord.x, y=Coord.z}, Altitude, Speed, self:_Randomize(90,0.9))
|
||||||
|
local TaskWaypoint = self:_TaskFunction("RAT._WaypointFunction", self, index)
|
||||||
TaskCombo[#TaskCombo+1]=TaskWaypoint
|
|
||||||
if Type==RAT.wp.holding then
|
RoutePoint.task = {}
|
||||||
TaskCombo[#TaskCombo+1]=TaskHolding
|
RoutePoint.task.id = "ComboTask"
|
||||||
|
RoutePoint.task.params = {}
|
||||||
|
|
||||||
|
TaskCombo[#TaskCombo+1]=TaskWaypoint
|
||||||
|
if Type==RAT.wp.holding then
|
||||||
|
TaskCombo[#TaskCombo+1]=TaskHolding
|
||||||
|
end
|
||||||
|
|
||||||
|
RoutePoint.task.params.tasks = TaskCombo
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
RoutePoint.task.params.tasks = TaskCombo
|
|
||||||
|
|
||||||
-- Return waypoint.
|
-- Return waypoint.
|
||||||
return RoutePoint
|
return RoutePoint
|
||||||
end
|
end
|
||||||
@ -4846,6 +4708,7 @@ function RAT._WaypointFunction(group, rat, wp)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- TODO: Move this to OnAfter Final Waypoint
|
||||||
if wp==WPfinal then
|
if wp==WPfinal then
|
||||||
text=string.format("Flight %s arrived at final destination %s.", group:GetName(), destination)
|
text=string.format("Flight %s arrived at final destination %s.", group:GetName(), destination)
|
||||||
MESSAGE:New(text, 10):ToAllIf(rat.reportstatus)
|
MESSAGE:New(text, 10):ToAllIf(rat.reportstatus)
|
||||||
@ -6013,8 +5876,8 @@ function RAT:_ATCClearForLanding(airportname, flightname)
|
|||||||
-- Debug message.
|
-- Debug message.
|
||||||
BASE:I(RAT.id..string.format("ATC %s: Flight %s cleared for landing", airportname, flightname))
|
BASE:I(RAT.id..string.format("ATC %s: Flight %s cleared for landing", airportname, flightname))
|
||||||
|
|
||||||
if string.find(flight,"#") then
|
if string.find(flightname,"#") then
|
||||||
flight = string.match(flight,"^(.+)#")
|
flightname = string.match(flightname,"^(.+)#")
|
||||||
end
|
end
|
||||||
local text=string.format("ATC %s: Flight %s you are cleared for landing.", airportname, flightname)
|
local text=string.format("ATC %s: Flight %s you are cleared for landing.", airportname, flightname)
|
||||||
MESSAGE:New(text, 10):ToAllIf(RAT.ATC.messages)
|
MESSAGE:New(text, 10):ToAllIf(RAT.ATC.messages)
|
||||||
|
|||||||
@ -1257,9 +1257,12 @@ function FLIGHTGROUP:Status()
|
|||||||
-- Check ammo status.
|
-- Check ammo status.
|
||||||
self:_CheckAmmoStatus()
|
self:_CheckAmmoStatus()
|
||||||
|
|
||||||
-- Check damage.
|
-- Check damage.
|
||||||
self:_CheckDamage()
|
self:_CheckDamage()
|
||||||
|
|
||||||
|
-- Check if stuck while taxiing.
|
||||||
|
self:_CheckStuck()
|
||||||
|
|
||||||
-- Get current mission (if any).
|
-- Get current mission (if any).
|
||||||
local mission=self:GetMissionCurrent()
|
local mission=self:GetMissionCurrent()
|
||||||
|
|
||||||
@ -1627,6 +1630,9 @@ function FLIGHTGROUP:Status()
|
|||||||
if not mission then
|
if not mission then
|
||||||
self.Twaiting=nil
|
self.Twaiting=nil
|
||||||
self.dTwait=nil
|
self.dTwait=nil
|
||||||
|
|
||||||
|
-- Check if group is done.
|
||||||
|
-- TODO: Not sure why I introduced this here.
|
||||||
self:_CheckGroupDone()
|
self:_CheckGroupDone()
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -2139,6 +2145,10 @@ function FLIGHTGROUP:onafterSpawned(From, Event, To)
|
|||||||
self.isDestroyed=false
|
self.isDestroyed=false
|
||||||
|
|
||||||
if self.isAI then
|
if self.isAI then
|
||||||
|
|
||||||
|
-- TODO: Could be that element is spawned UNCONTROLLED.
|
||||||
|
-- In that case, the commands are not yet used.
|
||||||
|
-- This should be shifted to something like after ACTIVATED
|
||||||
|
|
||||||
-- Set ROE.
|
-- Set ROE.
|
||||||
self:SwitchROE(self.option.ROE)
|
self:SwitchROE(self.option.ROE)
|
||||||
@ -2740,6 +2750,7 @@ function FLIGHTGROUP:onafterOutOfMissilesAA(From, Event, To)
|
|||||||
if self.outofAAMrtb then
|
if self.outofAAMrtb then
|
||||||
-- Back to destination or home.
|
-- Back to destination or home.
|
||||||
local airbase=self.destbase or self.homebase
|
local airbase=self.destbase or self.homebase
|
||||||
|
self:T(self.lid.."Calling RTB in onafterOutOfMissilesAA")
|
||||||
self:__RTB(-5, airbase)
|
self:__RTB(-5, airbase)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -2754,6 +2765,7 @@ function FLIGHTGROUP:onafterOutOfMissilesAG(From, Event, To)
|
|||||||
if self.outofAGMrtb then
|
if self.outofAGMrtb then
|
||||||
-- Back to destination or home.
|
-- Back to destination or home.
|
||||||
local airbase=self.destbase or self.homebase
|
local airbase=self.destbase or self.homebase
|
||||||
|
self:T(self.lid.."Calling RTB in onafterOutOfMissilesAG")
|
||||||
self:__RTB(-5, airbase)
|
self:__RTB(-5, airbase)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -2843,8 +2855,8 @@ function FLIGHTGROUP:_CheckGroupDone(delay, waittime)
|
|||||||
-- Number of remaining tasks/missions?
|
-- Number of remaining tasks/missions?
|
||||||
if nTasks==0 and nMissions==0 and nTransports==0 then
|
if nTasks==0 and nMissions==0 and nTransports==0 then
|
||||||
|
|
||||||
local destbase=self.destbase or self.homebase
|
local destbase=self.destbase or self.homebase --Wrapper.Airbase#AIRBASE
|
||||||
local destzone=self.destzone or self.homezone
|
local destzone=self.destzone or self.homezone --Wrapper.Airbase#AIRBASE
|
||||||
|
|
||||||
-- Send flight to destination.
|
-- Send flight to destination.
|
||||||
if waittime then
|
if waittime then
|
||||||
@ -2855,8 +2867,11 @@ function FLIGHTGROUP:_CheckGroupDone(delay, waittime)
|
|||||||
self:T(self.lid.."Passed Final WP and No current and/or future missions/tasks/transports AND parking at destination airbase ==> Arrived!")
|
self:T(self.lid.."Passed Final WP and No current and/or future missions/tasks/transports AND parking at destination airbase ==> Arrived!")
|
||||||
self:Arrived()
|
self:Arrived()
|
||||||
else
|
else
|
||||||
self:T(self.lid.."Passed Final WP and No current and/or future missions/tasks/transports ==> RTB!")
|
-- Only send RTB if current base is not yet the destination
|
||||||
self:__RTB(-0.1, destbase)
|
if self.currbase==nil or self.currbase.AirbaseName~=destbase.AirbaseName then
|
||||||
|
self:T(self.lid.."Passed Final WP and No current and/or future missions/tasks/transports ==> RTB!")
|
||||||
|
self:__RTB(-0.1, destbase)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
elseif destzone then
|
elseif destzone then
|
||||||
self:T(self.lid.."Passed Final WP and No current and/or future missions/tasks/transports ==> RTZ!")
|
self:T(self.lid.."Passed Final WP and No current and/or future missions/tasks/transports ==> RTZ!")
|
||||||
@ -2984,6 +2999,7 @@ function FLIGHTGROUP:onbeforeRTB(From, Event, To, airbase, SpeedTo, SpeedHold)
|
|||||||
end
|
end
|
||||||
|
|
||||||
if Tsuspend and not allowed then
|
if Tsuspend and not allowed then
|
||||||
|
self:T(self.lid.."Calling RTB in onbeforeRTB")
|
||||||
self:__RTB(Tsuspend, airbase, SpeedTo, SpeedHold)
|
self:__RTB(Tsuspend, airbase, SpeedTo, SpeedHold)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -3364,8 +3380,8 @@ function FLIGHTGROUP:onafterWait(From, Event, To, Duration, Altitude, Speed)
|
|||||||
-- Set time stamp.
|
-- Set time stamp.
|
||||||
self.Twaiting=timer.getAbsTime()
|
self.Twaiting=timer.getAbsTime()
|
||||||
|
|
||||||
-- Max waiting
|
-- Max waiting time in seconds.
|
||||||
self.dTwait=Duration
|
self.dTwait=Duration
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -3664,6 +3680,7 @@ function FLIGHTGROUP:onafterFuelLow(From, Event, To)
|
|||||||
|
|
||||||
-- Send back to airbase.
|
-- Send back to airbase.
|
||||||
if airbase and self.fuellowrtb then
|
if airbase and self.fuellowrtb then
|
||||||
|
self:T(self.lid.."Calling RTB in onafterFuelLow")
|
||||||
self:RTB(airbase)
|
self:RTB(airbase)
|
||||||
--TODO: RTZ
|
--TODO: RTZ
|
||||||
end
|
end
|
||||||
@ -3688,6 +3705,7 @@ function FLIGHTGROUP:onafterFuelCritical(From, Event, To)
|
|||||||
local airbase=self.destbase or self.homebase
|
local airbase=self.destbase or self.homebase
|
||||||
|
|
||||||
if airbase and self.fuelcriticalrtb and not self:IsGoing4Fuel() then
|
if airbase and self.fuelcriticalrtb and not self:IsGoing4Fuel() then
|
||||||
|
self:T(self.lid.."Calling RTB in onafterFuelCritical")
|
||||||
self:RTB(airbase)
|
self:RTB(airbase)
|
||||||
--TODO: RTZ
|
--TODO: RTZ
|
||||||
end
|
end
|
||||||
@ -4835,6 +4853,87 @@ function FLIGHTGROUP:_GetTerminal(_attribute, _category)
|
|||||||
return _terminal
|
return _terminal
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Check if group got stuck. This overwrites the OPSGROUP function.
|
||||||
|
-- Here we only check if stuck whilst taxiing.
|
||||||
|
-- @param #FLIGHTGROUP self
|
||||||
|
-- @param #boolean Despawn If `true`, despawn group if stuck.
|
||||||
|
-- @return #number Time in seconds the group got stuck or nil if not stuck.
|
||||||
|
function FLIGHTGROUP:_CheckStuck(Despawn)
|
||||||
|
|
||||||
|
-- Cases we are not stuck.
|
||||||
|
if not self:IsTaxiing() then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Current time.
|
||||||
|
local Tnow=timer.getTime()
|
||||||
|
|
||||||
|
-- Expected speed in m/s.
|
||||||
|
local ExpectedSpeed=5
|
||||||
|
|
||||||
|
-- Current speed in m/s.
|
||||||
|
local speed=self:GetVelocity()
|
||||||
|
|
||||||
|
-- Check speed.
|
||||||
|
if speed<0.1 then
|
||||||
|
|
||||||
|
if ExpectedSpeed>0 and not self.stuckTimestamp then
|
||||||
|
self:T2(self.lid..string.format("WARNING: Group came to an unexpected standstill. Speed=%.1f<%.1f m/s expected", speed, ExpectedSpeed))
|
||||||
|
self.stuckTimestamp=Tnow
|
||||||
|
self.stuckVec3=self:GetVec3()
|
||||||
|
end
|
||||||
|
|
||||||
|
else
|
||||||
|
-- Moving (again).
|
||||||
|
self.stuckTimestamp=nil
|
||||||
|
end
|
||||||
|
|
||||||
|
local holdtime=nil
|
||||||
|
|
||||||
|
-- Somehow we are not moving...
|
||||||
|
if self.stuckTimestamp then
|
||||||
|
|
||||||
|
-- Time we are holding.
|
||||||
|
holdtime=Tnow-self.stuckTimestamp
|
||||||
|
|
||||||
|
-- Trigger stuck event.
|
||||||
|
self:Stuck(holdtime)
|
||||||
|
|
||||||
|
if holdtime>=5*60 and holdtime<15*60 then
|
||||||
|
|
||||||
|
-- Debug warning.
|
||||||
|
self:T(self.lid..string.format("WARNING: Group came to an unexpected standstill. Speed=%.1f<%.1f m/s expected for %d sec", speed, ExpectedSpeed, holdtime))
|
||||||
|
|
||||||
|
elseif holdtime>=15*60 then
|
||||||
|
|
||||||
|
-- Debug warning.
|
||||||
|
self:T(self.lid..string.format("WARNING: Group came to an unexpected standstill. Speed=%.1f<%.1f m/s expected for %d sec", speed, ExpectedSpeed, holdtime))
|
||||||
|
|
||||||
|
-- Look for a current mission and cancel it as we do not seem to be able to perform it.
|
||||||
|
local mission=self:GetMissionCurrent()
|
||||||
|
|
||||||
|
if mission then
|
||||||
|
self:T(self.lid..string.format("WARNING: Cancelling mission %s [%s] due to being stuck", mission:GetName(), mission:GetType()))
|
||||||
|
self:MissionCancel(mission)
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.stuckDespawn then
|
||||||
|
if self.legion then
|
||||||
|
self:T(self.lid..string.format("Asset is returned to its legion after being stuck!"))
|
||||||
|
self:ReturnToLegion()
|
||||||
|
else
|
||||||
|
self:T(self.lid..string.format("Despawning group after being stuck!"))
|
||||||
|
self:Despawn()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
return holdtime
|
||||||
|
end
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- OPTION FUNCTIONS
|
-- OPTION FUNCTIONS
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|||||||
@ -117,6 +117,10 @@
|
|||||||
-- @field #string callsignAlias Callsign alias.
|
-- @field #string callsignAlias Callsign alias.
|
||||||
--
|
--
|
||||||
-- @field #OPSGROUP.Spot spot Laser and IR spot.
|
-- @field #OPSGROUP.Spot spot Laser and IR spot.
|
||||||
|
--
|
||||||
|
-- @field DCS#Vec3 stuckVec3 Position where the group got stuck.
|
||||||
|
-- @field #number stuckTimestamp Time stamp [sec], when the group got stuck.
|
||||||
|
-- @field #boolean stuckDespawn If `true`, group gets despawned after beeing stuck for a certain time.
|
||||||
--
|
--
|
||||||
-- @field #OPSGROUP.Ammo ammo Initial ammount of ammo.
|
-- @field #OPSGROUP.Ammo ammo Initial ammount of ammo.
|
||||||
-- @field #OPSGROUP.WeaponData weaponData Weapon data table with key=BitType.
|
-- @field #OPSGROUP.WeaponData weaponData Weapon data table with key=BitType.
|
||||||
@ -676,10 +680,11 @@ function OPSGROUP:New(group)
|
|||||||
self:AddTransition("*", "UpdateRoute", "*") -- Update route of group.
|
self:AddTransition("*", "UpdateRoute", "*") -- Update route of group.
|
||||||
|
|
||||||
self:AddTransition("*", "PassingWaypoint", "*") -- Group passed a waypoint.
|
self:AddTransition("*", "PassingWaypoint", "*") -- Group passed a waypoint.
|
||||||
self:AddTransition("*", "PassedFinalWaypoint", "*") -- Group passed the waypoint.
|
self:AddTransition("*", "PassedFinalWaypoint", "*") -- Group passed the waypoint.
|
||||||
self:AddTransition("*", "GotoWaypoint", "*") -- Group switches to a specific waypoint.
|
self:AddTransition("*", "GotoWaypoint", "*") -- Group switches to a specific waypoint.
|
||||||
|
|
||||||
self:AddTransition("*", "Wait", "*") -- Group will wait for further orders.
|
self:AddTransition("*", "Wait", "*") -- Group will wait for further orders.
|
||||||
|
self:AddTransition("*", "Stuck", "*") -- Group got stuck.
|
||||||
|
|
||||||
self:AddTransition("*", "DetectedUnit", "*") -- Unit was detected (again) in this detection cycle.
|
self:AddTransition("*", "DetectedUnit", "*") -- Unit was detected (again) in this detection cycle.
|
||||||
self:AddTransition("*", "DetectedUnitNew", "*") -- Add a newly detected unit to the detected units set.
|
self:AddTransition("*", "DetectedUnitNew", "*") -- Add a newly detected unit to the detected units set.
|
||||||
@ -1889,7 +1894,7 @@ end
|
|||||||
|
|
||||||
--- Get current velocity of the group.
|
--- Get current velocity of the group.
|
||||||
-- @param #OPSGROUP self
|
-- @param #OPSGROUP self
|
||||||
-- @param #string UnitName (Optional) Get heading of a specific unit of the group. Default is from the first existing unit in the group.
|
-- @param #string UnitName (Optional) Get velocity of a specific unit of the group. Default is from the first existing unit in the group.
|
||||||
-- @return #number Velocity in m/s.
|
-- @return #number Velocity in m/s.
|
||||||
function OPSGROUP:GetVelocity(UnitName)
|
function OPSGROUP:GetVelocity(UnitName)
|
||||||
|
|
||||||
|
|||||||
@ -359,14 +359,15 @@ end
|
|||||||
-- @param #GROUP self
|
-- @param #GROUP self
|
||||||
-- @return DCS#Group The DCS Group.
|
-- @return DCS#Group The DCS Group.
|
||||||
function GROUP:GetDCSObject()
|
function GROUP:GetDCSObject()
|
||||||
|
|
||||||
|
-- Get DCS group.
|
||||||
local DCSGroup = Group.getByName( self.GroupName )
|
local DCSGroup = Group.getByName( self.GroupName )
|
||||||
|
|
||||||
if DCSGroup then
|
if DCSGroup then
|
||||||
return DCSGroup
|
return DCSGroup
|
||||||
else
|
|
||||||
env.error("ERROR: Could not get DCS group object!")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
self:E(string.format("ERROR: Could not get DCS group object of group %s because DCS object could not be found!", tostring(self.GroupName)))
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user