mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2026-08-16 07:56:35 +00:00
Merge branch 'master' into develop
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -440,20 +449,52 @@ AIRBASE.TerminalType = {
|
||||
-- @field Core.Point#COORDINATE position Position of runway start.
|
||||
-- @field Core.Point#COORDINATE endpoint End point of runway.
|
||||
|
||||
-- Registration.
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Registration
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- 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)
|
||||
|
||||
-- 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 self = BASE:Inherit( self, POSITIONABLE:New( AirbaseName ) ) --#AIRBASE
|
||||
self.AirbaseName = AirbaseName
|
||||
self.AirbaseID = self:GetID(true)
|
||||
local vec2=self:GetVec2()
|
||||
|
||||
-- Init coordinate.
|
||||
self:GetCoordinate()
|
||||
|
||||
if vec2 then
|
||||
self.AirbaseZone = ZONE_RADIUS:New( AirbaseName, vec2, 2500 )
|
||||
-- TODO: For ships we need a moving zone.
|
||||
self.AirbaseZone=ZONE_RADIUS:New( AirbaseName, vec2, 2500 )
|
||||
else
|
||||
self:E(string.format("ERROR: Cound not get position Vec2 of airbase %s", AirbaseName))
|
||||
end
|
||||
@@ -461,7 +502,9 @@ function AIRBASE:Register( AirbaseName )
|
||||
return self
|
||||
end
|
||||
|
||||
-- Reference methods.
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Reference methods
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Finds a AIRBASE from the _DATABASE using a DCSAirbase object.
|
||||
-- @param #AIRBASE self
|
||||
@@ -508,7 +551,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 +578,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
|
||||
@@ -543,6 +588,25 @@ function AIRBASE.GetAllAirbases(coalition, category)
|
||||
return airbases
|
||||
end
|
||||
|
||||
--- Get all airbase names of the current map. This includes ships and FARPS.
|
||||
-- @param DCS#Coalition coalition (Optional) Return only airbases belonging to the specified coalition. By default, all airbases of the map are returned.
|
||||
-- @param #number category (Optional) Return only airbases of a certain category, e.g. Airbase.Category.FARP
|
||||
-- @return #table Table containing all airbase names of the current map.
|
||||
function AIRBASE.GetAllAirbaseNames(coalition, category)
|
||||
|
||||
local airbases={}
|
||||
for airbasename,_airbase in pairs(_DATABASE.AIRBASES) do
|
||||
local airbase=_airbase --#AIRBASE
|
||||
if coalition==nil or airbase:GetCoalition()==coalition then
|
||||
if category==nil or category==airbase:GetAirbaseCategory() then
|
||||
table.insert(airbases, airbasename)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return airbases
|
||||
end
|
||||
|
||||
--- Get ID of the airbase.
|
||||
-- @param #AIRBASE self
|
||||
-- @param #boolean unique (Optional) If true, ships will get a negative sign as the unit ID might be the same as an airbase ID. Default off!
|
||||
@@ -565,22 +629,6 @@ function AIRBASE:GetID(unique)
|
||||
|
||||
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.
|
||||
@@ -598,6 +646,38 @@ function AIRBASE:GetID(unique)
|
||||
end
|
||||
|
||||
|
||||
--- Get category of airbase.
|
||||
-- @param #AIRBASE self
|
||||
-- @return #number Category of airbase from GetDesc().category.
|
||||
function AIRBASE:GetAirbaseCategory()
|
||||
return self.category
|
||||
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
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Parking
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Returns a table of parking data for a given airbase. If the optional parameter *available* is true only available parking will be returned, otherwise all parking at the base is returned. Term types have the following enumerated values:
|
||||
--
|
||||
-- * 16 : Valid spawn points on runway
|
||||
@@ -728,6 +808,58 @@ 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.NparkingTerminal={}
|
||||
for _,terminalType in pairs(AIRBASE.TerminalType) do
|
||||
self.NparkingTerminal[terminalType]=0
|
||||
end
|
||||
|
||||
-- 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
|
||||
|
||||
for _,terminalType in pairs(AIRBASE.TerminalType) do
|
||||
if self._CheckTerminalType(terminalType, park.TerminalType) then
|
||||
self.NparkingTerminal[terminalType]=self.NparkingTerminal[terminalType]+1
|
||||
end
|
||||
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 +869,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,15 +886,18 @@ 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})
|
||||
end
|
||||
end
|
||||
|
||||
self:T2({ spots = spots } )
|
||||
if AIRBASE._CheckTerminalType(_spot.Term_Type, termtype) then
|
||||
|
||||
local spot=self:_GetParkingSpotByID(_spot.Term_Index)
|
||||
|
||||
spot.Free=_isfree(_spot) -- updated
|
||||
spot.TOAC=_spot.TO_AC -- updated
|
||||
|
||||
table.insert(spots, spot)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
return spots
|
||||
end
|
||||
@@ -781,8 +917,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 +937,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})
|
||||
@@ -1041,99 +1179,6 @@ function AIRBASE:FindFreeParkingSpotForAircraft(group, terminaltype, scanradius,
|
||||
return validspots
|
||||
end
|
||||
|
||||
--- Function that checks if at leat one unit of a group has been spawned close to a spawn point on the runway.
|
||||
-- @param #AIRBASE self
|
||||
-- @param Wrapper.Group#GROUP group Group to be checked.
|
||||
-- @param #number radius Radius around the spawn point to be checked. Default is 50 m.
|
||||
-- @param #boolean despawn If true, the group is destroyed.
|
||||
-- @return #boolean True if group is within radius around spawn points on runway.
|
||||
function AIRBASE:CheckOnRunWay(group, radius, despawn)
|
||||
|
||||
-- Default radius.
|
||||
radius=radius or 50
|
||||
|
||||
-- We only check at real airbases (not FARPS or ships).
|
||||
if self:GetAirbaseCategory()~=Airbase.Category.AIRDROME then
|
||||
return false
|
||||
end
|
||||
|
||||
if group and group:IsAlive() then
|
||||
|
||||
-- Debug.
|
||||
self:T(string.format("%s, checking if group %s is on runway?",self:GetName(), group:GetName()))
|
||||
|
||||
-- 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()
|
||||
|
||||
-- Loop over units.
|
||||
for _,_unit in pairs(units) do
|
||||
|
||||
local unit=_unit --Wrapper.Unit#UNIT
|
||||
|
||||
-- Check if unit is alive and not in air.
|
||||
if unit and unit:IsAlive() and not unit:InAir() then
|
||||
self:T(string.format("%s, checking if unit %s is on runway?",self:GetName(), unit:GetName()))
|
||||
|
||||
-- Loop over runway spawn points.
|
||||
for _i,_coord in pairs(runwaypoints) do
|
||||
|
||||
-- Distance between unit and spawn pos.
|
||||
local dist=unit:GetCoordinate():Get2DDistance(_coord)
|
||||
|
||||
-- Mark unit spawn points for debugging.
|
||||
--unit:GetCoordinate():MarkToAll(string.format("unit %s distance to rwy %d = %d",unit:GetName(),_i, dist))
|
||||
|
||||
-- Check if unit is withing radius.
|
||||
if dist<radius then
|
||||
self:E(string.format("%s, unit %s of group %s was spawned on runway #%d. Distance %.1f < radius %.1f m. Despawn = %s.", self:GetName(), unit:GetName(), group:GetName(),_i, dist, radius, tostring(despawn)))
|
||||
--unit:FlareRed()
|
||||
if despawn then
|
||||
group:Destroy(true)
|
||||
end
|
||||
return true
|
||||
else
|
||||
self:T(string.format("%s, unit %s of group %s was NOT spawned on runway #%d. Distance %.1f > radius %.1f m. Despawn = %s.", self:GetName(), unit:GetName(), group:GetName(),_i, dist, radius, tostring(despawn)))
|
||||
--unit:FlareGreen()
|
||||
end
|
||||
|
||||
end
|
||||
else
|
||||
self:T(string.format("%s, checking if unit %s of group %s is on runway. Unit is NOT alive.",self:GetName(), unit:GetName(), group:GetName()))
|
||||
end
|
||||
end
|
||||
else
|
||||
self:T(string.format("%s, checking if group %s is on runway. Group is NOT alive.",self:GetName(), group:GetName()))
|
||||
end
|
||||
|
||||
return false
|
||||
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
|
||||
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.
|
||||
@@ -1180,6 +1225,10 @@ function AIRBASE._CheckTerminalType(Term_Type, termtype)
|
||||
return match
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Runway
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Get runways data. Only for airdromes!
|
||||
-- @param #AIRBASE self
|
||||
-- @param #number magvar (Optional) Magnetic variation in degrees.
|
||||
@@ -1194,41 +1243,124 @@ function AIRBASE:GetRunwayData(magvar, mark)
|
||||
return {}
|
||||
end
|
||||
|
||||
-- Get spawn points on runway.
|
||||
-- Get spawn points on runway. These can be used to determine the runway heading.
|
||||
local runwaycoords=self:GetParkingSpotsCoordinates(AIRBASE.TerminalType.Runway)
|
||||
|
||||
-- Debug: For finding the numbers of the spawn points belonging to each runway.
|
||||
if false then
|
||||
for i,_coord in pairs(runwaycoords) do
|
||||
local coord=_coord --Core.Point#COORDINATE
|
||||
coord:Translate(100, 0):MarkToAll("Runway i="..i)
|
||||
end
|
||||
end
|
||||
|
||||
-- Magnetic declination.
|
||||
magvar=magvar or UTILS.GetMagneticDeclination()
|
||||
|
||||
-- Number of runways.
|
||||
local N=#runwaycoords
|
||||
local dN=2
|
||||
local ex=false
|
||||
local N2=N/2
|
||||
local exception=false
|
||||
|
||||
-- Airbase name.
|
||||
local name=self:GetName()
|
||||
|
||||
|
||||
-- Exceptions
|
||||
if name==AIRBASE.Nevada.Jean_Airport or
|
||||
name==AIRBASE.Nevada.Creech_AFB or
|
||||
name==AIRBASE.PersianGulf.Abu_Dhabi_International_Airport or
|
||||
name==AIRBASE.PersianGulf.Dubai_Intl or
|
||||
name==AIRBASE.PersianGulf.Shiraz_International_Airport or
|
||||
name==AIRBASE.PersianGulf.Kish_International_Airport then
|
||||
name==AIRBASE.PersianGulf.Kish_International_Airport
|
||||
then
|
||||
|
||||
N=#runwaycoords/2
|
||||
dN=1
|
||||
ex=true
|
||||
-- 1-->4, 2-->3, 3-->2, 4-->1
|
||||
exception=1
|
||||
|
||||
elseif UTILS.GetDCSMap()==DCSMAP.Syria and N>=2 and
|
||||
name~=AIRBASE.Syria.Minakh and
|
||||
name~=AIRBASE.Syria.Damascus and
|
||||
name~=AIRBASE.Syria.Khalkhalah and
|
||||
name~=AIRBASE.Syria.Marj_Ruhayyil and
|
||||
name~=AIRBASE.Syria.Beirut_Rafic_Hariri then
|
||||
|
||||
-- 1-->3, 2-->4, 3-->1, 4-->2
|
||||
exception=2
|
||||
|
||||
end
|
||||
|
||||
local function f(i)
|
||||
|
||||
local j
|
||||
|
||||
if exception==1 then
|
||||
|
||||
j=N-(i+1) -- 1-->4, 2-->3
|
||||
|
||||
elseif exception==2 then
|
||||
|
||||
if i<=N2 then
|
||||
j=i+N2 -- 1-->3, 2-->4
|
||||
else
|
||||
j=i-N2 -- 3-->1, 4-->3
|
||||
end
|
||||
|
||||
else
|
||||
|
||||
if i%2==0 then
|
||||
j=i-1 -- even 2-->1, 4-->3
|
||||
else
|
||||
j=i+1 -- odd 1-->2, 3-->4
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- Special case where there is no obvious order.
|
||||
if name==AIRBASE.Syria.Beirut_Rafic_Hariri then
|
||||
if i==1 then
|
||||
j=3
|
||||
elseif i==2 then
|
||||
j=6
|
||||
elseif i==3 then
|
||||
j=1
|
||||
elseif i==4 then
|
||||
j=5
|
||||
elseif i==5 then
|
||||
j=4
|
||||
elseif i==6 then
|
||||
j=2
|
||||
end
|
||||
end
|
||||
|
||||
if name==AIRBASE.Syria.Ramat_David then
|
||||
if i==1 then
|
||||
j=4
|
||||
elseif i==2 then
|
||||
j=6
|
||||
elseif i==3 then
|
||||
j=5
|
||||
elseif i==4 then
|
||||
j=1
|
||||
elseif i==5 then
|
||||
j=3
|
||||
elseif i==6 then
|
||||
j=2
|
||||
end
|
||||
end
|
||||
|
||||
return j
|
||||
end
|
||||
|
||||
|
||||
for i=1,N,dN do
|
||||
for i=1,N do
|
||||
|
||||
local j=i+1
|
||||
if ex then
|
||||
--j=N+i
|
||||
j=#runwaycoords-i+1
|
||||
end
|
||||
-- Get the other spawn point coordinate.
|
||||
local j=f(i)
|
||||
|
||||
-- Coordinates of the two runway points.
|
||||
local c1=runwaycoords[i] --Core.Point#COORDINATES
|
||||
local c2=runwaycoords[j] --Core.Point#COORDINATES
|
||||
local c1=runwaycoords[i] --Core.Point#COORDINATE
|
||||
local c2=runwaycoords[j] --Core.Point#COORDINATE
|
||||
|
||||
-- Heading of runway.
|
||||
local hdg=c1:HeadingTo(c2)
|
||||
@@ -1245,11 +1377,11 @@ function AIRBASE:GetRunwayData(magvar, mark)
|
||||
runway.endpoint=c2
|
||||
|
||||
-- Debug info.
|
||||
self:T(string.format("Airbase %s: Adding runway id=%s, heading=%03d, length=%d m", self:GetName(), runway.idx, runway.heading, runway.length))
|
||||
self:I(string.format("Airbase %s: Adding runway id=%s, heading=%03d, length=%d m i=%d j=%d", self:GetName(), runway.idx, runway.heading, runway.length, i, j))
|
||||
|
||||
-- Debug mark
|
||||
if mark then
|
||||
runway.position:MarkToAll(string.format("Runway %s: true heading=%03d (magvar=%d), length=%d m", runway.idx, runway.heading, magvar, runway.length))
|
||||
runway.position:MarkToAll(string.format("Runway %s: true heading=%03d (magvar=%d), length=%d m, i=%d, j=%d", runway.idx, runway.heading, magvar, runway.length, i, j))
|
||||
end
|
||||
|
||||
-- Add runway.
|
||||
@@ -1257,38 +1389,6 @@ function AIRBASE:GetRunwayData(magvar, mark)
|
||||
|
||||
end
|
||||
|
||||
-- Get inverse runways
|
||||
local inverse={}
|
||||
for _,_runway in pairs(runways) do
|
||||
local r=_runway --#AIRBASE.Runway
|
||||
|
||||
local runway={} --#AIRBASE.Runway
|
||||
runway.heading=r.heading-180
|
||||
if runway.heading<0 then
|
||||
runway.heading=runway.heading+360
|
||||
end
|
||||
runway.idx=string.format("%02d", math.max(0, UTILS.Round((runway.heading-magvar)/10, 0)))
|
||||
runway.length=r.length
|
||||
runway.position=r.endpoint
|
||||
runway.endpoint=r.position
|
||||
|
||||
-- Debug info.
|
||||
self:T(string.format("Airbase %s: Adding runway id=%s, heading=%03d, length=%d m", self:GetName(), runway.idx, runway.heading, runway.length))
|
||||
|
||||
-- Debug mark
|
||||
if mark then
|
||||
runway.position:MarkToAll(string.format("Runway %s: true heading=%03d (magvar=%d), length=%d m", runway.idx, runway.heading, magvar, runway.length))
|
||||
end
|
||||
|
||||
-- Add runway.
|
||||
table.insert(inverse, runway)
|
||||
end
|
||||
|
||||
-- Add inverse runway.
|
||||
for _,runway in pairs(inverse) do
|
||||
table.insert(runways, runway)
|
||||
end
|
||||
|
||||
return runways
|
||||
end
|
||||
|
||||
@@ -1358,3 +1458,73 @@ function AIRBASE:GetActiveRunway(magvar)
|
||||
|
||||
return runways[iact]
|
||||
end
|
||||
|
||||
--- Function that checks if at leat one unit of a group has been spawned close to a spawn point on the runway.
|
||||
-- @param #AIRBASE self
|
||||
-- @param Wrapper.Group#GROUP group Group to be checked.
|
||||
-- @param #number radius Radius around the spawn point to be checked. Default is 50 m.
|
||||
-- @param #boolean despawn If true, the group is destroyed.
|
||||
-- @return #boolean True if group is within radius around spawn points on runway.
|
||||
function AIRBASE:CheckOnRunWay(group, radius, despawn)
|
||||
|
||||
-- Default radius.
|
||||
radius=radius or 50
|
||||
|
||||
-- We only check at real airbases (not FARPS or ships).
|
||||
if self:GetAirbaseCategory()~=Airbase.Category.AIRDROME then
|
||||
return false
|
||||
end
|
||||
|
||||
if group and group:IsAlive() then
|
||||
|
||||
-- Debug.
|
||||
self:T(string.format("%s, checking if group %s is on runway?",self:GetName(), group:GetName()))
|
||||
|
||||
-- Get coordinates on runway.
|
||||
local runwaypoints=self:GetParkingSpotsCoordinates(AIRBASE.TerminalType.Runway)
|
||||
|
||||
-- Get units of group.
|
||||
local units=group:GetUnits()
|
||||
|
||||
-- Loop over units.
|
||||
for _,_unit in pairs(units) do
|
||||
|
||||
local unit=_unit --Wrapper.Unit#UNIT
|
||||
|
||||
-- Check if unit is alive and not in air.
|
||||
if unit and unit:IsAlive() and not unit:InAir() then
|
||||
self:T(string.format("%s, checking if unit %s is on runway?",self:GetName(), unit:GetName()))
|
||||
|
||||
-- Loop over runway spawn points.
|
||||
for _i,_coord in pairs(runwaypoints) do
|
||||
|
||||
-- Distance between unit and spawn pos.
|
||||
local dist=unit:GetCoordinate():Get2DDistance(_coord)
|
||||
|
||||
-- Mark unit spawn points for debugging.
|
||||
--unit:GetCoordinate():MarkToAll(string.format("unit %s distance to rwy %d = %d",unit:GetName(),_i, dist))
|
||||
|
||||
-- Check if unit is withing radius.
|
||||
if dist<radius then
|
||||
self:E(string.format("%s, unit %s of group %s was spawned on runway #%d. Distance %.1f < radius %.1f m. Despawn = %s.", self:GetName(), unit:GetName(), group:GetName(),_i, dist, radius, tostring(despawn)))
|
||||
--unit:FlareRed()
|
||||
if despawn then
|
||||
group:Destroy(true)
|
||||
end
|
||||
return true
|
||||
else
|
||||
self:T(string.format("%s, unit %s of group %s was NOT spawned on runway #%d. Distance %.1f > radius %.1f m. Despawn = %s.", self:GetName(), unit:GetName(), group:GetName(),_i, dist, radius, tostring(despawn)))
|
||||
--unit:FlareGreen()
|
||||
end
|
||||
|
||||
end
|
||||
else
|
||||
self:T(string.format("%s, checking if unit %s of group %s is on runway. Unit is NOT alive.",self:GetName(), unit:GetName(), group:GetName()))
|
||||
end
|
||||
end
|
||||
else
|
||||
self:T(string.format("%s, checking if group %s is on runway. Group is NOT alive.",self:GetName(), group:GetName()))
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
@@ -243,8 +243,7 @@ end
|
||||
|
||||
--- Returns the initial health.
|
||||
-- @param #CONTROLLABLE self
|
||||
-- @return #number The controllable health value (unit or group average).
|
||||
-- @return #nil The controllable is not existing or alive.
|
||||
-- @return #number The controllable health value (unit or group average) or `nil` if the controllable does not exist.
|
||||
function CONTROLLABLE:GetLife0()
|
||||
self:F2( self.ControllableName )
|
||||
|
||||
@@ -296,7 +295,6 @@ end
|
||||
-- @return #nil The CONTROLLABLE is not existing or alive.
|
||||
function CONTROLLABLE:GetFuel()
|
||||
self:F( self.ControllableName )
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
@@ -1429,16 +1427,6 @@ end
|
||||
-- @return DCS#Task The DCS task structure.
|
||||
function CONTROLLABLE:TaskFireAtPoint( Vec2, Radius, AmmoCount, WeaponType )
|
||||
|
||||
-- FireAtPoint = {
|
||||
-- id = 'FireAtPoint',
|
||||
-- params = {
|
||||
-- point = Vec2,
|
||||
-- radius = Distance,
|
||||
-- expendQty = number,
|
||||
-- expendQtyEnabled = boolean,
|
||||
-- }
|
||||
-- }
|
||||
|
||||
local DCSTask = {
|
||||
id = 'FireAtPoint',
|
||||
params = {
|
||||
@@ -1458,7 +1446,6 @@ function CONTROLLABLE:TaskFireAtPoint( Vec2, Radius, AmmoCount, WeaponType )
|
||||
DCSTask.params.weaponType=WeaponType
|
||||
end
|
||||
|
||||
self:T3( { DCSTask } )
|
||||
return DCSTask
|
||||
end
|
||||
|
||||
|
||||
@@ -261,7 +261,9 @@ end
|
||||
-- @param #string GroupName The Group name
|
||||
-- @return #GROUP self
|
||||
function GROUP:Register( GroupName )
|
||||
|
||||
local self = BASE:Inherit( self, CONTROLLABLE:New( GroupName ) ) -- #GROUP
|
||||
|
||||
self.GroupName = GroupName
|
||||
|
||||
self:SetEventPriority( 4 )
|
||||
@@ -668,14 +670,15 @@ end
|
||||
-- @param #number UnitNumber The number of the UNIT wrapper class to be returned.
|
||||
-- @return Wrapper.Unit#UNIT The UNIT wrapper class.
|
||||
function GROUP:GetUnit( UnitNumber )
|
||||
self:F3( { self.GroupName, UnitNumber } )
|
||||
|
||||
local DCSGroup = self:GetDCSObject()
|
||||
|
||||
if DCSGroup then
|
||||
|
||||
local DCSUnit = DCSGroup:getUnit( UnitNumber )
|
||||
local UnitFound = UNIT:Find( DCSGroup:getUnit( UnitNumber ) )
|
||||
self:T2( UnitFound )
|
||||
|
||||
local UnitFound = UNIT:Find(DCSUnit)
|
||||
|
||||
return UnitFound
|
||||
end
|
||||
|
||||
@@ -688,13 +691,11 @@ end
|
||||
-- @param #number UnitNumber The number of the DCS Unit to be returned.
|
||||
-- @return DCS#Unit The DCS Unit.
|
||||
function GROUP:GetDCSUnit( UnitNumber )
|
||||
self:F3( { self.GroupName, UnitNumber } )
|
||||
|
||||
local DCSGroup = self:GetDCSObject()
|
||||
local DCSGroup=self:GetDCSObject()
|
||||
|
||||
if DCSGroup then
|
||||
local DCSUnitFound = DCSGroup:getUnit( UnitNumber )
|
||||
self:T3( DCSUnitFound )
|
||||
local DCSUnitFound=DCSGroup:getUnit( UnitNumber )
|
||||
return DCSUnitFound
|
||||
end
|
||||
|
||||
@@ -706,14 +707,14 @@ end
|
||||
-- @param #GROUP self
|
||||
-- @return #number The DCS Group size.
|
||||
function GROUP:GetSize()
|
||||
self:F3( { self.GroupName } )
|
||||
|
||||
local DCSGroup = self:GetDCSObject()
|
||||
|
||||
if DCSGroup then
|
||||
|
||||
local GroupSize = DCSGroup:getSize()
|
||||
|
||||
if GroupSize then
|
||||
self:T3( GroupSize )
|
||||
return GroupSize
|
||||
else
|
||||
return 0
|
||||
@@ -946,24 +947,29 @@ end
|
||||
-- @param #GROUP self
|
||||
-- @return DCS#Vec2 Current Vec2 point of the first DCS Unit of the DCS Group.
|
||||
function GROUP:GetVec2()
|
||||
self:F2( self.GroupName )
|
||||
|
||||
local UnitPoint = self:GetUnit(1)
|
||||
UnitPoint:GetVec2()
|
||||
local GroupPointVec2 = UnitPoint:GetVec2()
|
||||
self:T3( GroupPointVec2 )
|
||||
return GroupPointVec2
|
||||
local Unit=self:GetUnit(1)
|
||||
|
||||
if Unit then
|
||||
return Unit:GetVec2()
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- Returns the current Vec3 vector of the first DCS Unit in the GROUP.
|
||||
-- @param #GROUP self
|
||||
-- @return DCS#Vec3 Current Vec3 of the first DCS Unit of the GROUP.
|
||||
function GROUP:GetVec3()
|
||||
self:F2( self.GroupName )
|
||||
|
||||
local GroupVec3 = self:GetUnit(1):GetVec3()
|
||||
self:T3( GroupVec3 )
|
||||
return GroupVec3
|
||||
-- Get first unit.
|
||||
local unit=self:GetUnit(1)
|
||||
|
||||
if unit then
|
||||
return unit:GetVec3()
|
||||
end
|
||||
|
||||
self:E("ERROR: Cannot get Vec3 of group "..tostring(self.GroupName))
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Returns a POINT_VEC2 object indicating the point in 2D of the first UNIT of the GROUP within the mission.
|
||||
@@ -1166,6 +1172,32 @@ end
|
||||
|
||||
do -- Is Zone methods
|
||||
|
||||
|
||||
--- Check if any unit of a group is inside a @{Zone}.
|
||||
-- @param #GROUP self
|
||||
-- @param Core.Zone#ZONE_BASE Zone The zone to test.
|
||||
-- @return #boolean Returns true if at least one unit is inside the zone or false if no unit is inside.
|
||||
function GROUP:IsInZone( Zone )
|
||||
|
||||
if self:IsAlive() then
|
||||
|
||||
for UnitID, UnitData in pairs(self:GetUnits()) do
|
||||
local Unit = UnitData -- Wrapper.Unit#UNIT
|
||||
|
||||
if Zone:IsVec3InZone(Unit:GetVec3()) then
|
||||
return true -- At least one unit is in the zone. That is enough.
|
||||
else
|
||||
-- This one is not but another could be.
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Returns true if all units of the group are within a @{Zone}.
|
||||
-- @param #GROUP self
|
||||
-- @param Core.Zone#ZONE_BASE Zone The zone to test.
|
||||
@@ -2100,6 +2132,7 @@ end
|
||||
|
||||
--- Calculate the maxium A2G threat level of the Group.
|
||||
-- @param #GROUP self
|
||||
-- @return #number Number between 0 and 10.
|
||||
function GROUP:CalculateThreatLevelA2G()
|
||||
|
||||
local MaxThreatLevelA2G = 0
|
||||
@@ -2115,6 +2148,25 @@ function GROUP:CalculateThreatLevelA2G()
|
||||
return MaxThreatLevelA2G
|
||||
end
|
||||
|
||||
--- Get threat level of the group.
|
||||
-- @param #GROUP self
|
||||
-- @return #number Max threat level (a number between 0 and 10).
|
||||
function GROUP:GetThreatLevel()
|
||||
|
||||
local threatlevelMax = 0
|
||||
for UnitName, UnitData in pairs(self:GetUnits()) do
|
||||
local ThreatUnit = UnitData -- Wrapper.Unit#UNIT
|
||||
|
||||
local threatlevel = ThreatUnit:GetThreatLevel()
|
||||
if threatlevel > threatlevelMax then
|
||||
threatlevelMax=threatlevel
|
||||
end
|
||||
end
|
||||
|
||||
return threatlevelMax
|
||||
end
|
||||
|
||||
|
||||
--- Returns true if the first unit of the GROUP is in the air.
|
||||
-- @param Wrapper.Group#GROUP self
|
||||
-- @return #boolean true if in the first unit of the group is in the air or #nil if the GROUP is not existing or not alive.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
--- **Wrapper** - Markers On the F10 map.
|
||||
--
|
||||
--
|
||||
-- **Main Features:**
|
||||
--
|
||||
-- * Convenient handling of markers via multiple user API functions.
|
||||
@@ -8,7 +8,7 @@
|
||||
-- * Retrieve data such as text and coordinate.
|
||||
-- * Marker specific FSM events when a marker is added, removed or changed.
|
||||
-- * Additional FSM events when marker text or position is changed.
|
||||
--
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **funkyfranky**
|
||||
@@ -36,104 +36,104 @@
|
||||
-- 
|
||||
--
|
||||
-- # The MARKER Class Idea
|
||||
--
|
||||
--
|
||||
-- The MARKER class simplifies creating, updating and removing of markers on the F10 map.
|
||||
--
|
||||
--
|
||||
-- # Create a Marker
|
||||
--
|
||||
--
|
||||
-- -- Create a MARKER object at Batumi with a trivial text.
|
||||
-- local Coordinate=AIRBASE:FindByName("Batumi"):GetCoordinate()
|
||||
-- mymarker=MARKER:New(Coordinate, "I am Batumi Airfield")
|
||||
--
|
||||
-- Now this does **not** show the marker yet. We still need to specifiy to whom it is shown. There are several options, i.e.
|
||||
--
|
||||
-- Now this does **not** show the marker yet. We still need to specifiy to whom it is shown. There are several options, i.e.
|
||||
-- show the marker to everyone, to a speficic coaliton only, or only to a specific group.
|
||||
--
|
||||
--
|
||||
-- ## For Everyone
|
||||
--
|
||||
--
|
||||
-- If the marker should be visible to everyone, you can use the :ToAll() function.
|
||||
--
|
||||
-- mymarker=MARKER:New(Coordinate, "I am Batumi Airfield"):ToAll()
|
||||
--
|
||||
--
|
||||
-- ## For a Coaliton
|
||||
--
|
||||
--
|
||||
-- If the maker should be visible to a specific coalition, you can use the :ToCoalition() function.
|
||||
--
|
||||
--
|
||||
-- mymarker=MARKER:New(Coordinate, "I am Batumi Airfield"):ToCoaliton(coaliton.side.BLUE)
|
||||
--
|
||||
--
|
||||
-- ### To Blue Coaliton
|
||||
--
|
||||
--
|
||||
-- ### To Red Coalition
|
||||
--
|
||||
--
|
||||
-- This would show the marker only to the Blue coaliton.
|
||||
--
|
||||
--
|
||||
-- ## For a Group
|
||||
--
|
||||
--
|
||||
--
|
||||
--
|
||||
-- # Removing a Marker
|
||||
--
|
||||
--
|
||||
--
|
||||
--
|
||||
-- # Updating a Marker
|
||||
--
|
||||
--
|
||||
-- The marker text and coordinate can be updated easily as shown below.
|
||||
--
|
||||
--
|
||||
-- However, note that **updateing involves to remove and recreate the marker if either text or its coordinate is changed**.
|
||||
-- *This is a DCS scripting engine limitation.*
|
||||
--
|
||||
-- *This is a DCS scripting engine limitation.*
|
||||
--
|
||||
-- ## Update Text
|
||||
--
|
||||
--
|
||||
-- If you created a marker "mymarker" as shown above, you can update the dispayed test by
|
||||
--
|
||||
--
|
||||
-- mymarker:UpdateText("I am the new text at Batumi")
|
||||
--
|
||||
--
|
||||
-- The update can also be delayed by, e.g. 90 seconds, using
|
||||
--
|
||||
--
|
||||
-- mymarker:UpdateText("I am the new text at Batumi", 90)
|
||||
--
|
||||
--
|
||||
-- ## Update Coordinate
|
||||
--
|
||||
--
|
||||
-- If you created a marker "mymarker" as shown above, you can update its coordinate on the F10 map by
|
||||
--
|
||||
--
|
||||
-- mymarker:UpdateCoordinate(NewCoordinate)
|
||||
--
|
||||
--
|
||||
-- The update can also be delayed by, e.g. 60 seconds, using
|
||||
--
|
||||
--
|
||||
-- mymarker:UpdateCoordinate(NewCoordinate, 60)
|
||||
--
|
||||
--
|
||||
-- # Retrieve Data
|
||||
--
|
||||
--
|
||||
-- The important data as the displayed text and the coordinate of the marker can be retrieved easily.
|
||||
--
|
||||
--
|
||||
-- ## Text
|
||||
--
|
||||
--
|
||||
-- local text=mymarker:GetText()
|
||||
-- env.info("Marker Text = " .. text)
|
||||
--
|
||||
--
|
||||
-- ## Coordinate
|
||||
--
|
||||
--
|
||||
-- local Coordinate=mymarker:GetCoordinate()
|
||||
-- env.info("Marker Coordinate LL DSM = " .. Coordinate:ToStringLLDMS())
|
||||
--
|
||||
--
|
||||
--
|
||||
--
|
||||
-- # FSM Events
|
||||
--
|
||||
--
|
||||
-- Moose creates addditonal events, so called FSM event, when markers are added, changed, removed, and text or the coordianteis updated.
|
||||
--
|
||||
--
|
||||
-- These events can be captured and used for processing via OnAfter functions as shown below.
|
||||
--
|
||||
--
|
||||
-- ## Added
|
||||
--
|
||||
--
|
||||
-- ## Changed
|
||||
--
|
||||
--
|
||||
-- ## Removed
|
||||
--
|
||||
--
|
||||
-- ## TextUpdate
|
||||
--
|
||||
--
|
||||
-- ## CoordUpdate
|
||||
--
|
||||
--
|
||||
--
|
||||
--
|
||||
-- # Examples
|
||||
--
|
||||
--
|
||||
--
|
||||
--
|
||||
-- @field #MARKER
|
||||
MARKER = {
|
||||
ClassName = "MARKER",
|
||||
@@ -170,29 +170,29 @@ MARKER.version="0.1.0"
|
||||
--- Create a new MARKER class object.
|
||||
-- @param #MARKER self
|
||||
-- @param Core.Point#COORDINATE Coordinate Coordinate where to place the marker.
|
||||
-- @param #string Text Text displayed on the mark panel.
|
||||
-- @param #string Text Text displayed on the mark panel.
|
||||
-- @return #MARKER self
|
||||
function MARKER:New(Coordinate, Text)
|
||||
|
||||
-- Inherit everything from FSM class.
|
||||
local self=BASE:Inherit(self, FSM:New()) -- #MARKER
|
||||
|
||||
|
||||
self.coordinate=Coordinate
|
||||
|
||||
|
||||
self.text=Text
|
||||
|
||||
|
||||
-- Defaults
|
||||
self.readonly=false
|
||||
self.message=""
|
||||
|
||||
-- New marker ID. This is not the one of the actual marker.
|
||||
|
||||
-- New marker ID. This is not the one of the actual marker.
|
||||
_MARKERID=_MARKERID+1
|
||||
|
||||
|
||||
self.myid=_MARKERID
|
||||
|
||||
|
||||
-- Log ID.
|
||||
self.lid=string.format("Marker #%d | ", self.myid)
|
||||
|
||||
|
||||
-- Start State.
|
||||
self:SetStartState("Invisible")
|
||||
|
||||
@@ -201,7 +201,7 @@ function MARKER:New(Coordinate, Text)
|
||||
self:AddTransition("Invisible", "Added", "Visible") -- Marker was added.
|
||||
self:AddTransition("Visible", "Removed", "Invisible") -- Marker was removed.
|
||||
self:AddTransition("*", "Changed", "*") -- Marker was changed.
|
||||
|
||||
|
||||
self:AddTransition("*", "TextUpdate", "*") -- Text updated.
|
||||
self:AddTransition("*", "CoordUpdate", "*") -- Coordinates updated.
|
||||
|
||||
@@ -304,8 +304,8 @@ function MARKER:New(Coordinate, Text)
|
||||
self:HandleEvent(EVENTS.MarkAdded)
|
||||
self:HandleEvent(EVENTS.MarkRemoved)
|
||||
self:HandleEvent(EVENTS.MarkChange)
|
||||
|
||||
return self
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -318,7 +318,7 @@ end
|
||||
function MARKER:ReadOnly()
|
||||
|
||||
self.readonly=true
|
||||
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -329,7 +329,7 @@ end
|
||||
function MARKER:Message(Text)
|
||||
|
||||
self.message=Text or ""
|
||||
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -349,14 +349,14 @@ function MARKER:ToAll(Delay)
|
||||
self.togroup=nil
|
||||
self.groupname=nil
|
||||
self.groupid=nil
|
||||
|
||||
|
||||
-- First remove an existing mark.
|
||||
if self.shown then
|
||||
self:Remove()
|
||||
if self.shown then
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
|
||||
self.mid=UTILS.GetMarkID()
|
||||
|
||||
|
||||
-- Call DCS function.
|
||||
trigger.action.markToAll(self.mid, self.text, self.coordinate:GetVec3(), self.readonly, self.message)
|
||||
|
||||
@@ -377,25 +377,25 @@ function MARKER:ToCoalition(Coalition, Delay)
|
||||
else
|
||||
|
||||
self.coalition=Coalition
|
||||
|
||||
|
||||
self.tocoaliton=true
|
||||
self.toall=false
|
||||
self.togroup=false
|
||||
self.groupname=nil
|
||||
self.groupid=nil
|
||||
|
||||
|
||||
-- First remove an existing mark.
|
||||
if self.shown then
|
||||
self:Remove()
|
||||
if self.shown then
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
|
||||
self.mid=UTILS.GetMarkID()
|
||||
|
||||
|
||||
-- Call DCS function.
|
||||
trigger.action.markToCoalition(self.mid, self.text, self.coordinate:GetVec3(), self.coalition, self.readonly, self.message)
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -440,36 +440,36 @@ function MARKER:ToGroup(Group, Delay)
|
||||
|
||||
-- Check if group exists.
|
||||
if Group and Group:IsAlive()~=nil then
|
||||
|
||||
|
||||
self.groupid=Group:GetID()
|
||||
|
||||
|
||||
if self.groupid then
|
||||
|
||||
|
||||
self.groupname=Group:GetName()
|
||||
|
||||
|
||||
self.togroup=true
|
||||
self.tocoaliton=nil
|
||||
self.coalition=nil
|
||||
self.toall=nil
|
||||
|
||||
|
||||
-- First remove an existing mark.
|
||||
if self.shown then
|
||||
self:Remove()
|
||||
if self.shown then
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
|
||||
self.mid=UTILS.GetMarkID()
|
||||
|
||||
|
||||
-- Call DCS function.
|
||||
trigger.action.markToGroup(self.mid, self.text, self.coordinate:GetVec3(), self.groupid, self.readonly, self.message)
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
else
|
||||
--TODO: Warning!
|
||||
--TODO: Warning!
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -482,14 +482,14 @@ function MARKER:UpdateText(Text, Delay)
|
||||
|
||||
if Delay and Delay>0 then
|
||||
self:ScheduleOnce(Delay, MARKER.UpdateText, self, Text)
|
||||
else
|
||||
else
|
||||
|
||||
self.text=tostring(Text)
|
||||
|
||||
|
||||
self:Refresh()
|
||||
|
||||
|
||||
self:TextUpdate(tostring(Text))
|
||||
|
||||
|
||||
end
|
||||
|
||||
return self
|
||||
@@ -504,14 +504,14 @@ function MARKER:UpdateCoordinate(Coordinate, Delay)
|
||||
|
||||
if Delay and Delay>0 then
|
||||
self:ScheduleOnce(Delay, MARKER.UpdateCoordinate, self, Coordinate)
|
||||
else
|
||||
else
|
||||
|
||||
self.coordinate=Coordinate
|
||||
|
||||
|
||||
self:Refresh()
|
||||
|
||||
|
||||
self:CoordUpdate(Coordinate)
|
||||
|
||||
|
||||
end
|
||||
|
||||
return self
|
||||
@@ -525,26 +525,26 @@ function MARKER:Refresh(Delay)
|
||||
|
||||
if Delay and Delay>0 then
|
||||
self:ScheduleOnce(Delay, MARKER.Refresh, self)
|
||||
else
|
||||
else
|
||||
|
||||
if self.toall then
|
||||
|
||||
|
||||
self:ToAll()
|
||||
|
||||
|
||||
elseif self.tocoaliton then
|
||||
|
||||
|
||||
self:ToCoalition(self.coalition)
|
||||
|
||||
|
||||
elseif self.togroup then
|
||||
|
||||
|
||||
local group=GROUP:FindByName(self.groupname)
|
||||
|
||||
|
||||
self:ToGroup(group)
|
||||
|
||||
|
||||
else
|
||||
self:E(self.lid.."ERROR: unknown To in :Refresh()!")
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
return self
|
||||
@@ -564,9 +564,9 @@ function MARKER:Remove(Delay)
|
||||
|
||||
-- Call DCS function.
|
||||
trigger.action.removeMark(self.mid)
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
return self
|
||||
@@ -605,7 +605,7 @@ end
|
||||
|
||||
--- Check if marker is currently invisible on the F10 map.
|
||||
-- @param #MARKER self
|
||||
-- @return
|
||||
-- @return
|
||||
function MARKER:IsInvisible()
|
||||
return self:Is("Invisible")
|
||||
end
|
||||
@@ -620,17 +620,17 @@ end
|
||||
function MARKER:OnEventMarkAdded(EventData)
|
||||
|
||||
if EventData and EventData.MarkID then
|
||||
|
||||
|
||||
local MarkID=EventData.MarkID
|
||||
|
||||
|
||||
self:T3(self.lid..string.format("Captured event MarkAdded for Mark ID=%s", tostring(MarkID)))
|
||||
|
||||
|
||||
if MarkID==self.mid then
|
||||
|
||||
|
||||
self.shown=true
|
||||
|
||||
|
||||
self:Added(EventData)
|
||||
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
@@ -643,21 +643,21 @@ end
|
||||
function MARKER:OnEventMarkRemoved(EventData)
|
||||
|
||||
if EventData and EventData.MarkID then
|
||||
|
||||
|
||||
local MarkID=EventData.MarkID
|
||||
|
||||
|
||||
self:T3(self.lid..string.format("Captured event MarkAdded for Mark ID=%s", tostring(MarkID)))
|
||||
|
||||
|
||||
if MarkID==self.mid then
|
||||
|
||||
|
||||
self.shown=false
|
||||
|
||||
|
||||
self:Removed(EventData)
|
||||
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
--- Event function when a MARKER changed.
|
||||
@@ -666,17 +666,17 @@ end
|
||||
function MARKER:OnEventMarkChange(EventData)
|
||||
|
||||
if EventData and EventData.MarkID then
|
||||
|
||||
|
||||
local MarkID=EventData.MarkID
|
||||
|
||||
|
||||
self:T3(self.lid..string.format("Captured event MarkChange for Mark ID=%s", tostring(MarkID)))
|
||||
|
||||
|
||||
if MarkID==self.mid then
|
||||
|
||||
|
||||
self:Changed(EventData)
|
||||
|
||||
|
||||
self:TextChanged(tostring(EventData.MarkText))
|
||||
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
@@ -696,7 +696,7 @@ end
|
||||
function MARKER:onafterAdded(From, Event, To, EventData)
|
||||
|
||||
-- Debug info.
|
||||
local text=string.format("Captured event MarkAdded for myself:\n")
|
||||
local text=string.format("Captured event MarkAdded for myself:\n")
|
||||
text=text..string.format("Marker ID = %s\n", tostring(EventData.MarkID))
|
||||
text=text..string.format("Coalition = %s\n", tostring(EventData.MarkCoalition))
|
||||
text=text..string.format("Group ID = %s\n", tostring(EventData.MarkGroupID))
|
||||
@@ -716,7 +716,7 @@ end
|
||||
function MARKER:onafterRemoved(From, Event, To, EventData)
|
||||
|
||||
-- Debug info.
|
||||
local text=string.format("Captured event MarkRemoved for myself:\n")
|
||||
local text=string.format("Captured event MarkRemoved for myself:\n")
|
||||
text=text..string.format("Marker ID = %s\n", tostring(EventData.MarkID))
|
||||
text=text..string.format("Coalition = %s\n", tostring(EventData.MarkCoalition))
|
||||
text=text..string.format("Group ID = %s\n", tostring(EventData.MarkGroupID))
|
||||
@@ -736,7 +736,7 @@ end
|
||||
function MARKER:onafterChanged(From, Event, To, EventData)
|
||||
|
||||
-- Debug info.
|
||||
local text=string.format("Captured event MarkChange for myself:\n")
|
||||
local text=string.format("Captured event MarkChange for myself:\n")
|
||||
text=text..string.format("Marker ID = %s\n", tostring(EventData.MarkID))
|
||||
text=text..string.format("Coalition = %s\n", tostring(EventData.MarkCoalition))
|
||||
text=text..string.format("Group ID = %s\n", tostring(EventData.MarkGroupID))
|
||||
@@ -755,7 +755,7 @@ end
|
||||
-- @param #string Text The updated text, displayed in the mark panel.
|
||||
function MARKER:onafterTextUpdate(From, Event, To, Text)
|
||||
|
||||
self:I(self.lid..string.format("New Marker Text:\n%s", Text))
|
||||
self:T(self.lid..string.format("New Marker Text:\n%s", Text))
|
||||
|
||||
end
|
||||
|
||||
@@ -767,8 +767,8 @@ end
|
||||
-- @param Core.Point#COORDINATE Coordinate The updated coordinates.
|
||||
function MARKER:onafterCoordUpdate(From, Event, To, Coordinate)
|
||||
|
||||
self:I(self.lid..string.format("New Marker Coordinate in LL DMS: %s", Coordinate:ToStringLLDMS()))
|
||||
|
||||
self:T(self.lid..string.format("New Marker Coordinate in LL DMS: %s", Coordinate:ToStringLLDMS()))
|
||||
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -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.__
|
||||
@@ -121,10 +125,17 @@ function POSITIONABLE:Destroy( GenerateEvent )
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Returns the DCS object. Polymorphic for other classes like UNIT, STATIC, GROUP, AIRBASE.
|
||||
-- @param #POSITIONABLE self
|
||||
-- @return DCS#Object The DCS object.
|
||||
function POSITIONABLE:GetDCSObject()
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Returns a pos3 table of the objects current position and orientation in 3D space. X, Y, Z values are unit vectors defining the objects orientation.
|
||||
-- Coordinates are dependent on the position of the maps origin.
|
||||
-- @param Wrapper.Positionable#POSITIONABLE self
|
||||
-- @return DCS#Position Table consisting of the point and orientation tables.
|
||||
-- @return DCS#Position3 Table consisting of the point and orientation tables.
|
||||
function POSITIONABLE:GetPosition()
|
||||
self:F2( self.PositionableName )
|
||||
|
||||
@@ -215,27 +226,44 @@ function POSITIONABLE:GetPositionVec3()
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Returns the @{DCS#Vec2} vector indicating the point in 2D of the POSITIONABLE within the mission.
|
||||
--- Returns the @{DCS#Vec3} vector indicating the 3D vector of the POSITIONABLE within the mission.
|
||||
-- @param Wrapper.Positionable#POSITIONABLE self
|
||||
-- @return DCS#Vec2 The 2D point vector of the POSITIONABLE.
|
||||
-- @return #nil The POSITIONABLE is not existing or alive.
|
||||
function POSITIONABLE:GetVec2()
|
||||
self:F2( self.PositionableName )
|
||||
-- @return DCS#Vec3 The 3D point vector of the POSITIONABLE or `nil` if it is not existing or alive.
|
||||
function POSITIONABLE:GetVec3()
|
||||
|
||||
local DCSPositionable = self:GetDCSObject()
|
||||
|
||||
if DCSPositionable then
|
||||
local PositionableVec3 = DCSPositionable:getPosition().p
|
||||
|
||||
local PositionableVec2 = {}
|
||||
PositionableVec2.x = PositionableVec3.x
|
||||
PositionableVec2.y = PositionableVec3.z
|
||||
|
||||
self:T2( PositionableVec2 )
|
||||
return PositionableVec2
|
||||
local vec3=DCSPositionable:getPoint()
|
||||
|
||||
if vec3 then
|
||||
return vec3
|
||||
else
|
||||
self:E("ERROR: Cannot get vec3!")
|
||||
end
|
||||
end
|
||||
|
||||
BASE:E( { "Cannot GetVec2", Positionable = self, Alive = self:IsAlive() } )
|
||||
-- ERROR!
|
||||
self:E( { "Cannot GetVec3", Positionable = self, Alive = self:IsAlive() } )
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Returns the @{DCS#Vec2} vector indicating the point in 2D of the POSITIONABLE within the mission.
|
||||
-- @param Wrapper.Positionable#POSITIONABLE self
|
||||
-- @return DCS#Vec2 The 2D point vector of the POSITIONABLE or #nil if it is not existing or alive.
|
||||
function POSITIONABLE:GetVec2()
|
||||
|
||||
local DCSPositionable = self:GetDCSObject()
|
||||
|
||||
if DCSPositionable then
|
||||
|
||||
local Vec3=DCSPositionable:getPoint() --DCS#Vec3
|
||||
|
||||
return {x=Vec3.x, y=Vec3.z}
|
||||
end
|
||||
|
||||
self:E( { "Cannot GetVec2", Positionable = self, Alive = self:IsAlive() } )
|
||||
|
||||
return nil
|
||||
end
|
||||
@@ -258,7 +286,7 @@ function POSITIONABLE:GetPointVec2()
|
||||
return PositionablePointVec2
|
||||
end
|
||||
|
||||
BASE:E( { "Cannot GetPointVec2", Positionable = self, Alive = self:IsAlive() } )
|
||||
self:E( { "Cannot GetPointVec2", Positionable = self, Alive = self:IsAlive() } )
|
||||
|
||||
return nil
|
||||
end
|
||||
@@ -268,17 +296,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 false and self.pointvec3 then
|
||||
|
||||
-- Update vector.
|
||||
self.pointvec3.x=PositionableVec3.x
|
||||
self.pointvec3.y=PositionableVec3.y
|
||||
self.pointvec3.z=PositionableVec3.z
|
||||
|
||||
else
|
||||
|
||||
-- Create a new POINT_VEC3 object.
|
||||
self.pointvec3=POINT_VEC3:NewFromVec3(PositionableVec3)
|
||||
|
||||
end
|
||||
|
||||
return self.pointvec3
|
||||
end
|
||||
|
||||
BASE:E( { "Cannot GetPointVec3", Positionable = self, Alive = self:IsAlive() } )
|
||||
@@ -289,27 +329,62 @@ end
|
||||
--- Returns a COORDINATE object indicating the point in 3D of the POSITIONABLE within the mission.
|
||||
-- @param Wrapper.Positionable#POSITIONABLE self
|
||||
-- @return Core.Point#COORDINATE The COORDINATE of the POSITIONABLE.
|
||||
function POSITIONABLE:GetCoordinate()
|
||||
self:F2( self.PositionableName )
|
||||
function POSITIONABLE:GetCoord()
|
||||
|
||||
-- Get DCS object.
|
||||
local DCSPositionable = self:GetDCSObject()
|
||||
|
||||
if DCSPositionable then
|
||||
local PositionableVec3 = self:GetPositionVec3()
|
||||
|
||||
local PositionableCoordinate = COORDINATE:NewFromVec3( PositionableVec3 )
|
||||
PositionableCoordinate:SetHeading( self:GetHeading() )
|
||||
PositionableCoordinate:SetVelocity( self:GetVelocityMPS() )
|
||||
|
||||
self:T2( PositionableCoordinate )
|
||||
return PositionableCoordinate
|
||||
-- Get the current position.
|
||||
local Vec3 = self:GetVec3()
|
||||
|
||||
if self.coordinate then
|
||||
|
||||
-- Update vector.
|
||||
self.coordinate.x=Vec3.x
|
||||
self.coordinate.y=Vec3.y
|
||||
self.coordinate.z=Vec3.z
|
||||
|
||||
else
|
||||
|
||||
-- New COORDINATE.
|
||||
self.coordinate=COORDINATE:NewFromVec3(Vec3)
|
||||
|
||||
end
|
||||
|
||||
return self.coordinate
|
||||
end
|
||||
|
||||
-- Error message.
|
||||
BASE:E( { "Cannot GetCoordinate", Positionable = self, Alive = self:IsAlive() } )
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Returns a COORDINATE object indicating the point in 3D of the POSITIONABLE within the mission.
|
||||
-- @param Wrapper.Positionable#POSITIONABLE self
|
||||
-- @return Core.Point#COORDINATE The COORDINATE of the POSITIONABLE.
|
||||
function POSITIONABLE:GetCoordinate()
|
||||
|
||||
-- Get DCS object.
|
||||
local DCSPositionable = self:GetDCSObject()
|
||||
|
||||
if DCSPositionable then
|
||||
|
||||
-- Get the current position.
|
||||
local PositionableVec3 = self:GetVec3()
|
||||
|
||||
-- Return a new coordiante object.
|
||||
return COORDINATE:NewFromVec3(PositionableVec3)
|
||||
|
||||
end
|
||||
|
||||
-- Error message.
|
||||
self:E( { "Cannot GetCoordinate", Positionable = self, Alive = self:IsAlive() } )
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Returns a COORDINATE object, which is offset with respect to the orientation of the POSITIONABLE.
|
||||
-- @param Wrapper.Positionable#POSITIONABLE self
|
||||
-- @param #number x Offset in the direction "the nose" of the unit is pointing in meters. Default 0 m.
|
||||
@@ -384,26 +459,6 @@ function POSITIONABLE:GetRandomVec3( Radius )
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Returns the @{DCS#Vec3} vector indicating the 3D vector of the POSITIONABLE within the mission.
|
||||
-- @param Wrapper.Positionable#POSITIONABLE self
|
||||
-- @return DCS#Vec3 The 3D point vector of the POSITIONABLE.
|
||||
-- @return #nil The POSITIONABLE is not existing or alive.
|
||||
function POSITIONABLE:GetVec3()
|
||||
self:F2( self.PositionableName )
|
||||
|
||||
local DCSPositionable = self:GetDCSObject()
|
||||
|
||||
if DCSPositionable then
|
||||
local PositionableVec3 = DCSPositionable:getPosition().p
|
||||
self:T3( PositionableVec3 )
|
||||
return PositionableVec3
|
||||
end
|
||||
|
||||
BASE:E( { "Cannot GetVec3", Positionable = self, Alive = self:IsAlive() } )
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
--- Get the bounding box of the underlying POSITIONABLE DCS Object.
|
||||
-- @param #POSITIONABLE self
|
||||
@@ -1533,7 +1588,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 )
|
||||
|
||||
Reference in New Issue
Block a user