mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-08-15 10:47:21 +00:00
Compare commits
130 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4a406604bd | ||
|
|
55cee46a8d | ||
|
|
607c52c0b7 | ||
|
|
2694321256 | ||
|
|
e8e790102a | ||
|
|
9c5561921b | ||
|
|
78fab9ab0c | ||
|
|
058c750bc6 | ||
|
|
f29da39dff | ||
|
|
624a7c70c9 | ||
|
|
0447ee2d9e | ||
|
|
456fcd38d0 | ||
|
|
a3cab7097a | ||
|
|
848e2f1294 | ||
|
|
ef4dc48ea1 | ||
|
|
2138a33292 | ||
|
|
a59343b987 | ||
|
|
a4ca4bdc99 | ||
|
|
a57b9a9081 | ||
|
|
249a6af456 | ||
|
|
18685d1a94 | ||
|
|
493b090534 | ||
|
|
389adab9b8 | ||
|
|
6360b8c58f | ||
|
|
b0818977cf | ||
|
|
32deb160ef | ||
|
|
2ba5215036 | ||
|
|
73ea4c7b32 | ||
|
|
46c37ff06a | ||
|
|
ff4708b624 | ||
|
|
82b2c84f13 | ||
|
|
48e8b1a9b3 | ||
|
|
1ad7c54ace | ||
|
|
9998c86c1f | ||
|
|
01a707ae0a | ||
|
|
570e8388fc | ||
|
|
9c5b5d4633 | ||
|
|
822bf13626 | ||
|
|
c520de0087 | ||
|
|
0e9076efa3 | ||
|
|
74cd5e3387 | ||
|
|
65c92be09e | ||
|
|
8e776cb3ab | ||
|
|
ab6cd2b751 | ||
|
|
18c3d990fc | ||
|
|
19d5cb8ecb | ||
|
|
2b56a78255 | ||
|
|
176d9df476 | ||
|
|
c94275cb8b | ||
|
|
45dbce3677 | ||
|
|
18745158a3 | ||
|
|
98c6c88391 | ||
|
|
2e4fd72781 | ||
|
|
80ced88ef1 | ||
|
|
8af3f89c14 | ||
|
|
fe3079caad | ||
|
|
61ac6b4131 | ||
|
|
36cb189512 | ||
|
|
15f9843878 | ||
|
|
67f847dd16 | ||
|
|
8b9143d3f1 | ||
|
|
0388d47f23 | ||
|
|
de9b173d9b | ||
|
|
2cecc526fb | ||
|
|
968d178317 | ||
|
|
3c477b872a | ||
|
|
77e6088114 | ||
|
|
edd6594953 | ||
|
|
f8c05c99d0 | ||
|
|
50f6d98b49 | ||
|
|
147eeb05f6 | ||
|
|
d8cb15a577 | ||
|
|
0daac876ea | ||
|
|
1832125022 | ||
|
|
c311c40b72 | ||
|
|
db516a2077 | ||
|
|
ff8766669c | ||
|
|
06dc9a732e | ||
|
|
50c74d0852 | ||
|
|
1c97eb6f3c | ||
|
|
69449430d1 | ||
|
|
663cd34aa3 | ||
|
|
cfed6f5153 | ||
|
|
2b22d5288c | ||
|
|
a64424ecc8 | ||
|
|
fd1b2ecb86 | ||
|
|
6cae3e62cf | ||
|
|
05ce7e4513 | ||
|
|
136bd19f19 | ||
|
|
8873504daf | ||
|
|
a844a5d697 | ||
|
|
a49f4eaa21 | ||
|
|
e6e2651f8c | ||
|
|
b93ba13644 | ||
|
|
e4a51951b0 | ||
|
|
ad56e39942 | ||
|
|
ea09dc5a6e | ||
|
|
8ecfd913a3 | ||
|
|
53367c786e | ||
|
|
db5797bb4e | ||
|
|
5e8fe97752 | ||
|
|
393fa0bfbb | ||
|
|
4f51884b9d | ||
|
|
4c5c320073 | ||
|
|
9098590568 | ||
|
|
555bb7e68b | ||
|
|
c0a18957f0 | ||
|
|
2cf939560e | ||
|
|
9d3a7aae78 | ||
|
|
f6ed592f92 | ||
|
|
c98757d13c | ||
|
|
17378f509e | ||
|
|
7f18ea0e7a | ||
|
|
5172619cb1 | ||
|
|
3962529698 | ||
|
|
6481d5d41e | ||
|
|
6cc3d73c04 | ||
|
|
e541e39403 | ||
|
|
c7ea45e5fd | ||
|
|
20f28b3d2c | ||
|
|
f3f63ab8aa | ||
|
|
e91090cfff | ||
|
|
1a7fb3c13e | ||
|
|
59857ed79d | ||
|
|
4797665939 | ||
|
|
b89749036d | ||
|
|
c6268488de | ||
|
|
de04369703 | ||
|
|
05b6f19a87 | ||
|
|
2753df8216 |
33
Moose Development/Moose/.lua-format
Normal file
33
Moose Development/Moose/.lua-format
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
# See https://github.com/Koihik/LuaFormatter
|
||||||
|
# Use '-- LuaFormatter off' and '-- LuaFormatter on' around code blocks to inhibit formatting
|
||||||
|
|
||||||
|
column_limit: 500
|
||||||
|
indent_width: 2
|
||||||
|
use_tab: false
|
||||||
|
continuation_indent_width: 2
|
||||||
|
keep_simple_control_block_one_line: false
|
||||||
|
keep_simple_function_one_line: false
|
||||||
|
align_args: true
|
||||||
|
break_after_functioncall_lp: false
|
||||||
|
break_before_functioncall_rp: false
|
||||||
|
align_parameter: true
|
||||||
|
chop_down_parameter: true
|
||||||
|
break_after_functiondef_lp: false
|
||||||
|
break_before_functiondef_rp: false
|
||||||
|
align_table_field: true
|
||||||
|
break_after_table_lb: true
|
||||||
|
break_before_table_rb: true
|
||||||
|
chop_down_table: true
|
||||||
|
chop_down_kv_table: true
|
||||||
|
column_table_limit: 500
|
||||||
|
table_sep: ','
|
||||||
|
extra_sep_at_table_end: true
|
||||||
|
break_after_operator: true
|
||||||
|
single_quote_to_double_quote: false
|
||||||
|
double_quote_to_single_quote: false
|
||||||
|
spaces_before_call: 1
|
||||||
|
spaces_inside_functiondef_parens: true
|
||||||
|
spaces_inside_functioncall_parens: true
|
||||||
|
spaces_inside_table_braces: true
|
||||||
|
spaces_around_equals_in_field: true
|
||||||
|
line_breaks_after_function_body: 1
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -585,7 +585,7 @@ function AI_AIR:onafterRTB( AIGroup, From, Event, To )
|
|||||||
|
|
||||||
if AIGroup and AIGroup:IsAlive() then
|
if AIGroup and AIGroup:IsAlive() then
|
||||||
|
|
||||||
self:I( "Group " .. AIGroup:GetName() .. " ... RTB! ( " .. self:GetState() .. " )" )
|
self:T( "Group " .. AIGroup:GetName() .. " ... RTB! ( " .. self:GetState() .. " )" )
|
||||||
|
|
||||||
self:ClearTargetDistance()
|
self:ClearTargetDistance()
|
||||||
--AIGroup:ClearTasks()
|
--AIGroup:ClearTasks()
|
||||||
|
|||||||
@@ -47,19 +47,21 @@ function AI_CARGO:New( Carrier, CargoSet )
|
|||||||
|
|
||||||
self:SetStartState( "Unloaded" )
|
self:SetStartState( "Unloaded" )
|
||||||
|
|
||||||
self:AddTransition( "Unloaded", "Pickup", "*" )
|
-- Board
|
||||||
self:AddTransition( "Loaded", "Deploy", "*" )
|
self:AddTransition( "Unloaded", "Pickup", "Unloaded" )
|
||||||
|
self:AddTransition( "*", "Load", "*" )
|
||||||
|
self:AddTransition( "*", "Reload", "*" )
|
||||||
|
self:AddTransition( "*", "Board", "*" )
|
||||||
|
self:AddTransition( "*", "Loaded", "Loaded" )
|
||||||
|
self:AddTransition( "Loaded", "PickedUp", "Loaded" )
|
||||||
|
|
||||||
self:AddTransition( "*", "Load", "Boarding" )
|
-- Unload
|
||||||
self:AddTransition( "Boarding", "Board", "Boarding" )
|
self:AddTransition( "Loaded", "Deploy", "*" )
|
||||||
self:AddTransition( "Loaded", "Board", "Loaded" )
|
self:AddTransition( "*", "Unload", "*" )
|
||||||
self:AddTransition( "Boarding", "Loaded", "Boarding" )
|
self:AddTransition( "*", "Unboard", "*" )
|
||||||
self:AddTransition( "Boarding", "PickedUp", "Loaded" )
|
self:AddTransition( "*", "Unloaded", "Unloaded" )
|
||||||
|
self:AddTransition( "Unloaded", "Deployed", "Unloaded" )
|
||||||
self:AddTransition( "Loaded", "Unload", "Unboarding" )
|
|
||||||
self:AddTransition( "Unboarding", "Unboard", "Unboarding" )
|
|
||||||
self:AddTransition( "Unboarding", "Unloaded", "Unboarding" )
|
|
||||||
self:AddTransition( "Unboarding", "Deployed", "Unloaded" )
|
|
||||||
|
|
||||||
--- Pickup Handler OnBefore for AI_CARGO
|
--- Pickup Handler OnBefore for AI_CARGO
|
||||||
-- @function [parent=#AI_CARGO] OnBeforePickup
|
-- @function [parent=#AI_CARGO] OnBeforePickup
|
||||||
@@ -393,7 +395,7 @@ end
|
|||||||
function AI_CARGO:onafterBoard( Carrier, From, Event, To, Cargo, CarrierUnit, PickupZone )
|
function AI_CARGO:onafterBoard( Carrier, From, Event, To, Cargo, CarrierUnit, PickupZone )
|
||||||
self:F( { Carrier, From, Event, To, Cargo, CarrierUnit:GetName() } )
|
self:F( { Carrier, From, Event, To, Cargo, CarrierUnit:GetName() } )
|
||||||
|
|
||||||
if Carrier and Carrier:IsAlive() and From == "Boarding" then
|
if Carrier and Carrier:IsAlive() then
|
||||||
self:F({ IsLoaded = Cargo:IsLoaded(), Cargo:GetName(), Carrier:GetName() } )
|
self:F({ IsLoaded = Cargo:IsLoaded(), Cargo:GetName(), Carrier:GetName() } )
|
||||||
if not Cargo:IsLoaded() and not Cargo:IsDestroyed() then
|
if not Cargo:IsLoaded() and not Cargo:IsDestroyed() then
|
||||||
self:__Board( -10, Cargo, CarrierUnit, PickupZone )
|
self:__Board( -10, Cargo, CarrierUnit, PickupZone )
|
||||||
@@ -509,7 +511,7 @@ end
|
|||||||
function AI_CARGO:onafterUnboard( Carrier, From, Event, To, Cargo, CarrierUnit, DeployZone, Defend )
|
function AI_CARGO:onafterUnboard( Carrier, From, Event, To, Cargo, CarrierUnit, DeployZone, Defend )
|
||||||
self:F( { Carrier, From, Event, To, Cargo:GetName(), DeployZone = DeployZone, Defend = Defend } )
|
self:F( { Carrier, From, Event, To, Cargo:GetName(), DeployZone = DeployZone, Defend = Defend } )
|
||||||
|
|
||||||
if Carrier and Carrier:IsAlive() and From == "Unboarding" then
|
if Carrier and Carrier:IsAlive() then
|
||||||
if not Cargo:IsUnLoaded() then
|
if not Cargo:IsUnLoaded() then
|
||||||
self:__Unboard( 10, Cargo, CarrierUnit, DeployZone, Defend )
|
self:__Unboard( 10, Cargo, CarrierUnit, DeployZone, Defend )
|
||||||
return
|
return
|
||||||
@@ -580,4 +582,3 @@ function AI_CARGO:onafterDeployed( Carrier, From, Event, To, DeployZone, Defend
|
|||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -98,7 +98,8 @@ function AI_CARGO_APC:New( APC, CargoSet, CombatRadius )
|
|||||||
self:AddTransition( "*", "Guard", "Unloaded" )
|
self:AddTransition( "*", "Guard", "Unloaded" )
|
||||||
self:AddTransition( "*", "Home", "*" )
|
self:AddTransition( "*", "Home", "*" )
|
||||||
self:AddTransition( "*", "Reload", "Boarding" )
|
self:AddTransition( "*", "Reload", "Boarding" )
|
||||||
|
self:AddTransition( "*", "Deployed", "*" )
|
||||||
|
self:AddTransition( "*", "PickedUp", "*" )
|
||||||
self:AddTransition( "*", "Destroyed", "Destroyed" )
|
self:AddTransition( "*", "Destroyed", "Destroyed" )
|
||||||
|
|
||||||
self:SetCombatRadius( CombatRadius )
|
self:SetCombatRadius( CombatRadius )
|
||||||
|
|||||||
@@ -64,20 +64,24 @@ function AI_CARGO_HELICOPTER:New( Helicopter, CargoSet )
|
|||||||
self.Zone = ZONE_GROUP:New( Helicopter:GetName(), Helicopter, 300 )
|
self.Zone = ZONE_GROUP:New( Helicopter:GetName(), Helicopter, 300 )
|
||||||
|
|
||||||
self:SetStartState( "Unloaded" )
|
self:SetStartState( "Unloaded" )
|
||||||
|
-- Boarding
|
||||||
|
self:AddTransition( "Unloaded", "Pickup", "Unloaded" )
|
||||||
|
self:AddTransition( "*", "Landed", "*" )
|
||||||
|
self:AddTransition( "*", "Load", "*" )
|
||||||
|
self:AddTransition( "*", "Loaded", "Loaded" )
|
||||||
|
self:AddTransition( "Loaded", "PickedUp", "Loaded" )
|
||||||
|
|
||||||
self:AddTransition( "Unloaded", "Pickup", "*" )
|
-- Unboarding
|
||||||
self:AddTransition( "Loaded", "Deploy", "*" )
|
self:AddTransition( "Loaded", "Deploy", "*" )
|
||||||
self:AddTransition( "*", "Loaded", "Loaded" )
|
self:AddTransition( "*", "Queue", "*" )
|
||||||
self:AddTransition( "Unboarding", "Pickup", "Unloaded" )
|
self:AddTransition( "*", "Orbit" , "*" )
|
||||||
self:AddTransition( "Unloaded", "Unboard", "Unloaded" )
|
self:AddTransition( "*", "Destroyed", "*" )
|
||||||
self:AddTransition( "Unloaded", "Unloaded", "Unloaded" )
|
self:AddTransition( "*", "Unload", "*" )
|
||||||
self:AddTransition( "*", "PickedUp", "*" )
|
self:AddTransition( "*", "Unloaded", "Unloaded" )
|
||||||
self:AddTransition( "*", "Landed", "*" )
|
self:AddTransition( "Unloaded", "Deployed", "Unloaded" )
|
||||||
self:AddTransition( "*", "Queue", "*" )
|
|
||||||
self:AddTransition( "*", "Orbit" , "*" )
|
-- RTB
|
||||||
self:AddTransition( "*", "Home" , "*" )
|
self:AddTransition( "*", "Home" , "*" )
|
||||||
|
|
||||||
self:AddTransition( "*", "Destroyed", "Destroyed" )
|
|
||||||
|
|
||||||
--- Pickup Handler OnBefore for AI_CARGO_HELICOPTER
|
--- Pickup Handler OnBefore for AI_CARGO_HELICOPTER
|
||||||
-- @function [parent=#AI_CARGO_HELICOPTER] OnBeforePickup
|
-- @function [parent=#AI_CARGO_HELICOPTER] OnBeforePickup
|
||||||
@@ -207,6 +211,9 @@ function AI_CARGO_HELICOPTER:New( Helicopter, CargoSet )
|
|||||||
|
|
||||||
self:SetCarrier( Helicopter )
|
self:SetCarrier( Helicopter )
|
||||||
|
|
||||||
|
self.landingspeed = 15 -- kph
|
||||||
|
self.landingheight = 5.5 -- meter
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -255,6 +262,25 @@ function AI_CARGO_HELICOPTER:SetCarrier( Helicopter )
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Set landingspeed and -height for helicopter landings. Adjust after tracing if your helis get stuck after landing.
|
||||||
|
-- @param #AI_CARGO_HELICOPTER self
|
||||||
|
-- @param #number speed Landing speed in kph(!), e.g. 15
|
||||||
|
-- @param #number height Landing height in meters(!), e.g. 5.5
|
||||||
|
-- @return #AI_CARGO_HELICOPTER self
|
||||||
|
-- @usage If your choppers get stuck, add tracing to your script to determine if they hit the right parameters like so:
|
||||||
|
--
|
||||||
|
-- BASE:TraceOn()
|
||||||
|
-- BASE:TraceClass("AI_CARGO_HELICOPTER")
|
||||||
|
--
|
||||||
|
-- Watch the DCS.log for entries stating `Helicopter:<name>, Height = Helicopter:<number>, Velocity = Helicopter:<number>`
|
||||||
|
-- Adjust if necessary.
|
||||||
|
function AI_CARGO_HELICOPTER:SetLandingSpeedAndHeight(speed, height)
|
||||||
|
local _speed = speed or 15
|
||||||
|
local _height = height or 5.5
|
||||||
|
self.landingheight = _height
|
||||||
|
self.landingspeed = _speed
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- @param #AI_CARGO_HELICOPTER self
|
--- @param #AI_CARGO_HELICOPTER self
|
||||||
-- @param Wrapper.Group#GROUP Helicopter
|
-- @param Wrapper.Group#GROUP Helicopter
|
||||||
@@ -271,13 +297,13 @@ function AI_CARGO_HELICOPTER:onafterLanded( Helicopter, From, Event, To )
|
|||||||
-- 1 - When the helo lands normally on the ground.
|
-- 1 - When the helo lands normally on the ground.
|
||||||
-- 2 - when the helo is hit and goes RTB or even when it is destroyed.
|
-- 2 - when the helo is hit and goes RTB or even when it is destroyed.
|
||||||
-- For point 2, this is an issue, the infantry may not unload in this case!
|
-- For point 2, this is an issue, the infantry may not unload in this case!
|
||||||
-- So we check if the helo is on the ground, and velocity< 5.
|
-- So we check if the helo is on the ground, and velocity< 15.
|
||||||
-- Only then the infantry can unload (and load too, for consistency)!
|
-- Only then the infantry can unload (and load too, for consistency)!
|
||||||
|
|
||||||
self:F( { Helicopter:GetName(), Height = Helicopter:GetHeight( true ), Velocity = Helicopter:GetVelocityKMH() } )
|
self:T( { Helicopter:GetName(), Height = Helicopter:GetHeight( true ), Velocity = Helicopter:GetVelocityKMH() } )
|
||||||
|
|
||||||
if self.RoutePickup == true then
|
if self.RoutePickup == true then
|
||||||
if Helicopter:GetHeight( true ) <= 5.5 and Helicopter:GetVelocityKMH() < 15 then
|
if Helicopter:GetHeight( true ) <= self.landingheight then --and Helicopter:GetVelocityKMH() < self.landingspeed then
|
||||||
--self:Load( Helicopter:GetPointVec2() )
|
--self:Load( Helicopter:GetPointVec2() )
|
||||||
self:Load( self.PickupZone )
|
self:Load( self.PickupZone )
|
||||||
self.RoutePickup = false
|
self.RoutePickup = false
|
||||||
@@ -285,7 +311,7 @@ function AI_CARGO_HELICOPTER:onafterLanded( Helicopter, From, Event, To )
|
|||||||
end
|
end
|
||||||
|
|
||||||
if self.RouteDeploy == true then
|
if self.RouteDeploy == true then
|
||||||
if Helicopter:GetHeight( true ) <= 5.5 and Helicopter:GetVelocityKMH() < 15 then
|
if Helicopter:GetHeight( true ) <= self.landingheight then --and Helicopter:GetVelocityKMH() < self.landingspeed then
|
||||||
self:Unload( self.DeployZone )
|
self:Unload( self.DeployZone )
|
||||||
self.RouteDeploy = false
|
self.RouteDeploy = false
|
||||||
end
|
end
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,9 +1,9 @@
|
|||||||
--- **Core** - TACAN and other beacons.
|
--- **Core** - TACAN and other beacons.
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ## Features:
|
-- ## Features:
|
||||||
--
|
--
|
||||||
-- * Provide beacon functionality to assist pilots.
|
-- * Provide beacon functionality to assist pilots.
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
@@ -14,34 +14,34 @@
|
|||||||
-- @image Core_Radio.JPG
|
-- @image Core_Radio.JPG
|
||||||
|
|
||||||
--- *In order for the light to shine so brightly, the darkness must be present.* -- Francis Bacon
|
--- *In order for the light to shine so brightly, the darkness must be present.* -- Francis Bacon
|
||||||
--
|
--
|
||||||
-- After attaching a @{#BEACON} to your @{Wrapper.Positionable#POSITIONABLE}, you need to select the right function to activate the kind of beacon you want.
|
-- After attaching a @{#BEACON} to your @{Wrapper.Positionable#POSITIONABLE}, you need to select the right function to activate the kind of beacon you want.
|
||||||
-- There are two types of BEACONs available : the AA TACAN Beacon and the general purpose Radio Beacon.
|
-- There are two types of BEACONs available : the AA TACAN Beacon and the general purpose Radio Beacon.
|
||||||
-- Note that in both case, you can set an optional parameter : the `BeaconDuration`. This can be very usefull to simulate the battery time if your BEACON is
|
-- Note that in both case, you can set an optional parameter : the `BeaconDuration`. This can be very usefull to simulate the battery time if your BEACON is
|
||||||
-- attach to a cargo crate, for exemple.
|
-- attach to a cargo crate, for exemple.
|
||||||
--
|
--
|
||||||
-- ## AA TACAN Beacon usage
|
-- ## AA TACAN Beacon usage
|
||||||
--
|
--
|
||||||
-- This beacon only works with airborne @{Wrapper.Unit#UNIT} or a @{Wrapper.Group#GROUP}. Use @{#BEACON:AATACAN}() to set the beacon parameters and start the beacon.
|
-- This beacon only works with airborne @{Wrapper.Unit#UNIT} or a @{Wrapper.Group#GROUP}. Use @{#BEACON:AATACAN}() to set the beacon parameters and start the beacon.
|
||||||
-- Use @#BEACON:StopAATACAN}() to stop it.
|
-- Use @#BEACON:StopAATACAN}() to stop it.
|
||||||
--
|
--
|
||||||
-- ## General Purpose Radio Beacon usage
|
-- ## General Purpose Radio Beacon usage
|
||||||
--
|
--
|
||||||
-- This beacon will work with any @{Wrapper.Positionable#POSITIONABLE}, but **it won't follow the @{Wrapper.Positionable#POSITIONABLE}** ! This means that you should only use it with
|
-- This beacon will work with any @{Wrapper.Positionable#POSITIONABLE}, but **it won't follow the @{Wrapper.Positionable#POSITIONABLE}** ! This means that you should only use it with
|
||||||
-- @{Wrapper.Positionable#POSITIONABLE} that don't move, or move very slowly. Use @{#BEACON:RadioBeacon}() to set the beacon parameters and start the beacon.
|
-- @{Wrapper.Positionable#POSITIONABLE} that don't move, or move very slowly. Use @{#BEACON:RadioBeacon}() to set the beacon parameters and start the beacon.
|
||||||
-- Use @{#BEACON:StopRadioBeacon}() to stop it.
|
-- Use @{#BEACON:StopRadioBeacon}() to stop it.
|
||||||
--
|
--
|
||||||
-- @type BEACON
|
-- @type BEACON
|
||||||
-- @field #string ClassName Name of the class "BEACON".
|
-- @field #string ClassName Name of the class "BEACON".
|
||||||
-- @field Wrapper.Controllable#CONTROLLABLE Positionable The @{#CONTROLLABLE} that will receive radio capabilities.
|
-- @field Wrapper.Controllable#CONTROLLABLE Positionable The @{#CONTROLLABLE} that will receive radio capabilities.
|
||||||
-- @extends Core.Base#BASE
|
-- @extends Core.Base#BASE
|
||||||
BEACON = {
|
BEACON = {
|
||||||
ClassName = "BEACON",
|
ClassName = "BEACON",
|
||||||
Positionable = nil,
|
Positionable = nil,
|
||||||
name = nil,
|
name = nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Beacon types supported by DCS.
|
--- Beacon types supported by DCS.
|
||||||
-- @type BEACON.Type
|
-- @type BEACON.Type
|
||||||
-- @field #number NULL
|
-- @field #number NULL
|
||||||
-- @field #number VOR
|
-- @field #number VOR
|
||||||
@@ -65,19 +65,19 @@ BEACON = {
|
|||||||
-- @field #number ICLS_GLIDESLOPE
|
-- @field #number ICLS_GLIDESLOPE
|
||||||
-- @field #number NAUTICAL_HOMER
|
-- @field #number NAUTICAL_HOMER
|
||||||
BEACON.Type={
|
BEACON.Type={
|
||||||
NULL = 0,
|
NULL = 0,
|
||||||
VOR = 1,
|
VOR = 1,
|
||||||
DME = 2,
|
DME = 2,
|
||||||
VOR_DME = 3,
|
VOR_DME = 3,
|
||||||
TACAN = 4,
|
TACAN = 4,
|
||||||
VORTAC = 5,
|
VORTAC = 5,
|
||||||
RSBN = 128,
|
RSBN = 128,
|
||||||
BROADCAST_STATION = 1024,
|
BROADCAST_STATION = 1024,
|
||||||
HOMER = 8,
|
HOMER = 8,
|
||||||
AIRPORT_HOMER = 4104,
|
AIRPORT_HOMER = 4104,
|
||||||
AIRPORT_HOMER_WITH_MARKER = 4136,
|
AIRPORT_HOMER_WITH_MARKER = 4136,
|
||||||
ILS_FAR_HOMER = 16408,
|
ILS_FAR_HOMER = 16408,
|
||||||
ILS_NEAR_HOMER = 16424,
|
ILS_NEAR_HOMER = 16424,
|
||||||
ILS_LOCALIZER = 16640,
|
ILS_LOCALIZER = 16640,
|
||||||
ILS_GLIDESLOPE = 16896,
|
ILS_GLIDESLOPE = 16896,
|
||||||
PRMG_LOCALIZER = 33024,
|
PRMG_LOCALIZER = 33024,
|
||||||
@@ -95,11 +95,11 @@ BEACON.Type={
|
|||||||
-- @field #number TACAN TACtical Air Navigation system on ground.
|
-- @field #number TACAN TACtical Air Navigation system on ground.
|
||||||
-- @field #number TACAN_TANKER_X TACtical Air Navigation system for tankers on X band.
|
-- @field #number TACAN_TANKER_X TACtical Air Navigation system for tankers on X band.
|
||||||
-- @field #number TACAN_TANKER_Y TACtical Air Navigation system for tankers on Y band.
|
-- @field #number TACAN_TANKER_Y TACtical Air Navigation system for tankers on Y band.
|
||||||
-- @field #number VOR Very High Frequency Omni-Directional Range
|
-- @field #number VOR Very High Frequency Omnidirectional Range
|
||||||
-- @field #number ILS_LOCALIZER ILS localizer
|
-- @field #number ILS_LOCALIZER ILS localizer
|
||||||
-- @field #number ILS_GLIDESLOPE ILS glideslope.
|
-- @field #number ILS_GLIDESLOPE ILS glide slope.
|
||||||
-- @field #number PRGM_LOCALIZER PRGM localizer.
|
-- @field #number PRGM_LOCALIZER PRGM localizer.
|
||||||
-- @field #number PRGM_GLIDESLOPE PRGM glideslope.
|
-- @field #number PRGM_GLIDESLOPE PRGM glide slope.
|
||||||
-- @field #number BROADCAST_STATION Broadcast station.
|
-- @field #number BROADCAST_STATION Broadcast station.
|
||||||
-- @field #number VORTAC Radio-based navigational aid for aircraft pilots consisting of a co-located VHF omnidirectional range (VOR) beacon and a tactical air navigation system (TACAN) beacon.
|
-- @field #number VORTAC Radio-based navigational aid for aircraft pilots consisting of a co-located VHF omnidirectional range (VOR) beacon and a tactical air navigation system (TACAN) beacon.
|
||||||
-- @field #number TACAN_AA_MODE_X TACtical Air Navigation for aircraft on X band.
|
-- @field #number TACAN_AA_MODE_X TACtical Air Navigation for aircraft on X band.
|
||||||
@@ -108,13 +108,13 @@ BEACON.Type={
|
|||||||
-- @field #number ICLS_LOCALIZER Carrier landing system.
|
-- @field #number ICLS_LOCALIZER Carrier landing system.
|
||||||
-- @field #number ICLS_GLIDESLOPE Carrier landing system.
|
-- @field #number ICLS_GLIDESLOPE Carrier landing system.
|
||||||
BEACON.System={
|
BEACON.System={
|
||||||
PAR_10 = 1,
|
PAR_10 = 1,
|
||||||
RSBN_5 = 2,
|
RSBN_5 = 2,
|
||||||
TACAN = 3,
|
TACAN = 3,
|
||||||
TACAN_TANKER_X = 4,
|
TACAN_TANKER_X = 4,
|
||||||
TACAN_TANKER_Y = 5,
|
TACAN_TANKER_Y = 5,
|
||||||
VOR = 6,
|
VOR = 6,
|
||||||
ILS_LOCALIZER = 7,
|
ILS_LOCALIZER = 7,
|
||||||
ILS_GLIDESLOPE = 8,
|
ILS_GLIDESLOPE = 8,
|
||||||
PRMG_LOCALIZER = 9,
|
PRMG_LOCALIZER = 9,
|
||||||
PRMG_GLIDESLOPE = 10,
|
PRMG_GLIDESLOPE = 10,
|
||||||
@@ -131,28 +131,27 @@ BEACON.System={
|
|||||||
-- If you want to create a BEACON, you probably should use @{Wrapper.Positionable#POSITIONABLE.GetBeacon}() instead.
|
-- If you want to create a BEACON, you probably should use @{Wrapper.Positionable#POSITIONABLE.GetBeacon}() instead.
|
||||||
-- @param #BEACON self
|
-- @param #BEACON self
|
||||||
-- @param Wrapper.Positionable#POSITIONABLE Positionable The @{Positionable} that will receive radio capabilities.
|
-- @param Wrapper.Positionable#POSITIONABLE Positionable The @{Positionable} that will receive radio capabilities.
|
||||||
-- @return #BEACON Beacon object or #nil if the positionable is invalid.
|
-- @return #BEACON Beacon object or #nil if the POSITIONABLE is invalid.
|
||||||
function BEACON:New(Positionable)
|
function BEACON:New( Positionable )
|
||||||
|
|
||||||
-- Inherit BASE.
|
-- Inherit BASE.
|
||||||
local self=BASE:Inherit(self, BASE:New()) --#BEACON
|
local self = BASE:Inherit( self, BASE:New() ) -- #BEACON
|
||||||
|
|
||||||
-- Debug.
|
-- Debug.
|
||||||
self:F(Positionable)
|
self:F( Positionable )
|
||||||
|
|
||||||
-- Set positionable.
|
-- Set positionable.
|
||||||
if Positionable:GetPointVec2() then -- It's stupid, but the only way I found to make sure positionable is valid
|
if Positionable:GetPointVec2() then -- It's stupid, but the only way I found to make sure POSITIONABLE is valid
|
||||||
self.Positionable = Positionable
|
self.Positionable = Positionable
|
||||||
self.name=Positionable:GetName()
|
self.name = Positionable:GetName()
|
||||||
self:I(string.format("New BEACON %s", tostring(self.name)))
|
self:I( string.format( "New BEACON %s", tostring( self.name ) ) )
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
self:E({"The passed positionable is invalid, no BEACON created", Positionable})
|
self:E( { "The passed POSITIONABLE is invalid, no BEACON created", Positionable } )
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Activates a TACAN BEACON.
|
--- Activates a TACAN BEACON.
|
||||||
-- @param #BEACON self
|
-- @param #BEACON self
|
||||||
-- @param #number Channel TACAN channel, i.e. the "10" part in "10Y".
|
-- @param #number Channel TACAN channel, i.e. the "10" part in "10Y".
|
||||||
@@ -162,53 +161,55 @@ end
|
|||||||
-- @param #number Duration How long will the beacon last in seconds. Omit for forever.
|
-- @param #number Duration How long will the beacon last in seconds. Omit for forever.
|
||||||
-- @return #BEACON self
|
-- @return #BEACON self
|
||||||
-- @usage
|
-- @usage
|
||||||
|
--
|
||||||
-- -- Let's create a TACAN Beacon for a tanker
|
-- -- Let's create a TACAN Beacon for a tanker
|
||||||
-- local myUnit = UNIT:FindByName("MyUnit")
|
-- local myUnit = UNIT:FindByName("MyUnit")
|
||||||
-- local myBeacon = myUnit:GetBeacon() -- Creates the beacon
|
-- local myBeacon = myUnit:GetBeacon() -- Creates the beacon
|
||||||
--
|
--
|
||||||
-- myBeacon:ActivateTACAN(20, "Y", "TEXACO", true) -- Activate the beacon
|
-- myBeacon:ActivateTACAN(20, "Y", "TEXACO", true) -- Activate the beacon
|
||||||
function BEACON:ActivateTACAN(Channel, Mode, Message, Bearing, Duration)
|
--
|
||||||
self:T({channel=Channel, mode=Mode, callsign=Message, bearing=Bearing, duration=Duration})
|
function BEACON:ActivateTACAN( Channel, Mode, Message, Bearing, Duration )
|
||||||
|
self:T( { channel = Channel, mode = Mode, callsign = Message, bearing = Bearing, duration = Duration } )
|
||||||
|
|
||||||
-- Get frequency.
|
-- Get frequency.
|
||||||
local Frequency=UTILS.TACANToFrequency(Channel, Mode)
|
local Frequency = UTILS.TACANToFrequency( Channel, Mode )
|
||||||
|
|
||||||
-- Check.
|
-- Check.
|
||||||
if not Frequency then
|
if not Frequency then
|
||||||
self:E({"The passed TACAN channel is invalid, the BEACON is not emitting"})
|
self:E( { "The passed TACAN channel is invalid, the BEACON is not emitting" } )
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Beacon type.
|
-- Beacon type.
|
||||||
local Type=BEACON.Type.TACAN
|
local Type = BEACON.Type.TACAN
|
||||||
|
|
||||||
-- Beacon system.
|
-- Beacon system.
|
||||||
local System=BEACON.System.TACAN
|
local System = BEACON.System.TACAN
|
||||||
|
|
||||||
-- Check if unit is an aircraft and set system accordingly.
|
-- Check if unit is an aircraft and set system accordingly.
|
||||||
local AA=self.Positionable:IsAir()
|
local AA = self.Positionable:IsAir()
|
||||||
if AA then
|
if AA then
|
||||||
System=5 --NOTE: 5 is how you cat the correct tanker behaviour! --BEACON.System.TACAN_TANKER
|
System = 5 -- NOTE: 5 is how you cat the correct tanker behaviour! --BEACON.System.TACAN_TANKER
|
||||||
-- Check if "Y" mode is selected for aircraft.
|
-- Check if "Y" mode is selected for aircraft.
|
||||||
if Mode~="Y" then
|
if Mode ~= "Y" then
|
||||||
self:E({"WARNING: The POSITIONABLE you want to attach the AA Tacan Beacon is an aircraft: Mode should Y !The BEACON is not emitting.", self.Positionable})
|
self:E( { "WARNING: The POSITIONABLE you want to attach the AA TACAN Beacon is an aircraft: Mode should Y! The BEACON is not emitting.", self.Positionable } )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Attached unit.
|
-- Attached unit.
|
||||||
local UnitID=self.Positionable:GetID()
|
local UnitID = self.Positionable:GetID()
|
||||||
|
|
||||||
-- Debug.
|
-- Debug.
|
||||||
self:I({string.format("BEACON Activating TACAN %s: Channel=%d%s, Morse=%s, Bearing=%s, Duration=%s!", tostring(self.name), Channel, Mode, Message, tostring(Bearing), tostring(Duration))})
|
self:I( { string.format( "BEACON Activating TACAN %s: Channel=%d%s, Morse=%s, Bearing=%s, Duration=%s!", tostring( self.name ), Channel, Mode, Message, tostring( Bearing ), tostring( Duration ) ) } )
|
||||||
|
|
||||||
-- Start beacon.
|
-- Start beacon.
|
||||||
self.Positionable:CommandActivateBeacon(Type, System, Frequency, UnitID, Channel, Mode, AA, Message, Bearing)
|
self.Positionable:CommandActivateBeacon( Type, System, Frequency, UnitID, Channel, Mode, AA, Message, Bearing )
|
||||||
|
|
||||||
-- Stop sheduler.
|
-- Stop scheduler.
|
||||||
if Duration then
|
if Duration then
|
||||||
self.Positionable:DeactivateBeacon(Duration)
|
self.Positionable:DeactivateBeacon( Duration )
|
||||||
end
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -218,23 +219,23 @@ end
|
|||||||
-- @param #string Callsign The Message that is going to be coded in Morse and broadcasted by the beacon.
|
-- @param #string Callsign The Message that is going to be coded in Morse and broadcasted by the beacon.
|
||||||
-- @param #number Duration How long will the beacon last in seconds. Omit for forever.
|
-- @param #number Duration How long will the beacon last in seconds. Omit for forever.
|
||||||
-- @return #BEACON self
|
-- @return #BEACON self
|
||||||
function BEACON:ActivateICLS(Channel, Callsign, Duration)
|
function BEACON:ActivateICLS( Channel, Callsign, Duration )
|
||||||
self:F({Channel=Channel, Callsign=Callsign, Duration=Duration})
|
self:F( { Channel = Channel, Callsign = Callsign, Duration = Duration } )
|
||||||
|
|
||||||
-- Attached unit.
|
-- Attached unit.
|
||||||
local UnitID=self.Positionable:GetID()
|
local UnitID = self.Positionable:GetID()
|
||||||
|
|
||||||
-- Debug
|
-- Debug
|
||||||
self:T2({"ICLS BEACON started!"})
|
self:T2( { "ICLS BEACON started!" } )
|
||||||
|
|
||||||
-- Start beacon.
|
-- Start beacon.
|
||||||
self.Positionable:CommandActivateICLS(Channel, UnitID, Callsign)
|
self.Positionable:CommandActivateICLS( Channel, UnitID, Callsign )
|
||||||
|
|
||||||
-- Stop sheduler
|
-- Stop scheduler
|
||||||
if Duration then -- Schedule the stop of the BEACON if asked by the MD
|
if Duration then -- Schedule the stop of the BEACON if asked by the MD
|
||||||
self.Positionable:DeactivateBeacon(Duration)
|
self.Positionable:DeactivateBeacon( Duration )
|
||||||
end
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -246,27 +247,29 @@ end
|
|||||||
-- @param #number BeaconDuration How long will the beacon last in seconds. Omit for forever.
|
-- @param #number BeaconDuration How long will the beacon last in seconds. Omit for forever.
|
||||||
-- @return #BEACON self
|
-- @return #BEACON self
|
||||||
-- @usage
|
-- @usage
|
||||||
|
--
|
||||||
-- -- Let's create a TACAN Beacon for a tanker
|
-- -- Let's create a TACAN Beacon for a tanker
|
||||||
-- local myUnit = UNIT:FindByName("MyUnit")
|
-- local myUnit = UNIT:FindByName("MyUnit")
|
||||||
-- local myBeacon = myUnit:GetBeacon() -- Creates the beacon
|
-- local myBeacon = myUnit:GetBeacon() -- Creates the beacon
|
||||||
--
|
--
|
||||||
-- myBeacon:AATACAN(20, "TEXACO", true) -- Activate the beacon
|
-- myBeacon:AATACAN(20, "TEXACO", true) -- Activate the beacon
|
||||||
function BEACON:AATACAN(TACANChannel, Message, Bearing, BeaconDuration)
|
--
|
||||||
self:F({TACANChannel, Message, Bearing, BeaconDuration})
|
function BEACON:AATACAN( TACANChannel, Message, Bearing, BeaconDuration )
|
||||||
|
self:F( { TACANChannel, Message, Bearing, BeaconDuration } )
|
||||||
|
|
||||||
local IsValid = true
|
local IsValid = true
|
||||||
|
|
||||||
if not self.Positionable:IsAir() then
|
if not self.Positionable:IsAir() then
|
||||||
self:E({"The POSITIONABLE you want to attach the AA Tacan Beacon is not an aircraft ! The BEACON is not emitting", self.Positionable})
|
self:E( { "The POSITIONABLE you want to attach the AA TACAN Beacon is not an aircraft! The BEACON is not emitting", self.Positionable } )
|
||||||
IsValid = false
|
IsValid = false
|
||||||
end
|
end
|
||||||
|
|
||||||
local Frequency = self:_TACANToFrequency(TACANChannel, "Y")
|
local Frequency = self:_TACANToFrequency( TACANChannel, "Y" )
|
||||||
if not Frequency then
|
if not Frequency then
|
||||||
self:E({"The passed TACAN channel is invalid, the BEACON is not emitting"})
|
self:E( { "The passed TACAN channel is invalid, the BEACON is not emitting" } )
|
||||||
IsValid = false
|
IsValid = false
|
||||||
end
|
end
|
||||||
|
|
||||||
-- I'm using the beacon type 4 (BEACON_TYPE_TACAN). For System, I'm using 5 (TACAN_TANKER_MODE_Y) if the bearing shows its bearing
|
-- I'm using the beacon type 4 (BEACON_TYPE_TACAN). For System, I'm using 5 (TACAN_TANKER_MODE_Y) if the bearing shows its bearing
|
||||||
-- or 14 (TACAN_AA_MODE_Y) if it does not
|
-- or 14 (TACAN_AA_MODE_Y) if it does not
|
||||||
local System
|
local System
|
||||||
@@ -275,27 +278,26 @@ function BEACON:AATACAN(TACANChannel, Message, Bearing, BeaconDuration)
|
|||||||
else
|
else
|
||||||
System = 14
|
System = 14
|
||||||
end
|
end
|
||||||
|
|
||||||
if IsValid then -- Starts the BEACON
|
if IsValid then -- Starts the BEACON
|
||||||
self:T2({"AA TACAN BEACON started !"})
|
self:T2( { "AA TACAN BEACON started !" } )
|
||||||
self.Positionable:SetCommand({
|
self.Positionable:SetCommand( {
|
||||||
id = "ActivateBeacon",
|
id = "ActivateBeacon",
|
||||||
params = {
|
params = {
|
||||||
type = 4,
|
type = 4,
|
||||||
system = System,
|
system = System,
|
||||||
callsign = Message,
|
callsign = Message,
|
||||||
frequency = Frequency,
|
frequency = Frequency,
|
||||||
}
|
},
|
||||||
})
|
} )
|
||||||
|
|
||||||
if BeaconDuration then -- Schedule the stop of the BEACON if asked by the MD
|
if BeaconDuration then -- Schedule the stop of the BEACON if asked by the MD
|
||||||
SCHEDULER:New(nil,
|
SCHEDULER:New( nil, function()
|
||||||
function()
|
|
||||||
self:StopAATACAN()
|
self:StopAATACAN()
|
||||||
end, {}, BeaconDuration)
|
end, {}, BeaconDuration )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -305,21 +307,19 @@ end
|
|||||||
function BEACON:StopAATACAN()
|
function BEACON:StopAATACAN()
|
||||||
self:F()
|
self:F()
|
||||||
if not self.Positionable then
|
if not self.Positionable then
|
||||||
self:E({"Start the beacon first before stoping it !"})
|
self:E( { "Start the beacon first before stopping it!" } )
|
||||||
else
|
else
|
||||||
self.Positionable:SetCommand({
|
self.Positionable:SetCommand( {
|
||||||
id = 'DeactivateBeacon',
|
id = 'DeactivateBeacon',
|
||||||
params = {
|
params = {},
|
||||||
}
|
} )
|
||||||
})
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Activates a general purpose Radio Beacon
|
||||||
--- Activates a general pupose Radio Beacon
|
|
||||||
-- This uses the very generic singleton function "trigger.action.radioTransmission()" provided by DCS to broadcast a sound file on a specific frequency.
|
-- This uses the very generic singleton function "trigger.action.radioTransmission()" provided by DCS to broadcast a sound file on a specific frequency.
|
||||||
-- Although any frequency could be used, only 2 DCS Modules can home on radio beacons at the time of writing : the Huey and the Mi-8.
|
-- Although any frequency could be used, only 2 DCS Modules can home on radio beacons at the time of writing : the Huey and the Mi-8.
|
||||||
-- They can home in on these specific frequencies :
|
-- They can home in on these specific frequencies :
|
||||||
-- * **Mi8**
|
-- * **Mi8**
|
||||||
-- * R-828 -> 20-60MHz
|
-- * R-828 -> 20-60MHz
|
||||||
-- * ARKUD -> 100-150MHz (canal 1 : 114166, canal 2 : 114333, canal 3 : 114583, canal 4 : 121500, canal 5 : 123100, canal 6 : 124100) AM
|
-- * ARKUD -> 100-150MHz (canal 1 : 114166, canal 2 : 114333, canal 3 : 114583, canal 4 : 121500, canal 5 : 123100, canal 6 : 124100) AM
|
||||||
@@ -342,55 +342,54 @@ end
|
|||||||
--
|
--
|
||||||
-- -- Set the beacon and start it
|
-- -- Set the beacon and start it
|
||||||
-- UnitBeacon:RadioBeacon("MySoundFileSOS.ogg", 40, radio.modulation.FM, 20, 5*60)
|
-- UnitBeacon:RadioBeacon("MySoundFileSOS.ogg", 40, radio.modulation.FM, 20, 5*60)
|
||||||
function BEACON:RadioBeacon(FileName, Frequency, Modulation, Power, BeaconDuration)
|
function BEACON:RadioBeacon( FileName, Frequency, Modulation, Power, BeaconDuration )
|
||||||
self:F({FileName, Frequency, Modulation, Power, BeaconDuration})
|
self:F( { FileName, Frequency, Modulation, Power, BeaconDuration } )
|
||||||
local IsValid = false
|
local IsValid = false
|
||||||
|
|
||||||
-- Check the filename
|
-- Check the filename
|
||||||
if type(FileName) == "string" then
|
if type( FileName ) == "string" then
|
||||||
if FileName:find(".ogg") or FileName:find(".wav") then
|
if FileName:find( ".ogg" ) or FileName:find( ".wav" ) then
|
||||||
if not FileName:find("l10n/DEFAULT/") then
|
if not FileName:find( "l10n/DEFAULT/" ) then
|
||||||
FileName = "l10n/DEFAULT/" .. FileName
|
FileName = "l10n/DEFAULT/" .. FileName
|
||||||
end
|
end
|
||||||
IsValid = true
|
IsValid = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if not IsValid then
|
if not IsValid then
|
||||||
self:E({"File name invalid. Maybe something wrong with the extension ? ", FileName})
|
self:E( { "File name invalid. Maybe something wrong with the extension? ", FileName } )
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Check the Frequency
|
-- Check the Frequency
|
||||||
if type(Frequency) ~= "number" and IsValid then
|
if type( Frequency ) ~= "number" and IsValid then
|
||||||
self:E({"Frequency invalid. ", Frequency})
|
self:E( { "Frequency invalid. ", Frequency } )
|
||||||
IsValid = false
|
IsValid = false
|
||||||
end
|
end
|
||||||
Frequency = Frequency * 1000000 -- Conversion to Hz
|
Frequency = Frequency * 1000000 -- Conversion to Hz
|
||||||
|
|
||||||
-- Check the modulation
|
-- Check the modulation
|
||||||
if Modulation ~= radio.modulation.AM and Modulation ~= radio.modulation.FM and IsValid then --TODO Maybe make this future proof if ED decides to add an other modulation ?
|
if Modulation ~= radio.modulation.AM and Modulation ~= radio.modulation.FM and IsValid then -- TODO: Maybe make this future proof if ED decides to add an other modulation ?
|
||||||
self:E({"Modulation is invalid. Use DCS's enum radio.modulation.", Modulation})
|
self:E( { "Modulation is invalid. Use DCS's enum radio.modulation.", Modulation } )
|
||||||
IsValid = false
|
IsValid = false
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Check the Power
|
-- Check the Power
|
||||||
if type(Power) ~= "number" and IsValid then
|
if type( Power ) ~= "number" and IsValid then
|
||||||
self:E({"Power is invalid. ", Power})
|
self:E( { "Power is invalid. ", Power } )
|
||||||
IsValid = false
|
IsValid = false
|
||||||
end
|
end
|
||||||
Power = math.floor(math.abs(Power)) --TODO Find what is the maximum power allowed by DCS and limit power to that
|
Power = math.floor( math.abs( Power ) ) -- TODO: Find what is the maximum power allowed by DCS and limit power to that
|
||||||
|
|
||||||
if IsValid then
|
if IsValid then
|
||||||
self:T2({"Activating Beacon on ", Frequency, Modulation})
|
self:T2( { "Activating Beacon on ", Frequency, Modulation } )
|
||||||
-- Note that this is looped. I have to give this transmission a unique name, I use the class ID
|
-- Note that this is looped. I have to give this transmission a unique name, I use the class ID
|
||||||
trigger.action.radioTransmission(FileName, self.Positionable:GetPositionVec3(), Modulation, true, Frequency, Power, tostring(self.ID))
|
trigger.action.radioTransmission( FileName, self.Positionable:GetPositionVec3(), Modulation, true, Frequency, Power, tostring( self.ID ) )
|
||||||
|
|
||||||
if BeaconDuration then -- Schedule the stop of the BEACON if asked by the MD
|
if BeaconDuration then -- Schedule the stop of the BEACON if asked by the MD
|
||||||
SCHEDULER:New( nil,
|
SCHEDULER:New( nil, function()
|
||||||
function()
|
self:StopRadioBeacon()
|
||||||
self:StopRadioBeacon()
|
end, {}, BeaconDuration )
|
||||||
end, {}, BeaconDuration)
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Stops the AA TACAN BEACON
|
--- Stops the AA TACAN BEACON
|
||||||
@@ -399,7 +398,7 @@ end
|
|||||||
function BEACON:StopRadioBeacon()
|
function BEACON:StopRadioBeacon()
|
||||||
self:F()
|
self:F()
|
||||||
-- The unique name of the transmission is the class ID
|
-- The unique name of the transmission is the class ID
|
||||||
trigger.action.stopRadioTransmission(tostring(self.ID))
|
trigger.action.stopRadioTransmission( tostring( self.ID ) )
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -407,26 +406,26 @@ end
|
|||||||
-- @param #BEACON self
|
-- @param #BEACON self
|
||||||
-- @param #number TACANChannel
|
-- @param #number TACANChannel
|
||||||
-- @param #string TACANMode
|
-- @param #string TACANMode
|
||||||
-- @return #number Frequecy
|
-- @return #number Frequency
|
||||||
-- @return #nil if parameters are invalid
|
-- @return #nil if parameters are invalid
|
||||||
function BEACON:_TACANToFrequency(TACANChannel, TACANMode)
|
function BEACON:_TACANToFrequency( TACANChannel, TACANMode )
|
||||||
self:F3({TACANChannel, TACANMode})
|
self:F3( { TACANChannel, TACANMode } )
|
||||||
|
|
||||||
if type(TACANChannel) ~= "number" then
|
if type( TACANChannel ) ~= "number" then
|
||||||
if TACANMode ~= "X" and TACANMode ~= "Y" then
|
if TACANMode ~= "X" and TACANMode ~= "Y" then
|
||||||
return nil -- error in arguments
|
return nil -- error in arguments
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- This code is largely based on ED's code, in DCS World\Scripts\World\Radio\BeaconTypes.lua, line 137.
|
-- This code is largely based on ED's code, in DCS World\Scripts\World\Radio\BeaconTypes.lua, line 137.
|
||||||
-- I have no idea what it does but it seems to work
|
-- I have no idea what it does but it seems to work
|
||||||
local A = 1151 -- 'X', channel >= 64
|
local A = 1151 -- 'X', channel >= 64
|
||||||
local B = 64 -- channel >= 64
|
local B = 64 -- channel >= 64
|
||||||
|
|
||||||
if TACANChannel < 64 then
|
if TACANChannel < 64 then
|
||||||
B = 1
|
B = 1
|
||||||
end
|
end
|
||||||
|
|
||||||
if TACANMode == 'Y' then
|
if TACANMode == 'Y' then
|
||||||
A = 1025
|
A = 1025
|
||||||
if TACANChannel < 64 then
|
if TACANChannel < 64 then
|
||||||
@@ -437,6 +436,6 @@ function BEACON:_TACANToFrequency(TACANChannel, TACANMode)
|
|||||||
A = 962
|
A = 962
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return (A + TACANChannel - B) * 1000000
|
return (A + TACANChannel - B) * 1000000
|
||||||
end
|
end
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -14,7 +14,7 @@
|
|||||||
-- 
|
-- 
|
||||||
--
|
--
|
||||||
-- Within a running mission, various DCS events occur. Units are dynamically created, crash, die, shoot stuff, get hit etc.
|
-- Within a running mission, various DCS events occur. Units are dynamically created, crash, die, shoot stuff, get hit etc.
|
||||||
-- This module provides a mechanism to dispatch those events occuring within your running mission, to the different objects orchestrating your mission.
|
-- This module provides a mechanism to dispatch those events occurring within your running mission, to the different objects orchestrating your mission.
|
||||||
--
|
--
|
||||||
-- 
|
-- 
|
||||||
--
|
--
|
||||||
@@ -141,7 +141,6 @@
|
|||||||
-- EventData.IniUnit:SmokeGreen()
|
-- EventData.IniUnit:SmokeGreen()
|
||||||
-- end
|
-- end
|
||||||
--
|
--
|
||||||
--
|
|
||||||
-- Find below an overview which events populate which information categories:
|
-- Find below an overview which events populate which information categories:
|
||||||
--
|
--
|
||||||
-- 
|
-- 
|
||||||
@@ -172,7 +171,6 @@
|
|||||||
-- @module Core.Event
|
-- @module Core.Event
|
||||||
-- @image Core_Event.JPG
|
-- @image Core_Event.JPG
|
||||||
|
|
||||||
|
|
||||||
--- @type EVENT
|
--- @type EVENT
|
||||||
-- @field #EVENT.Events Events
|
-- @field #EVENT.Events Events
|
||||||
-- @extends Core.Base#BASE
|
-- @extends Core.Base#BASE
|
||||||
@@ -194,7 +192,6 @@ world.event.S_EVENT_DELETE_ZONE_GOAL = world.event.S_EVENT_MAX + 1005
|
|||||||
world.event.S_EVENT_REMOVE_UNIT = world.event.S_EVENT_MAX + 1006
|
world.event.S_EVENT_REMOVE_UNIT = world.event.S_EVENT_MAX + 1006
|
||||||
world.event.S_EVENT_PLAYER_ENTER_AIRCRAFT = world.event.S_EVENT_MAX + 1007
|
world.event.S_EVENT_PLAYER_ENTER_AIRCRAFT = world.event.S_EVENT_MAX + 1007
|
||||||
|
|
||||||
|
|
||||||
--- The different types of events supported by MOOSE.
|
--- The different types of events supported by MOOSE.
|
||||||
-- Use this structure to subscribe to events using the @{Core.Base#BASE.HandleEvent}() method.
|
-- Use this structure to subscribe to events using the @{Core.Base#BASE.HandleEvent}() method.
|
||||||
-- @type EVENTS
|
-- @type EVENTS
|
||||||
@@ -227,13 +224,13 @@ EVENTS = {
|
|||||||
MarkChange = world.event.S_EVENT_MARK_CHANGE,
|
MarkChange = world.event.S_EVENT_MARK_CHANGE,
|
||||||
MarkRemoved = world.event.S_EVENT_MARK_REMOVED,
|
MarkRemoved = world.event.S_EVENT_MARK_REMOVED,
|
||||||
-- Moose Events
|
-- Moose Events
|
||||||
NewCargo = world.event.S_EVENT_NEW_CARGO,
|
NewCargo = world.event.S_EVENT_NEW_CARGO,
|
||||||
DeleteCargo = world.event.S_EVENT_DELETE_CARGO,
|
DeleteCargo = world.event.S_EVENT_DELETE_CARGO,
|
||||||
NewZone = world.event.S_EVENT_NEW_ZONE,
|
NewZone = world.event.S_EVENT_NEW_ZONE,
|
||||||
DeleteZone = world.event.S_EVENT_DELETE_ZONE,
|
DeleteZone = world.event.S_EVENT_DELETE_ZONE,
|
||||||
NewZoneGoal = world.event.S_EVENT_NEW_ZONE_GOAL,
|
NewZoneGoal = world.event.S_EVENT_NEW_ZONE_GOAL,
|
||||||
DeleteZoneGoal = world.event.S_EVENT_DELETE_ZONE_GOAL,
|
DeleteZoneGoal = world.event.S_EVENT_DELETE_ZONE_GOAL,
|
||||||
RemoveUnit = world.event.S_EVENT_REMOVE_UNIT,
|
RemoveUnit = world.event.S_EVENT_REMOVE_UNIT,
|
||||||
PlayerEnterAircraft = world.event.S_EVENT_PLAYER_ENTER_AIRCRAFT,
|
PlayerEnterAircraft = world.event.S_EVENT_PLAYER_ENTER_AIRCRAFT,
|
||||||
-- Added with DCS 2.5.6
|
-- Added with DCS 2.5.6
|
||||||
DetailedFailure = world.event.S_EVENT_DETAILED_FAILURE or -1, --We set this to -1 for backward compatibility to DCS 2.5.5 and earlier
|
DetailedFailure = world.event.S_EVENT_DETAILED_FAILURE or -1, --We set this to -1 for backward compatibility to DCS 2.5.5 and earlier
|
||||||
@@ -304,8 +301,6 @@ EVENTS = {
|
|||||||
-- @field Core.ZONE#ZONE Zone The zone object.
|
-- @field Core.ZONE#ZONE Zone The zone object.
|
||||||
-- @field #string ZoneName The name of the zone.
|
-- @field #string ZoneName The name of the zone.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
local _EVENTMETA = {
|
local _EVENTMETA = {
|
||||||
[world.event.S_EVENT_SHOT] = {
|
[world.event.S_EVENT_SHOT] = {
|
||||||
Order = 1,
|
Order = 1,
|
||||||
@@ -562,7 +557,6 @@ local _EVENTMETA = {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
--- The Events structure
|
--- The Events structure
|
||||||
-- @type EVENT.Events
|
-- @type EVENT.Events
|
||||||
-- @field #number IniUnit
|
-- @field #number IniUnit
|
||||||
@@ -576,12 +570,11 @@ function EVENT:New()
|
|||||||
local self = BASE:Inherit( self, BASE:New() )
|
local self = BASE:Inherit( self, BASE:New() )
|
||||||
|
|
||||||
-- Add world event handler.
|
-- Add world event handler.
|
||||||
self.EventHandler = world.addEventHandler(self)
|
self.EventHandler = world.addEventHandler( self )
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Initializes the Events structure for the event.
|
--- Initializes the Events structure for the event.
|
||||||
-- @param #EVENT self
|
-- @param #EVENT self
|
||||||
-- @param DCS#world.event EventID Event ID.
|
-- @param DCS#world.event EventID Event ID.
|
||||||
@@ -595,7 +588,7 @@ function EVENT:Init( EventID, EventClass )
|
|||||||
self.Events[EventID] = {}
|
self.Events[EventID] = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Each event has a subtable of EventClasses, ordered by EventPriority.
|
-- Each event has a sub-table of EventClasses, ordered by EventPriority.
|
||||||
local EventPriority = EventClass:GetEventPriority()
|
local EventPriority = EventClass:GetEventPriority()
|
||||||
|
|
||||||
if not self.Events[EventID][EventPriority] then
|
if not self.Events[EventID][EventPriority] then
|
||||||
@@ -603,7 +596,7 @@ function EVENT:Init( EventID, EventClass )
|
|||||||
end
|
end
|
||||||
|
|
||||||
if not self.Events[EventID][EventPriority][EventClass] then
|
if not self.Events[EventID][EventPriority][EventClass] then
|
||||||
self.Events[EventID][EventPriority][EventClass] = {}
|
self.Events[EventID][EventPriority][EventClass] = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
return self.Events[EventID][EventPriority][EventClass]
|
return self.Events[EventID][EventPriority][EventClass]
|
||||||
@@ -614,7 +607,7 @@ end
|
|||||||
-- @param Core.Base#BASE EventClass The self instance of the class for which the event is.
|
-- @param Core.Base#BASE EventClass The self instance of the class for which the event is.
|
||||||
-- @param DCS#world.event EventID Event ID.
|
-- @param DCS#world.event EventID Event ID.
|
||||||
-- @return #EVENT self
|
-- @return #EVENT self
|
||||||
function EVENT:RemoveEvent( EventClass, EventID )
|
function EVENT:RemoveEvent( EventClass, EventID )
|
||||||
|
|
||||||
-- Debug info.
|
-- Debug info.
|
||||||
self:F2( { "Removing subscription for class: ", EventClass:GetClassNameAndID() } )
|
self:F2( { "Removing subscription for class: ", EventClass:GetClassNameAndID() } )
|
||||||
@@ -638,7 +631,7 @@ end
|
|||||||
-- @param Core.Base#BASE EventClass The self instance of the class for which the event is.
|
-- @param Core.Base#BASE EventClass The self instance of the class for which the event is.
|
||||||
-- @param DCS#world.event EventID Event ID.
|
-- @param DCS#world.event EventID Event ID.
|
||||||
-- @return #EVENT.Events
|
-- @return #EVENT.Events
|
||||||
function EVENT:Reset( EventObject ) --R2.1
|
function EVENT:Reset( EventObject ) -- R2.1
|
||||||
|
|
||||||
self:F( { "Resetting subscriptions for class: ", EventObject:GetClassNameAndID() } )
|
self:F( { "Resetting subscriptions for class: ", EventObject:GetClassNameAndID() } )
|
||||||
|
|
||||||
@@ -657,12 +650,11 @@ function EVENT:Reset( EventObject ) --R2.1
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Clears all event subscriptions for a @{Core.Base#BASE} derived object.
|
--- Clears all event subscriptions for a @{Core.Base#BASE} derived object.
|
||||||
-- @param #EVENT self
|
-- @param #EVENT self
|
||||||
-- @param Core.Base#BASE EventClass The self class object for which the events are removed.
|
-- @param Core.Base#BASE EventClass The self class object for which the events are removed.
|
||||||
-- @return #EVENT self
|
-- @return #EVENT self
|
||||||
function EVENT:RemoveAll(EventClass)
|
function EVENT:RemoveAll( EventClass )
|
||||||
|
|
||||||
local EventClassName = EventClass:GetClassNameAndID()
|
local EventClassName = EventClass:GetClassNameAndID()
|
||||||
|
|
||||||
@@ -676,8 +668,6 @@ function EVENT:RemoveAll(EventClass)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--- Create an OnDead event handler for a group
|
--- Create an OnDead event handler for a group
|
||||||
-- @param #EVENT self
|
-- @param #EVENT self
|
||||||
-- @param #table EventTemplate
|
-- @param #table EventTemplate
|
||||||
@@ -709,7 +699,6 @@ function EVENT:OnEventGeneric( EventFunction, EventClass, EventID )
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Set a new listener for an `S_EVENT_X` event for a UNIT.
|
--- Set a new listener for an `S_EVENT_X` event for a UNIT.
|
||||||
-- @param #EVENT self
|
-- @param #EVENT self
|
||||||
-- @param #string UnitName The name of the UNIT.
|
-- @param #string UnitName The name of the UNIT.
|
||||||
@@ -797,7 +786,6 @@ do -- OnDead
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
do -- OnLand
|
do -- OnLand
|
||||||
|
|
||||||
--- Create an OnLand event handler for a group
|
--- Create an OnLand event handler for a group
|
||||||
@@ -864,7 +852,7 @@ do -- Event Creation
|
|||||||
id = EVENTS.NewCargo,
|
id = EVENTS.NewCargo,
|
||||||
time = timer.getTime(),
|
time = timer.getTime(),
|
||||||
cargo = Cargo,
|
cargo = Cargo,
|
||||||
}
|
}
|
||||||
|
|
||||||
world.onEvent( Event )
|
world.onEvent( Event )
|
||||||
end
|
end
|
||||||
@@ -879,7 +867,7 @@ do -- Event Creation
|
|||||||
id = EVENTS.DeleteCargo,
|
id = EVENTS.DeleteCargo,
|
||||||
time = timer.getTime(),
|
time = timer.getTime(),
|
||||||
cargo = Cargo,
|
cargo = Cargo,
|
||||||
}
|
}
|
||||||
|
|
||||||
world.onEvent( Event )
|
world.onEvent( Event )
|
||||||
end
|
end
|
||||||
@@ -894,7 +882,7 @@ do -- Event Creation
|
|||||||
id = EVENTS.NewZone,
|
id = EVENTS.NewZone,
|
||||||
time = timer.getTime(),
|
time = timer.getTime(),
|
||||||
zone = Zone,
|
zone = Zone,
|
||||||
}
|
}
|
||||||
|
|
||||||
world.onEvent( Event )
|
world.onEvent( Event )
|
||||||
end
|
end
|
||||||
@@ -909,7 +897,7 @@ do -- Event Creation
|
|||||||
id = EVENTS.DeleteZone,
|
id = EVENTS.DeleteZone,
|
||||||
time = timer.getTime(),
|
time = timer.getTime(),
|
||||||
zone = Zone,
|
zone = Zone,
|
||||||
}
|
}
|
||||||
|
|
||||||
world.onEvent( Event )
|
world.onEvent( Event )
|
||||||
end
|
end
|
||||||
@@ -924,12 +912,11 @@ do -- Event Creation
|
|||||||
id = EVENTS.NewZoneGoal,
|
id = EVENTS.NewZoneGoal,
|
||||||
time = timer.getTime(),
|
time = timer.getTime(),
|
||||||
ZoneGoal = ZoneGoal,
|
ZoneGoal = ZoneGoal,
|
||||||
}
|
}
|
||||||
|
|
||||||
world.onEvent( Event )
|
world.onEvent( Event )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Creation of a ZoneGoal Deletion Event.
|
--- Creation of a ZoneGoal Deletion Event.
|
||||||
-- @param #EVENT self
|
-- @param #EVENT self
|
||||||
-- @param Core.ZoneGoal#ZONE_GOAL ZoneGoal The ZoneGoal created.
|
-- @param Core.ZoneGoal#ZONE_GOAL ZoneGoal The ZoneGoal created.
|
||||||
@@ -940,12 +927,11 @@ do -- Event Creation
|
|||||||
id = EVENTS.DeleteZoneGoal,
|
id = EVENTS.DeleteZoneGoal,
|
||||||
time = timer.getTime(),
|
time = timer.getTime(),
|
||||||
ZoneGoal = ZoneGoal,
|
ZoneGoal = ZoneGoal,
|
||||||
}
|
}
|
||||||
|
|
||||||
world.onEvent( Event )
|
world.onEvent( Event )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Creation of a S_EVENT_PLAYER_ENTER_UNIT Event.
|
--- Creation of a S_EVENT_PLAYER_ENTER_UNIT Event.
|
||||||
-- @param #EVENT self
|
-- @param #EVENT self
|
||||||
-- @param Wrapper.Unit#UNIT PlayerUnit.
|
-- @param Wrapper.Unit#UNIT PlayerUnit.
|
||||||
@@ -955,8 +941,8 @@ do -- Event Creation
|
|||||||
local Event = {
|
local Event = {
|
||||||
id = EVENTS.PlayerEnterUnit,
|
id = EVENTS.PlayerEnterUnit,
|
||||||
time = timer.getTime(),
|
time = timer.getTime(),
|
||||||
initiator = PlayerUnit:GetDCSObject()
|
initiator = PlayerUnit:GetDCSObject(),
|
||||||
}
|
}
|
||||||
|
|
||||||
world.onEvent( Event )
|
world.onEvent( Event )
|
||||||
end
|
end
|
||||||
@@ -970,8 +956,8 @@ do -- Event Creation
|
|||||||
local Event = {
|
local Event = {
|
||||||
id = EVENTS.PlayerEnterAircraft,
|
id = EVENTS.PlayerEnterAircraft,
|
||||||
time = timer.getTime(),
|
time = timer.getTime(),
|
||||||
initiator = PlayerUnit:GetDCSObject()
|
initiator = PlayerUnit:GetDCSObject(),
|
||||||
}
|
}
|
||||||
|
|
||||||
world.onEvent( Event )
|
world.onEvent( Event )
|
||||||
end
|
end
|
||||||
@@ -993,14 +979,13 @@ function EVENT:onEvent( Event )
|
|||||||
return errmsg
|
return errmsg
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Get event meta data.
|
-- Get event meta data.
|
||||||
local EventMeta = _EVENTMETA[Event.id]
|
local EventMeta = _EVENTMETA[Event.id]
|
||||||
|
|
||||||
-- Check if this is a known event?
|
-- Check if this is a known event?
|
||||||
if EventMeta then
|
if EventMeta then
|
||||||
|
|
||||||
if self and self.Events and self.Events[Event.id] and self.MissionEnd==false and (Event.initiator~=nil or (Event.initiator==nil and Event.id~=EVENTS.PlayerLeaveUnit)) then
|
if self and self.Events and self.Events[Event.id] and self.MissionEnd == false and (Event.initiator ~= nil or (Event.initiator == nil and Event.id ~= EVENTS.PlayerLeaveUnit)) then
|
||||||
|
|
||||||
if Event.id and Event.id == EVENTS.MissionEnd then
|
if Event.id and Event.id == EVENTS.MissionEnd then
|
||||||
self.MissionEnd = true
|
self.MissionEnd = true
|
||||||
@@ -1024,9 +1009,9 @@ function EVENT:onEvent( Event )
|
|||||||
if Event.IniDCSGroup and Event.IniDCSGroup:isExist() then
|
if Event.IniDCSGroup and Event.IniDCSGroup:isExist() then
|
||||||
Event.IniDCSGroupName = Event.IniDCSGroup:getName()
|
Event.IniDCSGroupName = Event.IniDCSGroup:getName()
|
||||||
Event.IniGroup = GROUP:FindByName( Event.IniDCSGroupName )
|
Event.IniGroup = GROUP:FindByName( Event.IniDCSGroupName )
|
||||||
--if Event.IniGroup then
|
-- if Event.IniGroup then
|
||||||
Event.IniGroupName = Event.IniDCSGroupName
|
Event.IniGroupName = Event.IniDCSGroupName
|
||||||
--end
|
-- end
|
||||||
end
|
end
|
||||||
Event.IniPlayerName = Event.IniDCSUnit:getPlayerName()
|
Event.IniPlayerName = Event.IniDCSUnit:getPlayerName()
|
||||||
Event.IniCoalition = Event.IniDCSUnit:getCoalition()
|
Event.IniCoalition = Event.IniDCSUnit:getCoalition()
|
||||||
@@ -1036,23 +1021,23 @@ function EVENT:onEvent( Event )
|
|||||||
|
|
||||||
if Event.IniObjectCategory == Object.Category.STATIC then
|
if Event.IniObjectCategory == Object.Category.STATIC then
|
||||||
|
|
||||||
if Event.id==31 then
|
if Event.id == 31 then
|
||||||
|
|
||||||
-- Event.initiator is a Static object representing the pilot. But getName() errors due to DCS bug.
|
-- Event.initiator is a Static object representing the pilot. But getName() errors due to DCS bug.
|
||||||
Event.IniDCSUnit = Event.initiator
|
Event.IniDCSUnit = Event.initiator
|
||||||
local ID=Event.initiator.id_
|
local ID = Event.initiator.id_
|
||||||
Event.IniDCSUnitName = string.format("Ejected Pilot ID %s", tostring(ID))
|
Event.IniDCSUnitName = string.format( "Ejected Pilot ID %s", tostring( ID ) )
|
||||||
Event.IniUnitName = Event.IniDCSUnitName
|
Event.IniUnitName = Event.IniDCSUnitName
|
||||||
Event.IniCoalition = 0
|
Event.IniCoalition = 0
|
||||||
Event.IniCategory = 0
|
Event.IniCategory = 0
|
||||||
Event.IniTypeName = "Ejected Pilot"
|
Event.IniTypeName = "Ejected Pilot"
|
||||||
elseif Event.id == 33 then -- ejection seat discarded
|
elseif Event.id == 33 then -- ejection seat discarded
|
||||||
Event.IniDCSUnit = Event.initiator
|
Event.IniDCSUnit = Event.initiator
|
||||||
local ID=Event.initiator.id_
|
local ID = Event.initiator.id_
|
||||||
Event.IniDCSUnitName = string.format("Ejection Seat ID %s", tostring(ID))
|
Event.IniDCSUnitName = string.format( "Ejection Seat ID %s", tostring( ID ) )
|
||||||
Event.IniUnitName = Event.IniDCSUnitName
|
Event.IniUnitName = Event.IniDCSUnitName
|
||||||
Event.IniCoalition = 0
|
Event.IniCoalition = 0
|
||||||
Event.IniCategory = 0
|
Event.IniCategory = 0
|
||||||
Event.IniTypeName = "Ejection Seat"
|
Event.IniTypeName = "Ejection Seat"
|
||||||
else
|
else
|
||||||
Event.IniDCSUnit = Event.initiator
|
Event.IniDCSUnit = Event.initiator
|
||||||
@@ -1088,7 +1073,7 @@ function EVENT:onEvent( Event )
|
|||||||
Event.IniDCSUnit = Event.initiator
|
Event.IniDCSUnit = Event.initiator
|
||||||
Event.IniDCSUnitName = Event.IniDCSUnit:getName()
|
Event.IniDCSUnitName = Event.IniDCSUnit:getName()
|
||||||
Event.IniUnitName = Event.IniDCSUnitName
|
Event.IniUnitName = Event.IniDCSUnitName
|
||||||
Event.IniUnit = AIRBASE:FindByName(Event.IniDCSUnitName)
|
Event.IniUnit = AIRBASE:FindByName( Event.IniDCSUnitName )
|
||||||
Event.IniCoalition = Event.IniDCSUnit:getCoalition()
|
Event.IniCoalition = Event.IniDCSUnit:getCoalition()
|
||||||
Event.IniCategory = Event.IniDCSUnit:getDesc().category
|
Event.IniCategory = Event.IniDCSUnit:getDesc().category
|
||||||
Event.IniTypeName = Event.IniDCSUnit:getTypeName()
|
Event.IniTypeName = Event.IniDCSUnit:getTypeName()
|
||||||
@@ -1109,9 +1094,9 @@ function EVENT:onEvent( Event )
|
|||||||
if Event.TgtDCSGroup and Event.TgtDCSGroup:isExist() then
|
if Event.TgtDCSGroup and Event.TgtDCSGroup:isExist() then
|
||||||
Event.TgtDCSGroupName = Event.TgtDCSGroup:getName()
|
Event.TgtDCSGroupName = Event.TgtDCSGroup:getName()
|
||||||
Event.TgtGroup = GROUP:FindByName( Event.TgtDCSGroupName )
|
Event.TgtGroup = GROUP:FindByName( Event.TgtDCSGroupName )
|
||||||
--if Event.TgtGroup then
|
-- if Event.TgtGroup then
|
||||||
Event.TgtGroupName = Event.TgtDCSGroupName
|
Event.TgtGroupName = Event.TgtDCSGroupName
|
||||||
--end
|
-- end
|
||||||
end
|
end
|
||||||
Event.TgtPlayerName = Event.TgtDCSUnit:getPlayerName()
|
Event.TgtPlayerName = Event.TgtDCSUnit:getPlayerName()
|
||||||
Event.TgtCoalition = Event.TgtDCSUnit:getCoalition()
|
Event.TgtCoalition = Event.TgtDCSUnit:getCoalition()
|
||||||
@@ -1130,18 +1115,18 @@ function EVENT:onEvent( Event )
|
|||||||
Event.TgtCategory = Event.TgtDCSUnit:getDesc().category
|
Event.TgtCategory = Event.TgtDCSUnit:getDesc().category
|
||||||
Event.TgtTypeName = Event.TgtDCSUnit:getTypeName()
|
Event.TgtTypeName = Event.TgtDCSUnit:getTypeName()
|
||||||
else
|
else
|
||||||
Event.TgtDCSUnitName = string.format("No target object for Event ID %s", tostring(Event.id))
|
Event.TgtDCSUnitName = string.format( "No target object for Event ID %s", tostring( Event.id ) )
|
||||||
Event.TgtUnitName = Event.TgtDCSUnitName
|
Event.TgtUnitName = Event.TgtDCSUnitName
|
||||||
Event.TgtUnit = nil
|
Event.TgtUnit = nil
|
||||||
Event.TgtCoalition = 0
|
Event.TgtCoalition = 0
|
||||||
Event.TgtCategory = 0
|
Event.TgtCategory = 0
|
||||||
if Event.id == 6 then
|
if Event.id == 6 then
|
||||||
Event.TgtTypeName = "Ejected Pilot"
|
Event.TgtTypeName = "Ejected Pilot"
|
||||||
Event.TgtDCSUnitName = string.format("Ejected Pilot ID %s", tostring(Event.IniDCSUnitName))
|
Event.TgtDCSUnitName = string.format( "Ejected Pilot ID %s", tostring( Event.IniDCSUnitName ) )
|
||||||
Event.TgtUnitName = Event.TgtDCSUnitName
|
Event.TgtUnitName = Event.TgtDCSUnitName
|
||||||
elseif Event.id == 33 then
|
elseif Event.id == 33 then
|
||||||
Event.TgtTypeName = "Ejection Seat"
|
Event.TgtTypeName = "Ejection Seat"
|
||||||
Event.TgtDCSUnitName = string.format("Ejection Seat ID %s", tostring(Event.IniDCSUnitName))
|
Event.TgtDCSUnitName = string.format( "Ejection Seat ID %s", tostring( Event.IniDCSUnitName ) )
|
||||||
Event.TgtUnitName = Event.TgtDCSUnitName
|
Event.TgtUnitName = Event.TgtDCSUnitName
|
||||||
else
|
else
|
||||||
Event.TgtTypeName = "Static"
|
Event.TgtTypeName = "Static"
|
||||||
@@ -1167,29 +1152,29 @@ function EVENT:onEvent( Event )
|
|||||||
Event.WeaponCoalition = Event.WeaponUNIT and Event.Weapon:getCoalition()
|
Event.WeaponCoalition = Event.WeaponUNIT and Event.Weapon:getCoalition()
|
||||||
Event.WeaponCategory = Event.WeaponUNIT and Event.Weapon:getDesc().category
|
Event.WeaponCategory = Event.WeaponUNIT and Event.Weapon:getDesc().category
|
||||||
Event.WeaponTypeName = Event.WeaponUNIT and Event.Weapon:getTypeName()
|
Event.WeaponTypeName = Event.WeaponUNIT and Event.Weapon:getTypeName()
|
||||||
--Event.WeaponTgtDCSUnit = Event.Weapon:getTarget()
|
-- Event.WeaponTgtDCSUnit = Event.Weapon:getTarget()
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Place should be given for takeoff and landing events as well as base captured. It should be a DCS airbase.
|
-- Place should be given for takeoff and landing events as well as base captured. It should be a DCS airbase.
|
||||||
if Event.place then
|
if Event.place then
|
||||||
if Event.id==EVENTS.LandingAfterEjection then
|
if Event.id == EVENTS.LandingAfterEjection then
|
||||||
-- Place is here the UNIT of which the pilot ejected.
|
-- Place is here the UNIT of which the pilot ejected.
|
||||||
--local name=Event.place:getName() -- This returns a DCS error "Airbase doesn't exit" :(
|
-- local name=Event.place:getName() -- This returns a DCS error "Airbase doesn't exit" :(
|
||||||
-- However, this is not a big thing, as the aircraft the pilot ejected from is usually long crashed before the ejected pilot touches the ground.
|
-- However, this is not a big thing, as the aircraft the pilot ejected from is usually long crashed before the ejected pilot touches the ground.
|
||||||
--Event.Place=UNIT:Find(Event.place)
|
-- Event.Place=UNIT:Find(Event.place)
|
||||||
else
|
else
|
||||||
Event.Place=AIRBASE:Find(Event.place)
|
Event.Place = AIRBASE:Find( Event.place )
|
||||||
Event.PlaceName=Event.Place:GetName()
|
Event.PlaceName = Event.Place:GetName()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Mark points.
|
-- Mark points.
|
||||||
if Event.idx then
|
if Event.idx then
|
||||||
Event.MarkID=Event.idx
|
Event.MarkID = Event.idx
|
||||||
Event.MarkVec3=Event.pos
|
Event.MarkVec3 = Event.pos
|
||||||
Event.MarkCoordinate=COORDINATE:NewFromVec3(Event.pos)
|
Event.MarkCoordinate = COORDINATE:NewFromVec3( Event.pos )
|
||||||
Event.MarkText=Event.text
|
Event.MarkText = Event.text
|
||||||
Event.MarkCoalition=Event.coalition
|
Event.MarkCoalition = Event.coalition
|
||||||
Event.MarkGroupID = Event.groupID
|
Event.MarkGroupID = Event.groupID
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1218,9 +1203,9 @@ function EVENT:onEvent( Event )
|
|||||||
-- Okay, we got the event from DCS. Now loop the SORTED self.EventSorted[] table for the received Event.id, and for each EventData registered, check if a function needs to be called.
|
-- Okay, we got the event from DCS. Now loop the SORTED self.EventSorted[] table for the received Event.id, and for each EventData registered, check if a function needs to be called.
|
||||||
for EventClass, EventData in pairs( self.Events[Event.id][EventPriority] ) do
|
for EventClass, EventData in pairs( self.Events[Event.id][EventPriority] ) do
|
||||||
|
|
||||||
--if Event.IniObjectCategory ~= Object.Category.STATIC then
|
-- if Event.IniObjectCategory ~= Object.Category.STATIC then
|
||||||
-- self:E( { "Evaluating: ", EventClass:GetClassNameAndID() } )
|
-- self:E( { "Evaluating: ", EventClass:GetClassNameAndID() } )
|
||||||
--end
|
-- end
|
||||||
|
|
||||||
Event.IniGroup = GROUP:FindByName( Event.IniDCSGroupName )
|
Event.IniGroup = GROUP:FindByName( Event.IniDCSGroupName )
|
||||||
Event.TgtGroup = GROUP:FindByName( Event.TgtDCSGroupName )
|
Event.TgtGroup = GROUP:FindByName( Event.TgtDCSGroupName )
|
||||||
@@ -1237,8 +1222,8 @@ function EVENT:onEvent( Event )
|
|||||||
|
|
||||||
local UnitName = EventClass:GetName()
|
local UnitName = EventClass:GetName()
|
||||||
|
|
||||||
if ( EventMeta.Side == "I" and UnitName == Event.IniDCSUnitName ) or
|
if (EventMeta.Side == "I" and UnitName == Event.IniDCSUnitName) or
|
||||||
( EventMeta.Side == "T" and UnitName == Event.TgtDCSUnitName ) then
|
(EventMeta.Side == "T" and UnitName == Event.TgtDCSUnitName) then
|
||||||
|
|
||||||
-- First test if a EventFunction is Set, otherwise search for the default function
|
-- First test if a EventFunction is Set, otherwise search for the default function
|
||||||
if EventData.EventFunction then
|
if EventData.EventFunction then
|
||||||
@@ -1247,15 +1232,14 @@ function EVENT:onEvent( Event )
|
|||||||
self:F( { "Calling EventFunction for UNIT ", EventClass:GetClassNameAndID(), ", Unit ", Event.IniUnitName, EventPriority } )
|
self:F( { "Calling EventFunction for UNIT ", EventClass:GetClassNameAndID(), ", Unit ", Event.IniUnitName, EventPriority } )
|
||||||
end
|
end
|
||||||
|
|
||||||
local Result, Value = xpcall(
|
local Result, Value = xpcall( function()
|
||||||
function()
|
return EventData.EventFunction( EventClass, Event )
|
||||||
return EventData.EventFunction( EventClass, Event )
|
end, ErrorHandler )
|
||||||
end, ErrorHandler )
|
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
-- There is no EventFunction defined, so try to find if a default OnEvent function is defined on the object.
|
-- There is no EventFunction defined, so try to find if a default OnEvent function is defined on the object.
|
||||||
local EventFunction = EventClass[ EventMeta.Event ]
|
local EventFunction = EventClass[EventMeta.Event]
|
||||||
if EventFunction and type( EventFunction ) == "function" then
|
if EventFunction and type( EventFunction ) == "function" then
|
||||||
|
|
||||||
-- Now call the default event function.
|
-- Now call the default event function.
|
||||||
@@ -1263,10 +1247,9 @@ function EVENT:onEvent( Event )
|
|||||||
self:F( { "Calling " .. EventMeta.Event .. " for Class ", EventClass:GetClassNameAndID(), EventPriority } )
|
self:F( { "Calling " .. EventMeta.Event .. " for Class ", EventClass:GetClassNameAndID(), EventPriority } )
|
||||||
end
|
end
|
||||||
|
|
||||||
local Result, Value = xpcall(
|
local Result, Value = xpcall( function()
|
||||||
function()
|
return EventFunction( EventClass, Event )
|
||||||
return EventFunction( EventClass, Event )
|
end, ErrorHandler )
|
||||||
end, ErrorHandler )
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -1290,8 +1273,8 @@ function EVENT:onEvent( Event )
|
|||||||
-- We can get the name of the EventClass, which is now always a GROUP object.
|
-- We can get the name of the EventClass, which is now always a GROUP object.
|
||||||
local GroupName = EventClass:GetName()
|
local GroupName = EventClass:GetName()
|
||||||
|
|
||||||
if ( EventMeta.Side == "I" and GroupName == Event.IniDCSGroupName ) or
|
if (EventMeta.Side == "I" and GroupName == Event.IniDCSGroupName) or
|
||||||
( EventMeta.Side == "T" and GroupName == Event.TgtDCSGroupName ) then
|
(EventMeta.Side == "T" and GroupName == Event.TgtDCSGroupName) then
|
||||||
|
|
||||||
-- First test if a EventFunction is Set, otherwise search for the default function
|
-- First test if a EventFunction is Set, otherwise search for the default function
|
||||||
if EventData.EventFunction then
|
if EventData.EventFunction then
|
||||||
@@ -1300,15 +1283,14 @@ function EVENT:onEvent( Event )
|
|||||||
self:F( { "Calling EventFunction for GROUP ", EventClass:GetClassNameAndID(), ", Unit ", Event.IniUnitName, EventPriority } )
|
self:F( { "Calling EventFunction for GROUP ", EventClass:GetClassNameAndID(), ", Unit ", Event.IniUnitName, EventPriority } )
|
||||||
end
|
end
|
||||||
|
|
||||||
local Result, Value = xpcall(
|
local Result, Value = xpcall( function()
|
||||||
function()
|
return EventData.EventFunction( EventClass, Event, unpack( EventData.Params ) )
|
||||||
return EventData.EventFunction( EventClass, Event, unpack( EventData.Params ) )
|
end, ErrorHandler )
|
||||||
end, ErrorHandler )
|
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
-- There is no EventFunction defined, so try to find if a default OnEvent function is defined on the object.
|
-- There is no EventFunction defined, so try to find if a default OnEvent function is defined on the object.
|
||||||
local EventFunction = EventClass[ EventMeta.Event ]
|
local EventFunction = EventClass[EventMeta.Event]
|
||||||
if EventFunction and type( EventFunction ) == "function" then
|
if EventFunction and type( EventFunction ) == "function" then
|
||||||
|
|
||||||
-- Now call the default event function.
|
-- Now call the default event function.
|
||||||
@@ -1316,16 +1298,15 @@ function EVENT:onEvent( Event )
|
|||||||
self:F( { "Calling " .. EventMeta.Event .. " for GROUP ", EventClass:GetClassNameAndID(), EventPriority } )
|
self:F( { "Calling " .. EventMeta.Event .. " for GROUP ", EventClass:GetClassNameAndID(), EventPriority } )
|
||||||
end
|
end
|
||||||
|
|
||||||
local Result, Value = xpcall(
|
local Result, Value = xpcall( function()
|
||||||
function()
|
return EventFunction( EventClass, Event, unpack( EventData.Params ) )
|
||||||
return EventFunction( EventClass, Event, unpack( EventData.Params ) )
|
end, ErrorHandler )
|
||||||
end, ErrorHandler )
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
-- The EventClass is not alive anymore, we remove it from the EventHandlers...
|
-- The EventClass is not alive anymore, we remove it from the EventHandlers...
|
||||||
--self:RemoveEvent( EventClass, Event.id )
|
-- self:RemoveEvent( EventClass, Event.id )
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
|
||||||
@@ -1340,14 +1321,13 @@ function EVENT:onEvent( Event )
|
|||||||
if Event.IniObjectCategory ~= 3 then
|
if Event.IniObjectCategory ~= 3 then
|
||||||
self:F2( { "Calling EventFunction for Class ", EventClass:GetClassNameAndID(), EventPriority } )
|
self:F2( { "Calling EventFunction for Class ", EventClass:GetClassNameAndID(), EventPriority } )
|
||||||
end
|
end
|
||||||
local Result, Value = xpcall(
|
local Result, Value = xpcall( function()
|
||||||
function()
|
return EventData.EventFunction( EventClass, Event )
|
||||||
return EventData.EventFunction( EventClass, Event )
|
end, ErrorHandler )
|
||||||
end, ErrorHandler )
|
|
||||||
else
|
else
|
||||||
|
|
||||||
-- There is no EventFunction defined, so try to find if a default OnEvent function is defined on the object.
|
-- There is no EventFunction defined, so try to find if a default OnEvent function is defined on the object.
|
||||||
local EventFunction = EventClass[ EventMeta.Event ]
|
local EventFunction = EventClass[EventMeta.Event]
|
||||||
if EventFunction and type( EventFunction ) == "function" then
|
if EventFunction and type( EventFunction ) == "function" then
|
||||||
|
|
||||||
-- Now call the default event function.
|
-- Now call the default event function.
|
||||||
@@ -1355,11 +1335,10 @@ function EVENT:onEvent( Event )
|
|||||||
self:F2( { "Calling " .. EventMeta.Event .. " for Class ", EventClass:GetClassNameAndID(), EventPriority } )
|
self:F2( { "Calling " .. EventMeta.Event .. " for Class ", EventClass:GetClassNameAndID(), EventPriority } )
|
||||||
end
|
end
|
||||||
|
|
||||||
local Result, Value = xpcall(
|
local Result, Value = xpcall( function()
|
||||||
function()
|
local Result, Value = EventFunction( EventClass, Event )
|
||||||
local Result, Value = EventFunction( EventClass, Event )
|
return Result, Value
|
||||||
return Result, Value
|
end, ErrorHandler )
|
||||||
end, ErrorHandler )
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1383,7 +1362,7 @@ function EVENT:onEvent( Event )
|
|||||||
self:T( { EventMeta.Text, Event } )
|
self:T( { EventMeta.Text, Event } )
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
self:E(string.format("WARNING: Could not get EVENTMETA data for event ID=%d! Is this an unknown/new DCS event?", tostring(Event.id)))
|
self:E( string.format( "WARNING: Could not get EVENTMETA data for event ID=%d! Is this an unknown/new DCS event?", tostring( Event.id ) ) )
|
||||||
end
|
end
|
||||||
|
|
||||||
Event = nil
|
Event = nil
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,89 +1,87 @@
|
|||||||
--- **Core** - Models the process to achieve goal(s).
|
--- **Core** - Models the process to achieve goal(s).
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ## Features:
|
-- ## Features:
|
||||||
--
|
--
|
||||||
-- * Define the goal.
|
-- * Define the goal.
|
||||||
-- * Monitor the goal achievement.
|
-- * Monitor the goal achievement.
|
||||||
-- * Manage goal contribution by players.
|
-- * Manage goal contribution by players.
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- Classes that implement a goal achievement, will derive from GOAL to implement the ways how the achievements can be realized.
|
-- Classes that implement a goal achievement, will derive from GOAL to implement the ways how the achievements can be realized.
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ### Author: **FlightControl**
|
-- ### Author: **FlightControl**
|
||||||
-- ### Contributions: **funkyfranky**
|
-- ### Contributions: **funkyfranky**
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- @module Core.Goal
|
-- @module Core.Goal
|
||||||
-- @image Core_Goal.JPG
|
-- @image Core_Goal.JPG
|
||||||
|
|
||||||
|
|
||||||
do -- Goal
|
do -- Goal
|
||||||
|
|
||||||
--- @type GOAL
|
--- @type GOAL
|
||||||
-- @extends Core.Fsm#FSM
|
-- @extends Core.Fsm#FSM
|
||||||
|
|
||||||
|
|
||||||
--- Models processes that have an objective with a defined achievement. Derived classes implement the ways how the achievements can be realized.
|
--- Models processes that have an objective with a defined achievement. Derived classes implement the ways how the achievements can be realized.
|
||||||
--
|
--
|
||||||
-- # 1. GOAL constructor
|
-- # 1. GOAL constructor
|
||||||
--
|
--
|
||||||
-- * @{#GOAL.New}(): Creates a new GOAL object.
|
-- * @{#GOAL.New}(): Creates a new GOAL object.
|
||||||
--
|
--
|
||||||
-- # 2. GOAL is a finite state machine (FSM).
|
-- # 2. GOAL is a finite state machine (FSM).
|
||||||
--
|
--
|
||||||
-- ## 2.1. GOAL States
|
-- ## 2.1. GOAL States
|
||||||
--
|
--
|
||||||
-- * **Pending**: The goal object is in progress.
|
-- * **Pending**: The goal object is in progress.
|
||||||
-- * **Achieved**: The goal objective is Achieved.
|
-- * **Achieved**: The goal objective is Achieved.
|
||||||
--
|
--
|
||||||
-- ## 2.2. GOAL Events
|
-- ## 2.2. GOAL Events
|
||||||
--
|
--
|
||||||
-- * **Achieved**: Set the goal objective to Achieved.
|
-- * **Achieved**: Set the goal objective to Achieved.
|
||||||
--
|
--
|
||||||
-- # 3. Player contributions.
|
-- # 3. Player contributions.
|
||||||
--
|
--
|
||||||
-- Goals are most of the time achieved by players. These player achievements can be registered as part of the goal achievement.
|
-- Goals are most of the time achieved by players. These player achievements can be registered as part of the goal achievement.
|
||||||
-- Use @{#GOAL.AddPlayerContribution}() to add a player contribution to the goal.
|
-- Use @{#GOAL.AddPlayerContribution}() to add a player contribution to the goal.
|
||||||
-- The player contributions are based on a points system, an internal counter per player.
|
-- The player contributions are based on a points system, an internal counter per player.
|
||||||
-- So once the goal has been achieved, the player contributions can be queried using @{#GOAL.GetPlayerContributions}(),
|
-- So once the goal has been achieved, the player contributions can be queried using @{#GOAL.GetPlayerContributions}(),
|
||||||
-- that retrieves all contributions done by the players. For one player, the contribution can be queried using @{#GOAL.GetPlayerContribution}().
|
-- that retrieves all contributions done by the players. For one player, the contribution can be queried using @{#GOAL.GetPlayerContribution}().
|
||||||
-- The total amount of player contributions can be queried using @{#GOAL.GetTotalContributions}().
|
-- The total amount of player contributions can be queried using @{#GOAL.GetTotalContributions}().
|
||||||
--
|
--
|
||||||
-- # 4. Goal achievement.
|
-- # 4. Goal achievement.
|
||||||
--
|
--
|
||||||
-- Once the goal is achieved, the mission designer will need to trigger the goal achievement using the **Achieved** event.
|
-- Once the goal is achieved, the mission designer will need to trigger the goal achievement using the **Achieved** event.
|
||||||
-- The underlying 2 examples will achieve the goals for the `Goal` object:
|
-- The underlying 2 examples will achieve the goals for the `Goal` object:
|
||||||
--
|
--
|
||||||
-- Goal:Achieved() -- Achieve the goal immediately.
|
-- Goal:Achieved() -- Achieve the goal immediately.
|
||||||
-- Goal:__Achieved( 30 ) -- Achieve the goal within 30 seconds.
|
-- Goal:__Achieved( 30 ) -- Achieve the goal within 30 seconds.
|
||||||
--
|
--
|
||||||
-- # 5. Check goal achievement.
|
-- # 5. Check goal achievement.
|
||||||
--
|
--
|
||||||
-- The method @{#GOAL.IsAchieved}() will return true if the goal is achieved (the trigger **Achieved** was executed).
|
-- The method @{#GOAL.IsAchieved}() will return true if the goal is achieved (the trigger **Achieved** was executed).
|
||||||
-- You can use this method to check asynchronously if a goal has been achieved, for example using a scheduler.
|
-- You can use this method to check asynchronously if a goal has been achieved, for example using a scheduler.
|
||||||
--
|
--
|
||||||
-- @field #GOAL
|
-- @field #GOAL
|
||||||
GOAL = {
|
GOAL = {
|
||||||
ClassName = "GOAL",
|
ClassName = "GOAL",
|
||||||
}
|
}
|
||||||
|
|
||||||
--- @field #table GOAL.Players
|
--- @field #table GOAL.Players
|
||||||
GOAL.Players = {}
|
GOAL.Players = {}
|
||||||
|
|
||||||
--- @field #number GOAL.TotalContributions
|
--- @field #number GOAL.TotalContributions
|
||||||
GOAL.TotalContributions = 0
|
GOAL.TotalContributions = 0
|
||||||
|
|
||||||
--- GOAL Constructor.
|
--- GOAL Constructor.
|
||||||
-- @param #GOAL self
|
-- @param #GOAL self
|
||||||
-- @return #GOAL
|
-- @return #GOAL
|
||||||
function GOAL:New()
|
function GOAL:New()
|
||||||
|
|
||||||
local self = BASE:Inherit( self, FSM:New() ) -- #GOAL
|
local self = BASE:Inherit( self, FSM:New() ) -- #GOAL
|
||||||
self:F( {} )
|
self:F( {} )
|
||||||
|
|
||||||
@@ -104,11 +102,10 @@ do -- Goal
|
|||||||
-- @param #string From
|
-- @param #string From
|
||||||
-- @param #string Event
|
-- @param #string Event
|
||||||
-- @param #string To
|
-- @param #string To
|
||||||
|
|
||||||
|
|
||||||
self:SetStartState( "Pending" )
|
self:SetStartState( "Pending" )
|
||||||
self:AddTransition( "*", "Achieved", "Achieved" )
|
self:AddTransition( "*", "Achieved", "Achieved" )
|
||||||
|
|
||||||
--- Achieved Handler OnBefore for GOAL
|
--- Achieved Handler OnBefore for GOAL
|
||||||
-- @function [parent=#GOAL] OnBeforeAchieved
|
-- @function [parent=#GOAL] OnBeforeAchieved
|
||||||
-- @param #GOAL self
|
-- @param #GOAL self
|
||||||
@@ -116,47 +113,44 @@ do -- Goal
|
|||||||
-- @param #string Event
|
-- @param #string Event
|
||||||
-- @param #string To
|
-- @param #string To
|
||||||
-- @return #boolean
|
-- @return #boolean
|
||||||
|
|
||||||
--- Achieved Handler OnAfter for GOAL
|
--- Achieved Handler OnAfter for GOAL
|
||||||
-- @function [parent=#GOAL] OnAfterAchieved
|
-- @function [parent=#GOAL] OnAfterAchieved
|
||||||
-- @param #GOAL self
|
-- @param #GOAL self
|
||||||
-- @param #string From
|
-- @param #string From
|
||||||
-- @param #string Event
|
-- @param #string Event
|
||||||
-- @param #string To
|
-- @param #string To
|
||||||
|
|
||||||
--- Achieved Trigger for GOAL
|
--- Achieved Trigger for GOAL
|
||||||
-- @function [parent=#GOAL] Achieved
|
-- @function [parent=#GOAL] Achieved
|
||||||
-- @param #GOAL self
|
-- @param #GOAL self
|
||||||
|
|
||||||
--- Achieved Asynchronous Trigger for GOAL
|
--- Achieved Asynchronous Trigger for GOAL
|
||||||
-- @function [parent=#GOAL] __Achieved
|
-- @function [parent=#GOAL] __Achieved
|
||||||
-- @param #GOAL self
|
-- @param #GOAL self
|
||||||
-- @param #number Delay
|
-- @param #number Delay
|
||||||
|
|
||||||
self:SetEventPriority( 5 )
|
self:SetEventPriority( 5 )
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Add a new contribution by a player.
|
--- Add a new contribution by a player.
|
||||||
-- @param #GOAL self
|
-- @param #GOAL self
|
||||||
-- @param #string PlayerName The name of the player.
|
-- @param #string PlayerName The name of the player.
|
||||||
function GOAL:AddPlayerContribution( PlayerName )
|
function GOAL:AddPlayerContribution( PlayerName )
|
||||||
self:F({PlayerName})
|
self:F( { PlayerName } )
|
||||||
self.Players[PlayerName] = self.Players[PlayerName] or 0
|
self.Players[PlayerName] = self.Players[PlayerName] or 0
|
||||||
self.Players[PlayerName] = self.Players[PlayerName] + 1
|
self.Players[PlayerName] = self.Players[PlayerName] + 1
|
||||||
self.TotalContributions = self.TotalContributions + 1
|
self.TotalContributions = self.TotalContributions + 1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- @param #GOAL self
|
--- @param #GOAL self
|
||||||
-- @param #number Player contribution.
|
-- @param #number Player contribution.
|
||||||
function GOAL:GetPlayerContribution( PlayerName )
|
function GOAL:GetPlayerContribution( PlayerName )
|
||||||
return self.Players[PlayerName] or 0
|
return self.Players[PlayerName] or 0
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Get the players who contributed to achieve the goal.
|
--- Get the players who contributed to achieve the goal.
|
||||||
-- The result is a list of players, sorted by the name of the players.
|
-- The result is a list of players, sorted by the name of the players.
|
||||||
-- @param #GOAL self
|
-- @param #GOAL self
|
||||||
@@ -165,7 +159,6 @@ do -- Goal
|
|||||||
return self.Players or {}
|
return self.Players or {}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Gets the total contributions that happened to achieve the goal.
|
--- Gets the total contributions that happened to achieve the goal.
|
||||||
-- The result is a number.
|
-- The result is a number.
|
||||||
-- @param #GOAL self
|
-- @param #GOAL self
|
||||||
@@ -173,9 +166,7 @@ do -- Goal
|
|||||||
function GOAL:GetTotalContributions()
|
function GOAL:GetTotalContributions()
|
||||||
return self.TotalContributions or 0
|
return self.TotalContributions or 0
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--- Validates if the goal is achieved.
|
--- Validates if the goal is achieved.
|
||||||
-- @param #GOAL self
|
-- @param #GOAL self
|
||||||
-- @return #boolean true if the goal is achieved.
|
-- @return #boolean true if the goal is achieved.
|
||||||
@@ -183,4 +174,4 @@ do -- Goal
|
|||||||
return self:Is( "Achieved" )
|
return self:Is( "Achieved" )
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,18 +1,18 @@
|
|||||||
--- **Core** - Informs the players using messages during a simulation.
|
--- **Core** - Informs the players using messages during a simulation.
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ## Features:
|
-- ## Features:
|
||||||
--
|
--
|
||||||
-- * A more advanced messaging system using the DCS message system.
|
-- * A more advanced messaging system using the DCS message system.
|
||||||
-- * Time messages.
|
-- * Time messages.
|
||||||
-- * Send messages based on a message type, which has a pre-defined duration that can be tweaked in SETTINGS.
|
-- * Send messages based on a message type, which has a pre-defined duration that can be tweaked in SETTINGS.
|
||||||
-- * Send message to all players.
|
-- * Send message to all players.
|
||||||
-- * Send messages to a coalition.
|
-- * Send messages to a coalition.
|
||||||
-- * Send messages to a specific group.
|
-- * Send messages to a specific group.
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- @module Core.Message
|
-- @module Core.Message
|
||||||
-- @image Core_Message.JPG
|
-- @image Core_Message.JPG
|
||||||
|
|
||||||
@@ -23,14 +23,14 @@
|
|||||||
--- Message System to display Messages to Clients, Coalitions or All.
|
--- Message System to display Messages to Clients, Coalitions or All.
|
||||||
-- Messages are shown on the display panel for an amount of seconds, and will then disappear.
|
-- Messages are shown on the display panel for an amount of seconds, and will then disappear.
|
||||||
-- Messages can contain a category which is indicating the category of the message.
|
-- Messages can contain a category which is indicating the category of the message.
|
||||||
--
|
--
|
||||||
-- ## MESSAGE construction
|
-- ## MESSAGE construction
|
||||||
--
|
--
|
||||||
-- Messages are created with @{#MESSAGE.New}. Note that when the MESSAGE object is created, no message is sent yet.
|
-- Messages are created with @{#MESSAGE.New}. Note that when the MESSAGE object is created, no message is sent yet.
|
||||||
-- To send messages, you need to use the To functions.
|
-- To send messages, you need to use the To functions.
|
||||||
--
|
--
|
||||||
-- ## Send messages to an audience
|
-- ## Send messages to an audience
|
||||||
--
|
--
|
||||||
-- Messages are sent:
|
-- Messages are sent:
|
||||||
--
|
--
|
||||||
-- * To a @{Client} using @{#MESSAGE.ToClient}().
|
-- * To a @{Client} using @{#MESSAGE.ToClient}().
|
||||||
@@ -39,26 +39,26 @@
|
|||||||
-- * To the red coalition using @{#MESSAGE.ToRed}().
|
-- * To the red coalition using @{#MESSAGE.ToRed}().
|
||||||
-- * To the blue coalition using @{#MESSAGE.ToBlue}().
|
-- * To the blue coalition using @{#MESSAGE.ToBlue}().
|
||||||
-- * To all Players using @{#MESSAGE.ToAll}().
|
-- * To all Players using @{#MESSAGE.ToAll}().
|
||||||
--
|
--
|
||||||
-- ## Send conditionally to an audience
|
-- ## Send conditionally to an audience
|
||||||
--
|
--
|
||||||
-- Messages can be sent conditionally to an audience (when a condition is true):
|
-- Messages can be sent conditionally to an audience (when a condition is true):
|
||||||
--
|
--
|
||||||
-- * To all players using @{#MESSAGE.ToAllIf}().
|
-- * To all players using @{#MESSAGE.ToAllIf}().
|
||||||
-- * To a coalition using @{#MESSAGE.ToCoalitionIf}().
|
-- * To a coalition using @{#MESSAGE.ToCoalitionIf}().
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ### Author: **FlightControl**
|
-- ### Author: **FlightControl**
|
||||||
-- ### Contributions:
|
-- ### Contributions:
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- @field #MESSAGE
|
-- @field #MESSAGE
|
||||||
MESSAGE = {
|
MESSAGE = {
|
||||||
ClassName = "MESSAGE",
|
ClassName = "MESSAGE",
|
||||||
MessageCategory = 0,
|
MessageCategory = 0,
|
||||||
MessageID = 0,
|
MessageID = 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Message Types
|
--- Message Types
|
||||||
@@ -68,10 +68,9 @@ MESSAGE.Type = {
|
|||||||
Information = "Information",
|
Information = "Information",
|
||||||
Briefing = "Briefing Report",
|
Briefing = "Briefing Report",
|
||||||
Overview = "Overview Report",
|
Overview = "Overview Report",
|
||||||
Detailed = "Detailed Report"
|
Detailed = "Detailed Report",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
--- Creates a new MESSAGE object. Note that these MESSAGE objects are not yet displayed on the display panel. You must use the functions @{ToClient} or @{ToCoalition} or @{ToAll} to send these Messages to the respective recipients.
|
--- Creates a new MESSAGE object. Note that these MESSAGE objects are not yet displayed on the display panel. You must use the functions @{ToClient} or @{ToCoalition} or @{ToAll} to send these Messages to the respective recipients.
|
||||||
-- @param self
|
-- @param self
|
||||||
-- @param #string MessageText is the text of the Message.
|
-- @param #string MessageText is the text of the Message.
|
||||||
@@ -80,52 +79,52 @@ MESSAGE.Type = {
|
|||||||
-- @param #boolean ClearScreen (optional) Clear all previous messages if true.
|
-- @param #boolean ClearScreen (optional) Clear all previous messages if true.
|
||||||
-- @return #MESSAGE
|
-- @return #MESSAGE
|
||||||
-- @usage
|
-- @usage
|
||||||
-- -- Create a series of new Messages.
|
--
|
||||||
-- -- MessageAll is meant to be sent to all players, for 25 seconds, and is classified as "Score".
|
-- -- Create a series of new Messages.
|
||||||
-- -- MessageRED is meant to be sent to the RED players only, for 10 seconds, and is classified as "End of Mission", with ID "Win".
|
-- -- MessageAll is meant to be sent to all players, for 25 seconds, and is classified as "Score".
|
||||||
-- -- MessageClient1 is meant to be sent to a Client, for 25 seconds, and is classified as "Score", with ID "Score".
|
-- -- MessageRED is meant to be sent to the RED players only, for 10 seconds, and is classified as "End of Mission", with ID "Win".
|
||||||
-- -- MessageClient1 is meant to be sent to a Client, for 25 seconds, and is classified as "Score", with ID "Score".
|
-- -- MessageClient1 is meant to be sent to a Client, for 25 seconds, and is classified as "Score", with ID "Score".
|
||||||
-- MessageAll = MESSAGE:New( "To all Players: BLUE has won! Each player of BLUE wins 50 points!", 25, "End of Mission" )
|
-- -- MessageClient1 is meant to be sent to a Client, for 25 seconds, and is classified as "Score", with ID "Score".
|
||||||
-- MessageRED = MESSAGE:New( "To the RED Players: You receive a penalty because you've killed one of your own units", 25, "Penalty" )
|
-- MessageAll = MESSAGE:New( "To all Players: BLUE has won! Each player of BLUE wins 50 points!", 25, "End of Mission" )
|
||||||
-- MessageClient1 = MESSAGE:New( "Congratulations, you've just hit a target", 25, "Score" )
|
-- MessageRED = MESSAGE:New( "To the RED Players: You receive a penalty because you've killed one of your own units", 25, "Penalty" )
|
||||||
-- MessageClient2 = MESSAGE:New( "Congratulations, you've just killed a target", 25, "Score")
|
-- MessageClient1 = MESSAGE:New( "Congratulations, you've just hit a target", 25, "Score" )
|
||||||
|
-- MessageClient2 = MESSAGE:New( "Congratulations, you've just killed a target", 25, "Score")
|
||||||
|
--
|
||||||
function MESSAGE:New( MessageText, MessageDuration, MessageCategory, ClearScreen )
|
function MESSAGE:New( MessageText, MessageDuration, MessageCategory, ClearScreen )
|
||||||
local self = BASE:Inherit( self, BASE:New() )
|
local self = BASE:Inherit( self, BASE:New() )
|
||||||
self:F( { MessageText, MessageDuration, MessageCategory } )
|
self:F( { MessageText, MessageDuration, MessageCategory } )
|
||||||
|
|
||||||
|
|
||||||
self.MessageType = nil
|
self.MessageType = nil
|
||||||
|
|
||||||
-- When no MessageCategory is given, we don't show it as a title...
|
-- When no MessageCategory is given, we don't show it as a title...
|
||||||
if MessageCategory and MessageCategory ~= "" then
|
if MessageCategory and MessageCategory ~= "" then
|
||||||
if MessageCategory:sub(-1) ~= "\n" then
|
if MessageCategory:sub( -1 ) ~= "\n" then
|
||||||
self.MessageCategory = MessageCategory .. ": "
|
self.MessageCategory = MessageCategory .. ": "
|
||||||
else
|
else
|
||||||
self.MessageCategory = MessageCategory:sub( 1, -2 ) .. ":\n"
|
self.MessageCategory = MessageCategory:sub( 1, -2 ) .. ":\n"
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
self.MessageCategory = ""
|
self.MessageCategory = ""
|
||||||
end
|
end
|
||||||
|
|
||||||
self.ClearScreen=false
|
self.ClearScreen = false
|
||||||
if ClearScreen~=nil then
|
if ClearScreen ~= nil then
|
||||||
self.ClearScreen=ClearScreen
|
self.ClearScreen = ClearScreen
|
||||||
end
|
end
|
||||||
|
|
||||||
self.MessageDuration = MessageDuration or 5
|
self.MessageDuration = MessageDuration or 5
|
||||||
self.MessageTime = timer.getTime()
|
self.MessageTime = timer.getTime()
|
||||||
self.MessageText = MessageText:gsub("^\n","",1):gsub("\n$","",1)
|
self.MessageText = MessageText:gsub( "^\n", "", 1 ):gsub( "\n$", "", 1 )
|
||||||
|
|
||||||
self.MessageSent = false
|
|
||||||
self.MessageGroup = false
|
|
||||||
self.MessageCoalition = false
|
|
||||||
|
|
||||||
return self
|
self.MessageSent = false
|
||||||
|
self.MessageGroup = false
|
||||||
|
self.MessageCoalition = false
|
||||||
|
|
||||||
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Creates a new MESSAGE object of a certain type.
|
||||||
--- Creates a new MESSAGE object of a certain type.
|
-- Note that these MESSAGE objects are not yet displayed on the display panel.
|
||||||
-- Note that these MESSAGE objects are not yet displayed on the display panel.
|
|
||||||
-- You must use the functions @{ToClient} or @{ToCoalition} or @{ToAll} to send these Messages to the respective recipients.
|
-- You must use the functions @{ToClient} or @{ToCoalition} or @{ToAll} to send these Messages to the respective recipients.
|
||||||
-- The message display times are automatically defined based on the timing settings in the @{Settings} menu.
|
-- The message display times are automatically defined based on the timing settings in the @{Settings} menu.
|
||||||
-- @param self
|
-- @param self
|
||||||
@@ -134,83 +133,83 @@ end
|
|||||||
-- @param #boolean ClearScreen (optional) Clear all previous messages.
|
-- @param #boolean ClearScreen (optional) Clear all previous messages.
|
||||||
-- @return #MESSAGE
|
-- @return #MESSAGE
|
||||||
-- @usage
|
-- @usage
|
||||||
|
--
|
||||||
-- MessageAll = MESSAGE:NewType( "To all Players: BLUE has won! Each player of BLUE wins 50 points!", MESSAGE.Type.Information )
|
-- MessageAll = MESSAGE:NewType( "To all Players: BLUE has won! Each player of BLUE wins 50 points!", MESSAGE.Type.Information )
|
||||||
-- MessageRED = MESSAGE:NewType( "To the RED Players: You receive a penalty because you've killed one of your own units", MESSAGE.Type.Information )
|
-- MessageRED = MESSAGE:NewType( "To the RED Players: You receive a penalty because you've killed one of your own units", MESSAGE.Type.Information )
|
||||||
-- MessageClient1 = MESSAGE:NewType( "Congratulations, you've just hit a target", MESSAGE.Type.Update )
|
-- MessageClient1 = MESSAGE:NewType( "Congratulations, you've just hit a target", MESSAGE.Type.Update )
|
||||||
-- MessageClient2 = MESSAGE:NewType( "Congratulations, you've just killed a target", MESSAGE.Type.Update )
|
-- MessageClient2 = MESSAGE:NewType( "Congratulations, you've just killed a target", MESSAGE.Type.Update )
|
||||||
|
--
|
||||||
function MESSAGE:NewType( MessageText, MessageType, ClearScreen )
|
function MESSAGE:NewType( MessageText, MessageType, ClearScreen )
|
||||||
|
|
||||||
local self = BASE:Inherit( self, BASE:New() )
|
local self = BASE:Inherit( self, BASE:New() )
|
||||||
self:F( { MessageText } )
|
self:F( { MessageText } )
|
||||||
|
|
||||||
self.MessageType = MessageType
|
self.MessageType = MessageType
|
||||||
|
|
||||||
self.ClearScreen=false
|
self.ClearScreen = false
|
||||||
if ClearScreen~=nil then
|
if ClearScreen ~= nil then
|
||||||
self.ClearScreen=ClearScreen
|
self.ClearScreen = ClearScreen
|
||||||
end
|
end
|
||||||
|
|
||||||
self.MessageTime = timer.getTime()
|
self.MessageTime = timer.getTime()
|
||||||
self.MessageText = MessageText:gsub("^\n","",1):gsub("\n$","",1)
|
self.MessageText = MessageText:gsub( "^\n", "", 1 ):gsub( "\n$", "", 1 )
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Clears all previous messages from the screen before the new message is displayed. Not that this must come before all functions starting with ToX(), e.g. ToAll(), ToGroup() etc.
|
||||||
|
|
||||||
--- Clears all previous messages from the screen before the new message is displayed. Not that this must come before all functions starting with ToX(), e.g. ToAll(), ToGroup() etc.
|
|
||||||
-- @param #MESSAGE self
|
-- @param #MESSAGE self
|
||||||
-- @return #MESSAGE
|
-- @return #MESSAGE
|
||||||
function MESSAGE:Clear()
|
function MESSAGE:Clear()
|
||||||
self:F()
|
self:F()
|
||||||
self.ClearScreen=true
|
self.ClearScreen = true
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--- Sends a MESSAGE to a Client Group. Note that the Group needs to be defined within the ME with the skillset "Client" or "Player".
|
--- Sends a MESSAGE to a Client Group. Note that the Group needs to be defined within the ME with the skillset "Client" or "Player".
|
||||||
-- @param #MESSAGE self
|
-- @param #MESSAGE self
|
||||||
-- @param Wrapper.Client#CLIENT Client is the Group of the Client.
|
-- @param Wrapper.Client#CLIENT Client is the Group of the Client.
|
||||||
-- @param Core.Settings#SETTINGS Settings Settings used to display the message.
|
-- @param Core.Settings#SETTINGS Settings Settings used to display the message.
|
||||||
-- @return #MESSAGE
|
-- @return #MESSAGE
|
||||||
-- @usage
|
-- @usage
|
||||||
-- -- Send the 2 messages created with the @{New} method to the Client Group.
|
|
||||||
-- -- Note that the Message of MessageClient2 is overwriting the Message of MessageClient1.
|
|
||||||
-- ClientGroup = Group.getByName( "ClientGroup" )
|
|
||||||
--
|
--
|
||||||
-- MessageClient1 = MESSAGE:New( "Congratulations, you've just hit a target", "Score", 25, "Score" ):ToClient( ClientGroup )
|
-- -- Send the 2 messages created with the @{New} method to the Client Group.
|
||||||
-- MessageClient2 = MESSAGE:New( "Congratulations, you've just killed a target", "Score", 25, "Score" ):ToClient( ClientGroup )
|
-- -- Note that the Message of MessageClient2 is overwriting the Message of MessageClient1.
|
||||||
-- or
|
-- ClientGroup = Group.getByName( "ClientGroup" )
|
||||||
-- MESSAGE:New( "Congratulations, you've just hit a target", "Score", 25, "Score" ):ToClient( ClientGroup )
|
--
|
||||||
-- MESSAGE:New( "Congratulations, you've just killed a target", "Score", 25, "Score" ):ToClient( ClientGroup )
|
-- MessageClient1 = MESSAGE:New( "Congratulations, you've just hit a target", "Score", 25, "Score" ):ToClient( ClientGroup )
|
||||||
-- or
|
-- MessageClient2 = MESSAGE:New( "Congratulations, you've just killed a target", "Score", 25, "Score" ):ToClient( ClientGroup )
|
||||||
-- MessageClient1 = MESSAGE:New( "Congratulations, you've just hit a target", "Score", 25, "Score" )
|
-- or
|
||||||
-- MessageClient2 = MESSAGE:New( "Congratulations, you've just killed a target", "Score", 25, "Score" )
|
-- MESSAGE:New( "Congratulations, you've just hit a target", "Score", 25, "Score" ):ToClient( ClientGroup )
|
||||||
-- MessageClient1:ToClient( ClientGroup )
|
-- MESSAGE:New( "Congratulations, you've just killed a target", "Score", 25, "Score" ):ToClient( ClientGroup )
|
||||||
-- MessageClient2:ToClient( ClientGroup )
|
-- or
|
||||||
|
-- MessageClient1 = MESSAGE:New( "Congratulations, you've just hit a target", "Score", 25, "Score" )
|
||||||
|
-- MessageClient2 = MESSAGE:New( "Congratulations, you've just killed a target", "Score", 25, "Score" )
|
||||||
|
-- MessageClient1:ToClient( ClientGroup )
|
||||||
|
-- MessageClient2:ToClient( ClientGroup )
|
||||||
|
--
|
||||||
function MESSAGE:ToClient( Client, Settings )
|
function MESSAGE:ToClient( Client, Settings )
|
||||||
self:F( Client )
|
self:F( Client )
|
||||||
|
|
||||||
if Client and Client:GetClientGroupID() then
|
if Client and Client:GetClientGroupID() then
|
||||||
|
|
||||||
if self.MessageType then
|
if self.MessageType then
|
||||||
local Settings = Settings or ( Client and _DATABASE:GetPlayerSettings( Client:GetPlayerName() ) ) or _SETTINGS -- Core.Settings#SETTINGS
|
local Settings = Settings or (Client and _DATABASE:GetPlayerSettings( Client:GetPlayerName() )) or _SETTINGS -- Core.Settings#SETTINGS
|
||||||
self.MessageDuration = Settings:GetMessageTime( self.MessageType )
|
self.MessageDuration = Settings:GetMessageTime( self.MessageType )
|
||||||
self.MessageCategory = "" -- self.MessageType .. ": "
|
self.MessageCategory = "" -- self.MessageType .. ": "
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.MessageDuration ~= 0 then
|
if self.MessageDuration ~= 0 then
|
||||||
local ClientGroupID = Client:GetClientGroupID()
|
local ClientGroupID = Client:GetClientGroupID()
|
||||||
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.outTextForGroup( ClientGroupID, self.MessageCategory .. self.MessageText:gsub("\n$",""):gsub("\n$",""), self.MessageDuration , self.ClearScreen)
|
trigger.action.outTextForGroup( ClientGroupID, self.MessageCategory .. self.MessageText:gsub( "\n$", "" ):gsub( "\n$", "" ), self.MessageDuration, self.ClearScreen )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Sends a MESSAGE to a Group.
|
--- Sends a MESSAGE to a Group.
|
||||||
-- @param #MESSAGE self
|
-- @param #MESSAGE self
|
||||||
-- @param Wrapper.Group#GROUP Group to which the message is displayed.
|
-- @param Wrapper.Group#GROUP Group to which the message is displayed.
|
||||||
-- @return #MESSAGE Message object.
|
-- @return #MESSAGE Message object.
|
||||||
@@ -218,74 +217,80 @@ function MESSAGE:ToGroup( Group, Settings )
|
|||||||
self:F( Group.GroupName )
|
self:F( Group.GroupName )
|
||||||
|
|
||||||
if Group then
|
if Group then
|
||||||
|
|
||||||
if self.MessageType then
|
if self.MessageType then
|
||||||
local Settings = Settings or ( Group and _DATABASE:GetPlayerSettings( Group:GetPlayerName() ) ) or _SETTINGS -- Core.Settings#SETTINGS
|
local Settings = Settings or (Group and _DATABASE:GetPlayerSettings( Group:GetPlayerName() )) or _SETTINGS -- Core.Settings#SETTINGS
|
||||||
self.MessageDuration = Settings:GetMessageTime( self.MessageType )
|
self.MessageDuration = Settings:GetMessageTime( self.MessageType )
|
||||||
self.MessageCategory = "" -- self.MessageType .. ": "
|
self.MessageCategory = "" -- self.MessageType .. ": "
|
||||||
end
|
end
|
||||||
|
|
||||||
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.outTextForGroup( Group:GetID(), self.MessageCategory .. self.MessageText:gsub("\n$",""):gsub("\n$",""), self.MessageDuration, self.ClearScreen )
|
trigger.action.outTextForGroup( Group:GetID(), self.MessageCategory .. self.MessageText:gsub( "\n$", "" ):gsub( "\n$", "" ), self.MessageDuration, self.ClearScreen )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
--- Sends a MESSAGE to the Blue coalition.
|
--- Sends a MESSAGE to the Blue coalition.
|
||||||
-- @param #MESSAGE self
|
|
||||||
-- @return #MESSAGE
|
|
||||||
-- @usage
|
|
||||||
-- -- Send a message created with the @{New} method to the BLUE coalition.
|
|
||||||
-- MessageBLUE = MESSAGE:New( "To the BLUE Players: You receive a penalty because you've killed one of your own units", "Penalty", 25, "Score" ):ToBlue()
|
|
||||||
-- or
|
|
||||||
-- MESSAGE:New( "To the BLUE Players: You receive a penalty because you've killed one of your own units", "Penalty", 25, "Score" ):ToBlue()
|
|
||||||
-- or
|
|
||||||
-- MessageBLUE = MESSAGE:New( "To the BLUE Players: You receive a penalty because you've killed one of your own units", "Penalty", 25, "Score" )
|
|
||||||
-- MessageBLUE:ToBlue()
|
|
||||||
function MESSAGE:ToBlue()
|
|
||||||
self:F()
|
|
||||||
|
|
||||||
self:ToCoalition( coalition.side.BLUE )
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Sends a MESSAGE to the Red Coalition.
|
|
||||||
-- @param #MESSAGE self
|
-- @param #MESSAGE self
|
||||||
-- @return #MESSAGE
|
-- @return #MESSAGE
|
||||||
-- @usage
|
-- @usage
|
||||||
-- -- Send a message created with the @{New} method to the RED coalition.
|
--
|
||||||
-- MessageRED = MESSAGE:New( "To the RED Players: You receive a penalty because you've killed one of your own units", "Penalty", 25, "Score" ):ToRed()
|
-- -- Send a message created with the @{New} method to the BLUE coalition.
|
||||||
-- or
|
-- MessageBLUE = MESSAGE:New( "To the BLUE Players: You receive a penalty because you've killed one of your own units", "Penalty", 25, "Score" ):ToBlue()
|
||||||
-- MESSAGE:New( "To the RED Players: You receive a penalty because you've killed one of your own units", "Penalty", 25, "Score" ):ToRed()
|
-- or
|
||||||
-- or
|
-- MESSAGE:New( "To the BLUE Players: You receive a penalty because you've killed one of your own units", "Penalty", 25, "Score" ):ToBlue()
|
||||||
-- MessageRED = MESSAGE:New( "To the RED Players: You receive a penalty because you've killed one of your own units", "Penalty", 25, "Score" )
|
-- or
|
||||||
-- MessageRED:ToRed()
|
-- MessageBLUE = MESSAGE:New( "To the BLUE Players: You receive a penalty because you've killed one of your own units", "Penalty", 25, "Score" )
|
||||||
function MESSAGE:ToRed( )
|
-- MessageBLUE:ToBlue()
|
||||||
self:F()
|
--
|
||||||
|
function MESSAGE:ToBlue()
|
||||||
|
self:F()
|
||||||
|
|
||||||
self:ToCoalition( coalition.side.RED )
|
self:ToCoalition( coalition.side.BLUE )
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Sends a MESSAGE to a Coalition.
|
--- Sends a MESSAGE to the Red Coalition.
|
||||||
|
-- @param #MESSAGE self
|
||||||
|
-- @return #MESSAGE
|
||||||
|
-- @usage
|
||||||
|
--
|
||||||
|
-- -- Send a message created with the @{New} method to the RED coalition.
|
||||||
|
-- MessageRED = MESSAGE:New( "To the RED Players: You receive a penalty because you've killed one of your own units", "Penalty", 25, "Score" ):ToRed()
|
||||||
|
-- or
|
||||||
|
-- MESSAGE:New( "To the RED Players: You receive a penalty because you've killed one of your own units", "Penalty", 25, "Score" ):ToRed()
|
||||||
|
-- or
|
||||||
|
-- MessageRED = MESSAGE:New( "To the RED Players: You receive a penalty because you've killed one of your own units", "Penalty", 25, "Score" )
|
||||||
|
-- MessageRED:ToRed()
|
||||||
|
--
|
||||||
|
function MESSAGE:ToRed()
|
||||||
|
self:F()
|
||||||
|
|
||||||
|
self:ToCoalition( coalition.side.RED )
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Sends a MESSAGE to a Coalition.
|
||||||
-- @param #MESSAGE self
|
-- @param #MESSAGE self
|
||||||
-- @param #DCS.coalition.side CoalitionSide @{#DCS.coalition.side} to which the message is displayed.
|
-- @param #DCS.coalition.side CoalitionSide @{#DCS.coalition.side} to which the message is displayed.
|
||||||
-- @param Core.Settings#SETTINGS Settings (Optional) Settings for message display.
|
-- @param Core.Settings#SETTINGS Settings (Optional) Settings for message display.
|
||||||
-- @return #MESSAGE Message object.
|
-- @return #MESSAGE Message object.
|
||||||
-- @usage
|
-- @usage
|
||||||
-- -- Send a message created with the @{New} method to the RED coalition.
|
--
|
||||||
-- MessageRED = MESSAGE:New( "To the RED Players: You receive a penalty because you've killed one of your own units", "Penalty", 25, "Score" ):ToCoalition( coalition.side.RED )
|
-- -- Send a message created with the @{New} method to the RED coalition.
|
||||||
-- or
|
-- MessageRED = MESSAGE:New( "To the RED Players: You receive a penalty because you've killed one of your own units", "Penalty", 25, "Score" ):ToCoalition( coalition.side.RED )
|
||||||
-- MESSAGE:New( "To the RED Players: You receive a penalty because you've killed one of your own units", "Penalty", 25, "Score" ):ToCoalition( coalition.side.RED )
|
-- or
|
||||||
-- or
|
-- MESSAGE:New( "To the RED Players: You receive a penalty because you've killed one of your own units", "Penalty", 25, "Score" ):ToCoalition( coalition.side.RED )
|
||||||
-- MessageRED = MESSAGE:New( "To the RED Players: You receive a penalty because you've killed one of your own units", "Penalty", 25, "Score" )
|
-- or
|
||||||
-- MessageRED:ToCoalition( coalition.side.RED )
|
-- MessageRED = MESSAGE:New( "To the RED Players: You receive a penalty because you've killed one of your own units", "Penalty", 25, "Score" )
|
||||||
|
-- MessageRED:ToCoalition( coalition.side.RED )
|
||||||
|
--
|
||||||
function MESSAGE:ToCoalition( CoalitionSide, Settings )
|
function MESSAGE:ToCoalition( CoalitionSide, Settings )
|
||||||
self:F( CoalitionSide )
|
self:F( CoalitionSide )
|
||||||
|
|
||||||
if self.MessageType then
|
if self.MessageType then
|
||||||
local Settings = Settings or _SETTINGS -- Core.Settings#SETTINGS
|
local Settings = Settings or _SETTINGS -- Core.Settings#SETTINGS
|
||||||
@@ -293,20 +298,20 @@ function MESSAGE:ToCoalition( CoalitionSide, Settings )
|
|||||||
self.MessageCategory = "" -- self.MessageType .. ": "
|
self.MessageCategory = "" -- self.MessageType .. ": "
|
||||||
end
|
end
|
||||||
|
|
||||||
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.MessageText:gsub( "\n$", "" ):gsub( "\n$", "" ), self.MessageDuration, self.ClearScreen )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Sends a MESSAGE to a Coalition if the given Condition is true.
|
--- Sends a MESSAGE to a Coalition if the given Condition is true.
|
||||||
-- @param #MESSAGE self
|
-- @param #MESSAGE self
|
||||||
-- @param CoalitionSide needs to be filled out by the defined structure of the standard scripting engine @{coalition.side}.
|
-- @param CoalitionSide needs to be filled out by the defined structure of the standard scripting engine @{coalition.side}.
|
||||||
-- @param #boolean Condition Sends the message only if the condition is true.
|
-- @param #boolean Condition Sends the message only if the condition is true.
|
||||||
-- @return #MESSAGE self
|
-- @return #MESSAGE self
|
||||||
function MESSAGE:ToCoalitionIf( CoalitionSide, Condition )
|
function MESSAGE:ToCoalitionIf( CoalitionSide, Condition )
|
||||||
self:F( CoalitionSide )
|
self:F( CoalitionSide )
|
||||||
@@ -314,7 +319,7 @@ function MESSAGE:ToCoalitionIf( CoalitionSide, Condition )
|
|||||||
if Condition and Condition == true then
|
if Condition and Condition == true then
|
||||||
self:ToCoalition( CoalitionSide )
|
self:ToCoalition( CoalitionSide )
|
||||||
end
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -323,14 +328,16 @@ end
|
|||||||
-- @param Core.Settings#Settings Settings (Optional) Settings for message display.
|
-- @param Core.Settings#Settings Settings (Optional) Settings for message display.
|
||||||
-- @return #MESSAGE
|
-- @return #MESSAGE
|
||||||
-- @usage
|
-- @usage
|
||||||
-- -- Send a message created to all players.
|
--
|
||||||
-- MessageAll = MESSAGE:New( "To all Players: BLUE has won! Each player of BLUE wins 50 points!", "End of Mission", 25, "Win" ):ToAll()
|
-- -- Send a message created to all players.
|
||||||
-- or
|
-- MessageAll = MESSAGE:New( "To all Players: BLUE has won! Each player of BLUE wins 50 points!", "End of Mission", 25, "Win" ):ToAll()
|
||||||
-- MESSAGE:New( "To all Players: BLUE has won! Each player of BLUE wins 50 points!", "End of Mission", 25, "Win" ):ToAll()
|
-- or
|
||||||
-- or
|
-- MESSAGE:New( "To all Players: BLUE has won! Each player of BLUE wins 50 points!", "End of Mission", 25, "Win" ):ToAll()
|
||||||
-- MessageAll = MESSAGE:New( "To all Players: BLUE has won! Each player of BLUE wins 50 points!", "End of Mission", 25, "Win" )
|
-- or
|
||||||
-- MessageAll:ToAll()
|
-- MessageAll = MESSAGE:New( "To all Players: BLUE has won! Each player of BLUE wins 50 points!", "End of Mission", 25, "Win" )
|
||||||
function MESSAGE:ToAll(Settings)
|
-- MessageAll:ToAll()
|
||||||
|
--
|
||||||
|
function MESSAGE:ToAll( Settings )
|
||||||
self:F()
|
self:F()
|
||||||
|
|
||||||
if self.MessageType then
|
if self.MessageType then
|
||||||
@@ -340,14 +347,13 @@ function MESSAGE:ToAll(Settings)
|
|||||||
end
|
end
|
||||||
|
|
||||||
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.outText( self.MessageCategory .. self.MessageText:gsub("\n$",""):gsub("\n$",""), self.MessageDuration, self.ClearScreen )
|
trigger.action.outText( self.MessageCategory .. self.MessageText:gsub( "\n$", "" ):gsub( "\n$", "" ), self.MessageDuration, self.ClearScreen )
|
||||||
end
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Sends a MESSAGE to all players if the given Condition is true.
|
--- Sends a MESSAGE to all players if the given Condition is true.
|
||||||
-- @param #MESSAGE self
|
-- @param #MESSAGE self
|
||||||
-- @return #MESSAGE
|
-- @return #MESSAGE
|
||||||
@@ -357,5 +363,5 @@ function MESSAGE:ToAllIf( Condition )
|
|||||||
self:ToAll()
|
self:ToAll()
|
||||||
end
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,13 +1,13 @@
|
|||||||
--- **Core** - Provides a handy means to create messages and reports.
|
--- **Core** - Provides a handy means to create messages and reports.
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ## Features:
|
-- ## Features:
|
||||||
--
|
--
|
||||||
-- * Create text blocks that are formatted.
|
-- * Create text blocks that are formatted.
|
||||||
-- * Create automatic indents.
|
-- * Create automatic indents.
|
||||||
-- * Variate the delimiters between reporting lines.
|
-- * Variate the delimiters between reporting lines.
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ### Authors: FlightControl : Design & Programming
|
-- ### Authors: FlightControl : Design & Programming
|
||||||
@@ -15,7 +15,6 @@
|
|||||||
-- @module Core.Report
|
-- @module Core.Report
|
||||||
-- @image Core_Report.JPG
|
-- @image Core_Report.JPG
|
||||||
|
|
||||||
|
|
||||||
--- @type REPORT
|
--- @type REPORT
|
||||||
-- @extends Core.Base#BASE
|
-- @extends Core.Base#BASE
|
||||||
|
|
||||||
@@ -36,7 +35,7 @@ function REPORT:New( Title )
|
|||||||
|
|
||||||
self.Report = {}
|
self.Report = {}
|
||||||
|
|
||||||
self:SetTitle( Title or "" )
|
self:SetTitle( Title or "" )
|
||||||
self:SetIndent( 3 )
|
self:SetIndent( 3 )
|
||||||
|
|
||||||
return self
|
return self
|
||||||
@@ -45,28 +44,26 @@ end
|
|||||||
--- Has the REPORT Text?
|
--- Has the REPORT Text?
|
||||||
-- @param #REPORT self
|
-- @param #REPORT self
|
||||||
-- @return #boolean
|
-- @return #boolean
|
||||||
function REPORT:HasText() --R2.1
|
function REPORT:HasText() -- R2.1
|
||||||
|
|
||||||
return #self.Report > 0
|
return #self.Report > 0
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Set indent of a REPORT.
|
--- Set indent of a REPORT.
|
||||||
-- @param #REPORT self
|
-- @param #REPORT self
|
||||||
-- @param #number Indent
|
-- @param #number Indent
|
||||||
-- @return #REPORT
|
-- @return #REPORT
|
||||||
function REPORT:SetIndent( Indent ) --R2.1
|
function REPORT:SetIndent( Indent ) -- R2.1
|
||||||
self.Indent = Indent
|
self.Indent = Indent
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Add a new line to a REPORT.
|
--- Add a new line to a REPORT.
|
||||||
-- @param #REPORT self
|
-- @param #REPORT self
|
||||||
-- @param #string Text
|
-- @param #string Text
|
||||||
-- @return #REPORT
|
-- @return #REPORT
|
||||||
function REPORT:Add( Text )
|
function REPORT:Add( Text )
|
||||||
self.Report[#self.Report+1] = Text
|
self.Report[#self.Report + 1] = Text
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -76,17 +73,17 @@ end
|
|||||||
-- @param #string Separator (optional) The start of each report line can begin with an optional separator character. This can be a "-", or "#", or "*". You're free to choose what you find the best.
|
-- @param #string Separator (optional) The start of each report line can begin with an optional separator character. This can be a "-", or "#", or "*". You're free to choose what you find the best.
|
||||||
-- @return #REPORT
|
-- @return #REPORT
|
||||||
function REPORT:AddIndent( Text, Separator )
|
function REPORT:AddIndent( Text, Separator )
|
||||||
self.Report[#self.Report+1] = ( ( Separator and Separator .. string.rep( " ", self.Indent - 1 ) ) or string.rep(" ", self.Indent ) ) .. Text:gsub("\n","\n"..string.rep( " ", self.Indent ) )
|
self.Report[#self.Report + 1] = ((Separator and Separator .. string.rep( " ", self.Indent - 1 )) or string.rep( " ", self.Indent )) .. Text:gsub( "\n", "\n" .. string.rep( " ", self.Indent ) )
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Produces the text of the report, taking into account an optional delimeter, which is \n by default.
|
--- Produces the text of the report, taking into account an optional delimiter, which is \n by default.
|
||||||
-- @param #REPORT self
|
-- @param #REPORT self
|
||||||
-- @param #string Delimiter (optional) A delimiter text.
|
-- @param #string Delimiter (optional) A delimiter text.
|
||||||
-- @return #string The report text.
|
-- @return #string The report text.
|
||||||
function REPORT:Text( Delimiter )
|
function REPORT:Text( Delimiter )
|
||||||
Delimiter = Delimiter or "\n"
|
Delimiter = Delimiter or "\n"
|
||||||
local ReportText = ( self.Title ~= "" and self.Title .. Delimiter or self.Title ) .. table.concat( self.Report, Delimiter ) or ""
|
local ReportText = (self.Title ~= "" and self.Title .. Delimiter or self.Title) .. table.concat( self.Report, Delimiter ) or ""
|
||||||
return ReportText
|
return ReportText
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -95,7 +92,7 @@ end
|
|||||||
-- @param #string Title The title of the report.
|
-- @param #string Title The title of the report.
|
||||||
-- @return #REPORT
|
-- @return #REPORT
|
||||||
function REPORT:SetTitle( Title )
|
function REPORT:SetTitle( Title )
|
||||||
self.Title = Title
|
self.Title = Title
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1,36 +1,36 @@
|
|||||||
--- **Core** -- SCHEDULEDISPATCHER dispatches the different schedules.
|
--- **Core** -- SCHEDULEDISPATCHER dispatches the different schedules.
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- Takes care of the creation and dispatching of scheduled functions for SCHEDULER objects.
|
-- Takes care of the creation and dispatching of scheduled functions for SCHEDULER objects.
|
||||||
--
|
--
|
||||||
-- This class is tricky and needs some thorough explanation.
|
-- This class is tricky and needs some thorough explanation.
|
||||||
-- SCHEDULE classes are used to schedule functions for objects, or as persistent objects.
|
-- SCHEDULE classes are used to schedule functions for objects, or as persistent objects.
|
||||||
-- The SCHEDULEDISPATCHER class ensures that:
|
-- The SCHEDULEDISPATCHER class ensures that:
|
||||||
--
|
--
|
||||||
-- - Scheduled functions are planned according the SCHEDULER object parameters.
|
-- - Scheduled functions are planned according the SCHEDULER object parameters.
|
||||||
-- - Scheduled functions are repeated when requested, according the SCHEDULER object parameters.
|
-- - Scheduled functions are repeated when requested, according the SCHEDULER object parameters.
|
||||||
-- - Scheduled functions are automatically removed when the schedule is finished, according the SCHEDULER object parameters.
|
-- - Scheduled functions are automatically removed when the schedule is finished, according the SCHEDULER object parameters.
|
||||||
--
|
--
|
||||||
-- The SCHEDULEDISPATCHER class will manage SCHEDULER object in memory during garbage collection:
|
-- The SCHEDULEDISPATCHER class will manage SCHEDULER object in memory during garbage collection:
|
||||||
--
|
--
|
||||||
-- - When a SCHEDULER object is not attached to another object (that is, it's first :Schedule() parameter is nil), then the SCHEDULER object is _persistent_ within memory.
|
-- - When a SCHEDULER object is not attached to another object (that is, it's first :Schedule() parameter is nil), then the SCHEDULER object is _persistent_ within memory.
|
||||||
-- - When a SCHEDULER object *is* attached to another object, then the SCHEDULER object is _not persistent_ within memory after a garbage collection!
|
-- - When a SCHEDULER object *is* attached to another object, then the SCHEDULER object is _not persistent_ within memory after a garbage collection!
|
||||||
--
|
--
|
||||||
-- The none persistency of SCHEDULERS attached to objects is required to allow SCHEDULER objects to be garbage collectged, when the parent object is also desroyed or nillified and garbage collected.
|
-- The non-persistency of SCHEDULERS attached to objects is required to allow SCHEDULER objects to be garbage collected when the parent object is destroyed, or set to nil and garbage collected.
|
||||||
-- Even when there are pending timer scheduled functions to be executed for the SCHEDULER object,
|
-- Even when there are pending timer scheduled functions to be executed for the SCHEDULER object,
|
||||||
-- these will not be executed anymore when the SCHEDULER object has been destroyed.
|
-- these will not be executed anymore when the SCHEDULER object has been destroyed.
|
||||||
--
|
--
|
||||||
-- The SCHEDULEDISPATCHER allows multiple scheduled functions to be planned and executed for one SCHEDULER object.
|
-- The SCHEDULEDISPATCHER allows multiple scheduled functions to be planned and executed for one SCHEDULER object.
|
||||||
-- The SCHEDULER object therefore keeps a table of "CallID's", which are returned after each planning of a new scheduled function by the SCHEDULEDISPATCHER.
|
-- The SCHEDULER object therefore keeps a table of "CallID's", which are returned after each planning of a new scheduled function by the SCHEDULEDISPATCHER.
|
||||||
-- The SCHEDULER object plans new scheduled functions through the @{Core.Scheduler#SCHEDULER.Schedule}() method.
|
-- The SCHEDULER object plans new scheduled functions through the @{Core.Scheduler#SCHEDULER.Schedule}() method.
|
||||||
-- The Schedule() method returns the CallID that is the reference ID for each planned schedule.
|
-- The Schedule() method returns the CallID that is the reference ID for each planned schedule.
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ### Contributions: -
|
-- ### Contributions: -
|
||||||
-- ### Authors: FlightControl : Design & Programming
|
-- ### Authors: FlightControl : Design & Programming
|
||||||
--
|
--
|
||||||
-- @module Core.ScheduleDispatcher
|
-- @module Core.ScheduleDispatcher
|
||||||
-- @image Core_Schedule_Dispatcher.JPG
|
-- @image Core_Schedule_Dispatcher.JPG
|
||||||
|
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
-- @type SCHEDULEDISPATCHER
|
-- @type SCHEDULEDISPATCHER
|
||||||
-- @field #string ClassName Name of the class.
|
-- @field #string ClassName Name of the class.
|
||||||
-- @field #number CallID Call ID counter.
|
-- @field #number CallID Call ID counter.
|
||||||
-- @field #table PersistentSchedulers Persistant schedulers.
|
-- @field #table PersistentSchedulers Persistent schedulers.
|
||||||
-- @field #table ObjectSchedulers Schedulers that only exist as long as the master object exists.
|
-- @field #table ObjectSchedulers Schedulers that only exist as long as the master object exists.
|
||||||
-- @field #table Schedule Meta table setmetatable( {}, { __mode = "k" } ).
|
-- @field #table Schedule Meta table setmetatable( {}, { __mode = "k" } ).
|
||||||
-- @extends Core.Base#BASE
|
-- @extends Core.Base#BASE
|
||||||
@@ -46,11 +46,11 @@
|
|||||||
--- The SCHEDULEDISPATCHER structure
|
--- The SCHEDULEDISPATCHER structure
|
||||||
-- @type SCHEDULEDISPATCHER
|
-- @type SCHEDULEDISPATCHER
|
||||||
SCHEDULEDISPATCHER = {
|
SCHEDULEDISPATCHER = {
|
||||||
ClassName = "SCHEDULEDISPATCHER",
|
ClassName = "SCHEDULEDISPATCHER",
|
||||||
CallID = 0,
|
CallID = 0,
|
||||||
PersistentSchedulers = {},
|
PersistentSchedulers = {},
|
||||||
ObjectSchedulers = {},
|
ObjectSchedulers = {},
|
||||||
Schedule = nil,
|
Schedule = nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Player data table holding all important parameters of each player.
|
--- Player data table holding all important parameters of each player.
|
||||||
@@ -58,7 +58,7 @@ SCHEDULEDISPATCHER = {
|
|||||||
-- @field #function Function The schedule function to be called.
|
-- @field #function Function The schedule function to be called.
|
||||||
-- @field #table Arguments Schedule function arguments.
|
-- @field #table Arguments Schedule function arguments.
|
||||||
-- @field #number Start Start time in seconds.
|
-- @field #number Start Start time in seconds.
|
||||||
-- @field #number Repeat Repeat time intervall in seconds.
|
-- @field #number Repeat Repeat time interval in seconds.
|
||||||
-- @field #number Randomize Randomization factor [0,1].
|
-- @field #number Randomize Randomization factor [0,1].
|
||||||
-- @field #number Stop Stop time in seconds.
|
-- @field #number Stop Stop time in seconds.
|
||||||
-- @field #number StartTime Time in seconds when the scheduler is created.
|
-- @field #number StartTime Time in seconds when the scheduler is created.
|
||||||
@@ -77,7 +77,7 @@ end
|
|||||||
|
|
||||||
--- Add a Schedule to the ScheduleDispatcher.
|
--- Add a Schedule to the ScheduleDispatcher.
|
||||||
-- The development of this method was really tidy.
|
-- The development of this method was really tidy.
|
||||||
-- It is constructed as such that a garbage collection is executed on the weak tables, when the Scheduler is nillified.
|
-- It is constructed as such that a garbage collection is executed on the weak tables, when the Scheduler is set to nil.
|
||||||
-- Nothing of this code should be modified without testing it thoroughly.
|
-- Nothing of this code should be modified without testing it thoroughly.
|
||||||
-- @param #SCHEDULEDISPATCHER self
|
-- @param #SCHEDULEDISPATCHER self
|
||||||
-- @param Core.Scheduler#SCHEDULER Scheduler Scheduler object.
|
-- @param Core.Scheduler#SCHEDULER Scheduler Scheduler object.
|
||||||
@@ -85,7 +85,7 @@ end
|
|||||||
-- @param #table ScheduleArguments Table of arguments passed to the ScheduleFunction.
|
-- @param #table ScheduleArguments Table of arguments passed to the ScheduleFunction.
|
||||||
-- @param #number Start Start time in seconds.
|
-- @param #number Start Start time in seconds.
|
||||||
-- @param #number Repeat Repeat interval in seconds.
|
-- @param #number Repeat Repeat interval in seconds.
|
||||||
-- @param #number Randomize Radomization factor [0,1].
|
-- @param #number Randomize Randomization factor [0,1].
|
||||||
-- @param #number Stop Stop time in seconds.
|
-- @param #number Stop Stop time in seconds.
|
||||||
-- @param #number TraceLevel Trace level [0,3].
|
-- @param #number TraceLevel Trace level [0,3].
|
||||||
-- @param Core.Fsm#FSM Fsm Finite state model.
|
-- @param Core.Fsm#FSM Fsm Finite state model.
|
||||||
@@ -95,39 +95,38 @@ function SCHEDULEDISPATCHER:AddSchedule( Scheduler, ScheduleFunction, ScheduleAr
|
|||||||
|
|
||||||
-- Increase counter.
|
-- Increase counter.
|
||||||
self.CallID = self.CallID + 1
|
self.CallID = self.CallID + 1
|
||||||
|
|
||||||
-- Create ID.
|
-- Create ID.
|
||||||
local CallID = self.CallID .. "#" .. ( Scheduler.MasterObject and Scheduler.MasterObject.GetClassNameAndID and Scheduler.MasterObject:GetClassNameAndID() or "" ) or ""
|
local CallID = self.CallID .. "#" .. (Scheduler.MasterObject and Scheduler.MasterObject.GetClassNameAndID and Scheduler.MasterObject:GetClassNameAndID() or "") or ""
|
||||||
|
|
||||||
self:T2(string.format("Adding schedule #%d CallID=%s", self.CallID, CallID))
|
self:T2( string.format( "Adding schedule #%d CallID=%s", self.CallID, CallID ) )
|
||||||
|
|
||||||
-- Initialize PersistentSchedulers
|
-- Initialize PersistentSchedulers
|
||||||
self.PersistentSchedulers = self.PersistentSchedulers or {}
|
self.PersistentSchedulers = self.PersistentSchedulers or {}
|
||||||
|
|
||||||
-- Initialize the ObjectSchedulers array, which is a weakly coupled table.
|
-- Initialize the ObjectSchedulers array, which is a weakly coupled table.
|
||||||
-- If the object used as the key is nil, then the garbage collector will remove the item from the Functions array.
|
-- If the object used as the key is nil, then the garbage collector will remove the item from the Functions array.
|
||||||
self.ObjectSchedulers = self.ObjectSchedulers or setmetatable( {}, { __mode = "v" } )
|
self.ObjectSchedulers = self.ObjectSchedulers or setmetatable( {}, { __mode = "v" } )
|
||||||
|
|
||||||
if Scheduler.MasterObject then
|
if Scheduler.MasterObject then
|
||||||
self.ObjectSchedulers[CallID] = Scheduler
|
self.ObjectSchedulers[CallID] = Scheduler
|
||||||
self:F3( { CallID = CallID, ObjectScheduler = tostring(self.ObjectSchedulers[CallID]), MasterObject = tostring(Scheduler.MasterObject) } )
|
self:F3( { CallID = CallID, ObjectScheduler = tostring( self.ObjectSchedulers[CallID] ), MasterObject = tostring( Scheduler.MasterObject ) } )
|
||||||
else
|
else
|
||||||
self.PersistentSchedulers[CallID] = Scheduler
|
self.PersistentSchedulers[CallID] = Scheduler
|
||||||
self:F3( { CallID = CallID, PersistentScheduler = self.PersistentSchedulers[CallID] } )
|
self:F3( { CallID = CallID, PersistentScheduler = self.PersistentSchedulers[CallID] } )
|
||||||
end
|
end
|
||||||
|
|
||||||
self.Schedule = self.Schedule or setmetatable( {}, { __mode = "k" } )
|
self.Schedule = self.Schedule or setmetatable( {}, { __mode = "k" } )
|
||||||
self.Schedule[Scheduler] = self.Schedule[Scheduler] or {}
|
self.Schedule[Scheduler] = self.Schedule[Scheduler] or {}
|
||||||
self.Schedule[Scheduler][CallID] = {} --#SCHEDULEDISPATCHER.ScheduleData
|
self.Schedule[Scheduler][CallID] = {} -- #SCHEDULEDISPATCHER.ScheduleData
|
||||||
self.Schedule[Scheduler][CallID].Function = ScheduleFunction
|
self.Schedule[Scheduler][CallID].Function = ScheduleFunction
|
||||||
self.Schedule[Scheduler][CallID].Arguments = ScheduleArguments
|
self.Schedule[Scheduler][CallID].Arguments = ScheduleArguments
|
||||||
self.Schedule[Scheduler][CallID].StartTime = timer.getTime() + ( Start or 0 )
|
self.Schedule[Scheduler][CallID].StartTime = timer.getTime() + (Start or 0)
|
||||||
self.Schedule[Scheduler][CallID].Start = Start + 0.1
|
self.Schedule[Scheduler][CallID].Start = Start + 0.1
|
||||||
self.Schedule[Scheduler][CallID].Repeat = Repeat or 0
|
self.Schedule[Scheduler][CallID].Repeat = Repeat or 0
|
||||||
self.Schedule[Scheduler][CallID].Randomize = Randomize or 0
|
self.Schedule[Scheduler][CallID].Randomize = Randomize or 0
|
||||||
self.Schedule[Scheduler][CallID].Stop = Stop
|
self.Schedule[Scheduler][CallID].Stop = Stop
|
||||||
|
|
||||||
|
|
||||||
-- This section handles the tracing of the scheduled calls.
|
-- This section handles the tracing of the scheduled calls.
|
||||||
-- Because these calls will be executed with a delay, we inspect the place where these scheduled calls are initiated.
|
-- Because these calls will be executed with a delay, we inspect the place where these scheduled calls are initiated.
|
||||||
-- The Info structure contains the output of the debug.getinfo() calls, which inspects the call stack for the function name, line number and source name.
|
-- The Info structure contains the output of the debug.getinfo() calls, which inspects the call stack for the function name, line number and source name.
|
||||||
@@ -149,10 +148,10 @@ function SCHEDULEDISPATCHER:AddSchedule( Scheduler, ScheduleFunction, ScheduleAr
|
|||||||
-- Therefore, in the call stack, at the TraceLevel these functions are mentioned as "tail calls", and the Info.name field will be nil as a result.
|
-- Therefore, in the call stack, at the TraceLevel these functions are mentioned as "tail calls", and the Info.name field will be nil as a result.
|
||||||
-- To obtain the correct function name for FSM object calls, the function is mentioned in the call stack at a higher stack level.
|
-- To obtain the correct function name for FSM object calls, the function is mentioned in the call stack at a higher stack level.
|
||||||
-- So when function name stored in Info.name is nil, then I inspect the function name within the call stack one level higher.
|
-- So when function name stored in Info.name is nil, then I inspect the function name within the call stack one level higher.
|
||||||
-- So this little piece of code does its magic wonderfully, preformance overhead is neglectible, as scheduled calls don't happen that often.
|
-- So this little piece of code does its magic wonderfully, performance overhead is negligible, as scheduled calls don't happen that often.
|
||||||
|
|
||||||
local Info = {}
|
local Info = {}
|
||||||
|
|
||||||
if debug then
|
if debug then
|
||||||
TraceLevel = TraceLevel or 2
|
TraceLevel = TraceLevel or 2
|
||||||
Info = debug.getinfo( TraceLevel, "nlS" )
|
Info = debug.getinfo( TraceLevel, "nlS" )
|
||||||
@@ -166,7 +165,7 @@ function SCHEDULEDISPATCHER:AddSchedule( Scheduler, ScheduleFunction, ScheduleAr
|
|||||||
|
|
||||||
--- Function passed to the DCS timer.scheduleFunction()
|
--- Function passed to the DCS timer.scheduleFunction()
|
||||||
self.Schedule[Scheduler][CallID].CallHandler = function( Params )
|
self.Schedule[Scheduler][CallID].CallHandler = function( Params )
|
||||||
|
|
||||||
local CallID = Params.CallID
|
local CallID = Params.CallID
|
||||||
local Info = Params.Info or {}
|
local Info = Params.Info or {}
|
||||||
local Source = Info.source or "?"
|
local Source = Info.source or "?"
|
||||||
@@ -180,27 +179,27 @@ function SCHEDULEDISPATCHER:AddSchedule( Scheduler, ScheduleFunction, ScheduleAr
|
|||||||
end
|
end
|
||||||
return errmsg
|
return errmsg
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Get object or persistant scheduler object.
|
-- Get object or persistent scheduler object.
|
||||||
local Scheduler = self.ObjectSchedulers[CallID] --Core.Scheduler#SCHEDULER
|
local Scheduler = self.ObjectSchedulers[CallID] -- Core.Scheduler#SCHEDULER
|
||||||
if not Scheduler then
|
if not Scheduler then
|
||||||
Scheduler = self.PersistentSchedulers[CallID]
|
Scheduler = self.PersistentSchedulers[CallID]
|
||||||
end
|
end
|
||||||
|
|
||||||
--self:T3( { Scheduler = Scheduler } )
|
-- self:T3( { Scheduler = Scheduler } )
|
||||||
|
|
||||||
if Scheduler then
|
if Scheduler then
|
||||||
|
|
||||||
local MasterObject = tostring(Scheduler.MasterObject)
|
local MasterObject = tostring( Scheduler.MasterObject )
|
||||||
|
|
||||||
-- Schedule object.
|
|
||||||
local Schedule = self.Schedule[Scheduler][CallID] --#SCHEDULEDISPATCHER.ScheduleData
|
|
||||||
|
|
||||||
--self:T3( { Schedule = Schedule } )
|
|
||||||
|
|
||||||
local SchedulerObject = Scheduler.MasterObject --Scheduler.SchedulerObject Now is this the Maste or Scheduler object?
|
-- Schedule object.
|
||||||
|
local Schedule = self.Schedule[Scheduler][CallID] -- #SCHEDULEDISPATCHER.ScheduleData
|
||||||
|
|
||||||
|
-- self:T3( { Schedule = Schedule } )
|
||||||
|
|
||||||
|
local SchedulerObject = Scheduler.MasterObject -- Scheduler.SchedulerObject Now is this the Master or Scheduler object?
|
||||||
local ShowTrace = Scheduler.ShowTrace
|
local ShowTrace = Scheduler.ShowTrace
|
||||||
|
|
||||||
local ScheduleFunction = Schedule.Function
|
local ScheduleFunction = Schedule.Function
|
||||||
local ScheduleArguments = Schedule.Arguments or {}
|
local ScheduleArguments = Schedule.Arguments or {}
|
||||||
local Start = Schedule.Start
|
local Start = Schedule.Start
|
||||||
@@ -208,18 +207,17 @@ function SCHEDULEDISPATCHER:AddSchedule( Scheduler, ScheduleFunction, ScheduleAr
|
|||||||
local Randomize = Schedule.Randomize or 0
|
local Randomize = Schedule.Randomize or 0
|
||||||
local Stop = Schedule.Stop or 0
|
local Stop = Schedule.Stop or 0
|
||||||
local ScheduleID = Schedule.ScheduleID
|
local ScheduleID = Schedule.ScheduleID
|
||||||
|
|
||||||
|
local Prefix = (Repeat == 0) and "--->" or "+++>"
|
||||||
local Prefix = ( Repeat == 0 ) and "--->" or "+++>"
|
|
||||||
|
|
||||||
local Status, Result
|
local Status, Result
|
||||||
--self:E( { SchedulerObject = SchedulerObject } )
|
-- self:E( { SchedulerObject = SchedulerObject } )
|
||||||
if SchedulerObject then
|
if SchedulerObject then
|
||||||
local function Timer()
|
local function Timer()
|
||||||
if ShowTrace then
|
if ShowTrace then
|
||||||
SchedulerObject:T( Prefix .. Name .. ":" .. Line .. " (" .. Source .. ")" )
|
SchedulerObject:T( Prefix .. Name .. ":" .. Line .. " (" .. Source .. ")" )
|
||||||
end
|
end
|
||||||
return ScheduleFunction( SchedulerObject, unpack( ScheduleArguments ) )
|
return ScheduleFunction( SchedulerObject, unpack( ScheduleArguments ) )
|
||||||
end
|
end
|
||||||
Status, Result = xpcall( Timer, ErrorHandler )
|
Status, Result = xpcall( Timer, ErrorHandler )
|
||||||
else
|
else
|
||||||
@@ -227,40 +225,39 @@ function SCHEDULEDISPATCHER:AddSchedule( Scheduler, ScheduleFunction, ScheduleAr
|
|||||||
if ShowTrace then
|
if ShowTrace then
|
||||||
self:T( Prefix .. Name .. ":" .. Line .. " (" .. Source .. ")" )
|
self:T( Prefix .. Name .. ":" .. Line .. " (" .. Source .. ")" )
|
||||||
end
|
end
|
||||||
return ScheduleFunction( unpack( ScheduleArguments ) )
|
return ScheduleFunction( unpack( ScheduleArguments ) )
|
||||||
end
|
end
|
||||||
Status, Result = xpcall( Timer, ErrorHandler )
|
Status, Result = xpcall( Timer, ErrorHandler )
|
||||||
end
|
end
|
||||||
|
|
||||||
local CurrentTime = timer.getTime()
|
local CurrentTime = timer.getTime()
|
||||||
local StartTime = Schedule.StartTime
|
local StartTime = Schedule.StartTime
|
||||||
|
|
||||||
-- Debug info.
|
-- Debug info.
|
||||||
self:F3( { CallID=CallID, ScheduleID=ScheduleID, Master = MasterObject, CurrentTime = CurrentTime, StartTime = StartTime, Start = Start, Repeat = Repeat, Randomize = Randomize, Stop = Stop } )
|
self:F3( { CallID = CallID, ScheduleID = ScheduleID, Master = MasterObject, CurrentTime = CurrentTime, StartTime = StartTime, Start = Start, Repeat = Repeat, Randomize = Randomize, Stop = Stop } )
|
||||||
|
|
||||||
|
if Status and ((Result == nil) or (Result and Result ~= false)) then
|
||||||
if Status and (( Result == nil ) or ( Result and Result ~= false ) ) then
|
|
||||||
|
if Repeat ~= 0 and ((Stop == 0) or (Stop ~= 0 and CurrentTime <= StartTime + Stop)) then
|
||||||
if Repeat ~= 0 and ( ( Stop == 0 ) or ( Stop ~= 0 and CurrentTime <= StartTime + Stop ) ) then
|
local ScheduleTime = CurrentTime + Repeat + math.random( -(Randomize * Repeat / 2), (Randomize * Repeat / 2) ) + 0.0001 -- Accuracy
|
||||||
local ScheduleTime = CurrentTime + Repeat + math.random(- ( Randomize * Repeat / 2 ), ( Randomize * Repeat / 2 )) + 0.0001 -- Accuracy
|
-- self:T3( { Repeat = CallID, CurrentTime, ScheduleTime, ScheduleArguments } )
|
||||||
--self:T3( { Repeat = CallID, CurrentTime, ScheduleTime, ScheduleArguments } )
|
|
||||||
return ScheduleTime -- returns the next time the function needs to be called.
|
return ScheduleTime -- returns the next time the function needs to be called.
|
||||||
else
|
else
|
||||||
self:Stop( Scheduler, CallID )
|
self:Stop( Scheduler, CallID )
|
||||||
end
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
self:Stop( Scheduler, CallID )
|
self:Stop( Scheduler, CallID )
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
self:I( "<<<>" .. Name .. ":" .. Line .. " (" .. Source .. ")" )
|
self:I( "<<<>" .. Name .. ":" .. Line .. " (" .. Source .. ")" )
|
||||||
end
|
end
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
self:Start( Scheduler, CallID, Info )
|
self:Start( Scheduler, CallID, Info )
|
||||||
|
|
||||||
return CallID
|
return CallID
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -284,33 +281,33 @@ end
|
|||||||
-- @param #string Info (Optional) Debug info.
|
-- @param #string Info (Optional) Debug info.
|
||||||
function SCHEDULEDISPATCHER:Start( Scheduler, CallID, Info )
|
function SCHEDULEDISPATCHER:Start( Scheduler, CallID, Info )
|
||||||
self:F2( { Start = CallID, Scheduler = Scheduler } )
|
self:F2( { Start = CallID, Scheduler = Scheduler } )
|
||||||
|
|
||||||
if CallID then
|
if CallID then
|
||||||
|
|
||||||
local Schedule = self.Schedule[Scheduler][CallID] --#SCHEDULEDISPATCHER.ScheduleData
|
local Schedule = self.Schedule[Scheduler][CallID] -- #SCHEDULEDISPATCHER.ScheduleData
|
||||||
|
|
||||||
-- Only start when there is no ScheduleID defined!
|
-- Only start when there is no ScheduleID defined!
|
||||||
-- This prevents to "Start" the scheduler twice with the same CallID...
|
-- This prevents to "Start" the scheduler twice with the same CallID...
|
||||||
if not Schedule.ScheduleID then
|
if not Schedule.ScheduleID then
|
||||||
|
|
||||||
-- Current time in seconds.
|
-- Current time in seconds.
|
||||||
local Tnow=timer.getTime()
|
local Tnow = timer.getTime()
|
||||||
|
|
||||||
Schedule.StartTime = Tnow -- Set the StartTime field to indicate when the scheduler started.
|
Schedule.StartTime = Tnow -- Set the StartTime field to indicate when the scheduler started.
|
||||||
|
|
||||||
-- Start DCS schedule function https://wiki.hoggitworld.com/view/DCS_func_scheduleFunction
|
-- Start DCS schedule function https://wiki.hoggitworld.com/view/DCS_func_scheduleFunction
|
||||||
Schedule.ScheduleID = timer.scheduleFunction(Schedule.CallHandler, { CallID = CallID, Info = Info }, Tnow + Schedule.Start)
|
Schedule.ScheduleID = timer.scheduleFunction( Schedule.CallHandler, { CallID = CallID, Info = Info }, Tnow + Schedule.Start )
|
||||||
|
|
||||||
self:T(string.format("Starting scheduledispatcher Call ID=%s ==> Schedule ID=%s", tostring(CallID), tostring(Schedule.ScheduleID)))
|
self:T( string.format( "Starting SCHEDULEDISPATCHER Call ID=%s ==> Schedule ID=%s", tostring( CallID ), tostring( Schedule.ScheduleID ) ) )
|
||||||
end
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
-- Recursive.
|
-- Recursive.
|
||||||
for CallID, Schedule in pairs( self.Schedule[Scheduler] or {} ) do
|
for CallID, Schedule in pairs( self.Schedule[Scheduler] or {} ) do
|
||||||
self:Start( Scheduler, CallID, Info ) -- Recursive
|
self:Start( Scheduler, CallID, Info ) -- Recursive
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -322,29 +319,29 @@ function SCHEDULEDISPATCHER:Stop( Scheduler, CallID )
|
|||||||
self:F2( { Stop = CallID, Scheduler = Scheduler } )
|
self:F2( { Stop = CallID, Scheduler = Scheduler } )
|
||||||
|
|
||||||
if CallID then
|
if CallID then
|
||||||
|
|
||||||
local Schedule = self.Schedule[Scheduler][CallID] --#SCHEDULEDISPATCHER.ScheduleData
|
local Schedule = self.Schedule[Scheduler][CallID] -- #SCHEDULEDISPATCHER.ScheduleData
|
||||||
|
|
||||||
-- Only stop when there is a ScheduleID defined for the CallID. So, when the scheduler was stopped before, do nothing.
|
-- Only stop when there is a ScheduleID defined for the CallID. So, when the scheduler was stopped before, do nothing.
|
||||||
if Schedule.ScheduleID then
|
if Schedule.ScheduleID then
|
||||||
|
|
||||||
self:T(string.format("scheduledispatcher stopping scheduler CallID=%s, ScheduleID=%s", tostring(CallID), tostring(Schedule.ScheduleID)))
|
self:T( string.format( "SCHEDULEDISPATCHER stopping scheduler CallID=%s, ScheduleID=%s", tostring( CallID ), tostring( Schedule.ScheduleID ) ) )
|
||||||
|
|
||||||
-- Remove schedule function https://wiki.hoggitworld.com/view/DCS_func_removeFunction
|
-- Remove schedule function https://wiki.hoggitworld.com/view/DCS_func_removeFunction
|
||||||
timer.removeFunction(Schedule.ScheduleID)
|
timer.removeFunction( Schedule.ScheduleID )
|
||||||
|
|
||||||
Schedule.ScheduleID = nil
|
Schedule.ScheduleID = nil
|
||||||
|
|
||||||
else
|
else
|
||||||
self:T(string.format("Error no ScheduleID for CallID=%s", tostring(CallID)))
|
self:T( string.format( "Error no ScheduleID for CallID=%s", tostring( CallID ) ) )
|
||||||
end
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
for CallID, Schedule in pairs( self.Schedule[Scheduler] or {} ) do
|
for CallID, Schedule in pairs( self.Schedule[Scheduler] or {} ) do
|
||||||
self:Stop( Scheduler, CallID ) -- Recursive
|
self:Stop( Scheduler, CallID ) -- Recursive
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -359,7 +356,7 @@ function SCHEDULEDISPATCHER:Clear( Scheduler )
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Shopw tracing info.
|
--- Show tracing info.
|
||||||
-- @param #SCHEDULEDISPATCHER self
|
-- @param #SCHEDULEDISPATCHER self
|
||||||
-- @param Core.Scheduler#SCHEDULER Scheduler Scheduler object.
|
-- @param Core.Scheduler#SCHEDULER Scheduler Scheduler object.
|
||||||
function SCHEDULEDISPATCHER:ShowTrace( Scheduler )
|
function SCHEDULEDISPATCHER:ShowTrace( Scheduler )
|
||||||
|
|||||||
@@ -1,41 +1,41 @@
|
|||||||
--- **Core** - Prepares and handles the execution of functions over scheduled time (intervals).
|
--- **Core** - Prepares and handles the execution of functions over scheduled time (intervals).
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ## Features:
|
-- ## Features:
|
||||||
--
|
--
|
||||||
-- * Schedule functions over time,
|
-- * Schedule functions over time,
|
||||||
-- * optionally in an optional specified time interval,
|
-- * optionally in an optional specified time interval,
|
||||||
-- * optionally **repeating** with a specified time repeat interval,
|
-- * optionally **repeating** with a specified time repeat interval,
|
||||||
-- * optionally **randomizing** with a specified time interval randomization factor,
|
-- * optionally **randomizing** with a specified time interval randomization factor,
|
||||||
-- * optionally **stop** the repeating after a specified time interval.
|
-- * optionally **stop** the repeating after a specified time interval.
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- # Demo Missions
|
-- # Demo Missions
|
||||||
--
|
--
|
||||||
-- ### [SCHEDULER Demo Missions source code](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master-release/SCH%20-%20Scheduler)
|
-- ### [SCHEDULER Demo Missions source code](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master-release/SCH%20-%20Scheduler)
|
||||||
--
|
--
|
||||||
-- ### [SCHEDULER Demo Missions, only for beta testers](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/SCH%20-%20Scheduler)
|
-- ### [SCHEDULER Demo Missions, only for beta testers](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/SCH%20-%20Scheduler)
|
||||||
--
|
--
|
||||||
-- ### [ALL Demo Missions pack of the last release](https://github.com/FlightControl-Master/MOOSE_MISSIONS/releases)
|
-- ### [ALL Demo Missions pack of the last release](https://github.com/FlightControl-Master/MOOSE_MISSIONS/releases)
|
||||||
--
|
--
|
||||||
-- ===
|
|
||||||
--
|
|
||||||
-- # YouTube Channel
|
|
||||||
--
|
|
||||||
-- ### [SCHEDULER YouTube Channel (none)]()
|
|
||||||
--
|
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ### Contributions:
|
-- # YouTube Channel
|
||||||
--
|
--
|
||||||
|
-- ### [SCHEDULER YouTube Channel (none)]()
|
||||||
|
--
|
||||||
|
-- ===
|
||||||
|
--
|
||||||
|
-- ### Contributions:
|
||||||
|
--
|
||||||
-- * FlightControl : Concept & Testing
|
-- * FlightControl : Concept & Testing
|
||||||
--
|
--
|
||||||
-- ### Authors:
|
-- ### Authors:
|
||||||
--
|
--
|
||||||
-- * FlightControl : Design & Programming
|
-- * FlightControl : Design & Programming
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- @module Core.Scheduler
|
-- @module Core.Scheduler
|
||||||
@@ -48,62 +48,61 @@
|
|||||||
-- @field #boolean ShowTrace Trace info if true.
|
-- @field #boolean ShowTrace Trace info if true.
|
||||||
-- @extends Core.Base#BASE
|
-- @extends Core.Base#BASE
|
||||||
|
|
||||||
|
|
||||||
--- Creates and handles schedules over time, which allow to execute code at specific time intervals with randomization.
|
--- Creates and handles schedules over time, which allow to execute code at specific time intervals with randomization.
|
||||||
--
|
--
|
||||||
-- A SCHEDULER can manage **multiple** (repeating) schedules. Each planned or executing schedule has a unique **ScheduleID**.
|
-- A SCHEDULER can manage **multiple** (repeating) schedules. Each planned or executing schedule has a unique **ScheduleID**.
|
||||||
-- The ScheduleID is returned when the method @{#SCHEDULER.Schedule}() is called.
|
-- The ScheduleID is returned when the method @{#SCHEDULER.Schedule}() is called.
|
||||||
-- It is recommended to store the ScheduleID in a variable, as it is used in the methods @{SCHEDULER.Start}() and @{SCHEDULER.Stop}(),
|
-- It is recommended to store the ScheduleID in a variable, as it is used in the methods @{SCHEDULER.Start}() and @{SCHEDULER.Stop}(),
|
||||||
-- which can start and stop specific repeating schedules respectively within a SCHEDULER object.
|
-- which can start and stop specific repeating schedules respectively within a SCHEDULER object.
|
||||||
--
|
--
|
||||||
-- ## SCHEDULER constructor
|
-- ## SCHEDULER constructor
|
||||||
--
|
--
|
||||||
-- The SCHEDULER class is quite easy to use, but note that the New constructor has variable parameters:
|
-- The SCHEDULER class is quite easy to use, but note that the New constructor has variable parameters:
|
||||||
--
|
--
|
||||||
-- The @{#SCHEDULER.New}() method returns 2 variables:
|
-- The @{#SCHEDULER.New}() method returns 2 variables:
|
||||||
--
|
--
|
||||||
-- 1. The SCHEDULER object reference.
|
-- 1. The SCHEDULER object reference.
|
||||||
-- 2. The first schedule planned in the SCHEDULER object.
|
-- 2. The first schedule planned in the SCHEDULER object.
|
||||||
--
|
--
|
||||||
-- To clarify the different appliances, lets have a look at the following examples:
|
-- To clarify the different appliances, lets have a look at the following examples:
|
||||||
--
|
--
|
||||||
-- ### Construct a SCHEDULER object without a persistent schedule.
|
-- ### Construct a SCHEDULER object without a persistent schedule.
|
||||||
--
|
--
|
||||||
-- * @{#SCHEDULER.New}( nil ): Setup a new SCHEDULER object, which is persistently executed after garbage collection.
|
-- * @{#SCHEDULER.New}( nil ): Setup a new SCHEDULER object, which is persistently executed after garbage collection.
|
||||||
--
|
--
|
||||||
-- MasterObject = SCHEDULER:New()
|
-- MasterObject = SCHEDULER:New()
|
||||||
-- SchedulerID = MasterObject:Schedule( nil, ScheduleFunction, {} )
|
-- SchedulerID = MasterObject:Schedule( nil, ScheduleFunction, {} )
|
||||||
--
|
--
|
||||||
-- The above example creates a new MasterObject, but does not schedule anything.
|
-- The above example creates a new MasterObject, but does not schedule anything.
|
||||||
-- A separate schedule is created by using the MasterObject using the method :Schedule..., which returns a ScheduleID
|
-- A separate schedule is created by using the MasterObject using the method :Schedule..., which returns a ScheduleID
|
||||||
--
|
--
|
||||||
-- ### Construct a SCHEDULER object without a volatile schedule, but volatile to the Object existence...
|
-- ### Construct a SCHEDULER object without a volatile schedule, but volatile to the Object existence...
|
||||||
--
|
--
|
||||||
-- * @{#SCHEDULER.New}( Object ): Setup a new SCHEDULER object, which is linked to the Object. When the Object is nillified or destroyed, the SCHEDULER object will also be destroyed and stopped after garbage collection.
|
-- * @{#SCHEDULER.New}( Object ): Setup a new SCHEDULER object, which is linked to the Object. When the Object is set to nil or destroyed, the SCHEDULER object will also be destroyed and stopped after garbage collection.
|
||||||
--
|
--
|
||||||
-- ZoneObject = ZONE:New( "ZoneName" )
|
-- ZoneObject = ZONE:New( "ZoneName" )
|
||||||
-- MasterObject = SCHEDULER:New( ZoneObject )
|
-- MasterObject = SCHEDULER:New( ZoneObject )
|
||||||
-- SchedulerID = MasterObject:Schedule( ZoneObject, ScheduleFunction, {} )
|
-- SchedulerID = MasterObject:Schedule( ZoneObject, ScheduleFunction, {} )
|
||||||
-- ...
|
-- ...
|
||||||
-- ZoneObject = nil
|
-- ZoneObject = nil
|
||||||
-- garbagecollect()
|
-- garbagecollect()
|
||||||
--
|
--
|
||||||
-- The above example creates a new MasterObject, but does not schedule anything, and is bound to the existence of ZoneObject, which is a ZONE.
|
-- The above example creates a new MasterObject, but does not schedule anything, and is bound to the existence of ZoneObject, which is a ZONE.
|
||||||
-- A separate schedule is created by using the MasterObject using the method :Schedule()..., which returns a ScheduleID
|
-- A separate schedule is created by using the MasterObject using the method :Schedule()..., which returns a ScheduleID
|
||||||
-- Later in the logic, the ZoneObject is put to nil, and garbage is collected.
|
-- Later in the logic, the ZoneObject is put to nil, and garbage is collected.
|
||||||
-- As a result, the MasterObject will cancel any planned schedule.
|
-- As a result, the MasterObject will cancel any planned schedule.
|
||||||
--
|
--
|
||||||
-- ### Construct a SCHEDULER object with a persistent schedule.
|
-- ### Construct a SCHEDULER object with a persistent schedule.
|
||||||
--
|
--
|
||||||
-- * @{#SCHEDULER.New}( nil, Function, FunctionArguments, Start, ... ): Setup a new persistent SCHEDULER object, and start a new schedule for the Function with the defined FunctionArguments according the Start and sequent parameters.
|
-- * @{#SCHEDULER.New}( nil, Function, FunctionArguments, Start, ... ): Setup a new persistent SCHEDULER object, and start a new schedule for the Function with the defined FunctionArguments according the Start and sequent parameters.
|
||||||
--
|
--
|
||||||
-- MasterObject, SchedulerID = SCHEDULER:New( nil, ScheduleFunction, {} )
|
-- MasterObject, SchedulerID = SCHEDULER:New( nil, ScheduleFunction, {} )
|
||||||
--
|
--
|
||||||
-- The above example creates a new MasterObject, and does schedule the first schedule as part of the call.
|
-- The above example creates a new MasterObject, and does schedule the first schedule as part of the call.
|
||||||
-- Note that 2 variables are returned here: MasterObject, ScheduleID...
|
-- Note that 2 variables are returned here: MasterObject, ScheduleID...
|
||||||
--
|
--
|
||||||
-- ### Construct a SCHEDULER object without a schedule, but volatile to the Object existence...
|
-- ### Construct a SCHEDULER object without a schedule, but volatile to the Object existence...
|
||||||
--
|
--
|
||||||
-- * @{#SCHEDULER.New}( Object, Function, FunctionArguments, Start, ... ): Setup a new SCHEDULER object, linked to Object, and start a new schedule for the Function with the defined FunctionArguments according the Start and sequent parameters.
|
-- * @{#SCHEDULER.New}( Object, Function, FunctionArguments, Start, ... ): Setup a new SCHEDULER object, linked to Object, and start a new schedule for the Function with the defined FunctionArguments according the Start and sequent parameters.
|
||||||
--
|
--
|
||||||
-- ZoneObject = ZONE:New( "ZoneName" )
|
-- ZoneObject = ZONE:New( "ZoneName" )
|
||||||
@@ -112,13 +111,13 @@
|
|||||||
-- ...
|
-- ...
|
||||||
-- ZoneObject = nil
|
-- ZoneObject = nil
|
||||||
-- garbagecollect()
|
-- garbagecollect()
|
||||||
--
|
--
|
||||||
-- The above example creates a new MasterObject, and schedules a method call (ScheduleFunction),
|
-- The above example creates a new MasterObject, and schedules a method call (ScheduleFunction),
|
||||||
-- and is bound to the existence of ZoneObject, which is a ZONE object (ZoneObject).
|
-- and is bound to the existence of ZoneObject, which is a ZONE object (ZoneObject).
|
||||||
-- Both a MasterObject and a SchedulerID variable are returned.
|
-- Both a MasterObject and a SchedulerID variable are returned.
|
||||||
-- Later in the logic, the ZoneObject is put to nil, and garbage is collected.
|
-- Later in the logic, the ZoneObject is put to nil, and garbage is collected.
|
||||||
-- As a result, the MasterObject will cancel the planned schedule.
|
-- As a result, the MasterObject will cancel the planned schedule.
|
||||||
--
|
--
|
||||||
-- ## SCHEDULER timer stopping and (re-)starting.
|
-- ## SCHEDULER timer stopping and (re-)starting.
|
||||||
--
|
--
|
||||||
-- The SCHEDULER can be stopped and restarted with the following methods:
|
-- The SCHEDULER can be stopped and restarted with the following methods:
|
||||||
@@ -133,70 +132,70 @@
|
|||||||
-- MasterObject:Stop( SchedulerID )
|
-- MasterObject:Stop( SchedulerID )
|
||||||
-- ...
|
-- ...
|
||||||
-- MasterObject:Start( SchedulerID )
|
-- MasterObject:Start( SchedulerID )
|
||||||
--
|
--
|
||||||
-- The above example creates a new MasterObject, and does schedule the first schedule as part of the call.
|
-- The above example creates a new MasterObject, and does schedule the first schedule as part of the call.
|
||||||
-- Note that 2 variables are returned here: MasterObject, ScheduleID...
|
-- Note that 2 variables are returned here: MasterObject, ScheduleID...
|
||||||
-- Later in the logic, the repeating schedule with SchedulerID is stopped.
|
-- Later in the logic, the repeating schedule with SchedulerID is stopped.
|
||||||
-- A bit later, the repeating schedule with SchedulerId is (re)-started.
|
-- A bit later, the repeating schedule with SchedulerId is (re)-started.
|
||||||
--
|
--
|
||||||
-- ## Create a new schedule
|
-- ## Create a new schedule
|
||||||
--
|
--
|
||||||
-- With the method @{#SCHEDULER.Schedule}() a new time event can be scheduled.
|
-- With the method @{#SCHEDULER.Schedule}() a new time event can be scheduled.
|
||||||
-- This method is used by the :New() constructor when a new schedule is planned.
|
-- This method is used by the :New() constructor when a new schedule is planned.
|
||||||
--
|
--
|
||||||
-- Consider the following code fragment of the SCHEDULER object creation.
|
-- Consider the following code fragment of the SCHEDULER object creation.
|
||||||
--
|
--
|
||||||
-- ZoneObject = ZONE:New( "ZoneName" )
|
-- ZoneObject = ZONE:New( "ZoneName" )
|
||||||
-- MasterObject = SCHEDULER:New( ZoneObject )
|
-- MasterObject = SCHEDULER:New( ZoneObject )
|
||||||
--
|
--
|
||||||
-- Several parameters can be specified that influence the behaviour of a Schedule.
|
-- Several parameters can be specified that influence the behavior of a Schedule.
|
||||||
--
|
--
|
||||||
-- ### A single schedule, immediately executed
|
-- ### A single schedule, immediately executed
|
||||||
--
|
--
|
||||||
-- SchedulerID = MasterObject:Schedule( ZoneObject, ScheduleFunction, {} )
|
-- SchedulerID = MasterObject:Schedule( ZoneObject, ScheduleFunction, {} )
|
||||||
--
|
--
|
||||||
-- The above example schedules a new ScheduleFunction call to be executed asynchronously, within milleseconds ...
|
-- The above example schedules a new ScheduleFunction call to be executed asynchronously, within milliseconds ...
|
||||||
--
|
--
|
||||||
-- ### A single schedule, planned over time
|
-- ### A single schedule, planned over time
|
||||||
--
|
--
|
||||||
-- SchedulerID = MasterObject:Schedule( ZoneObject, ScheduleFunction, {}, 10 )
|
-- SchedulerID = MasterObject:Schedule( ZoneObject, ScheduleFunction, {}, 10 )
|
||||||
--
|
--
|
||||||
-- The above example schedules a new ScheduleFunction call to be executed asynchronously, within 10 seconds ...
|
-- The above example schedules a new ScheduleFunction call to be executed asynchronously, within 10 seconds ...
|
||||||
--
|
--
|
||||||
-- ### A schedule with a repeating time interval, planned over time
|
-- ### A schedule with a repeating time interval, planned over time
|
||||||
--
|
--
|
||||||
-- SchedulerID = MasterObject:Schedule( ZoneObject, ScheduleFunction, {}, 10, 60 )
|
-- SchedulerID = MasterObject:Schedule( ZoneObject, ScheduleFunction, {}, 10, 60 )
|
||||||
--
|
--
|
||||||
-- The above example schedules a new ScheduleFunction call to be executed asynchronously, within 10 seconds,
|
-- The above example schedules a new ScheduleFunction call to be executed asynchronously, within 10 seconds,
|
||||||
-- and repeating 60 every seconds ...
|
-- and repeating 60 every seconds ...
|
||||||
--
|
--
|
||||||
-- ### A schedule with a repeating time interval, planned over time, with time interval randomization
|
-- ### A schedule with a repeating time interval, planned over time, with time interval randomization
|
||||||
--
|
--
|
||||||
-- SchedulerID = MasterObject:Schedule( ZoneObject, ScheduleFunction, {}, 10, 60, 0.5 )
|
-- SchedulerID = MasterObject:Schedule( ZoneObject, ScheduleFunction, {}, 10, 60, 0.5 )
|
||||||
--
|
--
|
||||||
-- The above example schedules a new ScheduleFunction call to be executed asynchronously, within 10 seconds,
|
-- The above example schedules a new ScheduleFunction call to be executed asynchronously, within 10 seconds,
|
||||||
-- and repeating 60 seconds, with a 50% time interval randomization ...
|
-- and repeating 60 seconds, with a 50% time interval randomization ...
|
||||||
-- So the repeating time interval will be randomized using the **0.5**,
|
-- So the repeating time interval will be randomized using the **0.5**,
|
||||||
-- and will calculate between **60 - ( 60 * 0.5 )** and **60 + ( 60 * 0.5 )** for each repeat,
|
-- and will calculate between **60 - ( 60 * 0.5 )** and **60 + ( 60 * 0.5 )** for each repeat,
|
||||||
-- which is in this example between **30** and **90** seconds.
|
-- which is in this example between **30** and **90** seconds.
|
||||||
--
|
--
|
||||||
-- ### A schedule with a repeating time interval, planned over time, with time interval randomization, and stop after a time interval
|
-- ### A schedule with a repeating time interval, planned over time, with time interval randomization, and stop after a time interval
|
||||||
--
|
--
|
||||||
-- SchedulerID = MasterObject:Schedule( ZoneObject, ScheduleFunction, {}, 10, 60, 0.5, 300 )
|
-- SchedulerID = MasterObject:Schedule( ZoneObject, ScheduleFunction, {}, 10, 60, 0.5, 300 )
|
||||||
--
|
--
|
||||||
-- The above example schedules a new ScheduleFunction call to be executed asynchronously, within 10 seconds,
|
-- The above example schedules a new ScheduleFunction call to be executed asynchronously, within 10 seconds,
|
||||||
-- The schedule will repeat every 60 seconds.
|
-- The schedule will repeat every 60 seconds.
|
||||||
-- So the repeating time interval will be randomized using the **0.5**,
|
-- So the repeating time interval will be randomized using the **0.5**,
|
||||||
-- and will calculate between **60 - ( 60 * 0.5 )** and **60 + ( 60 * 0.5 )** for each repeat,
|
-- and will calculate between **60 - ( 60 * 0.5 )** and **60 + ( 60 * 0.5 )** for each repeat,
|
||||||
-- which is in this example between **30** and **90** seconds.
|
-- which is in this example between **30** and **90** seconds.
|
||||||
-- The schedule will stop after **300** seconds.
|
-- The schedule will stop after **300** seconds.
|
||||||
--
|
--
|
||||||
-- @field #SCHEDULER
|
-- @field #SCHEDULER
|
||||||
SCHEDULER = {
|
SCHEDULER = {
|
||||||
ClassName = "SCHEDULER",
|
ClassName = "SCHEDULER",
|
||||||
Schedules = {},
|
Schedules = {},
|
||||||
MasterObject = nil,
|
MasterObject = nil,
|
||||||
ShowTrace = nil,
|
ShowTrace = nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
--- SCHEDULER constructor.
|
--- SCHEDULER constructor.
|
||||||
@@ -211,15 +210,15 @@ SCHEDULER = {
|
|||||||
-- @return #SCHEDULER self.
|
-- @return #SCHEDULER self.
|
||||||
-- @return #table The ScheduleID of the planned schedule.
|
-- @return #table The ScheduleID of the planned schedule.
|
||||||
function SCHEDULER:New( MasterObject, SchedulerFunction, SchedulerArguments, Start, Repeat, RandomizeFactor, Stop )
|
function SCHEDULER:New( MasterObject, SchedulerFunction, SchedulerArguments, Start, Repeat, RandomizeFactor, Stop )
|
||||||
|
|
||||||
local self = BASE:Inherit( self, BASE:New() ) -- #SCHEDULER
|
local self = BASE:Inherit( self, BASE:New() ) -- #SCHEDULER
|
||||||
self:F2( { Start, Repeat, RandomizeFactor, Stop } )
|
self:F2( { Start, Repeat, RandomizeFactor, Stop } )
|
||||||
|
|
||||||
local ScheduleID = nil
|
local ScheduleID = nil
|
||||||
|
|
||||||
self.MasterObject = MasterObject
|
self.MasterObject = MasterObject
|
||||||
self.ShowTrace = false
|
self.ShowTrace = false
|
||||||
|
|
||||||
if SchedulerFunction then
|
if SchedulerFunction then
|
||||||
ScheduleID = self:Schedule( MasterObject, SchedulerFunction, SchedulerArguments, Start, Repeat, RandomizeFactor, Stop, 3 )
|
ScheduleID = self:Schedule( MasterObject, SchedulerFunction, SchedulerArguments, Start, Repeat, RandomizeFactor, Stop, 3 )
|
||||||
end
|
end
|
||||||
@@ -235,7 +234,7 @@ end
|
|||||||
-- @param #number Start Specifies the amount of seconds that will be waited before the scheduling is started, and the event function is called.
|
-- @param #number Start Specifies the amount of seconds that will be waited before the scheduling is started, and the event function is called.
|
||||||
-- @param #number Repeat Specifies the time interval in seconds when the scheduler will call the event function.
|
-- @param #number Repeat Specifies the time interval in seconds when the scheduler will call the event function.
|
||||||
-- @param #number RandomizeFactor Specifies a randomization factor between 0 and 1 to randomize the Repeat.
|
-- @param #number RandomizeFactor Specifies a randomization factor between 0 and 1 to randomize the Repeat.
|
||||||
-- @param #number Stop Time interval in seconds after which the scheduler will be stoppe.
|
-- @param #number Stop Time interval in seconds after which the scheduler will be stopped.
|
||||||
-- @param #number TraceLevel Trace level [0,3]. Default 3.
|
-- @param #number TraceLevel Trace level [0,3]. Default 3.
|
||||||
-- @param Core.Fsm#FSM Fsm Finite state model.
|
-- @param Core.Fsm#FSM Fsm Finite state model.
|
||||||
-- @return #table The ScheduleID of the planned schedule.
|
-- @return #table The ScheduleID of the planned schedule.
|
||||||
@@ -245,28 +244,27 @@ function SCHEDULER:Schedule( MasterObject, SchedulerFunction, SchedulerArguments
|
|||||||
|
|
||||||
-- Debug info.
|
-- Debug info.
|
||||||
local ObjectName = "-"
|
local ObjectName = "-"
|
||||||
if MasterObject and MasterObject.ClassName and MasterObject.ClassID then
|
if MasterObject and MasterObject.ClassName and MasterObject.ClassID then
|
||||||
ObjectName = MasterObject.ClassName .. MasterObject.ClassID
|
ObjectName = MasterObject.ClassName .. MasterObject.ClassID
|
||||||
end
|
end
|
||||||
self:F3( { "Schedule :", ObjectName, tostring( MasterObject ), Start, Repeat, RandomizeFactor, Stop } )
|
self:F3( { "Schedule :", ObjectName, tostring( MasterObject ), Start, Repeat, RandomizeFactor, Stop } )
|
||||||
|
|
||||||
-- Set master object.
|
-- Set master object.
|
||||||
self.MasterObject = MasterObject
|
self.MasterObject = MasterObject
|
||||||
|
|
||||||
-- Add schedule.
|
-- Add schedule.
|
||||||
local ScheduleID = _SCHEDULEDISPATCHER:AddSchedule(
|
local ScheduleID = _SCHEDULEDISPATCHER:AddSchedule( self,
|
||||||
self,
|
SchedulerFunction,
|
||||||
SchedulerFunction,
|
SchedulerArguments,
|
||||||
SchedulerArguments,
|
Start,
|
||||||
Start,
|
Repeat,
|
||||||
Repeat,
|
RandomizeFactor,
|
||||||
RandomizeFactor,
|
Stop,
|
||||||
Stop,
|
TraceLevel or 3,
|
||||||
TraceLevel or 3,
|
Fsm
|
||||||
Fsm
|
)
|
||||||
)
|
|
||||||
|
self.Schedules[#self.Schedules + 1] = ScheduleID
|
||||||
self.Schedules[#self.Schedules+1] = ScheduleID
|
|
||||||
|
|
||||||
return ScheduleID
|
return ScheduleID
|
||||||
end
|
end
|
||||||
@@ -276,7 +274,7 @@ end
|
|||||||
-- @param #string ScheduleID (Optional) The ScheduleID of the planned (repeating) schedule.
|
-- @param #string ScheduleID (Optional) The ScheduleID of the planned (repeating) schedule.
|
||||||
function SCHEDULER:Start( ScheduleID )
|
function SCHEDULER:Start( ScheduleID )
|
||||||
self:F3( { ScheduleID } )
|
self:F3( { ScheduleID } )
|
||||||
self:T(string.format("Starting scheduler ID=%s", tostring(ScheduleID)))
|
self:T( string.format( "Starting scheduler ID=%s", tostring( ScheduleID ) ) )
|
||||||
_SCHEDULEDISPATCHER:Start( self, ScheduleID )
|
_SCHEDULEDISPATCHER:Start( self, ScheduleID )
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -285,7 +283,7 @@ end
|
|||||||
-- @param #string ScheduleID (Optional) The ScheduleID of the planned (repeating) schedule.
|
-- @param #string ScheduleID (Optional) The ScheduleID of the planned (repeating) schedule.
|
||||||
function SCHEDULER:Stop( ScheduleID )
|
function SCHEDULER:Stop( ScheduleID )
|
||||||
self:F3( { ScheduleID } )
|
self:F3( { ScheduleID } )
|
||||||
self:T(string.format("Stopping scheduler ID=%s", tostring(ScheduleID)))
|
self:T( string.format( "Stopping scheduler ID=%s", tostring( ScheduleID ) ) )
|
||||||
_SCHEDULEDISPATCHER:Stop( self, ScheduleID )
|
_SCHEDULEDISPATCHER:Stop( self, ScheduleID )
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -294,15 +292,15 @@ end
|
|||||||
-- @param #string ScheduleID (optional) The ScheduleID of the planned (repeating) schedule.
|
-- @param #string ScheduleID (optional) The ScheduleID of the planned (repeating) schedule.
|
||||||
function SCHEDULER:Remove( ScheduleID )
|
function SCHEDULER:Remove( ScheduleID )
|
||||||
self:F3( { ScheduleID } )
|
self:F3( { ScheduleID } )
|
||||||
self:T(string.format("Removing scheduler ID=%s", tostring(ScheduleID)))
|
self:T( string.format( "Removing scheduler ID=%s", tostring( ScheduleID ) ) )
|
||||||
_SCHEDULEDISPATCHER:RemoveSchedule( self, ScheduleID )
|
_SCHEDULEDISPATCHER:RemoveSchedule( self, ScheduleID )
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Clears all pending schedules.
|
--- Clears all pending schedules.
|
||||||
-- @param #SCHEDULER self
|
-- @param #SCHEDULER self
|
||||||
function SCHEDULER:Clear()
|
function SCHEDULER:Clear()
|
||||||
self:F3( )
|
self:F3()
|
||||||
self:T(string.format("Clearing scheduler"))
|
self:T( string.format( "Clearing scheduler" ) )
|
||||||
_SCHEDULEDISPATCHER:Clear( self )
|
_SCHEDULEDISPATCHER:Clear( self )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -29,15 +29,14 @@
|
|||||||
-- @module Core.Settings
|
-- @module Core.Settings
|
||||||
-- @image Core_Settings.JPG
|
-- @image Core_Settings.JPG
|
||||||
|
|
||||||
|
|
||||||
--- @type SETTINGS
|
--- @type SETTINGS
|
||||||
-- @extends Core.Base#BASE
|
-- @extends Core.Base#BASE
|
||||||
|
|
||||||
--- Takes care of various settings that influence the behaviour of certain functionalities and classes within the MOOSE framework.
|
--- Takes care of various settings that influence the behavior of certain functionalities and classes within the MOOSE framework.
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- The SETTINGS class takes care of various settings that influence the behaviour of certain functionalities and classes within the MOOSE framework.
|
-- The SETTINGS class takes care of various settings that influence the behavior of certain functionalities and classes within the MOOSE framework.
|
||||||
-- SETTINGS can work on 2 levels:
|
-- SETTINGS can work on 2 levels:
|
||||||
--
|
--
|
||||||
-- - **Default settings**: A running mission has **Default settings**.
|
-- - **Default settings**: A running mission has **Default settings**.
|
||||||
@@ -59,7 +58,7 @@
|
|||||||
--
|
--
|
||||||
-- A menu is created automatically per Command Center that allows to modify the **Default** settings.
|
-- A menu is created automatically per Command Center that allows to modify the **Default** settings.
|
||||||
-- So, when joining a CC unit, a menu will be available that allows to change the settings parameters **FOR ALL THE PLAYERS**!
|
-- So, when joining a CC unit, a menu will be available that allows to change the settings parameters **FOR ALL THE PLAYERS**!
|
||||||
-- Note that the **Default settings** will only be used when a player has not choosen its own settings.
|
-- Note that the **Default settings** will only be used when a player has not chosen its own settings.
|
||||||
--
|
--
|
||||||
-- ## 2.2) Player settings menu
|
-- ## 2.2) Player settings menu
|
||||||
--
|
--
|
||||||
@@ -69,7 +68,7 @@
|
|||||||
--
|
--
|
||||||
-- ## 2.3) Show or Hide the Player Setting menus
|
-- ## 2.3) Show or Hide the Player Setting menus
|
||||||
--
|
--
|
||||||
-- Of course, it may be requried not to show any setting menus. In this case, a method is available on the **\_SETTINGS object**.
|
-- Of course, it may be required not to show any setting menus. In this case, a method is available on the **\_SETTINGS object**.
|
||||||
-- Use @{#SETTINGS.SetPlayerMenuOff}() to hide the player menus, and use @{#SETTINGS.SetPlayerMenuOn}() show the player menus.
|
-- Use @{#SETTINGS.SetPlayerMenuOff}() to hide the player menus, and use @{#SETTINGS.SetPlayerMenuOn}() show the player menus.
|
||||||
-- Note that when this method is used, any player already in a slot will not have its menus visibility changed.
|
-- Note that when this method is used, any player already in a slot will not have its menus visibility changed.
|
||||||
-- The option will only have effect when a player enters a new slot or changes a slot.
|
-- The option will only have effect when a player enters a new slot or changes a slot.
|
||||||
@@ -94,8 +93,8 @@
|
|||||||
--
|
--
|
||||||
-- - A2G BR: [Bearing Range](https://en.wikipedia.org/wiki/Bearing_(navigation)).
|
-- - A2G BR: [Bearing Range](https://en.wikipedia.org/wiki/Bearing_(navigation)).
|
||||||
-- - A2G MGRS: The [Military Grid Reference System](https://en.wikipedia.org/wiki/Military_Grid_Reference_System). The accuracy can also be adapted.
|
-- - A2G MGRS: The [Military Grid Reference System](https://en.wikipedia.org/wiki/Military_Grid_Reference_System). The accuracy can also be adapted.
|
||||||
-- - A2G LL DMS: Lattitude Longitude [Degrees Minutes Seconds](https://en.wikipedia.org/wiki/Geographic_coordinate_conversion). The accuracy can also be adapted.
|
-- - A2G LL DMS: Latitude Longitude [Degrees Minutes Seconds](https://en.wikipedia.org/wiki/Geographic_coordinate_conversion). The accuracy can also be adapted.
|
||||||
-- - A2G LL DDM: Lattitude Longitude [Decimal Degrees Minutes](https://en.wikipedia.org/wiki/Decimal_degrees). The accuracy can also be adapted.
|
-- - A2G LL DDM: Latitude Longitude [Decimal Degrees Minutes](https://en.wikipedia.org/wiki/Decimal_degrees). The accuracy can also be adapted.
|
||||||
--
|
--
|
||||||
-- ### 3.1.2) A2G coordinates setting **menu**
|
-- ### 3.1.2) A2G coordinates setting **menu**
|
||||||
--
|
--
|
||||||
@@ -183,7 +182,7 @@
|
|||||||
-- The settings can be changed by using the **Default settings menu** on the Command Center or the **Player settings menu** on the Player Slot.
|
-- The settings can be changed by using the **Default settings menu** on the Command Center or the **Player settings menu** on the Player Slot.
|
||||||
--
|
--
|
||||||
-- Each Message Type has specific timings that will be applied when the message is displayed.
|
-- Each Message Type has specific timings that will be applied when the message is displayed.
|
||||||
-- The Settings Menu will provide for each Message Type a selection of proposed durations from which can be choosen.
|
-- The Settings Menu will provide for each Message Type a selection of proposed durations from which can be chosen.
|
||||||
-- So the player can choose its own amount of seconds how long a message should be displayed of a certain type.
|
-- So the player can choose its own amount of seconds how long a message should be displayed of a certain type.
|
||||||
-- Note that **Update** messages can be chosen not to be displayed at all!
|
-- Note that **Update** messages can be chosen not to be displayed at all!
|
||||||
--
|
--
|
||||||
@@ -196,7 +195,7 @@
|
|||||||
--
|
--
|
||||||
-- ## 3.5) **Era** of the battle
|
-- ## 3.5) **Era** of the battle
|
||||||
--
|
--
|
||||||
-- The threat level metric is scaled according the era of the battle. A target that is AAA, will pose a much greather threat in WWII than on modern warfare.
|
-- The threat level metric is scaled according the era of the battle. A target that is AAA, will pose a much greater threat in WWII than on modern warfare.
|
||||||
-- Therefore, there are 4 era that are defined within the settings:
|
-- Therefore, there are 4 era that are defined within the settings:
|
||||||
--
|
--
|
||||||
-- - **WWII** era: Use for warfare with equipment during the world war II time.
|
-- - **WWII** era: Use for warfare with equipment during the world war II time.
|
||||||
@@ -213,8 +212,8 @@
|
|||||||
SETTINGS = {
|
SETTINGS = {
|
||||||
ClassName = "SETTINGS",
|
ClassName = "SETTINGS",
|
||||||
ShowPlayerMenu = true,
|
ShowPlayerMenu = true,
|
||||||
MenuShort = false,
|
MenuShort = false,
|
||||||
MenuStatic = false,
|
MenuStatic = false,
|
||||||
}
|
}
|
||||||
|
|
||||||
SETTINGS.__Enum = {}
|
SETTINGS.__Enum = {}
|
||||||
@@ -231,7 +230,6 @@ SETTINGS.__Enum.Era = {
|
|||||||
Modern = 4,
|
Modern = 4,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
do -- SETTINGS
|
do -- SETTINGS
|
||||||
|
|
||||||
--- SETTINGS constructor.
|
--- SETTINGS constructor.
|
||||||
@@ -268,14 +266,14 @@ do -- SETTINGS
|
|||||||
-- Short text are better suited for, e.g., VR.
|
-- Short text are better suited for, e.g., VR.
|
||||||
-- @param #SETTINGS self
|
-- @param #SETTINGS self
|
||||||
-- @param #boolean onoff If *true* use short menu texts. If *false* long ones (default).
|
-- @param #boolean onoff If *true* use short menu texts. If *false* long ones (default).
|
||||||
function SETTINGS:SetMenutextShort(onoff)
|
function SETTINGS:SetMenutextShort( onoff )
|
||||||
_SETTINGS.MenuShort = onoff
|
_SETTINGS.MenuShort = onoff
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Set menu to be static.
|
--- Set menu to be static.
|
||||||
-- @param #SETTINGS self
|
-- @param #SETTINGS self
|
||||||
-- @param #boolean onoff If *true* menu is static. If *false* menu will be updated after changes (default).
|
-- @param #boolean onoff If *true* menu is static. If *false* menu will be updated after changes (default).
|
||||||
function SETTINGS:SetMenuStatic(onoff)
|
function SETTINGS:SetMenuStatic( onoff )
|
||||||
_SETTINGS.MenuStatic = onoff
|
_SETTINGS.MenuStatic = onoff
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -289,7 +287,7 @@ do -- SETTINGS
|
|||||||
-- @param #SETTINGS self
|
-- @param #SETTINGS self
|
||||||
-- @return #boolean true if metric.
|
-- @return #boolean true if metric.
|
||||||
function SETTINGS:IsMetric()
|
function SETTINGS:IsMetric()
|
||||||
return ( self.Metric ~= nil and self.Metric == true ) or ( self.Metric == nil and _SETTINGS:IsMetric() )
|
return (self.Metric ~= nil and self.Metric == true) or (self.Metric == nil and _SETTINGS:IsMetric())
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Sets the SETTINGS imperial.
|
--- Sets the SETTINGS imperial.
|
||||||
@@ -302,7 +300,7 @@ do -- SETTINGS
|
|||||||
-- @param #SETTINGS self
|
-- @param #SETTINGS self
|
||||||
-- @return #boolean true if imperial.
|
-- @return #boolean true if imperial.
|
||||||
function SETTINGS:IsImperial()
|
function SETTINGS:IsImperial()
|
||||||
return ( self.Metric ~= nil and self.Metric == false ) or ( self.Metric == nil and _SETTINGS:IsMetric() )
|
return (self.Metric ~= nil and self.Metric == false) or (self.Metric == nil and _SETTINGS:IsMetric())
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Sets the SETTINGS LL accuracy.
|
--- Sets the SETTINGS LL accuracy.
|
||||||
@@ -344,13 +342,12 @@ do -- SETTINGS
|
|||||||
self.MessageTypeTimings[MessageType] = MessageTime
|
self.MessageTypeTimings[MessageType] = MessageTime
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Gets the SETTINGS Message Display Timing of a MessageType
|
--- Gets the SETTINGS Message Display Timing of a MessageType
|
||||||
-- @param #SETTINGS self
|
-- @param #SETTINGS self
|
||||||
-- @param Core.Message#MESSAGE MessageType The type of the message.
|
-- @param Core.Message#MESSAGE MessageType The type of the message.
|
||||||
-- @return #number
|
-- @return #number
|
||||||
function SETTINGS:GetMessageTime( MessageType )
|
function SETTINGS:GetMessageTime( MessageType )
|
||||||
return ( self.MessageTypeTimings and self.MessageTypeTimings[MessageType] ) or _SETTINGS:GetMessageTime( MessageType )
|
return (self.MessageTypeTimings and self.MessageTypeTimings[MessageType]) or _SETTINGS:GetMessageTime( MessageType )
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Sets A2G LL DMS
|
--- Sets A2G LL DMS
|
||||||
@@ -371,14 +368,14 @@ do -- SETTINGS
|
|||||||
-- @param #SETTINGS self
|
-- @param #SETTINGS self
|
||||||
-- @return #boolean true if LL DMS
|
-- @return #boolean true if LL DMS
|
||||||
function SETTINGS:IsA2G_LL_DMS()
|
function SETTINGS:IsA2G_LL_DMS()
|
||||||
return ( self.A2GSystem and self.A2GSystem == "LL DMS" ) or ( not self.A2GSystem and _SETTINGS:IsA2G_LL_DMS() )
|
return (self.A2GSystem and self.A2GSystem == "LL DMS") or (not self.A2GSystem and _SETTINGS:IsA2G_LL_DMS())
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Is LL DDM
|
--- Is LL DDM
|
||||||
-- @param #SETTINGS self
|
-- @param #SETTINGS self
|
||||||
-- @return #boolean true if LL DDM
|
-- @return #boolean true if LL DDM
|
||||||
function SETTINGS:IsA2G_LL_DDM()
|
function SETTINGS:IsA2G_LL_DDM()
|
||||||
return ( self.A2GSystem and self.A2GSystem == "LL DDM" ) or ( not self.A2GSystem and _SETTINGS:IsA2G_LL_DDM() )
|
return (self.A2GSystem and self.A2GSystem == "LL DDM") or (not self.A2GSystem and _SETTINGS:IsA2G_LL_DDM())
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Sets A2G MGRS
|
--- Sets A2G MGRS
|
||||||
@@ -392,7 +389,7 @@ do -- SETTINGS
|
|||||||
-- @param #SETTINGS self
|
-- @param #SETTINGS self
|
||||||
-- @return #boolean true if MGRS
|
-- @return #boolean true if MGRS
|
||||||
function SETTINGS:IsA2G_MGRS()
|
function SETTINGS:IsA2G_MGRS()
|
||||||
return ( self.A2GSystem and self.A2GSystem == "MGRS" ) or ( not self.A2GSystem and _SETTINGS:IsA2G_MGRS() )
|
return (self.A2GSystem and self.A2GSystem == "MGRS") or (not self.A2GSystem and _SETTINGS:IsA2G_MGRS())
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Sets A2G BRA
|
--- Sets A2G BRA
|
||||||
@@ -406,7 +403,7 @@ do -- SETTINGS
|
|||||||
-- @param #SETTINGS self
|
-- @param #SETTINGS self
|
||||||
-- @return #boolean true if BRA
|
-- @return #boolean true if BRA
|
||||||
function SETTINGS:IsA2G_BR()
|
function SETTINGS:IsA2G_BR()
|
||||||
return ( self.A2GSystem and self.A2GSystem == "BR" ) or ( not self.A2GSystem and _SETTINGS:IsA2G_BR() )
|
return (self.A2GSystem and self.A2GSystem == "BR") or (not self.A2GSystem and _SETTINGS:IsA2G_BR())
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Sets A2A BRA
|
--- Sets A2A BRA
|
||||||
@@ -420,7 +417,7 @@ do -- SETTINGS
|
|||||||
-- @param #SETTINGS self
|
-- @param #SETTINGS self
|
||||||
-- @return #boolean true if BRA
|
-- @return #boolean true if BRA
|
||||||
function SETTINGS:IsA2A_BRAA()
|
function SETTINGS:IsA2A_BRAA()
|
||||||
return ( self.A2ASystem and self.A2ASystem == "BRAA" ) or ( not self.A2ASystem and _SETTINGS:IsA2A_BRAA() )
|
return (self.A2ASystem and self.A2ASystem == "BRAA") or (not self.A2ASystem and _SETTINGS:IsA2A_BRAA())
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Sets A2A BULLS
|
--- Sets A2A BULLS
|
||||||
@@ -434,7 +431,7 @@ do -- SETTINGS
|
|||||||
-- @param #SETTINGS self
|
-- @param #SETTINGS self
|
||||||
-- @return #boolean true if BULLS
|
-- @return #boolean true if BULLS
|
||||||
function SETTINGS:IsA2A_BULLS()
|
function SETTINGS:IsA2A_BULLS()
|
||||||
return ( self.A2ASystem and self.A2ASystem == "BULLS" ) or ( not self.A2ASystem and _SETTINGS:IsA2A_BULLS() )
|
return (self.A2ASystem and self.A2ASystem == "BULLS") or (not self.A2ASystem and _SETTINGS:IsA2A_BULLS())
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Sets A2A LL DMS
|
--- Sets A2A LL DMS
|
||||||
@@ -455,14 +452,14 @@ do -- SETTINGS
|
|||||||
-- @param #SETTINGS self
|
-- @param #SETTINGS self
|
||||||
-- @return #boolean true if LL DMS
|
-- @return #boolean true if LL DMS
|
||||||
function SETTINGS:IsA2A_LL_DMS()
|
function SETTINGS:IsA2A_LL_DMS()
|
||||||
return ( self.A2ASystem and self.A2ASystem == "LL DMS" ) or ( not self.A2ASystem and _SETTINGS:IsA2A_LL_DMS() )
|
return (self.A2ASystem and self.A2ASystem == "LL DMS") or (not self.A2ASystem and _SETTINGS:IsA2A_LL_DMS())
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Is LL DDM
|
--- Is LL DDM
|
||||||
-- @param #SETTINGS self
|
-- @param #SETTINGS self
|
||||||
-- @return #boolean true if LL DDM
|
-- @return #boolean true if LL DDM
|
||||||
function SETTINGS:IsA2A_LL_DDM()
|
function SETTINGS:IsA2A_LL_DDM()
|
||||||
return ( self.A2ASystem and self.A2ASystem == "LL DDM" ) or ( not self.A2ASystem and _SETTINGS:IsA2A_LL_DDM() )
|
return (self.A2ASystem and self.A2ASystem == "LL DDM") or (not self.A2ASystem and _SETTINGS:IsA2A_LL_DDM())
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Sets A2A MGRS
|
--- Sets A2A MGRS
|
||||||
@@ -476,7 +473,7 @@ do -- SETTINGS
|
|||||||
-- @param #SETTINGS self
|
-- @param #SETTINGS self
|
||||||
-- @return #boolean true if MGRS
|
-- @return #boolean true if MGRS
|
||||||
function SETTINGS:IsA2A_MGRS()
|
function SETTINGS:IsA2A_MGRS()
|
||||||
return ( self.A2ASystem and self.A2ASystem == "MGRS" ) or ( not self.A2ASystem and _SETTINGS:IsA2A_MGRS() )
|
return (self.A2ASystem and self.A2ASystem == "MGRS") or (not self.A2ASystem and _SETTINGS:IsA2A_MGRS())
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #SETTINGS self
|
--- @param #SETTINGS self
|
||||||
@@ -495,37 +492,37 @@ do -- SETTINGS
|
|||||||
-- A2G Coordinate System
|
-- A2G Coordinate System
|
||||||
-------
|
-------
|
||||||
|
|
||||||
local text="A2G Coordinate System"
|
local text = "A2G Coordinate System"
|
||||||
if _SETTINGS.MenuShort then
|
if _SETTINGS.MenuShort then
|
||||||
text="A2G Coordinates"
|
text = "A2G Coordinates"
|
||||||
end
|
end
|
||||||
local A2GCoordinateMenu = MENU_GROUP:New( MenuGroup, text, SettingsMenu ):SetTime( MenuTime )
|
local A2GCoordinateMenu = MENU_GROUP:New( MenuGroup, text, SettingsMenu ):SetTime( MenuTime )
|
||||||
|
|
||||||
-- Set LL DMS
|
-- Set LL DMS
|
||||||
if not self:IsA2G_LL_DMS() then
|
if not self:IsA2G_LL_DMS() then
|
||||||
local text="Lat/Lon Degree Min Sec (LL DMS)"
|
local text = "Lat/Lon Degree Min Sec (LL DMS)"
|
||||||
if _SETTINGS.MenuShort then
|
if _SETTINGS.MenuShort then
|
||||||
text="LL DMS"
|
text = "LL DMS"
|
||||||
end
|
end
|
||||||
MENU_GROUP_COMMAND:New( MenuGroup, text, A2GCoordinateMenu, self.A2GMenuSystem, self, MenuGroup, RootMenu, "LL DMS" ):SetTime( MenuTime )
|
MENU_GROUP_COMMAND:New( MenuGroup, text, A2GCoordinateMenu, self.A2GMenuSystem, self, MenuGroup, RootMenu, "LL DMS" ):SetTime( MenuTime )
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Set LL DDM
|
-- Set LL DDM
|
||||||
if not self:IsA2G_LL_DDM() then
|
if not self:IsA2G_LL_DDM() then
|
||||||
local text="Lat/Lon Degree Dec Min (LL DDM)"
|
local text = "Lat/Lon Degree Dec Min (LL DDM)"
|
||||||
if _SETTINGS.MenuShort then
|
if _SETTINGS.MenuShort then
|
||||||
text="LL DDM"
|
text = "LL DDM"
|
||||||
end
|
end
|
||||||
MENU_GROUP_COMMAND:New( MenuGroup, "Lat/Lon Degree Dec Min (LL DDM)", A2GCoordinateMenu, self.A2GMenuSystem, self, MenuGroup, RootMenu, "LL DDM" ):SetTime( MenuTime )
|
MENU_GROUP_COMMAND:New( MenuGroup, "Lat/Lon Degree Dec Min (LL DDM)", A2GCoordinateMenu, self.A2GMenuSystem, self, MenuGroup, RootMenu, "LL DDM" ):SetTime( MenuTime )
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Set LL DMS accuracy.
|
-- Set LL DMS accuracy.
|
||||||
if self:IsA2G_LL_DDM() then
|
if self:IsA2G_LL_DDM() then
|
||||||
local text1="LL DDM Accuracy 1"
|
local text1 = "LL DDM Accuracy 1"
|
||||||
local text2="LL DDM Accuracy 2"
|
local text2 = "LL DDM Accuracy 2"
|
||||||
local text3="LL DDM Accuracy 3"
|
local text3 = "LL DDM Accuracy 3"
|
||||||
if _SETTINGS.MenuShort then
|
if _SETTINGS.MenuShort then
|
||||||
text1="LL DDM"
|
text1 = "LL DDM"
|
||||||
end
|
end
|
||||||
MENU_GROUP_COMMAND:New( MenuGroup, "LL DDM Accuracy 1", A2GCoordinateMenu, self.MenuLL_DDM_Accuracy, self, MenuGroup, RootMenu, 1 ):SetTime( MenuTime )
|
MENU_GROUP_COMMAND:New( MenuGroup, "LL DDM Accuracy 1", A2GCoordinateMenu, self.MenuLL_DDM_Accuracy, self, MenuGroup, RootMenu, 1 ):SetTime( MenuTime )
|
||||||
MENU_GROUP_COMMAND:New( MenuGroup, "LL DDM Accuracy 2", A2GCoordinateMenu, self.MenuLL_DDM_Accuracy, self, MenuGroup, RootMenu, 2 ):SetTime( MenuTime )
|
MENU_GROUP_COMMAND:New( MenuGroup, "LL DDM Accuracy 2", A2GCoordinateMenu, self.MenuLL_DDM_Accuracy, self, MenuGroup, RootMenu, 2 ):SetTime( MenuTime )
|
||||||
@@ -534,18 +531,18 @@ do -- SETTINGS
|
|||||||
|
|
||||||
-- Set BR.
|
-- Set BR.
|
||||||
if not self:IsA2G_BR() then
|
if not self:IsA2G_BR() then
|
||||||
local text="Bearing, Range (BR)"
|
local text = "Bearing, Range (BR)"
|
||||||
if _SETTINGS.MenuShort then
|
if _SETTINGS.MenuShort then
|
||||||
text="BR"
|
text = "BR"
|
||||||
end
|
end
|
||||||
MENU_GROUP_COMMAND:New( MenuGroup, text , A2GCoordinateMenu, self.A2GMenuSystem, self, MenuGroup, RootMenu, "BR" ):SetTime( MenuTime )
|
MENU_GROUP_COMMAND:New( MenuGroup, text, A2GCoordinateMenu, self.A2GMenuSystem, self, MenuGroup, RootMenu, "BR" ):SetTime( MenuTime )
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Set MGRS.
|
-- Set MGRS.
|
||||||
if not self:IsA2G_MGRS() then
|
if not self:IsA2G_MGRS() then
|
||||||
local text="Military Grid (MGRS)"
|
local text = "Military Grid (MGRS)"
|
||||||
if _SETTINGS.MenuShort then
|
if _SETTINGS.MenuShort then
|
||||||
text="MGRS"
|
text = "MGRS"
|
||||||
end
|
end
|
||||||
MENU_GROUP_COMMAND:New( MenuGroup, text, A2GCoordinateMenu, self.A2GMenuSystem, self, MenuGroup, RootMenu, "MGRS" ):SetTime( MenuTime )
|
MENU_GROUP_COMMAND:New( MenuGroup, text, A2GCoordinateMenu, self.A2GMenuSystem, self, MenuGroup, RootMenu, "MGRS" ):SetTime( MenuTime )
|
||||||
end
|
end
|
||||||
@@ -563,24 +560,24 @@ do -- SETTINGS
|
|||||||
-- A2A Coordinate System
|
-- A2A Coordinate System
|
||||||
-------
|
-------
|
||||||
|
|
||||||
local text="A2A Coordinate System"
|
local text = "A2A Coordinate System"
|
||||||
if _SETTINGS.MenuShort then
|
if _SETTINGS.MenuShort then
|
||||||
text="A2A Coordinates"
|
text = "A2A Coordinates"
|
||||||
end
|
end
|
||||||
local A2ACoordinateMenu = MENU_GROUP:New( MenuGroup, text, SettingsMenu ):SetTime( MenuTime )
|
local A2ACoordinateMenu = MENU_GROUP:New( MenuGroup, text, SettingsMenu ):SetTime( MenuTime )
|
||||||
|
|
||||||
if not self:IsA2A_LL_DMS() then
|
if not self:IsA2A_LL_DMS() then
|
||||||
local text="Lat/Lon Degree Min Sec (LL DMS)"
|
local text = "Lat/Lon Degree Min Sec (LL DMS)"
|
||||||
if _SETTINGS.MenuShort then
|
if _SETTINGS.MenuShort then
|
||||||
text="LL DMS"
|
text = "LL DMS"
|
||||||
end
|
end
|
||||||
MENU_GROUP_COMMAND:New( MenuGroup, text, A2ACoordinateMenu, self.A2AMenuSystem, self, MenuGroup, RootMenu, "LL DMS" ):SetTime( MenuTime )
|
MENU_GROUP_COMMAND:New( MenuGroup, text, A2ACoordinateMenu, self.A2AMenuSystem, self, MenuGroup, RootMenu, "LL DMS" ):SetTime( MenuTime )
|
||||||
end
|
end
|
||||||
|
|
||||||
if not self:IsA2A_LL_DDM() then
|
if not self:IsA2A_LL_DDM() then
|
||||||
local text="Lat/Lon Degree Dec Min (LL DDM)"
|
local text = "Lat/Lon Degree Dec Min (LL DDM)"
|
||||||
if _SETTINGS.MenuShort then
|
if _SETTINGS.MenuShort then
|
||||||
text="LL DDM"
|
text = "LL DDM"
|
||||||
end
|
end
|
||||||
MENU_GROUP_COMMAND:New( MenuGroup, text, A2ACoordinateMenu, self.A2AMenuSystem, self, MenuGroup, RootMenu, "LL DDM" ):SetTime( MenuTime )
|
MENU_GROUP_COMMAND:New( MenuGroup, text, A2ACoordinateMenu, self.A2AMenuSystem, self, MenuGroup, RootMenu, "LL DDM" ):SetTime( MenuTime )
|
||||||
end
|
end
|
||||||
@@ -593,25 +590,25 @@ do -- SETTINGS
|
|||||||
end
|
end
|
||||||
|
|
||||||
if not self:IsA2A_BULLS() then
|
if not self:IsA2A_BULLS() then
|
||||||
local text="Bullseye (BULLS)"
|
local text = "Bullseye (BULLS)"
|
||||||
if _SETTINGS.MenuShort then
|
if _SETTINGS.MenuShort then
|
||||||
text="Bulls"
|
text = "Bulls"
|
||||||
end
|
end
|
||||||
MENU_GROUP_COMMAND:New( MenuGroup, text, A2ACoordinateMenu, self.A2AMenuSystem, self, MenuGroup, RootMenu, "BULLS" ):SetTime( MenuTime )
|
MENU_GROUP_COMMAND:New( MenuGroup, text, A2ACoordinateMenu, self.A2AMenuSystem, self, MenuGroup, RootMenu, "BULLS" ):SetTime( MenuTime )
|
||||||
end
|
end
|
||||||
|
|
||||||
if not self:IsA2A_BRAA() then
|
if not self:IsA2A_BRAA() then
|
||||||
local text="Bearing Range Altitude Aspect (BRAA)"
|
local text = "Bearing Range Altitude Aspect (BRAA)"
|
||||||
if _SETTINGS.MenuShort then
|
if _SETTINGS.MenuShort then
|
||||||
text="BRAA"
|
text = "BRAA"
|
||||||
end
|
end
|
||||||
MENU_GROUP_COMMAND:New( MenuGroup, text, A2ACoordinateMenu, self.A2AMenuSystem, self, MenuGroup, RootMenu, "BRAA" ):SetTime( MenuTime )
|
MENU_GROUP_COMMAND:New( MenuGroup, text, A2ACoordinateMenu, self.A2AMenuSystem, self, MenuGroup, RootMenu, "BRAA" ):SetTime( MenuTime )
|
||||||
end
|
end
|
||||||
|
|
||||||
if not self:IsA2A_MGRS() then
|
if not self:IsA2A_MGRS() then
|
||||||
local text="Military Grid (MGRS)"
|
local text = "Military Grid (MGRS)"
|
||||||
if _SETTINGS.MenuShort then
|
if _SETTINGS.MenuShort then
|
||||||
text="MGRS"
|
text = "MGRS"
|
||||||
end
|
end
|
||||||
MENU_GROUP_COMMAND:New( MenuGroup, text, A2ACoordinateMenu, self.A2AMenuSystem, self, MenuGroup, RootMenu, "MGRS" ):SetTime( MenuTime )
|
MENU_GROUP_COMMAND:New( MenuGroup, text, A2ACoordinateMenu, self.A2AMenuSystem, self, MenuGroup, RootMenu, "MGRS" ):SetTime( MenuTime )
|
||||||
end
|
end
|
||||||
@@ -624,31 +621,31 @@ do -- SETTINGS
|
|||||||
MENU_GROUP_COMMAND:New( MenuGroup, "MGRS Accuracy 5", A2ACoordinateMenu, self.MenuMGRS_Accuracy, self, MenuGroup, RootMenu, 5 ):SetTime( MenuTime )
|
MENU_GROUP_COMMAND:New( MenuGroup, "MGRS Accuracy 5", A2ACoordinateMenu, self.MenuMGRS_Accuracy, self, MenuGroup, RootMenu, 5 ):SetTime( MenuTime )
|
||||||
end
|
end
|
||||||
|
|
||||||
local text="Measures and Weights System"
|
local text = "Measures and Weights System"
|
||||||
if _SETTINGS.MenuShort then
|
if _SETTINGS.MenuShort then
|
||||||
text="Unit System"
|
text = "Unit System"
|
||||||
end
|
end
|
||||||
local MetricsMenu = MENU_GROUP:New( MenuGroup, text, SettingsMenu ):SetTime( MenuTime )
|
local MetricsMenu = MENU_GROUP:New( MenuGroup, text, SettingsMenu ):SetTime( MenuTime )
|
||||||
|
|
||||||
if self:IsMetric() then
|
if self:IsMetric() then
|
||||||
local text="Imperial (Miles,Feet)"
|
local text = "Imperial (Miles,Feet)"
|
||||||
if _SETTINGS.MenuShort then
|
if _SETTINGS.MenuShort then
|
||||||
text="Imperial"
|
text = "Imperial"
|
||||||
end
|
end
|
||||||
MENU_GROUP_COMMAND:New( MenuGroup, text, MetricsMenu, self.MenuMWSystem, self, MenuGroup, RootMenu, false ):SetTime( MenuTime )
|
MENU_GROUP_COMMAND:New( MenuGroup, text, MetricsMenu, self.MenuMWSystem, self, MenuGroup, RootMenu, false ):SetTime( MenuTime )
|
||||||
end
|
end
|
||||||
|
|
||||||
if self:IsImperial() then
|
if self:IsImperial() then
|
||||||
local text="Metric (Kilometers,Meters)"
|
local text = "Metric (Kilometers,Meters)"
|
||||||
if _SETTINGS.MenuShort then
|
if _SETTINGS.MenuShort then
|
||||||
text="Metric"
|
text = "Metric"
|
||||||
end
|
end
|
||||||
MENU_GROUP_COMMAND:New( MenuGroup, text, MetricsMenu, self.MenuMWSystem, self, MenuGroup, RootMenu, true ):SetTime( MenuTime )
|
MENU_GROUP_COMMAND:New( MenuGroup, text, MetricsMenu, self.MenuMWSystem, self, MenuGroup, RootMenu, true ):SetTime( MenuTime )
|
||||||
end
|
end
|
||||||
|
|
||||||
local text="Messages and Reports"
|
local text = "Messages and Reports"
|
||||||
if _SETTINGS.MenuShort then
|
if _SETTINGS.MenuShort then
|
||||||
text="Messages & Reports"
|
text = "Messages & Reports"
|
||||||
end
|
end
|
||||||
local MessagesMenu = MENU_GROUP:New( MenuGroup, text, SettingsMenu ):SetTime( MenuTime )
|
local MessagesMenu = MENU_GROUP:New( MenuGroup, text, SettingsMenu ):SetTime( MenuTime )
|
||||||
|
|
||||||
@@ -689,7 +686,6 @@ do -- SETTINGS
|
|||||||
MENU_GROUP_COMMAND:New( MenuGroup, "2 minutes", DetailedReportsMenu, self.MenuMessageTimingsSystem, self, MenuGroup, RootMenu, MESSAGE.Type.DetailedReportsMenu, 120 ):SetTime( MenuTime )
|
MENU_GROUP_COMMAND:New( MenuGroup, "2 minutes", DetailedReportsMenu, self.MenuMessageTimingsSystem, self, MenuGroup, RootMenu, MESSAGE.Type.DetailedReportsMenu, 120 ):SetTime( MenuTime )
|
||||||
MENU_GROUP_COMMAND:New( MenuGroup, "3 minutes", DetailedReportsMenu, self.MenuMessageTimingsSystem, self, MenuGroup, RootMenu, MESSAGE.Type.DetailedReportsMenu, 180 ):SetTime( MenuTime )
|
MENU_GROUP_COMMAND:New( MenuGroup, "3 minutes", DetailedReportsMenu, self.MenuMessageTimingsSystem, self, MenuGroup, RootMenu, MESSAGE.Type.DetailedReportsMenu, 180 ):SetTime( MenuTime )
|
||||||
|
|
||||||
|
|
||||||
SettingsMenu:Remove( MenuTime )
|
SettingsMenu:Remove( MenuTime )
|
||||||
|
|
||||||
return self
|
return self
|
||||||
@@ -733,11 +729,11 @@ do -- SETTINGS
|
|||||||
|
|
||||||
self.PlayerMenu = PlayerMenu
|
self.PlayerMenu = PlayerMenu
|
||||||
|
|
||||||
self:I(string.format("Setting menu for player %s", tostring(PlayerName)))
|
self:I( string.format( "Setting menu for player %s", tostring( PlayerName ) ) )
|
||||||
|
|
||||||
local submenu = MENU_GROUP:New( PlayerGroup, "LL Accuracy", PlayerMenu )
|
local submenu = MENU_GROUP:New( PlayerGroup, "LL Accuracy", PlayerMenu )
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "LL 0 Decimals", submenu, self.MenuGroupLL_DDM_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 0 )
|
MENU_GROUP_COMMAND:New( PlayerGroup, "LL 0 Decimals", submenu, self.MenuGroupLL_DDM_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 0 )
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "LL 1 Decimal", submenu, self.MenuGroupLL_DDM_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 1 )
|
MENU_GROUP_COMMAND:New( PlayerGroup, "LL 1 Decimal", submenu, self.MenuGroupLL_DDM_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 1 )
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "LL 2 Decimals", submenu, self.MenuGroupLL_DDM_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 2 )
|
MENU_GROUP_COMMAND:New( PlayerGroup, "LL 2 Decimals", submenu, self.MenuGroupLL_DDM_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 2 )
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "LL 3 Decimals", submenu, self.MenuGroupLL_DDM_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 3 )
|
MENU_GROUP_COMMAND:New( PlayerGroup, "LL 3 Decimals", submenu, self.MenuGroupLL_DDM_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 3 )
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "LL 4 Decimals", submenu, self.MenuGroupLL_DDM_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 4 )
|
MENU_GROUP_COMMAND:New( PlayerGroup, "LL 4 Decimals", submenu, self.MenuGroupLL_DDM_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 4 )
|
||||||
@@ -754,40 +750,40 @@ do -- SETTINGS
|
|||||||
-- A2G Coordinate System
|
-- A2G Coordinate System
|
||||||
------
|
------
|
||||||
|
|
||||||
local text="A2G Coordinate System"
|
local text = "A2G Coordinate System"
|
||||||
if _SETTINGS.MenuShort then
|
if _SETTINGS.MenuShort then
|
||||||
text="A2G Coordinates"
|
text = "A2G Coordinates"
|
||||||
end
|
end
|
||||||
local A2GCoordinateMenu = MENU_GROUP:New( PlayerGroup, text, PlayerMenu )
|
local A2GCoordinateMenu = MENU_GROUP:New( PlayerGroup, text, PlayerMenu )
|
||||||
|
|
||||||
if not self:IsA2G_LL_DMS() or _SETTINGS.MenuStatic then
|
if not self:IsA2G_LL_DMS() or _SETTINGS.MenuStatic then
|
||||||
local text="Lat/Lon Degree Min Sec (LL DMS)"
|
local text = "Lat/Lon Degree Min Sec (LL DMS)"
|
||||||
if _SETTINGS.MenuShort then
|
if _SETTINGS.MenuShort then
|
||||||
text="A2G LL DMS"
|
text = "A2G LL DMS"
|
||||||
end
|
end
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, text, A2GCoordinateMenu, self.MenuGroupA2GSystem, self, PlayerUnit, PlayerGroup, PlayerName, "LL DMS" )
|
MENU_GROUP_COMMAND:New( PlayerGroup, text, A2GCoordinateMenu, self.MenuGroupA2GSystem, self, PlayerUnit, PlayerGroup, PlayerName, "LL DMS" )
|
||||||
end
|
end
|
||||||
|
|
||||||
if not self:IsA2G_LL_DDM() or _SETTINGS.MenuStatic then
|
if not self:IsA2G_LL_DDM() or _SETTINGS.MenuStatic then
|
||||||
local text="Lat/Lon Degree Dec Min (LL DDM)"
|
local text = "Lat/Lon Degree Dec Min (LL DDM)"
|
||||||
if _SETTINGS.MenuShort then
|
if _SETTINGS.MenuShort then
|
||||||
text="A2G LL DDM"
|
text = "A2G LL DDM"
|
||||||
end
|
end
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, text, A2GCoordinateMenu, self.MenuGroupA2GSystem, self, PlayerUnit, PlayerGroup, PlayerName, "LL DDM" )
|
MENU_GROUP_COMMAND:New( PlayerGroup, text, A2GCoordinateMenu, self.MenuGroupA2GSystem, self, PlayerUnit, PlayerGroup, PlayerName, "LL DDM" )
|
||||||
end
|
end
|
||||||
|
|
||||||
if not self:IsA2G_BR() or _SETTINGS.MenuStatic then
|
if not self:IsA2G_BR() or _SETTINGS.MenuStatic then
|
||||||
local text="Bearing, Range (BR)"
|
local text = "Bearing, Range (BR)"
|
||||||
if _SETTINGS.MenuShort then
|
if _SETTINGS.MenuShort then
|
||||||
text="A2G BR"
|
text = "A2G BR"
|
||||||
end
|
end
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, text, A2GCoordinateMenu, self.MenuGroupA2GSystem, self, PlayerUnit, PlayerGroup, PlayerName, "BR" )
|
MENU_GROUP_COMMAND:New( PlayerGroup, text, A2GCoordinateMenu, self.MenuGroupA2GSystem, self, PlayerUnit, PlayerGroup, PlayerName, "BR" )
|
||||||
end
|
end
|
||||||
|
|
||||||
if not self:IsA2G_MGRS() or _SETTINGS.MenuStatic then
|
if not self:IsA2G_MGRS() or _SETTINGS.MenuStatic then
|
||||||
local text="Military Grid (MGRS)"
|
local text = "Military Grid (MGRS)"
|
||||||
if _SETTINGS.MenuShort then
|
if _SETTINGS.MenuShort then
|
||||||
text="A2G MGRS"
|
text = "A2G MGRS"
|
||||||
end
|
end
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, text, A2GCoordinateMenu, self.MenuGroupA2GSystem, self, PlayerUnit, PlayerGroup, PlayerName, "MGRS" )
|
MENU_GROUP_COMMAND:New( PlayerGroup, text, A2GCoordinateMenu, self.MenuGroupA2GSystem, self, PlayerUnit, PlayerGroup, PlayerName, "MGRS" )
|
||||||
end
|
end
|
||||||
@@ -796,49 +792,48 @@ do -- SETTINGS
|
|||||||
-- A2A Coordinates Menu
|
-- A2A Coordinates Menu
|
||||||
------
|
------
|
||||||
|
|
||||||
local text="A2A Coordinate System"
|
local text = "A2A Coordinate System"
|
||||||
if _SETTINGS.MenuShort then
|
if _SETTINGS.MenuShort then
|
||||||
text="A2A Coordinates"
|
text = "A2A Coordinates"
|
||||||
end
|
end
|
||||||
local A2ACoordinateMenu = MENU_GROUP:New( PlayerGroup, text, PlayerMenu )
|
local A2ACoordinateMenu = MENU_GROUP:New( PlayerGroup, text, PlayerMenu )
|
||||||
|
|
||||||
|
|
||||||
if not self:IsA2A_LL_DMS() or _SETTINGS.MenuStatic then
|
if not self:IsA2A_LL_DMS() or _SETTINGS.MenuStatic then
|
||||||
local text="Lat/Lon Degree Min Sec (LL DMS)"
|
local text = "Lat/Lon Degree Min Sec (LL DMS)"
|
||||||
if _SETTINGS.MenuShort then
|
if _SETTINGS.MenuShort then
|
||||||
text="A2A LL DMS"
|
text = "A2A LL DMS"
|
||||||
end
|
end
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, text, A2ACoordinateMenu, self.MenuGroupA2GSystem, self, PlayerUnit, PlayerGroup, PlayerName, "LL DMS" )
|
MENU_GROUP_COMMAND:New( PlayerGroup, text, A2ACoordinateMenu, self.MenuGroupA2GSystem, self, PlayerUnit, PlayerGroup, PlayerName, "LL DMS" )
|
||||||
end
|
end
|
||||||
|
|
||||||
if not self:IsA2A_LL_DDM() or _SETTINGS.MenuStatic then
|
if not self:IsA2A_LL_DDM() or _SETTINGS.MenuStatic then
|
||||||
local text="Lat/Lon Degree Dec Min (LL DDM)"
|
local text = "Lat/Lon Degree Dec Min (LL DDM)"
|
||||||
if _SETTINGS.MenuShort then
|
if _SETTINGS.MenuShort then
|
||||||
text="A2A LL DDM"
|
text = "A2A LL DDM"
|
||||||
end
|
end
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, text, A2ACoordinateMenu, self.MenuGroupA2ASystem, self, PlayerUnit, PlayerGroup, PlayerName, "LL DDM" )
|
MENU_GROUP_COMMAND:New( PlayerGroup, text, A2ACoordinateMenu, self.MenuGroupA2ASystem, self, PlayerUnit, PlayerGroup, PlayerName, "LL DDM" )
|
||||||
end
|
end
|
||||||
|
|
||||||
if not self:IsA2A_BULLS() or _SETTINGS.MenuStatic then
|
if not self:IsA2A_BULLS() or _SETTINGS.MenuStatic then
|
||||||
local text="Bullseye (BULLS)"
|
local text = "Bullseye (BULLS)"
|
||||||
if _SETTINGS.MenuShort then
|
if _SETTINGS.MenuShort then
|
||||||
text="A2A BULLS"
|
text = "A2A BULLS"
|
||||||
end
|
end
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, text, A2ACoordinateMenu, self.MenuGroupA2ASystem, self, PlayerUnit, PlayerGroup, PlayerName, "BULLS" )
|
MENU_GROUP_COMMAND:New( PlayerGroup, text, A2ACoordinateMenu, self.MenuGroupA2ASystem, self, PlayerUnit, PlayerGroup, PlayerName, "BULLS" )
|
||||||
end
|
end
|
||||||
|
|
||||||
if not self:IsA2A_BRAA() or _SETTINGS.MenuStatic then
|
if not self:IsA2A_BRAA() or _SETTINGS.MenuStatic then
|
||||||
local text="Bearing Range Altitude Aspect (BRAA)"
|
local text = "Bearing Range Altitude Aspect (BRAA)"
|
||||||
if _SETTINGS.MenuShort then
|
if _SETTINGS.MenuShort then
|
||||||
text="A2A BRAA"
|
text = "A2A BRAA"
|
||||||
end
|
end
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, text, A2ACoordinateMenu, self.MenuGroupA2ASystem, self, PlayerUnit, PlayerGroup, PlayerName, "BRAA" )
|
MENU_GROUP_COMMAND:New( PlayerGroup, text, A2ACoordinateMenu, self.MenuGroupA2ASystem, self, PlayerUnit, PlayerGroup, PlayerName, "BRAA" )
|
||||||
end
|
end
|
||||||
|
|
||||||
if not self:IsA2A_MGRS() or _SETTINGS.MenuStatic then
|
if not self:IsA2A_MGRS() or _SETTINGS.MenuStatic then
|
||||||
local text="Military Grid (MGRS)"
|
local text = "Military Grid (MGRS)"
|
||||||
if _SETTINGS.MenuShort then
|
if _SETTINGS.MenuShort then
|
||||||
text="A2A MGRS"
|
text = "A2A MGRS"
|
||||||
end
|
end
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, text, A2ACoordinateMenu, self.MenuGroupA2ASystem, self, PlayerUnit, PlayerGroup, PlayerName, "MGRS" )
|
MENU_GROUP_COMMAND:New( PlayerGroup, text, A2ACoordinateMenu, self.MenuGroupA2ASystem, self, PlayerUnit, PlayerGroup, PlayerName, "MGRS" )
|
||||||
end
|
end
|
||||||
@@ -847,24 +842,24 @@ do -- SETTINGS
|
|||||||
-- Unit system
|
-- Unit system
|
||||||
---
|
---
|
||||||
|
|
||||||
local text="Measures and Weights System"
|
local text = "Measures and Weights System"
|
||||||
if _SETTINGS.MenuShort then
|
if _SETTINGS.MenuShort then
|
||||||
text="Unit System"
|
text = "Unit System"
|
||||||
end
|
end
|
||||||
local MetricsMenu = MENU_GROUP:New( PlayerGroup, text, PlayerMenu )
|
local MetricsMenu = MENU_GROUP:New( PlayerGroup, text, PlayerMenu )
|
||||||
|
|
||||||
if self:IsMetric() or _SETTINGS.MenuStatic then
|
if self:IsMetric() or _SETTINGS.MenuStatic then
|
||||||
local text="Imperial (Miles,Feet)"
|
local text = "Imperial (Miles,Feet)"
|
||||||
if _SETTINGS.MenuShort then
|
if _SETTINGS.MenuShort then
|
||||||
text="Imperial"
|
text = "Imperial"
|
||||||
end
|
end
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, text, MetricsMenu, self.MenuGroupMWSystem, self, PlayerUnit, PlayerGroup, PlayerName, false )
|
MENU_GROUP_COMMAND:New( PlayerGroup, text, MetricsMenu, self.MenuGroupMWSystem, self, PlayerUnit, PlayerGroup, PlayerName, false )
|
||||||
end
|
end
|
||||||
|
|
||||||
if self:IsImperial() or _SETTINGS.MenuStatic then
|
if self:IsImperial() or _SETTINGS.MenuStatic then
|
||||||
local text="Metric (Kilometers,Meters)"
|
local text = "Metric (Kilometers,Meters)"
|
||||||
if _SETTINGS.MenuShort then
|
if _SETTINGS.MenuShort then
|
||||||
text="Metric"
|
text = "Metric"
|
||||||
end
|
end
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, text, MetricsMenu, self.MenuGroupMWSystem, self, PlayerUnit, PlayerGroup, PlayerName, true )
|
MENU_GROUP_COMMAND:New( PlayerGroup, text, MetricsMenu, self.MenuGroupMWSystem, self, PlayerUnit, PlayerGroup, PlayerName, true )
|
||||||
end
|
end
|
||||||
@@ -873,9 +868,9 @@ do -- SETTINGS
|
|||||||
-- Messages and Reports
|
-- Messages and Reports
|
||||||
---
|
---
|
||||||
|
|
||||||
local text="Messages and Reports"
|
local text = "Messages and Reports"
|
||||||
if _SETTINGS.MenuShort then
|
if _SETTINGS.MenuShort then
|
||||||
text="Messages & Reports"
|
text = "Messages & Reports"
|
||||||
end
|
end
|
||||||
local MessagesMenu = MENU_GROUP:New( PlayerGroup, text, PlayerMenu )
|
local MessagesMenu = MENU_GROUP:New( PlayerGroup, text, PlayerMenu )
|
||||||
|
|
||||||
@@ -935,39 +930,38 @@ do -- SETTINGS
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- @param #SETTINGS self
|
--- @param #SETTINGS self
|
||||||
function SETTINGS:A2GMenuSystem( MenuGroup, RootMenu, A2GSystem )
|
function SETTINGS:A2GMenuSystem( MenuGroup, RootMenu, A2GSystem )
|
||||||
self.A2GSystem = A2GSystem
|
self.A2GSystem = A2GSystem
|
||||||
MESSAGE:New( string.format("Settings: Default A2G coordinate system set to %s for all players!", A2GSystem ), 5 ):ToAll()
|
MESSAGE:New( string.format( "Settings: Default A2G coordinate system set to %s for all players!", A2GSystem ), 5 ):ToAll()
|
||||||
self:SetSystemMenu( MenuGroup, RootMenu )
|
self:SetSystemMenu( MenuGroup, RootMenu )
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #SETTINGS self
|
--- @param #SETTINGS self
|
||||||
function SETTINGS:A2AMenuSystem( MenuGroup, RootMenu, A2ASystem )
|
function SETTINGS:A2AMenuSystem( MenuGroup, RootMenu, A2ASystem )
|
||||||
self.A2ASystem = A2ASystem
|
self.A2ASystem = A2ASystem
|
||||||
MESSAGE:New( string.format("Settings: Default A2A coordinate system set to %s for all players!", A2ASystem ), 5 ):ToAll()
|
MESSAGE:New( string.format( "Settings: Default A2A coordinate system set to %s for all players!", A2ASystem ), 5 ):ToAll()
|
||||||
self:SetSystemMenu( MenuGroup, RootMenu )
|
self:SetSystemMenu( MenuGroup, RootMenu )
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #SETTINGS self
|
--- @param #SETTINGS self
|
||||||
function SETTINGS:MenuLL_DDM_Accuracy( MenuGroup, RootMenu, LL_Accuracy )
|
function SETTINGS:MenuLL_DDM_Accuracy( MenuGroup, RootMenu, LL_Accuracy )
|
||||||
self.LL_Accuracy = LL_Accuracy
|
self.LL_Accuracy = LL_Accuracy
|
||||||
MESSAGE:New( string.format("Settings: Default LL accuracy set to %s for all players!", LL_Accuracy ), 5 ):ToAll()
|
MESSAGE:New( string.format( "Settings: Default LL accuracy set to %s for all players!", LL_Accuracy ), 5 ):ToAll()
|
||||||
self:SetSystemMenu( MenuGroup, RootMenu )
|
self:SetSystemMenu( MenuGroup, RootMenu )
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #SETTINGS self
|
--- @param #SETTINGS self
|
||||||
function SETTINGS:MenuMGRS_Accuracy( MenuGroup, RootMenu, MGRS_Accuracy )
|
function SETTINGS:MenuMGRS_Accuracy( MenuGroup, RootMenu, MGRS_Accuracy )
|
||||||
self.MGRS_Accuracy = MGRS_Accuracy
|
self.MGRS_Accuracy = MGRS_Accuracy
|
||||||
MESSAGE:New( string.format("Settings: Default MGRS accuracy set to %s for all players!", MGRS_Accuracy ), 5 ):ToAll()
|
MESSAGE:New( string.format( "Settings: Default MGRS accuracy set to %s for all players!", MGRS_Accuracy ), 5 ):ToAll()
|
||||||
self:SetSystemMenu( MenuGroup, RootMenu )
|
self:SetSystemMenu( MenuGroup, RootMenu )
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #SETTINGS self
|
--- @param #SETTINGS self
|
||||||
function SETTINGS:MenuMWSystem( MenuGroup, RootMenu, MW )
|
function SETTINGS:MenuMWSystem( MenuGroup, RootMenu, MW )
|
||||||
self.Metric = MW
|
self.Metric = MW
|
||||||
MESSAGE:New( string.format("Settings: Default measurement format set to %s for all players!", MW and "Metric" or "Imperial" ), 5 ):ToAll()
|
MESSAGE:New( string.format( "Settings: Default measurement format set to %s for all players!", MW and "Metric" or "Imperial" ), 5 ):ToAll()
|
||||||
self:SetSystemMenu( MenuGroup, RootMenu )
|
self:SetSystemMenu( MenuGroup, RootMenu )
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -980,12 +974,12 @@ do -- SETTINGS
|
|||||||
do
|
do
|
||||||
--- @param #SETTINGS self
|
--- @param #SETTINGS self
|
||||||
function SETTINGS:MenuGroupA2GSystem( PlayerUnit, PlayerGroup, PlayerName, A2GSystem )
|
function SETTINGS:MenuGroupA2GSystem( PlayerUnit, PlayerGroup, PlayerName, A2GSystem )
|
||||||
BASE:E( {self, PlayerUnit:GetName(), A2GSystem} )
|
BASE:E( { self, PlayerUnit:GetName(), A2GSystem } )
|
||||||
self.A2GSystem = A2GSystem
|
self.A2GSystem = A2GSystem
|
||||||
MESSAGE:New( string.format( "Settings: A2G format set to %s for player %s.", A2GSystem, PlayerName ), 5 ):ToGroup( PlayerGroup )
|
MESSAGE:New( string.format( "Settings: A2G format set to %s for player %s.", A2GSystem, PlayerName ), 5 ):ToGroup( PlayerGroup )
|
||||||
if _SETTINGS.MenuStatic==false then
|
if _SETTINGS.MenuStatic == false then
|
||||||
self:RemovePlayerMenu(PlayerUnit)
|
self:RemovePlayerMenu( PlayerUnit )
|
||||||
self:SetPlayerMenu(PlayerUnit)
|
self:SetPlayerMenu( PlayerUnit )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -993,9 +987,9 @@ do -- SETTINGS
|
|||||||
function SETTINGS:MenuGroupA2ASystem( PlayerUnit, PlayerGroup, PlayerName, A2ASystem )
|
function SETTINGS:MenuGroupA2ASystem( PlayerUnit, PlayerGroup, PlayerName, A2ASystem )
|
||||||
self.A2ASystem = A2ASystem
|
self.A2ASystem = A2ASystem
|
||||||
MESSAGE:New( string.format( "Settings: A2A format set to %s for player %s.", A2ASystem, PlayerName ), 5 ):ToGroup( PlayerGroup )
|
MESSAGE:New( string.format( "Settings: A2A format set to %s for player %s.", A2ASystem, PlayerName ), 5 ):ToGroup( PlayerGroup )
|
||||||
if _SETTINGS.MenuStatic==false then
|
if _SETTINGS.MenuStatic == false then
|
||||||
self:RemovePlayerMenu(PlayerUnit)
|
self:RemovePlayerMenu( PlayerUnit )
|
||||||
self:SetPlayerMenu(PlayerUnit)
|
self:SetPlayerMenu( PlayerUnit )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1003,9 +997,9 @@ do -- SETTINGS
|
|||||||
function SETTINGS:MenuGroupLL_DDM_AccuracySystem( PlayerUnit, PlayerGroup, PlayerName, LL_Accuracy )
|
function SETTINGS:MenuGroupLL_DDM_AccuracySystem( PlayerUnit, PlayerGroup, PlayerName, LL_Accuracy )
|
||||||
self.LL_Accuracy = LL_Accuracy
|
self.LL_Accuracy = LL_Accuracy
|
||||||
MESSAGE:New( string.format( "Settings: LL format accuracy set to %d decimal places for player %s.", LL_Accuracy, PlayerName ), 5 ):ToGroup( PlayerGroup )
|
MESSAGE:New( string.format( "Settings: LL format accuracy set to %d decimal places for player %s.", LL_Accuracy, PlayerName ), 5 ):ToGroup( PlayerGroup )
|
||||||
if _SETTINGS.MenuStatic==false then
|
if _SETTINGS.MenuStatic == false then
|
||||||
self:RemovePlayerMenu(PlayerUnit)
|
self:RemovePlayerMenu( PlayerUnit )
|
||||||
self:SetPlayerMenu(PlayerUnit)
|
self:SetPlayerMenu( PlayerUnit )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1013,9 +1007,9 @@ do -- SETTINGS
|
|||||||
function SETTINGS:MenuGroupMGRS_AccuracySystem( PlayerUnit, PlayerGroup, PlayerName, MGRS_Accuracy )
|
function SETTINGS:MenuGroupMGRS_AccuracySystem( PlayerUnit, PlayerGroup, PlayerName, MGRS_Accuracy )
|
||||||
self.MGRS_Accuracy = MGRS_Accuracy
|
self.MGRS_Accuracy = MGRS_Accuracy
|
||||||
MESSAGE:New( string.format( "Settings: MGRS format accuracy set to %d for player %s.", MGRS_Accuracy, PlayerName ), 5 ):ToGroup( PlayerGroup )
|
MESSAGE:New( string.format( "Settings: MGRS format accuracy set to %d for player %s.", MGRS_Accuracy, PlayerName ), 5 ):ToGroup( PlayerGroup )
|
||||||
if _SETTINGS.MenuStatic==false then
|
if _SETTINGS.MenuStatic == false then
|
||||||
self:RemovePlayerMenu(PlayerUnit)
|
self:RemovePlayerMenu( PlayerUnit )
|
||||||
self:SetPlayerMenu(PlayerUnit)
|
self:SetPlayerMenu( PlayerUnit )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1023,9 +1017,9 @@ do -- SETTINGS
|
|||||||
function SETTINGS:MenuGroupMWSystem( PlayerUnit, PlayerGroup, PlayerName, MW )
|
function SETTINGS:MenuGroupMWSystem( PlayerUnit, PlayerGroup, PlayerName, MW )
|
||||||
self.Metric = MW
|
self.Metric = MW
|
||||||
MESSAGE:New( string.format( "Settings: Measurement format set to %s for player %s.", MW and "Metric" or "Imperial", PlayerName ), 5 ):ToGroup( PlayerGroup )
|
MESSAGE:New( string.format( "Settings: Measurement format set to %s for player %s.", MW and "Metric" or "Imperial", PlayerName ), 5 ):ToGroup( PlayerGroup )
|
||||||
if _SETTINGS.MenuStatic==false then
|
if _SETTINGS.MenuStatic == false then
|
||||||
self:RemovePlayerMenu(PlayerUnit)
|
self:RemovePlayerMenu( PlayerUnit )
|
||||||
self:SetPlayerMenu(PlayerUnit)
|
self:SetPlayerMenu( PlayerUnit )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1055,7 +1049,6 @@ do -- SETTINGS
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Configures the era of the mission to be Cold war.
|
--- Configures the era of the mission to be Cold war.
|
||||||
-- @param #SETTINGS self
|
-- @param #SETTINGS self
|
||||||
-- @return #SETTINGS self
|
-- @return #SETTINGS self
|
||||||
@@ -1065,7 +1058,6 @@ do -- SETTINGS
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Configures the era of the mission to be Modern war.
|
--- Configures the era of the mission to be Modern war.
|
||||||
-- @param #SETTINGS self
|
-- @param #SETTINGS self
|
||||||
-- @return #SETTINGS self
|
-- @return #SETTINGS self
|
||||||
@@ -1075,7 +1067,4 @@ do -- SETTINGS
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -138,24 +138,24 @@ SPAWNSTATIC = {
|
|||||||
-- @return #SPAWNSTATIC self
|
-- @return #SPAWNSTATIC self
|
||||||
function SPAWNSTATIC:NewFromStatic(SpawnTemplateName, SpawnCountryID)
|
function SPAWNSTATIC:NewFromStatic(SpawnTemplateName, SpawnCountryID)
|
||||||
|
|
||||||
local self = BASE:Inherit( self, BASE:New() ) -- #SPAWNSTATIC
|
local self = BASE:Inherit( self, BASE:New() ) -- #SPAWNSTATIC
|
||||||
|
|
||||||
local TemplateStatic, CoalitionID, CategoryID, CountryID = _DATABASE:GetStaticGroupTemplate(SpawnTemplateName)
|
local TemplateStatic, CoalitionID, CategoryID, CountryID = _DATABASE:GetStaticGroupTemplate(SpawnTemplateName)
|
||||||
|
|
||||||
if TemplateStatic then
|
if TemplateStatic then
|
||||||
self.SpawnTemplatePrefix = SpawnTemplateName
|
self.SpawnTemplatePrefix = SpawnTemplateName
|
||||||
self.TemplateStaticUnit = UTILS.DeepCopy(TemplateStatic.units[1])
|
self.TemplateStaticUnit = UTILS.DeepCopy(TemplateStatic.units[1])
|
||||||
self.CountryID = SpawnCountryID or CountryID
|
self.CountryID = SpawnCountryID or CountryID
|
||||||
self.CategoryID = CategoryID
|
self.CategoryID = CategoryID
|
||||||
self.CoalitionID = CoalitionID
|
self.CoalitionID = CoalitionID
|
||||||
self.SpawnIndex = 0
|
self.SpawnIndex = 0
|
||||||
else
|
else
|
||||||
error( "SPAWNSTATIC:New: There is no static declared in the mission editor with SpawnTemplatePrefix = '" .. tostring(SpawnTemplateName) .. "'" )
|
error( "SPAWNSTATIC:New: There is no static declared in the mission editor with SpawnTemplatePrefix = '" .. tostring(SpawnTemplateName) .. "'" )
|
||||||
end
|
end
|
||||||
|
|
||||||
self:SetEventPriority( 5 )
|
self:SetEventPriority( 5 )
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Creates the main object to spawn a @{Static} given a template table.
|
--- Creates the main object to spawn a @{Static} given a template table.
|
||||||
@@ -422,7 +422,11 @@ function SPAWNSTATIC:_SpawnStatic(Template, CountryID)
|
|||||||
end
|
end
|
||||||
|
|
||||||
if self.InitCargo~=nil then
|
if self.InitCargo~=nil then
|
||||||
Template.isCargo=self.InitCargo
|
Template.canCargo=self.InitCargo
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.InitCargoMass~=nil then
|
||||||
|
Template.mass=self.InitCargoMass
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.InitLinkUnit then
|
if self.InitLinkUnit then
|
||||||
|
|||||||
@@ -183,12 +183,12 @@ function ZONE_BASE:IsCoordinateInZone( Coordinate )
|
|||||||
return InZone
|
return InZone
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Returns if a PointVec2 is within the zone.
|
--- Returns if a PointVec2 is within the zone. (Name is misleading, actually takes a #COORDINATE)
|
||||||
-- @param #ZONE_BASE self
|
-- @param #ZONE_BASE self
|
||||||
-- @param Core.Point#POINT_VEC2 PointVec2 The PointVec2 to test.
|
-- @param Core.Point#COORDINATE PointVec2 The coordinate to test.
|
||||||
-- @return #boolean true if the PointVec2 is within the zone.
|
-- @return #boolean true if the PointVec2 is within the zone.
|
||||||
function ZONE_BASE:IsPointVec2InZone( PointVec2 )
|
function ZONE_BASE:IsPointVec2InZone( Coordinate )
|
||||||
local InZone = self:IsVec2InZone( PointVec2:GetVec2() )
|
local InZone = self:IsVec2InZone( Coordinate:GetVec2() )
|
||||||
return InZone
|
return InZone
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -498,8 +498,8 @@ end
|
|||||||
--
|
--
|
||||||
-- @field #ZONE_RADIUS
|
-- @field #ZONE_RADIUS
|
||||||
ZONE_RADIUS = {
|
ZONE_RADIUS = {
|
||||||
ClassName="ZONE_RADIUS",
|
ClassName="ZONE_RADIUS",
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Constructor of @{#ZONE_RADIUS}, taking the zone name, the zone location and a radius.
|
--- Constructor of @{#ZONE_RADIUS}, taking the zone name, the zone location and a radius.
|
||||||
-- @param #ZONE_RADIUS self
|
-- @param #ZONE_RADIUS self
|
||||||
@@ -510,15 +510,15 @@ ZONE_RADIUS = {
|
|||||||
function ZONE_RADIUS:New( ZoneName, Vec2, Radius )
|
function ZONE_RADIUS:New( ZoneName, Vec2, Radius )
|
||||||
|
|
||||||
-- Inherit ZONE_BASE.
|
-- Inherit ZONE_BASE.
|
||||||
local self = BASE:Inherit( self, ZONE_BASE:New( ZoneName ) ) -- #ZONE_RADIUS
|
local self = BASE:Inherit( self, ZONE_BASE:New( ZoneName ) ) -- #ZONE_RADIUS
|
||||||
self:F( { ZoneName, Vec2, Radius } )
|
self:F( { ZoneName, Vec2, Radius } )
|
||||||
|
|
||||||
self.Radius = Radius
|
self.Radius = Radius
|
||||||
self.Vec2 = Vec2
|
self.Vec2 = Vec2
|
||||||
|
|
||||||
--self.Coordinate=COORDINATE:NewFromVec2(Vec2)
|
--self.Coordinate=COORDINATE:NewFromVec2(Vec2)
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Update zone from a 2D vector.
|
--- Update zone from a 2D vector.
|
||||||
@@ -746,11 +746,11 @@ end
|
|||||||
-- @param #ZONE_RADIUS self
|
-- @param #ZONE_RADIUS self
|
||||||
-- @return DCS#Vec2 The location of the zone.
|
-- @return DCS#Vec2 The location of the zone.
|
||||||
function ZONE_RADIUS:GetVec2()
|
function ZONE_RADIUS:GetVec2()
|
||||||
self:F2( self.ZoneName )
|
self:F2( self.ZoneName )
|
||||||
|
|
||||||
self:T2( { self.Vec2 } )
|
self:T2( { self.Vec2 } )
|
||||||
|
|
||||||
return self.Vec2
|
return self.Vec2
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Sets the @{DCS#Vec2} of the zone.
|
--- Sets the @{DCS#Vec2} of the zone.
|
||||||
@@ -1165,20 +1165,20 @@ end
|
|||||||
-- @param #number outer (optional) Maximal distance from the outer edge of the zone. Default is the radius of the zone.
|
-- @param #number outer (optional) Maximal distance from the outer edge of the zone. Default is the radius of the zone.
|
||||||
-- @return DCS#Vec2 The random location within the zone.
|
-- @return DCS#Vec2 The random location within the zone.
|
||||||
function ZONE_RADIUS:GetRandomVec2( inner, outer )
|
function ZONE_RADIUS:GetRandomVec2( inner, outer )
|
||||||
self:F( self.ZoneName, inner, outer )
|
self:F( self.ZoneName, inner, outer )
|
||||||
|
|
||||||
local Point = {}
|
local Point = {}
|
||||||
local Vec2 = self:GetVec2()
|
local Vec2 = self:GetVec2()
|
||||||
local _inner = inner or 0
|
local _inner = inner or 0
|
||||||
local _outer = outer or self:GetRadius()
|
local _outer = outer or self:GetRadius()
|
||||||
|
|
||||||
local angle = math.random() * math.pi * 2;
|
local angle = math.random() * math.pi * 2;
|
||||||
Point.x = Vec2.x + math.cos( angle ) * math.random(_inner, _outer);
|
Point.x = Vec2.x + math.cos( angle ) * math.random(_inner, _outer);
|
||||||
Point.y = Vec2.y + math.sin( angle ) * math.random(_inner, _outer);
|
Point.y = Vec2.y + math.sin( angle ) * math.random(_inner, _outer);
|
||||||
|
|
||||||
self:T( { Point } )
|
self:T( { Point } )
|
||||||
|
|
||||||
return Point
|
return Point
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Returns a @{Core.Point#POINT_VEC2} object reflecting a random 2D location within the zone.
|
--- Returns a @{Core.Point#POINT_VEC2} object reflecting a random 2D location within the zone.
|
||||||
|
|||||||
@@ -23,7 +23,6 @@
|
|||||||
-- @module Functional.FOX
|
-- @module Functional.FOX
|
||||||
-- @image Functional_FOX.png
|
-- @image Functional_FOX.png
|
||||||
|
|
||||||
|
|
||||||
--- FOX class.
|
--- FOX class.
|
||||||
-- @type FOX
|
-- @type FOX
|
||||||
-- @field #string ClassName Name of the class.
|
-- @field #string ClassName Name of the class.
|
||||||
@@ -47,8 +46,7 @@
|
|||||||
-- @field #number dt10 Time step [sec] for missile position updates if distance to target > 10 km and < 50 km. Default 1 sec.
|
-- @field #number dt10 Time step [sec] for missile position updates if distance to target > 10 km and < 50 km. Default 1 sec.
|
||||||
-- @field #number dt05 Time step [sec] for missile position updates if distance to target > 5 km and < 10 km. Default 0.5 sec.
|
-- @field #number dt05 Time step [sec] for missile position updates if distance to target > 5 km and < 10 km. Default 0.5 sec.
|
||||||
-- @field #number dt01 Time step [sec] for missile position updates if distance to target > 1 km and < 5 km. Default 0.1 sec.
|
-- @field #number dt01 Time step [sec] for missile position updates if distance to target > 1 km and < 5 km. Default 0.1 sec.
|
||||||
-- @field #number dt00 Time step [sec] for missile position updates if distance to target < 1 km. Default 0.01 sec.
|
-- @field #number dt00 Time step [sec] for missile position updates if distance to target < 1 km. Default 0.01 sec.
|
||||||
-- @field #boolean
|
|
||||||
-- @extends Core.Fsm#FSM
|
-- @extends Core.Fsm#FSM
|
||||||
|
|
||||||
--- Fox 3!
|
--- Fox 3!
|
||||||
@@ -1707,8 +1705,8 @@ end
|
|||||||
--- Returns the unit of a player and the player name. If the unit does not belong to a player, nil is returned.
|
--- Returns the unit of a player and the player name. If the unit does not belong to a player, nil is returned.
|
||||||
-- @param #FOX self
|
-- @param #FOX self
|
||||||
-- @param DCS#Weapon weapon The weapon.
|
-- @param DCS#Weapon weapon The weapon.
|
||||||
-- @return #number Notching heading right, i.e. missile heading +90<EFBFBD>
|
-- @return #number Notching heading right, i.e. missile heading +90°.
|
||||||
-- @return #number Notching heading left, i.e. missile heading -90<EFBFBD>.
|
-- @return #number Notching heading left, i.e. missile heading -90°.
|
||||||
function FOX:_GetNotchingHeadings(weapon)
|
function FOX:_GetNotchingHeadings(weapon)
|
||||||
|
|
||||||
if weapon then
|
if weapon then
|
||||||
@@ -1813,4 +1811,4 @@ end
|
|||||||
|
|
||||||
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -5,7 +5,7 @@
|
|||||||
-- ## Features:
|
-- ## Features:
|
||||||
--
|
--
|
||||||
-- * Track the missiles fired at you and other players, providing bearing and range information of the missiles towards the airplanes.
|
-- * Track the missiles fired at you and other players, providing bearing and range information of the missiles towards the airplanes.
|
||||||
-- * Provide alerts of missile launches, including detailed information of the units launching, including bearing, range <EFBFBD>
|
-- * Provide alerts of missile launches, including detailed information of the units launching, including bearing, range °
|
||||||
-- * Provide alerts when a missile would have killed your aircraft.
|
-- * Provide alerts when a missile would have killed your aircraft.
|
||||||
-- * Provide alerts when the missile self destructs.
|
-- * Provide alerts when the missile self destructs.
|
||||||
-- * Enable / Disable and Configure the Missile Trainer using the various menu options.
|
-- * Enable / Disable and Configure the Missile Trainer using the various menu options.
|
||||||
|
|||||||
@@ -742,7 +742,7 @@ function PSEUDOATC:ReportWeather(GID, UID, position, location)
|
|||||||
local T=position:GetTemperature()
|
local T=position:GetTemperature()
|
||||||
|
|
||||||
-- Correct unit system.
|
-- Correct unit system.
|
||||||
local _T=string.format('%d°F', UTILS.CelciusToFarenheit(T))
|
local _T=string.format('%d°F', UTILS.CelsiusToFahrenheit(T))
|
||||||
if settings:IsMetric() then
|
if settings:IsMetric() then
|
||||||
_T=string.format('%d°C', T)
|
_T=string.format('%d°C', T)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -5371,7 +5371,7 @@ function RAT:_ModifySpawnTemplate(waypoints, livery, spawnplace, departure, take
|
|||||||
|
|
||||||
if spawnonground then
|
if spawnonground then
|
||||||
|
|
||||||
-- Sh<EFBFBD>ps and FARPS seem to have a build in queue.
|
-- Sh°ps and FARPS seem to have a build in queue.
|
||||||
if spawnonship or spawnonfarp or spawnonrunway or automatic then
|
if spawnonship or spawnonfarp or spawnonrunway or automatic then
|
||||||
self:T(RAT.id..string.format("RAT group %s spawning at farp, ship or runway %s.", self.alias, departure:GetName()))
|
self:T(RAT.id..string.format("RAT group %s spawning at farp, ship or runway %s.", self.alias, departure:GetName()))
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,54 +1,64 @@
|
|||||||
--- **Functional** -- Make SAM sites execute evasive and defensive behaviour when being fired upon.
|
--- **Functional** -- Make SAM sites execute evasive and defensive behaviour when being fired upon.
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ## Features:
|
-- ## Features:
|
||||||
--
|
--
|
||||||
-- * When SAM sites are being fired upon, the SAMs will take evasive action will reposition themselves when possible.
|
-- * When SAM sites are being fired upon, the SAMs will take evasive action will reposition themselves when possible.
|
||||||
-- * When SAM sites are being fired upon, the SAMs will take defensive action by shutting down their radars.
|
-- * When SAM sites are being fired upon, the SAMs will take defensive action by shutting down their radars.
|
||||||
--
|
-- * SEAD calculates the time it takes for a HARM to reach the target - and will attempt to minimize the shut-down time.
|
||||||
|
-- * Detection and evasion of shots has a random component based on the skill level of the SAM groups.
|
||||||
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ## Missions:
|
-- ## Missions:
|
||||||
--
|
--
|
||||||
-- [SEV - SEAD Evasion](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/SEV%20-%20SEAD%20Evasion)
|
-- [SEV - SEAD Evasion](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/SEV%20-%20SEAD%20Evasion)
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ### Authors: **FlightControl**, **applevangelist**
|
-- ### Authors: **FlightControl**, **applevangelist**
|
||||||
--
|
--
|
||||||
-- Last Update: July 2021
|
-- Last Update: Nov 2021
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- @module Functional.Sead
|
-- @module Functional.Sead
|
||||||
-- @image SEAD.JPG
|
-- @image SEAD.JPG
|
||||||
|
|
||||||
--- @type SEAD
|
---
|
||||||
|
-- @type SEAD
|
||||||
-- @extends Core.Base#BASE
|
-- @extends Core.Base#BASE
|
||||||
|
|
||||||
--- Make SAM sites execute evasive and defensive behaviour when being fired upon.
|
--- Make SAM sites execute evasive and defensive behaviour when being fired upon.
|
||||||
--
|
--
|
||||||
-- This class is very easy to use. Just setup a SEAD object by using @{#SEAD.New}() and SAMs will evade and take defensive action when being fired upon.
|
-- This class is very easy to use. Just setup a SEAD object by using @{#SEAD.New}() and SAMs will evade and take defensive action when being fired upon.
|
||||||
|
-- Once a HARM attack is detected, SEAD will shut down the radars of the attacked SAM site and take evasive action by moving the SAM
|
||||||
|
-- vehicles around (*if* they are drivable, that is). There's a component of randomness in detection and evasion, which is based on the
|
||||||
|
-- skill set of the SAM set (the higher the skill, the more likely). When a missile is fired from far away, the SAM will stay active for a
|
||||||
|
-- period of time to stay defensive, before it takes evasive actions.
|
||||||
--
|
--
|
||||||
-- # Constructor:
|
-- # Constructor:
|
||||||
--
|
--
|
||||||
-- Use the @{#SEAD.New}() constructor to create a new SEAD object.
|
-- Use the @{#SEAD.New}() constructor to create a new SEAD object.
|
||||||
--
|
--
|
||||||
-- SEAD_RU_SAM_Defenses = SEAD:New( { 'RU SA-6 Kub', 'RU SA-6 Defenses', 'RU MI-26 Troops', 'RU Attack Gori' } )
|
-- SEAD_RU_SAM_Defenses = SEAD:New( { 'RU SA-6 Kub', 'RU SA-6 Defenses', 'RU MI-26 Troops', 'RU Attack Gori' } )
|
||||||
--
|
--
|
||||||
-- @field #SEAD
|
-- @field #SEAD
|
||||||
SEAD = {
|
SEAD = {
|
||||||
ClassName = "SEAD",
|
ClassName = "SEAD",
|
||||||
TargetSkill = {
|
TargetSkill = {
|
||||||
Average = { Evade = 30, DelayOn = { 40, 60 } } ,
|
Average = { Evade = 30, DelayOn = { 40, 60 } } ,
|
||||||
Good = { Evade = 20, DelayOn = { 30, 50 } } ,
|
Good = { Evade = 20, DelayOn = { 30, 50 } } ,
|
||||||
High = { Evade = 15, DelayOn = { 20, 40 } } ,
|
High = { Evade = 15, DelayOn = { 20, 40 } } ,
|
||||||
Excellent = { Evade = 10, DelayOn = { 10, 30 } }
|
Excellent = { Evade = 10, DelayOn = { 10, 30 } }
|
||||||
},
|
},
|
||||||
SEADGroupPrefixes = {},
|
SEADGroupPrefixes = {},
|
||||||
SuppressedGroups = {},
|
SuppressedGroups = {},
|
||||||
EngagementRange = 75 -- default 75% engagement range Feature Request #1355
|
EngagementRange = 75, -- default 75% engagement range Feature Request #1355
|
||||||
|
Padding = 10,
|
||||||
|
CallBack = nil,
|
||||||
|
UseCallBack = false,
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Missile enumerators
|
--- Missile enumerators
|
||||||
@@ -59,7 +69,7 @@ SEAD = {
|
|||||||
["AGM_122"] = "AGM_122",
|
["AGM_122"] = "AGM_122",
|
||||||
["AGM_84"] = "AGM_84",
|
["AGM_84"] = "AGM_84",
|
||||||
["AGM_45"] = "AGM_45",
|
["AGM_45"] = "AGM_45",
|
||||||
["ALARN"] = "ALARM",
|
["ALARM"] = "ALARM",
|
||||||
["LD-10"] = "LD-10",
|
["LD-10"] = "LD-10",
|
||||||
["X_58"] = "X_58",
|
["X_58"] = "X_58",
|
||||||
["X_28"] = "X_28",
|
["X_28"] = "X_28",
|
||||||
@@ -67,22 +77,40 @@ SEAD = {
|
|||||||
["X_31"] = "X_31",
|
["X_31"] = "X_31",
|
||||||
["Kh25"] = "Kh25",
|
["Kh25"] = "Kh25",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
--- Missile enumerators - from DCS ME and Wikipedia
|
||||||
|
-- @field HarmData
|
||||||
|
SEAD.HarmData = {
|
||||||
|
-- km and mach
|
||||||
|
["AGM_88"] = { 150, 3},
|
||||||
|
["AGM_45"] = { 12, 2},
|
||||||
|
["AGM_122"] = { 16.5, 2.3},
|
||||||
|
["AGM_84"] = { 280, 0.85},
|
||||||
|
["ALARM"] = { 45, 2},
|
||||||
|
["LD-10"] = { 60, 4},
|
||||||
|
["X_58"] = { 70, 4},
|
||||||
|
["X_28"] = { 80, 2.5},
|
||||||
|
["X_25"] = { 25, 0.76},
|
||||||
|
["X_31"] = {150, 3},
|
||||||
|
["Kh25"] = {25, 0.8},
|
||||||
|
}
|
||||||
|
|
||||||
--- Creates the main object which is handling defensive actions for SA sites or moving SA vehicles.
|
--- Creates the main object which is handling defensive actions for SA sites or moving SA vehicles.
|
||||||
-- When an anti radiation missile is fired (KH-58, KH-31P, KH-31A, KH-25MPU, HARM missiles), the SA will shut down their radars and will take evasive actions...
|
-- When an anti radiation missile is fired (KH-58, KH-31P, KH-31A, KH-25MPU, HARM missiles), the SA will shut down their radars and will take evasive actions...
|
||||||
-- Chances are big that the missile will miss.
|
-- Chances are big that the missile will miss.
|
||||||
-- @param #SEAD self
|
-- @param #SEAD self
|
||||||
-- @param table{string,...}|string SEADGroupPrefixes which is a table of Prefixes of the SA Groups in the DCS mission editor on which evasive actions need to be taken.
|
-- @param #table SEADGroupPrefixes Table of #string entries or single #string, which is a table of Prefixes of the SA Groups in the DCS mission editor on which evasive actions need to be taken.
|
||||||
-- @return SEAD
|
-- @param #number Padding (Optional) Extra number of seconds to add to radar switch-back-on time
|
||||||
|
-- @return #SEAD self
|
||||||
-- @usage
|
-- @usage
|
||||||
-- -- CCCP SEAD Defenses
|
-- -- CCCP SEAD Defenses
|
||||||
-- -- Defends the Russian SA installations from SEAD attacks.
|
-- -- Defends the Russian SA installations from SEAD attacks.
|
||||||
-- SEAD_RU_SAM_Defenses = SEAD:New( { 'RU SA-6 Kub', 'RU SA-6 Defenses', 'RU MI-26 Troops', 'RU Attack Gori' } )
|
-- SEAD_RU_SAM_Defenses = SEAD:New( { 'RU SA-6 Kub', 'RU SA-6 Defenses', 'RU MI-26 Troops', 'RU Attack Gori' } )
|
||||||
function SEAD:New( SEADGroupPrefixes )
|
function SEAD:New( SEADGroupPrefixes, Padding )
|
||||||
|
|
||||||
local self = BASE:Inherit( self, BASE:New() )
|
local self = BASE:Inherit( self, BASE:New() )
|
||||||
self:F( SEADGroupPrefixes )
|
self:F( SEADGroupPrefixes )
|
||||||
|
|
||||||
if type( SEADGroupPrefixes ) == 'table' then
|
if type( SEADGroupPrefixes ) == 'table' then
|
||||||
for SEADGroupPrefixID, SEADGroupPrefix in pairs( SEADGroupPrefixes ) do
|
for SEADGroupPrefixID, SEADGroupPrefix in pairs( SEADGroupPrefixes ) do
|
||||||
self.SEADGroupPrefixes[SEADGroupPrefix] = SEADGroupPrefix
|
self.SEADGroupPrefixes[SEADGroupPrefix] = SEADGroupPrefix
|
||||||
@@ -90,20 +118,29 @@ function SEAD:New( SEADGroupPrefixes )
|
|||||||
else
|
else
|
||||||
self.SEADGroupPrefixes[SEADGroupPrefixes] = SEADGroupPrefixes
|
self.SEADGroupPrefixes[SEADGroupPrefixes] = SEADGroupPrefixes
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local padding = Padding or 10
|
||||||
|
if padding < 10 then padding = 10 end
|
||||||
|
self.Padding = padding
|
||||||
|
self.UseEmissionsOnOff = false
|
||||||
|
|
||||||
|
self.CallBack = nil
|
||||||
|
self.UseCallBack = false
|
||||||
|
|
||||||
self:HandleEvent( EVENTS.Shot, self.HandleEventShot )
|
self:HandleEvent( EVENTS.Shot, self.HandleEventShot )
|
||||||
self:I("*** SEAD - Started Version 0.2.8")
|
|
||||||
|
self:I("*** SEAD - Started Version 0.3.3")
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Update the active SEAD Set
|
--- Update the active SEAD Set (while running)
|
||||||
-- @param #SEAD self
|
-- @param #SEAD self
|
||||||
-- @param #table SEADGroupPrefixes The prefixes to add, note: can also be a single #string
|
-- @param #table SEADGroupPrefixes The prefixes to add, note: can also be a single #string
|
||||||
-- @return #SEAD self
|
-- @return #SEAD self
|
||||||
function SEAD:UpdateSet( SEADGroupPrefixes )
|
function SEAD:UpdateSet( SEADGroupPrefixes )
|
||||||
|
|
||||||
self:F( SEADGroupPrefixes )
|
self:T( SEADGroupPrefixes )
|
||||||
|
|
||||||
if type( SEADGroupPrefixes ) == 'table' then
|
if type( SEADGroupPrefixes ) == 'table' then
|
||||||
for SEADGroupPrefixID, SEADGroupPrefix in pairs( SEADGroupPrefixes ) do
|
for SEADGroupPrefixID, SEADGroupPrefix in pairs( SEADGroupPrefixes ) do
|
||||||
self.SEADGroupPrefixes[SEADGroupPrefix] = SEADGroupPrefix
|
self.SEADGroupPrefixes[SEADGroupPrefix] = SEADGroupPrefix
|
||||||
@@ -117,10 +154,10 @@ end
|
|||||||
|
|
||||||
--- Sets the engagement range of the SAMs. Defaults to 75% to make it more deadly. Feature Request #1355
|
--- Sets the engagement range of the SAMs. Defaults to 75% to make it more deadly. Feature Request #1355
|
||||||
-- @param #SEAD self
|
-- @param #SEAD self
|
||||||
-- @param #number range Set the engagement range in percent, e.g. 50
|
-- @param #number range Set the engagement range in percent, e.g. 55 (default 75)
|
||||||
-- @return self
|
-- @return #SEAD self
|
||||||
function SEAD:SetEngagementRange(range)
|
function SEAD:SetEngagementRange(range)
|
||||||
self:F( { range } )
|
self:T( { range } )
|
||||||
range = range or 75
|
range = range or 75
|
||||||
if range < 0 or range > 100 then
|
if range < 0 or range > 100 then
|
||||||
range = 75
|
range = 75
|
||||||
@@ -130,100 +167,218 @@ function SEAD:SetEngagementRange(range)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Check if a known HARM was fired
|
--- Set the padding in seconds, which extends the radar off time calculated by SEAD
|
||||||
-- @param #SEAD self
|
-- @param #SEAD self
|
||||||
-- @param #string WeaponName
|
-- @param #number Padding Extra number of seconds to add for the switch-on (default 10 seconds)
|
||||||
-- @return #boolean Returns true for a match
|
-- @return #SEAD self
|
||||||
function SEAD:_CheckHarms(WeaponName)
|
function SEAD:SetPadding(Padding)
|
||||||
self:F( { WeaponName } )
|
self:T( { Padding } )
|
||||||
local hit = false
|
local padding = Padding or 10
|
||||||
for _,_name in pairs (SEAD.Harms) do
|
if padding < 10 then padding = 10 end
|
||||||
if string.find(WeaponName,_name,1) then hit = true end
|
self.Padding = padding
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set SEAD to use emissions on/off in addition to alarm state.
|
||||||
|
-- @param #SEAD self
|
||||||
|
-- @param #boolean Switch True for on, false for off.
|
||||||
|
-- @return #SEAD self
|
||||||
|
function SEAD:SwitchEmissions(Switch)
|
||||||
|
self:T({Switch})
|
||||||
|
self.UseEmissionsOnOff = Switch
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Add an object to call back when going evasive.
|
||||||
|
-- @param #SEAD self
|
||||||
|
-- @param #table Object The object to call. Needs to have object functions as follows:
|
||||||
|
-- `:SeadSuppressionPlanned(Group, Name, SuppressionStartTime, SuppressionEndTime)`
|
||||||
|
-- `:SeadSuppressionStart(Group, Name)`,
|
||||||
|
-- `:SeadSuppressionEnd(Group, Name)`,
|
||||||
|
-- @return #SEAD self
|
||||||
|
function SEAD:AddCallBack(Object)
|
||||||
|
self:T({Class=Object.ClassName})
|
||||||
|
self.CallBack = Object
|
||||||
|
self.UseCallBack = true
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- (Internal) Check if a known HARM was fired
|
||||||
|
-- @param #SEAD self
|
||||||
|
-- @param #string WeaponName
|
||||||
|
-- @return #boolean Returns true for a match
|
||||||
|
-- @return #string name Name of hit in table
|
||||||
|
function SEAD:_CheckHarms(WeaponName)
|
||||||
|
self:T( { WeaponName } )
|
||||||
|
local hit = false
|
||||||
|
local name = ""
|
||||||
|
for _,_name in pairs (SEAD.Harms) do
|
||||||
|
if string.find(WeaponName,_name,1) then
|
||||||
|
hit = true
|
||||||
|
name = _name
|
||||||
|
break
|
||||||
end
|
end
|
||||||
return hit
|
end
|
||||||
|
return hit, name
|
||||||
|
end
|
||||||
|
|
||||||
|
--- (Internal) Return distance in meters between two coordinates or -1 on error.
|
||||||
|
-- @param #SEAD self
|
||||||
|
-- @param Core.Point#COORDINATE _point1 Coordinate one
|
||||||
|
-- @param Core.Point#COORDINATE _point2 Coordinate two
|
||||||
|
-- @return #number Distance in meters
|
||||||
|
function SEAD:_GetDistance(_point1, _point2)
|
||||||
|
self:T("_GetDistance")
|
||||||
|
if _point1 and _point2 then
|
||||||
|
local distance1 = _point1:Get2DDistance(_point2)
|
||||||
|
local distance2 = _point1:DistanceFromPointVec2(_point2)
|
||||||
|
--self:T({dist1=distance1, dist2=distance2})
|
||||||
|
if distance1 and type(distance1) == "number" then
|
||||||
|
return distance1
|
||||||
|
elseif distance2 and type(distance2) == "number" then
|
||||||
|
return distance2
|
||||||
|
else
|
||||||
|
self:E("*****Cannot calculate distance!")
|
||||||
|
self:E({_point1,_point2})
|
||||||
|
return -1
|
||||||
|
end
|
||||||
|
else
|
||||||
|
self:E("******Cannot calculate distance!")
|
||||||
|
self:E({_point1,_point2})
|
||||||
|
return -1
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
--- Detects if an SAM site was shot with an anti radiation missile. In this case, take evasive actions based on the skill level set within the ME.
|
--- (Internal) Detects if an SAM site was shot with an anti radiation missile. In this case, take evasive actions based on the skill level set within the ME.
|
||||||
-- @see SEAD
|
-- @param #SEAD self
|
||||||
-- @param #SEAD
|
|
||||||
-- @param Core.Event#EVENTDATA EventData
|
-- @param Core.Event#EVENTDATA EventData
|
||||||
|
-- @return #SEAD self
|
||||||
function SEAD:HandleEventShot( EventData )
|
function SEAD:HandleEventShot( EventData )
|
||||||
self:T( { EventData } )
|
self:T( { EventData.id } )
|
||||||
|
local SEADPlane = EventData.IniUnit -- Wrapper.Unit#UNIT
|
||||||
|
local SEADPlanePos = SEADPlane:GetCoordinate() -- Core.Point#COORDINATE
|
||||||
local SEADUnit = EventData.IniDCSUnit
|
local SEADUnit = EventData.IniDCSUnit
|
||||||
local SEADUnitName = EventData.IniDCSUnitName
|
local SEADUnitName = EventData.IniDCSUnitName
|
||||||
local SEADWeapon = EventData.Weapon -- Identify the weapon fired
|
local SEADWeapon = EventData.Weapon -- Identify the weapon fired
|
||||||
local SEADWeaponName = EventData.WeaponName -- return weapon type
|
local SEADWeaponName = EventData.WeaponName -- return weapon type
|
||||||
|
|
||||||
self:T( "*** SEAD - Missile Launched = " .. SEADWeaponName)
|
self:T( "*** SEAD - Missile Launched = " .. SEADWeaponName)
|
||||||
self:T({ SEADWeapon })
|
--self:T({ SEADWeapon })
|
||||||
|
|
||||||
if self:_CheckHarms(SEADWeaponName) then
|
if self:_CheckHarms(SEADWeaponName) then
|
||||||
|
self:T( '*** SEAD - Weapon Match' )
|
||||||
local _targetskill = "Random"
|
local _targetskill = "Random"
|
||||||
local _targetMimgroupName = "none"
|
local _targetgroupname = "none"
|
||||||
local _evade = math.random (1,100) -- random number for chance of evading action
|
local _target = EventData.Weapon:getTarget() -- Identify target
|
||||||
local _targetMim = EventData.Weapon:getTarget() -- Identify target
|
local _targetUnit = UNIT:Find(_target) -- Wrapper.Unit#UNIT
|
||||||
local _targetUnit = UNIT:Find(_targetMim) -- Unit name by DCS Object
|
local _targetgroup = nil -- Wrapper.Group#GROUP
|
||||||
if _targetUnit and _targetUnit:IsAlive() then
|
if _targetUnit and _targetUnit:IsAlive() then
|
||||||
local _targetMimgroup = _targetUnit:GetGroup()
|
_targetgroup = _targetUnit:GetGroup()
|
||||||
local _targetMimgroupName = _targetMimgroup:GetName() -- group name
|
_targetgroupname = _targetgroup:GetName() -- group name
|
||||||
--local _targetskill = _DATABASE.Templates.Units[_targetUnit].Template.skill
|
local _targetUnitName = _targetUnit:GetName()
|
||||||
self:T( self.SEADGroupPrefixes )
|
_targetUnit:GetSkill()
|
||||||
self:T( _targetMimgroupName )
|
_targetskill = _targetUnit:GetSkill()
|
||||||
end
|
end
|
||||||
-- see if we are shot at
|
-- see if we are shot at
|
||||||
local SEADGroupFound = false
|
local SEADGroupFound = false
|
||||||
for SEADGroupPrefixID, SEADGroupPrefix in pairs( self.SEADGroupPrefixes ) do
|
for SEADGroupPrefixID, SEADGroupPrefix in pairs( self.SEADGroupPrefixes ) do
|
||||||
if string.find( _targetMimgroupName, SEADGroupPrefix, 1, true ) then
|
self:T( _targetgroupname, SEADGroupPrefix )
|
||||||
|
if string.find( _targetgroupname, SEADGroupPrefix, 1, true ) then
|
||||||
SEADGroupFound = true
|
SEADGroupFound = true
|
||||||
self:T( '*** SEAD - Group Found' )
|
self:T( '*** SEAD - Group Match Found' )
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if SEADGroupFound == true then -- yes we are being attacked
|
if SEADGroupFound == true then -- yes we are being attacked
|
||||||
if _targetskill == "Random" then -- when skill is random, choose a skill
|
if _targetskill == "Random" then -- when skill is random, choose a skill
|
||||||
local Skills = { "Average", "Good", "High", "Excellent" }
|
local Skills = { "Average", "Good", "High", "Excellent" }
|
||||||
_targetskill = Skills[ math.random(1,4) ]
|
_targetskill = Skills[ math.random(1,4) ]
|
||||||
end
|
end
|
||||||
self:T( _targetskill )
|
--self:T( _targetskill )
|
||||||
if self.TargetSkill[_targetskill] then
|
if self.TargetSkill[_targetskill] then
|
||||||
|
local _evade = math.random (1,100) -- random number for chance of evading action
|
||||||
if (_evade > self.TargetSkill[_targetskill].Evade) then
|
if (_evade > self.TargetSkill[_targetskill].Evade) then
|
||||||
|
self:T("*** SEAD - Evading")
|
||||||
self:T( string.format("*** SEAD - Evading, target skill " ..string.format(_targetskill)) )
|
-- calculate distance of attacker
|
||||||
|
local _targetpos = _targetgroup:GetCoordinate()
|
||||||
local _targetMimgroup = Unit.getGroup(Weapon.getTarget(SEADWeapon))
|
local _distance = self:_GetDistance(SEADPlanePos, _targetpos)
|
||||||
local _targetMimcont= _targetMimgroup:getController()
|
-- weapon speed
|
||||||
|
local hit, data = self:_CheckHarms(SEADWeaponName)
|
||||||
routines.groupRandomDistSelf(_targetMimgroup,300,'Diamond',250,20) -- move randomly
|
local wpnspeed = 666 -- ;)
|
||||||
|
local reach = 10
|
||||||
--tracker ID table to switch groups off and on again
|
if hit then
|
||||||
local id = {
|
local wpndata = SEAD.HarmData[data]
|
||||||
groupName = _targetMimgroup,
|
reach = wpndata[1] * 1,1
|
||||||
ctrl = _targetMimcont
|
local mach = wpndata[2]
|
||||||
}
|
wpnspeed = math.floor(mach * 340.29)
|
||||||
|
|
||||||
local function SuppressionEnd(id) --switch group back on
|
|
||||||
local range = self.EngagementRange -- Feature Request #1355
|
|
||||||
self:T(string.format("*** SEAD - Engagement Range is %d", range))
|
|
||||||
id.ctrl:setOption(AI.Option.Ground.id.ALARM_STATE,AI.Option.Ground.val.ALARM_STATE.RED)
|
|
||||||
--id.groupName:enableEmission(true)
|
|
||||||
id.ctrl:setOption(AI.Option.Ground.id.AC_ENGAGEMENT_RANGE_RESTRICTION,range) --Feature Request #1355
|
|
||||||
self.SuppressedGroups[id.groupName] = nil --delete group id from table when done
|
|
||||||
end
|
end
|
||||||
-- randomize switch-on time
|
-- time to impact
|
||||||
local delay = math.random(self.TargetSkill[_targetskill].DelayOn[1], self.TargetSkill[_targetskill].DelayOn[2])
|
local _tti = math.floor(_distance / wpnspeed) -- estimated impact time
|
||||||
local SuppressionEndTime = timer.getTime() + delay
|
if _distance > 0 then
|
||||||
--create entry
|
_distance = math.floor(_distance / 1000) -- km
|
||||||
if self.SuppressedGroups[id.groupName] == nil then --no timer entry for this group yet
|
else
|
||||||
self.SuppressedGroups[id.groupName] = {
|
_distance = 0
|
||||||
SuppressionEndTime = delay
|
end
|
||||||
}
|
|
||||||
Controller.setOption(_targetMimcont, AI.Option.Ground.id.ALARM_STATE,AI.Option.Ground.val.ALARM_STATE.GREEN)
|
self:T( string.format("*** SEAD - target skill %s, distance %dkm, reach %dkm, tti %dsec", _targetskill, _distance,reach,_tti ))
|
||||||
--_targetMimgroup:enableEmission(false)
|
|
||||||
timer.scheduleFunction(SuppressionEnd, id, SuppressionEndTime) --Schedule the SuppressionEnd() function
|
if reach >= _distance then
|
||||||
|
self:T("*** SEAD - Shot in Reach")
|
||||||
|
|
||||||
|
local function SuppressionStart(args)
|
||||||
|
self:T(string.format("*** SEAD - %s Radar Off & Relocating",args[2]))
|
||||||
|
local grp = args[1] -- Wrapper.Group#GROUP
|
||||||
|
local name = args[2] -- #string Group Name
|
||||||
|
if self.UseEmissionsOnOff then
|
||||||
|
grp:EnableEmission(false)
|
||||||
|
end
|
||||||
|
grp:OptionAlarmStateGreen() -- needed else we cannot move around
|
||||||
|
grp:RelocateGroundRandomInRadius(20,300,false,false,"Diamond")
|
||||||
|
if self.UseCallBack then
|
||||||
|
local object = self.CallBack
|
||||||
|
object:SeadSuppressionStart(grp,name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function SuppressionStop(args)
|
||||||
|
self:T(string.format("*** SEAD - %s Radar On",args[2]))
|
||||||
|
local grp = args[1] -- Wrapper.Group#GROUP
|
||||||
|
local name = args[2] -- #string Group Nam
|
||||||
|
if self.UseEmissionsOnOff then
|
||||||
|
grp:EnableEmission(true)
|
||||||
|
end
|
||||||
|
grp:OptionAlarmStateAuto()
|
||||||
|
grp:OptionEngageRange(self.EngagementRange)
|
||||||
|
self.SuppressedGroups[name] = false
|
||||||
|
if self.UseCallBack then
|
||||||
|
local object = self.CallBack
|
||||||
|
object:SeadSuppressionEnd(grp,name)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- randomize switch-on time
|
||||||
|
local delay = math.random(self.TargetSkill[_targetskill].DelayOn[1], self.TargetSkill[_targetskill].DelayOn[2])
|
||||||
|
if delay > _tti then delay = delay / 2 end -- speed up
|
||||||
|
if _tti > (3*delay) then delay = (_tti / 2) * 0.9 end -- shot from afar
|
||||||
|
|
||||||
|
local SuppressionStartTime = timer.getTime() + delay
|
||||||
|
local SuppressionEndTime = timer.getTime() + _tti + self.Padding
|
||||||
|
|
||||||
|
if not self.SuppressedGroups[_targetgroupname] then
|
||||||
|
self:T(string.format("*** SEAD - %s | Parameters TTI %ds | Switch-Off in %ds",_targetgroupname,_tti,delay))
|
||||||
|
timer.scheduleFunction(SuppressionStart,{_targetgroup,_targetgroupname},SuppressionStartTime)
|
||||||
|
timer.scheduleFunction(SuppressionStop,{_targetgroup,_targetgroupname},SuppressionEndTime)
|
||||||
|
self.SuppressedGroups[_targetgroupname] = true
|
||||||
|
if self.UseCallBack then
|
||||||
|
local object = self.CallBack
|
||||||
|
object:SeadSuppressionPlanned(_targetgroup,_targetgroupname,SuppressionStartTime,SuppressionEndTime)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
return self
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ do
|
|||||||
["AGM_122"] = "AGM_122",
|
["AGM_122"] = "AGM_122",
|
||||||
["AGM_84"] = "AGM_84",
|
["AGM_84"] = "AGM_84",
|
||||||
["AGM_45"] = "AGM_45",
|
["AGM_45"] = "AGM_45",
|
||||||
["ALARN"] = "ALARM",
|
["ALARM"] = "ALARM",
|
||||||
["LD-10"] = "LD-10",
|
["LD-10"] = "LD-10",
|
||||||
["X_58"] = "X_58",
|
["X_58"] = "X_58",
|
||||||
["X_28"] = "X_28",
|
["X_28"] = "X_28",
|
||||||
|
|||||||
@@ -1601,7 +1601,7 @@ WAREHOUSE = {
|
|||||||
-- @field #number range Range of the unit in meters.
|
-- @field #number range Range of the unit in meters.
|
||||||
-- @field #number speedmax Maximum speed in km/h the group can do.
|
-- @field #number speedmax Maximum speed in km/h the group can do.
|
||||||
-- @field #number size Maximum size in length and with of the asset in meters.
|
-- @field #number size Maximum size in length and with of the asset in meters.
|
||||||
-- @field #number weight The weight of the whole asset group in kilo gramms.
|
-- @field #number weight The weight of the whole asset group in kilograms.
|
||||||
-- @field DCS#Object.Desc DCSdesc All DCS descriptors.
|
-- @field DCS#Object.Desc DCSdesc All DCS descriptors.
|
||||||
-- @field #WAREHOUSE.Attribute attribute Generalized attribute of the group.
|
-- @field #WAREHOUSE.Attribute attribute Generalized attribute of the group.
|
||||||
-- @field #table cargobay Array of cargo bays of all units in an asset group.
|
-- @field #table cargobay Array of cargo bays of all units in an asset group.
|
||||||
|
|||||||
@@ -715,20 +715,21 @@ do -- ZONE_CAPTURE_COALITION
|
|||||||
|
|
||||||
local UnitHit = EventData.TgtUnit
|
local UnitHit = EventData.TgtUnit
|
||||||
|
|
||||||
|
if UnitHit.ClassName ~= "SCENERY" then
|
||||||
-- Check if unit is inside the capture zone and that it is of the defending coalition.
|
-- Check if unit is inside the capture zone and that it is of the defending coalition.
|
||||||
if UnitHit and UnitHit:IsInZone(self) and UnitHit:GetCoalition()==self.Coalition then
|
if UnitHit and UnitHit:IsInZone(self) and UnitHit:GetCoalition()==self.Coalition then
|
||||||
|
|
||||||
-- Update last hit time.
|
-- Update last hit time.
|
||||||
self.HitTimeLast=timer.getTime()
|
self.HitTimeLast=timer.getTime()
|
||||||
|
|
||||||
-- Only trigger attacked event if not already in state "Attacked".
|
-- Only trigger attacked event if not already in state "Attacked".
|
||||||
if self:GetState()~="Attacked" then
|
if self:GetState()~="Attacked" then
|
||||||
self:F2("Hit ==> Attack")
|
self:F2("Hit ==> Attack")
|
||||||
self:Attack()
|
self:Attack()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
@@ -890,12 +891,14 @@ do -- ZONE_CAPTURE_COALITION
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Status text.
|
-- Status text.
|
||||||
local text=string.format("CAPTURE ZONE %s: Owner=%s (Previous=%s): #blue=%d, #red=%d, Status %s", self:GetZoneName(), self:GetCoalitionName(), UTILS.GetCoalitionName(self:GetPreviousCoalition()), nBlue, nRed, State)
|
if false then
|
||||||
local NewState = self:GetState()
|
local text=string.format("CAPTURE ZONE %s: Owner=%s (Previous=%s): #blue=%d, #red=%d, Status %s", self:GetZoneName(), self:GetCoalitionName(), UTILS.GetCoalitionName(self:GetPreviousCoalition()), nBlue, nRed, State)
|
||||||
if NewState~=State then
|
local NewState = self:GetState()
|
||||||
text=text..string.format(" --> %s", NewState)
|
if NewState~=State then
|
||||||
|
text=text..string.format(" --> %s", NewState)
|
||||||
|
end
|
||||||
|
self:I(text)
|
||||||
end
|
end
|
||||||
self:I(text)
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ _DATABASE:_RegisterCargos()
|
|||||||
|
|
||||||
--- Register zones.
|
--- Register zones.
|
||||||
_DATABASE:_RegisterZones()
|
_DATABASE:_RegisterZones()
|
||||||
|
_DATABASE:_RegisterAirbases()
|
||||||
|
|
||||||
--- Check if os etc is available.
|
--- Check if os etc is available.
|
||||||
BASE:I("Checking de-sanitization of os, io and lfs:")
|
BASE:I("Checking de-sanitization of os, io and lfs:")
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -802,7 +802,7 @@ function RESCUEHELO:_OnEventCrashOrEject(EventData)
|
|||||||
-- Debug.
|
-- Debug.
|
||||||
local text=string.format("Unit %s crashed or ejected.", unitname)
|
local text=string.format("Unit %s crashed or ejected.", unitname)
|
||||||
MESSAGE:New(text, 10, "DEBUG"):ToAllIf(self.Debug)
|
MESSAGE:New(text, 10, "DEBUG"):ToAllIf(self.Debug)
|
||||||
self:I(self.lid..text)
|
self:T(self.lid..text)
|
||||||
|
|
||||||
-- Get coordinate of unit.
|
-- Get coordinate of unit.
|
||||||
local coord=unit:GetCoordinate()
|
local coord=unit:GetCoordinate()
|
||||||
|
|||||||
@@ -157,7 +157,7 @@ end
|
|||||||
--- Set the frequency for the radio transmission.
|
--- Set the frequency for the radio transmission.
|
||||||
-- If the transmitting positionable is a unit or group, this also set the command "SetFrequency" with the defined frequency and modulation.
|
-- If the transmitting positionable is a unit or group, this also set the command "SetFrequency" with the defined frequency and modulation.
|
||||||
-- @param #RADIO self
|
-- @param #RADIO self
|
||||||
-- @param #number Frequency Frequency in MHz. Ranges allowed for radio transmissions in DCS : 30-87.995 / 108-173.995 / 225-399.975MHz.
|
-- @param #number Frequency Frequency in MHz.
|
||||||
-- @return #RADIO self
|
-- @return #RADIO self
|
||||||
function RADIO:SetFrequency(Frequency)
|
function RADIO:SetFrequency(Frequency)
|
||||||
self:F2(Frequency)
|
self:F2(Frequency)
|
||||||
@@ -165,7 +165,7 @@ function RADIO:SetFrequency(Frequency)
|
|||||||
if type(Frequency) == "number" then
|
if type(Frequency) == "number" then
|
||||||
|
|
||||||
-- If frequency is in range
|
-- If frequency is in range
|
||||||
if (Frequency >= 30 and Frequency <= 87.995) or (Frequency >= 108 and Frequency <= 173.995) or (Frequency >= 225 and Frequency <= 399.975) then
|
-- if (Frequency >= 30 and Frequency <= 87.995) or (Frequency >= 108 and Frequency <= 173.995) or (Frequency >= 225 and Frequency <= 399.975) then
|
||||||
|
|
||||||
-- Convert frequency from MHz to Hz
|
-- Convert frequency from MHz to Hz
|
||||||
self.Frequency = Frequency * 1000000
|
self.Frequency = Frequency * 1000000
|
||||||
@@ -186,10 +186,10 @@ function RADIO:SetFrequency(Frequency)
|
|||||||
end
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
-- end
|
||||||
end
|
end
|
||||||
|
|
||||||
self:E({"Frequency is outside of DCS Frequency ranges (30-80, 108-152, 225-400). Frequency unchanged.", Frequency})
|
self:E({"Frequency is not a number. Frequency unchanged.", Frequency})
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -162,33 +162,32 @@ RADIOSPEECH.Vocabulary.RU = {
|
|||||||
["8000"] = { "8000", 0.92 },
|
["8000"] = { "8000", 0.92 },
|
||||||
["9000"] = { "9000", 0.87 },
|
["9000"] = { "9000", 0.87 },
|
||||||
|
|
||||||
["Ñ<EFBFBD>тепени"] = { "degrees", 0.5 },
|
["градусы"] = { "degrees", 0.5 },
|
||||||
["километров"] = { "kilometers", 0.65 },
|
["километры"] = { "kilometers", 0.65 },
|
||||||
["km"] = { "kilometers", 0.65 },
|
["km"] = { "kilometers", 0.65 },
|
||||||
["миль"] = { "miles", 0.45 },
|
["мили"] = { "miles", 0.45 },
|
||||||
["mi"] = { "miles", 0.45 },
|
["mi"] = { "miles", 0.45 },
|
||||||
["метры"] = { "meters", 0.41 },
|
["метров"] = { "meters", 0.41 },
|
||||||
["m"] = { "meters", 0.41 },
|
["m"] = { "meters", 0.41 },
|
||||||
["ноги"] = { "feet", 0.37 },
|
["ноги"] = { "feet", 0.37 },
|
||||||
|
|
||||||
["br"] = { "br", 1.1 },
|
["br"] = { "br", 1.1 },
|
||||||
["bra"] = { "bra", 0.3 },
|
["bra"] = { "bra", 0.3 },
|
||||||
|
|
||||||
|
["возвращение на базу"] = { "returning_to_base", 1.40 },
|
||||||
|
["на пути к наземной цели"] = { "on_route_to_ground_target", 1.45 },
|
||||||
|
["перехват боги"] = { "intercepting_bogeys", 1.22 },
|
||||||
|
["поражение наземной цели"] = { "engaging_ground_target", 1.53 },
|
||||||
|
["привлечение болотных птиц"] = { "engaging_bogeys", 1.68 },
|
||||||
|
["колёса вверх..."] = { "wheels_up", 0.92 },
|
||||||
|
["посадка на базу"] = { "landing at base", 1.04 },
|
||||||
|
["патрулирование"] = { "patrolling", 0.96 },
|
||||||
|
|
||||||
["возвращаÑ<EFBFBD>Ñ<EFBFBD>ÑŒ на базу"] = { "returning_to_base", 1.40 },
|
["для"] = { "for", 0.27 },
|
||||||
["на пути к наземной цели"] = { "on_route_to_ground_target", 1.45 },
|
["и"] = { "and", 0.17 },
|
||||||
["перехват Ñ<>амолетов"] = { "intercepting_bogeys", 1.22 },
|
["на сайте"] = { "at", 0.19 },
|
||||||
["поражение наземной цели"] = { "engaging_ground_target", 1.53 },
|
["точка"] = { "dot", 0.51 },
|
||||||
["захватывающие Ñ<>амолеты"] = { "engaging_bogeys", 1.68 },
|
["защитник"] = { "defender", 0.45 },
|
||||||
["колеÑ<EFBFBD>а вверх"] = { "wheels_up", 0.92 },
|
|
||||||
["поÑ<EFBFBD>адка на базу"] = { "landing at base", 1.04 },
|
|
||||||
["патрулирующий"] = { "patrolling", 0.96 },
|
|
||||||
|
|
||||||
["за"] = { "for", 0.27 },
|
|
||||||
["и"] = { "and", 0.17 },
|
|
||||||
["в"] = { "at", 0.19 },
|
|
||||||
["dot"] = { "dot", 0.51 },
|
|
||||||
["defender"] = { "defender", 0.45 },
|
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Create a new RADIOSPEECH object for a given radio frequency/modulation.
|
--- Create a new RADIOSPEECH object for a given radio frequency/modulation.
|
||||||
|
|||||||
@@ -88,10 +88,19 @@
|
|||||||
--
|
--
|
||||||
-- Use a specific "culture" with the @{#MSRS.SetCulture} function, e.g. `:SetCulture("en-US")` or `:SetCulture("de-DE")`.
|
-- Use a specific "culture" with the @{#MSRS.SetCulture} function, e.g. `:SetCulture("en-US")` or `:SetCulture("de-DE")`.
|
||||||
--
|
--
|
||||||
|
-- ## Set Google
|
||||||
|
--
|
||||||
|
-- Use Google's text-to-speech engine with the @{#MSRS.SetGoogle} function, e.g. ':SetGoogle()'.
|
||||||
|
-- By enabling this it also allows you to utilize SSML in your text for added flexibilty.
|
||||||
|
-- For more information on setting up a cloud account, visit: https://cloud.google.com/text-to-speech
|
||||||
|
-- Google's supported SSML reference: https://cloud.google.com/text-to-speech/docs/ssml
|
||||||
|
--
|
||||||
-- ## Set Voice
|
-- ## Set Voice
|
||||||
--
|
--
|
||||||
-- Use a specifc voice with the @{#MSRS.SetVoice} function, e.g, `:SetVoice("Microsoft Hedda Desktop")`.
|
-- Use a specifc voice with the @{#MSRS.SetVoice} function, e.g, `:SetVoice("Microsoft Hedda Desktop")`.
|
||||||
-- Note that this must be installed on your windows system.
|
-- Note that this must be installed on your windows system.
|
||||||
|
-- If enabling SetGoogle(), you can use voices provided by Google
|
||||||
|
-- Google's supported voices: https://cloud.google.com/text-to-speech/docs/voices
|
||||||
--
|
--
|
||||||
-- ## Set Coordinate
|
-- ## Set Coordinate
|
||||||
--
|
--
|
||||||
@@ -678,7 +687,7 @@ function MSRS:_GetCommand(freqs, modus, coal, gender, voice, culture, volume, sp
|
|||||||
|
|
||||||
-- Set google.
|
-- Set google.
|
||||||
if self.google then
|
if self.google then
|
||||||
command=command..string.format(' -G "%s"', self.google)
|
command=command..string.format(' --ssml -G "%s"', self.google)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Debug output.
|
-- Debug output.
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
--- **Tasking** - The TASK_A2A models tasks for players in Air to Air engagements.
|
--- **Tasking** - The TASK_A2A models tasks for players in Air to Air engagements.
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ### Author: **FlightControl**
|
-- ### Author: **FlightControl**
|
||||||
--
|
--
|
||||||
-- ### Contributions:
|
-- ### Contributions:
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- @module Tasking.Task_A2A
|
-- @module Tasking.Task_A2A
|
||||||
-- @image MOOSE.JPG
|
-- @image MOOSE.JPG
|
||||||
|
|
||||||
@@ -35,12 +35,12 @@ do -- TASK_A2A
|
|||||||
-- * @{#TASK_A2A.SetScoreOnDestroy}(): Set a score when a target in scope of the A2A attack, has been destroyed.
|
-- * @{#TASK_A2A.SetScoreOnDestroy}(): Set a score when a target in scope of the A2A attack, has been destroyed.
|
||||||
-- * @{#TASK_A2A.SetScoreOnSuccess}(): Set a score when all the targets in scope of the A2A attack, have been destroyed.
|
-- * @{#TASK_A2A.SetScoreOnSuccess}(): Set a score when all the targets in scope of the A2A attack, have been destroyed.
|
||||||
-- * @{#TASK_A2A.SetPenaltyOnFailed}(): Set a penalty when the A2A attack has failed.
|
-- * @{#TASK_A2A.SetPenaltyOnFailed}(): Set a penalty when the A2A attack has failed.
|
||||||
--
|
--
|
||||||
-- @field #TASK_A2A
|
-- @field #TASK_A2A
|
||||||
TASK_A2A = {
|
TASK_A2A = {
|
||||||
ClassName = "TASK_A2A",
|
ClassName = "TASK_A2A"
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Instantiates a new TASK_A2A.
|
--- Instantiates a new TASK_A2A.
|
||||||
-- @param #TASK_A2A self
|
-- @param #TASK_A2A self
|
||||||
-- @param Tasking.Mission#MISSION Mission
|
-- @param Tasking.Mission#MISSION Mission
|
||||||
@@ -54,51 +54,49 @@ do -- TASK_A2A
|
|||||||
function TASK_A2A:New( Mission, SetAttack, TaskName, TargetSetUnit, TaskType, TaskBriefing )
|
function TASK_A2A:New( Mission, SetAttack, TaskName, TargetSetUnit, TaskType, TaskBriefing )
|
||||||
local self = BASE:Inherit( self, TASK:New( Mission, SetAttack, TaskName, TaskType, TaskBriefing ) ) -- Tasking.Task#TASK_A2A
|
local self = BASE:Inherit( self, TASK:New( Mission, SetAttack, TaskName, TaskType, TaskBriefing ) ) -- Tasking.Task#TASK_A2A
|
||||||
self:F()
|
self:F()
|
||||||
|
|
||||||
self.TargetSetUnit = TargetSetUnit
|
self.TargetSetUnit = TargetSetUnit
|
||||||
self.TaskType = TaskType
|
self.TaskType = TaskType
|
||||||
|
|
||||||
local Fsm = self:GetUnitProcess()
|
local Fsm = self:GetUnitProcess()
|
||||||
|
|
||||||
|
|
||||||
Fsm:AddTransition( "Assigned", "RouteToRendezVous", "RoutingToRendezVous" )
|
Fsm:AddTransition( "Assigned", "RouteToRendezVous", "RoutingToRendezVous" )
|
||||||
Fsm:AddProcess ( "RoutingToRendezVous", "RouteToRendezVousPoint", ACT_ROUTE_POINT:New(), { Arrived = "ArriveAtRendezVous" } )
|
Fsm:AddProcess( "RoutingToRendezVous", "RouteToRendezVousPoint", ACT_ROUTE_POINT:New(), { Arrived = "ArriveAtRendezVous" } )
|
||||||
Fsm:AddProcess ( "RoutingToRendezVous", "RouteToRendezVousZone", ACT_ROUTE_ZONE:New(), { Arrived = "ArriveAtRendezVous" } )
|
Fsm:AddProcess( "RoutingToRendezVous", "RouteToRendezVousZone", ACT_ROUTE_ZONE:New(), { Arrived = "ArriveAtRendezVous" } )
|
||||||
|
|
||||||
Fsm:AddTransition( { "Arrived", "RoutingToRendezVous" }, "ArriveAtRendezVous", "ArrivedAtRendezVous" )
|
Fsm:AddTransition( { "Arrived", "RoutingToRendezVous" }, "ArriveAtRendezVous", "ArrivedAtRendezVous" )
|
||||||
|
|
||||||
Fsm:AddTransition( { "ArrivedAtRendezVous", "HoldingAtRendezVous" }, "Engage", "Engaging" )
|
Fsm:AddTransition( { "ArrivedAtRendezVous", "HoldingAtRendezVous" }, "Engage", "Engaging" )
|
||||||
Fsm:AddTransition( { "ArrivedAtRendezVous", "HoldingAtRendezVous" }, "HoldAtRendezVous", "HoldingAtRendezVous" )
|
Fsm:AddTransition( { "ArrivedAtRendezVous", "HoldingAtRendezVous" }, "HoldAtRendezVous", "HoldingAtRendezVous" )
|
||||||
|
|
||||||
Fsm:AddProcess ( "Engaging", "Account", ACT_ACCOUNT_DEADS:New(), {} )
|
Fsm:AddProcess( "Engaging", "Account", ACT_ACCOUNT_DEADS:New(), {} )
|
||||||
Fsm:AddTransition( "Engaging", "RouteToTarget", "Engaging" )
|
Fsm:AddTransition( "Engaging", "RouteToTarget", "Engaging" )
|
||||||
Fsm:AddProcess( "Engaging", "RouteToTargetZone", ACT_ROUTE_ZONE:New(), {} )
|
Fsm:AddProcess( "Engaging", "RouteToTargetZone", ACT_ROUTE_ZONE:New(), {} )
|
||||||
Fsm:AddProcess( "Engaging", "RouteToTargetPoint", ACT_ROUTE_POINT:New(), {} )
|
Fsm:AddProcess( "Engaging", "RouteToTargetPoint", ACT_ROUTE_POINT:New(), {} )
|
||||||
Fsm:AddTransition( "Engaging", "RouteToTargets", "Engaging" )
|
Fsm:AddTransition( "Engaging", "RouteToTargets", "Engaging" )
|
||||||
|
|
||||||
-- Fsm:AddTransition( "Accounted", "DestroyedAll", "Accounted" )
|
-- Fsm:AddTransition( "Accounted", "DestroyedAll", "Accounted" )
|
||||||
-- Fsm:AddTransition( "Accounted", "Success", "Success" )
|
-- Fsm:AddTransition( "Accounted", "Success", "Success" )
|
||||||
Fsm:AddTransition( "Rejected", "Reject", "Aborted" )
|
Fsm:AddTransition( "Rejected", "Reject", "Aborted" )
|
||||||
Fsm:AddTransition( "Failed", "Fail", "Failed" )
|
Fsm:AddTransition( "Failed", "Fail", "Failed" )
|
||||||
|
|
||||||
|
|
||||||
---- @param #FSM_PROCESS self
|
-- @param #FSM_PROCESS self
|
||||||
-- @param Wrapper.Unit#UNIT TaskUnit
|
-- @param Wrapper.Unit#UNIT TaskUnit
|
||||||
-- @param #TASK_CARGO Task
|
-- @param #TASK_CARGO Task
|
||||||
function Fsm:OnLeaveAssigned( TaskUnit, Task )
|
function Fsm:OnLeaveAssigned( TaskUnit, Task )
|
||||||
self:F( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
|
self:F( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
|
||||||
|
|
||||||
self:SelectAction()
|
self:SelectAction()
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Test
|
--- Test
|
||||||
-- @param #FSM_PROCESS self
|
-- @param #FSM_PROCESS self
|
||||||
-- @param Wrapper.Unit#UNIT TaskUnit
|
-- @param Wrapper.Unit#UNIT TaskUnit
|
||||||
-- @param Tasking.Task_A2A#TASK_A2A Task
|
-- @param Tasking.Task_A2A#TASK_A2A Task
|
||||||
function Fsm:onafterRouteToRendezVous( TaskUnit, Task )
|
function Fsm:onafterRouteToRendezVous( TaskUnit, Task )
|
||||||
self:F( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
|
self:F( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
|
||||||
-- Determine the first Unit from the self.RendezVousSetUnit
|
-- Determine the first Unit from the self.RendezVousSetUnit
|
||||||
|
|
||||||
if Task:GetRendezVousZone( TaskUnit ) then
|
if Task:GetRendezVousZone( TaskUnit ) then
|
||||||
self:__RouteToRendezVousZone( 0.1 )
|
self:__RouteToRendezVousZone( 0.1 )
|
||||||
else
|
else
|
||||||
@@ -110,36 +108,36 @@ do -- TASK_A2A
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Test
|
--- Test
|
||||||
-- @param #FSM_PROCESS self
|
-- @param #FSM_PROCESS self
|
||||||
-- @param Wrapper.Unit#UNIT TaskUnit
|
-- @param Wrapper.Unit#UNIT TaskUnit
|
||||||
-- @param Tasking.Task#TASK_A2A Task
|
-- @param Tasking.Task#TASK_A2A Task
|
||||||
function Fsm:OnAfterArriveAtRendezVous( TaskUnit, Task )
|
function Fsm:OnAfterArriveAtRendezVous( TaskUnit, Task )
|
||||||
self:F( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
|
self:F( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
|
||||||
-- Determine the first Unit from the self.TargetSetUnit
|
-- Determine the first Unit from the self.TargetSetUnit
|
||||||
|
|
||||||
self:__Engage( 0.1 )
|
self:__Engage( 0.1 )
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Test
|
--- Test
|
||||||
-- @param #FSM_PROCESS self
|
-- @param #FSM_PROCESS self
|
||||||
-- @param Wrapper.Unit#UNIT TaskUnit
|
-- @param Wrapper.Unit#UNIT TaskUnit
|
||||||
-- @param Tasking.Task#TASK_A2A Task
|
-- @param Tasking.Task#TASK_A2A Task
|
||||||
function Fsm:onafterEngage( TaskUnit, Task )
|
function Fsm:onafterEngage( TaskUnit, Task )
|
||||||
self:F( { self } )
|
self:F( { self } )
|
||||||
self:__Account( 0.1 )
|
self:__Account( 0.1 )
|
||||||
self:__RouteToTarget(0.1 )
|
self:__RouteToTarget( 0.1 )
|
||||||
self:__RouteToTargets( -10 )
|
self:__RouteToTargets( -10 )
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Test
|
--- Test
|
||||||
-- @param #FSM_PROCESS self
|
-- @param #FSM_PROCESS self
|
||||||
-- @param Wrapper.Unit#UNIT TaskUnit
|
-- @param Wrapper.Unit#UNIT TaskUnit
|
||||||
-- @param Tasking.Task_A2A#TASK_A2A Task
|
-- @param Tasking.Task_A2A#TASK_A2A Task
|
||||||
function Fsm:onafterRouteToTarget( TaskUnit, Task )
|
function Fsm:onafterRouteToTarget( TaskUnit, Task )
|
||||||
self:F( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
|
self:F( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
|
||||||
-- Determine the first Unit from the self.TargetSetUnit
|
-- Determine the first Unit from the self.TargetSetUnit
|
||||||
|
|
||||||
if Task:GetTargetZone( TaskUnit ) then
|
if Task:GetTargetZone( TaskUnit ) then
|
||||||
self:__RouteToTargetZone( 0.1 )
|
self:__RouteToTargetZone( 0.1 )
|
||||||
else
|
else
|
||||||
@@ -152,8 +150,8 @@ do -- TASK_A2A
|
|||||||
self:__RouteToTargetPoint( 0.1 )
|
self:__RouteToTargetPoint( 0.1 )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Test
|
--- Test
|
||||||
-- @param #FSM_PROCESS self
|
-- @param #FSM_PROCESS self
|
||||||
-- @param Wrapper.Unit#UNIT TaskUnit
|
-- @param Wrapper.Unit#UNIT TaskUnit
|
||||||
-- @param Tasking.Task_A2A#TASK_A2A Task
|
-- @param Tasking.Task_A2A#TASK_A2A Task
|
||||||
@@ -165,20 +163,18 @@ do -- TASK_A2A
|
|||||||
end
|
end
|
||||||
self:__RouteToTargets( -10 )
|
self:__RouteToTargets( -10 )
|
||||||
end
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #TASK_A2A self
|
--- @param #TASK_A2A self
|
||||||
-- @param Core.Set#SET_UNIT TargetSetUnit The set of targets.
|
-- @param Core.Set#SET_UNIT TargetSetUnit The set of targets.
|
||||||
function TASK_A2A:SetTargetSetUnit( TargetSetUnit )
|
function TASK_A2A:SetTargetSetUnit( TargetSetUnit )
|
||||||
|
|
||||||
self.TargetSetUnit = TargetSetUnit
|
self.TargetSetUnit = TargetSetUnit
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--- @param #TASK_A2A self
|
--- @param #TASK_A2A self
|
||||||
function TASK_A2A:GetPlannedMenuText()
|
function TASK_A2A:GetPlannedMenuText()
|
||||||
return self:GetStateString() .. " - " .. self:GetTaskName() .. " ( " .. self.TargetSetUnit:GetUnitTypesText() .. " )"
|
return self:GetStateString() .. " - " .. self:GetTaskName() .. " ( " .. self.TargetSetUnit:GetUnitTypesText() .. " )"
|
||||||
@@ -188,34 +184,32 @@ do -- TASK_A2A
|
|||||||
-- @param Core.Point#COORDINATE RendezVousCoordinate The Coordinate object referencing to the 2D point where the RendezVous point is located on the map.
|
-- @param Core.Point#COORDINATE RendezVousCoordinate The Coordinate object referencing to the 2D point where the RendezVous point is located on the map.
|
||||||
-- @param #number RendezVousRange The RendezVousRange that defines when the player is considered to have arrived at the RendezVous point.
|
-- @param #number RendezVousRange The RendezVousRange that defines when the player is considered to have arrived at the RendezVous point.
|
||||||
-- @param Wrapper.Unit#UNIT TaskUnit
|
-- @param Wrapper.Unit#UNIT TaskUnit
|
||||||
function TASK_A2A:SetRendezVousCoordinate( RendezVousCoordinate, RendezVousRange, TaskUnit )
|
function TASK_A2A:SetRendezVousCoordinate( RendezVousCoordinate, RendezVousRange, TaskUnit )
|
||||||
|
|
||||||
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
||||||
|
|
||||||
local ActRouteRendezVous = ProcessUnit:GetProcess( "RoutingToRendezVous", "RouteToRendezVousPoint" ) -- Actions.Act_Route#ACT_ROUTE_POINT
|
local ActRouteRendezVous = ProcessUnit:GetProcess( "RoutingToRendezVous", "RouteToRendezVousPoint" ) -- Actions.Act_Route#ACT_ROUTE_POINT
|
||||||
ActRouteRendezVous:SetCoordinate( RendezVousCoordinate )
|
ActRouteRendezVous:SetCoordinate( RendezVousCoordinate )
|
||||||
ActRouteRendezVous:SetRange( RendezVousRange )
|
ActRouteRendezVous:SetRange( RendezVousRange )
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #TASK_A2A self
|
--- @param #TASK_A2A self
|
||||||
-- @param Wrapper.Unit#UNIT TaskUnit
|
-- @param Wrapper.Unit#UNIT TaskUnit
|
||||||
-- @return Core.Point#COORDINATE The Coordinate object referencing to the 2D point where the RendezVous point is located on the map.
|
-- @return Core.Point#COORDINATE The Coordinate object referencing to the 2D point where the RendezVous point is located on the map.
|
||||||
-- @return #number The RendezVousRange that defines when the player is considered to have arrived at the RendezVous point.
|
-- @return #number The RendezVousRange that defines when the player is considered to have arrived at the RendezVous point.
|
||||||
function TASK_A2A:GetRendezVousCoordinate( TaskUnit )
|
function TASK_A2A:GetRendezVousCoordinate( TaskUnit )
|
||||||
|
|
||||||
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
||||||
|
|
||||||
local ActRouteRendezVous = ProcessUnit:GetProcess( "RoutingToRendezVous", "RouteToRendezVousPoint" ) -- Actions.Act_Route#ACT_ROUTE_POINT
|
local ActRouteRendezVous = ProcessUnit:GetProcess( "RoutingToRendezVous", "RouteToRendezVousPoint" ) -- Actions.Act_Route#ACT_ROUTE_POINT
|
||||||
return ActRouteRendezVous:GetCoordinate(), ActRouteRendezVous:GetRange()
|
return ActRouteRendezVous:GetCoordinate(), ActRouteRendezVous:GetRange()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--- @param #TASK_A2A self
|
--- @param #TASK_A2A self
|
||||||
-- @param Core.Zone#ZONE_BASE RendezVousZone The Zone object where the RendezVous is located on the map.
|
-- @param Core.Zone#ZONE_BASE RendezVousZone The Zone object where the RendezVous is located on the map.
|
||||||
-- @param Wrapper.Unit#UNIT TaskUnit
|
-- @param Wrapper.Unit#UNIT TaskUnit
|
||||||
function TASK_A2A:SetRendezVousZone( RendezVousZone, TaskUnit )
|
function TASK_A2A:SetRendezVousZone( RendezVousZone, TaskUnit )
|
||||||
|
|
||||||
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
||||||
|
|
||||||
local ActRouteRendezVous = ProcessUnit:GetProcess( "RoutingToRendezVous", "RouteToRendezVousZone" ) -- Actions.Act_Route#ACT_ROUTE_ZONE
|
local ActRouteRendezVous = ProcessUnit:GetProcess( "RoutingToRendezVous", "RouteToRendezVousZone" ) -- Actions.Act_Route#ACT_ROUTE_ZONE
|
||||||
@@ -232,18 +226,17 @@ do -- TASK_A2A
|
|||||||
local ActRouteRendezVous = ProcessUnit:GetProcess( "RoutingToRendezVous", "RouteToRendezVousZone" ) -- Actions.Act_Route#ACT_ROUTE_ZONE
|
local ActRouteRendezVous = ProcessUnit:GetProcess( "RoutingToRendezVous", "RouteToRendezVousZone" ) -- Actions.Act_Route#ACT_ROUTE_ZONE
|
||||||
return ActRouteRendezVous:GetZone()
|
return ActRouteRendezVous:GetZone()
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #TASK_A2A self
|
--- @param #TASK_A2A self
|
||||||
-- @param Core.Point#COORDINATE TargetCoordinate The Coordinate object where the Target is located on the map.
|
-- @param Core.Point#COORDINATE TargetCoordinate The Coordinate object where the Target is located on the map.
|
||||||
-- @param Wrapper.Unit#UNIT TaskUnit
|
-- @param Wrapper.Unit#UNIT TaskUnit
|
||||||
function TASK_A2A:SetTargetCoordinate( TargetCoordinate, TaskUnit )
|
function TASK_A2A:SetTargetCoordinate( TargetCoordinate, TaskUnit )
|
||||||
|
|
||||||
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
||||||
|
|
||||||
local ActRouteTarget = ProcessUnit:GetProcess( "Engaging", "RouteToTargetPoint" ) -- Actions.Act_Route#ACT_ROUTE_POINT
|
local ActRouteTarget = ProcessUnit:GetProcess( "Engaging", "RouteToTargetPoint" ) -- Actions.Act_Route#ACT_ROUTE_POINT
|
||||||
ActRouteTarget:SetCoordinate( TargetCoordinate )
|
ActRouteTarget:SetCoordinate( TargetCoordinate )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- @param #TASK_A2A self
|
--- @param #TASK_A2A self
|
||||||
-- @param Wrapper.Unit#UNIT TaskUnit
|
-- @param Wrapper.Unit#UNIT TaskUnit
|
||||||
@@ -256,18 +249,16 @@ do -- TASK_A2A
|
|||||||
return ActRouteTarget:GetCoordinate()
|
return ActRouteTarget:GetCoordinate()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- @param #TASK_A2A self
|
--- @param #TASK_A2A self
|
||||||
-- @param Core.Zone#ZONE_BASE TargetZone The Zone object where the Target is located on the map.
|
-- @param Core.Zone#ZONE_BASE TargetZone The Zone object where the Target is located on the map.
|
||||||
-- @param Wrapper.Unit#UNIT TaskUnit
|
-- @param Wrapper.Unit#UNIT TaskUnit
|
||||||
function TASK_A2A:SetTargetZone( TargetZone, Altitude, Heading, TaskUnit )
|
function TASK_A2A:SetTargetZone( TargetZone, Altitude, Heading, TaskUnit )
|
||||||
|
|
||||||
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
||||||
|
|
||||||
local ActRouteTarget = ProcessUnit:GetProcess( "Engaging", "RouteToTargetZone" ) -- Actions.Act_Route#ACT_ROUTE_ZONE
|
local ActRouteTarget = ProcessUnit:GetProcess( "Engaging", "RouteToTargetZone" ) -- Actions.Act_Route#ACT_ROUTE_ZONE
|
||||||
ActRouteTarget:SetZone( TargetZone, Altitude, Heading )
|
ActRouteTarget:SetZone( TargetZone, Altitude, Heading )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- @param #TASK_A2A self
|
--- @param #TASK_A2A self
|
||||||
-- @param Wrapper.Unit#UNIT TaskUnit
|
-- @param Wrapper.Unit#UNIT TaskUnit
|
||||||
@@ -281,45 +272,43 @@ do -- TASK_A2A
|
|||||||
end
|
end
|
||||||
|
|
||||||
function TASK_A2A:SetGoalTotal()
|
function TASK_A2A:SetGoalTotal()
|
||||||
|
|
||||||
self.GoalTotal = self.TargetSetUnit:Count()
|
self.GoalTotal = self.TargetSetUnit:Count()
|
||||||
end
|
end
|
||||||
|
|
||||||
function TASK_A2A:GetGoalTotal()
|
function TASK_A2A:GetGoalTotal()
|
||||||
|
|
||||||
return self.GoalTotal
|
return self.GoalTotal
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Return the relative distance to the target vicinity from the player, in order to sort the targets in the reports per distance from the threats.
|
--- Return the relative distance to the target vicinity from the player, in order to sort the targets in the reports per distance from the threats.
|
||||||
-- @param #TASK_A2A self
|
-- @param #TASK_A2A self
|
||||||
function TASK_A2A:ReportOrder( ReportGroup )
|
function TASK_A2A:ReportOrder( ReportGroup )
|
||||||
self:UpdateTaskInfo( self.DetectedItem )
|
self:UpdateTaskInfo( self.DetectedItem )
|
||||||
|
|
||||||
local Coordinate = self.TaskInfo:GetData( "Coordinate" )
|
local Coordinate = self.TaskInfo:GetData( "Coordinate" )
|
||||||
local Distance = ReportGroup:GetCoordinate():Get2DDistance( Coordinate )
|
local Distance = ReportGroup:GetCoordinate():Get2DDistance( Coordinate )
|
||||||
|
|
||||||
return Distance
|
return Distance
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- This method checks every 10 seconds if the goal has been reached of the task.
|
--- This method checks every 10 seconds if the goal has been reached of the task.
|
||||||
-- @param #TASK_A2A self
|
-- @param #TASK_A2A self
|
||||||
function TASK_A2A:onafterGoal( TaskUnit, From, Event, To )
|
function TASK_A2A:onafterGoal( TaskUnit, From, Event, To )
|
||||||
local TargetSetUnit = self.TargetSetUnit -- Core.Set#SET_UNIT
|
local TargetSetUnit = self.TargetSetUnit -- Core.Set#SET_UNIT
|
||||||
|
|
||||||
if TargetSetUnit:Count() == 0 then
|
if TargetSetUnit:Count() == 0 then
|
||||||
self:Success()
|
self:Success()
|
||||||
end
|
end
|
||||||
|
|
||||||
self:__Goal( -10 )
|
self:__Goal( -10 )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- @param #TASK_A2A self
|
--- @param #TASK_A2A self
|
||||||
function TASK_A2A:UpdateTaskInfo( DetectedItem )
|
function TASK_A2A:UpdateTaskInfo( DetectedItem )
|
||||||
|
|
||||||
if self:IsStatePlanned() or self:IsStateAssigned() then
|
if self:IsStatePlanned() or self:IsStateAssigned() then
|
||||||
local TargetCoordinate = DetectedItem and self.Detection:GetDetectedItemCoordinate( DetectedItem ) or self.TargetSetUnit:GetFirst():GetCoordinate()
|
local TargetCoordinate = DetectedItem and self.Detection:GetDetectedItemCoordinate( DetectedItem ) or self.TargetSetUnit:GetFirst():GetCoordinate()
|
||||||
self.TaskInfo:AddTaskName( 0, "MSOD" )
|
self.TaskInfo:AddTaskName( 0, "MSOD" )
|
||||||
self.TaskInfo:AddCoordinate( TargetCoordinate, 1, "SOD" )
|
self.TaskInfo:AddCoordinate( TargetCoordinate, 1, "SOD" )
|
||||||
|
|
||||||
@@ -343,12 +332,12 @@ do -- TASK_A2A
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
self.TaskInfo:AddTargetCount( DetectedItemsCount, 11, "O", true )
|
self.TaskInfo:AddTargetCount( DetectedItemsCount, 11, "O", true )
|
||||||
self.TaskInfo:AddTargets( DetectedItemsCount, ReportTypes:Text( ", " ), 20, "D", true )
|
self.TaskInfo:AddTargets( DetectedItemsCount, ReportTypes:Text( ", " ), 20, "D", true )
|
||||||
else
|
else
|
||||||
local DetectedItemsCount = self.TargetSetUnit:Count()
|
local DetectedItemsCount = self.TargetSetUnit:Count()
|
||||||
local DetectedItemsTypes = self.TargetSetUnit:GetTypeNames()
|
local DetectedItemsTypes = self.TargetSetUnit:GetTypeNames()
|
||||||
self.TaskInfo:AddTargetCount( DetectedItemsCount, 11, "O", true )
|
self.TaskInfo:AddTargetCount( DetectedItemsCount, 11, "O", true )
|
||||||
self.TaskInfo:AddTargets( DetectedItemsCount, DetectedItemsTypes, 20, "D", true )
|
self.TaskInfo:AddTargets( DetectedItemsCount, DetectedItemsTypes, 20, "D", true )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -359,8 +348,8 @@ do -- TASK_A2A
|
|||||||
-- @param Tasking.CommandCenter#COMMANDCENTER CommandCenter The command center.
|
-- @param Tasking.CommandCenter#COMMANDCENTER CommandCenter The command center.
|
||||||
-- @param Wrapper.Group#GROUP TaskGroup The player group.
|
-- @param Wrapper.Group#GROUP TaskGroup The player group.
|
||||||
function TASK_A2A:GetAutoAssignPriority( AutoAssignMethod, CommandCenter, TaskGroup )
|
function TASK_A2A:GetAutoAssignPriority( AutoAssignMethod, CommandCenter, TaskGroup )
|
||||||
|
|
||||||
if AutoAssignMethod == COMMANDCENTER.AutoAssignMethods.Random then
|
if AutoAssignMethod == COMMANDCENTER.AutoAssignMethods.Random then
|
||||||
return math.random( 1, 9 )
|
return math.random( 1, 9 )
|
||||||
elseif AutoAssignMethod == COMMANDCENTER.AutoAssignMethods.Distance then
|
elseif AutoAssignMethod == COMMANDCENTER.AutoAssignMethods.Distance then
|
||||||
local Coordinate = self.TaskInfo:GetData( "Coordinate" )
|
local Coordinate = self.TaskInfo:GetData( "Coordinate" )
|
||||||
@@ -373,8 +362,7 @@ do -- TASK_A2A
|
|||||||
return 0
|
return 0
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
do -- TASK_A2A_INTERCEPT
|
do -- TASK_A2A_INTERCEPT
|
||||||
|
|
||||||
@@ -384,44 +372,39 @@ do -- TASK_A2A_INTERCEPT
|
|||||||
-- @extends Tasking.Task#TASK
|
-- @extends Tasking.Task#TASK
|
||||||
|
|
||||||
--- Defines an intercept task for a human player to be executed.
|
--- Defines an intercept task for a human player to be executed.
|
||||||
-- When enemy planes need to be intercepted by human players, use this task type to urgen the players to get out there!
|
-- When enemy planes need to be intercepted by human players, use this task type to urge the players to get out there!
|
||||||
--
|
--
|
||||||
-- The TASK_A2A_INTERCEPT is used by the @{Tasking.Task_A2A_Dispatcher#TASK_A2A_DISPATCHER} to automatically create intercept tasks
|
-- The TASK_A2A_INTERCEPT is used by the @{Tasking.Task_A2A_Dispatcher#TASK_A2A_DISPATCHER} to automatically create intercept tasks
|
||||||
-- based on detected airborne enemy targets intruding friendly airspace.
|
-- based on detected airborne enemy targets intruding friendly airspace.
|
||||||
--
|
--
|
||||||
-- The task is defined for a @{Tasking.Mission#MISSION}, where a friendly @{Core.Set#SET_GROUP} consisting of GROUPs with one human players each, is intercepting the targets.
|
-- The task is defined for a @{Tasking.Mission#MISSION}, where a friendly @{Core.Set#SET_GROUP} consisting of GROUPs with one human players each, is intercepting the targets.
|
||||||
-- The task is given a name and a briefing, that is used in the menu structure and in the reporting.
|
-- The task is given a name and a briefing, that is used in the menu structure and in the reporting.
|
||||||
--
|
--
|
||||||
-- @field #TASK_A2A_INTERCEPT
|
-- @field #TASK_A2A_INTERCEPT
|
||||||
TASK_A2A_INTERCEPT = {
|
TASK_A2A_INTERCEPT = {
|
||||||
ClassName = "TASK_A2A_INTERCEPT",
|
ClassName = "TASK_A2A_INTERCEPT"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--- Instantiates a new TASK_A2A_INTERCEPT.
|
--- Instantiates a new TASK_A2A_INTERCEPT.
|
||||||
-- @param #TASK_A2A_INTERCEPT self
|
-- @param #TASK_A2A_INTERCEPT self
|
||||||
-- @param Tasking.Mission#MISSION Mission
|
-- @param Tasking.Mission#MISSION Mission
|
||||||
-- @param Core.Set#SET_GROUP SetGroup The set of groups for which the Task can be assigned.
|
-- @param Core.Set#SET_GROUP SetGroup The set of groups for which the Task can be assigned.
|
||||||
-- @param #string TaskName The name of the Task.
|
-- @param #string TaskName The name of the Task.
|
||||||
-- @param Core.Set#SET_UNIT TargetSetUnit
|
-- @param Core.Set#SET_UNIT TargetSetUnit
|
||||||
-- @param #string TaskBriefing The briefing of the task.
|
-- @param #string TaskBriefing The briefing of the task.
|
||||||
-- @return #TASK_A2A_INTERCEPT
|
-- @return #TASK_A2A_INTERCEPT
|
||||||
function TASK_A2A_INTERCEPT:New( Mission, SetGroup, TaskName, TargetSetUnit, TaskBriefing )
|
function TASK_A2A_INTERCEPT:New( Mission, SetGroup, TaskName, TargetSetUnit, TaskBriefing )
|
||||||
local self = BASE:Inherit( self, TASK_A2A:New( Mission, SetGroup, TaskName, TargetSetUnit, "INTERCEPT", TaskBriefing ) ) -- #TASK_A2A_INTERCEPT
|
local self = BASE:Inherit( self, TASK_A2A:New( Mission, SetGroup, TaskName, TargetSetUnit, "INTERCEPT", TaskBriefing ) ) -- #TASK_A2A_INTERCEPT
|
||||||
self:F()
|
self:F()
|
||||||
|
|
||||||
Mission:AddTask( self )
|
Mission:AddTask( self )
|
||||||
|
|
||||||
self:SetBriefing(
|
self:SetBriefing( TaskBriefing or "Intercept incoming intruders.\n" )
|
||||||
TaskBriefing or
|
|
||||||
"Intercept incoming intruders.\n"
|
|
||||||
)
|
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Set a score when a target in scope of the A2A attack, has been destroyed .
|
--- Set a score when a target in scope of the A2A attack, has been destroyed.
|
||||||
-- @param #TASK_A2A_INTERCEPT self
|
-- @param #TASK_A2A_INTERCEPT self
|
||||||
-- @param #string PlayerName The name of the player.
|
-- @param #string PlayerName The name of the player.
|
||||||
-- @param #number Score The score in points to be granted when task process has been achieved.
|
-- @param #number Score The score in points to be granted when task process has been achieved.
|
||||||
@@ -433,7 +416,7 @@ do -- TASK_A2A_INTERCEPT
|
|||||||
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
||||||
|
|
||||||
ProcessUnit:AddScoreProcess( "Engaging", "Account", "AccountForPlayer", "Player " .. PlayerName .. " has intercepted a target.", Score )
|
ProcessUnit:AddScoreProcess( "Engaging", "Account", "AccountForPlayer", "Player " .. PlayerName .. " has intercepted a target.", Score )
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -449,7 +432,7 @@ do -- TASK_A2A_INTERCEPT
|
|||||||
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
||||||
|
|
||||||
ProcessUnit:AddScore( "Success", "All targets have been successfully intercepted!", Score )
|
ProcessUnit:AddScore( "Success", "All targets have been successfully intercepted!", Score )
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -465,14 +448,12 @@ do -- TASK_A2A_INTERCEPT
|
|||||||
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
||||||
|
|
||||||
ProcessUnit:AddScore( "Failed", "The intercept has failed!", Penalty )
|
ProcessUnit:AddScore( "Failed", "The intercept has failed!", Penalty )
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
do -- TASK_A2A_SWEEP
|
do -- TASK_A2A_SWEEP
|
||||||
|
|
||||||
--- The TASK_A2A_SWEEP class
|
--- The TASK_A2A_SWEEP class
|
||||||
@@ -484,20 +465,18 @@ do -- TASK_A2A_SWEEP
|
|||||||
-- A sweep task needs to be given when targets were detected but somehow the detection was lost.
|
-- A sweep task needs to be given when targets were detected but somehow the detection was lost.
|
||||||
-- Most likely, these enemy planes are hidden in the mountains or are flying under radar.
|
-- Most likely, these enemy planes are hidden in the mountains or are flying under radar.
|
||||||
-- These enemy planes need to be sweeped by human players, and use this task type to urge the players to get out there and find those enemy fighters.
|
-- These enemy planes need to be sweeped by human players, and use this task type to urge the players to get out there and find those enemy fighters.
|
||||||
--
|
--
|
||||||
-- The TASK_A2A_SWEEP is used by the @{Tasking.Task_A2A_Dispatcher#TASK_A2A_DISPATCHER} to automatically create sweep tasks
|
-- The TASK_A2A_SWEEP is used by the @{Tasking.Task_A2A_Dispatcher#TASK_A2A_DISPATCHER} to automatically create sweep tasks
|
||||||
-- based on detected airborne enemy targets intruding friendly airspace, for which the detection has been lost for more than 60 seconds.
|
-- based on detected airborne enemy targets intruding friendly airspace, for which the detection has been lost for more than 60 seconds.
|
||||||
--
|
--
|
||||||
-- The task is defined for a @{Tasking.Mission#MISSION}, where a friendly @{Core.Set#SET_GROUP} consisting of GROUPs with one human players each, is sweeping the targets.
|
-- The task is defined for a @{Tasking.Mission#MISSION}, where a friendly @{Core.Set#SET_GROUP} consisting of GROUPs with one human players each, is sweeping the targets.
|
||||||
-- The task is given a name and a briefing, that is used in the menu structure and in the reporting.
|
-- The task is given a name and a briefing, that is used in the menu structure and in the reporting.
|
||||||
--
|
--
|
||||||
-- @field #TASK_A2A_SWEEP
|
-- @field #TASK_A2A_SWEEP
|
||||||
TASK_A2A_SWEEP = {
|
TASK_A2A_SWEEP = {
|
||||||
ClassName = "TASK_A2A_SWEEP",
|
ClassName = "TASK_A2A_SWEEP"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--- Instantiates a new TASK_A2A_SWEEP.
|
--- Instantiates a new TASK_A2A_SWEEP.
|
||||||
-- @param #TASK_A2A_SWEEP self
|
-- @param #TASK_A2A_SWEEP self
|
||||||
-- @param Tasking.Mission#MISSION Mission
|
-- @param Tasking.Mission#MISSION Mission
|
||||||
@@ -509,29 +488,26 @@ do -- TASK_A2A_SWEEP
|
|||||||
function TASK_A2A_SWEEP:New( Mission, SetGroup, TaskName, TargetSetUnit, TaskBriefing )
|
function TASK_A2A_SWEEP:New( Mission, SetGroup, TaskName, TargetSetUnit, TaskBriefing )
|
||||||
local self = BASE:Inherit( self, TASK_A2A:New( Mission, SetGroup, TaskName, TargetSetUnit, "SWEEP", TaskBriefing ) ) -- #TASK_A2A_SWEEP
|
local self = BASE:Inherit( self, TASK_A2A:New( Mission, SetGroup, TaskName, TargetSetUnit, "SWEEP", TaskBriefing ) ) -- #TASK_A2A_SWEEP
|
||||||
self:F()
|
self:F()
|
||||||
|
|
||||||
Mission:AddTask( self )
|
Mission:AddTask( self )
|
||||||
|
|
||||||
self:SetBriefing(
|
self:SetBriefing( TaskBriefing or "Perform a fighter sweep. Incoming intruders were detected and could be hiding at the location.\n" )
|
||||||
TaskBriefing or
|
|
||||||
"Perform a fighter sweep. Incoming intruders were detected and could be hiding at the location.\n"
|
|
||||||
)
|
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #TASK_A2A_SWEEP self
|
--- @param #TASK_A2A_SWEEP self
|
||||||
function TASK_A2A_SWEEP:onafterGoal( TaskUnit, From, Event, To )
|
function TASK_A2A_SWEEP:onafterGoal( TaskUnit, From, Event, To )
|
||||||
local TargetSetUnit = self.TargetSetUnit -- Core.Set#SET_UNIT
|
local TargetSetUnit = self.TargetSetUnit -- Core.Set#SET_UNIT
|
||||||
|
|
||||||
if TargetSetUnit:Count() == 0 then
|
if TargetSetUnit:Count() == 0 then
|
||||||
self:Success()
|
self:Success()
|
||||||
end
|
end
|
||||||
|
|
||||||
self:__Goal( -10 )
|
self:__Goal( -10 )
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Set a score when a target in scope of the A2A attack, has been destroyed .
|
--- Set a score when a target in scope of the A2A attack, has been destroyed.
|
||||||
-- @param #TASK_A2A_SWEEP self
|
-- @param #TASK_A2A_SWEEP self
|
||||||
-- @param #string PlayerName The name of the player.
|
-- @param #string PlayerName The name of the player.
|
||||||
-- @param #number Score The score in points to be granted when task process has been achieved.
|
-- @param #number Score The score in points to be granted when task process has been achieved.
|
||||||
@@ -543,7 +519,7 @@ do -- TASK_A2A_SWEEP
|
|||||||
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
||||||
|
|
||||||
ProcessUnit:AddScoreProcess( "Engaging", "Account", "AccountForPlayer", "Player " .. PlayerName .. " has sweeped a target.", Score )
|
ProcessUnit:AddScoreProcess( "Engaging", "Account", "AccountForPlayer", "Player " .. PlayerName .. " has sweeped a target.", Score )
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -559,7 +535,7 @@ do -- TASK_A2A_SWEEP
|
|||||||
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
||||||
|
|
||||||
ProcessUnit:AddScore( "Success", "All targets have been successfully sweeped!", Score )
|
ProcessUnit:AddScore( "Success", "All targets have been successfully sweeped!", Score )
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -575,13 +551,12 @@ do -- TASK_A2A_SWEEP
|
|||||||
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
||||||
|
|
||||||
ProcessUnit:AddScore( "Failed", "The sweep has failed!", Penalty )
|
ProcessUnit:AddScore( "Failed", "The sweep has failed!", Penalty )
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
do -- TASK_A2A_ENGAGE
|
do -- TASK_A2A_ENGAGE
|
||||||
|
|
||||||
--- The TASK_A2A_ENGAGE class
|
--- The TASK_A2A_ENGAGE class
|
||||||
@@ -591,42 +566,37 @@ do -- TASK_A2A_ENGAGE
|
|||||||
|
|
||||||
--- Defines an engage task for a human player to be executed.
|
--- Defines an engage task for a human player to be executed.
|
||||||
-- When enemy planes are close to human players, use this task type is used urge the players to get out there!
|
-- When enemy planes are close to human players, use this task type is used urge the players to get out there!
|
||||||
--
|
--
|
||||||
-- The TASK_A2A_ENGAGE is used by the @{Tasking.Task_A2A_Dispatcher#TASK_A2A_DISPATCHER} to automatically create engage tasks
|
-- The TASK_A2A_ENGAGE is used by the @{Tasking.Task_A2A_Dispatcher#TASK_A2A_DISPATCHER} to automatically create engage tasks
|
||||||
-- based on detected airborne enemy targets intruding friendly airspace.
|
-- based on detected airborne enemy targets intruding friendly airspace.
|
||||||
--
|
--
|
||||||
-- The task is defined for a @{Tasking.Mission#MISSION}, where a friendly @{Core.Set#SET_GROUP} consisting of GROUPs with one human players each, is engaging the targets.
|
-- The task is defined for a @{Tasking.Mission#MISSION}, where a friendly @{Core.Set#SET_GROUP} consisting of GROUPs with one human players each, is engaging the targets.
|
||||||
-- The task is given a name and a briefing, that is used in the menu structure and in the reporting.
|
-- The task is given a name and a briefing, that is used in the menu structure and in the reporting.
|
||||||
--
|
--
|
||||||
-- @field #TASK_A2A_ENGAGE
|
-- @field #TASK_A2A_ENGAGE
|
||||||
TASK_A2A_ENGAGE = {
|
TASK_A2A_ENGAGE = {
|
||||||
ClassName = "TASK_A2A_ENGAGE",
|
ClassName = "TASK_A2A_ENGAGE"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--- Instantiates a new TASK_A2A_ENGAGE.
|
--- Instantiates a new TASK_A2A_ENGAGE.
|
||||||
-- @param #TASK_A2A_ENGAGE self
|
-- @param #TASK_A2A_ENGAGE self
|
||||||
-- @param Tasking.Mission#MISSION Mission
|
-- @param Tasking.Mission#MISSION Mission
|
||||||
-- @param Core.Set#SET_GROUP SetGroup The set of groups for which the Task can be assigned.
|
-- @param Core.Set#SET_GROUP SetGroup The set of groups for which the Task can be assigned.
|
||||||
-- @param #string TaskName The name of the Task.
|
-- @param #string TaskName The name of the Task.
|
||||||
-- @param Core.Set#SET_UNIT TargetSetUnit
|
-- @param Core.Set#SET_UNIT TargetSetUnit
|
||||||
-- @param #string TaskBriefing The briefing of the task.
|
-- @param #string TaskBriefing The briefing of the task.
|
||||||
-- @return #TASK_A2A_ENGAGE self
|
-- @return #TASK_A2A_ENGAGE self
|
||||||
function TASK_A2A_ENGAGE:New( Mission, SetGroup, TaskName, TargetSetUnit, TaskBriefing )
|
function TASK_A2A_ENGAGE:New( Mission, SetGroup, TaskName, TargetSetUnit, TaskBriefing )
|
||||||
local self = BASE:Inherit( self, TASK_A2A:New( Mission, SetGroup, TaskName, TargetSetUnit, "ENGAGE", TaskBriefing ) ) -- #TASK_A2A_ENGAGE
|
local self = BASE:Inherit( self, TASK_A2A:New( Mission, SetGroup, TaskName, TargetSetUnit, "ENGAGE", TaskBriefing ) ) -- #TASK_A2A_ENGAGE
|
||||||
self:F()
|
self:F()
|
||||||
|
|
||||||
Mission:AddTask( self )
|
Mission:AddTask( self )
|
||||||
|
|
||||||
self:SetBriefing(
|
self:SetBriefing( TaskBriefing or "Bogeys are nearby! Players close by are ordered to ENGAGE the intruders!\n" )
|
||||||
TaskBriefing or
|
|
||||||
"Bogeys are nearby! Players close by are ordered to ENGAGE the intruders!\n"
|
|
||||||
)
|
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Set a score when a target in scope of the A2A attack, has been destroyed .
|
--- Set a score when a target in scope of the A2A attack, has been destroyed .
|
||||||
-- @param #TASK_A2A_ENGAGE self
|
-- @param #TASK_A2A_ENGAGE self
|
||||||
-- @param #string PlayerName The name of the player.
|
-- @param #string PlayerName The name of the player.
|
||||||
@@ -639,7 +609,7 @@ do -- TASK_A2A_ENGAGE
|
|||||||
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
||||||
|
|
||||||
ProcessUnit:AddScoreProcess( "Engaging", "Account", "AccountForPlayer", "Player " .. PlayerName .. " has engaged and destroyed a target.", Score )
|
ProcessUnit:AddScoreProcess( "Engaging", "Account", "AccountForPlayer", "Player " .. PlayerName .. " has engaged and destroyed a target.", Score )
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -655,7 +625,7 @@ do -- TASK_A2A_ENGAGE
|
|||||||
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
||||||
|
|
||||||
ProcessUnit:AddScore( "Success", "All targets have been successfully engaged!", Score )
|
ProcessUnit:AddScore( "Success", "All targets have been successfully engaged!", Score )
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -671,7 +641,7 @@ do -- TASK_A2A_ENGAGE
|
|||||||
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
||||||
|
|
||||||
ProcessUnit:AddScore( "Failed", "The target engagement has failed!", Penalty )
|
ProcessUnit:AddScore( "Failed", "The target engagement has failed!", Penalty )
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
--- **Tasking** - Dynamically allocates A2A tasks to human players, based on detected airborne targets through an EWR network.
|
--- **Tasking** - Dynamically allocates A2A tasks to human players, based on detected airborne targets through an EWR network.
|
||||||
--
|
--
|
||||||
-- **Features:**
|
-- **Features:**
|
||||||
--
|
--
|
||||||
-- * Dynamically assign tasks to human players based on detected targets.
|
-- * Dynamically assign tasks to human players based on detected targets.
|
||||||
-- * Dynamically change the tasks as the tactical situation evolves during the mission.
|
-- * Dynamically change the tasks as the tactical situation evolves during the mission.
|
||||||
-- * Dynamically assign (CAP) Control Air Patrols tasks for human players to perform CAP.
|
-- * Dynamically assign (CAP) Control Air Patrols tasks for human players to perform CAP.
|
||||||
@@ -11,15 +11,15 @@
|
|||||||
-- * Define different ranges to engage upon intruders.
|
-- * Define different ranges to engage upon intruders.
|
||||||
-- * Keep task achievements.
|
-- * Keep task achievements.
|
||||||
-- * Score task achievements.
|
-- * Score task achievements.
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ### Author: **FlightControl**
|
-- ### Author: **FlightControl**
|
||||||
--
|
--
|
||||||
-- ### Contributions:
|
-- ### Contributions:
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- @module Tasking.Task_A2A_Dispatcher
|
-- @module Tasking.Task_A2A_Dispatcher
|
||||||
-- @image Task_A2A_Dispatcher.JPG
|
-- @image Task_A2A_Dispatcher.JPG
|
||||||
|
|
||||||
@@ -30,72 +30,72 @@ do -- TASK_A2A_DISPATCHER
|
|||||||
-- @extends Tasking.DetectionManager#DETECTION_MANAGER
|
-- @extends Tasking.DetectionManager#DETECTION_MANAGER
|
||||||
|
|
||||||
--- Orchestrates the dynamic dispatching of tasks upon groups of detected units determined a @{Set} of EWR installation groups.
|
--- Orchestrates the dynamic dispatching of tasks upon groups of detected units determined a @{Set} of EWR installation groups.
|
||||||
--
|
--
|
||||||
-- 
|
-- 
|
||||||
--
|
--
|
||||||
-- The EWR will detect units, will group them, and will dispatch @{Task}s to groups. Depending on the type of target detected, different tasks will be dispatched.
|
-- The EWR will detect units, will group them, and will dispatch @{Task}s to groups. Depending on the type of target detected, different tasks will be dispatched.
|
||||||
-- Find a summary below describing for which situation a task type is created:
|
-- Find a summary below describing for which situation a task type is created:
|
||||||
--
|
--
|
||||||
-- 
|
-- 
|
||||||
--
|
--
|
||||||
-- * **INTERCEPT Task**: Is created when the target is known, is detected and within a danger zone, and there is no friendly airborne in range.
|
-- * **INTERCEPT Task**: Is created when the target is known, is detected and within a danger zone, and there is no friendly airborne in range.
|
||||||
-- * **SWEEP Task**: Is created when the target is unknown, was detected and the last position is only known, and within a danger zone, and there is no friendly airborne in range.
|
-- * **SWEEP Task**: Is created when the target is unknown, was detected and the last position is only known, and within a danger zone, and there is no friendly airborne in range.
|
||||||
-- * **ENGAGE Task**: Is created when the target is known, is detected and within a danger zone, and there is a friendly airborne in range, that will receive this task.
|
-- * **ENGAGE Task**: Is created when the target is known, is detected and within a danger zone, and there is a friendly airborne in range, that will receive this task.
|
||||||
--
|
--
|
||||||
-- ## 1. TASK\_A2A\_DISPATCHER constructor:
|
-- ## 1. TASK\_A2A\_DISPATCHER constructor:
|
||||||
--
|
--
|
||||||
-- The @{#TASK_A2A_DISPATCHER.New}() method creates a new TASK\_A2A\_DISPATCHER instance.
|
-- The @{#TASK_A2A_DISPATCHER.New}() method creates a new TASK\_A2A\_DISPATCHER instance.
|
||||||
--
|
--
|
||||||
-- ### 1.1. Define or set the **Mission**:
|
-- ### 1.1. Define or set the **Mission**:
|
||||||
--
|
--
|
||||||
-- Tasking is executed to accomplish missions. Therefore, a MISSION object needs to be given as the first parameter.
|
-- Tasking is executed to accomplish missions. Therefore, a MISSION object needs to be given as the first parameter.
|
||||||
--
|
--
|
||||||
-- local HQ = GROUP:FindByName( "HQ", "Bravo" )
|
-- local HQ = GROUP:FindByName( "HQ", "Bravo" )
|
||||||
-- local CommandCenter = COMMANDCENTER:New( HQ, "Lima" )
|
-- local CommandCenter = COMMANDCENTER:New( HQ, "Lima" )
|
||||||
-- local Mission = MISSION:New( CommandCenter, "A2A Mission", "High", "Watch the air enemy units being detected.", coalition.side.RED )
|
-- local Mission = MISSION:New( CommandCenter, "A2A Mission", "High", "Watch the air enemy units being detected.", coalition.side.RED )
|
||||||
--
|
--
|
||||||
-- Missions are governed by COMMANDCENTERS, so, ensure you have a COMMANDCENTER object installed and setup within your mission.
|
-- Missions are governed by COMMANDCENTERS, so, ensure you have a COMMANDCENTER object installed and setup within your mission.
|
||||||
-- Create the MISSION object, and hook it under the command center.
|
-- Create the MISSION object, and hook it under the command center.
|
||||||
--
|
--
|
||||||
-- ### 1.2. Build a set of the groups seated by human players:
|
-- ### 1.2. Build a set of the groups seated by human players:
|
||||||
--
|
--
|
||||||
-- 
|
-- 
|
||||||
--
|
--
|
||||||
-- A set or collection of the groups wherein human players can be seated, these can be clients or units that can be joined as a slot or jumping into.
|
-- A set or collection of the groups wherein human players can be seated, these can be clients or units that can be joined as a slot or jumping into.
|
||||||
--
|
--
|
||||||
-- local AttackGroups = SET_GROUP:New():FilterCoalitions( "red" ):FilterPrefixes( "Defender" ):FilterStart()
|
-- local AttackGroups = SET_GROUP:New():FilterCoalitions( "red" ):FilterPrefixes( "Defender" ):FilterStart()
|
||||||
--
|
--
|
||||||
-- The set is built using the SET_GROUP class. Apply any filter criteria to identify the correct groups for your mission.
|
-- The set is built using the SET_GROUP class. Apply any filter criteria to identify the correct groups for your mission.
|
||||||
-- Only these slots or units will be able to execute the mission and will receive tasks for this mission, once available.
|
-- Only these slots or units will be able to execute the mission and will receive tasks for this mission, once available.
|
||||||
--
|
--
|
||||||
-- ### 1.3. Define the **EWR network**:
|
-- ### 1.3. Define the **EWR network**:
|
||||||
--
|
--
|
||||||
-- As part of the TASK\_A2A\_DISPATCHER constructor, an EWR network must be given as the third parameter.
|
-- As part of the TASK\_A2A\_DISPATCHER constructor, an EWR network must be given as the third parameter.
|
||||||
-- An EWR network, or, Early Warning Radar network, is used to early detect potential airborne targets and to understand the position of patrolling targets of the enemy.
|
-- An EWR network, or, Early Warning Radar network, is used to early detect potential airborne targets and to understand the position of patrolling targets of the enemy.
|
||||||
--
|
--
|
||||||
-- 
|
-- 
|
||||||
--
|
--
|
||||||
-- Typically EWR networks are setup using 55G6 EWR, 1L13 EWR, Hawk sr and Patriot str ground based radar units.
|
-- Typically EWR networks are setup using 55G6 EWR, 1L13 EWR, Hawk sr and Patriot str ground based radar units.
|
||||||
-- These radars have different ranges and 55G6 EWR and 1L13 EWR radars are Eastern Bloc units (eg Russia, Ukraine, Georgia) while the Hawk and Patriot radars are Western (eg US).
|
-- These radars have different ranges and 55G6 EWR and 1L13 EWR radars are Eastern Bloc units (eg Russia, Ukraine, Georgia) while the Hawk and Patriot radars are Western (eg US).
|
||||||
-- Additionally, ANY other radar capable unit can be part of the EWR network! Also AWACS airborne units, planes, helicopters can help to detect targets, as long as they have radar.
|
-- Additionally, ANY other radar capable unit can be part of the EWR network! Also AWACS airborne units, planes, helicopters can help to detect targets, as long as they have radar.
|
||||||
-- The position of these units is very important as they need to provide enough coverage
|
-- The position of these units is very important as they need to provide enough coverage
|
||||||
-- to pick up enemy aircraft as they approach so that CAP and GCI flights can be tasked to intercept them.
|
-- to pick up enemy aircraft as they approach so that CAP and GCI flights can be tasked to intercept them.
|
||||||
--
|
--
|
||||||
-- 
|
-- 
|
||||||
--
|
--
|
||||||
-- Additionally in a hot war situation where the border is no longer respected the placement of radars has a big effect on how fast the war escalates.
|
-- Additionally in a hot war situation where the border is no longer respected the placement of radars has a big effect on how fast the war escalates.
|
||||||
-- For example if they are a long way forward and can detect enemy planes on the ground and taking off
|
-- For example if they are a long way forward and can detect enemy planes on the ground and taking off
|
||||||
-- they will start to vector CAP and GCI flights to attack them straight away which will immediately draw a response from the other coalition.
|
-- they will start to vector CAP and GCI flights to attack them straight away which will immediately draw a response from the other coalition.
|
||||||
-- Having the radars further back will mean a slower escalation because fewer targets will be detected and
|
-- Having the radars further back will mean a slower escalation because fewer targets will be detected and
|
||||||
-- therefore less CAP and GCI flights will spawn and this will tend to make just the border area active rather than a melee over the whole map.
|
-- therefore less CAP and GCI flights will spawn and this will tend to make just the border area active rather than a melee over the whole map.
|
||||||
-- It all depends on what the desired effect is.
|
-- It all depends on what the desired effect is.
|
||||||
--
|
--
|
||||||
-- EWR networks are **dynamically constructed**, that is, they form part of the @{Functional.Detection#DETECTION_BASE} object that is given as the input parameter of the TASK\_A2A\_DISPATCHER class.
|
-- EWR networks are **dynamically constructed**, that is, they form part of the @{Functional.Detection#DETECTION_BASE} object that is given as the input parameter of the TASK\_A2A\_DISPATCHER class.
|
||||||
-- By defining in a **smart way the names or name prefixes of the groups** with EWR capable units, these groups will be **automatically added or deleted** from the EWR network,
|
-- By defining in a **smart way the names or name prefixes of the groups** with EWR capable units, these groups will be **automatically added or deleted** from the EWR network,
|
||||||
-- increasing or decreasing the radar coverage of the Early Warning System.
|
-- increasing or decreasing the radar coverage of the Early Warning System.
|
||||||
--
|
--
|
||||||
-- See the following example to setup an EWR network containing EWR stations and AWACS.
|
-- See the following example to setup an EWR network containing EWR stations and AWACS.
|
||||||
--
|
--
|
||||||
-- local EWRSet = SET_GROUP:New():FilterPrefixes( "EWR" ):FilterCoalitions("red"):FilterStart()
|
-- local EWRSet = SET_GROUP:New():FilterPrefixes( "EWR" ):FilterCoalitions("red"):FilterStart()
|
||||||
--
|
--
|
||||||
-- local EWRDetection = DETECTION_AREAS:New( EWRSet, 6000 )
|
-- local EWRDetection = DETECTION_AREAS:New( EWRSet, 6000 )
|
||||||
@@ -104,50 +104,50 @@ do -- TASK_A2A_DISPATCHER
|
|||||||
--
|
--
|
||||||
-- -- Setup the A2A dispatcher, and initialize it.
|
-- -- Setup the A2A dispatcher, and initialize it.
|
||||||
-- A2ADispatcher = TASK_A2A_DISPATCHER:New( Mission, AttackGroups, EWRDetection )
|
-- A2ADispatcher = TASK_A2A_DISPATCHER:New( Mission, AttackGroups, EWRDetection )
|
||||||
--
|
--
|
||||||
-- The above example creates a SET_GROUP instance, and stores this in the variable (object) **EWRSet**.
|
-- The above example creates a SET_GROUP instance, and stores this in the variable (object) **EWRSet**.
|
||||||
-- **EWRSet** is then being configured to filter all active groups with a group name starting with **EWR** to be included in the Set.
|
-- **EWRSet** is then being configured to filter all active groups with a group name starting with **EWR** to be included in the Set.
|
||||||
-- **EWRSet** is then being ordered to start the dynamic filtering. Note that any destroy or new spawn of a group with the above names will be removed or added to the Set.
|
-- **EWRSet** is then being ordered to start the dynamic filtering. Note that any destroy or new spawn of a group with the above names will be removed or added to the Set.
|
||||||
-- Then a new **EWRDetection** object is created from the class DETECTION_AREAS. A grouping radius of 6000 is choosen, which is 6km.
|
-- Then a new **EWRDetection** object is created from the class DETECTION_AREAS. A grouping radius of 6000 is chosen, which is 6 km.
|
||||||
-- The **EWRDetection** object is then passed to the @{#TASK_A2A_DISPATCHER.New}() method to indicate the EWR network configuration and setup the A2A tasking and detection mechanism.
|
-- The **EWRDetection** object is then passed to the @{#TASK_A2A_DISPATCHER.New}() method to indicate the EWR network configuration and setup the A2A tasking and detection mechanism.
|
||||||
--
|
--
|
||||||
-- ### 2. Define the detected **target grouping radius**:
|
-- ### 2. Define the detected **target grouping radius**:
|
||||||
--
|
--
|
||||||
-- 
|
-- 
|
||||||
--
|
--
|
||||||
-- The target grouping radius is a property of the Detection object, that was passed to the AI\_A2A\_DISPATCHER object, but can be changed.
|
-- The target grouping radius is a property of the Detection object, that was passed to the AI\_A2A\_DISPATCHER object, but can be changed.
|
||||||
-- The grouping radius should not be too small, but also depends on the types of planes and the era of the simulation.
|
-- The grouping radius should not be too small, but also depends on the types of planes and the era of the simulation.
|
||||||
-- Fast planes like in the 80s, need a larger radius than WWII planes.
|
-- Fast planes like in the 80s, need a larger radius than WWII planes.
|
||||||
-- Typically I suggest to use 30000 for new generation planes and 10000 for older era aircraft.
|
-- Typically I suggest to use 30000 for new generation planes and 10000 for older era aircraft.
|
||||||
--
|
--
|
||||||
-- Note that detected targets are constantly re-grouped, that is, when certain detected aircraft are moving further than the group radius, then these aircraft will become a separate
|
-- Note that detected targets are constantly re-grouped, that is, when certain detected aircraft are moving further than the group radius, then these aircraft will become a separate
|
||||||
-- group being detected. This may result in additional GCI being started by the dispatcher! So don't make this value too small!
|
-- group being detected. This may result in additional GCI being started by the dispatcher! So don't make this value too small!
|
||||||
--
|
--
|
||||||
-- ## 3. Set the **Engage radius**:
|
-- ## 3. Set the **Engage radius**:
|
||||||
--
|
--
|
||||||
-- Define the radius to engage any target by airborne friendlies, which are executing cap or returning from an intercept mission.
|
-- Define the radius to engage any target by airborne friendlies, which are executing cap or returning from an intercept mission.
|
||||||
--
|
--
|
||||||
-- 
|
-- 
|
||||||
--
|
--
|
||||||
-- So, if there is a target area detected and reported,
|
-- So, if there is a target area detected and reported,
|
||||||
-- then any friendlies that are airborne near this target area,
|
-- then any friendlies that are airborne near this target area,
|
||||||
-- will be commanded to (re-)engage that target when available (if no other tasks were commanded).
|
-- will be commanded to (re-)engage that target when available (if no other tasks were commanded).
|
||||||
-- For example, if 100000 is given as a value, then any friendly that is airborne within 100km from the detected target,
|
-- For example, if 100000 is given as a value, then any friendly that is airborne within 100km from the detected target,
|
||||||
-- will be considered to receive the command to engage that target area.
|
-- will be considered to receive the command to engage that target area.
|
||||||
-- You need to evaluate the value of this parameter carefully.
|
-- You need to evaluate the value of this parameter carefully.
|
||||||
-- If too small, more intercept missions may be triggered upon detected target areas.
|
-- If too small, more intercept missions may be triggered upon detected target areas.
|
||||||
-- If too large, any airborne cap may not be able to reach the detected target area in time, because it is too far.
|
-- If too large, any airborne cap may not be able to reach the detected target area in time, because it is too far.
|
||||||
--
|
--
|
||||||
-- ## 4. Set **Scoring** and **Messages**:
|
-- ## 4. Set **Scoring** and **Messages**:
|
||||||
--
|
--
|
||||||
-- The TASK\_A2A\_DISPATCHER is a state machine. It triggers the event Assign when a new player joins a @{Task} dispatched by the TASK\_A2A\_DISPATCHER.
|
-- The TASK\_A2A\_DISPATCHER is a state machine. It triggers the event Assign when a new player joins a @{Task} dispatched by the TASK\_A2A\_DISPATCHER.
|
||||||
-- An _event handler_ can be defined to catch the **Assign** event, and add **additional processing** to set _scoring_ and to _define messages_,
|
-- An _event handler_ can be defined to catch the **Assign** event, and add **additional processing** to set _scoring_ and to _define messages_,
|
||||||
-- when the player reaches certain achievements in the task.
|
-- when the player reaches certain achievements in the task.
|
||||||
--
|
--
|
||||||
-- The prototype to handle the **Assign** event needs to be developed as follows:
|
-- The prototype to handle the **Assign** event needs to be developed as follows:
|
||||||
--
|
--
|
||||||
-- TaskDispatcher = TASK_A2A_DISPATCHER:New( ... )
|
-- TaskDispatcher = TASK_A2A_DISPATCHER:New( ... )
|
||||||
--
|
--
|
||||||
-- --- @param #TaskDispatcher self
|
-- --- @param #TaskDispatcher self
|
||||||
-- -- @param #string From Contains the name of the state from where the Event was triggered.
|
-- -- @param #string From Contains the name of the state from where the Event was triggered.
|
||||||
-- -- @param #string Event Contains the name of the event that was triggered. In this case Assign.
|
-- -- @param #string Event Contains the name of the event that was triggered. In this case Assign.
|
||||||
@@ -160,22 +160,22 @@ do -- TASK_A2A_DISPATCHER
|
|||||||
-- Task:SetScoreOnSuccess( PlayerName, 200, TaskUnit )
|
-- Task:SetScoreOnSuccess( PlayerName, 200, TaskUnit )
|
||||||
-- Task:SetScoreOnFail( PlayerName, -100, TaskUnit )
|
-- Task:SetScoreOnFail( PlayerName, -100, TaskUnit )
|
||||||
-- end
|
-- end
|
||||||
--
|
--
|
||||||
-- The **OnAfterAssign** method (function) is added to the TaskDispatcher object.
|
-- The **OnAfterAssign** method (function) is added to the TaskDispatcher object.
|
||||||
-- This method will be called when a new player joins a unit in the set of groups in scope of the dispatcher.
|
-- This method will be called when a new player joins a unit in the set of groups in scope of the dispatcher.
|
||||||
-- So, this method will be called only **ONCE** when a player joins a unit in scope of the task.
|
-- So, this method will be called only **ONCE** when a player joins a unit in scope of the task.
|
||||||
--
|
--
|
||||||
-- The TASK class implements various methods to additional **set scoring** for player achievements:
|
-- The TASK class implements various methods to additional **set scoring** for player achievements:
|
||||||
--
|
--
|
||||||
-- * @{Tasking.Task#TASK.SetScoreOnProgress}() will add additional scores when a player achieves **Progress** while executing the task.
|
-- * @{Tasking.Task#TASK.SetScoreOnProgress}() will add additional scores when a player achieves **Progress** while executing the task.
|
||||||
-- Examples of **task progress** can be destroying units, arriving at zones etc.
|
-- Examples of **task progress** can be destroying units, arriving at zones etc.
|
||||||
--
|
--
|
||||||
-- * @{Tasking.Task#TASK.SetScoreOnSuccess}() will add additional scores when the task goes into **Success** state.
|
-- * @{Tasking.Task#TASK.SetScoreOnSuccess}() will add additional scores when the task goes into **Success** state.
|
||||||
-- This means the **task has been successfully completed**.
|
-- This means the **task has been successfully completed**.
|
||||||
--
|
--
|
||||||
-- * @{Tasking.Task#TASK.SetScoreOnSuccess}() will add additional (negative) scores when the task goes into **Failed** state.
|
-- * @{Tasking.Task#TASK.SetScoreOnSuccess}() will add additional (negative) scores when the task goes into **Failed** state.
|
||||||
-- This means the **task has not been successfully completed**, and the scores must be given with a negative value!
|
-- This means the **task has not been successfully completed**, and the scores must be given with a negative value!
|
||||||
--
|
--
|
||||||
-- @field #TASK_A2A_DISPATCHER
|
-- @field #TASK_A2A_DISPATCHER
|
||||||
TASK_A2A_DISPATCHER = {
|
TASK_A2A_DISPATCHER = {
|
||||||
ClassName = "TASK_A2A_DISPATCHER",
|
ClassName = "TASK_A2A_DISPATCHER",
|
||||||
@@ -184,8 +184,7 @@ do -- TASK_A2A_DISPATCHER
|
|||||||
Tasks = {},
|
Tasks = {},
|
||||||
SweepZones = {},
|
SweepZones = {},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
--- TASK_A2A_DISPATCHER constructor.
|
--- TASK_A2A_DISPATCHER constructor.
|
||||||
-- @param #TASK_A2A_DISPATCHER self
|
-- @param #TASK_A2A_DISPATCHER self
|
||||||
-- @param Tasking.Mission#MISSION Mission The mission for which the task dispatching is done.
|
-- @param Tasking.Mission#MISSION Mission The mission for which the task dispatching is done.
|
||||||
@@ -193,22 +192,21 @@ do -- TASK_A2A_DISPATCHER
|
|||||||
-- @param Functional.Detection#DETECTION_BASE Detection The detection results that are used to dynamically assign new tasks to human players.
|
-- @param Functional.Detection#DETECTION_BASE Detection The detection results that are used to dynamically assign new tasks to human players.
|
||||||
-- @return #TASK_A2A_DISPATCHER self
|
-- @return #TASK_A2A_DISPATCHER self
|
||||||
function TASK_A2A_DISPATCHER:New( Mission, SetGroup, Detection )
|
function TASK_A2A_DISPATCHER:New( Mission, SetGroup, Detection )
|
||||||
|
|
||||||
-- Inherits from DETECTION_MANAGER
|
-- Inherits from DETECTION_MANAGER
|
||||||
local self = BASE:Inherit( self, DETECTION_MANAGER:New( SetGroup, Detection ) ) -- #TASK_A2A_DISPATCHER
|
local self = BASE:Inherit( self, DETECTION_MANAGER:New( SetGroup, Detection ) ) -- #TASK_A2A_DISPATCHER
|
||||||
|
|
||||||
self.Detection = Detection
|
self.Detection = Detection
|
||||||
self.Mission = Mission
|
self.Mission = Mission
|
||||||
self.FlashNewTask = false
|
self.FlashNewTask = false
|
||||||
|
|
||||||
-- TODO: Check detection through radar.
|
-- TODO: Check detection through radar.
|
||||||
self.Detection:FilterCategories( Unit.Category.AIRPLANE, Unit.Category.HELICOPTER )
|
self.Detection:FilterCategories( Unit.Category.AIRPLANE, Unit.Category.HELICOPTER )
|
||||||
self.Detection:InitDetectRadar( true )
|
self.Detection:InitDetectRadar( true )
|
||||||
self.Detection:SetRefreshTimeInterval( 30 )
|
self.Detection:SetRefreshTimeInterval( 30 )
|
||||||
|
|
||||||
self:AddTransition( "Started", "Assign", "Started" )
|
self:AddTransition( "Started", "Assign", "Started" )
|
||||||
|
|
||||||
|
|
||||||
--- OnAfter Transition Handler for Event Assign.
|
--- OnAfter Transition Handler for Event Assign.
|
||||||
-- @function [parent=#TASK_A2A_DISPATCHER] OnAfterAssign
|
-- @function [parent=#TASK_A2A_DISPATCHER] OnAfterAssign
|
||||||
-- @param #TASK_A2A_DISPATCHER self
|
-- @param #TASK_A2A_DISPATCHER self
|
||||||
@@ -220,14 +218,13 @@ do -- TASK_A2A_DISPATCHER
|
|||||||
-- @param #string PlayerName
|
-- @param #string PlayerName
|
||||||
|
|
||||||
self:__Start( 5 )
|
self:__Start( 5 )
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Define the radius to when an ENGAGE task will be generated for any nearby by airborne friendlies, which are executing cap or returning from an intercept mission.
|
--- Define the radius to when an ENGAGE task will be generated for any nearby by airborne friendlies, which are executing cap or returning from an intercept mission.
|
||||||
-- So, if there is a target area detected and reported,
|
-- So, if there is a target area detected and reported,
|
||||||
-- then any friendlies that are airborne near this target area,
|
-- then any friendlies that are airborne near this target area,
|
||||||
-- will be commanded to (re-)engage that target when available (if no other tasks were commanded).
|
-- will be commanded to (re-)engage that target when available (if no other tasks were commanded).
|
||||||
-- An ENGAGE task will be created for those pilots.
|
-- An ENGAGE task will be created for those pilots.
|
||||||
-- For example, if 100000 is given as a value, then any friendly that is airborne within 100km from the detected target,
|
-- For example, if 100000 is given as a value, then any friendly that is airborne within 100km from the detected target,
|
||||||
@@ -239,27 +236,27 @@ do -- TASK_A2A_DISPATCHER
|
|||||||
-- @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.
|
||||||
-- @return #TASK_A2A_DISPATCHER
|
-- @return #TASK_A2A_DISPATCHER
|
||||||
-- @usage
|
-- @usage
|
||||||
--
|
--
|
||||||
-- -- Set 50km as the radius to engage any target by airborne friendlies.
|
-- -- Set 50km as the radius to engage any target by airborne friendlies.
|
||||||
-- TaskA2ADispatcher:SetEngageRadius( 50000 )
|
-- TaskA2ADispatcher:SetEngageRadius( 50000 )
|
||||||
--
|
--
|
||||||
-- -- Set 100km as the radius to engage any target by airborne friendlies.
|
-- -- Set 100km as the radius to engage any target by airborne friendlies.
|
||||||
-- TaskA2ADispatcher:SetEngageRadius() -- 100000 is the default value.
|
-- TaskA2ADispatcher:SetEngageRadius() -- 100000 is the default value.
|
||||||
--
|
--
|
||||||
function TASK_A2A_DISPATCHER:SetEngageRadius( EngageRadius )
|
function TASK_A2A_DISPATCHER:SetEngageRadius( EngageRadius )
|
||||||
|
|
||||||
self.Detection:SetFriendliesRange( EngageRadius or 100000 )
|
self.Detection:SetFriendliesRange( EngageRadius or 100000 )
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Set flashing player messages on or off
|
--- Set flashing player messages on or off
|
||||||
-- @param #TASK_A2A_DISPATCHER self
|
-- @param #TASK_A2A_DISPATCHER self
|
||||||
-- @param #boolean onoff Set messages on (true) or off (false)
|
-- @param #boolean onoff Set messages on (true) or off (false)
|
||||||
function TASK_A2A_DISPATCHER:SetSendMessages( onoff )
|
function TASK_A2A_DISPATCHER:SetSendMessages( onoff )
|
||||||
self.FlashNewTask = onoff
|
self.FlashNewTask = onoff
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Creates an INTERCEPT task when there are targets for it.
|
--- Creates an INTERCEPT task when there are targets for it.
|
||||||
-- @param #TASK_A2A_DISPATCHER self
|
-- @param #TASK_A2A_DISPATCHER self
|
||||||
-- @param Functional.Detection#DETECTION_BASE.DetectedItem DetectedItem
|
-- @param Functional.Detection#DETECTION_BASE.DetectedItem DetectedItem
|
||||||
@@ -267,26 +264,25 @@ do -- TASK_A2A_DISPATCHER
|
|||||||
-- @return #nil If there are no targets to be set.
|
-- @return #nil If there are no targets to be set.
|
||||||
function TASK_A2A_DISPATCHER:EvaluateINTERCEPT( DetectedItem )
|
function TASK_A2A_DISPATCHER:EvaluateINTERCEPT( DetectedItem )
|
||||||
self:F( { DetectedItem.ItemID } )
|
self:F( { DetectedItem.ItemID } )
|
||||||
|
|
||||||
local DetectedSet = DetectedItem.Set
|
local DetectedSet = DetectedItem.Set
|
||||||
local DetectedZone = DetectedItem.Zone
|
local DetectedZone = DetectedItem.Zone
|
||||||
|
|
||||||
-- Check if there is at least one UNIT in the DetectedSet is visible.
|
-- Check if there is at least one UNIT in the DetectedSet is visible.
|
||||||
|
|
||||||
if DetectedItem.IsDetected == true then
|
if DetectedItem.IsDetected == true then
|
||||||
|
|
||||||
-- Here we're doing something advanced... We're copying the DetectedSet.
|
-- Here we're doing something advanced... We're copying the DetectedSet.
|
||||||
local TargetSetUnit = SET_UNIT:New()
|
local TargetSetUnit = SET_UNIT:New()
|
||||||
TargetSetUnit:SetDatabase( DetectedSet )
|
TargetSetUnit:SetDatabase( DetectedSet )
|
||||||
TargetSetUnit:FilterOnce() -- Filter but don't do any events!!! Elements are added manually upon each detection.
|
TargetSetUnit:FilterOnce() -- Filter but don't do any events!!! Elements are added manually upon each detection.
|
||||||
|
|
||||||
return TargetSetUnit
|
return TargetSetUnit
|
||||||
end
|
end
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Creates an SWEEP task when there are targets for it.
|
--- Creates an SWEEP task when there are targets for it.
|
||||||
-- @param #TASK_A2A_DISPATCHER self
|
-- @param #TASK_A2A_DISPATCHER self
|
||||||
-- @param Functional.Detection#DETECTION_BASE.DetectedItem DetectedItem
|
-- @param Functional.Detection#DETECTION_BASE.DetectedItem DetectedItem
|
||||||
@@ -294,10 +290,9 @@ do -- TASK_A2A_DISPATCHER
|
|||||||
-- @return #nil If there are no targets to be set.
|
-- @return #nil If there are no targets to be set.
|
||||||
function TASK_A2A_DISPATCHER:EvaluateSWEEP( DetectedItem )
|
function TASK_A2A_DISPATCHER:EvaluateSWEEP( DetectedItem )
|
||||||
self:F( { DetectedItem.ItemID } )
|
self:F( { DetectedItem.ItemID } )
|
||||||
|
|
||||||
local DetectedSet = DetectedItem.Set
|
|
||||||
local DetectedZone = DetectedItem.Zone
|
|
||||||
|
|
||||||
|
local DetectedSet = DetectedItem.Set
|
||||||
|
local DetectedZone = DetectedItem.Zone -- TODO: This seems unused, remove?
|
||||||
|
|
||||||
if DetectedItem.IsDetected == false then
|
if DetectedItem.IsDetected == false then
|
||||||
|
|
||||||
@@ -305,14 +300,13 @@ do -- TASK_A2A_DISPATCHER
|
|||||||
local TargetSetUnit = SET_UNIT:New()
|
local TargetSetUnit = SET_UNIT:New()
|
||||||
TargetSetUnit:SetDatabase( DetectedSet )
|
TargetSetUnit:SetDatabase( DetectedSet )
|
||||||
TargetSetUnit:FilterOnce() -- Filter but don't do any events!!! Elements are added manually upon each detection.
|
TargetSetUnit:FilterOnce() -- Filter but don't do any events!!! Elements are added manually upon each detection.
|
||||||
|
|
||||||
return TargetSetUnit
|
return TargetSetUnit
|
||||||
end
|
end
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Creates an ENGAGE task when there are human friendlies airborne near the targets.
|
--- Creates an ENGAGE task when there are human friendlies airborne near the targets.
|
||||||
-- @param #TASK_A2A_DISPATCHER self
|
-- @param #TASK_A2A_DISPATCHER self
|
||||||
-- @param Functional.Detection#DETECTION_BASE.DetectedItem DetectedItem
|
-- @param Functional.Detection#DETECTION_BASE.DetectedItem DetectedItem
|
||||||
@@ -320,13 +314,12 @@ do -- TASK_A2A_DISPATCHER
|
|||||||
-- @return #nil If there are no targets to be set.
|
-- @return #nil If there are no targets to be set.
|
||||||
function TASK_A2A_DISPATCHER:EvaluateENGAGE( DetectedItem )
|
function TASK_A2A_DISPATCHER:EvaluateENGAGE( DetectedItem )
|
||||||
self:F( { DetectedItem.ItemID } )
|
self:F( { DetectedItem.ItemID } )
|
||||||
|
|
||||||
local DetectedSet = DetectedItem.Set
|
local DetectedSet = DetectedItem.Set
|
||||||
local DetectedZone = DetectedItem.Zone
|
local DetectedZone = DetectedItem.Zone -- TODO: This seems unused, remove?
|
||||||
|
|
||||||
local PlayersCount, PlayersReport = self:GetPlayerFriendliesNearBy( DetectedItem )
|
local PlayersCount, PlayersReport = self:GetPlayerFriendliesNearBy( DetectedItem )
|
||||||
|
|
||||||
|
|
||||||
-- Only allow ENGAGE when there are Players near the zone, and when the Area has detected items since the last run in a 60 seconds time zone.
|
-- Only allow ENGAGE when there are Players near the zone, and when the Area has detected items since the last run in a 60 seconds time zone.
|
||||||
if PlayersCount > 0 and DetectedItem.IsDetected == true then
|
if PlayersCount > 0 and DetectedItem.IsDetected == true then
|
||||||
|
|
||||||
@@ -334,16 +327,13 @@ do -- TASK_A2A_DISPATCHER
|
|||||||
local TargetSetUnit = SET_UNIT:New()
|
local TargetSetUnit = SET_UNIT:New()
|
||||||
TargetSetUnit:SetDatabase( DetectedSet )
|
TargetSetUnit:SetDatabase( DetectedSet )
|
||||||
TargetSetUnit:FilterOnce() -- Filter but don't do any events!!! Elements are added manually upon each detection.
|
TargetSetUnit:FilterOnce() -- Filter but don't do any events!!! Elements are added manually upon each detection.
|
||||||
|
|
||||||
return TargetSetUnit
|
return TargetSetUnit
|
||||||
end
|
end
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--- Evaluates the removal of the Task from the Mission.
|
--- Evaluates the removal of the Task from the Mission.
|
||||||
-- Can only occur when the DetectedItem is Changed AND the state of the Task is "Planned".
|
-- Can only occur when the DetectedItem is Changed AND the state of the Task is "Planned".
|
||||||
-- @param #TASK_A2A_DISPATCHER self
|
-- @param #TASK_A2A_DISPATCHER self
|
||||||
@@ -354,24 +344,24 @@ do -- TASK_A2A_DISPATCHER
|
|||||||
-- @param #boolean DetectedItemChange
|
-- @param #boolean DetectedItemChange
|
||||||
-- @return Tasking.Task#TASK
|
-- @return Tasking.Task#TASK
|
||||||
function TASK_A2A_DISPATCHER:EvaluateRemoveTask( Mission, Task, Detection, DetectedItem, DetectedItemIndex, DetectedItemChanged )
|
function TASK_A2A_DISPATCHER:EvaluateRemoveTask( Mission, Task, Detection, DetectedItem, DetectedItemIndex, DetectedItemChanged )
|
||||||
|
|
||||||
if Task then
|
if Task then
|
||||||
|
|
||||||
if Task:IsStatePlanned() then
|
if Task:IsStatePlanned() then
|
||||||
local TaskName = Task:GetName()
|
local TaskName = Task:GetName()
|
||||||
local TaskType = TaskName:match( "(%u+)%.%d+" )
|
local TaskType = TaskName:match( "(%u+)%.%d+" )
|
||||||
|
|
||||||
self:T2( { TaskType = TaskType } )
|
self:T2( { TaskType = TaskType } )
|
||||||
|
|
||||||
local Remove = false
|
local Remove = false
|
||||||
|
|
||||||
local IsPlayers = Detection:IsPlayersNearBy( DetectedItem )
|
local IsPlayers = Detection:IsPlayersNearBy( DetectedItem )
|
||||||
if TaskType == "ENGAGE" then
|
if TaskType == "ENGAGE" then
|
||||||
if IsPlayers == false then
|
if IsPlayers == false then
|
||||||
Remove = true
|
Remove = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if TaskType == "INTERCEPT" then
|
if TaskType == "INTERCEPT" then
|
||||||
if IsPlayers == true then
|
if IsPlayers == true then
|
||||||
Remove = true
|
Remove = true
|
||||||
@@ -380,7 +370,7 @@ do -- TASK_A2A_DISPATCHER
|
|||||||
Remove = true
|
Remove = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if TaskType == "SWEEP" then
|
if TaskType == "SWEEP" then
|
||||||
if DetectedItem.IsDetected == true then
|
if DetectedItem.IsDetected == true then
|
||||||
Remove = true
|
Remove = true
|
||||||
@@ -388,18 +378,18 @@ do -- TASK_A2A_DISPATCHER
|
|||||||
end
|
end
|
||||||
|
|
||||||
local DetectedSet = DetectedItem.Set -- Core.Set#SET_UNIT
|
local DetectedSet = DetectedItem.Set -- Core.Set#SET_UNIT
|
||||||
--DetectedSet:Flush( self )
|
-- DetectedSet:Flush( self )
|
||||||
--self:F( { DetectedSetCount = DetectedSet:Count() } )
|
-- self:F( { DetectedSetCount = DetectedSet:Count() } )
|
||||||
if DetectedSet:Count() == 0 then
|
if DetectedSet:Count() == 0 then
|
||||||
Remove = true
|
Remove = true
|
||||||
end
|
end
|
||||||
|
|
||||||
if DetectedItemChanged == true or Remove then
|
if DetectedItemChanged == true or Remove then
|
||||||
Task = self:RemoveTask( DetectedItemIndex )
|
Task = self:RemoveTask( DetectedItemIndex )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return Task
|
return Task
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -408,10 +398,10 @@ do -- TASK_A2A_DISPATCHER
|
|||||||
-- @param DetectedItem
|
-- @param DetectedItem
|
||||||
-- @return #number, Core.CommandCenter#REPORT
|
-- @return #number, Core.CommandCenter#REPORT
|
||||||
function TASK_A2A_DISPATCHER:GetFriendliesNearBy( DetectedItem )
|
function TASK_A2A_DISPATCHER:GetFriendliesNearBy( DetectedItem )
|
||||||
|
|
||||||
local DetectedSet = DetectedItem.Set
|
local DetectedSet = DetectedItem.Set
|
||||||
local FriendlyUnitsNearBy = self.Detection:GetFriendliesNearBy( DetectedItem, Unit.Category.AIRPLANE )
|
local FriendlyUnitsNearBy = self.Detection:GetFriendliesNearBy( DetectedItem, Unit.Category.AIRPLANE )
|
||||||
|
|
||||||
local FriendlyTypes = {}
|
local FriendlyTypes = {}
|
||||||
local FriendliesCount = 0
|
local FriendliesCount = 0
|
||||||
|
|
||||||
@@ -423,27 +413,26 @@ do -- TASK_A2A_DISPATCHER
|
|||||||
local FriendlyUnitThreatLevel = FriendlyUnit:GetThreatLevel()
|
local FriendlyUnitThreatLevel = FriendlyUnit:GetThreatLevel()
|
||||||
FriendliesCount = FriendliesCount + 1
|
FriendliesCount = FriendliesCount + 1
|
||||||
local FriendlyType = FriendlyUnit:GetTypeName()
|
local FriendlyType = FriendlyUnit:GetTypeName()
|
||||||
FriendlyTypes[FriendlyType] = FriendlyTypes[FriendlyType] and ( FriendlyTypes[FriendlyType] + 1 ) or 1
|
FriendlyTypes[FriendlyType] = FriendlyTypes[FriendlyType] and (FriendlyTypes[FriendlyType] + 1) or 1
|
||||||
if DetectedTreatLevel < FriendlyUnitThreatLevel + 2 then
|
if DetectedTreatLevel < FriendlyUnitThreatLevel + 2 then
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--self:F( { FriendliesCount = FriendliesCount } )
|
-- self:F( { FriendliesCount = FriendliesCount } )
|
||||||
|
|
||||||
local FriendlyTypesReport = REPORT:New()
|
local FriendlyTypesReport = REPORT:New()
|
||||||
|
|
||||||
if FriendliesCount > 0 then
|
if FriendliesCount > 0 then
|
||||||
for FriendlyType, FriendlyTypeCount in pairs( FriendlyTypes ) do
|
for FriendlyType, FriendlyTypeCount in pairs( FriendlyTypes ) do
|
||||||
FriendlyTypesReport:Add( string.format("%d of %s", FriendlyTypeCount, FriendlyType ) )
|
FriendlyTypesReport:Add( string.format( "%d of %s", FriendlyTypeCount, FriendlyType ) )
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
FriendlyTypesReport:Add( "-" )
|
FriendlyTypesReport:Add( "-" )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
return FriendliesCount, FriendlyTypesReport
|
return FriendliesCount, FriendlyTypesReport
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -452,10 +441,10 @@ do -- TASK_A2A_DISPATCHER
|
|||||||
-- @param DetectedItem
|
-- @param DetectedItem
|
||||||
-- @return #number, Core.CommandCenter#REPORT
|
-- @return #number, Core.CommandCenter#REPORT
|
||||||
function TASK_A2A_DISPATCHER:GetPlayerFriendliesNearBy( DetectedItem )
|
function TASK_A2A_DISPATCHER:GetPlayerFriendliesNearBy( DetectedItem )
|
||||||
|
|
||||||
local DetectedSet = DetectedItem.Set
|
local DetectedSet = DetectedItem.Set
|
||||||
local PlayersNearBy = self.Detection:GetPlayersNearBy( DetectedItem )
|
local PlayersNearBy = self.Detection:GetPlayersNearBy( DetectedItem )
|
||||||
|
|
||||||
local PlayerTypes = {}
|
local PlayerTypes = {}
|
||||||
local PlayersCount = 0
|
local PlayersCount = 0
|
||||||
|
|
||||||
@@ -464,7 +453,7 @@ do -- TASK_A2A_DISPATCHER
|
|||||||
for PlayerUnitName, PlayerUnitData in pairs( PlayersNearBy ) do
|
for PlayerUnitName, PlayerUnitData in pairs( PlayersNearBy ) do
|
||||||
local PlayerUnit = PlayerUnitData -- Wrapper.Unit#UNIT
|
local PlayerUnit = PlayerUnitData -- Wrapper.Unit#UNIT
|
||||||
local PlayerName = PlayerUnit:GetPlayerName()
|
local PlayerName = PlayerUnit:GetPlayerName()
|
||||||
--self:F( { PlayerName = PlayerName, PlayerUnit = PlayerUnit } )
|
-- self:F( { PlayerName = PlayerName, PlayerUnit = PlayerUnit } )
|
||||||
if PlayerUnit:IsAirPlane() and PlayerName ~= nil then
|
if PlayerUnit:IsAirPlane() and PlayerName ~= nil then
|
||||||
local FriendlyUnitThreatLevel = PlayerUnit:GetThreatLevel()
|
local FriendlyUnitThreatLevel = PlayerUnit:GetThreatLevel()
|
||||||
PlayersCount = PlayersCount + 1
|
PlayersCount = PlayersCount + 1
|
||||||
@@ -474,20 +463,19 @@ do -- TASK_A2A_DISPATCHER
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local PlayerTypesReport = REPORT:New()
|
local PlayerTypesReport = REPORT:New()
|
||||||
|
|
||||||
if PlayersCount > 0 then
|
if PlayersCount > 0 then
|
||||||
for PlayerName, PlayerType in pairs( PlayerTypes ) do
|
for PlayerName, PlayerType in pairs( PlayerTypes ) do
|
||||||
PlayerTypesReport:Add( string.format('"%s" in %s', PlayerName, PlayerType ) )
|
PlayerTypesReport:Add( string.format( '"%s" in %s', PlayerName, PlayerType ) )
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
PlayerTypesReport:Add( "-" )
|
PlayerTypesReport:Add( "-" )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
return PlayersCount, PlayerTypesReport
|
return PlayersCount, PlayerTypesReport
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -496,24 +484,23 @@ do -- TASK_A2A_DISPATCHER
|
|||||||
self.Tasks[TaskIndex] = nil
|
self.Tasks[TaskIndex] = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Assigns tasks in relation to the detected items to the @{Core.Set#SET_GROUP}.
|
--- Assigns tasks in relation to the detected items to the @{Core.Set#SET_GROUP}.
|
||||||
-- @param #TASK_A2A_DISPATCHER self
|
-- @param #TASK_A2A_DISPATCHER self
|
||||||
-- @param Functional.Detection#DETECTION_BASE Detection The detection created by the @{Functional.Detection#DETECTION_BASE} derived object.
|
-- @param Functional.Detection#DETECTION_BASE Detection The detection created by the @{Functional.Detection#DETECTION_BASE} derived object.
|
||||||
-- @return #boolean Return true if you want the task assigning to continue... false will cancel the loop.
|
-- @return #boolean Return true if you want the task assigning to continue... false will cancel the loop.
|
||||||
function TASK_A2A_DISPATCHER:ProcessDetected( Detection )
|
function TASK_A2A_DISPATCHER:ProcessDetected( Detection )
|
||||||
self:F()
|
self:F()
|
||||||
|
|
||||||
local AreaMsg = {}
|
local AreaMsg = {}
|
||||||
local TaskMsg = {}
|
local TaskMsg = {}
|
||||||
local ChangeMsg = {}
|
local ChangeMsg = {}
|
||||||
|
|
||||||
local Mission = self.Mission
|
local Mission = self.Mission
|
||||||
|
|
||||||
if Mission:IsIDLE() or Mission:IsENGAGED() then
|
if Mission:IsIDLE() or Mission:IsENGAGED() then
|
||||||
|
|
||||||
local TaskReport = REPORT:New()
|
local TaskReport = REPORT:New()
|
||||||
|
|
||||||
-- Checking the task queue for the dispatcher, and removing any obsolete task!
|
-- Checking the task queue for the dispatcher, and removing any obsolete task!
|
||||||
for TaskIndex, TaskData in pairs( self.Tasks ) do
|
for TaskIndex, TaskData in pairs( self.Tasks ) do
|
||||||
local Task = TaskData -- Tasking.Task#TASK
|
local Task = TaskData -- Tasking.Task#TASK
|
||||||
@@ -531,18 +518,18 @@ do -- TASK_A2A_DISPATCHER
|
|||||||
|
|
||||||
-- Now that all obsolete tasks are removed, loop through the detected targets.
|
-- Now that all obsolete tasks are removed, loop through the detected targets.
|
||||||
for DetectedItemID, DetectedItem in pairs( Detection:GetDetectedItems() ) do
|
for DetectedItemID, DetectedItem in pairs( Detection:GetDetectedItems() ) do
|
||||||
|
|
||||||
local DetectedItem = DetectedItem -- Functional.Detection#DETECTION_BASE.DetectedItem
|
local DetectedItem = DetectedItem -- Functional.Detection#DETECTION_BASE.DetectedItem
|
||||||
local DetectedSet = DetectedItem.Set -- Core.Set#SET_UNIT
|
local DetectedSet = DetectedItem.Set -- Core.Set#SET_UNIT
|
||||||
local DetectedCount = DetectedSet:Count()
|
local DetectedCount = DetectedSet:Count()
|
||||||
local DetectedZone = DetectedItem.Zone
|
local DetectedZone = DetectedItem.Zone
|
||||||
--self:F( { "Targets in DetectedItem", DetectedItem.ItemID, DetectedSet:Count(), tostring( DetectedItem ) } )
|
-- self:F( { "Targets in DetectedItem", DetectedItem.ItemID, DetectedSet:Count(), tostring( DetectedItem ) } )
|
||||||
--DetectedSet:Flush( self )
|
-- DetectedSet:Flush( self )
|
||||||
|
|
||||||
local DetectedID = DetectedItem.ID
|
local DetectedID = DetectedItem.ID
|
||||||
local TaskIndex = DetectedItem.Index
|
local TaskIndex = DetectedItem.Index
|
||||||
local DetectedItemChanged = DetectedItem.Changed
|
local DetectedItemChanged = DetectedItem.Changed
|
||||||
|
|
||||||
local Task = self.Tasks[TaskIndex]
|
local Task = self.Tasks[TaskIndex]
|
||||||
Task = self:EvaluateRemoveTask( Mission, Task, Detection, DetectedItem, TaskIndex, DetectedItemChanged ) -- Task will be removed if it is planned and changed.
|
Task = self:EvaluateRemoveTask( Mission, Task, Detection, DetectedItem, TaskIndex, DetectedItemChanged ) -- Task will be removed if it is planned and changed.
|
||||||
|
|
||||||
@@ -565,7 +552,7 @@ do -- TASK_A2A_DISPATCHER
|
|||||||
Task = TASK_A2A_SWEEP:New( Mission, self.SetGroup, string.format( "SWEEP.%03d", DetectedID ), TargetSetUnit )
|
Task = TASK_A2A_SWEEP:New( Mission, self.SetGroup, string.format( "SWEEP.%03d", DetectedID ), TargetSetUnit )
|
||||||
Task:SetDetection( Detection, DetectedItem )
|
Task:SetDetection( Detection, DetectedItem )
|
||||||
Task:UpdateTaskInfo( DetectedItem )
|
Task:UpdateTaskInfo( DetectedItem )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -582,7 +569,7 @@ do -- TASK_A2A_DISPATCHER
|
|||||||
function Task.OnEnterCancelled( Task, From, Event, To )
|
function Task.OnEnterCancelled( Task, From, Event, To )
|
||||||
self:Cancelled( Task )
|
self:Cancelled( Task )
|
||||||
end
|
end
|
||||||
|
|
||||||
function Task.OnEnterFailed( Task, From, Event, To )
|
function Task.OnEnterFailed( Task, From, Event, To )
|
||||||
self:Failed( Task )
|
self:Failed( Task )
|
||||||
end
|
end
|
||||||
@@ -590,38 +577,38 @@ do -- TASK_A2A_DISPATCHER
|
|||||||
function Task.OnEnterAborted( Task, From, Event, To )
|
function Task.OnEnterAborted( Task, From, Event, To )
|
||||||
self:Aborted( Task )
|
self:Aborted( Task )
|
||||||
end
|
end
|
||||||
|
|
||||||
TaskReport:Add( Task:GetName() )
|
TaskReport:Add( Task:GetName() )
|
||||||
else
|
else
|
||||||
self:F("This should not happen")
|
self:F( "This should not happen" )
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if Task then
|
if Task then
|
||||||
local FriendliesCount, FriendliesReport = self:GetFriendliesNearBy( DetectedItem, Unit.Category.AIRPLANE )
|
local FriendliesCount, FriendliesReport = self:GetFriendliesNearBy( DetectedItem, Unit.Category.AIRPLANE )
|
||||||
Task.TaskInfo:AddText( "Friendlies", string.format( "%d ( %s )", FriendliesCount, FriendliesReport:Text( "," ) ), 40, "MOD" )
|
Task.TaskInfo:AddText( "Friendlies", string.format( "%d ( %s )", FriendliesCount, FriendliesReport:Text( "," ) ), 40, "MOD" )
|
||||||
local PlayersCount, PlayersReport = self:GetPlayerFriendliesNearBy( DetectedItem )
|
local PlayersCount, PlayersReport = self:GetPlayerFriendliesNearBy( DetectedItem )
|
||||||
Task.TaskInfo:AddText( "Players", string.format( "%d ( %s )", PlayersCount, PlayersReport:Text( "," ) ), 40, "MOD" )
|
Task.TaskInfo:AddText( "Players", string.format( "%d ( %s )", PlayersCount, PlayersReport:Text( "," ) ), 40, "MOD" )
|
||||||
end
|
end
|
||||||
|
|
||||||
-- OK, so the tasking has been done, now delete the changes reported for the area.
|
-- OK, so the tasking has been done, now delete the changes reported for the area.
|
||||||
Detection:AcceptChanges( DetectedItem )
|
Detection:AcceptChanges( DetectedItem )
|
||||||
end
|
end
|
||||||
|
|
||||||
-- TODO set menus using the HQ coordinator
|
-- TODO set menus using the HQ coordinator
|
||||||
Mission:GetCommandCenter():SetMenu()
|
Mission:GetCommandCenter():SetMenu()
|
||||||
|
|
||||||
local TaskText = TaskReport:Text(", ")
|
local TaskText = TaskReport:Text( ", " )
|
||||||
|
|
||||||
for TaskGroupID, TaskGroup in pairs( self.SetGroup:GetSet() ) do
|
for TaskGroupID, TaskGroup in pairs( self.SetGroup:GetSet() ) do
|
||||||
if ( not Mission:IsGroupAssigned(TaskGroup) ) and TaskText ~= "" and (self.FlashNewTask) then
|
if (not Mission:IsGroupAssigned( TaskGroup )) and TaskText ~= "" and (self.FlashNewTask) then
|
||||||
Mission:GetCommandCenter():MessageToGroup( string.format( "%s has tasks %s. Subscribe to a task using the radio menu.", Mission:GetShortText(), TaskText ), TaskGroup )
|
Mission:GetCommandCenter():MessageToGroup( string.format( "%s has tasks %s. Subscribe to a task using the radio menu.", Mission:GetShortText(), TaskText ), TaskGroup )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
--- **Tasking** - The TASK_A2G models tasks for players in Air to Ground engagements.
|
--- **Tasking** - The TASK_A2G models tasks for players in Air to Ground engagements.
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ### Author: **FlightControl**
|
-- ### Author: **FlightControl**
|
||||||
--
|
--
|
||||||
-- ### Contributions:
|
-- ### Contributions:
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- @module Tasking.Task_A2G
|
-- @module Tasking.Task_A2G
|
||||||
-- @image MOOSE.JPG
|
-- @image MOOSE.JPG
|
||||||
|
|
||||||
@@ -18,29 +18,29 @@ do -- TASK_A2G
|
|||||||
-- @field Core.Set#SET_UNIT TargetSetUnit
|
-- @field Core.Set#SET_UNIT TargetSetUnit
|
||||||
-- @extends Tasking.Task#TASK
|
-- @extends Tasking.Task#TASK
|
||||||
|
|
||||||
--- The TASK_A2G class defines Air To Ground tasks for a @{Set} of Target Units,
|
--- The TASK_A2G class defines Air To Ground tasks for a @{Set} of Target Units,
|
||||||
-- based on the tasking capabilities defined in @{Tasking.Task#TASK}.
|
-- based on the tasking capabilities defined in @{Tasking.Task#TASK}.
|
||||||
-- The TASK_A2G is implemented using a @{Core.Fsm#FSM_TASK}, and has the following statuses:
|
-- The TASK_A2G is implemented using a @{Core.Fsm#FSM_TASK}, and has the following statuses:
|
||||||
--
|
--
|
||||||
-- * **None**: Start of the process
|
-- * **None**: Start of the process
|
||||||
-- * **Planned**: The A2G task is planned.
|
-- * **Planned**: The A2G task is planned.
|
||||||
-- * **Assigned**: The A2G task is assigned to a @{Wrapper.Group#GROUP}.
|
-- * **Assigned**: The A2G task is assigned to a @{Wrapper.Group#GROUP}.
|
||||||
-- * **Success**: The A2G task is successfully completed.
|
-- * **Success**: The A2G task is successfully completed.
|
||||||
-- * **Failed**: The A2G task has failed. This will happen if the player exists the task early, without communicating a possible cancellation to HQ.
|
-- * **Failed**: The A2G task has failed. This will happen if the player exists the task early, without communicating a possible cancellation to HQ.
|
||||||
--
|
--
|
||||||
-- ## 1) Set the scoring of achievements in an A2G attack.
|
-- ## 1) Set the scoring of achievements in an A2G attack.
|
||||||
--
|
--
|
||||||
-- Scoring or penalties can be given in the following circumstances:
|
-- Scoring or penalties can be given in the following circumstances:
|
||||||
--
|
--
|
||||||
-- * @{#TASK_A2G.SetScoreOnDestroy}(): Set a score when a target in scope of the A2G attack, has been destroyed.
|
-- * @{#TASK_A2G.SetScoreOnDestroy}(): Set a score when a target in scope of the A2G attack, has been destroyed.
|
||||||
-- * @{#TASK_A2G.SetScoreOnSuccess}(): Set a score when all the targets in scope of the A2G attack, have been destroyed.
|
-- * @{#TASK_A2G.SetScoreOnSuccess}(): Set a score when all the targets in scope of the A2G attack, have been destroyed.
|
||||||
-- * @{#TASK_A2G.SetPenaltyOnFailed}(): Set a penalty when the A2G attack has failed.
|
-- * @{#TASK_A2G.SetPenaltyOnFailed}(): Set a penalty when the A2G attack has failed.
|
||||||
--
|
--
|
||||||
-- @field #TASK_A2G
|
-- @field #TASK_A2G
|
||||||
TASK_A2G = {
|
TASK_A2G = {
|
||||||
ClassName = "TASK_A2G",
|
ClassName = "TASK_A2G"
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Instantiates a new TASK_A2G.
|
--- Instantiates a new TASK_A2G.
|
||||||
-- @param #TASK_A2G self
|
-- @param #TASK_A2G self
|
||||||
-- @param Tasking.Mission#MISSION Mission
|
-- @param Tasking.Mission#MISSION Mission
|
||||||
@@ -54,53 +54,51 @@ do -- TASK_A2G
|
|||||||
function TASK_A2G:New( Mission, SetGroup, TaskName, TargetSetUnit, TaskType, TaskBriefing )
|
function TASK_A2G:New( Mission, SetGroup, TaskName, TargetSetUnit, TaskType, TaskBriefing )
|
||||||
local self = BASE:Inherit( self, TASK:New( Mission, SetGroup, TaskName, TaskType, TaskBriefing ) ) -- Tasking.Task#TASK_A2G
|
local self = BASE:Inherit( self, TASK:New( Mission, SetGroup, TaskName, TaskType, TaskBriefing ) ) -- Tasking.Task#TASK_A2G
|
||||||
self:F()
|
self:F()
|
||||||
|
|
||||||
self.TargetSetUnit = TargetSetUnit
|
self.TargetSetUnit = TargetSetUnit
|
||||||
self.TaskType = TaskType
|
self.TaskType = TaskType
|
||||||
|
|
||||||
local Fsm = self:GetUnitProcess()
|
local Fsm = self:GetUnitProcess()
|
||||||
|
|
||||||
Fsm:AddTransition( "Assigned", "RouteToRendezVous", "RoutingToRendezVous" )
|
Fsm:AddTransition( "Assigned", "RouteToRendezVous", "RoutingToRendezVous" )
|
||||||
Fsm:AddProcess ( "RoutingToRendezVous", "RouteToRendezVousPoint", ACT_ROUTE_POINT:New(), { Arrived = "ArriveAtRendezVous" } )
|
Fsm:AddProcess( "RoutingToRendezVous", "RouteToRendezVousPoint", ACT_ROUTE_POINT:New(), { Arrived = "ArriveAtRendezVous" } )
|
||||||
Fsm:AddProcess ( "RoutingToRendezVous", "RouteToRendezVousZone", ACT_ROUTE_ZONE:New(), { Arrived = "ArriveAtRendezVous" } )
|
Fsm:AddProcess( "RoutingToRendezVous", "RouteToRendezVousZone", ACT_ROUTE_ZONE:New(), { Arrived = "ArriveAtRendezVous" } )
|
||||||
|
|
||||||
Fsm:AddTransition( { "Arrived", "RoutingToRendezVous" }, "ArriveAtRendezVous", "ArrivedAtRendezVous" )
|
Fsm:AddTransition( { "Arrived", "RoutingToRendezVous" }, "ArriveAtRendezVous", "ArrivedAtRendezVous" )
|
||||||
|
|
||||||
Fsm:AddTransition( { "ArrivedAtRendezVous", "HoldingAtRendezVous" }, "Engage", "Engaging" )
|
Fsm:AddTransition( { "ArrivedAtRendezVous", "HoldingAtRendezVous" }, "Engage", "Engaging" )
|
||||||
Fsm:AddTransition( { "ArrivedAtRendezVous", "HoldingAtRendezVous" }, "HoldAtRendezVous", "HoldingAtRendezVous" )
|
Fsm:AddTransition( { "ArrivedAtRendezVous", "HoldingAtRendezVous" }, "HoldAtRendezVous", "HoldingAtRendezVous" )
|
||||||
|
|
||||||
Fsm:AddProcess ( "Engaging", "Account", ACT_ACCOUNT_DEADS:New(), {} )
|
Fsm:AddProcess( "Engaging", "Account", ACT_ACCOUNT_DEADS:New(), {} )
|
||||||
Fsm:AddTransition( "Engaging", "RouteToTarget", "Engaging" )
|
Fsm:AddTransition( "Engaging", "RouteToTarget", "Engaging" )
|
||||||
Fsm:AddProcess( "Engaging", "RouteToTargetZone", ACT_ROUTE_ZONE:New(), {} )
|
Fsm:AddProcess( "Engaging", "RouteToTargetZone", ACT_ROUTE_ZONE:New(), {} )
|
||||||
Fsm:AddProcess( "Engaging", "RouteToTargetPoint", ACT_ROUTE_POINT:New(), {} )
|
Fsm:AddProcess( "Engaging", "RouteToTargetPoint", ACT_ROUTE_POINT:New(), {} )
|
||||||
Fsm:AddTransition( "Engaging", "RouteToTargets", "Engaging" )
|
Fsm:AddTransition( "Engaging", "RouteToTargets", "Engaging" )
|
||||||
|
|
||||||
--Fsm:AddTransition( "Accounted", "DestroyedAll", "Accounted" )
|
-- Fsm:AddTransition( "Accounted", "DestroyedAll", "Accounted" )
|
||||||
--Fsm:AddTransition( "Accounted", "Success", "Success" )
|
-- Fsm:AddTransition( "Accounted", "Success", "Success" )
|
||||||
Fsm:AddTransition( "Rejected", "Reject", "Aborted" )
|
Fsm:AddTransition( "Rejected", "Reject", "Aborted" )
|
||||||
Fsm:AddTransition( "Failed", "Fail", "Failed" )
|
Fsm:AddTransition( "Failed", "Fail", "Failed" )
|
||||||
|
|
||||||
|
|
||||||
|
--- Test
|
||||||
--- Test
|
|
||||||
-- @param #FSM_PROCESS self
|
-- @param #FSM_PROCESS self
|
||||||
-- @param Wrapper.Unit#UNIT TaskUnit
|
-- @param Wrapper.Unit#UNIT TaskUnit
|
||||||
-- @param Tasking.Task_A2G#TASK_A2G Task
|
-- @param Tasking.Task_A2G#TASK_A2G Task
|
||||||
function Fsm:onafterAssigned( TaskUnit, Task )
|
function Fsm:onafterAssigned( TaskUnit, Task )
|
||||||
self:F( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
|
self:F( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
|
||||||
-- Determine the first Unit from the self.RendezVousSetUnit
|
-- Determine the first Unit from the self.RendezVousSetUnit
|
||||||
|
|
||||||
self:RouteToRendezVous()
|
self:RouteToRendezVous()
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Test
|
--- Test
|
||||||
-- @param #FSM_PROCESS self
|
-- @param #FSM_PROCESS self
|
||||||
-- @param Wrapper.Unit#UNIT TaskUnit
|
-- @param Wrapper.Unit#UNIT TaskUnit
|
||||||
-- @param Tasking.Task_A2G#TASK_A2G Task
|
-- @param Tasking.Task_A2G#TASK_A2G Task
|
||||||
function Fsm:onafterRouteToRendezVous( TaskUnit, Task )
|
function Fsm:onafterRouteToRendezVous( TaskUnit, Task )
|
||||||
self:F( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
|
self:F( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
|
||||||
-- Determine the first Unit from the self.RendezVousSetUnit
|
-- Determine the first Unit from the self.RendezVousSetUnit
|
||||||
|
|
||||||
if Task:GetRendezVousZone( TaskUnit ) then
|
if Task:GetRendezVousZone( TaskUnit ) then
|
||||||
self:__RouteToRendezVousZone( 0.1 )
|
self:__RouteToRendezVousZone( 0.1 )
|
||||||
else
|
else
|
||||||
@@ -112,36 +110,36 @@ do -- TASK_A2G
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Test
|
--- Test
|
||||||
-- @param #FSM_PROCESS self
|
-- @param #FSM_PROCESS self
|
||||||
-- @param Wrapper.Unit#UNIT TaskUnit
|
-- @param Wrapper.Unit#UNIT TaskUnit
|
||||||
-- @param Tasking.Task#TASK_A2G Task
|
-- @param Tasking.Task#TASK_A2G Task
|
||||||
function Fsm:OnAfterArriveAtRendezVous( TaskUnit, Task )
|
function Fsm:OnAfterArriveAtRendezVous( TaskUnit, Task )
|
||||||
self:F( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
|
self:F( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
|
||||||
-- Determine the first Unit from the self.TargetSetUnit
|
-- Determine the first Unit from the self.TargetSetUnit
|
||||||
|
|
||||||
self:__Engage( 0.1 )
|
self:__Engage( 0.1 )
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Test
|
--- Test
|
||||||
-- @param #FSM_PROCESS self
|
-- @param #FSM_PROCESS self
|
||||||
-- @param Wrapper.Unit#UNIT TaskUnit
|
-- @param Wrapper.Unit#UNIT TaskUnit
|
||||||
-- @param Tasking.Task#TASK_A2G Task
|
-- @param Tasking.Task#TASK_A2G Task
|
||||||
function Fsm:onafterEngage( TaskUnit, Task )
|
function Fsm:onafterEngage( TaskUnit, Task )
|
||||||
self:F( { self } )
|
self:F( { self } )
|
||||||
self:__Account( 0.1 )
|
self:__Account( 0.1 )
|
||||||
self:__RouteToTarget(0.1 )
|
self:__RouteToTarget( 0.1 )
|
||||||
self:__RouteToTargets( -10 )
|
self:__RouteToTargets( -10 )
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Test
|
--- Test
|
||||||
-- @param #FSM_PROCESS self
|
-- @param #FSM_PROCESS self
|
||||||
-- @param Wrapper.Unit#UNIT TaskUnit
|
-- @param Wrapper.Unit#UNIT TaskUnit
|
||||||
-- @param Tasking.Task_A2G#TASK_A2G Task
|
-- @param Tasking.Task_A2G#TASK_A2G Task
|
||||||
function Fsm:onafterRouteToTarget( TaskUnit, Task )
|
function Fsm:onafterRouteToTarget( TaskUnit, Task )
|
||||||
self:F( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
|
self:F( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
|
||||||
-- Determine the first Unit from the self.TargetSetUnit
|
-- Determine the first Unit from the self.TargetSetUnit
|
||||||
|
|
||||||
if Task:GetTargetZone( TaskUnit ) then
|
if Task:GetTargetZone( TaskUnit ) then
|
||||||
self:__RouteToTargetZone( 0.1 )
|
self:__RouteToTargetZone( 0.1 )
|
||||||
else
|
else
|
||||||
@@ -154,8 +152,8 @@ do -- TASK_A2G
|
|||||||
self:__RouteToTargetPoint( 0.1 )
|
self:__RouteToTargetPoint( 0.1 )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Test
|
--- Test
|
||||||
-- @param #FSM_PROCESS self
|
-- @param #FSM_PROCESS self
|
||||||
-- @param Wrapper.Unit#UNIT TaskUnit
|
-- @param Wrapper.Unit#UNIT TaskUnit
|
||||||
-- @param Tasking.Task_A2G#TASK_A2G Task
|
-- @param Tasking.Task_A2G#TASK_A2G Task
|
||||||
@@ -167,20 +165,18 @@ do -- TASK_A2G
|
|||||||
end
|
end
|
||||||
self:__RouteToTargets( -10 )
|
self:__RouteToTargets( -10 )
|
||||||
end
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #TASK_A2G self
|
--- @param #TASK_A2G self
|
||||||
-- @param Core.Set#SET_UNIT TargetSetUnit The set of targets.
|
-- @param Core.Set#SET_UNIT TargetSetUnit The set of targets.
|
||||||
function TASK_A2G:SetTargetSetUnit( TargetSetUnit )
|
function TASK_A2G:SetTargetSetUnit( TargetSetUnit )
|
||||||
|
|
||||||
self.TargetSetUnit = TargetSetUnit
|
self.TargetSetUnit = TargetSetUnit
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--- @param #TASK_A2G self
|
--- @param #TASK_A2G self
|
||||||
function TASK_A2G:GetPlannedMenuText()
|
function TASK_A2G:GetPlannedMenuText()
|
||||||
return self:GetStateString() .. " - " .. self:GetTaskName() .. " ( " .. self.TargetSetUnit:GetUnitTypesText() .. " )"
|
return self:GetStateString() .. " - " .. self:GetTaskName() .. " ( " .. self.TargetSetUnit:GetUnitTypesText() .. " )"
|
||||||
@@ -190,34 +186,32 @@ do -- TASK_A2G
|
|||||||
-- @param Core.Point#COORDINATE RendezVousCoordinate The Coordinate object referencing to the 2D point where the RendezVous point is located on the map.
|
-- @param Core.Point#COORDINATE RendezVousCoordinate The Coordinate object referencing to the 2D point where the RendezVous point is located on the map.
|
||||||
-- @param #number RendezVousRange The RendezVousRange that defines when the player is considered to have arrived at the RendezVous point.
|
-- @param #number RendezVousRange The RendezVousRange that defines when the player is considered to have arrived at the RendezVous point.
|
||||||
-- @param Wrapper.Unit#UNIT TaskUnit
|
-- @param Wrapper.Unit#UNIT TaskUnit
|
||||||
function TASK_A2G:SetRendezVousCoordinate( RendezVousCoordinate, RendezVousRange, TaskUnit )
|
function TASK_A2G:SetRendezVousCoordinate( RendezVousCoordinate, RendezVousRange, TaskUnit )
|
||||||
|
|
||||||
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
||||||
|
|
||||||
local ActRouteRendezVous = ProcessUnit:GetProcess( "RoutingToRendezVous", "RouteToRendezVousPoint" ) -- Actions.Act_Route#ACT_ROUTE_POINT
|
local ActRouteRendezVous = ProcessUnit:GetProcess( "RoutingToRendezVous", "RouteToRendezVousPoint" ) -- Actions.Act_Route#ACT_ROUTE_POINT
|
||||||
ActRouteRendezVous:SetCoordinate( RendezVousCoordinate )
|
ActRouteRendezVous:SetCoordinate( RendezVousCoordinate )
|
||||||
ActRouteRendezVous:SetRange( RendezVousRange )
|
ActRouteRendezVous:SetRange( RendezVousRange )
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #TASK_A2G self
|
--- @param #TASK_A2G self
|
||||||
-- @param Wrapper.Unit#UNIT TaskUnit
|
-- @param Wrapper.Unit#UNIT TaskUnit
|
||||||
-- @return Core.Point#COORDINATE The Coordinate object referencing to the 2D point where the RendezVous point is located on the map.
|
-- @return Core.Point#COORDINATE The Coordinate object referencing to the 2D point where the RendezVous point is located on the map.
|
||||||
-- @return #number The RendezVousRange that defines when the player is considered to have arrived at the RendezVous point.
|
-- @return #number The RendezVousRange that defines when the player is considered to have arrived at the RendezVous point.
|
||||||
function TASK_A2G:GetRendezVousCoordinate( TaskUnit )
|
function TASK_A2G:GetRendezVousCoordinate( TaskUnit )
|
||||||
|
|
||||||
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
||||||
|
|
||||||
local ActRouteRendezVous = ProcessUnit:GetProcess( "RoutingToRendezVous", "RouteToRendezVousPoint" ) -- Actions.Act_Route#ACT_ROUTE_POINT
|
local ActRouteRendezVous = ProcessUnit:GetProcess( "RoutingToRendezVous", "RouteToRendezVousPoint" ) -- Actions.Act_Route#ACT_ROUTE_POINT
|
||||||
return ActRouteRendezVous:GetCoordinate(), ActRouteRendezVous:GetRange()
|
return ActRouteRendezVous:GetCoordinate(), ActRouteRendezVous:GetRange()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--- @param #TASK_A2G self
|
--- @param #TASK_A2G self
|
||||||
-- @param Core.Zone#ZONE_BASE RendezVousZone The Zone object where the RendezVous is located on the map.
|
-- @param Core.Zone#ZONE_BASE RendezVousZone The Zone object where the RendezVous is located on the map.
|
||||||
-- @param Wrapper.Unit#UNIT TaskUnit
|
-- @param Wrapper.Unit#UNIT TaskUnit
|
||||||
function TASK_A2G:SetRendezVousZone( RendezVousZone, TaskUnit )
|
function TASK_A2G:SetRendezVousZone( RendezVousZone, TaskUnit )
|
||||||
|
|
||||||
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
||||||
|
|
||||||
local ActRouteRendezVous = ProcessUnit:GetProcess( "RoutingToRendezVous", "RouteToRendezVousZone" ) -- Actions.Act_Route#ACT_ROUTE_ZONE
|
local ActRouteRendezVous = ProcessUnit:GetProcess( "RoutingToRendezVous", "RouteToRendezVousZone" ) -- Actions.Act_Route#ACT_ROUTE_ZONE
|
||||||
@@ -234,18 +228,17 @@ do -- TASK_A2G
|
|||||||
local ActRouteRendezVous = ProcessUnit:GetProcess( "RoutingToRendezVous", "RouteToRendezVousZone" ) -- Actions.Act_Route#ACT_ROUTE_ZONE
|
local ActRouteRendezVous = ProcessUnit:GetProcess( "RoutingToRendezVous", "RouteToRendezVousZone" ) -- Actions.Act_Route#ACT_ROUTE_ZONE
|
||||||
return ActRouteRendezVous:GetZone()
|
return ActRouteRendezVous:GetZone()
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #TASK_A2G self
|
--- @param #TASK_A2G self
|
||||||
-- @param Core.Point#COORDINATE TargetCoordinate The Coordinate object where the Target is located on the map.
|
-- @param Core.Point#COORDINATE TargetCoordinate The Coordinate object where the Target is located on the map.
|
||||||
-- @param Wrapper.Unit#UNIT TaskUnit
|
-- @param Wrapper.Unit#UNIT TaskUnit
|
||||||
function TASK_A2G:SetTargetCoordinate( TargetCoordinate, TaskUnit )
|
function TASK_A2G:SetTargetCoordinate( TargetCoordinate, TaskUnit )
|
||||||
|
|
||||||
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
||||||
|
|
||||||
local ActRouteTarget = ProcessUnit:GetProcess( "Engaging", "RouteToTargetPoint" ) -- Actions.Act_Route#ACT_ROUTE_POINT
|
local ActRouteTarget = ProcessUnit:GetProcess( "Engaging", "RouteToTargetPoint" ) -- Actions.Act_Route#ACT_ROUTE_POINT
|
||||||
ActRouteTarget:SetCoordinate( TargetCoordinate )
|
ActRouteTarget:SetCoordinate( TargetCoordinate )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- @param #TASK_A2G self
|
--- @param #TASK_A2G self
|
||||||
-- @param Wrapper.Unit#UNIT TaskUnit
|
-- @param Wrapper.Unit#UNIT TaskUnit
|
||||||
@@ -258,18 +251,16 @@ do -- TASK_A2G
|
|||||||
return ActRouteTarget:GetCoordinate()
|
return ActRouteTarget:GetCoordinate()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- @param #TASK_A2G self
|
--- @param #TASK_A2G self
|
||||||
-- @param Core.Zone#ZONE_BASE TargetZone The Zone object where the Target is located on the map.
|
-- @param Core.Zone#ZONE_BASE TargetZone The Zone object where the Target is located on the map.
|
||||||
-- @param Wrapper.Unit#UNIT TaskUnit
|
-- @param Wrapper.Unit#UNIT TaskUnit
|
||||||
function TASK_A2G:SetTargetZone( TargetZone, TaskUnit )
|
function TASK_A2G:SetTargetZone( TargetZone, TaskUnit )
|
||||||
|
|
||||||
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
||||||
|
|
||||||
local ActRouteTarget = ProcessUnit:GetProcess( "Engaging", "RouteToTargetZone" ) -- Actions.Act_Route#ACT_ROUTE_ZONE
|
local ActRouteTarget = ProcessUnit:GetProcess( "Engaging", "RouteToTargetZone" ) -- Actions.Act_Route#ACT_ROUTE_ZONE
|
||||||
ActRouteTarget:SetZone( TargetZone )
|
ActRouteTarget:SetZone( TargetZone )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- @param #TASK_A2G self
|
--- @param #TASK_A2G self
|
||||||
-- @param Wrapper.Unit#UNIT TaskUnit
|
-- @param Wrapper.Unit#UNIT TaskUnit
|
||||||
@@ -283,47 +274,46 @@ do -- TASK_A2G
|
|||||||
end
|
end
|
||||||
|
|
||||||
function TASK_A2G:SetGoalTotal()
|
function TASK_A2G:SetGoalTotal()
|
||||||
|
|
||||||
self.GoalTotal = self.TargetSetUnit:Count()
|
self.GoalTotal = self.TargetSetUnit:Count()
|
||||||
end
|
end
|
||||||
|
|
||||||
function TASK_A2G:GetGoalTotal()
|
function TASK_A2G:GetGoalTotal()
|
||||||
|
|
||||||
return self.GoalTotal
|
return self.GoalTotal
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Return the relative distance to the target vicinity from the player, in order to sort the targets in the reports per distance from the threats.
|
--- Return the relative distance to the target vicinity from the player, in order to sort the targets in the reports per distance from the threats.
|
||||||
-- @param #TASK_A2G self
|
-- @param #TASK_A2G self
|
||||||
function TASK_A2G:ReportOrder( ReportGroup )
|
function TASK_A2G:ReportOrder( ReportGroup )
|
||||||
self:UpdateTaskInfo( self.DetectedItem )
|
self:UpdateTaskInfo( self.DetectedItem )
|
||||||
|
|
||||||
local Coordinate = self.TaskInfo:GetData( "Coordinate" )
|
local Coordinate = self.TaskInfo:GetData( "Coordinate" )
|
||||||
local Distance = ReportGroup:GetCoordinate():Get2DDistance( Coordinate )
|
local Distance = ReportGroup:GetCoordinate():Get2DDistance( Coordinate )
|
||||||
|
|
||||||
return Distance
|
return Distance
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- This method checks every 10 seconds if the goal has been reached of the task.
|
--- This method checks every 10 seconds if the goal has been reached of the task.
|
||||||
-- @param #TASK_A2G self
|
-- @param #TASK_A2G self
|
||||||
function TASK_A2G:onafterGoal( TaskUnit, From, Event, To )
|
function TASK_A2G:onafterGoal( TaskUnit, From, Event, To )
|
||||||
local TargetSetUnit = self.TargetSetUnit -- Core.Set#SET_UNIT
|
local TargetSetUnit = self.TargetSetUnit -- Core.Set#SET_UNIT
|
||||||
|
|
||||||
if TargetSetUnit:Count() == 0 then
|
if TargetSetUnit:Count() == 0 then
|
||||||
self:Success()
|
self:Success()
|
||||||
end
|
end
|
||||||
|
|
||||||
self:__Goal( -10 )
|
self:__Goal( -10 )
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #TASK_A2G self
|
--- @param #TASK_A2G self
|
||||||
function TASK_A2G:UpdateTaskInfo( DetectedItem )
|
function TASK_A2G:UpdateTaskInfo( DetectedItem )
|
||||||
|
|
||||||
if self:IsStatePlanned() or self:IsStateAssigned() then
|
if self:IsStatePlanned() or self:IsStateAssigned() then
|
||||||
local TargetCoordinate = DetectedItem and self.Detection:GetDetectedItemCoordinate( DetectedItem ) or self.TargetSetUnit:GetFirst():GetCoordinate()
|
local TargetCoordinate = DetectedItem and self.Detection:GetDetectedItemCoordinate( DetectedItem ) or self.TargetSetUnit:GetFirst():GetCoordinate()
|
||||||
self.TaskInfo:AddTaskName( 0, "MSOD" )
|
self.TaskInfo:AddTaskName( 0, "MSOD" )
|
||||||
self.TaskInfo:AddCoordinate( TargetCoordinate, 1, "SOD" )
|
self.TaskInfo:AddCoordinate( TargetCoordinate, 1, "SOD" )
|
||||||
|
|
||||||
local ThreatLevel, ThreatText
|
local ThreatLevel, ThreatText
|
||||||
if DetectedItem then
|
if DetectedItem then
|
||||||
ThreatLevel, ThreatText = self.Detection:GetDetectedItemThreatLevel( DetectedItem )
|
ThreatLevel, ThreatText = self.Detection:GetDetectedItemThreatLevel( DetectedItem )
|
||||||
@@ -331,7 +321,7 @@ do -- TASK_A2G
|
|||||||
ThreatLevel, ThreatText = self.TargetSetUnit:CalculateThreatLevelA2G()
|
ThreatLevel, ThreatText = self.TargetSetUnit:CalculateThreatLevelA2G()
|
||||||
end
|
end
|
||||||
self.TaskInfo:AddThreat( ThreatText, ThreatLevel, 10, "MOD", true )
|
self.TaskInfo:AddThreat( ThreatText, ThreatLevel, 10, "MOD", true )
|
||||||
|
|
||||||
if self.Detection then
|
if self.Detection then
|
||||||
local DetectedItemsCount = self.TargetSetUnit:Count()
|
local DetectedItemsCount = self.TargetSetUnit:Count()
|
||||||
local ReportTypes = REPORT:New()
|
local ReportTypes = REPORT:New()
|
||||||
@@ -344,33 +334,33 @@ do -- TASK_A2G
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
self.TaskInfo:AddTargetCount( DetectedItemsCount, 11, "O", true )
|
self.TaskInfo:AddTargetCount( DetectedItemsCount, 11, "O", true )
|
||||||
self.TaskInfo:AddTargets( DetectedItemsCount, ReportTypes:Text( ", " ), 20, "D", true )
|
self.TaskInfo:AddTargets( DetectedItemsCount, ReportTypes:Text( ", " ), 20, "D", true )
|
||||||
else
|
else
|
||||||
local DetectedItemsCount = self.TargetSetUnit:Count()
|
local DetectedItemsCount = self.TargetSetUnit:Count()
|
||||||
local DetectedItemsTypes = self.TargetSetUnit:GetTypeNames()
|
local DetectedItemsTypes = self.TargetSetUnit:GetTypeNames()
|
||||||
self.TaskInfo:AddTargetCount( DetectedItemsCount, 11, "O", true )
|
self.TaskInfo:AddTargetCount( DetectedItemsCount, 11, "O", true )
|
||||||
self.TaskInfo:AddTargets( DetectedItemsCount, DetectedItemsTypes, 20, "D", true )
|
self.TaskInfo:AddTargets( DetectedItemsCount, DetectedItemsTypes, 20, "D", true )
|
||||||
end
|
end
|
||||||
self.TaskInfo:AddQFEAtCoordinate( TargetCoordinate, 30, "MOD" )
|
self.TaskInfo:AddQFEAtCoordinate( TargetCoordinate, 30, "MOD" )
|
||||||
self.TaskInfo:AddTemperatureAtCoordinate( TargetCoordinate, 31, "MD" )
|
self.TaskInfo:AddTemperatureAtCoordinate( TargetCoordinate, 31, "MD" )
|
||||||
self.TaskInfo:AddWindAtCoordinate( TargetCoordinate, 32, "MD" )
|
self.TaskInfo:AddWindAtCoordinate( TargetCoordinate, 32, "MD" )
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- This function is called from the @{Tasking.CommandCenter#COMMANDCENTER} to determine the method of automatic task selection.
|
--- This function is called from the @{Tasking.CommandCenter#COMMANDCENTER} to determine the method of automatic task selection.
|
||||||
-- @param #TASK_A2G self
|
-- @param #TASK_A2G self
|
||||||
-- @param #number AutoAssignMethod The method to be applied to the task.
|
-- @param #number AutoAssignMethod The method to be applied to the task.
|
||||||
-- @param Tasking.CommandCenter#COMMANDCENTER CommandCenter The command center.
|
-- @param Tasking.CommandCenter#COMMANDCENTER CommandCenter The command center.
|
||||||
-- @param Wrapper.Group#GROUP TaskGroup The player group.
|
-- @param Wrapper.Group#GROUP TaskGroup The player group.
|
||||||
function TASK_A2G:GetAutoAssignPriority( AutoAssignMethod, CommandCenter, TaskGroup )
|
function TASK_A2G:GetAutoAssignPriority( AutoAssignMethod, CommandCenter, TaskGroup )
|
||||||
|
|
||||||
if AutoAssignMethod == COMMANDCENTER.AutoAssignMethods.Random then
|
if AutoAssignMethod == COMMANDCENTER.AutoAssignMethods.Random then
|
||||||
return math.random( 1, 9 )
|
return math.random( 1, 9 )
|
||||||
elseif AutoAssignMethod == COMMANDCENTER.AutoAssignMethods.Distance then
|
elseif AutoAssignMethod == COMMANDCENTER.AutoAssignMethods.Distance then
|
||||||
local Coordinate = self.TaskInfo:GetData( "Coordinate" )
|
local Coordinate = self.TaskInfo:GetData( "Coordinate" )
|
||||||
local Distance = Coordinate:Get2DDistance( CommandCenter:GetPositionable():GetCoordinate() )
|
local Distance = Coordinate:Get2DDistance( CommandCenter:GetPositionable():GetCoordinate() )
|
||||||
self:F({Distance=Distance})
|
self:F( { Distance = Distance } )
|
||||||
return math.floor( Distance )
|
return math.floor( Distance )
|
||||||
elseif AutoAssignMethod == COMMANDCENTER.AutoAssignMethods.Priority then
|
elseif AutoAssignMethod == COMMANDCENTER.AutoAssignMethods.Priority then
|
||||||
return 1
|
return 1
|
||||||
@@ -379,8 +369,7 @@ do -- TASK_A2G
|
|||||||
return 0
|
return 0
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
do -- TASK_A2G_SEAD
|
do -- TASK_A2G_SEAD
|
||||||
|
|
||||||
@@ -397,9 +386,9 @@ do -- TASK_A2G_SEAD
|
|||||||
--
|
--
|
||||||
-- @field #TASK_A2G_SEAD
|
-- @field #TASK_A2G_SEAD
|
||||||
TASK_A2G_SEAD = {
|
TASK_A2G_SEAD = {
|
||||||
ClassName = "TASK_A2G_SEAD",
|
ClassName = "TASK_A2G_SEAD"
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Instantiates a new TASK_A2G_SEAD.
|
--- Instantiates a new TASK_A2G_SEAD.
|
||||||
-- @param #TASK_A2G_SEAD self
|
-- @param #TASK_A2G_SEAD self
|
||||||
-- @param Tasking.Mission#MISSION Mission
|
-- @param Tasking.Mission#MISSION Mission
|
||||||
@@ -408,19 +397,16 @@ do -- TASK_A2G_SEAD
|
|||||||
-- @param Core.Set#SET_UNIT TargetSetUnit
|
-- @param Core.Set#SET_UNIT TargetSetUnit
|
||||||
-- @param #string TaskBriefing The briefing of the task.
|
-- @param #string TaskBriefing The briefing of the task.
|
||||||
-- @return #TASK_A2G_SEAD self
|
-- @return #TASK_A2G_SEAD self
|
||||||
function TASK_A2G_SEAD:New( Mission, SetGroup, TaskName, TargetSetUnit, TaskBriefing)
|
function TASK_A2G_SEAD:New( Mission, SetGroup, TaskName, TargetSetUnit, TaskBriefing )
|
||||||
local self = BASE:Inherit( self, TASK_A2G:New( Mission, SetGroup, TaskName, TargetSetUnit, "SEAD", TaskBriefing ) ) -- #TASK_A2G_SEAD
|
local self = BASE:Inherit( self, TASK_A2G:New( Mission, SetGroup, TaskName, TargetSetUnit, "SEAD", TaskBriefing ) ) -- #TASK_A2G_SEAD
|
||||||
self:F()
|
self:F()
|
||||||
|
|
||||||
Mission:AddTask( self )
|
Mission:AddTask( self )
|
||||||
|
|
||||||
self:SetBriefing(
|
self:SetBriefing( TaskBriefing or "Execute a Suppression of Enemy Air Defenses." )
|
||||||
TaskBriefing or
|
|
||||||
"Execute a Suppression of Enemy Air Defenses."
|
|
||||||
)
|
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Set a score when a target in scope of the A2G attack, has been destroyed .
|
--- Set a score when a target in scope of the A2G attack, has been destroyed .
|
||||||
-- @param #TASK_A2G_SEAD self
|
-- @param #TASK_A2G_SEAD self
|
||||||
@@ -434,7 +420,7 @@ do -- TASK_A2G_SEAD
|
|||||||
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
||||||
|
|
||||||
ProcessUnit:AddScoreProcess( "Engaging", "Account", "AccountForPlayer", "Player " .. PlayerName .. " has SEADed a target.", Score )
|
ProcessUnit:AddScoreProcess( "Engaging", "Account", "AccountForPlayer", "Player " .. PlayerName .. " has SEADed a target.", Score )
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -450,7 +436,7 @@ do -- TASK_A2G_SEAD
|
|||||||
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
||||||
|
|
||||||
ProcessUnit:AddScore( "Success", "All radar emitting targets have been successfully SEADed!", Score )
|
ProcessUnit:AddScore( "Success", "All radar emitting targets have been successfully SEADed!", Score )
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -466,11 +452,10 @@ do -- TASK_A2G_SEAD
|
|||||||
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
||||||
|
|
||||||
ProcessUnit:AddScore( "Failed", "The SEADing has failed!", Penalty )
|
ProcessUnit:AddScore( "Failed", "The SEADing has failed!", Penalty )
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
do -- TASK_A2G_BAI
|
do -- TASK_A2G_BAI
|
||||||
@@ -488,10 +473,8 @@ do -- TASK_A2G_BAI
|
|||||||
-- based on detected enemy ground targets.
|
-- based on detected enemy ground targets.
|
||||||
--
|
--
|
||||||
-- @field #TASK_A2G_BAI
|
-- @field #TASK_A2G_BAI
|
||||||
TASK_A2G_BAI = {
|
TASK_A2G_BAI = { ClassName = "TASK_A2G_BAI" }
|
||||||
ClassName = "TASK_A2G_BAI",
|
|
||||||
}
|
|
||||||
|
|
||||||
--- Instantiates a new TASK_A2G_BAI.
|
--- Instantiates a new TASK_A2G_BAI.
|
||||||
-- @param #TASK_A2G_BAI self
|
-- @param #TASK_A2G_BAI self
|
||||||
-- @param Tasking.Mission#MISSION Mission
|
-- @param Tasking.Mission#MISSION Mission
|
||||||
@@ -503,14 +486,11 @@ do -- TASK_A2G_BAI
|
|||||||
function TASK_A2G_BAI:New( Mission, SetGroup, TaskName, TargetSetUnit, TaskBriefing )
|
function TASK_A2G_BAI:New( Mission, SetGroup, TaskName, TargetSetUnit, TaskBriefing )
|
||||||
local self = BASE:Inherit( self, TASK_A2G:New( Mission, SetGroup, TaskName, TargetSetUnit, "BAI", TaskBriefing ) ) -- #TASK_A2G_BAI
|
local self = BASE:Inherit( self, TASK_A2G:New( Mission, SetGroup, TaskName, TargetSetUnit, "BAI", TaskBriefing ) ) -- #TASK_A2G_BAI
|
||||||
self:F()
|
self:F()
|
||||||
|
|
||||||
Mission:AddTask( self )
|
Mission:AddTask( self )
|
||||||
|
|
||||||
self:SetBriefing(
|
self:SetBriefing( TaskBriefing or "Execute a Battlefield Air Interdiction of a group of enemy targets." )
|
||||||
TaskBriefing or
|
|
||||||
"Execute a Battlefield Air Interdiction of a group of enemy targets."
|
|
||||||
)
|
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -526,7 +506,7 @@ do -- TASK_A2G_BAI
|
|||||||
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
||||||
|
|
||||||
ProcessUnit:AddScoreProcess( "Engaging", "Account", "AccountForPlayer", "Player " .. PlayerName .. " has destroyed a target in Battlefield Air Interdiction (BAI).", Score )
|
ProcessUnit:AddScoreProcess( "Engaging", "Account", "AccountForPlayer", "Player " .. PlayerName .. " has destroyed a target in Battlefield Air Interdiction (BAI).", Score )
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -542,7 +522,7 @@ do -- TASK_A2G_BAI
|
|||||||
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
||||||
|
|
||||||
ProcessUnit:AddScore( "Success", "All targets have been successfully destroyed! The Battlefield Air Interdiction (BAI) is a success!", Score )
|
ProcessUnit:AddScore( "Success", "All targets have been successfully destroyed! The Battlefield Air Interdiction (BAI) is a success!", Score )
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -558,15 +538,12 @@ do -- TASK_A2G_BAI
|
|||||||
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
||||||
|
|
||||||
ProcessUnit:AddScore( "Failed", "The Battlefield Air Interdiction (BAI) has failed!", Penalty )
|
ProcessUnit:AddScore( "Failed", "The Battlefield Air Interdiction (BAI) has failed!", Penalty )
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
do -- TASK_A2G_CAS
|
do -- TASK_A2G_CAS
|
||||||
|
|
||||||
--- The TASK_A2G_CAS class
|
--- The TASK_A2G_CAS class
|
||||||
@@ -581,10 +558,8 @@ do -- TASK_A2G_CAS
|
|||||||
-- based on detected enemy ground targets.
|
-- based on detected enemy ground targets.
|
||||||
--
|
--
|
||||||
-- @field #TASK_A2G_CAS
|
-- @field #TASK_A2G_CAS
|
||||||
TASK_A2G_CAS = {
|
TASK_A2G_CAS = { ClassName = "TASK_A2G_CAS" }
|
||||||
ClassName = "TASK_A2G_CAS",
|
|
||||||
}
|
|
||||||
|
|
||||||
--- Instantiates a new TASK_A2G_CAS.
|
--- Instantiates a new TASK_A2G_CAS.
|
||||||
-- @param #TASK_A2G_CAS self
|
-- @param #TASK_A2G_CAS self
|
||||||
-- @param Tasking.Mission#MISSION Mission
|
-- @param Tasking.Mission#MISSION Mission
|
||||||
@@ -596,19 +571,13 @@ do -- TASK_A2G_CAS
|
|||||||
function TASK_A2G_CAS:New( Mission, SetGroup, TaskName, TargetSetUnit, TaskBriefing )
|
function TASK_A2G_CAS:New( Mission, SetGroup, TaskName, TargetSetUnit, TaskBriefing )
|
||||||
local self = BASE:Inherit( self, TASK_A2G:New( Mission, SetGroup, TaskName, TargetSetUnit, "CAS", TaskBriefing ) ) -- #TASK_A2G_CAS
|
local self = BASE:Inherit( self, TASK_A2G:New( Mission, SetGroup, TaskName, TargetSetUnit, "CAS", TaskBriefing ) ) -- #TASK_A2G_CAS
|
||||||
self:F()
|
self:F()
|
||||||
|
|
||||||
Mission:AddTask( self )
|
|
||||||
|
|
||||||
self:SetBriefing(
|
|
||||||
TaskBriefing or
|
|
||||||
"Execute a Close Air Support for a group of enemy targets. " ..
|
|
||||||
"Beware of friendlies at the vicinity! "
|
|
||||||
)
|
|
||||||
|
|
||||||
|
Mission:AddTask( self )
|
||||||
|
|
||||||
|
self:SetBriefing( TaskBriefing or ( "Execute a Close Air Support for a group of enemy targets. " .. "Beware of friendlies at the vicinity! " ) )
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Set a score when a target in scope of the A2G attack, has been destroyed .
|
--- Set a score when a target in scope of the A2G attack, has been destroyed .
|
||||||
-- @param #TASK_A2G_CAS self
|
-- @param #TASK_A2G_CAS self
|
||||||
@@ -622,7 +591,7 @@ do -- TASK_A2G_CAS
|
|||||||
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
||||||
|
|
||||||
ProcessUnit:AddScoreProcess( "Engaging", "Account", "AccountForPlayer", "Player " .. PlayerName .. " has destroyed a target in Close Air Support (CAS).", Score )
|
ProcessUnit:AddScoreProcess( "Engaging", "Account", "AccountForPlayer", "Player " .. PlayerName .. " has destroyed a target in Close Air Support (CAS).", Score )
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -638,7 +607,7 @@ do -- TASK_A2G_CAS
|
|||||||
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
||||||
|
|
||||||
ProcessUnit:AddScore( "Success", "All targets have been successfully destroyed! The Close Air Support (CAS) was a success!", Score )
|
ProcessUnit:AddScore( "Success", "All targets have been successfully destroyed! The Close Air Support (CAS) was a success!", Score )
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -654,9 +623,8 @@ do -- TASK_A2G_CAS
|
|||||||
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
local ProcessUnit = self:GetUnitProcess( TaskUnit )
|
||||||
|
|
||||||
ProcessUnit:AddScore( "Failed", "The Close Air Support (CAS) has failed!", Penalty )
|
ProcessUnit:AddScore( "Failed", "The Close Air Support (CAS) has failed!", Penalty )
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,24 +1,25 @@
|
|||||||
--- **Tasking** -- Dynamically allocates A2G tasks to human players, based on detected ground targets through reconnaissance.
|
--- **Tasking** -- Dynamically allocates A2G tasks to human players, based on detected ground targets through reconnaissance.
|
||||||
--
|
--
|
||||||
-- **Features:**
|
-- **Features:**
|
||||||
--
|
--
|
||||||
-- * Dynamically assign tasks to human players based on detected targets.
|
-- * Dynamically assign tasks to human players based on detected targets.
|
||||||
-- * Dynamically change the tasks as the tactical situation evolves during the mission.
|
-- * Dynamically change the tasks as the tactical situation evolves during the mission.
|
||||||
-- * Dynamically assign (CAS) Close Air Support tasks for human players.
|
-- * Dynamically assign (CAS) Close Air Support tasks for human players.
|
||||||
-- * Dynamically assign (BAI) Battlefield Air Interdiction tasks for human players.
|
-- * Dynamically assign (BAI) Battlefield Air Interdiction tasks for human players.
|
||||||
-- * Dynamically assign (SEAD) Supression of Enemy Air Defense tasks for human players to eliminate G2A missile threats.
|
-- * Dynamically assign (SEAD) Suppression of Enemy Air Defense tasks for human players to eliminate G2A missile threats.
|
||||||
-- * Define and use an EWR (Early Warning Radar) network.
|
-- * Define and use an EWR (Early Warning Radar) network.
|
||||||
-- * Define different ranges to engage upon intruders.
|
-- * Define different ranges to engage upon intruders.
|
||||||
-- * Keep task achievements.
|
-- * Keep task achievements.
|
||||||
-- * Score task achievements.--
|
-- * Score task achievements.
|
||||||
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ### Author: **FlightControl**
|
-- ### Author: **FlightControl**
|
||||||
--
|
--
|
||||||
-- ### Contributions:
|
-- ### Contributions:
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- @module Tasking.Task_A2G_Dispatcher
|
-- @module Tasking.Task_A2G_Dispatcher
|
||||||
-- @image Task_A2G_Dispatcher.JPG
|
-- @image Task_A2G_Dispatcher.JPG
|
||||||
|
|
||||||
@@ -32,151 +33,151 @@ do -- TASK_A2G_DISPATCHER
|
|||||||
-- @extends Tasking.DetectionManager#DETECTION_MANAGER
|
-- @extends Tasking.DetectionManager#DETECTION_MANAGER
|
||||||
|
|
||||||
--- Orchestrates dynamic **A2G Task Dispatching** based on the detection results of a linked @{Detection} object.
|
--- Orchestrates dynamic **A2G Task Dispatching** based on the detection results of a linked @{Detection} object.
|
||||||
--
|
--
|
||||||
-- It uses the Tasking System within the MOOSE framework, which is a multi-player Tasking Orchestration system.
|
-- It uses the Tasking System within the MOOSE framework, which is a multi-player Tasking Orchestration system.
|
||||||
-- It provides a truly dynamic battle environment for pilots and ground commanders to engage upon,
|
-- It provides a truly dynamic battle environment for pilots and ground commanders to engage upon,
|
||||||
-- in a true co-operation environment wherein **Multiple Teams** will collaborate in Missions to **achieve a common Mission Goal**.
|
-- in a true co-operation environment wherein **Multiple Teams** will collaborate in Missions to **achieve a common Mission Goal**.
|
||||||
--
|
--
|
||||||
-- The A2G dispatcher will dispatch the A2G Tasks to a defined @{Set} of @{Wrapper.Group}s that will be manned by **Players**.
|
-- The A2G dispatcher will dispatch the A2G Tasks to a defined @{Set} of @{Wrapper.Group}s that will be manned by **Players**.
|
||||||
-- We call this the **AttackSet** of the A2G dispatcher. So, the Players are seated in the @{Client}s of the @{Wrapper.Group} @{Set}.
|
-- We call this the **AttackSet** of the A2G dispatcher. So, the Players are seated in the @{Client}s of the @{Wrapper.Group} @{Set}.
|
||||||
--
|
--
|
||||||
-- Depending on the actions of the enemy, preventive tasks are dispatched to the players to orchestrate the engagement in a true co-operation.
|
-- Depending on the actions of the enemy, preventive tasks are dispatched to the players to orchestrate the engagement in a true co-operation.
|
||||||
-- The detection object will group the detected targets by its grouping method, and integrates a @{Set} of @{Wrapper.Group}s that are Recce vehicles or air units.
|
-- The detection object will group the detected targets by its grouping method, and integrates a @{Set} of @{Wrapper.Group}s that are Recce vehicles or air units.
|
||||||
-- We call this the **RecceSet** of the A2G dispatcher.
|
-- We call this the **RecceSet** of the A2G dispatcher.
|
||||||
--
|
--
|
||||||
-- Depending on the current detected tactical situation, different task types will be dispatched to the Players seated in the AttackSet..
|
-- Depending on the current detected tactical situation, different task types will be dispatched to the Players seated in the AttackSet..
|
||||||
-- There are currently 3 **Task Types** implemented in the TASK\_A2G\_DISPATCHER:
|
-- There are currently 3 **Task Types** implemented in the TASK\_A2G\_DISPATCHER:
|
||||||
--
|
--
|
||||||
-- - **SEAD Task**: Dispatched when there are ground based Radar Emitters detected within an area.
|
-- - **SEAD Task**: Dispatched when there are ground based Radar Emitters detected within an area.
|
||||||
-- - **CAS Task**: Dispatched when there are no ground based Radar Emitters within the area, but there are friendly ground Units within 6 km from the enemy.
|
-- - **CAS Task**: Dispatched when there are no ground based Radar Emitters within the area, but there are friendly ground Units within 6 km from the enemy.
|
||||||
-- - **BAI Task**: Dispatched when there are no ground based Radar Emitters within the area, and there aren't friendly ground Units within 6 km from the enemy.
|
-- - **BAI Task**: Dispatched when there are no ground based Radar Emitters within the area, and there aren't friendly ground Units within 6 km from the enemy.
|
||||||
--
|
--
|
||||||
-- # 0. Tactical Situations
|
-- # 0. Tactical Situations
|
||||||
--
|
--
|
||||||
-- This chapters provides some insights in the tactical situations when certain Task Types are created.
|
-- This chapters provides some insights in the tactical situations when certain Task Types are created.
|
||||||
-- The Task Types are depending on the enemy positions that were detected, and the current location of friendly units.
|
-- The Task Types are depending on the enemy positions that were detected, and the current location of friendly units.
|
||||||
--
|
--
|
||||||
-- 
|
-- 
|
||||||
--
|
--
|
||||||
-- In the demonstration mission [TAD-A2G-000 - AREAS - Detection test],
|
-- In the demonstration mission [TAD-A2G-000 - AREAS - Detection test],
|
||||||
-- the tactical situation is a demonstration how the A2G detection works.
|
-- the tactical situation is a demonstration how the A2G detection works.
|
||||||
-- This example will be taken further in the explanation in the following chapters.
|
-- This example will be taken further in the explanation in the following chapters.
|
||||||
--
|
--
|
||||||
-- 
|
-- 
|
||||||
--
|
--
|
||||||
-- The red coalition are the players, the blue coalition is the enemy.
|
-- The red coalition are the players, the blue coalition is the enemy.
|
||||||
--
|
--
|
||||||
-- Red reconnaissance vehicles and airborne units are detecting the targets.
|
-- Red reconnaissance vehicles and airborne units are detecting the targets.
|
||||||
-- We call this the RecceSet as explained above, which is a Set of Groups that
|
-- We call this the RecceSet as explained above, which is a Set of Groups that
|
||||||
-- have a group name starting with `Recce` (configured in the mission script).
|
-- have a group name starting with `Recce` (configured in the mission script).
|
||||||
--
|
--
|
||||||
-- Red attack units are responsible for executing the mission for the command center.
|
-- Red attack units are responsible for executing the mission for the command center.
|
||||||
-- We call this the AttackSet, which is a Set of Groups with a group name starting with `Attack` (configured in the mission script).
|
-- We call this the AttackSet, which is a Set of Groups with a group name starting with `Attack` (configured in the mission script).
|
||||||
-- These units are setup in this demonstration mission to be ground vehicles and airplanes.
|
-- These units are setup in this demonstration mission to be ground vehicles and airplanes.
|
||||||
-- For demonstration purposes, the attack airplane is stationed on the ground to explain
|
-- For demonstration purposes, the attack airplane is stationed on the ground to explain
|
||||||
-- the messages and the menus properly.
|
-- the messages and the menus properly.
|
||||||
-- Further test missions demonstrate the A2G task dispatcher from within air.
|
-- Further test missions demonstrate the A2G task dispatcher from within air.
|
||||||
--
|
--
|
||||||
-- Depending upon the detection results, the A2G dispatcher will create different tasks.
|
-- Depending upon the detection results, the A2G dispatcher will create different tasks.
|
||||||
--
|
--
|
||||||
-- # 0.1. SEAD Task
|
-- # 0.1. SEAD Task
|
||||||
--
|
--
|
||||||
-- A SEAD Task is dispatched when there are ground based Radar Emitters detected within an area.
|
-- A SEAD Task is dispatched when there are ground based Radar Emitters detected within an area.
|
||||||
--
|
--
|
||||||
-- 
|
-- 
|
||||||
--
|
--
|
||||||
-- - Once all Radar Emitting Units have been destroyed, the Task will convert into a BAI or CAS task!
|
-- - Once all Radar Emitting Units have been destroyed, the Task will convert into a BAI or CAS task!
|
||||||
-- - A CAS and BAI task may be converted into a SEAD task, once a radar has been detected within the area!
|
-- - A CAS and BAI task may be converted into a SEAD task, once a radar has been detected within the area!
|
||||||
--
|
--
|
||||||
-- # 0.2. CAS Task
|
-- # 0.2. CAS Task
|
||||||
--
|
--
|
||||||
-- A CAS Task is dispatched when there are no ground based Radar Emitters within the area, but there are friendly ground Units within 6 km from the enemy.
|
-- A CAS Task is dispatched when there are no ground based Radar Emitters within the area, but there are friendly ground Units within 6 km from the enemy.
|
||||||
--
|
--
|
||||||
-- 
|
-- 
|
||||||
--
|
--
|
||||||
-- - After the detection of the CAS task, if the friendly Units are destroyed, the CAS task will convert into a BAI task!
|
-- - After the detection of the CAS task, if the friendly Units are destroyed, the CAS task will convert into a BAI task!
|
||||||
-- - Only ground Units are taken into account. Airborne units are ships are not considered friendlies that require Close Air Support.
|
-- - Only ground Units are taken into account. Airborne units are ships are not considered friendlies that require Close Air Support.
|
||||||
--
|
--
|
||||||
-- # 0.3. BAI Task
|
-- # 0.3. BAI Task
|
||||||
--
|
--
|
||||||
-- A BAI Task is dispatched when there are no ground based Radar Emitters within the area, and there aren't friendly ground Units within 6 km from the enemy.
|
-- A BAI Task is dispatched when there are no ground based Radar Emitters within the area, and there aren't friendly ground Units within 6 km from the enemy.
|
||||||
--
|
--
|
||||||
-- 
|
-- 
|
||||||
--
|
--
|
||||||
-- - A BAI task may be converted into a CAS task if friendly Ground Units approach within 6 km range!
|
-- - A BAI task may be converted into a CAS task if friendly Ground Units approach within 6 km range!
|
||||||
--
|
--
|
||||||
-- # 1. Player Experience
|
-- # 1. Player Experience
|
||||||
--
|
--
|
||||||
-- The A2G dispatcher is residing under a @{CommandCenter}, which is orchestrating a @{Mission}.
|
-- The A2G dispatcher is residing under a @{CommandCenter}, which is orchestrating a @{Mission}.
|
||||||
-- As a result, you'll find for DCS World missions that implement the A2G dispatcher a **Command Center Menu** and under this one or more **Mission Menus**.
|
-- As a result, you'll find for DCS World missions that implement the A2G dispatcher a **Command Center Menu** and under this one or more **Mission Menus**.
|
||||||
--
|
--
|
||||||
-- For example, if there are 2 Command Centers (CC).
|
-- For example, if there are 2 Command Centers (CC).
|
||||||
-- Each CC is controlling a couple of Missions, the Radio Menu Structure could look like this:
|
-- Each CC is controlling a couple of Missions, the Radio Menu Structure could look like this:
|
||||||
--
|
--
|
||||||
-- Radio MENU Structure (F10. Other)
|
-- Radio MENU Structure (F10. Other)
|
||||||
--
|
--
|
||||||
-- F1. Command Center [Gori]
|
-- F1. Command Center [Gori]
|
||||||
-- F1. Mission "Alpha (Primary)"
|
-- F1. Mission "Alpha (Primary)"
|
||||||
-- F2. Mission "Beta (Secondary)"
|
-- F2. Mission "Beta (Secondary)"
|
||||||
-- F3. Mission "Gamma (Tactical)"
|
-- F3. Mission "Gamma (Tactical)"
|
||||||
-- F1. Command Center [Lima]
|
-- F1. Command Center [Lima]
|
||||||
-- F1. Mission "Overlord (High)"
|
-- F1. Mission "Overlord (High)"
|
||||||
--
|
--
|
||||||
-- Command Center [Gori] is controlling Mission "Alpha", "Beta", "Gamma". Alpha is the Primary mission, Beta the Secondary and there is a Tacical mission Gamma.
|
-- Command Center [Gori] is controlling Mission "Alpha", "Beta", "Gamma". Alpha is the Primary mission, Beta the Secondary and there is a Tactical mission Gamma.
|
||||||
-- Command Center [Lima] is controlling Missions "Overlord", which needs to be executed with High priority.
|
-- Command Center [Lima] is controlling Missions "Overlord", which needs to be executed with High priority.
|
||||||
--
|
--
|
||||||
-- ## 1.1. Mission Menu (Under the Command Center Menu)
|
-- ## 1.1. Mission Menu (Under the Command Center Menu)
|
||||||
--
|
--
|
||||||
-- The Mission Menu controls the information of the mission, including the:
|
-- The Mission Menu controls the information of the mission, including the:
|
||||||
--
|
--
|
||||||
-- - **Mission Briefing**: A briefing of the Mission in text, which will be shown as a message.
|
-- - **Mission Briefing**: A briefing of the Mission in text, which will be shown as a message.
|
||||||
-- - **Mark Task Locations**: A summary of each Task will be shown on the map as a marker.
|
-- - **Mark Task Locations**: A summary of each Task will be shown on the map as a marker.
|
||||||
-- - **Create Task Reports**: A menu to create various reports of the current tasks dispatched by the A2G dispatcher.
|
-- - **Create Task Reports**: A menu to create various reports of the current tasks dispatched by the A2G dispatcher.
|
||||||
-- - **Create Mission Reports**: A menu to create various reports on the current mission.
|
-- - **Create Mission Reports**: A menu to create various reports on the current mission.
|
||||||
--
|
--
|
||||||
-- For CC [Lima], Mission "Overlord", the menu structure could look like this:
|
-- For CC [Lima], Mission "Overlord", the menu structure could look like this:
|
||||||
--
|
--
|
||||||
-- Radio MENU Structure (F10. Other)
|
-- Radio MENU Structure (F10. Other)
|
||||||
--
|
--
|
||||||
-- F1. Command Center [Lima]
|
-- F1. Command Center [Lima]
|
||||||
-- F1. Mission "Overlord"
|
-- F1. Mission "Overlord"
|
||||||
-- F1. Mission Briefing
|
-- F1. Mission Briefing
|
||||||
-- F2. Mark Task Locations on Map
|
-- F2. Mark Task Locations on Map
|
||||||
-- F3. Task Reports
|
-- F3. Task Reports
|
||||||
-- F4. Mission Reports
|
-- F4. Mission Reports
|
||||||
--
|
--
|
||||||
-- 
|
-- 
|
||||||
--
|
--
|
||||||
-- ### 1.1.1. Mission Briefing Menu
|
-- ### 1.1.1. Mission Briefing Menu
|
||||||
--
|
--
|
||||||
-- The Mission Briefing Menu will show in text a summary description of the overall mission objectives and expectations.
|
-- The Mission Briefing Menu will show in text a summary description of the overall mission objectives and expectations.
|
||||||
-- Note that the Mission Briefing is not the briefing of a specific task, but rather provides an overall strategy and tactical situation,
|
-- Note that the Mission Briefing is not the briefing of a specific task, but rather provides an overall strategy and tactical situation,
|
||||||
-- and explains the mission goals.
|
-- and explains the mission goals.
|
||||||
--
|
--
|
||||||
--
|
--
|
||||||
-- ### 1.1.2. Mark Task Locations Menu
|
-- ### 1.1.2. Mark Task Locations Menu
|
||||||
--
|
--
|
||||||
-- The Mark Task Locations Menu will mark the location indications of the Tasks on the map, if this intelligence is known by the Command Center.
|
-- The Mark Task Locations Menu will mark the location indications of the Tasks on the map, if this intelligence is known by the Command Center.
|
||||||
-- For A2G tasks this information will always be know, but it can be that for other tasks a location intelligence will be less relevant.
|
-- For A2G tasks this information will always be know, but it can be that for other tasks a location intelligence will be less relevant.
|
||||||
-- Note that each Planned task and each Engaged task will be marked. Completed, Failed and Cancelled tasks are not marked.
|
-- Note that each Planned task and each Engaged task will be marked. Completed, Failed and Cancelled tasks are not marked.
|
||||||
-- Depending on the task type, a summary information is shown to bring to the player the relevant information for situational awareness.
|
-- Depending on the task type, a summary information is shown to bring to the player the relevant information for situational awareness.
|
||||||
--
|
--
|
||||||
-- ### 1.1.3. Task Reports Menu
|
-- ### 1.1.3. Task Reports Menu
|
||||||
--
|
--
|
||||||
-- The Task Reports Menu is a sub menu, that allows to create various reports:
|
-- The Task Reports Menu is a sub menu, that allows to create various reports:
|
||||||
--
|
--
|
||||||
-- - **Tasks Summary**: This report will list all the Tasks that are or were active within the mission, indicating its status.
|
-- - **Tasks Summary**: This report will list all the Tasks that are or were active within the mission, indicating its status.
|
||||||
-- - **Planned Tasks**: This report will list all the Tasks that are in status Planned, which are Tasks not assigned to any player, and are ready to be executed.
|
-- - **Planned Tasks**: This report will list all the Tasks that are in status Planned, which are Tasks not assigned to any player, and are ready to be executed.
|
||||||
-- - **Assigned Tasks**: This report will list all the Tasks that are in status Assigned, which are Tasks assigned to (a) player(s) and are currently executed.
|
-- - **Assigned Tasks**: This report will list all the Tasks that are in status Assigned, which are Tasks assigned to (a) player(s) and are currently executed.
|
||||||
-- - **Successful Tasks**: This report will list all the Tasks that are in status Success, which are Tasks executed by (a) player(s) and are completed successfully.
|
-- - **Successful Tasks**: This report will list all the Tasks that are in status Success, which are Tasks executed by (a) player(s) and are completed successfully.
|
||||||
-- - **Failed Tasks**: This report will list all the Tasks that are in status Success, which are Tasks executed by (a) player(s) and that have failed.
|
-- - **Failed Tasks**: This report will list all the Tasks that are in status Success, which are Tasks executed by (a) player(s) and that have failed.
|
||||||
--
|
--
|
||||||
-- The information shown of the tasks will vary according the underlying task type, but are self explanatory.
|
-- The information shown of the tasks will vary according the underlying task type, but are self explanatory.
|
||||||
--
|
--
|
||||||
-- For CC [Gori], Mission "Alpha", the Task Reports menu structure could look like this:
|
-- For CC [Gori], Mission "Alpha", the Task Reports menu structure could look like this:
|
||||||
--
|
--
|
||||||
-- Radio MENU Structure (F10. Other)
|
-- Radio MENU Structure (F10. Other)
|
||||||
--
|
--
|
||||||
-- F1. Command Center [Gori]
|
-- F1. Command Center [Gori]
|
||||||
-- F1. Mission "Alpha"
|
-- F1. Mission "Alpha"
|
||||||
-- F1. Mission Briefing
|
-- F1. Mission Briefing
|
||||||
@@ -188,21 +189,21 @@ do -- TASK_A2G_DISPATCHER
|
|||||||
-- F4. Successful Tasks
|
-- F4. Successful Tasks
|
||||||
-- F5. Failed Tasks
|
-- F5. Failed Tasks
|
||||||
-- F4. Mission Reports
|
-- F4. Mission Reports
|
||||||
--
|
--
|
||||||
-- Note that these reports provide an "overview" of the tasks. Detailed information of the task can be retrieved using the Detailed Report on the Task Menu.
|
-- Note that these reports provide an "overview" of the tasks. Detailed information of the task can be retrieved using the Detailed Report on the Task Menu.
|
||||||
-- (See later).
|
-- (See later).
|
||||||
--
|
--
|
||||||
-- ### 1.1.4. Mission Reports Menu
|
-- ### 1.1.4. Mission Reports Menu
|
||||||
--
|
--
|
||||||
-- The Mission Reports Menu is a sub menu, that provides options to retrieve further information on the current Mission:
|
-- The Mission Reports Menu is a sub menu, that provides options to retrieve further information on the current Mission:
|
||||||
--
|
--
|
||||||
-- - **Report Mission Progress**: Shows the progress of the current Mission. Each Task has a %-tage of completion.
|
-- - **Report Mission Progress**: Shows the progress of the current Mission. Each Task has a % of completion.
|
||||||
-- - **Report Players per Task**: Show which players are engaged on which Task within the Mission.
|
-- - **Report Players per Task**: Show which players are engaged on which Task within the Mission.
|
||||||
--
|
--
|
||||||
-- For CC |Gori|, Mission "Alpha", the Mission Reports menu structure could look like this:
|
-- For CC |Gori|, Mission "Alpha", the Mission Reports menu structure could look like this:
|
||||||
--
|
--
|
||||||
-- Radio MENU Structure (F10. Other)
|
-- Radio MENU Structure (F10. Other)
|
||||||
--
|
--
|
||||||
-- F1. Command Center [Gori]
|
-- F1. Command Center [Gori]
|
||||||
-- F1. Mission "Alpha"
|
-- F1. Mission "Alpha"
|
||||||
-- F1. Mission Briefing
|
-- F1. Mission Briefing
|
||||||
@@ -211,25 +212,25 @@ do -- TASK_A2G_DISPATCHER
|
|||||||
-- F4. Mission Reports
|
-- F4. Mission Reports
|
||||||
-- F1. Report Mission Progress
|
-- F1. Report Mission Progress
|
||||||
-- F2. Report Players per Task
|
-- F2. Report Players per Task
|
||||||
--
|
--
|
||||||
--
|
--
|
||||||
-- ## 1.2. Task Management Menus
|
-- ## 1.2. Task Management Menus
|
||||||
--
|
--
|
||||||
-- Very important to remember is: **Multiple Players can be assigned to the same Task, but from the player perspective, the Player can only be assigned to one Task per Mission at the same time!**
|
-- Very important to remember is: **Multiple Players can be assigned to the same Task, but from the player perspective, the Player can only be assigned to one Task per Mission at the same time!**
|
||||||
-- Consider this like the two major modes in which a player can be in. He can be free of tasks or he can be assigned to a Task.
|
-- Consider this like the two major modes in which a player can be in. He can be free of tasks or he can be assigned to a Task.
|
||||||
-- Depending on whether a Task has been Planned or Assigned to a Player (Group),
|
-- Depending on whether a Task has been Planned or Assigned to a Player (Group),
|
||||||
-- **the Mission Menu will contain extra Menus to control specific Tasks.**
|
-- **the Mission Menu will contain extra Menus to control specific Tasks.**
|
||||||
--
|
--
|
||||||
-- #### 1.2.1. Join a Planned Task
|
-- #### 1.2.1. Join a Planned Task
|
||||||
--
|
--
|
||||||
-- If the Player has not yet been assigned to a Task within the Mission, the Mission Menu will contain additionally a:
|
-- If the Player has not yet been assigned to a Task within the Mission, the Mission Menu will contain additionally a:
|
||||||
--
|
--
|
||||||
-- - Join Planned Task Menu: This menu structure allows the player to join a planned task (a Task with status Planned).
|
-- - Join Planned Task Menu: This menu structure allows the player to join a planned task (a Task with status Planned).
|
||||||
--
|
--
|
||||||
-- For CC |Gori|, Mission "Alpha", the menu structure could look like this:
|
-- For CC |Gori|, Mission "Alpha", the menu structure could look like this:
|
||||||
--
|
--
|
||||||
-- Radio MENU Structure (F10. Other)
|
-- Radio MENU Structure (F10. Other)
|
||||||
--
|
--
|
||||||
-- F1. Command Center [Gori]
|
-- F1. Command Center [Gori]
|
||||||
-- F1. Mission "Alpha"
|
-- F1. Mission "Alpha"
|
||||||
-- F1. Mission Briefing
|
-- F1. Mission Briefing
|
||||||
@@ -237,23 +238,23 @@ do -- TASK_A2G_DISPATCHER
|
|||||||
-- F3. Task Reports
|
-- F3. Task Reports
|
||||||
-- F4. Mission Reports
|
-- F4. Mission Reports
|
||||||
-- F5. Join Planned Task
|
-- F5. Join Planned Task
|
||||||
--
|
--
|
||||||
-- **The F5. Join Planned Task allows the player to join a Planned Task and take an engagement in the running Mission.**
|
-- **The F5. Join Planned Task allows the player to join a Planned Task and take an engagement in the running Mission.**
|
||||||
--
|
--
|
||||||
-- #### 1.2.2. Manage an Assigned Task
|
-- #### 1.2.2. Manage an Assigned Task
|
||||||
--
|
--
|
||||||
-- If the Player has been assigned to one Task within the Mission, the Mission Menu will contain an extra:
|
-- If the Player has been assigned to one Task within the Mission, the Mission Menu will contain an extra:
|
||||||
--
|
--
|
||||||
-- - Assigned Task __TaskName__ Menu: This menu structure allows the player to take actions on the currently engaged task.
|
-- - Assigned Task __TaskName__ Menu: This menu structure allows the player to take actions on the currently engaged task.
|
||||||
--
|
--
|
||||||
-- In this example, the Group currently seated by the player is not assigned yet to a Task.
|
-- In this example, the Group currently seated by the player is not assigned yet to a Task.
|
||||||
-- The Player has the option to assign itself to a Planned Task using menu option F5 under the Mission Menu "Alpha".
|
-- The Player has the option to assign itself to a Planned Task using menu option F5 under the Mission Menu "Alpha".
|
||||||
--
|
--
|
||||||
-- This would be an example menu structure,
|
-- This would be an example menu structure,
|
||||||
-- for CC |Gori|, Mission "Alpha", when a player would have joined Task CAS.001:
|
-- for CC |Gori|, Mission "Alpha", when a player would have joined Task CAS.001:
|
||||||
--
|
--
|
||||||
-- Radio MENU Structure (F10. Other)
|
-- Radio MENU Structure (F10. Other)
|
||||||
--
|
--
|
||||||
-- F1. Command Center [Gori]
|
-- F1. Command Center [Gori]
|
||||||
-- F1. Mission "Alpha"
|
-- F1. Mission "Alpha"
|
||||||
-- F1. Mission Briefing
|
-- F1. Mission Briefing
|
||||||
@@ -261,26 +262,25 @@ do -- TASK_A2G_DISPATCHER
|
|||||||
-- F3. Task Reports
|
-- F3. Task Reports
|
||||||
-- F4. Mission Reports
|
-- F4. Mission Reports
|
||||||
-- F5. Assigned Task CAS.001
|
-- F5. Assigned Task CAS.001
|
||||||
--
|
--
|
||||||
-- **The F5. Assigned Task __TaskName__ allows the player to control the current Assigned Task and take further actions.**
|
-- **The F5. Assigned Task __TaskName__ allows the player to control the current Assigned Task and take further actions.**
|
||||||
--
|
--
|
||||||
--
|
|
||||||
-- ## 1.3. Join Planned Task Menu
|
-- ## 1.3. Join Planned Task Menu
|
||||||
--
|
--
|
||||||
-- The Join Planned Task Menu contains the different Planned A2G Tasks **in a structured Menu Hierarchy**.
|
-- The Join Planned Task Menu contains the different Planned A2G Tasks **in a structured Menu Hierarchy**.
|
||||||
-- The Menu Hierarchy is structuring the Tasks per **Task Type**, and then by **Task Name (ID)**.
|
-- The Menu Hierarchy is structuring the Tasks per **Task Type**, and then by **Task Name (ID)**.
|
||||||
--
|
--
|
||||||
-- For example, for CC [Gori], Mission "Alpha",
|
-- For example, for CC [Gori], Mission "Alpha",
|
||||||
-- if a Mission "ALpha" contains 5 Planned Tasks, which would be:
|
-- if a Mission "ALpha" contains 5 Planned Tasks, which would be:
|
||||||
--
|
--
|
||||||
-- - 2 CAS Tasks
|
-- - 2 CAS Tasks
|
||||||
-- - 1 BAI Task
|
-- - 1 BAI Task
|
||||||
-- - 2 SEAD Tasks
|
-- - 2 SEAD Tasks
|
||||||
--
|
--
|
||||||
-- the Join Planned Task Menu Hierarchy could look like this:
|
-- the Join Planned Task Menu Hierarchy could look like this:
|
||||||
--
|
--
|
||||||
-- Radio MENU Structure (F10. Other)
|
-- Radio MENU Structure (F10. Other)
|
||||||
--
|
--
|
||||||
-- F1. Command Center [Gori]
|
-- F1. Command Center [Gori]
|
||||||
-- F1. Mission "Alpha"
|
-- F1. Mission "Alpha"
|
||||||
-- F1. Mission Briefing
|
-- F1. Mission Briefing
|
||||||
@@ -296,26 +296,26 @@ do -- TASK_A2G_DISPATCHER
|
|||||||
-- F1. SEAD.003
|
-- F1. SEAD.003
|
||||||
-- F2. SEAD.004
|
-- F2. SEAD.004
|
||||||
-- F3. SEAD.005
|
-- F3. SEAD.005
|
||||||
--
|
--
|
||||||
-- An example from within a running simulation:
|
-- An example from within a running simulation:
|
||||||
--
|
--
|
||||||
-- 
|
-- 
|
||||||
--
|
--
|
||||||
-- Each Task Type Menu would have a list of the Task Menus underneath.
|
-- Each Task Type Menu would have a list of the Task Menus underneath.
|
||||||
-- Each Task Menu (eg. `CAS.001`) has a **detailed Task Menu structure to control the specific task**!
|
-- Each Task Menu (eg. `CAS.001`) has a **detailed Task Menu structure to control the specific task**!
|
||||||
--
|
--
|
||||||
-- ### 1.3.1. Planned Task Menu
|
-- ### 1.3.1. Planned Task Menu
|
||||||
--
|
--
|
||||||
-- Each Planned Task Menu will allow for the following actions:
|
-- Each Planned Task Menu will allow for the following actions:
|
||||||
--
|
--
|
||||||
-- - Report Task Details: Provides a detailed report on the Planned Task.
|
-- - Report Task Details: Provides a detailed report on the Planned Task.
|
||||||
-- - Mark Task Location on Map: Mark the approximate location of the Task on the Map, if relevant.
|
-- - Mark Task Location on Map: Mark the approximate location of the Task on the Map, if relevant.
|
||||||
-- - Join Task: Join the Task. This is THE menu option to let a Player join the Task, and to engage within the Mission.
|
-- - Join Task: Join the Task. This is THE menu option to let a Player join the Task, and to engage within the Mission.
|
||||||
--
|
--
|
||||||
-- The Join Planned Task Menu could look like this for for CC |Gori|, Mission "Alpha":
|
-- The Join Planned Task Menu could look like this for for CC |Gori|, Mission "Alpha":
|
||||||
--
|
--
|
||||||
-- Radio MENU Structure (F10. Other)
|
-- Radio MENU Structure (F10. Other)
|
||||||
--
|
--
|
||||||
-- F1. Command Center |Gori|
|
-- F1. Command Center |Gori|
|
||||||
-- F1. Mission "Alpha"
|
-- F1. Mission "Alpha"
|
||||||
-- F1. Mission Briefing
|
-- F1. Mission Briefing
|
||||||
@@ -328,22 +328,22 @@ do -- TASK_A2G_DISPATCHER
|
|||||||
-- F1. Report Task Details
|
-- F1. Report Task Details
|
||||||
-- F2. Mark Task Location on Map
|
-- F2. Mark Task Location on Map
|
||||||
-- F3. Join Task
|
-- F3. Join Task
|
||||||
--
|
--
|
||||||
-- **The Join Task is THE menu option to let a Player join the Task, and to engage within the Mission.**
|
-- **The Join Task is THE menu option to let a Player join the Task, and to engage within the Mission.**
|
||||||
--
|
--
|
||||||
--
|
--
|
||||||
-- ## 1.4. Assigned Task Menu
|
-- ## 1.4. Assigned Task Menu
|
||||||
--
|
--
|
||||||
-- The Assigned Task Menu allows to control the **current assigned task** within the Mission.
|
-- The Assigned Task Menu allows to control the **current assigned task** within the Mission.
|
||||||
--
|
--
|
||||||
-- Depending on the Type of Task, the following menu options will be available:
|
-- Depending on the Type of Task, the following menu options will be available:
|
||||||
--
|
--
|
||||||
-- - **Report Task Details**: Provides a detailed report on the Planned Task.
|
-- - **Report Task Details**: Provides a detailed report on the Planned Task.
|
||||||
-- - **Mark Task Location on Map**: Mark the approximate location of the Task on the Map, if relevant.
|
-- - **Mark Task Location on Map**: Mark the approximate location of the Task on the Map, if relevant.
|
||||||
-- - **Abort Task: Abort the current assigned Task:** This menu option lets the player abort the Task.
|
-- - **Abort Task: Abort the current assigned Task:** This menu option lets the player abort the Task.
|
||||||
--
|
--
|
||||||
-- For example, for CC |Gori|, Mission "Alpha", the Assigned Menu could be:
|
-- For example, for CC |Gori|, Mission "Alpha", the Assigned Menu could be:
|
||||||
--
|
--
|
||||||
-- F1. Command Center |Gori|
|
-- F1. Command Center |Gori|
|
||||||
-- F1. Mission "Alpha"
|
-- F1. Mission "Alpha"
|
||||||
-- F1. Mission Briefing
|
-- F1. Mission Briefing
|
||||||
@@ -354,90 +354,89 @@ do -- TASK_A2G_DISPATCHER
|
|||||||
-- F1. Report Task Details
|
-- F1. Report Task Details
|
||||||
-- F2. Mark Task Location on Map
|
-- F2. Mark Task Location on Map
|
||||||
-- F3. Abort Task
|
-- F3. Abort Task
|
||||||
--
|
--
|
||||||
-- Task abortion will result in the Task to be Cancelled, and the Task **may** be **Replanned**.
|
-- Task abortion will result in the Task to be Cancelled, and the Task **may** be **Replanned**.
|
||||||
-- However, this will depend on the setup of each Mission.
|
-- However, this will depend on the setup of each Mission.
|
||||||
--
|
--
|
||||||
-- ## 1.5. Messages
|
-- ## 1.5. Messages
|
||||||
--
|
--
|
||||||
-- During game play, different messages are displayed.
|
-- During game play, different messages are displayed.
|
||||||
-- These messages provide an update of the achievements made, and the state wherein the task is.
|
-- These messages provide an update of the achievements made, and the state wherein the task is.
|
||||||
--
|
--
|
||||||
-- The various reports can be used also to retrieve the current status of the mission and its tasks.
|
-- The various reports can be used also to retrieve the current status of the mission and its tasks.
|
||||||
--
|
--
|
||||||
-- 
|
-- 
|
||||||
--
|
--
|
||||||
-- The @{Settings} menu provides additional options to control the timing of the messages.
|
-- The @{Settings} menu provides additional options to control the timing of the messages.
|
||||||
-- There are:
|
-- There are:
|
||||||
--
|
--
|
||||||
-- - Status messages, which are quick status updates. The settings menu allows to switch off these messages.
|
-- - Status messages, which are quick status updates. The settings menu allows to switch off these messages.
|
||||||
-- - Information messages, which are shown a bit longer, as they contain important information.
|
-- - Information messages, which are shown a bit longer, as they contain important information.
|
||||||
-- - Summary reports, which are quick reports showing a high level summary.
|
-- - Summary reports, which are quick reports showing a high level summary.
|
||||||
-- - Overview reports, which are providing the essential information. It provides an overview of a greater thing, and may take a bit of time to read.
|
-- - Overview reports, which are providing the essential information. It provides an overview of a greater thing, and may take a bit of time to read.
|
||||||
-- - Detailed reports, which provide with very detailed information. It takes a bit longer to read those reports, so the display of those could be a bit longer.
|
-- - Detailed reports, which provide with very detailed information. It takes a bit longer to read those reports, so the display of those could be a bit longer.
|
||||||
--
|
--
|
||||||
-- # 2. TASK\_A2G\_DISPATCHER constructor
|
-- # 2. TASK\_A2G\_DISPATCHER constructor
|
||||||
--
|
--
|
||||||
-- The @{#TASK_A2G_DISPATCHER.New}() method creates a new TASK\_A2G\_DISPATCHER instance.
|
-- The @{#TASK_A2G_DISPATCHER.New}() method creates a new TASK\_A2G\_DISPATCHER instance.
|
||||||
--
|
--
|
||||||
-- # 3. Usage
|
-- # 3. Usage
|
||||||
--
|
--
|
||||||
-- To use the TASK\_A2G\_DISPATCHER class, you need:
|
-- To use the TASK\_A2G\_DISPATCHER class, you need:
|
||||||
--
|
--
|
||||||
-- - A @{CommandCenter} object. The master communication channel.
|
-- - A @{CommandCenter} object. The master communication channel.
|
||||||
-- - A @{Mission} object. Each task belongs to a Mission.
|
-- - A @{Mission} object. Each task belongs to a Mission.
|
||||||
-- - A @{Detection} object. There are several detection grouping methods to choose from.
|
-- - A @{Detection} object. There are several detection grouping methods to choose from.
|
||||||
-- - A @{Task_A2G_Dispatcher} object. The master A2G task dispatcher.
|
-- - A @{Task_A2G_Dispatcher} object. The master A2G task dispatcher.
|
||||||
-- - A @{Set} of @{Wrapper.Group} objects that will detect the emeny, the RecceSet. This is attached to the @{Detection} object.
|
-- - A @{Set} of @{Wrapper.Group} objects that will detect the enemy, the RecceSet. This is attached to the @{Detection} object.
|
||||||
-- - A @{Set} ob @{Wrapper.Group} objects that will attack the enemy, the AttackSet. This is attached to the @{Task_A2G_Dispatcher} object.
|
-- - A @{Set} ob @{Wrapper.Group} objects that will attack the enemy, the AttackSet. This is attached to the @{Task_A2G_Dispatcher} object.
|
||||||
--
|
|
||||||
-- Below an example mission declaration that is defines a Task A2G Dispatcher object.
|
|
||||||
--
|
--
|
||||||
-- -- Declare the Command Center
|
-- Below an example mission declaration that is defines a Task A2G Dispatcher object.
|
||||||
|
--
|
||||||
|
-- -- Declare the Command Center
|
||||||
-- local HQ = GROUP
|
-- local HQ = GROUP
|
||||||
-- :FindByName( "HQ", "Bravo HQ" )
|
-- :FindByName( "HQ", "Bravo HQ" )
|
||||||
--
|
--
|
||||||
-- local CommandCenter = COMMANDCENTER
|
-- local CommandCenter = COMMANDCENTER
|
||||||
-- :New( HQ, "Lima" )
|
-- :New( HQ, "Lima" )
|
||||||
--
|
--
|
||||||
-- -- Declare the Mission for the Command Center.
|
-- -- Declare the Mission for the Command Center.
|
||||||
-- local Mission = MISSION
|
-- local Mission = MISSION
|
||||||
-- :New( CommandCenter, "Overlord", "High", "Attack Detect Mission Briefing", coalition.side.RED )
|
-- :New( CommandCenter, "Overlord", "High", "Attack Detect Mission Briefing", coalition.side.RED )
|
||||||
--
|
--
|
||||||
-- -- Define the RecceSet that will detect the enemy.
|
-- -- Define the RecceSet that will detect the enemy.
|
||||||
-- local RecceSet = SET_GROUP
|
-- local RecceSet = SET_GROUP
|
||||||
-- :New()
|
-- :New()
|
||||||
-- :FilterPrefixes( "FAC" )
|
-- :FilterPrefixes( "FAC" )
|
||||||
-- :FilterCoalitions("red")
|
-- :FilterCoalitions("red")
|
||||||
-- :FilterStart()
|
-- :FilterStart()
|
||||||
--
|
--
|
||||||
-- -- Setup the detection. We use DETECTION_AREAS to detect and group the enemies within areas of 3 km radius.
|
-- -- Setup the detection. We use DETECTION_AREAS to detect and group the enemies within areas of 3 km radius.
|
||||||
-- local DetectionAreas = DETECTION_AREAS
|
-- local DetectionAreas = DETECTION_AREAS
|
||||||
-- :New( RecceSet, 3000 ) -- The RecceSet will detect the enemies.
|
-- :New( RecceSet, 3000 ) -- The RecceSet will detect the enemies.
|
||||||
--
|
--
|
||||||
-- -- Setup the AttackSet, which is a SET_GROUP.
|
-- -- Setup the AttackSet, which is a SET_GROUP.
|
||||||
-- -- The SET_GROUP is a dynamic collection of GROUP objects.
|
-- -- The SET_GROUP is a dynamic collection of GROUP objects.
|
||||||
-- local AttackSet = SET_GROUP
|
-- local AttackSet = SET_GROUP
|
||||||
-- :New() -- Create the SET_GROUP object.
|
-- :New() -- Create the SET_GROUP object.
|
||||||
-- :FilterCoalitions( "red" ) -- Only incorporate the RED coalitions.
|
-- :FilterCoalitions( "red" ) -- Only incorporate the RED coalitions.
|
||||||
-- :FilterPrefixes( "Attack" ) -- Only incorporate groups that start with the name Attack.
|
-- :FilterPrefixes( "Attack" ) -- Only incorporate groups that start with the name Attack.
|
||||||
-- :FilterStart() -- Enable the dynamic filtering. From this moment the AttackSet will contain all groups that are red and start with the name Attack.
|
-- :FilterStart() -- Enable the dynamic filtering. From this moment the AttackSet will contain all groups that are red and start with the name Attack.
|
||||||
--
|
--
|
||||||
-- -- Now we have everything to setup the main A2G TaskDispatcher.
|
-- -- Now we have everything to setup the main A2G TaskDispatcher.
|
||||||
-- TaskDispatcher = TASK_A2G_DISPATCHER
|
-- TaskDispatcher = TASK_A2G_DISPATCHER
|
||||||
-- :New( Mission, AttackSet, DetectionAreas ) -- We assign the TaskDispatcher under Mission. The AttackSet will engage the enemy and will recieve the dispatched Tasks. The DetectionAreas will report any detected enemies to the TaskDispatcher.
|
-- :New( Mission, AttackSet, DetectionAreas ) -- We assign the TaskDispatcher under Mission. The AttackSet will engage the enemy and will receive the dispatched Tasks. The DetectionAreas will report any detected enemies to the TaskDispatcher.
|
||||||
--
|
--
|
||||||
--
|
--
|
||||||
--
|
--
|
||||||
-- @field #TASK_A2G_DISPATCHER
|
-- @field #TASK_A2G_DISPATCHER
|
||||||
TASK_A2G_DISPATCHER = {
|
TASK_A2G_DISPATCHER = {
|
||||||
ClassName = "TASK_A2G_DISPATCHER",
|
ClassName = "TASK_A2G_DISPATCHER",
|
||||||
Mission = nil,
|
Mission = nil,
|
||||||
Detection = nil,
|
Detection = nil,
|
||||||
Tasks = {},
|
Tasks = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
--- TASK_A2G_DISPATCHER constructor.
|
--- TASK_A2G_DISPATCHER constructor.
|
||||||
-- @param #TASK_A2G_DISPATCHER self
|
-- @param #TASK_A2G_DISPATCHER self
|
||||||
-- @param Tasking.Mission#MISSION Mission The mission for which the task dispatching is done.
|
-- @param Tasking.Mission#MISSION Mission The mission for which the task dispatching is done.
|
||||||
@@ -445,18 +444,18 @@ do -- TASK_A2G_DISPATCHER
|
|||||||
-- @param Functional.Detection#DETECTION_BASE Detection The detection results that are used to dynamically assign new tasks to human players.
|
-- @param Functional.Detection#DETECTION_BASE Detection The detection results that are used to dynamically assign new tasks to human players.
|
||||||
-- @return #TASK_A2G_DISPATCHER self
|
-- @return #TASK_A2G_DISPATCHER self
|
||||||
function TASK_A2G_DISPATCHER:New( Mission, SetGroup, Detection )
|
function TASK_A2G_DISPATCHER:New( Mission, SetGroup, Detection )
|
||||||
|
|
||||||
-- Inherits from DETECTION_MANAGER
|
-- Inherits from DETECTION_MANAGER
|
||||||
local self = BASE:Inherit( self, DETECTION_MANAGER:New( SetGroup, Detection ) ) -- #TASK_A2G_DISPATCHER
|
local self = BASE:Inherit( self, DETECTION_MANAGER:New( SetGroup, Detection ) ) -- #TASK_A2G_DISPATCHER
|
||||||
|
|
||||||
self.Detection = Detection
|
self.Detection = Detection
|
||||||
self.Mission = Mission
|
self.Mission = Mission
|
||||||
self.FlashNewTask = true --set to false to suppress flash messages
|
self.FlashNewTask = true -- set to false to suppress flash messages
|
||||||
|
|
||||||
self.Detection:FilterCategories( { Unit.Category.GROUND_UNIT } )
|
self.Detection:FilterCategories( { Unit.Category.GROUND_UNIT } )
|
||||||
|
|
||||||
self:AddTransition( "Started", "Assign", "Started" )
|
self:AddTransition( "Started", "Assign", "Started" )
|
||||||
|
|
||||||
--- OnAfter Transition Handler for Event Assign.
|
--- OnAfter Transition Handler for Event Assign.
|
||||||
-- @function [parent=#TASK_A2G_DISPATCHER] OnAfterAssign
|
-- @function [parent=#TASK_A2G_DISPATCHER] OnAfterAssign
|
||||||
-- @param #TASK_A2G_DISPATCHER self
|
-- @param #TASK_A2G_DISPATCHER self
|
||||||
@@ -466,19 +465,19 @@ do -- TASK_A2G_DISPATCHER
|
|||||||
-- @param Tasking.Task_A2G#TASK_A2G Task
|
-- @param Tasking.Task_A2G#TASK_A2G Task
|
||||||
-- @param Wrapper.Unit#UNIT TaskUnit
|
-- @param Wrapper.Unit#UNIT TaskUnit
|
||||||
-- @param #string PlayerName
|
-- @param #string PlayerName
|
||||||
|
|
||||||
self:__Start( 5 )
|
self:__Start( 5 )
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Set flashing player messages on or off
|
--- Set flashing player messages on or off
|
||||||
-- @param #TASK_A2G_DISPATCHER self
|
-- @param #TASK_A2G_DISPATCHER self
|
||||||
-- @param #boolean onoff Set messages on (true) or off (false)
|
-- @param #boolean onoff Set messages on (true) or off (false)
|
||||||
function TASK_A2G_DISPATCHER:SetSendMessages( onoff )
|
function TASK_A2G_DISPATCHER:SetSendMessages( onoff )
|
||||||
self.FlashNewTask = onoff
|
self.FlashNewTask = onoff
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Creates a SEAD task when there are targets for it.
|
--- Creates a SEAD task when there are targets for it.
|
||||||
-- @param #TASK_A2G_DISPATCHER self
|
-- @param #TASK_A2G_DISPATCHER self
|
||||||
-- @param Functional.Detection#DETECTION_AREAS.DetectedItem DetectedItem
|
-- @param Functional.Detection#DETECTION_AREAS.DetectedItem DetectedItem
|
||||||
@@ -486,7 +485,7 @@ do -- TASK_A2G_DISPATCHER
|
|||||||
-- @return #nil If there are no targets to be set.
|
-- @return #nil If there are no targets to be set.
|
||||||
function TASK_A2G_DISPATCHER:EvaluateSEAD( DetectedItem )
|
function TASK_A2G_DISPATCHER:EvaluateSEAD( DetectedItem )
|
||||||
self:F( { DetectedItem.ItemID } )
|
self:F( { DetectedItem.ItemID } )
|
||||||
|
|
||||||
local DetectedSet = DetectedItem.Set
|
local DetectedSet = DetectedItem.Set
|
||||||
local DetectedZone = DetectedItem.Zone
|
local DetectedZone = DetectedItem.Zone
|
||||||
|
|
||||||
@@ -500,10 +499,10 @@ do -- TASK_A2G_DISPATCHER
|
|||||||
TargetSetUnit:SetDatabase( DetectedSet )
|
TargetSetUnit:SetDatabase( DetectedSet )
|
||||||
TargetSetUnit:FilterHasSEAD()
|
TargetSetUnit:FilterHasSEAD()
|
||||||
TargetSetUnit:FilterOnce() -- Filter but don't do any events!!! Elements are added manually upon each detection.
|
TargetSetUnit:FilterOnce() -- Filter but don't do any events!!! Elements are added manually upon each detection.
|
||||||
|
|
||||||
return TargetSetUnit
|
return TargetSetUnit
|
||||||
end
|
end
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -514,11 +513,10 @@ do -- TASK_A2G_DISPATCHER
|
|||||||
-- @return #nil If there are no targets to be set.
|
-- @return #nil If there are no targets to be set.
|
||||||
function TASK_A2G_DISPATCHER:EvaluateCAS( DetectedItem )
|
function TASK_A2G_DISPATCHER:EvaluateCAS( DetectedItem )
|
||||||
self:F( { DetectedItem.ItemID } )
|
self:F( { DetectedItem.ItemID } )
|
||||||
|
|
||||||
local DetectedSet = DetectedItem.Set
|
local DetectedSet = DetectedItem.Set
|
||||||
local DetectedZone = DetectedItem.Zone
|
local DetectedZone = DetectedItem.Zone
|
||||||
|
|
||||||
|
|
||||||
-- Determine if the set has ground units.
|
-- Determine if the set has ground units.
|
||||||
-- There should be ground unit friendlies nearby. Airborne units are valid friendlies types.
|
-- There should be ground unit friendlies nearby. Airborne units are valid friendlies types.
|
||||||
-- And there shouldn't be any radar.
|
-- And there shouldn't be any radar.
|
||||||
@@ -532,13 +530,13 @@ do -- TASK_A2G_DISPATCHER
|
|||||||
local TargetSetUnit = SET_UNIT:New()
|
local TargetSetUnit = SET_UNIT:New()
|
||||||
TargetSetUnit:SetDatabase( DetectedSet )
|
TargetSetUnit:SetDatabase( DetectedSet )
|
||||||
TargetSetUnit:FilterOnce() -- Filter but don't do any events!!! Elements are added manually upon each detection.
|
TargetSetUnit:FilterOnce() -- Filter but don't do any events!!! Elements are added manually upon each detection.
|
||||||
|
|
||||||
return TargetSetUnit
|
return TargetSetUnit
|
||||||
end
|
end
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Creates a BAI task when there are targets for it.
|
--- Creates a BAI task when there are targets for it.
|
||||||
-- @param #TASK_A2G_DISPATCHER self
|
-- @param #TASK_A2G_DISPATCHER self
|
||||||
-- @param Functional.Detection#DETECTION_AREAS.DetectedItem DetectedItem
|
-- @param Functional.Detection#DETECTION_AREAS.DetectedItem DetectedItem
|
||||||
@@ -546,11 +544,10 @@ do -- TASK_A2G_DISPATCHER
|
|||||||
-- @return #nil If there are no targets to be set.
|
-- @return #nil If there are no targets to be set.
|
||||||
function TASK_A2G_DISPATCHER:EvaluateBAI( DetectedItem, FriendlyCoalition )
|
function TASK_A2G_DISPATCHER:EvaluateBAI( DetectedItem, FriendlyCoalition )
|
||||||
self:F( { DetectedItem.ItemID } )
|
self:F( { DetectedItem.ItemID } )
|
||||||
|
|
||||||
local DetectedSet = DetectedItem.Set
|
local DetectedSet = DetectedItem.Set
|
||||||
local DetectedZone = DetectedItem.Zone
|
local DetectedZone = DetectedItem.Zone
|
||||||
|
|
||||||
|
|
||||||
-- Determine if the set has ground units.
|
-- Determine if the set has ground units.
|
||||||
-- There shouldn't be any ground unit friendlies nearby.
|
-- There shouldn't be any ground unit friendlies nearby.
|
||||||
-- And there shouldn't be any radar.
|
-- And there shouldn't be any radar.
|
||||||
@@ -564,19 +561,18 @@ do -- TASK_A2G_DISPATCHER
|
|||||||
local TargetSetUnit = SET_UNIT:New()
|
local TargetSetUnit = SET_UNIT:New()
|
||||||
TargetSetUnit:SetDatabase( DetectedSet )
|
TargetSetUnit:SetDatabase( DetectedSet )
|
||||||
TargetSetUnit:FilterOnce() -- Filter but don't do any events!!! Elements are added manually upon each detection.
|
TargetSetUnit:FilterOnce() -- Filter but don't do any events!!! Elements are added manually upon each detection.
|
||||||
|
|
||||||
return TargetSetUnit
|
return TargetSetUnit
|
||||||
end
|
end
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
function TASK_A2G_DISPATCHER:RemoveTask( TaskIndex )
|
function TASK_A2G_DISPATCHER:RemoveTask( TaskIndex )
|
||||||
self.Mission:RemoveTask( self.Tasks[TaskIndex] )
|
self.Mission:RemoveTask( self.Tasks[TaskIndex] )
|
||||||
self.Tasks[TaskIndex] = nil
|
self.Tasks[TaskIndex] = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Evaluates the removal of the Task from the Mission.
|
--- Evaluates the removal of the Task from the Mission.
|
||||||
-- Can only occur when the DetectedItem is Changed AND the state of the Task is "Planned".
|
-- Can only occur when the DetectedItem is Changed AND the state of the Task is "Planned".
|
||||||
-- @param #TASK_A2G_DISPATCHER self
|
-- @param #TASK_A2G_DISPATCHER self
|
||||||
@@ -586,17 +582,16 @@ do -- TASK_A2G_DISPATCHER
|
|||||||
-- @param #boolean DetectedItemChange
|
-- @param #boolean DetectedItemChange
|
||||||
-- @return Tasking.Task#TASK
|
-- @return Tasking.Task#TASK
|
||||||
function TASK_A2G_DISPATCHER:EvaluateRemoveTask( Mission, Task, TaskIndex, DetectedItemChanged )
|
function TASK_A2G_DISPATCHER:EvaluateRemoveTask( Mission, Task, TaskIndex, DetectedItemChanged )
|
||||||
|
|
||||||
if Task then
|
if Task then
|
||||||
if ( Task:IsStatePlanned() and DetectedItemChanged == true ) or Task:IsStateCancelled() then
|
if (Task:IsStatePlanned() and DetectedItemChanged == true) or Task:IsStateCancelled() then
|
||||||
--self:F( "Removing Tasking: " .. Task:GetTaskName() )
|
-- self:F( "Removing Tasking: " .. Task:GetTaskName() )
|
||||||
self:RemoveTask( TaskIndex )
|
self:RemoveTask( TaskIndex )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return Task
|
return Task
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Assigns tasks in relation to the detected items to the @{Core.Set#SET_GROUP}.
|
--- Assigns tasks in relation to the detected items to the @{Core.Set#SET_GROUP}.
|
||||||
-- @param #TASK_A2G_DISPATCHER self
|
-- @param #TASK_A2G_DISPATCHER self
|
||||||
@@ -604,15 +599,15 @@ do -- TASK_A2G_DISPATCHER
|
|||||||
-- @return #boolean Return true if you want the task assigning to continue... false will cancel the loop.
|
-- @return #boolean Return true if you want the task assigning to continue... false will cancel the loop.
|
||||||
function TASK_A2G_DISPATCHER:ProcessDetected( Detection )
|
function TASK_A2G_DISPATCHER:ProcessDetected( Detection )
|
||||||
self:F()
|
self:F()
|
||||||
|
|
||||||
local AreaMsg = {}
|
local AreaMsg = {}
|
||||||
local TaskMsg = {}
|
local TaskMsg = {}
|
||||||
local ChangeMsg = {}
|
local ChangeMsg = {}
|
||||||
|
|
||||||
local Mission = self.Mission
|
local Mission = self.Mission
|
||||||
|
|
||||||
if Mission:IsIDLE() or Mission:IsENGAGED() then
|
if Mission:IsIDLE() or Mission:IsENGAGED() then
|
||||||
|
|
||||||
local TaskReport = REPORT:New()
|
local TaskReport = REPORT:New()
|
||||||
|
|
||||||
-- Checking the task queue for the dispatcher, and removing any obsolete task!
|
-- Checking the task queue for the dispatcher, and removing any obsolete task!
|
||||||
@@ -634,21 +629,21 @@ do -- TASK_A2G_DISPATCHER
|
|||||||
|
|
||||||
--- First we need to the detected targets.
|
--- First we need to the detected targets.
|
||||||
for DetectedItemID, DetectedItem in pairs( Detection:GetDetectedItems() ) do
|
for DetectedItemID, DetectedItem in pairs( Detection:GetDetectedItems() ) do
|
||||||
|
|
||||||
local DetectedItem = DetectedItem -- Functional.Detection#DETECTION_BASE.DetectedItem
|
local DetectedItem = DetectedItem -- Functional.Detection#DETECTION_BASE.DetectedItem
|
||||||
local DetectedSet = DetectedItem.Set -- Core.Set#SET_UNIT
|
local DetectedSet = DetectedItem.Set -- Core.Set#SET_UNIT
|
||||||
local DetectedZone = DetectedItem.Zone
|
local DetectedZone = DetectedItem.Zone
|
||||||
--self:F( { "Targets in DetectedItem", DetectedItem.ItemID, DetectedSet:Count(), tostring( DetectedItem ) } )
|
-- self:F( { "Targets in DetectedItem", DetectedItem.ItemID, DetectedSet:Count(), tostring( DetectedItem ) } )
|
||||||
--DetectedSet:Flush( self )
|
-- DetectedSet:Flush( self )
|
||||||
|
|
||||||
local DetectedItemID = DetectedItem.ID
|
local DetectedItemID = DetectedItem.ID
|
||||||
local TaskIndex = DetectedItem.Index
|
local TaskIndex = DetectedItem.Index
|
||||||
local DetectedItemChanged = DetectedItem.Changed
|
local DetectedItemChanged = DetectedItem.Changed
|
||||||
|
|
||||||
self:F( { DetectedItemChanged = DetectedItemChanged, DetectedItemID = DetectedItemID, TaskIndex = TaskIndex } )
|
self:F( { DetectedItemChanged = DetectedItemChanged, DetectedItemID = DetectedItemID, TaskIndex = TaskIndex } )
|
||||||
|
|
||||||
local Task = self.Tasks[TaskIndex] -- Tasking.Task_A2G#TASK_A2G
|
local Task = self.Tasks[TaskIndex] -- Tasking.Task_A2G#TASK_A2G
|
||||||
|
|
||||||
if Task then
|
if Task then
|
||||||
-- If there is a Task and the task was assigned, then we check if the task was changed ... If it was, we need to reevaluate the targets.
|
-- If there is a Task and the task was assigned, then we check if the task was changed ... If it was, we need to reevaluate the targets.
|
||||||
if Task:IsStateAssigned() then
|
if Task:IsStateAssigned() then
|
||||||
@@ -660,7 +655,7 @@ do -- TASK_A2G_DISPATCHER
|
|||||||
Task:SetTargetSetUnit( TargetSetUnit )
|
Task:SetTargetSetUnit( TargetSetUnit )
|
||||||
Task:SetDetection( Detection, DetectedItem )
|
Task:SetDetection( Detection, DetectedItem )
|
||||||
Task:UpdateTaskInfo( DetectedItem )
|
Task:UpdateTaskInfo( DetectedItem )
|
||||||
TargetsReport:Add( Detection:GetChangeText( DetectedItem ) )
|
TargetsReport:Add( Detection:GetChangeText( DetectedItem ) )
|
||||||
else
|
else
|
||||||
Task:Cancel()
|
Task:Cancel()
|
||||||
end
|
end
|
||||||
@@ -691,18 +686,18 @@ do -- TASK_A2G_DISPATCHER
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Now we send to each group the changes, if any.
|
-- Now we send to each group the changes, if any.
|
||||||
for TaskGroupID, TaskGroup in pairs( self.SetGroup:GetSet() ) do
|
for TaskGroupID, TaskGroup in pairs( self.SetGroup:GetSet() ) do
|
||||||
local TargetsText = TargetsReport:Text(", ")
|
local TargetsText = TargetsReport:Text( ", " )
|
||||||
if ( Mission:IsGroupAssigned(TaskGroup) ) and TargetsText ~= "" and self.FlashNewTask then
|
if (Mission:IsGroupAssigned( TaskGroup )) and TargetsText ~= "" and self.FlashNewTask then
|
||||||
Mission:GetCommandCenter():MessageToGroup( string.format( "Task %s has change of targets:\n %s", Task:GetName(), TargetsText ), TaskGroup )
|
Mission:GetCommandCenter():MessageToGroup( string.format( "Task %s has change of targets:\n %s", Task:GetName(), TargetsText ), TaskGroup )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if Task then
|
if Task then
|
||||||
if Task:IsStatePlanned() then
|
if Task:IsStatePlanned() then
|
||||||
if DetectedItemChanged == true then -- The detection has changed, thus a new TargetSet is to be evaluated and set
|
if DetectedItemChanged == true then -- The detection has changed, thus a new TargetSet is to be evaluated and set
|
||||||
@@ -753,7 +748,7 @@ do -- TASK_A2G_DISPATCHER
|
|||||||
local TargetSetUnit = self:EvaluateSEAD( DetectedItem ) -- Returns a SetUnit if there are targets to be SEADed...
|
local TargetSetUnit = self:EvaluateSEAD( DetectedItem ) -- Returns a SetUnit if there are targets to be SEADed...
|
||||||
if TargetSetUnit then
|
if TargetSetUnit then
|
||||||
Task = TASK_A2G_SEAD:New( Mission, self.SetGroup, string.format( "SEAD.%03d", DetectedItemID ), TargetSetUnit )
|
Task = TASK_A2G_SEAD:New( Mission, self.SetGroup, string.format( "SEAD.%03d", DetectedItemID ), TargetSetUnit )
|
||||||
DetectedItem.DesignateMenuName = string.format( "SEAD.%03d", DetectedItemID ) --inject a name for DESIGNATE, if using same DETECTION object
|
DetectedItem.DesignateMenuName = string.format( "SEAD.%03d", DetectedItemID ) -- inject a name for DESIGNATE, if using same DETECTION object
|
||||||
Task:SetDetection( Detection, DetectedItem )
|
Task:SetDetection( Detection, DetectedItem )
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -762,7 +757,7 @@ do -- TASK_A2G_DISPATCHER
|
|||||||
local TargetSetUnit = self:EvaluateCAS( DetectedItem ) -- Returns a SetUnit if there are targets to be CASed...
|
local TargetSetUnit = self:EvaluateCAS( DetectedItem ) -- Returns a SetUnit if there are targets to be CASed...
|
||||||
if TargetSetUnit then
|
if TargetSetUnit then
|
||||||
Task = TASK_A2G_CAS:New( Mission, self.SetGroup, string.format( "CAS.%03d", DetectedItemID ), TargetSetUnit )
|
Task = TASK_A2G_CAS:New( Mission, self.SetGroup, string.format( "CAS.%03d", DetectedItemID ), TargetSetUnit )
|
||||||
DetectedItem.DesignateMenuName = string.format( "CAS.%03d", DetectedItemID ) --inject a name for DESIGNATE, if using same DETECTION object
|
DetectedItem.DesignateMenuName = string.format( "CAS.%03d", DetectedItemID ) -- inject a name for DESIGNATE, if using same DETECTION object
|
||||||
Task:SetDetection( Detection, DetectedItem )
|
Task:SetDetection( Detection, DetectedItem )
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -771,19 +766,19 @@ do -- TASK_A2G_DISPATCHER
|
|||||||
local TargetSetUnit = self:EvaluateBAI( DetectedItem, self.Mission:GetCommandCenter():GetPositionable():GetCoalition() ) -- Returns a SetUnit if there are targets to be BAIed...
|
local TargetSetUnit = self:EvaluateBAI( DetectedItem, self.Mission:GetCommandCenter():GetPositionable():GetCoalition() ) -- Returns a SetUnit if there are targets to be BAIed...
|
||||||
if TargetSetUnit then
|
if TargetSetUnit then
|
||||||
Task = TASK_A2G_BAI:New( Mission, self.SetGroup, string.format( "BAI.%03d", DetectedItemID ), TargetSetUnit )
|
Task = TASK_A2G_BAI:New( Mission, self.SetGroup, string.format( "BAI.%03d", DetectedItemID ), TargetSetUnit )
|
||||||
DetectedItem.DesignateMenuName = string.format( "BAI.%03d", DetectedItemID ) --inject a name for DESIGNATE, if using same DETECTION object
|
DetectedItem.DesignateMenuName = string.format( "BAI.%03d", DetectedItemID ) -- inject a name for DESIGNATE, if using same DETECTION object
|
||||||
Task:SetDetection( Detection, DetectedItem )
|
Task:SetDetection( Detection, DetectedItem )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if Task then
|
if Task then
|
||||||
self.Tasks[TaskIndex] = Task
|
self.Tasks[TaskIndex] = Task
|
||||||
Task:SetTargetZone( DetectedZone )
|
Task:SetTargetZone( DetectedZone )
|
||||||
Task:SetDispatcher( self )
|
Task:SetDispatcher( self )
|
||||||
Task:UpdateTaskInfo( DetectedItem )
|
Task:UpdateTaskInfo( DetectedItem )
|
||||||
Mission:AddTask( Task )
|
Mission:AddTask( Task )
|
||||||
|
|
||||||
function Task.OnEnterSuccess( Task, From, Event, To )
|
function Task.OnEnterSuccess( Task, From, Event, To )
|
||||||
self:Success( Task )
|
self:Success( Task )
|
||||||
end
|
end
|
||||||
@@ -791,7 +786,7 @@ do -- TASK_A2G_DISPATCHER
|
|||||||
function Task.OnEnterCancelled( Task, From, Event, To )
|
function Task.OnEnterCancelled( Task, From, Event, To )
|
||||||
self:Cancelled( Task )
|
self:Cancelled( Task )
|
||||||
end
|
end
|
||||||
|
|
||||||
function Task.OnEnterFailed( Task, From, Event, To )
|
function Task.OnEnterFailed( Task, From, Event, To )
|
||||||
self:Failed( Task )
|
self:Failed( Task )
|
||||||
end
|
end
|
||||||
@@ -799,31 +794,29 @@ do -- TASK_A2G_DISPATCHER
|
|||||||
function Task.OnEnterAborted( Task, From, Event, To )
|
function Task.OnEnterAborted( Task, From, Event, To )
|
||||||
self:Aborted( Task )
|
self:Aborted( Task )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
TaskReport:Add( Task:GetName() )
|
TaskReport:Add( Task:GetName() )
|
||||||
else
|
else
|
||||||
self:F("This should not happen")
|
self:F( "This should not happen" )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- OK, so the tasking has been done, now delete the changes reported for the area.
|
-- OK, so the tasking has been done, now delete the changes reported for the area.
|
||||||
Detection:AcceptChanges( DetectedItem )
|
Detection:AcceptChanges( DetectedItem )
|
||||||
end
|
end
|
||||||
|
|
||||||
-- TODO set menus using the HQ coordinator
|
-- TODO set menus using the HQ coordinator
|
||||||
Mission:GetCommandCenter():SetMenu()
|
Mission:GetCommandCenter():SetMenu()
|
||||||
|
|
||||||
local TaskText = TaskReport:Text(", ")
|
local TaskText = TaskReport:Text( ", " )
|
||||||
for TaskGroupID, TaskGroup in pairs( self.SetGroup:GetSet() ) do
|
for TaskGroupID, TaskGroup in pairs( self.SetGroup:GetSet() ) do
|
||||||
if ( not Mission:IsGroupAssigned(TaskGroup) ) and TaskText ~= "" and self.FlashNewTask then
|
if (not Mission:IsGroupAssigned( TaskGroup )) and TaskText ~= "" and self.FlashNewTask then
|
||||||
Mission:GetCommandCenter():MessageToGroup( string.format( "%s has tasks %s. Subscribe to a task using the radio menu.", Mission:GetShortText(), TaskText ), TaskGroup )
|
Mission:GetCommandCenter():MessageToGroup( string.format( "%s has tasks %s. Subscribe to a task using the radio menu.", Mission:GetShortText(), TaskText ), TaskGroup )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
--- **Utilities** Enumerators.
|
--- **Utilities** Enumerators.
|
||||||
--
|
--
|
||||||
-- An enumerator is a variable that holds a constant value. Enumerators are very useful because they make the code easier to read and to change in general.
|
-- An enumerator is a variable that holds a constant value. Enumerators are very useful because they make the code easier to read and to change in general.
|
||||||
--
|
--
|
||||||
-- For example, instead of using the same value at multiple different places in your code, you should use a variable set to that value.
|
-- For example, instead of using the same value at multiple different places in your code, you should use a variable set to that value.
|
||||||
-- If, for whatever reason, the value needs to be changed, you only have to change the variable once and do not have to search through you code and reset
|
-- If, for whatever reason, the value needs to be changed, you only have to change the variable once and do not have to search through you code and reset
|
||||||
-- every value by hand.
|
-- every value by hand.
|
||||||
--
|
--
|
||||||
-- Another big advantage is that the LDT intellisense "knows" the enumerators. So you can use the autocompletion feature and do not have to keep all the
|
-- Another big advantage is that the LDT intellisense "knows" the enumerators. So you can use the autocompletion feature and do not have to keep all the
|
||||||
-- values in your head or look them up in the docs.
|
-- values in your head or look them up in the docs.
|
||||||
--
|
--
|
||||||
-- DCS itself provides a lot of enumerators for various things. See [Enumerators](https://wiki.hoggitworld.com/view/Category:Enumerators) on Hoggit.
|
-- DCS itself provides a lot of enumerators for various things. See [Enumerators](https://wiki.hoggitworld.com/view/Category:Enumerators) on Hoggit.
|
||||||
--
|
--
|
||||||
-- Other Moose classe also have enumerators. For example, the AIRBASE class has enumerators for airbase names.
|
-- Other Moose classes also have enumerators. For example, the AIRBASE class has enumerators for airbase names.
|
||||||
--
|
--
|
||||||
-- @module ENUMS
|
-- @module ENUMS
|
||||||
-- @image MOOSE.JPG
|
-- @image MOOSE.JPG
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
-- @type ENUMS
|
-- @type ENUMS
|
||||||
|
|
||||||
--- Because ENUMS are just better practice.
|
--- Because ENUMS are just better practice.
|
||||||
--
|
--
|
||||||
-- The ENUMS class adds some handy variables, which help you to make your code better and more general.
|
-- The ENUMS class adds some handy variables, which help you to make your code better and more general.
|
||||||
--
|
--
|
||||||
-- @field #ENUMS
|
-- @field #ENUMS
|
||||||
@@ -30,16 +30,16 @@ ENUMS = {}
|
|||||||
-- @type ENUMS.ROE
|
-- @type ENUMS.ROE
|
||||||
-- @field #number WeaponFree AI will engage any enemy group it detects. Target prioritization is based based on the threat of the target.
|
-- @field #number WeaponFree AI will engage any enemy group it detects. Target prioritization is based based on the threat of the target.
|
||||||
-- @field #number OpenFireWeaponFree AI will engage any enemy group it detects, but will prioritize targets specified in the groups tasking.
|
-- @field #number OpenFireWeaponFree AI will engage any enemy group it detects, but will prioritize targets specified in the groups tasking.
|
||||||
-- @field #number OpenFire AI will engage only targets specified in its taskings.
|
-- @field #number OpenFire AI will engage only targets specified in its tasking.
|
||||||
-- @field #number ReturnFire AI will only engage threats that shoot first.
|
-- @field #number ReturnFire AI will only engage threats that shoot first.
|
||||||
-- @field #number WeaponHold AI will hold fire under all circumstances.
|
-- @field #number WeaponHold AI will hold fire under all circumstances.
|
||||||
ENUMS.ROE = {
|
ENUMS.ROE = {
|
||||||
WeaponFree=0,
|
WeaponFree = 0,
|
||||||
OpenFireWeaponFree=1,
|
OpenFireWeaponFree = 1,
|
||||||
OpenFire=2,
|
OpenFire = 2,
|
||||||
ReturnFire=3,
|
ReturnFire = 3,
|
||||||
WeaponHold=4,
|
WeaponHold = 4,
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Reaction On Threat.
|
--- Reaction On Threat.
|
||||||
-- @type ENUMS.ROT
|
-- @type ENUMS.ROT
|
||||||
@@ -49,11 +49,11 @@ ENUMS.ROE = {
|
|||||||
-- @field #number BypassAndEscape AI will attempt to avoid enemy threat zones all together. This includes attempting to fly above or around threats.
|
-- @field #number BypassAndEscape AI will attempt to avoid enemy threat zones all together. This includes attempting to fly above or around threats.
|
||||||
-- @field #number AllowAbortMission If a threat is deemed severe enough the AI will abort its mission and return to base.
|
-- @field #number AllowAbortMission If a threat is deemed severe enough the AI will abort its mission and return to base.
|
||||||
ENUMS.ROT = {
|
ENUMS.ROT = {
|
||||||
NoReaction=0,
|
NoReaction = 0,
|
||||||
PassiveDefense=1,
|
PassiveDefense = 1,
|
||||||
EvadeFire=2,
|
EvadeFire = 2,
|
||||||
BypassAndEscape=3,
|
BypassAndEscape = 3,
|
||||||
AllowAbortMission=4,
|
AllowAbortMission = 4,
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Alarm state.
|
--- Alarm state.
|
||||||
@@ -62,12 +62,12 @@ ENUMS.ROT = {
|
|||||||
-- @field #number Green Group is not combat ready. Sensors are stowed if possible.
|
-- @field #number Green Group is not combat ready. Sensors are stowed if possible.
|
||||||
-- @field #number Red Group is combat ready and actively searching for targets. Some groups like infantry will not move in this state.
|
-- @field #number Red Group is combat ready and actively searching for targets. Some groups like infantry will not move in this state.
|
||||||
ENUMS.AlarmState = {
|
ENUMS.AlarmState = {
|
||||||
Auto=0,
|
Auto = 0,
|
||||||
Green=1,
|
Green = 1,
|
||||||
Red=2,
|
Red = 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Weapon types. See the [Weapon Flag](https://wiki.hoggitworld.com/view/DCS_enum_weapon_flag) enumerotor on hoggit wiki.
|
--- Weapon types. See the [Weapon Flag](https://wiki.hoggitworld.com/view/DCS_enum_weapon_flag) enumerator on Hoggit wiki.
|
||||||
-- @type ENUMS.WeaponFlag
|
-- @type ENUMS.WeaponFlag
|
||||||
ENUMS.WeaponFlag={
|
ENUMS.WeaponFlag={
|
||||||
-- Bombs
|
-- Bombs
|
||||||
@@ -111,7 +111,7 @@ ENUMS.WeaponFlag={
|
|||||||
--
|
--
|
||||||
-- Bombs
|
-- Bombs
|
||||||
GuidedBomb = 14, -- (LGB + TvGB + SNSGB)
|
GuidedBomb = 14, -- (LGB + TvGB + SNSGB)
|
||||||
AnyUnguidedBomb = 2147485680, -- (HeBomb + Penetrator + NapalmBomb + FAEBomb + ClusterBomb + Dispencer + CandleBomb + ParachuteBomb)
|
AnyUnguidedBomb = 2147485680, -- (HeBomb + Penetrator + NapalmBomb + FAEBomb + ClusterBomb + Dispenser + CandleBomb + ParachuteBomb)
|
||||||
AnyBomb = 2147485694, -- (GuidedBomb + AnyUnguidedBomb)
|
AnyBomb = 2147485694, -- (GuidedBomb + AnyUnguidedBomb)
|
||||||
--- Rockets
|
--- Rockets
|
||||||
AnyRocket = 30720, -- LightRocket + MarkerRocket + CandleRocket + HeavyRocket
|
AnyRocket = 30720, -- LightRocket + MarkerRocket + CandleRocket + HeavyRocket
|
||||||
@@ -123,7 +123,7 @@ ENUMS.WeaponFlag={
|
|||||||
--- Air-To-Air Missiles
|
--- Air-To-Air Missiles
|
||||||
AnyAAM = 264241152, -- IR_AAM + SAR_AAM + AR_AAM + SRAAM + MRAAM + LRAAM
|
AnyAAM = 264241152, -- IR_AAM + SAR_AAM + AR_AAM + SRAAM + MRAAM + LRAAM
|
||||||
AnyAutonomousMissile = 36012032, -- IR_AAM + AntiRadarMissile + AntiShipMissile + FireAndForgetASM + CruiseMissile
|
AnyAutonomousMissile = 36012032, -- IR_AAM + AntiRadarMissile + AntiShipMissile + FireAndForgetASM + CruiseMissile
|
||||||
AnyMissile = 268402688, -- AnyASM + AnyAAM
|
AnyMissile = 268402688, -- AnyASM + AnyAAM
|
||||||
--- Guns
|
--- Guns
|
||||||
Cannons = 805306368, -- GUN_POD + BuiltInCannon
|
Cannons = 805306368, -- GUN_POD + BuiltInCannon
|
||||||
---
|
---
|
||||||
@@ -133,7 +133,7 @@ ENUMS.WeaponFlag={
|
|||||||
AnyAG = 2956984318, -- Any Air-To-Ground Weapon
|
AnyAG = 2956984318, -- Any Air-To-Ground Weapon
|
||||||
AnyAA = 264241152, -- Any Air-To-Air Weapon
|
AnyAA = 264241152, -- Any Air-To-Air Weapon
|
||||||
AnyUnguided = 2952822768, -- Any Unguided Weapon
|
AnyUnguided = 2952822768, -- Any Unguided Weapon
|
||||||
AnyGuided = 268402702, -- Any Guided Weapon
|
AnyGuided = 268402702, -- Any Guided Weapon
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Mission tasks.
|
--- Mission tasks.
|
||||||
@@ -173,7 +173,7 @@ ENUMS.MissionTask={
|
|||||||
TRANSPORT="Transport",
|
TRANSPORT="Transport",
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Formations (new). See the [Formations](https://wiki.hoggitworld.com/view/DCS_enum_formation) on hoggit wiki.
|
--- Formations (new). See the [Formations](https://wiki.hoggitworld.com/view/DCS_enum_formation) on Hoggit wiki.
|
||||||
-- @type ENUMS.Formation
|
-- @type ENUMS.Formation
|
||||||
ENUMS.Formation={}
|
ENUMS.Formation={}
|
||||||
ENUMS.Formation.FixedWing={}
|
ENUMS.Formation.FixedWing={}
|
||||||
@@ -216,23 +216,23 @@ ENUMS.Formation.FixedWing.FighterVic.Close = 917505
|
|||||||
ENUMS.Formation.FixedWing.FighterVic.Open = 917506
|
ENUMS.Formation.FixedWing.FighterVic.Open = 917506
|
||||||
ENUMS.Formation.RotaryWing={}
|
ENUMS.Formation.RotaryWing={}
|
||||||
ENUMS.Formation.RotaryWing.Column={}
|
ENUMS.Formation.RotaryWing.Column={}
|
||||||
ENUMS.Formation.RotaryWing.Column.D70=720896
|
ENUMS.Formation.RotaryWing.Column.D70 = 720896
|
||||||
ENUMS.Formation.RotaryWing.Wedge={}
|
ENUMS.Formation.RotaryWing.Wedge={}
|
||||||
ENUMS.Formation.RotaryWing.Wedge.D70=8
|
ENUMS.Formation.RotaryWing.Wedge.D70 = 8
|
||||||
ENUMS.Formation.RotaryWing.FrontRight={}
|
ENUMS.Formation.RotaryWing.FrontRight={}
|
||||||
ENUMS.Formation.RotaryWing.FrontRight.D300=655361
|
ENUMS.Formation.RotaryWing.FrontRight.D300 = 655361
|
||||||
ENUMS.Formation.RotaryWing.FrontRight.D600=655362
|
ENUMS.Formation.RotaryWing.FrontRight.D600 = 655362
|
||||||
ENUMS.Formation.RotaryWing.FrontLeft={}
|
ENUMS.Formation.RotaryWing.FrontLeft={}
|
||||||
ENUMS.Formation.RotaryWing.FrontLeft.D300=655617
|
ENUMS.Formation.RotaryWing.FrontLeft.D300 = 655617
|
||||||
ENUMS.Formation.RotaryWing.FrontLeft.D600=655618
|
ENUMS.Formation.RotaryWing.FrontLeft.D600 = 655618
|
||||||
ENUMS.Formation.RotaryWing.EchelonRight={}
|
ENUMS.Formation.RotaryWing.EchelonRight={}
|
||||||
ENUMS.Formation.RotaryWing.EchelonRight.D70 =589825
|
ENUMS.Formation.RotaryWing.EchelonRight.D70 = 589825
|
||||||
ENUMS.Formation.RotaryWing.EchelonRight.D300=589826
|
ENUMS.Formation.RotaryWing.EchelonRight.D300 = 589826
|
||||||
ENUMS.Formation.RotaryWing.EchelonRight.D600=589827
|
ENUMS.Formation.RotaryWing.EchelonRight.D600 = 589827
|
||||||
ENUMS.Formation.RotaryWing.EchelonLeft={}
|
ENUMS.Formation.RotaryWing.EchelonLeft={}
|
||||||
ENUMS.Formation.RotaryWing.EchelonLeft.D70 =590081
|
ENUMS.Formation.RotaryWing.EchelonLeft.D70 = 590081
|
||||||
ENUMS.Formation.RotaryWing.EchelonLeft.D300=590082
|
ENUMS.Formation.RotaryWing.EchelonLeft.D300 = 590082
|
||||||
ENUMS.Formation.RotaryWing.EchelonLeft.D600=590083
|
ENUMS.Formation.RotaryWing.EchelonLeft.D600 = 590083
|
||||||
ENUMS.Formation.Vehicle={}
|
ENUMS.Formation.Vehicle={}
|
||||||
ENUMS.Formation.Vehicle.Vee="Vee"
|
ENUMS.Formation.Vehicle.Vee="Vee"
|
||||||
ENUMS.Formation.Vehicle.EchelonRight="EchelonR"
|
ENUMS.Formation.Vehicle.EchelonRight="EchelonR"
|
||||||
@@ -244,34 +244,34 @@ ENUMS.Formation.Vehicle.Cone="Cone"
|
|||||||
ENUMS.Formation.Vehicle.Diamond="Diamond"
|
ENUMS.Formation.Vehicle.Diamond="Diamond"
|
||||||
|
|
||||||
--- Formations (old). The old format is a simplified version of the new formation enums, which allow more sophisticated settings.
|
--- Formations (old). The old format is a simplified version of the new formation enums, which allow more sophisticated settings.
|
||||||
-- See the [Formations](https://wiki.hoggitworld.com/view/DCS_enum_formation) on hoggit wiki.
|
-- See the [Formations](https://wiki.hoggitworld.com/view/DCS_enum_formation) on Hoggit wiki.
|
||||||
-- @type ENUMS.FormationOld
|
-- @type ENUMS.FormationOld
|
||||||
ENUMS.FormationOld={}
|
ENUMS.FormationOld={}
|
||||||
ENUMS.FormationOld.FixedWing={}
|
ENUMS.FormationOld.FixedWing={}
|
||||||
ENUMS.FormationOld.FixedWing.LineAbreast=1
|
ENUMS.FormationOld.FixedWing.LineAbreast = 1
|
||||||
ENUMS.FormationOld.FixedWing.Trail=2
|
ENUMS.FormationOld.FixedWing.Trail = 2
|
||||||
ENUMS.FormationOld.FixedWing.Wedge=3
|
ENUMS.FormationOld.FixedWing.Wedge = 3
|
||||||
ENUMS.FormationOld.FixedWing.EchelonRight=4
|
ENUMS.FormationOld.FixedWing.EchelonRight = 4
|
||||||
ENUMS.FormationOld.FixedWing.EchelonLeft=5
|
ENUMS.FormationOld.FixedWing.EchelonLeft = 5
|
||||||
ENUMS.FormationOld.FixedWing.FingerFour=6
|
ENUMS.FormationOld.FixedWing.FingerFour = 6
|
||||||
ENUMS.FormationOld.FixedWing.SpreadFour=7
|
ENUMS.FormationOld.FixedWing.SpreadFour = 7
|
||||||
ENUMS.FormationOld.FixedWing.BomberElement=12
|
ENUMS.FormationOld.FixedWing.BomberElement = 12
|
||||||
ENUMS.FormationOld.FixedWing.BomberElementHeight=13
|
ENUMS.FormationOld.FixedWing.BomberElementHeight = 13
|
||||||
ENUMS.FormationOld.FixedWing.FighterVic=14
|
ENUMS.FormationOld.FixedWing.FighterVic = 14
|
||||||
ENUMS.FormationOld.RotaryWing={}
|
ENUMS.FormationOld.RotaryWing={}
|
||||||
ENUMS.FormationOld.RotaryWing.Wedge=8
|
ENUMS.FormationOld.RotaryWing.Wedge = 8
|
||||||
ENUMS.FormationOld.RotaryWing.Echelon=9
|
ENUMS.FormationOld.RotaryWing.Echelon = 9
|
||||||
ENUMS.FormationOld.RotaryWing.Front=10
|
ENUMS.FormationOld.RotaryWing.Front = 10
|
||||||
ENUMS.FormationOld.RotaryWing.Column=11
|
ENUMS.FormationOld.RotaryWing.Column = 11
|
||||||
|
|
||||||
|
|
||||||
--- Morse Code. See the [Wikipedia](https://en.wikipedia.org/wiki/Morse_code).
|
--- Morse Code. See the [Wikipedia](https://en.wikipedia.org/wiki/Morse_code).
|
||||||
--
|
--
|
||||||
-- * Short pulse "*"
|
-- * Short pulse "*"
|
||||||
-- * Long pulse "-"
|
-- * Long pulse "-"
|
||||||
--
|
--
|
||||||
-- Pulses are separated by a blank character " ".
|
-- Pulses are separated by a blank character " ".
|
||||||
--
|
--
|
||||||
-- @type ENUMS.Morse
|
-- @type ENUMS.Morse
|
||||||
ENUMS.Morse={}
|
ENUMS.Morse={}
|
||||||
ENUMS.Morse.A="* -"
|
ENUMS.Morse.A="* -"
|
||||||
@@ -313,9 +313,9 @@ ENUMS.Morse.N0="- - - - -"
|
|||||||
ENUMS.Morse[" "]=" "
|
ENUMS.Morse[" "]=" "
|
||||||
|
|
||||||
--- ISO (639-1) 2-letter Language Codes. See the [Wikipedia](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes).
|
--- ISO (639-1) 2-letter Language Codes. See the [Wikipedia](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes).
|
||||||
--
|
--
|
||||||
-- @type ENUMS.ISOLang
|
-- @type ENUMS.ISOLang
|
||||||
ENUMS.ISOLang =
|
ENUMS.ISOLang =
|
||||||
{
|
{
|
||||||
Arabic = 'AR',
|
Arabic = 'AR',
|
||||||
Chinese = 'ZH',
|
Chinese = 'ZH',
|
||||||
@@ -329,7 +329,7 @@ ENUMS.ISOLang =
|
|||||||
}
|
}
|
||||||
|
|
||||||
--- Phonetic Alphabet (NATO). See the [Wikipedia](https://en.wikipedia.org/wiki/NATO_phonetic_alphabet).
|
--- Phonetic Alphabet (NATO). See the [Wikipedia](https://en.wikipedia.org/wiki/NATO_phonetic_alphabet).
|
||||||
--
|
--
|
||||||
-- @type ENUMS.Phonetic
|
-- @type ENUMS.Phonetic
|
||||||
ENUMS.Phonetic =
|
ENUMS.Phonetic =
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,11 +5,10 @@
|
|||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ### Author: **TAW CougarNL**, *funkyfranky*
|
-- ### Author: **TAW CougarNL**, *funkyfranky*
|
||||||
--
|
--
|
||||||
-- @module Utilities.PROFILER
|
-- @module Utilities.PROFILER
|
||||||
-- @image MOOSE.JPG
|
-- @image MOOSE.JPG
|
||||||
|
|
||||||
|
|
||||||
--- PROFILER class.
|
--- PROFILER class.
|
||||||
-- @type PROFILER
|
-- @type PROFILER
|
||||||
-- @field #string ClassName Name of the class.
|
-- @field #string ClassName Name of the class.
|
||||||
@@ -25,7 +24,6 @@
|
|||||||
-- @field #number ThreshTtot Total time threshold. Only write output if total function CPU time is more than this value.
|
-- @field #number ThreshTtot Total time threshold. Only write output if total function CPU time is more than this value.
|
||||||
-- @field #string fileNamePrefix Output file name prefix, e.g. "MooseProfiler".
|
-- @field #string fileNamePrefix Output file name prefix, e.g. "MooseProfiler".
|
||||||
-- @field #string fileNameSuffix Output file name prefix, e.g. "txt"
|
-- @field #string fileNameSuffix Output file name prefix, e.g. "txt"
|
||||||
|
|
||||||
--- *The emperor counsels simplicity. First principles. Of each particular thing, ask: What is it in itself, in its own constitution? What is its causal nature? *
|
--- *The emperor counsels simplicity. First principles. Of each particular thing, ask: What is it in itself, in its own constitution? What is its causal nature? *
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
@@ -33,60 +31,59 @@
|
|||||||
-- 
|
-- 
|
||||||
--
|
--
|
||||||
-- # The PROFILER Concept
|
-- # The PROFILER Concept
|
||||||
--
|
--
|
||||||
-- Profile your lua code. This tells you, which functions are called very often and which consume most real time.
|
-- Profile your lua code. This tells you, which functions are called very often and which consume most real time.
|
||||||
-- With this information you can optimize the perfomance of your code.
|
-- With this information you can optimize the performance of your code.
|
||||||
--
|
--
|
||||||
-- # Prerequisites
|
-- # Prerequisites
|
||||||
--
|
--
|
||||||
-- The modules **os** and **lfs** need to be desanizied.
|
-- The modules **os** and **lfs** need to be de-sanitized.
|
||||||
--
|
--
|
||||||
--
|
|
||||||
-- # Start
|
-- # Start
|
||||||
--
|
--
|
||||||
-- The profiler can simply be started with the @{#PROFILER.Start}(*Delay, Duration*) function
|
-- The profiler can simply be started with the @{#PROFILER.Start}(*Delay, Duration*) function
|
||||||
--
|
--
|
||||||
-- PROFILER.Start()
|
-- PROFILER.Start()
|
||||||
--
|
--
|
||||||
-- The optional parameter *Delay* can be used to delay the start by a certain amount of seconds and the optional parameter *Duration* can be used to
|
-- The optional parameter *Delay* can be used to delay the start by a certain amount of seconds and the optional parameter *Duration* can be used to
|
||||||
-- stop the profiler after a certain amount of seconds.
|
-- stop the profiler after a certain amount of seconds.
|
||||||
--
|
--
|
||||||
-- # Stop
|
-- # Stop
|
||||||
--
|
--
|
||||||
-- The profiler automatically stops when the mission ends. But it can be stopped any time with the @{#PROFILER.Stop}(*Delay*) function
|
-- The profiler automatically stops when the mission ends. But it can be stopped any time with the @{#PROFILER.Stop}(*Delay*) function
|
||||||
--
|
--
|
||||||
-- PROFILER.Stop()
|
-- PROFILER.Stop()
|
||||||
--
|
--
|
||||||
-- The optional parameter *Delay* can be used to specify a delay after which the profiler is stopped.
|
-- The optional parameter *Delay* can be used to specify a delay after which the profiler is stopped.
|
||||||
--
|
--
|
||||||
-- When the profiler is stopped, the output is written to a file.
|
-- When the profiler is stopped, the output is written to a file.
|
||||||
--
|
--
|
||||||
-- # Output
|
-- # Output
|
||||||
--
|
--
|
||||||
-- The profiler output is written to a file in your DCS home folder
|
-- The profiler output is written to a file in your DCS home folder
|
||||||
--
|
--
|
||||||
-- X:\User\<Your User Name>\Saved Games\DCS OpenBeta\Logs
|
-- X:\User\<Your User Name>\Saved Games\DCS OpenBeta\Logs
|
||||||
--
|
--
|
||||||
-- The default file name is "MooseProfiler.txt". If that file exists, the file name is "MooseProfiler-001.txt" etc.
|
-- The default file name is "MooseProfiler.txt". If that file exists, the file name is "MooseProfiler-001.txt" etc.
|
||||||
--
|
--
|
||||||
-- ## Data
|
-- ## Data
|
||||||
--
|
--
|
||||||
-- The data in the output file provides information on the functions that were called in the mission.
|
-- The data in the output file provides information on the functions that were called in the mission.
|
||||||
--
|
--
|
||||||
-- It will tell you how many times a function was called in total, how many times per second, how much time in total and the percentage of time.
|
-- It will tell you how many times a function was called in total, how many times per second, how much time in total and the percentage of time.
|
||||||
--
|
--
|
||||||
-- If you only want output for functions that are called more than *X* times per second, you can set
|
-- If you only want output for functions that are called more than *X* times per second, you can set
|
||||||
--
|
--
|
||||||
-- PROFILER.ThreshCPS=1.5
|
-- PROFILER.ThreshCPS=1.5
|
||||||
--
|
--
|
||||||
-- With this setting, only functions which are called more than 1.5 times per second are displayed. The default setting is PROFILER.ThreshCPS=0.0 (no threshold).
|
-- With this setting, only functions which are called more than 1.5 times per second are displayed. The default setting is PROFILER.ThreshCPS=0.0 (no threshold).
|
||||||
--
|
--
|
||||||
-- Furthermore, you can limit the output for functions that consumed a certain amount of CPU time in total by
|
-- Furthermore, you can limit the output for functions that consumed a certain amount of CPU time in total by
|
||||||
--
|
--
|
||||||
-- PROFILER.ThreshTtot=0.005
|
-- PROFILER.ThreshTtot=0.005
|
||||||
--
|
--
|
||||||
-- With this setting, which is also the default, only functions which in total used more than 5 milliseconds CPU time.
|
-- With this setting, which is also the default, only functions which in total used more than 5 milliseconds CPU time.
|
||||||
--
|
--
|
||||||
-- @field #PROFILER
|
-- @field #PROFILER
|
||||||
PROFILER = {
|
PROFILER = {
|
||||||
ClassName = "PROFILER",
|
ClassName = "PROFILER",
|
||||||
@@ -117,97 +114,95 @@ PROFILER = {
|
|||||||
--- Start profiler.
|
--- Start profiler.
|
||||||
-- @param #number Delay Delay in seconds before profiler is stated. Default is immediately.
|
-- @param #number Delay Delay in seconds before profiler is stated. Default is immediately.
|
||||||
-- @param #number Duration Duration in (game) seconds before the profiler is stopped. Default is when mission ends.
|
-- @param #number Duration Duration in (game) seconds before the profiler is stopped. Default is when mission ends.
|
||||||
function PROFILER.Start(Delay, Duration)
|
function PROFILER.Start( Delay, Duration )
|
||||||
|
|
||||||
-- Check if os, io and lfs are available.
|
-- Check if os, io and lfs are available.
|
||||||
local go=true
|
local go = true
|
||||||
if not os then
|
if not os then
|
||||||
env.error("ERROR: Profiler needs os to be desanitized!")
|
env.error( "ERROR: Profiler needs os to be de-sanitized!" )
|
||||||
go=false
|
go = false
|
||||||
end
|
end
|
||||||
if not io then
|
if not io then
|
||||||
env.error("ERROR: Profiler needs io to be desanitized!")
|
env.error( "ERROR: Profiler needs io to be de-sanitized!" )
|
||||||
go=false
|
go = false
|
||||||
end
|
end
|
||||||
if not lfs then
|
if not lfs then
|
||||||
env.error("ERROR: Profiler needs lfs to be desanitized!")
|
env.error( "ERROR: Profiler needs lfs to be de-sanitized!" )
|
||||||
go=false
|
go = false
|
||||||
end
|
end
|
||||||
if not go then
|
if not go then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if Delay and Delay>0 then
|
if Delay and Delay > 0 then
|
||||||
BASE:ScheduleOnce(Delay, PROFILER.Start, 0, Duration)
|
BASE:ScheduleOnce( Delay, PROFILER.Start, 0, Duration )
|
||||||
else
|
else
|
||||||
|
|
||||||
-- Set start time.
|
-- Set start time.
|
||||||
PROFILER.TstartGame=timer.getTime()
|
PROFILER.TstartGame = timer.getTime()
|
||||||
PROFILER.TstartOS=os.clock()
|
PROFILER.TstartOS = os.clock()
|
||||||
|
|
||||||
-- Add event handler.
|
-- Add event handler.
|
||||||
world.addEventHandler(PROFILER.eventHandler)
|
world.addEventHandler( PROFILER.eventHandler )
|
||||||
|
|
||||||
-- Info in log.
|
-- Info in log.
|
||||||
env.info('############################ Profiler Started ############################')
|
env.info( '############################ Profiler Started ############################' )
|
||||||
if Duration then
|
if Duration then
|
||||||
env.info(string.format("- Will be running for %d seconds", Duration))
|
env.info( string.format( "- Will be running for %d seconds", Duration ) )
|
||||||
else
|
else
|
||||||
env.info(string.format("- Will be stopped when mission ends"))
|
env.info( string.format( "- Will be stopped when mission ends" ) )
|
||||||
end
|
end
|
||||||
env.info(string.format("- Calls per second threshold %.3f/sec", PROFILER.ThreshCPS))
|
env.info( string.format( "- Calls per second threshold %.3f/sec", PROFILER.ThreshCPS ) )
|
||||||
env.info(string.format("- Total function time threshold %.3f sec", PROFILER.ThreshTtot))
|
env.info( string.format( "- Total function time threshold %.3f sec", PROFILER.ThreshTtot ) )
|
||||||
env.info(string.format("- Output file \"%s\" in your DCS log file folder", PROFILER.getfilename(PROFILER.fileNameSuffix)))
|
env.info( string.format( "- Output file \"%s\" in your DCS log file folder", PROFILER.getfilename( PROFILER.fileNameSuffix ) ) )
|
||||||
env.info(string.format("- Output file \"%s\" in CSV format", PROFILER.getfilename("csv")))
|
env.info( string.format( "- Output file \"%s\" in CSV format", PROFILER.getfilename( "csv" ) ) )
|
||||||
env.info('###############################################################################')
|
env.info( '###############################################################################' )
|
||||||
|
|
||||||
|
|
||||||
-- Message on screen
|
-- Message on screen
|
||||||
local duration=Duration or 600
|
local duration = Duration or 600
|
||||||
trigger.action.outText("### Profiler running ###", duration)
|
trigger.action.outText( "### Profiler running ###", duration )
|
||||||
|
|
||||||
-- Set hook.
|
-- Set hook.
|
||||||
debug.sethook(PROFILER.hook, "cr")
|
debug.sethook( PROFILER.hook, "cr" )
|
||||||
|
|
||||||
-- Auto stop profiler.
|
-- Auto stop profiler.
|
||||||
if Duration then
|
if Duration then
|
||||||
PROFILER.Stop(Duration)
|
PROFILER.Stop( Duration )
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Stop profiler.
|
--- Stop profiler.
|
||||||
-- @param #number Delay Delay before stop in seconds.
|
-- @param #number Delay Delay before stop in seconds.
|
||||||
function PROFILER.Stop(Delay)
|
function PROFILER.Stop( Delay )
|
||||||
|
|
||||||
|
if Delay and Delay > 0 then
|
||||||
|
|
||||||
|
BASE:ScheduleOnce( Delay, PROFILER.Stop )
|
||||||
|
|
||||||
if Delay and Delay>0 then
|
|
||||||
|
|
||||||
BASE:ScheduleOnce(Delay, PROFILER.Stop)
|
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
-- Remove hook.
|
-- Remove hook.
|
||||||
debug.sethook()
|
debug.sethook()
|
||||||
|
|
||||||
|
|
||||||
-- Run time game.
|
-- Run time game.
|
||||||
local runTimeGame=timer.getTime()-PROFILER.TstartGame
|
local runTimeGame = timer.getTime() - PROFILER.TstartGame
|
||||||
|
|
||||||
-- Run time real OS.
|
-- Run time real OS.
|
||||||
local runTimeOS=os.clock()-PROFILER.TstartOS
|
local runTimeOS = os.clock() - PROFILER.TstartOS
|
||||||
|
|
||||||
-- Show info.
|
-- Show info.
|
||||||
PROFILER.showInfo(runTimeGame, runTimeOS)
|
PROFILER.showInfo( runTimeGame, runTimeOS )
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Event handler.
|
--- Event handler.
|
||||||
function PROFILER.eventHandler:onEvent(event)
|
function PROFILER.eventHandler:onEvent( event )
|
||||||
if event.id==world.event.S_EVENT_MISSION_END then
|
if event.id == world.event.S_EVENT_MISSION_END then
|
||||||
PROFILER.Stop()
|
PROFILER.Stop()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -218,38 +213,38 @@ end
|
|||||||
|
|
||||||
--- Debug hook.
|
--- Debug hook.
|
||||||
-- @param #table event Event.
|
-- @param #table event Event.
|
||||||
function PROFILER.hook(event)
|
function PROFILER.hook( event )
|
||||||
|
|
||||||
local f=debug.getinfo(2, "f").func
|
local f = debug.getinfo( 2, "f" ).func
|
||||||
|
|
||||||
if event=='call' then
|
if event == 'call' then
|
||||||
|
|
||||||
if PROFILER.Counters[f]==nil then
|
if PROFILER.Counters[f] == nil then
|
||||||
|
|
||||||
PROFILER.Counters[f]=1
|
PROFILER.Counters[f] = 1
|
||||||
PROFILER.dInfo[f]=debug.getinfo(2,"Sn")
|
PROFILER.dInfo[f] = debug.getinfo( 2, "Sn" )
|
||||||
|
|
||||||
if PROFILER.fTimeTotal[f]==nil then
|
if PROFILER.fTimeTotal[f] == nil then
|
||||||
PROFILER.fTimeTotal[f]=0
|
PROFILER.fTimeTotal[f] = 0
|
||||||
end
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
PROFILER.Counters[f]=PROFILER.Counters[f]+1
|
PROFILER.Counters[f] = PROFILER.Counters[f] + 1
|
||||||
end
|
end
|
||||||
|
|
||||||
if PROFILER.fTime[f]==nil then
|
if PROFILER.fTime[f] == nil then
|
||||||
PROFILER.fTime[f]=os.clock()
|
PROFILER.fTime[f] = os.clock()
|
||||||
end
|
end
|
||||||
|
|
||||||
elseif (event=='return') then
|
elseif (event == 'return') then
|
||||||
|
|
||||||
if PROFILER.fTime[f]~=nil then
|
if PROFILER.fTime[f] ~= nil then
|
||||||
PROFILER.fTimeTotal[f]=PROFILER.fTimeTotal[f]+(os.clock()-PROFILER.fTime[f])
|
PROFILER.fTimeTotal[f] = PROFILER.fTimeTotal[f] + (os.clock() - PROFILER.fTime[f])
|
||||||
PROFILER.fTime[f]=nil
|
PROFILER.fTime[f] = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
@@ -262,105 +257,104 @@ end
|
|||||||
-- @return #string Source file name.
|
-- @return #string Source file name.
|
||||||
-- @return #string Line number.
|
-- @return #string Line number.
|
||||||
-- @return #number Function time in seconds.
|
-- @return #number Function time in seconds.
|
||||||
function PROFILER.getData(func)
|
function PROFILER.getData( func )
|
||||||
|
|
||||||
local n=PROFILER.dInfo[func]
|
local n = PROFILER.dInfo[func]
|
||||||
|
|
||||||
if n.what=="C" then
|
if n.what == "C" then
|
||||||
return n.name, "?", "?", PROFILER.fTimeTotal[func]
|
return n.name, "?", "?", PROFILER.fTimeTotal[func]
|
||||||
end
|
end
|
||||||
|
|
||||||
return n.name, n.short_src, n.linedefined, PROFILER.fTimeTotal[func]
|
return n.name, n.short_src, n.linedefined, PROFILER.fTimeTotal[func]
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Write text to log file.
|
--- Write text to log file.
|
||||||
-- @param #function f The file.
|
-- @param #function f The file.
|
||||||
-- @param #string txt The text.
|
-- @param #string txt The text.
|
||||||
function PROFILER._flog(f, txt)
|
function PROFILER._flog( f, txt )
|
||||||
f:write(txt.."\r\n")
|
f:write( txt .. "\r\n" )
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Show table.
|
--- Show table.
|
||||||
-- @param #table data Data table.
|
-- @param #table data Data table.
|
||||||
-- @param #function f The file.
|
-- @param #function f The file.
|
||||||
-- @param #number runTimeGame Game run time in seconds.
|
-- @param #number runTimeGame Game run time in seconds.
|
||||||
function PROFILER.showTable(data, f, runTimeGame)
|
function PROFILER.showTable( data, f, runTimeGame )
|
||||||
|
|
||||||
-- Loop over data.
|
-- Loop over data.
|
||||||
for i=1, #data do
|
for i = 1, #data do
|
||||||
local t=data[i] --#PROFILER.Data
|
local t = data[i] -- #PROFILER.Data
|
||||||
|
|
||||||
-- Calls per second.
|
-- Calls per second.
|
||||||
local cps=t.count/runTimeGame
|
local cps = t.count / runTimeGame
|
||||||
|
|
||||||
local threshCPS=cps>=PROFILER.ThreshCPS
|
local threshCPS = cps >= PROFILER.ThreshCPS
|
||||||
local threshTot=t.tm>=PROFILER.ThreshTtot
|
local threshTot = t.tm >= PROFILER.ThreshTtot
|
||||||
|
|
||||||
if threshCPS and threshTot then
|
if threshCPS and threshTot then
|
||||||
|
|
||||||
-- Output
|
-- Output
|
||||||
local text=string.format("%30s: %8d calls %8.1f/sec - Time Total %8.3f sec (%.3f %%) %5.3f sec/call %s line %s", t.func, t.count, cps, t.tm, t.tm/runTimeGame*100, t.tm/t.count, tostring(t.src), tostring(t.line))
|
local text = string.format( "%30s: %8d calls %8.1f/sec - Time Total %8.3f sec (%.3f %%) %5.3f sec/call %s line %s", t.func, t.count, cps, t.tm, t.tm / runTimeGame * 100, t.tm / t.count, tostring( t.src ), tostring( t.line ) )
|
||||||
PROFILER._flog(f, text)
|
PROFILER._flog( f, text )
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Print csv file.
|
--- Print csv file.
|
||||||
-- @param #table data Data table.
|
-- @param #table data Data table.
|
||||||
-- @param #number runTimeGame Game run time in seconds.
|
-- @param #number runTimeGame Game run time in seconds.
|
||||||
function PROFILER.printCSV(data, runTimeGame)
|
function PROFILER.printCSV( data, runTimeGame )
|
||||||
|
|
||||||
-- Output file.
|
-- Output file.
|
||||||
local file=PROFILER.getfilename("csv")
|
local file = PROFILER.getfilename( "csv" )
|
||||||
local g=io.open(file, 'w')
|
local g = io.open( file, 'w' )
|
||||||
|
|
||||||
-- Header.
|
-- Header.
|
||||||
local text="Function,Total Calls,Calls per Sec,Total Time,Total in %,Sec per Call,Source File;Line Number,"
|
local text = "Function,Total Calls,Calls per Sec,Total Time,Total in %,Sec per Call,Source File;Line Number,"
|
||||||
g:write(text.."\r\n")
|
g:write( text .. "\r\n" )
|
||||||
|
|
||||||
-- Loop over data.
|
-- Loop over data.
|
||||||
for i=1, #data do
|
for i = 1, #data do
|
||||||
local t=data[i] --#PROFILER.Data
|
local t = data[i] -- #PROFILER.Data
|
||||||
|
|
||||||
-- Calls per second.
|
-- Calls per second.
|
||||||
local cps=t.count/runTimeGame
|
local cps = t.count / runTimeGame
|
||||||
|
|
||||||
-- Output
|
-- Output
|
||||||
local txt=string.format("%s,%d,%.1f,%.3f,%.3f,%.3f,%s,%s,", t.func, t.count, cps, t.tm, t.tm/runTimeGame*100, t.tm/t.count, tostring(t.src), tostring(t.line))
|
local txt = string.format( "%s,%d,%.1f,%.3f,%.3f,%.3f,%s,%s,", t.func, t.count, cps, t.tm, t.tm / runTimeGame * 100, t.tm / t.count, tostring( t.src ), tostring( t.line ) )
|
||||||
g:write(txt.."\r\n")
|
g:write( txt .. "\r\n" )
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Close file.
|
-- Close file.
|
||||||
g:close()
|
g:close()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Write info to output file.
|
--- Write info to output file.
|
||||||
-- @param #string ext Extension.
|
-- @param #string ext Extension.
|
||||||
-- @return #string File name.
|
-- @return #string File name.
|
||||||
function PROFILER.getfilename(ext)
|
function PROFILER.getfilename( ext )
|
||||||
|
|
||||||
local dir=lfs.writedir()..[[Logs\]]
|
local dir = lfs.writedir() .. [[Logs\]]
|
||||||
|
|
||||||
ext=ext or PROFILER.fileNameSuffix
|
ext = ext or PROFILER.fileNameSuffix
|
||||||
|
|
||||||
local file=dir..PROFILER.fileNamePrefix.."."..ext
|
local file = dir .. PROFILER.fileNamePrefix .. "." .. ext
|
||||||
|
|
||||||
if not UTILS.FileExists(file) then
|
if not UTILS.FileExists( file ) then
|
||||||
return file
|
return file
|
||||||
end
|
end
|
||||||
|
|
||||||
for i=1,999 do
|
|
||||||
|
|
||||||
local file=string.format("%s%s-%03d.%s", dir,PROFILER.fileNamePrefix, i, ext)
|
|
||||||
|
|
||||||
if not UTILS.FileExists(file) then
|
for i = 1, 999 do
|
||||||
|
|
||||||
|
local file = string.format( "%s%s-%03d.%s", dir, PROFILER.fileNamePrefix, i, ext )
|
||||||
|
|
||||||
|
if not UTILS.FileExists( file ) then
|
||||||
return file
|
return file
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
@@ -368,172 +362,172 @@ end
|
|||||||
--- Write info to output file.
|
--- Write info to output file.
|
||||||
-- @param #number runTimeGame Game time in seconds.
|
-- @param #number runTimeGame Game time in seconds.
|
||||||
-- @param #number runTimeOS OS time in seconds.
|
-- @param #number runTimeOS OS time in seconds.
|
||||||
function PROFILER.showInfo(runTimeGame, runTimeOS)
|
function PROFILER.showInfo( runTimeGame, runTimeOS )
|
||||||
|
|
||||||
-- Output file.
|
-- Output file.
|
||||||
local file=PROFILER.getfilename(PROFILER.fileNameSuffix)
|
local file = PROFILER.getfilename( PROFILER.fileNameSuffix )
|
||||||
local f=io.open(file, 'w')
|
local f = io.open( file, 'w' )
|
||||||
|
|
||||||
-- Gather data.
|
-- Gather data.
|
||||||
local Ttot=0
|
local Ttot = 0
|
||||||
local Calls=0
|
local Calls = 0
|
||||||
|
|
||||||
local t={}
|
local t = {}
|
||||||
|
|
||||||
local tcopy=nil --#PROFILER.Data
|
local tcopy = nil -- #PROFILER.Data
|
||||||
local tserialize=nil --#PROFILER.Data
|
local tserialize = nil -- #PROFILER.Data
|
||||||
local tforgen=nil --#PROFILER.Data
|
local tforgen = nil -- #PROFILER.Data
|
||||||
local tpairs=nil --#PROFILER.Data
|
local tpairs = nil -- #PROFILER.Data
|
||||||
|
|
||||||
|
for func, count in pairs( PROFILER.Counters ) do
|
||||||
for func, count in pairs(PROFILER.Counters) do
|
|
||||||
|
local s, src, line, tm = PROFILER.getData( func )
|
||||||
local s,src,line,tm=PROFILER.getData(func)
|
|
||||||
|
if PROFILER.logUnknown == true then
|
||||||
if PROFILER.logUnknown==true then
|
if s == nil then
|
||||||
if s==nil then s="<Unknown>" end
|
s = "<Unknown>"
|
||||||
end
|
|
||||||
|
|
||||||
if s~=nil then
|
|
||||||
|
|
||||||
-- Profile data.
|
|
||||||
local T=
|
|
||||||
{ func=s,
|
|
||||||
src=src,
|
|
||||||
line=line,
|
|
||||||
count=count,
|
|
||||||
tm=tm,
|
|
||||||
} --#PROFILER.Data
|
|
||||||
|
|
||||||
-- Collect special cases. Somehow, e.g. "_copy" appears multiple times so we try to gather all data.
|
|
||||||
if s=="_copy" then
|
|
||||||
if tcopy==nil then
|
|
||||||
tcopy=T
|
|
||||||
else
|
|
||||||
tcopy.count=tcopy.count+T.count
|
|
||||||
tcopy.tm=tcopy.tm+T.tm
|
|
||||||
end
|
|
||||||
elseif s=="_Serialize" then
|
|
||||||
if tserialize==nil then
|
|
||||||
tserialize=T
|
|
||||||
else
|
|
||||||
tserialize.count=tserialize.count+T.count
|
|
||||||
tserialize.tm=tserialize.tm+T.tm
|
|
||||||
end
|
|
||||||
elseif s=="(for generator)" then
|
|
||||||
if tforgen==nil then
|
|
||||||
tforgen=T
|
|
||||||
else
|
|
||||||
tforgen.count=tforgen.count+T.count
|
|
||||||
tforgen.tm=tforgen.tm+T.tm
|
|
||||||
end
|
|
||||||
elseif s=="pairs" then
|
|
||||||
if tpairs==nil then
|
|
||||||
tpairs=T
|
|
||||||
else
|
|
||||||
tpairs.count=tpairs.count+T.count
|
|
||||||
tpairs.tm=tpairs.tm+T.tm
|
|
||||||
end
|
|
||||||
else
|
|
||||||
table.insert(t, T)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Total function time.
|
|
||||||
Ttot=Ttot+tm
|
|
||||||
|
|
||||||
-- Total number of calls.
|
|
||||||
Calls=Calls+count
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if s ~= nil then
|
||||||
|
|
||||||
|
-- Profile data.
|
||||||
|
local T = { func = s, src = src, line = line, count = count, tm = tm } -- #PROFILER.Data
|
||||||
|
|
||||||
|
-- Collect special cases. Somehow, e.g. "_copy" appears multiple times so we try to gather all data.
|
||||||
|
if s == "_copy" then
|
||||||
|
if tcopy == nil then
|
||||||
|
tcopy = T
|
||||||
|
else
|
||||||
|
tcopy.count = tcopy.count + T.count
|
||||||
|
tcopy.tm = tcopy.tm + T.tm
|
||||||
|
end
|
||||||
|
elseif s == "_Serialize" then
|
||||||
|
if tserialize == nil then
|
||||||
|
tserialize = T
|
||||||
|
else
|
||||||
|
tserialize.count = tserialize.count + T.count
|
||||||
|
tserialize.tm = tserialize.tm + T.tm
|
||||||
|
end
|
||||||
|
elseif s == "(for generator)" then
|
||||||
|
if tforgen == nil then
|
||||||
|
tforgen = T
|
||||||
|
else
|
||||||
|
tforgen.count = tforgen.count + T.count
|
||||||
|
tforgen.tm = tforgen.tm + T.tm
|
||||||
|
end
|
||||||
|
elseif s == "pairs" then
|
||||||
|
if tpairs == nil then
|
||||||
|
tpairs = T
|
||||||
|
else
|
||||||
|
tpairs.count = tpairs.count + T.count
|
||||||
|
tpairs.tm = tpairs.tm + T.tm
|
||||||
|
end
|
||||||
|
else
|
||||||
|
table.insert( t, T )
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Total function time.
|
||||||
|
Ttot = Ttot + tm
|
||||||
|
|
||||||
|
-- Total number of calls.
|
||||||
|
Calls = Calls + count
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Add special cases.
|
-- Add special cases.
|
||||||
if tcopy then
|
if tcopy then
|
||||||
table.insert(t, tcopy)
|
table.insert( t, tcopy )
|
||||||
end
|
end
|
||||||
if tserialize then
|
if tserialize then
|
||||||
table.insert(t, tserialize)
|
table.insert( t, tserialize )
|
||||||
end
|
end
|
||||||
if tforgen then
|
if tforgen then
|
||||||
table.insert(t, tforgen)
|
table.insert( t, tforgen )
|
||||||
end
|
end
|
||||||
if tpairs then
|
if tpairs then
|
||||||
table.insert(t, tpairs)
|
table.insert( t, tpairs )
|
||||||
end
|
end
|
||||||
|
|
||||||
env.info('############################ Profiler Stopped ############################')
|
env.info( '############################ Profiler Stopped ############################' )
|
||||||
env.info(string.format("* Runtime Game : %s = %d sec", UTILS.SecondsToClock(runTimeGame, true), runTimeGame))
|
env.info( string.format( "* Runtime Game : %s = %d sec", UTILS.SecondsToClock( runTimeGame, true ), runTimeGame ) )
|
||||||
env.info(string.format("* Runtime Real : %s = %d sec", UTILS.SecondsToClock(runTimeOS, true), runTimeOS))
|
env.info( string.format( "* Runtime Real : %s = %d sec", UTILS.SecondsToClock( runTimeOS, true ), runTimeOS ) )
|
||||||
env.info(string.format("* Function time : %s = %.1f sec (%.1f percent of runtime game)", UTILS.SecondsToClock(Ttot, true), Ttot, Ttot/runTimeGame*100))
|
env.info( string.format( "* Function time : %s = %.1f sec (%.1f percent of runtime game)", UTILS.SecondsToClock( Ttot, true ), Ttot, Ttot / runTimeGame * 100 ) )
|
||||||
env.info(string.format("* Total functions : %d", #t))
|
env.info( string.format( "* Total functions : %d", #t ) )
|
||||||
env.info(string.format("* Total func calls : %d", Calls))
|
env.info( string.format( "* Total func calls : %d", Calls ) )
|
||||||
env.info(string.format("* Writing to file : \"%s\"", file))
|
env.info( string.format( "* Writing to file : \"%s\"", file ) )
|
||||||
env.info(string.format("* Writing to file : \"%s\"", PROFILER.getfilename("csv")))
|
env.info( string.format( "* Writing to file : \"%s\"", PROFILER.getfilename( "csv" ) ) )
|
||||||
env.info("##############################################################################")
|
env.info( "##############################################################################" )
|
||||||
|
|
||||||
-- Sort by total time.
|
-- Sort by total time.
|
||||||
table.sort(t, function(a,b) return a.tm>b.tm end)
|
table.sort( t, function( a, b )
|
||||||
|
return a.tm > b.tm
|
||||||
|
end )
|
||||||
|
|
||||||
-- Write data.
|
-- Write data.
|
||||||
PROFILER._flog(f,"")
|
PROFILER._flog( f, "" )
|
||||||
PROFILER._flog(f,"************************************************************************************************************************")
|
PROFILER._flog( f, "************************************************************************************************************************" )
|
||||||
PROFILER._flog(f,"************************************************************************************************************************")
|
PROFILER._flog( f, "************************************************************************************************************************" )
|
||||||
PROFILER._flog(f,"************************************************************************************************************************")
|
PROFILER._flog( f, "************************************************************************************************************************" )
|
||||||
PROFILER._flog(f,"")
|
PROFILER._flog( f, "" )
|
||||||
PROFILER._flog(f,"-------------------------")
|
PROFILER._flog( f, "-------------------------" )
|
||||||
PROFILER._flog(f,"---- Profiler Report ----")
|
PROFILER._flog( f, "---- Profiler Report ----" )
|
||||||
PROFILER._flog(f,"-------------------------")
|
PROFILER._flog( f, "-------------------------" )
|
||||||
PROFILER._flog(f,"")
|
PROFILER._flog( f, "" )
|
||||||
PROFILER._flog(f,string.format("* Runtime Game : %s = %.1f sec", UTILS.SecondsToClock(runTimeGame, true), runTimeGame))
|
PROFILER._flog( f, string.format( "* Runtime Game : %s = %.1f sec", UTILS.SecondsToClock( runTimeGame, true ), runTimeGame ) )
|
||||||
PROFILER._flog(f,string.format("* Runtime Real : %s = %.1f sec", UTILS.SecondsToClock(runTimeOS, true), runTimeOS))
|
PROFILER._flog( f, string.format( "* Runtime Real : %s = %.1f sec", UTILS.SecondsToClock( runTimeOS, true ), runTimeOS ) )
|
||||||
PROFILER._flog(f,string.format("* Function time : %s = %.1f sec (%.1f %% of runtime game)", UTILS.SecondsToClock(Ttot, true), Ttot, Ttot/runTimeGame*100))
|
PROFILER._flog( f, string.format( "* Function time : %s = %.1f sec (%.1f %% of runtime game)", UTILS.SecondsToClock( Ttot, true ), Ttot, Ttot / runTimeGame * 100 ) )
|
||||||
PROFILER._flog(f,"")
|
PROFILER._flog( f, "" )
|
||||||
PROFILER._flog(f,string.format("* Total functions = %d", #t))
|
PROFILER._flog( f, string.format( "* Total functions = %d", #t ) )
|
||||||
PROFILER._flog(f,string.format("* Total func calls = %d", Calls))
|
PROFILER._flog( f, string.format( "* Total func calls = %d", Calls ) )
|
||||||
PROFILER._flog(f,"")
|
PROFILER._flog( f, "" )
|
||||||
PROFILER._flog(f,string.format("* Calls per second threshold = %.3f/sec", PROFILER.ThreshCPS))
|
PROFILER._flog( f, string.format( "* Calls per second threshold = %.3f/sec", PROFILER.ThreshCPS ) )
|
||||||
PROFILER._flog(f,string.format("* Total func time threshold = %.3f sec", PROFILER.ThreshTtot))
|
PROFILER._flog( f, string.format( "* Total func time threshold = %.3f sec", PROFILER.ThreshTtot ) )
|
||||||
PROFILER._flog(f,"")
|
PROFILER._flog( f, "" )
|
||||||
PROFILER._flog(f,"************************************************************************************************************************")
|
PROFILER._flog( f, "************************************************************************************************************************" )
|
||||||
PROFILER._flog(f,"")
|
PROFILER._flog( f, "" )
|
||||||
PROFILER.showTable(t, f, runTimeGame)
|
PROFILER.showTable( t, f, runTimeGame )
|
||||||
|
|
||||||
-- Sort by number of calls.
|
-- Sort by number of calls.
|
||||||
table.sort(t, function(a,b) return a.tm/a.count>b.tm/b.count end)
|
table.sort( t, function( a, b )
|
||||||
|
return a.tm / a.count > b.tm / b.count
|
||||||
|
end )
|
||||||
|
|
||||||
-- Detailed data.
|
-- Detailed data.
|
||||||
PROFILER._flog(f,"")
|
PROFILER._flog( f, "" )
|
||||||
PROFILER._flog(f,"************************************************************************************************************************")
|
PROFILER._flog( f, "************************************************************************************************************************" )
|
||||||
PROFILER._flog(f,"")
|
PROFILER._flog( f, "" )
|
||||||
PROFILER._flog(f,"--------------------------------------")
|
PROFILER._flog( f, "--------------------------------------" )
|
||||||
PROFILER._flog(f,"---- Data Sorted by Time per Call ----")
|
PROFILER._flog( f, "---- Data Sorted by Time per Call ----" )
|
||||||
PROFILER._flog(f,"--------------------------------------")
|
PROFILER._flog( f, "--------------------------------------" )
|
||||||
PROFILER._flog(f,"")
|
PROFILER._flog( f, "" )
|
||||||
PROFILER.showTable(t, f, runTimeGame)
|
PROFILER.showTable( t, f, runTimeGame )
|
||||||
|
|
||||||
-- Sort by number of calls.
|
-- Sort by number of calls.
|
||||||
table.sort(t, function(a,b) return a.count>b.count end)
|
table.sort( t, function( a, b )
|
||||||
|
return a.count > b.count
|
||||||
|
end )
|
||||||
|
|
||||||
-- Detailed data.
|
-- Detailed data.
|
||||||
PROFILER._flog(f,"")
|
PROFILER._flog( f, "" )
|
||||||
PROFILER._flog(f,"************************************************************************************************************************")
|
PROFILER._flog( f, "************************************************************************************************************************" )
|
||||||
PROFILER._flog(f,"")
|
PROFILER._flog( f, "" )
|
||||||
PROFILER._flog(f,"------------------------------------")
|
PROFILER._flog( f, "------------------------------------" )
|
||||||
PROFILER._flog(f,"---- Data Sorted by Total Calls ----")
|
PROFILER._flog( f, "---- Data Sorted by Total Calls ----" )
|
||||||
PROFILER._flog(f,"------------------------------------")
|
PROFILER._flog( f, "------------------------------------" )
|
||||||
PROFILER._flog(f,"")
|
PROFILER._flog( f, "" )
|
||||||
PROFILER.showTable(t, f, runTimeGame)
|
PROFILER.showTable( t, f, runTimeGame )
|
||||||
|
|
||||||
-- Closing.
|
-- Closing.
|
||||||
PROFILER._flog(f,"")
|
PROFILER._flog( f, "" )
|
||||||
PROFILER._flog(f,"************************************************************************************************************************")
|
PROFILER._flog( f, "************************************************************************************************************************" )
|
||||||
PROFILER._flog(f,"************************************************************************************************************************")
|
PROFILER._flog( f, "************************************************************************************************************************" )
|
||||||
PROFILER._flog(f,"************************************************************************************************************************")
|
PROFILER._flog( f, "************************************************************************************************************************" )
|
||||||
-- Close file.
|
-- Close file.
|
||||||
f:close()
|
f:close()
|
||||||
|
|
||||||
-- Print csv file.
|
|
||||||
PROFILER.printCSV(t, runTimeGame)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
-- Print csv file.
|
||||||
|
PROFILER.printCSV( t, runTimeGame )
|
||||||
|
end
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,6 @@
|
|||||||
--- **Utilities** DCS Simple Text-To-Speech (STTS).
|
--- **Utilities** DCS Simple Text-To-Speech (STTS).
|
||||||
--
|
--
|
||||||
--
|
--
|
||||||
--
|
|
||||||
-- @module Utils.STTS
|
-- @module Utils.STTS
|
||||||
-- @image MOOSE.JPG
|
-- @image MOOSE.JPG
|
||||||
|
|
||||||
@@ -10,29 +9,29 @@
|
|||||||
-- @field #string DIRECTORY Path of the SRS directory.
|
-- @field #string DIRECTORY Path of the SRS directory.
|
||||||
|
|
||||||
--- Simple Text-To-Speech
|
--- Simple Text-To-Speech
|
||||||
--
|
--
|
||||||
-- Version 0.4 - Compatible with SRS version 1.9.6.0+
|
-- Version 0.4 - Compatible with SRS version 1.9.6.0+
|
||||||
--
|
--
|
||||||
-- # DCS Modification Required
|
-- # DCS Modification Required
|
||||||
--
|
--
|
||||||
-- You will need to edit MissionScripting.lua in DCS World/Scripts/MissionScripting.lua and remove the sanitisation.
|
-- You will need to edit MissionScripting.lua in DCS World/Scripts/MissionScripting.lua and remove the sanitization.
|
||||||
-- To do this remove all the code below the comment - the line starts "local function sanitizeModule(name)"
|
-- To do this remove all the code below the comment - the line starts "local function sanitizeModule(name)"
|
||||||
-- Do this without DCS running to allow mission scripts to use os functions.
|
-- Do this without DCS running to allow mission scripts to use os functions.
|
||||||
--
|
--
|
||||||
-- *You WILL HAVE TO REAPPLY AFTER EVERY DCS UPDATE*
|
-- *You WILL HAVE TO REAPPLY AFTER EVERY DCS UPDATE*
|
||||||
--
|
--
|
||||||
-- # USAGE:
|
-- # USAGE:
|
||||||
--
|
--
|
||||||
-- Add this script into the mission as a DO SCRIPT or DO SCRIPT FROM FILE to initialise it
|
-- Add this script into the mission as a DO SCRIPT or DO SCRIPT FROM FILE to initialize it
|
||||||
-- Make sure to edit the STTS.SRS_PORT and STTS.DIRECTORY to the correct values before adding to the mission.
|
-- Make sure to edit the STTS.SRS_PORT and STTS.DIRECTORY to the correct values before adding to the mission.
|
||||||
-- Then its as simple as calling the correct function in LUA as a DO SCRIPT or in your own scripts.
|
-- Then its as simple as calling the correct function in LUA as a DO SCRIPT or in your own scripts.
|
||||||
--
|
--
|
||||||
-- Example calls:
|
-- Example calls:
|
||||||
--
|
--
|
||||||
-- STTS.TextToSpeech("Hello DCS WORLD","251","AM","1.0","SRS",2)
|
-- STTS.TextToSpeech("Hello DCS WORLD","251","AM","1.0","SRS",2)
|
||||||
--
|
--
|
||||||
-- Arguments in order are:
|
-- Arguments in order are:
|
||||||
--
|
--
|
||||||
-- * Message to say, make sure not to use a newline (\n) !
|
-- * Message to say, make sure not to use a newline (\n) !
|
||||||
-- * Frequency in MHz
|
-- * Frequency in MHz
|
||||||
-- * Modulation - AM/FM
|
-- * Modulation - AM/FM
|
||||||
@@ -43,44 +42,44 @@
|
|||||||
-- * OPTIONAL - Speed -10 to +10
|
-- * OPTIONAL - Speed -10 to +10
|
||||||
-- * OPTIONAL - Gender male, female or neuter
|
-- * OPTIONAL - Gender male, female or neuter
|
||||||
-- * OPTIONAL - Culture - en-US, en-GB etc
|
-- * OPTIONAL - Culture - en-US, en-GB etc
|
||||||
-- * OPTIONAL - Voice - a specfic voice by name. Run DCS-SR-ExternalAudio.exe with --help to get the ones you can use on the command line
|
-- * OPTIONAL - Voice - a specific voice by name. Run DCS-SR-ExternalAudio.exe with --help to get the ones you can use on the command line
|
||||||
-- * OPTIONAL - Google TTS - Switch to Google Text To Speech - Requires STTS.GOOGLE_CREDENTIALS path and Google project setup correctly
|
-- * OPTIONAL - Google TTS - Switch to Google Text To Speech - Requires STTS.GOOGLE_CREDENTIALS path and Google project setup correctly
|
||||||
--
|
--
|
||||||
--
|
--
|
||||||
-- ## Example
|
-- ## Example
|
||||||
--
|
--
|
||||||
-- This example will say the words "Hello DCS WORLD" on 251 MHz AM at maximum volume with a client called SRS and to the Blue coalition only
|
-- This example will say the words "Hello DCS WORLD" on 251 MHz AM at maximum volume with a client called SRS and to the Blue coalition only
|
||||||
--
|
--
|
||||||
-- STTS.TextToSpeech("Hello DCS WORLD","251","AM","1.0","SRS",2,null,-5,"male","en-GB")
|
-- STTS.TextToSpeech("Hello DCS WORLD","251","AM","1.0","SRS",2,null,-5,"male","en-GB")
|
||||||
--
|
--
|
||||||
-- ## Example
|
-- ## Example
|
||||||
--
|
--
|
||||||
--This example will say the words "Hello DCS WORLD" on 251 MHz AM at maximum volume with a client called SRS and to the Blue coalition only centered on the position of the Unit called "A UNIT"
|
-- This example will say the words "Hello DCS WORLD" on 251 MHz AM at maximum volume with a client called SRS and to the Blue coalition only centered on the position of the Unit called "A UNIT"
|
||||||
--
|
--
|
||||||
-- STTS.TextToSpeech("Hello DCS WORLD","251","AM","1.0","SRS",2,Unit.getByName("A UNIT"):getPoint(),-5,"male","en-GB")
|
-- STTS.TextToSpeech("Hello DCS WORLD","251","AM","1.0","SRS",2,Unit.getByName("A UNIT"):getPoint(),-5,"male","en-GB")
|
||||||
--
|
--
|
||||||
-- Arguments in order are:
|
-- Arguments in order are:
|
||||||
--
|
--
|
||||||
-- * FULL path to the MP3 OR OGG to play
|
-- * FULL path to the MP3 OR OGG to play
|
||||||
-- * Frequency in MHz - to use multiple separate with a comma - Number of frequencies MUST match number of Modulations
|
-- * Frequency in MHz - to use multiple separate with a comma - Number of frequencies MUST match number of Modulations
|
||||||
-- * Modulation - AM/FM - to use multiple
|
-- * Modulation - AM/FM - to use multiple
|
||||||
-- * Volume - 1.0 max, 0.5 half
|
-- * Volume - 1.0 max, 0.5 half
|
||||||
-- * Name of the transmitter - ATC, RockFM etc
|
-- * Name of the transmitter - ATC, RockFM etc
|
||||||
-- * Coalition - 0 spectator, 1 red 2 blue
|
-- * Coalition - 0 spectator, 1 red 2 blue
|
||||||
--
|
--
|
||||||
-- ## Example
|
-- ## Example
|
||||||
--
|
--
|
||||||
-- This will play that MP3 on 255MHz AM & 31 FM at half volume with a client called "Multiple" and to Spectators only
|
-- This will play that MP3 on 255MHz AM & 31 FM at half volume with a client called "Multiple" and to Spectators only
|
||||||
--
|
--
|
||||||
-- STTS.PlayMP3("C:\\Users\\Ciaran\\Downloads\\PR-Music.mp3","255,31","AM,FM","0.5","Multiple",0)
|
-- STTS.PlayMP3("C:\\Users\\Ciaran\\Downloads\\PR-Music.mp3","255,31","AM,FM","0.5","Multiple",0)
|
||||||
--
|
--
|
||||||
-- @field #STTS
|
-- @field #STTS
|
||||||
STTS={
|
STTS = {
|
||||||
ClassName="STTS",
|
ClassName = "STTS",
|
||||||
DIRECTORY="",
|
DIRECTORY = "",
|
||||||
SRS_PORT=5002,
|
SRS_PORT = 5002,
|
||||||
GOOGLE_CREDENTIALS="C:\\Users\\Ciaran\\Downloads\\googletts.json",
|
GOOGLE_CREDENTIALS = "C:\\Users\\Ciaran\\Downloads\\googletts.json",
|
||||||
EXECUTABLE="DCS-SR-ExternalAudio.exe",
|
EXECUTABLE = "DCS-SR-ExternalAudio.exe"
|
||||||
}
|
}
|
||||||
|
|
||||||
--- FULL Path to the FOLDER containing DCS-SR-ExternalAudio.exe - EDIT TO CORRECT FOLDER
|
--- FULL Path to the FOLDER containing DCS-SR-ExternalAudio.exe - EDIT TO CORRECT FOLDER
|
||||||
@@ -92,142 +91,144 @@ STTS.SRS_PORT = 5002
|
|||||||
--- Google credentials file
|
--- Google credentials file
|
||||||
STTS.GOOGLE_CREDENTIALS = "C:\\Users\\Ciaran\\Downloads\\googletts.json"
|
STTS.GOOGLE_CREDENTIALS = "C:\\Users\\Ciaran\\Downloads\\googletts.json"
|
||||||
|
|
||||||
--- DONT CHANGE THIS UNLESS YOU KNOW WHAT YOU'RE DOING
|
--- DON'T CHANGE THIS UNLESS YOU KNOW WHAT YOU'RE DOING
|
||||||
STTS.EXECUTABLE = "DCS-SR-ExternalAudio.exe"
|
STTS.EXECUTABLE = "DCS-SR-ExternalAudio.exe"
|
||||||
|
|
||||||
|
|
||||||
--- Function for UUID.
|
--- Function for UUID.
|
||||||
function STTS.uuid()
|
function STTS.uuid()
|
||||||
local random = math.random
|
local random = math.random
|
||||||
local template ='yxxx-xxxxxxxxxxxx'
|
local template = 'yxxx-xxxxxxxxxxxx'
|
||||||
return string.gsub(template, '[xy]', function (c)
|
return string.gsub( template, '[xy]', function( c )
|
||||||
local v = (c == 'x') and random(0, 0xf) or random(8, 0xb)
|
local v = (c == 'x') and random( 0, 0xf ) or random( 8, 0xb )
|
||||||
return string.format('%x', v)
|
return string.format( '%x', v )
|
||||||
end)
|
end )
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Round a number.
|
--- Round a number.
|
||||||
-- @param #number x Number.
|
-- @param #number x Number.
|
||||||
-- @param #number n Precision.
|
-- @param #number n Precision.
|
||||||
function STTS.round(x, n)
|
function STTS.round( x, n )
|
||||||
n = math.pow(10, n or 0)
|
n = math.pow( 10, n or 0 )
|
||||||
x = x * n
|
x = x * n
|
||||||
if x >= 0 then x = math.floor(x + 0.5) else x = math.ceil(x - 0.5) end
|
if x >= 0 then
|
||||||
|
x = math.floor( x + 0.5 )
|
||||||
|
else
|
||||||
|
x = math.ceil( x - 0.5 )
|
||||||
|
end
|
||||||
return x / n
|
return x / n
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Function returns estimated speech time in seconds.
|
--- Function returns estimated speech time in seconds.
|
||||||
-- Assumptions for time calc: 100 Words per min, avarage of 5 letters for english word so
|
-- Assumptions for time calc: 100 Words per min, average of 5 letters for english word so
|
||||||
--
|
--
|
||||||
-- * 5 chars * 100wpm = 500 characters per min = 8.3 chars per second
|
-- * 5 chars * 100wpm = 500 characters per min = 8.3 chars per second
|
||||||
--
|
--
|
||||||
-- So lengh of msg / 8.3 = number of seconds needed to read it. rounded down to 8 chars per sec map function:
|
-- So length of msg / 8.3 = number of seconds needed to read it. rounded down to 8 chars per sec map function:
|
||||||
--
|
--
|
||||||
-- * (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min
|
-- * (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min
|
||||||
--
|
--
|
||||||
function STTS.getSpeechTime(length,speed,isGoogle)
|
function STTS.getSpeechTime( length, speed, isGoogle )
|
||||||
|
|
||||||
local maxRateRatio = 3
|
local maxRateRatio = 3
|
||||||
|
|
||||||
speed = speed or 1.0
|
speed = speed or 1.0
|
||||||
isGoogle = isGoogle or false
|
isGoogle = isGoogle or false
|
||||||
|
|
||||||
local speedFactor = 1.0
|
local speedFactor = 1.0
|
||||||
if isGoogle then
|
if isGoogle then
|
||||||
speedFactor = speed
|
speedFactor = speed
|
||||||
else
|
else
|
||||||
if speed ~= 0 then
|
if speed ~= 0 then
|
||||||
speedFactor = math.abs(speed) * (maxRateRatio - 1) / 10 + 1
|
speedFactor = math.abs( speed ) * (maxRateRatio - 1) / 10 + 1
|
||||||
end
|
end
|
||||||
if speed < 0 then
|
if speed < 0 then
|
||||||
speedFactor = 1/speedFactor
|
speedFactor = 1 / speedFactor
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local wpm = math.ceil(100 * speedFactor)
|
local wpm = math.ceil( 100 * speedFactor )
|
||||||
local cps = math.floor((wpm * 5)/60)
|
local cps = math.floor( (wpm * 5) / 60 )
|
||||||
|
|
||||||
if type(length) == "string" then
|
if type( length ) == "string" then
|
||||||
length = string.len(length)
|
length = string.len( length )
|
||||||
end
|
end
|
||||||
|
|
||||||
return math.ceil(length/cps)
|
return math.ceil( length / cps )
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Text to speech function.
|
--- Text to speech function.
|
||||||
function STTS.TextToSpeech(message, freqs, modulations, volume, name, coalition, point, speed, gender, culture, voice, googleTTS)
|
function STTS.TextToSpeech( message, freqs, modulations, volume, name, coalition, point, speed, gender, culture, voice, googleTTS )
|
||||||
if os == nil or io == nil then
|
if os == nil or io == nil then
|
||||||
env.info("[DCS-STTS] LUA modules os or io are sanitized. skipping. ")
|
env.info( "[DCS-STTS] LUA modules os or io are sanitized. skipping. " )
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
speed = speed or 1
|
speed = speed or 1
|
||||||
gender = gender or "female"
|
gender = gender or "female"
|
||||||
culture = culture or ""
|
culture = culture or ""
|
||||||
voice = voice or ""
|
voice = voice or ""
|
||||||
coalition=coalition or "0"
|
coalition = coalition or "0"
|
||||||
name=name or "ROBOT"
|
name = name or "ROBOT"
|
||||||
volume=1
|
volume = 1
|
||||||
speed=1
|
speed = 1
|
||||||
|
|
||||||
|
message = message:gsub( "\"", "\\\"" )
|
||||||
|
|
||||||
|
local cmd = string.format( "start /min \"\" /d \"%s\" /b \"%s\" -f %s -m %s -c %s -p %s -n \"%s\" -h", STTS.DIRECTORY, STTS.EXECUTABLE, freqs or "305", modulations or "AM", coalition, STTS.SRS_PORT, name )
|
||||||
|
|
||||||
message = message:gsub("\"","\\\"")
|
|
||||||
|
|
||||||
local cmd = string.format("start /min \"\" /d \"%s\" /b \"%s\" -f %s -m %s -c %s -p %s -n \"%s\" -h", STTS.DIRECTORY, STTS.EXECUTABLE, freqs or "305", modulations or "AM", coalition, STTS.SRS_PORT, name)
|
|
||||||
|
|
||||||
if voice ~= "" then
|
if voice ~= "" then
|
||||||
cmd = cmd .. string.format(" -V \"%s\"",voice)
|
cmd = cmd .. string.format( " -V \"%s\"", voice )
|
||||||
else
|
else
|
||||||
|
|
||||||
if culture ~= "" then
|
if culture ~= "" then
|
||||||
cmd = cmd .. string.format(" -l %s",culture)
|
cmd = cmd .. string.format( " -l %s", culture )
|
||||||
end
|
end
|
||||||
|
|
||||||
if gender ~= "" then
|
if gender ~= "" then
|
||||||
cmd = cmd .. string.format(" -g %s",gender)
|
cmd = cmd .. string.format( " -g %s", gender )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if googleTTS == true then
|
if googleTTS == true then
|
||||||
cmd = cmd .. string.format(" -G \"%s\"",STTS.GOOGLE_CREDENTIALS)
|
cmd = cmd .. string.format( " -G \"%s\"", STTS.GOOGLE_CREDENTIALS )
|
||||||
end
|
end
|
||||||
|
|
||||||
if speed ~= 1 then
|
if speed ~= 1 then
|
||||||
cmd = cmd .. string.format(" -s %s",speed)
|
cmd = cmd .. string.format( " -s %s", speed )
|
||||||
end
|
end
|
||||||
|
|
||||||
if volume ~= 1.0 then
|
if volume ~= 1.0 then
|
||||||
cmd = cmd .. string.format(" -v %s",volume)
|
cmd = cmd .. string.format( " -v %s", volume )
|
||||||
end
|
end
|
||||||
|
|
||||||
if point and type(point) == "table" and point.x then
|
if point and type( point ) == "table" and point.x then
|
||||||
local lat, lon, alt = coord.LOtoLL(point)
|
local lat, lon, alt = coord.LOtoLL( point )
|
||||||
|
|
||||||
lat = STTS.round(lat,4)
|
lat = STTS.round( lat, 4 )
|
||||||
lon = STTS.round(lon,4)
|
lon = STTS.round( lon, 4 )
|
||||||
alt = math.floor(alt)
|
alt = math.floor( alt )
|
||||||
|
|
||||||
cmd = cmd .. string.format(" -L %s -O %s -A %s",lat,lon,alt)
|
cmd = cmd .. string.format( " -L %s -O %s -A %s", lat, lon, alt )
|
||||||
end
|
end
|
||||||
|
|
||||||
cmd = cmd ..string.format(" -t \"%s\"",message)
|
cmd = cmd .. string.format( " -t \"%s\"", message )
|
||||||
|
|
||||||
if string.len(cmd) > 255 then
|
if string.len( cmd ) > 255 then
|
||||||
local filename = os.getenv('TMP') .. "\\DCS_STTS-" .. STTS.uuid() .. ".bat"
|
local filename = os.getenv( 'TMP' ) .. "\\DCS_STTS-" .. STTS.uuid() .. ".bat"
|
||||||
local script = io.open(filename,"w+")
|
local script = io.open( filename, "w+" )
|
||||||
script:write(cmd .. " && exit" )
|
script:write( cmd .. " && exit" )
|
||||||
script:close()
|
script:close()
|
||||||
cmd = string.format("\"%s\"",filename)
|
cmd = string.format( "\"%s\"", filename )
|
||||||
timer.scheduleFunction(os.remove, filename, timer.getTime() + 1)
|
timer.scheduleFunction( os.remove, filename, timer.getTime() + 1 )
|
||||||
end
|
end
|
||||||
|
|
||||||
if string.len(cmd) > 255 then
|
if string.len( cmd ) > 255 then
|
||||||
env.info("[DCS-STTS] - cmd string too long")
|
env.info( "[DCS-STTS] - cmd string too long" )
|
||||||
env.info("[DCS-STTS] TextToSpeech Command :\n" .. cmd.."\n")
|
env.info( "[DCS-STTS] TextToSpeech Command :\n" .. cmd .. "\n" )
|
||||||
end
|
end
|
||||||
os.execute(cmd)
|
os.execute( cmd )
|
||||||
|
|
||||||
return STTS.getSpeechTime(message,speed,googleTTS)
|
return STTS.getSpeechTime( message, speed, googleTTS )
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Play mp3 function.
|
--- Play mp3 function.
|
||||||
@@ -235,22 +236,21 @@ end
|
|||||||
-- @param #string freqs Frequencies, e.g. "305, 256".
|
-- @param #string freqs Frequencies, e.g. "305, 256".
|
||||||
-- @param #string modulations Modulations, e.g. "AM, FM".
|
-- @param #string modulations Modulations, e.g. "AM, FM".
|
||||||
-- @param #string volume Volume, e.g. "0.5".
|
-- @param #string volume Volume, e.g. "0.5".
|
||||||
function STTS.PlayMP3(pathToMP3, freqs, modulations, volume, name, coalition, point)
|
function STTS.PlayMP3( pathToMP3, freqs, modulations, volume, name, coalition, point )
|
||||||
|
|
||||||
local cmd = string.format("start \"\" /d \"%s\" /b /min \"%s\" -i \"%s\" -f %s -m %s -c %s -p %s -n \"%s\" -v %s -h",
|
local cmd = string.format( "start \"\" /d \"%s\" /b /min \"%s\" -i \"%s\" -f %s -m %s -c %s -p %s -n \"%s\" -v %s -h", STTS.DIRECTORY, STTS.EXECUTABLE, pathToMP3, freqs or "305", modulations or "AM", coalition or "0", STTS.SRS_PORT, name or "ROBOT", volume or "1" )
|
||||||
STTS.DIRECTORY, STTS.EXECUTABLE, pathToMP3, freqs or "305", modulations or "AM", coalition or "0", STTS.SRS_PORT, name or "ROBOT", volume or "1")
|
|
||||||
|
|
||||||
if point and type(point) == "table" and point.x then
|
|
||||||
local lat, lon, alt = coord.LOtoLL(point)
|
|
||||||
|
|
||||||
lat = STTS.round(lat,4)
|
if point and type( point ) == "table" and point.x then
|
||||||
lon = STTS.round(lon,4)
|
local lat, lon, alt = coord.LOtoLL( point )
|
||||||
alt = math.floor(alt)
|
|
||||||
|
|
||||||
cmd = cmd .. string.format(" -L %s -O %s -A %s",lat,lon,alt)
|
lat = STTS.round( lat, 4 )
|
||||||
end
|
lon = STTS.round( lon, 4 )
|
||||||
|
alt = math.floor( alt )
|
||||||
|
|
||||||
env.info("[DCS-STTS] MP3/OGG Command :\n" .. cmd.."\n")
|
cmd = cmd .. string.format( " -L %s -O %s -A %s", lat, lon, alt )
|
||||||
os.execute(cmd)
|
end
|
||||||
|
|
||||||
end
|
env.info( "[DCS-STTS] MP3/OGG Command :\n" .. cmd .. "\n" )
|
||||||
|
os.execute( cmd )
|
||||||
|
|
||||||
|
end
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -17,6 +17,7 @@
|
|||||||
-- @field #table CategoryName Names of airbase categories.
|
-- @field #table CategoryName Names of airbase categories.
|
||||||
-- @field #string AirbaseName Name of the airbase.
|
-- @field #string AirbaseName Name of the airbase.
|
||||||
-- @field #number AirbaseID Airbase ID.
|
-- @field #number AirbaseID Airbase ID.
|
||||||
|
-- @field Core.Zone#ZONE AirbaseZone Circular zone around the airbase with a radius of 2500 meters. For ships this is a ZONE_UNIT object.
|
||||||
-- @field #number category Airbase category.
|
-- @field #number category Airbase category.
|
||||||
-- @field #table descriptors DCS descriptors.
|
-- @field #table descriptors DCS descriptors.
|
||||||
-- @field #boolean isAirdrome Airbase is an airdrome.
|
-- @field #boolean isAirdrome Airbase is an airdrome.
|
||||||
@@ -526,19 +527,19 @@ function AIRBASE:Register(AirbaseName)
|
|||||||
|
|
||||||
-- Inherit everything from positionable.
|
-- Inherit everything from positionable.
|
||||||
local self=BASE:Inherit(self, POSITIONABLE:New(AirbaseName)) --#AIRBASE
|
local self=BASE:Inherit(self, POSITIONABLE:New(AirbaseName)) --#AIRBASE
|
||||||
|
|
||||||
-- Set airbase name.
|
-- Set airbase name.
|
||||||
self.AirbaseName=AirbaseName
|
self.AirbaseName=AirbaseName
|
||||||
|
|
||||||
-- Set airbase ID.
|
-- Set airbase ID.
|
||||||
self.AirbaseID=self:GetID(true)
|
self.AirbaseID=self:GetID(true)
|
||||||
|
|
||||||
-- Get descriptors.
|
-- Get descriptors.
|
||||||
self.descriptors=self:GetDesc()
|
self.descriptors=self:GetDesc()
|
||||||
|
|
||||||
-- Category.
|
-- Category.
|
||||||
self.category=self.descriptors and self.descriptors.category or Airbase.Category.AIRDROME
|
self.category=self.descriptors and self.descriptors.category or Airbase.Category.AIRDROME
|
||||||
|
|
||||||
-- Set category.
|
-- Set category.
|
||||||
if self.category==Airbase.Category.AIRDROME then
|
if self.category==Airbase.Category.AIRDROME then
|
||||||
self.isAirdrome=true
|
self.isAirdrome=true
|
||||||
@@ -546,20 +547,33 @@ function AIRBASE:Register(AirbaseName)
|
|||||||
self.isHelipad=true
|
self.isHelipad=true
|
||||||
elseif self.category==Airbase.Category.SHIP then
|
elseif self.category==Airbase.Category.SHIP then
|
||||||
self.isShip=true
|
self.isShip=true
|
||||||
|
-- DCS bug: Oil rigs and gas platforms have category=2 (ship). Also they cannot be retrieved by coalition.getStaticObjects()
|
||||||
|
if self.descriptors.typeName=="Oil rig" or self.descriptors.typeName=="Ga" then
|
||||||
|
self.isHelipad=true
|
||||||
|
self.isShip=false
|
||||||
|
self.category=Airbase.Category.HELIPAD
|
||||||
|
_DATABASE:AddStatic(AirbaseName)
|
||||||
|
end
|
||||||
else
|
else
|
||||||
self:E("ERROR: Unknown airbase category!")
|
self:E("ERROR: Unknown airbase category!")
|
||||||
end
|
end
|
||||||
|
|
||||||
self:_InitParkingSpots()
|
self:_InitParkingSpots()
|
||||||
|
|
||||||
local vec2=self:GetVec2()
|
local vec2=self:GetVec2()
|
||||||
|
|
||||||
-- Init coordinate.
|
-- Init coordinate.
|
||||||
self:GetCoordinate()
|
self:GetCoordinate()
|
||||||
|
|
||||||
if vec2 then
|
if vec2 then
|
||||||
-- TODO: For ships we need a moving zone.
|
if self.isShip then
|
||||||
self.AirbaseZone=ZONE_RADIUS:New( AirbaseName, vec2, 2500 )
|
local unit=UNIT:FindByName(AirbaseName)
|
||||||
|
if unit then
|
||||||
|
self.AirbaseZone=ZONE_UNIT:New(AirbaseName, unit, 2500)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
self.AirbaseZone=ZONE_RADIUS:New(AirbaseName, vec2, 2500)
|
||||||
|
end
|
||||||
else
|
else
|
||||||
self:E(string.format("ERROR: Cound not get position Vec2 of airbase %s", AirbaseName))
|
self:E(string.format("ERROR: Cound not get position Vec2 of airbase %s", AirbaseName))
|
||||||
end
|
end
|
||||||
@@ -693,7 +707,7 @@ function AIRBASE:GetID(unique)
|
|||||||
local airbaseID=tonumber(DCSAirbase:getID())
|
local airbaseID=tonumber(DCSAirbase:getID())
|
||||||
|
|
||||||
local airbaseCategory=self:GetAirbaseCategory()
|
local airbaseCategory=self:GetAirbaseCategory()
|
||||||
|
|
||||||
if AirbaseName==self.AirbaseName then
|
if AirbaseName==self.AirbaseName then
|
||||||
if airbaseCategory==Airbase.Category.SHIP or airbaseCategory==Airbase.Category.HELIPAD then
|
if airbaseCategory==Airbase.Category.SHIP or airbaseCategory==Airbase.Category.HELIPAD then
|
||||||
-- Ships get a negative sign as their unit number might be the same as the ID of another airbase.
|
-- Ships get a negative sign as their unit number might be the same as the ID of another airbase.
|
||||||
@@ -932,16 +946,16 @@ function AIRBASE:_InitParkingSpots()
|
|||||||
-- Init table.
|
-- Init table.
|
||||||
self.parking={}
|
self.parking={}
|
||||||
self.parkingByID={}
|
self.parkingByID={}
|
||||||
|
|
||||||
self.NparkingTotal=0
|
self.NparkingTotal=0
|
||||||
self.NparkingTerminal={}
|
self.NparkingTerminal={}
|
||||||
for _,terminalType in pairs(AIRBASE.TerminalType) do
|
for _,terminalType in pairs(AIRBASE.TerminalType) do
|
||||||
self.NparkingTerminal[terminalType]=0
|
self.NparkingTerminal[terminalType]=0
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Put coordinates of parking spots into table.
|
-- Put coordinates of parking spots into table.
|
||||||
for _,spot in pairs(parkingdata) do
|
for _,spot in pairs(parkingdata) do
|
||||||
|
|
||||||
-- New parking spot.
|
-- New parking spot.
|
||||||
local park={} --#AIRBASE.ParkingSpot
|
local park={} --#AIRBASE.ParkingSpot
|
||||||
park.Vec3=spot.vTerminalPos
|
park.Vec3=spot.vTerminalPos
|
||||||
@@ -952,15 +966,15 @@ function AIRBASE:_InitParkingSpots()
|
|||||||
park.TerminalID0=spot.Term_Index_0
|
park.TerminalID0=spot.Term_Index_0
|
||||||
park.TerminalType=spot.Term_Type
|
park.TerminalType=spot.Term_Type
|
||||||
park.TOAC=spot.TO_AC
|
park.TOAC=spot.TO_AC
|
||||||
|
|
||||||
self.NparkingTotal=self.NparkingTotal+1
|
self.NparkingTotal=self.NparkingTotal+1
|
||||||
|
|
||||||
for _,terminalType in pairs(AIRBASE.TerminalType) do
|
for _,terminalType in pairs(AIRBASE.TerminalType) do
|
||||||
if self._CheckTerminalType(terminalType, park.TerminalType) then
|
if self._CheckTerminalType(terminalType, park.TerminalType) then
|
||||||
self.NparkingTerminal[terminalType]=self.NparkingTerminal[terminalType]+1
|
self.NparkingTerminal[terminalType]=self.NparkingTerminal[terminalType]+1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
self.parkingByID[park.TerminalID]=park
|
self.parkingByID[park.TerminalID]=park
|
||||||
table.insert(self.parking, park)
|
table.insert(self.parking, park)
|
||||||
end
|
end
|
||||||
@@ -984,7 +998,7 @@ function AIRBASE:GetParkingSpotsTable(termtype)
|
|||||||
|
|
||||||
-- Get parking data of all spots (free or occupied)
|
-- Get parking data of all spots (free or occupied)
|
||||||
local parkingdata=self:GetParkingData(false)
|
local parkingdata=self:GetParkingData(false)
|
||||||
|
|
||||||
-- Get parking data of all free spots.
|
-- Get parking data of all free spots.
|
||||||
local parkingfree=self:GetParkingData(true)
|
local parkingfree=self:GetParkingData(true)
|
||||||
|
|
||||||
@@ -1001,17 +1015,26 @@ function AIRBASE:GetParkingSpotsTable(termtype)
|
|||||||
-- Put coordinates of parking spots into table.
|
-- Put coordinates of parking spots into table.
|
||||||
local spots={}
|
local spots={}
|
||||||
for _,_spot in pairs(parkingdata) do
|
for _,_spot in pairs(parkingdata) do
|
||||||
|
|
||||||
if AIRBASE._CheckTerminalType(_spot.Term_Type, termtype) then
|
if AIRBASE._CheckTerminalType(_spot.Term_Type, termtype) then
|
||||||
|
|
||||||
local spot=self:_GetParkingSpotByID(_spot.Term_Index)
|
local spot=self:_GetParkingSpotByID(_spot.Term_Index)
|
||||||
|
|
||||||
spot.Free=_isfree(_spot) -- updated
|
if spot then
|
||||||
spot.TOAC=_spot.TO_AC -- updated
|
|
||||||
|
spot.Free=_isfree(_spot) -- updated
|
||||||
table.insert(spots, spot)
|
spot.TOAC=_spot.TO_AC -- updated
|
||||||
|
|
||||||
|
table.insert(spots, spot)
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
self:E(string.format("ERROR: Parking spot %s is nil!", tostring(_spot.Term_Index)))
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return spots
|
return spots
|
||||||
@@ -1032,14 +1055,14 @@ function AIRBASE:GetFreeParkingSpotsTable(termtype, allowTOAC)
|
|||||||
for _,_spot in pairs(parkingfree) do
|
for _,_spot in pairs(parkingfree) do
|
||||||
if AIRBASE._CheckTerminalType(_spot.Term_Type, termtype) and _spot.Term_Index>0 then
|
if AIRBASE._CheckTerminalType(_spot.Term_Type, termtype) and _spot.Term_Index>0 then
|
||||||
if (allowTOAC and allowTOAC==true) or _spot.TO_AC==false then
|
if (allowTOAC and allowTOAC==true) or _spot.TO_AC==false then
|
||||||
|
|
||||||
local spot=self:_GetParkingSpotByID(_spot.Term_Index)
|
local spot=self:_GetParkingSpotByID(_spot.Term_Index)
|
||||||
|
|
||||||
spot.Free=true -- updated
|
spot.Free=true -- updated
|
||||||
spot.TOAC=_spot.TO_AC -- updated
|
spot.TOAC=_spot.TO_AC -- updated
|
||||||
|
|
||||||
table.insert(freespots, spot)
|
table.insert(freespots, spot)
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -1084,7 +1107,7 @@ function AIRBASE:MarkParkingSpots(termtype, mark)
|
|||||||
|
|
||||||
-- Get airbase name.
|
-- Get airbase name.
|
||||||
local airbasename=self:GetName()
|
local airbasename=self:GetName()
|
||||||
self:E(string.format("Parking spots at %s for termial type %s:", airbasename, tostring(termtype)))
|
self:E(string.format("Parking spots at %s for terminal type %s:", airbasename, tostring(termtype)))
|
||||||
|
|
||||||
for _,_spot in pairs(parkingdata) do
|
for _,_spot in pairs(parkingdata) do
|
||||||
|
|
||||||
@@ -1118,7 +1141,7 @@ end
|
|||||||
-- @param #table parkingdata (Optional) Parking spots data table. If not given it is automatically derived from the GetParkingSpotsTable() function.
|
-- @param #table parkingdata (Optional) Parking spots data table. If not given it is automatically derived from the GetParkingSpotsTable() function.
|
||||||
-- @return #table Table of coordinates and terminal IDs of free parking spots. Each table entry has the elements .Coordinate and .TerminalID.
|
-- @return #table Table of coordinates and terminal IDs of free parking spots. Each table entry has the elements .Coordinate and .TerminalID.
|
||||||
function AIRBASE:FindFreeParkingSpotForAircraft(group, terminaltype, scanradius, scanunits, scanstatics, scanscenery, verysafe, nspots, parkingdata)
|
function AIRBASE:FindFreeParkingSpotForAircraft(group, terminaltype, scanradius, scanunits, scanstatics, scanscenery, verysafe, nspots, parkingdata)
|
||||||
|
|
||||||
-- Init default
|
-- Init default
|
||||||
scanradius=scanradius or 50
|
scanradius=scanradius or 50
|
||||||
if scanunits==nil then
|
if scanunits==nil then
|
||||||
@@ -1161,14 +1184,25 @@ function AIRBASE:FindFreeParkingSpotForAircraft(group, terminaltype, scanradius,
|
|||||||
parkingdata=parkingdata or self:GetParkingSpotsTable(terminaltype)
|
parkingdata=parkingdata or self:GetParkingSpotsTable(terminaltype)
|
||||||
|
|
||||||
-- Get the aircraft size, i.e. it's longest side of x,z.
|
-- Get the aircraft size, i.e. it's longest side of x,z.
|
||||||
local aircraft=group:GetUnit(1)
|
local aircraft = nil -- fix local problem below
|
||||||
local _aircraftsize, ax,ay,az=aircraft:GetObjectSize()
|
local _aircraftsize, ax,ay,az
|
||||||
|
if group and group.ClassName == "GROUP" then
|
||||||
|
aircraft=group:GetUnit(1)
|
||||||
|
_aircraftsize, ax,ay,az=aircraft:GetObjectSize()
|
||||||
|
else
|
||||||
|
-- SU27 dimensions
|
||||||
|
_aircraftsize = 23
|
||||||
|
ax = 23 -- length
|
||||||
|
ay = 7 -- height
|
||||||
|
az = 17 -- width
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Number of spots we are looking for. Note that, e.g. grouping can require a number different from the group size!
|
-- Number of spots we are looking for. Note that, e.g. grouping can require a number different from the group size!
|
||||||
local _nspots=nspots or group:GetSize()
|
local _nspots=nspots or group:GetSize()
|
||||||
|
|
||||||
-- Debug info.
|
-- Debug info.
|
||||||
self:E(string.format("%s: Looking for %d parking spot(s) for aircraft of size %.1f m (x=%.1f,y=%.1f,z=%.1f) at termial type %s.", airport, _nspots, _aircraftsize, ax, ay, az, tostring(terminaltype)))
|
self:E(string.format("%s: Looking for %d parking spot(s) for aircraft of size %.1f m (x=%.1f,y=%.1f,z=%.1f) at terminal type %s.", airport, _nspots, _aircraftsize, ax, ay, az, tostring(terminaltype)))
|
||||||
|
|
||||||
-- Table of valid spots.
|
-- Table of valid spots.
|
||||||
local validspots={}
|
local validspots={}
|
||||||
@@ -1291,6 +1325,7 @@ function AIRBASE:FindFreeParkingSpotForAircraft(group, terminaltype, scanradius,
|
|||||||
|
|
||||||
-- Retrun spots we found, even if there were not enough.
|
-- Retrun spots we found, even if there were not enough.
|
||||||
return validspots
|
return validspots
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Check black and white lists.
|
--- Check black and white lists.
|
||||||
@@ -1392,7 +1427,7 @@ function AIRBASE:GetRunwayData(magvar, mark)
|
|||||||
|
|
||||||
-- Get spawn points on runway. These can be used to determine the runway heading.
|
-- Get spawn points on runway. These can be used to determine the runway heading.
|
||||||
local runwaycoords=self:GetParkingSpotsCoordinates(AIRBASE.TerminalType.Runway)
|
local runwaycoords=self:GetParkingSpotsCoordinates(AIRBASE.TerminalType.Runway)
|
||||||
|
|
||||||
-- Debug: For finding the numbers of the spawn points belonging to each runway.
|
-- Debug: For finding the numbers of the spawn points belonging to each runway.
|
||||||
if false then
|
if false then
|
||||||
for i,_coord in pairs(runwaycoords) do
|
for i,_coord in pairs(runwaycoords) do
|
||||||
@@ -1411,7 +1446,7 @@ function AIRBASE:GetRunwayData(magvar, mark)
|
|||||||
|
|
||||||
-- Airbase name.
|
-- Airbase name.
|
||||||
local name=self:GetName()
|
local name=self:GetName()
|
||||||
|
|
||||||
|
|
||||||
-- Exceptions
|
-- Exceptions
|
||||||
if name==AIRBASE.Nevada.Jean_Airport or
|
if name==AIRBASE.Nevada.Jean_Airport or
|
||||||
@@ -1424,36 +1459,36 @@ function AIRBASE:GetRunwayData(magvar, mark)
|
|||||||
|
|
||||||
-- 1-->4, 2-->3, 3-->2, 4-->1
|
-- 1-->4, 2-->3, 3-->2, 4-->1
|
||||||
exception=1
|
exception=1
|
||||||
|
|
||||||
elseif UTILS.GetDCSMap()==DCSMAP.Syria and N>=2 and
|
elseif UTILS.GetDCSMap()==DCSMAP.Syria and N>=2 and
|
||||||
name~=AIRBASE.Syria.Minakh and
|
name~=AIRBASE.Syria.Minakh and
|
||||||
name~=AIRBASE.Syria.Damascus and
|
name~=AIRBASE.Syria.Damascus and
|
||||||
name~=AIRBASE.Syria.Khalkhalah and
|
name~=AIRBASE.Syria.Khalkhalah and
|
||||||
name~=AIRBASE.Syria.Marj_Ruhayyil and
|
name~=AIRBASE.Syria.Marj_Ruhayyil and
|
||||||
name~=AIRBASE.Syria.Beirut_Rafic_Hariri then
|
name~=AIRBASE.Syria.Beirut_Rafic_Hariri then
|
||||||
|
|
||||||
-- 1-->3, 2-->4, 3-->1, 4-->2
|
-- 1-->3, 2-->4, 3-->1, 4-->2
|
||||||
exception=2
|
exception=2
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Function returning the index of the runway coordinate belonding to the given index i.
|
--- Function returning the index of the runway coordinate belonding to the given index i.
|
||||||
local function f(i)
|
local function f(i)
|
||||||
|
|
||||||
local j
|
local j
|
||||||
|
|
||||||
if exception==1 then
|
if exception==1 then
|
||||||
|
|
||||||
j=N-(i-1) -- 1-->4, 2-->3
|
j=N-(i-1) -- 1-->4, 2-->3
|
||||||
|
|
||||||
elseif exception==2 then
|
elseif exception==2 then
|
||||||
|
|
||||||
if i<=N2 then
|
if i<=N2 then
|
||||||
j=i+N2 -- 1-->3, 2-->4
|
j=i+N2 -- 1-->3, 2-->4
|
||||||
else
|
else
|
||||||
j=i-N2 -- 3-->1, 4-->3
|
j=i-N2 -- 3-->1, 4-->3
|
||||||
end
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
if i%2==0 then
|
if i%2==0 then
|
||||||
@@ -1461,9 +1496,9 @@ function AIRBASE:GetRunwayData(magvar, mark)
|
|||||||
else
|
else
|
||||||
j=i+1 -- odd 1-->2, 3-->4
|
j=i+1 -- odd 1-->2, 3-->4
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Special case where there is no obvious order.
|
-- Special case where there is no obvious order.
|
||||||
if name==AIRBASE.Syria.Beirut_Rafic_Hariri then
|
if name==AIRBASE.Syria.Beirut_Rafic_Hariri then
|
||||||
if i==1 then
|
if i==1 then
|
||||||
@@ -1496,7 +1531,7 @@ function AIRBASE:GetRunwayData(magvar, mark)
|
|||||||
j=2
|
j=2
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return j
|
return j
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1505,7 +1540,7 @@ function AIRBASE:GetRunwayData(magvar, mark)
|
|||||||
|
|
||||||
-- Get the other spawn point coordinate.
|
-- Get the other spawn point coordinate.
|
||||||
local j=f(i)
|
local j=f(i)
|
||||||
|
|
||||||
-- Debug info.
|
-- Debug info.
|
||||||
--env.info(string.format("Runway i=%s j=%s (N=%d #runwaycoord=%d)", tostring(i), tostring(j), N, #runwaycoords))
|
--env.info(string.format("Runway i=%s j=%s (N=%d #runwaycoord=%d)", tostring(i), tostring(j), N, #runwaycoords))
|
||||||
|
|
||||||
|
|||||||
@@ -3779,8 +3779,9 @@ end
|
|||||||
-- @param #number radius Radius of the relocation zone, default 500
|
-- @param #number radius Radius of the relocation zone, default 500
|
||||||
-- @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"
|
||||||
-- @return #CONTROLLABLE self
|
-- @return #CONTROLLABLE self
|
||||||
function CONTROLLABLE:RelocateGroundRandomInRadius(speed, radius, onroad, shortcut)
|
function CONTROLLABLE:RelocateGroundRandomInRadius(speed, radius, onroad, shortcut, formation)
|
||||||
self:F2( { self.ControllableName } )
|
self:F2( { self.ControllableName } )
|
||||||
|
|
||||||
local _coord = self:GetCoordinate()
|
local _coord = self:GetCoordinate()
|
||||||
@@ -3791,14 +3792,14 @@ function CONTROLLABLE:RelocateGroundRandomInRadius(speed, radius, onroad, shortc
|
|||||||
local _grptsk = {}
|
local _grptsk = {}
|
||||||
local _candoroad = false
|
local _candoroad = false
|
||||||
local _shortcut = shortcut or false
|
local _shortcut = shortcut or false
|
||||||
|
local _formation = formation or "Off Road"
|
||||||
|
|
||||||
-- create a DCS Task an push it on the group
|
-- create a DCS Task an push it on the group
|
||||||
-- TaskGroundOnRoad(ToCoordinate,Speed,OffRoadFormation,Shortcut,FromCoordinate,WaypointFunction,WaypointFunctionArguments)
|
|
||||||
if onroad then
|
if onroad then
|
||||||
_grptsk, _candoroad = self:TaskGroundOnRoad(_tocoord,_speed,"Off Road",_shortcut)
|
_grptsk, _candoroad = self:TaskGroundOnRoad(_tocoord,_speed,_formation,_shortcut)
|
||||||
self:Route(_grptsk,5)
|
self:Route(_grptsk,5)
|
||||||
else
|
else
|
||||||
self:TaskRouteToVec2(_tocoord:GetVec2(),_speed,"Off Road")
|
self:TaskRouteToVec2(_tocoord:GetVec2(),_speed,_formation)
|
||||||
end
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
|
|||||||
@@ -310,8 +310,7 @@ end
|
|||||||
|
|
||||||
--- Returns the @{DCS#Position3} position vectors indicating the point and direction vectors in 3D of the POSITIONABLE within the mission.
|
--- Returns the @{DCS#Position3} position vectors indicating the point and direction vectors in 3D of the POSITIONABLE within the mission.
|
||||||
-- @param Wrapper.Positionable#POSITIONABLE self
|
-- @param Wrapper.Positionable#POSITIONABLE self
|
||||||
-- @return DCS#Position The 3D position vectors of the POSITIONABLE.
|
-- @return DCS#Position The 3D position vectors of the POSITIONABLE or #nil if the groups not existing or alive.
|
||||||
-- @return #nil The POSITIONABLE is not existing or alive.
|
|
||||||
function GROUP:GetPositionVec3() -- Overridden from POSITIONABLE:GetPositionVec3()
|
function GROUP:GetPositionVec3() -- Overridden from POSITIONABLE:GetPositionVec3()
|
||||||
self:F2( self.PositionableName )
|
self:F2( self.PositionableName )
|
||||||
|
|
||||||
@@ -339,9 +338,7 @@ end
|
|||||||
-- If the first @{Wrapper.Unit} of the group is inactive, it will return false.
|
-- If the first @{Wrapper.Unit} of the group is inactive, it will return false.
|
||||||
--
|
--
|
||||||
-- @param #GROUP self
|
-- @param #GROUP self
|
||||||
-- @return #boolean true if the group is alive and active.
|
-- @return #boolean `true` if the group is alive *and* active, `false` if the group is alive but inactive or `#nil` if the group does not exist anymore.
|
||||||
-- @return #boolean false if the group is alive but inactive.
|
|
||||||
-- @return #nil if the group does not exist anymore.
|
|
||||||
function GROUP:IsAlive()
|
function GROUP:IsAlive()
|
||||||
self:F2( self.GroupName )
|
self:F2( self.GroupName )
|
||||||
|
|
||||||
@@ -363,8 +360,7 @@ end
|
|||||||
|
|
||||||
--- Returns if the group is activated.
|
--- Returns if the group is activated.
|
||||||
-- @param #GROUP self
|
-- @param #GROUP self
|
||||||
-- @return #boolean true if group is activated.
|
-- @return #boolean `true` if group is activated or `#nil` The group is not existing or alive.
|
||||||
-- @return #nil The group is not existing or alive.
|
|
||||||
function GROUP:IsActive()
|
function GROUP:IsActive()
|
||||||
self:F2( self.GroupName )
|
self:F2( self.GroupName )
|
||||||
|
|
||||||
@@ -412,7 +408,6 @@ function GROUP:Destroy( GenerateEvent, delay )
|
|||||||
self:F2( self.GroupName )
|
self:F2( self.GroupName )
|
||||||
|
|
||||||
if delay and delay>0 then
|
if delay and delay>0 then
|
||||||
--SCHEDULER:New(nil, GROUP.Destroy, {self, GenerateEvent}, delay)
|
|
||||||
self:ScheduleOnce(delay, GROUP.Destroy, self, GenerateEvent)
|
self:ScheduleOnce(delay, GROUP.Destroy, self, GenerateEvent)
|
||||||
else
|
else
|
||||||
|
|
||||||
@@ -568,12 +563,12 @@ function GROUP:GetSpeedMax()
|
|||||||
|
|
||||||
local Units=self:GetUnits()
|
local Units=self:GetUnits()
|
||||||
|
|
||||||
local speedmax=nil
|
local speedmax=0
|
||||||
|
|
||||||
for _,unit in pairs(Units) do
|
for _,unit in pairs(Units) do
|
||||||
local unit=unit --Wrapper.Unit#UNIT
|
local unit=unit --Wrapper.Unit#UNIT
|
||||||
local speed=unit:GetSpeedMax()
|
local speed=unit:GetSpeedMax()
|
||||||
if speedmax==nil then
|
if speedmax==0 then
|
||||||
speedmax=speed
|
speedmax=speed
|
||||||
elseif speed<speedmax then
|
elseif speed<speedmax then
|
||||||
speedmax=speed
|
speedmax=speed
|
||||||
@@ -1137,7 +1132,7 @@ end
|
|||||||
-- @return #number Number of shells left.
|
-- @return #number Number of shells left.
|
||||||
-- @return #number Number of rockets left.
|
-- @return #number Number of rockets left.
|
||||||
-- @return #number Number of bombs left.
|
-- @return #number Number of bombs left.
|
||||||
-- @return #number Number of missiles left.
|
-- @return #number Number of missiles left.
|
||||||
function GROUP:GetAmmunition()
|
function GROUP:GetAmmunition()
|
||||||
self:F( self.ControllableName )
|
self:F( self.ControllableName )
|
||||||
|
|
||||||
@@ -1147,6 +1142,7 @@ function GROUP:GetAmmunition()
|
|||||||
local Nshells=0
|
local Nshells=0
|
||||||
local Nrockets=0
|
local Nrockets=0
|
||||||
local Nmissiles=0
|
local Nmissiles=0
|
||||||
|
local Nbombs=0
|
||||||
|
|
||||||
if DCSControllable then
|
if DCSControllable then
|
||||||
|
|
||||||
@@ -1155,18 +1151,19 @@ function GROUP:GetAmmunition()
|
|||||||
local Unit = UnitData -- Wrapper.Unit#UNIT
|
local Unit = UnitData -- Wrapper.Unit#UNIT
|
||||||
|
|
||||||
-- Get ammo of the unit
|
-- Get ammo of the unit
|
||||||
local ntot, nshells, nrockets, nmissiles = Unit:GetAmmunition()
|
local ntot, nshells, nrockets, nbombs, nmissiles = Unit:GetAmmunition()
|
||||||
|
|
||||||
Ntot=Ntot+ntot
|
Ntot=Ntot+ntot
|
||||||
Nshells=Nshells+nshells
|
Nshells=Nshells+nshells
|
||||||
Nrockets=Nrockets+nrockets
|
Nrockets=Nrockets+nrockets
|
||||||
Nmissiles=Nmissiles+nmissiles
|
Nmissiles=Nmissiles+nmissiles
|
||||||
|
Nbombs=Nbombs+nbombs
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return Ntot, Nshells, Nrockets, Nmissiles
|
return Ntot, Nshells, Nrockets, Nbombs, Nmissiles
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -2324,41 +2321,44 @@ function GROUP:GetAttribute()
|
|||||||
local unarmedship=self:HasAttribute("Unarmed ships")
|
local unarmedship=self:HasAttribute("Unarmed ships")
|
||||||
|
|
||||||
|
|
||||||
-- Define attribute. Order is important.
|
-- Define attribute. Order of attack is important.
|
||||||
if transportplane then
|
if fighter then
|
||||||
attribute=GROUP.Attribute.AIR_TRANSPORTPLANE
|
|
||||||
elseif awacs then
|
|
||||||
attribute=GROUP.Attribute.AIR_AWACS
|
|
||||||
elseif fighter then
|
|
||||||
attribute=GROUP.Attribute.AIR_FIGHTER
|
attribute=GROUP.Attribute.AIR_FIGHTER
|
||||||
elseif bomber then
|
elseif bomber then
|
||||||
attribute=GROUP.Attribute.AIR_BOMBER
|
attribute=GROUP.Attribute.AIR_BOMBER
|
||||||
|
elseif awacs then
|
||||||
|
attribute=GROUP.Attribute.AIR_AWACS
|
||||||
|
elseif transportplane then
|
||||||
|
attribute=GROUP.Attribute.AIR_TRANSPORTPLANE
|
||||||
elseif tanker then
|
elseif tanker then
|
||||||
attribute=GROUP.Attribute.AIR_TANKER
|
attribute=GROUP.Attribute.AIR_TANKER
|
||||||
|
-- helos
|
||||||
|
elseif attackhelicopter then
|
||||||
|
attribute=GROUP.Attribute.AIR_ATTACKHELO
|
||||||
elseif transporthelo then
|
elseif transporthelo then
|
||||||
attribute=GROUP.Attribute.AIR_TRANSPORTHELO
|
attribute=GROUP.Attribute.AIR_TRANSPORTHELO
|
||||||
elseif attackhelicopter then
|
|
||||||
attribute=GROUP.Attribute.AIR_ATTACKHELO
|
|
||||||
elseif uav then
|
elseif uav then
|
||||||
attribute=GROUP.Attribute.AIR_UAV
|
attribute=GROUP.Attribute.AIR_UAV
|
||||||
elseif apc then
|
-- ground - order of attack
|
||||||
attribute=GROUP.Attribute.GROUND_APC
|
|
||||||
elseif infantry then
|
|
||||||
attribute=GROUP.Attribute.GROUND_INFANTRY
|
|
||||||
elseif artillery then
|
|
||||||
attribute=GROUP.Attribute.GROUND_ARTILLERY
|
|
||||||
elseif tank then
|
|
||||||
attribute=GROUP.Attribute.GROUND_TANK
|
|
||||||
elseif aaa then
|
|
||||||
attribute=GROUP.Attribute.GROUND_AAA
|
|
||||||
elseif ewr then
|
elseif ewr then
|
||||||
attribute=GROUP.Attribute.GROUND_EWR
|
attribute=GROUP.Attribute.GROUND_EWR
|
||||||
elseif sam then
|
elseif sam then
|
||||||
attribute=GROUP.Attribute.GROUND_SAM
|
attribute=GROUP.Attribute.GROUND_SAM
|
||||||
|
elseif aaa then
|
||||||
|
attribute=GROUP.Attribute.GROUND_AAA
|
||||||
|
elseif artillery then
|
||||||
|
attribute=GROUP.Attribute.GROUND_ARTILLERY
|
||||||
|
elseif tank then
|
||||||
|
attribute=GROUP.Attribute.GROUND_TANK
|
||||||
|
elseif apc then
|
||||||
|
attribute=GROUP.Attribute.GROUND_APC
|
||||||
|
elseif infantry then
|
||||||
|
attribute=GROUP.Attribute.GROUND_INFANTRY
|
||||||
elseif truck then
|
elseif truck then
|
||||||
attribute=GROUP.Attribute.GROUND_TRUCK
|
attribute=GROUP.Attribute.GROUND_TRUCK
|
||||||
elseif train then
|
elseif train then
|
||||||
attribute=GROUP.Attribute.GROUND_TRAIN
|
attribute=GROUP.Attribute.GROUND_TRAIN
|
||||||
|
-- ships
|
||||||
elseif aircraftcarrier then
|
elseif aircraftcarrier then
|
||||||
attribute=GROUP.Attribute.NAVAL_AIRCRAFTCARRIER
|
attribute=GROUP.Attribute.NAVAL_AIRCRAFTCARRIER
|
||||||
elseif warship then
|
elseif warship then
|
||||||
@@ -2576,8 +2576,10 @@ end
|
|||||||
-- @return #GROUP self
|
-- @return #GROUP self
|
||||||
function GROUP:SetCommandInvisible(switch)
|
function GROUP:SetCommandInvisible(switch)
|
||||||
self:F2( self.GroupName )
|
self:F2( self.GroupName )
|
||||||
local switch = switch or false
|
if switch==nil then
|
||||||
local SetInvisible = {id = 'SetInvisible', params = {value = true}}
|
switch=false
|
||||||
|
end
|
||||||
|
local SetInvisible = {id = 'SetInvisible', params = {value = switch}}
|
||||||
self:SetCommand(SetInvisible)
|
self:SetCommand(SetInvisible)
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
@@ -2588,12 +2590,25 @@ end
|
|||||||
-- @return #GROUP self
|
-- @return #GROUP self
|
||||||
function GROUP:SetCommandImmortal(switch)
|
function GROUP:SetCommandImmortal(switch)
|
||||||
self:F2( self.GroupName )
|
self:F2( self.GroupName )
|
||||||
local switch = switch or false
|
if switch==nil then
|
||||||
local SetInvisible = {id = 'SetImmortal', params = {value = true}}
|
switch=false
|
||||||
self:SetCommand(SetInvisible)
|
end
|
||||||
|
local SetImmortal = {id = 'SetImmortal', params = {value = switch}}
|
||||||
|
self:SetCommand(SetImmortal)
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Get skill from Group. Effectively gets the skill from Unit 1 as the group holds no skill value.
|
||||||
|
-- @param #GROUP self
|
||||||
|
-- @return #string Skill String of skill name.
|
||||||
|
function GROUP:GetSkill()
|
||||||
|
self:F2( self.GroupName )
|
||||||
|
local unit = self:GetUnit(1)
|
||||||
|
local name = unit:GetName()
|
||||||
|
local skill = _DATABASE.Templates.Units[name].Template.skill or "Random"
|
||||||
|
return skill
|
||||||
|
end
|
||||||
|
|
||||||
--do -- Smoke
|
--do -- Smoke
|
||||||
--
|
--
|
||||||
----- Signal a flare at the position of the GROUP.
|
----- Signal a flare at the position of the GROUP.
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,52 +1,46 @@
|
|||||||
--- **Wrapper** -- STATIC wraps the DCS StaticObject class.
|
--- **Wrapper** -- STATIC wraps the DCS StaticObject class.
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ### Author: **FlightControl**
|
-- ### Author: **FlightControl**
|
||||||
--
|
--
|
||||||
-- ### Contributions: **funkyfranky**
|
-- ### Contributions: **funkyfranky**
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- @module Wrapper.Static
|
-- @module Wrapper.Static
|
||||||
-- @image Wrapper_Static.JPG
|
-- @image Wrapper_Static.JPG
|
||||||
|
|
||||||
|
|
||||||
--- @type STATIC
|
--- @type STATIC
|
||||||
-- @extends Wrapper.Positionable#POSITIONABLE
|
-- @extends Wrapper.Positionable#POSITIONABLE
|
||||||
|
|
||||||
--- Wrapper class to handle Static objects.
|
--- Wrapper class to handle Static objects.
|
||||||
--
|
--
|
||||||
-- Note that Statics are almost the same as Units, but they don't have a controller.
|
-- Note that Statics are almost the same as Units, but they don't have a controller.
|
||||||
-- The @{Wrapper.Static#STATIC} class is a wrapper class to handle the DCS Static objects:
|
-- The @{Wrapper.Static#STATIC} class is a wrapper class to handle the DCS Static objects:
|
||||||
--
|
--
|
||||||
-- * Wraps the DCS Static objects.
|
-- * Wraps the DCS Static objects.
|
||||||
-- * Support all DCS Static APIs.
|
-- * Support all DCS Static APIs.
|
||||||
-- * Enhance with Static specific APIs not in the DCS API set.
|
-- * Enhance with Static specific APIs not in the DCS API set.
|
||||||
--
|
--
|
||||||
-- ## STATIC reference methods
|
-- ## STATIC reference methods
|
||||||
--
|
--
|
||||||
-- For each DCS Static will have a STATIC wrapper object (instance) within the _@{DATABASE} object.
|
-- For each DCS Static will have a STATIC wrapper object (instance) within the _@{DATABASE} object.
|
||||||
-- This is done at the beginning of the mission (when the mission starts).
|
-- This is done at the beginning of the mission (when the mission starts).
|
||||||
--
|
--
|
||||||
-- The STATIC class does not contain a :New() method, rather it provides :Find() methods to retrieve the object reference
|
-- The STATIC class does not contain a :New() method, rather it provides :Find() methods to retrieve the object reference
|
||||||
-- using the Static Name.
|
-- using the Static Name.
|
||||||
--
|
--
|
||||||
-- Another thing to know is that STATIC objects do not "contain" the DCS Static object.
|
-- Another thing to know is that STATIC objects do not "contain" the DCS Static object.
|
||||||
-- The STATIc methods will reference the DCS Static object by name when it is needed during API execution.
|
-- The STATIc methods will reference the DCS Static object by name when it is needed during API execution.
|
||||||
-- If the DCS Static object does not exist or is nil, the STATIC methods will return nil and log an exception in the DCS.log file.
|
-- If the DCS Static object does not exist or is nil, the STATIC methods will return nil and log an exception in the DCS.log file.
|
||||||
--
|
--
|
||||||
-- The STATIc class provides the following functions to retrieve quickly the relevant STATIC instance:
|
-- The STATIc class provides the following functions to retrieve quickly the relevant STATIC instance:
|
||||||
--
|
--
|
||||||
-- * @{#STATIC.FindByName}(): Find a STATIC instance from the _DATABASE object using a DCS Static name.
|
-- * @{#STATIC.FindByName}(): Find a STATIC instance from the _DATABASE object using a DCS Static name.
|
||||||
--
|
--
|
||||||
-- IMPORTANT: ONE SHOULD NEVER SANATIZE these STATIC OBJECT REFERENCES! (make the STATIC object references nil).
|
-- IMPORTANT: ONE SHOULD NEVER SANITIZE these STATIC OBJECT REFERENCES! (make the STATIC object references nil).
|
||||||
--
|
--
|
||||||
-- @field #STATIC
|
-- @field #STATIC
|
||||||
STATIC = {
|
STATIC = { ClassName = "STATIC" }
|
||||||
ClassName = "STATIC",
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
--- Register a static object.
|
--- Register a static object.
|
||||||
-- @param #STATIC self
|
-- @param #STATIC self
|
||||||
@@ -58,7 +52,6 @@ function STATIC:Register( StaticName )
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Finds a STATIC from the _DATABASE using a DCSStatic object.
|
--- Finds a STATIC from the _DATABASE using a DCSStatic object.
|
||||||
-- @param #STATIC self
|
-- @param #STATIC self
|
||||||
-- @param DCS#StaticObject DCSStatic An existing DCS Static object reference.
|
-- @param DCS#StaticObject DCSStatic An existing DCS Static object reference.
|
||||||
@@ -83,13 +76,13 @@ function STATIC:FindByName( StaticName, RaiseError )
|
|||||||
|
|
||||||
-- Set static name.
|
-- Set static name.
|
||||||
self.StaticName = StaticName
|
self.StaticName = StaticName
|
||||||
|
|
||||||
if StaticFound then
|
if StaticFound then
|
||||||
return StaticFound
|
return StaticFound
|
||||||
end
|
end
|
||||||
|
|
||||||
if RaiseError == nil or RaiseError == true then
|
if RaiseError == nil or RaiseError == true then
|
||||||
error( "STATIC not found for: " .. StaticName )
|
error( "STATIC not found for: " .. StaticName )
|
||||||
end
|
end
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -97,38 +90,39 @@ end
|
|||||||
|
|
||||||
--- Destroys the STATIC.
|
--- Destroys the STATIC.
|
||||||
-- @param #STATIC self
|
-- @param #STATIC self
|
||||||
-- @param #boolean GenerateEvent (Optional) true if you want to generate a crash or dead event for the static.
|
-- @param #boolean GenerateEvent (Optional) true to generate a crash or dead event, false to not generate any event. `nil` (default) creates a remove event.
|
||||||
-- @return #nil The DCS StaticObject is not existing or alive.
|
-- @return #nil The DCS StaticObject is not existing or alive.
|
||||||
|
--
|
||||||
-- @usage
|
-- @usage
|
||||||
-- -- Air static example: destroy the static Helicopter and generate a S_EVENT_CRASH.
|
-- -- Air static example: destroy the static Helicopter and generate a S_EVENT_CRASH.
|
||||||
-- Helicopter = STATIC:FindByName( "Helicopter" )
|
-- Helicopter = STATIC:FindByName( "Helicopter" )
|
||||||
-- Helicopter:Destroy( true )
|
-- Helicopter:Destroy( true )
|
||||||
--
|
--
|
||||||
-- @usage
|
-- @usage
|
||||||
-- -- Ground static example: destroy the static Tank and generate a S_EVENT_DEAD.
|
-- -- Ground static example: destroy the static Tank and generate a S_EVENT_DEAD.
|
||||||
-- Tanks = UNIT:FindByName( "Tank" )
|
-- Tanks = UNIT:FindByName( "Tank" )
|
||||||
-- Tanks:Destroy( true )
|
-- Tanks:Destroy( true )
|
||||||
--
|
--
|
||||||
-- @usage
|
-- @usage
|
||||||
-- -- Ship static example: destroy the Ship silently.
|
-- -- Ship static example: destroy the Ship silently.
|
||||||
-- Ship = STATIC:FindByName( "Ship" )
|
-- Ship = STATIC:FindByName( "Ship" )
|
||||||
-- Ship:Destroy()
|
-- Ship:Destroy()
|
||||||
--
|
--
|
||||||
-- @usage
|
-- @usage
|
||||||
-- -- Destroy without event generation example.
|
-- -- Destroy without event generation example.
|
||||||
-- Ship = STATIC:FindByName( "Boat" )
|
-- Ship = STATIC:FindByName( "Boat" )
|
||||||
-- Ship:Destroy( false ) -- Don't generate an event upon destruction.
|
-- Ship:Destroy( false ) -- Don't generate any event upon destruction.
|
||||||
--
|
--
|
||||||
function STATIC:Destroy( GenerateEvent )
|
function STATIC:Destroy( GenerateEvent )
|
||||||
self:F2( self.ObjectName )
|
self:F2( self.ObjectName )
|
||||||
|
|
||||||
local DCSObject = self:GetDCSObject()
|
local DCSObject = self:GetDCSObject()
|
||||||
|
|
||||||
if DCSObject then
|
if DCSObject then
|
||||||
|
|
||||||
local StaticName = DCSObject:getName()
|
local StaticName = DCSObject:getName()
|
||||||
self:F( { StaticName = StaticName } )
|
self:F( { StaticName = StaticName } )
|
||||||
|
|
||||||
if GenerateEvent and GenerateEvent == true then
|
if GenerateEvent and GenerateEvent == true then
|
||||||
if self:IsAir() then
|
if self:IsAir() then
|
||||||
self:CreateEventCrash( timer.getTime(), DCSObject )
|
self:CreateEventCrash( timer.getTime(), DCSObject )
|
||||||
@@ -140,7 +134,7 @@ function STATIC:Destroy( GenerateEvent )
|
|||||||
else
|
else
|
||||||
self:CreateEventRemoveUnit( timer.getTime(), DCSObject )
|
self:CreateEventRemoveUnit( timer.getTime(), DCSObject )
|
||||||
end
|
end
|
||||||
|
|
||||||
DCSObject:destroy()
|
DCSObject:destroy()
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
@@ -148,17 +142,16 @@ function STATIC:Destroy( GenerateEvent )
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Get DCS object of static of static.
|
--- Get DCS object of static of static.
|
||||||
-- @param #STATIC self
|
-- @param #STATIC self
|
||||||
-- @return DCS static object
|
-- @return DCS static object
|
||||||
function STATIC:GetDCSObject()
|
function STATIC:GetDCSObject()
|
||||||
local DCSStatic = StaticObject.getByName( self.StaticName )
|
local DCSStatic = StaticObject.getByName( self.StaticName )
|
||||||
|
|
||||||
if DCSStatic then
|
if DCSStatic then
|
||||||
return DCSStatic
|
return DCSStatic
|
||||||
end
|
end
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -170,7 +163,7 @@ function STATIC:GetUnits()
|
|||||||
local DCSStatic = self:GetDCSObject()
|
local DCSStatic = self:GetDCSObject()
|
||||||
|
|
||||||
local Statics = {}
|
local Statics = {}
|
||||||
|
|
||||||
if DCSStatic then
|
if DCSStatic then
|
||||||
Statics[1] = STATIC:Find( DCSStatic )
|
Statics[1] = STATIC:Find( DCSStatic )
|
||||||
self:T3( Statics )
|
self:T3( Statics )
|
||||||
@@ -180,7 +173,6 @@ function STATIC:GetUnits()
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Get threat level of static.
|
--- Get threat level of static.
|
||||||
-- @param #STATIC self
|
-- @param #STATIC self
|
||||||
-- @return #number Threat level 1.
|
-- @return #number Threat level 1.
|
||||||
@@ -194,66 +186,62 @@ end
|
|||||||
-- @param Core.Point#COORDINATE Coordinate The coordinate where to spawn the new Static.
|
-- @param Core.Point#COORDINATE Coordinate The coordinate where to spawn the new Static.
|
||||||
-- @param #number Heading The heading of the static respawn in degrees. Default is 0 deg.
|
-- @param #number Heading The heading of the static respawn in degrees. Default is 0 deg.
|
||||||
-- @param #number Delay Delay in seconds before the static is spawned.
|
-- @param #number Delay Delay in seconds before the static is spawned.
|
||||||
function STATIC:SpawnAt(Coordinate, Heading, Delay)
|
function STATIC:SpawnAt( Coordinate, Heading, Delay )
|
||||||
|
|
||||||
Heading=Heading or 0
|
Heading = Heading or 0
|
||||||
|
|
||||||
if Delay and Delay>0 then
|
if Delay and Delay > 0 then
|
||||||
SCHEDULER:New(nil, self.SpawnAt, {self, Coordinate, Heading}, Delay)
|
SCHEDULER:New( nil, self.SpawnAt, { self, Coordinate, Heading }, Delay )
|
||||||
else
|
else
|
||||||
|
|
||||||
local SpawnStatic=SPAWNSTATIC:NewFromStatic(self.StaticName)
|
local SpawnStatic = SPAWNSTATIC:NewFromStatic( self.StaticName )
|
||||||
|
|
||||||
SpawnStatic:SpawnFromPointVec2( Coordinate, Heading, self.StaticName )
|
SpawnStatic:SpawnFromPointVec2( Coordinate, Heading, self.StaticName )
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Respawn the @{Wrapper.Unit} at the same location with the same properties.
|
--- Respawn the @{Wrapper.Unit} at the same location with the same properties.
|
||||||
-- This is useful to respawn a cargo after it has been destroyed.
|
-- This is useful to respawn a cargo after it has been destroyed.
|
||||||
-- @param #STATIC self
|
-- @param #STATIC self
|
||||||
-- @param DCS#country.id CountryID (Optional) The country ID used for spawning the new static. Default is same as currently.
|
-- @param DCS#country.id CountryID (Optional) The country ID used for spawning the new static. Default is same as currently.
|
||||||
-- @param #number Delay (Optional) Delay in seconds before static is respawned. Default now.
|
-- @param #number Delay (Optional) Delay in seconds before static is respawned. Default now.
|
||||||
function STATIC:ReSpawn(CountryID, Delay)
|
function STATIC:ReSpawn( CountryID, Delay )
|
||||||
|
|
||||||
if Delay and Delay>0 then
|
if Delay and Delay > 0 then
|
||||||
SCHEDULER:New(nil, self.ReSpawn, {self, CountryID}, Delay)
|
SCHEDULER:New( nil, self.ReSpawn, { self, CountryID }, Delay )
|
||||||
else
|
else
|
||||||
|
|
||||||
CountryID=CountryID or self:GetCountry()
|
CountryID = CountryID or self:GetCountry()
|
||||||
|
|
||||||
|
local SpawnStatic = SPAWNSTATIC:NewFromStatic( self.StaticName, CountryID )
|
||||||
|
|
||||||
|
SpawnStatic:Spawn( nil, self.StaticName )
|
||||||
|
|
||||||
local SpawnStatic=SPAWNSTATIC:NewFromStatic(self.StaticName, CountryID)
|
|
||||||
|
|
||||||
SpawnStatic:Spawn(nil, self.StaticName)
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Respawn the @{Wrapper.Unit} at a defined Coordinate with an optional heading.
|
--- Respawn the @{Wrapper.Unit} at a defined Coordinate with an optional heading.
|
||||||
-- @param #STATIC self
|
-- @param #STATIC self
|
||||||
-- @param Core.Point#COORDINATE Coordinate The coordinate where to spawn the new Static.
|
-- @param Core.Point#COORDINATE Coordinate The coordinate where to spawn the new Static.
|
||||||
-- @param #number Heading (Optional) The heading of the static respawn in degrees. Default the current heading.
|
-- @param #number Heading (Optional) The heading of the static respawn in degrees. Default is the current heading.
|
||||||
-- @param #number Delay (Optional) Delay in seconds before static is respawned. Default now.
|
-- @param #number Delay (Optional) Delay in seconds before static is respawned. Default is now.
|
||||||
function STATIC:ReSpawnAt(Coordinate, Heading, Delay)
|
function STATIC:ReSpawnAt( Coordinate, Heading, Delay )
|
||||||
|
|
||||||
--Heading=Heading or 0
|
-- Heading=Heading or 0
|
||||||
|
|
||||||
if Delay and Delay>0 then
|
if Delay and Delay > 0 then
|
||||||
SCHEDULER:New(nil, self.ReSpawnAt, {self, Coordinate, Heading}, Delay)
|
SCHEDULER:New( nil, self.ReSpawnAt, { self, Coordinate, Heading }, Delay )
|
||||||
else
|
else
|
||||||
|
local SpawnStatic = SPAWNSTATIC:NewFromStatic( self.StaticName, self:GetCountry() )
|
||||||
local SpawnStatic=SPAWNSTATIC:NewFromStatic(self.StaticName, self:GetCountry())
|
|
||||||
|
SpawnStatic:SpawnFromCoordinate( Coordinate, Heading, self.StaticName )
|
||||||
SpawnStatic:SpawnFromCoordinate(Coordinate, Heading, self.StaticName)
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -168,9 +168,6 @@ function UNIT:GetDCSObject()
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--- Respawn the @{Wrapper.Unit} using a (tweaked) template of the parent Group.
|
--- Respawn the @{Wrapper.Unit} using a (tweaked) template of the parent Group.
|
||||||
--
|
--
|
||||||
-- This function will:
|
-- This function will:
|
||||||
@@ -263,8 +260,6 @@ function UNIT:ReSpawnAt( Coordinate, Heading )
|
|||||||
_DATABASE:Spawn( SpawnGroupTemplate )
|
_DATABASE:Spawn( SpawnGroupTemplate )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--- Returns if the unit is activated.
|
--- Returns if the unit is activated.
|
||||||
-- @param #UNIT self
|
-- @param #UNIT self
|
||||||
-- @return #boolean `true` if Unit is activated. `nil` The DCS Unit is not existing or alive.
|
-- @return #boolean `true` if Unit is activated. `nil` The DCS Unit is not existing or alive.
|
||||||
@@ -301,8 +296,6 @@ function UNIT:IsAlive()
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--- Returns the Unit's callsign - the localized string.
|
--- Returns the Unit's callsign - the localized string.
|
||||||
-- @param #UNIT self
|
-- @param #UNIT self
|
||||||
-- @return #string The Callsign of the Unit.
|
-- @return #string The Callsign of the Unit.
|
||||||
@@ -442,7 +435,7 @@ function UNIT:GetSpeedMax()
|
|||||||
return SpeedMax*3.6
|
return SpeedMax*3.6
|
||||||
end
|
end
|
||||||
|
|
||||||
return nil
|
return 0
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Returns the unit's max range in meters derived from the DCS descriptors.
|
--- Returns the unit's max range in meters derived from the DCS descriptors.
|
||||||
@@ -626,8 +619,8 @@ function UNIT:GetAmmunition()
|
|||||||
-- Type name of current weapon.
|
-- Type name of current weapon.
|
||||||
local Tammo=ammotable[w]["desc"]["typeName"]
|
local Tammo=ammotable[w]["desc"]["typeName"]
|
||||||
|
|
||||||
local _weaponString = UTILS.Split(Tammo,"%.")
|
--local _weaponString = UTILS.Split(Tammo,"%.")
|
||||||
local _weaponName = _weaponString[#_weaponString]
|
--local _weaponName = _weaponString[#_weaponString]
|
||||||
|
|
||||||
-- Get the weapon category: shell=0, missile=1, rocket=2, bomb=3
|
-- Get the weapon category: shell=0, missile=1, rocket=2, bomb=3
|
||||||
local Category=ammotable[w].desc.category
|
local Category=ammotable[w].desc.category
|
||||||
@@ -655,8 +648,9 @@ function UNIT:GetAmmunition()
|
|||||||
nbombs=nbombs+Nammo
|
nbombs=nbombs+Nammo
|
||||||
|
|
||||||
elseif Category==Weapon.Category.MISSILE then
|
elseif Category==Weapon.Category.MISSILE then
|
||||||
|
|
||||||
-- Add up all cruise missiles (category 5)
|
|
||||||
|
-- Add up all missiles (category 5)
|
||||||
if MissileCategory==Weapon.MissileCategory.AAM then
|
if MissileCategory==Weapon.MissileCategory.AAM then
|
||||||
nmissiles=nmissiles+Nammo
|
nmissiles=nmissiles+Nammo
|
||||||
elseif MissileCategory==Weapon.MissileCategory.ANTI_SHIP then
|
elseif MissileCategory==Weapon.MissileCategory.ANTI_SHIP then
|
||||||
@@ -665,6 +659,10 @@ function UNIT:GetAmmunition()
|
|||||||
nmissiles=nmissiles+Nammo
|
nmissiles=nmissiles+Nammo
|
||||||
elseif MissileCategory==Weapon.MissileCategory.OTHER then
|
elseif MissileCategory==Weapon.MissileCategory.OTHER then
|
||||||
nmissiles=nmissiles+Nammo
|
nmissiles=nmissiles+Nammo
|
||||||
|
elseif MissileCategory==Weapon.MissileCategory.SAM then
|
||||||
|
nmissiles=nmissiles+Nammo
|
||||||
|
elseif MissileCategory==Weapon.MissileCategory.CRUISE then
|
||||||
|
nmissiles=nmissiles+Nammo
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
@@ -956,7 +954,6 @@ end
|
|||||||
-- @return #string Some text.
|
-- @return #string Some text.
|
||||||
function UNIT:GetThreatLevel()
|
function UNIT:GetThreatLevel()
|
||||||
|
|
||||||
|
|
||||||
local ThreatLevel = 0
|
local ThreatLevel = 0
|
||||||
local ThreatText = ""
|
local ThreatText = ""
|
||||||
|
|
||||||
@@ -982,7 +979,6 @@ function UNIT:GetThreatLevel()
|
|||||||
"LR SAMs"
|
"LR SAMs"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if Attributes["LR SAM"] then ThreatLevel = 10
|
if Attributes["LR SAM"] then ThreatLevel = 10
|
||||||
elseif Attributes["MR SAM"] then ThreatLevel = 9
|
elseif Attributes["MR SAM"] then ThreatLevel = 9
|
||||||
elseif Attributes["SR SAM"] and
|
elseif Attributes["SR SAM"] and
|
||||||
@@ -1018,7 +1014,6 @@ function UNIT:GetThreatLevel()
|
|||||||
"Fighter"
|
"Fighter"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if Attributes["Fighters"] then ThreatLevel = 10
|
if Attributes["Fighters"] then ThreatLevel = 10
|
||||||
elseif Attributes["Multirole fighters"] then ThreatLevel = 9
|
elseif Attributes["Multirole fighters"] then ThreatLevel = 9
|
||||||
elseif Attributes["Battleplanes"] then ThreatLevel = 8
|
elseif Attributes["Battleplanes"] then ThreatLevel = 8
|
||||||
@@ -1136,12 +1131,6 @@ function UNIT:OtherUnitInRadius( AwaitUnit, Radius )
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--- Returns if the unit is a friendly unit.
|
--- Returns if the unit is a friendly unit.
|
||||||
-- @param #UNIT self
|
-- @param #UNIT self
|
||||||
-- @return #boolean IsFriendly evaluation result.
|
-- @return #boolean IsFriendly evaluation result.
|
||||||
@@ -1426,3 +1415,13 @@ function UNIT:EnableEmission(switch)
|
|||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Get skill from Unit.
|
||||||
|
-- @param #UNIT self
|
||||||
|
-- @return #string Skill String of skill name.
|
||||||
|
function UNIT:GetSkill()
|
||||||
|
self:F2( self.UnitName )
|
||||||
|
local name = self.UnitName
|
||||||
|
local skill = _DATABASE.Templates.Units[name].Template.skill or "Random"
|
||||||
|
return skill
|
||||||
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user