mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-10-29 16:58:06 +00:00
Progress
This commit is contained in:
@@ -22,6 +22,10 @@
|
||||
-- @type AIBALANCER
|
||||
-- @field Set#SET_CLIENT SetClient
|
||||
-- @field Spawn#SPAWN SpawnAI
|
||||
-- @field #boolean ReturnToAirbase
|
||||
-- @field Set#SET_AIRBASE ReturnAirbaseSet
|
||||
-- @field DCSTypes#Distance ReturnTresholdRange
|
||||
-- @field #boolean ReturnToHomeAirbase
|
||||
-- @extends Base#BASE
|
||||
AIBALANCER = {
|
||||
ClassName = "AIBALANCER",
|
||||
@@ -38,13 +42,48 @@ function AIBALANCER:New( SetClient, SpawnAI )
|
||||
local self = BASE:Inherit( self, BASE:New() )
|
||||
|
||||
self.SetClient = SetClient
|
||||
self.SpawnAI = SpawnAI
|
||||
if type( SpawnAI ) == "table" then
|
||||
if SpawnAI.ClassName and SpawnAI.ClassName == "SPAWN" then
|
||||
self.SpawnAI = { SpawnAI }
|
||||
else
|
||||
local SpawnObjects = true
|
||||
for SpawnObjectID, SpawnObject in pairs( SpawnAI ) do
|
||||
if SpawnObject.ClassName and SpawnObject.ClassName == "SPAWN" then
|
||||
self:E( SpawnObject.ClassName )
|
||||
else
|
||||
self:E( "other object" )
|
||||
SpawnObjects = false
|
||||
end
|
||||
end
|
||||
if SpawnObjects == true then
|
||||
self.SpawnAI = SpawnAI
|
||||
else
|
||||
error( "No SPAWN object given in parameter SpawnAI, either as a single object or as a table of objects!" )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
self.ReturnToAirbase = false
|
||||
self.ReturnHomeAirbase = false
|
||||
|
||||
self.AIMonitorSchedule = SCHEDULER:New( self, self._ClientAliveMonitorScheduler, {}, 1, 10, 0 )
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function AIBALANCER:ReturnToNearestAirbases( ReturnTresholdRange, ReturnAirbaseSet )
|
||||
|
||||
self.ReturnToAirbase = true
|
||||
self.ReturnTresholdRange = ReturnTresholdRange
|
||||
self.ReturnAirbaseSet = ReturnAirbaseSet
|
||||
end
|
||||
|
||||
function AIBALANCER:ReturnToHomeAirbase( ReturnTresholdRange )
|
||||
|
||||
self.ReturnToHomeAirbase = true
|
||||
self.ReturnTresholdRange = ReturnTresholdRange
|
||||
end
|
||||
|
||||
--- @param #AIBALANCER self
|
||||
function AIBALANCER:_ClientAliveMonitorScheduler()
|
||||
|
||||
@@ -56,13 +95,70 @@ function AIBALANCER:_ClientAliveMonitorScheduler()
|
||||
if Client:IsAlive() then
|
||||
if ClientAIAliveState == true then
|
||||
Client:SetState( self, 'AIAlive', false )
|
||||
|
||||
local AIGroup = Client:GetState( self, 'AIGroup' ) -- Group#GROUP
|
||||
AIGroup:Destroy()
|
||||
|
||||
if self.ReturnToAirbase == false and self.ReturnToHomeAirbase == false then
|
||||
AIGroup:Destroy()
|
||||
else
|
||||
-- We test if there is no other CLIENT within the self.ReturnTresholdRange of the first unit of the AI group.
|
||||
-- If there is a CLIENT, the AI stays engaged and will not return.
|
||||
-- If there is no CLIENT within the self.ReturnTresholdRange, then the unit will return to the Airbase return method selected.
|
||||
|
||||
local ClientInZone = { Value = false }
|
||||
local RangeZone = ZONE_RADIUS:New( 'RangeZone', AIGroup:GetPointVec2(), self.ReturnTresholdRange )
|
||||
|
||||
self:E( RangeZone )
|
||||
|
||||
_DATABASE:ForEachUnit(
|
||||
--- @param Unit#UNIT RangeTestUnit
|
||||
function( RangeTestUnit, RangeZone, AIGroup, ClientInZone )
|
||||
self:E( { ClientInZone, RangeTestUnit.UnitName, RangeZone.ZoneName } )
|
||||
if RangeTestUnit:IsInZone( RangeZone ) == true then
|
||||
self:E( "in zone" )
|
||||
if RangeTestUnit:GetCoalition() ~= AIGroup:GetCoalition() then
|
||||
self:E( "in range" )
|
||||
ClientInZone.Value = true
|
||||
end
|
||||
end
|
||||
end,
|
||||
|
||||
--- @param Zone#ZONE_RADIUS RangeZone
|
||||
-- @param Group#GROUP AIGroup
|
||||
function( RangeZone, AIGroup, ClientInZone )
|
||||
local AIGroupTemplate = AIGroup:GetTemplate()
|
||||
if ClientInZone.Value == false then
|
||||
if self.ReturnToHomeAirbase == true then
|
||||
local WayPointCount = #AIGroupTemplate.route.points
|
||||
local SwitchWayPointCommand = AIGroup:CommandSwitchWayPoint( 1, WayPointCount, 1 )
|
||||
AIGroup:SetCommand( SwitchWayPointCommand )
|
||||
AIGroup:MessageToRed( "Returning to home base ...", 30 )
|
||||
else
|
||||
-- Okay, we need to send this Group back to the nearest base of the Coalition of the AI.
|
||||
--TODO: i need to rework the POINT_VEC2 thing.
|
||||
local PointVec2 = POINT_VEC2:New( AIGroup:GetPointVec2().x, AIGroup:GetPointVec2().y )
|
||||
local ClosestAirbase = self.ReturnAirbaseSet:FindNearestAirbaseFromPointVec2( PointVec2 )
|
||||
self:T( ClosestAirbase.AirbaseName )
|
||||
AIGroup:MessageToRed( "Returning to " .. ClosestAirbase:GetName() " ...", 30 )
|
||||
local RTBRoute = AIGroup:RouteReturnToAirbase( ClosestAirbase )
|
||||
AIGroupTemplate.route = RTBRoute
|
||||
AIGroup:Respawn( AIGroupTemplate )
|
||||
end
|
||||
end
|
||||
end
|
||||
, RangeZone, AIGroup, ClientInZone
|
||||
)
|
||||
|
||||
end
|
||||
end
|
||||
else
|
||||
if not ClientAIAliveState or ClientAIAliveState == false then
|
||||
Client:SetState( self, 'AIAlive', true )
|
||||
Client:SetState( self, 'AIGroup', self.SpawnAI:Spawn() )
|
||||
|
||||
-- OK, spawn a new group from the SpawnAI objects provided.
|
||||
local SpawnAICount = #self.SpawnAI
|
||||
local SpawnAIIndex = math.random( 1, SpawnAICount )
|
||||
Client:SetState( self, 'AIGroup', self.SpawnAI[SpawnAIIndex]:Spawn() )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
--- AIRBASE Class
|
||||
--- This module contains the AIRBASE classes.
|
||||
--
|
||||
-- @{AIRBASE} class
|
||||
-- ==============
|
||||
-- ===
|
||||
--
|
||||
-- 1) @{Airbase#AIRBASE} class, extends @{Base#BASE}
|
||||
-- =================================================
|
||||
-- The @{AIRBASE} class is a wrapper class to handle the DCS Airbase objects:
|
||||
--
|
||||
-- * Support all DCS Airbase APIs.
|
||||
-- * Enhance with Airbase specific APIs not in the DCS Airbase API set.
|
||||
--
|
||||
--
|
||||
-- AIRBASE reference methods
|
||||
-- ======================
|
||||
-- 1.1) AIRBASE reference methods
|
||||
-- ------------------------------
|
||||
-- For each DCS Airbase object alive within a running mission, a AIRBASE wrapper object (instance) will be created within the _@{DATABASE} object.
|
||||
-- This is done at the beginning of the mission (when the mission starts).
|
||||
--
|
||||
@@ -27,8 +29,8 @@
|
||||
--
|
||||
-- IMPORTANT: ONE SHOULD NEVER SANATIZE these AIRBASE OBJECT REFERENCES! (make the AIRBASE object references nil).
|
||||
--
|
||||
-- DCS AIRBASE APIs
|
||||
-- =============
|
||||
-- 1.2) DCS AIRBASE APIs
|
||||
-- ---------------------
|
||||
-- The DCS Airbase APIs are used extensively within MOOSE. The AIRBASE class has for each DCS Airbase API a corresponding method.
|
||||
-- To be able to distinguish easily in your code the difference between a AIRBASE API call and a DCS Airbase API call,
|
||||
-- the first letter of the method is also capitalized. So, by example, the DCS Airbase method @{DCSAirbase#Airbase.getName}()
|
||||
@@ -274,6 +276,21 @@ function AIRBASE:GetPointVec2()
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Returns the DCS Airbase category as defined within the DCS Airbase Descriptor.
|
||||
-- @param Airbase#AIRBASE self
|
||||
-- @return DCSAirbase#Airbase.Category The DCS Airbase Category
|
||||
function AIRBASE:GetCategory()
|
||||
local DCSAirbase = self:GetDCSAirbase()
|
||||
|
||||
if DCSAirbase then
|
||||
local AirbaseCategory = self:GetDesc().category
|
||||
return AirbaseCategory
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
--- Returns the DCS Airbase category name as defined within the DCS Airbase Descriptor.
|
||||
-- @param Airbase#AIRBASE self
|
||||
-- @return #string The DCS Airbase Category Name
|
||||
@@ -288,3 +305,4 @@ function AIRBASE:GetCategoryName()
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
|
||||
@@ -236,7 +236,6 @@ end
|
||||
|
||||
--- @param #CLIENT self
|
||||
function CLIENT:_AliveCheckScheduler( SchedulerName )
|
||||
self:E( SchedulerName )
|
||||
self:F( { SchedulerName, self.ClientName, self.ClientAlive2, self.ClientBriefingShown, self.ClientCallBack } )
|
||||
|
||||
if self:IsAlive() then
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
--- Manage the mission database.
|
||||
--- This module contains the DATABASE class, managing the database of mission objects.
|
||||
--
|
||||
-- @{#DATABASE} class
|
||||
-- ==================
|
||||
-- ====
|
||||
--
|
||||
-- 1) @{Database#DATABASE} class, extends @{Base#BASE}
|
||||
-- ===================================================
|
||||
-- Mission designers can use the DATABASE class to refer to:
|
||||
--
|
||||
-- * UNITS
|
||||
@@ -16,8 +18,8 @@
|
||||
-- Moose will automatically create one instance of the DATABASE class into the **global** object _DATABASE.
|
||||
-- Moose refers to _DATABASE within the framework extensively, but you can also refer to the _DATABASE object within your missions if required.
|
||||
--
|
||||
-- DATABASE iterators:
|
||||
-- ===================
|
||||
-- 1.1) DATABASE iterators
|
||||
-- -----------------------
|
||||
-- You can iterate the database with the available iterator methods.
|
||||
-- The iterator methods will walk the DATABASE set, and call for each element within the set a function that you provide.
|
||||
-- The following iterator methods are currently available within the DATABASE:
|
||||
@@ -32,17 +34,6 @@
|
||||
-- @module Database
|
||||
-- @author FlightControl
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
--- DATABASE class
|
||||
-- @type DATABASE
|
||||
-- @extends Base#BASE
|
||||
@@ -61,6 +52,7 @@ DATABASE = {
|
||||
PLAYERSALIVE = {},
|
||||
CLIENTS = {},
|
||||
CLIENTSALIVE = {},
|
||||
AIRBASES = {},
|
||||
NavPoints = {},
|
||||
}
|
||||
|
||||
@@ -105,6 +97,7 @@ function DATABASE:New()
|
||||
self:_RegisterClients()
|
||||
self:_RegisterStatics()
|
||||
self:_RegisterPlayers()
|
||||
self:_RegisterAirbases()
|
||||
|
||||
return self
|
||||
end
|
||||
@@ -166,6 +159,33 @@ function DATABASE:FindStatic( StaticName )
|
||||
return StaticFound
|
||||
end
|
||||
|
||||
--- Adds a Airbase based on the Airbase Name in the DATABASE.
|
||||
-- @param #DATABASE self
|
||||
function DATABASE:AddAirbase( DCSAirbaseName )
|
||||
|
||||
if not self.AIRBASES[DCSAirbaseName] then
|
||||
self.AIRBASES[DCSAirbaseName] = AIRBASE:Register( DCSAirbaseName )
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--- Deletes a Airbase from the DATABASE based on the Airbase Name.
|
||||
-- @param #DATABASE self
|
||||
function DATABASE:DeleteAirbase( DCSAirbaseName )
|
||||
|
||||
--self.AIRBASES[DCSAirbaseName] = nil
|
||||
end
|
||||
|
||||
--- Finds a AIRBASE based on the AirbaseName.
|
||||
-- @param #DATABASE self
|
||||
-- @param #string AirbaseName
|
||||
-- @return Airbase#AIRBASE The found AIRBASE.
|
||||
function DATABASE:FindAirbase( AirbaseName )
|
||||
|
||||
local AirbaseFound = self.AIRBASES[AirbaseName]
|
||||
return AirbaseFound
|
||||
end
|
||||
|
||||
|
||||
--- Finds a CLIENT based on the ClientName.
|
||||
-- @param #DATABASE self
|
||||
@@ -371,6 +391,18 @@ function DATABASE:GetCountryFromClientTemplate( ClientName )
|
||||
return self.Templates.ClientsByName[ClientName].CountryID
|
||||
end
|
||||
|
||||
--- Airbase
|
||||
|
||||
function DATABASE:GetCoalitionFromAirbase( AirbaseName )
|
||||
return self.AIRBASES[AirbaseName]:GetCoalition()
|
||||
end
|
||||
|
||||
function DATABASE:GetCategoryFromAirbase( AirbaseName )
|
||||
return self.AIRBASES[AirbaseName]:GetCategory()
|
||||
end
|
||||
|
||||
|
||||
|
||||
--- Private method that registers all alive players in the mission.
|
||||
-- @param #DATABASE self
|
||||
-- @return #DATABASE self
|
||||
@@ -439,6 +471,7 @@ function DATABASE:_RegisterClients()
|
||||
return self
|
||||
end
|
||||
|
||||
--- @param #DATABASE self
|
||||
function DATABASE:_RegisterStatics()
|
||||
|
||||
local CoalitionsData = { GroupsRed = coalition.getStaticObjects( coalition.side.RED ), GroupsBlue = coalition.getStaticObjects( coalition.side.BLUE ) }
|
||||
@@ -459,6 +492,23 @@ function DATABASE:_RegisterStatics()
|
||||
return self
|
||||
end
|
||||
|
||||
--- @param #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:E( { "Register Airbase:", DCSAirbaseName } )
|
||||
self:AddAirbase( DCSAirbaseName )
|
||||
end
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Events
|
||||
|
||||
@@ -526,7 +576,7 @@ end
|
||||
-- @param #DATABASE self
|
||||
-- @param #function IteratorFunction The function that will be called when there is an alive player in the database.
|
||||
-- @return #DATABASE self
|
||||
function DATABASE:ForEach( IteratorFunction, arg, Set )
|
||||
function DATABASE:ForEach( IteratorFunction, FinalizeFunction, arg, Set )
|
||||
self:F2( arg )
|
||||
|
||||
local function CoRoutine()
|
||||
@@ -547,7 +597,7 @@ function DATABASE:ForEach( IteratorFunction, arg, Set )
|
||||
local function Schedule()
|
||||
|
||||
local status, res = coroutine.resume( co )
|
||||
self:T2( { status, res } )
|
||||
self:T3( { status, res } )
|
||||
|
||||
if status == false then
|
||||
error( res )
|
||||
@@ -555,7 +605,9 @@ function DATABASE:ForEach( IteratorFunction, arg, Set )
|
||||
if res == false then
|
||||
return true -- resume next time the loop
|
||||
end
|
||||
|
||||
if FinalizeFunction then
|
||||
FinalizeFunction( unpack( arg ) )
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
@@ -569,10 +621,10 @@ end
|
||||
-- @param #DATABASE self
|
||||
-- @param #function IteratorFunction The function that will be called when there is an alive UNIT in the database. The function needs to accept a UNIT parameter.
|
||||
-- @return #DATABASE self
|
||||
function DATABASE:ForEachUnit( IteratorFunction, ... )
|
||||
function DATABASE:ForEachUnit( IteratorFunction, FinalizeFunction, ... )
|
||||
self:F2( arg )
|
||||
|
||||
self:ForEach( IteratorFunction, arg, self.UNITS )
|
||||
self:ForEach( IteratorFunction, FinalizeFunction, arg, self.UNITS )
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -65,6 +65,7 @@
|
||||
-- * @{#GROUP.TaskRouteToVec2}: (AIR + GROUND) Make the Group move to a given point.
|
||||
-- * @{#GROUP.TaskRouteToVec3}: (AIR + GROUND) Make the Group move to a given point.
|
||||
-- * @{#GROUP.TaskRouteToZone}: (AIR + GROUND) Route the group to a given zone.
|
||||
-- * @{#GROUP.TaskReturnToBase}: (AIR) Route the group to an airbase.
|
||||
--
|
||||
-- ### 1.2.2) EnRoute task methods
|
||||
--
|
||||
@@ -1050,6 +1051,24 @@ function GROUP:CommandSwitchWayPoint( FromWayPoint, ToWayPoint, Index )
|
||||
return CommandSwitchWayPoint
|
||||
end
|
||||
|
||||
--- Perform stop route command
|
||||
-- @param #GROUP self
|
||||
-- @param #boolean StopRoute
|
||||
-- @return DCSTask#Task
|
||||
function GROUP:CommandStopRoute( StopRoute, Index )
|
||||
self:F2( { StopRoute, Index } )
|
||||
|
||||
local CommandStopRoute = {
|
||||
id = 'StopRoute',
|
||||
params = {
|
||||
value = StopRoute,
|
||||
},
|
||||
}
|
||||
|
||||
self:T3( { CommandStopRoute } )
|
||||
return CommandStopRoute
|
||||
end
|
||||
|
||||
|
||||
-- TASKS FOR AIR GROUPS
|
||||
|
||||
@@ -2216,6 +2235,125 @@ function GROUP:TaskRouteToZone( Zone, Randomize, Speed, Formation )
|
||||
return nil
|
||||
end
|
||||
|
||||
--- (AIR) Return the Group to an @{Airbase#AIRBASE}
|
||||
-- A speed can be given in km/h.
|
||||
-- A given formation can be given.
|
||||
-- @param #GROUP self
|
||||
-- @param Airbase#AIRBASE ReturnAirbase The @{Airbase#AIRBASE} to return to.
|
||||
-- @param #number Speed (optional) The speed.
|
||||
-- @return #string The route
|
||||
function GROUP:RouteReturnToAirbase( ReturnAirbase, Speed )
|
||||
self:F2( { ReturnAirbase, Speed } )
|
||||
|
||||
-- Example
|
||||
-- [4] =
|
||||
-- {
|
||||
-- ["alt"] = 45,
|
||||
-- ["type"] = "Land",
|
||||
-- ["action"] = "Landing",
|
||||
-- ["alt_type"] = "BARO",
|
||||
-- ["formation_template"] = "",
|
||||
-- ["properties"] =
|
||||
-- {
|
||||
-- ["vnav"] = 1,
|
||||
-- ["scale"] = 0,
|
||||
-- ["angle"] = 0,
|
||||
-- ["vangle"] = 0,
|
||||
-- ["steer"] = 2,
|
||||
-- }, -- end of ["properties"]
|
||||
-- ["ETA"] = 527.81058817743,
|
||||
-- ["airdromeId"] = 12,
|
||||
-- ["y"] = 243127.2973737,
|
||||
-- ["x"] = -5406.2803440839,
|
||||
-- ["name"] = "DictKey_WptName_53",
|
||||
-- ["speed"] = 138.88888888889,
|
||||
-- ["ETA_locked"] = false,
|
||||
-- ["task"] =
|
||||
-- {
|
||||
-- ["id"] = "ComboTask",
|
||||
-- ["params"] =
|
||||
-- {
|
||||
-- ["tasks"] =
|
||||
-- {
|
||||
-- }, -- end of ["tasks"]
|
||||
-- }, -- end of ["params"]
|
||||
-- }, -- end of ["task"]
|
||||
-- ["speed_locked"] = true,
|
||||
-- }, -- end of [4]
|
||||
|
||||
|
||||
local DCSGroup = self:GetDCSGroup()
|
||||
|
||||
if DCSGroup then
|
||||
|
||||
local GroupPoint = self:GetPointVec2()
|
||||
local GroupVelocity = self:GetMaxVelocity()
|
||||
|
||||
local PointFrom = {}
|
||||
PointFrom.x = GroupPoint.x
|
||||
PointFrom.y = GroupPoint.y
|
||||
PointFrom.type = "Turning Point"
|
||||
PointFrom.action = "Turning Point"
|
||||
PointFrom.speed = GroupVelocity
|
||||
|
||||
|
||||
local PointTo = {}
|
||||
local AirbasePoint = ReturnAirbase:GetPointVec2()
|
||||
|
||||
PointTo.x = AirbasePoint.x
|
||||
PointTo.y = AirbasePoint.y
|
||||
PointTo.type = "Land"
|
||||
PointTo.action = "Landing"
|
||||
PointTo.airdromeId = ReturnAirbase:GetID()-- Airdrome ID
|
||||
self:T(PointTo.airdromeId)
|
||||
--PointTo.alt = 0
|
||||
|
||||
local Points = { PointFrom, PointTo }
|
||||
|
||||
self:T3( Points )
|
||||
|
||||
local Route = { points = Points, }
|
||||
|
||||
return Route
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
--- @param Group#GROUP self
|
||||
function GROUP:Respawn( Template )
|
||||
|
||||
local Vec3 = self:GetPointVec3()
|
||||
--Template.x = Vec3.x
|
||||
--Template.y = Vec3.z
|
||||
Template.x = nil
|
||||
Template.y = nil
|
||||
|
||||
self:E( #Template.units )
|
||||
for UnitID, UnitData in pairs( self:GetUnits() ) do
|
||||
local GroupUnit = UnitData -- Unit#UNIT
|
||||
self:E( GroupUnit:GetName() )
|
||||
if GroupUnit:IsAlive() then
|
||||
local GroupUnitVec3 = GroupUnit:GetPointVec3()
|
||||
local GroupUnitHeading = GroupUnit:GetHeading()
|
||||
Template.units[UnitID].alt = GroupUnitVec3.y
|
||||
Template.units[UnitID].x = GroupUnitVec3.x
|
||||
Template.units[UnitID].y = GroupUnitVec3.z
|
||||
Template.units[UnitID].heading = GroupUnitHeading
|
||||
self:E( { UnitID, Template.units[UnitID], Template.units[UnitID] } )
|
||||
end
|
||||
end
|
||||
|
||||
_DATABASE:Spawn( Template )
|
||||
|
||||
end
|
||||
|
||||
function GROUP:GetTemplate()
|
||||
|
||||
return _DATABASE.Templates.Groups[self:GetName()].Template
|
||||
|
||||
end
|
||||
|
||||
-- Commands
|
||||
|
||||
--- Do Script command
|
||||
|
||||
@@ -10,6 +10,7 @@ Include.File( "Unit" )
|
||||
Include.File( "Zone" )
|
||||
Include.File( "Client" )
|
||||
Include.File( "Static" )
|
||||
Include.File( "Airbase" )
|
||||
Include.File( "Database" )
|
||||
Include.File( "Set" )
|
||||
Include.File( "Point" )
|
||||
@@ -38,40 +39,6 @@ Include.File( "MissileTrainer" )
|
||||
Include.File( "AIBalancer" )
|
||||
Include.File( "AirbasePolice" )
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
-- The order of the declarations is important here. Don't touch it.
|
||||
|
||||
--- Declare the event dispatcher based on the EVENT class
|
||||
|
||||
@@ -164,6 +164,7 @@ end
|
||||
|
||||
--- The POINT_VEC2 class
|
||||
-- @type POINT_VEC2
|
||||
-- @field DCSTypes#Vec2 PointVec2
|
||||
-- @extends Point#POINT_VEC3
|
||||
POINT_VEC2 = {
|
||||
ClassName = "POINT_VEC2",
|
||||
@@ -184,8 +185,36 @@ function POINT_VEC2:New( x, y, LandHeightAdd )
|
||||
|
||||
local self = BASE:Inherit( self, POINT_VEC3:New( x, LandHeight, y ) )
|
||||
self:F2( { x, y, LandHeightAdd } )
|
||||
|
||||
self.PointVec2 = { x = x, y = y }
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Calculate the distance from a reference @{Point#POINT_VEC2}.
|
||||
-- @param #POINT_VEC2 self
|
||||
-- @param #POINT_VEC2 PointVec2Reference The reference @{Point#POINT_VEC2}.
|
||||
-- @return DCSTypes#Distance The distance from the reference @{Point#POINT_VEC2} in meters.
|
||||
function POINT_VEC2:DistanceFromPointVec2( PointVec2Reference )
|
||||
self:F2( PointVec2Reference )
|
||||
|
||||
local Distance = ( ( PointVec2Reference.PointVec2.x - self.PointVec2.x ) ^ 2 + ( PointVec2Reference.PointVec2.y - self.PointVec2.y ) ^2 ) ^0.5
|
||||
|
||||
self:T2( Distance )
|
||||
return Distance
|
||||
end
|
||||
|
||||
--- Calculate the distance from a reference @{DCSTypes#Vec2}.
|
||||
-- @param #POINT_VEC2 self
|
||||
-- @param DCSTypes#Vec2 Vec2Reference The reference @{DCSTypes#Vec2}.
|
||||
-- @return DCSTypes#Distance The distance from the reference @{DCSTypes#Vec2} in meters.
|
||||
function POINT_VEC2:DistanceFromVec2( Vec2Reference )
|
||||
self:F2( Vec2Reference )
|
||||
|
||||
local Distance = ( ( Vec2Reference.x - self.PointVec2.x ) ^ 2 + ( Vec2Reference.y - self.PointVec2.y ) ^2 ) ^0.5
|
||||
|
||||
self:T2( Distance )
|
||||
return Distance
|
||||
end
|
||||
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
-- ===
|
||||
--
|
||||
-- 1) @{Set#SET_BASE} class, extends @{Base#BASE}
|
||||
-- ================================================
|
||||
-- ==============================================
|
||||
-- The @{Set#SET_BASE} class defines the core functions that define a collection of objects.
|
||||
-- A SET provides iterators to iterate the SET, but will **temporarily** yield the ForEach interator loop at defined **"intervals"** to the mail simulator loop.
|
||||
-- In this way, large loops can be done while not blocking the simulator main processing loop.
|
||||
@@ -14,15 +14,15 @@
|
||||
-- ---------------------------------------
|
||||
-- Some key core functions are @{Set#SET_BASE.Add} and @{Set#SET_BASE.Remove} to add or remove objects from the SET in your logic.
|
||||
--
|
||||
-- 1.2) Define the SET iterator **"yield interval"** and the **"time interval"**.
|
||||
-- -------------------------------------------------------------------------------------
|
||||
-- 1.2) Define the SET iterator **"yield interval"** and the **"time interval"**
|
||||
-- -----------------------------------------------------------------------------
|
||||
-- Modify the iterator intervals with the @{Set#SET_BASE.SetInteratorIntervals} method.
|
||||
-- You can set the **"yield interval"**, and the **"time interval"**. (See above).
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- 2) @{Set#SET_GROUP} class, extends @{Set#SET_BASE}
|
||||
-- ====================================================
|
||||
-- ==================================================
|
||||
-- Mission designers can use the @{Set#SET_GROUP} class to build sets of groups belonging to certain:
|
||||
--
|
||||
-- * Coalitions
|
||||
@@ -128,6 +128,8 @@
|
||||
-- * @{#SET_UNIT.ForEachUnitCompletelyInZone}: Iterate and call an iterator function for each **alive** UNIT presence completely in a @{Zone}, providing the UNIT and optional parameters to the called function.
|
||||
-- * @{#SET_UNIT.ForEachUnitNotInZone}: Iterate and call an iterator function for each **alive** UNIT presence not in a @{Zone}, providing the UNIT and optional parameters to the called function.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- 4) @{Set#SET_CLIENT} class, extends @{Set#SET_BASE}
|
||||
-- ===================================================
|
||||
-- Mission designers can use the @{Set#SET_CLIENT} class to build sets of units belonging to certain:
|
||||
@@ -178,9 +180,48 @@
|
||||
--
|
||||
-- ====
|
||||
--
|
||||
-- 5) @{Set#SET_AIRBASE} class, extends @{Set#SET_BASE}
|
||||
-- ====================================================
|
||||
-- Mission designers can use the @{Set#SET_AIRBASE} class to build sets of airbases optionally belonging to certain:
|
||||
--
|
||||
-- * Coalitions
|
||||
--
|
||||
-- 5.1) SET_AIRBASE construction
|
||||
-- -----------------------------
|
||||
-- Create a new SET_AIRBASE object with the @{#SET_AIRBASE.New} method:
|
||||
--
|
||||
-- * @{#SET_AIRBASE.New}: Creates a new SET_AIRBASE object.
|
||||
--
|
||||
-- 5.2) Add or Remove AIRBASEs from SET_AIRBASE
|
||||
-- --------------------------------------------
|
||||
-- AIRBASEs can be added and removed using the @{Set#SET_AIRBASE.AddAirbasesByName} and @{Set#SET_AIRBASE.RemoveAirbasesByName} respectively.
|
||||
-- These methods take a single AIRBASE name or an array of AIRBASE names to be added or removed from SET_AIRBASE.
|
||||
--
|
||||
-- 5.3) SET_AIRBASE filter criteria
|
||||
-- --------------------------------
|
||||
-- You can set filter criteria to define the set of clients within the SET_AIRBASE.
|
||||
-- Filter criteria are defined by:
|
||||
--
|
||||
-- * @{#SET_AIRBASE.FilterCoalitions}: Builds the SET_AIRBASE with the airbases belonging to the coalition(s).
|
||||
--
|
||||
-- Once the filter criteria have been set for the SET_AIRBASE, you can start filtering using:
|
||||
--
|
||||
-- * @{#SET_AIRBASE.FilterStart}: Starts the filtering of the airbases within the SET_AIRBASE.
|
||||
--
|
||||
-- 5.4) SET_AIRBASE iterators:
|
||||
-- ---------------------------
|
||||
-- Once the filters have been defined and the SET_AIRBASE has been built, you can iterate the SET_AIRBASE with the available iterator methods.
|
||||
-- The iterator methods will walk the SET_AIRBASE set, and call for each airbase within the set a function that you provide.
|
||||
-- The following iterator methods are currently available within the SET_AIRBASE:
|
||||
--
|
||||
-- * @{#SET_AIRBASE.ForEachAirbase}: Calls a function for each airbase it finds within the SET_AIRBASE.
|
||||
--
|
||||
-- ====
|
||||
--
|
||||
-- @module Set
|
||||
-- @author FlightControl
|
||||
|
||||
|
||||
--- SET_BASE class
|
||||
-- @type SET_BASE
|
||||
-- @extends Base#BASE
|
||||
@@ -279,6 +320,32 @@ function SET_BASE:_FilterStart()
|
||||
return self
|
||||
end
|
||||
|
||||
--- Iterate the SET_BASE while identifying the nearest object from a @{Point#POINT_VEC2}.
|
||||
-- @param #SET_BASE self
|
||||
-- @param Point#POINT_VEC2 PointVec2 A @{Point#POINT_VEC2} object from where to evaluate the closest object in the set.
|
||||
-- @return Base#BASE The closest object.
|
||||
function SET_BASE:FindNearestObjectFromPointVec2( PointVec2 )
|
||||
self:F2( PointVec2 )
|
||||
|
||||
local NearestObject = nil
|
||||
local ClosestDistance = nil
|
||||
|
||||
for ObjectID, ObjectData in pairs( self.Set ) do
|
||||
if NearestObject == nil then
|
||||
NearestObject = ObjectData
|
||||
ClosestDistance = PointVec2:DistanceFromVec2( ObjectData:GetPointVec2() )
|
||||
else
|
||||
local Distance = PointVec2:DistanceFromVec2( ObjectData:GetPointVec2() )
|
||||
if Distance < ClosestDistance then
|
||||
NearestObject = ObjectData
|
||||
ClosestDistance = Distance
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return NearestObject
|
||||
end
|
||||
|
||||
|
||||
|
||||
----- Private method that registers all alive players in the mission.
|
||||
@@ -420,7 +487,7 @@ function SET_BASE:ForEach( IteratorFunction, arg, Set, Function, FunctionArgumen
|
||||
end
|
||||
|
||||
|
||||
----- Interate the SET_BASE and call an interator function for each **alive** unit, providing the Unit and optional parameters.
|
||||
----- Iterate the SET_BASE and call an interator function for each **alive** unit, providing the Unit and optional parameters.
|
||||
---- @param #SET_BASE self
|
||||
---- @param #function IteratorFunction The function that will be called when there is an alive unit in the SET_BASE. The function needs to accept a UNIT parameter.
|
||||
---- @return #SET_BASE self
|
||||
@@ -432,7 +499,7 @@ end
|
||||
-- return self
|
||||
--end
|
||||
--
|
||||
----- Interate the SET_BASE and call an interator function for each **alive** player, providing the Unit of the player and optional parameters.
|
||||
----- Iterate the SET_BASE and call an interator function for each **alive** player, providing the Unit of the player and optional parameters.
|
||||
---- @param #SET_BASE self
|
||||
---- @param #function IteratorFunction The function that will be called when there is an alive player in the SET_BASE. The function needs to accept a UNIT parameter.
|
||||
---- @return #SET_BASE self
|
||||
@@ -445,7 +512,7 @@ end
|
||||
--end
|
||||
--
|
||||
--
|
||||
----- Interate the SET_BASE and call an interator function for each client, providing the Client to the function and optional parameters.
|
||||
----- Iterate the SET_BASE and call an interator function for each client, providing the Client to the function and optional parameters.
|
||||
---- @param #SET_BASE self
|
||||
---- @param #function IteratorFunction The function that will be called when there is an alive player in the SET_BASE. The function needs to accept a CLIENT parameter.
|
||||
---- @return #SET_BASE self
|
||||
@@ -767,7 +834,7 @@ function SET_GROUP:ForEachGroupNotInZone( ZoneObject, IteratorFunction, ... )
|
||||
end
|
||||
|
||||
|
||||
----- Interate the SET_GROUP and call an interator function for each **alive** player, providing the Group of the player and optional parameters.
|
||||
----- Iterate the SET_GROUP and call an interator function for each **alive** player, providing the Group of the player and optional parameters.
|
||||
---- @param #SET_GROUP self
|
||||
---- @param #function IteratorFunction The function that will be called when there is an alive player in the SET_GROUP. The function needs to accept a GROUP parameter.
|
||||
---- @return #SET_GROUP self
|
||||
@@ -780,7 +847,7 @@ end
|
||||
--end
|
||||
--
|
||||
--
|
||||
----- Interate the SET_GROUP and call an interator function for each client, providing the Client to the function and optional parameters.
|
||||
----- Iterate the SET_GROUP and call an interator function for each client, providing the Client to the function and optional parameters.
|
||||
---- @param #SET_GROUP self
|
||||
---- @param #function IteratorFunction The function that will be called when there is an alive player in the SET_GROUP. The function needs to accept a CLIENT parameter.
|
||||
---- @return #SET_GROUP self
|
||||
@@ -1074,7 +1141,7 @@ function SET_UNIT:FindInDatabase( Event )
|
||||
return Event.IniDCSUnitName, self.Database[Event.IniDCSUnitName]
|
||||
end
|
||||
|
||||
--- Interate the SET_UNIT and call an interator function for each **alive** UNIT, providing the UNIT and optional parameters.
|
||||
--- Iterate the SET_UNIT and call an interator function for each **alive** UNIT, providing the UNIT and optional parameters.
|
||||
-- @param #SET_UNIT self
|
||||
-- @param #function IteratorFunction The function that will be called when there is an alive UNIT in the SET_UNIT. The function needs to accept a UNIT parameter.
|
||||
-- @return #SET_UNIT self
|
||||
@@ -1132,7 +1199,7 @@ end
|
||||
|
||||
|
||||
|
||||
----- Interate the SET_UNIT and call an interator function for each **alive** player, providing the Unit of the player and optional parameters.
|
||||
----- Iterate the SET_UNIT and call an interator function for each **alive** player, providing the Unit of the player and optional parameters.
|
||||
---- @param #SET_UNIT self
|
||||
---- @param #function IteratorFunction The function that will be called when there is an alive player in the SET_UNIT. The function needs to accept a UNIT parameter.
|
||||
---- @return #SET_UNIT self
|
||||
@@ -1145,7 +1212,7 @@ end
|
||||
--end
|
||||
--
|
||||
--
|
||||
----- Interate the SET_UNIT and call an interator function for each client, providing the Client to the function and optional parameters.
|
||||
----- Iterate the SET_UNIT and call an interator function for each client, providing the Client to the function and optional parameters.
|
||||
---- @param #SET_UNIT self
|
||||
---- @param #function IteratorFunction The function that will be called when there is an alive player in the SET_UNIT. The function needs to accept a CLIENT parameter.
|
||||
---- @return #SET_UNIT self
|
||||
@@ -1447,7 +1514,7 @@ function SET_CLIENT:FindInDatabase( Event )
|
||||
return Event.IniDCSUnitName, self.Database[Event.IniDCSUnitName]
|
||||
end
|
||||
|
||||
--- Interate the SET_CLIENT and call an interator function for each **alive** CLIENT, providing the CLIENT and optional parameters.
|
||||
--- Iterate the SET_CLIENT and call an interator function for each **alive** CLIENT, providing the CLIENT and optional parameters.
|
||||
-- @param #SET_CLIENT self
|
||||
-- @param #function IteratorFunction The function that will be called when there is an alive CLIENT in the SET_CLIENT. The function needs to accept a CLIENT parameter.
|
||||
-- @return #SET_CLIENT self
|
||||
@@ -1583,3 +1650,226 @@ function SET_CLIENT:IsIncludeObject( MClient )
|
||||
return MClientInclude
|
||||
end
|
||||
|
||||
--- SET_AIRBASE
|
||||
|
||||
--- SET_AIRBASE class
|
||||
-- @type SET_AIRBASE
|
||||
-- @extends Set#SET_BASE
|
||||
SET_AIRBASE = {
|
||||
ClassName = "SET_AIRBASE",
|
||||
Airbases = {},
|
||||
Filter = {
|
||||
Coalitions = nil,
|
||||
},
|
||||
FilterMeta = {
|
||||
Coalitions = {
|
||||
red = coalition.side.RED,
|
||||
blue = coalition.side.BLUE,
|
||||
neutral = coalition.side.NEUTRAL,
|
||||
},
|
||||
Categories = {
|
||||
airdrome = Airbase.Category.AIRDROME,
|
||||
helipad = Airbase.Category.HELIPAD,
|
||||
ship = Airbase.Category.SHIP,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
--- Creates a new SET_AIRBASE object, building a set of airbases belonging to a coalitions and categories.
|
||||
-- @param #SET_AIRBASE self
|
||||
-- @return #SET_AIRBASE self
|
||||
-- @usage
|
||||
-- -- Define a new SET_AIRBASE Object. The DatabaseSet will contain a reference to all Airbases.
|
||||
-- DatabaseSet = SET_AIRBASE:New()
|
||||
function SET_AIRBASE:New()
|
||||
-- Inherits from BASE
|
||||
local self = BASE:Inherit( self, SET_BASE:New( _DATABASE.AIRBASES ) )
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Add AIRBASEs to SET_AIRBASE.
|
||||
-- @param Set#SET_AIRBASE self
|
||||
-- @param #string AddAirbaseNames A single name or an array of AIRBASE names.
|
||||
-- @return self
|
||||
function SET_AIRBASE:AddAirbasesByName( AddAirbaseNames )
|
||||
|
||||
local AddAirbaseNamesArray = ( type( AddAirbaseNames ) == "table" ) and AddAirbaseNames or { AddAirbaseNames }
|
||||
|
||||
for AddAirbaseID, AddAirbaseName in pairs( AddAirbaseNamesArray ) do
|
||||
self:Add( AddAirbaseName, AIRBASE:FindByName( AddAirbaseName ) )
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Remove AIRBASEs from SET_AIRBASE.
|
||||
-- @param Set#SET_AIRBASE self
|
||||
-- @param Airbase#AIRBASE RemoveAirbaseNames A single name or an array of AIRBASE names.
|
||||
-- @return self
|
||||
function SET_AIRBASE:RemoveAirbasesByName( RemoveAirbaseNames )
|
||||
|
||||
local RemoveAirbaseNamesArray = ( type( RemoveAirbaseNames ) == "table" ) and RemoveAirbaseNames or { RemoveAirbaseNames }
|
||||
|
||||
for RemoveAirbaseID, RemoveAirbaseName in pairs( RemoveAirbaseNamesArray ) do
|
||||
self:Remove( RemoveAirbaseName.AirbaseName )
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Finds a Airbase based on the Airbase Name.
|
||||
-- @param #SET_AIRBASE self
|
||||
-- @param #string AirbaseName
|
||||
-- @return Airbase#AIRBASE The found Airbase.
|
||||
function SET_AIRBASE:FindAirbase( AirbaseName )
|
||||
|
||||
local AirbaseFound = self.Set[AirbaseName]
|
||||
return AirbaseFound
|
||||
end
|
||||
|
||||
|
||||
|
||||
--- Builds a set of airbases of coalitions.
|
||||
-- Possible current coalitions are red, blue and neutral.
|
||||
-- @param #SET_AIRBASE self
|
||||
-- @param #string Coalitions Can take the following values: "red", "blue", "neutral".
|
||||
-- @return #SET_AIRBASE self
|
||||
function SET_AIRBASE:FilterCoalitions( Coalitions )
|
||||
if not self.Filter.Coalitions then
|
||||
self.Filter.Coalitions = {}
|
||||
end
|
||||
if type( Coalitions ) ~= "table" then
|
||||
Coalitions = { Coalitions }
|
||||
end
|
||||
for CoalitionID, Coalition in pairs( Coalitions ) do
|
||||
self.Filter.Coalitions[Coalition] = Coalition
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Builds a set of airbases out of categories.
|
||||
-- Possible current categories are plane, helicopter, ground, ship.
|
||||
-- @param #SET_AIRBASE self
|
||||
-- @param #string Categories Can take the following values: "airdrome", "helipad", "ship".
|
||||
-- @return #SET_AIRBASE self
|
||||
function SET_AIRBASE:FilterCategories( Categories )
|
||||
if not self.Filter.Categories then
|
||||
self.Filter.Categories = {}
|
||||
end
|
||||
if type( Categories ) ~= "table" then
|
||||
Categories = { Categories }
|
||||
end
|
||||
for CategoryID, Category in pairs( Categories ) do
|
||||
self.Filter.Categories[Category] = Category
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- Starts the filtering.
|
||||
-- @param #SET_AIRBASE self
|
||||
-- @return #SET_AIRBASE self
|
||||
function SET_AIRBASE:FilterStart()
|
||||
|
||||
if _DATABASE then
|
||||
self:_FilterStart()
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Handles the Database to check on an event (birth) that the Object was added in the Database.
|
||||
-- This is required, because sometimes the _DATABASE birth event gets called later than the SET_BASE birth event!
|
||||
-- @param #SET_AIRBASE self
|
||||
-- @param Event#EVENTDATA Event
|
||||
-- @return #string The name of the AIRBASE
|
||||
-- @return #table The AIRBASE
|
||||
function SET_AIRBASE:AddInDatabase( Event )
|
||||
self:F3( { Event } )
|
||||
|
||||
return Event.IniDCSUnitName, self.Database[Event.IniDCSUnitName]
|
||||
end
|
||||
|
||||
--- Handles the Database to check on any event that Object exists in the Database.
|
||||
-- This is required, because sometimes the _DATABASE event gets called later than the SET_BASE event or vise versa!
|
||||
-- @param #SET_AIRBASE self
|
||||
-- @param Event#EVENTDATA Event
|
||||
-- @return #string The name of the AIRBASE
|
||||
-- @return #table The AIRBASE
|
||||
function SET_AIRBASE:FindInDatabase( Event )
|
||||
self:F3( { Event } )
|
||||
|
||||
return Event.IniDCSUnitName, self.Database[Event.IniDCSUnitName]
|
||||
end
|
||||
|
||||
--- Iterate the SET_AIRBASE and call an interator function for each AIRBASE, providing the AIRBASE and optional parameters.
|
||||
-- @param #SET_AIRBASE self
|
||||
-- @param #function IteratorFunction The function that will be called when there is an alive AIRBASE in the SET_AIRBASE. The function needs to accept a AIRBASE parameter.
|
||||
-- @return #SET_AIRBASE self
|
||||
function SET_AIRBASE:ForEachAirbase( IteratorFunction, ... )
|
||||
self:F2( arg )
|
||||
|
||||
self:ForEach( IteratorFunction, arg, self.Set )
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Iterate the SET_AIRBASE while identifying the nearest @{Airbase#AIRBASE} from a @{Point#POINT_VEC2}.
|
||||
-- @param #SET_AIRBASE self
|
||||
-- @param Point#POINT_VEC2 PointVec2 A @{Point#POINT_VEC2} object from where to evaluate the closest @{Airbase#AIRBASE}.
|
||||
-- @return Airbase#AIRBASE The closest @{Airbase#AIRBASE}.
|
||||
function SET_AIRBASE:FindNearestAirbaseFromPointVec2( PointVec2 )
|
||||
self:F2( PointVec2 )
|
||||
|
||||
local NearestAirbase = self:FindNearestObjectFromPointVec2( PointVec2 )
|
||||
return NearestAirbase
|
||||
end
|
||||
|
||||
|
||||
|
||||
---
|
||||
-- @param #SET_AIRBASE self
|
||||
-- @param Airbase#AIRBASE MAirbase
|
||||
-- @return #SET_AIRBASE self
|
||||
function SET_AIRBASE:IsIncludeObject( MAirbase )
|
||||
self:F2( MAirbase )
|
||||
|
||||
local MAirbaseInclude = true
|
||||
|
||||
if MAirbase then
|
||||
local MAirbaseName = MAirbase:GetName()
|
||||
|
||||
if self.Filter.Coalitions then
|
||||
local MAirbaseCoalition = false
|
||||
for CoalitionID, CoalitionName in pairs( self.Filter.Coalitions ) do
|
||||
local AirbaseCoalitionID = _DATABASE:GetCoalitionFromAirbase( MAirbaseName )
|
||||
self:T3( { "Coalition:", AirbaseCoalitionID, self.FilterMeta.Coalitions[CoalitionName], CoalitionName } )
|
||||
if self.FilterMeta.Coalitions[CoalitionName] and self.FilterMeta.Coalitions[CoalitionName] == AirbaseCoalitionID then
|
||||
MAirbaseCoalition = true
|
||||
end
|
||||
end
|
||||
self:T( { "Evaluated Coalition", MAirbaseCoalition } )
|
||||
MAirbaseInclude = MAirbaseInclude and MAirbaseCoalition
|
||||
end
|
||||
|
||||
if self.Filter.Categories then
|
||||
local MAirbaseCategory = false
|
||||
for CategoryID, CategoryName in pairs( self.Filter.Categories ) do
|
||||
local AirbaseCategoryID = _DATABASE:GetCategoryFromAirbase( MAirbaseName )
|
||||
self:T3( { "Category:", AirbaseCategoryID, self.FilterMeta.Categories[CategoryName], CategoryName } )
|
||||
if self.FilterMeta.Categories[CategoryName] and self.FilterMeta.Categories[CategoryName] == AirbaseCategoryID then
|
||||
MAirbaseCategory = true
|
||||
end
|
||||
end
|
||||
self:T( { "Evaluated Category", MAirbaseCategory } )
|
||||
MAirbaseInclude = MAirbaseInclude and MAirbaseCategory
|
||||
end
|
||||
end
|
||||
|
||||
self:T2( MAirbaseInclude )
|
||||
return MAirbaseInclude
|
||||
end
|
||||
|
||||
@@ -736,6 +736,29 @@ function UNIT:GetCategoryName()
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Returns the DCS Unit heading.
|
||||
-- @param Unit#UNIT self
|
||||
-- @return #number The DCS Unit heading
|
||||
function UNIT:GetHeading()
|
||||
local DCSUnit = self:GetDCSUnit()
|
||||
|
||||
if DCSUnit then
|
||||
|
||||
local UnitPosition = DCSUnit:getPosition()
|
||||
if UnitPosition then
|
||||
local UnitHeading = math.atan2( UnitPosition.x.z, UnitPosition.x.x )
|
||||
if UnitHeading < 0 then
|
||||
UnitHeading = UnitHeading + 2 * math.pi
|
||||
end
|
||||
self:T2( UnitHeading )
|
||||
return UnitHeading
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
--- Signal a flare at the position of the UNIT.
|
||||
-- @param #UNIT self
|
||||
function UNIT:Flare( FlareColor )
|
||||
|
||||
Reference in New Issue
Block a user