mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-10-29 16:58:06 +00:00
Merge branch 'FF/Ops' into FF/OpsDev
This commit is contained in:
8
.github/workflows/build-includes.yml
vendored
8
.github/workflows/build-includes.yml
vendored
@@ -95,10 +95,6 @@ jobs:
|
|||||||
export COMMIT_TIME=$(git show -s --format=%cd ${{ github.sha }} --date=iso-strict)
|
export COMMIT_TIME=$(git show -s --format=%cd ${{ github.sha }} --date=iso-strict)
|
||||||
lua5.3 "./Moose Setup/Moose_Create.lua" D "$COMMIT_TIME-${{ github.sha }}" "./Moose Development/Moose" "./Moose Setup" "./build/result/Moose_Include_Dynamic"
|
lua5.3 "./Moose Setup/Moose_Create.lua" D "$COMMIT_TIME-${{ github.sha }}" "./Moose Development/Moose" "./Moose Setup" "./build/result/Moose_Include_Dynamic"
|
||||||
|
|
||||||
- name: Run LuaSrcDiet
|
|
||||||
run: |
|
|
||||||
luasrcdiet --basic --opt-emptylines ./build/result/Moose_Include_Static/Moose.lua -o ./build/result/Moose_Include_Static/Moose_.lua
|
|
||||||
|
|
||||||
#########################################################################
|
#########################################################################
|
||||||
# Run LuaCheck
|
# Run LuaCheck
|
||||||
#########################################################################
|
#########################################################################
|
||||||
@@ -108,6 +104,10 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
luacheck --std=lua51c --config=.luacheckrc -gurasqq "Moose Development/Moose"
|
luacheck --std=lua51c --config=.luacheckrc -gurasqq "Moose Development/Moose"
|
||||||
|
|
||||||
|
- name: Run LuaSrcDiet
|
||||||
|
run: |
|
||||||
|
luasrcdiet --basic --opt-emptylines ./build/result/Moose_Include_Static/Moose.lua -o ./build/result/Moose_Include_Static/Moose_.lua
|
||||||
|
|
||||||
#########################################################################
|
#########################################################################
|
||||||
# Push to MOOSE_INCLUDE
|
# Push to MOOSE_INCLUDE
|
||||||
#########################################################################
|
#########################################################################
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
--
|
--
|
||||||
-- ## Missions:
|
-- ## Missions:
|
||||||
--
|
--
|
||||||
-- [AID-A2A - AI A2A Dispatching](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AID%20-%20AI%20Dispatching/AID-A2A%20-%20AI%20A2A%20Dispatching)
|
-- [AID-A2A - AI A2A Dispatching](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AI/AI_A2A_Dispatcher)
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
@@ -310,7 +310,7 @@ do -- AI_A2A_DISPATCHER
|
|||||||
-- Use the method @{#AI_A2A_DISPATCHER.SetEngageRadius}() to set a specific Engage Radius.
|
-- Use the method @{#AI_A2A_DISPATCHER.SetEngageRadius}() to set a specific Engage Radius.
|
||||||
-- **The Engage Radius is defined for ALL squadrons which are operational.**
|
-- **The Engage Radius is defined for ALL squadrons which are operational.**
|
||||||
--
|
--
|
||||||
-- Demonstration Mission: [AID-019 - AI_A2A - Engage Range Test](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AID%20-%20AI%20Dispatching/AID-A2A%20-%20AI%20A2A%20Dispatching/AID-A2A-019%20-%20Engage%20Range%20Test)
|
-- Demonstration Mission: [AID-019 - AI_A2A - Engage Range Test](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AI/AI_A2A_Dispatcher/AID-A2A-019%20-%20Engage%20Range%20Test)
|
||||||
--
|
--
|
||||||
-- In this example an Engage Radius is set to various values.
|
-- In this example an Engage Radius is set to various values.
|
||||||
--
|
--
|
||||||
@@ -333,7 +333,7 @@ do -- AI_A2A_DISPATCHER
|
|||||||
-- Use the method @{#AI_A2A_DISPATCHER.SetGciRadius}() to set a specific controlled ground intercept radius.
|
-- Use the method @{#AI_A2A_DISPATCHER.SetGciRadius}() to set a specific controlled ground intercept radius.
|
||||||
-- **The Ground Controlled Intercept radius is defined for ALL squadrons which are operational.**
|
-- **The Ground Controlled Intercept radius is defined for ALL squadrons which are operational.**
|
||||||
--
|
--
|
||||||
-- Demonstration Mission: [AID-013 - AI_A2A - Intercept Test](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AID%20-%20AI%20Dispatching/AID-A2A%20-%20AI%20A2A%20Dispatching/AID-A2A-013%20-%20Intercept%20Test)
|
-- Demonstration Mission: [AID-013 - AI_A2A - Intercept Test](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AI/AI_A2A_Dispatcher/AID-A2A-013%20-%20Intercept%20Test)
|
||||||
--
|
--
|
||||||
-- In these examples, the Gci Radius is set to various values:
|
-- In these examples, the Gci Radius is set to various values:
|
||||||
--
|
--
|
||||||
@@ -366,7 +366,7 @@ do -- AI_A2A_DISPATCHER
|
|||||||
-- it makes it easier sometimes for the mission maker to envisage where the red and blue territories roughly are.
|
-- it makes it easier sometimes for the mission maker to envisage where the red and blue territories roughly are.
|
||||||
-- In a hot war the borders are effectively defined by the ground based radar coverage of a coalition.
|
-- In a hot war the borders are effectively defined by the ground based radar coverage of a coalition.
|
||||||
--
|
--
|
||||||
-- Demonstration Mission: [AID-009 - AI_A2A - Border Test](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AID%20-%20AI%20Dispatching/AID-A2A%20-%20AI%20A2A%20Dispatching/AID-A2A-009%20-%20Border%20Test)
|
-- Demonstration Mission: [AID-009 - AI_A2A - Border Test](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AI/AI_A2A_Dispatcher/AID-A2A-009%20-%20Border%20Test)
|
||||||
--
|
--
|
||||||
-- In this example a border is set for the CCCP A2A dispatcher:
|
-- In this example a border is set for the CCCP A2A dispatcher:
|
||||||
--
|
--
|
||||||
@@ -1233,7 +1233,7 @@ do -- AI_A2A_DISPATCHER
|
|||||||
--
|
--
|
||||||
-- **Use the method @{#AI_A2A_DISPATCHER.SetEngageRadius}() to modify the default Engage Radius for ALL squadrons.**
|
-- **Use the method @{#AI_A2A_DISPATCHER.SetEngageRadius}() to modify the default Engage Radius for ALL squadrons.**
|
||||||
--
|
--
|
||||||
-- Demonstration Mission: [AID-019 - AI_A2A - Engage Range Test](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AID%20-%20AI%20Dispatching/AID-A2A%20-%20AI%20A2A%20Dispatching/AID-A2A-019%20-%20Engage%20Range%20Test)
|
-- Demonstration Mission: [AID-019 - AI_A2A - Engage Range Test](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AI/AI_A2A_Dispatcher/AID-A2A-019%20-%20Engage%20Range%20Test)
|
||||||
--
|
--
|
||||||
-- @param #AI_A2A_DISPATCHER self
|
-- @param #AI_A2A_DISPATCHER self
|
||||||
-- @param #number EngageRadius (Optional, Default = 100000) The radius to report friendlies near the target.
|
-- @param #number EngageRadius (Optional, Default = 100000) The radius to report friendlies near the target.
|
||||||
@@ -1283,7 +1283,7 @@ do -- AI_A2A_DISPATCHER
|
|||||||
-- Use the method @{#AI_A2A_DISPATCHER.SetGciRadius}() to set a specific controlled ground intercept radius.
|
-- Use the method @{#AI_A2A_DISPATCHER.SetGciRadius}() to set a specific controlled ground intercept radius.
|
||||||
-- **The Ground Controlled Intercept radius is defined for ALL squadrons which are operational.**
|
-- **The Ground Controlled Intercept radius is defined for ALL squadrons which are operational.**
|
||||||
--
|
--
|
||||||
-- Demonstration Mission: [AID-013 - AI_A2A - Intercept Test](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AID%20-%20AI%20Dispatching/AID-A2A%20-%20AI%20A2A%20Dispatching/AID-A2A-013%20-%20Intercept%20Test)
|
-- Demonstration Mission: [AID-013 - AI_A2A - Intercept Test](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AI/AI_A2A_Dispatcher/AID-A2A-013%20-%20Intercept%20Test)
|
||||||
--
|
--
|
||||||
-- @param #AI_A2A_DISPATCHER self
|
-- @param #AI_A2A_DISPATCHER self
|
||||||
-- @param #number GciRadius (Optional, Default = 200000) The radius to ground control intercept detected targets from the nearest airbase.
|
-- @param #number GciRadius (Optional, Default = 200000) The radius to ground control intercept detected targets from the nearest airbase.
|
||||||
@@ -3257,7 +3257,8 @@ do -- AI_A2A_DISPATCHER
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #AI_A2A_DISPATCHER self
|
--- AI_A2A_Fsm:onafterHome
|
||||||
|
-- @param #AI_A2A_DISPATCHER self
|
||||||
function AI_A2A_Fsm:onafterHome( Defender, From, Event, To, Action )
|
function AI_A2A_Fsm:onafterHome( Defender, From, Event, To, Action )
|
||||||
if Defender and Defender:IsAlive() then
|
if Defender and Defender:IsAlive() then
|
||||||
self:F( { "CAP Home", Defender:GetName() } )
|
self:F( { "CAP Home", Defender:GetName() } )
|
||||||
@@ -3505,7 +3506,8 @@ do -- AI_A2A_DISPATCHER
|
|||||||
Dispatcher:ClearDefenderTaskTarget( DefenderGroup )
|
Dispatcher:ClearDefenderTaskTarget( DefenderGroup )
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #AI_A2A_DISPATCHER self
|
--- function Fsm:onafterLostControl
|
||||||
|
-- @param #AI_A2A_DISPATCHER self
|
||||||
function Fsm:onafterLostControl( Defender, From, Event, To )
|
function Fsm:onafterLostControl( Defender, From, Event, To )
|
||||||
self:F( { "GCI LostControl", Defender:GetName() } )
|
self:F( { "GCI LostControl", Defender:GetName() } )
|
||||||
self:GetParent( self ).onafterHome( self, Defender, From, Event, To )
|
self:GetParent( self ).onafterHome( self, Defender, From, Event, To )
|
||||||
@@ -3518,7 +3520,8 @@ do -- AI_A2A_DISPATCHER
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #AI_A2A_DISPATCHER self
|
--- function Fsm:onafterHome
|
||||||
|
-- @param #AI_A2A_DISPATCHER self
|
||||||
function Fsm:onafterHome( DefenderGroup, From, Event, To, Action )
|
function Fsm:onafterHome( DefenderGroup, From, Event, To, Action )
|
||||||
self:F( { "GCI Home", DefenderGroup:GetName() } )
|
self:F( { "GCI Home", DefenderGroup:GetName() } )
|
||||||
self:GetParent( self ).onafterHome( self, DefenderGroup, From, Event, To )
|
self:GetParent( self ).onafterHome( self, DefenderGroup, From, Event, To )
|
||||||
@@ -3959,7 +3962,7 @@ do
|
|||||||
--
|
--
|
||||||
-- # Demo Missions
|
-- # Demo Missions
|
||||||
--
|
--
|
||||||
-- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AID%20-%20AI%20Dispatching/AID-A2A%20-%20AI%20A2A%20Dispatching)
|
-- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AI/AI_A2A_Dispatcher)
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
--
|
--
|
||||||
-- ## Missions:
|
-- ## Missions:
|
||||||
--
|
--
|
||||||
-- [AID-A2G - AI A2G Dispatching](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AID%20-%20AI%20Dispatching/AID-A2G%20-%20AI%20A2G%20Dispatching)
|
-- [AID-A2G - AI A2G Dispatching](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AI/AI_A2G_Dispatcher)
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
--
|
--
|
||||||
-- ## Missions:
|
-- ## Missions:
|
||||||
--
|
--
|
||||||
-- [AID-AIR - AI AIR Dispatching](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AID%20-%20AI%20Dispatching)
|
-- [AI_A2A_Dispatcher](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AI/AI_A2A_Dispatcher)
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AIB%20-%20AI%20Balancing)
|
-- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AI/AI_Balancer)
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
@@ -168,7 +168,8 @@ function AI_BALANCER:ReturnToHomeAirbase( ReturnThresholdRange )
|
|||||||
self.ReturnThresholdRange = ReturnThresholdRange
|
self.ReturnThresholdRange = ReturnThresholdRange
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #AI_BALANCER self
|
--- AI_BALANCER:onenterSpawning
|
||||||
|
-- @param #AI_BALANCER self
|
||||||
-- @param Core.Set#SET_GROUP SetGroup
|
-- @param Core.Set#SET_GROUP SetGroup
|
||||||
-- @param #string ClientName
|
-- @param #string ClientName
|
||||||
-- @param Wrapper.Group#GROUP AIGroup
|
-- @param Wrapper.Group#GROUP AIGroup
|
||||||
@@ -190,7 +191,8 @@ function AI_BALANCER:onenterSpawning( SetGroup, From, Event, To, ClientName )
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #AI_BALANCER self
|
--- AI_BALANCER:onenterDestroying
|
||||||
|
-- @param #AI_BALANCER self
|
||||||
-- @param Core.Set#SET_GROUP SetGroup
|
-- @param Core.Set#SET_GROUP SetGroup
|
||||||
-- @param Wrapper.Group#GROUP AIGroup
|
-- @param Wrapper.Group#GROUP AIGroup
|
||||||
function AI_BALANCER:onenterDestroying( SetGroup, From, Event, To, ClientName, AIGroup )
|
function AI_BALANCER:onenterDestroying( SetGroup, From, Event, To, ClientName, AIGroup )
|
||||||
@@ -233,15 +235,16 @@ function AI_BALANCER:onenterReturning( SetGroup, From, Event, To, AIGroup )
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- AI_BALANCER:onenterMonitoring
|
||||||
--- @param #AI_BALANCER self
|
-- @param #AI_BALANCER self
|
||||||
function AI_BALANCER:onenterMonitoring( SetGroup )
|
function AI_BALANCER:onenterMonitoring( SetGroup )
|
||||||
|
|
||||||
self:T2( { self.SetClient:Count() } )
|
self:T2( { self.SetClient:Count() } )
|
||||||
--self.SetClient:Flush()
|
--self.SetClient:Flush()
|
||||||
|
|
||||||
self.SetClient:ForEachClient(
|
self.SetClient:ForEachClient(
|
||||||
--- @param Wrapper.Client#CLIENT Client
|
--- SetClient:ForEachClient
|
||||||
|
-- @param Wrapper.Client#CLIENT Client
|
||||||
function( Client )
|
function( Client )
|
||||||
self:T3(Client.ClientName)
|
self:T3(Client.ClientName)
|
||||||
|
|
||||||
@@ -264,7 +267,8 @@ function AI_BALANCER:onenterMonitoring( SetGroup )
|
|||||||
self:T2( RangeZone )
|
self:T2( RangeZone )
|
||||||
|
|
||||||
_DATABASE:ForEachPlayerUnit(
|
_DATABASE:ForEachPlayerUnit(
|
||||||
--- @param Wrapper.Unit#UNIT RangeTestUnit
|
--- Nameless function
|
||||||
|
-- @param Wrapper.Unit#UNIT RangeTestUnit
|
||||||
function( RangeTestUnit, RangeZone, AIGroup, PlayerInRange )
|
function( RangeTestUnit, RangeZone, AIGroup, PlayerInRange )
|
||||||
self:T2( { PlayerInRange, RangeTestUnit.UnitName, RangeZone.ZoneName } )
|
self:T2( { PlayerInRange, RangeTestUnit.UnitName, RangeZone.ZoneName } )
|
||||||
if RangeTestUnit:IsInZone( RangeZone ) == true then
|
if RangeTestUnit:IsInZone( RangeZone ) == true then
|
||||||
@@ -276,7 +280,8 @@ function AI_BALANCER:onenterMonitoring( SetGroup )
|
|||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
|
|
||||||
--- @param Core.Zone#ZONE_RADIUS RangeZone
|
--- Nameless function
|
||||||
|
-- @param Core.Zone#ZONE_RADIUS RangeZone
|
||||||
-- @param Wrapper.Group#GROUP AIGroup
|
-- @param Wrapper.Group#GROUP AIGroup
|
||||||
function( RangeZone, AIGroup, PlayerInRange )
|
function( RangeZone, AIGroup, PlayerInRange )
|
||||||
if PlayerInRange.Value == false then
|
if PlayerInRange.Value == false then
|
||||||
@@ -307,6 +312,3 @@ function AI_BALANCER:onenterMonitoring( SetGroup )
|
|||||||
|
|
||||||
self:__Monitor( 10 )
|
self:__Monitor( 10 )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
--
|
--
|
||||||
-- Test missions can be located on the main GITHUB site.
|
-- Test missions can be located on the main GITHUB site.
|
||||||
--
|
--
|
||||||
-- [FlightControl-Master/MOOSE_MISSIONS/AID - AI Dispatching/AID-CGO - AI Cargo Dispatching/](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/AID%20-%20AI%20Dispatching/AID-CGO%20-%20AI%20Cargo%20Dispatching)
|
-- [FlightControl-Master/MOOSE_MISSIONS/AID - AI Dispatching/AID-CGO - AI Cargo Dispatching/](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AI/AI_Cargo_Dispatcher)
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
@@ -583,10 +583,12 @@ AI_CARGO_DISPATCHER = {
|
|||||||
PickupCargo = {}
|
PickupCargo = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
--- @field #list
|
--- List of AI_Cargo
|
||||||
|
-- @field #list
|
||||||
AI_CARGO_DISPATCHER.AI_Cargo = {}
|
AI_CARGO_DISPATCHER.AI_Cargo = {}
|
||||||
|
|
||||||
--- @field #list
|
--- List of PickupCargo
|
||||||
|
-- @field #list
|
||||||
AI_CARGO_DISPATCHER.PickupCargo = {}
|
AI_CARGO_DISPATCHER.PickupCargo = {}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -370,7 +370,7 @@ CARGOS = {}
|
|||||||
|
|
||||||
do -- CARGO
|
do -- CARGO
|
||||||
|
|
||||||
--- @type CARGO
|
-- @type CARGO
|
||||||
-- @extends Core.Fsm#FSM_PROCESS
|
-- @extends Core.Fsm#FSM_PROCESS
|
||||||
-- @field #string Type A string defining the type of the cargo. eg. Engineers, Equipment, Screwdrivers.
|
-- @field #string Type A string defining the type of the cargo. eg. Engineers, Equipment, Screwdrivers.
|
||||||
-- @field #string Name A string defining the name of the cargo. The name is the unique identifier of the cargo.
|
-- @field #string Name A string defining the name of the cargo. The name is the unique identifier of the cargo.
|
||||||
@@ -433,7 +433,7 @@ do -- CARGO
|
|||||||
Reported = {},
|
Reported = {},
|
||||||
}
|
}
|
||||||
|
|
||||||
--- @type CARGO.CargoObjects
|
-- @type CARGO.CargoObjects
|
||||||
-- @map < #string, Wrapper.Positionable#POSITIONABLE > The alive POSITIONABLE objects representing the the cargo.
|
-- @map < #string, Wrapper.Positionable#POSITIONABLE > The alive POSITIONABLE objects representing the the cargo.
|
||||||
|
|
||||||
--- CARGO Constructor. This class is an abstract class and should not be instantiated.
|
--- CARGO Constructor. This class is an abstract class and should not be instantiated.
|
||||||
@@ -447,7 +447,7 @@ do -- CARGO
|
|||||||
function CARGO:New( Type, Name, Weight, LoadRadius, NearRadius ) --R2.1
|
function CARGO:New( Type, Name, Weight, LoadRadius, NearRadius ) --R2.1
|
||||||
|
|
||||||
local self = BASE:Inherit( self, FSM:New() ) -- #CARGO
|
local self = BASE:Inherit( self, FSM:New() ) -- #CARGO
|
||||||
self:F( { Type, Name, Weight, LoadRadius, NearRadius } )
|
self:T( { Type, Name, Weight, LoadRadius, NearRadius } )
|
||||||
|
|
||||||
self:SetStartState( "UnLoaded" )
|
self:SetStartState( "UnLoaded" )
|
||||||
self:AddTransition( { "UnLoaded", "Boarding" }, "Board", "Boarding" )
|
self:AddTransition( { "UnLoaded", "Boarding" }, "Board", "Boarding" )
|
||||||
@@ -711,7 +711,7 @@ do -- CARGO
|
|||||||
-- @param #CARGO self
|
-- @param #CARGO self
|
||||||
-- @return #CARGO
|
-- @return #CARGO
|
||||||
function CARGO:Spawn( PointVec2 )
|
function CARGO:Spawn( PointVec2 )
|
||||||
self:F()
|
self:T()
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -812,7 +812,7 @@ do -- CARGO
|
|||||||
-- @param Core.Point#COORDINATE Coordinate
|
-- @param Core.Point#COORDINATE Coordinate
|
||||||
-- @return #boolean true if the CargoGroup is within the loading radius.
|
-- @return #boolean true if the CargoGroup is within the loading radius.
|
||||||
function CARGO:IsInLoadRadius( Coordinate )
|
function CARGO:IsInLoadRadius( Coordinate )
|
||||||
self:F( { Coordinate, LoadRadius = self.LoadRadius } )
|
self:T( { Coordinate, LoadRadius = self.LoadRadius } )
|
||||||
|
|
||||||
local Distance = 0
|
local Distance = 0
|
||||||
if self:IsUnLoaded() then
|
if self:IsUnLoaded() then
|
||||||
@@ -832,7 +832,7 @@ do -- CARGO
|
|||||||
-- @param Core.Point#COORDINATE Coordinate
|
-- @param Core.Point#COORDINATE Coordinate
|
||||||
-- @return #boolean true if the Cargo can report itself.
|
-- @return #boolean true if the Cargo can report itself.
|
||||||
function CARGO:IsInReportRadius( Coordinate )
|
function CARGO:IsInReportRadius( Coordinate )
|
||||||
self:F( { Coordinate } )
|
self:T( { Coordinate } )
|
||||||
|
|
||||||
local Distance = 0
|
local Distance = 0
|
||||||
if self:IsUnLoaded() then
|
if self:IsUnLoaded() then
|
||||||
@@ -853,23 +853,23 @@ do -- CARGO
|
|||||||
-- @param #number NearRadius The radius when the cargo will board the Carrier (to avoid collision).
|
-- @param #number NearRadius The radius when the cargo will board the Carrier (to avoid collision).
|
||||||
-- @return #boolean
|
-- @return #boolean
|
||||||
function CARGO:IsNear( Coordinate, NearRadius )
|
function CARGO:IsNear( Coordinate, NearRadius )
|
||||||
--self:F( { PointVec2 = PointVec2, NearRadius = NearRadius } )
|
--self:T( { PointVec2 = PointVec2, NearRadius = NearRadius } )
|
||||||
|
|
||||||
if self.CargoObject:IsAlive() then
|
if self.CargoObject:IsAlive() then
|
||||||
--local Distance = PointVec2:Get2DDistance( self.CargoObject:GetPointVec2() )
|
--local Distance = PointVec2:Get2DDistance( self.CargoObject:GetPointVec2() )
|
||||||
--self:F( { CargoObjectName = self.CargoObject:GetName() } )
|
--self:T( { CargoObjectName = self.CargoObject:GetName() } )
|
||||||
--self:F( { CargoObjectVec2 = self.CargoObject:GetVec2() } )
|
--self:T( { CargoObjectVec2 = self.CargoObject:GetVec2() } )
|
||||||
--self:F( { PointVec2 = PointVec2:GetVec2() } )
|
--self:T( { PointVec2 = PointVec2:GetVec2() } )
|
||||||
local Distance = Coordinate:Get2DDistance( self.CargoObject:GetCoordinate() )
|
local Distance = Coordinate:Get2DDistance( self.CargoObject:GetCoordinate() )
|
||||||
--self:F( { Distance = Distance, NearRadius = NearRadius or "nil" } )
|
--self:T( { Distance = Distance, NearRadius = NearRadius or "nil" } )
|
||||||
|
|
||||||
if Distance <= NearRadius then
|
if Distance <= NearRadius then
|
||||||
--self:F( { PointVec2 = PointVec2, NearRadius = NearRadius, IsNear = true } )
|
--self:T( { PointVec2 = PointVec2, NearRadius = NearRadius, IsNear = true } )
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--self:F( { PointVec2 = PointVec2, NearRadius = NearRadius, IsNear = false } )
|
--self:T( { PointVec2 = PointVec2, NearRadius = NearRadius, IsNear = false } )
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -878,12 +878,12 @@ do -- CARGO
|
|||||||
-- @param Core.Zone#ZONE_BASE Zone
|
-- @param Core.Zone#ZONE_BASE Zone
|
||||||
-- @return #boolean **true** if cargo is in the Zone, **false** if cargo is not in the Zone.
|
-- @return #boolean **true** if cargo is in the Zone, **false** if cargo is not in the Zone.
|
||||||
function CARGO:IsInZone( Zone )
|
function CARGO:IsInZone( Zone )
|
||||||
--self:F( { Zone } )
|
--self:T( { Zone } )
|
||||||
|
|
||||||
if self:IsLoaded() then
|
if self:IsLoaded() then
|
||||||
return Zone:IsPointVec2InZone( self.CargoCarrier:GetPointVec2() )
|
return Zone:IsPointVec2InZone( self.CargoCarrier:GetPointVec2() )
|
||||||
else
|
else
|
||||||
--self:F( { Size = self.CargoObject:GetSize(), Units = self.CargoObject:GetUnits() } )
|
--self:T( { Size = self.CargoObject:GetSize(), Units = self.CargoObject:GetUnits() } )
|
||||||
if self.CargoObject:GetSize() ~= 0 then
|
if self.CargoObject:GetSize() ~= 0 then
|
||||||
return Zone:IsPointVec2InZone( self.CargoObject:GetPointVec2() )
|
return Zone:IsPointVec2InZone( self.CargoObject:GetPointVec2() )
|
||||||
else
|
else
|
||||||
@@ -1034,7 +1034,7 @@ end -- CARGO
|
|||||||
|
|
||||||
do -- CARGO_REPRESENTABLE
|
do -- CARGO_REPRESENTABLE
|
||||||
|
|
||||||
--- @type CARGO_REPRESENTABLE
|
-- @type CARGO_REPRESENTABLE
|
||||||
-- @extends #CARGO
|
-- @extends #CARGO
|
||||||
-- @field test
|
-- @field test
|
||||||
|
|
||||||
@@ -1056,7 +1056,7 @@ do -- CARGO_REPRESENTABLE
|
|||||||
|
|
||||||
-- Inherit CARGO.
|
-- Inherit CARGO.
|
||||||
local self = BASE:Inherit( self, CARGO:New( Type, Name, 0, LoadRadius, NearRadius ) ) -- #CARGO_REPRESENTABLE
|
local self = BASE:Inherit( self, CARGO:New( Type, Name, 0, LoadRadius, NearRadius ) ) -- #CARGO_REPRESENTABLE
|
||||||
self:F( { Type, Name, LoadRadius, NearRadius } )
|
self:T( { Type, Name, LoadRadius, NearRadius } )
|
||||||
|
|
||||||
-- Descriptors.
|
-- Descriptors.
|
||||||
local Desc=CargoObject:GetDesc()
|
local Desc=CargoObject:GetDesc()
|
||||||
@@ -1086,7 +1086,7 @@ do -- CARGO_REPRESENTABLE
|
|||||||
function CARGO_REPRESENTABLE:Destroy()
|
function CARGO_REPRESENTABLE:Destroy()
|
||||||
|
|
||||||
-- Cargo objects are deleted from the _DATABASE and SET_CARGO objects.
|
-- Cargo objects are deleted from the _DATABASE and SET_CARGO objects.
|
||||||
self:F( { CargoName = self:GetName() } )
|
self:T( { CargoName = self:GetName() } )
|
||||||
--_EVENTDISPATCHER:CreateEventDeleteCargo( self )
|
--_EVENTDISPATCHER:CreateEventDeleteCargo( self )
|
||||||
|
|
||||||
return self
|
return self
|
||||||
@@ -1123,12 +1123,12 @@ do -- CARGO_REPRESENTABLE
|
|||||||
CoordinateZone:Scan( { Object.Category.UNIT } )
|
CoordinateZone:Scan( { Object.Category.UNIT } )
|
||||||
for _, DCSUnit in pairs( CoordinateZone:GetScannedUnits() ) do
|
for _, DCSUnit in pairs( CoordinateZone:GetScannedUnits() ) do
|
||||||
local NearUnit = UNIT:Find( DCSUnit )
|
local NearUnit = UNIT:Find( DCSUnit )
|
||||||
self:F({NearUnit=NearUnit})
|
self:T({NearUnit=NearUnit})
|
||||||
local NearUnitCoalition = NearUnit:GetCoalition()
|
local NearUnitCoalition = NearUnit:GetCoalition()
|
||||||
local CargoCoalition = self:GetCoalition()
|
local CargoCoalition = self:GetCoalition()
|
||||||
if NearUnitCoalition == CargoCoalition then
|
if NearUnitCoalition == CargoCoalition then
|
||||||
local Attributes = NearUnit:GetDesc()
|
local Attributes = NearUnit:GetDesc()
|
||||||
self:F({Desc=Attributes})
|
self:T({Desc=Attributes})
|
||||||
if NearUnit:HasAttribute( "Trucks" ) then
|
if NearUnit:HasAttribute( "Trucks" ) then
|
||||||
MESSAGE:New( Message, 20, NearUnit:GetCallsign() .. " reporting - Cargo " .. self:GetName() ):ToGroup( TaskGroup )
|
MESSAGE:New( Message, 20, NearUnit:GetCallsign() .. " reporting - Cargo " .. self:GetName() ):ToGroup( TaskGroup )
|
||||||
break
|
break
|
||||||
@@ -1142,7 +1142,7 @@ end -- CARGO_REPRESENTABLE
|
|||||||
|
|
||||||
do -- CARGO_REPORTABLE
|
do -- CARGO_REPORTABLE
|
||||||
|
|
||||||
--- @type CARGO_REPORTABLE
|
-- @type CARGO_REPORTABLE
|
||||||
-- @extends #CARGO
|
-- @extends #CARGO
|
||||||
CARGO_REPORTABLE = {
|
CARGO_REPORTABLE = {
|
||||||
ClassName = "CARGO_REPORTABLE"
|
ClassName = "CARGO_REPORTABLE"
|
||||||
@@ -1158,7 +1158,7 @@ do -- CARGO_REPORTABLE
|
|||||||
-- @return #CARGO_REPORTABLE
|
-- @return #CARGO_REPORTABLE
|
||||||
function CARGO_REPORTABLE:New( Type, Name, Weight, LoadRadius, NearRadius )
|
function CARGO_REPORTABLE:New( Type, Name, Weight, LoadRadius, NearRadius )
|
||||||
local self = BASE:Inherit( self, CARGO:New( Type, Name, Weight, LoadRadius, NearRadius ) ) -- #CARGO_REPORTABLE
|
local self = BASE:Inherit( self, CARGO:New( Type, Name, Weight, LoadRadius, NearRadius ) ) -- #CARGO_REPORTABLE
|
||||||
self:F( { Type, Name, Weight, LoadRadius, NearRadius } )
|
self:T( { Type, Name, Weight, LoadRadius, NearRadius } )
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
@@ -1178,7 +1178,7 @@ end
|
|||||||
|
|
||||||
do -- CARGO_PACKAGE
|
do -- CARGO_PACKAGE
|
||||||
|
|
||||||
--- @type CARGO_PACKAGE
|
-- @type CARGO_PACKAGE
|
||||||
-- @extends #CARGO_REPRESENTABLE
|
-- @extends #CARGO_REPRESENTABLE
|
||||||
CARGO_PACKAGE = {
|
CARGO_PACKAGE = {
|
||||||
ClassName = "CARGO_PACKAGE"
|
ClassName = "CARGO_PACKAGE"
|
||||||
@@ -1195,7 +1195,7 @@ do -- CARGO_PACKAGE
|
|||||||
-- @return #CARGO_PACKAGE
|
-- @return #CARGO_PACKAGE
|
||||||
function CARGO_PACKAGE:New( CargoCarrier, Type, Name, Weight, LoadRadius, NearRadius )
|
function CARGO_PACKAGE:New( CargoCarrier, Type, Name, Weight, LoadRadius, NearRadius )
|
||||||
local self = BASE:Inherit( self, CARGO_REPRESENTABLE:New( CargoCarrier, Type, Name, Weight, LoadRadius, NearRadius ) ) -- #CARGO_PACKAGE
|
local self = BASE:Inherit( self, CARGO_REPRESENTABLE:New( CargoCarrier, Type, Name, Weight, LoadRadius, NearRadius ) ) -- #CARGO_PACKAGE
|
||||||
self:F( { Type, Name, Weight, LoadRadius, NearRadius } )
|
self:T( { Type, Name, Weight, LoadRadius, NearRadius } )
|
||||||
|
|
||||||
self:T( CargoCarrier )
|
self:T( CargoCarrier )
|
||||||
self.CargoCarrier = CargoCarrier
|
self.CargoCarrier = CargoCarrier
|
||||||
@@ -1213,7 +1213,7 @@ end
|
|||||||
-- @param #number BoardDistance
|
-- @param #number BoardDistance
|
||||||
-- @param #number Angle
|
-- @param #number Angle
|
||||||
function CARGO_PACKAGE:onafterOnBoard( From, Event, To, CargoCarrier, Speed, BoardDistance, LoadDistance, Angle )
|
function CARGO_PACKAGE:onafterOnBoard( From, Event, To, CargoCarrier, Speed, BoardDistance, LoadDistance, Angle )
|
||||||
self:F()
|
self:T()
|
||||||
|
|
||||||
self.CargoInAir = self.CargoCarrier:InAir()
|
self.CargoInAir = self.CargoCarrier:InAir()
|
||||||
|
|
||||||
@@ -1246,7 +1246,7 @@ end
|
|||||||
-- @param Wrapper.Unit#UNIT CargoCarrier
|
-- @param Wrapper.Unit#UNIT CargoCarrier
|
||||||
-- @return #boolean
|
-- @return #boolean
|
||||||
function CARGO_PACKAGE:IsNear( CargoCarrier )
|
function CARGO_PACKAGE:IsNear( CargoCarrier )
|
||||||
self:F()
|
self:T()
|
||||||
|
|
||||||
local CargoCarrierPoint = CargoCarrier:GetCoordinate()
|
local CargoCarrierPoint = CargoCarrier:GetCoordinate()
|
||||||
|
|
||||||
@@ -1271,7 +1271,7 @@ end
|
|||||||
-- @param #number LoadDistance
|
-- @param #number LoadDistance
|
||||||
-- @param #number Angle
|
-- @param #number Angle
|
||||||
function CARGO_PACKAGE:onafterOnBoarded( From, Event, To, CargoCarrier, Speed, BoardDistance, LoadDistance, Angle )
|
function CARGO_PACKAGE:onafterOnBoarded( From, Event, To, CargoCarrier, Speed, BoardDistance, LoadDistance, Angle )
|
||||||
self:F()
|
self:T()
|
||||||
|
|
||||||
if self:IsNear( CargoCarrier ) then
|
if self:IsNear( CargoCarrier ) then
|
||||||
self:__Load( 1, CargoCarrier, Speed, LoadDistance, Angle )
|
self:__Load( 1, CargoCarrier, Speed, LoadDistance, Angle )
|
||||||
@@ -1292,7 +1292,7 @@ end
|
|||||||
-- @param #number Radius
|
-- @param #number Radius
|
||||||
-- @param #number Angle
|
-- @param #number Angle
|
||||||
function CARGO_PACKAGE:onafterUnBoard( From, Event, To, CargoCarrier, Speed, UnLoadDistance, UnBoardDistance, Radius, Angle )
|
function CARGO_PACKAGE:onafterUnBoard( From, Event, To, CargoCarrier, Speed, UnLoadDistance, UnBoardDistance, Radius, Angle )
|
||||||
self:F()
|
self:T()
|
||||||
|
|
||||||
self.CargoInAir = self.CargoCarrier:InAir()
|
self.CargoInAir = self.CargoCarrier:InAir()
|
||||||
|
|
||||||
@@ -1331,7 +1331,7 @@ end
|
|||||||
-- @param Wrapper.Unit#UNIT CargoCarrier
|
-- @param Wrapper.Unit#UNIT CargoCarrier
|
||||||
-- @param #number Speed
|
-- @param #number Speed
|
||||||
function CARGO_PACKAGE:onafterUnBoarded( From, Event, To, CargoCarrier, Speed )
|
function CARGO_PACKAGE:onafterUnBoarded( From, Event, To, CargoCarrier, Speed )
|
||||||
self:F()
|
self:T()
|
||||||
|
|
||||||
if self:IsNear( CargoCarrier ) then
|
if self:IsNear( CargoCarrier ) then
|
||||||
self:__UnLoad( 1, CargoCarrier, Speed )
|
self:__UnLoad( 1, CargoCarrier, Speed )
|
||||||
@@ -1350,7 +1350,7 @@ end
|
|||||||
-- @param #number LoadDistance
|
-- @param #number LoadDistance
|
||||||
-- @param #number Angle
|
-- @param #number Angle
|
||||||
function CARGO_PACKAGE:onafterLoad( From, Event, To, CargoCarrier, Speed, LoadDistance, Angle )
|
function CARGO_PACKAGE:onafterLoad( From, Event, To, CargoCarrier, Speed, LoadDistance, Angle )
|
||||||
self:F()
|
self:T()
|
||||||
|
|
||||||
self.CargoCarrier = CargoCarrier
|
self.CargoCarrier = CargoCarrier
|
||||||
|
|
||||||
@@ -1378,7 +1378,7 @@ end
|
|||||||
-- @param #number Distance
|
-- @param #number Distance
|
||||||
-- @param #number Angle
|
-- @param #number Angle
|
||||||
function CARGO_PACKAGE:onafterUnLoad( From, Event, To, CargoCarrier, Speed, Distance, Angle )
|
function CARGO_PACKAGE:onafterUnLoad( From, Event, To, CargoCarrier, Speed, Distance, Angle )
|
||||||
self:F()
|
self:T()
|
||||||
|
|
||||||
local StartPointVec2 = self.CargoCarrier:GetPointVec2()
|
local StartPointVec2 = self.CargoCarrier:GetPointVec2()
|
||||||
local CargoCarrierHeading = self.CargoCarrier:GetHeading() -- Get Heading of object in degrees.
|
local CargoCarrierHeading = self.CargoCarrier:GetHeading() -- Get Heading of object in degrees.
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ do -- CARGO_CRATE
|
|||||||
-- @return #CARGO_CRATE
|
-- @return #CARGO_CRATE
|
||||||
function CARGO_CRATE:New( CargoStatic, Type, Name, LoadRadius, NearRadius )
|
function CARGO_CRATE:New( CargoStatic, Type, Name, LoadRadius, NearRadius )
|
||||||
local self = BASE:Inherit( self, CARGO_REPRESENTABLE:New( CargoStatic, Type, Name, nil, LoadRadius, NearRadius ) ) -- #CARGO_CRATE
|
local self = BASE:Inherit( self, CARGO_REPRESENTABLE:New( CargoStatic, Type, Name, nil, LoadRadius, NearRadius ) ) -- #CARGO_CRATE
|
||||||
self:F( { Type, Name, NearRadius } )
|
self:T( { Type, Name, NearRadius } )
|
||||||
|
|
||||||
self.CargoObject = CargoStatic -- Wrapper.Static#STATIC
|
self.CargoObject = CargoStatic -- Wrapper.Static#STATIC
|
||||||
|
|
||||||
@@ -116,7 +116,7 @@ do -- CARGO_CRATE
|
|||||||
-- @param #string To
|
-- @param #string To
|
||||||
-- @param Core.Point#POINT_VEC2
|
-- @param Core.Point#POINT_VEC2
|
||||||
function CARGO_CRATE:onenterUnLoaded( From, Event, To, ToPointVec2 )
|
function CARGO_CRATE:onenterUnLoaded( From, Event, To, ToPointVec2 )
|
||||||
--self:F( { ToPointVec2, From, Event, To } )
|
--self:T( { ToPointVec2, From, Event, To } )
|
||||||
|
|
||||||
local Angle = 180
|
local Angle = 180
|
||||||
local Speed = 10
|
local Speed = 10
|
||||||
@@ -153,7 +153,7 @@ do -- CARGO_CRATE
|
|||||||
-- @param #string To
|
-- @param #string To
|
||||||
-- @param Wrapper.Unit#UNIT CargoCarrier
|
-- @param Wrapper.Unit#UNIT CargoCarrier
|
||||||
function CARGO_CRATE:onenterLoaded( From, Event, To, CargoCarrier )
|
function CARGO_CRATE:onenterLoaded( From, Event, To, CargoCarrier )
|
||||||
--self:F( { From, Event, To, CargoCarrier } )
|
--self:T( { From, Event, To, CargoCarrier } )
|
||||||
|
|
||||||
self.CargoCarrier = CargoCarrier
|
self.CargoCarrier = CargoCarrier
|
||||||
|
|
||||||
@@ -190,7 +190,7 @@ do -- CARGO_CRATE
|
|||||||
-- @param Core.Point#COORDINATE Coordinate
|
-- @param Core.Point#COORDINATE Coordinate
|
||||||
-- @return #boolean true if the Cargo Crate is within the report radius.
|
-- @return #boolean true if the Cargo Crate is within the report radius.
|
||||||
function CARGO_CRATE:IsInReportRadius( Coordinate )
|
function CARGO_CRATE:IsInReportRadius( Coordinate )
|
||||||
--self:F( { Coordinate, LoadRadius = self.LoadRadius } )
|
--self:T( { Coordinate, LoadRadius = self.LoadRadius } )
|
||||||
|
|
||||||
local Distance = 0
|
local Distance = 0
|
||||||
if self:IsUnLoaded() then
|
if self:IsUnLoaded() then
|
||||||
@@ -210,7 +210,7 @@ do -- CARGO_CRATE
|
|||||||
-- @param Core.Point#Coordinate Coordinate
|
-- @param Core.Point#Coordinate Coordinate
|
||||||
-- @return #boolean true if the Cargo Crate is within the loading radius.
|
-- @return #boolean true if the Cargo Crate is within the loading radius.
|
||||||
function CARGO_CRATE:IsInLoadRadius( Coordinate )
|
function CARGO_CRATE:IsInLoadRadius( Coordinate )
|
||||||
--self:F( { Coordinate, LoadRadius = self.NearRadius } )
|
--self:T( { Coordinate, LoadRadius = self.NearRadius } )
|
||||||
|
|
||||||
local Distance = 0
|
local Distance = 0
|
||||||
if self:IsUnLoaded() then
|
if self:IsUnLoaded() then
|
||||||
@@ -231,7 +231,7 @@ do -- CARGO_CRATE
|
|||||||
-- @return Core.Point#COORDINATE The current Coordinate of the first Cargo of the CargoGroup.
|
-- @return Core.Point#COORDINATE The current Coordinate of the first Cargo of the CargoGroup.
|
||||||
-- @return #nil There is no valid Cargo in the CargoGroup.
|
-- @return #nil There is no valid Cargo in the CargoGroup.
|
||||||
function CARGO_CRATE:GetCoordinate()
|
function CARGO_CRATE:GetCoordinate()
|
||||||
--self:F()
|
--self:T()
|
||||||
|
|
||||||
return self.CargoObject:GetCoordinate()
|
return self.CargoObject:GetCoordinate()
|
||||||
end
|
end
|
||||||
@@ -261,7 +261,7 @@ do -- CARGO_CRATE
|
|||||||
-- @param #CARGO_CRATE self
|
-- @param #CARGO_CRATE self
|
||||||
-- @param Core.Point#COORDINATE Coordinate
|
-- @param Core.Point#COORDINATE Coordinate
|
||||||
function CARGO_CRATE:RouteTo( Coordinate )
|
function CARGO_CRATE:RouteTo( Coordinate )
|
||||||
self:F( {Coordinate = Coordinate } )
|
self:T( {Coordinate = Coordinate } )
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -274,7 +274,7 @@ do -- CARGO_CRATE
|
|||||||
-- @return #boolean The Cargo is near to the Carrier.
|
-- @return #boolean The Cargo is near to the Carrier.
|
||||||
-- @return #nil The Cargo is not near to the Carrier.
|
-- @return #nil The Cargo is not near to the Carrier.
|
||||||
function CARGO_CRATE:IsNear( CargoCarrier, NearRadius )
|
function CARGO_CRATE:IsNear( CargoCarrier, NearRadius )
|
||||||
self:F( {NearRadius = NearRadius } )
|
self:T( {NearRadius = NearRadius } )
|
||||||
|
|
||||||
return self:IsNear( CargoCarrier:GetCoordinate(), NearRadius )
|
return self:IsNear( CargoCarrier:GetCoordinate(), NearRadius )
|
||||||
end
|
end
|
||||||
@@ -283,7 +283,7 @@ do -- CARGO_CRATE
|
|||||||
-- @param #CARGO_CRATE self
|
-- @param #CARGO_CRATE self
|
||||||
function CARGO_CRATE:Respawn()
|
function CARGO_CRATE:Respawn()
|
||||||
|
|
||||||
self:F( { "Respawning crate " .. self:GetName() } )
|
self:T( { "Respawning crate " .. self:GetName() } )
|
||||||
|
|
||||||
|
|
||||||
-- Respawn the group...
|
-- Respawn the group...
|
||||||
@@ -300,7 +300,7 @@ do -- CARGO_CRATE
|
|||||||
-- @param #CARGO_CRATE self
|
-- @param #CARGO_CRATE self
|
||||||
function CARGO_CRATE:onafterReset()
|
function CARGO_CRATE:onafterReset()
|
||||||
|
|
||||||
self:F( { "Reset crate " .. self:GetName() } )
|
self:T( { "Reset crate " .. self:GetName() } )
|
||||||
|
|
||||||
|
|
||||||
-- Respawn the group...
|
-- Respawn the group...
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ do -- CARGO_GROUP
|
|||||||
|
|
||||||
-- Inherit CAROG_REPORTABLE
|
-- Inherit CAROG_REPORTABLE
|
||||||
local self = BASE:Inherit( self, CARGO_REPORTABLE:New( Type, Name, 0, LoadRadius, NearRadius ) ) -- #CARGO_GROUP
|
local self = BASE:Inherit( self, CARGO_REPORTABLE:New( Type, Name, 0, LoadRadius, NearRadius ) ) -- #CARGO_GROUP
|
||||||
self:F( { Type, Name, LoadRadius } )
|
self:T( { Type, Name, LoadRadius } )
|
||||||
|
|
||||||
self.CargoSet = SET_CARGO:New()
|
self.CargoSet = SET_CARGO:New()
|
||||||
self.CargoGroup = CargoGroup
|
self.CargoGroup = CargoGroup
|
||||||
@@ -146,7 +146,7 @@ do -- CARGO_GROUP
|
|||||||
-- @param #CARGO_GROUP self
|
-- @param #CARGO_GROUP self
|
||||||
function CARGO_GROUP:Respawn()
|
function CARGO_GROUP:Respawn()
|
||||||
|
|
||||||
self:F( { "Respawning" } )
|
self:T( { "Respawning" } )
|
||||||
|
|
||||||
for CargoID, CargoData in pairs( self.CargoSet:GetSet() ) do
|
for CargoID, CargoData in pairs( self.CargoSet:GetSet() ) do
|
||||||
local Cargo = CargoData -- Cargo.Cargo#CARGO
|
local Cargo = CargoData -- Cargo.Cargo#CARGO
|
||||||
@@ -227,7 +227,7 @@ do -- CARGO_GROUP
|
|||||||
-- @param #CARGO_GROUP self
|
-- @param #CARGO_GROUP self
|
||||||
function CARGO_GROUP:Regroup()
|
function CARGO_GROUP:Regroup()
|
||||||
|
|
||||||
self:F("Regroup")
|
self:T("Regroup")
|
||||||
|
|
||||||
if self.Grouped == false then
|
if self.Grouped == false then
|
||||||
|
|
||||||
@@ -241,7 +241,7 @@ do -- CARGO_GROUP
|
|||||||
for CargoUnitName, CargoUnit in pairs( self.CargoSet:GetSet() ) do
|
for CargoUnitName, CargoUnit in pairs( self.CargoSet:GetSet() ) do
|
||||||
local CargoUnit = CargoUnit -- Cargo.CargoUnit#CARGO_UNIT
|
local CargoUnit = CargoUnit -- Cargo.CargoUnit#CARGO_UNIT
|
||||||
|
|
||||||
self:F( { CargoUnit:GetName(), UnLoaded = CargoUnit:IsUnLoaded() } )
|
self:T( { CargoUnit:GetName(), UnLoaded = CargoUnit:IsUnLoaded() } )
|
||||||
|
|
||||||
if CargoUnit:IsUnLoaded() then
|
if CargoUnit:IsUnLoaded() then
|
||||||
|
|
||||||
@@ -258,7 +258,7 @@ do -- CARGO_GROUP
|
|||||||
-- Then we register the new group in the database
|
-- Then we register the new group in the database
|
||||||
self.CargoGroup = GROUP:NewTemplate( GroupTemplate, GroupTemplate.CoalitionID, GroupTemplate.CategoryID, GroupTemplate.CountryID )
|
self.CargoGroup = GROUP:NewTemplate( GroupTemplate, GroupTemplate.CoalitionID, GroupTemplate.CategoryID, GroupTemplate.CountryID )
|
||||||
|
|
||||||
self:F( { "Regroup", GroupTemplate } )
|
self:T( { "Regroup", GroupTemplate } )
|
||||||
|
|
||||||
-- Now we spawn the new group based on the template created.
|
-- Now we spawn the new group based on the template created.
|
||||||
self.CargoObject = _DATABASE:Spawn( GroupTemplate )
|
self.CargoObject = _DATABASE:Spawn( GroupTemplate )
|
||||||
@@ -271,7 +271,7 @@ do -- CARGO_GROUP
|
|||||||
-- @param Core.Event#EVENTDATA EventData
|
-- @param Core.Event#EVENTDATA EventData
|
||||||
function CARGO_GROUP:OnEventCargoDead( EventData )
|
function CARGO_GROUP:OnEventCargoDead( EventData )
|
||||||
|
|
||||||
self:E(EventData)
|
self:T(EventData)
|
||||||
|
|
||||||
local Destroyed = false
|
local Destroyed = false
|
||||||
|
|
||||||
@@ -296,7 +296,7 @@ do -- CARGO_GROUP
|
|||||||
|
|
||||||
if Destroyed then
|
if Destroyed then
|
||||||
self:Destroyed()
|
self:Destroyed()
|
||||||
self:E( { "Cargo group destroyed" } )
|
self:T( { "Cargo group destroyed" } )
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
@@ -309,14 +309,14 @@ do -- CARGO_GROUP
|
|||||||
-- @param Wrapper.Unit#UNIT CargoCarrier
|
-- @param Wrapper.Unit#UNIT CargoCarrier
|
||||||
-- @param #number NearRadius If distance is smaller than this number, cargo is loaded into the carrier.
|
-- @param #number NearRadius If distance is smaller than this number, cargo is loaded into the carrier.
|
||||||
function CARGO_GROUP:onafterBoard( From, Event, To, CargoCarrier, NearRadius, ... )
|
function CARGO_GROUP:onafterBoard( From, Event, To, CargoCarrier, NearRadius, ... )
|
||||||
self:F( { CargoCarrier.UnitName, From, Event, To, NearRadius = NearRadius } )
|
self:T( { CargoCarrier.UnitName, From, Event, To, NearRadius = NearRadius } )
|
||||||
|
|
||||||
NearRadius = NearRadius or self.NearRadius
|
NearRadius = NearRadius or self.NearRadius
|
||||||
|
|
||||||
-- For each Cargo object within the CARGO_GROUPED, route each object to the CargoLoadPointVec2
|
-- For each Cargo object within the CARGO_GROUPED, route each object to the CargoLoadPointVec2
|
||||||
self.CargoSet:ForEach(
|
self.CargoSet:ForEach(
|
||||||
function( Cargo, ... )
|
function( Cargo, ... )
|
||||||
self:F( { "Board Unit", Cargo:GetName( ), Cargo:IsDestroyed(), Cargo.CargoObject:IsAlive() } )
|
self:T( { "Board Unit", Cargo:GetName( ), Cargo:IsDestroyed(), Cargo.CargoObject:IsAlive() } )
|
||||||
local CargoGroup = Cargo.CargoObject --Wrapper.Group#GROUP
|
local CargoGroup = Cargo.CargoObject --Wrapper.Group#GROUP
|
||||||
CargoGroup:OptionAlarmStateGreen()
|
CargoGroup:OptionAlarmStateGreen()
|
||||||
Cargo:__Board( 1, CargoCarrier, NearRadius, ... )
|
Cargo:__Board( 1, CargoCarrier, NearRadius, ... )
|
||||||
@@ -334,7 +334,7 @@ do -- CARGO_GROUP
|
|||||||
-- @param #string To
|
-- @param #string To
|
||||||
-- @param Wrapper.Unit#UNIT CargoCarrier
|
-- @param Wrapper.Unit#UNIT CargoCarrier
|
||||||
function CARGO_GROUP:onafterLoad( From, Event, To, CargoCarrier, ... )
|
function CARGO_GROUP:onafterLoad( From, Event, To, CargoCarrier, ... )
|
||||||
--self:F( { From, Event, To, CargoCarrier, ...} )
|
--self:T( { From, Event, To, CargoCarrier, ...} )
|
||||||
|
|
||||||
if From == "UnLoaded" then
|
if From == "UnLoaded" then
|
||||||
-- For each Cargo object within the CARGO_GROUP, load each cargo to the CargoCarrier.
|
-- For each Cargo object within the CARGO_GROUP, load each cargo to the CargoCarrier.
|
||||||
@@ -359,7 +359,7 @@ do -- CARGO_GROUP
|
|||||||
-- @param Wrapper.Unit#UNIT CargoCarrier
|
-- @param Wrapper.Unit#UNIT CargoCarrier
|
||||||
-- @param #number NearRadius If distance is smaller than this number, cargo is loaded into the carrier.
|
-- @param #number NearRadius If distance is smaller than this number, cargo is loaded into the carrier.
|
||||||
function CARGO_GROUP:onafterBoarding( From, Event, To, CargoCarrier, NearRadius, ... )
|
function CARGO_GROUP:onafterBoarding( From, Event, To, CargoCarrier, NearRadius, ... )
|
||||||
--self:F( { CargoCarrier.UnitName, From, Event, To } )
|
--self:T( { CargoCarrier.UnitName, From, Event, To } )
|
||||||
|
|
||||||
local Boarded = true
|
local Boarded = true
|
||||||
local Cancelled = false
|
local Cancelled = false
|
||||||
@@ -393,7 +393,7 @@ do -- CARGO_GROUP
|
|||||||
if not Boarded then
|
if not Boarded then
|
||||||
self:__Boarding( -5, CargoCarrier, NearRadius, ... )
|
self:__Boarding( -5, CargoCarrier, NearRadius, ... )
|
||||||
else
|
else
|
||||||
self:F("Group Cargo is loaded")
|
self:T("Group Cargo is loaded")
|
||||||
self:__Load( 1, CargoCarrier, ... )
|
self:__Load( 1, CargoCarrier, ... )
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
@@ -413,7 +413,7 @@ do -- CARGO_GROUP
|
|||||||
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
||||||
-- @param #number NearRadius If distance is smaller than this number, cargo is loaded into the carrier.
|
-- @param #number NearRadius If distance is smaller than this number, cargo is loaded into the carrier.
|
||||||
function CARGO_GROUP:onafterUnBoard( From, Event, To, ToPointVec2, NearRadius, ... )
|
function CARGO_GROUP:onafterUnBoard( From, Event, To, ToPointVec2, NearRadius, ... )
|
||||||
self:F( {From, Event, To, ToPointVec2, NearRadius } )
|
self:T( {From, Event, To, ToPointVec2, NearRadius } )
|
||||||
|
|
||||||
NearRadius = NearRadius or 25
|
NearRadius = NearRadius or 25
|
||||||
|
|
||||||
@@ -456,7 +456,7 @@ do -- CARGO_GROUP
|
|||||||
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
||||||
-- @param #number NearRadius If distance is smaller than this number, cargo is loaded into the carrier.
|
-- @param #number NearRadius If distance is smaller than this number, cargo is loaded into the carrier.
|
||||||
function CARGO_GROUP:onafterUnBoarding( From, Event, To, ToPointVec2, NearRadius, ... )
|
function CARGO_GROUP:onafterUnBoarding( From, Event, To, ToPointVec2, NearRadius, ... )
|
||||||
--self:F( { From, Event, To, ToPointVec2, NearRadius } )
|
--self:T( { From, Event, To, ToPointVec2, NearRadius } )
|
||||||
|
|
||||||
--local NearRadius = NearRadius or 25
|
--local NearRadius = NearRadius or 25
|
||||||
|
|
||||||
@@ -493,7 +493,7 @@ do -- CARGO_GROUP
|
|||||||
-- @param #string To
|
-- @param #string To
|
||||||
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
||||||
function CARGO_GROUP:onafterUnLoad( From, Event, To, ToPointVec2, ... )
|
function CARGO_GROUP:onafterUnLoad( From, Event, To, ToPointVec2, ... )
|
||||||
--self:F( { From, Event, To, ToPointVec2 } )
|
--self:T( { From, Event, To, ToPointVec2 } )
|
||||||
|
|
||||||
if From == "Loaded" then
|
if From == "Loaded" then
|
||||||
|
|
||||||
@@ -611,7 +611,7 @@ do -- CARGO_GROUP
|
|||||||
-- @param #CARGO_GROUP self
|
-- @param #CARGO_GROUP self
|
||||||
-- @param Core.Point#COORDINATE Coordinate
|
-- @param Core.Point#COORDINATE Coordinate
|
||||||
function CARGO_GROUP:RouteTo( Coordinate )
|
function CARGO_GROUP:RouteTo( Coordinate )
|
||||||
--self:F( {Coordinate = Coordinate } )
|
--self:T( {Coordinate = Coordinate } )
|
||||||
|
|
||||||
-- For each Cargo within the CargoSet, route each object to the Coordinate
|
-- For each Cargo within the CargoSet, route each object to the Coordinate
|
||||||
self.CargoSet:ForEach(
|
self.CargoSet:ForEach(
|
||||||
@@ -629,13 +629,13 @@ do -- CARGO_GROUP
|
|||||||
-- @param #number NearRadius
|
-- @param #number NearRadius
|
||||||
-- @return #boolean The Cargo is near to the Carrier or #nil if the Cargo is not near to the Carrier.
|
-- @return #boolean The Cargo is near to the Carrier or #nil if the Cargo is not near to the Carrier.
|
||||||
function CARGO_GROUP:IsNear( CargoCarrier, NearRadius )
|
function CARGO_GROUP:IsNear( CargoCarrier, NearRadius )
|
||||||
self:F( {NearRadius = NearRadius } )
|
self:T( {NearRadius = NearRadius } )
|
||||||
|
|
||||||
for _, Cargo in pairs( self.CargoSet:GetSet() ) do
|
for _, Cargo in pairs( self.CargoSet:GetSet() ) do
|
||||||
local Cargo = Cargo -- Cargo.Cargo#CARGO
|
local Cargo = Cargo -- Cargo.Cargo#CARGO
|
||||||
if Cargo:IsAlive() then
|
if Cargo:IsAlive() then
|
||||||
if Cargo:IsNear( CargoCarrier:GetCoordinate(), NearRadius ) then
|
if Cargo:IsNear( CargoCarrier:GetCoordinate(), NearRadius ) then
|
||||||
self:F( "Near" )
|
self:T( "Near" )
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -649,7 +649,7 @@ do -- CARGO_GROUP
|
|||||||
-- @param Core.Point#COORDINATE Coordinate
|
-- @param Core.Point#COORDINATE Coordinate
|
||||||
-- @return #boolean true if the Cargo Group is within the load radius.
|
-- @return #boolean true if the Cargo Group is within the load radius.
|
||||||
function CARGO_GROUP:IsInLoadRadius( Coordinate )
|
function CARGO_GROUP:IsInLoadRadius( Coordinate )
|
||||||
--self:F( { Coordinate } )
|
--self:T( { Coordinate } )
|
||||||
|
|
||||||
local Cargo = self:GetFirstAlive() -- Cargo.Cargo#CARGO
|
local Cargo = self:GetFirstAlive() -- Cargo.Cargo#CARGO
|
||||||
|
|
||||||
@@ -669,7 +669,7 @@ do -- CARGO_GROUP
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
self:F( { Distance = Distance, LoadRadius = self.LoadRadius } )
|
self:T( { Distance = Distance, LoadRadius = self.LoadRadius } )
|
||||||
if Distance <= self.LoadRadius then
|
if Distance <= self.LoadRadius then
|
||||||
return true
|
return true
|
||||||
else
|
else
|
||||||
@@ -687,12 +687,12 @@ do -- CARGO_GROUP
|
|||||||
-- @param Core.Point#Coordinate Coordinate
|
-- @param Core.Point#Coordinate Coordinate
|
||||||
-- @return #boolean true if the Cargo Group is within the report radius.
|
-- @return #boolean true if the Cargo Group is within the report radius.
|
||||||
function CARGO_GROUP:IsInReportRadius( Coordinate )
|
function CARGO_GROUP:IsInReportRadius( Coordinate )
|
||||||
--self:F( { Coordinate } )
|
--self:T( { Coordinate } )
|
||||||
|
|
||||||
local Cargo = self:GetFirstAlive() -- Cargo.Cargo#CARGO
|
local Cargo = self:GetFirstAlive() -- Cargo.Cargo#CARGO
|
||||||
|
|
||||||
if Cargo then
|
if Cargo then
|
||||||
self:F( { Cargo } )
|
self:T( { Cargo } )
|
||||||
local Distance = 0
|
local Distance = 0
|
||||||
if Cargo:IsUnLoaded() then
|
if Cargo:IsUnLoaded() then
|
||||||
Distance = Coordinate:Get2DDistance( Cargo.CargoObject:GetCoordinate() )
|
Distance = Coordinate:Get2DDistance( Cargo.CargoObject:GetCoordinate() )
|
||||||
@@ -738,7 +738,7 @@ do -- CARGO_GROUP
|
|||||||
-- @return #boolean **true** if the first element of the CargoGroup is in the Zone
|
-- @return #boolean **true** if the first element of the CargoGroup is in the Zone
|
||||||
-- @return #boolean **false** if there is no element of the CargoGroup in the Zone.
|
-- @return #boolean **false** if there is no element of the CargoGroup in the Zone.
|
||||||
function CARGO_GROUP:IsInZone( Zone )
|
function CARGO_GROUP:IsInZone( Zone )
|
||||||
--self:F( { Zone } )
|
--self:T( { Zone } )
|
||||||
|
|
||||||
local Cargo = self.CargoSet:GetFirst() -- Cargo.Cargo#CARGO
|
local Cargo = self.CargoSet:GetFirst() -- Cargo.Cargo#CARGO
|
||||||
|
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ do -- CARGO_SLINGLOAD
|
|||||||
-- @return #CARGO_SLINGLOAD
|
-- @return #CARGO_SLINGLOAD
|
||||||
function CARGO_SLINGLOAD:New( CargoStatic, Type, Name, LoadRadius, NearRadius )
|
function CARGO_SLINGLOAD:New( CargoStatic, Type, Name, LoadRadius, NearRadius )
|
||||||
local self = BASE:Inherit( self, CARGO_REPRESENTABLE:New( CargoStatic, Type, Name, nil, LoadRadius, NearRadius ) ) -- #CARGO_SLINGLOAD
|
local self = BASE:Inherit( self, CARGO_REPRESENTABLE:New( CargoStatic, Type, Name, nil, LoadRadius, NearRadius ) ) -- #CARGO_SLINGLOAD
|
||||||
self:F( { Type, Name, NearRadius } )
|
self:T( { Type, Name, NearRadius } )
|
||||||
|
|
||||||
self.CargoObject = CargoStatic
|
self.CargoObject = CargoStatic
|
||||||
|
|
||||||
@@ -130,7 +130,7 @@ do -- CARGO_SLINGLOAD
|
|||||||
-- @param Core.Point#COORDINATE Coordinate
|
-- @param Core.Point#COORDINATE Coordinate
|
||||||
-- @return #boolean true if the Cargo Crate is within the report radius.
|
-- @return #boolean true if the Cargo Crate is within the report radius.
|
||||||
function CARGO_SLINGLOAD:IsInReportRadius( Coordinate )
|
function CARGO_SLINGLOAD:IsInReportRadius( Coordinate )
|
||||||
--self:F( { Coordinate, LoadRadius = self.LoadRadius } )
|
--self:T( { Coordinate, LoadRadius = self.LoadRadius } )
|
||||||
|
|
||||||
local Distance = 0
|
local Distance = 0
|
||||||
if self:IsUnLoaded() then
|
if self:IsUnLoaded() then
|
||||||
@@ -149,7 +149,7 @@ do -- CARGO_SLINGLOAD
|
|||||||
-- @param Core.Point#COORDINATE Coordinate
|
-- @param Core.Point#COORDINATE Coordinate
|
||||||
-- @return #boolean true if the Cargo Slingload is within the loading radius.
|
-- @return #boolean true if the Cargo Slingload is within the loading radius.
|
||||||
function CARGO_SLINGLOAD:IsInLoadRadius( Coordinate )
|
function CARGO_SLINGLOAD:IsInLoadRadius( Coordinate )
|
||||||
--self:F( { Coordinate } )
|
--self:T( { Coordinate } )
|
||||||
|
|
||||||
local Distance = 0
|
local Distance = 0
|
||||||
if self:IsUnLoaded() then
|
if self:IsUnLoaded() then
|
||||||
@@ -169,7 +169,7 @@ do -- CARGO_SLINGLOAD
|
|||||||
-- @return Core.Point#COORDINATE The current Coordinate of the first Cargo of the CargoGroup.
|
-- @return Core.Point#COORDINATE The current Coordinate of the first Cargo of the CargoGroup.
|
||||||
-- @return #nil There is no valid Cargo in the CargoGroup.
|
-- @return #nil There is no valid Cargo in the CargoGroup.
|
||||||
function CARGO_SLINGLOAD:GetCoordinate()
|
function CARGO_SLINGLOAD:GetCoordinate()
|
||||||
--self:F()
|
--self:T()
|
||||||
|
|
||||||
return self.CargoObject:GetCoordinate()
|
return self.CargoObject:GetCoordinate()
|
||||||
end
|
end
|
||||||
@@ -199,7 +199,7 @@ do -- CARGO_SLINGLOAD
|
|||||||
-- @param #CARGO_SLINGLOAD self
|
-- @param #CARGO_SLINGLOAD self
|
||||||
-- @param Core.Point#COORDINATE Coordinate
|
-- @param Core.Point#COORDINATE Coordinate
|
||||||
function CARGO_SLINGLOAD:RouteTo( Coordinate )
|
function CARGO_SLINGLOAD:RouteTo( Coordinate )
|
||||||
--self:F( {Coordinate = Coordinate } )
|
--self:T( {Coordinate = Coordinate } )
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -212,7 +212,7 @@ do -- CARGO_SLINGLOAD
|
|||||||
-- @return #boolean The Cargo is near to the Carrier.
|
-- @return #boolean The Cargo is near to the Carrier.
|
||||||
-- @return #nil The Cargo is not near to the Carrier.
|
-- @return #nil The Cargo is not near to the Carrier.
|
||||||
function CARGO_SLINGLOAD:IsNear( CargoCarrier, NearRadius )
|
function CARGO_SLINGLOAD:IsNear( CargoCarrier, NearRadius )
|
||||||
--self:F( {NearRadius = NearRadius } )
|
--self:T( {NearRadius = NearRadius } )
|
||||||
|
|
||||||
return self:IsNear( CargoCarrier:GetCoordinate(), NearRadius )
|
return self:IsNear( CargoCarrier:GetCoordinate(), NearRadius )
|
||||||
end
|
end
|
||||||
@@ -222,7 +222,7 @@ do -- CARGO_SLINGLOAD
|
|||||||
-- @param #CARGO_SLINGLOAD self
|
-- @param #CARGO_SLINGLOAD self
|
||||||
function CARGO_SLINGLOAD:Respawn()
|
function CARGO_SLINGLOAD:Respawn()
|
||||||
|
|
||||||
--self:F( { "Respawning slingload " .. self:GetName() } )
|
--self:T( { "Respawning slingload " .. self:GetName() } )
|
||||||
|
|
||||||
|
|
||||||
-- Respawn the group...
|
-- Respawn the group...
|
||||||
@@ -239,7 +239,7 @@ do -- CARGO_SLINGLOAD
|
|||||||
-- @param #CARGO_SLINGLOAD self
|
-- @param #CARGO_SLINGLOAD self
|
||||||
function CARGO_SLINGLOAD:onafterReset()
|
function CARGO_SLINGLOAD:onafterReset()
|
||||||
|
|
||||||
--self:F( { "Reset slingload " .. self:GetName() } )
|
--self:T( { "Reset slingload " .. self:GetName() } )
|
||||||
|
|
||||||
|
|
||||||
-- Respawn the group...
|
-- Respawn the group...
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ do -- CARGO_UNIT
|
|||||||
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
||||||
-- @param #number NearRadius (optional) Defaut 25 m.
|
-- @param #number NearRadius (optional) Defaut 25 m.
|
||||||
function CARGO_UNIT:onenterUnBoarding( From, Event, To, ToPointVec2, NearRadius )
|
function CARGO_UNIT:onenterUnBoarding( From, Event, To, ToPointVec2, NearRadius )
|
||||||
self:F( { From, Event, To, ToPointVec2, NearRadius } )
|
self:T( { From, Event, To, ToPointVec2, NearRadius } )
|
||||||
|
|
||||||
local Angle = 180
|
local Angle = 180
|
||||||
local Speed = 60
|
local Speed = 60
|
||||||
@@ -114,7 +114,7 @@ do -- CARGO_UNIT
|
|||||||
else
|
else
|
||||||
self.CargoObject:ReSpawnAt( FromPointVec2, CargoDeployHeading )
|
self.CargoObject:ReSpawnAt( FromPointVec2, CargoDeployHeading )
|
||||||
end
|
end
|
||||||
self:F( { "CargoUnits:", self.CargoObject:GetGroup():GetName() } )
|
self:T( { "CargoUnits:", self.CargoObject:GetGroup():GetName() } )
|
||||||
self.CargoCarrier = nil
|
self.CargoCarrier = nil
|
||||||
|
|
||||||
local Points = {}
|
local Points = {}
|
||||||
@@ -148,7 +148,7 @@ do -- CARGO_UNIT
|
|||||||
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
||||||
-- @param #number NearRadius (optional) Defaut 100 m.
|
-- @param #number NearRadius (optional) Defaut 100 m.
|
||||||
function CARGO_UNIT:onleaveUnBoarding( From, Event, To, ToPointVec2, NearRadius )
|
function CARGO_UNIT:onleaveUnBoarding( From, Event, To, ToPointVec2, NearRadius )
|
||||||
self:F( { From, Event, To, ToPointVec2, NearRadius } )
|
self:T( { From, Event, To, ToPointVec2, NearRadius } )
|
||||||
|
|
||||||
local Angle = 180
|
local Angle = 180
|
||||||
local Speed = 10
|
local Speed = 10
|
||||||
@@ -174,7 +174,7 @@ do -- CARGO_UNIT
|
|||||||
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
||||||
-- @param #number NearRadius (optional) Defaut 100 m.
|
-- @param #number NearRadius (optional) Defaut 100 m.
|
||||||
function CARGO_UNIT:onafterUnBoarding( From, Event, To, ToPointVec2, NearRadius )
|
function CARGO_UNIT:onafterUnBoarding( From, Event, To, ToPointVec2, NearRadius )
|
||||||
self:F( { From, Event, To, ToPointVec2, NearRadius } )
|
self:T( { From, Event, To, ToPointVec2, NearRadius } )
|
||||||
|
|
||||||
self.CargoInAir = self.CargoObject:InAir()
|
self.CargoInAir = self.CargoObject:InAir()
|
||||||
|
|
||||||
@@ -199,7 +199,7 @@ do -- CARGO_UNIT
|
|||||||
-- @param #string To
|
-- @param #string To
|
||||||
-- @param Core.Point#POINT_VEC2
|
-- @param Core.Point#POINT_VEC2
|
||||||
function CARGO_UNIT:onenterUnLoaded( From, Event, To, ToPointVec2 )
|
function CARGO_UNIT:onenterUnLoaded( From, Event, To, ToPointVec2 )
|
||||||
self:F( { ToPointVec2, From, Event, To } )
|
self:T( { ToPointVec2, From, Event, To } )
|
||||||
|
|
||||||
local Angle = 180
|
local Angle = 180
|
||||||
local Speed = 10
|
local Speed = 10
|
||||||
@@ -236,7 +236,7 @@ do -- CARGO_UNIT
|
|||||||
-- @param Wrapper.Group#GROUP CargoCarrier
|
-- @param Wrapper.Group#GROUP CargoCarrier
|
||||||
-- @param #number NearRadius
|
-- @param #number NearRadius
|
||||||
function CARGO_UNIT:onafterBoard( From, Event, To, CargoCarrier, NearRadius, ... )
|
function CARGO_UNIT:onafterBoard( From, Event, To, CargoCarrier, NearRadius, ... )
|
||||||
self:F( { From, Event, To, CargoCarrier, NearRadius = NearRadius } )
|
self:T( { From, Event, To, CargoCarrier, NearRadius = NearRadius } )
|
||||||
|
|
||||||
self.CargoInAir = self.CargoObject:InAir()
|
self.CargoInAir = self.CargoObject:InAir()
|
||||||
|
|
||||||
@@ -244,7 +244,7 @@ do -- CARGO_UNIT
|
|||||||
local MaxSpeed = Desc.speedMaxOffRoad
|
local MaxSpeed = Desc.speedMaxOffRoad
|
||||||
local TypeName = Desc.typeName
|
local TypeName = Desc.typeName
|
||||||
|
|
||||||
--self:F({Unit=self.CargoObject:GetName()})
|
--self:T({Unit=self.CargoObject:GetName()})
|
||||||
|
|
||||||
-- A cargo unit can only be boarded if it is not dead
|
-- A cargo unit can only be boarded if it is not dead
|
||||||
|
|
||||||
@@ -298,9 +298,9 @@ do -- CARGO_UNIT
|
|||||||
-- @param Wrapper.Client#CLIENT CargoCarrier
|
-- @param Wrapper.Client#CLIENT CargoCarrier
|
||||||
-- @param #number NearRadius Default 25 m.
|
-- @param #number NearRadius Default 25 m.
|
||||||
function CARGO_UNIT:onafterBoarding( From, Event, To, CargoCarrier, NearRadius, ... )
|
function CARGO_UNIT:onafterBoarding( From, Event, To, CargoCarrier, NearRadius, ... )
|
||||||
self:F( { From, Event, To, CargoCarrier:GetName(), NearRadius = NearRadius } )
|
self:T( { From, Event, To, CargoCarrier:GetName(), NearRadius = NearRadius } )
|
||||||
|
|
||||||
self:F( { IsAlive=self.CargoObject:IsAlive() } )
|
self:T( { IsAlive=self.CargoObject:IsAlive() } )
|
||||||
|
|
||||||
if CargoCarrier and CargoCarrier:IsAlive() then -- and self.CargoObject and self.CargoObject:IsAlive() then
|
if CargoCarrier and CargoCarrier:IsAlive() then -- and self.CargoObject and self.CargoObject:IsAlive() then
|
||||||
if (CargoCarrier:IsAir() and not CargoCarrier:InAir()) or true then
|
if (CargoCarrier:IsAir() and not CargoCarrier:InAir()) or true then
|
||||||
@@ -321,7 +321,7 @@ do -- CARGO_UNIT
|
|||||||
local Angle = 180
|
local Angle = 180
|
||||||
local Distance = 0
|
local Distance = 0
|
||||||
|
|
||||||
--self:F({Unit=self.CargoObject:GetName()})
|
--self:T({Unit=self.CargoObject:GetName()})
|
||||||
|
|
||||||
local CargoCarrierPointVec2 = CargoCarrier:GetPointVec2()
|
local CargoCarrierPointVec2 = CargoCarrier:GetPointVec2()
|
||||||
local CargoCarrierHeading = CargoCarrier:GetHeading() -- Get Heading of object in degrees.
|
local CargoCarrierHeading = CargoCarrier:GetHeading() -- Get Heading of object in degrees.
|
||||||
@@ -348,7 +348,7 @@ do -- CARGO_UNIT
|
|||||||
self.CargoObject:SetCommand( self.CargoObject:CommandStopRoute( true ) )
|
self.CargoObject:SetCommand( self.CargoObject:CommandStopRoute( true ) )
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
self:E("Something is wrong")
|
self:T("Something is wrong")
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
@@ -361,11 +361,11 @@ do -- CARGO_UNIT
|
|||||||
-- @param #string To
|
-- @param #string To
|
||||||
-- @param Wrapper.Unit#UNIT CargoCarrier
|
-- @param Wrapper.Unit#UNIT CargoCarrier
|
||||||
function CARGO_UNIT:onenterLoaded( From, Event, To, CargoCarrier )
|
function CARGO_UNIT:onenterLoaded( From, Event, To, CargoCarrier )
|
||||||
self:F( { From, Event, To, CargoCarrier } )
|
self:T( { From, Event, To, CargoCarrier } )
|
||||||
|
|
||||||
self.CargoCarrier = CargoCarrier
|
self.CargoCarrier = CargoCarrier
|
||||||
|
|
||||||
--self:F({Unit=self.CargoObject:GetName()})
|
--self:T({Unit=self.CargoObject:GetName()})
|
||||||
|
|
||||||
-- Only destroy the CargoObject if there is a CargoObject (packages don't have CargoObjects).
|
-- Only destroy the CargoObject if there is a CargoObject (packages don't have CargoObjects).
|
||||||
if self.CargoObject then
|
if self.CargoObject then
|
||||||
|
|||||||
@@ -489,8 +489,30 @@ do -- Zones and Pathlines
|
|||||||
-- Create new polygon zone.
|
-- Create new polygon zone.
|
||||||
local Zone=ZONE_POLYGON:NewFromPointsArray(ZoneName, points)
|
local Zone=ZONE_POLYGON:NewFromPointsArray(ZoneName, points)
|
||||||
|
|
||||||
|
--Zone.DrawID = objectID
|
||||||
|
|
||||||
-- Set color.
|
-- Set color.
|
||||||
Zone:SetColor({1, 0, 0}, 0.15)
|
Zone:SetColor({1, 0, 0}, 0.15)
|
||||||
|
Zone:SetFillColor({1, 0, 0}, 0.15)
|
||||||
|
|
||||||
|
if objectData.colorString then
|
||||||
|
-- eg colorString = 0xff0000ff
|
||||||
|
local color = string.gsub(objectData.colorString,"^0x","")
|
||||||
|
local r = tonumber(string.sub(color,1,2),16)/255
|
||||||
|
local g = tonumber(string.sub(color,3,4),16)/255
|
||||||
|
local b = tonumber(string.sub(color,5,6),16)/255
|
||||||
|
local a = tonumber(string.sub(color,7,8),16)/255
|
||||||
|
Zone:SetColor({r, g, b}, a)
|
||||||
|
end
|
||||||
|
if objectData.fillColorString then
|
||||||
|
-- eg fillColorString = 0xff00004b
|
||||||
|
local color = string.gsub(objectData.colorString,"^0x","")
|
||||||
|
local r = tonumber(string.sub(color,1,2),16)/255
|
||||||
|
local g = tonumber(string.sub(color,3,4),16)/255
|
||||||
|
local b = tonumber(string.sub(color,5,6),16)/255
|
||||||
|
local a = tonumber(string.sub(color,7,8),16)/255
|
||||||
|
Zone:SetFillColor({r, g, b}, a)
|
||||||
|
end
|
||||||
|
|
||||||
-- Store in DB.
|
-- Store in DB.
|
||||||
self.ZONENAMES[ZoneName] = ZoneName
|
self.ZONENAMES[ZoneName] = ZoneName
|
||||||
@@ -533,6 +555,25 @@ do -- Zones and Pathlines
|
|||||||
-- Set color.
|
-- Set color.
|
||||||
Zone:SetColor({1, 0, 0}, 0.15)
|
Zone:SetColor({1, 0, 0}, 0.15)
|
||||||
|
|
||||||
|
if objectData.colorString then
|
||||||
|
-- eg colorString = 0xff0000ff
|
||||||
|
local color = string.gsub(objectData.colorString,"^0x","")
|
||||||
|
local r = tonumber(string.sub(color,1,2),16)/255
|
||||||
|
local g = tonumber(string.sub(color,3,4),16)/255
|
||||||
|
local b = tonumber(string.sub(color,5,6),16)/255
|
||||||
|
local a = tonumber(string.sub(color,7,8),16)/255
|
||||||
|
Zone:SetColor({r, g, b}, a)
|
||||||
|
end
|
||||||
|
if objectData.fillColorString then
|
||||||
|
-- eg fillColorString = 0xff00004b
|
||||||
|
local color = string.gsub(objectData.colorString,"^0x","")
|
||||||
|
local r = tonumber(string.sub(color,1,2),16)/255
|
||||||
|
local g = tonumber(string.sub(color,3,4),16)/255
|
||||||
|
local b = tonumber(string.sub(color,5,6),16)/255
|
||||||
|
local a = tonumber(string.sub(color,7,8),16)/255
|
||||||
|
Zone:SetFillColor({r, g, b}, a)
|
||||||
|
end
|
||||||
|
|
||||||
-- Store in DB.
|
-- Store in DB.
|
||||||
self.ZONENAMES[ZoneName] = ZoneName
|
self.ZONENAMES[ZoneName] = ZoneName
|
||||||
|
|
||||||
@@ -756,7 +797,7 @@ end -- cargo
|
|||||||
|
|
||||||
--- Finds a CLIENT based on the ClientName.
|
--- Finds a CLIENT based on the ClientName.
|
||||||
-- @param #DATABASE self
|
-- @param #DATABASE self
|
||||||
-- @param #string ClientName
|
-- @param #string ClientName - Note this is the UNIT name of the client!
|
||||||
-- @return Wrapper.Client#CLIENT The found CLIENT.
|
-- @return Wrapper.Client#CLIENT The found CLIENT.
|
||||||
function DATABASE:FindClient( ClientName )
|
function DATABASE:FindClient( ClientName )
|
||||||
|
|
||||||
|
|||||||
@@ -368,7 +368,7 @@ function MESSAGE:ToCoalition( CoalitionSide, Settings )
|
|||||||
if CoalitionSide then
|
if CoalitionSide then
|
||||||
if self.MessageDuration ~= 0 then
|
if self.MessageDuration ~= 0 then
|
||||||
self:T( self.MessageCategory .. self.MessageText:gsub( "\n$", "" ):gsub( "\n$", "" ) .. " / " .. self.MessageDuration )
|
self:T( self.MessageCategory .. self.MessageText:gsub( "\n$", "" ):gsub( "\n$", "" ) .. " / " .. self.MessageDuration )
|
||||||
trigger.action.outTextForCoalition( CoalitionSide, self.MessageText:gsub( "\n$", "" ):gsub( "\n$", "" ), self.MessageDuration, self.ClearScreen )
|
trigger.action.outTextForCoalition( CoalitionSide, self.MessageCategory .. self.MessageText:gsub( "\n$", "" ):gsub( "\n$", "" ), self.MessageDuration, self.ClearScreen )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -498,7 +498,6 @@ function MESSAGE.SetMSRS(PathToSRS,Port,PathToCredentials,Frequency,Modulation,G
|
|||||||
_MESSAGESRS.Gender = Gender or "female"
|
_MESSAGESRS.Gender = Gender or "female"
|
||||||
|
|
||||||
_MESSAGESRS.MSRS:SetGoogle(PathToCredentials)
|
_MESSAGESRS.MSRS:SetGoogle(PathToCredentials)
|
||||||
_MESSAGESRS.google = PathToCredentials
|
|
||||||
|
|
||||||
_MESSAGESRS.MSRS:SetLabel(Label or "MESSAGE")
|
_MESSAGESRS.MSRS:SetLabel(Label or "MESSAGE")
|
||||||
_MESSAGESRS.label = Label or "MESSAGE"
|
_MESSAGESRS.label = Label or "MESSAGE"
|
||||||
@@ -512,8 +511,6 @@ function MESSAGE.SetMSRS(PathToSRS,Port,PathToCredentials,Frequency,Modulation,G
|
|||||||
if Voice then _MESSAGESRS.MSRS:SetVoice(Voice) end
|
if Voice then _MESSAGESRS.MSRS:SetVoice(Voice) end
|
||||||
|
|
||||||
_MESSAGESRS.voice = Voice --or MSRS.Voices.Microsoft.Hedda
|
_MESSAGESRS.voice = Voice --or MSRS.Voices.Microsoft.Hedda
|
||||||
--if _MESSAGESRS.google and not Voice then _MESSAGESRS.Voice = MSRS.Voices.Google.Standard.en_GB_Standard_A end
|
|
||||||
--_MESSAGESRS.MSRS:SetVoice(Voice or _MESSAGESRS.voice)
|
|
||||||
|
|
||||||
_MESSAGESRS.SRSQ = MSRSQUEUE:New(Label or "MESSAGE")
|
_MESSAGESRS.SRSQ = MSRSQUEUE:New(Label or "MESSAGE")
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -25,7 +25,8 @@
|
|||||||
|
|
||||||
do -- COORDINATE
|
do -- COORDINATE
|
||||||
|
|
||||||
--- @type COORDINATE
|
---
|
||||||
|
-- @type COORDINATE
|
||||||
-- @field #string ClassName Name of the class
|
-- @field #string ClassName Name of the class
|
||||||
-- @field #number x Component of the 3D vector.
|
-- @field #number x Component of the 3D vector.
|
||||||
-- @field #number y Component of the 3D vector.
|
-- @field #number y Component of the 3D vector.
|
||||||
@@ -2472,15 +2473,18 @@ do -- COORDINATE
|
|||||||
-- Write command as string and execute that. Idea by Grimes https://forum.dcs.world/topic/324201-mark-to-all-function/#comment-5273793
|
-- Write command as string and execute that. Idea by Grimes https://forum.dcs.world/topic/324201-mark-to-all-function/#comment-5273793
|
||||||
local s=string.format("trigger.action.markupToAll(7, %d, %d,", Coalition, MarkID)
|
local s=string.format("trigger.action.markupToAll(7, %d, %d,", Coalition, MarkID)
|
||||||
for _,vec in pairs(vecs) do
|
for _,vec in pairs(vecs) do
|
||||||
s=s..string.format("%s,", UTILS._OneLineSerialize(vec))
|
--s=s..string.format("%s,", UTILS._OneLineSerialize(vec))
|
||||||
|
s=s..string.format("{x=%.1f, y=%.1f, z=%.1f},", vec.x, vec.y, vec.z)
|
||||||
end
|
end
|
||||||
s=s..string.format("%s, %s, %s, %s", UTILS._OneLineSerialize(Color), UTILS._OneLineSerialize(FillColor), tostring(LineType), tostring(ReadOnly))
|
s=s..string.format("{%.3f, %.3f, %.3f, %.3f},", Color[1], Color[2], Color[3], Color[4])
|
||||||
if Text and Text~="" then
|
s=s..string.format("{%.3f, %.3f, %.3f, %.3f},", FillColor[1], FillColor[2], FillColor[3], FillColor[4])
|
||||||
s=s..string.format(", \"%s\"", Text)
|
s=s..string.format("%d,", LineType or 1)
|
||||||
|
s=s..string.format("%s", tostring(ReadOnly))
|
||||||
|
if Text and type(Text)=="string" and string.len(Text)>0 then
|
||||||
|
s=s..string.format(", \"%s\"", tostring(Text))
|
||||||
end
|
end
|
||||||
s=s..")"
|
s=s..")"
|
||||||
|
|
||||||
|
|
||||||
-- Execute string command
|
-- Execute string command
|
||||||
local success=UTILS.DoString(s)
|
local success=UTILS.DoString(s)
|
||||||
|
|
||||||
@@ -2568,7 +2572,7 @@ do -- COORDINATE
|
|||||||
|
|
||||||
Offset=Offset or 2
|
Offset=Offset or 2
|
||||||
|
|
||||||
-- Measurement of visibility should not be from the ground, so Adding a hypotethical 2 meters to each Coordinate.
|
-- Measurement of visibility should not be from the ground, so Adding a hypothetical 2 meters to each Coordinate.
|
||||||
local FromVec3 = self:GetVec3()
|
local FromVec3 = self:GetVec3()
|
||||||
FromVec3.y = FromVec3.y + Offset
|
FromVec3.y = FromVec3.y + Offset
|
||||||
|
|
||||||
@@ -3118,6 +3122,49 @@ do -- COORDINATE
|
|||||||
return "MGRS " .. UTILS.tostringMGRS( MGRS, MGRS_Accuracy )
|
return "MGRS " .. UTILS.tostringMGRS( MGRS, MGRS_Accuracy )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Provides a COORDINATE from an MGRS String
|
||||||
|
-- @param #COORDINATE self
|
||||||
|
-- @param #string MGRSString MGRS String, e.g. "MGRS 37T DK 12345 12345"
|
||||||
|
-- @return #COORDINATE self
|
||||||
|
function COORDINATE:NewFromMGRSString( MGRSString )
|
||||||
|
local myparts = UTILS.Split(MGRSString," ")
|
||||||
|
local northing = tostring(myparts[5]) or ""
|
||||||
|
local easting = tostring(myparts[4]) or ""
|
||||||
|
if string.len(easting) < 5 then easting = easting..string.rep("0",5-string.len(easting)) end
|
||||||
|
if string.len(northing) < 5 then northing = northing..string.rep("0",5-string.len(northing)) end
|
||||||
|
local MGRS = {
|
||||||
|
UTMZone = myparts[2],
|
||||||
|
MGRSDigraph = myparts[3],
|
||||||
|
Easting = easting,
|
||||||
|
Northing = northing,
|
||||||
|
}
|
||||||
|
local lat, lon = coord.MGRStoLL(MGRS)
|
||||||
|
local point = coord.LLtoLO(lat, lon, 0)
|
||||||
|
local coord = COORDINATE:NewFromVec2({x=point.x,y=point.z})
|
||||||
|
return coord
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Provides a COORDINATE from an MGRS Coordinate
|
||||||
|
-- @param #COORDINATE self
|
||||||
|
-- @param #string UTMZone UTM Zone, e.g. "37T"
|
||||||
|
-- @param #string MGRSDigraph Digraph, e.g. "DK"
|
||||||
|
-- @param #string Easting Meters easting - string in order to allow for leading zeros, e.g. "01234". Should be 5 digits.
|
||||||
|
-- @param #string Northing Meters northing - string in order to allow for leading zeros, e.g. "12340". Should be 5 digits.
|
||||||
|
-- @return #COORDINATE self
|
||||||
|
function COORDINATE:NewFromMGRS( UTMZone, MGRSDigraph, Easting, Northing )
|
||||||
|
if string.len(Easting) < 5 then Easting = Easting..string.rep("0",5-string.len(Easting) )end
|
||||||
|
if string.len(Northing) < 5 then Northing = Northing..string.rep("0",5-string.len(Northing) )end
|
||||||
|
local MGRS = {
|
||||||
|
UTMZone = UTMZone,
|
||||||
|
MGRSDigraph = MGRSDigraph,
|
||||||
|
Easting = Easting,
|
||||||
|
Northing = Northing,
|
||||||
|
}
|
||||||
|
local lat, lon = coord.MGRStoLL(MGRS)
|
||||||
|
local point = coord.LLtoLO(lat, lon, 0)
|
||||||
|
local coord = COORDINATE:NewFromVec2({x=point.x,y=point.z})
|
||||||
|
end
|
||||||
|
|
||||||
--- Provides a coordinate string of the point, based on a coordinate format system:
|
--- Provides a coordinate string of the point, based on a coordinate format system:
|
||||||
-- * Uses default settings in COORDINATE.
|
-- * Uses default settings in COORDINATE.
|
||||||
-- * Can be overridden if for a GROUP containing x clients, a menu was selected to override the default.
|
-- * Can be overridden if for a GROUP containing x clients, a menu was selected to override the default.
|
||||||
@@ -3630,7 +3677,7 @@ end
|
|||||||
|
|
||||||
do -- POINT_VEC2
|
do -- POINT_VEC2
|
||||||
|
|
||||||
--- @type POINT_VEC2
|
-- @type POINT_VEC2
|
||||||
-- @field DCS#Distance x The x coordinate in meters.
|
-- @field DCS#Distance x The x coordinate in meters.
|
||||||
-- @field DCS#Distance y the y coordinate in meters.
|
-- @field DCS#Distance y the y coordinate in meters.
|
||||||
-- @extends Core.Point#COORDINATE
|
-- @extends Core.Point#COORDINATE
|
||||||
|
|||||||
@@ -147,6 +147,44 @@ do -- SET_BASE
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- [Internal] Add a functional filter
|
||||||
|
-- @param #SET_BASE self
|
||||||
|
-- @param #function ConditionFunction If this function returns `true`, the object is added to the SET. The function needs to take a CONTROLLABLE object as first argument.
|
||||||
|
-- @param ... Condition function arguments, if any.
|
||||||
|
-- @return #boolean If true, at least one condition is true
|
||||||
|
function SET_BASE:FilterFunction(ConditionFunction, ...)
|
||||||
|
|
||||||
|
local condition={}
|
||||||
|
condition.func=ConditionFunction
|
||||||
|
condition.arg={}
|
||||||
|
|
||||||
|
if arg then
|
||||||
|
condition.arg=arg
|
||||||
|
end
|
||||||
|
|
||||||
|
if not self.Filter.Functions then self.Filter.Functions = {} end
|
||||||
|
table.insert(self.Filter.Functions, condition)
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [Internal] Check if the condition functions returns true.
|
||||||
|
-- @param #SET_BASE self
|
||||||
|
-- @param Wrapper.Controllable#CONTROLLABLE Object The object to filter for
|
||||||
|
-- @return #boolean If true, if **all** conditions are true
|
||||||
|
function SET_BASE:_EvalFilterFunctions(Object)
|
||||||
|
-- All conditions must be true.
|
||||||
|
for _,_condition in pairs(self.Filter.Functions or {}) do
|
||||||
|
local condition=_condition
|
||||||
|
-- Call function.
|
||||||
|
if condition.func(Object,unpack(condition.arg)) == false then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- No condition was true.
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
--- Clear the Objects in the Set.
|
--- Clear the Objects in the Set.
|
||||||
-- @param #SET_BASE self
|
-- @param #SET_BASE self
|
||||||
-- @param #boolean TriggerEvent If `true`, an event remove is triggered for each group that is removed from the set.
|
-- @param #boolean TriggerEvent If `true`, an event remove is triggered for each group that is removed from the set.
|
||||||
@@ -419,7 +457,11 @@ do -- SET_BASE
|
|||||||
-- @param #SET_BASE self
|
-- @param #SET_BASE self
|
||||||
-- @return Core.Base#BASE
|
-- @return Core.Base#BASE
|
||||||
function SET_BASE:GetRandom()
|
function SET_BASE:GetRandom()
|
||||||
local tablemax = table.maxn(self.Index)
|
local tablemax = 0
|
||||||
|
for _,_ind in pairs(self.Index) do
|
||||||
|
tablemax = tablemax + 1
|
||||||
|
end
|
||||||
|
--local tablemax = table.maxn(self.Index)
|
||||||
local RandomItem = self.Set[self.Index[math.random(1,tablemax)]]
|
local RandomItem = self.Set[self.Index[math.random(1,tablemax)]]
|
||||||
self:T3( { RandomItem } )
|
self:T3( { RandomItem } )
|
||||||
return RandomItem
|
return RandomItem
|
||||||
@@ -561,10 +603,12 @@ do -- SET_BASE
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Iterate the SET_BASE while identifying the nearest object from a @{Core.Point#POINT_VEC2}.
|
--- Iterate the SET_BASE while identifying the nearest object in the set from a @{Core.Point#POINT_VEC2}.
|
||||||
-- @param #SET_BASE self
|
-- @param #SET_BASE self
|
||||||
-- @param Core.Point#POINT_VEC2 PointVec2 A @{Core.Point#POINT_VEC2} object from where to evaluate the closest object in the set.
|
-- @param Core.Point#POINT_VEC2 PointVec2 A @{Core.Point#COORDINATE} or @{Core.Point#POINT_VEC2} object (but **not** a simple DCS#Vec2!) from where to evaluate the closest object in the set.
|
||||||
-- @return Core.Base#BASE The closest object.
|
-- @return Core.Base#BASE The closest object.
|
||||||
|
-- @usage
|
||||||
|
-- myset:FindNearestObjectFromPointVec2( ZONE:New("Test Zone"):GetCoordinate() )
|
||||||
function SET_BASE:FindNearestObjectFromPointVec2( PointVec2 )
|
function SET_BASE:FindNearestObjectFromPointVec2( PointVec2 )
|
||||||
self:F2( PointVec2 )
|
self:F2( PointVec2 )
|
||||||
|
|
||||||
@@ -961,6 +1005,7 @@ do
|
|||||||
-- * @{#SET_GROUP.FilterCategoryShip}: Builds the SET_GROUP from ships.
|
-- * @{#SET_GROUP.FilterCategoryShip}: Builds the SET_GROUP from ships.
|
||||||
-- * @{#SET_GROUP.FilterCategoryStructure}: Builds the SET_GROUP from structures.
|
-- * @{#SET_GROUP.FilterCategoryStructure}: Builds the SET_GROUP from structures.
|
||||||
-- * @{#SET_GROUP.FilterZones}: Builds the SET_GROUP with the groups within a @{Core.Zone#ZONE}.
|
-- * @{#SET_GROUP.FilterZones}: Builds the SET_GROUP with the groups within a @{Core.Zone#ZONE}.
|
||||||
|
-- * @{#SET_GROUP.FilterFunction}: Builds the SET_GROUP with a custom condition.
|
||||||
--
|
--
|
||||||
-- Once the filter criteria have been set for the SET_GROUP, you can start filtering using:
|
-- Once the filter criteria have been set for the SET_GROUP, you can start filtering using:
|
||||||
--
|
--
|
||||||
@@ -1034,6 +1079,7 @@ do
|
|||||||
Countries = nil,
|
Countries = nil,
|
||||||
GroupPrefixes = nil,
|
GroupPrefixes = nil,
|
||||||
Zones = nil,
|
Zones = nil,
|
||||||
|
Functions = nil,
|
||||||
},
|
},
|
||||||
FilterMeta = {
|
FilterMeta = {
|
||||||
Coalitions = {
|
Coalitions = {
|
||||||
@@ -1248,6 +1294,25 @@ do
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- [User] Add a custom condition function.
|
||||||
|
-- @function [parent=#SET_GROUP] FilterFunction
|
||||||
|
-- @param #SET_GROUP self
|
||||||
|
-- @param #function ConditionFunction If this function returns `true`, the object is added to the SET. The function needs to take a GROUP object as first argument.
|
||||||
|
-- @param ... Condition function arguments if any.
|
||||||
|
-- @return #SET_GROUP self
|
||||||
|
-- @usage
|
||||||
|
-- -- Image you want to exclude a specific GROUP from a SET:
|
||||||
|
-- local groundset = SET_GROUP:New():FilterCoalitions("blue"):FilterCategoryGround():FilterFunction(
|
||||||
|
-- -- The function needs to take a GROUP object as first - and in this case, only - argument.
|
||||||
|
-- function(grp)
|
||||||
|
-- local isinclude = true
|
||||||
|
-- if grp:GetName() == "Exclude Me" then isinclude = false end
|
||||||
|
-- return isinclude
|
||||||
|
-- end
|
||||||
|
-- ):FilterOnce()
|
||||||
|
-- BASE:I(groundset:Flush())
|
||||||
|
|
||||||
|
|
||||||
--- Builds a set of groups of coalitions.
|
--- Builds a set of groups of coalitions.
|
||||||
-- Possible current coalitions are red, blue and neutral.
|
-- Possible current coalitions are red, blue and neutral.
|
||||||
-- @param #SET_GROUP self
|
-- @param #SET_GROUP self
|
||||||
@@ -1921,7 +1986,7 @@ do
|
|||||||
MGroupInclude = MGroupInclude and MGroupActive
|
MGroupInclude = MGroupInclude and MGroupActive
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.Filter.Coalitions then
|
if self.Filter.Coalitions and MGroupInclude then
|
||||||
local MGroupCoalition = false
|
local MGroupCoalition = false
|
||||||
for CoalitionID, CoalitionName in pairs( self.Filter.Coalitions ) do
|
for CoalitionID, CoalitionName in pairs( self.Filter.Coalitions ) do
|
||||||
self:T3( { "Coalition:", MGroup:GetCoalition(), self.FilterMeta.Coalitions[CoalitionName], CoalitionName } )
|
self:T3( { "Coalition:", MGroup:GetCoalition(), self.FilterMeta.Coalitions[CoalitionName], CoalitionName } )
|
||||||
@@ -1932,7 +1997,7 @@ do
|
|||||||
MGroupInclude = MGroupInclude and MGroupCoalition
|
MGroupInclude = MGroupInclude and MGroupCoalition
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.Filter.Categories then
|
if self.Filter.Categories and MGroupInclude then
|
||||||
local MGroupCategory = false
|
local MGroupCategory = false
|
||||||
for CategoryID, CategoryName in pairs( self.Filter.Categories ) do
|
for CategoryID, CategoryName in pairs( self.Filter.Categories ) do
|
||||||
self:T3( { "Category:", MGroup:GetCategory(), self.FilterMeta.Categories[CategoryName], CategoryName } )
|
self:T3( { "Category:", MGroup:GetCategory(), self.FilterMeta.Categories[CategoryName], CategoryName } )
|
||||||
@@ -1943,7 +2008,7 @@ do
|
|||||||
MGroupInclude = MGroupInclude and MGroupCategory
|
MGroupInclude = MGroupInclude and MGroupCategory
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.Filter.Countries then
|
if self.Filter.Countries and MGroupInclude then
|
||||||
local MGroupCountry = false
|
local MGroupCountry = false
|
||||||
for CountryID, CountryName in pairs( self.Filter.Countries ) do
|
for CountryID, CountryName in pairs( self.Filter.Countries ) do
|
||||||
self:T3( { "Country:", MGroup:GetCountry(), CountryName } )
|
self:T3( { "Country:", MGroup:GetCountry(), CountryName } )
|
||||||
@@ -1954,7 +2019,7 @@ do
|
|||||||
MGroupInclude = MGroupInclude and MGroupCountry
|
MGroupInclude = MGroupInclude and MGroupCountry
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.Filter.GroupPrefixes then
|
if self.Filter.GroupPrefixes and MGroupInclude then
|
||||||
local MGroupPrefix = false
|
local MGroupPrefix = false
|
||||||
for GroupPrefixId, GroupPrefix in pairs( self.Filter.GroupPrefixes ) do
|
for GroupPrefixId, GroupPrefix in pairs( self.Filter.GroupPrefixes ) do
|
||||||
self:T3( { "Prefix:", string.find( MGroup:GetName(), GroupPrefix, 1 ), GroupPrefix } )
|
self:T3( { "Prefix:", string.find( MGroup:GetName(), GroupPrefix, 1 ), GroupPrefix } )
|
||||||
@@ -1965,7 +2030,7 @@ do
|
|||||||
MGroupInclude = MGroupInclude and MGroupPrefix
|
MGroupInclude = MGroupInclude and MGroupPrefix
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.Filter.Zones then
|
if self.Filter.Zones and MGroupInclude then
|
||||||
local MGroupZone = false
|
local MGroupZone = false
|
||||||
for ZoneName, Zone in pairs( self.Filter.Zones ) do
|
for ZoneName, Zone in pairs( self.Filter.Zones ) do
|
||||||
--self:T( "Zone:", ZoneName )
|
--self:T( "Zone:", ZoneName )
|
||||||
@@ -1976,6 +2041,12 @@ do
|
|||||||
MGroupInclude = MGroupInclude and MGroupZone
|
MGroupInclude = MGroupInclude and MGroupZone
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if self.Filter.Functions and MGroupInclude then
|
||||||
|
local MGroupFunc = false
|
||||||
|
MGroupFunc = self:_EvalFilterFunctions(MGroup)
|
||||||
|
MGroupInclude = MGroupInclude and MGroupFunc
|
||||||
|
end
|
||||||
|
|
||||||
self:T2( MGroupInclude )
|
self:T2( MGroupInclude )
|
||||||
return MGroupInclude
|
return MGroupInclude
|
||||||
end
|
end
|
||||||
@@ -2074,6 +2145,7 @@ do -- SET_UNIT
|
|||||||
-- Have a read through here to understand the application of regular expressions: [LUA regular expressions](https://riptutorial.com/lua/example/20315/lua-pattern-matching)
|
-- Have a read through here to understand the application of regular expressions: [LUA regular expressions](https://riptutorial.com/lua/example/20315/lua-pattern-matching)
|
||||||
-- * @{#SET_UNIT.FilterActive}: Builds the SET_UNIT with the units that are only active. Units that are inactive (late activation) won't be included in the set!
|
-- * @{#SET_UNIT.FilterActive}: Builds the SET_UNIT with the units that are only active. Units that are inactive (late activation) won't be included in the set!
|
||||||
-- * @{#SET_UNIT.FilterZones}: Builds the SET_UNIT with the units within a @{Core.Zone#ZONE}.
|
-- * @{#SET_UNIT.FilterZones}: Builds the SET_UNIT with the units within a @{Core.Zone#ZONE}.
|
||||||
|
-- * @{#SET_UNIT.FilterFunction}: Builds the SET_UNIT with a custom condition.
|
||||||
--
|
--
|
||||||
-- Once the filter criteria have been set for the SET_UNIT, you can start filtering using:
|
-- Once the filter criteria have been set for the SET_UNIT, you can start filtering using:
|
||||||
--
|
--
|
||||||
@@ -2152,6 +2224,7 @@ do -- SET_UNIT
|
|||||||
Countries = nil,
|
Countries = nil,
|
||||||
UnitPrefixes = nil,
|
UnitPrefixes = nil,
|
||||||
Zones = nil,
|
Zones = nil,
|
||||||
|
Functions = nil,
|
||||||
},
|
},
|
||||||
FilterMeta = {
|
FilterMeta = {
|
||||||
Coalitions = {
|
Coalitions = {
|
||||||
@@ -2523,6 +2596,25 @@ do -- SET_UNIT
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- [User] Add a custom condition function.
|
||||||
|
-- @function [parent=#SET_UNIT] FilterFunction
|
||||||
|
-- @param #SET_UNIT self
|
||||||
|
-- @param #function ConditionFunction If this function returns `true`, the object is added to the SET. The function needs to take a UNIT object as first argument.
|
||||||
|
-- @param ... Condition function arguments if any.
|
||||||
|
-- @return #SET_UNIT self
|
||||||
|
-- @usage
|
||||||
|
-- -- Image you want to exclude a specific UNIT from a SET:
|
||||||
|
-- local groundset = SET_UNIT:New():FilterCoalitions("blue"):FilterCategories("ground"):FilterFunction(
|
||||||
|
-- -- The function needs to take a UNIT object as first - and in this case, only - argument.
|
||||||
|
-- function(unit)
|
||||||
|
-- local isinclude = true
|
||||||
|
-- if unit:GetName() == "Exclude Me" then isinclude = false end
|
||||||
|
-- return isinclude
|
||||||
|
-- end
|
||||||
|
-- ):FilterOnce()
|
||||||
|
-- BASE:I(groundset:Flush())
|
||||||
|
|
||||||
|
|
||||||
--- Handles the Database to check on an event (birth) that the Object was added in the Database.
|
--- Handles the Database to check on an event (birth) that the Object was added in the Database.
|
||||||
-- This is required, because sometimes the _DATABASE birth event gets called later than the SET_BASE birth event!
|
-- This is required, because sometimes the _DATABASE birth event gets called later than the SET_BASE birth event!
|
||||||
-- @param #SET_UNIT self
|
-- @param #SET_UNIT self
|
||||||
@@ -2848,59 +2940,50 @@ do -- SET_UNIT
|
|||||||
-- @return Core.Point#COORDINATE The center coordinate of all the units in the set, including heading in degrees and speed in mps in case of moving units.
|
-- @return Core.Point#COORDINATE The center coordinate of all the units in the set, including heading in degrees and speed in mps in case of moving units.
|
||||||
function SET_UNIT:GetCoordinate()
|
function SET_UNIT:GetCoordinate()
|
||||||
|
|
||||||
|
local function GetSetVec3(units)
|
||||||
|
-- Init.
|
||||||
|
local x=0
|
||||||
|
local y=0
|
||||||
|
local z=0
|
||||||
|
local n=0
|
||||||
|
-- Loop over all units.
|
||||||
|
for _,unit in pairs(units) do
|
||||||
|
local vec3=nil --DCS#Vec3
|
||||||
|
if unit and unit:IsAlive() then
|
||||||
|
vec3 = unit:GetVec3()
|
||||||
|
end
|
||||||
|
if vec3 then
|
||||||
|
-- Sum up posits.
|
||||||
|
x=x+vec3.x
|
||||||
|
y=y+vec3.y
|
||||||
|
z=z+vec3.z
|
||||||
|
-- Increase counter.
|
||||||
|
n=n+1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if n>0 then
|
||||||
|
-- Average.
|
||||||
|
local Vec3={x=x/n, y=y/n, z=z/n} --DCS#Vec3
|
||||||
|
return Vec3
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
local Coordinate = nil
|
local Coordinate = nil
|
||||||
local unit = self:GetRandom()
|
local Vec3 = GetSetVec3(self.Set)
|
||||||
if self:Count() == 1 and unit then
|
if Vec3 then
|
||||||
return unit:GetCoordinate()
|
Coordinate = COORDINATE:NewFromVec3(Vec3)
|
||||||
end
|
|
||||||
if unit then
|
|
||||||
local Coordinate = unit:GetCoordinate()
|
|
||||||
--self:F({Coordinate:GetVec3()})
|
|
||||||
|
|
||||||
|
|
||||||
local x1 = Coordinate.x
|
|
||||||
local x2 = Coordinate.x
|
|
||||||
local y1 = Coordinate.y
|
|
||||||
local y2 = Coordinate.y
|
|
||||||
local z1 = Coordinate.z
|
|
||||||
local z2 = Coordinate.z
|
|
||||||
local MaxVelocity = 0
|
|
||||||
local AvgHeading = nil
|
|
||||||
local MovingCount = 0
|
|
||||||
|
|
||||||
for UnitName, UnitData in pairs( self:GetAliveSet() ) do
|
|
||||||
|
|
||||||
local Unit = UnitData -- Wrapper.Unit#UNIT
|
|
||||||
local Coordinate = Unit:GetCoordinate()
|
|
||||||
|
|
||||||
x1 = (Coordinate.x < x1) and Coordinate.x or x1
|
|
||||||
x2 = (Coordinate.x > x2) and Coordinate.x or x2
|
|
||||||
y1 = (Coordinate.y < y1) and Coordinate.y or y1
|
|
||||||
y2 = (Coordinate.y > y2) and Coordinate.y or y2
|
|
||||||
z1 = (Coordinate.y < z1) and Coordinate.z or z1
|
|
||||||
z2 = (Coordinate.y > z2) and Coordinate.z or z2
|
|
||||||
|
|
||||||
local Velocity = Coordinate:GetVelocity()
|
|
||||||
if Velocity ~= 0 then
|
|
||||||
MaxVelocity = (MaxVelocity < Velocity) and Velocity or MaxVelocity
|
|
||||||
local Heading = Coordinate:GetHeading()
|
|
||||||
AvgHeading = AvgHeading and (AvgHeading + Heading) or Heading
|
|
||||||
MovingCount = MovingCount + 1
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
AvgHeading = AvgHeading and (AvgHeading / MovingCount)
|
if Coordinate then
|
||||||
|
local heading = self:GetHeading() or 0
|
||||||
Coordinate.x = (x2 - x1) / 2 + x1
|
local velocity = self:GetVelocity() or 0
|
||||||
Coordinate.y = (y2 - y1) / 2 + y1
|
Coordinate:SetHeading( heading )
|
||||||
Coordinate.z = (z2 - z1) / 2 + z1
|
Coordinate:SetVelocity( velocity )
|
||||||
Coordinate:SetHeading( AvgHeading )
|
self:I(UTILS.PrintTableToLog(Coordinate))
|
||||||
Coordinate:SetVelocity( MaxVelocity )
|
|
||||||
|
|
||||||
self:F( { Coordinate = Coordinate } )
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return Coordinate
|
return Coordinate
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Get the maximum velocity of the SET_UNIT.
|
--- Get the maximum velocity of the SET_UNIT.
|
||||||
@@ -3109,7 +3192,7 @@ do -- SET_UNIT
|
|||||||
MUnitInclude = MUnitInclude and MUnitActive
|
MUnitInclude = MUnitInclude and MUnitActive
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.Filter.Coalitions then
|
if self.Filter.Coalitions and MUnitInclude then
|
||||||
local MUnitCoalition = false
|
local MUnitCoalition = false
|
||||||
for CoalitionID, CoalitionName in pairs( self.Filter.Coalitions ) do
|
for CoalitionID, CoalitionName in pairs( self.Filter.Coalitions ) do
|
||||||
self:F( { "Coalition:", MUnit:GetCoalition(), self.FilterMeta.Coalitions[CoalitionName], CoalitionName } )
|
self:F( { "Coalition:", MUnit:GetCoalition(), self.FilterMeta.Coalitions[CoalitionName], CoalitionName } )
|
||||||
@@ -3120,7 +3203,7 @@ do -- SET_UNIT
|
|||||||
MUnitInclude = MUnitInclude and MUnitCoalition
|
MUnitInclude = MUnitInclude and MUnitCoalition
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.Filter.Categories then
|
if self.Filter.Categories and MUnitInclude then
|
||||||
local MUnitCategory = false
|
local MUnitCategory = false
|
||||||
for CategoryID, CategoryName in pairs( self.Filter.Categories ) do
|
for CategoryID, CategoryName in pairs( self.Filter.Categories ) do
|
||||||
self:T3( { "Category:", MUnit:GetDesc().category, self.FilterMeta.Categories[CategoryName], CategoryName } )
|
self:T3( { "Category:", MUnit:GetDesc().category, self.FilterMeta.Categories[CategoryName], CategoryName } )
|
||||||
@@ -3131,7 +3214,7 @@ do -- SET_UNIT
|
|||||||
MUnitInclude = MUnitInclude and MUnitCategory
|
MUnitInclude = MUnitInclude and MUnitCategory
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.Filter.Types then
|
if self.Filter.Types and MUnitInclude then
|
||||||
local MUnitType = false
|
local MUnitType = false
|
||||||
for TypeID, TypeName in pairs( self.Filter.Types ) do
|
for TypeID, TypeName in pairs( self.Filter.Types ) do
|
||||||
self:T3( { "Type:", MUnit:GetTypeName(), TypeName } )
|
self:T3( { "Type:", MUnit:GetTypeName(), TypeName } )
|
||||||
@@ -3142,7 +3225,7 @@ do -- SET_UNIT
|
|||||||
MUnitInclude = MUnitInclude and MUnitType
|
MUnitInclude = MUnitInclude and MUnitType
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.Filter.Countries then
|
if self.Filter.Countries and MUnitInclude then
|
||||||
local MUnitCountry = false
|
local MUnitCountry = false
|
||||||
for CountryID, CountryName in pairs( self.Filter.Countries ) do
|
for CountryID, CountryName in pairs( self.Filter.Countries ) do
|
||||||
self:T3( { "Country:", MUnit:GetCountry(), CountryName } )
|
self:T3( { "Country:", MUnit:GetCountry(), CountryName } )
|
||||||
@@ -3153,7 +3236,7 @@ do -- SET_UNIT
|
|||||||
MUnitInclude = MUnitInclude and MUnitCountry
|
MUnitInclude = MUnitInclude and MUnitCountry
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.Filter.UnitPrefixes then
|
if self.Filter.UnitPrefixes and MUnitInclude then
|
||||||
local MUnitPrefix = false
|
local MUnitPrefix = false
|
||||||
for UnitPrefixId, UnitPrefix in pairs( self.Filter.UnitPrefixes ) do
|
for UnitPrefixId, UnitPrefix in pairs( self.Filter.UnitPrefixes ) do
|
||||||
self:T3( { "Prefix:", string.find( MUnit:GetName(), UnitPrefix, 1 ), UnitPrefix } )
|
self:T3( { "Prefix:", string.find( MUnit:GetName(), UnitPrefix, 1 ), UnitPrefix } )
|
||||||
@@ -3164,7 +3247,7 @@ do -- SET_UNIT
|
|||||||
MUnitInclude = MUnitInclude and MUnitPrefix
|
MUnitInclude = MUnitInclude and MUnitPrefix
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.Filter.RadarTypes then
|
if self.Filter.RadarTypes and MUnitInclude then
|
||||||
local MUnitRadar = false
|
local MUnitRadar = false
|
||||||
for RadarTypeID, RadarType in pairs( self.Filter.RadarTypes ) do
|
for RadarTypeID, RadarType in pairs( self.Filter.RadarTypes ) do
|
||||||
self:T3( { "Radar:", RadarType } )
|
self:T3( { "Radar:", RadarType } )
|
||||||
@@ -3178,7 +3261,7 @@ do -- SET_UNIT
|
|||||||
MUnitInclude = MUnitInclude and MUnitRadar
|
MUnitInclude = MUnitInclude and MUnitRadar
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.Filter.SEAD then
|
if self.Filter.SEAD and MUnitInclude then
|
||||||
local MUnitSEAD = false
|
local MUnitSEAD = false
|
||||||
if MUnit:HasSEAD() == true then
|
if MUnit:HasSEAD() == true then
|
||||||
self:T3( "SEAD Found" )
|
self:T3( "SEAD Found" )
|
||||||
@@ -3188,7 +3271,7 @@ do -- SET_UNIT
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.Filter.Zones then
|
if self.Filter.Zones and MUnitInclude then
|
||||||
local MGroupZone = false
|
local MGroupZone = false
|
||||||
for ZoneName, Zone in pairs( self.Filter.Zones ) do
|
for ZoneName, Zone in pairs( self.Filter.Zones ) do
|
||||||
self:T3( "Zone:", ZoneName )
|
self:T3( "Zone:", ZoneName )
|
||||||
@@ -3199,6 +3282,11 @@ do -- SET_UNIT
|
|||||||
MUnitInclude = MUnitInclude and MGroupZone
|
MUnitInclude = MUnitInclude and MGroupZone
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if self.Filter.Functions and MUnitInclude then
|
||||||
|
local MUnitFunc = self:_EvalFilterFunctions(MUnit)
|
||||||
|
MUnitInclude = MUnitInclude and MUnitFunc
|
||||||
|
end
|
||||||
|
|
||||||
self:T2( MUnitInclude )
|
self:T2( MUnitInclude )
|
||||||
return MUnitInclude
|
return MUnitInclude
|
||||||
end
|
end
|
||||||
@@ -3280,6 +3368,7 @@ do -- SET_STATIC
|
|||||||
-- * @{#SET_STATIC.FilterPrefixes}: Builds the SET_STATIC with the units containing the same string(s) in their name. **Attention!** LUA regular expression apply here, so special characters in names like minus, dot, hash (#) etc might lead to unexpected results.
|
-- * @{#SET_STATIC.FilterPrefixes}: Builds the SET_STATIC with the units containing the same string(s) in their name. **Attention!** LUA regular expression apply here, so special characters in names like minus, dot, hash (#) etc might lead to unexpected results.
|
||||||
-- Have a read through here to understand the application of regular expressions: [LUA regular expressions](https://riptutorial.com/lua/example/20315/lua-pattern-matching)
|
-- Have a read through here to understand the application of regular expressions: [LUA regular expressions](https://riptutorial.com/lua/example/20315/lua-pattern-matching)
|
||||||
-- * @{#SET_STATIC.FilterZones}: Builds the SET_STATIC with the units within a @{Core.Zone#ZONE}.
|
-- * @{#SET_STATIC.FilterZones}: Builds the SET_STATIC with the units within a @{Core.Zone#ZONE}.
|
||||||
|
-- * @{#SET_STATIC.FilterFunction}: Builds the SET_STATIC with a custom condition.
|
||||||
--
|
--
|
||||||
-- Once the filter criteria have been set for the SET_STATIC, you can start filtering using:
|
-- Once the filter criteria have been set for the SET_STATIC, you can start filtering using:
|
||||||
--
|
--
|
||||||
@@ -3483,6 +3572,24 @@ do -- SET_STATIC
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- [User] Add a custom condition function.
|
||||||
|
-- @function [parent=#SET_STATIC] FilterFunction
|
||||||
|
-- @param #SET_STATIC self
|
||||||
|
-- @param #function ConditionFunction If this function returns `true`, the object is added to the SET. The function needs to take a STATIC object as first argument.
|
||||||
|
-- @param ... Condition function arguments if any.
|
||||||
|
-- @return #SET_STATIC self
|
||||||
|
-- @usage
|
||||||
|
-- -- Image you want to exclude a specific CLIENT from a SET:
|
||||||
|
-- local groundset = SET_STATIC:New():FilterCoalitions("blue"):FilterActive(true):FilterFunction(
|
||||||
|
-- -- The function needs to take a STATIC object as first - and in this case, only - argument.
|
||||||
|
-- function(static)
|
||||||
|
-- local isinclude = true
|
||||||
|
-- if static:GetName() == "Exclude Me" then isinclude = false end
|
||||||
|
-- return isinclude
|
||||||
|
-- end
|
||||||
|
-- ):FilterOnce()
|
||||||
|
-- BASE:I(groundset:Flush())
|
||||||
|
|
||||||
--- Builds a set of units of defined countries.
|
--- Builds a set of units of defined countries.
|
||||||
-- Possible current countries are those known within DCS world.
|
-- Possible current countries are those known within DCS world.
|
||||||
-- @param #SET_STATIC self
|
-- @param #SET_STATIC self
|
||||||
@@ -4039,6 +4146,7 @@ do -- SET_CLIENT
|
|||||||
-- Have a read through here to understand the application of regular expressions: [LUA regular expressions](https://riptutorial.com/lua/example/20315/lua-pattern-matching)
|
-- Have a read through here to understand the application of regular expressions: [LUA regular expressions](https://riptutorial.com/lua/example/20315/lua-pattern-matching)
|
||||||
-- * @{#SET_CLIENT.FilterActive}: Builds the SET_CLIENT with the units that are only active. Units that are inactive (late activation) won't be included in the set!
|
-- * @{#SET_CLIENT.FilterActive}: Builds the SET_CLIENT with the units that are only active. Units that are inactive (late activation) won't be included in the set!
|
||||||
-- * @{#SET_CLIENT.FilterZones}: Builds the SET_CLIENT with the clients within a @{Core.Zone#ZONE}.
|
-- * @{#SET_CLIENT.FilterZones}: Builds the SET_CLIENT with the clients within a @{Core.Zone#ZONE}.
|
||||||
|
-- * @{#SET_CLIENT.FilterFunction}: Builds the SET_CLIENT with a custom condition.
|
||||||
--
|
--
|
||||||
-- Once the filter criteria have been set for the SET_CLIENT, you can start filtering using:
|
-- Once the filter criteria have been set for the SET_CLIENT, you can start filtering using:
|
||||||
--
|
--
|
||||||
@@ -4541,6 +4649,25 @@ do -- SET_CLIENT
|
|||||||
return AliveSet.Set or {}
|
return AliveSet.Set or {}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- [User] Add a custom condition function.
|
||||||
|
-- @function [parent=#SET_CLIENT] FilterFunction
|
||||||
|
-- @param #SET_CLIENT self
|
||||||
|
-- @param #function ConditionFunction If this function returns `true`, the object is added to the SET. The function needs to take a CLIENT object as first argument.
|
||||||
|
-- @param ... Condition function arguments if any.
|
||||||
|
-- @return #SET_CLIENT self
|
||||||
|
-- @usage
|
||||||
|
-- -- Image you want to exclude a specific CLIENT from a SET:
|
||||||
|
-- local groundset = SET_CLIENT:New():FilterCoalitions("blue"):FilterActive(true):FilterFunction(
|
||||||
|
-- -- The function needs to take a UNIT object as first - and in this case, only - argument.
|
||||||
|
-- function(client)
|
||||||
|
-- local isinclude = true
|
||||||
|
-- if client:GetPlayerName() == "Exclude Me" then isinclude = false end
|
||||||
|
-- return isinclude
|
||||||
|
-- end
|
||||||
|
-- ):FilterOnce()
|
||||||
|
-- BASE:I(groundset:Flush())
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
-- @param #SET_CLIENT self
|
-- @param #SET_CLIENT self
|
||||||
-- @param Wrapper.Client#CLIENT MClient
|
-- @param Wrapper.Client#CLIENT MClient
|
||||||
@@ -4562,7 +4689,7 @@ do -- SET_CLIENT
|
|||||||
MClientInclude = MClientInclude and MClientActive
|
MClientInclude = MClientInclude and MClientActive
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.Filter.Coalitions then
|
if self.Filter.Coalitions and MClientInclude then
|
||||||
local MClientCoalition = false
|
local MClientCoalition = false
|
||||||
for CoalitionID, CoalitionName in pairs( self.Filter.Coalitions ) do
|
for CoalitionID, CoalitionName in pairs( self.Filter.Coalitions ) do
|
||||||
local ClientCoalitionID = _DATABASE:GetCoalitionFromClientTemplate( MClientName )
|
local ClientCoalitionID = _DATABASE:GetCoalitionFromClientTemplate( MClientName )
|
||||||
@@ -4575,7 +4702,7 @@ do -- SET_CLIENT
|
|||||||
MClientInclude = MClientInclude and MClientCoalition
|
MClientInclude = MClientInclude and MClientCoalition
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.Filter.Categories then
|
if self.Filter.Categories and MClientInclude then
|
||||||
local MClientCategory = false
|
local MClientCategory = false
|
||||||
for CategoryID, CategoryName in pairs( self.Filter.Categories ) do
|
for CategoryID, CategoryName in pairs( self.Filter.Categories ) do
|
||||||
local ClientCategoryID = _DATABASE:GetCategoryFromClientTemplate( MClientName )
|
local ClientCategoryID = _DATABASE:GetCategoryFromClientTemplate( MClientName )
|
||||||
@@ -4588,7 +4715,7 @@ do -- SET_CLIENT
|
|||||||
MClientInclude = MClientInclude and MClientCategory
|
MClientInclude = MClientInclude and MClientCategory
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.Filter.Types then
|
if self.Filter.Types and MClientInclude then
|
||||||
local MClientType = false
|
local MClientType = false
|
||||||
for TypeID, TypeName in pairs( self.Filter.Types ) do
|
for TypeID, TypeName in pairs( self.Filter.Types ) do
|
||||||
self:T3( { "Type:", MClient:GetTypeName(), TypeName } )
|
self:T3( { "Type:", MClient:GetTypeName(), TypeName } )
|
||||||
@@ -4600,7 +4727,7 @@ do -- SET_CLIENT
|
|||||||
MClientInclude = MClientInclude and MClientType
|
MClientInclude = MClientInclude and MClientType
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.Filter.Countries then
|
if self.Filter.Countries and MClientInclude then
|
||||||
local MClientCountry = false
|
local MClientCountry = false
|
||||||
for CountryID, CountryName in pairs( self.Filter.Countries ) do
|
for CountryID, CountryName in pairs( self.Filter.Countries ) do
|
||||||
local ClientCountryID = _DATABASE:GetCountryFromClientTemplate( MClientName )
|
local ClientCountryID = _DATABASE:GetCountryFromClientTemplate( MClientName )
|
||||||
@@ -4613,7 +4740,7 @@ do -- SET_CLIENT
|
|||||||
MClientInclude = MClientInclude and MClientCountry
|
MClientInclude = MClientInclude and MClientCountry
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.Filter.ClientPrefixes then
|
if self.Filter.ClientPrefixes and MClientInclude then
|
||||||
local MClientPrefix = false
|
local MClientPrefix = false
|
||||||
for ClientPrefixId, ClientPrefix in pairs( self.Filter.ClientPrefixes ) do
|
for ClientPrefixId, ClientPrefix in pairs( self.Filter.ClientPrefixes ) do
|
||||||
self:T3( { "Prefix:", string.find( MClient.UnitName, ClientPrefix, 1 ), ClientPrefix } )
|
self:T3( { "Prefix:", string.find( MClient.UnitName, ClientPrefix, 1 ), ClientPrefix } )
|
||||||
@@ -4625,7 +4752,7 @@ do -- SET_CLIENT
|
|||||||
MClientInclude = MClientInclude and MClientPrefix
|
MClientInclude = MClientInclude and MClientPrefix
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.Filter.Zones then
|
if self.Filter.Zones and MClientInclude then
|
||||||
local MClientZone = false
|
local MClientZone = false
|
||||||
for ZoneName, Zone in pairs( self.Filter.Zones ) do
|
for ZoneName, Zone in pairs( self.Filter.Zones ) do
|
||||||
self:T3( "Zone:", ZoneName )
|
self:T3( "Zone:", ZoneName )
|
||||||
@@ -4637,7 +4764,7 @@ do -- SET_CLIENT
|
|||||||
MClientInclude = MClientInclude and MClientZone
|
MClientInclude = MClientInclude and MClientZone
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.Filter.Playernames then
|
if self.Filter.Playernames and MClientInclude then
|
||||||
local MClientPlayername = false
|
local MClientPlayername = false
|
||||||
local playername = MClient:GetPlayerName() or "Unknown"
|
local playername = MClient:GetPlayerName() or "Unknown"
|
||||||
--self:T(playername)
|
--self:T(playername)
|
||||||
@@ -4650,7 +4777,7 @@ do -- SET_CLIENT
|
|||||||
MClientInclude = MClientInclude and MClientPlayername
|
MClientInclude = MClientInclude and MClientPlayername
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.Filter.Callsigns then
|
if self.Filter.Callsigns and MClientInclude then
|
||||||
local MClientCallsigns = false
|
local MClientCallsigns = false
|
||||||
local callsign = MClient:GetCallsign()
|
local callsign = MClient:GetCallsign()
|
||||||
--self:I(callsign)
|
--self:I(callsign)
|
||||||
@@ -4663,6 +4790,11 @@ do -- SET_CLIENT
|
|||||||
MClientInclude = MClientInclude and MClientCallsigns
|
MClientInclude = MClientInclude and MClientCallsigns
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if self.Filter.Functions and MClientInclude then
|
||||||
|
local MClientFunc = self:_EvalFilterFunctions(MClient)
|
||||||
|
MClientInclude = MClientInclude and MClientFunc
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
self:T2( MClientInclude )
|
self:T2( MClientInclude )
|
||||||
return MClientInclude
|
return MClientInclude
|
||||||
@@ -5256,7 +5388,7 @@ do -- SET_AIRBASE
|
|||||||
function SET_AIRBASE:GetRandomAirbase()
|
function SET_AIRBASE:GetRandomAirbase()
|
||||||
|
|
||||||
local RandomAirbase = self:GetRandom()
|
local RandomAirbase = self:GetRandom()
|
||||||
self:F( { RandomAirbase = RandomAirbase:GetName() } )
|
--self:F( { RandomAirbase = RandomAirbase:GetName() } )
|
||||||
|
|
||||||
return RandomAirbase
|
return RandomAirbase
|
||||||
end
|
end
|
||||||
@@ -5422,7 +5554,7 @@ do -- SET_AIRBASE
|
|||||||
MAirbaseInclude = MAirbaseInclude and MAirbaseCoalition
|
MAirbaseInclude = MAirbaseInclude and MAirbaseCoalition
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.Filter.Categories then
|
if self.Filter.Categories and MAirbaseInclude then
|
||||||
local MAirbaseCategory = false
|
local MAirbaseCategory = false
|
||||||
for CategoryID, CategoryName in pairs( self.Filter.Categories ) do
|
for CategoryID, CategoryName in pairs( self.Filter.Categories ) do
|
||||||
local AirbaseCategoryID = _DATABASE:GetCategoryFromAirbase( MAirbaseName )
|
local AirbaseCategoryID = _DATABASE:GetCategoryFromAirbase( MAirbaseName )
|
||||||
@@ -7768,7 +7900,7 @@ do -- SET_OPSGROUP
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Filter coalitions.
|
-- Filter coalitions.
|
||||||
if self.Filter.Coalitions then
|
if self.Filter.Coalitions and MGroupInclude then
|
||||||
|
|
||||||
local MGroupCoalition = false
|
local MGroupCoalition = false
|
||||||
|
|
||||||
@@ -7782,7 +7914,7 @@ do -- SET_OPSGROUP
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Filter categories.
|
-- Filter categories.
|
||||||
if self.Filter.Categories then
|
if self.Filter.Categories and MGroupInclude then
|
||||||
|
|
||||||
local MGroupCategory = false
|
local MGroupCategory = false
|
||||||
|
|
||||||
@@ -7796,7 +7928,7 @@ do -- SET_OPSGROUP
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Filter countries.
|
-- Filter countries.
|
||||||
if self.Filter.Countries then
|
if self.Filter.Countries and MGroupInclude then
|
||||||
local MGroupCountry = false
|
local MGroupCountry = false
|
||||||
for CountryID, CountryName in pairs( self.Filter.Countries ) do
|
for CountryID, CountryName in pairs( self.Filter.Countries ) do
|
||||||
if country.id[CountryName] == MGroup:GetCountry() then
|
if country.id[CountryName] == MGroup:GetCountry() then
|
||||||
@@ -7807,12 +7939,12 @@ do -- SET_OPSGROUP
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Filter "prefixes".
|
-- Filter "prefixes".
|
||||||
if self.Filter.GroupPrefixes then
|
if self.Filter.GroupPrefixes and MGroupInclude then
|
||||||
|
|
||||||
local MGroupPrefix = false
|
local MGroupPrefix = false
|
||||||
|
|
||||||
for GroupPrefixId, GroupPrefix in pairs( self.Filter.GroupPrefixes ) do
|
for GroupPrefixId, GroupPrefix in pairs( self.Filter.GroupPrefixes ) do
|
||||||
if string.find( MGroup:GetName(), GroupPrefix:gsub ("-", "%%-"), 1 ) then --Not sure why "-" is replaced by "%-" ?!
|
if string.find( MGroup:GetName(), GroupPrefix:gsub ("-", "%%-"), 1 ) then --Not sure why "-" is replaced by "%-" ?! - So we can still match group names with a dash in them
|
||||||
MGroupPrefix = true
|
MGroupPrefix = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1108,6 +1108,22 @@ function SPAWN:InitRandomizeCallsign()
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- [BLUE AIR only!] This method sets a specific callsign for a spawned group. Use for a group with one unit only!
|
||||||
|
-- @param #SPAWN self
|
||||||
|
-- @param #number ID ID of the callsign enumerator, e.g. CALLSIGN.Tanker.Texaco - - resulting in e.g. Texaco-2-1
|
||||||
|
-- @param #string Name Name of this callsign as it cannot be determined from the ID because of the dependency on the task type of the plane, and the plane type. E.g. "Texaco"
|
||||||
|
-- @param #number Minor Minor number, i.e. the unit number within the group, e.g 2 - resulting in e.g. Texaco-2-1
|
||||||
|
-- @param #number Major Major number, i.e. the group number of this name, e.g. 1 - resulting in e.g. Texaco-2-1
|
||||||
|
-- @return #SPAWN self
|
||||||
|
function SPAWN:InitCallSign(ID,Name,Minor,Major)
|
||||||
|
self.SpawnInitCallSign = true
|
||||||
|
self.SpawnInitCallSignID = ID or 1
|
||||||
|
self.SpawnInitCallSignMinor = Minor or 1
|
||||||
|
self.SpawnInitCallSignMajor = Major or 1
|
||||||
|
self.SpawnInitCallSignName = string.lower(Name) or "enfield"
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- This method sets a spawn position for the group that is different from the location of the template.
|
--- This method sets a spawn position for the group that is different from the location of the template.
|
||||||
-- @param #SPAWN self
|
-- @param #SPAWN self
|
||||||
-- @param Core.Point#COORDINATE Coordinate The position to spawn from
|
-- @param Core.Point#COORDINATE Coordinate The position to spawn from
|
||||||
@@ -3331,10 +3347,23 @@ function SPAWN:_Prepare( SpawnTemplatePrefix, SpawnIndex ) -- R2.2
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if self.SpawnInitCallSign then
|
||||||
|
for UnitID = 1, #SpawnTemplate.units do
|
||||||
|
local Callsign = SpawnTemplate.units[UnitID].callsign
|
||||||
|
if Callsign and type( Callsign ) ~= "number" then
|
||||||
|
SpawnTemplate.units[UnitID].callsign[1] = self.SpawnInitCallSignID
|
||||||
|
SpawnTemplate.units[UnitID].callsign[2] = self.SpawnInitCallSignMinor
|
||||||
|
SpawnTemplate.units[UnitID].callsign[3] = self.SpawnInitCallSignMajor
|
||||||
|
SpawnTemplate.units[UnitID].callsign["name"] = string.format("%s%d%d",self.SpawnInitCallSignName,self.SpawnInitCallSignMinor,self.SpawnInitCallSignMajor)
|
||||||
|
--UTILS.PrintTableToLog(SpawnTemplate.units[UnitID].callsign,1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
for UnitID = 1, #SpawnTemplate.units do
|
for UnitID = 1, #SpawnTemplate.units do
|
||||||
local Callsign = SpawnTemplate.units[UnitID].callsign
|
local Callsign = SpawnTemplate.units[UnitID].callsign
|
||||||
if Callsign then
|
if Callsign then
|
||||||
if type( Callsign ) ~= "number" then -- blue callsign
|
if type( Callsign ) ~= "number" and not self.SpawnInitCallSign then -- blue callsign
|
||||||
-- UTILS.PrintTableToLog(Callsign,1)
|
-- UTILS.PrintTableToLog(Callsign,1)
|
||||||
Callsign[2] = ((SpawnIndex - 1) % 10) + 1
|
Callsign[2] = ((SpawnIndex - 1) % 10) + 1
|
||||||
local CallsignName = SpawnTemplate.units[UnitID].callsign["name"] -- #string
|
local CallsignName = SpawnTemplate.units[UnitID].callsign["name"] -- #string
|
||||||
@@ -3342,7 +3371,7 @@ function SPAWN:_Prepare( SpawnTemplatePrefix, SpawnIndex ) -- R2.2
|
|||||||
local CallsignLen = CallsignName:len()
|
local CallsignLen = CallsignName:len()
|
||||||
SpawnTemplate.units[UnitID].callsign[2] = UnitID
|
SpawnTemplate.units[UnitID].callsign[2] = UnitID
|
||||||
SpawnTemplate.units[UnitID].callsign["name"] = CallsignName:sub( 1, CallsignLen ) .. SpawnTemplate.units[UnitID].callsign[2] .. SpawnTemplate.units[UnitID].callsign[3]
|
SpawnTemplate.units[UnitID].callsign["name"] = CallsignName:sub( 1, CallsignLen ) .. SpawnTemplate.units[UnitID].callsign[2] .. SpawnTemplate.units[UnitID].callsign[3]
|
||||||
else
|
elseif type( Callsign ) == "number" then
|
||||||
SpawnTemplate.units[UnitID].callsign = Callsign + SpawnIndex
|
SpawnTemplate.units[UnitID].callsign = Callsign + SpawnIndex
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -3377,11 +3406,11 @@ function SPAWN:_Prepare( SpawnTemplatePrefix, SpawnIndex ) -- R2.2
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
-- VoiceCallsignNumber
|
-- VoiceCallsignNumber
|
||||||
if SpawnTemplate.units[UnitID].AddPropAircraft.VoiceCallsignNumber then
|
if SpawnTemplate.units[UnitID].AddPropAircraft.VoiceCallsignNumber and type( Callsign ) ~= "number" then
|
||||||
SpawnTemplate.units[UnitID].AddPropAircraft.VoiceCallsignNumber = SpawnTemplate.units[UnitID].callsign[2] .. SpawnTemplate.units[UnitID].callsign[3]
|
SpawnTemplate.units[UnitID].AddPropAircraft.VoiceCallsignNumber = SpawnTemplate.units[UnitID].callsign[2] .. SpawnTemplate.units[UnitID].callsign[3]
|
||||||
end
|
end
|
||||||
-- VoiceCallsignLabel
|
-- VoiceCallsignLabel
|
||||||
if SpawnTemplate.units[UnitID].AddPropAircraft.VoiceCallsignLabel then
|
if SpawnTemplate.units[UnitID].AddPropAircraft.VoiceCallsignLabel and type( Callsign ) ~= "number" then
|
||||||
local CallsignName = SpawnTemplate.units[UnitID].callsign["name"] -- #string
|
local CallsignName = SpawnTemplate.units[UnitID].callsign["name"] -- #string
|
||||||
CallsignName = string.match(CallsignName,"^(%a+)") -- 2.8 - only the part w/o numbers
|
CallsignName = string.match(CallsignName,"^(%a+)") -- 2.8 - only the part w/o numbers
|
||||||
local label = "NY" -- Navy One exception
|
local label = "NY" -- Navy One exception
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
-- * Create moving zones around a unit.
|
-- * Create moving zones around a unit.
|
||||||
-- * Create moving zones around a group.
|
-- * Create moving zones around a group.
|
||||||
-- * Provide the zone behavior. Some zones are static, while others are moveable.
|
-- * Provide the zone behavior. Some zones are static, while others are moveable.
|
||||||
-- * Enquiry if a coordinate is within a zone.
|
-- * Enquire if a coordinate is within a zone.
|
||||||
-- * Smoke zones.
|
-- * Smoke zones.
|
||||||
-- * Set a zone probability to control zone selection.
|
-- * Set a zone probability to control zone selection.
|
||||||
-- * Get zone coordinates.
|
-- * Get zone coordinates.
|
||||||
@@ -42,7 +42,7 @@
|
|||||||
-- * @{#ZONE_UNIT}: The ZONE_UNIT class defines by a zone around a @{Wrapper.Unit#UNIT} with a radius.
|
-- * @{#ZONE_UNIT}: The ZONE_UNIT class defines by a zone around a @{Wrapper.Unit#UNIT} with a radius.
|
||||||
-- * @{#ZONE_GROUP}: The ZONE_GROUP class defines by a zone around a @{Wrapper.Group#GROUP} with a radius.
|
-- * @{#ZONE_GROUP}: The ZONE_GROUP class defines by a zone around a @{Wrapper.Group#GROUP} with a radius.
|
||||||
-- * @{#ZONE_POLYGON}: The ZONE_POLYGON class defines by a sequence of @{Wrapper.Group#GROUP} waypoints within the Mission Editor, forming a polygon.
|
-- * @{#ZONE_POLYGON}: The ZONE_POLYGON class defines by a sequence of @{Wrapper.Group#GROUP} waypoints within the Mission Editor, forming a polygon.
|
||||||
-- * @{#ZONE_OVAL}: The ZONE_OVAL class isdefined by a center point, major axis, minor axis, and angle.
|
-- * @{#ZONE_OVAL}: The ZONE_OVAL class is defined by a center point, major axis, minor axis, and angle.
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
@@ -2015,249 +2015,33 @@ function ZONE_GROUP:GetRandomPointVec2( inner, outer )
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- ZONE_OVAL created from a center point, major axis, minor axis, and angle.
|
|
||||||
-- Ported from https://github.com/nielsvaes/CCMOOSE/blob/master/Moose%20Development/Moose/Shapes/Oval.lua
|
|
||||||
-- @type ZONE_OVAL
|
|
||||||
-- @extends Core.Zone#ZONE_BASE
|
|
||||||
|
|
||||||
--- ## ZONE_OVAL class, extends @{#ZONE_BASE}
|
|
||||||
--
|
|
||||||
-- The ZONE_OVAL class is defined by a center point, major axis, minor axis, and angle.
|
|
||||||
-- This class implements the inherited functions from @{#ZONE_BASE} taking into account the own zone format and properties.
|
|
||||||
--
|
|
||||||
-- @field #ZONE_OVAL
|
|
||||||
ZONE_OVAL = {
|
|
||||||
ClassName = "OVAL",
|
|
||||||
ZoneName="",
|
|
||||||
MajorAxis = nil,
|
|
||||||
MinorAxis = nil,
|
|
||||||
Angle = 0,
|
|
||||||
DrawPoly = nil -- let's just use a ZONE_POLYGON to draw the ZONE_OVAL on the map
|
|
||||||
}
|
|
||||||
|
|
||||||
--- Creates a new ZONE_OVAL from a center point, major axis, minor axis, and angle.
|
|
||||||
--- ported from https://github.com/nielsvaes/CCMOOSE/blob/master/Moose%20Development/Moose/Shapes/Oval.lua
|
|
||||||
-- @param #table vec2 The center point of the oval
|
|
||||||
-- @param #number major_axis The major axis of the oval
|
|
||||||
-- @param #number minor_axis The minor axis of the oval
|
|
||||||
-- @param #number angle The angle of the oval
|
|
||||||
-- @return #ZONE_OVAL The new oval
|
|
||||||
function ZONE_OVAL:New(name, vec2, major_axis, minor_axis, angle)
|
|
||||||
self = BASE:Inherit(self, ZONE_BASE:New())
|
|
||||||
self.ZoneName = name
|
|
||||||
self.CenterVec2 = vec2
|
|
||||||
self.MajorAxis = major_axis
|
|
||||||
self.MinorAxis = minor_axis
|
|
||||||
self.Angle = angle or 0
|
|
||||||
|
|
||||||
_DATABASE:AddZone(name, self)
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Constructor to create a ZONE_OVAL instance, taking the name of a drawing made with the draw tool in the Mission Editor.
|
|
||||||
--- ported from https://github.com/nielsvaes/CCMOOSE/blob/master/Moose%20Development/Moose/Shapes/Oval.lua
|
|
||||||
-- @param #ZONE_OVAL self
|
|
||||||
-- @param #string DrawingName The name of the drawing in the Mission Editor
|
|
||||||
-- @return #ZONE_OVAL self
|
|
||||||
function ZONE_OVAL:NewFromDrawing(DrawingName)
|
|
||||||
self = BASE:Inherit(self, ZONE_BASE:New(DrawingName))
|
|
||||||
for _, layer in pairs(env.mission.drawings.layers) do
|
|
||||||
for _, object in pairs(layer["objects"]) do
|
|
||||||
if string.find(object["name"], DrawingName, 1, true) then
|
|
||||||
if object["polygonMode"] == "oval" then
|
|
||||||
self.CenterVec2 = { x = object["mapX"], y = object["mapY"] }
|
|
||||||
self.MajorAxis = object["r1"]
|
|
||||||
self.MinorAxis = object["r2"]
|
|
||||||
self.Angle = object["angle"]
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
_DATABASE:AddZone(DrawingName, self)
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Gets the major axis of the oval.
|
|
||||||
-- @param #ZONE_OVAL self
|
|
||||||
-- @return #number The major axis of the oval
|
|
||||||
function ZONE_OVAL:GetMajorAxis()
|
|
||||||
return self.MajorAxis
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Gets the minor axis of the oval.
|
|
||||||
-- @param #ZONE_OVAL self
|
|
||||||
-- @return #number The minor axis of the oval
|
|
||||||
function ZONE_OVAL:GetMinorAxis()
|
|
||||||
return self.MinorAxis
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Gets the angle of the oval.
|
|
||||||
-- @param #ZONE_OVAL self
|
|
||||||
-- @return #number The angle of the oval
|
|
||||||
function ZONE_OVAL:GetAngle()
|
|
||||||
return self.Angle
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Returns a the center point of the oval
|
|
||||||
-- @param #ZONE_OVAL self
|
|
||||||
-- @return #table The center Vec2
|
|
||||||
function ZONE_OVAL:GetVec2()
|
|
||||||
return self.CenterVec2
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Checks if a point is contained within the oval.
|
|
||||||
-- @param #ZONE_OVAL self
|
|
||||||
-- @param #table point The point to check
|
|
||||||
-- @return #bool True if the point is contained, false otherwise
|
|
||||||
function ZONE_OVAL:IsVec2InZone(vec2)
|
|
||||||
local cos, sin = math.cos, math.sin
|
|
||||||
local dx = vec2.x - self.CenterVec2.x
|
|
||||||
local dy = vec2.y - self.CenterVec2.y
|
|
||||||
local rx = dx * cos(self.Angle) + dy * sin(self.Angle)
|
|
||||||
local ry = -dx * sin(self.Angle) + dy * cos(self.Angle)
|
|
||||||
return rx * rx / (self.MajorAxis * self.MajorAxis) + ry * ry / (self.MinorAxis * self.MinorAxis) <= 1
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Calculates the bounding box of the oval. The bounding box is the smallest rectangle that contains the oval.
|
|
||||||
-- @param #ZONE_OVAL self
|
|
||||||
-- @return #table The bounding box of the oval
|
|
||||||
function ZONE_OVAL:GetBoundingSquare()
|
|
||||||
local min_x = self.CenterVec2.x - self.MajorAxis
|
|
||||||
local min_y = self.CenterVec2.y - self.MinorAxis
|
|
||||||
local max_x = self.CenterVec2.x + self.MajorAxis
|
|
||||||
local max_y = self.CenterVec2.y + self.MinorAxis
|
|
||||||
|
|
||||||
return {
|
|
||||||
{x=min_x, y=min_x}, {x=max_x, y=min_y}, {x=max_x, y=max_y}, {x=min_x, y=max_y}
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Find points on the edge of the oval
|
|
||||||
-- @param #ZONE_OVAL self
|
|
||||||
-- @param #number num_points How many points should be found. More = smoother shape
|
|
||||||
-- @return #table Points on he edge
|
|
||||||
function ZONE_OVAL:PointsOnEdge(num_points)
|
|
||||||
num_points = num_points or 40
|
|
||||||
local points = {}
|
|
||||||
local dtheta = 2 * math.pi / num_points
|
|
||||||
|
|
||||||
for i = 0, num_points - 1 do
|
|
||||||
local theta = i * dtheta
|
|
||||||
local x = self.CenterVec2.x + self.MajorAxis * math.cos(theta) * math.cos(self.Angle) - self.MinorAxis * math.sin(theta) * math.sin(self.Angle)
|
|
||||||
local y = self.CenterVec2.y + self.MajorAxis * math.cos(theta) * math.sin(self.Angle) + self.MinorAxis * math.sin(theta) * math.cos(self.Angle)
|
|
||||||
table.insert(points, {x = x, y = y})
|
|
||||||
end
|
|
||||||
|
|
||||||
return points
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Returns a random Vec2 within the oval.
|
|
||||||
-- @param #ZONE_OVAL self
|
|
||||||
-- @return #table The random Vec2
|
|
||||||
function ZONE_OVAL:GetRandomVec2()
|
|
||||||
local theta = math.rad(self.Angle)
|
|
||||||
|
|
||||||
local random_point = math.sqrt(math.random()) --> uniformly
|
|
||||||
--local random_point = math.random() --> more clumped around center
|
|
||||||
local phi = math.random() * 2 * math.pi
|
|
||||||
local x_c = random_point * math.cos(phi)
|
|
||||||
local y_c = random_point * math.sin(phi)
|
|
||||||
local x_e = x_c * self.MajorAxis
|
|
||||||
local y_e = y_c * self.MinorAxis
|
|
||||||
local rx = (x_e * math.cos(theta) - y_e * math.sin(theta)) + self.CenterVec2.x
|
|
||||||
local ry = (x_e * math.sin(theta) + y_e * math.cos(theta)) + self.CenterVec2.y
|
|
||||||
|
|
||||||
return {x=rx, y=ry}
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Define a random @{Core.Point#POINT_VEC2} within the zone.
|
|
||||||
-- @param #ZONE_OVAL self
|
|
||||||
-- @return Core.Point#POINT_VEC2 The PointVec2 coordinates.
|
|
||||||
function ZONE_OVAL:GetRandomPointVec2()
|
|
||||||
return POINT_VEC2:NewFromVec2(self:GetRandomVec2())
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Define a random @{Core.Point#POINT_VEC2} within the zone.
|
|
||||||
-- @param #ZONE_OVAL self
|
|
||||||
-- @return Core.Point#POINT_VEC2 The PointVec2 coordinates.
|
|
||||||
function ZONE_OVAL:GetRandomPointVec3()
|
|
||||||
return POINT_VEC2:NewFromVec3(self:GetRandomVec2())
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Draw the zone on the F10 map.
|
|
||||||
--- ported from https://github.com/nielsvaes/CCMOOSE/blob/master/Moose%20Development/Moose/Shapes/Oval.lua
|
|
||||||
-- @param #ZONE_OVAL self
|
|
||||||
-- @param #number Coalition Coalition: All=-1, Neutral=0, Red=1, Blue=2. Default -1=All.
|
|
||||||
-- @param #table Color RGB color table {r, g, b}, e.g. {1,0,0} for red.
|
|
||||||
-- @param #number Alpha Transparency [0,1]. Default 1.
|
|
||||||
-- @param #table FillColor RGB color table {r, g, b}, e.g. {1,0,0} for red. Default is same as `Color` value. -- doesn't seem to work
|
|
||||||
-- @param #number FillAlpha Transparency [0,1]. Default 0.15. -- doesn't seem to work
|
|
||||||
-- @param #number LineType Line type: 0=No line, 1=Solid, 2=Dashed, 3=Dotted, 4=Dot dash, 5=Long dash, 6=Two dash. Default 1=Solid.
|
|
||||||
-- @param #boolean ReadOnly (Optional) Mark is readonly and cannot be removed by users. Default false.
|
|
||||||
-- @return #ZONE_OVAL self
|
|
||||||
function ZONE_OVAL:DrawZone(Coalition, Color, Alpha, FillColor, FillAlpha, LineType)
|
|
||||||
Coalition = Coalition or self:GetDrawCoalition()
|
|
||||||
|
|
||||||
-- Set draw coalition.
|
|
||||||
self:SetDrawCoalition(Coalition)
|
|
||||||
|
|
||||||
Color = Color or self:GetColorRGB()
|
|
||||||
Alpha = Alpha or 1
|
|
||||||
|
|
||||||
-- Set color.
|
|
||||||
self:SetColor(Color, Alpha)
|
|
||||||
|
|
||||||
FillColor = FillColor or self:GetFillColorRGB()
|
|
||||||
if not FillColor then
|
|
||||||
UTILS.DeepCopy(Color)
|
|
||||||
end
|
|
||||||
FillAlpha = FillAlpha or self:GetFillColorAlpha()
|
|
||||||
if not FillAlpha then
|
|
||||||
FillAlpha = 0.15
|
|
||||||
end
|
|
||||||
|
|
||||||
LineType = LineType or 1
|
|
||||||
|
|
||||||
-- Set fill color -----------> has fill color worked in recent versions of DCS?
|
|
||||||
-- doing something like
|
|
||||||
--
|
|
||||||
-- trigger.action.markupToAll(7, -1, 501, p.Coords[1]:GetVec3(), p.Coords[2]:GetVec3(),p.Coords[3]:GetVec3(),p.Coords[4]:GetVec3(),{1,0,0, 1}, {1,0,0, 1}, 4, false, Text or "")
|
|
||||||
--
|
|
||||||
-- doesn't seem to fill in the shape for an n-sided polygon
|
|
||||||
self:SetFillColor(FillColor, FillAlpha)
|
|
||||||
|
|
||||||
self.DrawPoly = ZONE_POLYGON:NewFromPointsArray(self.ZoneName, self:PointsOnEdge(80))
|
|
||||||
self.DrawPoly:DrawZone(Coalition, Color, Alpha, FillColor, FillAlpha, LineType)
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Remove drawing from F10 map
|
|
||||||
-- @param #ZONE_OVAL self
|
|
||||||
function ZONE_OVAL:UndrawZone()
|
|
||||||
if self.DrawPoly then
|
|
||||||
self.DrawPoly:UndrawZone()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
--- Ported from https://github.com/nielsvaes/CCMOOSE/blob/master/Moose%20Development/Moose/Shapes/Triangle.lua
|
--- Ported from https://github.com/nielsvaes/CCMOOSE/blob/master/Moose%20Development/Moose/Shapes/Triangle.lua
|
||||||
--- This triangle "zone" is not really to be used on its own, it only serves as building blocks for
|
--- This triangle "zone" is not really to be used on its own, it only serves as building blocks for
|
||||||
--- ZONE_POLYGON to accurately find a point inside a polygon; as well as getting the correct surface area of
|
--- ZONE_POLYGON to accurately find a point inside a polygon; as well as getting the correct surface area of
|
||||||
--- a polygon.
|
--- a polygon.
|
||||||
-- @type _ZONE_TRIANGLE
|
-- @type _ZONE_TRIANGLE
|
||||||
-- @extends #BASE
|
-- @extends Core.Zone#ZONE_BASE
|
||||||
|
|
||||||
|
--- ## _ZONE_TRIANGLE class, extends @{#ZONE_BASE}
|
||||||
|
--
|
||||||
|
-- _ZONE_TRIANGLE class is a helper class for ZONE_POLYGON
|
||||||
|
-- This class implements the inherited functions from @{#ZONE_BASE} taking into account the own zone format and properties.
|
||||||
|
--
|
||||||
|
-- @field #_ZONE_TRIANGLE
|
||||||
_ZONE_TRIANGLE = {
|
_ZONE_TRIANGLE = {
|
||||||
ClassName="ZONE_TRIANGLE",
|
ClassName="ZONE_TRIANGLE",
|
||||||
Points={},
|
Points={},
|
||||||
Coords={},
|
Coords={},
|
||||||
CenterVec2={x=0, y=0},
|
CenterVec2={x=0, y=0},
|
||||||
SurfaceArea=0,
|
SurfaceArea=0,
|
||||||
DrawIDs={}
|
DrawID={}
|
||||||
}
|
}
|
||||||
|
---
|
||||||
|
-- @param #_ZONE_TRIANGLE self
|
||||||
|
-- @param DCS#Vec p1
|
||||||
|
-- @param DCS#Vec p2
|
||||||
|
-- @param DCS#Vec p3
|
||||||
|
-- @return #_ZONE_TRIANGLE self
|
||||||
function _ZONE_TRIANGLE:New(p1, p2, p3)
|
function _ZONE_TRIANGLE:New(p1, p2, p3)
|
||||||
local self = BASE:Inherit(self, ZONE_BASE:New())
|
local self = BASE:Inherit(self, ZONE_BASE:New())
|
||||||
self.Points = {p1, p2, p3}
|
self.Points = {p1, p2, p3}
|
||||||
@@ -2276,6 +2060,7 @@ function _ZONE_TRIANGLE:New(p1, p2, p3)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Checks if a point is contained within the triangle.
|
--- Checks if a point is contained within the triangle.
|
||||||
|
-- @param #_ZONE_TRIANGLE self
|
||||||
-- @param #table pt The point to check
|
-- @param #table pt The point to check
|
||||||
-- @param #table points (optional) The points of the triangle, or 3 other points if you're just using the TRIANGLE class without an object of it
|
-- @param #table points (optional) The points of the triangle, or 3 other points if you're just using the TRIANGLE class without an object of it
|
||||||
-- @return #bool True if the point is contained, false otherwise
|
-- @return #bool True if the point is contained, false otherwise
|
||||||
@@ -2297,6 +2082,7 @@ function _ZONE_TRIANGLE:ContainsPoint(pt, points)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Returns a random Vec2 within the triangle.
|
--- Returns a random Vec2 within the triangle.
|
||||||
|
-- @param #_ZONE_TRIANGLE self
|
||||||
-- @param #table points The points of the triangle, or 3 other points if you're just using the TRIANGLE class without an object of it
|
-- @param #table points The points of the triangle, or 3 other points if you're just using the TRIANGLE class without an object of it
|
||||||
-- @return #table The random Vec2
|
-- @return #table The random Vec2
|
||||||
function _ZONE_TRIANGLE:GetRandomVec2(points)
|
function _ZONE_TRIANGLE:GetRandomVec2(points)
|
||||||
@@ -2312,6 +2098,8 @@ function _ZONE_TRIANGLE:GetRandomVec2(points)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Draw the triangle
|
--- Draw the triangle
|
||||||
|
-- @param #_ZONE_TRIANGLE self
|
||||||
|
-- @return #table of draw IDs
|
||||||
function _ZONE_TRIANGLE:Draw(Coalition, Color, Alpha, FillColor, FillAlpha, LineType, ReadOnly)
|
function _ZONE_TRIANGLE:Draw(Coalition, Color, Alpha, FillColor, FillAlpha, LineType, ReadOnly)
|
||||||
Coalition=Coalition or -1
|
Coalition=Coalition or -1
|
||||||
|
|
||||||
@@ -2326,15 +2114,35 @@ function _ZONE_TRIANGLE:Draw(Coalition, Color, Alpha, FillColor, FillAlpha, Line
|
|||||||
for i=1, #self.Coords do
|
for i=1, #self.Coords do
|
||||||
local c1 = self.Coords[i]
|
local c1 = self.Coords[i]
|
||||||
local c2 = self.Coords[i % #self.Coords + 1]
|
local c2 = self.Coords[i % #self.Coords + 1]
|
||||||
table.add(self.DrawIDs, c1:LineToAll(c2, Coalition, Color, Alpha, LineType, ReadOnly))
|
local id = c1:LineToAll(c2, Coalition, Color, Alpha, LineType, ReadOnly)
|
||||||
|
self.DrawID[#self.DrawID+1] = id
|
||||||
end
|
end
|
||||||
return self.DrawIDs
|
local newID = self.Coords[1]:MarkupToAllFreeForm({self.Coords[2],self.Coords[3]},Coalition,Color,Alpha,FillColor,FillAlpha,LineType,ReadOnly)
|
||||||
|
self.DrawID[#self.DrawID+1] = newID
|
||||||
|
return self.DrawID
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Draw the triangle
|
||||||
|
-- @param #_ZONE_TRIANGLE self
|
||||||
|
-- @return #table of draw IDs
|
||||||
|
function _ZONE_TRIANGLE:Fill(Coalition, FillColor, FillAlpha, ReadOnly)
|
||||||
|
Coalition=Coalition or -1
|
||||||
|
FillColor = FillColor
|
||||||
|
FillAlpha = FillAlpha
|
||||||
|
local newID = self.Coords[1]:MarkupToAllFreeForm({self.Coords[2],self.Coords[3]},Coalition,nil,nil,FillColor,FillAlpha,0,nil)
|
||||||
|
self.DrawID[#self.DrawID+1] = newID
|
||||||
|
return self.DrawID
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
-- @type ZONE_POLYGON_BASE
|
-- @type ZONE_POLYGON_BASE
|
||||||
-- @field #ZONE_POLYGON_BASE.ListVec2 Polygon The polygon defined by an array of @{DCS#Vec2}.
|
-- @field #ZONE_POLYGON_BASE.ListVec2 Polygon The polygon defined by an array of @{DCS#Vec2}.
|
||||||
|
-- @field #number SurfaceArea
|
||||||
|
-- @field #table DrawID
|
||||||
|
-- @field #table FillTriangles
|
||||||
|
-- @field #table _Triangles
|
||||||
|
-- @field #table Borderlines
|
||||||
-- @extends #ZONE_BASE
|
-- @extends #ZONE_BASE
|
||||||
|
|
||||||
|
|
||||||
@@ -2359,9 +2167,11 @@ end
|
|||||||
-- @field #ZONE_POLYGON_BASE
|
-- @field #ZONE_POLYGON_BASE
|
||||||
ZONE_POLYGON_BASE = {
|
ZONE_POLYGON_BASE = {
|
||||||
ClassName="ZONE_POLYGON_BASE",
|
ClassName="ZONE_POLYGON_BASE",
|
||||||
_Triangles={}, -- _ZONE_TRIANGLES
|
_Triangles={}, -- #table of #_ZONE_TRIANGLE
|
||||||
SurfaceArea=0,
|
SurfaceArea=0,
|
||||||
DrawID={} -- making a table out of the MarkID so its easier to draw an n-sided polygon, see ZONE_POLYGON_BASE:Draw()
|
DrawID={}, -- making a table out of the MarkID so its easier to draw an n-sided polygon, see ZONE_POLYGON_BASE:Draw()
|
||||||
|
FillTriangles = {},
|
||||||
|
Borderlines = {},
|
||||||
}
|
}
|
||||||
|
|
||||||
--- A 2D points array.
|
--- A 2D points array.
|
||||||
@@ -2394,19 +2204,20 @@ function ZONE_POLYGON_BASE:New( ZoneName, PointsArray )
|
|||||||
self._.Polygon[i].y = PointsArray[i].y
|
self._.Polygon[i].y = PointsArray[i].y
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
-- triangulate the polygon so we can work with it
|
-- triangulate the polygon so we can work with it
|
||||||
self._Triangles = self:_Triangulate()
|
self._Triangles = self:_Triangulate()
|
||||||
-- set the polygon's surface area
|
-- set the polygon's surface area
|
||||||
self.SurfaceArea = self:_CalculateSurfaceArea()
|
self.SurfaceArea = self:_CalculateSurfaceArea()
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Triangulates the polygon.
|
--- Triangulates the polygon.
|
||||||
--- ported from https://github.com/nielsvaes/CCMOOSE/blob/master/Moose%20Development/Moose/Shapes/Polygon.lua
|
--- ported from https://github.com/nielsvaes/CCMOOSE/blob/master/Moose%20Development/Moose/Shapes/Polygon.lua
|
||||||
-- @return #table The #_TRIANGLE list that make up
|
-- @param #ZONE_POLYGON_BASE self
|
||||||
|
-- @return #table The #_ZONE_TRIANGLE list that makes up the polygon
|
||||||
function ZONE_POLYGON_BASE:_Triangulate()
|
function ZONE_POLYGON_BASE:_Triangulate()
|
||||||
local points = self._.Polygon
|
local points = self._.Polygon
|
||||||
local triangles = {}
|
local triangles = {}
|
||||||
@@ -2535,6 +2346,7 @@ end
|
|||||||
|
|
||||||
--- Calculates the surface area of the polygon. The surface area is the sum of the areas of the triangles that make up the polygon.
|
--- Calculates the surface area of the polygon. The surface area is the sum of the areas of the triangles that make up the polygon.
|
||||||
--- ported from https://github.com/nielsvaes/CCMOOSE/blob/master/Moose%20Development/Moose/Shapes/Polygon.lua
|
--- ported from https://github.com/nielsvaes/CCMOOSE/blob/master/Moose%20Development/Moose/Shapes/Polygon.lua
|
||||||
|
-- @param #ZONE_POLYGON_BASE self
|
||||||
-- @return #number The surface area of the polygon
|
-- @return #number The surface area of the polygon
|
||||||
function ZONE_POLYGON_BASE:_CalculateSurfaceArea()
|
function ZONE_POLYGON_BASE:_CalculateSurfaceArea()
|
||||||
local area = 0
|
local area = 0
|
||||||
@@ -2694,9 +2506,11 @@ end
|
|||||||
-- @param #table FillColor RGB color table {r, g, b}, e.g. {1,0,0} for red. Default is same as `Color` value. -- doesn't seem to work
|
-- @param #table FillColor RGB color table {r, g, b}, e.g. {1,0,0} for red. Default is same as `Color` value. -- doesn't seem to work
|
||||||
-- @param #number FillAlpha Transparency [0,1]. Default 0.15. -- doesn't seem to work
|
-- @param #number FillAlpha Transparency [0,1]. Default 0.15. -- doesn't seem to work
|
||||||
-- @param #number LineType Line type: 0=No line, 1=Solid, 2=Dashed, 3=Dotted, 4=Dot dash, 5=Long dash, 6=Two dash. Default 1=Solid.
|
-- @param #number LineType Line type: 0=No line, 1=Solid, 2=Dashed, 3=Dotted, 4=Dot dash, 5=Long dash, 6=Two dash. Default 1=Solid.
|
||||||
-- @param #boolean ReadOnly (Optional) Mark is readonly and cannot be removed by users. Default false.
|
-- @param #boolean ReadOnly (Optional) Mark is readonly and cannot be removed by users. Default false.s
|
||||||
-- @return #ZONE_POLYGON_BASE self
|
-- @return #ZONE_POLYGON_BASE self
|
||||||
function ZONE_POLYGON_BASE:DrawZone(Coalition, Color, Alpha, FillColor, FillAlpha, LineType, ReadOnly, IncludeTriangles)
|
function ZONE_POLYGON_BASE:DrawZone(Coalition, Color, Alpha, FillColor, FillAlpha, LineType, ReadOnly, IncludeTriangles)
|
||||||
|
|
||||||
|
|
||||||
if self._.Polygon and #self._.Polygon >= 3 then
|
if self._.Polygon and #self._.Polygon >= 3 then
|
||||||
Coalition = Coalition or self:GetDrawCoalition()
|
Coalition = Coalition or self:GetDrawCoalition()
|
||||||
|
|
||||||
@@ -2704,45 +2518,99 @@ function ZONE_POLYGON_BASE:DrawZone(Coalition, Color, Alpha, FillColor, FillAlph
|
|||||||
self:SetDrawCoalition(Coalition)
|
self:SetDrawCoalition(Coalition)
|
||||||
|
|
||||||
Color = Color or self:GetColorRGB()
|
Color = Color or self:GetColorRGB()
|
||||||
Alpha = Alpha or 1
|
Alpha = Alpha or self:GetColorAlpha()
|
||||||
|
|
||||||
-- Set color.
|
|
||||||
self:SetColor(Color, Alpha)
|
|
||||||
|
|
||||||
FillColor = FillColor or self:GetFillColorRGB()
|
FillColor = FillColor or self:GetFillColorRGB()
|
||||||
if not FillColor then
|
|
||||||
UTILS.DeepCopy(Color)
|
|
||||||
end
|
|
||||||
FillAlpha = FillAlpha or self:GetFillColorAlpha()
|
FillAlpha = FillAlpha or self:GetFillColorAlpha()
|
||||||
if not FillAlpha then
|
|
||||||
FillAlpha = 0.15
|
if FillColor then
|
||||||
|
self:ReFill(FillColor,FillAlpha)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Set fill color -----------> has fill color worked in recent versions of DCS?
|
if Color then
|
||||||
-- doing something like
|
self:ReDrawBorderline(Color,Alpha,LineType)
|
||||||
--
|
end
|
||||||
-- trigger.action.markupToAll(7, -1, 501, p.Coords[1]:GetVec3(), p.Coords[2]:GetVec3(),p.Coords[3]:GetVec3(),p.Coords[4]:GetVec3(),{1,0,0, 1}, {1,0,0, 1}, 4, false, Text or "")
|
end
|
||||||
--
|
|
||||||
-- doesn't seem to fill in the shape for an n-sided polygon
|
|
||||||
self:SetFillColor(FillColor, FillAlpha)
|
|
||||||
|
|
||||||
IncludeTriangles = IncludeTriangles or false
|
|
||||||
|
|
||||||
-- just draw the triangles, we get the outline for free
|
if false then
|
||||||
if IncludeTriangles then
|
local coords = self:GetVerticiesCoordinates()
|
||||||
|
|
||||||
|
local coord=coords[1] --Core.Point#COORDINATE
|
||||||
|
|
||||||
|
table.remove(coords, 1)
|
||||||
|
|
||||||
|
coord:MarkupToAllFreeForm(coords, Coalition, Color, Alpha, FillColor, FillAlpha, LineType, ReadOnly, "Drew Polygon")
|
||||||
|
|
||||||
|
if true then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Change/Re-fill a Polygon Zone
|
||||||
|
-- @param #ZONE_POLYGON_BASE self
|
||||||
|
-- @param #table Color RGB color table {r, g, b}, e.g. {1,0,0} for red.
|
||||||
|
-- @param #number Alpha Transparency [0,1]. Default 1.
|
||||||
|
-- @return #ZONE_POLYGON_BASE self
|
||||||
|
function ZONE_POLYGON_BASE:ReFill(Color,Alpha)
|
||||||
|
local color = Color or self:GetFillColorRGB() or {1,0,0}
|
||||||
|
local alpha = Alpha or self:GetFillColorAlpha() or 1
|
||||||
|
local coalition = self:GetDrawCoalition() or -1
|
||||||
|
-- undraw if already filled
|
||||||
|
if #self.FillTriangles > 0 then
|
||||||
for _, triangle in pairs(self._Triangles) do
|
for _, triangle in pairs(self._Triangles) do
|
||||||
local draw_ids = triangle:Draw()
|
triangle:UndrawZone()
|
||||||
|
end
|
||||||
|
-- remove mark IDs
|
||||||
|
for _,_value in pairs(self.FillTriangles) do
|
||||||
|
table.remove_by_value(self.DrawID, _value)
|
||||||
|
end
|
||||||
|
self.FillTriangles = nil
|
||||||
|
self.FillTriangles = {}
|
||||||
|
end
|
||||||
|
-- refill
|
||||||
|
for _, triangle in pairs(self._Triangles) do
|
||||||
|
local draw_ids = triangle:Fill(coalition,color,alpha,nil)
|
||||||
|
self.FillTriangles = draw_ids
|
||||||
table.combine(self.DrawID, draw_ids)
|
table.combine(self.DrawID, draw_ids)
|
||||||
end
|
end
|
||||||
-- draw outline only
|
return self
|
||||||
else
|
end
|
||||||
|
|
||||||
|
--- Change/Re-draw the border of a Polygon Zone
|
||||||
|
-- @param #ZONE_POLYGON_BASE self
|
||||||
|
-- @param #table Color RGB color table {r, g, b}, e.g. {1,0,0} for red.
|
||||||
|
-- @param #number Alpha Transparency [0,1]. Default 1.
|
||||||
|
-- @param #number LineType Line type: 0=No line, 1=Solid, 2=Dashed, 3=Dotted, 4=Dot dash, 5=Long dash, 6=Two dash. Default 1=Solid.
|
||||||
|
-- @return #ZONE_POLYGON_BASE
|
||||||
|
function ZONE_POLYGON_BASE:ReDrawBorderline(Color, Alpha, LineType)
|
||||||
|
local color = Color or self:GetFillColorRGB() or {1,0,0}
|
||||||
|
local alpha = Alpha or self:GetFillColorAlpha() or 1
|
||||||
|
local coalition = self:GetDrawCoalition() or -1
|
||||||
|
local linetype = LineType or 1
|
||||||
|
-- undraw if already drawn
|
||||||
|
if #self.Borderlines > 0 then
|
||||||
|
for _, MarkID in pairs(self.Borderlines) do
|
||||||
|
trigger.action.removeMark(MarkID)
|
||||||
|
end
|
||||||
|
-- remove mark IDs
|
||||||
|
for _,_value in pairs(self.Borderlines) do
|
||||||
|
table.remove_by_value(self.DrawID, _value)
|
||||||
|
end
|
||||||
|
self.Borderlines = nil
|
||||||
|
self.Borderlines = {}
|
||||||
|
end
|
||||||
|
-- Redraw border
|
||||||
local coords = self:GetVerticiesCoordinates()
|
local coords = self:GetVerticiesCoordinates()
|
||||||
for i = 1, #coords do
|
for i = 1, #coords do
|
||||||
local c1 = coords[i]
|
local c1 = coords[i]
|
||||||
local c2 = coords[i % #coords + 1]
|
local c2 = coords[i % #coords + 1]
|
||||||
table.add(self.DrawID, c1:LineToAll(c2, Coalition, Color, Alpha, LineType, ReadOnly))
|
local newID = c1:LineToAll(c2, coalition, color, alpha, linetype, nil)
|
||||||
end
|
self.DrawID[#self.DrawID+1]=newID
|
||||||
end
|
self.Borderlines[#self.Borderlines+1] = newID
|
||||||
end
|
end
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
@@ -3080,6 +2948,7 @@ function ZONE_POLYGON_BASE:Boundary(Coalition, Color, Radius, Alpha, Segments, C
|
|||||||
Alpha = Alpha or 1
|
Alpha = Alpha or 1
|
||||||
Segments = Segments or 10
|
Segments = Segments or 10
|
||||||
Closed = Closed or false
|
Closed = Closed or false
|
||||||
|
local Limit
|
||||||
local i = 1
|
local i = 1
|
||||||
local j = #self._.Polygon
|
local j = #self._.Polygon
|
||||||
if (Closed) then
|
if (Closed) then
|
||||||
@@ -3104,9 +2973,13 @@ function ZONE_POLYGON_BASE:Boundary(Coalition, Color, Radius, Alpha, Segments, C
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
do -- Zone_Polygon
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
-- @type ZONE_POLYGON
|
-- @type ZONE_POLYGON
|
||||||
-- @extends #ZONE_POLYGON_BASE
|
-- @extends #ZONE_POLYGON_BASE
|
||||||
|
-- @extends #ZONE_BASE
|
||||||
|
|
||||||
|
|
||||||
--- The ZONE_POLYGON class defined by a sequence of @{Wrapper.Group#GROUP} waypoints within the Mission Editor, forming a polygon, OR by drawings made with the Draw tool
|
--- The ZONE_POLYGON class defined by a sequence of @{Wrapper.Group#GROUP} waypoints within the Mission Editor, forming a polygon, OR by drawings made with the Draw tool
|
||||||
@@ -3138,8 +3011,7 @@ end
|
|||||||
--
|
--
|
||||||
-- This class has been updated to use a accurate way of generating random points inside the polygon without having to use trial and error guesses.
|
-- This class has been updated to use a accurate way of generating random points inside the polygon without having to use trial and error guesses.
|
||||||
-- You can also get the surface area of the polygon now, handy if you want measure which coalition has the largest captured area, for example.
|
-- You can also get the surface area of the polygon now, handy if you want measure which coalition has the largest captured area, for example.
|
||||||
|
--
|
||||||
|
|
||||||
-- @field #ZONE_POLYGON
|
-- @field #ZONE_POLYGON
|
||||||
ZONE_POLYGON = {
|
ZONE_POLYGON = {
|
||||||
ClassName="ZONE_POLYGON",
|
ClassName="ZONE_POLYGON",
|
||||||
@@ -3604,9 +3476,11 @@ function ZONE_POLYGON:IsNoneInZone()
|
|||||||
return self:CountScannedCoalitions() == 0
|
return self:CountScannedCoalitions() == 0
|
||||||
end
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
do -- ZONE_ELASTIC
|
do -- ZONE_ELASTIC
|
||||||
|
|
||||||
|
---
|
||||||
-- @type ZONE_ELASTIC
|
-- @type ZONE_ELASTIC
|
||||||
-- @field #table points Points in 2D.
|
-- @field #table points Points in 2D.
|
||||||
-- @field #table setGroups Set of GROUPs.
|
-- @field #table setGroups Set of GROUPs.
|
||||||
@@ -3805,8 +3679,242 @@ do -- ZONE_ELASTIC
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
--- ZONE_OVAL created from a center point, major axis, minor axis, and angle.
|
||||||
|
-- Ported from https://github.com/nielsvaes/CCMOOSE/blob/master/Moose%20Development/Moose/Shapes/Oval.lua
|
||||||
|
-- @type ZONE_OVAL
|
||||||
|
-- @extends Core.Zone#ZONE_BASE
|
||||||
|
|
||||||
|
--- ## ZONE_OVAL class, extends @{#ZONE_BASE}
|
||||||
|
--
|
||||||
|
-- The ZONE_OVAL class is defined by a center point, major axis, minor axis, and angle.
|
||||||
|
-- This class implements the inherited functions from @{#ZONE_BASE} taking into account the own zone format and properties.
|
||||||
|
--
|
||||||
|
-- @field #ZONE_OVAL
|
||||||
|
ZONE_OVAL = {
|
||||||
|
ClassName = "OVAL",
|
||||||
|
ZoneName="",
|
||||||
|
MajorAxis = nil,
|
||||||
|
MinorAxis = nil,
|
||||||
|
Angle = 0,
|
||||||
|
DrawPoly = nil -- let's just use a ZONE_POLYGON to draw the ZONE_OVAL on the map
|
||||||
|
}
|
||||||
|
|
||||||
|
--- Creates a new ZONE_OVAL from a center point, major axis, minor axis, and angle.
|
||||||
|
--- ported from https://github.com/nielsvaes/CCMOOSE/blob/master/Moose%20Development/Moose/Shapes/Oval.lua
|
||||||
|
-- @param #ZONE_OVAL self
|
||||||
|
-- @param #string name Name of the zone.
|
||||||
|
-- @param #table vec2 The center point of the oval
|
||||||
|
-- @param #number major_axis The major axis of the oval
|
||||||
|
-- @param #number minor_axis The minor axis of the oval
|
||||||
|
-- @param #number angle The angle of the oval
|
||||||
|
-- @return #ZONE_OVAL The new oval
|
||||||
|
function ZONE_OVAL:New(name, vec2, major_axis, minor_axis, angle)
|
||||||
|
|
||||||
|
self = BASE:Inherit(self, ZONE_BASE:New())
|
||||||
|
|
||||||
|
self.ZoneName = name
|
||||||
|
self.CenterVec2 = vec2
|
||||||
|
self.MajorAxis = major_axis
|
||||||
|
self.MinorAxis = minor_axis
|
||||||
|
self.Angle = angle or 0
|
||||||
|
|
||||||
|
_DATABASE:AddZone(name, self)
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Constructor to create a ZONE_OVAL instance, taking the name of a drawing made with the draw tool in the Mission Editor.
|
||||||
|
--- ported from https://github.com/nielsvaes/CCMOOSE/blob/master/Moose%20Development/Moose/Shapes/Oval.lua
|
||||||
|
-- @param #ZONE_OVAL self
|
||||||
|
-- @param #string DrawingName The name of the drawing in the Mission Editor
|
||||||
|
-- @return #ZONE_OVAL self
|
||||||
|
function ZONE_OVAL:NewFromDrawing(DrawingName)
|
||||||
|
self = BASE:Inherit(self, ZONE_BASE:New(DrawingName))
|
||||||
|
for _, layer in pairs(env.mission.drawings.layers) do
|
||||||
|
for _, object in pairs(layer["objects"]) do
|
||||||
|
if string.find(object["name"], DrawingName, 1, true) then
|
||||||
|
if object["polygonMode"] == "oval" then
|
||||||
|
self.CenterVec2 = { x = object["mapX"], y = object["mapY"] }
|
||||||
|
self.MajorAxis = object["r1"]
|
||||||
|
self.MinorAxis = object["r2"]
|
||||||
|
self.Angle = object["angle"]
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
_DATABASE:AddZone(DrawingName, self)
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Gets the major axis of the oval.
|
||||||
|
-- @param #ZONE_OVAL self
|
||||||
|
-- @return #number The major axis of the oval
|
||||||
|
function ZONE_OVAL:GetMajorAxis()
|
||||||
|
return self.MajorAxis
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Gets the minor axis of the oval.
|
||||||
|
-- @param #ZONE_OVAL self
|
||||||
|
-- @return #number The minor axis of the oval
|
||||||
|
function ZONE_OVAL:GetMinorAxis()
|
||||||
|
return self.MinorAxis
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Gets the angle of the oval.
|
||||||
|
-- @param #ZONE_OVAL self
|
||||||
|
-- @return #number The angle of the oval
|
||||||
|
function ZONE_OVAL:GetAngle()
|
||||||
|
return self.Angle
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Returns a the center point of the oval
|
||||||
|
-- @param #ZONE_OVAL self
|
||||||
|
-- @return #table The center Vec2
|
||||||
|
function ZONE_OVAL:GetVec2()
|
||||||
|
return self.CenterVec2
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Checks if a point is contained within the oval.
|
||||||
|
-- @param #ZONE_OVAL self
|
||||||
|
-- @param #table point The point to check
|
||||||
|
-- @return #bool True if the point is contained, false otherwise
|
||||||
|
function ZONE_OVAL:IsVec2InZone(vec2)
|
||||||
|
local cos, sin = math.cos, math.sin
|
||||||
|
local dx = vec2.x - self.CenterVec2.x
|
||||||
|
local dy = vec2.y - self.CenterVec2.y
|
||||||
|
local rx = dx * cos(self.Angle) + dy * sin(self.Angle)
|
||||||
|
local ry = -dx * sin(self.Angle) + dy * cos(self.Angle)
|
||||||
|
return rx * rx / (self.MajorAxis * self.MajorAxis) + ry * ry / (self.MinorAxis * self.MinorAxis) <= 1
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Calculates the bounding box of the oval. The bounding box is the smallest rectangle that contains the oval.
|
||||||
|
-- @param #ZONE_OVAL self
|
||||||
|
-- @return #table The bounding box of the oval
|
||||||
|
function ZONE_OVAL:GetBoundingSquare()
|
||||||
|
local min_x = self.CenterVec2.x - self.MajorAxis
|
||||||
|
local min_y = self.CenterVec2.y - self.MinorAxis
|
||||||
|
local max_x = self.CenterVec2.x + self.MajorAxis
|
||||||
|
local max_y = self.CenterVec2.y + self.MinorAxis
|
||||||
|
|
||||||
|
return {
|
||||||
|
{x=min_x, y=min_x}, {x=max_x, y=min_y}, {x=max_x, y=max_y}, {x=min_x, y=max_y}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Find points on the edge of the oval
|
||||||
|
-- @param #ZONE_OVAL self
|
||||||
|
-- @param #number num_points How many points should be found. More = smoother shape
|
||||||
|
-- @return #table Points on he edge
|
||||||
|
function ZONE_OVAL:PointsOnEdge(num_points)
|
||||||
|
num_points = num_points or 40
|
||||||
|
local points = {}
|
||||||
|
local dtheta = 2 * math.pi / num_points
|
||||||
|
|
||||||
|
for i = 0, num_points - 1 do
|
||||||
|
local theta = i * dtheta
|
||||||
|
local x = self.CenterVec2.x + self.MajorAxis * math.cos(theta) * math.cos(self.Angle) - self.MinorAxis * math.sin(theta) * math.sin(self.Angle)
|
||||||
|
local y = self.CenterVec2.y + self.MajorAxis * math.cos(theta) * math.sin(self.Angle) + self.MinorAxis * math.sin(theta) * math.cos(self.Angle)
|
||||||
|
table.insert(points, {x = x, y = y})
|
||||||
|
end
|
||||||
|
|
||||||
|
return points
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Returns a random Vec2 within the oval.
|
||||||
|
-- @param #ZONE_OVAL self
|
||||||
|
-- @return #table The random Vec2
|
||||||
|
function ZONE_OVAL:GetRandomVec2()
|
||||||
|
local theta = math.rad(self.Angle)
|
||||||
|
|
||||||
|
local random_point = math.sqrt(math.random()) --> uniformly
|
||||||
|
--local random_point = math.random() --> more clumped around center
|
||||||
|
local phi = math.random() * 2 * math.pi
|
||||||
|
local x_c = random_point * math.cos(phi)
|
||||||
|
local y_c = random_point * math.sin(phi)
|
||||||
|
local x_e = x_c * self.MajorAxis
|
||||||
|
local y_e = y_c * self.MinorAxis
|
||||||
|
local rx = (x_e * math.cos(theta) - y_e * math.sin(theta)) + self.CenterVec2.x
|
||||||
|
local ry = (x_e * math.sin(theta) + y_e * math.cos(theta)) + self.CenterVec2.y
|
||||||
|
|
||||||
|
return {x=rx, y=ry}
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Define a random @{Core.Point#POINT_VEC2} within the zone.
|
||||||
|
-- @param #ZONE_OVAL self
|
||||||
|
-- @return Core.Point#POINT_VEC2 The PointVec2 coordinates.
|
||||||
|
function ZONE_OVAL:GetRandomPointVec2()
|
||||||
|
return POINT_VEC2:NewFromVec2(self:GetRandomVec2())
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Define a random @{Core.Point#POINT_VEC2} within the zone.
|
||||||
|
-- @param #ZONE_OVAL self
|
||||||
|
-- @return Core.Point#POINT_VEC2 The PointVec2 coordinates.
|
||||||
|
function ZONE_OVAL:GetRandomPointVec3()
|
||||||
|
return POINT_VEC2:NewFromVec3(self:GetRandomVec2())
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Draw the zone on the F10 map.
|
||||||
|
--- ported from https://github.com/nielsvaes/CCMOOSE/blob/master/Moose%20Development/Moose/Shapes/Oval.lua
|
||||||
|
-- @param #ZONE_OVAL self
|
||||||
|
-- @param #number Coalition Coalition: All=-1, Neutral=0, Red=1, Blue=2. Default -1=All.
|
||||||
|
-- @param #table Color RGB color table {r, g, b}, e.g. {1,0,0} for red.
|
||||||
|
-- @param #number Alpha Transparency [0,1]. Default 1.
|
||||||
|
-- @param #table FillColor RGB color table {r, g, b}, e.g. {1,0,0} for red. Default is same as `Color` value. -- doesn't seem to work
|
||||||
|
-- @param #number FillAlpha Transparency [0,1]. Default 0.15. -- doesn't seem to work
|
||||||
|
-- @param #number LineType Line type: 0=No line, 1=Solid, 2=Dashed, 3=Dotted, 4=Dot dash, 5=Long dash, 6=Two dash. Default 1=Solid.
|
||||||
|
-- @param #boolean ReadOnly (Optional) Mark is readonly and cannot be removed by users. Default false.
|
||||||
|
-- @return #ZONE_OVAL self
|
||||||
|
function ZONE_OVAL:DrawZone(Coalition, Color, Alpha, FillColor, FillAlpha, LineType)
|
||||||
|
Coalition = Coalition or self:GetDrawCoalition()
|
||||||
|
|
||||||
|
-- Set draw coalition.
|
||||||
|
self:SetDrawCoalition(Coalition)
|
||||||
|
|
||||||
|
Color = Color or self:GetColorRGB()
|
||||||
|
Alpha = Alpha or 1
|
||||||
|
|
||||||
|
-- Set color.
|
||||||
|
self:SetColor(Color, Alpha)
|
||||||
|
|
||||||
|
FillColor = FillColor or self:GetFillColorRGB()
|
||||||
|
if not FillColor then
|
||||||
|
UTILS.DeepCopy(Color)
|
||||||
|
end
|
||||||
|
FillAlpha = FillAlpha or self:GetFillColorAlpha()
|
||||||
|
if not FillAlpha then
|
||||||
|
FillAlpha = 0.15
|
||||||
|
end
|
||||||
|
|
||||||
|
LineType = LineType or 1
|
||||||
|
|
||||||
|
-- Set fill color -----------> has fill color worked in recent versions of DCS?
|
||||||
|
-- doing something like
|
||||||
|
--
|
||||||
|
-- trigger.action.markupToAll(7, -1, 501, p.Coords[1]:GetVec3(), p.Coords[2]:GetVec3(),p.Coords[3]:GetVec3(),p.Coords[4]:GetVec3(),{1,0,0, 1}, {1,0,0, 1}, 4, false, Text or "")
|
||||||
|
--
|
||||||
|
-- doesn't seem to fill in the shape for an n-sided polygon
|
||||||
|
self:SetFillColor(FillColor, FillAlpha)
|
||||||
|
|
||||||
|
self.DrawPoly = ZONE_POLYGON:NewFromPointsArray(self.ZoneName, self:PointsOnEdge(80))
|
||||||
|
self.DrawPoly:DrawZone(Coalition, Color, Alpha, FillColor, FillAlpha, LineType)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Remove drawing from F10 map
|
||||||
|
-- @param #ZONE_OVAL self
|
||||||
|
function ZONE_OVAL:UndrawZone()
|
||||||
|
if self.DrawPoly then
|
||||||
|
self.DrawPoly:UndrawZone()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
do -- ZONE_AIRBASE
|
do -- ZONE_AIRBASE
|
||||||
|
|
||||||
|
---
|
||||||
-- @type ZONE_AIRBASE
|
-- @type ZONE_AIRBASE
|
||||||
-- @field #boolean isShip If `true`, airbase is a ship.
|
-- @field #boolean isShip If `true`, airbase is a ship.
|
||||||
-- @field #boolean isHelipad If `true`, airbase is a helipad.
|
-- @field #boolean isHelipad If `true`, airbase is a helipad.
|
||||||
|
|||||||
@@ -606,8 +606,10 @@ function AICSAR:SetPilotTTSVoice(Voice,Culture,Gender)
|
|||||||
self.SRSPilot:SetCulture(Culture or "en-US")
|
self.SRSPilot:SetCulture(Culture or "en-US")
|
||||||
self.SRSPilot:SetGender(Gender or "male")
|
self.SRSPilot:SetGender(Gender or "male")
|
||||||
self.SRSPilot:SetLabel("PILOT")
|
self.SRSPilot:SetLabel("PILOT")
|
||||||
if self.SRS.google then
|
if self.SRSGoogle then
|
||||||
self.SRSPilot:SetGoogle(self.SRS.google)
|
local poptions = self.SRS:GetProviderOptions(MSRS.Provider.GOOGLE) -- Sound.SRS#MSRS.ProviderOptions
|
||||||
|
self.SRSPilot:SetGoogle(poptions.credentials)
|
||||||
|
self.SRSPilot:SetGoogleAPIKey(poptions.key)
|
||||||
end
|
end
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
@@ -627,9 +629,11 @@ function AICSAR:SetOperatorTTSVoice(Voice,Culture,Gender)
|
|||||||
self.SRSOperator:SetVoice(Voice)
|
self.SRSOperator:SetVoice(Voice)
|
||||||
self.SRSOperator:SetCulture(Culture or "en-GB")
|
self.SRSOperator:SetCulture(Culture or "en-GB")
|
||||||
self.SRSOperator:SetGender(Gender or "female")
|
self.SRSOperator:SetGender(Gender or "female")
|
||||||
self.SRSPilot:SetLabel("RESCUE")
|
self.SRSOperator:SetLabel("RESCUE")
|
||||||
if self.SRS.google then
|
if self.SRSGoogle then
|
||||||
self.SRSOperator:SetGoogle(self.SRS.google)
|
local poptions = self.SRS:GetProviderOptions(MSRS.Provider.GOOGLE) -- Sound.SRS#MSRS.ProviderOptions
|
||||||
|
self.SRSOperator:SetGoogle(poptions.credentials)
|
||||||
|
self.SRSOperator:SetGoogleAPIKey(poptions.key)
|
||||||
end
|
end
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -10,9 +10,7 @@
|
|||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ## Missions:
|
-- ## Missions: None
|
||||||
--
|
|
||||||
-- [ABP - Airbase Police](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/ABP%20-%20Airbase%20Police)
|
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
@@ -699,7 +697,8 @@ end
|
|||||||
function ATC_GROUND_UNIVERSAL:_AirbaseMonitor()
|
function ATC_GROUND_UNIVERSAL:_AirbaseMonitor()
|
||||||
self:I("_AirbaseMonitor")
|
self:I("_AirbaseMonitor")
|
||||||
self.SetClient:ForEachClient(
|
self.SetClient:ForEachClient(
|
||||||
--- @param Wrapper.Client#CLIENT Client
|
--- Nameless function
|
||||||
|
-- @param Wrapper.Client#CLIENT Client
|
||||||
function( Client )
|
function( Client )
|
||||||
|
|
||||||
if Client:IsAlive() then
|
if Client:IsAlive() then
|
||||||
|
|||||||
@@ -39,7 +39,8 @@
|
|||||||
|
|
||||||
do -- DETECTION_BASE
|
do -- DETECTION_BASE
|
||||||
|
|
||||||
--- @type DETECTION_BASE
|
---
|
||||||
|
-- @type DETECTION_BASE
|
||||||
-- @field Core.Set#SET_GROUP DetectionSetGroup The @{Core.Set} of GROUPs in the Forward Air Controller role.
|
-- @field Core.Set#SET_GROUP DetectionSetGroup The @{Core.Set} of GROUPs in the Forward Air Controller role.
|
||||||
-- @field DCS#Distance DetectionRange The range till which targets are accepted to be detected.
|
-- @field DCS#Distance DetectionRange The range till which targets are accepted to be detected.
|
||||||
-- @field #DETECTION_BASE.DetectedObjects DetectedObjects The list of detected objects.
|
-- @field #DETECTION_BASE.DetectedObjects DetectedObjects The list of detected objects.
|
||||||
@@ -91,6 +92,11 @@ do -- DETECTION_BASE
|
|||||||
--
|
--
|
||||||
-- DetectionObject:FilterCategories( { Unit.Category.AIRPLANE, Unit.Category.HELICOPTER } )
|
-- DetectionObject:FilterCategories( { Unit.Category.AIRPLANE, Unit.Category.HELICOPTER } )
|
||||||
--
|
--
|
||||||
|
--
|
||||||
|
-- ## Radar Blur - use to make the radar less exact, e.g. for WWII scenarios
|
||||||
|
--
|
||||||
|
-- * @{#DETECTION_BASE.SetRadarBlur}(): Set the radar blur to be used.
|
||||||
|
--
|
||||||
-- ## **DETECTION_ derived classes** group the detected units into a **DetectedItems[]** list
|
-- ## **DETECTION_ derived classes** group the detected units into a **DetectedItems[]** list
|
||||||
--
|
--
|
||||||
-- DETECTION_BASE derived classes build a list called DetectedItems[], which is essentially a first later
|
-- DETECTION_BASE derived classes build a list called DetectedItems[], which is essentially a first later
|
||||||
@@ -269,10 +275,12 @@ do -- DETECTION_BASE
|
|||||||
DetectedItemsByIndex = {},
|
DetectedItemsByIndex = {},
|
||||||
}
|
}
|
||||||
|
|
||||||
--- @type DETECTION_BASE.DetectedObjects
|
---
|
||||||
|
-- @type DETECTION_BASE.DetectedObjects
|
||||||
-- @list <#DETECTION_BASE.DetectedObject>
|
-- @list <#DETECTION_BASE.DetectedObject>
|
||||||
|
|
||||||
--- @type DETECTION_BASE.DetectedObject
|
---
|
||||||
|
-- @type DETECTION_BASE.DetectedObject
|
||||||
-- @field #string Name
|
-- @field #string Name
|
||||||
-- @field #boolean IsVisible
|
-- @field #boolean IsVisible
|
||||||
-- @field #boolean KnowType
|
-- @field #boolean KnowType
|
||||||
@@ -284,7 +292,8 @@ do -- DETECTION_BASE
|
|||||||
-- @field #boolean LastPos
|
-- @field #boolean LastPos
|
||||||
-- @field #number LastVelocity
|
-- @field #number LastVelocity
|
||||||
|
|
||||||
--- @type DETECTION_BASE.DetectedItems
|
---
|
||||||
|
-- @type DETECTION_BASE.DetectedItems
|
||||||
-- @list <#DETECTION_BASE.DetectedItem>
|
-- @list <#DETECTION_BASE.DetectedItem>
|
||||||
|
|
||||||
--- Detected item data structure.
|
--- Detected item data structure.
|
||||||
@@ -522,7 +531,7 @@ do -- DETECTION_BASE
|
|||||||
|
|
||||||
do -- State Transition Handling
|
do -- State Transition Handling
|
||||||
|
|
||||||
--- @param #DETECTION_BASE self
|
-- @param #DETECTION_BASE self
|
||||||
-- @param #string From The From State string.
|
-- @param #string From The From State string.
|
||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
-- @param #string To The To State string.
|
-- @param #string To The To State string.
|
||||||
@@ -530,7 +539,7 @@ do -- DETECTION_BASE
|
|||||||
self:__Detect( 1 )
|
self:__Detect( 1 )
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #DETECTION_BASE self
|
-- @param #DETECTION_BASE self
|
||||||
-- @param #string From The From State string.
|
-- @param #string From The From State string.
|
||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
-- @param #string To The To State string.
|
-- @param #string To The To State string.
|
||||||
@@ -570,7 +579,7 @@ do -- DETECTION_BASE
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #DETECTION_BASE self
|
-- @param #DETECTION_BASE self
|
||||||
-- @param #number The amount of alive recce.
|
-- @param #number The amount of alive recce.
|
||||||
function DETECTION_BASE:CountAliveRecce()
|
function DETECTION_BASE:CountAliveRecce()
|
||||||
|
|
||||||
@@ -578,7 +587,7 @@ do -- DETECTION_BASE
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #DETECTION_BASE self
|
-- @param #DETECTION_BASE self
|
||||||
function DETECTION_BASE:ForEachAliveRecce( IteratorFunction, ... )
|
function DETECTION_BASE:ForEachAliveRecce( IteratorFunction, ... )
|
||||||
self:F2( arg )
|
self:F2( arg )
|
||||||
|
|
||||||
@@ -587,7 +596,7 @@ do -- DETECTION_BASE
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #DETECTION_BASE self
|
-- @param #DETECTION_BASE self
|
||||||
-- @param #string From The From State string.
|
-- @param #string From The From State string.
|
||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
-- @param #string To The To State string.
|
-- @param #string To The To State string.
|
||||||
@@ -712,6 +721,31 @@ do -- DETECTION_BASE
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Calculate radar blur probability
|
||||||
|
|
||||||
|
if self.RadarBlur then
|
||||||
|
MESSAGE:New("Radar Blur",10):ToLogIf(self.debug):ToAllIf(self.verbose)
|
||||||
|
local minheight = self.RadarBlurMinHeight or 250 -- meters
|
||||||
|
local thresheight = self.RadarBlurThresHeight or 90 -- 10% chance to find a low flying group
|
||||||
|
local thresblur = self.RadarBlurThresBlur or 85 -- 25% chance to escape the radar overall
|
||||||
|
local dist = math.floor(Distance)
|
||||||
|
if dist <= self.RadarBlurClosing then
|
||||||
|
thresheight = (((dist*dist)/self.RadarBlurClosingSquare)*thresheight)
|
||||||
|
thresblur = (((dist*dist)/self.RadarBlurClosingSquare)*thresblur)
|
||||||
|
end
|
||||||
|
local fheight = math.floor(math.random(1,10000)/100)
|
||||||
|
local fblur = math.floor(math.random(1,10000)/100)
|
||||||
|
local unit = UNIT:FindByName(DetectedObjectName)
|
||||||
|
if unit and unit:IsAlive() then
|
||||||
|
local AGL = unit:GetAltitude(true)
|
||||||
|
MESSAGE:New("Unit "..DetectedObjectName.." is at "..math.floor(AGL).."m. Distance "..math.floor(Distance).."km.",10):ToLogIf(self.debug):ToAllIf(self.verbose)
|
||||||
|
MESSAGE:New(string.format("fheight = %d/%d | fblur = %d/%d",fheight,thresheight,fblur,thresblur),10):ToLogIf(self.debug):ToAllIf(self.verbose)
|
||||||
|
if fblur > thresblur then DetectionAccepted = false end
|
||||||
|
if AGL <= minheight and fheight < thresheight then DetectionAccepted = false end
|
||||||
|
MESSAGE:New("Detection Accepted = "..tostring(DetectionAccepted),10):ToLogIf(self.debug):ToAllIf(self.verbose)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- Calculate additional probabilities
|
-- Calculate additional probabilities
|
||||||
|
|
||||||
if not self.DetectedObjects[DetectedObjectName] and TargetIsVisible and self.DistanceProbability then
|
if not self.DetectedObjects[DetectedObjectName] and TargetIsVisible and self.DistanceProbability then
|
||||||
@@ -1012,6 +1046,23 @@ do -- DETECTION_BASE
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Method to make the radar detection less accurate, e.g. for WWII scenarios.
|
||||||
|
-- @param #DETECTION_BASE self
|
||||||
|
-- @param #number minheight Minimum flight height to be detected, in meters AGL (above ground)
|
||||||
|
-- @param #number thresheight Threshold to escape the radar if flying below minheight, defaults to 90 (90% escape chance)
|
||||||
|
-- @param #number thresblur Threshold to be detected by the radar overall, defaults to 85 (85% chance to be found)
|
||||||
|
-- @param #number closing Closing-in in km - the limit of km from which on it becomes increasingly difficult to escape radar detection if flying towards the radar position. Should be about 1/3 of the radar detection radius in kilometers, defaults to 20.
|
||||||
|
-- @return #DETECTION_BASE self
|
||||||
|
function DETECTION_BASE:SetRadarBlur(minheight,thresheight,thresblur,closing)
|
||||||
|
self.RadarBlur = true
|
||||||
|
self.RadarBlurMinHeight = minheight or 250 -- meters
|
||||||
|
self.RadarBlurThresHeight = thresheight or 90 -- 10% chance to find a low flying group
|
||||||
|
self.RadarBlurThresBlur = thresblur or 85 -- 25% chance to escape the radar overall
|
||||||
|
self.RadarBlurClosing = closing or 20 -- 20km
|
||||||
|
self.RadarBlurClosingSquare = self.RadarBlurClosing * self.RadarBlurClosing
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
do
|
do
|
||||||
@@ -1354,7 +1405,7 @@ do -- DETECTION_BASE
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
--- @param DCS#Unit FoundDCSUnit
|
-- @param DCS#Unit FoundDCSUnit
|
||||||
-- @param Wrapper.Group#GROUP ReportGroup
|
-- @param Wrapper.Group#GROUP ReportGroup
|
||||||
-- @param Core.Set#SET_GROUP ReportSetGroup
|
-- @param Core.Set#SET_GROUP ReportSetGroup
|
||||||
local FindNearByFriendlies = function( FoundDCSUnit, ReportGroupData )
|
local FindNearByFriendlies = function( FoundDCSUnit, ReportGroupData )
|
||||||
@@ -1419,7 +1470,7 @@ do -- DETECTION_BASE
|
|||||||
DetectedItem.PlayersNearBy = nil
|
DetectedItem.PlayersNearBy = nil
|
||||||
|
|
||||||
_DATABASE:ForEachPlayer(
|
_DATABASE:ForEachPlayer(
|
||||||
--- @param Wrapper.Unit#UNIT PlayerUnit
|
-- @param Wrapper.Unit#UNIT PlayerUnit
|
||||||
function( PlayerUnitName )
|
function( PlayerUnitName )
|
||||||
local PlayerUnit = UNIT:FindByName( PlayerUnitName )
|
local PlayerUnit = UNIT:FindByName( PlayerUnitName )
|
||||||
|
|
||||||
@@ -1976,7 +2027,8 @@ end
|
|||||||
|
|
||||||
do -- DETECTION_UNITS
|
do -- DETECTION_UNITS
|
||||||
|
|
||||||
--- @type DETECTION_UNITS
|
---
|
||||||
|
-- @type DETECTION_UNITS
|
||||||
-- @field DCS#Distance DetectionRange The range till which targets are detected.
|
-- @field DCS#Distance DetectionRange The range till which targets are detected.
|
||||||
-- @extends Functional.Detection#DETECTION_BASE
|
-- @extends Functional.Detection#DETECTION_BASE
|
||||||
|
|
||||||
@@ -2232,7 +2284,8 @@ end
|
|||||||
|
|
||||||
do -- DETECTION_TYPES
|
do -- DETECTION_TYPES
|
||||||
|
|
||||||
--- @type DETECTION_TYPES
|
---
|
||||||
|
-- @type DETECTION_TYPES
|
||||||
-- @extends Functional.Detection#DETECTION_BASE
|
-- @extends Functional.Detection#DETECTION_BASE
|
||||||
|
|
||||||
--- Will detect units within the battle zone.
|
--- Will detect units within the battle zone.
|
||||||
@@ -2435,7 +2488,8 @@ end
|
|||||||
|
|
||||||
do -- DETECTION_AREAS
|
do -- DETECTION_AREAS
|
||||||
|
|
||||||
--- @type DETECTION_AREAS
|
---
|
||||||
|
-- @type DETECTION_AREAS
|
||||||
-- @field DCS#Distance DetectionZoneRange The range till which targets are grouped upon the first detected target.
|
-- @field DCS#Distance DetectionZoneRange The range till which targets are grouped upon the first detected target.
|
||||||
-- @field #DETECTION_BASE.DetectedItems DetectedItems A list of areas containing the set of @{Wrapper.Unit}s, @{Core.Zone}s, the center @{Wrapper.Unit} within the zone, and ID of each area that was detected within a DetectionZoneRange.
|
-- @field #DETECTION_BASE.DetectedItems DetectedItems A list of areas containing the set of @{Wrapper.Unit}s, @{Core.Zone}s, the center @{Wrapper.Unit} within the zone, and ID of each area that was detected within a DetectionZoneRange.
|
||||||
-- @extends Functional.Detection#DETECTION_BASE
|
-- @extends Functional.Detection#DETECTION_BASE
|
||||||
@@ -2961,7 +3015,7 @@ do -- DETECTION_AREAS
|
|||||||
|
|
||||||
-- DetectedSet:Flush( self )
|
-- DetectedSet:Flush( self )
|
||||||
|
|
||||||
DetectedSet:ForEachUnit( --- @param Wrapper.Unit#UNIT DetectedUnit
|
DetectedSet:ForEachUnit( -- @param Wrapper.Unit#UNIT DetectedUnit
|
||||||
function( DetectedUnit )
|
function( DetectedUnit )
|
||||||
if DetectedUnit:IsAlive() then
|
if DetectedUnit:IsAlive() then
|
||||||
-- self:T( "Detected Set #" .. DetectedItem.ID .. ":" .. DetectedUnit:GetName() )
|
-- self:T( "Detected Set #" .. DetectedItem.ID .. ":" .. DetectedUnit:GetName() )
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
-- @module Functional.Mantis
|
-- @module Functional.Mantis
|
||||||
-- @image Functional.Mantis.jpg
|
-- @image Functional.Mantis.jpg
|
||||||
--
|
--
|
||||||
-- Last Update: Nov 2023
|
-- Last Update: Dec 2023
|
||||||
|
|
||||||
-------------------------------------------------------------------------
|
-------------------------------------------------------------------------
|
||||||
--- **MANTIS** class, extends Core.Base#BASE
|
--- **MANTIS** class, extends Core.Base#BASE
|
||||||
@@ -94,7 +94,7 @@
|
|||||||
-- Known SAM types at the time of writing are:
|
-- Known SAM types at the time of writing are:
|
||||||
--
|
--
|
||||||
-- * Avenger
|
-- * Avenger
|
||||||
-- * Chaparrel
|
-- * Chaparral
|
||||||
-- * Hawk
|
-- * Hawk
|
||||||
-- * Linebacker
|
-- * Linebacker
|
||||||
-- * NASAMS
|
-- * NASAMS
|
||||||
@@ -365,7 +365,7 @@ MANTIS.SamData = {
|
|||||||
["SA-15"] = { Range=11, Blindspot=0, Height=6, Type="Short", Radar="Tor 9A331" },
|
["SA-15"] = { Range=11, Blindspot=0, Height=6, Type="Short", Radar="Tor 9A331" },
|
||||||
["SA-13"] = { Range=5, Blindspot=0, Height=3, Type="Short", Radar="Strela" },
|
["SA-13"] = { Range=5, Blindspot=0, Height=3, Type="Short", Radar="Strela" },
|
||||||
["Avenger"] = { Range=4, Blindspot=0, Height=3, Type="Short", Radar="Avenger" },
|
["Avenger"] = { Range=4, Blindspot=0, Height=3, Type="Short", Radar="Avenger" },
|
||||||
["Chaparrel"] = { Range=8, Blindspot=0, Height=3, Type="Short", Radar="Chaparral" },
|
["Chaparral"] = { Range=8, Blindspot=0, Height=3, Type="Short", Radar="Chaparral" },
|
||||||
["Linebacker"] = { Range=4, Blindspot=0, Height=3, Type="Short", Radar="Linebacker" },
|
["Linebacker"] = { Range=4, Blindspot=0, Height=3, Type="Short", Radar="Linebacker" },
|
||||||
["Silkworm"] = { Range=90, Blindspot=1, Height=0.2, Type="Long", Radar="Silkworm" },
|
["Silkworm"] = { Range=90, Blindspot=1, Height=0.2, Type="Long", Radar="Silkworm" },
|
||||||
-- units from HDS Mod, multi launcher options is tricky
|
-- units from HDS Mod, multi launcher options is tricky
|
||||||
@@ -631,7 +631,7 @@ do
|
|||||||
|
|
||||||
-- TODO Version
|
-- TODO Version
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
self.version="0.8.15"
|
self.version="0.8.16"
|
||||||
self:I(string.format("***** Starting MANTIS Version %s *****", self.version))
|
self:I(string.format("***** Starting MANTIS Version %s *****", self.version))
|
||||||
|
|
||||||
--- FSM Functions ---
|
--- FSM Functions ---
|
||||||
@@ -1149,7 +1149,7 @@ do
|
|||||||
--self:T(self.lid.." Relocating HQ")
|
--self:T(self.lid.." Relocating HQ")
|
||||||
local text = self.lid.." Relocating HQ"
|
local text = self.lid.." Relocating HQ"
|
||||||
--local m= MESSAGE:New(text,10,"MANTIS"):ToAll()
|
--local m= MESSAGE:New(text,10,"MANTIS"):ToAll()
|
||||||
_hqgrp:RelocateGroundRandomInRadius(20,500,true,true)
|
_hqgrp:RelocateGroundRandomInRadius(20,500,true,true,nil,true)
|
||||||
end
|
end
|
||||||
--relocate EWR
|
--relocate EWR
|
||||||
-- TODO: maybe dependent on AlarmState? Observed: SA11 SR only relocates if no objects in reach
|
-- TODO: maybe dependent on AlarmState? Observed: SA11 SR only relocates if no objects in reach
|
||||||
@@ -1163,7 +1163,7 @@ do
|
|||||||
local text = self.lid.." Relocating EWR ".._grp:GetName()
|
local text = self.lid.." Relocating EWR ".._grp:GetName()
|
||||||
local m= MESSAGE:New(text,10,"MANTIS"):ToAllIf(self.debug)
|
local m= MESSAGE:New(text,10,"MANTIS"):ToAllIf(self.debug)
|
||||||
if self.verbose then self:I(text) end
|
if self.verbose then self:I(text) end
|
||||||
_grp:RelocateGroundRandomInRadius(20,500,true,true)
|
_grp:RelocateGroundRandomInRadius(20,500,true,true,nil,true)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -170,7 +170,7 @@
|
|||||||
--
|
--
|
||||||
-- * A specific departure and/or destination airport can be chosen.
|
-- * A specific departure and/or destination airport can be chosen.
|
||||||
-- * Valid coalitions can be set, e.g. only red, blue or neutral, all three "colours".
|
-- * Valid coalitions can be set, e.g. only red, blue or neutral, all three "colours".
|
||||||
-- * It is possible to start in air within a zone defined in the mission editor or within a zone above an airport of the map.
|
-- * It is possible to start in air within a zone or within a zone above an airport of the map.
|
||||||
--
|
--
|
||||||
-- ## Flight Plan
|
-- ## Flight Plan
|
||||||
--
|
--
|
||||||
@@ -1179,13 +1179,13 @@ function RAT:SetTakeoffAir()
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Set possible departure ports. This can be an airport or a zone defined in the mission editor.
|
--- Set possible departure ports. This can be an airport or a zone.
|
||||||
-- @param #RAT self
|
-- @param #RAT self
|
||||||
-- @param #string departurenames Name or table of names of departure airports or zones.
|
-- @param #string departurenames Name or table of names of departure airports or zones.
|
||||||
-- @return #RAT RAT self object.
|
-- @return #RAT RAT self object.
|
||||||
-- @usage RAT:SetDeparture("Sochi-Adler") will spawn RAT objects at Sochi-Adler airport.
|
-- @usage RAT:SetDeparture("Sochi-Adler") will spawn RAT objects at Sochi-Adler airport.
|
||||||
-- @usage RAT:SetDeparture({"Sochi-Adler", "Gudauta"}) will spawn RAT aircraft radomly at Sochi-Adler or Gudauta airport.
|
-- @usage RAT:SetDeparture({"Sochi-Adler", "Gudauta"}) will spawn RAT aircraft radomly at Sochi-Adler or Gudauta airport.
|
||||||
-- @usage RAT:SetDeparture({"Zone A", "Gudauta"}) will spawn RAT aircraft in air randomly within Zone A, which has to be defined in the mission editor, or within a zone around Gudauta airport. Note that this also requires RAT:takeoff("air") to be set.
|
-- @usage RAT:SetDeparture({"Zone A", "Gudauta"}) will spawn RAT aircraft in air randomly within Zone A, or within a zone around Gudauta airport. Note that this also requires RAT:takeoff("air") to be set.
|
||||||
function RAT:SetDeparture(departurenames)
|
function RAT:SetDeparture(departurenames)
|
||||||
self:F2(departurenames)
|
self:F2(departurenames)
|
||||||
|
|
||||||
@@ -2537,7 +2537,7 @@ function RAT:_SetRoute(takeoff, landing, _departure, _destination, _waypoint)
|
|||||||
end
|
end
|
||||||
elseif self:_ZoneExists(_departure) then
|
elseif self:_ZoneExists(_departure) then
|
||||||
-- If it's not an airport, check whether it's a zone.
|
-- If it's not an airport, check whether it's a zone.
|
||||||
departure=ZONE:New(_departure)
|
departure=ZONE:FindByName(_departure)
|
||||||
else
|
else
|
||||||
local text=string.format("ERROR! Specified departure airport %s does not exist for %s.", _departure, self.alias)
|
local text=string.format("ERROR! Specified departure airport %s does not exist for %s.", _departure, self.alias)
|
||||||
self:E(RAT.id..text)
|
self:E(RAT.id..text)
|
||||||
@@ -2635,7 +2635,7 @@ function RAT:_SetRoute(takeoff, landing, _departure, _destination, _waypoint)
|
|||||||
end
|
end
|
||||||
|
|
||||||
elseif self:_ZoneExists(_destination) then
|
elseif self:_ZoneExists(_destination) then
|
||||||
destination=ZONE:New(_destination)
|
destination=ZONE:FindByName(_destination)
|
||||||
else
|
else
|
||||||
local text=string.format("ERROR: Specified destination airport/zone %s does not exist for %s!", _destination, self.alias)
|
local text=string.format("ERROR: Specified destination airport/zone %s does not exist for %s!", _destination, self.alias)
|
||||||
self:E(RAT.id.."ERROR: "..text)
|
self:E(RAT.id.."ERROR: "..text)
|
||||||
@@ -3142,7 +3142,7 @@ function RAT:_PickDeparture(takeoff)
|
|||||||
end
|
end
|
||||||
elseif self:_ZoneExists(name) then
|
elseif self:_ZoneExists(name) then
|
||||||
if takeoff==RAT.wp.air then
|
if takeoff==RAT.wp.air then
|
||||||
dep=ZONE:New(name)
|
dep=ZONE:FindByName(name)
|
||||||
else
|
else
|
||||||
self:E(RAT.id..string.format("ERROR! Takeoff is not in air. Cannot use %s as departure.", name))
|
self:E(RAT.id..string.format("ERROR! Takeoff is not in air. Cannot use %s as departure.", name))
|
||||||
end
|
end
|
||||||
@@ -3254,7 +3254,7 @@ function RAT:_PickDestination(departure, q, minrange, maxrange, random, landing)
|
|||||||
end
|
end
|
||||||
elseif self:_ZoneExists(name) then
|
elseif self:_ZoneExists(name) then
|
||||||
if landing==RAT.wp.air then
|
if landing==RAT.wp.air then
|
||||||
dest=ZONE:New(name)
|
dest=ZONE:FindByName(name)
|
||||||
else
|
else
|
||||||
self:E(RAT.id..string.format("ERROR! Landing is not in air. Cannot use zone %s as destination!", name))
|
self:E(RAT.id..string.format("ERROR! Landing is not in air. Cannot use zone %s as destination!", name))
|
||||||
end
|
end
|
||||||
@@ -4930,12 +4930,12 @@ function RAT:_AirportExists(name)
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Test if a trigger zone defined in the mission editor exists.
|
--- Test if a zone exists.
|
||||||
-- @param #RAT self
|
-- @param #RAT self
|
||||||
-- @param #string name
|
-- @param #string name
|
||||||
-- @return #boolean True if zone exsits, false otherwise.
|
-- @return #boolean True if zone exsits, false otherwise.
|
||||||
function RAT:_ZoneExists(name)
|
function RAT:_ZoneExists(name)
|
||||||
local z=trigger.misc.getZone(name)
|
local z=ZONE:FindByName(name) --trigger.misc.getZone(name) as suggested by @Viking on MOOSE discord #rat
|
||||||
if z then
|
if z then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1207,18 +1207,18 @@ end
|
|||||||
-- @return #RANGE self
|
-- @return #RANGE self
|
||||||
function RANGE:SetSRS(PathToSRS, Port, Coalition, Frequency, Modulation, Volume, PathToGoogleKey)
|
function RANGE:SetSRS(PathToSRS, Port, Coalition, Frequency, Modulation, Volume, PathToGoogleKey)
|
||||||
|
|
||||||
if PathToSRS then
|
if PathToSRS or MSRS.path then
|
||||||
|
|
||||||
self.useSRS=true
|
self.useSRS=true
|
||||||
|
|
||||||
self.controlmsrs=MSRS:New(PathToSRS, Frequency or 256, Modulation or radio.modulation.AM, Volume or 1.0)
|
self.controlmsrs=MSRS:New(PathToSRS or MSRS.path, Frequency or 256, Modulation or radio.modulation.AM, Volume or 1.0)
|
||||||
self.controlmsrs:SetPort(Port)
|
self.controlmsrs:SetPort(Port or MSRS.port)
|
||||||
self.controlmsrs:SetCoalition(Coalition or coalition.side.BLUE)
|
self.controlmsrs:SetCoalition(Coalition or coalition.side.BLUE)
|
||||||
self.controlmsrs:SetLabel("RANGEC")
|
self.controlmsrs:SetLabel("RANGEC")
|
||||||
self.controlsrsQ = MSRSQUEUE:New("CONTROL")
|
self.controlsrsQ = MSRSQUEUE:New("CONTROL")
|
||||||
|
|
||||||
self.instructmsrs=MSRS:New(PathToSRS, Frequency or 305, Modulation or radio.modulation.AM, Volume or 1.0)
|
self.instructmsrs=MSRS:New(PathToSRS or MSRS.path, Frequency or 305, Modulation or radio.modulation.AM, Volume or 1.0)
|
||||||
self.instructmsrs:SetPort(Port)
|
self.instructmsrs:SetPort(Port or MSRS.port)
|
||||||
self.instructmsrs:SetCoalition(Coalition or coalition.side.BLUE)
|
self.instructmsrs:SetCoalition(Coalition or coalition.side.BLUE)
|
||||||
self.instructmsrs:SetLabel("RANGEI")
|
self.instructmsrs:SetLabel("RANGEI")
|
||||||
self.instructsrsQ = MSRSQUEUE:New("INSTRUCT")
|
self.instructsrsQ = MSRSQUEUE:New("INSTRUCT")
|
||||||
@@ -1738,6 +1738,8 @@ end
|
|||||||
function RANGE:OnEventBirth( EventData )
|
function RANGE:OnEventBirth( EventData )
|
||||||
self:F( { eventbirth = EventData } )
|
self:F( { eventbirth = EventData } )
|
||||||
|
|
||||||
|
if not EventData.IniPlayerName then return end
|
||||||
|
|
||||||
local _unitName = EventData.IniUnitName
|
local _unitName = EventData.IniUnitName
|
||||||
local _unit, _playername = self:_GetPlayerUnitAndName( _unitName )
|
local _unit, _playername = self:_GetPlayerUnitAndName( _unitName )
|
||||||
|
|
||||||
@@ -2187,7 +2189,7 @@ function RANGE:onafterExitRange( From, Event, To, player )
|
|||||||
|
|
||||||
local text = "You left the bombing range zone. "
|
local text = "You left the bombing range zone. "
|
||||||
|
|
||||||
local r=math.random(2)
|
local r=math.random(5)
|
||||||
|
|
||||||
if r==1 then
|
if r==1 then
|
||||||
text=text.."Have a nice day!"
|
text=text.."Have a nice day!"
|
||||||
|
|||||||
@@ -17,9 +17,9 @@
|
|||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ### Authors: **FlightControl**, **applevangelist**
|
-- ### Authors: **applevangelist**, **FlightControl**
|
||||||
--
|
--
|
||||||
-- Last Update: Oct 2023
|
-- Last Update: Dec 2023
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
@@ -144,7 +144,7 @@ function SEAD:New( SEADGroupPrefixes, Padding )
|
|||||||
self:AddTransition("*", "ManageEvasion", "*")
|
self:AddTransition("*", "ManageEvasion", "*")
|
||||||
self:AddTransition("*", "CalculateHitZone", "*")
|
self:AddTransition("*", "CalculateHitZone", "*")
|
||||||
|
|
||||||
self:I("*** SEAD - Started Version 0.4.5")
|
self:I("*** SEAD - Started Version 0.4.6")
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -401,7 +401,7 @@ function SEAD:onafterManageEvasion(From,Event,To,_targetskill,_targetgroup,SEADP
|
|||||||
grp:EnableEmission(false)
|
grp:EnableEmission(false)
|
||||||
end
|
end
|
||||||
grp:OptionAlarmStateGreen() -- needed else we cannot move around
|
grp:OptionAlarmStateGreen() -- needed else we cannot move around
|
||||||
grp:RelocateGroundRandomInRadius(20,300,false,false,"Diamond")
|
grp:RelocateGroundRandomInRadius(20,300,false,false,"Diamond",true)
|
||||||
if self.UseCallBack then
|
if self.UseCallBack then
|
||||||
local object = self.CallBack
|
local object = self.CallBack
|
||||||
object:SeadSuppressionStart(grp,name,attacker)
|
object:SeadSuppressionStart(grp,name,attacker)
|
||||||
|
|||||||
590
Moose Development/Moose/Functional/Tiresias.lua
Normal file
590
Moose Development/Moose/Functional/Tiresias.lua
Normal file
@@ -0,0 +1,590 @@
|
|||||||
|
--- **Functional** - TIRESIAS - manages AI behaviour.
|
||||||
|
--
|
||||||
|
-- ===
|
||||||
|
--
|
||||||
|
-- The @{#TIRESIAS} class is working in the back to keep your large-scale ground units in check.
|
||||||
|
--
|
||||||
|
-- ## Features:
|
||||||
|
--
|
||||||
|
-- * Designed to keep CPU and Network usage lower on missions with a lot of ground units.
|
||||||
|
-- * Does not affect ships to keep the Navy guys happy.
|
||||||
|
-- * Does not affect OpsGroup type groups.
|
||||||
|
-- * Distinguishes between SAM groups, AAA groups and other ground groups.
|
||||||
|
-- * Exceptions can be defined to keep certain actions going.
|
||||||
|
-- * Works coalition-independent in the back
|
||||||
|
-- * Easy setup.
|
||||||
|
--
|
||||||
|
-- ===
|
||||||
|
--
|
||||||
|
-- ## Missions:
|
||||||
|
--
|
||||||
|
-- ### [TIRESIAS](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master)
|
||||||
|
--
|
||||||
|
-- ===
|
||||||
|
--
|
||||||
|
-- ### Author : **applevangelist **
|
||||||
|
--
|
||||||
|
-- @module Functional.Tiresias
|
||||||
|
-- @image Functional.Tiresias.jpg
|
||||||
|
--
|
||||||
|
-- Last Update: Dec 2023
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------
|
||||||
|
--- **TIRESIAS** class, extends Core.Base#BASE
|
||||||
|
-- @type TIRESIAS
|
||||||
|
-- @field #string ClassName
|
||||||
|
-- @field #booelan debug
|
||||||
|
-- @field #string version
|
||||||
|
-- @field #number Interval
|
||||||
|
-- @field Core.Set#SET_GROUP GroundSet
|
||||||
|
-- @field #number Coalition
|
||||||
|
-- @field Core.Set#SET_GROUP VehicleSet
|
||||||
|
-- @field Core.Set#SET_GROUP AAASet
|
||||||
|
-- @field Core.Set#SET_GROUP SAMSet
|
||||||
|
-- @field Core.Set#SET_GROUP ExceptionSet
|
||||||
|
-- @field Core.Set#SET_OPSGROUP OpsGroupSet
|
||||||
|
-- @field #number AAARange
|
||||||
|
-- @field #number HeloSwitchRange
|
||||||
|
-- @field #number PlaneSwitchRange
|
||||||
|
-- @field Core.Set#SET_GROUP FlightSet
|
||||||
|
-- @field #boolean SwitchAAA
|
||||||
|
-- @extends Core.Fsm#FSM
|
||||||
|
|
||||||
|
---
|
||||||
|
-- @type TIRESIAS.Data
|
||||||
|
-- @field #string type
|
||||||
|
-- @field #number range
|
||||||
|
-- @field #boolean invisible
|
||||||
|
-- @field #boolean AIOff
|
||||||
|
-- @field #boolean exception
|
||||||
|
|
||||||
|
|
||||||
|
--- *Tiresias, Greek demi-god and shapeshifter, blinded by the Gods, works as oracle for you.* (Wiki)
|
||||||
|
--
|
||||||
|
-- ===
|
||||||
|
--
|
||||||
|
-- ## TIRESIAS Concept
|
||||||
|
--
|
||||||
|
-- * Designed to keep CPU and Network usage lower on missions with a lot of ground units.
|
||||||
|
-- * Does not affect ships to keep the Navy guys happy.
|
||||||
|
-- * Does not affect OpsGroup type groups.
|
||||||
|
-- * Distinguishes between SAM groups, AAA groups and other ground groups.
|
||||||
|
-- * Exceptions can be defined in SET_GROUP objects to keep certain actions going.
|
||||||
|
-- * Works coalition-independent in the back
|
||||||
|
-- * Easy setup.
|
||||||
|
--
|
||||||
|
-- ## Setup
|
||||||
|
--
|
||||||
|
-- Setup is a one-liner:
|
||||||
|
--
|
||||||
|
-- local blinder = TIRESIAS:New()
|
||||||
|
--
|
||||||
|
-- Optionally you can set up exceptions, e.g. for convoys driving around
|
||||||
|
--
|
||||||
|
-- local exceptionset = SET_GROUP:New():FilterCoalitions("red"):FilterPrefixes("Convoy"):FilterStart()
|
||||||
|
-- local blinder = TIRESIAS:New()
|
||||||
|
-- blinder:AddExceptionSet(exceptionset)
|
||||||
|
--
|
||||||
|
-- Options
|
||||||
|
--
|
||||||
|
-- -- Setup different radius for activation around helo and airplane groups (applies to AI and humans)
|
||||||
|
-- blinder:SetActivationRanges(10,25) -- defaults are 10, and 25
|
||||||
|
--
|
||||||
|
-- -- Setup engagement ranges for AAA (non-advanced SAM units like Flaks etc) and if you want them to be AIOff
|
||||||
|
-- blinder:SetAAARanges(60,true) -- defaults are 60, and true
|
||||||
|
--
|
||||||
|
-- @field #TIRESIAS
|
||||||
|
TIRESIAS = {
|
||||||
|
ClassName = "TIRESIAS",
|
||||||
|
debug = false,
|
||||||
|
version = "0.0.4",
|
||||||
|
Interval = 20,
|
||||||
|
GroundSet = nil,
|
||||||
|
VehicleSet = nil,
|
||||||
|
AAASet = nil,
|
||||||
|
SAMSet = nil,
|
||||||
|
ExceptionSet = nil,
|
||||||
|
AAARange = 60, -- 60%
|
||||||
|
HeloSwitchRange = 10, -- NM
|
||||||
|
PlaneSwitchRange = 25, -- NM
|
||||||
|
SwitchAAA = true,
|
||||||
|
}
|
||||||
|
|
||||||
|
--- [USER] Create a new Tiresias object and start it up.
|
||||||
|
-- @param #TIRESIAS self
|
||||||
|
-- @return #TIRESIAS self
|
||||||
|
function TIRESIAS:New()
|
||||||
|
|
||||||
|
-- Inherit everything from FSM class.
|
||||||
|
local self = BASE:Inherit(self, FSM:New()) -- #TIRESIAS
|
||||||
|
|
||||||
|
--- FSM Functions ---
|
||||||
|
|
||||||
|
-- Start State.
|
||||||
|
self:SetStartState("Stopped")
|
||||||
|
|
||||||
|
-- Add FSM transitions.
|
||||||
|
-- From State --> Event --> To State
|
||||||
|
self:AddTransition("Stopped", "Start", "Running") -- Start FSM.
|
||||||
|
self:AddTransition("*", "Status", "*") -- TIRESIAS status update.
|
||||||
|
self:AddTransition("*", "Stop", "Stopped") -- Stop FSM.
|
||||||
|
|
||||||
|
self.ExceptionSet = SET_GROUP:New():Clear(false)
|
||||||
|
|
||||||
|
self:HandleEvent(EVENTS.PlayerEnterAircraft,self._EventHandler)
|
||||||
|
|
||||||
|
self.lid = string.format("TIRESIAS %s | ",self.version)
|
||||||
|
|
||||||
|
self:I(self.lid.."Managing ground groups!")
|
||||||
|
|
||||||
|
--- Triggers the FSM event "Stop". Stops TIRESIAS and all its event handlers.
|
||||||
|
-- @function [parent=#TIRESIAS] Stop
|
||||||
|
-- @param #TIRESIAS self
|
||||||
|
|
||||||
|
--- Triggers the FSM event "Stop" after a delay. Stops TIRESIAS and all its event handlers.
|
||||||
|
-- @function [parent=#TIRESIAS] __Stop
|
||||||
|
-- @param #TIRESIAS self
|
||||||
|
-- @param #number delay Delay in seconds.
|
||||||
|
|
||||||
|
--- Triggers the FSM event "Start". Starts TIRESIAS and all its event handlers. Note - `:New()` already starts the instance.
|
||||||
|
-- @function [parent=#TIRESIAS] Start
|
||||||
|
-- @param #TIRESIAS self
|
||||||
|
|
||||||
|
--- Triggers the FSM event "Start" after a delay. Starts TIRESIAS and all its event handlers. Note - `:New()` already starts the instance.
|
||||||
|
-- @function [parent=#TIRESIAS] __Start
|
||||||
|
-- @param #TIRESIAS self
|
||||||
|
-- @param #number delay Delay in seconds.
|
||||||
|
|
||||||
|
self:__Start(1)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- Helper Functions
|
||||||
|
--
|
||||||
|
-------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
---[USER] Set activation radius for Helos and Planes in Nautical Miles.
|
||||||
|
-- @param #TIRESIAS self
|
||||||
|
-- @param #number HeloMiles Radius around a Helicopter in which AI ground units will be activated. Defaults to 10NM.
|
||||||
|
-- @param #number PlaneMiles Radius around an Airplane in which AI ground units will be activated. Defaults to 25NM.
|
||||||
|
-- @return #TIRESIAS self
|
||||||
|
function TIRESIAS:SetActivationRanges(HeloMiles,PlaneMiles)
|
||||||
|
self.HeloSwitchRange = HeloMiles or 10
|
||||||
|
self.PlaneSwitchRange = PlaneMiles or 25
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
---[USER] Set AAA Ranges - AAA equals non-SAM systems which qualify as AAA in DCS world.
|
||||||
|
-- @param #TIRESIAS self
|
||||||
|
-- @param #number FiringRange The engagement range that AAA units will be set to. Can be 0 to 100 (percent). Defaults to 60.
|
||||||
|
-- @param #boolean SwitchAAA Decide if these system will have their AI switched off, too. Defaults to true.
|
||||||
|
-- @return #TIRESIAS self
|
||||||
|
function TIRESIAS:SetAAARanges(FiringRange,SwitchAAA)
|
||||||
|
self.AAARange = FiringRange or 60
|
||||||
|
self.SwitchAAA = (SwitchAAA == false) and false or true
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [USER] Add a SET_GROUP of GROUP objects as exceptions. Can be done multiple times.
|
||||||
|
-- @param #TIRESIAS self
|
||||||
|
-- @param Core.Set#SET_GROUP Set to add to the exception list.
|
||||||
|
-- @return #TIRESIAS self
|
||||||
|
function TIRESIAS:AddExceptionSet(Set)
|
||||||
|
self:T(self.lid.."AddExceptionSet")
|
||||||
|
local exceptions = self.ExceptionSet
|
||||||
|
Set:ForEachGroupAlive(
|
||||||
|
function(grp)
|
||||||
|
if not grp.Tiresias then
|
||||||
|
grp.Tiresias = { -- #TIRESIAS.Data
|
||||||
|
type = "Exception",
|
||||||
|
exception = true,
|
||||||
|
}
|
||||||
|
exceptions:AddGroup(grp,true)
|
||||||
|
end
|
||||||
|
BASE:I("TIRESIAS: Added exception group: "..grp:GetName())
|
||||||
|
end
|
||||||
|
)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [INTERNAL] Filter Function
|
||||||
|
-- @param Wrapper.Group#GROUP Group
|
||||||
|
-- @return #boolean isin
|
||||||
|
function TIRESIAS._FilterNotAAA(Group)
|
||||||
|
local grp = Group -- Wrapper.Group#GROUP
|
||||||
|
local isaaa = grp:IsAAA()
|
||||||
|
if isaaa == true and grp:IsGround() and not grp:IsShip() then
|
||||||
|
return false -- remove from SET
|
||||||
|
else
|
||||||
|
return true -- keep in SET
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [INTERNAL] Filter Function
|
||||||
|
-- @param Wrapper.Group#GROUP Group
|
||||||
|
-- @return #boolean isin
|
||||||
|
function TIRESIAS._FilterNotSAM(Group)
|
||||||
|
local grp = Group -- Wrapper.Group#GROUP
|
||||||
|
local issam = grp:IsSAM()
|
||||||
|
if issam == true and grp:IsGround() and not grp:IsShip() then
|
||||||
|
return false -- remove from SET
|
||||||
|
else
|
||||||
|
return true -- keep in SET
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [INTERNAL] Filter Function
|
||||||
|
-- @param Wrapper.Group#GROUP Group
|
||||||
|
-- @return #boolean isin
|
||||||
|
function TIRESIAS._FilterAAA(Group)
|
||||||
|
local grp = Group -- Wrapper.Group#GROUP
|
||||||
|
local isaaa = grp:IsAAA()
|
||||||
|
if isaaa == true and grp:IsGround() and not grp:IsShip() then
|
||||||
|
return true -- remove from SET
|
||||||
|
else
|
||||||
|
return false -- keep in SET
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [INTERNAL] Filter Function
|
||||||
|
-- @param Wrapper.Group#GROUP Group
|
||||||
|
-- @return #boolean isin
|
||||||
|
function TIRESIAS._FilterSAM(Group)
|
||||||
|
local grp = Group -- Wrapper.Group#GROUP
|
||||||
|
local issam = grp:IsSAM()
|
||||||
|
if issam == true and grp:IsGround() and not grp:IsShip() then
|
||||||
|
return true -- remove from SET
|
||||||
|
else
|
||||||
|
return false -- keep in SET
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [INTERNAL] Init Groups
|
||||||
|
-- @param #TIRESIAS self
|
||||||
|
-- @return #TIRESIAS self
|
||||||
|
function TIRESIAS:_InitGroups()
|
||||||
|
self:T(self.lid.."_InitGroups")
|
||||||
|
-- Set all groups invisible/motionless
|
||||||
|
local EngageRange = self.AAARange
|
||||||
|
local SwitchAAA = self.SwitchAAA
|
||||||
|
--- AAA
|
||||||
|
self.AAASet:ForEachGroupAlive(
|
||||||
|
function(grp)
|
||||||
|
if not grp.Tiresias then
|
||||||
|
grp:OptionEngageRange(EngageRange)
|
||||||
|
grp:SetCommandInvisible(true)
|
||||||
|
if SwitchAAA then
|
||||||
|
grp:SetAIOff()
|
||||||
|
grp:EnableEmission(false)
|
||||||
|
end
|
||||||
|
grp.Tiresias = { -- #TIRESIAS.Data
|
||||||
|
type = "AAA",
|
||||||
|
invisible = true,
|
||||||
|
range = EngageRange,
|
||||||
|
exception = false,
|
||||||
|
AIOff = SwitchAAA,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
if grp.Tiresias and (not grp.Tiresias.exception == true) then
|
||||||
|
if grp.Tiresias.invisible and grp.Tiresias.invisible == false then
|
||||||
|
grp:SetCommandInvisible(true)
|
||||||
|
grp.Tiresias.invisible = true
|
||||||
|
if SwitchAAA then
|
||||||
|
grp:SetAIOff()
|
||||||
|
grp:EnableEmission(false)
|
||||||
|
grp.Tiresias.AIOff = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
--BASE:I(string.format("Init/Switch off AAA %s (Exception %s)",grp:GetName(),tostring(grp.Tiresias.exception)))
|
||||||
|
end
|
||||||
|
)
|
||||||
|
--- Vehicles
|
||||||
|
self.VehicleSet:ForEachGroupAlive(
|
||||||
|
function(grp)
|
||||||
|
if not grp.Tiresias then
|
||||||
|
grp:SetAIOff()
|
||||||
|
grp:SetCommandInvisible(true)
|
||||||
|
grp.Tiresias = { -- #TIRESIAS.Data
|
||||||
|
type = "Vehicle",
|
||||||
|
invisible = true,
|
||||||
|
AIOff = true,
|
||||||
|
exception = false,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
if grp.Tiresias and (not grp.Tiresias.exception == true) then
|
||||||
|
if grp.Tiresias and grp.Tiresias.invisible and grp.Tiresias.invisible == false then
|
||||||
|
grp:SetCommandInvisible(true)
|
||||||
|
grp:SetAIOff()
|
||||||
|
grp.Tiresias.invisible = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
--BASE:I(string.format("Init/Switch off Vehicle %s (Exception %s)",grp:GetName(),tostring(grp.Tiresias.exception)))
|
||||||
|
end
|
||||||
|
)
|
||||||
|
--- SAM
|
||||||
|
self.SAMSet:ForEachGroupAlive(
|
||||||
|
function(grp)
|
||||||
|
if not grp.Tiresias then
|
||||||
|
grp:SetCommandInvisible(true)
|
||||||
|
grp.Tiresias = { -- #TIRESIAS.Data
|
||||||
|
type = "SAM",
|
||||||
|
invisible = true,
|
||||||
|
exception = false,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
if grp.Tiresias and (not grp.Tiresias.exception == true) then
|
||||||
|
if grp.Tiresias and grp.Tiresias.invisible and grp.Tiresias.invisible == false then
|
||||||
|
grp:SetCommandInvisible(true)
|
||||||
|
grp.Tiresias.invisible = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
--BASE:I(string.format("Init/Switch off SAM %s (Exception %s)",grp:GetName(),tostring(grp.Tiresias.exception)))
|
||||||
|
end
|
||||||
|
)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [INTERNAL] Event handler function
|
||||||
|
-- @param #TIRESIAS self
|
||||||
|
-- @param Core.Event#EVENTDATA EventData
|
||||||
|
-- @return #TIRESIAS self
|
||||||
|
function TIRESIAS:_EventHandler(EventData)
|
||||||
|
self:T(string.format("%s Event = %d",self.lid, EventData.id))
|
||||||
|
local event = EventData -- Core.Event#EVENTDATA
|
||||||
|
if event.id == EVENTS.PlayerEnterAircraft or event.id == EVENTS.PlayerEnterUnit then
|
||||||
|
--local _coalition = event.IniCoalition
|
||||||
|
--if _coalition ~= self.Coalition then
|
||||||
|
-- return --ignore!
|
||||||
|
--end
|
||||||
|
local unitname = event.IniUnitName or "none"
|
||||||
|
local _unit = event.IniUnit
|
||||||
|
local _group = event.IniGroup
|
||||||
|
if _group and _group:IsAlive() then
|
||||||
|
local radius = self.PlaneSwitchRange
|
||||||
|
if _group:IsHelicopter() then
|
||||||
|
radius = self.HeloSwitchRange
|
||||||
|
end
|
||||||
|
self:_SwitchOnGroups(_group,radius)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [INTERNAL] Switch Groups Behaviour
|
||||||
|
-- @param #TIRESIAS self
|
||||||
|
-- @param Wrapper.Group#GROUP group
|
||||||
|
-- @param #number radius Radius in NM
|
||||||
|
-- @return #TIRESIAS self
|
||||||
|
function TIRESIAS:_SwitchOnGroups(group,radius)
|
||||||
|
self:T(self.lid.."_SwitchOnGroups "..group:GetName().." Radius "..radius.." NM")
|
||||||
|
local zone = ZONE_GROUP:New("Zone-"..group:GetName(),group,UTILS.NMToMeters(radius))
|
||||||
|
local ground = SET_GROUP:New():FilterCategoryGround():FilterZones({zone}):FilterOnce()
|
||||||
|
local count = ground:CountAlive()
|
||||||
|
if self.debug then
|
||||||
|
local text = string.format("There are %d groups around this plane or helo!",count)
|
||||||
|
self:I(text)
|
||||||
|
end
|
||||||
|
local SwitchAAA = self.SwitchAAA
|
||||||
|
if ground:CountAlive() > 0 then
|
||||||
|
ground:ForEachGroupAlive(
|
||||||
|
function(grp)
|
||||||
|
if grp.Tiresias and grp.Tiresias.type and (not grp.Tiresias.exception == true ) then
|
||||||
|
if grp.Tiresias.invisible == true then
|
||||||
|
grp:SetCommandInvisible(false)
|
||||||
|
grp.Tiresias.invisible = false
|
||||||
|
end
|
||||||
|
if grp.Tiresias.type == "Vehicle" and grp.Tiresias.AIOff and grp.Tiresias.AIOff == true then
|
||||||
|
grp:SetAIOn()
|
||||||
|
grp.Tiresias.AIOff = false
|
||||||
|
end
|
||||||
|
if SwitchAAA and grp.Tiresias.type == "AAA" and grp.Tiresias.AIOff and grp.Tiresias.AIOff == true then
|
||||||
|
grp:SetAIOn()
|
||||||
|
grp:EnableEmission(true)
|
||||||
|
grp.Tiresias.AIOff = false
|
||||||
|
end
|
||||||
|
--BASE:I(string.format("TIRESIAS - Switch on %s %s (Exception %s)",tostring(grp.Tiresias.type),grp:GetName(),tostring(grp.Tiresias.exception)))
|
||||||
|
else
|
||||||
|
BASE:E("TIRESIAS - This group has not been initialized or is an exception!")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
)
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- FSM Functions
|
||||||
|
--
|
||||||
|
-------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- [INTERNAL] FSM Function
|
||||||
|
-- @param #TIRESIAS self
|
||||||
|
-- @param #string From
|
||||||
|
-- @param #string Event
|
||||||
|
-- @param #string To
|
||||||
|
-- @return #TIRESIAS self
|
||||||
|
function TIRESIAS:onafterStart(From, Event, To)
|
||||||
|
self:T({From, Event, To})
|
||||||
|
|
||||||
|
local VehicleSet = SET_GROUP:New():FilterCategoryGround():FilterFunction(TIRESIAS._FilterNotAAA):FilterFunction(TIRESIAS._FilterNotSAM):FilterStart()
|
||||||
|
local AAASet = SET_GROUP:New():FilterCategoryGround():FilterFunction(TIRESIAS._FilterAAA):FilterStart()
|
||||||
|
local SAMSet = SET_GROUP:New():FilterCategoryGround():FilterFunction(TIRESIAS._FilterSAM):FilterStart()
|
||||||
|
local OpsGroupSet = SET_OPSGROUP:New():FilterActive(true):FilterStart()
|
||||||
|
self.FlightSet = SET_GROUP:New():FilterCategories({"plane","helicopter"}):FilterStart()
|
||||||
|
|
||||||
|
local EngageRange = self.AAARange
|
||||||
|
|
||||||
|
local ExceptionSet = self.ExceptionSet
|
||||||
|
if self.ExceptionSet then
|
||||||
|
function ExceptionSet:OnAfterAdded(From,Event,To,ObjectName,Object)
|
||||||
|
BASE:I("TIRESIAS: EXCEPTION Object Added: "..Object:GetName())
|
||||||
|
if Object and Object:IsAlive() then
|
||||||
|
Object.Tiresias = { -- #TIRESIAS.Data
|
||||||
|
type = "Exception",
|
||||||
|
exception = true,
|
||||||
|
}
|
||||||
|
Object:SetAIOn()
|
||||||
|
Object:SetCommandInvisible(false)
|
||||||
|
Object:EnableEmission(true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local OGS = OpsGroupSet:GetAliveSet()
|
||||||
|
for _,_OG in pairs(OGS or {}) do
|
||||||
|
local OG = _OG -- Ops.OpsGroup#OPSGROUP
|
||||||
|
local grp = OG:GetGroup()
|
||||||
|
ExceptionSet:AddGroup(grp,true)
|
||||||
|
end
|
||||||
|
|
||||||
|
function OpsGroupSet:OnAfterAdded(From,Event,To,ObjectName,Object)
|
||||||
|
local grp = Object:GetGroup()
|
||||||
|
ExceptionSet:AddGroup(grp,true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function VehicleSet:OnAfterAdded(From,Event,To,ObjectName,Object)
|
||||||
|
BASE:I("TIRESIAS: VEHCILE Object Added: "..Object:GetName())
|
||||||
|
if Object and Object:IsAlive() then
|
||||||
|
Object:SetAIOff()
|
||||||
|
Object:SetCommandInvisible(true)
|
||||||
|
Object.Tiresias = { -- #TIRESIAS.Data
|
||||||
|
type = "Vehicle",
|
||||||
|
invisible = true,
|
||||||
|
AIOff = true,
|
||||||
|
exception = false,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local SwitchAAA = self.SwitchAAA
|
||||||
|
|
||||||
|
function AAASet:OnAfterAdded(From,Event,To,ObjectName,Object)
|
||||||
|
if Object and Object:IsAlive() then
|
||||||
|
BASE:I("TIRESIAS: AAA Object Added: "..Object:GetName())
|
||||||
|
Object:OptionEngageRange(EngageRange)
|
||||||
|
Object:SetCommandInvisible(true)
|
||||||
|
if SwitchAAA then
|
||||||
|
Object:SetAIOff()
|
||||||
|
Object:EnableEmission(false)
|
||||||
|
end
|
||||||
|
Object.Tiresias = { -- #TIRESIAS.Data
|
||||||
|
type = "AAA",
|
||||||
|
invisible = true,
|
||||||
|
range = EngageRange,
|
||||||
|
exception = false,
|
||||||
|
AIOff = SwitchAAA,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function SAMSet:OnAfterAdded(From,Event,To,ObjectName,Object)
|
||||||
|
if Object and Object:IsAlive() then
|
||||||
|
BASE:I("TIRESIAS: SAM Object Added: "..Object:GetName())
|
||||||
|
Object:SetCommandInvisible(true)
|
||||||
|
Object.Tiresias = { -- #TIRESIAS.Data
|
||||||
|
type = "SAM",
|
||||||
|
invisible = true,
|
||||||
|
exception = false,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
self.VehicleSet = VehicleSet
|
||||||
|
self.AAASet = AAASet
|
||||||
|
self.SAMSet = SAMSet
|
||||||
|
self.OpsGroupSet = OpsGroupSet
|
||||||
|
|
||||||
|
self:_InitGroups()
|
||||||
|
|
||||||
|
self:__Status(1)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [INTERNAL] FSM Function
|
||||||
|
-- @param #TIRESIAS self
|
||||||
|
-- @param #string From
|
||||||
|
-- @param #string Event
|
||||||
|
-- @param #string To
|
||||||
|
-- @return #TIRESIAS self
|
||||||
|
function TIRESIAS:onbeforeStatus(From, Event, To)
|
||||||
|
self:T({From, Event, To})
|
||||||
|
if self:GetState() == "Stopped" then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [INTERNAL] FSM Function
|
||||||
|
-- @param #TIRESIAS self
|
||||||
|
-- @param #string From
|
||||||
|
-- @param #string Event
|
||||||
|
-- @param #string To
|
||||||
|
-- @return #TIRESIAS self
|
||||||
|
function TIRESIAS:onafterStatus(From, Event, To)
|
||||||
|
self:T({From, Event, To})
|
||||||
|
if self.debug then
|
||||||
|
local count = self.VehicleSet:CountAlive()
|
||||||
|
local AAAcount = self.AAASet:CountAlive()
|
||||||
|
local SAMcount = self.SAMSet:CountAlive()
|
||||||
|
local text = string.format("Overall: %d | Vehicles: %d | AAA: %d | SAM: %d",count+AAAcount+SAMcount,count,AAAcount,SAMcount)
|
||||||
|
self:I(text)
|
||||||
|
end
|
||||||
|
self:_InitGroups()
|
||||||
|
if self.FlightSet:CountAlive() > 0 then
|
||||||
|
local Set = self.FlightSet:GetAliveSet()
|
||||||
|
for _,_plane in pairs(Set) do
|
||||||
|
local plane = _plane -- Wrapper.Group#GROUP
|
||||||
|
local radius = self.PlaneSwitchRange
|
||||||
|
if plane:IsHelicopter() then
|
||||||
|
radius = self.HeloSwitchRange
|
||||||
|
end
|
||||||
|
self:_SwitchOnGroups(_plane,radius)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if self:GetState() ~= "Stopped" then
|
||||||
|
self:__Status(self.Interval)
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [INTERNAL] FSM Function
|
||||||
|
-- @param #TIRESIAS self
|
||||||
|
-- @param #string From
|
||||||
|
-- @param #string Event
|
||||||
|
-- @param #string To
|
||||||
|
-- @return #TIRESIAS self
|
||||||
|
function TIRESIAS:onafterStop(From, Event, To)
|
||||||
|
self:T({From, Event, To})
|
||||||
|
self:UnHandleEvent(EVENTS.PlayerEnterAircraft)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------
|
||||||
|
--
|
||||||
|
-- End
|
||||||
|
--
|
||||||
|
-------------------------------------------------------------------------------------------------------------
|
||||||
@@ -84,6 +84,7 @@ __Moose.Include( 'Scripts/Moose/Functional/ZoneCaptureCoalition.lua' )
|
|||||||
__Moose.Include( 'Scripts/Moose/Functional/ZoneGoal.lua' )
|
__Moose.Include( 'Scripts/Moose/Functional/ZoneGoal.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Functional/ZoneGoalCargo.lua' )
|
__Moose.Include( 'Scripts/Moose/Functional/ZoneGoalCargo.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Functional/ZoneGoalCoalition.lua' )
|
__Moose.Include( 'Scripts/Moose/Functional/ZoneGoalCoalition.lua' )
|
||||||
|
__Moose.Include( 'Scripts/Moose/Functional/Tiresias.lua' )
|
||||||
|
|
||||||
__Moose.Include( 'Scripts/Moose/Ops/Airboss.lua' )
|
__Moose.Include( 'Scripts/Moose/Ops/Airboss.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Ops/AirWing.lua' )
|
__Moose.Include( 'Scripts/Moose/Ops/AirWing.lua' )
|
||||||
|
|||||||
@@ -890,7 +890,7 @@ _ATIS = {}
|
|||||||
|
|
||||||
--- ATIS class version.
|
--- ATIS class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
ATIS.version = "0.10.4"
|
ATIS.version = "1.0.0"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- TODO list
|
-- TODO list
|
||||||
@@ -1528,12 +1528,12 @@ end
|
|||||||
|
|
||||||
--- Use SRS Simple-Text-To-Speech for transmissions. No sound files necessary.
|
--- Use SRS Simple-Text-To-Speech for transmissions. No sound files necessary.
|
||||||
-- @param #ATIS self
|
-- @param #ATIS self
|
||||||
-- @param #string PathToSRS Path to SRS directory.
|
-- @param #string PathToSRS Path to SRS directory (only necessary if SRS exe backend is used).
|
||||||
-- @param #string Gender Gender: "male" or "female" (default).
|
-- @param #string Gender Gender: "male" or "female" (default).
|
||||||
-- @param #string Culture Culture, e.g. "en-GB" (default).
|
-- @param #string Culture Culture, e.g. "en-GB" (default).
|
||||||
-- @param #string Voice Specific voice. Overrides `Gender` and `Culture`.
|
-- @param #string Voice Specific voice. Overrides `Gender` and `Culture`.
|
||||||
-- @param #number Port SRS port. Default 5002.
|
-- @param #number Port SRS port. Default 5002.
|
||||||
-- @param #string GoogleKey Path to Google JSON-Key.
|
-- @param #string GoogleKey Path to Google JSON-Key (SRS exe backend) or Google API key (DCS-gRPC backend).
|
||||||
-- @return #ATIS self
|
-- @return #ATIS self
|
||||||
function ATIS:SetSRS(PathToSRS, Gender, Culture, Voice, Port, GoogleKey)
|
function ATIS:SetSRS(PathToSRS, Gender, Culture, Voice, Port, GoogleKey)
|
||||||
if PathToSRS or MSRS.path then
|
if PathToSRS or MSRS.path then
|
||||||
|
|||||||
@@ -8212,7 +8212,7 @@ function AIRBOSS:OnEventBirth( EventData )
|
|||||||
self:E( EventData )
|
self:E( EventData )
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
if EventData.IniUnit == nil then
|
if EventData.IniUnit == nil and (not EventData.IniObjectCategory == Object.Category.STATIC) then
|
||||||
self:E( self.lid .. "ERROR: EventData.IniUnit=nil in event BIRTH!" )
|
self:E( self.lid .. "ERROR: EventData.IniUnit=nil in event BIRTH!" )
|
||||||
self:E( EventData )
|
self:E( EventData )
|
||||||
return
|
return
|
||||||
@@ -11197,7 +11197,7 @@ function AIRBOSS:_AttitudeMonitor( playerData )
|
|||||||
end
|
end
|
||||||
text = text .. string.format( "\nPitch=%.1f° | Roll=%.1f° | Yaw=%.1f°", pitch, roll, yaw )
|
text = text .. string.format( "\nPitch=%.1f° | Roll=%.1f° | Yaw=%.1f°", pitch, roll, yaw )
|
||||||
text = text .. string.format( "\nClimb Angle=%.1f° | Rate=%d ft/min", unit:GetClimbAngle(), velo.y * 196.85 )
|
text = text .. string.format( "\nClimb Angle=%.1f° | Rate=%d ft/min", unit:GetClimbAngle(), velo.y * 196.85 )
|
||||||
local dist = self:_GetOptLandingCoordinate():Get3DDistance( playerData.unit )
|
local dist = self:_GetOptLandingCoordinate():Get3DDistance( playerData.unit:GetVec3() )
|
||||||
-- Get player velocity in km/h.
|
-- Get player velocity in km/h.
|
||||||
local vplayer = playerData.unit:GetVelocityKMH()
|
local vplayer = playerData.unit:GetVelocityKMH()
|
||||||
-- Get carrier velocity in km/h.
|
-- Get carrier velocity in km/h.
|
||||||
@@ -14957,7 +14957,7 @@ function AIRBOSS:SetSRSPilotVoice( Voice, Gender, Culture )
|
|||||||
self.PilotRadio.gender = Gender or "male"
|
self.PilotRadio.gender = Gender or "male"
|
||||||
self.PilotRadio.culture = Culture or "en-US"
|
self.PilotRadio.culture = Culture or "en-US"
|
||||||
|
|
||||||
if (not Voice) and self.SRS and self.SRS.google then
|
if (not Voice) and self.SRS and self.SRS:GetProvider() == MSRS.Provider.GOOGLE then
|
||||||
self.PilotRadio.voice = MSRS.Voices.Google.Standard.en_US_Standard_J
|
self.PilotRadio.voice = MSRS.Voices.Google.Standard.en_US_Standard_J
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1861,6 +1861,7 @@ function ARMYGROUP:_UpdateEngageTarget()
|
|||||||
else
|
else
|
||||||
|
|
||||||
-- Could not get position of target (not alive any more?) ==> Disengage.
|
-- Could not get position of target (not alive any more?) ==> Disengage.
|
||||||
|
self:T(self.lid.."Could not get position of target ==> Disengage!")
|
||||||
self:Disengage()
|
self:Disengage()
|
||||||
|
|
||||||
end
|
end
|
||||||
@@ -1868,6 +1869,7 @@ function ARMYGROUP:_UpdateEngageTarget()
|
|||||||
else
|
else
|
||||||
|
|
||||||
-- Target not alive any more ==> Disengage.
|
-- Target not alive any more ==> Disengage.
|
||||||
|
self:T(self.lid.."Target not ALIVE ==> Disengage!")
|
||||||
self:Disengage()
|
self:Disengage()
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
-- @image OPS_CSAR.jpg
|
-- @image OPS_CSAR.jpg
|
||||||
|
|
||||||
-- Date: May 2023
|
-- Date: May 2023
|
||||||
-- Last: Update Oct 2024
|
-- Last: Update Dec 2024
|
||||||
|
|
||||||
-------------------------------------------------------------------------
|
-------------------------------------------------------------------------
|
||||||
--- **CSAR** class, extends Core.Base#BASE, Core.Fsm#FSM
|
--- **CSAR** class, extends Core.Base#BASE, Core.Fsm#FSM
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
-- @module Ops.CTLD
|
-- @module Ops.CTLD
|
||||||
-- @image OPS_CTLD.jpg
|
-- @image OPS_CTLD.jpg
|
||||||
|
|
||||||
-- Last Update November 2023
|
-- Last Update December 2023
|
||||||
|
|
||||||
do
|
do
|
||||||
|
|
||||||
@@ -1228,7 +1228,7 @@ CTLD.UnitTypeCapabilities = {
|
|||||||
|
|
||||||
--- CTLD class version.
|
--- CTLD class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
CTLD.version="1.0.43"
|
CTLD.version="1.0.45"
|
||||||
|
|
||||||
--- Instantiate a new CTLD.
|
--- Instantiate a new CTLD.
|
||||||
-- @param #CTLD self
|
-- @param #CTLD self
|
||||||
@@ -1443,6 +1443,7 @@ function CTLD:New(Coalition, Prefixes, Alias)
|
|||||||
-- @param #number delay Delay in seconds.
|
-- @param #number delay Delay in seconds.
|
||||||
|
|
||||||
--- Triggers the FSM event "Stop". Stops the CTLD and all its event handlers.
|
--- Triggers the FSM event "Stop". Stops the CTLD and all its event handlers.
|
||||||
|
-- @function [parent=#CTLD] Stop
|
||||||
-- @param #CTLD self
|
-- @param #CTLD self
|
||||||
|
|
||||||
--- Triggers the FSM event "Stop" after a delay. Stops the CTLD and all its event handlers.
|
--- Triggers the FSM event "Stop" after a delay. Stops the CTLD and all its event handlers.
|
||||||
@@ -2455,10 +2456,12 @@ function CTLD:_GetCrates(Group, Unit, Cargo, number, drop, pack)
|
|||||||
table.insert(droppedcargo,realcargo)
|
table.insert(droppedcargo,realcargo)
|
||||||
else
|
else
|
||||||
realcargo = CTLD_CARGO:New(self.CargoCounter,cratename,templ,sorte,false,false,cratesneeded,self.Spawned_Crates[self.CrateCounter],false,cargotype.PerCrateMass,nil,subcat)
|
realcargo = CTLD_CARGO:New(self.CargoCounter,cratename,templ,sorte,false,false,cratesneeded,self.Spawned_Crates[self.CrateCounter],false,cargotype.PerCrateMass,nil,subcat)
|
||||||
Cargo:RemoveStock()
|
|
||||||
end
|
end
|
||||||
table.insert(self.Spawned_Cargo, realcargo)
|
table.insert(self.Spawned_Cargo, realcargo)
|
||||||
end
|
end
|
||||||
|
if not (drop or pack) then
|
||||||
|
Cargo:RemoveStock()
|
||||||
|
end
|
||||||
local text = string.format("Crates for %s have been positioned near you!",cratename)
|
local text = string.format("Crates for %s have been positioned near you!",cratename)
|
||||||
if drop then
|
if drop then
|
||||||
text = string.format("Crates for %s have been dropped!",cratename)
|
text = string.format("Crates for %s have been dropped!",cratename)
|
||||||
@@ -2561,6 +2564,40 @@ function CTLD:_ListCratesNearby( _group, _unit)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- (Internal) Function to find and Remove nearby crates.
|
||||||
|
-- @param #CTLD self
|
||||||
|
-- @param Wrapper.Group#GROUP Group
|
||||||
|
-- @param Wrapper.Unit#UNIT Unit
|
||||||
|
-- @return #CTLD self
|
||||||
|
function CTLD:_RemoveCratesNearby( _group, _unit)
|
||||||
|
self:T(self.lid .. " _RemoveCratesNearby")
|
||||||
|
local finddist = self.CrateDistance or 35
|
||||||
|
local crates,number = self:_FindCratesNearby(_group,_unit, finddist,true) -- #table
|
||||||
|
if number > 0 then
|
||||||
|
local text = REPORT:New("Removing Crates Found Nearby:")
|
||||||
|
text:Add("------------------------------------------------------------")
|
||||||
|
for _,_entry in pairs (crates) do
|
||||||
|
local entry = _entry -- #CTLD_CARGO
|
||||||
|
local name = entry:GetName() --#string
|
||||||
|
local dropped = entry:WasDropped()
|
||||||
|
if dropped then
|
||||||
|
text:Add(string.format("Crate for %s, %dkg removed",name, entry.PerCrateMass))
|
||||||
|
else
|
||||||
|
text:Add(string.format("Crate for %s, %dkg removed",name, entry.PerCrateMass))
|
||||||
|
end
|
||||||
|
entry:GetPositionable():Destroy(false)
|
||||||
|
end
|
||||||
|
if text:GetCount() == 1 then
|
||||||
|
text:Add(" N O N E")
|
||||||
|
end
|
||||||
|
text:Add("------------------------------------------------------------")
|
||||||
|
self:_SendMessage(text:Text(), 30, true, _group)
|
||||||
|
else
|
||||||
|
self:_SendMessage(string.format("No (loadable) crates within %d meters!",finddist), 10, false, _group)
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- (Internal) Return distance in meters between two coordinates.
|
--- (Internal) Return distance in meters between two coordinates.
|
||||||
-- @param #CTLD self
|
-- @param #CTLD self
|
||||||
-- @param Core.Point#COORDINATE _point1 Coordinate one
|
-- @param Core.Point#COORDINATE _point1 Coordinate one
|
||||||
@@ -2976,6 +3013,35 @@ function CTLD:IsHercules(Unit)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- (Internal) Function to set troops positions of a template to a nice circle
|
||||||
|
-- @param #CTLD self
|
||||||
|
-- @param Core.Point#COORDINATE Coordinate Start coordinate to use
|
||||||
|
-- @param #number Radius Radius to be used
|
||||||
|
-- @param #number Heading Heading starting with
|
||||||
|
-- @param #string Template The group template name
|
||||||
|
-- @return #table Positions The positions table
|
||||||
|
function CTLD:_GetUnitPositions(Coordinate,Radius,Heading,Template)
|
||||||
|
local Positions = {}
|
||||||
|
local template = _DATABASE:GetGroupTemplate(Template)
|
||||||
|
UTILS.PrintTableToLog(template)
|
||||||
|
local numbertroops = #template.units
|
||||||
|
local newcenter = Coordinate:Translate(Radius,((Heading+270)%360))
|
||||||
|
for i=1,360,math.floor(360/numbertroops) do
|
||||||
|
local phead = ((Heading+270+i)%360)
|
||||||
|
local post = newcenter:Translate(Radius,phead)
|
||||||
|
local pos1 = post:GetVec2()
|
||||||
|
local p1t = {
|
||||||
|
x = pos1.x,
|
||||||
|
y = pos1.y,
|
||||||
|
heading = phead,
|
||||||
|
}
|
||||||
|
table.insert(Positions,p1t)
|
||||||
|
end
|
||||||
|
UTILS.PrintTableToLog(Positions)
|
||||||
|
return Positions
|
||||||
|
end
|
||||||
|
|
||||||
--- (Internal) Function to unload troops from heli.
|
--- (Internal) Function to unload troops from heli.
|
||||||
-- @param #CTLD self
|
-- @param #CTLD self
|
||||||
-- @param Wrapper.Group#GROUP Group
|
-- @param Wrapper.Group#GROUP Group
|
||||||
@@ -3027,14 +3093,29 @@ function CTLD:_UnloadTroops(Group, Unit)
|
|||||||
zoneradius = Unit:GetVelocityMPS() or 100
|
zoneradius = Unit:GetVelocityMPS() or 100
|
||||||
end
|
end
|
||||||
local zone = ZONE_GROUP:New(string.format("Unload zone-%s",unitname),Group,zoneradius*factor)
|
local zone = ZONE_GROUP:New(string.format("Unload zone-%s",unitname),Group,zoneradius*factor)
|
||||||
local randomcoord = zone:GetRandomCoordinate(10,30*factor):GetVec2()
|
local randomcoord = zone:GetRandomCoordinate(10,30*factor) --:GetVec2()
|
||||||
|
local heading = Group:GetHeading() or 0
|
||||||
|
-- Spawn troops left from us, closer when hovering, further off when landed
|
||||||
|
if hoverunload or grounded then
|
||||||
|
randomcoord = Group:GetCoordinate()
|
||||||
|
-- slightly left from us
|
||||||
|
local Angle = (heading+270)%360
|
||||||
|
local offset = hoverunload and 1.5 or 5
|
||||||
|
randomcoord:Translate(offset,Angle,nil,true)
|
||||||
|
end
|
||||||
|
local tempcount = 0
|
||||||
for _,_template in pairs(temptable) do
|
for _,_template in pairs(temptable) do
|
||||||
self.TroopCounter = self.TroopCounter + 1
|
self.TroopCounter = self.TroopCounter + 1
|
||||||
|
tempcount = tempcount+1
|
||||||
local alias = string.format("%s-%d", _template, math.random(1,100000))
|
local alias = string.format("%s-%d", _template, math.random(1,100000))
|
||||||
|
local rad = 2.5+tempcount
|
||||||
|
local Positions = self:_GetUnitPositions(randomcoord,rad,heading,_template)
|
||||||
self.DroppedTroops[self.TroopCounter] = SPAWN:NewWithAlias(_template,alias)
|
self.DroppedTroops[self.TroopCounter] = SPAWN:NewWithAlias(_template,alias)
|
||||||
:InitRandomizeUnits(true,20,2)
|
--:InitRandomizeUnits(true,20,2)
|
||||||
|
--:InitHeading(heading)
|
||||||
:InitDelayOff()
|
:InitDelayOff()
|
||||||
:SpawnFromVec2(randomcoord)
|
:InitSetUnitAbsolutePositions(Positions)
|
||||||
|
:SpawnFromVec2(randomcoord:GetVec2())
|
||||||
self:__TroopsDeployed(1, Group, Unit, self.DroppedTroops[self.TroopCounter],type)
|
self:__TroopsDeployed(1, Group, Unit, self.DroppedTroops[self.TroopCounter],type)
|
||||||
end -- template loop
|
end -- template loop
|
||||||
cargo:SetWasDropped(true)
|
cargo:SetWasDropped(true)
|
||||||
@@ -3637,6 +3718,7 @@ function CTLD:_RefreshF10Menus()
|
|||||||
local loadmenu = MENU_GROUP_COMMAND:New(_group,"Load crates",topcrates, self._LoadCratesNearby, self, _group, _unit)
|
local loadmenu = MENU_GROUP_COMMAND:New(_group,"Load crates",topcrates, self._LoadCratesNearby, self, _group, _unit)
|
||||||
local cratesmenu = MENU_GROUP:New(_group,"Get Crates",topcrates)
|
local cratesmenu = MENU_GROUP:New(_group,"Get Crates",topcrates)
|
||||||
local packmenu = MENU_GROUP_COMMAND:New(_group, "Pack crates", topcrates, self._PackCratesNearby, self, _group, _unit)
|
local packmenu = MENU_GROUP_COMMAND:New(_group, "Pack crates", topcrates, self._PackCratesNearby, self, _group, _unit)
|
||||||
|
local removecratesmenu = MENU_GROUP:New(_group, "Remove crates", topcrates)
|
||||||
|
|
||||||
if self.usesubcats then
|
if self.usesubcats then
|
||||||
local subcatmenus = {}
|
local subcatmenus = {}
|
||||||
@@ -3672,6 +3754,7 @@ function CTLD:_RefreshF10Menus()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
listmenu = MENU_GROUP_COMMAND:New(_group,"List crates nearby",topcrates, self._ListCratesNearby, self, _group, _unit)
|
listmenu = MENU_GROUP_COMMAND:New(_group,"List crates nearby",topcrates, self._ListCratesNearby, self, _group, _unit)
|
||||||
|
removecrates = MENU_GROUP_COMMAND:New(_group,"Remove crates nearby",removecratesmenu, self._RemoveCratesNearby, self, _group, _unit)
|
||||||
local unloadmenu = MENU_GROUP_COMMAND:New(_group,"Drop crates",topcrates, self._UnloadCrates, self, _group, _unit)
|
local unloadmenu = MENU_GROUP_COMMAND:New(_group,"Drop crates",topcrates, self._UnloadCrates, self, _group, _unit)
|
||||||
if not self.nobuildmenu then
|
if not self.nobuildmenu then
|
||||||
local buildmenu = MENU_GROUP_COMMAND:New(_group,"Build crates",topcrates, self._BuildCrates, self, _group, _unit)
|
local buildmenu = MENU_GROUP_COMMAND:New(_group,"Build crates",topcrates, self._BuildCrates, self, _group, _unit)
|
||||||
@@ -3744,7 +3827,7 @@ end
|
|||||||
-- @param #CTLD_CARGO.Enum Type Type of cargo. I.e. VEHICLE or FOB. VEHICLE will move to destination zones when dropped/build, FOB stays put.
|
-- @param #CTLD_CARGO.Enum Type Type of cargo. I.e. VEHICLE or FOB. VEHICLE will move to destination zones when dropped/build, FOB stays put.
|
||||||
-- @param #number NoCrates Number of crates needed to build this cargo.
|
-- @param #number NoCrates Number of crates needed to build this cargo.
|
||||||
-- @param #number PerCrateMass Mass in kg of each crate
|
-- @param #number PerCrateMass Mass in kg of each crate
|
||||||
-- @param #number Stock Number of groups in stock. Nil for unlimited.
|
-- @param #number Stock Number of buildable groups in stock. Nil for unlimited.
|
||||||
-- @param #string SubCategory Name of sub-category (optional).
|
-- @param #string SubCategory Name of sub-category (optional).
|
||||||
function CTLD:AddCratesCargo(Name,Templates,Type,NoCrates,PerCrateMass,Stock,SubCategory)
|
function CTLD:AddCratesCargo(Name,Templates,Type,NoCrates,PerCrateMass,Stock,SubCategory)
|
||||||
self:T(self.lid .. " AddCratesCargo")
|
self:T(self.lid .. " AddCratesCargo")
|
||||||
|
|||||||
@@ -141,14 +141,14 @@
|
|||||||
-- -- **Note** If you need different tanker types, i.e. Boom and Drogue, set them up at different AirWings!
|
-- -- **Note** If you need different tanker types, i.e. Boom and Drogue, set them up at different AirWings!
|
||||||
-- -- Add a tanker point
|
-- -- Add a tanker point
|
||||||
-- mywing:AddPatrolPointTanker(AIRBASE.Caucasus.Kutaisi,ZONE:FindByName("Blue Zone Tanker"):GetCoordinate(),20000,280,270,50)
|
-- mywing:AddPatrolPointTanker(AIRBASE.Caucasus.Kutaisi,ZONE:FindByName("Blue Zone Tanker"):GetCoordinate(),20000,280,270,50)
|
||||||
-- -- Add an AWACS squad - Radio 251 AM, TACAN 51Y
|
-- -- Add a tanker squad - Radio 251 AM, TACAN 51Y
|
||||||
-- mywing:AddTankerSquadron("Blue Tanker","Tanker Ops Kutaisi",AIRBASE.Caucasus.Kutaisi,20,AI.Skill.EXCELLENT,602,nil,251,radio.modulation.AM,51)
|
-- mywing:AddTankerSquadron("Blue Tanker","Tanker Ops Kutaisi",AIRBASE.Caucasus.Kutaisi,20,AI.Skill.EXCELLENT,602,nil,251,radio.modulation.AM,51)
|
||||||
--
|
--
|
||||||
-- ### Add an AWACS (optional)
|
-- ### Add an AWACS (optional)
|
||||||
--
|
--
|
||||||
-- -- Add an AWACS point
|
-- -- Add an AWACS point
|
||||||
-- mywing:AddPatrolPointAwacs(AIRBASE.Caucasus.Kutaisi,ZONE:FindByName("Blue Zone AWACS"):GetCoordinate(),25000,300,270,50)
|
-- mywing:AddPatrolPointAwacs(AIRBASE.Caucasus.Kutaisi,ZONE:FindByName("Blue Zone AWACS"):GetCoordinate(),25000,300,270,50)
|
||||||
-- -- Add a tanker squad - Radio 251 AM, TACAN 51Y
|
-- -- Add an AWACS squad - Radio 251 AM, TACAN 51Y
|
||||||
-- mywing:AddAWACSSquadron("Blue AWACS","AWACS Ops Kutaisi",AIRBASE.Caucasus.Kutaisi,20,AI.Skill.AVERAGE,702,nil,271,radio.modulation.AM)
|
-- mywing:AddAWACSSquadron("Blue AWACS","AWACS Ops Kutaisi",AIRBASE.Caucasus.Kutaisi,20,AI.Skill.AVERAGE,702,nil,271,radio.modulation.AM)
|
||||||
--
|
--
|
||||||
-- # Fine-Tuning
|
-- # Fine-Tuning
|
||||||
|
|||||||
@@ -4957,7 +4957,7 @@ end
|
|||||||
-- Misc Functions
|
-- Misc Functions
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
--- Add parking guard in front of a parking aircraft.
|
--- [INTERNAL] Add parking guard in front of a parking aircraft - delayed for MP.
|
||||||
-- @param #FLIGHTCONTROL self
|
-- @param #FLIGHTCONTROL self
|
||||||
-- @param Wrapper.Unit#UNIT unit The aircraft.
|
-- @param Wrapper.Unit#UNIT unit The aircraft.
|
||||||
function FLIGHTCONTROL:SpawnParkingGuard(unit)
|
function FLIGHTCONTROL:SpawnParkingGuard(unit)
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
-- @field #table filterCategoryGroup Filter for group categories.
|
-- @field #table filterCategoryGroup Filter for group categories.
|
||||||
-- @field Core.Set#SET_ZONE acceptzoneset Set of accept zones. If defined, only contacts in these zones are considered.
|
-- @field Core.Set#SET_ZONE acceptzoneset Set of accept zones. If defined, only contacts in these zones are considered.
|
||||||
-- @field Core.Set#SET_ZONE rejectzoneset Set of reject zones. Contacts in these zones are not considered, even if they are in accept zones.
|
-- @field Core.Set#SET_ZONE rejectzoneset Set of reject zones. Contacts in these zones are not considered, even if they are in accept zones.
|
||||||
|
-- @field Core.Set#SET_ZONE conflictzoneset Set of conflict zones. Contacts in these zones are considered, even if they are not in accept zones or if they are in reject zones.
|
||||||
-- @field #table Contacts Table of detected items.
|
-- @field #table Contacts Table of detected items.
|
||||||
-- @field #table ContactsLost Table of lost detected items.
|
-- @field #table ContactsLost Table of lost detected items.
|
||||||
-- @field #table ContactsUnknown Table of new detected items.
|
-- @field #table ContactsUnknown Table of new detected items.
|
||||||
@@ -159,13 +160,12 @@ INTEL.Ctype={
|
|||||||
|
|
||||||
--- INTEL class version.
|
--- INTEL class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
INTEL.version="0.3.5"
|
INTEL.version="0.3.6"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- ToDo list
|
-- ToDo list
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
-- TODO: Make forget times user input. Currently these are hard coded.
|
|
||||||
-- TODO: Add min cluster size. Only create new clusters if they have a certain group size.
|
-- TODO: Add min cluster size. Only create new clusters if they have a certain group size.
|
||||||
-- TODO: process detected set asynchroniously for better performance.
|
-- TODO: process detected set asynchroniously for better performance.
|
||||||
-- DONE: Add statics.
|
-- DONE: Add statics.
|
||||||
@@ -266,6 +266,7 @@ function INTEL:New(DetectionSet, Coalition, Alias)
|
|||||||
self:SetForgetTime()
|
self:SetForgetTime()
|
||||||
self:SetAcceptZones()
|
self:SetAcceptZones()
|
||||||
self:SetRejectZones()
|
self:SetRejectZones()
|
||||||
|
self:SetConflictZones()
|
||||||
|
|
||||||
------------------------
|
------------------------
|
||||||
--- Pseudo Functions ---
|
--- Pseudo Functions ---
|
||||||
@@ -416,7 +417,7 @@ function INTEL:RemoveAcceptZone(AcceptZone)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Set reject zones. Contacts detected in this/these zone(s) are rejected and not reported by the detection.
|
--- Set reject zones. Contacts detected in this/these zone(s) are rejected and not reported by the detection.
|
||||||
-- Note that reject zones overrule accept zones, i.e. if a unit is inside and accept zone and inside a reject zone, it is rejected.
|
-- Note that reject zones overrule accept zones, i.e. if a unit is inside an accept zone and inside a reject zone, it is rejected.
|
||||||
-- @param #INTEL self
|
-- @param #INTEL self
|
||||||
-- @param Core.Set#SET_ZONE RejectZoneSet Set of reject zone(s).
|
-- @param Core.Set#SET_ZONE RejectZoneSet Set of reject zone(s).
|
||||||
-- @return #INTEL self
|
-- @return #INTEL self
|
||||||
@@ -426,7 +427,7 @@ function INTEL:SetRejectZones(RejectZoneSet)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Add a reject zone. Contacts detected in this zone are rejected and not reported by the detection.
|
--- Add a reject zone. Contacts detected in this zone are rejected and not reported by the detection.
|
||||||
-- Note that reject zones overrule accept zones, i.e. if a unit is inside and accept zone and inside a reject zone, it is rejected.
|
-- Note that reject zones overrule accept zones, i.e. if a unit is inside an accept zone and inside a reject zone, it is rejected.
|
||||||
-- @param #INTEL self
|
-- @param #INTEL self
|
||||||
-- @param Core.Zone#ZONE RejectZone Add a zone to the reject zone set.
|
-- @param Core.Zone#ZONE RejectZone Add a zone to the reject zone set.
|
||||||
-- @return #INTEL self
|
-- @return #INTEL self
|
||||||
@@ -444,6 +445,36 @@ function INTEL:RemoveRejectZone(RejectZone)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Set conflict zones. Contacts detected in this/these zone(s) are reported by the detection.
|
||||||
|
-- Note that conflict zones overrule all other zones, i.e. if a unit is outside of an accept zone and inside a reject zone, it is still reported if inside a conflict zone.
|
||||||
|
-- @param #INTEL self
|
||||||
|
-- @param Core.Set#SET_ZONE ConflictZoneSet Set of conflict zone(s).
|
||||||
|
-- @return #INTEL self
|
||||||
|
function INTEL:SetConflictZones(ConflictZoneSet)
|
||||||
|
self.conflictzoneset=ConflictZoneSet or SET_ZONE:New()
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Add a conflict zone. Contacts detected in this zone are conflicted and not reported by the detection.
|
||||||
|
-- Note that conflict zones overrule all other zones, i.e. if a unit is outside of an accept zone and inside a reject zone, it is still reported if inside a conflict zone.
|
||||||
|
-- @param #INTEL self
|
||||||
|
-- @param Core.Zone#ZONE ConflictZone Add a zone to the conflict zone set.
|
||||||
|
-- @return #INTEL self
|
||||||
|
function INTEL:AddConflictZone(ConflictZone)
|
||||||
|
self.conflictzoneset:AddZone(ConflictZone)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Remove a conflict zone from the conflict zone set.
|
||||||
|
-- Note that conflict zones overrule all other zones, i.e. if a unit is outside of an accept zone and inside a reject zone, it is still reported if inside a conflict zone.
|
||||||
|
-- @param #INTEL self
|
||||||
|
-- @param Core.Zone#ZONE ConflictZone Remove a zone from the conflict zone set.
|
||||||
|
-- @return #INTEL self
|
||||||
|
function INTEL:RemoveConflictZone(ConflictZone)
|
||||||
|
self.conflictzoneset:Remove(ConflictZone:GetName(), true)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- **OBSOLETE, will be removed in next version!** Set forget contacts time interval.
|
--- **OBSOLETE, will be removed in next version!** Set forget contacts time interval.
|
||||||
-- Previously known contacts that are not detected any more, are "lost" after this time.
|
-- Previously known contacts that are not detected any more, are "lost" after this time.
|
||||||
-- This avoids fast oscillations between a contact being detected and undetected.
|
-- This avoids fast oscillations between a contact being detected and undetected.
|
||||||
@@ -481,6 +512,33 @@ function INTEL:SetFilterCategory(Categories)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Method to make the radar detection less accurate, e.g. for WWII scenarios.
|
||||||
|
-- @param #INTEL self
|
||||||
|
-- @param #number minheight Minimum flight height to be detected, in meters AGL (above ground)
|
||||||
|
-- @param #number thresheight Threshold to escape the radar if flying below minheight, defaults to 90 (90% escape chance)
|
||||||
|
-- @param #number thresblur Threshold to be detected by the radar overall, defaults to 85 (85% chance to be found)
|
||||||
|
-- @param #number closing Closing-in in km - the limit of km from which on it becomes increasingly difficult to escape radar detection if flying towards the radar position. Should be about 1/3 of the radar detection radius in kilometers, defaults to 20.
|
||||||
|
-- @return #INTEL self
|
||||||
|
function INTEL:SetRadarBlur(minheight,thresheight,thresblur,closing)
|
||||||
|
self.RadarBlur = true
|
||||||
|
self.RadarBlurMinHeight = minheight or 250 -- meters
|
||||||
|
self.RadarBlurThresHeight = thresheight or 90 -- 10% chance to find a low flying group
|
||||||
|
self.RadarBlurThresBlur = thresblur or 85 -- 25% chance to escape the radar overall
|
||||||
|
self.RadarBlurClosing = closing or 20 -- 20km
|
||||||
|
self.RadarBlurClosingSquare = self.RadarBlurClosing * self.RadarBlurClosing
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set the accept range in kilometers from each of the recce. Only object closer than this range will be detected.
|
||||||
|
-- @param #INTEL self
|
||||||
|
-- @param #number Range Range in kilometers
|
||||||
|
-- @return #INTEL self
|
||||||
|
function INTEL:SetAcceptRange(Range)
|
||||||
|
self.RadarAcceptRange = true
|
||||||
|
self.RadarAcceptRangeKilometers = Range or 75
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- Filter group categories. Valid categories are:
|
--- Filter group categories. Valid categories are:
|
||||||
--
|
--
|
||||||
-- * Group.Category.AIRPLANE
|
-- * Group.Category.AIRPLANE
|
||||||
@@ -781,6 +839,18 @@ function INTEL:UpdateIntel()
|
|||||||
for unitname,_unit in pairs(DetectedUnits) do
|
for unitname,_unit in pairs(DetectedUnits) do
|
||||||
local unit=_unit --Wrapper.Unit#UNIT
|
local unit=_unit --Wrapper.Unit#UNIT
|
||||||
|
|
||||||
|
local inconflictzone=false
|
||||||
|
-- Check if unit is in any of the conflict zones.
|
||||||
|
if self.conflictzoneset:Count()>0 then
|
||||||
|
for _,_zone in pairs(self.conflictzoneset.Set) do
|
||||||
|
local zone=_zone --Core.Zone#ZONE
|
||||||
|
if unit:IsInZone(zone) then
|
||||||
|
inconflictzone=true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- Check if unit is in any of the accept zones.
|
-- Check if unit is in any of the accept zones.
|
||||||
if self.acceptzoneset:Count()>0 then
|
if self.acceptzoneset:Count()>0 then
|
||||||
local inzone=false
|
local inzone=false
|
||||||
@@ -793,7 +863,7 @@ function INTEL:UpdateIntel()
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Unit is not in accept zone ==> remove!
|
-- Unit is not in accept zone ==> remove!
|
||||||
if not inzone then
|
if (not inzone) and (not inconflictzone) then
|
||||||
table.insert(remove, unitname)
|
table.insert(remove, unitname)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -810,7 +880,7 @@ function INTEL:UpdateIntel()
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Unit is inside a reject zone ==> remove!
|
-- Unit is inside a reject zone ==> remove!
|
||||||
if inzone then
|
if inzone and (not inconflictzone) then
|
||||||
table.insert(remove, unitname)
|
table.insert(remove, unitname)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -1037,7 +1107,7 @@ function INTEL:CreateDetectedItems(DetectedGroups, DetectedStatics, RecceDetecti
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- (Internal) Return the detected target groups of the controllable as a @{SET_GROUP}.
|
--- (Internal) Return the detected target groups of the controllable as a @{SET_GROUP}.
|
||||||
-- The optional parametes specify the detection methods that can be applied.
|
-- The optional parameters specify the detection methods that can be applied.
|
||||||
-- If no detection method is given, the detection will use all the available methods by default.
|
-- If no detection method is given, the detection will use all the available methods by default.
|
||||||
-- @param #INTEL self
|
-- @param #INTEL self
|
||||||
-- @param Wrapper.Unit#UNIT Unit The unit detecting.
|
-- @param Wrapper.Unit#UNIT Unit The unit detecting.
|
||||||
@@ -1053,6 +1123,7 @@ function INTEL:GetDetectedUnits(Unit, DetectedUnits, RecceDetecting, DetectVisua
|
|||||||
|
|
||||||
-- Get detected DCS units.
|
-- Get detected DCS units.
|
||||||
local reccename = Unit:GetName()
|
local reccename = Unit:GetName()
|
||||||
|
|
||||||
local detectedtargets=Unit:GetDetectedTargets(DetectVisual, DetectOptical, DetectRadar, DetectIRST, DetectRWR, DetectDLINK)
|
local detectedtargets=Unit:GetDetectedTargets(DetectVisual, DetectOptical, DetectRadar, DetectIRST, DetectRWR, DetectDLINK)
|
||||||
|
|
||||||
for DetectionObjectID, Detection in pairs(detectedtargets or {}) do
|
for DetectionObjectID, Detection in pairs(detectedtargets or {}) do
|
||||||
@@ -1073,9 +1144,45 @@ function INTEL:GetDetectedUnits(Unit, DetectedUnits, RecceDetecting, DetectVisua
|
|||||||
local unit=UNIT:FindByName(name)
|
local unit=UNIT:FindByName(name)
|
||||||
|
|
||||||
if unit and unit:IsAlive() then
|
if unit and unit:IsAlive() then
|
||||||
|
local DetectionAccepted = true
|
||||||
|
|
||||||
|
if self.RadarAcceptRange then
|
||||||
|
local reccecoord = Unit:GetCoordinate()
|
||||||
|
local coord = unit:GetCoordinate()
|
||||||
|
local dist = math.floor(coord:Get2DDistance(reccecoord)/1000) -- km
|
||||||
|
if dist > self.RadarAcceptRangeKilometers then DetectionAccepted = false end
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.RadarBlur then
|
||||||
|
local reccecoord = Unit:GetCoordinate()
|
||||||
|
local coord = unit:GetCoordinate()
|
||||||
|
local dist = math.floor(coord:Get2DDistance(reccecoord)/1000) -- km
|
||||||
|
local AGL = unit:GetAltitude(true)
|
||||||
|
local minheight = self.RadarBlurMinHeight or 250 -- meters
|
||||||
|
local thresheight = self.RadarBlurThresHeight or 90 -- 10% chance to find a low flying group
|
||||||
|
local thresblur = self.RadarBlurThresBlur or 85 -- 25% chance to escape the radar overall
|
||||||
|
--local dist = math.floor(Distance)
|
||||||
|
if dist <= self.RadarBlurClosing then
|
||||||
|
thresheight = (((dist*dist)/self.RadarBlurClosingSquare)*thresheight)
|
||||||
|
thresblur = (((dist*dist)/self.RadarBlurClosingSquare)*thresblur)
|
||||||
|
end
|
||||||
|
local fheight = math.floor(math.random(1,10000)/100)
|
||||||
|
local fblur = math.floor(math.random(1,10000)/100)
|
||||||
|
if fblur > thresblur then DetectionAccepted = false end
|
||||||
|
if AGL <= minheight and fheight < thresheight then DetectionAccepted = false end
|
||||||
|
if self.debug or self.verbose > 1 then
|
||||||
|
MESSAGE:New("Radar Blur",10):ToLogIf(self.debug):ToAllIf(self.verbose>1)
|
||||||
|
MESSAGE:New("Unit "..name.." is at "..math.floor(AGL).."m. Distance "..math.floor(dist).."km.",10):ToLogIf(self.debug):ToAllIf(self.verbose>1)
|
||||||
|
MESSAGE:New(string.format("fheight = %d/%d | fblur = %d/%d",fheight,thresheight,fblur,thresblur),10):ToLogIf(self.debug):ToAllIf(self.verbose>1)
|
||||||
|
MESSAGE:New("Detection Accepted = "..tostring(DetectionAccepted),10):ToLogIf(self.debug):ToAllIf(self.verbose>1)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if DetectionAccepted then
|
||||||
DetectedUnits[name]=unit
|
DetectedUnits[name]=unit
|
||||||
RecceDetecting[name]=reccename
|
RecceDetecting[name]=reccename
|
||||||
self:T(string.format("Unit %s detect by %s", name, reccename))
|
self:T(string.format("Unit %s detect by %s", name, reccename))
|
||||||
|
end
|
||||||
else
|
else
|
||||||
if self.detectStatics then
|
if self.detectStatics then
|
||||||
local static=STATIC:FindByName(name, false)
|
local static=STATIC:FindByName(name, false)
|
||||||
@@ -1093,7 +1200,6 @@ function INTEL:GetDetectedUnits(Unit, DetectedUnits, RecceDetecting, DetectVisua
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -3480,10 +3480,9 @@ function OPSGROUP:RemoveWaypoint(wpindex)
|
|||||||
|
|
||||||
-- Could be that the waypoint we are currently moving to was the LAST waypoint. Then we now passed the final waypoint.
|
-- Could be that the waypoint we are currently moving to was the LAST waypoint. Then we now passed the final waypoint.
|
||||||
if (self.adinfinitum or istemp) then
|
if (self.adinfinitum or istemp) then
|
||||||
self:_PassedFinalWaypoint(false, "Removed PASSED temporary waypoint ")
|
self:_PassedFinalWaypoint(false, "Removed PASSED temporary waypoint")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
@@ -5811,6 +5810,27 @@ function OPSGROUP:onafterMissionDone(From, Event, To, Mission)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if self.legion and self.legionReturn==false and self.waypoints and #self.waypoints==1 then
|
||||||
|
---
|
||||||
|
-- This is the case where a group was send on a mission (which is over now), has no addional
|
||||||
|
-- waypoints or tasks and should NOT return to its legion.
|
||||||
|
-- We create a new waypoint at the current position and let it hold here.
|
||||||
|
---
|
||||||
|
|
||||||
|
local Coordinate=self:GetCoordinate()
|
||||||
|
|
||||||
|
if self.isArmygroup then
|
||||||
|
ARMYGROUP.AddWaypoint(self, Coordinate, 0, nil, nil, false)
|
||||||
|
elseif self.isNavygroup then
|
||||||
|
NAVYGROUP.AddWaypoint(self,Coordinate, 0, nil, nil, false)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Remove original waypoint.
|
||||||
|
self:RemoveWaypoint(1)
|
||||||
|
|
||||||
|
self:_PassedFinalWaypoint(true, "Passed final waypoint as group is done with mission but should NOT return to its legion")
|
||||||
|
end
|
||||||
|
|
||||||
-- Check if group is done.
|
-- Check if group is done.
|
||||||
self:_CheckGroupDone(delay)
|
self:_CheckGroupDone(delay)
|
||||||
|
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ OPSZONE.ZoneType={
|
|||||||
|
|
||||||
--- OPSZONE class version.
|
--- OPSZONE class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
OPSZONE.version="0.6.0"
|
OPSZONE.version="0.6.1"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- ToDo list
|
-- ToDo list
|
||||||
@@ -1277,7 +1277,7 @@ function OPSZONE:EvaluateZone()
|
|||||||
|
|
||||||
if Nblu>0 then
|
if Nblu>0 then
|
||||||
|
|
||||||
if not self:IsAttacked() then
|
if not self:IsAttacked() and self.Tnut>=self.threatlevelCapture then
|
||||||
self:Attacked(coalition.side.BLUE)
|
self:Attacked(coalition.side.BLUE)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1329,7 +1329,7 @@ function OPSZONE:EvaluateZone()
|
|||||||
|
|
||||||
if Nred>0 then
|
if Nred>0 then
|
||||||
|
|
||||||
if not self:IsAttacked() then
|
if not self:IsAttacked() and self.Tnut>=self.threatlevelCapture then
|
||||||
-- Red is attacking blue zone.
|
-- Red is attacking blue zone.
|
||||||
self:Attacked(coalition.side.RED)
|
self:Attacked(coalition.side.RED)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -79,6 +79,7 @@
|
|||||||
-- @field Utilities.FiFo#FIFO TargetCache
|
-- @field Utilities.FiFo#FIFO TargetCache
|
||||||
-- @field #boolean smokeownposition
|
-- @field #boolean smokeownposition
|
||||||
-- @field #table SmokeOwn
|
-- @field #table SmokeOwn
|
||||||
|
-- @field #boolean smokeaveragetargetpos
|
||||||
-- @extends Core.Fsm#FSM
|
-- @extends Core.Fsm#FSM
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -104,7 +105,7 @@ PLAYERRECCE = {
|
|||||||
ClassName = "PLAYERRECCE",
|
ClassName = "PLAYERRECCE",
|
||||||
verbose = true,
|
verbose = true,
|
||||||
lid = nil,
|
lid = nil,
|
||||||
version = "0.0.22",
|
version = "0.1.23",
|
||||||
ViewZone = {},
|
ViewZone = {},
|
||||||
ViewZoneVisual = {},
|
ViewZoneVisual = {},
|
||||||
ViewZoneLaser = {},
|
ViewZoneLaser = {},
|
||||||
@@ -130,8 +131,9 @@ PLAYERRECCE = {
|
|||||||
ReferencePoint = nil,
|
ReferencePoint = nil,
|
||||||
TForget = 600,
|
TForget = 600,
|
||||||
TargetCache = nil,
|
TargetCache = nil,
|
||||||
smokeownposition = true,
|
smokeownposition = false,
|
||||||
SmokeOwn = {},
|
SmokeOwn = {},
|
||||||
|
smokeaveragetargetpos = false,
|
||||||
}
|
}
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -1109,9 +1111,8 @@ function PLAYERRECCE:_SmokeTargets(client,group,playername)
|
|||||||
self:T(self.lid.."_SmokeTargets")
|
self:T(self.lid.."_SmokeTargets")
|
||||||
local cameraset = self:_GetTargetSet(client,true) -- Core.Set#SET_UNIT
|
local cameraset = self:_GetTargetSet(client,true) -- Core.Set#SET_UNIT
|
||||||
local visualset = self:_GetTargetSet(client,false) -- Core.Set#SET_UNIT
|
local visualset = self:_GetTargetSet(client,false) -- Core.Set#SET_UNIT
|
||||||
cameraset:AddSet(visualset)
|
|
||||||
|
|
||||||
if cameraset:CountAlive() > 0 then
|
if cameraset:CountAlive() > 0 or visualset:CountAlive() > 0 then
|
||||||
self:__TargetsSmoked(-1,client,playername,cameraset)
|
self:__TargetsSmoked(-1,client,playername,cameraset)
|
||||||
else
|
else
|
||||||
return self
|
return self
|
||||||
@@ -1126,29 +1127,31 @@ function PLAYERRECCE:_SmokeTargets(client,group,playername)
|
|||||||
-- laser targer gets extra smoke
|
-- laser targer gets extra smoke
|
||||||
if laser and laser.Target and laser.Target:IsAlive() then
|
if laser and laser.Target and laser.Target:IsAlive() then
|
||||||
laser.Target:GetCoordinate():Smoke(lasersmoke)
|
laser.Target:GetCoordinate():Smoke(lasersmoke)
|
||||||
if cameraset:IsInSet(laser.Target) then
|
|
||||||
cameraset:Remove(laser.Target:GetName(),true)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local coordinate = nil
|
local coord = visualset:GetCoordinate()
|
||||||
local setthreat = 0
|
if coord and self.smokeaveragetargetpos then
|
||||||
-- smoke everything else
|
coord:SetAtLandheight()
|
||||||
if cameraset:CountAlive() > 1 then
|
coord:Smoke(medsmoke)
|
||||||
local coordinate = cameraset:GetCoordinate()
|
else
|
||||||
local setthreat = cameraset:CalculateThreatLevelA2G()
|
-- smoke everything
|
||||||
end
|
for _,_unit in pairs(visualset.Set) do
|
||||||
|
local unit = _unit --Wrapper.Unit#UNIT
|
||||||
if coordinate then
|
if unit and unit:IsAlive() then
|
||||||
|
local coord = unit:GetCoordinate()
|
||||||
|
local threat = unit:GetThreatLevel()
|
||||||
|
if coord then
|
||||||
local color = lowsmoke
|
local color = lowsmoke
|
||||||
if setthreat > 7 then
|
if threat > 7 then
|
||||||
|
color = highsmoke
|
||||||
|
elseif threat > 2 then
|
||||||
color = medsmoke
|
color = medsmoke
|
||||||
elseif setthreat > 2 then
|
|
||||||
color = lowsmoke
|
|
||||||
end
|
end
|
||||||
coordinate:Smoke(color)
|
coord:Smoke(color)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.SmokeOwn[playername] then
|
if self.SmokeOwn[playername] then
|
||||||
local cc = client:GetVec2()
|
local cc = client:GetVec2()
|
||||||
-- don't smoke mid-air
|
-- don't smoke mid-air
|
||||||
@@ -1189,15 +1192,15 @@ function PLAYERRECCE:_FlareTargets(client,group,playername)
|
|||||||
-- smoke everything else
|
-- smoke everything else
|
||||||
for _,_unit in pairs(cameraset.Set) do
|
for _,_unit in pairs(cameraset.Set) do
|
||||||
local unit = _unit --Wrapper.Unit#UNIT
|
local unit = _unit --Wrapper.Unit#UNIT
|
||||||
if unit then
|
if unit and unit:IsAlive() then
|
||||||
local coord = unit:GetCoordinate()
|
local coord = unit:GetCoordinate()
|
||||||
local threat = unit:GetThreatLevel()
|
local threat = unit:GetThreatLevel()
|
||||||
if coord then
|
if coord then
|
||||||
local color = lowsmoke
|
local color = lowsmoke
|
||||||
if threat > 7 then
|
if threat > 7 then
|
||||||
color = medsmoke
|
color = highsmoke
|
||||||
elseif threat > 2 then
|
elseif threat > 2 then
|
||||||
color = lowsmoke
|
color = medsmoke
|
||||||
end
|
end
|
||||||
coord:Flare(color)
|
coord:Flare(color)
|
||||||
end
|
end
|
||||||
@@ -1546,7 +1549,7 @@ end
|
|||||||
-- @param #PLAYERRECCE self
|
-- @param #PLAYERRECCE self
|
||||||
-- @return #PLAYERRECCE self
|
-- @return #PLAYERRECCE self
|
||||||
function PLAYERRECCE:EnableSmokeOwnPosition()
|
function PLAYERRECCE:EnableSmokeOwnPosition()
|
||||||
self:T(self.lid.."ENableSmokeOwnPosition")
|
self:T(self.lid.."EnableSmokeOwnPosition")
|
||||||
self.smokeownposition = true
|
self.smokeownposition = true
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
@@ -1560,6 +1563,24 @@ function PLAYERRECCE:DisableSmokeOwnPosition()
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- [User] Enable smoking of average target positions, instead of all targets visible. Loses smoke per threatlevel -- each is med threat. Default is - smoke all positions.
|
||||||
|
-- @param #PLAYERRECCE self
|
||||||
|
-- @return #PLAYERRECCE self
|
||||||
|
function PLAYERRECCE:EnableSmokeAverageTargetPosition()
|
||||||
|
self:T(self.lid.."ENableSmokeOwnPosition")
|
||||||
|
self.smokeaveragetargetpos = true
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [User] Disable smoking of average target positions, instead of all targets visible. Default is - smoke all positions.
|
||||||
|
-- @param #PLAYERRECCE self
|
||||||
|
-- @return #PLAYERRECCE
|
||||||
|
function PLAYERRECCE:DisableSmokeAverageTargetPosition()
|
||||||
|
self:T(self.lid.."DisableSmokeAverageTargetPosition")
|
||||||
|
self.smokeaveragetargetpos = false
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- [Internal] Get text for text-to-speech.
|
--- [Internal] Get text for text-to-speech.
|
||||||
-- Numbers are spaced out, e.g. "Heading 180" becomes "Heading 1 8 0 ".
|
-- Numbers are spaced out, e.g. "Heading 180" becomes "Heading 1 8 0 ".
|
||||||
-- @param #PLAYERRECCE self
|
-- @param #PLAYERRECCE self
|
||||||
|
|||||||
@@ -526,7 +526,7 @@ function TARGET:IsAlive()
|
|||||||
|
|
||||||
for _,_target in pairs(self.targets) do
|
for _,_target in pairs(self.targets) do
|
||||||
local target=_target --Ops.Target#TARGET.Object
|
local target=_target --Ops.Target#TARGET.Object
|
||||||
if target.Status==TARGET.ObjectStatus.ALIVE then
|
if target.Status~=TARGET.ObjectStatus.DEAD then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -160,24 +160,28 @@ do -- Sound File
|
|||||||
-- @param #string FileName The name of the sound file, e.g. "Hello World.ogg".
|
-- @param #string FileName The name of the sound file, e.g. "Hello World.ogg".
|
||||||
-- @param #string Path The path of the directory, where the sound file is located. Default is "l10n/DEFAULT/" within the miz file.
|
-- @param #string Path The path of the directory, where the sound file is located. Default is "l10n/DEFAULT/" within the miz file.
|
||||||
-- @param #number Duration Duration in seconds, how long it takes to play the sound file. Default is 3 seconds.
|
-- @param #number Duration Duration in seconds, how long it takes to play the sound file. Default is 3 seconds.
|
||||||
|
-- @param #bolean UseSrs Set if SRS should be used to play this file. Default is false.
|
||||||
-- @return #SOUNDFILE self
|
-- @return #SOUNDFILE self
|
||||||
function SOUNDFILE:New(FileName, Path, Duration)
|
function SOUNDFILE:New(FileName, Path, Duration, UseSrs)
|
||||||
|
|
||||||
-- Inherit BASE.
|
-- Inherit BASE.
|
||||||
local self=BASE:Inherit(self, BASE:New()) -- #SOUNDFILE
|
local self=BASE:Inherit(self, BASE:New()) -- #SOUNDFILE
|
||||||
|
|
||||||
|
-- Debug info:
|
||||||
|
self:F( {FileName, Path, Duration, UseSrs} )
|
||||||
|
|
||||||
-- Set file name.
|
-- Set file name.
|
||||||
self:SetFileName(FileName)
|
self:SetFileName(FileName)
|
||||||
|
|
||||||
|
-- Set if SRS should be used to play this file
|
||||||
|
self:SetPlayWithSRS(UseSrs or false)
|
||||||
|
|
||||||
-- Set path.
|
-- Set path.
|
||||||
self:SetPath(Path)
|
self:SetPath(Path)
|
||||||
|
|
||||||
-- Set duration.
|
-- Set duration.
|
||||||
self:SetDuration(Duration)
|
self:SetDuration(Duration)
|
||||||
|
|
||||||
-- Debug info:
|
|
||||||
self:T(string.format("New SOUNDFILE: file name=%s, path=%s", self.filename, self.path))
|
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -186,12 +190,17 @@ do -- Sound File
|
|||||||
-- @param #string Path Path to the directory, where the sound file is located. In case this is nil, it defaults to the DCS mission temp directory.
|
-- @param #string Path Path to the directory, where the sound file is located. In case this is nil, it defaults to the DCS mission temp directory.
|
||||||
-- @return #SOUNDFILE self
|
-- @return #SOUNDFILE self
|
||||||
function SOUNDFILE:SetPath(Path)
|
function SOUNDFILE:SetPath(Path)
|
||||||
|
self:F( {Path} )
|
||||||
|
|
||||||
-- Init path.
|
-- Init path.
|
||||||
self.path=Path or "l10n/DEFAULT/"
|
if not Path then
|
||||||
|
if self.useSRS then -- use path to mission temp dir
|
||||||
if not Path and self.useSRS then -- use path to mission temp dir
|
self.path = lfs.tempdir() .. "Mission\\l10n\\DEFAULT"
|
||||||
self.path = os.getenv('TMP') .. "\\DCS\\Mission\\l10n\\DEFAULT"
|
else -- use internal path in miz file
|
||||||
|
self.path="l10n/DEFAULT/"
|
||||||
|
end
|
||||||
|
else
|
||||||
|
self.path = Path
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Remove (back)slashes.
|
-- Remove (back)slashes.
|
||||||
@@ -204,6 +213,8 @@ do -- Sound File
|
|||||||
-- Append slash.
|
-- Append slash.
|
||||||
self.path=self.path.."/"
|
self.path=self.path.."/"
|
||||||
|
|
||||||
|
self:T("self.path=".. self.path)
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -264,11 +275,13 @@ do -- Sound File
|
|||||||
-- @param #boolean Switch If true or nil, use SRS. If false, use DCS transmission.
|
-- @param #boolean Switch If true or nil, use SRS. If false, use DCS transmission.
|
||||||
-- @return #SOUNDFILE self
|
-- @return #SOUNDFILE self
|
||||||
function SOUNDFILE:SetPlayWithSRS(Switch)
|
function SOUNDFILE:SetPlayWithSRS(Switch)
|
||||||
|
self:F( {Switch} )
|
||||||
if Switch==true or Switch==nil then
|
if Switch==true or Switch==nil then
|
||||||
self.useSRS=true
|
self.useSRS=true
|
||||||
else
|
else
|
||||||
self.useSRS=false
|
self.useSRS=false
|
||||||
end
|
end
|
||||||
|
self:T("self.useSRS=".. tostring(self.useSRS))
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -159,4 +159,24 @@ do -- UserSound
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Play the usersound to the given @{Wrapper.Client}.
|
||||||
|
-- @param #USERSOUND self
|
||||||
|
-- @param Wrapper.Client#CLIENT The @{Wrapper.Client} to play the usersound to.
|
||||||
|
-- @param #number Delay (Optional) Delay in seconds, before the sound is played. Default 0.
|
||||||
|
-- @return #USERSOUND The usersound instance.
|
||||||
|
-- @usage
|
||||||
|
-- local BlueVictory = USERSOUND:New( "BlueVictory.ogg" )
|
||||||
|
-- local PlayerUnit = CLIENT:FindByPlayerName("Karl Heinz")-- Search for the active client with playername "Karl Heinz", a human player.
|
||||||
|
-- BlueVictory:ToClient( PlayerUnit ) -- Play the victory sound to the player unit.
|
||||||
|
--
|
||||||
|
function USERSOUND:ToClient( Client, Delay )
|
||||||
|
Delay=Delay or 0
|
||||||
|
if Delay>0 then
|
||||||
|
SCHEDULER:New(nil, USERSOUND.ToClient,{self, Client}, Delay)
|
||||||
|
else
|
||||||
|
trigger.action.outSoundForUnit( Client:GetID(), self.UserSoundFileName )
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
end
|
end
|
||||||
@@ -523,6 +523,7 @@ ENUMS.ReportingName =
|
|||||||
Hawkeye = "E-2D",
|
Hawkeye = "E-2D",
|
||||||
Sentry = "E-3A",
|
Sentry = "E-3A",
|
||||||
Stratotanker = "KC-135",
|
Stratotanker = "KC-135",
|
||||||
|
Gasstation = "KC-135MPRS",
|
||||||
Extender = "KC-10",
|
Extender = "KC-10",
|
||||||
Orion = "P-3C",
|
Orion = "P-3C",
|
||||||
Viking = "S-3B",
|
Viking = "S-3B",
|
||||||
|
|||||||
@@ -443,22 +443,35 @@ end
|
|||||||
|
|
||||||
--- Print a table to log in a nice format
|
--- Print a table to log in a nice format
|
||||||
-- @param #table table The table to print
|
-- @param #table table The table to print
|
||||||
-- @param #number indent Number of idents
|
-- @param #number indent Number of indents
|
||||||
|
-- @return #string text Text created on the fly of the log output
|
||||||
function UTILS.PrintTableToLog(table, indent)
|
function UTILS.PrintTableToLog(table, indent)
|
||||||
|
local text = "\n"
|
||||||
if not table then
|
if not table then
|
||||||
env.warning("No table passed!")
|
env.warning("No table passed!")
|
||||||
return
|
return nil
|
||||||
end
|
end
|
||||||
if not indent then indent = 0 end
|
if not indent then indent = 0 end
|
||||||
for k, v in pairs(table) do
|
for k, v in pairs(table) do
|
||||||
|
if string.find(k," ") then k='"'..k..'"'end
|
||||||
if type(v) == "table" then
|
if type(v) == "table" then
|
||||||
env.info(string.rep(" ", indent) .. tostring(k) .. " = {")
|
env.info(string.rep(" ", indent) .. tostring(k) .. " = {")
|
||||||
UTILS.PrintTableToLog(v, indent + 1)
|
text = text ..string.rep(" ", indent) .. tostring(k) .. " = {\n"
|
||||||
env.info(string.rep(" ", indent) .. "}")
|
text = text .. tostring(UTILS.PrintTableToLog(v, indent + 1)).."\n"
|
||||||
|
env.info(string.rep(" ", indent) .. "},")
|
||||||
|
text = text .. string.rep(" ", indent) .. "},\n"
|
||||||
else
|
else
|
||||||
env.info(string.rep(" ", indent) .. tostring(k) .. " = " .. tostring(v))
|
local value
|
||||||
|
if tostring(v) == "true" or tostring(v) == "false" or tonumber(v) ~= nil then
|
||||||
|
value=v
|
||||||
|
else
|
||||||
|
value = '"'..tostring(v)..'"'
|
||||||
|
end
|
||||||
|
env.info(string.rep(" ", indent) .. tostring(k) .. " = " .. tostring(value)..",\n")
|
||||||
|
text = text .. string.rep(" ", indent) .. tostring(k) .. " = " .. tostring(value)..",\n"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
return text
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Returns table in a easy readable string representation.
|
--- Returns table in a easy readable string representation.
|
||||||
@@ -1078,9 +1091,9 @@ function UTILS.BeaufortScale(speed)
|
|||||||
return bn,bd
|
return bn,bd
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Split string at seperators. C.f. [split-string-in-lua](http://stackoverflow.com/questions/1426954/split-string-in-lua).
|
--- Split string at separators. C.f. [split-string-in-lua](http://stackoverflow.com/questions/1426954/split-string-in-lua).
|
||||||
-- @param #string str Sting to split.
|
-- @param #string str Sting to split.
|
||||||
-- @param #string sep Speparator for split.
|
-- @param #string sep Separator for split.
|
||||||
-- @return #table Split text.
|
-- @return #table Split text.
|
||||||
function UTILS.Split(str, sep)
|
function UTILS.Split(str, sep)
|
||||||
local result = {}
|
local result = {}
|
||||||
@@ -2208,17 +2221,17 @@ function UTILS.IsLoadingDoorOpen( unit_name )
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
if string.find(type_name, "Bell-47") then -- bell aint got no doors so always ready to load injured soldiers
|
if type_name == "Bell-47" then -- bell aint got no doors so always ready to load injured soldiers
|
||||||
BASE:T(unit_name .. " door is open")
|
BASE:T(unit_name .. " door is open")
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
if string.find(type_name, "UH-60L") and (unit:getDrawArgumentValue(401) == 1 or unit:getDrawArgumentValue(402) == 1) then
|
if type_name == "UH-60L" and (unit:getDrawArgumentValue(401) == 1 or unit:getDrawArgumentValue(402) == 1) then
|
||||||
BASE:T(unit_name .. " cargo door is open")
|
BASE:T(unit_name .. " cargo door is open")
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
if string.find(type_name, "UH-60L" ) and (unit:getDrawArgumentValue(38) == 1 or unit:getDrawArgumentValue(400) == 1 ) then
|
if type_name == "UH-60L" and (unit:getDrawArgumentValue(38) > 0 or unit:getDrawArgumentValue(400) == 1 ) then
|
||||||
BASE:T(unit_name .. " front door(s) are open")
|
BASE:T(unit_name .. " front door(s) are open")
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -2937,7 +2937,7 @@ function CONTROLLABLE:CopyRoute( Begin, End, Randomize, Radius )
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Return the detected targets of the controllable.
|
--- Return the detected targets of the controllable.
|
||||||
-- The optional parametes specify the detection methods that can be applied.
|
-- The optional parameters specify the detection methods that can be applied.
|
||||||
-- If no detection method is given, the detection will use all the available methods by default.
|
-- If no detection method is given, the detection will use all the available methods by default.
|
||||||
-- @param #CONTROLLABLE self
|
-- @param #CONTROLLABLE self
|
||||||
-- @param #boolean DetectVisual (optional)
|
-- @param #boolean DetectVisual (optional)
|
||||||
@@ -3772,54 +3772,66 @@ function CONTROLLABLE:OptionProhibitAfterburner( Prohibit )
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Defines the usage of Electronic Counter Measures by airborne forces. Disables the ability for AI to use their ECM.
|
--- [Air] Defines the usage of Electronic Counter Measures by airborne forces.
|
||||||
|
-- @param #CONTROLLABLE self
|
||||||
|
-- @param #number ECMvalue Can be - 0=Never on, 1=if locked by radar, 2=if detected by radar, 3=always on, defaults to 1
|
||||||
|
-- @return #CONTROLLABLE self
|
||||||
|
function CONTROLLABLE:OptionECM( ECMvalue )
|
||||||
|
self:F2( { self.ControllableName } )
|
||||||
|
|
||||||
|
local DCSControllable = self:GetDCSObject()
|
||||||
|
if DCSControllable then
|
||||||
|
local Controller = self:_GetController()
|
||||||
|
|
||||||
|
if self:IsAir() then
|
||||||
|
Controller:setOption( AI.Option.Air.id.ECM_USING, ECMvalue or 1 )
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [Air] Defines the usage of Electronic Counter Measures by airborne forces. Disables the ability for AI to use their ECM.
|
||||||
-- @param #CONTROLLABLE self
|
-- @param #CONTROLLABLE self
|
||||||
-- @return #CONTROLLABLE self
|
-- @return #CONTROLLABLE self
|
||||||
function CONTROLLABLE:OptionECM_Never()
|
function CONTROLLABLE:OptionECM_Never()
|
||||||
self:F2( { self.ControllableName } )
|
self:F2( { self.ControllableName } )
|
||||||
|
|
||||||
if self:IsAir() then
|
self:OptionECM(0)
|
||||||
self:SetOption( AI.Option.Air.id.ECM_USING, 0 )
|
|
||||||
end
|
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Defines the usage of Electronic Counter Measures by airborne forces. If the AI is actively being locked by an enemy radar they will enable their ECM jammer.
|
--- [Air] Defines the usage of Electronic Counter Measures by airborne forces. If the AI is actively being locked by an enemy radar they will enable their ECM jammer.
|
||||||
-- @param #CONTROLLABLE self
|
-- @param #CONTROLLABLE self
|
||||||
-- @return #CONTROLLABLE self
|
-- @return #CONTROLLABLE self
|
||||||
function CONTROLLABLE:OptionECM_OnlyLockByRadar()
|
function CONTROLLABLE:OptionECM_OnlyLockByRadar()
|
||||||
self:F2( { self.ControllableName } )
|
self:F2( { self.ControllableName } )
|
||||||
|
|
||||||
if self:IsAir() then
|
self:OptionECM(1)
|
||||||
self:SetOption( AI.Option.Air.id.ECM_USING, 1 )
|
|
||||||
end
|
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Defines the usage of Electronic Counter Measures by airborne forces. If the AI is being detected by a radar they will enable their ECM.
|
--- [Air] Defines the usage of Electronic Counter Measures by airborne forces. If the AI is being detected by a radar they will enable their ECM.
|
||||||
-- @param #CONTROLLABLE self
|
-- @param #CONTROLLABLE self
|
||||||
-- @return #CONTROLLABLE self
|
-- @return #CONTROLLABLE self
|
||||||
function CONTROLLABLE:OptionECM_DetectedLockByRadar()
|
function CONTROLLABLE:OptionECM_DetectedLockByRadar()
|
||||||
self:F2( { self.ControllableName } )
|
self:F2( { self.ControllableName } )
|
||||||
|
|
||||||
if self:IsAir() then
|
self:OptionECM(2)
|
||||||
self:SetOption( AI.Option.Air.id.ECM_USING, 2 )
|
|
||||||
end
|
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Defines the usage of Electronic Counter Measures by airborne forces. AI will leave their ECM on all the time.
|
--- [Air] Defines the usage of Electronic Counter Measures by airborne forces. AI will leave their ECM on all the time.
|
||||||
-- @param #CONTROLLABLE self
|
-- @param #CONTROLLABLE self
|
||||||
-- @return #CONTROLLABLE self
|
-- @return #CONTROLLABLE self
|
||||||
function CONTROLLABLE:OptionECM_AlwaysOn()
|
function CONTROLLABLE:OptionECM_AlwaysOn()
|
||||||
self:F2( { self.ControllableName } )
|
self:F2( { self.ControllableName } )
|
||||||
|
|
||||||
if self:IsAir() then
|
self:OptionECM(3)
|
||||||
self:SetOption( AI.Option.Air.id.ECM_USING, 3 )
|
|
||||||
end
|
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
@@ -4013,14 +4025,22 @@ end
|
|||||||
-- @param #boolean onroad If true, route on road (less problems with AI way finding), default true
|
-- @param #boolean onroad If true, route on road (less problems with AI way finding), default true
|
||||||
-- @param #boolean shortcut If true and onroad is set, take a shorter route - if available - off road, default false
|
-- @param #boolean shortcut If true and onroad is set, take a shorter route - if available - off road, default false
|
||||||
-- @param #string formation Formation string as in the mission editor, e.g. "Vee", "Diamond", "Line abreast", etc. Defaults to "Off Road"
|
-- @param #string formation Formation string as in the mission editor, e.g. "Vee", "Diamond", "Line abreast", etc. Defaults to "Off Road"
|
||||||
|
-- @param #boolean onland (optional) If true, try up to 50 times to get a coordinate on land.SurfaceType.LAND. Note - this descriptor value is not reliably implemented on all maps.
|
||||||
-- @return #CONTROLLABLE self
|
-- @return #CONTROLLABLE self
|
||||||
function CONTROLLABLE:RelocateGroundRandomInRadius( speed, radius, onroad, shortcut, formation )
|
function CONTROLLABLE:RelocateGroundRandomInRadius( speed, radius, onroad, shortcut, formation, onland )
|
||||||
self:F2( { self.ControllableName } )
|
self:F2( { self.ControllableName } )
|
||||||
|
|
||||||
local _coord = self:GetCoordinate()
|
local _coord = self:GetCoordinate()
|
||||||
local _radius = radius or 500
|
local _radius = radius or 500
|
||||||
local _speed = speed or 20
|
local _speed = speed or 20
|
||||||
local _tocoord = _coord:GetRandomCoordinateInRadius( _radius, 100 )
|
local _tocoord = _coord:GetRandomCoordinateInRadius( _radius, 100 )
|
||||||
|
if onland then
|
||||||
|
for i=1,50 do
|
||||||
|
local island = _tocoord:GetSurfaceType() == land.SurfaceType.LAND and true or false
|
||||||
|
if island then break end
|
||||||
|
_tocoord = _coord:GetRandomCoordinateInRadius( _radius, 100 )
|
||||||
|
end
|
||||||
|
end
|
||||||
local _onroad = onroad or true
|
local _onroad = onroad or true
|
||||||
local _grptsk = {}
|
local _grptsk = {}
|
||||||
local _candoroad = false
|
local _candoroad = false
|
||||||
|
|||||||
@@ -302,7 +302,7 @@ end
|
|||||||
|
|
||||||
--- Find the first(!) GROUP matching using patterns. Note that this is **a lot** slower than `:FindByName()`!
|
--- Find the first(!) GROUP matching using patterns. Note that this is **a lot** slower than `:FindByName()`!
|
||||||
-- @param #GROUP self
|
-- @param #GROUP self
|
||||||
-- @param #string Pattern The pattern to look for. Refer to [LUA patterns](http://www.easyuo.com/openeuo/wiki/index.php/Lua_Patterns_and_Captures_(Regular_Expressions)) for regular expressions in LUA.
|
-- @param #string Pattern The pattern to look for. Refer to [LUA patterns](http://www.easyuo.com/openeuo/wiki/index.php/Lua_Patterns_and_Captures_\(Regular_Expressions\)) for regular expressions in LUA.
|
||||||
-- @return #GROUP The GROUP.
|
-- @return #GROUP The GROUP.
|
||||||
-- @usage
|
-- @usage
|
||||||
-- -- Find a group with a partial group name
|
-- -- Find a group with a partial group name
|
||||||
@@ -327,7 +327,7 @@ end
|
|||||||
|
|
||||||
--- Find all GROUP objects matching using patterns. Note that this is **a lot** slower than `:FindByName()`!
|
--- Find all GROUP objects matching using patterns. Note that this is **a lot** slower than `:FindByName()`!
|
||||||
-- @param #GROUP self
|
-- @param #GROUP self
|
||||||
-- @param #string Pattern The pattern to look for. Refer to [LUA patterns](http://www.easyuo.com/openeuo/wiki/index.php/Lua_Patterns_and_Captures_(Regular_Expressions)) for regular expressions in LUA.
|
-- @param #string Pattern The pattern to look for. Refer to [LUA patterns](http://www.easyuo.com/openeuo/wiki/index.php/Lua_Patterns_and_Captures_\(Regular_Expressions\)) for regular expressions in LUA.
|
||||||
-- @return #table Groups Table of matching #GROUP objects found
|
-- @return #table Groups Table of matching #GROUP objects found
|
||||||
-- @usage
|
-- @usage
|
||||||
-- -- Find all group with a partial group name
|
-- -- Find all group with a partial group name
|
||||||
@@ -1177,6 +1177,7 @@ function GROUP:GetAverageCoordinate()
|
|||||||
local coord = COORDINATE:NewFromVec3(vec3)
|
local coord = COORDINATE:NewFromVec3(vec3)
|
||||||
local Heading = self:GetHeading()
|
local Heading = self:GetHeading()
|
||||||
coord.Heading = Heading
|
coord.Heading = Heading
|
||||||
|
return coord
|
||||||
else
|
else
|
||||||
BASE:E( { "Cannot GetAverageCoordinate", Group = self, Alive = self:IsAlive() } )
|
BASE:E( { "Cannot GetAverageCoordinate", Group = self, Alive = self:IsAlive() } )
|
||||||
return nil
|
return nil
|
||||||
@@ -2782,7 +2783,7 @@ end
|
|||||||
|
|
||||||
--- Switch on/off invisible flag for the group.
|
--- Switch on/off invisible flag for the group.
|
||||||
-- @param #GROUP self
|
-- @param #GROUP self
|
||||||
-- @param #boolean switch If true, emission is enabled. If false, emission is disabled.
|
-- @param #boolean switch If true, Invisible is enabled. If false, Invisible is disabled.
|
||||||
-- @return #GROUP self
|
-- @return #GROUP self
|
||||||
function GROUP:SetCommandInvisible(switch)
|
function GROUP:SetCommandInvisible(switch)
|
||||||
self:F2( self.GroupName )
|
self:F2( self.GroupName )
|
||||||
@@ -2796,7 +2797,7 @@ end
|
|||||||
|
|
||||||
--- Switch on/off immortal flag for the group.
|
--- Switch on/off immortal flag for the group.
|
||||||
-- @param #GROUP self
|
-- @param #GROUP self
|
||||||
-- @param #boolean switch If true, emission is enabled. If false, emission is disabled.
|
-- @param #boolean switch If true, Immortal is enabled. If false, Immortal is disabled.
|
||||||
-- @return #GROUP self
|
-- @return #GROUP self
|
||||||
function GROUP:SetCommandImmortal(switch)
|
function GROUP:SetCommandImmortal(switch)
|
||||||
self:F2( self.GroupName )
|
self:F2( self.GroupName )
|
||||||
@@ -3002,3 +3003,36 @@ function GROUP:GetGroupSTN()
|
|||||||
return tSTN,text
|
return tSTN,text
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- [GROUND] Determine if a GROUP is a SAM unit, i.e. has radar or optical tracker and is no mobile AAA.
|
||||||
|
-- @param #GROUP self
|
||||||
|
-- @return #boolean IsSAM True if SAM, else false
|
||||||
|
function GROUP:IsSAM()
|
||||||
|
local issam = false
|
||||||
|
local units = self:GetUnits()
|
||||||
|
for _,_unit in pairs(units or {}) do
|
||||||
|
local unit = _unit -- Wrapper.Unit#UNIT
|
||||||
|
if unit:HasSEAD() and unit:IsGround() and (not unit:HasAttribute("Mobile AAA")) then
|
||||||
|
issam = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return issam
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [GROUND] Determine if a GROUP has a AAA unit, i.e. has no radar or optical tracker but the AAA = true or the "Mobile AAA" = true attribute.
|
||||||
|
-- @param #GROUP self
|
||||||
|
-- @return #boolean IsSAM True if AAA, else false
|
||||||
|
function GROUP:IsAAA()
|
||||||
|
local issam = false
|
||||||
|
local units = self:GetUnits()
|
||||||
|
for _,_unit in pairs(units or {}) do
|
||||||
|
local unit = _unit -- Wrapper.Unit#UNIT
|
||||||
|
local desc = unit:GetDesc() or {}
|
||||||
|
local attr = desc.attributes or {}
|
||||||
|
if unit:HasSEAD() then return false end
|
||||||
|
if attr["AAA"] or attr["SAM related"] then
|
||||||
|
issam = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return issam
|
||||||
|
end
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ end
|
|||||||
|
|
||||||
--- Find the first(!) UNIT matching using patterns. Note that this is **a lot** slower than `:FindByName()`!
|
--- Find the first(!) UNIT matching using patterns. Note that this is **a lot** slower than `:FindByName()`!
|
||||||
-- @param #UNIT self
|
-- @param #UNIT self
|
||||||
-- @param #string Pattern The pattern to look for. Refer to [LUA patterns](http://www.easyuo.com/openeuo/wiki/index.php/Lua_Patterns_and_Captures_(Regular_Expressions)) for regular expressions in LUA.
|
-- @param #string Pattern The pattern to look for. Refer to [LUA patterns](http://www.easyuo.com/openeuo/wiki/index.php/Lua_Patterns_and_Captures_\(Regular_Expressions\)) for regular expressions in LUA.
|
||||||
-- @return #UNIT The UNIT.
|
-- @return #UNIT The UNIT.
|
||||||
-- @usage
|
-- @usage
|
||||||
-- -- Find a group with a partial group name
|
-- -- Find a group with a partial group name
|
||||||
@@ -189,7 +189,7 @@ end
|
|||||||
|
|
||||||
--- Find all UNIT objects matching using patterns. Note that this is **a lot** slower than `:FindByName()`!
|
--- Find all UNIT objects matching using patterns. Note that this is **a lot** slower than `:FindByName()`!
|
||||||
-- @param #UNIT self
|
-- @param #UNIT self
|
||||||
-- @param #string Pattern The pattern to look for. Refer to [LUA patterns](http://www.easyuo.com/openeuo/wiki/index.php/Lua_Patterns_and_Captures_(Regular_Expressions)) for regular expressions in LUA.
|
-- @param #string Pattern The pattern to look for. Refer to [LUA patterns](http://www.easyuo.com/openeuo/wiki/index.php/Lua_Patterns_and_Captures_\(Regular_Expressions\)) for regular expressions in LUA.
|
||||||
-- @return #table Units Table of matching #UNIT objects found
|
-- @return #table Units Table of matching #UNIT objects found
|
||||||
-- @usage
|
-- @usage
|
||||||
-- -- Find all group with a partial group name
|
-- -- Find all group with a partial group name
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ Utilities/Profiler.lua
|
|||||||
Utilities/Templates.lua
|
Utilities/Templates.lua
|
||||||
Utilities/STTS.lua
|
Utilities/STTS.lua
|
||||||
Utilities/FiFo.lua
|
Utilities/FiFo.lua
|
||||||
|
Utilities/Socket.lua
|
||||||
|
|
||||||
Core/Base.lua
|
Core/Base.lua
|
||||||
Core/Beacon.lua
|
Core/Beacon.lua
|
||||||
@@ -32,6 +33,8 @@ Core/TextAndSound.lua
|
|||||||
Core/Condition.lua
|
Core/Condition.lua
|
||||||
Core/Pathline.lua
|
Core/Pathline.lua
|
||||||
Core/ClientMenu.lua
|
Core/ClientMenu.lua
|
||||||
|
Core/Astar.lua
|
||||||
|
Core/MarkerOps_Base.lua
|
||||||
|
|
||||||
Wrapper/Object.lua
|
Wrapper/Object.lua
|
||||||
Wrapper/Identifiable.lua
|
Wrapper/Identifiable.lua
|
||||||
@@ -79,6 +82,8 @@ Functional/Shorad.lua
|
|||||||
Functional/Autolase.lua
|
Functional/Autolase.lua
|
||||||
Functional/AICSAR.lua
|
Functional/AICSAR.lua
|
||||||
Functional/AmmoTruck.lua
|
Functional/AmmoTruck.lua
|
||||||
|
Functional/ZoneGoalCargo.lua
|
||||||
|
Functional/Tiresias.lua
|
||||||
|
|
||||||
Ops/Airboss.lua
|
Ops/Airboss.lua
|
||||||
Ops/RecoveryTanker.lua
|
Ops/RecoveryTanker.lua
|
||||||
@@ -107,6 +112,10 @@ Ops/FlightControl.lua
|
|||||||
Ops/PlayerTask.lua
|
Ops/PlayerTask.lua
|
||||||
Ops/PlayerRecce.lua
|
Ops/PlayerRecce.lua
|
||||||
Ops/EasyGCICAP.lua
|
Ops/EasyGCICAP.lua
|
||||||
|
Ops/OpsZone.lua
|
||||||
|
Ops/ArmyGroup.lua
|
||||||
|
Ops/OpsTransport.lua
|
||||||
|
Ops/Target.lua
|
||||||
|
|
||||||
Navigation/Navaid.lua
|
Navigation/Navaid.lua
|
||||||
Navigation/FlightPlan.lua
|
Navigation/FlightPlan.lua
|
||||||
|
|||||||
77
docs/beginner/ask-for-help.md
Normal file
77
docs/beginner/ask-for-help.md
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
---
|
||||||
|
parent: Beginner
|
||||||
|
nav_order: 06
|
||||||
|
---
|
||||||
|
# How to ask for help
|
||||||
|
{: .no_toc }
|
||||||
|
|
||||||
|
1. Table of contents
|
||||||
|
{:toc}
|
||||||
|
|
||||||
|
After you have tried to solve the problem on your own, you can also get help
|
||||||
|
from the community.
|
||||||
|
|
||||||
|
{: .highlight }
|
||||||
|
> But it is important to follow certain rules! Read them below.
|
||||||
|
|
||||||
|
## Communities
|
||||||
|
|
||||||
|
There are two ways to communicate with the community.
|
||||||
|
The fastest way is to use Discord:
|
||||||
|
|
||||||
|
- <https://discord.gg/gj68fm969S>{:target="_blank"}
|
||||||
|
|
||||||
|
But if you don't like Discord, you are able to post in the DCS forum.
|
||||||
|
Check out the MOOSE thread here:
|
||||||
|
|
||||||
|
- <https://forums.eagle.ru/showthread.php?t=138043>
|
||||||
|
|
||||||
|
## How to post requests
|
||||||
|
|
||||||
|
MOOSE is a community project and support is community based.
|
||||||
|
|
||||||
|
Please remember when posting a question:
|
||||||
|
|
||||||
|
- Before posting anything follow the [troubleshooting steps].
|
||||||
|
- **Read your logs**.
|
||||||
|
|
||||||
|
A post should contain the following:
|
||||||
|
|
||||||
|
1. A describtion what you expected to happen and what actually happened.
|
||||||
|
- Do not use vague words this stuff is hard to help with! Be specific.
|
||||||
|
|
||||||
|
2. Describe what happens instead.
|
||||||
|
- The less detail you offer, the less chance you can be helped.
|
||||||
|
- Don’t say it doesn’t work. Or is it broken. Say what it actually does.
|
||||||
|
|
||||||
|
3. Post your code in Discord as formatted code:
|
||||||
|
|
||||||
|
- Wrap a single line of code in backticks \` like this:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
- Multiple lines of code should be posted like this:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
- Post your log lines with the error or warning messages. Format them like this:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
- Some complex problems need the mission (.miz file) also.
|
||||||
|
|
||||||
|
- But post your mission only when requested.
|
||||||
|
- Try to simplify your mission if it is complex!
|
||||||
|
|
||||||
|
There are people in the Discord and in the forum, who spend their free time to
|
||||||
|
help you. <br />
|
||||||
|
It is your responsibility to make their "work" as easy as possible.
|
||||||
|
|
||||||
|
Welcome to MOOSE and good luck!
|
||||||
|
|
||||||
|
## Next step
|
||||||
|
|
||||||
|
Last but not least some [tipps and tricks].
|
||||||
|
|
||||||
|
[troubleshooting steps]: problems.md
|
||||||
|
[tipps and tricks]: tipps-and-tricks.md
|
||||||
58
docs/beginner/demo-missions.md
Normal file
58
docs/beginner/demo-missions.md
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
---
|
||||||
|
parent: Beginner
|
||||||
|
nav_order: 04
|
||||||
|
---
|
||||||
|
|
||||||
|
# Demo missions
|
||||||
|
{: .no_toc }
|
||||||
|
|
||||||
|
1. Table of contents
|
||||||
|
{:toc}
|
||||||
|
|
||||||
|
The best way to get comfortable with a Moose class is to try the demo missions
|
||||||
|
of the class you want to learn. The Moose team created a lot of demo missions
|
||||||
|
for most of the classes.
|
||||||
|
|
||||||
|
## Download demo missions
|
||||||
|
|
||||||
|
Go to the repository [MOOSE_MISSIONS]{:target="_blank"}, search the folder of
|
||||||
|
the class, download the mission (`.miz`) and run them.
|
||||||
|
|
||||||
|
## Read the mission script
|
||||||
|
|
||||||
|
In the same folder a `.lua` file with the same name is placed which is the
|
||||||
|
included mission script. You can watch these mission scripts easily online at
|
||||||
|
GitHub to understand what is happening in the mission.
|
||||||
|
|
||||||
|
## Read documentation
|
||||||
|
|
||||||
|
Next step is to read the [documentation]{:target="_blank"} of the class to
|
||||||
|
understand the code of the demo mission.
|
||||||
|
|
||||||
|
{: .note }
|
||||||
|
> The documentation is quite long and might be confusing for beginners.
|
||||||
|
> Start by looking at the description at the top of the documentation of a
|
||||||
|
> class. It often contains examples and explanations. <br /><br />
|
||||||
|
> Then search for the function names and look at the description of the
|
||||||
|
> functions and its parameters.
|
||||||
|
|
||||||
|
## Make small changes to the script
|
||||||
|
|
||||||
|
Download the `.lua` file, change the parameters to suit your needs in
|
||||||
|
[Notepad++]{:target="_blank"}, add it to the mission and rerun the mission.
|
||||||
|
Observe what happens and adapt the code.
|
||||||
|
|
||||||
|
If you want to use more functions combine them all up.
|
||||||
|
|
||||||
|
{: .note }
|
||||||
|
> But it is wise to do this in small steps. So it is easier to find errors.
|
||||||
|
|
||||||
|
## Next step
|
||||||
|
|
||||||
|
If the mission does not show the expected behaviour take a look at section
|
||||||
|
[problems].
|
||||||
|
|
||||||
|
[MOOSE_MISSIONS]: https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop
|
||||||
|
[documentation]: https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/index.html
|
||||||
|
[Notepad++]: https://notepad-plus-plus.org/downloads/
|
||||||
|
[problems]: problems.md
|
||||||
@@ -4,6 +4,178 @@ nav_order: 03
|
|||||||
---
|
---
|
||||||
|
|
||||||
# Create your own Hello world
|
# Create your own Hello world
|
||||||
|
{: .no_toc }
|
||||||
|
|
||||||
{: .warning }
|
1. Table of contents
|
||||||
> THIS DOCUMENT IS STILL WORK IN PROGRESS!
|
{:toc}
|
||||||
|
|
||||||
|
This page will lead you step by step through the process of creating a mission
|
||||||
|
with MOOSE. This time we include a simple mission script, which sends only
|
||||||
|
a "Hello world" message to all players. But the steps are the same to add
|
||||||
|
another mission script, which will do whatever class(es) you want to use.
|
||||||
|
|
||||||
|
## Create Mission script
|
||||||
|
|
||||||
|
At first we will create the mission script. It is a simple text file and can be
|
||||||
|
changed with a lot of different tools. Theoretically even the Microsoft Notepad
|
||||||
|
editor can be used. But it lacks a lot of features, which helps you to avoid
|
||||||
|
errors.
|
||||||
|
|
||||||
|
For this guide we suggest you to download, install and use [Notepad++]{:target="_blank"}.
|
||||||
|
|
||||||
|
{: .important }
|
||||||
|
> Windows hides filename extensions by default. So when you create a text file
|
||||||
|
> and name it `hello-world.lua` it's name is `hello-world.lua.txt` in reality.
|
||||||
|
> You must activate the display of the file name extension.
|
||||||
|
> Open a `File Explorer`, switch to menu `View` and find the option
|
||||||
|
> `File name extensions` in the section `Show/hide`. Activate it.
|
||||||
|
|
||||||
|
- Open a File Explorer.
|
||||||
|
- Go to the subfolder `Missions` of your [Saved Games folder]{:target="_blank"}.
|
||||||
|
- Create a new text file and name it `hello-world.lua`.
|
||||||
|
- Add the following content and save the file:
|
||||||
|
|
||||||
|
`MESSAGE:New( "Hello World! This messages is printed by MOOSE", 35, "INFO" ):ToAll()`
|
||||||
|
|
||||||
|
## Get Moose
|
||||||
|
|
||||||
|
To download Moose click on the following link:
|
||||||
|
|
||||||
|
- [Moose_.lua from develop branch]{:target="_blank"}
|
||||||
|
|
||||||
|
Press `Ctrl + S` to save the file on your hard disk next to your mission script.
|
||||||
|
|
||||||
|
## Create the mission
|
||||||
|
|
||||||
|
- Start DCS.
|
||||||
|
- In the main menu choose `MISSION EDITOR`.
|
||||||
|
- Click on `create new mission`.
|
||||||
|
- In the dialog `NEW MISSION SETTINGS`:
|
||||||
|
- Choose map `Caucasus`.
|
||||||
|
- In the drop box upper left choose `Modern` as coalition preset.
|
||||||
|
- Click on `OK`.
|
||||||
|
- The mission editor will load with a fresh new and empty mission.
|
||||||
|
- Click on `File` in the menu bar and `SAVE` or Press `Ctrl + S`.
|
||||||
|
- Open `My Missions` and save the file with the name `hello-world.miz`.
|
||||||
|
|
||||||
|
## Add Moose to the mission
|
||||||
|
|
||||||
|
- On the left side activate `TRIGGERS`:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
- On the right side the `TRIGGERS` dialog opens with a lot of options.
|
||||||
|
- Click on `NEW`, choose `4 MISSION START` as **TYPE**.
|
||||||
|
- Give it the `Load MOOSE` as **NAME**.
|
||||||
|
- Leave the **EVENT** option set to `NO EVENT`.
|
||||||
|
- Optional: Choose a color for easy recognition (e.g. yellow).
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
- In the middle part the `CONDITIONS` will be shown.
|
||||||
|
For this trigger we do not configure any conditions.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
{: .important }
|
||||||
|
> The trigger type `4 MISSION START` does not support `CONDITIONS`. <br />
|
||||||
|
> So `CONDITIONS` must left blank when using it. <br />
|
||||||
|
> **If you add a condition the trigger will never be executed!**
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
- On the right side `ACTIONS` is shown.
|
||||||
|
- We need to click on `NEW`.
|
||||||
|
- Choose **ACTION** `Do SCRIPT FILE` and ignore all other actions.
|
||||||
|
- Click **OPEN** and navigate to the downloaded `Moose_.lua` file.
|
||||||
|
- The result should look like this:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Add the mission script
|
||||||
|
|
||||||
|
- Click on `NEW`, choose `1 ONCE` as **TYPE**.
|
||||||
|
- Give it the `Load Mission Script` as **NAME**.
|
||||||
|
- Leave the **EVENT** option set to `NO EVENT`.
|
||||||
|
- Optional: Choose a color for easy recognition (e.g. green).
|
||||||
|
- The result should look like this:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
- Switch to the middle part, the `CONDITIONS` section. <br />
|
||||||
|
For this trigger we add one condition:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
- The combination of `1 ONCE` with `TIME MORE(1)` will ensure, that the mission
|
||||||
|
script is executed 1 second after the mission is started.
|
||||||
|
|
||||||
|
- On the right side under `ACTIONS` you need to add the script:
|
||||||
|
- Click on `NEW`.
|
||||||
|
- Choose **ACTION** `Do SCRIPT FILE`.
|
||||||
|
- Click **OPEN** and navigate to the created `hello-world.lua` file.
|
||||||
|
|
||||||
|
{: .important }
|
||||||
|
> Most important is the fact, that the mission script (`hello-world.lua`)
|
||||||
|
> is executed **after** `Moose_.lua`, because the mission script needs the
|
||||||
|
> classes defined in `Moose_.lua`. And they are only available when `Moose_.lua`
|
||||||
|
> is executed before the mission script.
|
||||||
|
|
||||||
|
## Test the mission
|
||||||
|
|
||||||
|
- Save the mission again.
|
||||||
|
- Click on the green **Fly mission** cirlce on the left tool side bar.
|
||||||
|
- It is an empty mission, so skip `BRIEFING` with `START` and then `FLY`.
|
||||||
|
- You spawn as a spectator. After some seconds you will see this message in
|
||||||
|
the upper right corner:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
This is the same result as already seen in the last chapter, but this time you
|
||||||
|
have create everything on your own.
|
||||||
|
|
||||||
|
{: .note }
|
||||||
|
> You can use this mission as a template for your own missions. So you don't
|
||||||
|
> need to do alle these steps again and again.
|
||||||
|
|
||||||
|
## Update mission script
|
||||||
|
|
||||||
|
- Open the `hello-world.lua` with Notepad++ again.
|
||||||
|
- Change the text a little bit, like `Hello Dude! ...` and save the file.
|
||||||
|
- Run the mission again.
|
||||||
|
- The text will not be changed in the mission. Why?
|
||||||
|
|
||||||
|
{: .important }
|
||||||
|
The mission editor copies the script into the mission file when you add it.
|
||||||
|
Every change on the script file on your hard disk is not recognized by mission
|
||||||
|
editor. **You have to add the file after each change again!**
|
||||||
|
|
||||||
|
There is also another method available to dynamically load mission scripts.
|
||||||
|
But this method has some brawbacks and will be explained in the advanced section.
|
||||||
|
|
||||||
|
Now we add the mission script again:
|
||||||
|
|
||||||
|
- On the left side of the `TRIGGERS` dialog click on `Load Mission Script`.
|
||||||
|
- On the right side under `ACTIONS` you need to add the script again:
|
||||||
|
- Click **OPEN** and navigate to the created `hello-world.lua` file.
|
||||||
|
- Save the mission and test it again.
|
||||||
|
- Now the new text should be shown.
|
||||||
|
|
||||||
|
## Update Moose
|
||||||
|
|
||||||
|
Moose is constantly being developed so that new functionallity is added or
|
||||||
|
existing errors are corrected. Also from time to time changes of the DCS
|
||||||
|
scripting engine comes with a new DCS version. It may therefore be useful or
|
||||||
|
necessary to update Moose.
|
||||||
|
|
||||||
|
- To update Moose download it again and add it again in the same way you did
|
||||||
|
with the mission script in the last step.
|
||||||
|
|
||||||
|
## Next step
|
||||||
|
|
||||||
|
Let's move on to the [demo missions].
|
||||||
|
|
||||||
|
[Notepad++]: https://notepad-plus-plus.org/downloads/
|
||||||
|
[Saved Games folder]: tipps-and-tricks.md#find-the-saved-games-folder
|
||||||
|
[Moose_.lua from develop branch]: https://raw.githubusercontent.com/FlightControl-Master/MOOSE_INCLUDE/develop/Moose_Include_Static/Moose_.lua
|
||||||
|
[demo missions]: demo-missions.md
|
||||||
|
|||||||
46
docs/beginner/problems.md
Normal file
46
docs/beginner/problems.md
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
---
|
||||||
|
parent: Beginner
|
||||||
|
nav_order: 05
|
||||||
|
---
|
||||||
|
|
||||||
|
# Problems
|
||||||
|
{: .no_toc }
|
||||||
|
|
||||||
|
1. Table of contents
|
||||||
|
{:toc}
|
||||||
|
|
||||||
|
## Something went wrong
|
||||||
|
|
||||||
|
If the mission shows not the expected behaviour do the following steps:
|
||||||
|
|
||||||
|
1. Double check if you added the changed mission script to the mission again!
|
||||||
|
1. Check if the triggers are configured as requested in the last sections.
|
||||||
|
|
||||||
|
## Read the logs
|
||||||
|
|
||||||
|
The DCS log is a super important and useful log for the entire of DCS World.
|
||||||
|
All scripting and other errors are recorded here. It is the one stop shop for
|
||||||
|
things that occurred in your mission. It will tell you if there was a mistake.
|
||||||
|
|
||||||
|
1. Open the file `dcs.log` in the `Logs` subfolder in your DCS
|
||||||
|
[Saved Games folder].
|
||||||
|
|
||||||
|
1. Search for the following line: `*** MOOSE INCLUDE END ***`
|
||||||
|
- If it is included in the log, Moose was loaded.
|
||||||
|
- If the line is not in the log check the triggers again!
|
||||||
|
|
||||||
|
1. Search for lines with `SCRIPTING` and `WARNING` or `ERROR` and read them.
|
||||||
|
- This might help to find your error.
|
||||||
|
|
||||||
|
{: .note }
|
||||||
|
> You will find a lot of warning and error lines in the log which are not
|
||||||
|
> related to `SCRIPTING`. They are related to stuff from Eagle Dynamics or
|
||||||
|
> Third Parties and you have to ignore them. EA does the same. ;o)
|
||||||
|
|
||||||
|
## Next step
|
||||||
|
|
||||||
|
If you don't find the error and/or don't understand the messages in the log file
|
||||||
|
you can [ask for help].
|
||||||
|
|
||||||
|
[Saved Games folder]: tipps-and-tricks.md#find-the-saved-games-folder
|
||||||
|
[ask for help]: ask-for-help.md
|
||||||
@@ -33,7 +33,9 @@ This folder can be found in your userprofile as subfolder of `Saved Games`.
|
|||||||
The easiest way to find it, is to open search and paste the text below into it
|
The easiest way to find it, is to open search and paste the text below into it
|
||||||
and press Enter:
|
and press Enter:
|
||||||
|
|
||||||
```%userprofile%\Saved Games```
|
```
|
||||||
|
%userprofile%\Saved Games
|
||||||
|
```
|
||||||
|
|
||||||
{: .note }
|
{: .note }
|
||||||
> The text will work even if your Windows is installed with another language,
|
> The text will work even if your Windows is installed with another language,
|
||||||
|
|||||||
BIN
docs/images/beginner/dcs-triggers-once-conditions-conf.png
Normal file
BIN
docs/images/beginner/dcs-triggers-once-conditions-conf.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
BIN
docs/images/beginner/discord-fomat-logs.png
Normal file
BIN
docs/images/beginner/discord-fomat-logs.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.6 KiB |
BIN
docs/images/beginner/discord-multi-line-code.png
Normal file
BIN
docs/images/beginner/discord-multi-line-code.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 7.3 KiB |
BIN
docs/images/beginner/discord-single-line-code.png
Normal file
BIN
docs/images/beginner/discord-single-line-code.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.3 KiB |
@@ -26,14 +26,30 @@ You only need to load **one** of those files at the beginning of your mission.
|
|||||||
|
|
||||||
This repository contains the generated documentation and pictures and other references.
|
This repository contains the generated documentation and pictures and other references.
|
||||||
The generated documentation is reflected in html and is published at:
|
The generated documentation is reflected in html and is published at:
|
||||||
- Stable `master` branch: <https://flightcontrol-master.github.io/MOOSE_DOCS/>
|
- `master` branch: <https://flightcontrol-master.github.io/MOOSE_DOCS/>
|
||||||
- `develop` branch: <https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/>
|
- `develop` branch: <https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/>
|
||||||
|
|
||||||
|
## [MOOSE_GUIDES](https://github.com/FlightControl-Master/MOOSE_GUIDES) - For external documentation and help
|
||||||
|
|
||||||
|
This repository will be removed in future.
|
||||||
|
|
||||||
|
## [MOOSE_PRESENTATIONS](https://github.com/FlightControl-Master/MOOSE_PRESENTATIONS)
|
||||||
|
|
||||||
|
A collection of presentations used in the videos on the youtube channel of FlightControl.
|
||||||
|
|
||||||
## [MOOSE_MISSIONS](https://github.com/FlightControl-Master/MOOSE_MISSIONS) - For users (provides demo missions)
|
## [MOOSE_MISSIONS](https://github.com/FlightControl-Master/MOOSE_MISSIONS) - For users (provides demo missions)
|
||||||
|
|
||||||
This repository contains all the demonstration missions in packed format (*.miz),
|
This repository contains all the demonstration missions in packed format (*.miz),
|
||||||
and can be used without any further setup in DCS WORLD.
|
and can be used without any further setup in DCS WORLD.
|
||||||
|
|
||||||
|
## [Moose_Community_Scripts](https://github.com/FlightControl-Master/Moose_Community_Scripts)
|
||||||
|
|
||||||
|
This repository is for Moose based helper scripts, snippets, functional demos.
|
||||||
|
|
||||||
|
## [MOOSE_SOUND](https://github.com/FlightControl-Master/MOOSE_SOUND)
|
||||||
|
|
||||||
|
Sound packs for different MOOSE framework classes.
|
||||||
|
|
||||||
## [MOOSE_MISSIONS_DYNAMIC](https://github.com/FlightControl-Master/MOOSE_MISSIONS_DYNAMIC) - Outdated
|
## [MOOSE_MISSIONS_DYNAMIC](https://github.com/FlightControl-Master/MOOSE_MISSIONS_DYNAMIC) - Outdated
|
||||||
|
|
||||||
This repository will be removed in future.
|
This repository will be removed in future.
|
||||||
@@ -41,3 +57,11 @@ This repository will be removed in future.
|
|||||||
## [MOOSE_MISSIONS_UNPACKED](https://github.com/FlightControl-Master/MOOSE_MISSIONS_UNPACKED) - Outdated
|
## [MOOSE_MISSIONS_UNPACKED](https://github.com/FlightControl-Master/MOOSE_MISSIONS_UNPACKED) - Outdated
|
||||||
|
|
||||||
This repository will be removed in future.
|
This repository will be removed in future.
|
||||||
|
|
||||||
|
## [MOOSE_COMMUNITY_MISSIONS](https://github.com/FlightControl-Master/MOOSE_COMMUNITY_MISSIONS) - Outdated
|
||||||
|
|
||||||
|
A database of missions created by the community, using MOOSE.
|
||||||
|
|
||||||
|
## [MOOSE_TOOLS](https://github.com/FlightControl-Master/MOOSE_TOOLS) - Outdated
|
||||||
|
|
||||||
|
A collection of the required tools to develop and contribute in the MOOSE framework for DCS World.
|
||||||
|
|||||||
Reference in New Issue
Block a user