diff --git a/Moose Development/Moose/Core/Condition.lua b/Moose Development/Moose/Core/Condition.lua
index 7c25f1948..d88a1fc33 100644
--- a/Moose Development/Moose/Core/Condition.lua
+++ b/Moose Development/Moose/Core/Condition.lua
@@ -273,7 +273,7 @@ function CONDITION:_EvalConditionsAny(functions)
end
end
---- Create conditon fucntion object.
+--- Create conditon function object.
-- @param #CONDITION self
-- @param #function Function The function to call.
-- @param ... (Optional) Parameters passed to the function (if any).
diff --git a/Moose Development/Moose/Core/Menu.lua b/Moose Development/Moose/Core/Menu.lua
index 54328a0ec..2cbf1d6b5 100644
--- a/Moose Development/Moose/Core/Menu.lua
+++ b/Moose Development/Moose/Core/Menu.lua
@@ -378,6 +378,7 @@ do -- MENU_MISSION
end
end
+
--- Refreshes a radio item for a mission
-- @param #MENU_MISSION self
-- @return #MENU_MISSION
@@ -832,6 +833,29 @@ do
return self
end
+ --- Refreshes a new radio item for a group and submenus, ordering by (numerical) MenuTag
+ -- @param #MENU_GROUP self
+ -- @return #MENU_GROUP
+ function MENU_GROUP:RefreshAndOrderByTag()
+
+ do
+ missionCommands.removeItemForGroup( self.GroupID, self.MenuPath )
+ missionCommands.addSubMenuForGroup( self.GroupID, self.MenuText, self.MenuParentPath )
+
+ local MenuTable = {}
+ for MenuText, Menu in pairs( self.Menus or {} ) do
+ local tag = Menu.MenuTag or math.random(1,10000)
+ MenuTable[#MenuTable+1] = {Tag=tag, Enty=Menu}
+ end
+ table.sort(MenuTable, function (k1, k2) return k1.tag < k2.tag end )
+ for _, Menu in pairs( MenuTable ) do
+ Menu.Entry:Refresh()
+ end
+ end
+
+ return self
+ end
+
--- Removes the sub menus recursively of this MENU_GROUP.
-- @param #MENU_GROUP self
-- @param MenuStamp
diff --git a/Moose Development/Moose/Core/Zone.lua b/Moose Development/Moose/Core/Zone.lua
index 5debc3a12..02c915c90 100644
--- a/Moose Development/Moose/Core/Zone.lua
+++ b/Moose Development/Moose/Core/Zone.lua
@@ -899,8 +899,8 @@ end
-- @param ObjectCategories An array of categories of the objects to find in the zone. E.g. `{Object.Category.UNIT}`
-- @param UnitCategories An array of unit categories of the objects to find in the zone. E.g. `{Unit.Category.GROUND_UNIT,Unit.Category.SHIP}`
-- @usage
--- self.Zone:Scan({Object.Category.UNIT},{Unit.Category.GROUND_UNIT})
--- local IsAttacked = self.Zone:IsSomeInZoneOfCoalition( self.Coalition )
+-- myzone:Scan({Object.Category.UNIT},{Unit.Category.GROUND_UNIT})
+-- local IsAttacked = myzone:IsSomeInZoneOfCoalition( self.Coalition )
function ZONE_RADIUS:Scan( ObjectCategories, UnitCategories )
self.ScanData = {}
diff --git a/Moose Development/Moose/DCS.lua b/Moose Development/Moose/DCS.lua
index 8cbe4354d..b791abd27 100644
--- a/Moose Development/Moose/DCS.lua
+++ b/Moose Development/Moose/DCS.lua
@@ -1374,7 +1374,9 @@ do -- AI
--- @type AI.Option.Ground
-- @field #AI.Option.Ground.id id
-- @field #AI.Option.Ground.val val
-
+ -- @field #AI.Option.Ground.mid mid
+ -- @field #AI.Option.Ground.mval mval
+ --
--- @type AI.Option.Naval
-- @field #AI.Option.Naval.id id
-- @field #AI.Option.Naval.val val
@@ -1397,6 +1399,11 @@ do -- AI
-- @field PROHIBIT_AG
-- @field MISSILE_ATTACK
-- @field PROHIBIT_WP_PASS_REPORT
+ -- @field OPTION_RADIO_USAGE_CONTACT
+ -- @field OPTION_RADIO_USAGE_ENGAGE
+ -- @field OPTION_RADIO_USAGE_KILL
+ -- @field JETT_TANKS_IF_EMPTY
+ -- @field FORCED_ATTACK
--- @type AI.Option.Air.id.FORMATION
-- @field LINE_ABREAST
@@ -1466,19 +1473,35 @@ do -- AI
--- @type AI.Option.Ground.id
-- @field NO_OPTION
-- @field ROE @{#AI.Option.Ground.val.ROE}
+ -- @field FORMATION
-- @field DISPERSE_ON_ATTACK true or false
-- @field ALARM_STATE @{#AI.Option.Ground.val.ALARM_STATE}
-- @field ENGAGE_AIR_WEAPONS
+ -- @field AC_ENGAGEMENT_RANGE_RESTRICTION
+
+ --- @type AI.Option.Ground.mid -- Moose added
+ -- @field RESTRICT_AAA_MIN 27
+ -- @field RESTRICT_AAA_MAX 29
+ -- @field RESTRICT_TARGETS @{#AI.Option.Ground.mval.ENGAGE_TARGETS} 28
--- @type AI.Option.Ground.val
-- @field #AI.Option.Ground.val.ROE ROE
-- @field #AI.Option.Ground.val.ALARM_STATE ALARM_STATE
+ -- @field #AI.Option.Ground.val.ENGAGE_TARGETS RESTRICT_TARGETS
--- @type AI.Option.Ground.val.ROE
-- @field OPEN_FIRE
-- @field RETURN_FIRE
-- @field WEAPON_HOLD
+ --- @type AI.Option.Ground.mval -- Moose added
+ -- @field #AI.Option.Ground.mval.ENGAGE_TARGETS ENGAGE_TARGETS
+
+ --- @type AI.Option.Ground.mval.ENGAGE_TARGETS -- Moose added
+ -- @field ANY_TARGET -- 0
+ -- @field AIR_UNITS_ONLY -- 1
+ -- @field GROUND_UNITS_ONLY -- 2
+
--- @type AI.Option.Ground.val.ALARM_STATE
-- @field AUTO
-- @field GREEN
diff --git a/Moose Development/Moose/Functional/ATC_Ground.lua b/Moose Development/Moose/Functional/ATC_Ground.lua
index 269111aa6..2e72dcea3 100644
--- a/Moose Development/Moose/Functional/ATC_Ground.lua
+++ b/Moose Development/Moose/Functional/ATC_Ground.lua
@@ -18,6 +18,8 @@
--
-- ### Contributions: Dutch Baron - Concept & Testing
-- ### Author: FlightControl - Framework Design & Programming
+-- ### Refactoring to use the Runway auto-detection: Applevangelist
+-- @date August 2022
--
-- ===
--
@@ -28,21 +30,20 @@
-- @field Core.Set#SET_CLIENT SetClient
-- @extends Core.Base#BASE
---- Base class for ATC\_GROUND implementations.
+--- [DEPRECATED, use ATC_GROUND_UNIVERSAL] Base class for ATC\_GROUND implementations.
-- @field #ATC_GROUND
ATC_GROUND = {
ClassName = "ATC_GROUND",
SetClient = nil,
Airbases = nil,
AirbaseNames = nil,
- --KickSpeed = nil, -- The maximum speed in meters per second for all airbases until a player gets kicked. This is overridden at each derived class.
}
--- @type ATC_GROUND.AirbaseNames
-- @list <#string>
---- Creates a new ATC\_GROUND object.
+--- [DEPRECATED, use ATC_GROUND_UNIVERSAL] Creates a new ATC\_GROUND object.
-- @param #ATC_GROUND self
-- @param Airbases A table of Airbase Names.
-- @return #ATC_GROUND self
@@ -59,7 +60,7 @@ function ATC_GROUND:New( Airbases, AirbaseList )
for AirbaseID, Airbase in pairs( self.Airbases ) do
- -- Specified ZoneBoundary is used if setted or Airbase radius by default
+ -- Specified ZoneBoundary is used if set or Airbase radius by default
if Airbase.ZoneBoundary then
Airbase.ZoneBoundary = ZONE_POLYGON_BASE:New( "Boundary " .. AirbaseID, Airbase.ZoneBoundary )
else
@@ -67,8 +68,10 @@ function ATC_GROUND:New( Airbases, AirbaseList )
end
Airbase.ZoneRunways = {}
- for PointsRunwayID, PointsRunway in pairs( Airbase.PointsRunways ) do
- Airbase.ZoneRunways[PointsRunwayID] = ZONE_POLYGON_BASE:New( "Runway " .. PointsRunwayID, PointsRunway )
+ if Airbase.PointsRunways then
+ for PointsRunwayID, PointsRunway in pairs( Airbase.PointsRunways ) do
+ Airbase.ZoneRunways[PointsRunwayID] = ZONE_POLYGON_BASE:New( "Runway " .. PointsRunwayID, PointsRunway )
+ end
end
Airbase.Monitor = self.AirbaseList and false or true -- When AirbaseList is not given, monitor every Airbase, otherwise don't monitor any (yet).
end
@@ -78,13 +81,6 @@ function ATC_GROUND:New( Airbases, AirbaseList )
self.Airbases[AirbaseName].Monitor = true
end
--- -- Template
--- local TemplateBoundary = GROUP:FindByName( "Template Boundary" )
--- self.Airbases.Template.ZoneBoundary = ZONE_POLYGON:New( "Template Boundary", TemplateBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
---
--- local TemplateRunway1 = GROUP:FindByName( "Template Runway 1" )
--- self.Airbases.Template.ZoneRunways[1] = ZONE_POLYGON:New( "Template Runway 1", TemplateRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
-
self.SetClient:ForEachClient(
--- @param Wrapper.Client#CLIENT Client
function( Client )
@@ -103,7 +99,6 @@ function ATC_GROUND:New( Airbases, AirbaseList )
return self
end
-
--- Smoke the airbases runways.
-- @param #ATC_GROUND self
-- @param Utilities.Utils#SMOKECOLOR SmokeColor The color of the smoke around the runways.
@@ -117,7 +112,6 @@ function ATC_GROUND:SmokeRunways( SmokeColor )
end
end
-
--- Set the maximum speed in meters per second (Mps) until the player gets kicked.
-- An airbase can be specified to set the kick speed for.
-- @param #ATC_GROUND self
@@ -252,7 +246,6 @@ function ATC_GROUND:SetMaximumKickSpeedMiph( MaximumKickSpeedMiph, Airbase )
return self
end
-
--- @param #ATC_GROUND self
function ATC_GROUND:_AirbaseMonitor()
@@ -408,11 +401,455 @@ function ATC_GROUND:_AirbaseMonitor()
return true
end
+---
+-- @type ATC_GROUND_UNIVERSAL
+-- @field Core.Set#SET_CLIENT SetClient
+-- @field #string Version
+-- @field #string ClassName
+-- @field #table Airbases
+-- @field #table AirbaseList
+-- @field #number KickSpeed
+-- @extends Core.Base#BASE
+
+--- Base class for ATC\_GROUND\_UNIVERSAL implementations.
+-- @field #ATC_GROUND_UNIVERSAL
+ATC_GROUND_UNIVERSAL = {
+ ClassName = "ATC_GROUND_UNIVERSAL",
+ Version = "0.0.1",
+ SetClient = nil,
+ Airbases = nil,
+ AirbaseList = nil,
+ KickSpeed = nil, -- The maximum speed in meters per second for all airbases until a player gets kicked. This is overridden at each derived class.
+}
+
+--- Creates a new ATC\_GROUND\_UNIVERSAL object. This works on any map.
+-- @param #ATC_GROUND_UNIVERSAL self
+-- @param AirbaseList (Optional) A table of Airbase Names.
+-- @return #ATC_GROUND_UNIVERSAL self
+function ATC_GROUND_UNIVERSAL:New(AirbaseList)
+
+ -- Inherits from BASE
+ local self = BASE:Inherit( self, BASE:New() ) -- #ATC_GROUND
+ self:E( { self.ClassName } )
+
+ self.Airbases = {}
+
+ for _name,_ in pairs(_DATABASE.AIRBASES) do
+ self.Airbases[_name]={}
+ end
+
+ self.AirbaseList = AirbaseList
+
+ self.SetClient = SET_CLIENT:New():FilterCategories( "plane" ):FilterStart()
+
+
+ for AirbaseID, Airbase in pairs( self.Airbases ) do
+ -- Specified ZoneBoundary is used if set or Airbase radius by default
+ if Airbase.ZoneBoundary then
+ Airbase.ZoneBoundary = ZONE_POLYGON_BASE:New( "Boundary " .. AirbaseID, Airbase.ZoneBoundary )
+ else
+ Airbase.ZoneBoundary = _DATABASE:FindAirbase( AirbaseID ):GetZone()
+ end
+
+ Airbase.ZoneRunways = AIRBASE:FindByName(AirbaseID):GetRunways()
+ Airbase.Monitor = self.AirbaseList and false or true -- When AirbaseList is not given, monitor every Airbase, otherwise don't monitor any (yet).
+ end
+
+ -- Now activate the monitoring for the airbases that need to be monitored.
+ for AirbaseID, AirbaseName in pairs( self.AirbaseList or {} ) do
+ self.Airbases[AirbaseName].Monitor = true
+ end
+
+ self.SetClient:ForEachClient(
+ --- @param Wrapper.Client#CLIENT Client
+ function( Client )
+ Client:SetState( self, "Speeding", false )
+ Client:SetState( self, "Warnings", 0)
+ Client:SetState( self, "IsOffRunway", false )
+ Client:SetState( self, "OffRunwayWarnings", 0 )
+ Client:SetState( self, "Taxi", false )
+ end
+ )
+
+ -- This is simple slot blocker is used on the server.
+ SSB = USERFLAG:New( "SSB" )
+ SSB:Set( 100 )
+
+ -- Kickspeed
+ self.KickSpeed = UTILS.KnotsToMps(10)
+ self:SetMaximumKickSpeedMiph(30)
+
+ return self
+end
+
+
+--- Add a specific Airbase Boundary if you don't want to use the round zone that is auto-created.
+-- @param #ATC_GROUND_UNIVERSAL self
+-- @param #string Airbase The name of the Airbase
+-- @param Core.Zone#ZONE Zone The ZONE object to be used, e.g. a ZONE_POLYGON
+-- @return #ATC_GROUND_UNIVERSAL self
+function ATC_GROUND_UNIVERSAL:SetAirbaseBoundaries(Airbase, Zone)
+ self.Airbases[Airbase].ZoneBoundary = Zone
+ return self
+end
+
+--- Smoke the airbases runways.
+-- @param #ATC_GROUND_UNIVERSAL self
+-- @param Utilities.Utils#SMOKECOLOR SmokeColor The color of the smoke around the runways.
+-- @return #ATC_GROUND_UNIVERSAL self
+function ATC_GROUND_UNIVERSAL:SmokeRunways( SmokeColor )
+
+ local SmokeColor = SmokeColor or SMOKECOLOR.Red
+ for AirbaseID, Airbase in pairs( self.Airbases ) do
+ if Airbase.ZoneRunways then
+ for _,_runwaydata in pairs (Airbase.ZoneRunways) do
+ local runwaydata = _runwaydata -- Wrapper.Airbase#AIRBASE.Runway
+ runwaydata.zone:SmokeZone(SmokeColor)
+ end
+ end
+ end
+
+ return self
+end
+
+--- Draw the airbases runways.
+-- @param #ATC_GROUND_UNIVERSAL self
+-- @param #table Color The color of the line around the runways, in RGB, e.g `{1,0,0}` for red.
+-- @return #ATC_GROUND_UNIVERSAL self
+function ATC_GROUND_UNIVERSAL:DrawRunways( Color )
+
+ local Color = Color or {1,0,0}
+ for AirbaseID, Airbase in pairs( self.Airbases ) do
+ if Airbase.ZoneRunways then
+ for _,_runwaydata in pairs (Airbase.ZoneRunways) do
+ local runwaydata = _runwaydata -- Wrapper.Airbase#AIRBASE.Runway
+ runwaydata.zone:DrawZone(-1,Color)
+ end
+ end
+ end
+
+ return self
+end
+
+--- Draw the airbases boundaries.
+-- @param #ATC_GROUND_UNIVERSAL self
+-- @param #table Color The color of the line around the runways, in RGB, e.g `{1,0,0}` for red.
+-- @return #ATC_GROUND_UNIVERSAL self
+function ATC_GROUND_UNIVERSAL:DrawBoundaries( Color )
+
+ local Color = Color or {1,0,0}
+ for AirbaseID, Airbase in pairs( self.Airbases ) do
+ if Airbase.ZoneBoundary then
+ Airbase.ZoneBoundary:DrawZone(-1, Color)
+ end
+ end
+
+ return self
+end
+
+--- Set the maximum speed in meters per second (Mps) until the player gets kicked.
+-- An airbase can be specified to set the kick speed for.
+-- @param #ATC_GROUND_UNIVERSAL self
+-- @param #number KickSpeed The speed in Mps.
+-- @param #string Airbase (optional) The airbase name to set the kick speed for.
+-- @return #ATC_GROUND_UNIVERSAL self
+-- @usage
+--
+-- -- Declare Atc_Ground
+--
+-- Atc_Ground = ATC_GROUND_UNIVERSAL:New()
+--
+-- -- Then use one of these methods...
+--
+-- Atc_Ground:SetKickSpeed( UTILS.KmphToMps( 80 ) ) -- Kick the players at 80 kilometers per hour
+--
+-- Atc_Ground:SetKickSpeed( UTILS.MiphToMps( 100 ) ) -- Kick the players at 100 miles per hour
+--
+-- Atc_Ground:SetKickSpeed( 24 ) -- Kick the players at 24 meters per second ( 24 * 3.6 = 86.4 kilometers per hour )
+--
+function ATC_GROUND_UNIVERSAL:SetKickSpeed( KickSpeed, Airbase )
+
+ if not Airbase then
+ self.KickSpeed = KickSpeed
+ else
+ self.Airbases[Airbase].KickSpeed = KickSpeed
+ end
+
+ return self
+end
+
+--- Set the maximum speed in Kmph until the player gets kicked.
+-- @param #ATC_GROUND_UNIVERSAL self
+-- @param #number KickSpeed Set the speed in Kmph.
+-- @param #string Airbase (optional) The airbase name to set the kick speed for.
+-- @return #ATC_GROUND_UNIVERSAL self
+--
+-- Atc_Ground:SetKickSpeedKmph( 80 ) -- Kick the players at 80 kilometers per hour
+--
+function ATC_GROUND_UNIVERSAL:SetKickSpeedKmph( KickSpeed, Airbase )
+
+ self:SetKickSpeed( UTILS.KmphToMps( KickSpeed ), Airbase )
+
+ return self
+end
+
+--- Set the maximum speed in Miph until the player gets kicked.
+-- @param #ATC_GROUND_UNIVERSAL self
+-- @param #number KickSpeedMiph Set the speed in Mph.
+-- @param #string Airbase (optional) The airbase name to set the kick speed for.
+-- @return #ATC_GROUND_UNIVERSAL self
+--
+-- Atc_Ground:SetKickSpeedMiph( 100 ) -- Kick the players at 100 miles per hour
+--
+function ATC_GROUND_UNIVERSAL:SetKickSpeedMiph( KickSpeedMiph, Airbase )
+
+ self:SetKickSpeed( UTILS.MiphToMps( KickSpeedMiph ), Airbase )
+
+ return self
+end
+
+
+--- Set the maximum kick speed in meters per second (Mps) until the player gets kicked.
+-- There are no warnings given if this speed is reached, and is to prevent players to take off from the airbase!
+-- An airbase can be specified to set the maximum kick speed for.
+-- @param #ATC_GROUND_UNIVERSAL self
+-- @param #number MaximumKickSpeed The speed in Mps.
+-- @param #string Airbase (optional) The airbase name to set the kick speed for.
+-- @return #ATC_GROUND_UNIVERSAL self
+-- @usage
+--
+-- -- Declare Atc_Ground
+--
+-- Atc_Ground = ATC_GROUND_UNIVERSAL:New()
+--
+-- -- Then use one of these methods...
+--
+-- Atc_Ground:SetMaximumKickSpeed( UTILS.KmphToMps( 80 ) ) -- Kick the players at 80 kilometers per hour
+--
+-- Atc_Ground:SetMaximumKickSpeed( UTILS.MiphToMps( 100 ) ) -- Kick the players at 100 miles per hour
+--
+-- Atc_Ground:SetMaximumKickSpeed( 24 ) -- Kick the players at 24 meters per second ( 24 * 3.6 = 86.4 kilometers per hour )
+--
+function ATC_GROUND_UNIVERSAL:SetMaximumKickSpeed( MaximumKickSpeed, Airbase )
+
+ if not Airbase then
+ self.MaximumKickSpeed = MaximumKickSpeed
+ else
+ self.Airbases[Airbase].MaximumKickSpeed = MaximumKickSpeed
+ end
+
+ return self
+end
+
+--- Set the maximum kick speed in kilometers per hour (Kmph) until the player gets kicked.
+-- There are no warnings given if this speed is reached, and is to prevent players to take off from the airbase!
+-- An airbase can be specified to set the maximum kick speed for.
+-- @param #ATC_GROUND_UNIVERSAL self
+-- @param #number MaximumKickSpeed Set the speed in Kmph.
+-- @param #string Airbase (optional) The airbase name to set the kick speed for.
+-- @return #ATC_GROUND_UNIVERSAL self
+--
+-- Atc_Ground:SetMaximumKickSpeedKmph( 150 ) -- Kick the players at 150 kilometers per hour
+--
+function ATC_GROUND_UNIVERSAL:SetMaximumKickSpeedKmph( MaximumKickSpeed, Airbase )
+
+ self:SetMaximumKickSpeed( UTILS.KmphToMps( MaximumKickSpeed ), Airbase )
+
+ return self
+end
+
+--- Set the maximum kick speed in miles per hour (Miph) until the player gets kicked.
+-- There are no warnings given if this speed is reached, and is to prevent players to take off from the airbase!
+-- An airbase can be specified to set the maximum kick speed for.
+-- @param #ATC_GROUND_UNIVERSAL self
+-- @param #number MaximumKickSpeedMiph Set the speed in Mph.
+-- @param #string Airbase (optional) The airbase name to set the kick speed for.
+-- @return #ATC_GROUND_UNIVERSAL self
+--
+-- Atc_Ground:SetMaximumKickSpeedMiph( 100 ) -- Kick the players at 100 miles per hour
+--
+function ATC_GROUND_UNIVERSAL:SetMaximumKickSpeedMiph( MaximumKickSpeedMiph, Airbase )
+
+ self:SetMaximumKickSpeed( UTILS.MiphToMps( MaximumKickSpeedMiph ), Airbase )
+
+ return self
+end
+
+--- [Internal] Monitoring function
+-- @param #ATC_GROUND_UNIVERSAL self
+-- @return #ATC_GROUND_UNIVERSAL self
+function ATC_GROUND_UNIVERSAL:_AirbaseMonitor()
+
+ self.SetClient:ForEachClient(
+ --- @param Wrapper.Client#CLIENT Client
+ function( Client )
+
+ if Client:IsAlive() then
+
+ local IsOnGround = Client:InAir() == false
+
+ for AirbaseID, AirbaseMeta in pairs( self.Airbases ) do
+ self:E( AirbaseID, AirbaseMeta.KickSpeed )
+
+ if AirbaseMeta.Monitor == true and Client:IsInZone( AirbaseMeta.ZoneBoundary ) then
+
+ local NotInRunwayZone = true
+
+ if AirbaseMeta.ZoneRunways then
+ for _,_runwaydata in pairs (AirbaseMeta.ZoneRunways) do
+ local runwaydata = _runwaydata -- Wrapper.Airbase#AIRBASE.Runway
+ NotInRunwayZone = ( Client:IsNotInZone( _runwaydata.zone ) == true ) and NotInRunwayZone or false
+ end
+ end
+
+ if NotInRunwayZone then
+
+ if IsOnGround then
+ local Taxi = Client:GetState( self, "Taxi" )
+ self:E( Taxi )
+ if Taxi == false then
+ local Velocity = VELOCITY:New( AirbaseMeta.KickSpeed or self.KickSpeed )
+ Client:Message( "Welcome to " .. AirbaseID .. ". The maximum taxiing speed is " ..
+ Velocity:ToString() , 20, "ATC" )
+ Client:SetState( self, "Taxi", true )
+ end
+
+ -- TODO: GetVelocityKMH function usage
+ local Velocity = VELOCITY_POSITIONABLE:New( Client )
+ --MESSAGE:New( "Velocity = " .. Velocity:ToString(), 1 ):ToAll()
+ local IsAboveRunway = Client:IsAboveRunway()
+ self:T( {IsAboveRunway, IsOnGround, Velocity:Get() })
+
+ if IsOnGround then
+ local Speeding = false
+ if AirbaseMeta.MaximumKickSpeed then
+ if Velocity:Get() > AirbaseMeta.MaximumKickSpeed then
+ Speeding = true
+ end
+ else
+ if Velocity:Get() > self.MaximumKickSpeed then
+ Speeding = true
+ end
+ end
+ if Speeding == true then
+ MESSAGE:New( "Penalty! Player " .. Client:GetPlayerName() ..
+ " has been kicked, due to a severe airbase traffic rule violation ...", 10, "ATC" ):ToAll()
+ Client:Destroy()
+ Client:SetState( self, "Speeding", false )
+ Client:SetState( self, "Warnings", 0 )
+ end
+ end
+
+
+ if IsOnGround then
+
+ local Speeding = false
+ if AirbaseMeta.KickSpeed then -- If there is a speed defined for the airbase, use that only.
+ if Velocity:Get() > AirbaseMeta.KickSpeed then
+ Speeding = true
+ end
+ else
+ if Velocity:Get() > self.KickSpeed then
+ Speeding = true
+ end
+ end
+ if Speeding == true then
+ local IsSpeeding = Client:GetState( self, "Speeding" )
+
+ if IsSpeeding == true then
+ local SpeedingWarnings = Client:GetState( self, "Warnings" )
+ self:T( SpeedingWarnings )
+
+ if SpeedingWarnings <= 3 then
+ Client:Message( "Warning " .. SpeedingWarnings .. "/3! Airbase traffic rule violation! Slow down now! Your speed is " ..
+ Velocity:ToString(), 5, "ATC" )
+ Client:SetState( self, "Warnings", SpeedingWarnings + 1 )
+ else
+ MESSAGE:New( "Penalty! Player " .. Client:GetPlayerName() .. " has been kicked, due to a severe airbase traffic rule violation ...", 10, "ATC" ):ToAll()
+ --- @param Wrapper.Client#CLIENT Client
+ Client:Destroy()
+ Client:SetState( self, "Speeding", false )
+ Client:SetState( self, "Warnings", 0 )
+ end
+
+ else
+ Client:Message( "Attention! You are speeding on the taxiway, slow down! Your speed is " ..
+ Velocity:ToString(), 5, "ATC" )
+ Client:SetState( self, "Speeding", true )
+ Client:SetState( self, "Warnings", 1 )
+ end
+
+ else
+ Client:SetState( self, "Speeding", false )
+ Client:SetState( self, "Warnings", 0 )
+ end
+ end
+
+ if IsOnGround and not IsAboveRunway then
+
+ local IsOffRunway = Client:GetState( self, "IsOffRunway" )
+
+ if IsOffRunway == true then
+ local OffRunwayWarnings = Client:GetState( self, "OffRunwayWarnings" )
+ self:T( OffRunwayWarnings )
+
+ if OffRunwayWarnings <= 3 then
+ Client:Message( "Warning " .. OffRunwayWarnings .. "/3! Airbase traffic rule violation! Get back on the taxi immediately!", 5, "ATC" )
+ Client:SetState( self, "OffRunwayWarnings", OffRunwayWarnings + 1 )
+ else
+ MESSAGE:New( "Penalty! Player " .. Client:GetPlayerName() .. " has been kicked, due to a severe airbase traffic rule violation ...", 10, "ATC" ):ToAll()
+ --- @param Wrapper.Client#CLIENT Client
+ Client:Destroy()
+ Client:SetState( self, "IsOffRunway", false )
+ Client:SetState( self, "OffRunwayWarnings", 0 )
+ end
+ else
+ Client:Message( "Attention! You are off the taxiway. Get back on the taxiway immediately!", 5, "ATC" )
+ Client:SetState( self, "IsOffRunway", true )
+ Client:SetState( self, "OffRunwayWarnings", 1 )
+ end
+
+ else
+ Client:SetState( self, "IsOffRunway", false )
+ Client:SetState( self, "OffRunwayWarnings", 0 )
+ end
+ end
+ else
+ Client:SetState( self, "Speeding", false )
+ Client:SetState( self, "Warnings", 0 )
+ Client:SetState( self, "IsOffRunway", false )
+ Client:SetState( self, "OffRunwayWarnings", 0 )
+ local Taxi = Client:GetState( self, "Taxi" )
+ if Taxi == true then
+ Client:Message( "You have progressed to the runway ... Await take-off clearance ...", 20, "ATC" )
+ Client:SetState( self, "Taxi", false )
+ end
+ end
+ end
+ end
+ else
+ Client:SetState( self, "Taxi", false )
+ end
+ end
+ )
+
+ return true
+end
+
+--- Start SCHEDULER for ATC_GROUND_UNIVERSAL object.
+-- @param #ATC_GROUND_UNIVERSAL self
+-- @param RepeatScanSeconds Time in second for defining occurency of alerts.
+-- @return #ATC_GROUND_UNIVERSAL self
+function ATC_GROUND_UNIVERSAL:Start( RepeatScanSeconds )
+ RepeatScanSeconds = RepeatScanSeconds or 0.05
+ self.AirbaseMonitor = SCHEDULER:New( self, self._AirbaseMonitor, { self }, 0, 2, RepeatScanSeconds )
+ return self
+end
--- @type ATC_GROUND_CAUCASUS
-- @extends #ATC_GROUND
---- # ATC\_GROUND\_CAUCASUS, extends @{#ATC_GROUND}
+--- # ATC\_GROUND\_CAUCASUS, extends @{#ATC_GROUND_UNIVERSAL}
--
-- The ATC\_GROUND\_CAUCASUS class monitors the speed of the airplanes at the airbase during taxi.
-- The pilots may not drive faster than the maximum speed for the airbase, or they will be despawned.
@@ -520,269 +957,6 @@ end
-- @field #ATC_GROUND_CAUCASUS
ATC_GROUND_CAUCASUS = {
ClassName = "ATC_GROUND_CAUCASUS",
- Airbases = {
- [AIRBASE.Caucasus.Anapa_Vityazevo] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=242140.57142858,["x"]=-6478.8571428583,},
- [2]={["y"]=242188.57142858,["x"]=-6522.0000000011,},
- [3]={["y"]=244124.2857143,["x"]=-4344.0000000011,},
- [4]={["y"]=244068.2857143,["x"]=-4296.5714285726,},
- [5]={["y"]=242140.57142858,["x"]=-6480.0000000011,}
- },
- },
- },
- [AIRBASE.Caucasus.Batumi] = {
- 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,},
- },
- },
- },
- [AIRBASE.Caucasus.Beslan] = {
- 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,},
- },
- },
- },
- [AIRBASE.Caucasus.Gelendzhik] = {
- 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,},
- },
- },
- },
- [AIRBASE.Caucasus.Gudauta] = {
- 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,},
- },
- },
- },
- [AIRBASE.Caucasus.Kobuleti] = {
- 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,},
- },
- },
- },
- [AIRBASE.Caucasus.Krasnodar_Center] = {
- 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,},
- },
- },
- },
- [AIRBASE.Caucasus.Krasnodar_Pashkovsky] = {
- 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,},
- },
- },
- },
- [AIRBASE.Caucasus.Krymsk] = {
- 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,},
- },
- },
- },
- [AIRBASE.Caucasus.Kutaisi] = {
- 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,},
- },
- },
- },
- [AIRBASE.Caucasus.Maykop_Khanskaya] = {
- 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,},
- },
- },
- },
- [AIRBASE.Caucasus.Mineralnye_Vody] = {
- 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,},
- },
- },
- },
- [AIRBASE.Caucasus.Mozdok] = {
- 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,},
- },
- },
- },
- [AIRBASE.Caucasus.Nalchik] = {
- 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,},
- },
- },
- },
- [AIRBASE.Caucasus.Novorossiysk] = {
- 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,},
- },
- },
- },
- [AIRBASE.Caucasus.Senaki_Kolkhi] = {
- 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,},
- },
- },
- },
- [AIRBASE.Caucasus.Sochi_Adler] = {
- 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,},
- },
- },
- },
- [AIRBASE.Caucasus.Soganlug] = {
- 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,},
- },
- },
- },
- [AIRBASE.Caucasus.Sukhumi_Babushara] = {
- 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,},
- },
- },
- },
- [AIRBASE.Caucasus.Tbilisi_Lochini] = {
- 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,},
- },
- [2] = {
- [1]={["y"]=895605.71428572,["x"]=-314724.57142857,},
- [2]={["y"]=897639.71428572,["x"]=-316148,},
- [3]={["y"]=897683.42857143,["x"]=-316087.14285714,},
- [4]={["y"]=895650,["x"]=-314660,},
- [5]={["y"]=895606,["x"]=-314724.85714286,}
- },
- },
- },
- [AIRBASE.Caucasus.Vaziani] = {
- 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,},
- },
- },
- },
- },
}
--- Creates a new ATC_GROUND_CAUCASUS object.
@@ -792,216 +966,11 @@ ATC_GROUND_CAUCASUS = {
function ATC_GROUND_CAUCASUS:New( AirbaseNames )
-- Inherits from BASE
- local self = BASE:Inherit( self, ATC_GROUND:New( self.Airbases, AirbaseNames ) )
+ local self = BASE:Inherit( self, ATC_GROUND_UNIVERSAL:New(AirbaseNames) )
self:SetKickSpeedKmph( 50 )
self:SetMaximumKickSpeedKmph( 150 )
- -- -- AnapaVityazevo
- -- local AnapaVityazevoBoundary = GROUP:FindByName( "AnapaVityazevo Boundary" )
- -- self.Airbases.AnapaVityazevo.ZoneBoundary = ZONE_POLYGON:New( "AnapaVityazevo Boundary", AnapaVityazevoBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
- --
- -- local AnapaVityazevoRunway1 = GROUP:FindByName( "AnapaVityazevo Runway 1" )
- -- self.Airbases.AnapaVityazevo.ZoneRunways[1] = ZONE_POLYGON:New( "AnapaVityazevo Runway 1", AnapaVityazevoRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- --
- --
- --
- -- -- Batumi
- -- local BatumiBoundary = GROUP:FindByName( "Batumi Boundary" )
- -- self.Airbases.Batumi.ZoneBoundary = ZONE_POLYGON:New( "Batumi Boundary", BatumiBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
- --
- -- local BatumiRunway1 = GROUP:FindByName( "Batumi Runway 1" )
- -- self.Airbases.Batumi.ZoneRunways[1] = ZONE_POLYGON:New( "Batumi Runway 1", BatumiRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- --
- --
- --
- -- -- Beslan
- -- local BeslanBoundary = GROUP:FindByName( "Beslan Boundary" )
- -- self.Airbases.Beslan.ZoneBoundary = ZONE_POLYGON:New( "Beslan Boundary", BeslanBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
- --
- -- local BeslanRunway1 = GROUP:FindByName( "Beslan Runway 1" )
- -- self.Airbases.Beslan.ZoneRunways[1] = ZONE_POLYGON:New( "Beslan Runway 1", BeslanRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- --
- --
- --
- -- -- Gelendzhik
- -- local GelendzhikBoundary = GROUP:FindByName( "Gelendzhik Boundary" )
- -- self.Airbases.Gelendzhik.ZoneBoundary = ZONE_POLYGON:New( "Gelendzhik Boundary", GelendzhikBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
- --
- -- local GelendzhikRunway1 = GROUP:FindByName( "Gelendzhik Runway 1" )
- -- self.Airbases.Gelendzhik.ZoneRunways[1] = ZONE_POLYGON:New( "Gelendzhik Runway 1", GelendzhikRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- --
- --
- --
- -- -- Gudauta
- -- local GudautaBoundary = GROUP:FindByName( "Gudauta Boundary" )
- -- self.Airbases.Gudauta.ZoneBoundary = ZONE_POLYGON:New( "Gudauta Boundary", GudautaBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
- --
- -- local GudautaRunway1 = GROUP:FindByName( "Gudauta Runway 1" )
- -- self.Airbases.Gudauta.ZoneRunways[1] = ZONE_POLYGON:New( "Gudauta Runway 1", GudautaRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- --
- --
- --
- -- -- Kobuleti
- -- local KobuletiBoundary = GROUP:FindByName( "Kobuleti Boundary" )
- -- self.Airbases.Kobuleti.ZoneBoundary = ZONE_POLYGON:New( "Kobuleti Boundary", KobuletiBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
- --
- -- local KobuletiRunway1 = GROUP:FindByName( "Kobuleti Runway 1" )
- -- self.Airbases.Kobuleti.ZoneRunways[1] = ZONE_POLYGON:New( "Kobuleti Runway 1", KobuletiRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- --
- --
- --
- -- -- KrasnodarCenter
- -- local KrasnodarCenterBoundary = GROUP:FindByName( "KrasnodarCenter Boundary" )
- -- self.Airbases.KrasnodarCenter.ZoneBoundary = ZONE_POLYGON:New( "KrasnodarCenter Boundary", KrasnodarCenterBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
- --
- -- local KrasnodarCenterRunway1 = GROUP:FindByName( "KrasnodarCenter Runway 1" )
- -- self.Airbases.KrasnodarCenter.ZoneRunways[1] = ZONE_POLYGON:New( "KrasnodarCenter Runway 1", KrasnodarCenterRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- --
- --
- --
- -- -- KrasnodarPashkovsky
- -- local KrasnodarPashkovskyBoundary = GROUP:FindByName( "KrasnodarPashkovsky Boundary" )
- -- self.Airbases.KrasnodarPashkovsky.ZoneBoundary = ZONE_POLYGON:New( "KrasnodarPashkovsky Boundary", KrasnodarPashkovskyBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
- --
- -- local KrasnodarPashkovskyRunway1 = GROUP:FindByName( "KrasnodarPashkovsky Runway 1" )
- -- self.Airbases.KrasnodarPashkovsky.ZoneRunways[1] = ZONE_POLYGON:New( "KrasnodarPashkovsky Runway 1", KrasnodarPashkovskyRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- -- local KrasnodarPashkovskyRunway2 = GROUP:FindByName( "KrasnodarPashkovsky Runway 2" )
- -- self.Airbases.KrasnodarPashkovsky.ZoneRunways[2] = ZONE_POLYGON:New( "KrasnodarPashkovsky Runway 2", KrasnodarPashkovskyRunway2 ):SmokeZone(SMOKECOLOR.Red):Flush()
- --
- --
- --
- -- -- Krymsk
- -- local KrymskBoundary = GROUP:FindByName( "Krymsk Boundary" )
- -- self.Airbases.Krymsk.ZoneBoundary = ZONE_POLYGON:New( "Krymsk Boundary", KrymskBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
- --
- -- local KrymskRunway1 = GROUP:FindByName( "Krymsk Runway 1" )
- -- self.Airbases.Krymsk.ZoneRunways[1] = ZONE_POLYGON:New( "Krymsk Runway 1", KrymskRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- --
- --
- --
- -- -- Kutaisi
- -- local KutaisiBoundary = GROUP:FindByName( "Kutaisi Boundary" )
- -- self.Airbases.Kutaisi.ZoneBoundary = ZONE_POLYGON:New( "Kutaisi Boundary", KutaisiBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
- --
- -- local KutaisiRunway1 = GROUP:FindByName( "Kutaisi Runway 1" )
- -- self.Airbases.Kutaisi.ZoneRunways[1] = ZONE_POLYGON:New( "Kutaisi Runway 1", KutaisiRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- --
- --
- --
- -- -- MaykopKhanskaya
- -- local MaykopKhanskayaBoundary = GROUP:FindByName( "MaykopKhanskaya Boundary" )
- -- self.Airbases.MaykopKhanskaya.ZoneBoundary = ZONE_POLYGON:New( "MaykopKhanskaya Boundary", MaykopKhanskayaBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
- --
- -- local MaykopKhanskayaRunway1 = GROUP:FindByName( "MaykopKhanskaya Runway 1" )
- -- self.Airbases.MaykopKhanskaya.ZoneRunways[1] = ZONE_POLYGON:New( "MaykopKhanskaya Runway 1", MaykopKhanskayaRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- --
- --
- --
- -- -- MineralnyeVody
- -- local MineralnyeVodyBoundary = GROUP:FindByName( "MineralnyeVody Boundary" )
- -- self.Airbases.MineralnyeVody.ZoneBoundary = ZONE_POLYGON:New( "MineralnyeVody Boundary", MineralnyeVodyBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
- --
- -- local MineralnyeVodyRunway1 = GROUP:FindByName( "MineralnyeVody Runway 1" )
- -- self.Airbases.MineralnyeVody.ZoneRunways[1] = ZONE_POLYGON:New( "MineralnyeVody Runway 1", MineralnyeVodyRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- --
- --
- --
- -- -- Mozdok
- -- local MozdokBoundary = GROUP:FindByName( "Mozdok Boundary" )
- -- self.Airbases.Mozdok.ZoneBoundary = ZONE_POLYGON:New( "Mozdok Boundary", MozdokBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
- --
- -- local MozdokRunway1 = GROUP:FindByName( "Mozdok Runway 1" )
- -- self.Airbases.Mozdok.ZoneRunways[1] = ZONE_POLYGON:New( "Mozdok Runway 1", MozdokRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- --
- --
- --
- -- -- Nalchik
- -- local NalchikBoundary = GROUP:FindByName( "Nalchik Boundary" )
- -- self.Airbases.Nalchik.ZoneBoundary = ZONE_POLYGON:New( "Nalchik Boundary", NalchikBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
- --
- -- local NalchikRunway1 = GROUP:FindByName( "Nalchik Runway 1" )
- -- self.Airbases.Nalchik.ZoneRunways[1] = ZONE_POLYGON:New( "Nalchik Runway 1", NalchikRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- --
- --
- --
- -- -- Novorossiysk
- -- local NovorossiyskBoundary = GROUP:FindByName( "Novorossiysk Boundary" )
- -- self.Airbases.Novorossiysk.ZoneBoundary = ZONE_POLYGON:New( "Novorossiysk Boundary", NovorossiyskBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
- --
- -- local NovorossiyskRunway1 = GROUP:FindByName( "Novorossiysk Runway 1" )
- -- self.Airbases.Novorossiysk.ZoneRunways[1] = ZONE_POLYGON:New( "Novorossiysk Runway 1", NovorossiyskRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- --
- --
- --
- -- -- SenakiKolkhi
- -- local SenakiKolkhiBoundary = GROUP:FindByName( "SenakiKolkhi Boundary" )
- -- self.Airbases.SenakiKolkhi.ZoneBoundary = ZONE_POLYGON:New( "SenakiKolkhi Boundary", SenakiKolkhiBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
- --
- -- local SenakiKolkhiRunway1 = GROUP:FindByName( "SenakiKolkhi Runway 1" )
- -- self.Airbases.SenakiKolkhi.ZoneRunways[1] = ZONE_POLYGON:New( "SenakiKolkhi Runway 1", SenakiKolkhiRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- --
- --
- --
- -- -- SochiAdler
- -- local SochiAdlerBoundary = GROUP:FindByName( "SochiAdler Boundary" )
- -- self.Airbases.SochiAdler.ZoneBoundary = ZONE_POLYGON:New( "SochiAdler Boundary", SochiAdlerBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
- --
- -- local SochiAdlerRunway1 = GROUP:FindByName( "SochiAdler Runway 1" )
- -- self.Airbases.SochiAdler.ZoneRunways[1] = ZONE_POLYGON:New( "SochiAdler Runway 1", SochiAdlerRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- -- local SochiAdlerRunway2 = GROUP:FindByName( "SochiAdler Runway 2" )
- -- self.Airbases.SochiAdler.ZoneRunways[2] = ZONE_POLYGON:New( "SochiAdler Runway 2", SochiAdlerRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- --
- --
- --
- -- -- Soganlug
- -- local SoganlugBoundary = GROUP:FindByName( "Soganlug Boundary" )
- -- self.Airbases.Soganlug.ZoneBoundary = ZONE_POLYGON:New( "Soganlug Boundary", SoganlugBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
- --
- -- local SoganlugRunway1 = GROUP:FindByName( "Soganlug Runway 1" )
- -- self.Airbases.Soganlug.ZoneRunways[1] = ZONE_POLYGON:New( "Soganlug Runway 1", SoganlugRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- --
- --
- --
- -- -- SukhumiBabushara
- -- local SukhumiBabusharaBoundary = GROUP:FindByName( "SukhumiBabushara Boundary" )
- -- self.Airbases.SukhumiBabushara.ZoneBoundary = ZONE_POLYGON:New( "SukhumiBabushara Boundary", SukhumiBabusharaBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
- --
- -- local SukhumiBabusharaRunway1 = GROUP:FindByName( "SukhumiBabushara Runway 1" )
- -- self.Airbases.SukhumiBabushara.ZoneRunways[1] = ZONE_POLYGON:New( "SukhumiBabushara Runway 1", SukhumiBabusharaRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- --
- --
- --
- -- -- TbilisiLochini
- -- local TbilisiLochiniBoundary = GROUP:FindByName( "TbilisiLochini Boundary" )
- -- self.Airbases.TbilisiLochini.ZoneBoundary = ZONE_POLYGON:New( "TbilisiLochini Boundary", TbilisiLochiniBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
- --
- -- local TbilisiLochiniRunway1 = GROUP:FindByName( "TbilisiLochini Runway 1" )
- -- self.Airbases.TbilisiLochini.ZoneRunways[1] = ZONE_POLYGON:New( "TbilisiLochini Runway 1", TbilisiLochiniRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- --
- -- local TbilisiLochiniRunway2 = GROUP:FindByName( "TbilisiLochini Runway 2" )
- -- self.Airbases.TbilisiLochini.ZoneRunways[2] = ZONE_POLYGON:New( "TbilisiLochini Runway 2", TbilisiLochiniRunway2 ):SmokeZone(SMOKECOLOR.Red):Flush()
- --
- --
- --
- -- -- Vaziani
- -- local VazianiBoundary = GROUP:FindByName( "Vaziani Boundary" )
- -- self.Airbases.Vaziani.ZoneBoundary = ZONE_POLYGON:New( "Vaziani Boundary", VazianiBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
- --
- -- local VazianiRunway1 = GROUP:FindByName( "Vaziani Runway 1" )
- -- self.Airbases.Vaziani.ZoneRunways[1] = ZONE_POLYGON:New( "Vaziani Runway 1", VazianiRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- --
- --
- --
-
-
- -- Template
- -- local TemplateBoundary = GROUP:FindByName( "Template Boundary" )
- -- self.Airbases.Template.ZoneBoundary = ZONE_POLYGON:New( "Template Boundary", TemplateBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
- --
- -- local TemplateRunway1 = GROUP:FindByName( "Template Runway 1" )
- -- self.Airbases.Template.ZoneRunways[1] = ZONE_POLYGON:New( "Template Runway 1", TemplateRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
-
return self
end
@@ -1128,257 +1097,6 @@ end
-- @field #ATC_GROUND_NEVADA
ATC_GROUND_NEVADA = {
ClassName = "ATC_GROUND_NEVADA",
- Airbases = {
-
- [AIRBASE.Nevada.Beatty_Airport] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=-174950.05857143,["x"]=-329679.65,},
- [2]={["y"]=-174946.53828571,["x"]=-331394.03885715,},
- [3]={["y"]=-174967.10971429,["x"]=-331394.32457143,},
- [4]={["y"]=-174971.01828571,["x"]=-329682.59171429,},
- },
- },
- },
- [AIRBASE.Nevada.Boulder_City_Airport] = {
- PointsRunways = {
- [1] = {
- [1] = {["y"]=-1317.841714286,["x"]=-429014.92857142,},
- [2] = {["y"]=-951.26228571458,["x"]=-430310.21142856,},
- [3] = {["y"]=-978.11942857172,["x"]=-430317.06857142,},
- [4] = {["y"]=-1347.5088571432,["x"]=-429023.98485713,},
- },
- [2] = {
- [1] = {["y"]=-1879.955714286,["x"]=-429783.83742856,},
- [2] = {["y"]=-256.25257142886,["x"]=-430023.63542856,},
- [3] = {["y"]=-260.25257142886,["x"]=-430048.77828571,},
- [4] = {["y"]=-1883.955714286,["x"]=-429807.83742856,},
- },
- },
- },
- [AIRBASE.Nevada.Creech_AFB] = {
- PointsRunways = {
- [1] = {
- [1] = {["y"]=-74234.729142857,["x"]=-360501.80857143,},
- [2] = {["y"]=-77606.122285714,["x"]=-360417.86542857,},
- [3] = {["y"]=-77608.578,["x"]=-360486.13428571,},
- [4] = {["y"]=-74237.930571428,["x"]=-360586.25628571,},
- },
- [2] = {
- [1] = {["y"]=-75807.571428572,["x"]=-359073.42857142,},
- [2] = {["y"]=-74770.142857144,["x"]=-360581.71428571,},
- [3] = {["y"]=-74641.285714287,["x"]=-360585.42857142,},
- [4] = {["y"]=-75734.142857144,["x"]=-359023.14285714,},
- },
- },
- },
- [AIRBASE.Nevada.Echo_Bay] = {
- PointsRunways = {
- [1] = {
- [1] = {["y"]=33182.919428572,["x"]=-388698.21657142,},
- [2] = {["y"]=34202.543142857,["x"]=-388469.55485714,},
- [3] = {["y"]=34207.686,["x"]=-388488.69771428,},
- [4] = {["y"]=33185.422285715,["x"]=-388717.82228571,},
- },
- },
- },
- [AIRBASE.Nevada.Groom_Lake_AFB] = {
- PointsRunways = {
- [1] = {
- [1] = {["y"]=-85971.465428571,["x"]=-290567.77,},
- [2] = {["y"]=-87691.155428571,["x"]=-286637.75428571,},
- [3] = {["y"]=-87756.714285715,["x"]=-286663.99999999,},
- [4] = {["y"]=-86035.940285714,["x"]=-290598.81314286,},
- },
- [2] = {
- [1] = {["y"]=-86741.547142857,["x"]=-290353.31971428,},
- [2] = {["y"]=-89672.714285714,["x"]=-283546.57142855,},
- [3] = {["y"]=-89772.142857143,["x"]=-283587.71428569,},
- [4] = {["y"]=-86799.623714285,["x"]=-290374.16771428,},
- },
- },
- },
- [AIRBASE.Nevada.Henderson_Executive_Airport] = {
- PointsRunways = {
- [1] = {
- [1] = {["y"]=-25837.500571429,["x"]=-426404.25257142,},
- [2] = {["y"]=-25843.509428571,["x"]=-428752.67942856,},
- [3] = {["y"]=-25902.343714286,["x"]=-428749.96399999,},
- [4] = {["y"]=-25934.667142857,["x"]=-426411.45657142,},
- },
- [2] = {
- [1] = {["y"]=-25650.296285714,["x"]=-426510.17971428,},
- [2] = {["y"]=-25632.443428571,["x"]=-428297.11428571,},
- [3] = {["y"]=-25686.690285714,["x"]=-428299.37457142,},
- [4] = {["y"]=-25708.296285714,["x"]=-426515.15114285,},
- },
- },
- },
- [AIRBASE.Nevada.Jean_Airport] = {
- PointsRunways = {
- [1] = {
- [1] = {["y"]=-42549.187142857,["x"]=-449663.23257143,},
- [2] = {["y"]=-43367.466285714,["x"]=-451044.77657143,},
- [3] = {["y"]=-43395.180571429,["x"]=-451028.20514286,},
- [4] = {["y"]=-42579.893142857,["x"]=-449648.18371428,},
- },
- [2] = {
- [1] = {["y"]=-42588.359428572,["x"]=-449900.14342857,},
- [2] = {["y"]=-43349.698285714,["x"]=-451185.46857143,},
- [3] = {["y"]=-43369.624571429,["x"]=-451173.49342857,},
- [4] = {["y"]=-42609.216571429,["x"]=-449891.28628571,},
- },
- },
- },
- [AIRBASE.Nevada.Laughlin_Airport] = {
- PointsRunways = {
- [1] = {
- [1] = {["y"]=28231.600857143,["x"]=-515555.94114286,},
- [2] = {["y"]=28453.728285714,["x"]=-518170.78885714,},
- [3] = {["y"]=28370.788285714,["x"]=-518176.25742857,},
- [4] = {["y"]=28138.022857143,["x"]=-515573.07514286,},
- },
- [2] = {
- [1] = {["y"]=28231.600857143,["x"]=-515555.94114286,},
- [2] = {["y"]=28453.728285714,["x"]=-518170.78885714,},
- [3] = {["y"]=28370.788285714,["x"]=-518176.25742857,},
- [4] = {["y"]=28138.022857143,["x"]=-515573.07514286,},
- },
- },
- },
- [AIRBASE.Nevada.Lincoln_County] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=33222.34171429,["x"]=-223959.40171429,},
- [2]={["y"]=33200.040000004,["x"]=-225369.36828572,},
- [3]={["y"]=33177.634571428,["x"]=-225369.21485715,},
- [4]={["y"]=33201.198857147,["x"]=-223960.54457143,},
- },
- },
- },
- [AIRBASE.Nevada.McCarran_International_Airport] = {
- PointsRunways = {
- [1] = {
- [1] = {["y"]=-29406.035714286,["x"]=-416102.48199999,},
- [2] = {["y"]=-24680.714285715,["x"]=-416003.14285713,},
- [3] = {["y"]=-24681.857142858,["x"]=-415926.57142856,},
- [4] = {["y"]=-29408.42857143,["x"]=-416016.57142856,},
- },
- [2] = {
- [1] = {["y"]=-28567.221714286,["x"]=-416378.61799999,},
- [2] = {["y"]=-25109.912285714,["x"]=-416309.92914285,},
- [3] = {["y"]=-25112.508,["x"]=-416240.78714285,},
- [4] = {["y"]=-28576.247428571,["x"]=-416308.49514285,},
- },
- [3] = {
- [1] = {["y"]=-29255.953142857,["x"]=-416307.10657142,},
- [2] = {["y"]=-28005.571428572,["x"]=-413449.7142857,},
- [3] = {["y"]=-28068.714285715,["x"]=-413422.85714284,},
- [4] = {["y"]=-29331.000000001,["x"]=-416275.7142857,},
- },
- [4] = {
- [1] = {["y"]=-28994.901714286,["x"]=-416423.0522857,},
- [2] = {["y"]=-27697.571428572,["x"]=-413464.57142856,},
- [3] = {["y"]=-27767.857142858,["x"]=-413434.28571427,},
- [4] = {["y"]=-29073.000000001,["x"]=-416386.85714284,},
- },
- },
- },
- [AIRBASE.Nevada.Mesquite] = {
- PointsRunways = {
- [1] = {
- [1] = {["y"]=68188.340285714,["x"]=-330302.54742857,},
- [2] = {["y"]=68911.303428571,["x"]=-328920.76571429,},
- [3] = {["y"]=68936.927142857,["x"]=-328933.888,},
- [4] = {["y"]=68212.460285714,["x"]=-330317.19171429,},
- },
- },
- },
- [AIRBASE.Nevada.Mina_Airport] = {
- PointsRunways = {
- [1] = {
- [1] = {["y"]=-290054.57371429,["x"]=-160930.02228572,},
- [2] = {["y"]=-289469.77457143,["x"]=-162048.73571429,},
- [3] = {["y"]=-289520.06028572,["x"]=-162074.73571429,},
- [4] = {["y"]=-290104.69085714,["x"]=-160956.19457143,},
- },
- },
- },
- [AIRBASE.Nevada.Nellis_AFB] = {
- PointsRunways = {
- [1] = {
- [1] = {["y"]=-18614.218571428,["x"]=-399437.91085714,},
- [2] = {["y"]=-16217.857142857,["x"]=-396596.85714286,},
- [3] = {["y"]=-16300.142857143,["x"]=-396530,},
- [4] = {["y"]=-18692.543428571,["x"]=-399381.31114286,},
- },
- [2] = {
- [1] = {["y"]=-18388.948857143,["x"]=-399630.51828571,},
- [2] = {["y"]=-16011,["x"]=-396806.85714286,},
- [3] = {["y"]=-16074.714285714,["x"]=-396751.71428572,},
- [4] = {["y"]=-18451.571428572,["x"]=-399580.85714285,},
- },
- },
- },
- [AIRBASE.Nevada.Pahute_Mesa_Airstrip] = {
- PointsRunways = {
- [1] = {
- [1] = {["y"]=-132690.40942857,["x"]=-302733.53085714,},
- [2] = {["y"]=-133112.43228571,["x"]=-304499.70742857,},
- [3] = {["y"]=-133179.91685714,["x"]=-304485.544,},
- [4] = {["y"]=-132759.988,["x"]=-302723.326,},
- },
- },
- },
- [AIRBASE.Nevada.Tonopah_Test_Range_Airfield] = {
- PointsRunways = {
- [1] = {
- [1] = {["y"]=-175389.162,["x"]=-224778.07685715,},
- [2] = {["y"]=-173942.15485714,["x"]=-228210.27571429,},
- [3] = {["y"]=-174001.77085714,["x"]=-228233.60371429,},
- [4] = {["y"]=-175452.38685714,["x"]=-224806.84200001,},
- },
- },
- },
- [AIRBASE.Nevada.Tonopah_Airport] = {
- PointsRunways = {
- [1] = {
- [1] = {["y"]=-202128.25228571,["x"]=-196701.34314286,},
- [2] = {["y"]=-201562.40828571,["x"]=-198814.99714286,},
- [3] = {["y"]=-201591.44828571,["x"]=-198820.93714286,},
- [4] = {["y"]=-202156.06828571,["x"]=-196707.68714286,},
- },
- [2] = {
- [1] = {["y"]=-202084.57171428,["x"]=-196722.02228572,},
- [2] = {["y"]=-200592.75485714,["x"]=-197768.05571429,},
- [3] = {["y"]=-200605.37285714,["x"]=-197783.49228572,},
- [4] = {["y"]=-202097.14314285,["x"]=-196739.16514286,},
- },
- },
- },
- [AIRBASE.Nevada.North_Las_Vegas] = {
- PointsRunways = {
- [1] = {
- [1] = {["y"]=-32599.017714286,["x"]=-400913.26485714,},
- [2] = {["y"]=-30881.068857143,["x"]=-400837.94628571,},
- [3] = {["y"]=-30879.354571428,["x"]=-400873.08914285,},
- [4] = {["y"]=-32595.966285714,["x"]=-400947.13571428,},
- },
- [2] = {
- [1] = {["y"]=-32499.448571428,["x"]=-400690.99514285,},
- [2] = {["y"]=-31247.514857143,["x"]=-401868.95571428,},
- [3] = {["y"]=-31271.802857143,["x"]=-401894.97857142,},
- [4] = {["y"]=-32520.02,["x"]=-400716.99514285,},
- },
- [3] = {
- [1] = {["y"]=-31865.254857143,["x"]=-400999.74057143,},
- [2] = {["y"]=-30893.604,["x"]=-401908.85742857,},
- [3] = {["y"]=-30915.578857143,["x"]=-401936.03685714,},
- [4] = {["y"]=-31884.969142858,["x"]=-401020.59771429,},
- },
- },
- },
- },
}
--- Creates a new ATC_GROUND_NEVADA object.
@@ -1388,168 +1106,11 @@ ATC_GROUND_NEVADA = {
function ATC_GROUND_NEVADA:New( AirbaseNames )
-- Inherits from BASE
- local self = BASE:Inherit( self, ATC_GROUND:New( self.Airbases, AirbaseNames ) )
+ local self = BASE:Inherit( self, ATC_GROUND_UNIVERSAL:New( AirbaseNames ) )
self:SetKickSpeedKmph( 50 )
self:SetMaximumKickSpeedKmph( 150 )
- -- These lines here are for the demonstration mission.
- -- They create in the dcs.log the coordinates of the runway polygons, that are then
- -- taken by the moose designer from the dcs.log and reworked to define the
- -- Airbases structure, which is part of the class.
- -- When new airbases are added or airbases are changed on the map,
- -- the MOOSE designer willde-comment this section and apply the changes in the demo
- -- mission, and do a re-run to create a new dcs.log, and then add the changed coordinates
- -- in the Airbases structure.
- -- So, this needs to stay commented normally once a map has been finished.
-
- --[[
-
- -- Beatty
- do
- local VillagePrefix = "Beatty"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
- -- Boulder
- do
- local VillagePrefix = "Boulder"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- local Runway2 = GROUP:FindByName( VillagePrefix .. " 2" )
- local Zone2 = ZONE_POLYGON:New( VillagePrefix .. " 2", Runway2 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
- -- Creech
- do
- local VillagePrefix = "Creech"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- local Runway2 = GROUP:FindByName( VillagePrefix .. " 2" )
- local Zone2 = ZONE_POLYGON:New( VillagePrefix .. " 2", Runway2 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
- -- Echo
- do
- local VillagePrefix = "Echo"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
- -- Groom Lake
- do
- local VillagePrefix = "GroomLake"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- local Runway2 = GROUP:FindByName( VillagePrefix .. " 2" )
- local Zone2 = ZONE_POLYGON:New( VillagePrefix .. " 2", Runway2 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
- -- Henderson
- do
- local VillagePrefix = "Henderson"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- local Runway2 = GROUP:FindByName( VillagePrefix .. " 2" )
- local Zone2 = ZONE_POLYGON:New( VillagePrefix .. " 2", Runway2 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
- -- Jean
- do
- local VillagePrefix = "Jean"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- local Runway2 = GROUP:FindByName( VillagePrefix .. " 2" )
- local Zone2 = ZONE_POLYGON:New( VillagePrefix .. " 2", Runway2 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
- -- Laughlin
- do
- local VillagePrefix = "Laughlin"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
- -- Lincoln
- do
- local VillagePrefix = "Lincoln"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
- -- McCarran
- do
- local VillagePrefix = "McCarran"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- local Runway2 = GROUP:FindByName( VillagePrefix .. " 2" )
- local Zone2 = ZONE_POLYGON:New( VillagePrefix .. " 2", Runway2 ):SmokeZone(SMOKECOLOR.Red):Flush()
- local Runway3 = GROUP:FindByName( VillagePrefix .. " 3" )
- local Zone3 = ZONE_POLYGON:New( VillagePrefix .. " 3", Runway3 ):SmokeZone(SMOKECOLOR.Red):Flush()
- local Runway4 = GROUP:FindByName( VillagePrefix .. " 4" )
- local Zone4 = ZONE_POLYGON:New( VillagePrefix .. " 4", Runway4 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
- -- Mesquite
- do
- local VillagePrefix = "Mesquite"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
- -- Mina
- do
- local VillagePrefix = "Mina"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
- -- Nellis
- do
- local VillagePrefix = "Nellis"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- local Runway2 = GROUP:FindByName( VillagePrefix .. " 2" )
- local Zone2 = ZONE_POLYGON:New( VillagePrefix .. " 2", Runway2 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
- -- Pahute
- do
- local VillagePrefix = "Pahute"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
- -- TonopahTR
- do
- local VillagePrefix = "TonopahTR"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
- -- Tonopah
- do
- local VillagePrefix = "Tonopah"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- local Runway2 = GROUP:FindByName( VillagePrefix .. " 2" )
- local Zone2 = ZONE_POLYGON:New( VillagePrefix .. " 2", Runway2 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
- -- Vegas
- do
- local VillagePrefix = "Vegas"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- local Runway2 = GROUP:FindByName( VillagePrefix .. " 2" )
- local Zone2 = ZONE_POLYGON:New( VillagePrefix .. " 2", Runway2 ):SmokeZone(SMOKECOLOR.Red):Flush()
- local Runway3 = GROUP:FindByName( VillagePrefix .. " 3" )
- local Zone3 = ZONE_POLYGON:New( VillagePrefix .. " 3", Runway3 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
- --]]
-
return self
end
@@ -1690,440 +1251,7 @@ end
--
-- @field #ATC_GROUND_NORMANDY
ATC_GROUND_NORMANDY = {
- ClassName = "ATC_GROUND_NORMANDY",
- Airbases = {
- [AIRBASE.Normandy.Azeville] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=-74194.387714285,["x"]=-2691.1399999998,},
- [2]={["y"]=-73160.282571428,["x"]=-2310.0274285712,},
- [3]={["y"]=-73141.711142857,["x"]=-2357.7417142855,},
- [4]={["y"]=-74176.959142857,["x"]=-2741.997142857,},
- },
- },
- },
- [AIRBASE.Normandy.Bazenville] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=-19246.209999999,["x"]=-21246.748,},
- [2]={["y"]=-17883.70142857,["x"]=-20219.009714285,},
- [3]={["y"]=-17855.415714285,["x"]=-20256.438285714,},
- [4]={["y"]=-19217.791999999,["x"]=-21283.597714285,},
- },
- },
- },
- [AIRBASE.Normandy.Beny_sur_Mer] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=-8592.7442857133,["x"]=-20386.15542857,},
- [2]={["y"]=-8404.4931428561,["x"]=-21744.113142856,},
- [3]={["y"]=-8267.9917142847,["x"]=-21724.97742857,},
- [4]={["y"]=-8451.0482857133,["x"]=-20368.87542857,},
- },
- },
- },
- [AIRBASE.Normandy.Beuzeville] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=-71552.573428571,["x"]=-8744.3688571427,},
- [2]={["y"]=-72577.765714285,["x"]=-9638.5682857141,},
- [3]={["y"]=-72609.304285714,["x"]=-9601.2954285712,},
- [4]={["y"]=-71585.849428571,["x"]=-8709.9648571426,},
- },
- },
- },
- [AIRBASE.Normandy.Biniville] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=-84757.320285714,["x"]=-7377.1354285713,},
- [2]={["y"]=-84271.482,["x"]=-7956.4859999999,},
- [3]={["y"]=-84299.482,["x"]=-7981.6288571427,},
- [4]={["y"]=-84784.969714286,["x"]=-7402.0588571427,},
- },
- },
- },
- [AIRBASE.Normandy.Brucheville] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=-65546.792857142,["x"]=-14615.640857143,},
- [2]={["y"]=-66914.692,["x"]=-15232.713714285,},
- [3]={["y"]=-66896.527714285,["x"]=-15271.948571428,},
- [4]={["y"]=-65528.393714285,["x"]=-14657.995714286,},
- },
- },
- },
- [AIRBASE.Normandy.Cardonville] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=-54280.445428571,["x"]=-15843.749142857,},
- [2]={["y"]=-53646.998571428,["x"]=-17143.012285714,},
- [3]={["y"]=-53683.93,["x"]=-17161.317428571,},
- [4]={["y"]=-54323.354571428,["x"]=-15855.004,},
- },
- },
- },
- [AIRBASE.Normandy.Carpiquet] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=-10751.325714285,["x"]=-34229.494,},
- [2]={["y"]=-9283.5279999993,["x"]=-35192.352857142,},
- [3]={["y"]=-9325.2005714274,["x"]=-35260.967714285,},
- [4]={["y"]=-10794.90942857,["x"]=-34287.041428571,},
- },
- },
- },
- [AIRBASE.Normandy.Chailey] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=12895.585714292,["x"]=164683.05657144,},
- [2]={["y"]=11410.727142863,["x"]=163606.54485715,},
- [3]={["y"]=11363.012857149,["x"]=163671.97342858,},
- [4]={["y"]=12797.537142863,["x"]=164711.01857144,},
- [5]={["y"]=12862.902857149,["x"]=164726.99685715,},
- },
- [2] = {
- [1]={["y"]=11805.316000006,["x"]=164502.90971429,},
- [2]={["y"]=11997.280857149,["x"]=163032.65542858,},
- [3]={["y"]=11918.640857149,["x"]=163023.04657144,},
- [4]={["y"]=11726.973428578,["x"]=164489.94257143,},
- },
- },
- },
- [AIRBASE.Normandy.Chippelle] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=-48540.313999999,["x"]=-28884.795999999,},
- [2]={["y"]=-47251.820285713,["x"]=-28140.128571427,},
- [3]={["y"]=-47274.551714285,["x"]=-28103.758285713,},
- [4]={["y"]=-48555.657714285,["x"]=-28839.90142857,},
- },
- },
- },
- [AIRBASE.Normandy.Cretteville] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=-78351.723142857,["x"]=-18177.725428571,},
- [2]={["y"]=-77220.322285714,["x"]=-19125.687714286,},
- [3]={["y"]=-77247.899428571,["x"]=-19158.49,},
- [4]={["y"]=-78380.008857143,["x"]=-18208.011142857,},
- },
- },
- },
- [AIRBASE.Normandy.Cricqueville_en_Bessin] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=-50875.034571428,["x"]=-14322.404571428,},
- [2]={["y"]=-50681.148571428,["x"]=-15825.258,},
- [3]={["y"]=-50717.434285713,["x"]=-15829.829428571,},
- [4]={["y"]=-50910.569428571,["x"]=-14327.562857142,},
- },
- },
- },
- [AIRBASE.Normandy.Deux_Jumeaux] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=-49575.410857142,["x"]=-16575.161142857,},
- [2]={["y"]=-48149.077999999,["x"]=-16952.193428571,},
- [3]={["y"]=-48159.935142856,["x"]=-16996.764857142,},
- [4]={["y"]=-49584.839428571,["x"]=-16617.732571428,},
- },
- },
- },
- [AIRBASE.Normandy.Evreux] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=112906.84828572,["x"]=-45585.824857142,},
- [2]={["y"]=112050.38228572,["x"]=-46811.871999999,},
- [3]={["y"]=111980.05371429,["x"]=-46762.173142856,},
- [4]={["y"]=112833.54542857,["x"]=-45540.010571428,},
- },
- [2] = {
- [1]={["y"]=112046.02085714,["x"]=-45091.056571428,},
- [2]={["y"]=112488.668,["x"]=-46623.617999999,},
- [3]={["y"]=112405.66914286,["x"]=-46647.419142856,},
- [4]={["y"]=111966.03657143,["x"]=-45112.604285713,},
- },
- },
- },
- [AIRBASE.Normandy.Ford_AF] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=-26506.13971428,["x"]=147514.39971429,},
- [2]={["y"]=-25012.977428565,["x"]=147566.14485715,},
- [3]={["y"]=-25009.851428565,["x"]=147482.63600001,},
- [4]={["y"]=-26503.693999994,["x"]=147427.33228572,},
- },
- [2] = {
- [1]={["y"]=-25169.701999994,["x"]=148421.09257143,},
- [2]={["y"]=-26092.421999994,["x"]=147190.89628572,},
- [3]={["y"]=-26158.136285708,["x"]=147240.89628572,},
- [4]={["y"]=-25252.357999994,["x"]=148448.64457143,},
- },
- },
- },
- [AIRBASE.Normandy.Funtington] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=-44698.388571423,["x"]=152952.17257143,},
- [2]={["y"]=-46452.993142851,["x"]=152388.77885714,},
- [3]={["y"]=-46476.361142851,["x"]=152470.05885714,},
- [4]={["y"]=-44787.256571423,["x"]=153009.52,},
- [5]={["y"]=-44715.581428566,["x"]=153002.08714286,},
- },
- [2] = {
- [1]={["y"]=-45792.665999994,["x"]=153123.894,},
- [2]={["y"]=-46068.084857137,["x"]=151665.98342857,},
- [3]={["y"]=-46148.632285708,["x"]=151681.58685714,},
- [4]={["y"]=-45871.25971428,["x"]=153136.82714286,},
- },
- },
- },
- [AIRBASE.Normandy.Lantheuil] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=-17158.84542857,["x"]=-24602.999428571,},
- [2]={["y"]=-15978.59342857,["x"]=-23922.978571428,},
- [3]={["y"]=-15932.021999999,["x"]=-24004.121428571,},
- [4]={["y"]=-17090.734857142,["x"]=-24673.248,},
- },
- },
- },
- [AIRBASE.Normandy.Lessay] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=-87667.304571429,["x"]=-33220.165714286,},
- [2]={["y"]=-86146.607714286,["x"]=-34248.483142857,},
- [3]={["y"]=-86191.538285714,["x"]=-34316.991142857,},
- [4]={["y"]=-87712.212,["x"]=-33291.774857143,},
- },
- [2] = {
- [1]={["y"]=-87125.123142857,["x"]=-34183.682571429,},
- [2]={["y"]=-85803.278285715,["x"]=-33498.428857143,},
- [3]={["y"]=-85768.408285715,["x"]=-33570.13,},
- [4]={["y"]=-87087.688571429,["x"]=-34258.272285715,},
- },
- },
- },
- [AIRBASE.Normandy.Lignerolles] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=-35279.611714285,["x"]=-35232.026857142,},
- [2]={["y"]=-33804.948857142,["x"]=-35770.713999999,},
- [3]={["y"]=-33789.876285713,["x"]=-35726.655714284,},
- [4]={["y"]=-35263.548285713,["x"]=-35192.75542857,},
- },
- },
- },
- [AIRBASE.Normandy.Longues_sur_Mer] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=-29444.070285713,["x"]=-16334.105428571,},
- [2]={["y"]=-28265.52942857,["x"]=-17011.557999999,},
- [3]={["y"]=-28344.74742857,["x"]=-17143.587999999,},
- [4]={["y"]=-29529.616285713,["x"]=-16477.766571428,},
- },
- },
- },
- [AIRBASE.Normandy.Maupertus] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=-85605.340857143,["x"]=16175.267714286,},
- [2]={["y"]=-84132.567142857,["x"]=15895.905714286,},
- [3]={["y"]=-84139.995142857,["x"]=15847.623714286,},
- [4]={["y"]=-85613.626571429,["x"]=16132.410571429,},
- },
- },
- },
- [AIRBASE.Normandy.Meautis] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=-72642.527714286,["x"]=-24593.622285714,},
- [2]={["y"]=-71298.672571429,["x"]=-24352.651142857,},
- [3]={["y"]=-71290.101142857,["x"]=-24398.365428571,},
- [4]={["y"]=-72631.715714286,["x"]=-24639.966857143,},
- },
- },
- },
- [AIRBASE.Normandy.Le_Molay] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=-41876.526857142,["x"]=-26701.052285713,},
- [2]={["y"]=-40979.545714285,["x"]=-25675.045999999,},
- [3]={["y"]=-41017.687428571,["x"]=-25644.272571427,},
- [4]={["y"]=-41913.638285713,["x"]=-26665.137999999,},
- },
- },
- },
- [AIRBASE.Normandy.Needs_Oar_Point] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=-83882.441142851,["x"]=141429.83314286,},
- [2]={["y"]=-85138.159428566,["x"]=140187.52828572,},
- [3]={["y"]=-85208.323428566,["x"]=140161.04371429,},
- [4]={["y"]=-85245.751999994,["x"]=140201.61514286,},
- [5]={["y"]=-83939.966571423,["x"]=141485.22085714,},
- },
- [2] = {
- [1]={["y"]=-84528.76571428,["x"]=141988.01428572,},
- [2]={["y"]=-84116.98971428,["x"]=140565.78685714,},
- [3]={["y"]=-84199.35771428,["x"]=140541.14685714,},
- [4]={["y"]=-84605.051428566,["x"]=141966.01428572,},
- },
- },
- },
- [AIRBASE.Normandy.Picauville] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=-80808.838571429,["x"]=-11834.554571428,},
- [2]={["y"]=-79531.574285714,["x"]=-12311.274,},
- [3]={["y"]=-79549.355428571,["x"]=-12356.928285714,},
- [4]={["y"]=-80827.815142857,["x"]=-11901.835142857,},
- },
- },
- },
- [AIRBASE.Normandy.Rucqueville] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=-20023.988857141,["x"]=-26569.565428571,},
- [2]={["y"]=-18688.92542857,["x"]=-26571.086571428,},
- [3]={["y"]=-18688.012571427,["x"]=-26611.252285713,},
- [4]={["y"]=-20022.218857141,["x"]=-26608.505428571,},
- },
- },
- },
- [AIRBASE.Normandy.Saint_Pierre_du_Mont] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=-48015.384571428,["x"]=-11886.631714285,},
- [2]={["y"]=-46540.412285713,["x"]=-11945.226571428,},
- [3]={["y"]=-46541.349999999,["x"]=-11991.174571428,},
- [4]={["y"]=-48016.837142856,["x"]=-11929.371142857,},
- },
- },
- },
- [AIRBASE.Normandy.Sainte_Croix_sur_Mer] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=-15877.817999999,["x"]=-18812.579999999,},
- [2]={["y"]=-14464.377142856,["x"]=-18807.46,},
- [3]={["y"]=-14463.879714285,["x"]=-18759.706857142,},
- [4]={["y"]=-15878.229142856,["x"]=-18764.071428571,},
- },
- },
- },
- [AIRBASE.Normandy.Sainte_Laurent_sur_Mer] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=-41676.834857142,["x"]=-14475.109428571,},
- [2]={["y"]=-40566.11142857,["x"]=-14817.319999999,},
- [3]={["y"]=-40579.543999999,["x"]=-14860.059999999,},
- [4]={["y"]=-41687.120571427,["x"]=-14509.680857142,},
- },
- },
- },
- [AIRBASE.Normandy.Sommervieu] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=-26821.913714284,["x"]=-21390.466571427,},
- [2]={["y"]=-25465.308857142,["x"]=-21296.859999999,},
- [3]={["y"]=-25462.451714284,["x"]=-21343.717142856,},
- [4]={["y"]=-26818.002285713,["x"]=-21440.532857142,},
- },
- },
- },
- [AIRBASE.Normandy.Tangmere] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=-34684.581142851,["x"]=150459.61657143,},
- [2]={["y"]=-33250.625428566,["x"]=149954.17,},
- [3]={["y"]=-33275.724285708,["x"]=149874.69028572,},
- [4]={["y"]=-34709.020571423,["x"]=150377.93742857,},
- },
- [2] = {
- [1]={["y"]=-33103.438857137,["x"]=150812.72542857,},
- [2]={["y"]=-34410.246285708,["x"]=150009.73142857,},
- [3]={["y"]=-34453.535142851,["x"]=150082.02685714,},
- [4]={["y"]=-33176.545999994,["x"]=150870.22542857,},
- },
- },
- },
- [AIRBASE.Normandy.Argentan] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=22322.280338032,["x"]=-78607.309765269,},
- [2]={["y"]=23032.778713963,["x"]=-78967.17709893,},
- [3]={["y"]=23015.27074041,["x"]=-79008.02903722,},
- [4]={["y"]=22299.944963827,["x"]=-78650.366148928,},
- },
- },
- },
- [AIRBASE.Normandy.Goulet] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=24901.788373185,["x"]=-89139.367511763,},
- [2]={["y"]=25459.965967043,["x"]=-89709.67940114,},
- [3]={["y"]=25422.459962713,["x"]=-89741.669816598,},
- [4]={["y"]=24857.663662208,["x"]=-89173.56416277,},
- },
- },
- },
- [AIRBASE.Normandy.Essay] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=44610.072022849,["x"]=-105469.21149064,},
- [2]={["y"]=45417.939023956,["x"]=-105536.08535277,},
- [3]={["y"]=45412.558368383,["x"]=-105585.27991801,},
- [4]={["y"]=44602.38537203,["x"]=-105516.10006064,},
- },
- },
- },
- [AIRBASE.Normandy.Hauterive] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=40617.185360953,["x"]=-107657.10147517,},
- [2]={["y"]=41114.628372034,["x"]=-108298.77015609,},
- [3]={["y"]=41080.006684855,["x"]=-108319.06562788,},
- [4]={["y"]=40584.558402807,["x"]=-107692.29370481,},
- },
- },
- },
- [AIRBASE.Normandy.Vrigny] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=24892.131051827,["x"]=-89131.628297486,},
- [2]={["y"]=25469.738000575,["x"]=-89709.235246234,},
- [3]={["y"]=25418.869206793,["x"]=-89738.771965204,},
- [4]={["y"]=24859.312475193,["x"]=-89171.010589446,},
- },
- },
- },
- [AIRBASE.Normandy.Barville] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=49027.850333166,["x"]=-109217.05049066,},
- [2]={["y"]=49755.022185805,["x"]=-110346.63783457,},
- [3]={["y"]=49682.657996586,["x"]=-110401.35222154,},
- [4]={["y"]=48921.951519675,["x"]=-109285.88471943,},
- },
- [2] = {
- [1]={["y"]=48429.522036941,["x"]=-109818.90874734,},
- [2]={["y"]=49746.197284681,["x"]=-109954.81222465,},
- [3]={["y"]=49735.607403332,["x"]=-110032.47135455,},
- [4]={["y"]=48420.697135816,["x"]=-109900.09783768,},
- },
- },
- },
- [AIRBASE.Normandy.Conches] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=95099.187473266,["x"]=-56389.619005858,},
- [2]={["y"]=95181.545025963,["x"]=-56465.440244849,},
- [3]={["y"]=94071.678958666,["x"]=-57627.596821795,},
- [4]={["y"]=94005.008558864,["x"]=-57558.31189651,},
- },
- },
- },
- },
+ ClassName = "ATC_GROUND_NORMANDY",
}
@@ -2134,285 +1262,10 @@ ATC_GROUND_NORMANDY = {
function ATC_GROUND_NORMANDY:New( AirbaseNames )
-- Inherits from BASE
- local self = BASE:Inherit( self, ATC_GROUND:New( self.Airbases, AirbaseNames ) ) -- #ATC_GROUND_NORMANDY
+ local self = BASE:Inherit( self, ATC_GROUND_UNIVERSAL:New( AirbaseNames ) ) -- #ATC_GROUND_NORMANDY
self:SetKickSpeedKmph( 40 )
self:SetMaximumKickSpeedKmph( 100 )
-
- -- These lines here are for the demonstration mission.
- -- They create in the dcs.log the coordinates of the runway polygons, that are then
- -- taken by the moose designer from the dcs.log and reworked to define the
- -- Airbases structure, which is part of the class.
- -- When new airbases are added or airbases are changed on the map,
- -- the MOOSE designer willde-comment this section and apply the changes in the demo
- -- mission, and do a re-run to create a new dcs.log, and then add the changed coordinates
- -- in the Airbases structure.
- -- So, this needs to stay commented normally once a map has been finished.
-
- --[[
-
- -- Azeville
- do
- local VillagePrefix = "Azeville"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Bazenville
- do
- local VillagePrefix = "Bazenville"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Beny
- do
- local VillagePrefix = "Beny"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Beuzeville
- do
- local VillagePrefix = "Beuzeville"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Biniville
- do
- local VillagePrefix = "Biniville"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Brucheville
- do
- local VillagePrefix = "Brucheville"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Cardonville
- do
- local VillagePrefix = "Cardonville"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Carpiquet
- do
- local VillagePrefix = "Carpiquet"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Chailey
- do
- local VillagePrefix = "Chailey"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- local Runway2 = GROUP:FindByName( VillagePrefix .. " 2" )
- local Zone2 = ZONE_POLYGON:New( VillagePrefix .. " 2", Runway2 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Chippelle
- do
- local VillagePrefix = "Chippelle"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Cretteville
- do
- local VillagePrefix = "Cretteville"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Cricqueville
- do
- local VillagePrefix = "Cricqueville"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Deux
- do
- local VillagePrefix = "Deux"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Evreux
- do
- local VillagePrefix = "Evreux"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- local Runway2 = GROUP:FindByName( VillagePrefix .. " 2" )
- local Zone2 = ZONE_POLYGON:New( VillagePrefix .. " 2", Runway2 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Ford
- do
- local VillagePrefix = "Ford"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- local Runway2 = GROUP:FindByName( VillagePrefix .. " 2" )
- local Zone2 = ZONE_POLYGON:New( VillagePrefix .. " 2", Runway2 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Funtington
- do
- local VillagePrefix = "Funtington"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- local Runway2 = GROUP:FindByName( VillagePrefix .. " 2" )
- local Zone2 = ZONE_POLYGON:New( VillagePrefix .. " 2", Runway2 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Lantheuil
- do
- local VillagePrefix = "Lantheuil"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Lessay
- do
- local VillagePrefix = "Lessay"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- local Runway2 = GROUP:FindByName( VillagePrefix .. " 2" )
- local Zone2 = ZONE_POLYGON:New( VillagePrefix .. " 2", Runway2 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Lignerolles
- do
- local VillagePrefix = "Lignerolles"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Longues
- do
- local VillagePrefix = "Longues"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Maupertus
- do
- local VillagePrefix = "Maupertus"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Meautis
- do
- local VillagePrefix = "Meautis"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Molay
- do
- local VillagePrefix = "Molay"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Oar
- do
- local VillagePrefix = "Oar"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- local Runway2 = GROUP:FindByName( VillagePrefix .. " 2" )
- local Zone2 = ZONE_POLYGON:New( VillagePrefix .. " 2", Runway2 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Picauville
- do
- local VillagePrefix = "Picauville"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Rucqueville
- do
- local VillagePrefix = "Rucqueville"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- SaintPierre
- do
- local VillagePrefix = "SaintPierre"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- SainteCroix
- do
- local VillagePrefix = "SainteCroix"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- --SainteLaurent
- do
- local VillagePrefix = "SainteLaurent"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Sommervieu
- do
- local VillagePrefix = "Sommervieu"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Tangmere
- do
- local VillagePrefix = "Tangmere"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- local Runway2 = GROUP:FindByName( VillagePrefix .. " 2" )
- local Zone2 = ZONE_POLYGON:New( VillagePrefix .. " 2", Runway2 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
- --]]
return self
end
@@ -2544,452 +1397,8 @@ end
-- @field #ATC_GROUND_PERSIANGULF
ATC_GROUND_PERSIANGULF = {
ClassName = "ATC_GROUND_PERSIANGULF",
- Airbases = {
- [AIRBASE.PersianGulf.Abu_Musa_Island_Airport] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=-122813.71002344,["x"]=-31689.936027827,},
- [2]={["y"]=-122827.82488722,["x"]=-31590.105445836,},
- [3]={["y"]=-122769.5689949,["x"]=-31583.176330891,},
- [4]={["y"]=-122726.96776968,["x"]=-31614.998932862,},
- [5]={["y"]=-121293.92414543,["x"]=-31467.947715689,},
- [6]={["y"]=-121296.4904843,["x"]=-31432.018971528,},
- [7]={["y"]=-121236.18152088,["x"]=-31424.576588809,},
- [8]={["y"]=-121190.50068902,["x"]=-31458.452261875,},
- [9]={["y"]=-119839.83654246,["x"]=-31319.356695194,},
- [10]={["y"]=-119824.69514313,["x"]=-31423.293419374,},
- [11]={["y"]=-119886.80054375,["x"]=-31430.22253432,},
- [12]={["y"]=-119932.22474173,["x"]=-31395.320325706,},
- [13]={["y"]=-122813.9472789,["x"]=-31689.81193251,},
- },
- },
- },
- [AIRBASE.PersianGulf.Al_Dhafra_AB] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=-174672.06004916,["x"]=-209880.97145616,},
- [2]={["y"]=-174705.15693282,["x"]=-209923.15131918,},
- [3]={["y"]=-171819.05380065,["x"]=-212172.84298281,},
- [4]={["y"]=-171785.09826475,["x"]=-212129.87417284,},
- [5]={["y"]=-174671.96413454,["x"]=-209880.52453983,},
- },
- [2] = {
- [1]={["y"]=-174351.95872272,["x"]=-211813.88516693,},
- [2]={["y"]=-174381.29169939,["x"]=-211851.81242636,},
- [3]={["y"]=-171493.65648904,["x"]=-214102.92235002,},
- [4]={["y"]=-171464.99693831,["x"]=-214062.78788361,},
- [5]={["y"]=-174351.8628081,["x"]=-211813.4382506,},
- },
- },
- },
- [AIRBASE.PersianGulf.Al_Maktoum_Intl] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=-111879.49046471,["x"]=-138953.80105841,},
- [2]={["y"]=-111917.23447224,["x"]=-139018.2804046,},
- [3]={["y"]=-108092.98121312,["x"]=-141406.67838426,},
- [4]={["y"]=-108052.34416748,["x"]=-141341.82058294,},
- [5]={["y"]=-111879.5412879,["x"]=-138952.87693763,},
- },
- },
- },
- [AIRBASE.PersianGulf.Al_Minhad_AB] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=-91070.628933035,["x"]=-125989.64095162,},
- [2]={["y"]=-91072.346560159,["x"]=-126040.59722299,},
- [3]={["y"]=-87098.282779771,["x"]=-126039.41747017,},
- [4]={["y"]=-87099.632735396,["x"]=-125991.26905291,},
- [5]={["y"]=-91071.031270042,["x"]=-125987.44617225,},
- },
- },
- },
- [AIRBASE.PersianGulf.Bandar_Abbas_Intl] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=12988.484058788,["x"]=113979.99250505,},
- [2]={["y"]=13037.8836239,["x"]=113952.60241152,},
- [3]={["y"]=14877.313199902,["x"]=117414.37833333,},
- [4]={["y"]=14828.777486364,["x"]=117439.06043783,},
- [5]={["y"]=12988.939584604,["x"]=113979.52494386,},
- },
- [2] = {
- [1]={["y"]=13203.406014284,["x"]=113848.44907555,},
- [2]={["y"]=13258.268500181,["x"]=113818.47303925,},
- [3]={["y"]=15315.015323566,["x"]=117694.27156647,},
- [4]={["y"]=15264.815746383,["x"]=117725.22168173,},
- [5]={["y"]=13203.861540099,["x"]=113847.98151436,},
- },
- },
- },
- [AIRBASE.PersianGulf.Bandar_Lengeh] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=-142373.15541415,["x"]=41364.94047809,},
- [2]={["y"]=-142363.30071107,["x"]=41298.112282592,},
- [3]={["y"]=-142217.57151662,["x"]=41320.35666061,},
- [4]={["y"]=-142213.00856728,["x"]=41291.838227254,},
- [5]={["y"]=-142131.44584788,["x"]=41301.534494595,},
- [6]={["y"]=-142132.58658522,["x"]=41323.778872613,},
- [7]={["y"]=-142123.17550221,["x"]=41336.041798956,},
- [8]={["y"]=-139580.45381288,["x"]=41711.022304533,},
- [9]={["y"]=-139590.04241918,["x"]=41778.350996659,},
- [10]={["y"]=-139732.41237808,["x"]=41757.089304408,},
- [11]={["y"]=-139736.7897853,["x"]=41785.646675372,},
- [12]={["y"]=-139816.41690726,["x"]=41775.641173137,},
- [13]={["y"]=-139816.00001133,["x"]=41754.58792885,},
- [14]={["y"]=-139824.1294819,["x"]=41743.748634761,},
- [15]={["y"]=-142373.20183966,["x"]=41365.161507021,},
- },
- },
- },
- [AIRBASE.PersianGulf.Dubai_Intl] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=-89693.511670714,["x"]=-100490.47082052,},
- [2]={["y"]=-89731.488328846,["x"]=-100555.50584758,},
- [3]={["y"]=-85706.437275049,["x"]=-103076.68123933,},
- [4]={["y"]=-85669.519216262,["x"]=-103010.44994755,},
- [5]={["y"]=-89693.036962487,["x"]=-100489.9961123,},
- },
- [2] = {
- [1]={["y"]=-90797.505501889,["x"]=-99344.082465487,},
- [2]={["y"]=-90835.482160021,["x"]=-99409.11749254,},
- [3]={["y"]=-87210.216900398,["x"]=-101681.72494832,},
- [4]={["y"]=-87171.474397253,["x"]=-101619.20256393,},
- [5]={["y"]=-90797.030793662,["x"]=-99343.607757261,},
- },
- },
- },
- [AIRBASE.PersianGulf.Fujairah_Intl] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=5808.8716147284,["x"]=-116602.15633995,},
- [2]={["y"]=5781.9885293892,["x"]=-116666.67574476,},
- [3]={["y"]=9435.1910907931,["x"]=-118192.91910235,},
- [4]={["y"]=9459.878635843,["x"]=-118134.40047704,},
- [5]={["y"]=5808.4078522575,["x"]=-116603.31550719,},
- },
- },
- },
- [AIRBASE.PersianGulf.Havadarya] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=-7565.4887830428,["x"]=109074.13162774,},
- [2]={["y"]=-7557.8281079193,["x"]=109030.65729641,},
- [3]={["y"]=-4987.3556518085,["x"]=109524.49147773,},
- [4]={["y"]=-4996.215358578,["x"]=109566.57508489,},
- [5]={["y"]=-7565.4936338604,["x"]=109074.32262205,},
- },
- },
- },
- [AIRBASE.PersianGulf.Kerman_Airport] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=70375.468628778,["x"]=456046.12685302,},
- [2]={["y"]=70297.050081575,["x"]=456015.1578105,},
- [3]={["y"]=71814.291673715,["x"]=452165.51037702,},
- [4]={["y"]=71902.918622452,["x"]=452188.46411914,},
- [5]={["y"]=70860.465673482,["x"]=454829.89695989,},
- [6]={["y"]=70862.525255971,["x"]=454892.77675983,},
- [7]={["y"]=70816.157465062,["x"]=454922.77944807,},
- [8]={["y"]=70462.749176371,["x"]=455833.38051827,},
- [9]={["y"]=70483.400377364,["x"]=455901.17880077,},
- [10]={["y"]=70453.787334431,["x"]=455974.8217628,},
- [11]={["y"]=70405.860962315,["x"]=455961.57382254,},
- [12]={["y"]=70374.689338175,["x"]=456046.51649833,},
- },
- },
- },
- [AIRBASE.PersianGulf.Khasab] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=-534.81827307392,["x"]=-1495.070060483,},
- [2]={["y"]=-434.82912685139,["x"]=-1519.8421462589,},
- [3]={["y"]=-405.55302547993,["x"]=-1413.0969766429,},
- [4]={["y"]=-424.92029254105,["x"]=-1352.0675653224,},
- [5]={["y"]=216.05735069389,["x"]=1206.9187095195,},
- [6]={["y"]=116.42961315781,["x"]=1229.9576238247,},
- [7]={["y"]=88.253643635887,["x"]=1123.7918160128,},
- [8]={["y"]=101.1741158476,["x"]=1042.6886109249,},
- [9]={["y"]=-535.31436058928,["x"]=-1494.8762081291,},
- },
- },
- },
- [AIRBASE.PersianGulf.Lar_Airbase] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=-183987.5454359,["x"]=169021.72039309,},
- [2]={["y"]=-183988.41292374,["x"]=168955.27082471,},
- [3]={["y"]=-180847.92031188,["x"]=168930.46175795,},
- [4]={["y"]=-180806.58653731,["x"]=168888.39641215,},
- [5]={["y"]=-180740.37934087,["x"]=168886.56748407,},
- [6]={["y"]=-180735.62412787,["x"]=168932.65647164,},
- [7]={["y"]=-180685.14571291,["x"]=168934.11961411,},
- [8]={["y"]=-180682.5852136,["x"]=169001.78995301,},
- [9]={["y"]=-183987.48111493,["x"]=169021.35002828,},
- },
- },
- },
- [AIRBASE.PersianGulf.Qeshm_Island] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=-35140.372717152,["x"]=63373.658918509,},
- [2]={["y"]=-35098.556715749,["x"]=63320.377239302,},
- [3]={["y"]=-34991.318905699,["x"]=63408.730403557,},
- [4]={["y"]=-34984.574389344,["x"]=63401.311435566,},
- [5]={["y"]=-34991.993357335,["x"]=63313.632722947,},
- [6]={["y"]=-34956.921872287,["x"]=63265.746656824,},
- [7]={["y"]=-34917.129225791,["x"]=63261.699947011,},
- [8]={["y"]=-34832.822771349,["x"]=63337.23853019,},
- [9]={["y"]=-34915.105870884,["x"]=63436.382920614,},
- [10]={["y"]=-34906.337999622,["x"]=63478.198922017,},
- [11]={["y"]=-32728.533668488,["x"]=65307.986209216,},
- [12]={["y"]=-32676.600892552,["x"]=65299.218337954,},
- [13]={["y"]=-32623.99366498,["x"]=65334.964274638,},
- [14]={["y"]=-32626.691471522,["x"]=65388.92040548,},
- [15]={["y"]=-31822.745121968,["x"]=66067.418750826,},
- [16]={["y"]=-31777.556862387,["x"]=66068.767654097,},
- [17]={["y"]=-31691.227053039,["x"]=65974.344425122,},
- [18]={["y"]=-31606.246146962,["x"]=66042.464040311,},
- [19]={["y"]=-31602.199437148,["x"]=66084.280041714,},
- [20]={["y"]=-31632.549760747,["x"]=66124.747139846,},
- [21]={["y"]=-31727.647441358,["x"]=66134.189462744,},
- [22]={["y"]=-31734.391957713,["x"]=66141.608430735,},
- [23]={["y"]=-31632.549760747,["x"]=66225.914885176,},
- [24]={["y"]=-31673.691310515,["x"]=66277.173209477,},
- [25]={["y"]=-35140.880825624,["x"]=63373.905965825,},
- },
- },
- },
- [AIRBASE.PersianGulf.Sharjah_Intl] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=-71668.808658476,["x"]=-93980.156242153,},
- [2]={["y"]=-75307.847363315,["x"]=-91617.097584505,},
- [3]={["y"]=-75280.458023829,["x"]=-91574.709321014,},
- [4]={["y"]=-72249.697184234,["x"]=-93529.134331507,},
- [5]={["y"]=-72179.919581256,["x"]=-93526.199759419,},
- [6]={["y"]=-72138.183444896,["x"]=-93597.933743788,},
- [7]={["y"]=-71638.654062835,["x"]=-93927.584008321,},
- [8]={["y"]=-71668.325847279,["x"]=-93979.428115206,},
- },
- [2] = {
- [1]={["y"]=-71553.225408723,["x"]=-93775.312323319,},
- [2]={["y"]=-75168.13829548,["x"]=-91426.51571111,},
- [3]={["y"]=-75125.388157445,["x"]=-91363.754870166,},
- [4]={["y"]=-71510.511081666,["x"]=-93703.252275385,},
- [5]={["y"]=-71552.247218027,["x"]=-93775.638386885,},
- },
- },
- },
- [AIRBASE.PersianGulf.Shiraz_International_Airport] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=-353995.75579778,["x"]=382327.42294273,},
- [2]={["y"]=-354029.77009807,["x"]=382265.46199492,},
- [3]={["y"]=-349407.98049238,["x"]=379941.14030526,},
- [4]={["y"]=-349376.87025024,["x"]=380004.69408564,},
- [5]={["y"]=-353995.71101815,["x"]=382327.59771695,},
- },
- [2] = {
- [1]={["y"]=-354056.29510012,["x"]=381845.97598829,},
- [2]={["y"]=-354091.48797289,["x"]=381783.6025623,},
- [3]={["y"]=-349650.64038107,["x"]=379550.92898242,},
- [4]={["y"]=-349624.41889127,["x"]=379614.92719482,},
- [5]={["y"]=-354056.25032049,["x"]=381846.15076251,},
- },
- },
- },
- [AIRBASE.PersianGulf.Sir_Abu_Nuayr] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=-203367.3128691,["x"]=-103017.22553918,},
- [2]={["y"]=-203373.59664477,["x"]=-103054.92819323,},
- [3]={["y"]=-202578.27577922,["x"]=-103188.26018333,},
- [4]={["y"]=-202571.37254488,["x"]=-103151.01482599,},
- [5]={["y"]=-203367.65259839,["x"]=-103016.48202662,},
- [6]={["y"]=-203291.39594004,["x"]=-102985.49774228,},
- },
- },
- },
- [AIRBASE.PersianGulf.Sirri_Island] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=-169713.12842428,["x"]=-27766.658020853,},
- [2]={["y"]=-169682.02009414,["x"]=-27726.583172021,},
- [3]={["y"]=-169727.21866794,["x"]=-27691.632048154,},
- [4]={["y"]=-169694.28043602,["x"]=-27650.276268081,},
- [5]={["y"]=-169763.08474269,["x"]=-27598.490047901,},
- [6]={["y"]=-169825.30140298,["x"]=-27607.090586235,},
- [7]={["y"]=-171614.98889813,["x"]=-26246.247907014,},
- [8]={["y"]=-171620.85326172,["x"]=-26187.105176343,},
- [9]={["y"]=-171686.10990337,["x"]=-26138.56820961,},
- [10]={["y"]=-171716.55468456,["x"]=-26178.745338885,},
- [11]={["y"]=-171764.9668776,["x"]=-26142.810515186,},
- [12]={["y"]=-171796.29599657,["x"]=-26183.416460911,},
- [13]={["y"]=-169713.5628285,["x"]=-27766.883787223,},
- },
- },
- },
- [AIRBASE.PersianGulf.Tunb_Island_AFB] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=-92923.634698863,["x"]=9547.6862547173,},
- [2]={["y"]=-92963.030803298,["x"]=9565.7274614215,},
- [3]={["y"]=-92934.128053782,["x"]=9619.2987996964,},
- [4]={["y"]=-92970.946842975,["x"]=9640.1014155901,},
- [5]={["y"]=-92949.591945243,["x"]=9682.8112110532,},
- [6]={["y"]=-92899.518391942,["x"]=9699.7478540817,},
- [7]={["y"]=-91969.13471408,["x"]=11464.627292768,},
- [8]={["y"]=-91983.666755417,["x"]=11515.293058512,},
- [9]={["y"]=-91960.101282978,["x"]=11557.710908902,},
- [10]={["y"]=-91921.021874517,["x"]=11539.251288825,},
- [11]={["y"]=-91893.725202275,["x"]=11589.720675632,},
- [12]={["y"]=-91859.751646175,["x"]=11571.850192366,},
- [13]={["y"]=-92922.149728329,["x"]=9547.2937058617,},
- },
- },
- },
- [AIRBASE.PersianGulf.Tunb_Kochak] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=-109925.50271188,["x"]=8974.5666013181,},
- [2]={["y"]=-109905.7382908,["x"]=8937.53274444,},
- [3]={["y"]=-109009.93726324,["x"]=9072.2234968343,},
- [4]={["y"]=-109040.82867587,["x"]=9104.9871291834,},
- [5]={["y"]=-109925.26515172,["x"]=8974.091480998,},
- },
- },
- },
- [AIRBASE.PersianGulf.Sas_Al_Nakheel_Airport] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=-176230.75865538,["x"]=-188732.01369812,},
- [2]={["y"]=-176274.78045186,["x"]=-188744.8049371,},
- [3]={["y"]=-175692.03171595,["x"]=-190564.17145168,},
- [4]={["y"]=-175649.7486572,["x"]=-190550.58435053,},
- [5]={["y"]=-176230.66274076,["x"]=-188731.5667818,},
- },
- },
- },
- [AIRBASE.PersianGulf.Bandar_e_Jask_airfield] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=155156.73167657,["x"]=-57837.031277333,},
- [2]={["y"]=155130.38996239,["x"]=-57790.475605714,},
- [3]={["y"]=157137.17872571,["x"]=-56710.411783359,},
- [4]={["y"]=157148.46631801,["x"]=-56688.071756941,},
- [5]={["y"]=157220.07198163,["x"]=-56649.035500253,},
- [6]={["y"]=157227.83220133,["x"]=-56662.204357931,},
- [7]={["y"]=157359.6383572,["x"]=-56590.481115222,},
- [8]={["y"]=157383.03659539,["x"]=-56633.044744502,},
- [9]={["y"]=155156.7940421,["x"]=-57837.149989814,},
- },
- },
- },
- [AIRBASE.PersianGulf.Abu_Dhabi_International_Airport] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=-163964.56943899,["x"]=-189427.63621921,},
- [2]={["y"]=-164005.96838287,["x"]=-189478.90226888,},
- [3]={["y"]=-160798.22080495,["x"]=-192054.59531727,},
- [4]={["y"]=-160755.05282258,["x"]=-192002.58569997,},
- [5]={["y"]=-163964.47352437,["x"]=-189427.18930288,},
- },
- [2] = {
- [1]={["y"]=-163615.44952024,["x"]=-187144.00786922,},
- [2]={["y"]=-163656.84846411,["x"]=-187195.27391888,},
- [3]={["y"]=-160452.71811093,["x"]=-189764.86593382,},
- [4]={["y"]=-160411.94568221,["x"]=-189715.47961171,},
- [5]={["y"]=-163615.35360562,["x"]=-187143.56095289,},
- },
- },
- },
- [AIRBASE.PersianGulf.Al_Bateen_Airport] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=-183207.51774197,["x"]=-189871.8319832,},
- [2]={["y"]=-183240.61462564,["x"]=-189914.01184622,},
- [3]={["y"]=-180748.88998479,["x"]=-191943.30402837,},
- [4]={["y"]=-180711.83076051,["x"]=-191896.52435182,},
- [5]={["y"]=-183207.42182735,["x"]=-189871.38506688,},
- },
- },
- },
- [AIRBASE.PersianGulf.Kish_International_Airport] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=-227330.79164594,["x"]=42691.91536494,},
- [2]={["y"]=-227321.58531968,["x"]=42758.113234714,},
- [3]={["y"]=-223235.73004619,["x"]=42313.579195302,},
- [4]={["y"]=-223240.99080406,["x"]=42247.819722016,},
- [5]={["y"]=-227330.67774245,["x"]=42691.785682556,},
- },
- [2] = {
- [1]={["y"]=-227283.77911886,["x"]=42987.748941936,},
- [2]={["y"]=-227274.5727926,["x"]=43053.946811711,},
- [3]={["y"]=-222907.94761294,["x"]=42580.826755904,},
- [4]={["y"]=-222915.76510871,["x"]=42514.58376547,},
- [5]={["y"]=-227283.66521537,["x"]=42987.619259553,},
- },
- },
- },
- [AIRBASE.PersianGulf.Al_Ain_International_Airport] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=-65165.315648901,["x"]=-209042.45716363,},
- [2]={["y"]=-65112.933878375,["x"]=-209048.84518442,},
- [3]={["y"]=-65672.013626755,["x"]=-213019.66479976,},
- [4]={["y"]=-65722.555424932,["x"]=-213013.91596964,},
- [5]={["y"]=-65165.400582791,["x"]=-209042.15059908,},
- },
- },
- },
- [AIRBASE.PersianGulf.Lavan_Island_Airport] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=-288099.83301495,["x"]=76353.443273049,},
- [2]={["y"]=-288119.51457685,["x"]=76302.756224611,},
- [3]={["y"]=-288070.96603401,["x"]=76283.898526152,},
- [4]={["y"]=-288085.61084238,["x"]=76247.386812114,},
- [5]={["y"]=-288032.04695421,["x"]=76224.316223573,},
- [6]={["y"]=-287991.12173627,["x"]=76245.38067398,},
- [7]={["y"]=-287489.96435675,["x"]=76037.610404141,},
- [8]={["y"]=-287497.65444594,["x"]=76017.686082159,},
- [9]={["y"]=-287453.61120787,["x"]=75998.111309685,},
- [10]={["y"]=-287419.70490555,["x"]=76007.199596905,},
- [11]={["y"]=-285642.24565503,["x"]=75279.787069797,},
- [12]={["y"]=-285625.46727862,["x"]=75239.239326815,},
- [13]={["y"]=-285570.23845628,["x"]=75217.217707782,},
- [14]={["y"]=-285555.20782742,["x"]=75252.172658628,},
- [15]={["y"]=-285505.92134673,["x"]=75231.199688121,},
- [16]={["y"]=-285484.28380792,["x"]=75284.258832895,},
- [17]={["y"]=-288099.97979219,["x"]=76354.32393647,},
- },
- },
- },
- [AIRBASE.PersianGulf.Jiroft_Airport] = {
- PointsRunways = {
- [1] = {
- [1]={["y"]=140376.87310595,["x"]=283748.07558774,},
- [2]={["y"]=140299.43760975,["x"]=283655.81201779,},
- [3]={["y"]=143008.43807723,["x"]=281517.41347718,},
- [4]={["y"]=143052.6952428,["x"]=281573.25195709,},
- [5]={["y"]=142946.60213095,["x"]=281656.5960586,},
- [6]={["y"]=142975.14179847,["x"]=281687.20381796,},
- [7]={["y"]=142932.12548801,["x"]=281724.01585287,},
- [8]={["y"]=142870.49635092,["x"]=281719.05243244,},
- [9]={["y"]=140437.35783025,["x"]=283640.84253664,},
- [10]={["y"]=140433.27045062,["x"]=283705.80267729,},
- [11]={["y"]=140376.77702493,["x"]=283747.8442964,},
- },
- },
- },
- },
}
-
--- Creates a new ATC_GROUND_PERSIANGULF object.
-- @param #ATC_GROUND_PERSIANGULF self
-- @param AirbaseNames A list {} of airbase names (Use AIRBASE.PersianGulf enumerator).
@@ -2997,266 +1406,11 @@ ATC_GROUND_PERSIANGULF = {
function ATC_GROUND_PERSIANGULF:New( AirbaseNames )
-- Inherits from BASE
- local self = BASE:Inherit( self, ATC_GROUND:New( self.Airbases, AirbaseNames ) ) -- #ATC_GROUND_PERSIANGULF
+ local self = BASE:Inherit( self, ATC_GROUND_UNIVERSAL:New( AirbaseNames ) ) -- #ATC_GROUND_PERSIANGULF
self:SetKickSpeedKmph( 50 )
self:SetMaximumKickSpeedKmph( 150 )
-
- -- These lines here are for the demonstration mission.
- -- They create in the dcs.log the coordinates of the runway polygons, that are then
- -- taken by the moose designer from the dcs.log and reworked to define the
- -- Airbases structure, which is part of the class.
- -- When new airbases are added or airbases are changed on the map,
- -- the MOOSE designer willde-comment this section and apply the changes in the demo
- -- mission, and do a re-run to create a new dcs.log, and then add the changed coordinates
- -- in the Airbases structure.
- -- So, this needs to stay commented normally once a map has been finished.
-
- --[[
-
- -- Abu_Musa_Island_Airport
- do
- local VillagePrefix = "Abu_Musa_Island_Airport"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Al_Dhafra_AB
- do
- local VillagePrefix = "Al_Dhafra_AB"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- local Runway2 = GROUP:FindByName( VillagePrefix .. " 2" )
- local Zone2 = ZONE_POLYGON:New( VillagePrefix .. " 2", Runway2 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Al_Maktoum_Intl
- do
- local VillagePrefix = "Al_Maktoum_Intl"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Al_Minhad_AB
- do
- local VillagePrefix = "Al_Minhad_AB"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Bandar_Abbas_Intl
- do
- local VillagePrefix = "Bandar_Abbas_Intl"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- local Runway2 = GROUP:FindByName( VillagePrefix .. " 2" )
- local Zone2 = ZONE_POLYGON:New( VillagePrefix .. " 2", Runway2 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Bandar_Lengeh
- do
- local VillagePrefix = "Bandar_Lengeh"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Dubai_Intl
- do
- local VillagePrefix = "Dubai_Intl"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- local Runway2 = GROUP:FindByName( VillagePrefix .. " 2" )
- local Zone2 = ZONE_POLYGON:New( VillagePrefix .. " 2", Runway2 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Fujairah_Intl
- do
- local VillagePrefix = "Fujairah_Intl"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Havadarya
- do
- local VillagePrefix = "Havadarya"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Kerman_Airport
- do
- local VillagePrefix = "Kerman_Airport"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Khasab
- do
- local VillagePrefix = "Khasab"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Lar_Airbase
- do
- local VillagePrefix = "Lar_Airbase"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Qeshm_Island
- do
- local VillagePrefix = "Qeshm_Island"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Sharjah_Intl
- do
- local VillagePrefix = "Sharjah_Intl"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- local Runway2 = GROUP:FindByName( VillagePrefix .. " 2" )
- local Zone2 = ZONE_POLYGON:New( VillagePrefix .. " 2", Runway2 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Shiraz_International_Airport
- do
- local VillagePrefix = "Shiraz_International_Airport"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- local Runway2 = GROUP:FindByName( VillagePrefix .. " 2" )
- local Zone2 = ZONE_POLYGON:New( VillagePrefix .. " 2", Runway2 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Sir_Abu_Nuayr
- do
- local VillagePrefix = "Sir_Abu_Nuayr"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Sirri_Island
- do
- local VillagePrefix = "Sirri_Island"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Tunb_Island_AFB
- do
- local VillagePrefix = "Tunb_Island_AFB"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Tunb_Kochak
- do
- local VillagePrefix = "Tunb_Kochak"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Sas_Al_Nakheel_Airport
- do
- local VillagePrefix = "Sas_Al_Nakheel_Airport"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Bandar_e_Jask_airfield
- do
- local VillagePrefix = "Bandar_e_Jask_airfield"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Abu_Dhabi_International_Airport
- do
- local VillagePrefix = "Abu_Dhabi_International_Airport"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- local Runway2 = GROUP:FindByName( VillagePrefix .. " 2" )
- local Zone2 = ZONE_POLYGON:New( VillagePrefix .. " 2", Runway2 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Al_Bateen_Airport
- do
- local VillagePrefix = "Al_Bateen_Airport"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Kish_International_Airport
- do
- local VillagePrefix = "Kish_International_Airport"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- local Runway2 = GROUP:FindByName( VillagePrefix .. " 2" )
- local Zone2 = ZONE_POLYGON:New( VillagePrefix .. " 2", Runway2 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Al_Ain_International_Airport
- do
- local VillagePrefix = "Al_Ain_International_Airport"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Lavan_Island_Airport
- do
- local VillagePrefix = "Lavan_Island_Airport"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Jiroft_Airport
- do
- local VillagePrefix = "Jiroft_Airport"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
-
- -- Bandar_Abbas_Intl
- do
- local VillagePrefix = "Bandar_Abbas_Intl"
- local Runway1 = GROUP:FindByName( VillagePrefix .. " 1" )
- local Zone1 = ZONE_POLYGON:New( VillagePrefix .. " 1", Runway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
- local Runway2 = GROUP:FindByName( VillagePrefix .. " 2" )
- local Zone2 = ZONE_POLYGON:New( VillagePrefix .. " 2", Runway2 ):SmokeZone(SMOKECOLOR.Red):Flush()
- end
-
- --]]
-
- return self
end
--- Start SCHEDULER for ATC_GROUND_PERSIANGULF object.
@@ -3366,142 +1520,6 @@ end
---- @field #ATC_GROUND_MARIANAISLANDS
ATC_GROUND_MARIANAISLANDS = {
ClassName = "ATC_GROUND_MARIANAISLANDS",
- Airbases = {
-
- [AIRBASE.MarianaIslands.Andersen_AFB] = {
- ZoneBoundary = {
- [1]={["y"]=16534.138036037,["x"]=11357.42159178,},
- [2]={["y"]=16193.406442738,["x"]=12080.012957533,},
- [3]={["y"]=13846.966851869,["x"]=12017.348398727,},
- [4]={["y"]=13085.815989171,["x"]=11686.317876875,},
- [5]={["y"]=13157.991797443,["x"]=11307.826209991,},
- [6]={["y"]=12055.725179065,["x"]=10795.955695916,},
- [7]={["y"]=12762.455491112,["x"]=8890.9830441032,},
- [8]={["y"]=15955.829493693,["x"]=10333.527220132,},
- [9]={["y"]=16537.500532414,["x"]=11302.009499603,},
- },
- PointsRunways = {
- [1]={
- [1]={["y"]=12586.683049611,["x"]=10224.374497932,},
- [2]={["y"]=16191.720475696,["x"]=11791.299100017,},
- [3]={["y"]=16126.93956642,["x"]=11938.855615591,},
- [4]={["y"]=12520.758127164,["x"]=10385.177131701,},
- [5]={["y"]=12584.654720512,["x"]=10227.416991581,},
- },
- [2]={
- [1]={["y"]=12663.030391743,["x"]=9661.9623015306,},
- [2]={["y"]=16478.347303358,["x"]=11328.665745976,},
- [3]={["y"]=16405.4731048,["x"]=11479.11570429,},
- [4]={["y"]=12597.277684174,["x"]=9817.9733769647,},
- [5]={["y"]=12661.894752524,["x"]=9674.4462086962,},
- },
- },
- },
- [AIRBASE.MarianaIslands.Antonio_B_Won_Pat_Intl] = {
- ZoneBoundary = {
- [1]={["y"]=2288.5182403943,["x"]=1469.0170841716,},
- [2]={["y"]=1126.2025877996,["x"]=1174.37135631,},
- [3]={["y"]=-2015.6461924287,["x"]=-484.62000718931,},
- [4]={["y"]=-2102.1292389114,["x"]=-988.03393750566,},
- [5]={["y"]=476.03853524366,["x"]=-1220.1783269883,},
- [6]={["y"]=2059.2220058047,["x"]=78.889693514402,},
- [7]={["y"]=1898.1396965104,["x"]=705.67531284795,},
- [8]={["y"]=2760.1768681934,["x"]=1026.0681119777,},
- [9]={["y"]=2317.2278959994,["x"]=1460.8143254273,},
- },
- PointsRunways = {
- [1]={
- [1]={["y"]=-1872.6620108821,["x"]=-924.3572605835,},
- [2]={["y"]=1763.4754603305,["x"]=735.35988877983,},
- [3]={["y"]=1700.6941677961,["x"]=866.32615476157,},
- [4]={["y"]=-1934.0078007732,["x"]=-779.8149298453,},
- [5]={["y"]=-1875.0113982627,["x"]=-914.95971106094,},
- },
- [2]={
- [1]={["y"]=-1512.9403660377,["x"]=-1005.5903386188,},
- [2]={["y"]=1577.9055714735,["x"]=413.22750176368,},
- [3]={["y"]=1523.1182807849,["x"]=543.89726442232,},
- [4]={["y"]=-1572.5102998047,["x"]=-867.04004322806,},
- [5]={["y"]=-1514.2790162347,["x"]=-1003.5823633233,},
- },
- },
- },
- [AIRBASE.MarianaIslands.Rota_Intl] = {
- ZoneBoundary = {
- [1]={["y"]=47237.615412849,["x"]=76048.890408862,},
- [2]={["y"]=49938.030053628,["x"]=75921.721582932,},
- [3]={["y"]=49931.24873272,["x"]=75735.184004851,},
- [4]={["y"]=49295.999227075,["x"]=75754.716414519,},
- [5]={["y"]=49286.963307515,["x"]=75510.037806569,},
- [6]={["y"]=48774.280745707,["x"]=75513.331990155,},
- [7]={["y"]=48785.021396773,["x"]=75795.691662161,},
- [8]={["y"]=47232.749278491,["x"]=75839.239059146,},
- [9]={["y"]=47236.687866223,["x"]=76042.706764692,},
- },
- PointsRunways = {
- [1]={
- [1]={["y"]=49741.295228062,["x"]=75901.50955922,},
- [2]={["y"]=49739.033213305,["x"]=75768.333440425,},
- [3]={["y"]=47448.460520408,["x"]=75857.400271466,},
- [4]={["y"]=47452.270177742,["x"]=75999.965448133,},
- [5]={["y"]=49738.502011054,["x"]=75905.338915708,},
- },
- },
- },
- [AIRBASE.MarianaIslands.Saipan_Intl] = {
- ZoneBoundary = {
- [1]={["y"]=100489.08491445,["x"]=179799.05158855,},
- [2]={["y"]=100869.73415313,["x"]=179948.98719903,},
- [3]={["y"]=101364.78967515,["x"]=180831.98517043,},
- [4]={["y"]=101563.85713359,["x"]=180885.21496237,},
- [5]={["y"]=101733.92591034,["x"]=180457.73296886,},
- [6]={["y"]=103340.30228775,["x"]=180990.08362622,},
- [7]={["y"]=103459.55080438,["x"]=180453.77747027,},
- [8]={["y"]=100406.63048095,["x"]=179266.60983762,},
- [9]={["y"]=100225.55027532,["x"]=179423.9380961,},
- [10]={["y"]=100477.48558937,["x"]=179791.9827288,},
- },
- PointsRunways = {
- [1]={
- [1]={["y"]=103170.38882002,["x"]=180654.56630524,},
- [2]={["y"]=103235.37868835,["x"]=180497.25368418,},
- [3]={["y"]=100564.72969504,["x"]=179435.41443498,},
- [4]={["y"]=100509.30718722,["x"]=179584.65394733,},
- [5]={["y"]=103163.53918905,["x"]=180651.82645285,},
- },
- [2]={
- [1]={["y"]=103048.83223261,["x"]=180819.94107128,},
- [2]={["y"]=103087.60579257,["x"]=180720.06315265,},
- [3]={["y"]=101037.52694966,["x"]=179899.50061624,},
- [4]={["y"]=100994.61708907,["x"]=180009.33151758,},
- [5]={["y"]=103043.26643227,["x"]=180820.40488798,},
- },
- },
- },
- [AIRBASE.MarianaIslands.Tinian_Intl] = {
- ZoneBoundary = {
- [1]={["y"]=88393.477575413,["x"]=166704.16076438,},
- [2]={["y"]=91581.732441809,["x"]=167402.54409276,},
- [3]={["y"]=91533.451647402,["x"]=166826.23670062,},
- [4]={["y"]=90827.604136952,["x"]=166699.75590414,},
- [5]={["y"]=90894.853975623,["x"]=166375.37836304,},
- [6]={["y"]=89995.027922869,["x"]=166224.92495935,},
- [7]={["y"]=88937.62899352,["x"]=166244.48573911,},
- [8]={["y"]=88408.916178231,["x"]=166480.39896864,},
- [9]={["y"]=88387.745481732,["x"]=166685.82715656,},
- },
- PointsRunways = {
- [1]={
- [1]={["y"]=91329.480937912,["x"]=167204.44064529,},
- [2]={["y"]=91363.95475433,["x"]=167038.15603429,},
- [3]={["y"]=88585.849307337,["x"]=166520.3807647,},
- [4]={["y"]=88554.422227212,["x"]=166686.49505251,},
- [5]={["y"]=91318.8152578,["x"]=167203.31794212,},
- },
- },
- },
-
- },
}
--- Creates a new ATC_GROUND_MARIANAISLANDS object.
@@ -3511,63 +1529,14 @@ ATC_GROUND_MARIANAISLANDS = {
function ATC_GROUND_MARIANAISLANDS:New( AirbaseNames )
-- Inherits from BASE
- local self = BASE:Inherit( self, ATC_GROUND:New( self.Airbases, AirbaseNames ) )
+ local self = BASE:Inherit( self, ATC_GROUND_UNIVERSAL:New( self.Airbases, AirbaseNames ) )
self:SetKickSpeedKmph( 50 )
self:SetMaximumKickSpeedKmph( 150 )
--- -- Andersen
--- local AndersenBoundary = GROUP:FindByName( "Andersen Boundary" )
--- self.Airbases[AIRBASE.MarianaIslands.Andersen_AFB].ZoneBoundary = ZONE_POLYGON:New( "Andersen Boundary", AndersenBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
---
--- local AndersenRunway1 = GROUP:FindByName( "Andersen Runway 1" )
--- self.Airbases[AIRBASE.MarianaIslands.Andersen_AFB].ZoneRunways[1] = ZONE_POLYGON:New( "Andersen Runway 1", AndersenRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
---
--- local AndersenRunway2 = GROUP:FindByName( "Andersen Runway 2" )
--- self.Airbases[AIRBASE.MarianaIslands.Andersen_AFB].ZoneRunways[2] = ZONE_POLYGON:New( "Andersen Runway 2", AndersenRunway2 ):SmokeZone(SMOKECOLOR.Red):Flush()
---
---
--- -- Antonio_B_Won_Pat_International_Airport
--- local AntonioBoundary = GROUP:FindByName( "Antonio Boundary" )
--- self.Airbases[AIRBASE.MarianaIslands.Antonio_B_Won_Pat_Intl].ZoneBoundary = ZONE_POLYGON:New( "Antonio Boundary", AntonioBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
---
--- local AntonioRunway1 = GROUP:FindByName( "Antonio Runway 1" )
--- self.Airbases[AIRBASE.MarianaIslands.Antonio_B_Won_Pat_Intl].ZoneRunways[1] = ZONE_POLYGON:New( "Antonio Runway 1", AntonioRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
---
--- local AntonioRunway2 = GROUP:FindByName( "Antonio Runway 2" )
--- self.Airbases[AIRBASE.MarianaIslands.Antonio_B_Won_Pat_Intl].ZoneRunways[2] = ZONE_POLYGON:New( "Antonio Runway 2", AntonioRunway2 ):SmokeZone(SMOKECOLOR.Red):Flush()
---
---
--- -- Rota_International_Airport
--- local RotaBoundary = GROUP:FindByName( "Rota Boundary" )
--- self.Airbases[AIRBASE.MarianaIslands.Rota_Intl].ZoneBoundary = ZONE_POLYGON:New( "Rota Boundary", RotaBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
---
--- local RotaRunway1 = GROUP:FindByName( "Rota Runway 1" )
--- self.Airbases[AIRBASE.MarianaIslands.Rota_Intl].ZoneRunways[1] = ZONE_POLYGON:New( "Rota Runway 1", RotaRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
---
---
--- -- Saipan_International_Airport
--- local SaipanBoundary = GROUP:FindByName( "Saipan Boundary" )
--- self.Airbases[AIRBASE.MarianaIslands.Saipan_Intl].ZoneBoundary = ZONE_POLYGON:New( "Saipan Boundary", SaipanBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
---
--- local SaipanRunway1 = GROUP:FindByName( "Saipan Runway 1" )
--- self.Airbases[AIRBASE.MarianaIslands.Saipan_Intl].ZoneRunways[1] = ZONE_POLYGON:New( "Saipan Runway 1", SaipanRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
---
--- local SaipanRunway2 = GROUP:FindByName( "Saipan Runway 2" )
--- self.Airbases[AIRBASE.MarianaIslands.Saipan_Intl].ZoneRunways[2] = ZONE_POLYGON:New( "Saipan Runway 2", SaipanRunway2 ):SmokeZone(SMOKECOLOR.Red):Flush()
---
---
--- -- Tinian_International_Airport
--- local TinianBoundary = GROUP:FindByName( "Tinian Boundary" )
--- self.Airbases[AIRBASE.MarianaIslands.Tinian_Intl].ZoneBoundary = ZONE_POLYGON:New( "Tinian Boundary", TinianBoundary ):SmokeZone(SMOKECOLOR.White):Flush()
---
--- local TinianRunway1 = GROUP:FindByName( "Tinian Runway 1" )
--- self.Airbases[AIRBASE.MarianaIslands.Tinian_Intl].ZoneRunways[1] = ZONE_POLYGON:New( "Tinian Runway 1", TinianRunway1 ):SmokeZone(SMOKECOLOR.Red):Flush()
-
return self
end
-
--- Start SCHEDULER for ATC_GROUND_MARIANAISLANDS object.
-- @param #ATC_GROUND_MARIANAISLANDS self
-- @param RepeatScanSeconds Time in second for defining occurency of alerts.
diff --git a/Moose Development/Moose/Functional/Autolase.lua b/Moose Development/Moose/Functional/Autolase.lua
index daffdfa22..6c249e003 100644
--- a/Moose Development/Moose/Functional/Autolase.lua
+++ b/Moose Development/Moose/Functional/Autolase.lua
@@ -74,6 +74,7 @@
-- @image Designation.JPG
--
-- Date: 24 Oct 2021
+-- Last Update: Aug 2022
--
--- Class AUTOLASE
-- @type AUTOLASE
@@ -110,7 +111,7 @@ AUTOLASE = {
--- AUTOLASE class version.
-- @field #string version
-AUTOLASE.version = "0.0.12"
+AUTOLASE.version = "0.1.14"
-------------------------------------------------------------------
-- Begin Functional.Autolase.lua
@@ -192,6 +193,7 @@ function AUTOLASE:New(RecceSet, Coalition, Alias, PilotSet)
self.SRSPath = ""
self.SRSFreq = 251
self.SRSMod = radio.modulation.AM
+ self.NoMenus = false
-- Set some string id for output to DCS.log file.
self.lid=string.format("AUTOLASE %s (%s) | ", self.alias, self.coalition and UTILS.GetCoalitionName(self.coalition) or "unknown")
@@ -207,14 +209,14 @@ function AUTOLASE:New(RecceSet, Coalition, Alias, PilotSet)
self:AddTransition("*", "Cancel", "*") -- Stop Autolase
-- Menu Entry
- if not PilotSet then
- self.Menu = MENU_COALITION_COMMAND:New(self.coalition,"Autolase",nil,self.ShowStatus,self)
- else
+ if PilotSet then
self.usepilotset = true
self.pilotset = PilotSet
self:HandleEvent(EVENTS.PlayerEnterAircraft)
- self:SetPilotMenu()
+ --self:SetPilotMenu()
end
+ --self.SetPilotMenu()
+
self:SetClusterAnalysis(false, false)
@@ -308,6 +310,10 @@ function AUTOLASE:SetPilotMenu()
lasemenu:Refresh()
end
end
+ else
+ if not self.NoMenus then
+ self.Menu = MENU_COALITION_COMMAND:New(self.coalition,"Autolase",nil,self.ShowStatus,self)
+ end
end
return self
end
@@ -356,12 +362,45 @@ end
-- @param #string Path Path to SRS directory, e.g. C:\\Program Files\\DCS-SimpleRadio-Standalon
-- @param #number Frequency Frequency to send, e.g. 243
-- @param #number Modulation Modulation i.e. radio.modulation.AM or radio.modulation.FM
+-- @param #string Label (Optional) Short label to be used on the SRS Client Overlay
+-- @param #string Gender (Optional) Defaults to "male"
+-- @param #string Culture (Optional) Defaults to "en-US"
+-- @param #number Port (Optional) Defaults to 5002
+-- @param #string Voice (Optional) Use a specifc voice with the @{Sound.SRS.SetVoice} function, e.g, `:SetVoice("Microsoft Hedda Desktop")`.
+-- Note that this must be installed on your windows system. Can also be Google voice types, if you are using Google TTS.
+-- @param #number Volume (Optional) Volume - between 0.0 (silent) and 1.0 (loudest)
+-- @param #string PathToGoogleKey (Optional) Path to your google key if you want to use google TTS
-- @return #AUTOLASE self
-function AUTOLASE:SetUsingSRS(OnOff,Path,Frequency,Modulation)
- self.useSRS = OnOff or true
- self.SRSPath = Path or "E:\\Program Files\\DCS-SimpleRadio-Standalone"
- self.SRSFreq = Frequency or 271
- self.SRSMod = Modulation or radio.modulation.AM
+function AUTOLASE:SetUsingSRS(OnOff,Path,Frequency,Modulation,Label,Gender,Culture,Port,Voice,Volume,PathToGoogleKey)
+ if OnOff then
+ self.useSRS = true
+ self.SRSPath = Path or "C:\\Program Files\\DCS-SimpleRadio-Standalone"
+ self.SRSFreq = Frequency or 271
+ self.SRSMod = Modulation or radio.modulation.AM
+ self.Gender = Gender or "male"
+ self.Culture = Culture or "en-US"
+ self.Port = Port or 5002
+ self.Voice = Voice
+ self.PathToGoogleKey = PathToGoogleKey
+ self.Volume = Volume or 1.0
+ self.Label = Label
+ -- set up SRS
+ self.SRS = MSRS:New(self.SRSPath,self.SRSFreq,self.SRSMod,self.Volume)
+ self.SRS:SetCoalition(self.coalition)
+ self.SRS:SetLabel(self.MenuName or self.Name)
+ self.SRS:SetGender(self.Gender)
+ self.SRS:SetCulture(self.Culture)
+ self.SRS:SetPort(self.Port)
+ self.SRS:SetVoice(self.Voice)
+ if self.PathToGoogleKey then
+ self.SRS:SetGoogle(self.PathToGoogleKey)
+ end
+ self.SRSQueue = MSRSQUEUE:New(self.alias)
+ else
+ self.useSRS = false
+ self.SRS= nil
+ self.SRSQueue = nil
+ end
return self
end
@@ -643,20 +682,7 @@ end
-- end
function AUTOLASE:NotifyPilotsWithSRS(Message)
if self.useSRS then
- -- Create a SOUNDTEXT object.
- if self.debug then
- BASE:TraceOn()
- BASE:TraceClass("SOUNDTEXT")
- BASE:TraceClass("MSRS")
- end
- local path = self.SRSPath or "C:\\Program Files\\DCS-SimpleRadio-Standalone"
- local freq = self.SRSFreq or 271
- local mod = self.SRSMod or radio.modulation.AM
- local text=SOUNDTEXT:New(Message)
- -- MOOSE SRS
- local msrs=MSRS:New(path, freq, mod)
- -- Text-to speech with default voice after 2 seconds.
- msrs:PlaySoundText(text, 2)
+ self.SRSQueue:NewTransmission(Message,nil,self.SRS,nil,2)
end
if self.debug then self:I(Message) end
return self
diff --git a/Moose Development/Moose/Functional/Range.lua b/Moose Development/Moose/Functional/Range.lua
index 1fc035c8c..21af22579 100644
--- a/Moose Development/Moose/Functional/Range.lua
+++ b/Moose Development/Moose/Functional/Range.lua
@@ -1412,7 +1412,7 @@ function RANGE:AddBombingTargets( targetnames, goodhitrange, randommove )
elseif _isstatic == false then
local _unit = UNIT:FindByName( name )
self:T2( self.id .. string.format( "Adding unit bombing target %s with hit range %d.", name, goodhitrange, randommove ) )
- self:AddBombingTargetUnit( _unit, goodhitrange )
+ self:AddBombingTargetUnit( _unit, goodhitrange, randommove )
else
self:E( self.id .. string.format( "ERROR! Could not find bombing target %s.", name ) )
end
@@ -2419,7 +2419,8 @@ end
--- Start smoking a coordinate with a delay.
-- @param #table _args Argements passed.
function RANGE._DelayedSmoke( _args )
- trigger.action.smoke( _args.coord:GetVec3(), _args.color )
+ _args.coord:Smoke(_args.color)
+ --trigger.action.smoke( _args.coord:GetVec3(), _args.color )
end
--- Display top 10 stafing results of a specific player.
@@ -2447,7 +2448,7 @@ function RANGE:_DisplayMyStrafePitResults( _unitName )
-- Sort results table wrt number of hits.
local _sort = function( a, b )
- return a.hits > b.hits
+ return a.roundsHit > b.roundsHit
end
table.sort( _results, _sort )
@@ -2464,7 +2465,7 @@ function RANGE:_DisplayMyStrafePitResults( _unitName )
-- Best result.
if _bestMsg == "" then
- _bestMsg = string.format( "Hits %d - %s - %s", _result.hits, _result.zone.name, _result.text )
+ _bestMsg = string.format( "Hits %d - %s - %s", result.roundsHit, result.name, result.roundsQuality)
end
-- 10 runs
@@ -2509,15 +2510,15 @@ function RANGE:_DisplayStrafePitResults( _unitName )
-- Get the best result of the player.
local _best = nil
for _, _result in pairs( _results ) do
- if _best == nil or _result.hits > _best.hits then
+ if _best == nil or _result.roundsHit > _best.roundsHit then
_best = _result
end
end
-- Add best result to table.
if _best ~= nil then
- local text = string.format( "%s: Hits %i - %s - %s", _playerName, _best.hits, _best.zone.name, _best.text )
- table.insert( _playerResults, { msg = text, hits = _best.hits } )
+ local text = string.format( "%s: Hits %i - %s - %s", _playerName, _best.roundsHit, _best.name, _best.roundsQuality )
+ table.insert( _playerResults, { msg = text, hits = _best.roundsHit } )
end
end
@@ -3543,6 +3544,7 @@ function RANGE:_DisplayMessageToGroup( _unit, _text, _time, _clear, display )
-- Group ID.
local _gid = _unit:GetGroup():GetID()
+ local _grp = _unit:GetGroup()
-- Get playername and player settings
local _, playername = self:_GetPlayerUnitAndName( _unit:GetName() )
@@ -3550,14 +3552,14 @@ function RANGE:_DisplayMessageToGroup( _unit, _text, _time, _clear, display )
-- Send message to player if messages enabled and not only for the examiner.
if _gid and (playermessage == true or display) and (not self.examinerexclusive) then
- trigger.action.outTextForGroup( _gid, _text, _time, _clear )
+ local m = MESSAGE:New(_text,_time,nil,_clear):ToUnit(_unit)
end
-- Send message to examiner.
if self.examinergroupname ~= nil then
- local _examinerid = GROUP:FindByName( self.examinergroupname ):GetID()
+ local _examinerid = GROUP:FindByName( self.examinergroupname )
if _examinerid then
- trigger.action.outTextForGroup( _examinerid, _text, _time, _clear )
+ local m = MESSAGE:New(_text,_time,nil,_clear):ToGroup(_examinerid)
end
end
end
diff --git a/Moose Development/Moose/Ops/Awacs.lua b/Moose Development/Moose/Ops/Awacs.lua
index 9b9c14acb..9e9d31d29 100644
--- a/Moose Development/Moose/Ops/Awacs.lua
+++ b/Moose Development/Moose/Ops/Awacs.lua
@@ -17,7 +17,7 @@
-- ===
--
-- ### Author: **applevangelist**
--- @date Last Update July 2022
+-- @date Last Update August 2022
-- @module Ops.AWACS
-- @image OPS_AWACS.jpg
@@ -109,6 +109,7 @@ do
-- @field #string PlayerStationName
-- @field #boolean GCI Act as GCI
-- @field Wrapper.Group#GROUP GCIGroup EWR group object for GCI ops
+-- @field #string locale Localization
-- @extends Core.Fsm#FSM
@@ -310,7 +311,8 @@ do
-- ## 8 Bespoke Player CallSigns
--
-- Append the GROUP name of your client slots with "#CallSign" to use bespoke callsigns in AWACS callouts. E.g. "Player F14#Ghostrider" will be refered to
--- as "Ghostrider" plus group number, e.g. "Ghostrider 9".
+-- as "Ghostrider" plus group number, e.g. "Ghostrider 9". Alternatively, if you have set up your Player name in the "Logbook" in the mission editor main screen
+-- as e.g. "Pikes | Goose", you will be addressed as "Goose" by the AWACS callouts.
--
-- ## 9 Options
--
@@ -359,6 +361,7 @@ do
-- -- messages or too long pauses
-- testawacs.GoogleTTSPadding = 1 -- seconds
-- testawacs.WindowsTTSPadding = 2.5 -- seconds
+-- testawacs.PikesSpecialSwitch = false -- if set to true, AWACS will omit the "doing xy knots" on the station assignement callout
--
-- ## 9.2 Bespoke random voices for AI CAP (Google TTS only)
--
@@ -390,8 +393,98 @@ do
-- in this example will be the name of the new station point. The user marker can then be deleted, an info marker point at the same place will remain.
-- You can delete a player station point the same way: "AWACS Delete London"; note this will only work if currently there are no assigned flights on this station.
-- Lastly, you can move the station around with keyword "Move": "AWACS Move London".
---
--- ## 11 Discussion
+--
+-- ## 11 Localization
+--
+-- Localization for English text is build-in. Default setting is English. Change with @{#AWACS.SetLocale}()
+--
+-- ### 11.1 Adding Localization
+--
+-- A list of fields to be defined follows below. **Note** that in some cases `string.format()` is used to format texts for screen and SRS.
+-- Hence, the `%d`, `%s` and `%f` special characters need to appear in the exact same amount and order of appearance in the localized text or it will create errors.
+-- To add a localization, the following texts need to be translated and set in your mission script **before** @{#AWACS.Start}():
+--
+-- AWACS.Messages = {
+-- EN =
+-- {
+-- DEFEND = "%s, %s! %s! %s! Defend!",
+-- VECTORTO = "%s, %s. Vector%s %s",
+-- VECTORTOTTS = "%s, %s, Vector%s %s",
+-- ANGELS = ". Angels ",
+-- ZERO = "zero",
+-- VANISHED = "%s, %s Group. Vanished.",
+-- VANISHEDTTS = "%s, %s group vanished.",
+-- SHIFTCHANGE = "%s shift change for %s control.",
+-- GROUPCAP = "Group",
+-- GROUP = "group",
+-- MILES = "miles",
+-- THOUSAND = "thousand",
+-- BOGEY = "Bogey",
+-- ALLSTATIONS = "All Stations",
+-- PICCLEAN = "%s. %s. Picture Clean.",
+-- PICTURE = "Picture",
+-- ONE = "One",
+-- GROUPMULTI = "groups",
+-- NOTCHECKEDIN = "%s. %s. Negative. You are not checked in.",
+-- CLEAN = "%s. %s. Clean.",
+-- DOPE = "%s. %s. Bogey Dope. ",
+-- VIDPOS = "%s. %s. Copy, target identified as %s.",
+-- VIDNEG = "%s. %s. Negative, get closer to target.",
+-- FFNEUTRAL = "Neutral",
+-- FFFRIEND = "Friendly",
+-- FFHOSTILE = "Hostile",
+-- FFSPADES = "Spades",
+-- FFCLEAN = "Clean",
+-- COPY = "%s. %s. Copy.",
+-- TARGETEDBY = "Targeted by %s.",
+-- STATUS = "Status",
+-- ALREADYCHECKEDIN = "%s. %s. Negative. You are already checked in.",
+-- ALPHACHECK = "Alpha Check",
+-- CHECKINAI = "%s. %s. Checking in as fragged. Expected playtime %d hours. Request Alpha Check %s.",
+-- SAFEFLIGHT = "%s. %s. Copy. Have a safe flight home.",
+-- VERYLOW = "very low",
+-- AIONSTATION = "%s. %s. On station over anchor %d at angels %d. Ready for tasking.",
+-- POPUP = "Pop-up",
+-- NEWGROUP = "New group",
+-- HIGH= " High.",
+-- VERYFAST = " Very fast.",
+-- FAST = " Fast.",
+-- THREAT = "Threat",
+-- MERGED = "Merged",
+-- SCREENVID = "Intercept and VID %s group.",
+-- SCREENINTER = "Intercept %s group.",
+-- ENGAGETAG = "Targeted by %s.",
+-- REQCOMMIT = "%s. %s group. %s. %s, request commit.",
+-- AICOMMIT = "%s. %s group. %s. %s, commit.",
+-- COMMIT = "Commit",
+-- SUNRISE = "%s. All stations, SUNRISE SUNRISE SUNRISE, %s.",
+-- AWONSTATION = "%s on station for %s control.",
+-- STATIONAT = "%s. %s. Station at %s at angels %d.",
+-- STATIONATLONG = "%s. %s. Station at %s at angels %d doing %d knots.",
+-- STATIONSCREEN = "%s. %s.\nStation at %s\nAngels %d\nSpeed %d knots\nCoord %s\nROE %s.",
+-- STATIONTASK = "Station at %s\nAngels %d\nSpeed %d knots\nCoord %s\nROE %s",
+-- VECTORSTATION = " to Station",
+-- TEXTOPTIONS1 = "Lost friendly flight",
+-- TEXTOPTIONS2 = "Vanished friendly flight",
+-- TEXTOPTIONS3 = "Faded friendly contact",
+-- TEXTOPTIONS4 = "Lost contact with",
+-- },
+-- }
+--
+-- e.g.
+--
+-- testawacs.Messages = {
+-- DE = {
+-- ...
+-- FFNEUTRAL = "Neutral",
+-- FFFRIEND = "Freund",
+-- FFHOSTILE = "Feind",
+-- FFSPADES = "Uneindeutig",
+-- FFCLEAN = "Sauber",
+-- ...
+-- },
+--
+-- ## 12 Discussion
--
-- If you have questions or suggestions, please visit the [MOOSE Discord](https://discord.gg/AeYAkHP) #ops-awacs channel.
--
@@ -401,7 +494,7 @@ do
-- @field #AWACS
AWACS = {
ClassName = "AWACS", -- #string
- version = "beta 0.2.33", -- #string
+ version = "0.2.40", -- #string
lid = "", -- #string
coalition = coalition.side.BLUE, -- #number
coalitiontxt = "blue", -- #string
@@ -485,6 +578,7 @@ AWACS = {
PlayerStationName = nil,
GCI = false,
GCIGroup = nil,
+ locale = "en",
}
---
@@ -606,6 +700,76 @@ AWACS.CapVoices = {
[9] = "en-US-Wavenet-J",
[10] = "en-US-Wavenet-H",
}
+
+---
+-- @field Messages
+AWACS.Messages = {
+ EN =
+ {
+ DEFEND = "%s, %s! %s! %s! Defend!",
+ VECTORTO = "%s, %s. Vector%s %s",
+ VECTORTOTTS = "%s, %s, Vector%s %s",
+ ANGELS = ". Angels ",
+ ZERO = "zero",
+ VANISHED = "%s, %s Group. Vanished.",
+ VANISHEDTTS = "%s, %s group vanished.",
+ SHIFTCHANGE = "%s shift change for %s control.",
+ GROUPCAP = "Group",
+ GROUP = "group",
+ MILES = "miles",
+ THOUSAND = "thousand",
+ BOGEY = "Bogey",
+ ALLSTATIONS = "All Stations",
+ PICCLEAN = "%s. %s. Picture Clean.",
+ PICTURE = "Picture",
+ ONE = "One",
+ GROUPMULTI = "groups",
+ NOTCHECKEDIN = "%s. %s. Negative. You are not checked in.",
+ CLEAN = "%s. %s. Clean.",
+ DOPE = "%s. %s. Bogey Dope. ",
+ VIDPOS = "%s. %s. Copy, target identified as %s.",
+ VIDNEG = "%s. %s. Negative, get closer to target.",
+ FFNEUTRAL = "Neutral",
+ FFFRIEND = "Friendly",
+ FFHOSTILE = "Hostile",
+ FFSPADES = "Spades",
+ FFCLEAN = "Clean",
+ COPY = "%s. %s. Copy.",
+ TARGETEDBY = "Targeted by %s.",
+ STATUS = "Status",
+ ALREADYCHECKEDIN = "%s. %s. Negative. You are already checked in.",
+ ALPHACHECK = "Alpha Check",
+ CHECKINAI = "%s. %s. Checking in as fragged. Expected playtime %d hours. Request Alpha Check %s.",
+ SAFEFLIGHT = "%s. %s. Copy. Have a safe flight home.",
+ VERYLOW = "very low",
+ AIONSTATION = "%s. %s. On station over anchor %d at angels %d. Ready for tasking.",
+ POPUP = "Pop-up",
+ NEWGROUP = "New group",
+ HIGH= " High.",
+ VERYFAST = " Very fast.",
+ FAST = " Fast.",
+ THREAT = "Threat",
+ MERGED = "Merged",
+ SCREENVID = "Intercept and VID %s group.",
+ SCREENINTER = "Intercept %s group.",
+ ENGAGETAG = "Targeted by %s.",
+ REQCOMMIT = "%s. %s group. %s. %s, request commit.",
+ AICOMMIT = "%s. %s group. %s. %s, commit.",
+ COMMIT = "Commit",
+ SUNRISE = "%s. All stations, SUNRISE SUNRISE SUNRISE, %s.",
+ AWONSTATION = "%s on station for %s control.",
+ STATIONAT = "%s. %s. Station at %s at angels %d.",
+ STATIONATLONG = "%s. %s. Station at %s at angels %d doing %d knots.",
+ STATIONSCREEN = "%s. %s.\nStation at %s\nAngels %d\nSpeed %d knots\nCoord %s\nROE %s.",
+ STATIONTASK = "Station at %s\nAngels %d\nSpeed %d knots\nCoord %s\nROE %s",
+ VECTORSTATION = " to Station",
+ TEXTOPTIONS1 = "Lost friendly flight",
+ TEXTOPTIONS2 = "Vanished friendly flight",
+ TEXTOPTIONS3 = "Faded friendly contact",
+ TEXTOPTIONS4 = "Lost contact with",
+ },
+}
+
---
-- @type AWACS.MonitoringData
-- @field #string AwacsStateMission
@@ -847,7 +1011,7 @@ function AWACS:New(Name,AirWing,Coalition,AirbaseName,AwacsOrbit,OpsZone,Station
elseif type(OpsZone) == "table" and OpsZone.ClassName and string.find(OpsZone.ClassName,"ZONE") then
self.OpsZone = OpsZone
else
- self:E("AWACS - Invalid OpsZone passed!")
+ self:E("AWACS - Invalid Zone passed!")
return
end
@@ -1053,6 +1217,7 @@ function AWACS:New(Name,AirWing,Coalition,AirbaseName,AwacsOrbit,OpsZone,Station
-- Missile warning
self:HandleEvent(EVENTS.Shot, self._EventHandler)
+ self:_InitLocalization()
------------------------
--- Pseudo Functions ---
@@ -1174,6 +1339,34 @@ end
-- Functions
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+--- [Internal] Init localization
+-- @param #AWACS self
+-- @return #AWACS self
+function AWACS:_InitLocalization()
+ self:T(self.lid.."_InitLocalization")
+ self.gettext = TEXTANDSOUND:New("AWACS","en") -- Core.TextAndSound#TEXTANDSOUND
+ self.locale = "en"
+ for locale,table in pairs(self.Messages) do
+ local Locale = string.lower(tostring(locale))
+ self:T("**** Adding locale: "..Locale)
+ for ID,Text in pairs(table) do
+ self:T(string.format('Adding ID %s',tostring(ID)))
+ self.gettext:AddEntry(Locale,tostring(ID),Text)
+ end
+ end
+ return self
+end
+
+--- [User] Set locale for localization. Defaults to "en"
+-- @param #AWACS self
+-- @param #string Locale The locale to use
+-- @return #AWACS self
+function AWACS:SetLocale(Locale)
+ self:T(self.lid.."SetLocale")
+ self.locale = Locale or "en"
+ return self
+end
+
--- [User] Set this instance to act as GCI TACS Theater Air Control System
-- @param #AWACS self
-- @param Wrapper.Group#GROUP EWR The **main** Early Warning Radar (EWR) GROUP object for GCI.
@@ -1376,15 +1569,15 @@ function AWACS:_EventHandler(EventData)
if Event.id == EVENTS.Shot and self.PlayerGuidance and not self.NoMissileCalls then
if Event.IniCoalition ~= self.coalition then
self:T("Shot from: " .. Event.IniGroupName)
- --self:T(UTILS.OneLineSerialize(Event))
+
local position = Event.IniGroup:GetCoordinate()
if not position then return self end
- --self:T("Coalition = " .. UTILS.GetCoalitionName(Event.IniCoalition))
+
-- Check missile type
local Category = Event.WeaponCategory
local WeaponDesc = EventData.Weapon:getDesc() -- https://wiki.hoggitworld.com/view/DCS_enum_weapon
self:T({WeaponDesc})
- --self:T("Weapon = " .. tostring(WeaponDesc.displayName))
+
if WeaponDesc.category == 1 and (WeaponDesc.missileCategory == 1 or WeaponDesc.missileCategory == 2) then
self:T("AAM or SAM Missile fired")
-- Missile fired
@@ -1422,20 +1615,22 @@ end
-- @return #AWACS self
function AWACS:_MissileWarning(Coordinate,Type,Warndist)
self:T(self.lid.."_MissileWarning Type="..Type.." WarnDist="..Warndist)
- --self:T(UTILS.OneLineSerialize(Coordinate))
+
if not Coordinate then return self end
local shotzone = ZONE_RADIUS:New("WarningZone",Coordinate:GetVec2(),UTILS.NMToMeters(Warndist))
local targetgrpset = SET_GROUP:New():FilterCoalitions(self.coalitiontxt):FilterCategoryAirplane():FilterActive():FilterZones({shotzone}):FilterOnce()
if targetgrpset:Count() > 0 then
local targets = targetgrpset:GetSetObjects()
for _,_grp in pairs (targets) do
- -- TODO -- player callouts only
+ -- DONE -- player callouts only
if _grp and _grp:IsAlive() then
local isPlayer = _grp:IsPlayer()
- --if self.debug or isPlayer then
+
if isPlayer then
local callsign = self:_GetCallSign(_grp)
- local text = string.format("%s, %s! %s! %s! Defend!",callsign,Type,Type,Type)
+ local defend = self.gettext:GetEntry("DEFEND",self.locale)
+ --local text = string.format("%s, %s! %s! %s! Defend!",callsign,Type,Type,Type)
+ local text = string.format(defend,callsign,Type,Type,Type)
self:_NewRadioEntry(text, text,0,false,self.debug,true,false,true)
end
end
@@ -1750,12 +1945,21 @@ function AWACS:_MessageVector(GID,Tag,Coordinate,Angels)
--local BRtext = Coordinate:ToStringBR(groupposition)
local BRtext,BRtextTTS = self:_ToStringBR(groupposition,Coordinate)
- local text = string.format("%s, %s. Vector%s %s",tocallsign, self.callsigntxt,Tag,BRtextTTS)
- local textScreen = string.format("%s, %s, Vector%s %s",tocallsign, self.callsigntxt,Tag,BRtext)
+ local vector = self.gettext:GetEntry("VECTORTO",self.locale)
+ local vectortts = self.gettext:GetEntry("VECTORTOTTS",self.locale)
+ local angelstxt = self.gettext:GetEntry("ANGELS",self.locale)
+
+ --local text = string.format("%s, %s. Vector%s %s",tocallsign, self.callsigntxt,Tag,BRtextTTS)
+ --local textScreen = string.format("%s, %s, Vector%s %s",tocallsign, self.callsigntxt,Tag,BRtext)
+
+ local text = string.format(vectortts,tocallsign, self.callsigntxt,Tag,BRtextTTS)
+ local textScreen = string.format(vector,tocallsign, self.callsigntxt,Tag,BRtext)
if Angels then
- text = text .. ". Angels "..tostring(Angels).."."
- textScreen = textScreen .. ". Angels "..tostring(Angels).."."
+ --text = text .. ". Angels "..tostring(Angels).."."
+ --textScreen = textScreen .. ". Angels "..tostring(Angels).."."
+ text = text .. angelstxt ..tostring(Angels).."."
+ textScreen = textScreen ..angelstxt..tostring(Angels).."."
end
self:_NewRadioEntry(text,textScreen,0,false,self.debug,true,false)
@@ -1870,24 +2074,22 @@ function AWACS:_StartSettings(FlightGroup,Mission)
group:SetCommandInvisible(self.invisible)
group:SetCommandImmortal(self.immortal)
group:CommandSetCallsign(self.CallSign,self.CallSignNo,2)
- -- Non AWACS does not seem take AWACS CS in DCS Group
- -- group:CommandSetCallsign(CALLSIGN.Aircraft.Pig,self.CallSignNo,2)
AwacsFG:SetSRS(self.PathToSRS,self.Gender,self.Culture,self.Voice,self.Port,nil,"AWACS")
- --self.callsigntxt = string.format("%s %d %d",AWACS.CallSignClear[self.CallSign],1,self.CallSignNo)
+
self.callsigntxt = string.format("%s",AWACS.CallSignClear[self.CallSign])
- local text = string.format("%s shift change for %s control.",self.callsigntxt,self.AOName or "Rock")
+ local shifting = self.gettext:GetEntry("SHIFTCHANGE",self.locale)
+
+ local text = string.format(shifting,self.callsigntxt,self.AOName or "Rock")
+
self:T(self.lid..text)
AwacsFG:RadioTransmission(text,1,false)
self.AwacsFG = AwacsFG
- --self:__CheckRadioQueue(10)
-
if self.HasEscorts then
- --mission:SetRequiredEscorts(self.EscortNumber)
self:_StartEscorts(true)
end
@@ -1907,9 +2109,8 @@ end
-- @param #boolean TTS For non-Alpha checks, hand back in format "Rock 0 2 1, 16"
-- @return #string BullseyeBR
function AWACS:_ToStringBULLS( Coordinate, ssml, TTS )
- -- local BullsCoordinate = COORDINATE:NewFromVec3( coalition.getMainRefPoint( self.coalition ) )
+ self:T(self.lid.."_ToStringBULLS")
local bullseyename = self.AOName or "Rock"
- --local BullsCoordinate = self.OpsZone:GetCoordinate()
local BullsCoordinate = self.AOCoordinate
local DirectionVec3 = BullsCoordinate:GetDirectionVec3( Coordinate )
local AngleRadians = Coordinate:GetAngleRadians( DirectionVec3 )
@@ -1921,7 +2122,8 @@ function AWACS:_ToStringBULLS( Coordinate, ssml, TTS )
return string.format("%s %03d, %d",bullseyename,Bearing,Distance)
elseif TTS then
Bearing = self:_ToStringBullsTTS(Bearing)
- local BearingTTS = string.gsub(Bearing,"0","zero")
+ local zero = self.gettext:GetEntry("ZERO",self.locale)
+ local BearingTTS = string.gsub(Bearing,"0",zero)
return string.format("%s %s, %d",bullseyename,BearingTTS,Distance)
else
return string.format("%s %s, %d",bullseyename,Bearing,Distance)
@@ -1974,8 +2176,9 @@ end
-- @param #AWACS self
-- @param Wrapper.Group#GROUP Group Group to use
-- @param #number GID GID to use
+-- @param #booean IsPlayer Check in player if true
-- @return #string Callsign
-function AWACS:_GetCallSign(Group,GID)
+function AWACS:_GetCallSign(Group,GID, IsPlayer)
self:T(self.lid.."_GetCallSign - GID "..tostring(GID))
if GID and type(GID) == "number" and GID > 0 then
@@ -1988,18 +2191,26 @@ function AWACS:_GetCallSign(Group,GID)
if Group and Group:IsAlive() then
local shortcallsign = Group:GetCallsign() or "unknown11"-- e.g.Uzi11, but we want Uzi 1 1
local callsignroot = string.match(shortcallsign, '(%a+)')
- if self.callsignTranslations and self.callsignTranslations[callsignroot] then
- shortcallsign = string.gsub(shortcallsign, callsignroot, self.callsignTranslations[callsignroot])
- end
-
+ self:I("CallSign = " .. callsignroot)
local groupname = Group:GetName()
local callnumber = string.match(shortcallsign, "(%d+)$" ) or "unknown11"
local callnumbermajor = string.char(string.byte(callnumber,1))
local callnumberminor = string.char(string.byte(callnumber,2))
- if string.find(groupname,"#") then
+ local personalized = false
+ if IsPlayer and string.find(groupname,"#") then
-- personalized flight name in group naming
shortcallsign = string.match(groupname,"#([%a]+)")
+ personalized = true
end
+ if IsPlayer and string.find(Group:GetPlayerName(),"|") then
+ -- personalized flight name in group naming
+ shortcallsign = string.match(Group:GetPlayerName(),"| ([%a]+)")
+ personalized = true
+ end
+ if (not personalized) and self.callsignTranslations and self.callsignTranslations[callsignroot] then
+ shortcallsign = string.gsub(shortcallsign, callsignroot, self.callsignTranslations[callsignroot])
+ end
+
if self.callsignshort then
callsign = string.gsub(shortcallsign,callnumber,"").." "..callnumbermajor
else
@@ -2101,8 +2312,10 @@ function AWACS:_CleanUpContacts()
deadcontacts:ForEach(
function (Contact)
local contact = Contact -- #AWACS.ManagedContact
- local text = string.format("%s, %s Group. Vanished.",self.callsigntxt, contact.TargetGroupNaming)
- local textScreen = string.format("%s, %s group vanished.", self.callsigntxt, contact.TargetGroupNaming)
+ local vanished = self.gettext:GetEntry("VANISHED",self.locale)
+ local vanishedtts = self.gettext:GetEntry("VANISHEDTTS",self.locale)
+ local text = string.format(vanishedtts,self.callsigntxt, contact.TargetGroupNaming)
+ local textScreen = string.format(vanished, self.callsigntxt, contact.TargetGroupNaming)
self:_NewRadioEntry(text,textScreen,0,false,self.debug,true,false,true)
self.Contacts:PullByID(contact.CID)
-- end
@@ -2374,21 +2587,27 @@ function AWACS:_CreatePicture(AO,Callsign,GID,MaxEntries,IsGeneral)
local refBRAATTS = ""
if self.NoGroupTags then
- text = "Group." -- Alpha Group.
- textScreen = "Group,"
+ local grouptxt = self.gettext:GetEntry("GROUPCAP",self.locale)
+ text = grouptxt .. "." -- Alpha Group.
+ textScreen = grouptxt ..","
else
- text = contact.TargetGroupNaming.." group." -- Alpha Group.
- textScreen = contact.TargetGroupNaming.." group,"
+ local grouptxt = self.gettext:GetEntry("GROUP",self.locale)
+ text = contact.TargetGroupNaming.." "..grouptxt.."." -- Alpha Group.
+ textScreen = contact.TargetGroupNaming.." "..grouptxt..","
end
if IsGeneral or not self.PlayerGuidance then
+ local milestxt = self.gettext:GetEntry("MILES",self.locale)
+ local thsdtxt = self.gettext:GetEntry("THOUSAND",self.locale)
refBRAA=self:_ToStringBULLS(coordinate)
refBRAATTS = self:_ToStringBULLS(coordinate, false, true)
local alt = contact.Contact.group:GetAltitude() or 8000
alt = UTILS.Round(UTILS.MetersToFeet(alt)/1000,0)
-- Alpha Group. Bulls eye 0 2 1, 16 miles, 25 thousand.
- text = text .. " "..refBRAATTS.." miles, "..alt.." thousand." -- Alpha Group. Bulls eye 0 2 1, 16 miles, 25 thousand.
- textScreen = textScreen .. " "..refBRAA.." miles, "..alt.." thousand." -- Alpha Group, Bullseye 021, 16 miles, 25 thousand,
+ --text = text .. " "..refBRAATTS.." miles, "..alt.." thousand." -- Alpha Group. Bulls eye 0 2 1, 16 miles, 25 thousand.
+ text = string.format("%s %s %s, %d %s.",text,refBRAATTS,milestxt,alt,thsdtxt)
+ --textScreen = textScreen .. " "..refBRAA.." miles, "..alt.." thousand." -- Alpha Group, Bullseye 021, 16 miles, 25 thousand,
+ textScreen = string.format("%s %s %s, %d %s.",textScreen,refBRAA,milestxt,alt,thsdtxt)
else
-- pilot reference
refBRAA = coordinate:ToStringBRAANATO(groupcoord,true,true)
@@ -2399,8 +2618,9 @@ function AWACS:_CreatePicture(AO,Callsign,GID,MaxEntries,IsGeneral)
refBRAATTS = coordinate:ToStringBRAANATO(groupcoord,true,true,true,false,true)
end
if contact.IFF ~= AWACS.IFF.BOGEY then
- refBRAA = string.gsub(refBRAA,"Bogey", contact.IFF)
- refBRAATTS = string.gsub(refBRAATTS,"Bogey", contact.IFF)
+ local bogey = self.gettext:GetEntry("BOGEY",self.locale)
+ refBRAA = string.gsub(refBRAA,bogey, contact.IFF)
+ refBRAATTS = string.gsub(refBRAATTS,bogey, contact.IFF)
end
text = text .. " "..refBRAATTS
textScreen = textScreen .." "..refBRAA
@@ -2499,9 +2719,8 @@ function AWACS:_Picture(Group,IsGeneral)
--local gcallsign = ""
if general then
- gcallsign = "All Stations"
- --else
- --gcallsign = self:_GetCallSign(Group,GID) or "Ghost 1"
+ local allst = self.gettext:GetEntry("ALLSTATIONS",self.locale)
+ gcallsign = allst
end
if Group and Outcome then
@@ -2510,7 +2729,8 @@ function AWACS:_Picture(Group,IsGeneral)
if not self.intel then
-- no intel yet!
- text = string.format("%s. %s. Picture Clean.",self.callsigntxt, gcallsign)
+ local picclean = self.gettext:GetEntry("PICCLEAN",self.locale)
+ text = string.format(picclean,self.callsigntxt, gcallsign)
textScreen = text
self:_NewRadioEntry(text,text,GID,false,true,true,false)
@@ -2521,7 +2741,6 @@ function AWACS:_Picture(Group,IsGeneral)
if Outcome or general then
-- Pilot is checked in
-- get clusters from Intel
- -- DONE Use contacts table!
local contactstable = self.Contacts:GetDataTable()
--local clustertable = self.intel:GetClusterTable() or {}
@@ -2529,12 +2748,8 @@ function AWACS:_Picture(Group,IsGeneral)
for _,_contact in pairs(contactstable) do
local contact = _contact -- #AWACS.ManagedContact
-
- --self:T(UTILS.OneLineSerialize(contact))
-
- local coordVec2 = contact.Contact.position:GetVec2()
-
- --local coordVec2 = cluster.coordinate:GetVec2()
+
+ local coordVec2 = contact.Contact.position:GetVec2()
if self.OpsZone:IsVec2InZone(coordVec2) then
self.PictureAO:Push(contact)
@@ -2573,19 +2788,22 @@ function AWACS:_Picture(Group,IsGeneral)
else
if clustersAO > 0 then
- --if general then
- --text = string.format("%s, %s. ",gcallsign, self.callsigntxt)
- --textScreen = string.format("%s, %s. ",gcallsign, self.callsigntxt)
- --else
- text = string.format("%s, %s. Picture. ",gcallsign, self.callsigntxt)
- textScreen = string.format("%s, %s. Picture. ",gcallsign, self.callsigntxt)
- --end
+ local picture = self.gettext:GetEntry("PICTURE",self.locale)
+ text = string.format("%s, %s. %s. ",gcallsign, self.callsigntxt,picture)
+ textScreen = string.format("%s, %s. %s. ",gcallsign, self.callsigntxt,picture)
+ local onetxt = self.gettext:GetEntry("ONE",self.locale)
+ local grptxt = self.gettext:GetEntry("GROUP",self.locale)
+ local groupstxt = self.gettext:GetEntry("GROUPMULTI",self.locale)
if clustersAO == 1 then
- text = text .. "One group. "
- textScreen = textScreen .. "One group.\n"
+ --text = text .. "One group. "
+ text = string.format("%s%s %s. ",text,onetxt,grptxt)
+ --textScreen = textScreen .. "One group.\n"
+ textScreen = string.format("%s%s %s.\n",textScreen,onetxt,grptxt)
else
- text = text .. clustersAO .. " groups. "
- textScreen = textScreen .. clustersAO .. " groups.\n"
+ text = string.format("%s%d %s. ",text,clustersAO,groupstxt)
+ --text = text .. clustersAO .. " groups. "
+ textScreen = string.format("%s%d %s.\n",textScreen,clustersAO,groupstxt)
+ --textScreen = textScreen .. clustersAO .. " groups.\n"
end
self:_NewRadioEntry(text,textScreen,GID,Outcome,true,true,false)
@@ -2598,7 +2816,8 @@ function AWACS:_Picture(Group,IsGeneral)
elseif self.AwacsFG then
-- no, unknown
- text = string.format("%s. %s. Negative. You are not checked in.",gcallsign, self.callsigntxt)
+ local nocheckin = self.gettext:GetEntry("NOTCHECKEDIN",self.locale)
+ text = string.format(nocheckin,gcallsign, self.callsigntxt)
self:_NewRadioEntry(text,text,GID,Outcome,true,true,false)
end
return self
@@ -2617,7 +2836,8 @@ function AWACS:_BogeyDope(Group)
if not self.intel then
-- no intel yet!
- text = string.format("%s. %s. Clean.",self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt)
+ local clean = self.gettext:GetEntry("CLEAN",self.locale)
+ text = string.format(clean,self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt)
self:_NewRadioEntry(text,text,0,false,true,true,false,true)
return self
@@ -2630,7 +2850,6 @@ function AWACS:_BogeyDope(Group)
local pilotgroup = managedgroup.Group
local pilotcoord = managedgroup.Group:GetCoordinate()
- -- TODO - Use known contacts
local contactstable = self.Contacts:GetDataTable()
-- sort into buckets - AO only for bogey dope!
@@ -2659,15 +2878,17 @@ function AWACS:_BogeyDope(Group)
if contactsAO == 0 then
-- clean
-
- text = string.format("%s. %s. Clean.",self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt)
+ local clean = self.gettext:GetEntry("CLEAN",self.locale)
+ text = string.format(clean,self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt)
self:_NewRadioEntry(text,textScreen,GID,Outcome,Outcome,true,false,true)
else
if contactsAO > 0 then
- text = string.format("%s. %s. Bogey Dope. ",self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt)
+ local dope = self.gettext:GetEntry("DOPE",self.locale)
+ text = string.format(dope,self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt)
+ --[[
if contactsAO == 1 then
text = text .. "One group. "
textScreen = text .. "\n"
@@ -2675,7 +2896,22 @@ function AWACS:_BogeyDope(Group)
text = text .. contactsAO .. " groups. "
textScreen = textScreen .. contactsAO .. " groups.\n"
end
-
+ --]]
+ local onetxt = self.gettext:GetEntry("ONE",self.locale)
+ local grptxt = self.gettext:GetEntry("GROUP",self.locale)
+ local groupstxt = self.gettext:GetEntry("GROUPMULTI",self.locale)
+ if contactsAO == 1 then
+ --text = text .. "One group. "
+ text = string.format("%s%s %s. ",text,onetxt,grptxt)
+ --textScreen = textScreen .. "One group.\n"
+ textScreen = string.format("%s%s %s.\n",textScreen,onetxt,grptxt)
+ else
+ text = string.format("%s%d %s. ",text,contactsAO,groupstxt)
+ --text = text .. clustersAO .. " groups. "
+ textScreen = string.format("%s%d %s.\n",textScreen,contactsAO,groupstxt)
+ --textScreen = textScreen .. clustersAO .. " groups.\n"
+ end
+
self:_NewRadioEntry(text,textScreen,GID,Outcome,true,true,false,true)
self:_CreateBogeyDope(self:_GetCallSign(Group,GID) or "Ghost 1",GID)
@@ -2684,8 +2920,9 @@ function AWACS:_BogeyDope(Group)
elseif self.AwacsFG then
-- no, unknown
- text = string.format("%s. %s. Negative. You are not checked in.",self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt)
-
+ --text = string.format("%s. %s. Negative. You are not checked in.",self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt)
+ local nocheckin = self.gettext:GetEntry("NOTCHECKEDIN",self.locale)
+ text = string.format(nocheckin,self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt)
self:_NewRadioEntry(text,text,GID,Outcome,true,true,false)
end
@@ -2763,12 +3000,14 @@ function AWACS:_VID(Group,Declaration)
self.ManagedTasks:Push(task,TID)
self.Contacts:PullByID(CID)
self.Contacts:Push(cluster,CID)
- text = string.format("%s. %s. Copy, target identified as %s.",Callsign,self.callsigntxt, Declaration)
+ local vidpos = self.gettext:GetEntry("VIDPOS",self.locale)
+ text = string.format(vidpos,Callsign,self.callsigntxt, Declaration)
self:T(text)
else
-- too far away
self:T("Contact VID not close enough")
- text = string.format("%s. %s. Negative, get closer to target.",Callsign,self.callsigntxt)
+ local vidneg = self.gettext:GetEntry("VIDNEG",self.locale)
+ text = string.format(vidneg,Callsign,self.callsigntxt)
self:T(text)
end
self:_NewRadioEntry(text,text,GID,Outcome,true,true,false,true)
@@ -2777,7 +3016,8 @@ function AWACS:_VID(Group,Declaration)
--
elseif self.AwacsFG then
-- no, unknown
- text = string.format("%s. %s. Negative. You are not checked in.",self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt)
+ local nocheckin = self.gettext:GetEntry("NOTCHECKEDIN",self.locale)
+ text = string.format(nocheckin,self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt)
self:_NewRadioEntry(text,text,GID,Outcome,true,true,false)
end
return self
@@ -2828,17 +3068,22 @@ function AWACS:_Declare(Group)
local ccoalition = contact:GetCoalition()
local ctypename = contact:GetTypeName()
- local friendorfoe = "Neutral"
+ local ffneutral = self.gettext:GetEntry("FFNEUTRAL",self.locale)
+ local fffriend = self.gettext:GetEntry("FFFRIEND",self.locale)
+ local ffhostile = self.gettext:GetEntry("FFHOSTILE",self.locale)
+ local ffspades = self.gettext:GetEntry("FFSPADES",self.locale)
+
+ local friendorfoe = ffneutral
if self.self.ModernEra then
if ccoalition == self.coalition then
- friendorfoe = "Friendly"
+ friendorfoe = fffriend
elseif ccoalition == coalition.side.NEUTRAL then
- friendorfoe = "Neutral"
+ friendorfoe = ffneutral
elseif ccoalition ~= self.coalition then
- friendorfoe = "Hostile"
+ friendorfoe = ffhostile
end
else
- friendorfoe = "Spades"
+ friendorfoe = ffspades
end
-- see if that works
self:T(string.format("Distance %d ContactName %s Coalition %d (%s) TypeName %s",distanz,contact:GetName(),ccoalition,friendorfoe,ctypename))
@@ -2852,14 +3097,16 @@ function AWACS:_Declare(Group)
end
else
-- clean
- text = string.format("%s. %s. %s.",Callsign,self.callsigntxt,"Clean")
+ local ffclean = self.gettext:GetEntry("FFCLEAN",self.locale)
+ text = string.format("%s. %s. %s.",Callsign,self.callsigntxt,ffclean)
TextTTS = text
end
self:_NewRadioEntry(TextTTS,text,GID,Outcome,true,true,false,true)
--
elseif self.AwacsFG then
-- no, unknown
- text = string.format("%s. %s. Negative. You are not checked in.",self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt)
+ local nocheckin = self.gettext:GetEntry("NOTCHECKEDIN",self.locale)
+ text = string.format(nocheckin,self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt)
self:_NewRadioEntry(text,text,GID,Outcome,true,true,false)
end
return self
@@ -2891,8 +3138,10 @@ function AWACS:_Commit(Group)
Pilot.HasAssignedTask = true
Pilot.CurrentTask = currtaskid
self.ManagedGrps[GID] = Pilot
- text = string.format("%s. %s. Copy.",self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt)
- local EngagementTag = string.format("Targeted by %s.",Pilot.CallSign)
+ local copy = self.gettext:GetEntry("COPY",self.locale)
+ local targetedby = self.gettext:GetEntry("TARGETEDBY",self.locale)
+ text = string.format(copy,self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt)
+ local EngagementTag = string.format(targetedby,Pilot.CallSign)
self:_UpdateContactEngagementTag(Pilot.ContactCID,EngagementTag,false,false,AWACS.TaskStatus.ASSIGNED)
self:_NewRadioEntry(text,text,GID,Outcome,true,true,false,true)
else
@@ -2903,7 +3152,8 @@ function AWACS:_Commit(Group)
end
elseif self.AwacsFG then
-- no, unknown
- text = string.format("%s. %s. Negative. You are not checked in.",self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt)
+ local nocheckin = self.gettext:GetEntry("NOTCHECKEDIN",self.locale)
+ text = string.format(nocheckin,self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt)
self:_NewRadioEntry(text,text,GID,Outcome,true,true,false)
end
return self
@@ -2929,8 +3179,10 @@ function AWACS:_Judy(Group)
managedtask = self.ManagedTasks:PullByID(currtaskid)
managedtask.Status = AWACS.TaskStatus.ASSIGNED
self.ManagedTasks:Push(managedtask,currtaskid)
- text = string.format("%s. %s. Copy.",self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt)
- local EngagementTag = string.format("Targeted by %s.",Pilot.CallSign)
+ local copy = self.gettext:GetEntry("COPY",self.locale)
+ local targetedby = self.gettext:GetEntry("TARGETEDBY",self.locale)
+ text = string.format(copy,self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt)
+ local EngagementTag = string.format(targetedby,Pilot.CallSign)
self:_UpdateContactEngagementTag(Pilot.ContactCID,EngagementTag,false,false,AWACS.TaskStatus.ASSIGNED)
self:_NewRadioEntry(text,text,GID,Outcome,true,true,false,true)
else
@@ -2941,7 +3193,8 @@ function AWACS:_Judy(Group)
end
elseif self.AwacsFG then
-- no, unknown
- text = string.format("%s. %s. Negative. You are not checked in.",self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt)
+ local nocheckin = self.gettext:GetEntry("NOTCHECKEDIN",self.locale)
+ text = string.format(nocheckin,self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt)
self:_NewRadioEntry(text,text,GID,Outcome,true,true,false)
end
return self
@@ -2976,7 +3229,8 @@ function AWACS:_Unable(Group)
Pilot.CurrentTask = 0
Pilot.LastTasking = timer.getTime()
self.ManagedGrps[GID] = Pilot
- text = string.format("%s. %s. Copy.",self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt)
+ local copy = self.gettext:GetEntry("COPY",self.locale)
+ text = string.format(copy,self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt)
local EngagementTag = ""
self:_UpdateContactEngagementTag(Pilot.ContactCID,EngagementTag,false,false,AWACS.TaskStatus.UNASSIGNED)
self:_NewRadioEntry(text,text,GID,Outcome,true,true,false,true)
@@ -2988,7 +3242,8 @@ function AWACS:_Unable(Group)
end
elseif self.AwacsFG then
-- no, unknown
- text = string.format("%s. %s. Negative. You are not checked in.",self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt)
+ local nocheckin = self.gettext:GetEntry("NOTCHECKEDIN",self.locale)
+ text = string.format(nocheckin,self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt)
self:_NewRadioEntry(text,text,GID,Outcome,true,true,false)
end
return self
@@ -3026,7 +3281,8 @@ function AWACS:_TaskAbort(Group)
Pilot.CurrentTask = 0
Pilot.LastTasking = timer.getTime()
self.ManagedGrps[GID] = Pilot
- text = string.format("%s. %s. Copy.",self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt)
+ local copy = self.gettext:GetEntry("COPY",self.locale)
+ text = string.format(copy,self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt)
local EngagementTag = ""
self:_UpdateContactEngagementTag(Pilot.ContactCID,EngagementTag,false,false,AWACS.TaskStatus.UNASSIGNED)
self:_NewRadioEntry(text,text,GID,Outcome,true,true,false,true)
@@ -3038,7 +3294,8 @@ function AWACS:_TaskAbort(Group)
end
elseif self.AwacsFG then
-- no, unknown
- text = string.format("%s. %s. Negative. You are not checked in.",self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt)
+ local nocheckin = self.gettext:GetEntry("NOTCHECKEDIN",self.locale)
+ text = string.format(nocheckin,self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt)
self:_NewRadioEntry(text,text,GID,Outcome,true,true,false)
end
@@ -3098,8 +3355,8 @@ function AWACS:_Showtask(Group)
local direction = self:_ToStringBR(pposition,targetpos)
description = description .. "\nBR "..direction
end
-
- MESSAGE:New(string.format("%s\nStatus %s",description,status),30,"AWACS",true):ToGroup(Group)
+ local statustxt = self.gettext:GetEntry("STATUS",self.locale)
+ MESSAGE:New(string.format("%s\n%s %s",description,statustxt,status),30,"AWACS",true):ToGroup(Group)
end
end
@@ -3107,7 +3364,8 @@ function AWACS:_Showtask(Group)
elseif self.AwacsFG then
-- no, unknown
- text = string.format("%s. %s. Negative. You are not checked in.",self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt)
+ local nocheckin = self.gettext:GetEntry("NOTCHECKEDIN",self.locale)
+ text = string.format(nocheckin,self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt)
self:_NewRadioEntry(text,text,GID,Outcome,true,true,false)
end
return self
@@ -3127,17 +3385,15 @@ function AWACS:_CheckIn(Group)
self.ManagedGrpID = self.ManagedGrpID + 1
local managedgroup = {} -- #AWACS.ManagedGroup
managedgroup.Group = Group
- --managedgroup.GroupName = string.match(Group:GetName(),"([%a%s]+)#")
managedgroup.GroupName = Group:GetName()
managedgroup.IsPlayer = true
managedgroup.IsAI = false
- managedgroup.CallSign = self:_GetCallSign(Group,GID) or "Ghost 1"
+ managedgroup.CallSign = self:_GetCallSign(Group,GID,true) or "Ghost 1"
managedgroup.CurrentAuftrag = 0
managedgroup.CurrentTask = 0
managedgroup.HasAssignedTask = true
managedgroup.Blocked = true
managedgroup.GID = self.ManagedGrpID
- --managedgroup.TaskQueue = FIFO:New()
managedgroup.LastKnownPosition = Group:GetCoordinate()
managedgroup.LastTasking = timer.getTime()
@@ -3145,12 +3401,12 @@ function AWACS:_CheckIn(Group)
self.ManagedGrps[self.ManagedGrpID]=managedgroup
local alphacheckbulls = self:_ToStringBULLS(Group:GetCoordinate())
- --local alphacheckbullstts = self:_ToStringBullsTTS(alphacheckbulls)-- make tts friendly
local alphacheckbullstts = self:_ToStringBULLS(Group:GetCoordinate(),false,true)
--self.ManagedGrps[self.ManagedGrpID]=managedgroup
- text = string.format("%s. %s. Alpha Check. %s",managedgroup.CallSign,self.callsigntxt,alphacheckbulls)
- textTTS = string.format("%s. %s. Alpha Check. %s",managedgroup.CallSign,self.callsigntxt,alphacheckbullstts)
+ local alpha = self.gettext:GetEntry("ALPHACHECK",self.locale)
+ text = string.format("%s. %s. %s. %s",managedgroup.CallSign,self.callsigntxt,alpha,alphacheckbulls)
+ textTTS = text
self:__CheckedIn(1,managedgroup.GID)
@@ -3161,7 +3417,9 @@ function AWACS:_CheckIn(Group)
end
elseif self.AwacsFG then
- text = string.format("%s. %s. Negative. You are already checked in.",self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt)
+ local nocheckin = self.gettext:GetEntry("ALREADYCHECKEDIN",self.locale)
+ text = string.format(nocheckin,self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt)
+ textTTS = text
end
self:_NewRadioEntry(textTTS,text,GID,Outcome,true,true,false)
@@ -3189,6 +3447,9 @@ function AWACS:_CheckInAI(FlightGroup,Group,AuftragsNr)
managedgroup.IsPlayer = false
managedgroup.IsAI = true
local callsignstring = UTILS.GetCallsignName(self.AICAPCAllName)
+ if self.callsignTranslations and self.callsignTranslations[callsignstring] then
+ callsignstring = self.callsignTranslations[callsignstring]
+ end
local callsignmajor = math.fmod(self.AICAPCAllNumber,9)
local callsign = string.format("%s %d 1",callsignstring,callsignmajor)
if self.callsignshort then
@@ -3215,14 +3476,15 @@ function AWACS:_CheckInAI(FlightGroup,Group,AuftragsNr)
FlightGroup:SetSRS(self.PathToSRS,self.CAPGender,self.CAPCulture,CAPVoice,self.Port,self.PathToGoogleKey,"FLIGHT")
- text = string.format("%s. %s. Checking in as fragged. Expected playtime %d hours. Request Alpha Check %s.",self.callsigntxt, managedgroup.CallSign, self.CAPTimeOnStation, self.AOName)
+ local checkai = self.gettext:GetEntry("CHECKINAI",self.locale)
+ text = string.format(checkai,self.callsigntxt, managedgroup.CallSign, self.CAPTimeOnStation, self.AOName)
self:_NewRadioEntry(text,text,managedgroup.GID,Outcome,false,true,true)
local alphacheckbulls = self:_ToStringBULLS(Group:GetCoordinate(),false,true)
- --alphacheckbulls = self:_ToStringBullsTTS(alphacheckbulls)-- make tts friendly
-
- text = string.format("%s. %s. Alpha Check. %s",managedgroup.CallSign,self.callsigntxt,alphacheckbulls)
+
+ local alpha = self.gettext:GetEntry("ALPHACHECK",self.locale)
+ text = string.format("%s. %s. %s. %s",managedgroup.CallSign,self.callsigntxt,alpha,alphacheckbulls)
self:__CheckedIn(1,managedgroup.GID)
local AW = FlightGroup:GetAirWing()
@@ -3232,7 +3494,8 @@ function AWACS:_CheckInAI(FlightGroup,Group,AuftragsNr)
self:__AssignAnchor(5,managedgroup.GID)
end
else
- text = string.format("%s. %s. Negative. You are already checked in.",self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt)
+ local nocheckin = self.gettext:GetEntry("ALREADYCHECKEDIN",self.locale)
+ text = string.format(nocheckin,self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt)
end
self:_NewRadioEntry(text,text,GID,Outcome,false,true,false)
@@ -3254,7 +3517,8 @@ function AWACS:_CheckOut(Group,GID,dead)
local text = ""
if Outcome then
-- yes, known
- text = string.format("%s. %s. Copy. Have a safe flight home.",self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt)
+ local safeflight = self.gettext:GetEntry("SAFEFLIGHT",self.locale)
+ text = string.format(safeflight,self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt)
self:T(text)
-- grab some data before we nil the entry
local managedgroup = self.ManagedGrps[GID] -- #AWACS.ManagedGroup
@@ -3279,7 +3543,8 @@ function AWACS:_CheckOut(Group,GID,dead)
else
-- no, unknown
if not dead then
- text = string.format("%s. %s. Negative. You are not checked in.",self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt)
+ local nocheckin = self.gettext:GetEntry("NOTCHECKEDIN",self.locale)
+ text = string.format(nocheckin,self:_GetCallSign(Group,GID) or "Ghost 1", self.callsigntxt)
end
end
@@ -3329,6 +3594,10 @@ function AWACS:_SetClientMenus()
basemenu:RemoveSubMenus()
--basemenu:Refresh()
+ local bogeydope = MENU_GROUP_COMMAND:New(cgrp,"Bogey Dope",basemenu,self._BogeyDope,self,cgrp)
+ local picture = MENU_GROUP_COMMAND:New(cgrp,"Picture",basemenu,self._Picture,self,cgrp)
+ local declare = MENU_GROUP_COMMAND:New(cgrp,"Declare",basemenu,self._Declare,self,cgrp)
+
local tasking = MENU_GROUP:New(cgrp,"Tasking",basemenu)
local showtask = MENU_GROUP_COMMAND:New(cgrp,"Showtask",tasking,self._Showtask,self,cgrp)
local commit = MENU_GROUP_COMMAND:New(cgrp,"Commit",tasking,self._Commit,self,cgrp)
@@ -3343,15 +3612,8 @@ function AWACS:_SetClientMenus()
local friendly = MENU_GROUP_COMMAND:New(cgrp,"Friendly",vid,self._VID,self,cgrp,AWACS.IFF.FRIENDLY)
end
- local picture = MENU_GROUP_COMMAND:New(cgrp,"Picture",basemenu,self._Picture,self,cgrp)
- local bogeydope = MENU_GROUP_COMMAND:New(cgrp,"Bogey Dope",basemenu,self._BogeyDope,self,cgrp)
-
- local declare = MENU_GROUP_COMMAND:New(cgrp,"Declare",basemenu,self._Declare,self,cgrp)
local ainfo = MENU_GROUP_COMMAND:New(cgrp,"Awacs Info",basemenu,self._ShowAwacsInfo,self,cgrp)
local checkout = MENU_GROUP_COMMAND:New(cgrp,"Check Out",basemenu,self._CheckOut,self,cgrp)
-
- --basemenu:Set()
- basemenu:Refresh()
local menus = { -- #AWACS.MenuStructure
groupname = cgrpname,
@@ -3415,7 +3677,6 @@ function AWACS:_SetClientMenus()
local checkin = MENU_GROUP_COMMAND:New(cgrp,"Check In",basemenu,self._CheckIn,self,cgrp)
local checkout = MENU_GROUP_COMMAND:New(cgrp,"Check Out",basemenu,self._CheckOut,self,cgrp)
- --basemenu:Set()
basemenu:Refresh()
local menus = { -- #AWACS.MenuStructure
@@ -3438,8 +3699,7 @@ function AWACS:_SetClientMenus()
end
end
end
-
- --self.clientmenus = clientmenus
+
self.MonitoringData.Players = clientcount or 0
self.MonitoringData.PlayersCheckedin = clientcheckedin or 0
@@ -3702,8 +3962,6 @@ function AWACS:_RemoveIDFromAnchor(GID,AnchorStackNo,Angels)
local removedID = Anchor.AnchorAssignedID:PullByID(GID)
-- push free angels to stack
Anchor.Anchors:Push(Angels)
- -- push back AnchorStack
- --self.AnchorStacks:Push(Anchor)
end
return self
end
@@ -3845,24 +4103,22 @@ function AWACS:_ToStringBR(FromCoordinate,ToCoordinate)
local AngleDegText = string.format("%03d",AngleDegrees) -- 051
local AngleDegTextTTS = ""
- --if self.PathToGoogleKey then
- --AngleDegTextTTS = string.format("%s",AngleDegText)
- --else
- --AngleDegTextTTS = string.format("%s",AngleDegText)
- --end
+ local zero = self.gettext:GetEntry("ZERO",self.locale)
+ local miles = self.gettext:GetEntry("MILES",self.locale)
+
AngleDegText = string.gsub(AngleDegText,"%d","%1 ") -- "0 5 1 "
AngleDegText = string.gsub(AngleDegText," $","") -- "0 5 1"
- AngleDegTextTTS = string.gsub(AngleDegText,"0","zero")
+ AngleDegTextTTS = string.gsub(AngleDegText,"0",zero)
local Distance = ToCoordinate:Get2DDistance( FromCoordinate ) --meters
local distancenm = UTILS.Round(UTILS.MetersToNM(Distance),0)
- BRText = string.format("%03d, %d miles",AngleDegrees,distancenm)
- BRTextTTS = string.format("%s, %d miles",AngleDegText,distancenm)
+ BRText = string.format("%03d, %d %s",AngleDegrees,distancenm,miles)
+ BRTextTTS = string.format("%s, %d %s",AngleDegText,distancenm,miles)
if self.PathToGoogleKey then
- BRTextTTS = string.format("%s, %d miles",AngleDegTextTTS,distancenm)
+ BRTextTTS = string.format("%s, %d %s",AngleDegTextTTS,distancenm,miles)
end
self:T(BRText,BRTextTTS)
@@ -3886,24 +4142,29 @@ function AWACS:_ToStringBRA(FromCoordinate,ToCoordinate,Altitude)
local AngleDegrees = UTILS.Round( UTILS.ToDegree( AngleRadians ), 0 ) -- degrees
local AngleDegText = string.format("%03d",AngleDegrees) -- 051
- --local AngleDegTextTTS = string.format("%s",AngleDegText)
AngleDegText = string.gsub(AngleDegText,"%d","%1 ") -- "0 5 1 "
AngleDegText = string.gsub(AngleDegText," $","") -- "0 5 1"
local AngleDegTextTTS = string.gsub(AngleDegText,"0","zero")
local Distance = ToCoordinate:Get2DDistance( FromCoordinate ) --meters
local distancenm = UTILS.Round(UTILS.MetersToNM(Distance),0)
+
+ local zero = self.gettext:GetEntry("ZERO",self.locale)
+ local miles = self.gettext:GetEntry("MILES",self.locale)
+ local thsd = self.gettext:GetEntry("THOUSAND",self.locale)
+ local vlow = self.gettext:GetEntry("VERYLOW",self.locale)
+
if altitude >= 1 then
- BRText = string.format("%03d, %d miles, %d thousand",AngleDegrees,distancenm,altitude)
- BRTextTTS = string.format("%s, %d miles, %d thousand",AngleDegText,distancenm,altitude)
+ BRText = string.format("%03d, %d %s, %d %s",AngleDegrees,distancenm,miles,altitude,thsd)
+ BRTextTTS = string.format("%s, %d %s, %d %s",AngleDegText,distancenm,miles,altitude,thsd)
if self.PathToGoogleKey then
- BRTextTTS = string.format("%s, %d miles, %d thousand",AngleDegTextTTS,distancenm,altitude)
+ BRTextTTS = string.format("%s, %d %s, %d %s",AngleDegTextTTS,distancenm,miles,altitude,thsd)
end
else
- BRText = string.format("%03d, %d miles, very low",AngleDegrees,distancenm)
- BRTextTTS = string.format("%s, %d miles, very low",AngleDegText,distancenm)
+ BRText = string.format("%03d, %d %s, %s",AngleDegrees,distancenm,miles,vlow)
+ BRTextTTS = string.format("%s, %d %s, %s",AngleDegText,distancenm,miles,vlow)
if self.PathToGoogleKey then
- BRTextTTS = string.format("%s, %d miles, very low",AngleDegTextTTS,distancenm)
+ BRTextTTS = string.format("%s, %d %s, %s",AngleDegTextTTS,distancenm,miles,vlow)
end
end
self:T(BRText,BRTextTTS)
@@ -4026,7 +4287,6 @@ function AWACS:_CreateIdleTaskForContact(Description,Object,Contact)
task.ToDo = Description
task.Target = TARGET:New(Object)
task.Contact = Contact
- --task.IsContact = true
task.ScreenText = Description
if Description == AWACS.TaskDescription.ANCHOR or Description == AWACS.TaskDescription.REANCHOR then
task.Target.Type = TARGET.ObjectType.ZONE
@@ -4049,11 +4309,8 @@ function AWACS:_CreateIdleTaskForCluster(Description,Object,Cluster)
task.AssignedGroupID = 0
task.Status = AWACS.TaskStatus.IDLE
task.ToDo = Description
- --self:T({Cluster.Contacts})
- --task.Target = TARGET:New(Cluster.Contacts[1])
task.Target = TARGET:New(self.intel:GetClusterCoordinate(Cluster))
task.Cluster = Cluster
- --task.IsCluster = true
task.ScreenText = Description
if Description == AWACS.TaskDescription.ANCHOR or Description == AWACS.TaskDescription.REANCHOR then
task.Target.Type = TARGET.ObjectType.ZONE
@@ -4072,7 +4329,8 @@ function AWACS:_MessageAIReadyForTasking(GID)
if GID >0 and self.ManagedGrps[GID] then
local managedgroup = self.ManagedGrps[GID] -- #AWACS.ManagedGroup
local GFCallsign = self:_GetCallSign(managedgroup.Group)
- local TextTTS = string.format("%s. %s. On station over anchor %d at angels %d. Ready for tasking.",GFCallsign,self.callsigntxt,managedgroup.AnchorStackNo or 1,managedgroup.AnchorStackAngels or 25)
+ local aionst = self.gettext:GetEntry("AIONSTATION",self.locale)
+ local TextTTS = string.format(aionst,GFCallsign,self.callsigntxt,managedgroup.AnchorStackNo or 1,managedgroup.AnchorStackAngels or 25)
self:_NewRadioEntry(TextTTS,TextTTS,GID,false,false,true,true)
end
return self
@@ -4153,9 +4411,6 @@ function AWACS:_CheckTaskQueue()
if managedgroup.IsAI then
-- message AI on station
self:_MessageAIReadyForTasking(managedgroup.GID)
- elseif managedgroup.IsPlayer then
- --self.TaskedCAPHuman:PullByPointer(entry.AssignedGroupID)
- --self.CAPIdleHuman:Push(entry.AssignedGroupID)
end -- end isAI
managedgroup.HasAssignedTask = false
self.ManagedGrps[entry.AssignedGroupID] = managedgroup
@@ -4195,7 +4450,6 @@ function AWACS:_CheckTaskQueue()
local targetgrp = entry.Contact.group
local position = entry.Contact.position or entry.Cluster.coordinate
if targetgrp and targetgrp:IsAlive() and managedgroup then
- --position = targetgrp:GetCoordinate()
if position and managedgroup.Group and managedgroup.Group:IsAlive() then
local grouposition = managedgroup.Group:GetCoordinate() or managedgroup.Group:GetCoordinate()
local distance = 1000
@@ -4354,7 +4608,6 @@ function AWACS:_CheckTaskQueue()
-- check we're alive
if (not managedgroup) or (not managedgroup.Group:IsAlive()) then
self.ManagedTasks:PullByID(entry.TID)
- --entry.Status = AWACS.TaskStatus.FAILED
return self
end
@@ -4419,7 +4672,6 @@ function AWACS:_CheckTaskQueue()
local targetgrp = entry.Contact.group
local position = entry.Contact.position or entry.Cluster.coordinate
if targetgrp and targetgrp:IsAlive() and managedgroup then
- --position = targetgrp:GetCoordinate()
if position and managedgroup.Group and managedgroup.Group:IsAlive() then
local grouposition = managedgroup.Group:GetCoordinate() or managedgroup.Group:GetCoordinate()
local distance = 1000
@@ -4464,14 +4716,12 @@ function AWACS:_CheckTaskQueue()
if managedgroup.IsPlayer then
entry.IsPlayerTask = false
end
- --self.ManagedTasks:PullByID(entry.TID)
self.ManagedGrps[entry.AssignedGroupID] = managedgroup
self:__ReAnchor(5,managedgroup.GID)
end
elseif Contact and Contact.IFF == AWACS.IFF.ENEMY then
self:T("IFF outcome hostile for GroupID "..entry.AssignedGroupID)
-- change to intercept
- --self.ManagedTasks:PullByID(entry.TID)
entry.ToDo = AWACS.TaskDescription.INTERCEPT
entry.Status = AWACS.TaskStatus.ASSIGNED
local cname = Contact.TargetGroupNaming
@@ -4495,7 +4745,6 @@ function AWACS:_CheckTaskQueue()
if managedgroup.IsPlayer then
entry.IsPlayerTask = false
end
- --self.ManagedTasks:PullByID(entry.TID)
self.ManagedGrps[entry.AssignedGroupID] = managedgroup
if managedgroup.Group:IsAlive() or managedgroup.FlightGroup:IsAlive() then
self:__ReAnchor(5,managedgroup.GID)
@@ -4619,7 +4868,6 @@ end
-- @return #AWACS self
function AWACS:_AnnounceContact(Contact,IsNew,Group,IsBogeyDope,Tag,IsPopup,ReportingName)
self:T(self.lid.."_AnnounceContact")
- --self:T({Contact})
-- do we have a group to talk to?
local tag = ""
local Tag = Tag
@@ -4628,7 +4876,6 @@ function AWACS:_AnnounceContact(Contact,IsNew,Group,IsBogeyDope,Tag,IsPopup,Repo
-- injected data available?
CID = Contact.CID or 0
Tag = Contact.TargetGroupNaming or ""
- --self:T({CID,Tag})
end
if self.NoGroupTags then
Tag = nil
@@ -4639,7 +4886,6 @@ function AWACS:_AnnounceContact(Contact,IsNew,Group,IsBogeyDope,Tag,IsPopup,Repo
if Group and Group:IsAlive() then
GID, isGroup,grpcallsign = self:_GetManagedGrpID(Group)
self:T("GID="..GID.." CheckedIn = "..tostring(isGroup))
- --grpcallsign = self:_GetCallSign(Group,GID) or "Ghost 1"
end
local cluster = Contact.Cluster
@@ -4655,8 +4901,7 @@ function AWACS:_AnnounceContact(Contact,IsNew,Group,IsBogeyDope,Tag,IsPopup,Repo
clustercoordinate:SetHeading(Contact.Contact.group:GetHeading())
local BRAfromBulls, BRAfromBullsTTS = self:_GetBRAfromBullsOrAO(clustercoordinate)
-
-
+
self:T(BRAfromBulls)
self:T(BRAfromBullsTTS)
BRAfromBulls=BRAfromBulls.."."
@@ -4670,9 +4915,6 @@ function AWACS:_AnnounceContact(Contact,IsNew,Group,IsBogeyDope,Tag,IsPopup,Repo
BRAfromBullsTTS = clustercoordinate:ToStringBRAANATO(Group:GetCoordinate(),true,true,true,false,true)
end
end
-
- -- "Uzi 1-1, Magic, BRA, 183 for 10 at 2000, hot"
- -- ", , /, , BRA for at angels , , "
local BRAText = ""
local TextScreen = ""
@@ -4685,18 +4927,31 @@ function AWACS:_AnnounceContact(Contact,IsNew,Group,IsBogeyDope,Tag,IsPopup,Repo
TextScreen = string.format("%s.",self.callsigntxt)
end
+ local newgrp = self.gettext:GetEntry("NEWGROUP",self.locale)
+ local grptxt = self.gettext:GetEntry("GROUP",self.locale)
+ local GRPtxt = self.gettext:GetEntry("GROUPCAP",self.locale)
+ local popup = self.gettext:GetEntry("POPUP",self.locale)
+
if IsNew and self.PlayerGuidance then
- BRAText = BRAText .. " New group."
- TextScreen = TextScreen .. " New group."
+ --BRAText = BRAText .. " New group."
+ BRAText = string.format("%s %s.",BRAText,newgrp)
+ --TextScreen = TextScreen .. " New group."
+ TextScreen = string.format("%s %s.",TextScreen,newgrp)
elseif IsPopup then
- BRAText = BRAText .. " Pop-up group."
- TextScreen = TextScreen .. " Pop-up group."
+ --BRAText = BRAText .. " Pop-up group."
+ BRAText = string.format("%s %s %s.",BRAText,popup,grptxt)
+ --TextScreen = TextScreen .. " Pop-up group."
+ TextScreen = string.format("%s %s %s.",TextScreen,popup,grptxt)
elseif IsBogeyDope and Tag and Tag ~= "" then
- BRAText = BRAText .. " "..Tag.." group."
- TextScreen = TextScreen .. " "..Tag.." group."
+ --BRAText = BRAText .. " "..Tag.." group."
+ BRAText = string.format("%s %s %s.",BRAText,Tag,grptxt)
+ --TextScreen = TextScreen .. " "..Tag.." group."
+ TextScreen = string.format("%s %s %s.",TextScreen,Tag,grptxt)
else
- BRAText = BRAText .. " Group."
- TextScreen = TextScreen .. " Group."
+ --BRAText = BRAText .. " Group."
+ BRAText = string.format("%s %s.",BRAText,GRPtxt)
+ --TextScreen = TextScreen .. " Group."
+ TextScreen = string.format("%s %s.",TextScreen,GRPtxt)
end
if not IsBogeyDope then
@@ -4707,18 +4962,17 @@ function AWACS:_AnnounceContact(Contact,IsNew,Group,IsBogeyDope,Tag,IsPopup,Repo
end
if threatsize > 1 then
- --BRAText = BRAText .. " "..threatsizetext..". "..BRAfromBullsTTS
BRAText = BRAText .. " "..BRAfromBullsTTS.." "..threatsizetext.."."
- --TextScreen = TextScreen .. " "..threatsizetext..". "..BRAfromBulls
TextScreen = TextScreen .. " "..BRAfromBulls.." "..threatsizetext.."."
else
- --BRAText = BRAText .. " "..threatsizetext..". "..BRAfromBullsTTS
BRAText = BRAText .. " "..BRAfromBullsTTS
- --TextScreen = TextScreen .. " "..threatsizetext..". "..BRAfromBulls
TextScreen = TextScreen .. " "..BRAfromBulls
end
if self.ModernEra then
+ local high = self.gettext:GetEntry("HIGH",self.locale)
+ local vfast = self.gettext:GetEntry("VERYFAST",self.locale)
+ local fast = self.gettext:GetEntry("FAST",self.locale)
-- Platform
if ReportingName and ReportingName ~= "Bogey" then
ReportingName = string.gsub(ReportingName,"_"," ")
@@ -4729,24 +4983,23 @@ function AWACS:_AnnounceContact(Contact,IsNew,Group,IsBogeyDope,Tag,IsPopup,Repo
local height = Contact.Contact.group:GetHeight()
local height = UTILS.Round(UTILS.MetersToFeet(height)/1000,0) -- e.g, 25
if height >= 40 then
- BRAText = BRAText .. " High."
- TextScreen = TextScreen .. " High."
+ BRAText = BRAText .. high
+ TextScreen = TextScreen .. high
end
-- Fast (>600kn) or Very fast (>900kn)
local speed = Contact.Contact.group:GetVelocityKNOTS()
if speed > 900 then
- BRAText = BRAText .. " Very Fast."
- TextScreen = TextScreen .. " Very Fast."
+ BRAText = BRAText .. vfast
+ TextScreen = TextScreen .. vfast
elseif speed >= 600 and speed <= 900 then
- BRAText = BRAText .. " Fast."
- TextScreen = TextScreen .. " Fast."
+ BRAText = BRAText .. fast
+ TextScreen = TextScreen .. fast
end
end
string.gsub(BRAText,"BRAA","brah")
string.gsub(BRAText,"BRA","brah")
- --self:T(BRAText)
local prio = IsNew or IsBogeyDope
self:_NewRadioEntry(BRAText,TextScreen,GID,isGroup,true,IsNew,false,prio)
@@ -4764,7 +5017,6 @@ function AWACS:_GetAliveOpsGroupFromTable(OpsGroups)
local OG = _OG -- Ops.OpsGroup#OPSGROUP
if OG and OG:IsAlive() then
handback = OG
- --self:T("Handing back OG: " .. OG:GetName())
break
end
end
@@ -4886,7 +5138,6 @@ function AWACS:_CheckAICAPOnStation()
local onstation = capmissions + alert5missions
- --if self.AIRequested > self.MaxAIonCAP then
if capmissions > self.MaxAIonCAP then
-- too many, send one home
self:T(string.format("*** Onstation %d > MaxAIOnCAP %d",onstation,self.MaxAIonCAP))
@@ -4902,7 +5153,7 @@ function AWACS:_CheckAICAPOnStation()
end
-- control number of AI CAP Flights
- if capmissions < self.MaxAIonCAP then
+ if capmissions < self.MaxAIonCAP and alert5missions < self.MaxAIonCAP+2 then
-- not enough
local AnchorStackNo,free = self:_GetFreeAnchorStack()
if free then
@@ -5056,7 +5307,9 @@ function AWACS:_TACRangeCall(GID,Contact)
if position then
local distance = position:Get2DDistance(managedgroup.Group:GetCoordinate())
distance = UTILS.Round(UTILS.MetersToNM(distance)) -- 30nm - hopefully
- local text = string.format("%s. %s. %s group, %d miles.",self.callsigntxt,pilotcallsign,contacttag,distance)
+ local grptxt = self.gettext:GetEntry("GROUP",self.locale)
+ local miles = self.gettext:GetEntry("MILES",self.locale)
+ local text = string.format("%s. %s. %s %s, %d %s.",self.callsigntxt,pilotcallsign,contacttag,grptxt,distance,miles)
self:_NewRadioEntry(text,text,GID,true,self.debug,true,false,true)
self:_UpdateContactEngagementTag(Contact.CID,Contact.EngagementTag,true,false,AWACS.TaskStatus.EXECUTING)
end
@@ -5087,7 +5340,8 @@ function AWACS:_MeldRangeCall(GID,Contact)
else
BRATExt = position:ToStringBRAANATO(flightpos,false,false)
end
- local text = string.format("%s. %s. %s group, %s",self.callsigntxt,pilotcallsign,contacttag,BRATExt)
+ local grptxt = self.gettext:GetEntry("GROUP",self.locale)
+ local text = string.format("%s. %s. %s %s, %s",self.callsigntxt,pilotcallsign,contacttag,grptxt,BRATExt)
self:_NewRadioEntry(text,text,GID,true,self.debug,true,false,true)
self:_UpdateContactEngagementTag(Contact.CID,Contact.EngagementTag,true,true,AWACS.TaskStatus.EXECUTING)
end
@@ -5116,7 +5370,9 @@ function AWACS:_ThreatRangeCall(GID,Contact)
else
BRATExt = position:ToStringBRAANATO(flightpos,false,false)
end
- local text = string.format("%s. %s. %s group, Threat. %s",self.callsigntxt,pilotcallsign,contacttag,BRATExt)
+ local grptxt = self.gettext:GetEntry("GROUP",self.locale)
+ local thrt = self.gettext:GetEntry("THREAT",self.locale)
+ local text = string.format("%s. %s. %s %s, %s. %s",self.callsigntxt,pilotcallsign,contacttag,grptxt, thrt, BRATExt)
self:_NewRadioEntry(text,text,GID,true,self.debug,true,false,true)
end
end
@@ -5131,8 +5387,8 @@ function AWACS:_MergedCall(GID)
self:T(self.lid.."_MergedCall")
-- AIC: “Enforcer, mergedb”
local pilotcallsign = self:_GetCallSign(nil,GID)
- --local managedgroup = self.ManagedGrps[GID] -- #AWACS.ManagedGroup
- local text = string.format("%s. %s. Merged.",self.callsigntxt,pilotcallsign)
+ local merge = self.gettext:GetEntry("MERGED",self.locale)
+ local text = string.format("%s. %s. %s.",self.callsigntxt,pilotcallsign,merge)
self:_NewRadioEntry(text,text,GID,true,self.debug,true,false,true)
return self
end
@@ -5188,10 +5444,12 @@ function AWACS:_AssignPilotToTarget(Pilots,Targets)
local ScreenText = ""
local TaskType = AWACS.TaskDescription.INTERCEPT
if self.AwacsROE == AWACS.ROE.POLICE or self.AwacsROE == AWACS.ROE.VID then
- ScreenText = string.format("Intercept and VID %s group.",Target.TargetGroupNaming)
+ local interc = self.gettext:GetEntry("SCREENVID",self.locale)
+ ScreenText = string.format(interc,Target.TargetGroupNaming)
TaskType = AWACS.TaskDescription.VID
else
- ScreenText = string.format("Intercept %s group.",Target.TargetGroupNaming)
+ local interc = self.gettext:GetEntry("SCREENINTER",self.locale)
+ ScreenText = string.format(interc,Target.TargetGroupNaming)
end
Pilot.CurrentTask = self:_CreateTaskForGroup(Pilot.GID,TaskType,ScreenText,Target.Target,AWACS.TaskStatus.REQUESTED,nil,Target.Cluster,Target.Contact)
@@ -5204,13 +5462,15 @@ function AWACS:_AssignPilotToTarget(Pilots,Targets)
Target.LinkedTask = Pilot.CurrentTask
Target.LinkedGroup = Pilot.GID
Target.Status = AWACS.TaskStatus.REQUESTED
- Target.EngagementTag = string.format("Targeted by %s.",Pilot.CallSign)
+ local targeted = self.gettext:GetEntry("ENGAGETAG",self.locale)
+ Target.EngagementTag = string.format(targeted,Pilot.CallSign)
self.Contacts:PullByID(Target.CID)
self.Contacts:Push(Target,Target.CID)
- local text = string.format("%s. %s group. %s. %s, request commit.", self.callsigntxt,Target.TargetGroupNaming,TargetDirectionsTTS,Pilot.CallSign)
- local textScreen = string.format("%s. %s group. %s. %s, request commit.", self.callsigntxt,Target.TargetGroupNaming,TargetDirections,Pilot.CallSign)
+ local reqcomm = self.gettext:GetEntry("REQCOMMIT",self.locale)
+ local text = string.format(reqcomm, self.callsigntxt,Target.TargetGroupNaming,TargetDirectionsTTS,Pilot.CallSign)
+ local textScreen = string.format(reqcomm, self.callsigntxt,Target.TargetGroupNaming,TargetDirections,Pilot.CallSign)
self:_NewRadioEntry(text,textScreen,Pilot.GID,true,self.debug,true,false,true)
@@ -5312,14 +5572,12 @@ function AWACS:_AssignPilotToTarget(Pilots,Targets)
Target.LinkedTask = Pilot.CurrentTask
Target.LinkedGroup = Pilot.GID
Target.Status = AWACS.TaskStatus.ASSIGNED
- Target.EngagementTag = string.format("Targeted by %s.",Pilot.CallSign)
+ local targeted = self.gettext:GetEntry("ENGAGETAG",self.locale)
+ Target.EngagementTag = string.format(targeted,Pilot.CallSign)
self.Contacts:PullByID(Target.CID)
self.Contacts:Push(Target,Target.CID)
- -- message commit and return commit from AI
- --local bratext = Target.Contact.position:ToStringBRA(Pilot.Group:GetCoordinate())
-
local altitude = Target.Contact.altitude or Target.Contact.group:GetAltitude()
local position = Target.Cluster.coordinate or Target.Contact.position
if not position then
@@ -5327,12 +5585,14 @@ function AWACS:_AssignPilotToTarget(Pilots,Targets)
end
local bratext, bratexttts = self:_ToStringBRA(Pilot.Group:GetCoordinate(),position,altitude or 8000)
- local text = string.format("%s. %s group. %s. %s, commit.", self.callsigntxt,Target.TargetGroupNaming,bratexttts,Pilot.CallSign)
- local textScreen = string.format("%s. %s group. %s. %s, request commit.", self.callsigntxt,Target.TargetGroupNaming,bratext,Pilot.CallSign)
+ local aicomm = self.gettext:GetEntry("AICOMMIT",self.locale)
+ local text = string.format(aicomm, self.callsigntxt,Target.TargetGroupNaming,bratexttts,Pilot.CallSign)
+ local textScreen = string.format(aicomm, self.callsigntxt,Target.TargetGroupNaming,bratext,Pilot.CallSign)
self:_NewRadioEntry(text,textScreen,Pilot.GID,true,self.debug,true,false,true)
- local text = string.format("%s. Commit.",Pilot.CallSign)
+ local comm = self.gettext:GetEntry("COMMIT",self.locale)
+ local text = string.format("%s. %s.",Pilot.CallSign,comm)
self:_NewRadioEntry(text,text,Pilot.GID,true,self.debug,true,true,true)
@@ -5421,7 +5681,8 @@ function AWACS:onafterStart(From, Event, To)
self.callsigntxt = string.format("%s",AWACS.CallSignClear[self.CallSign])
self:__CheckRadioQueue(-10)
- local text = string.format("%s. All stations, SUNRISE SUNRISE SUNRISE, %s.",self.callsigntxt,self.callsigntxt)
+ local sunrise = self.gettext:GetEntry("SUNRISE",self.locale)
+ local text = string.format(sunrise,self.callsigntxt,self.callsigntxt)
self:_NewRadioEntry(text,text,0,false,false,false,false,true)
self:T(self.lid..text)
self.sunrisedone = true
@@ -5476,19 +5737,16 @@ function AWACS:onafterStart(From, Event, To)
-- Event functions
function MarkerOps:OnAfterMarkAdded(From,Event,To,Text,Keywords,Coord)
--local m = MESSAGE:New(string.format("AWACS %s Mark Added.", self.Tag),10,"Info",true):ToAllIf(self.debug)
- BASE:I(string.format("%s Mark Added.", self.Tag))
Handler(Keywords,Coord,Text)
end
function MarkerOps:OnAfterMarkChanged(From,Event,To,Text,Keywords,Coord)
- BASE:I(string.format("%s Mark Changed.", self.Tag))
- --local m = MESSAGE:New(string.format("AWACS %s Mark Changed.", self.Tag),10,"Info",true):ToAllIf(self.debug)
+ --BASE:I(string.format("%s Mark Changed.", self.Tag))
Handler(Keywords,Coord,Text)
end
function MarkerOps:OnAfterMarkDeleted(From,Event,To)
- BASE:I(string.format("%s Mark Deleted.", self.Tag))
- --local m = MESSAGE:New(string.format("AWACS %s Mark Deleted.", self.Tag),10,"Info",true):ToAllIf(self.debug)
+ --BASE:I(string.format("%s Mark Deleted.", self.Tag))
end
self.MarkerOps = MarkerOps
@@ -5522,8 +5780,9 @@ function AWACS:_CheckAwacsStatus()
-- arrived
self.AwacsInZone = true
self:T(self.lid.."Arrived in Orbit Zone: " .. orbitzone:GetName())
- local text = string.format("%s on station for %s control.",self.callsigntxt,self.AOName or "Rock")
- local textScreen = string.format("%s on station for %s control.",self.callsigntxt,self.AOName or "Rock")
+ local onstationtxt = self.gettext:GetEntry("AWONSTATION",self.locale)
+ local text = string.format(onstationtxt,self.callsigntxt,self.AOName or "Rock")
+ local textScreen = text
self:_NewRadioEntry(text,textScreen,0,false,true,true,false,true)
end
end
@@ -5544,8 +5803,9 @@ function AWACS:_CheckAwacsStatus()
if self.intelstarted and not self.sunrisedone then
-- TODO Sunrise call on after airborne at ca 10k feet
local alt = UTILS.Round(UTILS.MetersToFeet(awacs:GetAltitude())/1000,0)
- if alt >= 10 then
- local text = string.format("%s. All stations, SUNRISE SUNRISE SUNRISE, %s.",self.callsigntxt,self.callsigntxt)
+ if alt >= 10 then
+ local sunrise = self.gettext:GetEntry("SUNRISE",self.locale)
+ local text = string.format(sunrise,self.callsigntxt,self.callsigntxt)
self:_NewRadioEntry(text,text,0,false,false,false,false,true)
--self.AwacsFG:RadioTransmission(text,1,false)
self:T(self.lid..text)
@@ -5599,13 +5859,10 @@ function AWACS:_CheckAwacsStatus()
local ESTOSLeft = UTILS.Round((((self.AwacsTimeOnStation+self.ShiftChangeTime)*3600) - ESmissiontime),0) -- seconds
ESTOSLeft = UTILS.Round(ESTOSLeft/60,0) -- minutes
local ChangeTime = UTILS.Round(((self.ShiftChangeTime * 3600)/60),0)
- --local Changedue = "No"
- --report:Add("====================")
report:Add("AWACS REPLACEMENT:")
report:Add(string.format("Auftrag Status: %s",esstatus))
report:Add(string.format("TOS Left: %d min",ESTOSLeft))
- --report:Add(string.format("Needs ShiftChange: %s",Changedue))
local OpsGroups = AWmission:GetOpsGroups()
local OpsGroup = self:_GetAliveOpsGroupFromTable(OpsGroups) -- Ops.OpsGroup#OPSGROUP
@@ -5931,16 +6188,25 @@ function AWACS:onafterAssignedAnchor(From, Event, To, GID, Anchor, AnchorStackNo
local Angels = AnchorAngels or 25
local AnchorSpeed = self.CapSpeedBase or 270
local AuftragsNr = managedgroup.CurrentAuftrag
-
- local textTTS = string.format("%s. %s. Station at %s at angels %d doing %d knots.",CallSign,self.callsigntxt,AnchorName,Angels,AnchorSpeed)
+
+ local textTTS = ""
+ if self.PikesSpecialSwitch then
+ local stationtxt = self.gettext:GetEntry("STATIONAT",self.locale)
+ textTTS = string.format(stationtxt,CallSign,self.callsigntxt,AnchorName,Angels)
+ else
+ local stationtxt = self.gettext:GetEntry("STATIONATLONG",self.locale)
+ textTTS = string.format(stationtxt,CallSign,self.callsigntxt,AnchorName,Angels,AnchorSpeed)
+ end
local ROEROT = self.AwacsROE..", "..self.AwacsROT
- local textScreen = string.format("%s. %s.\nStation at %s\nAngels %d\nSpeed %d knots\nCoord %s\nROE %s.",CallSign,self.callsigntxt,AnchorName,Angels,AnchorSpeed,AnchorCoordTxt,ROEROT)
- local TextTasking = string.format("Station at %s\nAngels %d\nSpeed %d knots\nCoord %s\nROE %s",AnchorName,Angels,AnchorSpeed,AnchorCoordTxt,ROEROT)
+ local stationtxtsc = self.gettext:GetEntry("STATIONSCREEN",self.locale)
+ local stationtxtta = self.gettext:GetEntry("STATIONTASK",self.locale)
+ local textScreen = string.format(stationtxtsc,CallSign,self.callsigntxt,AnchorName,Angels,AnchorSpeed,AnchorCoordTxt,ROEROT)
+ local TextTasking = string.format(stationtxtta,AnchorName,Angels,AnchorSpeed,AnchorCoordTxt,ROEROT)
self:_NewRadioEntry(textTTS,textScreen,GID,isPlayer,isPlayer,true,false)
managedgroup.CurrentTask = self:_CreateTaskForGroup(GID,AWACS.TaskDescription.ANCHOR,TextTasking,Anchor.StationZone)
-
+
-- if it's a Alert5, we want to push CAP instead
if isAI then
local auftrag = managedgroup.FlightGroup:GetMissionCurrent() -- Ops.Auftrag#AUFTRAG
@@ -5952,10 +6218,8 @@ function AWACS:onafterAssignedAnchor(From, Event, To, GID, Anchor, AnchorStackNo
capauftrag:SetTime(nil,((self.CAPTimeOnStation*3600)+(15*60)))
capauftrag:AddAsset(managedgroup.FlightGroup)
self.CatchAllMissions[#self.CatchAllMissions+1] = capauftrag
- --local AirWing = managedgroup.FlightGroup:GetAirWing()
managedgroup.FlightGroup:AddMission(capauftrag)
auftrag:Cancel()
- --AirWing:AddMission(capauftrag)
else
self:E("**** AssignedAnchor but Auftrag NOT ALERT5!")
end
@@ -6285,11 +6549,7 @@ end
-- @return #AWACS self
function AWACS:onafterReAnchor(From, Event, To, GID)
self:T({From, Event, To, GID})
- -- get managedgroup
- -- check AI FG state
- -- check weapon state
- -- check fuel state
- -- vector back to anchor or RTB
+ -- get managedgroup, heck AI FG state, heck weapon state, check fuel state, vector back to anchor or RTB
local managedgroup = self.ManagedGrps[GID] -- #AWACS.ManagedGroup
if managedgroup then
if managedgroup.IsAI then
@@ -6306,8 +6566,7 @@ function AWACS:onafterReAnchor(From, Event, To, GID)
self:_CheckOut(AIFG:GetGroup(),GID)
self.AIRequested = self.AIRequested - 1
else
- -- re-establish anchor task
- -- get anchor zone data
+ -- re-establish anchor task, get anchor zone data
local Anchor = self.AnchorStacks:ReadByPointer(managedgroup.AnchorStackNo) -- #AWACS.AnchorData
local StationZone = Anchor.StationZone -- Core.Zone#ZONE
managedgroup.CurrentTask = self:_CreateTaskForGroup(GID,AWACS.TaskDescription.ANCHOR,"Re-Station AI",StationZone)
@@ -6319,8 +6578,9 @@ function AWACS:onafterReAnchor(From, Event, To, GID)
managedgroup.CurrentAuftrag = 0
end
managedgroup.ContactCID = 0
- self.ManagedGrps[GID] = managedgroup
- self:_MessageVector(GID," to Station",Anchor.StationZoneCoordinate,managedgroup.AnchorStackAngels)
+ self.ManagedGrps[GID] = managedgroup
+ local tostation = self.gettext:GetEntry("VECTORSTATION",self.locale)
+ self:_MessageVector(GID,tostation,Anchor.StationZoneCoordinate,managedgroup.AnchorStackAngels)
end
else
-- lost group, remove from known groups, declare vanished
@@ -6331,28 +6591,26 @@ function AWACS:onafterReAnchor(From, Event, To, GID)
local savedcallsign = managedgroup.CallSign
--vanished/friendly flight faded/lost contact with C/S/CSAR Scramble
-- Magic, RIGHTGUARD, RIGHTGUARD, Dodge 41, Bullseye X/Y
- local textoptions = {
- [1] = "Lost friendly flight",
- [2] = "Vanished friendly flight",
- [3] = "Faded friendly contact",
- [4] = "Lost contact with",
- }
-
+ local textoptions = {}
+ textoptions[1] = self.gettext:GetEntry("TEXTOPTIONS1",self.locale)
+ textoptions[2] = self.gettext:GetEntry("TEXTOPTIONS2",self.locale)
+ textoptions[3] = self.gettext:GetEntry("TEXTOPTIONS3",self.locale)
+ textoptions[4] = self.gettext:GetEntry("TEXTOPTIONS4",self.locale)
+ local allstations = self.gettext:GetEntry("ALLSTATIONS",self.locale)
+ local milestxt = self.gettext:GetEntry("MILES",self.locale)
-- DONE - need to save last known coordinate
if managedgroup.LastKnownPosition then
local lastknown = UTILS.DeepCopy(managedgroup.LastKnownPosition)
local faded = textoptions[math.random(1,4)]
- local text = string.format("All stations. %s. %s %s.",self.callsigntxt, faded, savedcallsign)
- local textScreen = string.format("All stations, %s. %s %s.", self.callsigntxt, faded, savedcallsign)
+ local text = string.format("%s. %s. %s %s.",allstations,self.callsigntxt, faded, savedcallsign)
+ local textScreen = string.format("%s, %s. %s %s.",allstations, self.callsigntxt, faded, savedcallsign)
local brtext = self:_ToStringBULLS(lastknown)
local brtexttts = self:_ToStringBULLS(lastknown,false,true)
- --if self.PathToGoogleKey then
- --brtexttts = self:_ToStringBULLS(lastknown,true)
- --end
- text = text .. " "..brtexttts.." miles."
- textScreen = textScreen .. " "..brtext.." miles."
+
+ text = text .. " "..brtexttts.." "..milestxt.."."
+ textScreen = textScreen .. " "..brtext.." "..milestxt.."."
self:_NewRadioEntry(text,textScreen,0,false,self.debug,true,false,true)
end
@@ -6371,12 +6629,14 @@ function AWACS:onafterReAnchor(From, Event, To, GID)
local AnchorSpeed = self.CapSpeedBase or 270
local StationZone = Anchor.StationZone -- Core.Zone#ZONE
local ROEROT = self.AwacsROE.." "..self.AwacsROT
- local TextTasking = string.format("Station at %s\nAngels %d\nSpeed %d knots\nCoord %s\nROE %s",AnchorName,Angels,AnchorSpeed,AnchorCoordTxt,ROEROT)
+ local stationtxt = self.gettext:GetEntry("STATIONTASK",self.locale)
+ local TextTasking = string.format(stationtxt,AnchorName,Angels,AnchorSpeed,AnchorCoordTxt,ROEROT)
managedgroup.CurrentTask = self:_CreateTaskForGroup(GID,AWACS.TaskDescription.ANCHOR,TextTasking,StationZone)
managedgroup.HasAssignedTask = true
managedgroup.ContactCID = 0
- self.ManagedGrps[GID] = managedgroup
- self:_MessageVector(GID," to Station",Anchor.StationZoneCoordinate,managedgroup.AnchorStackAngels)
+ self.ManagedGrps[GID] = managedgroup
+ local vectortxt = self.gettext:GetEntry("VECTORSTATION",self.locale)
+ self:_MessageVector(GID,vectortxt,Anchor.StationZoneCoordinate,managedgroup.AnchorStackAngels)
else
-- lost group, remove from known groups, declare vanished
-- ALL remove from managedgrps
@@ -6384,17 +6644,18 @@ function AWACS:onafterReAnchor(From, Event, To, GID)
local savedcallsign = managedgroup.CallSign
--vanished/friendly flight faded/lost contact with C/S/CSAR Scramble
-- Magic, RIGHTGUARD, RIGHTGUARD, Dodge 41, Bullseye X/Y
- local textoptions = {
- [1] = "Lost friendly flight",
- [2] = "Vanished friendly flight",
- [3] = "Faded friendly contact",
- [4] = "Lost contact with",
- }
+ local textoptions = {}
+ textoptions[1] = self.gettext:GetEntry("TEXTOPTIONS1",self.locale)
+ textoptions[2] = self.gettext:GetEntry("TEXTOPTIONS2",self.locale)
+ textoptions[3] = self.gettext:GetEntry("TEXTOPTIONS3",self.locale)
+ textoptions[4] = self.gettext:GetEntry("TEXTOPTIONS4",self.locale)
+ local allstations = self.gettext:GetEntry("ALLSTATIONS",self.locale)
+ local milestxt = self.gettext:GetEntry("MILES",self.locale)
-- DONE - need to save last known coordinate
local faded = textoptions[math.random(1,4)]
- local text = string.format("All stations. %s. %s %s.",self.callsigntxt, faded, savedcallsign)
- local textScreen = string.format("All stations, %s. %s %s.", self.callsigntxt, faded, savedcallsign)
+ local text = string.format("%s. %s. %s %s.",allstations, self.callsigntxt, faded, savedcallsign)
+ local textScreen = string.format("%s, %s. %s %s.", allstations,self.callsigntxt, faded, savedcallsign)
if managedgroup.LastKnownPosition then
local lastknown = UTILS.DeepCopy(managedgroup.LastKnownPosition)
local brtext = self:_ToStringBULLS(lastknown)
@@ -6402,8 +6663,8 @@ function AWACS:onafterReAnchor(From, Event, To, GID)
--if self.PathToGoogleKey then
--brtexttts = self:_ToStringBULLS(lastknown,true)
--end
- text = text .. " "..brtexttts.." miles."
- textScreen = textScreen .. " "..brtext.." miles."
+ text = text .. " "..brtexttts.." "..milestxt.."."
+ textScreen = textScreen .. " "..brtext.." "..milestxt.."."
self:_NewRadioEntry(text,textScreen,0,false,self.debug,true,false,true)
end
diff --git a/Moose Development/Moose/Ops/Operation.lua b/Moose Development/Moose/Ops/Operation.lua
index 158af4fd4..a304395d7 100644
--- a/Moose Development/Moose/Ops/Operation.lua
+++ b/Moose Development/Moose/Ops/Operation.lua
@@ -454,7 +454,7 @@ function OPERATION:GetPhaseStatus(Phase)
return Phase.status
end
---- Set codition when the given phase is over.
+--- Set condition when the given phase is over.
-- @param #OPERATION self
-- @param #OPERATION.Phase Phase The phase.
-- @param Core.Condition#CONDITION Condition Condition when the phase is over.
@@ -624,7 +624,7 @@ end
--- Count phases.
-- @param #OPERATION self
-- @param #string Status (Optional) Only count phases in a certain status, e.g. `OPERATION.PhaseStatus.PLANNED`.
--- @param #OPERATION.Branch (Optional) Branch.
+-- @param #OPERATION.Branch Branch (Optional) Branch.
-- @return #number Number of phases
function OPERATION:CountPhases(Status, Branch)
@@ -644,6 +644,7 @@ end
--- Add a new branch to the operation.
-- @param #OPERATION self
+-- @param #string Name
-- @return #OPERATION.Branch Branch table object.
function OPERATION:AddBranch(Name)
@@ -666,6 +667,7 @@ end
--- Get name of the branch.
-- @param #OPERATION self
-- @param #OPERATION.Branch Branch The branch of which the name is requested. Default is the currently active or master branch.
+-- @return #string Name Name or "None"
function OPERATION:GetBranchName(Branch)
Branch=Branch or self:GetBranchActive()
if Branch then
diff --git a/Moose Development/Moose/Ops/PlayerTask.lua b/Moose Development/Moose/Ops/PlayerTask.lua
index 39ac33044..866b8c054 100644
--- a/Moose Development/Moose/Ops/PlayerTask.lua
+++ b/Moose Development/Moose/Ops/PlayerTask.lua
@@ -3,13 +3,15 @@
-- ## Main Features:
--
-- * Simplifies defining and executing Player tasks
--- * FSM events when a mission is done, successful or failed
+-- * FSM events when a mission is added, done, successful or failed, replanned
+-- * Ready to use SRS and localization
+-- * Mission locations can be smoked, flared and marked on the map
--
-- ===
--
-- ## Example Missions:
--
--- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/).
+-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/OPS%20-%20PlayerTask).
--
-- ===
--
@@ -17,9 +19,16 @@
--
-- ===
-- @module Ops.PlayerTask
--- @image OPS_PlayerTask.png
+-- @image OPS_PlayerTask.jpg
+-- @date Last Update August 2022
+do
+-------------------------------------------------------------------------------------------------------------------
+-- PLAYERTASK
+-- TODO: PLAYERTASK
+-------------------------------------------------------------------------------------------------------------------
+
--- PLAYERTASK class.
-- @type PLAYERTASK
-- @field #string ClassName Name of the class.
@@ -38,9 +47,10 @@
-- @field #table conditionSuccess = {},
-- @field #table conditionFailure = {},
-- @field Ops.PlayerTask#PLAYERTASKCONTROLLER TaskController
---
+-- @field #number timestamp
-- @extends Core.Fsm#FSM
+
--- Global PlayerTaskNr counter
_PlayerTaskNr = 0
@@ -48,10 +58,11 @@ _PlayerTaskNr = 0
-- @field #PLAYERTASK
PLAYERTASK = {
ClassName = "PLAYERTASK",
- verbose = true,
+ verbose = false,
lid = nil,
PlayerTaskNr = nil,
Type = nil,
+ TTSType = nil,
Target = nil,
Clients = nil,
Repeat = false,
@@ -63,11 +74,12 @@ PLAYERTASK = {
conditionSuccess = {},
conditionFailure = {},
TaskController = nil,
+ timestamp = 0,
}
--- PLAYERTASK class version.
-- @field #string version
-PLAYERTASK.version="0.0.7"
+PLAYERTASK.version="0.0.9"
--- Generic task condition.
-- @type PLAYERTASK.Condition
@@ -81,7 +93,7 @@ PLAYERTASK.version="0.0.7"
-- @param #boolean Repeat Repeat this task if true (default = false)
-- @param #number Times Repeat on failure this many times if Repeat is true (default = 1)
-- @return #PLAYERTASK self
-function PLAYERTASK:New(Type, Target, Repeat, Times)
+function PLAYERTASK:New(Type, Target, Repeat, Times, TTSType)
-- Inherit everything from FSM class.
local self=BASE:Inherit(self, FSM:New()) -- #PLAYERTASK
@@ -97,6 +109,8 @@ function PLAYERTASK:New(Type, Target, Repeat, Times)
self.conditionSuccess = {}
self.conditionFailure = {}
self.TaskController = nil -- Ops.PlayerTask#PLAYERTASKCONTROLLER
+ self.timestamp = timer.getTime()
+ self.TTSType = TTSType or "close air support"
if Repeat then
self.Repeat = true
@@ -118,7 +132,7 @@ function PLAYERTASK:New(Type, Target, Repeat, Times)
return self
end
- self:I(self.lid.."Created.")
+ self:T(self.lid.."Created.")
-- FMS start state is PLANNED.
self:SetStartState("Planned")
@@ -139,6 +153,89 @@ function PLAYERTASK:New(Type, Target, Repeat, Times)
self:__Status(-5)
return self
+
+ ---
+ -- Pseudo Functions
+ ---
+
+ --- On After "Planned" event. Task has been planned.
+ -- @function [parent=#PLAYERTASK] OnAfterPlanned
+ -- @param #PLAYERTASK self
+ -- @param #string From From state.
+ -- @param #string Event Event.
+ -- @param #string To To state.
+
+ --- On After "Requested" event. Task has been Requested.
+ -- @function [parent=#PLAYERTASK] OnAfterRequested
+ -- @param #PLAYERTASK self
+ -- @param #string From From state.
+ -- @param #string Event Event.
+ -- @param #string To To state.
+
+ --- On After "ClientAdded" event. Client has been added to the task.
+ -- @function [parent=#PLAYERTASK] OnAfterClientAdded
+ -- @param #PLAYERTASK self
+ -- @param #string From From state.
+ -- @param #string Event Event.
+ -- @param #string To To state.
+ -- @param Wrapper.Client#CLIENT Client
+
+ --- On After "ClientRemoved" event. Client has been removed from the task.
+ -- @function [parent=#PLAYERTASK] OnAfterClientRemoved
+ -- @param #PLAYERTASK self
+ -- @param #string From From state.
+ -- @param #string Event Event.
+ -- @param #string To To state.
+
+ --- On After "Executing" event. Task is executed by the 1st client.
+ -- @function [parent=#PLAYERTASK] OnAfterExecuting
+ -- @param #PLAYERTASK self
+ -- @param #string From From state.
+ -- @param #string Event Event.
+ -- @param #string To To state.
+
+ --- On After "Done" event. Task is done.
+ -- @function [parent=#PLAYERTASK] OnAfterDone
+ -- @param #PLAYERTASK self
+ -- @param #string From From state.
+ -- @param #string Event Event.
+ -- @param #string To To state.
+
+ --- On After "Cancel" event. Task has been cancelled.
+ -- @function [parent=#PLAYERTASK] OnAfterCancel
+ -- @param #PLAYERTASK self
+ -- @param #string From From state.
+ -- @param #string Event Event.
+ -- @param #string To To state.
+
+ --- On After "Planned" event. Task has been planned.
+ -- @function [parent=#PLAYERTASK] OnAfterPilotPlanned
+ -- @param #PLAYERTASK self
+ -- @param #string From From state.
+ -- @param #string Event Event.
+ -- @param #string To To state.
+
+ --- On After "Success" event. Task has been a success.
+ -- @function [parent=#PLAYERTASK] OnAfterSuccess
+ -- @param #PLAYERTASK self
+ -- @param #string From From state.
+ -- @param #string Event Event.
+ -- @param #string To To state.
+
+ --- On After "ClientAborted" event. A client has aborted the task.
+ -- @function [parent=#PLAYERTASK] OnAfterClientAborted
+ -- @param #PLAYERTASK self
+ -- @param #string From From state.
+ -- @param #string Event Event.
+ -- @param #string To To state.
+
+ --- On After "Failed" event. Task has been a failure.
+ -- @function [parent=#PLAYERTASK] OnAfterFailed
+ -- @param #PLAYERTASK self
+ -- @param #string From From state.
+ -- @param #string Event Event.
+ -- @param #string To To state.
+
end
--- [Internal] Add a PLAYERTASKCONTROLLER for this task
@@ -146,7 +243,7 @@ end
-- @param Ops.PlayerTask#PLAYERTASKCONTROLLER Controller
-- @return #PLAYERTASK self
function PLAYERTASK:_SetController(Controller)
- self:I(self.lid.."_SetController")
+ self:T(self.lid.."_SetController")
self.TaskController = Controller
return self
end
@@ -155,7 +252,7 @@ end
-- @param #PLAYERTASK self
-- @return #boolean done
function PLAYERTASK:IsDone()
- self:I(self.lid.."IsDone?")
+ self:T(self.lid.."IsDone?")
local IsDone = false
local state = self:GetState()
if state == "Done" or state == "Stopped" then
@@ -168,17 +265,25 @@ end
-- @param #PLAYERTASK self
-- @return #table clients
function PLAYERTASK:GetClients()
- self:I(self.lid.."GetClients?")
+ self:T(self.lid.."GetClients")
local clientlist = self.Clients:GetIDStackSorted() or {}
return clientlist
end
+--- [User] Count clients
+-- @param #PLAYERTASK self
+-- @return #number clientcount
+function PLAYERTASK:CountClients()
+ self:T(self.lid.."CountClients")
+ return self.Clients:Count()
+end
+
--- [User] Check if a player name is assigned to this task
-- @param #PLAYERTASK self
-- @param #string Name
-- @return #boolean HasName
function PLAYERTASK:HasPlayerName(Name)
- self:I(self.lid.."HasPlayerName?")
+ self:T(self.lid.."HasPlayerName?")
return self.Clients:HasUniqueID(Name)
end
@@ -187,7 +292,7 @@ end
-- @param Wrapper.Client#CLIENT Client
-- @return #PLAYERTASK self
function PLAYERTASK:AddClient(Client)
- self:I(self.lid.."AddClient")
+ self:T(self.lid.."AddClient")
local name = Client:GetPlayerName()
if not self.Clients:HasUniqueID(name) then
self.Clients:Push(Client,name)
@@ -201,7 +306,7 @@ end
-- @param Wrapper.Client#CLIENT Client
-- @return #PLAYERTASK self
function PLAYERTASK:RemoveClient(Client)
- self:I(self.lid.."RemoveClient")
+ self:T(self.lid.."RemoveClient")
local name = Client:GetPlayerName()
if self.Clients:HasUniqueID(name) then
self.Clients:PullByID(name)
@@ -221,7 +326,7 @@ end
-- @param Wrapper.Client#CLIENT Client (optional)
-- @return #PLAYERTASK self
function PLAYERTASK:ClientAbort(Client)
- self:I(self.lid.."ClientAbort")
+ self:T(self.lid.."ClientAbort")
if Client and Client:IsAlive() then
self:RemoveClient(Client)
self:__ClientAborted(-1,Client)
@@ -238,9 +343,10 @@ end
--- [User] Create target mark on F10 map
-- @param #PLAYERTASK self
+-- @param #string Text (optional) Text to show on the marker
-- @return #PLAYERTASK self
-function PLAYERTASK:MarkTargetOnF10Map()
- self:I(self.lid.."MarkTargetOnF10Map")
+function PLAYERTASK:MarkTargetOnF10Map(Text)
+ self:T(self.lid.."MarkTargetOnF10Map")
if self.Target then
local coordinate = self.Target:GetCoordinate()
if coordinate then
@@ -248,6 +354,7 @@ function PLAYERTASK:MarkTargetOnF10Map()
-- Marker exists, delete one first
self.TargetMarker:Remove()
end
+ local text = Text or "Target of "..self.lid
self.TargetMarker = MARKER:New(coordinate,"Target of "..self.lid)
self.TargetMarker:ReadOnly()
self.TargetMarker:ToAll()
@@ -261,7 +368,7 @@ end
-- @param #number Color, defaults to SMOKECOLOR.Red
-- @return #PLAYERTASK self
function PLAYERTASK:SmokeTarget(Color)
- self:I(self.lid.."SmokeTarget")
+ self:T(self.lid.."SmokeTarget")
local color = Color or SMOKECOLOR.Red
if self.Target then
local coordinate = self.Target:GetCoordinate()
@@ -277,7 +384,7 @@ end
-- @param #number Color, defaults to FLARECOLOR.Red
-- @return #PLAYERTASK self
function PLAYERTASK:FlareTarget(Color)
- self:I(self.lid.."SmokeTarget")
+ self:T(self.lid.."SmokeTarget")
local color = Color or FLARECOLOR.Red
if self.Target then
local coordinate = self.Target:GetCoordinate()
@@ -361,8 +468,8 @@ end
-- @param #string To
-- @return #PLAYERTASK self
function PLAYERTASK:onafterStatus(From, Event, To)
- self:I({From, Event, To})
- self:I(self.lid.."onafterStatus")
+ self:T({From, Event, To})
+ self:T(self.lid.."onafterStatus")
local status = self:GetState()
@@ -429,7 +536,7 @@ end
-- @param #string To
-- @return #PLAYERTASK self
function PLAYERTASK:onafterPlanned(From, Event, To)
- self:I({From, Event, To})
+ self:T({From, Event, To})
return self
end
@@ -440,7 +547,7 @@ end
-- @param #string To
-- @return #PLAYERTASK self
function PLAYERTASK:onafterRequested(From, Event, To)
- self:I({From, Event, To})
+ self:T({From, Event, To})
return self
end
@@ -451,7 +558,7 @@ end
-- @param #string To
-- @return #PLAYERTASK self
function PLAYERTASK:onafterExecuting(From, Event, To)
- self:I({From, Event, To})
+ self:T({From, Event, To})
return self
end
@@ -462,7 +569,7 @@ end
-- @param #string To
-- @return #PLAYERTASK self
function PLAYERTASK:onafterStop(From, Event, To)
- self:I({From, Event, To})
+ self:T({From, Event, To})
return self
end
@@ -474,9 +581,9 @@ end
-- @param Wrapper.Client#CLIENT Client
-- @return #PLAYERTASK self
function PLAYERTASK:onafterClientAdded(From, Event, To, Client)
- self:I({From, Event, To})
- if Client then
- local text = string.format("Player %s joined task %d!",Client:GetPlayerName() or "Generic",self.PlayerTaskNr)
+ self:T({From, Event, To})
+ if Client and self.verbose then
+ local text = string.format("Player %s joined task %03d!",Client:GetPlayerName() or "Generic",self.PlayerTaskNr)
self:I(self.lid..text)
end
return self
@@ -489,7 +596,7 @@ end
-- @param #string To
-- @return #PLAYERTASK self
function PLAYERTASK:onafterDone(From, Event, To)
- self:I({From, Event, To})
+ self:T({From, Event, To})
if self.TaskController then
self.TaskController:__TaskDone(-1,self)
end
@@ -504,7 +611,7 @@ end
-- @param #string To
-- @return #PLAYERTASK self
function PLAYERTASK:onafterCancel(From, Event, To)
- self:I({From, Event, To})
+ self:T({From, Event, To})
if self.TaskController then
self.TaskController:__TaskCancelled(-1,self)
end
@@ -519,7 +626,7 @@ end
-- @param #string To
-- @return #PLAYERTASK self
function PLAYERTASK:onafterSuccess(From, Event, To)
- self:I({From, Event, To})
+ self:T({From, Event, To})
if self.TaskController then
self.TaskController:__TaskSuccess(-1,self)
end
@@ -537,7 +644,7 @@ end
-- @param #string To
-- @return #PLAYERTASK self
function PLAYERTASK:onafterFailed(From, Event, To)
- self:I({From, Event, To})
+ self:T({From, Event, To})
self.repeats = self.repeats + 1
-- repeat on failed?
if self.Repeat and (self.repeats <= self.RepeatNo) then
@@ -557,7 +664,12 @@ function PLAYERTASK:onafterFailed(From, Event, To)
end
return self
end
+-------------------------------------------------------------------------------------------------------------------
+-- END PLAYERTASK
+-------------------------------------------------------------------------------------------------------------------
+end
+do
-------------------------------------------------------------------------------------------------------------------
-- PLAYERTASKCONTROLLER
-- TODO: PLAYERTASKCONTROLLER
@@ -571,16 +683,277 @@ end
-- @field Utilities.FiFo#FIFO TargetQueue
-- @field Utilities.FiFo#FIFO TaskQueue
-- @field Utilities.FiFo#FIFO TasksPerPlayer
+-- @field Utilities.FiFo#FIFO PrecisionTasks
-- @field Core.Set#SET_CLIENT ClientSet
-- @field #string ClientFilter
-- @field #string Name
-- @field #string Type
-- @field #boolean UseGroupNames
-- @field #table PlayerMenu
---
-
+-- @field #boolean usecluster
+-- @field #number ClusterRadius
+-- @field #string MenuName
+-- @field #boolean NoScreenOutput
+-- @field #number TargetRadius
+-- @field #boolean UseWhiteList
+-- @field #table WhiteList
+-- @field #boolean UseBlackList
+-- @field #table BlackList
+-- @field Core.TextAndSound#TEXTANDSOUND gettext
+-- @field #string locale
+-- @field #boolean precisionbombing
+-- @field Ops.FlightGroup#FLIGHTGROUP LasingDrone
+-- @extends Core.Fsm#FSM
---
+--
+-- *It is our attitude at the beginning of a difficult task which, more than anything else, which will affect its successful outcome.* (William James)
+--
+-- ===
+--
+-- # PLAYERTASKCONTROLLER
+--
+-- * Simplifies defining, executing and controlling of Player tasks
+-- * FSM events when a mission is added, done, successful or failed, replanned
+-- * Ready to use SRS and localization
+-- * Mission locations can be smoked, flared and marked on the map
+--
+-- ## 1 Overview
+--
+-- PLAYERTASKCONTROLLER is used to auto-create (optional) and control tasks for players. It can be set up as Air-to-Ground (A2G, main focus), Air-to-Ship (A2S) or Air-to-Air (A2A) controller.
+-- For the latter task type, also have a look at the @{Ops.Awacs#AWACS} class which allows for more complex scenarios.
+-- One task at a time can be joined by the player from the F10 menu. A task can be joined by multiple players. Once joined, task information is available via the F10 menu, the task location
+-- can be marked on the map and for A2G/S targets, the target can be marked with smoke and flares.
+--
+-- For the mission designer, tasks can be auto-created by means of detection with the integrated @{Ops.Intel#INTEL} class setup, or be manually added to the task queue.
+--
+-- ## 2 Task Types
+--
+-- Targets can be of types GROUP, SET\_GROUP, UNIT, SET\_UNIT, STATIC, SET\_STATIC, AIRBASE, ZONE or COORDINATE. The system will auto-create tasks for players from these targets.
+-- Tasks are created as @{Ops.PlayerTask#PLAYERTASK} objects, which leverage @{Ops.Target#TARGET} for the management of the actual target. The system creates these task types
+-- from the target objects:
+--
+-- * A2A - AUFTRAG.Type.INTERCEPT
+-- * A2S - AUFTRAG.Type.ANTISHIP
+-- * A2G - AUFTRAG.Type.CAS, AUFTRAG.Type.BAI, AUFTRAG.Type.SEAD, AUFTRAG.Type.BOMBING, AUFTRAG.Type.PRECISIONBOMBING, AUFTRAG.Type.BOMBRUNWAY
+-- * A2GS - A2S and A2G combined
+--
+-- Task types are derived from @{Ops.Auftrag#AUFTRAG}:
+--
+-- * CAS - Close air support, created to attack ground units, where friendly ground units are around the location in a bespoke radius (default: 500m/1km diameter)
+-- * BAI - Battlefield air interdiction, same as above, but no friendlies around
+-- * SEAD - Same as CAS, but the enemy ground units field AAA, SAM or EWR units
+-- * Bombing - Against static targets
+-- * Precision Bombing - (if enabled) Laser-guided bombing, against static targets and high-value ground targets (MBTs etc)
+-- * Bomb Runway - Against Airbase runways (in effect, drop bombs over the runway)
+-- * ZONE and COORDINATE - Targets will be scanned for GROUND or STATIC enemy units and tasks created from these
+-- * Intercept - Any airborne targets, if the controller is of type "A2A"
+-- * Anti-Ship - Any ship targets, if the controller is of type "A2S"
+--
+-- ## 3 Task repetition
+--
+-- On failure, tasks will be replanned by default for a maximum of 5 times.
+--
+-- ## 4 SETTINGS, SRS and language options (localization)
+--
+-- The system can optionally communicate to players via SRS. Also localization is available, both "en" and "de" has been build in already.
+-- Player and global @{Core.Settings#SETTINGS} for coordinates will be observed.
+--
+-- ## 5 Setup
+--
+-- A basic setup is very simple:
+--
+-- -- Settings - we want players to have a settings menu, be on imperial measures, and get directions as BR
+-- _SETTINGS:SetPlayerMenuOn()
+-- _SETTINGS:SetImperial()
+-- _SETTINGS:SetA2G_BR()
+--
+-- -- Set up the A2G task controller for the blue side named "82nd Airborne"
+-- local taskmanager = PLAYERTASKCONTROLLER:New("82nd Airborne",coalition.side.BLUE,PLAYERTASKCONTROLLER.Type.A2G)
+--
+-- -- set locale to English
+-- taskmanager:SetLocale("en")
+--
+-- -- Set up detection with grup names *containing* "Blue Recce", these will add targets to our controller via detection. Can be e.g. a drone.
+-- taskmanager:SetupIntel("Blue Recce")
+--
+-- -- Add a single Recce group name "Blue Humvee"
+-- taskmanager:AddAgent(GROUP:FindByName("Blue Humvee"))
+--
+-- -- Set the callsign for SRS and Menu name to be "Groundhog"
+-- taskmanager:SetMenuName("Groundhog")
+--
+-- -- Add accept- and reject-zones for detection
+-- -- Accept zones are handy to limit e.g. the engagement to a certain zone. The example is a round, mission editor created zone named "AcceptZone"
+-- taskmanager:AddAcceptZone(ZONE:New("AcceptZone"))
+--
+-- -- Reject zones are handy to create borders. The example is a ZONE_POLYGON, created in the mission editor, late activated with waypoints,
+-- -- named "AcceptZone#ZONE_POLYGON"
+-- taskmanager:AddRejectZone(ZONE:FindByName("RejectZone"))
+--
+-- -- Set up using SRS for messaging
+-- local hereSRSPath = "C:\\Program Files\\DCS-SimpleRadio-Standalone"
+-- local hereSRSPort = 5002
+-- -- local hereSRSGoogle = "C:\\Program Files\\DCS-SimpleRadio-Standalone\\yourkey.json"
+-- taskmanager:SetSRS({130,255},{radio.modulation.AM,radio.modulation.AM},hereSRSPath,"female","en-GB",hereSRSPort,"Microsoft Hazel Desktop",0.7,hereSRSGoogle)
+--
+-- -- Controller will announce itself under these broadcast frequencies, handy to use cold-start frequencies here of your aircraft
+-- taskmanager:SetSRSBroadcast({127.5,305},{radio.modulation.AM,radio.modulation.AM})
+--
+-- -- Example: Manually add an AIRBASE as a target
+-- taskmanager:AddTarget(AIRBASE:FindByName(AIRBASE.Caucasus.Senaki_Kolkhi))
+--
+-- -- Example: Manually add a COORDINATE as a target
+-- taskmanager:AddTarget(GROUP:FindByName("Scout Coordinate"):GetCoordinate())
+--
+-- -- Set a whitelist for tasks, e.g. skip SEAD tasks
+-- taskmanager:SetTaskWhiteList({AUFTRAG.Type.CAS, AUFTRAG.Type.BAI, AUFTRAG.Type.BOMBING, AUFTRAG.Type.BOMBRUNWAY})
+--
+-- -- Set target radius
+-- taskmanager:SetTargetRadius(1000)
+--
+-- ## 6 Localization
+--
+-- Localization for English and German texts are build-in. Default setting is English. Change with @{#PLAYERTASKCONTROLLER.SetLocale}()
+--
+-- ### 6.1 Adding Localization
+--
+-- A list of fields to be defined follows below. **Note** that in some cases `string.format()` is used to format texts for screen and SRS.
+-- Hence, the `%d`, `%s` and `%f` special characters need to appear in the exact same amount and order of appearance in the localized text or it will create errors.
+-- To add a localization, the following texts need to be translated and set in your mission script **before** @{#PLAYERTASKCONTROLLER.New}():
+--
+-- PLAYERTASKCONTROLLER.Messages = {
+-- EN = {
+-- TASKABORT = "Task aborted!",
+-- NOACTIVETASK = "No active task!",
+-- FREQUENCIES = "frequencies ",
+-- FREQUENCY = "frequency %.3f",
+-- BROADCAST = "%s, %s, switch to %s for task assignment!",
+-- CASTTS = "close air support",
+-- SEADTTS = "suppress air defense",
+-- BOMBTTS = "bombing",
+-- PRECBOMBTTS = "precision bombing",
+-- BAITTS = "battle field air interdiction",
+-- ANTISHIPTTS = "anti-ship",
+-- INTERCEPTTS = "intercept",
+-- BOMBRUNWAYTTS = "bomb runway",
+-- HAVEACTIVETASK = "You already have one active task! Complete it first!",
+-- PILOTJOINEDTASK = "%s, %s joined task %03d",
+-- TASKNAME = "%s Task ID %03d",
+-- TASKNAMETTS = "%s Task ID %03d",
+-- THREATHIGH = "high",
+-- THREATMEDIUM = "medium",
+-- THREATLOW = "low",
+-- THREATTEXT = "%s\nThreat: %s\nTargets left: %d\nCoord: %s",
+-- THREATTEXTTTS = "%s, %s. Target information for %s. Threat level %s. Targets left %d. Target location %s.",
+-- MARKTASK = "%s, %s, copy, task %03d location marked on map!",
+-- SMOKETASK = "%s, %s, copy, task %03d location smoked!",
+-- FLARETASK = "%s, %s, copy, task %03d location illuminated!",
+-- ABORTTASK = "%s, all stations, %s aborted task %03d!",
+-- UNKNOWN = "Unknown",
+-- MENUTASKING = " Tasking ",
+-- MENUACTIVE = "Active Task",
+-- MENUINFO = "Info",
+-- MENUMARK = "Mark on map",
+-- MENUSMOKE = "Smoke",
+-- MENUFLARE = "Flare",
+-- MENUABORT = "Abort",
+-- MENUJOIN = "Join Task",
+-- MENUTASKNO = "TaskNo",
+-- MENUNOTASKS = "Currently no tasks available.",
+-- TASKCANCELLED = "Task #%03d %s is cancelled!",
+-- TASKCANCELLEDTTS = "%s, task %03d %s is cancelled!",
+-- TASKSUCCESS = "Task #%03d %s completed successfully!",
+-- TASKSUCCESSTTS = "%s, task %03d %s completed successfully!",
+-- TASKFAILED = "Task #%03d %s was a failure!",
+-- TASKFAILEDTTS = "%s, task %03d %s was a failure!",
+-- TASKFAILEDREPLAN = "Task #%03d %s was a failure! Replanning!",
+-- TASKFAILEDREPLANTTS = "%s, task %03d %s was a failure! Replanning!",
+-- TASKADDED = "%s has a new task %s available!",
+-- PILOTS = "\nPilot(s): ",
+-- PILOTSTTS = ". Pilot(s): ",
+-- YES = "Yes",
+-- NO = "No",
+-- POINTEROVERTARGET = "%s, %s, pointer over target for task %03d, lasing!",
+-- POINTERTARGETREPORT = "\nPointer over target: %s\nLasing: %s",
+-- POINTERTARGETLASINGTTS = ". Pointer over target and lasing.",
+-- },
+--
+-- e.g.
+--
+-- taskmanager.Messages = {
+-- FR = {
+-- TASKABORT = "Tâche abandonnée!",
+-- NOACTIVETASK = "Aucune tâche active!",
+-- FREQUENCIES = "fréquences ",
+-- FREQUENCY = "fréquence %.3f",
+-- BROADCAST = "%s, %s, passer au %s pour l'attribution des tâches!",
+-- ...
+-- TASKADDED = "%s a créé une nouvelle tâche %s",
+-- PILOTS = "\nPilote(s): ",
+-- PILOTSTTS = ". Pilote(s): ",
+-- },
+--
+-- and then `taskmanager:SetLocale("fr")` **after** @{#PLAYERTASKCONTROLLER.New}() in your script.
+--
+-- ## 7 Events
+--
+-- The class comes with a number of FSM-based events that missions designers can use to shape their mission.
+-- These are:
+--
+-- ### 7.1 TaskAdded.
+--
+-- The event is triggered when a new task is added to the controller. Use @{#PLAYERTASKCONTROLLER.OnAfterTaskAdded}() to link into this event:
+--
+-- function taskmanager:OnAfterTaskAdded(From, Event, To, Task)
+-- ... your code here ...
+-- end
+--
+-- ### 7.2 TaskDone.
+--
+-- The event is triggered when a task has ended. Use @{#PLAYERTASKCONTROLLER.OnAfterTaskDone}() to link into this event:
+--
+-- function taskmanager:OnAfterTaskDone(From, Event, To, Task)
+-- ... your code here ...
+-- end
+--
+-- ### 7.3 TaskCancelled.
+--
+-- The event is triggered when a task was cancelled manually. Use @{#PLAYERTASKCONTROLLER.OnAfterTaskCancelled}()` to link into this event:
+--
+-- function taskmanager:OnAfterTaskCancelled(From, Event, To, Task)
+-- ... your code here ...
+-- end
+--
+-- ### 7.4 TaskSuccess.
+--
+-- The event is triggered when a task completed successfully. Use @{#PLAYERTASKCONTROLLER.OnAfterTaskSuccess}() to link into this event:
+--
+-- function taskmanager:OnAfterTaskSuccess(From, Event, To, Task)
+-- ... your code here ...
+-- end
+--
+-- ### 7.5 TaskFailed.
+--
+-- The event is triggered when a task failed, no repeats. Use @{#PLAYERTASKCONTROLLER.OnAfterTaskFailed}() to link into this event:
+--
+-- function taskmanager:OnAfterTaskFailed(From, Event, To, Task)
+-- ... your code here ...
+-- end
+--
+-- ### 7.6 TaskRepeatOnFailed.
+--
+-- The event is triggered when a task failed and is re-planned for execution. Use @{#PLAYERTASKCONTROLLER.OnAfterRepeatOnFailed}() to link into this event:
+--
+-- function taskmanager:OnAfterRepeatOnFailed(From, Event, To, Task)
+-- ... your code here ...
+-- end
+--
+-- ## 8 Discussion
+--
+-- If you have questions or suggestions, please visit the [MOOSE Discord](https://discord.gg/AeYAkHP) #ops-playertask channel.
+--
+--
-- @field #PLAYERTASKCONTROLLER
PLAYERTASKCONTROLLER = {
ClassName = "PLAYERTASKCONTROLLER",
@@ -590,19 +963,152 @@ PLAYERTASKCONTROLLER = {
ClientSet = nil,
UseGroupNames = true,
PlayerMenu = {},
+ usecluster = false,
+ MenuName = nil,
+ ClusterRadius = 1250,
+ NoScreenOutput = false,
+ TargetRadius = 500,
+ UseWhiteList = false,
+ WhiteList = {},
+ gettext = nil,
+ locale = "en",
+ precisionbombing = false,
}
---
--- @field Type
+-- @type Type
+-- @field #string A2A Air-to-Air Controller
+-- @field #string A2G Air-to-Ground Controller
+-- @field #string A2S Air-to-Ship Controller
+-- @field #string A2GS Air-to-Ground-and-Ship Controller
PLAYERTASKCONTROLLER.Type = {
A2A = "Air-To-Air",
A2G = "Air-To-Ground",
A2S = "Air-To-Sea",
+ A2GS = "Air-To-Ground-Sea",
+}
+
+--- Define a new AUFTRAG Type
+AUFTRAG.Type.PRECISIONBOMBING = "Precision Bombing"
+
+---
+-- @field Messages
+PLAYERTASKCONTROLLER.Messages = {
+ EN = {
+ TASKABORT = "Task aborted!",
+ NOACTIVETASK = "No active task!",
+ FREQUENCIES = "frequencies ",
+ FREQUENCY = "frequency %.3f",
+ BROADCAST = "%s, %s, switch to %s for task assignment!",
+ CASTTS = "close air support",
+ SEADTTS = "suppress air defense",
+ BOMBTTS = "bombing",
+ PRECBOMBTTS = "precision bombing",
+ BAITTS = "battle field air interdiction",
+ ANTISHIPTTS = "anti-ship",
+ INTERCEPTTS = "intercept",
+ BOMBRUNWAYTTS = "bomb runway",
+ HAVEACTIVETASK = "You already have one active task! Complete it first!",
+ PILOTJOINEDTASK = "%s, %s joined task %03d",
+ TASKNAME = "%s Task ID %03d",
+ TASKNAMETTS = "%s Task ID %03d",
+ THREATHIGH = "high",
+ THREATMEDIUM = "medium",
+ THREATLOW = "low",
+ THREATTEXT = "%s\nThreat: %s\nTargets left: %d\nCoord: %s",
+ THREATTEXTTTS = "%s, %s. Target information for %s. Threat level %s. Targets left %d. Target location %s.",
+ MARKTASK = "%s, %s, copy, task %03d location marked on map!",
+ SMOKETASK = "%s, %s, copy, task %03d location smoked!",
+ FLARETASK = "%s, %s, copy, task %03d location illuminated!",
+ ABORTTASK = "%s, all stations, %s aborted task %03d!",
+ UNKNOWN = "Unknown",
+ MENUTASKING = " Tasking ",
+ MENUACTIVE = "Active Task",
+ MENUINFO = "Info",
+ MENUMARK = "Mark on map",
+ MENUSMOKE = "Smoke",
+ MENUFLARE = "Flare",
+ MENUABORT = "Abort",
+ MENUJOIN = "Join Task",
+ MENUTASKNO = "TaskNo",
+ MENUNOTASKS = "Currently no tasks available.",
+ TASKCANCELLED = "Task #%03d %s is cancelled!",
+ TASKCANCELLEDTTS = "%s, task %03d %s is cancelled!",
+ TASKSUCCESS = "Task #%03d %s completed successfully!",
+ TASKSUCCESSTTS = "%s, task %03d %s completed successfully!",
+ TASKFAILED = "Task #%03d %s was a failure!",
+ TASKFAILEDTTS = "%s, task %03d %s was a failure!",
+ TASKFAILEDREPLAN = "Task #%03d %s was a failure! Replanning!",
+ TASKFAILEDREPLANTTS = "%s, task %03d %s was a failure! Replanning!",
+ TASKADDED = "%s has a new task %s available!",
+ PILOTS = "\nPilot(s): ",
+ PILOTSTTS = ". Pilot(s): ",
+ YES = "Yes",
+ NO = "No",
+ POINTEROVERTARGET = "%s, %s, pointer over target for task %03d, lasing!",
+ POINTERTARGETREPORT = "\nPointer over target: %s\nLasing: %s",
+ POINTERTARGETLASINGTTS = ". Pointer over target and lasing.",
+ },
+ DE = {
+ TASKABORT = "Auftrag abgebrochen!",
+ NOACTIVETASK = "Kein aktiver Auftrag!",
+ FREQUENCIES = "Frequenzen ",
+ FREQUENCY = "Frequenz %.3f",
+ BROADCAST = "%s, %s, Radio %s für Aufgabenzuteilung!",
+ CASTTS = "Nahbereichsunterstützung",
+ SEADTTS = "Luftabwehr ausschalten",
+ BOMBTTS = "Bombardieren",
+ PRECBOMBTTS = "Präzisionsbombardieren",
+ BAITTS = "Luftunterstützung",
+ ANTISHIPTTS = "Anti-Schiff",
+ INTERCEPTTS = "Abfangen",
+ BOMBRUNWAYTTS = "Startbahn Bombardieren",
+ HAVEACTIVETASK = "Du hast einen aktiven Auftrag! Beende ihn zuerst!",
+ PILOTJOINEDTASK = "%s, %s hat Auftrag %03d angenommen",
+ TASKNAME = "%s Auftrag ID %03d",
+ TASKNAMETTS = "%s Auftrag ID %03d",
+ THREATHIGH = "hoch",
+ THREATMEDIUM = "mittel",
+ THREATLOW = "niedrig",
+ THREATTEXT = "%s\nGefahrstufe: %s\nZiele: %d\nKoord: %s",
+ THREATTEXTTTS = "%s, %s. Zielinformation zu %s. Gefahrstufe %s. Ziele %d. Zielposition %s.",
+ MARKTASK = "%s, %s, verstanden, Zielposition %03d auf der Karte markiert!",
+ SMOKETASK = "%s, %s, verstanden, Zielposition %03d mit Rauch markiert!",
+ FLARETASK = "%s, %s, verstanden, Zielposition %03d beleuchtet!",
+ ABORTTASK = "%s, an alle, %s hat Auftrag %03d abgebrochen!",
+ UNKNOWN = "Unbekannt",
+ MENUTASKING = " Aufträge ",
+ MENUACTIVE = "Aktiver Auftrag",
+ MENUINFO = "Information",
+ MENUMARK = "Kartenmarkierung",
+ MENUSMOKE = "Rauchgranate",
+ MENUFLARE = "Leuchtgranate",
+ MENUABORT = "Abbrechen",
+ MENUJOIN = "Auftrag annehmen",
+ MENUTASKNO = "AuftragsNr",
+ MENUNOTASKS = "Momentan keine Aufträge verfügbar.",
+ TASKCANCELLED = "Auftrag #%03d %s wurde beendet!",
+ TASKCANCELLEDTTS = "%s, Auftrag %03d %s wurde beendet!",
+ TASKSUCCESS = "Auftrag #%03d %s erfolgreich!",
+ TASKSUCCESSTTS = "%s, Auftrag %03d %s erfolgreich!",
+ TASKFAILED = "Auftrag #%03d %s gescheitert!",
+ TASKFAILEDTTS = "%s, Auftrag %03d %s gescheitert!",
+ TASKFAILEDREPLAN = "Auftrag #%03d %s gescheitert! Neuplanung!",
+ TASKFAILEDREPLANTTS = "%s, Auftrag %03d %s gescheitert! Neuplanung!",
+ TASKADDED = "%s hat einen neuen Auftrag %s erstellt!",
+ PILOTS = "\nPilot(en): ",
+ PILOTSTTS = ". Pilot(en): ",
+ YES = "Ja",
+ NO = "Nein",
+ POINTEROVERTARGET = "%s, %s, Marker im Zielbereich für %03d, Laser an!",
+ POINTERTARGETREPORT = "\nMarker im Zielbereich: %s\nLaser an: %s",
+ POINTERTARGETLASINGTTS = ". Marker im Zielbereich, Laser is an.",
+ },
}
--- PLAYERTASK class version.
-- @field #string version
-PLAYERTASKCONTROLLER.version="0.0.7"
+PLAYERTASKCONTROLLER.version="0.1.25"
--- Constructor
-- @param #PLAYERTASKCONTROLLER self
@@ -620,17 +1126,29 @@ function PLAYERTASKCONTROLLER:New(Name, Coalition, Type, ClientFilter)
self.Coalition = Coalition or coalition.side.BLUE
self.CoalitionName = UTILS.GetCoalitionName(Coalition)
self.Type = Type or PLAYERTASKCONTROLLER.Type.A2G
+
+ self.usecluster = false
+ if self.Type == PLAYERTASKCONTROLLER.Type.A2A then
+ self.usecluster = true
+ end
+
+ self.ClusterRadius = 1250
+ self.TargetRadius = 500
+
self.ClientFilter = ClientFilter or ""
self.TargetQueue = FIFO:New() -- Utilities.FiFo#FIFO
self.TaskQueue = FIFO:New() -- Utilities.FiFo#FIFO
self.TasksPerPlayer = FIFO:New() -- Utilities.FiFo#FIFO
+ self.PrecisionTasks = FIFO:New() -- Utilities.FiFo#FIFO
self.PlayerMenu = {} -- #table
+ self.MenuName = nil
+
self.repeatonfailed = true
self.repeattimes = 5
self.UseGroupNames = true
-
+
if ClientFilter then
self.ClientSet = SET_CLIENT:New():FilterCoalitions(string.lower(self.CoalitionName)):FilterActive(true):FilterPrefixes(ClientFilter):FilterStart()
else
@@ -639,6 +1157,8 @@ function PLAYERTASKCONTROLLER:New(Name, Coalition, Type, ClientFilter)
self.lid=string.format("PlayerTaskController %s %s | ", self.Name, tostring(self.Type))
+ self:_InitLocalization()
+
-- FSM start state is STOPPED.
self:SetStartState("Stopped")
@@ -660,21 +1180,189 @@ function PLAYERTASKCONTROLLER:New(Name, Coalition, Type, ClientFilter)
self:HandleEvent(EVENTS.Ejection, self._EventHandler)
self:HandleEvent(EVENTS.Crash, self._EventHandler)
self:HandleEvent(EVENTS.PilotDead, self._EventHandler)
+ self:HandleEvent(EVENTS.PlayerEnterAircraft, self._EventHandler)
- self:I(self.lid.."Started.")
+ self:I(self.lid..self.version.." Started.")
return self
+
+ ---
+ -- Pseudo Functions
+ ---
+
+ --- On After "TaskAdded" event. Task has been added.
+ -- @function [parent=#PLAYERTASKCONTROLLER] OnAfterTaskAdded
+ -- @param #PLAYERTASKCONTROLLER self
+ -- @param #string From From state.
+ -- @param #string Event Event.
+ -- @param #string To To state.
+ -- @param Ops.PlayerTask#PLAYERTASK Task
+
+ --- On After "TaskDone" event. Task is done.
+ -- @function [parent=#PLAYERTASKCONTROLLER] OnAfterTaskDone
+ -- @param #PLAYERTASKCONTROLLER self
+ -- @param #string From From state.
+ -- @param #string Event Event.
+ -- @param #string To To state.
+ -- @param Ops.PlayerTask#PLAYERTASK Task
+
+ --- On After "TaskCancelled" event. Task has been cancelled.
+ -- @function [parent=#PLAYERTASKCONTROLLER] OnAfterTaskCancelled
+ -- @param #PLAYERTASKCONTROLLER self
+ -- @param #string From From state.
+ -- @param #string Event Event.
+ -- @param #string To To state.
+ -- @param Ops.PlayerTask#PLAYERTASK Task
+
+ --- On After "TaskFailed" event. Task has failed.
+ -- @function [parent=#PLAYERTASKCONTROLLER] OnAfterTaskFailed
+ -- @param #PLAYERTASKCONTROLLER self
+ -- @param #string From From state.
+ -- @param #string Event Event.
+ -- @param #string To To state.
+ -- @param Ops.PlayerTask#PLAYERTASK Task
+
+ --- On After "TaskSuccess" event. Task has been a success.
+ -- @function [parent=#PLAYERTASKCONTROLLER] OnAfterTaskSuccess
+ -- @param #PLAYERTASKCONTROLLER self
+ -- @param #string From From state.
+ -- @param #string Event Event.
+ -- @param #string To To state.
+ -- @param Ops.PlayerTask#PLAYERTASK Task
+
+ --- On After "TaskRepeatOnFailed" event. Task has failed and will be repeated.
+ -- @function [parent=#PLAYERTASKCONTROLLER] OnAfterTaskRepeatOnFailed
+ -- @param #PLAYERTASKCONTROLLER self
+ -- @param #string From From state.
+ -- @param #string Event Event.
+ -- @param #string To To state.
+ -- @param Ops.PlayerTask#PLAYERTASK Task
+
+end
+
+--- [Internal] Init localization
+-- @param #PLAYERTASKCONTROLLER self
+-- @return #PLAYERTASKCONTROLLER self
+function PLAYERTASKCONTROLLER:_InitLocalization()
+ self:T(self.lid.."_InitLocalization")
+ self.gettext = TEXTANDSOUND:New("PLAYERTASKCONTROLLER","en") -- Core.TextAndSound#TEXTANDSOUND
+ self.locale = "en"
+ for locale,table in pairs(self.Messages) do
+ local Locale = string.lower(tostring(locale))
+ self:T("**** Adding locale: "..Locale)
+ for ID,Text in pairs(table) do
+ self:T(string.format('Adding ID %s',tostring(ID)))
+ self.gettext:AddEntry(Locale,tostring(ID),Text)
+ end
+ end
+ return self
end
---- [internal] Event handling
+--- [User] Set repetition options for tasks
+-- @param #PLAYERTASKCONTROLLER self
+-- @param #boolean OnOff Set to `true` to switch on and `false` to switch off (defaults to true)
+-- @param #number Repeats Number of repeats (defaults to 5)
+-- @return #PLAYERTASKCONTROLLER self
+-- @usage `taskmanager:SetTaskRepetition(true, 5)`
+function PLAYERTASKCONTROLLER:SetTaskRepetition(OnOff, Repeats)
+ self:T(self.lid.."SetTaskRepetition")
+ if OnOff then
+ self.repeatonfailed = true
+ self.repeattimes = Repeats or 5
+ else
+ self.repeatonfailed = false
+ self.repeattimes = Repeats or 5
+ end
+ return self
+end
+
+--- [User] Allow precision laser-guided bombing on statics and "high-value" ground units (MBT etc)
+-- @param #PLAYERTASKCONTROLLER self
+-- @param Ops.FlightGroup#FLIGHTGROUP FlightGroup The FlightGroup (e.g. drone) to be used for lasing (one unit in one group only).
+-- Can optionally be handed as Ops.ArmyGroup#ARMYGROUP - **Note** might not find an LOS spot or get lost on the way. Cannot island-hop.
+-- @param #number LaserCode The lasercode to be used. Defaults to 1688.
+-- @return #PLAYERTASKCONTROLLER self
+-- @usage
+-- -- Set up precision bombing, FlightGroup as lasing unit
+-- local FlightGroup = FLIGHTGROUP:New("LasingUnit")
+-- FlightGroup:Activate()
+-- taskmanager:EnablePrecisionBombing(FlightGroup,1688)
+--
+-- -- Alternatively, set up precision bombing, ArmyGroup as lasing unit
+-- local ArmyGroup = ARMYGROUP:New("LasingUnit")
+-- ArmyGroup:SetDefaultROE(ENUMS.ROE.WeaponHold)
+-- ArmyGroup:SetDefaultInvisible(true)
+-- ArmyGroup:Activate()
+-- taskmanager:EnablePrecisionBombing(ArmyGroup,1688)
+--
+function PLAYERTASKCONTROLLER:EnablePrecisionBombing(FlightGroup,LaserCode)
+ self:T(self.lid.."EnablePrecisionBombing")
+ if FlightGroup then
+ if FlightGroup.ClassName and (FlightGroup.ClassName == "FLIGHTGROUP" or FlightGroup.ClassName == "ARMYGROUP")then
+ -- ok we have a FG
+ self.LasingDrone = FlightGroup -- Ops.FlightGroup#FLIGHTGROUP FlightGroup
+ self.LasingDrone.playertask = {}
+ self.LasingDrone.playertask.busy = false
+ self.LasingDrone.playertask.id = 0
+ self.precisionbombing = true
+ self.LasingDrone:SetLaser(LaserCode)
+ self.LaserCode = LaserCode or 1688
+ self.LasingDroneTemplate = self.LasingDrone:_GetTemplate(true)
+ -- let it orbit the BullsEye if FG
+ if self.LasingDrone:IsFlightgroup() then
+ local BullsCoordinate = COORDINATE:NewFromVec3( coalition.getMainRefPoint( self.Coalition ))
+ local Orbit = AUFTRAG:NewORBIT_CIRCLE(BullsCoordinate,10000,120)
+ self.LasingDrone:AddMission(Orbit)
+ end
+ else
+ self:E(self.lid.."No FLIGHTGROUP object passed or FLIGHTGROUP is not alive!")
+ end
+ else
+ self.autolase = nil
+ self.precisionbombing = false
+ end
+ return self
+end
+
+--- [Internal] Get player name
+-- @param #PLAYERTASKCONTROLLER self
+-- @param Wrapper.Client#CLIENT Client
+-- @return #string playername
+-- @return #string ttsplayername
+function PLAYERTASKCONTROLLER:_GetPlayerName(Client)
+ self:T(self.lid.."DisablePrecisionBombing")
+ local playername = Client:GetPlayerName()
+ local ttsplayername = playername
+ if string.find(playername,"|") then
+ -- personalized flight name in player naming
+ ttsplayername = string.match(playername,"| ([%a]+)")
+ end
+ if string.find(playername,"#") then
+ -- personalized flight name in player naming
+ ttsplayername = string.match(playername,"# ([%a]+)")
+ end
+ return playername, ttsplayername
+end
+
+--- [User] Disable precision laser-guided bombing on statics and "high-value" ground units (MBT etc)
+-- @param #PLAYERTASKCONTROLLER self
+-- @return #PLAYERTASKCONTROLLER self
+function PLAYERTASKCONTROLLER:DisablePrecisionBombing(FlightGroup,LaserCode)
+ self:T(self.lid.."DisablePrecisionBombing")
+ self.autolase = nil
+ self.precisionbombing = false
+ return self
+end
+
+--- [Internal] Event handling
-- @param #PLAYERTASKCONTROLLER self
-- @param Core.Event#EVENTDATA EventData
-- @return #PLAYERTASKCONTROLLER self
function PLAYERTASKCONTROLLER:_EventHandler(EventData)
- self:I(self.lid.."_EventHandler: "..EventData.id)
+ self:T(self.lid.."_EventHandler: "..EventData.id)
if EventData.id == EVENTS.PlayerLeaveUnit or EventData.id == EVENTS.Ejection or EventData.id == EVENTS.Crash or EventData.id == EVENTS.PilotDead then
if EventData.IniPlayerName then
- self:I(self.lid.."Event for player: "..EventData.IniPlayerName)
+ self:T(self.lid.."Event for player: "..EventData.IniPlayerName)
if self.PlayerMenu[EventData.IniPlayerName] then
self.PlayerMenu[EventData.IniPlayerName]:Remove()
self.PlayerMenu[EventData.IniPlayerName] = nil
@@ -685,28 +1373,108 @@ function PLAYERTASKCONTROLLER:_EventHandler(EventData)
local Client = _DATABASE:FindClient( EventData.IniPlayerName )
if Client then
task:RemoveClient(Client)
- text = "Task aborted!"
+ --text = "Task aborted!"
+ text = self.gettext:GetEntry("TASKABORT",self.locale)
end
else
- text = "No active task!"
+ --text = "No active task!"
+ text = self.gettext:GetEntry("NOACTIVETASK",self.locale)
end
- self:I(self.lid..text)
+ self:T(self.lid..text)
+ end
+ elseif EventData.id == EVENTS.PlayerEnterAircraft and EventData.IniCoalition == self.Coalition then
+ if EventData.IniPlayerName and EventData.IniGroup and self.UseSRS then
+ self:T(self.lid.."Event for player: "..EventData.IniPlayerName)
+ local frequency = self.Frequency
+ local freqtext = ""
+ if type(frequency) == "table" then
+ freqtext = self.gettext:GetEntry("FREQUENCIES",self.locale)
+ freqtext = freqtext..table.concat(frequency,", ")
+ else
+ local freqt = self.gettext:GetEntry("FREQUENCY",self.locale)
+ freqtext = string.format(freqt,frequency)
+ end
+ local modulation = self.Modulation
+ if type(modulation) == "table" then modulation = modulation[1] end
+ modulation = UTILS.GetModulationName(modulation)
+ local switchtext = self.gettext:GetEntry("BROADCAST",self.locale)
+
+ local playername = EventData.IniPlayerName
+ if string.find(playername,"|") then
+ -- personalized flight name in player naming
+ playername = string.match(playername,"| ([%a]+)")
+ end
+ --local text = string.format("%s, %s, switch to %s for task assignment!",EventData.IniPlayerName,self.MenuName or self.Name,freqtext)
+ local text = string.format(switchtext,self.MenuName or self.Name,playername,freqtext)
+ self.SRSQueue:NewTransmission(text,nil,self.SRS,timer.getAbsTime()+60,2,{EventData.IniGroup},text,30,self.BCFrequency,self.BCModulation)
end
end
return self
end
function PLAYERTASKCONTROLLER:_DummyMenu(group)
- self:I(self.lid.."_DummyMenu")
+ self:T(self.lid.."_DummyMenu")
return self
end
---- [user] Switch usage of target names for menu entries on or off
+--- [User] Set locale for localization. Defaults to "en"
+-- @param #PLAYERTASKCONTROLLER self
+-- @param #string Locale The locale to use
+-- @return #PLAYERTASKCONTROLLER self
+function PLAYERTASKCONTROLLER:SetLocale(Locale)
+ self:T(self.lid.."SetLocale")
+ self.locale = Locale or "en"
+ return self
+end
+
+--- [User] Switch screen output.
+-- @param #PLAYERTASKCONTROLLER self
+-- @param #boolean OnOff. Switch screen output off (true) or on (false)
+-- @return #PLAYERTASKCONTROLLER self
+function PLAYERTASKCONTROLLER:SuppressScreenOutput(OnOff)
+ self:T(self.lid.."SuppressScreenOutput")
+ self.NoScreenOutput = OnOff or false
+ return self
+end
+
+--- [User] Set target radius. Determines the zone radius to distinguish CAS from BAI tasks and to find enemies if the TARGET object is a COORDINATE.
+-- @param #PLAYERTASKCONTROLLER self
+-- @param #number Radius Radius to use in meters. Defaults to 500 meters.
+-- @return #PLAYERTASKCONTROLLER self
+function PLAYERTASKCONTROLLER:SetTargetRadius(Radius)
+ self:T(self.lid.."SetTargetRadius")
+ self.TargetRadius = Radius or 500
+ return self
+end
+
+--- [User] Set the cluster radius if you want to use target clusters rather than single group detection.
+-- Note that for a controller type A2A target clustering is on by default. Also remember that the diameter of the resulting zone is double the radius.
+-- @param #PLAYERTASKCONTROLLER self
+-- @param #number Radius Target cluster radius in meters. Default is 1250m or 0.67NM
+-- @return #PLAYERTASKCONTROLLER self
+function PLAYERTASKCONTROLLER:SetClusterRadius(Radius)
+ self:T(self.lid.."SetClusterRadius")
+ self.ClusterRadius = Radius or 1250
+ self.usecluster = true
+ return self
+end
+
+--- [User] Manually cancel a specific task
+-- @param #PLAYERTASKCONTROLLER self
+-- @param Ops.PlayerTask#PLAYERTASK Task The task to be cancelled
+-- @return #PLAYERTASKCONTROLLER self
+function PLAYERTASKCONTROLLER:CancelTask(Task)
+ self:T(self.lid.."CancelTask")
+ Task:__Cancel(-1)
+ return self
+end
+
+--- [User] Switch usage of target names for menu entries on or off
-- @param #PLAYERTASKCONTROLLER self
-- @param #boolean OnOff If true, set to on (default), if nil or false, set to off
-- @return #PLAYERTASKCONTROLLER self
function PLAYERTASKCONTROLLER:SwitchUseGroupNames(OnOff)
- self:I(self.lid.."SwitchUseGroupNames")
+ self:T(self.lid.."SwitchUseGroupNames")
if OnOff then
self.UseGroupNames = true
else
@@ -719,7 +1487,7 @@ end
-- @param #PLAYERTASKCONTROLLER self
-- @return #table TaskTypes
function PLAYERTASKCONTROLLER:_GetAvailableTaskTypes()
- self:I(self.lid.."_GetAvailableTaskTypes")
+ self:T(self.lid.."_GetAvailableTaskTypes")
local tasktypes = {}
self.TaskQueue:ForEach(
function (Task)
@@ -735,20 +1503,31 @@ end
-- @param #PLAYERTASKCONTROLLER self
-- @return #table TasksPerTypes
function PLAYERTASKCONTROLLER:_GetTasksPerType()
- self:I(self.lid.."_GetTasksPerType")
+ self:T(self.lid.."_GetTasksPerType")
local tasktypes = self:_GetAvailableTaskTypes()
- self:I({tasktypes})
+ self:T({tasktypes})
- self.TaskQueue:ForEach(
- function (Task)
- local task = Task -- Ops.PlayerTask#PLAYERTASK
- local type = Task.Type
- if task:GetState() ~= "Executing" and not task:IsDone() then
- table.insert(tasktypes[type],task)
- end
+ -- Sort tasks per threat level first
+ local datatable = self.TaskQueue:GetDataTable()
+ local threattable = {}
+ for _,_task in pairs(datatable) do
+ local task = _task -- Ops.PlayerTask#PLAYERTASK
+ local threat = task.Target:GetThreatLevelMax()
+ threattable[#threattable+1]={task=task,threat=threat}
+ end
+
+ table.sort(threattable, function (k1, k2) return k1.threat > k2.threat end )
+
+
+ for _id,_data in pairs(threattable) do
+ local threat=_data.threat
+ local task = _data.task -- Ops.PlayerTask#PLAYERTASK
+ local type = task.Type
+ if not task:IsDone() then
+ table.insert(tasktypes[type],task)
end
- )
+ end
return tasktypes
end
@@ -757,7 +1536,7 @@ end
-- @param #PLAYERTASKCONTROLLER self
-- @return #PLAYERTASKCONTROLLER self
function PLAYERTASKCONTROLLER:_CheckTargetQueue()
- self:I(self.lid.."_CheckTargetQueue")
+ self:T(self.lid.."_CheckTargetQueue")
if self.TargetQueue:Count() > 0 then
local object = self.TargetQueue:Pull()
local target = TARGET:New(object)
@@ -770,19 +1549,19 @@ end
-- @param #PLAYERTASKCONTROLLER self
-- @return #PLAYERTASKCONTROLLER self
function PLAYERTASKCONTROLLER:_CheckTaskQueue()
- self:I(self.lid.."_CheckTaskQueue")
+ self:T(self.lid.."_CheckTaskQueue")
if self.TaskQueue:Count() > 0 then
-- remove done tasks
local tasks = self.TaskQueue:GetIDStack()
for _id,_entry in pairs(tasks) do
local data = _entry.data -- Ops.PlayerTask#PLAYERTASK
- self:I("Looking at Task: "..data.PlayerTaskNr.." Type: "..data.Type.." State: "..data:GetState())
+ self:T("Looking at Task: "..data.PlayerTaskNr.." Type: "..data.Type.." State: "..data:GetState())
if data:GetState() == "Done" or data:GetState() == "Stopped" then
local task = self.TaskQueue:ReadByID(_id) -- Ops.PlayerTask#PLAYERTASK
- -- DEBUG: Remove clients from the task
+ -- DONE: Remove clients from the task
local clientsattask = task.Clients:GetIDStackSorted()
for _,_id in pairs(clientsattask) do
- self:I("*****Removing player " .. _id)
+ self:T("*****Removing player " .. _id)
self.TasksPerPlayer:PullByID(_id)
end
local task = self.TaskQueue:PullByID(_id) -- Ops.PlayerTask#PLAYERTASK
@@ -793,89 +1572,398 @@ function PLAYERTASKCONTROLLER:_CheckTaskQueue()
return self
end
---- [user] Add a target object to the target queue
+--- [Internal] Check precision task queue
-- @param #PLAYERTASKCONTROLLER self
--- @param Wrapper.Positionable#POSITIONABLE Target The target GROUP, SET_GROUP, UNIT, SET_UNIT, STATIC, AIRBASE or COORDINATE.
+-- @return #PLAYERTASKCONTROLLER self
+function PLAYERTASKCONTROLLER:_CheckPrecisionTasks()
+ self:T(self.lid.."_CheckTaskQueue")
+ if self.PrecisionTasks:Count() > 0 and self.precisionbombing then
+ if not self.LasingDrone or self.LasingDrone:IsDead() then
+ -- we need a new drone
+ self:E(self.lid.."Lasing drone is dead ... creating a new one!")
+ if self.LasingDrone then
+ self.LasingDrone:_Respawn(1,nil,true)
+ else
+ -- TODO: Handle ArmyGroup
+ local FG = FLIGHTGROUP:New(self.LasingDroneTemplate)
+ FG:Activate()
+ self:EnablePrecisionBombing(FG,self.LaserCode or 1688)
+ end
+ return self
+ end
+ -- do we have a lasing unit assigned?
+ if self.LasingDrone and self.LasingDrone:IsAlive() then
+ if self.LasingDrone.playertask and (not self.LasingDrone.playertask.busy) then
+ -- not busy, get a task
+ self:I(self.lid.."Sending lasing unit to target")
+ local task = self.PrecisionTasks:Pull() -- Ops.PlayerTask#PLAYERTASK
+ self.LasingDrone.playertask.id = task.PlayerTaskNr
+ self.LasingDrone.playertask.busy = true
+ self.LasingDrone.playertask.inreach = false
+ self.LasingDrone.playertask.reachmessage = false
+ -- move the drone to target
+ if self.LasingDrone:IsFlightgroup() then
+ local auftrag = AUFTRAG:NewORBIT_CIRCLE(task.Target:GetCoordinate(),10000,120)
+ local currmission = self.LasingDrone:GetMissionCurrent()
+ self.LasingDrone:AddMission(auftrag)
+ currmission:__Cancel(-2)
+ elseif self.LasingDrone:IsArmygroup() then
+ local tgtcoord = task.Target:GetCoordinate()
+ local tgtzone = ZONE_RADIUS:New("ArmyGroup-"..math.random(1,10000),tgtcoord:GetVec2(),3000)
+ local finalpos=nil -- Core.Point#COORDINATE
+ for i=1,50 do
+ finalpos = tgtzone:GetRandomCoordinate(2000,0,{land.SurfaceType.LAND,land.SurfaceType.ROAD,land.SurfaceType.SHALLOW_WATER})
+ if finalpos then
+ if finalpos:IsLOS(tgtcoord,0) then
+ break
+ end
+ end
+ end
+ if finalpos then
+ -- yeah we got one
+ local auftrag = AUFTRAG:NewARMOREDGUARD(finalpos)
+ local currmission = self.LasingDrone:GetMissionCurrent()
+ self.LasingDrone:AddMission(auftrag)
+ if currmission then currmission:__Cancel(-2) end
+ else
+ -- could not find LOS position!
+ self:E("***Could not find LOS position to post ArmyGroup for lasing!")
+ self.LasingDrone.playertask.id = 0
+ self.LasingDrone.playertask.busy = false
+ self.LasingDrone.playertask.inreach = false
+ self.LasingDrone.playertask.reachmessage = false
+ end
+ end
+ self.PrecisionTasks:Push(task,task.PlayerTaskNr)
+ elseif self.LasingDrone.playertask and self.LasingDrone.playertask.busy then
+ -- drone is busy, set up laser when over target
+ local task = self.PrecisionTasks:ReadByID(self.LasingDrone.playertask.id) -- Ops.PlayerTask#PLAYERTASK
+ self:I("Looking at Task: "..task.PlayerTaskNr.." Type: "..task.Type.." State: "..task:GetState())
+ if (not task) or task:GetState() == "Done" or task:GetState() == "Stopped" then
+ -- we're done here
+ local task = self.PrecisionTasks:PullByID(self.LasingDrone.playertask.id) -- Ops.PlayerTask#PLAYERTASK
+ self:_CheckTaskQueue()
+ task = nil
+ if self.LasingDrone:IsLasing() then
+ self.LasingDrone:__LaserOff(-1)
+ end
+ self.LasingDrone.playertask.busy = false
+ self.LasingDrone.playertask.inreach = false
+ self.LasingDrone.playertask.id = 0
+ self.LasingDrone.playertask.reachmessage = false
+ self:I(self.lid.."Laser Off")
+ else
+ -- not done yet
+ local dcoord = self.LasingDrone:GetCoordinate()
+ local tcoord = task.Target:GetCoordinate()
+ local dist = dcoord:Get2DDistance(tcoord)
+ -- close enough?
+ if dist < 3000 and not self.LasingDrone:IsLasing() then
+ self:I(self.lid.."Laser On")
+ self.LasingDrone:__LaserOn(-1,tcoord)
+ self.LasingDrone.playertask.inreach = true
+ if not self.LasingDrone.playertask.reachmessage then
+ --local textmark = self.gettext:GetEntry("FLARETASK",self.locale)
+ self.LasingDrone.playertask.reachmessage = true
+ local clients = task:GetClients()
+ local text = ""
+ for _,playername in pairs(clients) do
+ local pointertext = self.gettext:GetEntry("POINTEROVERTARGET",self.locale)
+ --text = string.format("%s, %s, pointer over target for task %03d, lasing!", playername, self.MenuName or self.Name, task.PlayerTaskNr)
+ text = string.format(pointertext, playername, self.MenuName or self.Name, task.PlayerTaskNr)
+ if not self.NoScreenOutput then
+ local client = nil
+ self.ClientSet:ForEachClient(
+ function(Client)
+ if Client:GetPlayerName() == playername then client = Client end
+ end
+ )
+ if client then
+ local m = MESSAGE:New(text,15,"Tasking"):ToClient(client)
+ end
+ end
+ end
+ if self.UseSRS then
+ self.SRSQueue:NewTransmission(text,nil,self.SRS,nil,2)
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ return self
+end
+
+--- [Internal] Check task queue for a specific player name
+-- @param #PLAYERTASKCONTROLLER self
+-- @return #boolean outcome
+function PLAYERTASKCONTROLLER:_CheckPlayerHasTask(PlayerName)
+ self:T(self.lid.."_CheckPlayerHasTask")
+ return self.TasksPerPlayer:HasUniqueID(PlayerName)
+end
+
+--- [User] Add a target object to the target queue
+-- @param #PLAYERTASKCONTROLLER self
+-- @param Wrapper.Positionable#POSITIONABLE Target The target GROUP, SET\_GROUP, UNIT, SET\_UNIT, STATIC, SET\_STATIC, AIRBASE, ZONE or COORDINATE.
-- @return #PLAYERTASKCONTROLLER self
function PLAYERTASKCONTROLLER:AddTarget(Target)
- self:I(self.lid.."AddTarget")
+ self:T(self.lid.."AddTarget")
self.TargetQueue:Push(Target)
return self
end
+--- [Internal] Check for allowed task type, if there is a (positive) whitelist
+-- @param #PLAYERTASKCONTROLLER self
+-- @param #string Type
+-- @return #boolean Outcome
+function PLAYERTASKCONTROLLER:_CheckTaskTypeAllowed(Type)
+ self:T(self.lid.."_CheckTaskTypeAllowed")
+ local Outcome = false
+ if self.UseWhiteList then
+ for _,_type in pairs(self.WhiteList) do
+ if Type == _type then
+ Outcome = true
+ break
+ end
+ end
+ else
+ return true
+ end
+ return Outcome
+end
+
+--- [Internal] Check for allowed task type, if there is a (negative) blacklist
+-- @param #PLAYERTASKCONTROLLER self
+-- @param #string Type
+-- @return #boolean Outcome
+function PLAYERTASKCONTROLLER:_CheckTaskTypeDisallowed(Type)
+ self:T(self.lid.."_CheckTaskTypeDisallowed")
+ local Outcome = false
+ if self.UseBlackList then
+ for _,_type in pairs(self.BlackList) do
+ if Type == _type then
+ Outcome = true
+ break
+ end
+ end
+ else
+ return true
+ end
+ return Outcome
+end
+
+--- [User] Set up a (positive) whitelist of allowed task types. Only these types will be generated.
+-- @param #PLAYERTASKCONTROLLER self
+-- @param #table WhiteList Table of task types that can be generated. Use to restrict available types.
+-- @return #PLAYERTASKCONTROLLER self
+-- @usage Currently, the following task types will be generated, if detection has been set up:
+-- A2A - AUFTRAG.Type.INTERCEPT
+-- A2S - AUFTRAG.Type.ANTISHIP
+-- A2G - AUFTRAG.Type.CAS, AUFTRAG.Type.BAI, AUFTRAG.Type.SEAD, AUFTRAG.Type.BOMBING, AUFTRAG.Type.PRECISIONBOMBING, AUFTRAG.Type.BOMBRUNWAY
+-- A2GS - A2G + A2S
+-- If you don't want SEAD tasks generated, use as follows where "mycontroller" is your PLAYERTASKCONTROLLER object:
+--
+-- `mycontroller:SetTaskWhiteList({AUFTRAG.Type.CAS, AUFTRAG.Type.BAI, AUFTRAG.Type.BOMBING, AUFTRAG.Type.BOMBRUNWAY})`
+--
+function PLAYERTASKCONTROLLER:SetTaskWhiteList(WhiteList)
+ self:T(self.lid.."SetTaskWhiteList")
+ self.WhiteList = WhiteList
+ self.UseWhiteList = true
+ return self
+end
+
+--- [User] Set up a (negative) blacklist of forbidden task types. These types will **not** be generated.
+-- @param #PLAYERTASKCONTROLLER self
+-- @param #table BlackList Table of task types that cannot be generated. Use to restrict available types.
+-- @return #PLAYERTASKCONTROLLER self
+-- @usage Currently, the following task types will be generated, if detection has been set up:
+-- A2A - AUFTRAG.Type.INTERCEPT
+-- A2S - AUFTRAG.Type.ANTISHIP
+-- A2G - AUFTRAG.Type.CAS, AUFTRAG.Type.BAI, AUFTRAG.Type.SEAD, AUFTRAG.Type.BOMBING, AUFTRAG.Type.PRECISIONBOMBING, AUFTRAG.Type.BOMBRUNWAY
+-- A2GS - A2G + A2S
+-- If you don't want SEAD tasks generated, use as follows where "mycontroller" is your PLAYERTASKCONTROLLER object:
+--
+-- `mycontroller:SetTaskBlackList({AUFTRAG.Type.SEAD})`
+--
+function PLAYERTASKCONTROLLER:SetTaskBlackList(BlackList)
+ self:T(self.lid.."SetTaskBlackList")
+ self.BlackList = BlackList
+ self.UseBlackList = true
+ return self
+end
+
--- [Internal] Add a task to the task queue
-- @param #PLAYERTASKCONTROLLER self
-- @param Ops.Target#TARGET Target
-- @return #PLAYERTASKCONTROLLER self
function PLAYERTASKCONTROLLER:_AddTask(Target)
- self:I(self.lid.."_AddTask")
+ self:T(self.lid.."_AddTask")
local cat = Target:GetCategory()
+ local threat = Target:GetThreatLevelMax()
local type = AUFTRAG.Type.CAS
+ --local ttstype = "close air support"
+ local ttstype = self.gettext:GetEntry("CASTTS",self.locale)
+
if cat == TARGET.Category.GROUND then
type = AUFTRAG.Type.CAS
-- TODO: debug BAI, CAS, SEAD
local targetobject = Target:GetObject() -- Wrapper.Positionable#POSITIONABLE
if targetobject:IsInstanceOf("UNIT") then
- self:I("SEAD Check UNIT")
+ self:T("SEAD Check UNIT")
if targetobject:HasSEAD() then
type = AUFTRAG.Type.SEAD
+ --ttstype = "suppress air defense"
+ ttstype = self.gettext:GetEntry("SEADTTS",self.locale)
end
elseif targetobject:IsInstanceOf("GROUP") then
- self:I("SEAD Check GROUP")
+ self:T("SEAD Check GROUP")
local attribute = targetobject:GetAttribute()
- if attribute == GROUP.Attribute.GROUND_SAM or attribute == GROUP.Attribute.GROUND_AAA then
+ if attribute == GROUP.Attribute.GROUND_SAM or attribute == GROUP.Attribute.GROUND_AAA or attribute == GROUP.Attribute.GROUND_EWR then
type = AUFTRAG.Type.SEAD
+ --ttstype = "suppress air defense"
+ ttstype = self.gettext:GetEntry("SEADTTS",self.locale)
end
elseif targetobject:IsInstanceOf("SET_GROUP") then
- self:I("SEAD Check SET_GROUP")
+ self:T("SEAD Check SET_GROUP")
targetobject:ForEachGroup(
function (group)
local attribute = group:GetAttribute()
- if attribute == GROUP.Attribute.GROUND_SAM or attribute == GROUP.Attribute.GROUND_AAA then
+ if attribute == GROUP.Attribute.GROUND_SAM or attribute == GROUP.Attribute.GROUND_AAA or attribute == GROUP.Attribute.GROUND_EWR then
type = AUFTRAG.Type.SEAD
+ --ttstype = "suppress air defense"
+ ttstype = self.gettext:GetEntry("SEADTTS",self.locale)
end
end
)
elseif targetobject:IsInstanceOf("SET_UNIT") then
- self:I("SEAD Check SET_UNIT")
+ self:T("SEAD Check SET_UNIT")
targetobject:ForEachUnit(
function (unit)
if unit:HasSEAD() then
type = AUFTRAG.Type.SEAD
+ --ttstype = "suppress air defenses"
+ ttstype = self.gettext:GetEntry("SEADTTS",self.locale)
end
end
)
+ elseif targetobject:IsInstanceOf("SET_STATIC") or targetobject:IsInstanceOf("STATIC") then
+ self:T("(PRECISION-)BOMBING SET_STATIC or STATIC")
+ if self.precisionbombing then
+ type = AUFTRAG.Type.PRECISIONBOMBING
+ ttstype = self.gettext:GetEntry("PRECBOMBTTS",self.locale)
+ else
+ type = AUFTRAG.Type.BOMBING
+ ttstype = self.gettext:GetEntry("BOMBTTS",self.locale)
+ end
+
end
- -- if there are no friendlies nearby ~2km and task isn't SEAD, then it's BAI
+ -- if there are no friendlies nearby ~0.5km and task isn't SEAD, then it's BAI
local targetcoord = Target:GetCoordinate()
local targetvec2 = targetcoord:GetVec2()
- local targetzone = ZONE_RADIUS:New(self.Name,targetvec2,2000)
+ local targetzone = ZONE_RADIUS:New(self.Name,targetvec2,self.TargetRadius)
local coalition = targetobject:GetCoalitionName() or "Blue"
coalition = string.lower(coalition)
- self:I("Target coalition is "..tostring(coalition))
+ self:T("Target coalition is "..tostring(coalition))
local filtercoalition = "blue"
if coalition == "blue" then filtercoalition = "red" end
local friendlyset = SET_GROUP:New():FilterCategoryGround():FilterCoalitions(filtercoalition):FilterZones({targetzone}):FilterOnce()
- if friendlyset:Count() == 0 and type ~= AUFTRAG.Type.SEAD then
+ if friendlyset:Count() == 0 and type == AUFTRAG.Type.CAS then
type = AUFTRAG.Type.BAI
+ --ttstype = "battle field air interdiction"
+ ttstype = self.gettext:GetEntry("BAITTS",self.locale)
+ end
+ -- see if we can do precision bombing
+ if (type == AUFTRAG.Type.BAI or type == AUFTRAG.Type.CAS) and self.precisionbombing then
+ -- threatlevel between 3 and 6 means, it's artillery, tank, modern tank or AAA
+ if threat > 2 and threat < 7 then
+ type = AUFTRAG.Type.PRECISIONBOMBING
+ ttstype = self.gettext:GetEntry("PRECBOMBTTS",self.locale)
+ end
end
elseif cat == TARGET.Category.NAVAL then
type = AUFTRAG.Type.ANTISHIP
+ --ttstype = "anti-ship"
+ ttstype = self.gettext:GetEntry("ANTISHIPTTS",self.locale)
elseif cat == TARGET.Category.AIRCRAFT then
type = AUFTRAG.Type.INTERCEPT
+ --ttstype = "intercept"
+ ttstype = self.gettext:GetEntry("INTERCEPTTS",self.locale)
elseif cat == TARGET.Category.AIRBASE then
- --TODO: Define Success Criteria, AB hit? Runway blocked, how to determine? change of coalition?
+ --TODO: Define Success Criteria, AB hit? Runway blocked, how to determine? change of coalition? Void of enemies?
+ -- Current implementation - bombing in AFB zone (EVENTS.Shot)
type = AUFTRAG.Type.BOMBRUNWAY
+ -- ttstype = "bomb runway"
+ ttstype = self.gettext:GetEntry("BOMBRUNWAYTTS",self.locale)
elseif cat == TARGET.Category.COORDINATE or cat == TARGET.Category.ZONE then
--TODO: Define Success Criteria, void of enemies?
- type = AUFTRAG.Type.BOMBING
+ -- Current implementation - find SET of enemies in ZONE or 500m radius around coordinate, and assign as targets
+ local zone = Target:GetObject()
+ if cat == TARGET.Category.COORDINATE then
+ zone = ZONE_RADIUS:New("TargetZone-"..math.random(1,10000),Target:GetVec2(),self.TargetRadius)
+ end
+ -- find some enemies around there...
+ local enemies = self.CoalitionName == "Blue" and "red" or "blue"
+ local enemysetg = SET_GROUP:New():FilterCoalitions(enemies):FilterCategoryGround():FilterActive(true):FilterZones({zone}):FilterOnce()
+ local enemysets = SET_STATIC:New():FilterCoalitions(enemies):FilterZones({zone}):FilterOnce()
+ local countg = enemysetg:Count()
+ local counts = enemysets:Count()
+ if countg > 0 then
+ self:AddTarget(enemysetg)
+ end
+ if counts > 0 then
+ self:AddTarget(enemysets)
+ end
+ return self
+ end
+
+ if self.UseWhiteList then
+ if not self:_CheckTaskTypeAllowed(type) then
+ return self
+ end
+ end
+
+ if self.UseBlackList then
+ if self:_CheckTaskTypeDisallowed(type) then
+ return self
+ end
+ end
+
+ local task = PLAYERTASK:New(type,Target,self.repeatonfailed,self.repeattimes,ttstype)
+
+ task.coalition = self.Coalition
+
+ if type == AUFTRAG.Type.BOMBRUNWAY then
+ -- task to handle event shot
+ task:HandleEvent(EVENTS.Shot)
+ function task:OnEventShot(EventData)
+ local data = EventData -- Core.Event#EVENTDATA EventData
+ local wcat = data.Weapon:getCategory() -- cat 2 or 3
+ local coord = data.IniUnit:GetCoordinate() or data.IniGroup:GetCoordinate()
+ local vec2 = coord:GetVec2() or {x=0, y=0}
+ local coal = data.IniCoalition
+ local afbzone = AIRBASE:FindByName(Target:GetName()):GetZone()
+ local runways = AIRBASE:FindByName(Target:GetName()):GetRunways() or {}
+ local inrunwayzone = false
+ for _,_runway in pairs(runways) do
+ local runway = _runway -- Wrapper.Airbase#AIRBASE.Runway
+ if runway.zone:IsVec2InZone(vec2) then
+ inrunwayzone = true
+ end
+ end
+ local inzone = afbzone:IsVec2InZone(vec2)
+ if coal == task.coalition and (wcat == 2 or wcat == 3) and (inrunwayzone or inzone) then
+ -- bombing/rockets inside target AFB zone - well done!
+ task:__Success(-20)
+ end
+ end
end
- local task = PLAYERTASK:New(type,Target,self.repeatonfailed,self.repeattimes)
task:_SetController(self)
self.TaskQueue:Push(task)
self:__TaskAdded(-1,task)
+
return self
end
@@ -886,26 +1974,39 @@ end
-- @param Ops.PlayerTask#PLAYERTASK Task
-- @return #PLAYERTASKCONTROLLER self
function PLAYERTASKCONTROLLER:_JoinTask(Group, Client, Task)
- self:I(self.lid.."_JoinTask")
- local playername = Client:GetPlayerName()
+ self:T(self.lid.."_JoinTask")
+ local playername, ttsplayername = self:_GetPlayerName(Client)
if self.TasksPerPlayer:HasUniqueID(playername) then
-- Player already has a task
- local m=MESSAGE:New("You already have one active task! Complete it first!","10","Info"):ToGroup(Group)
+ if not self.NoScreenOutput then
+ local text = self.gettext:GetEntry("HAVEACTIVETASK",self.locale)
+ local m=MESSAGE:New(text,"10","Tasking"):ToGroup(Group)
+ end
return self
end
- Task:AddClient(Client)
local taskstate = Task:GetState()
- --self:I(self.lid.."Taskstate = "..taskstate)
- if taskstate ~= "Executing" and taskstate ~= "Done" then
- Task:__Requested(-1)
- Task:__Executing(-2)
- local text = string.format("Player %s joined task %d in state %s", playername, Task.PlayerTaskNr, taskstate)
- self:I(self.lid..text)
- local m=MESSAGE:New(text,"10","Info"):ToAll()
+ if not Task:IsDone() then
+ if taskstate ~= "Executing" then
+ Task:__Requested(-1)
+ Task:__Executing(-2)
+ end
+ Task:AddClient(Client)
+ local joined = self.gettext:GetEntry("PILOTJOINEDTASK",self.locale)
+ local text = string.format(joined, self.MenuName or self.Name, ttsplayername, Task.PlayerTaskNr)
+ self:T(self.lid..text)
+ if not self.NoScreenOutput then
+ local m=MESSAGE:New(text,"10","Tasking"):ToAll()
+ end
+ if self.UseSRS then
+ self.SRSQueue:NewTransmission(text,nil,self.SRS,nil,2)
+ end
self.TasksPerPlayer:Push(Task,playername)
-- clear menu
- if self.PlayerMenu[playername] then
- self.PlayerMenu[playername]:RemoveSubMenus()
+ self:_BuildMenus(Client)
+ end
+ if Task.Type == AUFTRAG.Type.PRECISIONBOMBING then
+ if not self.PrecisionTasks:HasUniqueID(Task.PlayerTaskNr) then
+ self.PrecisionTasks:Push(Task,Task.PlayerTaskNr)
end
end
return self
@@ -917,31 +2018,80 @@ end
-- @param Wrapper.Client#CLIENT Client
-- @return #PLAYERTASKCONTROLLER self
function PLAYERTASKCONTROLLER:_ActiveTaskInfo(Group, Client)
- self:I(self.lid.."_ActiveTaskInfo")
- local playername = Client:GetPlayerName()
+ self:T(self.lid.."_ActiveTaskInfo")
+ local playername, ttsplayername = self:_GetPlayerName(Client)
local text = ""
if self.TasksPerPlayer:HasUniqueID(playername) then
- -- TODO: Show multiple
- local task = self.TasksPerPlayer:GetIDStack()
+ -- TODO: Show multiple?
local task = self.TasksPerPlayer:ReadByID(playername) -- Ops.PlayerTask#PLAYERTASK
- local taskname = string.format("%s Task ID %02d",task.Type,task.PlayerTaskNr)
+ local tname = self.gettext:GetEntry("TASKNAME",self.locale)
+ local ttsname = self.gettext:GetEntry("TASKNAMETTS",self.locale)
+ local taskname = string.format(tname,task.Type,task.PlayerTaskNr)
+ local ttstaskname = string.format(ttsname,task.TTSType,task.PlayerTaskNr)
local Coordinate = task.Target:GetCoordinate()
- local CoordText = Coordinate:ToStringA2G(Client)
+ local CoordText = ""
+ if self.Type ~= PLAYERTASKCONTROLLER.Type.A2A then
+ CoordText = Coordinate:ToStringA2G(Client)
+ else
+ CoordText = Coordinate:ToStringA2A(Client)
+ end
local ThreatLevel = task.Target:GetThreatLevelMax()
+ --local ThreatLevelText = "high"
+ local ThreatLevelText = self.gettext:GetEntry("THREATHIGH",self.locale)
+ if ThreatLevel > 3 and ThreatLevel < 8 then
+ --ThreatLevelText = "medium"
+ ThreatLevelText = self.gettext:GetEntry("THREATMEDIUM",self.locale)
+ elseif ThreatLevel <= 3 then
+ --ThreatLevelText = "low"
+ ThreatLevelText = self.gettext:GetEntry("THREATLOW",self.locale)
+ end
local targets = task.Target:CountTargets() or 0
local clientlist = task:GetClients()
local ThreatGraph = "[" .. string.rep( "■", ThreatLevel ) .. string.rep( "□", 10 - ThreatLevel ) .. "]: "..ThreatLevel
- text = string.format("%s\nThreat: %s\nTargets left: %d\nCoord: %s", taskname, ThreatGraph, targets, CoordText)
- local clienttxt = "\nPilot(s): "
+ local ThreatLocaleText = self.gettext:GetEntry("THREATTEXT",self.locale)
+ text = string.format(ThreatLocaleText, taskname, ThreatGraph, targets, CoordText)
+ if task.Type == AUFTRAG.Type.PRECISIONBOMBING and self.precisionbombing then
+ if self.LasingDrone and self.LasingDrone.playertask then
+ local yes = self.gettext:GetEntry("YES",self.locale)
+ local no = self.gettext:GetEntry("NO",self.locale)
+ local inreach = self.LasingDrone.playertask.inreach == true and yes or no
+ local islasing = self.LasingDrone:IsLasing() == true and yes or no
+ local prectext = self.gettext:GetEntry("POINTERTARGETREPORT",self.locale)
+ prectext = string.format(prectext,inreach,islasing)
+ text = text .. prectext
+ end
+ end
+ local clienttxt = self.gettext:GetEntry("PILOTS",self.locale)
for _,_name in pairs(clientlist) do
+ if string.find(_name,"|") then
+ -- personalized flight name in player naming
+ _name = string.match(_name,"| ([%a]+)")
+ end
clienttxt = clienttxt .. _name .. ", "
end
- clienttxt=string.gsub(clienttxt,", $",".")
- text = text .. clienttxt
+ clienttxt=string.gsub(clienttxt,", $",".")
+ text = text .. clienttxt
+ if self.UseSRS then
+ if string.find(CoordText," BR, ") then
+ CoordText = string.gsub(CoordText," BR, "," Bee, Arr, ")
+ end
+ local ThreatLocaleTextTTS = self.gettext:GetEntry("THREATTEXTTTS",self.locale)
+ local ttstext = string.format(ThreatLocaleTextTTS,self.MenuName or self.Name,ttsplayername,ttstaskname,ThreatLevelText, targets, CoordText)
+ -- POINTERTARGETLASINGTTS = ". Pointer over target and lasing."
+ if task.Type == AUFTRAG.Type.PRECISIONBOMBING and self.precisionbombing then
+ if self.LasingDrone.playertask.inreach and self.LasingDrone:IsLasing() then
+ local lasingtext = self.gettext:GetEntry("POINTERTARGETLASINGTTS",self.locale)
+ ttstext = ttstext .. lasingtext
+ end
+ end
+ self.SRSQueue:NewTransmission(ttstext,nil,self.SRS,nil,2)
+ end
else
- text = "No active task!"
+ text = self.gettext:GetEntry("NOACTIVETASK",self.locale)
+ end
+ if not self.NoScreenOutput then
+ local m=MESSAGE:New(text,15,"Tasking"):ToGroup(Group)
end
- local m=MESSAGE:New(text,15,"Tasking"):ToGroup(Group)
return self
end
@@ -951,17 +2101,26 @@ end
-- @param Wrapper.Client#CLIENT Client
-- @return #PLAYERTASKCONTROLLER self
function PLAYERTASKCONTROLLER:_MarkTask(Group, Client)
- self:I(self.lid.."_ActiveTaskInfo")
- local playername = Client:GetPlayerName()
+ self:T(self.lid.."_MarkTask")
+ local playername, ttsplayername = self:_GetPlayerName(Client)
local text = ""
if self.TasksPerPlayer:HasUniqueID(playername) then
local task = self.TasksPerPlayer:ReadByID(playername) -- Ops.PlayerTask#PLAYERTASK
- task:MarkTargetOnF10Map()
- text = "Task location marked!"
+ local text = string.format("Task ID #%03d | Type: %s | Threat: %d",task.PlayerTaskNr,task.Type,task.Target:GetThreatLevelMax())
+ task:MarkTargetOnF10Map(text)
+ local textmark = self.gettext:GetEntry("MARKTASK",self.locale)
+ --text = string.format("%s, copy pilot %s, task %03d location marked on map!", self.MenuName or self.Name, playername, task.PlayerTaskNr)
+ text = string.format(textmark, ttsplayername, self.MenuName or self.Name, task.PlayerTaskNr)
+ self:T(self.lid..text)
+ if self.UseSRS then
+ self.SRSQueue:NewTransmission(text,nil,self.SRS,nil,2)
+ end
else
- text = "No active task!"
+ text = self.gettext:GetEntry("NOACTIVETASK",self.locale)
+ end
+ if not self.NoScreenOutput then
+ local m=MESSAGE:New(text,"10","Tasking"):ToGroup(Group)
end
- local m=MESSAGE:New(text,15,"Info"):ToGroup(Group)
return self
end
@@ -971,17 +2130,25 @@ end
-- @param Wrapper.Client#CLIENT Client
-- @return #PLAYERTASKCONTROLLER self
function PLAYERTASKCONTROLLER:_SmokeTask(Group, Client)
- self:I(self.lid.."_SmokeTask")
- local playername = Client:GetPlayerName()
+ self:T(self.lid.."_SmokeTask")
+ local playername, ttsplayername = self:_GetPlayerName(Client)
local text = ""
if self.TasksPerPlayer:HasUniqueID(playername) then
local task = self.TasksPerPlayer:ReadByID(playername) -- Ops.PlayerTask#PLAYERTASK
task:SmokeTarget()
- text = "Task location smoked!"
+ local textmark = self.gettext:GetEntry("SMOKETASK",self.locale)
+ text = string.format(textmark, ttsplayername, self.MenuName or self.Name, task.PlayerTaskNr)
+ self:T(self.lid..text)
+ --local m=MESSAGE:New(text,"10","Tasking"):ToAll()
+ if self.UseSRS then
+ self.SRSQueue:NewTransmission(text,nil,self.SRS,nil,2)
+ end
else
- text = "No active task!"
+ text = self.gettext:GetEntry("NOACTIVETASK",self.locale)
+ end
+ if not self.NoScreenOutput then
+ local m=MESSAGE:New(text,15,"Tasking"):ToGroup(Group)
end
- local m=MESSAGE:New(text,15,"Info"):ToGroup(Group)
return self
end
@@ -991,17 +2158,25 @@ end
-- @param Wrapper.Client#CLIENT Client
-- @return #PLAYERTASKCONTROLLER self
function PLAYERTASKCONTROLLER:_FlareTask(Group, Client)
- self:I(self.lid.."_FlareTask")
- local playername = Client:GetPlayerName()
+ self:T(self.lid.."_FlareTask")
+ local playername, ttsplayername = self:_GetPlayerName(Client)
local text = ""
if self.TasksPerPlayer:HasUniqueID(playername) then
local task = self.TasksPerPlayer:ReadByID(playername) -- Ops.PlayerTask#PLAYERTASK
task:FlareTarget()
- text = "Task location illuminated!"
+ local textmark = self.gettext:GetEntry("FLARETASK",self.locale)
+ text = string.format(textmark, ttsplayername, self.MenuName or self.Name, task.PlayerTaskNr)
+ self:T(self.lid..text)
+ --local m=MESSAGE:New(text,"10","Tasking"):ToAll()
+ if self.UseSRS then
+ self.SRSQueue:NewTransmission(text,nil,self.SRS,nil,2)
+ end
else
- text = "No active task!"
+ text = self.gettext:GetEntry("NOACTIVETASK",self.locale)
+ end
+ if not self.NoScreenOutput then
+ local m=MESSAGE:New(text,15,"Tasking"):ToGroup(Group)
end
- local m=MESSAGE:New(text,15,"Info"):ToGroup(Group)
return self
end
@@ -1011,73 +2186,126 @@ end
-- @param Wrapper.Client#CLIENT Client
-- @return #PLAYERTASKCONTROLLER self
function PLAYERTASKCONTROLLER:_AbortTask(Group, Client)
- self:I(self.lid.."_FlareTask")
- local playername = Client:GetPlayerName()
+ self:T(self.lid.."_FlareTask")
+ local playername, ttsplayername = self:_GetPlayerName(Client)
local text = ""
if self.TasksPerPlayer:HasUniqueID(playername) then
local task = self.TasksPerPlayer:PullByID(playername) -- Ops.PlayerTask#PLAYERTASK
task:ClientAbort(Client)
- text = "Task aborted!"
+ local textmark = self.gettext:GetEntry("ABORTTASK",self.locale)
+ text = string.format(textmark, ttsplayername, self.MenuName or self.Name, task.PlayerTaskNr)
+ self:T(self.lid..text)
+ --local m=MESSAGE:New(text,"10","Tasking"):ToAll()
+ if self.UseSRS then
+ self.SRSQueue:NewTransmission(text,nil,self.SRS,nil,2)
+ end
else
- text = "No active task!"
+ text = self.gettext:GetEntry("NOACTIVETASK",self.locale)
end
- local m=MESSAGE:New(text,15,"Info"):ToGroup(Group)
+ if not self.NoScreenOutput then
+ local m=MESSAGE:New(text,15,"Tasking"):ToGroup(Group)
+ end
+ self:_BuildMenus(Client)
return self
end
--- [Internal] Build client menus
-- @param #PLAYERTASKCONTROLLER self
+-- @param Wrapper.Client#CLIENT Client (optional) build for this client name only
-- @return #PLAYERTASKCONTROLLER self
-function PLAYERTASKCONTROLLER:_BuildMenus()
- self:I(self.lid.."_BuildMenus")
+function PLAYERTASKCONTROLLER:_BuildMenus(Client)
+ self:T(self.lid.."_BuildMenus")
local clients = self.ClientSet:GetAliveSet()
+ if Client then
+ clients = {Client}
+ end
for _,_client in pairs(clients) do
if _client then
local client = _client -- Wrapper.Client#CLIENT
local group = client:GetGroup()
- local playername = client:GetPlayerName() or "Unknown"
+ local unknown = self.gettext:GetEntry("UNKNOWN",self.locale)
+ local playername = client:GetPlayerName() or unknown
if group and client then
- local topmenu = MENU_GROUP:New(group,self.Name.." Tasking "..self.Type,nil)
- local active = MENU_GROUP:New(group,"Active Task",topmenu)
- local info = MENU_GROUP_COMMAND:New(group,"Info",active,self._ActiveTaskInfo,self,group,client)
- local mark = MENU_GROUP_COMMAND:New(group,"Mark on map",active,self._MarkTask,self,group,client)
- if self.Type ~= PLAYERTASKCONTROLLER.Type.A2A then
- -- no smoking/flaring here if A2A
- local smoke = MENU_GROUP_COMMAND:New(group,"Smoke",active,self._SmokeTask,self,group,client)
- local flare = MENU_GROUP_COMMAND:New(group,"Flare",active,self._FlareTask,self,group,client)
- end
- local abort = MENU_GROUP_COMMAND:New(group,"Abort",active,self._AbortTask,self,group,client)
+ ---
+ -- TOPMENU
+ ---
+ local taskings = self.gettext:GetEntry("MENUTASKING",self.locale)
+ local menuname = self.MenuName or self.Name..taskings..self.Type
+ local topmenu = MENU_GROUP:New(group,menuname,nil)
if self.PlayerMenu[playername] then
self.PlayerMenu[playername]:RemoveSubMenus()
else
- self.PlayerMenu[playername] = MENU_GROUP:New(group,"Join Task",topmenu)
+ self.PlayerMenu[playername] = topmenu
end
- local tasktypes = self:_GetAvailableTaskTypes()
- local taskpertype = self:_GetTasksPerType()
-
- local ttypes = {}
- local taskmenu = {}
- for _tasktype,_data in pairs(tasktypes) do
- ttypes[_tasktype] = MENU_GROUP:New(group,_tasktype,self.PlayerMenu[playername])
- local tasks = taskpertype[_tasktype] or {}
- for _,_task in pairs(tasks) do
- _task = _task -- Ops.PlayerTask#PLAYERTASK
- local text = string.format("TaskNo %03d",_task.PlayerTaskNr)
- if self.UseGroupNames then
- local name = _task.Target:GetName()
- if name ~= "Unknown" then
- text = string.format("%s (%03d)",name,_task.PlayerTaskNr)
+ ---
+ -- ACTIVE TASK MENU
+ ---
+ if self:_CheckPlayerHasTask(playername) then
+
+ local menuactive = self.gettext:GetEntry("MENUACTIVE",self.locale)
+ local menuinfo = self.gettext:GetEntry("MENUINFO",self.locale)
+ local menumark = self.gettext:GetEntry("MENUMARK",self.locale)
+ local menusmoke = self.gettext:GetEntry("MENUSMOKE",self.locale)
+ local menuflare = self.gettext:GetEntry("MENUFLARE",self.locale)
+ local menuabort = self.gettext:GetEntry("MENUABORT",self.locale)
+
+ local active = MENU_GROUP:New(group,menuactive,topmenu)
+ local info = MENU_GROUP_COMMAND:New(group,menuinfo,active,self._ActiveTaskInfo,self,group,client)
+ local mark = MENU_GROUP_COMMAND:New(group,menumark,active,self._MarkTask,self,group,client)
+ if self.Type ~= PLAYERTASKCONTROLLER.Type.A2A then
+ -- no smoking/flaring here if A2A
+ local smoke = MENU_GROUP_COMMAND:New(group,menusmoke,active,self._SmokeTask,self,group,client)
+ local flare = MENU_GROUP_COMMAND:New(group,menuflare,active,self._FlareTask,self,group,client)
+ end
+ local abort = MENU_GROUP_COMMAND:New(group,menuabort,active,self._AbortTask,self,group,client)
+ elseif self.TaskQueue:Count() > 0 then
+ ---
+ -- JOIN TASK MENU
+ ---
+ local tasktypes = self:_GetAvailableTaskTypes()
+ local taskpertype = self:_GetTasksPerType()
+ local menujoin = self.gettext:GetEntry("MENUJOIN",self.locale)
+ local joinmenu = MENU_GROUP:New(group,menujoin,topmenu)
+
+ local ttypes = {}
+ local taskmenu = {}
+ for _tasktype,_data in pairs(tasktypes) do
+ ttypes[_tasktype] = MENU_GROUP:New(group,_tasktype,joinmenu)
+ local tasks = taskpertype[_tasktype] or {}
+ for _,_task in pairs(tasks) do
+ _task = _task -- Ops.PlayerTask#PLAYERTASK
+ local pilotcount = _task:CountClients()
+ local newtext = "]"
+ local tnow = timer.getTime()
+ -- marker for new tasks
+ if tnow - _task.timestamp < 60 then
+ newtext = "*]"
end
- end
- if _task:GetState() == "Planned" or (not _task:HasPlayerName(playername)) then
+ local menutaskno = self.gettext:GetEntry("MENUTASKNO",self.locale)
+ local text = string.format("%s %03d [%d%s",menutaskno,_task.PlayerTaskNr,pilotcount,newtext)
+ if self.UseGroupNames then
+ local name = _task.Target:GetName()
+ if name ~= "Unknown" then
+ text = string.format("%s (%03d) [%d%s",name,_task.PlayerTaskNr,pilotcount,newtext)
+ end
+ end
+ --if _task:GetState() == "Planned" or (not _task:HasPlayerName(playername)) then
local taskentry = MENU_GROUP_COMMAND:New(group,text,ttypes[_tasktype],self._JoinTask,self,group,client,_task)
taskentry:SetTag(playername)
taskmenu[#taskmenu+1] = taskentry
- end
+ --end
+ end
end
+ else
+ -- no tasks (yet)
+ local menunotasks = self.gettext:GetEntry("MENUNOTASKS",self.locale)
+ local joinmenu = MENU_GROUP:New(group,menunotasks,topmenu)
end
+ ---
+ -- REFRESH MENU
+ ---
self.PlayerMenu[playername]:Refresh()
end
end
@@ -1085,6 +2313,225 @@ function PLAYERTASKCONTROLLER:_BuildMenus()
return self
end
+--- [User] Add agent group to INTEL detection
+-- @param #PLAYERTASKCONTROLLER self
+-- @param Wrapper.Group#GROUP Recce Group of agents. Can also be an @{Ops.OpsGroup#OPSGROUP} object.
+-- @return #PLAYERTASKCONTROLLER self
+function PLAYERTASKCONTROLLER:AddAgent(Recce)
+ self:T(self.lid.."AddAgent: "..Recce:GetName())
+ if self.Intel then
+ self.Intel:AddAgent(Recce)
+ end
+ return self
+end
+
+--- [User] Add accept zone to INTEL detection
+-- @param #PLAYERTASKCONTROLLER self
+-- @param Core.Zone#ZONE AcceptZone Add a zone to the accept zone set.
+-- @return #PLAYERTASKCONTROLLER self
+function PLAYERTASKCONTROLLER:AddAcceptZone(AcceptZone)
+ self:T(self.lid.."AddAcceptZone")
+ if self.Intel then
+ self.Intel:AddAcceptZone(AcceptZone)
+ end
+ return self
+end
+
+--- [User] Add reject zone to INTEL detection
+-- @param #PLAYERTASKCONTROLLER self
+-- @param Core.Zone#ZONE RejectZone Add a zone to the reject zone set.
+-- @return #PLAYERTASKCONTROLLER self
+function PLAYERTASKCONTROLLER:AddRejectZone(RejectZone)
+ self:T(self.lid.."AddRejectZone")
+ if self.Intel then
+ self.Intel:AddRejectZone(RejectZone)
+ end
+ return self
+end
+
+--- [User] Remove accept zone from INTEL detection
+-- @param #PLAYERTASKCONTROLLER self
+-- @param Core.Zone#ZONE AcceptZone Add a zone to the accept zone set.
+-- @return #PLAYERTASKCONTROLLER self
+function PLAYERTASKCONTROLLER:RemoveAcceptZone(AcceptZone)
+ self:T(self.lid.."RemoveAcceptZone")
+ if self.Intel then
+ self.Intel:RemoveAcceptZone(AcceptZone)
+ end
+ return self
+end
+
+--- [User] Remove reject zone from INTEL detection
+-- @param #PLAYERTASKCONTROLLER self
+-- @param Core.Zone#ZONE RejectZone Add a zone to the reject zone set.
+-- @return #PLAYERTASKCONTROLLER self
+function PLAYERTASKCONTROLLER:RemoveRejectZone(RejectZone)
+ self:T(self.lid.."RemoveRejectZone")
+ if self.Intel then
+ self.Intel:RemoveRejectZone(RejectZone)
+ end
+ return self
+end
+
+--- [User] Set the top menu name to a custom string.
+-- @param #PLAYERTASKCONTROLLER self
+-- @param #string Name The name to use as the top menu designation.
+-- @return #PLAYERTASKCONTROLLER self
+function PLAYERTASKCONTROLLER:SetMenuName(Name)
+ self:T(self.lid.."SetMenuName: "..Name)
+ self.MenuName = Name
+ return self
+end
+
+--- [User] Set up INTEL detection
+-- @param #PLAYERTASKCONTROLLER self
+-- @param #string RecceName This name will be used to build a detection group set. All groups with this string somewhere in their group name will be added as Recce.
+-- @return #PLAYERTASKCONTROLLER self
+function PLAYERTASKCONTROLLER:SetupIntel(RecceName)
+ self:T(self.lid.."SetupIntel: "..RecceName)
+ self.RecceSet = SET_GROUP:New():FilterCoalitions(self.CoalitionName):FilterPrefixes(RecceName):FilterStart()
+ self.Intel = INTEL:New(self.RecceSet,self.Coalition,self.Name.."-Intel")
+ self.Intel:SetClusterAnalysis(true,false,false)
+ self.Intel:SetClusterRadius(self.ClusterRadius or 500)
+ self.Intel.statusupdate = 25
+ self.Intel:SetAcceptZones()
+ self.Intel:SetRejectZones()
+ --if self.verbose then
+ --self.Intel:SetDetectionTypes(true,true,false,true,true,true)
+ --end
+ if self.Type == PLAYERTASKCONTROLLER.Type.A2G or self.Type == PLAYERTASKCONTROLLER.Type.A2GS then
+ self.Intel:SetDetectStatics(true)
+ end
+ self.Intel:__Start(2)
+
+ local function NewCluster(Cluster)
+ if not self.usecluster then return self end
+ local cluster = Cluster -- Ops.Intelligence#INTEL.Cluster
+ local type = cluster.ctype
+ self:T({type,self.Type})
+ if (type == INTEL.Ctype.AIRCRAFT and self.Type == PLAYERTASKCONTROLLER.Type.A2A) or (type == INTEL.Ctype.NAVAL and (self.Type == PLAYERTASKCONTROLLER.Type.A2S or self.Type == PLAYERTASKCONTROLLER.Type.A2GS)) then
+ self:T("A2A or A2S")
+ local contacts = cluster.Contacts -- #table of GROUP
+ local targetset = SET_GROUP:New()
+ for _,_object in pairs(contacts) do
+ local contact = _object -- Ops.Intelligence#INTEL.Contact
+ self:T("Adding group: "..contact.groupname)
+ targetset:AddGroup(contact.group,true)
+ end
+ self:AddTarget(targetset)
+ elseif (type == INTEL.Ctype.GROUND or type == INTEL.Ctype.STRUCTURE) and (self.Type == PLAYERTASKCONTROLLER.Type.A2G or self.Type == PLAYERTASKCONTROLLER.Type.A2GS) then
+ self:T("A2G")
+ local contacts = cluster.Contacts -- #table of GROUP or STATIC
+ local targetset = nil -- Core.Set#SET_BASE
+ if type == INTEL.Ctype.GROUND then
+ targetset = SET_GROUP:New()
+ for _,_object in pairs(contacts) do
+ local contact = _object -- Ops.Intelligence#INTEL.Contact
+ self:T("Adding group: "..contact.groupname)
+ targetset:AddGroup(contact.group,true)
+ end
+ elseif type == INTEL.Ctype.STRUCTURE then
+ targetset = SET_STATIC:New()
+ for _,_object in pairs(contacts) do
+ local contact = _object -- Ops.Intelligence#INTEL.Contact
+ self:T("Adding static: "..contact.groupname)
+ targetset:AddStatic(contact.group)
+ end
+ end
+ if targetset then
+ self:AddTarget(targetset)
+ end
+ end
+ end
+
+ local function NewContact(Contact)
+ if self.usecluster then return self end
+ local contact = Contact -- Ops.Intelligence#INTEL.Contact
+ local type = contact.ctype
+ self:T({type,self.Type})
+ if (type == INTEL.Ctype.AIRCRAFT and self.Type == PLAYERTASKCONTROLLER.Type.A2A) or (type == INTEL.Ctype.NAVAL and (self.Type == PLAYERTASKCONTROLLER.Type.A2S or self.Type == PLAYERTASKCONTROLLER.Type.A2GS)) then
+ self:T("A2A or A2S")
+ self:T("Adding group: "..contact.groupname)
+ self:AddTarget(contact.group)
+ elseif (type == INTEL.Ctype.GROUND or type == INTEL.Ctype.STRUCTURE) and (self.Type == PLAYERTASKCONTROLLER.Type.A2G or self.Type == PLAYERTASKCONTROLLER.Type.A2GS) then
+ self:T("A2G")
+ self:T("Adding group: "..contact.groupname)
+ self:AddTarget(contact.group)
+ end
+ end
+
+ function self.Intel:OnAfterNewCluster(From,Event,To,Cluster)
+ NewCluster(Cluster)
+ end
+
+ function self.Intel:OnAfterNewContact(From,Event,To,Contact)
+ NewContact(Contact)
+ end
+
+ return self
+end
+
+--- [User] Set SRS TTS details - see @{Sound.SRS} for details
+-- @param #PLAYERTASKCONTROLLER self
+-- @param #number Frequency Frequency to be used. Can also be given as a table of multiple frequencies, e.g. 271 or {127,251}. There needs to be exactly the same number of modulations!
+-- @param #number Modulation Modulation to be used. Can also be given as a table of multiple modulations, e.g. radio.modulation.AM or {radio.modulation.FM,radio.modulation.AM}. There needs to be exactly the same number of frequencies!
+-- @param #string PathToSRS Defaults to "C:\\Program Files\\DCS-SimpleRadio-Standalone"
+-- @param #string Gender (Optional) Defaults to "male"
+-- @param #string Culture (Optional) Defaults to "en-US"
+-- @param #number Port (Optional) Defaults to 5002
+-- @param #string Voice (Optional) Use a specifc voice with the @{Sound.SRS.SetVoice} function, e.g, `:SetVoice("Microsoft Hedda Desktop")`.
+-- Note that this must be installed on your windows system. Can also be Google voice types, if you are using Google TTS.
+-- @param #number Volume (Optional) Volume - between 0.0 (silent) and 1.0 (loudest)
+-- @param #string PathToGoogleKey (Optional) Path to your google key if you want to use google TTS
+-- @return #PLAYERTASKCONTROLLER self
+function PLAYERTASKCONTROLLER:SetSRS(Frequency,Modulation,PathToSRS,Gender,Culture,Port,Voice,Volume,PathToGoogleKey)
+ self:T(self.lid.."SetSRS")
+ self.PathToSRS = PathToSRS or "C:\\Program Files\\DCS-SimpleRadio-Standalone" --
+ self.Gender = Gender or "male" --
+ self.Culture = Culture or "en-US" --
+ self.Port = Port or 5002 --
+ self.Voice = Voice --
+ self.PathToGoogleKey = PathToGoogleKey --
+ self.Volume = Volume or 1.0 --
+ self.UseSRS = true
+ self.Frequency = Frequency or {127,251} --
+ self.BCFrequency = self.Frequency
+ self.Modulation = Modulation or {radio.modulation.FM,radio.modulation.AM} --
+ self.BCModulation = self.Modulation
+ -- set up SRS
+ self.SRS=MSRS:New(self.PathToSRS,self.Frequency,self.Modulation,self.Volume)
+ self.SRS:SetCoalition(self.Coalition)
+ self.SRS:SetLabel(self.MenuName or self.Name)
+ self.SRS:SetGender(self.Gender)
+ self.SRS:SetCulture(self.Culture)
+ self.SRS:SetPort(self.Port)
+ self.SRS:SetVoice(self.Voice)
+ if self.PathToGoogleKey then
+ self.SRS:SetGoogle(self.PathToGoogleKey)
+ end
+ self.SRSQueue = MSRSQUEUE:New(self.MenuName or self.Name)
+ return self
+end
+
+--- [User] Set SRS Broadcast - for the announcement to joining players which SRS frequency, modulation to use. Use in case you want to set this differently to the standard SRS.
+-- @param #PLAYERTASKCONTROLLER self
+-- @param #number Frequency Frequency to be used. Can also be given as a table of multiple frequencies, e.g. 271 or {127,251}. There needs to be exactly the same number of modulations!
+-- @param #number Modulation Modulation to be used. Can also be given as a table of multiple modulations, e.g. radio.modulation.AM or {radio.modulation.FM,radio.modulation.AM}. There needs to be exactly the same number of frequencies!
+-- @return #PLAYERTASKCONTROLLER self
+function PLAYERTASKCONTROLLER:SetSRSBroadcast(Frequency,Modulation)
+ self:T(self.lid.."SetSRSBroadcast")
+ if self.SRS then
+ self.BCFrequency = Frequency
+ self.BCModulation = Modulation
+ end
+ return self
+end
+
+-------------------------------------------------------------------------------------------------------------------
+-- FSM Functions PLAYERTASKCONTROLLER
+-- TODO: FSM Functions PLAYERTASKCONTROLLER
+-------------------------------------------------------------------------------------------------------------------
+
--- [Internal] On after Status call
-- @param #PLAYERTASKCONTROLLER self
-- @param #string From
@@ -1095,14 +2542,16 @@ function PLAYERTASKCONTROLLER:onafterStatus(From, Event, To)
self:I({From, Event, To})
self:_CheckTargetQueue()
self:_CheckTaskQueue()
+ self:_CheckPrecisionTasks()
self:_BuildMenus()
local targetcount = self.TargetQueue:Count()
local taskcount = self.TaskQueue:Count()
local playercount = self.ClientSet:CountAlive()
+ local assignedtasks = self.TasksPerPlayer:Count()
if self.verbose then
- local text = string.format("New Targets: %02d | Active Tasks: %02d | Active Players: %02d",targetcount,taskcount,playercount)
+ local text = string.format("New Targets: %02d | Active Tasks: %02d | Active Players: %02d | Assigned Tasks: %02d",targetcount,taskcount,playercount,assignedtasks)
self:I(text)
end
@@ -1120,8 +2569,8 @@ end
-- @param Ops.PlayerTask#PLAYERTASK Task
-- @return #PLAYERTASKCONTROLLER self
function PLAYERTASKCONTROLLER:onafterTaskDone(From, Event, To, Task)
- self:I({From, Event, To})
- self:I(self.lid.."TaskDone")
+ self:T({From, Event, To})
+ self:T(self.lid.."TaskDone")
return self
end
@@ -1133,8 +2582,18 @@ end
-- @param Ops.PlayerTask#PLAYERTASK Task
-- @return #PLAYERTASKCONTROLLER self
function PLAYERTASKCONTROLLER:onafterTaskCancelled(From, Event, To, Task)
- self:I({From, Event, To})
- self:I(self.lid.."TaskCancelled")
+ self:T({From, Event, To})
+ self:T(self.lid.."TaskCancelled")
+ local canceltxt = self.gettext:GetEntry("TASKCANCELLED",self.locale)
+ local canceltxttts = self.gettext:GetEntry("TASKCANCELLEDTTS",self.locale)
+ local taskname = string.format(canceltxt, Task.PlayerTaskNr, tostring(Task.Type))
+ if not self.NoScreenOutput then
+ local m = MESSAGE:New(taskname,15,"Tasking"):ToCoalition(self.Coalition)
+ end
+ if self.UseSRS then
+ taskname = string.format(canceltxttts, self.MenuName or self.Name, Task.PlayerTaskNr, tostring(Task.TTSType))
+ self.SRSQueue:NewTransmission(taskname,nil,self.SRS,nil,2)
+ end
return self
end
@@ -1146,10 +2605,18 @@ end
-- @param Ops.PlayerTask#PLAYERTASK Task
-- @return #PLAYERTASKCONTROLLER self
function PLAYERTASKCONTROLLER:onafterTaskSuccess(From, Event, To, Task)
- self:I({From, Event, To})
- self:I(self.lid.."TaskSuccess")
- local taskname = string.format("Task #%d %s Success!", Task.PlayerTaskNr, tostring(Task.Type))
- local m = MESSAGE:New(taskname,15,"Tasking"):ToCoalition(self.Coalition)
+ self:T({From, Event, To})
+ self:T(self.lid.."TaskSuccess")
+ local succtxt = self.gettext:GetEntry("TASKSUCCESS",self.locale)
+ local succtxttts = self.gettext:GetEntry("TASKSUCCESSTTS",self.locale)
+ local taskname = string.format(succtxt, Task.PlayerTaskNr, tostring(Task.Type))
+ if not self.NoScreenOutput then
+ local m = MESSAGE:New(taskname,15,"Tasking"):ToCoalition(self.Coalition)
+ end
+ if self.UseSRS then
+ taskname = string.format(succtxttts, self.MenuName or self.Name, Task.PlayerTaskNr, tostring(Task.TTSType))
+ self.SRSQueue:NewTransmission(taskname,nil,self.SRS,nil,2)
+ end
return self
end
@@ -1161,10 +2628,18 @@ end
-- @param Ops.PlayerTask#PLAYERTASK Task
-- @return #PLAYERTASKCONTROLLER self
function PLAYERTASKCONTROLLER:onafterTaskFailed(From, Event, To, Task)
- self:I({From, Event, To})
- self:I(self.lid.."TaskFailed")
- local taskname = string.format("Task #%d %s Failed!", Task.PlayerTaskNr, tostring(Task.Type))
- local m = MESSAGE:New(taskname,15,"Tasking"):ToCoalition(self.Coalition)
+ self:T({From, Event, To})
+ self:T(self.lid.."TaskFailed")
+ local failtxt = self.gettext:GetEntry("TASKFAILED",self.locale)
+ local failtxttts = self.gettext:GetEntry("TASKFAILEDTTS",self.locale)
+ local taskname = string.format(failtxt, Task.PlayerTaskNr, tostring(Task.Type))
+ if not self.NoScreenOutput then
+ local m = MESSAGE:New(taskname,15,"Tasking"):ToCoalition(self.Coalition)
+ end
+ if self.UseSRS then
+ taskname = string.format(failtxttts, self.MenuName or self.Name, Task.PlayerTaskNr, tostring(Task.TTSType))
+ self.SRSQueue:NewTransmission(taskname,nil,self.SRS,nil,2)
+ end
return self
end
@@ -1176,10 +2651,18 @@ end
-- @param Ops.PlayerTask#PLAYERTASK Task
-- @return #PLAYERTASKCONTROLLER self
function PLAYERTASKCONTROLLER:onafterTaskRepeatOnFailed(From, Event, To, Task)
- self:I({From, Event, To})
- self:I(self.lid.."RepeatOnFailed")
- local taskname = string.format("Task #%d %s Failed! Replanning!", Task.PlayerTaskNr, tostring(Task.Type))
- local m = MESSAGE:New(taskname,15,"Tasking"):ToCoalition(self.Coalition)
+ self:T({From, Event, To})
+ self:T(self.lid.."RepeatOnFailed")
+ local repfailtxt = self.gettext:GetEntry("TASKFAILEDREPLAN",self.locale)
+ local repfailtxttts = self.gettext:GetEntry("TASKFAILEDREPLANTTS",self.locale)
+ local taskname = string.format(repfailtxt, Task.PlayerTaskNr, tostring(Task.Type))
+ if not self.NoScreenOutput then
+ local m = MESSAGE:New(taskname,15,"Tasking"):ToCoalition(self.Coalition)
+ end
+ if self.UseSRS then
+ taskname = string.format(repfailtxttts, self.MenuName or self.Name, Task.PlayerTaskNr, tostring(Task.TTSType))
+ self.SRSQueue:NewTransmission(taskname,nil,self.SRS,nil,2)
+ end
return self
end
@@ -1191,27 +2674,39 @@ end
-- @param Ops.PlayerTask#PLAYERTASK Task
-- @return #PLAYERTASKCONTROLLER self
function PLAYERTASKCONTROLLER:onafterTaskAdded(From, Event, To, Task)
- self:I({From, Event, To})
- self:I(self.lid.."TaskAdded")
- local taskname = string.format("%s has a new Task %s", self.Name, tostring(Task.Type))
- local m = MESSAGE:New(taskname,15,"Tasking"):ToCoalition(self.Coalition)
+ self:T({From, Event, To})
+ self:T(self.lid.."TaskAdded")
+ local addtxt = self.gettext:GetEntry("TASKADDED",self.locale)
+ local taskname = string.format(addtxt, self.MenuName or self.Name, tostring(Task.Type))
+ if not self.NoScreenOutput then
+ local m = MESSAGE:New(taskname,15,"Tasking"):ToCoalition(self.Coalition)
+ end
+ if self.UseSRS then
+ taskname = string.format(addtxt, self.MenuName or self.Name, tostring(Task.TTSType))
+ self.SRSQueue:NewTransmission(taskname,nil,self.SRS,nil,2)
+ end
return self
end
--- [Internal] On after Stop call
-- @param #PLAYERTASKCONTROLLER self
-- @param #string From
--- @param #string Event
+-- @param #string Event
-- @param #string To
-- @return #PLAYERTASKCONTROLLER self
function PLAYERTASKCONTROLLER:onafterStop(From, Event, To)
- self:I({From, Event, To})
- self:I(self.lid.."Stopped.")
+ self:T({From, Event, To})
+ self:T(self.lid.."Stopped.")
-- Player leaves
self:UnHandleEvent(EVENTS.PlayerLeaveUnit)
self:UnHandleEvent(EVENTS.Ejection)
self:UnHandleEvent(EVENTS.Crash)
self:UnHandleEvent(EVENTS.PilotDead)
+ self:UnHandleEvent(EVENTS.PlayerEnterAircraft)
return self
end
+-------
+-- END PLAYERTASKCONTROLLER
+-----
+end
diff --git a/Moose Development/Moose/Utilities/Utils.lua b/Moose Development/Moose/Utilities/Utils.lua
index 650aaea3a..5b832317e 100644
--- a/Moose Development/Moose/Utilities/Utils.lua
+++ b/Moose Development/Moose/Utilities/Utils.lua
@@ -1725,10 +1725,16 @@ end
-- @return #number Os time in seconds.
function UTILS.GetOSTime()
if os then
- return os.clock()
+ local ts = 0
+ local t = os.date("*t")
+ local s = t.sec
+ local m = t.min * 60
+ local h = t.hour * 3600
+ ts = s+m+h
+ return ts
+ else
+ return nil
end
-
- return nil
end
--- Shuffle a table accoring to Fisher Yeates algorithm
diff --git a/Moose Development/Moose/Wrapper/Airbase.lua b/Moose Development/Moose/Wrapper/Airbase.lua
index 157715061..57035a324 100644
--- a/Moose Development/Moose/Wrapper/Airbase.lua
+++ b/Moose Development/Moose/Wrapper/Airbase.lua
@@ -500,6 +500,9 @@ AIRBASE.MarianaIslands={
-- * AIRBASE.SouthAtlantic.Punta_Arenas
-- * AIRBASE.SouthAtlantic.Pampa_Guanaco
-- * AIRBASE.SouthAtlantic.San_Julian
+-- * AIRBASE.SouthAtlantic.Puerto_Williams
+-- * AIRBASE.SouthAtlantic.Puerto_Natales
+-- * AIRBASE.SouthAtlantic.El_Calafate
--
--@field MarianaIslands
AIRBASE.SouthAtlantic={
@@ -513,6 +516,9 @@ AIRBASE.SouthAtlantic={
["Punta_Arenas"]="Punta Arenas",
["Pampa_Guanaco"]="Pampa Guanaco",
["San_Julian"]="San Julian",
+ ["Puerto_Williams"]="Puerto Williams",
+ ["Puerto_Natales"]="Puerto Natales",
+ ["El_Calafate"]="El Calafate",
}
--- AIRBASE.ParkingSpot ".Coordinate, ".TerminalID", ".TerminalType", ".TOAC", ".Free", ".TerminalID0", ".DistToRwy".