From ec85b42a388fef0cd8febae4d55fedced59b36d3 Mon Sep 17 00:00:00 2001 From: Frank Date: Sun, 18 Aug 2019 22:21:41 +0200 Subject: [PATCH] OPS 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. --- Moose Development/Moose/Ops/Airboss.lua | 167 ++++++++++++----- Moose Development/Moose/Ops/RescueHelo.lua | 25 ++- Moose Development/Moose/Wrapper/Group.lua | 199 +++++++++++---------- 3 files changed, 250 insertions(+), 141 deletions(-) diff --git a/Moose Development/Moose/Ops/Airboss.lua b/Moose Development/Moose/Ops/Airboss.lua index 960ea2510..e8a88ec21 100644 --- a/Moose Development/Moose/Ops/Airboss.lua +++ b/Moose Development/Moose/Ops/Airboss.lua @@ -48,11 +48,15 @@ -- -- 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 -- @@ -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,9 +3281,13 @@ 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() self.Corientation=self.carrier:GetOrientationX() @@ -3687,7 +3723,7 @@ function AIRBOSS:_CheckRecoveryTimes() -- Closed. recovery.OPEN=false - + -- Window just closed. recovery.OVER=true @@ -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 @@ -7796,6 +7838,14 @@ function AIRBOSS:_RemoveFlight(flight, completely) self:_RemoveFlightFromQueue(self.flights, flight) 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 @@ -12672,6 +12717,9 @@ end -- @param #AIRBOSS.PlayerData playerData Player data. 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 @@ -12735,7 +12783,7 @@ function AIRBOSS:_Debrief(playerData) -- Add LSO grade to player grades table. table.insert(self.playerscores[playerData.name], mygrade) - + -- Trigger grading event. self:LSOGrade(playerData, mygrade) @@ -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. @@ -14455,12 +14525,23 @@ function AIRBOSS:RadioTransmission(radio, call, loud, delay, interval, click, pi table.insert(self.RQLSO, transmission) 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 @@ -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. @@ -15797,6 +15879,11 @@ function AIRBOSS:_ResetPlayerStatus(_unitName) -- Remove flight from queues. Collapse marshal stack if necessary. -- 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) diff --git a/Moose Development/Moose/Ops/RescueHelo.lua b/Moose Development/Moose/Ops/RescueHelo.lua index 350722c50..0a040f32e 100644 --- a/Moose Development/Moose/Ops/RescueHelo.lua +++ b/Moose Development/Moose/Ops/RescueHelo.lua @@ -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) diff --git a/Moose Development/Moose/Wrapper/Group.lua b/Moose Development/Moose/Wrapper/Group.lua index a6f372e1a..8c855be45 100644 --- a/Moose Development/Moose/Wrapper/Group.lua +++ b/Moose Development/Moose/Wrapper/Group.lua @@ -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 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 self and self:IsAlive() then - 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 + -- Get closest airbase. Should be the one we are currently on. + local airbase=self:GetCoordinate():GetClosestAirbase() - 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 + 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 - SpawnPoint.type = GROUPTEMPLATE.Takeoff[Takeoff][1] -- type - SpawnPoint.action = GROUPTEMPLATE.Takeoff[Takeoff][2] -- action + -- Coordinate of the airbase. + local AirbaseCoord=airbase:GetCoordinate() - -- Get the units of the group. - local units=self:GetUnits() - - local x - local y - for UnitID=1,#units do + -- 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) - 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) + --Parkingspot:MarkToAll("parking spot") + self:T2(string.format("Closest parking spot distance = %s, terminal ID=%s", tostring(Distance), tostring(TermialID))) - -- Reset events. - self:ResetEvents() - - return self + -- 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("WARNING: GROUP is not alive!") end return nil