diff --git a/Moose Development/Moose/AI/AI_A2A_Patrol.lua b/Moose Development/Moose/AI/AI_A2A_Patrol.lua index 229e15328..d0a01bdd6 100644 --- a/Moose Development/Moose/AI/AI_A2A_Patrol.lua +++ b/Moose Development/Moose/AI/AI_A2A_Patrol.lua @@ -121,7 +121,7 @@ AI_A2A_PATROL = { --- Creates a new AI_A2A_PATROL object -- @param #AI_A2A_PATROL self --- @param Wrapper.Group#GROUP AIPatrol +-- @param Wrapper.Group#GROUP AIPatrol The patrol group object. -- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed. -- @param DCS#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol. -- @param DCS#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol. @@ -137,7 +137,7 @@ AI_A2A_PATROL = { function AI_A2A_PATROL:New( AIPatrol, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType ) local AI_Air = AI_AIR:New( AIPatrol ) - local AI_Air_Patrol = AI_A2A_PATROL:New( AI_Air, AIPatrol, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType ) + local AI_Air_Patrol = AI_AIR_PATROL:New( AI_Air, AIPatrol, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType ) local self = BASE:Inherit( self, AI_Air_Patrol ) -- #AI_A2A_PATROL self:SetFuelThreshold( .2, 60 ) diff --git a/Moose Development/Moose/AI/AI_Air.lua b/Moose Development/Moose/AI/AI_Air.lua index 5fbd84349..213e58757 100644 --- a/Moose Development/Moose/AI/AI_Air.lua +++ b/Moose Development/Moose/AI/AI_Air.lua @@ -492,6 +492,7 @@ function AI_AIR:onafterStatus() OldAIControllable:SetTask( TimedOrbitTask, 10 ) self:Fuel() + RTB = true end else end diff --git a/Moose Development/Moose/AI/AI_Air_Engage.lua b/Moose Development/Moose/AI/AI_Air_Engage.lua index 50b2e0988..2679d472d 100644 --- a/Moose Development/Moose/AI/AI_Air_Engage.lua +++ b/Moose Development/Moose/AI/AI_Air_Engage.lua @@ -374,7 +374,7 @@ end -- @param #string To The To State string. function AI_AIR_ENGAGE:onafterAccomplish( AIGroup, From, Event, To ) self.Accomplished = true - self:SetDetectionOff() + --self:SetDetectionOff() end --- @param #AI_AIR_ENGAGE self diff --git a/Moose Development/Moose/Core/Point.lua b/Moose Development/Moose/Core/Point.lua index 6358341ef..65022dec4 100644 --- a/Moose Development/Moose/Core/Point.lua +++ b/Moose Development/Moose/Core/Point.lua @@ -655,6 +655,28 @@ do -- COORDINATE return Angle end + --- Return an intermediate COORDINATE between this an another coordinate. + -- @param #COORDINATE self + -- @param #COORDINATE ToCoordinate The other coordinate. + -- @param #number Fraction The fraction (0,1) where the new coordinate is created. Default 0.5, i.e. in the middle. + -- @return #COORDINATE Coordinate between this and the other coordinate. + function COORDINATE:GetIntermediateCoordinate( ToCoordinate, Fraction ) + + local f=Fraction or 0.5 + + -- Get the vector from A to B + local vec=UTILS.VecSubstract(ToCoordinate, self) + + -- Scale the vector. + vec.x=f*vec.x + vec.y=f*vec.y + vec.z=f*vec.z + + -- Move the vector to start at the end of A. + vec=UTILS.VecAdd(self, vec) + + return self:New(vec.x,vec.y,vec.z) + end --- Return the 2D distance in meters between the target COORDINATE and the COORDINATE. -- @param #COORDINATE self diff --git a/Moose Development/Moose/Core/RadioQueue.lua b/Moose Development/Moose/Core/RadioQueue.lua index 756b5a967..33857ba43 100644 --- a/Moose Development/Moose/Core/RadioQueue.lua +++ b/Moose Development/Moose/Core/RadioQueue.lua @@ -113,18 +113,20 @@ end -- @param #number dt (Optional) Time step in seconds for checking the queue. Default 0.01 sec. -- @return #RADIOQUEUE self The RADIOQUEUE object. function RADIOQUEUE:Start(delay, dt) - + + -- Delay before start. self.delay=delay or 1 + -- Time interval for queue check. self.dt=dt or 0.01 + -- Debug message. self:I(self.lid..string.format("Starting RADIOQUEUE %s on Frequency %.2f MHz [modulation=%d] in %.1f seconds (dt=%.3f sec)", self.alias, self.frequency/1000000, self.modulation, delay, dt)) - + -- Start Scheduler. if self.schedonce then - self:_CheckRadioQueueDelayed(self.delta) + self:_CheckRadioQueueDelayed(delay) else - --self.RQid=self.scheduler:Schedule(self, self._CheckRadioQueue, {}, delay, dt) self.RQid=self.scheduler:Schedule(nil, RADIOQUEUE._CheckRadioQueue, {self}, delay, dt) end diff --git a/Moose Development/Moose/Core/Settings.lua b/Moose Development/Moose/Core/Settings.lua index fd1aca413..3a557de65 100644 --- a/Moose Development/Moose/Core/Settings.lua +++ b/Moose Development/Moose/Core/Settings.lua @@ -1,9 +1,9 @@ --- **Core** - Manages various settings for running missions, consumed by moose classes and provides a menu system for players to tweak settings in running missions. -- -- === --- +-- -- ## Features: --- +-- -- * Provide a settings menu system to the players. -- * Provide a player settings menu and an overall mission settings menu. -- * Mission settings provide default settings, while player settings override mission settings. @@ -11,19 +11,19 @@ -- * Provide a menu to select between different coordinate formats for A2A coordinates. -- * Provide a menu to select between different message time duration options. -- * Provide a menu to select between different metric systems. --- +-- -- === --- +-- -- The documentation of the SETTINGS class can be found further in this document. --- +-- -- === --- +-- -- # **AUTHORS and CONTRIBUTIONS** --- --- ### Contributions: --- --- ### Authors: --- +-- +-- ### Contributions: +-- +-- ### Authors: +-- -- * **FlightControl**: Design & Programming -- -- @module Core.Settings @@ -34,185 +34,187 @@ -- @extends Core.Base#BASE --- Takes care of various settings that influence the behaviour of certain functionalities and classes within the MOOSE framework. --- +-- -- === --- +-- -- The SETTINGS class takes care of various settings that influence the behaviour of certain functionalities and classes within the MOOSE framework. -- SETTINGS can work on 2 levels: --- --- - **Default settings**: A running mission has **Default settings**. +-- +-- - **Default settings**: A running mission has **Default settings**. -- - **Player settings**: For each player its own **Player settings** can be defined, overriding the **Default settings**. --- +-- -- So, when there isn't any **Player setting** defined for a player for a specific setting, or, the player cannot be identified, the **Default setting** will be used instead. --- +-- -- # 1) \_SETTINGS object --- +-- -- MOOSE defines by default a singleton object called **\_SETTINGS**. Use this object to modify all the **Default settings** for a running mission. -- For each player, MOOSE will automatically allocate also a **player settings** object, and will expose a radio menu to allow the player to adapt the settings to his own preferences. --- +-- -- # 2) SETTINGS Menu --- +-- -- Settings can be adapted by the Players and by the Mission Administrator through **radio menus, which are automatically available in the mission**. -- These menus can be found **on level F10 under "Settings"**. There are two kinds of menus generated by the system. --- +-- -- ## 2.1) Default settings menu --- +-- -- A menu is created automatically per Command Center that allows to modify the **Default** settings. -- So, when joining a CC unit, a menu will be available that allows to change the settings parameters **FOR ALL THE PLAYERS**! -- Note that the **Default settings** will only be used when a player has not choosen its own settings. --- +-- -- ## 2.2) Player settings menu --- +-- -- A menu is created automatically per Player Slot (group) that allows to modify the **Player** settings. -- So, when joining a slot, a menu wil be available that allows to change the settings parameters **FOR THE PLAYER ONLY**! -- Note that when a player has not chosen a specific setting, the **Default settings** will be used. --- +-- -- ## 2.3) Show or Hide the Player Setting menus --- +-- -- Of course, it may be requried not to show any setting menus. In this case, a method is available on the **\_SETTINGS object**. -- Use @{#SETTINGS.SetPlayerMenuOff}() to hide the player menus, and use @{#SETTINGS.SetPlayerMenuOn}() show the player menus. -- Note that when this method is used, any player already in a slot will not have its menus visibility changed. --- The option will only have effect when a player enters a new slot or changes a slot. --- +-- The option will only have effect when a player enters a new slot or changes a slot. +-- -- Example: --- +-- -- _SETTINGS:SetPlayerMenuOff() -- will disable the player menus. -- _SETTINGS:SetPlayerMenuOn() -- will enable the player menus. -- -- But only when a player exits and reenters the slot these settings will have effect! --- --- +-- +-- -- # 3) Settings --- +-- -- There are different settings that are managed and applied within the MOOSE framework. -- See below a comprehensive description of each. --- +-- -- ## 3.1) **A2G coordinates** display formatting --- +-- -- ### 3.1.1) A2G coordinates setting **types** --- +-- -- Will customize which display format is used to indicate A2G coordinates in text as part of the Command Center communications. --- +-- -- - A2G BR: [Bearing Range](https://en.wikipedia.org/wiki/Bearing_(navigation)). -- - A2G MGRS: The [Military Grid Reference System](https://en.wikipedia.org/wiki/Military_Grid_Reference_System). The accuracy can also be adapted. -- - A2G LL DMS: Lattitude Longitude [Degrees Minutes Seconds](https://en.wikipedia.org/wiki/Geographic_coordinate_conversion). The accuracy can also be adapted. -- - A2G LL DDM: Lattitude Longitude [Decimal Degrees Minutes](https://en.wikipedia.org/wiki/Decimal_degrees). The accuracy can also be adapted. --- +-- -- ### 3.1.2) A2G coordinates setting **menu** --- +-- -- The settings can be changed by using the **Default settings menu** on the Command Center or the **Player settings menu** on the Player Slot. --- +-- -- ### 3.1.3) A2G coordinates setting **methods** --- +-- -- There are different methods that can be used to change the **System settings** using the \_SETTINGS object. --- +-- -- - @{#SETTINGS.SetA2G_BR}(): Enable the BR display formatting by default. -- - @{#SETTINGS.SetA2G_MGRS}(): Enable the MGRS display formatting by default. Use @{SETTINGS.SetMGRS_Accuracy}() to adapt the accuracy of the MGRS formatting. --- - @{#SETTINGS.SetA2G_LL_DMS}(): Enable the LL DMS display formatting by default. Use @{SETTINGS.SetLL_Accuracy}() to adapt the accuracy of the Seconds formatting. +-- - @{#SETTINGS.SetA2G_LL_DMS}(): Enable the LL DMS display formatting by default. Use @{SETTINGS.SetLL_Accuracy}() to adapt the accuracy of the Seconds formatting. -- - @{#SETTINGS.SetA2G_LL_DDM}(): Enable the LL DDM display formatting by default. Use @{SETTINGS.SetLL_Accuracy}() to adapt the accuracy of the Seconds formatting. --- +-- -- ### 3.1.4) A2G coordinates setting - additional notes --- --- One additional note on BR. In a situation when a BR coordinate should be given, +-- +-- One additional note on BR. In a situation when a BR coordinate should be given, -- but there isn't any player context (no player unit to reference from), the MGRS formatting will be applied! --- +-- -- ## 3.2) **A2A coordinates** formatting --- +-- -- ### 3.2.1) A2A coordinates setting **types** --- +-- -- Will customize which display format is used to indicate A2A coordinates in text as part of the Command Center communications. --- +-- -- - A2A BRAA: [Bearing Range Altitude Aspect](https://en.wikipedia.org/wiki/Bearing_(navigation)). -- - A2A MGRS: The [Military Grid Reference System](https://en.wikipedia.org/wiki/Military_Grid_Reference_System). The accuracy can also be adapted. -- - A2A LL DMS: Lattitude Longitude [Degrees Minutes Seconds](https://en.wikipedia.org/wiki/Geographic_coordinate_conversion). The accuracy can also be adapted. -- - A2A LL DDM: Lattitude Longitude [Decimal Degrees and Minutes](https://en.wikipedia.org/wiki/Decimal_degrees). The accuracy can also be adapted. -- - A2A BULLS: [Bullseye](http://falcon4.wikidot.com/concepts:bullseye). --- +-- -- ### 3.2.2) A2A coordinates setting **menu** --- +-- -- The settings can be changed by using the **Default settings menu** on the Command Center or the **Player settings menu** on the Player Slot. --- +-- -- ### 3.2.3) A2A coordinates setting **methods** --- +-- -- There are different methods that can be used to change the **System settings** using the \_SETTINGS object. --- +-- -- - @{#SETTINGS.SetA2A_BRAA}(): Enable the BR display formatting by default. -- - @{#SETTINGS.SetA2A_MGRS}(): Enable the MGRS display formatting by default. Use @{SETTINGS.SetMGRS_Accuracy}() to adapt the accuracy of the MGRS formatting. --- - @{#SETTINGS.SetA2A_LL_DMS}(): Enable the LL DMS display formatting by default. Use @{SETTINGS.SetLL_Accuracy}() to adapt the accuracy of the Seconds formatting. +-- - @{#SETTINGS.SetA2A_LL_DMS}(): Enable the LL DMS display formatting by default. Use @{SETTINGS.SetLL_Accuracy}() to adapt the accuracy of the Seconds formatting. -- - @{#SETTINGS.SetA2A_LL_DDM}(): Enable the LL DDM display formatting by default. Use @{SETTINGS.SetLL_Accuracy}() to adapt the accuracy of the Seconds formatting. -- - @{#SETTINGS.SetA2A_BULLS}(): Enable the BULLSeye display formatting by default. --- +-- -- ### 3.2.4) A2A coordinates settings - additional notes --- --- One additional note on BRAA. In a situation when a BRAA coordinate should be given, +-- +-- One additional note on BRAA. In a situation when a BRAA coordinate should be given, -- but there isn't any player context (no player unit to reference from), the MGRS formatting will be applied! --- +-- -- ## 3.3) **Measurements** formatting --- +-- -- ### 3.3.1) Measurements setting **types** --- +-- -- Will customize the measurements system being used as part as part of the Command Center communications. --- +-- -- - **Metrics** system: Applies the [Metrics system](https://en.wikipedia.org/wiki/Metric_system) ... --- - **Imperial** system: Applies the [Imperial system](https://en.wikipedia.org/wiki/Imperial_units) ... --- +-- - **Imperial** system: Applies the [Imperial system](https://en.wikipedia.org/wiki/Imperial_units) ... +-- -- ### 3.3.2) Measurements setting **menu** --- +-- -- The settings can be changed by using the **Default settings menu** on the Command Center or the **Player settings menu** on the Player Slot. --- +-- -- ### 3.3.3) Measurements setting **methods** --- +-- -- There are different methods that can be used to change the **Default settings** using the \_SETTINGS object. --- +-- -- - @{#SETTINGS.SetMetric}(): Enable the Metric system. -- - @{#SETTINGS.SetImperial}(): Enable the Imperial system. --- +-- -- ## 3.4) **Message** display times --- +-- -- ### 3.4.1) Message setting **types** --- +-- -- There are various **Message Types** that will influence the duration how long a message will appear as part of the Command Center communications. --- +-- -- - **Update** message: A short update message. -- - **Information** message: Provides new information **while** executing a mission. -- - **Briefing** message: Provides a complete briefing **before** executing a mission. -- - **Overview report**: Provides a short report overview, the summary of the report. -- - **Detailed report**: Provides a complete report. --- +-- -- ### 3.4.2) Message setting **menu** --- +-- -- The settings can be changed by using the **Default settings menu** on the Command Center or the **Player settings menu** on the Player Slot. --- +-- -- Each Message Type has specific timings that will be applied when the message is displayed. -- The Settings Menu will provide for each Message Type a selection of proposed durations from which can be choosen. -- So the player can choose its own amount of seconds how long a message should be displayed of a certain type. -- Note that **Update** messages can be chosen not to be displayed at all! --- +-- -- ### 3.4.3) Message setting **methods** --- +-- -- There are different methods that can be used to change the **System settings** using the \_SETTINGS object. --- --- - @{#SETTINGS.SetMessageTime}(): Define for a specific @{Message.MESSAGE.MessageType} the duration to be displayed in seconds. --- - @{#SETTINGS.GetMessageTime}(): Retrieves for a specific @{Message.MESSAGE.MessageType} the duration to be displayed in seconds. --- +-- +-- - @{#SETTINGS.SetMessageTime}(): Define for a specific @{Message.MESSAGE.MessageType} the duration to be displayed in seconds. +-- - @{#SETTINGS.GetMessageTime}(): Retrieves for a specific @{Message.MESSAGE.MessageType} the duration to be displayed in seconds. +-- -- ## 3.5) **Era** of the battle --- +-- -- The threat level metric is scaled according the era of the battle. A target that is AAA, will pose a much greather threat in WWII than on modern warfare. -- Therefore, there are 4 era that are defined within the settings: --- +-- -- - **WWII** era: Use for warfare with equipment during the world war II time. -- - **Korea** era: Use for warfare with equipment during the Korea war time. --- - **Cold War** era: Use for warfare with equipment during the cold war time. +-- - **Cold War** era: Use for warfare with equipment during the cold war time. -- - **Modern** era: Use for warfare with modern equipment in the 2000s. --- --- There are different API defined that you can use with the _SETTINGS object to configure your mission script to work in one of the 4 era: +-- +-- There are different API defined that you can use with the _SETTINGS object to configure your mission script to work in one of the 4 era: -- @{#SETTINGS.SetEraWWII}(), @{#SETTINGS.SetEraKorea}(), @{#SETTINGS.SetEraCold}(), @{#SETTINGS.SetEraModern}() --- +-- -- === --- +-- -- @field #SETTINGS SETTINGS = { ClassName = "SETTINGS", ShowPlayerMenu = true, + MenuShort = false, + MenuStatic = false, } SETTINGS.__Enum = {} @@ -235,7 +237,7 @@ do -- SETTINGS --- SETTINGS constructor. -- @param #SETTINGS self -- @return #SETTINGS - function SETTINGS:Set( PlayerName ) + function SETTINGS:Set( PlayerName ) if PlayerName == nil then local self = BASE:Inherit( self, BASE:New() ) -- #SETTINGS @@ -260,14 +262,28 @@ do -- SETTINGS return Settings end end - - + + --- Set short text for menus on (*true*) or off (*false*). + -- Short text are better suited for, e.g., VR. + -- @param #SETTINGS self + -- @param #boolean onoff If *true* use short menu texts. If *false* long ones (default). + function SETTINGS:SetMenutextShort(onoff) + _SETTINGS.MenuShort = onoff + end + + --- Set menu to be static. + -- @param #SETTINGS self + -- @param #boolean onoff If *true* menu is static. If *false* menu will be updated after changes (default). + function SETTINGS:SetMenuStatic(onoff) + _SETTINGS.MenuStatic = onoff + end + --- Sets the SETTINGS metric. -- @param #SETTINGS self function SETTINGS:SetMetric() self.Metric = true end - + --- Gets if the SETTINGS is metric. -- @param #SETTINGS self -- @return #boolean true if metric. @@ -280,7 +296,7 @@ do -- SETTINGS function SETTINGS:SetImperial() self.Metric = false end - + --- Gets if the SETTINGS is imperial. -- @param #SETTINGS self -- @return #boolean true if imperial. @@ -317,7 +333,7 @@ do -- SETTINGS function SETTINGS:GetMGRS_Accuracy() return self.MGRS_Accuracy or _SETTINGS:GetMGRS_Accuracy() end - + --- Sets the SETTINGS Message Display Timing of a MessageType -- @param #SETTINGS self -- @param Core.Message#MESSAGE MessageType The type of the message. @@ -326,8 +342,8 @@ do -- SETTINGS self.MessageTypeTimings = self.MessageTypeTimings or {} self.MessageTypeTimings[MessageType] = MessageTime end - - + + --- Gets the SETTINGS Message Display Timing of a MessageType -- @param #SETTINGS self -- @param Core.Message#MESSAGE MessageType The type of the message. @@ -463,40 +479,77 @@ do -- SETTINGS end --- @param #SETTINGS self + -- @param Wrapper.Group#GROUP MenuGroup Group for which to add menus. + -- @param #table RootMenu Root menu table -- @return #SETTINGS function SETTINGS:SetSystemMenu( MenuGroup, RootMenu ) local MenuText = "System Settings" - + local MenuTime = timer.getTime() - + local SettingsMenu = MENU_GROUP:New( MenuGroup, MenuText, RootMenu ):SetTime( MenuTime ) - local A2GCoordinateMenu = MENU_GROUP:New( MenuGroup, "A2G Coordinate System", SettingsMenu ):SetTime( MenuTime ) - - - if not self:IsA2G_LL_DMS() then - MENU_GROUP_COMMAND:New( MenuGroup, "Lat/Lon Degree Min Sec (LL DMS)", A2GCoordinateMenu, self.A2GMenuSystem, self, MenuGroup, RootMenu, "LL DMS" ):SetTime( MenuTime ) + ------- + -- A2G Coordinate System + ------- + + local text="A2G Coordinate System" + if _SETTINGS.MenuShort then + text="A2G Coordinates" end - + local A2GCoordinateMenu = MENU_GROUP:New( MenuGroup, text, SettingsMenu ):SetTime( MenuTime ) + + -- Set LL DMS + if not self:IsA2G_LL_DMS() then + local text="Lat/Lon Degree Min Sec (LL DMS)" + if _SETTINGS.MenuShort then + text="LL DMS" + end + MENU_GROUP_COMMAND:New( MenuGroup, text, A2GCoordinateMenu, self.A2GMenuSystem, self, MenuGroup, RootMenu, "LL DMS" ):SetTime( MenuTime ) + end + + -- Set LL DDM if not self:IsA2G_LL_DDM() then + local text="Lat/Lon Degree Dec Min (LL DDM)" + if _SETTINGS.MenuShort then + text="LL DDM" + end MENU_GROUP_COMMAND:New( MenuGroup, "Lat/Lon Degree Dec Min (LL DDM)", A2GCoordinateMenu, self.A2GMenuSystem, self, MenuGroup, RootMenu, "LL DDM" ):SetTime( MenuTime ) end - + + -- Set LL DMS accuracy. if self:IsA2G_LL_DDM() then + local text1="LL DDM Accuracy 1" + local text2="LL DDM Accuracy 2" + local text3="LL DDM Accuracy 3" + if _SETTINGS.MenuShort then + text1="LL DDM" + end MENU_GROUP_COMMAND:New( MenuGroup, "LL DDM Accuracy 1", A2GCoordinateMenu, self.MenuLL_DDM_Accuracy, self, MenuGroup, RootMenu, 1 ):SetTime( MenuTime ) MENU_GROUP_COMMAND:New( MenuGroup, "LL DDM Accuracy 2", A2GCoordinateMenu, self.MenuLL_DDM_Accuracy, self, MenuGroup, RootMenu, 2 ):SetTime( MenuTime ) MENU_GROUP_COMMAND:New( MenuGroup, "LL DDM Accuracy 3", A2GCoordinateMenu, self.MenuLL_DDM_Accuracy, self, MenuGroup, RootMenu, 3 ):SetTime( MenuTime ) end - + + -- Set BR. if not self:IsA2G_BR() then - MENU_GROUP_COMMAND:New( MenuGroup, "Bearing, Range (BR)", A2GCoordinateMenu, self.A2GMenuSystem, self, MenuGroup, RootMenu, "BR" ):SetTime( MenuTime ) + local text="Bearing, Range (BR)" + if _SETTINGS.MenuShort then + text="BR" + end + MENU_GROUP_COMMAND:New( MenuGroup, text , A2GCoordinateMenu, self.A2GMenuSystem, self, MenuGroup, RootMenu, "BR" ):SetTime( MenuTime ) end - + + -- Set MGRS. if not self:IsA2G_MGRS() then - MENU_GROUP_COMMAND:New( MenuGroup, "Military Grid (MGRS)", A2GCoordinateMenu, self.A2GMenuSystem, self, MenuGroup, RootMenu, "MGRS" ):SetTime( MenuTime ) + local text="Military Grid (MGRS)" + if _SETTINGS.MenuShort then + text="MGRS" + end + MENU_GROUP_COMMAND:New( MenuGroup, text, A2GCoordinateMenu, self.A2GMenuSystem, self, MenuGroup, RootMenu, "MGRS" ):SetTime( MenuTime ) end - + + -- Set MGRS accuracy. if self:IsA2G_MGRS() then MENU_GROUP_COMMAND:New( MenuGroup, "MGRS Accuracy 1", A2GCoordinateMenu, self.MenuMGRS_Accuracy, self, MenuGroup, RootMenu, 1 ):SetTime( MenuTime ) MENU_GROUP_COMMAND:New( MenuGroup, "MGRS Accuracy 2", A2GCoordinateMenu, self.MenuMGRS_Accuracy, self, MenuGroup, RootMenu, 2 ):SetTime( MenuTime ) @@ -505,32 +558,61 @@ do -- SETTINGS MENU_GROUP_COMMAND:New( MenuGroup, "MGRS Accuracy 5", A2GCoordinateMenu, self.MenuMGRS_Accuracy, self, MenuGroup, RootMenu, 5 ):SetTime( MenuTime ) end - local A2ACoordinateMenu = MENU_GROUP:New( MenuGroup, "A2A Coordinate System", SettingsMenu ):SetTime( MenuTime ) + ------- + -- A2A Coordinate System + ------- + + local text="A2A Coordinate System" + if _SETTINGS.MenuShort then + text="A2A Coordinates" + end + local A2ACoordinateMenu = MENU_GROUP:New( MenuGroup, text, SettingsMenu ):SetTime( MenuTime ) if not self:IsA2A_LL_DMS() then - MENU_GROUP_COMMAND:New( MenuGroup, "Lat/Lon Degree Min Sec (LL DMS)", A2ACoordinateMenu, self.A2AMenuSystem, self, MenuGroup, RootMenu, "LL DMS" ):SetTime( MenuTime ) + local text="Lat/Lon Degree Min Sec (LL DMS)" + if _SETTINGS.MenuShort then + text="LL DMS" + end + MENU_GROUP_COMMAND:New( MenuGroup, text, A2ACoordinateMenu, self.A2AMenuSystem, self, MenuGroup, RootMenu, "LL DMS" ):SetTime( MenuTime ) end if not self:IsA2A_LL_DDM() then - MENU_GROUP_COMMAND:New( MenuGroup, "Lat/Lon Degree Dec Min (LL DDM)", A2ACoordinateMenu, self.A2AMenuSystem, self, MenuGroup, RootMenu, "LL DDM" ):SetTime( MenuTime ) + local text="Lat/Lon Degree Dec Min (LL DDM)" + if _SETTINGS.MenuShort then + text="LL DDM" + end + MENU_GROUP_COMMAND:New( MenuGroup, text, A2ACoordinateMenu, self.A2AMenuSystem, self, MenuGroup, RootMenu, "LL DDM" ):SetTime( MenuTime ) end - if self:IsA2A_LL_DDM() then - MENU_GROUP_COMMAND:New( MenuGroup, "LL DDM Accuracy 1", A2ACoordinateMenu, self.MenuLL_DDM_Accuracy, self, MenuGroup, RootMenu, 1 ):SetTime( MenuTime ) - MENU_GROUP_COMMAND:New( MenuGroup, "LL DDM Accuracy 2", A2ACoordinateMenu, self.MenuLL_DDM_Accuracy, self, MenuGroup, RootMenu, 2 ):SetTime( MenuTime ) - MENU_GROUP_COMMAND:New( MenuGroup, "LL DDM Accuracy 3", A2ACoordinateMenu, self.MenuLL_DDM_Accuracy, self, MenuGroup, RootMenu, 3 ):SetTime( MenuTime ) - end + if self:IsA2A_LL_DDM() or self:IsA2A_LL_DMS() then + MENU_GROUP_COMMAND:New( MenuGroup, "LL Accuracy 0", A2ACoordinateMenu, self.MenuLL_DDM_Accuracy, self, MenuGroup, RootMenu, 0 ):SetTime( MenuTime ) + MENU_GROUP_COMMAND:New( MenuGroup, "LL Accuracy 1", A2ACoordinateMenu, self.MenuLL_DDM_Accuracy, self, MenuGroup, RootMenu, 1 ):SetTime( MenuTime ) + MENU_GROUP_COMMAND:New( MenuGroup, "LL Accuracy 2", A2ACoordinateMenu, self.MenuLL_DDM_Accuracy, self, MenuGroup, RootMenu, 2 ):SetTime( MenuTime ) + MENU_GROUP_COMMAND:New( MenuGroup, "LL Accuracy 3", A2ACoordinateMenu, self.MenuLL_DDM_Accuracy, self, MenuGroup, RootMenu, 3 ):SetTime( MenuTime ) + end if not self:IsA2A_BULLS() then - MENU_GROUP_COMMAND:New( MenuGroup, "Bullseye (BULLS)", A2ACoordinateMenu, self.A2AMenuSystem, self, MenuGroup, RootMenu, "BULLS" ):SetTime( MenuTime ) + local text="Bullseye (BULLS)" + if _SETTINGS.MenuShort then + text="Bulls" + end + MENU_GROUP_COMMAND:New( MenuGroup, text, A2ACoordinateMenu, self.A2AMenuSystem, self, MenuGroup, RootMenu, "BULLS" ):SetTime( MenuTime ) end - + if not self:IsA2A_BRAA() then - MENU_GROUP_COMMAND:New( MenuGroup, "Bearing Range Altitude Aspect (BRAA)", A2ACoordinateMenu, self.A2AMenuSystem, self, MenuGroup, RootMenu, "BRAA" ):SetTime( MenuTime ) + local text="Bearing Range Altitude Aspect (BRAA)" + if _SETTINGS.MenuShort then + text="BRAA" + end + MENU_GROUP_COMMAND:New( MenuGroup, text, A2ACoordinateMenu, self.A2AMenuSystem, self, MenuGroup, RootMenu, "BRAA" ):SetTime( MenuTime ) end - + if not self:IsA2A_MGRS() then - MENU_GROUP_COMMAND:New( MenuGroup, "Military Grid (MGRS)", A2ACoordinateMenu, self.A2AMenuSystem, self, MenuGroup, RootMenu, "MGRS" ):SetTime( MenuTime ) + local text="Military Grid (MGRS)" + if _SETTINGS.MenuShort then + text="MGRS" + end + MENU_GROUP_COMMAND:New( MenuGroup, text, A2ACoordinateMenu, self.A2AMenuSystem, self, MenuGroup, RootMenu, "MGRS" ):SetTime( MenuTime ) end if self:IsA2A_MGRS() then @@ -539,19 +621,35 @@ do -- SETTINGS MENU_GROUP_COMMAND:New( MenuGroup, "MGRS Accuracy 3", A2ACoordinateMenu, self.MenuMGRS_Accuracy, self, MenuGroup, RootMenu, 3 ):SetTime( MenuTime ) MENU_GROUP_COMMAND:New( MenuGroup, "MGRS Accuracy 4", A2ACoordinateMenu, self.MenuMGRS_Accuracy, self, MenuGroup, RootMenu, 4 ):SetTime( MenuTime ) MENU_GROUP_COMMAND:New( MenuGroup, "MGRS Accuracy 5", A2ACoordinateMenu, self.MenuMGRS_Accuracy, self, MenuGroup, RootMenu, 5 ):SetTime( MenuTime ) - end - - local MetricsMenu = MENU_GROUP:New( MenuGroup, "Measures and Weights System", SettingsMenu ):SetTime( MenuTime ) - - if self:IsMetric() then - MENU_GROUP_COMMAND:New( MenuGroup, "Imperial (Miles,Feet)", MetricsMenu, self.MenuMWSystem, self, MenuGroup, RootMenu, false ):SetTime( MenuTime ) end - + + local text="Measures and Weights System" + if _SETTINGS.MenuShort then + text="Unit System" + end + local MetricsMenu = MENU_GROUP:New( MenuGroup, text, SettingsMenu ):SetTime( MenuTime ) + + if self:IsMetric() then + local text="Imperial (Miles,Feet)" + if _SETTINGS.MenuShort then + text="Imperial" + end + MENU_GROUP_COMMAND:New( MenuGroup, text, MetricsMenu, self.MenuMWSystem, self, MenuGroup, RootMenu, false ):SetTime( MenuTime ) + end + if self:IsImperial() then - MENU_GROUP_COMMAND:New( MenuGroup, "Metric (Kilometers,Meters)", MetricsMenu, self.MenuMWSystem, self, MenuGroup, RootMenu, true ):SetTime( MenuTime ) - end - - local MessagesMenu = MENU_GROUP:New( MenuGroup, "Messages and Reports", SettingsMenu ):SetTime( MenuTime ) + local text="Metric (Kilometers,Meters)" + if _SETTINGS.MenuShort then + text="Metric" + end + MENU_GROUP_COMMAND:New( MenuGroup, text, MetricsMenu, self.MenuMWSystem, self, MenuGroup, RootMenu, true ):SetTime( MenuTime ) + end + + local text="Messages and Reports" + if _SETTINGS.MenuShort then + text="Messages & Reports" + end + local MessagesMenu = MENU_GROUP:New( MenuGroup, text, SettingsMenu ):SetTime( MenuTime ) local UpdateMessagesMenu = MENU_GROUP:New( MenuGroup, "Update Messages", MessagesMenu ):SetTime( MenuTime ) MENU_GROUP_COMMAND:New( MenuGroup, "Off", UpdateMessagesMenu, self.MenuMessageTimingsSystem, self, MenuGroup, RootMenu, MESSAGE.Type.Update, 0 ):SetTime( MenuTime ) @@ -589,10 +687,10 @@ do -- SETTINGS MENU_GROUP_COMMAND:New( MenuGroup, "1 minute", DetailedReportsMenu, self.MenuMessageTimingsSystem, self, MenuGroup, RootMenu, MESSAGE.Type.DetailedReportsMenu, 60 ):SetTime( MenuTime ) MENU_GROUP_COMMAND:New( MenuGroup, "2 minutes", DetailedReportsMenu, self.MenuMessageTimingsSystem, self, MenuGroup, RootMenu, MESSAGE.Type.DetailedReportsMenu, 120 ):SetTime( MenuTime ) MENU_GROUP_COMMAND:New( MenuGroup, "3 minutes", DetailedReportsMenu, self.MenuMessageTimingsSystem, self, MenuGroup, RootMenu, MESSAGE.Type.DetailedReportsMenu, 180 ):SetTime( MenuTime ) - + SettingsMenu:Remove( MenuTime ) - + return self end @@ -618,8 +716,6 @@ do -- SETTINGS self.ShowPlayerMenu = false end - - --- Updates the menu of the player seated in the PlayerUnit. -- @param #SETTINGS self -- @param Wrapper.Client#CLIENT PlayerUnit @@ -627,136 +723,200 @@ do -- SETTINGS function SETTINGS:SetPlayerMenu( PlayerUnit ) if _SETTINGS.ShowPlayerMenu == true then - + local PlayerGroup = PlayerUnit:GetGroup() local PlayerName = PlayerUnit:GetPlayerName() local PlayerNames = PlayerGroup:GetPlayerNames() - + local PlayerMenu = MENU_GROUP:New( PlayerGroup, 'Settings "' .. PlayerName .. '"' ) - + self.PlayerMenu = PlayerMenu - - local A2GCoordinateMenu = MENU_GROUP:New( PlayerGroup, "A2G Coordinate System", PlayerMenu ) - - if not self:IsA2G_LL_DMS() then - MENU_GROUP_COMMAND:New( PlayerGroup, "Lat/Lon Degree Min Sec (LL DMS)", A2GCoordinateMenu, self.MenuGroupA2GSystem, self, PlayerUnit, PlayerGroup, PlayerName, "LL DMS" ) + + self:I(string.format("Setting menu for player %s", tostring(PlayerName))) + + local submenu = MENU_GROUP:New( PlayerGroup, "LL Accuracy", PlayerMenu ) + MENU_GROUP_COMMAND:New( PlayerGroup, "LL 0 Decimals", submenu, self.MenuGroupLL_DDM_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 0 ) + MENU_GROUP_COMMAND:New( PlayerGroup, "LL 1 Decimal", submenu, self.MenuGroupLL_DDM_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 1 ) + MENU_GROUP_COMMAND:New( PlayerGroup, "LL 2 Decimals", submenu, self.MenuGroupLL_DDM_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 2 ) + MENU_GROUP_COMMAND:New( PlayerGroup, "LL 3 Decimals", submenu, self.MenuGroupLL_DDM_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 3 ) + MENU_GROUP_COMMAND:New( PlayerGroup, "LL 4 Decimals", submenu, self.MenuGroupLL_DDM_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 4 ) + + local submenu = MENU_GROUP:New( PlayerGroup, "MGRS Accuracy", PlayerMenu ) + MENU_GROUP_COMMAND:New( PlayerGroup, "MRGS Accuracy 0", submenu, self.MenuGroupMGRS_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 0 ) + MENU_GROUP_COMMAND:New( PlayerGroup, "MRGS Accuracy 1", submenu, self.MenuGroupMGRS_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 1 ) + MENU_GROUP_COMMAND:New( PlayerGroup, "MRGS Accuracy 2", submenu, self.MenuGroupMGRS_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 2 ) + MENU_GROUP_COMMAND:New( PlayerGroup, "MRGS Accuracy 3", submenu, self.MenuGroupMGRS_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 3 ) + MENU_GROUP_COMMAND:New( PlayerGroup, "MRGS Accuracy 4", submenu, self.MenuGroupMGRS_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 4 ) + MENU_GROUP_COMMAND:New( PlayerGroup, "MRGS Accuracy 5", submenu, self.MenuGroupMGRS_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 5 ) + + ------ + -- A2G Coordinate System + ------ + + local text="A2G Coordinate System" + if _SETTINGS.MenuShort then + text="A2G Coordinates" end - - if not self:IsA2G_LL_DDM() then - MENU_GROUP_COMMAND:New( PlayerGroup, "Lat/Lon Degree Dec Min (LL DDM)", A2GCoordinateMenu, self.MenuGroupA2GSystem, self, PlayerUnit, PlayerGroup, PlayerName, "LL DDM" ) + local A2GCoordinateMenu = MENU_GROUP:New( PlayerGroup, text, PlayerMenu ) + + if not self:IsA2G_LL_DMS() or _SETTINGS.MenuStatic then + local text="Lat/Lon Degree Min Sec (LL DMS)" + if _SETTINGS.MenuShort then + text="A2G LL DMS" + end + MENU_GROUP_COMMAND:New( PlayerGroup, text, A2GCoordinateMenu, self.MenuGroupA2GSystem, self, PlayerUnit, PlayerGroup, PlayerName, "LL DMS" ) end - - if self:IsA2G_LL_DDM() then - MENU_GROUP_COMMAND:New( PlayerGroup, "LL DDM Accuracy 1", A2GCoordinateMenu, self.MenuGroupLL_DDM_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 1 ) - MENU_GROUP_COMMAND:New( PlayerGroup, "LL DDM Accuracy 2", A2GCoordinateMenu, self.MenuGroupLL_DDM_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 2 ) - MENU_GROUP_COMMAND:New( PlayerGroup, "LL DDM Accuracy 3", A2GCoordinateMenu, self.MenuGroupLL_DDM_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 3 ) + + if not self:IsA2G_LL_DDM() or _SETTINGS.MenuStatic then + local text="Lat/Lon Degree Dec Min (LL DDM)" + if _SETTINGS.MenuShort then + text="A2G LL DDM" + end + MENU_GROUP_COMMAND:New( PlayerGroup, text, A2GCoordinateMenu, self.MenuGroupA2GSystem, self, PlayerUnit, PlayerGroup, PlayerName, "LL DDM" ) end - - if not self:IsA2G_BR() then - MENU_GROUP_COMMAND:New( PlayerGroup, "Bearing, Range (BR)", A2GCoordinateMenu, self.MenuGroupA2GSystem, self, PlayerUnit, PlayerGroup, PlayerName, "BR" ) + + if not self:IsA2G_BR() or _SETTINGS.MenuStatic then + local text="Bearing, Range (BR)" + if _SETTINGS.MenuShort then + text="A2G BR" + end + MENU_GROUP_COMMAND:New( PlayerGroup, text, A2GCoordinateMenu, self.MenuGroupA2GSystem, self, PlayerUnit, PlayerGroup, PlayerName, "BR" ) end - - if not self:IsA2G_MGRS() then - MENU_GROUP_COMMAND:New( PlayerGroup, "Military Grid (MGRS)", A2GCoordinateMenu, self.MenuGroupA2GSystem, self, PlayerUnit, PlayerGroup, PlayerName, "MGRS" ) - end - - if self:IsA2G_MGRS() then - MENU_GROUP_COMMAND:New( PlayerGroup, "MGRS Accuracy 1", A2GCoordinateMenu, self.MenuGroupMGRS_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 1 ) - MENU_GROUP_COMMAND:New( PlayerGroup, "MGRS Accuracy 2", A2GCoordinateMenu, self.MenuGroupMGRS_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 2 ) - MENU_GROUP_COMMAND:New( PlayerGroup, "MGRS Accuracy 3", A2GCoordinateMenu, self.MenuGroupMGRS_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 3 ) - MENU_GROUP_COMMAND:New( PlayerGroup, "MGRS Accuracy 4", A2GCoordinateMenu, self.MenuGroupMGRS_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 4 ) - MENU_GROUP_COMMAND:New( PlayerGroup, "MGRS Accuracy 5", A2GCoordinateMenu, self.MenuGroupMGRS_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 5 ) + + if not self:IsA2G_MGRS() or _SETTINGS.MenuStatic then + local text="Military Grid (MGRS)" + if _SETTINGS.MenuShort then + text="A2G MGRS" + end + MENU_GROUP_COMMAND:New( PlayerGroup, text, A2GCoordinateMenu, self.MenuGroupA2GSystem, self, PlayerUnit, PlayerGroup, PlayerName, "MGRS" ) end - - local A2ACoordinateMenu = MENU_GROUP:New( PlayerGroup, "A2A Coordinate System", PlayerMenu ) - - - if not self:IsA2A_LL_DMS() then - MENU_GROUP_COMMAND:New( PlayerGroup, "Lat/Lon Degree Min Sec (LL DMS)", A2GCoordinateMenu, self.MenuGroupA2GSystem, self, PlayerUnit, PlayerGroup, PlayerName, "LL DMS" ) + + ------ + -- A2A Coordinates Menu + ------ + + local text="A2A Coordinate System" + if _SETTINGS.MenuShort then + text="A2A Coordinates" end - - if not self:IsA2A_LL_DDM() then - MENU_GROUP_COMMAND:New( PlayerGroup, "Lat/Lon Degree Dec Min (LL DDM)", A2GCoordinateMenu, self.MenuGroupA2GSystem, self, PlayerUnit, PlayerGroup, PlayerName, "LL DDM" ) + local A2ACoordinateMenu = MENU_GROUP:New( PlayerGroup, text, PlayerMenu ) + + + if not self:IsA2A_LL_DMS() or _SETTINGS.MenuStatic then + local text="Lat/Lon Degree Min Sec (LL DMS)" + if _SETTINGS.MenuShort then + text="A2A LL DMS" + end + MENU_GROUP_COMMAND:New( PlayerGroup, text, A2ACoordinateMenu, self.MenuGroupA2GSystem, self, PlayerUnit, PlayerGroup, PlayerName, "LL DMS" ) end - - if self:IsA2A_LL_DDM() then - MENU_GROUP_COMMAND:New( PlayerGroup, "LL DDM Accuracy 1", A2GCoordinateMenu, self.MenuGroupLL_DDM_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 1 ) - MENU_GROUP_COMMAND:New( PlayerGroup, "LL DDM Accuracy 2", A2GCoordinateMenu, self.MenuGroupLL_DDM_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 2 ) - MENU_GROUP_COMMAND:New( PlayerGroup, "LL DDM Accuracy 3", A2GCoordinateMenu, self.MenuGroupLL_DDM_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 3 ) + + if not self:IsA2A_LL_DDM() or _SETTINGS.MenuStatic then + local text="Lat/Lon Degree Dec Min (LL DDM)" + if _SETTINGS.MenuShort then + text="A2A LL DDM" + end + MENU_GROUP_COMMAND:New( PlayerGroup, text, A2ACoordinateMenu, self.MenuGroupA2ASystem, self, PlayerUnit, PlayerGroup, PlayerName, "LL DDM" ) end - - if not self:IsA2A_BULLS() then - MENU_GROUP_COMMAND:New( PlayerGroup, "Bullseye (BULLS)", A2ACoordinateMenu, self.MenuGroupA2ASystem, self, PlayerUnit, PlayerGroup, PlayerName, "BULLS" ) + + if not self:IsA2A_BULLS() or _SETTINGS.MenuStatic then + local text="Bullseye (BULLS)" + if _SETTINGS.MenuShort then + text="A2A BULLS" + end + MENU_GROUP_COMMAND:New( PlayerGroup, text, A2ACoordinateMenu, self.MenuGroupA2ASystem, self, PlayerUnit, PlayerGroup, PlayerName, "BULLS" ) end - - if not self:IsA2A_BRAA() then - MENU_GROUP_COMMAND:New( PlayerGroup, "Bearing Range Altitude Aspect (BRAA)", A2ACoordinateMenu, self.MenuGroupA2ASystem, self, PlayerUnit, PlayerGroup, PlayerName, "BRAA" ) + + if not self:IsA2A_BRAA() or _SETTINGS.MenuStatic then + local text="Bearing Range Altitude Aspect (BRAA)" + if _SETTINGS.MenuShort then + text="A2A BRAA" + end + MENU_GROUP_COMMAND:New( PlayerGroup, text, A2ACoordinateMenu, self.MenuGroupA2ASystem, self, PlayerUnit, PlayerGroup, PlayerName, "BRAA" ) end - - if not self:IsA2A_MGRS() then - MENU_GROUP_COMMAND:New( PlayerGroup, "Military Grid (MGRS)", A2ACoordinateMenu, self.MenuGroupA2ASystem, self, PlayerUnit, PlayerGroup, PlayerName, "MGRS" ) + + if not self:IsA2A_MGRS() or _SETTINGS.MenuStatic then + local text="Military Grid (MGRS)" + if _SETTINGS.MenuShort then + text="A2A MGRS" + end + MENU_GROUP_COMMAND:New( PlayerGroup, text, A2ACoordinateMenu, self.MenuGroupA2ASystem, self, PlayerUnit, PlayerGroup, PlayerName, "MGRS" ) end - - if self:IsA2A_MGRS() then - MENU_GROUP_COMMAND:New( PlayerGroup, "Military Grid (MGRS) Accuracy 1", A2ACoordinateMenu, self.MenuGroupMGRS_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 1 ) - MENU_GROUP_COMMAND:New( PlayerGroup, "Military Grid (MGRS) Accuracy 2", A2ACoordinateMenu, self.MenuGroupMGRS_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 2 ) - MENU_GROUP_COMMAND:New( PlayerGroup, "Military Grid (MGRS) Accuracy 3", A2ACoordinateMenu, self.MenuGroupMGRS_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 3 ) - MENU_GROUP_COMMAND:New( PlayerGroup, "Military Grid (MGRS) Accuracy 4", A2ACoordinateMenu, self.MenuGroupMGRS_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 4 ) - MENU_GROUP_COMMAND:New( PlayerGroup, "Military Grid (MGRS) Accuracy 5", A2ACoordinateMenu, self.MenuGroupMGRS_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 5 ) - end - - local MetricsMenu = MENU_GROUP:New( PlayerGroup, "Measures and Weights System", PlayerMenu ) - - if self:IsMetric() then - MENU_GROUP_COMMAND:New( PlayerGroup, "Imperial (Miles,Feet)", MetricsMenu, self.MenuGroupMWSystem, self, PlayerUnit, PlayerGroup, PlayerName, false ) + + --- + -- Unit system + --- + + local text="Measures and Weights System" + if _SETTINGS.MenuShort then + text="Unit System" end - - if self:IsImperial() then - MENU_GROUP_COMMAND:New( PlayerGroup, "Metric (Kilometers,Meters)", MetricsMenu, self.MenuGroupMWSystem, self, PlayerUnit, PlayerGroup, PlayerName, true ) - end - - - local MessagesMenu = MENU_GROUP:New( PlayerGroup, "Messages and Reports", PlayerMenu ) - + local MetricsMenu = MENU_GROUP:New( PlayerGroup, text, PlayerMenu ) + + if self:IsMetric() or _SETTINGS.MenuStatic then + local text="Imperial (Miles,Feet)" + if _SETTINGS.MenuShort then + text="Imperial" + end + MENU_GROUP_COMMAND:New( PlayerGroup, text, MetricsMenu, self.MenuGroupMWSystem, self, PlayerUnit, PlayerGroup, PlayerName, false ) + end + + if self:IsImperial() or _SETTINGS.MenuStatic then + local text="Metric (Kilometers,Meters)" + if _SETTINGS.MenuShort then + text="Metric" + end + MENU_GROUP_COMMAND:New( PlayerGroup, text, MetricsMenu, self.MenuGroupMWSystem, self, PlayerUnit, PlayerGroup, PlayerName, true ) + end + + --- + -- Messages and Reports + --- + + local text="Messages and Reports" + if _SETTINGS.MenuShort then + text="Messages & Reports" + end + local MessagesMenu = MENU_GROUP:New( PlayerGroup, text, PlayerMenu ) + local UpdateMessagesMenu = MENU_GROUP:New( PlayerGroup, "Update Messages", MessagesMenu ) - MENU_GROUP_COMMAND:New( PlayerGroup, "Off", UpdateMessagesMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Update, 0 ) - MENU_GROUP_COMMAND:New( PlayerGroup, "5 seconds", UpdateMessagesMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Update, 5 ) - MENU_GROUP_COMMAND:New( PlayerGroup, "10 seconds", UpdateMessagesMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Update, 10 ) - MENU_GROUP_COMMAND:New( PlayerGroup, "15 seconds", UpdateMessagesMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Update, 15 ) - MENU_GROUP_COMMAND:New( PlayerGroup, "30 seconds", UpdateMessagesMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Update, 30 ) - MENU_GROUP_COMMAND:New( PlayerGroup, "1 minute", UpdateMessagesMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Update, 60 ) - - local InformationMessagesMenu = MENU_GROUP:New( PlayerGroup, "Information Messages", MessagesMenu ) - MENU_GROUP_COMMAND:New( PlayerGroup, "5 seconds", InformationMessagesMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Information, 5 ) - MENU_GROUP_COMMAND:New( PlayerGroup, "10 seconds", InformationMessagesMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Information, 10 ) - MENU_GROUP_COMMAND:New( PlayerGroup, "15 seconds", InformationMessagesMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Information, 15 ) - MENU_GROUP_COMMAND:New( PlayerGroup, "30 seconds", InformationMessagesMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Information, 30 ) - MENU_GROUP_COMMAND:New( PlayerGroup, "1 minute", InformationMessagesMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Information, 60 ) - MENU_GROUP_COMMAND:New( PlayerGroup, "2 minutes", InformationMessagesMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Information, 120 ) - + MENU_GROUP_COMMAND:New( PlayerGroup, "Updates Off", UpdateMessagesMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Update, 0 ) + MENU_GROUP_COMMAND:New( PlayerGroup, "Updates 5 sec", UpdateMessagesMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Update, 5 ) + MENU_GROUP_COMMAND:New( PlayerGroup, "Updates 10 sec", UpdateMessagesMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Update, 10 ) + MENU_GROUP_COMMAND:New( PlayerGroup, "Updates 15 sec", UpdateMessagesMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Update, 15 ) + MENU_GROUP_COMMAND:New( PlayerGroup, "Updates 30 sec", UpdateMessagesMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Update, 30 ) + MENU_GROUP_COMMAND:New( PlayerGroup, "Updates 1 min", UpdateMessagesMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Update, 60 ) + + local InformationMessagesMenu = MENU_GROUP:New( PlayerGroup, "Info Messages", MessagesMenu ) + MENU_GROUP_COMMAND:New( PlayerGroup, "Info 5 sec", InformationMessagesMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Information, 5 ) + MENU_GROUP_COMMAND:New( PlayerGroup, "Info 10 sec", InformationMessagesMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Information, 10 ) + MENU_GROUP_COMMAND:New( PlayerGroup, "Info 15 sec", InformationMessagesMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Information, 15 ) + MENU_GROUP_COMMAND:New( PlayerGroup, "Info 30 sec", InformationMessagesMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Information, 30 ) + MENU_GROUP_COMMAND:New( PlayerGroup, "Info 1 min", InformationMessagesMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Information, 60 ) + MENU_GROUP_COMMAND:New( PlayerGroup, "Info 2 min", InformationMessagesMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Information, 120 ) + local BriefingReportsMenu = MENU_GROUP:New( PlayerGroup, "Briefing Reports", MessagesMenu ) - MENU_GROUP_COMMAND:New( PlayerGroup, "15 seconds", BriefingReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Briefing, 15 ) - MENU_GROUP_COMMAND:New( PlayerGroup, "30 seconds", BriefingReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Briefing, 30 ) - MENU_GROUP_COMMAND:New( PlayerGroup, "1 minute", BriefingReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Briefing, 60 ) - MENU_GROUP_COMMAND:New( PlayerGroup, "2 minutes", BriefingReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Briefing, 120 ) - MENU_GROUP_COMMAND:New( PlayerGroup, "3 minutes", BriefingReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Briefing, 180 ) - + MENU_GROUP_COMMAND:New( PlayerGroup, "Brief 15 sec", BriefingReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Briefing, 15 ) + MENU_GROUP_COMMAND:New( PlayerGroup, "Brief 30 sec", BriefingReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Briefing, 30 ) + MENU_GROUP_COMMAND:New( PlayerGroup, "Brief 1 min", BriefingReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Briefing, 60 ) + MENU_GROUP_COMMAND:New( PlayerGroup, "Brief 2 min", BriefingReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Briefing, 120 ) + MENU_GROUP_COMMAND:New( PlayerGroup, "Brief 3 min", BriefingReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Briefing, 180 ) + local OverviewReportsMenu = MENU_GROUP:New( PlayerGroup, "Overview Reports", MessagesMenu ) - MENU_GROUP_COMMAND:New( PlayerGroup, "15 seconds", OverviewReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Overview, 15 ) - MENU_GROUP_COMMAND:New( PlayerGroup, "30 seconds", OverviewReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Overview, 30 ) - MENU_GROUP_COMMAND:New( PlayerGroup, "1 minute", OverviewReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Overview, 60 ) - MENU_GROUP_COMMAND:New( PlayerGroup, "2 minutes", OverviewReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Overview, 120 ) - MENU_GROUP_COMMAND:New( PlayerGroup, "3 minutes", OverviewReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Overview, 180 ) - + MENU_GROUP_COMMAND:New( PlayerGroup, "Overview 15 sec", OverviewReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Overview, 15 ) + MENU_GROUP_COMMAND:New( PlayerGroup, "Overview 30 sec", OverviewReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Overview, 30 ) + MENU_GROUP_COMMAND:New( PlayerGroup, "Overview 1 min", OverviewReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Overview, 60 ) + MENU_GROUP_COMMAND:New( PlayerGroup, "Overview 2 min", OverviewReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Overview, 120 ) + MENU_GROUP_COMMAND:New( PlayerGroup, "Overview 3 min", OverviewReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Overview, 180 ) + local DetailedReportsMenu = MENU_GROUP:New( PlayerGroup, "Detailed Reports", MessagesMenu ) - MENU_GROUP_COMMAND:New( PlayerGroup, "15 seconds", DetailedReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.DetailedReportsMenu, 15 ) - MENU_GROUP_COMMAND:New( PlayerGroup, "30 seconds", DetailedReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.DetailedReportsMenu, 30 ) - MENU_GROUP_COMMAND:New( PlayerGroup, "1 minute", DetailedReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.DetailedReportsMenu, 60 ) - MENU_GROUP_COMMAND:New( PlayerGroup, "2 minutes", DetailedReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.DetailedReportsMenu, 120 ) - MENU_GROUP_COMMAND:New( PlayerGroup, "3 minutes", DetailedReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.DetailedReportsMenu, 180 ) - - end - + MENU_GROUP_COMMAND:New( PlayerGroup, "Detailed 15 sec", DetailedReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.DetailedReportsMenu, 15 ) + MENU_GROUP_COMMAND:New( PlayerGroup, "Detailed 30 sec", DetailedReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.DetailedReportsMenu, 30 ) + MENU_GROUP_COMMAND:New( PlayerGroup, "Detailed 1 min", DetailedReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.DetailedReportsMenu, 60 ) + MENU_GROUP_COMMAND:New( PlayerGroup, "Detailed 2 min", DetailedReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.DetailedReportsMenu, 120 ) + MENU_GROUP_COMMAND:New( PlayerGroup, "Detailed 3 min", DetailedReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.DetailedReportsMenu, 180 ) + + end + return self end @@ -770,7 +930,7 @@ do -- SETTINGS self.PlayerMenu:Remove() self.PlayerMenu = nil end - + return self end @@ -822,40 +982,50 @@ do -- SETTINGS BASE:E( {self, PlayerUnit:GetName(), A2GSystem} ) self.A2GSystem = A2GSystem MESSAGE:New( string.format( "Settings: A2G format set to %s for player %s.", A2GSystem, PlayerName ), 5 ):ToGroup( PlayerGroup ) - self:RemovePlayerMenu(PlayerUnit) - self:SetPlayerMenu(PlayerUnit) + if _SETTINGS.MenuStatic==false then + self:RemovePlayerMenu(PlayerUnit) + self:SetPlayerMenu(PlayerUnit) + end end - + --- @param #SETTINGS self function SETTINGS:MenuGroupA2ASystem( PlayerUnit, PlayerGroup, PlayerName, A2ASystem ) self.A2ASystem = A2ASystem MESSAGE:New( string.format( "Settings: A2A format set to %s for player %s.", A2ASystem, PlayerName ), 5 ):ToGroup( PlayerGroup ) - self:RemovePlayerMenu(PlayerUnit) - self:SetPlayerMenu(PlayerUnit) + if _SETTINGS.MenuStatic==false then + self:RemovePlayerMenu(PlayerUnit) + self:SetPlayerMenu(PlayerUnit) + end end - + --- @param #SETTINGS self function SETTINGS:MenuGroupLL_DDM_AccuracySystem( PlayerUnit, PlayerGroup, PlayerName, LL_Accuracy ) self.LL_Accuracy = LL_Accuracy - MESSAGE:New( string.format( "Settings: A2G LL format accuracy set to %d for player %s.", LL_Accuracy, PlayerName ), 5 ):ToGroup( PlayerGroup ) - self:RemovePlayerMenu(PlayerUnit) - self:SetPlayerMenu(PlayerUnit) + MESSAGE:New( string.format( "Settings: LL format accuracy set to %d decimal places for player %s.", LL_Accuracy, PlayerName ), 5 ):ToGroup( PlayerGroup ) + if _SETTINGS.MenuStatic==false then + self:RemovePlayerMenu(PlayerUnit) + self:SetPlayerMenu(PlayerUnit) + end end - + --- @param #SETTINGS self function SETTINGS:MenuGroupMGRS_AccuracySystem( PlayerUnit, PlayerGroup, PlayerName, MGRS_Accuracy ) self.MGRS_Accuracy = MGRS_Accuracy - MESSAGE:New( string.format( "Settings: A2G MGRS format accuracy set to %d for player %s.", MGRS_Accuracy, PlayerName ), 5 ):ToGroup( PlayerGroup ) - self:RemovePlayerMenu(PlayerUnit) - self:SetPlayerMenu(PlayerUnit) + MESSAGE:New( string.format( "Settings: MGRS format accuracy set to %d for player %s.", MGRS_Accuracy, PlayerName ), 5 ):ToGroup( PlayerGroup ) + if _SETTINGS.MenuStatic==false then + self:RemovePlayerMenu(PlayerUnit) + self:SetPlayerMenu(PlayerUnit) + end end --- @param #SETTINGS self function SETTINGS:MenuGroupMWSystem( PlayerUnit, PlayerGroup, PlayerName, MW ) self.Metric = MW MESSAGE:New( string.format( "Settings: Measurement format set to %s for player %s.", MW and "Metric" or "Imperial", PlayerName ), 5 ):ToGroup( PlayerGroup ) - self:RemovePlayerMenu(PlayerUnit) - self:SetPlayerMenu(PlayerUnit) + if _SETTINGS.MenuStatic==false then + self:RemovePlayerMenu(PlayerUnit) + self:SetPlayerMenu(PlayerUnit) + end end --- @param #SETTINGS self @@ -863,50 +1033,48 @@ do -- SETTINGS self:SetMessageTime( MessageType, MessageTime ) MESSAGE:New( string.format( "Settings: Default message time set for %s to %d.", MessageType, MessageTime ), 5 ):ToGroup( PlayerGroup ) end - + end - + --- Configures the era of the mission to be WWII. -- @param #SETTINGS self -- @return #SETTINGS self function SETTINGS:SetEraWWII() - + self.Era = SETTINGS.__Enum.Era.WWII - + end - + --- Configures the era of the mission to be Korea. -- @param #SETTINGS self -- @return #SETTINGS self function SETTINGS:SetEraKorea() - + self.Era = SETTINGS.__Enum.Era.Korea - + end - - + + --- Configures the era of the mission to be Cold war. -- @param #SETTINGS self -- @return #SETTINGS self function SETTINGS:SetEraCold() - + self.Era = SETTINGS.__Enum.Era.Cold - + end - + --- Configures the era of the mission to be Modern war. -- @param #SETTINGS self -- @return #SETTINGS self function SETTINGS:SetEraModern() - + self.Era = SETTINGS.__Enum.Era.Modern - + end - - - + + + end - - diff --git a/Moose Development/Moose/DCS.lua b/Moose Development/Moose/DCS.lua index df37c1c50..206165bd3 100644 --- a/Moose Development/Moose/DCS.lua +++ b/Moose Development/Moose/DCS.lua @@ -47,9 +47,13 @@ do -- world -- @field S_EVENT_PLAYER_COMMENT -- @field S_EVENT_SHOOTING_START [https://wiki.hoggitworld.com/view/DCS_event_shooting_start](https://wiki.hoggitworld.com/view/DCS_event_shooting_start) -- @field S_EVENT_SHOOTING_END [https://wiki.hoggitworld.com/view/DCS_event_shooting_end](https://wiki.hoggitworld.com/view/DCS_event_shooting_end) - -- @field S_EVENT_MARK ADDED [https://wiki.hoggitworld.com/view/DCS_event_mark_added](https://wiki.hoggitworld.com/view/DCS_event_mark_added) - -- @field S_EVENT_MARK CHANGE [https://wiki.hoggitworld.com/view/DCS_event_mark_change](https://wiki.hoggitworld.com/view/DCS_event_mark_change) - -- @field S_EVENT_MARK REMOVE [https://wiki.hoggitworld.com/view/DCS_event_mark_remove](https://wiki.hoggitworld.com/view/DCS_event_mark_remove) + -- @field S_EVENT_MARK ADDED [https://wiki.hoggitworld.com/view/DCS_event_mark_added](https://wiki.hoggitworld.com/view/DCS_event_mark_added) DCS>=2.5.1 + -- @field S_EVENT_MARK CHANGE [https://wiki.hoggitworld.com/view/DCS_event_mark_change](https://wiki.hoggitworld.com/view/DCS_event_mark_change) DCS>=2.5.1 + -- @field S_EVENT_MARK REMOVE [https://wiki.hoggitworld.com/view/DCS_event_mark_remove](https://wiki.hoggitworld.com/view/DCS_event_mark_remove) DCS>=2.5.1 + -- @field S_EVENT_KILL [https://wiki.hoggitworld.com/view/DCS_event_kill](https://wiki.hoggitworld.com/view/DCS_event_kill) DCS>=2.5.6 + -- @field S_EVENT_SCORE [https://wiki.hoggitworld.com/view/DCS_event_score](https://wiki.hoggitworld.com/view/DCS_event_score) DCS>=2.5.6 + -- @field S_EVENT_UNIT_LOST [https://wiki.hoggitworld.com/view/DCS_event_unit_lost](https://wiki.hoggitworld.com/view/DCS_event_unit_lost) DCS>=2.5.6 + -- @field S_EVENT_LANDING_AFTER_EJECTION [https://wiki.hoggitworld.com/view/DCS_event_landing_after_ejection](https://wiki.hoggitworld.com/view/DCS_event_landing_after_ejection) DCS>=2.5.6 -- @field S_EVENT_MAX --- The birthplace enumerator is used to define where an aircraft or helicopter has spawned in association with birth events. @@ -326,9 +330,27 @@ end -- coalition do -- Types --- @type Desc - -- @field #TypeName typeName type name - -- @field #string displayName localized display name - -- @field #table attributes object type attributes + -- @field #number speedMax0 Max speed in meters/second at zero altitude. + -- @field #number massEmpty Empty mass in kg. + -- @field #number tankerType Type of refueling system: 0=boom, 1=probe. + -- @field #number range Range in km(?). + -- @field #table box Bounding box. + -- @field #number Hmax Max height in meters. + -- @field #number Kmax ? + -- @field #number speedMax10K Max speed in meters/second at 10k altitude. + -- @field #number NyMin ? + -- @field #number NyMax ? + -- @field #number fuelMassMax Max fuel mass in kg. + -- @field #number speedMax10K Max speed in meters/second. + -- @field #number massMax Max mass of unit. + -- @field #number RCS ? + -- @field #number life Life points. + -- @field #number VyMax Max vertical velocity in m/s. + -- @field #number Kab ? + -- @field #table attributes Table of attributes. + -- @field #TypeName typeName Type Name. + -- @field #string displayName Localized display name. + -- @field #number category Unit category. --- A distance type -- @type Distance diff --git a/Moose Development/Moose/Ops/ATIS.lua b/Moose Development/Moose/Ops/ATIS.lua index 0c34562c6..db2fa22a9 100644 --- a/Moose Development/Moose/Ops/ATIS.lua +++ b/Moose Development/Moose/Ops/ATIS.lua @@ -531,7 +531,7 @@ _ATIS={} --- ATIS class version. -- @field #string version -ATIS.version="0.7.0" +ATIS.version="0.7.1" ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- TODO list @@ -1230,13 +1230,22 @@ function ATIS:onafterBroadcast(From, Event, To) if self.windtrue then magvar=0 end + windFrom=windFrom-magvar + + -- Correct negative values. + if windFrom<0 then + windFrom=windFrom+360 + end - local WINDFROM=string.format("%03d", windFrom-magvar) + local WINDFROM=string.format("%03d", windFrom) local WINDSPEED=string.format("%d", UTILS.MpsToKnots(windSpeed)) - + + -- Report North as 0. if WINDFROM=="000" then WINDFROM="360" end + + env.info(string.format("FF WINDFROM = %s", tostring(WINDFROM))) if self.metric then WINDSPEED=string.format("%d", windSpeed) diff --git a/Moose Development/Moose/Ops/Airboss.lua b/Moose Development/Moose/Ops/Airboss.lua index 83502fa80..d604d7441 100644 --- a/Moose Development/Moose/Ops/Airboss.lua +++ b/Moose Development/Moose/Ops/Airboss.lua @@ -1691,7 +1691,7 @@ AIRBOSS.MenuF10Root=nil --- Airboss class version. -- @field #string version -AIRBOSS.version="1.1.1" +AIRBOSS.version="1.1.3" ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- TODO list @@ -1880,6 +1880,9 @@ function AIRBOSS:New(carriername, alias) -- Default recovery case. This sets self.defaultcase and self.case. Default Case I. self:SetRecoveryCase() + -- Set time the turn starts before the window opens. + self:SetRecoveryTurnTime() + -- Set holding offset to 0 degrees. This set self.defaultoffset and self.holdingoffset. self:SetHoldingOffsetAngle() @@ -2433,6 +2436,15 @@ function AIRBOSS:AddRecoveryWindow(starttime, stoptime, case, holdingoffset, tur -- Absolute mission time in seconds. local Tnow=timer.getAbsTime() + if starttime and type(starttime)=="number" then + starttime=UTILS.SecondsToClock(Tnow+starttime) + end + + if stoptime and type(stoptime)=="number" then + stoptime=UTILS.SecondsToClock(Tnow+stoptime) + end + + -- Input or now. starttime=starttime or UTILS.SecondsToClock(Tnow) @@ -2598,6 +2610,15 @@ function AIRBOSS:DeleteRecoveryWindow(window, delay) end end +--- Set time before carrier turns and recovery window opens. +-- @param #AIRBOSS self +-- @param #number interval Time interval in seconds. Default 600 sec. +-- @return #AIRBOSS self +function AIRBOSS:SetRecoveryTurnTime(interval) + self.dTturn=interval or 600 + return self +end + --- Set time interval for updating queues and other stuff. -- @param #AIRBOSS self -- @param #number interval Time interval in seconds. Default 30 sec. @@ -3226,6 +3247,27 @@ function AIRBOSS:SetDebugModeOFF() return self end +--- Get next time the carrier will start recovering aircraft. +-- @param #AIRBOSS self +-- @param #boolean InSeconds If true, abs. mission time seconds is returned. Default is a clock #string. +-- @return #string Clock start (or start time in abs. seconds). +-- @return #string Clock stop (or stop time in abs. seconds). +function AIRBOSS:GetNextRecoveryTime(InSeconds) + if self.recoverywindow then + if InSeconds then + return self.recoverywindow.START, self.recoverywindow.STOP + else + return UTILS.SecondsToClock(self.recoverywindow.START), UTILS.SecondsToClock(self.recoverywindow.STOP) + end + else + if InSeconds then + return -1, -1 + else + return "?", "?" + end + end +end + --- Check if carrier is recovering aircraft. -- @param #AIRBOSS self -- @return #boolean If true, time slot for recovery is open. @@ -3782,7 +3824,7 @@ function AIRBOSS:_CheckRecoveryTimes() self:RecoveryCase(nextwindow.CASE, nextwindow.OFFSET) -- Check if time is less than 5 minutes. - if nextwindow.WIND and nextwindow.START-time<5*60 and not self.turnintowind then + if nextwindow.WIND and nextwindow.START-time 5° different from the current heading. local hdg=self:GetHeading() @@ -3805,7 +3847,7 @@ function AIRBOSS:_CheckRecoveryTimes() self:T(self.lid..string.format("Heading=%03d°, Wind=%03d° %.1f kts, Delta=%03d° ==> U-turn=%s", hdg, wind,UTILS.MpsToKnots(vwind), delta, tostring(uturn))) -- Time into the wind 1 day or if longer recovery time + the 5 min early. - local t=math.max(nextwindow.STOP-nextwindow.START+300, 60*60*24) + local t=math.max(nextwindow.STOP-nextwindow.START+self.dTturn, 60*60*24) -- Recovery wind on deck in knots. local v=UTILS.KnotsToMps(nextwindow.SPEED) @@ -5964,7 +6006,6 @@ function AIRBOSS:_ScanCarrierZone() end end - -- Find new flights that are inside CCA. for groupname,_group in pairs(insideCCA) do local group=_group --Wrapper.Group#GROUP @@ -6070,7 +6111,6 @@ function AIRBOSS:_ScanCarrierZone() end - -- Find flights that are not in CCA. local remove={} for _,_flight in pairs(self.flights) do @@ -10769,53 +10809,6 @@ function AIRBOSS:_GetZoneCorridor(case, l) local zone=ZONE_POLYGON_BASE:New("CASE II/III Approach Corridor", p) return zone - - --[[ - -- OLD - - -- Angle between radial and offset in rad. - local alpha=math.rad(self.holdingoffset) - - -- Some math... - local y1=d-w2 - local x1=y1*math.tan(alpha) - local y2=d+w2 - local x2=y2*math.tan(alpha) - local b=w2*(1/math.cos(alpha)-1) - - -- This is what we need. - local P=x1+b - local Q=x2-b - - -- Debug output. - self:T3(string.format("FF case %d radial = %d", case, radial)) - self:T3(string.format("FF case %d offset = %d", case, offset)) - self:T3(string.format("FF w = %.1f NM", w)) - self:T3(string.format("FF l = %.1f NM", l)) - self:T3(string.format("FF d = %.1f NM", d)) - self:T3(string.format("FF y1 = %.1f NM", y1)) - self:T3(string.format("FF x1 = %.1f NM", x1)) - self:T3(string.format("FF y2 = %.1f NM", y2)) - self:T3(string.format("FF x2 = %.1f NM", x2)) - self:T3(string.format("FF b = %.1f NM", b)) - self:T3(string.format("FF P = %.1f NM", P)) - self:T3(string.format("FF Q = %.1f NM", Q)) - - -- Complicated case with an angle. - c[2]=c[1]:Translate( UTILS.NMToMeters(w2), radial-90) -- 1 Right of carrier. - c[3]=c[2]:Translate( UTILS.NMToMeters(d+dx+w2), radial) -- 13 "south" @ 1 right - c[4]=c[3]:Translate( UTILS.NMToMeters(Q), radial+90) -- - c[5]=c[4]:Translate( UTILS.NMToMeters(l), offset) - c[6]=c[5]:Translate( UTILS.NMToMeters(w), offset+90) -- Back wall (angled) - c[9]=c[1]:Translate( UTILS.NMToMeters(w2), radial+90) -- 1 left of carrier. - c[8]=c[9]:Translate( UTILS.NMToMeters(d+dx-w2), radial) -- 1 left and 11 behind of carrier. - c[7]=c[8]:Translate( UTILS.NMToMeters(P), radial+90) - - -- Translate these points a bit for a smoother turn. - --c[4]=c[4]:Translate(UTILS.NMToMeters(2), offset) - --c[7]=c[7]:Translate(UTILS.NMToMeters(2), offset) - ]] - end @@ -11314,20 +11307,6 @@ function AIRBOSS:_Lineup(unit, runway) --- local lineup=math.deg(math.atan2(z, x)) - --[[ - -- Position of the aircraft in the new coordinate system. - local a={x=x, y=0, z=z} - - -- Stern position in the new coordinate system, which is simply the origin. - local b={x=0, y=0, z=0} - - -- Vector from plane to ref point on the boat. - local c=UTILS.VecSubstract(a, b) - - -- Current line up and error wrt to final heading of the runway. - local lineup=math.deg(math.atan2(c.z, c.x)) - ]] - return lineup end @@ -11946,9 +11925,13 @@ function AIRBOSS:_LSOgrade(playerData) local nS=count(G, '%(') local nN=N-nS-nL + -- Groove time 16-18 sec for a unicorn. + local Tgroove=playerData.Tgroove + local TgrooveUnicorn=Tgroove and (Tgroove>=16.0 and Tgroove<=18.0) or false + local grade local points - if N==0 then + if N==0 and TgrooveUnicorn then -- No deviations, should be REALLY RARE! grade="_OK_" points=5.0 @@ -12019,7 +12002,7 @@ function AIRBOSS:_LSOgrade(playerData) ----------------- grade="OWO" points=2.0 - if G=="Unicorn" then + if N==0 then G="n/a" end elseif playerData.waveoff then @@ -13511,63 +13494,6 @@ function AIRBOSS:_InitWaypoints() return self end ---[[ - ---- Patrol carrier. --- @param #AIRBOSS self --- @param #number n Current waypoint. --- @return #AIRBOSS self -function AIRBOSS:_PatrolRoute(n) - - -- Get carrier group. - local CarrierGroup=self.carrier:GetGroup() - - -- Waypoints of group. - local Waypoints = CarrierGroup:GetTemplateRoutePoints() - - -- Loop over waypoints. - for n=1,#Waypoints do - - -- Passing waypoint taskfunction - local TaskPassingWP=CarrierGroup:TaskFunction("AIRBOSS._PassingWaypoint", self, n, #Waypoints) - - -- Call task function when carrier arrives at waypoint. - CarrierGroup:SetTaskWaypoint(Waypoints[n], TaskPassingWP) - end - - -- Init array. - self.waypoints={} - - -- Set waypoint table. - for i,point in ipairs(Waypoints) do - - -- Coordinate of the waypoint - local coord=COORDINATE:New(point.x, point.alt, point.y) - - -- Set velocity of the coordinate. - coord:SetVelocity(point.speed) - - -- Add to table. - table.insert(self.waypoints, coord) - - -- Debug info. - if self.Debug then - coord:MarkToAll(string.format("Carrier Waypoint %d, Speed=%.1f knots", i, UTILS.MpsToKnots(point.speed))) - end - - end - - -- Current waypoint is 1. - self.currentwp=n or 1 - - -- Route carrier group. - CarrierGroup:Route(Waypoints) - - return self -end - -]] - --- Patrol carrier. -- @param #AIRBOSS self -- @param #number n Next waypoint number. diff --git a/Moose Development/Moose/Utilities/Enums.lua b/Moose Development/Moose/Utilities/Enums.lua index 91c814937..f47e66b94 100644 --- a/Moose Development/Moose/Utilities/Enums.lua +++ b/Moose Development/Moose/Utilities/Enums.lua @@ -1,49 +1,163 @@ --- **Utilities** Enumerators. -- --- See the [Simulator Scripting Engine Documentation](https://wiki.hoggitworld.com/view/Simulator_Scripting_Engine_Documentation) on Hoggit for further explanation and examples. +-- An enumerator is a variable that holds a constant value. Enumerators are very useful because they make the code easier to read and to change in general. -- --- @module DCS +-- For example, instead of using the same value at multiple different places in your code, you should use a variable set to that value. +-- If, for whatever reason, the value needs to be changed, you only have to change the variable once and do not have to search through you code and reset +-- every value by hand. +-- +-- Another big advantage is that the LDT intellisense "knows" the enumerators. So you can use the autocompletion feature and do not have to keep all the +-- values in your head or look them up in the docs. +-- +-- DCS itself provides a lot of enumerators for various things. See [Enumerators](https://wiki.hoggitworld.com/view/Category:Enumerators) on Hoggit. +-- +-- Other Moose classe also have enumerators. For example, the AIRBASE class has enumerators for airbase names. +-- +-- @module ENUMS -- @image MOOSE.JPG +--- [DCS Enum world](https://wiki.hoggitworld.com/view/DCS_enum_world) +-- @type ENUMS +--- Because ENUMS are just better practice. +-- +-- The ENUMS class adds some handy variables, which help you to make your code better and more general. +-- +-- @field #ENUMS ENUMS = {} +--- Rules of Engagement. +-- @type ENUMS.ROE +-- @field #number WeaponFree AI will engage any enemy group it detects. Target prioritization is based based on the threat of the target. +-- @field #number OpenFireWeaponFree AI will engage any enemy group it detects, but will prioritize targets specified in the groups tasking. +-- @field #number OpenFire AI will engage only targets specified in its taskings. +-- @field #number ReturnFire AI will only engage threats that shoot first. +-- @field #number WeaponHold AI will hold fire under all circumstances. ENUMS.ROE = { - HoldFire = 1, - ReturnFire = 2, - OpenFire = 3, - WeaponFree = 4 + WeaponFree=0, + OpenFireWeaponFree=1, + OpenFire=2, + ReturnFire=3, + WeaponHold=4, } - + +--- Reaction On Threat. +-- @type ENUMS.ROT +-- @field #number NoReaction No defensive actions will take place to counter threats. +-- @field #number PassiveDefense AI will use jammers and other countermeasures in an attempt to defeat the threat. AI will not attempt a maneuver to defeat a threat. +-- @field #number EvadeFire AI will react by performing defensive maneuvers against incoming threats. AI will also use passive defense. +-- @field #number BypassAndEscape AI will attempt to avoid enemy threat zones all together. This includes attempting to fly above or around threats. +-- @field #number AllowAbortMission If a threat is deemed severe enough the AI will abort its mission and return to base. ENUMS.ROT = { - NoReaction = 1, - PassiveDefense = 2, - EvadeFire = 3, - Vertical = 4 + NoReaction=0, + PassiveDefense=1, + EvadeFire=2, + BypassAndEscape=3, + AllowAbortMission=4, } +--- Weapon types. See the [Weapon Flag](https://wiki.hoggitworld.com/view/DCS_enum_weapon_flag) enumerotor on hoggit wiki. +-- @type ENUMS.WeaponFlag ENUMS.WeaponFlag={ - -- Auto - Auto=1073741822, -- Bombs - LGB=2, - TvGB=4, - SNSGB=8, - HEBomb=16, - Penetrator=32, - NapalmBomb=64, - FAEBomb=128, - ClusterBomb=256, - Dispencer=512, - CandleBomb=1024, - ParachuteBomb=2147483648, - GuidedBomb=14, -- (LGB + TvGB + SNSGB) - AnyUnguidedBomb=2147485680, -- (HeBomb + Penetrator + NapalmBomb + FAEBomb + ClusterBomb + Dispencer + CandleBomb + ParachuteBomb) - AnyBomb=2147485694, -- (GuidedBomb + AnyUnguidedBomb) + LGB = 2, + TvGB = 4, + SNSGB = 8, + HEBomb = 16, + Penetrator = 32, + NapalmBomb = 64, + FAEBomb = 128, + ClusterBomb = 256, + Dispencer = 512, + CandleBomb = 1024, + ParachuteBomb = 2147483648, -- Rockets - LightRocket=2048, - MarkerRocket=4096, - CandleRocket=8192, - HeavyRocket=16384, - AnyRocket=30720 -- (LightRocket + MarkerRocket + CandleRocket + HeavyRocket) + LightRocket = 2048, + MarkerRocket = 4096, + CandleRocket = 8192, + HeavyRocket = 16384, + -- Air-To-Surface Missiles + AntiRadarMissile = 32768, + AntiShipMissile = 65536, + AntiTankMissile = 131072, + FireAndForgetASM = 262144, + LaserASM = 524288, + TeleASM = 1048576, + CruiseMissile = 2097152, + AntiRadarMissile2 = 1073741824, + -- Air-To-Air Missiles + SRAM = 4194304, + MRAAM = 8388608, + LRAAM = 16777216, + IR_AAM = 33554432, + SAR_AAM = 67108864, + AR_AAM = 134217728, + --- Guns + GunPod = 268435456, + BuiltInCannon = 536870912, + --- + -- Combinations + -- + -- Bombs + GuidedBomb = 14, -- (LGB + TvGB + SNSGB) + AnyUnguidedBomb = 2147485680, -- (HeBomb + Penetrator + NapalmBomb + FAEBomb + ClusterBomb + Dispencer + CandleBomb + ParachuteBomb) + AnyBomb = 2147485694, -- (GuidedBomb + AnyUnguidedBomb) + --- Rockets + AnyRocket = 30720, -- LightRocket + MarkerRocket + CandleRocket + HeavyRocket + --- Air-To-Surface Missiles + GuidedASM = 1572864, -- (LaserASM + TeleASM) + TacticalASM = 1835008, -- (GuidedASM + FireAndForgetASM) + AnyASM = 4161536, -- (AntiRadarMissile + AntiShipMissile + AntiTankMissile + FireAndForgetASM + GuidedASM + CruiseMissile) + AnyASM2 = 1077903360, -- 4161536+1073741824, + --- Air-To-Air Missiles + AnyAAM = 264241152, -- IR_AAM + SAR_AAM + AR_AAM + SRAAM + MRAAM + LRAAM + AnyAutonomousMissile = 36012032, -- IR_AAM + AntiRadarMissile + AntiShipMissile + FireAndForgetASM + CruiseMissile + AnyMissile = 268402688, -- AnyASM + AnyAAM + --- Guns + Cannons = 805306368, -- GUN_POD + BuiltInCannon + --- + -- Even More Genral + Auto = 3221225470, -- Any Weapon (AnyBomb + AnyRocket + AnyMissile + Cannons) + AutoDCS = 1073741822, -- Something if often see + AnyAG = 2956984318, -- Any Air-To-Ground Weapon + AnyAA = 264241152, -- Any Air-To-Air Weapon + AnyUnguided = 2952822768, -- Any Unguided Weapon + AnyGuided = 268402702, -- Any Guided Weapon +} + +--- Mission tasks. +-- @type ENUMS.MissionTask +-- @field #string NOTHING No special task. Group can perform the minimal tasks: Orbit, Refuelling, Follow and Aerobatics. +-- @field #string AFAC Forward Air Controller Air. Can perform the tasks: Attack Group, Attack Unit, FAC assign group, Bombing, Attack Map Object. +-- @field #string ANTISHIPSTRIKE Naval ops. Can perform the tasks: Attack Group, Attack Unit. +-- @field #string AWACS AWACS. +-- @field #string CAP Combat Air Patrol. +-- @field #string CAS Close Air Support. +-- @field #string ESCORT Escort another group. +-- @field #string FIGHTERSWEEP Fighter sweep. +-- @field #string GROUNDATTACK Ground attack. +-- @field #string INTERCEPT Intercept. +-- @field #string PINPOINTSTRIKE Pinpoint strike. +-- @field #string RECONNAISSANCE Reconnaissance mission. +-- @field #string REFUELING Refueling mission. +-- @field #string RUNWAYATTACK Attack the runway of an airdrome. +-- @field #string SEAD Suppression of Enemy Air Defenses. +-- @field #string TRANSPORT Troop transport. +ENUMS.MissionTask={ + NOTHING="Nothing", + AFAC="AFAC", + ANTISHIPSTRIKE="Antiship Strike", + AWACS="AWACS", + CAP="CAP", + CAS="CAS", + ESCORT="Escort", + FIGHTERSWEEP="Fighter Sweep", + GROUNDATTACK="Ground Attack", + INTERCEPT="Intercept", + PINPOINTSTRIKE="Pinpoint Strike", + RECONNAISSANCE="Reconnaissance", + REFUELING="Refueling", + RUNWAYATTACK="Runway Attack", + SEAD="SEAD", + TRANSPORT="Transport", } \ No newline at end of file diff --git a/Moose Development/Moose/Utilities/Utils.lua b/Moose Development/Moose/Utilities/Utils.lua index 15ae1ac1b..2980550b9 100644 --- a/Moose Development/Moose/Utilities/Utils.lua +++ b/Moose Development/Moose/Utilities/Utils.lua @@ -65,7 +65,7 @@ CALLSIGN={ Enfield=1, Springfield=2, Uzi=3, - Cold=4, + Colt=4, Dodge=5, Ford=6, Chevy=7, @@ -437,8 +437,8 @@ UTILS.tostringLL = function( lat, lon, acc, DMS) end -- 024� 23' 12"N or 024� 23' 12.03"N - return string.format('%03d°', latDeg) .. ' ' .. string.format('%02d', latMin) .. '\' ' .. string.format(secFrmtStr, latSec) .. '"' .. latHemi .. ' ' - .. string.format('%03d°', lonDeg) .. ' ' .. string.format('%02d', lonMin) .. '\' ' .. string.format(secFrmtStr, lonSec) .. '"' .. lonHemi + return string.format('%03d°', latDeg)..string.format('%02d', latMin)..'\''..string.format(secFrmtStr, latSec)..'"'..latHemi..' ' + .. string.format('%03d°', lonDeg)..string.format('%02d', lonMin)..'\''..string.format(secFrmtStr, lonSec)..'"'..lonHemi else -- degrees, decimal minutes. latMin = UTILS.Round(latMin, acc) @@ -1098,5 +1098,36 @@ function UTILS.GetModulationName(Modulation) end +--- Get the callsign name from its enumerator value +-- @param #number Callsign The enumerator callsign. +-- @return #string The callsign name. +function UTILS.GetCallsignName(Callsign) + + for name, value in pairs(CALLSIGN.Aircraft) do + if value==Callsign then + return name + end + end + + for name, value in pairs(CALLSIGN.AWACS) do + if value==Callsign then + return name + end + end + + for name, value in pairs(CALLSIGN.JTAC) do + if value==Callsign then + return name + end + end + + for name, value in pairs(CALLSIGN.Tanker) do + if value==Callsign then + return name + end + end + + return "Unknown Calsing" +end -- Just a test to see commits in new environment for Wingthor \ No newline at end of file diff --git a/Moose Development/Moose/Wrapper/Controllable.lua b/Moose Development/Moose/Wrapper/Controllable.lua index 97f17d59a..828188dc9 100644 --- a/Moose Development/Moose/Wrapper/Controllable.lua +++ b/Moose Development/Moose/Wrapper/Controllable.lua @@ -312,7 +312,6 @@ function CONTROLLABLE:ClearTasks() if DCSControllable then local Controller = self:_GetController() - env.info("FF clearing tasks!") Controller:resetTask() return self end @@ -450,7 +449,6 @@ end -- @param #number lastWayPoint Last waypoint. -- return DCS#Task function CONTROLLABLE:TaskCondition( time, userFlag, userFlagValue, condition, duration, lastWayPoint ) - self:F2( { time, userFlag, userFlagValue, condition, duration, lastWayPoint } ) --[[ StopCondition = { @@ -471,7 +469,6 @@ function CONTROLLABLE:TaskCondition( time, userFlag, userFlagValue, condition, d DCSStopCondition.duration = duration DCSStopCondition.lastWayPoint = lastWayPoint - self:T3( { DCSStopCondition } ) return DCSStopCondition end @@ -481,11 +478,8 @@ end -- @param DCS#DCSStopCondition DCSStopCondition -- @return DCS#Task function CONTROLLABLE:TaskControlled( DCSTask, DCSStopCondition ) - self:F2( { DCSTask, DCSStopCondition } ) - local DCSTaskControlled - - DCSTaskControlled = { + local DCSTaskControlled = { id = 'ControlledTask', params = { task = DCSTask, @@ -493,7 +487,6 @@ function CONTROLLABLE:TaskControlled( DCSTask, DCSStopCondition ) } } - self:T3( { DCSTaskControlled } ) return DCSTaskControlled end @@ -502,22 +495,14 @@ end -- @param DCS#TaskArray DCSTasks Array of @{DCSTasking.Task#Task} -- @return DCS#Task function CONTROLLABLE:TaskCombo( DCSTasks ) - self:F2( { DCSTasks } ) - local DCSTaskCombo - - DCSTaskCombo = { + local DCSTaskCombo = { id = 'ComboTask', params = { tasks = DCSTasks } } - - for TaskID, Task in ipairs( DCSTasks ) do - self:T( Task ) - end - - self:T3( { DCSTaskCombo } ) + return DCSTaskCombo end @@ -526,11 +511,8 @@ end -- @param DCS#Command DCSCommand -- @return DCS#Task function CONTROLLABLE:TaskWrappedAction( DCSCommand, Index ) - self:F2( { DCSCommand } ) - local DCSTaskWrappedAction - - DCSTaskWrappedAction = { + local DCSTaskWrappedAction = { id = "WrappedAction", enabled = true, number = Index or 1, @@ -540,7 +522,6 @@ function CONTROLLABLE:TaskWrappedAction( DCSCommand, Index ) }, } - self:T3( { DCSTaskWrappedAction } ) return DCSTaskWrappedAction end @@ -703,7 +684,6 @@ end -- @param #number Delay (Optional) Delay in seconds before the ICLS is deactivated. -- @return #CONTROLLABLE self function CONTROLLABLE:CommandActivateICLS(Channel, UnitID, Callsign, Delay) - self:F() -- Command to activate ICLS system. local CommandActivateICLS= { @@ -731,7 +711,6 @@ end -- @param #number Delay (Optional) Delay in seconds before the beacon is deactivated. -- @return #CONTROLLABLE self function CONTROLLABLE:CommandDeactivateBeacon(Delay) - self:F() -- Command to deactivate local CommandDeactivateBeacon={id='DeactivateBeacon', params={}} @@ -750,7 +729,6 @@ end -- @param #number Delay (Optional) Delay in seconds before the ICLS is deactivated. -- @return #CONTROLLABLE self function CONTROLLABLE:CommandDeactivateICLS(Delay) - self:F() -- Command to deactivate local CommandDeactivateICLS={id='DeactivateICLS', params={}} @@ -771,7 +749,6 @@ end -- @param #number Delay (Optional) Delay in seconds before the callsign is set. Default is immediately. -- @return #CONTROLLABLE self function CONTROLLABLE:CommandSetCallsign(CallName, CallNumber, Delay) - self:F() -- Command to set the callsign. local CommandSetCallsign={id='SetCallsign', params={callname=CallName, callnumber=CallNumber or 1}} @@ -791,28 +768,56 @@ end -- @param #number Delay (Optional) Delay in seconds before the callsign is set. Default is immediately. -- @return #CONTROLLABLE self function CONTROLLABLE:CommandEPLRS(SwitchOnOff, Delay) - self:F() if SwitchOnOff==nil then SwitchOnOff=true end - -- ID - local _id=self:GetID() - -- Command to set the callsign. - local CommandEPLRS={id='EPLRS', params={value=SwitchOnOff, groupId=_id}} + local CommandEPLRS={ + id='EPLRS', + params={ + value=SwitchOnOff, + groupId=self:GetID() + } + } if Delay and Delay>0 then SCHEDULER:New(nil, self.CommandEPLRS, {self, SwitchOnOff}, Delay) else - self:T(string.format("EPLRS=%s for controllable %s (id=%s)", tostring(SwitchOnOff), tostring(self:GetName()), tostring(_id))) + self:T(string.format("EPLRS=%s for controllable %s (id=%s)", tostring(SwitchOnOff), tostring(self:GetName()), tostring(self:GetID()))) self:SetCommand(CommandEPLRS) end return self end +--- Set radio frequency. See [DCS command EPLRS](https://wiki.hoggitworld.com/view/DCS_command_setFrequency) +-- @param #CONTROLLABLE self +-- @param #number Frequency Radio frequency in MHz. +-- @param #number Modulation Radio modulation. Default `radio.modulation.AM`. +-- @param #number Delay (Optional) Delay in seconds before the frequncy is set. Default is immediately. +-- @return #CONTROLLABLE self +function CONTROLLABLE:CommandSetFrequency(Frequency, Modulation, Delay) + + local CommandSetFrequency = { + id = 'SetFrequency', + params = { + frequency = Frequency, + modulation = Modulation or radio.modulation.AM, + } + } + + if Delay and Delay>0 then + SCHEDULER:New(nil, self.CommandSetFrequency, {self, Frequency, Modulation}, Delay) + else + self:SetCommand(CommandSetFrequency) + end + + return self +end + + --- Set EPLRS data link on/off. -- @param #CONTROLLABLE self -- @param #boolean SwitchOnOff If true (or nil) switch EPLRS on. If false switch off. @@ -820,14 +825,20 @@ end -- @return #table Task wrapped action. function CONTROLLABLE:TaskEPLRS(SwitchOnOff, idx) - -- ID - local _id=self:GetID() + if SwitchOnOff==nil then + SwitchOnOff=true + end -- Command to set the callsign. - local CommandEPLRS={id='EPLRS', params={value=SwitchOnOff, groupId=_id}} + local CommandEPLRS={ + id='EPLRS', + params={ + value=SwitchOnOff, + groupId=self:GetID() + } + } return self:TaskWrappedAction(CommandEPLRS, idx or 1) - end @@ -835,16 +846,17 @@ end --- (AIR) Attack a Controllable. -- @param #CONTROLLABLE self --- @param Wrapper.Controllable#CONTROLLABLE AttackGroup The Controllable to be attacked. +-- @param Wrapper.Group#GROUP AttackGroup The Group to be attacked. -- @param #number WeaponType (optional) Bitmask of weapon types those allowed to use. If parameter is not defined that means no limits on weapon usage. -- @param DCS#AI.Task.WeaponExpend WeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / controllable will choose expend on its own discretion. -- @param #number AttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo. -- @param DCS#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction. -- @param DCS#Distance Altitude (optional) Desired attack start altitude. Controllable/aircraft will make its attacks from the altitude. If the altitude is too low or too high to use weapon aircraft/controllable will choose closest altitude to the desired attack start altitude. If the desired altitude is defined controllable/aircraft will not attack from safe altitude. -- @param #boolean AttackQtyLimit (optional) The flag determines how to interpret attackQty parameter. If the flag is true then attackQty is a limit on maximal attack quantity for "AttackGroup" and "AttackUnit" tasks. If the flag is false then attackQty is a desired attack quantity for "Bombing" and "BombingRunway" tasks. +-- @param #boolean GroupAttack (Optional) If true, attack as group. -- @return DCS#Task The DCS task structure. -function CONTROLLABLE:TaskAttackGroup( AttackGroup, WeaponType, WeaponExpend, AttackQty, Direction, Altitude, AttackQtyLimit ) - self:F2( { self.ControllableName, AttackGroup, WeaponType, WeaponExpend, AttackQty, Direction, Altitude, AttackQtyLimit } ) +function CONTROLLABLE:TaskAttackGroup( AttackGroup, WeaponType, WeaponExpend, AttackQty, Direction, Altitude, AttackQtyLimit, GroupAttack ) + --self:F2( { self.ControllableName, AttackGroup, WeaponType, WeaponExpend, AttackQty, Direction, Altitude, AttackQtyLimit } ) -- AttackGroup = { -- id = 'AttackGroup', @@ -868,15 +880,15 @@ function CONTROLLABLE:TaskAttackGroup( AttackGroup, WeaponType, WeaponExpend, At weaponType = WeaponType or 1073741822, expend = WeaponExpend or "Auto", attackQtyLimit = AttackQty and true or false, - attackQty = AttackQty, + attackQty = AttackQty or 1, directionEnabled = Direction and true or false, - direction = Direction and math.rad(Direction) or nil, + direction = Direction and math.rad(Direction) or 0, altitudeEnabled = Altitude and true or false, altitude = Altitude, + groupAttack = GroupAttack and true or false, }, - }, + } - self:T3( { DCSTask } ) return DCSTask end @@ -891,17 +903,15 @@ end -- @param #number WeaponType (optional) The WeaponType. See [DCS Enumerator Weapon Type](https://wiki.hoggitworld.com/view/DCS_enum_weapon_flag) on Hoggit. -- @return DCS#Task The DCS task structure. function CONTROLLABLE:TaskAttackUnit(AttackUnit, GroupAttack, WeaponExpend, AttackQty, Direction, Altitude, WeaponType) - self:F2({self.ControllableName, AttackUnit, GroupAttack, WeaponExpend, AttackQty, Direction, Altitude, WeaponType}) - local DCSTask - DCSTask = { + local DCSTask = { id = 'AttackUnit', params = { unitId = AttackUnit:GetID(), groupAttack = GroupAttack and GroupAttack or false, expend = WeaponExpend or "Auto", directionEnabled = Direction and true or false, - direction = Direction and math.rad(Direction) or nil, + direction = Direction and math.rad(Direction) or 0, altitudeEnabled = Altitude and true or false, altitude = Altitude, attackQtyLimit = AttackQty and true or false, @@ -909,9 +919,7 @@ function CONTROLLABLE:TaskAttackUnit(AttackUnit, GroupAttack, WeaponExpend, Atta weaponType = WeaponType or 1073741822, } } - - self:T3( DCSTask ) - + return DCSTask end @@ -928,16 +936,8 @@ end -- @param #boolean Divebomb (optional) Perform dive bombing. Default false. -- @return DCS#Task The DCS task structure. function CONTROLLABLE:TaskBombing( Vec2, GroupAttack, WeaponExpend, AttackQty, Direction, Altitude, WeaponType, Divebomb ) - self:F( { self.ControllableName, Vec2, GroupAttack, WeaponExpend, AttackQty, Direction, Altitude, WeaponType, Divebomb } ) - local _attacktype=nil - if Divebomb then - _attacktype="Dive" - end - - - local DCSTask - DCSTask = { + local DCSTask = { id = 'Bombing', params = { point = Vec2, @@ -946,17 +946,16 @@ function CONTROLLABLE:TaskBombing( Vec2, GroupAttack, WeaponExpend, AttackQty, D groupAttack = GroupAttack and GroupAttack or false, expend = WeaponExpend or "Auto", attackQtyLimit = AttackQty and true or false, - attackQty = AttackQty, + attackQty = AttackQty or 1, directionEnabled = Direction and true or false, - direction = Direction and math.rad(Direction) or nil, + direction = Direction and math.rad(Direction) or 0, altitudeEnabled = Altitude and true or false, - altitude = Altitude, + altitude = Altitude or 2000, weaponType = WeaponType or 1073741822, - attackType = _attacktype, + attackType = Divebomb and "Dive" or nil, }, } - self:F( { TaskBombing=DCSTask } ) return DCSTask end @@ -971,10 +970,8 @@ end -- @param #number WeaponType (Optional) The WeaponType. Default Auto=1073741822. -- @return DCS#Task The DCS task structure. function CONTROLLABLE:TaskAttackMapObject( Vec2, GroupAttack, WeaponExpend, AttackQty, Direction, Altitude, WeaponType ) - self:F2( { self.ControllableName, Vec2, GroupAttack, WeaponExpend, AttackQty, Direction, Altitude, WeaponType } ) - local DCSTask - DCSTask = { + local DCSTask = { id = 'AttackMapObject', params = { point = Vec2, @@ -985,14 +982,13 @@ function CONTROLLABLE:TaskAttackMapObject( Vec2, GroupAttack, WeaponExpend, Atta attackQtyLimit = AttackQty and true or false, attackQty = AttackQty, directionEnabled = Direction and true or false, - direction = Direction, + direction = Direction and math.rad(Direction) or 0, altitudeEnabled = Altitude and true or false, altitude = Altitude, weaponType = WeaponType or 1073741822, }, - }, + } - self:T3( { DCSTask } ) return DCSTask end @@ -1009,7 +1005,6 @@ end -- @param #number CarpetLength (optional) default to 500 m. -- @return DCS#Task The DCS task structure. function CONTROLLABLE:TaskCarpetBombing(Vec2, GroupAttack, WeaponExpend, AttackQty, Direction, Altitude, WeaponType, CarpetLength) - self:F2( { self.ControllableName, Vec2, GroupAttack, WeaponExpend, AttackQty, Direction, Altitude, WeaponType, CarpetLength } ) -- Build Task Structure local DCSTask = { @@ -1026,7 +1021,7 @@ function CONTROLLABLE:TaskCarpetBombing(Vec2, GroupAttack, WeaponExpend, AttackQ attackQtyLimit = AttackQty and true or false, attackQty = AttackQty, directionEnabled = Direction and true or false, - direction = Direction and math.rad(Direction) or nil, + direction = Direction and math.rad(Direction) or 0, altitudeEnabled = Altitude and true or false, altitude = Altitude, } @@ -1061,14 +1056,14 @@ function CONTROLLABLE:TaskFollowBigFormation(FollowControllable, Vec3, LastWaypo end ---- (AIR) Move the controllable to a Vec2 Point, wait for a defined duration and embark a controllable. +--- (AIR HELICOPTER) Move the controllable to a Vec2 Point, wait for a defined duration and embark infantry groups. -- @param #CONTROLLABLE self --- @param DCS#Vec2 Vec2 The point where to wait. Needs to have x and y components. --- @param Core.Set#SET_GROUP GroupSetForEmparking Set of groups to embark. +-- @param Core.Point#COORDINATE Coordinate The point where to pickup the troops. +-- @param Core.Set#SET_GROUP GroupSetForEmbarking Set of groups to embark. -- @param #number Duration (Optional) The maximum duration in seconds to wait until all groups have embarked. --- @param Core.Set#SET_GROUP (Optional) DistributionGroupSet Set of groups identifying the groups needing to board specific helicopters. +-- @param #table Distribution (Optional) Distribution used to put the infantry groups into specific carrier units. -- @return DCS#Task The DCS task structure. -function CONTROLLABLE:TaskEmbarking(Vec2, GroupSetForEmbarking, Duration, DistributionGroupSet) +function CONTROLLABLE:TaskEmbarking(Coordinate, GroupSetForEmbarking, Duration, Distribution) -- Table of group IDs for embarking. local g4e={} @@ -1084,34 +1079,88 @@ function CONTROLLABLE:TaskEmbarking(Vec2, GroupSetForEmbarking, Duration, Distri end -- Table of group IDs for embarking. - local Distribution={} + --local Distribution={} - if DistributionGroupSet then - for _,_group in pairs(DistributionGroupSet:GetSet()) do - local group=_group --Wrapper.Group#GROUP - table.insert(Distribution, group:GetID()) - end - end + -- Distribution + --local distribution={} + --distribution[id]=gids + + local groupID=self and self:GetID() local DCSTask = { id = 'Embarking', params = { - Vec2 = Vec2, - x = Vec2.x, - y = Vec2.y, + selectedTransport = groupID, + x = Coordinate.x, + y = Coordinate.z, groupsForEmbarking = g4e, durationFlag = Duration and true or false, duration = Duration, - distributionFlag = DistributionGroupSet and true or false, + distributionFlag = Distribution and true or false, distribution = Distribution, } } - self:T3( { DCSTask } ) return DCSTask end +--- Used in conjunction with the embarking task for a transport helicopter group. The Ground units will move to the specified location and wait to be picked up by a helicopter. +-- The helicopter will then fly them to their dropoff point defined by another task for the ground forces; DisembarkFromTransport task. +-- The controllable has to be an infantry group! +-- @param #CONTROLLABLE self +-- @param Core.Point#COORDINATE Coordinate Coordinates where AI is expecting to be picked up. +-- @param #number Radius Radius in meters. Default 200 m. +-- @param #string UnitType The unit type name of the carrier, e.g. "UH-1H". Must not be specified. +-- @return DCS#Task Embark to transport task. +function CONTROLLABLE:TaskEmbarkToTransport(Coordinate, Radius, UnitType) + + local EmbarkToTransport = { + id = "EmbarkToTransport", + params={ + x = Coordinate.x, + y = Coordinate.z, + zoneRadius = Radius or 200, + selectedType = UnitType, + } + } + + return EmbarkToTransport +end + + +--- Specifies the location infantry groups that is being transported by helicopters will be unloaded at. Used in conjunction with the EmbarkToTransport task. +-- @param #CONTROLLABLE self +-- @param Core.Point#COORDINATE Coordinate Coordinates where AI is expecting to be picked up. +-- @return DCS#Task Embark to transport task. +function CONTROLLABLE:TaskDisembarking(Coordinate, GroupSetToDisembark) + + -- Table of group IDs for disembarking. + local g4e={} + + if GroupSetToDisembark then + for _,_group in pairs(GroupSetToDisembark:GetSet()) do + local group=_group --Wrapper.Group#GROUP + table.insert(g4e, group:GetID()) + end + else + self:E("ERROR: No groups for disembarking specified!") + return nil + end + + local Disembarking={ + id = "Disembarking", + params = { + x = Coordinate.x, + y = Coordinate.z, + groupsForEmbarking = g4e, -- This is no bug, the entry is really "groupsForEmbarking" even if we disembark the troops. + } + } + + return Disembarking +end + + --- (AIR) Orbit at a specified position at a specified alititude during a specified duration with a specified speed. -- @param #CONTROLLABLE self -- @param DCS#Vec2 Point The point to hold the position. @@ -1218,7 +1267,6 @@ end -- @param #boolean GroupAttack (optional) Flag indicates that the target must be engaged by all aircrafts of the controllable. Has effect only if the task is assigned to a group and not to a single aircraft. -- @return DCS#Task The DCS task structure. function CONTROLLABLE:TaskBombingRunway(Airbase, WeaponType, WeaponExpend, AttackQty, Direction, GroupAttack) - self:F2( { self.ControllableName, Airbase, WeaponType, WeaponExpend, AttackQty, Direction, GroupAttack } ) local DCSTask = { id = 'BombingRunway', @@ -1227,8 +1275,8 @@ function CONTROLLABLE:TaskBombingRunway(Airbase, WeaponType, WeaponExpend, Attac weaponType = WeaponType or ENUMS.WeaponFlag.AnyBomb, expend = WeaponExpend or AI.Task.WeaponExpend.ALL, attackQty = AttackQty or 1, - direction = Direction and math.rad(Direction) or nil, - groupAttack = GroupAttack and GroupAttack or false, + direction = Direction and math.rad(Direction) or 0, + groupAttack = GroupAttack and true or false, }, } @@ -1241,7 +1289,10 @@ end -- @return DCS#Task The DCS task structure. function CONTROLLABLE:TaskRefueling() - local DCSTask={id='Refueling', params={}} + local DCSTask={ + id='Refueling', + params={} + } return DCSTask end @@ -1249,7 +1300,7 @@ end --- (AIR HELICOPTER) Landing at the ground. For helicopters only. -- @param #CONTROLLABLE self --- @param DCS#Vec2 Point The point where to land. +-- @param DCS#Vec2 Vec2 The point where to land. -- @param #number Duration The duration in seconds to stay on the ground. -- @return #CONTROLLABLE self function CONTROLLABLE:TaskLandAtVec2(Vec2, Duration) @@ -1262,6 +1313,7 @@ function CONTROLLABLE:TaskLandAtVec2(Vec2, Duration) duration = Duration, }, } + return DCSTask end @@ -1271,18 +1323,12 @@ end -- @param #number Duration The duration in seconds to stay on the ground. -- @return #CONTROLLABLE self function CONTROLLABLE:TaskLandAtZone( Zone, Duration, RandomPoint ) - self:F2( { self.ControllableName, Zone, Duration, RandomPoint } ) - local Point - if RandomPoint then - Point = Zone:GetRandomVec2() - else - Point = Zone:GetVec2() - end + -- Get landing point + local Point=RandomPoint and Zone:GetRandomVec2() or Zone:GetVec2() - local DCSTask = self:TaskLandAtVec2( Point, Duration ) + local DCSTask = CONTROLLABLE.TaskLandAtVec2( self, Point, Duration ) - self:T3( DCSTask ) return DCSTask end @@ -1343,7 +1389,6 @@ end -- @param DCS#AttributeNameArray TargetTypes Array of AttributeName that is contains threat categories allowed to engage. Default {"Air"}. -- @return DCS#Task The DCS task structure. function CONTROLLABLE:TaskEscort( FollowControllable, Vec3, LastWaypointIndex, EngagementDistance, TargetTypes ) - self:F2( { self.ControllableName, FollowControllable, Vec3, LastWaypointIndex, EngagementDistance, TargetTypes } ) -- Escort = { -- id = 'Escort', @@ -1368,9 +1413,8 @@ function CONTROLLABLE:TaskEscort( FollowControllable, Vec3, LastWaypointIndex, E engagementDistMax = EngagementDistance, targetTypes = TargetTypes or {"Air"}, }, - }, + } - self:T3( { DCSTask } ) return DCSTask end @@ -1385,7 +1429,6 @@ end -- @param #number WeaponType (optional) Enum for weapon type ID. This value is only required if you want the group firing to use a specific weapon, for instance using the task on a ship to force it to fire guided missiles at targets within cannon range. See http://wiki.hoggit.us/view/DCS_enum_weapon_flag -- @return DCS#Task The DCS task structure. function CONTROLLABLE:TaskFireAtPoint( Vec2, Radius, AmmoCount, WeaponType ) - self:F2( { self.ControllableName, Vec2, Radius, AmmoCount, WeaponType } ) -- FireAtPoint = { -- id = 'FireAtPoint', @@ -1397,13 +1440,12 @@ function CONTROLLABLE:TaskFireAtPoint( Vec2, Radius, AmmoCount, WeaponType ) -- } -- } - local DCSTask - DCSTask = { + local DCSTask = { id = 'FireAtPoint', params = { - point = Vec2, - zoneRadius = Radius, - expendQty = 100, -- dummy value + point = Vec2, + zoneRadius = Radius, + expendQty = 100, -- dummy value expendQtyEnabled = false, } } @@ -1436,13 +1478,16 @@ end -- The killer is player-controlled allied CAS-aircraft that is in contact with the FAC. -- If the task is assigned to the controllable lead unit will be a FAC. -- @param #CONTROLLABLE self --- @param Wrapper.Controllable#CONTROLLABLE AttackGroup Target CONTROLLABLE. --- @param #number WeaponType Bitmask of weapon types those allowed to use. If parameter is not defined that means no limits on weapon usage. --- @param DCS#AI.Task.Designation Designation (optional) Designation type. --- @param #boolean Datalink (optional) Allows to use datalink to send the target information to attack aircraft. Enabled by default. +-- @param Wrapper.Group#GROUP AttackGroup Target GROUP object. +-- @param #number WeaponType Bitmask of weapon types, which are allowed to use. +-- @param DCS#AI.Task.Designation Designation (Optional) Designation type. +-- @param #boolean Datalink (Optional) Allows to use datalink to send the target information to attack aircraft. Enabled by default. +-- @param #number Frequency Frequency used to communicate with the FAC. +-- @param #number Modulation Modulation of radio for communication. +-- @param #number CallsignName Callsign enumerator name of the FAC. +-- @param #number CallsignNumber Callsign number, e.g. Axeman-**1**. -- @return DCS#Task The DCS task structure. -function CONTROLLABLE:TaskFAC_AttackGroup( AttackGroup, WeaponType, Designation, Datalink ) - self:F2( { self.ControllableName, AttackGroup, WeaponType, Designation, Datalink } ) +function CONTROLLABLE:TaskFAC_AttackGroup( AttackGroup, WeaponType, Designation, Datalink, Frequency, Modulation, CallsignName, CallsignNumber ) local DCSTask = { id = 'FAC_AttackGroup', @@ -1451,10 +1496,13 @@ function CONTROLLABLE:TaskFAC_AttackGroup( AttackGroup, WeaponType, Designation, weaponType = WeaponType, designation = Designation, datalink = Datalink, + frequency = Frequency, + modulation = Modulation, + callname = CallsignName, + number = CallsignNumber, } } - self:T3( { DCSTask } ) return DCSTask end @@ -1467,7 +1515,6 @@ end -- @param #number Priority All enroute tasks have the priority parameter. This is a number (less value - higher priority) that determines actions related to what task will be performed first. Default 0. -- @return DCS#Task The DCS task structure. function CONTROLLABLE:EnRouteTaskEngageTargets( Distance, TargetTypes, Priority ) - self:F2( { self.ControllableName, Distance, TargetTypes, Priority } ) local DCSTask = { id = 'EngageTargets', @@ -1479,7 +1526,6 @@ function CONTROLLABLE:EnRouteTaskEngageTargets( Distance, TargetTypes, Priority } } - self:T3( { DCSTask } ) return DCSTask end @@ -1489,11 +1535,10 @@ end -- @param #CONTROLLABLE self -- @param DCS#Vec2 Vec2 2D-coordinates of the zone. -- @param DCS#Distance Radius Radius of the zone. --- @param DCS#AttributeNameArray (Optional) TargetTypes Array of target categories allowed to engage. Default {"Air"}. +-- @param DCS#AttributeNameArray TargetTypes (Optional) Array of target categories allowed to engage. Default {"Air"}. -- @param #number Priority (Optional) All en-route tasks have the priority parameter. This is a number (less value - higher priority) that determines actions related to what task will be performed first. Default 0. -- @return DCS#Task The DCS task structure. function CONTROLLABLE:EnRouteTaskEngageTargetsInZone( Vec2, Radius, TargetTypes, Priority ) - self:F2( { self.ControllableName, Vec2, Radius, TargetTypes, Priority } ) local DCSTask = { id = 'EngageTargetsInZone', @@ -1505,7 +1550,6 @@ function CONTROLLABLE:EnRouteTaskEngageTargetsInZone( Vec2, Radius, TargetTypes, } } - self:T3( { DCSTask } ) return DCSTask end @@ -1522,7 +1566,6 @@ end -- @param #boolean AttackQtyLimit (optional) The flag determines how to interpret attackQty parameter. If the flag is true then attackQty is a limit on maximal attack quantity for "AttackGroup" and "AttackUnit" tasks. If the flag is false then attackQty is a desired attack quantity for "Bombing" and "BombingRunway" tasks. -- @return DCS#Task The DCS task structure. function CONTROLLABLE:EnRouteTaskEngageGroup( AttackGroup, Priority, WeaponType, WeaponExpend, AttackQty, Direction, Altitude, AttackQtyLimit ) - self:F2( { self.ControllableName, AttackGroup, Priority, WeaponType, WeaponExpend, AttackQty, Direction, Altitude, AttackQtyLimit } ) -- EngageControllable = { -- id = 'EngageControllable ', @@ -1554,9 +1597,8 @@ function CONTROLLABLE:EnRouteTaskEngageGroup( AttackGroup, Priority, WeaponType, attackQty = AttackQty, priority = Priority or 1, }, - }, + } - self:T3( { DCSTask } ) return DCSTask end @@ -1574,7 +1616,6 @@ end -- @param #boolean ControllableAttack (optional) Flag indicates that the target must be engaged by all aircrafts of the controllable. Has effect only if the task is assigned to a controllable, not to a single aircraft. -- @return DCS#Task The DCS task structure. function CONTROLLABLE:EnRouteTaskEngageUnit( EngageUnit, Priority, GroupAttack, WeaponExpend, AttackQty, Direction, Altitude, Visible, ControllableAttack ) - self:F2( { self.ControllableName, EngageUnit, Priority, GroupAttack, WeaponExpend, AttackQty, Direction, Altitude, Visible, ControllableAttack } ) local DCSTask = { id = 'EngageUnit', @@ -1592,9 +1633,8 @@ function CONTROLLABLE:EnRouteTaskEngageUnit( EngageUnit, Priority, GroupAttack, attackQty = AttackQty, controllableAttack = ControllableAttack, }, - }, + } - self:T3( { DCSTask } ) return DCSTask end @@ -1604,11 +1644,12 @@ end -- @param #CONTROLLABLE self -- @return DCS#Task The DCS task structure. function CONTROLLABLE:EnRouteTaskAWACS( ) - self:F2( { self.ControllableName } ) - local DCSTask = {id = 'AWACS', params = {}} + local DCSTask = { + id = 'AWACS', + params = {}, + } - self:T3( { DCSTask } ) return DCSTask end @@ -1617,11 +1658,12 @@ end -- @param #CONTROLLABLE self -- @return DCS#Task The DCS task structure. function CONTROLLABLE:EnRouteTaskTanker( ) - self:F2( { self.ControllableName } ) - local DCSTask = {id = 'Tanker', params = {}} + local DCSTask = { + id = 'Tanker', + params = {}, + } - self:T3( { DCSTask } ) return DCSTask end @@ -1632,11 +1674,12 @@ end -- @param #CONTROLLABLE self -- @return DCS#Task The DCS task structure. function CONTROLLABLE:EnRouteTaskEWR( ) - self:F2( { self.ControllableName } ) - local DCSTask = {id = 'EWR', params = {}} + local DCSTask = { + id = 'EWR', + params = {}, + } - self:T3( { DCSTask } ) return DCSTask end @@ -1654,7 +1697,6 @@ end -- @param #boolean Datalink (optional) Allows to use datalink to send the target information to attack aircraft. Enabled by default. -- @return DCS#Task The DCS task structure. function CONTROLLABLE:EnRouteTaskFAC_EngageGroup( AttackGroup, Priority, WeaponType, Designation, Datalink ) - self:F2( { self.ControllableName, AttackGroup, WeaponType, Priority, Designation, Datalink } ) local DCSTask = { id = 'FAC_EngageControllable', @@ -1667,7 +1709,6 @@ function CONTROLLABLE:EnRouteTaskFAC_EngageGroup( AttackGroup, Priority, WeaponT } } - self:T3( { DCSTask } ) return DCSTask end @@ -1680,7 +1721,6 @@ end -- @param #number Priority All en-route tasks have the priority parameter. This is a number (less value - higher priority) that determines actions related to what task will be performed first. -- @return DCS#Task The DCS task structure. function CONTROLLABLE:EnRouteTaskFAC( Radius, Priority ) - self:F2( { self.ControllableName, Radius, Priority } ) -- FAC = { -- id = 'FAC', @@ -1690,161 +1730,14 @@ function CONTROLLABLE:EnRouteTaskFAC( Radius, Priority ) -- } -- } - local DCSTask - DCSTask = { id = 'FAC', + local DCSTask = { + id = 'FAC', params = { radius = Radius, priority = Priority } } - self:T3( { DCSTask } ) - return DCSTask -end - - - ---[[ ---- Used in conjunction with the embarking task for a transport helicopter group. The Ground units will move to the specified location and wait to be picked up by a helicopter. --- The helicopter will then fly them to their dropoff point defined by another task for the ground forces; DisembarkFromTransport task. --- The controllable has to be an infantry group! --- @param #CONTROLLABLE self --- @param Core.Point#COORDINATE Coordinate Coordinates where AI is expecting to be picked up. --- @param #number Radius Radius in meters. --- @return #table Embark to transport task. -function CONTROLLABLE:TaskEmbarkToTransport(Coordinate, Radius) - - local EmbarkToTransport = { - id="EmbarkToTransport", - params={ - x=Coordinate.x, - y=Coordinate.z, - zoneRadius=Radius, - --selectedType="UH-1H", - } - } - - self:E(EmbarkToTransport) - return EmbarkToTransport -end - ---- Used in conjunction with the EmbarkToTransport task for a ground infantry group, the controlled helicopter flight will land at the specified coordinates, --- pick up boarding troops and transport them to that groups DisembarkFromTransport task. --- The CONTROLLABLE has to be a helicopter group! --- @param #CONTROLLABLE self --- @param Core.Set#SET_GROUP GroupSet Set of groups to be embarked by the controllable. --- @param Core.Point#COORDINATE Coordinate Coordinate of embarking. --- @param #number Duration Duration of embarking in seconds. --- @return #table Embarking task. -function CONTROLLABLE:TaskEmbarking(GroupSet, Coordinate, Duration) - - -- Create table of group IDs. - local gids={} - for _,_group in pairs(GroupSet:GetAliveSet()) do - local group=_group --Wrapper.Group#GROUP - table.insert(gids, group:GetID()) - end - - -- Group ID of controllable. - local id=self:GetID() - - -- Distribution - local distribution={} - distribution[id]=gids - - local durationFlag=false - if Duration then - durationFlag=true - else - Duration=300 - end - - local DCStask={ - id="Embarking", - params={ - selectedTransport=self:GetID(), - distributionFlag=true, - distribution=distribution, - groupsForEmbarking=gids, - durationFlag=durationFlag, - distribution=distribution, - duration=Duration, - x=Coordinate.x, - y=Coordinate.z, - } - } - - self:E(DCStask) - - return DCStask -end - ---- Specifies the location an infantry group that is being transported by helicopters will be unloaded at. Used in conjunction with the EmbarkToTransport task. --- The CONTROLLABLE has to be an infantry group! --- @param #CONTROLLABLE self --- @param Core.Point#COORDINATE Coordinate Coordinates where AI is expecting to be picked up. --- @param #number Radius Radius in meters. --- @return #table Embark to transport task. -function CONTROLLABLE:TaskDisembarkFromTransport(Coordinate, Radius) - - local DisembarkFromTransport={ - id="DisembarkFromTransport", - params = { - x=Coordinate.x, - y=Coordinate.y, - zoneRadius=Radius, - }} - - return DisembarkFromTransport -end -]] - ---- (AIR) Move the controllable to a Vec2 Point, wait for a defined duration and embark a controllable. --- @param #CONTROLLABLE self --- @param DCS#Vec2 Point The point where to wait. --- @param #number Duration The duration in seconds to wait. --- @param #CONTROLLABLE EmbarkingControllable The controllable to be embarked. --- @return DCS#Task The DCS task structure -function CONTROLLABLE:TaskEmbarking( Point, Duration, EmbarkingControllable ) - self:F2( { self.ControllableName, Point, Duration, EmbarkingControllable.DCSControllable } ) - - local DCSTask - DCSTask = { id = 'Embarking', - params = { x = Point.x, - y = Point.y, - duration = Duration, - controllablesForEmbarking = { EmbarkingControllable.ControllableID }, - durationFlag = true, - distributionFlag = false, - distribution = {}, - } - } - - self:T3( { DCSTask } ) - return DCSTask -end - ---- (GROUND) Embark to a Transport landed at a location. --- Move to a defined Vec2 Point, and embark to a controllable when arrived within a defined Radius. --- @param #CONTROLLABLE self --- @param DCS#Vec2 Point The point where to wait. --- @param #number Radius The radius of the embarking zone around the Point. --- @return DCS#Task The DCS task structure. -function CONTROLLABLE:TaskEmbarkToTransport( Point, Radius ) - self:F2( { self.ControllableName, Point, Radius } ) - - local DCSTask --DCS#Task - DCSTask = { - id = 'EmbarkToTransport', - params = { - point = Point, - x = Point.x, - y = Point.y, - zoneRadius = Radius, - } - } - - self:T3( { DCSTask } ) return DCSTask end @@ -1899,12 +1792,9 @@ end -- function CONTROLLABLE:TaskFunction( FunctionString, ... ) - local DCSTask - + -- Script local DCSScript = {} DCSScript[#DCSScript+1] = "local MissionControllable = GROUP:Find( ... ) " - --DCSScript[#DCSScript+1] = "env.info( 'TaskFunction: ' .. ( MissionControllable and MissionControllable:GetName() ) or 'No Group' )" - if arg and arg.n > 0 then local ArgumentKey = '_' .. tostring( arg ):match("table: (.*)") self:SetState( self, ArgumentKey, arg ) @@ -1914,12 +1804,10 @@ function CONTROLLABLE:TaskFunction( FunctionString, ... ) DCSScript[#DCSScript+1] = FunctionString .. "( MissionControllable )" end - DCSTask = self:TaskWrappedAction(self:CommandDoScript(table.concat( DCSScript ))) - - self:T( DCSTask ) - + -- DCS task. + local DCSTask = self:TaskWrappedAction(self:CommandDoScript(table.concat( DCSScript ))) + return DCSTask - end @@ -1929,12 +1817,12 @@ end -- @param #table TaskMission A table containing the mission task. -- @return DCS#Task function CONTROLLABLE:TaskMission( TaskMission ) - self:F2( Points ) - local DCSTask - DCSTask = { id = 'Mission', params = { TaskMission, }, } + local DCSTask = { + id = 'Mission', + params = { TaskMission, }, + } - self:T3( { DCSTask } ) return DCSTask end @@ -2995,6 +2883,51 @@ end -- Options +--- Set option. +-- @param #CONTROLLABLE self +-- @param #number OptionID ID/Type of the option. +-- @param #number OptionValue Value of the option +-- @return #CONTROLLABLE self +function CONTROLLABLE:SetOption(OptionID, OptionValue) + + local DCSControllable = self:GetDCSObject() + if DCSControllable then + local Controller = self:_GetController() + + Controller:setOption( OptionID, OptionValue ) + + return self + end + + return nil +end + +--- Set option for Rules of Engagement (ROE). +-- @param Wrapper.Controllable#CONTROLLABLE self +-- @param #number ROEvalue ROE value. See ENUMS.ROE. +-- @return Wrapper.Controllable#CONTROLLABLE self +function CONTROLLABLE:OptionROE(ROEvalue) + + local DCSControllable = self:GetDCSObject() + + if DCSControllable then + + local Controller = self:_GetController() + + if self:IsAir() then + Controller:setOption(AI.Option.Air.id.ROE, ROEvalue ) + elseif self:IsGround() then + Controller:setOption(AI.Option.Ground.id.ROE, ROEvalue ) + elseif self:IsShip() then + Controller:setOption(AI.Option.Naval.id.ROE, ROEvalue ) + end + + return self + end + + return nil +end + --- Can the CONTROLLABLE hold their weapons? -- @param #CONTROLLABLE self -- @return #boolean @@ -3237,6 +3170,27 @@ function CONTROLLABLE:OptionROTNoReaction() return nil end +--- Set Reation On Threat behaviour. +-- @param #CONTROLLABLE self +-- @param #number ROTvalue ROT value. See ENUMS.ROT. +-- @return #CONTROLLABLE self +function CONTROLLABLE:OptionROT(ROTvalue) + self:F2( { self.ControllableName } ) + + local DCSControllable = self:GetDCSObject() + if DCSControllable then + local Controller = self:_GetController() + + if self:IsAir() then + Controller:setOption( AI.Option.Air.id.REACTION_ON_THREAT, ROTvalue ) + end + + return self + end + + return nil +end + --- Can the CONTROLLABLE evade using passive defenses? -- @param #CONTROLLABLE self -- @return #boolean @@ -3515,8 +3469,76 @@ function CONTROLLABLE:OptionKeepWeaponsOnThreat() return nil end +--- Prohibit Afterburner. +-- @param #CONTROLLABLE self +-- @param #boolean Prohibit If true or nil, prohibit. If false, do not prohibit. +-- @return #CONTROLLABLE self +function CONTROLLABLE:OptionProhibitAfterburner(Prohibit) + self:F2( { self.ControllableName } ) + + if Prohibit==nil then + Prohibit=true + end + + if self:IsAir() then + self:SetOption(AI.Option.Air.id.PROHIBIT_AB, Prohibit) + end + + return self +end + +--- Defines the usage of Electronic Counter Measures by airborne forces. Disables the ability for AI to use their ECM. +-- @param #CONTROLLABLE self +-- @return #CONTROLLABLE self +function CONTROLLABLE:OptionECM_Never() + self:F2( { self.ControllableName } ) + + if self:IsAir() then + self:SetOption(AI.Option.Air.id.ECM_USING, 0) + end + + return self +end + +--- Defines the usage of Electronic Counter Measures by airborne forces. If the AI is actively being locked by an enemy radar they will enable their ECM jammer. +-- @param #CONTROLLABLE self +-- @return #CONTROLLABLE self +function CONTROLLABLE:OptionECM_OnlyLockByRadar() + self:F2( { self.ControllableName } ) + + if self:IsAir() then + self:SetOption(AI.Option.Air.id.ECM_USING, 1) + end + + return self +end +--- Defines the usage of Electronic Counter Measures by airborne forces. If the AI is being detected by a radar they will enable their ECM. +-- @param #CONTROLLABLE self +-- @return #CONTROLLABLE self +function CONTROLLABLE:OptionECM_DetectedLockByRadar() + self:F2( { self.ControllableName } ) + + if self:IsAir() then + self:SetOption(AI.Option.Air.id.ECM_USING, 2) + end + + return self +end + +--- Defines the usage of Electronic Counter Measures by airborne forces. AI will leave their ECM on all the time. +-- @param #CONTROLLABLE self +-- @return #CONTROLLABLE self +function CONTROLLABLE:OptionECM_AlwaysOn() + self:F2( { self.ControllableName } ) + + if self:IsAir() then + self:SetOption(AI.Option.Air.id.ECM_USING, 3) + end + + return self +end --- Retrieve the controllable mission and allow to place function hooks within the mission waypoint plan. -- Use the method @{Wrapper.Controllable#CONTROLLABLE:WayPointFunction} to define the hook functions for specific waypoints. diff --git a/Moose Development/Moose/Wrapper/Group.lua b/Moose Development/Moose/Wrapper/Group.lua index 484dc160b..9ac9211c2 100644 --- a/Moose Development/Moose/Wrapper/Group.lua +++ b/Moose Development/Moose/Wrapper/Group.lua @@ -440,9 +440,16 @@ function GROUP:Destroy( GenerateEvent, delay ) end ---- Returns category of the DCS Group. +--- Returns category of the DCS Group. Returns one of +-- +-- * Group.Category.AIRPLANE +-- * Group.Category.HELICOPTER +-- * Group.Category.GROUND +-- * Group.Category.SHIP +-- * Group.Category.TRAIN +-- -- @param #GROUP self --- @return DCS#Group.Category The category ID +-- @return DCS#Group.Category The category ID. function GROUP:GetCategory() self:F2( self.GroupName ) @@ -458,7 +465,7 @@ end --- Returns the category name of the #GROUP. -- @param #GROUP self --- @return #string Category name = Helicopter, Airplane, Ground Unit, Ship +-- @return #string Category name = Helicopter, Airplane, Ground Unit, Ship, Train. function GROUP:GetCategoryName() self:F2( self.GroupName ) @@ -469,6 +476,7 @@ function GROUP:GetCategoryName() [Group.Category.HELICOPTER] = "Helicopter", [Group.Category.GROUND] = "Ground Unit", [Group.Category.SHIP] = "Ship", + [Group.Category.TRAIN] = "Train", } local GroupCategory = DCSGroup:getCategory() self:T3( GroupCategory ) @@ -867,10 +875,15 @@ end --- Activates a late activated GROUP. -- @param #GROUP self +-- @param #number delay Delay in seconds, before the group is activated. -- @return #GROUP self -function GROUP:Activate() +function GROUP:Activate(delay) self:F2( { self.GroupName } ) - trigger.action.activateGroup( self:GetDCSObject() ) + if delay and delay>0 then + self:ScheduleOnce(delay, GROUP.Activate, self) + else + trigger.action.activateGroup( self:GetDCSObject() ) + end return self end diff --git a/Moose Development/Moose/Wrapper/Identifiable.lua b/Moose Development/Moose/Wrapper/Identifiable.lua index 7943fe049..5b340aec8 100644 --- a/Moose Development/Moose/Wrapper/Identifiable.lua +++ b/Moose Development/Moose/Wrapper/Identifiable.lua @@ -90,7 +90,6 @@ end --- Returns the type name of the DCS Identifiable. -- @param #IDENTIFIABLE self -- @return #string The type name of the DCS Identifiable. --- @return #nil The DCS Identifiable is not existing or alive. function IDENTIFIABLE:GetTypeName() self:F2( self.IdentifiableName ) @@ -107,9 +106,17 @@ function IDENTIFIABLE:GetTypeName() end ---- Returns category of the DCS Identifiable. +--- Returns object category of the DCS Identifiable. One of +-- +-- * Object.Category.UNIT = 1 +-- * Object.Category.WEAPON = 2 +-- * Object.Category.STATIC = 3 +-- * Object.Category.BASE = 4 +-- * Object.Category.SCENERY = 5 +-- * Object.Category.Cargo = 6 +-- -- @param #IDENTIFIABLE self --- @return DCS#Object.Category The category ID +-- @return DCS#Object.Category The category ID, i.e. a number. function IDENTIFIABLE:GetCategory() self:F2( self.ObjectName ) diff --git a/Moose Development/Moose/Wrapper/Static.lua b/Moose Development/Moose/Wrapper/Static.lua index d26aca44c..16b07c03f 100644 --- a/Moose Development/Moose/Wrapper/Static.lua +++ b/Moose Development/Moose/Wrapper/Static.lua @@ -4,7 +4,7 @@ -- -- ### Author: **FlightControl** -- --- ### Contributions: +-- ### Contributions: **funkyfranky** -- -- === -- @@ -48,6 +48,10 @@ STATIC = { } +--- Register a static object. +-- @param #STATIC self +-- @param #string StaticName Name of the static object. +-- @return #STATIC self function STATIC:Register( StaticName ) local self = BASE:Inherit( self, POSITIONABLE:New( StaticName ) ) self.StaticName = StaticName @@ -71,19 +75,21 @@ end -- @param #STATIC self -- @param #string StaticName Name of the DCS **Static** as defined within the Mission Editor. -- @param #boolean RaiseError Raise an error if not found. --- @return #STATIC +-- @return #STATIC self or *nil* function STATIC:FindByName( StaticName, RaiseError ) + + -- Find static in DB. local StaticFound = _DATABASE:FindStatic( StaticName ) + -- Set static name. self.StaticName = StaticName if StaticFound then - StaticFound:F3( { StaticName } ) return StaticFound end - - if RaiseError == nil or RaiseError == true then - error( "STATIC not found for: " .. StaticName ) + + if RaiseError == nil or RaiseError == true then + error( "STATIC not found for: " .. StaticName ) end return nil diff --git a/Moose Development/Moose/Wrapper/Unit.lua b/Moose Development/Moose/Wrapper/Unit.lua index 9be25e3f8..a7b2316b9 100644 --- a/Moose Development/Moose/Wrapper/Unit.lua +++ b/Moose Development/Moose/Wrapper/Unit.lua @@ -424,9 +424,9 @@ function UNIT:GetRange() local Desc = self:GetDesc() if Desc then - local Range = Desc.range --This is in nautical miles for some reason. But should check again! + local Range = Desc.range --This is in kilometers (not meters) for some reason. But should check again! if Range then - Range=UTILS.NMToMeters(Range) + Range=Range*1000 -- convert to meters. else Range=10000000 --10.000 km if no range end @@ -436,6 +436,64 @@ function UNIT:GetRange() return nil end +--- Check if the unit is refuelable. Also retrieves the refuelling system (boom or probe) if applicable. +-- @param #UNIT self +-- @return #boolean If true, unit is refuelable (checks for the attribute "Refuelable"). +-- @return #number Refueling system (if any): 0=boom, 1=probe. +function UNIT:IsRefuelable() + self:F2( self.UnitName ) + + local refuelable=self:HasAttribute("Refuelable") + + local system=nil + + local Desc=self:GetDesc() + if Desc and Desc.tankerType then + system=Desc.tankerType + end + + return refuelable, system +end + +--- Check if the unit is a tanker. Also retrieves the refuelling system (boom or probe) if applicable. +-- @param #UNIT self +-- @return #boolean If true, unit is refuelable (checks for the attribute "Refuelable"). +-- @return #number Refueling system (if any): 0=boom, 1=probe. +function UNIT:IsTanker() + self:F2( self.UnitName ) + + local tanker=self:HasAttribute("Tankers") + + local system=nil + + if tanker then + + local Desc=self:GetDesc() + if Desc and Desc.tankerType then + system=Desc.tankerType + end + + local typename=self:GetTypeName() + + -- Some hard coded data as this is not in the descriptors... + if typename=="IL-78M" then + system=1 --probe + elseif typename=="KC130" then + system=1 --probe + elseif typename=="KC135BDA" then + system=1 --probe + elseif typename=="KC135MPRS" then + system=1 --probe + elseif typename=="S-3B Tanker" then + system=1 --probe + end + + end + + return tanker, system +end + + --- Returns the unit's group if it exist and nil otherwise. -- @param Wrapper.Unit#UNIT self -- @return Wrapper.Group#GROUP The Group of the Unit. @@ -756,6 +814,27 @@ function UNIT:GetDamageRelative() return 1 end +--- Returns the category of the #UNIT from descriptor. Returns one of +-- +-- * Unit.Category.AIRPLANE +-- * Unit.Category.HELICOPTER +-- * Unit.Category.GROUND_UNIT +-- * Unit.Category.SHIP +-- * Unit.Category.STRUCTURE +-- +-- @param #UNIT self +-- @return #number Unit category from `getDesc().category`. +function UNIT:GetUnitCategory() + self:F3( self.UnitName ) + + local DCSUnit = self:GetDCSObject() + if DCSUnit then + return DCSUnit:getDesc().category + end + + return nil +end + --- Returns the category name of the #UNIT. -- @param #UNIT self -- @return #string Category name = Helicopter, Airplane, Ground Unit, Ship @@ -833,7 +912,9 @@ end -- * Threat level 10: Unit is AAA. -- -- --- @param #UNIT self +-- @param #UNIT self +-- @return #number Number between 0 (low threat level) and 10 (high threat level). +-- @return #string Some text. function UNIT:GetThreatLevel()