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**
|
||||
--
|
||||
-- ### Contributions: FlightControl
|
||||
--
|
||||
-- ===
|
||||
-- @module Functional.RAT
|
||||
-- @image RAT.JPG
|
||||
@ -589,6 +587,8 @@ RAT.version={
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--TODO list:
|
||||
--TODO: Add max number of spawns
|
||||
--TODO: Add Stop function
|
||||
--TODO: Integrate FLIGHTGROUP
|
||||
--DONE: Add scheduled spawn.
|
||||
--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 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)
|
||||
BASE:F({groupname=groupname, alias=alias})
|
||||
|
||||
-- Inherit SPAWN class.
|
||||
self=BASE:Inherit(self, SPAWN:NewWithAlias(groupname, alias)) -- #RAT
|
||||
@ -685,6 +684,12 @@ function RAT:New(groupname, alias)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Stop RAT spawning by unhandling events, stoping schedulers etc.
|
||||
-- @param #RAT self
|
||||
function RAT:Stop()
|
||||
-- TODO
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Spawn function
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
@ -881,6 +886,8 @@ function RAT:Spawn(naircraft)
|
||||
-- Start scheduled spawning.
|
||||
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.
|
||||
if self.uncontrolled and self.activate_uncontrolled then
|
||||
SCHEDULER:New(nil, self._ActivateUncontrolled, {self}, self.activate_delay, self.activate_delta, self.activate_frand)
|
||||
@ -914,7 +921,7 @@ function RAT:_CheckConsistency()
|
||||
-- Only zones but not takeoff air == > Enable takeoff air.
|
||||
if self.Ndeparture_Zones>0 and self.takeoff~=RAT.wp.air then
|
||||
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
|
||||
-- No airport and no zone specified.
|
||||
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
|
||||
self.landing=RAT.wp.air
|
||||
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
|
||||
-- No specified airport and no zone found at all.
|
||||
if self.Ndestination_Airports==0 and self.Ndestination_Zones==0 then
|
||||
@ -1525,7 +1532,8 @@ function RAT:SetMaxRespawnTriedWhenSpawnedOnRunway(n)
|
||||
return self
|
||||
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
|
||||
-- @return #RAT RAT self object.
|
||||
function RAT:RespawnAfterTakeoff()
|
||||
@ -1600,15 +1608,6 @@ function RAT:CheckOnTop(switch, radius)
|
||||
return self
|
||||
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.
|
||||
-- @param #RAT self
|
||||
-- @return #RAT RAT self object.
|
||||
@ -2199,17 +2198,23 @@ function RAT:_SpawnWithRoute(_departure, _destination, _takeoff, _landing, _live
|
||||
-- Create a flightgroup object.
|
||||
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
|
||||
|
||||
local _self=self
|
||||
-- No automatic despawning if group gets stuck.
|
||||
flightgroup.stuckDespawn=false
|
||||
|
||||
|
||||
--- 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 flightgroup=Flightgroup --Ops.FlightGroup#FLIGHTGROUP
|
||||
|
||||
local wp=waypoint.uid
|
||||
|
||||
-- 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.
|
||||
-- * calls _ATCRegisterFlight at holding waypoint ==> now in OnAfterHolding
|
||||
@ -2217,6 +2222,10 @@ function RAT:_SpawnWithRoute(_departure, _destination, _takeoff, _landing, _live
|
||||
-- * sets status
|
||||
RAT._WaypointFunction(group, self, waypoint.uid)
|
||||
|
||||
if waypoint.uid==3 then
|
||||
--flightgroup:SelfDestruction(Delay,ExplosionPower,ElementName)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- Function called when passing the final waypoint
|
||||
@ -2242,7 +2251,23 @@ function RAT:_SpawnWithRoute(_departure, _destination, _takeoff, _landing, _live
|
||||
end
|
||||
self:_ATCRegisterFlight(groupname, timer.getTime())
|
||||
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
|
||||
|
||||
@ -2297,24 +2322,8 @@ function RAT:_SpawnWithRoute(_departure, _destination, _takeoff, _landing, _live
|
||||
ratcraft.waypoints=waypoints
|
||||
ratcraft.airborne=group:InAir()
|
||||
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.
|
||||
ratcraft.P0=group:GetCoordinate()
|
||||
ratcraft.Pnow=group:GetCoordinate()
|
||||
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)
|
||||
end
|
||||
|
||||
--- Respawn a group.
|
||||
--- Respawn a group. The original group is despawned and a new group is spawed.
|
||||
-- @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 #number delay Delay before respawn
|
||||
function RAT:_Respawn(index, lastpos, delay)
|
||||
-- @param #number delay Delay before respawn in seconds.
|
||||
function RAT:_Respawn(group, lastpos, delay)
|
||||
|
||||
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
|
||||
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()))
|
||||
else
|
||||
self:E(self.lid..string.format("ERROR: group is nil in _Respawn!"))
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Ratcraft object
|
||||
local ratcraft=self.ratcraft[index] --#RAT.RatCraft
|
||||
-- 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.
|
||||
local departure=ratcraft.departure
|
||||
local destination=ratcraft.destination
|
||||
local destination=ratcraft.destination --Wrapper.Airbase#AIRBASE
|
||||
local takeoff=ratcraft.takeoff
|
||||
local landing=ratcraft.landing
|
||||
local livery=ratcraft.livery
|
||||
@ -2403,7 +2420,9 @@ function RAT:_Respawn(index, lastpos, delay)
|
||||
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
|
||||
if self.continuejourney or self.commute then
|
||||
for _,_element in pairs(flightgroup.elements) do
|
||||
local element=_element --Ops.OpsGroup#OPSGROUP.Element
|
||||
|
||||
@ -2419,19 +2438,13 @@ function RAT:_Respawn(index, lastpos, delay)
|
||||
self:E(self.lid..string.format("WARNING: Element %s did NOT have a not parking spot!", tostring(element.name)))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Despawn flight group
|
||||
flightgroup:Despawn(0, true)
|
||||
flightgroup:__Stop(0.1)
|
||||
|
||||
|
||||
-- This is usually done in _Despawn
|
||||
ratcraft.group=nil
|
||||
ratcraft.status="Dead"
|
||||
self.ratcraft[index]=nil
|
||||
-- Despawn old group.
|
||||
self:_Despawn(ratcraft.group)
|
||||
|
||||
local _departure=nil
|
||||
local _destination=nil
|
||||
local _destination=nil --Wrapper.Airbase#AIRBASE
|
||||
local _takeoff=nil
|
||||
local _landing=nil
|
||||
local _livery=nil
|
||||
@ -2585,6 +2598,76 @@ function RAT:_Respawn(index, lastpos, delay)
|
||||
|
||||
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.
|
||||
@ -3582,14 +3665,6 @@ function RAT:Status(message, forID)
|
||||
|
||||
self:T(self.lid.."Checking status")
|
||||
|
||||
-- Optional arguments.
|
||||
if message==nil then
|
||||
message=false
|
||||
end
|
||||
if forID==nil then
|
||||
forID=false
|
||||
end
|
||||
|
||||
-- Current time.
|
||||
local Tnow=timer.getTime()
|
||||
|
||||
@ -3597,14 +3672,15 @@ function RAT:Status(message, forID)
|
||||
local nalive=0
|
||||
|
||||
-- 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)))
|
||||
|
||||
-- Get 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
|
||||
|
||||
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 fuel=group:GetFuel()*100.0
|
||||
local airborne=group:InAir()
|
||||
local coords=group:GetCoordinate() or group:GetVec3()
|
||||
local alt=1000
|
||||
if coords then
|
||||
alt=coords.y or 1000
|
||||
end
|
||||
--local vel=group:GetVelocityKMH()
|
||||
local coords=group:GetCoordinate()
|
||||
local alt=coords~=nil and coords.y or 1000
|
||||
local departure=ratcraft.departure:GetName()
|
||||
local destination=ratcraft.destination:GetName()
|
||||
local type=self.aircraft.type
|
||||
local status=ratcraft.status
|
||||
local active=ratcraft.active
|
||||
local Nunits=ratcraft.nunits -- group:GetSize()
|
||||
local Nunits=ratcraft.nunits
|
||||
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.
|
||||
local Pn=coords
|
||||
local Dtravel=Pn:Get2DDistance(ratcraft["Pnow"])
|
||||
ratcraft["Pnow"]=Pn
|
||||
local Pnow=coords
|
||||
local Dtravel=Pnow:Get2DDistance(ratcraft.Pnow)
|
||||
ratcraft.Pnow=Pnow
|
||||
|
||||
-- Add up the travelled distance.
|
||||
ratcraft["Distance"]=ratcraft["Distance"]+Dtravel
|
||||
ratcraft.Distance=ratcraft.Distance+Dtravel
|
||||
|
||||
-- Distance remaining to destination.
|
||||
local Ddestination=Pn:Get2DDistance(ratcraft.destination:GetCoordinate())
|
||||
local Ddestination=Pnow:Get2DDistance(ratcraft.destination:GetCoordinate())
|
||||
|
||||
-- Status report.
|
||||
if (forID and spawnindex==forID) or (not forID) then
|
||||
@ -3737,56 +3735,32 @@ function RAT:Status(message, forID)
|
||||
text=text..string.format("Fuel = %3.0f %%\n", fuel)
|
||||
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("Speed = %i km/h\n", vel)
|
||||
text=text..string.format("Distance travelled = %6.1f km\n", ratcraft["Distance"]/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
|
||||
text=text..string.format("Distance to dest = %6.1f km", Ddestination/1000)
|
||||
self:T(self.lid..text)
|
||||
if message then
|
||||
MESSAGE:New(text, 20):ToAll()
|
||||
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.
|
||||
if ratcraft.despawnme then
|
||||
|
||||
local text=string.format("Flight %s will be despawned NOW!", self.alias)
|
||||
self:T(self.lid..text)
|
||||
if self.norespawn or self.respawn_after_takeoff then
|
||||
|
||||
-- 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.
|
||||
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)
|
||||
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
|
||||
|
||||
@ -4164,9 +4138,7 @@ function RAT:_OnLand(EventData)
|
||||
self:T(self.lid..text)
|
||||
|
||||
-- Respawn group.
|
||||
local idx=self:GetSpawnIndexFromGroup(SpawnGroup)
|
||||
local coord=SpawnGroup:GetCoordinate()
|
||||
self:_Respawn(idx, coord)
|
||||
self:_Respawn(SpawnGroup)
|
||||
end
|
||||
|
||||
end
|
||||
@ -4215,9 +4187,7 @@ function RAT:_OnEngineShutdown(EventData)
|
||||
self:T(self.lid..text)
|
||||
|
||||
-- Respawn group.
|
||||
local idx=self:GetSpawnIndexFromGroup(SpawnGroup)
|
||||
local coord=SpawnGroup:GetCoordinate()
|
||||
self:_Respawn(idx, coord, 3)
|
||||
self:_Respawn(SpawnGroup, nil, 3)
|
||||
|
||||
else
|
||||
|
||||
@ -4383,12 +4353,8 @@ function RAT:_OnCrash(EventData)
|
||||
-- Debug info.
|
||||
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.
|
||||
self:_Respawn(idx, coord)
|
||||
self:_Respawn(SpawnGroup)
|
||||
end
|
||||
|
||||
else
|
||||
@ -4404,117 +4370,6 @@ function RAT:_OnCrash(EventData)
|
||||
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.
|
||||
-- @param #RAT self
|
||||
@ -4673,6 +4528,11 @@ function RAT:_Waypoint(index, description, Type, Coord, Speed, Altitude, Airport
|
||||
self:T(self.lid.."Unknown Airport category in _Waypoint()!")
|
||||
end
|
||||
end
|
||||
|
||||
if false then
|
||||
|
||||
-- TODO: Disable the tasks as this is done by FLIGHTGROUP now. Delete when working
|
||||
|
||||
-- properties
|
||||
RoutePoint.properties = {
|
||||
["vnav"] = 1,
|
||||
@ -4697,6 +4557,8 @@ function RAT:_Waypoint(index, description, Type, Coord, Speed, Altitude, Airport
|
||||
|
||||
RoutePoint.task.params.tasks = TaskCombo
|
||||
|
||||
end
|
||||
|
||||
-- Return waypoint.
|
||||
return RoutePoint
|
||||
end
|
||||
@ -4846,6 +4708,7 @@ function RAT._WaypointFunction(group, rat, wp)
|
||||
end
|
||||
end
|
||||
|
||||
-- TODO: Move this to OnAfter Final Waypoint
|
||||
if wp==WPfinal then
|
||||
text=string.format("Flight %s arrived at final destination %s.", group:GetName(), destination)
|
||||
MESSAGE:New(text, 10):ToAllIf(rat.reportstatus)
|
||||
@ -6013,8 +5876,8 @@ function RAT:_ATCClearForLanding(airportname, flightname)
|
||||
-- Debug message.
|
||||
BASE:I(RAT.id..string.format("ATC %s: Flight %s cleared for landing", airportname, flightname))
|
||||
|
||||
if string.find(flight,"#") then
|
||||
flight = string.match(flight,"^(.+)#")
|
||||
if string.find(flightname,"#") then
|
||||
flightname = string.match(flightname,"^(.+)#")
|
||||
end
|
||||
local text=string.format("ATC %s: Flight %s you are cleared for landing.", airportname, flightname)
|
||||
MESSAGE:New(text, 10):ToAllIf(RAT.ATC.messages)
|
||||
|
||||
@ -1260,6 +1260,9 @@ function FLIGHTGROUP:Status()
|
||||
-- Check damage.
|
||||
self:_CheckDamage()
|
||||
|
||||
-- Check if stuck while taxiing.
|
||||
self:_CheckStuck()
|
||||
|
||||
-- Get current mission (if any).
|
||||
local mission=self:GetMissionCurrent()
|
||||
|
||||
@ -1627,6 +1630,9 @@ function FLIGHTGROUP:Status()
|
||||
if not mission then
|
||||
self.Twaiting=nil
|
||||
self.dTwait=nil
|
||||
|
||||
-- Check if group is done.
|
||||
-- TODO: Not sure why I introduced this here.
|
||||
self:_CheckGroupDone()
|
||||
end
|
||||
|
||||
@ -2140,6 +2146,10 @@ function FLIGHTGROUP:onafterSpawned(From, Event, To)
|
||||
|
||||
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.
|
||||
self:SwitchROE(self.option.ROE)
|
||||
|
||||
@ -2740,6 +2750,7 @@ function FLIGHTGROUP:onafterOutOfMissilesAA(From, Event, To)
|
||||
if self.outofAAMrtb then
|
||||
-- Back to destination or home.
|
||||
local airbase=self.destbase or self.homebase
|
||||
self:T(self.lid.."Calling RTB in onafterOutOfMissilesAA")
|
||||
self:__RTB(-5, airbase)
|
||||
end
|
||||
end
|
||||
@ -2754,6 +2765,7 @@ function FLIGHTGROUP:onafterOutOfMissilesAG(From, Event, To)
|
||||
if self.outofAGMrtb then
|
||||
-- Back to destination or home.
|
||||
local airbase=self.destbase or self.homebase
|
||||
self:T(self.lid.."Calling RTB in onafterOutOfMissilesAG")
|
||||
self:__RTB(-5, airbase)
|
||||
end
|
||||
end
|
||||
@ -2843,8 +2855,8 @@ function FLIGHTGROUP:_CheckGroupDone(delay, waittime)
|
||||
-- Number of remaining tasks/missions?
|
||||
if nTasks==0 and nMissions==0 and nTransports==0 then
|
||||
|
||||
local destbase=self.destbase or self.homebase
|
||||
local destzone=self.destzone or self.homezone
|
||||
local destbase=self.destbase or self.homebase --Wrapper.Airbase#AIRBASE
|
||||
local destzone=self.destzone or self.homezone --Wrapper.Airbase#AIRBASE
|
||||
|
||||
-- Send flight to destination.
|
||||
if waittime then
|
||||
@ -2855,9 +2867,12 @@ 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:Arrived()
|
||||
else
|
||||
-- Only send RTB if current base is not yet the destination
|
||||
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
|
||||
elseif destzone then
|
||||
self:T(self.lid.."Passed Final WP and No current and/or future missions/tasks/transports ==> RTZ!")
|
||||
self:__RTZ(-0.1, destzone)
|
||||
@ -2984,6 +2999,7 @@ function FLIGHTGROUP:onbeforeRTB(From, Event, To, airbase, SpeedTo, SpeedHold)
|
||||
end
|
||||
|
||||
if Tsuspend and not allowed then
|
||||
self:T(self.lid.."Calling RTB in onbeforeRTB")
|
||||
self:__RTB(Tsuspend, airbase, SpeedTo, SpeedHold)
|
||||
end
|
||||
|
||||
@ -3364,7 +3380,7 @@ function FLIGHTGROUP:onafterWait(From, Event, To, Duration, Altitude, Speed)
|
||||
-- Set time stamp.
|
||||
self.Twaiting=timer.getAbsTime()
|
||||
|
||||
-- Max waiting
|
||||
-- Max waiting time in seconds.
|
||||
self.dTwait=Duration
|
||||
|
||||
end
|
||||
@ -3664,6 +3680,7 @@ function FLIGHTGROUP:onafterFuelLow(From, Event, To)
|
||||
|
||||
-- Send back to airbase.
|
||||
if airbase and self.fuellowrtb then
|
||||
self:T(self.lid.."Calling RTB in onafterFuelLow")
|
||||
self:RTB(airbase)
|
||||
--TODO: RTZ
|
||||
end
|
||||
@ -3688,6 +3705,7 @@ function FLIGHTGROUP:onafterFuelCritical(From, Event, To)
|
||||
local airbase=self.destbase or self.homebase
|
||||
|
||||
if airbase and self.fuelcriticalrtb and not self:IsGoing4Fuel() then
|
||||
self:T(self.lid.."Calling RTB in onafterFuelCritical")
|
||||
self:RTB(airbase)
|
||||
--TODO: RTZ
|
||||
end
|
||||
@ -4835,6 +4853,87 @@ function FLIGHTGROUP:_GetTerminal(_attribute, _category)
|
||||
return _terminal
|
||||
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
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
@ -118,6 +118,10 @@
|
||||
--
|
||||
-- @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.WeaponData weaponData Weapon data table with key=BitType.
|
||||
--
|
||||
@ -680,6 +684,7 @@ function OPSGROUP:New(group)
|
||||
self:AddTransition("*", "GotoWaypoint", "*") -- Group switches to a specific waypoint.
|
||||
|
||||
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("*", "DetectedUnitNew", "*") -- Add a newly detected unit to the detected units set.
|
||||
@ -1889,7 +1894,7 @@ end
|
||||
|
||||
--- Get current velocity of the group.
|
||||
-- @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.
|
||||
function OPSGROUP:GetVelocity(UnitName)
|
||||
|
||||
|
||||
@ -359,14 +359,15 @@ end
|
||||
-- @param #GROUP self
|
||||
-- @return DCS#Group The DCS Group.
|
||||
function GROUP:GetDCSObject()
|
||||
|
||||
-- Get DCS group.
|
||||
local DCSGroup = Group.getByName( self.GroupName )
|
||||
|
||||
if DCSGroup then
|
||||
return DCSGroup
|
||||
else
|
||||
env.error("ERROR: Could not get DCS group object!")
|
||||
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
|
||||
end
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user