mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2026-08-12 16:57:50 +00:00
Merge branch 'FF/Ops' into FF/OpsDev
This commit is contained in:
@@ -1475,7 +1475,7 @@ function EVENT:onEvent( Event )
|
||||
-- SCENERY
|
||||
---
|
||||
Event.TgtDCSUnit = Event.target
|
||||
Event.TgtDCSUnitName = Event.TgtDCSUnit.getName and Event.TgtDCSUnit.getName() or nil
|
||||
Event.TgtDCSUnitName = Event.TgtDCSUnit.getName and Event.TgtDCSUnit:getName() or nil
|
||||
if Event.TgtDCSUnitName~=nil then
|
||||
Event.TgtUnitName = Event.TgtDCSUnitName
|
||||
Event.TgtUnit = SCENERY:Register( Event.TgtDCSUnitName, Event.target )
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
-- ## Features:
|
||||
--
|
||||
-- * Provides a COORDINATE class, which allows to manage points in 3D space and perform various operations on it.
|
||||
-- * Provides a POINT\_VEC2 class, which is derived from COORDINATE, and allows to manage points in 3D space, but from a Lat/Lon and Altitude perspective.
|
||||
-- * Provides a POINT\_VEC3 class, which is derived from COORDINATE, and allows to manage points in 3D space, but from a X, Z and Y vector perspective.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
@@ -3892,171 +3890,3 @@ do -- COORDINATE
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
do
|
||||
|
||||
--- The POINT_VEC3 class
|
||||
-- @type POINT_VEC3
|
||||
-- @field #number x The x coordinate in 3D space.
|
||||
-- @field #number y The y coordinate in 3D space.
|
||||
-- @field #number z The z COORDINATE in 3D space.
|
||||
-- @field Utilities.Utils#SMOKECOLOR SmokeColor
|
||||
-- @field Utilities.Utils#FLARECOLOR FlareColor
|
||||
-- @field #POINT_VEC3.RoutePointAltType RoutePointAltType
|
||||
-- @field #POINT_VEC3.RoutePointType RoutePointType
|
||||
-- @field #POINT_VEC3.RoutePointAction RoutePointAction
|
||||
-- @extends #COORDINATE
|
||||
|
||||
|
||||
--- Defines a 3D point in the simulator and with its methods, you can use or manipulate the point in 3D space.
|
||||
--
|
||||
-- **DEPRECATED - PLEASE USE COORDINATE!**
|
||||
--
|
||||
-- **Important Note:** Most of the functions in this section were taken from MIST, and reworked to OO concepts.
|
||||
-- In order to keep the credibility of the the author,
|
||||
-- I want to emphasize that the formulas embedded in the MIST framework were created by Grimes or previous authors,
|
||||
-- who you can find on the Eagle Dynamics Forums.
|
||||
--
|
||||
--
|
||||
-- ## POINT_VEC3 constructor
|
||||
--
|
||||
-- A new POINT_VEC3 object can be created with:
|
||||
--
|
||||
-- * @{#POINT_VEC3.New}(): a 3D point.
|
||||
-- * @{#POINT_VEC3.NewFromVec3}(): a 3D point created from a @{DCS#Vec3}.
|
||||
--
|
||||
--
|
||||
-- ## Manupulate the X, Y, Z coordinates of the POINT_VEC3
|
||||
--
|
||||
-- A POINT_VEC3 class works in 3D space. It contains internally an X, Y, Z coordinate.
|
||||
-- Methods exist to manupulate these coordinates.
|
||||
--
|
||||
-- The current X, Y, Z axis can be retrieved with the methods @{#POINT_VEC3.GetX}(), @{#POINT_VEC3.GetY}(), @{#POINT_VEC3.GetZ}() respectively.
|
||||
-- The methods @{#POINT_VEC3.SetX}(), @{#POINT_VEC3.SetY}(), @{#POINT_VEC3.SetZ}() change the respective axis with a new value.
|
||||
-- The current axis values can be changed by using the methods @{#POINT_VEC3.AddX}(), @{#POINT_VEC3.AddY}(), @{#POINT_VEC3.AddZ}()
|
||||
-- to add or substract a value from the current respective axis value.
|
||||
-- Note that the Set and Add methods return the current POINT_VEC3 object, so these manipulation methods can be chained... For example:
|
||||
--
|
||||
-- local Vec3 = PointVec3:AddX( 100 ):AddZ( 150 ):GetVec3()
|
||||
--
|
||||
--
|
||||
-- ## 3D calculation methods
|
||||
--
|
||||
-- Various calculation methods exist to use or manipulate 3D space. Find below a short description of each method:
|
||||
--
|
||||
--
|
||||
-- ## Point Randomization
|
||||
--
|
||||
-- Various methods exist to calculate random locations around a given 3D point.
|
||||
--
|
||||
-- * @{#POINT_VEC3.GetRandomPointVec3InRadius}(): Provides a random 3D point around the current 3D point, in the given inner to outer band.
|
||||
--
|
||||
--
|
||||
-- @field #POINT_VEC3
|
||||
POINT_VEC3 = {
|
||||
ClassName = "POINT_VEC3",
|
||||
Metric = true,
|
||||
RoutePointAltType = {
|
||||
BARO = "BARO",
|
||||
},
|
||||
RoutePointType = {
|
||||
TakeOffParking = "TakeOffParking",
|
||||
TurningPoint = "Turning Point",
|
||||
},
|
||||
RoutePointAction = {
|
||||
FromParkingArea = "From Parking Area",
|
||||
TurningPoint = "Turning Point",
|
||||
},
|
||||
}
|
||||
|
||||
--- RoutePoint AltTypes
|
||||
-- @type POINT_VEC3.RoutePointAltType
|
||||
-- @field BARO "BARO"
|
||||
|
||||
--- RoutePoint Types
|
||||
-- @type POINT_VEC3.RoutePointType
|
||||
-- @field TakeOffParking "TakeOffParking"
|
||||
-- @field TurningPoint "Turning Point"
|
||||
|
||||
--- RoutePoint Actions
|
||||
-- @type POINT_VEC3.RoutePointAction
|
||||
-- @field FromParkingArea "From Parking Area"
|
||||
-- @field TurningPoint "Turning Point"
|
||||
|
||||
-- Constructor.
|
||||
|
||||
--- Create a new POINT_VEC3 object.
|
||||
-- @param #POINT_VEC3 self
|
||||
-- @param DCS#Distance x The x coordinate of the Vec3 point, pointing to the North.
|
||||
-- @param DCS#Distance y The y coordinate of the Vec3 point, pointing Upwards.
|
||||
-- @param DCS#Distance z The z coordinate of the Vec3 point, pointing to the Right.
|
||||
-- @return Core.Point#POINT_VEC3
|
||||
function POINT_VEC3:New( x, y, z )
|
||||
|
||||
local self = BASE:Inherit( self, COORDINATE:New( x, y, z ) ) -- Core.Point#POINT_VEC3
|
||||
self:F2( self )
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
do
|
||||
|
||||
--- @type POINT_VEC2
|
||||
-- @field DCS#Distance x The x coordinate in meters.
|
||||
-- @field DCS#Distance y the y coordinate in meters.
|
||||
-- @extends Core.Point#COORDINATE
|
||||
|
||||
--- Defines a 2D point in the simulator. The height coordinate (if needed) will be the land height + an optional added height specified.
|
||||
--
|
||||
-- **DEPRECATED - PLEASE USE COORDINATE!**
|
||||
--
|
||||
-- ## POINT_VEC2 constructor
|
||||
--
|
||||
-- A new POINT_VEC2 instance can be created with:
|
||||
--
|
||||
-- * @{Core.Point#POINT_VEC2.New}(): a 2D point, taking an additional height parameter.
|
||||
-- * @{Core.Point#POINT_VEC2.NewFromVec2}(): a 2D point created from a @{DCS#Vec2}.
|
||||
--
|
||||
-- ## Manupulate the X, Altitude, Y coordinates of the 2D point
|
||||
--
|
||||
-- A POINT_VEC2 class works in 2D space, with an altitude setting. It contains internally an X, Altitude, Y coordinate.
|
||||
-- Methods exist to manupulate these coordinates.
|
||||
--
|
||||
-- The current X, Altitude, Y axis can be retrieved with the methods @{#POINT_VEC2.GetX}(), @{#POINT_VEC2.GetAlt}(), @{#POINT_VEC2.GetY}() respectively.
|
||||
-- The methods @{#POINT_VEC2.SetX}(), @{#POINT_VEC2.SetAlt}(), @{#POINT_VEC2.SetY}() change the respective axis with a new value.
|
||||
-- The current Lat(itude), Alt(itude), Lon(gitude) values can also be retrieved with the methods @{#POINT_VEC2.GetLat}(), @{#POINT_VEC2.GetAlt}(), @{#POINT_VEC2.GetLon}() respectively.
|
||||
-- The current axis values can be changed by using the methods @{#POINT_VEC2.AddX}(), @{#POINT_VEC2.AddAlt}(), @{#POINT_VEC2.AddY}()
|
||||
-- to add or substract a value from the current respective axis value.
|
||||
-- Note that the Set and Add methods return the current POINT_VEC2 object, so these manipulation methods can be chained... For example:
|
||||
--
|
||||
-- local Vec2 = PointVec2:AddX( 100 ):AddY( 2000 ):GetVec2()
|
||||
--
|
||||
-- @field #POINT_VEC2
|
||||
POINT_VEC2 = {
|
||||
ClassName = "POINT_VEC2",
|
||||
}
|
||||
|
||||
|
||||
|
||||
--- POINT_VEC2 constructor.
|
||||
-- @param #POINT_VEC2 self
|
||||
-- @param DCS#Distance x The x coordinate of the Vec3 point, pointing to the North.
|
||||
-- @param DCS#Distance y The y coordinate of the Vec3 point, pointing to the Right.
|
||||
-- @param DCS#Distance LandHeightAdd (optional) The default height if required to be evaluated will be the land height of the x, y coordinate. You can specify an extra height to be added to the land height.
|
||||
-- @return Core.Point#POINT_VEC2
|
||||
function POINT_VEC2:New( x, y, LandHeightAdd )
|
||||
|
||||
local LandHeight = land.getHeight( { ["x"] = x, ["y"] = y } )
|
||||
|
||||
LandHeightAdd = LandHeightAdd or 0
|
||||
LandHeight = LandHeight + LandHeightAdd
|
||||
|
||||
local self = BASE:Inherit( self, COORDINATE:New( x, LandHeight, y ) ) -- Core.Point#POINT_VEC2
|
||||
self:F2( self )
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -945,7 +945,8 @@ do -- SET_BASE
|
||||
function SET_BASE:IsInSet(Object)
|
||||
--self:F3(Object)
|
||||
local outcome = false
|
||||
local name = Object:GetName()
|
||||
if Object == nil then return false end
|
||||
local name = (Object ~= nil and Object.GetName) and Object:GetName() or "none"
|
||||
--self:I("SET_BASE: Objectname = "..name)
|
||||
self:ForEach(
|
||||
function(object)
|
||||
|
||||
@@ -1179,7 +1179,7 @@ function ZONE_RADIUS:Scan( ObjectCategories, UnitCategories )
|
||||
self.ScanData.SceneryTable = {}
|
||||
self.ScanData.Units = {}
|
||||
|
||||
local ZoneCoord = self:GetCoordinate()
|
||||
local ZoneCoord = self:GetCoordinate():SetAlt()
|
||||
local ZoneRadius = self:GetRadius()
|
||||
|
||||
--self:F({ZoneCoord = ZoneCoord, ZoneRadius = ZoneRadius, ZoneCoordLL = ZoneCoord:ToStringLLDMS()})
|
||||
|
||||
@@ -0,0 +1,999 @@
|
||||
--- **Functional** - Build large airborne formations of aircraft.
|
||||
--
|
||||
-- **Features:**
|
||||
--
|
||||
-- * Build in-air formations consisting of more than 40 aircraft as one group.
|
||||
-- * Build different formation types.
|
||||
-- * Assign a group leader that will guide the large formation path.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ## Additional Material:
|
||||
--
|
||||
-- * **Demo Missions:** [GitHub](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AI/FORMATION)
|
||||
-- * **Guides:** None
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **FlightControl**
|
||||
-- ### Contributions: **Applevangelist** (refactor)
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module Functional.FORMATION
|
||||
-- @image AI_Large_Formations.JPG
|
||||
|
||||
--- FORMATION class
|
||||
-- @type FORMATION
|
||||
-- @extends Core.Fsm#FSM_SET
|
||||
-- @field Wrapper.Unit#UNIT FollowUnit
|
||||
-- @field Core.Set#SET_GROUP FollowGroupSet
|
||||
-- @field #string FollowName
|
||||
-- @field Core.Scheduler#SCHEDULER FollowScheduler The instance of the SCHEDULER class.
|
||||
-- @field #number FollowDistance The current follow distance.
|
||||
-- @field DCS#AI.Option.Air.val.ROE OptionROE Which ROE is set to the FollowGroup.
|
||||
-- @field DCS#AI.Option.Air.val.REACTION_ON_THREAT OptionReactionOnThreat Which REACTION_ON_THREAT is set to the FollowGroup.
|
||||
-- @field #number dtFollow Time step between position updates.
|
||||
|
||||
|
||||
--- Build (large) formations, make AI follow a @{Wrapper.Client#CLIENT} (player) leader or a @{Wrapper.Unit#UNIT} (AI) leader.
|
||||
--
|
||||
-- FORMATION makes AI @{Wrapper.Group#GROUP}s fly in formation of various compositions.
|
||||
-- The FORMATION class models formations in a different manner than the internal DCS formation logic!!!
|
||||
-- The purpose of the class is to:
|
||||
--
|
||||
-- * Make formation building a process that can be managed while in flight, rather than a task.
|
||||
-- * Human players can guide formations, consisting of larget planes.
|
||||
-- * Build large formations (like a large bomber field).
|
||||
-- * Form formations that DCS does not support off-the-shelve.
|
||||
--
|
||||
-- A few remarks:
|
||||
--
|
||||
-- * Depending on the type of plane, the change in direction by the leader may result in the formation getting disentangled while in flight and needs to be rebuild.
|
||||
-- * Formations are vulnerable to collissions, but is depending on the type of plane, the distance between the planes and the speed and angle executed by the leader.
|
||||
-- * Formations may take a while to build up.
|
||||
--
|
||||
-- As a result, the FORMATION is not perfect, but is very useful to:
|
||||
--
|
||||
-- * Model large formations when flying straight line. You can build close formations when doing this.
|
||||
-- * Make humans guide a large formation, when the planes are wide from each other.
|
||||
--
|
||||
-- ## FORMATION construction
|
||||
--
|
||||
-- Create a new SPAWN object with the @{#FORMATION.New} method:
|
||||
--
|
||||
-- * @{#FORMATION.New}(): Creates a new FORMATION object from a @{Wrapper.Group#GROUP} for a @{Wrapper.Client#CLIENT} or a @{Wrapper.Unit#UNIT}, with an optional briefing text.
|
||||
--
|
||||
-- ## Formation methods
|
||||
--
|
||||
-- The following methods can be used to set or change the formation:
|
||||
--
|
||||
-- * @{#FORMATION.FormationLine}(): Form a line formation (core formation function).
|
||||
-- * @{#FORMATION.FormationTrail}(): Form a trail formation.
|
||||
-- * @{#FORMATION.FormationLeftLine}(): Form a left line formation.
|
||||
-- * @{#FORMATION.FormationRightLine}(): Form a right line formation.
|
||||
-- * @{#FORMATION.FormationRightWing}(): Form a right wing formation.
|
||||
-- * @{#FORMATION.FormationLeftWing}(): Form a left wing formation.
|
||||
-- * @{#FORMATION.FormationCenterWing}(): Form a center wing formation.
|
||||
-- * @{#FORMATION.FormationCenterVic}(): Form a Vic formation (same as CenterWing).
|
||||
-- * @{#FORMATION.FormationCenterBoxed}(): Form a center boxed formation.
|
||||
--
|
||||
-- ## Randomization
|
||||
--
|
||||
-- Use the method @{FORMATION#FORMATION.SetFlightRandomization}() to simulate the formation flying errors that pilots make while in formation. Is a range set in meters.
|
||||
--
|
||||
-- @usage
|
||||
-- local FollowGroupSet = SET_GROUP:New():FilterCategories("plane"):FilterCoalitions("blue"):FilterPrefixes("Follow"):FilterStart()
|
||||
-- local LeaderUnit = UNIT:FindByName( "Leader" )
|
||||
-- local LargeFormation = FORMATION:New( LeaderUnit, FollowGroupSet, "Center Wing Formation", "Briefing" )
|
||||
-- LargeFormation:FormationCenterWing( 500, 50, 0, 250, 250 )
|
||||
-- LargeFormation:__Start( 1 )
|
||||
--
|
||||
-- @field #FORMATION
|
||||
FORMATION = {
|
||||
ClassName = "FORMATION",
|
||||
FollowName = nil, -- The Follow Name
|
||||
FollowUnit = nil,
|
||||
FollowGroupSet = nil,
|
||||
FollowScheduler = nil,
|
||||
OptionROE = AI.Option.Air.val.ROE.OPEN_FIRE,
|
||||
OptionReactionOnThreat = AI.Option.Air.val.REACTION_ON_THREAT.ALLOW_ABORT_MISSION,
|
||||
dtFollow = 0.5,
|
||||
}
|
||||
|
||||
--- @type FORMATION.Formation
|
||||
-- @field #number None
|
||||
-- @field #number Line
|
||||
-- @field #number Trail
|
||||
-- @field #number Stack
|
||||
-- @field #number LeftLine
|
||||
-- @field #number RightLine
|
||||
-- @field #number LeftWing
|
||||
-- @field #number RightWing
|
||||
-- @field #number Vic
|
||||
-- @field #number Box
|
||||
FORMATION.Formation = {
|
||||
None = 1,
|
||||
Line = 2,
|
||||
Trail = 3,
|
||||
Stack = 4,
|
||||
LeftLine = 5,
|
||||
RightLine = 6,
|
||||
LeftWing = 7,
|
||||
RightWing = 8,
|
||||
Vic = 9,
|
||||
Box = 10,
|
||||
}
|
||||
|
||||
--- FORMATION class constructor for an AI group
|
||||
-- @param #FORMATION self
|
||||
-- @param Wrapper.Unit#UNIT FollowUnit The UNIT leading the FolllowGroupSet.
|
||||
-- @param Core.Set#SET_GROUP FollowGroupSet The group AI escorting the FollowUnit.
|
||||
-- @param #string FollowName Name of the escort.
|
||||
-- @return #FORMATION self
|
||||
function FORMATION:New( FollowUnit, FollowGroupSet, FollowName )
|
||||
local self = BASE:Inherit( self, FSM_SET:New( FollowGroupSet ) )
|
||||
self:F( { FollowUnit, FollowGroupSet, FollowName } )
|
||||
|
||||
self.FollowUnit = FollowUnit -- Wrapper.Unit#UNIT
|
||||
self.FollowGroupSet = FollowGroupSet -- Core.Set#SET_GROUP
|
||||
|
||||
self:SetFlightRandomization( 2 )
|
||||
|
||||
self:SetStartState( "None" )
|
||||
|
||||
self:AddTransition( "*", "Stop", "Stopped" )
|
||||
|
||||
self:AddTransition( {"None", "Stopped"}, "Start", "Following" )
|
||||
|
||||
self:AddTransition( "*", "FormationLine", "*" )
|
||||
|
||||
--- Start Trigger for FORMATION
|
||||
-- @function [parent=#FORMATION] Start
|
||||
-- @param #FORMATION self
|
||||
|
||||
--- Start Asynchronous Trigger for FORMATION
|
||||
-- @function [parent=#FORMATION] __Start
|
||||
-- @param #FORMATION self
|
||||
-- @param #number Delay
|
||||
|
||||
--- Stop Trigger for FORMATION
|
||||
-- @function [parent=#FORMATION] Stop
|
||||
-- @param #FORMATION self
|
||||
|
||||
--- Stop Asynchronous Trigger for FORMATION
|
||||
-- @function [parent=#FORMATION] __Stop
|
||||
-- @param #FORMATION self
|
||||
-- @param #number Delay
|
||||
|
||||
--- FormationLine Handler OnAfter for FORMATION
|
||||
-- @function [parent=#FORMATION] OnAfterFormationLine
|
||||
-- @param #FORMATION self
|
||||
-- @param Core.Set#SET_GROUP FollowGroupSet The group AI escorting the FollowUnit.
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @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 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 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.
|
||||
|
||||
--- FormationLine Trigger for FORMATION
|
||||
-- @function [parent=#FORMATION] FormationLine
|
||||
-- @param #FORMATION self
|
||||
-- @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 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 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.
|
||||
|
||||
--- FormationLine Asynchronous Trigger for FORMATION
|
||||
-- @function [parent=#FORMATION] __FormationLine
|
||||
-- @param #FORMATION self
|
||||
-- @param #number Delay
|
||||
-- @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 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 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.
|
||||
|
||||
self:AddTransition( "*", "FormationTrail", "*" )
|
||||
|
||||
--- FormationTrail Handler OnAfter for FORMATION
|
||||
-- @function [parent=#FORMATION] OnAfterFormationTrail
|
||||
-- @param #FORMATION self
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @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 YStart The start position on the Y-axis in meters for the first group.
|
||||
|
||||
--- FormationTrail Trigger for FORMATION
|
||||
-- @function [parent=#FORMATION] FormationTrail
|
||||
-- @param #FORMATION self
|
||||
-- @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 YStart The start position on the Y-axis in meters for the first group.
|
||||
|
||||
--- FormationTrail Asynchronous Trigger for FORMATION
|
||||
-- @function [parent=#FORMATION] __FormationTrail
|
||||
-- @param #FORMATION self
|
||||
-- @param #number Delay
|
||||
-- @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 YStart The start position on the Y-axis in meters for the first group.
|
||||
|
||||
self:AddTransition( "*", "FormationStack", "*" )
|
||||
|
||||
--- FormationStack Handler OnAfter for FORMATION
|
||||
-- @function [parent=#FORMATION] OnAfterFormationStack
|
||||
-- @param #FORMATION self
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @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 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.
|
||||
|
||||
--- FormationStack Trigger for FORMATION
|
||||
-- @function [parent=#FORMATION] FormationStack
|
||||
-- @param #FORMATION self
|
||||
-- @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 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.
|
||||
|
||||
--- FormationStack Asynchronous Trigger for FORMATION
|
||||
-- @function [parent=#FORMATION] __FormationStack
|
||||
-- @param #FORMATION self
|
||||
-- @param #number Delay
|
||||
-- @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 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.
|
||||
|
||||
self:AddTransition( "*", "FormationLeftLine", "*" )
|
||||
|
||||
--- FormationLeftLine Handler OnAfter for FORMATION
|
||||
-- @function [parent=#FORMATION] OnAfterFormationLeftLine
|
||||
-- @param #FORMATION self
|
||||
-- @param Core.Set#SET_GROUP FollowGroupSet The group AI escorting the FollowUnit.
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @param #number XStart The start position on the X-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 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.
|
||||
|
||||
--- FormationLeftLine Trigger for FORMATION
|
||||
-- @function [parent=#FORMATION] FormationLeftLine
|
||||
-- @param #FORMATION self
|
||||
-- @param #number XStart The start position on the X-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 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.
|
||||
|
||||
--- FormationLeftLine Asynchronous Trigger for FORMATION
|
||||
-- @function [parent=#FORMATION] __FormationLeftLine
|
||||
-- @param #FORMATION self
|
||||
-- @param #number Delay
|
||||
-- @param #number XStart The start position on the X-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 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.
|
||||
|
||||
self:AddTransition( "*", "FormationRightLine", "*" )
|
||||
|
||||
--- FormationRightLine Handler OnAfter for FORMATION
|
||||
-- @function [parent=#FORMATION] OnAfterFormationRightLine
|
||||
-- @param #FORMATION self
|
||||
-- @param Core.Set#SET_GROUP FollowGroupSet The group AI escorting the FollowUnit.
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @param #number XStart The start position on the X-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 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.
|
||||
|
||||
--- FormationRightLine Trigger for FORMATION
|
||||
-- @function [parent=#FORMATION] FormationRightLine
|
||||
-- @param #FORMATION self
|
||||
-- @param #number XStart The start position on the X-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 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.
|
||||
|
||||
--- FormationRightLine Asynchronous Trigger for FORMATION
|
||||
-- @function [parent=#FORMATION] __FormationRightLine
|
||||
-- @param #FORMATION self
|
||||
-- @param #number Delay
|
||||
-- @param #number XStart The start position on the X-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 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.
|
||||
|
||||
self:AddTransition( "*", "FormationLeftWing", "*" )
|
||||
|
||||
--- FormationLeftWing Handler OnAfter for FORMATION
|
||||
-- @function [parent=#FORMATION] OnAfterFormationLeftWing
|
||||
-- @param #FORMATION self
|
||||
-- @param Core.Set#SET_GROUP FollowGroupSet The group AI escorting the FollowUnit.
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @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 YStart The start position on the Y-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.
|
||||
|
||||
--- FormationLeftWing Trigger for FORMATION
|
||||
-- @function [parent=#FORMATION] FormationLeftWing
|
||||
-- @param #FORMATION self
|
||||
-- @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 YStart The start position on the Y-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.
|
||||
|
||||
--- FormationLeftWing Asynchronous Trigger for FORMATION
|
||||
-- @function [parent=#FORMATION] __FormationLeftWing
|
||||
-- @param #FORMATION self
|
||||
-- @param #number Delay
|
||||
-- @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 YStart The start position on the Y-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.
|
||||
|
||||
self:AddTransition( "*", "FormationRightWing", "*" )
|
||||
|
||||
--- FormationRightWing Handler OnAfter for FORMATION
|
||||
-- @function [parent=#FORMATION] OnAfterFormationRightWing
|
||||
-- @param #FORMATION self
|
||||
-- @param Core.Set#SET_GROUP FollowGroupSet The group AI escorting the FollowUnit.
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @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 YStart The start position on the Y-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.
|
||||
|
||||
--- FormationRightWing Trigger for FORMATION
|
||||
-- @function [parent=#FORMATION] FormationRightWing
|
||||
-- @param #FORMATION self
|
||||
-- @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 YStart The start position on the Y-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.
|
||||
|
||||
--- FormationRightWing Asynchronous Trigger for FORMATION
|
||||
-- @function [parent=#FORMATION] __FormationRightWing
|
||||
-- @param #FORMATION self
|
||||
-- @param #number Delay
|
||||
-- @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 YStart The start position on the Y-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.
|
||||
|
||||
self:AddTransition( "*", "FormationCenterWing", "*" )
|
||||
|
||||
--- FormationCenterWing Handler OnAfter for FORMATION
|
||||
-- @function [parent=#FORMATION] OnAfterFormationCenterWing
|
||||
-- @param #FORMATION self
|
||||
-- @param Core.Set#SET_GROUP FollowGroupSet The group AI escorting the FollowUnit.
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @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 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 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.
|
||||
|
||||
--- FormationCenterWing Trigger for FORMATION
|
||||
-- @function [parent=#FORMATION] FormationCenterWing
|
||||
-- @param #FORMATION self
|
||||
-- @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 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 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.
|
||||
|
||||
--- FormationCenterWing Asynchronous Trigger for FORMATION
|
||||
-- @function [parent=#FORMATION] __FormationCenterWing
|
||||
-- @param #FORMATION self
|
||||
-- @param #number Delay
|
||||
-- @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 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 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.
|
||||
|
||||
self:AddTransition( "*", "FormationVic", "*" )
|
||||
|
||||
--- FormationVic Handler OnAfter for FORMATION
|
||||
-- @function [parent=#FORMATION] OnAfterFormationVic
|
||||
-- @param #FORMATION self
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @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 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 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.
|
||||
|
||||
--- FormationVic Trigger for FORMATION
|
||||
-- @function [parent=#FORMATION] FormationVic
|
||||
-- @param #FORMATION self
|
||||
-- @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 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 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.
|
||||
|
||||
--- FormationVic Asynchronous Trigger for FORMATION
|
||||
-- @function [parent=#FORMATION] __FormationVic
|
||||
-- @param #FORMATION self
|
||||
-- @param #number Delay
|
||||
-- @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 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 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.
|
||||
|
||||
self:AddTransition( "*", "FormationBox", "*" )
|
||||
|
||||
--- FormationBox Handler OnAfter for FORMATION
|
||||
-- @function [parent=#FORMATION] OnAfterFormationBox
|
||||
-- @param #FORMATION self
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @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 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 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 ZLevels The amount of levels on the Z-axis.
|
||||
|
||||
--- FormationBox Trigger for FORMATION
|
||||
-- @function [parent=#FORMATION] FormationBox
|
||||
-- @param #FORMATION self
|
||||
-- @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 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 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 ZLevels The amount of levels on the Z-axis.
|
||||
|
||||
--- FormationBox Asynchronous Trigger for FORMATION
|
||||
-- @function [parent=#FORMATION] __FormationBox
|
||||
-- @param #FORMATION self
|
||||
-- @param #number Delay
|
||||
-- @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 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 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 ZLevels The amount of levels on the Z-axis.
|
||||
|
||||
self:AddTransition( "*", "Follow", "Following" )
|
||||
|
||||
self:FormationLeftLine( 500, 0, 250, 250 )
|
||||
|
||||
self.FollowName = FollowName
|
||||
|
||||
self.CT1 = 0
|
||||
self.GT1 = 0
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Set time interval between updates of the formation.
|
||||
-- @param #FORMATION self
|
||||
-- @param #number dt Time step in seconds between formation updates. Default is every 0.5 seconds.
|
||||
-- @return #FORMATION
|
||||
function FORMATION:SetFollowTimeInterval(dt)
|
||||
self.dtFollow=dt or 0.5
|
||||
return self
|
||||
end
|
||||
|
||||
--- This function is for test, it will put on the frequency of the FollowScheduler a red smoke at the direction vector calculated for the escort to fly to.
|
||||
-- This allows to visualize where the escort is flying to.
|
||||
-- @param #FORMATION self
|
||||
-- @param #boolean SmokeDirection If true, then the direction vector will be smoked.
|
||||
-- @return #FORMATION
|
||||
function FORMATION:TestSmokeDirectionVector( SmokeDirection )
|
||||
self.SmokeDirectionVector = ( SmokeDirection == true ) and true or false
|
||||
return self
|
||||
end
|
||||
|
||||
--- FormationLine Handler OnAfter for FORMATION
|
||||
-- @param #FORMATION self
|
||||
-- @param Core.Set#SET_GROUP FollowGroupSet The group AI escorting the FollowUnit.
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @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 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 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.
|
||||
-- @return #FORMATION
|
||||
function FORMATION:onafterFormationLine( FollowGroupSet, From , Event , To, XStart, XSpace, YStart, YSpace, ZStart, ZSpace, Formation )
|
||||
self:F( { FollowGroupSet, From , Event ,To, XStart, XSpace, YStart, YSpace, ZStart, ZSpace, Formation } )
|
||||
|
||||
XStart = XStart or self.XStart
|
||||
XSpace = XSpace or self.XSpace
|
||||
YStart = YStart or self.YStart
|
||||
YSpace = YSpace or self.YSpace
|
||||
ZStart = ZStart or self.ZStart
|
||||
ZSpace = ZSpace or self.ZSpace
|
||||
|
||||
local FollowSet = FollowGroupSet:GetSet()
|
||||
|
||||
local i = 1 --FF i=0 caused first unit to have no XSpace! Probably needs further adjustments. This is just a quick work around.
|
||||
|
||||
for FollowID, FollowGroup in pairs( FollowSet ) do
|
||||
|
||||
local PointVec3 = COORDINATE:New()
|
||||
PointVec3:SetX( XStart + i * XSpace )
|
||||
PointVec3:SetY( YStart + i * YSpace )
|
||||
PointVec3:SetZ( ZStart + i * ZSpace )
|
||||
|
||||
local Vec3 = PointVec3:GetVec3()
|
||||
FollowGroup:SetState( self, "FormationVec3", Vec3 )
|
||||
i = i + 1
|
||||
|
||||
FollowGroup:SetState( FollowGroup, "Formation", Formation )
|
||||
end
|
||||
|
||||
return self
|
||||
|
||||
end
|
||||
|
||||
--- FormationTrail Handler OnAfter for FORMATION
|
||||
-- @param #FORMATION self
|
||||
-- @param Core.Set#SET_GROUP FollowGroupSet The group AI escorting the FollowUnit.
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @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 YStart The start position on the Y-axis in meters for the first group.
|
||||
-- @return #FORMATION
|
||||
function FORMATION:onafterFormationTrail( FollowGroupSet, From , Event , To, XStart, XSpace, YStart )
|
||||
|
||||
self:onafterFormationLine(FollowGroupSet,From,Event,To,XStart,XSpace,YStart,0,0,0, self.Formation.Trail )
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- FormationStack Handler OnAfter for FORMATION
|
||||
-- @param #FORMATION self
|
||||
-- @param Core.Set#SET_GROUP FollowGroupSet The group AI escorting the FollowUnit.
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @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 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.
|
||||
-- @return #FORMATION
|
||||
function FORMATION:onafterFormationStack( FollowGroupSet, From , Event , To, XStart, XSpace, YStart, YSpace )
|
||||
|
||||
self:onafterFormationLine(FollowGroupSet,From,Event,To,XStart,XSpace,YStart,YSpace,0,0, self.Formation.Stack )
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- FormationLeftLine Handler OnAfter for FORMATION
|
||||
-- @param #FORMATION self
|
||||
-- @param Core.Set#SET_GROUP FollowGroupSet The group AI escorting the FollowUnit.
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @param #number XStart The start position on the X-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 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.
|
||||
-- @return #FORMATION
|
||||
function FORMATION:onafterFormationLeftLine( FollowGroupSet, From , Event , To, XStart, YStart, ZStart, ZSpace )
|
||||
|
||||
self:onafterFormationLine(FollowGroupSet,From,Event,To,XStart,0,YStart,0,-ZStart,-ZSpace, self.Formation.LeftLine )
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- FormationRightLine Handler OnAfter for FORMATION
|
||||
-- @param #FORMATION self
|
||||
-- @param Core.Set#SET_GROUP FollowGroupSet The group AI escorting the FollowUnit.
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @param #number XStart The start position on the X-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 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.
|
||||
-- @return #FORMATION
|
||||
function FORMATION:onafterFormationRightLine( FollowGroupSet, From , Event , To, XStart, YStart, ZStart, ZSpace )
|
||||
|
||||
self:onafterFormationLine(FollowGroupSet,From,Event,To,XStart,0,YStart,0,ZStart,ZSpace,self.Formation.RightLine)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- FormationLeftWing Handler OnAfter for FORMATION
|
||||
-- @param #FORMATION self
|
||||
-- @param Core.Set#SET_GROUP FollowGroupSet The group AI escorting the FollowUnit.
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @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 YStart The start position on the Y-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.
|
||||
function FORMATION:onafterFormationLeftWing( FollowGroupSet, From , Event , To, XStart, XSpace, YStart, ZStart, ZSpace )
|
||||
|
||||
self:onafterFormationLine(FollowGroupSet,From,Event,To,XStart,XSpace,YStart,0,-ZStart,-ZSpace,self.Formation.LeftWing)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- FormationRightWing Handler OnAfter for FORMATION
|
||||
-- @function [parent=#FORMATION] OnAfterFormationRightWing
|
||||
-- @param #FORMATION self
|
||||
-- @param Core.Set#SET_GROUP FollowGroupSet The group AI escorting the FollowUnit.
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @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 YStart The start position on the Y-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.
|
||||
function FORMATION:onafterFormationRightWing( FollowGroupSet, From , Event , To, XStart, XSpace, YStart, ZStart, ZSpace )
|
||||
|
||||
self:onafterFormationLine(FollowGroupSet,From,Event,To,XStart,XSpace,YStart,0,ZStart,ZSpace,self.Formation.RightWing)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- FormationCenterWing Handler OnAfter for FORMATION
|
||||
-- @param #FORMATION self
|
||||
-- @param Core.Set#SET_GROUP FollowGroupSet The group AI escorting the FollowUnit.
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @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 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 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.
|
||||
function FORMATION:onafterFormationCenterWing( FollowGroupSet, From , Event , To, XStart, XSpace, YStart, YSpace, ZStart, ZSpace )
|
||||
|
||||
local FollowSet = FollowGroupSet:GetSet()
|
||||
|
||||
local i = 0
|
||||
|
||||
for FollowID, FollowGroup in pairs( FollowSet ) do
|
||||
|
||||
local PointVec3 = COORDINATE:New()
|
||||
|
||||
local Side = ( i % 2 == 0 ) and 1 or -1
|
||||
local Row = i / 2 + 1
|
||||
|
||||
PointVec3:SetX( XStart + Row * XSpace )
|
||||
PointVec3:SetY( YStart )
|
||||
PointVec3:SetZ( Side * ( ZStart + i * ZSpace ) )
|
||||
|
||||
local Vec3 = PointVec3:GetVec3()
|
||||
FollowGroup:SetState( self, "FormationVec3", Vec3 )
|
||||
i = i + 1
|
||||
FollowGroup:SetState( FollowGroup, "Formation", self.Formation.Vic )
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- FormationVic Handle for FORMATION
|
||||
-- @param #FORMATION self
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @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 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 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.
|
||||
-- @return #FORMATION
|
||||
function FORMATION:onafterFormationVic( FollowGroupSet, From , Event , To, XStart, XSpace, YStart, YSpace, ZStart, ZSpace )
|
||||
|
||||
self:onafterFormationCenterWing(FollowGroupSet,From,Event,To,XStart,XSpace,YStart,YSpace,ZStart,ZSpace)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- FormationBox Handler OnAfter for FORMATION
|
||||
-- @param #FORMATION self
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @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 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 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 ZLevels The amount of levels on the Z-axis.
|
||||
-- @return #FORMATION
|
||||
function FORMATION:onafterFormationBox( FollowGroupSet, From , Event , To, XStart, XSpace, YStart, YSpace, ZStart, ZSpace, ZLevels )
|
||||
|
||||
local FollowSet = FollowGroupSet:GetSet()
|
||||
|
||||
local i = 0
|
||||
|
||||
for FollowID, FollowGroup in pairs( FollowSet ) do
|
||||
|
||||
local PointVec3 = COORDINATE:New()
|
||||
|
||||
local ZIndex = i % ZLevels
|
||||
local XIndex = math.floor( i / ZLevels )
|
||||
local YIndex = math.floor( i / ZLevels )
|
||||
|
||||
PointVec3:SetX( XStart + XIndex * XSpace )
|
||||
PointVec3:SetY( YStart + YIndex * YSpace )
|
||||
PointVec3:SetZ( -ZStart - (ZSpace * ZLevels / 2 ) + ZSpace * ZIndex )
|
||||
|
||||
local Vec3 = PointVec3:GetVec3()
|
||||
FollowGroup:SetState( self, "FormationVec3", Vec3 )
|
||||
i = i + 1
|
||||
FollowGroup:SetState( FollowGroup, "Formation", self.Formation.Box )
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Use the method @{FORMATION#FORMATION.SetFlightRandomization}() to make the air units in your formation randomize their flight a bit while in formation.
|
||||
-- @param #FORMATION self
|
||||
-- @param #number FlightRandomization The formation flying errors that pilots can make while in formation. Is a range set in meters.
|
||||
-- @return #FORMATION
|
||||
function FORMATION:SetFlightRandomization( FlightRandomization )
|
||||
self.FlightRandomization = FlightRandomization
|
||||
return self
|
||||
end
|
||||
|
||||
--- Stop function. Formation will not be updated any more.
|
||||
-- @param #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 FORMATION:onafterStop(FollowGroupSet, From, Event, To)
|
||||
self:E("Stopping formation.")
|
||||
end
|
||||
|
||||
--- Follow event fuction. Check if coming from state "stopped". If so the transition is rejected.
|
||||
-- @param #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 FORMATION:onbeforeFollow( FollowGroupSet, From, Event, To )
|
||||
if From=="Stopped" then
|
||||
return false -- Deny transition.
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
--- Enter following state.
|
||||
-- @param #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 FORMATION:onenterFollowing( FollowGroupSet )
|
||||
|
||||
if self.FollowUnit:IsAlive() then
|
||||
|
||||
local ClientUnit = self.FollowUnit
|
||||
|
||||
local CT1, CT2, CV1, CV2
|
||||
CT1 = ClientUnit:GetState( self, "CT1" )
|
||||
|
||||
local CuVec3=ClientUnit:GetVec3()
|
||||
|
||||
if CT1 == nil or CT1 == 0 then
|
||||
ClientUnit:SetState( self, "CV1", CuVec3)
|
||||
ClientUnit:SetState( self, "CT1", timer.getTime() )
|
||||
else
|
||||
CT1 = ClientUnit:GetState( self, "CT1" )
|
||||
CT2 = timer.getTime()
|
||||
CV1 = ClientUnit:GetState( self, "CV1" )
|
||||
CV2 = CuVec3
|
||||
|
||||
ClientUnit:SetState( self, "CT1", CT2 )
|
||||
ClientUnit:SetState( self, "CV1", CV2 )
|
||||
end
|
||||
|
||||
--FollowGroupSet:ForEachGroupAlive( bla, self, ClientUnit, CT1, CV1, CT2, CV2)
|
||||
|
||||
for _,_group in pairs(FollowGroupSet:GetSet()) do
|
||||
local group=_group --Wrapper.Group#GROUP
|
||||
if group and group:IsAlive() then
|
||||
self:FollowMe(group, ClientUnit, CT1, CV1, CT2, CV2)
|
||||
end
|
||||
end
|
||||
|
||||
self:__Follow( -self.dtFollow )
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- Follow me.
|
||||
-- @param #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 FORMATION:FollowMe(FollowGroup, ClientUnit, CT1, CV1, CT2, CV2)
|
||||
|
||||
if not self:Is("Stopped") 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.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,
|
||||
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
|
||||
@@ -90,7 +90,8 @@
|
||||
-- @image Scoring.JPG
|
||||
|
||||
--- @type SCORING
|
||||
-- @field Players A collection of the current players that have joined the game.
|
||||
-- @field #table Players A collection of the current players that have joined the game.
|
||||
-- @field Core.Set#SET_SCENERY ScoringScenery
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
--- SCORING class
|
||||
@@ -229,7 +230,8 @@ SCORING = {
|
||||
ClassID = 0,
|
||||
Players = {},
|
||||
AutoSave = true,
|
||||
version = "1.18.4"
|
||||
version = "1.18.4",
|
||||
ScoringScenery = nil, -- Core.Set#SET_SCENERY
|
||||
}
|
||||
|
||||
local _SCORINGCoalition = {
|
||||
@@ -325,6 +327,8 @@ function SCORING:New( GameName, SavePath, AutoSave )
|
||||
self:OpenCSV( GameName )
|
||||
end
|
||||
|
||||
self:I("SCORING "..tostring(GameName).." started! v"..self.version)
|
||||
|
||||
return self
|
||||
|
||||
end
|
||||
@@ -377,7 +381,7 @@ function SCORING:AddUnitScore( ScoreUnit, Score )
|
||||
return self
|
||||
end
|
||||
|
||||
--- Removes a @{Wrapper.Unit} for additional scoring when the @{Wrapper.Unit} is destroyed.
|
||||
--- Removes a @{Wrapper.Unit} for scoring when the @{Wrapper.Unit} is destroyed.
|
||||
-- @param #SCORING self
|
||||
-- @param Wrapper.Unit#UNIT ScoreUnit The @{Wrapper.Unit} for which the Score needs to be given.
|
||||
-- @return #SCORING
|
||||
@@ -394,10 +398,26 @@ end
|
||||
-- Note that if there was already a @{Wrapper.Static} declared within the scoring with the same name,
|
||||
-- then the old @{Wrapper.Static} will be replaced with the new @{Wrapper.Static}.
|
||||
-- @param #SCORING self
|
||||
-- @param Wrapper.Static#UNIT ScoreStatic The @{Wrapper.Static} for which the Score needs to be given.
|
||||
-- @param Wrapper.Static#STATIC ScoreStatic The @{Wrapper.Static} for which the Score needs to be given.
|
||||
-- @param #number Score The Score value.
|
||||
-- @return #SCORING
|
||||
function SCORING:AddStaticScore( ScoreStatic, Score )
|
||||
return self:AddScoreStatic( ScoreStatic, Score )
|
||||
end
|
||||
|
||||
--- Add a @{Wrapper.Static} for additional scoring when the @{Wrapper.Static} is destroyed.
|
||||
-- Note that if there was already a @{Wrapper.Static} declared within the scoring with the same name,
|
||||
-- then the old @{Wrapper.Static} will be replaced with the new @{Wrapper.Static}.
|
||||
-- @param #SCORING self
|
||||
-- @param Wrapper.Static#STATIC ScoreStatic The @{Wrapper.Static} for which the Score needs to be given.
|
||||
-- @param #number Score The Score value.
|
||||
-- @return #SCORING
|
||||
function SCORING:AddScoreStatic( ScoreStatic, Score )
|
||||
|
||||
if ScoreStatic == nil then
|
||||
BASE:E("SCORING.AddStaticScore: Parameter ScoreStatic is nil!")
|
||||
return self
|
||||
end
|
||||
|
||||
local StaticName = ScoreStatic:GetName()
|
||||
|
||||
@@ -406,7 +426,61 @@ function SCORING:AddStaticScore( ScoreStatic, Score )
|
||||
return self
|
||||
end
|
||||
|
||||
--- Removes a @{Wrapper.Static} for additional scoring when the @{Wrapper.Static} is destroyed.
|
||||
--- Add a @{Wrapper.Scenery} for additional scoring when the @{Wrapper.Scenery} is destroyed.
|
||||
-- @param #SCORING self
|
||||
-- @param Wrapper.Scenery#SCENERY ScoreScenery The @{Wrapper.Scenery} for which the Score needs to be given.
|
||||
-- @param #number Score The Score value.
|
||||
-- @return #SCORING
|
||||
function SCORING:AddScoreScenery( ScoreScenery, Score )
|
||||
|
||||
if ScoreScenery == nil then
|
||||
self:E("SCORING.ScoreScenery: Parameter ScoreScenery is nil!")
|
||||
return self
|
||||
end
|
||||
|
||||
if not self.ScoringScenery then
|
||||
self.ScoringScenery = SET_SCENERY:New() -- Core.Set#SET_SCENERY
|
||||
end
|
||||
|
||||
local StaticName = ScoreScenery:GetName()
|
||||
self:T("Scenery name = ".. StaticName)
|
||||
|
||||
self.ScoringScenery:AddScenery(ScoreScenery)
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Removes a @{Wrapper.Scenery} for scoring when the @{Wrapper.Scenery} is destroyed.
|
||||
-- @param #SCORING self
|
||||
-- @param Wrapper.Scenery#SCENERY ScoreStatic The @{Wrapper.Scenery} for which the Score needs to be given.
|
||||
-- @return #SCORING
|
||||
function SCORING:RemoveSceneryScore( ScoreScenery )
|
||||
|
||||
local StaticName = ScoreScenery:GetName()
|
||||
|
||||
self.ScoringObjects[StaticName] = nil
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Specify a special additional score for a @{Core.Set#SET_SCENERY}.
|
||||
-- @param #SCORING self
|
||||
-- @param Core.Set#SET_SCENERY Set The @{Core.Set#SET_SCENERY} for which each @{Wrapper.Scenery} in the SET a Score is given.
|
||||
-- @param #number Score The Score value.
|
||||
-- @return #SCORING
|
||||
function SCORING:AddScoreSetScenery(Set, Score)
|
||||
local set = Set.Set
|
||||
|
||||
for _,_static in pairs (set) do
|
||||
if _static ~= nil then
|
||||
self:AddScoreScenery(_static,Score)
|
||||
end
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Removes a @{Wrapper.Static} for scoring when the @{Wrapper.Static} is destroyed.
|
||||
-- @param #SCORING self
|
||||
-- @param Wrapper.Static#UNIT ScoreStatic The @{Wrapper.Static} for which the Score needs to be given.
|
||||
-- @return #SCORING
|
||||
@@ -461,6 +535,31 @@ function SCORING:AddScoreSetGroup(Set, Score)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Specify a special additional score for a @{Core.Set#SET_STATIC}.
|
||||
-- @param #SCORING self
|
||||
-- @param Core.Set#SET_STATIC Set The @{Core.Set#SET_STATIC} for which each @{Wrapper.Static} in the SET a Score is given.
|
||||
-- @param #number Score The Score value.
|
||||
-- @return #SCORING
|
||||
function SCORING:AddScoreSetStatic(Set, Score)
|
||||
local set = Set:GetSetObjects()
|
||||
|
||||
for _,_static in pairs (set) do
|
||||
if _static and _static:IsAlive() then
|
||||
self:AddStaticScore(_static,Score)
|
||||
end
|
||||
end
|
||||
|
||||
local function AddScore(static)
|
||||
self:AddStaticScore(static,Score)
|
||||
end
|
||||
|
||||
function Set:OnAfterAdded(From,Event,To,ObjectName,Object)
|
||||
AddScore(Object)
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Add a @{Core.Zone} to define additional scoring when any object is destroyed in that zone.
|
||||
-- Note that if a @{Core.Zone} with the same name is already within the scoring added, the @{Core.Zone} (type) and Score will be replaced!
|
||||
-- This allows for a dynamic destruction zone evolution within your mission.
|
||||
@@ -480,7 +579,24 @@ function SCORING:AddZoneScore( ScoreZone, Score )
|
||||
return self
|
||||
end
|
||||
|
||||
--- Remove a @{Core.Zone} for additional scoring.
|
||||
--- Add a @{Core.Set#SET_ZONE} to define additional scoring when any object is destroyed in that zone.
|
||||
-- Note that if a @{Core.Zone} with the same name is already within the scoring added, the @{Core.Zone} (type) and Score will be replaced!
|
||||
-- This allows for a dynamic destruction zone evolution within your mission.
|
||||
-- @param #SCORING self
|
||||
-- @param Core.Set#SET_ZONE ScoreZoneSet The @{Core.Set#SET_ZONE} which defines the destruction score perimeters.
|
||||
-- Note that a zone can be a polygon or a moving zone.
|
||||
-- @param #number Score The Score value.
|
||||
-- @return #SCORING
|
||||
function SCORING:AddZoneScoreSet( ScoreZoneSet, Score )
|
||||
|
||||
for _,_zone in pairs(ScoreZoneSet.Set or {}) do
|
||||
self:AddZoneScore(_zone,Score)
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Remove a @{Core.Zone} for scoring.
|
||||
-- The scoring will search if any @{Core.Zone} is added with the given name, and will remove that zone from the scoring.
|
||||
-- This allows for a dynamic destruction zone evolution within your mission.
|
||||
-- @param #SCORING self
|
||||
@@ -958,7 +1074,7 @@ end
|
||||
-- @param #SCORING self
|
||||
-- @param Core.Event#EVENTDATA Event
|
||||
function SCORING:_EventOnHit( Event )
|
||||
self:F( { Event } )
|
||||
--self:F( { Event } )
|
||||
|
||||
local InitUnit = nil
|
||||
local InitUNIT = nil
|
||||
@@ -988,6 +1104,7 @@ function SCORING:_EventOnHit( Event )
|
||||
local TargetUnitCategory = nil
|
||||
local TargetUnitType = nil
|
||||
local TargetIsScenery = false
|
||||
local TargetSceneryObject = nil
|
||||
|
||||
if Event.IniDCSUnit then
|
||||
|
||||
@@ -1009,7 +1126,7 @@ function SCORING:_EventOnHit( Event )
|
||||
InitUnitCategory = _SCORINGCategory[InitCategory]
|
||||
InitUnitType = InitType
|
||||
|
||||
self:T( { InitUnitName, InitGroupName, InitPlayerName, InitCoalition, InitCategory, InitType, InitUnitCoalition, InitUnitCategory, InitUnitType } )
|
||||
--self:T( { InitUnitName, InitGroupName, InitPlayerName, InitCoalition, InitCategory, InitType, InitUnitCoalition, InitUnitCategory, InitUnitType } )
|
||||
end
|
||||
|
||||
if Event.TgtDCSUnit then
|
||||
@@ -1027,18 +1144,23 @@ function SCORING:_EventOnHit( Event )
|
||||
-- TargetCategory = TargetUnit:getDesc().category
|
||||
TargetCategory = Event.TgtCategory
|
||||
TargetType = Event.TgtTypeName
|
||||
|
||||
|
||||
-- Scenery hit
|
||||
if (not TargetCategory) and TargetUNIT ~= nil and TargetUnit:IsInstanceOf("SCENERY") then
|
||||
if TargetUNIT ~= nil and TargetUNIT:IsInstanceOf("SCENERY") then
|
||||
TargetCategory = Unit.Category.STRUCTURE
|
||||
TargetIsScenery = true
|
||||
TargetType = "Scenery"
|
||||
TargetSceneryObject = TargetUNIT
|
||||
self:T("***** Target is Scenery and TargetUNIT is SCENERY object!")
|
||||
UTILS.PrintTableToLog(TargetSceneryObject)
|
||||
end
|
||||
|
||||
TargetUnitCoalition = _SCORINGCoalition[TargetCoalition]
|
||||
TargetUnitCategory = _SCORINGCategory[TargetCategory]
|
||||
TargetUnitType = TargetType
|
||||
|
||||
self:T( { TargetUnitName, TargetGroupName, TargetPlayerName, TargetCoalition, TargetCategory, TargetType, TargetUnitCoalition, TargetUnitCategory, TargetUnitType } )
|
||||
--self:T( { TargetUnitName=TargetUnitName, TargetGroupName=TargetGroupName, TargetPlayerName=TargetPlayerName, TargetCoalition=TargetCoalition, TargetCategory=TargetCategory, TargetType=TargetType, TargetUnitCoalition=TargetUnitCoalition, TargetUnitCategory=TargetUnitCategory, TargetUnitType=TargetUnitType } )
|
||||
end
|
||||
|
||||
if InitPlayerName ~= nil then -- It is a player that is hitting something
|
||||
@@ -1051,7 +1173,7 @@ function SCORING:_EventOnHit( Event )
|
||||
self:T( "Hitting Something" )
|
||||
|
||||
-- What is he hitting?
|
||||
if TargetCategory then
|
||||
if (TargetCategory ~=nil) and (TargetIsScenery == false) then
|
||||
|
||||
-- A target got hit, score it.
|
||||
-- Player contains the score data from self.Players[InitPlayerName]
|
||||
@@ -1071,7 +1193,7 @@ function SCORING:_EventOnHit( Event )
|
||||
PlayerHit.TimeStamp = PlayerHit.TimeStamp or 0
|
||||
PlayerHit.UNIT = PlayerHit.UNIT or TargetUNIT
|
||||
-- After an instant kill we can't compute the threat level anymore. To fix this we compute at OnEventBirth
|
||||
if PlayerHit.UNIT.ThreatType == nil then
|
||||
if PlayerHit.UNIT and PlayerHit.UNIT.ThreatType == nil then
|
||||
PlayerHit.ThreatLevel, PlayerHit.ThreatType = PlayerHit.UNIT:GetThreatLevel()
|
||||
-- if this fails for some reason, set a good default value
|
||||
if PlayerHit.ThreatType == nil or PlayerHit.ThreatType == "" then
|
||||
@@ -1157,21 +1279,21 @@ function SCORING:_EventOnHit( Event )
|
||||
|
||||
-- It is a weapon initiated by a player, that is hitting something
|
||||
-- This seems to occur only with scenery and static objects.
|
||||
if Event.WeaponPlayerName ~= nil then
|
||||
self:_AddPlayerFromUnit( Event.WeaponUNIT )
|
||||
if self.Players[Event.WeaponPlayerName] then -- This should normally not happen, but i'll test it anyway.
|
||||
if TargetPlayerName ~= nil then -- It is a player hitting another player ...
|
||||
self:_AddPlayerFromUnit( TargetUNIT )
|
||||
end
|
||||
if Event.WeaponPlayerName ~= nil or TargetIsScenery == true then
|
||||
|
||||
local playername = Event.WeaponPlayerName or Event.IniPlayerName or "Ghost"
|
||||
|
||||
--self:_AddPlayerFromUnit( Event.WeaponUNIT )
|
||||
if self.Players[playername] then -- This should normally not happen, but i'll test it anyway.
|
||||
|
||||
self:T( "Hitting Scenery" )
|
||||
self:T( "Hitting Scenery or Static" )
|
||||
|
||||
-- What is he hitting?
|
||||
if TargetCategory then
|
||||
if Event.TgtObjectCategory then
|
||||
|
||||
-- A scenery or static got hit, score it.
|
||||
-- Player contains the score data from self.Players[WeaponPlayerName]
|
||||
local Player = self.Players[Event.WeaponPlayerName]
|
||||
local Player = self.Players[playername]
|
||||
|
||||
-- Ensure there is a hit table per TargetCategory and TargetUnitName.
|
||||
Player.Hit[TargetCategory] = Player.Hit[TargetCategory] or {}
|
||||
@@ -1179,15 +1301,17 @@ function SCORING:_EventOnHit( Event )
|
||||
|
||||
-- PlayerHit contains the score counters and data per unit that was hit.
|
||||
local PlayerHit = Player.Hit[TargetCategory][TargetUnitName]
|
||||
|
||||
|
||||
-- Init player scores
|
||||
PlayerHit.Score = PlayerHit.Score or 0
|
||||
PlayerHit.Penalty = PlayerHit.Penalty or 0
|
||||
PlayerHit.ScoreHit = PlayerHit.ScoreHit or 0
|
||||
PlayerHit.PenaltyHit = PlayerHit.PenaltyHit or 0
|
||||
PlayerHit.TimeStamp = PlayerHit.TimeStamp or 0
|
||||
PlayerHit.UNIT = PlayerHit.UNIT or TargetUNIT
|
||||
|
||||
-- After an instant kill we can't compute the threat level anymore. To fix this we compute at OnEventBirth
|
||||
if PlayerHit.UNIT.ThreatType == nil then
|
||||
if PlayerHit.UNIT and PlayerHit.UNIT.ThreatType == nil then
|
||||
PlayerHit.ThreatLevel, PlayerHit.ThreatType = PlayerHit.UNIT:GetThreatLevel()
|
||||
-- if this fails for some reason, set a good default value
|
||||
if PlayerHit.ThreatType == nil then
|
||||
@@ -1195,8 +1319,8 @@ function SCORING:_EventOnHit( Event )
|
||||
PlayerHit.ThreatType = "Unknown"
|
||||
end
|
||||
else
|
||||
PlayerHit.ThreatLevel = PlayerHit.UNIT.ThreatLevel
|
||||
PlayerHit.ThreatType = PlayerHit.UNIT.ThreatType
|
||||
PlayerHit.ThreatLevel = PlayerHit.UNIT and PlayerHit.UNIT.ThreatLevel or 1
|
||||
PlayerHit.ThreatType = PlayerHit.UNIT and PlayerHit.UNIT.ThreatType or "Unknown"
|
||||
end
|
||||
|
||||
-- Only grant hit scores if there was more than one second between the last hit.
|
||||
@@ -1204,50 +1328,68 @@ function SCORING:_EventOnHit( Event )
|
||||
PlayerHit.TimeStamp = timer.getTime()
|
||||
|
||||
local Score = 0
|
||||
|
||||
if InitCoalition then -- A coalition object was hit, probably a static.
|
||||
if InitCoalition == TargetCoalition then
|
||||
-- TODO: Penalty according scale
|
||||
local Penalty = 10
|
||||
Player.Penalty = Player.Penalty + Penalty --* self.ScaleDestroyPenalty
|
||||
PlayerHit.Penalty = PlayerHit.Penalty + Penalty --* self.ScaleDestroyPenalty
|
||||
PlayerHit.PenaltyHit = PlayerHit.PenaltyHit + 1 * self.ScaleDestroyPenalty
|
||||
|
||||
MESSAGE
|
||||
:NewType( self.DisplayMessagePrefix .. "Player '" .. Event.WeaponPlayerName .. "' hit friendly target " ..
|
||||
TargetUnitCategory .. " ( " .. TargetType .. " ) " ..
|
||||
"Penalty: -" .. Penalty .. " = " .. Player.Score - Player.Penalty,
|
||||
MESSAGE.Type.Update
|
||||
)
|
||||
:ToAllIf( self:IfMessagesHit() and self:IfMessagesToAll() )
|
||||
:ToCoalitionIf( Event.WeaponCoalition, self:IfMessagesHit() and self:IfMessagesToCoalition() )
|
||||
self:ScoreCSV( Event.WeaponPlayerName, TargetPlayerName, "HIT_PENALTY", 1, -10, Event.WeaponName, Event.WeaponCoalition, Event.WeaponCategory, Event.WeaponTypeName, TargetUnitName, TargetUnitCoalition, TargetUnitCategory, TargetUnitType )
|
||||
else
|
||||
|
||||
local TgtName = Event.TgtDCSUnit and Event.TgtDCSUnit.getName and Event.TgtDCSUnit:getName() or "Unknown"
|
||||
|
||||
--if InitCoalition then -- A coalition object was hit, probably a static.
|
||||
if TargetIsScenery == true and self.ScoringScenery:IsInSet(TargetSceneryObject) then
|
||||
Player.Score = Player.Score + self.ScoreIncrementOnHit
|
||||
PlayerHit.Score = PlayerHit.Score + self.ScoreIncrementOnHit
|
||||
PlayerHit.ScoreHit = PlayerHit.ScoreHit + 1
|
||||
MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. Event.WeaponPlayerName .. "' hit enemy target " .. TargetUnitCategory .. " ( " .. TargetType .. " ) " ..
|
||||
MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. playername .. "' hit scenery target " .. TargetUnitCategory .. " ( " .. TargetType .. " ) " ..
|
||||
"Score: " .. PlayerHit.Score .. ". Score Total:" .. Player.Score - Player.Penalty,
|
||||
MESSAGE.Type.Update )
|
||||
:ToAllIf( self:IfMessagesHit() and self:IfMessagesToAll() )
|
||||
:ToCoalitionIf( Event.WeaponCoalition, self:IfMessagesHit() and self:IfMessagesToCoalition() )
|
||||
|
||||
self:ScoreCSV( Event.WeaponPlayerName, TargetPlayerName, "HIT_SCORE", 1, 1, Event.WeaponName, Event.WeaponCoalition, Event.WeaponCategory, Event.WeaponTypeName, TargetUnitName, TargetUnitCoalition, TargetUnitCategory, TargetUnitType )
|
||||
end
|
||||
else -- A scenery object was hit.
|
||||
MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. Event.WeaponPlayerName .. "' hit scenery object.",
|
||||
MESSAGE.Type.Update )
|
||||
:ToAllIf( self:IfMessagesHit() and self:IfMessagesToAll() )
|
||||
:ToCoalitionIf( InitCoalition, self:IfMessagesHit() and self:IfMessagesToCoalition() )
|
||||
self:ScoreCSV( playername, TargetPlayerName, "HIT_SCORE", 1, 1, Event.WeaponName, Event.WeaponCoalition, Event.WeaponCategory, Event.WeaponTypeName, TargetUnitName, TargetUnitCoalition, TargetUnitCategory, TargetUnitType )
|
||||
elseif TargetIsScenery == false and Event.TgtObjectCategory == Object.Category.STATIC and self.ScoringObjects[TgtName] then
|
||||
Player.Score = Player.Score + self.ScoreIncrementOnHit
|
||||
PlayerHit.Score = PlayerHit.Score + self.ScoreIncrementOnHit
|
||||
PlayerHit.ScoreHit = PlayerHit.ScoreHit + 1
|
||||
MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. playername .. "' hit static target " .. TargetUnitCategory .. " ( " .. TargetType .. " ) " ..
|
||||
"Score: " .. PlayerHit.Score .. ". Score Total:" .. Player.Score - Player.Penalty,
|
||||
MESSAGE.Type.Update )
|
||||
:ToAllIf( self:IfMessagesHit() and self:IfMessagesToAll() )
|
||||
:ToCoalitionIf( Event.WeaponCoalition, self:IfMessagesHit() and self:IfMessagesToCoalition() )
|
||||
|
||||
self:ScoreCSV( Event.WeaponPlayerName, "", "HIT_SCORE", 1, 0, Event.WeaponName, Event.WeaponCoalition, Event.WeaponCategory, Event.WeaponTypeName, TargetUnitName, "", "Scenery", TargetUnitType )
|
||||
end
|
||||
self:ScoreCSV( playername, TargetPlayerName, "HIT_SCORE", 1, 1, Event.WeaponName, Event.WeaponCoalition, Event.WeaponCategory, Event.WeaponTypeName, TargetUnitName, TargetUnitCoalition, TargetUnitCategory, TargetUnitType )
|
||||
|
||||
else
|
||||
self:E("Hit unregistered scenery or static object - NO target! ("..TgtName..")")
|
||||
end
|
||||
--end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Check if there are Zones where the destruction happened.
|
||||
for ZoneName, ScoreZoneData in pairs( self.ScoringZones ) do
|
||||
self:F( { ScoringZone = ScoreZoneData } )
|
||||
local hit=Event.TgtUnit
|
||||
local ScoreZone = ScoreZoneData.ScoreZone -- Core.Zone#ZONE_BASE
|
||||
local Score = ScoreZoneData.Score
|
||||
if TargetUNIT and ScoreZone:IsVec2InZone( TargetUNIT:GetVec2() ) then
|
||||
-- A scenery or static got hit, score it.
|
||||
-- Player contains the score data from self.Players[WeaponPlayerName]
|
||||
local PlayerName = Event.IniPlayerName or "Ghost"
|
||||
local Player = self.Players[PlayerName]
|
||||
|
||||
Player.Score = Player.Score + Score
|
||||
Player.Score = Player.Score + self.ScoreIncrementOnHit
|
||||
MESSAGE:NewType( self.DisplayMessagePrefix .. "hit in zone '" .. ScoreZone:GetName() .. "'." ..
|
||||
"Player '" .. PlayerName .. "' receives an extra " .. Score .. " points! " .. "Total: " .. Player.Score - Player.Penalty,
|
||||
MESSAGE.Type.Information )
|
||||
:ToAllIf( self:IfMessagesZone() and self:IfMessagesToAll() )
|
||||
:ToCoalitionIf( InitCoalition, self:IfMessagesZone() and self:IfMessagesToCoalition() )
|
||||
|
||||
self:ScoreCSV( PlayerName, "", "HIT_SCORE", 1, Score, InitUnitName, InitUnitCoalition, InitUnitCategory, InitUnitType, TargetUnitName, "", "Zone", TargetUnitType )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
--- Track DEAD or CRASH events for the scoring.
|
||||
-- @param #SCORING self
|
||||
-- @param Core.Event#EVENTDATA Event
|
||||
@@ -1305,7 +1447,7 @@ function SCORING:_EventOnDeadOrCrash( Event )
|
||||
local Destroyed = false
|
||||
|
||||
-- What is the player destroying?
|
||||
if Player and Player.Hit and Player.Hit[TargetCategory] and Player.Hit[TargetCategory][TargetUnitName] and Player.Hit[TargetCategory][TargetUnitName].TimeStamp ~= 0 and (TargetUnit.BirthTime == nil or Player.Hit[TargetCategory][TargetUnitName].TimeStamp > TargetUnit.BirthTime) then -- Was there a hit for this unit for this player before registered???
|
||||
if Player and Player.Hit and Player.Hit[TargetCategory] and Player.Hit[TargetCategory][TargetUnitName] and Player.Hit[TargetCategory][TargetUnitName].TimeStamp ~= 0 and TargetUnit and (TargetUnit.BirthTime == nil or Player.Hit[TargetCategory][TargetUnitName].TimeStamp > TargetUnit.BirthTime) then -- Was there a hit for this unit for this player before registered???
|
||||
|
||||
local TargetThreatLevel = Player.Hit[TargetCategory][TargetUnitName].ThreatLevel
|
||||
local TargetThreatType = Player.Hit[TargetCategory][TargetUnitName].ThreatType
|
||||
|
||||
@@ -1132,7 +1132,7 @@
|
||||
-- specify an "Assignment". This can be later used to identify the request and take the right actions.
|
||||
--
|
||||
-- Once the request is processed, the @{#WAREHOUSE.OnAfterSelfRequest} function is called. This is where we hook in and postprocess the spawned assets.
|
||||
-- In particular, we use the @{AI.AI_Formation#AI_FORMATION} class to make some nice escorts for our carrier.
|
||||
-- In particular, we use the @{Functional.Formation#FORMATION} class to make some nice escorts for our carrier.
|
||||
--
|
||||
-- When the resue helo is spawned, we can check that this is the correct asset and make the helo go into formation with the carrier.
|
||||
-- Once the helo runs out of fuel, it will automatically return to the ship and land. For the warehouse, this means that the "cargo", i.e. the helicopter
|
||||
@@ -1175,7 +1175,7 @@
|
||||
--
|
||||
-- -- Define AI Formation object.
|
||||
-- -- Note that this has to be a global variable or the garbage collector will remove it for some reason!
|
||||
-- CarrierFormationLeft = AI_FORMATION:New(Mother, groupset, "Left Formation with Carrier", "Escort Carrier.")
|
||||
-- CarrierFormationLeft = FORMATION:New(Mother, groupset, "Left Formation with Carrier")
|
||||
--
|
||||
-- -- Formation parameters.
|
||||
-- CarrierFormationLeft:FormationLeftWing(200 ,50, 0, 0, 500, 50)
|
||||
@@ -1190,7 +1190,7 @@
|
||||
--
|
||||
-- -- Define AI Formation object.
|
||||
-- -- Note that this has to be a global variable or the garbage collector will remove it for some reason!
|
||||
-- CarrierFormationRight = AI_FORMATION:New(Mother, groupset, "Right Formation with Carrier", "Escort Carrier.")
|
||||
-- CarrierFormationRight = FORMATION:New(Mother, groupset, "Right Formation with Carrier")
|
||||
--
|
||||
-- -- Formation parameters.
|
||||
-- CarrierFormationRight:FormationRightWing(200 ,50, 0, 0, 500, 50)
|
||||
@@ -1208,7 +1208,7 @@
|
||||
-- group:StartUncontrolled()
|
||||
--
|
||||
-- -- Define AI Formation object.
|
||||
-- CarrierFormationHelo = AI_FORMATION:New(Mother, groupset, "Helo Formation with Carrier", "Fly Formation.")
|
||||
-- CarrierFormationHelo = FORMATION:New(Mother, groupset, "Helo Formation with Carrier")
|
||||
--
|
||||
-- -- Formation parameters.
|
||||
-- CarrierFormationHelo:FormationCenterWing(-150, 50, 20, 50, 100, 50)
|
||||
|
||||
@@ -85,6 +85,7 @@ __Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/ZoneGoalCargo.lua'
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/Tiresias.lua' )
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/Stratego.lua' )
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/ClientWatch.lua')
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/Formation.lua')
|
||||
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/Airboss.lua' )
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/RecoveryTanker.lua' )
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
--
|
||||
-- ===
|
||||
-- @module Navigation.Beacons
|
||||
-- @image NAVIGATION_Beacons.png
|
||||
-- @image MOOSE.JPG
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -43,6 +43,7 @@
|
||||
--
|
||||
-- **Note** that try to avoid hard coding stuff in Moose since DCS is updated frequently and things change. Therefore, the main source of information is either a file `beacons.lua` that can be
|
||||
-- found in the installation directory of DCS for each map or a table that the user needs to provide.
|
||||
-- **Note** your `MissionScripting` environment needs to be desanitized to read this data. `Package` als needs to be available.
|
||||
--
|
||||
-- # Basic Setup
|
||||
--
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
--
|
||||
-- ===
|
||||
-- @module Navigation.Point
|
||||
-- @image NAVIGATION_Point.png
|
||||
-- @image MOOSE.JPG
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
--
|
||||
-- ===
|
||||
-- @module Navigation.Radios
|
||||
-- @image NAVIGATION_Radios.png
|
||||
-- @image MOOSE.JPG
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -43,6 +43,7 @@
|
||||
--
|
||||
-- **Note** that try to avoid hard coding stuff in Moose since DCS is updated frequently and things change. Therefore, the main source of information is either a file `radio.lua` that can be
|
||||
-- found in the installation directory of DCS for each map or a table that the user needs to provide.
|
||||
-- **Note** your `MissionScripting` environment needs to be desanitized to read this data.
|
||||
--
|
||||
-- # Basic Setup
|
||||
--
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
--
|
||||
-- ===
|
||||
-- @module Navigation.Towns
|
||||
-- @image NAVIGATION_Towns.png
|
||||
-- @image MOOSE.JPG
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -43,6 +43,7 @@
|
||||
--
|
||||
-- **Note** that try to avoid hard coding stuff in Moose since DCS is updated frequently and things change. Therefore, the main source of information is either a file `towns.lua` that can be
|
||||
-- found in the installation directory of DCS for each map or a table that the user needs to provide.
|
||||
-- **Note** your `MissionScripting` environment needs to be desanitized to read this data.
|
||||
--
|
||||
-- # Basic Setup
|
||||
--
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
-- **Supported Aircraft:**
|
||||
--
|
||||
-- * [F/A-18C Hornet Lot 20](https://forums.eagle.ru/forumdisplay.php?f=557) (Player & AI)
|
||||
-- * [F-14A/B Tomcat](https://forums.eagle.ru/forumdisplay.php?f=395) (Player & AI)
|
||||
-- * [F-14A/B/A Early Tomcat](https://forums.eagle.ru/forumdisplay.php?f=395) (Player & AI)
|
||||
-- * [A-4E Skyhawk Community Mod](https://forums.eagle.ru/showthread.php?t=224989) (Player & AI)
|
||||
-- * [AV-8B N/A Harrier](https://forums.eagle.ru/forumdisplay.php?f=555) (Player & AI)
|
||||
-- * [T-45C Goshawk](https://forum.dcs.world/topic/203816-vnao-t-45-goshawk/) (VNAO mod) (Player & AI)
|
||||
@@ -63,7 +63,7 @@
|
||||
-- no other fixed wing aircraft (human or AI controlled) are supposed to land on these ships. Currently only Case I is supported. Case II/III take slightly different steps from the CVN carrier.
|
||||
-- However, if no offset is used for the holding radial this provides a very close representation of the V/STOL Case III, allowing for an approach to over the deck and a vertical landing.
|
||||
--
|
||||
-- Heatblur's mighty F-14B Tomcat has been added (March 13th 2019) as well. Same goes for the A version.
|
||||
-- Heatblur's mighty F-14A/B/A Early Tomcat has been added as well.
|
||||
--
|
||||
-- The [DCS Supercarriers](https://www.digitalcombatsimulator.com/de/shop/modules/supercarrier/) are also supported.
|
||||
--
|
||||
@@ -1276,6 +1276,7 @@ AIRBOSS = {
|
||||
-- @field #string A4EC A-4E Community mod.
|
||||
-- @field #string HORNET F/A-18C Lot 20 Hornet by Eagle Dynamics.
|
||||
-- @field #string F14A F-14A by Heatblur.
|
||||
-- @field #string F14A_Early F-14A-135-GR-Early by Heatblur.
|
||||
-- @field #string F14B F-14B by Heatblur.
|
||||
-- @field #string F14A_AI F-14A Tomcat (AI).
|
||||
-- @field #string FA18C F/A-18C Hornet (AI).
|
||||
@@ -1294,6 +1295,7 @@ AIRBOSS.AircraftCarrier={
|
||||
HORNET="FA-18C_hornet",
|
||||
A4EC="A-4E-C",
|
||||
F14A="F-14A-135-GR",
|
||||
F14A_Early="F-14A-135-GR-Early",
|
||||
F14B="F-14B",
|
||||
F14A_AI="F-14A",
|
||||
FA18C="F/A-18C",
|
||||
@@ -5473,7 +5475,7 @@ function AIRBOSS:_GetAircraftAoA( playerData )
|
||||
local goshawk = playerData.actype == AIRBOSS.AircraftCarrier.T45C
|
||||
local skyhawk = playerData.actype == AIRBOSS.AircraftCarrier.A4EC
|
||||
local harrier = playerData.actype == AIRBOSS.AircraftCarrier.AV8B
|
||||
local tomcat = playerData.actype == AIRBOSS.AircraftCarrier.F14A or playerData.actype == AIRBOSS.AircraftCarrier.F14B
|
||||
local tomcat = playerData.actype == AIRBOSS.AircraftCarrier.F14A or playerData.actype == AIRBOSS.AircraftCarrier.F14B or playerData.actype == AIRBOSS.AircraftCarrier.F14A_Early
|
||||
local corsair = playerData.actype == AIRBOSS.AircraftCarrier.CORSAIR or playerData.actype == AIRBOSS.AircraftCarrier.CORSAIR_CW
|
||||
|
||||
-- Table with AoA values.
|
||||
@@ -5552,7 +5554,7 @@ function AIRBOSS:_AoAUnit2Deg( playerData, aoaunits )
|
||||
local degrees = aoaunits
|
||||
|
||||
-- Check aircraft type of player.
|
||||
if playerData.actype == AIRBOSS.AircraftCarrier.F14A or playerData.actype == AIRBOSS.AircraftCarrier.F14B then
|
||||
if playerData.actype == AIRBOSS.AircraftCarrier.F14A or playerData.actype == AIRBOSS.AircraftCarrier.F14B or playerData.actype == AIRBOSS.AircraftCarrier.F14A_Early then
|
||||
|
||||
-------------
|
||||
-- F-14A/B --
|
||||
@@ -5595,7 +5597,7 @@ function AIRBOSS:_AoADeg2Units( playerData, degrees )
|
||||
local aoaunits = degrees
|
||||
|
||||
-- Check aircraft type of player.
|
||||
if playerData.actype == AIRBOSS.AircraftCarrier.F14A or playerData.actype == AIRBOSS.AircraftCarrier.F14B then
|
||||
if playerData.actype == AIRBOSS.AircraftCarrier.F14A or playerData.actype == AIRBOSS.AircraftCarrier.F14B or playerData.actype == AIRBOSS.AircraftCarrier.F14A_Early then
|
||||
|
||||
-------------
|
||||
-- F-14A/B --
|
||||
@@ -11593,7 +11595,7 @@ function AIRBOSS:_AttitudeMonitor( playerData )
|
||||
|
||||
local unitClient = Unit.getByName(unit:GetName()) -- VNAO Edit - Added
|
||||
local hornet = playerData.actype == AIRBOSS.AircraftCarrier.HORNET -- VNAO Edit - Added
|
||||
local tomcat = playerData.actype == AIRBOSS.AircraftCarrier.F14A or playerData.actype == AIRBOSS.AircraftCarrier.F14B -- VNAO Edit - Added
|
||||
local tomcat = playerData.actype == AIRBOSS.AircraftCarrier.F14A or playerData.actype == AIRBOSS.AircraftCarrier.F14B or playerData.actype == AIRBOSS.AircraftCarrier.F14A_Early -- VNAO Edit - Added
|
||||
|
||||
if hornet then -- VNAO Edit - Added
|
||||
local nozzlePosL = 0 -- VNAO Edit - Added
|
||||
@@ -11826,7 +11828,7 @@ function AIRBOSS:_NozzleArgumentLeft( unit ) -- VNAO Edit - Added
|
||||
else -- VNAO Edit - Added
|
||||
nozzlePosL = 0 -- VNAO Edit - Added
|
||||
end -- VNAO Edit - Added
|
||||
elseif typeName == "F-14A-135-GR" or typeName == "F-14B" then -- VNAO Edit - Added
|
||||
elseif typeName == "F-14A-135-GR" or typeName == "F-14B" or typeName == "F-14A-135-GR-Early" then -- VNAO Edit - Added
|
||||
nozzlePosL = unitClient:getDrawArgumentValue(434) -- VNAO Edit - Added
|
||||
end -- VNAO Edit - Added
|
||||
|
||||
@@ -11851,7 +11853,7 @@ function AIRBOSS:_NozzleArgumentRight( unit ) -- VNAO Edit - Added
|
||||
else -- VNAO Edit - Added
|
||||
nozzlePosR = 0 -- VNAO Edit - Added
|
||||
end -- VNAO Edit - Added
|
||||
elseif typeName == "F-14A-135-GR" or typeName == "F-14B" then -- VNAO Edit - Added
|
||||
elseif typeName == "F-14A-135-GR" or typeName == "F-14B" or typeName == "F-14A-135-GR-Early" then -- VNAO Edit - Added
|
||||
nozzlePosR = unitClient:getDrawArgumentValue(433) -- VNAO Edit - Added
|
||||
end -- VNAO Edit - Added
|
||||
return nozzlePosR -- VNAO Edit - Added
|
||||
@@ -15066,7 +15068,7 @@ function AIRBOSS:_GetACNickname( actype )
|
||||
nickname = "Hawkeye"
|
||||
elseif actype == AIRBOSS.AircraftCarrier.C2A then
|
||||
nickname = "Greyhound"
|
||||
elseif actype == AIRBOSS.AircraftCarrier.F14A_AI or actype == AIRBOSS.AircraftCarrier.F14A or actype == AIRBOSS.AircraftCarrier.F14B then
|
||||
elseif actype == AIRBOSS.AircraftCarrier.F14A_AI or actype == AIRBOSS.AircraftCarrier.F14A or actype == AIRBOSS.AircraftCarrier.F14B or actype == AIRBOSS.AircraftCarrier.F14A_Early then
|
||||
nickname = "Tomcat"
|
||||
elseif actype == AIRBOSS.AircraftCarrier.FA18C or actype == AIRBOSS.AircraftCarrier.HORNET then
|
||||
nickname = "Hornet"
|
||||
|
||||
@@ -2037,7 +2037,7 @@ function AUFTRAG:NewRESCUEHELO(Carrier)
|
||||
|
||||
-- Mission options:
|
||||
mission.missionTask=ENUMS.MissionTask.NOTHING
|
||||
mission.missionFraction=0.5
|
||||
mission.missionFraction=0.9
|
||||
mission.optionROE=ENUMS.ROE.WeaponHold
|
||||
mission.optionROT=ENUMS.ROT.NoReaction
|
||||
|
||||
|
||||
@@ -4308,7 +4308,27 @@ function OPSGROUP:_UpdateTask(Task, Mission)
|
||||
Mission=Mission or self:GetMissionByTaskID(self.taskcurrent)
|
||||
|
||||
if Task.dcstask.id==AUFTRAG.SpecialTask.FORMATION then
|
||||
|
||||
|
||||
if Mission.type == AUFTRAG.Type.RESCUEHELO then
|
||||
self:T("**********")
|
||||
self:T("** RESCUEHELO USED")
|
||||
self:T("**********")
|
||||
local param=Task.dcstask.params
|
||||
local followUnit=UNIT:FindByName(param.unitname)
|
||||
local helogroupname = self:GetGroup():GetName()
|
||||
Task.formation = RESCUEHELO:New(followUnit,helogroupname)
|
||||
Task.formation:SetRespawnOnOff(false)
|
||||
Task.formation.respawninair=false
|
||||
Task.formation:SetTakeoffCold()
|
||||
Task.formation:SetHomeBase(followUnit)
|
||||
Task.formation.helo = self:GetGroup()
|
||||
-- Start formation FSM.
|
||||
Task.formation:Start()
|
||||
if self:IsFlightgroup() then
|
||||
self:SetDespawnAfterLanding()
|
||||
end
|
||||
else
|
||||
|
||||
-- Set of group(s) to follow Mother.
|
||||
local followSet=SET_GROUP:New():AddGroup(self.group)
|
||||
|
||||
@@ -4317,7 +4337,7 @@ function OPSGROUP:_UpdateTask(Task, Mission)
|
||||
local followUnit=UNIT:FindByName(param.unitname)
|
||||
|
||||
-- Define AI Formation object.
|
||||
Task.formation=AI_FORMATION:New(followUnit, followSet, AUFTRAG.SpecialTask.FORMATION, "Follow X at given parameters.")
|
||||
Task.formation=FORMATION:New(followUnit, followSet, AUFTRAG.SpecialTask.FORMATION)
|
||||
|
||||
-- Formation parameters.
|
||||
Task.formation:FormationCenterWing(-param.offsetX, 50, math.abs(param.altitude), 50, param.offsetZ, 50)
|
||||
@@ -4326,11 +4346,13 @@ function OPSGROUP:_UpdateTask(Task, Mission)
|
||||
Task.formation:SetFollowTimeInterval(param.dtFollow)
|
||||
|
||||
-- Formation mode.
|
||||
Task.formation:SetFlightModeFormation(self.group)
|
||||
--Task.formation:SetFlightModeFormation(self.group)
|
||||
|
||||
-- Start formation FSM.
|
||||
Task.formation:Start()
|
||||
|
||||
|
||||
end
|
||||
|
||||
elseif Task.dcstask.id==AUFTRAG.SpecialTask.PATROLZONE then
|
||||
|
||||
---
|
||||
@@ -8026,11 +8048,16 @@ function OPSGROUP:onafterDead(From, Event, To)
|
||||
-- Get asset.
|
||||
local asset=self.legion:GetAssetByName(self.groupname)
|
||||
|
||||
if asset then
|
||||
|
||||
-- Get request.
|
||||
local request=self.legion:GetRequestByID(asset.rid)
|
||||
|
||||
-- Trigger asset dead event.
|
||||
self.legion:AssetDead(asset, request)
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- Stop in 5 sec to give possible respawn attempts a chance.
|
||||
@@ -12723,7 +12750,7 @@ end
|
||||
-- @return #OPSGROUP self
|
||||
function OPSGROUP:SetDefaultCallsign(CallsignName, CallsignNumber)
|
||||
|
||||
self:T(self.lid..string.format("Setting Default callsing %s-%s", tostring(CallsignName), tostring(CallsignNumber)))
|
||||
self:T(self.lid..string.format("Setting Default callsign %s-%s", tostring(CallsignName), tostring(CallsignNumber)))
|
||||
|
||||
self.callsignDefault={} --#OPSGROUP.Callsign
|
||||
self.callsignDefault.NumberSquad=CallsignName
|
||||
@@ -13482,8 +13509,8 @@ function OPSGROUP:GetAmmoUnit(unit, display)
|
||||
if ammotable then
|
||||
local weapons=#ammotable
|
||||
|
||||
--self:I(ammotable)
|
||||
--UTILS.PrintTableToLog(ammotable)
|
||||
--self:I(ammotable)
|
||||
--UTILS.PrintTableToLog(ammotable)
|
||||
|
||||
-- Loop over all weapons.
|
||||
for w=1,weapons do
|
||||
@@ -13491,9 +13518,9 @@ function OPSGROUP:GetAmmoUnit(unit, display)
|
||||
-- Number of current weapon.
|
||||
local Nammo=ammotable[w]["count"]
|
||||
|
||||
-- Range in meters. Seems only to exist for missiles (not shells).
|
||||
local rmin=ammotable[w]["desc"]["rangeMin"] or 0
|
||||
local rmax=ammotable[w]["desc"]["rangeMaxAltMin"] or 0
|
||||
-- Range in meters. Seems only to exist for missiles (not shells).
|
||||
local rmin=ammotable[w]["desc"]["rangeMin"] or 0
|
||||
local rmax=ammotable[w]["desc"]["rangeMaxAltMin"] or 0
|
||||
|
||||
-- Type name of current weapon.
|
||||
local Tammo=ammotable[w]["desc"]["typeName"]
|
||||
@@ -13515,7 +13542,7 @@ function OPSGROUP:GetAmmoUnit(unit, display)
|
||||
|
||||
-- Add up all shells.
|
||||
nshells=nshells+Nammo
|
||||
|
||||
|
||||
-- Add small and large caliber shells for guns and cannons
|
||||
if ammotable[w]["desc"]["warhead"] and ammotable[w]["desc"]["warhead"]["caliber"] then
|
||||
local caliber=ammotable[w]["desc"]["warhead"]["caliber"]
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **funkyfranky**
|
||||
-- ### Contributions: Flightcontrol (@{AI.AI_Formation} class being used here)
|
||||
--
|
||||
-- @module Ops.RescueHelo
|
||||
-- @image Ops_RescueHelo.png
|
||||
@@ -37,7 +36,7 @@
|
||||
-- @field #number takeoff Takeoff type.
|
||||
-- @field Wrapper.Airbase#AIRBASE airbase The airbase object acting as home base of the helo.
|
||||
-- @field Core.Set#SET_GROUP followset Follow group set.
|
||||
-- @field AI.AI_Formation#AI_FORMATION formation AI_FORMATION object.
|
||||
-- @field Functional.Formation#FORMATION formation FORMATION object.
|
||||
-- @field #number lowfuel Low fuel threshold of helo in percent.
|
||||
-- @field #number altitude Altitude of helo in meters.
|
||||
-- @field #number offsetX Offset in meters to carrier in longitudinal direction.
|
||||
@@ -235,7 +234,7 @@ _RESCUEHELOID=0
|
||||
|
||||
--- Class version.
|
||||
-- @field #string version
|
||||
RESCUEHELO.version="1.1.0"
|
||||
RESCUEHELO.version="1.2.0"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- TODO list
|
||||
@@ -248,6 +247,7 @@ RESCUEHELO.version="1.1.0"
|
||||
-- DONE: Possibility to add already present/spawned aircraft, e.g. for warehouse.
|
||||
-- DONE: Add rescue event when aircraft crashes.
|
||||
-- DONE: Make offset input parameter.
|
||||
-- DONE: Make useable for AUFTRAG
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Constructor
|
||||
@@ -337,6 +337,9 @@ function RESCUEHELO:New(carrierunit, helogroupname)
|
||||
self:AddTransition("*", "Status", "*")
|
||||
self:AddTransition("*", "Stop", "Stopped")
|
||||
|
||||
|
||||
self:I(self.lid.."Started.")
|
||||
|
||||
|
||||
--- Triggers the FSM event "Start" that starts the rescue helo. Initializes parameters and starts event handlers.
|
||||
-- @function [parent=#RESCUEHELO] Start
|
||||
@@ -871,15 +874,25 @@ function RESCUEHELO:onafterStart(From, Event, To)
|
||||
|
||||
-- Delay before formation is started.
|
||||
local delay=120
|
||||
|
||||
-- Spawn helo. We need to introduce an alias in case this class is used twice. This would confuse the spawn routine.
|
||||
local Spawn=SPAWN:NewWithAlias(self.helogroupname, self.alias)
|
||||
|
||||
-- Set modex for spawn.
|
||||
Spawn:InitModex(self.modex)
|
||||
|
||||
local UsesAliveGroup=false
|
||||
local Spawn = GROUP:FindByName(self.helogroupname)
|
||||
if Spawn and Spawn:IsAlive() then
|
||||
self.helo=Spawn
|
||||
UsesAliveGroup = true
|
||||
delay = 1
|
||||
else
|
||||
|
||||
-- Spawn helo. We need to introduce an alias in case this class is used twice. This would confuse the spawn routine.
|
||||
local Spawn=SPAWN:NewWithAlias(self.helogroupname, self.alias)
|
||||
|
||||
-- Set modex for spawn.
|
||||
Spawn:InitModex(self.modex)
|
||||
|
||||
end
|
||||
|
||||
-- Spawn in air or at airbase.
|
||||
if self.takeoff==SPAWN.Takeoff.Air then
|
||||
if UsesAliveGroup==false and self.takeoff==SPAWN.Takeoff.Air then
|
||||
|
||||
-- Carrier heading
|
||||
local hdg=self.carrier:GetHeading()
|
||||
@@ -899,7 +912,7 @@ function RESCUEHELO:onafterStart(From, Event, To)
|
||||
-- Start formation in 1 seconds
|
||||
delay=1
|
||||
|
||||
else
|
||||
elseif UsesAliveGroup==false and self.uncontrolledac then
|
||||
|
||||
-- Check if an uncontrolled helo group was requested.
|
||||
if self.uncontrolledac then
|
||||
@@ -919,9 +932,9 @@ function RESCUEHELO:onafterStart(From, Event, To)
|
||||
-- No group of that name!
|
||||
self:E(string.format("ERROR: No uncontrolled (alive) rescue helo group with name %s could be found!", self.helogroupname))
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
else
|
||||
elseif UsesAliveGroup==false then
|
||||
|
||||
-- Spawn at airbase.
|
||||
self.helo=Spawn:SpawnAtAirbase(self.airbase, self.takeoff, nil, AIRBASE.TerminalType.HelicopterUsable)
|
||||
@@ -947,17 +960,13 @@ function RESCUEHELO:onafterStart(From, Event, To)
|
||||
self.HeloFuel0=self.helo:GetFuel()
|
||||
|
||||
-- Define AI Formation object.
|
||||
self.formation=AI_FORMATION:New(self.carrier, self.followset, "Helo Formation with Carrier", "Follow Carrier at given parameters.")
|
||||
|
||||
self.formation=FORMATION:New(self.carrier, self.followset, "Helo Formation with Carrier")
|
||||
-- Formation parameters.
|
||||
self.formation:FormationCenterWing(-self.offsetX, 50, math.abs(self.altitude), 50, self.offsetZ, 50)
|
||||
|
||||
-- Set follow time interval.
|
||||
self.formation:SetFollowTimeInterval(self.dtFollow)
|
||||
|
||||
-- Formation mode.
|
||||
self.formation:SetFlightModeFormation(self.helo)
|
||||
|
||||
-- Start formation FSM.
|
||||
self.formation:__Start(delay)
|
||||
|
||||
|
||||
@@ -5236,3 +5236,116 @@ function UTILS.ValidateAndRepositionStatic(Country, Category, Type, Position, Sh
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
---
|
||||
-- This function can be used to scan all airdromes of a map and write the Moose enums to a file.
|
||||
function UTILS.CreateAirbaseEnum()
|
||||
|
||||
-- Save file function
|
||||
local function _savefile( filename, data )
|
||||
local file=lfs.writedir() .. filename
|
||||
local f = io.open(file , "wb")
|
||||
if f then
|
||||
f:write( data )
|
||||
f:close()
|
||||
env.info(string.format("Saving to file %s", tostring(file) ))
|
||||
else
|
||||
env.info(string.format("ERROR: Could not save results to file %s", tostring(file) ))
|
||||
end
|
||||
end
|
||||
|
||||
-- Get all airbases
|
||||
local airbases=world.getAirbases()
|
||||
|
||||
-- Get map name
|
||||
local mapname=env.mission.theatre
|
||||
|
||||
-- Put airbases in a table
|
||||
local myab={}
|
||||
for i,_airbase in pairs(airbases) do
|
||||
local airbase=_airbase --DCS#Airbase
|
||||
|
||||
|
||||
local cat=airbase:getDesc().category
|
||||
|
||||
if cat==Airbase.Category.AIRDROME then
|
||||
|
||||
-- Get airbase name
|
||||
local name=airbase:getName()
|
||||
|
||||
-- Key is the name with illigal characters replaced
|
||||
local key=name
|
||||
|
||||
-- Germany map specifics
|
||||
if name=="Airracing Lubeck" then
|
||||
key="Airracing_Luebeck"
|
||||
elseif name=="Bad Durkheim" then
|
||||
key="Bad_Duerkheim"
|
||||
elseif name=="Buchel" then
|
||||
key="Buechel"
|
||||
elseif name=="Buckeburg" then
|
||||
key="Bueckeburg"
|
||||
elseif name=="Dusseldorf" then
|
||||
key="Duesseldorf"
|
||||
elseif name=="Gutersloh" then
|
||||
key="Guetersloh"
|
||||
elseif name=="Kothen" then
|
||||
key="Koethen"
|
||||
elseif name=="Larz" then
|
||||
key="Laerz"
|
||||
elseif name=="Lubeck" then
|
||||
key="Luebeck"
|
||||
elseif name=="Luneburg" then
|
||||
key="Lueneburg"
|
||||
elseif name=="Norvenich" then
|
||||
key="Noervenich"
|
||||
elseif name=="Ober-Morlen" then
|
||||
key="Ober_Moerlen"
|
||||
elseif name=="Peenemunde" then
|
||||
key="Peenemuende"
|
||||
elseif name=="Pottschutthohe" then
|
||||
key="Pottschutthoehe"
|
||||
elseif name=="Schonefeld" then
|
||||
key="Schoenefeld"
|
||||
elseif name=="Weser Wumme" then
|
||||
key="Weser_Wuemme"
|
||||
elseif name=="Zollschen" then
|
||||
key="Zoellschen"
|
||||
elseif name=="Zweibrucken" then
|
||||
key="Zweibruecken"
|
||||
end
|
||||
|
||||
-- Replace blanks, hyphens by underscores
|
||||
key=key:gsub(" ", "_")
|
||||
key=key:gsub("-", "_")
|
||||
key=key:gsub("'", "_")
|
||||
key=UTILS.ReplaceIllegalCharacters(key, "_")
|
||||
|
||||
local entry={}
|
||||
entry.key=key
|
||||
entry.name=name
|
||||
table.insert(myab, entry)
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- Sort by name
|
||||
table.sort(myab, function(a,b) return a.name < b.name end)
|
||||
|
||||
local text=string.format("\n--- Airbases of the %s map", mapname)
|
||||
text=text.."\n--"
|
||||
for _,ab in pairs(myab) do
|
||||
text=text..string.format("\n-- * `AIRBASE.%s.%s` %s", mapname, ab.key, ab.name)
|
||||
end
|
||||
text=text.."\n--"
|
||||
text=text..string.format("\n-- @field %s", mapname)
|
||||
text=text..string.format("\nAIRBASE.%s = {", mapname)
|
||||
for _,ab in pairs(myab) do
|
||||
text=text..string.format('\n\t["%s"] = "%s",', ab.key, ab.name)
|
||||
end
|
||||
text=text.."\n}"
|
||||
|
||||
_savefile(string.format("%s-enums.txt", env.mission.theatre), text)
|
||||
--env.info(text)
|
||||
end
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -409,7 +409,7 @@ function CONTROLLABLE:SetTask( DCSTask, WaitTime )
|
||||
local Controller = self:_GetController()
|
||||
-- self:I( "Before SetTask" )
|
||||
Controller:setTask( DCSTask )
|
||||
-- AI_FORMATION class (used by RESCUEHELO) calls SetTask twice per second! hence spamming the DCS log file ==> setting this to trace.
|
||||
-- FORMATION class (used by RESCUEHELO) calls SetTask twice per second! hence spamming the DCS log file ==> setting this to trace.
|
||||
self:T( { ControllableName = self:GetName(), DCSTask = DCSTask } )
|
||||
else
|
||||
BASE:E( { DCSControllableName .. " is not alive anymore.", DCSTask = DCSTask } )
|
||||
|
||||
@@ -18,7 +18,13 @@
|
||||
-- @field #string SceneryName Name of the scenery object.
|
||||
-- @field DCS#Object SceneryObject DCS scenery object.
|
||||
-- @field #number Life0 Initial life points.
|
||||
-- @field #table Properties
|
||||
-- @field #table Properties.
|
||||
-- @field #number ID.
|
||||
-- @field Core.Zone#ZONE_POLYGON SceneryZone.
|
||||
-- @field Core.Point#COORDINATE Coordinate.
|
||||
-- @field DCS#Vec2 Vec2.
|
||||
-- @field DCS#Vec3 Vec3.
|
||||
-- @field Core.Vector#VECTOR Vector.
|
||||
-- @extends Wrapper.Positionable#POSITIONABLE
|
||||
|
||||
|
||||
@@ -35,27 +41,79 @@ SCENERY = {
|
||||
ClassName = "SCENERY",
|
||||
}
|
||||
|
||||
_SCENERY = {}
|
||||
|
||||
--- Register scenery object as POSITIONABLE.
|
||||
--@param #SCENERY self
|
||||
--@param #string SceneryName Scenery name.
|
||||
--@param DCS#Object SceneryObject DCS scenery object.
|
||||
--@param Core.Zone#ZONE_POLYGON SceneryZone (optional) The zone object.
|
||||
--@return #SCENERY Scenery object.
|
||||
function SCENERY:Register( SceneryName, SceneryObject )
|
||||
|
||||
function SCENERY:Register( SceneryName, SceneryObject, SceneryZone )
|
||||
|
||||
local ID = (SceneryObject and SceneryObject.getID) and SceneryObject:getID() or SceneryName
|
||||
|
||||
if _SCENERY[ID] and _SCENERY[ID].SceneryObject == nil then
|
||||
|
||||
_SCENERY[ID].SceneryObject=SceneryObject
|
||||
SCENERY._UpdateFromDCSObject(_SCENERY[ID])
|
||||
|
||||
end
|
||||
|
||||
if _SCENERY[ID] then return _SCENERY[ID] end
|
||||
|
||||
local self = BASE:Inherit( self, POSITIONABLE:New( SceneryName ) )
|
||||
|
||||
self.SceneryName = tostring(SceneryName)
|
||||
|
||||
self.ID = ID
|
||||
self.SceneryObject = SceneryObject
|
||||
self.SceneryZone = SceneryZone
|
||||
|
||||
if SceneryZone then
|
||||
self.Vec3 = SceneryZone:GetVec3()
|
||||
self.Vec2 = SceneryZone:GetVec2()
|
||||
self.Vector = (self.Vec3 and VECTOR) and VECTOR:NewFromVec(self.Vec3) or nil
|
||||
end
|
||||
|
||||
if SceneryObject then
|
||||
local vec3 = SceneryObject:getPoint()
|
||||
self.Vec3 = { x = vec3.x, y = vec3.y, z = vec3.z }
|
||||
self.Vec2 = { x = vec3.x, y = vec3.z }
|
||||
self.Vector = (self.Vec3 and VECTOR) and VECTOR:NewFromVec(self.Vec3) or nil
|
||||
end
|
||||
|
||||
if self.SceneryObject and self.SceneryObject.getLife then -- fix some objects do not have all functions
|
||||
self.Life0 = self.SceneryObject:getLife() or 0
|
||||
self.Life0 = self.SceneryObject:getLife() or 1
|
||||
else
|
||||
self.Life0 = 0
|
||||
self.Life0 = 1
|
||||
end
|
||||
|
||||
self.Properties = {}
|
||||
|
||||
_SCENERY[self.ID] = self
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- [INTERNAL] Update data
|
||||
-- @param Wrapper.Scenery#SCENERY Scenery The object to update.
|
||||
function SCENERY._UpdateFromDCSObject(Scenery)
|
||||
env.info("APPLE _UpdateFromDCSObject "..tostring(Scenery.SceneryName))
|
||||
local self=Scenery
|
||||
if self.Vec2 == nil and self.SceneryObject ~= nil then
|
||||
self.Vec3 = self.SceneryObject:getPoint()
|
||||
if self.Vec3 then
|
||||
self.Vec2 = {x=self.Vec3.x,y=self.Vec3.z}
|
||||
self.Vector = VECTOR:NewFromVec(self.Vec3)
|
||||
end
|
||||
end
|
||||
if not self.Life0 or self.Life0 == 1 then
|
||||
if self.SceneryObject and self.SceneryObject.getLife() then
|
||||
self.Life = self.SceneryObject:getLife() or 1
|
||||
self.Life0 = self.Life
|
||||
end
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -99,6 +157,39 @@ function SCENERY:GetName()
|
||||
return self.SceneryName
|
||||
end
|
||||
|
||||
--- Obtain object coordinate.
|
||||
--@param #SCENERY self
|
||||
--@return Core.Point#COORDINATE Coordinate
|
||||
function SCENERY:GetCoordinate()
|
||||
if self.Coordinate then
|
||||
return self.Coordinate
|
||||
elseif self.Vec3 then
|
||||
self.Coordinate = COORDINATE:NewFromVec3(self.Vec3):SetAlt()
|
||||
end
|
||||
return self.Coordinate
|
||||
end
|
||||
|
||||
--- Obtain object coordinate.
|
||||
--@param #SCENERY self
|
||||
--@return DCS#Vec3 Vec3
|
||||
function SCENERY:GetVec3()
|
||||
return self.Vec3
|
||||
end
|
||||
|
||||
--- Obtain object coordinate.
|
||||
--@param #SCENERY self
|
||||
--@return DCS#Vec2 Vec2
|
||||
function SCENERY:GetVec2()
|
||||
return self.Vec2
|
||||
end
|
||||
|
||||
--- Obtain object coordinate.
|
||||
--@param #SCENERY self
|
||||
--@return Core.Vector#VECTOR Vector
|
||||
function SCENERY:GetVector()
|
||||
return self.Vector
|
||||
end
|
||||
|
||||
--- Obtain DCS Object from the SCENERY Object.
|
||||
--@param #SCENERY self
|
||||
--@return DCS#Object DCS scenery object.
|
||||
@@ -106,6 +197,13 @@ function SCENERY:GetDCSObject()
|
||||
return self.SceneryObject
|
||||
end
|
||||
|
||||
--- Obtain object ID.
|
||||
--@param #SCENERY self
|
||||
--@return #string Name
|
||||
function SCENERY:GetID()
|
||||
return self.ID
|
||||
end
|
||||
|
||||
--- Get current life points from the SCENERY Object. Note - Some scenery objects always have 0 life points.
|
||||
-- **CAVEAT**: Some objects change their life value or "hitpoints" **after** the first hit. Hence we will adjust the life0 value to 120%
|
||||
-- of the last life value if life exceeds life0 (initial life) at any point. Thus will will get a smooth percentage decrease, if you use this e.g. as success
|
||||
@@ -113,12 +211,14 @@ end
|
||||
--@param #SCENERY self
|
||||
--@return #number life
|
||||
function SCENERY:GetLife()
|
||||
local life = 0
|
||||
local life = 1
|
||||
if self.SceneryObject and self.SceneryObject.getLife then
|
||||
life = self.SceneryObject:getLife()
|
||||
if life > self.Life0 then
|
||||
self.Life0 = math.floor(life * 1.2)
|
||||
end
|
||||
elseif self.Life then
|
||||
life = self.Life
|
||||
end
|
||||
return life
|
||||
end
|
||||
@@ -176,12 +276,19 @@ end
|
||||
--- Find a SCENERY object from its name or id. Since SCENERY isn't registered in the Moose database (just too many objects per map), we need to do a scan first
|
||||
-- to find the correct object.
|
||||
--@param #SCENERY self
|
||||
--@param #string Name The name/id of the scenery object as taken from the ME. Ex. '595785449'
|
||||
--@param Core.Point#COORDINATE Coordinate Where to find the scenery object
|
||||
--@param #number Radius (optional) Search radius around coordinate, defaults to 100
|
||||
--@return #SCENERY Scenery Object or `nil` if it cannot be found
|
||||
function SCENERY:FindByName(Name, Coordinate, Radius, Role)
|
||||
|
||||
--@param #string Name The name/id of the scenery object as taken from the ME. Ex. '595785449'.
|
||||
--@param Core.Point#COORDINATE Coordinate Where to find the scenery object.
|
||||
--@param #number Radius (optional) Search radius around coordinate, defaults to 100.
|
||||
--@param #string Role (optional) The role if set on the zone object.
|
||||
--@param Core.Zone#ZONE_POLYGON Zone (optional) The Zone where the scenery is located.
|
||||
--@return #SCENERY Scenery Object or `nil` if it cannot be found.
|
||||
function SCENERY:FindByName(Name, Coordinate, Radius, Role, Zone)
|
||||
|
||||
--BASE:I("Coordinate x = "..Coordinate.x .. " y = "..Coordinate.y.." z = "..Coordinate.z)
|
||||
|
||||
local findme = self:_FindByName(Name)
|
||||
if findme then return findme end
|
||||
|
||||
local radius = Radius or 100
|
||||
local name = Name or "unknown"
|
||||
local scenery = nil
|
||||
@@ -193,12 +300,13 @@ function SCENERY:FindByName(Name, Coordinate, Radius, Role)
|
||||
local function SceneryScan(scoordinate, sradius, sname)
|
||||
if scoordinate ~= nil then
|
||||
local Vec2 = scoordinate:GetVec2()
|
||||
local scanzone = ZONE_RADIUS:New("Zone-"..sname,Vec2,sradius,true)
|
||||
local scanzone = ZONE_RADIUS:New("Zone-"..sname,Vec2,sradius)
|
||||
scanzone:Scan({Object.Category.SCENERY})
|
||||
local scanned = scanzone:GetScannedSceneryObjects()
|
||||
local rscenery = nil -- Wrapper.Scenery#SCENERY
|
||||
for _,_scenery in pairs(scanned) do
|
||||
local scenery = _scenery -- Wrapper.Scenery#SCENERY
|
||||
--BASE:I({tostring(scenery.SceneryName),tostring(sname)})
|
||||
if tostring(scenery.SceneryName) == tostring(sname) then
|
||||
rscenery = scenery
|
||||
if Role then rscenery:SetProperty("ROLE",Role) end
|
||||
@@ -211,13 +319,36 @@ function SCENERY:FindByName(Name, Coordinate, Radius, Role)
|
||||
end
|
||||
|
||||
if Coordinate then
|
||||
--BASE:I("Coordinate Scenery Scan")
|
||||
scenery = SceneryScan(Coordinate, radius, name)
|
||||
end
|
||||
|
||||
|
||||
if not scenery then scenery = SCENERY:Register(Name,nil,Zone) end
|
||||
|
||||
return scenery
|
||||
end
|
||||
|
||||
--- Find a SCENERY object that was previously registered(!) by it's ID.
|
||||
-- @param #SCENERY self
|
||||
-- @param #number ID
|
||||
-- @return Wrapper.Scenery#SCENERY Scenery or nil if it could not be found
|
||||
function SCENERY:FindByID(ID)
|
||||
return _SCENERY[ID]
|
||||
end
|
||||
|
||||
--- Find a SCENERY object that was previously registered(!) by it's name.
|
||||
-- @param #SCENERY self
|
||||
-- @param #string Name
|
||||
-- @return Wrapper.Scenery#SCENERY Scenery or nil if it could not be found
|
||||
function SCENERY:_FindByName(Name)
|
||||
for _id,_object in pairs(_SCENERY) do
|
||||
if _object and _object.GetName and _object:GetName() then
|
||||
local name = _object:GetName()
|
||||
if Name == name then return _object end
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Find a SCENERY object from its name or id. Since SCENERY isn't registered in the Moose database (just too many objects per map), we need to do a scan first
|
||||
-- to find the correct object.
|
||||
--@param #SCENERY self
|
||||
@@ -231,8 +362,8 @@ function SCENERY:FindByNameInZone(Name, Zone, Radius)
|
||||
if type(Zone) == "string" then
|
||||
Zone = ZONE:FindByName(Zone)
|
||||
end
|
||||
local coordinate = Zone:GetCoordinate()
|
||||
return self:FindByName(Name,coordinate,Radius,Zone:GetProperty("ROLE"))
|
||||
local coordinate = Zone:GetCoordinate():SetAlt()
|
||||
return self:FindByName(Name,coordinate,Radius,Zone:GetProperty("ROLE"),Zone)
|
||||
end
|
||||
|
||||
--- Find a SCENERY object from its zone name. Since SCENERY isn't registered in the Moose database (just too many objects per map), we need to do a scan first
|
||||
@@ -241,14 +372,18 @@ end
|
||||
--@param #string ZoneName The name of the scenery zone as created with a right-click on the map in the mission editor and select "assigned to...". Can be handed over as ZONE object.
|
||||
--@return #SCENERY First found Scenery Object or `nil` if it cannot be found
|
||||
function SCENERY:FindByZoneName( ZoneName )
|
||||
--BASE:I(ZoneName)
|
||||
|
||||
local zone = ZoneName -- Core.Zone#ZONE_BASE
|
||||
|
||||
if type(ZoneName) == "string" then
|
||||
zone = ZONE:FindByName(ZoneName) -- Core.Zone#ZONE_POLYGON
|
||||
end
|
||||
|
||||
local _id = zone:GetProperty('OBJECT ID')
|
||||
--local properties = zone:GetAllProperties() or {}
|
||||
--BASE:I(string.format("Object ID is: %s",_id or "none"))
|
||||
--BASE:T("Object ID ".._id)
|
||||
|
||||
--BASE:I("Object ID ".._id)
|
||||
|
||||
if not _id then
|
||||
-- this zone has no object ID
|
||||
BASE:E("**** Zone without object ID: "..ZoneName.." | Type: "..tostring(zone.ClassName))
|
||||
@@ -257,23 +392,27 @@ function SCENERY:FindByZoneName( ZoneName )
|
||||
local scanned = zone:GetScannedSceneryObjects()
|
||||
for _,_scenery in (scanned) do
|
||||
local scenery = _scenery -- Wrapper.Scenery#SCENERY
|
||||
if scenery:IsAlive() then
|
||||
--if scenery:IsAlive() then
|
||||
local role = zone:GetProperty("ROLE")
|
||||
if role then scenery:SetProperty("ROLE",role) end
|
||||
return scenery
|
||||
end
|
||||
--end
|
||||
end
|
||||
return nil
|
||||
else
|
||||
return self:FindByName(_id, zone:GetCoordinate(),nil,zone:GetProperty("ROLE"))
|
||||
local coordinate = zone:GetCoordinate()
|
||||
coordinate:SetAlt()
|
||||
return self:FindByName(_id, coordinate,nil,zone:GetProperty("ROLE"),zone)
|
||||
end
|
||||
else
|
||||
return self:FindByName(_id, zone:GetCoordinate(),nil,zone:GetProperty("ROLE"))
|
||||
local coordinate = zone:GetCoordinate()
|
||||
coordinate:SetAlt()
|
||||
return self:FindByName(_id, coordinate,nil,zone:GetProperty("ROLE"),zone)
|
||||
end
|
||||
end
|
||||
|
||||
--- Scan and find all SCENERY objects from a zone by zone-name. Since SCENERY isn't registered in the Moose database (just too many objects per map), we need to do a scan first
|
||||
-- to find the correct object.
|
||||
-- to find the correct object. Might return nil!
|
||||
--@param #SCENERY self
|
||||
--@param #string ZoneName The name of the zone, can be handed as ZONE_RADIUS or ZONE_POLYGON object
|
||||
--@return #table of SCENERY Objects, or `nil` if nothing found
|
||||
@@ -295,7 +434,7 @@ function SCENERY:FindAllByZoneName( ZoneName )
|
||||
return nil
|
||||
end
|
||||
else
|
||||
local obj = self:FindByName(_id, zone:GetCoordinate(),nil,zone:GetProperty("ROLE"))
|
||||
local obj = self:FindByName(_id, zone:GetCoordinate():SetAlt(),nil,zone:GetProperty("ROLE"), zone)
|
||||
if obj then
|
||||
return {obj}
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user