diff --git a/Moose Development/Moose/.editorconfig b/Moose Development/Moose/.editorconfig new file mode 100644 index 000000000..2cc2ce1ca --- /dev/null +++ b/Moose Development/Moose/.editorconfig @@ -0,0 +1,166 @@ +# Repository: https://github.com/CppCXY/EmmyLuaCodeStyle +# English documentation: https://github.com/CppCXY/EmmyLuaCodeStyle/blob/master/README_EN.md +[*.lua] +# [basic] + +# optional space/tab +indent_style = space +# if indent_style is space, this is valid +indent_size = 4 +# if indent_style is tab, this is valid +tab_width = 4 +# none/single/double +quote_style = none + +# only support number +continuation_indent_size = 0 + +# optional crlf/lf/cr/auto, if it is 'auto', in windows it is crlf other platforms are lf +end_of_line = auto + +detect_end_of_line = false + +# this mean utf8 length , if this is 'unset' then the line width is no longer checked +# this option decides when to chopdown the code +max_line_length = 9999 + +# this will check text end with new line +insert_final_newline = true + +# [function] + +# function call expression's args will align to first arg +# optional true/false/only_after_more_indention_statement/only_not_exist_cross_row_expression +align_call_args = false + +# if true, all function define params will align to first param +align_function_define_params = true + +remove_expression_list_finish_comma = true + +# keep/remove/remove_table_only/remove_string_only/unambiguous_remove_string_only +call_arg_parentheses = keep + +# [table] + +#optional none/comma/semicolon +table_separator_style = none + +#optional keep/never/always/smart +trailing_table_separator = keep + +# see document for detail +continuous_assign_table_field_align_to_equal_sign = true + +# if true, format like this "local t = { 1, 2, 3 }" +keep_one_space_between_table_and_bracket = true + +# if indent_style is tab, this option is invalid +align_table_field_to_first_field = true + +# [statement] + +align_chained_expression_statement = false + +# continous line distance +max_continuous_line_distance = 1 + +# see document for detail +continuous_assign_statement_align_to_equal_sign = true + +# if statement will align like switch case +if_condition_align_with_each_other = false + +# if true, continuation_indent_size for local or assign statement is invalid +# however, if the expression list has cross row expression, it will not be aligned to the first expression +local_assign_continuation_align_to_first_expression = false + +statement_inline_comment_space = 1 + +# [indentation] + +# if true, the label loses its current indentation +label_no_indent = false +# if true, there will be no indentation in the do statement +do_statement_no_indent = false +# if true, the conditional expression of the if statement will not be a continuation line indent +if_condition_no_continuation_indent = false + +if_branch_comments_after_block_no_indent = false + +# [space] + +# if true, t[#t+1] will not space wrapper '+' +table_append_expression_no_space = false + +long_chain_expression_allow_one_space_after_colon = false + +remove_empty_header_and_footer_lines_in_function = true + +space_before_function_open_parenthesis = false + +space_inside_function_call_parentheses = false + +space_inside_function_param_list_parentheses = false + +space_before_open_square_bracket = false + +space_inside_square_brackets = false + +# if true, ormat like this "local t = 1" +keep_one_space_between_namedef_and_attribute = true + +# [row_layout] +# The following configuration supports four expressions +# minLine:${n} +# keepLine +# keepLine:${n} +# maxLine:${n} + +keep_line_after_if_statement = minLine:0 + +keep_line_after_do_statement = minLine:0 + +keep_line_after_while_statement = minLine:0 + +keep_line_after_repeat_statement = minLine:0 + +keep_line_after_for_statement = minLine:0 + +keep_line_after_local_or_assign_statement = keepLine + +keep_line_after_function_define_statement = keepLine:1 + +keep_line_after_expression_statement = keepLine + +# [diagnostic] + +# the following is code diagnostic options +enable_check_codestyle = true + +# [diagnostic.name_style] +enable_name_style_check = false +# the following is name style check rule +# base option off/camel_case/snake_case/upper_snake_case/pascal_case/same(filename/first_param/'', snake_case/pascal_case/camel_case) +# all option can use '|' represent or +# for example: +# snake_case | upper_snake_case +# same(first_param, snake_case) +# same('m') +local_name_define_style = snake_case + +function_param_name_style = snake_case + +function_name_define_style = snake_case + +local_function_name_define_style = snake_case + +table_field_name_define_style = snake_case + +global_variable_name_define_style = snake_case|upper_snake_case + +module_name_define_style = same('m')|same(filename, snake_case) + +require_module_name_style = same(first_param, snake_case) + +class_name_define_style = same(filename, snake_case) diff --git a/Moose Development/Moose/.lua-format b/Moose Development/Moose/.lua-format deleted file mode 100644 index 6fa8431a8..000000000 --- a/Moose Development/Moose/.lua-format +++ /dev/null @@ -1,33 +0,0 @@ -# See https://github.com/Koihik/LuaFormatter -# Use '-- LuaFormatter off' and '-- LuaFormatter on' around code blocks to inhibit formatting - -column_limit: 500 -indent_width: 2 -use_tab: false -continuation_indent_width: 2 -keep_simple_control_block_one_line: false -keep_simple_function_one_line: false -align_args: true -break_after_functioncall_lp: false -break_before_functioncall_rp: false -align_parameter: true -chop_down_parameter: true -break_after_functiondef_lp: false -break_before_functiondef_rp: false -align_table_field: true -break_after_table_lb: true -break_before_table_rb: true -chop_down_table: true -chop_down_kv_table: true -column_table_limit: 500 -table_sep: ',' -extra_sep_at_table_end: true -break_after_operator: true -single_quote_to_double_quote: false -double_quote_to_single_quote: false -spaces_before_call: 1 -spaces_inside_functiondef_parens: true -spaces_inside_functioncall_parens: true -spaces_inside_table_braces: true -spaces_around_equals_in_field: true -line_breaks_after_function_body: 1 \ No newline at end of file diff --git a/Moose Development/Moose/AI/AI_A2A_Cap.lua b/Moose Development/Moose/AI/AI_A2A_Cap.lua index aa43344e6..61b82e19e 100644 --- a/Moose Development/Moose/AI/AI_A2A_Cap.lua +++ b/Moose Development/Moose/AI/AI_A2A_Cap.lua @@ -1,4 +1,6 @@ ---- **AI** -- (R2.2) - Models the process of Combat Air Patrol (CAP) for airplanes. +--- **AI** - Models the process of Combat Air Patrol (CAP) for airplanes. +-- +-- This is a class used in the @{AI.AI_A2A_Dispatcher}. -- -- === -- @@ -13,8 +15,7 @@ -- @extends AI.AI_Air_Patrol#AI_AIR_PATROL -- @extends AI.AI_Air_Engage#AI_AIR_ENGAGE - ---- The AI_A2A_CAP class implements the core functions to patrol a @{Zone} by an AI @{Wrapper.Group} or @{Wrapper.Group} +--- The AI_A2A_CAP class implements the core functions to patrol a @{Core.Zone} by an AI @{Wrapper.Group} or @{Wrapper.Group} -- and automatically engage any airborne enemies that are within a certain range or within a certain zone. -- -- ![Process](..\Presentations\AI_CAP\Dia3.JPG) @@ -81,15 +82,15 @@ -- that will define when the AI will engage with the detected airborne enemy targets. -- The range can be beyond or smaller than the range of the Patrol Zone. -- The range is applied at the position of the AI. --- Use the method @{AI.AI_CAP#AI_A2A_CAP.SetEngageRange}() to define that range. +-- Use the method @{#AI_A2A_CAP.SetEngageRange}() to define that range. -- -- ## 4. Set the Zone of Engagement -- -- ![Zone](..\Presentations\AI_CAP\Dia12.JPG) -- --- An optional @{Zone} can be set, +-- An optional @{Core.Zone} can be set, -- that will define when the AI will engage with the detected airborne enemy targets. --- Use the method @{AI.AI_Cap#AI_A2A_CAP.SetEngageZone}() to define that Zone. +-- Use the method @{#AI_A2A_CAP.SetEngageZone}() to define that Zone. -- -- === -- @@ -106,7 +107,7 @@ AI_A2A_CAP = { -- @param DCS#Altitude EngageFloorAltitude The lowest altitude in meters where to execute the engagement. -- @param DCS#Altitude EngageCeilingAltitude The highest altitude in meters where to execute the engagement. -- @param DCS#AltitudeType EngageAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to "RADIO". --- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed. +-- @param Core.Zone#ZONE_BASE PatrolZone The @{Core.Zone} where the patrol needs to be executed. -- @param DCS#Speed PatrolMinSpeed The minimum speed of the @{Wrapper.Group} in km/h. -- @param DCS#Speed PatrolMaxSpeed The maximum speed of the @{Wrapper.Group} in km/h. -- @param DCS#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol. @@ -132,7 +133,7 @@ end --- Creates a new AI_A2A_CAP object -- @param #AI_A2A_CAP self -- @param Wrapper.Group#GROUP AICap --- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed. +-- @param Core.Zone#ZONE_BASE PatrolZone The @{Core.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. -- @param DCS#Speed PatrolMinSpeed The minimum speed of the @{Wrapper.Group} in km/h. @@ -191,7 +192,7 @@ end --- Evaluate the attack and create an AttackUnitTask list. -- @param #AI_A2A_CAP self -- @param Core.Set#SET_UNIT AttackSetUnit The set of units to attack. --- @param Wrappper.Group#GROUP DefenderGroup The group of defenders. +-- @param Wrapper.Group#GROUP DefenderGroup The group of defenders. -- @param #number EngageAltitude The altitude to engage the targets. -- @return #AI_A2A_CAP self function AI_A2A_CAP:CreateAttackUnitTasks( AttackSetUnit, DefenderGroup, EngageAltitude ) diff --git a/Moose Development/Moose/AI/AI_A2A_Dispatcher.lua b/Moose Development/Moose/AI/AI_A2A_Dispatcher.lua index 9776bf3f0..889ebe631 100644 --- a/Moose Development/Moose/AI/AI_A2A_Dispatcher.lua +++ b/Moose Development/Moose/AI/AI_A2A_Dispatcher.lua @@ -1,4 +1,4 @@ ---- **AI** - (R2.2) - Manages the process of an automatic A2A defense system based on an EWR network targets and coordinating CAP and GCI. +--- **AI** - Manages the process of an automatic A2A defense system based on an EWR network targets and coordinating CAP and GCI. -- -- === -- @@ -57,8 +57,8 @@ -- -- ## 2. Which type of EWR will I setup? Grouping based per AREA, per TYPE or per UNIT? (Later others will follow). -- --- The MOOSE framework leverages the @{Detection} classes to perform the EWR detection. --- Several types of @{Detection} classes exist, and the most common characteristics of these classes is that they: +-- The MOOSE framework leverages the @{Functional.Detection} classes to perform the EWR detection. +-- Several types of @{Functional.Detection} classes exist, and the most common characteristics of these classes is that they: -- -- * Perform detections from multiple FACs as one co-operating entity. -- * Communicate with a Head Quarters, which consolidates each detection. @@ -126,7 +126,7 @@ -- * polygon zones -- * moving zones -- --- Depending on the type of zone selected, a different @{Zone} object needs to be created from a ZONE_ class. +-- Depending on the type of zone selected, a different @{Core.Zone} object needs to be created from a ZONE_ class. -- -- ## 14. For each Squadron doing CAP, what are the time intervals and CAP amounts to be performed? -- @@ -356,7 +356,7 @@ do -- AI_A2A_DISPATCHER -- -- ![Banner Image](..\Presentations\AI_A2A_DISPATCHER\Dia9.JPG) -- - -- If it's a cold war then the **borders of red and blue territory** need to be defined using a @{zone} object derived from @{Core.Zone#ZONE_BASE}. + -- If it's a cold war then the **borders of red and blue territory** need to be defined using a @{Core.Zone} object derived from @{Core.Zone#ZONE_BASE}. -- If a hot war is chosen then **no borders** actually need to be defined using the helicopter units other than -- it makes it easier sometimes for the mission maker to envisage where the red and blue territories roughly are. -- In a hot war the borders are effectively defined by the ground based radar coverage of a coalition. @@ -592,7 +592,7 @@ do -- AI_A2A_DISPATCHER -- A2ADispatcher:SetSquadronCap( "Maykop", CAPZoneMiddle, 4000, 8000, 600, 800, 800, 1200, "RADIO" ) -- A2ADispatcher:SetSquadronCapInterval( "Sochi", 2, 30, 120, 1 ) -- - -- Note the different @{Zone} MOOSE classes being used to create zones of different types. Please click the @{Zone} link for more information about the different zone types. + -- Note the different @{Core.Zone} MOOSE classes being used to create zones of different types. Please click the @{Core.Zone} link for more information about the different zone types. -- Zones can be circles, can be setup in the mission editor using trigger zones, but can also be setup in the mission editor as polygons and in this case GROUP objects are being used! -- -- ## 7.2. Set the squadron to execute CAP: @@ -1148,7 +1148,7 @@ do -- AI_A2A_DISPATCHER self:I( "Captured " .. AirbaseName ) - -- Now search for all squadrons located at the airbase, and sanatize them. + -- Now search for all squadrons located at the airbase, and sanitize them. for SquadronName, Squadron in pairs( self.DefenderSquadrons ) do if Squadron.AirbaseName == AirbaseName then Squadron.ResourceCount = -999 -- The base has been captured, and the resources are eliminated. No more spawning. @@ -1304,7 +1304,7 @@ do -- AI_A2A_DISPATCHER --- Define a border area to simulate a **cold war** scenario. -- A **cold war** is one where CAP aircraft patrol their territory but will not attack enemy aircraft or launch GCI aircraft unless enemy aircraft enter their territory. In other words the EWR may detect an enemy aircraft but will only send aircraft to attack it if it crosses the border. -- A **hot war** is one where CAP aircraft will intercept any detected enemy aircraft and GCI aircraft will launch against detected enemy aircraft without regard for territory. In other words if the ground radar can detect the enemy aircraft then it will send CAP and GCI aircraft to attack it. - -- If it's a cold war then the **borders of red and blue territory** need to be defined using a @{zone} object derived from @{Core.Zone#ZONE_BASE}. This method needs to be used for this. + -- If it's a cold war then the **borders of red and blue territory** need to be defined using a @{Core.Zone} object derived from @{Core.Zone#ZONE_BASE}. This method needs to be used for this. -- If a hot war is chosen then **no borders** actually need to be defined using the helicopter units other than it makes it easier sometimes for the mission maker to envisage where the red and blue territories roughly are. In a hot war the borders are effectively defined by the ground based radar coverage of a coalition. Set the noborders parameter to 1 -- @param #AI_A2A_DISPATCHER self -- @param Core.Zone#ZONE_BASE BorderZone An object derived from ZONE_BASE, or a list of objects derived from ZONE_BASE. @@ -1713,7 +1713,7 @@ do -- AI_A2A_DISPATCHER -- Get free parking for fighter aircraft. local nfreeparking = DefenderSquadron.Airbase:GetFreeParkingSpotsNumber( AIRBASE.TerminalType.FighterAircraft, true ) - -- Take number of free parking spots if no resource count was specifed. + -- Take number of free parking spots if no resource count was specified. DefenderSquadron.ResourceCount = DefenderSquadron.ResourceCount or nfreeparking -- Check that resource count is not larger than free parking spots. @@ -1758,7 +1758,7 @@ do -- AI_A2A_DISPATCHER -- @param DCS#Altitude EngageFloorAltitude The lowest altitude in meters where to execute the engagement. -- @param DCS#Altitude EngageCeilingAltitude The highest altitude in meters where to execute the engagement. -- @param #number EngageAltType The altitude type to engage, which is a string "BARO" defining Barometric or "RADIO" defining radio controlled altitude. - -- @param Core.Zone#ZONE_BASE Zone The @{Zone} object derived from @{Core.Zone#ZONE_BASE} that defines the zone wherein the CAP will be executed. + -- @param Core.Zone#ZONE_BASE Zone The @{Core.Zone} object derived from @{Core.Zone#ZONE_BASE} that defines the zone wherein the CAP will be executed. -- @param #number PatrolMinSpeed The minimum speed at which the cap can be executed. -- @param #number PatrolMaxSpeed The maximum speed at which the cap can be executed. -- @param #number PatrolFloorAltitude The minimum altitude at which the cap can be executed. @@ -1825,7 +1825,7 @@ do -- AI_A2A_DISPATCHER --- Set a CAP for a Squadron. -- @param #AI_A2A_DISPATCHER self -- @param #string SquadronName The squadron name. - -- @param Core.Zone#ZONE_BASE Zone The @{Zone} object derived from @{Core.Zone#ZONE_BASE} that defines the zone wherein the CAP will be executed. + -- @param Core.Zone#ZONE_BASE Zone The @{Core.Zone} object derived from @{Core.Zone#ZONE_BASE} that defines the zone wherein the CAP will be executed. -- @param #number PatrolFloorAltitude The minimum altitude at which the cap can be executed. -- @param #number PatrolCeilingAltitude the maximum altitude at which the cap can be executed. -- @param #number PatrolMinSpeed The minimum speed at which the cap can be executed. diff --git a/Moose Development/Moose/AI/AI_A2A_Gci.lua b/Moose Development/Moose/AI/AI_A2A_Gci.lua index 15653d1e0..567ff55c2 100644 --- a/Moose Development/Moose/AI/AI_A2A_Gci.lua +++ b/Moose Development/Moose/AI/AI_A2A_Gci.lua @@ -1,6 +1,6 @@ ---- **AI** -- (R2.2) - Models the process of Ground Controlled Interception (GCI) for airplanes. +--- **AI** - Models the process of Ground Controlled Interception (GCI) for airplanes. -- --- This is a class used in the @{AI_A2A_Dispatcher}. +-- This is a class used in the @{AI.AI_A2A_Dispatcher}. -- -- === -- @@ -8,7 +8,7 @@ -- -- === -- --- @module AI.AI_A2A_GCI +-- @module AI.AI_A2A_Gci -- @image AI_Ground_Control_Intercept.JPG @@ -89,9 +89,9 @@ -- -- ![Zone](..\Presentations\AI_GCI\Dia12.JPG) -- --- An optional @{Zone} can be set, +-- An optional @{Core.Zone} can be set, -- that will define when the AI will engage with the detected airborne enemy targets. --- Use the method @{AI.AI_Cap#AI_A2A_GCI.SetEngageZone}() to define that Zone. +-- Use the method @{AI.AI_CAP#AI_CAP_ZONE.SetEngageZone}() to define that Zone. -- -- === -- @@ -153,7 +153,7 @@ end --- Evaluate the attack and create an AttackUnitTask list. -- @param #AI_A2A_GCI self -- @param Core.Set#SET_UNIT AttackSetUnit The set of units to attack. --- @param Wrappper.Group#GROUP DefenderGroup The group of defenders. +-- @param Wrapper.Group#GROUP DefenderGroup The group of defenders. -- @param #number EngageAltitude The altitude to engage the targets. -- @return #AI_A2A_GCI self function AI_A2A_GCI:CreateAttackUnitTasks( AttackSetUnit, DefenderGroup, EngageAltitude ) diff --git a/Moose Development/Moose/AI/AI_A2A_Patrol.lua b/Moose Development/Moose/AI/AI_A2A_Patrol.lua index f4252fac1..07fdd43c1 100644 --- a/Moose Development/Moose/AI/AI_A2A_Patrol.lua +++ b/Moose Development/Moose/AI/AI_A2A_Patrol.lua @@ -1,4 +1,4 @@ ---- **AI** -- (R2.2) - Models the process of air patrol of airplanes. +--- **AI** - Models the process of air patrol of airplanes. -- -- === -- @@ -13,7 +13,7 @@ --- @type AI_A2A_PATROL -- @extends AI.AI_A2A#AI_A2A ---- Implements the core functions to patrol a @{Zone} by an AI @{Wrapper.Group} or @{Wrapper.Group}. +--- Implements the core functions to patrol a @{Core.Zone} by an AI @{Wrapper.Group} or @{Wrapper.Group}. -- -- ![Process](..\Presentations\AI_PATROL\Dia3.JPG) -- @@ -102,7 +102,7 @@ -- When the AI is out of fuel, it is required that a new AI is started, before the old AI can return to the home base. -- Therefore, with a parameter and a calculation of the distance to the home base, the fuel threshold is calculated. -- When the fuel threshold is reached, the AI will continue for a given time its patrol task in orbit, --- while a new AI is targetted to the AI_A2A_PATROL. +-- while a new AI is targeted to the AI_A2A_PATROL. -- Once the time is finished, the old AI will return to the base. -- Use the method @{#AI_A2A_PATROL.ManageFuel}() to have this proces in place. -- @@ -122,7 +122,7 @@ AI_A2A_PATROL = { --- Creates a new AI_A2A_PATROL object -- @param #AI_A2A_PATROL self -- @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 Core.Zone#ZONE_BASE PatrolZone The @{Core.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. -- @param DCS#Speed PatrolMinSpeed The minimum speed of the @{Wrapper.Group} in km/h. @@ -264,7 +264,7 @@ function AI_A2A_PATROL:SetAltitude( PatrolFloorAltitude, PatrolCeilingAltitude ) end ---- Defines a new patrol route using the @{Process_PatrolZone} parameters and settings. +--- Defines a new patrol route using the @{AI.AI_Patrol#AI_PATROL_ZONE} parameters and settings. -- @param #AI_A2A_PATROL self -- @return #AI_A2A_PATROL self -- @param Wrapper.Group#GROUP AIPatrol The Group Object managed by the FSM. @@ -287,7 +287,7 @@ function AI_A2A_PATROL:onafterPatrol( AIPatrol, From, Event, To ) end ---- This statis method is called from the route path within the last task at the last waaypoint of the AIPatrol. +--- This static method is called from the route path within the last task at the last waypoint of the AIPatrol. -- Note that this method is required, as triggers the next route when patrolling for the AIPatrol. -- @param Wrapper.Group#GROUP AIPatrol The AI group. -- @param #AI_A2A_PATROL Fsm The FSM. @@ -302,7 +302,7 @@ function AI_A2A_PATROL.PatrolRoute( AIPatrol, Fsm ) end ---- Defines a new patrol route using the @{Process_PatrolZone} parameters and settings. +--- Defines a new patrol route using the @{AI.AI_Patrol#AI_PATROL_ZONE} parameters and settings. -- @param #AI_A2A_PATROL self -- @param Wrapper.Group#GROUP AIPatrol The Group managed by the FSM. -- @param #string From The From State string. diff --git a/Moose Development/Moose/AI/AI_A2G_BAI.lua b/Moose Development/Moose/AI/AI_A2G_BAI.lua index f35009033..4f00f7635 100644 --- a/Moose Development/Moose/AI/AI_A2G_BAI.lua +++ b/Moose Development/Moose/AI/AI_A2G_BAI.lua @@ -1,6 +1,6 @@ ---- **AI** -- Models the process of air to ground BAI engagement for airplanes and helicopters. +--- **AI** - Models the process of air to ground BAI engagement for airplanes and helicopters. -- --- This is a class used in the @{AI_A2G_Dispatcher}. +-- This is a class used in the @{AI.AI_A2G_Dispatcher}. -- -- === -- @@ -11,11 +11,8 @@ -- @module AI.AI_A2G_BAI -- @image AI_Air_To_Ground_Engage.JPG - - --- @type AI_A2G_BAI --- @extends AI.AI_A2A_Engage#AI_A2A_Engage - +-- @extends AI.AI_A2A_Engage#AI_A2A_Engage -- TODO: Documentation. This class does not exist, unable to determine what it extends. --- Implements the core functions to intercept intruders. Use the Engage trigger to intercept intruders. -- @@ -26,8 +23,6 @@ AI_A2G_BAI = { ClassName = "AI_A2G_BAI", } - - --- Creates a new AI_A2G_BAI object -- @param #AI_A2G_BAI self -- @param Wrapper.Group#GROUP AIGroup @@ -36,7 +31,7 @@ AI_A2G_BAI = { -- @param DCS#Altitude EngageFloorAltitude The lowest altitude in meters where to execute the engagement. -- @param DCS#Altitude EngageCeilingAltitude The highest altitude in meters where to execute the engagement. -- @param DCS#AltitudeType EngageAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to "RADIO". --- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed. +-- @param Core.Zone#ZONE_BASE PatrolZone The @{Core.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. -- @param DCS#Speed PatrolMinSpeed The minimum speed of the @{Wrapper.Group} in km/h. @@ -53,7 +48,6 @@ function AI_A2G_BAI:New2( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAl return self end - --- Creates a new AI_A2G_BAI object -- @param #AI_A2G_BAI self -- @param Wrapper.Group#GROUP AIGroup @@ -61,7 +55,7 @@ end -- @param DCS#Speed EngageMaxSpeed The maximum speed of the @{Wrapper.Group} in km/h when engaging a target. -- @param DCS#Altitude EngageFloorAltitude The lowest altitude in meters where to execute the engagement. -- @param DCS#Altitude EngageCeilingAltitude The highest altitude in meters where to execute the engagement. --- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed. +-- @param Core.Zone#ZONE_BASE PatrolZone The @{Core.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. -- @param DCS#Speed PatrolMinSpeed The minimum speed of the @{Wrapper.Group} in km/h. @@ -76,7 +70,7 @@ end --- Evaluate the attack and create an AttackUnitTask list. -- @param #AI_A2G_BAI self -- @param Core.Set#SET_UNIT AttackSetUnit The set of units to attack. --- @param Wrappper.Group#GROUP DefenderGroup The group of defenders. +-- @param Wrapper.Group#GROUP DefenderGroup The group of defenders. -- @param #number EngageAltitude The altitude to engage the targets. -- @return #AI_A2G_BAI self function AI_A2G_BAI:CreateAttackUnitTasks( AttackSetUnit, DefenderGroup, EngageAltitude ) @@ -92,8 +86,6 @@ function AI_A2G_BAI:CreateAttackUnitTasks( AttackSetUnit, DefenderGroup, EngageA end end end - + return AttackUnitTasks end - - diff --git a/Moose Development/Moose/AI/AI_A2G_CAS.lua b/Moose Development/Moose/AI/AI_A2G_CAS.lua index de24056c9..a1a31414f 100644 --- a/Moose Development/Moose/AI/AI_A2G_CAS.lua +++ b/Moose Development/Moose/AI/AI_A2G_CAS.lua @@ -1,6 +1,6 @@ ---- **AI** -- Models the process of air to ground engagement for airplanes and helicopters. +--- **AI** - Models the process of air to ground engagement for airplanes and helicopters. -- --- This is a class used in the @{AI_A2G_Dispatcher}. +-- This is a class used in the @{AI.AI_A2G_Dispatcher}. -- -- === -- @@ -11,11 +11,8 @@ -- @module AI.AI_A2G_CAS -- @image AI_Air_To_Ground_Engage.JPG - - --- @type AI_A2G_CAS --- @extends AI.AI_A2G_Patrol#AI_AIR_PATROL - +-- @extends AI.AI_A2G_Patrol#AI_AIR_PATROL TODO: Documentation. This class does not exist, unable to determine what it extends. --- Implements the core functions to intercept intruders. Use the Engage trigger to intercept intruders. -- @@ -26,8 +23,6 @@ AI_A2G_CAS = { ClassName = "AI_A2G_CAS", } - - --- Creates a new AI_A2G_CAS object -- @param #AI_A2G_CAS self -- @param Wrapper.Group#GROUP AIGroup @@ -36,7 +31,7 @@ AI_A2G_CAS = { -- @param DCS#Altitude EngageFloorAltitude The lowest altitude in meters where to execute the engagement. -- @param DCS#Altitude EngageCeilingAltitude The highest altitude in meters where to execute the engagement. -- @param DCS#AltitudeType EngageAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to "RADIO". --- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed. +-- @param Core.Zone#ZONE_BASE PatrolZone The @{Core.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. -- @param DCS#Speed PatrolMinSpeed The minimum speed of the @{Wrapper.Group} in km/h. @@ -53,7 +48,6 @@ function AI_A2G_CAS:New2( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAl return self end - --- Creates a new AI_A2G_CAS object -- @param #AI_A2G_CAS self -- @param Wrapper.Group#GROUP AIGroup @@ -61,7 +55,7 @@ end -- @param DCS#Speed EngageMaxSpeed The maximum speed of the @{Wrapper.Group} in km/h when engaging a target. -- @param DCS#Altitude EngageFloorAltitude The lowest altitude in meters where to execute the engagement. -- @param DCS#Altitude EngageCeilingAltitude The highest altitude in meters where to execute the engagement. --- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed. +-- @param Core.Zone#ZONE_BASE PatrolZone The @{Core.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. -- @param DCS#Speed PatrolMinSpeed The minimum speed of the @{Wrapper.Group} in km/h. @@ -76,7 +70,7 @@ end --- Evaluate the attack and create an AttackUnitTask list. -- @param #AI_A2G_CAS self -- @param Core.Set#SET_UNIT AttackSetUnit The set of units to attack. --- @param Wrappper.Group#GROUP DefenderGroup The group of defenders. +-- @param Wrapper.Group#GROUP DefenderGroup The group of defenders. -- @param #number EngageAltitude The altitude to engage the targets. -- @return #AI_A2G_CAS self function AI_A2G_CAS:CreateAttackUnitTasks( AttackSetUnit, DefenderGroup, EngageAltitude ) @@ -92,9 +86,6 @@ function AI_A2G_CAS:CreateAttackUnitTasks( AttackSetUnit, DefenderGroup, EngageA end end end - + return AttackUnitTasks end - - - diff --git a/Moose Development/Moose/AI/AI_A2G_Dispatcher.lua b/Moose Development/Moose/AI/AI_A2G_Dispatcher.lua index ac1a06b7d..25ebaf022 100644 --- a/Moose Development/Moose/AI/AI_A2G_Dispatcher.lua +++ b/Moose Development/Moose/AI/AI_A2G_Dispatcher.lua @@ -175,7 +175,7 @@ -- * polygon zones -- * moving zones -- --- Depending on the type of zone selected, a different @{Zone} object needs to be created from a ZONE_ class. +-- Depending on the type of zone selected, a different @{Core.Zone} object needs to be created from a ZONE_ class. -- -- -- ## 12. Are moving defense coordinates possible? @@ -1389,7 +1389,7 @@ do -- AI_A2G_DISPATCHER --- Define a border area to simulate a **cold war** scenario. -- A **cold war** is one where Patrol aircraft patrol their territory but will not attack enemy aircraft or launch GCI aircraft unless enemy aircraft enter their territory. In other words the EWR may detect an enemy aircraft but will only send aircraft to attack it if it crosses the border. -- A **hot war** is one where Patrol aircraft will intercept any detected enemy aircraft and GCI aircraft will launch against detected enemy aircraft without regard for territory. In other words if the ground radar can detect the enemy aircraft then it will send Patrol and GCI aircraft to attack it. - -- If it's a cold war then the **borders of red and blue territory** need to be defined using a @{zone} object derived from @{Core.Zone#ZONE_BASE}. This method needs to be used for this. + -- If it's a cold war then the **borders of red and blue territory** need to be defined using a @{Core.Zone} object derived from @{Core.Zone#ZONE_BASE}. This method needs to be used for this. -- If a hot war is chosen then **no borders** actually need to be defined using the helicopter units other than it makes it easier sometimes for the mission maker to envisage where the red and blue territories roughly are. In a hot war the borders are effectively defined by the ground based radar coverage of a coalition. Set the noborders parameter to 1 -- @param #AI_A2G_DISPATCHER self -- @param Core.Zone#ZONE_BASE BorderZone An object derived from ZONE_BASE, or a list of objects derived from ZONE_BASE. @@ -2185,7 +2185,7 @@ do -- AI_A2G_DISPATCHER -- The Sead patrol will start a patrol of the aircraft at a specified zone, and will engage when commanded. -- @param #AI_A2G_DISPATCHER self -- @param #string SquadronName The squadron name. - -- @param Core.Zone#ZONE_BASE Zone The @{Zone} object derived from @{Core.Zone#ZONE_BASE} that defines the zone wherein the Patrol will be executed. + -- @param Core.Zone#ZONE_BASE Zone The @{Core.Zone} object derived from @{Core.Zone#ZONE_BASE} that defines the zone wherein the Patrol will be executed. -- @param #number PatrolMinSpeed (optional, default = 50% of max speed) The minimum speed at which the cap can be executed. -- @param #number PatrolMaxSpeed (optional, default = 75% of max speed) The maximum speed at which the cap can be executed. -- @param #number PatrolFloorAltitude (optional, default = 1000m ) The minimum altitude at which the cap can be executed. @@ -2234,7 +2234,7 @@ do -- AI_A2G_DISPATCHER -- The Sead patrol will start a patrol of the aircraft at a specified zone, and will engage when commanded. -- @param #AI_A2G_DISPATCHER self -- @param #string SquadronName The squadron name. - -- @param Core.Zone#ZONE_BASE Zone The @{Zone} object derived from @{Core.Zone#ZONE_BASE} that defines the zone wherein the Patrol will be executed. + -- @param Core.Zone#ZONE_BASE Zone The @{Core.Zone} object derived from @{Core.Zone#ZONE_BASE} that defines the zone wherein the Patrol will be executed. -- @param #number FloorAltitude (optional, default = 1000m ) The minimum altitude at which the cap can be executed. -- @param #number CeilingAltitude (optional, default = 1500m ) The maximum altitude at which the cap can be executed. -- @param #number PatrolMinSpeed (optional, default = 50% of max speed) The minimum speed at which the cap can be executed. @@ -2336,7 +2336,7 @@ do -- AI_A2G_DISPATCHER -- The Cas patrol will start a patrol of the aircraft at a specified zone, and will engage when commanded. -- @param #AI_A2G_DISPATCHER self -- @param #string SquadronName The squadron name. - -- @param Core.Zone#ZONE_BASE Zone The @{Zone} object derived from @{Core.Zone#ZONE_BASE} that defines the zone wherein the Patrol will be executed. + -- @param Core.Zone#ZONE_BASE Zone The @{Core.Zone} object derived from @{Core.Zone#ZONE_BASE} that defines the zone wherein the Patrol will be executed. -- @param #number PatrolMinSpeed (optional, default = 50% of max speed) The minimum speed at which the cap can be executed. -- @param #number PatrolMaxSpeed (optional, default = 75% of max speed) The maximum speed at which the cap can be executed. -- @param #number PatrolFloorAltitude (optional, default = 1000m ) The minimum altitude at which the cap can be executed. @@ -2385,7 +2385,7 @@ do -- AI_A2G_DISPATCHER -- The Cas patrol will start a patrol of the aircraft at a specified zone, and will engage when commanded. -- @param #AI_A2G_DISPATCHER self -- @param #string SquadronName The squadron name. - -- @param Core.Zone#ZONE_BASE Zone The @{Zone} object derived from @{Core.Zone#ZONE_BASE} that defines the zone wherein the Patrol will be executed. + -- @param Core.Zone#ZONE_BASE Zone The @{Core.Zone} object derived from @{Core.Zone#ZONE_BASE} that defines the zone wherein the Patrol will be executed. -- @param #number FloorAltitude (optional, default = 1000m ) The minimum altitude at which the cap can be executed. -- @param #number CeilingAltitude (optional, default = 1500m ) The maximum altitude at which the cap can be executed. -- @param #number PatrolMinSpeed (optional, default = 50% of max speed) The minimum speed at which the cap can be executed. @@ -2487,7 +2487,7 @@ do -- AI_A2G_DISPATCHER -- The Bai patrol will start a patrol of the aircraft at a specified zone, and will engage when commanded. -- @param #AI_A2G_DISPATCHER self -- @param #string SquadronName The squadron name. - -- @param Core.Zone#ZONE_BASE Zone The @{Zone} object derived from @{Core.Zone#ZONE_BASE} that defines the zone wherein the Patrol will be executed. + -- @param Core.Zone#ZONE_BASE Zone The @{Core.Zone} object derived from @{Core.Zone#ZONE_BASE} that defines the zone wherein the Patrol will be executed. -- @param #number PatrolMinSpeed (optional, default = 50% of max speed) The minimum speed at which the cap can be executed. -- @param #number PatrolMaxSpeed (optional, default = 75% of max speed) The maximum speed at which the cap can be executed. -- @param #number PatrolFloorAltitude (optional, default = 1000m ) The minimum altitude at which the cap can be executed. @@ -2536,7 +2536,7 @@ do -- AI_A2G_DISPATCHER -- The Bai patrol will start a patrol of the aircraft at a specified zone, and will engage when commanded. -- @param #AI_A2G_DISPATCHER self -- @param #string SquadronName The squadron name. - -- @param Core.Zone#ZONE_BASE Zone The @{Zone} object derived from @{Core.Zone#ZONE_BASE} that defines the zone wherein the Patrol will be executed. + -- @param Core.Zone#ZONE_BASE Zone The @{Core.Zone} object derived from @{Core.Zone#ZONE_BASE} that defines the zone wherein the Patrol will be executed. -- @param #number FloorAltitude (optional, default = 1000m ) The minimum altitude at which the cap can be executed. -- @param #number CeilingAltitude (optional, default = 1500m ) The maximum altitude at which the cap can be executed. -- @param #number PatrolMinSpeed (optional, default = 50% of max speed) The minimum speed at which the cap can be executed. diff --git a/Moose Development/Moose/AI/AI_A2G_SEAD.lua b/Moose Development/Moose/AI/AI_A2G_SEAD.lua index 49d7ac16c..d98c40ee8 100644 --- a/Moose Development/Moose/AI/AI_A2G_SEAD.lua +++ b/Moose Development/Moose/AI/AI_A2G_SEAD.lua @@ -1,6 +1,6 @@ ---- **AI** -- Models the process of air to ground SEAD engagement for airplanes and helicopters. +--- **AI** - Models the process of air to ground SEAD engagement for airplanes and helicopters. -- --- This is a class used in the @{AI_A2G_Dispatcher}. +-- This is a class used in the @{AI.AI_A2G_Dispatcher}. -- -- === -- @@ -65,9 +65,9 @@ -- -- ![Zone](..\Presentations\AI_GCI\Dia12.JPG) -- --- An optional @{Zone} can be set, +-- An optional @{Core.Zone} can be set, -- that will define when the AI will engage with the detected airborne enemy targets. --- Use the method @{AI.AI_Cap#AI_A2G_SEAD.SetEngageZone}() to define that Zone. +-- Use the method @{AI.AI_CAP#AI_CAP_ZONE.SetEngageZone}() to define that Zone. -- TODO: Documentation. Check that this is actually correct. The originally referenced class does not exist. -- -- === -- @@ -76,8 +76,6 @@ AI_A2G_SEAD = { ClassName = "AI_A2G_SEAD", } - - --- Creates a new AI_A2G_SEAD object -- @param #AI_A2G_SEAD self -- @param Wrapper.Group#GROUP AIGroup @@ -86,7 +84,7 @@ AI_A2G_SEAD = { -- @param DCS#Altitude EngageFloorAltitude The lowest altitude in meters where to execute the engagement. -- @param DCS#Altitude EngageCeilingAltitude The highest altitude in meters where to execute the engagement. -- @param DCS#AltitudeType EngageAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to "RADIO". --- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed. +-- @param Core.Zone#ZONE_BASE PatrolZone The @{Core.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. -- @param DCS#Speed PatrolMinSpeed The minimum speed of the @{Wrapper.Group} in km/h. @@ -111,7 +109,7 @@ end -- @param DCS#Speed EngageMaxSpeed The maximum speed of the @{Wrapper.Group} in km/h when engaging a target. -- @param DCS#Altitude EngageFloorAltitude The lowest altitude in meters where to execute the engagement. -- @param DCS#Altitude EngageCeilingAltitude The highest altitude in meters where to execute the engagement. --- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed. +-- @param Core.Zone#ZONE_BASE PatrolZone The @{Core.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. -- @param DCS#Speed PatrolMinSpeed The minimum speed of the @{Wrapper.Group} in km/h. @@ -127,7 +125,7 @@ end --- Evaluate the attack and create an AttackUnitTask list. -- @param #AI_A2G_SEAD self -- @param Core.Set#SET_UNIT AttackSetUnit The set of units to attack. --- @param Wrappper.Group#GROUP DefenderGroup The group of defenders. +-- @param Wrapper.Group#GROUP DefenderGroup The group of defenders. -- @param #number EngageAltitude The altitude to engage the targets. -- @return #AI_A2G_SEAD self function AI_A2G_SEAD:CreateAttackUnitTasks( AttackSetUnit, DefenderGroup, EngageAltitude ) diff --git a/Moose Development/Moose/AI/AI_Air.lua b/Moose Development/Moose/AI/AI_Air.lua index 62c1f4a00..dea3ee2a8 100644 --- a/Moose Development/Moose/AI/AI_Air.lua +++ b/Moose Development/Moose/AI/AI_Air.lua @@ -374,7 +374,7 @@ end --- When the AI is out of fuel, it is required that a new AI is started, before the old AI can return to the home base. -- Therefore, with a parameter and a calculation of the distance to the home base, the fuel threshold is calculated. --- When the fuel threshold is reached, the AI will continue for a given time its patrol task in orbit, while a new AIControllable is targetted to the AI_AIR. +-- When the fuel threshold is reached, the AI will continue for a given time its patrol task in orbit, while a new AIControllable is targeted to the AI_AIR. -- Once the time is finished, the old AI will return to the base. -- @param #AI_AIR self -- @param #number FuelThresholdPercentage The threshold in percentage (between 0 and 1) when the AIControllable is considered to get out of fuel. @@ -409,7 +409,7 @@ end ---- Defines a new patrol route using the @{Process_PatrolZone} parameters and settings. +--- Defines a new patrol route using the @{AI.AI_Patrol#AI_PATROL_ZONE} parameters and settings. -- @param #AI_AIR self -- @return #AI_AIR self -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. @@ -473,27 +473,27 @@ function AI_AIR:onafterStatus() -- self:Home( "Destroy" ) -- end -- end - + if not self:Is( "Fuel" ) and not self:Is( "Home" ) and not self:is( "Refuelling" )then - + local Fuel = self.Controllable:GetFuelMin() - + -- If the fuel in the controllable is below the threshold percentage, -- then send for refuel in case of a tanker, otherwise RTB. if Fuel < self.FuelThresholdPercentage then - + if self.TankerName then self:I( self.Controllable:GetName() .. " is out of fuel: " .. Fuel .. " ... Refuelling at Tanker!" ) self:Refuel() else self:I( self.Controllable:GetName() .. " is out of fuel: " .. Fuel .. " ... RTB!" ) local OldAIControllable = self.Controllable - + local OrbitTask = OldAIControllable:TaskOrbitCircle( math.random( self.PatrolFloorAltitude, self.PatrolCeilingAltitude ), self.PatrolMinSpeed ) local TimedOrbitTask = OldAIControllable:TaskControlled( OrbitTask, OldAIControllable:TaskCondition(nil,nil,nil,nil,self.OutOfFuelOrbitTime,nil ) ) OldAIControllable:SetTask( TimedOrbitTask, 10 ) - + self:Fuel() RTB = true end @@ -504,11 +504,11 @@ function AI_AIR:onafterStatus() if self:Is( "Fuel" ) and not self:Is( "Home" ) and not self:is( "Refuelling" ) then RTB = true end - + -- TODO: Check GROUP damage function. local Damage = self.Controllable:GetLife() local InitialLife = self.Controllable:GetLife0() - + -- If the group is damaged, then RTB. -- Note that a group can consist of more units, so if one unit is damaged of a group, the mission may continue. -- The damaged unit will RTB due to DCS logic, and the others will continue to engage. @@ -518,7 +518,7 @@ function AI_AIR:onafterStatus() RTB = true self:SetStatusOff() end - + -- Check if planes went RTB and are out of control. -- We only check if planes are out of control, when they are in duty. if self.Controllable:HasTask() == false then @@ -532,7 +532,7 @@ function AI_AIR:onafterStatus() self:Damaged() else self:I( self.Controllable:GetName() .. " control lost! " ) - + self:LostControl() end else @@ -550,7 +550,7 @@ function AI_AIR:onafterStatus() if not self:Is("Home") then self:__Status( 10 ) end - + end end @@ -559,11 +559,11 @@ end function AI_AIR.RTBRoute( AIGroup, Fsm ) AIGroup:F( { "AI_AIR.RTBRoute:", AIGroup:GetName() } ) - + if AIGroup:IsAlive() then Fsm:RTB() end - + end --- @param Wrapper.Group#GROUP AIGroup @@ -576,7 +576,7 @@ function AI_AIR.RTBHold( AIGroup, Fsm ) local Task = AIGroup:TaskOrbitCircle( 4000, 400 ) AIGroup:SetTask( Task ) end - + end --- Set the min and max factors on RTB speed. Use this, if your planes are heading back to base too fast. Default values are 0.5 and 0.6. @@ -598,54 +598,53 @@ end function AI_AIR:onafterRTB( AIGroup, From, Event, To ) self:F( { AIGroup, From, Event, To } ) - - if AIGroup and AIGroup:IsAlive() then + if AIGroup and AIGroup:IsAlive() then self:T( "Group " .. AIGroup:GetName() .. " ... RTB! ( " .. self:GetState() .. " )" ) - + self:ClearTargetDistance() --AIGroup:ClearTasks() - + AIGroup:OptionProhibitAfterburner(true) - + local EngageRoute = {} --- Calculate the target route point. - + local FromCoord = AIGroup:GetCoordinate() local ToTargetCoord = self.HomeAirbase:GetCoordinate() -- coordinate is on land height(!) local ToTargetVec3 = ToTargetCoord:GetVec3() ToTargetVec3.y = ToTargetCoord:GetLandHeight()+3000 -- let's set this 1000m/3000 feet above ground local ToTargetCoord2 = COORDINATE:NewFromVec3( ToTargetVec3 ) - + if not self.RTBMinSpeed or not self.RTBMaxSpeed then local RTBSpeedMax = AIGroup:GetSpeedMax() local RTBSpeedMaxFactor = self.RTBSpeedMaxFactor or 0.6 local RTBSpeedMinFactor = self.RTBSpeedMinFactor or 0.5 self:SetRTBSpeed( RTBSpeedMax * RTBSpeedMinFactor, RTBSpeedMax * RTBSpeedMaxFactor) end - + local RTBSpeed = math.random( self.RTBMinSpeed, self.RTBMaxSpeed ) --local ToAirbaseAngle = FromCoord:GetAngleDegrees( FromCoord:GetDirectionVec3( ToTargetCoord2 ) ) local Distance = FromCoord:Get2DDistance( ToTargetCoord2 ) - + --local ToAirbaseCoord = FromCoord:Translate( 5000, ToAirbaseAngle ) local ToAirbaseCoord = ToTargetCoord2 - + if Distance < 5000 then self:I( "RTB and near the airbase!" ) self:Home() return end - + if not AIGroup:InAir() == true then self:I( "Not anymore in the air, considered Home." ) self:Home() return end - - + + --- Create a route point of type air. local FromRTBRoutePoint = FromCoord:WaypointAir( self.PatrolAltType, @@ -666,10 +665,10 @@ function AI_AIR:onafterRTB( AIGroup, From, Event, To ) EngageRoute[#EngageRoute+1] = FromRTBRoutePoint EngageRoute[#EngageRoute+1] = ToRTBRoutePoint - + local Tasks = {} Tasks[#Tasks+1] = AIGroup:TaskFunction( "AI_AIR.RTBRoute", self ) - + EngageRoute[#EngageRoute].task = AIGroup:TaskCombo( Tasks ) AIGroup:OptionROEHoldFire() @@ -677,9 +676,9 @@ function AI_AIR:onafterRTB( AIGroup, From, Event, To ) --- NOW ROUTE THE GROUP! AIGroup:Route( EngageRoute, self.TaskDelay ) - + end - + end --- @param #AI_AIR self diff --git a/Moose Development/Moose/AI/AI_Air_Dispatcher.lua b/Moose Development/Moose/AI/AI_Air_Dispatcher.lua index 58e4308e4..c63e007d7 100644 --- a/Moose Development/Moose/AI/AI_Air_Dispatcher.lua +++ b/Moose Development/Moose/AI/AI_Air_Dispatcher.lua @@ -1,4 +1,4 @@ ---- **AI** - Create an automated AIR defense system based on a detection network of reconnaissance vehicles and air units, coordinating SEAD, BAI and CAP operations. +--- **AI** - Create an automated AIR defense system with reconnaissance units, coordinating SEAD, BAI and CAP operations. -- -- === -- @@ -7,7 +7,7 @@ -- * Setup quickly an AIR defense system for a coalition. -- * Setup multiple defense zones to defend specific coordinates in your battlefield. -- * Setup (SEAD) Suppression of Air Defense squadrons, to gain control in the air of enemy grounds. --- * Setup (CAS) Controlled Air Support squadrons, to attack closeby enemy ground units near friendly installations. +-- * Setup (CAS) Controlled Air Support squadrons, to attack close by enemy ground units near friendly installations. -- * Setup (BAI) Battleground Air Interdiction squadrons to attack remote enemy ground units and targets. -- * Define and use a detection network controlled by recce. -- * Define AIR defense squadrons at airbases, FARPs and carriers. @@ -24,7 +24,7 @@ -- -- ## Missions: -- --- [AID-AIR - AI AIR Dispatching](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AID%20-%20AI%20Dispatching/AID-AIR%20-%20AI%20AIR%20Dispatching) +-- [AID-AIR - AI AIR Dispatching](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AID%20-%20AI%20Dispatching) -- -- === -- @@ -88,7 +88,7 @@ -- -- ## 4. How do the defenses decide **when and where to engage** on approaching enemy units? -- --- The AIR dispacher needs you to setup (various) defense coordinates, which are strategic positions in the battle field to be defended. +-- The AIR dispatcher needs you to setup (various) defense coordinates, which are strategic positions in the battle field to be defended. -- Any ground based enemy approaching within the proximity of such a defense point, may trigger for a defensive action by friendly air units. -- -- There are 2 important parameters that play a role in the defensive decision making: defensiveness and reactivity. @@ -108,7 +108,7 @@ -- ## 5. Are defense coordinates and defense reactivity the only parameters? -- -- No, depending on the target type, and the threat level of the target, the probability of defense will be higher. --- In other words, when a SAM-10 radar emitter is detected, its probabilty for defense will be much higher than when a BMP-1 vehicle is +-- In other words, when a SAM-10 radar emitter is detected, its probability for defense will be much higher than when a BMP-1 vehicle is -- detected, even when both enemies are at the same distance from a defense coordinate. -- This will ensure optimal defenses, SEAD tasks will be launched much more quicker against engaging radar emitters, to ensure air superiority. -- Approaching main battle tanks will be engaged much faster, than a group of approaching trucks. @@ -117,12 +117,12 @@ -- ## 6. Which Squadrons will I create and which name will I give each Squadron? -- -- The AIR defense system works with **Squadrons**. Each Squadron must be given a unique name, that forms the **key** to the squadron. --- Several options and activities can be set per Squadron. A free format name can be given, but always ensure that the name is meaningfull +-- Several options and activities can be set per Squadron. A free format name can be given, but always ensure that the name is meaningful -- for your mission, and remember that squadron names are used for communication to the players of your mission. -- -- There are mainly 3 types of defenses: **SEAD**, **CAS** and **BAI**. -- --- Suppression of Air Defenses (SEAD) are effective agains radar emitters. Close Air Support (CAS) is launched when the enemy is close near friendly units. +-- Suppression of Air Defenses (SEAD) are effective against radar emitters. Close Air Support (CAS) is launched when the enemy is close near friendly units. -- Battleground Air Interdiction (BAI) tasks are launched when there are no friendlies around. -- -- Depending on the defense type, different payloads will be needed. See further points on squadron definition. @@ -174,13 +174,13 @@ -- * polygon zones -- * moving zones -- --- Depending on the type of zone selected, a different @{Zone} object needs to be created from a ZONE_ class. +-- Depending on the type of zone selected, a different @{Core.Zone} object needs to be created from a ZONE_ class. -- -- -- ## 12. Are moving defense coordinates possible? -- -- Yes, different COORDINATE types are possible to be used. --- The COORDINATE_UNIT will help you to specify a defense coodinate that is attached to a moving unit. +-- The COORDINATE_UNIT will help you to specify a defense coordinate that is attached to a moving unit. -- -- -- ## 13. How much defense coordinates do I need to create? @@ -214,7 +214,7 @@ -- * From a parking spot with running engines -- * From a parking spot with cold engines -- --- **The default takeoff method is staight in the air.** +-- **The default takeoff method is straight in the air.** -- This takeoff method is the most useful if you want to avoid airplane clutter at airbases! -- But it is the least realistic one! -- @@ -236,10 +236,10 @@ -- -- For each Squadron, depending on the helicopter or airplane type (modern, old) and payload, which overhead is required to provide any defense? -- --- In other words, if **X** enemy ground units are detected, how many **Y** defense helicpters or airplanes need to engage (per squadron)? +-- In other words, if **X** enemy ground units are detected, how many **Y** defense helicopters or airplanes need to engage (per squadron)? -- The **Y** is dependent on the type of airplane (era), payload, fuel levels, skills etc. -- But the most important factor is the payload, which is the amount of AIR weapons the defense can carry to attack the enemy ground units. --- For example, a Ka-50 can carry 16 vikrs, that means, that it potentially can destroy at least 8 ground units without a reload of ammunication. +-- For example, a Ka-50 can carry 16 vikrs, that means, that it potentially can destroy at least 8 ground units without a reload of ammunition. -- That means, that one defender can destroy more enemy ground units. -- Thus, the overhead is a **factor** that will calculate dynamically how many **Y** defenses will be required based on **X** attackers detected. -- @@ -259,7 +259,7 @@ -- -- ### Author: **FlightControl** rework of GCICAP + introduction of new concepts (squadrons). -- --- @module AI.AI_AIR_Dispatcher +-- @module AI.AI_Air_Dispatcher -- @image AI_Air_To_Ground_Dispatching.JPG @@ -279,7 +279,7 @@ do -- AI_AIR_DISPATCHER -- Multiple defense coordinates can be setup. Defense coordinates can be strategic or tactical positions or references to strategic units or scenery. -- The AIR dispatcher will evaluate every x seconds the tactical situation around each defense coordinate. When a defense coordinate -- is under threat, it will communicate through the command center that defensive actions need to be taken and will launch groups of air units for defense. - -- The level of threat to the defense coordinate varyies upon the strength and types of the enemy units, the distance to the defense point, and the defensiveness parameters. + -- The level of threat to the defense coordinate varies upon the strength and types of the enemy units, the distance to the defense point, and the defensiveness parameters. -- Defensive actions are taken through probability, but the closer and the more threat the enemy poses to the defense coordinate, the faster it will be attacked by friendly AIR units. -- -- Please study carefully the underlying explanations how to setup and use this module, as it has many features. @@ -328,7 +328,7 @@ do -- AI_AIR_DISPATCHER -- By spawning in dynamically additional recce, you can ensure that there is sufficient reconnaissance coverage so the defense mechanism is continuously -- alerted of new enemy ground targets. -- - -- The following example defens a new reconnaissance network using a @{Functional.Detection#DETECTION_AREAS} object. + -- The following example defense a new reconnaissance network using a @{Functional.Detection#DETECTION_AREAS} object. -- -- -- Define a SET_GROUP object that builds a collection of groups that define the recce network. -- -- Here we build the network with all the groups that have a name starting with CCCP Recce. @@ -473,7 +473,7 @@ do -- AI_AIR_DISPATCHER -- the mission designer can choose to increase or reduce the amount of planes spawned. -- -- The method @{#AI_AIR_DISPATCHER.SetSquadron}() defines for you a new squadron. - -- The provided parameters are the squadron name, airbase name and a list of template prefixe, and a number that indicates the amount of resources. + -- The provided parameters are the squadron name, airbase name and a list of template prefixes, and a number that indicates the amount of resources. -- -- For example, this defines 3 new squadrons: -- @@ -619,7 +619,7 @@ do -- AI_AIR_DISPATCHER -- Depending on the demand of requested takeoffs by the AIR dispatcher, an airfield can become overloaded. Too many aircraft need to be taken -- off at the same time, which will result in clutter as described above. In order to better control this behaviour, a takeoff scheduler is implemented, -- which can be used to control how many aircraft are ordered for takeoff between specific time intervals. - -- The takeff intervals can be specified per squadron, which make sense, as each squadron have a "home" airfield. + -- The takeoff intervals can be specified per squadron, which make sense, as each squadron have a "home" airfield. -- -- For this purpose, the method @{#AI_AIR_DISPATCHER.SetSquadronTakeOffInterval}() can be used to specify the takeoff intervals of -- aircraft groups per squadron to avoid cluttering of aircraft at airbases. @@ -1021,7 +1021,7 @@ do -- AI_AIR_DISPATCHER -- @param #string From The From State string. -- @param #string Event The Event string. -- @param #string To The To State string. - -- @param Tasking.Task_AIR#AI_AIR Task + -- @param AI.AI_Air#AI_AIR Task -- @param Wrapper.Unit#UNIT TaskUnit -- @param #string PlayerName @@ -1224,7 +1224,7 @@ do -- AI_AIR_DISPATCHER self:I( "Captured " .. AirbaseName ) - -- Now search for all squadrons located at the airbase, and sanatize them. + -- Now search for all squadrons located at the airbase, and sanitize them. for SquadronName, Squadron in pairs( self.DefenderSquadrons ) do if Squadron.AirbaseName == AirbaseName then Squadron.ResourceCount = -999 -- The base has been captured, and the resources are eliminated. No more spawning. @@ -1376,7 +1376,7 @@ do -- AI_AIR_DISPATCHER --- Define a border area to simulate a **cold war** scenario. -- A **cold war** is one where Patrol aircraft patrol their territory but will not attack enemy aircraft or launch GCI aircraft unless enemy aircraft enter their territory. In other words the EWR may detect an enemy aircraft but will only send aircraft to attack it if it crosses the border. -- A **hot war** is one where Patrol aircraft will intercept any detected enemy aircraft and GCI aircraft will launch against detected enemy aircraft without regard for territory. In other words if the ground radar can detect the enemy aircraft then it will send Patrol and GCI aircraft to attack it. - -- If it's a cold war then the **borders of red and blue territory** need to be defined using a @{zone} object derived from @{Core.Zone#ZONE_BASE}. This method needs to be used for this. + -- If it's a cold war then the **borders of red and blue territory** need to be defined using a @{Core.Zone} object derived from @{Core.Zone#ZONE_BASE}. This method needs to be used for this. -- If a hot war is chosen then **no borders** actually need to be defined using the helicopter units other than it makes it easier sometimes for the mission maker to envisage where the red and blue territories roughly are. In a hot war the borders are effectively defined by the ground based radar coverage of a coalition. Set the noborders parameter to 1 -- @param #AI_AIR_DISPATCHER self -- @param Core.Zone#ZONE_BASE BorderZone An object derived from ZONE_BASE, or a list of objects derived from ZONE_BASE. @@ -1796,12 +1796,12 @@ do -- AI_AIR_DISPATCHER -- -- @return #AI_AIR_DISPATCHER function AI_AIR_DISPATCHER:SetSquadron2( Squadron ) - + local SquadronName = Squadron:GetName() -- Retrieves the Squadron Name. - self.DefenderSquadrons[SquadronName] = self.DefenderSquadrons[SquadronName] or {} + self.DefenderSquadrons[SquadronName] = self.DefenderSquadrons[SquadronName] or {} local DefenderSquadron = self.DefenderSquadrons[SquadronName] - + return self end @@ -1812,15 +1812,15 @@ do -- AI_AIR_DISPATCHER function AI_AIR_DISPATCHER:GetSquadron( SquadronName ) local DefenderSquadron = self.DefenderSquadrons[SquadronName] - + if not DefenderSquadron then error( "Unknown Squadron for Dispatcher:" .. SquadronName ) end - + return DefenderSquadron end - + --- Set the Squadron visible before startup of the dispatcher. -- All planes will be spawned as uncontrolled on the parking spot. -- They will lock the parking spot. diff --git a/Moose Development/Moose/AI/AI_Air_Engage.lua b/Moose Development/Moose/AI/AI_Air_Engage.lua index 31dbed41a..40438daba 100644 --- a/Moose Development/Moose/AI/AI_Air_Engage.lua +++ b/Moose Development/Moose/AI/AI_Air_Engage.lua @@ -1,6 +1,6 @@ ---- **AI** -- Models the process of air to ground engagement for airplanes and helicopters. +--- **AI** - Models the process of air to ground engagement for airplanes and helicopters. -- --- This is a class used in the @{AI_A2G_Dispatcher}. +-- This is a class used in the @{AI.AI_A2G_Dispatcher}. -- -- === -- @@ -65,9 +65,9 @@ -- -- ![Zone](..\Presentations\AI_GCI\Dia12.JPG) -- --- An optional @{Zone} can be set, +-- An optional @{Core.Zone} can be set, -- that will define when the AI will engage with the detected airborne enemy targets. --- Use the method @{AI.AI_Cap#AI_AIR_ENGAGE.SetEngageZone}() to define that Zone. +-- Use the method @{AI.AI_CAP#AI_AIR_ENGAGE.SetEngageZone}() to define that Zone. -- -- === -- diff --git a/Moose Development/Moose/AI/AI_Air_Patrol.lua b/Moose Development/Moose/AI/AI_Air_Patrol.lua index 185e64572..d354ded6f 100644 --- a/Moose Development/Moose/AI/AI_Air_Patrol.lua +++ b/Moose Development/Moose/AI/AI_Air_Patrol.lua @@ -1,4 +1,4 @@ ---- **AI** -- Models the process of A2G patrolling and engaging ground targets for airplanes and helicopters. +--- **AI** - Models the process of A2G patrolling and engaging ground targets for airplanes and helicopters. -- -- === -- @@ -12,8 +12,7 @@ --- @type AI_AIR_PATROL -- @extends AI.AI_Air#AI_AIR - ---- The AI_AIR_PATROL class implements the core functions to patrol a @{Zone} by an AI @{Wrapper.Group} or @{Wrapper.Group} +--- The AI_AIR_PATROL class implements the core functions to patrol a @{Core.Zone} by an AI @{Wrapper.Group} -- and automatically engage any airborne enemies that are within a certain range or within a certain zone. -- -- ![Process](..\Presentations\AI_CAP\Dia3.JPG) @@ -86,9 +85,9 @@ -- -- ![Zone](..\Presentations\AI_CAP\Dia12.JPG) -- --- An optional @{Zone} can be set, +-- An optional @{Core.Zone} can be set, -- that will define when the AI will engage with the detected airborne enemy targets. --- Use the method @{AI.AI_Cap#AI_AIR_PATROL.SetEngageZone}() to define that Zone. +-- Use the method @{AI.AI_CAP#AI_AIR_PATROL.SetEngageZone}() to define that Zone. -- -- === -- @@ -101,7 +100,7 @@ AI_AIR_PATROL = { -- @param #AI_AIR_PATROL self -- @param AI.AI_Air#AI_AIR AI_Air The AI_AIR FSM. -- @param Wrapper.Group#GROUP AIGroup The AI group. --- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed. +-- @param Core.Zone#ZONE_BASE PatrolZone The @{Core.Zone} where the patrol needs to be executed. -- @param DCS#Altitude PatrolFloorAltitude (optional, default = 1000m ) The lowest altitude in meters where to execute the patrol. -- @param DCS#Altitude PatrolCeilingAltitude (optional, default = 1500m ) The highest altitude in meters where to execute the patrol. -- @param DCS#Speed PatrolMinSpeed (optional, default = 50% of max speed) The minimum speed of the @{Wrapper.Group} in km/h. @@ -114,17 +113,17 @@ function AI_AIR_PATROL:New( AI_Air, AIGroup, PatrolZone, PatrolFloorAltitude, Pa local self = BASE:Inherit( self, AI_Air ) -- #AI_AIR_PATROL local SpeedMax = AIGroup:GetSpeedMax() - + self.PatrolZone = PatrolZone - + self.PatrolFloorAltitude = PatrolFloorAltitude or 1000 self.PatrolCeilingAltitude = PatrolCeilingAltitude or 1500 self.PatrolMinSpeed = PatrolMinSpeed or SpeedMax * 0.5 self.PatrolMaxSpeed = PatrolMaxSpeed or SpeedMax * 0.75 - + -- defafult PatrolAltType to "RADIO" if not specified self.PatrolAltType = PatrolAltType or "RADIO" - + self:AddTransition( { "Started", "Airborne", "Refuelling" }, "Patrol", "Patrolling" ) --- OnBefore Transition Handler for Event Patrol. @@ -135,7 +134,7 @@ function AI_AIR_PATROL:New( AI_Air, AIGroup, PatrolZone, PatrolFloorAltitude, Pa -- @param #string Event The Event string. -- @param #string To The To State string. -- @return #boolean Return false to cancel Transition. - + --- OnAfter Transition Handler for Event Patrol. -- @function [parent=#AI_AIR_PATROL] OnAfterPatrol -- @param #AI_AIR_PATROL self @@ -143,16 +142,16 @@ function AI_AIR_PATROL:New( AI_Air, AIGroup, PatrolZone, PatrolFloorAltitude, Pa -- @param #string From The From State string. -- @param #string Event The Event string. -- @param #string To The To State string. - + --- Synchronous Event Trigger for Event Patrol. -- @function [parent=#AI_AIR_PATROL] Patrol -- @param #AI_AIR_PATROL self - + --- Asynchronous Event Trigger for Event Patrol. -- @function [parent=#AI_AIR_PATROL] __Patrol -- @param #AI_AIR_PATROL self -- @param #number Delay The delay in seconds. - + --- OnLeave Transition Handler for State Patrolling. -- @function [parent=#AI_AIR_PATROL] OnLeavePatrolling -- @param #AI_AIR_PATROL self @@ -161,7 +160,7 @@ function AI_AIR_PATROL:New( AI_Air, AIGroup, PatrolZone, PatrolFloorAltitude, Pa -- @param #string Event The Event string. -- @param #string To The To State string. -- @return #boolean Return false to cancel Transition. - + --- OnEnter Transition Handler for State Patrolling. -- @function [parent=#AI_AIR_PATROL] OnEnterPatrolling -- @param #AI_AIR_PATROL self @@ -169,9 +168,9 @@ function AI_AIR_PATROL:New( AI_Air, AIGroup, PatrolZone, PatrolFloorAltitude, Pa -- @param #string From The From State string. -- @param #string Event The Event string. -- @param #string To The To State string. - + self:AddTransition( "Patrolling", "PatrolRoute", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_AIR_PATROL. - + --- OnBefore Transition Handler for Event PatrolRoute. -- @function [parent=#AI_AIR_PATROL] OnBeforePatrolRoute -- @param #AI_AIR_PATROL self @@ -180,7 +179,7 @@ function AI_AIR_PATROL:New( AI_Air, AIGroup, PatrolZone, PatrolFloorAltitude, Pa -- @param #string Event The Event string. -- @param #string To The To State string. -- @return #boolean Return false to cancel Transition. - + --- OnAfter Transition Handler for Event PatrolRoute. -- @function [parent=#AI_AIR_PATROL] OnAfterPatrolRoute -- @param #AI_AIR_PATROL self @@ -188,23 +187,21 @@ function AI_AIR_PATROL:New( AI_Air, AIGroup, PatrolZone, PatrolFloorAltitude, Pa -- @param #string From The From State string. -- @param #string Event The Event string. -- @param #string To The To State string. - + --- Synchronous Event Trigger for Event PatrolRoute. -- @function [parent=#AI_AIR_PATROL] PatrolRoute -- @param #AI_AIR_PATROL self - + --- Asynchronous Event Trigger for Event PatrolRoute. -- @function [parent=#AI_AIR_PATROL] __PatrolRoute -- @param #AI_AIR_PATROL self -- @param #number Delay The delay in seconds. - self:AddTransition( "*", "Reset", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_AIR_PATROL. return self end - --- Set the Engage Range when the AI will engage with airborne enemies. -- @param #AI_AIR_PATROL self -- @param #number EngageRange The Engage Range. @@ -230,7 +227,7 @@ end -- @param #table CapCoordinates Table of coordinates of first race track point. Second point is determined by leg length and heading. -- @return #AI_AIR_PATROL self function AI_AIR_PATROL:SetRaceTrackPattern(LegMin, LegMax, HeadingMin, HeadingMax, DurationMin, DurationMax, CapCoordinates) - + self.racetrack=true self.racetracklegmin=LegMin or 10000 self.racetracklegmax=LegMax or 15000 @@ -238,18 +235,16 @@ function AI_AIR_PATROL:SetRaceTrackPattern(LegMin, LegMax, HeadingMin, HeadingMa self.racetrackheadingmax=HeadingMax or 180 self.racetrackdurationmin=DurationMin self.racetrackdurationmax=DurationMax - + if self.racetrackdurationmax and not self.racetrackdurationmin then self.racetrackdurationmin=self.racetrackdurationmax end - + self.racetrackcapcoordinates=CapCoordinates - + end - - ---- Defines a new patrol route using the @{Process_PatrolZone} parameters and settings. +--- Defines a new patrol route using the @{AI.AI_Patrol#AI_PATROL_ZONE} parameters and settings. -- @param #AI_AIR_PATROL self -- @return #AI_AIR_PATROL self -- @param Wrapper.Group#GROUP AIPatrol The Group Object managed by the FSM. @@ -262,7 +257,7 @@ function AI_AIR_PATROL:onafterPatrol( AIPatrol, From, Event, To ) self:ClearTargetDistance() self:__PatrolRoute( self.TaskDelay ) - + AIPatrol:OnReSpawn( function( PatrolGroup ) self:__Reset( self.TaskDelay ) @@ -271,7 +266,7 @@ function AI_AIR_PATROL:onafterPatrol( AIPatrol, From, Event, To ) ) end ---- This statis method is called from the route path within the last task at the last waaypoint of the AIPatrol. +--- This static method is called from the route path within the last task at the last waypoint of the AIPatrol. -- Note that this method is required, as triggers the next route when patrolling for the AIPatrol. -- @param Wrapper.Group#GROUP AIPatrol The AI group. -- @param #AI_AIR_PATROL Fsm The FSM. @@ -282,10 +277,10 @@ function AI_AIR_PATROL.___PatrolRoute( AIPatrol, Fsm ) if AIPatrol and AIPatrol:IsAlive() then Fsm:PatrolRoute() end - + end ---- Defines a new patrol route using the @{Process_PatrolZone} parameters and settings. +--- Defines a new patrol route using the @{AI.AI_Patrol#AI_PATROL_ZONE} parameters and settings. -- @param #AI_AIR_PATROL self -- @param Wrapper.Group#GROUP AIPatrol The Group managed by the FSM. -- @param #string From The From State string. @@ -300,21 +295,20 @@ function AI_AIR_PATROL:onafterPatrolRoute( AIPatrol, From, Event, To ) return end - if AIPatrol and AIPatrol:IsAlive() then - + local PatrolRoute = {} --- Calculate the target route point. - + local CurrentCoord = AIPatrol:GetCoordinate() - + local altitude= math.random( self.PatrolFloorAltitude, self.PatrolCeilingAltitude ) - + local ToTargetCoord = self.PatrolZone:GetRandomPointVec2() ToTargetCoord:SetAlt( altitude ) self:SetTargetDistance( ToTargetCoord ) -- For RTB status check - + local ToTargetSpeed = math.random( self.PatrolMinSpeed, self.PatrolMaxSpeed ) local speedkmh=ToTargetSpeed @@ -322,31 +316,31 @@ function AI_AIR_PATROL:onafterPatrolRoute( AIPatrol, From, Event, To ) PatrolRoute[#PatrolRoute+1] = FromWP if self.racetrack then - + -- Random heading. local heading = math.random(self.racetrackheadingmin, self.racetrackheadingmax) - + -- Random leg length. local leg=math.random(self.racetracklegmin, self.racetracklegmax) - + -- Random duration if any. local duration = self.racetrackdurationmin if self.racetrackdurationmax then duration=math.random(self.racetrackdurationmin, self.racetrackdurationmax) end - + -- CAP coordinate. local c0=self.PatrolZone:GetRandomCoordinate() if self.racetrackcapcoordinates and #self.racetrackcapcoordinates>0 then c0=self.racetrackcapcoordinates[math.random(#self.racetrackcapcoordinates)] end - + -- Race track points. local c1=c0:SetAltitude(altitude) --Core.Point#COORDINATE local c2=c1:Translate(leg, heading):SetAltitude(altitude) - + self:SetTargetDistance(c0) -- For RTB status check - + -- Debug: self:T(string.format("Patrol zone race track: v=%.1f knots, h=%.1f ft, heading=%03d, leg=%d m, t=%s sec", UTILS.KmphToKnots(speedkmh), UTILS.MetersToFeet(altitude), heading, leg, tostring(duration))) --c1:MarkToAll("Race track c1") @@ -354,39 +348,41 @@ function AI_AIR_PATROL:onafterPatrolRoute( AIPatrol, From, Event, To ) -- Task to orbit. local taskOrbit=AIPatrol:TaskOrbit(c1, altitude, UTILS.KmphToMps(speedkmh), c2) - + -- Task function to redo the patrol at other random position. local taskPatrol=AIPatrol:TaskFunction("AI_AIR_PATROL.___PatrolRoute", self) - + -- Controlled task with task condition. local taskCond=AIPatrol:TaskCondition(nil, nil, nil, nil, duration, nil) local taskCont=AIPatrol:TaskControlled(taskOrbit, taskCond) - + -- Second waypoint PatrolRoute[2]=c1:WaypointAirTurningPoint(self.PatrolAltType, speedkmh, {taskCont, taskPatrol}, "CAP Orbit") else - + --- Create a route point of type air. local ToWP = ToTargetCoord:WaypointAir(self.PatrolAltType, POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, ToTargetSpeed, true) PatrolRoute[#PatrolRoute+1] = ToWP - + local Tasks = {} Tasks[#Tasks+1] = AIPatrol:TaskFunction("AI_AIR_PATROL.___PatrolRoute", self) PatrolRoute[#PatrolRoute].task = AIPatrol:TaskCombo( Tasks ) - + end - + AIPatrol:OptionROEReturnFire() AIPatrol:OptionROTEvadeFire() - + AIPatrol:Route( PatrolRoute, self.TaskDelay ) - + end end ---- @param Wrapper.Group#GROUP AIPatrol +--- Resumes the AIPatrol +-- @param Wrapper.Group#GROUP AIPatrol +-- @param Core.Fsm#FSM Fsm function AI_AIR_PATROL.Resume( AIPatrol, Fsm ) AIPatrol:F( { "AI_AIR_PATROL.Resume:", AIPatrol:GetName() } ) @@ -394,5 +390,5 @@ function AI_AIR_PATROL.Resume( AIPatrol, Fsm ) Fsm:__Reset( Fsm.TaskDelay ) Fsm:__PatrolRoute( Fsm.TaskDelay ) end - + end diff --git a/Moose Development/Moose/AI/AI_Air_Squadron.lua b/Moose Development/Moose/AI/AI_Air_Squadron.lua index 69e660877..40585187b 100644 --- a/Moose Development/Moose/AI/AI_Air_Squadron.lua +++ b/Moose Development/Moose/AI/AI_Air_Squadron.lua @@ -1,6 +1,6 @@ --- **AI** - Models squadrons for airplanes and helicopters. -- --- This is a class used in the @{AI_Air_Dispatcher} and derived dispatcher classes. +-- This is a class used in the @{AI.AI_Air_Dispatcher} and derived dispatcher classes. -- -- === -- diff --git a/Moose Development/Moose/AI/AI_BAI.lua b/Moose Development/Moose/AI/AI_BAI.lua index 9da590e03..32a6616e9 100644 --- a/Moose Development/Moose/AI/AI_BAI.lua +++ b/Moose Development/Moose/AI/AI_BAI.lua @@ -1,4 +1,4 @@ ---- **AI** -- Peform Battlefield Area Interdiction (BAI) within an engagement zone. +--- **AI** - Peform Battlefield Area Interdiction (BAI) within an engagement zone. -- -- **Features:** -- @@ -26,17 +26,17 @@ -- -- === -- --- @module AI.AI_Bai +-- @module AI.AI_BAI -- @image AI_Battlefield_Air_Interdiction.JPG --- AI_BAI_ZONE class -- @type AI_BAI_ZONE -- @field Wrapper.Controllable#CONTROLLABLE AIControllable The @{Wrapper.Controllable} patrolling. --- @field Core.Zone#ZONE_BASE TargetZone The @{Zone} where the patrol needs to be executed. +-- @field Core.Zone#ZONE_BASE TargetZone The @{Core.Zone} where the patrol needs to be executed. -- @extends AI.AI_Patrol#AI_PATROL_ZONE ---- Implements the core functions to provide BattleGround Air Interdiction in an Engage @{Zone} by an AIR @{Wrapper.Controllable} or @{Wrapper.Group}. +--- Implements the core functions to provide BattleGround Air Interdiction in an Engage @{Core.Zone} by an AIR @{Wrapper.Controllable} or @{Wrapper.Group}. -- -- The AI_BAI_ZONE runs a process. It holds an AI in a Patrol Zone and when the AI is commanded to engage, it will fly to an Engage Zone. -- @@ -142,7 +142,7 @@ AI_BAI_ZONE = { --- Creates a new AI_BAI_ZONE object -- @param #AI_BAI_ZONE self --- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed. +-- @param Core.Zone#ZONE_BASE PatrolZone The @{Core.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. -- @param DCS#Speed PatrolMinSpeed The minimum speed of the @{Wrapper.Controllable} in km/h. @@ -566,7 +566,7 @@ function AI_BAI_ZONE:onafterEngage( Controllable, From, Event, To, EngageRoute[#EngageRoute].task = Controllable:TaskCombo( AttackTasks ) - --- Define a random point in the @{Zone}. The AI will fly to that point within the zone. + --- Define a random point in the @{Core.Zone}. The AI will fly to that point within the zone. --- Find a random 2D point in EngageZone. local ToTargetVec2 = self.EngageZone:GetRandomVec2() diff --git a/Moose Development/Moose/AI/AI_Balancer.lua b/Moose Development/Moose/AI/AI_Balancer.lua index b855acf9c..047135fb1 100644 --- a/Moose Development/Moose/AI/AI_Balancer.lua +++ b/Moose Development/Moose/AI/AI_Balancer.lua @@ -1,4 +1,4 @@ ---- **AI** -- Balance player slots with AI to create an engaging simulation environment, independent of the amount of players. +--- **AI** - Balance player slots with AI to create an engaging simulation environment, independent of the amount of players. -- -- **Features:** -- diff --git a/Moose Development/Moose/AI/AI_CAP.lua b/Moose Development/Moose/AI/AI_CAP.lua index f89f2f88f..f767a52cd 100644 --- a/Moose Development/Moose/AI/AI_CAP.lua +++ b/Moose Development/Moose/AI/AI_CAP.lua @@ -1,4 +1,4 @@ ---- **AI** -- Perform Combat Air Patrolling (CAP) for airplanes. +--- **AI** - Perform Combat Air Patrolling (CAP) for airplanes. -- -- **Features:** -- @@ -6,7 +6,6 @@ -- * Trigger detected events when enemy airplanes are detected. -- * Manage a fuel threshold to RTB on time. -- * Engage the enemy when detected. --- -- -- === -- @@ -19,27 +18,25 @@ -- === -- -- ### Author: **FlightControl** --- ### Contributions: +-- ### Contributions: -- -- * **[Quax](https://forums.eagle.ru/member.php?u=90530)**: Concept, Advice & Testing. -- * **[Pikey](https://forums.eagle.ru/member.php?u=62835)**: Concept, Advice & Testing. -- * **[Gunterlund](http://forums.eagle.ru:8080/member.php?u=75036)**: Test case revision. -- * **[Whisper](http://forums.eagle.ru/member.php?u=3829): Testing. --- * **[Delta99](https://forums.eagle.ru/member.php?u=125166): Testing. +-- * **[Delta99](https://forums.eagle.ru/member.php?u=125166): Testing. -- -- === -- --- @module AI.AI_Cap +-- @module AI.AI_CAP -- @image AI_Combat_Air_Patrol.JPG - --- @type AI_CAP_ZONE -- @field Wrapper.Controllable#CONTROLLABLE AIControllable The @{Wrapper.Controllable} patrolling. --- @field Core.Zone#ZONE_BASE TargetZone The @{Zone} where the patrol needs to be executed. +-- @field Core.Zone#ZONE_BASE TargetZone The @{Core.Zone} where the patrol needs to be executed. -- @extends AI.AI_Patrol#AI_PATROL_ZONE - ---- Implements the core functions to patrol a @{Zone} by an AI @{Wrapper.Controllable} or @{Wrapper.Group} +--- Implements the core functions to patrol a @{Core.Zone} by an AI @{Wrapper.Controllable} or @{Wrapper.Group} -- and automatically engage any airborne enemies that are within a certain range or within a certain zone. -- -- ![Process](..\Presentations\AI_CAP\Dia3.JPG) @@ -106,15 +103,15 @@ -- that will define when the AI will engage with the detected airborne enemy targets. -- The range can be beyond or smaller than the range of the Patrol Zone. -- The range is applied at the position of the AI. --- Use the method @{AI.AI_CAP#AI_CAP_ZONE.SetEngageRange}() to define that range. +-- Use the method @{#AI_CAP_ZONE.SetEngageRange}() to define that range. -- -- ## 4. Set the Zone of Engagement -- -- ![Zone](..\Presentations\AI_CAP\Dia12.JPG) -- --- An optional @{Zone} can be set, +-- An optional @{Core.Zone} can be set, -- that will define when the AI will engage with the detected airborne enemy targets. --- Use the method @{AI.AI_Cap#AI_CAP_ZONE.SetEngageZone}() to define that Zone. +-- Use the method @{#AI_CAP_ZONE.SetEngageZone}() to define that Zone. -- -- === -- @@ -123,11 +120,9 @@ AI_CAP_ZONE = { ClassName = "AI_CAP_ZONE", } - - --- Creates a new AI_CAP_ZONE object -- @param #AI_CAP_ZONE self --- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed. +-- @param Core.Zone#ZONE_BASE PatrolZone The @{Core.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. -- @param DCS#Speed PatrolMinSpeed The minimum speed of the @{Wrapper.Controllable} in km/h. @@ -141,7 +136,7 @@ function AI_CAP_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude self.Accomplished = false self.Engaging = false - + self:AddTransition( { "Patrolling", "Engaging" }, "Engage", "Engaging" ) -- FSM_CONTROLLABLE Transition for type #AI_CAP_ZONE. --- OnBefore Transition Handler for Event Engage. @@ -152,7 +147,7 @@ function AI_CAP_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude -- @param #string Event The Event string. -- @param #string To The To State string. -- @return #boolean Return false to cancel Transition. - + --- OnAfter Transition Handler for Event Engage. -- @function [parent=#AI_CAP_ZONE] OnAfterEngage -- @param #AI_CAP_ZONE self @@ -160,11 +155,11 @@ function AI_CAP_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude -- @param #string From The From State string. -- @param #string Event The Event string. -- @param #string To The To State string. - + --- Synchronous Event Trigger for Event Engage. -- @function [parent=#AI_CAP_ZONE] Engage -- @param #AI_CAP_ZONE self - + --- Asynchronous Event Trigger for Event Engage. -- @function [parent=#AI_CAP_ZONE] __Engage -- @param #AI_CAP_ZONE self @@ -188,7 +183,7 @@ function AI_CAP_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude -- @param #string To The To State string. self:AddTransition( "Engaging", "Fired", "Engaging" ) -- FSM_CONTROLLABLE Transition for type #AI_CAP_ZONE. - + --- OnBefore Transition Handler for Event Fired. -- @function [parent=#AI_CAP_ZONE] OnBeforeFired -- @param #AI_CAP_ZONE self @@ -197,7 +192,7 @@ function AI_CAP_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude -- @param #string Event The Event string. -- @param #string To The To State string. -- @return #boolean Return false to cancel Transition. - + --- OnAfter Transition Handler for Event Fired. -- @function [parent=#AI_CAP_ZONE] OnAfterFired -- @param #AI_CAP_ZONE self @@ -205,11 +200,11 @@ function AI_CAP_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude -- @param #string From The From State string. -- @param #string Event The Event string. -- @param #string To The To State string. - + --- Synchronous Event Trigger for Event Fired. -- @function [parent=#AI_CAP_ZONE] Fired -- @param #AI_CAP_ZONE self - + --- Asynchronous Event Trigger for Event Fired. -- @function [parent=#AI_CAP_ZONE] __Fired -- @param #AI_CAP_ZONE self @@ -225,7 +220,7 @@ function AI_CAP_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude -- @param #string Event The Event string. -- @param #string To The To State string. -- @return #boolean Return false to cancel Transition. - + --- OnAfter Transition Handler for Event Destroy. -- @function [parent=#AI_CAP_ZONE] OnAfterDestroy -- @param #AI_CAP_ZONE self @@ -233,17 +228,16 @@ function AI_CAP_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude -- @param #string From The From State string. -- @param #string Event The Event string. -- @param #string To The To State string. - + --- Synchronous Event Trigger for Event Destroy. -- @function [parent=#AI_CAP_ZONE] Destroy -- @param #AI_CAP_ZONE self - + --- Asynchronous Event Trigger for Event Destroy. -- @function [parent=#AI_CAP_ZONE] __Destroy -- @param #AI_CAP_ZONE self -- @param #number Delay The delay in seconds. - self:AddTransition( "Engaging", "Abort", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_CAP_ZONE. --- OnBefore Transition Handler for Event Abort. @@ -254,7 +248,7 @@ function AI_CAP_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude -- @param #string Event The Event string. -- @param #string To The To State string. -- @return #boolean Return false to cancel Transition. - + --- OnAfter Transition Handler for Event Abort. -- @function [parent=#AI_CAP_ZONE] OnAfterAbort -- @param #AI_CAP_ZONE self @@ -262,11 +256,11 @@ function AI_CAP_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude -- @param #string From The From State string. -- @param #string Event The Event string. -- @param #string To The To State string. - + --- Synchronous Event Trigger for Event Abort. -- @function [parent=#AI_CAP_ZONE] Abort -- @param #AI_CAP_ZONE self - + --- Asynchronous Event Trigger for Event Abort. -- @function [parent=#AI_CAP_ZONE] __Abort -- @param #AI_CAP_ZONE self @@ -282,7 +276,7 @@ function AI_CAP_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude -- @param #string Event The Event string. -- @param #string To The To State string. -- @return #boolean Return false to cancel Transition. - + --- OnAfter Transition Handler for Event Accomplish. -- @function [parent=#AI_CAP_ZONE] OnAfterAccomplish -- @param #AI_CAP_ZONE self @@ -290,11 +284,11 @@ function AI_CAP_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude -- @param #string From The From State string. -- @param #string Event The Event string. -- @param #string To The To State string. - + --- Synchronous Event Trigger for Event Accomplish. -- @function [parent=#AI_CAP_ZONE] Accomplish -- @param #AI_CAP_ZONE self - + --- Asynchronous Event Trigger for Event Accomplish. -- @function [parent=#AI_CAP_ZONE] __Accomplish -- @param #AI_CAP_ZONE self @@ -303,7 +297,6 @@ function AI_CAP_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude return self end - --- Set the Engage Zone which defines where the AI will engage bogies. -- @param #AI_CAP_ZONE self -- @param Core.Zone#ZONE EngageZone The zone where the AI is performing CAP. @@ -311,7 +304,7 @@ end function AI_CAP_ZONE:SetEngageZone( EngageZone ) self:F2() - if EngageZone then + if EngageZone then self.EngageZone = EngageZone else self.EngageZone = nil @@ -346,7 +339,6 @@ function AI_CAP_ZONE:onafterStart( Controllable, From, Event, To ) end - --- @param AI.AI_CAP#AI_CAP_ZONE -- @param Wrapper.Group#GROUP EngageGroup function AI_CAP_ZONE.EngageRoute( EngageGroup, Fsm ) @@ -358,8 +350,6 @@ function AI_CAP_ZONE.EngageRoute( EngageGroup, Fsm ) end end - - --- @param #AI_CAP_ZONE self -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. -- @param #string From The From State string. @@ -380,11 +370,11 @@ end function AI_CAP_ZONE:onafterDetected( Controllable, From, Event, To ) if From ~= "Engaging" then - + local Engage = false - + for DetectedUnit, Detected in pairs( self.DetectedUnits ) do - + local DetectedUnit = DetectedUnit -- Wrapper.Unit#UNIT self:T( DetectedUnit ) if DetectedUnit:IsAlive() and DetectedUnit:IsAir() then @@ -392,7 +382,7 @@ function AI_CAP_ZONE:onafterDetected( Controllable, From, Event, To ) break end end - + if Engage == true then self:F( 'Detected -> Engaging' ) self:__Engage( 1 ) @@ -400,7 +390,6 @@ function AI_CAP_ZONE:onafterDetected( Controllable, From, Event, To ) end end - --- @param #AI_CAP_ZONE self -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. -- @param #string From The From State string. @@ -411,9 +400,6 @@ function AI_CAP_ZONE:onafterAbort( Controllable, From, Event, To ) self:__Route( 1 ) end - - - --- @param #AI_CAP_ZONE self -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. -- @param #string From The From State string. @@ -427,24 +413,23 @@ function AI_CAP_ZONE:onafterEngage( Controllable, From, Event, To ) --- Calculate the current route point. local CurrentVec2 = self.Controllable:GetVec2() - + if not CurrentVec2 then return self end - + --DONE: Create GetAltitude function for GROUP, and delete GetUnit(1). local CurrentAltitude = self.Controllable:GetAltitude() local CurrentPointVec3 = POINT_VEC3:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y ) local ToEngageZoneSpeed = self.PatrolMaxSpeed - local CurrentRoutePoint = CurrentPointVec3:WaypointAir( - self.PatrolAltType, - POINT_VEC3.RoutePointType.TurningPoint, - POINT_VEC3.RoutePointAction.TurningPoint, - ToEngageZoneSpeed, - true + local CurrentRoutePoint = CurrentPointVec3:WaypointAir( + self.PatrolAltType, + POINT_VEC3.RoutePointType.TurningPoint, + POINT_VEC3.RoutePointAction.TurningPoint, + ToEngageZoneSpeed, + true ) - + EngageRoute[#EngageRoute+1] = CurrentRoutePoint - --- Find a random 2D point in PatrolZone. local ToTargetVec2 = self.PatrolZone:GetRandomVec2() self:T2( ToTargetVec2 ) @@ -453,17 +438,17 @@ function AI_CAP_ZONE:onafterEngage( Controllable, From, Event, To ) local ToTargetAltitude = math.random( self.EngageFloorAltitude, self.EngageCeilingAltitude ) local ToTargetSpeed = math.random( self.PatrolMinSpeed, self.PatrolMaxSpeed ) self:T2( { self.PatrolMinSpeed, self.PatrolMaxSpeed, ToTargetSpeed } ) - + --- Obtain a 3D @{Point} from the 2D point + altitude. local ToTargetPointVec3 = POINT_VEC3:New( ToTargetVec2.x, ToTargetAltitude, ToTargetVec2.y ) - + --- Create a route point of type air. - local ToPatrolRoutePoint = ToTargetPointVec3:WaypointAir( - self.PatrolAltType, - POINT_VEC3.RoutePointType.TurningPoint, - POINT_VEC3.RoutePointAction.TurningPoint, - ToTargetSpeed, - true + local ToPatrolRoutePoint = ToTargetPointVec3:WaypointAir( + self.PatrolAltType, + POINT_VEC3.RoutePointType.TurningPoint, + POINT_VEC3.RoutePointAction.TurningPoint, + ToTargetSpeed, + true ) EngageRoute[#EngageRoute+1] = ToPatrolRoutePoint @@ -482,7 +467,7 @@ function AI_CAP_ZONE:onafterEngage( Controllable, From, Event, To ) self:F( {"Within Zone and Engaging ", DetectedUnit } ) AttackTasks[#AttackTasks+1] = Controllable:TaskAttackUnit( DetectedUnit ) end - else + else if self.EngageRange then if DetectedUnit:GetPointVec3():Get2DDistance(Controllable:GetPointVec3() ) <= self.EngageRange then self:F( {"Within Range and Engaging", DetectedUnit } ) @@ -506,12 +491,12 @@ function AI_CAP_ZONE:onafterEngage( Controllable, From, Event, To ) AttackTasks[#AttackTasks+1] = Controllable:TaskFunction( "AI_CAP_ZONE.EngageRoute", self ) EngageRoute[1].task = Controllable:TaskCombo( AttackTasks ) - + self:SetDetectionDeactivated() end - + Controllable:Route( EngageRoute, 0.5 ) - + end end diff --git a/Moose Development/Moose/AI/AI_CAS.lua b/Moose Development/Moose/AI/AI_CAS.lua index de6ab65c1..d92c6baa4 100644 --- a/Moose Development/Moose/AI/AI_CAS.lua +++ b/Moose Development/Moose/AI/AI_CAS.lua @@ -1,4 +1,4 @@ ---- **AI** -- Perform Close Air Support (CAS) near friendlies. +--- **AI** - Perform Close Air Support (CAS) near friendlies. -- -- **Features:** -- @@ -28,16 +28,16 @@ -- -- === -- --- @module AI.AI_Cas +-- @module AI.AI_CAS -- @image AI_Close_Air_Support.JPG --- AI_CAS_ZONE class -- @type AI_CAS_ZONE -- @field Wrapper.Controllable#CONTROLLABLE AIControllable The @{Wrapper.Controllable} patrolling. --- @field Core.Zone#ZONE_BASE TargetZone The @{Zone} where the patrol needs to be executed. +-- @field Core.Zone#ZONE_BASE TargetZone The @{Core.Zone} where the patrol needs to be executed. -- @extends AI.AI_Patrol#AI_PATROL_ZONE ---- Implements the core functions to provide Close Air Support in an Engage @{Zone} by an AIR @{Wrapper.Controllable} or @{Wrapper.Group}. +--- Implements the core functions to provide Close Air Support in an Engage @{Core.Zone} by an AIR @{Wrapper.Controllable} or @{Wrapper.Group}. -- The AI_CAS_ZONE runs a process. It holds an AI in a Patrol Zone and when the AI is commanded to engage, it will fly to an Engage Zone. -- -- ![HoldAndEngage](..\Presentations\AI_CAS\Dia3.JPG) @@ -130,7 +130,7 @@ AI_CAS_ZONE = { --- Creates a new AI_CAS_ZONE object -- @param #AI_CAS_ZONE self --- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed. +-- @param Core.Zone#ZONE_BASE PatrolZone The @{Core.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. -- @param DCS#Speed PatrolMinSpeed The minimum speed of the @{Wrapper.Controllable} in km/h. @@ -496,7 +496,7 @@ function AI_CAS_ZONE:onafterEngage( Controllable, From, Event, To, AttackTasks[#AttackTasks+1] = Controllable:TaskFunction( "AI_CAS_ZONE.EngageRoute", self ) EngageRoute[#EngageRoute].task = Controllable:TaskCombo( AttackTasks ) - --- Define a random point in the @{Zone}. The AI will fly to that point within the zone. + --- Define a random point in the @{Core.Zone}. The AI will fly to that point within the zone. --- Find a random 2D point in EngageZone. local ToTargetVec2 = self.EngageZone:GetRandomVec2() diff --git a/Moose Development/Moose/AI/AI_Cargo_Dispatcher_Airplane.lua b/Moose Development/Moose/AI/AI_Cargo_Dispatcher_Airplane.lua index 11df8c188..81121e357 100644 --- a/Moose Development/Moose/AI/AI_Cargo_Dispatcher_Airplane.lua +++ b/Moose Development/Moose/AI/AI_Cargo_Dispatcher_Airplane.lua @@ -1,4 +1,4 @@ ---- **AI** -- (R2.4) - Models the intelligent transportation of infantry and other cargo using Planes. +--- **AI** - Models the intelligent transportation of infantry and other cargo using Planes. -- -- ## Features: -- diff --git a/Moose Development/Moose/AI/AI_Cargo_Dispatcher_Helicopter.lua b/Moose Development/Moose/AI/AI_Cargo_Dispatcher_Helicopter.lua index bba9b7108..33e6ca0d1 100644 --- a/Moose Development/Moose/AI/AI_Cargo_Dispatcher_Helicopter.lua +++ b/Moose Development/Moose/AI/AI_Cargo_Dispatcher_Helicopter.lua @@ -1,4 +1,4 @@ ---- **AI** -- (2.4) - Models the intelligent transportation of infantry and other cargo using Helicopters. +--- **AI** - Models the intelligent transportation of infantry and other cargo using Helicopters. -- -- ## Features: -- diff --git a/Moose Development/Moose/AI/AI_Cargo_Dispatcher_Ship.lua b/Moose Development/Moose/AI/AI_Cargo_Dispatcher_Ship.lua index 70f325f62..36604f30b 100644 --- a/Moose Development/Moose/AI/AI_Cargo_Dispatcher_Ship.lua +++ b/Moose Development/Moose/AI/AI_Cargo_Dispatcher_Ship.lua @@ -1,4 +1,4 @@ ---- **AI** -- (2.5.1) - Models the intelligent transportation of infantry and other cargo using Ships +--- **AI** - Models the intelligent transportation of infantry and other cargo using Ships. -- -- ## Features: -- @@ -37,14 +37,14 @@ -- -- This will be particularly helpful in order to determine how to **Tailor the different cargo handling events**. -- --- The AI_CARGO_DISPATCHER_SHIP class uses the @{Cargo.Cargo} capabilities within the MOOSE framwork. +-- The AI_CARGO_DISPATCHER_SHIP class uses the @{Cargo.Cargo} capabilities within the MOOSE framework. -- Also ensure that you fully understand how to declare and setup Cargo objects within the MOOSE framework before using this class. -- CARGO derived objects must generally be declared within the mission to make the AI_CARGO_DISPATCHER_SHIP object recognize the cargo. -- -- -- # 1) AI_CARGO_DISPATCHER_SHIP constructor. -- --- * @{AI_CARGO_DISPATCHER_SHIP.New}(): Creates a new AI_CARGO_DISPATCHER_SHIP object. +-- * @{#AI_CARGO_DISPATCHER_SHIP.New}(): Creates a new AI_CARGO_DISPATCHER_SHIP object. -- -- --- -- diff --git a/Moose Development/Moose/AI/AI_Cargo_Ship.lua b/Moose Development/Moose/AI/AI_Cargo_Ship.lua index 37c7da57a..8722e5026 100644 --- a/Moose Development/Moose/AI/AI_Cargo_Ship.lua +++ b/Moose Development/Moose/AI/AI_Cargo_Ship.lua @@ -1,4 +1,4 @@ ---- **AI** -- (R2.5.1) - Models the intelligent transportation of infantry and other cargo. +--- **AI** - Models the intelligent transportation of infantry and other cargo. -- -- === -- @@ -46,12 +46,12 @@ -- -- ## Cargo deployment. -- --- Using the @{AI_CARGO_SHIP.Deploy}() method, you are able to direct the Ship towards a Deploy zone to unboard/unload the cargo at the +-- Using the @{#AI_CARGO_SHIP.Deploy}() method, you are able to direct the Ship towards a Deploy zone to unboard/unload the cargo at the -- specified coordinate. The Ship will follow the Shipping Lane to ensure consistent cargo transportation within the simulation environment. -- -- ## Cargo pickup. -- --- Using the @{AI_CARGO_SHIP.Pickup}() method, you are able to direct the Ship towards a Pickup zone to board/load the cargo at the specified +-- Using the @{#AI_CARGO_SHIP.Pickup}() method, you are able to direct the Ship towards a Pickup zone to board/load the cargo at the specified -- coordinate. The Ship will follow the Shipping Lane to ensure consistent cargo transportation within the simulation environment. -- -- diff --git a/Moose Development/Moose/AI/AI_Escort.lua b/Moose Development/Moose/AI/AI_Escort.lua index af3a4c304..0ca7a05eb 100644 --- a/Moose Development/Moose/AI/AI_Escort.lua +++ b/Moose Development/Moose/AI/AI_Escort.lua @@ -1,4 +1,4 @@ ---- **Functional** -- Taking the lead of AI escorting your flight or of other AI. +--- **AI** - Taking the lead of AI escorting your flight or of other AI. -- -- === -- diff --git a/Moose Development/Moose/AI/AI_Escort_Dispatcher_Request.lua b/Moose Development/Moose/AI/AI_Escort_Dispatcher_Request.lua index 33c614d4a..25d29b7e5 100644 --- a/Moose Development/Moose/AI/AI_Escort_Dispatcher_Request.lua +++ b/Moose Development/Moose/AI/AI_Escort_Dispatcher_Request.lua @@ -11,7 +11,7 @@ -- -- === -- --- @module AI.AI_ESCORT_DISPATCHER_REQUEST +-- @module AI.AI_Escort_Dispatcher_Request -- @image MOOSE.JPG diff --git a/Moose Development/Moose/AI/AI_Escort_Request.lua b/Moose Development/Moose/AI/AI_Escort_Request.lua index 0994a143c..c7d109fff 100644 --- a/Moose Development/Moose/AI/AI_Escort_Request.lua +++ b/Moose Development/Moose/AI/AI_Escort_Request.lua @@ -1,4 +1,4 @@ ---- **Functional** -- Taking the lead of AI escorting your flight or of other AI, upon request using the menu. +--- **AI** - Taking the lead of AI escorting your flight or of other AI, upon request using the menu. -- -- === -- @@ -143,7 +143,7 @@ -- -- === -- --- @module AI.AI_Escort +-- @module AI.AI_Escort_Request -- @image Escorting.JPG diff --git a/Moose Development/Moose/AI/AI_Formation.lua b/Moose Development/Moose/AI/AI_Formation.lua index aaf4fbe54..657f8aa2a 100644 --- a/Moose Development/Moose/AI/AI_Formation.lua +++ b/Moose Development/Moose/AI/AI_Formation.lua @@ -1,4 +1,4 @@ ---- **AI** -- Build large airborne formations of aircraft. +--- **AI** - Build large airborne formations of aircraft. -- -- **Features:** -- @@ -41,7 +41,7 @@ --- Build large formations, make AI follow a @{Wrapper.Client#CLIENT} (player) leader or a @{Wrapper.Unit#UNIT} (AI) leader. -- --- AI_FORMATION makes AI @{GROUP}s fly in formation of various compositions. +-- AI_FORMATION makes AI @{Wrapper.Group#GROUP}s fly in formation of various compositions. -- The AI_FORMATION class models formations in a different manner than the internal DCS formation logic!!! -- The purpose of the class is to: -- diff --git a/Moose Development/Moose/AI/AI_Patrol.lua b/Moose Development/Moose/AI/AI_Patrol.lua index 9fd07539a..beba94951 100644 --- a/Moose Development/Moose/AI/AI_Patrol.lua +++ b/Moose Development/Moose/AI/AI_Patrol.lua @@ -1,4 +1,4 @@ ---- **AI** -- Perform Air Patrolling for airplanes. +--- **AI** - Perform Air Patrolling for airplanes. -- -- **Features:** -- @@ -38,7 +38,7 @@ --- AI_PATROL_ZONE class -- @type AI_PATROL_ZONE -- @field Wrapper.Controllable#CONTROLLABLE AIControllable The @{Wrapper.Controllable} patrolling. --- @field Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed. +-- @field Core.Zone#ZONE_BASE PatrolZone The @{Core.Zone} where the patrol needs to be executed. -- @field DCS#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol. -- @field DCS#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol. -- @field DCS#Speed PatrolMinSpeed The minimum speed of the @{Wrapper.Controllable} in km/h. @@ -46,7 +46,7 @@ -- @field Core.Spawn#SPAWN CoordTest -- @extends Core.Fsm#FSM_CONTROLLABLE ---- Implements the core functions to patrol a @{Zone} by an AI @{Wrapper.Controllable} or @{Wrapper.Group}. +--- Implements the core functions to patrol a @{Core.Zone} by an AI @{Wrapper.Controllable} or @{Wrapper.Group}. -- -- ![Process](..\Presentations\AI_PATROL\Dia3.JPG) -- @@ -135,15 +135,15 @@ -- When the AI is out of fuel, it is required that a new AI is started, before the old AI can return to the home base. -- Therefore, with a parameter and a calculation of the distance to the home base, the fuel threshold is calculated. -- When the fuel threshold is reached, the AI will continue for a given time its patrol task in orbit, --- while a new AI is targetted to the AI_PATROL_ZONE. +-- while a new AI is targeted to the AI_PATROL_ZONE. -- Once the time is finished, the old AI will return to the base. --- Use the method @{#AI_PATROL_ZONE.ManageFuel}() to have this proces in place. +-- Use the method @{#AI_PATROL_ZONE.ManageFuel}() to have this process in place. -- -- ## 7. Manage "damage" behaviour of the AI in the AI_PATROL_ZONE -- -- When the AI is damaged, it is required that a new AIControllable is started. However, damage cannon be foreseen early on. -- Therefore, when the damage threshold is reached, the AI will return immediately to the home base (RTB). --- Use the method @{#AI_PATROL_ZONE.ManageDamage}() to have this proces in place. +-- Use the method @{#AI_PATROL_ZONE.ManageDamage}() to have this process in place. -- -- === -- @@ -154,7 +154,7 @@ AI_PATROL_ZONE = { --- Creates a new AI_PATROL_ZONE object -- @param #AI_PATROL_ZONE self --- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed. +-- @param Core.Zone#ZONE_BASE PatrolZone The @{Core.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. -- @param DCS#Speed PatrolMinSpeed The minimum speed of the @{Wrapper.Controllable} in km/h. @@ -170,27 +170,27 @@ function AI_PATROL_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltit -- Inherits from BASE local self = BASE:Inherit( self, FSM_CONTROLLABLE:New() ) -- #AI_PATROL_ZONE - - + + self.PatrolZone = PatrolZone self.PatrolFloorAltitude = PatrolFloorAltitude self.PatrolCeilingAltitude = PatrolCeilingAltitude self.PatrolMinSpeed = PatrolMinSpeed self.PatrolMaxSpeed = PatrolMaxSpeed - + -- defafult PatrolAltType to "BARO" if not specified self.PatrolAltType = PatrolAltType or "BARO" - + self:SetRefreshTimeInterval( 30 ) - + self.CheckStatus = true - + self:ManageFuel( .2, 60 ) self:ManageDamage( 1 ) - + self.DetectedUnits = {} -- This table contains the targets detected during patrol. - + self:SetStartState( "None" ) self:AddTransition( "*", "Stop", "Stopped" ) @@ -228,7 +228,7 @@ function AI_PATROL_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltit -- @param #string From The From State string. -- @param #string Event The Event string. -- @param #string To The To State string. - + --- Synchronous Event Trigger for Event Stop. -- @function [parent=#AI_PATROL_ZONE] Stop -- @param #AI_PATROL_ZONE self @@ -256,7 +256,7 @@ function AI_PATROL_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltit -- @param #string From The From State string. -- @param #string Event The Event string. -- @param #string To The To State string. - + --- Synchronous Event Trigger for Event Start. -- @function [parent=#AI_PATROL_ZONE] Start -- @param #AI_PATROL_ZONE self @@ -329,7 +329,7 @@ function AI_PATROL_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltit -- @param #string From The From State string. -- @param #string Event The Event string. -- @param #string To The To State string. - + --- Synchronous Event Trigger for Event Status. -- @function [parent=#AI_PATROL_ZONE] Status -- @param #AI_PATROL_ZONE self @@ -413,7 +413,7 @@ function AI_PATROL_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltit -- @param #string From The From State string. -- @param #string Event The Event string. -- @param #string To The To State string. - + --- Synchronous Event Trigger for Event RTB. -- @function [parent=#AI_PATROL_ZONE] RTB -- @param #AI_PATROL_ZONE self @@ -441,11 +441,11 @@ function AI_PATROL_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltit -- @param #string To The To State string. self:AddTransition( "*", "Reset", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_PATROL_ZONE. - + self:AddTransition( "*", "Eject", "*" ) self:AddTransition( "*", "Crash", "Crashed" ) self:AddTransition( "*", "PilotDead", "*" ) - + return self end @@ -459,7 +459,7 @@ end -- @return #AI_PATROL_ZONE self function AI_PATROL_ZONE:SetSpeed( PatrolMinSpeed, PatrolMaxSpeed ) self:F2( { PatrolMinSpeed, PatrolMaxSpeed } ) - + self.PatrolMinSpeed = PatrolMinSpeed self.PatrolMaxSpeed = PatrolMaxSpeed end @@ -473,7 +473,7 @@ end -- @return #AI_PATROL_ZONE self function AI_PATROL_ZONE:SetAltitude( PatrolFloorAltitude, PatrolCeilingAltitude ) self:F2( { PatrolFloorAltitude, PatrolCeilingAltitude } ) - + self.PatrolFloorAltitude = PatrolFloorAltitude self.PatrolCeilingAltitude = PatrolCeilingAltitude end @@ -582,7 +582,7 @@ end --- When the AI is out of fuel, it is required that a new AI is started, before the old AI can return to the home base. -- Therefore, with a parameter and a calculation of the distance to the home base, the fuel threshold is calculated. --- When the fuel threshold is reached, the AI will continue for a given time its patrol task in orbit, while a new AIControllable is targetted to the AI_PATROL_ZONE. +-- When the fuel threshold is reached, the AI will continue for a given time its patrol task in orbit, while a new AIControllable is targeted to the AI_PATROL_ZONE. -- Once the time is finished, the old AI will return to the base. -- @param #AI_PATROL_ZONE self -- @param #number PatrolFuelThresholdPercentage The threshold in percentage (between 0 and 1) when the AIControllable is considered to get out of fuel. @@ -592,7 +592,7 @@ function AI_PATROL_ZONE:ManageFuel( PatrolFuelThresholdPercentage, PatrolOutOfFu self.PatrolFuelThresholdPercentage = PatrolFuelThresholdPercentage self.PatrolOutOfFuelOrbitTime = PatrolOutOfFuelOrbitTime - + return self end @@ -609,28 +609,28 @@ function AI_PATROL_ZONE:ManageDamage( PatrolDamageThreshold ) self.PatrolManageDamage = true self.PatrolDamageThreshold = PatrolDamageThreshold - + return self end ---- Defines a new patrol route using the @{Process_PatrolZone} parameters and settings. +--- Defines a new patrol route using the @{#AI_PATROL_ZONE} parameters and settings. -- @param #AI_PATROL_ZONE self --- @return #AI_PATROL_ZONE self -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. -- @param #string From The From State string. -- @param #string Event The Event string. -- @param #string To The To State string. +-- @return #AI_PATROL_ZONE self function AI_PATROL_ZONE:onafterStart( Controllable, From, Event, To ) self:F2() self:__Route( 1 ) -- Route to the patrol point. The asynchronous trigger is important, because a spawned group and units takes at least one second to come live. self:__Status( 60 ) -- Check status status every 30 seconds. self:SetDetectionActivated() - + self:HandleEvent( EVENTS.PilotDead, self.OnPilotDead ) self:HandleEvent( EVENTS.Crash, self.OnCrash ) self:HandleEvent( EVENTS.Ejection, self.OnEjection ) - + Controllable:OptionROEHoldFire() Controllable:OptionROTVertical() @@ -667,12 +667,12 @@ function AI_PATROL_ZONE:onafterDetect( Controllable, From, Event, To ) if TargetObject and TargetObject:isExist() and TargetObject.id_ < 50000000 then local TargetUnit = UNIT:Find( TargetObject ) - + -- Check that target is alive due to issue https://github.com/FlightControl-Master/MOOSE/issues/1234 if TargetUnit and TargetUnit:IsAlive() then - + local TargetUnitName = TargetUnit:GetName() - + if self.DetectionZone then if TargetUnit:IsInZone( self.DetectionZone ) then self:T( {"Detected ", TargetUnit } ) @@ -687,13 +687,13 @@ function AI_PATROL_ZONE:onafterDetect( Controllable, From, Event, To ) end Detected = true end - + end end end self:__Detect( -self.DetectInterval ) - + if Detected == true then self:__Detected( 1.5 ) end @@ -701,7 +701,7 @@ function AI_PATROL_ZONE:onafterDetect( Controllable, From, Event, To ) end --- @param Wrapper.Controllable#CONTROLLABLE AIControllable --- This statis method is called from the route path within the last task at the last waaypoint of the Controllable. +-- This static method is called from the route path within the last task at the last waypoint of the Controllable. -- Note that this method is required, as triggers the next route when patrolling for the Controllable. function AI_PATROL_ZONE:_NewPatrolRoute( AIControllable ) @@ -710,7 +710,7 @@ function AI_PATROL_ZONE:_NewPatrolRoute( AIControllable ) end ---- Defines a new patrol route using the @{Process_PatrolZone} parameters and settings. +--- Defines a new patrol route using the @{#AI_PATROL_ZONE} parameters and settings. -- @param #AI_PATROL_ZONE self -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. -- @param #string From The From State string. @@ -729,7 +729,7 @@ function AI_PATROL_ZONE:onafterRoute( Controllable, From, Event, To ) if self.Controllable:IsAlive() and life > 1 then -- Determine if the AIControllable is within the PatrolZone. -- If not, make a waypoint within the to that the AIControllable will fly at maximum speed to that point. - + local PatrolRoute = {} -- Calculate the current route point of the controllable as the start point of the route. @@ -775,7 +775,7 @@ function AI_PATROL_ZONE:onafterRoute( Controllable, From, Event, To ) end - --- Define a random point in the @{Zone}. The AI will fly to that point within the zone. + --- Define a random point in the @{Core.Zone}. The AI will fly to that point within the zone. --- Find a random 2D point in PatrolZone. local ToTargetVec2 = self.PatrolZone:GetRandomVec2() diff --git a/Moose Development/Moose/Actions/Act_Account.lua b/Moose Development/Moose/Actions/Act_Account.lua index 835b52871..ef2e6d15d 100644 --- a/Moose Development/Moose/Actions/Act_Account.lua +++ b/Moose Development/Moose/Actions/Act_Account.lua @@ -1,10 +1,10 @@ ---- **Actions** - ACT_ACCOUNT_ classes **account for** (detect, count & report) various DCS events occuring on @{Wrapper.Unit}s. +--- **Actions** - ACT_ACCOUNT_ classes **account for** (detect, count & report) various DCS events occurring on UNITs. -- -- ![Banner Image](..\Presentations\ACT_ACCOUNT\Dia1.JPG) -- -- === -- --- @module Actions.Account +-- @module Actions.Act_Account -- @image MOOSE.JPG do -- ACT_ACCOUNT @@ -20,7 +20,7 @@ do -- ACT_ACCOUNT -- -- ### ACT_ACCOUNT States -- - -- * **Asigned**: The player is assigned. + -- * **Assigned**: The player is assigned. -- * **Waiting**: Waiting for an event. -- * **Report**: Reporting. -- * **Account**: Account for an event. @@ -104,7 +104,6 @@ do -- ACT_ACCOUNT self:__Wait( 1 ) end - --- StateMachine callback function -- @param #ACT_ACCOUNT self -- @param Wrapper.Unit#UNIT ProcessUnit @@ -141,7 +140,7 @@ do -- ACT_ACCOUNT_DEADS --- # @{#ACT_ACCOUNT_DEADS} FSM class, extends @{Core.Fsm.Account#ACT_ACCOUNT} -- -- The ACT_ACCOUNT_DEADS class accounts (detects, counts and reports) successful kills of DCS units. - -- The process is given a @{Set} of units that will be tracked upon successful destruction. + -- The process is given a @{Core.Set} of units that will be tracked upon successful destruction. -- The process will end after each target has been successfully destroyed. -- Each successful dead will trigger an Account state transition that can be scored, modified or administered. -- @@ -157,7 +156,6 @@ do -- ACT_ACCOUNT_DEADS ClassName = "ACT_ACCOUNT_DEADS", } - --- Creates a new DESTROY process. -- @param #ACT_ACCOUNT_DEADS self -- @param Core.Set#SET_UNIT TargetSetUnit @@ -195,7 +193,6 @@ do -- ACT_ACCOUNT_DEADS self:GetCommandCenter():MessageTypeToGroup( MessageText, ProcessUnit:GetGroup(), MESSAGE.Type.Information ) end - --- StateMachine callback function -- @param #ACT_ACCOUNT_DEADS self -- @param Wrapper.Unit#UNIT ProcessUnit @@ -270,7 +267,6 @@ do -- ACT_ACCOUNT_DEADS end end - --- DCS Events --- @param #ACT_ACCOUNT_DEADS self diff --git a/Moose Development/Moose/Actions/Act_Assign.lua b/Moose Development/Moose/Actions/Act_Assign.lua index c6748cba8..8ac364bbe 100644 --- a/Moose Development/Moose/Actions/Act_Assign.lua +++ b/Moose Development/Moose/Actions/Act_Assign.lua @@ -77,7 +77,7 @@ -- -- === -- --- @module Actions.Assign +-- @module Actions.Act_Assign -- @image MOOSE.JPG diff --git a/Moose Development/Moose/Actions/Act_Assist.lua b/Moose Development/Moose/Actions/Act_Assist.lua index fb0e81d6b..07d990fb3 100644 --- a/Moose Development/Moose/Actions/Act_Assist.lua +++ b/Moose Development/Moose/Actions/Act_Assist.lua @@ -50,7 +50,7 @@ -- -- # 1) @{#ACT_ASSIST_SMOKE_TARGETS_ZONE} class, extends @{Core.Fsm.Route#ACT_ASSIST} -- --- The ACT_ASSIST_SMOKE_TARGETS_ZONE class implements the core functions to smoke targets in a @{Zone}. +-- The ACT_ASSIST_SMOKE_TARGETS_ZONE class implements the core functions to smoke targets in a @{Core.Zone}. -- The targets are smoked within a certain range around each target, simulating a realistic smoking behaviour. -- At random intervals, a new target is smoked. -- @@ -60,7 +60,7 @@ -- -- === -- --- @module Actions.Assist +-- @module Actions.Act_Assist -- @image MOOSE.JPG diff --git a/Moose Development/Moose/Actions/Act_Route.lua b/Moose Development/Moose/Actions/Act_Route.lua index 7f075b420..faa9c40b9 100644 --- a/Moose Development/Moose/Actions/Act_Route.lua +++ b/Moose Development/Moose/Actions/Act_Route.lua @@ -62,7 +62,7 @@ -- -- # 1) @{#ACT_ROUTE_ZONE} class, extends @{Core.Fsm.Route#ACT_ROUTE} -- --- The ACT_ROUTE_ZONE class implements the core functions to route an AIR @{Wrapper.Controllable} player @{Wrapper.Unit} to a @{Zone}. +-- The ACT_ROUTE_ZONE class implements the core functions to route an AIR @{Wrapper.Controllable} player @{Wrapper.Unit} to a @{Core.Zone}. -- The player receives on perioding times messages with the coordinates of the route to follow. -- Upon arrival at the zone, a confirmation of arrival is sent, and the process will be ended. -- @@ -72,7 +72,7 @@ -- -- === -- --- @module Actions.Route +-- @module Actions.Act_Route -- @image MOOSE.JPG diff --git a/Moose Development/Moose/Cargo/Cargo.lua b/Moose Development/Moose/Cargo/Cargo.lua index e23e43199..0d2d53ef8 100644 --- a/Moose Development/Moose/Cargo/Cargo.lua +++ b/Moose Development/Moose/Cargo/Cargo.lua @@ -66,7 +66,7 @@ -- you can board the cargo into the carrier `CargoCarrier`. -- Simple, isn't it? Told you, and this is only the beginning. -- --- The boarding, unboarding, loading, unloading of cargo is however something that is not meant to be coded manualy by mission designers. +-- The boarding, unboarding, loading, unloading of cargo is however something that is not meant to be coded manually by mission designers. -- It would be too low-level and not end-user friendly to deal with cargo handling complexity. -- Things can become really complex if you want to make cargo being handled and behave in multiple scenarios. -- @@ -77,8 +77,8 @@ -- -- ## 3.1) AI Cargo handlers. -- --- - @{AI.AI_Cargo_APC} will create for you the capatility to make an APC group handle cargo. --- - @{AI.AI_Cargo_Helicopter} will create for you the capatility to make a Helicopter group handle cargo. +-- - @{AI.AI_Cargo_APC} will create for you the capability to make an APC group handle cargo. +-- - @{AI.AI_Cargo_Helicopter} will create for you the capability to make a Helicopter group handle cargo. -- -- -- ## 3.2) AI Cargo transportation dispatchers. @@ -86,7 +86,7 @@ -- There are also dispatchers that make AI work together to transport cargo automatically!!! -- -- - @{AI.AI_Cargo_Dispatcher_APC} derived classes will create for your dynamic cargo handlers controlled by AI ground vehicle groups (APCs) to transport cargo between sites. --- - @{AI.AI_Cargo_Dispatcher_Helicopters} derived classes will create for your dynamic cargo handlers controlled by AI helicpter groups to transport cargo between sites. +-- - @{AI.AI_Cargo_Dispatcher_Helicopters} derived classes will create for your dynamic cargo handlers controlled by AI helicopter groups to transport cargo between sites. -- -- ## 3.3) Cargo transportation tasking. -- @@ -94,7 +94,7 @@ -- -- - @{Tasking.Task_CARGO} derived classes will create for you cargo transportation tasks, that allow human players to interact with MOOSE cargo objects to complete tasks. -- --- Please refer to the documentation reflected within these modules to understand the detailed capabilties. +-- Please refer to the documentation reflected within these modules to understand the detailed capabilities. -- -- # 4) Cargo SETs. -- @@ -228,7 +228,7 @@ -- `StaticName #CARGO(T=CargoTypeName,C=Category,RR=Range,NR=Range)` -- -- * **T=** Provide a text that contains the type name of the cargo object. This type name can be used to filter cargo within a SET_CARGO object. --- * **C=** Provide either `CRATE` or `SLING` to have this static created as a CARGO_CRATE or CARGO_SLINGLOAD respectivly. +-- * **C=** Provide either `CRATE` or `SLING` to have this static created as a CARGO_CRATE or CARGO_SLINGLOAD respectively. -- * **RR=** Provide the minimal range in meters when the report to the carrier, and board to the carrier. -- Note that this option is optional, so can be omitted. The default value of the RR is 250 meters. -- * **NR=** Provide the maximum range in meters when the cargo units will be boarded within the carrier during boarding. @@ -377,7 +377,7 @@ do -- CARGO -- @field #boolean Moveable This flag defines if the cargo is moveable. -- @field #boolean Representable This flag defines if the cargo can be represented by a DCS Unit. -- @field #boolean Containable This flag defines if the cargo can be contained within a DCS Unit. - + --- Defines the core functions that defines a cargo object within MOOSE. -- -- A cargo is a **logical object** defined that is available for transport, and has a life status within a simulation. @@ -430,8 +430,7 @@ do -- CARGO --- @type CARGO.CargoObjects -- @map < #string, Wrapper.Positionable#POSITIONABLE > The alive POSITIONABLE objects representing the the cargo. - - + --- CARGO Constructor. This class is an abstract class and should not be instantiated. -- @param #CARGO self -- @param #string Type @@ -441,10 +440,10 @@ do -- CARGO -- @param #number NearRadius (optional) -- @return #CARGO function CARGO:New( Type, Name, Weight, LoadRadius, NearRadius ) --R2.1 - + local self = BASE:Inherit( self, FSM:New() ) -- #CARGO self:F( { Type, Name, Weight, LoadRadius, NearRadius } ) - + self:SetStartState( "UnLoaded" ) self:AddTransition( { "UnLoaded", "Boarding" }, "Board", "Boarding" ) self:AddTransition( "Boarding" , "Boarding", "Boarding" ) @@ -459,7 +458,7 @@ do -- CARGO self:AddTransition( "*", "Destroyed", "Destroyed" ) self:AddTransition( "*", "Respawn", "UnLoaded" ) self:AddTransition( "*", "Reset", "UnLoaded" ) - + self.Type = Type self.Name = Name self.Weight = Weight or 0 @@ -471,31 +470,29 @@ do -- CARGO self.Containable = false self.CargoLimit = 0 - + self.LoadRadius = LoadRadius or 500 --self.NearRadius = NearRadius or 25 - + self:SetDeployed( false ) - + self.CargoScheduler = SCHEDULER:New() - + CARGOS[self.Name] = self - - + return self end - - + --- Find a CARGO in the _DATABASE. -- @param #CARGO self -- @param #string CargoName The Cargo Name. -- @return #CARGO self function CARGO:FindByName( CargoName ) - + local CargoFound = _DATABASE:FindCargo( CargoName ) return CargoFound end - + --- Get the x position of the cargo. -- @param #CARGO self -- @return #number @@ -504,9 +501,9 @@ do -- CARGO return self.CargoCarrier:GetCoordinate().x else return self.CargoObject:GetCoordinate().x - end + end end - + --- Get the y position of the cargo. -- @param #CARGO self -- @return #number @@ -515,9 +512,9 @@ do -- CARGO return self.CargoCarrier:GetCoordinate().z else return self.CargoObject:GetCoordinate().z - end + end end - + --- Get the heading of the cargo. -- @param #CARGO self -- @return #number @@ -526,22 +523,21 @@ do -- CARGO return self.CargoCarrier:GetHeading() else return self.CargoObject:GetHeading() - end + end end - - + --- Check if the cargo can be Slingloaded. -- @param #CARGO self function CARGO:CanSlingload() return false end - + --- Check if the cargo can be Boarded. -- @param #CARGO self function CARGO:CanBoard() return true end - + --- Check if the cargo can be Unboarded. -- @param #CARGO self function CARGO:CanUnboard() @@ -553,14 +549,13 @@ do -- CARGO function CARGO:CanLoad() return true end - + --- Check if the cargo can be Unloaded. -- @param #CARGO self function CARGO:CanUnload() return true end - --- Destroy the cargo. -- @param #CARGO self function CARGO:Destroy() @@ -569,14 +564,14 @@ do -- CARGO end self:Destroyed() end - + --- Get the name of the Cargo. -- @param #CARGO self -- @return #string The name of the Cargo. function CARGO:GetName() --R2.1 return self.Name end - + --- Get the current active object representing or being the Cargo. -- @param #CARGO self -- @return Wrapper.Positionable#POSITIONABLE The object representing or being the Cargo. @@ -585,9 +580,9 @@ do -- CARGO return self.CargoCarrier else return self.CargoObject - end + end end - + --- Get the object name of the Cargo. -- @param #CARGO self -- @return #string The object name of the Cargo. @@ -596,9 +591,9 @@ do -- CARGO return self.CargoCarrier:GetName() else return self.CargoObject:GetName() - end + end end - + --- Get the amount of Cargo. -- @param #CARGO self -- @return #number The amount of Cargo. @@ -613,7 +608,6 @@ do -- CARGO return self.Type end - --- Get the transportation method of the Cargo. -- @param #CARGO self -- @return #string The transportation method of the Cargo. @@ -621,7 +615,6 @@ do -- CARGO return self.TransportationMethod end - --- Get the coalition of the Cargo. -- @param #CARGO self -- @return Coalition @@ -630,32 +623,30 @@ do -- CARGO return self.CargoCarrier:GetCoalition() else return self.CargoObject:GetCoalition() - end + end end - --- Get the current coordinates of the Cargo. -- @param #CARGO self -- @return Core.Point#COORDINATE The coordinates of the Cargo. function CARGO:GetCoordinate() return self.CargoObject:GetCoordinate() end - + --- Check if cargo is destroyed. -- @param #CARGO self -- @return #boolean true if destroyed function CARGO:IsDestroyed() return self:Is( "Destroyed" ) end - - + --- Check if cargo is loaded. -- @param #CARGO self -- @return #boolean true if loaded function CARGO:IsLoaded() return self:Is( "Loaded" ) end - + --- Check if cargo is loaded. -- @param #CARGO self -- @param Wrapper.Unit#UNIT Carrier @@ -663,14 +654,14 @@ do -- CARGO function CARGO:IsLoadedInCarrier( Carrier ) return self.CargoCarrier and self.CargoCarrier:GetName() == Carrier:GetName() end - + --- Check if cargo is unloaded. -- @param #CARGO self -- @return #boolean true if unloaded function CARGO:IsUnLoaded() return self:Is( "UnLoaded" ) end - + --- Check if cargo is boarding. -- @param #CARGO self -- @return #boolean true if boarding @@ -678,52 +669,47 @@ do -- CARGO return self:Is( "Boarding" ) end - --- Check if cargo is unboarding. -- @param #CARGO self -- @return #boolean true if unboarding function CARGO:IsUnboarding() return self:Is( "UnBoarding" ) end - --- Check if cargo is alive. -- @param #CARGO self -- @return #boolean true if unloaded function CARGO:IsAlive() - + if self:IsLoaded() then return self.CargoCarrier:IsAlive() else return self.CargoObject:IsAlive() - end + end end - + --- Set the cargo as deployed. -- @param #CARGO self -- @param #boolean Deployed true if the cargo is to be deployed. false or nil otherwise. function CARGO:SetDeployed( Deployed ) self.Deployed = Deployed end - + --- Is the cargo deployed -- @param #CARGO self -- @return #boolean function CARGO:IsDeployed() return self.Deployed end - - - - + --- Template method to spawn a new representation of the CARGO in the simulator. -- @param #CARGO self -- @return #CARGO function CARGO:Spawn( PointVec2 ) self:F() - + end - + --- Signal a flare at the position of the CARGO. -- @param #CARGO self -- @param Utilities.Utils#FLARECOLOR FlareColor @@ -732,31 +718,31 @@ do -- CARGO trigger.action.signalFlare( self.CargoObject:GetVec3(), FlareColor , 0 ) end end - + --- Signal a white flare at the position of the CARGO. -- @param #CARGO self function CARGO:FlareWhite() self:Flare( trigger.flareColor.White ) end - + --- Signal a yellow flare at the position of the CARGO. -- @param #CARGO self function CARGO:FlareYellow() self:Flare( trigger.flareColor.Yellow ) end - + --- Signal a green flare at the position of the CARGO. -- @param #CARGO self function CARGO:FlareGreen() self:Flare( trigger.flareColor.Green ) end - + --- Signal a red flare at the position of the CARGO. -- @param #CARGO self function CARGO:FlareRed() self:Flare( trigger.flareColor.Red ) end - + --- Smoke the CARGO. -- @param #CARGO self -- @param Utilities.Utils#SMOKECOLOR SmokeColor The color of the smoke. @@ -770,38 +756,37 @@ do -- CARGO end end end - + --- Smoke the CARGO Green. -- @param #CARGO self function CARGO:SmokeGreen() self:Smoke( trigger.smokeColor.Green, Range ) end - + --- Smoke the CARGO Red. -- @param #CARGO self function CARGO:SmokeRed() self:Smoke( trigger.smokeColor.Red, Range ) end - + --- Smoke the CARGO White. -- @param #CARGO self function CARGO:SmokeWhite() self:Smoke( trigger.smokeColor.White, Range ) end - + --- Smoke the CARGO Orange. -- @param #CARGO self function CARGO:SmokeOrange() self:Smoke( trigger.smokeColor.Orange, Range ) end - + --- Smoke the CARGO Blue. -- @param #CARGO self function CARGO:SmokeBlue() self:Smoke( trigger.smokeColor.Blue, Range ) end - - + --- Set the Load radius, which is the radius till when the Cargo can be loaded. -- @param #CARGO self -- @param #number LoadRadius The radius till Cargo can be loaded. @@ -809,23 +794,21 @@ do -- CARGO function CARGO:SetLoadRadius( LoadRadius ) self.LoadRadius = LoadRadius or 150 end - + --- Get the Load radius, which is the radius till when the Cargo can be loaded. -- @param #CARGO self -- @return #number The radius till Cargo can be loaded. function CARGO:GetLoadRadius() return self.LoadRadius end - - - + --- Check if Cargo is in the LoadRadius for the Cargo to be Boarded or Loaded. -- @param #CARGO self -- @param Core.Point#COORDINATE Coordinate -- @return #boolean true if the CargoGroup is within the loading radius. function CARGO:IsInLoadRadius( Coordinate ) self:F( { Coordinate, LoadRadius = self.LoadRadius } ) - + local Distance = 0 if self:IsUnLoaded() then local CargoCoordinate = self.CargoObject:GetCoordinate() @@ -835,18 +818,17 @@ do -- CARGO return true end end - + return false end - --- Check if the Cargo can report itself to be Boarded or Loaded. -- @param #CARGO self -- @param Core.Point#COORDINATE Coordinate -- @return #boolean true if the Cargo can report itself. function CARGO:IsInReportRadius( Coordinate ) self:F( { Coordinate } ) - + local Distance = 0 if self:IsUnLoaded() then Distance = Coordinate:Get2DDistance( self.CargoObject:GetCoordinate() ) @@ -855,7 +837,7 @@ do -- CARGO return true end end - + return false end @@ -867,7 +849,7 @@ do -- CARGO -- @return #boolean function CARGO:IsNear( Coordinate, NearRadius ) --self:F( { PointVec2 = PointVec2, NearRadius = NearRadius } ) - + if self.CargoObject:IsAlive() then --local Distance = PointVec2:Get2DDistance( self.CargoObject:GetPointVec2() ) --self:F( { CargoObjectName = self.CargoObject:GetName() } ) @@ -875,26 +857,24 @@ do -- CARGO --self:F( { PointVec2 = PointVec2:GetVec2() } ) local Distance = Coordinate:Get2DDistance( self.CargoObject:GetCoordinate() ) --self:F( { Distance = Distance, NearRadius = NearRadius or "nil" } ) - + if Distance <= NearRadius then --self:F( { PointVec2 = PointVec2, NearRadius = NearRadius, IsNear = true } ) return true end end - + --self:F( { PointVec2 = PointVec2, NearRadius = NearRadius, IsNear = false } ) return false end - - - - --- Check if Cargo is the given @{Zone}. + + --- Check if Cargo is the given @{Core.Zone}. -- @param #CARGO self -- @param Core.Zone#ZONE_BASE Zone -- @return #boolean **true** if cargo is in the Zone, **false** if cargo is not in the Zone. function CARGO:IsInZone( Zone ) --self:F( { Zone } ) - + if self:IsLoaded() then return Zone:IsPointVec2InZone( self.CargoCarrier:GetPointVec2() ) else @@ -904,34 +884,33 @@ do -- CARGO else return false end - end - + end + return nil - + end - - + --- Get the current PointVec2 of the cargo. -- @param #CARGO self -- @return Core.Point#POINT_VEC2 function CARGO:GetPointVec2() return self.CargoObject:GetPointVec2() end - + --- Get the current Coordinate of the cargo. -- @param #CARGO self -- @return Core.Point#COORDINATE function CARGO:GetCoordinate() return self.CargoObject:GetCoordinate() end - + --- Get the weight of the cargo. -- @param #CARGO self -- @return #number Weight The weight in kg. function CARGO:GetWeight() return self.Weight end - + --- Set the weight of the cargo. -- @param #CARGO self -- @param #number Weight The weight in kg. @@ -940,14 +919,14 @@ do -- CARGO self.Weight = Weight return self end - + --- Get the volume of the cargo. -- @param #CARGO self -- @return #number Volume The volume in kg. function CARGO:GetVolume() return self.Volume end - + --- Set the volume of the cargo. -- @param #CARGO self -- @param #number Volume The volume in kg. @@ -956,18 +935,18 @@ do -- CARGO self.Volume = Volume return self end - + --- Send a CC message to a @{Wrapper.Group}. -- @param #CARGO self -- @param #string Message -- @param Wrapper.Group#GROUP CarrierGroup The Carrier Group. -- @param #string Name (optional) The name of the Group used as a prefix for the message to the Group. If not provided, there will be nothing shown. function CARGO:MessageToGroup( Message, CarrierGroup, Name ) - + MESSAGE:New( Message, 20, "Cargo " .. self:GetName() ):ToGroup( CarrierGroup ) - + end - + --- Report to a Carrier Group. -- @param #CARGO self -- @param #string Action The string describing the action for the cargo. @@ -993,8 +972,7 @@ do -- CARGO end end end - - + --- Report to a Carrier Group with a Flaring signal. -- @param #CARGO self -- @param Utils#UTILS.FlareColor FlareColor the color of the flare. @@ -1003,8 +981,7 @@ do -- CARGO self.ReportFlareColor = FlareColor end - - + --- Report to a Carrier Group with a Smoking signal. -- @param #CARGO self -- @param Utils#UTILS.SmokeColor SmokeColor the color of the smoke. @@ -1013,8 +990,7 @@ do -- CARGO self.ReportSmokeColor = SmokeColor end - - + --- Reset the reporting for a Carrier Group. -- @param #CARGO self -- @param #string Action The string describing the action for the cargo. @@ -1024,7 +1000,7 @@ do -- CARGO self.Reported[CarrierGroup][Action] = nil end - + --- Reset all the reporting for a Carrier Group. -- @param #CARGO self -- @param Wrapper.Group#GROUP CarrierGroup The Carrier Group to send the report to. @@ -1033,7 +1009,7 @@ do -- CARGO self.Reported[CarrierGroup] = nil end - + --- Respawn the cargo when destroyed -- @param #CARGO self -- @param #boolean RespawnDestroyed @@ -1046,11 +1022,8 @@ do -- CARGO else self.onenterDestroyed = nil end - - end - - + end end -- CARGO @@ -1075,7 +1048,7 @@ do -- CARGO_REPRESENTABLE -- @param #number NearRadius (optional) Radius in meters when the cargo is loaded into the carrier. -- @return #CARGO_REPRESENTABLE function CARGO_REPRESENTABLE:New( CargoObject, Type, Name, LoadRadius, NearRadius ) - + -- Inherit CARGO. local self = BASE:Inherit( self, CARGO:New( Type, Name, 0, LoadRadius, NearRadius ) ) -- #CARGO_REPRESENTABLE self:F( { Type, Name, LoadRadius, NearRadius } ) @@ -1083,10 +1056,10 @@ do -- CARGO_REPRESENTABLE -- Descriptors. local Desc=CargoObject:GetDesc() self:T({Desc=Desc}) - + -- Weight. local Weight = math.random( 80, 120 ) - + -- Adjust weight.. if Desc then if Desc.typeName == "2B11 mortar" then @@ -1097,8 +1070,8 @@ do -- CARGO_REPRESENTABLE end -- Set weight. - self:SetWeight( Weight ) - + self:SetWeight( Weight ) + return self end @@ -1106,14 +1079,14 @@ do -- CARGO_REPRESENTABLE -- @param #CARGO_REPRESENTABLE self -- @return #CARGO_REPRESENTABLE function CARGO_REPRESENTABLE:Destroy() - + -- Cargo objects are deleted from the _DATABASE and SET_CARGO objects. self:F( { CargoName = self:GetName() } ) --_EVENTDISPATCHER:CreateEventDeleteCargo( self ) - + return self end - + --- Route a cargo unit to a PointVec2. -- @param #CARGO_REPRESENTABLE self -- @param Core.Point#POINT_VEC2 ToPointVec2 @@ -1121,19 +1094,19 @@ do -- CARGO_REPRESENTABLE -- @return #CARGO_REPRESENTABLE function CARGO_REPRESENTABLE:RouteTo( ToPointVec2, Speed ) self:F2( ToPointVec2 ) - + local Points = {} - + local PointStartVec2 = self.CargoObject:GetPointVec2() - + Points[#Points+1] = PointStartVec2:WaypointGround( Speed ) Points[#Points+1] = ToPointVec2:WaypointGround( Speed ) - + local TaskRoute = self.CargoObject:TaskRoute( Points ) self.CargoObject:SetTask( TaskRoute, 2 ) - return self + return self end - + --- Send a message to a @{Wrapper.Group} through a communication channel near the cargo. -- @param #CARGO_REPRESENTABLE self -- @param #string Message @@ -1157,20 +1130,19 @@ do -- CARGO_REPRESENTABLE end end end - + end - end -- CARGO_REPRESENTABLE do -- CARGO_REPORTABLE - + --- @type CARGO_REPORTABLE -- @extends #CARGO CARGO_REPORTABLE = { ClassName = "CARGO_REPORTABLE" } - + --- CARGO_REPORTABLE Constructor. -- @param #CARGO_REPORTABLE self -- @param #string Type @@ -1182,31 +1154,23 @@ do -- CARGO_REPORTABLE function CARGO_REPORTABLE:New( Type, Name, Weight, LoadRadius, NearRadius ) local self = BASE:Inherit( self, CARGO:New( Type, Name, Weight, LoadRadius, NearRadius ) ) -- #CARGO_REPORTABLE self:F( { Type, Name, Weight, LoadRadius, NearRadius } ) - + return self end - + --- Send a CC message to a @{Wrapper.Group}. -- @param #CARGO_REPORTABLE self -- @param #string Message -- @param Wrapper.Group#GROUP TaskGroup -- @param #string Name (optional) The name of the Group used as a prefix for the message to the Group. If not provided, there will be nothing shown. function CARGO_REPORTABLE:MessageToGroup( Message, TaskGroup, Name ) - + MESSAGE:New( Message, 20, "Cargo " .. self:GetName() .. " reporting" ):ToGroup( TaskGroup ) - + end - - end - - - - - - do -- CARGO_PACKAGE --- @type CARGO_PACKAGE @@ -1280,10 +1244,10 @@ function CARGO_PACKAGE:IsNear( CargoCarrier ) self:F() local CargoCarrierPoint = CargoCarrier:GetCoordinate() - + local Distance = CargoCarrierPoint:Get2DDistance( self.CargoCarrier:GetCoordinate() ) self:T( Distance ) - + if Distance <= self.NearRadius then return true else @@ -1334,7 +1298,7 @@ function CARGO_PACKAGE:onafterUnBoard( From, Event, To, CargoCarrier, Speed, UnL if not self.CargoInAir then self:_Next( self.FsmP.UnLoad, UnLoadDistance, Angle ) - + local Points = {} local StartPointVec2 = CargoCarrier:GetPointVec2() @@ -1389,7 +1353,7 @@ function CARGO_PACKAGE:onafterLoad( From, Event, To, CargoCarrier, Speed, LoadDi local CargoCarrierHeading = self.CargoCarrier:GetHeading() -- Get Heading of object in degrees. local CargoDeployHeading = ( ( CargoCarrierHeading + Angle ) >= 360 ) and ( CargoCarrierHeading + Angle - 360 ) or ( CargoCarrierHeading + Angle ) local CargoDeployPointVec2 = StartPointVec2:Translate( LoadDistance, CargoDeployHeading ) - + local Points = {} Points[#Points+1] = StartPointVec2:WaypointGround( Speed ) Points[#Points+1] = CargoDeployPointVec2:WaypointGround( Speed ) @@ -1410,12 +1374,12 @@ end -- @param #number Angle function CARGO_PACKAGE:onafterUnLoad( From, Event, To, CargoCarrier, Speed, Distance, Angle ) self:F() - + local StartPointVec2 = self.CargoCarrier:GetPointVec2() local CargoCarrierHeading = self.CargoCarrier:GetHeading() -- Get Heading of object in degrees. local CargoDeployHeading = ( ( CargoCarrierHeading + Angle ) >= 360 ) and ( CargoCarrierHeading + Angle - 360 ) or ( CargoCarrierHeading + Angle ) local CargoDeployPointVec2 = StartPointVec2:Translate( Distance, CargoDeployHeading ) - + self.CargoCarrier = CargoCarrier local Points = {} @@ -1427,5 +1391,4 @@ function CARGO_PACKAGE:onafterUnLoad( From, Event, To, CargoCarrier, Speed, Dist end - end diff --git a/Moose Development/Moose/Cargo/CargoCrate.lua b/Moose Development/Moose/Cargo/CargoCrate.lua index 50cef9a97..81bc7ca6a 100644 --- a/Moose Development/Moose/Cargo/CargoCrate.lua +++ b/Moose Development/Moose/Cargo/CargoCrate.lua @@ -1,4 +1,4 @@ ---- **Cargo** -- Management of single cargo crates, which are based on a @{Static} object. +--- **Cargo** - Management of single cargo crates, which are based on a STATIC object. -- -- === -- diff --git a/Moose Development/Moose/Cargo/CargoGroup.lua b/Moose Development/Moose/Cargo/CargoGroup.lua index 2d59f75d3..deb46b7d1 100644 --- a/Moose Development/Moose/Cargo/CargoGroup.lua +++ b/Moose Development/Moose/Cargo/CargoGroup.lua @@ -1,4 +1,4 @@ ---- **Cargo** - Management of grouped cargo logistics, which are based on a @{Wrapper.Group} object. +--- **Cargo** - Management of grouped cargo logistics, which are based on a GROUP object. -- -- === -- @@ -47,7 +47,7 @@ do -- CARGO_GROUP --- CARGO_GROUP constructor. -- This make a new CARGO_GROUP from a @{Wrapper.Group} object. - -- It will "ungroup" the group object within the sim, and will create a @{Set} of individual Unit objects. + -- It will "ungroup" the group object within the sim, and will create a @{Core.Set} of individual Unit objects. -- @param #CARGO_GROUP self -- @param Wrapper.Group#GROUP CargoGroup Group to be transported as cargo. -- @param #string Type Cargo type, e.g. "Infantry". This is the type used in SET_CARGO:New():FilterTypes("Infantry") to define the valid cargo groups of the set. @@ -727,7 +727,7 @@ do -- CARGO_GROUP end end - --- Check if the first element of the CargoGroup is the given @{Zone}. + --- Check if the first element of the CargoGroup is the given @{Core.Zone}. -- @param #CARGO_GROUP self -- @param Core.Zone#ZONE_BASE Zone -- @return #boolean **true** if the first element of the CargoGroup is in the Zone diff --git a/Moose Development/Moose/Cargo/CargoSlingload.lua b/Moose Development/Moose/Cargo/CargoSlingload.lua index 8af9d5304..ba3d8bb0b 100644 --- a/Moose Development/Moose/Cargo/CargoSlingload.lua +++ b/Moose Development/Moose/Cargo/CargoSlingload.lua @@ -1,4 +1,4 @@ ---- **Cargo** -- Management of single cargo crates, which are based on a @{Static} object. The cargo can only be slingloaded. +--- **Cargo** - Management of single cargo crates, which are based on a STATIC object. The cargo can only be slingloaded. -- -- === -- diff --git a/Moose Development/Moose/Cargo/CargoUnit.lua b/Moose Development/Moose/Cargo/CargoUnit.lua index 92baf40a4..6c5c5ffd6 100644 --- a/Moose Development/Moose/Cargo/CargoUnit.lua +++ b/Moose Development/Moose/Cargo/CargoUnit.lua @@ -1,4 +1,4 @@ ---- **Cargo** - Management of single cargo logistics, which are based on a @{Wrapper.Unit} object. +--- **Cargo** - Management of single cargo logistics, which are based on a UNIT object. -- -- === -- diff --git a/Moose Development/Moose/Core/Base.lua b/Moose Development/Moose/Core/Base.lua index 2adc50223..c94aee4cd 100644 --- a/Moose Development/Moose/Core/Base.lua +++ b/Moose Development/Moose/Core/Base.lua @@ -157,7 +157,7 @@ local _ClassID = 0 -- self:SmokeBlue() -- end -- --- See the @{Event} module for more information about event handling. +-- See the @{Core.Event} module for more information about event handling. -- -- # 4. Class identification methods. -- @@ -412,20 +412,20 @@ do -- Event Handling return _EVENTDISPATCHER end - --- Get the Class @{Event} processing Priority. + --- Get the Class @{Core.Event} processing Priority. -- The Event processing Priority is a number from 1 to 10, -- reflecting the order of the classes subscribed to the Event to be processed. -- @param #BASE self - -- @return #number The @{Event} processing Priority. + -- @return #number The @{Core.Event} processing Priority. function BASE:GetEventPriority() return self._.EventPriority or 5 end - --- Set the Class @{Event} processing Priority. + --- Set the Class @{Core.Event} processing Priority. -- The Event processing Priority is a number from 1 to 10, -- reflecting the order of the classes subscribed to the Event to be processed. -- @param #BASE self - -- @param #number EventPriority The @{Event} processing Priority. + -- @param #number EventPriority The @{Core.Event} processing Priority. -- @return #BASE self function BASE:SetEventPriority( EventPriority ) self._.EventPriority = EventPriority @@ -464,16 +464,16 @@ do -- Event Handling return self end - -- Event handling function prototypes - Have a look at the class @{Core.EVENT#EVENT} as these are just the prototypes. + -- Event handling function prototypes - Have a look at the class @{Core.Event#EVENT} as these are just the prototypes. --- Occurs whenever any unit in a mission fires a weapon. But not any machine gun or autocannon based weapon, those are handled by EVENT.ShootingStart. - -- Have a look at the class @{Core.EVENT#EVENT} as these are just the prototypes. + -- Have a look at the class @{Core.Event#EVENT} as these are just the prototypes. -- @function [parent=#BASE] OnEventShot -- @param #BASE self -- @param Core.Event#EVENTDATA EventData The EventData structure. --- Occurs whenever an object is hit by a weapon. - -- Have a look at the class @{Core.EVENT#EVENT} as these are just the prototypes. + -- Have a look at the class @{Core.Event#EVENT} as these are just the prototypes. -- initiator : The unit object the fired the weapon -- weapon: Weapon object that hit the target -- target: The Object that was hit. @@ -482,7 +482,7 @@ do -- Event Handling -- @param Core.Event#EVENTDATA EventData The EventData structure. --- Occurs when an aircraft takes off from an airbase, farp, or ship. - -- Have a look at the class @{Core.EVENT#EVENT} as these are just the prototypes. + -- Have a look at the class @{Core.Event#EVENT} as these are just the prototypes. -- initiator : The unit that tookoff -- place: Object from where the AI took-off from. Can be an Airbase Object, FARP, or Ships -- @function [parent=#BASE] OnEventTakeoff @@ -490,7 +490,7 @@ do -- Event Handling -- @param Core.Event#EVENTDATA EventData The EventData structure. --- Occurs when an aircraft lands at an airbase, farp or ship - -- Have a look at the class @{Core.EVENT#EVENT} as these are just the prototypes. + -- Have a look at the class @{Core.Event#EVENT} as these are just the prototypes. -- initiator : The unit that has landed -- place: Object that the unit landed on. Can be an Airbase Object, FARP, or Ships -- @function [parent=#BASE] OnEventLand @@ -498,49 +498,49 @@ do -- Event Handling -- @param Core.Event#EVENTDATA EventData The EventData structure. --- Occurs when any aircraft crashes into the ground and is completely destroyed. - -- Have a look at the class @{Core.EVENT#EVENT} as these are just the prototypes. + -- Have a look at the class @{Core.Event#EVENT} as these are just the prototypes. -- initiator : The unit that has crashed -- @function [parent=#BASE] OnEventCrash -- @param #BASE self -- @param Core.Event#EVENTDATA EventData The EventData structure. --- Occurs when a pilot ejects from an aircraft - -- Have a look at the class @{Core.EVENT#EVENT} as these are just the prototypes. + -- Have a look at the class @{Core.Event#EVENT} as these are just the prototypes. -- initiator : The unit that has ejected -- @function [parent=#BASE] OnEventEjection -- @param #BASE self -- @param Core.Event#EVENTDATA EventData The EventData structure. --- Occurs when an aircraft connects with a tanker and begins taking on fuel. - -- Have a look at the class @{Core.EVENT#EVENT} as these are just the prototypes. + -- Have a look at the class @{Core.Event#EVENT} as these are just the prototypes. -- initiator : The unit that is receiving fuel. -- @function [parent=#BASE] OnEventRefueling -- @param #BASE self -- @param Core.Event#EVENTDATA EventData The EventData structure. --- Occurs when an object is dead. - -- Have a look at the class @{Core.EVENT#EVENT} as these are just the prototypes. + -- Have a look at the class @{Core.Event#EVENT} as these are just the prototypes. -- initiator : The unit that is dead. -- @function [parent=#BASE] OnEventDead -- @param #BASE self -- @param Core.Event#EVENTDATA EventData The EventData structure. --- Occurs when an Event for an object is triggered. - -- Have a look at the class @{Core.EVENT#EVENT} as these are just the prototypes. + -- Have a look at the class @{Core.Event#EVENT} as these are just the prototypes. -- initiator : The unit that triggered the event. -- @function [parent=#BASE] OnEvent -- @param #BASE self -- @param Core.Event#EVENTDATA EventData The EventData structure. --- Occurs when the pilot of an aircraft is killed. Can occur either if the player is alive and crashes or if a weapon kills the pilot without completely destroying the plane. - -- Have a look at the class @{Core.EVENT#EVENT} as these are just the prototypes. + -- Have a look at the class @{Core.Event#EVENT} as these are just the prototypes. -- initiator : The unit that the pilot has died in. -- @function [parent=#BASE] OnEventPilotDead -- @param #BASE self -- @param Core.Event#EVENTDATA EventData The EventData structure. --- Occurs when a ground unit captures either an airbase or a farp. - -- Have a look at the class @{Core.EVENT#EVENT} as these are just the prototypes. + -- Have a look at the class @{Core.Event#EVENT} as these are just the prototypes. -- initiator : The unit that captured the base -- place: The airbase that was captured, can be a FARP or Airbase. When calling place:getCoalition() the faction will already be the new owning faction. -- @function [parent=#BASE] OnEventBaseCaptured @@ -548,68 +548,68 @@ do -- Event Handling -- @param Core.Event#EVENTDATA EventData The EventData structure. --- Occurs when a mission starts - -- Have a look at the class @{Core.EVENT#EVENT} as these are just the prototypes. + -- Have a look at the class @{Core.Event#EVENT} as these are just the prototypes. -- @function [parent=#BASE] OnEventMissionStart -- @param #BASE self -- @param Core.Event#EVENTDATA EventData The EventData structure. --- Occurs when a mission ends - -- Have a look at the class @{Core.EVENT#EVENT} as these are just the prototypes. + -- Have a look at the class @{Core.Event#EVENT} as these are just the prototypes. -- @function [parent=#BASE] OnEventMissionEnd -- @param #BASE self -- @param Core.Event#EVENTDATA EventData The EventData structure. --- Occurs when an aircraft is finished taking fuel. - -- Have a look at the class @{Core.EVENT#EVENT} as these are just the prototypes. + -- Have a look at the class @{Core.Event#EVENT} as these are just the prototypes. -- initiator : The unit that was receiving fuel. -- @function [parent=#BASE] OnEventRefuelingStop -- @param #BASE self -- @param Core.Event#EVENTDATA EventData The EventData structure. --- Occurs when any object is spawned into the mission. - -- Have a look at the class @{Core.EVENT#EVENT} as these are just the prototypes. + -- Have a look at the class @{Core.Event#EVENT} as these are just the prototypes. -- initiator : The unit that was spawned -- @function [parent=#BASE] OnEventBirth -- @param #BASE self -- @param Core.Event#EVENTDATA EventData The EventData structure. --- Occurs when any system fails on a human controlled aircraft. - -- Have a look at the class @{Core.EVENT#EVENT} as these are just the prototypes. + -- Have a look at the class @{Core.Event#EVENT} as these are just the prototypes. -- initiator : The unit that had the failure -- @function [parent=#BASE] OnEventHumanFailure -- @param #BASE self -- @param Core.Event#EVENTDATA EventData The EventData structure. --- Occurs when any aircraft starts its engines. - -- Have a look at the class @{Core.EVENT#EVENT} as these are just the prototypes. + -- Have a look at the class @{Core.Event#EVENT} as these are just the prototypes. -- initiator : The unit that is starting its engines. -- @function [parent=#BASE] OnEventEngineStartup -- @param #BASE self -- @param Core.Event#EVENTDATA EventData The EventData structure. --- Occurs when any aircraft shuts down its engines. - -- Have a look at the class @{Core.EVENT#EVENT} as these are just the prototypes. + -- Have a look at the class @{Core.Event#EVENT} as these are just the prototypes. -- initiator : The unit that is stopping its engines. -- @function [parent=#BASE] OnEventEngineShutdown -- @param #BASE self -- @param Core.Event#EVENTDATA EventData The EventData structure. --- Occurs when any player assumes direct control of a unit. Note - not Mulitplayer safe. Use PlayerEnterAircraft. - -- Have a look at the class @{Core.EVENT#EVENT} as these are just the prototypes. + -- Have a look at the class @{Core.Event#EVENT} as these are just the prototypes. -- initiator : The unit that is being taken control of. -- @function [parent=#BASE] OnEventPlayerEnterUnit -- @param #BASE self -- @param Core.Event#EVENTDATA EventData The EventData structure. --- Occurs when any player relieves control of a unit to the AI. - -- Have a look at the class @{Core.EVENT#EVENT} as these are just the prototypes. + -- Have a look at the class @{Core.Event#EVENT} as these are just the prototypes. -- initiator : The unit that the player left. -- @function [parent=#BASE] OnEventPlayerLeaveUnit -- @param #BASE self -- @param Core.Event#EVENTDATA EventData The EventData structure. --- Occurs when any unit begins firing a weapon that has a high rate of fire. Most common with aircraft cannons (GAU-8), autocannons, and machine guns. - -- Have a look at the class @{Core.EVENT#EVENT} as these are just the prototypes. + -- Have a look at the class @{Core.Event#EVENT} as these are just the prototypes. -- initiator : The unit that is doing the shooting. -- target: The unit that is being targeted. -- @function [parent=#BASE] OnEventShootingStart @@ -617,28 +617,28 @@ do -- Event Handling -- @param Core.Event#EVENTDATA EventData The EventData structure. --- Occurs when any unit stops firing its weapon. Event will always correspond with a shooting start event. - -- Have a look at the class @{Core.EVENT#EVENT} as these are just the prototypes. + -- Have a look at the class @{Core.Event#EVENT} as these are just the prototypes. -- initiator : The unit that was doing the shooting. -- @function [parent=#BASE] OnEventShootingEnd -- @param #BASE self -- @param Core.Event#EVENTDATA EventData The EventData structure. --- Occurs when a new mark was added. - -- Have a look at the class @{Core.EVENT#EVENT} as these are just the prototypes. + -- Have a look at the class @{Core.Event#EVENT} as these are just the prototypes. -- MarkID: ID of the mark. -- @function [parent=#BASE] OnEventMarkAdded -- @param #BASE self -- @param Core.Event#EVENTDATA EventData The EventData structure. --- Occurs when a mark was removed. - -- Have a look at the class @{Core.EVENT#EVENT} as these are just the prototypes. + -- Have a look at the class @{Core.Event#EVENT} as these are just the prototypes. -- MarkID: ID of the mark. -- @function [parent=#BASE] OnEventMarkRemoved -- @param #BASE self -- @param Core.Event#EVENTDATA EventData The EventData structure. --- Occurs when a mark text was changed. - -- Have a look at the class @{Core.EVENT#EVENT} as these are just the prototypes. + -- Have a look at the class @{Core.Event#EVENT} as these are just the prototypes. -- MarkID: ID of the mark. -- @function [parent=#BASE] OnEventMarkChange -- @param #BASE self @@ -654,13 +654,13 @@ do -- Event Handling --- Occurs when any modification to the "Score" as seen on the debrief menu would occur. -- There is no information on what values the score was changed to. Event is likely similar to player_comment in this regard. - -- Have a look at the class @{Core.EVENT#EVENT} as these are just the prototypes. + -- Have a look at the class @{Core.Event#EVENT} as these are just the prototypes. -- @function [parent=#BASE] OnEventScore -- @param #BASE self -- @param Core.Event#EVENTDATA EventData The EventData structure. --- Occurs on the death of a unit. Contains more and different information. Similar to unit_lost it will occur for aircraft before the aircraft crash event occurs. - -- Have a look at the class @{Core.EVENT#EVENT} as these are just the prototypes. + -- Have a look at the class @{Core.Event#EVENT} as these are just the prototypes. -- -- * initiator: The unit that killed the target -- * target: Target Object @@ -672,13 +672,13 @@ do -- Event Handling --- Occurs when any modification to the "Score" as seen on the debrief menu would occur. -- There is no information on what values the score was changed to. Event is likely similar to player_comment in this regard. - -- Have a look at the class @{Core.EVENT#EVENT} as these are just the prototypes. + -- Have a look at the class @{Core.Event#EVENT} as these are just the prototypes. -- @function [parent=#BASE] OnEventScore -- @param #BASE self -- @param Core.Event#EVENTDATA EventData The EventData structure. --- Occurs when the game thinks an object is destroyed. - -- Have a look at the class @{Core.EVENT#EVENT} as these are just the prototypes. + -- Have a look at the class @{Core.Event#EVENT} as these are just the prototypes. -- -- * initiator: The unit that is was destroyed. -- @@ -687,7 +687,7 @@ do -- Event Handling -- @param Core.Event#EVENTDATA EventData The EventData structure. --- Occurs shortly after the landing animation of an ejected pilot touching the ground and standing up. Event does not occur if the pilot lands in the water and sub combs to Davey Jones Locker. - -- Have a look at the class @{Core.EVENT#EVENT} as these are just the prototypes. + -- Have a look at the class @{Core.Event#EVENT} as these are just the prototypes. -- -- * initiator: Static object representing the ejected pilot. Place : Aircraft that the pilot ejected from. -- * place: may not return as a valid object if the aircraft has crashed into the ground and no longer exists. @@ -698,43 +698,43 @@ do -- Event Handling -- @param Core.Event#EVENTDATA EventData The EventData structure. --- Paratrooper landing. - -- Have a look at the class @{Core.EVENT#EVENT} as these are just the prototypes. + -- Have a look at the class @{Core.Event#EVENT} as these are just the prototypes. -- @function [parent=#BASE] OnEventParatrooperLanding -- @param #BASE self -- @param Core.Event#EVENTDATA EventData The EventData structure. --- Discard chair after ejection. - -- Have a look at the class @{Core.EVENT#EVENT} as these are just the prototypes. + -- Have a look at the class @{Core.Event#EVENT} as these are just the prototypes. -- @function [parent=#BASE] OnEventDiscardChairAfterEjection -- @param #BASE self -- @param Core.Event#EVENTDATA EventData The EventData structure. --- Weapon add. Fires when entering a mission per pylon with the name of the weapon (double pylons not counted, infinite wep reload not counted. - -- Have a look at the class @{Core.EVENT#EVENT} as these are just the prototypes. + -- Have a look at the class @{Core.Event#EVENT} as these are just the prototypes. -- @function [parent=#BASE] OnEventParatrooperLanding -- @param #BASE self -- @param Core.Event#EVENTDATA EventData The EventData structure. --- Trigger zone. - -- Have a look at the class @{Core.EVENT#EVENT} as these are just the prototypes. + -- Have a look at the class @{Core.Event#EVENT} as these are just the prototypes. -- @function [parent=#BASE] OnEventTriggerZone -- @param #BASE self -- @param Core.Event#EVENTDATA EventData The EventData structure. --- Landing quality mark. - -- Have a look at the class @{Core.EVENT#EVENT} as these are just the prototypes. + -- Have a look at the class @{Core.Event#EVENT} as these are just the prototypes. -- @function [parent=#BASE] OnEventLandingQualityMark -- @param #BASE self -- @param Core.Event#EVENTDATA EventData The EventData structure. --- BDA. - -- Have a look at the class @{Core.EVENT#EVENT} as these are just the prototypes. + -- Have a look at the class @{Core.Event#EVENT} as these are just the prototypes. -- @function [parent=#BASE] OnEventBDA -- @param #BASE self -- @param Core.Event#EVENTDATA EventData The EventData structure. --- Occurs when a player enters a slot and takes control of an aircraft. - -- Have a look at the class @{Core.EVENT#EVENT} as these are just the prototypes. + -- Have a look at the class @{Core.Event#EVENT} as these are just the prototypes. -- **NOTE**: This is a workaround of a long standing DCS bug with the PLAYER_ENTER_UNIT event. -- initiator : The unit that is being taken control of. -- @function [parent=#BASE] OnEventPlayerEnterAircraft diff --git a/Moose Development/Moose/Core/Beacon.lua b/Moose Development/Moose/Core/Beacon.lua index ef7a5f3b6..c3d22b823 100644 --- a/Moose Development/Moose/Core/Beacon.lua +++ b/Moose Development/Moose/Core/Beacon.lua @@ -17,8 +17,8 @@ -- -- After attaching a @{#BEACON} to your @{Wrapper.Positionable#POSITIONABLE}, you need to select the right function to activate the kind of beacon you want. -- There are two types of BEACONs available : the (aircraft) TACAN Beacon and the general purpose Radio Beacon. --- Note that in both case, you can set an optional parameter : the `BeaconDuration`. This can be very usefull to simulate the battery time if your BEACON is --- attach to a cargo crate, for exemple. +-- Note that in both case, you can set an optional parameter : the `BeaconDuration`. This can be very useful to simulate the battery time if your BEACON is +-- attach to a cargo crate, for example. -- -- ## Aircraft TACAN Beacon usage -- @@ -33,7 +33,7 @@ -- -- @type BEACON -- @field #string ClassName Name of the class "BEACON". --- @field Wrapper.Controllable#CONTROLLABLE Positionable The @{#CONTROLLABLE} that will receive radio capabilities. +-- @field Wrapper.Controllable#CONTROLLABLE Positionable The @{Wrapper.Controllable#CONTROLLABLE} that will receive radio capabilities. -- @extends Core.Base#BASE BEACON = { ClassName = "BEACON", @@ -72,12 +72,12 @@ BEACON.Type={ TACAN = 4, VORTAC = 5, RSBN = 128, - BROADCAST_STATION = 1024, + BROADCAST_STATION = 1024, HOMER = 8, - AIRPORT_HOMER = 4104, - AIRPORT_HOMER_WITH_MARKER = 4136, + AIRPORT_HOMER = 4104, + AIRPORT_HOMER_WITH_MARKER = 4136, ILS_FAR_HOMER = 16408, - ILS_NEAR_HOMER = 16424, + ILS_NEAR_HOMER = 16424, ILS_LOCALIZER = 16640, ILS_GLIDESLOPE = 16896, PRMG_LOCALIZER = 33024, @@ -108,13 +108,13 @@ BEACON.Type={ -- @field #number ICLS_LOCALIZER Carrier landing system. -- @field #number ICLS_GLIDESLOPE Carrier landing system. BEACON.System={ - PAR_10 = 1, - RSBN_5 = 2, - TACAN = 3, + PAR_10 = 1, + RSBN_5 = 2, + TACAN = 3, TACAN_TANKER_X = 4, TACAN_TANKER_Y = 5, - VOR = 6, - ILS_LOCALIZER = 7, + VOR = 6, + ILS_LOCALIZER = 7, ILS_GLIDESLOPE = 8, PRMG_LOCALIZER = 9, PRMG_GLIDESLOPE = 10, @@ -130,16 +130,16 @@ BEACON.System={ --- Create a new BEACON Object. This doesn't activate the beacon, though, use @{#BEACON.ActivateTACAN} etc. -- If you want to create a BEACON, you probably should use @{Wrapper.Positionable#POSITIONABLE.GetBeacon}() instead. -- @param #BEACON self --- @param Wrapper.Positionable#POSITIONABLE Positionable The @{Positionable} that will receive radio capabilities. +-- @param Wrapper.Positionable#POSITIONABLE Positionable The @{Wrapper.Positionable} that will receive radio capabilities. -- @return #BEACON Beacon object or #nil if the positionable is invalid. function BEACON:New(Positionable) -- Inherit BASE. local self=BASE:Inherit(self, BASE:New()) --#BEACON - + -- Debug. self:F(Positionable) - + -- Set positionable. if Positionable:GetPointVec2() then -- It's stupid, but the only way I found to make sure positionable is valid self.Positionable = Positionable @@ -147,12 +147,11 @@ function BEACON:New(Positionable) self:I(string.format("New BEACON %s", tostring(self.name))) return self end - + self:E({"The passed positionable is invalid, no BEACON created", Positionable}) return nil end - --- Activates a TACAN BEACON. -- @param #BEACON self -- @param #number Channel TACAN channel, i.e. the "10" part in "10Y". @@ -169,28 +168,28 @@ end -- myBeacon:ActivateTACAN(20, "Y", "TEXACO", true) -- Activate the beacon function BEACON:ActivateTACAN(Channel, Mode, Message, Bearing, Duration) self:T({channel=Channel, mode=Mode, callsign=Message, bearing=Bearing, duration=Duration}) - + Mode=Mode or "Y" - + -- Get frequency. local Frequency=UTILS.TACANToFrequency(Channel, Mode) - + -- Check. if not Frequency then self:E({"The passed TACAN channel is invalid, the BEACON is not emitting"}) return self end - + -- Beacon type. local Type=BEACON.Type.TACAN - + -- Beacon system. local System=BEACON.System.TACAN - + -- Check if unit is an aircraft and set system accordingly. local AA=self.Positionable:IsAir() - - + + if AA then System=5 --NOTE: 5 is how you cat the correct tanker behaviour! --BEACON.System.TACAN_TANKER -- Check if "Y" mode is selected for aircraft. @@ -201,21 +200,21 @@ function BEACON:ActivateTACAN(Channel, Mode, Message, Bearing, Duration) System=BEACON.System.TACAN_TANKER_Y end end - + -- Attached unit. local UnitID=self.Positionable:GetID() - + -- Debug. self:I({string.format("BEACON Activating TACAN %s: Channel=%d%s, Morse=%s, Bearing=%s, Duration=%s!", tostring(self.name), Channel, Mode, Message, tostring(Bearing), tostring(Duration))}) - + -- Start beacon. self.Positionable:CommandActivateBeacon(Type, System, Frequency, UnitID, Channel, Mode, AA, Message, Bearing) - + -- Stop scheduler. if Duration then self.Positionable:DeactivateBeacon(Duration) end - + return self end @@ -227,21 +226,21 @@ end -- @return #BEACON self function BEACON:ActivateICLS(Channel, Callsign, Duration) self:F({Channel=Channel, Callsign=Callsign, Duration=Duration}) - + -- Attached unit. local UnitID=self.Positionable:GetID() - + -- Debug self:T2({"ICLS BEACON started!"}) - + -- Start beacon. self.Positionable:CommandActivateICLS(Channel, UnitID, Callsign) - + -- Stop scheduler if Duration then -- Schedule the stop of the BEACON if asked by the MD self.Positionable:DeactivateBeacon(Duration) end - + return self end @@ -253,25 +252,25 @@ end -- @return #BEACON self function BEACON:ActivateLink4(Frequency, Morse, Duration) self:F({Frequency=Frequency, Morse=Morse, Duration=Duration}) - + -- Attached unit. local UnitID=self.Positionable:GetID() - + -- Debug self:T2({"LINK4 BEACON started!"}) - + -- Start beacon. self.Positionable:CommandActivateLink4(Frequency,UnitID,Morse) - + -- Stop sheduler if Duration then -- Schedule the stop of the BEACON if asked by the MD self.Positionable:CommandDeactivateLink4(Duration) end - + return self end ---- DEPRECATED: Please use @{BEACON:ActivateTACAN}() instead. +--- DEPRECATED: Please use @{#BEACON.ActivateTACAN}() instead. -- Activates a TACAN BEACON on an Aircraft. -- @param #BEACON self -- @param #number TACANChannel (the "10" part in "10Y"). Note that AA TACAN are only available on Y Channels @@ -287,20 +286,20 @@ end -- myBeacon:AATACAN(20, "TEXACO", true) -- Activate the beacon function BEACON:AATACAN(TACANChannel, Message, Bearing, BeaconDuration) self:F({TACANChannel, Message, Bearing, BeaconDuration}) - + local IsValid = true - + if not self.Positionable:IsAir() then self:E({"The POSITIONABLE you want to attach the AA Tacan Beacon is not an aircraft ! The BEACON is not emitting", self.Positionable}) IsValid = false end - + local Frequency = self:_TACANToFrequency(TACANChannel, "Y") if not Frequency then self:E({"The passed TACAN channel is invalid, the BEACON is not emitting"}) IsValid = false end - + -- I'm using the beacon type 4 (BEACON_TYPE_TACAN). For System, I'm using 5 (TACAN_TANKER_MODE_Y) if the bearing shows its bearing or 14 (TACAN_AA_MODE_Y) if it does not local System if Bearing then @@ -308,7 +307,7 @@ function BEACON:AATACAN(TACANChannel, Message, Bearing, BeaconDuration) else System = BEACON.System.TACAN_AA_MODE_Y end - + if IsValid then -- Starts the BEACON self:T2({"AA TACAN BEACON started !"}) self.Positionable:SetCommand({ @@ -323,7 +322,7 @@ function BEACON:AATACAN(TACANChannel, Message, Bearing, BeaconDuration) modeChannel = "Y", } }) - + if BeaconDuration then -- Schedule the stop of the BEACON if asked by the MD SCHEDULER:New(nil, function() @@ -331,7 +330,7 @@ function BEACON:AATACAN(TACANChannel, Message, Bearing, BeaconDuration) end, {}, BeaconDuration) end end - + return self end @@ -351,7 +350,6 @@ function BEACON:StopAATACAN() end end - --- Activates a general purpose Radio Beacon -- This uses the very generic singleton function "trigger.action.radioTransmission()" provided by DCS to broadcast a sound file on a specific frequency. -- Although any frequency could be used, only a few DCS Modules can home on radio beacons at the time of writing, i.e. the Mi-8, Huey, Gazelle etc. @@ -381,7 +379,7 @@ end function BEACON:RadioBeacon(FileName, Frequency, Modulation, Power, BeaconDuration) self:F({FileName, Frequency, Modulation, Power, BeaconDuration}) local IsValid = false - + -- Check the filename if type(FileName) == "string" then if FileName:find(".ogg") or FileName:find(".wav") then @@ -394,32 +392,32 @@ function BEACON:RadioBeacon(FileName, Frequency, Modulation, Power, BeaconDurati if not IsValid then self:E({"File name invalid. Maybe something wrong with the extension ? ", FileName}) end - + -- Check the Frequency if type(Frequency) ~= "number" and IsValid then self:E({"Frequency invalid. ", Frequency}) IsValid = false end Frequency = Frequency * 1000000 -- Conversion to Hz - + -- Check the modulation if Modulation ~= radio.modulation.AM and Modulation ~= radio.modulation.FM and IsValid then --TODO Maybe make this future proof if ED decides to add an other modulation ? self:E({"Modulation is invalid. Use DCS's enum radio.modulation.", Modulation}) IsValid = false end - + -- Check the Power if type(Power) ~= "number" and IsValid then self:E({"Power is invalid. ", Power}) IsValid = false end Power = math.floor(math.abs(Power)) --TODO Find what is the maximum power allowed by DCS and limit power to that - + if IsValid then self:T2({"Activating Beacon on ", Frequency, Modulation}) -- Note that this is looped. I have to give this transmission a unique name, I use the class ID trigger.action.radioTransmission(FileName, self.Positionable:GetPositionVec3(), Modulation, true, Frequency, Power, tostring(self.ID)) - + if BeaconDuration then -- Schedule the stop of the BEACON if asked by the MD SCHEDULER:New( nil, function() @@ -453,16 +451,16 @@ function BEACON:_TACANToFrequency(TACANChannel, TACANMode) return nil -- error in arguments end end - + -- This code is largely based on ED's code, in DCS World\Scripts\World\Radio\BeaconTypes.lua, line 137. -- I have no idea what it does but it seems to work local A = 1151 -- 'X', channel >= 64 local B = 64 -- channel >= 64 - + if TACANChannel < 64 then B = 1 end - + if TACANMode == 'Y' then A = 1025 if TACANChannel < 64 then @@ -473,6 +471,6 @@ function BEACON:_TACANToFrequency(TACANChannel, TACANMode) A = 962 end end - + return (A + TACANChannel - B) * 1000000 end diff --git a/Moose Development/Moose/Core/Condition.lua b/Moose Development/Moose/Core/Condition.lua index d88a1fc33..8d9824a72 100644 --- a/Moose Development/Moose/Core/Condition.lua +++ b/Moose Development/Moose/Core/Condition.lua @@ -17,7 +17,7 @@ -- -- === -- @module Core.Condition --- @image Core_Conditon.png +-- @image MOOSE.JPG --- CONDITON class. -- @type CONDITION diff --git a/Moose Development/Moose/Core/Database.lua b/Moose Development/Moose/Core/Database.lua index e80f36558..1b5fba242 100644 --- a/Moose Development/Moose/Core/Database.lua +++ b/Moose Development/Moose/Core/Database.lua @@ -51,7 +51,7 @@ -- * PLAYERS -- * CARGOS -- --- On top, for internal MOOSE administration purposes, the DATBASE administers the Unit and Group TEMPLATES as defined within the Mission Editor. +-- On top, for internal MOOSE administration purposes, the DATABASE administers the Unit and Group TEMPLATES as defined within the Mission Editor. -- -- The singleton object **_DATABASE** is automatically created by MOOSE, that administers all objects within the mission. -- Moose refers to **_DATABASE** within the framework extensively, but you can also refer to the _DATABASE object within your missions if required. @@ -246,7 +246,7 @@ end do -- Zones - --- Finds a @{Zone} based on the zone name. + --- Finds a @{Core.Zone} based on the zone name. -- @param #DATABASE self -- @param #string ZoneName The name of the zone. -- @return Core.Zone#ZONE_BASE The found ZONE. @@ -256,7 +256,7 @@ do -- Zones return ZoneFound end - --- Adds a @{Zone} based on the zone name in the DATABASE. + --- Adds a @{Core.Zone} based on the zone name in the DATABASE. -- @param #DATABASE self -- @param #string ZoneName The name of the zone. -- @param Core.Zone#ZONE_BASE Zone The zone. @@ -268,7 +268,7 @@ do -- Zones end - --- Deletes a @{Zone} from the DATABASE based on the zone name. + --- Deletes a @{Core.Zone} from the DATABASE based on the zone name. -- @param #DATABASE self -- @param #string ZoneName The name of the zone. function DATABASE:DeleteZone( ZoneName ) @@ -309,7 +309,7 @@ do -- Zones self:I(string.format("Register ZONE: %s (Polygon, Quad)", ZoneName)) - Zone=ZONE_POLYGON_BASE:New(ZoneName, ZoneData.verticies) + Zone=ZONE_POLYGON:NewFromPointsArray(ZoneName, ZoneData.verticies) --for i,vec2 in pairs(ZoneData.verticies) do -- local coord=COORDINATE:NewFromVec2(vec2) @@ -322,7 +322,7 @@ do -- Zones -- Store color of zone. Zone.Color=color - + -- Store zone ID. Zone.ZoneID=ZoneData.zoneId @@ -379,7 +379,7 @@ end -- zone do -- Zone_Goal - --- Finds a @{Zone} based on the zone name. + --- Finds a @{Core.Zone} based on the zone name. -- @param #DATABASE self -- @param #string ZoneName The name of the zone. -- @return Core.Zone#ZONE_BASE The found ZONE. @@ -389,7 +389,7 @@ do -- Zone_Goal return ZoneFound end - --- Adds a @{Zone} based on the zone name in the DATABASE. + --- Adds a @{Core.Zone} based on the zone name in the DATABASE. -- @param #DATABASE self -- @param #string ZoneName The name of the zone. -- @param Core.Zone#ZONE_BASE Zone The zone. @@ -401,7 +401,7 @@ do -- Zone_Goal end - --- Deletes a @{Zone} from the DATABASE based on the zone name. + --- Deletes a @{Core.Zone} from the DATABASE based on the zone name. -- @param #DATABASE self -- @param #string ZoneName The name of the zone. function DATABASE:DeleteZoneGoal( ZoneName ) @@ -777,7 +777,7 @@ function DATABASE:_RegisterStaticTemplate( StaticTemplate, CoalitionID, Category local StaticTemplate = UTILS.DeepCopy( StaticTemplate ) local StaticTemplateGroupName = env.getValueDictByKey(StaticTemplate.name) - + local StaticTemplateName=StaticTemplate.units[1].name self.Templates.Statics[StaticTemplateName] = self.Templates.Statics[StaticTemplateName] or {} @@ -1153,11 +1153,11 @@ function DATABASE:_EventOnDeadOrCrash( Event ) if self.STATICS[Event.IniDCSUnitName] then self:DeleteStatic( Event.IniDCSUnitName ) end - + --- -- Maybe a UNIT? --- - + -- Delete unit. if self.UNITS[Event.IniDCSUnitName] then self:T("STATIC Event for UNIT "..tostring(Event.IniDCSUnitName)) @@ -1556,11 +1556,11 @@ function DATABASE:FindOpsGroupFromUnit(unitname) else unit=unitname end - + if unit then groupname=unit:GetGroup():GetName() end - + if groupname then return self.FLIGHTGROUPS[groupname] else diff --git a/Moose Development/Moose/Core/Event.lua b/Moose Development/Moose/Core/Event.lua index 05d7ae41f..d59f1c244 100644 --- a/Moose Development/Moose/Core/Event.lua +++ b/Moose Development/Moose/Core/Event.lua @@ -35,7 +35,7 @@ -- There are 5 types/levels of objects that the _EVENTDISPATCHER services: -- -- * _DATABASE object: The core of the MOOSE objects. Any object that is created, deleted or updated, is done in this database. --- * SET_ derived classes: These are subsets of the _DATABASE object. These subsets are updated by the _EVENTDISPATCHER as the second priority. +-- * SET_ derived classes: These are subsets of the global _DATABASE object (an instance of @{Core.Database#DATABASE}). These subsets are updated by the _EVENTDISPATCHER as the second priority. -- * UNIT objects: UNIT objects can subscribe to DCS events. Each DCS event will be directly published to the subscribed UNIT object. -- * GROUP objects: GROUP objects can subscribe to DCS events. Each DCS event will be directly published to the subscribed GROUP object. -- * Any other object: Various other objects can subscribe to DCS events. Each DCS event triggered will be published to each subscribed object. @@ -52,7 +52,7 @@ -- -- ![Objects](..\Presentations\EVENT\Dia8.JPG) -- --- The actual event subscribing and handling is not facilitated through the _EVENTDISPATCHER, but it is done through the @{BASE} class, @{UNIT} class and @{GROUP} class. +-- The actual event subscribing and handling is not facilitated through the _EVENTDISPATCHER, but it is done through the @{Core.Base#BASE} class, @{Wrapper.Unit#UNIT} class and @{Wrapper.Group#GROUP} class. -- The _EVENTDISPATCHER is a component that is quietly working in the background of MOOSE. -- -- ![Objects](..\Presentations\EVENT\Dia9.JPG) @@ -248,6 +248,18 @@ EVENTS = { TriggerZone = world.event.S_EVENT_TRIGGER_ZONE or -1, LandingQualityMark = world.event.S_EVENT_LANDING_QUALITY_MARK or -1, BDA = world.event.S_EVENT_BDA or -1, + -- Added with DCS 2.8.0 + AIAbortMission = world.event.S_EVENT_AI_ABORT_MISSION or -1, + DayNight = world.event.S_EVENT_DAYNIGHT or -1, + FlightTime = world.event.S_EVENT_FLIGHT_TIME or -1, + SelfKillPilot = world.event.S_EVENT_PLAYER_SELF_KILL_PILOT or -1, + PlayerCaptureAirfield = world.event.S_EVENT_PLAYER_CAPTURE_AIRFIELD or -1, + EmergencyLanding = world.event.S_EVENT_EMERGENCY_LANDING or -1, + UnitCreateTask = world.event.S_EVENT_UNIT_CREATE_TASK or -1, + UnitDeleteTask = world.event.S_EVENT_UNIT_DELETE_TASK or -1, + SimulationStart = world.event.S_EVENT_SIMULATION_START or -1, + WeaponRearm = world.event.S_EVENT_WEAPON_REARM or -1, + WeaponDrop = world.event.S_EVENT_WEAPON_DROP or -1, } --- The Event structure @@ -560,9 +572,69 @@ local _EVENTMETA = { Event = "OnEventBDA", Text = "S_EVENT_BDA" }, + -- Added with DCS 2.8 + [EVENTS.AIAbortMission] = { + Order = 1, + Side = "I", + Event = "OnEventAIAbortMission", + Text = "S_EVENT_AI_ABORT_MISSION" + }, + [EVENTS.DayNight] = { + Order = 1, + Event = "OnEventDayNight", + Text = "S_EVENT_DAYNIGHT" + }, + [EVENTS.FlightTime] = { + Order = 1, + Event = "OnEventFlightTime", + Text = "S_EVENT_FLIGHT_TIME" + }, + [EVENTS.SelfKillPilot] = { + Order = 1, + Side = "I", + Event = "OnEventSelfKillPilot", + Text = "S_EVENT_PLAYER_SELF_KILL_PILOT" + }, + [EVENTS.PlayerCaptureAirfield] = { + Order = 1, + Event = "OnEventPlayerCaptureAirfield", + Text = "S_EVENT_PLAYER_CAPTURE_AIRFIELD" + }, + [EVENTS.EmergencyLanding] = { + Order = 1, + Side = "I", + Event = "OnEventEmergencyLanding", + Text = "S_EVENT_EMERGENCY_LANDING" + }, + [EVENTS.UnitCreateTask] = { + Order = 1, + Event = "OnEventUnitCreateTask", + Text = "S_EVENT_UNIT_CREATE_TASK" + }, + [EVENTS.UnitDeleteTask] = { + Order = 1, + Event = "OnEventUnitDeleteTask", + Text = "S_EVENT_UNIT_DELETE_TASK" + }, + [EVENTS.SimulationStart] = { + Order = 1, + Event = "OnEventSimulationStart", + Text = "S_EVENT_SIMULATION_START" + }, + [EVENTS.WeaponRearm] = { + Order = 1, + Side = "I", + Event = "OnEventWeaponRearm", + Text = "S_EVENT_WEAPON_REARM" + }, + [EVENTS.WeaponDrop] = { + Order = 1, + Side = "I", + Event = "OnEventWeaponDrop", + Text = "S_EVENT_WEAPON_DROP" + }, } - --- The Events structure -- @type EVENT.Events -- @field #number IniUnit @@ -932,7 +1004,7 @@ do -- Event Creation --- Creation of a ZoneGoal Deletion Event. -- @param #EVENT self - -- @param Core.ZoneGoal#ZONE_GOAL ZoneGoal The ZoneGoal created. + -- @param Functional.ZoneGoal#ZONE_GOAL ZoneGoal The ZoneGoal created. function EVENT:CreateEventDeleteZoneGoal( ZoneGoal ) self:F( { ZoneGoal } ) diff --git a/Moose Development/Moose/Core/Fsm.lua b/Moose Development/Moose/Core/Fsm.lua index 89f42e88f..2b5f499e5 100644 --- a/Moose Development/Moose/Core/Fsm.lua +++ b/Moose Development/Moose/Core/Fsm.lua @@ -47,9 +47,9 @@ -- and tailored** by mission designers through **the implementation of Transition Handlers**. -- Each of these FSM implementation classes start either with: -- --- * an acronym **AI\_**, which indicates a FSM implementation directing **AI controlled** @{GROUP} and/or @{UNIT}. These AI\_ classes derive the @{#FSM_CONTROLLABLE} class. --- * an acronym **TASK\_**, which indicates a FSM implementation executing a @{TASK} executed by Groups of players. These TASK\_ classes derive the @{#FSM_TASK} class. --- * an acronym **ACT\_**, which indicates an Sub-FSM implementation, directing **Humans actions** that need to be done in a @{TASK}, seated in a @{CLIENT} (slot) or a @{UNIT} (CA join). These ACT\_ classes derive the @{#FSM_PROCESS} class. +-- * an acronym **AI\_**, which indicates a FSM implementation directing **AI controlled** @{Wrapper.Group#GROUP} and/or @{Wrapper.Unit#UNIT}. These AI\_ classes derive the @{#FSM_CONTROLLABLE} class. +-- * an acronym **TASK\_**, which indicates a FSM implementation executing a @{Tasking.Task#TASK} executed by Groups of players. These TASK\_ classes derive the @{#FSM_TASK} class. +-- * an acronym **ACT\_**, which indicates an Sub-FSM implementation, directing **Humans actions** that need to be done in a @{Tasking.Task#TASK}, seated in a @{Wrapper.Client#CLIENT} (slot) or a @{Wrapper.Unit#UNIT} (CA join). These ACT\_ classes derive the @{#FSM_PROCESS} class. -- -- Detailed explanations and API specifics are further below clarified and FSM derived class specifics are described in those class documentation sections. -- @@ -61,10 +61,10 @@ -- -- The following derived classes are available in the MOOSE framework, that implement a specialized form of a FSM: -- --- * @{#FSM_TASK}: Models Finite State Machines for @{Task}s. --- * @{#FSM_PROCESS}: Models Finite State Machines for @{Task} actions, which control @{Client}s. --- * @{#FSM_CONTROLLABLE}: Models Finite State Machines for @{Wrapper.Controllable}s, which are @{Wrapper.Group}s, @{Wrapper.Unit}s, @{Client}s. --- * @{#FSM_SET}: Models Finite State Machines for @{Set}s. Note that these FSMs control multiple objects!!! So State concerns here +-- * @{#FSM_TASK}: Models Finite State Machines for @{Tasking.Task}s. +-- * @{#FSM_PROCESS}: Models Finite State Machines for @{Tasking.Task} actions, which control @{Wrapper.Client}s. +-- * @{#FSM_CONTROLLABLE}: Models Finite State Machines for @{Wrapper.Controllable}s, which are @{Wrapper.Group}s, @{Wrapper.Unit}s, @{Wrapper.Client}s. +-- * @{#FSM_SET}: Models Finite State Machines for @{Core.Set}s. Note that these FSMs control multiple objects!!! So State concerns here -- for multiple objects or the position of the state machine in the process. -- -- === @@ -119,9 +119,9 @@ do -- FSM -- and tailored** by mission designers through **the implementation of Transition Handlers**. -- Each of these FSM implementation classes start either with: -- - -- * an acronym **AI\_**, which indicates an FSM implementation directing **AI controlled** @{GROUP} and/or @{UNIT}. These AI\_ classes derive the @{#FSM_CONTROLLABLE} class. - -- * an acronym **TASK\_**, which indicates an FSM implementation executing a @{TASK} executed by Groups of players. These TASK\_ classes derive the @{#FSM_TASK} class. - -- * an acronym **ACT\_**, which indicates an Sub-FSM implementation, directing **Humans actions** that need to be done in a @{TASK}, seated in a @{CLIENT} (slot) or a @{UNIT} (CA join). These ACT\_ classes derive the @{#FSM_PROCESS} class. + -- * an acronym **AI\_**, which indicates an FSM implementation directing **AI controlled** @{Wrapper.Group#GROUP} and/or @{Wrapper.Unit#UNIT}. These AI\_ classes derive the @{#FSM_CONTROLLABLE} class. + -- * an acronym **TASK\_**, which indicates an FSM implementation executing a @{Tasking.Task#TASK} executed by Groups of players. These TASK\_ classes derive the @{#FSM_TASK} class. + -- * an acronym **ACT\_**, which indicates an Sub-FSM implementation, directing **Humans actions** that need to be done in a @{Tasking.Task#TASK}, seated in a @{Wrapper.Client#CLIENT} (slot) or a @{Wrapper.Unit#UNIT} (CA join). These ACT\_ classes derive the @{#FSM_PROCESS} class. -- -- ![Transition Rules and Transition Handlers and Event Triggers](..\Presentations\FSM\Dia3.JPG) -- @@ -418,7 +418,7 @@ do -- FSM return self._Transitions or {} end - --- Set the default @{Process} template with key ProcessName providing the ProcessClass and the process object when it is assigned to a @{Wrapper.Controllable} by the task. + --- Set the default @{#FSM_PROCESS} template with key ProcessName providing the ProcessClass and the process object when it is assigned to a @{Wrapper.Controllable} by the task. -- @param #FSM self -- @param #table From Can contain a string indicating the From state or a table of strings containing multiple From states. -- @param #string Event The Event name. @@ -953,7 +953,7 @@ do -- FSM_CONTROLLABLE -- @field Wrapper.Controllable#CONTROLLABLE Controllable -- @extends Core.Fsm#FSM - --- Models Finite State Machines for @{Wrapper.Controllable}s, which are @{Wrapper.Group}s, @{Wrapper.Unit}s, @{Client}s. + --- Models Finite State Machines for @{Wrapper.Controllable}s, which are @{Wrapper.Group}s, @{Wrapper.Unit}s, @{Wrapper.Client}s. -- -- === -- @@ -1086,7 +1086,7 @@ do -- FSM_PROCESS -- @field Tasking.Task#TASK Task -- @extends Core.Fsm#FSM_CONTROLLABLE - --- FSM_PROCESS class models Finite State Machines for @{Task} actions, which control @{Client}s. + --- FSM_PROCESS class models Finite State Machines for @{Tasking.Task} actions, which control @{Wrapper.Client}s. -- -- === -- @@ -1241,7 +1241,7 @@ do -- FSM_PROCESS -- TODO: Need to check and fix that an FSM_PROCESS is only for a UNIT. Not for a GROUP. - --- Send a message of the @{Task} to the Group of the Unit. + --- Send a message of the @{Tasking.Task} to the Group of the Unit. -- @param #FSM_PROCESS self function FSM_PROCESS:Message( Message ) self:F( { Message = Message } ) @@ -1382,7 +1382,7 @@ do -- FSM_SET -- @field Core.Set#SET_BASE Set -- @extends Core.Fsm#FSM - --- FSM_SET class models Finite State Machines for @{Set}s. Note that these FSMs control multiple objects!!! So State concerns here + --- FSM_SET class models Finite State Machines for @{Core.Set}s. Note that these FSMs control multiple objects!!! So State concerns here -- for multiple objects or the position of the state machine in the process. -- -- === diff --git a/Moose Development/Moose/Core/MarkerOps_Base.lua b/Moose Development/Moose/Core/MarkerOps_Base.lua index 12095c5d9..5e5aa273f 100644 --- a/Moose Development/Moose/Core/MarkerOps_Base.lua +++ b/Moose Development/Moose/Core/MarkerOps_Base.lua @@ -1,4 +1,4 @@ ---- **Core** - MarkerOps_Base. +--- **Core** - Tap into markers added to the F10 map by users. -- -- **Main Features:** -- diff --git a/Moose Development/Moose/Core/Message.lua b/Moose Development/Moose/Core/Message.lua index 888ae3779..51c307c2e 100644 --- a/Moose Development/Moose/Core/Message.lua +++ b/Moose Development/Moose/Core/Message.lua @@ -34,7 +34,7 @@ -- -- Messages are sent: -- --- * To a @{Client} using @{#MESSAGE.ToClient}(). +-- * To a @{Wrapper.Client} using @{#MESSAGE.ToClient}(). -- * To a @{Wrapper.Group} using @{#MESSAGE.ToGroup}() -- * To a @{Wrapper.Unit} using @{#MESSAGE.ToUnit}() -- * To a coalition using @{#MESSAGE.ToCoalition}(). @@ -128,7 +128,7 @@ end --- Creates a new MESSAGE object of a certain type. -- Note that these MESSAGE objects are not yet displayed on the display panel. -- You must use the functions @{ToClient} or @{ToCoalition} or @{ToAll} to send these Messages to the respective recipients. --- The message display times are automatically defined based on the timing settings in the @{Settings} menu. +-- The message display times are automatically defined based on the timing settings in the @{Core.Settings} menu. -- @param self -- @param #string MessageText is the text of the Message. -- @param #MESSAGE.Type MessageType The type of the message. @@ -171,7 +171,7 @@ end --- Sends a MESSAGE to a Client Group. Note that the Group needs to be defined within the ME with the skillset "Client" or "Player". -- @param #MESSAGE self -- @param Wrapper.Client#CLIENT Client is the Group of the Client. --- @param Core.Settings#SETTINGS Settings Settings used to display the message. +-- @param Core.Settings#SETTINGS Settings used to display the message. -- @return #MESSAGE -- @usage -- @@ -182,11 +182,11 @@ end -- MessageClient1 = MESSAGE:New( "Congratulations, you've just hit a target", "Score", 25, "Score" ):ToClient( ClientGroup ) -- MessageClient2 = MESSAGE:New( "Congratulations, you've just killed a target", "Score", 25, "Score" ):ToClient( ClientGroup ) -- or --- MESSAGE:New( "Congratulations, you've just hit a target", "Score", 25, "Score" ):ToClient( ClientGroup ) --- MESSAGE:New( "Congratulations, you've just killed a target", "Score", 25, "Score" ):ToClient( ClientGroup ) +-- MESSAGE:New( "Congratulations, you've just hit a target", "Score", 25 ):ToClient( ClientGroup ) +-- MESSAGE:New( "Congratulations, you've just killed a target", "Score", 25 ):ToClient( ClientGroup ) -- or --- MessageClient1 = MESSAGE:New( "Congratulations, you've just hit a target", "Score", 25, "Score" ) --- MessageClient2 = MESSAGE:New( "Congratulations, you've just killed a target", "Score", 25, "Score" ) +-- MessageClient1 = MESSAGE:New( "Congratulations, you've just hit a target", "Score", 25 ) +-- MessageClient2 = MESSAGE:New( "Congratulations, you've just killed a target", "Score", 25 ) -- MessageClient1:ToClient( ClientGroup ) -- MessageClient2:ToClient( ClientGroup ) -- @@ -217,6 +217,7 @@ end --- Sends a MESSAGE to a Group. -- @param #MESSAGE self -- @param Wrapper.Group#GROUP Group to which the message is displayed. +-- @param Core.Settings#Settings Settings (Optional) Settings for message display. -- @return #MESSAGE Message object. function MESSAGE:ToGroup( Group, Settings ) self:F( Group.GroupName ) @@ -241,6 +242,7 @@ end --- Sends a MESSAGE to a Unit. -- @param #MESSAGE self -- @param Wrapper.Unit#UNIT Unit to which the message is displayed. +-- @param Core.Settings#Settings Settings (Optional) Settings for message display. -- @return #MESSAGE Message object. function MESSAGE:ToUnit( Unit, Settings ) self:F( Unit.IdentifiableName ) @@ -262,27 +264,38 @@ function MESSAGE:ToUnit( Unit, Settings ) return self end ---- Sends a MESSAGE to a Unit. +--- Sends a MESSAGE to a Country. -- @param #MESSAGE self --- @param Wrapper.Unit#UNIT Unit to which the message is displayed. +-- @param #number Country to which the message is displayed, e.g. country.id.GERMANY. For all country numbers see here: [Hoggit Wiki](https://wiki.hoggitworld.com/view/DCS_enum_country) +-- @param Core.Settings#Settings Settings (Optional) Settings for message display. -- @return #MESSAGE Message object. -function MESSAGE:ToUnit( Unit, Settings ) - self:F( Unit.IdentifiableName ) - - if Unit then - +function MESSAGE:ToCountry( Country, Settings ) + self:F(Country ) + if Country then if self.MessageType then - local Settings = Settings or ( Unit and _DATABASE:GetPlayerSettings( Unit:GetPlayerName() ) ) or _SETTINGS -- Core.Settings#SETTINGS + local Settings = Settings or _SETTINGS -- Core.Settings#SETTINGS self.MessageDuration = Settings:GetMessageTime( self.MessageType ) self.MessageCategory = "" -- self.MessageType .. ": " end - if self.MessageDuration ~= 0 then self:T( self.MessageCategory .. self.MessageText:gsub("\n$",""):gsub("\n$","") .. " / " .. self.MessageDuration ) - trigger.action.outTextForUnit( Unit:GetID(), self.MessageCategory .. self.MessageText:gsub("\n$",""):gsub("\n$",""), self.MessageDuration, self.ClearScreen ) + trigger.action.outTextForCountry( Country, self.MessageCategory .. self.MessageText:gsub("\n$",""):gsub("\n$",""), self.MessageDuration, self.ClearScreen ) end + end + return self +end + +--- Sends a MESSAGE to a Country. +-- @param #MESSAGE self +-- @param #number Country to which the message is displayed, , e.g. country.id.GERMANY. For all country numbers see here: [Hoggit Wiki](https://wiki.hoggitworld.com/view/DCS_enum_country) +-- @param #boolean Condition Sends the message only if the condition is true. +-- @param Core.Settings#Settings Settings (Optional) Settings for message display. +-- @return #MESSAGE Message object. +function MESSAGE:ToCountryIf( Country, Condition, Settings ) + self:F(Country ) + if Country and Condition == true then + self:ToCountry( Country, Settings ) end - return self end @@ -292,11 +305,11 @@ end -- @usage -- -- -- Send a message created with the @{New} method to the BLUE coalition. --- MessageBLUE = MESSAGE:New( "To the BLUE Players: You receive a penalty because you've killed one of your own units", "Penalty", 25, "Score" ):ToBlue() +-- MessageBLUE = MESSAGE:New( "To the BLUE Players: You receive a penalty because you've killed one of your own units", "Penalty", 25):ToBlue() -- or --- MESSAGE:New( "To the BLUE Players: You receive a penalty because you've killed one of your own units", "Penalty", 25, "Score" ):ToBlue() +-- MESSAGE:New( "To the BLUE Players: You receive a penalty because you've killed one of your own units", "Penalty", 25 ):ToBlue() -- or --- MessageBLUE = MESSAGE:New( "To the BLUE Players: You receive a penalty because you've killed one of your own units", "Penalty", 25, "Score" ) +-- MessageBLUE = MESSAGE:New( "To the BLUE Players: You receive a penalty because you've killed one of your own units", "Penalty", 25 ) -- MessageBLUE:ToBlue() -- function MESSAGE:ToBlue() @@ -313,11 +326,11 @@ end -- @usage -- -- -- Send a message created with the @{New} method to the RED coalition. --- MessageRED = MESSAGE:New( "To the RED Players: You receive a penalty because you've killed one of your own units", "Penalty", 25, "Score" ):ToRed() +-- MessageRED = MESSAGE:New( "To the RED Players: You receive a penalty because you've killed one of your own units", "Penalty", 25 ):ToRed() -- or --- MESSAGE:New( "To the RED Players: You receive a penalty because you've killed one of your own units", "Penalty", 25, "Score" ):ToRed() +-- MESSAGE:New( "To the RED Players: You receive a penalty because you've killed one of your own units", "Penalty", 25 ):ToRed() -- or --- MessageRED = MESSAGE:New( "To the RED Players: You receive a penalty because you've killed one of your own units", "Penalty", 25, "Score" ) +-- MessageRED = MESSAGE:New( "To the RED Players: You receive a penalty because you've killed one of your own units", "Penalty", 25 ) -- MessageRED:ToRed() -- function MESSAGE:ToRed() @@ -336,11 +349,11 @@ end -- @usage -- -- -- Send a message created with the @{New} method to the RED coalition. --- MessageRED = MESSAGE:New( "To the RED Players: You receive a penalty because you've killed one of your own units", "Penalty", 25, "Score" ):ToCoalition( coalition.side.RED ) +-- MessageRED = MESSAGE:New( "To the RED Players: You receive a penalty because you've killed one of your own units", "Penalty", 25 ):ToCoalition( coalition.side.RED ) -- or --- MESSAGE:New( "To the RED Players: You receive a penalty because you've killed one of your own units", "Penalty", 25, "Score" ):ToCoalition( coalition.side.RED ) +-- MESSAGE:New( "To the RED Players: You receive a penalty because you've killed one of your own units", "Penalty", 25 ):ToCoalition( coalition.side.RED ) -- or --- MessageRED = MESSAGE:New( "To the RED Players: You receive a penalty because you've killed one of your own units", "Penalty", 25, "Score" ) +-- MessageRED = MESSAGE:New( "To the RED Players: You receive a penalty because you've killed one of your own units", "Penalty", 25 ) -- MessageRED:ToCoalition( coalition.side.RED ) -- function MESSAGE:ToCoalition( CoalitionSide, Settings ) @@ -384,11 +397,11 @@ end -- @usage -- -- -- Send a message created to all players. --- MessageAll = MESSAGE:New( "To all Players: BLUE has won! Each player of BLUE wins 50 points!", "End of Mission", 25, "Win" ):ToAll() +-- MessageAll = MESSAGE:New( "To all Players: BLUE has won! Each player of BLUE wins 50 points!", "End of Mission", 25 ):ToAll() -- or --- MESSAGE:New( "To all Players: BLUE has won! Each player of BLUE wins 50 points!", "End of Mission", 25, "Win" ):ToAll() +-- MESSAGE:New( "To all Players: BLUE has won! Each player of BLUE wins 50 points!", "End of Mission", 25 ):ToAll() -- or --- MessageAll = MESSAGE:New( "To all Players: BLUE has won! Each player of BLUE wins 50 points!", "End of Mission", 25, "Win" ) +-- MessageAll = MESSAGE:New( "To all Players: BLUE has won! Each player of BLUE wins 50 points!", "End of Mission", 25 ) -- MessageAll:ToAll() -- function MESSAGE:ToAll( Settings ) @@ -410,6 +423,7 @@ end --- Sends a MESSAGE to all players if the given Condition is true. -- @param #MESSAGE self +-- @param #boolean Condition -- @return #MESSAGE function MESSAGE:ToAllIf( Condition ) diff --git a/Moose Development/Moose/Core/Point.lua b/Moose Development/Moose/Core/Point.lua index 6d6ac18df..fe4863f54 100644 --- a/Moose Development/Moose/Core/Point.lua +++ b/Moose Development/Moose/Core/Point.lua @@ -138,7 +138,7 @@ do -- COORDINATE -- -- Calculate if the coordinate has Line of Sight (LOS) with the other given coordinate. -- Mountains, trees and other objects can be positioned between the two 3D points, preventing visibilty in a straight continuous line. - -- The method @{#COORDINATE.IsLOS}() returns if the two coodinates have LOS. + -- The method @{#COORDINATE.IsLOS}() returns if the two coordinates have LOS. -- -- ## 4.7) Check the coordinate position. -- @@ -594,7 +594,7 @@ do -- COORDINATE --- Scan/find SCENERY objects within a certain radius around the coordinate using the world.searchObjects() DCS API function. -- @param #COORDINATE self -- @param #number radius (Optional) Scan radius in meters. Default 100 m. - -- @return table Set of scenery objects. + -- @return table Table of SCENERY objects. function COORDINATE:ScanScenery(radius) local _,_,_,_,_,scenerys=self:ScanObjects(radius, false, false, true) @@ -654,7 +654,7 @@ do -- COORDINATE -- @param DCS#Distance Distance The Distance to be added in meters. -- @param DCS#Angle Angle The Angle in degrees. Defaults to 0 if not specified (nil). -- @param #boolean Keepalt If true, keep altitude of original coordinate. Default is that the new coordinate is created at the translated land height. - -- @param #boolean Overwrite If true, overwrite the original COORDINATE with the translated one. Otherwise, create a new COODINATE. + -- @param #boolean Overwrite If true, overwrite the original COORDINATE with the translated one. Otherwise, create a new COORDINATE. -- @return #COORDINATE The new calculated COORDINATE. function COORDINATE:Translate( Distance, Angle, Keepalt, Overwrite ) @@ -923,7 +923,7 @@ do -- COORDINATE return T-273.15 end - --- Returns a text of the temperature according the measurement system @{Settings}. + --- Returns a text of the temperature according the measurement system @{Core.Settings}. -- The text will reflect the temperature like this: -- -- - For Russian and European aircraft using the metric system - Degrees Celcius (°C) @@ -936,7 +936,7 @@ do -- COORDINATE -- -- @param #COORDINATE self -- @param height (Optional) parameter specifying the height ASL. - -- @return #string Temperature according the measurement system @{Settings}. + -- @return #string Temperature according the measurement system @{Core.Settings}. function COORDINATE:GetTemperatureText( height, Settings ) local DegreesCelcius = self:GetTemperature( height ) @@ -969,7 +969,7 @@ do -- COORDINATE return P/100 end - --- Returns a text of the pressure according the measurement system @{Settings}. + --- Returns a text of the pressure according the measurement system @{Core.Settings}. -- The text will contain always the pressure in hPa and: -- -- - For Russian and European aircraft using the metric system - hPa and mmHg @@ -982,7 +982,7 @@ do -- COORDINATE -- -- @param #COORDINATE self -- @param height (Optional) parameter specifying the height ASL. E.g. set height=0 for QNH. - -- @return #string Pressure in hPa and mmHg or inHg depending on the measurement system @{Settings}. + -- @return #string Pressure in hPa and mmHg or inHg depending on the measurement system @{Core.Settings}. function COORDINATE:GetPressureText( height, Settings ) local Pressure_hPa = self:GetPressure( height ) @@ -1062,7 +1062,7 @@ do -- COORDINATE end - --- Returns a text documenting the wind direction (from) and strength according the measurement system @{Settings}. + --- Returns a text documenting the wind direction (from) and strength according the measurement system @{Core.Settings}. -- The text will reflect the wind like this: -- -- - For Russian and European aircraft using the metric system - Wind direction in degrees (°) and wind speed in meters per second (mps). @@ -1075,7 +1075,7 @@ do -- COORDINATE -- -- @param #COORDINATE self -- @param height (Optional) parameter specifying the height ASL. The minimum height will be always be the land height since the wind is zero below the ground. - -- @return #string Wind direction and strength according the measurement system @{Settings}. + -- @return #string Wind direction and strength according the measurement system @{Core.Settings}. function COORDINATE:GetWindText( height, Settings ) local Direction, Strength = self:GetWind( height ) @@ -1111,15 +1111,25 @@ do -- COORDINATE -- @param #number AngleRadians The angle in randians. -- @param #number Precision The precision. -- @param Core.Settings#SETTINGS Settings + -- @param #boolean MagVar If true, include magentic degrees -- @return #string The bearing text in degrees. - function COORDINATE:GetBearingText( AngleRadians, Precision, Settings, Language ) + function COORDINATE:GetBearingText( AngleRadians, Precision, Settings, MagVar ) local Settings = Settings or _SETTINGS -- Core.Settings#SETTINGS local AngleDegrees = UTILS.Round( UTILS.ToDegree( AngleRadians ), Precision ) local s = string.format( '%03d°', AngleDegrees ) - + + if MagVar then + local variation = UTILS.GetMagneticDeclination() or 0 + local AngleMagnetic = AngleDegrees - variation + + if AngleMagnetic < 0 then AngleMagnetic = 360-AngleMagnetic end + + s = string.format( '%03d°M|%03d°', AngleMagnetic,AngleDegrees ) + end + return s end @@ -1133,21 +1143,22 @@ do -- COORDINATE function COORDINATE:GetDistanceText( Distance, Settings, Language, Precision ) local Settings = Settings or _SETTINGS -- Core.Settings#SETTINGS - local Language = Language or "EN" + local Language = Language or Settings.Locale or _SETTINGS.Locale or "EN" + Language = string.lower(Language) local Precision = Precision or 0 local DistanceText if Settings:IsMetric() then - if Language == "EN" then + if Language == "en" then DistanceText = " for " .. UTILS.Round( Distance / 1000, Precision ) .. " km" - elseif Language == "RU" then + elseif Language == "ru" then DistanceText = " за " .. UTILS.Round( Distance / 1000, Precision ) .. " километров" end else - if Language == "EN" then + if Language == "en" then DistanceText = " for " .. UTILS.Round( UTILS.MetersToNM( Distance ), Precision ) .. " miles" - elseif Language == "RU" then + elseif Language == "ru" then DistanceText = " за " .. UTILS.Round( UTILS.MetersToNM( Distance ), Precision ) .. " миль" end end @@ -1161,19 +1172,21 @@ do -- COORDINATE function COORDINATE:GetAltitudeText( Settings, Language ) local Altitude = self.y local Settings = Settings or _SETTINGS - local Language = Language or "EN" - + local Language = Language or Settings.Locale or _SETTINGS.Locale or "EN" + + Language = string.lower(Language) + if Altitude ~= 0 then if Settings:IsMetric() then - if Language == "EN" then + if Language == "en" then return " at " .. UTILS.Round( self.y, -3 ) .. " meters" - elseif Language == "RU" then + elseif Language == "ru" then return " в " .. UTILS.Round( self.y, -3 ) .. " метры" end else - if Language == "EN" then + if Language == "en" then return " at " .. UTILS.Round( UTILS.MetersToFeet( self.y ), -3 ) .. " feet" - elseif Language == "RU" then + elseif Language == "ru" then return " в " .. UTILS.Round( self.y, -3 ) .. " ноги" end end @@ -1220,12 +1233,14 @@ do -- COORDINATE -- @param #number AngleRadians The angle in randians -- @param #number Distance The distance -- @param Core.Settings#SETTINGS Settings + -- @param #string Language (Optional) Language "en" or "ru" + -- @param #boolean MagVar If true, also state angle in magnetic -- @return #string The BR Text - function COORDINATE:GetBRText( AngleRadians, Distance, Settings, Language ) + function COORDINATE:GetBRText( AngleRadians, Distance, Settings, Language, MagVar ) local Settings = Settings or _SETTINGS -- Core.Settings#SETTINGS - local BearingText = self:GetBearingText( AngleRadians, 0, Settings, Language ) + local BearingText = self:GetBearingText( AngleRadians, 0, Settings, MagVar ) local DistanceText = self:GetDistanceText( Distance, Settings, Language, 0 ) local BRText = BearingText .. DistanceText @@ -1238,12 +1253,14 @@ do -- COORDINATE -- @param #number AngleRadians The angle in randians -- @param #number Distance The distance -- @param Core.Settings#SETTINGS Settings + -- @param #string Language (Optional) Language "en" or "ru" + -- @param #boolean MagVar If true, also state angle in magnetic -- @return #string The BRA Text - function COORDINATE:GetBRAText( AngleRadians, Distance, Settings, Language ) + function COORDINATE:GetBRAText( AngleRadians, Distance, Settings, Language, MagVar ) local Settings = Settings or _SETTINGS -- Core.Settings#SETTINGS - local BearingText = self:GetBearingText( AngleRadians, 0, Settings, Language ) + local BearingText = self:GetBearingText( AngleRadians, 0, Settings, MagVar ) local DistanceText = self:GetDistanceText( Distance, Settings, Language, 0 ) local AltitudeText = self:GetAltitudeText( Settings, Language ) @@ -1519,7 +1536,7 @@ do -- COORDINATE -- @param #number Coalition (Optional) Coalition of the airbase. -- @return Wrapper.Airbase#AIRBASE Closest Airbase to the given coordinate. -- @return #number Distance to the closest airbase in meters. - function COORDINATE:GetClosestAirbase2(Category, Coalition) + function COORDINATE:GetClosestAirbase(Category, Coalition) -- Get all airbases of the map. local airbases=AIRBASE.GetAllAirbases(Coalition) @@ -1553,34 +1570,15 @@ do -- COORDINATE return closest,distmin end - --- Gets the nearest airbase with respect to the current coordinates. + --- [kept for downwards compatibility only] Gets the nearest airbase with respect to the current coordinates. -- @param #COORDINATE self -- @param #number Category (Optional) Category of the airbase. Enumerator of @{Wrapper.Airbase#AIRBASE.Category}. -- @param #number Coalition (Optional) Coalition of the airbase. -- @return Wrapper.Airbase#AIRBASE Closest Airbase to the given coordinate. -- @return #number Distance to the closest airbase in meters. - function COORDINATE:GetClosestAirbase(Category, Coalition) - - local a=self:GetVec3() - - local distmin=math.huge - local airbase=nil - for DCSairbaseID, DCSairbase in pairs(world.getAirbases(Coalition)) do - local b=DCSairbase:getPoint() - - local c=UTILS.VecSubstract(a,b) - local dist=UTILS.VecNorm(c) - - --env.info(string.format("Airbase %s dist=%d category=%d", DCSairbase:getName(), dist, DCSairbase:getCategory())) - - if dist x2 ) and Coordinate.x or x2 + y1 = ( Coordinate.y < y1 ) and Coordinate.y or y1 + y2 = ( Coordinate.y > y2 ) and Coordinate.y or y2 + z1 = ( Coordinate.y < z1 ) and Coordinate.z or z1 + z2 = ( Coordinate.y > z2 ) and Coordinate.z or z2 + + end + + Coordinate.x = ( x2 - x1 ) / 2 + x1 + Coordinate.y = ( y2 - y1 ) / 2 + y1 + Coordinate.z = ( z2 - z1 ) / 2 + z1 + + self:F( { Coordinate = Coordinate } ) + return Coordinate + + end + + --- + -- @param #SET_SCENERY self + -- @param Wrapper.Scenery#SCENERY MScenery + -- @return #SET_SCENERY self + function SET_SCENERY:IsIncludeObject( MScenery ) + self:F2( MScenery ) + return true + end +end diff --git a/Moose Development/Moose/Core/Settings.lua b/Moose Development/Moose/Core/Settings.lua index 8dd213952..671b4cfb0 100644 --- a/Moose Development/Moose/Core/Settings.lua +++ b/Moose Development/Moose/Core/Settings.lua @@ -1,4 +1,4 @@ ---- **Core** - Manages various settings for running missions, consumed by moose classes and provides a menu system for players to tweak settings in running missions. +--- **Core** - Manages various settings for missions, providing a menu for players to tweak settings in running missions. -- -- === -- @@ -335,7 +335,7 @@ do -- SETTINGS --- Sets the SETTINGS MGRS accuracy. -- @param #SETTINGS self - -- @param #number MGRS_Accuracy + -- @param #number MGRS_Accuracy 0 to 5 -- @return #SETTINGS function SETTINGS:SetMGRS_Accuracy( MGRS_Accuracy ) self.MGRS_Accuracy = MGRS_Accuracy diff --git a/Moose Development/Moose/Core/Spawn.lua b/Moose Development/Moose/Core/Spawn.lua index e37570f35..9c5225a0b 100644 --- a/Moose Development/Moose/Core/Spawn.lua +++ b/Moose Development/Moose/Core/Spawn.lua @@ -167,7 +167,7 @@ -- -- * @{#SPAWN.InitRandomizePosition}(): Randomizes the position of @{Wrapper.Group}s that are spawned within a **radius band**, given an Outer and Inner radius, from the point that the spawn happens. -- * @{#SPAWN.InitRandomizeUnits}(): Randomizes the @{Wrapper.Unit}s in the @{Wrapper.Group} that is spawned within a **radius band**, given an Outer and Inner radius. --- * @{#SPAWN.InitRandomizeZones}(): Randomizes the spawning between a predefined list of @{Zone}s that are declared using this function. Each zone can be given a probability factor. +-- * @{#SPAWN.InitRandomizeZones}(): Randomizes the spawning between a predefined list of @{Core.Zone}s that are declared using this function. Each zone can be given a probability factor. -- -- ### Enable / Disable AI when spawning a new @{Wrapper.Group} -- @@ -200,13 +200,13 @@ -- * @{#SPAWN.ReSpawn}(): Re-spawn a group based on a given index. -- * @{#SPAWN.SpawnFromVec3}(): Spawn a new group from a Vec3 coordinate. (The group will can be spawned at a point in the air). -- * @{#SPAWN.SpawnFromVec2}(): Spawn a new group from a Vec2 coordinate. (The group will be spawned at land height ). --- * @{#SPAWN.SpawnFromStatic}(): Spawn a new group from a structure, taking the position of a @{Static}. +-- * @{#SPAWN.SpawnFromStatic}(): Spawn a new group from a structure, taking the position of a @{Wrapper.Static}. -- * @{#SPAWN.SpawnFromUnit}(): Spawn a new group taking the position of a @{Wrapper.Unit}. --- * @{#SPAWN.SpawnInZone}(): Spawn a new group in a @{Zone}. +-- * @{#SPAWN.SpawnInZone}(): Spawn a new group in a @{Core.Zone}. -- * @{#SPAWN.SpawnAtAirbase}(): Spawn a new group at an @{Wrapper.Airbase}, which can be an airdrome, ship or helipad. -- -- Note that @{#SPAWN.Spawn} and @{#SPAWN.ReSpawn} return a @{Wrapper.Group#GROUP.New} object, that contains a reference to the DCSGroup object. --- You can use the @{GROUP} object to do further actions with the DCSGroup. +-- You can use the @{Wrapper.Group#GROUP} object to do further actions with the DCSGroup. -- -- ### **Scheduled** spawning methods -- @@ -765,7 +765,7 @@ end --- Randomizes the UNITs that are spawned within a radius band given an Outer and Inner radius. -- @param #SPAWN self --- @param #boolean RandomizeUnits If true, SPAWN will perform the randomization of the @{UNIT}s position within the group between a given outer and inner radius. +-- @param #boolean RandomizeUnits If true, SPAWN will perform the randomization of the @{Wrapper.Unit#UNIT}s position within the group between a given outer and inner radius. -- @param DCS#Distance OuterRadius (optional) The outer radius in meters where the new group will be spawned. -- @param DCS#Distance InnerRadius (optional) The inner radius in meters where the new group will NOT be spawned. -- @return #SPAWN @@ -813,8 +813,13 @@ end -- Spawn_US_Platoon_Right = SPAWN:New( 'US Tank Platoon Right' ):InitLimit( 12, 150 ):SpawnScheduled( 200, 0.4 ):InitRandomizeTemplate( Spawn_US_Platoon ):InitRandomizeRoute( 3, 3, 2000 ) function SPAWN:InitRandomizeTemplate( SpawnTemplatePrefixTable ) self:F( { self.SpawnTemplatePrefix, SpawnTemplatePrefixTable } ) - - self.SpawnTemplatePrefixTable = SpawnTemplatePrefixTable + + local temptable = {} + for _,_temp in pairs(SpawnTemplatePrefixTable) do + temptable[#temptable+1] = _temp + end + + self.SpawnTemplatePrefixTable = UTILS.ShuffleTable(temptable) self.SpawnRandomizeTemplate = true for SpawnGroupID = 1, self.SpawnMaxGroups do @@ -848,16 +853,12 @@ end -- Spawn_US_Platoon_Middle = SPAWN:New( 'US Tank Platoon Middle' ):InitLimit( 12, 150 ):SpawnScheduled( 200, 0.4 ):InitRandomizeTemplateSet( Spawn_US_PlatoonSet ):InitRandomizeRoute( 3, 3, 2000 ) -- Spawn_US_Platoon_Right = SPAWN:New( 'US Tank Platoon Right' ):InitLimit( 12, 150 ):SpawnScheduled( 200, 0.4 ):InitRandomizeTemplateSet( Spawn_US_PlatoonSet ):InitRandomizeRoute( 3, 3, 2000 ) -- -function SPAWN:InitRandomizeTemplateSet( SpawnTemplateSet ) -- R2.3 +function SPAWN:InitRandomizeTemplateSet( SpawnTemplateSet ) self:F( { self.SpawnTemplatePrefix } ) - self.SpawnTemplatePrefixTable = SpawnTemplateSet:GetSetNames() - self.SpawnRandomizeTemplate = true - - for SpawnGroupID = 1, self.SpawnMaxGroups do - self:_RandomizeTemplate( SpawnGroupID ) - end - + local setnames = SpawnTemplateSet:GetSetNames() + self:InitRandomizeTemplate(setnames) + return self end @@ -906,7 +907,7 @@ end --- This method provides the functionality to randomize the spawning of the Groups at a given list of zones of different types. -- @param #SPAWN self --- @param #table SpawnZoneTable A table with @{Zone} objects. If this table is given, then each spawn will be executed within the given list of @{Zone}s objects. +-- @param #table SpawnZoneTable A table with @{Core.Zone} objects. If this table is given, then each spawn will be executed within the given list of @{Core.Zone}s objects. -- @return #SPAWN -- @usage -- @@ -921,8 +922,13 @@ end -- function SPAWN:InitRandomizeZones( SpawnZoneTable ) self:F( { self.SpawnTemplatePrefix, SpawnZoneTable } ) - - self.SpawnZoneTable = SpawnZoneTable + + local temptable = {} + for _,_temp in pairs(SpawnZoneTable) do + temptable[#temptable+1] = _temp + end + + self.SpawnZoneTable = UTILS.ShuffleTable(temptable) self.SpawnRandomizeZones = true for SpawnGroupID = 1, self.SpawnMaxGroups do @@ -1159,7 +1165,7 @@ do -- Delay methods end -- Delay methods --- Will spawn a group based on the internal index. --- Note: Uses @{DATABASE} module defined in MOOSE. +-- Note: This method uses the global _DATABASE object (an instance of @{Core.Database#DATABASE}), which contains ALL initial and new spawned objects in MOOSE. -- @param #SPAWN self -- @return Wrapper.Group#GROUP The group that was spawned. You can use this group for further actions. function SPAWN:Spawn() @@ -1174,7 +1180,7 @@ function SPAWN:Spawn() end --- Will re-spawn a group based on a given index. --- Note: Uses @{DATABASE} module defined in MOOSE. +-- Note: This method uses the global _DATABASE object (an instance of @{Core.Database#DATABASE}), which contains ALL initial and new spawned objects in MOOSE. -- @param #SPAWN self -- @param #string SpawnIndex The index of the group to be spawned. -- @return Wrapper.Group#GROUP The group that was spawned. You can use this group for further actions. @@ -1222,7 +1228,7 @@ function SPAWN:SetSpawnIndex( SpawnIndex ) end --- Will spawn a group with a specified index number. --- Uses @{DATABASE} global object defined in MOOSE. +-- Note: This method uses the global _DATABASE object (an instance of @{Core.Database#DATABASE}), which contains ALL initial and new spawned objects in MOOSE. -- @param #SPAWN self -- @param #string SpawnIndex The index of the group to be spawned. -- @return Wrapper.Group#GROUP The group that was spawned. You can use this group for further actions. @@ -2615,8 +2621,8 @@ function SPAWN:SpawnFromStatic( HostStatic, MinHeight, MaxHeight, SpawnIndex ) return nil end ---- Will spawn a Group within a given @{Zone}. --- The @{Zone} can be of any type derived from @{Core.Zone#ZONE_BASE}. +--- Will spawn a Group within a given @{Core.Zone}. +-- The @{Core.Zone} can be of any type derived from @{Core.Zone#ZONE_BASE}. -- Once the @{Wrapper.Group} is spawned within the zone, the @{Wrapper.Group} will continue on its route. -- The **first waypoint** (where the group is spawned) is replaced with the zone location coordinates. -- @param #SPAWN self @@ -2937,7 +2943,7 @@ function SPAWN:_GetGroupCountryID( SpawnPrefix ) end --- Gets the Group Template from the ME environment definition. --- This method used the @{DATABASE} object, which contains ALL initial and new spawned object in MOOSE. +-- Note: This method uses the global _DATABASE object (an instance of @{Core.Database#DATABASE}), which contains ALL initial and new spawned objects in MOOSE. -- @param #SPAWN self -- @param #string SpawnTemplatePrefix -- @return @SPAWN self @@ -3108,7 +3114,7 @@ function SPAWN:_RandomizeTemplate( SpawnIndex ) return self end ---- Private method that randomizes the @{Zone}s where the Group will be spawned. +--- Private method that randomizes the @{Core.Zone}s where the Group will be spawned. -- @param #SPAWN self -- @param #number SpawnIndex -- @return #SPAWN self diff --git a/Moose Development/Moose/Core/SpawnStatic.lua b/Moose Development/Moose/Core/SpawnStatic.lua index b2ad3523d..8508c760f 100644 --- a/Moose Development/Moose/Core/SpawnStatic.lua +++ b/Moose Development/Moose/Core/SpawnStatic.lua @@ -57,15 +57,15 @@ -- @extends Core.Base#BASE ---- Allows to spawn dynamically new @{Static}s into your mission. +--- Allows to spawn dynamically new @{Wrapper.Static}s into your mission. -- -- Through creating a copy of an existing static object template as defined in the Mission Editor (ME), SPAWNSTATIC can retireve the properties of the defined static object template (like type, category etc), -- and "copy" these properties to create a new static object and place it at the desired coordinate. -- --- New spawned @{Static}s get **the same name** as the name of the template Static, or gets the given name when a new name is provided at the Spawn method. --- By default, spawned @{Static}s will follow a naming convention at run-time: +-- New spawned @{Wrapper.Static}s get **the same name** as the name of the template Static, or gets the given name when a new name is provided at the Spawn method. +-- By default, spawned @{Wrapper.Static}s will follow a naming convention at run-time: -- --- * Spawned @{Static}s will have the name _StaticName_#_nnn_, where _StaticName_ is the name of the **Template Static**, and _nnn_ is a **counter from 0 to 99999**. +-- * Spawned @{Wrapper.Static}s will have the name _StaticName_#_nnn_, where _StaticName_ is the name of the **Template Static**, and _nnn_ is a **counter from 0 to 99999**. -- -- # SPAWNSTATIC Constructors -- @@ -106,7 +106,7 @@ -- * @{#SPAWNSTATIC.Spawn}(Heading, NewName) spawns the static with the set parameters. Optionally, heading and name can be given. The name **must be unique**! -- * @{#SPAWNSTATIC.SpawnFromCoordinate}(Coordinate, Heading, NewName) spawn the static at the given coordinate. Optionally, heading and name can be given. The name **must be unique**! -- * @{#SPAWNSTATIC.SpawnFromPointVec2}(PointVec2, Heading, NewName) spawns the static at a POINT_VEC2 coordinate. Optionally, heading and name can be given. The name **must be unique**! --- * @{#SPAWNSTATIC.SpawnFromZone}(Zone, Heading, NewName) spawns the static at the center of a @{Zone}. Optionally, heading and name can be given. The name **must be unique**! +-- * @{#SPAWNSTATIC.SpawnFromZone}(Zone, Heading, NewName) spawns the static at the center of a @{Core.Zone}. Optionally, heading and name can be given. The name **must be unique**! -- -- @field #SPAWNSTATIC SPAWNSTATIC -- @@ -131,7 +131,7 @@ SPAWNSTATIC = { -- @field #number mass Cargo mass in kg. -- @field #boolean canCargo Static can be a cargo. ---- Creates the main object to spawn a @{Static} defined in the mission editor (ME). +--- Creates the main object to spawn a @{Wrapper.Static} defined in the mission editor (ME). -- @param #SPAWNSTATIC self -- @param #string SpawnTemplateName Name of the static object in the ME. Each new static will have the name starting with this prefix. -- @param DCS#country.id SpawnCountryID (Optional) The ID of the country. @@ -158,7 +158,7 @@ function SPAWNSTATIC:NewFromStatic(SpawnTemplateName, SpawnCountryID) return self end ---- Creates the main object to spawn a @{Static} given a template table. +--- Creates the main object to spawn a @{Wrapper.Static} given a template table. -- @param #SPAWNSTATIC self -- @param #table SpawnTemplate Template used for spawning. -- @param DCS#country.id CountryID The ID of the country. Default `country.id.USA`. @@ -174,7 +174,7 @@ function SPAWNSTATIC:NewFromTemplate(SpawnTemplate, CountryID) return self end ---- Creates the main object to spawn a @{Static} from a given type. +--- Creates the main object to spawn a @{Wrapper.Static} from a given type. -- NOTE that you have to init many other parameters as spawn coordinate etc. -- @param #SPAWNSTATIC self -- @param #string StaticType Type of the static. @@ -336,7 +336,7 @@ function SPAWNSTATIC:Spawn(Heading, NewName) end ---- Creates a new @{Static} from a POINT_VEC2. +--- Creates a new @{Wrapper.Static} from a POINT_VEC2. -- @param #SPAWNSTATIC self -- @param Core.Point#POINT_VEC2 PointVec2 The 2D coordinate where to spawn the static. -- @param #number Heading The heading of the static, which is a number in degrees from 0 to 360. @@ -352,7 +352,7 @@ function SPAWNSTATIC:SpawnFromPointVec2(PointVec2, Heading, NewName) end ---- Creates a new @{Static} from a COORDINATE. +--- Creates a new @{Wrapper.Static} from a COORDINATE. -- @param #SPAWNSTATIC self -- @param Core.Point#COORDINATE Coordinate The 3D coordinate where to spawn the static. -- @param #number Heading (Optional) Heading The heading of the static in degrees. Default is 0 degrees. @@ -375,7 +375,7 @@ function SPAWNSTATIC:SpawnFromCoordinate(Coordinate, Heading, NewName) end ---- Creates a new @{Static} from a @{Zone}. +--- Creates a new @{Wrapper.Static} from a @{Core.Zone}. -- @param #SPAWNSTATIC self -- @param Core.Zone#ZONE_BASE Zone The Zone where to spawn the static. -- @param #number Heading (Optional)The heading of the static in degrees. Default is the heading of the template. diff --git a/Moose Development/Moose/Core/Spot.lua b/Moose Development/Moose/Core/Spot.lua index b8dfa0e75..f4dc1f967 100644 --- a/Moose Development/Moose/Core/Spot.lua +++ b/Moose Development/Moose/Core/Spot.lua @@ -249,8 +249,10 @@ do local RecceDcsUnit = self.Recce:GetDCSObject() - self.SpotIR = Spot.createInfraRed( RecceDcsUnit, { x = 0, y = 2, z = 0 }, Target:GetPointVec3():AddY(1):GetVec3() ) - self.SpotLaser = Spot.createLaser( RecceDcsUnit, { x = 0, y = 2, z = 0 }, Target:GetPointVec3():AddY(1):GetVec3(), LaserCode ) + local relativespot = self.relstartpos or { x = 0, y = 2, z = 0 } + + self.SpotIR = Spot.createInfraRed( RecceDcsUnit, relativespot, Target:GetPointVec3():AddY(1):GetVec3() ) + self.SpotLaser = Spot.createLaser( RecceDcsUnit, relativespot, Target:GetPointVec3():AddY(1):GetVec3(), LaserCode ) if Duration then self.ScheduleID = self.LaseScheduler:Schedule( self, StopLase, {self}, Duration ) @@ -368,4 +370,16 @@ do return self.Lasing end -end \ No newline at end of file + --- Set laser start position relative to the lasing unit. + -- @param #SPOT self + -- @param #table position Start position of the laser relative to the lasing unit. Default is { x = 0, y = 2, z = 0 } + -- @return #SPOT self + -- @usage + -- -- Set lasing position to be the position of the optics of the Gazelle M: + -- myspot:SetRelativeStartPosition({ x = 1.7, y = 1.2, z = 0 }) + function SPOT:SetRelativeStartPosition(position) + self.relstartpos = position or { x = 0, y = 2, z = 0 } + return self + end + +end diff --git a/Moose Development/Moose/Core/TextAndSound.lua b/Moose Development/Moose/Core/TextAndSound.lua index f56015fe2..71e1c35f8 100644 --- a/Moose Development/Moose/Core/TextAndSound.lua +++ b/Moose Development/Moose/Core/TextAndSound.lua @@ -1,4 +1,4 @@ ---- **Core** - TEXTANDSOUND (MOOSE gettext) system +--- **Core** - A Moose GetText system. -- -- === -- diff --git a/Moose Development/Moose/Core/UserFlag.lua b/Moose Development/Moose/Core/UserFlag.lua index 6d8bdd719..5ed5d6cd7 100644 --- a/Moose Development/Moose/Core/UserFlag.lua +++ b/Moose Development/Moose/Core/UserFlag.lua @@ -35,13 +35,13 @@ do -- UserFlag ClassName = "USERFLAG", UserFlagName = nil, } - + --- USERFLAG Constructor. -- @param #USERFLAG self -- @param #string UserFlagName The name of the userflag, which is a free text string. -- @return #USERFLAG function USERFLAG:New( UserFlagName ) --R2.3 - + local self = BASE:Inherit( self, BASE:New() ) -- #USERFLAG self.UserFlagName = UserFlagName @@ -52,7 +52,7 @@ do -- UserFlag --- Get the userflag name. -- @param #USERFLAG self -- @return #string Name of the user flag. - function USERFLAG:GetName() + function USERFLAG:GetName() return self.UserFlagName end @@ -66,18 +66,17 @@ do -- UserFlag -- BlueVictory:Set( 100 ) -- Set the UserFlag VictoryBlue to 100. -- function USERFLAG:Set( Number, Delay ) --R2.3 - + if Delay and Delay>0 then self:ScheduleOnce(Delay, USERFLAG.Set, self, Number) else --env.info(string.format("Setting flag \"%s\" to %d at T=%.1f", self.UserFlagName, Number, timer.getTime())) trigger.action.setUserFlag( self.UserFlagName, Number ) end - - return self - end - + return self + end + --- Get the userflag Number. -- @param #USERFLAG self -- @return #number Number The number value to be checked if it is the same as the userflag. @@ -86,12 +85,10 @@ do -- UserFlag -- local BlueVictoryValue = BlueVictory:Get() -- Get the UserFlag VictoryBlue value. -- function USERFLAG:Get() --R2.3 - - return trigger.misc.getUserFlag( self.UserFlagName ) - end - - + return trigger.misc.getUserFlag( self.UserFlagName ) + end + --- Check if the userflag has a value of Number. -- @param #USERFLAG self -- @param #number Number The number value to be checked if it is the same as the userflag. @@ -102,9 +99,9 @@ do -- UserFlag -- return "Blue has won" -- end function USERFLAG:Is( Number ) --R2.3 - + return trigger.misc.getUserFlag( self.UserFlagName ) == Number - - end + + end end \ No newline at end of file diff --git a/Moose Development/Moose/Core/Velocity.lua b/Moose Development/Moose/Core/Velocity.lua index 5f86f6696..e71282208 100644 --- a/Moose Development/Moose/Core/Velocity.lua +++ b/Moose Development/Moose/Core/Velocity.lua @@ -54,7 +54,7 @@ do -- Velocity self.Velocity = VelocityMps return self end - + --- Get the velocity in Mps (meters per second). -- @param #VELOCITY self -- @return #number The velocity in meters per second. @@ -70,12 +70,12 @@ do -- Velocity self.Velocity = UTILS.KmphToMps( VelocityKmph ) return self end - + --- Get the velocity in Kmph (kilometers per hour). -- @param #VELOCITY self -- @return #number The velocity in kilometers per hour. function VELOCITY:GetKmph() - + return UTILS.MpsToKmph( self.Velocity ) end @@ -87,7 +87,7 @@ do -- Velocity self.Velocity = UTILS.MiphToMps( VelocityMiph ) return self end - + --- Get the velocity in Miph (miles per hour). -- @param #VELOCITY self -- @return #number The velocity in miles per hour. @@ -95,8 +95,7 @@ do -- Velocity return UTILS.MpsToMiph( self.Velocity ) end - - --- Get the velocity in text, according the player @{Settings}. + --- Get the velocity in text, according the player @{Core.Settings}. -- @param #VELOCITY self -- @param Core.Settings#SETTINGS Settings -- @return #string The velocity in text. @@ -113,11 +112,11 @@ do -- Velocity end end - --- Get the velocity in text, according the player or default @{Settings}. + --- Get the velocity in text, according the player or default @{Core.Settings}. -- @param #VELOCITY self -- @param Wrapper.Controllable#CONTROLLABLE Controllable -- @param Core.Settings#SETTINGS Settings - -- @return #string The velocity in text according the player or default @{Settings} + -- @return #string The velocity in text according the player or default @{Core.Settings} function VELOCITY:ToString( VelocityGroup, Settings ) -- R2.3 self:F( { Group = VelocityGroup and VelocityGroup:GetName() } ) local Settings = Settings or ( VelocityGroup and _DATABASE:GetPlayerSettings( VelocityGroup:GetPlayerName() ) ) or _SETTINGS @@ -134,7 +133,7 @@ do -- VELOCITY_POSITIONABLE --- # VELOCITY_POSITIONABLE class, extends @{Core.Base#BASE} -- - -- VELOCITY_POSITIONABLE monitors the speed of an @{Positionable} in the simulation, which can be expressed in various formats according the Settings. + -- @{#VELOCITY_POSITIONABLE} monitors the speed of a @{Wrapper.Positionable#POSITIONABLE} in the simulation, which can be expressed in various formats according the Settings. -- -- ## 1. VELOCITY_POSITIONABLE constructor -- @@ -167,7 +166,7 @@ do -- VELOCITY_POSITIONABLE -- @param #VELOCITY_POSITIONABLE self -- @return #number The velocity in kilometers per hour. function VELOCITY_POSITIONABLE:GetKmph() - + return UTILS.MpsToKmph( self.Positionable:GetVelocityMPS() or 0) end @@ -178,9 +177,9 @@ do -- VELOCITY_POSITIONABLE return UTILS.MpsToMiph( self.Positionable:GetVelocityMPS() or 0 ) end - --- Get the velocity in text, according the player or default @{Settings}. + --- Get the velocity in text, according the player or default @{Core.Settings}. -- @param #VELOCITY_POSITIONABLE self - -- @return #string The velocity in text according the player or default @{Settings} + -- @return #string The velocity in text according the player or default @{Core.Settings} function VELOCITY_POSITIONABLE:ToString() -- R2.3 self:F( { Group = self.Positionable and self.Positionable:GetName() } ) local Settings = Settings or ( self.Positionable and _DATABASE:GetPlayerSettings( self.Positionable:GetPlayerName() ) ) or _SETTINGS diff --git a/Moose Development/Moose/Core/Zone.lua b/Moose Development/Moose/Core/Zone.lua index 1ec83be66..5f89fdaed 100644 --- a/Moose Development/Moose/Core/Zone.lua +++ b/Moose Development/Moose/Core/Zone.lua @@ -46,14 +46,13 @@ -- === -- -- ### Author: **FlightControl** --- ### Contributions: +-- ### Contributions: **Applevangelist**, **FunkyFranky** -- -- === -- -- @module Core.Zone -- @image Core_Zones.JPG - --- @type ZONE_BASE -- @field #string ZoneName Name of the zone. -- @field #number ZoneProbability A value between 0 and 1. 0 = 0% and 1 = 100% probability. @@ -75,7 +74,7 @@ -- * @{#ZONE_BASE.SetName}(): Sets the name of the zone. -- -- --- ## Each zone implements two polymorphic functions defined in @{Core.Zone#ZONE_BASE}: +-- ## Each zone implements two polymorphic functions defined in @{#ZONE_BASE}: -- -- * @{#ZONE_BASE.IsVec2InZone}(): Returns if a 2D vector is within the zone. -- * @{#ZONE_BASE.IsVec3InZone}(): Returns if a 3D vector is within the zone. @@ -121,10 +120,9 @@ ZONE_BASE = { Color={}, ZoneID=nil, Properties={}, - Sureface=nil, + Surface=nil, } - --- The ZONE_BASE.BoundingSquare -- @type ZONE_BASE.BoundingSquare -- @field DCS#Distance x1 The lower x coordinate (left down) @@ -132,7 +130,6 @@ ZONE_BASE = { -- @field DCS#Distance x2 The higher x coordinate (right up) -- @field DCS#Distance y2 The higher y coordinate (right up) - --- ZONE_BASE constructor -- @param #ZONE_BASE self -- @param #string ZoneName Name of the zone. @@ -142,14 +139,12 @@ function ZONE_BASE:New( ZoneName ) self:F( ZoneName ) self.ZoneName = ZoneName - + --_DATABASE:AddZone(ZoneName,self) - + return self end - - --- Returns the name of the zone. -- @param #ZONE_BASE self -- @return #string The name of the zone. @@ -159,7 +154,6 @@ function ZONE_BASE:GetName() return self.ZoneName end - --- Sets the name of the zone. -- @param #ZONE_BASE self -- @param #string ZoneName The name of the zone. @@ -217,7 +211,6 @@ function ZONE_BASE:IsPointVec3InZone( PointVec3 ) return InZone end - --- Returns the @{DCS#Vec2} coordinate of the zone. -- @param #ZONE_BASE self -- @return #nil. @@ -241,7 +234,6 @@ function ZONE_BASE:GetPointVec2() return PointVec2 end - --- Returns the @{DCS#Vec3} of the zone. -- @param #ZONE_BASE self -- @param DCS#Distance Height The height to add to the land height where the center of the zone is located. @@ -365,7 +357,6 @@ function ZONE_BASE:BoundZone() self:F2() end - --- Set draw coalition of zone. -- @param #ZONE_BASE self -- @param #number Coalition Coalition. Default -1. @@ -377,7 +368,7 @@ end --- Get draw coalition of zone. -- @param #ZONE_BASE self --- @return #number Draw coaliton. +-- @return #number Draw coalition. function ZONE_BASE:GetDrawCoalition() return self.drawCoalition or -1 end @@ -385,7 +376,7 @@ end --- Set color of zone. -- @param #ZONE_BASE self -- @param #table RGBcolor RGB color table. Default `{1, 0, 0}`. --- @param #number Alpha Transparacy between 0 and 1. Default 0.15. +-- @param #number Alpha Transparency between 0 and 1. Default 0.15. -- @return #ZONE_BASE self function ZONE_BASE:SetColor(RGBcolor, Alpha) @@ -420,7 +411,7 @@ function ZONE_BASE:GetColorRGB() return rgb end ---- Get transperency Alpha value of zone. +--- Get transparency Alpha value of zone. -- @param #ZONE_BASE self -- @return #number Alpha value. function ZONE_BASE:GetColorAlpha() @@ -467,7 +458,7 @@ function ZONE_BASE:GetFillColorRGB() return rgb end ---- Get transperency Alpha fill value of zone. +--- Get transparency Alpha fill value of zone. -- @param #ZONE_BASE self -- @return #number Alpha value. function ZONE_BASE:GetFillColorAlpha() @@ -592,7 +583,7 @@ end -- @extends #ZONE_BASE --- The ZONE_RADIUS class defined by a zone name, a location and a radius. --- This class implements the inherited functions from Core.Zone#ZONE_BASE taking into account the own zone format and properties. +-- This class implements the inherited functions from @{#ZONE_BASE} taking into account the own zone format and properties. -- -- ## ZONE_RADIUS constructor -- @@ -631,8 +622,9 @@ ZONE_RADIUS = { -- @param #string ZoneName Name of the zone. -- @param DCS#Vec2 Vec2 The location of the zone. -- @param DCS#Distance Radius The radius of the zone. +-- @param DCS#Boolean DoNotRegisterZone Determines if the Zone should not be registered in the _Database Table. Default=false -- @return #ZONE_RADIUS self -function ZONE_RADIUS:New( ZoneName, Vec2, Radius ) +function ZONE_RADIUS:New( ZoneName, Vec2, Radius, DoNotRegisterZone ) -- Inherit ZONE_BASE. local self = BASE:Inherit( self, ZONE_BASE:New( ZoneName ) ) -- #ZONE_RADIUS @@ -641,6 +633,10 @@ function ZONE_RADIUS:New( ZoneName, Vec2, Radius ) self.Radius = Radius self.Vec2 = Vec2 + if not DoNotRegisterZone then + _EVENTDISPATCHER:CreateEventNewZone(self) + end + --self.Coordinate=COORDINATE:NewFromVec2(Vec2) return self @@ -750,7 +746,6 @@ function ZONE_RADIUS:BoundZone( Points, CountryID, UnBound ) local Angle local RadialBase = math.pi*2 - -- for Angle = 0, 360, (360 / Points ) do local Radial = Angle * RadialBase / 360 Point.x = Vec2.x + math.cos( Radial ) * self:GetRadius() @@ -780,7 +775,6 @@ function ZONE_RADIUS:BoundZone( Points, CountryID, UnBound ) return self end - --- Smokes the zone boundaries in a color. -- @param #ZONE_RADIUS self -- @param Utilities.Utils#SMOKECOLOR SmokeColor The smoke color. @@ -812,7 +806,6 @@ function ZONE_RADIUS:SmokeZone( SmokeColor, Points, AddHeight, AngleOffset ) return self end - --- Flares the zone boundaries in a color. -- @param #ZONE_RADIUS self -- @param Utilities.Utils#FLARECOLOR FlareColor The flare color. @@ -909,10 +902,6 @@ function ZONE_RADIUS:GetVec3( Height ) return Vec3 end - - - - --- Scan the zone for the presence of units of the given ObjectCategories. -- Note that **only after** a zone has been scanned, the zone can be evaluated by: -- @@ -921,7 +910,6 @@ end -- * @{ZONE_RADIUS.IsSomeInZoneOfCoalition}(): Scan if there is some presence of units in the zone of the given coalition. -- * @{ZONE_RADIUS.IsNoneInZoneOfCoalition}(): Scan if there isn't any presence of units in the zone of an other coalition than the given one. -- * @{ZONE_RADIUS.IsNoneInZone}(): Scan if the zone is empty. --- @{#ZONE_RADIUS. -- @param #ZONE_RADIUS self -- @param ObjectCategories An array of categories of the objects to find in the zone. E.g. `{Object.Category.UNIT}` -- @param UnitCategories An array of unit categories of the objects to find in the zone. E.g. `{Unit.Category.GROUND_UNIT,Unit.Category.SHIP}` @@ -933,6 +921,7 @@ function ZONE_RADIUS:Scan( ObjectCategories, UnitCategories ) self.ScanData = {} self.ScanData.Coalitions = {} self.ScanData.Scenery = {} + self.ScanData.SceneryTable = {} self.ScanData.Units = {} local ZoneCoord = self:GetCoordinate() @@ -995,8 +984,10 @@ function ZONE_RADIUS:Scan( ObjectCategories, UnitCategories ) if ObjectCategory == Object.Category.SCENERY then local SceneryType = ZoneObject:getTypeName() local SceneryName = ZoneObject:getName() + --BASE:I("SceneryType "..SceneryType.."SceneryName"..SceneryName) self.ScanData.Scenery[SceneryType] = self.ScanData.Scenery[SceneryType] or {} self.ScanData.Scenery[SceneryType][SceneryName] = SCENERY:Register( SceneryName, ZoneObject ) + table.insert(self.ScanData.SceneryTable,self.ScanData.Scenery[SceneryType][SceneryName] ) self:T( { SCENERY = self.ScanData.Scenery[SceneryType][SceneryName] } ) end @@ -1018,7 +1009,6 @@ function ZONE_RADIUS:GetScannedUnits() return self.ScanData.Units end - --- Get a set of scanned units. -- @param #ZONE_RADIUS self -- @return Core.Set#SET_UNIT Set of units and statics inside the zone. @@ -1072,7 +1062,6 @@ function ZONE_RADIUS:GetScannedSetGroup() return self.ScanSetGroup end - --- Count the number of different coalitions inside the zone. -- @param #ZONE_RADIUS self -- @return #number Counted coalitions. @@ -1125,7 +1114,6 @@ function ZONE_RADIUS:GetScannedCoalition( Coalition ) end end - --- Get scanned scenery type -- @param #ZONE_RADIUS self -- @return #table Table of DCS scenery type objects. @@ -1133,17 +1121,34 @@ function ZONE_RADIUS:GetScannedSceneryType( SceneryType ) return self.ScanData.Scenery[SceneryType] end - --- Get scanned scenery table -- @param #ZONE_RADIUS self --- @return #table Table of DCS scenery objects. +-- @return #table Structured object table: [type].[name].SCENERY function ZONE_RADIUS:GetScannedScenery() return self.ScanData.Scenery end +--- Get table of scanned scenery objects +-- @param #ZONE_RADIUS self +-- @return #table Table of SCENERY objects. +function ZONE_RADIUS:GetScannedSceneryObjects() + return self.ScanData.SceneryTable +end + +--- Get set of scanned scenery objects +-- @param #ZONE_RADIUS self +-- @return #table Table of Wrapper.Scenery#SCENERY scenery objects. +function ZONE_RADIUS:GetScannedSetScenery() + local scenery = SET_SCENERY:New() + local objects = self:GetScannedSceneryObjects() + for _,_obj in pairs (objects) do + scenery:AddScenery(_obj) + end + return scenery +end --- Is All in Zone of Coalition? --- Check if only the specifed coalition is inside the zone and noone else. +-- Check if only the specified coalition is inside the zone and no one else. -- @param #ZONE_RADIUS self -- @param #number Coalition Coalition ID of the coalition which is checked to be the only one in the zone. -- @return #boolean True, if **only** that coalition is inside the zone and no one else. @@ -1156,7 +1161,6 @@ function ZONE_RADIUS:IsAllInZoneOfCoalition( Coalition ) return self:CountScannedCoalitions() == 1 and self:GetScannedCoalition( Coalition ) == true end - --- Is All in Zone of Other Coalition? -- Check if only one coalition is inside the zone and the specified coalition is not the one. -- You first need to use the @{#ZONE_RADIUS.Scan} method to scan the zone before it can be evaluated! @@ -1173,13 +1177,12 @@ function ZONE_RADIUS:IsAllInZoneOfOtherCoalition( Coalition ) return self:CountScannedCoalitions() == 1 and self:GetScannedCoalition( Coalition ) == nil end - --- Is Some in Zone of Coalition? --- Check if more than one coaltion is inside the zone and the specifed coalition is one of them. +-- Check if more than one coalition is inside the zone and the specified coalition is one of them. -- You first need to use the @{#ZONE_RADIUS.Scan} method to scan the zone before it can be evaluated! -- Note that once a zone has been scanned, multiple evaluations can be done on the scan result set. -- @param #ZONE_RADIUS self --- @param #number Coalition ID of the coaliton which is checked to be inside the zone. +-- @param #number Coalition ID of the coalition which is checked to be inside the zone. -- @return #boolean True if more than one coalition is inside the zone and the specified coalition is one of them. -- @usage -- self.Zone:Scan() @@ -1189,7 +1192,6 @@ function ZONE_RADIUS:IsSomeInZoneOfCoalition( Coalition ) return self:CountScannedCoalitions() > 1 and self:GetScannedCoalition( Coalition ) == true end - --- Is None in Zone of Coalition? -- You first need to use the @{#ZONE_RADIUS.Scan} method to scan the zone before it can be evaluated! -- Note that once a zone has been scanned, multiple evaluations can be done on the scan result set. @@ -1204,7 +1206,6 @@ function ZONE_RADIUS:IsNoneInZoneOfCoalition( Coalition ) return self:GetScannedCoalition( Coalition ) == nil end - --- Is None in Zone? -- You first need to use the @{#ZONE_RADIUS.Scan} method to scan the zone before it can be evaluated! -- Note that once a zone has been scanned, multiple evaluations can be done on the scan result set. @@ -1218,9 +1219,6 @@ function ZONE_RADIUS:IsNoneInZone() return self:CountScannedCoalitions() == 0 end - - - --- Searches the zone -- @param #ZONE_RADIUS self -- @param ObjectCategories A list of categories, which are members of Object.Category @@ -1260,9 +1258,9 @@ end -- @return #boolean true if the location is within the zone. function ZONE_RADIUS:IsVec2InZone( Vec2 ) self:F2( Vec2 ) - + if not Vec2 then return false end - + local ZoneVec2 = self:GetVec2() if ZoneVec2 then @@ -1294,13 +1292,13 @@ end -- @return DCS#Vec2 The random location within the zone. function ZONE_RADIUS:GetRandomVec2(inner, outer, surfacetypes) - local Vec2 = self:GetVec2() - local _inner = inner or 0 - local _outer = outer or self:GetRadius() + local Vec2 = self:GetVec2() + local _inner = inner or 0 + local _outer = outer or self:GetRadius() - if surfacetypes and type(surfacetypes)~="table" then + if surfacetypes and type(surfacetypes)~="table" then surfacetypes={surfacetypes} - end + end local function _getpoint() local point = {} @@ -1320,22 +1318,22 @@ function ZONE_RADIUS:GetRandomVec2(inner, outer, surfacetypes) return false end - local point=_getpoint() + local point=_getpoint() - if surfacetypes then - local N=1 ; local Nmax=100 ; local gotit=false + if surfacetypes then + local N=1 ; local Nmax=100 ; local gotit=false while gotit==false and N<=Nmax do gotit=_checkSurface(point) if gotit then --env.info(string.format("Got random coordinate with surface type %d after N=%d/%d iterations", land.getSurfaceType(point), N, Nmax)) else point=_getpoint() - N=N+1 + N=N+1 end end end - return point + return point end --- Returns a @{Core.Point#POINT_VEC2} object reflecting a random 2D location within the zone. @@ -1405,27 +1403,26 @@ end -- @param #ZONE_RADIUS self -- @param #number inner (Optional) Minimal distance from the center of the zone in meters. Default is 0m. -- @param #number outer (Optional) Maximal distance from the outer edge of the zone in meters. Default is the radius of the zone. --- @param #number distance (Optional) Minumum distance from any building coordinate. Defaults to 100m. +-- @param #number distance (Optional) Minimum distance from any building coordinate. Defaults to 100m. -- @param #boolean markbuildings (Optional) Place markers on found buildings (if any). -- @param #boolean markfinal (Optional) Place marker on the final coordinate (if any). -- @return Core.Point#COORDINATE The random coordinate or `nil` if cannot be found in 1000 iterations. function ZONE_RADIUS:GetRandomCoordinateWithoutBuildings(inner,outer,distance,markbuildings,markfinal) - + local dist = distance or 100 - + local objects = {} - + if self.ScanData and self.ScanData.Scenery then objects = self:GetScannedScenery() else self:Scan({Object.Category.SCENERY}) objects = self:GetScannedScenery() end - + local T0 = timer.getTime() local T1 = timer.getTime() - - + local buildings = {} if self.ScanData and self.ScanData.BuildingCoordinates then buildings = self.ScanData.BuildingCoordinates @@ -1445,12 +1442,12 @@ function ZONE_RADIUS:GetRandomCoordinateWithoutBuildings(inner,outer,distance,ma end self.ScanData.BuildingCoordinates = buildings end - + -- max 1000 tries local rcoord = nil local found = false local iterations = 0 - + for i=1,1000 do iterations = iterations + 1 rcoord = self:GetRandomCoordinate(inner,outer) @@ -1458,7 +1455,7 @@ function ZONE_RADIUS:GetRandomCoordinateWithoutBuildings(inner,outer,distance,ma for _,_coord in pairs (buildings) do local coord = _coord -- Core.Point#COORDINATE -- keep >50m dist from buildings - if coord:Get2DDistance(rcoord) > dist then + if coord:Get3DDistance(rcoord) > dist then found = true else found = false @@ -1542,7 +1539,7 @@ function ZONE:New( ZoneName ) end -- Create a new ZONE_RADIUS. - local self=BASE:Inherit( self, ZONE_RADIUS:New(ZoneName, {x=Zone.point.x, y=Zone.point.z}, Zone.radius)) + local self=BASE:Inherit( self, ZONE_RADIUS:New(ZoneName, {x=Zone.point.x, y=Zone.point.z}, Zone.radius, true)) self:F(ZoneName) -- Color of zone. @@ -1571,7 +1568,7 @@ end -- @extends Core.Zone#ZONE_RADIUS ---- # ZONE_UNIT class, extends @{Zone#ZONE_RADIUS} +--- # ZONE_UNIT class, extends @{#ZONE_RADIUS} -- -- The ZONE_UNIT class defined by a zone attached to a @{Wrapper.Unit#UNIT} with a radius and optional offsets. -- This class implements the inherited functions from @{#ZONE_RADIUS} taking into account the own zone format and properties. @@ -1609,7 +1606,7 @@ function ZONE_UNIT:New( ZoneName, ZoneUNIT, Radius, Offset) self.relative_to_unit = Offset.relative_to_unit or false end - local self = BASE:Inherit( self, ZONE_RADIUS:New( ZoneName, ZoneUNIT:GetVec2(), Radius ) ) + local self = BASE:Inherit( self, ZONE_RADIUS:New( ZoneName, ZoneUNIT:GetVec2(), Radius, true ) ) self:F( { ZoneName, ZoneUNIT:GetVec2(), Radius } ) @@ -1711,7 +1708,7 @@ end --- The ZONE_GROUP class defines by a zone around a @{Wrapper.Group#GROUP} with a radius. The current leader of the group defines the center of the zone. --- This class implements the inherited functions from @{Core.Zone#ZONE_RADIUS} taking into account the own zone format and properties. +-- This class implements the inherited functions from @{#ZONE_RADIUS} taking into account the own zone format and properties. -- -- @field #ZONE_GROUP ZONE_GROUP = { @@ -1725,7 +1722,7 @@ ZONE_GROUP = { -- @param DCS#Distance Radius The radius of the zone. -- @return #ZONE_GROUP self function ZONE_GROUP:New( ZoneName, ZoneGROUP, Radius ) - local self = BASE:Inherit( self, ZONE_RADIUS:New( ZoneName, ZoneGROUP:GetVec2(), Radius ) ) + local self = BASE:Inherit( self, ZONE_RADIUS:New( ZoneName, ZoneGROUP:GetVec2(), Radius, true ) ) self:F( { ZoneName, ZoneGROUP:GetVec2(), Radius } ) self._.ZoneGROUP = ZoneGROUP @@ -1798,7 +1795,7 @@ end --- The ZONE_POLYGON_BASE class defined by a sequence of @{Wrapper.Group#GROUP} waypoints within the Mission Editor, forming a polygon. --- This class implements the inherited functions from @{Core.Zone#ZONE_RADIUS} taking into account the own zone format and properties. +-- This class implements the inherited functions from @{#ZONE_RADIUS} taking into account the own zone format and properties. -- This class is an abstract BASE class for derived classes, and is not meant to be instantiated. -- -- ## Zone point randomization @@ -2030,7 +2027,6 @@ function ZONE_POLYGON_BASE:BoundZone( UnBound ) return self end - --- Draw the zone on the F10 map. **NOTE** Currently, only polygons **up to ten points** are supported! -- @param #ZONE_POLYGON_BASE self -- @param #number Coalition Coalition: All=-1, Neutral=0, Red=1, Blue=2. Default -1=All. @@ -2046,43 +2042,43 @@ function ZONE_POLYGON_BASE:DrawZone(Coalition, Color, Alpha, FillColor, FillAlph if self._.Polygon and #self._.Polygon>=3 then local coordinate=COORDINATE:NewFromVec2(self._.Polygon[1]) - + Coalition=Coalition or self:GetDrawCoalition() - + -- Set draw coalition. - self:SetDrawCoalition(Coalition) - + self:SetDrawCoalition(Coalition) + Color=Color or self:GetColorRGB() Alpha=Alpha or 1 - + -- Set color. self:SetColor(Color, Alpha) - + FillColor=FillColor or self:GetFillColorRGB() if not FillColor then UTILS.DeepCopy(Color) end FillAlpha=FillAlpha or self:GetFillColorAlpha() if not FillAlpha then FillAlpha=0.15 end - + -- Set fill color. self:SetFillColor(FillColor, FillAlpha) - + if #self._.Polygon==4 then - + local Coord2=COORDINATE:NewFromVec2(self._.Polygon[2]) local Coord3=COORDINATE:NewFromVec2(self._.Polygon[3]) local Coord4=COORDINATE:NewFromVec2(self._.Polygon[4]) - + self.DrawID=coordinate:QuadToAll(Coord2, Coord3, Coord4, Coalition, Color, Alpha, FillColor, FillAlpha, LineType, ReadOnly) - + else - + local Coordinates=self:GetVerticiesCoordinates() table.remove(Coordinates, 1) - + self.DrawID=coordinate:MarkupToAllFreeForm(Coordinates, Coalition, Color, Alpha, FillColor, FillAlpha, LineType, ReadOnly) - + end - + end return self @@ -2119,7 +2115,6 @@ function ZONE_POLYGON_BASE:SmokeZone( SmokeColor, Segments ) return self end - --- Flare the zone boundaries in a color. -- @param #ZONE_POLYGON_BASE self -- @param Utilities.Utils#FLARECOLOR FlareColor The flare color. @@ -2155,9 +2150,6 @@ function ZONE_POLYGON_BASE:FlareZone( FlareColor, Segments, Azimuth, AddHeight ) return self end - - - --- Returns if a location is within the zone. -- Source learned and taken from: https://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html -- @param #ZONE_POLYGON_BASE self @@ -2325,7 +2317,7 @@ function ZONE_POLYGON_BASE:Boundary(Coalition, Color, Radius, Alpha, Segments, C for Segment = 0, Segments do local PointX = self._.Polygon[i].x + ( Segment * DeltaX / Segments ) local PointY = self._.Polygon[i].y + ( Segment * DeltaY / Segments ) - ZONE_RADIUS:New( "Zone", {x = PointX, y = PointY}, Radius ):DrawZone(Coalition, Color, 1, Color, Alpha, nil, true) + --ZONE_RADIUS:New( "Zone", {x = PointX, y = PointY}, Radius ):DrawZone(Coalition, Color, 1, Color, Alpha, nil, true) end end j = i @@ -2339,7 +2331,7 @@ end --- The ZONE_POLYGON class defined by a sequence of @{Wrapper.Group#GROUP} waypoints within the Mission Editor, forming a polygon. --- This class implements the inherited functions from @{Core.Zone#ZONE_RADIUS} taking into account the own zone format and properties. +-- This class implements the inherited functions from @{#ZONE_RADIUS} taking into account the own zone format and properties. -- -- ## Declare a ZONE_POLYGON directly in the DCS mission editor! -- @@ -2385,6 +2377,21 @@ function ZONE_POLYGON:New( ZoneName, ZoneGroup ) return self end +--- Constructor to create a ZONE_POLYGON instance, taking the zone name and an array of DCS#Vec2, forming a polygon. +-- @param #ZONE_POLYGON self +-- @param #string ZoneName Name of the zone. +-- @param #ZONE_POLYGON_BASE.ListVec2 PointsArray An array of @{DCS#Vec2}, forming a polygon. +-- @return #ZONE_POLYGON self +function ZONE_POLYGON:NewFromPointsArray( ZoneName, PointsArray ) + + local self = BASE:Inherit( self, ZONE_POLYGON_BASE:New( ZoneName, PointsArray ) ) + self:F( { ZoneName, self._.Polygon } ) + + -- Zone objects are added to the _DATABASE and SET_ZONE objects. + _EVENTDISPATCHER:CreateEventNewZone( self ) + + return self +end --- Constructor to create a ZONE_POLYGON instance, taking the zone name and the **name** of the @{Wrapper.Group#GROUP} defined within the Mission Editor. -- The @{Wrapper.Group#GROUP} waypoints define the polygon corners. The first and the last point are automatically connected by ZONE_POLYGON. @@ -2417,6 +2424,357 @@ function ZONE_POLYGON:FindByName( ZoneName ) return ZoneFound end +--- Scan the zone for the presence of units of the given ObjectCategories. Does **not** scan for scenery at the moment. +-- Note that **only after** a zone has been scanned, the zone can be evaluated by: +-- +-- * @{ZONE_POLYGON.IsAllInZoneOfCoalition}(): Scan the presence of units in the zone of a coalition. +-- * @{ZONE_POLYGON.IsAllInZoneOfOtherCoalition}(): Scan the presence of units in the zone of an other coalition. +-- * @{ZONE_POLYGON.IsSomeInZoneOfCoalition}(): Scan if there is some presence of units in the zone of the given coalition. +-- * @{ZONE_POLYGON.IsNoneInZoneOfCoalition}(): Scan if there isn't any presence of units in the zone of an other coalition than the given one. +-- * @{ZONE_POLYGON.IsNoneInZone}(): Scan if the zone is empty. +-- @param #ZONE_POLYGON self +-- @param ObjectCategories An array of categories of the objects to find in the zone. E.g. `{Object.Category.UNIT}` +-- @param UnitCategories An array of unit categories of the objects to find in the zone. E.g. `{Unit.Category.GROUND_UNIT,Unit.Category.SHIP}` +-- @usage +-- myzone:Scan({Object.Category.UNIT},{Unit.Category.GROUND_UNIT}) +-- local IsAttacked = myzone:IsSomeInZoneOfCoalition( self.Coalition ) +function ZONE_POLYGON:Scan( ObjectCategories, UnitCategories ) + + self.ScanData = {} + self.ScanData.Coalitions = {} + self.ScanData.Scenery = {} + self.ScanData.SceneryTable = {} + self.ScanData.Units = {} + + local vectors = self:GetBoundingSquare() + + local minVec3 = {x=vectors.x1, y=0, z=vectors.y1} + local maxVec3 = {x=vectors.x2, y=0, z=vectors.y2} + + local minmarkcoord = COORDINATE:NewFromVec3(minVec3) + local maxmarkcoord = COORDINATE:NewFromVec3(maxVec3) + local ZoneRadius = minmarkcoord:Get2DDistance(maxmarkcoord)/2 + + local CenterVec3 = self:GetCoordinate():GetVec3() + + --[[ this a bit shaky in functionality it seems + local VolumeBox = { + id = world.VolumeType.BOX, + params = { + min = minVec3, + max = maxVec3 + } + } + --]] + + local SphereSearch = { + id = world.VolumeType.SPHERE, + params = { + point = CenterVec3, + radius = ZoneRadius, + } + } + + local function EvaluateZone( ZoneObject ) + + if ZoneObject then + + local ObjectCategory = ZoneObject:getCategory() + + if ( ObjectCategory == Object.Category.UNIT and ZoneObject:isExist() and ZoneObject:isActive() ) or (ObjectCategory == Object.Category.STATIC and ZoneObject:isExist()) then + + local CoalitionDCSUnit = ZoneObject:getCoalition() + + local Include = false + if not UnitCategories then + -- Anything found is included. + Include = true + else + -- Check if found object is in specified categories. + local CategoryDCSUnit = ZoneObject:getDesc().category + + for UnitCategoryID, UnitCategory in pairs( UnitCategories ) do + if UnitCategory == CategoryDCSUnit then + Include = true + break + end + end + + end + + if Include then + + local CoalitionDCSUnit = ZoneObject:getCoalition() + + -- This coalition is inside the zone. + self.ScanData.Coalitions[CoalitionDCSUnit] = true + + self.ScanData.Units[ZoneObject] = ZoneObject + + self:F2( { Name = ZoneObject:getName(), Coalition = CoalitionDCSUnit } ) + end + end + + -- trying with box search + if ObjectCategory == Object.Category.SCENERY and self:IsVec3InZone(ZoneObject:getPoint()) then + local SceneryType = ZoneObject:getTypeName() + local SceneryName = ZoneObject:getName() + self.ScanData.Scenery[SceneryType] = self.ScanData.Scenery[SceneryType] or {} + self.ScanData.Scenery[SceneryType][SceneryName] = SCENERY:Register( SceneryName, ZoneObject ) + table.insert(self.ScanData.SceneryTable,self.ScanData.Scenery[SceneryType][SceneryName]) + self:T( { SCENERY = self.ScanData.Scenery[SceneryType][SceneryName] } ) + end + + end + + return true + end + + -- Search objects. + local inzoneunits = SET_UNIT:New():FilterZones({self}):FilterOnce() + local inzonestatics = SET_STATIC:New():FilterZones({self}):FilterOnce() + + inzoneunits:ForEach( + function(unit) + local Unit = unit --Wrapper.Unit#UNIT + local DCS = Unit:GetDCSObject() + EvaluateZone(DCS) + end + ) + + inzonestatics:ForEach( + function(static) + local Static = static --Wrapper.Static#STATIC + local DCS = Static:GetDCSObject() + EvaluateZone(DCS) + end + ) + + local searchscenery = false + for _,_type in pairs(ObjectCategories) do + if _type == Object.Category.SCENERY then + searchscenery = true + end + end + + if searchscenery then + -- Search objects. + world.searchObjects({Object.Category.SCENERY}, SphereSearch, EvaluateZone ) + end + +end + +--- Count the number of different coalitions inside the zone. +-- @param #ZONE_POLYGON self +-- @return #table Table of DCS units and DCS statics inside the zone. +function ZONE_POLYGON:GetScannedUnits() + return self.ScanData.Units +end + +--- Get a set of scanned units. +-- @param #ZONE_POLYGON self +-- @return Core.Set#SET_UNIT Set of units and statics inside the zone. +function ZONE_POLYGON:GetScannedSetUnit() + + local SetUnit = SET_UNIT:New() + + if self.ScanData then + for ObjectID, UnitObject in pairs( self.ScanData.Units ) do + local UnitObject = UnitObject -- DCS#Unit + if UnitObject:isExist() then + local FoundUnit = UNIT:FindByName( UnitObject:getName() ) + if FoundUnit then + SetUnit:AddUnit( FoundUnit ) + else + local FoundStatic = STATIC:FindByName( UnitObject:getName() ) + if FoundStatic then + SetUnit:AddUnit( FoundStatic ) + end + end + end + end + end + + return SetUnit +end + +--- Get a set of scanned units. +-- @param #ZONE_POLYGON self +-- @return Core.Set#SET_GROUP Set of groups. +function ZONE_POLYGON:GetScannedSetGroup() + + self.ScanSetGroup=self.ScanSetGroup or SET_GROUP:New() --Core.Set#SET_GROUP + + self.ScanSetGroup.Set={} + + if self.ScanData then + for ObjectID, UnitObject in pairs( self.ScanData.Units ) do + local UnitObject = UnitObject -- DCS#Unit + if UnitObject:isExist() then + + local FoundUnit=UNIT:FindByName(UnitObject:getName()) + if FoundUnit then + local group=FoundUnit:GetGroup() + self.ScanSetGroup:AddGroup(group) + end + end + end + end + + return self.ScanSetGroup +end + +--- Count the number of different coalitions inside the zone. +-- @param #ZONE_POLYGON self +-- @return #number Counted coalitions. +function ZONE_POLYGON:CountScannedCoalitions() + + local Count = 0 + + for CoalitionID, Coalition in pairs( self.ScanData.Coalitions ) do + Count = Count + 1 + end + + return Count +end + +--- Check if a certain coalition is inside a scanned zone. +-- @param #ZONE_POLYGON self +-- @param #number Coalition The coalition id, e.g. coalition.side.BLUE. +-- @return #boolean If true, the coalition is inside the zone. +function ZONE_POLYGON:CheckScannedCoalition( Coalition ) + if Coalition then + return self.ScanData.Coalitions[Coalition] + end + return nil +end + +--- Get Coalitions of the units in the Zone, or Check if there are units of the given Coalition in the Zone. +-- Returns nil if there are none to two Coalitions in the zone! +-- Returns one Coalition if there are only Units of one Coalition in the Zone. +-- Returns the Coalition for the given Coalition if there are units of the Coalition in the Zone. +-- @param #ZONE_POLYGON self +-- @return #table +function ZONE_POLYGON:GetScannedCoalition( Coalition ) + + if Coalition then + return self.ScanData.Coalitions[Coalition] + else + local Count = 0 + local ReturnCoalition = nil + + for CoalitionID, Coalition in pairs( self.ScanData.Coalitions ) do + Count = Count + 1 + ReturnCoalition = CoalitionID + end + + if Count ~= 1 then + ReturnCoalition = nil + end + + return ReturnCoalition + end +end + +--- Get scanned scenery types +-- @param #ZONE_POLYGON self +-- @return #table Table of DCS scenery type objects. +function ZONE_POLYGON:GetScannedSceneryType( SceneryType ) + return self.ScanData.Scenery[SceneryType] +end + +--- Get scanned scenery table +-- @param #ZONE_POLYGON self +-- @return #table Table of Wrapper.Scenery#SCENERY scenery objects. +function ZONE_POLYGON:GetScannedSceneryObjects() + return self.ScanData.SceneryTable +end + +--- Get scanned scenery table +-- @param #ZONE_POLYGON self +-- @return #table Structured table of [type].[name].Wrapper.Scenery#SCENERY scenery objects. +function ZONE_POLYGON:GetScannedScenery() + return self.ScanData.Scenery +end + +--- Get scanned set of scenery objects +-- @param #ZONE_POLYGON self +-- @return #table Table of Wrapper.Scenery#SCENERY scenery objects. +function ZONE_POLYGON:GetScannedSetScenery() + local scenery = SET_SCENERY:New() + local objects = self:GetScannedSceneryObjects() + for _,_obj in pairs (objects) do + scenery:AddScenery(_obj) + end + return scenery +end + +--- Is All in Zone of Coalition? +-- Check if only the specified coalition is inside the zone and noone else. +-- @param #ZONE_POLYGON self +-- @param #number Coalition Coalition ID of the coalition which is checked to be the only one in the zone. +-- @return #boolean True, if **only** that coalition is inside the zone and no one else. +-- @usage +-- self.Zone:Scan() +-- local IsGuarded = self.Zone:IsAllInZoneOfCoalition( self.Coalition ) +function ZONE_POLYGON:IsAllInZoneOfCoalition( Coalition ) + return self:CountScannedCoalitions() == 1 and self:GetScannedCoalition( Coalition ) == true +end + +--- Is All in Zone of Other Coalition? +-- Check if only one coalition is inside the zone and the specified coalition is not the one. +-- You first need to use the @{#ZONE_POLYGON.Scan} method to scan the zone before it can be evaluated! +-- Note that once a zone has been scanned, multiple evaluations can be done on the scan result set. +-- @param #ZONE_POLYGON self +-- @param #number Coalition Coalition ID of the coalition which is not supposed to be in the zone. +-- @return #boolean True, if and only if only one coalition is inside the zone and the specified coalition is not it. +-- @usage +-- self.Zone:Scan() +-- local IsCaptured = self.Zone:IsAllInZoneOfOtherCoalition( self.Coalition ) +function ZONE_POLYGON:IsAllInZoneOfOtherCoalition( Coalition ) + return self:CountScannedCoalitions() == 1 and self:GetScannedCoalition( Coalition ) == nil +end + +--- Is Some in Zone of Coalition? +-- Check if more than one coalition is inside the zone and the specified coalition is one of them. +-- You first need to use the @{#ZONE_POLYGON.Scan} method to scan the zone before it can be evaluated! +-- Note that once a zone has been scanned, multiple evaluations can be done on the scan result set. +-- @param #ZONE_POLYGON self +-- @param #number Coalition ID of the coalition which is checked to be inside the zone. +-- @return #boolean True if more than one coalition is inside the zone and the specified coalition is one of them. +-- @usage +-- self.Zone:Scan() +-- local IsAttacked = self.Zone:IsSomeInZoneOfCoalition( self.Coalition ) +function ZONE_POLYGON:IsSomeInZoneOfCoalition( Coalition ) + return self:CountScannedCoalitions() > 1 and self:GetScannedCoalition( Coalition ) == true +end + +--- Is None in Zone of Coalition? +-- You first need to use the @{#ZONE_POLYGON.Scan} method to scan the zone before it can be evaluated! +-- Note that once a zone has been scanned, multiple evaluations can be done on the scan result set. +-- @param #ZONE_POLYGON self +-- @param Coalition +-- @return #boolean +-- @usage +-- self.Zone:Scan() +-- local IsOccupied = self.Zone:IsNoneInZoneOfCoalition( self.Coalition ) +function ZONE_POLYGON:IsNoneInZoneOfCoalition( Coalition ) + return self:GetScannedCoalition( Coalition ) == nil +end + +--- Is None in Zone? +-- You first need to use the @{#ZONE_POLYGON.Scan} method to scan the zone before it can be evaluated! +-- Note that once a zone has been scanned, multiple evaluations can be done on the scan result set. +-- @param #ZONE_POLYGON self +-- @return #boolean +-- @usage +-- self.Zone:Scan() +-- local IsEmpty = self.Zone:IsNoneInZone() +function ZONE_POLYGON:IsNoneInZone() + return self:CountScannedCoalitions() == 0 +end + + do -- ZONE_ELASTIC --- @type ZONE_ELASTIC @@ -2627,7 +2985,7 @@ do -- ZONE_AIRBASE --- The ZONE_AIRBASE class defines by a zone around a @{Wrapper.Airbase#AIRBASE} with a radius. - -- This class implements the inherited functions from @{Core.Zone#ZONE_RADIUS} taking into account the own zone format and properties. + -- This class implements the inherited functions from @{#ZONE_RADIUS} taking into account the own zone format and properties. -- -- @field #ZONE_AIRBASE ZONE_AIRBASE = { @@ -2647,7 +3005,7 @@ do -- ZONE_AIRBASE local Airbase = AIRBASE:FindByName( AirbaseName ) - local self = BASE:Inherit( self, ZONE_RADIUS:New( AirbaseName, Airbase:GetVec2(), Radius ) ) + local self = BASE:Inherit( self, ZONE_RADIUS:New( AirbaseName, Airbase:GetVec2(), Radius, true ) ) self._.ZoneAirbase = Airbase self._.ZoneVec2Cache = self._.ZoneAirbase:GetVec2() @@ -2714,5 +3072,4 @@ do -- ZONE_AIRBASE return PointVec2 end - end diff --git a/Moose Development/Moose/Core/Zone_Detection.lua b/Moose Development/Moose/Core/Zone_Detection.lua index 96a508c0e..bb5424a37 100644 --- a/Moose Development/Moose/Core/Zone_Detection.lua +++ b/Moose Development/Moose/Core/Zone_Detection.lua @@ -1,6 +1,8 @@ +--- **Core** - The ZONE_DETECTION class, defined by a zone name, a detection object and a radius. +-- @module Core.Zone_Detection +-- @image MOOSE.JPG ---- The ZONE_DETECTION class, defined by a zone name, a detection object and a radius. --- @type ZONE_DETECTION +--- @type ZONE_DETECTION -- @field DCS#Vec2 Vec2 The current location of the zone. -- @field DCS#Distance Radius The radius of the zone. -- @extends #ZONE_BASE @@ -29,7 +31,7 @@ function ZONE_DETECTION:New( ZoneName, Detection, Radius ) self.Detection = Detection self.Radius = Radius - + return self end @@ -48,15 +50,14 @@ function ZONE_DETECTION:BoundZone( Points, CountryID, UnBound ) local Angle local RadialBase = math.pi*2 - - -- + for Angle = 0, 360, (360 / Points ) do local Radial = Angle * RadialBase / 360 Point.x = Vec2.x + math.cos( Radial ) * self:GetRadius() Point.y = Vec2.y + math.sin( Radial ) * self:GetRadius() - + local CountryName = _DATABASE.COUNTRY_NAME[CountryID] - + local Tire = { ["country"] = CountryName, ["category"] = "Fortifications", diff --git a/Moose Development/Moose/DCS.lua b/Moose Development/Moose/DCS.lua index b791abd27..bc5a06de1 100644 --- a/Moose Development/Moose/DCS.lua +++ b/Moose Development/Moose/DCS.lua @@ -1,4 +1,6 @@ ---- **DCS API** Prototypes +--- **DCS API** Prototypes. +-- +-- === -- -- See the [Simulator Scripting Engine Documentation](https://wiki.hoggitworld.com/view/Simulator_Scripting_Engine_Documentation) on Hoggit for further explanation and examples. -- @@ -306,6 +308,11 @@ do -- country -- @field Argentinia -- @field Cyprus -- @field Slovenia + -- @field BOLIVIA + -- @field GHANA + -- @field NIGERIA + -- @field PERU + -- @field ECUADOR country = {} --#country diff --git a/Moose Development/Moose/Functional/ATC_Ground.lua b/Moose Development/Moose/Functional/ATC_Ground.lua index 2e72dcea3..5e89ff144 100644 --- a/Moose Development/Moose/Functional/ATC_Ground.lua +++ b/Moose Development/Moose/Functional/ATC_Ground.lua @@ -1,4 +1,4 @@ ---- **Functional** -- Monitor airbase traffic and regulate speed while taxiing. +--- **Functional** - Monitor airbase traffic and regulate speed while taxiing. -- -- === -- diff --git a/Moose Development/Moose/Functional/Artillery.lua b/Moose Development/Moose/Functional/Artillery.lua index f611ff58d..990f0e8a3 100644 --- a/Moose Development/Moose/Functional/Artillery.lua +++ b/Moose Development/Moose/Functional/Artillery.lua @@ -30,7 +30,7 @@ -- ### Contributions: [FlightControl](https://forums.eagle.ru/member.php?u=89536) -- -- ==== --- @module Functional.Arty +-- @module Functional.Artillery -- @image Artillery.JPG ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -108,7 +108,7 @@ --- Enables mission designers easily to assign targets for artillery units. Since the implementation is based on a Finite State Model (FSM), the mission designer can -- interact with the process at certain events or states. -- --- A new ARTY object can be created with the @{#ARTY.New}(*group*) contructor. +-- A new ARTY object can be created with the @{#ARTY.New}(*group*) constructor. -- The parameter *group* has to be a MOOSE Group object and defines ARTY group. -- -- The ARTY FSM process can be started by the @{#ARTY.Start}() command. @@ -146,7 +146,7 @@ -- When a new target is assigned via the @{#ARTY.AssignTargetCoord}() function (see below), the **NewTarget** event is triggered. -- -- ## Assigning Targets --- Assigning targets is a central point of the ARTY class. Multiple targets can be assigned simultanioulsly and are put into a queue. +-- Assigning targets is a central point of the ARTY class. Multiple targets can be assigned simultaneously and are put into a queue. -- Of course, targets can be added at any time during the mission. For example, once they are detected by a reconnaissance unit. -- -- In order to add a target, the function @{#ARTY.AssignTargetCoord}(*coord*, *prio*, *radius*, *nshells*, *maxengage*, *time*, *weapontype*, *name*) has to be used. @@ -161,7 +161,7 @@ -- * *maxengage*: Number of times a target is engaged. -- * *time*: Time of day the engagement is schedule in the format "hh:mm:ss" for hh=hours, mm=minutes, ss=seconds. -- For example "10:15:35". In the case the attack will be executed at a quarter past ten in the morning at the day the mission started. --- If the engagement should start on the following day the format can be specified as "10:15:35+1", where the +1 denots the following day. +-- If the engagement should start on the following day the format can be specified as "10:15:35+1", where the +1 denotes the following day. -- This is useful for longer running missions or if the mission starts at 23:00 hours and the attack should be scheduled at 01:00 hours on the following day. -- Of course, later days are also possible by appending "+2", "+3", etc. -- **Note** that the time has to be given as a string. So the enclosing quotation marks "" are important. @@ -179,7 +179,7 @@ -- Let's first consider the case that none of the targets is scheduled to be executed at a certain time (*time*=nil). -- The ARTY group will first engage the target with higher priority (*prio*=10). After the engagement is finished, the target with lower priority is attacked. -- This is because the target with lower prio has been attacked one time less. After the attack on the lower priority task is finished and both targets --- have been engaged equally often, the target with the higher priority is engaged again. This coninues until a target has engaged three times. +-- have been engaged equally often, the target with the higher priority is engaged again. This continues until a target has engaged three times. -- Once the maximum number of engagements is reached, the target is deleted from the queue. -- -- In other words, the queue is first sorted with respect to the number of engagements and targets with the same number of engagements are sorted with @@ -190,7 +190,7 @@ -- As mentioned above, targets can be engaged at a specific time of the day via the *time* parameter. -- -- If the *time* parameter is specified for a target, the first engagement of that target will happen at that time of the day and not before. --- This also applies when multiple engagements are requested via the *maxengage* parameter. The first attack will not happen before the specifed time. +-- This also applies when multiple engagements are requested via the *maxengage* parameter. The first attack will not happen before the specified time. -- When that timed attack is finished, the *time* parameter is deleted and the remaining engagements are carried out in the same manner as for untimed targets (described above). -- -- Of course, it can happen that a scheduled task should be executed at a time, when another target is already under attack. @@ -201,7 +201,7 @@ -- -- ## Determining the Amount of Ammo -- --- In order to determin when a unit is out of ammo and possible initiate the rearming process it is necessary to know which types of weapons have to be counted. +-- In order to determine when a unit is out of ammo and possible initiate the rearming process it is necessary to know which types of weapons have to be counted. -- For most artillery unit types, this is simple because they only have one type of weapon and hence ammunition. -- -- However, there are more complex scenarios. For example, naval units carry a big arsenal of different ammunition types ranging from various cannon shell types @@ -217,7 +217,7 @@ -- **Note** that the default parameters "weapons.shells", "weapons.nurs", "weapons.missiles" **should in priciple** capture all the corresponding ammo types. -- However, the logic searches for the string "weapon.missies" in the ammo type. Especially for missiles, this string is often not contained in the ammo type descriptor. -- --- One way to determin which types of ammo the unit carries, one can use the debug mode of the arty class via @{#ARTY.SetDebugON}(). +-- One way to determine which types of ammo the unit carries, one can use the debug mode of the arty class via @{#ARTY.SetDebugON}(). -- In debug mode, the all ammo types of the group are printed to the monitor as message and can be found in the DCS.log file. -- -- ## Employing Selected Weapons @@ -274,7 +274,7 @@ -- -- ## Simulated Weapons -- --- In addtion to the standard weapons a group has available some special weapon types that are not possible to use in the native DCS environment are simulated. +-- In addition to the standard weapons a group has available some special weapon types that are not possible to use in the native DCS environment are simulated. -- -- ### Tactical Nukes -- @@ -283,9 +283,9 @@ -- -- By default, they group does not have any nukes available. To give the group the ability the function @{#ARTY.SetTacNukeShells}(*n*) can be used. -- This supplies the group with *n* nuclear shells, where *n* is restricted to the number of conventional shells the group can carry. --- Note that the group must always have convenctional shells left in order to fire a nuclear shell. +-- Note that the group must always have conventional shells left in order to fire a nuclear shell. -- --- The default explostion strength is 0.075 kilo tons TNT. The can be changed with the @{#ARTY.SetTacNukeWarhead}(*strength*), where *strength* is given in kilo tons TNT. +-- The default explosion strength is 0.075 kilo tons TNT. The can be changed with the @{#ARTY.SetTacNukeWarhead}(*strength*), where *strength* is given in kilo tons TNT. -- -- ### Illumination Shells -- @@ -301,12 +301,12 @@ -- -- ### Smoke Shells -- --- In a similar way to illumination shells, ARTY groups can also employ smoke shells. The numer of smoke shells the group has available is set by the function +-- In a similar way to illumination shells, ARTY groups can also employ smoke shells. The number of smoke shells the group has available is set by the function -- @{#ARTY.SetSmokeShells}(*n*, *color*), where *n* is the number of shells and *color* defines the smoke color. Default is SMOKECOLOR.Red. -- -- The weapon type to be used in the @{#ARTY.AssignTargetCoord}() function is *ARTY.WeaponType.SmokeShells*. -- --- The explosive shell the group fired is destroyed shortly before its impact on the ground and smoke of the speficied color is triggered at that position. +-- The explosive shell the group fired is destroyed shortly before its impact on the ground and smoke of the specified color is triggered at that position. -- -- -- ## Assignments via Markers on F10 Map @@ -320,15 +320,15 @@ -- ### Target Assignments -- A new target can be assigned by writing **arty engage** in the marker text. -- This is followed by a **comma separated list** of (optional) keywords and parameters. --- First, it is important to address the ARTY group or groups that should engage. This can be done in numrous ways. The keywords are *battery*, *alias*, *cluster*. +-- First, it is important to address the ARTY group or groups that should engage. This can be done in numerous ways. The keywords are *battery*, *alias*, *cluster*. -- It is also possible to address all ARTY groups by the keyword *everyone* or *allbatteries*. These two can be used synonymously. -- **Note that**, if no battery is assigned nothing will happen. -- -- * *everyone* or *allbatteries* The target is assigned to all batteries. -- * *battery* Name of the ARTY group that the target is assigned to. Note that **the name is case sensitive** and has to be given in quotation marks. Default is all ARTY groups of the right coalition. -- * *alias* Alias of the ARTY group that the target is assigned to. The alias is **case sensitive** and needs to be in quotation marks. --- * *cluster* The cluster of ARTY groups that is addessed. Clusters can be defined by the function @{#ARTY.AddToCluster}(*clusters*). Names are **case sensitive** and need to be in quotation marks. --- * *key* A number to authorize the target assignment. Only specifing the correct number will trigger an engagement. +-- * *cluster* The cluster of ARTY groups that is addressed. Clusters can be defined by the function @{#ARTY.AddToCluster}(*clusters*). Names are **case sensitive** and need to be in quotation marks. +-- * *key* A number to authorize the target assignment. Only specifying the correct number will trigger an engagement. -- * *time* Time for which which the engagement is schedules, e.g. 08:42. Default is as soon as possible. -- * *prio* Priority of the engagement as number between 1 (high prio) and 100 (low prio). Default is 50, i.e. medium priority. -- * *shots* Number of shots (shells, rockets or missiles) fired at each engagement. Default is 5. @@ -353,8 +353,8 @@ -- arty engage, battery "Paladin Alpha", weapon nukes, shots 1, time 20:15 -- arty engage, battery "Horwitzer 1", lldms 41:51:00N 41:47:58E -- --- Note that the keywords and parameters are *case insensitve*. Only exception are the battery, alias and cluster names. --- These must be exactly the same as the names of the goups defined in the mission editor or the aliases and cluster names defined in the script. +-- Note that the keywords and parameters are *case insensitive*. Only exception are the battery, alias and cluster names. +-- These must be exactly the same as the names of the groups defined in the mission editor or the aliases and cluster names defined in the script. -- -- ### Relocation Assignments -- @@ -363,11 +363,11 @@ -- * *time* Time for which which the relocation/move is schedules, e.g. 08:42. Default is as soon as possible. -- * *speed* The speed in km/h the group will drive at. Default is 70% of its max possible speed. -- * *on road* Group will use mainly roads. Default is off, i.e. it will go in a straight line from its current position to the assigned coordinate. --- * *canceltarget* Group will cancel all running firing engagements and immidiately start to move. Default is that group will wait until is current assignment is over. +-- * *canceltarget* Group will cancel all running firing engagements and immediately start to move. Default is that group will wait until is current assignment is over. -- * *battery* Name of the ARTY group that the relocation is assigned to. -- * *alias* Alias of the ARTY group that the target is assigned to. The alias is **case sensitive** and needs to be in quotation marks. --- * *cluster* The cluster of ARTY groups that is addessed. Clusters can be defined by the function @{#ARTY.AddToCluster}(*clusters*). Names are **case sensitive** and need to be in quotation marks. --- * *key* A number to authorize the target assignment. Only specifing the correct number will trigger an engagement. +-- * *cluster* The cluster of ARTY groups that is addressed. Clusters can be defined by the function @{#ARTY.AddToCluster}(*clusters*). Names are **case sensitive** and need to be in quotation marks. +-- * *key* A number to authorize the target assignment. Only specifying the correct number will trigger an engagement. -- * *lldms* Specify the coordinates in Lat/Long degrees, minutes and seconds format. The actual location of the marker is unimportant. The group will move to the coordinates given in the lldms keyword. -- Format is DD:MM:SS[N,S] DD:MM:SS[W,E]. See example below. -- * *readonly* Marker cannot be deleted by users any more. Hence, assignment cannot be cancelled by removing the marker. @@ -410,12 +410,12 @@ -- -- A few options can be set by marks. The corresponding keyword is **arty set**. This can be used to define the rearming place and group for a battery. -- --- To set the reamring place of a group at the marker position type +-- To set the rearming place of a group at the marker position type -- arty set, battery "Paladin Alpha", rearming place -- -- Setting the rearming group is independent of the position of the mark. Just create one anywhere on the map and type -- arty set, battery "Mortar Bravo", rearming group "Ammo Truck M818" --- Note that the name of the rearming group has to be given in quotation marks and spellt exactly as the group name defined in the mission editor. +-- Note that the name of the rearming group has to be given in quotation marks and spelt exactly as the group name defined in the mission editor. -- -- ## Transporting -- @@ -3422,7 +3422,7 @@ function ARTY:onafterMove(Controllable, From, Event, To, move) -- Set current move. self.currentMove=move - -- Route group to coodinate. + -- Route group to coordinate. self:_Move(self.Controllable, move.coord, move.speed, move.onroad) end diff --git a/Moose Development/Moose/Functional/CleanUp.lua b/Moose Development/Moose/Functional/CleanUp.lua index a2183c097..994147589 100644 --- a/Moose Development/Moose/Functional/CleanUp.lua +++ b/Moose Development/Moose/Functional/CleanUp.lua @@ -1,4 +1,4 @@ ---- **Functional** -- Keep airbases clean of crashing or colliding airplanes, and kill missiles when being fired at airbases. +--- **Functional** - Keep airbases clean of crashing or colliding airplanes, and kill missiles when being fired at airbases. -- -- === -- diff --git a/Moose Development/Moose/Functional/Designate.lua b/Moose Development/Moose/Functional/Designate.lua index d6a6be101..7bc0c7a82 100644 --- a/Moose Development/Moose/Functional/Designate.lua +++ b/Moose Development/Moose/Functional/Designate.lua @@ -1,4 +1,4 @@ ---- **Functional** -- Management of target **Designation**. Lase, smoke and illuminate targets. +--- **Functional** - Management of target **Designation**. Lase, smoke and illuminate targets. -- -- === -- @@ -48,7 +48,7 @@ -- -- ![Banner Image](..\Presentations\DESIGNATE\Dia3.JPG) -- --- A typical mission setup would require Recce (a @{Set} of Recce) to be detecting potential targets. +-- A typical mission setup would require Recce (a @{Core.Set} of Recce) to be detecting potential targets. -- The DetectionObject will group the detected targets based on the detection method being used. -- Possible detection methods could be by Area, by Type or by Unit. -- Each grouping will result in a **TargetGroup**, for terminology and clarity we will use this term throughout the document. @@ -276,7 +276,7 @@ do -- DESIGNATE -- # 7. Designate Menu Location for a Mission -- -- You can make DESIGNATE work for a @{Tasking.Mission#MISSION} object. In this way, the designate menu will not appear in the root of the radio menu, but in the menu of the Mission. - -- Use the method @{#DESIGNATE.SetMission}() to set the @{Mission} object for the designate function. + -- Use the method @{#DESIGNATE.SetMission}() to set the @{Tasking.Mission} object for the designate function. -- -- # 8. Status Report -- diff --git a/Moose Development/Moose/Functional/Detection.lua b/Moose Development/Moose/Functional/Detection.lua index d48937517..dfafcae01 100644 --- a/Moose Development/Moose/Functional/Detection.lua +++ b/Moose Development/Moose/Functional/Detection.lua @@ -1,4 +1,4 @@ ---- **Functional** -- Models the detection of enemy units by FACs or RECCEs and group them according various methods. +--- **Functional** - Models the detection of enemy units by FACs or RECCEs and group them according various methods. -- -- === -- @@ -40,7 +40,7 @@ do -- DETECTION_BASE --- @type DETECTION_BASE - -- @field Core.Set#SET_GROUP DetectionSetGroup The @{Set} of GROUPs in the Forward Air Controller role. + -- @field Core.Set#SET_GROUP DetectionSetGroup The @{Core.Set} of GROUPs in the Forward Air Controller role. -- @field DCS#Distance DetectionRange The range till which targets are accepted to be detected. -- @field #DETECTION_BASE.DetectedObjects DetectedObjects The list of detected objects. -- @field #table DetectedObjectsIdentified Map of the DetectedObjects identified. @@ -318,7 +318,7 @@ do -- DETECTION_BASE --- DETECTION constructor. -- @param #DETECTION_BASE self - -- @param Core.Set#SET_GROUP DetectionSet The @{Set} of @{Group}s that is used to detect the units. + -- @param Core.Set#SET_GROUP DetectionSet The @{Core.Set} of @{Wrapper.Group}s that is used to detect the units. -- @return #DETECTION_BASE self function DETECTION_BASE:New( DetectionSet ) @@ -1982,7 +1982,7 @@ do -- DETECTION_UNITS --- Will detect units within the battle zone. -- - -- It will build a DetectedItems list filled with DetectedItems. Each DetectedItem will contain a field Set, which contains a @{Core.Set#SET_UNIT} containing ONE @{UNIT} object reference. + -- It will build a DetectedItems list filled with DetectedItems. Each DetectedItem will contain a field Set, which contains a @{Core.Set#SET_UNIT} containing ONE @{Wrapper.Unit#UNIT} object reference. -- Beware that when the amount of units detected is large, the DetectedItems list will be large also. -- -- @field #DETECTION_UNITS @@ -1993,7 +1993,7 @@ do -- DETECTION_UNITS --- DETECTION_UNITS constructor. -- @param Functional.Detection#DETECTION_UNITS self - -- @param Core.Set#SET_GROUP DetectionSetGroup The @{Set} of GROUPs in the Forward Air Controller role. + -- @param Core.Set#SET_GROUP DetectionSetGroup The @{Core.Set} of GROUPs in the Forward Air Controller role. -- @return Functional.Detection#DETECTION_UNITS self function DETECTION_UNITS:New( DetectionSetGroup ) @@ -2237,7 +2237,7 @@ do -- DETECTION_TYPES --- Will detect units within the battle zone. -- It will build a DetectedItems[] list filled with DetectedItems, grouped by the type of units detected. - -- Each DetectedItem will contain a field Set, which contains a @{Core.Set#SET_UNIT} containing ONE @{UNIT} object reference. + -- Each DetectedItem will contain a field Set, which contains a @{Core.Set#SET_UNIT} containing ONE @{Wrapper.Unit#UNIT} object reference. -- Beware that when the amount of different types detected is large, the DetectedItems[] list will be large also. -- -- @field #DETECTION_TYPES @@ -2248,7 +2248,7 @@ do -- DETECTION_TYPES --- DETECTION_TYPES constructor. -- @param Functional.Detection#DETECTION_TYPES self - -- @param Core.Set#SET_GROUP DetectionSetGroup The @{Set} of GROUPs in the Recce role. + -- @param Core.Set#SET_GROUP DetectionSetGroup The @{Core.Set} of GROUPs in the Recce role. -- @return Functional.Detection#DETECTION_TYPES self function DETECTION_TYPES:New( DetectionSetGroup ) @@ -2436,7 +2436,7 @@ do -- DETECTION_AREAS --- @type DETECTION_AREAS -- @field DCS#Distance DetectionZoneRange The range till which targets are grouped upon the first detected target. - -- @field #DETECTION_BASE.DetectedItems DetectedItems A list of areas containing the set of @{Wrapper.Unit}s, @{Zone}s, the center @{Wrapper.Unit} within the zone, and ID of each area that was detected within a DetectionZoneRange. + -- @field #DETECTION_BASE.DetectedItems DetectedItems A list of areas containing the set of @{Wrapper.Unit}s, @{Core.Zone}s, the center @{Wrapper.Unit} within the zone, and ID of each area that was detected within a DetectionZoneRange. -- @extends Functional.Detection#DETECTION_BASE --- Detect units within the battle zone for a list of @{Wrapper.Group}s detecting targets following (a) detection method(s), @@ -2477,7 +2477,7 @@ do -- DETECTION_AREAS --- DETECTION_AREAS constructor. -- @param #DETECTION_AREAS self - -- @param Core.Set#SET_GROUP DetectionSetGroup The @{Set} of GROUPs in the Forward Air Controller role. + -- @param Core.Set#SET_GROUP DetectionSetGroup The @{Core.Set} of GROUPs in the Forward Air Controller role. -- @param DCS#Distance DetectionZoneRange The range till which targets are grouped upon the first detected target. -- @return #DETECTION_AREAS function DETECTION_AREAS:New( DetectionSetGroup, DetectionZoneRange ) @@ -2498,7 +2498,7 @@ do -- DETECTION_AREAS --- Retrieve set of detected zones. -- @param #DETECTION_AREAS self - -- @return Core.Set#SET_ZONE The @{Set} of ZONE_UNIT objects detected. + -- @return Core.Set#SET_ZONE The @{Core.Set} of ZONE_UNIT objects detected. function DETECTION_AREAS:GetDetectionZones() local zoneset = SET_ZONE:New() for _ID,_Item in pairs (self.DetectedItems) do diff --git a/Moose Development/Moose/Functional/DetectionZones.lua b/Moose Development/Moose/Functional/DetectionZones.lua index a64710a15..8cb9b9d10 100644 --- a/Moose Development/Moose/Functional/DetectionZones.lua +++ b/Moose Development/Moose/Functional/DetectionZones.lua @@ -1,8 +1,12 @@ +--- **Functional** - Captures the class DETECTION_ZONES. +-- @module Functional.DetectionZones +-- @image MOOSE.JPG + do -- DETECTION_ZONES --- @type DETECTION_ZONES -- @field DCS#Distance DetectionZoneRange The range till which targets are grouped upon the first detected target. - -- @field #DETECTION_BASE.DetectedItems DetectedItems A list of areas containing the set of @{Wrapper.Unit}s, @{Zone}s, the center @{Wrapper.Unit} within the zone, and ID of each area that was detected within a DetectionZoneRange. + -- @field #DETECTION_BASE.DetectedItems DetectedItems A list of areas containing the set of @{Wrapper.Unit}s, @{Core.Zone}s, the center @{Wrapper.Unit} within the zone, and ID of each area that was detected within a DetectionZoneRange. -- @extends Functional.Detection#DETECTION_BASE --- (old, to be revised ) Detect units within the battle zone for a list of @{Core.Zone}s detecting targets following (a) detection method(s), @@ -40,27 +44,27 @@ do -- DETECTION_ZONES ClassName = "DETECTION_ZONES", DetectionZoneRange = nil, } - - + + --- DETECTION_ZONES constructor. -- @param #DETECTION_ZONES self - -- @param Core.Set#SET_ZONE DetectionSetZone The @{Set} of ZONE_RADIUS. + -- @param Core.Set#SET_ZONE DetectionSetZone The @{Core.Set} of ZONE_RADIUS. -- @param DCS#Coalition.side DetectionCoalition The coalition of the detection. -- @return #DETECTION_ZONES function DETECTION_ZONES:New( DetectionSetZone, DetectionCoalition ) - + -- Inherits from DETECTION_BASE local self = BASE:Inherit( self, DETECTION_BASE:New( DetectionSetZone ) ) -- #DETECTION_ZONES - + self.DetectionSetZone = DetectionSetZone -- Core.Set#SET_ZONE self.DetectionCoalition = DetectionCoalition - + self._SmokeDetectedUnits = false self._FlareDetectedUnits = false self._SmokeDetectedZones = false self._FlareDetectedZones = false self._BoundDetectedZones = false - + return self end diff --git a/Moose Development/Moose/Functional/Escort.lua b/Moose Development/Moose/Functional/Escort.lua index 43686ba06..57a9ed5da 100644 --- a/Moose Development/Moose/Functional/Escort.lua +++ b/Moose Development/Moose/Functional/Escort.lua @@ -1,4 +1,4 @@ ---- **Functional** -- Taking the lead of AI escorting your flight. +--- **Functional** - Taking the lead of AI escorting your flight. -- -- === -- diff --git a/Moose Development/Moose/Functional/Fox.lua b/Moose Development/Moose/Functional/Fox.lua index 1e6341a0d..9aa65eabf 100644 --- a/Moose Development/Moose/Functional/Fox.lua +++ b/Moose Development/Moose/Functional/Fox.lua @@ -1,4 +1,4 @@ ---- **Functional** - (R2.5) - Yet Another Missile Trainer. +--- **Functional** - Yet Another Missile Trainer. -- -- -- Practice to evade missiles without being destroyed. @@ -20,7 +20,7 @@ -- === -- -- ### Author: **funkyfranky** --- @module Functional.FOX +-- @module Functional.Fox -- @image Functional_FOX.png --- FOX class. diff --git a/Moose Development/Moose/Functional/Mantis.lua b/Moose Development/Moose/Functional/Mantis.lua index 2dde61915..3f6f7b008 100644 --- a/Moose Development/Moose/Functional/Mantis.lua +++ b/Moose Development/Moose/Functional/Mantis.lua @@ -1,11 +1,13 @@ ---- **Functional** -- Modular, Automatic and Network capable Targeting and Interception System for Air Defenses +--- **Functional** - Modular, Automatic and Network capable Targeting and Interception System for Air Defenses. -- -- === -- --- **MANTIS** - Moose derived Modular, Automatic and Network capable Targeting and Interception System --- Controls a network of SAM sites. Uses detection to switch on the AA site closest to the enemy. --- Automatic mode (default since 0.8) can set-up your SAM site network automatically for you. --- Leverage evasiveness from SEAD, leverage attack range setting. +-- ## Features: +-- +-- * Moose derived Modular, Automatic and Network capable Targeting and Interception System. +-- * Controls a network of SAM sites. Uses detection to switch on the AA site closest to the enemy. +-- * Automatic mode (default since 0.8) can set-up your SAM site network automatically for you. +-- * Leverage evasiveness from SEAD, leverage attack range setting. -- -- === -- @@ -20,7 +22,7 @@ -- @module Functional.Mantis -- @image Functional.Mantis.jpg -- --- Date: Dec 2021 +-- Last Update: Oct 2022 ------------------------------------------------------------------------- --- **MANTIS** class, extends Core.Base#BASE @@ -61,10 +63,11 @@ --- *The worst thing that can happen to a good cause is, not to be skillfully attacked, but to be ineptly defended.* - Frédéric Bastiat -- --- Simple Class for a more intelligent Air Defense System +-- Moose class for a more intelligent Air Defense System -- --- #MANTIS --- Moose derived Modular, Automatic and Network capable Targeting and Interception System. +-- # MANTIS +-- +-- * Moose derived Modular, Automatic and Network capable Targeting and Interception System. -- * Controls a network of SAM sites. Uses detection to switch on the SAM site closest to the enemy. -- * **Automatic mode** (default since 0.8) can set-up your SAM site network automatically for you -- * **Classic mode** behaves like before @@ -100,9 +103,11 @@ -- * Roland -- * Silkworm (though strictly speaking this is a surface to ship missile) -- * SA-2, SA-3, SA-5, SA-6, SA-7, SA-8, SA-9, SA-10, SA-11, SA-13, SA-15, SA-19 --- * and from HDS (see note below): SA-2, SA-3, SA-10B, SA-10C, SA-12, SA-17, SA-20A, SA-20B, SA-23, HQ-2 +-- * From HDS (see note on HDS below): SA-2, SA-3, SA-10B, SA-10C, SA-12, SA-17, SA-20A, SA-20B, SA-23, HQ-2 +-- * From SMA: RBS98M, RBS70, RBS90, RBS90M, RBS103A, RBS103B, RBS103AM, RBS103BM, Lvkv9040M +-- **NOTE** If you are using the Swedish Military Assets (SMA), please note that the **group name** for RBS-SAM types also needs to contain the keyword "SMA" -- --- Following the example started above, an SA-6 site group name should start with "Red SAM SA-6" then, or a blue Patriot installation with e.g. "Blue SAM Patriot". +-- Following the example started above, an SA-6 site group name should start with "Red SAM SA-6" then, or a blue Patriot installation with e.g. "Blue SAM Patriot". -- **NOTE** If you are using the High-Digit-Sam Mod, please note that the **group name** for the following SAM types also needs to contain the keyword "HDS": -- -- * SA-2 (with V759 missile, e.g. "Red SAM SA-2 HDS") @@ -211,7 +216,7 @@ -- * grouping = 5000 (meters) - Detection (EWR) will group enemy flights to areas of 5km for tracking - `MANTIS:SetEWRGrouping(radius)` -- * detectinterval = 30 (seconds) - MANTIS will decide every 30 seconds which SAM to activate - `MANTIS:SetDetectInterval(interval)` -- * engagerange = 95 (percent) - SAMs will only fire if flights are inside of a 95% radius of their max firerange - `MANTIS:SetSAMRange(range)` --- * dynamic = false - Group filtering is set to once, i.e. newly added groups will not be part of the setup by default - `MANTIS:New(name,samprefix,ewrprefix,hq,coaltion,dynamic)` +-- * dynamic = false - Group filtering is set to once, i.e. newly added groups will not be part of the setup by default - `MANTIS:New(name,samprefix,ewrprefix,hq,coalition,dynamic)` -- * autorelocate = false - HQ and (mobile) EWR system will not relocate in random intervals between 30mins and 1 hour - `MANTIS:SetAutoRelocate(hq, ewr)` -- * debug = false - Debugging reports on screen are set to off - `MANTIS:Debug(onoff)` -- @@ -387,6 +392,29 @@ MANTIS.SamDataHDS = { ["HQ-2 HDS"] = { Range=50, Blindspot=6, Height=35, Type="Medium", Radar="HQ_2_Guideline_LN" }, } +--- SAM data SMA +-- @type MANTIS.SamDataSMA +-- @field #number Range Max firing range in km +-- @field #number Blindspot no-firing range (green circle) +-- @field #number Height Max firing height in km +-- @field #string Type #MANTIS.SamType of SAM, i.e. SHORT, MEDIUM or LONG (range) +-- @field #string Radar Radar typename on unit level (used as key) +MANTIS.SamDataSMA = { + -- units from SMA Mod (Sweedish Military Assets) + -- https://forum.dcs.world/topic/295202-swedish-military-assets-for-dcs-by-currenthill/ + -- group name MUST contain SMA to ID launcher type correctly! + ["RBS98M SMA"] = { Range=20, Blindspot=0, Height=8, Type="Short", Radar="RBS-98" }, + ["RBS70 SMA"] = { Range=8, Blindspot=0, Height=5.5, Type="Short", Radar="RBS-70" }, + ["RBS70M SMA"] = { Range=8, Blindspot=0, Height=5.5, Type="Short", Radar="BV410_RBS70" }, + ["RBS90 SMA"] = { Range=8, Blindspot=0, Height=5.5, Type="Short", Radar="RBS-90" }, + ["RBS90M SMA"] = { Range=8, Blindspot=0, Height=5.5, Type="Short", Radar="BV410_RBS90" }, + ["RBS103A SMA"] = { Range=150, Blindspot=3, Height=24.5, Type="Long", Radar="LvS-103_Lavett103_Rb103A" }, + ["RBS103B SMA"] = { Range=35, Blindspot=0, Height=36, Type="Medium", Radar="LvS-103_Lavett103_Rb103B" }, + ["RBS103AM SMA"] = { Range=150, Blindspot=3, Height=24.5, Type="Long", Radar="LvS-103_Lavett103_HX_Rb103A" }, + ["RBS103BM SMA"] = { Range=35, Blindspot=0, Height=36, Type="Medium", Radar="LvS-103_Lavett103_HX_Rb103B" }, + ["Lvkv9040M SMA"] = { Range=4, Blindspot=0, Height=2.5, Type="Short", Radar="LvKv9040" }, +} + ----------------------------------------------------------------------- -- MANTIS System ----------------------------------------------------------------------- @@ -398,7 +426,7 @@ do --@param #string samprefix Prefixes for the SAM groups from the ME, e.g. all groups starting with "Red Sam..." --@param #string ewrprefix Prefixes for the EWR groups from the ME, e.g. all groups starting with "Red EWR..." --@param #string hq Group name of your HQ (optional) - --@param #string coaltion Coalition side of your setup, e.g. "blue", "red" or "neutral" + --@param #string coalition Coalition side of your setup, e.g. "blue", "red" or "neutral" --@param #boolean dynamic Use constant (true) filtering or just filter once (false, default) (optional) --@param #string awacs Group name of your Awacs (optional) --@param #boolean EmOnOff Make MANTIS switch Emissions on and off instead of changing the alarm state between RED and GREEN (optional) @@ -421,7 +449,7 @@ do -- mybluemantis = MANTIS:New("bluemantis","Blue SAM","Blue EWR",nil,"blue",false,"Blue Awacs") -- mybluemantis:Start() -- - function MANTIS:New(name,samprefix,ewrprefix,hq,coaltion,dynamic,awacs, EmOnOff, Padding) + function MANTIS:New(name,samprefix,ewrprefix,hq,coalition,dynamic,awacs, EmOnOff, Padding) -- DONE: Create some user functions for these -- DONE: Make HQ useful @@ -434,7 +462,7 @@ do self.SAM_Templates_Prefix = samprefix or "Red SAM" self.EWR_Templates_Prefix = ewrprefix or "Red EWR" self.HQ_Template_CC = hq or nil - self.Coalition = coaltion or "red" + self.Coalition = coalition or "red" self.SAM_Table = {} self.SAM_Table_Long = {} self.SAM_Table_Medium = {} @@ -550,7 +578,7 @@ do -- TODO Version -- @field #string version - self.version="0.8.8" + self.version="0.8.9" self:I(string.format("***** Starting MANTIS Version %s *****", self.version)) --- FSM Functions --- @@ -1270,11 +1298,12 @@ do -- @param #MANTIS self -- @param #string grpname Name of the group -- @param #boolean mod HDS mod flag + -- @param #boolean sma SMA mod flag -- @return #number range Max firing range -- @return #number height Max firing height -- @return #string type Long, medium or short range -- @return #number blind "blind" spot - function MANTIS:_GetSAMDataFromUnits(grpname,mod) + function MANTIS:_GetSAMDataFromUnits(grpname,mod,sma) self:T(self.lid.."_GetSAMRangeFromUnits") local found = false local range = self.checkradius @@ -1287,6 +1316,8 @@ do local SAMData = self.SamData if mod then SAMData = self.SamDataHDS + elseif sma then + SAMData = self.SamDataSMA end --self:I("Looking to auto-match for "..grpname) for _,_unit in pairs(units) do @@ -1332,8 +1363,11 @@ do local blind = 0 local found = false local HDSmod = false + local SMAMod = false if string.find(grpname,"HDS",1,true) then HDSmod = true + elseif string.find(grpname,"SMA",1,true) then + SMAMod = true end if self.automode then for idx,entry in pairs(self.SamData) do @@ -1352,8 +1386,8 @@ do end end -- secondary filter if not found - if (not found and self.automode) or HDSmod then - range, height, type = self:_GetSAMDataFromUnits(grpname,HDSmod) + if (not found and self.automode) or HDSmod or SMAMod then + range, height, type = self:_GetSAMDataFromUnits(grpname,HDSmod,SMAMod) elseif not found then self:E(self.lid .. string.format("*****Could not match radar data for %s! Will default to midrange values!",grpname)) end diff --git a/Moose Development/Moose/Functional/MissileTrainer.lua b/Moose Development/Moose/Functional/MissileTrainer.lua index cc8de571b..24f2046bc 100644 --- a/Moose Development/Moose/Functional/MissileTrainer.lua +++ b/Moose Development/Moose/Functional/MissileTrainer.lua @@ -1,4 +1,4 @@ ---- **Functional** -- Train missile defence and deflection. +--- **Functional** - Train missile defence and deflection. -- -- === -- @@ -28,14 +28,14 @@ -- * **Messages Off**: Disable all messages. -- * **Tracking**: Menu to configure missile tracking messages. -- * **To All**: Shows missile tracking messages to all players. --- * **To Target**: Shows missile tracking messages only to the player where the missile is targetted at. +-- * **To Target**: Shows missile tracking messages only to the player where the missile is targeted at. -- * **Tracking On**: Show missile tracking messages. -- * **Tracking Off**: Disable missile tracking messages. -- * **Frequency Increase**: Increases the missile tracking message frequency with one second. -- * **Frequency Decrease**: Decreases the missile tracking message frequency with one second. -- * **Alerts**: Menu to configure alert messages. -- * **To All**: Shows alert messages to all players. --- * **To Target**: Shows alert messages only to the player where the missile is (was) targetted at. +-- * **To Target**: Shows alert messages only to the player where the missile is (was) targeted at. -- * **Hits On**: Show missile hit alert messages. -- * **Hits Off**: Disable missile hit alert messages. -- * **Launches On**: Show missile launch messages. @@ -88,7 +88,7 @@ -- A MISSILETRAINER object will behave differently based on the usage of initialization methods: -- -- * @{#MISSILETRAINER.InitMessagesOnOff}: Sets by default the display of any message to be ON or OFF. --- * @{#MISSILETRAINER.InitTrackingToAll}: Sets by default the missile tracking report for all players or only for those missiles targetted to you. +-- * @{#MISSILETRAINER.InitTrackingToAll}: Sets by default the missile tracking report for all players or only for those missiles targeted to you. -- * @{#MISSILETRAINER.InitTrackingOnOff}: Sets by default the display of missile tracking report to be ON or OFF. -- * @{#MISSILETRAINER.InitTrackingFrequency}: Increases, decreases the missile tracking message display frequency with the provided time interval in seconds. -- * @{#MISSILETRAINER.InitAlertsToAll}: Sets by default the display of alerts to be shown to all players or only to you. @@ -256,7 +256,7 @@ function MISSILETRAINER:InitMessagesOnOff( MessagesOnOff ) return self end ---- Sets by default the missile tracking report for all players or only for those missiles targetted to you. +--- Sets by default the missile tracking report for all players or only for those missiles targeted to you. -- @param #MISSILETRAINER self -- @param #boolean TrackingToAll true or false -- @return #MISSILETRAINER self diff --git a/Moose Development/Moose/Functional/Movement.lua b/Moose Development/Moose/Functional/Movement.lua index 7c004d4e2..bcb8bb9c1 100644 --- a/Moose Development/Moose/Functional/Movement.lua +++ b/Moose Development/Moose/Functional/Movement.lua @@ -1,4 +1,4 @@ ---- **Functional** -- Limit the movement of simulaneous moving ground vehicles. +--- **Functional** - Limit the movement of simulaneous moving ground vehicles. -- -- === -- @@ -30,23 +30,23 @@ MOVEMENT = { function MOVEMENT:New( MovePrefixes, MoveMaximum ) local self = BASE:Inherit( self, BASE:New() ) -- #MOVEMENT self:F( { MovePrefixes, MoveMaximum } ) - + if type( MovePrefixes ) == 'table' then self.MovePrefixes = MovePrefixes else self.MovePrefixes = { MovePrefixes } end - self.MoveCount = 0 -- The internal counter of the amount of Moveing the has happened since MoveStart. - self.MoveMaximum = MoveMaximum -- Contains the Maximum amount of units that are allowed to move... - self.AliveUnits = 0 -- Contains the counter how many units are currently alive - self.MoveUnits = {} -- Reflects if the Moving for this MovePrefixes is going to be scheduled or not. - + self.MoveCount = 0 -- The internal counter of the amount of Moving the has happened since MoveStart. + self.MoveMaximum = MoveMaximum -- Contains the Maximum amount of units that are allowed to move. + self.AliveUnits = 0 -- Contains the counter how many units are currently alive. + self.MoveUnits = {} -- Reflects if the Moving for this MovePrefixes is going to be scheduled or not. + self:HandleEvent( EVENTS.Birth ) - + -- self:AddEvent( world.event.S_EVENT_BIRTH, self.OnBirth ) -- -- self:EnableEvents() - + self:ScheduleStart() return self @@ -67,7 +67,7 @@ function MOVEMENT:ScheduleStop() end --- Captures the birth events when new Units were spawned. --- @todo This method should become obsolete. The new @{DATABASE} class will handle the collection administration. +-- @todo This method should become obsolete. The global _DATABASE object (an instance of @{Core.Database#DATABASE}) will handle the collection administration. -- @param #MOVEMENT self -- @param Core.Event#EVENTDATA self function MOVEMENT:OnEventBirth( EventData ) @@ -86,14 +86,14 @@ function MOVEMENT:OnEventBirth( EventData ) end end end - + EventData.IniUnit:HandleEvent( EVENTS.DEAD, self.OnDeadOrCrash ) end end --- Captures the Dead or Crash events when Units crash or are destroyed. --- @todo This method should become obsolete. The new @{DATABASE} class will handle the collection administration. +-- @todo This method should become obsolete. The global _DATABASE object (an instance of @{Core.Database#DATABASE}) will handle the collection administration. function MOVEMENT:OnDeadOrCrash( Event ) self:F( { Event } ) diff --git a/Moose Development/Moose/Functional/PseudoATC.lua b/Moose Development/Moose/Functional/PseudoATC.lua index a203ec8fe..0cf76281f 100644 --- a/Moose Development/Moose/Functional/PseudoATC.lua +++ b/Moose Development/Moose/Functional/PseudoATC.lua @@ -1,4 +1,4 @@ ---- **Functional** - Rudimentary ATC. +--- **Functional** - Basic ATC. -- -- ![Banner Image](..\Presentations\PSEUDOATC\PSEUDOATC_Main.jpg) -- diff --git a/Moose Development/Moose/Functional/RAT.lua b/Moose Development/Moose/Functional/RAT.lua index b33285764..0643cf01b 100644 --- a/Moose Development/Moose/Functional/RAT.lua +++ b/Moose Development/Moose/Functional/RAT.lua @@ -51,7 +51,7 @@ -- ### Contributions: [FlightControl](https://forums.eagle.ru/member.php?u=89536) -- -- === --- @module Functional.Rat +-- @module Functional.RAT -- @image RAT.JPG ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -5443,7 +5443,7 @@ function RAT:_ModifySpawnTemplate(waypoints, livery, spawnplace, departure, take SpawnTemplate.units[UnitID]["onboard_num"] = string.format("%s%d%02d", self.onboardnum, (self.SpawnIndex-1)%10, (self.onboardnum0-1)+UnitID) end - -- Modify coaltion and country of template. + -- Modify coalition and country of template. SpawnTemplate.CoalitionID=self.coalition if self.country then SpawnTemplate.CountryID=self.country diff --git a/Moose Development/Moose/Functional/Range.lua b/Moose Development/Moose/Functional/Range.lua index 4388d2cba..20d879ee0 100644 --- a/Moose Development/Moose/Functional/Range.lua +++ b/Moose Development/Moose/Functional/Range.lua @@ -138,7 +138,7 @@ -- -- A strafe pit can be added to the range by the @{#RANGE.AddStrafePit}(*targetnames, boxlength, boxwidth, heading, inverseheading, goodpass, foulline*) function. -- --- * The first parameter *targetnames* defines the target or targets. This can be a single item or a Table with the name(s) of @{Wrapper.Unit} or @{Static} objects defined in the mission editor. +-- * The first parameter *targetnames* defines the target or targets. This can be a single item or a Table with the name(s) of @{Wrapper.Unit} or @{Wrapper.Static} objects defined in the mission editor. -- * In order to perform a valid pass on the strafe pit, the pilot has to begin his run from the correct direction. Therefore, an "approach box" is defined in front -- of the strafe targets. The parameters *boxlength* and *boxwidth* define the size of the box in meters, while the *heading* parameter defines the heading of the box FROM the target. -- For example, if heading 120 is set, the approach box will start FROM the target and extend outwards on heading 120. A strafe run approach must then be flown apx. heading 300 TOWARDS the target. @@ -157,7 +157,7 @@ -- -- One ore multiple bombing targets can be added to the range by the @{#RANGE.AddBombingTargets}(targetnames, goodhitrange, randommove) function. -- --- * The first parameter *targetnames* defines the target or targets. This can be a single item or a Table with the name(s) of @{Wrapper.Unit} or @{Static} objects defined in the mission editor. +-- * The first parameter *targetnames* defines the target or targets. This can be a single item or a Table with the name(s) of @{Wrapper.Unit} or @{Wrapper.Static} objects defined in the mission editor. -- * The (optional) parameter *goodhitrange* specifies the radius in metres around the target within which a bomb/rocket hit is considered to be "good". -- * If final (optional) parameter "*randommove*" can be enabled to create moving targets. If this parameter is set to true, the units of this bombing target will randomly move within the range zone. -- Note that there might be quirks since DCS units can get stuck in buildings etc. So it might be safer to manually define a route for the units in the mission editor if moving targets are desired. @@ -301,7 +301,7 @@ -- BASE:TraceLevel(1) -- BASE:TraceClass("RANGE") -- --- To get even more output you can increase the trace level to 2 or even 3, c.f. @{BASE} for more details. +-- To get even more output you can increase the trace level to 2 or even 3, c.f. @{Core.Base#BASE} for more details. -- -- The function @{#RANGE.DebugON}() can be used to send messages on screen. It also smokes all defined strafe and bombing targets, the strafe pit approach boxes and the range zone. -- @@ -2259,7 +2259,7 @@ function RANGE:onafterImpact( From, Event, To, result, player ) end -- Send message to player. - local text = string.format( "%s, impact %03d° for %d ft", player.playername, result.radial, UTILS.MetersToFeet( result.distance ) ) + local text = string.format( "%s, impact %03d° for %d ft (%d m)", player.playername, result.radial, UTILS.MetersToFeet( result.distance ), result.distance ) if targetname then text = text .. string.format( " from bulls of target %s.", targetname ) else @@ -4074,19 +4074,12 @@ function RANGE:_myname( unitname ) self:F2( unitname ) local pname = "Ghost 1 1" local unit = UNIT:FindByName( unitname ) - if unit then + if unit and unit:IsAlive() then local grp = unit:GetGroup() - if grp then + if grp and grp:IsAlive() then pname = grp:GetCustomCallSign(true,true) end end - --[[ - local pname = unit:GetPlayerName() - -- local csign = unit:GetCallsign() - - -- return string.format("%s (%s)", csign, pname) - return string.format( "%s", pname ) - --]] return pname end diff --git a/Moose Development/Moose/Functional/Scoring.lua b/Moose Development/Moose/Functional/Scoring.lua index 6b6e05619..24085edf3 100644 --- a/Moose Development/Moose/Functional/Scoring.lua +++ b/Moose Development/Moose/Functional/Scoring.lua @@ -1,4 +1,4 @@ ---- **Functional** - Administer the scoring of player achievements, and create a CSV file logging the scoring events for use at team or squadron websites. +--- **Functional** - Administer the scoring of player achievements, file and log the scoring events for use at websites. -- -- === -- @@ -12,7 +12,7 @@ -- * Score the hits and destroys of units. -- * Score the hits and destroys of statics. -- * Score the hits and destroys of scenery. --- * Log scores into a CSV file. +-- * (optional) Log scores into a CSV file. -- * Connect to a remote server using JSON and IP. -- -- === @@ -59,7 +59,7 @@ -- -- ![Banner Image](..\Presentations\SCORING\Dia9.JPG) -- --- Various @{Zone}s can be defined for which scores are also granted when objects in that @{Zone} are destroyed. +-- Various @{Core.Zone}s can be defined for which scores are also granted when objects in that @{Core.Zone} are destroyed. -- This is **specifically useful** to designate **scenery targets on the map** that will generate points when destroyed. -- -- With a small change in MissionScripting.lua, the scoring results can also be logged in a **CSV file**. @@ -115,7 +115,7 @@ -- -- Special targets can be set that will give extra scores to the players when these are destroyed. -- Use the methods @{#SCORING.AddUnitScore}() and @{#SCORING.RemoveUnitScore}() to specify a special additional score for a specific @{Wrapper.Unit}s. --- Use the methods @{#SCORING.AddStaticScore}() and @{#SCORING.RemoveStaticScore}() to specify a special additional score for a specific @{Static}s. +-- Use the methods @{#SCORING.AddStaticScore}() and @{#SCORING.RemoveStaticScore}() to specify a special additional score for a specific @{Wrapper.Static}s. -- Use the method @{#SCORING.SetGroupGroup}() to specify a special additional score for a specific @{Wrapper.Group}s. -- -- local Scoring = SCORING:New( "Scoring File" ) @@ -131,11 +131,11 @@ -- # Define destruction zones that will give extra scores: -- -- Define zones of destruction. Any object destroyed within the zone of the given category will give extra points. --- Use the method @{#SCORING.AddZoneScore}() to add a @{Zone} for additional scoring. --- Use the method @{#SCORING.RemoveZoneScore}() to remove a @{Zone} for additional scoring. --- There are interesting variations that can be achieved with this functionality. For example, if the @{Zone} is a @{Core.Zone#ZONE_UNIT}, --- then the zone is a moving zone, and anything destroyed within that @{Zone} will generate points. --- The other implementation could be to designate a scenery target (a building) in the mission editor surrounded by a @{Zone}, +-- Use the method @{#SCORING.AddZoneScore}() to add a @{Core.Zone} for additional scoring. +-- Use the method @{#SCORING.RemoveZoneScore}() to remove a @{Core.Zone} for additional scoring. +-- There are interesting variations that can be achieved with this functionality. For example, if the @{Core.Zone} is a @{Core.Zone#ZONE_UNIT}, +-- then the zone is a moving zone, and anything destroyed within that @{Core.Zone} will generate points. +-- The other implementation could be to designate a scenery target (a building) in the mission editor surrounded by a @{Core.Zone}, -- just large enough around that building. -- -- # Add extra Goal scores upon an event or a condition: @@ -225,6 +225,7 @@ SCORING = { ClassName = "SCORING", ClassID = 0, Players = {}, + AutoSave = true, } local _SCORINGCoalition = { @@ -306,6 +307,7 @@ function SCORING:New( GameName ) end ) -- Create the CSV file. + self.AutoSave = true self:OpenCSV( GameName ) return self @@ -373,11 +375,11 @@ function SCORING:RemoveUnitScore( ScoreUnit ) return self end ---- Add a @{Static} for additional scoring when the @{Static} is destroyed. --- Note that if there was already a @{Static} declared within the scoring with the same name, --- then the old @{Static} will be replaced with the new @{Static}. +--- Add a @{Wrapper.Static} for additional scoring when the @{Wrapper.Static} is destroyed. +-- Note that if there was already a @{Wrapper.Static} declared within the scoring with the same name, +-- then the old @{Wrapper.Static} will be replaced with the new @{Wrapper.Static}. -- @param #SCORING self --- @param Wrapper.Static#UNIT ScoreStatic The @{Static} for which the Score needs to be given. +-- @param Wrapper.Static#UNIT ScoreStatic The @{Wrapper.Static} for which the Score needs to be given. -- @param #number Score The Score value. -- @return #SCORING function SCORING:AddStaticScore( ScoreStatic, Score ) @@ -389,9 +391,9 @@ function SCORING:AddStaticScore( ScoreStatic, Score ) return self end ---- Removes a @{Static} for additional scoring when the @{Static} is destroyed. +--- Removes a @{Wrapper.Static} for additional scoring when the @{Wrapper.Static} is destroyed. -- @param #SCORING self --- @param Wrapper.Static#UNIT ScoreStatic The @{Static} for which the Score needs to be given. +-- @param Wrapper.Static#UNIT ScoreStatic The @{Wrapper.Static} for which the Score needs to be given. -- @return #SCORING function SCORING:RemoveStaticScore( ScoreStatic ) @@ -419,11 +421,11 @@ function SCORING:AddScoreGroup( ScoreGroup, Score ) return self end ---- Add a @{Zone} to define additional scoring when any object is destroyed in that zone. --- Note that if a @{Zone} with the same name is already within the scoring added, the @{Zone} (type) and Score will be replaced! +--- Add a @{Core.Zone} to define additional scoring when any object is destroyed in that zone. +-- Note that if a @{Core.Zone} with the same name is already within the scoring added, the @{Core.Zone} (type) and Score will be replaced! -- This allows for a dynamic destruction zone evolution within your mission. -- @param #SCORING self --- @param Core.Zone#ZONE_BASE ScoreZone The @{Zone} which defines the destruction score perimeters. +-- @param Core.Zone#ZONE_BASE ScoreZone The @{Core.Zone} which defines the destruction score perimeters. -- Note that a zone can be a polygon or a moving zone. -- @param #number Score The Score value. -- @return #SCORING @@ -438,11 +440,11 @@ function SCORING:AddZoneScore( ScoreZone, Score ) return self end ---- Remove a @{Zone} for additional scoring. --- The scoring will search if any @{Zone} is added with the given name, and will remove that zone from the scoring. +--- Remove a @{Core.Zone} for additional scoring. +-- The scoring will search if any @{Core.Zone} is added with the given name, and will remove that zone from the scoring. -- This allows for a dynamic destruction zone evolution within your mission. -- @param #SCORING self --- @param Core.Zone#ZONE_BASE ScoreZone The @{Zone} which defines the destruction score perimeters. +-- @param Core.Zone#ZONE_BASE ScoreZone The @{Core.Zone} which defines the destruction score perimeters. -- Note that a zone can be a polygon or a moving zone. -- @return #SCORING function SCORING:RemoveZoneScore( ScoreZone ) @@ -1748,7 +1750,7 @@ end function SCORING:OpenCSV( ScoringCSV ) self:F( ScoringCSV ) - if lfs and io and os then + if lfs and io and os and self.AutoSave then if ScoringCSV then self.ScoringCSV = ScoringCSV local fdir = lfs.writedir() .. [[Logs\]] .. self.ScoringCSV .. " " .. os.date( "%Y-%m-%d %H-%M-%S" ) .. ".csv" @@ -1828,7 +1830,7 @@ function SCORING:ScoreCSV( PlayerName, TargetPlayerName, ScoreType, ScoreTimes, TargetUnitType = TargetUnitType or "" TargetUnitName = TargetUnitName or "" - if lfs and io and os then + if lfs and io and os and self.AutoSave then self.CSVFile:write( '"' .. self.GameName .. '"' .. ',' .. '"' .. self.RunTime .. '"' .. ',' .. @@ -1852,9 +1854,20 @@ function SCORING:ScoreCSV( PlayerName, TargetPlayerName, ScoreType, ScoreTimes, end end +--- Close CSV file +-- @param #SCORING self +-- @return #SCORING self function SCORING:CloseCSV() - if lfs and io and os then + if lfs and io and os and self.AutoSave then self.CSVFile:close() end end +--- Registers a score for a player. +-- @param #SCORING self +-- @param #boolean OnOff Switch saving to CSV on = true or off = false +-- @return #SCORING self +function SCORING:SwitchAutoSave(OnOff) + self.AutoSave = OnOff + return self +end diff --git a/Moose Development/Moose/Functional/Sead.lua b/Moose Development/Moose/Functional/Sead.lua index 2af6c64f3..ebcd2228c 100644 --- a/Moose Development/Moose/Functional/Sead.lua +++ b/Moose Development/Moose/Functional/Sead.lua @@ -1,4 +1,4 @@ ---- **Functional** -- Make SAM sites execute evasive and defensive behaviour when being fired upon. +--- **Functional** - Make SAM sites execute evasive and defensive behaviour when being fired upon. -- -- === -- diff --git a/Moose Development/Moose/Functional/Shorad.lua b/Moose Development/Moose/Functional/Shorad.lua index f70bb11a5..e08f7fa29 100644 --- a/Moose Development/Moose/Functional/Shorad.lua +++ b/Moose Development/Moose/Functional/Shorad.lua @@ -1,9 +1,11 @@ ---- **Functional** -- Short Range Air Defense System +--- **Functional** - Short Range Air Defense System. -- -- === +-- +-- ## Features: -- --- **SHORAD** - Short Range Air Defense System --- Controls a network of short range air/missile defense groups. +-- * Short Range Air Defense System +-- * Controls a network of short range air/missile defense groups. -- -- === -- diff --git a/Moose Development/Moose/Functional/Warehouse.lua b/Moose Development/Moose/Functional/Warehouse.lua index c753a7b0a..26cef4db9 100644 --- a/Moose Development/Moose/Functional/Warehouse.lua +++ b/Moose Development/Moose/Functional/Warehouse.lua @@ -1274,7 +1274,7 @@ -- -- ## Example 13: Battlefield Air Interdiction -- --- This example show how to couple the WAREHOUSE class with the @{AI.AI_Bai} class. +-- This example show how to couple the WAREHOUSE class with the @{AI.AI_BAI} class. -- Four enemy targets have been located at the famous Kobuleti X. All three available Viggen 2-ship flights are assigned to kill at least one of the BMPs to complete their mission. -- -- -- Start Warehouse at Kobuleti. @@ -6814,7 +6814,7 @@ function WAREHOUSE:_OnEventBaseCaptured(EventData) self:AirbaseRecaptured(NewCoalitionAirbase) end else - -- Captured airbase belongs to this warehouse but was captured by other coaltion. + -- Captured airbase belongs to this warehouse but was captured by other coalition. if NewCoalitionAirbase ~= self:GetCoalition() then self:AirbaseCaptured(NewCoalitionAirbase) end @@ -7007,7 +7007,7 @@ function WAREHOUSE:_CheckRequestConsistancy(queue) -- Request from enemy coalition? if self:GetCoalition()~=request.warehouse:GetCoalition() then - self:E(self.lid..string.format("ERROR: INVALID request. Requesting warehouse is of wrong coaltion! Own coalition %s != %s of requesting warehouse.", self:GetCoalitionName(), request.warehouse:GetCoalitionName())) + self:E(self.lid..string.format("ERROR: INVALID request. Requesting warehouse is of wrong coalition! Own coalition %s != %s of requesting warehouse.", self:GetCoalitionName(), request.warehouse:GetCoalitionName())) valid=false end diff --git a/Moose Development/Moose/Functional/ZoneCaptureCoalition.lua b/Moose Development/Moose/Functional/ZoneCaptureCoalition.lua index 9be2c35bf..2439029f9 100644 --- a/Moose Development/Moose/Functional/ZoneCaptureCoalition.lua +++ b/Moose Development/Moose/Functional/ZoneCaptureCoalition.lua @@ -1,4 +1,4 @@ ---- **Functional** -- Models the process to zone guarding and capturing. +--- **Functional** - Models the process to zone guarding and capturing. -- -- === -- @@ -68,9 +68,9 @@ do -- ZONE_CAPTURE_COALITION -- -- In order to use ZONE_CAPTURE_COALITION, you need to: -- - -- * Create a @{Zone} object from one of the ZONE_ classes. - -- Note that ZONE_POLYGON_ classes are not yet functional. - -- The only functional ZONE_ classses are those derived from a ZONE_RADIUS. + -- * Create a @{Core.Zone} object from one of the ZONE_ classes. + -- The functional ZONE_ classses are those derived from a ZONE_RADIUS. + -- In order to use a ZONE_POLYGON, hand over the **GROUP name** of a late activated group forming a polygon with it's waypoints. -- * Set the state of the zone. Most of the time, Guarded would be the initial state. -- * Start the zone capturing **monitoring process**. -- This will check the presence of friendly and/or enemy units within the zone and will transition the state of the zone when the tactical situation changed. @@ -363,7 +363,7 @@ do -- ZONE_CAPTURE_COALITION --- ZONE_CAPTURE_COALITION Constructor. -- @param #ZONE_CAPTURE_COALITION self - -- @param Core.Zone#ZONE Zone A @{Zone} object with the goal to be achieved. + -- @param Core.Zone#ZONE Zone A @{Core.Zone} object with the goal to be achieved. Alternatively, can be handed as the name of late activated group describing a @{ZONE_POLYGON} with its waypoints. -- @param DCSCoalition.DCSCoalition#coalition Coalition The initial coalition owning the zone. -- @param #table UnitCategories Table of unit categories. See [DCS Class Unit](https://wiki.hoggitworld.com/view/DCS_Class_Unit). Default {Unit.Category.GROUND_UNIT}. -- @param #table ObjectCategories Table of unit categories. See [DCS Class Object](https://wiki.hoggitworld.com/view/DCS_Class_Object). Default {Object.Category.UNIT, Object.Category.STATIC}, i.e. all UNITS and STATICS. diff --git a/Moose Development/Moose/Functional/ZoneGoal.lua b/Moose Development/Moose/Functional/ZoneGoal.lua index cd55b2603..1044e7920 100644 --- a/Moose Development/Moose/Functional/ZoneGoal.lua +++ b/Moose Development/Moose/Functional/ZoneGoal.lua @@ -1,4 +1,4 @@ ---- **Functional (WIP)** -- Base class that models processes to achieve goals involving a Zone. +--- **Functional** - Base class that models processes to achieve goals involving a Zone. -- -- === -- @@ -8,7 +8,7 @@ -- === -- -- ### Author: **FlightControl** --- ### Contributions: **funkyfranky** +-- ### Contributions: **funkyfranky**, **Applevangelist** -- -- === -- @@ -26,7 +26,6 @@ do -- Zone -- @field #boolean SmokeZone If true, smoke zone. -- @extends Core.Zone#ZONE_RADIUS - --- Models processes that have a Goal with a defined achievement involving a Zone. -- Derived classes implement the ways how the achievements can be realized. -- @@ -53,21 +52,26 @@ do -- Zone SmokeColor = nil, SmokeZone = nil, } - + --- ZONE_GOAL Constructor. -- @param #ZONE_GOAL self - -- @param Core.Zone#ZONE_RADIUS Zone A @{Zone} object with the goal to be achieved. + -- @param Core.Zone#ZONE_RADIUS Zone A @{Core.Zone} object with the goal to be achieved. Alternatively, can be handed as the name of late activated group describing a ZONE_POLYGON with its waypoints. -- @return #ZONE_GOAL function ZONE_GOAL:New( Zone ) - - local self = BASE:Inherit( self, ZONE_RADIUS:New( Zone:GetName(), Zone:GetVec2(), Zone:GetRadius() ) ) -- #ZONE_GOAL - self:F( { Zone = Zone } ) + BASE:I({Zone=Zone}) + local self = BASE:Inherit( self, BASE:New()) + if type(Zone) == "string" then + self = BASE:Inherit( self, ZONE_POLYGON:NewFromGroupName(Zone) ) + else + self = BASE:Inherit( self, ZONE_RADIUS:New( Zone:GetName(), Zone:GetVec2(), Zone:GetRadius() ) ) -- #ZONE_GOAL + self:F( { Zone = Zone } ) + end -- Goal object. self.Goal = GOAL:New() self.SmokeTime = nil - + -- Set smoke ON. self:SetSmokeZone(true) @@ -81,7 +85,7 @@ do -- Zone -- @function [parent=#ZONE_GOAL] __DestroyedUnit -- @param #ZONE_GOAL self -- @param #number delay Delay in seconds. - + --- DestroyedUnit Handler OnAfter for ZONE_GOAL -- @function [parent=#ZONE_GOAL] OnAfterDestroyedUnit -- @param #ZONE_GOAL self @@ -93,15 +97,15 @@ do -- Zone return self end - + --- Get the Zone. -- @param #ZONE_GOAL self -- @return #ZONE_GOAL function ZONE_GOAL:GetZone() return self end - - + + --- Get the name of the Zone. -- @param #ZONE_GOAL self -- @return #string @@ -109,7 +113,6 @@ do -- Zone return self:GetName() end - --- Activate smoking of zone with the color or the current owner. -- @param #ZONE_GOAL self -- @param #boolean switch If *true* or *nil* activate smoke. If *false* or *nil*, no smoke. @@ -131,11 +134,10 @@ do -- Zone -- @param DCS#SMOKECOLOR.Color SmokeColor function ZONE_GOAL:Smoke( SmokeColor ) self:F( { SmokeColor = SmokeColor} ) - + self.SmokeColor = SmokeColor end - - + --- Flare the zone boundary. -- @param #ZONE_GOAL self -- @param DCS#SMOKECOLOR.Color FlareColor @@ -143,7 +145,6 @@ do -- Zone self:FlareZone( FlareColor, 30) end - --- When started, check the Smoke and the Zone status. -- @param #ZONE_GOAL self function ZONE_GOAL:onafterGuard() @@ -155,17 +156,16 @@ do -- Zone end end - --- Check status Smoke. -- @param #ZONE_GOAL self function ZONE_GOAL:StatusSmoke() self:F({self.SmokeTime, self.SmokeColor}) - + if self.SmokeZone then - + -- Current time. local CurrentTime = timer.getTime() - + -- Restart smoke every 5 min. if self.SmokeTime == nil or self.SmokeTime + 300 <= CurrentTime then if self.SmokeColor then @@ -173,11 +173,10 @@ do -- Zone self.SmokeTime = CurrentTime end end - - end - - end + end + + end --- @param #ZONE_GOAL self -- @param Core.Event#EVENTDATA EventData Event data table. @@ -185,38 +184,37 @@ do -- Zone self:F( { "EventDead", EventData } ) self:F( { EventData.IniUnit } ) - + if EventData.IniDCSUnit then local Vec3 = EventData.IniDCSUnit:getPosition().p self:F( { Vec3 = Vec3 } ) - + if Vec3 and self:IsVec3InZone(Vec3) then - + local PlayerHits = _DATABASE.HITS[EventData.IniUnitName] - + if PlayerHits then - + for PlayerName, PlayerHit in pairs( PlayerHits.Players or {} ) do self.Goal:AddPlayerContribution( PlayerName ) self:DestroyedUnit( EventData.IniUnitName, PlayerName ) end - + end - + end end - + end - - + --- Activate the event UnitDestroyed to be fired when a unit is destroyed in the zone. -- @param #ZONE_GOAL self function ZONE_GOAL:MonitorDestroyedUnits() self:HandleEvent( EVENTS.Dead, self.__Destroyed ) self:HandleEvent( EVENTS.Crash, self.__Destroyed ) - + end - + end diff --git a/Moose Development/Moose/Functional/ZoneGoalCargo.lua b/Moose Development/Moose/Functional/ZoneGoalCargo.lua index 9ae8ae613..fdd0deedf 100644 --- a/Moose Development/Moose/Functional/ZoneGoalCargo.lua +++ b/Moose Development/Moose/Functional/ZoneGoalCargo.lua @@ -1,4 +1,4 @@ ---- **Functional (WIP)** -- Base class that models processes to achieve goals involving a Zone and Cargo. +--- **Functional** - Base class that models processes to achieve goals involving a Zone and Cargo. -- -- === -- @@ -55,7 +55,7 @@ do -- ZoneGoal --- ZONE_GOAL_CARGO Constructor. -- @param #ZONE_GOAL_CARGO self - -- @param Core.Zone#ZONE Zone A @{Zone} object with the goal to be achieved. + -- @param Core.Zone#ZONE Zone A @{Core.Zone} object with the goal to be achieved. -- @param DCSCoalition.DCSCoalition#coalition Coalition The initial coalition owning the zone. -- @return #ZONE_GOAL_CARGO function ZONE_GOAL_CARGO:New( Zone, Coalition ) diff --git a/Moose Development/Moose/Functional/ZoneGoalCoalition.lua b/Moose Development/Moose/Functional/ZoneGoalCoalition.lua index d2086f1ad..64e0034ef 100644 --- a/Moose Development/Moose/Functional/ZoneGoalCoalition.lua +++ b/Moose Development/Moose/Functional/ZoneGoalCoalition.lua @@ -1,4 +1,4 @@ ---- **Functional (WIP)** -- Base class that models processes to achieve goals involving a Zone for a Coalition. +--- **Functional** - Base class that models processes to achieve goals involving a Zone for a Coalition. -- -- === -- @@ -53,7 +53,7 @@ do -- ZoneGoal --- ZONE_GOAL_COALITION Constructor. -- @param #ZONE_GOAL_COALITION self - -- @param Core.Zone#ZONE Zone A @{Zone} object with the goal to be achieved. + -- @param Core.Zone#ZONE Zone A @{Core.Zone} object with the goal to be achieved. -- @param DCSCoalition.DCSCoalition#coalition Coalition The initial coalition owning the zone. Default coalition.side.NEUTRAL. -- @param #table UnitCategories Table of unit categories. See [DCS Class Unit](https://wiki.hoggitworld.com/view/DCS_Class_Unit). Default {Unit.Category.GROUND_UNIT}. -- @return #ZONE_GOAL_COALITION diff --git a/Moose Development/Moose/Globals.lua b/Moose Development/Moose/Globals.lua index f63f57e84..4762a10fb 100644 --- a/Moose Development/Moose/Globals.lua +++ b/Moose Development/Moose/Globals.lua @@ -22,25 +22,37 @@ _DATABASE:_RegisterAirbases() --- Check if os etc is available. BASE:I("Checking de-sanitization of os, io and lfs:") -local __na=false +local __na = false if os then BASE:I("- os available") else BASE:I("- os NOT available! Some functions may not work.") - __na=true + __na = true end if io then BASE:I("- io available") else BASE:I("- io NOT available! Some functions may not work.") - __na=true + __na = true end if lfs then BASE:I("- lfs available") else BASE:I("- lfs NOT available! Some functions may not work.") - __na=true + __na = true end if __na then BASE:I("Check /Scripts/MissionScripting.lua and comment out the lines with sanitizeModule(''). Use at your own risk!)") end +BASE.ServerName = "Unknown" +if lfs and loadfile then + local serverfile = lfs.writedir() .. 'Config/serverSettings.lua' + if UTILS.FileExists(serverfile) then + loadfile(serverfile)() + if cfg and cfg.name then + BASE.ServerName = cfg.name + end + end + BASE.ServerName = BASE.ServerName or "Unknown" + BASE:I("Server Name: " .. tostring(BASE.ServerName)) +end diff --git a/Moose Development/Moose/Ops/ATIS.lua b/Moose Development/Moose/Ops/ATIS.lua index 591129617..083aa86a4 100644 --- a/Moose Development/Moose/Ops/ATIS.lua +++ b/Moose Development/Moose/Ops/ATIS.lua @@ -46,7 +46,7 @@ -- -- ### Author: **funkyfranky** -- --- @module Ops.Atis +-- @module Ops.ATIS -- @image OPS_ATIS.png --- ATIS class. @@ -91,6 +91,8 @@ -- @field #boolean useSRS If true, use SRS for transmission. -- @field Sound.SRS#MSRS msrs Moose SRS object. -- @field #number dTQueueCheck Time interval to check the radio queue. Default 5 sec or 90 sec if SRS is used. +-- @field #boolean ReportmBar Report mBar/hpa even if not metric, i.e. for Mirage flights +-- @field #boolean TransmitOnlyWithPlayers For SRS - If true, only transmit if there are alive Players. -- @extends Core.Fsm#FSM --- *It is a very sad thing that nowadays there is so little useless information.* - Oscar Wilde @@ -120,7 +122,7 @@ -- The @{#ATIS.New}(*airbasename*, *frequency*) creates a new ATIS object. The parameter *airbasename* is the name of the airbase or airport. Note that this has to be spelled exactly as in the DCS mission editor. -- The parameter *frequency* is the frequency the ATIS broadcasts in MHz. -- --- Broadcasting is started via the @{#ATIS.Start}() function. The start can be delayed by useing @{#ATIS.__Start}(*delay*), where *delay* is the delay in seconds. +-- Broadcasting is started via the @{#ATIS.Start}() function. The start can be delayed by using @{#ATIS.__Start}(*delay*), where *delay* is the delay in seconds. -- -- ## Subtitles -- @@ -344,6 +346,8 @@ ATIS = { usemarker = nil, markerid = nil, relHumidity = nil, + ReportmBar = false, + TransmitOnlyWithPlayers = false, } --- NATO alphabet. @@ -586,15 +590,18 @@ _ATIS = {} --- ATIS class version. -- @field #string version -ATIS.version = "0.9.8" +ATIS.version = "0.9.11" ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- TODO list ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --- TODO: Add new Normany airfields. +-- TODO: Add new Normandy airfields. -- TODO: Zulu time --> Zulu in output. -- TODO: Correct fog for elevation. +-- DONE: Use new AIRBASE system to set start/landing runway +-- DONE: SetILS doesn't work +-- DONE: Visibility reported twice over SRS -- DONE: Add text report for output. -- DONE: Add stop FMS functions. -- NOGO: Use local time. Not realisitc! @@ -651,6 +658,7 @@ function ATIS:New(AirbaseName, Frequency, Modulation) self:SetMapMarks( false ) self:SetRelativeHumidity() self:SetQueueUpdateTime() + self:SetReportmBar(false) -- Start State. self:SetStartState( "Stopped" ) @@ -774,13 +782,52 @@ function ATIS:SetTowerFrequencies( freqs ) return self end ---- Set active runway. This can be used if the automatic runway determination via the wind direction gives incorrect results. +--- For SRS - Switch to only transmit if there are players on the server. +-- @param #ATIS self +-- @param #boolean Switch If true, only send SRS if there are alive Players. +-- @return #ATIS self +function ATIS:SetTransmitOnlyWithPlayers(Switch) + self.TransmitOnlyWithPlayers = Switch + if self.msrsQ then + self.msrsQ:SetTransmitOnlyWithPlayers(Switch) + end + return self +end + +--- Set active runway for **landing** operations. This can be used if the automatic runway determination via the wind direction gives incorrect results. -- For example, use this if there are two runways with the same directions. -- @param #ATIS self -- @param #string runway Active runway, *e.g.* "31L". -- @return #ATIS self function ATIS:SetActiveRunway( runway ) self.activerunway = tostring( runway ) + local prefer = nil + if string.find(string.lower(runway),"l") then + prefer = true + elseif string.find(string.lower(runway),"r") then + prefer = false + end + self.airbase:SetActiveRunway(runway,prefer) + return self +end + +--- Set the active runway for landing. +-- @param #ATIS self +-- @param #string runway : Name of the runway, e.g. "31" or "02L" or "90R". If not given, the runway is determined from the wind direction. +-- @param #boolean preferleft : If true, perfer the left runway. If false, prefer the right runway. If nil (default), do not care about left or right. +-- @return #ATIS self +function ATIS:SetActiveRunwayLanding(runway, preferleft) + self.airbase:SetActiveRunwayLanding(runway,preferleft) + return self +end + +--- Set the active runway for take-off. +-- @param #ATIS self +-- @param #string runway : Name of the runway, e.g. "31" or "02L" or "90R". If not given, the runway is determined from the wind direction. +-- @param #boolean preferleft : If true, perfer the left runway. If false, prefer the right runway. If nil (default), do not care about left or right. +-- @return #ATIS self +function ATIS:SetActiveRunwayTakeoff(runway,preferleft) + self.airbase:SetActiveRunwayTakeoff(runway,preferleft) return self end @@ -947,6 +994,28 @@ function ATIS:SetAltimeterQNH( switch ) return self end +--- Additionally report altimeter QNH/QFE in hPa, even if not set to metric. +-- @param #ATIS self +-- @param #boolean switch If true or nil, report mBar/hPa in addition. +-- @return #ATIS self +function ATIS:SetReportmBar(switch) + if switch == true or switch == nil then + self.ReportmBar = true + else + self.ReportmBar = false + end + return self +end + +--- Additionally report free text, only working with SRS(!) +-- @param #ATIS self +-- @param #string text The text to report at the end of the ATIS message, e.g. runway closure, warnings, etc. +-- @return #ATIS self +function ATIS:SetAdditionalInformation(text) + self.AdditionalInformation = text + return self +end + --- Suppresses QFE readout. Default is to report both QNH and QFE. -- @param #ATIS self -- @return #ATIS self @@ -978,7 +1047,7 @@ end -- Or you make your life simple and just include the sign so you don't have to bother about East/West. -- -- @param #ATIS self --- @param #number magvar Magnetic variation in degrees. Positive for easterly and negative for westerly variation. Default is magnatic declinaton of the used map, c.f. @{Utilities.UTils#UTILS.GetMagneticDeclination}. +-- @param #number magvar Magnetic variation in degrees. Positive for easterly and negative for westerly variation. Default is magnatic declinaton of the used map, c.f. @{Utilities.Utils#UTILS.GetMagneticDeclination}. -- @return #ATIS self function ATIS:SetMagneticDeclination( magvar ) self.magvar = magvar or UTILS.GetMagneticDeclination() @@ -1140,6 +1209,7 @@ function ATIS:SetSRS(PathToSRS, Gender, Culture, Voice, Port, GoogleKey) self.msrs:SetLabel("ATIS") self.msrs:SetGoogle(GoogleKey) self.msrsQ = MSRSQUEUE:New("ATIS") + self.msrsQ:SetTransmitOnlyWithPlayers(self.TransmitOnlyWithPlayers) if self.dTQueueCheck<=10 then self:SetQueueUpdateTime(90) end @@ -1188,16 +1258,16 @@ function ATIS:onafterStart( From, Event, To ) -- Start radio queue. if not self.useSRS then self.radioqueue = RADIOQUEUE:New( self.frequency, self.modulation, string.format( "ATIS %s", self.airbasename ) ) - + -- Send coordinate is airbase coord. self.radioqueue:SetSenderCoordinate( self.airbase:GetCoordinate() ) - + -- Set relay unit if we have one. self.radioqueue:SetSenderUnitName( self.relayunitname ) - + -- Set radio power. self.radioqueue:SetRadioPower( self.power ) - + -- Init numbers. self.radioqueue:SetDigit( 0, ATIS.Sound.N0.filename, ATIS.Sound.N0.duration, self.soundpath ) self.radioqueue:SetDigit( 1, ATIS.Sound.N1.filename, ATIS.Sound.N1.duration, self.soundpath ) @@ -1209,11 +1279,11 @@ function ATIS:onafterStart( From, Event, To ) self.radioqueue:SetDigit( 7, ATIS.Sound.N7.filename, ATIS.Sound.N7.duration, self.soundpath ) self.radioqueue:SetDigit( 8, ATIS.Sound.N8.filename, ATIS.Sound.N8.duration, self.soundpath ) self.radioqueue:SetDigit( 9, ATIS.Sound.N9.filename, ATIS.Sound.N9.duration, self.soundpath ) - + -- Start radio queue. self.radioqueue:Start( 1, 0.1 ) end - + -- Handle airbase capture -- Handle events. self:HandleEvent( EVENTS.BaseCaptured ) @@ -1249,8 +1319,10 @@ function ATIS:onafterStatus( From, Event, To ) text = text .. string.format( ", Relay unit=%s (alive=%s)", tostring( self.relayunitname ), relayunitstatus ) end self:T( self.lid .. text ) - - self:__Status( -60 ) + + if not self:Is("Stopped") then + self:__Status( -60 ) + end end ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -1278,9 +1350,11 @@ function ATIS:onafterCheckQueue( From, Event, To ) end end - - -- Check back in 5 seconds. - self:__CheckQueue( -math.abs( self.dTQueueCheck ) ) + + if not self:Is("Stopped") then + -- Check back in 5 seconds. + self:__CheckQueue( -math.abs( self.dTQueueCheck ) ) + end end --- Broadcast ATIS radio message. @@ -1328,6 +1402,9 @@ function ATIS:onafterBroadcast( From, Event, To ) end + local mBarqnh = qnh + local mBarqfe = qfe + -- Convert to inHg. if self.PmmHg then qfe = UTILS.hPa2mmHg( qfe ) @@ -1778,7 +1855,9 @@ function ATIS:onafterBroadcast( From, Event, To ) end end alltext = alltext .. ";\n" .. subtitle - + --self:I("Line 1811") + --self:I(alltext) + -- Visibility if self.metric then subtitle = string.format( "Visibility %s km", VISIBILITY ) @@ -1795,7 +1874,10 @@ function ATIS:onafterBroadcast( From, Event, To ) end end alltext = alltext .. ";\n" .. subtitle - + --self:I("Line 1830") + --self:I(alltext) + + subtitle = "" -- Weather phenomena local wp = false local wpsub = "" @@ -1895,8 +1977,11 @@ function ATIS:onafterBroadcast( From, Event, To ) end end end - alltext = alltext .. ";\n" .. subtitle + --self:I("Line 1932") + alltext = alltext .. ";\n" .. subtitle + --self:I(alltext) + subtitle = "" -- Temperature if self.TDegF then if temperature < 0 then @@ -1924,8 +2009,10 @@ function ATIS:onafterBroadcast( From, Event, To ) self:Transmission( ATIS.Sound.DegreesCelsius, 0.2 ) end end + --self:I("Line 1962") alltext = alltext .. ";\n" .. subtitle - + --self:I(alltext) + -- Dew point if self.TDegF then if dewpoint < 0 then @@ -1953,6 +2040,8 @@ function ATIS:onafterBroadcast( From, Event, To ) self:Transmission( ATIS.Sound.DegreesCelsius, 0.2 ) end end + --self:I("Line 1992") + --self:I(alltext) alltext = alltext .. ";\n" .. subtitle -- Altimeter QNH/QFE. @@ -1977,6 +2066,15 @@ function ATIS:onafterBroadcast( From, Event, To ) end end end + + if self.ReportmBar and not self.metric then + if self.qnhonly then + subtitle = string.format( "%s;\nAltimeter %d hPa", subtitle, mBarqnh ) + else + subtitle = string.format( "%s;\nAltimeter: QNH %d, QFE %d hPa", subtitle, mBarqnh, mBarqfe) + end + end + local _ALTIMETER = subtitle if not self.useSRS then self:Transmission( ATIS.Sound.Altimeter, 1.0, subtitle ) @@ -2009,6 +2107,8 @@ function ATIS:onafterBroadcast( From, Event, To ) end end end + --self:I("Line 2049") + --self:I(alltext) alltext = alltext .. ";\n" .. subtitle -- Active runway. @@ -2136,7 +2236,9 @@ function ATIS:onafterBroadcast( From, Event, To ) end -- ILS + --self:I({ils=self.ils}) local ils=self:GetNavPoint(self.ils, runwayLanding, rwyLandingLeft) + --self:I({ils=ils,runwayLanding=runwayLanding, rwyLandingLeft=rwyLandingLeft}) if ils then subtitle = string.format( "ILS frequency %.2f MHz", ils.frequency ) if not self.useSRS then @@ -2151,6 +2253,7 @@ function ATIS:onafterBroadcast( From, Event, To ) self:Transmission( ATIS.Sound.MegaHertz, 0.2 ) end alltext = alltext .. ";\n" .. subtitle + --self:I(alltext) end -- Outer NDB @@ -2240,7 +2343,12 @@ function ATIS:onafterBroadcast( From, Event, To ) end alltext = alltext .. ";\n" .. subtitle end - + + -- additional info, if any + if self.useSRS and self.AdditionalInformation then + alltext = alltext .. ";\n"..self.AdditionalInformation + end + -- Advice on initial... subtitle = string.format( "Advise on initial contact, you have information %s", NATO ) if not self.useSRS then diff --git a/Moose Development/Moose/Ops/Airboss.lua b/Moose Development/Moose/Ops/Airboss.lua index 85ec855b7..9cebc5e58 100644 --- a/Moose Development/Moose/Ops/Airboss.lua +++ b/Moose Development/Moose/Ops/Airboss.lua @@ -27,17 +27,17 @@ -- **Supported Carriers:** -- -- * [USS John C. Stennis](https://en.wikipedia.org/wiki/USS_John_C._Stennis) (CVN-74) --- * [USS Theodore Roosevelt](https://en.wikipedia.org/wiki/USS_Theodore_Roosevelt_(CVN-71)) (CVN-71) [Super Carrier Module] --- * [USS Abraham Lincoln](https://en.wikipedia.org/wiki/USS_Abraham_Lincoln_(CVN-72)) (CVN-72) [Super Carrier Module] --- * [USS George Washington](https://en.wikipedia.org/wiki/USS_George_Washington_(CVN-73)) (CVN-73) [Super Carrier Module] +-- * [USS Theodore Roosevelt](https://en.wikipedia.org/wiki/USS_Theodore_Roosevelt_(CVN-71\)) (CVN-71) [Super Carrier Module] +-- * [USS Abraham Lincoln](https://en.wikipedia.org/wiki/USS_Abraham_Lincoln_(CVN-72\)) (CVN-72) [Super Carrier Module] +-- * [USS George Washington](https://en.wikipedia.org/wiki/USS_George_Washington_(CVN-73\)) (CVN-73) [Super Carrier Module] -- * [USS Harry S. Truman](https://en.wikipedia.org/wiki/USS_Harry_S._Truman) (CVN-75) [Super Carrier Module] --- * [USS Forrestal](https://en.wikipedia.org/wiki/USS_Forrestal_(CV-59)) (CV-59) [Heatblur Carrier Module] --- * [HMS Hermes](https://en.wikipedia.org/wiki/HMS_Hermes_(R12)) (R12) [**WIP**] --- * [HMS Invincible](https://en.wikipedia.org/wiki/HMS_Invincible_(R05) (R05) [**WIP**] --- * [USS Tarawa](https://en.wikipedia.org/wiki/USS_Tarawa_(LHA-1)) (LHA-1) [**WIP**] --- * [USS America](https://en.wikipedia.org/wiki/USS_America_(LHA-6)) (LHA-6) [**WIP**] +-- * [USS Forrestal](https://en.wikipedia.org/wiki/USS_Forrestal_(CV-59\)) (CV-59) [Heatblur Carrier Module] +-- * [HMS Hermes](https://en.wikipedia.org/wiki/HMS_Hermes_(R12\)) (R12) [**WIP**] +-- * [HMS Invincible](https://en.wikipedia.org/wiki/HMS_Invincible_(R05\)) (R05) [**WIP**] +-- * [USS Tarawa](https://en.wikipedia.org/wiki/USS_Tarawa_(LHA-1\)) (LHA-1) [**WIP**] +-- * [USS America](https://en.wikipedia.org/wiki/USS_America_(LHA-6\)) (LHA-6) [**WIP**] -- * [Juan Carlos I](https://en.wikipedia.org/wiki/Spanish_amphibious_assault_ship_Juan_Carlos_I) (L61) [**WIP**] --- * [HMAS Canberra](https://en.wikipedia.org/wiki/HMAS_Canberra_(L02)) (L02) [**WIP**] +-- * [HMAS Canberra](https://en.wikipedia.org/wiki/HMAS_Canberra_(L02\)) (L02) [**WIP**] -- -- **Supported Aircraft:** -- @@ -117,6 +117,7 @@ -- * [Updated Airboss V/STOL Features USS Tarawa](https://youtu.be/K7I4pU6j718) -- * [Harrier Practice pattern USS America](https://youtu.be/99NigITYmcI) -- * [Harrier CASE III TACAN Approach USS Tarawa](https://www.youtube.com/watch?v=bTgJXZ9Mhdc&t=1s) +-- * [Harrier CASE III TACAN Approach USS Tarawa](https://www.youtube.com/watch?v=wWHag5WpNZ0) -- -- === -- @@ -142,7 +143,7 @@ -- @field Wrapper.Airbase#AIRBASE airbase Carrier airbase object. -- @field #table waypoints Waypoint coordinates of carrier. -- @field #number currentwp Current waypoint, i.e. the one that has been passed last. --- @field Core.Radio#BEACON beacon Carrier beacon for TACAN and ICLS. +-- @field Core.Beacon#BEACON beacon Carrier beacon for TACAN and ICLS. -- @field #boolean TACANon Automatic TACAN is activated. -- @field #number TACANchannel TACAN channel. -- @field #string TACANmode TACAN mode, i.e. "X" or "Y". @@ -296,7 +297,7 @@ -- -- The flight that transitions form the holding pattern to the landing approach, it should leave the Marshal stack at the 3 position and make a left hand turn to the *Initial* -- position, which is 3 NM astern of the boat. Note that you need to be below 1300 feet to be registered in the initial zone. --- The altitude can be set via the function @{AIRBOSS.SetInitialMaxAlt}(*altitude*) function. +-- The altitude can be set via the function @{#AIRBOSS.SetInitialMaxAlt}(*altitude*) function. -- As described below, the initial zone can be smoked or flared via the AIRBOSS F10 Help radio menu. -- -- ### Landing Pattern @@ -761,7 +762,7 @@ -- -- ## Save Results -- --- Saving asset data to file is achieved by the @{AIRBOSS.Save}(*path*, *filename*) function. +-- Saving asset data to file is achieved by the @{#AIRBOSS.Save}(*path*, *filename*) function. -- -- The parameter *path* specifies the path on the file system where the -- player grades are saved. If you do not specify a path, the file is saved your the DCS installation root directory if the **lfs** module is *not* desanizied or @@ -782,7 +783,7 @@ -- -- ### Automatic Saving -- --- The player grades can be saved automatically after each graded player pass via the @{AIRBOSS.SetAutoSave}(*path*, *filename*) function. Again the parameters *path* and *filename* are optional. +-- The player grades can be saved automatically after each graded player pass via the @{#AIRBOSS.SetAutoSave}(*path*, *filename*) function. Again the parameters *path* and *filename* are optional. -- In the simplest case, you desanitize the **lfs** module and just add -- -- airbossStennis:SetAutoSave() @@ -820,7 +821,7 @@ -- -- ## Load Results -- --- Loading player grades from file is achieved by the @{AIRBOSS.Load}(*path*, *filename*) function. The parameter *path* specifies the path on the file system where the +-- Loading player grades from file is achieved by the @{#AIRBOSS.Load}(*path*, *filename*) function. The parameter *path* specifies the path on the file system where the -- data is loaded from. If you do not specify a path, the file is loaded from your the DCS installation root directory or, if **lfs** was desanitized from you "Saved Games\DCS" directory. -- The parameter *filename* is optional and defines the name of the file to load. By default this is automatically generated from the AIBOSS carrier name/alias, for example -- "Airboss-USS Stennis_LSOgrades.csv". @@ -1040,7 +1041,7 @@ -- -- AI groups that enter the CCA are usually guided to Marshal stack. However, due to DCS limitations they might not obey the landing task if they have another airfield as departure and/or destination in -- their mission task. Therefore, AI groups can be respawned when detected in the CCA. This should clear all other airfields and allow the aircraft to land on the carrier. --- This is achieved by the @{AIRBOSS.SetRespawnAI}() function. +-- This is achieved by the @{#AIRBOSS.SetRespawnAI}() function. -- -- ## Known Issues -- @@ -1202,6 +1203,8 @@ AIRBOSS = { NmaxSection = nil, NmaxStack = nil, handleai = nil, + xtVoiceOvers = nil, + xtVoiceOversAI = nil, tanker = nil, Corientation = nil, Corientlast = nil, @@ -1333,6 +1336,7 @@ AIRBOSS.CarrierType = { -- @field #number wire2 Distance in meters from carrier position to second wire. -- @field #number wire3 Distance in meters from carrier position to third wire. -- @field #number wire4 Distance in meters from carrier position to fourth wire. +-- @field #number landingdist Distance in meeters to the landing position. -- @field #number rwylength Length of the landing runway in meters. -- @field #number rwywidth Width of the landing runway in meters. -- @field #number totlength Total length of carrier. @@ -1732,8 +1736,7 @@ AIRBOSS.MenuF10Root = nil --- Airboss class version. -- @field #string version -AIRBOSS.version = "1.2.1" - +AIRBOSS.version = "1.3.0" ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- TODO list ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -1903,6 +1906,12 @@ function AIRBOSS:New( carriername, alias ) -- Set AI handling On. self:SetHandleAION() + -- No extra voiceover/calls from player by default + self:SetExtraVoiceOvers(false) + + -- No extra voiceover/calls from AI by default + self:SetExtraVoiceOversAI(false) + -- Airboss is a nice guy. self:SetAirbossNiceGuy() @@ -1974,7 +1983,8 @@ function AIRBOSS:New( carriername, alias ) -- Init carrier parameters. if self.carriertype == AIRBOSS.CarrierType.STENNIS then - self:_InitStennis() + -- Stennis parameters were updated to match the other Super Carriers. + self:_InitNimitz() elseif self.carriertype == AIRBOSS.CarrierType.ROOSEVELT then self:_InitNimitz() elseif self.carriertype == AIRBOSS.CarrierType.LINCOLN then @@ -1986,7 +1996,7 @@ function AIRBOSS:New( carriername, alias ) elseif self.carriertype == AIRBOSS.CarrierType.FORRESTAL then self:_InitForrestal() elseif self.carriertype == AIRBOSS.CarrierType.VINSON then - -- TODO: Carl Vinson parameters. + -- Carl Vinson is legacy now. self:_InitStennis() elseif self.carriertype == AIRBOSS.CarrierType.HERMES then -- Hermes parameters. @@ -2004,8 +2014,8 @@ function AIRBOSS:New( carriername, alias ) -- Use Juan Carlos parameters. self:_InitJcarlos() elseif self.carriertype == AIRBOSS.CarrierType.CANBERRA then - -- Use Juan Carlos parameters at this stage --TODO Check primary Landing spot. - self:_InitJcarlos() + -- Use Juan Carlos parameters at this stage. + self:_InitCanberra() elseif self.carriertype == AIRBOSS.CarrierType.KUZNETSOV then -- Kusnetsov parameters - maybe... self:_InitStennis() @@ -3234,6 +3244,24 @@ function AIRBOSS:SetHandleAION() return self end +--- Will play the inbound calls, commencing, initial, etc. from the player when requesteing marshal +-- @param #AIRBOSS self +-- @param #AIRBOSS status Boolean to activate (true) / deactivate (false) the radio inbound calls (default is ON) +-- @return #AIRBOSS self +function AIRBOSS:SetExtraVoiceOvers(status) + self.xtVoiceOvers=status + return self +end + +--- Will simulate the inbound call, commencing, initial, etc from the AI when requested by Airboss +-- @param #AIRBOSS self +-- @param #AIRBOSS status Boolean to activate (true) / deactivate (false) the radio inbound calls (default is ON) +-- @return #AIRBOSS self +function AIRBOSS:SetExtraVoiceOversAI(status) + self.xtVoiceOversAI=status + return self +end + --- Do not handle AI aircraft. -- @param #AIRBOSS self -- @return #AIRBOSS self @@ -3340,6 +3368,20 @@ function AIRBOSS:SetDebugModeOFF() return self end + +--- Set FunkMan socket. LSO grades and trap sheets will be send to your Discord bot. +-- **Requires running FunkMan program**. +-- @param #AIRBOSS self +-- @param #number Port Port. Default `10042`. +-- @param #string Host Host. Default `"127.0.0.1"`. +-- @return #AIRBOSS self +function AIRBOSS:SetFunkManOn(Port, Host) + + self.funkmanSocket=SOCKET:New(Port, Host) + + 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. @@ -4251,6 +4293,9 @@ function AIRBOSS:_InitStennis() self.carrierparam.wire3 = 46 + 24 self.carrierparam.wire4 = 46 + 35 -- Last wire is strangely one meter closer. + -- Landing distance. + self.carrierparam.landingdist = self.carrierparam.sterndist+self.carrierparam.wire3 + -- Platform at 5k. Reduce descent rate to 2000 ft/min to 1200 dirty up level flight. self.Platform.name = "Platform 5k" self.Platform.Xmin = -UTILS.NMToMeters( 22 ) -- Not more than 22 NM behind the boat. Last check was at 21 NM. @@ -4401,6 +4446,9 @@ function AIRBOSS:_InitNimitz() self.carrierparam.wire3 = 79 self.carrierparam.wire4 = 92 + -- Landing distance. + self.carrierparam.landingdist = self.carrierparam.sterndist+self.carrierparam.wire3 + end --- Init parameters for Forrestal class super carriers. @@ -4430,6 +4478,9 @@ function AIRBOSS:_InitForrestal() self.carrierparam.wire3 = 64 -- 62 self.carrierparam.wire4 = 74 -- 72.5 + -- Landing distance. + self.carrierparam.landingdist = self.carrierparam.sterndist+self.carrierparam.wire3 + end --- Init parameters for R12 HMS Hermes carrier. @@ -4459,6 +4510,12 @@ function AIRBOSS:_InitHermes() self.carrierparam.wire3 = nil self.carrierparam.wire4 = nil + -- Distance to landing spot. + self.carrierparam.landingspot=69 + + -- Landing distance. + self.carrierparam.landingdist = self.carrierparam.sterndist+self.carrierparam.landingspot + -- Late break. self.BreakLate.name = "Late Break" self.BreakLate.Xmin = -UTILS.NMToMeters( 1 ) -- Not more than 1 NM behind the boat. Last check was at 0. @@ -4499,6 +4556,12 @@ function AIRBOSS:_InitInvincible() self.carrierparam.wire3 = nil self.carrierparam.wire4 = nil + -- Distance to landing spot. + self.carrierparam.landingspot=69 + + -- Landing distance. + self.carrierparam.landingdist = self.carrierparam.sterndist+self.carrierparam.landingspot + -- Late break. self.BreakLate.name = "Late Break" self.BreakLate.Xmin = -UTILS.NMToMeters( 1 ) -- Not more than 1 NM behind the boat. Last check was at 0. @@ -4539,6 +4602,12 @@ function AIRBOSS:_InitTarawa() self.carrierparam.wire3 = nil self.carrierparam.wire4 = nil + -- Distance to landing spot. + self.carrierparam.landingspot=57 + + -- Landing distance. + self.carrierparam.landingdist = self.carrierparam.sterndist+self.carrierparam.landingspot + -- Late break. self.BreakLate.name = "Late Break" self.BreakLate.Xmin = -UTILS.NMToMeters( 1 ) -- Not more than 1 NM behind the boat. Last check was at 0. @@ -4579,6 +4648,12 @@ function AIRBOSS:_InitAmerica() self.carrierparam.wire3 = nil self.carrierparam.wire4 = nil + -- Distance to landing spot. + self.carrierparam.landingspot=59 + + -- Landing distance. + self.carrierparam.landingdist = self.carrierparam.sterndist+self.carrierparam.landingspot + -- Late break. self.BreakLate.name = "Late Break" self.BreakLate.Xmin = -UTILS.NMToMeters( 1 ) -- Not more than 1 NM behind the boat. Last check was at 0. @@ -4619,6 +4694,12 @@ function AIRBOSS:_InitJcarlos() self.carrierparam.wire3 = nil self.carrierparam.wire4 = nil + -- Distance to landing spot. + self.carrierparam.landingspot=89 + + -- Landing distance. + self.carrierparam.landingdist = self.carrierparam.sterndist+self.carrierparam.landingspot + -- Late break. self.BreakLate.name = "Late Break" self.BreakLate.Xmin = -UTILS.NMToMeters( 1 ) -- Not more than 1 NM behind the boat. Last check was at 0. @@ -4631,6 +4712,16 @@ function AIRBOSS:_InitJcarlos() self.BreakLate.LimitZmax = nil end + +--- Init parameters for L02 Canberra carrier. +-- @param #AIRBOSS self +function AIRBOSS:_InitCanberra() + + -- Init Juan Carlos as default. + self:_InitJcarlos() + +end + --- Init parameters for Marshal Voice overs *Gabriella* by HighwaymanEd. -- @param #AIRBOSS self -- @param #string mizfolder (Optional) Folder within miz file where the sound files are located. @@ -5353,16 +5444,12 @@ function AIRBOSS:_GetAircraftParameters( playerData, step ) aoa = aoaac.OnSpeed - if harrier then - -- 0.8 to 1.0 NM - dist = UTILS.NMToMeters( 0.9 ) - else - dist = UTILS.NMToMeters( 1.2 ) - end - if goshawk then -- 0.9 to 1.1 NM per natops ch.4 page 48 dist = UTILS.NMToMeters( 0.9 ) + elseif harrier then + -- 0.8 to 1.0 NM + dist = UTILS.NMToMeters( 0.9 ) else dist = UTILS.NMToMeters( 1.1 ) end @@ -5404,7 +5491,6 @@ function AIRBOSS:_GetAircraftParameters( playerData, step ) alt = UTILS.FeetToMeters( 300 ) -- ? elseif harrier then alt=UTILS.FeetToMeters(312)-- 300-325 ft - end aoa = aoaac.OnSpeed @@ -5622,6 +5708,12 @@ function AIRBOSS:_ClearForLanding( flight ) -- Cleared for Case X recovery. self:_MarshalCallClearedForRecovery( flight.onboard, flight.case ) + -- Voice over of the commencing simulated call from AI + if self.xtVoiceOversAI then + local leader = flight.group:GetUnits()[1] + self:_CommencingCall(leader, flight.onboard) + end + else -- Cleared for Case X recovery. @@ -5721,12 +5813,12 @@ function AIRBOSS:_ScanCarrierZone() if knownflight then -- Check if flight is AI and if we want to handle it at all. - if knownflight.ai and knownflight.flag == -100 and self.handleai then + if knownflight.ai and knownflight.flag == -100 and self.handleai and false then --Disabled AI handling because of incorrect OPSGROUP reference! local putintomarshal = false -- Get flight group. - local flight = _DATABASE:GetFlightGroup( groupname ) + local flight = _DATABASE:GetOpsGroup( groupname ) if flight and flight:IsInbound() and flight.destbase:GetName() == self.carrier:GetName() then if flight.ishelo then @@ -5772,7 +5864,6 @@ function AIRBOSS:_ScanCarrierZone() if not self:_IsHuman( group ) then self:_CreateFlightGroup( group ) end - end end @@ -5986,7 +6077,12 @@ function AIRBOSS:_MarshalAI( flight, nstack, respawn ) end -- Check if flight is already in Marshal queue. - if not self:_InQueue( self.Qmarshal, flight.group ) then + if not self:_InQueue(self.Qmarshal,flight.group) then + -- Simulate inbound call + if self.xtVoiceOversAI then + local leader = flight.group:GetUnits()[1] + self:_MarshallInboundCall(leader, flight.onboard) + end -- Add group to marshal stack queue. self:_AddMarshalGroup( flight, nstack ) end @@ -6068,7 +6164,7 @@ function AIRBOSS:_MarshalAI( flight, nstack, respawn ) local radial = self:GetRadial( case, false, true ) -- Point in the middle of the race track and a 5 NM more port perpendicular. - p0 = p2:Translate( UTILS.NMToMeters( 5 ), radial + 90 ):Translate( UTILS.NMToMeters( 5 ), radial, true ) + p0 = p2:Translate( UTILS.NMToMeters( 5 ), radial + 90, true ):Translate( UTILS.NMToMeters( 5 ), radial, true ) -- Entering Case II/III marshal pattern waypoint. wp[#wp + 1] = p0:WaypointAirTurningPoint( nil, speedTransit, { TaskArrivedHolding }, "Entering Case II/III Marshal Pattern" ) @@ -10129,7 +10225,7 @@ function AIRBOSS:_GetWirePos( Lcoord, dc ) if self.Debug and false then - -- Wire position coodinates. + -- Wire position coordinates. local wp1 = Scoord:Translate( w1, FB ) local wp2 = Scoord:Translate( w2, FB ) local wp3 = Scoord:Translate( w3, FB ) @@ -10854,7 +10950,6 @@ function AIRBOSS:_GetZoneCommence( case, stack ) local Three = self:GetCoordinate():Translate( D, hdg + 275 ) if self.carriertype == AIRBOSS.CarrierType.INVINCIBLE or self.carriertype == AIRBOSS.CarrierType.HERMES or self.carriertype == AIRBOSS.CarrierType.TARAWA or self.carriertype == AIRBOSS.CarrierType.AMERICA or self.carriertype == AIRBOSS.CarrierType.JCARLOS or self.carriertype == AIRBOSS.CarrierType.CANBERRA then - local Dx = UTILS.NMToMeters( 2.25 ) local Dz = UTILS.NMToMeters( 2.25 ) @@ -11152,28 +11247,31 @@ function AIRBOSS:_GetOptLandingCoordinate() -- Start with stern coordiante. self.landingcoord:UpdateFromCoordinate( self:_GetSternCoord() ) - -- Stern coordinate. - -- local stern=self:_GetSternCoord() -- Final bearing. - local FB=self:GetFinalBearing(false) + + -- Cse local case=self.case + -- set Case III V/STOL abeam landing spot over deck -- Pene Testing if self.carriertype==AIRBOSS.CarrierType.INVINCIBLE or self.carriertype==AIRBOSS.CarrierType.HERMES or self.carriertype==AIRBOSS.CarrierType.TARAWA or self.carriertype==AIRBOSS.CarrierType.AMERICA or self.carriertype==AIRBOSS.CarrierType.JCARLOS or self.carriertype==AIRBOSS.CarrierType.CANBERRA then if case==3 then - self.landingcoord:UpdateFromCoordinate(self:_GetLandingSpotCoordinate()) - -- Altitude 120ft -- is this corect for Case III? - self.landingcoord:SetAltitude(UTILS.FeetToMeters(120)) + + -- Landing coordinate. + self.landingcoord:UpdateFromCoordinate(self:_GetLandingSpotCoordinate()) + + -- Altitude 120ft -- is this corect for Case III? + self.landingcoord:SetAltitude(UTILS.FeetToMeters(120)) elseif case==2 or case==1 then - -- Landing 100 ft abeam, 120 ft alt. - self.landingcoord:UpdateFromCoordinate(self:_GetLandingSpotCoordinate()):Translate(35, FB-90, true, true) - --stern=self:_GetLandingSpotCoordinate():Translate(35, FB-90) + -- Landing 100 ft abeam, 120 ft alt. + self.landingcoord:UpdateFromCoordinate(self:_GetLandingSpotCoordinate()):Translate(35, FB-90, true, true) + + -- Alitude 120 ft. + self.landingcoord:SetAltitude(UTILS.FeetToMeters(120)) - -- Atlitude 120 ft. - self.landingcoord:SetAltitude(UTILS.FeetToMeters(120)) end else @@ -11181,8 +11279,7 @@ function AIRBOSS:_GetOptLandingCoordinate() -- Ideally we want to land between 2nd and 3rd wire. if self.carrierparam.wire3 then -- We take the position of the 3rd wire to approximately account for the length of the aircraft. - local w3 = self.carrierparam.wire3 - self.landingcoord:Translate( w3, FB, true, true ) + self.landingcoord:Translate( self.carrierparam.wire3, FB, true, true ) end -- Add 2 meters to account for aircraft height. @@ -11193,61 +11290,19 @@ function AIRBOSS:_GetOptLandingCoordinate() return self.landingcoord end ---- Get landing spot on Tarawa. +--- Get landing spot on Tarawa and others. -- @param #AIRBOSS self -- @return Core.Point#COORDINATE Primary landing spot coordinate. function AIRBOSS:_GetLandingSpotCoordinate() + -- Start at stern coordinate. self.landingspotcoord:UpdateFromCoordinate( self:_GetSternCoord() ) - -- Stern coordinate. - -- local stern=self:_GetSternCoord() + -- Landing 100 ft abeam, 100 alt. + local hdg = self:GetHeading() - if self.carriertype==AIRBOSS.CarrierType.HERMES then - - -- Landing 100 ft abeam, 100 alt. - local hdg = self:GetHeading() - - -- Primary landing spot 5 - self.landingspotcoord:Translate( 69, hdg, true, true ):SetAltitude( self.carrierparam.deckheight ) - elseif self.carriertype == AIRBOSS.CarrierType.INVINCIBLE then - - -- Using spot 3 as the default - local hdg = self:GetHeading() - - self.landingspotcoord:Translate( 69, hdg, true, true ):SetAltitude( self.carrierparam.deckheight ) - -- This location looks good. - elseif self.carriertype == AIRBOSS.CarrierType.TARAWA then - - -- Landing 100 ft abeam, 120 alt. - local hdg = self:GetHeading() - - -- Primary landing spot 7.5 - self.landingspotcoord:Translate( 57, hdg, true, true ):SetAltitude( self.carrierparam.deckheight ) - elseif self.carriertype == AIRBOSS.CarrierType.AMERICA then - - -- Landing 100 ft abeam, 120 alt. - local hdg = self:GetHeading() - - -- Primary landing spot 7.5 a little further forwad on the America - self.landingspotcoord:Translate( 59, hdg, true, true ):SetAltitude( self.carrierparam.deckheight ) - - elseif self.carriertype == AIRBOSS.CarrierType.JCARLOS then - - -- Landing 100 ft abeam, 120 alt. - local hdg = self:GetHeading() - - -- Primary landing spot 5.0 -- Done voice for different landing Spots. - self.landingspotcoord:Translate( 89, hdg, true, true ):SetAltitude( self.carrierparam.deckheight ) - - elseif self.carriertype == AIRBOSS.CarrierType.CANBERRA then - - -- Landing 100 ft abeam, 120 alt. - local hdg = self:GetHeading() - - -- Primary landing spot 5.0 -- Done voice for different landing Spots. - self.landingspotcoord:Translate( 89, hdg, true, true ):SetAltitude( self.carrierparam.deckheight ) - end + -- Primary landing spot. Different carriers handled via carrier parameter landingspot now. + self.landingspotcoord:Translate( self.carrierparam.landingspot, hdg, true, true ):SetAltitude( self.carrierparam.deckheight ) return self.landingspotcoord end @@ -11295,8 +11350,8 @@ function AIRBOSS:GetWind( alt, magnetic, coord ) -- Current position of the carrier or input. local cv = coord or self:GetCoordinate() - -- Wind direction and speed. By default at 15 meters ASL. - local Wdir, Wspeed = cv:GetWind( alt or 15 ) + -- Wind direction and speed. By default at 18 meters ASL. + local Wdir, Wspeed = cv:GetWind( alt or 18 ) -- Include magnetic declination. if magnetic then @@ -11312,7 +11367,7 @@ end --- Get wind speed on carrier deck parallel and perpendicular to runway. -- @param #AIRBOSS self --- @param #number alt Altitude in meters. Default 15 m. (change made from 50m from Discord discussion from Sickdog) +-- @param #number alt Altitude in meters. Default 18 m. -- @return #number Wind component parallel to runway im m/s. -- @return #number Wind component perpendicular to runway in m/s. -- @return #number Total wind strength in m/s. @@ -11335,7 +11390,7 @@ function AIRBOSS:GetWindOnDeck( alt ) zc = UTILS.Rotate2D( zc, -self.carrierparam.rwyangle ) -- Wind (from) vector - local vw = cv:GetWindWithTurbulenceVec3( alt or 15 ) + local vw = cv:GetWindWithTurbulenceVec3( alt or 18 ) --(change made from 50m to 15m from Discord discussion from Sickdog, next change to 18m due to SC higher deck discord) -- Total wind velocity vector. -- Carrier velocity has to be negative. If carrier drives in the direction the wind is blowing from, we have less wind in total. @@ -11358,7 +11413,7 @@ end --- Get true (or magnetic) heading of carrier into the wind. This accounts for the angled runway. -- @param #AIRBOSS self -- @param #boolean magnetic If true, calculate magnetic heading. By default true heading is returned. --- @param Core.Point#COORDINATE coord (Optional) Coodinate from which heading is calculated. Default is current carrier position. +-- @param Core.Point#COORDINATE coord (Optional) Coordinate from which heading is calculated. Default is current carrier position. -- @return #number Carrier heading in degrees. function AIRBOSS:GetHeadingIntoWind( magnetic, coord ) @@ -11821,7 +11876,7 @@ function AIRBOSS:_LSOgrade( playerData ) local grade local points - if N == 0 and (TgrooveUnicorn or TgrooveVstolUnicorn) then + if N == 0 and (TgrooveUnicorn or TgrooveVstolUnicorn or playerData.case==3) then -- No deviations, should be REALLY RARE! grade = "_OK_" points = 5.0 @@ -12820,19 +12875,23 @@ function AIRBOSS:_Debrief( playerData ) end mygrade.case = playerData.case local windondeck = self:GetWindOnDeck() - mygrade.wind = tostring( UTILS.Round( UTILS.MpsToKnots( windondeck ), 1 ) ) + mygrade.wind = UTILS.Round( UTILS.MpsToKnots( windondeck ), 1 ) mygrade.modex = playerData.onboard mygrade.airframe = playerData.actype mygrade.carriertype = self.carriertype mygrade.carriername = self.alias + mygrade.carrierrwy = self.carrierparam.rwyangle mygrade.theatre = self.theatre - mygrade.mitime = UTILS.SecondsToClock( timer.getAbsTime() ) + mygrade.mitime = UTILS.SecondsToClock( timer.getAbsTime(), true ) mygrade.midate = UTILS.GetDCSMissionDate() mygrade.osdate = "n/a" if os then mygrade.osdate = os.date() -- os.date("%d.%m.%Y") end + -- Add last grade to playerdata for FunkMan. + playerData.grade=mygrade + -- Save trap sheet. if playerData.trapon and self.trapsheet then self:_SaveTrapSheet( playerData, mygrade ) @@ -15143,6 +15202,86 @@ function AIRBOSS:_Number2Radio( radio, number, delay, interval, pilotcall ) return wait end +--- Aircraft request marshal (Inbound call both for players and AI). +-- @param #AIRBOSS self +-- @return Wrapper.Unit#UNIT Unit of player or nil. +-- @param #string modex Tail number. +function AIRBOSS:_MarshallInboundCall(unit, modex) + + -- Calculate + local vectorCarrier = self:GetCoordinate():GetDirectionVec3(unit:GetCoordinate()) + local bearing = UTILS.Round(unit:GetCoordinate():GetAngleDegrees( vectorCarrier ), 0) + local distance = UTILS.Round(UTILS.MetersToNM(unit:GetCoordinate():Get2DDistance(self:GetCoordinate())),0) + local angels = UTILS.Round(UTILS.MetersToFeet(unit:GetHeight()/1000),0) + local state = UTILS.Round(self:_GetFuelState(unit)/1000,1) + + -- Pilot: "Marshall, [modex], marking mom's [bearing] for [distance], angels [XX], state [X.X]" + local text=string.format("Marshal, %s, marking mom's %d for %d, angels %d, state %.1f", modex, bearing, distance, angels, state) + -- Debug message. + self:T(self.lid..text) + + -- Fuel state. + local FS=UTILS.Split(string.format("%.1f", state), ".") + + -- Create new call to display complete subtitle. + local inboundcall=self:_NewRadioCall(self.MarshalCall.CLICK, unit.UnitName:upper() , text, self.Tmessage, nil, unit.UnitName:upper()) + + -- CLICK! + self:RadioTransmission(self.MarshalRadio, inboundcall) + -- Marshal .. + self:RadioTransmission(self.MarshalRadio, self.PilotCall.MARSHAL, nil, nil, nil, nil, true) + -- Modex.. + self:_Number2Radio(self.MarshalRadio, modex, nil, nil, true) + -- Marking Mom's, + self:RadioTransmission(self.MarshalRadio, self.PilotCall.MARKINGMOMS, nil, nil, nil, nil, true) + -- Bearing .. + self:_Number2Radio(self.MarshalRadio, tostring(bearing), nil, nil, true) + -- For .. + self:RadioTransmission(self.MarshalRadio, self.PilotCall.FOR, nil, nil, nil, nil, true) + -- Distance .. + self:_Number2Radio(self.MarshalRadio, tostring(distance), nil, nil, true) + -- Angels .. + self:RadioTransmission(self.MarshalRadio, self.PilotCall.ANGELS, nil, nil, nil, nil, true) + -- Angels Number .. + self:_Number2Radio(self.MarshalRadio, tostring(angels), nil, nil, true) + -- State .. + self:RadioTransmission(self.MarshalRadio, self.PilotCall.STATE, nil, nil, nil, nil, true) + -- X.. + self:_Number2Radio(self.MarshalRadio, FS[1], nil, nil, true) + -- Point.. + self:RadioTransmission(self.MarshalRadio, self.PilotCall.POINT, nil, nil, nil, nil, true) + -- Y. + self:_Number2Radio(self.MarshalRadio, FS[2], nil, nil, true) + -- CLICK! + self:RadioTransmission(self.MarshalRadio, self.MarshalRadio.CLICK, nil, nil, nil, nil, true) + +end + +--- Aircraft commencing call (both for players and AI). +-- @param #AIRBOSS self +-- @return Wrapper.Unit#UNIT Unit of player or nil. +-- @param #string modex Tail number. +function AIRBOSS:_CommencingCall(unit, modex) + + -- Pilot: "[modex], commencing" + local text=string.format("%s, commencing", modex) + -- Debug message. + self:T(self.lid..text) + + -- Create new call to display complete subtitle. + local commencingCall=self:_NewRadioCall(self.MarshalCall.CLICK, unit.UnitName:upper() , text, self.Tmessage, nil, unit.UnitName:upper()) + + -- Click + self:RadioTransmission(self.MarshalRadio, commencingCall) + -- Modex.. + self:_Number2Radio(self.MarshalRadio, modex, nil, nil, true) + -- Commencing + self:RadioTransmission(self.MarshalRadio, self.PilotCall.COMMENCING, nil, nil, nil, nil, true) + -- CLICK! + self:RadioTransmission(self.MarshalRadio, self.MarshalRadio.CLICK, nil, nil, nil, nil, true) + +end + --- AI aircraft calls the ball. -- @param #AIRBOSS self -- @param #string modex Tail number. @@ -15192,6 +15331,7 @@ function AIRBOSS:_MarshalCallGasAtTanker( modex ) -- Debug message. self:I( self.lid .. text ) + -- Create new call to display complete subtitle. local call = self:_NewRadioCall( self.PilotCall.BINGOFUEL, modex, text, self.Tmessage, nil, modex ) @@ -15898,6 +16038,11 @@ function AIRBOSS:_RequestMarshal( _unitName ) if playerData then + -- Voice over of inbound call (regardless of airboss rejecting it or not) + if self.xtVoiceOvers then + self:_MarshallInboundCall(_unit, playerData.onboard) + end + -- Check if player is in CCA local inCCA = playerData.unit:IsInZone( self.zoneCCA ) @@ -16145,7 +16290,12 @@ function AIRBOSS:_RequestCommence( _unitName ) local playerData = self.players[_playername] -- #AIRBOSS.PlayerData if playerData then - + + -- Voice over of Commencing call (regardless of Airboss will rejected or not) + if self.xtVoiceOvers then + self:_CommencingCall(_unit, playerData.onboard) + end + -- Check if unit is in CCA. local text = "" local cleared = false @@ -17857,6 +18007,59 @@ function AIRBOSS:onafterLoad( From, Event, To, path, filename ) end +--- On after "LSOGrade" event. +-- @param #AIRBOSS self +-- @param #string From From state. +-- @param #string Event Event. +-- @param #string To To state. +-- @param #AIRBOSS.PlayerData playerData Player Data. +-- @param #AIRBOSS.LSOgrade grade LSO grade. +function AIRBOSS:onafterLSOGrade(From, Event, To, playerData, grade) + + if self.funkmanSocket then + + -- Extract used info for FunkMan. We need to be careful with the amount of data send via UDP socket. + local trapsheet={} ; trapsheet.X={} ; trapsheet.Z={} ; trapsheet.AoA={} ; trapsheet.Alt={} + + -- Loop over trapsheet and extract used values. + for i = 1, #playerData.trapsheet do + local ts=playerData.trapsheet[i] --#AIRBOSS.GrooveData + table.insert(trapsheet.X, UTILS.Round(ts.X, 1)) + table.insert(trapsheet.Z, UTILS.Round(ts.Z, 1)) + table.insert(trapsheet.AoA, UTILS.Round(ts.AoA, 2)) + table.insert(trapsheet.Alt, UTILS.Round(ts.Alt, 1)) + end + + local result={} + result.command=SOCKET.DataType.LSOGRADE + result.name=playerData.name + result.trapsheet=trapsheet + result.airframe=grade.airframe + result.mitime=grade.mitime + result.midate=grade.midate + result.wind=grade.wind + result.carriertype=grade.carriertype + result.carriername=grade.carriername + result.carrierrwy=grade.carrierrwy + result.landingdist=self.carrierparam.landingdist + result.theatre=grade.theatre + result.case=playerData.case + result.Tgroove=grade.Tgroove + result.wire=grade.wire + result.grade=grade.grade + result.points=grade.points + result.details=grade.details + + -- Debug info. + self:T(self.lid.."Result onafterLSOGrade") + self:T(result) + + -- Send result. + self.funkmanSocket:SendTable(result) + end + +end + ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ diff --git a/Moose Development/Moose/Ops/CSAR.lua b/Moose Development/Moose/Ops/CSAR.lua index 35fd9794e..da3853223 100644 --- a/Moose Development/Moose/Ops/CSAR.lua +++ b/Moose Development/Moose/Ops/CSAR.lua @@ -1,4 +1,4 @@ ---- **Ops** -- Combat Search and Rescue. +--- **Ops** - Combat Search and Rescue. -- -- === -- @@ -30,7 +30,7 @@ -- @module Ops.CSAR -- @image OPS_CSAR.jpg --- Date: June 2022 +-- Date: November 2022 ------------------------------------------------------------------------- --- **CSAR** class, extends Core.Base#BASE, Core.Fsm#FSM @@ -114,6 +114,7 @@ -- mycsar.countryneutral = country.id.UN_PEACEKEEPERS -- mycsar.topmenuname = "CSAR" -- set the menu entry name -- mycsar.ADFRadioPwr = 1000 -- ADF Beacons sending with 1KW as default +-- mycsar.PilotWeight = 80 -- Loaded pilots weigh 80kgs each -- -- ## 2.1 Experimental Features -- @@ -233,6 +234,7 @@ CSAR = { allheligroupset = nil, topmenuname = "CSAR", ADFRadioPwr = 1000, + PilotWeight = 80, } --- Downed pilots info. @@ -270,7 +272,7 @@ CSAR.AircraftType["Bronco-OV-10A"] = 2 --- CSAR class version. -- @field #string version -CSAR.version="1.0.11" +CSAR.version="1.0.16" ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- ToDo list @@ -278,7 +280,7 @@ CSAR.version="1.0.11" -- DONE: SRS Integration (to be tested) -- TODO: Maybe - add option to smoke/flare closest MASH --- TODO: shagrat Add cargoWeight to helicopter when pilot boarded +-- DONE: shagrat Add cargoWeight to helicopter when pilot boarded ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- Constructor ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -418,10 +420,13 @@ function CSAR:New(Coalition, Template, Alias) self.wetfeettemplate = nil self.usewetfeet = false - -- added 0.1.8 + -- added 1.0.15 self.allowbronco = false -- set to true to use the Bronco mod as a CSAR plane self.ADFRadioPwr = 1000 + + -- added 1.0.16 + self.PilotWeight = 80 -- WARNING - here\'ll be dragons -- for this to work you need to de-sanitize your mission environment in \Scripts\MissionScripting.lua @@ -613,6 +618,19 @@ function CSAR:_DoubleEjection(_unitname) return false end +--- (User) Add a PLAYERTASK - FSM events will check success +-- @param #CSAR self +-- @param Ops.PlayerTask#PLAYERTASK PlayerTask +-- @return #CSAR self +function CSAR:AddPlayerTask(PlayerTask) + self:T(self.lid .. " AddPlayerTask") + if not self.PlayerTaskQueue then + self.PlayerTaskQueue = FIFO:New() + end + self.PlayerTaskQueue:Push(PlayerTask,PlayerTask.PlayerTaskNr) + return self +end + --- (Internal) Spawn a downed pilot -- @param #CSAR self -- @param #number country Country for template. @@ -1197,6 +1215,38 @@ function CSAR:_RemoveNameFromDownedPilots(name,force) return found end +--- [User] Set callsign options for TTS output. See @{Wrapper.Group#GROUP.GetCustomCallSign}() on how to set customized callsigns. +-- @param #CSAR self +-- @param #boolean ShortCallsign If true, only call out the major flight number +-- @param #boolean Keepnumber If true, keep the **customized callsign** in the #GROUP name for players as-is, no amendments or numbers. +-- @param #table CallsignTranslations (optional) Table to translate between DCS standard callsigns and bespoke ones. Does not apply if using customized +-- callsigns from playername or group name. +-- @return #CSAR self +function CSAR:SetCallSignOptions(ShortCallsign,Keepnumber,CallsignTranslations) + if not ShortCallsign or ShortCallsign == false then + self.ShortCallsign = false + else + self.ShortCallsign = true + end + self.Keepnumber = Keepnumber or false + self.CallsignTranslations = CallsignTranslations + return self +end + +--- (Internal) Check if a name is in downed pilot table and remove it. +-- @param #CSAR self +-- @param #string UnitName +-- @return #string CallSign +function CSAR:_GetCustomCallSign(UnitName) + local callsign = Unitname + local unit = UNIT:FindByName(UnitName) + if unit and unit:IsAlive() then + local group = unit:GetGroup() + callsign = group:GetCustomCallSign(self.ShortCallsign,self.Keepnumber,self.CallsignTranslations) + end + return callsign +end + --- (Internal) Check state of wounded group. -- @param #CSAR self -- @param #string heliname heliname @@ -1253,9 +1303,9 @@ function CSAR:_CheckWoundedGroupStatus(heliname,woundedgroupname) local dist = UTILS.MetersToNM(self.autosmokedistance) disttext = string.format("%.0fnm",dist) end - self:_DisplayMessageToSAR(_heliUnit, string.format("%s: %s. I hear you! Finally, that is music in my ears!\nI'll pop a smoke when you are %s away.\nLand or hover by the smoke.", _heliName, _pilotName, disttext), self.messageTime,false,true) + self:_DisplayMessageToSAR(_heliUnit, string.format("%s: %s. I hear you! Finally, that is music in my ears!\nI'll pop a smoke when you are %s away.\nLand or hover by the smoke.", self:_GetCustomCallSign(_heliName), _pilotName, disttext), self.messageTime,false,true) else - self:_DisplayMessageToSAR(_heliUnit, string.format("%s: %s. I hear you! Finally, that is music in my ears!\nRequest a flare or smoke if you need.", _heliName, _pilotName), self.messageTime,false,true) + self:_DisplayMessageToSAR(_heliUnit, string.format("%s: %s. I hear you! Finally, that is music in my ears!\nRequest a flare or smoke if you need.", self:_GetCustomCallSign(_heliName), _pilotName), self.messageTime,false,true) end --mark as shown for THIS heli and THIS group self.heliVisibleMessage[_lookupKeyHeli] = true @@ -1319,7 +1369,7 @@ function CSAR:_PickupUnit(_heliUnit, _pilotName, _woundedGroup, _woundedGroupNam _maxUnits = self.max_units end if _unitsInHelicopter + 1 > _maxUnits then - self:_DisplayMessageToSAR(_heliUnit, string.format("%s, %s. We\'re already crammed with %d guys! Sorry!", _pilotName, _heliName, _unitsInHelicopter, _unitsInHelicopter), self.messageTime,false,false,true) + self:_DisplayMessageToSAR(_heliUnit, string.format("%s, %s. We\'re already crammed with %d guys! Sorry!", _pilotName, self:_GetCustomCallSign(_heliName), _unitsInHelicopter, _unitsInHelicopter), self.messageTime,false,false,true) return self end @@ -1337,13 +1387,29 @@ function CSAR:_PickupUnit(_heliUnit, _pilotName, _woundedGroup, _woundedGroupNam _woundedGroup:Destroy(false) self:_RemoveNameFromDownedPilots(_woundedGroupName,true) - self:_DisplayMessageToSAR(_heliUnit, string.format("%s: %s I\'m in! Get to the MASH ASAP! ", _heliName, _pilotName), self.messageTime,true,true) + self:_DisplayMessageToSAR(_heliUnit, string.format("%s: %s I\'m in! Get to the MASH ASAP! ", self:_GetCustomCallSign(_heliName), _pilotName), self.messageTime,true,true) + + self:_UpdateUnitCargoMass(_heliName) self:__Boarded(5,_heliName,_woundedGroupName,grouptable.desc) return self end +--- (Internal) Function to calculate and set Unit internal cargo mass +-- @param #CSAR self +-- @param #string _heliName Unit name +-- @return #CSAR self +function CSAR:_UpdateUnitCargoMass(_heliName) + self:T(self.lid .. " _UpdateUnitCargoMass") + local calculatedMass = self:_PilotsOnboard(_heliName)*(self.PilotWeight or 80) + local Unit = UNIT:FindByName(_heliName) + if Unit then + Unit:SetUnitInternalCargo(calculatedMass) + end + return self +end + --- (Internal) Move group to destination. -- @param #CSAR self -- @param Wrapper.Group#GROUP _leader @@ -1358,7 +1424,6 @@ function CSAR:_OrderGroupToMoveToPoint(_leader, _destination) return self end - --- (internal) Function to check if the heli door(s) are open. Thanks to Shadowze. -- @param #CSAR self -- @param #string unit_name Name of unit. @@ -1392,9 +1457,9 @@ function CSAR:_CheckCloseWoundedGroup(_distance, _heliUnit, _heliName, _woundedG if self.heliCloseMessage[_lookupKeyHeli] == nil then if self.autosmoke == true then - self:_DisplayMessageToSAR(_heliUnit, string.format("%s: %s. You\'re close now! Land or hover at the smoke.", _heliName, _pilotName), self.messageTime,false,true) + self:_DisplayMessageToSAR(_heliUnit, string.format("%s: %s. You\'re close now! Land or hover at the smoke.", self:_GetCustomCallSign(_heliName), _pilotName), self.messageTime,false,true) else - self:_DisplayMessageToSAR(_heliUnit, string.format("%s: %s. You\'re close now! Land in a safe place, I will go there ", _heliName, _pilotName), self.messageTime,false,true) + self:_DisplayMessageToSAR(_heliUnit, string.format("%s: %s. You\'re close now! Land in a safe place, I will go there ", self:_GetCustomCallSign(_heliName), _pilotName), self.messageTime,false,true) end self.heliCloseMessage[_lookupKeyHeli] = true end @@ -1447,7 +1512,7 @@ function CSAR:_CheckCloseWoundedGroup(_distance, _heliUnit, _heliName, _woundedG end if _heliUnit:InAir() and _unitsInHelicopter + 1 <= _maxUnits then - -- TODO - make variable + -- DONE - make variable if _distance < self.rescuehoverdistance then --check height! @@ -1455,7 +1520,7 @@ function CSAR:_CheckCloseWoundedGroup(_distance, _heliUnit, _heliName, _woundedG if leaderheight < 0 then leaderheight = 0 end local _height = _heliUnit:GetHeight() - leaderheight - -- TODO - make variable + -- DONE - make variable if _height <= self.rescuehoverheight then local _time = self.hoverStatus[_lookupKeyHeli] @@ -1561,9 +1626,12 @@ function CSAR:_RescuePilots(_heliUnit) self.inTransitGroups[_heliName] = nil - local _txt = string.format("%s: The %d pilot(s) have been taken to the\nmedical clinic. Good job!", _heliName, PilotsSaved) + local _txt = string.format("%s: The %d pilot(s) have been taken to the\nmedical clinic. Good job!", self:_GetCustomCallSign(_heliName), PilotsSaved) self:_DisplayMessageToSAR(_heliUnit, _txt, self.messageTime) + + self:_UpdateUnitCargoMass(_heliName) + -- trigger event self:__Rescued(-1,_heliUnit,_heliName, PilotsSaved) return self @@ -1597,7 +1665,7 @@ function CSAR:_DisplayMessageToSAR(_unit, _text, _time, _clear, _speak, _overrid local _clear = _clear or nil local _time = _time or self.messageTime if _override or not self.suppressmessages then - local m = MESSAGE:New(_text,_time,"Info",_clear):ToGroup(group) + local m = MESSAGE:New(_text,_time,"CSAR",_clear):ToGroup(group) end -- integrate SRS if _speak and self.useSRS then @@ -1746,7 +1814,7 @@ function CSAR:_SignalFlare(_unitName) else _distance = string.format("%.1fkm",_closest.distance) end - local _msg = string.format("%s - Popping signal flare at your %s o\'clock. Distance %s", _unitName, _clockDir, _distance) + local _msg = string.format("%s - Popping signal flare at your %s o\'clock. Distance %s", self:_GetCustomCallSign(_unitName), _clockDir, _distance) self:_DisplayMessageToSAR(_heli, _msg, self.messageTime, false, true, true) local _coord = _closest.pilot:GetCoordinate() @@ -1800,7 +1868,7 @@ function CSAR:_Reqsmoke( _unitName ) else _distance = string.format("%.1fkm",_closest.distance/1000) end - local _msg = string.format("%s - Popping smoke at your %s o\'clock. Distance %s", _unitName, _clockDir, _distance) + local _msg = string.format("%s - Popping smoke at your %s o\'clock. Distance %s", self:_GetCustomCallSign(_unitName), _clockDir, _distance) self:_DisplayMessageToSAR(_heli, _msg, self.messageTime, false, true, true) local _coord = _closest.pilot:GetCoordinate() local color = self.smokecolor @@ -1851,7 +1919,7 @@ function CSAR:_GetClosestMASH(_heli) if self.allowFARPRescue then local position = _heli:GetCoordinate() - local afb,distance = position:GetClosestAirbase2(nil,self.coalition) + local afb,distance = position:GetClosestAirbase(nil,self.coalition) _shortestDistance = distance end @@ -2004,13 +2072,17 @@ function CSAR:_GetClockDirection(_heli, _group) local DirectionVec3 = _playerPosition:GetDirectionVec3( _targetpostions ) local Angle = _playerPosition:GetAngleDegrees( DirectionVec3 ) self:T(self.lid .. " _GetClockDirection"..tostring(Angle).." "..tostring(_heading)) - local clock = 12 - if _heading then - local Aspect = Angle - _heading - if Aspect == 0 then Aspect = 360 end - clock = math.abs(UTILS.Round((Aspect / 30),0)) - if clock == 0 then clock = 12 end - end + local hours = 0 + local clock = 12 + if _heading and Angle then + clock = 12 + --if angle == 0 then angle = 360 end + clock = _heading-Angle + hours = (clock/30)*-1 + clock = 12+hours + clock = UTILS.Round(clock,0) + if clock > 12 then clock = clock-12 end + end return clock end @@ -2282,6 +2354,29 @@ end function CSAR:onbeforeBoarded(From, Event, To, Heliname, Woundedgroupname) self:T({From, Event, To, Heliname, Woundedgroupname}) self:_ScheduledSARFlight(Heliname,Woundedgroupname) + local Unit = UNIT:FindByName(Heliname) + if Unit and Unit:IsPlayer() and self.PlayerTaskQueue then + local playername = Unit:GetPlayerName() + local dropcoord = Unit:GetCoordinate() or COORDINATE:New(0,0,0) + local dropvec2 = dropcoord:GetVec2() + self.PlayerTaskQueue:ForEach( + function (Task) + local task = Task -- Ops.PlayerTask#PLAYERTASK + local subtype = task:GetSubType() + -- right subtype? + if Event == subtype and not task:IsDone() then + local targetzone = task.Target:GetObject() -- Core.Zone#ZONE should be a zone in this case .... + if (targetzone and targetzone.ClassName and string.match(targetzone.ClassName,"ZONE") and targetzone:IsVec2InZone(dropvec2)) + or (string.find(task.CSARPilotName,Woundedgroupname)) then + if task.Clients:HasUniqueID(playername) then + -- success + task:__Success(-1) + end + end + end + end + ) + end return self end @@ -2311,6 +2406,23 @@ function CSAR:onbeforeRescued(From, Event, To, HeliUnit, HeliName, PilotsSaved) self:T({From, Event, To, HeliName, HeliUnit}) self.rescues = self.rescues + 1 self.rescuedpilots = self.rescuedpilots + PilotsSaved + local Unit = HeliUnit or UNIT:FindByName(HeliName) + if Unit and Unit:IsPlayer() and self.PlayerTaskQueue then + local playername = Unit:GetPlayerName() + self.PlayerTaskQueue:ForEach( + function (Task) + local task = Task -- Ops.PlayerTask#PLAYERTASK + local subtype = task:GetSubType() + -- right subtype? + if Event == subtype and not task:IsDone() then + if task.Clients:HasUniqueID(playername) then + -- success + task:__Success(-1) + end + end + end + ) + end return self end diff --git a/Moose Development/Moose/Ops/CTLD.lua b/Moose Development/Moose/Ops/CTLD.lua index 6ec93761c..0a7c38665 100644 --- a/Moose Development/Moose/Ops/CTLD.lua +++ b/Moose Development/Moose/Ops/CTLD.lua @@ -1,4 +1,4 @@ ---- **Ops** -- Combat Troops & Logistics Department. +--- **Ops** - Combat Troops & Logistics Department. -- -- === -- @@ -22,8 +22,7 @@ -- @module Ops.CTLD -- @image OPS_CTLD.jpg --- Date: Feb 2022 --- Last Update Sep 2022 +-- Last Update October 2022 do @@ -288,8 +287,8 @@ CTLD_ENGINEERING = { end -do - + +do ------------------------------------------------------ --- **CTLD_CARGO** class, extends Core.Base#BASE -- @type CTLD_CARGO @@ -308,9 +307,8 @@ do -- @field #string Subcategory Sub-category name. -- @extends Core.Base#BASE - --- --- @field CTLD_CARGO +-- @field #CTLD_CARGO CTLD_CARGO CTLD_CARGO = { ClassName = "CTLD_CARGO", ID = 0, @@ -343,7 +341,7 @@ CTLD_CARGO = { CRATE = "Crate", -- #string crate REPAIR = "Repair", -- #string repair ENGINEERS = "Engineers", -- #string engineers - STATIC = "Static", -- #string engineers + STATIC = "Static", -- #string statics } --- Function to create new CTLD_CARGO object. @@ -574,6 +572,10 @@ CTLD_CARGO = { end do +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +-- TODO CTLD +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + ------------------------------------------------------------------------- --- **CTLD** class, extends Core.Base#BASE, Core.Fsm#FSM -- @type CTLD @@ -581,6 +583,7 @@ do -- @field #number verbose Verbosity level. -- @field #string lid Class id string for output to DCS log file. -- @field #number coalition Coalition side number, e.g. `coalition.side.RED`. +-- @field #boolean debug -- @extends Core.Fsm#FSM --- *Combat Troop & Logistics Deployment (CTLD): Everyone wants to be a POG, until there\'s POG stuff to be done.* (Mil Saying) @@ -697,6 +700,7 @@ do -- my_ctld.smokedistance = 2000 -- Only smoke or flare zones if requesting player unit is this far away (in meters) -- my_ctld.suppressmessages = false -- Set to true if you want to script your own messages. -- my_ctld.repairtime = 300 -- Number of seconds it takes to repair a unit. +-- my_ctld.buildtime = 300 -- Number of seconds it takes to build a unit. Set to zero or nil to build instantly. -- my_ctld.cratecountry = country.id.GERMANY -- ID of crates. Will default to country.id.RUSSIA for RED coalition setups. -- my_ctld.allowcratepickupagain = true -- allow re-pickup crates that were dropped. -- my_ctld.enableslingload = false -- allow cargos to be slingloaded - might not work for all cargo types @@ -706,6 +710,7 @@ do -- my_ctld.basetype = "container_cargo" -- default shape of the cargo container -- my_ctld.droppedbeacontimeout = 600 -- dropped beacon lasts 10 minutes -- my_ctld.usesubcats = false -- use sub-category names for crates, adds an extra menu layer in "Get Crates", useful if you have > 10 crate types. +-- my_ctld.placeCratesAhead = false -- place crates straight ahead of the helicopter, in a random way. If true, crates are more neatly sorted. -- -- ## 2.1 User functions -- @@ -824,6 +829,8 @@ do -- -- To award player with points, using the SCORING Class (SCORING: my_Scoring, CTLD: CTLD_Cargotransport) -- +-- my_scoring = SCORING:New("Combat Transport") +-- -- function CTLD_Cargotransport:OnAfterCratesDropped(From, Event, To, Group, Unit, Cargotable) -- local points = 10 -- if Unit then @@ -901,7 +908,7 @@ do -- -- my_ctld.useprefix = true -- this is true by default and MUST BE ON. -- --- ### 5.2 Integrate Hercules ground crew (F8 Menu) loadable objects (alternative method) +-- ### 5.2 Integrate Hercules ground crew (F8 Menu) loadable objects (alternative method, use either the above OR this method, NOT both!) -- -- Integrate to your CTLD instance like so, where `my_ctld` is a previously created CTLD instance: -- @@ -928,6 +935,8 @@ do -- The script works on the EVENTS.Shot trigger, which is used by the mod when you **drop cargo from the Hercules while flying**. Unloading on the ground does -- not achieve anything here. If you just want to unload on the ground, use the normal Moose CTLD (see 5.1). -- +-- DO NOT use the "splash damage" script together with this method! Your cargo will explode on the ground! +-- -- There are two ways of airdropping: -- -- 1) Very low and very slow (>5m and <10m AGL) - here you can drop stuff which has "Skid" at the end of the cargo name (loaded via F8 Ground Crew menu) @@ -1064,11 +1073,12 @@ CTLD.UnitTypes = { --Actually it's longer, but the center coord is off-center of the model. ["UH-60L"] = {type="UH-60L", crates=true, troops=true, cratelimit = 2, trooplimit = 20, length = 16, cargoweightlimit = 3500}, -- 4t cargo, 20 (unsec) seats ["AH-64D_BLK_II"] = {type="AH-64D_BLK_II", crates=false, troops=true, cratelimit = 0, trooplimit = 2, length = 17, cargoweightlimit = 200}, -- 2 ppl **outside** the helo + ["Bronco-OV-10A"] = {type="Bronco-OV-10A", crates= false, troops=true, cratelimit = 0, trooplimit = 5, length = 13, cargoweightlimit = 1450}, } --- CTLD class version. -- @field #string version -CTLD.version="1.0.11" +CTLD.version="1.0.19" --- Instantiate a new CTLD. -- @param #CTLD self @@ -1206,8 +1216,9 @@ function CTLD:New(Coalition, Prefixes, Alias) -- message suppression self.suppressmessages = false - -- time to repair a unit/group + -- time to repairor build a unit/group self.repairtime = 300 + self.buildtime = 300 -- place spawned crates in front of aircraft self.placeCratesAhead = false @@ -1302,6 +1313,92 @@ function CTLD:New(Coalition, Prefixes, Alias) -- @param #CTLD self -- @param #number delay Delay in seconds. + --- FSM Function OnBeforeTroopsPickedUp. + -- @function [parent=#CTLD] OnBeforeTroopsPickedUp + -- @param #CTLD self + -- @param #string From State. + -- @param #string Event Trigger. + -- @param #string To State. + -- @param Wrapper.Group#GROUP Group Group Object. + -- @param Wrapper.Unit#UNIT Unit Unit Object. + -- @param #CTLD_CARGO Cargo Cargo troops. + -- @return #CTLD self + + --- FSM Function OnBeforeTroopsExtracted. + -- @function [parent=#CTLD] OnBeforeTroopsExtracted + -- @param #CTLD self + -- @param #string From State. + -- @param #string Event Trigger. + -- @param #string To State. + -- @param Wrapper.Group#GROUP Group Group Object. + -- @param Wrapper.Unit#UNIT Unit Unit Object. + -- @param #CTLD_CARGO Cargo Cargo troops. + -- @return #CTLD self + + --- FSM Function OnBeforeCratesPickedUp. + -- @function [parent=#CTLD] OnBeforeCratesPickedUp + -- @param #CTLD self + -- @param #string From State . + -- @param #string Event Trigger. + -- @param #string To State. + -- @param Wrapper.Group#GROUP Group Group Object. + -- @param Wrapper.Unit#UNIT Unit Unit Object. + -- @param #CTLD_CARGO Cargo Cargo crate. + -- @return #CTLD self + + --- FSM Function OnBeforeTroopsDeployed. + -- @function [parent=#CTLD] OnBeforeTroopsDeployed + -- @param #CTLD self + -- @param #string From State. + -- @param #string Event Trigger. + -- @param #string To State. + -- @param Wrapper.Group#GROUP Group Group Object. + -- @param Wrapper.Unit#UNIT Unit Unit Object. + -- @param Wrapper.Group#GROUP Troops Troops #GROUP Object. + -- @return #CTLD self + + --- FSM Function OnBeforeCratesDropped. + -- @function [parent=#CTLD] OnBeforeCratesDropped + -- @param #CTLD self + -- @param #string From State. + -- @param #string Event Trigger. + -- @param #string To State. + -- @param Wrapper.Group#GROUP Group Group Object. + -- @param Wrapper.Unit#UNIT Unit Unit Object. + -- @param #table Cargotable Table of #CTLD_CARGO objects dropped. + -- @return #CTLD self + + --- FSM Function OnBeforeCratesBuild. + -- @function [parent=#CTLD] OnBeforeCratesBuild + -- @param #CTLD self + -- @param #string From State. + -- @param #string Event Trigger. + -- @param #string To State. + -- @param Wrapper.Group#GROUP Group Group Object. + -- @param Wrapper.Unit#UNIT Unit Unit Object. + -- @param Wrapper.Group#GROUP Vehicle The #GROUP object of the vehicle or FOB build. + -- @return #CTLD self + + --- FSM Function OnBeforeCratesRepaired. + -- @function [parent=#CTLD] OnBeforeCratesRepaired + -- @param #CTLD self + -- @param #string From State. + -- @param #string Event Trigger. + -- @param #string To State. + -- @param Wrapper.Group#GROUP Group Group Object. + -- @param Wrapper.Unit#UNIT Unit Unit Object. + -- @param Wrapper.Group#GROUP Vehicle The #GROUP object of the vehicle or FOB repaired. + -- @return #CTLD self + + --- FSM Function OnBeforeTroopsRTB. + -- @function [parent=#CTLD] OnBeforeTroopsRTB + -- @param #CTLD self + -- @param #string From State. + -- @param #string Event Trigger. + -- @param #string To State. + -- @param Wrapper.Group#GROUP Group Group Object. + -- @param Wrapper.Unit#UNIT Unit Unit Object. + --- FSM Function OnAfterTroopsPickedUp. -- @function [parent=#CTLD] OnAfterTroopsPickedUp -- @param #CTLD self @@ -1476,6 +1573,19 @@ function CTLD:SetTroopDropZoneRadius(Radius) return self end +--- (User) Add a PLAYERTASK - FSM events will check success +-- @param #CTLD self +-- @param Ops.PlayerTask#PLAYERTASK PlayerTask +-- @return #CTLD self +function CTLD:AddPlayerTask(PlayerTask) + self:T(self.lid .. " AddPlayerTask") + if not self.PlayerTaskQueue then + self.PlayerTaskQueue = FIFO:New() + end + self.PlayerTaskQueue:Push(PlayerTask,PlayerTask.PlayerTaskNr) + return self +end + --- (Internal) Event handler function -- @param #CTLD self -- @param Core.Event#EVENTDATA EventData @@ -1496,7 +1606,7 @@ function CTLD:_EventHandler(EventData) self:_RefreshF10Menus() end -- Herc support - if _unit:GetTypeName() == "Hercules" and self.enableHercules then + if self:IsHercules(_unit) and self.enableHercules then local unitname = event.IniUnitName or "none" self.Loaded_Cargo[unitname] = nil self:_RefreshF10Menus() @@ -2501,7 +2611,7 @@ end -- @param Wrapper.Unit#UNIT Unit -- @return #boolean Outcome function CTLD:IsHercules(Unit) - if Unit:GetTypeName() == "Hercules" then + if Unit:GetTypeName() == "Hercules" or string.find(Unit:GetTypeName(),"Bronco") then return true else return false @@ -2567,9 +2677,7 @@ function CTLD:_UnloadTroops(Group, Unit) :InitRandomizeUnits(true,20,2) :InitDelayOff() :SpawnFromVec2(randomcoord) - if self.movetroopstowpzone and type ~= CTLD_CARGO.Enum.ENGINEERS then - self:_MoveGroupToZone(self.DroppedTroops[self.TroopCounter]) - end + self:__TroopsDeployed(1, Group, Unit, self.DroppedTroops[self.TroopCounter],type) end -- template loop cargo:SetWasDropped(true) -- engineering group? @@ -2581,7 +2689,6 @@ function CTLD:_UnloadTroops(Group, Unit) else self:_SendMessage(string.format("Dropped Troops %s into action!",name), 10, false, Group) end - self:__TroopsDeployed(1, Group, Unit, self.DroppedTroops[self.TroopCounter]) end -- if type end end -- cargotable loop else -- droppingatbase @@ -2710,8 +2817,7 @@ end function CTLD:_BuildCrates(Group, Unit,Engineering) self:T(self.lid .. " _BuildCrates") -- avoid users trying to build from flying Hercs - local type = Unit:GetTypeName() - if type == "Hercules" and self.enableHercules and not Engineering then + if self:IsHercules(Unit) and self.enableHercules and not Engineering then local speed = Unit:GetVelocityKMH() if speed > 1 then self:_SendMessage("You need to land / stop to build something, Pilot!", 10, false, Group) @@ -2788,7 +2894,13 @@ function CTLD:_BuildCrates(Group, Unit,Engineering) local build = _build -- #CTLD.Buildable if build.CanBuild then self:_CleanUpCrates(crates,build,number) - self:_BuildObjectFromCrates(Group,Unit,build) + if self.buildtime and self.buildtime > 0 then + local buildtimer = TIMER:New(self._BuildObjectFromCrates,self,Group,Unit,build,false,Group:GetCoordinate()) + buildtimer:Start(self.buildtime) + self:_SendMessage(string.format("Build started, ready in %d seconds!",self.buildtime),15,false,Group) + else + self:_BuildObjectFromCrates(Group,Unit,build) + end end end end @@ -2887,13 +2999,13 @@ end -- @param Wrapper.Group#UNIT Unit -- @param #CTLD.Buildable Build -- @param #boolean Repair If true this is a repair and not a new build --- @param Core.Point#COORDINATE Coordinate Location for repair (e.g. where the destroyed unit was) +-- @param Core.Point#COORDINATE RepairLocation Location for repair (e.g. where the destroyed unit was) function CTLD:_BuildObjectFromCrates(Group,Unit,Build,Repair,RepairLocation) self:T(self.lid .. " _BuildObjectFromCrates") -- Spawn-a-crate-content - if Group and Group:IsAlive() then - local position = Unit:GetCoordinate() or Group:GetCoordinate() - local unitname = Unit:GetName() or Group:GetName() + if Group and Group:IsAlive() or (RepairLocation and not Repair) then + --local position = Unit:GetCoordinate() or Group:GetCoordinate() + --local unitname = Unit:GetName() or Group:GetName() or "Unknown" local name = Build.Name local ctype = Build.Type -- #CTLD_CARGO.Enum local canmove = false @@ -2905,7 +3017,13 @@ function CTLD:_BuildObjectFromCrates(Group,Unit,Build,Repair,RepairLocation) if type(temptable) == "string" then temptable = {temptable} end - local zone = ZONE_GROUP:New(string.format("Unload zone-%s",unitname),Group,100) + local zone = nil + if RepairLocation and not Repair then + -- timed build + zone = ZONE_RADIUS:New(string.format("Build zone-%d",math.random(1,10000)),RepairLocation:GetVec2(),100) + else + zone = ZONE_GROUP:New(string.format("Unload zone-%d",math.random(1,10000)),Group,100) + end --local randomcoord = zone:GetRandomCoordinate(35):GetVec2() local randomcoord = Build.Coord or zone:GetRandomCoordinate(35):GetVec2() if Repair then @@ -2924,9 +3042,6 @@ function CTLD:_BuildObjectFromCrates(Group,Unit,Build,Repair,RepairLocation) :InitDelayOff() :SpawnFromVec2(randomcoord) end - if self.movetroopstowpzone and canmove then - self:_MoveGroupToZone(self.DroppedTroops[self.TroopCounter]) - end if Repair then self:__CratesRepaired(1,Group,Unit,self.DroppedTroops[self.TroopCounter]) else @@ -3012,7 +3127,7 @@ function CTLD:_RefreshF10Menus() local _unit = _group:GetUnit(1) -- Wrapper.Unit#UNIT Asume that there is only one unit in the flight for players if _unit then if _unit:IsAlive() and _unit:IsPlayer() then - if _unit:IsHelicopter() or (_unit:GetTypeName() == "Hercules" and self.enableHercules) then --ensure no stupid unit entries here + if _unit:IsHelicopter() or (self:IsHercules(_unit) and self.enableHercules) then --ensure no stupid unit entries here local unitName = _unit:GetName() _UnitList[unitName] = unitName end @@ -3111,7 +3226,7 @@ function CTLD:_RefreshF10Menus() local buildmenu = MENU_GROUP_COMMAND:New(_group,"Build crates",topcrates, self._BuildCrates, self, _group, _unit) local repairmenu = MENU_GROUP_COMMAND:New(_group,"Repair",topcrates, self._RepairCrates, self, _group, _unit):Refresh() end - if unittype == "Hercules" then + if self:IsHercules(_unit) then local hoverpars = MENU_GROUP_COMMAND:New(_group,"Show flight parameters",topmenu, self._ShowFlightParams, self, _group, _unit):Refresh() else local hoverpars = MENU_GROUP_COMMAND:New(_group,"Show hover parameters",topmenu, self._ShowHoverParams, self, _group, _unit):Refresh() @@ -3386,7 +3501,21 @@ end -- @return #CTLD self function CTLD:AddCTLDZone(Name, Type, Color, Active, HasBeacon, Shiplength, Shipwidth) self:T(self.lid .. " AddCTLDZone") - + + local zone = ZONE:FindByName(Name) + if not zone and Type ~= CTLD.CargoZoneType.SHIP then + self:E(self.lid.."**** Zone does not exist: "..Name) + return self + end + + if Type == CTLD.CargoZoneType.SHIP then + local Ship = UNIT:FindByName(Name) + if not Ship then + self:E(self.lid.."**** Ship does not exist: "..Name) + return self + end + end + local ctldzone = {} -- #CTLD.CargoZone ctldzone.active = Active or false ctldzone.color = Color or SMOKECOLOR.Red @@ -3632,9 +3761,10 @@ function CTLD:IsUnitInZone(Unit,Zonetype) local zoneret = nil local zonewret = nil local zonenameret = nil + local unitcoord = Unit:GetCoordinate() + local unitVec2 = unitcoord:GetVec2() for _,_cargozone in pairs(zonetable) do local czone = _cargozone -- #CTLD.CargoZone - local unitcoord = Unit:GetCoordinate() local zonename = czone.name local active = czone.active local color = czone.color @@ -3643,25 +3773,26 @@ function CTLD:IsUnitInZone(Unit,Zonetype) local zonewidth = 20 if Zonetype == CTLD.CargoZoneType.SHIP then self:T("Checking Type Ship: "..zonename) - zone = UNIT:FindByName(zonename) - zonecoord = zone:GetCoordinate() + local ZoneUNIT = UNIT:FindByName(zonename) + zonecoord = ZoneUNIT:GetCoordinate() zoneradius = czone.shiplength zonewidth = czone.shipwidth + zone = ZONE_UNIT:New( ZoneUNIT:GetName(), ZoneUNIT, zoneradius/2) elseif ZONE:FindByName(zonename) then zone = ZONE:FindByName(zonename) self:T("Checking Zone: "..zonename) zonecoord = zone:GetCoordinate() - zoneradius = zone:GetRadius() + --zoneradius = 1500 zonewidth = zoneradius elseif AIRBASE:FindByName(zonename) then zone = AIRBASE:FindByName(zonename):GetZone() self:T("Checking Zone: "..zonename) zonecoord = zone:GetCoordinate() - zoneradius = zone:GetRadius() + zoneradius = 2000 zonewidth = zoneradius end local distance = self:_GetDistance(zonecoord,unitcoord) - if distance <= zoneradius and active then + if zone:IsVec2InZone(unitVec2) and active then outcome = true end if maxdist > distance then @@ -3915,7 +4046,7 @@ end function CTLD:IsUnitInAir(Unit) -- get speed and height local minheight = self.minimumHoverHeight - if self.enableHercules and Unit:GetTypeName() == "Hercules" then + if self.enableHercules and self:IsHercules(Unit) then minheight = 5.1 -- herc is 5m AGL on the ground end local uheight = Unit:GetHeight() @@ -4165,7 +4296,7 @@ end self.EngineersInField[self.Engineers] = CTLD_ENGINEERING:New(name, grpname) end if self.eventoninject then - self:__TroopsDeployed(1,nil,nil,self.DroppedTroops[self.TroopCounter]) + self:__TroopsDeployed(1,nil,nil,self.DroppedTroops[self.TroopCounter],type) end end -- if type end return self @@ -4232,9 +4363,6 @@ end :InitDelayOff() :SpawnFromVec2(randomcoord) end - if self.movetroopstowpzone and canmove then - self:_MoveGroupToZone(self.DroppedTroops[self.TroopCounter]) - end if self.eventoninject then self:__CratesBuild(1,nil,nil,self.DroppedTroops[self.TroopCounter]) end @@ -4244,7 +4372,7 @@ end end ------------------------------------------------------------------- --- FSM functions +-- TODO FSM functions ------------------------------------------------------------------- --- (Internal) FSM Function onafterStart. @@ -4417,6 +4545,45 @@ end -- @return #CTLD self function CTLD:onbeforeTroopsDeployed(From, Event, To, Group, Unit, Troops) self:T({From, Event, To}) + if Unit and Unit:IsPlayer() and self.PlayerTaskQueue then + local playername = Unit:GetPlayerName() + local dropcoord = Troops:GetCoordinate() or COORDINATE:New(0,0,0) + local dropvec2 = dropcoord:GetVec2() + self.PlayerTaskQueue:ForEach( + function (Task) + local task = Task -- Ops.PlayerTask#PLAYERTASK + local subtype = task:GetSubType() + -- right subtype? + if Event == subtype and not task:IsDone() then + local targetzone = task.Target:GetObject() -- Core.Zone#ZONE should be a zone in this case .... + if targetzone and targetzone.ClassName and string.match(targetzone.ClassName,"ZONE") and targetzone:IsVec2InZone(dropvec2) then + if task.Clients:HasUniqueID(playername) then + -- success + task:__Success(-1) + end + end + end + end + ) + end + return self + end + + --- (Internal) FSM Function onafterTroopsDeployed. + -- @param #CTLD self + -- @param #string From State. + -- @param #string Event Trigger. + -- @param #string To State. + -- @param Wrapper.Group#GROUP Group Group Object. + -- @param Wrapper.Unit#UNIT Unit Unit Object. + -- @param Wrapper.Group#GROUP Troops Troops #GROUP Object. + -- @param #CTLD.CargoZoneType Type Type of Cargo deployed + -- @return #CTLD self + function CTLD:onafterTroopsDeployed(From, Event, To, Group, Unit, Troops, Type) + self:T({From, Event, To}) + if self.movetroopstowpzone and Type ~= CTLD_CARGO.Enum.ENGINEERS then + self:_MoveGroupToZone(Troops) + end return self end @@ -4444,7 +4611,45 @@ end -- @param Wrapper.Group#GROUP Vehicle The #GROUP object of the vehicle or FOB build. -- @return #CTLD self function CTLD:onbeforeCratesBuild(From, Event, To, Group, Unit, Vehicle) + self:I({From, Event, To}) + if Unit and Unit:IsPlayer() and self.PlayerTaskQueue then + local playername = Unit:GetPlayerName() + local dropcoord = Vehicle:GetCoordinate() or COORDINATE:New(0,0,0) + local dropvec2 = dropcoord:GetVec2() + self.PlayerTaskQueue:ForEach( + function (Task) + local task = Task -- Ops.PlayerTask#PLAYERTASK + local subtype = task:GetSubType() + -- right subtype? + if Event == subtype and not task:IsDone() then + local targetzone = task.Target:GetObject() -- Core.Zone#ZONE should be a zone in this case .... + if targetzone and targetzone.ClassName and string.match(targetzone.ClassName,"ZONE") and targetzone:IsVec2InZone(dropvec2) then + if task.Clients:HasUniqueID(playername) then + -- success + task:__Success(-1) + end + end + end + end + ) + end + return self + end + + --- (Internal) FSM Function onafterCratesBuild. + -- @param #CTLD self + -- @param #string From State. + -- @param #string Event Trigger. + -- @param #string To State. + -- @param Wrapper.Group#GROUP Group Group Object. + -- @param Wrapper.Unit#UNIT Unit Unit Object. + -- @param Wrapper.Group#GROUP Vehicle The #GROUP object of the vehicle or FOB build. + -- @return #CTLD self + function CTLD:onafterCratesBuild(From, Event, To, Group, Unit, Vehicle) self:T({From, Event, To}) + if self.movetroopstowpzone then + self:_MoveGroupToZone(Vehicle) + end return self end @@ -4802,7 +5007,9 @@ end -- end do do --- **Hercules Cargo AIR Drop Events** by Anubis Yinepu -- Moose CTLD OO refactoring by Applevangelist --- +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ +-- TODO CTLD_HERCULES +------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ -- This script will only work for the Herculus mod by Anubis, and only for **Air Dropping** cargo from the Hercules. -- Use the standard Moose CTLD if you want to unload on the ground. -- Payloads carried by pylons 11, 12 and 13 need to be declared in the Herculus_Loadout.lua file @@ -4825,7 +5032,7 @@ CTLD_HERCULES = { ClassName = "CTLD_HERCULES", lid = "", Name = "", - Version = "0.0.1", + Version = "0.0.2", } --- Define cargo types. @@ -4932,13 +5139,21 @@ CTLD_HERCULES.Types = { -- -- Expected template names are the ones in the rounded brackets. -- --- HINTS +-- ### HINTS -- -- The script works on the EVENTS.Shot trigger, which is used by the mod when you **drop cargo from the Hercules while flying**. Unloading on the ground does -- not achieve anything here. If you just want to unload on the ground, use the normal Moose CTLD. +-- **Do not use** the **splash damage** script together with this, your cargo will just explode when reaching the ground! +-- +-- ### Airdrops +-- -- There are two ways of airdropping: -- 1) Very low and very slow (>5m and <10m AGL) - here you can drop stuff which has "Skid" at the end of the cargo name (loaded via F8 Ground Crew menu) -- 2) Higher up and slow (>100m AGL) - here you can drop paratroopers and cargo which has "Air" at the end of the cargo name (loaded via F8 Ground Crew menu) +-- +-- ### General +-- +-- Use either this method to integrate the Hercules **or** the one from the "normal" CTLD. Never both! function CTLD_HERCULES:New(Coalition, Alias, CtldObject) -- Inherit everything from FSM class. local self=BASE:Inherit(self, FSM:New()) -- #CTLD_HERCULES @@ -5228,7 +5443,7 @@ function CTLD_HERCULES:Cargo_Track(cargo, initiator) if self:Check_SurfaceType(cargo.Cargo_Contents) == 2 or self:Check_SurfaceType(cargo.Cargo_Contents) == 3 then cargo.Cargo_over_water = true--pallets gets destroyed in water end - local dcsvec3 = self.ObjectTracker[cargo.Cargo_Contents.id_] -- last known position + local dcsvec3 = self.ObjectTracker[cargo.Cargo_Contents.id_] or initiator:GetVec3() -- last known position self:T("SPAWNPOSITION: ") self:T({dcsvec3}) local Vec2 = { @@ -5331,7 +5546,7 @@ function CTLD_HERCULES:Cargo_Initialize(Initiator, Cargo_Contents, Cargo_Type_na local timer = TIMER:New(self.Cargo_Track,self,self.Cargo[self.j],Initiator) self.Cargo[self.j].scheduleFunctionID = timer - timer:Start(5,2,600) + timer:Start(1,1,600) else -- no paras @@ -5356,7 +5571,7 @@ function CTLD_HERCULES:Cargo_Initialize(Initiator, Cargo_Contents, Cargo_Type_na local timer = TIMER:New(self.Cargo_Track,self,self.Cargo[self.j],Initiator) self.Cargo[self.j].scheduleFunctionID = timer - timer:Start(5,2,600) + timer:Start(1,1,600) end end return self diff --git a/Moose Development/Moose/Sound/Radio.lua b/Moose Development/Moose/Sound/Radio.lua index 40343e2ac..56eb8ddf0 100644 --- a/Moose Development/Moose/Sound/Radio.lua +++ b/Moose Development/Moose/Sound/Radio.lua @@ -9,13 +9,13 @@ -- What are radio communications in DCS? -- -- * Radio transmissions consist of **sound files** that are broadcasted on a specific **frequency** (e.g. 115MHz) and **modulation** (e.g. AM), --- * They can be **subtitled** for a specific **duration**, the **power** in Watts of the transmiter's antenna can be set, and the transmission can be **looped**. +-- * They can be **subtitled** for a specific **duration**, the **power** in Watts of the transmitter's antenna can be set, and the transmission can be **looped**. -- -- How to supply DCS my own Sound Files? -- -- * Your sound files need to be encoded in **.ogg** or .wav, -- * Your sound files should be **as tiny as possible**. It is suggested you encode in .ogg with low bitrate and sampling settings, --- * They need to be added in .\l10n\DEFAULT\ in you .miz file (wich can be decompressed like a .zip file), +-- * They need to be added in .\l10n\DEFAULT\ in you .miz file (which can be decompressed like a .zip file), -- * For simplicity sake, you can **let DCS' Mission Editor add the file** itself, by creating a new Trigger with the action "Sound to Country", and choosing your sound file and a country you don't use in your mission. -- -- Due to weird DCS quirks, **radio communications behave differently** if sent by a @{Wrapper.Unit#UNIT} or a @{Wrapper.Group#GROUP} or by any other @{Wrapper.Positionable#POSITIONABLE} @@ -26,7 +26,7 @@ -- Note that obviously, the **frequency** and the **modulation** of the transmission are important only if the players are piloting an **Advanced System Modelling** enabled aircraft, -- like the A10C or the Mirage 2000C. They will **hear the transmission** if they are tuned on the **right frequency and modulation** (and if they are close enough - more on that below). -- If an FC3 aircraft is used, it will **hear every communication, whatever the frequency and the modulation** is set to. The same is true for TACAN beacons. If your aircraft isn't compatible, --- you won't hear/be able to use the TACAN beacon informations. +-- you won't hear/be able to use the TACAN beacon information. -- -- === -- @@ -98,12 +98,12 @@ RADIO = { --- Create a new RADIO Object. This doesn't broadcast a transmission, though, use @{#RADIO.Broadcast} to actually broadcast. -- If you want to create a RADIO, you probably should use @{Wrapper.Positionable#POSITIONABLE.GetRadio}() instead. -- @param #RADIO self --- @param Wrapper.Positionable#POSITIONABLE Positionable The @{Positionable} that will receive radio capabilities. +-- @param Wrapper.Positionable#POSITIONABLE Positionable The @{Wrapper.Positionable#POSITIONABLE} that will receive radio capabilities. -- @return #RADIO The RADIO object or #nil if Positionable is invalid. function RADIO:New(Positionable) -- Inherit base - local self = BASE:Inherit( self, BASE:New() ) -- Core.Radio#RADIO + local self = BASE:Inherit( self, BASE:New() ) -- Sound.Radio#RADIO self:F(Positionable) if Positionable:GetPointVec2() then -- It's stupid, but the only way I found to make sure positionable is valid @@ -375,7 +375,7 @@ end --- Stops a transmission --- This function is especially usefull to stop the broadcast of looped transmissions +-- This function is especially useful to stop the broadcast of looped transmissions -- @param #RADIO self -- @return #RADIO self function RADIO:StopBroadcast() diff --git a/Moose Development/Moose/Sound/SRS.lua b/Moose Development/Moose/Sound/SRS.lua index bc1bb67dc..1679c9bf6 100644 --- a/Moose Development/Moose/Sound/SRS.lua +++ b/Moose Development/Moose/Sound/SRS.lua @@ -1,4 +1,4 @@ ---- **Sound** - Simple Radio Standalone (SRS) Integration. +--- **Sound** - Simple Radio Standalone (SRS) Integration and Text-to-Speech. -- -- === -- @@ -26,7 +26,7 @@ -- === -- -- ### Author: **funkyfranky** --- @module Sound.MSRS +-- @module Sound.SRS -- @image Sound_MSRS.png --- MSRS class. @@ -94,8 +94,6 @@ -- For more information on setting up a cloud account, visit: https://cloud.google.com/text-to-speech -- Google's supported SSML reference: https://cloud.google.com/text-to-speech/docs/ssml -- --- **NOTE on using GOOGLE TTS with SRS:** You need to have the C# library installed in your SRS folder for Google to work. --- You can obtain it e.g. here: [NuGet](https://www.nuget.org/packages/Grpc.Core) -- -- **Pro-Tipp** - use the command line with power shell to call DCS-SR-ExternalAudio.exe - it will tell you what is missing. -- and also the Google Console error, in case you have missed a step in setting up your Google TTS. @@ -104,10 +102,14 @@ -- -- ## Set Voice -- --- Use a specifc voice with the @{#MSRS.SetVoice} function, e.g, `:SetVoice("Microsoft Hedda Desktop")`. +-- Use a specific voice with the @{#MSRS.SetVoice} function, e.g, `:SetVoice("Microsoft Hedda Desktop")`. -- Note that this must be installed on your windows system. -- If enabling SetGoogle(), you can use voices provided by Google -- Google's supported voices: https://cloud.google.com/text-to-speech/docs/voices +-- For voices there are enumerators in this class to help you out on voice names: +-- +-- MSRS.Voices.Microsoft -- e.g. MSRS.Voices.Microsoft.Hedda - the Microsoft enumerator contains all voices known to work with SRS +-- MSRS.Voices.Google -- e.g. MSRS.Voices.Google.Standard.en_AU_Standard_A or MSRS.Voices.Google.Wavenet.de_DE_Wavenet_C - The Google enumerator contains voices for EN, DE, IT, FR and ES. -- -- ## Set Coordinate -- @@ -141,7 +143,7 @@ MSRS = { --- MSRS class version. -- @field #string version -MSRS.version="0.1.0" +MSRS.version="0.1.1" --- Voices -- @type Voices @@ -248,7 +250,7 @@ MSRS.Voices = { -- TODO list ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --- TODO: Add functions to add/remove freqs and modulations. +-- TODO: Add functions to remove freqs and modulations. -- DONE: Add coordinate. -- DONE: Add google. @@ -410,6 +412,24 @@ function MSRS:SetFrequencies(Frequencies) return self end +--- Add frequencies. +-- @param #MSRS self +-- @param #table Frequencies Frequencies in MHz. Can also be given as a #number if only one frequency should be used. +-- @return #MSRS self +function MSRS:AddFrequencies(Frequencies) + + -- Ensure table. + if type(Frequencies)~="table" then + Frequencies={Frequencies} + end + + for _,_freq in pairs(Frequencies) do + table.insert(self.frequencies,_freq) + end + + return self +end + --- Get frequencies. -- @param #MSRS self -- @param #table Frequencies in MHz. @@ -434,6 +454,24 @@ function MSRS:SetModulations(Modulations) return self end +--- Add modulations. +-- @param #MSRS self +-- @param #table Modulations Modulations. Can also be given as a #number if only one modulation should be used. +-- @return #MSRS self +function MSRS:AddModulations(Modulations) + + -- Ensure table. + if type(Modulations)~="table" then + Modulations={Modulations} + end + + for _,_mod in pairs(Modulations) do + table.insert(self.modulations,_mod) + end + + return self +end + --- Get modulations. -- @param #MSRS self -- @param #table Modulations. @@ -882,6 +920,8 @@ MSRSQUEUE = { -- @field #boolean isplaying If true, transmission is currently playing. -- @field #number Tplay Mission time (abs) in seconds when the transmission should be played. -- @field #number interval Interval in seconds before next transmission. +-- @field #boolean TransmitOnlyWithPlayers If true, only transmit if there are alive Players. +-- @field Core.Set#SET_CLIENT PlayerSet PlayerSet created when TransmitOnlyWithPlayers == true --- Create a new MSRSQUEUE object for a given radio frequency/modulation. -- @param #MSRSQUEUE self @@ -932,6 +972,23 @@ function MSRSQUEUE:AddTransmission(transmission) return self end +--- Switch to only transmit if there are players on the server. +-- @param #MSRSQUEUE self +-- @param #boolean Switch If true, only send SRS if there are alive Players. +-- @return #MSRSQUEUE self +function MSRSQUEUE:SetTransmitOnlyWithPlayers(Switch) + self.TransmitOnlyWithPlayers = Switch + if Switch == false or Switch==nil then + if self.PlayerSet then + self.PlayerSet:FilterStop() + end + self.PlayerSet = nil + else + self.PlayerSet = SET_CLIENT:New():FilterStart() + end + return self +end + --- Create a new transmission and add it to the radio queue. -- @param #MSRSQUEUE self -- @param #string text Text to play. @@ -946,7 +1003,13 @@ end -- @param #number modulation Radio modulation if other then MSRS default. -- @return #MSRSQUEUE.Transmission Radio transmission table. function MSRSQUEUE:NewTransmission(text, duration, msrs, tstart, interval, subgroups, subtitle, subduration, frequency, modulation) - + + if self.TransmitOnlyWithPlayers then + if self.PlayerSet and self.PlayerSet:CountAlive() == 0 then + return self + end + end + -- Sanity checks. if not text then self:E(self.lid.."ERROR: No text specified.") diff --git a/Moose Development/Moose/Tasking/CommandCenter.lua b/Moose Development/Moose/Tasking/CommandCenter.lua index 8df64d063..6562fcb90 100644 --- a/Moose Development/Moose/Tasking/CommandCenter.lua +++ b/Moose Development/Moose/Tasking/CommandCenter.lua @@ -1,4 +1,4 @@ ---- **Tasking** -- A command center governs multiple missions, and takes care of the reporting and communications. +--- **Tasking** - A command center governs multiple missions, and takes care of the reporting and communications. -- -- **Features:** -- diff --git a/Moose Development/Moose/Tasking/DetectionManager.lua b/Moose Development/Moose/Tasking/DetectionManager.lua index 3e16fad29..6005a9ffa 100644 --- a/Moose Development/Moose/Tasking/DetectionManager.lua +++ b/Moose Development/Moose/Tasking/DetectionManager.lua @@ -342,7 +342,7 @@ do -- DETECTION_REPORTING return self end - --- Creates a string of the detected items in a @{Detection}. + --- Creates a string of the detected items in a @{Functional.Detection} object. -- @param #DETECTION_MANAGER self -- @param Core.Set#SET_UNIT DetectedSet The detected Set created by the @{Functional.Detection#DETECTION_BASE} object. -- @return #DETECTION_MANAGER self diff --git a/Moose Development/Moose/Tasking/Mission.lua b/Moose Development/Moose/Tasking/Mission.lua index e8da4f102..ba84fe162 100644 --- a/Moose Development/Moose/Tasking/Mission.lua +++ b/Moose Development/Moose/Tasking/Mission.lua @@ -1,4 +1,4 @@ ---- **Tasking** -- A mission models a goal to be achieved through the execution and completion of tasks by human players. +--- **Tasking** - A mission models a goal to be achieved through the execution and completion of tasks by human players. -- -- **Features:** -- @@ -86,7 +86,7 @@ -- - @{#MISSION.GetTasks}(): Retrieves a list of the tasks controlled by the mission. -- - @{#MISSION.GetTask}(): Retrieves a specific task controlled by the mission. -- - @{#MISSION.GetTasksRemaining}(): Retrieve a list of the tasks that aren't finished or failed, and are governed by the mission. --- - @{#MISSION.GetGroupTasks}(): Retrieve a list of the tasks that can be asigned to a @{Wrapper.Group}. +-- - @{#MISSION.GetGroupTasks}(): Retrieve a list of the tasks that can be assigned to a @{Wrapper.Group}. -- - @{#MISSION.GetTaskTypes}(): Retrieve a list of the different task types governed by the mission. -- -- ### 3.3. Get the command center. @@ -131,7 +131,7 @@ MISSION = { -- @param Tasking.CommandCenter#COMMANDCENTER CommandCenter -- @param #string MissionName Name of the mission. This name will be used to reference the status of each mission by the players. -- @param #string MissionPriority String indicating the "priority" of the Mission. e.g. "Primary", "Secondary". It is free format and up to the Mission designer to choose. There are no rules behind this field. --- @param #string MissionBriefing String indicating the mission briefing to be shown when a player joins a @{CLIENT}. +-- @param #string MissionBriefing String indicating the mission briefing to be shown when a player joins a @{Wrapper.Client#CLIENT}. -- @param DCS#coalition.side MissionCoalition Side of the coalition, i.e. and enumerator @{#DCS.coalition.side} corresponding to RED, BLUE or NEUTRAL. -- @return #MISSION self function MISSION:New( CommandCenter, MissionName, MissionPriority, MissionBriefing, MissionCoalition ) @@ -543,7 +543,7 @@ end do -- Group Assignment - --- Returns if the @{Mission} is assigned to the Group. + --- Returns if the @{Tasking.Mission} is assigned to the Group. -- @param #MISSION self -- @param Wrapper.Group#GROUP MissionGroup -- @return #boolean @@ -561,7 +561,7 @@ do -- Group Assignment end - --- Set @{Wrapper.Group} assigned to the @{Mission}. + --- Set @{Wrapper.Group} assigned to the @{Tasking.Mission}. -- @param #MISSION self -- @param Wrapper.Group#GROUP MissionGroup -- @return #MISSION @@ -576,7 +576,7 @@ do -- Group Assignment return self end - --- Clear the @{Wrapper.Group} assignment from the @{Mission}. + --- Clear the @{Wrapper.Group} assignment from the @{Tasking.Mission}. -- @param #MISSION self -- @param Wrapper.Group#GROUP MissionGroup -- @return #MISSION @@ -667,7 +667,7 @@ end --- Get the TASK identified by the TaskNumber from the Mission. This function is useful in GoalFunctions. --- @param #string TaskName The Name of the @{Task} within the @{Mission}. +-- @param #string TaskName The Name of the @{Tasking.Task} within the @{Tasking.Mission}. -- @return Tasking.Task#TASK The Task -- @return #nil Returns nil if no task was found. function MISSION:GetTask( TaskName ) @@ -677,9 +677,9 @@ function MISSION:GetTask( TaskName ) end ---- Return the next @{Task} ID to be completed within the @{Mission}. +--- Return the next @{Tasking.Task} ID to be completed within the @{Tasking.Mission}. -- @param #MISSION self --- @param Tasking.Task#TASK Task is the @{Task} object. +-- @param Tasking.Task#TASK Task is the @{Tasking.Task} object. -- @return Tasking.Task#TASK The task added. function MISSION:GetNextTaskID( Task ) @@ -689,11 +689,11 @@ function MISSION:GetNextTaskID( Task ) end ---- Register a @{Task} to be completed within the @{Mission}. --- Note that there can be multiple @{Task}s registered to be completed. +--- Register a @{Tasking.Task} to be completed within the @{Tasking.Mission}. +-- Note that there can be multiple @{Tasking.Task}s registered to be completed. -- Each Task can be set a certain Goals. The Mission will not be completed until all Goals are reached. -- @param #MISSION self --- @param Tasking.Task#TASK Task is the @{Task} object. +-- @param Tasking.Task#TASK Task is the @{Tasking.Task} object. -- @return Tasking.Task#TASK The task added. function MISSION:AddTask( Task ) @@ -708,11 +708,11 @@ function MISSION:AddTask( Task ) end ---- Removes a @{Task} to be completed within the @{Mission}. --- Note that there can be multiple @{Task}s registered to be completed. +--- Removes a @{Tasking.Task} to be completed within the @{Tasking.Mission}. +-- Note that there can be multiple @{Tasking.Task}s registered to be completed. -- Each Task can be set a certain Goals. The Mission will not be completed until all Goals are reached. -- @param #MISSION self --- @param Tasking.Task#TASK Task is the @{Task} object. +-- @param Tasking.Task#TASK Task is the @{Tasking.Task} object. -- @return #nil The cleaned Task reference. function MISSION:RemoveTask( Task ) @@ -733,35 +733,35 @@ function MISSION:RemoveTask( Task ) return nil end ---- Is the @{Mission} **COMPLETED**. +--- Is the @{Tasking.Mission} **COMPLETED**. -- @param #MISSION self -- @return #boolean function MISSION:IsCOMPLETED() return self:Is( "COMPLETED" ) end ---- Is the @{Mission} **IDLE**. +--- Is the @{Tasking.Mission} **IDLE**. -- @param #MISSION self -- @return #boolean function MISSION:IsIDLE() return self:Is( "IDLE" ) end ---- Is the @{Mission} **ENGAGED**. +--- Is the @{Tasking.Mission} **ENGAGED**. -- @param #MISSION self -- @return #boolean function MISSION:IsENGAGED() return self:Is( "ENGAGED" ) end ---- Is the @{Mission} **FAILED**. +--- Is the @{Tasking.Mission} **FAILED**. -- @param #MISSION self -- @return #boolean function MISSION:IsFAILED() return self:Is( "FAILED" ) end ---- Is the @{Mission} **HOLD**. +--- Is the @{Tasking.Mission} **HOLD**. -- @param #MISSION self -- @return #boolean function MISSION:IsHOLD() @@ -1105,7 +1105,7 @@ function MISSION:ReportDetails( ReportGroup ) end --- Get all the TASKs from the Mission. This function is useful in GoalFunctions. --- @return {TASK,...} Structure of TASKS with the @{TASK} number as the key. +-- @return {TASK,...} Structure of TASKS with the @{Tasking.Task#TASK} number as the key. -- @usage -- -- Get Tasks from the Mission. -- Tasks = Mission:GetTasks() diff --git a/Moose Development/Moose/Tasking/Task.lua b/Moose Development/Moose/Tasking/Task.lua index f553cfc71..950ca6656 100644 --- a/Moose Development/Moose/Tasking/Task.lua +++ b/Moose Development/Moose/Tasking/Task.lua @@ -1,4 +1,4 @@ ---- **Tasking** -- A task object governs the main engine to administer human taskings. +--- **Tasking** - A task object governs the main engine to administer human taskings. -- -- **Features:** -- @@ -38,7 +38,7 @@ -- -- A mission can be in a specific state during the simulation run. For more information about these states, please check the @{Tasking.Mission} section. -- --- To achieve the mission goal, a mission administers @{Tasking.Task}s that are set to achieve the mission goal by the human players. +-- To achieve the mission goal, a mission administers @{#TASK}s that are set to achieve the mission goal by the human players. -- Each of these tasks can be **dynamically created** using a task dispatcher, or **coded** by the mission designer. -- Each mission has a separate **Mission Menu**, that focuses on the administration of these tasks. -- @@ -143,7 +143,7 @@ -- -- ![Command Center](../Tasking/Menu_CommandCenter.JPG) -- --- When we take back the command center menu, you see two addtional **Assign Task** menu items. +-- When we take back the command center menu, you see two additional **Assign Task** menu items. -- The menu **Assign Task On** will automatically allocate a task to the player. -- After the selection of this menu, the menu will change into **Assign Task Off**, -- and will need to be selected again by the player to switch of the automatic task assignment. @@ -190,7 +190,7 @@ -- -- The state completion is by default set to **Success**, if the goals of the task have been reached, but can be overruled by a goal method. -- --- Depending on the tactical situation, a task can be **Cancelled** by the mission governer. +-- Depending on the tactical situation, a task can be **Cancelled** by the mission governor. -- It is actually the mission designer who has the flexibility to decide at which conditions a task would be set to **Success**, **Failed** or **Cancelled**. -- This decision all depends on the task goals, and the phase/evolution of the task conditions that would accomplish the goals. -- @@ -199,16 +199,16 @@ -- However, it could very well be also acceptable that the task would be flagged as **Success**. -- -- The tasking mechanism governs beside the progress also a scoring mechanism, and in case of goal completion without any active pilot involved --- in the execution of the task, could result in a **Success** task completion status, but no score would be awared, as there were no players involved. +-- in the execution of the task, could result in a **Success** task completion status, but no score would be awarded, as there were no players involved. -- -- These different completion states are important for the mission designer to reflect scoring to a player. -- A success could mean a positive score to be given, while a failure could mean a negative score or penalties to be awarded. -- -- === -- --- ### Author: **FlightControl** +-- ### Author(s): **FlightControl** -- --- ### Contributions: +-- ### Contribution(s): -- -- === -- @@ -262,8 +262,8 @@ -- -- ## 1.3) Cargo Tasks -- --- - @{Tasking.Task_Cargo#TASK_CARGO_TRANSPORT} - Models the transportation of cargo to deployment zones. --- - @{Tasking.Task_Cargo#TASK_CARGO_CSAR} - Models the rescue of downed friendly pilots from behind enemy lines. +-- - @{Tasking.Task_CARGO#TASK_CARGO_TRANSPORT} - Models the transportation of cargo to deployment zones. +-- - @{Tasking.Task_CARGO#TASK_CARGO_CSAR} - Models the rescue of downed friendly pilots from behind enemy lines. -- -- -- # 2) Task status events. @@ -293,7 +293,7 @@ -- -- function Task:OnAfterGoal() -- if condition == true then --- self:Success() -- This will flag the task to Succcess when the condition is true. +-- self:Success() -- This will flag the task to Success when the condition is true. -- else -- if condition2 == true and condition3 == true then -- self:Fail() -- This will flag the task to Failed, when condition2 and condition3 would be true. @@ -732,7 +732,7 @@ end do -- Group Assignment - --- Returns if the @{Task} is assigned to the Group. + --- Returns if the @{#TASK} is assigned to the Group. -- @param #TASK self -- @param Wrapper.Group#GROUP TaskGroup -- @return #boolean @@ -750,7 +750,7 @@ do -- Group Assignment end - --- Set @{Wrapper.Group} assigned to the @{Task}. + --- Set @{Wrapper.Group} assigned to the @{#TASK}. -- @param #TASK self -- @param Wrapper.Group#GROUP TaskGroup -- @return #TASK @@ -780,7 +780,7 @@ do -- Group Assignment return self end - --- Clear the @{Wrapper.Group} assignment from the @{Task}. + --- Clear the @{Wrapper.Group} assignment from the @{#TASK}. -- @param #TASK self -- @param Wrapper.Group#GROUP TaskGroup -- @return #TASK @@ -824,7 +824,7 @@ do -- Group Assignment end - --- Assign the @{Task} to a @{Wrapper.Group}. + --- Assign the @{#TASK} to a @{Wrapper.Group}. -- @param #TASK self -- @param Wrapper.Group#GROUP TaskGroup -- @return #TASK @@ -861,7 +861,7 @@ do -- Group Assignment return self end - --- UnAssign the @{Task} from a @{Wrapper.Group}. + --- UnAssign the @{#TASK} from a @{Wrapper.Group}. -- @param #TASK self -- @param Wrapper.Group#GROUP TaskGroup function TASK:UnAssignFromGroup( TaskGroup ) @@ -899,7 +899,7 @@ function TASK:HasGroup( FindGroup ) end ---- Assign the @{Task} to an alive @{Wrapper.Unit}. +--- Assign the @{#TASK} to an alive @{Wrapper.Unit}. -- @param #TASK self -- @param Wrapper.Unit#UNIT TaskUnit -- @return #TASK self @@ -918,7 +918,7 @@ function TASK:AssignToUnit( TaskUnit ) return self end ---- UnAssign the @{Task} from an alive @{Wrapper.Unit}. +--- UnAssign the @{#TASK} from an alive @{Wrapper.Unit}. -- @param #TASK self -- @param Wrapper.Unit#UNIT TaskUnit -- @return #TASK self @@ -932,7 +932,7 @@ function TASK:UnAssignFromUnit( TaskUnit ) return self end ---- Sets the TimeOut for the @{Task}. If @{Task} stayed planned for longer than TimeOut, it gets into Cancelled status. +--- Sets the TimeOut for the @{#TASK}. If @{#TASK} stayed planned for longer than TimeOut, it gets into Cancelled status. -- @param #TASK self -- @param #integer Timer in seconds -- @return #TASK self @@ -943,7 +943,7 @@ function TASK:SetTimeOut ( Timer ) return self end ---- Send a message of the @{Task} to the assigned @{Wrapper.Group}s. +--- Send a message of the @{#TASK} to the assigned @{Wrapper.Group}s. -- @param #TASK self function TASK:MessageToGroups( Message ) self:F( { Message = Message } ) @@ -960,7 +960,7 @@ function TASK:MessageToGroups( Message ) end ---- Send the briefng message of the @{Task} to the assigned @{Wrapper.Group}s. +--- Send the briefing message of the @{#TASK} to the assigned @{Wrapper.Group}s. -- @param #TASK self function TASK:SendBriefingToAssignedGroups() self:F2() @@ -975,7 +975,7 @@ function TASK:SendBriefingToAssignedGroups() end ---- UnAssign the @{Task} from the @{Wrapper.Group}s. +--- UnAssign the @{#TASK} from the @{Wrapper.Group}s. -- @param #TASK self function TASK:UnAssignFromGroups() self:F2() @@ -991,7 +991,7 @@ end ---- Returns if the @{Task} has still alive and assigned Units. +--- Returns if the @{#TASK} has still alive and assigned Units. -- @param #TASK self -- @return #boolean function TASK:HasAliveUnits() @@ -1016,7 +1016,7 @@ function TASK:HasAliveUnits() return false end ---- Set the menu options of the @{Task} to all the groups in the SetGroup. +--- Set the menu options of the @{#TASK} to all the groups in the SetGroup. -- @param #TASK self -- @param #number MenuTime -- @return #TASK @@ -1057,7 +1057,7 @@ function TASK:SetMenuForGroup( TaskGroup, MenuTime ) end ---- Set the planned menu option of the @{Task}. +--- Set the planned menu option of the @{#TASK}. -- @param #TASK self -- @param Wrapper.Group#GROUP TaskGroup -- @param #string MenuText The menu text. @@ -1092,7 +1092,7 @@ function TASK:SetPlannedMenuForGroup( TaskGroup, MenuTime ) return self end ---- Set the assigned menu options of the @{Task}. +--- Set the assigned menu options of the @{#TASK}. -- @param #TASK self -- @param Wrapper.Group#GROUP TaskGroup -- @param #number MenuTime @@ -1127,7 +1127,7 @@ function TASK:SetAssignedMenuForGroup( TaskGroup, MenuTime ) return self end ---- Remove the menu options of the @{Task} to all the groups in the SetGroup. +--- Remove the menu options of the @{#TASK} to all the groups in the SetGroup. -- @param #TASK self -- @param #number MenuTime -- @return #TASK @@ -1145,7 +1145,7 @@ function TASK:RemoveMenu( MenuTime ) end ---- Remove the menu option of the @{Task} for a @{Wrapper.Group}. +--- Remove the menu option of the @{#TASK} for a @{Wrapper.Group}. -- @param #TASK self -- @param Wrapper.Group#GROUP TaskGroup -- @param #number MenuTime @@ -1176,7 +1176,7 @@ function TASK:RefreshMenus( TaskGroup, MenuTime ) end ---- Remove the assigned menu option of the @{Task} for a @{Wrapper.Group}. +--- Remove the assigned menu option of the @{#TASK} for a @{Wrapper.Group}. -- @param #TASK self -- @param Wrapper.Group#GROUP TaskGroup -- @param #number MenuTime @@ -1275,14 +1275,14 @@ end ---- Returns the @{Task} name. +--- Returns the @{#TASK} name. -- @param #TASK self -- @return #string TaskName function TASK:GetTaskName() return self.TaskName end ---- Returns the @{Task} briefing. +--- Returns the @{#TASK} briefing. -- @param #TASK self -- @return #string Task briefing. function TASK:GetTaskBriefing() @@ -1292,7 +1292,7 @@ end ---- Get the default or currently assigned @{Process} template with key ProcessName. +--- Get the default or currently assigned @{Core.Fsm#FSM_PROCESS} template with key ProcessName. -- @param #TASK self -- @param #string ProcessName -- @return Core.Fsm#FSM_PROCESS @@ -1305,8 +1305,8 @@ end --- TODO: Obscolete? ---- Fail processes from @{Task} with key @{Wrapper.Unit} +-- TODO: Obsolete? +--- Fail processes from @{#TASK} with key @{Wrapper.Unit}. -- @param #TASK self -- @param #string TaskUnitName -- @return #TASK self @@ -1318,7 +1318,7 @@ function TASK:FailProcesses( TaskUnitName ) end end ---- Add a FiniteStateMachine to @{Task} with key Task@{Wrapper.Unit} +--- Add a FiniteStateMachine to @{#TASK} with key @{Wrapper.Unit}. -- @param #TASK self -- @param Wrapper.Unit#UNIT TaskUnit -- @param Core.Fsm#FSM_PROCESS Fsm @@ -1331,7 +1331,7 @@ function TASK:SetStateMachine( TaskUnit, Fsm ) return Fsm end ---- Gets the FiniteStateMachine of @{Task} with key Task@{Wrapper.Unit} +--- Gets the FiniteStateMachine of @{#TASK} with key @{Wrapper.Unit}. -- @param #TASK self -- @param Wrapper.Unit#UNIT TaskUnit -- @return Core.Fsm#FSM_PROCESS @@ -1341,7 +1341,7 @@ function TASK:GetStateMachine( TaskUnit ) return self.Fsm[TaskUnit] end ---- Remove FiniteStateMachines from @{Task} with key Task@{Wrapper.Unit} +--- Remove FiniteStateMachines from @{#TASK} with key @{Wrapper.Unit}. -- @param #TASK self -- @param Wrapper.Unit#UNIT TaskUnit -- @return #TASK self @@ -1365,7 +1365,7 @@ function TASK:RemoveStateMachine( TaskUnit ) end ---- Checks if there is a FiniteStateMachine assigned to Task@{Wrapper.Unit} for @{Task} +--- Checks if there is a FiniteStateMachine assigned to @{Wrapper.Unit} for @{#TASK}. -- @param #TASK self -- @param Wrapper.Unit#UNIT TaskUnit -- @return #TASK self @@ -1438,117 +1438,117 @@ function TASK:GetID() end ---- Sets a @{Task} to status **Success**. +--- Sets a @{#TASK} to status **Success**. -- @param #TASK self function TASK:StateSuccess() self:SetState( self, "State", "Success" ) return self end ---- Is the @{Task} status **Success**. +--- Is the @{#TASK} status **Success**. -- @param #TASK self function TASK:IsStateSuccess() return self:Is( "Success" ) end ---- Sets a @{Task} to status **Failed**. +--- Sets a @{#TASK} to status **Failed**. -- @param #TASK self function TASK:StateFailed() self:SetState( self, "State", "Failed" ) return self end ---- Is the @{Task} status **Failed**. +--- Is the @{#TASK} status **Failed**. -- @param #TASK self function TASK:IsStateFailed() return self:Is( "Failed" ) end ---- Sets a @{Task} to status **Planned**. +--- Sets a @{#TASK} to status **Planned**. -- @param #TASK self function TASK:StatePlanned() self:SetState( self, "State", "Planned" ) return self end ---- Is the @{Task} status **Planned**. +--- Is the @{#TASK} status **Planned**. -- @param #TASK self function TASK:IsStatePlanned() return self:Is( "Planned" ) end ---- Sets a @{Task} to status **Aborted**. +--- Sets a @{#TASK} to status **Aborted**. -- @param #TASK self function TASK:StateAborted() self:SetState( self, "State", "Aborted" ) return self end ---- Is the @{Task} status **Aborted**. +--- Is the @{#TASK} status **Aborted**. -- @param #TASK self function TASK:IsStateAborted() return self:Is( "Aborted" ) end ---- Sets a @{Task} to status **Cancelled**. +--- Sets a @{#TASK} to status **Cancelled**. -- @param #TASK self function TASK:StateCancelled() self:SetState( self, "State", "Cancelled" ) return self end ---- Is the @{Task} status **Cancelled**. +--- Is the @{#TASK} status **Cancelled**. -- @param #TASK self function TASK:IsStateCancelled() return self:Is( "Cancelled" ) end ---- Sets a @{Task} to status **Assigned**. +--- Sets a @{#TASK} to status **Assigned**. -- @param #TASK self function TASK:StateAssigned() self:SetState( self, "State", "Assigned" ) return self end ---- Is the @{Task} status **Assigned**. +--- Is the @{#TASK} status **Assigned**. -- @param #TASK self function TASK:IsStateAssigned() return self:Is( "Assigned" ) end ---- Sets a @{Task} to status **Hold**. +--- Sets a @{#TASK} to status **Hold**. -- @param #TASK self function TASK:StateHold() self:SetState( self, "State", "Hold" ) return self end ---- Is the @{Task} status **Hold**. +--- Is the @{#TASK} status **Hold**. -- @param #TASK self function TASK:IsStateHold() return self:Is( "Hold" ) end ---- Sets a @{Task} to status **Replanned**. +--- Sets a @{#TASK} to status **Replanned**. -- @param #TASK self function TASK:StateReplanned() self:SetState( self, "State", "Replanned" ) return self end ---- Is the @{Task} status **Replanned**. +--- Is the @{#TASK} status **Replanned**. -- @param #TASK self function TASK:IsStateReplanned() return self:Is( "Replanned" ) end ---- Gets the @{Task} status. +--- Gets the @{#TASK} status. -- @param #TASK self function TASK:GetStateString() return self:GetState( self, "State" ) end ---- Sets a @{Task} briefing. +--- Sets a @{#TASK} briefing. -- @param #TASK self -- @param #string TaskBriefing -- @return #TASK self @@ -1558,7 +1558,7 @@ function TASK:SetBriefing( TaskBriefing ) return self end ---- Gets the @{Task} briefing. +--- Gets the @{#TASK} briefing. -- @param #TASK self -- @return #string The briefing text. function TASK:GetBriefing() diff --git a/Moose Development/Moose/Tasking/TaskInfo.lua b/Moose Development/Moose/Tasking/TaskInfo.lua index 8d825e309..9c1eb7a18 100644 --- a/Moose Development/Moose/Tasking/TaskInfo.lua +++ b/Moose Development/Moose/Tasking/TaskInfo.lua @@ -1,4 +1,4 @@ ---- **Tasking** -- Controls the information of a Task. +--- **Tasking** - Controls the information of a Task. -- -- === -- diff --git a/Moose Development/Moose/Tasking/Task_A2A.lua b/Moose Development/Moose/Tasking/Task_A2A.lua index 389be7dd7..b9af14ef2 100644 --- a/Moose Development/Moose/Tasking/Task_A2A.lua +++ b/Moose Development/Moose/Tasking/Task_A2A.lua @@ -18,7 +18,7 @@ do -- TASK_A2A -- @field Core.Set#SET_UNIT TargetSetUnit -- @extends Tasking.Task#TASK - --- Defines Air To Air tasks for a @{Set} of Target Units, + --- Defines Air To Air tasks for a @{Core.Set} of Target Units, -- based on the tasking capabilities defined in @{Tasking.Task#TASK}. -- The TASK_A2A is implemented using a @{Core.Fsm#FSM_TASK}, and has the following statuses: -- diff --git a/Moose Development/Moose/Tasking/Task_A2A_Dispatcher.lua b/Moose Development/Moose/Tasking/Task_A2A_Dispatcher.lua index 12f0446a7..52f2317aa 100644 --- a/Moose Development/Moose/Tasking/Task_A2A_Dispatcher.lua +++ b/Moose Development/Moose/Tasking/Task_A2A_Dispatcher.lua @@ -29,11 +29,11 @@ do -- TASK_A2A_DISPATCHER -- @type TASK_A2A_DISPATCHER -- @extends Tasking.DetectionManager#DETECTION_MANAGER - --- Orchestrates the dynamic dispatching of tasks upon groups of detected units determined a @{Set} of EWR installation groups. + --- Orchestrates the dynamic dispatching of tasks upon groups of detected units determined a @{Core.Set} of EWR installation groups. -- -- ![Banner Image](..\Presentations\TASK_A2A_DISPATCHER\Dia3.JPG) -- - -- The EWR will detect units, will group them, and will dispatch @{Task}s to groups. Depending on the type of target detected, different tasks will be dispatched. + -- The EWR will detect units, will group them, and will dispatch @{Tasking.Task}s to groups. Depending on the type of target detected, different tasks will be dispatched. -- Find a summary below describing for which situation a task type is created: -- -- ![Banner Image](..\Presentations\TASK_A2A_DISPATCHER\Dia9.JPG) @@ -140,7 +140,7 @@ do -- TASK_A2A_DISPATCHER -- -- ## 4. Set **Scoring** and **Messages**: -- - -- The TASK\_A2A\_DISPATCHER is a state machine. It triggers the event Assign when a new player joins a @{Task} dispatched by the TASK\_A2A\_DISPATCHER. + -- The TASK\_A2A\_DISPATCHER is a state machine. It triggers the event Assign when a new player joins a @{Tasking.Task} dispatched by the TASK\_A2A\_DISPATCHER. -- An _event handler_ can be defined to catch the **Assign** event, and add **additional processing** to set _scoring_ and to _define messages_, -- when the player reaches certain achievements in the task. -- diff --git a/Moose Development/Moose/Tasking/Task_A2G.lua b/Moose Development/Moose/Tasking/Task_A2G.lua index 20e5df555..d6c8dd613 100644 --- a/Moose Development/Moose/Tasking/Task_A2G.lua +++ b/Moose Development/Moose/Tasking/Task_A2G.lua @@ -18,7 +18,7 @@ do -- TASK_A2G -- @field Core.Set#SET_UNIT TargetSetUnit -- @extends Tasking.Task#TASK - --- The TASK_A2G class defines Air To Ground tasks for a @{Set} of Target Units, + --- The TASK_A2G class defines Air To Ground tasks for a @{Core.Set} of Target Units, -- based on the tasking capabilities defined in @{Tasking.Task#TASK}. -- The TASK_A2G is implemented using a @{Core.Fsm#FSM_TASK}, and has the following statuses: -- diff --git a/Moose Development/Moose/Tasking/Task_A2G_Dispatcher.lua b/Moose Development/Moose/Tasking/Task_A2G_Dispatcher.lua index b9aedb1b6..6bbc5592f 100644 --- a/Moose Development/Moose/Tasking/Task_A2G_Dispatcher.lua +++ b/Moose Development/Moose/Tasking/Task_A2G_Dispatcher.lua @@ -1,4 +1,4 @@ ---- **Tasking** -- Dynamically allocates A2G tasks to human players, based on detected ground targets through reconnaissance. +--- **Tasking** - Dynamically allocates A2G tasks to human players, based on detected ground targets through reconnaissance. -- -- **Features:** -- @@ -32,17 +32,17 @@ do -- TASK_A2G_DISPATCHER -- @field Tasking.Mission#MISSION Mission -- @extends Tasking.DetectionManager#DETECTION_MANAGER - --- Orchestrates dynamic **A2G Task Dispatching** based on the detection results of a linked @{Detection} object. + --- Orchestrates dynamic **A2G Task Dispatching** based on the detection results of a linked @{Functional.Detection} object. -- -- It uses the Tasking System within the MOOSE framework, which is a multi-player Tasking Orchestration system. -- It provides a truly dynamic battle environment for pilots and ground commanders to engage upon, -- in a true co-operation environment wherein **Multiple Teams** will collaborate in Missions to **achieve a common Mission Goal**. -- - -- The A2G dispatcher will dispatch the A2G Tasks to a defined @{Set} of @{Wrapper.Group}s that will be manned by **Players**. - -- We call this the **AttackSet** of the A2G dispatcher. So, the Players are seated in the @{Client}s of the @{Wrapper.Group} @{Set}. + -- The A2G dispatcher will dispatch the A2G Tasks to a defined @{Core.Set} of @{Wrapper.Group}s that will be manned by **Players**. + -- We call this the **AttackSet** of the A2G dispatcher. So, the Players are seated in the @{Wrapper.Client}s of the @{Wrapper.Group} @{Core.Set}. -- -- Depending on the actions of the enemy, preventive tasks are dispatched to the players to orchestrate the engagement in a true co-operation. - -- The detection object will group the detected targets by its grouping method, and integrates a @{Set} of @{Wrapper.Group}s that are Recce vehicles or air units. + -- The detection object will group the detected targets by its grouping method, and integrates a @{Core.Set} of @{Wrapper.Group}s that are Recce vehicles or air units. -- We call this the **RecceSet** of the A2G dispatcher. -- -- Depending on the current detected tactical situation, different task types will be dispatched to the Players seated in the AttackSet.. @@ -108,7 +108,7 @@ do -- TASK_A2G_DISPATCHER -- -- # 1. Player Experience -- - -- The A2G dispatcher is residing under a @{CommandCenter}, which is orchestrating a @{Mission}. + -- The A2G dispatcher is residing under a @{Tasking.CommandCenter}, which is orchestrating a @{Tasking.Mission}. -- As a result, you'll find for DCS World missions that implement the A2G dispatcher a **Command Center Menu** and under this one or more **Mission Menus**. -- -- For example, if there are 2 Command Centers (CC). @@ -367,7 +367,7 @@ do -- TASK_A2G_DISPATCHER -- -- ![](..\Presentations\TASK_A2G_DISPATCHER\Dia7.JPG) -- - -- The @{Settings} menu provides additional options to control the timing of the messages. + -- The @{Core.Settings} menu provides additional options to control the timing of the messages. -- There are: -- -- - Status messages, which are quick status updates. The settings menu allows to switch off these messages. @@ -384,12 +384,12 @@ do -- TASK_A2G_DISPATCHER -- -- To use the TASK\_A2G\_DISPATCHER class, you need: -- - -- - A @{CommandCenter} object. The master communication channel. - -- - A @{Mission} object. Each task belongs to a Mission. - -- - A @{Detection} object. There are several detection grouping methods to choose from. - -- - A @{Task_A2G_Dispatcher} object. The master A2G task dispatcher. - -- - A @{Set} of @{Wrapper.Group} objects that will detect the enemy, the RecceSet. This is attached to the @{Detection} object. - -- - A @{Set} ob @{Wrapper.Group} objects that will attack the enemy, the AttackSet. This is attached to the @{Task_A2G_Dispatcher} object. + -- - A @{Tasking.CommandCenter} object. The master communication channel. + -- - A @{Tasking.Mission} object. Each task belongs to a Mission. + -- - A @{Functional.Detection} object. There are several detection grouping methods to choose from. + -- - A @{Tasking.Task_A2G_Dispatcher} object. The master A2G task dispatcher. + -- - A @{Core.Set} of @{Wrapper.Group} objects that will detect the enemy, the RecceSet. This is attached to the @{Functional.Detection} object. + -- - A @{Core.Set} of @{Wrapper.Group} objects that will attack the enemy, the AttackSet. This is attached to the @{Tasking.Task_A2G_Dispatcher} object. -- -- Below an example mission declaration that is defines a Task A2G Dispatcher object. -- diff --git a/Moose Development/Moose/Tasking/Task_CARGO.lua b/Moose Development/Moose/Tasking/Task_CARGO.lua index b327ab6a3..3c1923b3c 100644 --- a/Moose Development/Moose/Tasking/Task_CARGO.lua +++ b/Moose Development/Moose/Tasking/Task_CARGO.lua @@ -1,11 +1,11 @@ ---- **Tasking** -- Base class to model tasks for players to transport cargo. +--- **Tasking** - Base class to model tasks for players to transport cargo. -- -- ## Features: -- -- * TASK_CARGO is the **base class** for: -- -- * @{Tasking.Task_Cargo_Transport#TASK_CARGO_TRANSPORT} --- * @{Tasking.Task_Cargo_CSAR#TASK_CARGO_CSAR} +-- * @{Tasking.Task_CARGO_CSAR#TASK_CARGO_CSAR} -- -- -- === @@ -34,7 +34,7 @@ -- The following TASK_CARGO_ classes are important, as they implement the CONCRETE tasks: -- -- * @{Tasking.Task_Cargo_Transport#TASK_CARGO_TRANSPORT}: Defines a task for a human player to transport a set of cargo between various zones. --- * @{Tasking.Task_Cargo_CSAR#TASK_CARGO_CSAR}: Defines a task for a human player to Search and Rescue wounded pilots. +-- * @{Tasking.Task_CARGO_CSAR#TASK_CARGO_CSAR}: Defines a task for a human player to Search and Rescue wounded pilots. -- -- However! The menu system and basic usage of the TASK_CARGO classes is explained in the @{#TASK_CARGO} class description. -- So please browse further below to understand how to use it from a player perspective! @@ -387,9 +387,9 @@ -- -- Please consult the documentation how to implement the derived classes of SET_CARGO in: -- --- - @{Tasking.Task_Cargo#TASK_CARGO}: Documents the main methods how to handle the cargo tasking from a mission designer perspective. --- - @{Tasking.Task_Cargo#TASK_CARGO_TRANSPORT}: Documents the specific methods how to handle the cargo transportation tasking from a mission designer perspective. --- - @{Tasking.Task_Cargo#TASK_CARGO_CSAR}: Documents the specific methods how to handle the cargo CSAR tasking from a mission designer perspective. +-- - @{Tasking.Task_CARGO#TASK_CARGO}: Documents the main methods how to handle the cargo tasking from a mission designer perspective. +-- - @{Tasking.Task_CARGO#TASK_CARGO_TRANSPORT}: Documents the specific methods how to handle the cargo transportation tasking from a mission designer perspective. +-- - @{Tasking.Task_CARGO#TASK_CARGO_CSAR}: Documents the specific methods how to handle the cargo CSAR tasking from a mission designer perspective. -- -- -- === @@ -400,7 +400,7 @@ -- -- === -- --- @module Tasking.Task_Cargo +-- @module Tasking.Task_CARGO -- @image MOOSE.JPG do -- TASK_CARGO @@ -438,8 +438,8 @@ do -- TASK_CARGO -- -- ### 2.1.1) Cargo Tasks -- - -- - @{Tasking.Task_Cargo#TASK_CARGO_TRANSPORT} - Models the transportation of cargo to deployment zones. - -- - @{Tasking.Task_Cargo#TASK_CARGO_CSAR} - Models the rescue of downed friendly pilots from behind enemy lines. + -- - @{Tasking.Task_CARGO#TASK_CARGO_TRANSPORT} - Models the transportation of cargo to deployment zones. + -- - @{Tasking.Task_CARGO#TASK_CARGO_CSAR} - Models the rescue of downed friendly pilots from behind enemy lines. -- -- ## 2.2) Handle TASK_CARGO Events ... -- diff --git a/Moose Development/Moose/Tasking/Task_Capture_Dispatcher.lua b/Moose Development/Moose/Tasking/Task_Capture_Dispatcher.lua index e9b3954ac..87046e1ff 100644 --- a/Moose Development/Moose/Tasking/Task_Capture_Dispatcher.lua +++ b/Moose Development/Moose/Tasking/Task_Capture_Dispatcher.lua @@ -54,7 +54,7 @@ -- -- === -- --- @module Tasking.Task_Zone_Capture_Dispatcher +-- @module Tasking.Task_Capture_Dispatcher -- @image MOOSE.JPG do -- TASK_CAPTURE_DISPATCHER diff --git a/Moose Development/Moose/Tasking/Task_Capture_Zone.lua b/Moose Development/Moose/Tasking/Task_Capture_Zone.lua index 3ca128b98..9a7a30a9b 100644 --- a/Moose Development/Moose/Tasking/Task_Capture_Zone.lua +++ b/Moose Development/Moose/Tasking/Task_Capture_Zone.lua @@ -8,14 +8,14 @@ -- -- === -- --- @module Tasking.TaskZoneCapture +-- @module Tasking.Task_Capture_Zone -- @image MOOSE.JPG do -- TASK_ZONE_GOAL --- The TASK_ZONE_GOAL class -- @type TASK_ZONE_GOAL - -- @field Core.ZoneGoal#ZONE_GOAL ZoneGoal + -- @field Functional.ZoneGoal#ZONE_GOAL ZoneGoal -- @extends Tasking.Task#TASK --- # TASK_ZONE_GOAL class, extends @{Tasking.Task#TASK} @@ -47,7 +47,7 @@ do -- TASK_ZONE_GOAL -- @param Tasking.Mission#MISSION Mission -- @param Core.Set#SET_GROUP SetGroup The set of groups for which the Task can be assigned. -- @param #string TaskName The name of the Task. - -- @param Core.ZoneGoalCoalition#ZONE_GOAL_COALITION ZoneGoal + -- @param Functional.ZoneGoalCoalition#ZONE_GOAL_COALITION ZoneGoal -- @return #TASK_ZONE_GOAL self function TASK_ZONE_GOAL:New( Mission, SetGroup, TaskName, ZoneGoal, TaskType, TaskBriefing ) local self = BASE:Inherit( self, TASK:New( Mission, SetGroup, TaskName, TaskType, TaskBriefing ) ) -- #TASK_ZONE_GOAL @@ -115,10 +115,10 @@ do -- TASK_ZONE_GOAL end --- @param #TASK_ZONE_GOAL self - -- @param Core.ZoneGoal#ZONE_GOAL ZoneGoal The ZoneGoal Engine. + -- @param Functional.ZoneGoal#ZONE_GOAL ZoneGoal The ZoneGoal Engine. function TASK_ZONE_GOAL:SetProtect( ZoneGoal ) - self.ZoneGoal = ZoneGoal -- Core.ZoneGoal#ZONE_GOAL + self.ZoneGoal = ZoneGoal -- Functional.ZoneGoal#ZONE_GOAL end @@ -169,10 +169,10 @@ do -- TASK_CAPTURE_ZONE --- The TASK_CAPTURE_ZONE class -- @type TASK_CAPTURE_ZONE - -- @field Core.ZoneGoalCoalition#ZONE_GOAL_COALITION ZoneGoal + -- @field Functional.ZoneGoalCoalition#ZONE_GOAL_COALITION ZoneGoal -- @extends #TASK_ZONE_GOAL - --- # TASK_CAPTURE_ZONE class, extends @{Tasking.TaskZoneGoal#TASK_ZONE_GOAL} + --- # TASK_CAPTURE_ZONE class, extends @{Tasking.Task_Capture_Zone#TASK_ZONE_GOAL} -- -- The TASK_CAPTURE_ZONE class defines an Suppression or Extermination of Air Defenses task for a human player to be executed. -- These tasks are important to be executed as they will help to achieve air superiority at the vicinity. @@ -191,7 +191,7 @@ do -- TASK_CAPTURE_ZONE -- @param Tasking.Mission#MISSION Mission -- @param Core.Set#SET_GROUP SetGroup The set of groups for which the Task can be assigned. -- @param #string TaskName The name of the Task. - -- @param Core.ZoneGoalCoalition#ZONE_GOAL_COALITION ZoneGoalCoalition + -- @param Functional.ZoneGoalCoalition#ZONE_GOAL_COALITION ZoneGoalCoalition -- @param #string TaskBriefing The briefing of the task. -- @return #TASK_CAPTURE_ZONE self function TASK_CAPTURE_ZONE:New( Mission, SetGroup, TaskName, ZoneGoalCoalition, TaskBriefing) diff --git a/Moose Development/Moose/Tasking/Task_Cargo_CSAR.lua b/Moose Development/Moose/Tasking/Task_Cargo_CSAR.lua index 7b099980f..c48c27a22 100644 --- a/Moose Development/Moose/Tasking/Task_Cargo_CSAR.lua +++ b/Moose Development/Moose/Tasking/Task_Cargo_CSAR.lua @@ -1,4 +1,4 @@ ---- **Tasking** -- Orchestrates the task for players to execute CSAR for downed pilots. +--- **Tasking** - Orchestrates the task for players to execute CSAR for downed pilots. -- -- **Specific features:** -- @@ -44,7 +44,7 @@ -- -- === -- --- Please read through the @{Tasking.Task_Cargo} process to understand the mechanisms of tasking and cargo tasking and handling. +-- Please read through the @{Tasking.Task_CARGO} process to understand the mechanisms of tasking and cargo tasking and handling. -- -- The cargo will be a downed pilot, which is located somwhere on the battlefield. Use the menus system and facilities to -- join the CSAR task, and retrieve the pilot from behind enemy lines. The menu system is generic, there is nothing diff --git a/Moose Development/Moose/Tasking/Task_Cargo_Transport.lua b/Moose Development/Moose/Tasking/Task_Cargo_Transport.lua index 8629871b2..25bcb2c9c 100644 --- a/Moose Development/Moose/Tasking/Task_Cargo_Transport.lua +++ b/Moose Development/Moose/Tasking/Task_Cargo_Transport.lua @@ -1,4 +1,4 @@ ---- **Tasking** -- Models tasks for players to transport cargo. +--- **Tasking** - Models tasks for players to transport cargo. -- -- **Specific features:** -- diff --git a/Moose Development/Moose/Tasking/Task_Manager.lua b/Moose Development/Moose/Tasking/Task_Manager.lua index e4f4ee9a7..b65694dfd 100644 --- a/Moose Development/Moose/Tasking/Task_Manager.lua +++ b/Moose Development/Moose/Tasking/Task_Manager.lua @@ -1,4 +1,4 @@ ---- This module contains the TASK_MANAGER class and derived classes. +--- **Tasking** - This module contains the TASK_MANAGER class and derived classes. -- -- === -- @@ -33,7 +33,7 @@ -- @image MOOSE.JPG do -- TASK_MANAGER - + --- TASK_MANAGER class. -- @type TASK_MANAGER -- @field Core.Set#SET_GROUP SetGroup The set of group objects containing players for which tasks are managed. @@ -42,21 +42,21 @@ do -- TASK_MANAGER ClassName = "TASK_MANAGER", SetGroup = nil, } - + --- TASK\_MANAGER constructor. -- @param #TASK_MANAGER self -- @param Core.Set#SET_GROUP SetGroup The set of group objects containing players for which tasks are managed. -- @return #TASK_MANAGER self function TASK_MANAGER:New( SetGroup ) - + -- Inherits from BASE local self = BASE:Inherit( self, FSM:New() ) -- #TASK_MANAGER - + self.SetGroup = SetGroup - + self:SetStartState( "Stopped" ) self:AddTransition( "Stopped", "StartTasks", "Started" ) - + --- StartTasks Handler OnBefore for TASK_MANAGER -- @function [parent=#TASK_MANAGER] OnBeforeStartTasks -- @param #TASK_MANAGER self @@ -64,27 +64,25 @@ do -- TASK_MANAGER -- @param #string Event -- @param #string To -- @return #boolean - + --- StartTasks Handler OnAfter for TASK_MANAGER -- @function [parent=#TASK_MANAGER] OnAfterStartTasks -- @param #TASK_MANAGER self -- @param #string From -- @param #string Event -- @param #string To - + --- StartTasks Trigger for TASK_MANAGER -- @function [parent=#TASK_MANAGER] StartTasks -- @param #TASK_MANAGER self - + --- StartTasks Asynchronous Trigger for TASK_MANAGER -- @function [parent=#TASK_MANAGER] __StartTasks -- @param #TASK_MANAGER self -- @param #number Delay - - - + self:AddTransition( "Started", "StopTasks", "Stopped" ) - + --- StopTasks Handler OnBefore for TASK_MANAGER -- @function [parent=#TASK_MANAGER] OnBeforeStopTasks -- @param #TASK_MANAGER self @@ -92,28 +90,27 @@ do -- TASK_MANAGER -- @param #string Event -- @param #string To -- @return #boolean - + --- StopTasks Handler OnAfter for TASK_MANAGER -- @function [parent=#TASK_MANAGER] OnAfterStopTasks -- @param #TASK_MANAGER self -- @param #string From -- @param #string Event -- @param #string To - + --- StopTasks Trigger for TASK_MANAGER -- @function [parent=#TASK_MANAGER] StopTasks -- @param #TASK_MANAGER self - + --- StopTasks Asynchronous Trigger for TASK_MANAGER -- @function [parent=#TASK_MANAGER] __StopTasks -- @param #TASK_MANAGER self -- @param #number Delay - self:AddTransition( "Started", "Manage", "Started" ) self:AddTransition( "Started", "Success", "Started" ) - + --- Success Handler OnAfter for TASK_MANAGER -- @function [parent=#TASK_MANAGER] OnAfterSuccess -- @param #TASK_MANAGER self @@ -121,10 +118,9 @@ do -- TASK_MANAGER -- @param #string Event -- @param #string To -- @param Tasking.Task#TASK Task - - + self:AddTransition( "Started", "Failed", "Started" ) - + --- Failed Handler OnAfter for TASK_MANAGER -- @function [parent=#TASK_MANAGER] OnAfterFailed -- @param #TASK_MANAGER self @@ -132,10 +128,9 @@ do -- TASK_MANAGER -- @param #string Event -- @param #string To -- @param Tasking.Task#TASK Task - - + self:AddTransition( "Started", "Aborted", "Started" ) - + --- Aborted Handler OnAfter for TASK_MANAGER -- @function [parent=#TASK_MANAGER] OnAfterAborted -- @param #TASK_MANAGER self @@ -143,9 +138,9 @@ do -- TASK_MANAGER -- @param #string Event -- @param #string To -- @param Tasking.Task#TASK Task - + self:AddTransition( "Started", "Cancelled", "Started" ) - + --- Cancelled Handler OnAfter for TASK_MANAGER -- @function [parent=#TASK_MANAGER] OnAfterCancelled -- @param #TASK_MANAGER self @@ -155,37 +150,37 @@ do -- TASK_MANAGER -- @param Tasking.Task#TASK Task self:SetRefreshTimeInterval( 30 ) - + return self end - + function TASK_MANAGER:onafterStartTasks( From, Event, To ) self:Manage() end - + function TASK_MANAGER:onafterManage( From, Event, To ) self:__Manage( -self._RefreshTimeInterval ) self:ManageTasks() end - + --- Set the refresh time interval in seconds when a new task management action needs to be done. -- @param #TASK_MANAGER self -- @param #number RefreshTimeInterval The refresh time interval in seconds when a new task management action needs to be done. -- @return #TASK_MANAGER self function TASK_MANAGER:SetRefreshTimeInterval( RefreshTimeInterval ) self:F2() - + self._RefreshTimeInterval = RefreshTimeInterval end - - + + --- Manages the tasks for the @{Core.Set#SET_GROUP}. -- @param #TASK_MANAGER self -- @return #TASK_MANAGER self function TASK_MANAGER:ManageTasks() - + end end diff --git a/Moose Development/Moose/Utilities/Enums.lua b/Moose Development/Moose/Utilities/Enums.lua index 18d959928..63f3d6187 100644 --- a/Moose Development/Moose/Utilities/Enums.lua +++ b/Moose Development/Moose/Utilities/Enums.lua @@ -13,7 +13,7 @@ -- -- Other Moose classes also have enumerators. For example, the AIRBASE class has enumerators for airbase names. -- --- @module ENUMS +-- @module Utilities.Enums -- @image MOOSE.JPG --- [DCS Enum world](https://wiki.hoggitworld.com/view/DCS_enum_world) diff --git a/Moose Development/Moose/Utilities/FiFo.lua b/Moose Development/Moose/Utilities/FiFo.lua index 323cc7526..c1d604e4f 100644 --- a/Moose Development/Moose/Utilities/FiFo.lua +++ b/Moose Development/Moose/Utilities/FiFo.lua @@ -1,4 +1,4 @@ ---- **UTILS** - ClassicFiFo Stack. +--- **UTILS** - Classic FiFo Stack. -- -- === -- @@ -10,7 +10,7 @@ -- === -- -- ### Author: **applevangelist** --- @module Utils.FiFo +-- @module Utilities.FiFo -- @image MOOSE.JPG -- Date: April 2022 diff --git a/Moose Development/Moose/Utilities/Profiler.lua b/Moose Development/Moose/Utilities/Profiler.lua index 66240179d..821ab6672 100644 --- a/Moose Development/Moose/Utilities/Profiler.lua +++ b/Moose Development/Moose/Utilities/Profiler.lua @@ -6,7 +6,7 @@ -- -- ### Author: **TAW CougarNL**, *funkyfranky* -- --- @module Utilities.PROFILER +-- @module Utilities.Profiler -- @image Utils_Profiler.jpg --- PROFILER class. @@ -34,11 +34,11 @@ -- # The PROFILER Concept -- -- Profile your lua code. This tells you, which functions are called very often and which consume most real time. --- With this information you can optimize the perfomance of your code. +-- With this information you can optimize the performance of your code. -- -- # Prerequisites -- --- The modules **os**, **io** and **lfs** need to be desanizied. Comment out the lines +-- The modules **os**, **io** and **lfs** need to be de-sanitized. Comment out the lines -- -- --sanitizeModule('os') -- --sanitizeModule('io') diff --git a/Moose Development/Moose/Utilities/Routines.lua b/Moose Development/Moose/Utilities/Routines.lua index 926c8686d..8545a1dd7 100644 --- a/Moose Development/Moose/Utilities/Routines.lua +++ b/Moose Development/Moose/Utilities/Routines.lua @@ -1,5 +1,5 @@ ---- Various routines --- @module routines +--- **Utilities** - Various routines. +-- @module Utilities.Routines -- @image MOOSE.JPG env.setErrorMessageBoxEnabled( false ) diff --git a/Moose Development/Moose/Utilities/STTS.lua b/Moose Development/Moose/Utilities/STTS.lua index 36aa2cc43..1a27696f1 100644 --- a/Moose Development/Moose/Utilities/STTS.lua +++ b/Moose Development/Moose/Utilities/STTS.lua @@ -1,7 +1,7 @@ ---- **Utilities** DCS Simple Text-To-Speech (STTS). +--- **Utilities** - DCS Simple Text-To-Speech (STTS). -- -- --- @module Utils.STTS +-- @module Utilities.STTS -- @image MOOSE.JPG --- [DCS Enum world](https://wiki.hoggitworld.com/view/DCS_enum_world) diff --git a/Moose Development/Moose/Utilities/Socket.lua b/Moose Development/Moose/Utilities/Socket.lua index a5626600e..4729fcfbb 100644 --- a/Moose Development/Moose/Utilities/Socket.lua +++ b/Moose Development/Moose/Utilities/Socket.lua @@ -11,7 +11,7 @@ -- -- ### Author: **funkyfranky** -- @module Utilities.Socket --- @image Utilities_Socket.png +-- @image MOOSE.JPG --- SOCKET class. @@ -58,7 +58,7 @@ SOCKET.DataType={ --- SOCKET class version. -- @field #string version -SOCKET.version="0.1.0" +SOCKET.version="0.2.0" ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- TODO list @@ -121,6 +121,10 @@ end -- @return #SOCKET self function SOCKET:SendTable(Table) + -- Add server name for DCS + Table.server_name=BASE.ServerName or "Unknown" + + -- Encode json table. local json= self.json:encode(Table) -- Debug info. diff --git a/Moose Development/Moose/Utilities/Templates.lua b/Moose Development/Moose/Utilities/Templates.lua index 182925689..52a648a9a 100644 --- a/Moose Development/Moose/Utilities/Templates.lua +++ b/Moose Development/Moose/Utilities/Templates.lua @@ -1,4 +1,4 @@ ---- **Utils** Templates +--- **Utilities** - Templates. -- -- DCS unit templates -- diff --git a/Moose Development/Moose/Utilities/Utils.lua b/Moose Development/Moose/Utilities/Utils.lua index da6e66988..df656431b 100644 --- a/Moose Development/Moose/Utilities/Utils.lua +++ b/Moose Development/Moose/Utilities/Utils.lua @@ -1,4 +1,4 @@ ---- This module contains derived utilities taken from the MIST framework, as well as a lot of added helpers from the MOOSE community. +--- **Utilities** - Derived utilities taken from the MIST framework, added helpers from the MOOSE community. -- -- ### Authors: -- @@ -9,7 +9,7 @@ -- * FlightControl : Rework to OO framework. -- * And many more -- --- @module Utils +-- @module Utilities.Utils -- @image MOOSE.JPG @@ -606,10 +606,12 @@ end -- acc- the accuracy of each easting/northing. 0, 1, 2, 3, 4, or 5. UTILS.tostringMGRS = function(MGRS, acc) --R2.1 - if acc == 0 then + if acc <= 0 then return MGRS.UTMZone .. ' ' .. MGRS.MGRSDigraph else - + + if acc > 5 then acc = 5 end + -- Test if Easting/Northing have less than 4 digits. --MGRS.Easting=123 -- should be 00123 --MGRS.Northing=5432 -- should be 05432 @@ -740,7 +742,9 @@ function UTILS.RemoveMark(MarkID, Delay) if Delay and Delay>0 then TIMER:New(UTILS.RemoveMark, MarkID):Start(Delay) else - trigger.action.removeMark(MarkID) + if MarkID then + trigger.action.removeMark(MarkID) + end end end @@ -1062,9 +1066,13 @@ end -- @return #number Distance between the vectors. function UTILS.VecDist2D(a, b) + local d = math.huge + + if (not a) or (not b) then return d end + local c={x=b.x-a.x, y=b.y-a.y} - local d=math.sqrt(c.x*c.x+c.y*c.y) + d=math.sqrt(c.x*c.x+c.y*c.y) return d end @@ -1075,10 +1083,15 @@ end -- @param DCS#Vec3 b Vector in 3D with x, y, z components. -- @return #number Distance between the vectors. function UTILS.VecDist3D(a, b) - + + + local d = math.huge + + if (not a) or (not b) then return d end + local c={x=b.x-a.x, y=b.y-a.y, z=b.z-a.z} - local d=math.sqrt(UTILS.VecDot(c, c)) + d=math.sqrt(UTILS.VecDot(c, c)) return d end @@ -1412,7 +1425,7 @@ function UTILS.CheckMemory(output) end ---- Get the coalition name from its numerical ID, e.g. coaliton.side.RED. +--- Get the coalition name from its numerical ID, e.g. coalition.side.RED. -- @param #number Coalition The coalition ID. -- @return #string The coalition name, i.e. "Neutral", "Red" or "Blue" (or "Unknown"). function UTILS.GetCoalitionName(Coalition) @@ -2006,6 +2019,28 @@ function UTILS.GenerateLaserCodes() return jtacGeneratedLaserCodes end +--- Ensure the passed object is a table. +-- @param #table Object The object that should be a table. +-- @param #boolean ReturnNil If `true`, return `#nil` if `Object` is nil. Otherwise an empty table `{}` is returned. +-- @return #table The object that now certainly *is* a table. +function UTILS.EnsureTable(Object, ReturnNil) + + if Object then + if type(Object)~="table" then + Object={Object} + end + else + if ReturnNil then + return nil + else + Object={} + end + + end + + return Object +end + --- Function to save an object to a file -- @param #string Path The path to use. Use double backslashes \\\\ on Windows filesystems. -- @param #string Filename The name of the file. Existing file will be overwritten. diff --git a/Moose Development/Moose/Wrapper/Airbase.lua b/Moose Development/Moose/Wrapper/Airbase.lua index 4ef5d9731..f4f658477 100644 --- a/Moose Development/Moose/Wrapper/Airbase.lua +++ b/Moose Development/Moose/Wrapper/Airbase.lua @@ -1,4 +1,4 @@ ---- **Wrapper** -- AIRBASE is a wrapper class to handle the DCS Airbase objects. +--- **Wrapper** - AIRBASE is a wrapper class to handle the DCS Airbase objects. -- -- === -- @@ -39,7 +39,7 @@ -- -- ## AIRBASE reference methods -- --- For each DCS Airbase object alive within a running mission, a AIRBASE wrapper object (instance) will be created within the _@{DATABASE} object. +-- For each DCS Airbase object alive within a running mission, a AIRBASE wrapper object (instance) will be created within the global _DATABASE object (an instance of @{Core.Database#DATABASE}). -- This is done at the beginning of the mission (when the mission starts). -- -- The AIRBASE class **does not contain a :New()** method, rather it provides **:Find()** methods to retrieve the object reference @@ -51,8 +51,8 @@ -- -- The AIRBASE class provides the following functions to retrieve quickly the relevant AIRBASE instance: -- --- * @{#AIRBASE.Find}(): Find a AIRBASE instance from the _DATABASE object using a DCS Airbase object. --- * @{#AIRBASE.FindByName}(): Find a AIRBASE instance from the _DATABASE object using a DCS Airbase name. +-- * @{#AIRBASE.Find}(): Find a AIRBASE instance from the global _DATABASE object (an instance of @{Core.Database#DATABASE}) using a DCS Airbase object. +-- * @{#AIRBASE.FindByName}(): Find a AIRBASE instance from the global _DATABASE object (an instance of @{Core.Database#DATABASE}) using a DCS Airbase name. -- -- IMPORTANT: ONE SHOULD NEVER SANITIZE these AIRBASE OBJECT REFERENCES! (make the AIRBASE object references nil). -- @@ -504,6 +504,12 @@ AIRBASE.MarianaIslands = { -- * AIRBASE.SouthAtlantic.Puerto_Williams -- * AIRBASE.SouthAtlantic.Puerto_Natales -- * AIRBASE.SouthAtlantic.El_Calafate +-- * AIRBASE.SouthAtlantic.Puerto_Santa_Cruz +-- * AIRBASE.SouthAtlantic.Comandante_Luis_Piedrabuena +-- * AIRBASE.SouthAtlantic.Aerodromo_De_Tolhuin +-- * AIRBASE.SouthAtlantic.Porvenir_Airfield +-- * AIRBASE.SouthAtlantic.Almirante_Schroeders +-- * AIRBASE.SouthAtlantic.Rio_Turbio -- --@field MarianaIslands AIRBASE.SouthAtlantic={ @@ -520,6 +526,12 @@ AIRBASE.SouthAtlantic={ ["Puerto_Williams"]="Puerto Williams", ["Puerto_Natales"]="Puerto Natales", ["El_Calafate"]="El Calafate", + ["Puerto_Santa_Cruz"]="Puerto Santa Cruz", + ["Comandante_Luis_Piedrabuena"]="Comandante Luis Piedrabuena", + ["Aerodromo_De_Tolhuin"]="Aerodromo De Tolhuin", + ["Porvenir_Airfield"]="Porvenir Airfield", + ["Almirante_Schroeders"]="Almirante Schroeders", + ["Rio_Turbio"]="Rio Turbio", } --- AIRBASE.ParkingSpot ".Coordinate, ".TerminalID", ".TerminalType", ".TOAC", ".Free", ".TerminalID0", ".DistToRwy". diff --git a/Moose Development/Moose/Wrapper/Client.lua b/Moose Development/Moose/Wrapper/Client.lua index 529accdcf..12f2baa13 100644 --- a/Moose Development/Moose/Wrapper/Client.lua +++ b/Moose Development/Moose/Wrapper/Client.lua @@ -1,4 +1,4 @@ ---- **Wrapper** -- CLIENT wraps DCS Unit objects acting as a __Client__ or __Player__ within a mission. +--- **Wrapper** - CLIENT wraps DCS Unit objects acting as a __Client__ or __Player__ within a mission. -- -- === -- @@ -39,11 +39,11 @@ -- * Handles messages to players. -- * Manage the "state" of the DCS Unit. -- --- Clients are being used by the @{MISSION} class to follow players and register their successes. +-- Clients are being used by the @{Tasking.Mission#MISSION} class to follow players and register their successes. -- -- ## CLIENT reference methods -- --- For each DCS Unit having skill level Player or Client, a CLIENT wrapper object (instance) will be created within the _@{DATABASE} object. +-- For each DCS Unit having skill level Player or Client, a CLIENT wrapper object (instance) will be created within the global _DATABASE object (an instance of @{Core.Database#DATABASE}). -- This is done at the beginning of the mission (when the mission starts). -- -- The CLIENT class does not contain a :New() method, rather it provides :Find() methods to retrieve the object reference @@ -55,10 +55,10 @@ -- -- The CLIENT class provides the following functions to retrieve quickly the relevant CLIENT instance: -- --- * @{#CLIENT.Find}(): Find a CLIENT instance from the _DATABASE object using a DCS Unit object. --- * @{#CLIENT.FindByName}(): Find a CLIENT instance from the _DATABASE object using a DCS Unit name. +-- * @{#CLIENT.Find}(): Find a CLIENT instance from the global _DATABASE object (an instance of @{Core.Database#DATABASE}) using a DCS Unit object. +-- * @{#CLIENT.FindByName}(): Find a CLIENT instance from the global _DATABASE object (an instance of @{Core.Database#DATABASE}) using a DCS Unit name. -- --- **IMPORTANT: ONE SHOULD NEVER SANATIZE these CLIENT OBJECT REFERENCES! (make the CLIENT object references nil).** +-- **IMPORTANT: ONE SHOULD NEVER SANITIZE these CLIENT OBJECT REFERENCES! (make the CLIENT object references nil).** -- -- @field #CLIENT CLIENT = { diff --git a/Moose Development/Moose/Wrapper/Controllable.lua b/Moose Development/Moose/Wrapper/Controllable.lua index e5a165ea1..95c8c4ade 100644 --- a/Moose Development/Moose/Wrapper/Controllable.lua +++ b/Moose Development/Moose/Wrapper/Controllable.lua @@ -1,4 +1,4 @@ ---- **Wrapper** -- CONTROLLABLE is an intermediate class wrapping Group and Unit classes "controllers". +--- **Wrapper** - CONTROLLABLE is an intermediate class wrapping Group and Unit classes "controllers". -- -- === -- @@ -32,7 +32,7 @@ -- # 2) CONTROLLABLE Task methods -- -- Several controllable task methods are available that help you to prepare tasks. --- These methods return a string consisting of the task description, which can then be given to either a @{Wrapper.Controllable#CONTROLLABLE.PushTask} or @{Wrapper.Controllable#SetTask} method to assign the task to the CONTROLLABLE. +-- These methods return a string consisting of the task description, which can then be given to either a @{#CONTROLLABLE.PushTask}() or @{#CONTROLLABLE.SetTask}() method to assign the task to the CONTROLLABLE. -- Tasks are specific for the category of the CONTROLLABLE, more specific, for AIR, GROUND or AIR and GROUND. -- Each task description where applicable indicates for which controllable category the task is valid. -- There are 2 main subdivisions of tasks: Assigned tasks and EnRoute tasks. @@ -62,6 +62,7 @@ -- * @{#CONTROLLABLE.TaskOrbitCircle}: (AIR) Orbit at the current position of the first unit of the controllable at a specified altitude. -- * @{#CONTROLLABLE.TaskOrbitCircleAtVec2}: (AIR) Orbit at a specified position at a specified altitude during a specified duration with a specified speed. -- * @{#CONTROLLABLE.TaskRefueling}: (AIR) Refueling from the nearest tanker. No parameters. +-- * @{#CONTROLLABLE.TaskRecoveryTanker}: (AIR) Set group to act as recovery tanker for a naval group. -- * @{#CONTROLLABLE.TaskRoute}: (AIR + GROUND) Return a Mission task to follow a given route defined by Points. -- * @{#CONTROLLABLE.TaskRouteToVec2}: (AIR + GROUND) Make the Controllable move to a given point. -- * @{#CONTROLLABLE.TaskRouteToVec3}: (AIR + GROUND) Make the Controllable move to a given point. @@ -318,7 +319,7 @@ end --- Popping current Task from the controllable. -- @param #CONTROLLABLE self --- @return Wrapper.Controllable#CONTROLLABLE self +-- @return #CONTROLLABLE self function CONTROLLABLE:PopCurrentTask() self:F2() @@ -335,7 +336,7 @@ end --- Pushing Task on the queue from the controllable. -- @param #CONTROLLABLE self --- @return Wrapper.Controllable#CONTROLLABLE self +-- @return #CONTROLLABLE self function CONTROLLABLE:PushTask( DCSTask, WaitTime ) self:F2() @@ -374,7 +375,7 @@ end -- @param #CONTROLLABLE self -- @param DCS#Task DCSTask DCS Task array. -- @param #number WaitTime Time in seconds, before the task is set. --- @return Wrapper.Controllable#CONTROLLABLE self +-- @return #CONTROLLABLE self function CONTROLLABLE:SetTask( DCSTask, WaitTime ) self:F( { "SetTask", WaitTime, DCSTask = DCSTask } ) @@ -418,7 +419,7 @@ end --- Checking the Task Queue of the controllable. Returns false if no task is on the queue. true if there is a task. -- @param #CONTROLLABLE self --- @return Wrapper.Controllable#CONTROLLABLE self +-- @return #CONTROLLABLE self function CONTROLLABLE:HasTask() -- R2.2 local HasTaskResult = false @@ -627,8 +628,8 @@ end -- For specific beacons like TACAN use the more convenient @{#BEACON} class. -- Note that a controllable can only have one beacon activated at a time with the execption of ICLS. -- @param #CONTROLLABLE self --- @param Core.Radio#BEACON.Type Type Beacon type (VOR, DME, TACAN, RSBN, ILS etc). --- @param Core.Radio#BEACON.System System Beacon system (VOR, DME, TACAN, RSBN, ILS etc). +-- @param Core.Beacon#BEACON.Type Type Beacon type (VOR, DME, TACAN, RSBN, ILS etc). +-- @param Core.Beacon#BEACON.System System Beacon system (VOR, DME, TACAN, RSBN, ILS etc). -- @param #number Frequency Frequency in Hz the beacon is running on. Use @{#UTILS.TACANToFrequency} to generate a frequency for TACAN beacons. -- @param #number UnitID The ID of the unit the beacon is attached to. Useful if more units are in one group. -- @param #number Channel Channel the beacon is using. For, e.g. TACAN beacons. @@ -1367,6 +1368,31 @@ function CONTROLLABLE:TaskRefueling() return DCSTask end +--- (AIR) Act as Recovery Tanker for a naval/carrier group. +-- @param #CONTROLLABLE self +-- @param Wrapper.Group#GROUP CarrierGroup +-- @param #number Speed Speed in meters per second +-- @param #number Altitude Altitude the tanker orbits at in meters +-- @param #number LastWptNumber (optional) Waypoint of carrier group that when reached, ends the recovery tanker task +-- @return DCS#Task The DCS task structure. +function CONTROLLABLE:TaskRecoveryTanker(CarrierGroup, Speed, Altitude, LastWptNumber) + + local LastWptFlag = type(LastWptNumber) == "number" and true or false + + local DCSTask = { + id = "RecoveryTanker", + params = { + groupId = CarrierGroup:GetID(), + speed = Speed, + altitude = Altitude, + lastWptIndexFlag = LastWptFlag, + lastWptIndex = LastWptNumber + } + } + + return DCSTask +end + --- (AIR HELICOPTER) Landing at the ground. For helicopters only. -- @param #CONTROLLABLE self -- @param DCS#Vec2 Vec2 The point where to land. @@ -1405,7 +1431,7 @@ end -- The unit / controllable will follow lead unit of another controllable, wingmens of both controllables will continue following their leaders. -- If another controllable is on land the unit / controllable will orbit around. -- @param #CONTROLLABLE self --- @param Wrapper.Controllable#CONTROLLABLE FollowControllable The controllable to be followed. +-- @param #CONTROLLABLE FollowControllable The controllable to be followed. -- @param DCS#Vec3 Vec3 Position of the unit / lead unit of the controllable relative lead unit of another controllable in frame reference oriented by course of lead unit of another controllable. If another controllable is on land the unit / controllable will orbit around. -- @param #number LastWaypointIndex Detach waypoint of another controllable. Once reached the unit / controllable Follow task is finished. -- @return DCS#Task The DCS task structure. @@ -1448,7 +1474,7 @@ end -- The unit / controllable will follow lead unit of another controllable, wingmens of both controllables will continue following their leaders. -- The unit / controllable will also protect that controllable from threats of specified types. -- @param #CONTROLLABLE self --- @param Wrapper.Controllable#CONTROLLABLE FollowControllable The controllable to be escorted. +-- @param #CONTROLLABLE FollowControllable The controllable to be escorted. -- @param DCS#Vec3 Vec3 Position of the unit / lead unit of the controllable relative lead unit of another controllable in frame reference oriented by course of lead unit of another controllable. If another controllable is on land the unit / controllable will orbit around. -- @param #number LastWaypointIndex Detach waypoint of another controllable. Once reached the unit / controllable Follow task is finished. -- @param #number EngagementDistance Maximal distance from escorted controllable to threat. If the threat is already engaged by escort escort will disengage if the distance becomes greater than 1.5 * engagementDistMax. @@ -1642,7 +1668,7 @@ end --- (AIR) Engaging a controllable. The task does not assign the target controllable to the unit/controllable to attack now; it just allows the unit/controllable to engage the target controllable as well as other assigned targets. -- @param #CONTROLLABLE self --- @param Wrapper.Controllable#CONTROLLABLE AttackGroup The Controllable to be attacked. +-- @param #CONTROLLABLE AttackGroup The Controllable to be attacked. -- @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. -- @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. @@ -1770,7 +1796,7 @@ 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 #CONTROLLABLE AttackGroup Target CONTROLLABLE. -- @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 is 0. -- @param #number WeaponType (Optional) Bitmask of weapon types those allowed to use. Default is "Auto". -- @param DCS#AI.Task.Designation Designation (Optional) Designation type. @@ -2281,7 +2307,7 @@ do -- Route methods -- @param #number Speed (optional) Speed in km/h. The default speed is 20 km/h. -- @param #string Formation (optional) The route point Formation, which is a text string that specifies exactly the Text in the Type of the route point, like "Vee", "Echelon Right". -- @param #number DelaySeconds Wait for the specified seconds before executing the Route. - -- @param #function WaypointFunction (Optional) Function called when passing a waypoint. First parameters of the function are the @{CONTROLLABLE} object, the number of the waypoint and the total number of waypoints. + -- @param #function WaypointFunction (Optional) Function called when passing a waypoint. First parameters of the function are the @{#CONTROLLABLE} object, the number of the waypoint and the total number of waypoints. -- @param #table WaypointFunctionArguments (Optional) List of parameters passed to the *WaypointFunction*. -- @return #CONTROLLABLE The CONTROLLABLE. function CONTROLLABLE:RouteGroundTo( ToCoordinate, Speed, Formation, DelaySeconds, WaypointFunction, WaypointFunctionArguments ) @@ -2315,7 +2341,7 @@ do -- Route methods -- @param #number Speed (Optional) Speed in km/h. The default speed is 20 km/h. -- @param #number DelaySeconds (Optional) Wait for the specified seconds before executing the Route. Default is one second. -- @param #string OffRoadFormation (Optional) The formation at initial and final waypoint. Default is "Off Road". - -- @param #function WaypointFunction (Optional) Function called when passing a waypoint. First parameters of the function are the @{CONTROLLABLE} object, the number of the waypoint and the total number of waypoints. + -- @param #function WaypointFunction (Optional) Function called when passing a waypoint. First parameters of the function are the @{#CONTROLLABLE} object, the number of the waypoint and the total number of waypoints. -- @param #table WaypointFunctionArguments (Optional) List of parameters passed to the *WaypointFunction*. -- @return #CONTROLLABLE The CONTROLLABLE. function CONTROLLABLE:RouteGroundOnRoad( ToCoordinate, Speed, DelaySeconds, OffRoadFormation, WaypointFunction, WaypointFunctionArguments ) @@ -2339,7 +2365,7 @@ do -- Route methods -- @param Core.Point#COORDINATE ToCoordinate A Coordinate to drive to. -- @param #number Speed (Optional) Speed in km/h. The default speed is 20 km/h. -- @param #number DelaySeconds (Optional) Wait for the specified seconds before executing the Route. Default is one second. - -- @param #function WaypointFunction (Optional) Function called when passing a waypoint. First parameters of the function are the @{CONTROLLABLE} object, the number of the waypoint and the total number of waypoints. + -- @param #function WaypointFunction (Optional) Function called when passing a waypoint. First parameters of the function are the @{#CONTROLLABLE} object, the number of the waypoint and the total number of waypoints. -- @param #table WaypointFunctionArguments (Optional) List of parameters passed to the *WaypointFunction*. -- @return #CONTROLLABLE The CONTROLLABLE. function CONTROLLABLE:RouteGroundOnRailRoads( ToCoordinate, Speed, DelaySeconds, WaypointFunction, WaypointFunctionArguments ) @@ -2364,7 +2390,7 @@ do -- Route methods -- @param #string OffRoadFormation (Optional) The formation at initial and final waypoint. Default is "Off Road". -- @param #boolean Shortcut (Optional) If true, controllable will take the direct route if the path on road is 10x longer or path on road is less than 5% of total path. -- @param Core.Point#COORDINATE FromCoordinate (Optional) Explicit initial coordinate. Default is the position of the controllable. - -- @param #function WaypointFunction (Optional) Function called when passing a waypoint. First parameters of the function are the @{CONTROLLABLE} object, the number of the waypoint and the total number of waypoints. + -- @param #function WaypointFunction (Optional) Function called when passing a waypoint. First parameters of the function are the @{#CONTROLLABLE} object, the number of the waypoint and the total number of waypoints. -- @param #table WaypointFunctionArguments (Optional) List of parameters passed to the *WaypointFunction*. -- @return DCS#Task Task. -- @return #boolean If true, path on road is possible. If false, task will route the group directly to its destination. @@ -2467,7 +2493,7 @@ do -- Route methods -- @param #CONTROLLABLE self -- @param Core.Point#COORDINATE ToCoordinate A Coordinate to drive to. -- @param #number Speed (Optional) Speed in km/h. The default speed is 20 km/h. - -- @param #function WaypointFunction (Optional) Function called when passing a waypoint. First parameters of the function are the @{CONTROLLABLE} object, the number of the waypoint and the total number of waypoints. + -- @param #function WaypointFunction (Optional) Function called when passing a waypoint. First parameters of the function are the @{#CONTROLLABLE} object, the number of the waypoint and the total number of waypoints. -- @param #table WaypointFunctionArguments (Optional) List of parameters passed to the *WaypointFunction*. -- @return Task function CONTROLLABLE:TaskGroundOnRailRoads( ToCoordinate, Speed, WaypointFunction, WaypointFunctionArguments ) @@ -2748,7 +2774,7 @@ end --- Return the detected targets of the controllable. -- The optional parametes specify the detection methods that can be applied. -- If no detection method is given, the detection will use all the available methods by default. --- @param Wrapper.Controllable#CONTROLLABLE self +-- @param #CONTROLLABLE self -- @param #boolean DetectVisual (optional) -- @param #boolean DetectOptical (optional) -- @param #boolean DetectRadar (optional) @@ -2802,9 +2828,9 @@ end -- The optional parametes specify the detection methods that can be applied. -- If **no** detection method is given, the detection will use **all** the available methods by default. -- If **at least one** detection method is specified, only the methods set to *true* will be used. --- @param Wrapper.Controllable#CONTROLLABLE self +-- @param #CONTROLLABLE self -- @param DCS#Object DCSObject The DCS object that is checked. --- @param Wrapper.Controllable#CONTROLLABLE self +-- @param #CONTROLLABLE self -- @param #boolean DetectVisual (Optional) If *false*, do not include visually detected targets. -- @param #boolean DetectOptical (Optional) If *false*, do not include optically detected targets. -- @param #boolean DetectRadar (Optional) If *false*, do not include targets detected by radar. @@ -2910,7 +2936,7 @@ end -- The optional parametes specify the detection methods that can be applied. -- If **no** detection method is given, the detection will use **all** the available methods by default. -- If **at least one** detection method is specified, only the methods set to *true* will be used. --- @param Wrapper.Controllable#CONTROLLABLE self +-- @param #CONTROLLABLE self -- @param #boolean DetectVisual (Optional) If *false*, do not include visually detected targets. -- @param #boolean DetectOptical (Optional) If *false*, do not include optically detected targets. -- @param #boolean DetectRadar (Optional) If *false*, do not include targets detected by radar. @@ -2947,7 +2973,7 @@ end --- Return the detected target groups of the controllable as a @{Core.Set#SET_GROUP}. -- The optional parametes specify the detection methods that can be applied. -- If no detection method is given, the detection will use all the available methods by default. --- @param Wrapper.Controllable#CONTROLLABLE self +-- @param #CONTROLLABLE self -- @param #boolean DetectVisual (Optional) If *false*, do not include visually detected targets. -- @param #boolean DetectOptical (Optional) If *false*, do not include optically detected targets. -- @param #boolean DetectRadar (Optional) If *false*, do not include targets detected by radar. @@ -3004,7 +3030,7 @@ function CONTROLLABLE:SetOption( OptionID, OptionValue ) end --- Set option for Rules of Engagement (ROE). --- @param Wrapper.Controllable#CONTROLLABLE self +-- @param #CONTROLLABLE self -- @param #number ROEvalue ROE value. See ENUMS.ROE. -- @return #CONTROLLABLE self function CONTROLLABLE:OptionROE( ROEvalue ) @@ -3634,8 +3660,8 @@ function CONTROLLABLE:OptionECM_AlwaysOn() 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. --- Use the method @{Controllable@CONTROLLABLE:WayPointExecute) to start the execution of the new mission plan. +-- Use the method @{#CONTROLLABLE.WayPointFunction}() to define the hook functions for specific waypoints. +-- Use the method @{#CONTROLLABLE.WayPointExecute}() to start the execution of the new mission plan. -- Note that when WayPointInitialize is called, the Mission of the controllable is RESTARTED! -- @param #CONTROLLABLE self -- @param #table WayPoints If WayPoints is given, then use the route. diff --git a/Moose Development/Moose/Wrapper/Group.lua b/Moose Development/Moose/Wrapper/Group.lua index c12292433..08853948a 100644 --- a/Moose Development/Moose/Wrapper/Group.lua +++ b/Moose Development/Moose/Wrapper/Group.lua @@ -1,4 +1,4 @@ ---- **Wrapper** -- GROUP wraps the DCS Class Group objects. +--- **Wrapper** - GROUP wraps the DCS Class Group objects. -- -- === -- @@ -11,12 +11,12 @@ -- * Handle local Group Controller. -- * Manage the "state" of the DCS Group. -- --- **IMPORTANT: ONE SHOULD NEVER SANATIZE these GROUP OBJECT REFERENCES! (make the GROUP object references nil).** +-- **IMPORTANT: ONE SHOULD NEVER SANITIZE these GROUP OBJECT REFERENCES! (make the GROUP object references nil).** -- -- === -- --- For each DCS Group object alive within a running mission, a GROUP wrapper object (instance) will be created within the _@{DATABASE} object. --- This is done at the beginning of the mission (when the mission starts), and dynamically when new DCS Group objects are spawned (using the @{SPAWN} class). +-- For each DCS Group object alive within a running mission, a GROUP wrapper object (instance) will be created within the global _DATABASE object (an instance of @{Core.Database#DATABASE}). +-- This is done at the beginning of the mission (when the mission starts), and dynamically when new DCS Group objects are spawned (using the @{Core.Spawn} class). -- -- The GROUP class does not contain a :New() method, rather it provides :Find() methods to retrieve the object reference -- using the DCS Group or the DCS GroupName. @@ -47,8 +47,8 @@ -- -- The GROUP class provides the following functions to retrieve quickly the relevant GROUP instance: -- --- * @{#GROUP.Find}(): Find a GROUP instance from the _DATABASE object using a DCS Group object. --- * @{#GROUP.FindByName}(): Find a GROUP instance from the _DATABASE object using a DCS Group name. +-- * @{#GROUP.Find}(): Find a GROUP instance from the global _DATABASE object (an instance of @{Core.Database#DATABASE}) using a DCS Group object. +-- * @{#GROUP.FindByName}(): Find a GROUP instance from the global _DATABASE object (an instance of @{Core.Database#DATABASE}) using a DCS Group name. -- -- # 1. Tasking of groups -- @@ -132,14 +132,14 @@ -- -- ## GROUP Zone validation methods -- --- The group can be validated whether it is completely, partly or not within a @{Zone}. +-- The group can be validated whether it is completely, partly or not within a @{Core.Zone}. -- Use the following Zone validation methods on the group: -- --- * @{#GROUP.IsCompletelyInZone}: Returns true if all units of the group are within a @{Zone}. --- * @{#GROUP.IsPartlyInZone}: Returns true if some units of the group are within a @{Zone}. --- * @{#GROUP.IsNotInZone}: Returns true if none of the group units of the group are within a @{Zone}. +-- * @{#GROUP.IsCompletelyInZone}: Returns true if all units of the group are within a @{Core.Zone}. +-- * @{#GROUP.IsPartlyInZone}: Returns true if some units of the group are within a @{Core.Zone}. +-- * @{#GROUP.IsNotInZone}: Returns true if none of the group units of the group are within a @{Core.Zone}. -- --- The zone can be of any @{Zone} class derived from @{Core.Zone#ZONE_BASE}. So, these methods are polymorphic to the zones tested on. +-- The zone can be of any @{Core.Zone} class derived from @{Core.Zone#ZONE_BASE}. So, these methods are polymorphic to the zones tested on. -- -- ## GROUP AI methods -- @@ -1019,9 +1019,9 @@ function GROUP:GetVec2() end ---- Returns the current Vec3 vector of the first DCS Unit in the GROUP. +--- Returns the current Vec3 vector of the first Unit in the GROUP. -- @param #GROUP self --- @return DCS#Vec3 Current Vec3 of the first DCS Unit of the GROUP. +-- @return DCS#Vec3 Current Vec3 of the first Unit of the GROUP or nil if cannot be found. function GROUP:GetVec3() -- Get first unit. @@ -1036,6 +1036,37 @@ function GROUP:GetVec3() return nil end +--- Returns the average Vec3 vector of the Units in the GROUP. +-- @param #GROUP self +-- @return DCS#Vec3 Current Vec3 of the GROUP or nil if cannot be found. +function GROUP:GetAverageVec3() + local units = self:GetUnits() or {} + -- Init. + local x=0 ; local y=0 ; local z=0 ; local n=0 + -- Loop over all units. + for _,unit in pairs(units) do + local vec3=nil --DCS#Vec3 + if unit and unit:IsAlive() then + vec3 = unit:GetVec3() + end + if vec3 then + -- Sum up posits. + x=x+vec3.x + y=y+vec3.y + z=z+vec3.z + -- Increase counter. + n=n+1 + end + end + + if n>0 then + -- Average. + local Vec3={x=x/n, y=y/n, z=z/n} --DCS#Vec3 + return Vec3 + end + return nil +end + --- Returns a POINT_VEC2 object indicating the point in 2D of the first UNIT of the GROUP within the mission. -- @param #GROUP self -- @return Core.Point#POINT_VEC2 The 2D point vector of the first DCS Unit of the GROUP. @@ -1056,6 +1087,21 @@ function GROUP:GetPointVec2() return nil end +--- Returns a COORDINATE object indicating the average position of the GROUP within the mission. +-- @param Wrapper.Group#GROUP self +-- @return Core.Point#COORDINATE The COORDINATE of the GROUP. +function GROUP:GetAverageCoordinate() + local vec3 = self:GetAverageVec3() + if vec3 then + local coord = COORDINATE:NewFromVec3(vec3) + local Heading = self:GetHeading() + coord.Heading = Heading + else + BASE:E( { "Cannot GetAverageCoordinate", Group = self, Alive = self:IsAlive() } ) + return nil + end +end + --- Returns a COORDINATE object indicating the point of the first UNIT of the GROUP within the mission. -- @param Wrapper.Group#GROUP self -- @return Core.Point#COORDINATE The COORDINATE of the GROUP. @@ -1249,7 +1295,7 @@ end do -- Is Zone methods ---- Check if any unit of a group is inside a @{Zone}. +--- Check if any unit of a group is inside a @{Core.Zone}. -- @param #GROUP self -- @param Core.Zone#ZONE_BASE Zone The zone to test. -- @return #boolean Returns `true` if *at least one unit* is inside the zone or `false` if *no* unit is inside. @@ -1278,7 +1324,7 @@ function GROUP:IsInZone( Zone ) return nil end ---- Returns true if all units of the group are within a @{Zone}. +--- Returns true if all units of the group are within a @{Core.Zone}. -- @param #GROUP self -- @param Core.Zone#ZONE_BASE Zone The zone to test. -- @return #boolean Returns true if the Group is completely within the @{Core.Zone#ZONE_BASE} @@ -1298,7 +1344,7 @@ function GROUP:IsCompletelyInZone( Zone ) return true end ---- Returns true if some but NOT ALL units of the group are within a @{Zone}. +--- Returns true if some but NOT ALL units of the group are within a @{Core.Zone}. -- @param #GROUP self -- @param Core.Zone#ZONE_BASE Zone The zone to test. -- @return #boolean Returns true if the Group is partially within the @{Core.Zone#ZONE_BASE} @@ -1326,7 +1372,7 @@ function GROUP:IsPartlyInZone( Zone ) end end ---- Returns true if part or all units of the group are within a @{Zone}. +--- Returns true if part or all units of the group are within a @{Core.Zone}. -- @param #GROUP self -- @param Core.Zone#ZONE_BASE Zone The zone to test. -- @return #boolean Returns true if the Group is partially or completely within the @{Core.Zone#ZONE_BASE}. @@ -1334,7 +1380,7 @@ function GROUP:IsPartlyOrCompletelyInZone( Zone ) return self:IsPartlyInZone(Zone) or self:IsCompletelyInZone(Zone) end ---- Returns true if none of the group units of the group are within a @{Zone}. +--- Returns true if none of the group units of the group are within a @{Core.Zone}. -- @param #GROUP self -- @param Core.Zone#ZONE_BASE Zone The zone to test. -- @return #boolean Returns true if the Group is not within the @{Core.Zone#ZONE_BASE} @@ -1370,10 +1416,10 @@ function GROUP:IsAnyInZone( Zone ) return false end ---- Returns the number of UNITs that are in the @{Zone} +--- Returns the number of UNITs that are in the @{Core.Zone} -- @param #GROUP self -- @param Core.Zone#ZONE_BASE Zone The zone to test. --- @return #number The number of UNITs that are in the @{Zone} +-- @return #number The number of UNITs that are in the @{Core.Zone} function GROUP:CountInZone( Zone ) self:F2( {self.GroupName, Zone} ) local Count = 0 @@ -1630,7 +1676,7 @@ end -- RESPAWNING ---- Returns the group template from the @{DATABASE} (_DATABASE object). +--- Returns the group template from the global _DATABASE object (an instance of @{Core.Database#DATABASE}). -- @param #GROUP self -- @return #table function GROUP:GetTemplate() @@ -1638,7 +1684,7 @@ function GROUP:GetTemplate() return UTILS.DeepCopy( _DATABASE:GetGroupTemplate( GroupName ) ) end ---- Returns the group template route.points[] (the waypoints) from the @{DATABASE} (_DATABASE object). +--- Returns the group template route.points[] (the waypoints) from the global _DATABASE object (an instance of @{Core.Database#DATABASE}). -- @param #GROUP self -- @return #table function GROUP:GetTemplateRoutePoints() @@ -1696,7 +1742,7 @@ function GROUP:InitHeight( Height ) end ---- Set the respawn @{Zone} for the respawned group. +--- Set the respawn @{Core.Zone} for the respawned group. -- @param #GROUP self -- @param Core.Zone#ZONE Zone The zone in meters. -- @return #GROUP self @@ -1706,7 +1752,7 @@ function GROUP:InitZone( Zone ) end ---- Randomize the positions of the units of the respawned group within the @{Zone}. +--- Randomize the positions of the units of the respawned group within the @{Core.Zone}. -- When a Respawn happens, the units of the group will be placed at random positions within the Zone (selected). -- @param #GROUP self -- @param #boolean PositionZone true will randomize the positions within the Zone. @@ -1806,9 +1852,9 @@ end -- - @{#GROUP.InitHeading}: Set the heading for the units in degrees within the respawned group. -- - @{#GROUP.InitHeight}: Set the height for the units in meters for the respawned group. (This is applicable for air units). -- - @{#GROUP.InitRandomizeHeading}: Randomize the headings for the units within the respawned group. --- - @{#GROUP.InitZone}: Set the respawn @{Zone} for the respawned group. --- - @{#GROUP.InitRandomizeZones}: Randomize the respawn @{Zone} between one of the @{Zone}s given for the respawned group. --- - @{#GROUP.InitRandomizePositionZone}: Randomize the positions of the units of the respawned group within the @{Zone}. +-- - @{#GROUP.InitZone}: Set the respawn @{Core.Zone} for the respawned group. +-- - @{#GROUP.InitRandomizeZones}: Randomize the respawn @{Core.Zone} between one of the @{Core.Zone}s given for the respawned group. +-- - @{#GROUP.InitRandomizePositionZone}: Randomize the positions of the units of the respawned group within the @{Core.Zone}. -- - @{#GROUP.InitRandomizePositionRadius}: Randomize the positions of the units of the respawned group in a circle band. -- - @{#GROUP.InitRandomizeTemplates}: Randomize the Template for the respawned group. -- @@ -2159,7 +2205,7 @@ function GROUP:GetTaskRoute() return routines.utils.deepCopy( _DATABASE.Templates.Groups[self.GroupName].Template.route.points ) end ---- Return the route of a group by using the @{Core.Database#DATABASE} class. +--- Return the route of a group by using the global _DATABASE object (an instance of @{Core.Database#DATABASE}). -- @param #GROUP self -- @param #number Begin The route point from where the copy will start. The base route point is 0. -- @param #number End The route point where the copy will end. The End point is the last point - the End point. The last point has base 0. @@ -2384,7 +2430,7 @@ function GROUP:GetAttribute() local truck=self:HasAttribute("Trucks") and self:GetCategory()==Group.Category.GROUND local infantry=self:HasAttribute("Infantry") local artillery=self:HasAttribute("Artillery") - local tank=self:HasAttribute("Old Tanks") or self:HasAttribute("Modern Tanks") + local tank=self:HasAttribute("Old Tanks") or self:HasAttribute("Modern Tanks") or self:HasAttribute("Tanks") local aaa=self:HasAttribute("AAA") and (not self:HasAttribute("SAM elements")) local ewr=self:HasAttribute("EWR") local ifv=self:HasAttribute("IFV") @@ -2766,15 +2812,15 @@ function GROUP:GetCustomCallSign(ShortCallsign,Keepnumber,CallsignTranslations) local personalized = false if IsPlayer and string.find(groupname,"#") then -- personalized flight name in group naming - if Keepnumber then - shortcallsign = string.match(groupname,"#(.+)") -- Ghostrider 219 - else - shortcallsign = string.match(groupname,"#%s*([%a]+)") -- Ghostrider - end + if Keepnumber then + shortcallsign = string.match(groupname,"#(.+)") or "Ghost 111" -- Ghostrider 219 + else + shortcallsign = string.match(groupname,"#%s*([%a]+)") or "Ghost" -- Ghostrider + end personalized = true elseif IsPlayer and string.find(self:GetPlayerName(),"|") then -- personalized flight name in group naming - shortcallsign = string.match(self:GetPlayerName(),"|%s*([%a]+)") -- Ghostrider + shortcallsign = string.match(self:GetPlayerName(),"|%s*([%a]+)") or string.match(self:GetPlayerName(),"|%s*([%d]+)") or "Ghost" -- Ghostrider personalized = true end @@ -2809,3 +2855,30 @@ function GROUP:GetCustomCallSign(ShortCallsign,Keepnumber,CallsignTranslations) return callsign end + +--- +-- @param #GROUP self +-- @param Wrapper.Group#GROUP CarrierGroup. +-- @param #number Speed Speed in knots. +-- @param #boolean ToKIAS If true, adjust speed to altitude (KIAS). +-- @param #number Altitude Altitude the tanker orbits at in feet. +-- @param #number Delay (optional) Set the task after this many seconds. Defaults to one. +-- @param #number LastWaypoint (optional) Waypoint number of carrier group that when reached, ends the recovery tanker task. +-- @return #GROUP self +function GROUP:SetAsRecoveryTanker(CarrierGroup,Speed,ToKIAS,Altitude,Delay,LastWaypoint) + + local speed = ToKIAS == true and UTILS.KnotsToAltKIAS(Speed,Altitude) or Speed + speed = UTILS.KnotsToMps(speed) + + local alt = UTILS.FeetToMeters(Altitude) + local delay = Delay or 1 + + local task = self:TaskRecoveryTanker(CarrierGroup,speed,alt,LastWaypoint) + + self:SetTask(task,delay) + + local tankertask = self:EnRouteTaskTanker() + self:PushTask(tankertask,delay+2) + + return self +end diff --git a/Moose Development/Moose/Wrapper/Identifiable.lua b/Moose Development/Moose/Wrapper/Identifiable.lua index 7b77c9512..1710289d7 100644 --- a/Moose Development/Moose/Wrapper/Identifiable.lua +++ b/Moose Development/Moose/Wrapper/Identifiable.lua @@ -1,4 +1,4 @@ ---- **Wrapper** -- IDENTIFIABLE is an intermediate class wrapping DCS Object class derived Objects. +--- **Wrapper** - IDENTIFIABLE is an intermediate class wrapping DCS Object class derived Objects. -- -- === -- diff --git a/Moose Development/Moose/Wrapper/Object.lua b/Moose Development/Moose/Wrapper/Object.lua index f57ff73e8..4488141fa 100644 --- a/Moose Development/Moose/Wrapper/Object.lua +++ b/Moose Development/Moose/Wrapper/Object.lua @@ -1,4 +1,4 @@ ---- **Wrapper** -- OBJECT wraps the DCS Object derived objects. +--- **Wrapper** - OBJECT wraps the DCS Object derived objects. -- -- === -- diff --git a/Moose Development/Moose/Wrapper/Positionable.lua b/Moose Development/Moose/Wrapper/Positionable.lua index 87e199c9a..72f9a9fce 100644 --- a/Moose Development/Moose/Wrapper/Positionable.lua +++ b/Moose Development/Moose/Wrapper/Positionable.lua @@ -1,4 +1,4 @@ ---- **Wrapper** -- POSITIONABLE wraps DCS classes that are "positionable". +--- **Wrapper** - POSITIONABLE wraps DCS classes that are "positionable". -- -- === -- @@ -11,7 +11,7 @@ -- @module Wrapper.Positionable -- @image Wrapper_Positionable.JPG ---- @type POSITIONABLE.__ Methods which are not intended for mission designers, but which are used interally by the moose designer :-) +--- @type POSITIONABLE.__ Methods which are not intended for mission designers, but which are used internally by the moose designer :-) -- @extends Wrapper.Identifiable#IDENTIFIABLE --- @type POSITIONABLE @@ -136,7 +136,7 @@ end --- Returns a pos3 table of the objects current position and orientation in 3D space. X, Y, Z values are unit vectors defining the objects orientation. -- Coordinates are dependent on the position of the maps origin. --- @param Wrapper.Positionable#POSITIONABLE self +-- @param #POSITIONABLE self -- @return DCS#Position3 Table consisting of the point and orientation tables. function POSITIONABLE:GetPosition() self:F2( self.PositionableName ) @@ -155,7 +155,7 @@ end --- Returns a {@DCS#Vec3} table of the objects current orientation in 3D space. X, Y, Z values are unit vectors defining the objects orientation. -- X is the orientation parallel to the movement of the object, Z perpendicular and Y vertical orientation. --- @param Wrapper.Positionable#POSITIONABLE self +-- @param #POSITIONABLE self -- @return DCS#Vec3 X orientation, i.e. parallel to the direction of movement. -- @return DCS#Vec3 Y orientation, i.e. vertical. -- @return DCS#Vec3 Z orientation, i.e. perpendicular to the direction of movement. @@ -171,7 +171,7 @@ function POSITIONABLE:GetOrientation() end --- Returns a {@DCS#Vec3} table of the objects current X orientation in 3D space, i.e. along the direction of movement. --- @param Wrapper.Positionable#POSITIONABLE self +-- @param #POSITIONABLE self -- @return DCS#Vec3 X orientation, i.e. parallel to the direction of movement. -- @return #nil The POSITIONABLE is not existing or alive. function POSITIONABLE:GetOrientationX() @@ -185,7 +185,7 @@ function POSITIONABLE:GetOrientationX() end --- Returns a {@DCS#Vec3} table of the objects current Y orientation in 3D space, i.e. vertical orientation. --- @param Wrapper.Positionable#POSITIONABLE self +-- @param #POSITIONABLE self -- @return DCS#Vec3 Y orientation, i.e. vertical. -- @return #nil The POSITIONABLE is not existing or alive. function POSITIONABLE:GetOrientationY() @@ -199,7 +199,7 @@ function POSITIONABLE:GetOrientationY() end --- Returns a {@DCS#Vec3} table of the objects current Z orientation in 3D space, i.e. perpendicular to direction of movement. --- @param Wrapper.Positionable#POSITIONABLE self +-- @param #POSITIONABLE self -- @return DCS#Vec3 Z orientation, i.e. perpendicular to movement. -- @return #nil The POSITIONABLE is not existing or alive. function POSITIONABLE:GetOrientationZ() @@ -213,7 +213,7 @@ function POSITIONABLE:GetOrientationZ() end --- Returns the @{DCS#Position3} position vectors indicating the point and direction vectors in 3D of the POSITIONABLE within the mission. --- @param Wrapper.Positionable#POSITIONABLE self +-- @param #POSITIONABLE self -- @return DCS#Position The 3D position vectors of the POSITIONABLE. -- @return #nil The POSITIONABLE is not existing or alive. function POSITIONABLE:GetPositionVec3() @@ -233,7 +233,7 @@ function POSITIONABLE:GetPositionVec3() end --- Returns the @{DCS#Vec3} vector indicating the 3D vector of the POSITIONABLE within the mission. --- @param Wrapper.Positionable#POSITIONABLE self +-- @param #POSITIONABLE self -- @return DCS#Vec3 The 3D point vector of the POSITIONABLE. -- @return #nil The POSITIONABLE is not existing or alive. function POSITIONABLE:GetVec3() @@ -257,7 +257,7 @@ function POSITIONABLE:GetVec3() end --- Returns the @{DCS#Vec2} vector indicating the point in 2D of the POSITIONABLE within the mission. --- @param Wrapper.Positionable#POSITIONABLE self +-- @param #POSITIONABLE self -- @return DCS#Vec2 The 2D point vector of the POSITIONABLE. -- @return #nil The POSITIONABLE is not existing or alive. function POSITIONABLE:GetVec2() @@ -277,7 +277,7 @@ function POSITIONABLE:GetVec2() end --- Returns a POINT_VEC2 object indicating the point in 2D of the POSITIONABLE within the mission. --- @param Wrapper.Positionable#POSITIONABLE self +-- @param #POSITIONABLE self -- @return Core.Point#POINT_VEC2 The 2D point vector of the POSITIONABLE. -- @return #nil The POSITIONABLE is not existing or alive. function POSITIONABLE:GetPointVec2() @@ -300,7 +300,7 @@ function POSITIONABLE:GetPointVec2() end --- Returns a POINT_VEC3 object indicating the point in 3D of the POSITIONABLE within the mission. --- @param Wrapper.Positionable#POSITIONABLE self +-- @param #POSITIONABLE self -- @return Core.Point#POINT_VEC3 The 3D point vector of the POSITIONABLE. -- @return #nil The POSITIONABLE is not existing or alive. function POSITIONABLE:GetPointVec3() @@ -339,7 +339,7 @@ end -- within the POSITIONABLE. This has higher performance, but comes with all considerations associated with the possible referencing to the same COORDINATE object. -- This should only be used when performance is critical and there is sufficient awareness of the possible pitfalls. However, in most instances, GetCoordinate() is -- preferred as it will return a fresh new COORDINATE and thus avoid potentially unexpected issues. --- @param Wrapper.Positionable#POSITIONABLE self +-- @param #POSITIONABLE self -- @return Core.Point#COORDINATE A reference to the COORDINATE object of the POSITIONABLE. function POSITIONABLE:GetCoord() @@ -369,7 +369,7 @@ function POSITIONABLE:GetCoord() end --- Returns a new COORDINATE object indicating the point in 3D of the POSITIONABLE within the mission. --- @param Wrapper.Positionable#POSITIONABLE self +-- @param #POSITIONABLE self -- @return Core.Point#COORDINATE A new COORDINATE object of the POSITIONABLE. function POSITIONABLE:GetCoordinate() @@ -395,7 +395,7 @@ function POSITIONABLE:GetCoordinate() end --- Returns a COORDINATE object, which is offset with respect to the orientation of the POSITIONABLE. --- @param Wrapper.Positionable#POSITIONABLE self +-- @param #POSITIONABLE self -- @param #number x Offset in the direction "the nose" of the unit is pointing in meters. Default 0 m. -- @param #number y Offset "above" the unit in meters. Default 0 m. -- @param #number z Offset in the direction "the wing" of the unit is pointing in meters. z>0 starboard, z<0 port. Default 0 m. @@ -436,7 +436,7 @@ function POSITIONABLE:GetOffsetCoordinate( x, y, z ) end --- Returns a random @{DCS#Vec3} vector within a range, indicating the point in 3D of the POSITIONABLE within the mission. --- @param Wrapper.Positionable#POSITIONABLE self +-- @param #POSITIONABLE self -- @param #number Radius -- @return DCS#Vec3 The 3D point vector of the POSITIONABLE. -- @return #nil The POSITIONABLE is not existing or alive. @@ -538,7 +538,7 @@ function POSITIONABLE:GetBoundingRadius( MinDist ) end --- Returns the altitude above sea level of the POSITIONABLE. --- @param Wrapper.Positionable#POSITIONABLE self +-- @param #POSITIONABLE self -- @return DCS#Distance The altitude of the POSITIONABLE. -- @return #nil The POSITIONABLE is not existing or alive. function POSITIONABLE:GetAltitude() @@ -557,7 +557,7 @@ function POSITIONABLE:GetAltitude() end --- Returns if the Positionable is located above a runway. --- @param Wrapper.Positionable#POSITIONABLE self +-- @param #POSITIONABLE self -- @return #boolean true if Positionable is above a runway. -- @return #nil The POSITIONABLE is not existing or alive. function POSITIONABLE:IsAboveRunway() @@ -592,7 +592,7 @@ function POSITIONABLE:GetSize() end --- Returns the POSITIONABLE heading in degrees. --- @param Wrapper.Positionable#POSITIONABLE self +-- @param #POSITIONABLE self -- @return #number The POSITIONABLE heading in degrees. -- @return #nil The POSITIONABLE is not existing or alive. function POSITIONABLE:GetHeading() @@ -716,7 +716,7 @@ end --- Returns true if the POSITIONABLE is in the air. -- Polymorphic, is overridden in GROUP and UNIT. --- @param Wrapper.Positionable#POSITIONABLE self +-- @param #POSITIONABLE self -- @return #boolean true if in the air. -- @return #nil The POSITIONABLE is not existing or alive. function POSITIONABLE:InAir() @@ -725,8 +725,8 @@ function POSITIONABLE:InAir() return nil end ---- Returns the a @{Velocity} object from the POSITIONABLE. --- @param Wrapper.Positionable#POSITIONABLE self +--- Returns the @{Core.Velocity} object from the POSITIONABLE. +-- @param #POSITIONABLE self -- @return Core.Velocity#VELOCITY Velocity The Velocity object. -- @return #nil The POSITIONABLE is not existing or alive. function POSITIONABLE:GetVelocity() @@ -745,7 +745,7 @@ function POSITIONABLE:GetVelocity() end --- Returns the POSITIONABLE velocity Vec3 vector. --- @param Wrapper.Positionable#POSITIONABLE self +-- @param #POSITIONABLE self -- @return DCS#Vec3 The velocity Vec3 vector -- @return #nil The POSITIONABLE is not existing or alive. function POSITIONABLE:GetVelocityVec3() @@ -781,7 +781,7 @@ end --- Returns the POSITIONABLE height above sea level in meters. --- @param Wrapper.Positionable#POSITIONABLE self +-- @param #POSITIONABLE self -- @return DCS#Vec3 Height of the positionable in meters (or nil, if the object does not exist). function POSITIONABLE:GetHeight() --R2.1 self:F2( self.PositionableName ) @@ -801,7 +801,7 @@ function POSITIONABLE:GetHeight() --R2.1 end --- Returns the POSITIONABLE velocity in km/h. --- @param Wrapper.Positionable#POSITIONABLE self +-- @param #POSITIONABLE self -- @return #number The velocity in km/h. function POSITIONABLE:GetVelocityKMH() self:F2( self.PositionableName ) @@ -820,7 +820,7 @@ function POSITIONABLE:GetVelocityKMH() end --- Returns the POSITIONABLE velocity in meters per second. --- @param Wrapper.Positionable#POSITIONABLE self +-- @param #POSITIONABLE self -- @return #number The velocity in meters per second. function POSITIONABLE:GetVelocityMPS() self:F2( self.PositionableName ) @@ -838,7 +838,7 @@ function POSITIONABLE:GetVelocityMPS() end --- Returns the POSITIONABLE velocity in knots. --- @param Wrapper.Positionable#POSITIONABLE self +-- @param #POSITIONABLE self -- @return #number The velocity in knots. function POSITIONABLE:GetVelocityKNOTS() self:F2( self.PositionableName ) @@ -846,7 +846,7 @@ function POSITIONABLE:GetVelocityKNOTS() end --- Returns the Angle of Attack of a POSITIONABLE. --- @param Wrapper.Positionable#POSITIONABLE self +-- @param #POSITIONABLE self -- @return #number Angle of attack in degrees. -- @return #nil The POSITIONABLE is not existing or alive. function POSITIONABLE:GetAoA() @@ -895,7 +895,7 @@ function POSITIONABLE:GetAoA() end --- Returns the climb or descent angle of the POSITIONABLE. --- @param Wrapper.Positionable#POSITIONABLE self +-- @param #POSITIONABLE self -- @return #number Climb or descent angle in degrees. Or 0 if velocity vector norm is zero. -- @return #nil The POSITIONABLE is not existing or alive. function POSITIONABLE:GetClimbAngle() @@ -925,7 +925,7 @@ function POSITIONABLE:GetClimbAngle() end --- Returns the pitch angle of a POSITIONABLE. --- @param Wrapper.Positionable#POSITIONABLE self +-- @param #POSITIONABLE self -- @return #number Pitch angle in degrees. -- @return #nil The POSITIONABLE is not existing or alive. function POSITIONABLE:GetPitch() @@ -941,7 +941,7 @@ function POSITIONABLE:GetPitch() end --- Returns the roll angle of a unit. --- @param Wrapper.Positionable#POSITIONABLE self +-- @param #POSITIONABLE self -- @return #number Pitch angle in degrees. -- @return #nil The POSITIONABLE is not existing or alive. function POSITIONABLE:GetRoll() @@ -975,7 +975,7 @@ function POSITIONABLE:GetRoll() end --- Returns the yaw angle of a POSITIONABLE. --- @param Wrapper.Positionable#POSITIONABLE self +-- @param #POSITIONABLE self -- @return #number Yaw angle in degrees. -- @return #nil The POSITIONABLE is not existing or alive. function POSITIONABLE:GetYaw() @@ -1366,24 +1366,24 @@ function POSITIONABLE:Message( Message, Duration, Name ) return nil end ---- Create a @{Core.Radio#RADIO}, to allow radio transmission for this POSITIONABLE. +--- Create a @{Sound.Radio#RADIO}, to allow radio transmission for this POSITIONABLE. -- Set parameters with the methods provided, then use RADIO:Broadcast() to actually broadcast the message -- @param #POSITIONABLE self --- @return Core.Radio#RADIO Radio +-- @return Sound.Radio#RADIO Radio function POSITIONABLE:GetRadio() self:F2( self ) return RADIO:New( self ) end ---- Create a @{Core.Radio#BEACON}, to allow this POSITIONABLE to broadcast beacon signals +--- Create a @{Core.Beacon#BEACON}, to allow this POSITIONABLE to broadcast beacon signals. -- @param #POSITIONABLE self --- @return Core.Radio#RADIO Radio +-- @return Core.Beacon#BEACON Beacon function POSITIONABLE:GetBeacon() self:F2( self ) return BEACON:New( self ) end ---- Start Lasing a POSITIONABLE +--- Start Lasing a POSITIONABLE. -- @param #POSITIONABLE self -- @param #POSITIONABLE Target The target to lase. -- @param #number LaserCode Laser code or random number in [1000, 9999]. @@ -1424,7 +1424,7 @@ function POSITIONABLE:LaseCoordinate( Coordinate, LaserCode, Duration ) return self.Spot end ---- Stop Lasing a POSITIONABLE +--- Stop Lasing a POSITIONABLE. -- @param #POSITIONABLE self -- @return #POSITIONABLE function POSITIONABLE:LaseOff() @@ -1438,7 +1438,7 @@ function POSITIONABLE:LaseOff() return self end ---- Check if the POSITIONABLE is lasing a target +--- Check if the POSITIONABLE is lasing a target. -- @param #POSITIONABLE self -- @return #boolean true if it is lasing a target function POSITIONABLE:IsLasing() @@ -1815,7 +1815,7 @@ function POSITIONABLE:SmokeBlue() trigger.action.smoke( self:GetVec3(), trigger.smokeColor.Blue ) end ---- Returns true if the unit is within a @{Zone}. +--- Returns true if the unit is within a @{Core.Zone}. -- @param #POSITIONABLE self -- @param Core.Zone#ZONE_BASE Zone The zone to test. -- @return #boolean Returns true if the unit is within the @{Core.Zone#ZONE_BASE} @@ -1830,7 +1830,7 @@ function POSITIONABLE:IsInZone( Zone ) return false end ---- Returns true if the unit is not within a @{Zone}. +--- Returns true if the unit is not within a @{Core.Zone}. -- @param #POSITIONABLE self -- @param Core.Zone#ZONE_BASE Zone The zone to test. -- @return #boolean Returns true if the unit is not within the @{Core.Zone#ZONE_BASE} diff --git a/Moose Development/Moose/Wrapper/Scenery.lua b/Moose Development/Moose/Wrapper/Scenery.lua index 445154037..4cd321063 100644 --- a/Moose Development/Moose/Wrapper/Scenery.lua +++ b/Moose Development/Moose/Wrapper/Scenery.lua @@ -1,10 +1,10 @@ ---- **Wrapper** -- SCENERY models scenery within the DCS simulator. +--- **Wrapper** - SCENERY models scenery within the DCS simulator. -- -- === -- -- ### Author: **FlightControl** -- --- ### Contributions: +-- ### Contributions: **Applevangelist** -- -- === -- @@ -14,6 +14,10 @@ --- @type SCENERY +-- @field #string ClassName +-- @field #string SceneryName +-- @field #DCS.Object SceneryObject +-- @field #number Life0 -- @extends Wrapper.Positionable#POSITIONABLE @@ -27,10 +31,9 @@ -- -- @field #SCENERY SCENERY = { - ClassName = "SCENERY", + ClassName = "SCENERY", } - --- Register scenery object as POSITIONABLE. --@param #SCENERY self --@param #string SceneryName Scenery name. @@ -40,17 +43,54 @@ function SCENERY:Register( SceneryName, SceneryObject ) local self = BASE:Inherit( self, POSITIONABLE:New( SceneryName ) ) self.SceneryName = SceneryName self.SceneryObject = SceneryObject + if self.SceneryObject then + self.Life0 = self.SceneryObject:getLife() + else + self.Life0 = 0 + end return self end ---- Register scenery object as POSITIONABLE. +--- Obtain DCS Object from the SCENERY Object. --@param #SCENERY self --@return #DCS.Object DCS scenery object. function SCENERY:GetDCSObject() return self.SceneryObject end ---- Register scenery object as POSITIONABLE. +--- Get current life points from the SCENERY Object. +--@param #SCENERY self +--@return #number life +function SCENERY:GetLife() + local life = 0 + if self.SceneryObject then + life = self.SceneryObject:getLife() + end + return life +end + +--- Get current initial life points from the SCENERY Object. +--@param #SCENERY self +--@return #number life +function SCENERY:GetLife0() + return self.Life0 or 0 +end + +--- Check if SCENERY Object is alive. +--@param #SCENERY self +--@return #number life +function SCENERY:IsAlive() + return self:GetLife() >= 1 and true or false +end + +--- Check if SCENERY Object is dead. +--@param #SCENERY self +--@return #number life +function SCENERY:IsDead() + return self:GetLife() < 1 and true or false +end + +--- Get the threat level of a SCENERY object. Always 0. --@param #SCENERY self --@return #number Threat level 0. --@return #string "Scenery". @@ -58,39 +98,130 @@ function SCENERY:GetThreatLevel() return 0, "Scenery" end ---- Find a SCENERY object by it's name/id. +--- Find a SCENERY object from its name or id. Since SCENERY isn't registered in the Moose database (just too many objects per map), we need to do a scan first +-- to find the correct object. --@param #SCENERY self ---@param #string name The name/id of the scenery object as taken from the ME. Ex. '595785449' ---@return #SCENERY Scenery Object or nil if not found. -function SCENERY:FindByName(name) - local findAirbase = function () - local airbases = AIRBASE.GetAllAirbases() - for index,airbase in pairs(airbases) do - local surftype = airbase:GetCoordinate():GetSurfaceType() - if surftype ~= land.SurfaceType.SHALLOW_WATER and surftype ~= land.SurfaceType.WATER then - return airbase:GetCoordinate() - end - end - return nil - end - - local sceneryScan = function (scancoord) - if scancoord ~= nil then - local _,_,sceneryfound,_,_,scenerylist = scancoord:ScanObjects(200, false, false, true) - if sceneryfound == true then - scenerylist[1].id_ = name - SCENERY.SceneryObject = SCENERY:Register(scenerylist[1].id_, scenerylist[1]) - return SCENERY.SceneryObject +--@param #string Name The name/id of the scenery object as taken from the ME. Ex. '595785449' +--@param Core.Point#COORDINATE Coordinate Where to find the scenery object +--@param #number Radius (optional) Search radius around coordinate, defaults to 100 +--@return #SCENERY Scenery Object or `nil` if it cannot be found +function SCENERY:FindByName(Name, Coordinate, Radius) + + local radius = Radius or 100 + local name = Name or "unknown" + local scenery = nil + + --- + -- @param Core.Point#COORDINATE coordinate + -- @param #number radius + -- @param #string name + local function SceneryScan(coordinate, radius, name) + if coordinate ~= nil then + local scenerylist = coordinate:ScanScenery(radius) + local rscenery = nil + for _,_scenery in pairs(scenerylist) do + local scenery = _scenery -- Wrapper.Scenery#SCENERY + if tostring(scenery.SceneryName) == tostring(name) then + rscenery = scenery + break + end end + return rscenery end return nil end - if SCENERY.SceneryObject then - SCENERY.SceneryObject.SceneryObject.id_ = name - SCENERY.SceneryObject.SceneryName = name - return SCENERY:Register(SCENERY.SceneryObject.SceneryObject.id_, SCENERY.SceneryObject.SceneryObject) + if Coordinate then + scenery = SceneryScan(Coordinate, radius, name) + end + + return scenery +end + +--- Find a SCENERY object from its name or id. Since SCENERY isn't registered in the Moose database (just too many objects per map), we need to do a scan first +-- to find the correct object. +--@param #SCENERY self +--@param #string Name The name or id of the scenery object as taken from the ME. Ex. '595785449' +--@param Core.Zone#ZONE Zone Where to find the scenery object. Can be handed as zone name. +--@param #number Radius (optional) Search radius around coordinate, defaults to 100 +--@return #SCENERY Scenery Object or `nil` if it cannot be found +function SCENERY:FindByNameInZone(Name, Zone, Radius) + local radius = Radius or 100 + local name = Name or "unknown" + if type(Zone) == "string" then + Zone = ZONE:FindByName(Zone) + end + local coordinate = Zone:GetCoordinate() + return self:FindByName(Name,coordinate,Radius) +end + +--- Find a SCENERY object from its zone name. Since SCENERY isn't registered in the Moose database (just too many objects per map), we need to do a scan first +-- to find the correct object. +--@param #SCENERY self +--@param #string ZoneName The name of the scenery zone as created with a right-click on the map in the mission editor and select "assigned to...". Can be handed over as ZONE object. +--@return #SCENERY First found Scenery Object or `nil` if it cannot be found +function SCENERY:FindByZoneName( ZoneName ) + local zone = ZoneName -- Core.Zone#ZONE + if type(ZoneName) == "string" then + zone = ZONE:FindByName(ZoneName) + end + local _id = zone:GetProperty('OBJECT ID') + if not _id then + -- this zone has no object ID + BASE:E("**** Zone without object ID: "..ZoneName.." | Type: "..tostring(zone.ClassName)) + if string.find(zone.ClassName,"POLYGON") then + zone:Scan({Object.Category.SCENERY}) + local scanned = zone:GetScannedScenery() + for _,_scenery in (scanned) do + local scenery = _scenery -- Wrapper.Scenery#SCENERY + if scenery:IsAlive() then + return scenery + end + end + return nil + else + local coordinate = zone:GetCoordinate() + local scanned = coordinate:ScanScenery() + for _,_scenery in (scanned) do + local scenery = _scenery -- Wrapper.Scenery#SCENERY + if scenery:IsAlive() then + return scenery + end + end + return nil + end else - return sceneryScan(findAirbase()) + return self:FindByName(_id, zone:GetCoordinate()) + end +end + +--- Scan and find all SCENERY objects from a zone by zone-name. Since SCENERY isn't registered in the Moose database (just too many objects per map), we need to do a scan first +-- to find the correct object. +--@param #SCENERY self +--@param #string ZoneName The name of the zone, can be handed as ZONE_RADIUS or ZONE_POLYGON object +--@return #table of SCENERY Objects, or `nil` if nothing found +function SCENERY:FindAllByZoneName( ZoneName ) + local zone = ZoneName -- Core.Zone#ZONE_RADIUS + if type(ZoneName) == "string" then + zone = ZONE:FindByName(ZoneName) + end + local _id = zone:GetProperty('OBJECT ID') + if not _id then + -- this zone has no object ID + --BASE:E("**** Zone without object ID: "..ZoneName.." | Type: "..tostring(zone.ClassName)) + zone:Scan({Object.Category.SCENERY}) + local scanned = zone:GetScannedSceneryObjects() + if #scanned > 0 then + return scanned + else + return nil + end + else + local obj = self:FindByName(_id, zone:GetCoordinate()) + if obj then + return {obj} + else + return nil + end end end diff --git a/Moose Development/Moose/Wrapper/Static.lua b/Moose Development/Moose/Wrapper/Static.lua index 08c9a0bce..933052517 100644 --- a/Moose Development/Moose/Wrapper/Static.lua +++ b/Moose Development/Moose/Wrapper/Static.lua @@ -1,4 +1,4 @@ ---- **Wrapper** -- STATIC wraps the DCS StaticObject class. +--- **Wrapper** - STATIC wraps the DCS StaticObject class. -- -- === -- @@ -26,21 +26,21 @@ -- -- ## STATIC reference methods -- --- For each DCS Static will have a STATIC wrapper object (instance) within the _@{DATABASE} object. +-- For each DCS Static will have a STATIC wrapper object (instance) within the global _DATABASE object (an instance of @{Core.Database#DATABASE}). -- This is done at the beginning of the mission (when the mission starts). -- --- The STATIC class does not contain a :New() method, rather it provides :Find() methods to retrieve the object reference +-- The @{#STATIC} class does not contain a :New() method, rather it provides :Find() methods to retrieve the object reference -- using the Static Name. -- -- Another thing to know is that STATIC objects do not "contain" the DCS Static object. --- The STATIc methods will reference the DCS Static object by name when it is needed during API execution. +-- The @{#STATIC} methods will reference the DCS Static object by name when it is needed during API execution. -- If the DCS Static object does not exist or is nil, the STATIC methods will return nil and log an exception in the DCS.log file. -- --- The STATIc class provides the following functions to retrieve quickly the relevant STATIC instance: +-- The @{#STATIC} class provides the following functions to retrieve quickly the relevant STATIC instance: -- --- * @{#STATIC.FindByName}(): Find a STATIC instance from the _DATABASE object using a DCS Static name. +-- * @{#STATIC.FindByName}(): Find a STATIC instance from the global _DATABASE object (an instance of @{Core.Database#DATABASE}) using a DCS Static name. -- --- IMPORTANT: ONE SHOULD NEVER SANATIZE these STATIC OBJECT REFERENCES! (make the STATIC object references nil). +-- IMPORTANT: ONE SHOULD NEVER SANITIZE these STATIC OBJECT REFERENCES! (make the STATIC object references nil). -- -- @field #STATIC STATIC = { @@ -55,9 +55,33 @@ STATIC = { function STATIC:Register( StaticName ) local self = BASE:Inherit( self, POSITIONABLE:New( StaticName ) ) self.StaticName = StaticName + + local DCSStatic = StaticObject.getByName( self.StaticName ) + if DCSStatic then + local Life0 = DCSStatic:getLife() or 1 + self.Life0 = Life0 + end + return self end +--- Get initial life points +-- @param #STATIC self +-- @return #number lifepoints +function STATIC:GetLife0() + return self.Life0 or 1 +end + +--- Get current life points +-- @param #STATIC self +-- @return #number lifepoints or nil +function STATIC:GetLife() + local DCSStatic = StaticObject.getByName( self.StaticName ) + if DCSStatic then + return DCSStatic:getLife() or 1 + end + return nil +end --- Finds a STATIC from the _DATABASE using a DCSStatic object. -- @param #STATIC self @@ -162,9 +186,9 @@ function STATIC:GetDCSObject() return nil end ---- Returns a list of one @{Static}. +--- Returns a list of one @{Wrapper.Static}. -- @param #STATIC self --- @return #list A list of one @{Static}. +-- @return #list A list of one @{Wrapper.Static}. function STATIC:GetUnits() self:F2( { self.StaticName } ) local DCSStatic = self:GetDCSObject() diff --git a/Moose Development/Moose/Wrapper/Unit.lua b/Moose Development/Moose/Wrapper/Unit.lua index 06617bafb..ecff1ef41 100644 --- a/Moose Development/Moose/Wrapper/Unit.lua +++ b/Moose Development/Moose/Wrapper/Unit.lua @@ -27,8 +27,8 @@ -- @field #string GroupName Name of the group the unit belongs to. -- @extends Wrapper.Controllable#CONTROLLABLE ---- For each DCS Unit object alive within a running mission, a UNIT wrapper object (instance) will be created within the _@{DATABASE} object. --- This is done at the beginning of the mission (when the mission starts), and dynamically when new DCS Unit objects are spawned (using the @{SPAWN} class). +--- For each DCS Unit object alive within a running mission, a UNIT wrapper object (instance) will be created within the global _DATABASE object (an instance of @{Core.Database#DATABASE}). +-- This is done at the beginning of the mission (when the mission starts), and dynamically when new DCS Unit objects are spawned (using the @{Core.Spawn} class). -- -- The UNIT class **does not contain a :New()** method, rather it provides **:Find()** methods to retrieve the object reference -- using the DCS Unit or the DCS UnitName. @@ -39,10 +39,10 @@ -- -- The UNIT class provides the following functions to retrieve quickly the relevant UNIT instance: -- --- * @{#UNIT.Find}(): Find a UNIT instance from the _DATABASE object using a DCS Unit object. --- * @{#UNIT.FindByName}(): Find a UNIT instance from the _DATABASE object using a DCS Unit name. +-- * @{#UNIT.Find}(): Find a UNIT instance from the global _DATABASE object (an instance of @{Core.Database#DATABASE}) using a DCS Unit object. +-- * @{#UNIT.FindByName}(): Find a UNIT instance from the global _DATABASE object (an instance of @{Core.Database#DATABASE}) using a DCS Unit name. -- --- IMPORTANT: ONE SHOULD NEVER SANATIZE these UNIT OBJECT REFERENCES! (make the UNIT object references nil). +-- IMPORTANT: ONE SHOULD NEVER SANITIZE these UNIT OBJECT REFERENCES! (make the UNIT object references nil). -- -- ## DCS UNIT APIs -- @@ -361,6 +361,8 @@ function UNIT:IsPlayer() -- Get group. local group=self:GetGroup() + + if not group then return false end -- Units of template group. local units=group:GetTemplate().units @@ -644,7 +646,7 @@ end -- Need to add here functions to check if radar is on and which object etc. --- Returns the prefix name of the DCS Unit. A prefix name is a part of the name before a '#'-sign. --- DCS Units spawned with the @{SPAWN} class contain a '#'-sign to indicate the end of the (base) DCS Unit name. +-- DCS Units spawned with the @{Core.Spawn#SPAWN} class contain a '#'-sign to indicate the end of the (base) DCS Unit name. -- The spawn sequence number and unit number are contained within the name after the '#' sign. -- @param #UNIT self -- @return #string The name of the DCS Unit.