Merge branch 'master' into develop

This commit is contained in:
Frank 2020-08-30 17:15:31 +02:00
commit c84a92c787
23 changed files with 3089 additions and 2215 deletions

View File

@ -164,7 +164,7 @@ AI_FORMATION.__Enum.ReportType = {
--- MENUPARAM type --- MENUPARAM type
-- @type MENUPARAM -- @type MENUPARAM
-- @field #AI_FORMATION ParamSelf -- @field #AI_FORMATION ParamSelf
-- @field #Distance ParamDistance -- @field #number ParamDistance
-- @field #function ParamFunction -- @field #function ParamFunction
-- @field #string ParamMessage -- @field #string ParamMessage
@ -207,9 +207,9 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
-- @param #string To -- @param #string To
-- @param #number XStart The start position on the X-axis in meters for the first group. -- @param #number XStart The start position on the X-axis in meters for the first group.
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. -- @param #number YStart The start position on the Y-axis in meters for the first group.
-- @param #nubmer YSpace The space between groups on the Y-axis in meters for each sequent group. -- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. -- @param #number ZStart The start position on the Z-axis in meters for the first group.
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
-- @return #boolean -- @return #boolean
@ -222,9 +222,9 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
-- @param #string To -- @param #string To
-- @param #number XStart The start position on the X-axis in meters for the first group. -- @param #number XStart The start position on the X-axis in meters for the first group.
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. -- @param #number YStart The start position on the Y-axis in meters for the first group.
-- @param #nubmer YSpace The space between groups on the Y-axis in meters for each sequent group. -- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. -- @param #number ZStart The start position on the Z-axis in meters for the first group.
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
--- FormationLine Trigger for AI_FORMATION --- FormationLine Trigger for AI_FORMATION
@ -232,9 +232,9 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
-- @param #AI_FORMATION self -- @param #AI_FORMATION self
-- @param #number XStart The start position on the X-axis in meters for the first group. -- @param #number XStart The start position on the X-axis in meters for the first group.
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. -- @param #number YStart The start position on the Y-axis in meters for the first group.
-- @param #nubmer YSpace The space between groups on the Y-axis in meters for each sequent group. -- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. -- @param #number ZStart The start position on the Z-axis in meters for the first group.
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
--- FormationLine Asynchronous Trigger for AI_FORMATION --- FormationLine Asynchronous Trigger for AI_FORMATION
@ -243,9 +243,9 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
-- @param #number Delay -- @param #number Delay
-- @param #number XStart The start position on the X-axis in meters for the first group. -- @param #number XStart The start position on the X-axis in meters for the first group.
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. -- @param #number YStart The start position on the Y-axis in meters for the first group.
-- @param #nubmer YSpace The space between groups on the Y-axis in meters for each sequent group. -- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. -- @param #number ZStart The start position on the Z-axis in meters for the first group.
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
self:AddTransition( "*", "FormationTrail", "*" ) self:AddTransition( "*", "FormationTrail", "*" )
@ -257,7 +257,7 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
-- @param #string To -- @param #string To
-- @param #number XStart The start position on the X-axis in meters for the first group. -- @param #number XStart The start position on the X-axis in meters for the first group.
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. -- @param #number YStart The start position on the Y-axis in meters for the first group.
-- @return #boolean -- @return #boolean
--- FormationTrail Handler OnAfter for AI_FORMATION --- FormationTrail Handler OnAfter for AI_FORMATION
@ -268,14 +268,14 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
-- @param #string To -- @param #string To
-- @param #number XStart The start position on the X-axis in meters for the first group. -- @param #number XStart The start position on the X-axis in meters for the first group.
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. -- @param #number YStart The start position on the Y-axis in meters for the first group.
--- FormationTrail Trigger for AI_FORMATION --- FormationTrail Trigger for AI_FORMATION
-- @function [parent=#AI_FORMATION] FormationTrail -- @function [parent=#AI_FORMATION] FormationTrail
-- @param #AI_FORMATION self -- @param #AI_FORMATION self
-- @param #number XStart The start position on the X-axis in meters for the first group. -- @param #number XStart The start position on the X-axis in meters for the first group.
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. -- @param #number YStart The start position on the Y-axis in meters for the first group.
--- FormationTrail Asynchronous Trigger for AI_FORMATION --- FormationTrail Asynchronous Trigger for AI_FORMATION
-- @function [parent=#AI_FORMATION] __FormationTrail -- @function [parent=#AI_FORMATION] __FormationTrail
@ -283,7 +283,7 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
-- @param #number Delay -- @param #number Delay
-- @param #number XStart The start position on the X-axis in meters for the first group. -- @param #number XStart The start position on the X-axis in meters for the first group.
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. -- @param #number YStart The start position on the Y-axis in meters for the first group.
self:AddTransition( "*", "FormationStack", "*" ) self:AddTransition( "*", "FormationStack", "*" )
--- FormationStack Handler OnBefore for AI_FORMATION --- FormationStack Handler OnBefore for AI_FORMATION
@ -294,7 +294,7 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
-- @param #string To -- @param #string To
-- @param #number XStart The start position on the X-axis in meters for the first group. -- @param #number XStart The start position on the X-axis in meters for the first group.
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. -- @param #number YStart The start position on the Y-axis in meters for the first group.
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group. -- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
-- @return #boolean -- @return #boolean
@ -306,7 +306,7 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
-- @param #string To -- @param #string To
-- @param #number XStart The start position on the X-axis in meters for the first group. -- @param #number XStart The start position on the X-axis in meters for the first group.
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. -- @param #number YStart The start position on the Y-axis in meters for the first group.
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group. -- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
--- FormationStack Trigger for AI_FORMATION --- FormationStack Trigger for AI_FORMATION
@ -314,7 +314,7 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
-- @param #AI_FORMATION self -- @param #AI_FORMATION self
-- @param #number XStart The start position on the X-axis in meters for the first group. -- @param #number XStart The start position on the X-axis in meters for the first group.
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. -- @param #number YStart The start position on the Y-axis in meters for the first group.
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group. -- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
--- FormationStack Asynchronous Trigger for AI_FORMATION --- FormationStack Asynchronous Trigger for AI_FORMATION
@ -323,7 +323,7 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
-- @param #number Delay -- @param #number Delay
-- @param #number XStart The start position on the X-axis in meters for the first group. -- @param #number XStart The start position on the X-axis in meters for the first group.
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. -- @param #number YStart The start position on the Y-axis in meters for the first group.
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group. -- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
self:AddTransition( "*", "FormationLeftLine", "*" ) self:AddTransition( "*", "FormationLeftLine", "*" )
@ -335,8 +335,8 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
-- @param #string Event -- @param #string Event
-- @param #string To -- @param #string To
-- @param #number XStart The start position on the X-axis in meters for the first group. -- @param #number XStart The start position on the X-axis in meters for the first group.
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. -- @param #number YStart The start position on the Y-axis in meters for the first group.
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. -- @param #number ZStart The start position on the Z-axis in meters for the first group.
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
-- @return #boolean -- @return #boolean
@ -348,16 +348,16 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
-- @param #string Event -- @param #string Event
-- @param #string To -- @param #string To
-- @param #number XStart The start position on the X-axis in meters for the first group. -- @param #number XStart The start position on the X-axis in meters for the first group.
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. -- @param #number YStart The start position on the Y-axis in meters for the first group.
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. -- @param #number ZStart The start position on the Z-axis in meters for the first group.
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
--- FormationLeftLine Trigger for AI_FORMATION --- FormationLeftLine Trigger for AI_FORMATION
-- @function [parent=#AI_FORMATION] FormationLeftLine -- @function [parent=#AI_FORMATION] FormationLeftLine
-- @param #AI_FORMATION self -- @param #AI_FORMATION self
-- @param #number XStart The start position on the X-axis in meters for the first group. -- @param #number XStart The start position on the X-axis in meters for the first group.
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. -- @param #number YStart The start position on the Y-axis in meters for the first group.
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. -- @param #number ZStart The start position on the Z-axis in meters for the first group.
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
--- FormationLeftLine Asynchronous Trigger for AI_FORMATION --- FormationLeftLine Asynchronous Trigger for AI_FORMATION
@ -365,8 +365,8 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
-- @param #AI_FORMATION self -- @param #AI_FORMATION self
-- @param #number Delay -- @param #number Delay
-- @param #number XStart The start position on the X-axis in meters for the first group. -- @param #number XStart The start position on the X-axis in meters for the first group.
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. -- @param #number YStart The start position on the Y-axis in meters for the first group.
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. -- @param #number ZStart The start position on the Z-axis in meters for the first group.
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
self:AddTransition( "*", "FormationRightLine", "*" ) self:AddTransition( "*", "FormationRightLine", "*" )
@ -378,8 +378,8 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
-- @param #string Event -- @param #string Event
-- @param #string To -- @param #string To
-- @param #number XStart The start position on the X-axis in meters for the first group. -- @param #number XStart The start position on the X-axis in meters for the first group.
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. -- @param #number YStart The start position on the Y-axis in meters for the first group.
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. -- @param #number ZStart The start position on the Z-axis in meters for the first group.
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
-- @return #boolean -- @return #boolean
@ -391,16 +391,16 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
-- @param #string Event -- @param #string Event
-- @param #string To -- @param #string To
-- @param #number XStart The start position on the X-axis in meters for the first group. -- @param #number XStart The start position on the X-axis in meters for the first group.
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. -- @param #number YStart The start position on the Y-axis in meters for the first group.
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. -- @param #number ZStart The start position on the Z-axis in meters for the first group.
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
--- FormationRightLine Trigger for AI_FORMATION --- FormationRightLine Trigger for AI_FORMATION
-- @function [parent=#AI_FORMATION] FormationRightLine -- @function [parent=#AI_FORMATION] FormationRightLine
-- @param #AI_FORMATION self -- @param #AI_FORMATION self
-- @param #number XStart The start position on the X-axis in meters for the first group. -- @param #number XStart The start position on the X-axis in meters for the first group.
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. -- @param #number YStart The start position on the Y-axis in meters for the first group.
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. -- @param #number ZStart The start position on the Z-axis in meters for the first group.
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
--- FormationRightLine Asynchronous Trigger for AI_FORMATION --- FormationRightLine Asynchronous Trigger for AI_FORMATION
@ -408,8 +408,8 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
-- @param #AI_FORMATION self -- @param #AI_FORMATION self
-- @param #number Delay -- @param #number Delay
-- @param #number XStart The start position on the X-axis in meters for the first group. -- @param #number XStart The start position on the X-axis in meters for the first group.
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. -- @param #number YStart The start position on the Y-axis in meters for the first group.
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. -- @param #number ZStart The start position on the Z-axis in meters for the first group.
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
self:AddTransition( "*", "FormationLeftWing", "*" ) self:AddTransition( "*", "FormationLeftWing", "*" )
@ -422,8 +422,8 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
-- @param #string To -- @param #string To
-- @param #number XStart The start position on the X-axis in meters for the first group. -- @param #number XStart The start position on the X-axis in meters for the first group.
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. -- @param #number YStart The start position on the Y-axis in meters for the first group.
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. -- @param #number ZStart The start position on the Z-axis in meters for the first group.
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
-- @return #boolean -- @return #boolean
@ -436,8 +436,8 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
-- @param #string To -- @param #string To
-- @param #number XStart The start position on the X-axis in meters for the first group. -- @param #number XStart The start position on the X-axis in meters for the first group.
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. -- @param #number YStart The start position on the Y-axis in meters for the first group.
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. -- @param #number ZStart The start position on the Z-axis in meters for the first group.
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
--- FormationLeftWing Trigger for AI_FORMATION --- FormationLeftWing Trigger for AI_FORMATION
@ -445,8 +445,8 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
-- @param #AI_FORMATION self -- @param #AI_FORMATION self
-- @param #number XStart The start position on the X-axis in meters for the first group. -- @param #number XStart The start position on the X-axis in meters for the first group.
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. -- @param #number YStart The start position on the Y-axis in meters for the first group.
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. -- @param #number ZStart The start position on the Z-axis in meters for the first group.
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
--- FormationLeftWing Asynchronous Trigger for AI_FORMATION --- FormationLeftWing Asynchronous Trigger for AI_FORMATION
@ -455,8 +455,8 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
-- @param #number Delay -- @param #number Delay
-- @param #number XStart The start position on the X-axis in meters for the first group. -- @param #number XStart The start position on the X-axis in meters for the first group.
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. -- @param #number YStart The start position on the Y-axis in meters for the first group.
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. -- @param #number ZStart The start position on the Z-axis in meters for the first group.
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
self:AddTransition( "*", "FormationRightWing", "*" ) self:AddTransition( "*", "FormationRightWing", "*" )
@ -469,8 +469,8 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
-- @param #string To -- @param #string To
-- @param #number XStart The start position on the X-axis in meters for the first group. -- @param #number XStart The start position on the X-axis in meters for the first group.
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. -- @param #number YStart The start position on the Y-axis in meters for the first group.
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. -- @param #number ZStart The start position on the Z-axis in meters for the first group.
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
-- @return #boolean -- @return #boolean
@ -483,8 +483,8 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
-- @param #string To -- @param #string To
-- @param #number XStart The start position on the X-axis in meters for the first group. -- @param #number XStart The start position on the X-axis in meters for the first group.
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. -- @param #number YStart The start position on the Y-axis in meters for the first group.
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. -- @param #number ZStart The start position on the Z-axis in meters for the first group.
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
--- FormationRightWing Trigger for AI_FORMATION --- FormationRightWing Trigger for AI_FORMATION
@ -492,8 +492,8 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
-- @param #AI_FORMATION self -- @param #AI_FORMATION self
-- @param #number XStart The start position on the X-axis in meters for the first group. -- @param #number XStart The start position on the X-axis in meters for the first group.
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. -- @param #number YStart The start position on the Y-axis in meters for the first group.
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. -- @param #number ZStart The start position on the Z-axis in meters for the first group.
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
--- FormationRightWing Asynchronous Trigger for AI_FORMATION --- FormationRightWing Asynchronous Trigger for AI_FORMATION
@ -502,8 +502,8 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
-- @param #number Delay -- @param #number Delay
-- @param #number XStart The start position on the X-axis in meters for the first group. -- @param #number XStart The start position on the X-axis in meters for the first group.
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. -- @param #number YStart The start position on the Y-axis in meters for the first group.
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. -- @param #number ZStart The start position on the Z-axis in meters for the first group.
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
self:AddTransition( "*", "FormationCenterWing", "*" ) self:AddTransition( "*", "FormationCenterWing", "*" )
@ -516,9 +516,9 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
-- @param #string To -- @param #string To
-- @param #number XStart The start position on the X-axis in meters for the first group. -- @param #number XStart The start position on the X-axis in meters for the first group.
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. -- @param #number YStart The start position on the Y-axis in meters for the first group.
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group. -- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. -- @param #number ZStart The start position on the Z-axis in meters for the first group.
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
-- @return #boolean -- @return #boolean
@ -531,9 +531,9 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
-- @param #string To -- @param #string To
-- @param #number XStart The start position on the X-axis in meters for the first group. -- @param #number XStart The start position on the X-axis in meters for the first group.
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. -- @param #number YStart The start position on the Y-axis in meters for the first group.
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group. -- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. -- @param #number ZStart The start position on the Z-axis in meters for the first group.
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
--- FormationCenterWing Trigger for AI_FORMATION --- FormationCenterWing Trigger for AI_FORMATION
@ -541,9 +541,9 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
-- @param #AI_FORMATION self -- @param #AI_FORMATION self
-- @param #number XStart The start position on the X-axis in meters for the first group. -- @param #number XStart The start position on the X-axis in meters for the first group.
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. -- @param #number YStart The start position on the Y-axis in meters for the first group.
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group. -- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. -- @param #number ZStart The start position on the Z-axis in meters for the first group.
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
--- FormationCenterWing Asynchronous Trigger for AI_FORMATION --- FormationCenterWing Asynchronous Trigger for AI_FORMATION
@ -552,9 +552,9 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
-- @param #number Delay -- @param #number Delay
-- @param #number XStart The start position on the X-axis in meters for the first group. -- @param #number XStart The start position on the X-axis in meters for the first group.
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. -- @param #number YStart The start position on the Y-axis in meters for the first group.
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group. -- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. -- @param #number ZStart The start position on the Z-axis in meters for the first group.
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
self:AddTransition( "*", "FormationVic", "*" ) self:AddTransition( "*", "FormationVic", "*" )
@ -566,9 +566,9 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
-- @param #string To -- @param #string To
-- @param #number XStart The start position on the X-axis in meters for the first group. -- @param #number XStart The start position on the X-axis in meters for the first group.
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. -- @param #number YStart The start position on the Y-axis in meters for the first group.
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group. -- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. -- @param #number ZStart The start position on the Z-axis in meters for the first group.
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
-- @return #boolean -- @return #boolean
@ -580,9 +580,9 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
-- @param #string To -- @param #string To
-- @param #number XStart The start position on the X-axis in meters for the first group. -- @param #number XStart The start position on the X-axis in meters for the first group.
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. -- @param #number YStart The start position on the Y-axis in meters for the first group.
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group. -- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. -- @param #number ZStart The start position on the Z-axis in meters for the first group.
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
--- FormationVic Trigger for AI_FORMATION --- FormationVic Trigger for AI_FORMATION
@ -590,9 +590,9 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
-- @param #AI_FORMATION self -- @param #AI_FORMATION self
-- @param #number XStart The start position on the X-axis in meters for the first group. -- @param #number XStart The start position on the X-axis in meters for the first group.
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. -- @param #number YStart The start position on the Y-axis in meters for the first group.
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group. -- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. -- @param #number ZStart The start position on the Z-axis in meters for the first group.
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
--- FormationVic Asynchronous Trigger for AI_FORMATION --- FormationVic Asynchronous Trigger for AI_FORMATION
@ -601,9 +601,9 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
-- @param #number Delay -- @param #number Delay
-- @param #number XStart The start position on the X-axis in meters for the first group. -- @param #number XStart The start position on the X-axis in meters for the first group.
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. -- @param #number YStart The start position on the Y-axis in meters for the first group.
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group. -- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. -- @param #number ZStart The start position on the Z-axis in meters for the first group.
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
self:AddTransition( "*", "FormationBox", "*" ) self:AddTransition( "*", "FormationBox", "*" )
@ -615,9 +615,9 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
-- @param #string To -- @param #string To
-- @param #number XStart The start position on the X-axis in meters for the first group. -- @param #number XStart The start position on the X-axis in meters for the first group.
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. -- @param #number YStart The start position on the Y-axis in meters for the first group.
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group. -- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. -- @param #number ZStart The start position on the Z-axis in meters for the first group.
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
-- @param #number ZLevels The amount of levels on the Z-axis. -- @param #number ZLevels The amount of levels on the Z-axis.
-- @return #boolean -- @return #boolean
@ -630,9 +630,9 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
-- @param #string To -- @param #string To
-- @param #number XStart The start position on the X-axis in meters for the first group. -- @param #number XStart The start position on the X-axis in meters for the first group.
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. -- @param #number YStart The start position on the Y-axis in meters for the first group.
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group. -- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. -- @param #number ZStart The start position on the Z-axis in meters for the first group.
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
-- @param #number ZLevels The amount of levels on the Z-axis. -- @param #number ZLevels The amount of levels on the Z-axis.
@ -641,9 +641,9 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
-- @param #AI_FORMATION self -- @param #AI_FORMATION self
-- @param #number XStart The start position on the X-axis in meters for the first group. -- @param #number XStart The start position on the X-axis in meters for the first group.
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. -- @param #number YStart The start position on the Y-axis in meters for the first group.
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group. -- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. -- @param #number ZStart The start position on the Z-axis in meters for the first group.
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
-- @param #number ZLevels The amount of levels on the Z-axis. -- @param #number ZLevels The amount of levels on the Z-axis.
@ -653,9 +653,9 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
-- @param #number Delay -- @param #number Delay
-- @param #number XStart The start position on the X-axis in meters for the first group. -- @param #number XStart The start position on the X-axis in meters for the first group.
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. -- @param #number YStart The start position on the Y-axis in meters for the first group.
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group. -- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. -- @param #number ZStart The start position on the Z-axis in meters for the first group.
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
-- @param #number ZLevels The amount of levels on the Z-axis. -- @param #number ZLevels The amount of levels on the Z-axis.
@ -704,9 +704,9 @@ end
-- @param #string To -- @param #string To
-- @param #number XStart The start position on the X-axis in meters for the first group. -- @param #number XStart The start position on the X-axis in meters for the first group.
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. -- @param #number YStart The start position on the Y-axis in meters for the first group.
-- @param #nubmer YSpace The space between groups on the Y-axis in meters for each sequent group. -- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. -- @param #number ZStart The start position on the Z-axis in meters for the first group.
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
-- @return #AI_FORMATION -- @return #AI_FORMATION
function AI_FORMATION:onafterFormationLine( FollowGroupSet, From , Event , To, XStart, XSpace, YStart, YSpace, ZStart, ZSpace, Formation ) --R2.1 function AI_FORMATION:onafterFormationLine( FollowGroupSet, From , Event , To, XStart, XSpace, YStart, YSpace, ZStart, ZSpace, Formation ) --R2.1
@ -751,7 +751,7 @@ end
-- @param #string To -- @param #string To
-- @param #number XStart The start position on the X-axis in meters for the first group. -- @param #number XStart The start position on the X-axis in meters for the first group.
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. -- @param #number YStart The start position on the Y-axis in meters for the first group.
-- @return #AI_FORMATION -- @return #AI_FORMATION
function AI_FORMATION:onafterFormationTrail( FollowGroupSet, From , Event , To, XStart, XSpace, YStart ) --R2.1 function AI_FORMATION:onafterFormationTrail( FollowGroupSet, From , Event , To, XStart, XSpace, YStart ) --R2.1
@ -769,7 +769,7 @@ end
-- @param #string To -- @param #string To
-- @param #number XStart The start position on the X-axis in meters for the first group. -- @param #number XStart The start position on the X-axis in meters for the first group.
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. -- @param #number YStart The start position on the Y-axis in meters for the first group.
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group. -- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
-- @return #AI_FORMATION -- @return #AI_FORMATION
function AI_FORMATION:onafterFormationStack( FollowGroupSet, From , Event , To, XStart, XSpace, YStart, YSpace ) --R2.1 function AI_FORMATION:onafterFormationStack( FollowGroupSet, From , Event , To, XStart, XSpace, YStart, YSpace ) --R2.1
@ -789,8 +789,8 @@ end
-- @param #string Event -- @param #string Event
-- @param #string To -- @param #string To
-- @param #number XStart The start position on the X-axis in meters for the first group. -- @param #number XStart The start position on the X-axis in meters for the first group.
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. -- @param #number YStart The start position on the Y-axis in meters for the first group.
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. -- @param #number ZStart The start position on the Z-axis in meters for the first group.
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
-- @return #AI_FORMATION -- @return #AI_FORMATION
function AI_FORMATION:onafterFormationLeftLine( FollowGroupSet, From , Event , To, XStart, YStart, ZStart, ZSpace ) --R2.1 function AI_FORMATION:onafterFormationLeftLine( FollowGroupSet, From , Event , To, XStart, YStart, ZStart, ZSpace ) --R2.1
@ -808,8 +808,8 @@ end
-- @param #string Event -- @param #string Event
-- @param #string To -- @param #string To
-- @param #number XStart The start position on the X-axis in meters for the first group. -- @param #number XStart The start position on the X-axis in meters for the first group.
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. -- @param #number YStart The start position on the Y-axis in meters for the first group.
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. -- @param #number ZStart The start position on the Z-axis in meters for the first group.
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
-- @return #AI_FORMATION -- @return #AI_FORMATION
function AI_FORMATION:onafterFormationRightLine( FollowGroupSet, From , Event , To, XStart, YStart, ZStart, ZSpace ) --R2.1 function AI_FORMATION:onafterFormationRightLine( FollowGroupSet, From , Event , To, XStart, YStart, ZStart, ZSpace ) --R2.1
@ -828,8 +828,8 @@ end
-- @param #string To -- @param #string To
-- @param #number XStart The start position on the X-axis in meters for the first group. -- @param #number XStart The start position on the X-axis in meters for the first group.
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. -- @param #number YStart The start position on the Y-axis in meters for the first group.
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. -- @param #number ZStart The start position on the Z-axis in meters for the first group.
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
function AI_FORMATION:onafterFormationLeftWing( FollowGroupSet, From , Event , To, XStart, XSpace, YStart, ZStart, ZSpace ) --R2.1 function AI_FORMATION:onafterFormationLeftWing( FollowGroupSet, From , Event , To, XStart, XSpace, YStart, ZStart, ZSpace ) --R2.1
@ -848,8 +848,8 @@ end
-- @param #string To -- @param #string To
-- @param #number XStart The start position on the X-axis in meters for the first group. -- @param #number XStart The start position on the X-axis in meters for the first group.
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. -- @param #number YStart The start position on the Y-axis in meters for the first group.
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. -- @param #number ZStart The start position on the Z-axis in meters for the first group.
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
function AI_FORMATION:onafterFormationRightWing( FollowGroupSet, From , Event , To, XStart, XSpace, YStart, ZStart, ZSpace ) --R2.1 function AI_FORMATION:onafterFormationRightWing( FollowGroupSet, From , Event , To, XStart, XSpace, YStart, ZStart, ZSpace ) --R2.1
@ -867,9 +867,9 @@ end
-- @param #string To -- @param #string To
-- @param #number XStart The start position on the X-axis in meters for the first group. -- @param #number XStart The start position on the X-axis in meters for the first group.
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. -- @param #number YStart The start position on the Y-axis in meters for the first group.
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group. -- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. -- @param #number ZStart The start position on the Z-axis in meters for the first group.
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
function AI_FORMATION:onafterFormationCenterWing( FollowGroupSet, From , Event , To, XStart, XSpace, YStart, YSpace, ZStart, ZSpace ) --R2.1 function AI_FORMATION:onafterFormationCenterWing( FollowGroupSet, From , Event , To, XStart, XSpace, YStart, YSpace, ZStart, ZSpace ) --R2.1
@ -905,9 +905,9 @@ end
-- @param #string To -- @param #string To
-- @param #number XStart The start position on the X-axis in meters for the first group. -- @param #number XStart The start position on the X-axis in meters for the first group.
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. -- @param #number YStart The start position on the Y-axis in meters for the first group.
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group. -- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. -- @param #number ZStart The start position on the Z-axis in meters for the first group.
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
-- @return #AI_FORMATION -- @return #AI_FORMATION
function AI_FORMATION:onafterFormationVic( FollowGroupSet, From , Event , To, XStart, XSpace, YStart, YSpace, ZStart, ZSpace ) --R2.1 function AI_FORMATION:onafterFormationVic( FollowGroupSet, From , Event , To, XStart, XSpace, YStart, YSpace, ZStart, ZSpace ) --R2.1
@ -924,9 +924,9 @@ end
-- @param #string To -- @param #string To
-- @param #number XStart The start position on the X-axis in meters for the first group. -- @param #number XStart The start position on the X-axis in meters for the first group.
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. -- @param #number YStart The start position on the Y-axis in meters for the first group.
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group. -- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. -- @param #number ZStart The start position on the Z-axis in meters for the first group.
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
-- @param #number ZLevels The amount of levels on the Z-axis. -- @param #number ZLevels The amount of levels on the Z-axis.
-- @return #AI_FORMATION -- @return #AI_FORMATION
@ -1065,7 +1065,7 @@ end
-- @param Core.Set#SET_GROUP FollowGroupSet The following set of groups. -- @param Core.Set#SET_GROUP FollowGroupSet The following set of groups.
-- @param #string From From state. -- @param #string From From state.
-- @param #string Event Event. -- @param #string Event Event.
-- @pram #string To The to state. -- @param #string To The to state.
function AI_FORMATION:onafterStop(FollowGroupSet, From, Event, To) --R2.1 function AI_FORMATION:onafterStop(FollowGroupSet, From, Event, To) --R2.1
self:E("Stopping formation.") self:E("Stopping formation.")
end end
@ -1075,7 +1075,7 @@ end
-- @param Core.Set#SET_GROUP FollowGroupSet The following set of groups. -- @param Core.Set#SET_GROUP FollowGroupSet The following set of groups.
-- @param #string From From state. -- @param #string From From state.
-- @param #string Event Event. -- @param #string Event Event.
-- @pram #string To The to state. -- @param #string To The to state.
function AI_FORMATION:onbeforeFollow( FollowGroupSet, From, Event, To ) --R2.1 function AI_FORMATION:onbeforeFollow( FollowGroupSet, From, Event, To ) --R2.1
if From=="Stopped" then if From=="Stopped" then
return false -- Deny transition. return false -- Deny transition.
@ -1083,7 +1083,12 @@ function AI_FORMATION:onbeforeFollow( FollowGroupSet, From, Event, To ) --R2.1
return true return true
end end
--- @param #AI_FORMATION self --- Enter following state.
-- @param #AI_FORMATION self
-- @param Core.Set#SET_GROUP FollowGroupSet The following set of groups.
-- @param #string From From state.
-- @param #string Event Event.
-- @param #string To The to state.
function AI_FORMATION:onenterFollowing( FollowGroupSet ) --R2.1 function AI_FORMATION:onenterFollowing( FollowGroupSet ) --R2.1
if self.FollowUnit:IsAlive() then if self.FollowUnit:IsAlive() then
@ -1093,153 +1098,184 @@ function AI_FORMATION:onenterFollowing( FollowGroupSet ) --R2.1
local CT1, CT2, CV1, CV2 local CT1, CT2, CV1, CV2
CT1 = ClientUnit:GetState( self, "CT1" ) CT1 = ClientUnit:GetState( self, "CT1" )
local CuVec3=ClientUnit:GetVec3()
if CT1 == nil or CT1 == 0 then if CT1 == nil or CT1 == 0 then
ClientUnit:SetState( self, "CV1", ClientUnit:GetPointVec3() ) ClientUnit:SetState( self, "CV1", CuVec3)
ClientUnit:SetState( self, "CT1", timer.getTime() ) ClientUnit:SetState( self, "CT1", timer.getTime() )
else else
CT1 = ClientUnit:GetState( self, "CT1" ) CT1 = ClientUnit:GetState( self, "CT1" )
CT2 = timer.getTime() CT2 = timer.getTime()
CV1 = ClientUnit:GetState( self, "CV1" ) CV1 = ClientUnit:GetState( self, "CV1" )
CV2 = ClientUnit:GetPointVec3() CV2 = CuVec3
ClientUnit:SetState( self, "CT1", CT2 ) ClientUnit:SetState( self, "CT1", CT2 )
ClientUnit:SetState( self, "CV1", CV2 ) ClientUnit:SetState( self, "CV1", CV2 )
end end
FollowGroupSet:ForEachGroupAlive( --FollowGroupSet:ForEachGroupAlive( bla, self, ClientUnit, CT1, CV1, CT2, CV2)
--- @param Wrapper.Group#GROUP FollowGroup
-- @param Wrapper.Unit#UNIT ClientUnit for _,_group in pairs(FollowGroupSet:GetSet()) do
function( FollowGroup, Formation, ClientUnit, CT1, CV1, CT2, CV2 ) local group=_group --Wrapper.Group#GROUP
if group and group:IsAlive() then
if FollowGroup:GetState( FollowGroup, "Mode" ) == self.__Enum.Mode.Formation then self:FollowMe(group, ClientUnit, CT1, CV1, CT2, CV2)
end
self:T({Mode=FollowGroup:GetState( FollowGroup, "Mode" )}) end
FollowGroup:OptionROTEvadeFire()
FollowGroup:OptionROEReturnFire()
local GroupUnit = FollowGroup:GetUnit( 1 )
local FollowFormation = FollowGroup:GetState( self, "FormationVec3" )
if FollowFormation then
local FollowDistance = FollowFormation.x
local GT1 = GroupUnit:GetState( self, "GT1" )
if CT1 == nil or CT1 == 0 or GT1 == nil or GT1 == 0 then
GroupUnit:SetState( self, "GV1", GroupUnit:GetPointVec3() )
GroupUnit:SetState( self, "GT1", timer.getTime() )
else
local CD = ( ( CV2.x - CV1.x )^2 + ( CV2.y - CV1.y )^2 + ( CV2.z - CV1.z )^2 ) ^ 0.5
local CT = CT2 - CT1
local CS = ( 3600 / CT ) * ( CD / 1000 ) / 3.6
local CDv = { x = CV2.x - CV1.x, y = CV2.y - CV1.y, z = CV2.z - CV1.z }
local Ca = math.atan2( CDv.x, CDv.z )
local GT1 = GroupUnit:GetState( self, "GT1" )
local GT2 = timer.getTime()
local GV1 = GroupUnit:GetState( self, "GV1" )
local GV2 = GroupUnit:GetPointVec3()
GV2:AddX( math.random( -Formation.FlightRandomization / 2, Formation.FlightRandomization / 2 ) )
GV2:AddY( math.random( -Formation.FlightRandomization / 2, Formation.FlightRandomization / 2 ) )
GV2:AddZ( math.random( -Formation.FlightRandomization / 2, Formation.FlightRandomization / 2 ) )
GroupUnit:SetState( self, "GT1", GT2 )
GroupUnit:SetState( self, "GV1", GV2 )
local GD = ( ( GV2.x - GV1.x )^2 + ( GV2.y - GV1.y )^2 + ( GV2.z - GV1.z )^2 ) ^ 0.5
local GT = GT2 - GT1
-- Calculate the distance
local GDv = { x = GV2.x - CV1.x, y = GV2.y - CV1.y, z = GV2.z - CV1.z }
local Alpha_T = math.atan2( GDv.x, GDv.z ) - math.atan2( CDv.x, CDv.z )
local Alpha_R = ( Alpha_T < 0 ) and Alpha_T + 2 * math.pi or Alpha_T
local Position = math.cos( Alpha_R )
local GD = ( ( GDv.x )^2 + ( GDv.z )^2 ) ^ 0.5
local Distance = GD * Position + - CS * 0.5
-- Calculate the group direction vector
local GV = { x = GV2.x - CV2.x, y = GV2.y - CV2.y, z = GV2.z - CV2.z }
-- Calculate GH2, GH2 with the same height as CV2.
local GH2 = { x = GV2.x, y = CV2.y + FollowFormation.y, z = GV2.z }
-- Calculate the angle of GV to the orthonormal plane
local alpha = math.atan2( GV.x, GV.z )
local GVx = FollowFormation.z * math.cos( Ca ) + FollowFormation.x * math.sin( Ca )
local GVz = FollowFormation.x * math.cos( Ca ) - FollowFormation.z * math.sin( Ca )
-- Now we calculate the intersecting vector between the circle around CV2 with radius FollowDistance and GH2.
-- From the GeoGebra model: CVI = (x(CV2) + FollowDistance cos(alpha), y(GH2) + FollowDistance sin(alpha), z(CV2))
local Inclination = ( Distance + FollowFormation.x ) / 10
if Inclination < -30 then
Inclination = - 30
end
local CVI = { x = CV2.x + CS * 10 * math.sin(Ca),
y = GH2.y + Inclination, -- + FollowFormation.y,
y = GH2.y,
z = CV2.z + CS * 10 * math.cos(Ca),
}
-- Calculate the direction vector DV of the escort group. We use CVI as the base and CV2 as the direction.
local DV = { x = CV2.x - CVI.x, y = CV2.y - CVI.y, z = CV2.z - CVI.z }
-- We now calculate the unary direction vector DVu, so that we can multiply DVu with the speed, which is expressed in meters / s.
-- We need to calculate this vector to predict the point the escort group needs to fly to according its speed.
-- The distance of the destination point should be far enough not to have the aircraft starting to swipe left to right...
local DVu = { x = DV.x / FollowDistance, y = DV.y, z = DV.z / FollowDistance }
-- Now we can calculate the group destination vector GDV.
local GDV = { x = CVI.x, y = CVI.y, z = CVI.z }
local ADDx = FollowFormation.x * math.cos(alpha) - FollowFormation.z * math.sin(alpha)
local ADDz = FollowFormation.z * math.cos(alpha) + FollowFormation.x * math.sin(alpha)
local GDV_Formation = {
x = GDV.x - GVx,
y = GDV.y,
z = GDV.z - GVz
}
if self.SmokeDirectionVector == true then
trigger.action.smoke( GDV, trigger.smokeColor.Green )
trigger.action.smoke( GDV_Formation, trigger.smokeColor.White )
end
local Time = 120
local Speed = - ( Distance + FollowFormation.x ) / Time
if Distance > -10000 then
Speed = - ( Distance + FollowFormation.x ) / 60
end
if Distance > -2500 then
Speed = - ( Distance + FollowFormation.x ) / 20
end
local GS = Speed + CS
self:F( { Distance = Distance, Speed = Speed, CS = CS, GS = GS } )
-- Now route the escort to the desired point with the desired speed.
FollowGroup:RouteToVec3( GDV_Formation, GS ) -- DCS models speed in Mps (Miles per second)
end
end
end
end,
self, ClientUnit, CT1, CV1, CT2, CV2
)
self:__Follow( -self.dtFollow ) self:__Follow( -self.dtFollow )
end end
end end
--- Follow me.
-- @param #AI_FORMATION self
-- @param Wrapper.Group#GROUP FollowGroup Follow group.
-- @param Wrapper.Unit#UNIT ClientUnit Client Unit.
-- @param DCS#Time CT1 Time
-- @param DCS#Vec3 CV1 Vec3
-- @param DCS#Time CT2 Time
-- @param DCS#Vec3 CV2 Vec3
function AI_FORMATION:FollowMe(FollowGroup, ClientUnit, CT1, CV1, CT2, CV2)
if FollowGroup:GetState( FollowGroup, "Mode" ) == self.__Enum.Mode.Formation then
self:T({Mode=FollowGroup:GetState( FollowGroup, "Mode" )})
FollowGroup:OptionROTEvadeFire()
FollowGroup:OptionROEReturnFire()
local GroupUnit = FollowGroup:GetUnit( 1 )
local GuVec3=GroupUnit:GetVec3()
local FollowFormation = FollowGroup:GetState( self, "FormationVec3" )
if FollowFormation then
local FollowDistance = FollowFormation.x
local GT1 = GroupUnit:GetState( self, "GT1" )
if CT1 == nil or CT1 == 0 or GT1 == nil or GT1 == 0 then
GroupUnit:SetState( self, "GV1", GuVec3)
GroupUnit:SetState( self, "GT1", timer.getTime() )
else
local CD = ( ( CV2.x - CV1.x )^2 + ( CV2.y - CV1.y )^2 + ( CV2.z - CV1.z )^2 ) ^ 0.5
local CT = CT2 - CT1
local CS = ( 3600 / CT ) * ( CD / 1000 ) / 3.6
local CDv = { x = CV2.x - CV1.x, y = CV2.y - CV1.y, z = CV2.z - CV1.z }
local Ca = math.atan2( CDv.x, CDv.z )
local GT1 = GroupUnit:GetState( self, "GT1" )
local GT2 = timer.getTime()
local GV1 = GroupUnit:GetState( self, "GV1" )
local GV2 = GuVec3
--[[
GV2:AddX( math.random( -Formation.FlightRandomization / 2, Formation.FlightRandomization / 2 ) )
GV2:AddY( math.random( -Formation.FlightRandomization / 2, Formation.FlightRandomization / 2 ) )
GV2:AddZ( math.random( -Formation.FlightRandomization / 2, Formation.FlightRandomization / 2 ) )
]]
GV2.x=GV2.x+math.random( -self.FlightRandomization / 2, self.FlightRandomization / 2 )
GV2.y=GV2.y+math.random( -self.FlightRandomization / 2, self.FlightRandomization / 2 )
GV2.z=GV2.z+math.random( -self.FlightRandomization / 2, self.FlightRandomization / 2 )
GroupUnit:SetState( self, "GT1", GT2 )
GroupUnit:SetState( self, "GV1", GV2 )
local GD = ( ( GV2.x - GV1.x )^2 + ( GV2.y - GV1.y )^2 + ( GV2.z - GV1.z )^2 ) ^ 0.5
local GT = GT2 - GT1
-- Calculate the distance
local GDv = { x = GV2.x - CV1.x, y = GV2.y - CV1.y, z = GV2.z - CV1.z }
local Alpha_T = math.atan2( GDv.x, GDv.z ) - math.atan2( CDv.x, CDv.z )
local Alpha_R = ( Alpha_T < 0 ) and Alpha_T + 2 * math.pi or Alpha_T
local Position = math.cos( Alpha_R )
local GD = ( ( GDv.x )^2 + ( GDv.z )^2 ) ^ 0.5
local Distance = GD * Position + - CS * 0.5
-- Calculate the group direction vector
local GV = { x = GV2.x - CV2.x, y = GV2.y - CV2.y, z = GV2.z - CV2.z }
-- Calculate GH2, GH2 with the same height as CV2.
local GH2 = { x = GV2.x, y = CV2.y + FollowFormation.y, z = GV2.z }
-- Calculate the angle of GV to the orthonormal plane
local alpha = math.atan2( GV.x, GV.z )
local GVx = FollowFormation.z * math.cos( Ca ) + FollowFormation.x * math.sin( Ca )
local GVz = FollowFormation.x * math.cos( Ca ) - FollowFormation.z * math.sin( Ca )
-- Now we calculate the intersecting vector between the circle around CV2 with radius FollowDistance and GH2.
-- From the GeoGebra model: CVI = (x(CV2) + FollowDistance cos(alpha), y(GH2) + FollowDistance sin(alpha), z(CV2))
local Inclination = ( Distance + FollowFormation.x ) / 10
if Inclination < -30 then
Inclination = - 30
end
local CVI = {
x = CV2.x + CS * 10 * math.sin(Ca),
y = GH2.y + Inclination, -- + FollowFormation.y,
y = GH2.y,
z = CV2.z + CS * 10 * math.cos(Ca),
}
-- Calculate the direction vector DV of the escort group. We use CVI as the base and CV2 as the direction.
local DV = { x = CV2.x - CVI.x, y = CV2.y - CVI.y, z = CV2.z - CVI.z }
-- We now calculate the unary direction vector DVu, so that we can multiply DVu with the speed, which is expressed in meters / s.
-- We need to calculate this vector to predict the point the escort group needs to fly to according its speed.
-- The distance of the destination point should be far enough not to have the aircraft starting to swipe left to right...
local DVu = { x = DV.x / FollowDistance, y = DV.y, z = DV.z / FollowDistance }
-- Now we can calculate the group destination vector GDV.
local GDV = { x = CVI.x, y = CVI.y, z = CVI.z }
local ADDx = FollowFormation.x * math.cos(alpha) - FollowFormation.z * math.sin(alpha)
local ADDz = FollowFormation.z * math.cos(alpha) + FollowFormation.x * math.sin(alpha)
local GDV_Formation = {
x = GDV.x - GVx,
y = GDV.y,
z = GDV.z - GVz
}
-- Debug smoke.
if self.SmokeDirectionVector == true then
trigger.action.smoke( GDV, trigger.smokeColor.Green )
trigger.action.smoke( GDV_Formation, trigger.smokeColor.White )
end
local Time = 120
local Speed = - ( Distance + FollowFormation.x ) / Time
if Distance > -10000 then
Speed = - ( Distance + FollowFormation.x ) / 60
end
if Distance > -2500 then
Speed = - ( Distance + FollowFormation.x ) / 20
end
local GS = Speed + CS
--self:F( { Distance = Distance, Speed = Speed, CS = CS, GS = GS } )
-- Now route the escort to the desired point with the desired speed.
FollowGroup:RouteToVec3( GDV_Formation, GS ) -- DCS models speed in Mps (Miles per second)
end
end
end
end

View File

@ -26,8 +26,6 @@
-- @module Core.Base -- @module Core.Base
-- @image Core_Base.JPG -- @image Core_Base.JPG
local _TraceOnOff = true local _TraceOnOff = true
local _TraceLevel = 1 local _TraceLevel = 1
local _TraceAll = false local _TraceAll = false
@ -256,6 +254,8 @@ end
-- @param #BASE Parent is the Parent class that the Child inherits from. -- @param #BASE Parent is the Parent class that the Child inherits from.
-- @return #BASE Child -- @return #BASE Child
function BASE:Inherit( Child, Parent ) function BASE:Inherit( Child, Parent )
-- Create child.
local Child = routines.utils.deepCopy( Child ) local Child = routines.utils.deepCopy( Child )
if Child ~= nil then if Child ~= nil then
@ -271,6 +271,7 @@ function BASE:Inherit( Child, Parent )
--Child:_SetDestructor() --Child:_SetDestructor()
end end
return Child return Child
end end

View File

@ -896,31 +896,25 @@ function DATABASE:_RegisterStatics()
return self return self
end end
--- @param #DATABASE self --- Register all world airbases.
-- @param #DATABASE self
-- @return #DATABASE self
function DATABASE:_RegisterAirbases() function DATABASE:_RegisterAirbases()
--[[
local CoalitionsData = { AirbasesRed = coalition.getAirbases( coalition.side.RED ), AirbasesBlue = coalition.getAirbases( coalition.side.BLUE ), AirbasesNeutral = coalition.getAirbases( coalition.side.NEUTRAL ) }
for CoalitionId, CoalitionData in pairs( CoalitionsData ) do
for DCSAirbaseId, DCSAirbase in pairs( CoalitionData ) do
local DCSAirbaseName = DCSAirbase:getName()
self:T( { "Register Airbase:", DCSAirbaseName, DCSAirbase:getID() } )
self:AddAirbase( DCSAirbaseName )
end
end
]]
for DCSAirbaseId, DCSAirbase in pairs(world.getAirbases()) do for DCSAirbaseId, DCSAirbase in pairs(world.getAirbases()) do
local DCSAirbaseName = DCSAirbase:getName()
-- This gives the incorrect value to be inserted into the airdromeID for DCS 2.5.6! -- Get the airbase name.
local airbaseID=DCSAirbase:getID() local DCSAirbaseName = DCSAirbase:getName()
local airbase=self:AddAirbase( DCSAirbaseName ) -- This gave the incorrect value to be inserted into the airdromeID for DCS 2.5.6. Is fixed now.
local airbaseID=DCSAirbase:getID()
-- Add and register airbase.
local airbase=self:AddAirbase( DCSAirbaseName )
-- Debug output.
self:I(string.format("Register Airbase: %s, getID=%d, GetID=%d (unique=%d)", DCSAirbaseName, DCSAirbase:getID(), airbase:GetID(), airbase:GetID(true)))
self:I(string.format("Register Airbase: %s, getID=%d, GetID=%d (unique=%d)", DCSAirbaseName, DCSAirbase:getID(), airbase:GetID(), airbase:GetID(true)))
end end
return self return self

View File

@ -1001,6 +1001,16 @@ function EVENT:onEvent( Event )
Event.IniCategory = Event.IniDCSUnit:getDesc().category Event.IniCategory = Event.IniDCSUnit:getDesc().category
Event.IniTypeName = Event.initiator:isExist() and Event.IniDCSUnit:getTypeName() or "SCENERY" -- TODO: Bug fix for 2.1! Event.IniTypeName = Event.initiator:isExist() and Event.IniDCSUnit:getTypeName() or "SCENERY" -- TODO: Bug fix for 2.1!
end end
if Event.IniObjectCategory == Object.Category.BASE then
Event.IniDCSUnit = Event.initiator
Event.IniDCSUnitName = Event.IniDCSUnit:getName()
Event.IniUnitName = Event.IniDCSUnitName
Event.IniUnit = AIRBASE:FindByName(Event.IniDCSUnitName)
Event.IniCoalition = Event.IniDCSUnit:getCoalition()
Event.IniCategory = Event.IniDCSUnit:getDesc().category
Event.IniTypeName = Event.IniDCSUnit:getTypeName()
end
end end
if Event.target then if Event.target then

View File

@ -71,7 +71,7 @@
-- --
-- --
-- ### Author: **FlightControl** -- ### Author: **FlightControl**
-- ### Contributions: -- ### Contributions: **funkyfranky**
-- --
-- === -- ===
-- --
@ -81,6 +81,12 @@
do -- FSM do -- FSM
--- @type FSM --- @type FSM
-- @field #string ClassName Name of the class.
-- @field Core.Scheduler#SCHEDULER CallScheduler Call scheduler.
-- @field #table options Options.
-- @field #table subs Subs.
-- @field #table Scores Scores.
-- @field #string current Current state name.
-- @extends Core.Base#BASE -- @extends Core.Base#BASE
@ -369,8 +375,7 @@ do -- FSM
self._EventSchedules = {} self._EventSchedules = {}
self.CallScheduler = SCHEDULER:New( self ) self.CallScheduler = SCHEDULER:New( self )
return self return self
end end
@ -379,7 +384,6 @@ do -- FSM
-- @param #FSM self -- @param #FSM self
-- @param #string State A string defining the start state. -- @param #string State A string defining the start state.
function FSM:SetStartState( State ) function FSM:SetStartState( State )
self._StartState = State self._StartState = State
self.current = State self.current = State
end end
@ -389,7 +393,6 @@ do -- FSM
-- @param #FSM self -- @param #FSM self
-- @return #string A string containing the start state. -- @return #string A string containing the start state.
function FSM:GetStartState() function FSM:GetStartState()
return self._StartState or {} return self._StartState or {}
end end
@ -406,6 +409,7 @@ do -- FSM
Transition.Event = Event Transition.Event = Event
Transition.To = To Transition.To = To
-- Debug message.
self:T2( Transition ) self:T2( Transition )
self._Transitions[Transition] = Transition self._Transitions[Transition] = Transition
@ -414,9 +418,9 @@ do -- FSM
--- Returns a table of the transition rules defined within the FSM. --- Returns a table of the transition rules defined within the FSM.
-- @return #table -- @param #FSM self
function FSM:GetTransitions() -- @return #table Transitions.
function FSM:GetTransitions()
return self._Transitions or {} return self._Transitions or {}
end end
@ -448,7 +452,8 @@ do -- FSM
--- Returns a table of the SubFSM rules defined within the FSM. --- Returns a table of the SubFSM rules defined within the FSM.
-- @return #table -- @param #FSM self
-- @return #table Sub processes.
function FSM:GetProcesses() function FSM:GetProcesses()
self:F( { Processes = self._Processes } ) self:F( { Processes = self._Processes } )
@ -480,15 +485,17 @@ do -- FSM
end end
--- Adds an End state. --- Adds an End state.
function FSM:AddEndState( State ) -- @param #FSM self
-- @param #string State The FSM state.
function FSM:AddEndState( State )
self._EndStates[State] = State self._EndStates[State] = State
self.endstates[State] = State self.endstates[State] = State
end end
--- Returns the End states. --- Returns the End states.
function FSM:GetEndStates() -- @param #FSM self
-- @return #table End states.
function FSM:GetEndStates()
return self._EndStates or {} return self._EndStates or {}
end end
@ -532,18 +539,22 @@ do -- FSM
end end
--- Returns a table with the scores defined. --- Returns a table with the scores defined.
function FSM:GetScores() -- @param #FSM self
-- @param #table Scores.
function FSM:GetScores()
return self._Scores or {} return self._Scores or {}
end end
--- Returns a table with the Subs defined. --- Returns a table with the Subs defined.
function FSM:GetSubs() -- @param #FSM self
-- @return #table Sub processes.
function FSM:GetSubs()
return self.options.subs return self.options.subs
end end
--- Load call backs.
-- @param #FSM self
-- @param #table CallBackTable Table of call backs.
function FSM:LoadCallBacks( CallBackTable ) function FSM:LoadCallBacks( CallBackTable )
for name, callback in pairs( CallBackTable or {} ) do for name, callback in pairs( CallBackTable or {} ) do
@ -551,21 +562,34 @@ do -- FSM
end end
end end
--- Event map.
-- @param #FSM self
-- @param #table Events Events.
-- @param #table EventStructure Event structure.
function FSM:_eventmap( Events, EventStructure ) function FSM:_eventmap( Events, EventStructure )
local Event = EventStructure.Event local Event = EventStructure.Event
local __Event = "__" .. EventStructure.Event local __Event = "__" .. EventStructure.Event
self[Event] = self[Event] or self:_create_transition(Event) self[Event] = self[Event] or self:_create_transition(Event)
self[__Event] = self[__Event] or self:_delayed_transition(Event) self[__Event] = self[__Event] or self:_delayed_transition(Event)
-- Debug message.
self:T2( "Added methods: " .. Event .. ", " .. __Event ) self:T2( "Added methods: " .. Event .. ", " .. __Event )
Events[Event] = self.Events[Event] or { map = {} } Events[Event] = self.Events[Event] or { map = {} }
self:_add_to_map( Events[Event].map, EventStructure ) self:_add_to_map( Events[Event].map, EventStructure )
end end
--- Sub maps.
-- @param #FSM self
-- @param #table subs Subs.
-- @param #table sub Sub.
-- @param #string name Name.
function FSM:_submap( subs, sub, name ) function FSM:_submap( subs, sub, name )
--self:F( { sub = sub, name = name } )
subs[sub.From] = subs[sub.From] or {} subs[sub.From] = subs[sub.From] or {}
subs[sub.From][sub.Event] = subs[sub.From][sub.Event] or {} subs[sub.From][sub.Event] = subs[sub.From][sub.Event] or {}
@ -578,22 +602,24 @@ do -- FSM
subs[sub.From][sub.Event][sub].ReturnEvents = sub.ReturnEvents or {} -- these events need to be given to find the correct continue event ... if none given, the processing will stop. subs[sub.From][sub.Event][sub].ReturnEvents = sub.ReturnEvents or {} -- these events need to be given to find the correct continue event ... if none given, the processing will stop.
subs[sub.From][sub.Event][sub].name = name subs[sub.From][sub.Event][sub].name = name
subs[sub.From][sub.Event][sub].fsmparent = self subs[sub.From][sub.Event][sub].fsmparent = self
end end
--- Call handler.
-- @param #FSM self
-- @param #string step Step "onafter", "onbefore", "onenter", "onleave".
-- @param #string trigger Trigger.
-- @param #table params Parameters.
-- @param #string EventName Event name.
-- @return Value.
function FSM:_call_handler( step, trigger, params, EventName ) function FSM:_call_handler( step, trigger, params, EventName )
--env.info(string.format("FF T=%.3f _call_handler step=%s, trigger=%s, event=%s", timer.getTime(), step, trigger, EventName))
local handler = step .. trigger local handler = step .. trigger
local ErrorHandler = function( errmsg )
env.info( "Error in SCHEDULER function:" .. errmsg )
if BASE.Debug ~= nil then
env.info( BASE.Debug.traceback() )
end
return errmsg
end
if self[handler] then if self[handler] then
--[[
if step == "onafter" or step == "OnAfter" then if step == "onafter" or step == "OnAfter" then
self:T( ":::>" .. step .. params[2] .. " : " .. params[1] .. " >> " .. params[2] .. ">" .. step .. params[2] .. "()" .. " >> " .. params[3] ) self:T( ":::>" .. step .. params[2] .. " : " .. params[1] .. " >> " .. params[2] .. ">" .. step .. params[2] .. "()" .. " >> " .. params[3] )
elseif step == "onbefore" or step == "OnBefore" then elseif step == "onbefore" or step == "OnBefore" then
@ -604,14 +630,33 @@ do -- FSM
self:T( ":::>" .. step .. params[1] .. " : " .. params[1] .. ">" .. step .. params[1] .. "()" .. " >> " .. params[2] .. " >> " .. params[3] ) self:T( ":::>" .. step .. params[1] .. " : " .. params[1] .. ">" .. step .. params[1] .. "()" .. " >> " .. params[2] .. " >> " .. params[3] )
else else
self:T( ":::>" .. step .. " : " .. params[1] .. " >> " .. params[2] .. " >> " .. params[3] ) self:T( ":::>" .. step .. " : " .. params[1] .. " >> " .. params[2] .. " >> " .. params[3] )
end end
]]
self._EventSchedules[EventName] = nil self._EventSchedules[EventName] = nil
local Result, Value = xpcall( function() return self[handler]( self, unpack( params ) ) end, ErrorHandler )
return Value -- Error handler.
local ErrorHandler = function( errmsg )
env.info( "Error in SCHEDULER function:" .. errmsg )
if BASE.Debug ~= nil then
env.info( BASE.Debug.traceback() )
end
return errmsg
end
--return self[handler](self, unpack( params ))
-- Protected call.
local Result, Value = xpcall( function() return self[handler]( self, unpack( params ) ) end, ErrorHandler )
return Value
end end
end end
--- @param #FSM self --- Handler.
-- @param #FSM self
-- @param #string EventName Event name.
-- @param ... Arguments.
function FSM._handler( self, EventName, ... ) function FSM._handler( self, EventName, ... )
local Can, To = self:can( EventName ) local Can, To = self:can( EventName )
@ -621,7 +666,11 @@ do -- FSM
end end
if Can then if Can then
-- From state.
local From = self.current local From = self.current
-- Parameters.
local Params = { From, EventName, To, ... } local Params = { From, EventName, To, ... }
@ -632,8 +681,8 @@ do -- FSM
self["onafter".. EventName] or self["onafter".. EventName] or
self["OnAfter".. EventName] or self["OnAfter".. EventName] or
self["onenter".. To] or self["onenter".. To] or
self["OnEnter".. To] self["OnEnter".. To] then
then
if self:_call_handler( "onbefore", EventName, Params, EventName ) == false then if self:_call_handler( "onbefore", EventName, Params, EventName ) == false then
self:T( "*** FSM *** Cancel" .. " *** " .. self.current .. " --> " .. EventName .. " --> " .. To .. " *** onbefore" .. EventName ) self:T( "*** FSM *** Cancel" .. " *** " .. self.current .. " --> " .. EventName .. " --> " .. To .. " *** onbefore" .. EventName )
return false return false
@ -653,8 +702,11 @@ do -- FSM
end end
end end
end end
else else
local ClassName = self:GetClassName() local ClassName = self:GetClassName()
if ClassName == "FSM" then if ClassName == "FSM" then
self:T( "*** FSM *** Transit *** " .. self.current .. " --> " .. EventName .. " --> " .. To ) self:T( "*** FSM *** Transit *** " .. self.current .. " --> " .. EventName .. " --> " .. To )
end end
@ -672,46 +724,56 @@ do -- FSM
end end
end end
-- New current state.
self.current = To self.current = To
local execute = true local execute = true
local subtable = self:_gosub( From, EventName ) local subtable = self:_gosub( From, EventName )
for _, sub in pairs( subtable ) do for _, sub in pairs( subtable ) do
--if sub.nextevent then --if sub.nextevent then
-- self:F2( "nextevent = " .. sub.nextevent ) -- self:F2( "nextevent = " .. sub.nextevent )
-- self[sub.nextevent]( self ) -- self[sub.nextevent]( self )
--end --end
self:T( "*** FSM *** Sub *** " .. sub.StartEvent ) self:T( "*** FSM *** Sub *** " .. sub.StartEvent )
sub.fsm.fsmparent = self sub.fsm.fsmparent = self
sub.fsm.ReturnEvents = sub.ReturnEvents sub.fsm.ReturnEvents = sub.ReturnEvents
sub.fsm[sub.StartEvent]( sub.fsm ) sub.fsm[sub.StartEvent]( sub.fsm )
execute = false execute = false
end end
local fsmparent, Event = self:_isendstate( To ) local fsmparent, Event = self:_isendstate( To )
if fsmparent and Event then if fsmparent and Event then
self:T( "*** FSM *** End *** " .. Event ) self:T( "*** FSM *** End *** " .. Event )
self:_call_handler("onenter", To, Params, EventName ) self:_call_handler("onenter", To, Params, EventName )
self:_call_handler("OnEnter", To, Params, EventName ) self:_call_handler("OnEnter", To, Params, EventName )
self:_call_handler("onafter", EventName, Params, EventName ) self:_call_handler("onafter", EventName, Params, EventName )
self:_call_handler("OnAfter", EventName, Params, EventName ) self:_call_handler("OnAfter", EventName, Params, EventName )
self:_call_handler("onstate", "change", Params, EventName ) self:_call_handler("onstate", "change", Params, EventName )
fsmparent[Event]( fsmparent ) fsmparent[Event]( fsmparent )
execute = false execute = false
end end
if execute then if execute then
self:_call_handler("onafter", EventName, Params, EventName )
self:_call_handler("OnAfter", EventName, Params, EventName )
-- only execute the call if the From state is not equal to the To state! Otherwise this function should never execute! self:_call_handler("onafter", EventName, Params, EventName )
--if from ~= to then self:_call_handler("OnAfter", EventName, Params, EventName )
self:_call_handler("onenter", To, Params, EventName )
self:_call_handler("OnEnter", To, Params, EventName ) self:_call_handler("onenter", To, Params, EventName )
--end self:_call_handler("OnEnter", To, Params, EventName )
self:_call_handler("onstate", "change", Params, EventName ) self:_call_handler("onstate", "change", Params, EventName )
end end
else else
self:T( "*** FSM *** NO Transition *** " .. self.current .. " --> " .. EventName .. " --> ? " ) self:T( "*** FSM *** NO Transition *** " .. self.current .. " --> " .. EventName .. " --> ? " )
@ -719,37 +781,68 @@ do -- FSM
return nil return nil
end end
--- Delayed transition.
-- @param #FSM self
-- @param #string EventName Event name.
-- @return #function Function.
function FSM:_delayed_transition( EventName ) function FSM:_delayed_transition( EventName )
return function( self, DelaySeconds, ... ) return function( self, DelaySeconds, ... )
-- Debug.
self:T2( "Delayed Event: " .. EventName ) self:T2( "Delayed Event: " .. EventName )
local CallID = 0 local CallID = 0
if DelaySeconds ~= nil then if DelaySeconds ~= nil then
if DelaySeconds < 0 then -- Only call the event ONCE! if DelaySeconds < 0 then -- Only call the event ONCE!
DelaySeconds = math.abs( DelaySeconds ) DelaySeconds = math.abs( DelaySeconds )
if not self._EventSchedules[EventName] then
if not self._EventSchedules[EventName] then
-- Call _handler.
CallID = self.CallScheduler:Schedule( self, self._handler, { EventName, ... }, DelaySeconds or 1, nil, nil, nil, 4, true ) CallID = self.CallScheduler:Schedule( self, self._handler, { EventName, ... }, DelaySeconds or 1, nil, nil, nil, 4, true )
-- Set call ID.
self._EventSchedules[EventName] = CallID self._EventSchedules[EventName] = CallID
-- Debug output.
self:T2(string.format("NEGATIVE Event %s delayed by %.1f sec SCHEDULED with CallID=%s", EventName, DelaySeconds, tostring(CallID))) self:T2(string.format("NEGATIVE Event %s delayed by %.1f sec SCHEDULED with CallID=%s", EventName, DelaySeconds, tostring(CallID)))
else else
self:T2(string.format("NEGATIVE Event %s delayed by %.1f sec CANCELLED as we already have such an event in the queue.", EventName, DelaySeconds)) self:T2(string.format("NEGATIVE Event %s delayed by %.1f sec CANCELLED as we already have such an event in the queue.", EventName, DelaySeconds))
-- reschedule -- reschedule
end end
else else
CallID = self.CallScheduler:Schedule( self, self._handler, { EventName, ... }, DelaySeconds or 1, nil, nil, nil, 4, true ) CallID = self.CallScheduler:Schedule( self, self._handler, { EventName, ... }, DelaySeconds or 1, nil, nil, nil, 4, true )
self:T2(string.format("Event %s delayed by %.1f sec SCHEDULED with CallID=%s", EventName, DelaySeconds, tostring(CallID))) self:T2(string.format("Event %s delayed by %.1f sec SCHEDULED with CallID=%s", EventName, DelaySeconds, tostring(CallID)))
end end
else else
error( "FSM: An asynchronous event trigger requires a DelaySeconds parameter!!! This can be positive or negative! Sorry, but will not process this." ) error( "FSM: An asynchronous event trigger requires a DelaySeconds parameter!!! This can be positive or negative! Sorry, but will not process this." )
end end
-- Debug.
self:T2( { CallID = CallID } ) self:T2( { CallID = CallID } )
end end
end end
--- Create transition.
-- @param #FSM self
-- @param #string EventName Event name.
-- @return #function Function.
function FSM:_create_transition( EventName ) function FSM:_create_transition( EventName )
return function( self, ... ) return self._handler( self, EventName , ... ) end return function( self, ... ) return self._handler( self, EventName , ... ) end
end end
--- Go sub.
-- @param #FSM self
-- @param #string ParentFrom Parent from state.
-- @param #string ParentEvent Parent event name.
-- @return #table Subs.
function FSM:_gosub( ParentFrom, ParentEvent ) function FSM:_gosub( ParentFrom, ParentEvent )
local fsmtable = {} local fsmtable = {}
if self.subs[ParentFrom] and self.subs[ParentFrom][ParentEvent] then if self.subs[ParentFrom] and self.subs[ParentFrom][ParentEvent] then
@ -759,9 +852,15 @@ do -- FSM
return {} return {}
end end
end end
--- Is end state.
-- @param #FSM self
-- @param #string Current Current state name.
-- @return #table FSM parent.
-- @return #string Event name.
function FSM:_isendstate( Current ) function FSM:_isendstate( Current )
local FSMParent = self.fsmparent local FSMParent = self.fsmparent
if FSMParent and self.endstates[Current] then if FSMParent and self.endstates[Current] then
--self:T( { state = Current, endstates = self.endstates, endstate = self.endstates[Current] } ) --self:T( { state = Current, endstates = self.endstates, endstate = self.endstates[Current] } )
FSMParent.current = Current FSMParent.current = Current
@ -778,9 +877,14 @@ do -- FSM
return nil return nil
end end
--- Add to map.
-- @param #FSM self
-- @param #table Map Map.
-- @param #table Event Event table.
function FSM:_add_to_map( Map, Event ) function FSM:_add_to_map( Map, Event )
self:F3( { Map, Event } ) self:F3( { Map, Event } )
if type(Event.From) == 'string' then if type(Event.From) == 'string' then
Map[Event.From] = Event.To Map[Event.From] = Event.To
else else
@ -788,33 +892,60 @@ do -- FSM
Map[From] = Event.To Map[From] = Event.To
end end
end end
self:T3( { Map, Event } ) self:T3( { Map, Event } )
end end
--- Get current state.
-- @param #FSM self
-- @return #string Current FSM state.
function FSM:GetState() function FSM:GetState()
return self.current return self.current
end end
--- Get current state.
-- @param #FSM self
-- @return #string Current FSM state.
function FSM:GetCurrentState() function FSM:GetCurrentState()
return self.current return self.current
end end
--- Check if FSM is in state.
-- @param #FSM self
-- @param #string State State name.
-- @param #boolean If true, FSM is in this state.
function FSM:Is( State ) function FSM:Is( State )
return self.current == State return self.current == State
end end
--- Check if FSM is in state.
-- @param #FSM self
-- @param #string State State name.
-- @param #boolean If true, FSM is in this state.
function FSM:is(state) function FSM:is(state)
return self.current == state return self.current == state
end end
--- Check if can do an event.
-- @param #FSM self
-- @param #string e Event name.
-- @return #boolean If true, FSM can do the event.
-- @return #string To state.
function FSM:can(e) function FSM:can(e)
local Event = self.Events[e] local Event = self.Events[e]
self:F3( { self.current, Event } )
--self:F3( { self.current, Event } )
local To = Event and Event.map[self.current] or Event.map['*'] local To = Event and Event.map[self.current] or Event.map['*']
return To ~= nil, To return To ~= nil, To
end end
--- Check if cannot do an event.
-- @param #FSM self
-- @param #string e Event name.
-- @return #boolean If true, FSM cannot do the event.
function FSM:cannot(e) function FSM:cannot(e)
return not self:can(e) return not self:can(e)
end end

View File

@ -175,10 +175,6 @@ do -- COORDINATE
-- In order to use the most optimal road system to transport vehicles, the method @{#COORDINATE.GetPathOnRoad}() will calculate -- In order to use the most optimal road system to transport vehicles, the method @{#COORDINATE.GetPathOnRoad}() will calculate
-- the most optimal path following the road between two coordinates. -- the most optimal path following the road between two coordinates.
-- --
--
--
--
--
-- ## 8) Metric or imperial system -- ## 8) Metric or imperial system
-- --
-- * @{#COORDINATE.IsMetric}(): Returns if the 3D point is Metric or Nautical Miles. -- * @{#COORDINATE.IsMetric}(): Returns if the 3D point is Metric or Nautical Miles.
@ -204,23 +200,23 @@ do -- COORDINATE
--- @field COORDINATE.WaypointAction --- @field COORDINATE.WaypointAction
COORDINATE.WaypointAction = { COORDINATE.WaypointAction = {
TurningPoint = "Turning Point", TurningPoint = "Turning Point",
FlyoverPoint = "Fly Over Point", FlyoverPoint = "Fly Over Point",
FromParkingArea = "From Parking Area", FromParkingArea = "From Parking Area",
FromParkingAreaHot = "From Parking Area Hot", FromParkingAreaHot = "From Parking Area Hot",
FromRunway = "From Runway", FromRunway = "From Runway",
Landing = "Landing", Landing = "Landing",
LandingReFuAr = "LandingReFuAr", LandingReFuAr = "LandingReFuAr",
} }
--- @field COORDINATE.WaypointType --- @field COORDINATE.WaypointType
COORDINATE.WaypointType = { COORDINATE.WaypointType = {
TakeOffParking = "TakeOffParking", TakeOffParking = "TakeOffParking",
TakeOffParkingHot = "TakeOffParkingHot", TakeOffParkingHot = "TakeOffParkingHot",
TakeOff = "TakeOffParkingHot", TakeOff = "TakeOffParkingHot",
TurningPoint = "Turning Point", TurningPoint = "Turning Point",
Land = "Land", Land = "Land",
LandingReFuAr = "LandingReFuAr", LandingReFuAr = "LandingReFuAr",
} }
@ -232,6 +228,7 @@ do -- COORDINATE
-- @return #COORDINATE -- @return #COORDINATE
function COORDINATE:New( x, y, z ) function COORDINATE:New( x, y, z )
--env.info("FF COORDINATE New")
local self = BASE:Inherit( self, BASE:New() ) -- #COORDINATE local self = BASE:Inherit( self, BASE:New() ) -- #COORDINATE
self.x = x self.x = x
self.y = y self.y = y
@ -303,6 +300,45 @@ do -- COORDINATE
return { x = self.x, y = self.z } return { x = self.x, y = self.z }
end end
--- Update x,y,z coordinates from a given 3D vector.
-- @param #COORDINATE self
-- @param DCS#Vec3 Vec3 The 3D vector with x,y,z components.
-- @return #COORDINATE The modified COORDINATE itself.
function COORDINATE:UpdateFromVec3(Vec3)
self.x=Vec3.x
self.y=Vec3.y
self.z=Vec3.z
return self
end
--- Update x,y,z coordinates from another given COORDINATE.
-- @param #COORDINATE self
-- @param #COORDINATE Coordinate The coordinate with the new x,y,z positions.
-- @return #COORDINATE The modified COORDINATE itself.
function COORDINATE:UpdateFromCoordinate(Coordinate)
self.x=Coordinate.x
self.y=Coordinate.y
self.z=Coordinate.z
return self
end
--- Update x and z coordinates from a given 2D vector.
-- @param #COORDINATE self
-- @param DCS#Vec2 Vec2 The 2D vector with x,y components. x is overwriting COORDINATE.x while y is overwriting COORDINATE.z.
-- @return #COORDINATE The modified COORDINATE itself.
function COORDINATE:UpdateFromVec2(Vec2)
self.x=Vec2.x
self.z=Vec2.y
return self
end
--- Returns the coordinate from the latitude and longitude given in decimal degrees. --- Returns the coordinate from the latitude and longitude given in decimal degrees.
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param #number latitude Latitude in decimal degrees. -- @param #number latitude Latitude in decimal degrees.
@ -506,19 +542,28 @@ do -- COORDINATE
-- @param DCS#Distance Distance The Distance to be added in meters. -- @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 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 Keepalt If true, keep altitude of original coordinate. Default is that the new coordinate is created at the translated land height.
-- @return Core.Point#COORDINATE The new calculated COORDINATE. -- @param #boolean Overwrite If true, overwrite the original COORDINATE with the translated one. Otherwise, create a new COODINATE.
function COORDINATE:Translate( Distance, Angle, Keepalt ) -- @return #COORDINATE The new calculated COORDINATE.
local SX = self.x function COORDINATE:Translate( Distance, Angle, Keepalt, Overwrite )
local SY = self.z
local Radians = (Angle or 0) / 180 * math.pi -- Angle in rad.
local TX = Distance * math.cos( Radians ) + SX local alpha = math.rad((Angle or 0))
local TY = Distance * math.sin( Radians ) + SY
local x = Distance * math.cos(alpha) + self.x -- New x
if Keepalt then local z = Distance * math.sin(alpha) + self.z -- New z
return COORDINATE:NewFromVec3( { x = TX, y=self.y, z = TY } )
local y=Keepalt and self.y or land.getHeight({x=x, y=z})
if Overwrite then
self.x=x
self.y=y
self.z=z
return self
else else
return COORDINATE:NewFromVec2( { x = TX, y = TY } ) --env.info("FF translate with NEW coordinate T="..timer.getTime())
return COORDINATE:New(x, y, z)
end end
end end
--- Rotate coordinate in 2D (x,z) space. --- Rotate coordinate in 2D (x,z) space.
@ -721,12 +766,18 @@ do -- COORDINATE
--- Return the 2D distance in meters between the target COORDINATE and the COORDINATE. --- Return the 2D distance in meters between the target COORDINATE and the COORDINATE.
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param #COORDINATE TargetCoordinate The target COORDINATE. -- @param #COORDINATE TargetCoordinate The target COORDINATE. Can also be a DCS#Vec3.
-- @return DCS#Distance Distance The distance in meters. -- @return DCS#Distance Distance The distance in meters.
function COORDINATE:Get2DDistance( TargetCoordinate ) function COORDINATE:Get2DDistance( TargetCoordinate )
local TargetVec3 = TargetCoordinate:GetVec3()
local SourceVec3 = self:GetVec3() local a={x=TargetCoordinate.x-self.x, y=0, z=TargetCoordinate.z-self.z}
return ( ( TargetVec3.x - SourceVec3.x ) ^ 2 + ( TargetVec3.z - SourceVec3.z ) ^ 2 ) ^ 0.5
return UTILS.VecNorm(a)
--local TargetVec3 = TargetCoordinate:GetVec3()
--local SourceVec3 = self:GetVec3()
--return ( ( TargetVec3.x - SourceVec3.x ) ^ 2 + ( TargetVec3.z - SourceVec3.z ) ^ 2 ) ^ 0.5
end end
--- Returns the temperature in Degrees Celsius. --- Returns the temperature in Degrees Celsius.
@ -1086,23 +1137,6 @@ do -- COORDINATE
return self return self
end end
--- Add a Distance in meters from the COORDINATE horizontal plane, with the given angle, and calculate the new COORDINATE.
-- @param #COORDINATE self
-- @param DCS#Distance Distance The Distance to be added in meters.
-- @param DCS#Angle Angle The Angle in degrees.
-- @return #COORDINATE The new calculated COORDINATE.
function COORDINATE:Translate( Distance, Angle )
local SX = self.x
local SZ = self.z
local Radians = Angle / 180 * math.pi
local TX = Distance * math.cos( Radians ) + SX
local TZ = Distance * math.sin( Radians ) + SZ
return COORDINATE:New( TX, self.y, TZ )
end
--- Build an air type route point. --- Build an air type route point.
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param #COORDINATE.WaypointAltType AltType The altitude type. -- @param #COORDINATE.WaypointAltType AltType The altitude type.
@ -1290,8 +1324,10 @@ do -- COORDINATE
RoutePoint.x = self.x RoutePoint.x = self.x
RoutePoint.y = self.z RoutePoint.y = self.z
RoutePoint.alt = self:GetLandHeight()+1 -- self.y RoutePoint.alt = self:GetLandHeight()+1
RoutePoint.alt_type = COORDINATE.WaypointAltType.BARO RoutePoint.alt_type = COORDINATE.WaypointAltType.BARO
RoutePoint.type = "Turning Point"
RoutePoint.action = Formation or "Off Road" RoutePoint.action = Formation or "Off Road"
RoutePoint.formation_template="" RoutePoint.formation_template=""
@ -1351,7 +1387,7 @@ do -- COORDINATE
-- @param #number Coalition (Optional) Coalition of the airbase. -- @param #number Coalition (Optional) Coalition of the airbase.
-- @return Wrapper.Airbase#AIRBASE Closest Airbase to the given coordinate. -- @return Wrapper.Airbase#AIRBASE Closest Airbase to the given coordinate.
-- @return #number Distance to the closest airbase in meters. -- @return #number Distance to the closest airbase in meters.
function COORDINATE:GetClosestAirbase(Category, Coalition) function COORDINATE:GetClosestAirbase2(Category, Coalition)
-- Get all airbases of the map. -- Get all airbases of the map.
local airbases=AIRBASE.GetAllAirbases(Coalition) local airbases=AIRBASE.GetAllAirbases(Coalition)
@ -1384,6 +1420,36 @@ do -- COORDINATE
return closest,distmin return closest,distmin
end end
--- 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<distmin and (Category==nil or Category==DCSairbase:getDesc().category) then
distmin=dist
airbase=DCSairbase
end
end
return AIRBASE:Find(airbase)
end
--- Gets the nearest parking spot. --- Gets the nearest parking spot.
-- @param #COORDINATE self -- @param #COORDINATE self
@ -1526,27 +1592,8 @@ do -- COORDINATE
local coord=COORDINATE:NewFromVec2(_vec2) local coord=COORDINATE:NewFromVec2(_vec2)
Path[#Path+1]=coord Path[#Path+1]=coord
if MarkPath then
coord:MarkToAll(string.format("Path segment %d.", _i))
end
if SmokePath then
coord:SmokeGreen()
end
end end
-- Mark/smoke endpoints
if IncludeEndpoints then
if MarkPath then
COORDINATE:NewFromVec2(path[1]):MarkToAll("Path Initinal Point")
COORDINATE:NewFromVec2(path[1]):MarkToAll("Path Final Point")
end
if SmokePath then
COORDINATE:NewFromVec2(path[1]):SmokeBlue()
COORDINATE:NewFromVec2(path[#path]):SmokeBlue()
end
end
else else
self:E("Path is nil. No valid path on road could be found.") self:E("Path is nil. No valid path on road could be found.")
GotPath=false GotPath=false
@ -1557,6 +1604,23 @@ do -- COORDINATE
Path[#Path+1]=ToCoord Path[#Path+1]=ToCoord
end end
-- Mark or smoke.
if MarkPath or SmokePath then
for i,c in pairs(Path) do
local coord=c --#COORDINATE
if MarkPath then
coord:MarkToAll(string.format("Path segment %d", i))
end
if SmokePath then
if i==1 or i==#Path then
coord:SmokeBlue()
else
coord:SmokeGreen()
end
end
end
end
-- Sum up distances. -- Sum up distances.
if #Path>=2 then if #Path>=2 then
for i=1,#Path-1 do for i=1,#Path-1 do
@ -1564,7 +1628,7 @@ do -- COORDINATE
end end
else else
-- There are cases where no path on road can be found. -- There are cases where no path on road can be found.
return nil,nil return nil,nil,false
end end
return Path, Way, GotPath return Path, Way, GotPath
@ -1921,15 +1985,18 @@ do -- COORDINATE
--- Returns if a Coordinate has Line of Sight (LOS) with the ToCoordinate. --- Returns if a Coordinate has Line of Sight (LOS) with the ToCoordinate.
-- @param #COORDINATE self -- @param #COORDINATE self
-- @param #COORDINATE ToCoordinate -- @param #COORDINATE ToCoordinate
-- @param #number Offset Height offset in meters. Default 2 m.
-- @return #boolean true If the ToCoordinate has LOS with the Coordinate, otherwise false. -- @return #boolean true If the ToCoordinate has LOS with the Coordinate, otherwise false.
function COORDINATE:IsLOS( ToCoordinate ) function COORDINATE:IsLOS( ToCoordinate, Offset )
Offset=Offset or 2
-- Measurement of visibility should not be from the ground, so Adding a hypotethical 2 meters to each Coordinate. -- Measurement of visibility should not be from the ground, so Adding a hypotethical 2 meters to each Coordinate.
local FromVec3 = self:GetVec3() local FromVec3 = self:GetVec3()
FromVec3.y = FromVec3.y + 2 FromVec3.y = FromVec3.y + Offset
local ToVec3 = ToCoordinate:GetVec3() local ToVec3 = ToCoordinate:GetVec3()
ToVec3.y = ToVec3.y + 2 ToVec3.y = ToVec3.y + Offset
local IsLOS = land.isVisible( FromVec3, ToVec3 ) local IsLOS = land.isVisible( FromVec3, ToVec3 )

View File

@ -429,7 +429,7 @@ BEACON = {
-- @field #number VOR -- @field #number VOR
-- @field #number DME -- @field #number DME
-- @field #number VOR_DME -- @field #number VOR_DME
-- @field #number TACAN -- @field #number TACAN TACtical Air Navigation system.
-- @field #number VORTAC -- @field #number VORTAC
-- @field #number RSBN -- @field #number RSBN
-- @field #number BROADCAST_STATION -- @field #number BROADCAST_STATION
@ -440,45 +440,74 @@ BEACON = {
-- @field #number ILS_NEAR_HOMER -- @field #number ILS_NEAR_HOMER
-- @field #number ILS_LOCALIZER -- @field #number ILS_LOCALIZER
-- @field #number ILS_GLIDESLOPE -- @field #number ILS_GLIDESLOPE
-- @field #number PRMG_LOCALIZER
-- @field #number PRMG_GLIDESLOPE
-- @field #number ICLS Same as ICLS glideslope.
-- @field #number ICLS_LOCALIZER
-- @field #number ICLS_GLIDESLOPE
-- @field #number NAUTICAL_HOMER -- @field #number NAUTICAL_HOMER
-- @field #number ICLS
BEACON.Type={ BEACON.Type={
NULL = 0, NULL = 0,
VOR = 1, VOR = 1,
DME = 2, DME = 2,
VOR_DME = 3, VOR_DME = 3,
TACAN = 4, TACAN = 4,
VORTAC = 5, VORTAC = 5,
RSBN = 32, RSBN = 128,
BROADCAST_STATION = 1024, BROADCAST_STATION = 1024,
HOMER = 8, HOMER = 8,
AIRPORT_HOMER = 4104, AIRPORT_HOMER = 4104,
AIRPORT_HOMER_WITH_MARKER = 4136, AIRPORT_HOMER_WITH_MARKER = 4136,
ILS_FAR_HOMER = 16408, ILS_FAR_HOMER = 16408,
ILS_NEAR_HOMER = 16456, ILS_NEAR_HOMER = 16424,
ILS_LOCALIZER = 16640, ILS_LOCALIZER = 16640,
ILS_GLIDESLOPE = 16896, ILS_GLIDESLOPE = 16896,
NAUTICAL_HOMER = 32776, PRMG_LOCALIZER = 33024,
ICLS = 131584, PRMG_GLIDESLOPE = 33280,
ICLS = 131584, --leaving this in here but it is the same as ICLS_GLIDESLOPE
ICLS_LOCALIZER = 131328,
ICLS_GLIDESLOPE = 131584,
NAUTICAL_HOMER = 65536,
} }
--- Beacon systems supported by DCS. https://wiki.hoggitworld.com/view/DCS_command_activateBeacon --- Beacon systems supported by DCS. https://wiki.hoggitworld.com/view/DCS_command_activateBeacon
-- @type BEACON.System -- @type BEACON.System
-- @field #number PAR_10 -- @field #number PAR_10 ?
-- @field #number RSBN_5 -- @field #number RSBN_5 Russian VOR/DME system.
-- @field #number TACAN -- @field #number TACAN TACtical Air Navigation system on ground.
-- @field #number TACAN_TANKER -- @field #number TACAN_TANKER_X TACtical Air Navigation system for tankers on X band.
-- @field #number ILS_LOCALIZER (This is the one to be used for AA TACAN Tanker!) -- @field #number TACAN_TANKER_Y TACtical Air Navigation system for tankers on Y band.
-- @field #number ILS_GLIDESLOPE -- @field #number VOR Very High Frequency Omni-Directional Range
-- @field #number BROADCAST_STATION -- @field #number ILS_LOCALIZER ILS localizer
-- @field #number ILS_GLIDESLOPE ILS glideslope.
-- @field #number PRGM_LOCALIZER PRGM localizer.
-- @field #number PRGM_GLIDESLOPE PRGM glideslope.
-- @field #number BROADCAST_STATION Broadcast station.
-- @field #number VORTAC Radio-based navigational aid for aircraft pilots consisting of a co-located VHF omnidirectional range (VOR) beacon and a tactical air navigation system (TACAN) beacon.
-- @field #number TACAN_AA_MODE_X TACtical Air Navigation for aircraft on X band.
-- @field #number TACAN_AA_MODE_Y TACtical Air Navigation for aircraft on Y band.
-- @field #number VORDME Radio beacon that combines a VHF omnidirectional range (VOR) with a distance measuring equipment (DME).
-- @field #number ICLS_LOCALIZER Carrier landing system.
-- @field #number ICLS_GLIDESLOPE Carrier landing system.
BEACON.System={ BEACON.System={
PAR_10 = 1, PAR_10 = 1,
RSBN_5 = 2, RSBN_5 = 2,
TACAN = 3, TACAN = 3,
TACAN_TANKER = 4, TACAN_TANKER_X = 4,
ILS_LOCALIZER = 5, TACAN_TANKER_Y = 5,
ILS_GLIDESLOPE = 6, VOR = 6,
BROADCAST_STATION = 7, ILS_LOCALIZER = 7,
ILS_GLIDESLOPE = 8,
PRMG_LOCALIZER = 9,
PRMG_GLIDESLOPE = 10,
BROADCAST_STATION = 11,
VORTAC = 12,
TACAN_AA_MODE_X = 13,
TACAN_AA_MODE_Y = 14,
VORDME = 15,
ICLS_LOCALIZER = 16,
ICLS_GLIDESLOPE = 17,
} }
--- Create a new BEACON Object. This doesn't activate the beacon, though, use @{#BEACON.ActivateTACAN} etc. --- Create a new BEACON Object. This doesn't activate the beacon, though, use @{#BEACON.ActivateTACAN} etc.

View File

@ -17,7 +17,7 @@
-- --
-- @type RADIOQUEUE -- @type RADIOQUEUE
-- @field #string ClassName Name of the class "RADIOQUEUE". -- @field #string ClassName Name of the class "RADIOQUEUE".
-- @field #boolean Debug Debug mode. More info. -- @field #boolean Debugmode Debug mode. More info.
-- @field #string lid ID for dcs.log. -- @field #string lid ID for dcs.log.
-- @field #number frequency The radio frequency in Hz. -- @field #number frequency The radio frequency in Hz.
-- @field #number modulation The radio modulation. Either radio.modulation.AM or radio.modulation.FM. -- @field #number modulation The radio modulation. Either radio.modulation.AM or radio.modulation.FM.
@ -38,7 +38,7 @@
-- @extends Core.Base#BASE -- @extends Core.Base#BASE
RADIOQUEUE = { RADIOQUEUE = {
ClassName = "RADIOQUEUE", ClassName = "RADIOQUEUE",
Debug = nil, Debugmode = nil,
lid = nil, lid = nil,
frequency = nil, frequency = nil,
modulation = nil, modulation = nil,
@ -55,7 +55,7 @@ RADIOQUEUE = {
power = nil, power = nil,
numbers = {}, numbers = {},
checking = nil, checking = nil,
schedonce = nil, schedonce = false,
} }
--- Radio queue transmission data. --- Radio queue transmission data.
@ -375,8 +375,10 @@ function RADIOQUEUE:Broadcast(transmission)
sender:SetCommand(commandTransmit) sender:SetCommand(commandTransmit)
-- Debug message. -- Debug message.
local text=string.format("file=%s, freq=%.2f MHz, duration=%.2f sec, subtitle=%s", filename, self.frequency/1000000, transmission.duration, transmission.subtitle or "") if self.Debugmode then
MESSAGE:New(text, 2, "RADIOQUEUE "..self.alias):ToAllIf(self.Debug) local text=string.format("file=%s, freq=%.2f MHz, duration=%.2f sec, subtitle=%s", filename, self.frequency/1000000, transmission.duration, transmission.subtitle or "")
MESSAGE:New(text, 2, "RADIOQUEUE "..self.alias):ToAll()
end
else else
@ -388,10 +390,7 @@ function RADIOQUEUE:Broadcast(transmission)
-- Try to get positon from sender unit/static. -- Try to get positon from sender unit/static.
if self.sendername then if self.sendername then
local coord=self:_GetRadioSenderCoord() vec3=self:_GetRadioSenderCoord()
if coord then
vec3=coord:GetVec3()
end
end end
-- Try to get fixed positon. -- Try to get fixed positon.
@ -408,8 +407,10 @@ function RADIOQUEUE:Broadcast(transmission)
trigger.action.radioTransmission(filename, vec3, self.modulation, false, self.frequency, self.power) trigger.action.radioTransmission(filename, vec3, self.modulation, false, self.frequency, self.power)
-- Debug message. -- Debug message.
local text=string.format("file=%s, freq=%.2f MHz, duration=%.2f sec, subtitle=%s", filename, self.frequency/1000000, transmission.duration, transmission.subtitle or "") if self.Debugmode then
MESSAGE:New(string.format(text, filename, transmission.duration, transmission.subtitle or ""), 5, "RADIOQUEUE "..self.alias):ToAllIf(self.Debug) local text=string.format("file=%s, freq=%.2f MHz, duration=%.2f sec, subtitle=%s", filename, self.frequency/1000000, transmission.duration, transmission.subtitle or "")
MESSAGE:New(string.format(text, filename, transmission.duration, transmission.subtitle or ""), 5, "RADIOQUEUE "..self.alias):ToAll()
end
end end
end end
@ -532,6 +533,7 @@ function RADIOQUEUE:_GetRadioSender()
-- Try the general default. -- Try the general default.
if self.sendername then if self.sendername then
-- First try to find a unit -- First try to find a unit
sender=UNIT:FindByName(self.sendername) sender=UNIT:FindByName(self.sendername)
@ -547,7 +549,7 @@ end
--- Get unit from which we want to transmit a radio message. This has to be an aircraft for subtitles to work. --- Get unit from which we want to transmit a radio message. This has to be an aircraft for subtitles to work.
-- @param #RADIOQUEUE self -- @param #RADIOQUEUE self
-- @return Core.Point#COORDINATE Coordinate of the sender unit. -- @return DCS#Vec3 Vector 3D.
function RADIOQUEUE:_GetRadioSenderCoord() function RADIOQUEUE:_GetRadioSenderCoord()
local vec3=nil local vec3=nil
@ -560,7 +562,7 @@ function RADIOQUEUE:_GetRadioSenderCoord()
-- Check that sender is alive and an aircraft. -- Check that sender is alive and an aircraft.
if sender and sender:IsAlive() then if sender and sender:IsAlive() then
return sender:GetCoordinate() return sender:GetVec3()
end end
-- Now try a static. -- Now try a static.
@ -568,7 +570,7 @@ function RADIOQUEUE:_GetRadioSenderCoord()
-- Check that sender is alive and an aircraft. -- Check that sender is alive and an aircraft.
if sender then if sender then
return sender:GetCoordinate() return sender:GetVec3()
end end
end end

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,250 @@
--- **Core** - Timer scheduler.
--
-- **Main Features:**
--
-- * Delay function calls
-- * Easy set up and little overhead
-- * Set start, stop and time interval
-- * Define max function calls
--
-- ===
--
-- ### Author: **funkyfranky**
-- @module Core.Timer
-- @image CORE_Timer.png
--- TIMER class.
-- @type TIMER
-- @field #string ClassName Name of the class.
-- @field #string lid Class id string for output to DCS log file.
-- @field #number tid Timer ID returned by the DCS API function.
-- @field #function func Timer function.
-- @field #table para Parameters passed to the timer function.
-- @field #number Tstart Relative start time in seconds.
-- @field #number Tstop Relative stop time in seconds.
-- @field #number dT Time interval between function calls in seconds.
-- @field #number ncalls Counter of function calls.
-- @field #number ncallsMax Max number of function calls. If reached, timer is stopped.
-- @extends Core.Base#BASE
--- *Better three hours too soon than a minute too late.* William Shakespeare
--
-- ===
--
-- ![Banner Image](..\Presentations\Timer\TIMER_Main.jpg)
--
-- # The TIMER Concept
--
-- The TIMER class is the little sister of the SCHEDULER class. It does the same thing but is a bit easier to use and has less overhead. It should be sufficient in many cases.
--
-- # Construction
--
-- A new TIMER is created by the @{#TIMER.New}(*func*, *...*) function
--
-- local mytimer=TIMER:New(myfunction, a, b)
--
-- The first parameter *func* is the function that is called followed by the necessary comma separeted parameters that are passed to that function.
--
-- ## Starting the Timer
--
-- The timer is started by the @{#TIMER.Start}(*Tstart*, *dT*, *Duration*) function
--
-- mytimer:Start(5, 1, 20)
--
-- where
--
-- * *Tstart* is the relative start time in seconds. In the example, the first function call happens after 5 sec.
-- * *dT* is the time interval between function calls in seconds. Above, the function is called once per second.
-- * *Duration* is the duration in seconds after which the timer is stopped. This is relative to the start time. Here, the timer will run for 20 seconds.
--
-- Note that
--
-- * if *Tstart* is not specified (*nil*), the first function call happens immediately.
-- * if *dT* is not specified (*nil*), the function is called only once.
-- * if *Duration* is not specified (*nil*), the timer runs forever or until stopped manually or until the max function calls are reached (see below).
--
-- For example,
--
-- mytimer:Start(3) -- Will call the function once after 3 seconds.
-- mytimer:Start(nil, 0.5) -- Will call right now and then every 0.5 sec until all eternaty.
-- mytimer:Start(nil, 2.0, 20) -- Will call right now and then every 2.0 sec for 20 sec.
-- mytimer:Start(1.0, nil, 10) -- Does not make sense as the function is only called once anyway.
--
-- ## Stopping the Timer
--
-- The timer can be stopped manually by the @{#TIMER.Start}(*Delay*) function
--
-- mytimer:Stop()
--
-- If the optional paramter *Delay* is specified, the timer is stopped after *delay* seconds.
--
-- ## Limit Function Calls
--
-- The timer can be stopped after a certain amount of function calles with the @{#TIMER.SetMaxFunctionCalls}(*Nmax*) function
--
-- mytimer:SetMaxFunctionCalls(20)
--
-- where *Nmax* is the number of calls after which the timer is stopped, here 20.
--
-- For example,
--
-- mytimer:SetMaxFunctionCalls(66):Start(1.0, 0.1)
--
-- will start the timer after one second and call the function every 0.1 seconds. Once the function has been called 66 times, the timer is stopped.
--
--
-- @field #TIMER
TIMER = {
ClassName = "TIMER",
lid = nil,
}
--- TIMER class version.
-- @field #string version
TIMER.version="0.1.0"
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO list
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO: A lot.
-- TODO: Write docs.
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Constructor
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Create a new TIMER object.
-- @param #TIMER self
-- @param #function Function The function to call.
-- @param ... Parameters passed to the function if any.
-- @return #TIMER self
function TIMER:New(Function, ...)
-- Inherit BASE.
local self=BASE:Inherit(self, BASE:New()) --#TIMER
self.lid="TIMER | "
-- Function to call.
self.func=Function
-- Function arguments.
self.para=arg or {}
-- Number of function calls.
self.ncalls=0
return self
end
--- Create a new TIMER object.
-- @param #TIMER self
-- @param #number Tstart Relative start time in seconds.
-- @param #number dT Interval between function calls in seconds. If not specified `nil`, the function is called only once.
-- @param #number Duration Time in seconds for how long the timer is running. If not specified `nil`, the timer runs forever or until stopped manually by the `TIMER:Stop()` function.
-- @return #TIMER self
function TIMER:Start(Tstart, dT, Duration)
-- Current time.
local Tnow=timer.getTime()
-- Start time in sec.
self.Tstart=Tstart or Tnow
-- Set time interval.
self.dT=dT
-- Stop time.
if Duration then
self.Tstop=self.Tstart+Duration
end
-- Call DCS timer function.
self.tid=timer.scheduleFunction(TIMER._Function, self, self.Tstart)
-- Set log id.
self.lid=string.format("TIMER ID=%d | ", self.tid)
-- Debug info.
self:T(self.lid..string.format("Starting Timer in %.3f sec, dT=%s, Tstop=%s", self.Tstart-Tnow, tostring(self.dT), tostring(self.Tstop)))
return self
end
--- Stop the timer by removing the timer function.
-- @param #TIMER self
-- @param #number Delay (Optional) Delay in seconds, before the timer is stopped.
-- @return #TIMER self
function TIMER:Stop(Delay)
if Delay and Delay>0 then
self.Tstop=timer.getTime()+Delay
else
if self.tid then
self:T(self.lid..string.format("Stopping timer by removing timer function after %d calls!", self.ncalls))
timer.removeFunction(self.tid)
end
end
return self
end
--- Set max number of function calls. When the function has been called this many times, the TIMER is stopped.
-- @param #TIMER self
-- @param #number Nmax Set number of max function calls.
-- @return #TIMER self
function TIMER:SetMaxFunctionCalls(Nmax)
self.ncallsMax=Nmax
return self
end
--- Call timer function.
-- @param #TIMER self
-- @param #number time DCS model time in seconds.
-- @return #number Time when the function is called again or `nil` if the timer is stopped.
function TIMER:_Function(time)
-- Call function.
self.func(unpack(self.para))
-- Increase number of calls.
self.ncalls=self.ncalls+1
-- Next time.
local Tnext=self.dT and time+self.dT or nil
-- Check if we stop the timer.
local stopme=false
if Tnext==nil then
-- No next time.
self:T(self.lid..string.format("No next time as dT=nil ==> Stopping timer after %d function calls", self.ncalls))
stopme=true
elseif self.Tstop and Tnext>self.Tstop then
-- Stop time passed.
self:T(self.lid..string.format("Stop time passed %.3f > %.3f ==> Stopping timer after %d function calls", Tnext, self.Tstop, self.ncalls))
stopme=true
elseif self.ncallsMax and self.ncalls>=self.ncallsMax then
-- Number of max function calls reached.
self:T(self.lid..string.format("Max function calls Nmax=%d reached ==> Stopping timer after %d function calls", self.ncallsMax, self.ncalls))
stopme=true
end
if stopme then
-- Remove timer function.
self:Stop()
return nil
else
-- Call again in Tnext seconds.
return Tnext
end
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

View File

@ -95,6 +95,11 @@ do -- world
--- Returns a table of mark panels indexed numerically that are present within the mission. See [hoggit](https://wiki.hoggitworld.com/view/DCS_func_getMarkPanels) --- Returns a table of mark panels indexed numerically that are present within the mission. See [hoggit](https://wiki.hoggitworld.com/view/DCS_func_getMarkPanels)
-- @function [parent=#world] getMarkPanels -- @function [parent=#world] getMarkPanels
-- @return #table Table of marks. -- @return #table Table of marks.
--- Returns a table of DCS airbase objects.
-- @function [parent=#world] getAirbases
-- @param #number coalitionId The coalition side number ID. Default is all airbases are returned.
-- @return #table Table of DCS airbase objects.
end -- world end -- world
@ -360,7 +365,7 @@ do -- Types
--- Time is given in seconds. --- Time is given in seconds.
-- @type Time -- @type Time
-- @extends #number -- @extends #number Time in seconds.
--- Model time is the time that drives the simulation. Model time may be stopped, accelerated and decelerated relative real time. --- Model time is the time that drives the simulation. Model time may be stopped, accelerated and decelerated relative real time.
-- @type ModelTime -- @type ModelTime
@ -368,20 +373,20 @@ do -- Types
--- Mission time is a model time plus time of the mission start. --- Mission time is a model time plus time of the mission start.
-- @type MissionTime -- @type MissionTime
-- @extends #number -- @extends #number Time in seconds.
--- Distance is given in meters. --- Distance is given in meters.
-- @type Distance -- @type Distance
-- @extends #number -- @extends #number Distance in meters.
--- Angle is given in radians. --- Angle is given in radians.
-- @type Angle -- @type Angle
-- @extends #number -- @extends #number Angle in radians.
--- Azimuth is an angle of rotation around world axis y counter-clockwise. --- Azimuth is an angle of rotation around world axis y counter-clockwise.
-- @type Azimuth -- @type Azimuth
-- @extends #number -- @extends #number Angle in radians.
--- Mass is given in kilograms. --- Mass is given in kilograms.
-- @type Mass -- @type Mass
@ -401,15 +406,15 @@ do -- Types
--- Position is a composite structure. It consists of both coordinate vector and orientation matrix. Position3 (also known as "Pos3" for short) is a table that has following format: --- Position is a composite structure. It consists of both coordinate vector and orientation matrix. Position3 (also known as "Pos3" for short) is a table that has following format:
-- @type Position3 -- @type Position3
-- @field #Vec3 p -- @field #Vec3 p 3D position vector.
-- @field #Vec3 x -- @field #Vec3 x Orientation component of vector pointing East.
-- @field #Vec3 y -- @field #Vec3 y Orientation component of vector pointing up.
-- @field #Vec3 z -- @field #Vec3 z Orientation component of vector pointing North.
--- 3-dimensional box. --- 3-dimensional box.
-- @type Box3 -- @type Box3
-- @field #Vec3 min -- @field #Vec3 min Min.
-- @field #Vec3 max -- @field #Vec3 max Max
--- Each object belongs to a type. Object type is a named couple of properties those independent of mission and common for all units of the same type. Name of unit type is a string. Samples of unit type: "Su-27", "KAMAZ" and "M2 Bradley". --- Each object belongs to a type. Object type is a named couple of properties those independent of mission and common for all units of the same type. Name of unit type is a string. Samples of unit type: "Su-27", "KAMAZ" and "M2 Bradley".
-- @type TypeName -- @type TypeName
@ -514,7 +519,7 @@ do -- Object
--- Returns object coordinates for current time. --- Returns object coordinates for current time.
-- @function [parent=#Object] getPoint -- @function [parent=#Object] getPoint
-- @param #Object self -- @param #Object self
-- @return #Vec3 -- @return #Vec3 3D position vector with x,y,z components.
--- Returns object position for current time. --- Returns object position for current time.
-- @function [parent=#Object] getPosition -- @function [parent=#Object] getPosition
@ -524,7 +529,7 @@ do -- Object
--- Returns the unit's velocity vector. --- Returns the unit's velocity vector.
-- @function [parent=#Object] getVelocity -- @function [parent=#Object] getVelocity
-- @param #Object self -- @param #Object self
-- @return #Vec3 -- @return #Vec3 3D velocity vector.
--- Returns true if the unit is in air. --- Returns true if the unit is in air.
-- @function [parent=#Object] inAir -- @function [parent=#Object] inAir

View File

@ -25,6 +25,7 @@ __Moose.Include( 'Scripts/Moose/Core/RadioQueue.lua' )
__Moose.Include( 'Scripts/Moose/Core/RadioSpeech.lua' ) __Moose.Include( 'Scripts/Moose/Core/RadioSpeech.lua' )
__Moose.Include( 'Scripts/Moose/Core/Spawn.lua' ) __Moose.Include( 'Scripts/Moose/Core/Spawn.lua' )
__Moose.Include( 'Scripts/Moose/Core/SpawnStatic.lua' ) __Moose.Include( 'Scripts/Moose/Core/SpawnStatic.lua' )
__Moose.Include( 'Scripts/Moose/Core/Timer.lua' )
__Moose.Include( 'Scripts/Moose/Core/Goal.lua' ) __Moose.Include( 'Scripts/Moose/Core/Goal.lua' )
__Moose.Include( 'Scripts/Moose/Core/Spot.lua' ) __Moose.Include( 'Scripts/Moose/Core/Spot.lua' )

View File

@ -513,7 +513,7 @@ ATIS.Sound = {
MegaHertz={filename="MegaHertz.ogg", duration=0.87}, MegaHertz={filename="MegaHertz.ogg", duration=0.87},
Meters={filename="Meters.ogg", duration=0.59}, Meters={filename="Meters.ogg", duration=0.59},
MetersPerSecond={filename="MetersPerSecond.ogg", duration=1.14}, MetersPerSecond={filename="MetersPerSecond.ogg", duration=1.14},
Miles={filename="Miles.ogg", duration=1.04}, Miles={filename="Miles.ogg", duration=0.60},
MillimetersOfMercury={filename="MillimetersOfMercury.ogg", duration=1.53}, MillimetersOfMercury={filename="MillimetersOfMercury.ogg", duration=1.53},
Minus={filename="Minus.ogg", duration=0.64}, Minus={filename="Minus.ogg", duration=0.64},
N0={filename="N-0.ogg", duration=0.55}, N0={filename="N-0.ogg", duration=0.55},
@ -534,6 +534,7 @@ ATIS.Sound = {
Right={filename="Right.ogg", duration=0.44}, Right={filename="Right.ogg", duration=0.44},
Snow={filename="Snow.ogg", duration=0.48}, Snow={filename="Snow.ogg", duration=0.48},
SnowStorm={filename="SnowStorm.ogg", duration=0.82}, SnowStorm={filename="SnowStorm.ogg", duration=0.82},
StatuteMiles={filename="StatuteMiles.ogg", duration=1.15},
SunriseAt={filename="SunriseAt.ogg", duration=0.92}, SunriseAt={filename="SunriseAt.ogg", duration=0.92},
SunsetAt={filename="SunsetAt.ogg", duration=0.95}, SunsetAt={filename="SunsetAt.ogg", duration=0.95},
Temperature={filename="Temperature.ogg", duration=0.64}, Temperature={filename="Temperature.ogg", duration=0.64},
@ -553,6 +554,7 @@ ATIS.Sound = {
TACANChannel={filename="TACANChannel.ogg", duration=0.88}, TACANChannel={filename="TACANChannel.ogg", duration=0.88},
PRMGChannel={filename="PRMGChannel.ogg", duration=1.18}, PRMGChannel={filename="PRMGChannel.ogg", duration=1.18},
RSBNChannel={filename="RSBNChannel.ogg", duration=1.14}, RSBNChannel={filename="RSBNChannel.ogg", duration=1.14},
Zulu={filename="Zulu.ogg", duration=0.62},
} }
@ -925,7 +927,7 @@ function ATIS:SetAltimeterQNH(switch)
return self return self
end end
-- Suppresses QFE readout. Default is to report both QNH and QFE. --- Suppresses QFE readout. Default is to report both QNH and QFE.
-- @param #ATIS self -- @param #ATIS self
-- @return #ATIS self -- @return #ATIS self
function ATIS:ReportQNHOnly() function ATIS:ReportQNHOnly()
@ -995,7 +997,7 @@ function ATIS:SetZuluTimeDifference(delta)
return self return self
end end
-- Suppresses local time, sunrise, and sunset. Default is to report all these times. --- Suppresses local time, sunrise, and sunset. Default is to report all these times.
-- @param #ATIS self -- @param #ATIS self
-- @return #ATIS self -- @return #ATIS self
function ATIS:ReportZuluTimeOnly() function ATIS:ReportZuluTimeOnly()
@ -1502,7 +1504,7 @@ function ATIS:onafterBroadcast(From, Event, To)
-- Zulu Time -- Zulu Time
subtitle=string.format("%s Zulu", ZULU) subtitle=string.format("%s Zulu", ZULU)
self.radioqueue:Number2Transmission(ZULU, nil, 0.5) self.radioqueue:Number2Transmission(ZULU, nil, 0.5)
self:Transmission(ATIS.Sound.TimeZulu, 0.2, subtitle) self:Transmission(ATIS.Sound.Zulu, 0.2, subtitle)
alltext=alltext..";\n"..subtitle alltext=alltext..";\n"..subtitle
if not self.zulutimeonly then if not self.zulutimeonly then
@ -1557,7 +1559,7 @@ function ATIS:onafterBroadcast(From, Event, To)
if self.metric then if self.metric then
self:Transmission(ATIS.Sound.Kilometers, 0.2) self:Transmission(ATIS.Sound.Kilometers, 0.2)
else else
self:Transmission(ATIS.Sound.Miles, 0.2) self:Transmission(ATIS.Sound.StatuteMiles, 0.2)
end end
alltext=alltext..";\n"..subtitle alltext=alltext..";\n"..subtitle
@ -1974,13 +1976,6 @@ function ATIS:onafterBroadcast(From, Event, To)
alltext=alltext..";\n"..subtitle alltext=alltext..";\n"..subtitle
end end
--[[
-- End of Information Alpha, Bravo, ...
subtitle=string.format("End of information %s", NATO)
self:Transmission(ATIS.Sound.EndOfInformation, 0.5, subtitle)
self.radioqueue:NewTransmission(string.format("NATO Alphabet/%s.ogg", NATO), 0.75, self.soundpath)
--]]
-- Advice on initial... -- Advice on initial...
subtitle=string.format("Advise on initial contact, you have information %s", NATO) subtitle=string.format("Advise on initial contact, you have information %s", NATO)

View File

@ -1345,7 +1345,6 @@ function RECOVERYTANKER:OnEventEngineShutdown(EventData)
group:InitModex(self.modex) group:InitModex(self.modex)
-- Respawn tanker. Delaying respawn due to DCS bug https://github.com/FlightControl-Master/MOOSE/issues/1076 -- Respawn tanker. Delaying respawn due to DCS bug https://github.com/FlightControl-Master/MOOSE/issues/1076
--SCHEDULER:New(nil , group.RespawnAtCurrentAirbase, {group}, 1)
self:ScheduleOnce(1, GROUP.RespawnAtCurrentAirbase, group) self:ScheduleOnce(1, GROUP.RespawnAtCurrentAirbase, group)
-- Create tanker beacon and activate TACAN. -- Create tanker beacon and activate TACAN.
@ -1364,7 +1363,6 @@ function RECOVERYTANKER:OnEventEngineShutdown(EventData)
end end
-- Initial route. -- Initial route.
--SCHEDULER:New(nil, self._InitRoute, {self, -self.distStern+UTILS.NMToMeters(3)}, 2)
self:ScheduleOnce(2, RECOVERYTANKER._InitRoute, self, -self.distStern+UTILS.NMToMeters(3)) self:ScheduleOnce(2, RECOVERYTANKER._InitRoute, self, -self.distStern+UTILS.NMToMeters(3))
end end

View File

@ -56,6 +56,17 @@ ENUMS.ROT = {
AllowAbortMission=4, AllowAbortMission=4,
} }
--- Alarm state.
-- @type ENUMS.AlarmState
-- @field #number Auto AI will automatically switch alarm states based on the presence of threats. The AI kind of cheats in this regard.
-- @field #number Green Group is not combat ready. Sensors are stowed if possible.
-- @field #number Red Group is combat ready and actively searching for targets. Some groups like infantry will not move in this state.
ENUMS.AlarmState = {
Auto=0,
Green=1,
Red=2,
}
--- Weapon types. See the [Weapon Flag](https://wiki.hoggitworld.com/view/DCS_enum_weapon_flag) enumerotor on hoggit wiki. --- Weapon types. See the [Weapon Flag](https://wiki.hoggitworld.com/view/DCS_enum_weapon_flag) enumerotor on hoggit wiki.
-- @type ENUMS.WeaponFlag -- @type ENUMS.WeaponFlag
ENUMS.WeaponFlag={ ENUMS.WeaponFlag={
@ -222,6 +233,15 @@ ENUMS.Formation.RotaryWing.EchelonLeft={}
ENUMS.Formation.RotaryWing.EchelonLeft.D70 =590081 ENUMS.Formation.RotaryWing.EchelonLeft.D70 =590081
ENUMS.Formation.RotaryWing.EchelonLeft.D300=590082 ENUMS.Formation.RotaryWing.EchelonLeft.D300=590082
ENUMS.Formation.RotaryWing.EchelonLeft.D600=590083 ENUMS.Formation.RotaryWing.EchelonLeft.D600=590083
ENUMS.Formation.Vehicle={}
ENUMS.Formation.Vehicle.Vee="Vee"
ENUMS.Formation.Vehicle.EchelonRight="EchelonR"
ENUMS.Formation.Vehicle.OffRoad="Off Road"
ENUMS.Formation.Vehicle.Rank="Rank"
ENUMS.Formation.Vehicle.EchelonLeft="EchelonL"
ENUMS.Formation.Vehicle.OnRoad="On Road"
ENUMS.Formation.Vehicle.Cone="Cone"
ENUMS.Formation.Vehicle.Diamond="Diamond"
--- Formations (old). The old format is a simplified version of the new formation enums, which allow more sophisticated settings. --- Formations (old). The old format is a simplified version of the new formation enums, which allow more sophisticated settings.
-- See the [Formations](https://wiki.hoggitworld.com/view/DCS_enum_formation) on hoggit wiki. -- See the [Formations](https://wiki.hoggitworld.com/view/DCS_enum_formation) on hoggit wiki.

View File

@ -5,7 +5,7 @@
-- === -- ===
-- --
-- ### Author: **TAW CougarNL**, *funkyfranky* -- ### Author: **TAW CougarNL**, *funkyfranky*
-- --
-- @module Utilities.PROFILER -- @module Utilities.PROFILER
-- @image Utils_Profiler.jpg -- @image Utils_Profiler.jpg
@ -33,14 +33,14 @@
-- ![Banner Image](..\Presentations\Utilities\PROFILER_Main.jpg) -- ![Banner Image](..\Presentations\Utilities\PROFILER_Main.jpg)
-- --
-- # The PROFILER Concept -- # The PROFILER Concept
-- --
-- Profile your lua code. This tells you, which functions are called very often and which consume most real time. -- 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 perfomance of your code.
-- --
-- # Prerequisites -- # Prerequisites
-- --
-- The modules **os**, **io** and **lfs** need to be desanizied. Comment out the lines -- The modules **os**, **io** and **lfs** need to be desanizied. Comment out the lines
-- --
-- --sanitizeModule('os') -- --sanitizeModule('os')
-- --sanitizeModule('io') -- --sanitizeModule('io')
-- --sanitizeModule('lfs') -- --sanitizeModule('lfs')
@ -48,57 +48,57 @@
-- in your *"DCS World OpenBeta/Scripts/MissionScripting.lua"* file. -- in your *"DCS World OpenBeta/Scripts/MissionScripting.lua"* file.
-- --
-- But be aware that these changes can make you system vulnerable to attacks. -- But be aware that these changes can make you system vulnerable to attacks.
-- --
-- # Disclaimer -- # Disclaimer
-- --
-- **Profiling itself is CPU expensive!** Don't use this when you want to fly or host a mission. -- **Profiling itself is CPU expensive!** Don't use this when you want to fly or host a mission.
-- --
-- --
-- # Start -- # Start
-- --
-- The profiler can simply be started with the @{#PROFILER.Start}(*Delay, Duration*) function -- The profiler can simply be started with the @{#PROFILER.Start}(*Delay, Duration*) function
-- --
-- PROFILER.Start() -- PROFILER.Start()
-- --
-- The optional parameter *Delay* can be used to delay the start by a certain amount of seconds and the optional parameter *Duration* can be used to -- The optional parameter *Delay* can be used to delay the start by a certain amount of seconds and the optional parameter *Duration* can be used to
-- stop the profiler after a certain amount of seconds. -- stop the profiler after a certain amount of seconds.
-- --
-- # Stop -- # Stop
-- --
-- The profiler automatically stops when the mission ends. But it can be stopped any time with the @{#PROFILER.Stop}(*Delay*) function -- The profiler automatically stops when the mission ends. But it can be stopped any time with the @{#PROFILER.Stop}(*Delay*) function
-- --
-- PROFILER.Stop() -- PROFILER.Stop()
-- --
-- The optional parameter *Delay* can be used to specify a delay after which the profiler is stopped. -- The optional parameter *Delay* can be used to specify a delay after which the profiler is stopped.
-- --
-- When the profiler is stopped, the output is written to a file. -- When the profiler is stopped, the output is written to a file.
-- --
-- # Output -- # Output
-- --
-- The profiler output is written to a file in your DCS home folder -- The profiler output is written to a file in your DCS home folder
-- --
-- X:\User\<Your User Name>\Saved Games\DCS OpenBeta\Logs -- X:\User\<Your User Name>\Saved Games\DCS OpenBeta\Logs
-- --
-- The default file name is "MooseProfiler.txt". If that file exists, the file name is "MooseProfiler-001.txt" etc. -- The default file name is "MooseProfiler.txt". If that file exists, the file name is "MooseProfiler-001.txt" etc.
-- --
-- ## Data -- ## Data
-- --
-- The data in the output file provides information on the functions that were called in the mission. -- The data in the output file provides information on the functions that were called in the mission.
-- --
-- It will tell you how many times a function was called in total, how many times per second, how much time in total and the percentage of time. -- It will tell you how many times a function was called in total, how many times per second, how much time in total and the percentage of time.
-- --
-- If you only want output for functions that are called more than *X* times per second, you can set -- If you only want output for functions that are called more than *X* times per second, you can set
-- --
-- PROFILER.ThreshCPS=1.5 -- PROFILER.ThreshCPS=1.5
-- --
-- With this setting, only functions which are called more than 1.5 times per second are displayed. The default setting is PROFILER.ThreshCPS=0.0 (no threshold). -- With this setting, only functions which are called more than 1.5 times per second are displayed. The default setting is PROFILER.ThreshCPS=0.0 (no threshold).
-- --
-- Furthermore, you can limit the output for functions that consumed a certain amount of CPU time in total by -- Furthermore, you can limit the output for functions that consumed a certain amount of CPU time in total by
-- --
-- PROFILER.ThreshTtot=0.005 -- PROFILER.ThreshTtot=0.005
-- --
-- With this setting, which is also the default, only functions which in total used more than 5 milliseconds CPU time. -- With this setting, which is also the default, only functions which in total used more than 5 milliseconds CPU time.
-- --
-- @field #PROFILER -- @field #PROFILER
PROFILER = { PROFILER = {
ClassName = "PROFILER", ClassName = "PROFILER",
@ -140,11 +140,11 @@ function PROFILER.Start(Delay, Duration)
if not io then if not io then
env.error("ERROR: Profiler needs io to be desanitized!") env.error("ERROR: Profiler needs io to be desanitized!")
go=false go=false
end end
if not lfs then if not lfs then
env.error("ERROR: Profiler needs lfs to be desanitized!") env.error("ERROR: Profiler needs lfs to be desanitized!")
go=false go=false
end end
if not go then if not go then
return return
end end
@ -152,14 +152,14 @@ function PROFILER.Start(Delay, Duration)
if Delay and Delay>0 then if Delay and Delay>0 then
BASE:ScheduleOnce(Delay, PROFILER.Start, 0, Duration) BASE:ScheduleOnce(Delay, PROFILER.Start, 0, Duration)
else else
-- Set start time. -- Set start time.
PROFILER.TstartGame=timer.getTime() PROFILER.TstartGame=timer.getTime()
PROFILER.TstartOS=os.clock() PROFILER.TstartOS=os.clock()
-- Add event handler. -- Add event handler.
world.addEventHandler(PROFILER.eventHandler) world.addEventHandler(PROFILER.eventHandler)
-- Info in log. -- Info in log.
env.info('############################ Profiler Started ############################') env.info('############################ Profiler Started ############################')
if Duration then if Duration then
@ -168,25 +168,26 @@ function PROFILER.Start(Delay, Duration)
env.info(string.format("- Will be stopped when mission ends")) env.info(string.format("- Will be stopped when mission ends"))
end end
env.info(string.format("- Calls per second threshold %.3f/sec", PROFILER.ThreshCPS)) env.info(string.format("- Calls per second threshold %.3f/sec", PROFILER.ThreshCPS))
env.info(string.format("- Total function time threshold %.3f/sec", PROFILER.ThreshTtot)) env.info(string.format("- Total function time threshold %.3f sec", PROFILER.ThreshTtot))
env.info(string.format("- Output file \"%s\" in your DCS log file folder", PROFILER.getfilename())) env.info(string.format("- Output file \"%s\" in your DCS log file folder", PROFILER.getfilename(PROFILER.fileNameSuffix)))
env.info(string.format("- Output file \"%s\" in CSV format", PROFILER.getfilename("csv")))
env.info('###############################################################################') env.info('###############################################################################')
-- Message on screen -- Message on screen
local duration=Duration or 600 local duration=Duration or 600
trigger.action.outText("### Profiler running ###", duration) trigger.action.outText("### Profiler running ###", duration)
-- Set hook. -- Set hook.
debug.sethook(PROFILER.hook, "cr") debug.sethook(PROFILER.hook, "cr")
-- Auto stop profiler. -- Auto stop profiler.
if Duration then if Duration then
PROFILER.Stop(Duration) PROFILER.Stop(Duration)
end end
end end
end end
--- Stop profiler. --- Stop profiler.
@ -194,24 +195,24 @@ end
function PROFILER.Stop(Delay) function PROFILER.Stop(Delay)
if Delay and Delay>0 then if Delay and Delay>0 then
BASE:ScheduleOnce(Delay, PROFILER.Stop) BASE:ScheduleOnce(Delay, PROFILER.Stop)
else else
-- Remove hook. -- Remove hook.
debug.sethook() debug.sethook()
-- Run time game. -- Run time game.
local runTimeGame=timer.getTime()-PROFILER.TstartGame local runTimeGame=timer.getTime()-PROFILER.TstartGame
-- Run time real OS. -- Run time real OS.
local runTimeOS=os.clock()-PROFILER.TstartOS local runTimeOS=os.clock()-PROFILER.TstartOS
-- Show info. -- Show info.
PROFILER.showInfo(runTimeGame, runTimeOS) PROFILER.showInfo(runTimeGame, runTimeOS)
end end
end end
@ -232,35 +233,35 @@ end
function PROFILER.hook(event) function PROFILER.hook(event)
local f=debug.getinfo(2, "f").func local f=debug.getinfo(2, "f").func
if event=='call' then if event=='call' then
if PROFILER.Counters[f]==nil then if PROFILER.Counters[f]==nil then
PROFILER.Counters[f]=1 PROFILER.Counters[f]=1
PROFILER.dInfo[f]=debug.getinfo(2,"Sn") PROFILER.dInfo[f]=debug.getinfo(2,"Sn")
if PROFILER.fTimeTotal[f]==nil then if PROFILER.fTimeTotal[f]==nil then
PROFILER.fTimeTotal[f]=0 PROFILER.fTimeTotal[f]=0
end end
else else
PROFILER.Counters[f]=PROFILER.Counters[f]+1 PROFILER.Counters[f]=PROFILER.Counters[f]+1
end end
if PROFILER.fTime[f]==nil then if PROFILER.fTime[f]==nil then
PROFILER.fTime[f]=os.clock() PROFILER.fTime[f]=os.clock()
end end
elseif (event=='return') then elseif (event=='return') then
if PROFILER.fTime[f]~=nil then if PROFILER.fTime[f]~=nil then
PROFILER.fTimeTotal[f]=PROFILER.fTimeTotal[f]+(os.clock()-PROFILER.fTime[f]) PROFILER.fTimeTotal[f]=PROFILER.fTimeTotal[f]+(os.clock()-PROFILER.fTime[f])
PROFILER.fTime[f]=nil PROFILER.fTime[f]=nil
end end
end end
end end
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
@ -276,12 +277,12 @@ end
function PROFILER.getData(func) function PROFILER.getData(func)
local n=PROFILER.dInfo[func] local n=PROFILER.dInfo[func]
if n.what=="C" then if n.what=="C" then
return n.name, "?", "?", PROFILER.fTimeTotal[func] return n.name, "?", "?", PROFILER.fTimeTotal[func]
end end
return n.name, n.short_src, n.linedefined, PROFILER.fTimeTotal[func] return n.name, n.short_src, n.linedefined, PROFILER.fTimeTotal[func]
end end
--- Write text to log file. --- Write text to log file.
@ -298,46 +299,80 @@ end
function PROFILER.showTable(data, f, runTimeGame) function PROFILER.showTable(data, f, runTimeGame)
-- Loop over data. -- Loop over data.
for i=1, #data do for i=1, #data do
local t=data[i] --#PROFILER.Data local t=data[i] --#PROFILER.Data
-- Calls per second. -- Calls per second.
local cps=t.count/runTimeGame local cps=t.count/runTimeGame
local threshCPS=cps>=PROFILER.ThreshCPS local threshCPS=cps>=PROFILER.ThreshCPS
local threshTot=t.tm>=PROFILER.ThreshTtot local threshTot=t.tm>=PROFILER.ThreshTtot
if threshCPS and threshTot then if threshCPS and threshTot then
-- Output -- Output
local text=string.format("%30s: %8d calls %8.1f/sec - Time Total %8.3f sec (%.3f %%) %5.3f sec/call %s line %s", t.func, t.count, cps, t.tm, t.tm/runTimeGame*100, t.tm/t.count, tostring(t.src), tostring(t.line)) local text=string.format("%30s: %8d calls %8.1f/sec - Time Total %8.3f sec (%.3f %%) %5.3f sec/call %s line %s", t.func, t.count, cps, t.tm, t.tm/runTimeGame*100, t.tm/t.count, tostring(t.src), tostring(t.line))
PROFILER._flog(f, text) PROFILER._flog(f, text)
end end
end end
end end
--- Print csv file.
-- @param #table data Data table.
-- @param #number runTimeGame Game run time in seconds.
function PROFILER.printCSV(data, runTimeGame)
-- Output file.
local file=PROFILER.getfilename("csv")
local g=io.open(file, 'w')
-- Header.
local text="Function,Total Calls,Calls per Sec,Total Time,Total in %,Sec per Call,Source File;Line Number,"
g:write(text.."\r\n")
-- Loop over data.
for i=1, #data do
local t=data[i] --#PROFILER.Data
-- Calls per second.
local cps=t.count/runTimeGame
-- Output
local txt=string.format("%s,%d,%.1f,%.3f,%.3f,%.3f,%s,%s,", t.func, t.count, cps, t.tm, t.tm/runTimeGame*100, t.tm/t.count, tostring(t.src), tostring(t.line))
g:write(txt.."\r\n")
end
-- Close file.
g:close()
end
--- Write info to output file. --- Write info to output file.
-- @param #string ext Extension.
-- @return #string File name. -- @return #string File name.
function PROFILER.getfilename() function PROFILER.getfilename(ext)
local dir=lfs.writedir()..[[Logs\]] local dir=lfs.writedir()..[[Logs\]]
local file=dir..PROFILER.fileNamePrefix.."."..PROFILER.fileNameSuffix ext=ext or PROFILER.fileNameSuffix
local file=dir..PROFILER.fileNamePrefix.."."..ext
if not UTILS.FileExists(file) then if not UTILS.FileExists(file) then
return file return file
end end
for i=1,999 do for i=1,999 do
local file=string.format("%s%s-%03d.%s", dir,PROFILER.fileNamePrefix, i, PROFILER.fileNameSuffix) local file=string.format("%s%s-%03d.%s", dir,PROFILER.fileNamePrefix, i, ext)
if not UTILS.FileExists(file) then if not UTILS.FileExists(file) then
return file return file
end end
end end
end end
@ -348,31 +383,31 @@ end
function PROFILER.showInfo(runTimeGame, runTimeOS) function PROFILER.showInfo(runTimeGame, runTimeOS)
-- Output file. -- Output file.
local file=PROFILER.getfilename() local file=PROFILER.getfilename(PROFILER.fileNameSuffix)
local f=io.open(file, 'w') local f=io.open(file, 'w')
-- Gather data. -- Gather data.
local Ttot=0 local Ttot=0
local Calls=0 local Calls=0
local t={} local t={}
local tcopy=nil --#PROFILER.Data local tcopy=nil --#PROFILER.Data
local tserialize=nil --#PROFILER.Data local tserialize=nil --#PROFILER.Data
local tforgen=nil --#PROFILER.Data local tforgen=nil --#PROFILER.Data
local tpairs=nil --#PROFILER.Data local tpairs=nil --#PROFILER.Data
for func, count in pairs(PROFILER.Counters) do for func, count in pairs(PROFILER.Counters) do
local s,src,line,tm=PROFILER.getData(func) local s,src,line,tm=PROFILER.getData(func)
if PROFILER.logUnknown==true then if PROFILER.logUnknown==true then
if s==nil then s="<Unknown>" end if s==nil then s="<Unknown>" end
end end
if s~=nil then if s~=nil then
-- Profile data. -- Profile data.
local T= local T=
{ func=s, { func=s,
@ -381,7 +416,7 @@ function PROFILER.showInfo(runTimeGame, runTimeOS)
count=count, count=count,
tm=tm, tm=tm,
} --#PROFILER.Data } --#PROFILER.Data
-- Collect special cases. Somehow, e.g. "_copy" appears multiple times so we try to gather all data. -- Collect special cases. Somehow, e.g. "_copy" appears multiple times so we try to gather all data.
if s=="_copy" then if s=="_copy" then
if tcopy==nil then if tcopy==nil then
@ -396,63 +431,62 @@ function PROFILER.showInfo(runTimeGame, runTimeOS)
else else
tserialize.count=tserialize.count+T.count tserialize.count=tserialize.count+T.count
tserialize.tm=tserialize.tm+T.tm tserialize.tm=tserialize.tm+T.tm
end end
elseif s=="(for generator)" then elseif s=="(for generator)" then
if tforgen==nil then if tforgen==nil then
tforgen=T tforgen=T
else else
tforgen.count=tforgen.count+T.count tforgen.count=tforgen.count+T.count
tforgen.tm=tforgen.tm+T.tm tforgen.tm=tforgen.tm+T.tm
end end
elseif s=="pairs" then elseif s=="pairs" then
if tpairs==nil then if tpairs==nil then
tpairs=T tpairs=T
else else
tpairs.count=tpairs.count+T.count tpairs.count=tpairs.count+T.count
tpairs.tm=tpairs.tm+T.tm tpairs.tm=tpairs.tm+T.tm
end end
else else
table.insert(t, T) table.insert(t, T)
end end
-- Total function time. -- Total function time.
Ttot=Ttot+tm Ttot=Ttot+tm
-- Total number of calls. -- Total number of calls.
Calls=Calls+count Calls=Calls+count
end end
end end
-- Add special cases. -- Add special cases.
if tcopy then if tcopy then
table.insert(t, tcopy) table.insert(t, tcopy)
end end
if tserialize then if tserialize then
table.insert(t, tserialize) table.insert(t, tserialize)
end end
if tforgen then if tforgen then
table.insert(t, tforgen) table.insert(t, tforgen)
end end
if tpairs then if tpairs then
table.insert(t, tpairs) table.insert(t, tpairs)
end end
env.info("**************************************************************************************************") env.info('############################ Profiler Stopped ############################')
env.info(string.format("Profiler"))
env.info(string.format("--------"))
env.info(string.format("* Runtime Game : %s = %d sec", UTILS.SecondsToClock(runTimeGame, true), runTimeGame)) env.info(string.format("* Runtime Game : %s = %d sec", UTILS.SecondsToClock(runTimeGame, true), runTimeGame))
env.info(string.format("* Runtime Real : %s = %d sec", UTILS.SecondsToClock(runTimeOS, true), runTimeOS)) env.info(string.format("* Runtime Real : %s = %d sec", UTILS.SecondsToClock(runTimeOS, true), runTimeOS))
env.info(string.format("* Function time : %s = %.1f sec (%.1f percent of runtime game)", UTILS.SecondsToClock(Ttot, true), Ttot, Ttot/runTimeGame*100)) env.info(string.format("* Function time : %s = %.1f sec (%.1f percent of runtime game)", UTILS.SecondsToClock(Ttot, true), Ttot, Ttot/runTimeGame*100))
env.info(string.format("* Total functions : %d", #t)) env.info(string.format("* Total functions : %d", #t))
env.info(string.format("* Total func calls : %d", Calls)) env.info(string.format("* Total func calls : %d", Calls))
env.info(string.format("* Writing to file : \"%s\"", file)) env.info(string.format("* Writing to file : \"%s\"", file))
env.info("**************************************************************************************************") env.info(string.format("* Writing to file : \"%s\"", PROFILER.getfilename("csv")))
env.info("##############################################################################")
-- Sort by total time. -- Sort by total time.
table.sort(t, function(a,b) return a.tm>b.tm end) table.sort(t, function(a,b) return a.tm>b.tm end)
-- Write data. -- Write data.
PROFILER._flog(f,"") PROFILER._flog(f,"")
PROFILER._flog(f,"************************************************************************************************************************") PROFILER._flog(f,"************************************************************************************************************************")
@ -471,7 +505,7 @@ function PROFILER.showInfo(runTimeGame, runTimeOS)
PROFILER._flog(f,string.format("* Total func calls = %d", Calls)) PROFILER._flog(f,string.format("* Total func calls = %d", Calls))
PROFILER._flog(f,"") PROFILER._flog(f,"")
PROFILER._flog(f,string.format("* Calls per second threshold = %.3f/sec", PROFILER.ThreshCPS)) PROFILER._flog(f,string.format("* Calls per second threshold = %.3f/sec", PROFILER.ThreshCPS))
PROFILER._flog(f,string.format("* Total func time threshold = %.3f/sec", PROFILER.ThreshTtot)) PROFILER._flog(f,string.format("* Total func time threshold = %.3f sec", PROFILER.ThreshTtot))
PROFILER._flog(f,"") PROFILER._flog(f,"")
PROFILER._flog(f,"************************************************************************************************************************") PROFILER._flog(f,"************************************************************************************************************************")
PROFILER._flog(f,"") PROFILER._flog(f,"")
@ -479,7 +513,7 @@ function PROFILER.showInfo(runTimeGame, runTimeOS)
-- Sort by number of calls. -- Sort by number of calls.
table.sort(t, function(a,b) return a.tm/a.count>b.tm/b.count end) table.sort(t, function(a,b) return a.tm/a.count>b.tm/b.count end)
-- Detailed data. -- Detailed data.
PROFILER._flog(f,"") PROFILER._flog(f,"")
PROFILER._flog(f,"************************************************************************************************************************") PROFILER._flog(f,"************************************************************************************************************************")
@ -489,10 +523,10 @@ function PROFILER.showInfo(runTimeGame, runTimeOS)
PROFILER._flog(f,"--------------------------------------") PROFILER._flog(f,"--------------------------------------")
PROFILER._flog(f,"") PROFILER._flog(f,"")
PROFILER.showTable(t, f, runTimeGame) PROFILER.showTable(t, f, runTimeGame)
-- Sort by number of calls. -- Sort by number of calls.
table.sort(t, function(a,b) return a.count>b.count end) table.sort(t, function(a,b) return a.count>b.count end)
-- Detailed data. -- Detailed data.
PROFILER._flog(f,"") PROFILER._flog(f,"")
PROFILER._flog(f,"************************************************************************************************************************") PROFILER._flog(f,"************************************************************************************************************************")
@ -502,7 +536,7 @@ function PROFILER.showInfo(runTimeGame, runTimeOS)
PROFILER._flog(f,"------------------------------------") PROFILER._flog(f,"------------------------------------")
PROFILER._flog(f,"") PROFILER._flog(f,"")
PROFILER.showTable(t, f, runTimeGame) PROFILER.showTable(t, f, runTimeGame)
-- Closing. -- Closing.
PROFILER._flog(f,"") PROFILER._flog(f,"")
PROFILER._flog(f,"************************************************************************************************************************") PROFILER._flog(f,"************************************************************************************************************************")
@ -510,5 +544,7 @@ function PROFILER.showInfo(runTimeGame, runTimeOS)
PROFILER._flog(f,"************************************************************************************************************************") PROFILER._flog(f,"************************************************************************************************************************")
-- Close file. -- Close file.
f:close() f:close()
end
-- Print csv file.
PROFILER.printCSV(t, runTimeGame)
end

View File

@ -191,21 +191,30 @@ end
-- @param #table object The input table. -- @param #table object The input table.
-- @return #table Copy of the input table. -- @return #table Copy of the input table.
UTILS.DeepCopy = function(object) UTILS.DeepCopy = function(object)
local lookup_table = {} local lookup_table = {}
-- Copy function.
local function _copy(object) local function _copy(object)
if type(object) ~= "table" then if type(object) ~= "table" then
return object return object
elseif lookup_table[object] then elseif lookup_table[object] then
return lookup_table[object] return lookup_table[object]
end end
local new_table = {} local new_table = {}
lookup_table[object] = new_table lookup_table[object] = new_table
for index, value in pairs(object) do for index, value in pairs(object) do
new_table[_copy(index)] = _copy(value) new_table[_copy(index)] = _copy(value)
end end
return setmetatable(new_table, getmetatable(object)) return setmetatable(new_table, getmetatable(object))
end end
local objectreturn = _copy(object) local objectreturn = _copy(object)
return objectreturn return objectreturn
end end
@ -359,7 +368,7 @@ UTILS.MpsToMiph = function( mps )
end end
--- Convert meters per second to knots. --- Convert meters per second to knots.
-- @param #number knots Speed in m/s. -- @param #number mps Speed in m/s.
-- @return #number Speed in knots. -- @return #number Speed in knots.
UTILS.MpsToKnots = function( mps ) UTILS.MpsToKnots = function( mps )
return mps * 1.94384 --3600 / 1852 return mps * 1.94384 --3600 / 1852
@ -975,6 +984,22 @@ function UTILS.HdgDiff(h1, h2)
end end
--- Translate 3D vector in the 2D (x,z) plane. y-component (usually altitude) unchanged.
-- @param DCS#Vec3 a Vector in 3D with x, y, z components.
-- @param #number distance The distance to translate.
-- @param #number angle Rotation angle in degrees.
-- @return DCS#Vec3 Vector rotated in the (x,z) plane.
function UTILS.VecTranslate(a, distance, angle)
local SX = a.x
local SY = a.z
local Radians=math.rad(angle or 0)
local TX=distance*math.cos(Radians)+SX
local TY=distance*math.sin(Radians)+SY
return {x=TX, y=a.y, z=TY}
end
--- Rotate 3D vector in the 2D (x,z) plane. y-component (usually altitude) unchanged. --- Rotate 3D vector in the 2D (x,z) plane. y-component (usually altitude) unchanged.
-- @param DCS#Vec3 a Vector in 3D with x, y, z components. -- @param DCS#Vec3 a Vector in 3D with x, y, z components.
-- @param #number angle Rotation angle in degrees. -- @param #number angle Rotation angle in degrees.
@ -996,7 +1021,6 @@ function UTILS.Rotate2D(a, angle)
end end
--- Converts a TACAN Channel/Mode couple into a frequency in Hz. --- Converts a TACAN Channel/Mode couple into a frequency in Hz.
-- @param #number TACANChannel The TACAN channel, i.e. the 10 in "10X". -- @param #number TACANChannel The TACAN channel, i.e. the 10 in "10X".
-- @param #string TACANMode The TACAN mode, i.e. the "X" in "10X". -- @param #string TACANMode The TACAN mode, i.e. the "X" in "10X".
@ -1410,4 +1434,14 @@ function UTILS.GetSunset(Day, Month, Year, Latitude, Longitude, Tlocal)
local DayOfYear=UTILS.GetDayOfYear(Year, Month, Day) local DayOfYear=UTILS.GetDayOfYear(Year, Month, Day)
return UTILS.GetSunRiseAndSet(DayOfYear, Latitude, Longitude, false, Tlocal) return UTILS.GetSunRiseAndSet(DayOfYear, Latitude, Longitude, false, Tlocal)
end
--- Get OS time. Needs os to be desanitized!
-- @return #number Os time in seconds.
function UTILS.GetOSTime()
if os then
return os.clock()
end
return nil
end end

View File

@ -15,6 +15,15 @@
--- @type AIRBASE --- @type AIRBASE
-- @field #string ClassName Name of the class, i.e. "AIRBASE". -- @field #string ClassName Name of the class, i.e. "AIRBASE".
-- @field #table CategoryName Names of airbase categories. -- @field #table CategoryName Names of airbase categories.
-- @field #string AirbaseName Name of the airbase.
-- @field #number AirbaseID Airbase ID.
-- @field #number category Airbase category.
-- @field #table descriptors DCS descriptors.
-- @field #boolean isAirdrome Airbase is an airdrome.
-- @field #boolean isHelipad Airbase is a helipad.
-- @field #boolean isShip Airbase is a ship.
-- @field #table parking Parking spot data.
-- @field #table parkingByID Parking spot data table with ID as key.
-- @field #number activerwyno Active runway number (forced). -- @field #number activerwyno Active runway number (forced).
-- @extends Wrapper.Positionable#POSITIONABLE -- @extends Wrapper.Positionable#POSITIONABLE
@ -440,20 +449,52 @@ AIRBASE.TerminalType = {
-- @field Core.Point#COORDINATE position Position of runway start. -- @field Core.Point#COORDINATE position Position of runway start.
-- @field Core.Point#COORDINATE endpoint End point of runway. -- @field Core.Point#COORDINATE endpoint End point of runway.
-- Registration. -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Registration
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Create a new AIRBASE from DCSAirbase. --- Create a new AIRBASE from DCSAirbase.
-- @param #AIRBASE self -- @param #AIRBASE self
-- @param #string AirbaseName The name of the airbase. -- @param #string AirbaseName The name of the airbase.
-- @return Wrapper.Airbase#AIRBASE -- @return #AIRBASE self
function AIRBASE:Register( AirbaseName ) function AIRBASE:Register(AirbaseName)
-- Inherit everything from positionable.
local self=BASE:Inherit(self, POSITIONABLE:New(AirbaseName)) --#AIRBASE
-- Set airbase name.
self.AirbaseName=AirbaseName
-- Set airbase ID.
self.AirbaseID=self:GetID(true)
-- Get descriptors.
self.descriptors=self:GetDesc()
-- Category.
self.category=self.descriptors and self.descriptors.category or Airbase.Category.AIRDROME
-- Set category.
if self.category==Airbase.Category.AIRDROME then
self.isAirdrome=true
elseif self.category==Airbase.Category.HELIPAD then
self.isHelipad=true
elseif self.category==Airbase.Category.SHIP then
self.isShip=true
else
self:E("ERROR: Unknown airbase category!")
end
self:_InitParkingSpots()
local self = BASE:Inherit( self, POSITIONABLE:New( AirbaseName ) ) --#AIRBASE
self.AirbaseName = AirbaseName
self.AirbaseID = self:GetID(true)
local vec2=self:GetVec2() local vec2=self:GetVec2()
-- Init coordinate.
self:GetCoordinate()
if vec2 then if vec2 then
self.AirbaseZone = ZONE_RADIUS:New( AirbaseName, vec2, 2500 ) -- TODO: For ships we need a moving zone.
self.AirbaseZone=ZONE_RADIUS:New( AirbaseName, vec2, 2500 )
else else
self:E(string.format("ERROR: Cound not get position Vec2 of airbase %s", AirbaseName)) self:E(string.format("ERROR: Cound not get position Vec2 of airbase %s", AirbaseName))
end end
@ -461,7 +502,9 @@ function AIRBASE:Register( AirbaseName )
return self return self
end end
-- Reference methods. -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Reference methods
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Finds a AIRBASE from the _DATABASE using a DCSAirbase object. --- Finds a AIRBASE from the _DATABASE using a DCSAirbase object.
-- @param #AIRBASE self -- @param #AIRBASE self
@ -508,7 +551,9 @@ end
-- @param #AIRBASE self -- @param #AIRBASE self
-- @return DCS#Airbase DCS airbase object. -- @return DCS#Airbase DCS airbase object.
function AIRBASE:GetDCSObject() function AIRBASE:GetDCSObject()
local DCSAirbase = Airbase.getByName( self.AirbaseName )
-- Get the DCS object.
local DCSAirbase = Airbase.getByName(self.AirbaseName)
if DCSAirbase then if DCSAirbase then
return DCSAirbase return DCSAirbase
@ -533,7 +578,7 @@ function AIRBASE.GetAllAirbases(coalition, category)
local airbases={} local airbases={}
for _,_airbase in pairs(_DATABASE.AIRBASES) do for _,_airbase in pairs(_DATABASE.AIRBASES) do
local airbase=_airbase --#AIRBASE local airbase=_airbase --#AIRBASE
if (coalition~=nil and airbase:GetCoalition()==coalition) or coalition==nil then if coalition==nil or airbase:GetCoalition()==coalition then
if category==nil or category==airbase:GetAirbaseCategory() then if category==nil or category==airbase:GetAirbaseCategory() then
table.insert(airbases, airbase) table.insert(airbases, airbase)
end end
@ -543,6 +588,25 @@ function AIRBASE.GetAllAirbases(coalition, category)
return airbases return airbases
end end
--- Get all airbase names of the current map. This includes ships and FARPS.
-- @param DCS#Coalition coalition (Optional) Return only airbases belonging to the specified coalition. By default, all airbases of the map are returned.
-- @param #number category (Optional) Return only airbases of a certain category, e.g. Airbase.Category.FARP
-- @return #table Table containing all airbase names of the current map.
function AIRBASE.GetAllAirbaseNames(coalition, category)
local airbases={}
for airbasename,_airbase in pairs(_DATABASE.AIRBASES) do
local airbase=_airbase --#AIRBASE
if coalition==nil or airbase:GetCoalition()==coalition then
if category==nil or category==airbase:GetAirbaseCategory() then
table.insert(airbases, airbasename)
end
end
end
return airbases
end
--- Get ID of the airbase. --- Get ID of the airbase.
-- @param #AIRBASE self -- @param #AIRBASE self
-- @param #boolean unique (Optional) If true, ships will get a negative sign as the unit ID might be the same as an airbase ID. Default off! -- @param #boolean unique (Optional) If true, ships will get a negative sign as the unit ID might be the same as an airbase ID. Default off!
@ -565,22 +629,6 @@ function AIRBASE:GetID(unique)
local airbaseCategory=self:GetAirbaseCategory() local airbaseCategory=self:GetAirbaseCategory()
--env.info(string.format("FF airbase=%s id=%s category=%s", tostring(AirbaseName), tostring(airbaseID), tostring(airbaseCategory)))
-- No way AFIK to get the DCS version. So we check if the event exists. That should tell us if we are on DCS 2.5.6 or prior to that.
--[[
if world.event.S_EVENT_KILL and world.event.S_EVENT_KILL>0 and airbaseCategory==Airbase.Category.AIRDROME then
-- We have to take the key value of this loop!
airbaseID=DCSAirbaseId
-- Now another quirk: for Caucasus, we need to add 11 to the key value to get the correct ID. See https://forums.eagle.ru/showpost.php?p=4210774&postcount=11
if UTILS.GetDCSMap()==DCSMAP.Caucasus then
airbaseID=airbaseID+11
end
end
]]
if AirbaseName==self.AirbaseName then if AirbaseName==self.AirbaseName then
if airbaseCategory==Airbase.Category.SHIP or airbaseCategory==Airbase.Category.HELIPAD then if airbaseCategory==Airbase.Category.SHIP or airbaseCategory==Airbase.Category.HELIPAD then
-- Ships get a negative sign as their unit number might be the same as the ID of another airbase. -- Ships get a negative sign as their unit number might be the same as the ID of another airbase.
@ -598,6 +646,38 @@ function AIRBASE:GetID(unique)
end end
--- Get category of airbase.
-- @param #AIRBASE self
-- @return #number Category of airbase from GetDesc().category.
function AIRBASE:GetAirbaseCategory()
return self.category
end
--- Check if airbase is an airdrome.
-- @param #AIRBASE self
-- @return #boolean If true, airbase is an airdrome.
function AIRBASE:IsAirdrome()
return self.isAirdrome
end
--- Check if airbase is a helipad.
-- @param #AIRBASE self
-- @return #boolean If true, airbase is a helipad.
function AIRBASE:IsHelipad()
return self.isHelipad
end
--- Check if airbase is a ship.
-- @param #AIRBASE self
-- @return #boolean If true, airbase is a ship.
function AIRBASE:IsShip()
return self.isShip
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Parking
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Returns a table of parking data for a given airbase. If the optional parameter *available* is true only available parking will be returned, otherwise all parking at the base is returned. Term types have the following enumerated values: --- Returns a table of parking data for a given airbase. If the optional parameter *available* is true only available parking will be returned, otherwise all parking at the base is returned. Term types have the following enumerated values:
-- --
-- * 16 : Valid spawn points on runway -- * 16 : Valid spawn points on runway
@ -728,6 +808,58 @@ function AIRBASE:GetParkingSpotsCoordinates(termtype)
return spots return spots
end end
--- Get a table containing the coordinates, terminal index and terminal type of free parking spots at an airbase.
-- @param #AIRBASE self
-- @return#AIRBASE self
function AIRBASE:_InitParkingSpots()
-- Get parking data of all spots (free or occupied)
local parkingdata=self:GetParkingData(false)
-- Init table.
self.parking={}
self.parkingByID={}
self.NparkingTotal=0
self.NparkingTerminal={}
for _,terminalType in pairs(AIRBASE.TerminalType) do
self.NparkingTerminal[terminalType]=0
end
-- Put coordinates of parking spots into table.
for _,spot in pairs(parkingdata) do
-- New parking spot.
local park={} --#AIRBASE.ParkingSpot
park.Vec3=spot.vTerminalPos
park.Coordinate=COORDINATE:NewFromVec3(spot.vTerminalPos)
park.DistToRwy=spot.fDistToRW
park.Free=nil
park.TerminalID=spot.Term_Index
park.TerminalID0=spot.Term_Index_0
park.TerminalType=spot.Term_Type
park.TOAC=spot.TO_AC
for _,terminalType in pairs(AIRBASE.TerminalType) do
if self._CheckTerminalType(terminalType, park.TerminalType) then
self.NparkingTerminal[terminalType]=self.NparkingTerminal[terminalType]+1
end
end
self.parkingByID[park.TerminalID]=park
table.insert(self.parking, park)
end
return self
end
--- Get a table containing the coordinates, terminal index and terminal type of free parking spots at an airbase.
-- @param #AIRBASE self
-- @param #number TerminalID Terminal ID.
-- @return #AIRBASE.ParkingSpot Parking spot.
function AIRBASE:_GetParkingSpotByID(TerminalID)
return self.parkingByID[TerminalID]
end
--- Get a table containing the coordinates, terminal index and terminal type of free parking spots at an airbase. --- Get a table containing the coordinates, terminal index and terminal type of free parking spots at an airbase.
-- @param #AIRBASE self -- @param #AIRBASE self
@ -737,6 +869,7 @@ function AIRBASE:GetParkingSpotsTable(termtype)
-- Get parking data of all spots (free or occupied) -- Get parking data of all spots (free or occupied)
local parkingdata=self:GetParkingData(false) local parkingdata=self:GetParkingData(false)
-- Get parking data of all free spots. -- Get parking data of all free spots.
local parkingfree=self:GetParkingData(true) local parkingfree=self:GetParkingData(true)
@ -753,15 +886,18 @@ function AIRBASE:GetParkingSpotsTable(termtype)
-- Put coordinates of parking spots into table. -- Put coordinates of parking spots into table.
local spots={} local spots={}
for _,_spot in pairs(parkingdata) do for _,_spot in pairs(parkingdata) do
if AIRBASE._CheckTerminalType(_spot.Term_Type, termtype) then
self:T2({_spot=_spot})
local _free=_isfree(_spot)
local _coord=COORDINATE:NewFromVec3(_spot.vTerminalPos)
table.insert(spots, {Coordinate=_coord, TerminalID=_spot.Term_Index, TerminalType=_spot.Term_Type, TOAC=_spot.TO_AC, Free=_free, TerminalID0=_spot.Term_Index_0, DistToRwy=_spot.fDistToRW})
end
end
self:T2({ spots = spots } ) if AIRBASE._CheckTerminalType(_spot.Term_Type, termtype) then
local spot=self:_GetParkingSpotByID(_spot.Term_Index)
spot.Free=_isfree(_spot) -- updated
spot.TOAC=_spot.TO_AC -- updated
table.insert(spots, spot)
end
end
return spots return spots
end end
@ -781,8 +917,14 @@ function AIRBASE:GetFreeParkingSpotsTable(termtype, allowTOAC)
for _,_spot in pairs(parkingfree) do for _,_spot in pairs(parkingfree) do
if AIRBASE._CheckTerminalType(_spot.Term_Type, termtype) and _spot.Term_Index>0 then if AIRBASE._CheckTerminalType(_spot.Term_Type, termtype) and _spot.Term_Index>0 then
if (allowTOAC and allowTOAC==true) or _spot.TO_AC==false then if (allowTOAC and allowTOAC==true) or _spot.TO_AC==false then
local _coord=COORDINATE:NewFromVec3(_spot.vTerminalPos)
table.insert(freespots, {Coordinate=_coord, TerminalID=_spot.Term_Index, TerminalType=_spot.Term_Type, TOAC=_spot.TO_AC, Free=true, TerminalID0=_spot.Term_Index_0, DistToRwy=_spot.fDistToRW}) local spot=self:_GetParkingSpotByID(_spot.Term_Index)
spot.Free=true -- updated
spot.TOAC=_spot.TO_AC -- updated
table.insert(freespots, spot)
end end
end end
end end
@ -795,14 +937,10 @@ end
-- @param #number TerminalID The terminal ID of the parking spot. -- @param #number TerminalID The terminal ID of the parking spot.
-- @return #AIRBASE.ParkingSpot Table free parking spots. Table has the elements ".Coordinate, ".TerminalID", ".TerminalType", ".TOAC", ".Free", ".TerminalID0", ".DistToRwy". -- @return #AIRBASE.ParkingSpot Table free parking spots. Table has the elements ".Coordinate, ".TerminalID", ".TerminalType", ".TOAC", ".Free", ".TerminalID0", ".DistToRwy".
function AIRBASE:GetParkingSpotData(TerminalID) function AIRBASE:GetParkingSpotData(TerminalID)
self:F({TerminalID=TerminalID})
-- Get parking data. -- Get parking data.
local parkingdata=self:GetParkingSpotsTable() local parkingdata=self:GetParkingSpotsTable()
-- Debug output.
self:T2({parkingdata=parkingdata})
for _,_spot in pairs(parkingdata) do for _,_spot in pairs(parkingdata) do
local spot=_spot --#AIRBASE.ParkingSpot local spot=_spot --#AIRBASE.ParkingSpot
self:T({TerminalID=spot.TerminalID,TerminalType=spot.TerminalType}) self:T({TerminalID=spot.TerminalID,TerminalType=spot.TerminalType})
@ -1041,99 +1179,6 @@ function AIRBASE:FindFreeParkingSpotForAircraft(group, terminaltype, scanradius,
return validspots return validspots
end end
--- Function that checks if at leat one unit of a group has been spawned close to a spawn point on the runway.
-- @param #AIRBASE self
-- @param Wrapper.Group#GROUP group Group to be checked.
-- @param #number radius Radius around the spawn point to be checked. Default is 50 m.
-- @param #boolean despawn If true, the group is destroyed.
-- @return #boolean True if group is within radius around spawn points on runway.
function AIRBASE:CheckOnRunWay(group, radius, despawn)
-- Default radius.
radius=radius or 50
-- We only check at real airbases (not FARPS or ships).
if self:GetAirbaseCategory()~=Airbase.Category.AIRDROME then
return false
end
if group and group:IsAlive() then
-- Debug.
self:T(string.format("%s, checking if group %s is on runway?",self:GetName(), group:GetName()))
-- Get coordinates on runway.
local runwaypoints=self:GetParkingSpotsCoordinates(AIRBASE.TerminalType.Runway)
-- Mark runway spawn points.
--[[
for _i,_coord in pairs(runwaypoints) do
_coord:MarkToAll(string.format("runway %d",_i))
end
]]
-- Get units of group.
local units=group:GetUnits()
-- Loop over units.
for _,_unit in pairs(units) do
local unit=_unit --Wrapper.Unit#UNIT
-- Check if unit is alive and not in air.
if unit and unit:IsAlive() and not unit:InAir() then
self:T(string.format("%s, checking if unit %s is on runway?",self:GetName(), unit:GetName()))
-- Loop over runway spawn points.
for _i,_coord in pairs(runwaypoints) do
-- Distance between unit and spawn pos.
local dist=unit:GetCoordinate():Get2DDistance(_coord)
-- Mark unit spawn points for debugging.
--unit:GetCoordinate():MarkToAll(string.format("unit %s distance to rwy %d = %d",unit:GetName(),_i, dist))
-- Check if unit is withing radius.
if dist<radius then
self:E(string.format("%s, unit %s of group %s was spawned on runway #%d. Distance %.1f < radius %.1f m. Despawn = %s.", self:GetName(), unit:GetName(), group:GetName(),_i, dist, radius, tostring(despawn)))
--unit:FlareRed()
if despawn then
group:Destroy(true)
end
return true
else
self:T(string.format("%s, unit %s of group %s was NOT spawned on runway #%d. Distance %.1f > radius %.1f m. Despawn = %s.", self:GetName(), unit:GetName(), group:GetName(),_i, dist, radius, tostring(despawn)))
--unit:FlareGreen()
end
end
else
self:T(string.format("%s, checking if unit %s of group %s is on runway. Unit is NOT alive.",self:GetName(), unit:GetName(), group:GetName()))
end
end
else
self:T(string.format("%s, checking if group %s is on runway. Group is NOT alive.",self:GetName(), group:GetName()))
end
return false
end
--- Get category of airbase.
-- @param #AIRBASE self
-- @return #number Category of airbase from GetDesc().category.
function AIRBASE:GetAirbaseCategory()
local desc=self:GetDesc()
local category=Airbase.Category.AIRDROME
if desc and desc.category then
category=desc.category
else
self:E(string.format("ERROR: Cannot get category of airbase %s due to DCS 2.5.6 bug! Assuming it is an AIRDROME for now...", tostring(self.AirbaseName)))
end
return category
end
--- Helper function to check for the correct terminal type including "artificial" ones. --- Helper function to check for the correct terminal type including "artificial" ones.
-- @param #number Term_Type Termial type from getParking routine. -- @param #number Term_Type Termial type from getParking routine.
-- @param #AIRBASE.TerminalType termtype Terminal type from AIRBASE.TerminalType enumerator. -- @param #AIRBASE.TerminalType termtype Terminal type from AIRBASE.TerminalType enumerator.
@ -1180,6 +1225,10 @@ function AIRBASE._CheckTerminalType(Term_Type, termtype)
return match return match
end end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Runway
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Get runways data. Only for airdromes! --- Get runways data. Only for airdromes!
-- @param #AIRBASE self -- @param #AIRBASE self
-- @param #number magvar (Optional) Magnetic variation in degrees. -- @param #number magvar (Optional) Magnetic variation in degrees.
@ -1194,41 +1243,124 @@ function AIRBASE:GetRunwayData(magvar, mark)
return {} return {}
end end
-- Get spawn points on runway. -- Get spawn points on runway. These can be used to determine the runway heading.
local runwaycoords=self:GetParkingSpotsCoordinates(AIRBASE.TerminalType.Runway) local runwaycoords=self:GetParkingSpotsCoordinates(AIRBASE.TerminalType.Runway)
-- Debug: For finding the numbers of the spawn points belonging to each runway.
if false then
for i,_coord in pairs(runwaycoords) do
local coord=_coord --Core.Point#COORDINATE
coord:Translate(100, 0):MarkToAll("Runway i="..i)
end
end
-- Magnetic declination. -- Magnetic declination.
magvar=magvar or UTILS.GetMagneticDeclination() magvar=magvar or UTILS.GetMagneticDeclination()
-- Number of runways.
local N=#runwaycoords local N=#runwaycoords
local dN=2 local N2=N/2
local ex=false local exception=false
-- Airbase name.
local name=self:GetName() local name=self:GetName()
-- Exceptions
if name==AIRBASE.Nevada.Jean_Airport or if name==AIRBASE.Nevada.Jean_Airport or
name==AIRBASE.Nevada.Creech_AFB or name==AIRBASE.Nevada.Creech_AFB or
name==AIRBASE.PersianGulf.Abu_Dhabi_International_Airport or name==AIRBASE.PersianGulf.Abu_Dhabi_International_Airport or
name==AIRBASE.PersianGulf.Dubai_Intl or name==AIRBASE.PersianGulf.Dubai_Intl or
name==AIRBASE.PersianGulf.Shiraz_International_Airport or name==AIRBASE.PersianGulf.Shiraz_International_Airport or
name==AIRBASE.PersianGulf.Kish_International_Airport then name==AIRBASE.PersianGulf.Kish_International_Airport
then
N=#runwaycoords/2 -- 1-->4, 2-->3, 3-->2, 4-->1
dN=1 exception=1
ex=true
elseif UTILS.GetDCSMap()==DCSMAP.Syria and N>=2 and
name~=AIRBASE.Syria.Minakh and
name~=AIRBASE.Syria.Damascus and
name~=AIRBASE.Syria.Khalkhalah and
name~=AIRBASE.Syria.Marj_Ruhayyil and
name~=AIRBASE.Syria.Beirut_Rafic_Hariri then
-- 1-->3, 2-->4, 3-->1, 4-->2
exception=2
end
local function f(i)
local j
if exception==1 then
j=N-(i+1) -- 1-->4, 2-->3
elseif exception==2 then
if i<=N2 then
j=i+N2 -- 1-->3, 2-->4
else
j=i-N2 -- 3-->1, 4-->3
end
else
if i%2==0 then
j=i-1 -- even 2-->1, 4-->3
else
j=i+1 -- odd 1-->2, 3-->4
end
end
-- Special case where there is no obvious order.
if name==AIRBASE.Syria.Beirut_Rafic_Hariri then
if i==1 then
j=3
elseif i==2 then
j=6
elseif i==3 then
j=1
elseif i==4 then
j=5
elseif i==5 then
j=4
elseif i==6 then
j=2
end
end
if name==AIRBASE.Syria.Ramat_David then
if i==1 then
j=4
elseif i==2 then
j=6
elseif i==3 then
j=5
elseif i==4 then
j=1
elseif i==5 then
j=3
elseif i==6 then
j=2
end
end
return j
end end
for i=1,N,dN do for i=1,N do
local j=i+1 -- Get the other spawn point coordinate.
if ex then local j=f(i)
--j=N+i
j=#runwaycoords-i+1
end
-- Coordinates of the two runway points. -- Coordinates of the two runway points.
local c1=runwaycoords[i] --Core.Point#COORDINATES local c1=runwaycoords[i] --Core.Point#COORDINATE
local c2=runwaycoords[j] --Core.Point#COORDINATES local c2=runwaycoords[j] --Core.Point#COORDINATE
-- Heading of runway. -- Heading of runway.
local hdg=c1:HeadingTo(c2) local hdg=c1:HeadingTo(c2)
@ -1245,11 +1377,11 @@ function AIRBASE:GetRunwayData(magvar, mark)
runway.endpoint=c2 runway.endpoint=c2
-- Debug info. -- Debug info.
self:T(string.format("Airbase %s: Adding runway id=%s, heading=%03d, length=%d m", self:GetName(), runway.idx, runway.heading, runway.length)) self:I(string.format("Airbase %s: Adding runway id=%s, heading=%03d, length=%d m i=%d j=%d", self:GetName(), runway.idx, runway.heading, runway.length, i, j))
-- Debug mark -- Debug mark
if mark then if mark then
runway.position:MarkToAll(string.format("Runway %s: true heading=%03d (magvar=%d), length=%d m", runway.idx, runway.heading, magvar, runway.length)) runway.position:MarkToAll(string.format("Runway %s: true heading=%03d (magvar=%d), length=%d m, i=%d, j=%d", runway.idx, runway.heading, magvar, runway.length, i, j))
end end
-- Add runway. -- Add runway.
@ -1257,38 +1389,6 @@ function AIRBASE:GetRunwayData(magvar, mark)
end end
-- Get inverse runways
local inverse={}
for _,_runway in pairs(runways) do
local r=_runway --#AIRBASE.Runway
local runway={} --#AIRBASE.Runway
runway.heading=r.heading-180
if runway.heading<0 then
runway.heading=runway.heading+360
end
runway.idx=string.format("%02d", math.max(0, UTILS.Round((runway.heading-magvar)/10, 0)))
runway.length=r.length
runway.position=r.endpoint
runway.endpoint=r.position
-- Debug info.
self:T(string.format("Airbase %s: Adding runway id=%s, heading=%03d, length=%d m", self:GetName(), runway.idx, runway.heading, runway.length))
-- Debug mark
if mark then
runway.position:MarkToAll(string.format("Runway %s: true heading=%03d (magvar=%d), length=%d m", runway.idx, runway.heading, magvar, runway.length))
end
-- Add runway.
table.insert(inverse, runway)
end
-- Add inverse runway.
for _,runway in pairs(inverse) do
table.insert(runways, runway)
end
return runways return runways
end end
@ -1358,3 +1458,73 @@ function AIRBASE:GetActiveRunway(magvar)
return runways[iact] return runways[iact]
end end
--- Function that checks if at leat one unit of a group has been spawned close to a spawn point on the runway.
-- @param #AIRBASE self
-- @param Wrapper.Group#GROUP group Group to be checked.
-- @param #number radius Radius around the spawn point to be checked. Default is 50 m.
-- @param #boolean despawn If true, the group is destroyed.
-- @return #boolean True if group is within radius around spawn points on runway.
function AIRBASE:CheckOnRunWay(group, radius, despawn)
-- Default radius.
radius=radius or 50
-- We only check at real airbases (not FARPS or ships).
if self:GetAirbaseCategory()~=Airbase.Category.AIRDROME then
return false
end
if group and group:IsAlive() then
-- Debug.
self:T(string.format("%s, checking if group %s is on runway?",self:GetName(), group:GetName()))
-- Get coordinates on runway.
local runwaypoints=self:GetParkingSpotsCoordinates(AIRBASE.TerminalType.Runway)
-- Get units of group.
local units=group:GetUnits()
-- Loop over units.
for _,_unit in pairs(units) do
local unit=_unit --Wrapper.Unit#UNIT
-- Check if unit is alive and not in air.
if unit and unit:IsAlive() and not unit:InAir() then
self:T(string.format("%s, checking if unit %s is on runway?",self:GetName(), unit:GetName()))
-- Loop over runway spawn points.
for _i,_coord in pairs(runwaypoints) do
-- Distance between unit and spawn pos.
local dist=unit:GetCoordinate():Get2DDistance(_coord)
-- Mark unit spawn points for debugging.
--unit:GetCoordinate():MarkToAll(string.format("unit %s distance to rwy %d = %d",unit:GetName(),_i, dist))
-- Check if unit is withing radius.
if dist<radius then
self:E(string.format("%s, unit %s of group %s was spawned on runway #%d. Distance %.1f < radius %.1f m. Despawn = %s.", self:GetName(), unit:GetName(), group:GetName(),_i, dist, radius, tostring(despawn)))
--unit:FlareRed()
if despawn then
group:Destroy(true)
end
return true
else
self:T(string.format("%s, unit %s of group %s was NOT spawned on runway #%d. Distance %.1f > radius %.1f m. Despawn = %s.", self:GetName(), unit:GetName(), group:GetName(),_i, dist, radius, tostring(despawn)))
--unit:FlareGreen()
end
end
else
self:T(string.format("%s, checking if unit %s of group %s is on runway. Unit is NOT alive.",self:GetName(), unit:GetName(), group:GetName()))
end
end
else
self:T(string.format("%s, checking if group %s is on runway. Group is NOT alive.",self:GetName(), group:GetName()))
end
return false
end

View File

@ -243,8 +243,7 @@ end
--- Returns the initial health. --- Returns the initial health.
-- @param #CONTROLLABLE self -- @param #CONTROLLABLE self
-- @return #number The controllable health value (unit or group average). -- @return #number The controllable health value (unit or group average) or `nil` if the controllable does not exist.
-- @return #nil The controllable is not existing or alive.
function CONTROLLABLE:GetLife0() function CONTROLLABLE:GetLife0()
self:F2( self.ControllableName ) self:F2( self.ControllableName )
@ -296,7 +295,6 @@ end
-- @return #nil The CONTROLLABLE is not existing or alive. -- @return #nil The CONTROLLABLE is not existing or alive.
function CONTROLLABLE:GetFuel() function CONTROLLABLE:GetFuel()
self:F( self.ControllableName ) self:F( self.ControllableName )
return nil return nil
end end
@ -1429,16 +1427,6 @@ end
-- @return DCS#Task The DCS task structure. -- @return DCS#Task The DCS task structure.
function CONTROLLABLE:TaskFireAtPoint( Vec2, Radius, AmmoCount, WeaponType ) function CONTROLLABLE:TaskFireAtPoint( Vec2, Radius, AmmoCount, WeaponType )
-- FireAtPoint = {
-- id = 'FireAtPoint',
-- params = {
-- point = Vec2,
-- radius = Distance,
-- expendQty = number,
-- expendQtyEnabled = boolean,
-- }
-- }
local DCSTask = { local DCSTask = {
id = 'FireAtPoint', id = 'FireAtPoint',
params = { params = {
@ -1458,7 +1446,6 @@ function CONTROLLABLE:TaskFireAtPoint( Vec2, Radius, AmmoCount, WeaponType )
DCSTask.params.weaponType=WeaponType DCSTask.params.weaponType=WeaponType
end end
self:T3( { DCSTask } )
return DCSTask return DCSTask
end end

View File

@ -261,7 +261,9 @@ end
-- @param #string GroupName The Group name -- @param #string GroupName The Group name
-- @return #GROUP self -- @return #GROUP self
function GROUP:Register( GroupName ) function GROUP:Register( GroupName )
local self = BASE:Inherit( self, CONTROLLABLE:New( GroupName ) ) -- #GROUP local self = BASE:Inherit( self, CONTROLLABLE:New( GroupName ) ) -- #GROUP
self.GroupName = GroupName self.GroupName = GroupName
self:SetEventPriority( 4 ) self:SetEventPriority( 4 )
@ -668,14 +670,15 @@ end
-- @param #number UnitNumber The number of the UNIT wrapper class to be returned. -- @param #number UnitNumber The number of the UNIT wrapper class to be returned.
-- @return Wrapper.Unit#UNIT The UNIT wrapper class. -- @return Wrapper.Unit#UNIT The UNIT wrapper class.
function GROUP:GetUnit( UnitNumber ) function GROUP:GetUnit( UnitNumber )
self:F3( { self.GroupName, UnitNumber } )
local DCSGroup = self:GetDCSObject() local DCSGroup = self:GetDCSObject()
if DCSGroup then if DCSGroup then
local DCSUnit = DCSGroup:getUnit( UnitNumber ) local DCSUnit = DCSGroup:getUnit( UnitNumber )
local UnitFound = UNIT:Find( DCSGroup:getUnit( UnitNumber ) )
self:T2( UnitFound ) local UnitFound = UNIT:Find(DCSUnit)
return UnitFound return UnitFound
end end
@ -688,13 +691,11 @@ end
-- @param #number UnitNumber The number of the DCS Unit to be returned. -- @param #number UnitNumber The number of the DCS Unit to be returned.
-- @return DCS#Unit The DCS Unit. -- @return DCS#Unit The DCS Unit.
function GROUP:GetDCSUnit( UnitNumber ) function GROUP:GetDCSUnit( UnitNumber )
self:F3( { self.GroupName, UnitNumber } )
local DCSGroup = self:GetDCSObject() local DCSGroup=self:GetDCSObject()
if DCSGroup then if DCSGroup then
local DCSUnitFound = DCSGroup:getUnit( UnitNumber ) local DCSUnitFound=DCSGroup:getUnit( UnitNumber )
self:T3( DCSUnitFound )
return DCSUnitFound return DCSUnitFound
end end
@ -706,14 +707,14 @@ end
-- @param #GROUP self -- @param #GROUP self
-- @return #number The DCS Group size. -- @return #number The DCS Group size.
function GROUP:GetSize() function GROUP:GetSize()
self:F3( { self.GroupName } )
local DCSGroup = self:GetDCSObject() local DCSGroup = self:GetDCSObject()
if DCSGroup then if DCSGroup then
local GroupSize = DCSGroup:getSize() local GroupSize = DCSGroup:getSize()
if GroupSize then if GroupSize then
self:T3( GroupSize )
return GroupSize return GroupSize
else else
return 0 return 0
@ -946,24 +947,29 @@ end
-- @param #GROUP self -- @param #GROUP self
-- @return DCS#Vec2 Current Vec2 point of the first DCS Unit of the DCS Group. -- @return DCS#Vec2 Current Vec2 point of the first DCS Unit of the DCS Group.
function GROUP:GetVec2() function GROUP:GetVec2()
self:F2( self.GroupName )
local UnitPoint = self:GetUnit(1) local Unit=self:GetUnit(1)
UnitPoint:GetVec2()
local GroupPointVec2 = UnitPoint:GetVec2() if Unit then
self:T3( GroupPointVec2 ) return Unit:GetVec2()
return GroupPointVec2 end
end end
--- Returns the current Vec3 vector of the first DCS Unit in the GROUP. --- Returns the current Vec3 vector of the first DCS Unit in the GROUP.
-- @param #GROUP self -- @param #GROUP self
-- @return DCS#Vec3 Current Vec3 of the first DCS Unit of the GROUP. -- @return DCS#Vec3 Current Vec3 of the first DCS Unit of the GROUP.
function GROUP:GetVec3() function GROUP:GetVec3()
self:F2( self.GroupName )
local GroupVec3 = self:GetUnit(1):GetVec3() -- Get first unit.
self:T3( GroupVec3 ) local unit=self:GetUnit(1)
return GroupVec3
if unit then
return unit:GetVec3()
end
self:E("ERROR: Cannot get Vec3 of group "..tostring(self.GroupName))
return nil
end end
--- Returns a POINT_VEC2 object indicating the point in 2D of the first UNIT of the GROUP within the mission. --- Returns a POINT_VEC2 object indicating the point in 2D of the first UNIT of the GROUP within the mission.
@ -1166,6 +1172,32 @@ end
do -- Is Zone methods do -- Is Zone methods
--- Check if any unit of a group is inside a @{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.
function GROUP:IsInZone( Zone )
if self:IsAlive() then
for UnitID, UnitData in pairs(self:GetUnits()) do
local Unit = UnitData -- Wrapper.Unit#UNIT
if Zone:IsVec3InZone(Unit:GetVec3()) then
return true -- At least one unit is in the zone. That is enough.
else
-- This one is not but another could be.
end
end
return false
end
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 @{Zone}.
-- @param #GROUP self -- @param #GROUP self
-- @param Core.Zone#ZONE_BASE Zone The zone to test. -- @param Core.Zone#ZONE_BASE Zone The zone to test.
@ -2100,6 +2132,7 @@ end
--- Calculate the maxium A2G threat level of the Group. --- Calculate the maxium A2G threat level of the Group.
-- @param #GROUP self -- @param #GROUP self
-- @return #number Number between 0 and 10.
function GROUP:CalculateThreatLevelA2G() function GROUP:CalculateThreatLevelA2G()
local MaxThreatLevelA2G = 0 local MaxThreatLevelA2G = 0
@ -2115,6 +2148,25 @@ function GROUP:CalculateThreatLevelA2G()
return MaxThreatLevelA2G return MaxThreatLevelA2G
end end
--- Get threat level of the group.
-- @param #GROUP self
-- @return #number Max threat level (a number between 0 and 10).
function GROUP:GetThreatLevel()
local threatlevelMax = 0
for UnitName, UnitData in pairs(self:GetUnits()) do
local ThreatUnit = UnitData -- Wrapper.Unit#UNIT
local threatlevel = ThreatUnit:GetThreatLevel()
if threatlevel > threatlevelMax then
threatlevelMax=threatlevel
end
end
return threatlevelMax
end
--- Returns true if the first unit of the GROUP is in the air. --- Returns true if the first unit of the GROUP is in the air.
-- @param Wrapper.Group#GROUP self -- @param Wrapper.Group#GROUP self
-- @return #boolean true if in the first unit of the group is in the air or #nil if the GROUP is not existing or not alive. -- @return #boolean true if in the first unit of the group is in the air or #nil if the GROUP is not existing or not alive.

View File

@ -1,5 +1,5 @@
--- **Wrapper** - Markers On the F10 map. --- **Wrapper** - Markers On the F10 map.
-- --
-- **Main Features:** -- **Main Features:**
-- --
-- * Convenient handling of markers via multiple user API functions. -- * Convenient handling of markers via multiple user API functions.
@ -8,7 +8,7 @@
-- * Retrieve data such as text and coordinate. -- * Retrieve data such as text and coordinate.
-- * Marker specific FSM events when a marker is added, removed or changed. -- * Marker specific FSM events when a marker is added, removed or changed.
-- * Additional FSM events when marker text or position is changed. -- * Additional FSM events when marker text or position is changed.
-- --
-- === -- ===
-- --
-- ### Author: **funkyfranky** -- ### Author: **funkyfranky**
@ -36,104 +36,104 @@
-- ![Banner Image](..\Presentations\MARKER\Marker_Main.jpg) -- ![Banner Image](..\Presentations\MARKER\Marker_Main.jpg)
-- --
-- # The MARKER Class Idea -- # The MARKER Class Idea
-- --
-- The MARKER class simplifies creating, updating and removing of markers on the F10 map. -- The MARKER class simplifies creating, updating and removing of markers on the F10 map.
-- --
-- # Create a Marker -- # Create a Marker
-- --
-- -- Create a MARKER object at Batumi with a trivial text. -- -- Create a MARKER object at Batumi with a trivial text.
-- local Coordinate=AIRBASE:FindByName("Batumi"):GetCoordinate() -- local Coordinate=AIRBASE:FindByName("Batumi"):GetCoordinate()
-- mymarker=MARKER:New(Coordinate, "I am Batumi Airfield") -- mymarker=MARKER:New(Coordinate, "I am Batumi Airfield")
-- --
-- Now this does **not** show the marker yet. We still need to specifiy to whom it is shown. There are several options, i.e. -- Now this does **not** show the marker yet. We still need to specifiy to whom it is shown. There are several options, i.e.
-- show the marker to everyone, to a speficic coaliton only, or only to a specific group. -- show the marker to everyone, to a speficic coaliton only, or only to a specific group.
-- --
-- ## For Everyone -- ## For Everyone
-- --
-- If the marker should be visible to everyone, you can use the :ToAll() function. -- If the marker should be visible to everyone, you can use the :ToAll() function.
-- --
-- mymarker=MARKER:New(Coordinate, "I am Batumi Airfield"):ToAll() -- mymarker=MARKER:New(Coordinate, "I am Batumi Airfield"):ToAll()
-- --
-- ## For a Coaliton -- ## For a Coaliton
-- --
-- If the maker should be visible to a specific coalition, you can use the :ToCoalition() function. -- If the maker should be visible to a specific coalition, you can use the :ToCoalition() function.
-- --
-- mymarker=MARKER:New(Coordinate, "I am Batumi Airfield"):ToCoaliton(coaliton.side.BLUE) -- mymarker=MARKER:New(Coordinate, "I am Batumi Airfield"):ToCoaliton(coaliton.side.BLUE)
-- --
-- ### To Blue Coaliton -- ### To Blue Coaliton
-- --
-- ### To Red Coalition -- ### To Red Coalition
-- --
-- This would show the marker only to the Blue coaliton. -- This would show the marker only to the Blue coaliton.
-- --
-- ## For a Group -- ## For a Group
-- --
-- --
-- # Removing a Marker -- # Removing a Marker
-- --
-- --
-- # Updating a Marker -- # Updating a Marker
-- --
-- The marker text and coordinate can be updated easily as shown below. -- The marker text and coordinate can be updated easily as shown below.
-- --
-- However, note that **updateing involves to remove and recreate the marker if either text or its coordinate is changed**. -- However, note that **updateing involves to remove and recreate the marker if either text or its coordinate is changed**.
-- *This is a DCS scripting engine limitation.* -- *This is a DCS scripting engine limitation.*
-- --
-- ## Update Text -- ## Update Text
-- --
-- If you created a marker "mymarker" as shown above, you can update the dispayed test by -- If you created a marker "mymarker" as shown above, you can update the dispayed test by
-- --
-- mymarker:UpdateText("I am the new text at Batumi") -- mymarker:UpdateText("I am the new text at Batumi")
-- --
-- The update can also be delayed by, e.g. 90 seconds, using -- The update can also be delayed by, e.g. 90 seconds, using
-- --
-- mymarker:UpdateText("I am the new text at Batumi", 90) -- mymarker:UpdateText("I am the new text at Batumi", 90)
-- --
-- ## Update Coordinate -- ## Update Coordinate
-- --
-- If you created a marker "mymarker" as shown above, you can update its coordinate on the F10 map by -- If you created a marker "mymarker" as shown above, you can update its coordinate on the F10 map by
-- --
-- mymarker:UpdateCoordinate(NewCoordinate) -- mymarker:UpdateCoordinate(NewCoordinate)
-- --
-- The update can also be delayed by, e.g. 60 seconds, using -- The update can also be delayed by, e.g. 60 seconds, using
-- --
-- mymarker:UpdateCoordinate(NewCoordinate, 60) -- mymarker:UpdateCoordinate(NewCoordinate, 60)
-- --
-- # Retrieve Data -- # Retrieve Data
-- --
-- The important data as the displayed text and the coordinate of the marker can be retrieved easily. -- The important data as the displayed text and the coordinate of the marker can be retrieved easily.
-- --
-- ## Text -- ## Text
-- --
-- local text=mymarker:GetText() -- local text=mymarker:GetText()
-- env.info("Marker Text = " .. text) -- env.info("Marker Text = " .. text)
-- --
-- ## Coordinate -- ## Coordinate
-- --
-- local Coordinate=mymarker:GetCoordinate() -- local Coordinate=mymarker:GetCoordinate()
-- env.info("Marker Coordinate LL DSM = " .. Coordinate:ToStringLLDMS()) -- env.info("Marker Coordinate LL DSM = " .. Coordinate:ToStringLLDMS())
-- --
-- --
-- # FSM Events -- # FSM Events
-- --
-- Moose creates addditonal events, so called FSM event, when markers are added, changed, removed, and text or the coordianteis updated. -- Moose creates addditonal events, so called FSM event, when markers are added, changed, removed, and text or the coordianteis updated.
-- --
-- These events can be captured and used for processing via OnAfter functions as shown below. -- These events can be captured and used for processing via OnAfter functions as shown below.
-- --
-- ## Added -- ## Added
-- --
-- ## Changed -- ## Changed
-- --
-- ## Removed -- ## Removed
-- --
-- ## TextUpdate -- ## TextUpdate
-- --
-- ## CoordUpdate -- ## CoordUpdate
-- --
-- --
-- # Examples -- # Examples
-- --
-- --
-- @field #MARKER -- @field #MARKER
MARKER = { MARKER = {
ClassName = "MARKER", ClassName = "MARKER",
@ -170,29 +170,29 @@ MARKER.version="0.1.0"
--- Create a new MARKER class object. --- Create a new MARKER class object.
-- @param #MARKER self -- @param #MARKER self
-- @param Core.Point#COORDINATE Coordinate Coordinate where to place the marker. -- @param Core.Point#COORDINATE Coordinate Coordinate where to place the marker.
-- @param #string Text Text displayed on the mark panel. -- @param #string Text Text displayed on the mark panel.
-- @return #MARKER self -- @return #MARKER self
function MARKER:New(Coordinate, Text) function MARKER:New(Coordinate, Text)
-- Inherit everything from FSM class. -- Inherit everything from FSM class.
local self=BASE:Inherit(self, FSM:New()) -- #MARKER local self=BASE:Inherit(self, FSM:New()) -- #MARKER
self.coordinate=Coordinate self.coordinate=Coordinate
self.text=Text self.text=Text
-- Defaults -- Defaults
self.readonly=false self.readonly=false
self.message="" self.message=""
-- New marker ID. This is not the one of the actual marker. -- New marker ID. This is not the one of the actual marker.
_MARKERID=_MARKERID+1 _MARKERID=_MARKERID+1
self.myid=_MARKERID self.myid=_MARKERID
-- Log ID. -- Log ID.
self.lid=string.format("Marker #%d | ", self.myid) self.lid=string.format("Marker #%d | ", self.myid)
-- Start State. -- Start State.
self:SetStartState("Invisible") self:SetStartState("Invisible")
@ -201,7 +201,7 @@ function MARKER:New(Coordinate, Text)
self:AddTransition("Invisible", "Added", "Visible") -- Marker was added. self:AddTransition("Invisible", "Added", "Visible") -- Marker was added.
self:AddTransition("Visible", "Removed", "Invisible") -- Marker was removed. self:AddTransition("Visible", "Removed", "Invisible") -- Marker was removed.
self:AddTransition("*", "Changed", "*") -- Marker was changed. self:AddTransition("*", "Changed", "*") -- Marker was changed.
self:AddTransition("*", "TextUpdate", "*") -- Text updated. self:AddTransition("*", "TextUpdate", "*") -- Text updated.
self:AddTransition("*", "CoordUpdate", "*") -- Coordinates updated. self:AddTransition("*", "CoordUpdate", "*") -- Coordinates updated.
@ -304,8 +304,8 @@ function MARKER:New(Coordinate, Text)
self:HandleEvent(EVENTS.MarkAdded) self:HandleEvent(EVENTS.MarkAdded)
self:HandleEvent(EVENTS.MarkRemoved) self:HandleEvent(EVENTS.MarkRemoved)
self:HandleEvent(EVENTS.MarkChange) self:HandleEvent(EVENTS.MarkChange)
return self return self
end end
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
@ -318,7 +318,7 @@ end
function MARKER:ReadOnly() function MARKER:ReadOnly()
self.readonly=true self.readonly=true
return self return self
end end
@ -329,7 +329,7 @@ end
function MARKER:Message(Text) function MARKER:Message(Text)
self.message=Text or "" self.message=Text or ""
return self return self
end end
@ -349,14 +349,14 @@ function MARKER:ToAll(Delay)
self.togroup=nil self.togroup=nil
self.groupname=nil self.groupname=nil
self.groupid=nil self.groupid=nil
-- First remove an existing mark. -- First remove an existing mark.
if self.shown then if self.shown then
self:Remove() self:Remove()
end end
self.mid=UTILS.GetMarkID() self.mid=UTILS.GetMarkID()
-- Call DCS function. -- Call DCS function.
trigger.action.markToAll(self.mid, self.text, self.coordinate:GetVec3(), self.readonly, self.message) trigger.action.markToAll(self.mid, self.text, self.coordinate:GetVec3(), self.readonly, self.message)
@ -377,25 +377,25 @@ function MARKER:ToCoalition(Coalition, Delay)
else else
self.coalition=Coalition self.coalition=Coalition
self.tocoaliton=true self.tocoaliton=true
self.toall=false self.toall=false
self.togroup=false self.togroup=false
self.groupname=nil self.groupname=nil
self.groupid=nil self.groupid=nil
-- First remove an existing mark. -- First remove an existing mark.
if self.shown then if self.shown then
self:Remove() self:Remove()
end end
self.mid=UTILS.GetMarkID() self.mid=UTILS.GetMarkID()
-- Call DCS function. -- Call DCS function.
trigger.action.markToCoalition(self.mid, self.text, self.coordinate:GetVec3(), self.coalition, self.readonly, self.message) trigger.action.markToCoalition(self.mid, self.text, self.coordinate:GetVec3(), self.coalition, self.readonly, self.message)
end end
return self return self
end end
@ -440,36 +440,36 @@ function MARKER:ToGroup(Group, Delay)
-- Check if group exists. -- Check if group exists.
if Group and Group:IsAlive()~=nil then if Group and Group:IsAlive()~=nil then
self.groupid=Group:GetID() self.groupid=Group:GetID()
if self.groupid then if self.groupid then
self.groupname=Group:GetName() self.groupname=Group:GetName()
self.togroup=true self.togroup=true
self.tocoaliton=nil self.tocoaliton=nil
self.coalition=nil self.coalition=nil
self.toall=nil self.toall=nil
-- First remove an existing mark. -- First remove an existing mark.
if self.shown then if self.shown then
self:Remove() self:Remove()
end end
self.mid=UTILS.GetMarkID() self.mid=UTILS.GetMarkID()
-- Call DCS function. -- Call DCS function.
trigger.action.markToGroup(self.mid, self.text, self.coordinate:GetVec3(), self.groupid, self.readonly, self.message) trigger.action.markToGroup(self.mid, self.text, self.coordinate:GetVec3(), self.groupid, self.readonly, self.message)
end end
else else
--TODO: Warning! --TODO: Warning!
end end
end end
return self return self
end end
@ -482,14 +482,14 @@ function MARKER:UpdateText(Text, Delay)
if Delay and Delay>0 then if Delay and Delay>0 then
self:ScheduleOnce(Delay, MARKER.UpdateText, self, Text) self:ScheduleOnce(Delay, MARKER.UpdateText, self, Text)
else else
self.text=tostring(Text) self.text=tostring(Text)
self:Refresh() self:Refresh()
self:TextUpdate(tostring(Text)) self:TextUpdate(tostring(Text))
end end
return self return self
@ -504,14 +504,14 @@ function MARKER:UpdateCoordinate(Coordinate, Delay)
if Delay and Delay>0 then if Delay and Delay>0 then
self:ScheduleOnce(Delay, MARKER.UpdateCoordinate, self, Coordinate) self:ScheduleOnce(Delay, MARKER.UpdateCoordinate, self, Coordinate)
else else
self.coordinate=Coordinate self.coordinate=Coordinate
self:Refresh() self:Refresh()
self:CoordUpdate(Coordinate) self:CoordUpdate(Coordinate)
end end
return self return self
@ -525,26 +525,26 @@ function MARKER:Refresh(Delay)
if Delay and Delay>0 then if Delay and Delay>0 then
self:ScheduleOnce(Delay, MARKER.Refresh, self) self:ScheduleOnce(Delay, MARKER.Refresh, self)
else else
if self.toall then if self.toall then
self:ToAll() self:ToAll()
elseif self.tocoaliton then elseif self.tocoaliton then
self:ToCoalition(self.coalition) self:ToCoalition(self.coalition)
elseif self.togroup then elseif self.togroup then
local group=GROUP:FindByName(self.groupname) local group=GROUP:FindByName(self.groupname)
self:ToGroup(group) self:ToGroup(group)
else else
self:E(self.lid.."ERROR: unknown To in :Refresh()!") self:E(self.lid.."ERROR: unknown To in :Refresh()!")
end end
end end
return self return self
@ -564,9 +564,9 @@ function MARKER:Remove(Delay)
-- Call DCS function. -- Call DCS function.
trigger.action.removeMark(self.mid) trigger.action.removeMark(self.mid)
end end
end end
return self return self
@ -605,7 +605,7 @@ end
--- Check if marker is currently invisible on the F10 map. --- Check if marker is currently invisible on the F10 map.
-- @param #MARKER self -- @param #MARKER self
-- @return -- @return
function MARKER:IsInvisible() function MARKER:IsInvisible()
return self:Is("Invisible") return self:Is("Invisible")
end end
@ -620,17 +620,17 @@ end
function MARKER:OnEventMarkAdded(EventData) function MARKER:OnEventMarkAdded(EventData)
if EventData and EventData.MarkID then if EventData and EventData.MarkID then
local MarkID=EventData.MarkID local MarkID=EventData.MarkID
self:T3(self.lid..string.format("Captured event MarkAdded for Mark ID=%s", tostring(MarkID))) self:T3(self.lid..string.format("Captured event MarkAdded for Mark ID=%s", tostring(MarkID)))
if MarkID==self.mid then if MarkID==self.mid then
self.shown=true self.shown=true
self:Added(EventData) self:Added(EventData)
end end
end end
@ -643,21 +643,21 @@ end
function MARKER:OnEventMarkRemoved(EventData) function MARKER:OnEventMarkRemoved(EventData)
if EventData and EventData.MarkID then if EventData and EventData.MarkID then
local MarkID=EventData.MarkID local MarkID=EventData.MarkID
self:T3(self.lid..string.format("Captured event MarkAdded for Mark ID=%s", tostring(MarkID))) self:T3(self.lid..string.format("Captured event MarkAdded for Mark ID=%s", tostring(MarkID)))
if MarkID==self.mid then if MarkID==self.mid then
self.shown=false self.shown=false
self:Removed(EventData) self:Removed(EventData)
end end
end end
end end
--- Event function when a MARKER changed. --- Event function when a MARKER changed.
@ -666,17 +666,17 @@ end
function MARKER:OnEventMarkChange(EventData) function MARKER:OnEventMarkChange(EventData)
if EventData and EventData.MarkID then if EventData and EventData.MarkID then
local MarkID=EventData.MarkID local MarkID=EventData.MarkID
self:T3(self.lid..string.format("Captured event MarkChange for Mark ID=%s", tostring(MarkID))) self:T3(self.lid..string.format("Captured event MarkChange for Mark ID=%s", tostring(MarkID)))
if MarkID==self.mid then if MarkID==self.mid then
self:Changed(EventData) self:Changed(EventData)
self:TextChanged(tostring(EventData.MarkText)) self:TextChanged(tostring(EventData.MarkText))
end end
end end
@ -696,7 +696,7 @@ end
function MARKER:onafterAdded(From, Event, To, EventData) function MARKER:onafterAdded(From, Event, To, EventData)
-- Debug info. -- Debug info.
local text=string.format("Captured event MarkAdded for myself:\n") local text=string.format("Captured event MarkAdded for myself:\n")
text=text..string.format("Marker ID = %s\n", tostring(EventData.MarkID)) text=text..string.format("Marker ID = %s\n", tostring(EventData.MarkID))
text=text..string.format("Coalition = %s\n", tostring(EventData.MarkCoalition)) text=text..string.format("Coalition = %s\n", tostring(EventData.MarkCoalition))
text=text..string.format("Group ID = %s\n", tostring(EventData.MarkGroupID)) text=text..string.format("Group ID = %s\n", tostring(EventData.MarkGroupID))
@ -716,7 +716,7 @@ end
function MARKER:onafterRemoved(From, Event, To, EventData) function MARKER:onafterRemoved(From, Event, To, EventData)
-- Debug info. -- Debug info.
local text=string.format("Captured event MarkRemoved for myself:\n") local text=string.format("Captured event MarkRemoved for myself:\n")
text=text..string.format("Marker ID = %s\n", tostring(EventData.MarkID)) text=text..string.format("Marker ID = %s\n", tostring(EventData.MarkID))
text=text..string.format("Coalition = %s\n", tostring(EventData.MarkCoalition)) text=text..string.format("Coalition = %s\n", tostring(EventData.MarkCoalition))
text=text..string.format("Group ID = %s\n", tostring(EventData.MarkGroupID)) text=text..string.format("Group ID = %s\n", tostring(EventData.MarkGroupID))
@ -736,7 +736,7 @@ end
function MARKER:onafterChanged(From, Event, To, EventData) function MARKER:onafterChanged(From, Event, To, EventData)
-- Debug info. -- Debug info.
local text=string.format("Captured event MarkChange for myself:\n") local text=string.format("Captured event MarkChange for myself:\n")
text=text..string.format("Marker ID = %s\n", tostring(EventData.MarkID)) text=text..string.format("Marker ID = %s\n", tostring(EventData.MarkID))
text=text..string.format("Coalition = %s\n", tostring(EventData.MarkCoalition)) text=text..string.format("Coalition = %s\n", tostring(EventData.MarkCoalition))
text=text..string.format("Group ID = %s\n", tostring(EventData.MarkGroupID)) text=text..string.format("Group ID = %s\n", tostring(EventData.MarkGroupID))
@ -755,7 +755,7 @@ end
-- @param #string Text The updated text, displayed in the mark panel. -- @param #string Text The updated text, displayed in the mark panel.
function MARKER:onafterTextUpdate(From, Event, To, Text) function MARKER:onafterTextUpdate(From, Event, To, Text)
self:I(self.lid..string.format("New Marker Text:\n%s", Text)) self:T(self.lid..string.format("New Marker Text:\n%s", Text))
end end
@ -767,8 +767,8 @@ end
-- @param Core.Point#COORDINATE Coordinate The updated coordinates. -- @param Core.Point#COORDINATE Coordinate The updated coordinates.
function MARKER:onafterCoordUpdate(From, Event, To, Coordinate) function MARKER:onafterCoordUpdate(From, Event, To, Coordinate)
self:I(self.lid..string.format("New Marker Coordinate in LL DMS: %s", Coordinate:ToStringLLDMS())) self:T(self.lid..string.format("New Marker Coordinate in LL DMS: %s", Coordinate:ToStringLLDMS()))
end end
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

View File

@ -15,6 +15,8 @@
-- @extends Wrapper.Identifiable#IDENTIFIABLE -- @extends Wrapper.Identifiable#IDENTIFIABLE
--- @type POSITIONABLE --- @type POSITIONABLE
-- @field Core.Point#COORDINATE coordinate Coordinate object.
-- @field Core.Point#POINT_VEC3 pointvec3 Point Vec3 object.
-- @extends Wrapper.Identifiable#IDENTIFIABLE -- @extends Wrapper.Identifiable#IDENTIFIABLE
@ -45,6 +47,8 @@
POSITIONABLE = { POSITIONABLE = {
ClassName = "POSITIONABLE", ClassName = "POSITIONABLE",
PositionableName = "", PositionableName = "",
coordinate = nil,
pointvec3 = nil,
} }
--- @field #POSITIONABLE.__ --- @field #POSITIONABLE.__
@ -121,10 +125,17 @@ function POSITIONABLE:Destroy( GenerateEvent )
return nil return nil
end end
--- Returns the DCS object. Polymorphic for other classes like UNIT, STATIC, GROUP, AIRBASE.
-- @param #POSITIONABLE self
-- @return DCS#Object The DCS object.
function POSITIONABLE:GetDCSObject()
return nil
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. --- 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. -- Coordinates are dependent on the position of the maps origin.
-- @param Wrapper.Positionable#POSITIONABLE self -- @param Wrapper.Positionable#POSITIONABLE self
-- @return DCS#Position Table consisting of the point and orientation tables. -- @return DCS#Position3 Table consisting of the point and orientation tables.
function POSITIONABLE:GetPosition() function POSITIONABLE:GetPosition()
self:F2( self.PositionableName ) self:F2( self.PositionableName )
@ -215,27 +226,44 @@ function POSITIONABLE:GetPositionVec3()
return nil return nil
end end
--- Returns the @{DCS#Vec2} vector indicating the point in 2D of the POSITIONABLE within the mission. --- Returns the @{DCS#Vec3} vector indicating the 3D vector of the POSITIONABLE within the mission.
-- @param Wrapper.Positionable#POSITIONABLE self -- @param Wrapper.Positionable#POSITIONABLE self
-- @return DCS#Vec2 The 2D point vector of the POSITIONABLE. -- @return DCS#Vec3 The 3D point vector of the POSITIONABLE or `nil` if it is not existing or alive.
-- @return #nil The POSITIONABLE is not existing or alive. function POSITIONABLE:GetVec3()
function POSITIONABLE:GetVec2()
self:F2( self.PositionableName )
local DCSPositionable = self:GetDCSObject() local DCSPositionable = self:GetDCSObject()
if DCSPositionable then if DCSPositionable then
local PositionableVec3 = DCSPositionable:getPosition().p
local PositionableVec2 = {}
PositionableVec2.x = PositionableVec3.x
PositionableVec2.y = PositionableVec3.z
self:T2( PositionableVec2 ) local vec3=DCSPositionable:getPoint()
return PositionableVec2
if vec3 then
return vec3
else
self:E("ERROR: Cannot get vec3!")
end
end end
BASE:E( { "Cannot GetVec2", Positionable = self, Alive = self:IsAlive() } ) -- ERROR!
self:E( { "Cannot GetVec3", Positionable = self, Alive = self:IsAlive() } )
return nil
end
--- Returns the @{DCS#Vec2} vector indicating the point in 2D of the POSITIONABLE within the mission.
-- @param Wrapper.Positionable#POSITIONABLE self
-- @return DCS#Vec2 The 2D point vector of the POSITIONABLE or #nil if it is not existing or alive.
function POSITIONABLE:GetVec2()
local DCSPositionable = self:GetDCSObject()
if DCSPositionable then
local Vec3=DCSPositionable:getPoint() --DCS#Vec3
return {x=Vec3.x, y=Vec3.z}
end
self:E( { "Cannot GetVec2", Positionable = self, Alive = self:IsAlive() } )
return nil return nil
end end
@ -258,7 +286,7 @@ function POSITIONABLE:GetPointVec2()
return PositionablePointVec2 return PositionablePointVec2
end end
BASE:E( { "Cannot GetPointVec2", Positionable = self, Alive = self:IsAlive() } ) self:E( { "Cannot GetPointVec2", Positionable = self, Alive = self:IsAlive() } )
return nil return nil
end end
@ -268,17 +296,29 @@ end
-- @return Core.Point#POINT_VEC3 The 3D point vector of the POSITIONABLE. -- @return Core.Point#POINT_VEC3 The 3D point vector of the POSITIONABLE.
-- @return #nil The POSITIONABLE is not existing or alive. -- @return #nil The POSITIONABLE is not existing or alive.
function POSITIONABLE:GetPointVec3() function POSITIONABLE:GetPointVec3()
self:F2( self.PositionableName )
local DCSPositionable = self:GetDCSObject() local DCSPositionable = self:GetDCSObject()
if DCSPositionable then if DCSPositionable then
local PositionableVec3 = self:GetPositionVec3()
local PositionablePointVec3 = POINT_VEC3:NewFromVec3( PositionableVec3 )
self:T2( PositionablePointVec3 ) -- Get 3D vector.
return PositionablePointVec3 local PositionableVec3 = self:GetPositionVec3()
if false and self.pointvec3 then
-- Update vector.
self.pointvec3.x=PositionableVec3.x
self.pointvec3.y=PositionableVec3.y
self.pointvec3.z=PositionableVec3.z
else
-- Create a new POINT_VEC3 object.
self.pointvec3=POINT_VEC3:NewFromVec3(PositionableVec3)
end
return self.pointvec3
end end
BASE:E( { "Cannot GetPointVec3", Positionable = self, Alive = self:IsAlive() } ) BASE:E( { "Cannot GetPointVec3", Positionable = self, Alive = self:IsAlive() } )
@ -289,27 +329,62 @@ end
--- Returns a COORDINATE object indicating the point in 3D of the POSITIONABLE within the mission. --- Returns a COORDINATE object indicating the point in 3D of the POSITIONABLE within the mission.
-- @param Wrapper.Positionable#POSITIONABLE self -- @param Wrapper.Positionable#POSITIONABLE self
-- @return Core.Point#COORDINATE The COORDINATE of the POSITIONABLE. -- @return Core.Point#COORDINATE The COORDINATE of the POSITIONABLE.
function POSITIONABLE:GetCoordinate() function POSITIONABLE:GetCoord()
self:F2( self.PositionableName )
-- Get DCS object.
local DCSPositionable = self:GetDCSObject() local DCSPositionable = self:GetDCSObject()
if DCSPositionable then if DCSPositionable then
local PositionableVec3 = self:GetPositionVec3()
local PositionableCoordinate = COORDINATE:NewFromVec3( PositionableVec3 )
PositionableCoordinate:SetHeading( self:GetHeading() )
PositionableCoordinate:SetVelocity( self:GetVelocityMPS() )
self:T2( PositionableCoordinate ) -- Get the current position.
return PositionableCoordinate local Vec3 = self:GetVec3()
if self.coordinate then
-- Update vector.
self.coordinate.x=Vec3.x
self.coordinate.y=Vec3.y
self.coordinate.z=Vec3.z
else
-- New COORDINATE.
self.coordinate=COORDINATE:NewFromVec3(Vec3)
end
return self.coordinate
end end
-- Error message.
BASE:E( { "Cannot GetCoordinate", Positionable = self, Alive = self:IsAlive() } ) BASE:E( { "Cannot GetCoordinate", Positionable = self, Alive = self:IsAlive() } )
return nil return nil
end end
--- Returns a COORDINATE object indicating the point in 3D of the POSITIONABLE within the mission.
-- @param Wrapper.Positionable#POSITIONABLE self
-- @return Core.Point#COORDINATE The COORDINATE of the POSITIONABLE.
function POSITIONABLE:GetCoordinate()
-- Get DCS object.
local DCSPositionable = self:GetDCSObject()
if DCSPositionable then
-- Get the current position.
local PositionableVec3 = self:GetVec3()
-- Return a new coordiante object.
return COORDINATE:NewFromVec3(PositionableVec3)
end
-- Error message.
self:E( { "Cannot GetCoordinate", Positionable = self, Alive = self:IsAlive() } )
return nil
end
--- Returns a COORDINATE object, which is offset with respect to the orientation of the POSITIONABLE. --- Returns a COORDINATE object, which is offset with respect to the orientation of the POSITIONABLE.
-- @param Wrapper.Positionable#POSITIONABLE self -- @param Wrapper.Positionable#POSITIONABLE self
-- @param #number x Offset in the direction "the nose" of the unit is pointing in meters. Default 0 m. -- @param #number x Offset in the direction "the nose" of the unit is pointing in meters. Default 0 m.
@ -384,26 +459,6 @@ function POSITIONABLE:GetRandomVec3( Radius )
return nil return nil
end end
--- Returns the @{DCS#Vec3} vector indicating the 3D vector of the POSITIONABLE within the mission.
-- @param Wrapper.Positionable#POSITIONABLE self
-- @return DCS#Vec3 The 3D point vector of the POSITIONABLE.
-- @return #nil The POSITIONABLE is not existing or alive.
function POSITIONABLE:GetVec3()
self:F2( self.PositionableName )
local DCSPositionable = self:GetDCSObject()
if DCSPositionable then
local PositionableVec3 = DCSPositionable:getPosition().p
self:T3( PositionableVec3 )
return PositionableVec3
end
BASE:E( { "Cannot GetVec3", Positionable = self, Alive = self:IsAlive() } )
return nil
end
--- Get the bounding box of the underlying POSITIONABLE DCS Object. --- Get the bounding box of the underlying POSITIONABLE DCS Object.
-- @param #POSITIONABLE self -- @param #POSITIONABLE self
@ -1533,7 +1588,7 @@ end
--- Returns true if the unit is within a @{Zone}. --- Returns true if the unit is within a @{Zone}.
-- @param #STPOSITIONABLEATIC self -- @param #POSITIONABLE self
-- @param Core.Zone#ZONE_BASE Zone The zone to test. -- @param Core.Zone#ZONE_BASE Zone The zone to test.
-- @return #boolean Returns true if the unit is within the @{Core.Zone#ZONE_BASE} -- @return #boolean Returns true if the unit is within the @{Core.Zone#ZONE_BASE}
function POSITIONABLE:IsInZone( Zone ) function POSITIONABLE:IsInZone( Zone )

View File

@ -22,6 +22,7 @@ Core/Fsm.lua
Core/Radio.lua Core/Radio.lua
Core/Spawn.lua Core/Spawn.lua
Core/SpawnStatic.lua Core/SpawnStatic.lua
Core/Timer.lua
Core/Goal.lua Core/Goal.lua
Core/Spot.lua Core/Spot.lua