diff --git a/Moose Development/Moose/AI/AI_A2A_Dispatcher.lua b/Moose Development/Moose/AI/AI_A2A_Dispatcher.lua index f14d02b3a..32a0cabd0 100644 --- a/Moose Development/Moose/AI/AI_A2A_Dispatcher.lua +++ b/Moose Development/Moose/AI/AI_A2A_Dispatcher.lua @@ -168,26 +168,27 @@ do -- AI_A2A_DISPATCHER function AI_A2A_DISPATCHER:onafterCAP( SquadronName, Repeat ) - local A2AType = "CAP" - - self.DefenderSquadrons["CAP"] = self.DefenderSquadrons["CAP"] or {} - self.DefenderSquadrons["CAP"][SquadronName] = self.DefenderSquadrons["CAP"][SquadronName] or {} + self.DefenderSquadrons[SquadronName] = self.DefenderSquadrons[SquadronName] or {} + self.DefenderSquadrons[SquadronName].Cap = self.DefenderSquadrons[SquadronName].Cap or {} - local CAP = self.DefenderSquadrons["CAP"][SquadronName] - if CAP then + local DefenderSquadron = self.DefenderSquadrons[SquadronName] + local Cap = DefenderSquadron.Cap + + if Cap then if self:CanCAP( SquadronName ) then - local AIGroup = CAP.Spawn:Spawn() + local Spawn = DefenderSquadron.Spawn[ math.random( 1, #DefenderSquadron.Spawn ) ] + local AIGroup = Spawn:SpawnAtAirbase( DefenderSquadron.Airbase ) self:F( { AIGroup = AIGroup:GetName() } ) if AIGroup then - local Fsm = AI_A2A_CAP:New( AIGroup, CAP.Zone, CAP.FloorAltitude, CAP.CeilingAltitude, CAP.MinSpeed, CAP.MaxSpeed, CAP.AltType ) + local Fsm = AI_A2A_CAP:New( AIGroup, Cap.Zone, Cap.FloorAltitude, Cap.CeilingAltitude, Cap.MinSpeed, Cap.MaxSpeed, Cap.AltType ) Fsm:__Patrol( 1 ) self.DefenderTasks = self.DefenderTasks or {} self.DefenderTasks[AIGroup] = self.DefenderTasks[AIGroup] or {} - self.DefenderTasks[AIGroup].Type = A2AType + self.DefenderTasks[AIGroup].Type = "CAP" self.DefenderTasks[AIGroup].Fsm = Fsm end end @@ -202,8 +203,6 @@ do -- AI_A2A_DISPATCHER function AI_A2A_DISPATCHER:onafterENGAGE( From, Event, To, TargetSetUnit, TargetReference, AIGroups ) - local A2AType = "CAP" - self:F( { AIGroups = AIGroups } ) if AIGroups then @@ -229,33 +228,35 @@ do -- AI_A2A_DISPATCHER function AI_A2A_DISPATCHER:onafterINTERCEPT( From, Event, To, TargetSetUnit, TargetReference, DefendersMissing ) - local A2AType = "INTERCEPT" - local ClosestDistance = 0 - local ClosestINTERCEPTName = nil + local ClosestDefenderSquadronName = nil local AttackerCount = TargetSetUnit:Count() local DefendersCount = 0 while( DefendersCount < DefendersMissing ) do - for INTERCEPTName, INTERCEPT in pairs( self.DefenderSquadrons[A2AType] or {} ) do - - local SpawnCoord = INTERCEPT.Spawn:GetCoordinate() -- Core.Point#COORDINATE - local TargetCoord = TargetSetUnit:GetFirst():GetCoordinate() - local Distance = SpawnCoord:Get2DDistance( TargetCoord ) - - if ClosestDistance == 0 or Distance < ClosestDistance then - ClosestDistance = Distance - ClosestINTERCEPTName = INTERCEPTName + for SquadronName, DefenderSquadron in pairs( self.DefenderSquadrons or {} ) do + for InterceptID, Intercept in pairs( DefenderSquadron.Intercept or {} ) do + + local SpawnCoord = DefenderSquadron.Airbase:GetCoordinate() -- Core.Point#COORDINATE + local TargetCoord = TargetSetUnit:GetFirst():GetCoordinate() + local Distance = SpawnCoord:Get2DDistance( TargetCoord ) + + if ClosestDistance == 0 or Distance < ClosestDistance then + ClosestDistance = Distance + ClosestDefenderSquadronName = SquadronName + end end end - if ClosestINTERCEPTName then + if ClosestDefenderSquadronName then - local INTERCEPT = self.DefenderSquadrons[A2AType][ClosestINTERCEPTName] + local DefenderSquadron = self.DefenderSquadrons[ClosestDefenderSquadronName] + local Intercept = self.DefenderSquadrons[ClosestDefenderSquadronName].Intercept - local AIGroup = INTERCEPT.Spawn:Spawn() + local Spawn = DefenderSquadron.Spawn[ math.random( 1, #DefenderSquadron.Spawn ) ] + local AIGroup = Spawn:SpawnAtAirbase( DefenderSquadron.Airbase ) self:F( { AIGroup = AIGroup:GetName() } ) if AIGroup then @@ -267,7 +268,7 @@ do -- AI_A2A_DISPATCHER self.DefenderTasks = self.DefenderTasks or {} self.DefenderTasks[AIGroup] = self.DefenderTasks[AIGroup] or {} - self.DefenderTasks[AIGroup].Type = A2AType + self.DefenderTasks[AIGroup].Type = "INTERCEPT" self.DefenderTasks[AIGroup].Fsm = Fsm self.DefenderTasks[AIGroup].Target = TargetReference @@ -284,53 +285,80 @@ do -- AI_A2A_DISPATCHER end + function AI_A2A_DISPATCHER:SetSquadron( SquadronName, AirbaseName, SpawnTemplates, Resources ) - function AI_A2A_DISPATCHER:SetCAP( SquadronName, Spawn, Zone, FloorAltitude, CeilingAltitude, MinSpeed, MaxSpeed, AltType ) - - self.DefenderSquadrons["CAP"] = self.DefenderSquadrons["CAP"] or {} - self.DefenderSquadrons["CAP"][SquadronName] = self.DefenderSquadrons["CAP"][SquadronName] or {} - - local CAP = self.DefenderSquadrons["CAP"][SquadronName] - CAP.Name = SquadronName - CAP.Spawn = Spawn -- Funtional.Spawn#SPAWN - CAP.Zone = Zone - CAP.FloorAltitude = FloorAltitude - CAP.CeilingAltitude = CeilingAltitude - CAP.MinSpeed = MinSpeed - CAP.MaxSpeed = MaxSpeed - CAP.AltType = AltType + self.DefenderSquadrons[SquadronName] = self.DefenderSquadrons[SquadronName] or {} - self:SetCAPInterval( SquadronName, 60, 300, 1 ) + local DefenderSquadron = self.DefenderSquadrons[SquadronName] + + self:E( { AirbaseName = AirbaseName } ) + DefenderSquadron.Airbase = AIRBASE:FindByName( AirbaseName ) + self:E( { Airbase = DefenderSquadron.Airbase } ) + self:E( { AirbaseObject = DefenderSquadron.Airbase:GetDCSObject() } ) + + DefenderSquadron.Spawn = {} + if type( SpawnTemplates ) == "string" then + local SpawnTemplate = SpawnTemplates + DefenderSquadron.Spawn[1] = SPAWN:New( SpawnTemplate ) + else + for TemplateID, SpawnTemplate in pairs( SpawnTemplates ) do + DefenderSquadron.Spawn[#DefenderSquadron.Spawn+1] = SPAWN:New( SpawnTemplate ) + end + end + DefenderSquadron.Resources = Resources + end + + + function AI_A2A_DISPATCHER:SetCAP( SquadronName, Zone, FloorAltitude, CeilingAltitude, MinSpeed, MaxSpeed, AltType ) + + self.DefenderSquadrons[SquadronName] = self.DefenderSquadrons[SquadronName] or {} + self.DefenderSquadrons[SquadronName].Cap = self.DefenderSquadrons[SquadronName].Cap or {} + + local DefenderSquadron = self.DefenderSquadrons[SquadronName] + + local Cap = self.DefenderSquadrons[SquadronName].Cap + Cap.Name = SquadronName + Cap.Zone = Zone + Cap.FloorAltitude = FloorAltitude + Cap.CeilingAltitude = CeilingAltitude + Cap.MinSpeed = MinSpeed + Cap.MaxSpeed = MaxSpeed + Cap.AltType = AltType + + self:SetCAPInterval( SquadronName, 2, 180, 600, 1 ) end - function AI_A2A_DISPATCHER:SetCAPInterval( SquadronName, LowInterval, HighInterval, Probability ) + function AI_A2A_DISPATCHER:SetCAPInterval( SquadronName, Limit, LowInterval, HighInterval, Probability ) - self.DefenderSquadrons["CAP"] = self.DefenderSquadrons["CAP"] or {} - self.DefenderSquadrons["CAP"][SquadronName] = self.DefenderSquadrons["CAP"][SquadronName] or {} + self.DefenderSquadrons[SquadronName] = self.DefenderSquadrons[SquadronName] or {} + self.DefenderSquadrons[SquadronName].Cap = self.DefenderSquadrons[SquadronName].Cap or {} - local CAP = self.DefenderSquadrons["CAP"][SquadronName] - - if CAP then - CAP.LowInterval = LowInterval - CAP.HighInterval = HighInterval - CAP.Probability = Probability + local DefenderSquadron = self.DefenderSquadrons[SquadronName] + + local Cap = self.DefenderSquadrons[SquadronName].Cap + if Cap then + Cap.LowInterval = LowInterval + Cap.HighInterval = HighInterval + Cap.Probability = Probability + Cap.Limit = Limit else error( "This squadron does not exist:" .. SquadronName ) end - self:__CAP( self:GetCAPDelay( SquadronName ), SquadronName, true ) + self:__CAP( -self:GetCAPDelay( SquadronName ), SquadronName, true ) end function AI_A2A_DISPATCHER:GetCAPDelay( SquadronName ) - self.DefenderSquadrons["CAP"] = self.DefenderSquadrons["CAP"] or {} - self.DefenderSquadrons["CAP"][SquadronName] = self.DefenderSquadrons["CAP"][SquadronName] or {} + self.DefenderSquadrons[SquadronName] = self.DefenderSquadrons[SquadronName] or {} + self.DefenderSquadrons[SquadronName].Cap = self.DefenderSquadrons[SquadronName].Cap or {} - local CAP = self.DefenderSquadrons["CAP"][SquadronName] + local DefenderSquadron = self.DefenderSquadrons[SquadronName] - if CAP then - return math.random( CAP.LowInterval, CAP.HighInterval ) + local Cap = self.DefenderSquadrons[SquadronName].Cap + if Cap then + return math.random( Cap.LowInterval, Cap.HighInterval ) else error( "This squadron does not exist:" .. SquadronName ) end @@ -338,33 +366,34 @@ do -- AI_A2A_DISPATCHER function AI_A2A_DISPATCHER:CanCAP( SquadronName ) - self.DefenderSquadrons["CAP"] = self.DefenderSquadrons["CAP"] or {} - self.DefenderSquadrons["CAP"][SquadronName] = self.DefenderSquadrons["CAP"][SquadronName] or {} + self.DefenderSquadrons[SquadronName] = self.DefenderSquadrons[SquadronName] or {} + self.DefenderSquadrons[SquadronName].Cap = self.DefenderSquadrons[SquadronName].Cap or {} - local CAP = self.DefenderSquadrons["CAP"][SquadronName] + local DefenderSquadron = self.DefenderSquadrons[SquadronName] - if CAP then - local Probability = math.random() - if Probability < CAP.Probability then - return true - else - return false + local Cap = self.DefenderSquadrons[SquadronName].Cap + if Cap then + local CapCount = self:CountCapAirborne( SquadronName ) + if CapCount < Cap.Limit then + local Probability = math.random() + if Probability <= Cap.Probability then + return true + end end + return false else error( "This squadron does not exist:" .. SquadronName ) end end - function AI_A2A_DISPATCHER:SetINTERCEPT( Name, Spawn, MinSpeed, MaxSpeed ) + function AI_A2A_DISPATCHER:SetINTERCEPT( SquadronName, MinSpeed, MaxSpeed ) - self.DefenderSquadrons["INTERCEPT"] = self.DefenderSquadrons["INTERCEPT"] or {} - self.DefenderSquadrons["INTERCEPT"][Name] = self.DefenderSquadrons["INTERCEPT"][Name] or {} + self.DefenderSquadrons[SquadronName] = self.DefenderSquadrons[SquadronName] or {} + self.DefenderSquadrons[SquadronName].Intercept = self.DefenderSquadrons[SquadronName].Intercept or {} - local INTERCEPT = self.DefenderSquadrons["INTERCEPT"][Name] - INTERCEPT.Name = Name - INTERCEPT.Spawn = Spawn - INTERCEPT.MinSpeed = MinSpeed - INTERCEPT.MaxSpeed = MaxSpeed + local Intercept = self.DefenderSquadrons[SquadronName].Intercept + Intercept.Name = SquadronName + Intercept.MaxSpeed = MaxSpeed end @@ -393,6 +422,22 @@ do -- AI_A2A_DISPATCHER return nil end + + function AI_A2A_DISPATCHER:CountCapAirborne( SquadronName ) + + -- First, count the active AIGroups Units, targetting the DetectedSet + local CapCount = 0 + + local DefenderSquadron = self.DefenderSquadrons[SquadronName] + if DefenderSquadron then + for InterceptID, Intercept in pairs( DefenderSquadron.Intercept or {} ) do + CapCount = CapCount + 1 + end + end + + return CapCount + end + function AI_A2A_DISPATCHER:CountDefendersEngaged( DetectedItem ) @@ -613,27 +658,27 @@ do -- AI_A2A_DISPATCHER -- @param #boolean DetectedItemID -- @param #boolean DetectedItemChange -- @return Tasking.Task#TASK - function AI_A2A_DISPATCHER:EvaluateRemoveTask( DetectedItem, A2A_Index ) + function AI_A2A_DISPATCHER:EvaluateRemoveTask( DetectedItem, TargetIndex ) - local A2A_Target = self.DefenderTargets[A2A_Index] + local DefenderTarget = self.DefenderTargets[TargetIndex] - if A2A_Target then + if DefenderTarget then - for AIGroupName, AIGroup in pairs( A2A_Target.Groups ) do + for AIGroupName, AIGroup in pairs( DefenderTarget.Groups ) do local AIGroup = AIGroup -- Wrapper.Group#GROUP if not AIGroup:IsAlive() then self.DefenderTasks[AIGroup] = nil - self.DefenderTargets[A2A_Index].Groups[AIGroupName] = nil + self.DefenderTargets[TargetIndex].Groups[AIGroupName] = nil end end local DetectedSet = DetectedItem.Set -- Core.Set#SET_UNIT if DetectedSet:Count() == 0 then - self.DefenderTargets[A2A_Index] = nil + self.DefenderTargets[TargetIndex] = nil end end - return self.DefenderTargets[A2A_Index] + return self.DefenderTargets[TargetIndex] end diff --git a/Moose Development/Moose/AI/AI_A2A_Intercept.lua b/Moose Development/Moose/AI/AI_A2A_Intercept.lua index d177ae7ae..8ae61ff32 100644 --- a/Moose Development/Moose/AI/AI_A2A_Intercept.lua +++ b/Moose Development/Moose/AI/AI_A2A_Intercept.lua @@ -21,6 +21,9 @@ -- @module AI_A2A_Intercept +BASE:TraceClass("AI_A2A_INTERCEPT") + + --- @type AI_A2A_INTERCEPT -- @extends AI.AI_A2A#AI_A2A @@ -352,32 +355,40 @@ function AI_A2A_INTERCEPT:onafterEngage( AIGroup, From, Event, To, AttackSetUnit local EngageRoute = {} --- Calculate the current route point. - local CurrentVec2 = AIGroup:GetVec2() - --TODO: Create GetAltitude function for GROUP, and delete GetUnit(1). - local CurrentAltitude = AIGroup:GetUnit(1):GetAltitude() - local CurrentSpeed = AIGroup:GetUnit(1):GetVelocityKMH() - local CurrentPointVec3 = POINT_VEC3:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y ) - local ToEngageZoneSpeed = self.PatrolMaxSpeed - local CurrentRoutePoint = CurrentPointVec3:RoutePointAir( - self.PatrolAltType, - POINT_VEC3.RoutePointType.TurningPoint, - POINT_VEC3.RoutePointAction.TurningPoint, - CurrentSpeed, - true - ) - - EngageRoute[#EngageRoute+1] = CurrentRoutePoint + local CurrentCoord = AIGroup:GetCoordinate() + local ToTargetSpeed = math.random( self.MinSpeed, self.MaxSpeed ) + + if not AIGroup:GetUnit(1):IsAboveRunway() then + + --TODO: Create GetAltitude function for GROUP, and delete GetUnit(1). + local CurrentSpeed = AIGroup:GetUnit(1):GetVelocityKMH() + local ToEngageZoneSpeed = self.PatrolMaxSpeed + local CurrentRoutePoint = CurrentCoord:RoutePointAir( + self.PatrolAltType, + POINT_VEC3.RoutePointType.TurningPoint, + POINT_VEC3.RoutePointAction.TurningPoint, + ToTargetSpeed, + true + ) + + EngageRoute[#EngageRoute+1] = CurrentRoutePoint + end --- Find the target point. + + local ToTargetCoord = self.AttackSetUnit:GetFirst():GetCoordinate() - local ToTargetSpeed = math.random( self.MinSpeed, self.MaxSpeed ) + local ToInterceptAngle = CurrentCoord:GetAngleDegrees( CurrentCoord:GetDirectionVec3( ToTargetCoord ) ) + local ToInterceptCoord = CurrentCoord:Translate( 5000, ToInterceptAngle ) + self:T2( { self.MinSpeed, self.MaxSpeed, ToTargetSpeed } ) + --- Create a route point of type air. - local ToPatrolRoutePoint = ToTargetCoord:RoutePointAir( + local ToPatrolRoutePoint = ToInterceptCoord:RoutePointAir( self.PatrolAltType, POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, @@ -386,6 +397,8 @@ function AI_A2A_INTERCEPT:onafterEngage( AIGroup, From, Event, To, AttackSetUnit ) EngageRoute[#EngageRoute+1] = ToPatrolRoutePoint + + AIGroup:OptionROEOpenFire() AIGroup:OptionROTPassiveDefense() @@ -394,7 +407,7 @@ function AI_A2A_INTERCEPT:onafterEngage( AIGroup, From, Event, To, AttackSetUnit for AttackUnitID, AttackUnit in pairs( self.AttackSetUnit:GetSet() ) do local AttackUnit = AttackUnit -- Wrapper.Unit#UNIT - self:T( { AttackUnit, AttackUnit:IsAlive(), AttackUnit:IsAir() } ) + self:T( { "Intercepting Unit:", AttackUnit:GetName(), AttackUnit:IsAlive(), AttackUnit:IsAir() } ) if AttackUnit:IsAlive() and AttackUnit:IsAir() then AttackTasks[#AttackTasks+1] = AIGroup:TaskAttackUnit( AttackUnit ) end diff --git a/Moose Development/Moose/Core/Point.lua b/Moose Development/Moose/Core/Point.lua index 05309b052..18da277e7 100644 --- a/Moose Development/Moose/Core/Point.lua +++ b/Moose Development/Moose/Core/Point.lua @@ -138,12 +138,13 @@ do -- COORDINATE ClassName = "COORDINATE", } + --- COORDINATE constructor. -- @param #COORDINATE self -- @param Dcs.DCSTypes#Distance x The x coordinate of the Vec3 point, pointing to the North. -- @param Dcs.DCSTypes#Distance y The y coordinate of the Vec3 point, pointing to the Right. -- @param Dcs.DCSTypes#Distance z The z coordinate of the Vec3 point, pointing to the Right. - -- @return Core.Point#COORDINATE + -- @return #COORDINATE function COORDINATE:New( x, y, z ) local self = BASE:Inherit( self, BASE:New() ) -- #COORDINATE @@ -177,7 +178,7 @@ do -- COORDINATE --- Create a new COORDINATE object from Vec3 coordinates. -- @param #COORDINATE self -- @param Dcs.DCSTypes#Vec3 Vec3 The Vec3 point. - -- @return Core.Point#COORDINATE + -- @return #COORDINATE function COORDINATE:NewFromVec3( Vec3 ) local self = self:New( Vec3.x, Vec3.y, Vec3.z ) -- #COORDINATE diff --git a/Moose Development/Moose/Functional/Spawn.lua b/Moose Development/Moose/Functional/Spawn.lua index dd0315fd5..77a6c48c0 100644 --- a/Moose Development/Moose/Functional/Spawn.lua +++ b/Moose Development/Moose/Functional/Spawn.lua @@ -957,6 +957,68 @@ function SPAWN:OnSpawnGroup( SpawnCallBackFunction, ... ) return self end +--- Will spawn a group at an airbase. +-- This method is mostly advisable to be used if you want to simulate spawning units at an airbase. +-- Note that each point in the route assigned to the spawning group is reset to the point of the spawn. +-- You can use the returned group to further define the route to be followed. +-- @param #SPAWN self +-- @param Wrapper.Airbase#AIRBASE Airbase The @{Airbase} where to spawn the group. +-- @param #number SpawnIndex (optional) The index which group to spawn within the given zone. +-- @return Wrapper.Group#GROUP that was spawned. +-- @return #nil Nothing was spawned. +function SPAWN:SpawnAtAirbase( Airbase, SpawnIndex ) + self:F( { self.SpawnTemplatePrefix, Airbase, SpawnIndex } ) + + local PointVec3 = Airbase:GetPointVec3() + self:T2(PointVec3) + + if SpawnIndex then + else + SpawnIndex = self.SpawnIndex + 1 + end + + if self:_GetSpawnIndex( SpawnIndex ) then + + local SpawnTemplate = self.SpawnGroups[self.SpawnIndex].SpawnTemplate + + if SpawnTemplate then + + self:T( { "Current point of ", self.SpawnTemplatePrefix, Airbase } ) + + -- Translate the position of the Group Template to the Vec3. + for UnitID = 1, #SpawnTemplate.units do + self:T( 'Before Translation SpawnTemplate.units['..UnitID..'].x = ' .. SpawnTemplate.units[UnitID].x .. ', SpawnTemplate.units['..UnitID..'].y = ' .. SpawnTemplate.units[UnitID].y ) + local UnitTemplate = SpawnTemplate.units[UnitID] + local SX = UnitTemplate.x + local SY = UnitTemplate.y + local BX = SpawnTemplate.route.points[1].x + local BY = SpawnTemplate.route.points[1].y + local TX = PointVec3.x + ( SX - BX ) + local TY = PointVec3.z + ( SY - BY ) + SpawnTemplate.units[UnitID].x = TX + SpawnTemplate.units[UnitID].y = TY + SpawnTemplate.units[UnitID].alt = PointVec3.y + self:T( 'After Translation SpawnTemplate.units['..UnitID..'].x = ' .. SpawnTemplate.units[UnitID].x .. ', SpawnTemplate.units['..UnitID..'].y = ' .. SpawnTemplate.units[UnitID].y ) + end + + SpawnTemplate.route.points[1].x = PointVec3.x + SpawnTemplate.route.points[1].y = PointVec3.z + SpawnTemplate.route.points[1].alt = Airbase.y + SpawnTemplate.route.points[1].action = "From Parking Area Hot" + SpawnTemplate.route.points[1].type = "TakeOffParkingHot" + SpawnTemplate.route.points[1].airdromeId = Airbase:GetID() + + SpawnTemplate.x = PointVec3.x + SpawnTemplate.y = PointVec3.z + + return self:SpawnWithIndex( self.SpawnIndex ) + end + end + + return nil +end + + --- Will spawn a group from a Vec3 in 3D space. -- This method is mostly advisable to be used if you want to simulate spawning units in the air, like helicopters or airplanes. diff --git a/Moose Development/Moose/Wrapper/Airbase.lua b/Moose Development/Moose/Wrapper/Airbase.lua index 6d0900e33..cb08574e9 100644 --- a/Moose Development/Moose/Wrapper/Airbase.lua +++ b/Moose Development/Moose/Wrapper/Airbase.lua @@ -47,7 +47,7 @@ -- the first letter of the method is also capitalized. So, by example, the DCS Airbase method @{DCSWrapper.Airbase#Airbase.getName}() -- is implemented in the AIRBASE class as @{#AIRBASE.GetName}(). -- --- @field #AIRBASE +-- @field #AIRBASE AIRBASE AIRBASE = { ClassName="AIRBASE", CategoryName = { @@ -57,6 +57,31 @@ AIRBASE = { }, } +--- @field Caucasus +AIRBASE.Caucasus = { + ["Gelendzhik"] = "Gelendzhik", + ["Krasnodar_Pashkovsky"] = "Krasnodar-Pashkovsky", + ["Sukhumi_Babushara"] = "Sukhumi-Babushara", + ["Gudauta"] = "Gudauta", + ["Batumi"] = "Batumi", + ["Senaki_Kolkhi"] = "Senaki-Kolkhi", + ["Kobuleti"] = "Kobuleti", + ["Kutaisi"] = "Kutaisi", + ["Tbilisi_Lochini"] = "Tbilisi-Lochini", + ["Soganlug"] = "Soganlug", + ["Vaziani"] = "Vaziani", + ["Anapa_Vityazevo"] = "Anapa-Vityazevo", + ["Krasnodar_Center"] = "Krasnodar-Center", + ["Novorossiysk"] = "Novorossiysk", + ["Krymsk"] = "Krymsk", + ["Maykop_Khanskaya"] = "Maykop-Khanskaya", + ["Sochi_Adler"] = "Sochi-Adler", + ["Mineralnye_Vody"] = "Mineralnye Vody", + ["Nalchik"] = "Nalchik", + ["Mozdok"] = "Mozdok", + ["Beslan"] = "Beslan", + } + -- Registration. --- Create a new AIRBASE from DCSAirbase.