AIRBOSS v1.0.8
- Fixed bug that status reset after wave off causes a unitcorn grade.
- Optimized radio scheduler calls ==> leads to less mem consumtion according to collectgarbage("count").

RESCUEHELO v1.0.9
- Adjusted default follow time interval to 1.0 sec.
- Added SetFollowTimeInterval() function.
- Respawn after returned delayed by 5 sec.

GROUP
- Added nil check in RespawnAtCurrentAirbase() function.
This commit is contained in:
Frank 2019-08-18 22:21:41 +02:00
parent 97e1a65b52
commit ec85b42a38
3 changed files with 250 additions and 141 deletions

View File

@ -48,12 +48,16 @@
--
-- Heatblur's mighty F-14B Tomcat has been added (March 13th 2019) as well.
--
--
-- ## Discussion
--
-- If you have questions or suggestions, please visit the [MOOSE Discord](https://discord.gg/AeYAkHP) #ops-airboss channel.
-- There you also find an example mission and the necessary voice over sound files. Check out the **pinned messages**.
--
-- ## Example Missions
--
-- Example missions can be found [here](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/OPS%20-%20Airboss).
-- They contain the latest development Moose.lua file.
--
-- ## IMPORTANT
--
-- Some important restrictions (of DCS) you should be aware of:
@ -1671,6 +1675,7 @@ AIRBOSS.Difficulty={
-- @field #boolean showhints If true, show step hints.
-- @field #table trapsheet Groove data table recorded every 0.5 seconds.
-- @field #boolean trapon If true, save trap sheets.
-- @field #string debriefschedulerID Debrief scheduler ID.
-- @extends #AIRBOSS.FlightGroup
--- Main group level radio menu: F10 Other/Airboss.
@ -1683,7 +1688,7 @@ AIRBOSS.MenuF10Root=nil
--- Airboss class version.
-- @field #string version
AIRBOSS.version="1.0.7"
AIRBOSS.version="1.0.8"
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO list
@ -1944,7 +1949,7 @@ function AIRBOSS:New(carriername, alias)
self.Debug=true
BASE:TraceOnOff(true)
BASE:TraceClass(self.ClassName)
BASE:TraceLevel(1)
BASE:TraceLevel(3)
--self.dTstatus=0.1
end
@ -2265,6 +2270,29 @@ function AIRBOSS:New(carriername, alias)
-- @param #AIRBOSS.LSOgrade grade LSO grade.
--- Triggers the FSM event "LSOGrade". Called when the LSO grades a player
-- @function [parent=#AIRBOSS] LSOGrade
-- @param #AIRBOSS self
-- @param #AIRBOSS.PlayerData playerData Player Data.
-- @param #AIRBOSS.LSOgrade grade LSO grade.
--- Triggers the FSM event "LSOGrade". Delayed called when the LSO grades a player.
-- @function [parent=#AIRBOSS] __LSOGrade
-- @param #AIRBOSS self
-- @param #number delay Delay in seconds.
-- @param #AIRBOSS.PlayerData playerData Player Data.
-- @param #AIRBOSS.LSOgrade grade LSO grade.
--- On after "LSOGrade" user function. Called when the carrier passes a waypoint of its route.
-- @function [parent=#AIRBOSS] OnAfterLSOGrade
-- @param #AIRBOSS self
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To To state.
-- @param #AIRBOSS.PlayerData playerData Player Data.
-- @param #AIRBOSS.LSOgrade grade LSO grade.
--- Triggers the FSM event "Stop" that stops the airboss. Event handlers are stopped.
-- @function [parent=#AIRBOSS] Stop
-- @param #AIRBOSS self
@ -2494,7 +2522,8 @@ end
function AIRBOSS:CloseCurrentRecoveryWindow(delay)
if delay and delay>0 then
SCHEDULER:New(nil, self.CloseCurrentRecoveryWindow, {self}, delay)
--SCHEDULER:New(nil, self.CloseCurrentRecoveryWindow, {self}, delay)
self:ScheduleOnce(delay, self.CloseCurrentRecoveryWindow, self)
else
if self:IsRecovering() and self.recoverywindow and self.recoverywindow.OPEN then
self:RecoveryStop()
@ -2544,7 +2573,8 @@ function AIRBOSS:DeleteRecoveryWindow(window, delay)
if delay and delay>0 then
-- Delayed call.
SCHEDULER:New(nil, self.DeleteRecoveryWindow, {self, window}, delay)
--SCHEDULER:New(nil, self.DeleteRecoveryWindow, {self, window}, delay)
self:ScheduleOnce(delay, self.DeleteRecoveryWindow, self, window)
else
for i,_recovery in pairs(self.recoverytimes) do
@ -2964,7 +2994,8 @@ function AIRBOSS:SoundCheckLSO(delay)
if delay and delay>0 then
-- Delayed call.
SCHEDULER:New(nil, AIRBOSS.SoundCheckLSO, {self}, delay)
--SCHEDULER:New(nil, AIRBOSS.SoundCheckLSO, {self}, delay)
self:ScheduleOnce(delay, AIRBOSS.SoundCheckLSO, self)
else
@ -2999,7 +3030,8 @@ function AIRBOSS:SoundCheckMarshal(delay)
if delay and delay>0 then
-- Delayed call.
SCHEDULER:New(nil, AIRBOSS.SoundCheckMarshal, {self}, delay)
--SCHEDULER:New(nil, AIRBOSS.SoundCheckMarshal, {self}, delay)
self:ScheduleOnce(delay, AIRBOSS.SoundCheckMarshal, self)
else
@ -3249,8 +3281,12 @@ function AIRBOSS:onafterStart(From, Event, To)
self:_ActivateBeacons()
-- Schedule radio queue checks.
self.RQLid=self.radiotimer:Schedule(self, self._CheckRadioQueue, {self.RQLSO, "LSO"}, 1, 0.01)
self.RQMid=self.radiotimer:Schedule(self, self._CheckRadioQueue, {self.RQMarshal, "MARSHAL"}, 1, 0.01)
--self.RQLid=self.radiotimer:Schedule(nil, AIRBOSS._CheckRadioQueue, {self, self.RQLSO, "LSO"}, 1, 0.1)
--self.RQMid=self.radiotimer:Schedule(nil, AIRBOSS._CheckRadioQueue, {self, self.RQMarshal, "MARSHAL"}, 1, 0.1)
--self:I("FF: starting timer.scheduleFunction")
--timer.scheduleFunction(AIRBOSS._CheckRadioQueueT, {airboss=self, radioqueue=self.RQLSO, name="LSO"}, timer.getTime()+1)
--timer.scheduleFunction(AIRBOSS._CheckRadioQueueT, {airboss=self, radioqueue=self.RQMarshal, name="MARSHAL"}, timer.getTime()+1)
-- Initial carrier position and orientation.
self.Cposition=self:GetCoordinate()
@ -4023,6 +4059,8 @@ end
-- @param #string Event Event.
-- @param #string To To state.
function AIRBOSS:onafterStop(From, Event, To)
self:I(self.lid..string.format("Stopping airboss script."))
-- Unhandle events.
self:UnHandleEvent(EVENTS.Birth)
self:UnHandleEvent(EVENTS.Land)
@ -4032,6 +4070,8 @@ function AIRBOSS:onafterStop(From, Event, To)
self:UnHandleEvent(EVENTS.Ejection)
self:UnHandleEvent(EVENTS.PlayerLeaveUnit)
self:UnHandleEvent(EVENTS.MissionEnd)
self.CallScheduler:Clear()
end
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
@ -5848,7 +5888,8 @@ function AIRBOSS:_SetPlayerStep(playerData, step, delay)
if delay and delay>0 then
-- Delayed call.
SCHEDULER:New(nil, self._SetPlayerStep, {self, playerData, step}, delay)
--SCHEDULER:New(nil, self._SetPlayerStep, {self, playerData, step}, delay)
self:ScheduleOnce(delay, self._SetPlayerStep, self, playerData, step)
else
-- Check if player still exists after possible delay.
@ -7316,6 +7357,7 @@ function AIRBOSS:_InitPlayer(playerData, step)
playerData.TIG0=nil
playerData.wire=nil
playerData.flag=-100
playerData.debriefschedulerID=nil
-- Set us up on final if group name contains "Groove". But only for the first pass.
if playerData.group:GetName():match("Groove") and playerData.passes==0 then
@ -7797,6 +7839,14 @@ function AIRBOSS:_RemoveFlight(flight, completely)
else
-- Remove all grades until a final grade is reached.
local grades=self.playerscores[flight.name]
if grades and #grades>0 then
while #grades>0 and grades[#grades].finalscore==nil do
table.remove(grades, #grades)
end
end
-- Check if flight should be completely removed, e.g. after the player died or simply left the slot.
if completely then
@ -7806,15 +7856,6 @@ function AIRBOSS:_RemoveFlight(flight, completely)
-- Remove completely.
self:_RemoveFlightFromQueue(self.flights, flight)
-- Remove all grades until a final grade is reached.
local grades=self.playerscores[flight.name]
if grades and #grades>0 then
while #grades>0 and grades[#grades].finalscore==nil do
table.remove(grades, #grades)
end
end
-- Remove player from players table.
local playerdata=self.players[flight.name]
if playerdata then
@ -8005,7 +8046,8 @@ function AIRBOSS:_CheckPlayerStatus()
elseif playerData.step==AIRBOSS.PatternStep.DEBRIEF then
-- Debriefing in 5 seconds.
SCHEDULER:New(nil, self._Debrief, {self, playerData}, 5)
--SCHEDULER:New(nil, self._Debrief, {self, playerData}, 5)
playerData.debriefschedulerID=self:ScheduleOnce(5, self._Debrief, self, playerData)
-- Undefined status.
playerData.step=AIRBOSS.PatternStep.UNDEFINED
@ -8186,7 +8228,8 @@ function AIRBOSS:OnEventBirth(EventData)
self:_AddF10Commands(_unitName)
-- Delaying the new player for a second, because AI units of the flight would not be registered correctly.
SCHEDULER:New(nil, self._NewPlayer, {self, _unitName}, 1)
--SCHEDULER:New(nil, self._NewPlayer, {self, _unitName}, 1)
self:ScheduleOnce(1, self._NewPlayer, self, _unitName)
end
end
@ -8339,7 +8382,8 @@ function AIRBOSS:OnEventLand(EventData)
self:_SetPlayerStep(playerData, AIRBOSS.PatternStep.UNDEFINED)
-- Call trapped function in 1 second to make sure we did not bolter.
SCHEDULER:New(nil, self._Trapped, {self, playerData}, 1)
--SCHEDULER:New(nil, self._Trapped, {self, playerData}, 1)
self:ScheduleOnce(1, self._Trapped, self, playerData)
end
@ -10233,7 +10277,8 @@ function AIRBOSS:_Trapped(playerData)
end
-- Call function again and check if converged or back in air.
SCHEDULER:New(nil, self._Trapped, {self, playerData}, 0.1)
--SCHEDULER:New(nil, self._Trapped, {self, playerData}, 0.1)
self:ScheduleOnce(0.1, self._Trapped, self, playerData)
return
end
@ -12673,6 +12718,9 @@ end
function AIRBOSS:_Debrief(playerData)
self:F(self.lid..string.format("Debriefing of player %s.", playerData.name))
-- Delete scheduler ID.
playerData.debriefschedulerID=nil
-- Switch attitude monitor off if on.
playerData.attitudemonitor=false
@ -14299,6 +14347,14 @@ end
-- RADIO MESSAGE Functions
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Function called by DCS timer. Unused.
-- @param #table param Parameters.
-- @param #number time Time.
function AIRBOSS._CheckRadioQueueT(param, time)
AIRBOSS._CheckRadioQueue(param.airboss, param.radioqueue, param.name)
return time+0.05
end
--- Radio queue item.
-- @type AIRBOSS.Radioitem
-- @field #number Tplay Abs time when transmission should be played.
@ -14315,37 +14371,50 @@ end
-- @param #string name Name of the queue.
function AIRBOSS:_CheckRadioQueue(radioqueue, name)
--env.info(string.format("FF %s #radioqueue %d", name, #radioqueue))
-- Check if queue is empty.
if #radioqueue==0 then
if name=="LSO" then
self:T(self.lid..string.format("Stopping LSO radio queue."))
self.radiotimer:Stop(self.RQLid)
self.RQLid=nil
elseif name=="MARSHAL" then
self:T(self.lid..string.format("Stopping Marshal radio queue."))
self.radiotimer:Stop(self.RQMid)
self.RQMid=nil
end
return
end
-- Get current abs time.
local time=timer.getAbsTime()
local _time=timer.getAbsTime()
local playing=false
local next=nil --#AIRBOSS.Radioitem
local remove=nil
local _remove=nil
for i,_transmission in ipairs(radioqueue) do
local transmission=_transmission --#AIRBOSS.Radioitem
-- Check if transmission time has passed.
if time>=transmission.Tplay then
if _time>=transmission.Tplay then
-- Check if transmission is currently playing.
if transmission.isplaying then
-- Check if transmission is finished.
if time>=transmission.Tstarted+transmission.call.duration then
if _time>=transmission.Tstarted+transmission.call.duration then
-- Transmission over.
transmission.isplaying=false
remove=i
_remove=i
if transmission.radio.alias=="LSO" then
self.TQLSO=time
self.TQLSO=_time
elseif transmission.radio.alias=="MARSHAL" then
self.TQMarshal=time
self.TQMarshal=_time
end
else -- still playing
@ -14375,7 +14444,7 @@ function AIRBOSS:_CheckRadioQueue(radioqueue, name)
else
if time-Tlast>=transmission.interval then
if _time-Tlast>=transmission.interval then
next=transmission
else
@ -14400,14 +14469,15 @@ function AIRBOSS:_CheckRadioQueue(radioqueue, name)
if next~=nil and not playing then
self:Broadcast(next.radio, next.call, next.loud)
next.isplaying=true
next.Tstarted=time
next.Tstarted=_time
end
-- Remove completed calls from queue.
if remove then
table.remove(radioqueue, remove)
if _remove then
table.remove(radioqueue, _remove)
end
return
end
--- Add Radio transmission to radio queue.
@ -14456,12 +14526,23 @@ function AIRBOSS:RadioTransmission(radio, call, loud, delay, interval, click, pi
caller="LSOCall"
-- Schedule radio queue checks.
if not self.RQLid then
self:T(self.lid..string.format("Starting LSO radio queue."))
self.RQLid=self.radiotimer:Schedule(nil, AIRBOSS._CheckRadioQueue, {self, self.RQLSO, "LSO"}, 0.02, 0.05)
end
elseif radio.alias=="MARSHAL" then
table.insert(self.RQMarshal, transmission)
caller="MarshalCall"
if not self.RQMid then
self:T(self.lid..string.format("Starting Marhal radio queue."))
self.RQMid=self.radiotimer:Schedule(nil, AIRBOSS._CheckRadioQueue, {self, self.RQMarshal, "MARSHAL"}, 0.02, 0.05)
end
end
-- Append radio click sound at the end of the transmission.
@ -14743,7 +14824,8 @@ function AIRBOSS:MessageToPlayer(playerData, message, sender, receiver, duration
if delay and delay>0 then
-- Delayed call.
SCHEDULER:New(nil, self.MessageToPlayer, {self, playerData, message, sender, receiver, duration, clear}, delay)
--SCHEDULER:New(nil, self.MessageToPlayer, {self, playerData, message, sender, receiver, duration, clear}, delay)
self:ScheduleOnce(delay, self.MessageToPlayer, self, playerData, message, sender, receiver, duration, clear)
else
-- Wait until previous sound finished.
@ -15798,6 +15880,11 @@ function AIRBOSS:_ResetPlayerStatus(_unitName)
-- Section members are removed from the Spinning queue. If flight is member, he is removed from the section.
self:_RemoveFlight(playerData)
-- Stop pending debrief scheduler.
if playerData.debriefschedulerID and self.Scheduler then
self.Scheduler:Stop(playerData.debriefschedulerID)
end
-- Initialize player data.
self:_InitPlayer(playerData)

View File

@ -57,6 +57,7 @@
-- @field #string alias Alias of the spawn group.
-- @field #number uid Unique ID of this helo.
-- @field #number modex Tail number of the helo.
-- @field #number dtFollow Follow time update interval in seconds. Default 1.0 sec.
-- @extends Core.Fsm#FSM
--- Rescue Helo
@ -227,6 +228,7 @@ RESCUEHELO = {
alias = nil,
uid = 0,
modex = nil,
dtFollow = nil,
}
--- Unique ID (global).
@ -235,7 +237,7 @@ _RESCUEHELOID=0
--- Class version.
-- @field #string version
RESCUEHELO.version="1.0.8"
RESCUEHELO.version="1.0.9"
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO list
@ -303,6 +305,7 @@ function RESCUEHELO:New(carrierunit, helogroupname)
self:SetRescueZone()
self:SetRescueHoverSpeed()
self:SetRescueDuration()
self:SetFollowTimeInterval()
self:SetRescueStopBoatOff()
-- Some more.
@ -644,6 +647,15 @@ function RESCUEHELO:SetModex(modex)
return self
end
--- Set follow time update interval.
-- @param #RESCUEHELO self
-- @param #number dt Time interval in seconds. Default 1.0 sec.
-- @return #RESCUEHELO self
function RESCUEHELO:SetFollowTimeInterval(dt)
self.dtFollow=dt or 1.0
return self
end
--- Use an uncontrolled aircraft already present in the mission rather than spawning a new helo as initial rescue helo.
-- This can be useful when interfaced with, e.g., a warehouse.
-- The group name is the one specified in the @{#RESCUEHELO.New} function.
@ -895,7 +907,7 @@ function RESCUEHELO:onafterStart(From, Event, To)
-- Use an uncontrolled aircraft group.
self.helo=GROUP:FindByName(self.helogroupname)
if self.helo:IsAlive() then
if self.helo and self.helo:IsAlive() then
-- Start uncontrolled group.
self.helo:StartUncontrolled()
@ -940,6 +952,9 @@ function RESCUEHELO:onafterStart(From, Event, To)
-- Formation parameters.
self.formation:FormationCenterWing(-self.offsetX, 50, math.abs(self.altitude), 50, self.offsetZ, 50)
-- Set follow time interval.
self.formation:SetFollowTimeInterval(self.dtFollow)
-- Formation mode.
self.formation:SetFlightModeFormation(self.helo)
@ -1005,7 +1020,7 @@ function RESCUEHELO:onafterStatus(From, Event, To)
else
-- Send helo back to base.
self:RTB()
self:RTB(self.airbase)
end
@ -1196,7 +1211,9 @@ function RESCUEHELO:onafterReturned(From, Event, To, airbase)
self.helo:InitModex(self.modex)
-- Respawn helo at current airbase.
self.helo:RespawnAtCurrentAirbase()
if self.helo and self.helo:IsAlive() then
self:ScheduleOnce(5, self.helo.RespawnAtCurrentAirbase, self.helo)
end
-- Restart the formation.
self:__Run(10)

View File

@ -1773,110 +1773,115 @@ end
function GROUP:RespawnAtCurrentAirbase(SpawnTemplate, Takeoff, Uncontrolled) -- R2.4
self:F2( { SpawnTemplate, Takeoff, Uncontrolled} )
-- Get closest airbase. Should be the one we are currently on.
local airbase=self:GetCoordinate():GetClosestAirbase()
if self and self:IsAlive() then
if airbase then
self:F2("Closest airbase = "..airbase:GetName())
-- Get closest airbase. Should be the one we are currently on.
local airbase=self:GetCoordinate():GetClosestAirbase()
if airbase then
self:F2("Closest airbase = "..airbase:GetName())
else
self:E("ERROR: could not find closest airbase!")
return nil
end
-- Takeoff type. Default hot.
Takeoff = Takeoff or SPAWN.Takeoff.Hot
-- Coordinate of the airbase.
local AirbaseCoord=airbase:GetCoordinate()
-- Spawn template.
SpawnTemplate = SpawnTemplate or self:GetTemplate()
if SpawnTemplate then
local SpawnPoint = SpawnTemplate.route.points[1]
-- These are only for ships.
SpawnPoint.linkUnit = nil
SpawnPoint.helipadId = nil
SpawnPoint.airdromeId = nil
-- Aibase id and category.
local AirbaseID = airbase:GetID()
local AirbaseCategory = airbase:GetDesc().category
if AirbaseCategory == Airbase.Category.SHIP or AirbaseCategory == Airbase.Category.HELIPAD then
SpawnPoint.linkUnit = AirbaseID
SpawnPoint.helipadId = AirbaseID
elseif AirbaseCategory == Airbase.Category.AIRDROME then
SpawnPoint.airdromeId = AirbaseID
end
SpawnPoint.type = GROUPTEMPLATE.Takeoff[Takeoff][1] -- type
SpawnPoint.action = GROUPTEMPLATE.Takeoff[Takeoff][2] -- action
-- Get the units of the group.
local units=self:GetUnits()
local x
local y
for UnitID=1,#units do
local unit=units[UnitID] --Wrapper.Unit#UNIT
-- Get closest parking spot of current unit. Note that we look for occupied spots since the unit is currently sitting on it!
local Parkingspot, TermialID, Distance=unit:GetCoordinate():GetClosestParkingSpot(airbase)
--Parkingspot:MarkToAll("parking spot")
self:T2(string.format("Closest parking spot distance = %s, terminal ID=%s", tostring(Distance), tostring(TermialID)))
-- Get unit coordinates for respawning position.
local uc=unit:GetCoordinate()
--uc:MarkToAll(string.format("re-spawnplace %s terminal %d", unit:GetName(), TermialID))
SpawnTemplate.units[UnitID].x = uc.x --Parkingspot.x
SpawnTemplate.units[UnitID].y = uc.z --Parkingspot.z
SpawnTemplate.units[UnitID].alt = uc.y --Parkingspot.y
SpawnTemplate.units[UnitID].parking = TermialID
SpawnTemplate.units[UnitID].parking_id = nil
--SpawnTemplate.units[UnitID].unitId=nil
end
--SpawnTemplate.groupId=nil
SpawnPoint.x = SpawnTemplate.units[1].x --x --AirbaseCoord.x
SpawnPoint.y = SpawnTemplate.units[1].y --y --AirbaseCoord.z
SpawnPoint.alt = SpawnTemplate.units[1].alt --AirbaseCoord:GetLandHeight()
SpawnTemplate.x = SpawnTemplate.units[1].x --x --AirbaseCoord.x
SpawnTemplate.y = SpawnTemplate.units[1].y --y --AirbaseCoord.z
-- Set uncontrolled state.
SpawnTemplate.uncontrolled=Uncontrolled
-- Set radio frequency and modulation.
if self.InitRespawnRadio then
SpawnTemplate.communication=self.InitRespawnRadio
end
if self.InitRespawnFreq then
SpawnTemplate.frequency=self.InitRespawnFreq
end
if self.InitRespawnModu then
SpawnTemplate.modulation=self.InitRespawnModu
end
-- Destroy old group.
self:Destroy(false)
-- Spawn new group.
_DATABASE:Spawn(SpawnTemplate)
-- Reset events.
self:ResetEvents()
return self
end
else
self:E("ERROR: could not find closest airbase!")
return nil
end
-- Takeoff type. Default hot.
Takeoff = Takeoff or SPAWN.Takeoff.Hot
-- Coordinate of the airbase.
local AirbaseCoord=airbase:GetCoordinate()
-- Spawn template.
SpawnTemplate = SpawnTemplate or self:GetTemplate()
if SpawnTemplate then
local SpawnPoint = SpawnTemplate.route.points[1]
-- These are only for ships.
SpawnPoint.linkUnit = nil
SpawnPoint.helipadId = nil
SpawnPoint.airdromeId = nil
-- Aibase id and category.
local AirbaseID = airbase:GetID()
local AirbaseCategory = airbase:GetDesc().category
if AirbaseCategory == Airbase.Category.SHIP or AirbaseCategory == Airbase.Category.HELIPAD then
SpawnPoint.linkUnit = AirbaseID
SpawnPoint.helipadId = AirbaseID
elseif AirbaseCategory == Airbase.Category.AIRDROME then
SpawnPoint.airdromeId = AirbaseID
end
SpawnPoint.type = GROUPTEMPLATE.Takeoff[Takeoff][1] -- type
SpawnPoint.action = GROUPTEMPLATE.Takeoff[Takeoff][2] -- action
-- Get the units of the group.
local units=self:GetUnits()
local x
local y
for UnitID=1,#units do
local unit=units[UnitID] --Wrapper.Unit#UNIT
-- Get closest parking spot of current unit. Note that we look for occupied spots since the unit is currently sitting on it!
local Parkingspot, TermialID, Distance=unit:GetCoordinate():GetClosestParkingSpot(airbase)
--Parkingspot:MarkToAll("parking spot")
self:T2(string.format("Closest parking spot distance = %s, terminal ID=%s", tostring(Distance), tostring(TermialID)))
-- Get unit coordinates for respawning position.
local uc=unit:GetCoordinate()
--uc:MarkToAll(string.format("re-spawnplace %s terminal %d", unit:GetName(), TermialID))
SpawnTemplate.units[UnitID].x = uc.x --Parkingspot.x
SpawnTemplate.units[UnitID].y = uc.z --Parkingspot.z
SpawnTemplate.units[UnitID].alt = uc.y --Parkingspot.y
SpawnTemplate.units[UnitID].parking = TermialID
SpawnTemplate.units[UnitID].parking_id = nil
--SpawnTemplate.units[UnitID].unitId=nil
end
--SpawnTemplate.groupId=nil
SpawnPoint.x = SpawnTemplate.units[1].x --x --AirbaseCoord.x
SpawnPoint.y = SpawnTemplate.units[1].y --y --AirbaseCoord.z
SpawnPoint.alt = SpawnTemplate.units[1].alt --AirbaseCoord:GetLandHeight()
SpawnTemplate.x = SpawnTemplate.units[1].x --x --AirbaseCoord.x
SpawnTemplate.y = SpawnTemplate.units[1].y --y --AirbaseCoord.z
-- Set uncontrolled state.
SpawnTemplate.uncontrolled=Uncontrolled
-- Set radio frequency and modulation.
if self.InitRespawnRadio then
SpawnTemplate.communication=self.InitRespawnRadio
end
if self.InitRespawnFreq then
SpawnTemplate.frequency=self.InitRespawnFreq
end
if self.InitRespawnModu then
SpawnTemplate.modulation=self.InitRespawnModu
end
-- Destroy old group.
self:Destroy(false)
-- Spawn new group.
_DATABASE:Spawn(SpawnTemplate)
-- Reset events.
self:ResetEvents()
return self
self:E("WARNING: GROUP is not alive!")
end
return nil