diff --git a/Moose Development/Moose/Detection.lua b/Moose Development/Moose/Detection.lua index 6f6f1787f..11e762e5b 100644 --- a/Moose Development/Moose/Detection.lua +++ b/Moose Development/Moose/Detection.lua @@ -11,20 +11,33 @@ -- @author Mechanic : Concept & Testing -- @author FlightControl : Design & Programming + + --- DETECTION_BASE class -- @type DETECTION_BASE -- @field Group#GROUP FACGroup The GROUP in the Forward Air Controller role. -- @field DCSTypes#Distance DetectionRange The range till which targets are accepted to be detected. -- @field DCSTypes#Distance DetectionZoneRange The range till which targets are grouped upon the first detected target. +-- @field #DETECTION_BASE.DetectedUnitSets DetectedUnitSets A list of @{Set#SET_UNIT}s containing the units in each set that were detected within a DetectedZoneRange. +-- @field #DETECTION_BASE.DetectedZones DetectedZones A list of @{Zone#ZONE_UNIT}s containing the zones of the reference detected units. -- @extends Set#SET_BASE DETECTION_BASE = { ClassName = "DETECTION_BASE", - Sets = {}, + DetectedUnitSets = {}, + DetectedUnits = {}, FACGroup = nil, DetectionRange = nil, DetectionZoneRange = nil, } +--- @type DETECTION_BASE.DetectedUnitSets +-- @list + + +--- @type DETECTION_BASE.DetectedZones +-- @list + + --- DETECTION constructor. -- @param #DETECTION_BASE self -- @return #DETECTION_BASE self @@ -37,7 +50,7 @@ function DETECTION_BASE:New( FACGroup, DetectionRange, DetectionZoneRange ) self.DetectionRange = DetectionRange self.DetectionZoneRange = DetectionZoneRange - self.DetectionScheduler = SCHEDULER:New(self, self._DetectionScheduler, { self, "Detection" }, 1, 30, 0.2 ) + self.DetectionScheduler = SCHEDULER:New(self, self._DetectionScheduler, { self, "Detection" }, 10, 30, 0.2 ) end --- Form @{Set}s of detected @{Unit#UNIT}s in an array of @{Set#SET_UNIT}s. @@ -45,7 +58,7 @@ end function DETECTION_BASE:_DetectionScheduler( SchedulerName ) self:F2( { SchedulerName } ) - self.Sets = {} + self.DetectedUnitSets = {} if self.FACGroup:IsAlive() then local FACGroupName = self.FACGroup:GetName() @@ -57,36 +70,91 @@ function DETECTION_BASE:_DetectionScheduler( SchedulerName ) if FACObject and FACObject:isExist() and FACObject.id_ < 50000000 then - local FACDetectedTargetUnit = UNIT:Find( FACObject ) - local FACDetectedTargetUnitName = FACDetectedTargetUnit:GetName() + local FACDetectedUnit = UNIT:Find( FACObject ) + local FACDetectedUnitName = FACDetectedUnit:GetName() - local FACDetectedTargetUnitPositionVec3 = FACDetectedTargetUnit:GetPointVec3() + local FACDetectedUnitPositionVec3 = FACDetectedUnit:GetPointVec3() local FACGroupPositionVec3 = self.FACGroup:GetPointVec3() - local Distance = ( ( FACDetectedTargetUnitPositionVec3.x - FACGroupPositionVec3.x )^2 + - ( FACDetectedTargetUnitPositionVec3.y - FACGroupPositionVec3.y )^2 + - ( FACDetectedTargetUnitPositionVec3.z - FACGroupPositionVec3.z )^2 + local Distance = ( ( FACDetectedUnitPositionVec3.x - FACGroupPositionVec3.x )^2 + + ( FACDetectedUnitPositionVec3.y - FACGroupPositionVec3.y )^2 + + ( FACDetectedUnitPositionVec3.z - FACGroupPositionVec3.z )^2 ) ^ 0.5 / 1000 - self:T( { self.FACGroup:GetName(), FACDetectedTargetUnit:GetName(), Distance } ) + self:T( { FACGroupName, FACDetectedUnitName, Distance } ) - if Distance <= self then + if Distance <= self.DetectionRange then - if not ClientEscortTargets[EscortTargetUnitName] then - ClientEscortTargets[EscortTargetUnitName] = {} + if not self.DetectedUnits[FACDetectedUnitName] then + self.DetectedUnits[FACDetectedUnitName] = {} end - ClientEscortTargets[EscortTargetUnitName].AttackUnit = FACDetectedTargetUnit - ClientEscortTargets[EscortTargetUnitName].visible = EscortTarget.visible - ClientEscortTargets[EscortTargetUnitName].type = EscortTarget.type - ClientEscortTargets[EscortTargetUnitName].distance = EscortTarget.distance + self.DetectedUnits[FACDetectedUnitName].DetectedUnit = UNIT:FindByName( FACDetectedUnitName ) + self.DetectedUnits[FACDetectedUnitName].Visible = FACDetectedTarget.visible + self.DetectedUnits[FACDetectedUnitName].Type = FACDetectedTarget.type + self.DetectedUnits[FACDetectedUnitName].Distance = FACDetectedTarget.distance else - if ClientEscortTargets[EscortTargetUnitName] then - ClientEscortTargets[EscortTargetUnitName] = nil + -- if beyond the DetectionRange then nullify... + if self.DetectedUnits[FACDetectedUnitName] then + self.DetectedUnits[FACDetectedUnitName] = nil end end end - end + + -- okay, now we have a list of detected unit names ... + -- Sort the table based on distance ... + self:T( { "Sorting DetectedUnits table:", self.DetectedUnits } ) + table.sort( self.DetectedUnits, function( a, b ) return a.Distance < b.Distance end ) + self:T( { "Sorted Targets Table:", self.DetectedUnits } ) + -- Now group the DetectedUnits table into SET_UNITs, evaluating the DetectionZoneRange. + + if self.DetectedUnits then + for DetectedUnitName, DetectedUnitData in pairs( self.DetectedUnits ) do + local DetectedUnit = DetectedUnitData.DetectedUnit -- Unit#UNIT + self:T( DetectedUnit:GetName() ) + if #self.DetectedUnitSets == 0 then + self:T( { "Adding Unit Set #", 1 } ) + self.DetectedUnitSets[1] = {} + self.DetectedUnitSets[1].Zone = ZONE_UNIT:New( DetectedUnitName, DetectedUnit, self.DetectionZoneRange ) + self.DetectedUnitSets[1].Set = SET_UNIT:New() + self.DetectedUnitSets[1].Set:AddUnit( DetectedUnit ) + else + local AddedToSet = false + for DetectedUnitSetID, DetectedUnitSetData in pairs( self.DetectedUnitSets ) do + self:T( "Detected Unit Set #" .. DetectedUnitSetID ) + local DetectedUnitSet = DetectedUnitSetData.Set -- Set#SET_UNIT + local DetectedZone = DetectedUnitSetData.Zone -- Zone#ZONE_UNIT + if DetectedUnit:IsInZone( DetectedZone ) then + self:T( "Adding to Unit Set #" .. DetectedUnitSetID ) + self.DetectedUnitSets[DetectedUnitSetID].Set:AddUnit( DetectedUnit ) + AddedToSet = true + end + end + if AddedToSet == false then + self:T( "Adding new Unit Set #" .. #self.DetectedUnitSets+1 ) + self.DetectedUnitSets[#self.DetectedUnitSets+1] = {} + self.DetectedUnitSets[#self.DetectedUnitSets].Zone = ZONE_UNIT:New( DetectedUnitName, DetectedUnit, self.DetectionZoneRange ) + self.DetectedUnitSets[#self.DetectedUnitSets].Set = SET_UNIT:New() + self.DetectedUnitSets[#self.DetectedUnitSets].Set:AddUnit( DetectedUnit ) + end + end + end + end + + -- Now all the tests should have been build, now make some smoke and flares... + + for DetectedUnitSetID, DetectedUnitSetData in pairs( self.DetectedUnitSets ) do + local DetectedUnitSet = DetectedUnitSetData.Set -- Set#SET_UNIT + local DetectedZone = DetectedUnitSetData.Zone -- Zone#ZONE_UNIT + self:T( "Detected Set #" .. DetectedUnitSetID ) + DetectedUnitSet:ForEachUnit( + --- @param Unit#UNIT DetectedUnit + function( DetectedUnit ) + self:T( DetectedUnit:GetName() ) + DetectedUnit:FlareRed() + end + ) + DetectedZone:SmokeZone( POINT_VEC3.SmokeColor.White, 30 ) + end end - end \ No newline at end of file diff --git a/Moose Development/Moose/Moose.lua b/Moose Development/Moose/Moose.lua index f6f3cafe8..8d9f43635 100644 --- a/Moose Development/Moose/Moose.lua +++ b/Moose Development/Moose/Moose.lua @@ -37,6 +37,7 @@ Include.File( "Escort" ) Include.File( "MissileTrainer" ) Include.File( "AIBalancer" ) Include.File( "AirbasePolice" ) +Include.File( "Detection" ) diff --git a/Moose Development/Moose/Set.lua b/Moose Development/Moose/Set.lua index 412d4af52..b35a693b6 100644 --- a/Moose Development/Moose/Set.lua +++ b/Moose Development/Moose/Set.lua @@ -197,8 +197,6 @@ SET_BASE = { -- DBObject = SET_BASE:New() function SET_BASE:New( Database ) - env.info( tostring( Database ) ) - -- Inherits from BASE local self = BASE:Inherit( self, BASE:New() ) @@ -894,13 +892,26 @@ function SET_UNIT:New() end --- Add UNIT(s) to SET_UNIT. --- @param Set#SET_UNIT self +-- @param #SET_UNIT self +-- @param #string AddUnit A single UNIT. +-- @return #SET_UNIT self +function SET_UNIT:AddUnit( AddUnit ) + + self:Add( AddUnit:GetName(), AddUnit ) + + return self +end + + +--- Add UNIT(s) to SET_UNIT. +-- @param #SET_UNIT self -- @param #string AddUnitNames A single name or an array of UNIT names. --- @return self +-- @return #SET_UNIT self function SET_UNIT:AddUnitsByName( AddUnitNames ) local AddUnitNamesArray = ( type( AddUnitNames ) == "table" ) and AddUnitNames or { AddUnitNames } + self:T( AddUnitNamesArray ) for AddUnitID, AddUnitName in pairs( AddUnitNamesArray ) do self:Add( AddUnitName, UNIT:FindByName( AddUnitName ) ) end diff --git a/Moose Mission Setup/Moose Mission Update/l10n/DEFAULT/Moose.lua b/Moose Mission Setup/Moose Mission Update/l10n/DEFAULT/Moose.lua index 9c8bf3739..15c498977 100644 --- a/Moose Mission Setup/Moose Mission Update/l10n/DEFAULT/Moose.lua +++ b/Moose Mission Setup/Moose Mission Update/l10n/DEFAULT/Moose.lua @@ -1,5 +1,5 @@ env.info( '*** MOOSE STATIC INCLUDE START *** ' ) -env.info( 'Moose Generation Timestamp: 20160615_0641' ) +env.info( 'Moose Generation Timestamp: 20160615_2239' ) local base = _G Include = {} @@ -3150,8 +3150,8 @@ end -- -- * @{Scheduler#SCHEDULER.New}: Setup a new scheduler and start it with the specified parameters. -- --- SCHEDULER timer stop and start --- ------------------------------ +-- 1.2) SCHEDULER timer stop and start +-- ----------------------------------- -- The SCHEDULER can be stopped and restarted with the following methods: -- -- * @{Scheduler#SCHEDULER.Start}: (Re-)Start the scheduler. @@ -3160,6 +3160,7 @@ end -- @module Scheduler -- @author FlightControl + --- The SCHEDULER class -- @type SCHEDULER -- @field #number ScheduleID the ID of the scheduler. @@ -9752,8 +9753,6 @@ SET_BASE = { -- DBObject = SET_BASE:New() function SET_BASE:New( Database ) - env.info( tostring( Database ) ) - -- Inherits from BASE local self = BASE:Inherit( self, BASE:New() ) @@ -10449,13 +10448,26 @@ function SET_UNIT:New() end --- Add UNIT(s) to SET_UNIT. --- @param Set#SET_UNIT self +-- @param #SET_UNIT self +-- @param #string AddUnit A single UNIT. +-- @return #SET_UNIT self +function SET_UNIT:AddUnit( AddUnit ) + + self:Add( AddUnit:GetName(), AddUnit ) + + return self +end + + +--- Add UNIT(s) to SET_UNIT. +-- @param #SET_UNIT self -- @param #string AddUnitNames A single name or an array of UNIT names. --- @return self +-- @return #SET_UNIT self function SET_UNIT:AddUnitsByName( AddUnitNames ) local AddUnitNamesArray = ( type( AddUnitNames ) == "table" ) and AddUnitNames or { AddUnitNames } + self:T( AddUnitNamesArray ) for AddUnitID, AddUnitName in pairs( AddUnitNamesArray ) do self:Add( AddUnitName, UNIT:FindByName( AddUnitName ) ) end @@ -11368,6 +11380,7 @@ Include.File( "Escort" ) Include.File( "MissileTrainer" ) Include.File( "AIBalancer" ) Include.File( "AirbasePolice" ) +Include.File( "Detection" ) @@ -20206,6 +20219,1090 @@ end +--- This module contains the AIRBASEPOLICE classes. +-- +-- === +-- +-- 1) @{AirbasePolice#AIRBASEPOLICE_BASE} class, extends @{Base#BASE} +-- ================================================================== +-- The @{AirbasePolice#AIRBASEPOLICE_BASE} class provides the main methods to monitor CLIENT behaviour at airbases. +-- CLIENTS should not be allowed to: +-- +-- * Don't taxi faster than 40 km/h. +-- * Don't take-off on taxiways. +-- * Avoid to hit other planes on the airbase. +-- * Obey ground control orders. +-- +-- 2) @{AirbasePolice#AIRBASEPOLICE_CAUCASUS} class, extends @{AirbasePolice#AIRBASEPOLICE_BASE} +-- ============================================================================================= +-- All the airbases on the caucasus map can be monitored using this class. +-- If you want to monitor specific airbases, you need to use the @{#AIRBASEPOLICE_BASE.Monitor}() method, which takes a table or airbase names. +-- The following names can be given: +-- * AnapaVityazevo +-- * Batumi +-- * Beslan +-- * Gelendzhik +-- * Gudauta +-- * Kobuleti +-- * KrasnodarCenter +-- * KrasnodarPashkovsky +-- * Krymsk +-- * Kutaisi +-- * MaykopKhanskaya +-- * MineralnyeVody +-- * Mozdok +-- * Nalchik +-- * Novorossiysk +-- * SenakiKolkhi +-- * SochiAdler +-- * Soganlug +-- * SukhumiBabushara +-- * TbilisiLochini +-- * Vaziani +-- +-- @module AirbasePolice +-- @author FlightControl + +--- @type AIRBASEPOLICE_BASE +-- @field Set#SET_CLIENT SetClient +-- @extends Base#BASE + +AIRBASEPOLICE_BASE = { + ClassName = "AIRBASEPOLICE_BASE", + SetClient = nil, + Airbases = nil, + AirbaseNames = nil, +} + + +--- Creates a new AIRBASEPOLICE_BASE object. +-- @param #AIRBASEPOLICE_BASE self +-- @param SetClient A SET_CLIENT object that will contain the CLIENT objects to be monitored if they follow the rules of the airbase. +-- @param Airbases A table of Airbase Names. +-- @return #AIRBASEPOLICE_BASE self +function AIRBASEPOLICE_BASE:New( SetClient, Airbases ) + + -- Inherits from BASE + local self = BASE:Inherit( self, BASE:New() ) + self:E( { self.ClassName, SetClient, Airbases } ) + + self.SetClient = SetClient + self.Airbases = Airbases + + for AirbaseID, Airbase in pairs( self.Airbases ) do + Airbase.ZoneBoundary = ZONE_POLYGON_BASE:New( "Boundary", Airbase.PointsBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush() + for PointsRunwayID, PointsRunway in pairs( Airbase.PointsRunways ) do + Airbase.ZoneRunways[PointsRunwayID] = ZONE_POLYGON_BASE:New( "Runway " .. PointsRunwayID, PointsRunway ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush() + end + end + + -- -- Template + -- local TemplateBoundary = GROUP:FindByName( "Template Boundary" ) + -- self.Airbases.Template.ZoneBoundary = ZONE_POLYGON:New( "Template Boundary", TemplateBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush() + -- + -- local TemplateRunway1 = GROUP:FindByName( "Template Runway 1" ) + -- self.Airbases.Template.ZoneRunways[1] = ZONE_POLYGON:New( "Template Runway 1", TemplateRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush() + + self.SetClient:ForEachClient( + --- @param Client#CLIENT Client + function( Client ) + Client:SetState( self, "Speeding", false ) + Client:SetState( self, "Warnings", 0) + Client:SetState( self, "Taxi", false ) + end + ) + + self.AirbaseMonitor = SCHEDULER:New( self, self._AirbaseMonitor, {}, 0, 2, 0.05 ) + + return self +end + +--- @type AIRBASEPOLICE_BASE.AirbaseNames +-- @list <#string> + +--- Monitor a table of airbase names. +-- @param #AIRBASEPOLICE_BASE self +-- @param #AIRBASEPOLICE_BASE.AirbaseNames AirbaseNames A list of AirbaseNames to monitor. If this parameters is nil, then all airbases will be monitored. +-- @return #AIRBASEPOLICE_BASE self +function AIRBASEPOLICE_BASE:Monitor( AirbaseNames ) + + if AirbaseNames then + if type( AirbaseNames ) == "table" then + self.AirbaseNames = AirbaseNames + else + self.AirbaseNames = { AirbaseNames } + end + end +end + +--- @param #AIRBASEPOLICE_BASE self +function AIRBASEPOLICE_BASE:_AirbaseMonitor() + + for AirbaseID, Airbase in pairs( self.Airbases ) do + + if not self.AirbaseNames or self.AirbaseNames[AirbaseID] then + + self:E( AirbaseID ) + + self.SetClient:ForEachClientInZone( Airbase.ZoneBoundary, + + --- @param Client#CLIENT Client + function( Client ) + + self:E( Client.UnitName ) + if Client:IsAlive() then + local NotInRunwayZone = true + for ZoneRunwayID, ZoneRunway in pairs( Airbase.ZoneRunways ) do + NotInRunwayZone = ( Client:IsNotInZone( ZoneRunway ) == true ) and NotInRunwayZone or false + end + + if NotInRunwayZone then + local Taxi = self:GetState( self, "Taxi" ) + self:E( Taxi ) + if Taxi == false then + Client:Message( "Welcome at " .. AirbaseID .. ". The maximum taxiing speed is " .. Airbase.MaximumSpeed " km/h.", 20, "ATC" ) + self:SetState( self, "Taxi", true ) + end + + local VelocityVec3 = Client:GetVelocity() + local Velocity = math.abs(VelocityVec3.x) + math.abs(VelocityVec3.y) + math.abs(VelocityVec3.z) + local IsAboveRunway = Client:IsAboveRunway() + local IsOnGround = Client:InAir() == false + self:T( IsAboveRunway, IsOnGround ) + + if IsAboveRunway and IsOnGround then + + if Velocity > Airbase.MaximumSpeed then + local IsSpeeding = Client:GetState( self, "Speeding" ) + + if IsSpeeding == true then + local SpeedingWarnings = Client:GetState( self, "Warnings" ) + self:T( SpeedingWarnings ) + + if SpeedingWarnings <= 5 then + Client:Message( "You are speeding on the taxiway! Slow down or you will be removed from this airbase! Your current velocity is " .. string.format( "%2.0f km/h", Velocity ), 5, "Warning " .. SpeedingWarnings .. " / 5" ) + Client:SetState( self, "Warnings", SpeedingWarnings + 1 ) + else + MESSAGE:New( "Player " .. Client:GetPlayerName() .. " has been removed from the airbase, due to a speeding violation ...", 10, "Airbase Police" ):ToAll() + Client:GetGroup():Destroy() + Client:SetState( self, "Speeding", false ) + Client:SetState( self, "Warnings", 0 ) + end + + else + Client:Message( "You are speeding on the taxiway! Slow down please ...! Your current velocity is " .. string.format( "%2.0f km/h", Velocity ), 5, "Attention! " ) + Client:SetState( self, "Speeding", true ) + Client:SetState( self, "Warnings", 1 ) + end + + else + Client:SetState( self, "Speeding", false ) + Client:SetState( self, "Warnings", 0 ) + end + end + + else + Client:SetState( self, "Speeding", false ) + Client:SetState( self, "Warnings", 0 ) + local Taxi = self:GetState( self, "Taxi" ) + if Taxi == true then + Client:Message( "You have progressed to the runway ... Await take-off clearance ...", 20, "ATC" ) + self:SetState( self, "Taxi", false ) + end + end + end + end + ) + end + end + + return true +end + + +--- @type AIRBASEPOLICE_CAUCASUS +-- @field Set#SET_CLIENT SetClient +-- @extends #AIRBASEPOLICE_BASE + +AIRBASEPOLICE_CAUCASUS = { + ClassName = "AIRBASEPOLICE_CAUCASUS", + Airbases = { + AnapaVityazevo = { + PointsBoundary = { + [1]={["y"]=242234.85714287,["x"]=-6616.5714285726,}, + [2]={["y"]=241060.57142858,["x"]=-5585.142857144,}, + [3]={["y"]=243806.2857143,["x"]=-3962.2857142868,}, + [4]={["y"]=245240.57142858,["x"]=-4816.5714285726,}, + [5]={["y"]=244783.42857144,["x"]=-5630.8571428583,}, + [6]={["y"]=243800.57142858,["x"]=-5065.142857144,}, + [7]={["y"]=242232.00000001,["x"]=-6622.2857142868,}, + }, + PointsRunways = { + [1] = { + }, + }, + ZoneBoundary = {}, + ZoneRunways = {}, + MaximumSpeed = 50, + }, + Batumi = { + PointsBoundary = { + [1]={["y"]=617567.14285714,["x"]=-355313.14285715,}, + [2]={["y"]=616181.42857142,["x"]=-354800.28571429,}, + [3]={["y"]=616007.14285714,["x"]=-355128.85714286,}, + [4]={["y"]=618230,["x"]=-356914.57142858,}, + [5]={["y"]=618727.14285714,["x"]=-356166,}, + [6]={["y"]=617572.85714285,["x"]=-355308.85714286,}, + }, + PointsRunways = { + [1] = { + [1]={["y"]=616442.28571429,["x"]=-355090.28571429,}, + [2]={["y"]=618450.57142857,["x"]=-356522,}, + [3]={["y"]=618407.71428571,["x"]=-356584.85714286,}, + [4]={["y"]=618361.99999999,["x"]=-356554.85714286,}, + [5]={["y"]=618324.85714285,["x"]=-356599.14285715,}, + [6]={["y"]=618250.57142856,["x"]=-356543.42857143,}, + [7]={["y"]=618257.7142857,["x"]=-356496.28571429,}, + [8]={["y"]=618237.7142857,["x"]=-356459.14285715,}, + [9]={["y"]=616555.71428571,["x"]=-355258.85714286,}, + [10]={["y"]=616486.28571428,["x"]=-355280.57142858,}, + [11]={["y"]=616410.57142856,["x"]=-355227.71428572,}, + [12]={["y"]=616441.99999999,["x"]=-355179.14285715,}, + [13]={["y"]=616401.99999999,["x"]=-355147.71428572,}, + [14]={["y"]=616441.42857142,["x"]=-355092.57142858,}, + }, + }, + ZoneBoundary = {}, + ZoneRunways = {}, + MaximumSpeed = 50, + }, + Beslan = { + PointsBoundary = { + [1]={["y"]=842082.57142857,["x"]=-148445.14285715,}, + [2]={["y"]=845237.71428572,["x"]=-148639.71428572,}, + [3]={["y"]=845232,["x"]=-148765.42857143,}, + [4]={["y"]=844220.57142857,["x"]=-149168.28571429,}, + [5]={["y"]=843274.85714286,["x"]=-149125.42857143,}, + [6]={["y"]=842077.71428572,["x"]=-148554,}, + [7]={["y"]=842083.42857143,["x"]=-148445.42857143,}, + }, + PointsRunways = { + [1] = { + [1]={["y"]=842104.57142857,["x"]=-148460.57142857,}, + [2]={["y"]=845225.71428572,["x"]=-148656,}, + [3]={["y"]=845220.57142858,["x"]=-148750,}, + [4]={["y"]=842098.85714286,["x"]=-148556.28571429,}, + [5]={["y"]=842104,["x"]=-148460.28571429,}, + }, + }, + ZoneBoundary = {}, + ZoneRunways = {}, + MaximumSpeed = 50, + }, + Gelendzhik = { + PointsBoundary = { + [1]={["y"]=297856.00000001,["x"]=-51151.428571429,}, + [2]={["y"]=299044.57142858,["x"]=-49720.000000001,}, + [3]={["y"]=298861.71428572,["x"]=-49580.000000001,}, + [4]={["y"]=298198.85714286,["x"]=-49842.857142858,}, + [5]={["y"]=297990.28571429,["x"]=-50151.428571429,}, + [6]={["y"]=297696.00000001,["x"]=-51054.285714286,}, + [7]={["y"]=297850.28571429,["x"]=-51160.000000001,}, + }, + PointsRunways = { + [1] = { + [1]={["y"]=297834.00000001,["x"]=-51107.428571429,}, + [2]={["y"]=297786.57142858,["x"]=-51068.857142858,}, + [3]={["y"]=298946.57142858,["x"]=-49686.000000001,}, + [4]={["y"]=298993.14285715,["x"]=-49725.714285715,}, + [5]={["y"]=297835.14285715,["x"]=-51107.714285715,}, + }, + }, + ZoneBoundary = {}, + ZoneRunways = {}, + MaximumSpeed = 50, + }, + Gudauta = { + PointsBoundary = { + [1]={["y"]=517246.57142857,["x"]=-197850.28571429,}, + [2]={["y"]=516749.42857142,["x"]=-198070.28571429,}, + [3]={["y"]=515755.14285714,["x"]=-197598.85714286,}, + [4]={["y"]=515369.42857142,["x"]=-196538.85714286,}, + [5]={["y"]=515623.71428571,["x"]=-195618.85714286,}, + [6]={["y"]=515946.57142857,["x"]=-195510.28571429,}, + [7]={["y"]=517243.71428571,["x"]=-197858.85714286,}, + }, + PointsRunways = { + [1] = { + [1]={["y"]=517096.57142857,["x"]=-197804.57142857,}, + [2]={["y"]=515880.85714285,["x"]=-195590.28571429,}, + [3]={["y"]=515812.28571428,["x"]=-195628.85714286,}, + [4]={["y"]=517036.57142857,["x"]=-197834.57142857,}, + [5]={["y"]=517097.99999999,["x"]=-197807.42857143,}, + }, + }, + ZoneBoundary = {}, + ZoneRunways = {}, + MaximumSpeed = 50, + }, + Kobuleti = { + PointsBoundary = { + [1]={["y"]=634427.71428571,["x"]=-318290.28571429,}, + [2]={["y"]=635033.42857143,["x"]=-317550.2857143,}, + [3]={["y"]=635864.85714286,["x"]=-317333.14285715,}, + [4]={["y"]=636967.71428571,["x"]=-317261.71428572,}, + [5]={["y"]=637144.85714286,["x"]=-317913.14285715,}, + [6]={["y"]=634630.57142857,["x"]=-318687.42857144,}, + [7]={["y"]=634424.85714286,["x"]=-318290.2857143,}, + }, + PointsRunways = { + [1] = { + [1]={["y"]=634509.71428571,["x"]=-318339.42857144,}, + [2]={["y"]=636767.42857143,["x"]=-317516.57142858,}, + [3]={["y"]=636790,["x"]=-317575.71428572,}, + [4]={["y"]=634531.42857143,["x"]=-318398.00000001,}, + [5]={["y"]=634510.28571429,["x"]=-318339.71428572,}, + }, + }, + ZoneBoundary = {}, + ZoneRunways = {}, + MaximumSpeed = 50, + }, + KrasnodarCenter = { + PointsBoundary = { + [1]={["y"]=366680.28571429,["x"]=11699.142857142,}, + [2]={["y"]=366654.28571429,["x"]=11225.142857142,}, + [3]={["y"]=367497.14285715,["x"]=11082.285714285,}, + [4]={["y"]=368025.71428572,["x"]=10396.57142857,}, + [5]={["y"]=369854.28571429,["x"]=11367.999999999,}, + [6]={["y"]=369840.00000001,["x"]=11910.857142856,}, + [7]={["y"]=366682.57142858,["x"]=11697.999999999,}, + }, + PointsRunways = { + [1] = { + [1]={["y"]=369205.42857144,["x"]=11789.142857142,}, + [2]={["y"]=369209.71428572,["x"]=11714.857142856,}, + [3]={["y"]=366699.71428572,["x"]=11581.714285713,}, + [4]={["y"]=366698.28571429,["x"]=11659.142857142,}, + [5]={["y"]=369208.85714286,["x"]=11788.57142857,}, + }, + }, + ZoneBoundary = {}, + ZoneRunways = {}, + MaximumSpeed = 50, + }, + KrasnodarPashkovsky = { + PointsBoundary = { + [1]={["y"]=386754,["x"]=6476.5714285703,}, + [2]={["y"]=389182.57142858,["x"]=8722.2857142846,}, + [3]={["y"]=388832.57142858,["x"]=9086.5714285703,}, + [4]={["y"]=386961.14285715,["x"]=7707.9999999989,}, + [5]={["y"]=385404,["x"]=9179.4285714274,}, + [6]={["y"]=383239.71428572,["x"]=7386.5714285703,}, + [7]={["y"]=383954,["x"]=6486.5714285703,}, + [8]={["y"]=385775.42857143,["x"]=8097.9999999989,}, + [9]={["y"]=386804,["x"]=7319.4285714274,}, + [10]={["y"]=386375.42857143,["x"]=6797.9999999989,}, + [11]={["y"]=386746.85714286,["x"]=6472.2857142846,}, + }, + PointsRunways = { + [1] = { + [1]={["y"]=385891.14285715,["x"]=8416.5714285703,}, + [2]={["y"]=385842.28571429,["x"]=8467.9999999989,}, + [3]={["y"]=384180.85714286,["x"]=6917.1428571417,}, + [4]={["y"]=384228.57142858,["x"]=6867.7142857132,}, + [5]={["y"]=385891.14285715,["x"]=8416.5714285703,}, + }, + [2] = { + [1]={["y"]=386714.85714286,["x"]=6674.857142856,}, + [2]={["y"]=386757.71428572,["x"]=6627.7142857132,}, + [3]={["y"]=389028.57142858,["x"]=8741.4285714275,}, + [4]={["y"]=388981.71428572,["x"]=8790.5714285703,}, + [5]={["y"]=386714.57142858,["x"]=6674.5714285703,}, + }, + }, + ZoneBoundary = {}, + ZoneRunways = {}, + MaximumSpeed = 50, + }, + Krymsk = { + PointsBoundary = { + [1]={["y"]=293338.00000001,["x"]=-7575.4285714297,}, + [2]={["y"]=295199.42857144,["x"]=-5434.0000000011,}, + [3]={["y"]=295595.14285715,["x"]=-6239.7142857154,}, + [4]={["y"]=294152.2857143,["x"]=-8325.4285714297,}, + [5]={["y"]=293345.14285715,["x"]=-7596.8571428582,}, + }, + PointsRunways = { + [1] = { + [1]={["y"]=293522.00000001,["x"]=-7567.4285714297,}, + [2]={["y"]=293578.57142858,["x"]=-7616.0000000011,}, + [3]={["y"]=295246.00000001,["x"]=-5591.142857144,}, + [4]={["y"]=295187.71428573,["x"]=-5546.0000000011,}, + [5]={["y"]=293523.14285715,["x"]=-7568.2857142868,}, + }, + }, + ZoneBoundary = {}, + ZoneRunways = {}, + MaximumSpeed = 50, + }, + Kutaisi = { + PointsBoundary = { + [1]={["y"]=682087.42857143,["x"]=-284512.85714286,}, + [2]={["y"]=685387.42857143,["x"]=-283662.85714286,}, + [3]={["y"]=685294.57142857,["x"]=-284977.14285715,}, + [4]={["y"]=682744.57142857,["x"]=-286505.71428572,}, + [5]={["y"]=682094.57142857,["x"]=-284527.14285715,}, + }, + PointsRunways = { + [1] = { + [1]={["y"]=682638,["x"]=-285202.28571429,}, + [2]={["y"]=685050.28571429,["x"]=-284507.42857144,}, + [3]={["y"]=685068.85714286,["x"]=-284578.85714286,}, + [4]={["y"]=682657.42857143,["x"]=-285264.28571429,}, + [5]={["y"]=682638.28571429,["x"]=-285202.85714286,}, + }, + }, + ZoneBoundary = {}, + ZoneRunways = {}, + MaximumSpeed = 50, + }, + MaykopKhanskaya = { + PointsBoundary = { + [1]={["y"]=456876.28571429,["x"]=-27665.42857143,}, + [2]={["y"]=457800,["x"]=-28392.857142858,}, + [3]={["y"]=459368.57142857,["x"]=-26378.571428573,}, + [4]={["y"]=459425.71428572,["x"]=-25242.857142858,}, + [5]={["y"]=458961.42857143,["x"]=-24964.285714287,}, + [6]={["y"]=456878.57142857,["x"]=-27667.714285715,}, + }, + PointsRunways = { + [1] = { + [1]={["y"]=457005.42857143,["x"]=-27668.000000001,}, + [2]={["y"]=459028.85714286,["x"]=-25168.857142858,}, + [3]={["y"]=459082.57142857,["x"]=-25216.857142858,}, + [4]={["y"]=457060,["x"]=-27714.285714287,}, + [5]={["y"]=457004.57142857,["x"]=-27669.714285715,}, + }, + }, + ZoneBoundary = {}, + ZoneRunways = {}, + MaximumSpeed = 50, + }, + MineralnyeVody = { + PointsBoundary = { + [1]={["y"]=703857.14285714,["x"]=-50226.000000002,}, + [2]={["y"]=707385.71428571,["x"]=-51911.714285716,}, + [3]={["y"]=707595.71428571,["x"]=-51434.857142859,}, + [4]={["y"]=707900,["x"]=-51568.857142859,}, + [5]={["y"]=707542.85714286,["x"]=-52326.000000002,}, + [6]={["y"]=706628.57142857,["x"]=-52568.857142859,}, + [7]={["y"]=705142.85714286,["x"]=-51790.285714288,}, + [8]={["y"]=703678.57142857,["x"]=-50611.714285716,}, + [9]={["y"]=703857.42857143,["x"]=-50226.857142859,}, + }, + PointsRunways = { + [1] = { + [1]={["y"]=703904,["x"]=-50352.571428573,}, + [2]={["y"]=707596.28571429,["x"]=-52094.571428573,}, + [3]={["y"]=707560.57142858,["x"]=-52161.714285716,}, + [4]={["y"]=703871.71428572,["x"]=-50420.571428573,}, + [5]={["y"]=703902,["x"]=-50352.000000002,}, + }, + }, + ZoneBoundary = {}, + ZoneRunways = {}, + MaximumSpeed = 50, + }, + Mozdok = { + PointsBoundary = { + [1]={["y"]=832123.42857143,["x"]=-83608.571428573,}, + [2]={["y"]=835916.28571429,["x"]=-83144.285714288,}, + [3]={["y"]=835474.28571429,["x"]=-84170.571428573,}, + [4]={["y"]=832911.42857143,["x"]=-84470.571428573,}, + [5]={["y"]=832487.71428572,["x"]=-85565.714285716,}, + [6]={["y"]=831573.42857143,["x"]=-85351.42857143,}, + [7]={["y"]=832123.71428572,["x"]=-83610.285714288,}, + }, + PointsRunways = { + [1] = { + [1]={["y"]=832201.14285715,["x"]=-83699.428571431,}, + [2]={["y"]=832212.57142857,["x"]=-83780.571428574,}, + [3]={["y"]=835730.28571429,["x"]=-83335.714285717,}, + [4]={["y"]=835718.85714286,["x"]=-83246.571428574,}, + [5]={["y"]=832200.57142857,["x"]=-83700.000000002,}, + }, + }, + ZoneBoundary = {}, + ZoneRunways = {}, + MaximumSpeed = 50, + }, + Nalchik = { + PointsBoundary = { + [1]={["y"]=759370,["x"]=-125502.85714286,}, + [2]={["y"]=761384.28571429,["x"]=-124177.14285714,}, + [3]={["y"]=761472.85714286,["x"]=-124325.71428572,}, + [4]={["y"]=761092.85714286,["x"]=-125048.57142857,}, + [5]={["y"]=760295.71428572,["x"]=-125685.71428572,}, + [6]={["y"]=759444.28571429,["x"]=-125734.28571429,}, + [7]={["y"]=759375.71428572,["x"]=-125511.42857143,}, + }, + PointsRunways = { + [1] = { + [1]={["y"]=759454.28571429,["x"]=-125551.42857143,}, + [2]={["y"]=759492.85714286,["x"]=-125610.85714286,}, + [3]={["y"]=761406.28571429,["x"]=-124304.28571429,}, + [4]={["y"]=761361.14285714,["x"]=-124239.71428572,}, + [5]={["y"]=759456,["x"]=-125552.57142857,}, + }, + }, + ZoneBoundary = {}, + ZoneRunways = {}, + MaximumSpeed = 50, + }, + Novorossiysk = { + PointsBoundary = { + [1]={["y"]=278677.71428573,["x"]=-41656.571428572,}, + [2]={["y"]=278446.2857143,["x"]=-41453.714285715,}, + [3]={["y"]=278989.14285716,["x"]=-40188.000000001,}, + [4]={["y"]=279717.71428573,["x"]=-39968.000000001,}, + [5]={["y"]=280020.57142859,["x"]=-40208.000000001,}, + [6]={["y"]=278674.85714287,["x"]=-41660.857142858,}, + }, + PointsRunways = { + [1] = { + [1]={["y"]=278673.14285716,["x"]=-41615.142857144,}, + [2]={["y"]=278625.42857144,["x"]=-41570.571428572,}, + [3]={["y"]=279835.42857144,["x"]=-40226.000000001,}, + [4]={["y"]=279882.2857143,["x"]=-40270.000000001,}, + [5]={["y"]=278672.00000001,["x"]=-41614.857142858,}, + }, + }, + ZoneBoundary = {}, + ZoneRunways = {}, + MaximumSpeed = 50, + }, + SenakiKolkhi = { + PointsBoundary = { + [1]={["y"]=646036.57142857,["x"]=-281778.85714286,}, + [2]={["y"]=646045.14285714,["x"]=-281191.71428571,}, + [3]={["y"]=647032.28571429,["x"]=-280598.85714285,}, + [4]={["y"]=647669.42857143,["x"]=-281273.14285714,}, + [5]={["y"]=648323.71428571,["x"]=-281370.28571428,}, + [6]={["y"]=648520.85714286,["x"]=-281978.85714285,}, + [7]={["y"]=646039.42857143,["x"]=-281783.14285714,}, + }, + PointsRunways = { + [1] = { + [1]={["y"]=646060.85714285,["x"]=-281736,}, + [2]={["y"]=646056.57142857,["x"]=-281631.71428571,}, + [3]={["y"]=648442.28571428,["x"]=-281840.28571428,}, + [4]={["y"]=648432.28571428,["x"]=-281918.85714286,}, + [5]={["y"]=646063.71428571,["x"]=-281738.85714286,}, + }, + }, + ZoneBoundary = {}, + ZoneRunways = {}, + MaximumSpeed = 50, + }, + SochiAdler = { + PointsBoundary = { + [1]={["y"]=460642.28571428,["x"]=-164861.71428571,}, + [2]={["y"]=462820.85714285,["x"]=-163368.85714286,}, + [3]={["y"]=463649.42857142,["x"]=-163340.28571429,}, + [4]={["y"]=463835.14285714,["x"]=-164040.28571429,}, + [5]={["y"]=462535.14285714,["x"]=-165654.57142857,}, + [6]={["y"]=460678,["x"]=-165247.42857143,}, + [7]={["y"]=460635.14285714,["x"]=-164876,}, + }, + PointsRunways = { + [1] = { + [1]={["y"]=460831.42857143,["x"]=-165180,}, + [2]={["y"]=460878.57142857,["x"]=-165257.14285714,}, + [3]={["y"]=463663.71428571,["x"]=-163793.14285714,}, + [4]={["y"]=463612.28571428,["x"]=-163697.42857143,}, + [5]={["y"]=460831.42857143,["x"]=-165177.14285714,}, + }, + [2] = { + [1]={["y"]=460831.42857143,["x"]=-165180,}, + [2]={["y"]=460878.57142857,["x"]=-165257.14285714,}, + [3]={["y"]=463663.71428571,["x"]=-163793.14285714,}, + [4]={["y"]=463612.28571428,["x"]=-163697.42857143,}, + [5]={["y"]=460831.42857143,["x"]=-165177.14285714,}, + }, + }, + ZoneBoundary = {}, + ZoneRunways = {}, + MaximumSpeed = 50, + }, + Soganlug = { + PointsBoundary = { + [1]={["y"]=894530.85714286,["x"]=-316928.28571428,}, + [2]={["y"]=896422.28571428,["x"]=-318622.57142857,}, + [3]={["y"]=896090.85714286,["x"]=-318934,}, + [4]={["y"]=894019.42857143,["x"]=-317119.71428571,}, + [5]={["y"]=894533.71428571,["x"]=-316925.42857143,}, + }, + PointsRunways = { + [1] = { + [1]={["y"]=894525.71428571,["x"]=-316964,}, + [2]={["y"]=896363.14285714,["x"]=-318634.28571428,}, + [3]={["y"]=896299.14285714,["x"]=-318702.85714286,}, + [4]={["y"]=894464,["x"]=-317031.71428571,}, + [5]={["y"]=894524.57142857,["x"]=-316963.71428571,}, + }, + }, + ZoneBoundary = {}, + ZoneRunways = {}, + MaximumSpeed = 50, + }, + SukhumiBabushara = { + PointsBoundary = { + [1]={["y"]=562541.14285714,["x"]=-219852.28571429,}, + [2]={["y"]=562691.14285714,["x"]=-219395.14285714,}, + [3]={["y"]=564326.85714286,["x"]=-219523.71428571,}, + [4]={["y"]=566262.57142857,["x"]=-221166.57142857,}, + [5]={["y"]=566069.71428571,["x"]=-221580.85714286,}, + [6]={["y"]=562534,["x"]=-219873.71428571,}, + }, + PointsRunways = { + [1] = { + [1]={["y"]=562684,["x"]=-219779.71428571,}, + [2]={["y"]=562717.71428571,["x"]=-219718,}, + [3]={["y"]=566046.85714286,["x"]=-221376.57142857,}, + [4]={["y"]=566012.28571428,["x"]=-221446.57142857,}, + [5]={["y"]=562684.57142857,["x"]=-219782.57142857,}, + }, + }, + ZoneBoundary = {}, + ZoneRunways = {}, + MaximumSpeed = 50, + }, + TbilisiLochini = { + PointsBoundary = { + [1]={["y"]=895172.85714286,["x"]=-314667.42857143,}, + [2]={["y"]=895337.42857143,["x"]=-314143.14285714,}, + [3]={["y"]=895990.28571429,["x"]=-314036,}, + [4]={["y"]=897730.28571429,["x"]=-315284.57142857,}, + [5]={["y"]=897901.71428571,["x"]=-316284.57142857,}, + [6]={["y"]=897684.57142857,["x"]=-316618.85714286,}, + [7]={["y"]=895173.14285714,["x"]=-314667.42857143,}, + }, + PointsRunways = { + [1] = { + [1]={["y"]=895261.14285715,["x"]=-314652.28571428,}, + [2]={["y"]=897654.57142857,["x"]=-316523.14285714,}, + [3]={["y"]=897711.71428571,["x"]=-316450.28571429,}, + [4]={["y"]=895327.42857143,["x"]=-314568.85714286,}, + [5]={["y"]=895261.71428572,["x"]=-314656,}, + }, + }, + ZoneBoundary = {}, + ZoneRunways = {}, + MaximumSpeed = 50, + }, + Vaziani = { + PointsBoundary = { + [1]={["y"]=902122,["x"]=-318163.71428572,}, + [2]={["y"]=902678.57142857,["x"]=-317594,}, + [3]={["y"]=903275.71428571,["x"]=-317405.42857143,}, + [4]={["y"]=903418.57142857,["x"]=-317891.14285714,}, + [5]={["y"]=904292.85714286,["x"]=-318748.28571429,}, + [6]={["y"]=904542,["x"]=-319740.85714286,}, + [7]={["y"]=904042,["x"]=-320166.57142857,}, + [8]={["y"]=902121.42857143,["x"]=-318164.85714286,}, + }, + PointsRunways = { + [1] = { + [1]={["y"]=902239.14285714,["x"]=-318190.85714286,}, + [2]={["y"]=904014.28571428,["x"]=-319994.57142857,}, + [3]={["y"]=904064.85714285,["x"]=-319945.14285715,}, + [4]={["y"]=902294.57142857,["x"]=-318146,}, + [5]={["y"]=902247.71428571,["x"]=-318190.85714286,}, + }, + }, + ZoneBoundary = {}, + ZoneRunways = {}, + MaximumSpeed = 50, + }, + }, +} + +--- Creates a new AIRBASEPOLICE_CAUCASUS object. +-- @param #AIRBASEPOLICE_CAUCASUS self +-- @param SetClient A SET_CLIENT object that will contain the CLIENT objects to be monitored if they follow the rules of the airbase. +-- @return #AIRBASEPOLICE_CAUCASUS self +function AIRBASEPOLICE_CAUCASUS:New( SetClient ) + + -- Inherits from BASE + local self = BASE:Inherit( self, AIRBASEPOLICE_BASE:New( SetClient, self.Airbases ) ) + + -- -- AnapaVityazevo + -- local AnapaVityazevoBoundary = GROUP:FindByName( "AnapaVityazevo Boundary" ) + -- self.Airbases.AnapaVityazevo.ZoneBoundary = ZONE_POLYGON:New( "AnapaVityazevo Boundary", AnapaVityazevoBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush() + -- + -- local AnapaVityazevoRunway1 = GROUP:FindByName( "AnapaVityazevo Runway 1" ) + -- self.Airbases.AnapaVityazevo.ZoneRunways[1] = ZONE_POLYGON:New( "AnapaVityazevo Runway 1", AnapaVityazevoRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush() + -- + -- + -- + -- -- Batumi + -- local BatumiBoundary = GROUP:FindByName( "Batumi Boundary" ) + -- self.Airbases.Batumi.ZoneBoundary = ZONE_POLYGON:New( "Batumi Boundary", BatumiBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush() + -- + -- local BatumiRunway1 = GROUP:FindByName( "Batumi Runway 1" ) + -- self.Airbases.Batumi.ZoneRunways[1] = ZONE_POLYGON:New( "Batumi Runway 1", BatumiRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush() + -- + -- + -- + -- -- Beslan + -- local BeslanBoundary = GROUP:FindByName( "Beslan Boundary" ) + -- self.Airbases.Beslan.ZoneBoundary = ZONE_POLYGON:New( "Beslan Boundary", BeslanBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush() + -- + -- local BeslanRunway1 = GROUP:FindByName( "Beslan Runway 1" ) + -- self.Airbases.Beslan.ZoneRunways[1] = ZONE_POLYGON:New( "Beslan Runway 1", BeslanRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush() + -- + -- + -- + -- -- Gelendzhik + -- local GelendzhikBoundary = GROUP:FindByName( "Gelendzhik Boundary" ) + -- self.Airbases.Gelendzhik.ZoneBoundary = ZONE_POLYGON:New( "Gelendzhik Boundary", GelendzhikBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush() + -- + -- local GelendzhikRunway1 = GROUP:FindByName( "Gelendzhik Runway 1" ) + -- self.Airbases.Gelendzhik.ZoneRunways[1] = ZONE_POLYGON:New( "Gelendzhik Runway 1", GelendzhikRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush() + -- + -- + -- + -- -- Gudauta + -- local GudautaBoundary = GROUP:FindByName( "Gudauta Boundary" ) + -- self.Airbases.Gudauta.ZoneBoundary = ZONE_POLYGON:New( "Gudauta Boundary", GudautaBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush() + -- + -- local GudautaRunway1 = GROUP:FindByName( "Gudauta Runway 1" ) + -- self.Airbases.Gudauta.ZoneRunways[1] = ZONE_POLYGON:New( "Gudauta Runway 1", GudautaRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush() + -- + -- + -- + -- -- Kobuleti + -- local KobuletiBoundary = GROUP:FindByName( "Kobuleti Boundary" ) + -- self.Airbases.Kobuleti.ZoneBoundary = ZONE_POLYGON:New( "Kobuleti Boundary", KobuletiBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush() + -- + -- local KobuletiRunway1 = GROUP:FindByName( "Kobuleti Runway 1" ) + -- self.Airbases.Kobuleti.ZoneRunways[1] = ZONE_POLYGON:New( "Kobuleti Runway 1", KobuletiRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush() + -- + -- + -- + -- -- KrasnodarCenter + -- local KrasnodarCenterBoundary = GROUP:FindByName( "KrasnodarCenter Boundary" ) + -- self.Airbases.KrasnodarCenter.ZoneBoundary = ZONE_POLYGON:New( "KrasnodarCenter Boundary", KrasnodarCenterBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush() + -- + -- local KrasnodarCenterRunway1 = GROUP:FindByName( "KrasnodarCenter Runway 1" ) + -- self.Airbases.KrasnodarCenter.ZoneRunways[1] = ZONE_POLYGON:New( "KrasnodarCenter Runway 1", KrasnodarCenterRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush() + -- + -- + -- + -- -- KrasnodarPashkovsky + -- local KrasnodarPashkovskyBoundary = GROUP:FindByName( "KrasnodarPashkovsky Boundary" ) + -- self.Airbases.KrasnodarPashkovsky.ZoneBoundary = ZONE_POLYGON:New( "KrasnodarPashkovsky Boundary", KrasnodarPashkovskyBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush() + -- + -- local KrasnodarPashkovskyRunway1 = GROUP:FindByName( "KrasnodarPashkovsky Runway 1" ) + -- self.Airbases.KrasnodarPashkovsky.ZoneRunways[1] = ZONE_POLYGON:New( "KrasnodarPashkovsky Runway 1", KrasnodarPashkovskyRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush() + -- local KrasnodarPashkovskyRunway2 = GROUP:FindByName( "KrasnodarPashkovsky Runway 2" ) + -- self.Airbases.KrasnodarPashkovsky.ZoneRunways[2] = ZONE_POLYGON:New( "KrasnodarPashkovsky Runway 2", KrasnodarPashkovskyRunway2 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush() + -- + -- + -- + -- -- Krymsk + -- local KrymskBoundary = GROUP:FindByName( "Krymsk Boundary" ) + -- self.Airbases.Krymsk.ZoneBoundary = ZONE_POLYGON:New( "Krymsk Boundary", KrymskBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush() + -- + -- local KrymskRunway1 = GROUP:FindByName( "Krymsk Runway 1" ) + -- self.Airbases.Krymsk.ZoneRunways[1] = ZONE_POLYGON:New( "Krymsk Runway 1", KrymskRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush() + -- + -- + -- + -- -- Kutaisi + -- local KutaisiBoundary = GROUP:FindByName( "Kutaisi Boundary" ) + -- self.Airbases.Kutaisi.ZoneBoundary = ZONE_POLYGON:New( "Kutaisi Boundary", KutaisiBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush() + -- + -- local KutaisiRunway1 = GROUP:FindByName( "Kutaisi Runway 1" ) + -- self.Airbases.Kutaisi.ZoneRunways[1] = ZONE_POLYGON:New( "Kutaisi Runway 1", KutaisiRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush() + -- + -- + -- + -- -- MaykopKhanskaya + -- local MaykopKhanskayaBoundary = GROUP:FindByName( "MaykopKhanskaya Boundary" ) + -- self.Airbases.MaykopKhanskaya.ZoneBoundary = ZONE_POLYGON:New( "MaykopKhanskaya Boundary", MaykopKhanskayaBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush() + -- + -- local MaykopKhanskayaRunway1 = GROUP:FindByName( "MaykopKhanskaya Runway 1" ) + -- self.Airbases.MaykopKhanskaya.ZoneRunways[1] = ZONE_POLYGON:New( "MaykopKhanskaya Runway 1", MaykopKhanskayaRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush() + -- + -- + -- + -- -- MineralnyeVody + -- local MineralnyeVodyBoundary = GROUP:FindByName( "MineralnyeVody Boundary" ) + -- self.Airbases.MineralnyeVody.ZoneBoundary = ZONE_POLYGON:New( "MineralnyeVody Boundary", MineralnyeVodyBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush() + -- + -- local MineralnyeVodyRunway1 = GROUP:FindByName( "MineralnyeVody Runway 1" ) + -- self.Airbases.MineralnyeVody.ZoneRunways[1] = ZONE_POLYGON:New( "MineralnyeVody Runway 1", MineralnyeVodyRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush() + -- + -- + -- + -- -- Mozdok + -- local MozdokBoundary = GROUP:FindByName( "Mozdok Boundary" ) + -- self.Airbases.Mozdok.ZoneBoundary = ZONE_POLYGON:New( "Mozdok Boundary", MozdokBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush() + -- + -- local MozdokRunway1 = GROUP:FindByName( "Mozdok Runway 1" ) + -- self.Airbases.Mozdok.ZoneRunways[1] = ZONE_POLYGON:New( "Mozdok Runway 1", MozdokRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush() + -- + -- + -- + -- -- Nalchik + -- local NalchikBoundary = GROUP:FindByName( "Nalchik Boundary" ) + -- self.Airbases.Nalchik.ZoneBoundary = ZONE_POLYGON:New( "Nalchik Boundary", NalchikBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush() + -- + -- local NalchikRunway1 = GROUP:FindByName( "Nalchik Runway 1" ) + -- self.Airbases.Nalchik.ZoneRunways[1] = ZONE_POLYGON:New( "Nalchik Runway 1", NalchikRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush() + -- + -- + -- + -- -- Novorossiysk + -- local NovorossiyskBoundary = GROUP:FindByName( "Novorossiysk Boundary" ) + -- self.Airbases.Novorossiysk.ZoneBoundary = ZONE_POLYGON:New( "Novorossiysk Boundary", NovorossiyskBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush() + -- + -- local NovorossiyskRunway1 = GROUP:FindByName( "Novorossiysk Runway 1" ) + -- self.Airbases.Novorossiysk.ZoneRunways[1] = ZONE_POLYGON:New( "Novorossiysk Runway 1", NovorossiyskRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush() + -- + -- + -- + -- -- SenakiKolkhi + -- local SenakiKolkhiBoundary = GROUP:FindByName( "SenakiKolkhi Boundary" ) + -- self.Airbases.SenakiKolkhi.ZoneBoundary = ZONE_POLYGON:New( "SenakiKolkhi Boundary", SenakiKolkhiBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush() + -- + -- local SenakiKolkhiRunway1 = GROUP:FindByName( "SenakiKolkhi Runway 1" ) + -- self.Airbases.SenakiKolkhi.ZoneRunways[1] = ZONE_POLYGON:New( "SenakiKolkhi Runway 1", SenakiKolkhiRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush() + -- + -- + -- + -- -- SochiAdler + -- local SochiAdlerBoundary = GROUP:FindByName( "SochiAdler Boundary" ) + -- self.Airbases.SochiAdler.ZoneBoundary = ZONE_POLYGON:New( "SochiAdler Boundary", SochiAdlerBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush() + -- + -- local SochiAdlerRunway1 = GROUP:FindByName( "SochiAdler Runway 1" ) + -- self.Airbases.SochiAdler.ZoneRunways[1] = ZONE_POLYGON:New( "SochiAdler Runway 1", SochiAdlerRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush() + -- local SochiAdlerRunway2 = GROUP:FindByName( "SochiAdler Runway 2" ) + -- self.Airbases.SochiAdler.ZoneRunways[2] = ZONE_POLYGON:New( "SochiAdler Runway 2", SochiAdlerRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush() + -- + -- + -- + -- -- Soganlug + -- local SoganlugBoundary = GROUP:FindByName( "Soganlug Boundary" ) + -- self.Airbases.Soganlug.ZoneBoundary = ZONE_POLYGON:New( "Soganlug Boundary", SoganlugBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush() + -- + -- local SoganlugRunway1 = GROUP:FindByName( "Soganlug Runway 1" ) + -- self.Airbases.Soganlug.ZoneRunways[1] = ZONE_POLYGON:New( "Soganlug Runway 1", SoganlugRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush() + -- + -- + -- + -- -- SukhumiBabushara + -- local SukhumiBabusharaBoundary = GROUP:FindByName( "SukhumiBabushara Boundary" ) + -- self.Airbases.SukhumiBabushara.ZoneBoundary = ZONE_POLYGON:New( "SukhumiBabushara Boundary", SukhumiBabusharaBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush() + -- + -- local SukhumiBabusharaRunway1 = GROUP:FindByName( "SukhumiBabushara Runway 1" ) + -- self.Airbases.SukhumiBabushara.ZoneRunways[1] = ZONE_POLYGON:New( "SukhumiBabushara Runway 1", SukhumiBabusharaRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush() + -- + -- + -- + -- -- TbilisiLochini + -- local TbilisiLochiniBoundary = GROUP:FindByName( "TbilisiLochini Boundary" ) + -- self.Airbases.TbilisiLochini.ZoneBoundary = ZONE_POLYGON:New( "TbilisiLochini Boundary", TbilisiLochiniBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush() + -- + -- local TbilisiLochiniRunway1 = GROUP:FindByName( "TbilisiLochini Runway 1" ) + -- self.Airbases.TbilisiLochini.ZoneRunways[1] = ZONE_POLYGON:New( "TbilisiLochini Runway 1", TbilisiLochiniRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush() + -- + -- + -- + -- -- Vaziani + -- local VazianiBoundary = GROUP:FindByName( "Vaziani Boundary" ) + -- self.Airbases.Vaziani.ZoneBoundary = ZONE_POLYGON:New( "Vaziani Boundary", VazianiBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush() + -- + -- local VazianiRunway1 = GROUP:FindByName( "Vaziani Runway 1" ) + -- self.Airbases.Vaziani.ZoneRunways[1] = ZONE_POLYGON:New( "Vaziani Runway 1", VazianiRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush() + -- + -- + -- + + + -- -- Template + -- local TemplateBoundary = GROUP:FindByName( "Template Boundary" ) + -- self.Airbases.Template.ZoneBoundary = ZONE_POLYGON:New( "Template Boundary", TemplateBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush() + -- + -- local TemplateRunway1 = GROUP:FindByName( "Template Runway 1" ) + -- self.Airbases.Template.ZoneRunways[1] = ZONE_POLYGON:New( "Template Runway 1", TemplateRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush() + + return self + +end + +--- This module contains the DETECTION classes. +-- +-- === +-- +-- 1) @{Detection#DETECTION_BASE} class, extends @{Base#BASE} +-- ===================================================== +-- The @{Detection#DETECTION_BASE} class defines the core functions to administer detected objects. +-- Detected objects are grouped in SETS of UNITS. +-- +-- @module Detection +-- @author Mechanic : Concept & Testing +-- @author FlightControl : Design & Programming + + + +--- DETECTION_BASE class +-- @type DETECTION_BASE +-- @field Group#GROUP FACGroup The GROUP in the Forward Air Controller role. +-- @field DCSTypes#Distance DetectionRange The range till which targets are accepted to be detected. +-- @field DCSTypes#Distance DetectionZoneRange The range till which targets are grouped upon the first detected target. +-- @field #DETECTION_BASE.DetectedUnitSets DetectedUnitSets A list of @{Set#SET_UNIT}s containing the units in each set that were detected within a DetectedZoneRange. +-- @field #DETECTION_BASE.DetectedZones DetectedZones A list of @{Zone#ZONE_UNIT}s containing the zones of the reference detected units. +-- @extends Set#SET_BASE +DETECTION_BASE = { + ClassName = "DETECTION_BASE", + DetectedUnitSets = {}, + DetectedUnits = {}, + FACGroup = nil, + DetectionRange = nil, + DetectionZoneRange = nil, +} + +--- @type DETECTION_BASE.DetectedUnitSets +-- @list + + +--- @type DETECTION_BASE.DetectedZones +-- @list + + +--- DETECTION constructor. +-- @param #DETECTION_BASE self +-- @return #DETECTION_BASE self +function DETECTION_BASE:New( FACGroup, DetectionRange, DetectionZoneRange ) + + -- Inherits from BASE + local self = BASE:Inherit( self, BASE:New() ) + + self.FACGroup = FACGroup + self.DetectionRange = DetectionRange + self.DetectionZoneRange = DetectionZoneRange + + self.DetectionScheduler = SCHEDULER:New(self, self._DetectionScheduler, { self, "Detection" }, 10, 30, 0.2 ) +end + +--- Form @{Set}s of detected @{Unit#UNIT}s in an array of @{Set#SET_UNIT}s. +-- @param #DETECTION_BASE self +function DETECTION_BASE:_DetectionScheduler( SchedulerName ) + self:F2( { SchedulerName } ) + + self.DetectedUnitSets = {} + + if self.FACGroup:IsAlive() then + local FACGroupName = self.FACGroup:GetName() + local FACDetectedTargets = self.FACGroup:GetDetectedTargets() + + for FACDetectedTargetID, FACDetectedTarget in pairs( FACDetectedTargets ) do + local FACObject = FACDetectedTarget.object + self:T2( FACObject ) + + if FACObject and FACObject:isExist() and FACObject.id_ < 50000000 then + + local FACDetectedUnit = UNIT:Find( FACObject ) + local FACDetectedUnitName = FACDetectedUnit:GetName() + + local FACDetectedUnitPositionVec3 = FACDetectedUnit:GetPointVec3() + local FACGroupPositionVec3 = self.FACGroup:GetPointVec3() + local Distance = ( ( FACDetectedUnitPositionVec3.x - FACGroupPositionVec3.x )^2 + + ( FACDetectedUnitPositionVec3.y - FACGroupPositionVec3.y )^2 + + ( FACDetectedUnitPositionVec3.z - FACGroupPositionVec3.z )^2 + ) ^ 0.5 / 1000 + + self:T( { FACGroupName, FACDetectedUnitName, Distance } ) + + if Distance <= self.DetectionRange then + + if not self.DetectedUnits[FACDetectedUnitName] then + self.DetectedUnits[FACDetectedUnitName] = {} + end + self.DetectedUnits[FACDetectedUnitName].DetectedUnit = UNIT:FindByName( FACDetectedUnitName ) + self.DetectedUnits[FACDetectedUnitName].Visible = FACDetectedTarget.visible + self.DetectedUnits[FACDetectedUnitName].Type = FACDetectedTarget.type + self.DetectedUnits[FACDetectedUnitName].Distance = FACDetectedTarget.distance + else + -- if beyond the DetectionRange then nullify... + if self.DetectedUnits[FACDetectedUnitName] then + self.DetectedUnits[FACDetectedUnitName] = nil + end + end + end + end + + -- okay, now we have a list of detected unit names ... + -- Sort the table based on distance ... + self:T( { "Sorting DetectedUnits table:", self.DetectedUnits } ) + table.sort( self.DetectedUnits, function( a, b ) return a.Distance < b.Distance end ) + self:T( { "Sorted Targets Table:", self.DetectedUnits } ) + + -- Now group the DetectedUnits table into SET_UNITs, evaluating the DetectionZoneRange. + + if self.DetectedUnits then + for DetectedUnitName, DetectedUnitData in pairs( self.DetectedUnits ) do + local DetectedUnit = DetectedUnitData.DetectedUnit -- Unit#UNIT + self:T( DetectedUnit:GetName() ) + if #self.DetectedUnitSets == 0 then + self:T( { "Adding Unit Set #", 1 } ) + self.DetectedUnitSets[1] = {} + self.DetectedUnitSets[1].Zone = ZONE_UNIT:New( DetectedUnitName, DetectedUnit, self.DetectionZoneRange ) + self.DetectedUnitSets[1].Set = SET_UNIT:New() + self.DetectedUnitSets[1].Set:AddUnit( DetectedUnit ) + else + local AddedToSet = false + for DetectedUnitSetID, DetectedUnitSetData in pairs( self.DetectedUnitSets ) do + self:T( "Detected Unit Set #" .. DetectedUnitSetID ) + local DetectedUnitSet = DetectedUnitSetData.Set -- Set#SET_UNIT + local DetectedZone = DetectedUnitSetData.Zone -- Zone#ZONE_UNIT + if DetectedUnit:IsInZone( DetectedZone ) then + self:T( "Adding to Unit Set #" .. DetectedUnitSetID ) + self.DetectedUnitSets[DetectedUnitSetID].Set:AddUnit( DetectedUnit ) + AddedToSet = true + end + end + if AddedToSet == false then + self:T( "Adding new Unit Set #" .. #self.DetectedUnitSets+1 ) + self.DetectedUnitSets[#self.DetectedUnitSets+1] = {} + self.DetectedUnitSets[#self.DetectedUnitSets].Zone = ZONE_UNIT:New( DetectedUnitName, DetectedUnit, self.DetectionZoneRange ) + self.DetectedUnitSets[#self.DetectedUnitSets].Set = SET_UNIT:New() + self.DetectedUnitSets[#self.DetectedUnitSets].Set:AddUnit( DetectedUnit ) + end + end + end + end + + -- Now all the tests should have been build, now make some smoke and flares... + + for DetectedUnitSetID, DetectedUnitSetData in pairs( self.DetectedUnitSets ) do + local DetectedUnitSet = DetectedUnitSetData.Set -- Set#SET_UNIT + local DetectedZone = DetectedUnitSetData.Zone -- Zone#ZONE_UNIT + self:T( "Detected Set #" .. DetectedUnitSetID ) + DetectedUnitSet:ForEachUnit( + --- @param Unit#UNIT DetectedUnit + function( DetectedUnit ) + self:T( DetectedUnit:GetName() ) + DetectedUnit:FlareRed() + end + ) + DetectedZone:SmokeZone( POINT_VEC3.SmokeColor.White, 30 ) + end + end +end BASE:TraceOnOff( false ) env.info( '*** MOOSE INCLUDE END *** ' ) diff --git a/Moose Mission Setup/Moose.lua b/Moose Mission Setup/Moose.lua index 9c8bf3739..15c498977 100644 --- a/Moose Mission Setup/Moose.lua +++ b/Moose Mission Setup/Moose.lua @@ -1,5 +1,5 @@ env.info( '*** MOOSE STATIC INCLUDE START *** ' ) -env.info( 'Moose Generation Timestamp: 20160615_0641' ) +env.info( 'Moose Generation Timestamp: 20160615_2239' ) local base = _G Include = {} @@ -3150,8 +3150,8 @@ end -- -- * @{Scheduler#SCHEDULER.New}: Setup a new scheduler and start it with the specified parameters. -- --- SCHEDULER timer stop and start --- ------------------------------ +-- 1.2) SCHEDULER timer stop and start +-- ----------------------------------- -- The SCHEDULER can be stopped and restarted with the following methods: -- -- * @{Scheduler#SCHEDULER.Start}: (Re-)Start the scheduler. @@ -3160,6 +3160,7 @@ end -- @module Scheduler -- @author FlightControl + --- The SCHEDULER class -- @type SCHEDULER -- @field #number ScheduleID the ID of the scheduler. @@ -9752,8 +9753,6 @@ SET_BASE = { -- DBObject = SET_BASE:New() function SET_BASE:New( Database ) - env.info( tostring( Database ) ) - -- Inherits from BASE local self = BASE:Inherit( self, BASE:New() ) @@ -10449,13 +10448,26 @@ function SET_UNIT:New() end --- Add UNIT(s) to SET_UNIT. --- @param Set#SET_UNIT self +-- @param #SET_UNIT self +-- @param #string AddUnit A single UNIT. +-- @return #SET_UNIT self +function SET_UNIT:AddUnit( AddUnit ) + + self:Add( AddUnit:GetName(), AddUnit ) + + return self +end + + +--- Add UNIT(s) to SET_UNIT. +-- @param #SET_UNIT self -- @param #string AddUnitNames A single name or an array of UNIT names. --- @return self +-- @return #SET_UNIT self function SET_UNIT:AddUnitsByName( AddUnitNames ) local AddUnitNamesArray = ( type( AddUnitNames ) == "table" ) and AddUnitNames or { AddUnitNames } + self:T( AddUnitNamesArray ) for AddUnitID, AddUnitName in pairs( AddUnitNamesArray ) do self:Add( AddUnitName, UNIT:FindByName( AddUnitName ) ) end @@ -11368,6 +11380,7 @@ Include.File( "Escort" ) Include.File( "MissileTrainer" ) Include.File( "AIBalancer" ) Include.File( "AirbasePolice" ) +Include.File( "Detection" ) @@ -20206,6 +20219,1090 @@ end +--- This module contains the AIRBASEPOLICE classes. +-- +-- === +-- +-- 1) @{AirbasePolice#AIRBASEPOLICE_BASE} class, extends @{Base#BASE} +-- ================================================================== +-- The @{AirbasePolice#AIRBASEPOLICE_BASE} class provides the main methods to monitor CLIENT behaviour at airbases. +-- CLIENTS should not be allowed to: +-- +-- * Don't taxi faster than 40 km/h. +-- * Don't take-off on taxiways. +-- * Avoid to hit other planes on the airbase. +-- * Obey ground control orders. +-- +-- 2) @{AirbasePolice#AIRBASEPOLICE_CAUCASUS} class, extends @{AirbasePolice#AIRBASEPOLICE_BASE} +-- ============================================================================================= +-- All the airbases on the caucasus map can be monitored using this class. +-- If you want to monitor specific airbases, you need to use the @{#AIRBASEPOLICE_BASE.Monitor}() method, which takes a table or airbase names. +-- The following names can be given: +-- * AnapaVityazevo +-- * Batumi +-- * Beslan +-- * Gelendzhik +-- * Gudauta +-- * Kobuleti +-- * KrasnodarCenter +-- * KrasnodarPashkovsky +-- * Krymsk +-- * Kutaisi +-- * MaykopKhanskaya +-- * MineralnyeVody +-- * Mozdok +-- * Nalchik +-- * Novorossiysk +-- * SenakiKolkhi +-- * SochiAdler +-- * Soganlug +-- * SukhumiBabushara +-- * TbilisiLochini +-- * Vaziani +-- +-- @module AirbasePolice +-- @author FlightControl + +--- @type AIRBASEPOLICE_BASE +-- @field Set#SET_CLIENT SetClient +-- @extends Base#BASE + +AIRBASEPOLICE_BASE = { + ClassName = "AIRBASEPOLICE_BASE", + SetClient = nil, + Airbases = nil, + AirbaseNames = nil, +} + + +--- Creates a new AIRBASEPOLICE_BASE object. +-- @param #AIRBASEPOLICE_BASE self +-- @param SetClient A SET_CLIENT object that will contain the CLIENT objects to be monitored if they follow the rules of the airbase. +-- @param Airbases A table of Airbase Names. +-- @return #AIRBASEPOLICE_BASE self +function AIRBASEPOLICE_BASE:New( SetClient, Airbases ) + + -- Inherits from BASE + local self = BASE:Inherit( self, BASE:New() ) + self:E( { self.ClassName, SetClient, Airbases } ) + + self.SetClient = SetClient + self.Airbases = Airbases + + for AirbaseID, Airbase in pairs( self.Airbases ) do + Airbase.ZoneBoundary = ZONE_POLYGON_BASE:New( "Boundary", Airbase.PointsBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush() + for PointsRunwayID, PointsRunway in pairs( Airbase.PointsRunways ) do + Airbase.ZoneRunways[PointsRunwayID] = ZONE_POLYGON_BASE:New( "Runway " .. PointsRunwayID, PointsRunway ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush() + end + end + + -- -- Template + -- local TemplateBoundary = GROUP:FindByName( "Template Boundary" ) + -- self.Airbases.Template.ZoneBoundary = ZONE_POLYGON:New( "Template Boundary", TemplateBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush() + -- + -- local TemplateRunway1 = GROUP:FindByName( "Template Runway 1" ) + -- self.Airbases.Template.ZoneRunways[1] = ZONE_POLYGON:New( "Template Runway 1", TemplateRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush() + + self.SetClient:ForEachClient( + --- @param Client#CLIENT Client + function( Client ) + Client:SetState( self, "Speeding", false ) + Client:SetState( self, "Warnings", 0) + Client:SetState( self, "Taxi", false ) + end + ) + + self.AirbaseMonitor = SCHEDULER:New( self, self._AirbaseMonitor, {}, 0, 2, 0.05 ) + + return self +end + +--- @type AIRBASEPOLICE_BASE.AirbaseNames +-- @list <#string> + +--- Monitor a table of airbase names. +-- @param #AIRBASEPOLICE_BASE self +-- @param #AIRBASEPOLICE_BASE.AirbaseNames AirbaseNames A list of AirbaseNames to monitor. If this parameters is nil, then all airbases will be monitored. +-- @return #AIRBASEPOLICE_BASE self +function AIRBASEPOLICE_BASE:Monitor( AirbaseNames ) + + if AirbaseNames then + if type( AirbaseNames ) == "table" then + self.AirbaseNames = AirbaseNames + else + self.AirbaseNames = { AirbaseNames } + end + end +end + +--- @param #AIRBASEPOLICE_BASE self +function AIRBASEPOLICE_BASE:_AirbaseMonitor() + + for AirbaseID, Airbase in pairs( self.Airbases ) do + + if not self.AirbaseNames or self.AirbaseNames[AirbaseID] then + + self:E( AirbaseID ) + + self.SetClient:ForEachClientInZone( Airbase.ZoneBoundary, + + --- @param Client#CLIENT Client + function( Client ) + + self:E( Client.UnitName ) + if Client:IsAlive() then + local NotInRunwayZone = true + for ZoneRunwayID, ZoneRunway in pairs( Airbase.ZoneRunways ) do + NotInRunwayZone = ( Client:IsNotInZone( ZoneRunway ) == true ) and NotInRunwayZone or false + end + + if NotInRunwayZone then + local Taxi = self:GetState( self, "Taxi" ) + self:E( Taxi ) + if Taxi == false then + Client:Message( "Welcome at " .. AirbaseID .. ". The maximum taxiing speed is " .. Airbase.MaximumSpeed " km/h.", 20, "ATC" ) + self:SetState( self, "Taxi", true ) + end + + local VelocityVec3 = Client:GetVelocity() + local Velocity = math.abs(VelocityVec3.x) + math.abs(VelocityVec3.y) + math.abs(VelocityVec3.z) + local IsAboveRunway = Client:IsAboveRunway() + local IsOnGround = Client:InAir() == false + self:T( IsAboveRunway, IsOnGround ) + + if IsAboveRunway and IsOnGround then + + if Velocity > Airbase.MaximumSpeed then + local IsSpeeding = Client:GetState( self, "Speeding" ) + + if IsSpeeding == true then + local SpeedingWarnings = Client:GetState( self, "Warnings" ) + self:T( SpeedingWarnings ) + + if SpeedingWarnings <= 5 then + Client:Message( "You are speeding on the taxiway! Slow down or you will be removed from this airbase! Your current velocity is " .. string.format( "%2.0f km/h", Velocity ), 5, "Warning " .. SpeedingWarnings .. " / 5" ) + Client:SetState( self, "Warnings", SpeedingWarnings + 1 ) + else + MESSAGE:New( "Player " .. Client:GetPlayerName() .. " has been removed from the airbase, due to a speeding violation ...", 10, "Airbase Police" ):ToAll() + Client:GetGroup():Destroy() + Client:SetState( self, "Speeding", false ) + Client:SetState( self, "Warnings", 0 ) + end + + else + Client:Message( "You are speeding on the taxiway! Slow down please ...! Your current velocity is " .. string.format( "%2.0f km/h", Velocity ), 5, "Attention! " ) + Client:SetState( self, "Speeding", true ) + Client:SetState( self, "Warnings", 1 ) + end + + else + Client:SetState( self, "Speeding", false ) + Client:SetState( self, "Warnings", 0 ) + end + end + + else + Client:SetState( self, "Speeding", false ) + Client:SetState( self, "Warnings", 0 ) + local Taxi = self:GetState( self, "Taxi" ) + if Taxi == true then + Client:Message( "You have progressed to the runway ... Await take-off clearance ...", 20, "ATC" ) + self:SetState( self, "Taxi", false ) + end + end + end + end + ) + end + end + + return true +end + + +--- @type AIRBASEPOLICE_CAUCASUS +-- @field Set#SET_CLIENT SetClient +-- @extends #AIRBASEPOLICE_BASE + +AIRBASEPOLICE_CAUCASUS = { + ClassName = "AIRBASEPOLICE_CAUCASUS", + Airbases = { + AnapaVityazevo = { + PointsBoundary = { + [1]={["y"]=242234.85714287,["x"]=-6616.5714285726,}, + [2]={["y"]=241060.57142858,["x"]=-5585.142857144,}, + [3]={["y"]=243806.2857143,["x"]=-3962.2857142868,}, + [4]={["y"]=245240.57142858,["x"]=-4816.5714285726,}, + [5]={["y"]=244783.42857144,["x"]=-5630.8571428583,}, + [6]={["y"]=243800.57142858,["x"]=-5065.142857144,}, + [7]={["y"]=242232.00000001,["x"]=-6622.2857142868,}, + }, + PointsRunways = { + [1] = { + }, + }, + ZoneBoundary = {}, + ZoneRunways = {}, + MaximumSpeed = 50, + }, + Batumi = { + PointsBoundary = { + [1]={["y"]=617567.14285714,["x"]=-355313.14285715,}, + [2]={["y"]=616181.42857142,["x"]=-354800.28571429,}, + [3]={["y"]=616007.14285714,["x"]=-355128.85714286,}, + [4]={["y"]=618230,["x"]=-356914.57142858,}, + [5]={["y"]=618727.14285714,["x"]=-356166,}, + [6]={["y"]=617572.85714285,["x"]=-355308.85714286,}, + }, + PointsRunways = { + [1] = { + [1]={["y"]=616442.28571429,["x"]=-355090.28571429,}, + [2]={["y"]=618450.57142857,["x"]=-356522,}, + [3]={["y"]=618407.71428571,["x"]=-356584.85714286,}, + [4]={["y"]=618361.99999999,["x"]=-356554.85714286,}, + [5]={["y"]=618324.85714285,["x"]=-356599.14285715,}, + [6]={["y"]=618250.57142856,["x"]=-356543.42857143,}, + [7]={["y"]=618257.7142857,["x"]=-356496.28571429,}, + [8]={["y"]=618237.7142857,["x"]=-356459.14285715,}, + [9]={["y"]=616555.71428571,["x"]=-355258.85714286,}, + [10]={["y"]=616486.28571428,["x"]=-355280.57142858,}, + [11]={["y"]=616410.57142856,["x"]=-355227.71428572,}, + [12]={["y"]=616441.99999999,["x"]=-355179.14285715,}, + [13]={["y"]=616401.99999999,["x"]=-355147.71428572,}, + [14]={["y"]=616441.42857142,["x"]=-355092.57142858,}, + }, + }, + ZoneBoundary = {}, + ZoneRunways = {}, + MaximumSpeed = 50, + }, + Beslan = { + PointsBoundary = { + [1]={["y"]=842082.57142857,["x"]=-148445.14285715,}, + [2]={["y"]=845237.71428572,["x"]=-148639.71428572,}, + [3]={["y"]=845232,["x"]=-148765.42857143,}, + [4]={["y"]=844220.57142857,["x"]=-149168.28571429,}, + [5]={["y"]=843274.85714286,["x"]=-149125.42857143,}, + [6]={["y"]=842077.71428572,["x"]=-148554,}, + [7]={["y"]=842083.42857143,["x"]=-148445.42857143,}, + }, + PointsRunways = { + [1] = { + [1]={["y"]=842104.57142857,["x"]=-148460.57142857,}, + [2]={["y"]=845225.71428572,["x"]=-148656,}, + [3]={["y"]=845220.57142858,["x"]=-148750,}, + [4]={["y"]=842098.85714286,["x"]=-148556.28571429,}, + [5]={["y"]=842104,["x"]=-148460.28571429,}, + }, + }, + ZoneBoundary = {}, + ZoneRunways = {}, + MaximumSpeed = 50, + }, + Gelendzhik = { + PointsBoundary = { + [1]={["y"]=297856.00000001,["x"]=-51151.428571429,}, + [2]={["y"]=299044.57142858,["x"]=-49720.000000001,}, + [3]={["y"]=298861.71428572,["x"]=-49580.000000001,}, + [4]={["y"]=298198.85714286,["x"]=-49842.857142858,}, + [5]={["y"]=297990.28571429,["x"]=-50151.428571429,}, + [6]={["y"]=297696.00000001,["x"]=-51054.285714286,}, + [7]={["y"]=297850.28571429,["x"]=-51160.000000001,}, + }, + PointsRunways = { + [1] = { + [1]={["y"]=297834.00000001,["x"]=-51107.428571429,}, + [2]={["y"]=297786.57142858,["x"]=-51068.857142858,}, + [3]={["y"]=298946.57142858,["x"]=-49686.000000001,}, + [4]={["y"]=298993.14285715,["x"]=-49725.714285715,}, + [5]={["y"]=297835.14285715,["x"]=-51107.714285715,}, + }, + }, + ZoneBoundary = {}, + ZoneRunways = {}, + MaximumSpeed = 50, + }, + Gudauta = { + PointsBoundary = { + [1]={["y"]=517246.57142857,["x"]=-197850.28571429,}, + [2]={["y"]=516749.42857142,["x"]=-198070.28571429,}, + [3]={["y"]=515755.14285714,["x"]=-197598.85714286,}, + [4]={["y"]=515369.42857142,["x"]=-196538.85714286,}, + [5]={["y"]=515623.71428571,["x"]=-195618.85714286,}, + [6]={["y"]=515946.57142857,["x"]=-195510.28571429,}, + [7]={["y"]=517243.71428571,["x"]=-197858.85714286,}, + }, + PointsRunways = { + [1] = { + [1]={["y"]=517096.57142857,["x"]=-197804.57142857,}, + [2]={["y"]=515880.85714285,["x"]=-195590.28571429,}, + [3]={["y"]=515812.28571428,["x"]=-195628.85714286,}, + [4]={["y"]=517036.57142857,["x"]=-197834.57142857,}, + [5]={["y"]=517097.99999999,["x"]=-197807.42857143,}, + }, + }, + ZoneBoundary = {}, + ZoneRunways = {}, + MaximumSpeed = 50, + }, + Kobuleti = { + PointsBoundary = { + [1]={["y"]=634427.71428571,["x"]=-318290.28571429,}, + [2]={["y"]=635033.42857143,["x"]=-317550.2857143,}, + [3]={["y"]=635864.85714286,["x"]=-317333.14285715,}, + [4]={["y"]=636967.71428571,["x"]=-317261.71428572,}, + [5]={["y"]=637144.85714286,["x"]=-317913.14285715,}, + [6]={["y"]=634630.57142857,["x"]=-318687.42857144,}, + [7]={["y"]=634424.85714286,["x"]=-318290.2857143,}, + }, + PointsRunways = { + [1] = { + [1]={["y"]=634509.71428571,["x"]=-318339.42857144,}, + [2]={["y"]=636767.42857143,["x"]=-317516.57142858,}, + [3]={["y"]=636790,["x"]=-317575.71428572,}, + [4]={["y"]=634531.42857143,["x"]=-318398.00000001,}, + [5]={["y"]=634510.28571429,["x"]=-318339.71428572,}, + }, + }, + ZoneBoundary = {}, + ZoneRunways = {}, + MaximumSpeed = 50, + }, + KrasnodarCenter = { + PointsBoundary = { + [1]={["y"]=366680.28571429,["x"]=11699.142857142,}, + [2]={["y"]=366654.28571429,["x"]=11225.142857142,}, + [3]={["y"]=367497.14285715,["x"]=11082.285714285,}, + [4]={["y"]=368025.71428572,["x"]=10396.57142857,}, + [5]={["y"]=369854.28571429,["x"]=11367.999999999,}, + [6]={["y"]=369840.00000001,["x"]=11910.857142856,}, + [7]={["y"]=366682.57142858,["x"]=11697.999999999,}, + }, + PointsRunways = { + [1] = { + [1]={["y"]=369205.42857144,["x"]=11789.142857142,}, + [2]={["y"]=369209.71428572,["x"]=11714.857142856,}, + [3]={["y"]=366699.71428572,["x"]=11581.714285713,}, + [4]={["y"]=366698.28571429,["x"]=11659.142857142,}, + [5]={["y"]=369208.85714286,["x"]=11788.57142857,}, + }, + }, + ZoneBoundary = {}, + ZoneRunways = {}, + MaximumSpeed = 50, + }, + KrasnodarPashkovsky = { + PointsBoundary = { + [1]={["y"]=386754,["x"]=6476.5714285703,}, + [2]={["y"]=389182.57142858,["x"]=8722.2857142846,}, + [3]={["y"]=388832.57142858,["x"]=9086.5714285703,}, + [4]={["y"]=386961.14285715,["x"]=7707.9999999989,}, + [5]={["y"]=385404,["x"]=9179.4285714274,}, + [6]={["y"]=383239.71428572,["x"]=7386.5714285703,}, + [7]={["y"]=383954,["x"]=6486.5714285703,}, + [8]={["y"]=385775.42857143,["x"]=8097.9999999989,}, + [9]={["y"]=386804,["x"]=7319.4285714274,}, + [10]={["y"]=386375.42857143,["x"]=6797.9999999989,}, + [11]={["y"]=386746.85714286,["x"]=6472.2857142846,}, + }, + PointsRunways = { + [1] = { + [1]={["y"]=385891.14285715,["x"]=8416.5714285703,}, + [2]={["y"]=385842.28571429,["x"]=8467.9999999989,}, + [3]={["y"]=384180.85714286,["x"]=6917.1428571417,}, + [4]={["y"]=384228.57142858,["x"]=6867.7142857132,}, + [5]={["y"]=385891.14285715,["x"]=8416.5714285703,}, + }, + [2] = { + [1]={["y"]=386714.85714286,["x"]=6674.857142856,}, + [2]={["y"]=386757.71428572,["x"]=6627.7142857132,}, + [3]={["y"]=389028.57142858,["x"]=8741.4285714275,}, + [4]={["y"]=388981.71428572,["x"]=8790.5714285703,}, + [5]={["y"]=386714.57142858,["x"]=6674.5714285703,}, + }, + }, + ZoneBoundary = {}, + ZoneRunways = {}, + MaximumSpeed = 50, + }, + Krymsk = { + PointsBoundary = { + [1]={["y"]=293338.00000001,["x"]=-7575.4285714297,}, + [2]={["y"]=295199.42857144,["x"]=-5434.0000000011,}, + [3]={["y"]=295595.14285715,["x"]=-6239.7142857154,}, + [4]={["y"]=294152.2857143,["x"]=-8325.4285714297,}, + [5]={["y"]=293345.14285715,["x"]=-7596.8571428582,}, + }, + PointsRunways = { + [1] = { + [1]={["y"]=293522.00000001,["x"]=-7567.4285714297,}, + [2]={["y"]=293578.57142858,["x"]=-7616.0000000011,}, + [3]={["y"]=295246.00000001,["x"]=-5591.142857144,}, + [4]={["y"]=295187.71428573,["x"]=-5546.0000000011,}, + [5]={["y"]=293523.14285715,["x"]=-7568.2857142868,}, + }, + }, + ZoneBoundary = {}, + ZoneRunways = {}, + MaximumSpeed = 50, + }, + Kutaisi = { + PointsBoundary = { + [1]={["y"]=682087.42857143,["x"]=-284512.85714286,}, + [2]={["y"]=685387.42857143,["x"]=-283662.85714286,}, + [3]={["y"]=685294.57142857,["x"]=-284977.14285715,}, + [4]={["y"]=682744.57142857,["x"]=-286505.71428572,}, + [5]={["y"]=682094.57142857,["x"]=-284527.14285715,}, + }, + PointsRunways = { + [1] = { + [1]={["y"]=682638,["x"]=-285202.28571429,}, + [2]={["y"]=685050.28571429,["x"]=-284507.42857144,}, + [3]={["y"]=685068.85714286,["x"]=-284578.85714286,}, + [4]={["y"]=682657.42857143,["x"]=-285264.28571429,}, + [5]={["y"]=682638.28571429,["x"]=-285202.85714286,}, + }, + }, + ZoneBoundary = {}, + ZoneRunways = {}, + MaximumSpeed = 50, + }, + MaykopKhanskaya = { + PointsBoundary = { + [1]={["y"]=456876.28571429,["x"]=-27665.42857143,}, + [2]={["y"]=457800,["x"]=-28392.857142858,}, + [3]={["y"]=459368.57142857,["x"]=-26378.571428573,}, + [4]={["y"]=459425.71428572,["x"]=-25242.857142858,}, + [5]={["y"]=458961.42857143,["x"]=-24964.285714287,}, + [6]={["y"]=456878.57142857,["x"]=-27667.714285715,}, + }, + PointsRunways = { + [1] = { + [1]={["y"]=457005.42857143,["x"]=-27668.000000001,}, + [2]={["y"]=459028.85714286,["x"]=-25168.857142858,}, + [3]={["y"]=459082.57142857,["x"]=-25216.857142858,}, + [4]={["y"]=457060,["x"]=-27714.285714287,}, + [5]={["y"]=457004.57142857,["x"]=-27669.714285715,}, + }, + }, + ZoneBoundary = {}, + ZoneRunways = {}, + MaximumSpeed = 50, + }, + MineralnyeVody = { + PointsBoundary = { + [1]={["y"]=703857.14285714,["x"]=-50226.000000002,}, + [2]={["y"]=707385.71428571,["x"]=-51911.714285716,}, + [3]={["y"]=707595.71428571,["x"]=-51434.857142859,}, + [4]={["y"]=707900,["x"]=-51568.857142859,}, + [5]={["y"]=707542.85714286,["x"]=-52326.000000002,}, + [6]={["y"]=706628.57142857,["x"]=-52568.857142859,}, + [7]={["y"]=705142.85714286,["x"]=-51790.285714288,}, + [8]={["y"]=703678.57142857,["x"]=-50611.714285716,}, + [9]={["y"]=703857.42857143,["x"]=-50226.857142859,}, + }, + PointsRunways = { + [1] = { + [1]={["y"]=703904,["x"]=-50352.571428573,}, + [2]={["y"]=707596.28571429,["x"]=-52094.571428573,}, + [3]={["y"]=707560.57142858,["x"]=-52161.714285716,}, + [4]={["y"]=703871.71428572,["x"]=-50420.571428573,}, + [5]={["y"]=703902,["x"]=-50352.000000002,}, + }, + }, + ZoneBoundary = {}, + ZoneRunways = {}, + MaximumSpeed = 50, + }, + Mozdok = { + PointsBoundary = { + [1]={["y"]=832123.42857143,["x"]=-83608.571428573,}, + [2]={["y"]=835916.28571429,["x"]=-83144.285714288,}, + [3]={["y"]=835474.28571429,["x"]=-84170.571428573,}, + [4]={["y"]=832911.42857143,["x"]=-84470.571428573,}, + [5]={["y"]=832487.71428572,["x"]=-85565.714285716,}, + [6]={["y"]=831573.42857143,["x"]=-85351.42857143,}, + [7]={["y"]=832123.71428572,["x"]=-83610.285714288,}, + }, + PointsRunways = { + [1] = { + [1]={["y"]=832201.14285715,["x"]=-83699.428571431,}, + [2]={["y"]=832212.57142857,["x"]=-83780.571428574,}, + [3]={["y"]=835730.28571429,["x"]=-83335.714285717,}, + [4]={["y"]=835718.85714286,["x"]=-83246.571428574,}, + [5]={["y"]=832200.57142857,["x"]=-83700.000000002,}, + }, + }, + ZoneBoundary = {}, + ZoneRunways = {}, + MaximumSpeed = 50, + }, + Nalchik = { + PointsBoundary = { + [1]={["y"]=759370,["x"]=-125502.85714286,}, + [2]={["y"]=761384.28571429,["x"]=-124177.14285714,}, + [3]={["y"]=761472.85714286,["x"]=-124325.71428572,}, + [4]={["y"]=761092.85714286,["x"]=-125048.57142857,}, + [5]={["y"]=760295.71428572,["x"]=-125685.71428572,}, + [6]={["y"]=759444.28571429,["x"]=-125734.28571429,}, + [7]={["y"]=759375.71428572,["x"]=-125511.42857143,}, + }, + PointsRunways = { + [1] = { + [1]={["y"]=759454.28571429,["x"]=-125551.42857143,}, + [2]={["y"]=759492.85714286,["x"]=-125610.85714286,}, + [3]={["y"]=761406.28571429,["x"]=-124304.28571429,}, + [4]={["y"]=761361.14285714,["x"]=-124239.71428572,}, + [5]={["y"]=759456,["x"]=-125552.57142857,}, + }, + }, + ZoneBoundary = {}, + ZoneRunways = {}, + MaximumSpeed = 50, + }, + Novorossiysk = { + PointsBoundary = { + [1]={["y"]=278677.71428573,["x"]=-41656.571428572,}, + [2]={["y"]=278446.2857143,["x"]=-41453.714285715,}, + [3]={["y"]=278989.14285716,["x"]=-40188.000000001,}, + [4]={["y"]=279717.71428573,["x"]=-39968.000000001,}, + [5]={["y"]=280020.57142859,["x"]=-40208.000000001,}, + [6]={["y"]=278674.85714287,["x"]=-41660.857142858,}, + }, + PointsRunways = { + [1] = { + [1]={["y"]=278673.14285716,["x"]=-41615.142857144,}, + [2]={["y"]=278625.42857144,["x"]=-41570.571428572,}, + [3]={["y"]=279835.42857144,["x"]=-40226.000000001,}, + [4]={["y"]=279882.2857143,["x"]=-40270.000000001,}, + [5]={["y"]=278672.00000001,["x"]=-41614.857142858,}, + }, + }, + ZoneBoundary = {}, + ZoneRunways = {}, + MaximumSpeed = 50, + }, + SenakiKolkhi = { + PointsBoundary = { + [1]={["y"]=646036.57142857,["x"]=-281778.85714286,}, + [2]={["y"]=646045.14285714,["x"]=-281191.71428571,}, + [3]={["y"]=647032.28571429,["x"]=-280598.85714285,}, + [4]={["y"]=647669.42857143,["x"]=-281273.14285714,}, + [5]={["y"]=648323.71428571,["x"]=-281370.28571428,}, + [6]={["y"]=648520.85714286,["x"]=-281978.85714285,}, + [7]={["y"]=646039.42857143,["x"]=-281783.14285714,}, + }, + PointsRunways = { + [1] = { + [1]={["y"]=646060.85714285,["x"]=-281736,}, + [2]={["y"]=646056.57142857,["x"]=-281631.71428571,}, + [3]={["y"]=648442.28571428,["x"]=-281840.28571428,}, + [4]={["y"]=648432.28571428,["x"]=-281918.85714286,}, + [5]={["y"]=646063.71428571,["x"]=-281738.85714286,}, + }, + }, + ZoneBoundary = {}, + ZoneRunways = {}, + MaximumSpeed = 50, + }, + SochiAdler = { + PointsBoundary = { + [1]={["y"]=460642.28571428,["x"]=-164861.71428571,}, + [2]={["y"]=462820.85714285,["x"]=-163368.85714286,}, + [3]={["y"]=463649.42857142,["x"]=-163340.28571429,}, + [4]={["y"]=463835.14285714,["x"]=-164040.28571429,}, + [5]={["y"]=462535.14285714,["x"]=-165654.57142857,}, + [6]={["y"]=460678,["x"]=-165247.42857143,}, + [7]={["y"]=460635.14285714,["x"]=-164876,}, + }, + PointsRunways = { + [1] = { + [1]={["y"]=460831.42857143,["x"]=-165180,}, + [2]={["y"]=460878.57142857,["x"]=-165257.14285714,}, + [3]={["y"]=463663.71428571,["x"]=-163793.14285714,}, + [4]={["y"]=463612.28571428,["x"]=-163697.42857143,}, + [5]={["y"]=460831.42857143,["x"]=-165177.14285714,}, + }, + [2] = { + [1]={["y"]=460831.42857143,["x"]=-165180,}, + [2]={["y"]=460878.57142857,["x"]=-165257.14285714,}, + [3]={["y"]=463663.71428571,["x"]=-163793.14285714,}, + [4]={["y"]=463612.28571428,["x"]=-163697.42857143,}, + [5]={["y"]=460831.42857143,["x"]=-165177.14285714,}, + }, + }, + ZoneBoundary = {}, + ZoneRunways = {}, + MaximumSpeed = 50, + }, + Soganlug = { + PointsBoundary = { + [1]={["y"]=894530.85714286,["x"]=-316928.28571428,}, + [2]={["y"]=896422.28571428,["x"]=-318622.57142857,}, + [3]={["y"]=896090.85714286,["x"]=-318934,}, + [4]={["y"]=894019.42857143,["x"]=-317119.71428571,}, + [5]={["y"]=894533.71428571,["x"]=-316925.42857143,}, + }, + PointsRunways = { + [1] = { + [1]={["y"]=894525.71428571,["x"]=-316964,}, + [2]={["y"]=896363.14285714,["x"]=-318634.28571428,}, + [3]={["y"]=896299.14285714,["x"]=-318702.85714286,}, + [4]={["y"]=894464,["x"]=-317031.71428571,}, + [5]={["y"]=894524.57142857,["x"]=-316963.71428571,}, + }, + }, + ZoneBoundary = {}, + ZoneRunways = {}, + MaximumSpeed = 50, + }, + SukhumiBabushara = { + PointsBoundary = { + [1]={["y"]=562541.14285714,["x"]=-219852.28571429,}, + [2]={["y"]=562691.14285714,["x"]=-219395.14285714,}, + [3]={["y"]=564326.85714286,["x"]=-219523.71428571,}, + [4]={["y"]=566262.57142857,["x"]=-221166.57142857,}, + [5]={["y"]=566069.71428571,["x"]=-221580.85714286,}, + [6]={["y"]=562534,["x"]=-219873.71428571,}, + }, + PointsRunways = { + [1] = { + [1]={["y"]=562684,["x"]=-219779.71428571,}, + [2]={["y"]=562717.71428571,["x"]=-219718,}, + [3]={["y"]=566046.85714286,["x"]=-221376.57142857,}, + [4]={["y"]=566012.28571428,["x"]=-221446.57142857,}, + [5]={["y"]=562684.57142857,["x"]=-219782.57142857,}, + }, + }, + ZoneBoundary = {}, + ZoneRunways = {}, + MaximumSpeed = 50, + }, + TbilisiLochini = { + PointsBoundary = { + [1]={["y"]=895172.85714286,["x"]=-314667.42857143,}, + [2]={["y"]=895337.42857143,["x"]=-314143.14285714,}, + [3]={["y"]=895990.28571429,["x"]=-314036,}, + [4]={["y"]=897730.28571429,["x"]=-315284.57142857,}, + [5]={["y"]=897901.71428571,["x"]=-316284.57142857,}, + [6]={["y"]=897684.57142857,["x"]=-316618.85714286,}, + [7]={["y"]=895173.14285714,["x"]=-314667.42857143,}, + }, + PointsRunways = { + [1] = { + [1]={["y"]=895261.14285715,["x"]=-314652.28571428,}, + [2]={["y"]=897654.57142857,["x"]=-316523.14285714,}, + [3]={["y"]=897711.71428571,["x"]=-316450.28571429,}, + [4]={["y"]=895327.42857143,["x"]=-314568.85714286,}, + [5]={["y"]=895261.71428572,["x"]=-314656,}, + }, + }, + ZoneBoundary = {}, + ZoneRunways = {}, + MaximumSpeed = 50, + }, + Vaziani = { + PointsBoundary = { + [1]={["y"]=902122,["x"]=-318163.71428572,}, + [2]={["y"]=902678.57142857,["x"]=-317594,}, + [3]={["y"]=903275.71428571,["x"]=-317405.42857143,}, + [4]={["y"]=903418.57142857,["x"]=-317891.14285714,}, + [5]={["y"]=904292.85714286,["x"]=-318748.28571429,}, + [6]={["y"]=904542,["x"]=-319740.85714286,}, + [7]={["y"]=904042,["x"]=-320166.57142857,}, + [8]={["y"]=902121.42857143,["x"]=-318164.85714286,}, + }, + PointsRunways = { + [1] = { + [1]={["y"]=902239.14285714,["x"]=-318190.85714286,}, + [2]={["y"]=904014.28571428,["x"]=-319994.57142857,}, + [3]={["y"]=904064.85714285,["x"]=-319945.14285715,}, + [4]={["y"]=902294.57142857,["x"]=-318146,}, + [5]={["y"]=902247.71428571,["x"]=-318190.85714286,}, + }, + }, + ZoneBoundary = {}, + ZoneRunways = {}, + MaximumSpeed = 50, + }, + }, +} + +--- Creates a new AIRBASEPOLICE_CAUCASUS object. +-- @param #AIRBASEPOLICE_CAUCASUS self +-- @param SetClient A SET_CLIENT object that will contain the CLIENT objects to be monitored if they follow the rules of the airbase. +-- @return #AIRBASEPOLICE_CAUCASUS self +function AIRBASEPOLICE_CAUCASUS:New( SetClient ) + + -- Inherits from BASE + local self = BASE:Inherit( self, AIRBASEPOLICE_BASE:New( SetClient, self.Airbases ) ) + + -- -- AnapaVityazevo + -- local AnapaVityazevoBoundary = GROUP:FindByName( "AnapaVityazevo Boundary" ) + -- self.Airbases.AnapaVityazevo.ZoneBoundary = ZONE_POLYGON:New( "AnapaVityazevo Boundary", AnapaVityazevoBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush() + -- + -- local AnapaVityazevoRunway1 = GROUP:FindByName( "AnapaVityazevo Runway 1" ) + -- self.Airbases.AnapaVityazevo.ZoneRunways[1] = ZONE_POLYGON:New( "AnapaVityazevo Runway 1", AnapaVityazevoRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush() + -- + -- + -- + -- -- Batumi + -- local BatumiBoundary = GROUP:FindByName( "Batumi Boundary" ) + -- self.Airbases.Batumi.ZoneBoundary = ZONE_POLYGON:New( "Batumi Boundary", BatumiBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush() + -- + -- local BatumiRunway1 = GROUP:FindByName( "Batumi Runway 1" ) + -- self.Airbases.Batumi.ZoneRunways[1] = ZONE_POLYGON:New( "Batumi Runway 1", BatumiRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush() + -- + -- + -- + -- -- Beslan + -- local BeslanBoundary = GROUP:FindByName( "Beslan Boundary" ) + -- self.Airbases.Beslan.ZoneBoundary = ZONE_POLYGON:New( "Beslan Boundary", BeslanBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush() + -- + -- local BeslanRunway1 = GROUP:FindByName( "Beslan Runway 1" ) + -- self.Airbases.Beslan.ZoneRunways[1] = ZONE_POLYGON:New( "Beslan Runway 1", BeslanRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush() + -- + -- + -- + -- -- Gelendzhik + -- local GelendzhikBoundary = GROUP:FindByName( "Gelendzhik Boundary" ) + -- self.Airbases.Gelendzhik.ZoneBoundary = ZONE_POLYGON:New( "Gelendzhik Boundary", GelendzhikBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush() + -- + -- local GelendzhikRunway1 = GROUP:FindByName( "Gelendzhik Runway 1" ) + -- self.Airbases.Gelendzhik.ZoneRunways[1] = ZONE_POLYGON:New( "Gelendzhik Runway 1", GelendzhikRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush() + -- + -- + -- + -- -- Gudauta + -- local GudautaBoundary = GROUP:FindByName( "Gudauta Boundary" ) + -- self.Airbases.Gudauta.ZoneBoundary = ZONE_POLYGON:New( "Gudauta Boundary", GudautaBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush() + -- + -- local GudautaRunway1 = GROUP:FindByName( "Gudauta Runway 1" ) + -- self.Airbases.Gudauta.ZoneRunways[1] = ZONE_POLYGON:New( "Gudauta Runway 1", GudautaRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush() + -- + -- + -- + -- -- Kobuleti + -- local KobuletiBoundary = GROUP:FindByName( "Kobuleti Boundary" ) + -- self.Airbases.Kobuleti.ZoneBoundary = ZONE_POLYGON:New( "Kobuleti Boundary", KobuletiBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush() + -- + -- local KobuletiRunway1 = GROUP:FindByName( "Kobuleti Runway 1" ) + -- self.Airbases.Kobuleti.ZoneRunways[1] = ZONE_POLYGON:New( "Kobuleti Runway 1", KobuletiRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush() + -- + -- + -- + -- -- KrasnodarCenter + -- local KrasnodarCenterBoundary = GROUP:FindByName( "KrasnodarCenter Boundary" ) + -- self.Airbases.KrasnodarCenter.ZoneBoundary = ZONE_POLYGON:New( "KrasnodarCenter Boundary", KrasnodarCenterBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush() + -- + -- local KrasnodarCenterRunway1 = GROUP:FindByName( "KrasnodarCenter Runway 1" ) + -- self.Airbases.KrasnodarCenter.ZoneRunways[1] = ZONE_POLYGON:New( "KrasnodarCenter Runway 1", KrasnodarCenterRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush() + -- + -- + -- + -- -- KrasnodarPashkovsky + -- local KrasnodarPashkovskyBoundary = GROUP:FindByName( "KrasnodarPashkovsky Boundary" ) + -- self.Airbases.KrasnodarPashkovsky.ZoneBoundary = ZONE_POLYGON:New( "KrasnodarPashkovsky Boundary", KrasnodarPashkovskyBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush() + -- + -- local KrasnodarPashkovskyRunway1 = GROUP:FindByName( "KrasnodarPashkovsky Runway 1" ) + -- self.Airbases.KrasnodarPashkovsky.ZoneRunways[1] = ZONE_POLYGON:New( "KrasnodarPashkovsky Runway 1", KrasnodarPashkovskyRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush() + -- local KrasnodarPashkovskyRunway2 = GROUP:FindByName( "KrasnodarPashkovsky Runway 2" ) + -- self.Airbases.KrasnodarPashkovsky.ZoneRunways[2] = ZONE_POLYGON:New( "KrasnodarPashkovsky Runway 2", KrasnodarPashkovskyRunway2 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush() + -- + -- + -- + -- -- Krymsk + -- local KrymskBoundary = GROUP:FindByName( "Krymsk Boundary" ) + -- self.Airbases.Krymsk.ZoneBoundary = ZONE_POLYGON:New( "Krymsk Boundary", KrymskBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush() + -- + -- local KrymskRunway1 = GROUP:FindByName( "Krymsk Runway 1" ) + -- self.Airbases.Krymsk.ZoneRunways[1] = ZONE_POLYGON:New( "Krymsk Runway 1", KrymskRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush() + -- + -- + -- + -- -- Kutaisi + -- local KutaisiBoundary = GROUP:FindByName( "Kutaisi Boundary" ) + -- self.Airbases.Kutaisi.ZoneBoundary = ZONE_POLYGON:New( "Kutaisi Boundary", KutaisiBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush() + -- + -- local KutaisiRunway1 = GROUP:FindByName( "Kutaisi Runway 1" ) + -- self.Airbases.Kutaisi.ZoneRunways[1] = ZONE_POLYGON:New( "Kutaisi Runway 1", KutaisiRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush() + -- + -- + -- + -- -- MaykopKhanskaya + -- local MaykopKhanskayaBoundary = GROUP:FindByName( "MaykopKhanskaya Boundary" ) + -- self.Airbases.MaykopKhanskaya.ZoneBoundary = ZONE_POLYGON:New( "MaykopKhanskaya Boundary", MaykopKhanskayaBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush() + -- + -- local MaykopKhanskayaRunway1 = GROUP:FindByName( "MaykopKhanskaya Runway 1" ) + -- self.Airbases.MaykopKhanskaya.ZoneRunways[1] = ZONE_POLYGON:New( "MaykopKhanskaya Runway 1", MaykopKhanskayaRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush() + -- + -- + -- + -- -- MineralnyeVody + -- local MineralnyeVodyBoundary = GROUP:FindByName( "MineralnyeVody Boundary" ) + -- self.Airbases.MineralnyeVody.ZoneBoundary = ZONE_POLYGON:New( "MineralnyeVody Boundary", MineralnyeVodyBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush() + -- + -- local MineralnyeVodyRunway1 = GROUP:FindByName( "MineralnyeVody Runway 1" ) + -- self.Airbases.MineralnyeVody.ZoneRunways[1] = ZONE_POLYGON:New( "MineralnyeVody Runway 1", MineralnyeVodyRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush() + -- + -- + -- + -- -- Mozdok + -- local MozdokBoundary = GROUP:FindByName( "Mozdok Boundary" ) + -- self.Airbases.Mozdok.ZoneBoundary = ZONE_POLYGON:New( "Mozdok Boundary", MozdokBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush() + -- + -- local MozdokRunway1 = GROUP:FindByName( "Mozdok Runway 1" ) + -- self.Airbases.Mozdok.ZoneRunways[1] = ZONE_POLYGON:New( "Mozdok Runway 1", MozdokRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush() + -- + -- + -- + -- -- Nalchik + -- local NalchikBoundary = GROUP:FindByName( "Nalchik Boundary" ) + -- self.Airbases.Nalchik.ZoneBoundary = ZONE_POLYGON:New( "Nalchik Boundary", NalchikBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush() + -- + -- local NalchikRunway1 = GROUP:FindByName( "Nalchik Runway 1" ) + -- self.Airbases.Nalchik.ZoneRunways[1] = ZONE_POLYGON:New( "Nalchik Runway 1", NalchikRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush() + -- + -- + -- + -- -- Novorossiysk + -- local NovorossiyskBoundary = GROUP:FindByName( "Novorossiysk Boundary" ) + -- self.Airbases.Novorossiysk.ZoneBoundary = ZONE_POLYGON:New( "Novorossiysk Boundary", NovorossiyskBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush() + -- + -- local NovorossiyskRunway1 = GROUP:FindByName( "Novorossiysk Runway 1" ) + -- self.Airbases.Novorossiysk.ZoneRunways[1] = ZONE_POLYGON:New( "Novorossiysk Runway 1", NovorossiyskRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush() + -- + -- + -- + -- -- SenakiKolkhi + -- local SenakiKolkhiBoundary = GROUP:FindByName( "SenakiKolkhi Boundary" ) + -- self.Airbases.SenakiKolkhi.ZoneBoundary = ZONE_POLYGON:New( "SenakiKolkhi Boundary", SenakiKolkhiBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush() + -- + -- local SenakiKolkhiRunway1 = GROUP:FindByName( "SenakiKolkhi Runway 1" ) + -- self.Airbases.SenakiKolkhi.ZoneRunways[1] = ZONE_POLYGON:New( "SenakiKolkhi Runway 1", SenakiKolkhiRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush() + -- + -- + -- + -- -- SochiAdler + -- local SochiAdlerBoundary = GROUP:FindByName( "SochiAdler Boundary" ) + -- self.Airbases.SochiAdler.ZoneBoundary = ZONE_POLYGON:New( "SochiAdler Boundary", SochiAdlerBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush() + -- + -- local SochiAdlerRunway1 = GROUP:FindByName( "SochiAdler Runway 1" ) + -- self.Airbases.SochiAdler.ZoneRunways[1] = ZONE_POLYGON:New( "SochiAdler Runway 1", SochiAdlerRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush() + -- local SochiAdlerRunway2 = GROUP:FindByName( "SochiAdler Runway 2" ) + -- self.Airbases.SochiAdler.ZoneRunways[2] = ZONE_POLYGON:New( "SochiAdler Runway 2", SochiAdlerRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush() + -- + -- + -- + -- -- Soganlug + -- local SoganlugBoundary = GROUP:FindByName( "Soganlug Boundary" ) + -- self.Airbases.Soganlug.ZoneBoundary = ZONE_POLYGON:New( "Soganlug Boundary", SoganlugBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush() + -- + -- local SoganlugRunway1 = GROUP:FindByName( "Soganlug Runway 1" ) + -- self.Airbases.Soganlug.ZoneRunways[1] = ZONE_POLYGON:New( "Soganlug Runway 1", SoganlugRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush() + -- + -- + -- + -- -- SukhumiBabushara + -- local SukhumiBabusharaBoundary = GROUP:FindByName( "SukhumiBabushara Boundary" ) + -- self.Airbases.SukhumiBabushara.ZoneBoundary = ZONE_POLYGON:New( "SukhumiBabushara Boundary", SukhumiBabusharaBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush() + -- + -- local SukhumiBabusharaRunway1 = GROUP:FindByName( "SukhumiBabushara Runway 1" ) + -- self.Airbases.SukhumiBabushara.ZoneRunways[1] = ZONE_POLYGON:New( "SukhumiBabushara Runway 1", SukhumiBabusharaRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush() + -- + -- + -- + -- -- TbilisiLochini + -- local TbilisiLochiniBoundary = GROUP:FindByName( "TbilisiLochini Boundary" ) + -- self.Airbases.TbilisiLochini.ZoneBoundary = ZONE_POLYGON:New( "TbilisiLochini Boundary", TbilisiLochiniBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush() + -- + -- local TbilisiLochiniRunway1 = GROUP:FindByName( "TbilisiLochini Runway 1" ) + -- self.Airbases.TbilisiLochini.ZoneRunways[1] = ZONE_POLYGON:New( "TbilisiLochini Runway 1", TbilisiLochiniRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush() + -- + -- + -- + -- -- Vaziani + -- local VazianiBoundary = GROUP:FindByName( "Vaziani Boundary" ) + -- self.Airbases.Vaziani.ZoneBoundary = ZONE_POLYGON:New( "Vaziani Boundary", VazianiBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush() + -- + -- local VazianiRunway1 = GROUP:FindByName( "Vaziani Runway 1" ) + -- self.Airbases.Vaziani.ZoneRunways[1] = ZONE_POLYGON:New( "Vaziani Runway 1", VazianiRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush() + -- + -- + -- + + + -- -- Template + -- local TemplateBoundary = GROUP:FindByName( "Template Boundary" ) + -- self.Airbases.Template.ZoneBoundary = ZONE_POLYGON:New( "Template Boundary", TemplateBoundary ):SmokeZone(POINT_VEC3.SmokeColor.White):Flush() + -- + -- local TemplateRunway1 = GROUP:FindByName( "Template Runway 1" ) + -- self.Airbases.Template.ZoneRunways[1] = ZONE_POLYGON:New( "Template Runway 1", TemplateRunway1 ):SmokeZone(POINT_VEC3.SmokeColor.Red):Flush() + + return self + +end + +--- This module contains the DETECTION classes. +-- +-- === +-- +-- 1) @{Detection#DETECTION_BASE} class, extends @{Base#BASE} +-- ===================================================== +-- The @{Detection#DETECTION_BASE} class defines the core functions to administer detected objects. +-- Detected objects are grouped in SETS of UNITS. +-- +-- @module Detection +-- @author Mechanic : Concept & Testing +-- @author FlightControl : Design & Programming + + + +--- DETECTION_BASE class +-- @type DETECTION_BASE +-- @field Group#GROUP FACGroup The GROUP in the Forward Air Controller role. +-- @field DCSTypes#Distance DetectionRange The range till which targets are accepted to be detected. +-- @field DCSTypes#Distance DetectionZoneRange The range till which targets are grouped upon the first detected target. +-- @field #DETECTION_BASE.DetectedUnitSets DetectedUnitSets A list of @{Set#SET_UNIT}s containing the units in each set that were detected within a DetectedZoneRange. +-- @field #DETECTION_BASE.DetectedZones DetectedZones A list of @{Zone#ZONE_UNIT}s containing the zones of the reference detected units. +-- @extends Set#SET_BASE +DETECTION_BASE = { + ClassName = "DETECTION_BASE", + DetectedUnitSets = {}, + DetectedUnits = {}, + FACGroup = nil, + DetectionRange = nil, + DetectionZoneRange = nil, +} + +--- @type DETECTION_BASE.DetectedUnitSets +-- @list + + +--- @type DETECTION_BASE.DetectedZones +-- @list + + +--- DETECTION constructor. +-- @param #DETECTION_BASE self +-- @return #DETECTION_BASE self +function DETECTION_BASE:New( FACGroup, DetectionRange, DetectionZoneRange ) + + -- Inherits from BASE + local self = BASE:Inherit( self, BASE:New() ) + + self.FACGroup = FACGroup + self.DetectionRange = DetectionRange + self.DetectionZoneRange = DetectionZoneRange + + self.DetectionScheduler = SCHEDULER:New(self, self._DetectionScheduler, { self, "Detection" }, 10, 30, 0.2 ) +end + +--- Form @{Set}s of detected @{Unit#UNIT}s in an array of @{Set#SET_UNIT}s. +-- @param #DETECTION_BASE self +function DETECTION_BASE:_DetectionScheduler( SchedulerName ) + self:F2( { SchedulerName } ) + + self.DetectedUnitSets = {} + + if self.FACGroup:IsAlive() then + local FACGroupName = self.FACGroup:GetName() + local FACDetectedTargets = self.FACGroup:GetDetectedTargets() + + for FACDetectedTargetID, FACDetectedTarget in pairs( FACDetectedTargets ) do + local FACObject = FACDetectedTarget.object + self:T2( FACObject ) + + if FACObject and FACObject:isExist() and FACObject.id_ < 50000000 then + + local FACDetectedUnit = UNIT:Find( FACObject ) + local FACDetectedUnitName = FACDetectedUnit:GetName() + + local FACDetectedUnitPositionVec3 = FACDetectedUnit:GetPointVec3() + local FACGroupPositionVec3 = self.FACGroup:GetPointVec3() + local Distance = ( ( FACDetectedUnitPositionVec3.x - FACGroupPositionVec3.x )^2 + + ( FACDetectedUnitPositionVec3.y - FACGroupPositionVec3.y )^2 + + ( FACDetectedUnitPositionVec3.z - FACGroupPositionVec3.z )^2 + ) ^ 0.5 / 1000 + + self:T( { FACGroupName, FACDetectedUnitName, Distance } ) + + if Distance <= self.DetectionRange then + + if not self.DetectedUnits[FACDetectedUnitName] then + self.DetectedUnits[FACDetectedUnitName] = {} + end + self.DetectedUnits[FACDetectedUnitName].DetectedUnit = UNIT:FindByName( FACDetectedUnitName ) + self.DetectedUnits[FACDetectedUnitName].Visible = FACDetectedTarget.visible + self.DetectedUnits[FACDetectedUnitName].Type = FACDetectedTarget.type + self.DetectedUnits[FACDetectedUnitName].Distance = FACDetectedTarget.distance + else + -- if beyond the DetectionRange then nullify... + if self.DetectedUnits[FACDetectedUnitName] then + self.DetectedUnits[FACDetectedUnitName] = nil + end + end + end + end + + -- okay, now we have a list of detected unit names ... + -- Sort the table based on distance ... + self:T( { "Sorting DetectedUnits table:", self.DetectedUnits } ) + table.sort( self.DetectedUnits, function( a, b ) return a.Distance < b.Distance end ) + self:T( { "Sorted Targets Table:", self.DetectedUnits } ) + + -- Now group the DetectedUnits table into SET_UNITs, evaluating the DetectionZoneRange. + + if self.DetectedUnits then + for DetectedUnitName, DetectedUnitData in pairs( self.DetectedUnits ) do + local DetectedUnit = DetectedUnitData.DetectedUnit -- Unit#UNIT + self:T( DetectedUnit:GetName() ) + if #self.DetectedUnitSets == 0 then + self:T( { "Adding Unit Set #", 1 } ) + self.DetectedUnitSets[1] = {} + self.DetectedUnitSets[1].Zone = ZONE_UNIT:New( DetectedUnitName, DetectedUnit, self.DetectionZoneRange ) + self.DetectedUnitSets[1].Set = SET_UNIT:New() + self.DetectedUnitSets[1].Set:AddUnit( DetectedUnit ) + else + local AddedToSet = false + for DetectedUnitSetID, DetectedUnitSetData in pairs( self.DetectedUnitSets ) do + self:T( "Detected Unit Set #" .. DetectedUnitSetID ) + local DetectedUnitSet = DetectedUnitSetData.Set -- Set#SET_UNIT + local DetectedZone = DetectedUnitSetData.Zone -- Zone#ZONE_UNIT + if DetectedUnit:IsInZone( DetectedZone ) then + self:T( "Adding to Unit Set #" .. DetectedUnitSetID ) + self.DetectedUnitSets[DetectedUnitSetID].Set:AddUnit( DetectedUnit ) + AddedToSet = true + end + end + if AddedToSet == false then + self:T( "Adding new Unit Set #" .. #self.DetectedUnitSets+1 ) + self.DetectedUnitSets[#self.DetectedUnitSets+1] = {} + self.DetectedUnitSets[#self.DetectedUnitSets].Zone = ZONE_UNIT:New( DetectedUnitName, DetectedUnit, self.DetectionZoneRange ) + self.DetectedUnitSets[#self.DetectedUnitSets].Set = SET_UNIT:New() + self.DetectedUnitSets[#self.DetectedUnitSets].Set:AddUnit( DetectedUnit ) + end + end + end + end + + -- Now all the tests should have been build, now make some smoke and flares... + + for DetectedUnitSetID, DetectedUnitSetData in pairs( self.DetectedUnitSets ) do + local DetectedUnitSet = DetectedUnitSetData.Set -- Set#SET_UNIT + local DetectedZone = DetectedUnitSetData.Zone -- Zone#ZONE_UNIT + self:T( "Detected Set #" .. DetectedUnitSetID ) + DetectedUnitSet:ForEachUnit( + --- @param Unit#UNIT DetectedUnit + function( DetectedUnit ) + self:T( DetectedUnit:GetName() ) + DetectedUnit:FlareRed() + end + ) + DetectedZone:SmokeZone( POINT_VEC3.SmokeColor.White, 30 ) + end + end +end BASE:TraceOnOff( false ) env.info( '*** MOOSE INCLUDE END *** ' ) diff --git a/Moose Mission Setup/Moose_Create.bat b/Moose Mission Setup/Moose_Create.bat index 6265d188b..c2007e1cb 100644 --- a/Moose Mission Setup/Moose_Create.bat +++ b/Moose Mission Setup/Moose_Create.bat @@ -74,6 +74,8 @@ COPY /b Moose.lua + %1\Sead.lua Moose.lua COPY /b Moose.lua + %1\Escort.lua Moose.lua COPY /b Moose.lua + %1\MissileTrainer.lua Moose.lua COPY /b Moose.lua + %1\AIBalancer.lua Moose.lua +COPY /b Moose.lua + %1\AirbasePolice.lua Moose.lua +COPY /b Moose.lua + %1\Detection.lua Moose.lua COPY /b Moose.lua + "Moose Create Static\Moose_Trace_Off.lua" Moose.lua diff --git a/Moose Test Missions/Moose_Test_AIBALANCER/Moose_Test_AIBALANCER.miz b/Moose Test Missions/Moose_Test_AIBALANCER/Moose_Test_AIBALANCER.miz index 23fb906eb..fa9df5d23 100644 Binary files a/Moose Test Missions/Moose_Test_AIBALANCER/Moose_Test_AIBALANCER.miz and b/Moose Test Missions/Moose_Test_AIBALANCER/Moose_Test_AIBALANCER.miz differ diff --git a/Moose Test Missions/Moose_Test_AIRBASEPOLICE/Moose_Test_AIRBASEPOLICE.miz b/Moose Test Missions/Moose_Test_AIRBASEPOLICE/Moose_Test_AIRBASEPOLICE.miz index 1382a0fd7..889c0c02b 100644 Binary files a/Moose Test Missions/Moose_Test_AIRBASEPOLICE/Moose_Test_AIRBASEPOLICE.miz and b/Moose Test Missions/Moose_Test_AIRBASEPOLICE/Moose_Test_AIRBASEPOLICE.miz differ diff --git a/Moose Test Missions/Moose_Test_BASE/Moose_Test_AIRBLANCER_with_Moose.miz b/Moose Test Missions/Moose_Test_BASE/Moose_Test_AIRBLANCER_with_Moose.miz index 10f317853..9c062463a 100644 Binary files a/Moose Test Missions/Moose_Test_BASE/Moose_Test_AIRBLANCER_with_Moose.miz and b/Moose Test Missions/Moose_Test_BASE/Moose_Test_AIRBLANCER_with_Moose.miz differ diff --git a/Moose Test Missions/Moose_Test_BASE/Moose_Test_AIRBLANCER_without_Moose.miz b/Moose Test Missions/Moose_Test_BASE/Moose_Test_AIRBLANCER_without_Moose.miz index cebcf095f..a9f5cb2c9 100644 Binary files a/Moose Test Missions/Moose_Test_BASE/Moose_Test_AIRBLANCER_without_Moose.miz and b/Moose Test Missions/Moose_Test_BASE/Moose_Test_AIRBLANCER_without_Moose.miz differ diff --git a/Moose Test Missions/Moose_Test_BASE/Moose_Test_BASE.miz b/Moose Test Missions/Moose_Test_BASE/Moose_Test_BASE.miz index e451bf44a..bdd4c750e 100644 Binary files a/Moose Test Missions/Moose_Test_BASE/Moose_Test_BASE.miz and b/Moose Test Missions/Moose_Test_BASE/Moose_Test_BASE.miz differ diff --git a/Moose Test Missions/Moose_Test_CLEANUP/Moose_Test_CLEANUP.miz b/Moose Test Missions/Moose_Test_CLEANUP/Moose_Test_CLEANUP.miz index cae2f660c..8498701f6 100644 Binary files a/Moose Test Missions/Moose_Test_CLEANUP/Moose_Test_CLEANUP.miz and b/Moose Test Missions/Moose_Test_CLEANUP/Moose_Test_CLEANUP.miz differ diff --git a/Moose Test Missions/Moose_Test_DESTROY/MOOSE_Test_DESTROY.miz b/Moose Test Missions/Moose_Test_DESTROY/MOOSE_Test_DESTROY.miz index 3299ab03b..f55c36cdf 100644 Binary files a/Moose Test Missions/Moose_Test_DESTROY/MOOSE_Test_DESTROY.miz and b/Moose Test Missions/Moose_Test_DESTROY/MOOSE_Test_DESTROY.miz differ diff --git a/Moose Test Missions/Moose_Test_DETECTION/Moose_Test_DETECTION.lua b/Moose Test Missions/Moose_Test_DETECTION/Moose_Test_DETECTION.lua new file mode 100644 index 000000000..9caae011f --- /dev/null +++ b/Moose Test Missions/Moose_Test_DETECTION/Moose_Test_DETECTION.lua @@ -0,0 +1,4 @@ + +local FACGroup = GROUP:FindByName( "FAC Group" ) + +local FACDetection = DETECTION_BASE:New( FACGroup, 1000, 250 ) \ No newline at end of file diff --git a/Moose Test Missions/Moose_Test_DETECTION/Moose_Test_DETECTION.miz b/Moose Test Missions/Moose_Test_DETECTION/Moose_Test_DETECTION.miz new file mode 100644 index 000000000..a60644396 Binary files /dev/null and b/Moose Test Missions/Moose_Test_DETECTION/Moose_Test_DETECTION.miz differ diff --git a/Moose Test Missions/Moose_Test_ESCORT/MOOSE_Test_ESCORT.miz b/Moose Test Missions/Moose_Test_ESCORT/MOOSE_Test_ESCORT.miz index 4a9406b05..5118021e3 100644 Binary files a/Moose Test Missions/Moose_Test_ESCORT/MOOSE_Test_ESCORT.miz and b/Moose Test Missions/Moose_Test_ESCORT/MOOSE_Test_ESCORT.miz differ diff --git a/Moose Test Missions/Moose_Test_MISSILETRAINER/Moose_Test_MISSILETRAINER.miz b/Moose Test Missions/Moose_Test_MISSILETRAINER/Moose_Test_MISSILETRAINER.miz index 1d54e02a9..44779ba59 100644 Binary files a/Moose Test Missions/Moose_Test_MISSILETRAINER/Moose_Test_MISSILETRAINER.miz and b/Moose Test Missions/Moose_Test_MISSILETRAINER/Moose_Test_MISSILETRAINER.miz differ diff --git a/Moose Test Missions/Moose_Test_SEAD/MOOSE_Test_SEAD.miz b/Moose Test Missions/Moose_Test_SEAD/MOOSE_Test_SEAD.miz index 9c48dae59..feeb3e21e 100644 Binary files a/Moose Test Missions/Moose_Test_SEAD/MOOSE_Test_SEAD.miz and b/Moose Test Missions/Moose_Test_SEAD/MOOSE_Test_SEAD.miz differ diff --git a/Moose Test Missions/Moose_Test_SET_CLIENT/Moose_Test_SET_CLIENT.miz b/Moose Test Missions/Moose_Test_SET_CLIENT/Moose_Test_SET_CLIENT.miz index 4d1619242..688d5dfe2 100644 Binary files a/Moose Test Missions/Moose_Test_SET_CLIENT/Moose_Test_SET_CLIENT.miz and b/Moose Test Missions/Moose_Test_SET_CLIENT/Moose_Test_SET_CLIENT.miz differ diff --git a/Moose Test Missions/Moose_Test_SET_GROUP/Moose_Test_SET_GROUP.miz b/Moose Test Missions/Moose_Test_SET_GROUP/Moose_Test_SET_GROUP.miz index 20ea2e55b..ce45cccc9 100644 Binary files a/Moose Test Missions/Moose_Test_SET_GROUP/Moose_Test_SET_GROUP.miz and b/Moose Test Missions/Moose_Test_SET_GROUP/Moose_Test_SET_GROUP.miz differ diff --git a/Moose Test Missions/Moose_Test_SPAWN/MOOSE_Test_SPAWN.miz b/Moose Test Missions/Moose_Test_SPAWN/MOOSE_Test_SPAWN.miz index 496edc2c6..081240f50 100644 Binary files a/Moose Test Missions/Moose_Test_SPAWN/MOOSE_Test_SPAWN.miz and b/Moose Test Missions/Moose_Test_SPAWN/MOOSE_Test_SPAWN.miz differ diff --git a/Moose Test Missions/Moose_Test_SPAWN_Repeat/MOOSE_Test_SPAWN_Repeat.miz b/Moose Test Missions/Moose_Test_SPAWN_Repeat/MOOSE_Test_SPAWN_Repeat.miz index f8d3e4101..9e1ae2aa2 100644 Binary files a/Moose Test Missions/Moose_Test_SPAWN_Repeat/MOOSE_Test_SPAWN_Repeat.miz and b/Moose Test Missions/Moose_Test_SPAWN_Repeat/MOOSE_Test_SPAWN_Repeat.miz differ diff --git a/Moose Test Missions/Moose_Test_TASK_Pickup_and_Deploy/MOOSE_Test_TASK_Pickup_and_Deploy.miz b/Moose Test Missions/Moose_Test_TASK_Pickup_and_Deploy/MOOSE_Test_TASK_Pickup_and_Deploy.miz index 4afd8f05c..9e16f307d 100644 Binary files a/Moose Test Missions/Moose_Test_TASK_Pickup_and_Deploy/MOOSE_Test_TASK_Pickup_and_Deploy.miz and b/Moose Test Missions/Moose_Test_TASK_Pickup_and_Deploy/MOOSE_Test_TASK_Pickup_and_Deploy.miz differ diff --git a/Moose Test Missions/Moose_Test_WRAPPER/Moose_Test_WRAPPER.miz b/Moose Test Missions/Moose_Test_WRAPPER/Moose_Test_WRAPPER.miz index 15d1b1326..366fdb2a7 100644 Binary files a/Moose Test Missions/Moose_Test_WRAPPER/Moose_Test_WRAPPER.miz and b/Moose Test Missions/Moose_Test_WRAPPER/Moose_Test_WRAPPER.miz differ diff --git a/Moose Test Missions/Moose_Test_ZONE/Moose_Test_ZONE.miz b/Moose Test Missions/Moose_Test_ZONE/Moose_Test_ZONE.miz index bf4f2c02a..07def4d67 100644 Binary files a/Moose Test Missions/Moose_Test_ZONE/Moose_Test_ZONE.miz and b/Moose Test Missions/Moose_Test_ZONE/Moose_Test_ZONE.miz differ diff --git a/Moose Test Missions/Moose_Test_ZONE_POLYGON/Moose_Test_ZONE_POLYGON.miz b/Moose Test Missions/Moose_Test_ZONE_POLYGON/Moose_Test_ZONE_POLYGON.miz index c4ce960a8..d1564ffee 100644 Binary files a/Moose Test Missions/Moose_Test_ZONE_POLYGON/Moose_Test_ZONE_POLYGON.miz and b/Moose Test Missions/Moose_Test_ZONE_POLYGON/Moose_Test_ZONE_POLYGON.miz differ diff --git a/Moose Test Missions/Moose_Test_ZONE_RADIUS/Moose_Test_ZONE_RADIUS.miz b/Moose Test Missions/Moose_Test_ZONE_RADIUS/Moose_Test_ZONE_RADIUS.miz index e36b81726..0e9111de0 100644 Binary files a/Moose Test Missions/Moose_Test_ZONE_RADIUS/Moose_Test_ZONE_RADIUS.miz and b/Moose Test Missions/Moose_Test_ZONE_RADIUS/Moose_Test_ZONE_RADIUS.miz differ diff --git a/Moose Test Missions/Moose_Test_ZONE_UNIT/Moose_Test_ZONE_UNIT.miz b/Moose Test Missions/Moose_Test_ZONE_UNIT/Moose_Test_ZONE_UNIT.miz index b124b31ae..d634ccd7f 100644 Binary files a/Moose Test Missions/Moose_Test_ZONE_UNIT/Moose_Test_ZONE_UNIT.miz and b/Moose Test Missions/Moose_Test_ZONE_UNIT/Moose_Test_ZONE_UNIT.miz differ