From aac291c0c6eb7b83973e9226f5de03b4ebe2e5d1 Mon Sep 17 00:00:00 2001 From: Frank Date: Sat, 22 Aug 2020 00:09:36 +0200 Subject: [PATCH] Performance Optimizations --- Moose Development/Moose/Core/Base.lua | 3 + Moose Development/Moose/Core/Database.lua | 32 ++- Moose Development/Moose/Core/Point.lua | 15 +- Moose Development/Moose/Core/Zone.lua | 45 ++-- .../Moose/Functional/Warehouse.lua | 31 +-- Moose Development/Moose/Ops/OpsGroup.lua | 26 ++- .../Moose/Utilities/Profiler.lua | 16 +- Moose Development/Moose/Utilities/Utils.lua | 9 + Moose Development/Moose/Wrapper/Airbase.lua | 206 +++++++++++++----- .../Moose/Wrapper/Positionable.lua | 59 +++-- 10 files changed, 304 insertions(+), 138 deletions(-) diff --git a/Moose Development/Moose/Core/Base.lua b/Moose Development/Moose/Core/Base.lua index 827db5778..bdedec8a1 100644 --- a/Moose Development/Moose/Core/Base.lua +++ b/Moose Development/Moose/Core/Base.lua @@ -254,6 +254,8 @@ end -- @param #BASE Parent is the Parent class that the Child inherits from. -- @return #BASE Child function BASE:Inherit( Child, Parent ) + + -- Create child. local Child = routines.utils.deepCopy( Child ) if Child ~= nil then @@ -269,6 +271,7 @@ function BASE:Inherit( Child, Parent ) --Child:_SetDestructor() end + return Child end diff --git a/Moose Development/Moose/Core/Database.lua b/Moose Development/Moose/Core/Database.lua index 3b89132fc..6bd87bdd8 100644 --- a/Moose Development/Moose/Core/Database.lua +++ b/Moose Development/Moose/Core/Database.lua @@ -896,31 +896,25 @@ function DATABASE:_RegisterStatics() return self end ---- @param #DATABASE self +--- Register all world airbases. +-- @param #DATABASE self +-- @return #DATABASE self function DATABASE:_RegisterAirbases() - --[[ - local CoalitionsData = { AirbasesRed = coalition.getAirbases( coalition.side.RED ), AirbasesBlue = coalition.getAirbases( coalition.side.BLUE ), AirbasesNeutral = coalition.getAirbases( coalition.side.NEUTRAL ) } - for CoalitionId, CoalitionData in pairs( CoalitionsData ) do - for DCSAirbaseId, DCSAirbase in pairs( CoalitionData ) do - - local DCSAirbaseName = DCSAirbase:getName() - - self:T( { "Register Airbase:", DCSAirbaseName, DCSAirbase:getID() } ) - self:AddAirbase( DCSAirbaseName ) - end - end - ]] - for DCSAirbaseId, DCSAirbase in pairs(world.getAirbases()) do - local DCSAirbaseName = DCSAirbase:getName() + + -- Get the airbase name. + local DCSAirbaseName = DCSAirbase:getName() - -- This gives the incorrect value to be inserted into the airdromeID for DCS 2.5.6! - local airbaseID=DCSAirbase:getID() + -- This gave the incorrect value to be inserted into the airdromeID for DCS 2.5.6. Is fixed now. + local airbaseID=DCSAirbase:getID() - local airbase=self:AddAirbase( DCSAirbaseName ) + -- Add and register airbase. + local airbase=self:AddAirbase( DCSAirbaseName ) - self:I(string.format("Register Airbase: %s, getID=%d, GetID=%d (unique=%d)", DCSAirbaseName, DCSAirbase:getID(), airbase:GetID(), airbase:GetID(true))) + -- Debug output. + self:I(string.format("Register Airbase: %s, getID=%d, GetID=%d (unique=%d)", DCSAirbaseName, DCSAirbase:getID(), airbase:GetID(), airbase:GetID(true))) + end return self diff --git a/Moose Development/Moose/Core/Point.lua b/Moose Development/Moose/Core/Point.lua index efa40a584..34ebf940f 100644 --- a/Moose Development/Moose/Core/Point.lua +++ b/Moose Development/Moose/Core/Point.lua @@ -228,6 +228,7 @@ do -- COORDINATE -- @return #COORDINATE function COORDINATE:New( x, y, z ) + --env.info("FF COORDINATE New") local self = BASE:Inherit( self, BASE:New() ) -- #COORDINATE self.x = x self.y = y @@ -717,12 +718,18 @@ do -- COORDINATE --- Return the 2D distance in meters between the target COORDINATE and the COORDINATE. -- @param #COORDINATE self - -- @param #COORDINATE TargetCoordinate The target COORDINATE. + -- @param #COORDINATE TargetCoordinate The target COORDINATE. Can also be a DCS#Vec3. -- @return DCS#Distance Distance The distance in meters. function COORDINATE:Get2DDistance( TargetCoordinate ) - local TargetVec3 = TargetCoordinate:GetVec3() - local SourceVec3 = self:GetVec3() - return ( ( TargetVec3.x - SourceVec3.x ) ^ 2 + ( TargetVec3.z - SourceVec3.z ) ^ 2 ) ^ 0.5 + + local a={x=TargetCoordinate.x-self.x, y=0, z=TargetCoordinate.z-self.z} + + return UTILS.VecNorm(a) + + --local TargetVec3 = TargetCoordinate:GetVec3() + --local SourceVec3 = self:GetVec3() + + --return ( ( TargetVec3.x - SourceVec3.x ) ^ 2 + ( TargetVec3.z - SourceVec3.z ) ^ 2 ) ^ 0.5 end --- Returns the temperature in Degrees Celsius. diff --git a/Moose Development/Moose/Core/Zone.lua b/Moose Development/Moose/Core/Zone.lua index 8ef630eee..b5b83d2a1 100644 --- a/Moose Development/Moose/Core/Zone.lua +++ b/Moose Development/Moose/Core/Zone.lua @@ -56,6 +56,7 @@ --- @type ZONE_BASE -- @field #string ZoneName Name of the zone. -- @field #number ZoneProbability A value between 0 and 1. 0 = 0% and 1 = 100% probability. +-- @field Core.Point#COORDINATE Coordinate object of the zone. -- @extends Core.Fsm#FSM @@ -221,22 +222,6 @@ function ZONE_BASE:GetPointVec2() end ---- Returns a @{Core.Point#COORDINATE} of the zone. --- @param #ZONE_BASE self --- @return Core.Point#COORDINATE The Coordinate of the zone. -function ZONE_BASE:GetCoordinate() - self:F2( self.ZoneName ) - - local Vec2 = self:GetVec2() - - local Coordinate = COORDINATE:NewFromVec2( Vec2 ) - - self:T2( { Coordinate } ) - - return Coordinate -end - - --- Returns the @{DCS#Vec3} of the zone. -- @param #ZONE_BASE self -- @param DCS#Distance Height The height to add to the land height where the center of the zone is located. @@ -276,15 +261,27 @@ end -- @param DCS#Distance Height The height to add to the land height where the center of the zone is located. -- @return Core.Point#COORDINATE The Coordinate of the zone. function ZONE_BASE:GetCoordinate( Height ) --R2.1 - self:F2( self.ZoneName ) + self:F2(self.ZoneName) local Vec3 = self:GetVec3( Height ) - - local PointVec3 = COORDINATE:NewFromVec3( Vec3 ) - - self:T2( { PointVec3 } ) - return PointVec3 + if self.Coordinate then + + -- Update coordinates. + self.Coordinate.x=Vec3.x + self.Coordinate.y=Vec3.y + self.Coordinate.z=Vec3.z + + --env.info("FF GetCoordinate NEW for ZONE_BASE "..tostring(self.ZoneName)) + else + + -- Create a new coordinate object. + self.Coordinate=COORDINATE:NewFromVec3(Vec3) + + --env.info("FF GetCoordinate NEW for ZONE_BASE "..tostring(self.ZoneName)) + end + + return self.Coordinate end @@ -433,12 +430,16 @@ ZONE_RADIUS = { -- @param DCS#Distance Radius The radius of the zone. -- @return #ZONE_RADIUS self function ZONE_RADIUS:New( ZoneName, Vec2, Radius ) + + -- Inherit ZONE_BASE. local self = BASE:Inherit( self, ZONE_BASE:New( ZoneName ) ) -- #ZONE_RADIUS self:F( { ZoneName, Vec2, Radius } ) self.Radius = Radius self.Vec2 = Vec2 + --self.Coordinate=COORDINATE:NewFromVec2(Vec2) + return self end diff --git a/Moose Development/Moose/Functional/Warehouse.lua b/Moose Development/Moose/Functional/Warehouse.lua index 82d09a386..fc78fefe7 100644 --- a/Moose Development/Moose/Functional/Warehouse.lua +++ b/Moose Development/Moose/Functional/Warehouse.lua @@ -7521,13 +7521,6 @@ function WAREHOUSE:_FindParkingForAssets(airbase, assets) for i,unit in pairs(units) do local coord=COORDINATE:New(unit.x, unit.alt, unit.y) coords[unit.name]=coord - --[[ - local airbase=coord:GetClosestAirbase() - local _,TermID, dist, spot=coord:GetClosestParkingSpot(airbase) - if dist<=10 then - env.info(string.format("Found client %s on parking spot %d at airbase %s", unit.name, TermID, airbase:GetName())) - end - ]] end end return coords @@ -7538,6 +7531,12 @@ function WAREHOUSE:_FindParkingForAssets(airbase, assets) -- List of obstacles. local obstacles={} + + -- Check all clients. Clients dont change so we can put that out of the loop. + local clientcoords=_clients() + for clientname,_coord in pairs(clientcoords) do + table.insert(obstacles, {coord=_coord, size=15, name=clientname, type="client"}) + end -- Loop over all parking spots and get the currently present obstacles. -- How long does this take on very large airbases, i.e. those with hundereds of parking spots? Seems to be okay! @@ -7553,22 +7552,16 @@ function WAREHOUSE:_FindParkingForAssets(airbase, assets) -- Check all units. for _,_unit in pairs(_units) do local unit=_unit --Wrapper.Unit#UNIT - local _coord=unit:GetCoordinate() + local _coord=unit:GetVec3() local _size=self:_GetObjectSize(unit:GetDCSObject()) local _name=unit:GetName() table.insert(obstacles, {coord=_coord, size=_size, name=_name, type="unit"}) end - -- Check all clients. - local clientcoords=_clients() - for clientname,_coord in pairs(clientcoords) do - table.insert(obstacles, {coord=_coord, size=15, name=clientname, type="client"}) - end - -- Check all statics. for _,static in pairs(_statics) do - local _vec3=static:getPoint() - local _coord=COORDINATE:NewFromVec3(_vec3) + local _coord=static:getPoint() + --local _coord=COORDINATE:NewFromVec3(_vec3) local _name=static:getName() local _size=self:_GetObjectSize(static) table.insert(obstacles, {coord=_coord, size=_size, name=_name, type="static"}) @@ -7576,11 +7569,11 @@ function WAREHOUSE:_FindParkingForAssets(airbase, assets) -- Check all scenery. for _,scenery in pairs(_sceneries) do - local _vec3=scenery:getPoint() - local _coord=COORDINATE:NewFromVec3(_vec3) + local _coord=scenery:getPoint() + --local _coord=COORDINATE:NewFromVec3(_vec3) local _name=scenery:getTypeName() local _size=self:_GetObjectSize(scenery) - table.insert(obstacles,{coord=_coord, size=_size, name=_name, type="scenery"}) + table.insert(obstacles, {coord=_coord, size=_size, name=_name, type="scenery"}) end end diff --git a/Moose Development/Moose/Ops/OpsGroup.lua b/Moose Development/Moose/Ops/OpsGroup.lua index 229daab70..bf36b6cc6 100644 --- a/Moose Development/Moose/Ops/OpsGroup.lua +++ b/Moose Development/Moose/Ops/OpsGroup.lua @@ -49,6 +49,7 @@ -- @field #boolean detectionOn If true, detected units of the group are analyzed. -- @field Ops.Auftrag#AUFTRAG missionpaused Paused mission. -- +-- @field Core.Point#COORDINATE coordinate Current coordinate. -- @field Core.Point#COORDINATE position Position of the group at last status check. -- @field #number traveldist Distance traveled in meters. This is a lower bound! -- @field #number traveltime Time. @@ -481,15 +482,36 @@ function OPSGROUP:GetName() return self.groupname end +--- Get current 3D vector of the group. +-- @param #OPSGROUP self +-- @return DCS#Vec3 Vector with x,y,z components. +function OPSGROUP:GetVec3() + if self.group:IsAlive() then + self.group:GetVec3() + end + return nil +end + --- Get current coordinate of the group. -- @param #OPSGROUP self -- @return Core.Point#COORDINATE The coordinate (of the first unit) of the group. function OPSGROUP:GetCoordinate() - if self:IsAlive()~=nil then - return self.group:GetCoordinate() + + local vec3=self:GetVec3() + + if vec3 then + + self.coordinate=self.coordinate or COORDINATE:New(0,0,0) + + self.coordinate.x=vec3.x + self.coordinate.y=vec3.y + self.coordinate.z=vec3.z + + return self.coordinate else self:E(self.lid.."WARNING: Group is not alive. Cannot get coordinate!") end + return nil end diff --git a/Moose Development/Moose/Utilities/Profiler.lua b/Moose Development/Moose/Utilities/Profiler.lua index 76fee9dcc..78b4027b0 100644 --- a/Moose Development/Moose/Utilities/Profiler.lua +++ b/Moose Development/Moose/Utilities/Profiler.lua @@ -21,7 +21,8 @@ -- @field #number TstartGame Game start time timer.getTime(). -- @field #number TstartOS OS real start time os.clock. -- @field #boolean logUnknown Log unknown functions. Default is off. --- @field #number lowCpsThres Low calls per second threashold. Only write output if function has more calls per second than this value. +-- @field #number ThreshCPS Low calls per second threshold. Only write output if function has more calls per second than this value. +-- @field #number ThreshTtot Total time threshold. Only write output if total function CPU time is more than this value. -- @field #string fileNamePrefix Output file name prefix, e.g. "MooseProfiler". -- @field #string fileNameSuffix Output file name prefix, e.g. "txt" @@ -76,7 +77,7 @@ -- -- If you only want output for functions that are called more than X times per second, you can set -- --- PROFILER.lowCpsThres=1.5 +-- PROFILER.ThreshCPS=1.5 -- -- With this setting, only functions which are called more than 1.5 times per second are displayed. -- @@ -89,7 +90,8 @@ PROFILER = { fTimeTotal = {}, eventHandler = {}, logUnknown = false, - lowCpsThres = 0.0, + ThreshCPS = 0.0, + ThreshTtot = 0.005, fileNamePrefix = "MooseProfiler", fileNameSuffix = "txt" } @@ -147,7 +149,8 @@ function PROFILER.Start(Delay, Duration) else env.info(string.format("- Will be stopped when mission ends")) end - env.info(string.format("- Calls per second threshold %.3f/sec", PROFILER.lowCpsThres)) + env.info(string.format("- Calls per second threshold %.3f/sec", PROFILER.ThreshCPS)) + env.info(string.format("- Total function time threshold %.3f/sec", PROFILER.ThreshTtot)) env.info(string.format("- Output file \"%s\" in your DCS log file folder", PROFILER.getfilename())) env.info('###############################################################################') @@ -283,7 +286,10 @@ function PROFILER.showTable(data, f, runTimeGame) -- Calls per second. local cps=t.count/runTimeGame - if cps>=PROFILER.lowCpsThres then + local threshCPS=cps>=PROFILER.ThreshCPS + local threshTot=t.tm>=PROFILER.ThreshTtot + + if threshCPS and threshTot then -- Output local text=string.format("%30s: %8d calls %8.1f/sec - Time Total %8.3f sec (%.3f %%) %5.3f sec/call %s line %s", t.func, t.count, cps, t.tm, t.tm/runTimeGame*100, t.tm/t.count, tostring(t.src), tostring(t.line)) diff --git a/Moose Development/Moose/Utilities/Utils.lua b/Moose Development/Moose/Utilities/Utils.lua index 700e07475..bc7f32daa 100644 --- a/Moose Development/Moose/Utilities/Utils.lua +++ b/Moose Development/Moose/Utilities/Utils.lua @@ -191,21 +191,30 @@ end -- @param #table object The input table. -- @return #table Copy of the input table. UTILS.DeepCopy = function(object) + local lookup_table = {} + + -- Copy function. local function _copy(object) if type(object) ~= "table" then return object elseif lookup_table[object] then return lookup_table[object] end + local new_table = {} + lookup_table[object] = new_table + for index, value in pairs(object) do new_table[_copy(index)] = _copy(value) end + return setmetatable(new_table, getmetatable(object)) end + local objectreturn = _copy(object) + return objectreturn end diff --git a/Moose Development/Moose/Wrapper/Airbase.lua b/Moose Development/Moose/Wrapper/Airbase.lua index 234a92533..b246b621a 100644 --- a/Moose Development/Moose/Wrapper/Airbase.lua +++ b/Moose Development/Moose/Wrapper/Airbase.lua @@ -15,6 +15,15 @@ --- @type AIRBASE -- @field #string ClassName Name of the class, i.e. "AIRBASE". -- @field #table CategoryName Names of airbase categories. +-- @field #string AirbaseName Name of the airbase. +-- @field #number AirbaseID Airbase ID. +-- @field #number category Airbase category. +-- @field #table descriptors DCS descriptors. +-- @field #boolean isAirdrome Airbase is an airdrome. +-- @field #boolean isHelipad Airbase is a helipad. +-- @field #boolean isShip Airbase is a ship. +-- @field #table parking Parking spot data. +-- @field #table parkingByID Parking spot data table with ID as key. -- @field #number activerwyno Active runway number (forced). -- @extends Wrapper.Positionable#POSITIONABLE @@ -445,15 +454,44 @@ AIRBASE.TerminalType = { --- Create a new AIRBASE from DCSAirbase. -- @param #AIRBASE self -- @param #string AirbaseName The name of the airbase. --- @return Wrapper.Airbase#AIRBASE -function AIRBASE:Register( AirbaseName ) +-- @return #AIRBASE self +function AIRBASE:Register(AirbaseName) - local self = BASE:Inherit( self, POSITIONABLE:New( AirbaseName ) ) --#AIRBASE - self.AirbaseName = AirbaseName - self.AirbaseID = self:GetID(true) + -- Inherit everything from positionable. + local self=BASE:Inherit(self, POSITIONABLE:New(AirbaseName)) --#AIRBASE + + -- Set airbase name. + self.AirbaseName=AirbaseName + + -- Set airbase ID. + self.AirbaseID=self:GetID(true) + + -- Get descriptors. + self.descriptors=self:GetDesc() + + -- Category. + self.category=self.descriptors and self.descriptors.category or Airbase.Category.AIRDROME + + -- Set category. + if self.category==Airbase.Category.AIRDROME then + self.isAirdrome=true + elseif self.category==Airbase.Category.HELIPAD then + self.isHelipad=true + elseif self.category==Airbase.Category.SHIP then + self.isShip=true + else + self:E("ERROR: Unknown airbase category!") + end + + self:_InitParkingSpots() + local vec2=self:GetVec2() + + -- Init coordinate. + self:GetCoordinate() + if vec2 then - self.AirbaseZone = ZONE_RADIUS:New( AirbaseName, vec2, 2500 ) + self.AirbaseZone=ZONE_RADIUS:New( AirbaseName, vec2, 2500 ) else self:E(string.format("ERROR: Cound not get position Vec2 of airbase %s", AirbaseName)) end @@ -508,7 +546,9 @@ end -- @param #AIRBASE self -- @return DCS#Airbase DCS airbase object. function AIRBASE:GetDCSObject() - local DCSAirbase = Airbase.getByName( self.AirbaseName ) + + -- Get the DCS object. + local DCSAirbase = Airbase.getByName(self.AirbaseName) if DCSAirbase then return DCSAirbase @@ -533,7 +573,7 @@ function AIRBASE.GetAllAirbases(coalition, category) local airbases={} for _,_airbase in pairs(_DATABASE.AIRBASES) do local airbase=_airbase --#AIRBASE - if (coalition~=nil and airbase:GetCoalition()==coalition) or coalition==nil then + if coalition==nil or airbase:GetCoalition()==coalition then if category==nil or category==airbase:GetAirbaseCategory() then table.insert(airbases, airbase) end @@ -564,23 +604,7 @@ function AIRBASE:GetID(unique) local airbaseID=tonumber(DCSAirbase:getID()) local airbaseCategory=self:GetAirbaseCategory() - - --env.info(string.format("FF airbase=%s id=%s category=%s", tostring(AirbaseName), tostring(airbaseID), tostring(airbaseCategory))) - - -- No way AFIK to get the DCS version. So we check if the event exists. That should tell us if we are on DCS 2.5.6 or prior to that. - --[[ - if world.event.S_EVENT_KILL and world.event.S_EVENT_KILL>0 and airbaseCategory==Airbase.Category.AIRDROME then - - -- We have to take the key value of this loop! - airbaseID=DCSAirbaseId - - -- Now another quirk: for Caucasus, we need to add 11 to the key value to get the correct ID. See https://forums.eagle.ru/showpost.php?p=4210774&postcount=11 - if UTILS.GetDCSMap()==DCSMAP.Caucasus then - airbaseID=airbaseID+11 - end - end - ]] - + if AirbaseName==self.AirbaseName then if airbaseCategory==Airbase.Category.SHIP or airbaseCategory==Airbase.Category.HELIPAD then -- Ships get a negative sign as their unit number might be the same as the ID of another airbase. @@ -728,6 +752,69 @@ function AIRBASE:GetParkingSpotsCoordinates(termtype) return spots end +--- Get a table containing the coordinates, terminal index and terminal type of free parking spots at an airbase. +-- @param #AIRBASE self +-- @return#AIRBASE self +function AIRBASE:_InitParkingSpots() + + -- Get parking data of all spots (free or occupied) + local parkingdata=self:GetParkingData(false) + + -- Init table. + self.parking={} + self.parkingByID={} + + self.NparkingTotal=0 + self.NparkingX=0 + self.NparkingY=0 + + -- Put coordinates of parking spots into table. + for _,spot in pairs(parkingdata) do + + -- New parking spot. + local park={} --#AIRBASE.ParkingSpot + park.Vec3=spot.vTerminalPos + park.Coordinate=COORDINATE:NewFromVec3(spot.vTerminalPos) + park.DistToRwy=spot.fDistToRW + park.Free=nil + park.TerminalID=spot.Term_Index + park.TerminalID0=spot.Term_Index_0 + park.TerminalType=spot.Term_Type + park.TOAC=spot.TO_AC + + if park.TerminalID==AIRBASE.TerminalType.FighterAircraft then + + elseif park.TerminalID==AIRBASE.TerminalType.HelicopterOnly then + + elseif park.TerminalID==AIRBASE.TerminalType.HelicopterUsable then + + elseif park.TerminalID==AIRBASE.TerminalType.OpenBig then + + elseif park.TerminalID==AIRBASE.TerminalType.OpenMed then + + elseif park.TerminalID==AIRBASE.TerminalType.OpenMedOrBig then + + elseif park.TerminalID==AIRBASE.TerminalType.Runway then + + elseif park.TerminalID==AIRBASE.TerminalType.Shelter then + + end + + + self.parkingByID[park.TerminalID]=park + table.insert(self.parking, park) + end + + return self +end + +--- Get a table containing the coordinates, terminal index and terminal type of free parking spots at an airbase. +-- @param #AIRBASE self +-- @param #number TerminalID Terminal ID. +-- @return #AIRBASE.ParkingSpot Parking spot. +function AIRBASE:_GetParkingSpotByID(TerminalID) + return self.parkingByID[TerminalID] +end --- Get a table containing the coordinates, terminal index and terminal type of free parking spots at an airbase. -- @param #AIRBASE self @@ -737,6 +824,7 @@ function AIRBASE:GetParkingSpotsTable(termtype) -- Get parking data of all spots (free or occupied) local parkingdata=self:GetParkingData(false) + -- Get parking data of all free spots. local parkingfree=self:GetParkingData(true) @@ -753,16 +841,19 @@ function AIRBASE:GetParkingSpotsTable(termtype) -- Put coordinates of parking spots into table. local spots={} for _,_spot in pairs(parkingdata) do + if AIRBASE._CheckTerminalType(_spot.Term_Type, termtype) then - self:T2({_spot=_spot}) - local _free=_isfree(_spot) - local _coord=COORDINATE:NewFromVec3(_spot.vTerminalPos) - table.insert(spots, {Coordinate=_coord, TerminalID=_spot.Term_Index, TerminalType=_spot.Term_Type, TOAC=_spot.TO_AC, Free=_free, TerminalID0=_spot.Term_Index_0, DistToRwy=_spot.fDistToRW}) + + local spot=self:_GetParkingSpotByID(_spot.Term_Index) + + spot.Free=_isfree(_spot) -- updated + spot.TOAC=_spot.TO_AC -- updated + + table.insert(spots, spot) end + end - self:T2({ spots = spots } ) - return spots end @@ -781,8 +872,14 @@ function AIRBASE:GetFreeParkingSpotsTable(termtype, allowTOAC) for _,_spot in pairs(parkingfree) do if AIRBASE._CheckTerminalType(_spot.Term_Type, termtype) and _spot.Term_Index>0 then if (allowTOAC and allowTOAC==true) or _spot.TO_AC==false then - local _coord=COORDINATE:NewFromVec3(_spot.vTerminalPos) - table.insert(freespots, {Coordinate=_coord, TerminalID=_spot.Term_Index, TerminalType=_spot.Term_Type, TOAC=_spot.TO_AC, Free=true, TerminalID0=_spot.Term_Index_0, DistToRwy=_spot.fDistToRW}) + + local spot=self:_GetParkingSpotByID(_spot.Term_Index) + + spot.Free=true -- updated + spot.TOAC=_spot.TO_AC -- updated + + table.insert(freespots, spot) + end end end @@ -795,14 +892,10 @@ end -- @param #number TerminalID The terminal ID of the parking spot. -- @return #AIRBASE.ParkingSpot Table free parking spots. Table has the elements ".Coordinate, ".TerminalID", ".TerminalType", ".TOAC", ".Free", ".TerminalID0", ".DistToRwy". function AIRBASE:GetParkingSpotData(TerminalID) - self:F({TerminalID=TerminalID}) -- Get parking data. local parkingdata=self:GetParkingSpotsTable() - -- Debug output. - self:T2({parkingdata=parkingdata}) - for _,_spot in pairs(parkingdata) do local spot=_spot --#AIRBASE.ParkingSpot self:T({TerminalID=spot.TerminalID,TerminalType=spot.TerminalType}) @@ -1065,13 +1158,6 @@ function AIRBASE:CheckOnRunWay(group, radius, despawn) -- Get coordinates on runway. local runwaypoints=self:GetParkingSpotsCoordinates(AIRBASE.TerminalType.Runway) - -- Mark runway spawn points. - --[[ - for _i,_coord in pairs(runwaypoints) do - _coord:MarkToAll(string.format("runway %d",_i)) - end - ]] - -- Get units of group. local units=group:GetUnits() @@ -1118,22 +1204,34 @@ function AIRBASE:CheckOnRunWay(group, radius, despawn) return false end +--- Check if airbase is an airdrome. +-- @param #AIRBASE self +-- @return #boolean If true, airbase is an airdrome. +function AIRBASE:IsAirdrome() + return self.isAirdrome +end + +--- Check if airbase is a helipad. +-- @param #AIRBASE self +-- @return #boolean If true, airbase is a helipad. +function AIRBASE:IsHelipad() + return self.isHelipad +end + +--- Check if airbase is a ship. +-- @param #AIRBASE self +-- @return #boolean If true, airbase is a ship. +function AIRBASE:IsShip() + return self.isShip +end + --- Get category of airbase. -- @param #AIRBASE self -- @return #number Category of airbase from GetDesc().category. function AIRBASE:GetAirbaseCategory() - local desc=self:GetDesc() - local category=Airbase.Category.AIRDROME - - if desc and desc.category then - category=desc.category - else - self:E(string.format("ERROR: Cannot get category of airbase %s due to DCS 2.5.6 bug! Assuming it is an AIRDROME for now...", tostring(self.AirbaseName))) - end - return category + return self.category end - --- Helper function to check for the correct terminal type including "artificial" ones. -- @param #number Term_Type Termial type from getParking routine. -- @param #AIRBASE.TerminalType termtype Terminal type from AIRBASE.TerminalType enumerator. diff --git a/Moose Development/Moose/Wrapper/Positionable.lua b/Moose Development/Moose/Wrapper/Positionable.lua index be85454a3..e7c5dcdf9 100644 --- a/Moose Development/Moose/Wrapper/Positionable.lua +++ b/Moose Development/Moose/Wrapper/Positionable.lua @@ -15,6 +15,8 @@ -- @extends Wrapper.Identifiable#IDENTIFIABLE --- @type POSITIONABLE +-- @field Core.Point#COORDINATE coordinate Coordinate object. +-- @field Core.Point#POINT_VEC3 pointvec3 Point Vec3 object. -- @extends Wrapper.Identifiable#IDENTIFIABLE @@ -45,6 +47,8 @@ POSITIONABLE = { ClassName = "POSITIONABLE", PositionableName = "", + coordinate = nil, + pointvec3 = nil, } --- @field #POSITIONABLE.__ @@ -268,17 +272,29 @@ end -- @return Core.Point#POINT_VEC3 The 3D point vector of the POSITIONABLE. -- @return #nil The POSITIONABLE is not existing or alive. function POSITIONABLE:GetPointVec3() - self:F2( self.PositionableName ) local DCSPositionable = self:GetDCSObject() if DCSPositionable then - local PositionableVec3 = self:GetPositionVec3() - - local PositionablePointVec3 = POINT_VEC3:NewFromVec3( PositionableVec3 ) - self:T2( PositionablePointVec3 ) - return PositionablePointVec3 + -- Get 3D vector. + local PositionableVec3 = self:GetPositionVec3() + + if self.pointvec3 then + --env.info("FF GetCoordinate GOT for "..tostring(self.PositionableName)) + + -- Update vector. + self.pointvec3.x=PositionableVec3.x + self.pointvec3.y=PositionableVec3.y + self.pointvec3.z=PositionableVec3.z + + else + --env.info("FF GetCoordinate NEW for "..tostring(self.PositionableName)) + + self.pointvec3=POINT_VEC3:NewFromVec3(PositionableVec3) + end + + return self.pointvec3 end BASE:E( { "Cannot GetPointVec3", Positionable = self, Alive = self:IsAlive() } ) @@ -290,21 +306,38 @@ end -- @param Wrapper.Positionable#POSITIONABLE self -- @return Core.Point#COORDINATE The COORDINATE of the POSITIONABLE. function POSITIONABLE:GetCoordinate() - self:F2( self.PositionableName ) + -- Get DCS object. local DCSPositionable = self:GetDCSObject() if DCSPositionable then + + -- Get the current position. local PositionableVec3 = self:GetPositionVec3() - local PositionableCoordinate = COORDINATE:NewFromVec3( PositionableVec3 ) - PositionableCoordinate:SetHeading( self:GetHeading() ) - PositionableCoordinate:SetVelocity( self:GetVelocityMPS() ) + if self.coordinate then + --env.info("FF GetCoordinate GOT for "..tostring(self.PositionableName)) + + -- Update vector. + self.coordinate.x=PositionableVec3.x + self.coordinate.y=PositionableVec3.y + self.coordinate.z=PositionableVec3.z + + else + --env.info("FF GetCoordinate NEW for "..tostring(self.PositionableName)) + + self.coordinate=COORDINATE:NewFromVec3(PositionableVec3) + end + + + -- Set heading and velocity. + self.coordinate:SetHeading( self:GetHeading() ) + self.coordinate:SetVelocity( self:GetVelocityMPS() ) - self:T2( PositionableCoordinate ) - return PositionableCoordinate + return self.coordinate end + -- Error message. BASE:E( { "Cannot GetCoordinate", Positionable = self, Alive = self:IsAlive() } ) return nil @@ -1533,7 +1566,7 @@ end --- Returns true if the unit is within a @{Zone}. --- @param #STPOSITIONABLEATIC self +-- @param #POSITIONABLE self -- @param Core.Zone#ZONE_BASE Zone The zone to test. -- @return #boolean Returns true if the unit is within the @{Core.Zone#ZONE_BASE} function POSITIONABLE:IsInZone( Zone )