mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2026-08-18 05:05:56 +00:00
Compare commits
163 Commits
v2.5.0pre1
...
v2.5.1
| Author | SHA1 | Date | |
|---|---|---|---|
| 59f795fc17 | |||
| 26a935c29c | |||
| 848336f8ac | |||
| 8e6e9cbb4d | |||
| 15cb9bec40 | |||
| 38f5fd8249 | |||
| 6a04f83280 | |||
| ec4d12a0d5 | |||
| 999aba5d77 | |||
| 652f29b782 | |||
| 0c6aae45c1 | |||
| 25b8cff442 | |||
| 9f7471178b | |||
| f3f3406d64 | |||
| 4eb886d0f3 | |||
| 5c6e50e7f9 | |||
| fb3115a0f1 | |||
| 833d4f7b65 | |||
| 61bb59d8b3 | |||
| 21652de804 | |||
| e677e2acf4 | |||
| 2658230331 | |||
| bb0827bb8c | |||
| be1f8cde34 | |||
| 29028bf128 | |||
| c30ca2b18a | |||
| d1b40b63c2 | |||
| 0b7ac754c5 | |||
| 5b514d223b | |||
| 7d8e27c83e | |||
| dcd1060496 | |||
| 533e2abf17 | |||
| 6b318d0309 | |||
| bee44b97fd | |||
| 77de1dda2b | |||
| 5b03bc5066 | |||
| 0d6f32581c | |||
| 2620370890 | |||
| f866af0d4a | |||
| b86eac33b6 | |||
| c78bd2652a | |||
| 392d465b30 | |||
| 056cc1630d | |||
| 364ce927e7 | |||
| 517d5860fb | |||
| 4e49184da2 | |||
| 68ece29ab5 | |||
| c3cc76c15b | |||
| 0a570da986 | |||
| b25697e261 | |||
| 863e239204 | |||
| 457b30ed07 | |||
| 7360c51a8f | |||
| df512f7a58 | |||
| da05c41c27 | |||
| 3c428723f8 | |||
| 4c3fd1d867 | |||
| 909c028e48 | |||
| 14e12dc36b | |||
| 0502e0a020 | |||
| 36aebd3c04 | |||
| 007831bb9a | |||
| def44bde89 | |||
| 4b369fae95 | |||
| cb4a44b512 | |||
| 53fbec9c15 | |||
| d476922af2 | |||
| 861f2da4d6 | |||
| 6d75b25f57 | |||
| bfb3ae33f4 | |||
| a796c7a594 | |||
| af63c1a219 | |||
| 72da7a2c04 | |||
| f9bdbf4e3f | |||
| 850951bcb4 | |||
| 3d0f002f73 | |||
| ff8c454752 | |||
| 6882c4b42f | |||
| 9b0f474edf | |||
| ceaae5421c | |||
| 36666df76f | |||
| 3616e4264a | |||
| a704693abf | |||
| 4dc303a166 | |||
| 71b5140e69 | |||
| 00e5499f81 | |||
| 7cf73af707 | |||
| 4ef827836c | |||
| e3d6337481 | |||
| f258e9263e | |||
| 48d99a19c5 | |||
| f34511bd8c | |||
| 63a5d2e3ac | |||
| 3fb52d4fa1 | |||
| 463403cef4 | |||
| fedee49eb1 | |||
| 042cc7a85f | |||
| 9583168c4d | |||
| 0c32c35c27 | |||
| 6ab85072d2 | |||
| 04da941c36 | |||
| d6c919a097 | |||
| 1f9ffcd92d | |||
| 12ef34acaa | |||
| ce60e7ce74 | |||
| aa5d36db88 | |||
| a2759b1cc0 | |||
| 0da0b025b5 | |||
| f685064c0c | |||
| b68e254bc0 | |||
| d43f77706e | |||
| 5e1fb36d01 | |||
| 6d3bbe88e6 | |||
| e4906eb083 | |||
| 19eb81866a | |||
| cd34755036 | |||
| c72625c60f | |||
| 1e1154d190 | |||
| ff0f62c01b | |||
| e6e5787fc6 | |||
| 431e8a05f9 | |||
| b91a8cf4c8 | |||
| 3e8455410e | |||
| 3a9ad1b7cc | |||
| 6000421957 | |||
| 231ceef41f | |||
| 4661f6981e | |||
| fcfcfeae00 | |||
| 09ed562f61 | |||
| b1f2bab87e | |||
| aa6515e1ca | |||
| d5b8ed62ae | |||
| 6208c79d1f | |||
| 740ee74f61 | |||
| 0bb0c70667 | |||
| 9fb311bf7d | |||
| 8915657e91 | |||
| 8b506a2f20 | |||
| 6dd73dba44 | |||
| d3a3d96436 | |||
| 8337058306 | |||
| 389931fbf0 | |||
| b9fd6c0e31 | |||
| f48f53fb37 | |||
| 07edcd7e73 | |||
| a193d342d7 | |||
| 5b9978e390 | |||
| c3c984381e | |||
| ca49e8f8ae | |||
| 59c46f9b4b | |||
| b9384831fb | |||
| 0d57ad5584 | |||
| cf34ec0905 | |||
| 1c99e474b2 | |||
| e45134f086 | |||
| 1b5e9df586 | |||
| 4b6612e114 | |||
| e4473010eb | |||
| bb259b2572 | |||
| e16e2851c1 | |||
| 169c5a674c | |||
| 60042e14dc | |||
| 14de37f390 |
@@ -221,3 +221,8 @@ _gsdata_/
|
|||||||
.gitattributes
|
.gitattributes
|
||||||
.gitignore
|
.gitignore
|
||||||
Moose Test Missions/MOOSE_Test_Template.miz
|
Moose Test Missions/MOOSE_Test_Template.miz
|
||||||
|
Moose Development/Moose/.vscode/launch.json
|
||||||
|
MooseCodeWS.code-workspace
|
||||||
|
.gitignore
|
||||||
|
.gitignore
|
||||||
|
/.gitignore
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
projectKey=Test
|
||||||
|
serverUrl=http://localhost:9000
|
||||||
|
serverVersion=8.1.0.31237
|
||||||
|
dashboardUrl=http://localhost:9000/dashboard?id=Test
|
||||||
|
ceTaskId=AXAlUJO97YLjwz1VUDXR
|
||||||
|
ceTaskUrl=http://localhost:9000/api/ce/task?id=AXAlUJO97YLjwz1VUDXR
|
||||||
@@ -119,7 +119,7 @@ function AI_A2A_CAP:New2( AICap, EngageMinSpeed, EngageMaxSpeed, EngageFloorAlti
|
|||||||
local AI_Air = AI_AIR:New( AICap )
|
local AI_Air = AI_AIR:New( AICap )
|
||||||
local AI_Air_Patrol = AI_AIR_PATROL:New( AI_Air, AICap, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType ) -- #AI_AIR_PATROL
|
local AI_Air_Patrol = AI_AIR_PATROL:New( AI_Air, AICap, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType ) -- #AI_AIR_PATROL
|
||||||
local AI_Air_Engage = AI_AIR_ENGAGE:New( AI_Air_Patrol, AICap, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType )
|
local AI_Air_Engage = AI_AIR_ENGAGE:New( AI_Air_Patrol, AICap, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType )
|
||||||
local self = BASE:Inherit( self, AI_Air_Engage )
|
local self = BASE:Inherit( self, AI_Air_Engage ) --#AI_A2A_CAP
|
||||||
|
|
||||||
self:SetFuelThreshold( .2, 60 )
|
self:SetFuelThreshold( .2, 60 )
|
||||||
self:SetDamageThreshold( 0.4 )
|
self:SetDamageThreshold( 0.4 )
|
||||||
@@ -200,8 +200,7 @@ function AI_A2A_CAP:CreateAttackUnitTasks( AttackSetUnit, DefenderGroup, EngageA
|
|||||||
|
|
||||||
for AttackUnitID, AttackUnit in pairs( self.AttackSetUnit:GetSet() ) do
|
for AttackUnitID, AttackUnit in pairs( self.AttackSetUnit:GetSet() ) do
|
||||||
local AttackUnit = AttackUnit -- Wrapper.Unit#UNIT
|
local AttackUnit = AttackUnit -- Wrapper.Unit#UNIT
|
||||||
self:T( { "Attacking Unit:", AttackUnit:GetName(), AttackUnit:IsAlive(), AttackUnit:IsAir() } )
|
if AttackUnit and AttackUnit:IsAlive() and AttackUnit:IsAir() then
|
||||||
if AttackUnit:IsAlive() and AttackUnit:IsAir() then
|
|
||||||
-- TODO: Add coalition check? Only attack units of if AttackUnit:GetCoalition()~=AICap:GetCoalition()
|
-- TODO: Add coalition check? Only attack units of if AttackUnit:GetCoalition()~=AICap:GetCoalition()
|
||||||
-- Maybe the detected set also contains
|
-- Maybe the detected set also contains
|
||||||
self:T( { "Attacking Task:", AttackUnit:GetName(), AttackUnit:IsAlive(), AttackUnit:IsAir() } )
|
self:T( { "Attacking Task:", AttackUnit:GetName(), AttackUnit:IsAlive(), AttackUnit:IsAir() } )
|
||||||
@@ -211,4 +210,3 @@ function AI_A2A_CAP:CreateAttackUnitTasks( AttackSetUnit, DefenderGroup, EngageA
|
|||||||
|
|
||||||
return AttackUnitTasks
|
return AttackUnitTasks
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -75,7 +75,7 @@
|
|||||||
--
|
--
|
||||||
-- ## 4. Is a border required?
|
-- ## 4. Is a border required?
|
||||||
--
|
--
|
||||||
-- Is this a cold car or a hot war situation? In case of a cold war situation, a border can be set that will only trigger defenses
|
-- Is this a cold war or a hot war situation? In case of a cold war situation, a border can be set that will only trigger defenses
|
||||||
-- if the border is crossed by enemy units.
|
-- if the border is crossed by enemy units.
|
||||||
--
|
--
|
||||||
-- ## 5. What maximum range needs to be checked to allow defenses to engage any attacker?
|
-- ## 5. What maximum range needs to be checked to allow defenses to engage any attacker?
|
||||||
@@ -3045,8 +3045,7 @@ do -- AI_A2A_DISPATCHER
|
|||||||
if DefenderTask.Type == "CAP" or DefenderTask.Type == "GCI" then
|
if DefenderTask.Type == "CAP" or DefenderTask.Type == "GCI" then
|
||||||
-- If there is no target, then add the AIGroup to the ResultAIGroups for Engagement to the AttackerSet
|
-- If there is no target, then add the AIGroup to the ResultAIGroups for Engagement to the AttackerSet
|
||||||
if DefenderTask.Target == nil then
|
if DefenderTask.Target == nil then
|
||||||
if DefenderTask.Fsm:Is( "Returning" )
|
if DefenderTask.Fsm:Is( "Returning" ) or DefenderTask.Fsm:Is( "Patrolling" ) then
|
||||||
or DefenderTask.Fsm:Is( "Patrolling" ) then
|
|
||||||
Friendlies = Friendlies or {}
|
Friendlies = Friendlies or {}
|
||||||
Friendlies[Friendly] = Friendly
|
Friendlies[Friendly] = Friendly
|
||||||
DefenderCount = DefenderCount + Friendly:GetSize()
|
DefenderCount = DefenderCount + Friendly:GetSize()
|
||||||
@@ -3231,65 +3230,73 @@ do -- AI_A2A_DISPATCHER
|
|||||||
self:SetDefenderTask( SquadronName, DefenderCAP, "CAP", AI_A2A_Fsm )
|
self:SetDefenderTask( SquadronName, DefenderCAP, "CAP", AI_A2A_Fsm )
|
||||||
|
|
||||||
function AI_A2A_Fsm:onafterTakeoff( DefenderGroup, From, Event, To )
|
function AI_A2A_Fsm:onafterTakeoff( DefenderGroup, From, Event, To )
|
||||||
self:F({"CAP Takeoff", DefenderGroup:GetName()})
|
-- Issue GetCallsign() returns nil, see https://github.com/FlightControl-Master/MOOSE/issues/1228
|
||||||
--self:GetParent(self).onafterBirth( self, Defender, From, Event, To )
|
if DefenderGroup and DefenderGroup:IsAlive() then
|
||||||
|
self:F({"CAP Takeoff", DefenderGroup:GetName()})
|
||||||
|
--self:GetParent(self).onafterBirth( self, Defender, From, Event, To )
|
||||||
|
|
||||||
local DefenderName = DefenderGroup:GetCallsign()
|
local DefenderName = DefenderGroup:GetCallsign()
|
||||||
local Dispatcher = AI_A2A_Fsm:GetDispatcher() -- #AI_A2A_DISPATCHER
|
local Dispatcher = AI_A2A_Fsm:GetDispatcher() -- #AI_A2A_DISPATCHER
|
||||||
local Squadron = Dispatcher:GetSquadronFromDefender( DefenderGroup )
|
local Squadron = Dispatcher:GetSquadronFromDefender( DefenderGroup )
|
||||||
|
|
||||||
if Squadron then
|
if Squadron then
|
||||||
Dispatcher:MessageToPlayers( Squadron, DefenderName .. " Wheels up.", DefenderGroup )
|
Dispatcher:MessageToPlayers( Squadron, DefenderName .. " Wheels up.", DefenderGroup )
|
||||||
AI_A2A_Fsm:__Patrol( 2 ) -- Start Patrolling
|
AI_A2A_Fsm:__Patrol( 2 ) -- Start Patrolling
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function AI_A2A_Fsm:onafterPatrolRoute( DefenderGroup, From, Event, To )
|
function AI_A2A_Fsm:onafterPatrolRoute( DefenderGroup, From, Event, To )
|
||||||
self:F({"CAP PatrolRoute", DefenderGroup:GetName()})
|
if DefenderGroup and DefenderGroup:IsAlive() then
|
||||||
self:GetParent(self).onafterPatrolRoute( self, DefenderGroup, From, Event, To )
|
self:F({"CAP PatrolRoute", DefenderGroup:GetName()})
|
||||||
|
self:GetParent(self).onafterPatrolRoute( self, DefenderGroup, From, Event, To )
|
||||||
|
|
||||||
local DefenderName = DefenderGroup:GetCallsign()
|
local DefenderName = DefenderGroup:GetCallsign()
|
||||||
local Dispatcher = self:GetDispatcher() -- #AI_A2G_DISPATCHER
|
local Dispatcher = self:GetDispatcher() -- #AI_A2G_DISPATCHER
|
||||||
local Squadron = Dispatcher:GetSquadronFromDefender( DefenderGroup )
|
local Squadron = Dispatcher:GetSquadronFromDefender( DefenderGroup )
|
||||||
if Squadron then
|
if Squadron then
|
||||||
Dispatcher:MessageToPlayers( Squadron, DefenderName .. ", patrolling.", DefenderGroup )
|
Dispatcher:MessageToPlayers( Squadron, DefenderName .. ", patrolling.", DefenderGroup )
|
||||||
|
end
|
||||||
|
|
||||||
|
Dispatcher:ClearDefenderTaskTarget( DefenderGroup )
|
||||||
end
|
end
|
||||||
|
|
||||||
Dispatcher:ClearDefenderTaskTarget( DefenderGroup )
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function AI_A2A_Fsm:onafterRTB( DefenderGroup, From, Event, To )
|
function AI_A2A_Fsm:onafterRTB( DefenderGroup, From, Event, To )
|
||||||
|
if DefenderGroup and DefenderGroup:IsAlive() then
|
||||||
|
self:F({"CAP RTB", DefenderGroup:GetName()})
|
||||||
|
|
||||||
self:F({"CAP RTB", DefenderGroup:GetName()})
|
self:GetParent(self).onafterRTB( self, DefenderGroup, From, Event, To )
|
||||||
|
|
||||||
self:GetParent(self).onafterRTB( self, DefenderGroup, From, Event, To )
|
local DefenderName = DefenderGroup:GetCallsign()
|
||||||
|
local Dispatcher = self:GetDispatcher() -- #AI_A2A_DISPATCHER
|
||||||
local DefenderName = DefenderGroup:GetCallsign()
|
local Squadron = Dispatcher:GetSquadronFromDefender( DefenderGroup )
|
||||||
local Dispatcher = self:GetDispatcher() -- #AI_A2A_DISPATCHER
|
if Squadron then
|
||||||
local Squadron = Dispatcher:GetSquadronFromDefender( DefenderGroup )
|
Dispatcher:MessageToPlayers( Squadron, DefenderName .. " returning to base.", DefenderGroup )
|
||||||
if Squadron then
|
end
|
||||||
Dispatcher:MessageToPlayers( Squadron, DefenderName .. " returning to base.", DefenderGroup )
|
Dispatcher:ClearDefenderTaskTarget( DefenderGroup )
|
||||||
end
|
end
|
||||||
Dispatcher:ClearDefenderTaskTarget( DefenderGroup )
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #AI_A2A_DISPATCHER self
|
--- @param #AI_A2A_DISPATCHER self
|
||||||
function AI_A2A_Fsm:onafterHome( Defender, From, Event, To, Action )
|
function AI_A2A_Fsm:onafterHome( Defender, From, Event, To, Action )
|
||||||
self:F({"CAP Home", Defender:GetName()})
|
if Defender and Defender:IsAlive() then
|
||||||
self:GetParent(self).onafterHome( self, Defender, From, Event, To )
|
self:F({"CAP Home", Defender:GetName()})
|
||||||
|
self:GetParent(self).onafterHome( self, Defender, From, Event, To )
|
||||||
|
|
||||||
local Dispatcher = self:GetDispatcher() -- #AI_A2A_DISPATCHER
|
local Dispatcher = self:GetDispatcher() -- #AI_A2A_DISPATCHER
|
||||||
local Squadron = Dispatcher:GetSquadronFromDefender( Defender )
|
local Squadron = Dispatcher:GetSquadronFromDefender( Defender )
|
||||||
|
|
||||||
if Action and Action == "Destroy" then
|
if Action and Action == "Destroy" then
|
||||||
Dispatcher:RemoveDefenderFromSquadron( Squadron, Defender )
|
Dispatcher:RemoveDefenderFromSquadron( Squadron, Defender )
|
||||||
Defender:Destroy()
|
Defender:Destroy()
|
||||||
end
|
end
|
||||||
|
|
||||||
if Dispatcher:GetSquadronLanding( Squadron.Name ) == AI_A2A_DISPATCHER.Landing.NearAirbase then
|
if Dispatcher:GetSquadronLanding( Squadron.Name ) == AI_A2A_DISPATCHER.Landing.NearAirbase then
|
||||||
Dispatcher:RemoveDefenderFromSquadron( Squadron, Defender )
|
Dispatcher:RemoveDefenderFromSquadron( Squadron, Defender )
|
||||||
Defender:Destroy()
|
Defender:Destroy()
|
||||||
Dispatcher:ParkDefender( Squadron )
|
Dispatcher:ParkDefender( Squadron )
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -3307,19 +3314,20 @@ do -- AI_A2A_DISPATCHER
|
|||||||
-- @param Functional.Detection#DETECTION_BASE.DetectedItem AttackerDetection Detected item.
|
-- @param Functional.Detection#DETECTION_BASE.DetectedItem AttackerDetection Detected item.
|
||||||
-- @param #table Defenders Defenders table.
|
-- @param #table Defenders Defenders table.
|
||||||
function AI_A2A_DISPATCHER:onafterENGAGE( From, Event, To, AttackerDetection, Defenders )
|
function AI_A2A_DISPATCHER:onafterENGAGE( From, Event, To, AttackerDetection, Defenders )
|
||||||
|
self:F("ENGAGING Detection ID="..tostring(AttackerDetection.ID))
|
||||||
self:F("ENGAGING "..tostring(AttackerDetection.Name))
|
|
||||||
|
|
||||||
if Defenders then
|
if Defenders then
|
||||||
|
|
||||||
for DefenderID, Defender in pairs( Defenders ) do
|
for DefenderID, Defender in pairs( Defenders ) do
|
||||||
|
|
||||||
local Fsm = self:GetDefenderTaskFsm( Defender )
|
local Fsm = self:GetDefenderTaskFsm( Defender )
|
||||||
|
|
||||||
Fsm:EngageRoute( AttackerDetection.Set ) -- Engage on the TargetSetUnit
|
Fsm:EngageRoute( AttackerDetection.Set ) -- Engage on the TargetSetUnit
|
||||||
|
|
||||||
self:SetDefenderTaskTarget( Defender, AttackerDetection )
|
self:SetDefenderTaskTarget( Defender, AttackerDetection )
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -3333,7 +3341,7 @@ do -- AI_A2A_DISPATCHER
|
|||||||
-- @param #table DefenderFriendlies Friendly defenders.
|
-- @param #table DefenderFriendlies Friendly defenders.
|
||||||
function AI_A2A_DISPATCHER:onafterGCI( From, Event, To, AttackerDetection, DefendersMissing, DefenderFriendlies )
|
function AI_A2A_DISPATCHER:onafterGCI( From, Event, To, AttackerDetection, DefendersMissing, DefenderFriendlies )
|
||||||
|
|
||||||
self:F("GCI "..tostring(AttackerDetection.Name))
|
self:F("GCI Detection ID="..tostring(AttackerDetection.ID))
|
||||||
|
|
||||||
self:F( { From, Event, To, AttackerDetection.Index, DefendersMissing, DefenderFriendlies } )
|
self:F( { From, Event, To, AttackerDetection.Index, DefendersMissing, DefenderFriendlies } )
|
||||||
|
|
||||||
@@ -3599,7 +3607,6 @@ do -- AI_A2A_DISPATCHER
|
|||||||
-- 3. There is sufficient ammo
|
-- 3. There is sufficient ammo
|
||||||
-- 4. The plane is not damaged
|
-- 4. The plane is not damaged
|
||||||
if DefenderGroups and DetectedItem.IsDetected == true then
|
if DefenderGroups and DetectedItem.IsDetected == true then
|
||||||
|
|
||||||
return DefenderGroups
|
return DefenderGroups
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -3636,22 +3643,31 @@ do -- AI_A2A_DISPATCHER
|
|||||||
--- Assigns A2G AI Tasks in relation to the detected items.
|
--- Assigns A2G AI Tasks in relation to the detected items.
|
||||||
-- @param #AI_A2G_DISPATCHER self
|
-- @param #AI_A2G_DISPATCHER self
|
||||||
function AI_A2A_DISPATCHER:Order( DetectedItem )
|
function AI_A2A_DISPATCHER:Order( DetectedItem )
|
||||||
local AttackCoordinate = self.Detection:GetDetectedItemCoordinate( DetectedItem )
|
|
||||||
|
local detection=self.Detection -- Functional.Detection#DETECTION_AREAS
|
||||||
|
|
||||||
local ShortestDistance = 999999999
|
local ShortestDistance = 999999999
|
||||||
|
|
||||||
for DefenderSquadronName, DefenderSquadron in pairs( self.DefenderSquadrons ) do
|
-- Get coordinate (or nil).
|
||||||
|
local AttackCoordinate = detection:GetDetectedItemCoordinate( DetectedItem )
|
||||||
|
|
||||||
self:I( { DefenderSquadron = DefenderSquadron.Name } )
|
-- Issue https://github.com/FlightControl-Master/MOOSE/issues/1232
|
||||||
|
if AttackCoordinate then
|
||||||
|
|
||||||
local Airbase = DefenderSquadron.Airbase
|
for DefenderSquadronName, DefenderSquadron in pairs( self.DefenderSquadrons ) do
|
||||||
local AirbaseCoordinate = Airbase:GetCoordinate()
|
|
||||||
|
|
||||||
local EvaluateDistance = AttackCoordinate:Get2DDistance( AirbaseCoordinate )
|
self:T( { DefenderSquadron = DefenderSquadron.Name } )
|
||||||
|
|
||||||
if EvaluateDistance <= ShortestDistance then
|
local Airbase = DefenderSquadron.Airbase
|
||||||
ShortestDistance = EvaluateDistance
|
local AirbaseCoordinate = Airbase:GetCoordinate()
|
||||||
|
|
||||||
|
local EvaluateDistance = AttackCoordinate:Get2DDistance( AirbaseCoordinate )
|
||||||
|
|
||||||
|
if EvaluateDistance <= ShortestDistance then
|
||||||
|
ShortestDistance = EvaluateDistance
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return ShortestDistance
|
return ShortestDistance
|
||||||
@@ -3660,6 +3676,7 @@ do -- AI_A2A_DISPATCHER
|
|||||||
|
|
||||||
--- Shows the tactical display.
|
--- Shows the tactical display.
|
||||||
-- @param #AI_A2A_DISPATCHER self
|
-- @param #AI_A2A_DISPATCHER self
|
||||||
|
-- @param Functional.Detection#DETECTION_BASE Detection The detection created by the @{Functional.Detection#DETECTION_BASE} derived object.
|
||||||
function AI_A2A_DISPATCHER:ShowTacticalDisplay( Detection )
|
function AI_A2A_DISPATCHER:ShowTacticalDisplay( Detection )
|
||||||
|
|
||||||
local AreaMsg = {}
|
local AreaMsg = {}
|
||||||
@@ -3668,7 +3685,7 @@ do -- AI_A2A_DISPATCHER
|
|||||||
|
|
||||||
local TaskReport = REPORT:New()
|
local TaskReport = REPORT:New()
|
||||||
|
|
||||||
local Report = REPORT:New( "Tactical Overviews" )
|
local Report = REPORT:New( "Tactical Overview:" )
|
||||||
|
|
||||||
local DefenderGroupCount = 0
|
local DefenderGroupCount = 0
|
||||||
|
|
||||||
@@ -4508,4 +4525,3 @@ do
|
|||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -172,7 +172,3 @@ function AI_A2A_GCI:CreateAttackUnitTasks( AttackSetUnit, DefenderGroup, EngageA
|
|||||||
|
|
||||||
return AttackUnitTasks
|
return AttackUnitTasks
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -121,13 +121,13 @@ AI_A2A_PATROL = {
|
|||||||
|
|
||||||
--- Creates a new AI_A2A_PATROL object
|
--- Creates a new AI_A2A_PATROL object
|
||||||
-- @param #AI_A2A_PATROL self
|
-- @param #AI_A2A_PATROL self
|
||||||
-- @param Wrapper.Group#GROUP AIPatrol
|
-- @param Wrapper.Group#GROUP AIPatrol The patrol group object.
|
||||||
-- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed.
|
-- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed.
|
||||||
-- @param DCS#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
|
-- @param DCS#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
|
||||||
-- @param DCS#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
|
-- @param DCS#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
|
||||||
-- @param DCS#Speed PatrolMinSpeed The minimum speed of the @{Wrapper.Group} in km/h.
|
-- @param DCS#Speed PatrolMinSpeed The minimum speed of the @{Wrapper.Group} in km/h.
|
||||||
-- @param DCS#Speed PatrolMaxSpeed The maximum speed of the @{Wrapper.Group} in km/h.
|
-- @param DCS#Speed PatrolMaxSpeed The maximum speed of the @{Wrapper.Group} in km/h.
|
||||||
-- @param DCS#AltitudeType PatrolAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to RADIO
|
-- @param DCS#AltitudeType PatrolAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to BARO
|
||||||
-- @return #AI_A2A_PATROL self
|
-- @return #AI_A2A_PATROL self
|
||||||
-- @usage
|
-- @usage
|
||||||
-- -- Define a new AI_A2A_PATROL Object. This PatrolArea will patrol a Group within PatrolZone between 3000 and 6000 meters, with a variying speed between 600 and 900 km/h.
|
-- -- Define a new AI_A2A_PATROL Object. This PatrolArea will patrol a Group within PatrolZone between 3000 and 6000 meters, with a variying speed between 600 and 900 km/h.
|
||||||
@@ -137,7 +137,7 @@ AI_A2A_PATROL = {
|
|||||||
function AI_A2A_PATROL:New( AIPatrol, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType )
|
function AI_A2A_PATROL:New( AIPatrol, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType )
|
||||||
|
|
||||||
local AI_Air = AI_AIR:New( AIPatrol )
|
local AI_Air = AI_AIR:New( AIPatrol )
|
||||||
local AI_Air_Patrol = AI_A2A_PATROL:New( AI_Air, AIPatrol, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType )
|
local AI_Air_Patrol = AI_AIR_PATROL:New( AI_Air, AIPatrol, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType )
|
||||||
local self = BASE:Inherit( self, AI_Air_Patrol ) -- #AI_A2A_PATROL
|
local self = BASE:Inherit( self, AI_Air_Patrol ) -- #AI_A2A_PATROL
|
||||||
|
|
||||||
self:SetFuelThreshold( .2, 60 )
|
self:SetFuelThreshold( .2, 60 )
|
||||||
@@ -151,8 +151,8 @@ function AI_A2A_PATROL:New( AIPatrol, PatrolZone, PatrolFloorAltitude, PatrolCei
|
|||||||
self.PatrolMinSpeed = PatrolMinSpeed
|
self.PatrolMinSpeed = PatrolMinSpeed
|
||||||
self.PatrolMaxSpeed = PatrolMaxSpeed
|
self.PatrolMaxSpeed = PatrolMaxSpeed
|
||||||
|
|
||||||
-- defafult PatrolAltType to "RADIO" if not specified
|
-- defafult PatrolAltType to "BARO" if not specified
|
||||||
self.PatrolAltType = PatrolAltType or "RADIO"
|
self.PatrolAltType = PatrolAltType or "BARO"
|
||||||
|
|
||||||
self:AddTransition( { "Started", "Airborne", "Refuelling" }, "Patrol", "Patrolling" )
|
self:AddTransition( { "Started", "Airborne", "Refuelling" }, "Patrol", "Patrolling" )
|
||||||
|
|
||||||
@@ -287,15 +287,15 @@ function AI_A2A_PATROL:onafterPatrol( AIPatrol, From, Event, To )
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- This statis method is called from the route path within the last task at the last waaypoint of the AIPatrol.
|
||||||
--- @param Wrapper.Group#GROUP AIPatrol
|
|
||||||
-- This statis method is called from the route path within the last task at the last waaypoint of the AIPatrol.
|
|
||||||
-- Note that this method is required, as triggers the next route when patrolling for the AIPatrol.
|
-- Note that this method is required, as triggers the next route when patrolling for the AIPatrol.
|
||||||
|
-- @param Wrapper.Group#GROUP AIPatrol The AI group.
|
||||||
|
-- @param #AI_A2A_PATROL Fsm The FSM.
|
||||||
function AI_A2A_PATROL.PatrolRoute( AIPatrol, Fsm )
|
function AI_A2A_PATROL.PatrolRoute( AIPatrol, Fsm )
|
||||||
|
|
||||||
AIPatrol:F( { "AI_A2A_PATROL.PatrolRoute:", AIPatrol:GetName() } )
|
AIPatrol:F( { "AI_A2A_PATROL.PatrolRoute:", AIPatrol:GetName() } )
|
||||||
|
|
||||||
if AIPatrol:IsAlive() then
|
if AIPatrol and AIPatrol:IsAlive() then
|
||||||
Fsm:Route()
|
Fsm:Route()
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -309,7 +309,6 @@ end
|
|||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
-- @param #string To The To State string.
|
-- @param #string To The To State string.
|
||||||
function AI_A2A_PATROL:onafterRoute( AIPatrol, From, Event, To )
|
function AI_A2A_PATROL:onafterRoute( AIPatrol, From, Event, To )
|
||||||
|
|
||||||
self:F2()
|
self:F2()
|
||||||
|
|
||||||
-- When RTB, don't allow anymore the routing.
|
-- When RTB, don't allow anymore the routing.
|
||||||
|
|||||||
@@ -4375,7 +4375,7 @@ do -- AI_A2G_DISPATCHER
|
|||||||
|
|
||||||
Report:Add( string.format( "\n - Squadron Resources: ", #self.DefenseQueue ) )
|
Report:Add( string.format( "\n - Squadron Resources: ", #self.DefenseQueue ) )
|
||||||
for DefenderSquadronName, DefenderSquadron in pairs( self.DefenderSquadrons ) do
|
for DefenderSquadronName, DefenderSquadron in pairs( self.DefenderSquadrons ) do
|
||||||
Report:Add( string.format( " - %s - %d", DefenderSquadronName, DefenderSquadron.ResourceCount and DefenderSquadron.ResourceCount or "n/a" ) )
|
Report:Add( string.format( " - %s - %s", DefenderSquadronName, DefenderSquadron.ResourceCount and tostring(DefenderSquadron.ResourceCount) or "n/a" ) )
|
||||||
end
|
end
|
||||||
|
|
||||||
self:F( Report:Text( "\n" ) )
|
self:F( Report:Text( "\n" ) )
|
||||||
@@ -4594,7 +4594,7 @@ do -- AI_A2G_DISPATCHER
|
|||||||
|
|
||||||
Report:Add( string.format( "\n - Squadron Resources: ", #self.DefenseQueue ) )
|
Report:Add( string.format( "\n - Squadron Resources: ", #self.DefenseQueue ) )
|
||||||
for DefenderSquadronName, DefenderSquadron in pairs( self.DefenderSquadrons ) do
|
for DefenderSquadronName, DefenderSquadron in pairs( self.DefenderSquadrons ) do
|
||||||
Report:Add( string.format( " - %s - %d", DefenderSquadronName, DefenderSquadron.ResourceCount and DefenderSquadron.ResourceCount or "n/a" ) )
|
Report:Add( string.format( " - %s - %s", DefenderSquadronName, DefenderSquadron.ResourceCount and tostring(DefenderSquadron.ResourceCount) or "n/a" ) )
|
||||||
end
|
end
|
||||||
|
|
||||||
self:F( Report:Text( "\n" ) )
|
self:F( Report:Text( "\n" ) )
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
--- **AI** -- Models the process of AI air operations.
|
--- **AI** - Models the process of AI air operations.
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
@@ -492,6 +492,7 @@ function AI_AIR:onafterStatus()
|
|||||||
OldAIControllable:SetTask( TimedOrbitTask, 10 )
|
OldAIControllable:SetTask( TimedOrbitTask, 10 )
|
||||||
|
|
||||||
self:Fuel()
|
self:Fuel()
|
||||||
|
RTB = true
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
end
|
end
|
||||||
@@ -707,13 +708,14 @@ end
|
|||||||
function AI_AIR:onafterRefuel( AIGroup, From, Event, To )
|
function AI_AIR:onafterRefuel( AIGroup, From, Event, To )
|
||||||
self:F( { AIGroup, From, Event, To } )
|
self:F( { AIGroup, From, Event, To } )
|
||||||
|
|
||||||
|
|
||||||
if AIGroup and AIGroup:IsAlive() then
|
if AIGroup and AIGroup:IsAlive() then
|
||||||
|
|
||||||
|
-- Get tanker group.
|
||||||
local Tanker = GROUP:FindByName( self.TankerName )
|
local Tanker = GROUP:FindByName( self.TankerName )
|
||||||
|
|
||||||
if Tanker:IsAlive() and Tanker:IsAirPlane() then
|
if Tanker and Tanker:IsAlive() and Tanker:IsAirPlane() then
|
||||||
|
|
||||||
self:I( "Group " .. self.Controllable:GetName() .. " ... Refuelling! ( " .. self:GetState() .. "), at tanker " .. self.TankerName )
|
self:I( "Group " .. self.Controllable:GetName() .. " ... Refuelling! State=" .. self:GetState() .. ", Refuelling tanker " .. self.TankerName )
|
||||||
|
|
||||||
local RefuelRoute = {}
|
local RefuelRoute = {}
|
||||||
|
|
||||||
@@ -724,40 +726,43 @@ function AI_AIR:onafterRefuel( AIGroup, From, Event, To )
|
|||||||
local ToRefuelSpeed = math.random( self.PatrolMinSpeed, self.PatrolMaxSpeed )
|
local ToRefuelSpeed = math.random( self.PatrolMinSpeed, self.PatrolMaxSpeed )
|
||||||
|
|
||||||
--- Create a route point of type air.
|
--- Create a route point of type air.
|
||||||
local FromRefuelRoutePoint = FromRefuelCoord:WaypointAir(
|
local FromRefuelRoutePoint = FromRefuelCoord:WaypointAir(self.PatrolAltType, POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, ToRefuelSpeed, true)
|
||||||
self.PatrolAltType,
|
|
||||||
POINT_VEC3.RoutePointType.TurningPoint,
|
|
||||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
|
||||||
ToRefuelSpeed,
|
|
||||||
true
|
|
||||||
)
|
|
||||||
|
|
||||||
--- Create a route point of type air.
|
--- Create a route point of type air. NOT used!
|
||||||
local ToRefuelRoutePoint = FromRefuelCoord:WaypointAir(
|
local ToRefuelRoutePoint = Tanker:GetCoordinate():WaypointAir(self.PatrolAltType, POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, ToRefuelSpeed, true)
|
||||||
self.PatrolAltType,
|
|
||||||
POINT_VEC3.RoutePointType.TurningPoint,
|
|
||||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
|
||||||
ToRefuelSpeed,
|
|
||||||
true
|
|
||||||
)
|
|
||||||
|
|
||||||
self:F( { ToRefuelSpeed = ToRefuelSpeed } )
|
self:F( { ToRefuelSpeed = ToRefuelSpeed } )
|
||||||
|
|
||||||
RefuelRoute[#RefuelRoute+1] = FromRefuelRoutePoint
|
RefuelRoute[#RefuelRoute+1] = FromRefuelRoutePoint
|
||||||
--RefuelRoute[#RefuelRoute+1] = ToRefuelRoutePoint
|
RefuelRoute[#RefuelRoute+1] = ToRefuelRoutePoint
|
||||||
|
|
||||||
AIGroup:OptionROEHoldFire()
|
AIGroup:OptionROEHoldFire()
|
||||||
AIGroup:OptionROTEvadeFire()
|
AIGroup:OptionROTEvadeFire()
|
||||||
|
|
||||||
|
-- Get Class name for .Resume function
|
||||||
|
local classname=self:GetClassName()
|
||||||
|
|
||||||
|
-- AI_A2A_CAP can call this function but does not have a .Resume function. Try to fix.
|
||||||
|
if classname=="AI_A2A_CAP" then
|
||||||
|
classname="AI_AIR_PATROL"
|
||||||
|
end
|
||||||
|
|
||||||
|
env.info("FF refueling classname="..classname)
|
||||||
|
|
||||||
local Tasks = {}
|
local Tasks = {}
|
||||||
Tasks[#Tasks+1] = AIGroup:TaskRefueling()
|
Tasks[#Tasks+1] = AIGroup:TaskRefueling()
|
||||||
Tasks[#Tasks+1] = AIGroup:TaskFunction( self:GetClassName() .. ".Resume", self )
|
Tasks[#Tasks+1] = AIGroup:TaskFunction( classname .. ".Resume", self )
|
||||||
RefuelRoute[#RefuelRoute].task = AIGroup:TaskCombo( Tasks )
|
RefuelRoute[#RefuelRoute].task = AIGroup:TaskCombo( Tasks )
|
||||||
|
|
||||||
AIGroup:Route( RefuelRoute, self.TaskDelay )
|
AIGroup:Route( RefuelRoute, self.TaskDelay )
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
|
-- No tanker defined ==> RTB!
|
||||||
self:RTB()
|
self:RTB()
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -80,7 +80,8 @@ AI_AIR_ENGAGE = {
|
|||||||
|
|
||||||
--- Creates a new AI_AIR_ENGAGE object
|
--- Creates a new AI_AIR_ENGAGE object
|
||||||
-- @param #AI_AIR_ENGAGE self
|
-- @param #AI_AIR_ENGAGE self
|
||||||
-- @param Wrapper.Group#GROUP AIGroup
|
-- @param AI.AI_Air#AI_AIR AI_Air The AI_AIR FSM.
|
||||||
|
-- @param Wrapper.Group#GROUP AIGroup The AI group.
|
||||||
-- @param DCS#Speed EngageMinSpeed (optional, default = 50% of max speed) The minimum speed of the @{Wrapper.Group} in km/h when engaging a target.
|
-- @param DCS#Speed EngageMinSpeed (optional, default = 50% of max speed) The minimum speed of the @{Wrapper.Group} in km/h when engaging a target.
|
||||||
-- @param DCS#Speed EngageMaxSpeed (optional, default = 75% of max speed) The maximum speed of the @{Wrapper.Group} in km/h when engaging a target.
|
-- @param DCS#Speed EngageMaxSpeed (optional, default = 75% of max speed) The maximum speed of the @{Wrapper.Group} in km/h when engaging a target.
|
||||||
-- @param DCS#Altitude EngageFloorAltitude (optional, default = 1000m ) The lowest altitude in meters where to execute the engagement.
|
-- @param DCS#Altitude EngageFloorAltitude (optional, default = 1000m ) The lowest altitude in meters where to execute the engagement.
|
||||||
@@ -334,9 +335,8 @@ end
|
|||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
-- @param #string To The To State string.
|
-- @param #string To The To State string.
|
||||||
function AI_AIR_ENGAGE:onafterEngage( AIGroup, From, Event, To )
|
function AI_AIR_ENGAGE:onafterEngage( AIGroup, From, Event, To )
|
||||||
|
-- TODO: This function is overwritten below!
|
||||||
self:HandleEvent( EVENTS.Dead )
|
self:HandleEvent( EVENTS.Dead )
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- todo: need to fix this global function
|
-- todo: need to fix this global function
|
||||||
@@ -349,10 +349,10 @@ end
|
|||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
-- @param #string To The To State string.
|
-- @param #string To The To State string.
|
||||||
function AI_AIR_ENGAGE:onbeforeEngage( AIGroup, From, Event, To )
|
function AI_AIR_ENGAGE:onbeforeEngage( AIGroup, From, Event, To )
|
||||||
|
|
||||||
if self.Accomplished == true then
|
if self.Accomplished == true then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
--- onafter event handler for Abort event.
|
--- onafter event handler for Abort event.
|
||||||
@@ -374,7 +374,7 @@ end
|
|||||||
-- @param #string To The To State string.
|
-- @param #string To The To State string.
|
||||||
function AI_AIR_ENGAGE:onafterAccomplish( AIGroup, From, Event, To )
|
function AI_AIR_ENGAGE:onafterAccomplish( AIGroup, From, Event, To )
|
||||||
self.Accomplished = true
|
self.Accomplished = true
|
||||||
self:SetDetectionOff()
|
--self:SetDetectionOff()
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #AI_AIR_ENGAGE self
|
--- @param #AI_AIR_ENGAGE self
|
||||||
@@ -405,14 +405,10 @@ end
|
|||||||
|
|
||||||
--- @param Wrapper.Group#GROUP AIControllable
|
--- @param Wrapper.Group#GROUP AIControllable
|
||||||
function AI_AIR_ENGAGE.___EngageRoute( AIGroup, Fsm, AttackSetUnit )
|
function AI_AIR_ENGAGE.___EngageRoute( AIGroup, Fsm, AttackSetUnit )
|
||||||
|
Fsm:I(string.format("AI_AIR_ENGAGE.___EngageRoute: %s", tostring(AIGroup:GetName())))
|
||||||
|
|
||||||
Fsm:I( { "AI_AIR_ENGAGE.___EngageRoute:", AIGroup:GetName() } )
|
if AIGroup and AIGroup:IsAlive() then
|
||||||
|
Fsm:__EngageRoute( Fsm.TaskDelay or 0.1, AttackSetUnit )
|
||||||
if AIGroup:IsAlive() then
|
|
||||||
Fsm:__EngageRoute( Fsm.TaskDelay, AttackSetUnit )
|
|
||||||
|
|
||||||
--local Task = AIGroup:TaskOrbitCircle( 4000, 400 )
|
|
||||||
--AIGroup:SetTask( Task )
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -423,7 +419,6 @@ end
|
|||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
-- @param #string To The To State string.
|
-- @param #string To The To State string.
|
||||||
function AI_AIR_ENGAGE:onafterEngageRoute( DefenderGroup, From, Event, To, AttackSetUnit )
|
function AI_AIR_ENGAGE:onafterEngageRoute( DefenderGroup, From, Event, To, AttackSetUnit )
|
||||||
|
|
||||||
self:I( { DefenderGroup, From, Event, To, AttackSetUnit } )
|
self:I( { DefenderGroup, From, Event, To, AttackSetUnit } )
|
||||||
|
|
||||||
local DefenderGroupName = DefenderGroup:GetName()
|
local DefenderGroupName = DefenderGroup:GetName()
|
||||||
@@ -452,37 +447,31 @@ function AI_AIR_ENGAGE:onafterEngageRoute( DefenderGroup, From, Event, To, Attac
|
|||||||
local TargetDistance = DefenderCoord:Get2DDistance( TargetCoord )
|
local TargetDistance = DefenderCoord:Get2DDistance( TargetCoord )
|
||||||
local EngageDistance = ( DefenderGroup:IsHelicopter() and 5000 ) or ( DefenderGroup:IsAirPlane() and 10000 )
|
local EngageDistance = ( DefenderGroup:IsHelicopter() and 5000 ) or ( DefenderGroup:IsAirPlane() and 10000 )
|
||||||
|
|
||||||
if TargetDistance <= EngageDistance * 3 then
|
-- TODO: A factor of * 3 is way too close. This causes the AI not to engange until merged sometimes!
|
||||||
|
if TargetDistance <= EngageDistance * 9 then
|
||||||
|
|
||||||
|
self:I(string.format("AI_AIR_ENGAGE onafterEngageRoute ==> __Engage - target distance = %.1f km", TargetDistance/1000))
|
||||||
self:__Engage( 0.1, AttackSetUnit )
|
self:__Engage( 0.1, AttackSetUnit )
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
|
self:I(string.format("FF AI_AIR_ENGAGE onafterEngageRoute ==> Routing - target distance = %.1f km", TargetDistance/1000))
|
||||||
|
|
||||||
local EngageRoute = {}
|
local EngageRoute = {}
|
||||||
local AttackTasks = {}
|
local AttackTasks = {}
|
||||||
|
|
||||||
--- Calculate the target route point.
|
--- Calculate the target route point.
|
||||||
|
|
||||||
local FromWP = DefenderCoord:WaypointAir(
|
local FromWP = DefenderCoord:WaypointAir(self.PatrolAltType or "RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, EngageSpeed, true)
|
||||||
self.PatrolAltType or "RADIO",
|
|
||||||
POINT_VEC3.RoutePointType.TurningPoint,
|
|
||||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
|
||||||
EngageSpeed,
|
|
||||||
true
|
|
||||||
)
|
|
||||||
|
|
||||||
EngageRoute[#EngageRoute+1] = FromWP
|
EngageRoute[#EngageRoute+1] = FromWP
|
||||||
|
|
||||||
self:SetTargetDistance( TargetCoord ) -- For RTB status check
|
self:SetTargetDistance( TargetCoord ) -- For RTB status check
|
||||||
|
|
||||||
local FromEngageAngle = DefenderCoord:GetAngleDegrees( DefenderCoord:GetDirectionVec3( TargetCoord ) )
|
local FromEngageAngle = DefenderCoord:GetAngleDegrees( DefenderCoord:GetDirectionVec3( TargetCoord ) )
|
||||||
local ToWP = DefenderCoord:Translate( EngageDistance, FromEngageAngle, true ):WaypointAir(
|
local ToCoord=DefenderCoord:Translate( EngageDistance, FromEngageAngle, true )
|
||||||
self.PatrolAltType or "RADIO",
|
|
||||||
POINT_VEC3.RoutePointType.TurningPoint,
|
local ToWP = ToCoord:WaypointAir(self.PatrolAltType or "RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, EngageSpeed, true)
|
||||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
|
||||||
EngageSpeed,
|
|
||||||
true
|
|
||||||
)
|
|
||||||
|
|
||||||
EngageRoute[#EngageRoute+1] = ToWP
|
EngageRoute[#EngageRoute+1] = ToWP
|
||||||
|
|
||||||
@@ -492,11 +481,12 @@ function AI_AIR_ENGAGE:onafterEngageRoute( DefenderGroup, From, Event, To, Attac
|
|||||||
DefenderGroup:OptionROEReturnFire()
|
DefenderGroup:OptionROEReturnFire()
|
||||||
DefenderGroup:OptionROTEvadeFire()
|
DefenderGroup:OptionROTEvadeFire()
|
||||||
|
|
||||||
DefenderGroup:Route( EngageRoute, self.TaskDelay )
|
DefenderGroup:Route( EngageRoute, self.TaskDelay or 0.1 )
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
-- TODO: This will make an A2A Dispatcher CAP flight to return rather than going back to patrolling!
|
||||||
self:I( DefenderGroupName .. ": No targets found -> Going RTB")
|
self:I( DefenderGroupName .. ": No targets found -> Going RTB")
|
||||||
self:Return()
|
self:Return()
|
||||||
end
|
end
|
||||||
@@ -506,10 +496,11 @@ end
|
|||||||
--- @param Wrapper.Group#GROUP AIControllable
|
--- @param Wrapper.Group#GROUP AIControllable
|
||||||
function AI_AIR_ENGAGE.___Engage( AIGroup, Fsm, AttackSetUnit )
|
function AI_AIR_ENGAGE.___Engage( AIGroup, Fsm, AttackSetUnit )
|
||||||
|
|
||||||
Fsm:I( { "AI_AIR_ENGAGE.___Engage:", AIGroup:GetName() } )
|
Fsm:I(string.format("AI_AIR_ENGAGE.___Engage: %s", tostring(AIGroup:GetName())))
|
||||||
|
|
||||||
if AIGroup:IsAlive() then
|
if AIGroup and AIGroup:IsAlive() then
|
||||||
Fsm:__Engage( Fsm.TaskDelay, AttackSetUnit )
|
local delay=Fsm.TaskDelay or 0.1
|
||||||
|
Fsm:__Engage(delay, AttackSetUnit)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -520,7 +511,6 @@ end
|
|||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
-- @param #string To The To State string.
|
-- @param #string To The To State string.
|
||||||
function AI_AIR_ENGAGE:onafterEngage( DefenderGroup, From, Event, To, AttackSetUnit )
|
function AI_AIR_ENGAGE:onafterEngage( DefenderGroup, From, Event, To, AttackSetUnit )
|
||||||
|
|
||||||
self:F( { DefenderGroup, From, Event, To, AttackSetUnit} )
|
self:F( { DefenderGroup, From, Event, To, AttackSetUnit} )
|
||||||
|
|
||||||
local DefenderGroupName = DefenderGroup:GetName()
|
local DefenderGroupName = DefenderGroup:GetName()
|
||||||
@@ -532,7 +522,7 @@ function AI_AIR_ENGAGE:onafterEngage( DefenderGroup, From, Event, To, AttackSetU
|
|||||||
|
|
||||||
if AttackCount > 0 then
|
if AttackCount > 0 then
|
||||||
|
|
||||||
if DefenderGroup:IsAlive() then
|
if DefenderGroup and DefenderGroup:IsAlive() then
|
||||||
|
|
||||||
local EngageAltitude = math.random( self.EngageFloorAltitude or 500, self.EngageCeilingAltitude or 1000 )
|
local EngageAltitude = math.random( self.EngageFloorAltitude or 500, self.EngageCeilingAltitude or 1000 )
|
||||||
local EngageSpeed = math.random( self.EngageMinSpeed, self.EngageMaxSpeed )
|
local EngageSpeed = math.random( self.EngageMinSpeed, self.EngageMaxSpeed )
|
||||||
@@ -544,33 +534,25 @@ function AI_AIR_ENGAGE:onafterEngage( DefenderGroup, From, Event, To, AttackSetU
|
|||||||
TargetCoord:SetY( EngageAltitude ) -- Ground targets don't have an altitude.
|
TargetCoord:SetY( EngageAltitude ) -- Ground targets don't have an altitude.
|
||||||
|
|
||||||
local TargetDistance = DefenderCoord:Get2DDistance( TargetCoord )
|
local TargetDistance = DefenderCoord:Get2DDistance( TargetCoord )
|
||||||
|
|
||||||
local EngageDistance = ( DefenderGroup:IsHelicopter() and 5000 ) or ( DefenderGroup:IsAirPlane() and 10000 )
|
local EngageDistance = ( DefenderGroup:IsHelicopter() and 5000 ) or ( DefenderGroup:IsAirPlane() and 10000 )
|
||||||
|
|
||||||
local EngageRoute = {}
|
local EngageRoute = {}
|
||||||
local AttackTasks = {}
|
local AttackTasks = {}
|
||||||
|
|
||||||
local FromWP = DefenderCoord:WaypointAir(
|
local FromWP = DefenderCoord:WaypointAir(self.EngageAltType or "RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, EngageSpeed, true)
|
||||||
self.EngageAltType or "RADIO",
|
|
||||||
POINT_VEC3.RoutePointType.TurningPoint,
|
|
||||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
|
||||||
EngageSpeed,
|
|
||||||
true
|
|
||||||
)
|
|
||||||
EngageRoute[#EngageRoute+1] = FromWP
|
EngageRoute[#EngageRoute+1] = FromWP
|
||||||
|
|
||||||
self:SetTargetDistance( TargetCoord ) -- For RTB status check
|
self:SetTargetDistance( TargetCoord ) -- For RTB status check
|
||||||
|
|
||||||
local FromEngageAngle = DefenderCoord:GetAngleDegrees( DefenderCoord:GetDirectionVec3( TargetCoord ) )
|
local FromEngageAngle = DefenderCoord:GetAngleDegrees( DefenderCoord:GetDirectionVec3( TargetCoord ) )
|
||||||
local ToWP = DefenderCoord:Translate( EngageDistance, FromEngageAngle, true ):WaypointAir(
|
local ToCoord=DefenderCoord:Translate( EngageDistance, FromEngageAngle, true )
|
||||||
self.EngageAltType or "RADIO",
|
|
||||||
POINT_VEC3.RoutePointType.TurningPoint,
|
local ToWP = ToCoord:WaypointAir(self.EngageAltType or "RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, EngageSpeed, true)
|
||||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
|
||||||
EngageSpeed,
|
|
||||||
true
|
|
||||||
)
|
|
||||||
EngageRoute[#EngageRoute+1] = ToWP
|
EngageRoute[#EngageRoute+1] = ToWP
|
||||||
|
|
||||||
if TargetDistance <= EngageDistance * 3 then
|
-- TODO: A factor of * 3 this way too low. This causes the AI NOT to engage until very close or even merged sometimes. Some A2A missiles have a much longer range! Needs more frequent updates of the task!
|
||||||
|
if TargetDistance <= EngageDistance * 9 then
|
||||||
|
|
||||||
local AttackUnitTasks = self:CreateAttackUnitTasks( AttackSetUnit, DefenderGroup, EngageAltitude ) -- Polymorphic
|
local AttackUnitTasks = self:CreateAttackUnitTasks( AttackSetUnit, DefenderGroup, EngageAltitude ) -- Polymorphic
|
||||||
|
|
||||||
@@ -579,7 +561,8 @@ function AI_AIR_ENGAGE:onafterEngage( DefenderGroup, From, Event, To, AttackSetU
|
|||||||
self:Return()
|
self:Return()
|
||||||
return
|
return
|
||||||
else
|
else
|
||||||
self:I( DefenderGroupName .. ": Engaging targets " )
|
local text=string.format("%s: Engaging targets at distance %.2f NM", DefenderGroupName, UTILS.MetersToNM(TargetDistance))
|
||||||
|
self:I(text)
|
||||||
DefenderGroup:OptionROEOpenFire()
|
DefenderGroup:OptionROEOpenFire()
|
||||||
DefenderGroup:OptionROTEvadeFire()
|
DefenderGroup:OptionROTEvadeFire()
|
||||||
DefenderGroup:OptionKeepWeaponsOnThreat()
|
DefenderGroup:OptionKeepWeaponsOnThreat()
|
||||||
@@ -591,10 +574,11 @@ function AI_AIR_ENGAGE:onafterEngage( DefenderGroup, From, Event, To, AttackSetU
|
|||||||
AttackTasks[#AttackTasks+1] = DefenderGroup:TaskFunction( "AI_AIR_ENGAGE.___Engage", self, AttackSetUnit )
|
AttackTasks[#AttackTasks+1] = DefenderGroup:TaskFunction( "AI_AIR_ENGAGE.___Engage", self, AttackSetUnit )
|
||||||
EngageRoute[#EngageRoute].task = DefenderGroup:TaskCombo( AttackTasks )
|
EngageRoute[#EngageRoute].task = DefenderGroup:TaskCombo( AttackTasks )
|
||||||
|
|
||||||
DefenderGroup:Route( EngageRoute, self.TaskDelay )
|
DefenderGroup:Route( EngageRoute, self.TaskDelay or 0.1 )
|
||||||
|
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
-- TODO: This will make an A2A Dispatcher CAP flight to return rather than going back to patrolling!
|
||||||
self:I( DefenderGroupName .. ": No targets found -> returning.")
|
self:I( DefenderGroupName .. ": No targets found -> returning.")
|
||||||
self:Return()
|
self:Return()
|
||||||
return
|
return
|
||||||
@@ -605,9 +589,9 @@ end
|
|||||||
function AI_AIR_ENGAGE.Resume( AIEngage, Fsm )
|
function AI_AIR_ENGAGE.Resume( AIEngage, Fsm )
|
||||||
|
|
||||||
AIEngage:F( { "Resume:", AIEngage:GetName() } )
|
AIEngage:F( { "Resume:", AIEngage:GetName() } )
|
||||||
if AIEngage:IsAlive() then
|
if AIEngage and AIEngage:IsAlive() then
|
||||||
Fsm:__Reset( Fsm.TaskDelay )
|
Fsm:__Reset( Fsm.TaskDelay or 0.1 )
|
||||||
Fsm:__EngageRoute( Fsm.TaskDelay, Fsm.AttackSetUnit )
|
Fsm:__EngageRoute( Fsm.TaskDelay or 0.2, Fsm.AttackSetUnit )
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -99,7 +99,8 @@ AI_AIR_PATROL = {
|
|||||||
|
|
||||||
--- Creates a new AI_AIR_PATROL object
|
--- Creates a new AI_AIR_PATROL object
|
||||||
-- @param #AI_AIR_PATROL self
|
-- @param #AI_AIR_PATROL self
|
||||||
-- @param Wrapper.Group#GROUP AIGroup
|
-- @param AI.AI_Air#AI_AIR AI_Air The AI_AIR FSM.
|
||||||
|
-- @param Wrapper.Group#GROUP AIGroup The AI group.
|
||||||
-- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed.
|
-- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed.
|
||||||
-- @param DCS#Altitude PatrolFloorAltitude (optional, default = 1000m ) The lowest altitude in meters where to execute the patrol.
|
-- @param DCS#Altitude PatrolFloorAltitude (optional, default = 1000m ) The lowest altitude in meters where to execute the patrol.
|
||||||
-- @param DCS#Altitude PatrolCeilingAltitude (optional, default = 1500m ) The highest altitude in meters where to execute the patrol.
|
-- @param DCS#Altitude PatrolCeilingAltitude (optional, default = 1500m ) The highest altitude in meters where to execute the patrol.
|
||||||
@@ -270,14 +271,15 @@ function AI_AIR_PATROL:onafterPatrol( AIPatrol, From, Event, To )
|
|||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param Wrapper.Group#GROUP AIPatrol
|
--- This statis method is called from the route path within the last task at the last waaypoint of the AIPatrol.
|
||||||
-- This statis method is called from the route path within the last task at the last waaypoint of the AIPatrol.
|
|
||||||
-- Note that this method is required, as triggers the next route when patrolling for the AIPatrol.
|
-- Note that this method is required, as triggers the next route when patrolling for the AIPatrol.
|
||||||
|
-- @param Wrapper.Group#GROUP AIPatrol The AI group.
|
||||||
|
-- @param #AI_AIR_PATROL Fsm The FSM.
|
||||||
function AI_AIR_PATROL.___PatrolRoute( AIPatrol, Fsm )
|
function AI_AIR_PATROL.___PatrolRoute( AIPatrol, Fsm )
|
||||||
|
|
||||||
AIPatrol:F( { "AI_AIR_PATROL.___PatrolRoute:", AIPatrol:GetName() } )
|
AIPatrol:F( { "AI_AIR_PATROL.___PatrolRoute:", AIPatrol:GetName() } )
|
||||||
|
|
||||||
if AIPatrol:IsAlive() then
|
if AIPatrol and AIPatrol:IsAlive() then
|
||||||
Fsm:PatrolRoute()
|
Fsm:PatrolRoute()
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -299,7 +301,7 @@ function AI_AIR_PATROL:onafterPatrolRoute( AIPatrol, From, Event, To )
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
if AIPatrol:IsAlive() then
|
if AIPatrol and AIPatrol:IsAlive() then
|
||||||
|
|
||||||
local PatrolRoute = {}
|
local PatrolRoute = {}
|
||||||
|
|
||||||
@@ -316,13 +318,7 @@ function AI_AIR_PATROL:onafterPatrolRoute( AIPatrol, From, Event, To )
|
|||||||
local ToTargetSpeed = math.random( self.PatrolMinSpeed, self.PatrolMaxSpeed )
|
local ToTargetSpeed = math.random( self.PatrolMinSpeed, self.PatrolMaxSpeed )
|
||||||
local speedkmh=ToTargetSpeed
|
local speedkmh=ToTargetSpeed
|
||||||
|
|
||||||
local FromWP = CurrentCoord:WaypointAir(
|
local FromWP = CurrentCoord:WaypointAir(self.PatrolAltType or "RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, ToTargetSpeed, true)
|
||||||
self.PatrolAltType or "RADIO",
|
|
||||||
POINT_VEC3.RoutePointType.TurningPoint,
|
|
||||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
|
||||||
ToTargetSpeed,
|
|
||||||
true
|
|
||||||
)
|
|
||||||
PatrolRoute[#PatrolRoute+1] = FromWP
|
PatrolRoute[#PatrolRoute+1] = FromWP
|
||||||
|
|
||||||
if self.racetrack then
|
if self.racetrack then
|
||||||
@@ -360,7 +356,7 @@ function AI_AIR_PATROL:onafterPatrolRoute( AIPatrol, From, Event, To )
|
|||||||
local taskOrbit=AIPatrol:TaskOrbit(c1, altitude, UTILS.KmphToMps(speedkmh), c2)
|
local taskOrbit=AIPatrol:TaskOrbit(c1, altitude, UTILS.KmphToMps(speedkmh), c2)
|
||||||
|
|
||||||
-- Task function to redo the patrol at other random position.
|
-- Task function to redo the patrol at other random position.
|
||||||
local taskPatrol=AIPatrol:TaskFunction("AI_A2A_PATROL.PatrolRoute", self)
|
local taskPatrol=AIPatrol:TaskFunction("AI_AIR_PATROL.___PatrolRoute", self)
|
||||||
|
|
||||||
-- Controlled task with task condition.
|
-- Controlled task with task condition.
|
||||||
local taskCond=AIPatrol:TaskCondition(nil, nil, nil, nil, duration, nil)
|
local taskCond=AIPatrol:TaskCondition(nil, nil, nil, nil, duration, nil)
|
||||||
@@ -372,18 +368,11 @@ function AI_AIR_PATROL:onafterPatrolRoute( AIPatrol, From, Event, To )
|
|||||||
else
|
else
|
||||||
|
|
||||||
--- Create a route point of type air.
|
--- Create a route point of type air.
|
||||||
local ToWP = ToTargetCoord:WaypointAir(
|
local ToWP = ToTargetCoord:WaypointAir(self.PatrolAltType, POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, ToTargetSpeed, true)
|
||||||
self.PatrolAltType,
|
|
||||||
POINT_VEC3.RoutePointType.TurningPoint,
|
|
||||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
|
||||||
ToTargetSpeed,
|
|
||||||
true
|
|
||||||
)
|
|
||||||
|
|
||||||
PatrolRoute[#PatrolRoute+1] = ToWP
|
PatrolRoute[#PatrolRoute+1] = ToWP
|
||||||
|
|
||||||
local Tasks = {}
|
local Tasks = {}
|
||||||
Tasks[#Tasks+1] = AIPatrol:TaskFunction( "AI_AIR_PATROL.___PatrolRoute", self )
|
Tasks[#Tasks+1] = AIPatrol:TaskFunction("AI_AIR_PATROL.___PatrolRoute", self)
|
||||||
PatrolRoute[#PatrolRoute].task = AIPatrol:TaskCombo( Tasks )
|
PatrolRoute[#PatrolRoute].task = AIPatrol:TaskCombo( Tasks )
|
||||||
|
|
||||||
end
|
end
|
||||||
@@ -401,7 +390,7 @@ end
|
|||||||
function AI_AIR_PATROL.Resume( AIPatrol, Fsm )
|
function AI_AIR_PATROL.Resume( AIPatrol, Fsm )
|
||||||
|
|
||||||
AIPatrol:F( { "AI_AIR_PATROL.Resume:", AIPatrol:GetName() } )
|
AIPatrol:F( { "AI_AIR_PATROL.Resume:", AIPatrol:GetName() } )
|
||||||
if AIPatrol:IsAlive() then
|
if AIPatrol and AIPatrol:IsAlive() then
|
||||||
Fsm:__Reset( Fsm.TaskDelay )
|
Fsm:__Reset( Fsm.TaskDelay )
|
||||||
Fsm:__PatrolRoute( Fsm.TaskDelay )
|
Fsm:__PatrolRoute( Fsm.TaskDelay )
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
--- **AI** -- Models squadrons for airplanes and helicopters.
|
--- **AI** - Models squadrons for airplanes and helicopters.
|
||||||
--
|
--
|
||||||
-- This is a class used in the @{AI_Air_Dispatcher} and derived dispatcher classes.
|
-- This is a class used in the @{AI_Air_Dispatcher} and derived dispatcher classes.
|
||||||
--
|
--
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- @module AI.AI_Air_Squadron
|
-- @module AI.AI_Air_Squadron
|
||||||
-- @image AI_Air_To_Air_Engage.JPG
|
-- @image MOOSE.JPG
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -196,8 +196,12 @@ function AI_BALANCER:onenterDestroying( SetGroup, From, Event, To, ClientName, A
|
|||||||
SetGroup:Flush( self )
|
SetGroup:Flush( self )
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #AI_BALANCER self
|
--- RTB
|
||||||
|
-- @param #AI_BALANCER self
|
||||||
-- @param Core.Set#SET_GROUP SetGroup
|
-- @param Core.Set#SET_GROUP SetGroup
|
||||||
|
-- @param #string From
|
||||||
|
-- @param #string Event
|
||||||
|
-- @param #string To
|
||||||
-- @param Wrapper.Group#GROUP AIGroup
|
-- @param Wrapper.Group#GROUP AIGroup
|
||||||
function AI_BALANCER:onenterReturning( SetGroup, From, Event, To, AIGroup )
|
function AI_BALANCER:onenterReturning( SetGroup, From, Event, To, AIGroup )
|
||||||
|
|
||||||
@@ -213,10 +217,13 @@ function AI_BALANCER:onenterReturning( SetGroup, From, Event, To, AIGroup )
|
|||||||
local PointVec2 = POINT_VEC2:New( AIGroup:GetVec2().x, AIGroup:GetVec2().y )
|
local PointVec2 = POINT_VEC2:New( AIGroup:GetVec2().x, AIGroup:GetVec2().y )
|
||||||
local ClosestAirbase = self.ReturnAirbaseSet:FindNearestAirbaseFromPointVec2( PointVec2 )
|
local ClosestAirbase = self.ReturnAirbaseSet:FindNearestAirbaseFromPointVec2( PointVec2 )
|
||||||
self:T( ClosestAirbase.AirbaseName )
|
self:T( ClosestAirbase.AirbaseName )
|
||||||
|
--[[
|
||||||
AIGroup:MessageToRed( "Returning to " .. ClosestAirbase:GetName().. " ...", 30 )
|
AIGroup:MessageToRed( "Returning to " .. ClosestAirbase:GetName().. " ...", 30 )
|
||||||
local RTBRoute = AIGroup:RouteReturnToAirbase( ClosestAirbase )
|
local RTBRoute = AIGroup:RouteReturnToAirbase( ClosestAirbase )
|
||||||
AIGroupTemplate.route = RTBRoute
|
AIGroupTemplate.route = RTBRoute
|
||||||
AIGroup:Respawn( AIGroupTemplate )
|
AIGroup:Respawn( AIGroupTemplate )
|
||||||
|
]]
|
||||||
|
AIGroup:RouteRTB(ClosestAirbase)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -421,7 +421,7 @@ end
|
|||||||
-- @param #string To The To State string.
|
-- @param #string To The To State string.
|
||||||
function AI_CAP_ZONE:onafterEngage( Controllable, From, Event, To )
|
function AI_CAP_ZONE:onafterEngage( Controllable, From, Event, To )
|
||||||
|
|
||||||
if Controllable:IsAlive() then
|
if Controllable and Controllable:IsAlive() then
|
||||||
|
|
||||||
local EngageRoute = {}
|
local EngageRoute = {}
|
||||||
|
|
||||||
|
|||||||
@@ -142,6 +142,17 @@ function AI_CARGO:New( Carrier, CargoSet )
|
|||||||
-- @param #string Event
|
-- @param #string Event
|
||||||
-- @param #string To
|
-- @param #string To
|
||||||
|
|
||||||
|
--- On after Deployed event.
|
||||||
|
-- @function [parent=#AI_CARGO] OnAfterDeployed
|
||||||
|
-- @param #AI_CARGO self
|
||||||
|
-- @param Wrapper.Group#GROUP Carrier
|
||||||
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To To state.
|
||||||
|
-- @param Core.Zone#ZONE DeployZone The zone wherein the cargo is deployed. This can be any zone type, like a ZONE, ZONE_GROUP, ZONE_AIRBASE.
|
||||||
|
-- @param #boolean Defend Defend for APCs.
|
||||||
|
|
||||||
|
|
||||||
for _, CarrierUnit in pairs( Carrier:GetUnits() ) do
|
for _, CarrierUnit in pairs( Carrier:GetUnits() ) do
|
||||||
local CarrierUnit = CarrierUnit -- Wrapper.Unit#UNIT
|
local CarrierUnit = CarrierUnit -- Wrapper.Unit#UNIT
|
||||||
CarrierUnit:SetCargoBayWeightLimit()
|
CarrierUnit:SetCargoBayWeightLimit()
|
||||||
@@ -256,9 +267,10 @@ function AI_CARGO:onbeforeLoad( Carrier, From, Event, To, PickupZone )
|
|||||||
self:F( { "In radius", CarrierUnit:GetName() } )
|
self:F( { "In radius", CarrierUnit:GetName() } )
|
||||||
|
|
||||||
local CargoWeight = Cargo:GetWeight()
|
local CargoWeight = Cargo:GetWeight()
|
||||||
|
local CarrierSpace=Carrier_Weight[CarrierUnit]
|
||||||
|
|
||||||
-- Only when there is space within the bay to load the next cargo item!
|
-- Only when there is space within the bay to load the next cargo item!
|
||||||
if Carrier_Weight[CarrierUnit] > CargoWeight then --and CargoBayFreeVolume > CargoVolume then
|
if CarrierSpace > CargoWeight then
|
||||||
Carrier:RouteStop()
|
Carrier:RouteStop()
|
||||||
--Cargo:Ungroup()
|
--Cargo:Ungroup()
|
||||||
Cargo:__Board( -LoadDelay, CarrierUnit )
|
Cargo:__Board( -LoadDelay, CarrierUnit )
|
||||||
@@ -275,6 +287,8 @@ function AI_CARGO:onbeforeLoad( Carrier, From, Event, To, PickupZone )
|
|||||||
|
|
||||||
-- Ok, we loaded a cargo, now we can stop the loop.
|
-- Ok, we loaded a cargo, now we can stop the loop.
|
||||||
break
|
break
|
||||||
|
else
|
||||||
|
self:T(string.format("WARNING: Cargo too heavy for carrier %s. Cargo=%.1f > %.1f free space", tostring(CarrierUnit:GetName()), CargoWeight, CarrierSpace))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -554,6 +568,7 @@ end
|
|||||||
-- @param #string Event Event.
|
-- @param #string Event Event.
|
||||||
-- @param #string To To state.
|
-- @param #string To To state.
|
||||||
-- @param Core.Zone#ZONE DeployZone The zone wherein the cargo is deployed. This can be any zone type, like a ZONE, ZONE_GROUP, ZONE_AIRBASE.
|
-- @param Core.Zone#ZONE DeployZone The zone wherein the cargo is deployed. This can be any zone type, like a ZONE, ZONE_GROUP, ZONE_AIRBASE.
|
||||||
|
-- @param #boolean Defend Defend for APCs.
|
||||||
function AI_CARGO:onafterDeployed( Carrier, From, Event, To, DeployZone, Defend )
|
function AI_CARGO:onafterDeployed( Carrier, From, Event, To, DeployZone, Defend )
|
||||||
self:F( { Carrier, From, Event, To, DeployZone = DeployZone, Defend = Defend } )
|
self:F( { Carrier, From, Event, To, DeployZone = DeployZone, Defend = Defend } )
|
||||||
|
|
||||||
|
|||||||
@@ -76,25 +76,31 @@ function AI_CARGO_AIRPLANE:New( Airplane, CargoSet )
|
|||||||
--- Pickup Handler OnAfter for AI_CARGO_AIRPLANE
|
--- Pickup Handler OnAfter for AI_CARGO_AIRPLANE
|
||||||
-- @function [parent=#AI_CARGO_AIRPLANE] OnAfterPickup
|
-- @function [parent=#AI_CARGO_AIRPLANE] OnAfterPickup
|
||||||
-- @param #AI_CARGO_AIRPLANE self
|
-- @param #AI_CARGO_AIRPLANE self
|
||||||
-- @param Wrapper.Group#GROUP Airplane Cargo plane.
|
-- @param Wrapper.Group#GROUP Airplane Cargo transport plane.
|
||||||
-- @param #string From
|
-- @param #string From From state.
|
||||||
-- @param #string Event
|
-- @param #string Event Event.
|
||||||
-- @param #string To
|
-- @param #string To To state.
|
||||||
-- @param Wrapper.Airbase#AIRBASE Airbase Airbase where troops are picked up.
|
-- @param Core.Point#COORDINATE Coordinate The coordinate where to pickup stuff.
|
||||||
-- @param #number Speed in km/h for travelling to pickup base.
|
-- @param #number Speed Speed in km/h for travelling to pickup base.
|
||||||
|
-- @param #number Height Height in meters to move to the pickup coordinate.
|
||||||
|
-- @param Core.Zone#ZONE_AIRBASE PickupZone The airbase zone where the cargo will be picked up.
|
||||||
|
|
||||||
--- Pickup Trigger for AI_CARGO_AIRPLANE
|
--- Pickup Trigger for AI_CARGO_AIRPLANE
|
||||||
-- @function [parent=#AI_CARGO_AIRPLANE] Pickup
|
-- @function [parent=#AI_CARGO_AIRPLANE] Pickup
|
||||||
-- @param #AI_CARGO_AIRPLANE self
|
-- @param #AI_CARGO_AIRPLANE self
|
||||||
-- @param Wrapper.Airbase#AIRBASE Airbase Airbase where troops are picked up.
|
-- @param Core.Point#COORDINATE Coordinate The coordinate where to pickup stuff.
|
||||||
-- @param #number Speed in km/h for travelling to pickup base.
|
-- @param #number Speed Speed in km/h for travelling to pickup base.
|
||||||
|
-- @param #number Height Height in meters to move to the pickup coordinate.
|
||||||
|
-- @param Core.Zone#ZONE_AIRBASE PickupZone The airbase zone where the cargo will be picked up.
|
||||||
|
|
||||||
--- Pickup Asynchronous Trigger for AI_CARGO_AIRPLANE
|
--- Pickup Asynchronous Trigger for AI_CARGO_AIRPLANE
|
||||||
-- @function [parent=#AI_CARGO_AIRPLANE] __Pickup
|
-- @function [parent=#AI_CARGO_AIRPLANE] __Pickup
|
||||||
-- @param #AI_CARGO_AIRPLANE self
|
-- @param #AI_CARGO_AIRPLANE self
|
||||||
-- @param #number Delay Delay in seconds.
|
-- @param #number Delay Delay in seconds.
|
||||||
-- @param Wrapper.Airbase#AIRBASE Airbase Airbase where troops are picked up.
|
-- @param Core.Point#COORDINATE Coordinate The coordinate where to pickup stuff.
|
||||||
-- @param #number Speed in km/h for travelling to pickup base.
|
-- @param #number Speed Speed in km/h for travelling to pickup base.
|
||||||
|
-- @param #number Height Height in meters to move to the pickup coordinate.
|
||||||
|
-- @param Core.Zone#ZONE_AIRBASE PickupZone The airbase zone where the cargo will be picked up.
|
||||||
|
|
||||||
--- Deploy Handler OnBefore for AI_CARGO_AIRPLANE
|
--- Deploy Handler OnBefore for AI_CARGO_AIRPLANE
|
||||||
-- @function [parent=#AI_CARGO_AIRPLANE] OnBeforeDeploy
|
-- @function [parent=#AI_CARGO_AIRPLANE] OnBeforeDeploy
|
||||||
@@ -111,24 +117,30 @@ function AI_CARGO_AIRPLANE:New( Airplane, CargoSet )
|
|||||||
-- @function [parent=#AI_CARGO_AIRPLANE] OnAfterDeploy
|
-- @function [parent=#AI_CARGO_AIRPLANE] OnAfterDeploy
|
||||||
-- @param #AI_CARGO_AIRPLANE self
|
-- @param #AI_CARGO_AIRPLANE self
|
||||||
-- @param Wrapper.Group#GROUP Airplane Cargo plane.
|
-- @param Wrapper.Group#GROUP Airplane Cargo plane.
|
||||||
-- @param #string From
|
-- @param #string From From state.
|
||||||
-- @param #string Event
|
-- @param #string Event Event.
|
||||||
-- @param #string To
|
-- @param #string To To state.
|
||||||
-- @param Wrapper.Airbase#AIRBASE Airbase Destination airbase where troops are deployed.
|
-- @param Core.Point#COORDINATE Coordinate Coordinate where to deploy stuff.
|
||||||
-- @param #number Speed Speed in km/h for travelling to deploy base.
|
-- @param #number Speed Speed in km/h for travelling to the deploy base.
|
||||||
|
-- @param #number Height Height in meters to move to the home coordinate.
|
||||||
|
-- @param Core.Zone#ZONE_AIRBASE DeployZone The airbase zone where the cargo will be deployed.
|
||||||
|
|
||||||
--- Deploy Trigger for AI_CARGO_AIRPLANE
|
--- Deploy Trigger for AI_CARGO_AIRPLANE
|
||||||
-- @function [parent=#AI_CARGO_AIRPLANE] Deploy
|
-- @function [parent=#AI_CARGO_AIRPLANE] Deploy
|
||||||
-- @param #AI_CARGO_AIRPLANE self
|
-- @param #AI_CARGO_AIRPLANE self
|
||||||
-- @param Wrapper.Airbase#AIRBASE Airbase Destination airbase where troops are deployed.
|
-- @param Core.Point#COORDINATE Coordinate Coordinate where to deploy stuff.
|
||||||
-- @param #number Speed Speed in km/h for travelling to deploy base.
|
-- @param #number Speed Speed in km/h for travelling to the deploy base.
|
||||||
|
-- @param #number Height Height in meters to move to the home coordinate.
|
||||||
|
-- @param Core.Zone#ZONE_AIRBASE DeployZone The airbase zone where the cargo will be deployed.
|
||||||
|
|
||||||
--- Deploy Asynchronous Trigger for AI_CARGO_AIRPLANE
|
--- Deploy Asynchronous Trigger for AI_CARGO_AIRPLANE
|
||||||
-- @function [parent=#AI_CARGO_AIRPLANE] __Deploy
|
-- @function [parent=#AI_CARGO_AIRPLANE] __Deploy
|
||||||
-- @param #AI_CARGO_AIRPLANE self
|
-- @param #AI_CARGO_AIRPLANE self
|
||||||
-- @param #number Delay Delay in seconds.
|
-- @param #number Delay Delay in seconds.
|
||||||
-- @param Wrapper.Airbase#AIRBASE Airbase Destination airbase where troops are deployed.
|
-- @param Core.Point#COORDINATE Coordinate Coordinate where to deploy stuff.
|
||||||
-- @param #number Speed Speed in km/h for travelling to deploy base.
|
-- @param #number Speed Speed in km/h for travelling to the deploy base.
|
||||||
|
-- @param #number Height Height in meters to move to the home coordinate.
|
||||||
|
-- @param Core.Zone#ZONE_AIRBASE DeployZone The airbase zone where the cargo will be deployed.
|
||||||
|
|
||||||
--- On after Loaded event, i.e. triggered when the cargo is inside the carrier.
|
--- On after Loaded event, i.e. triggered when the cargo is inside the carrier.
|
||||||
-- @function [parent=#AI_CARGO_AIRPLANE] OnAfterLoaded
|
-- @function [parent=#AI_CARGO_AIRPLANE] OnAfterLoaded
|
||||||
@@ -138,6 +150,16 @@ function AI_CARGO_AIRPLANE:New( Airplane, CargoSet )
|
|||||||
-- @param Event
|
-- @param Event
|
||||||
-- @param To
|
-- @param To
|
||||||
|
|
||||||
|
|
||||||
|
--- On after Deployed event.
|
||||||
|
-- @function [parent=#AI_CARGO_AIRPLANE] OnAfterDeployed
|
||||||
|
-- @param #AI_CARGO_AIRPLANE self
|
||||||
|
-- @param Wrapper.Group#GROUP Airplane Cargo plane.
|
||||||
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To To state.
|
||||||
|
-- @param Core.Zone#ZONE DeployZone The zone wherein the cargo is deployed.
|
||||||
|
|
||||||
-- Set carrier.
|
-- Set carrier.
|
||||||
self:SetCarrier( Airplane )
|
self:SetCarrier( Airplane )
|
||||||
|
|
||||||
@@ -259,15 +281,17 @@ end
|
|||||||
-- @param #string From From state.
|
-- @param #string From From state.
|
||||||
-- @param #string Event Event.
|
-- @param #string Event Event.
|
||||||
-- @param #string To To state.
|
-- @param #string To To state.
|
||||||
-- @param Core.Point#COORDINATE Coordinate
|
-- @param Core.Point#COORDINATE Coordinate The coordinate where to pickup stuff.
|
||||||
-- @param #number Speed in km/h for travelling to pickup base.
|
-- @param #number Speed Speed in km/h for travelling to pickup base.
|
||||||
-- @param #number Height Height in meters to move to the pickup coordinate.
|
-- @param #number Height Height in meters to move to the pickup coordinate.
|
||||||
-- @param Core.Zone#ZONE_AIRBASE (optional) PickupZone The zone where the cargo will be picked up.
|
-- @param Core.Zone#ZONE_AIRBASE PickupZone The airbase zone where the cargo will be picked up.
|
||||||
function AI_CARGO_AIRPLANE:onafterPickup( Airplane, From, Event, To, Coordinate, Speed, Height, PickupZone )
|
function AI_CARGO_AIRPLANE:onafterPickup( Airplane, From, Event, To, Coordinate, Speed, Height, PickupZone )
|
||||||
|
|
||||||
if Airplane and Airplane:IsAlive() then
|
if Airplane and Airplane:IsAlive() then
|
||||||
|
|
||||||
self.PickupZone = PickupZone
|
local airbasepickup=Coordinate:GetClosestAirbase()
|
||||||
|
|
||||||
|
self.PickupZone = PickupZone or ZONE_AIRBASE:New(airbasepickup:GetName())
|
||||||
|
|
||||||
-- Get closest airbase of current position.
|
-- Get closest airbase of current position.
|
||||||
local ClosestAirbase, DistToAirbase=Airplane:GetCoordinate():GetClosestAirbase()
|
local ClosestAirbase, DistToAirbase=Airplane:GetCoordinate():GetClosestAirbase()
|
||||||
@@ -280,11 +304,10 @@ function AI_CARGO_AIRPLANE:onafterPickup( Airplane, From, Event, To, Coordinate,
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Set pickup airbase.
|
-- Set pickup airbase.
|
||||||
local Airbase = PickupZone:GetAirbase()
|
local Airbase = self.PickupZone:GetAirbase()
|
||||||
|
|
||||||
-- Distance from closest to pickup airbase ==> we need to know if we are already at the pickup airbase.
|
-- Distance from closest to pickup airbase ==> we need to know if we are already at the pickup airbase.
|
||||||
local Dist = Airbase:GetCoordinate():Get2DDistance(ClosestAirbase:GetCoordinate())
|
local Dist = Airbase:GetCoordinate():Get2DDistance(ClosestAirbase:GetCoordinate())
|
||||||
--env.info("Distance closest to pickup airbase = "..Dist)
|
|
||||||
|
|
||||||
if Airplane:InAir() or Dist>500 then
|
if Airplane:InAir() or Dist>500 then
|
||||||
|
|
||||||
@@ -305,7 +328,7 @@ function AI_CARGO_AIRPLANE:onafterPickup( Airplane, From, Event, To, Coordinate,
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
self:GetParent( self, AI_CARGO_AIRPLANE ).onafterPickup( self, Airplane, From, Event, To, Coordinate, Speed, Height, PickupZone )
|
self:GetParent( self, AI_CARGO_AIRPLANE ).onafterPickup( self, Airplane, From, Event, To, Coordinate, Speed, Height, self.PickupZone )
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -318,15 +341,19 @@ end
|
|||||||
-- @param #string From From state.
|
-- @param #string From From state.
|
||||||
-- @param #string Event Event.
|
-- @param #string Event Event.
|
||||||
-- @param #string To To state.
|
-- @param #string To To state.
|
||||||
-- @param Core.Point#COORDINATE Coordinate
|
-- @param Core.Point#COORDINATE Coordinate Coordinate where to deploy stuff.
|
||||||
-- @param #number Speed in km/h for travelling to pickup base.
|
-- @param #number Speed Speed in km/h for travelling to the deploy base.
|
||||||
-- @param #number Height Height in meters to move to the home coordinate.
|
-- @param #number Height Height in meters to move to the home coordinate.
|
||||||
-- @param Core.Zone#ZONE_AIRBASE DeployZone The zone where the cargo will be deployed.
|
-- @param Core.Zone#ZONE_AIRBASE DeployZone The airbase zone where the cargo will be deployed.
|
||||||
function AI_CARGO_AIRPLANE:onafterDeploy( Airplane, From, Event, To, Coordinate, Speed, Height, DeployZone )
|
function AI_CARGO_AIRPLANE:onafterDeploy( Airplane, From, Event, To, Coordinate, Speed, Height, DeployZone )
|
||||||
|
|
||||||
if Airplane and Airplane:IsAlive()~=nil then
|
if Airplane and Airplane:IsAlive()~=nil then
|
||||||
|
|
||||||
local Airbase = DeployZone:GetAirbase()
|
local Airbase = Coordinate:GetClosestAirbase()
|
||||||
|
|
||||||
|
if DeployZone then
|
||||||
|
Airbase=DeployZone:GetAirbase()
|
||||||
|
end
|
||||||
|
|
||||||
-- Activate uncontrolled airplane.
|
-- Activate uncontrolled airplane.
|
||||||
if Airplane:IsAlive()==false then
|
if Airplane:IsAlive()==false then
|
||||||
@@ -354,6 +381,7 @@ end
|
|||||||
-- @param #string From From state.
|
-- @param #string From From state.
|
||||||
-- @param #string Event Event.
|
-- @param #string Event Event.
|
||||||
-- @param #string To To state.
|
-- @param #string To To state.
|
||||||
|
-- @param Core.Zone#ZONE_AIRBASE DeployZone The airbase zone where the cargo will be deployed.
|
||||||
function AI_CARGO_AIRPLANE:onafterUnload( Airplane, From, Event, To, DeployZone )
|
function AI_CARGO_AIRPLANE:onafterUnload( Airplane, From, Event, To, DeployZone )
|
||||||
|
|
||||||
local UnboardInterval = 10
|
local UnboardInterval = 10
|
||||||
|
|||||||
@@ -1151,6 +1151,10 @@ function AI_CARGO_DISPATCHER:onafterMonitor()
|
|||||||
self.PickupCargo[Carrier] = CargoCoordinate
|
self.PickupCargo[Carrier] = CargoCoordinate
|
||||||
PickupCargo = Cargo
|
PickupCargo = Cargo
|
||||||
break
|
break
|
||||||
|
else
|
||||||
|
local text=string.format("WARNING: Cargo %s is too heavy to be loaded into transport. Cargo weight %.1f > %.1f load capacity of carrier %s.",
|
||||||
|
tostring(Cargo:GetName()), Cargo:GetWeight(), LargestLoadCapacity, tostring(Carrier:GetName()))
|
||||||
|
self:I(text)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
--- **AI** -- (R2.5) - Models the automatic assignment of AI escorts to player flights.
|
--- **AI** - Models the automatic assignment of AI escorts to player flights.
|
||||||
--
|
--
|
||||||
-- ## Features:
|
-- ## Features:
|
||||||
-- --
|
-- --
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- @module AI.AI_Escort_Dispatcher
|
-- @module AI.AI_Escort_Dispatcher
|
||||||
-- @image AI_Escort_Dispatcher.JPG
|
-- @image MOOSE.JPG
|
||||||
|
|
||||||
|
|
||||||
--- @type AI_ESCORT_DISPATCHER
|
--- @type AI_ESCORT_DISPATCHER
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
--- **AI** -- (R2.5) - Models the assignment of AI escorts to player flights upon request using the radio menu.
|
--- **AI** - Models the assignment of AI escorts to player flights upon request using the radio menu.
|
||||||
--
|
--
|
||||||
-- ## Features:
|
-- ## Features:
|
||||||
--
|
--
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- @module AI.AI_ESCORT_DISPATCHER_REQUEST
|
-- @module AI.AI_ESCORT_DISPATCHER_REQUEST
|
||||||
-- @image AI_ESCORT_DISPATCHER_REQUEST.JPG
|
-- @image MOOSE.JPG
|
||||||
|
|
||||||
|
|
||||||
--- @type AI_ESCORT_DISPATCHER_REQUEST
|
--- @type AI_ESCORT_DISPATCHER_REQUEST
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ AI_FORMATION.__Enum.ReportType = {
|
|||||||
--- MENUPARAM type
|
--- MENUPARAM type
|
||||||
-- @type MENUPARAM
|
-- @type MENUPARAM
|
||||||
-- @field #AI_FORMATION ParamSelf
|
-- @field #AI_FORMATION ParamSelf
|
||||||
-- @field #Distance ParamDistance
|
-- @field #number ParamDistance
|
||||||
-- @field #function ParamFunction
|
-- @field #function ParamFunction
|
||||||
-- @field #string ParamMessage
|
-- @field #string ParamMessage
|
||||||
|
|
||||||
@@ -207,9 +207,9 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
|
|||||||
-- @param #string To
|
-- @param #string To
|
||||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||||
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
||||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||||
-- @param #nubmer YSpace The space between groups on the Y-axis in meters for each sequent group.
|
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
|
||||||
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group.
|
-- @param #number ZStart The start position on the Z-axis in meters for the first group.
|
||||||
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
||||||
-- @return #boolean
|
-- @return #boolean
|
||||||
|
|
||||||
@@ -222,9 +222,9 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
|
|||||||
-- @param #string To
|
-- @param #string To
|
||||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||||
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
||||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||||
-- @param #nubmer YSpace The space between groups on the Y-axis in meters for each sequent group.
|
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
|
||||||
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group.
|
-- @param #number ZStart The start position on the Z-axis in meters for the first group.
|
||||||
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
||||||
|
|
||||||
--- FormationLine Trigger for AI_FORMATION
|
--- FormationLine Trigger for AI_FORMATION
|
||||||
@@ -232,9 +232,9 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
|
|||||||
-- @param #AI_FORMATION self
|
-- @param #AI_FORMATION self
|
||||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||||
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
||||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||||
-- @param #nubmer YSpace The space between groups on the Y-axis in meters for each sequent group.
|
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
|
||||||
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group.
|
-- @param #number ZStart The start position on the Z-axis in meters for the first group.
|
||||||
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
||||||
|
|
||||||
--- FormationLine Asynchronous Trigger for AI_FORMATION
|
--- FormationLine Asynchronous Trigger for AI_FORMATION
|
||||||
@@ -243,9 +243,9 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
|
|||||||
-- @param #number Delay
|
-- @param #number Delay
|
||||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||||
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
||||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||||
-- @param #nubmer YSpace The space between groups on the Y-axis in meters for each sequent group.
|
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
|
||||||
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group.
|
-- @param #number ZStart The start position on the Z-axis in meters for the first group.
|
||||||
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
||||||
|
|
||||||
self:AddTransition( "*", "FormationTrail", "*" )
|
self:AddTransition( "*", "FormationTrail", "*" )
|
||||||
@@ -257,7 +257,7 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
|
|||||||
-- @param #string To
|
-- @param #string To
|
||||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||||
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
||||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||||
-- @return #boolean
|
-- @return #boolean
|
||||||
|
|
||||||
--- FormationTrail Handler OnAfter for AI_FORMATION
|
--- FormationTrail Handler OnAfter for AI_FORMATION
|
||||||
@@ -268,14 +268,14 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
|
|||||||
-- @param #string To
|
-- @param #string To
|
||||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||||
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
||||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||||
|
|
||||||
--- FormationTrail Trigger for AI_FORMATION
|
--- FormationTrail Trigger for AI_FORMATION
|
||||||
-- @function [parent=#AI_FORMATION] FormationTrail
|
-- @function [parent=#AI_FORMATION] FormationTrail
|
||||||
-- @param #AI_FORMATION self
|
-- @param #AI_FORMATION self
|
||||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||||
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
||||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||||
|
|
||||||
--- FormationTrail Asynchronous Trigger for AI_FORMATION
|
--- FormationTrail Asynchronous Trigger for AI_FORMATION
|
||||||
-- @function [parent=#AI_FORMATION] __FormationTrail
|
-- @function [parent=#AI_FORMATION] __FormationTrail
|
||||||
@@ -283,7 +283,7 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
|
|||||||
-- @param #number Delay
|
-- @param #number Delay
|
||||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||||
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
||||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||||
|
|
||||||
self:AddTransition( "*", "FormationStack", "*" )
|
self:AddTransition( "*", "FormationStack", "*" )
|
||||||
--- FormationStack Handler OnBefore for AI_FORMATION
|
--- FormationStack Handler OnBefore for AI_FORMATION
|
||||||
@@ -294,7 +294,7 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
|
|||||||
-- @param #string To
|
-- @param #string To
|
||||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||||
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
||||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||||
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
|
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
|
||||||
-- @return #boolean
|
-- @return #boolean
|
||||||
|
|
||||||
@@ -306,7 +306,7 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
|
|||||||
-- @param #string To
|
-- @param #string To
|
||||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||||
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
||||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||||
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
|
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
|
||||||
|
|
||||||
--- FormationStack Trigger for AI_FORMATION
|
--- FormationStack Trigger for AI_FORMATION
|
||||||
@@ -314,7 +314,7 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
|
|||||||
-- @param #AI_FORMATION self
|
-- @param #AI_FORMATION self
|
||||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||||
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
||||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||||
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
|
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
|
||||||
|
|
||||||
--- FormationStack Asynchronous Trigger for AI_FORMATION
|
--- FormationStack Asynchronous Trigger for AI_FORMATION
|
||||||
@@ -323,7 +323,7 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
|
|||||||
-- @param #number Delay
|
-- @param #number Delay
|
||||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||||
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
||||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||||
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
|
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
|
||||||
|
|
||||||
self:AddTransition( "*", "FormationLeftLine", "*" )
|
self:AddTransition( "*", "FormationLeftLine", "*" )
|
||||||
@@ -335,8 +335,8 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
|
|||||||
-- @param #string Event
|
-- @param #string Event
|
||||||
-- @param #string To
|
-- @param #string To
|
||||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||||
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group.
|
-- @param #number ZStart The start position on the Z-axis in meters for the first group.
|
||||||
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
||||||
-- @return #boolean
|
-- @return #boolean
|
||||||
|
|
||||||
@@ -348,16 +348,16 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
|
|||||||
-- @param #string Event
|
-- @param #string Event
|
||||||
-- @param #string To
|
-- @param #string To
|
||||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||||
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group.
|
-- @param #number ZStart The start position on the Z-axis in meters for the first group.
|
||||||
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
||||||
|
|
||||||
--- FormationLeftLine Trigger for AI_FORMATION
|
--- FormationLeftLine Trigger for AI_FORMATION
|
||||||
-- @function [parent=#AI_FORMATION] FormationLeftLine
|
-- @function [parent=#AI_FORMATION] FormationLeftLine
|
||||||
-- @param #AI_FORMATION self
|
-- @param #AI_FORMATION self
|
||||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||||
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group.
|
-- @param #number ZStart The start position on the Z-axis in meters for the first group.
|
||||||
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
||||||
|
|
||||||
--- FormationLeftLine Asynchronous Trigger for AI_FORMATION
|
--- FormationLeftLine Asynchronous Trigger for AI_FORMATION
|
||||||
@@ -365,8 +365,8 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
|
|||||||
-- @param #AI_FORMATION self
|
-- @param #AI_FORMATION self
|
||||||
-- @param #number Delay
|
-- @param #number Delay
|
||||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||||
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group.
|
-- @param #number ZStart The start position on the Z-axis in meters for the first group.
|
||||||
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
||||||
|
|
||||||
self:AddTransition( "*", "FormationRightLine", "*" )
|
self:AddTransition( "*", "FormationRightLine", "*" )
|
||||||
@@ -378,8 +378,8 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
|
|||||||
-- @param #string Event
|
-- @param #string Event
|
||||||
-- @param #string To
|
-- @param #string To
|
||||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||||
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group.
|
-- @param #number ZStart The start position on the Z-axis in meters for the first group.
|
||||||
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
||||||
-- @return #boolean
|
-- @return #boolean
|
||||||
|
|
||||||
@@ -391,16 +391,16 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
|
|||||||
-- @param #string Event
|
-- @param #string Event
|
||||||
-- @param #string To
|
-- @param #string To
|
||||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||||
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group.
|
-- @param #number ZStart The start position on the Z-axis in meters for the first group.
|
||||||
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
||||||
|
|
||||||
--- FormationRightLine Trigger for AI_FORMATION
|
--- FormationRightLine Trigger for AI_FORMATION
|
||||||
-- @function [parent=#AI_FORMATION] FormationRightLine
|
-- @function [parent=#AI_FORMATION] FormationRightLine
|
||||||
-- @param #AI_FORMATION self
|
-- @param #AI_FORMATION self
|
||||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||||
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group.
|
-- @param #number ZStart The start position on the Z-axis in meters for the first group.
|
||||||
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
||||||
|
|
||||||
--- FormationRightLine Asynchronous Trigger for AI_FORMATION
|
--- FormationRightLine Asynchronous Trigger for AI_FORMATION
|
||||||
@@ -408,8 +408,8 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
|
|||||||
-- @param #AI_FORMATION self
|
-- @param #AI_FORMATION self
|
||||||
-- @param #number Delay
|
-- @param #number Delay
|
||||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||||
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group.
|
-- @param #number ZStart The start position on the Z-axis in meters for the first group.
|
||||||
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
||||||
|
|
||||||
self:AddTransition( "*", "FormationLeftWing", "*" )
|
self:AddTransition( "*", "FormationLeftWing", "*" )
|
||||||
@@ -422,8 +422,8 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
|
|||||||
-- @param #string To
|
-- @param #string To
|
||||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||||
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
||||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||||
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group.
|
-- @param #number ZStart The start position on the Z-axis in meters for the first group.
|
||||||
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
||||||
-- @return #boolean
|
-- @return #boolean
|
||||||
|
|
||||||
@@ -436,8 +436,8 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
|
|||||||
-- @param #string To
|
-- @param #string To
|
||||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||||
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
||||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||||
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group.
|
-- @param #number ZStart The start position on the Z-axis in meters for the first group.
|
||||||
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
||||||
|
|
||||||
--- FormationLeftWing Trigger for AI_FORMATION
|
--- FormationLeftWing Trigger for AI_FORMATION
|
||||||
@@ -445,8 +445,8 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
|
|||||||
-- @param #AI_FORMATION self
|
-- @param #AI_FORMATION self
|
||||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||||
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
||||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||||
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group.
|
-- @param #number ZStart The start position on the Z-axis in meters for the first group.
|
||||||
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
||||||
|
|
||||||
--- FormationLeftWing Asynchronous Trigger for AI_FORMATION
|
--- FormationLeftWing Asynchronous Trigger for AI_FORMATION
|
||||||
@@ -455,8 +455,8 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
|
|||||||
-- @param #number Delay
|
-- @param #number Delay
|
||||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||||
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
||||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||||
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group.
|
-- @param #number ZStart The start position on the Z-axis in meters for the first group.
|
||||||
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
||||||
|
|
||||||
self:AddTransition( "*", "FormationRightWing", "*" )
|
self:AddTransition( "*", "FormationRightWing", "*" )
|
||||||
@@ -469,8 +469,8 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
|
|||||||
-- @param #string To
|
-- @param #string To
|
||||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||||
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
||||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||||
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group.
|
-- @param #number ZStart The start position on the Z-axis in meters for the first group.
|
||||||
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
||||||
-- @return #boolean
|
-- @return #boolean
|
||||||
|
|
||||||
@@ -483,8 +483,8 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
|
|||||||
-- @param #string To
|
-- @param #string To
|
||||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||||
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
||||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||||
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group.
|
-- @param #number ZStart The start position on the Z-axis in meters for the first group.
|
||||||
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
||||||
|
|
||||||
--- FormationRightWing Trigger for AI_FORMATION
|
--- FormationRightWing Trigger for AI_FORMATION
|
||||||
@@ -492,8 +492,8 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
|
|||||||
-- @param #AI_FORMATION self
|
-- @param #AI_FORMATION self
|
||||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||||
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
||||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||||
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group.
|
-- @param #number ZStart The start position on the Z-axis in meters for the first group.
|
||||||
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
||||||
|
|
||||||
--- FormationRightWing Asynchronous Trigger for AI_FORMATION
|
--- FormationRightWing Asynchronous Trigger for AI_FORMATION
|
||||||
@@ -502,8 +502,8 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
|
|||||||
-- @param #number Delay
|
-- @param #number Delay
|
||||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||||
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
||||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||||
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group.
|
-- @param #number ZStart The start position on the Z-axis in meters for the first group.
|
||||||
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
||||||
|
|
||||||
self:AddTransition( "*", "FormationCenterWing", "*" )
|
self:AddTransition( "*", "FormationCenterWing", "*" )
|
||||||
@@ -516,9 +516,9 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
|
|||||||
-- @param #string To
|
-- @param #string To
|
||||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||||
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
||||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||||
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
|
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
|
||||||
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group.
|
-- @param #number ZStart The start position on the Z-axis in meters for the first group.
|
||||||
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
||||||
-- @return #boolean
|
-- @return #boolean
|
||||||
|
|
||||||
@@ -531,9 +531,9 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
|
|||||||
-- @param #string To
|
-- @param #string To
|
||||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||||
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
||||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||||
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
|
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
|
||||||
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group.
|
-- @param #number ZStart The start position on the Z-axis in meters for the first group.
|
||||||
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
||||||
|
|
||||||
--- FormationCenterWing Trigger for AI_FORMATION
|
--- FormationCenterWing Trigger for AI_FORMATION
|
||||||
@@ -541,9 +541,9 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
|
|||||||
-- @param #AI_FORMATION self
|
-- @param #AI_FORMATION self
|
||||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||||
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
||||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||||
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
|
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
|
||||||
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group.
|
-- @param #number ZStart The start position on the Z-axis in meters for the first group.
|
||||||
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
||||||
|
|
||||||
--- FormationCenterWing Asynchronous Trigger for AI_FORMATION
|
--- FormationCenterWing Asynchronous Trigger for AI_FORMATION
|
||||||
@@ -552,9 +552,9 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
|
|||||||
-- @param #number Delay
|
-- @param #number Delay
|
||||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||||
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
||||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||||
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
|
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
|
||||||
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group.
|
-- @param #number ZStart The start position on the Z-axis in meters for the first group.
|
||||||
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
||||||
|
|
||||||
self:AddTransition( "*", "FormationVic", "*" )
|
self:AddTransition( "*", "FormationVic", "*" )
|
||||||
@@ -566,9 +566,9 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
|
|||||||
-- @param #string To
|
-- @param #string To
|
||||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||||
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
||||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||||
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
|
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
|
||||||
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group.
|
-- @param #number ZStart The start position on the Z-axis in meters for the first group.
|
||||||
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
||||||
-- @return #boolean
|
-- @return #boolean
|
||||||
|
|
||||||
@@ -580,9 +580,9 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
|
|||||||
-- @param #string To
|
-- @param #string To
|
||||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||||
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
||||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||||
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
|
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
|
||||||
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group.
|
-- @param #number ZStart The start position on the Z-axis in meters for the first group.
|
||||||
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
||||||
|
|
||||||
--- FormationVic Trigger for AI_FORMATION
|
--- FormationVic Trigger for AI_FORMATION
|
||||||
@@ -590,9 +590,9 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
|
|||||||
-- @param #AI_FORMATION self
|
-- @param #AI_FORMATION self
|
||||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||||
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
||||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||||
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
|
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
|
||||||
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group.
|
-- @param #number ZStart The start position on the Z-axis in meters for the first group.
|
||||||
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
||||||
|
|
||||||
--- FormationVic Asynchronous Trigger for AI_FORMATION
|
--- FormationVic Asynchronous Trigger for AI_FORMATION
|
||||||
@@ -601,9 +601,9 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
|
|||||||
-- @param #number Delay
|
-- @param #number Delay
|
||||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||||
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
||||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||||
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
|
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
|
||||||
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group.
|
-- @param #number ZStart The start position on the Z-axis in meters for the first group.
|
||||||
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
||||||
|
|
||||||
self:AddTransition( "*", "FormationBox", "*" )
|
self:AddTransition( "*", "FormationBox", "*" )
|
||||||
@@ -615,9 +615,9 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
|
|||||||
-- @param #string To
|
-- @param #string To
|
||||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||||
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
||||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||||
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
|
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
|
||||||
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group.
|
-- @param #number ZStart The start position on the Z-axis in meters for the first group.
|
||||||
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
||||||
-- @param #number ZLevels The amount of levels on the Z-axis.
|
-- @param #number ZLevels The amount of levels on the Z-axis.
|
||||||
-- @return #boolean
|
-- @return #boolean
|
||||||
@@ -630,9 +630,9 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
|
|||||||
-- @param #string To
|
-- @param #string To
|
||||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||||
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
||||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||||
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
|
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
|
||||||
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group.
|
-- @param #number ZStart The start position on the Z-axis in meters for the first group.
|
||||||
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
||||||
-- @param #number ZLevels The amount of levels on the Z-axis.
|
-- @param #number ZLevels The amount of levels on the Z-axis.
|
||||||
|
|
||||||
@@ -641,9 +641,9 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
|
|||||||
-- @param #AI_FORMATION self
|
-- @param #AI_FORMATION self
|
||||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||||
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
||||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||||
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
|
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
|
||||||
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group.
|
-- @param #number ZStart The start position on the Z-axis in meters for the first group.
|
||||||
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
||||||
-- @param #number ZLevels The amount of levels on the Z-axis.
|
-- @param #number ZLevels The amount of levels on the Z-axis.
|
||||||
|
|
||||||
@@ -653,9 +653,9 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
|
|||||||
-- @param #number Delay
|
-- @param #number Delay
|
||||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||||
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
||||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||||
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
|
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
|
||||||
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group.
|
-- @param #number ZStart The start position on the Z-axis in meters for the first group.
|
||||||
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
||||||
-- @param #number ZLevels The amount of levels on the Z-axis.
|
-- @param #number ZLevels The amount of levels on the Z-axis.
|
||||||
|
|
||||||
@@ -704,9 +704,9 @@ end
|
|||||||
-- @param #string To
|
-- @param #string To
|
||||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||||
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
||||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||||
-- @param #nubmer YSpace The space between groups on the Y-axis in meters for each sequent group.
|
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
|
||||||
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group.
|
-- @param #number ZStart The start position on the Z-axis in meters for the first group.
|
||||||
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
||||||
-- @return #AI_FORMATION
|
-- @return #AI_FORMATION
|
||||||
function AI_FORMATION:onafterFormationLine( FollowGroupSet, From , Event , To, XStart, XSpace, YStart, YSpace, ZStart, ZSpace, Formation ) --R2.1
|
function AI_FORMATION:onafterFormationLine( FollowGroupSet, From , Event , To, XStart, XSpace, YStart, YSpace, ZStart, ZSpace, Formation ) --R2.1
|
||||||
@@ -751,7 +751,7 @@ end
|
|||||||
-- @param #string To
|
-- @param #string To
|
||||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||||
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
||||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||||
-- @return #AI_FORMATION
|
-- @return #AI_FORMATION
|
||||||
function AI_FORMATION:onafterFormationTrail( FollowGroupSet, From , Event , To, XStart, XSpace, YStart ) --R2.1
|
function AI_FORMATION:onafterFormationTrail( FollowGroupSet, From , Event , To, XStart, XSpace, YStart ) --R2.1
|
||||||
|
|
||||||
@@ -769,7 +769,7 @@ end
|
|||||||
-- @param #string To
|
-- @param #string To
|
||||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||||
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
||||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||||
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
|
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
|
||||||
-- @return #AI_FORMATION
|
-- @return #AI_FORMATION
|
||||||
function AI_FORMATION:onafterFormationStack( FollowGroupSet, From , Event , To, XStart, XSpace, YStart, YSpace ) --R2.1
|
function AI_FORMATION:onafterFormationStack( FollowGroupSet, From , Event , To, XStart, XSpace, YStart, YSpace ) --R2.1
|
||||||
@@ -789,8 +789,8 @@ end
|
|||||||
-- @param #string Event
|
-- @param #string Event
|
||||||
-- @param #string To
|
-- @param #string To
|
||||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||||
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group.
|
-- @param #number ZStart The start position on the Z-axis in meters for the first group.
|
||||||
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
||||||
-- @return #AI_FORMATION
|
-- @return #AI_FORMATION
|
||||||
function AI_FORMATION:onafterFormationLeftLine( FollowGroupSet, From , Event , To, XStart, YStart, ZStart, ZSpace ) --R2.1
|
function AI_FORMATION:onafterFormationLeftLine( FollowGroupSet, From , Event , To, XStart, YStart, ZStart, ZSpace ) --R2.1
|
||||||
@@ -808,8 +808,8 @@ end
|
|||||||
-- @param #string Event
|
-- @param #string Event
|
||||||
-- @param #string To
|
-- @param #string To
|
||||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||||
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group.
|
-- @param #number ZStart The start position on the Z-axis in meters for the first group.
|
||||||
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
||||||
-- @return #AI_FORMATION
|
-- @return #AI_FORMATION
|
||||||
function AI_FORMATION:onafterFormationRightLine( FollowGroupSet, From , Event , To, XStart, YStart, ZStart, ZSpace ) --R2.1
|
function AI_FORMATION:onafterFormationRightLine( FollowGroupSet, From , Event , To, XStart, YStart, ZStart, ZSpace ) --R2.1
|
||||||
@@ -828,8 +828,8 @@ end
|
|||||||
-- @param #string To
|
-- @param #string To
|
||||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||||
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
||||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||||
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group.
|
-- @param #number ZStart The start position on the Z-axis in meters for the first group.
|
||||||
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
||||||
function AI_FORMATION:onafterFormationLeftWing( FollowGroupSet, From , Event , To, XStart, XSpace, YStart, ZStart, ZSpace ) --R2.1
|
function AI_FORMATION:onafterFormationLeftWing( FollowGroupSet, From , Event , To, XStart, XSpace, YStart, ZStart, ZSpace ) --R2.1
|
||||||
|
|
||||||
@@ -848,8 +848,8 @@ end
|
|||||||
-- @param #string To
|
-- @param #string To
|
||||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||||
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
||||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||||
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group.
|
-- @param #number ZStart The start position on the Z-axis in meters for the first group.
|
||||||
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
||||||
function AI_FORMATION:onafterFormationRightWing( FollowGroupSet, From , Event , To, XStart, XSpace, YStart, ZStart, ZSpace ) --R2.1
|
function AI_FORMATION:onafterFormationRightWing( FollowGroupSet, From , Event , To, XStart, XSpace, YStart, ZStart, ZSpace ) --R2.1
|
||||||
|
|
||||||
@@ -867,9 +867,9 @@ end
|
|||||||
-- @param #string To
|
-- @param #string To
|
||||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||||
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
||||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||||
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
|
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
|
||||||
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group.
|
-- @param #number ZStart The start position on the Z-axis in meters for the first group.
|
||||||
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
||||||
function AI_FORMATION:onafterFormationCenterWing( FollowGroupSet, From , Event , To, XStart, XSpace, YStart, YSpace, ZStart, ZSpace ) --R2.1
|
function AI_FORMATION:onafterFormationCenterWing( FollowGroupSet, From , Event , To, XStart, XSpace, YStart, YSpace, ZStart, ZSpace ) --R2.1
|
||||||
|
|
||||||
@@ -905,9 +905,9 @@ end
|
|||||||
-- @param #string To
|
-- @param #string To
|
||||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||||
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
||||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||||
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
|
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
|
||||||
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group.
|
-- @param #number ZStart The start position on the Z-axis in meters for the first group.
|
||||||
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
||||||
-- @return #AI_FORMATION
|
-- @return #AI_FORMATION
|
||||||
function AI_FORMATION:onafterFormationVic( FollowGroupSet, From , Event , To, XStart, XSpace, YStart, YSpace, ZStart, ZSpace ) --R2.1
|
function AI_FORMATION:onafterFormationVic( FollowGroupSet, From , Event , To, XStart, XSpace, YStart, YSpace, ZStart, ZSpace ) --R2.1
|
||||||
@@ -924,9 +924,9 @@ end
|
|||||||
-- @param #string To
|
-- @param #string To
|
||||||
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
-- @param #number XStart The start position on the X-axis in meters for the first group.
|
||||||
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group.
|
||||||
-- @param #nubmer YStart The start position on the Y-axis in meters for the first group.
|
-- @param #number YStart The start position on the Y-axis in meters for the first group.
|
||||||
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
|
-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group.
|
||||||
-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group.
|
-- @param #number ZStart The start position on the Z-axis in meters for the first group.
|
||||||
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group.
|
||||||
-- @param #number ZLevels The amount of levels on the Z-axis.
|
-- @param #number ZLevels The amount of levels on the Z-axis.
|
||||||
-- @return #AI_FORMATION
|
-- @return #AI_FORMATION
|
||||||
@@ -1065,7 +1065,7 @@ end
|
|||||||
-- @param Core.Set#SET_GROUP FollowGroupSet The following set of groups.
|
-- @param Core.Set#SET_GROUP FollowGroupSet The following set of groups.
|
||||||
-- @param #string From From state.
|
-- @param #string From From state.
|
||||||
-- @param #string Event Event.
|
-- @param #string Event Event.
|
||||||
-- @pram #string To The to state.
|
-- @param #string To The to state.
|
||||||
function AI_FORMATION:onafterStop(FollowGroupSet, From, Event, To) --R2.1
|
function AI_FORMATION:onafterStop(FollowGroupSet, From, Event, To) --R2.1
|
||||||
self:E("Stopping formation.")
|
self:E("Stopping formation.")
|
||||||
end
|
end
|
||||||
@@ -1075,7 +1075,7 @@ end
|
|||||||
-- @param Core.Set#SET_GROUP FollowGroupSet The following set of groups.
|
-- @param Core.Set#SET_GROUP FollowGroupSet The following set of groups.
|
||||||
-- @param #string From From state.
|
-- @param #string From From state.
|
||||||
-- @param #string Event Event.
|
-- @param #string Event Event.
|
||||||
-- @pram #string To The to state.
|
-- @param #string To The to state.
|
||||||
function AI_FORMATION:onbeforeFollow( FollowGroupSet, From, Event, To ) --R2.1
|
function AI_FORMATION:onbeforeFollow( FollowGroupSet, From, Event, To ) --R2.1
|
||||||
if From=="Stopped" then
|
if From=="Stopped" then
|
||||||
return false -- Deny transition.
|
return false -- Deny transition.
|
||||||
@@ -1083,7 +1083,12 @@ function AI_FORMATION:onbeforeFollow( FollowGroupSet, From, Event, To ) --R2.1
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #AI_FORMATION self
|
--- Enter following state.
|
||||||
|
-- @param #AI_FORMATION self
|
||||||
|
-- @param Core.Set#SET_GROUP FollowGroupSet The following set of groups.
|
||||||
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To The to state.
|
||||||
function AI_FORMATION:onenterFollowing( FollowGroupSet ) --R2.1
|
function AI_FORMATION:onenterFollowing( FollowGroupSet ) --R2.1
|
||||||
|
|
||||||
if self.FollowUnit:IsAlive() then
|
if self.FollowUnit:IsAlive() then
|
||||||
@@ -1093,153 +1098,184 @@ function AI_FORMATION:onenterFollowing( FollowGroupSet ) --R2.1
|
|||||||
local CT1, CT2, CV1, CV2
|
local CT1, CT2, CV1, CV2
|
||||||
CT1 = ClientUnit:GetState( self, "CT1" )
|
CT1 = ClientUnit:GetState( self, "CT1" )
|
||||||
|
|
||||||
|
local CuVec3=ClientUnit:GetVec3()
|
||||||
|
|
||||||
if CT1 == nil or CT1 == 0 then
|
if CT1 == nil or CT1 == 0 then
|
||||||
ClientUnit:SetState( self, "CV1", ClientUnit:GetPointVec3() )
|
ClientUnit:SetState( self, "CV1", CuVec3)
|
||||||
ClientUnit:SetState( self, "CT1", timer.getTime() )
|
ClientUnit:SetState( self, "CT1", timer.getTime() )
|
||||||
else
|
else
|
||||||
CT1 = ClientUnit:GetState( self, "CT1" )
|
CT1 = ClientUnit:GetState( self, "CT1" )
|
||||||
CT2 = timer.getTime()
|
CT2 = timer.getTime()
|
||||||
CV1 = ClientUnit:GetState( self, "CV1" )
|
CV1 = ClientUnit:GetState( self, "CV1" )
|
||||||
CV2 = ClientUnit:GetPointVec3()
|
CV2 = CuVec3
|
||||||
|
|
||||||
ClientUnit:SetState( self, "CT1", CT2 )
|
ClientUnit:SetState( self, "CT1", CT2 )
|
||||||
ClientUnit:SetState( self, "CV1", CV2 )
|
ClientUnit:SetState( self, "CV1", CV2 )
|
||||||
end
|
end
|
||||||
|
|
||||||
FollowGroupSet:ForEachGroupAlive(
|
--FollowGroupSet:ForEachGroupAlive( bla, self, ClientUnit, CT1, CV1, CT2, CV2)
|
||||||
--- @param Wrapper.Group#GROUP FollowGroup
|
|
||||||
-- @param Wrapper.Unit#UNIT ClientUnit
|
|
||||||
function( FollowGroup, Formation, ClientUnit, CT1, CV1, CT2, CV2 )
|
|
||||||
|
|
||||||
if FollowGroup:GetState( FollowGroup, "Mode" ) == self.__Enum.Mode.Formation then
|
for _,_group in pairs(FollowGroupSet:GetSet()) do
|
||||||
|
local group=_group --Wrapper.Group#GROUP
|
||||||
self:T({Mode=FollowGroup:GetState( FollowGroup, "Mode" )})
|
if group and group:IsAlive() then
|
||||||
|
self:FollowMe(group, ClientUnit, CT1, CV1, CT2, CV2)
|
||||||
FollowGroup:OptionROTEvadeFire()
|
end
|
||||||
FollowGroup:OptionROEReturnFire()
|
end
|
||||||
|
|
||||||
local GroupUnit = FollowGroup:GetUnit( 1 )
|
|
||||||
local FollowFormation = FollowGroup:GetState( self, "FormationVec3" )
|
|
||||||
if FollowFormation then
|
|
||||||
local FollowDistance = FollowFormation.x
|
|
||||||
|
|
||||||
local GT1 = GroupUnit:GetState( self, "GT1" )
|
|
||||||
|
|
||||||
if CT1 == nil or CT1 == 0 or GT1 == nil or GT1 == 0 then
|
|
||||||
GroupUnit:SetState( self, "GV1", GroupUnit:GetPointVec3() )
|
|
||||||
GroupUnit:SetState( self, "GT1", timer.getTime() )
|
|
||||||
else
|
|
||||||
local CD = ( ( CV2.x - CV1.x )^2 + ( CV2.y - CV1.y )^2 + ( CV2.z - CV1.z )^2 ) ^ 0.5
|
|
||||||
local CT = CT2 - CT1
|
|
||||||
|
|
||||||
local CS = ( 3600 / CT ) * ( CD / 1000 ) / 3.6
|
|
||||||
|
|
||||||
local CDv = { x = CV2.x - CV1.x, y = CV2.y - CV1.y, z = CV2.z - CV1.z }
|
|
||||||
local Ca = math.atan2( CDv.x, CDv.z )
|
|
||||||
|
|
||||||
local GT1 = GroupUnit:GetState( self, "GT1" )
|
|
||||||
local GT2 = timer.getTime()
|
|
||||||
local GV1 = GroupUnit:GetState( self, "GV1" )
|
|
||||||
local GV2 = GroupUnit:GetPointVec3()
|
|
||||||
GV2:AddX( math.random( -Formation.FlightRandomization / 2, Formation.FlightRandomization / 2 ) )
|
|
||||||
GV2:AddY( math.random( -Formation.FlightRandomization / 2, Formation.FlightRandomization / 2 ) )
|
|
||||||
GV2:AddZ( math.random( -Formation.FlightRandomization / 2, Formation.FlightRandomization / 2 ) )
|
|
||||||
GroupUnit:SetState( self, "GT1", GT2 )
|
|
||||||
GroupUnit:SetState( self, "GV1", GV2 )
|
|
||||||
|
|
||||||
|
|
||||||
local GD = ( ( GV2.x - GV1.x )^2 + ( GV2.y - GV1.y )^2 + ( GV2.z - GV1.z )^2 ) ^ 0.5
|
|
||||||
local GT = GT2 - GT1
|
|
||||||
|
|
||||||
|
|
||||||
-- Calculate the distance
|
|
||||||
local GDv = { x = GV2.x - CV1.x, y = GV2.y - CV1.y, z = GV2.z - CV1.z }
|
|
||||||
local Alpha_T = math.atan2( GDv.x, GDv.z ) - math.atan2( CDv.x, CDv.z )
|
|
||||||
local Alpha_R = ( Alpha_T < 0 ) and Alpha_T + 2 * math.pi or Alpha_T
|
|
||||||
local Position = math.cos( Alpha_R )
|
|
||||||
local GD = ( ( GDv.x )^2 + ( GDv.z )^2 ) ^ 0.5
|
|
||||||
local Distance = GD * Position + - CS * 0.5
|
|
||||||
|
|
||||||
-- Calculate the group direction vector
|
|
||||||
local GV = { x = GV2.x - CV2.x, y = GV2.y - CV2.y, z = GV2.z - CV2.z }
|
|
||||||
|
|
||||||
-- Calculate GH2, GH2 with the same height as CV2.
|
|
||||||
local GH2 = { x = GV2.x, y = CV2.y + FollowFormation.y, z = GV2.z }
|
|
||||||
|
|
||||||
-- Calculate the angle of GV to the orthonormal plane
|
|
||||||
local alpha = math.atan2( GV.x, GV.z )
|
|
||||||
|
|
||||||
local GVx = FollowFormation.z * math.cos( Ca ) + FollowFormation.x * math.sin( Ca )
|
|
||||||
local GVz = FollowFormation.x * math.cos( Ca ) - FollowFormation.z * math.sin( Ca )
|
|
||||||
|
|
||||||
|
|
||||||
-- Now we calculate the intersecting vector between the circle around CV2 with radius FollowDistance and GH2.
|
|
||||||
-- From the GeoGebra model: CVI = (x(CV2) + FollowDistance cos(alpha), y(GH2) + FollowDistance sin(alpha), z(CV2))
|
|
||||||
local Inclination = ( Distance + FollowFormation.x ) / 10
|
|
||||||
if Inclination < -30 then
|
|
||||||
Inclination = - 30
|
|
||||||
end
|
|
||||||
local CVI = { x = CV2.x + CS * 10 * math.sin(Ca),
|
|
||||||
y = GH2.y + Inclination, -- + FollowFormation.y,
|
|
||||||
y = GH2.y,
|
|
||||||
z = CV2.z + CS * 10 * math.cos(Ca),
|
|
||||||
}
|
|
||||||
|
|
||||||
-- Calculate the direction vector DV of the escort group. We use CVI as the base and CV2 as the direction.
|
|
||||||
local DV = { x = CV2.x - CVI.x, y = CV2.y - CVI.y, z = CV2.z - CVI.z }
|
|
||||||
|
|
||||||
-- We now calculate the unary direction vector DVu, so that we can multiply DVu with the speed, which is expressed in meters / s.
|
|
||||||
-- We need to calculate this vector to predict the point the escort group needs to fly to according its speed.
|
|
||||||
-- The distance of the destination point should be far enough not to have the aircraft starting to swipe left to right...
|
|
||||||
local DVu = { x = DV.x / FollowDistance, y = DV.y, z = DV.z / FollowDistance }
|
|
||||||
|
|
||||||
-- Now we can calculate the group destination vector GDV.
|
|
||||||
local GDV = { x = CVI.x, y = CVI.y, z = CVI.z }
|
|
||||||
|
|
||||||
local ADDx = FollowFormation.x * math.cos(alpha) - FollowFormation.z * math.sin(alpha)
|
|
||||||
local ADDz = FollowFormation.z * math.cos(alpha) + FollowFormation.x * math.sin(alpha)
|
|
||||||
|
|
||||||
local GDV_Formation = {
|
|
||||||
x = GDV.x - GVx,
|
|
||||||
y = GDV.y,
|
|
||||||
z = GDV.z - GVz
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.SmokeDirectionVector == true then
|
|
||||||
trigger.action.smoke( GDV, trigger.smokeColor.Green )
|
|
||||||
trigger.action.smoke( GDV_Formation, trigger.smokeColor.White )
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
local Time = 120
|
|
||||||
|
|
||||||
local Speed = - ( Distance + FollowFormation.x ) / Time
|
|
||||||
|
|
||||||
if Distance > -10000 then
|
|
||||||
Speed = - ( Distance + FollowFormation.x ) / 60
|
|
||||||
end
|
|
||||||
|
|
||||||
if Distance > -2500 then
|
|
||||||
Speed = - ( Distance + FollowFormation.x ) / 20
|
|
||||||
end
|
|
||||||
|
|
||||||
local GS = Speed + CS
|
|
||||||
|
|
||||||
self:F( { Distance = Distance, Speed = Speed, CS = CS, GS = GS } )
|
|
||||||
|
|
||||||
|
|
||||||
-- Now route the escort to the desired point with the desired speed.
|
|
||||||
FollowGroup:RouteToVec3( GDV_Formation, GS ) -- DCS models speed in Mps (Miles per second)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
self, ClientUnit, CT1, CV1, CT2, CV2
|
|
||||||
)
|
|
||||||
|
|
||||||
self:__Follow( -self.dtFollow )
|
self:__Follow( -self.dtFollow )
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Follow me.
|
||||||
|
-- @param #AI_FORMATION self
|
||||||
|
-- @param Wrapper.Group#GROUP FollowGroup Follow group.
|
||||||
|
-- @param Wrapper.Unit#UNIT ClientUnit Client Unit.
|
||||||
|
-- @param DCS#Time CT1 Time
|
||||||
|
-- @param DCS#Vec3 CV1 Vec3
|
||||||
|
-- @param DCS#Time CT2 Time
|
||||||
|
-- @param DCS#Vec3 CV2 Vec3
|
||||||
|
function AI_FORMATION:FollowMe(FollowGroup, ClientUnit, CT1, CV1, CT2, CV2)
|
||||||
|
|
||||||
|
if FollowGroup:GetState( FollowGroup, "Mode" ) == self.__Enum.Mode.Formation then
|
||||||
|
|
||||||
|
self:T({Mode=FollowGroup:GetState( FollowGroup, "Mode" )})
|
||||||
|
|
||||||
|
FollowGroup:OptionROTEvadeFire()
|
||||||
|
FollowGroup:OptionROEReturnFire()
|
||||||
|
|
||||||
|
local GroupUnit = FollowGroup:GetUnit( 1 )
|
||||||
|
|
||||||
|
local GuVec3=GroupUnit:GetVec3()
|
||||||
|
|
||||||
|
local FollowFormation = FollowGroup:GetState( self, "FormationVec3" )
|
||||||
|
|
||||||
|
if FollowFormation then
|
||||||
|
local FollowDistance = FollowFormation.x
|
||||||
|
|
||||||
|
local GT1 = GroupUnit:GetState( self, "GT1" )
|
||||||
|
|
||||||
|
if CT1 == nil or CT1 == 0 or GT1 == nil or GT1 == 0 then
|
||||||
|
GroupUnit:SetState( self, "GV1", GuVec3)
|
||||||
|
GroupUnit:SetState( self, "GT1", timer.getTime() )
|
||||||
|
else
|
||||||
|
local CD = ( ( CV2.x - CV1.x )^2 + ( CV2.y - CV1.y )^2 + ( CV2.z - CV1.z )^2 ) ^ 0.5
|
||||||
|
local CT = CT2 - CT1
|
||||||
|
|
||||||
|
local CS = ( 3600 / CT ) * ( CD / 1000 ) / 3.6
|
||||||
|
|
||||||
|
local CDv = { x = CV2.x - CV1.x, y = CV2.y - CV1.y, z = CV2.z - CV1.z }
|
||||||
|
local Ca = math.atan2( CDv.x, CDv.z )
|
||||||
|
|
||||||
|
local GT1 = GroupUnit:GetState( self, "GT1" )
|
||||||
|
local GT2 = timer.getTime()
|
||||||
|
|
||||||
|
local GV1 = GroupUnit:GetState( self, "GV1" )
|
||||||
|
local GV2 = GuVec3
|
||||||
|
|
||||||
|
--[[
|
||||||
|
GV2:AddX( math.random( -Formation.FlightRandomization / 2, Formation.FlightRandomization / 2 ) )
|
||||||
|
GV2:AddY( math.random( -Formation.FlightRandomization / 2, Formation.FlightRandomization / 2 ) )
|
||||||
|
GV2:AddZ( math.random( -Formation.FlightRandomization / 2, Formation.FlightRandomization / 2 ) )
|
||||||
|
]]
|
||||||
|
|
||||||
|
GV2.x=GV2.x+math.random( -self.FlightRandomization / 2, self.FlightRandomization / 2 )
|
||||||
|
GV2.y=GV2.y+math.random( -self.FlightRandomization / 2, self.FlightRandomization / 2 )
|
||||||
|
GV2.z=GV2.z+math.random( -self.FlightRandomization / 2, self.FlightRandomization / 2 )
|
||||||
|
|
||||||
|
|
||||||
|
GroupUnit:SetState( self, "GT1", GT2 )
|
||||||
|
GroupUnit:SetState( self, "GV1", GV2 )
|
||||||
|
|
||||||
|
|
||||||
|
local GD = ( ( GV2.x - GV1.x )^2 + ( GV2.y - GV1.y )^2 + ( GV2.z - GV1.z )^2 ) ^ 0.5
|
||||||
|
local GT = GT2 - GT1
|
||||||
|
|
||||||
|
|
||||||
|
-- Calculate the distance
|
||||||
|
local GDv = { x = GV2.x - CV1.x, y = GV2.y - CV1.y, z = GV2.z - CV1.z }
|
||||||
|
local Alpha_T = math.atan2( GDv.x, GDv.z ) - math.atan2( CDv.x, CDv.z )
|
||||||
|
local Alpha_R = ( Alpha_T < 0 ) and Alpha_T + 2 * math.pi or Alpha_T
|
||||||
|
local Position = math.cos( Alpha_R )
|
||||||
|
local GD = ( ( GDv.x )^2 + ( GDv.z )^2 ) ^ 0.5
|
||||||
|
local Distance = GD * Position + - CS * 0.5
|
||||||
|
|
||||||
|
-- Calculate the group direction vector
|
||||||
|
local GV = { x = GV2.x - CV2.x, y = GV2.y - CV2.y, z = GV2.z - CV2.z }
|
||||||
|
|
||||||
|
-- Calculate GH2, GH2 with the same height as CV2.
|
||||||
|
local GH2 = { x = GV2.x, y = CV2.y + FollowFormation.y, z = GV2.z }
|
||||||
|
|
||||||
|
-- Calculate the angle of GV to the orthonormal plane
|
||||||
|
local alpha = math.atan2( GV.x, GV.z )
|
||||||
|
|
||||||
|
local GVx = FollowFormation.z * math.cos( Ca ) + FollowFormation.x * math.sin( Ca )
|
||||||
|
local GVz = FollowFormation.x * math.cos( Ca ) - FollowFormation.z * math.sin( Ca )
|
||||||
|
|
||||||
|
|
||||||
|
-- Now we calculate the intersecting vector between the circle around CV2 with radius FollowDistance and GH2.
|
||||||
|
-- From the GeoGebra model: CVI = (x(CV2) + FollowDistance cos(alpha), y(GH2) + FollowDistance sin(alpha), z(CV2))
|
||||||
|
local Inclination = ( Distance + FollowFormation.x ) / 10
|
||||||
|
if Inclination < -30 then
|
||||||
|
Inclination = - 30
|
||||||
|
end
|
||||||
|
|
||||||
|
local CVI = {
|
||||||
|
x = CV2.x + CS * 10 * math.sin(Ca),
|
||||||
|
y = GH2.y + Inclination, -- + FollowFormation.y,
|
||||||
|
y = GH2.y,
|
||||||
|
z = CV2.z + CS * 10 * math.cos(Ca),
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Calculate the direction vector DV of the escort group. We use CVI as the base and CV2 as the direction.
|
||||||
|
local DV = { x = CV2.x - CVI.x, y = CV2.y - CVI.y, z = CV2.z - CVI.z }
|
||||||
|
|
||||||
|
-- We now calculate the unary direction vector DVu, so that we can multiply DVu with the speed, which is expressed in meters / s.
|
||||||
|
-- We need to calculate this vector to predict the point the escort group needs to fly to according its speed.
|
||||||
|
-- The distance of the destination point should be far enough not to have the aircraft starting to swipe left to right...
|
||||||
|
local DVu = { x = DV.x / FollowDistance, y = DV.y, z = DV.z / FollowDistance }
|
||||||
|
|
||||||
|
-- Now we can calculate the group destination vector GDV.
|
||||||
|
local GDV = { x = CVI.x, y = CVI.y, z = CVI.z }
|
||||||
|
|
||||||
|
local ADDx = FollowFormation.x * math.cos(alpha) - FollowFormation.z * math.sin(alpha)
|
||||||
|
local ADDz = FollowFormation.z * math.cos(alpha) + FollowFormation.x * math.sin(alpha)
|
||||||
|
|
||||||
|
local GDV_Formation = {
|
||||||
|
x = GDV.x - GVx,
|
||||||
|
y = GDV.y,
|
||||||
|
z = GDV.z - GVz
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Debug smoke.
|
||||||
|
if self.SmokeDirectionVector == true then
|
||||||
|
trigger.action.smoke( GDV, trigger.smokeColor.Green )
|
||||||
|
trigger.action.smoke( GDV_Formation, trigger.smokeColor.White )
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
local Time = 120
|
||||||
|
|
||||||
|
local Speed = - ( Distance + FollowFormation.x ) / Time
|
||||||
|
|
||||||
|
if Distance > -10000 then
|
||||||
|
Speed = - ( Distance + FollowFormation.x ) / 60
|
||||||
|
end
|
||||||
|
|
||||||
|
if Distance > -2500 then
|
||||||
|
Speed = - ( Distance + FollowFormation.x ) / 20
|
||||||
|
end
|
||||||
|
|
||||||
|
local GS = Speed + CS
|
||||||
|
|
||||||
|
--self:F( { Distance = Distance, Speed = Speed, CS = CS, GS = GS } )
|
||||||
|
|
||||||
|
-- Now route the escort to the desired point with the desired speed.
|
||||||
|
FollowGroup:RouteToVec3( GDV_Formation, GS ) -- DCS models speed in Mps (Miles per second)
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|||||||
@@ -178,8 +178,8 @@ function AI_PATROL_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltit
|
|||||||
self.PatrolMinSpeed = PatrolMinSpeed
|
self.PatrolMinSpeed = PatrolMinSpeed
|
||||||
self.PatrolMaxSpeed = PatrolMaxSpeed
|
self.PatrolMaxSpeed = PatrolMaxSpeed
|
||||||
|
|
||||||
-- defafult PatrolAltType to "RADIO" if not specified
|
-- defafult PatrolAltType to "BARO" if not specified
|
||||||
self.PatrolAltType = PatrolAltType or "RADIO"
|
self.PatrolAltType = PatrolAltType or "BARO"
|
||||||
|
|
||||||
self:SetRefreshTimeInterval( 30 )
|
self:SetRefreshTimeInterval( 30 )
|
||||||
|
|
||||||
@@ -636,7 +636,7 @@ function AI_PATROL_ZONE:onafterStart( Controllable, From, Event, To )
|
|||||||
|
|
||||||
self.Controllable:OnReSpawn(
|
self.Controllable:OnReSpawn(
|
||||||
function( PatrolGroup )
|
function( PatrolGroup )
|
||||||
self:E( "ReSpawn" )
|
self:T( "ReSpawn" )
|
||||||
self:__Reset( 1 )
|
self:__Reset( 1 )
|
||||||
self:__Route( 5 )
|
self:__Route( 5 )
|
||||||
end
|
end
|
||||||
@@ -667,21 +667,27 @@ function AI_PATROL_ZONE:onafterDetect( Controllable, From, Event, To )
|
|||||||
if TargetObject and TargetObject:isExist() and TargetObject.id_ < 50000000 then
|
if TargetObject and TargetObject:isExist() and TargetObject.id_ < 50000000 then
|
||||||
|
|
||||||
local TargetUnit = UNIT:Find( TargetObject )
|
local TargetUnit = UNIT:Find( TargetObject )
|
||||||
local TargetUnitName = TargetUnit:GetName()
|
|
||||||
|
|
||||||
if self.DetectionZone then
|
-- Check that target is alive due to issue https://github.com/FlightControl-Master/MOOSE/issues/1234
|
||||||
if TargetUnit:IsInZone( self.DetectionZone ) then
|
if TargetUnit and TargetUnit:IsAlive() then
|
||||||
self:T( {"Detected ", TargetUnit } )
|
|
||||||
|
local TargetUnitName = TargetUnit:GetName()
|
||||||
|
|
||||||
|
if self.DetectionZone then
|
||||||
|
if TargetUnit:IsInZone( self.DetectionZone ) then
|
||||||
|
self:T( {"Detected ", TargetUnit } )
|
||||||
|
if self.DetectedUnits[TargetUnit] == nil then
|
||||||
|
self.DetectedUnits[TargetUnit] = true
|
||||||
|
end
|
||||||
|
Detected = true
|
||||||
|
end
|
||||||
|
else
|
||||||
if self.DetectedUnits[TargetUnit] == nil then
|
if self.DetectedUnits[TargetUnit] == nil then
|
||||||
self.DetectedUnits[TargetUnit] = true
|
self.DetectedUnits[TargetUnit] = true
|
||||||
end
|
end
|
||||||
Detected = true
|
Detected = true
|
||||||
end
|
end
|
||||||
else
|
|
||||||
if self.DetectedUnits[TargetUnit] == nil then
|
|
||||||
self.DetectedUnits[TargetUnit] = true
|
|
||||||
end
|
|
||||||
Detected = true
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -735,7 +741,7 @@ function AI_PATROL_ZONE:onafterRoute( Controllable, From, Event, To )
|
|||||||
-- This will make the plane fly immediately to the patrol zone.
|
-- This will make the plane fly immediately to the patrol zone.
|
||||||
|
|
||||||
if self.Controllable:InAir() == false then
|
if self.Controllable:InAir() == false then
|
||||||
self:E( "Not in the air, finding route path within PatrolZone" )
|
self:T( "Not in the air, finding route path within PatrolZone" )
|
||||||
local CurrentVec2 = self.Controllable:GetVec2()
|
local CurrentVec2 = self.Controllable:GetVec2()
|
||||||
--TODO: Create GetAltitude function for GROUP, and delete GetUnit(1).
|
--TODO: Create GetAltitude function for GROUP, and delete GetUnit(1).
|
||||||
local CurrentAltitude = self.Controllable:GetUnit(1):GetAltitude()
|
local CurrentAltitude = self.Controllable:GetUnit(1):GetAltitude()
|
||||||
@@ -750,7 +756,7 @@ function AI_PATROL_ZONE:onafterRoute( Controllable, From, Event, To )
|
|||||||
)
|
)
|
||||||
PatrolRoute[#PatrolRoute+1] = CurrentRoutePoint
|
PatrolRoute[#PatrolRoute+1] = CurrentRoutePoint
|
||||||
else
|
else
|
||||||
self:E( "In the air, finding route path within PatrolZone" )
|
self:T( "In the air, finding route path within PatrolZone" )
|
||||||
local CurrentVec2 = self.Controllable:GetVec2()
|
local CurrentVec2 = self.Controllable:GetVec2()
|
||||||
--TODO: Create GetAltitude function for GROUP, and delete GetUnit(1).
|
--TODO: Create GetAltitude function for GROUP, and delete GetUnit(1).
|
||||||
local CurrentAltitude = self.Controllable:GetUnit(1):GetAltitude()
|
local CurrentAltitude = self.Controllable:GetUnit(1):GetAltitude()
|
||||||
|
|||||||
@@ -26,8 +26,6 @@
|
|||||||
-- @module Core.Base
|
-- @module Core.Base
|
||||||
-- @image Core_Base.JPG
|
-- @image Core_Base.JPG
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
local _TraceOnOff = true
|
local _TraceOnOff = true
|
||||||
local _TraceLevel = 1
|
local _TraceLevel = 1
|
||||||
local _TraceAll = false
|
local _TraceAll = false
|
||||||
@@ -256,6 +254,8 @@ end
|
|||||||
-- @param #BASE Parent is the Parent class that the Child inherits from.
|
-- @param #BASE Parent is the Parent class that the Child inherits from.
|
||||||
-- @return #BASE Child
|
-- @return #BASE Child
|
||||||
function BASE:Inherit( Child, Parent )
|
function BASE:Inherit( Child, Parent )
|
||||||
|
|
||||||
|
-- Create child.
|
||||||
local Child = routines.utils.deepCopy( Child )
|
local Child = routines.utils.deepCopy( Child )
|
||||||
|
|
||||||
if Child ~= nil then
|
if Child ~= nil then
|
||||||
@@ -271,6 +271,7 @@ function BASE:Inherit( Child, Parent )
|
|||||||
|
|
||||||
--Child:_SetDestructor()
|
--Child:_SetDestructor()
|
||||||
end
|
end
|
||||||
|
|
||||||
return Child
|
return Child
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -298,7 +299,8 @@ end
|
|||||||
--
|
--
|
||||||
--
|
--
|
||||||
-- @param #BASE self
|
-- @param #BASE self
|
||||||
-- @param #BASE Child is the Child class from which the Parent class needs to be retrieved.
|
-- @param #BASE Child This is the Child class from which the Parent class needs to be retrieved.
|
||||||
|
-- @param #BASE FromClass (Optional) The class from which to get the parent.
|
||||||
-- @return #BASE
|
-- @return #BASE
|
||||||
function BASE:GetParent( Child, FromClass )
|
function BASE:GetParent( Child, FromClass )
|
||||||
|
|
||||||
@@ -432,7 +434,7 @@ do -- Event Handling
|
|||||||
-- reflecting the order of the classes subscribed to the Event to be processed.
|
-- reflecting the order of the classes subscribed to the Event to be processed.
|
||||||
-- @param #BASE self
|
-- @param #BASE self
|
||||||
-- @param #number EventPriority The @{Event} processing Priority.
|
-- @param #number EventPriority The @{Event} processing Priority.
|
||||||
-- @return self
|
-- @return #BASE self
|
||||||
function BASE:SetEventPriority( EventPriority )
|
function BASE:SetEventPriority( EventPriority )
|
||||||
self._.EventPriority = EventPriority
|
self._.EventPriority = EventPriority
|
||||||
end
|
end
|
||||||
@@ -625,6 +627,55 @@ do -- Event Handling
|
|||||||
-- @param #BASE self
|
-- @param #BASE self
|
||||||
-- @param Core.Event#EVENTDATA EventData The EventData structure.
|
-- @param Core.Event#EVENTDATA EventData The EventData structure.
|
||||||
|
|
||||||
|
|
||||||
|
--- Unknown precisely what creates this event, likely tied into newer damage model. Will update this page when new information become available.
|
||||||
|
--
|
||||||
|
-- * initiator: The unit that had the failure.
|
||||||
|
--
|
||||||
|
-- @function [parent=#BASE] OnEventDetailedFailure
|
||||||
|
-- @param #BASE self
|
||||||
|
-- @param Core.Event#EVENTDATA EventData The EventData structure.
|
||||||
|
|
||||||
|
--- Occurs when any modification to the "Score" as seen on the debrief menu would occur.
|
||||||
|
-- There is no information on what values the score was changed to. Event is likely similar to player_comment in this regard.
|
||||||
|
-- @function [parent=#BASE] OnEventScore
|
||||||
|
-- @param #BASE self
|
||||||
|
-- @param Core.Event#EVENTDATA EventData The EventData structure.
|
||||||
|
|
||||||
|
--- Occurs on the death of a unit. Contains more and different information. Similar to unit_lost it will occur for aircraft before the aircraft crash event occurs.
|
||||||
|
--
|
||||||
|
-- * initiator: The unit that killed the target
|
||||||
|
-- * target: Target Object
|
||||||
|
-- * weapon: Weapon Object
|
||||||
|
--
|
||||||
|
-- @function [parent=#BASE] OnEventKill
|
||||||
|
-- @param #BASE self
|
||||||
|
-- @param Core.Event#EVENTDATA EventData The EventData structure.
|
||||||
|
|
||||||
|
--- Occurs when any modification to the "Score" as seen on the debrief menu would occur.
|
||||||
|
-- There is no information on what values the score was changed to. Event is likely similar to player_comment in this regard.
|
||||||
|
-- @function [parent=#BASE] OnEventScore
|
||||||
|
-- @param #BASE self
|
||||||
|
-- @param Core.Event#EVENTDATA EventData The EventData structure.
|
||||||
|
|
||||||
|
--- Occurs when the game thinks an object is destroyed.
|
||||||
|
--
|
||||||
|
-- * initiator: The unit that is was destroyed.
|
||||||
|
--
|
||||||
|
-- @function [parent=#BASE] OnEventUnitLost
|
||||||
|
-- @param #BASE self
|
||||||
|
-- @param Core.Event#EVENTDATA EventData The EventData structure.
|
||||||
|
|
||||||
|
--- Occurs shortly after the landing animation of an ejected pilot touching the ground and standing up. Event does not occur if the pilot lands in the water and sub combs to Davey Jones Locker.
|
||||||
|
--
|
||||||
|
-- * initiator: Static object representing the ejected pilot. Place : Aircraft that the pilot ejected from.
|
||||||
|
-- * place: may not return as a valid object if the aircraft has crashed into the ground and no longer exists.
|
||||||
|
-- * subplace: is always 0 for unknown reasons.
|
||||||
|
--
|
||||||
|
-- @function [parent=#BASE] OnEventLandingAfterEjection
|
||||||
|
-- @param #BASE self
|
||||||
|
-- @param Core.Event#EVENTDATA EventData The EventData structure.
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -765,8 +816,6 @@ do -- Scheduling
|
|||||||
self.Scheduler = SCHEDULER:New( self )
|
self.Scheduler = SCHEDULER:New( self )
|
||||||
end
|
end
|
||||||
|
|
||||||
self.Scheduler.SchedulerObject = self.Scheduler
|
|
||||||
|
|
||||||
local ScheduleID = _SCHEDULEDISPATCHER:AddSchedule(
|
local ScheduleID = _SCHEDULEDISPATCHER:AddSchedule(
|
||||||
self,
|
self,
|
||||||
SchedulerFunction,
|
SchedulerFunction,
|
||||||
@@ -804,9 +853,6 @@ do -- Scheduling
|
|||||||
self.Scheduler = SCHEDULER:New( self )
|
self.Scheduler = SCHEDULER:New( self )
|
||||||
end
|
end
|
||||||
|
|
||||||
self.Scheduler.SchedulerObject = self.Scheduler
|
|
||||||
--self.MasterObject = self
|
|
||||||
|
|
||||||
local ScheduleID = self.Scheduler:Schedule(
|
local ScheduleID = self.Scheduler:Schedule(
|
||||||
self,
|
self,
|
||||||
SchedulerFunction,
|
SchedulerFunction,
|
||||||
@@ -925,7 +971,13 @@ end
|
|||||||
-- -- Switch the tracing Off
|
-- -- Switch the tracing Off
|
||||||
-- BASE:TraceOnOff( false )
|
-- BASE:TraceOnOff( false )
|
||||||
function BASE:TraceOnOff( TraceOnOff )
|
function BASE:TraceOnOff( TraceOnOff )
|
||||||
_TraceOnOff = TraceOnOff or true
|
if TraceOnOff==false then
|
||||||
|
self:I( "Tracing in MOOSE is OFF" )
|
||||||
|
_TraceOnOff = false
|
||||||
|
else
|
||||||
|
self:I( "Tracing in MOOSE is ON" )
|
||||||
|
_TraceOnOff = true
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -954,7 +1006,11 @@ end
|
|||||||
-- @param #boolean TraceAll true = trace all methods in MOOSE.
|
-- @param #boolean TraceAll true = trace all methods in MOOSE.
|
||||||
function BASE:TraceAll( TraceAll )
|
function BASE:TraceAll( TraceAll )
|
||||||
|
|
||||||
_TraceAll = TraceAll or true
|
if TraceAll==false then
|
||||||
|
_TraceAll=false
|
||||||
|
else
|
||||||
|
_TraceAll = true
|
||||||
|
end
|
||||||
|
|
||||||
if _TraceAll then
|
if _TraceAll then
|
||||||
self:I( "Tracing all methods in MOOSE " )
|
self:I( "Tracing all methods in MOOSE " )
|
||||||
|
|||||||
@@ -82,6 +82,9 @@ DATABASE = {
|
|||||||
DESTROYS = {},
|
DESTROYS = {},
|
||||||
ZONES = {},
|
ZONES = {},
|
||||||
ZONES_GOAL = {},
|
ZONES_GOAL = {},
|
||||||
|
WAREHOUSES = {},
|
||||||
|
FLIGHTGROUPS = {},
|
||||||
|
FLIGHTCONTROLS = {},
|
||||||
}
|
}
|
||||||
|
|
||||||
local _DATABASECoalition =
|
local _DATABASECoalition =
|
||||||
@@ -187,7 +190,7 @@ end
|
|||||||
function DATABASE:AddUnit( DCSUnitName )
|
function DATABASE:AddUnit( DCSUnitName )
|
||||||
|
|
||||||
if not self.UNITS[DCSUnitName] then
|
if not self.UNITS[DCSUnitName] then
|
||||||
self:I( { "Add UNIT:", DCSUnitName } )
|
self:T( { "Add UNIT:", DCSUnitName } )
|
||||||
local UnitRegister = UNIT:Register( DCSUnitName )
|
local UnitRegister = UNIT:Register( DCSUnitName )
|
||||||
self.UNITS[DCSUnitName] = UNIT:Register( DCSUnitName )
|
self.UNITS[DCSUnitName] = UNIT:Register( DCSUnitName )
|
||||||
|
|
||||||
@@ -247,12 +250,15 @@ end
|
|||||||
|
|
||||||
--- Adds a Airbase based on the Airbase Name in the DATABASE.
|
--- Adds a Airbase based on the Airbase Name in the DATABASE.
|
||||||
-- @param #DATABASE self
|
-- @param #DATABASE self
|
||||||
-- @param #string AirbaseName The name of the airbase
|
-- @param #string AirbaseName The name of the airbase.
|
||||||
|
-- @return Wrapper.Airbase#AIRBASE Airbase object.
|
||||||
function DATABASE:AddAirbase( AirbaseName )
|
function DATABASE:AddAirbase( AirbaseName )
|
||||||
|
|
||||||
if not self.AIRBASES[AirbaseName] then
|
if not self.AIRBASES[AirbaseName] then
|
||||||
self.AIRBASES[AirbaseName] = AIRBASE:Register( AirbaseName )
|
self.AIRBASES[AirbaseName] = AIRBASE:Register( AirbaseName )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return self.AIRBASES[AirbaseName]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -509,7 +515,7 @@ end
|
|||||||
function DATABASE:AddGroup( GroupName )
|
function DATABASE:AddGroup( GroupName )
|
||||||
|
|
||||||
if not self.GROUPS[GroupName] then
|
if not self.GROUPS[GroupName] then
|
||||||
self:I( { "Add GROUP:", GroupName } )
|
self:T( { "Add GROUP:", GroupName } )
|
||||||
self.GROUPS[GroupName] = GROUP:Register( GroupName )
|
self.GROUPS[GroupName] = GROUP:Register( GroupName )
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -521,7 +527,7 @@ end
|
|||||||
function DATABASE:AddPlayer( UnitName, PlayerName )
|
function DATABASE:AddPlayer( UnitName, PlayerName )
|
||||||
|
|
||||||
if PlayerName then
|
if PlayerName then
|
||||||
self:I( { "Add player for unit:", UnitName, PlayerName } )
|
self:T( { "Add player for unit:", UnitName, PlayerName } )
|
||||||
self.PLAYERS[PlayerName] = UnitName
|
self.PLAYERS[PlayerName] = UnitName
|
||||||
self.PLAYERUNITS[PlayerName] = self:FindUnit( UnitName )
|
self.PLAYERUNITS[PlayerName] = self:FindUnit( UnitName )
|
||||||
self.PLAYERSJOINED[PlayerName] = PlayerName
|
self.PLAYERSJOINED[PlayerName] = PlayerName
|
||||||
@@ -533,7 +539,7 @@ end
|
|||||||
function DATABASE:DeletePlayer( UnitName, PlayerName )
|
function DATABASE:DeletePlayer( UnitName, PlayerName )
|
||||||
|
|
||||||
if PlayerName then
|
if PlayerName then
|
||||||
self:I( { "Clean player:", PlayerName } )
|
self:T( { "Clean player:", PlayerName } )
|
||||||
self.PLAYERS[PlayerName] = nil
|
self.PLAYERS[PlayerName] = nil
|
||||||
self.PLAYERUNITS[PlayerName] = nil
|
self.PLAYERUNITS[PlayerName] = nil
|
||||||
end
|
end
|
||||||
@@ -698,11 +704,11 @@ function DATABASE:_RegisterGroupTemplate( GroupTemplate, CoalitionSide, Category
|
|||||||
UnitNames[#UnitNames+1] = self.Templates.Units[UnitTemplate.name].UnitName
|
UnitNames[#UnitNames+1] = self.Templates.Units[UnitTemplate.name].UnitName
|
||||||
end
|
end
|
||||||
|
|
||||||
self:I( { Group = self.Templates.Groups[GroupTemplateName].GroupName,
|
self:T( { Group = self.Templates.Groups[GroupTemplateName].GroupName,
|
||||||
Coalition = self.Templates.Groups[GroupTemplateName].CoalitionID,
|
Coalition = self.Templates.Groups[GroupTemplateName].CoalitionID,
|
||||||
Category = self.Templates.Groups[GroupTemplateName].CategoryID,
|
Category = self.Templates.Groups[GroupTemplateName].CategoryID,
|
||||||
Country = self.Templates.Groups[GroupTemplateName].CountryID,
|
Country = self.Templates.Groups[GroupTemplateName].CountryID,
|
||||||
Units = UnitNames
|
Units = UnitNames
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
@@ -847,9 +853,9 @@ function DATABASE:_RegisterGroupsAndUnits()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
self:I("Groups:")
|
self:T("Groups:")
|
||||||
for GroupName, Group in pairs( self.GROUPS ) do
|
for GroupName, Group in pairs( self.GROUPS ) do
|
||||||
self:I( { "Group:", GroupName } )
|
self:T( { "Group:", GroupName } )
|
||||||
end
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
@@ -861,7 +867,7 @@ end
|
|||||||
function DATABASE:_RegisterClients()
|
function DATABASE:_RegisterClients()
|
||||||
|
|
||||||
for ClientName, ClientTemplate in pairs( self.Templates.ClientsByName ) do
|
for ClientName, ClientTemplate in pairs( self.Templates.ClientsByName ) do
|
||||||
self:I( { "Register Client:", ClientName } )
|
self:T( { "Register Client:", ClientName } )
|
||||||
self:AddClient( ClientName )
|
self:AddClient( ClientName )
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -879,7 +885,7 @@ function DATABASE:_RegisterStatics()
|
|||||||
if DCSStatic:isExist() then
|
if DCSStatic:isExist() then
|
||||||
local DCSStaticName = DCSStatic:getName()
|
local DCSStaticName = DCSStatic:getName()
|
||||||
|
|
||||||
self:I( { "Register Static:", DCSStaticName } )
|
self:T( { "Register Static:", DCSStaticName } )
|
||||||
self:AddStatic( DCSStaticName )
|
self:AddStatic( DCSStaticName )
|
||||||
else
|
else
|
||||||
self:E( { "Static does not exist: ", DCSStatic } )
|
self:E( { "Static does not exist: ", DCSStatic } )
|
||||||
@@ -890,18 +896,25 @@ function DATABASE:_RegisterStatics()
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #DATABASE self
|
--- Register all world airbases.
|
||||||
|
-- @param #DATABASE self
|
||||||
|
-- @return #DATABASE self
|
||||||
function DATABASE:_RegisterAirbases()
|
function DATABASE:_RegisterAirbases()
|
||||||
|
|
||||||
local CoalitionsData = { AirbasesRed = coalition.getAirbases( coalition.side.RED ), AirbasesBlue = coalition.getAirbases( coalition.side.BLUE ), AirbasesNeutral = coalition.getAirbases( coalition.side.NEUTRAL ) }
|
for DCSAirbaseId, DCSAirbase in pairs(world.getAirbases()) do
|
||||||
for CoalitionId, CoalitionData in pairs( CoalitionsData ) do
|
|
||||||
for DCSAirbaseId, DCSAirbase in pairs( CoalitionData ) do
|
|
||||||
|
|
||||||
local DCSAirbaseName = DCSAirbase:getName()
|
-- Get the airbase name.
|
||||||
|
local DCSAirbaseName = DCSAirbase:getName()
|
||||||
|
|
||||||
|
-- This gave the incorrect value to be inserted into the airdromeID for DCS 2.5.6. Is fixed now.
|
||||||
|
local airbaseID=DCSAirbase:getID()
|
||||||
|
|
||||||
|
-- Add and register airbase.
|
||||||
|
local airbase=self:AddAirbase( DCSAirbaseName )
|
||||||
|
|
||||||
|
-- Debug output.
|
||||||
|
self:I(string.format("Register Airbase: %s, getID=%d, GetID=%d (unique=%d)", DCSAirbaseName, DCSAirbase:getID(), airbase:GetID(), airbase:GetID(true)))
|
||||||
|
|
||||||
self:I( { "Register Airbase:", DCSAirbaseName, DCSAirbase:getID() } )
|
|
||||||
self:AddAirbase( DCSAirbaseName )
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
@@ -1236,8 +1249,44 @@ function DATABASE:SetPlayerSettings( PlayerName, Settings )
|
|||||||
self.PLAYERSETTINGS[PlayerName] = Settings
|
self.PLAYERSETTINGS[PlayerName] = Settings
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Add a flight group to the data base.
|
||||||
|
-- @param #DATABASE self
|
||||||
|
-- @param Ops.FlightGroup#FLIGHTGROUP flightgroup
|
||||||
|
function DATABASE:AddFlightGroup(flightgroup)
|
||||||
|
self:I({NewFlightGroup=flightgroup.groupname})
|
||||||
|
self.FLIGHTGROUPS[flightgroup.groupname]=flightgroup
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get a flight group from the data base.
|
||||||
|
-- @param #DATABASE self
|
||||||
|
-- @param #string groupname Group name of the flight group. Can also be passed as GROUP object.
|
||||||
|
-- @return Ops.FlightGroup#FLIGHTGROUP Flight group object.
|
||||||
|
function DATABASE:GetFlightGroup(groupname)
|
||||||
|
|
||||||
|
-- Get group and group name.
|
||||||
|
if type(groupname)=="string" then
|
||||||
|
else
|
||||||
|
groupname=groupname:GetName()
|
||||||
|
end
|
||||||
|
|
||||||
|
return self.FLIGHTGROUPS[groupname]
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Add a flight control to the data base.
|
||||||
|
-- @param #DATABASE self
|
||||||
|
-- @param Ops.FlightControl#FLIGHTCONTROL flightcontrol
|
||||||
|
function DATABASE:AddFlightControl(flightcontrol)
|
||||||
|
self:F2( { flightcontrol } )
|
||||||
|
self.FLIGHTCONTROLS[flightcontrol.airbasename]=flightcontrol
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get a flight control object from the data base.
|
||||||
|
-- @param #DATABASE self
|
||||||
|
-- @param #string airbasename Name of the associated airbase.
|
||||||
|
-- @return Ops.FlightControl#FLIGHTCONTROL The FLIGHTCONTROL object.s
|
||||||
|
function DATABASE:GetFlightControl(airbasename)
|
||||||
|
return self.FLIGHTCONTROLS[airbasename]
|
||||||
|
end
|
||||||
|
|
||||||
--- @param #DATABASE self
|
--- @param #DATABASE self
|
||||||
function DATABASE:_RegisterTemplates()
|
function DATABASE:_RegisterTemplates()
|
||||||
@@ -1420,8 +1469,3 @@ end
|
|||||||
self.DESTROYS[Event.IniUnitName] = true
|
self.DESTROYS[Event.IniUnitName] = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -221,9 +221,11 @@ EVENTS = {
|
|||||||
PlayerComment = world.event.S_EVENT_PLAYER_COMMENT,
|
PlayerComment = world.event.S_EVENT_PLAYER_COMMENT,
|
||||||
ShootingStart = world.event.S_EVENT_SHOOTING_START,
|
ShootingStart = world.event.S_EVENT_SHOOTING_START,
|
||||||
ShootingEnd = world.event.S_EVENT_SHOOTING_END,
|
ShootingEnd = world.event.S_EVENT_SHOOTING_END,
|
||||||
|
-- Added with DCS 2.5.1
|
||||||
MarkAdded = world.event.S_EVENT_MARK_ADDED,
|
MarkAdded = world.event.S_EVENT_MARK_ADDED,
|
||||||
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
|
||||||
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,
|
||||||
@@ -231,6 +233,12 @@ EVENTS = {
|
|||||||
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,
|
||||||
|
-- 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
|
||||||
|
Kill = world.event.S_EVENT_KILL or -1,
|
||||||
|
Score = world.event.S_EVENT_SCORE or -1,
|
||||||
|
UnitLost = world.event.S_EVENT_UNIT_LOST or -1,
|
||||||
|
LandingAfterEjection = world.event.S_EVENT_LANDING_AFTER_EJECTION or -1,
|
||||||
}
|
}
|
||||||
|
|
||||||
--- The Event structure
|
--- The Event structure
|
||||||
@@ -481,6 +489,32 @@ local _EVENTMETA = {
|
|||||||
Event = "OnEventRemoveUnit",
|
Event = "OnEventRemoveUnit",
|
||||||
Text = "S_EVENT_REMOVE_UNIT"
|
Text = "S_EVENT_REMOVE_UNIT"
|
||||||
},
|
},
|
||||||
|
-- Added with DCS 2.5.6
|
||||||
|
[EVENTS.DetailedFailure] = {
|
||||||
|
Order = 1,
|
||||||
|
Event = "OnEventDetailedFailure",
|
||||||
|
Text = "S_EVENT_DETAILED_FAILURE"
|
||||||
|
},
|
||||||
|
[EVENTS.Kill] = {
|
||||||
|
Order = 1,
|
||||||
|
Event = "OnEventKill",
|
||||||
|
Text = "S_EVENT_KILL"
|
||||||
|
},
|
||||||
|
[EVENTS.Score] = {
|
||||||
|
Order = 1,
|
||||||
|
Event = "OnEventScore",
|
||||||
|
Text = "S_EVENT_SCORE"
|
||||||
|
},
|
||||||
|
[EVENTS.UnitLost] = {
|
||||||
|
Order = 1,
|
||||||
|
Event = "OnEventUnitLost",
|
||||||
|
Text = "S_EVENT_UNIT_LOST"
|
||||||
|
},
|
||||||
|
[EVENTS.LandingAfterEjection] = {
|
||||||
|
Order = 1,
|
||||||
|
Event = "OnEventLandingAfterEjection",
|
||||||
|
Text = "S_EVENT_LANDING_AFTER_EJECTION"
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -488,6 +522,9 @@ local _EVENTMETA = {
|
|||||||
-- @type EVENT.Events
|
-- @type EVENT.Events
|
||||||
-- @field #number IniUnit
|
-- @field #number IniUnit
|
||||||
|
|
||||||
|
--- Create new event handler.
|
||||||
|
-- @param #EVENT self
|
||||||
|
-- @return #EVENT self
|
||||||
function EVENT:New()
|
function EVENT:New()
|
||||||
local self = BASE:Inherit( self, BASE:New() )
|
local self = BASE:Inherit( self, BASE:New() )
|
||||||
self:F2()
|
self:F2()
|
||||||
@@ -518,6 +555,8 @@ function EVENT:Init( EventID, EventClass )
|
|||||||
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]
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -604,7 +643,7 @@ end
|
|||||||
-- @param EventID
|
-- @param EventID
|
||||||
-- @return #EVENT
|
-- @return #EVENT
|
||||||
function EVENT:OnEventGeneric( EventFunction, EventClass, EventID )
|
function EVENT:OnEventGeneric( EventFunction, EventClass, EventID )
|
||||||
self:F2( { EventID } )
|
self:F2( { EventID, EventClass, EventFunction } )
|
||||||
|
|
||||||
local EventData = self:Init( EventID, EventClass )
|
local EventData = self:Init( EventID, EventClass )
|
||||||
EventData.EventFunction = EventFunction
|
EventData.EventFunction = EventFunction
|
||||||
@@ -878,258 +917,237 @@ function EVENT:onEvent( Event )
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- Get event meta data.
|
||||||
local EventMeta = _EVENTMETA[Event.id]
|
local EventMeta = _EVENTMETA[Event.id]
|
||||||
|
|
||||||
--self:E( { EventMeta.Text, Event } ) -- Activate the see all incoming events ...
|
-- Check if this is a known event?
|
||||||
|
if EventMeta then
|
||||||
|
|
||||||
if self and
|
if self and
|
||||||
self.Events and
|
self.Events and
|
||||||
self.Events[Event.id] and
|
self.Events[Event.id] and
|
||||||
self.MissionEnd == false and
|
self.MissionEnd == false and
|
||||||
( Event.initiator ~= nil or ( Event.initiator == nil and Event.id ~= EVENTS.PlayerLeaveUnit ) ) then
|
( 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
|
||||||
end
|
end
|
||||||
|
|
||||||
if Event.initiator then
|
if Event.initiator then
|
||||||
|
|
||||||
Event.IniObjectCategory = Event.initiator:getCategory()
|
Event.IniObjectCategory = Event.initiator:getCategory()
|
||||||
|
|
||||||
if Event.IniObjectCategory == Object.Category.UNIT then
|
if Event.IniObjectCategory == Object.Category.UNIT then
|
||||||
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.IniDCSGroup = Event.IniDCSUnit:getGroup()
|
Event.IniDCSGroup = Event.IniDCSUnit:getGroup()
|
||||||
Event.IniUnit = UNIT:FindByName( Event.IniDCSUnitName )
|
Event.IniUnit = UNIT:FindByName( Event.IniDCSUnitName )
|
||||||
if not Event.IniUnit then
|
if not Event.IniUnit then
|
||||||
-- Unit can be a CLIENT. Most likely this will be the case ...
|
-- Unit can be a CLIENT. Most likely this will be the case ...
|
||||||
Event.IniUnit = CLIENT:FindByName( Event.IniDCSUnitName, '', true )
|
Event.IniUnit = CLIENT:FindByName( Event.IniDCSUnitName, '', true )
|
||||||
|
end
|
||||||
|
Event.IniDCSGroupName = ""
|
||||||
|
if Event.IniDCSGroup and Event.IniDCSGroup:isExist() then
|
||||||
|
Event.IniDCSGroupName = Event.IniDCSGroup:getName()
|
||||||
|
Event.IniGroup = GROUP:FindByName( Event.IniDCSGroupName )
|
||||||
|
--if Event.IniGroup then
|
||||||
|
Event.IniGroupName = Event.IniDCSGroupName
|
||||||
|
--end
|
||||||
|
end
|
||||||
|
Event.IniPlayerName = Event.IniDCSUnit:getPlayerName()
|
||||||
|
Event.IniCoalition = Event.IniDCSUnit:getCoalition()
|
||||||
|
Event.IniTypeName = Event.IniDCSUnit:getTypeName()
|
||||||
|
Event.IniCategory = Event.IniDCSUnit:getDesc().category
|
||||||
end
|
end
|
||||||
Event.IniDCSGroupName = ""
|
|
||||||
if Event.IniDCSGroup and Event.IniDCSGroup:isExist() then
|
|
||||||
Event.IniDCSGroupName = Event.IniDCSGroup:getName()
|
|
||||||
Event.IniGroup = GROUP:FindByName( Event.IniDCSGroupName )
|
|
||||||
--if Event.IniGroup then
|
|
||||||
Event.IniGroupName = Event.IniDCSGroupName
|
|
||||||
--end
|
|
||||||
end
|
|
||||||
Event.IniPlayerName = Event.IniDCSUnit:getPlayerName()
|
|
||||||
Event.IniCoalition = Event.IniDCSUnit:getCoalition()
|
|
||||||
Event.IniTypeName = Event.IniDCSUnit:getTypeName()
|
|
||||||
Event.IniCategory = Event.IniDCSUnit:getDesc().category
|
|
||||||
end
|
|
||||||
|
|
||||||
if Event.IniObjectCategory == Object.Category.STATIC then
|
if Event.IniObjectCategory == Object.Category.STATIC then
|
||||||
Event.IniDCSUnit = Event.initiator
|
if Event.id==31 then
|
||||||
Event.IniDCSUnitName = Event.IniDCSUnit:getName()
|
--env.info("FF event 31")
|
||||||
Event.IniUnitName = Event.IniDCSUnitName
|
-- Event.initiator is a Static object representing the pilot. But getName() error due to DCS bug.
|
||||||
Event.IniUnit = STATIC:FindByName( Event.IniDCSUnitName, false )
|
Event.IniDCSUnit = Event.initiator
|
||||||
Event.IniCoalition = Event.IniDCSUnit:getCoalition()
|
local ID=Event.initiator.id_
|
||||||
Event.IniCategory = Event.IniDCSUnit:getDesc().category
|
Event.IniDCSUnitName = string.format("Ejected Pilot ID %s", tostring(ID))
|
||||||
Event.IniTypeName = Event.IniDCSUnit:getTypeName()
|
Event.IniUnitName = Event.IniDCSUnitName
|
||||||
end
|
Event.IniCoalition = 0
|
||||||
|
Event.IniCategory = 0
|
||||||
if Event.IniObjectCategory == Object.Category.CARGO then
|
Event.IniTypeName = "Ejected Pilot"
|
||||||
Event.IniDCSUnit = Event.initiator
|
|
||||||
Event.IniDCSUnitName = Event.IniDCSUnit:getName()
|
|
||||||
Event.IniUnitName = Event.IniDCSUnitName
|
|
||||||
Event.IniUnit = CARGO:FindByName( Event.IniDCSUnitName )
|
|
||||||
Event.IniCoalition = Event.IniDCSUnit:getCoalition()
|
|
||||||
Event.IniCategory = Event.IniDCSUnit:getDesc().category
|
|
||||||
Event.IniTypeName = Event.IniDCSUnit:getTypeName()
|
|
||||||
end
|
|
||||||
|
|
||||||
if Event.IniObjectCategory == Object.Category.SCENERY then
|
|
||||||
Event.IniDCSUnit = Event.initiator
|
|
||||||
Event.IniDCSUnitName = Event.IniDCSUnit:getName()
|
|
||||||
Event.IniUnitName = Event.IniDCSUnitName
|
|
||||||
Event.IniUnit = SCENERY:Register( Event.IniDCSUnitName, Event.initiator )
|
|
||||||
Event.IniCategory = Event.IniDCSUnit:getDesc().category
|
|
||||||
Event.IniTypeName = Event.initiator:isExist() and Event.IniDCSUnit:getTypeName() or "SCENERY" -- TODO: Bug fix for 2.1!
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if Event.target then
|
|
||||||
|
|
||||||
Event.TgtObjectCategory = Event.target:getCategory()
|
|
||||||
|
|
||||||
if Event.TgtObjectCategory == Object.Category.UNIT then
|
|
||||||
Event.TgtDCSUnit = Event.target
|
|
||||||
Event.TgtDCSGroup = Event.TgtDCSUnit:getGroup()
|
|
||||||
Event.TgtDCSUnitName = Event.TgtDCSUnit:getName()
|
|
||||||
Event.TgtUnitName = Event.TgtDCSUnitName
|
|
||||||
Event.TgtUnit = UNIT:FindByName( Event.TgtDCSUnitName )
|
|
||||||
Event.TgtDCSGroupName = ""
|
|
||||||
if Event.TgtDCSGroup and Event.TgtDCSGroup:isExist() then
|
|
||||||
Event.TgtDCSGroupName = Event.TgtDCSGroup:getName()
|
|
||||||
Event.TgtGroup = GROUP:FindByName( Event.TgtDCSGroupName )
|
|
||||||
--if Event.TgtGroup then
|
|
||||||
Event.TgtGroupName = Event.TgtDCSGroupName
|
|
||||||
--end
|
|
||||||
end
|
|
||||||
Event.TgtPlayerName = Event.TgtDCSUnit:getPlayerName()
|
|
||||||
Event.TgtCoalition = Event.TgtDCSUnit:getCoalition()
|
|
||||||
Event.TgtCategory = Event.TgtDCSUnit:getDesc().category
|
|
||||||
Event.TgtTypeName = Event.TgtDCSUnit:getTypeName()
|
|
||||||
end
|
|
||||||
|
|
||||||
if Event.TgtObjectCategory == Object.Category.STATIC then
|
|
||||||
Event.TgtDCSUnit = Event.target
|
|
||||||
Event.TgtDCSUnitName = Event.TgtDCSUnit:getName()
|
|
||||||
Event.TgtUnitName = Event.TgtDCSUnitName
|
|
||||||
Event.TgtUnit = STATIC:FindByName( Event.TgtDCSUnitName, false )
|
|
||||||
Event.TgtCoalition = Event.TgtDCSUnit:getCoalition()
|
|
||||||
Event.TgtCategory = Event.TgtDCSUnit:getDesc().category
|
|
||||||
Event.TgtTypeName = Event.TgtDCSUnit:getTypeName()
|
|
||||||
end
|
|
||||||
|
|
||||||
if Event.TgtObjectCategory == Object.Category.SCENERY then
|
|
||||||
Event.TgtDCSUnit = Event.target
|
|
||||||
Event.TgtDCSUnitName = Event.TgtDCSUnit:getName()
|
|
||||||
Event.TgtUnitName = Event.TgtDCSUnitName
|
|
||||||
Event.TgtUnit = SCENERY:Register( Event.TgtDCSUnitName, Event.target )
|
|
||||||
Event.TgtCategory = Event.TgtDCSUnit:getDesc().category
|
|
||||||
Event.TgtTypeName = Event.TgtDCSUnit:getTypeName()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if Event.weapon then
|
|
||||||
Event.Weapon = Event.weapon
|
|
||||||
Event.WeaponName = Event.Weapon:getTypeName()
|
|
||||||
Event.WeaponUNIT = CLIENT:Find( Event.Weapon, '', true ) -- Sometimes, the weapon is a player unit!
|
|
||||||
Event.WeaponPlayerName = Event.WeaponUNIT and Event.Weapon:getPlayerName()
|
|
||||||
Event.WeaponCoalition = Event.WeaponUNIT and Event.Weapon:getCoalition()
|
|
||||||
Event.WeaponCategory = Event.WeaponUNIT and Event.Weapon:getDesc().category
|
|
||||||
Event.WeaponTypeName = Event.WeaponUNIT and Event.Weapon:getTypeName()
|
|
||||||
--Event.WeaponTgtDCSUnit = Event.Weapon:getTarget()
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Place should be given for takeoff and landing events as well as base captured. It should be a DCS airbase.
|
|
||||||
if Event.place then
|
|
||||||
Event.Place=AIRBASE:Find(Event.place)
|
|
||||||
Event.PlaceName=Event.Place:GetName()
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Mark points.
|
|
||||||
if Event.idx then
|
|
||||||
Event.MarkID=Event.idx
|
|
||||||
Event.MarkVec3=Event.pos
|
|
||||||
Event.MarkCoordinate=COORDINATE:NewFromVec3(Event.pos)
|
|
||||||
Event.MarkText=Event.text
|
|
||||||
Event.MarkCoalition=Event.coalition
|
|
||||||
Event.MarkGroupID = Event.groupID
|
|
||||||
end
|
|
||||||
|
|
||||||
if Event.cargo then
|
|
||||||
Event.Cargo = Event.cargo
|
|
||||||
Event.CargoName = Event.cargo.Name
|
|
||||||
end
|
|
||||||
|
|
||||||
if Event.zone then
|
|
||||||
Event.Zone = Event.zone
|
|
||||||
Event.ZoneName = Event.zone.ZoneName
|
|
||||||
end
|
|
||||||
|
|
||||||
local PriorityOrder = EventMeta.Order
|
|
||||||
local PriorityBegin = PriorityOrder == -1 and 5 or 1
|
|
||||||
local PriorityEnd = PriorityOrder == -1 and 1 or 5
|
|
||||||
|
|
||||||
if Event.IniObjectCategory ~= Object.Category.STATIC then
|
|
||||||
self:F( { EventMeta.Text, Event, Event.IniDCSUnitName, Event.TgtDCSUnitName, PriorityOrder } )
|
|
||||||
end
|
|
||||||
|
|
||||||
for EventPriority = PriorityBegin, PriorityEnd, PriorityOrder do
|
|
||||||
|
|
||||||
if self.Events[Event.id][EventPriority] then
|
|
||||||
|
|
||||||
-- 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
|
|
||||||
|
|
||||||
--if Event.IniObjectCategory ~= Object.Category.STATIC then
|
|
||||||
-- self:E( { "Evaluating: ", EventClass:GetClassNameAndID() } )
|
|
||||||
--end
|
|
||||||
|
|
||||||
Event.IniGroup = GROUP:FindByName( Event.IniDCSGroupName )
|
|
||||||
Event.TgtGroup = GROUP:FindByName( Event.TgtDCSGroupName )
|
|
||||||
|
|
||||||
-- If the EventData is for a UNIT, the call directly the EventClass EventFunction for that UNIT.
|
|
||||||
if EventData.EventUnit then
|
|
||||||
|
|
||||||
-- So now the EventClass must be a UNIT class!!! We check if it is still "Alive".
|
|
||||||
if EventClass:IsAlive() or
|
|
||||||
Event.id == EVENTS.PlayerEnterUnit or
|
|
||||||
Event.id == EVENTS.Crash or
|
|
||||||
Event.id == EVENTS.Dead or
|
|
||||||
Event.id == EVENTS.RemoveUnit then
|
|
||||||
|
|
||||||
local UnitName = EventClass:GetName()
|
|
||||||
|
|
||||||
if ( EventMeta.Side == "I" and UnitName == Event.IniDCSUnitName ) or
|
|
||||||
( EventMeta.Side == "T" and UnitName == Event.TgtDCSUnitName ) then
|
|
||||||
|
|
||||||
-- First test if a EventFunction is Set, otherwise search for the default function
|
|
||||||
if EventData.EventFunction then
|
|
||||||
|
|
||||||
if Event.IniObjectCategory ~= 3 then
|
|
||||||
self:F( { "Calling EventFunction for UNIT ", EventClass:GetClassNameAndID(), ", Unit ", Event.IniUnitName, EventPriority } )
|
|
||||||
end
|
|
||||||
|
|
||||||
local Result, Value = xpcall(
|
|
||||||
function()
|
|
||||||
return EventData.EventFunction( EventClass, Event )
|
|
||||||
end, ErrorHandler )
|
|
||||||
|
|
||||||
else
|
|
||||||
|
|
||||||
-- There is no EventFunction defined, so try to find if a default OnEvent function is defined on the object.
|
|
||||||
local EventFunction = EventClass[ EventMeta.Event ]
|
|
||||||
if EventFunction and type( EventFunction ) == "function" then
|
|
||||||
|
|
||||||
-- Now call the default event function.
|
|
||||||
if Event.IniObjectCategory ~= 3 then
|
|
||||||
self:F( { "Calling " .. EventMeta.Event .. " for Class ", EventClass:GetClassNameAndID(), EventPriority } )
|
|
||||||
end
|
|
||||||
|
|
||||||
local Result, Value = xpcall(
|
|
||||||
function()
|
|
||||||
return EventFunction( EventClass, Event )
|
|
||||||
end, ErrorHandler )
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
-- The EventClass is not alive anymore, we remove it from the EventHandlers...
|
|
||||||
self:RemoveEvent( EventClass, Event.id )
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
|
Event.IniDCSUnit = Event.initiator
|
||||||
|
Event.IniDCSUnitName = Event.IniDCSUnit:getName()
|
||||||
|
Event.IniUnitName = Event.IniDCSUnitName
|
||||||
|
Event.IniUnit = STATIC:FindByName( Event.IniDCSUnitName, false )
|
||||||
|
Event.IniCoalition = Event.IniDCSUnit:getCoalition()
|
||||||
|
Event.IniCategory = Event.IniDCSUnit:getDesc().category
|
||||||
|
Event.IniTypeName = Event.IniDCSUnit:getTypeName()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- If the EventData is for a GROUP, the call directly the EventClass EventFunction for the UNIT in that GROUP.
|
if Event.IniObjectCategory == Object.Category.CARGO then
|
||||||
if EventData.EventGroup then
|
Event.IniDCSUnit = Event.initiator
|
||||||
|
Event.IniDCSUnitName = Event.IniDCSUnit:getName()
|
||||||
|
Event.IniUnitName = Event.IniDCSUnitName
|
||||||
|
Event.IniUnit = CARGO:FindByName( Event.IniDCSUnitName )
|
||||||
|
Event.IniCoalition = Event.IniDCSUnit:getCoalition()
|
||||||
|
Event.IniCategory = Event.IniDCSUnit:getDesc().category
|
||||||
|
Event.IniTypeName = Event.IniDCSUnit:getTypeName()
|
||||||
|
end
|
||||||
|
|
||||||
-- So now the EventClass must be a GROUP class!!! We check if it is still "Alive".
|
if Event.IniObjectCategory == Object.Category.SCENERY then
|
||||||
|
Event.IniDCSUnit = Event.initiator
|
||||||
|
Event.IniDCSUnitName = Event.IniDCSUnit:getName()
|
||||||
|
Event.IniUnitName = Event.IniDCSUnitName
|
||||||
|
Event.IniUnit = SCENERY:Register( Event.IniDCSUnitName, Event.initiator )
|
||||||
|
Event.IniCategory = Event.IniDCSUnit:getDesc().category
|
||||||
|
Event.IniTypeName = Event.initiator:isExist() and Event.IniDCSUnit:getTypeName() or "SCENERY" -- TODO: Bug fix for 2.1!
|
||||||
|
end
|
||||||
|
|
||||||
|
if Event.IniObjectCategory == Object.Category.BASE then
|
||||||
|
Event.IniDCSUnit = Event.initiator
|
||||||
|
Event.IniDCSUnitName = Event.IniDCSUnit:getName()
|
||||||
|
Event.IniUnitName = Event.IniDCSUnitName
|
||||||
|
Event.IniUnit = AIRBASE:FindByName(Event.IniDCSUnitName)
|
||||||
|
Event.IniCoalition = Event.IniDCSUnit:getCoalition()
|
||||||
|
Event.IniCategory = Event.IniDCSUnit:getDesc().category
|
||||||
|
Event.IniTypeName = Event.IniDCSUnit:getTypeName()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if Event.target then
|
||||||
|
|
||||||
|
Event.TgtObjectCategory = Event.target:getCategory()
|
||||||
|
|
||||||
|
if Event.TgtObjectCategory == Object.Category.UNIT then
|
||||||
|
Event.TgtDCSUnit = Event.target
|
||||||
|
Event.TgtDCSGroup = Event.TgtDCSUnit:getGroup()
|
||||||
|
Event.TgtDCSUnitName = Event.TgtDCSUnit:getName()
|
||||||
|
Event.TgtUnitName = Event.TgtDCSUnitName
|
||||||
|
Event.TgtUnit = UNIT:FindByName( Event.TgtDCSUnitName )
|
||||||
|
Event.TgtDCSGroupName = ""
|
||||||
|
if Event.TgtDCSGroup and Event.TgtDCSGroup:isExist() then
|
||||||
|
Event.TgtDCSGroupName = Event.TgtDCSGroup:getName()
|
||||||
|
Event.TgtGroup = GROUP:FindByName( Event.TgtDCSGroupName )
|
||||||
|
--if Event.TgtGroup then
|
||||||
|
Event.TgtGroupName = Event.TgtDCSGroupName
|
||||||
|
--end
|
||||||
|
end
|
||||||
|
Event.TgtPlayerName = Event.TgtDCSUnit:getPlayerName()
|
||||||
|
Event.TgtCoalition = Event.TgtDCSUnit:getCoalition()
|
||||||
|
Event.TgtCategory = Event.TgtDCSUnit:getDesc().category
|
||||||
|
Event.TgtTypeName = Event.TgtDCSUnit:getTypeName()
|
||||||
|
end
|
||||||
|
|
||||||
|
if Event.TgtObjectCategory == Object.Category.STATIC then
|
||||||
|
Event.TgtDCSUnit = Event.target
|
||||||
|
Event.TgtDCSUnitName = Event.TgtDCSUnit:getName()
|
||||||
|
Event.TgtUnitName = Event.TgtDCSUnitName
|
||||||
|
Event.TgtUnit = STATIC:FindByName( Event.TgtDCSUnitName, false )
|
||||||
|
Event.TgtCoalition = Event.TgtDCSUnit:getCoalition()
|
||||||
|
Event.TgtCategory = Event.TgtDCSUnit:getDesc().category
|
||||||
|
Event.TgtTypeName = Event.TgtDCSUnit:getTypeName()
|
||||||
|
end
|
||||||
|
|
||||||
|
if Event.TgtObjectCategory == Object.Category.SCENERY then
|
||||||
|
Event.TgtDCSUnit = Event.target
|
||||||
|
Event.TgtDCSUnitName = Event.TgtDCSUnit:getName()
|
||||||
|
Event.TgtUnitName = Event.TgtDCSUnitName
|
||||||
|
Event.TgtUnit = SCENERY:Register( Event.TgtDCSUnitName, Event.target )
|
||||||
|
Event.TgtCategory = Event.TgtDCSUnit:getDesc().category
|
||||||
|
Event.TgtTypeName = Event.TgtDCSUnit:getTypeName()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if Event.weapon then
|
||||||
|
Event.Weapon = Event.weapon
|
||||||
|
Event.WeaponName = Event.Weapon:getTypeName()
|
||||||
|
Event.WeaponUNIT = CLIENT:Find( Event.Weapon, '', true ) -- Sometimes, the weapon is a player unit!
|
||||||
|
Event.WeaponPlayerName = Event.WeaponUNIT and Event.Weapon:getPlayerName()
|
||||||
|
Event.WeaponCoalition = Event.WeaponUNIT and Event.Weapon:getCoalition()
|
||||||
|
Event.WeaponCategory = Event.WeaponUNIT and Event.Weapon:getDesc().category
|
||||||
|
Event.WeaponTypeName = Event.WeaponUNIT and Event.Weapon:getTypeName()
|
||||||
|
--Event.WeaponTgtDCSUnit = Event.Weapon:getTarget()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- 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.id==EVENTS.LandingAfterEjection then
|
||||||
|
-- Place is here the UNIT of which the pilot ejected.
|
||||||
|
--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.
|
||||||
|
--Event.Place=UNIT:Find(Event.place)
|
||||||
|
else
|
||||||
|
Event.Place=AIRBASE:Find(Event.place)
|
||||||
|
Event.PlaceName=Event.Place:GetName()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Mark points.
|
||||||
|
if Event.idx then
|
||||||
|
Event.MarkID=Event.idx
|
||||||
|
Event.MarkVec3=Event.pos
|
||||||
|
Event.MarkCoordinate=COORDINATE:NewFromVec3(Event.pos)
|
||||||
|
Event.MarkText=Event.text
|
||||||
|
Event.MarkCoalition=Event.coalition
|
||||||
|
Event.MarkGroupID = Event.groupID
|
||||||
|
end
|
||||||
|
|
||||||
|
if Event.cargo then
|
||||||
|
Event.Cargo = Event.cargo
|
||||||
|
Event.CargoName = Event.cargo.Name
|
||||||
|
end
|
||||||
|
|
||||||
|
if Event.zone then
|
||||||
|
Event.Zone = Event.zone
|
||||||
|
Event.ZoneName = Event.zone.ZoneName
|
||||||
|
end
|
||||||
|
|
||||||
|
local PriorityOrder = EventMeta.Order
|
||||||
|
local PriorityBegin = PriorityOrder == -1 and 5 or 1
|
||||||
|
local PriorityEnd = PriorityOrder == -1 and 1 or 5
|
||||||
|
|
||||||
|
if Event.IniObjectCategory ~= Object.Category.STATIC then
|
||||||
|
self:F( { EventMeta.Text, Event, Event.IniDCSUnitName, Event.TgtDCSUnitName, PriorityOrder } )
|
||||||
|
end
|
||||||
|
|
||||||
|
for EventPriority = PriorityBegin, PriorityEnd, PriorityOrder do
|
||||||
|
|
||||||
|
if self.Events[Event.id][EventPriority] then
|
||||||
|
|
||||||
|
-- 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
|
||||||
|
|
||||||
|
--if Event.IniObjectCategory ~= Object.Category.STATIC then
|
||||||
|
-- self:E( { "Evaluating: ", EventClass:GetClassNameAndID() } )
|
||||||
|
--end
|
||||||
|
|
||||||
|
Event.IniGroup = GROUP:FindByName( Event.IniDCSGroupName )
|
||||||
|
Event.TgtGroup = GROUP:FindByName( Event.TgtDCSGroupName )
|
||||||
|
|
||||||
|
-- If the EventData is for a UNIT, the call directly the EventClass EventFunction for that UNIT.
|
||||||
|
if EventData.EventUnit then
|
||||||
|
|
||||||
|
-- So now the EventClass must be a UNIT class!!! We check if it is still "Alive".
|
||||||
if EventClass:IsAlive() or
|
if EventClass:IsAlive() or
|
||||||
Event.id == EVENTS.PlayerEnterUnit or
|
Event.id == EVENTS.PlayerEnterUnit or
|
||||||
Event.id == EVENTS.Crash or
|
Event.id == EVENTS.Crash or
|
||||||
Event.id == EVENTS.Dead or
|
Event.id == EVENTS.Dead or
|
||||||
Event.id == EVENTS.RemoveUnit then
|
Event.id == EVENTS.RemoveUnit then
|
||||||
|
|
||||||
-- We can get the name of the EventClass, which is now always a GROUP object.
|
local UnitName = EventClass:GetName()
|
||||||
local GroupName = EventClass:GetName()
|
|
||||||
|
|
||||||
if ( EventMeta.Side == "I" and GroupName == Event.IniDCSGroupName ) or
|
if ( EventMeta.Side == "I" and UnitName == Event.IniDCSUnitName ) or
|
||||||
( EventMeta.Side == "T" and GroupName == Event.TgtDCSGroupName ) 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
|
||||||
|
|
||||||
if Event.IniObjectCategory ~= 3 then
|
if Event.IniObjectCategory ~= 3 then
|
||||||
self:F( { "Calling EventFunction for GROUP ", 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, unpack( EventData.Params ) )
|
return EventData.EventFunction( EventClass, Event )
|
||||||
end, ErrorHandler )
|
end, ErrorHandler )
|
||||||
|
|
||||||
else
|
else
|
||||||
@@ -1140,74 +1158,130 @@ function EVENT:onEvent( Event )
|
|||||||
|
|
||||||
-- Now call the default event function.
|
-- Now call the default event function.
|
||||||
if Event.IniObjectCategory ~= 3 then
|
if Event.IniObjectCategory ~= 3 then
|
||||||
self:F( { "Calling " .. EventMeta.Event .. " for GROUP ", 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, unpack( EventData.Params ) )
|
return EventFunction( EventClass, Event )
|
||||||
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
|
||||||
|
|
||||||
-- If the EventData is not bound to a specific unit, then call the EventClass EventFunction.
|
--- If the EventData is for a GROUP, the call directly the EventClass EventFunction for the UNIT in that GROUP.
|
||||||
-- Note that here the EventFunction will need to implement and determine the logic for the relevant source- or target unit, or weapon.
|
if EventData.EventGroup then
|
||||||
if not EventData.EventUnit then
|
|
||||||
|
|
||||||
-- First test if a EventFunction is Set, otherwise search for the default function
|
-- So now the EventClass must be a GROUP class!!! We check if it is still "Alive".
|
||||||
if EventData.EventFunction then
|
if EventClass:IsAlive() or
|
||||||
|
Event.id == EVENTS.PlayerEnterUnit or
|
||||||
|
Event.id == EVENTS.Crash or
|
||||||
|
Event.id == EVENTS.Dead or
|
||||||
|
Event.id == EVENTS.RemoveUnit then
|
||||||
|
|
||||||
-- There is an EventFunction defined, so call the EventFunction.
|
-- We can get the name of the EventClass, which is now always a GROUP object.
|
||||||
if Event.IniObjectCategory ~= 3 then
|
local GroupName = EventClass:GetName()
|
||||||
self:F2( { "Calling EventFunction for Class ", EventClass:GetClassNameAndID(), EventPriority } )
|
|
||||||
end
|
|
||||||
local Result, Value = xpcall(
|
|
||||||
function()
|
|
||||||
return EventData.EventFunction( EventClass, Event )
|
|
||||||
end, ErrorHandler )
|
|
||||||
else
|
|
||||||
|
|
||||||
-- There is no EventFunction defined, so try to find if a default OnEvent function is defined on the object.
|
if ( EventMeta.Side == "I" and GroupName == Event.IniDCSGroupName ) or
|
||||||
local EventFunction = EventClass[ EventMeta.Event ]
|
( EventMeta.Side == "T" and GroupName == Event.TgtDCSGroupName ) then
|
||||||
if EventFunction and type( EventFunction ) == "function" then
|
|
||||||
|
|
||||||
-- Now call the default event function.
|
-- First test if a EventFunction is Set, otherwise search for the default function
|
||||||
if Event.IniObjectCategory ~= 3 then
|
if EventData.EventFunction then
|
||||||
self:F2( { "Calling " .. EventMeta.Event .. " for Class ", EventClass:GetClassNameAndID(), EventPriority } )
|
|
||||||
|
if Event.IniObjectCategory ~= 3 then
|
||||||
|
self:F( { "Calling EventFunction for GROUP ", EventClass:GetClassNameAndID(), ", Unit ", Event.IniUnitName, EventPriority } )
|
||||||
|
end
|
||||||
|
|
||||||
|
local Result, Value = xpcall(
|
||||||
|
function()
|
||||||
|
return EventData.EventFunction( EventClass, Event, unpack( EventData.Params ) )
|
||||||
|
end, ErrorHandler )
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
-- There is no EventFunction defined, so try to find if a default OnEvent function is defined on the object.
|
||||||
|
local EventFunction = EventClass[ EventMeta.Event ]
|
||||||
|
if EventFunction and type( EventFunction ) == "function" then
|
||||||
|
|
||||||
|
-- Now call the default event function.
|
||||||
|
if Event.IniObjectCategory ~= 3 then
|
||||||
|
self:F( { "Calling " .. EventMeta.Event .. " for GROUP ", EventClass:GetClassNameAndID(), EventPriority } )
|
||||||
|
end
|
||||||
|
|
||||||
|
local Result, Value = xpcall(
|
||||||
|
function()
|
||||||
|
return EventFunction( EventClass, Event, unpack( EventData.Params ) )
|
||||||
|
end, ErrorHandler )
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
-- The EventClass is not alive anymore, we remove it from the EventHandlers...
|
||||||
|
--self:RemoveEvent( EventClass, Event.id )
|
||||||
|
end
|
||||||
|
else
|
||||||
|
|
||||||
|
-- If the EventData is not bound to a specific unit, then call the EventClass EventFunction.
|
||||||
|
-- Note that here the EventFunction will need to implement and determine the logic for the relevant source- or target unit, or weapon.
|
||||||
|
if not EventData.EventUnit then
|
||||||
|
|
||||||
|
-- First test if a EventFunction is Set, otherwise search for the default function
|
||||||
|
if EventData.EventFunction then
|
||||||
|
|
||||||
|
-- There is an EventFunction defined, so call the EventFunction.
|
||||||
|
if Event.IniObjectCategory ~= 3 then
|
||||||
|
self:F2( { "Calling EventFunction for Class ", EventClass:GetClassNameAndID(), EventPriority } )
|
||||||
|
end
|
||||||
local Result, Value = xpcall(
|
local Result, Value = xpcall(
|
||||||
function()
|
function()
|
||||||
local Result, Value = EventFunction( EventClass, Event )
|
return EventData.EventFunction( EventClass, Event )
|
||||||
return Result, Value
|
|
||||||
end, ErrorHandler )
|
end, ErrorHandler )
|
||||||
end
|
else
|
||||||
end
|
|
||||||
|
|
||||||
|
-- There is no EventFunction defined, so try to find if a default OnEvent function is defined on the object.
|
||||||
|
local EventFunction = EventClass[ EventMeta.Event ]
|
||||||
|
if EventFunction and type( EventFunction ) == "function" then
|
||||||
|
|
||||||
|
-- Now call the default event function.
|
||||||
|
if Event.IniObjectCategory ~= 3 then
|
||||||
|
self:F2( { "Calling " .. EventMeta.Event .. " for Class ", EventClass:GetClassNameAndID(), EventPriority } )
|
||||||
|
end
|
||||||
|
|
||||||
|
local Result, Value = xpcall(
|
||||||
|
function()
|
||||||
|
local Result, Value = EventFunction( EventClass, Event )
|
||||||
|
return Result, Value
|
||||||
|
end, ErrorHandler )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
-- When cargo was deleted, it may probably be because of an S_EVENT_DEAD.
|
-- When cargo was deleted, it may probably be because of an S_EVENT_DEAD.
|
||||||
-- However, in the loading logic, an S_EVENT_DEAD is also generated after a Destroy() call.
|
-- However, in the loading logic, an S_EVENT_DEAD is also generated after a Destroy() call.
|
||||||
-- And this is a problem because it will remove all entries from the SET_CARGOs.
|
-- And this is a problem because it will remove all entries from the SET_CARGOs.
|
||||||
-- To prevent this from happening, the Cargo object has a flag NoDestroy.
|
-- To prevent this from happening, the Cargo object has a flag NoDestroy.
|
||||||
-- When true, the SET_CARGO won't Remove the Cargo object from the set.
|
-- When true, the SET_CARGO won't Remove the Cargo object from the set.
|
||||||
-- But we need to switch that flag off after the event handlers have been called.
|
-- But we need to switch that flag off after the event handlers have been called.
|
||||||
if Event.id == EVENTS.DeleteCargo then
|
if Event.id == EVENTS.DeleteCargo then
|
||||||
Event.Cargo.NoDestroy = nil
|
Event.Cargo.NoDestroy = nil
|
||||||
|
end
|
||||||
|
else
|
||||||
|
self:T( { EventMeta.Text, Event } )
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
self:T( { EventMeta.Text, Event } )
|
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
|
||||||
@@ -1223,7 +1297,7 @@ EVENTHANDLER = {
|
|||||||
|
|
||||||
--- The EVENTHANDLER constructor
|
--- The EVENTHANDLER constructor
|
||||||
-- @param #EVENTHANDLER self
|
-- @param #EVENTHANDLER self
|
||||||
-- @return #EVENTHANDLER
|
-- @return #EVENTHANDLER self
|
||||||
function EVENTHANDLER:New()
|
function EVENTHANDLER:New()
|
||||||
self = BASE:Inherit( self, BASE:New() ) -- #EVENTHANDLER
|
self = BASE:Inherit( self, BASE:New() ) -- #EVENTHANDLER
|
||||||
return self
|
return self
|
||||||
|
|||||||
@@ -71,7 +71,7 @@
|
|||||||
--
|
--
|
||||||
--
|
--
|
||||||
-- ### Author: **FlightControl**
|
-- ### Author: **FlightControl**
|
||||||
-- ### Contributions:
|
-- ### Contributions: **funkyfranky**
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
@@ -81,6 +81,12 @@
|
|||||||
do -- FSM
|
do -- FSM
|
||||||
|
|
||||||
--- @type FSM
|
--- @type FSM
|
||||||
|
-- @field #string ClassName Name of the class.
|
||||||
|
-- @field Core.Scheduler#SCHEDULER CallScheduler Call scheduler.
|
||||||
|
-- @field #table options Options.
|
||||||
|
-- @field #table subs Subs.
|
||||||
|
-- @field #table Scores Scores.
|
||||||
|
-- @field #string current Current state name.
|
||||||
-- @extends Core.Base#BASE
|
-- @extends Core.Base#BASE
|
||||||
|
|
||||||
|
|
||||||
@@ -370,7 +376,6 @@ do -- FSM
|
|||||||
|
|
||||||
self.CallScheduler = SCHEDULER:New( self )
|
self.CallScheduler = SCHEDULER:New( self )
|
||||||
|
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -379,7 +384,6 @@ do -- FSM
|
|||||||
-- @param #FSM self
|
-- @param #FSM self
|
||||||
-- @param #string State A string defining the start state.
|
-- @param #string State A string defining the start state.
|
||||||
function FSM:SetStartState( State )
|
function FSM:SetStartState( State )
|
||||||
|
|
||||||
self._StartState = State
|
self._StartState = State
|
||||||
self.current = State
|
self.current = State
|
||||||
end
|
end
|
||||||
@@ -389,7 +393,6 @@ do -- FSM
|
|||||||
-- @param #FSM self
|
-- @param #FSM self
|
||||||
-- @return #string A string containing the start state.
|
-- @return #string A string containing the start state.
|
||||||
function FSM:GetStartState()
|
function FSM:GetStartState()
|
||||||
|
|
||||||
return self._StartState or {}
|
return self._StartState or {}
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -406,6 +409,7 @@ do -- FSM
|
|||||||
Transition.Event = Event
|
Transition.Event = Event
|
||||||
Transition.To = To
|
Transition.To = To
|
||||||
|
|
||||||
|
-- Debug message.
|
||||||
self:T2( Transition )
|
self:T2( Transition )
|
||||||
|
|
||||||
self._Transitions[Transition] = Transition
|
self._Transitions[Transition] = Transition
|
||||||
@@ -414,9 +418,9 @@ do -- FSM
|
|||||||
|
|
||||||
|
|
||||||
--- Returns a table of the transition rules defined within the FSM.
|
--- Returns a table of the transition rules defined within the FSM.
|
||||||
-- @return #table
|
-- @param #FSM self
|
||||||
|
-- @return #table Transitions.
|
||||||
function FSM:GetTransitions()
|
function FSM:GetTransitions()
|
||||||
|
|
||||||
return self._Transitions or {}
|
return self._Transitions or {}
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -448,7 +452,8 @@ do -- FSM
|
|||||||
|
|
||||||
|
|
||||||
--- Returns a table of the SubFSM rules defined within the FSM.
|
--- Returns a table of the SubFSM rules defined within the FSM.
|
||||||
-- @return #table
|
-- @param #FSM self
|
||||||
|
-- @return #table Sub processes.
|
||||||
function FSM:GetProcesses()
|
function FSM:GetProcesses()
|
||||||
|
|
||||||
self:F( { Processes = self._Processes } )
|
self:F( { Processes = self._Processes } )
|
||||||
@@ -480,15 +485,17 @@ do -- FSM
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Adds an End state.
|
--- Adds an End state.
|
||||||
|
-- @param #FSM self
|
||||||
|
-- @param #string State The FSM state.
|
||||||
function FSM:AddEndState( State )
|
function FSM:AddEndState( State )
|
||||||
|
|
||||||
self._EndStates[State] = State
|
self._EndStates[State] = State
|
||||||
self.endstates[State] = State
|
self.endstates[State] = State
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Returns the End states.
|
--- Returns the End states.
|
||||||
|
-- @param #FSM self
|
||||||
|
-- @return #table End states.
|
||||||
function FSM:GetEndStates()
|
function FSM:GetEndStates()
|
||||||
|
|
||||||
return self._EndStates or {}
|
return self._EndStates or {}
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -532,18 +539,22 @@ do -- FSM
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- Returns a table with the scores defined.
|
--- Returns a table with the scores defined.
|
||||||
|
-- @param #FSM self
|
||||||
|
-- @param #table Scores.
|
||||||
function FSM:GetScores()
|
function FSM:GetScores()
|
||||||
|
|
||||||
return self._Scores or {}
|
return self._Scores or {}
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Returns a table with the Subs defined.
|
--- Returns a table with the Subs defined.
|
||||||
|
-- @param #FSM self
|
||||||
|
-- @return #table Sub processes.
|
||||||
function FSM:GetSubs()
|
function FSM:GetSubs()
|
||||||
|
|
||||||
return self.options.subs
|
return self.options.subs
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Load call backs.
|
||||||
|
-- @param #FSM self
|
||||||
|
-- @param #table CallBackTable Table of call backs.
|
||||||
function FSM:LoadCallBacks( CallBackTable )
|
function FSM:LoadCallBacks( CallBackTable )
|
||||||
|
|
||||||
for name, callback in pairs( CallBackTable or {} ) do
|
for name, callback in pairs( CallBackTable or {} ) do
|
||||||
@@ -552,20 +563,33 @@ do -- FSM
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Event map.
|
||||||
|
-- @param #FSM self
|
||||||
|
-- @param #table Events Events.
|
||||||
|
-- @param #table EventStructure Event structure.
|
||||||
function FSM:_eventmap( Events, EventStructure )
|
function FSM:_eventmap( Events, EventStructure )
|
||||||
|
|
||||||
local Event = EventStructure.Event
|
local Event = EventStructure.Event
|
||||||
local __Event = "__" .. EventStructure.Event
|
local __Event = "__" .. EventStructure.Event
|
||||||
|
|
||||||
self[Event] = self[Event] or self:_create_transition(Event)
|
self[Event] = self[Event] or self:_create_transition(Event)
|
||||||
self[__Event] = self[__Event] or self:_delayed_transition(Event)
|
self[__Event] = self[__Event] or self:_delayed_transition(Event)
|
||||||
|
|
||||||
|
-- Debug message.
|
||||||
self:T2( "Added methods: " .. Event .. ", " .. __Event )
|
self:T2( "Added methods: " .. Event .. ", " .. __Event )
|
||||||
|
|
||||||
Events[Event] = self.Events[Event] or { map = {} }
|
Events[Event] = self.Events[Event] or { map = {} }
|
||||||
self:_add_to_map( Events[Event].map, EventStructure )
|
self:_add_to_map( Events[Event].map, EventStructure )
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Sub maps.
|
||||||
|
-- @param #FSM self
|
||||||
|
-- @param #table subs Subs.
|
||||||
|
-- @param #table sub Sub.
|
||||||
|
-- @param #string name Name.
|
||||||
function FSM:_submap( subs, sub, name )
|
function FSM:_submap( subs, sub, name )
|
||||||
--self:F( { sub = sub, name = name } )
|
|
||||||
subs[sub.From] = subs[sub.From] or {}
|
subs[sub.From] = subs[sub.From] or {}
|
||||||
subs[sub.From][sub.Event] = subs[sub.From][sub.Event] or {}
|
subs[sub.From][sub.Event] = subs[sub.From][sub.Event] or {}
|
||||||
|
|
||||||
@@ -578,22 +602,24 @@ do -- FSM
|
|||||||
subs[sub.From][sub.Event][sub].ReturnEvents = sub.ReturnEvents or {} -- these events need to be given to find the correct continue event ... if none given, the processing will stop.
|
subs[sub.From][sub.Event][sub].ReturnEvents = sub.ReturnEvents or {} -- these events need to be given to find the correct continue event ... if none given, the processing will stop.
|
||||||
subs[sub.From][sub.Event][sub].name = name
|
subs[sub.From][sub.Event][sub].name = name
|
||||||
subs[sub.From][sub.Event][sub].fsmparent = self
|
subs[sub.From][sub.Event][sub].fsmparent = self
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Call handler.
|
||||||
|
-- @param #FSM self
|
||||||
|
-- @param #string step Step "onafter", "onbefore", "onenter", "onleave".
|
||||||
|
-- @param #string trigger Trigger.
|
||||||
|
-- @param #table params Parameters.
|
||||||
|
-- @param #string EventName Event name.
|
||||||
|
-- @return Value.
|
||||||
function FSM:_call_handler( step, trigger, params, EventName )
|
function FSM:_call_handler( step, trigger, params, EventName )
|
||||||
|
--env.info(string.format("FF T=%.3f _call_handler step=%s, trigger=%s, event=%s", timer.getTime(), step, trigger, EventName))
|
||||||
|
|
||||||
local handler = step .. trigger
|
local handler = step .. trigger
|
||||||
local ErrorHandler = function( errmsg )
|
|
||||||
|
|
||||||
env.info( "Error in SCHEDULER function:" .. errmsg )
|
|
||||||
if BASE.Debug ~= nil then
|
|
||||||
env.info( BASE.Debug.traceback() )
|
|
||||||
end
|
|
||||||
|
|
||||||
return errmsg
|
|
||||||
end
|
|
||||||
if self[handler] then
|
if self[handler] then
|
||||||
|
|
||||||
|
--[[
|
||||||
if step == "onafter" or step == "OnAfter" then
|
if step == "onafter" or step == "OnAfter" then
|
||||||
self:T( ":::>" .. step .. params[2] .. " : " .. params[1] .. " >> " .. params[2] .. ">" .. step .. params[2] .. "()" .. " >> " .. params[3] )
|
self:T( ":::>" .. step .. params[2] .. " : " .. params[1] .. " >> " .. params[2] .. ">" .. step .. params[2] .. "()" .. " >> " .. params[3] )
|
||||||
elseif step == "onbefore" or step == "OnBefore" then
|
elseif step == "onbefore" or step == "OnBefore" then
|
||||||
@@ -605,13 +631,32 @@ do -- FSM
|
|||||||
else
|
else
|
||||||
self:T( ":::>" .. step .. " : " .. params[1] .. " >> " .. params[2] .. " >> " .. params[3] )
|
self:T( ":::>" .. step .. " : " .. params[1] .. " >> " .. params[2] .. " >> " .. params[3] )
|
||||||
end
|
end
|
||||||
|
]]
|
||||||
|
|
||||||
self._EventSchedules[EventName] = nil
|
self._EventSchedules[EventName] = nil
|
||||||
|
|
||||||
|
-- Error handler.
|
||||||
|
local ErrorHandler = function( errmsg )
|
||||||
|
env.info( "Error in SCHEDULER function:" .. errmsg )
|
||||||
|
if BASE.Debug ~= nil then
|
||||||
|
env.info( BASE.Debug.traceback() )
|
||||||
|
end
|
||||||
|
return errmsg
|
||||||
|
end
|
||||||
|
|
||||||
|
--return self[handler](self, unpack( params ))
|
||||||
|
|
||||||
|
-- Protected call.
|
||||||
local Result, Value = xpcall( function() return self[handler]( self, unpack( params ) ) end, ErrorHandler )
|
local Result, Value = xpcall( function() return self[handler]( self, unpack( params ) ) end, ErrorHandler )
|
||||||
return Value
|
return Value
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #FSM self
|
--- Handler.
|
||||||
|
-- @param #FSM self
|
||||||
|
-- @param #string EventName Event name.
|
||||||
|
-- @param ... Arguments.
|
||||||
function FSM._handler( self, EventName, ... )
|
function FSM._handler( self, EventName, ... )
|
||||||
|
|
||||||
local Can, To = self:can( EventName )
|
local Can, To = self:can( EventName )
|
||||||
@@ -621,7 +666,11 @@ do -- FSM
|
|||||||
end
|
end
|
||||||
|
|
||||||
if Can then
|
if Can then
|
||||||
|
|
||||||
|
-- From state.
|
||||||
local From = self.current
|
local From = self.current
|
||||||
|
|
||||||
|
-- Parameters.
|
||||||
local Params = { From, EventName, To, ... }
|
local Params = { From, EventName, To, ... }
|
||||||
|
|
||||||
|
|
||||||
@@ -632,8 +681,8 @@ do -- FSM
|
|||||||
self["onafter".. EventName] or
|
self["onafter".. EventName] or
|
||||||
self["OnAfter".. EventName] or
|
self["OnAfter".. EventName] or
|
||||||
self["onenter".. To] or
|
self["onenter".. To] or
|
||||||
self["OnEnter".. To]
|
self["OnEnter".. To] then
|
||||||
then
|
|
||||||
if self:_call_handler( "onbefore", EventName, Params, EventName ) == false then
|
if self:_call_handler( "onbefore", EventName, Params, EventName ) == false then
|
||||||
self:T( "*** FSM *** Cancel" .. " *** " .. self.current .. " --> " .. EventName .. " --> " .. To .. " *** onbefore" .. EventName )
|
self:T( "*** FSM *** Cancel" .. " *** " .. self.current .. " --> " .. EventName .. " --> " .. To .. " *** onbefore" .. EventName )
|
||||||
return false
|
return false
|
||||||
@@ -653,8 +702,11 @@ do -- FSM
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
local ClassName = self:GetClassName()
|
local ClassName = self:GetClassName()
|
||||||
|
|
||||||
if ClassName == "FSM" then
|
if ClassName == "FSM" then
|
||||||
self:T( "*** FSM *** Transit *** " .. self.current .. " --> " .. EventName .. " --> " .. To )
|
self:T( "*** FSM *** Transit *** " .. self.current .. " --> " .. EventName .. " --> " .. To )
|
||||||
end
|
end
|
||||||
@@ -672,46 +724,56 @@ do -- FSM
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- New current state.
|
||||||
self.current = To
|
self.current = To
|
||||||
|
|
||||||
local execute = true
|
local execute = true
|
||||||
|
|
||||||
local subtable = self:_gosub( From, EventName )
|
local subtable = self:_gosub( From, EventName )
|
||||||
|
|
||||||
for _, sub in pairs( subtable ) do
|
for _, sub in pairs( subtable ) do
|
||||||
|
|
||||||
--if sub.nextevent then
|
--if sub.nextevent then
|
||||||
-- self:F2( "nextevent = " .. sub.nextevent )
|
-- self:F2( "nextevent = " .. sub.nextevent )
|
||||||
-- self[sub.nextevent]( self )
|
-- self[sub.nextevent]( self )
|
||||||
--end
|
--end
|
||||||
|
|
||||||
self:T( "*** FSM *** Sub *** " .. sub.StartEvent )
|
self:T( "*** FSM *** Sub *** " .. sub.StartEvent )
|
||||||
|
|
||||||
sub.fsm.fsmparent = self
|
sub.fsm.fsmparent = self
|
||||||
sub.fsm.ReturnEvents = sub.ReturnEvents
|
sub.fsm.ReturnEvents = sub.ReturnEvents
|
||||||
sub.fsm[sub.StartEvent]( sub.fsm )
|
sub.fsm[sub.StartEvent]( sub.fsm )
|
||||||
|
|
||||||
execute = false
|
execute = false
|
||||||
end
|
end
|
||||||
|
|
||||||
local fsmparent, Event = self:_isendstate( To )
|
local fsmparent, Event = self:_isendstate( To )
|
||||||
|
|
||||||
if fsmparent and Event then
|
if fsmparent and Event then
|
||||||
|
|
||||||
self:T( "*** FSM *** End *** " .. Event )
|
self:T( "*** FSM *** End *** " .. Event )
|
||||||
|
|
||||||
self:_call_handler("onenter", To, Params, EventName )
|
self:_call_handler("onenter", To, Params, EventName )
|
||||||
self:_call_handler("OnEnter", To, Params, EventName )
|
self:_call_handler("OnEnter", To, Params, EventName )
|
||||||
self:_call_handler("onafter", EventName, Params, EventName )
|
self:_call_handler("onafter", EventName, Params, EventName )
|
||||||
self:_call_handler("OnAfter", EventName, Params, EventName )
|
self:_call_handler("OnAfter", EventName, Params, EventName )
|
||||||
self:_call_handler("onstate", "change", Params, EventName )
|
self:_call_handler("onstate", "change", Params, EventName )
|
||||||
|
|
||||||
fsmparent[Event]( fsmparent )
|
fsmparent[Event]( fsmparent )
|
||||||
|
|
||||||
execute = false
|
execute = false
|
||||||
end
|
end
|
||||||
|
|
||||||
if execute then
|
if execute then
|
||||||
self:_call_handler("onafter", EventName, Params, EventName )
|
|
||||||
self:_call_handler("OnAfter", EventName, Params, EventName )
|
|
||||||
|
|
||||||
-- only execute the call if the From state is not equal to the To state! Otherwise this function should never execute!
|
self:_call_handler("onafter", EventName, Params, EventName )
|
||||||
--if from ~= to then
|
self:_call_handler("OnAfter", EventName, Params, EventName )
|
||||||
self:_call_handler("onenter", To, Params, EventName )
|
|
||||||
self:_call_handler("OnEnter", To, Params, EventName )
|
self:_call_handler("onenter", To, Params, EventName )
|
||||||
--end
|
self:_call_handler("OnEnter", To, Params, EventName )
|
||||||
|
|
||||||
self:_call_handler("onstate", "change", Params, EventName )
|
self:_call_handler("onstate", "change", Params, EventName )
|
||||||
|
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
self:T( "*** FSM *** NO Transition *** " .. self.current .. " --> " .. EventName .. " --> ? " )
|
self:T( "*** FSM *** NO Transition *** " .. self.current .. " --> " .. EventName .. " --> ? " )
|
||||||
@@ -720,33 +782,67 @@ do -- FSM
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Delayed transition.
|
||||||
|
-- @param #FSM self
|
||||||
|
-- @param #string EventName Event name.
|
||||||
|
-- @return #function Function.
|
||||||
function FSM:_delayed_transition( EventName )
|
function FSM:_delayed_transition( EventName )
|
||||||
|
|
||||||
return function( self, DelaySeconds, ... )
|
return function( self, DelaySeconds, ... )
|
||||||
|
|
||||||
|
-- Debug.
|
||||||
self:T2( "Delayed Event: " .. EventName )
|
self:T2( "Delayed Event: " .. EventName )
|
||||||
|
|
||||||
local CallID = 0
|
local CallID = 0
|
||||||
if DelaySeconds ~= nil then
|
if DelaySeconds ~= nil then
|
||||||
|
|
||||||
if DelaySeconds < 0 then -- Only call the event ONCE!
|
if DelaySeconds < 0 then -- Only call the event ONCE!
|
||||||
|
|
||||||
DelaySeconds = math.abs( DelaySeconds )
|
DelaySeconds = math.abs( DelaySeconds )
|
||||||
|
|
||||||
if not self._EventSchedules[EventName] then
|
if not self._EventSchedules[EventName] then
|
||||||
|
|
||||||
|
-- Call _handler.
|
||||||
CallID = self.CallScheduler:Schedule( self, self._handler, { EventName, ... }, DelaySeconds or 1, nil, nil, nil, 4, true )
|
CallID = self.CallScheduler:Schedule( self, self._handler, { EventName, ... }, DelaySeconds or 1, nil, nil, nil, 4, true )
|
||||||
|
|
||||||
|
-- Set call ID.
|
||||||
self._EventSchedules[EventName] = CallID
|
self._EventSchedules[EventName] = CallID
|
||||||
|
|
||||||
|
-- Debug output.
|
||||||
|
self:T2(string.format("NEGATIVE Event %s delayed by %.1f sec SCHEDULED with CallID=%s", EventName, DelaySeconds, tostring(CallID)))
|
||||||
else
|
else
|
||||||
|
self:T2(string.format("NEGATIVE Event %s delayed by %.1f sec CANCELLED as we already have such an event in the queue.", EventName, DelaySeconds))
|
||||||
-- reschedule
|
-- reschedule
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
|
||||||
CallID = self.CallScheduler:Schedule( self, self._handler, { EventName, ... }, DelaySeconds or 1, nil, nil, nil, 4, true )
|
CallID = self.CallScheduler:Schedule( self, self._handler, { EventName, ... }, DelaySeconds or 1, nil, nil, nil, 4, true )
|
||||||
|
|
||||||
|
self:T2(string.format("Event %s delayed by %.1f sec SCHEDULED with CallID=%s", EventName, DelaySeconds, tostring(CallID)))
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
error( "FSM: An asynchronous event trigger requires a DelaySeconds parameter!!! This can be positive or negative! Sorry, but will not process this." )
|
error( "FSM: An asynchronous event trigger requires a DelaySeconds parameter!!! This can be positive or negative! Sorry, but will not process this." )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Debug.
|
||||||
self:T2( { CallID = CallID } )
|
self:T2( { CallID = CallID } )
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Create transition.
|
||||||
|
-- @param #FSM self
|
||||||
|
-- @param #string EventName Event name.
|
||||||
|
-- @return #function Function.
|
||||||
function FSM:_create_transition( EventName )
|
function FSM:_create_transition( EventName )
|
||||||
return function( self, ... ) return self._handler( self, EventName , ... ) end
|
return function( self, ... ) return self._handler( self, EventName , ... ) end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Go sub.
|
||||||
|
-- @param #FSM self
|
||||||
|
-- @param #string ParentFrom Parent from state.
|
||||||
|
-- @param #string ParentEvent Parent event name.
|
||||||
|
-- @return #table Subs.
|
||||||
function FSM:_gosub( ParentFrom, ParentEvent )
|
function FSM:_gosub( ParentFrom, ParentEvent )
|
||||||
local fsmtable = {}
|
local fsmtable = {}
|
||||||
if self.subs[ParentFrom] and self.subs[ParentFrom][ParentEvent] then
|
if self.subs[ParentFrom] and self.subs[ParentFrom][ParentEvent] then
|
||||||
@@ -757,8 +853,14 @@ do -- FSM
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Is end state.
|
||||||
|
-- @param #FSM self
|
||||||
|
-- @param #string Current Current state name.
|
||||||
|
-- @return #table FSM parent.
|
||||||
|
-- @return #string Event name.
|
||||||
function FSM:_isendstate( Current )
|
function FSM:_isendstate( Current )
|
||||||
local FSMParent = self.fsmparent
|
local FSMParent = self.fsmparent
|
||||||
|
|
||||||
if FSMParent and self.endstates[Current] then
|
if FSMParent and self.endstates[Current] then
|
||||||
--self:T( { state = Current, endstates = self.endstates, endstate = self.endstates[Current] } )
|
--self:T( { state = Current, endstates = self.endstates, endstate = self.endstates[Current] } )
|
||||||
FSMParent.current = Current
|
FSMParent.current = Current
|
||||||
@@ -776,8 +878,13 @@ do -- FSM
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Add to map.
|
||||||
|
-- @param #FSM self
|
||||||
|
-- @param #table Map Map.
|
||||||
|
-- @param #table Event Event table.
|
||||||
function FSM:_add_to_map( Map, Event )
|
function FSM:_add_to_map( Map, Event )
|
||||||
self:F3( { Map, Event } )
|
self:F3( { Map, Event } )
|
||||||
|
|
||||||
if type(Event.From) == 'string' then
|
if type(Event.From) == 'string' then
|
||||||
Map[Event.From] = Event.To
|
Map[Event.From] = Event.To
|
||||||
else
|
else
|
||||||
@@ -785,33 +892,60 @@ do -- FSM
|
|||||||
Map[From] = Event.To
|
Map[From] = Event.To
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
self:T3( { Map, Event } )
|
self:T3( { Map, Event } )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Get current state.
|
||||||
|
-- @param #FSM self
|
||||||
|
-- @return #string Current FSM state.
|
||||||
function FSM:GetState()
|
function FSM:GetState()
|
||||||
return self.current
|
return self.current
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Get current state.
|
||||||
|
-- @param #FSM self
|
||||||
|
-- @return #string Current FSM state.
|
||||||
function FSM:GetCurrentState()
|
function FSM:GetCurrentState()
|
||||||
return self.current
|
return self.current
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Check if FSM is in state.
|
||||||
|
-- @param #FSM self
|
||||||
|
-- @param #string State State name.
|
||||||
|
-- @param #boolean If true, FSM is in this state.
|
||||||
function FSM:Is( State )
|
function FSM:Is( State )
|
||||||
return self.current == State
|
return self.current == State
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Check if FSM is in state.
|
||||||
|
-- @param #FSM self
|
||||||
|
-- @param #string State State name.
|
||||||
|
-- @param #boolean If true, FSM is in this state.
|
||||||
function FSM:is(state)
|
function FSM:is(state)
|
||||||
return self.current == state
|
return self.current == state
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Check if can do an event.
|
||||||
|
-- @param #FSM self
|
||||||
|
-- @param #string e Event name.
|
||||||
|
-- @return #boolean If true, FSM can do the event.
|
||||||
|
-- @return #string To state.
|
||||||
function FSM:can(e)
|
function FSM:can(e)
|
||||||
|
|
||||||
local Event = self.Events[e]
|
local Event = self.Events[e]
|
||||||
self:F3( { self.current, Event } )
|
|
||||||
|
--self:F3( { self.current, Event } )
|
||||||
|
|
||||||
local To = Event and Event.map[self.current] or Event.map['*']
|
local To = Event and Event.map[self.current] or Event.map['*']
|
||||||
|
|
||||||
return To ~= nil, To
|
return To ~= nil, To
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Check if cannot do an event.
|
||||||
|
-- @param #FSM self
|
||||||
|
-- @param #string e Event name.
|
||||||
|
-- @return #boolean If true, FSM cannot do the event.
|
||||||
function FSM:cannot(e)
|
function FSM:cannot(e)
|
||||||
return not self:can(e)
|
return not self:can(e)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ### Author: **FlightControl**
|
-- ### Author: **FlightControl**
|
||||||
|
-- ### Contributions: **funkyfranky**
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -175,10 +175,6 @@ do -- COORDINATE
|
|||||||
-- In order to use the most optimal road system to transport vehicles, the method @{#COORDINATE.GetPathOnRoad}() will calculate
|
-- In order to use the most optimal road system to transport vehicles, the method @{#COORDINATE.GetPathOnRoad}() will calculate
|
||||||
-- the most optimal path following the road between two coordinates.
|
-- the most optimal path following the road between two coordinates.
|
||||||
--
|
--
|
||||||
--
|
|
||||||
--
|
|
||||||
--
|
|
||||||
--
|
|
||||||
-- ## 8) Metric or imperial system
|
-- ## 8) Metric or imperial system
|
||||||
--
|
--
|
||||||
-- * @{#COORDINATE.IsMetric}(): Returns if the 3D point is Metric or Nautical Miles.
|
-- * @{#COORDINATE.IsMetric}(): Returns if the 3D point is Metric or Nautical Miles.
|
||||||
@@ -204,23 +200,23 @@ do -- COORDINATE
|
|||||||
|
|
||||||
--- @field COORDINATE.WaypointAction
|
--- @field COORDINATE.WaypointAction
|
||||||
COORDINATE.WaypointAction = {
|
COORDINATE.WaypointAction = {
|
||||||
TurningPoint = "Turning Point",
|
TurningPoint = "Turning Point",
|
||||||
FlyoverPoint = "Fly Over Point",
|
FlyoverPoint = "Fly Over Point",
|
||||||
FromParkingArea = "From Parking Area",
|
FromParkingArea = "From Parking Area",
|
||||||
FromParkingAreaHot = "From Parking Area Hot",
|
FromParkingAreaHot = "From Parking Area Hot",
|
||||||
FromRunway = "From Runway",
|
FromRunway = "From Runway",
|
||||||
Landing = "Landing",
|
Landing = "Landing",
|
||||||
LandingReFuAr = "LandingReFuAr",
|
LandingReFuAr = "LandingReFuAr",
|
||||||
}
|
}
|
||||||
|
|
||||||
--- @field COORDINATE.WaypointType
|
--- @field COORDINATE.WaypointType
|
||||||
COORDINATE.WaypointType = {
|
COORDINATE.WaypointType = {
|
||||||
TakeOffParking = "TakeOffParking",
|
TakeOffParking = "TakeOffParking",
|
||||||
TakeOffParkingHot = "TakeOffParkingHot",
|
TakeOffParkingHot = "TakeOffParkingHot",
|
||||||
TakeOff = "TakeOffParkingHot",
|
TakeOff = "TakeOffParkingHot",
|
||||||
TurningPoint = "Turning Point",
|
TurningPoint = "Turning Point",
|
||||||
Land = "Land",
|
Land = "Land",
|
||||||
LandingReFuAr = "LandingReFuAr",
|
LandingReFuAr = "LandingReFuAr",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -232,6 +228,7 @@ do -- COORDINATE
|
|||||||
-- @return #COORDINATE
|
-- @return #COORDINATE
|
||||||
function COORDINATE:New( x, y, z )
|
function COORDINATE:New( x, y, z )
|
||||||
|
|
||||||
|
--env.info("FF COORDINATE New")
|
||||||
local self = BASE:Inherit( self, BASE:New() ) -- #COORDINATE
|
local self = BASE:Inherit( self, BASE:New() ) -- #COORDINATE
|
||||||
self.x = x
|
self.x = x
|
||||||
self.y = y
|
self.y = y
|
||||||
@@ -303,6 +300,45 @@ do -- COORDINATE
|
|||||||
return { x = self.x, y = self.z }
|
return { x = self.x, y = self.z }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Update x,y,z coordinates from a given 3D vector.
|
||||||
|
-- @param #COORDINATE self
|
||||||
|
-- @param DCS#Vec3 Vec3 The 3D vector with x,y,z components.
|
||||||
|
-- @return #COORDINATE The modified COORDINATE itself.
|
||||||
|
function COORDINATE:UpdateFromVec3(Vec3)
|
||||||
|
|
||||||
|
self.x=Vec3.x
|
||||||
|
self.y=Vec3.y
|
||||||
|
self.z=Vec3.z
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Update x,y,z coordinates from another given COORDINATE.
|
||||||
|
-- @param #COORDINATE self
|
||||||
|
-- @param #COORDINATE Coordinate The coordinate with the new x,y,z positions.
|
||||||
|
-- @return #COORDINATE The modified COORDINATE itself.
|
||||||
|
function COORDINATE:UpdateFromCoordinate(Coordinate)
|
||||||
|
|
||||||
|
self.x=Coordinate.x
|
||||||
|
self.y=Coordinate.y
|
||||||
|
self.z=Coordinate.z
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Update x and z coordinates from a given 2D vector.
|
||||||
|
-- @param #COORDINATE self
|
||||||
|
-- @param DCS#Vec2 Vec2 The 2D vector with x,y components. x is overwriting COORDINATE.x while y is overwriting COORDINATE.z.
|
||||||
|
-- @return #COORDINATE The modified COORDINATE itself.
|
||||||
|
function COORDINATE:UpdateFromVec2(Vec2)
|
||||||
|
|
||||||
|
self.x=Vec2.x
|
||||||
|
self.z=Vec2.y
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Returns the coordinate from the latitude and longitude given in decimal degrees.
|
--- Returns the coordinate from the latitude and longitude given in decimal degrees.
|
||||||
-- @param #COORDINATE self
|
-- @param #COORDINATE self
|
||||||
-- @param #number latitude Latitude in decimal degrees.
|
-- @param #number latitude Latitude in decimal degrees.
|
||||||
@@ -357,7 +393,7 @@ do -- COORDINATE
|
|||||||
-- @return #table Table of DCS static objects found.
|
-- @return #table Table of DCS static objects found.
|
||||||
-- @return #table Table of DCS scenery objects found.
|
-- @return #table Table of DCS scenery objects found.
|
||||||
function COORDINATE:ScanObjects(radius, scanunits, scanstatics, scanscenery)
|
function COORDINATE:ScanObjects(radius, scanunits, scanstatics, scanscenery)
|
||||||
self:F(string.format("Scanning in radius %.1f m.", radius))
|
self:F(string.format("Scanning in radius %.1f m.", radius or 100))
|
||||||
|
|
||||||
local SphereSearch = {
|
local SphereSearch = {
|
||||||
id = world.VolumeType.SPHERE,
|
id = world.VolumeType.SPHERE,
|
||||||
@@ -437,14 +473,57 @@ do -- COORDINATE
|
|||||||
end
|
end
|
||||||
for _,static in pairs(Statics) do
|
for _,static in pairs(Statics) do
|
||||||
self:T(string.format("Scan found static %s", static:getName()))
|
self:T(string.format("Scan found static %s", static:getName()))
|
||||||
|
_DATABASE:AddStatic(static:getName())
|
||||||
end
|
end
|
||||||
for _,scenery in pairs(Scenery) do
|
for _,scenery in pairs(Scenery) do
|
||||||
self:T(string.format("Scan found scenery %s", scenery:getTypeName()))
|
self:T(string.format("Scan found scenery %s typename=%s", scenery:getName(), scenery:getTypeName()))
|
||||||
|
SCENERY:Register(scenery:getName(), scenery)
|
||||||
end
|
end
|
||||||
|
|
||||||
return gotunits, gotstatics, gotscenery, Units, Statics, Scenery
|
return gotunits, gotstatics, gotscenery, Units, Statics, Scenery
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Scan/find UNITS within a certain radius around the coordinate using the world.searchObjects() DCS API function.
|
||||||
|
-- @param #COORDINATE self
|
||||||
|
-- @param #number radius (Optional) Scan radius in meters. Default 100 m.
|
||||||
|
-- @return Core.Set#SET_UNIT Set of units.
|
||||||
|
function COORDINATE:ScanUnits(radius)
|
||||||
|
|
||||||
|
local _,_,_,units=self:ScanObjects(radius, true, false, false)
|
||||||
|
|
||||||
|
local set=SET_UNIT:New()
|
||||||
|
|
||||||
|
for _,unit in pairs(units) do
|
||||||
|
set:AddUnit(unit)
|
||||||
|
end
|
||||||
|
|
||||||
|
return set
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Find the closest unit to the COORDINATE within a certain radius.
|
||||||
|
-- @param #COORDINATE self
|
||||||
|
-- @param #number radius Scan radius in meters. Default 100 m.
|
||||||
|
-- @return Wrapper.Unit#UNIT The closest unit or #nil if no unit is inside the given radius.
|
||||||
|
function COORDINATE:FindClosestUnit(radius)
|
||||||
|
|
||||||
|
local units=self:ScanUnits(radius)
|
||||||
|
|
||||||
|
local umin=nil --Wrapper.Unit#UNIT
|
||||||
|
local dmin=math.huge
|
||||||
|
for _,_unit in pairs(units.Set) do
|
||||||
|
local unit=_unit --Wrapper.Unit#UNIT
|
||||||
|
local coordinate=unit:GetCoordinate()
|
||||||
|
local d=self:Get2DDistance(coordinate)
|
||||||
|
if d<dmin then
|
||||||
|
dmin=d
|
||||||
|
umin=unit
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return umin
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Calculate the distance from a reference @{#COORDINATE}.
|
--- Calculate the distance from a reference @{#COORDINATE}.
|
||||||
-- @param #COORDINATE self
|
-- @param #COORDINATE self
|
||||||
-- @param #COORDINATE PointVec2Reference The reference @{#COORDINATE}.
|
-- @param #COORDINATE PointVec2Reference The reference @{#COORDINATE}.
|
||||||
@@ -463,19 +542,29 @@ do -- COORDINATE
|
|||||||
-- @param DCS#Distance Distance The Distance to be added in meters.
|
-- @param DCS#Distance Distance The Distance to be added in meters.
|
||||||
-- @param DCS#Angle Angle The Angle in degrees. Defaults to 0 if not specified (nil).
|
-- @param DCS#Angle Angle The Angle in degrees. Defaults to 0 if not specified (nil).
|
||||||
-- @param #boolean Keepalt If true, keep altitude of original coordinate. Default is that the new coordinate is created at the translated land height.
|
-- @param #boolean Keepalt If true, keep altitude of original coordinate. Default is that the new coordinate is created at the translated land height.
|
||||||
-- @return Core.Point#COORDINATE The new calculated COORDINATE.
|
-- @param #boolean Overwrite If true, overwrite the original COORDINATE with the translated one. Otherwise, create a new COODINATE.
|
||||||
function COORDINATE:Translate( Distance, Angle, Keepalt )
|
-- @return #COORDINATE The new calculated COORDINATE.
|
||||||
local SX = self.x
|
function COORDINATE:Translate( Distance, Angle, Keepalt, Overwrite )
|
||||||
local SY = self.z
|
|
||||||
local Radians = (Angle or 0) / 180 * math.pi
|
|
||||||
local TX = Distance * math.cos( Radians ) + SX
|
|
||||||
local TY = Distance * math.sin( Radians ) + SY
|
|
||||||
|
|
||||||
if Keepalt then
|
-- Angle in rad.
|
||||||
return COORDINATE:NewFromVec3( { x = TX, y=self.y, z = TY } )
|
local alpha = math.rad((Angle or 0))
|
||||||
|
|
||||||
|
local x = Distance * math.cos(alpha) + self.x -- New x
|
||||||
|
local z = Distance * math.sin(alpha) + self.z -- New z
|
||||||
|
|
||||||
|
local y=Keepalt and self.y or land.getHeight({x=x, y=z})
|
||||||
|
|
||||||
|
if Overwrite then
|
||||||
|
self.x=x
|
||||||
|
self.y=y
|
||||||
|
self.z=z
|
||||||
|
return self
|
||||||
else
|
else
|
||||||
return COORDINATE:NewFromVec2( { x = TX, y = TY } )
|
--env.info("FF translate with NEW coordinate T="..timer.getTime())
|
||||||
|
local coord=COORDINATE:New(x, y, z)
|
||||||
|
return coord
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Rotate coordinate in 2D (x,z) space.
|
--- Rotate coordinate in 2D (x,z) space.
|
||||||
@@ -653,15 +742,44 @@ do -- COORDINATE
|
|||||||
return Angle
|
return Angle
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Return an intermediate COORDINATE between this an another coordinate.
|
||||||
|
-- @param #COORDINATE self
|
||||||
|
-- @param #COORDINATE ToCoordinate The other coordinate.
|
||||||
|
-- @param #number Fraction The fraction (0,1) where the new coordinate is created. Default 0.5, i.e. in the middle.
|
||||||
|
-- @return #COORDINATE Coordinate between this and the other coordinate.
|
||||||
|
function COORDINATE:GetIntermediateCoordinate( ToCoordinate, Fraction )
|
||||||
|
|
||||||
|
local f=Fraction or 0.5
|
||||||
|
|
||||||
|
-- Get the vector from A to B
|
||||||
|
local vec=UTILS.VecSubstract(ToCoordinate, self)
|
||||||
|
|
||||||
|
-- Scale the vector.
|
||||||
|
vec.x=f*vec.x
|
||||||
|
vec.y=f*vec.y
|
||||||
|
vec.z=f*vec.z
|
||||||
|
|
||||||
|
-- Move the vector to start at the end of A.
|
||||||
|
vec=UTILS.VecAdd(self, vec)
|
||||||
|
|
||||||
|
local coord=COORDINATE:New(vec.x,vec.y,vec.z)
|
||||||
|
return coord
|
||||||
|
end
|
||||||
|
|
||||||
--- Return the 2D distance in meters between the target COORDINATE and the COORDINATE.
|
--- Return the 2D distance in meters between the target COORDINATE and the COORDINATE.
|
||||||
-- @param #COORDINATE self
|
-- @param #COORDINATE self
|
||||||
-- @param #COORDINATE TargetCoordinate The target COORDINATE.
|
-- @param #COORDINATE TargetCoordinate The target COORDINATE. Can also be a DCS#Vec3.
|
||||||
-- @return DCS#Distance Distance The distance in meters.
|
-- @return DCS#Distance Distance The distance in meters.
|
||||||
function COORDINATE:Get2DDistance( TargetCoordinate )
|
function COORDINATE:Get2DDistance( TargetCoordinate )
|
||||||
local TargetVec3 = TargetCoordinate:GetVec3()
|
|
||||||
local SourceVec3 = self:GetVec3()
|
local a={x=TargetCoordinate.x-self.x, y=0, z=TargetCoordinate.z-self.z}
|
||||||
return ( ( TargetVec3.x - SourceVec3.x ) ^ 2 + ( TargetVec3.z - SourceVec3.z ) ^ 2 ) ^ 0.5
|
|
||||||
|
return UTILS.VecNorm(a)
|
||||||
|
|
||||||
|
--local TargetVec3 = TargetCoordinate:GetVec3()
|
||||||
|
--local SourceVec3 = self:GetVec3()
|
||||||
|
|
||||||
|
--return ( ( TargetVec3.x - SourceVec3.x ) ^ 2 + ( TargetVec3.z - SourceVec3.z ) ^ 2 ) ^ 0.5
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Returns the temperature in Degrees Celsius.
|
--- Returns the temperature in Degrees Celsius.
|
||||||
@@ -1021,23 +1139,6 @@ do -- COORDINATE
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Add a Distance in meters from the COORDINATE horizontal plane, with the given angle, and calculate the new COORDINATE.
|
|
||||||
-- @param #COORDINATE self
|
|
||||||
-- @param DCS#Distance Distance The Distance to be added in meters.
|
|
||||||
-- @param DCS#Angle Angle The Angle in degrees.
|
|
||||||
-- @return #COORDINATE The new calculated COORDINATE.
|
|
||||||
function COORDINATE:Translate( Distance, Angle )
|
|
||||||
local SX = self.x
|
|
||||||
local SZ = self.z
|
|
||||||
local Radians = Angle / 180 * math.pi
|
|
||||||
local TX = Distance * math.cos( Radians ) + SX
|
|
||||||
local TZ = Distance * math.sin( Radians ) + SZ
|
|
||||||
|
|
||||||
return COORDINATE:New( TX, self.y, TZ )
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--- Build an air type route point.
|
--- Build an air type route point.
|
||||||
-- @param #COORDINATE self
|
-- @param #COORDINATE self
|
||||||
-- @param #COORDINATE.WaypointAltType AltType The altitude type.
|
-- @param #COORDINATE.WaypointAltType AltType The altitude type.
|
||||||
@@ -1093,7 +1194,7 @@ do -- COORDINATE
|
|||||||
-- Airbase parameters for takeoff and landing points.
|
-- Airbase parameters for takeoff and landing points.
|
||||||
if airbase then
|
if airbase then
|
||||||
local AirbaseID = airbase:GetID()
|
local AirbaseID = airbase:GetID()
|
||||||
local AirbaseCategory = airbase:GetDesc().category
|
local AirbaseCategory = airbase:GetAirbaseCategory()
|
||||||
if AirbaseCategory == Airbase.Category.SHIP or AirbaseCategory == Airbase.Category.HELIPAD then
|
if AirbaseCategory == Airbase.Category.SHIP or AirbaseCategory == Airbase.Category.HELIPAD then
|
||||||
RoutePoint.linkUnit = AirbaseID
|
RoutePoint.linkUnit = AirbaseID
|
||||||
RoutePoint.helipadId = AirbaseID
|
RoutePoint.helipadId = AirbaseID
|
||||||
@@ -1213,41 +1314,71 @@ do -- COORDINATE
|
|||||||
|
|
||||||
--- Build an ground type route point.
|
--- Build an ground type route point.
|
||||||
-- @param #COORDINATE self
|
-- @param #COORDINATE self
|
||||||
-- @param #number Speed (optional) Speed in km/h. The default speed is 20 km/h.
|
-- @param #number Speed (Optional) Speed in km/h. The default speed is 20 km/h.
|
||||||
-- @param #string Formation (optional) The route point Formation, which is a text string that specifies exactly the Text in the Type of the route point, like "Vee", "Echelon Right".
|
-- @param #string Formation (Optional) The route point Formation, which is a text string that specifies exactly the Text in the Type of the route point, like "Vee", "Echelon Right".
|
||||||
|
-- @param #table DCSTasks (Optional) A table of DCS tasks that are executed at the waypoints. Mind the curly brackets {}!
|
||||||
-- @return #table The route point.
|
-- @return #table The route point.
|
||||||
function COORDINATE:WaypointGround( Speed, Formation )
|
function COORDINATE:WaypointGround( Speed, Formation, DCSTasks )
|
||||||
self:F2( { Formation, Speed } )
|
self:F2( { Speed, Formation, DCSTasks } )
|
||||||
|
|
||||||
|
|
||||||
local RoutePoint = {}
|
local RoutePoint = {}
|
||||||
RoutePoint.x = self.x
|
|
||||||
RoutePoint.y = self.z
|
|
||||||
|
|
||||||
RoutePoint.action = Formation or ""
|
RoutePoint.x = self.x
|
||||||
--RoutePoint.formation_template = Formation and "" or nil
|
RoutePoint.y = self.z
|
||||||
|
|
||||||
|
RoutePoint.alt = self:GetLandHeight()+1
|
||||||
|
RoutePoint.alt_type = COORDINATE.WaypointAltType.BARO
|
||||||
|
|
||||||
|
RoutePoint.type = "Turning Point"
|
||||||
|
|
||||||
|
RoutePoint.action = Formation or "Off Road"
|
||||||
|
RoutePoint.formation_template=""
|
||||||
|
|
||||||
|
RoutePoint.ETA=0
|
||||||
|
RoutePoint.ETA_locked=true
|
||||||
|
|
||||||
RoutePoint.speed = ( Speed or 20 ) / 3.6
|
RoutePoint.speed = ( Speed or 20 ) / 3.6
|
||||||
RoutePoint.speed_locked = true
|
RoutePoint.speed_locked = true
|
||||||
|
|
||||||
-- ["task"] =
|
RoutePoint.task = {}
|
||||||
-- {
|
RoutePoint.task.id = "ComboTask"
|
||||||
-- ["id"] = "ComboTask",
|
RoutePoint.task.params = {}
|
||||||
-- ["params"] =
|
RoutePoint.task.params.tasks = DCSTasks or {}
|
||||||
-- {
|
|
||||||
-- ["tasks"] =
|
|
||||||
-- {
|
|
||||||
-- }, -- end of ["tasks"]
|
|
||||||
-- }, -- end of ["params"]
|
|
||||||
-- }, -- end of ["task"]
|
|
||||||
|
|
||||||
|
return RoutePoint
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Build route waypoint point for Naval units.
|
||||||
|
-- @param #COORDINATE self
|
||||||
|
-- @param #number Speed (Optional) Speed in km/h. The default speed is 20 km/h.
|
||||||
|
-- @param #string Depth (Optional) Dive depth in meters. Only for submarines. Default is COORDINATE.y component.
|
||||||
|
-- @param #table DCSTasks (Optional) A table of DCS tasks that are executed at the waypoints. Mind the curly brackets {}!
|
||||||
|
-- @return #table The route point.
|
||||||
|
function COORDINATE:WaypointNaval( Speed, Depth, DCSTasks )
|
||||||
|
self:F2( { Speed, Depth, DCSTasks } )
|
||||||
|
|
||||||
|
local RoutePoint = {}
|
||||||
|
|
||||||
|
RoutePoint.x = self.x
|
||||||
|
RoutePoint.y = self.z
|
||||||
|
|
||||||
|
RoutePoint.alt = Depth or self.y -- Depth is for submarines only. Ships should have alt=0.
|
||||||
|
RoutePoint.alt_type = "BARO"
|
||||||
|
|
||||||
|
RoutePoint.type = "Turning Point"
|
||||||
|
RoutePoint.action = "Turning Point"
|
||||||
|
RoutePoint.formation_template = ""
|
||||||
|
|
||||||
|
RoutePoint.ETA=0
|
||||||
|
RoutePoint.ETA_locked=true
|
||||||
|
|
||||||
|
RoutePoint.speed = ( Speed or 20 ) / 3.6
|
||||||
|
RoutePoint.speed_locked = true
|
||||||
|
|
||||||
RoutePoint.task = {}
|
RoutePoint.task = {}
|
||||||
RoutePoint.task.id = "ComboTask"
|
RoutePoint.task.id = "ComboTask"
|
||||||
RoutePoint.task.params = {}
|
RoutePoint.task.params = {}
|
||||||
RoutePoint.task.params.tasks = {}
|
RoutePoint.task.params.tasks = DCSTasks or {}
|
||||||
|
|
||||||
|
|
||||||
return RoutePoint
|
return RoutePoint
|
||||||
end
|
end
|
||||||
@@ -1258,7 +1389,7 @@ do -- COORDINATE
|
|||||||
-- @param #number Coalition (Optional) Coalition of the airbase.
|
-- @param #number Coalition (Optional) Coalition of the airbase.
|
||||||
-- @return Wrapper.Airbase#AIRBASE Closest Airbase to the given coordinate.
|
-- @return Wrapper.Airbase#AIRBASE Closest Airbase to the given coordinate.
|
||||||
-- @return #number Distance to the closest airbase in meters.
|
-- @return #number Distance to the closest airbase in meters.
|
||||||
function COORDINATE:GetClosestAirbase(Category, Coalition)
|
function COORDINATE:GetClosestAirbase2(Category, Coalition)
|
||||||
|
|
||||||
-- Get all airbases of the map.
|
-- Get all airbases of the map.
|
||||||
local airbases=AIRBASE.GetAllAirbases(Coalition)
|
local airbases=AIRBASE.GetAllAirbases(Coalition)
|
||||||
@@ -1292,6 +1423,36 @@ do -- COORDINATE
|
|||||||
return closest,distmin
|
return closest,distmin
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Gets the nearest airbase with respect to the current coordinates.
|
||||||
|
-- @param #COORDINATE self
|
||||||
|
-- @param #number Category (Optional) Category of the airbase. Enumerator of @{Wrapper.Airbase#AIRBASE.Category}.
|
||||||
|
-- @param #number Coalition (Optional) Coalition of the airbase.
|
||||||
|
-- @return Wrapper.Airbase#AIRBASE Closest Airbase to the given coordinate.
|
||||||
|
-- @return #number Distance to the closest airbase in meters.
|
||||||
|
function COORDINATE:GetClosestAirbase(Category, Coalition)
|
||||||
|
|
||||||
|
local a=self:GetVec3()
|
||||||
|
|
||||||
|
local distmin=math.huge
|
||||||
|
local airbase=nil
|
||||||
|
for DCSairbaseID, DCSairbase in pairs(world.getAirbases(Coalition)) do
|
||||||
|
local b=DCSairbase:getPoint()
|
||||||
|
|
||||||
|
local c=UTILS.VecSubstract(a,b)
|
||||||
|
local dist=UTILS.VecNorm(c)
|
||||||
|
|
||||||
|
--env.info(string.format("Airbase %s dist=%d category=%d", DCSairbase:getName(), dist, DCSairbase:getCategory()))
|
||||||
|
|
||||||
|
if dist<distmin and (Category==nil or Category==DCSairbase:getDesc().category) then
|
||||||
|
distmin=dist
|
||||||
|
airbase=DCSairbase
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
return AIRBASE:Find(airbase)
|
||||||
|
end
|
||||||
|
|
||||||
--- Gets the nearest parking spot.
|
--- Gets the nearest parking spot.
|
||||||
-- @param #COORDINATE self
|
-- @param #COORDINATE self
|
||||||
-- @param Wrapper.Airbase#AIRBASE airbase (Optional) Search only parking spots at this airbase.
|
-- @param Wrapper.Airbase#AIRBASE airbase (Optional) Search only parking spots at this airbase.
|
||||||
@@ -1433,25 +1594,6 @@ do -- COORDINATE
|
|||||||
local coord=COORDINATE:NewFromVec2(_vec2)
|
local coord=COORDINATE:NewFromVec2(_vec2)
|
||||||
|
|
||||||
Path[#Path+1]=coord
|
Path[#Path+1]=coord
|
||||||
|
|
||||||
if MarkPath then
|
|
||||||
coord:MarkToAll(string.format("Path segment %d.", _i))
|
|
||||||
end
|
|
||||||
if SmokePath then
|
|
||||||
coord:SmokeGreen()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Mark/smoke endpoints
|
|
||||||
if IncludeEndpoints then
|
|
||||||
if MarkPath then
|
|
||||||
COORDINATE:NewFromVec2(path[1]):MarkToAll("Path Initinal Point")
|
|
||||||
COORDINATE:NewFromVec2(path[1]):MarkToAll("Path Final Point")
|
|
||||||
end
|
|
||||||
if SmokePath then
|
|
||||||
COORDINATE:NewFromVec2(path[1]):SmokeBlue()
|
|
||||||
COORDINATE:NewFromVec2(path[#path]):SmokeBlue()
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
@@ -1464,6 +1606,23 @@ do -- COORDINATE
|
|||||||
Path[#Path+1]=ToCoord
|
Path[#Path+1]=ToCoord
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Mark or smoke.
|
||||||
|
if MarkPath or SmokePath then
|
||||||
|
for i,c in pairs(Path) do
|
||||||
|
local coord=c --#COORDINATE
|
||||||
|
if MarkPath then
|
||||||
|
coord:MarkToAll(string.format("Path segment %d", i))
|
||||||
|
end
|
||||||
|
if SmokePath then
|
||||||
|
if i==1 or i==#Path then
|
||||||
|
coord:SmokeBlue()
|
||||||
|
else
|
||||||
|
coord:SmokeGreen()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- Sum up distances.
|
-- Sum up distances.
|
||||||
if #Path>=2 then
|
if #Path>=2 then
|
||||||
for i=1,#Path-1 do
|
for i=1,#Path-1 do
|
||||||
@@ -1471,7 +1630,7 @@ do -- COORDINATE
|
|||||||
end
|
end
|
||||||
else
|
else
|
||||||
-- There are cases where no path on road can be found.
|
-- There are cases where no path on road can be found.
|
||||||
return nil,nil
|
return nil,nil,false
|
||||||
end
|
end
|
||||||
|
|
||||||
return Path, Way, GotPath
|
return Path, Way, GotPath
|
||||||
@@ -1828,15 +1987,18 @@ do -- COORDINATE
|
|||||||
--- Returns if a Coordinate has Line of Sight (LOS) with the ToCoordinate.
|
--- Returns if a Coordinate has Line of Sight (LOS) with the ToCoordinate.
|
||||||
-- @param #COORDINATE self
|
-- @param #COORDINATE self
|
||||||
-- @param #COORDINATE ToCoordinate
|
-- @param #COORDINATE ToCoordinate
|
||||||
|
-- @param #number Offset Height offset in meters. Default 2 m.
|
||||||
-- @return #boolean true If the ToCoordinate has LOS with the Coordinate, otherwise false.
|
-- @return #boolean true If the ToCoordinate has LOS with the Coordinate, otherwise false.
|
||||||
function COORDINATE:IsLOS( ToCoordinate )
|
function COORDINATE:IsLOS( ToCoordinate, Offset )
|
||||||
|
|
||||||
|
Offset=Offset or 2
|
||||||
|
|
||||||
-- Measurement of visibility should not be from the ground, so Adding a hypotethical 2 meters to each Coordinate.
|
-- Measurement of visibility should not be from the ground, so Adding a hypotethical 2 meters to each Coordinate.
|
||||||
local FromVec3 = self:GetVec3()
|
local FromVec3 = self:GetVec3()
|
||||||
FromVec3.y = FromVec3.y + 2
|
FromVec3.y = FromVec3.y + Offset
|
||||||
|
|
||||||
local ToVec3 = ToCoordinate:GetVec3()
|
local ToVec3 = ToCoordinate:GetVec3()
|
||||||
ToVec3.y = ToVec3.y + 2
|
ToVec3.y = ToVec3.y + Offset
|
||||||
|
|
||||||
local IsLOS = land.isVisible( FromVec3, ToVec3 )
|
local IsLOS = land.isVisible( FromVec3, ToVec3 )
|
||||||
|
|
||||||
@@ -1876,6 +2038,296 @@ do -- COORDINATE
|
|||||||
return InSphere
|
return InSphere
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Get sun rise time for a specific date at the coordinate.
|
||||||
|
-- @param #COORDINATE self
|
||||||
|
-- @param #number Day The day.
|
||||||
|
-- @param #number Month The month.
|
||||||
|
-- @param #number Year The year.
|
||||||
|
-- @param #boolean InSeconds If true, return the sun rise time in seconds.
|
||||||
|
-- @return #string Sunrise time, e.g. "05:41".
|
||||||
|
function COORDINATE:GetSunriseAtDate(Day, Month, Year, InSeconds)
|
||||||
|
|
||||||
|
-- Day of the year.
|
||||||
|
local DayOfYear=UTILS.GetDayOfYear(Year, Month, Day)
|
||||||
|
|
||||||
|
local Latitude, Longitude=self:GetLLDDM()
|
||||||
|
|
||||||
|
local Tdiff=UTILS.GMTToLocalTimeDifference()
|
||||||
|
|
||||||
|
local sunrise=UTILS.GetSunRiseAndSet(DayOfYear, Latitude, Longitude, true, Tdiff)
|
||||||
|
|
||||||
|
if InSeconds then
|
||||||
|
return sunrise
|
||||||
|
else
|
||||||
|
return UTILS.SecondsToClock(sunrise, true)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get sun rise time for a specific day of the year at the coordinate.
|
||||||
|
-- @param #COORDINATE self
|
||||||
|
-- @param #number DayOfYear The day of the year.
|
||||||
|
-- @param #boolean InSeconds If true, return the sun rise time in seconds.
|
||||||
|
-- @return #string Sunrise time, e.g. "05:41".
|
||||||
|
function COORDINATE:GetSunriseAtDayOfYear(DayOfYear, InSeconds)
|
||||||
|
|
||||||
|
local Latitude, Longitude=self:GetLLDDM()
|
||||||
|
|
||||||
|
local Tdiff=UTILS.GMTToLocalTimeDifference()
|
||||||
|
|
||||||
|
local sunrise=UTILS.GetSunRiseAndSet(DayOfYear, Latitude, Longitude, true, Tdiff)
|
||||||
|
|
||||||
|
if InSeconds then
|
||||||
|
return sunrise
|
||||||
|
else
|
||||||
|
return UTILS.SecondsToClock(sunrise, true)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get todays sun rise time.
|
||||||
|
-- @param #COORDINATE self
|
||||||
|
-- @param #boolean InSeconds If true, return the sun rise time in seconds.
|
||||||
|
-- @return #string Sunrise time, e.g. "05:41".
|
||||||
|
function COORDINATE:GetSunrise(InSeconds)
|
||||||
|
|
||||||
|
-- Get current day of the year.
|
||||||
|
local DayOfYear=UTILS.GetMissionDayOfYear()
|
||||||
|
|
||||||
|
-- Lat and long at this point.
|
||||||
|
local Latitude, Longitude=self:GetLLDDM()
|
||||||
|
|
||||||
|
-- GMT time diff.
|
||||||
|
local Tdiff=UTILS.GMTToLocalTimeDifference()
|
||||||
|
|
||||||
|
-- Sunrise in seconds of the day.
|
||||||
|
local sunrise=UTILS.GetSunRiseAndSet(DayOfYear, Latitude, Longitude, true, Tdiff)
|
||||||
|
|
||||||
|
local date=UTILS.GetDCSMissionDate()
|
||||||
|
|
||||||
|
-- Debug output.
|
||||||
|
--self:I(string.format("Sun rise at lat=%.3f long=%.3f on %s (DayOfYear=%d): %s (%d sec of the day) (GMT %d)", Latitude, Longitude, date, DayOfYear, tostring(UTILS.SecondsToClock(sunrise)), sunrise, Tdiff))
|
||||||
|
|
||||||
|
if InSeconds then
|
||||||
|
return sunrise
|
||||||
|
else
|
||||||
|
return UTILS.SecondsToClock(sunrise, true)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get minutes until the next sun rise at this coordinate.
|
||||||
|
-- @param #COORDINATE self
|
||||||
|
-- @param OnlyToday If true, only calculate the sun rise of today. If sun has already risen, the time in negative minutes since sunrise is reported.
|
||||||
|
-- @return #number Minutes to the next sunrise.
|
||||||
|
function COORDINATE:GetMinutesToSunrise(OnlyToday)
|
||||||
|
|
||||||
|
-- Seconds of today
|
||||||
|
local time=UTILS.SecondsOfToday()
|
||||||
|
|
||||||
|
-- Next Sunrise in seconds.
|
||||||
|
local sunrise=nil
|
||||||
|
|
||||||
|
-- Time to sunrise.
|
||||||
|
local delta=nil
|
||||||
|
|
||||||
|
if OnlyToday then
|
||||||
|
|
||||||
|
---
|
||||||
|
-- Sunrise of today
|
||||||
|
---
|
||||||
|
|
||||||
|
sunrise=self:GetSunrise(true)
|
||||||
|
|
||||||
|
delta=sunrise-time
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
---
|
||||||
|
-- Sunrise of tomorrow
|
||||||
|
---
|
||||||
|
|
||||||
|
-- Tomorrows day of the year.
|
||||||
|
local DayOfYear=UTILS.GetMissionDayOfYear()+1
|
||||||
|
|
||||||
|
local Latitude, Longitude=self:GetLLDDM()
|
||||||
|
|
||||||
|
local Tdiff=UTILS.GMTToLocalTimeDifference()
|
||||||
|
|
||||||
|
sunrise=UTILS.GetSunRiseAndSet(DayOfYear, Latitude, Longitude, true, Tdiff)
|
||||||
|
|
||||||
|
delta=sunrise+UTILS.SecondsToMidnight()
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
return delta/60
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Check if it is day, i.e. if the sun has risen about the horizon at this coordinate.
|
||||||
|
-- @param #COORDINATE self
|
||||||
|
-- @param #string Clock (Optional) Time in format "HH:MM:SS+D", e.g. "05:40:00+3" to check if is day at 5:40 at third day after mission start. Default is to check right now.
|
||||||
|
-- @return #boolean If true, it is day. If false, it is night time.
|
||||||
|
function COORDINATE:IsDay(Clock)
|
||||||
|
|
||||||
|
if Clock then
|
||||||
|
|
||||||
|
local Time=UTILS.ClockToSeconds(Clock)
|
||||||
|
|
||||||
|
local clock=UTILS.Split(Clock, "+")[1]
|
||||||
|
|
||||||
|
-- Tomorrows day of the year.
|
||||||
|
local DayOfYear=UTILS.GetMissionDayOfYear(Time)
|
||||||
|
|
||||||
|
local Latitude, Longitude=self:GetLLDDM()
|
||||||
|
|
||||||
|
local Tdiff=UTILS.GMTToLocalTimeDifference()
|
||||||
|
|
||||||
|
local sunrise=UTILS.GetSunRiseAndSet(DayOfYear, Latitude, Longitude, true, Tdiff)
|
||||||
|
local sunset=UTILS.GetSunRiseAndSet(DayOfYear, Latitude, Longitude, false, Tdiff)
|
||||||
|
|
||||||
|
local time=UTILS.ClockToSeconds(clock)
|
||||||
|
|
||||||
|
-- Check if time is between sunrise and sunset.
|
||||||
|
if time>sunrise and time<=sunset then
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
-- Todays sun rise in sec.
|
||||||
|
local sunrise=self:GetSunrise(true)
|
||||||
|
|
||||||
|
-- Todays sun set in sec.
|
||||||
|
local sunset=self:GetSunset(true)
|
||||||
|
|
||||||
|
-- Seconds passed since midnight.
|
||||||
|
local time=UTILS.SecondsOfToday()
|
||||||
|
|
||||||
|
-- Check if time is between sunrise and sunset.
|
||||||
|
if time>sunrise and time<=sunset then
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Check if it is night, i.e. if the sun has set below the horizon at this coordinate.
|
||||||
|
-- @param #COORDINATE self
|
||||||
|
-- @param #string Clock (Optional) Time in format "HH:MM:SS+D", e.g. "05:40:00+3" to check if is night at 5:40 at third day after mission start. Default is to check right now.
|
||||||
|
-- @return #boolean If true, it is night. If false, it is day time.
|
||||||
|
function COORDINATE:IsNight(Clock)
|
||||||
|
return not self:IsDay(Clock)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get sun set time for a specific date at the coordinate.
|
||||||
|
-- @param #COORDINATE self
|
||||||
|
-- @param #number Day The day.
|
||||||
|
-- @param #number Month The month.
|
||||||
|
-- @param #number Year The year.
|
||||||
|
-- @param #boolean InSeconds If true, return the sun rise time in seconds.
|
||||||
|
-- @return #string Sunset time, e.g. "20:41".
|
||||||
|
function COORDINATE:GetSunsetAtDate(Day, Month, Year, InSeconds)
|
||||||
|
|
||||||
|
-- Day of the year.
|
||||||
|
local DayOfYear=UTILS.GetDayOfYear(Year, Month, Day)
|
||||||
|
|
||||||
|
local Latitude, Longitude=self:GetLLDDM()
|
||||||
|
|
||||||
|
local Tdiff=UTILS.GMTToLocalTimeDifference()
|
||||||
|
|
||||||
|
local sunset=UTILS.GetSunRiseAndSet(DayOfYear, Latitude, Longitude, false, Tdiff)
|
||||||
|
|
||||||
|
if InSeconds then
|
||||||
|
return sunset
|
||||||
|
else
|
||||||
|
return UTILS.SecondsToClock(sunset, true)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get todays sun set time.
|
||||||
|
-- @param #COORDINATE self
|
||||||
|
-- @param #boolean InSeconds If true, return the sun set time in seconds.
|
||||||
|
-- @return #string Sunrise time, e.g. "20:41".
|
||||||
|
function COORDINATE:GetSunset(InSeconds)
|
||||||
|
|
||||||
|
-- Get current day of the year.
|
||||||
|
local DayOfYear=UTILS.GetMissionDayOfYear()
|
||||||
|
|
||||||
|
-- Lat and long at this point.
|
||||||
|
local Latitude, Longitude=self:GetLLDDM()
|
||||||
|
|
||||||
|
-- GMT time diff.
|
||||||
|
local Tdiff=UTILS.GMTToLocalTimeDifference()
|
||||||
|
|
||||||
|
-- Sunrise in seconds of the day.
|
||||||
|
local sunrise=UTILS.GetSunRiseAndSet(DayOfYear, Latitude, Longitude, false, Tdiff)
|
||||||
|
|
||||||
|
local date=UTILS.GetDCSMissionDate()
|
||||||
|
|
||||||
|
-- Debug output.
|
||||||
|
--self:I(string.format("Sun set at lat=%.3f long=%.3f on %s (DayOfYear=%d): %s (%d sec of the day) (GMT %d)", Latitude, Longitude, date, DayOfYear, tostring(UTILS.SecondsToClock(sunrise)), sunrise, Tdiff))
|
||||||
|
|
||||||
|
if InSeconds then
|
||||||
|
return sunrise
|
||||||
|
else
|
||||||
|
return UTILS.SecondsToClock(sunrise, true)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get minutes until the next sun set at this coordinate.
|
||||||
|
-- @param #COORDINATE self
|
||||||
|
-- @param OnlyToday If true, only calculate the sun set of today. If sun has already set, the time in negative minutes since sunset is reported.
|
||||||
|
-- @return #number Minutes to the next sunrise.
|
||||||
|
function COORDINATE:GetMinutesToSunset(OnlyToday)
|
||||||
|
|
||||||
|
-- Seconds of today
|
||||||
|
local time=UTILS.SecondsOfToday()
|
||||||
|
|
||||||
|
-- Next Sunset in seconds.
|
||||||
|
local sunset=nil
|
||||||
|
|
||||||
|
-- Time to sunrise.
|
||||||
|
local delta=nil
|
||||||
|
|
||||||
|
if OnlyToday then
|
||||||
|
|
||||||
|
---
|
||||||
|
-- Sunset of today
|
||||||
|
---
|
||||||
|
|
||||||
|
sunset=self:GetSunset(true)
|
||||||
|
|
||||||
|
delta=sunset-time
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
---
|
||||||
|
-- Sunset of tomorrow
|
||||||
|
---
|
||||||
|
|
||||||
|
-- Tomorrows day of the year.
|
||||||
|
local DayOfYear=UTILS.GetMissionDayOfYear()+1
|
||||||
|
|
||||||
|
local Latitude, Longitude=self:GetLLDDM()
|
||||||
|
|
||||||
|
local Tdiff=UTILS.GMTToLocalTimeDifference()
|
||||||
|
|
||||||
|
sunset=UTILS.GetSunRiseAndSet(DayOfYear, Latitude, Longitude, false, Tdiff)
|
||||||
|
|
||||||
|
delta=sunset+UTILS.SecondsToMidnight()
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
return delta/60
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Return a BR string from a COORDINATE to the COORDINATE.
|
--- Return a BR string from a COORDINATE to the COORDINATE.
|
||||||
-- @param #COORDINATE self
|
-- @param #COORDINATE self
|
||||||
@@ -1943,6 +2395,14 @@ do -- COORDINATE
|
|||||||
return ""
|
return ""
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Get Latitude and Longitude in Degrees Decimal Minutes (DDM).
|
||||||
|
-- @param #COORDINATE self
|
||||||
|
-- @return #number Latitude in DDM.
|
||||||
|
-- @return #number Lontitude in DDM.
|
||||||
|
function COORDINATE:GetLLDDM()
|
||||||
|
return coord.LOtoLL( self:GetVec3() )
|
||||||
|
end
|
||||||
|
|
||||||
--- Provides a Lat Lon string in Degree Minute Second format.
|
--- Provides a Lat Lon string in Degree Minute Second format.
|
||||||
-- @param #COORDINATE self
|
-- @param #COORDINATE self
|
||||||
-- @param Core.Settings#SETTINGS Settings (optional) The settings. Can be nil, and in this case the default settings are used. If you want to specify your own settings, use the _SETTINGS object.
|
-- @param Core.Settings#SETTINGS Settings (optional) The settings. Can be nil, and in this case the default settings are used. If you want to specify your own settings, use the _SETTINGS object.
|
||||||
|
|||||||
@@ -429,7 +429,7 @@ BEACON = {
|
|||||||
-- @field #number VOR
|
-- @field #number VOR
|
||||||
-- @field #number DME
|
-- @field #number DME
|
||||||
-- @field #number VOR_DME
|
-- @field #number VOR_DME
|
||||||
-- @field #number TACAN
|
-- @field #number TACAN TACtical Air Navigation system.
|
||||||
-- @field #number VORTAC
|
-- @field #number VORTAC
|
||||||
-- @field #number RSBN
|
-- @field #number RSBN
|
||||||
-- @field #number BROADCAST_STATION
|
-- @field #number BROADCAST_STATION
|
||||||
@@ -440,45 +440,74 @@ BEACON = {
|
|||||||
-- @field #number ILS_NEAR_HOMER
|
-- @field #number ILS_NEAR_HOMER
|
||||||
-- @field #number ILS_LOCALIZER
|
-- @field #number ILS_LOCALIZER
|
||||||
-- @field #number ILS_GLIDESLOPE
|
-- @field #number ILS_GLIDESLOPE
|
||||||
|
-- @field #number PRMG_LOCALIZER
|
||||||
|
-- @field #number PRMG_GLIDESLOPE
|
||||||
|
-- @field #number ICLS Same as ICLS glideslope.
|
||||||
|
-- @field #number ICLS_LOCALIZER
|
||||||
|
-- @field #number ICLS_GLIDESLOPE
|
||||||
-- @field #number NAUTICAL_HOMER
|
-- @field #number NAUTICAL_HOMER
|
||||||
-- @field #number ICLS
|
|
||||||
BEACON.Type={
|
BEACON.Type={
|
||||||
NULL = 0,
|
NULL = 0,
|
||||||
VOR = 1,
|
VOR = 1,
|
||||||
DME = 2,
|
DME = 2,
|
||||||
VOR_DME = 3,
|
VOR_DME = 3,
|
||||||
TACAN = 4,
|
TACAN = 4,
|
||||||
VORTAC = 5,
|
VORTAC = 5,
|
||||||
RSBN = 32,
|
RSBN = 128,
|
||||||
BROADCAST_STATION = 1024,
|
BROADCAST_STATION = 1024,
|
||||||
HOMER = 8,
|
HOMER = 8,
|
||||||
AIRPORT_HOMER = 4104,
|
AIRPORT_HOMER = 4104,
|
||||||
AIRPORT_HOMER_WITH_MARKER = 4136,
|
AIRPORT_HOMER_WITH_MARKER = 4136,
|
||||||
ILS_FAR_HOMER = 16408,
|
ILS_FAR_HOMER = 16408,
|
||||||
ILS_NEAR_HOMER = 16456,
|
ILS_NEAR_HOMER = 16424,
|
||||||
ILS_LOCALIZER = 16640,
|
ILS_LOCALIZER = 16640,
|
||||||
ILS_GLIDESLOPE = 16896,
|
ILS_GLIDESLOPE = 16896,
|
||||||
NAUTICAL_HOMER = 32776,
|
PRMG_LOCALIZER = 33024,
|
||||||
ICLS = 131584,
|
PRMG_GLIDESLOPE = 33280,
|
||||||
|
ICLS = 131584, --leaving this in here but it is the same as ICLS_GLIDESLOPE
|
||||||
|
ICLS_LOCALIZER = 131328,
|
||||||
|
ICLS_GLIDESLOPE = 131584,
|
||||||
|
NAUTICAL_HOMER = 65536,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Beacon systems supported by DCS. https://wiki.hoggitworld.com/view/DCS_command_activateBeacon
|
--- Beacon systems supported by DCS. https://wiki.hoggitworld.com/view/DCS_command_activateBeacon
|
||||||
-- @type BEACON.System
|
-- @type BEACON.System
|
||||||
-- @field #number PAR_10
|
-- @field #number PAR_10 ?
|
||||||
-- @field #number RSBN_5
|
-- @field #number RSBN_5 Russian VOR/DME system.
|
||||||
-- @field #number TACAN
|
-- @field #number TACAN TACtical Air Navigation system on ground.
|
||||||
-- @field #number TACAN_TANKER
|
-- @field #number TACAN_TANKER_X TACtical Air Navigation system for tankers on X band.
|
||||||
-- @field #number ILS_LOCALIZER (This is the one to be used for AA TACAN Tanker!)
|
-- @field #number TACAN_TANKER_Y TACtical Air Navigation system for tankers on Y band.
|
||||||
-- @field #number ILS_GLIDESLOPE
|
-- @field #number VOR Very High Frequency Omni-Directional Range
|
||||||
-- @field #number BROADCAST_STATION
|
-- @field #number ILS_LOCALIZER ILS localizer
|
||||||
|
-- @field #number ILS_GLIDESLOPE ILS glideslope.
|
||||||
|
-- @field #number PRGM_LOCALIZER PRGM localizer.
|
||||||
|
-- @field #number PRGM_GLIDESLOPE PRGM glideslope.
|
||||||
|
-- @field #number BROADCAST_STATION Broadcast station.
|
||||||
|
-- @field #number VORTAC Radio-based navigational aid for aircraft pilots consisting of a co-located VHF omnidirectional range (VOR) beacon and a tactical air navigation system (TACAN) beacon.
|
||||||
|
-- @field #number TACAN_AA_MODE_X TACtical Air Navigation for aircraft on X band.
|
||||||
|
-- @field #number TACAN_AA_MODE_Y TACtical Air Navigation for aircraft on Y band.
|
||||||
|
-- @field #number VORDME Radio beacon that combines a VHF omnidirectional range (VOR) with a distance measuring equipment (DME).
|
||||||
|
-- @field #number ICLS_LOCALIZER Carrier landing system.
|
||||||
|
-- @field #number ICLS_GLIDESLOPE Carrier landing system.
|
||||||
BEACON.System={
|
BEACON.System={
|
||||||
PAR_10 = 1,
|
PAR_10 = 1,
|
||||||
RSBN_5 = 2,
|
RSBN_5 = 2,
|
||||||
TACAN = 3,
|
TACAN = 3,
|
||||||
TACAN_TANKER = 4,
|
TACAN_TANKER_X = 4,
|
||||||
ILS_LOCALIZER = 5,
|
TACAN_TANKER_Y = 5,
|
||||||
ILS_GLIDESLOPE = 6,
|
VOR = 6,
|
||||||
BROADCAST_STATION = 7,
|
ILS_LOCALIZER = 7,
|
||||||
|
ILS_GLIDESLOPE = 8,
|
||||||
|
PRMG_LOCALIZER = 9,
|
||||||
|
PRMG_GLIDESLOPE = 10,
|
||||||
|
BROADCAST_STATION = 11,
|
||||||
|
VORTAC = 12,
|
||||||
|
TACAN_AA_MODE_X = 13,
|
||||||
|
TACAN_AA_MODE_Y = 14,
|
||||||
|
VORDME = 15,
|
||||||
|
ICLS_LOCALIZER = 16,
|
||||||
|
ICLS_GLIDESLOPE = 17,
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Create a new BEACON Object. This doesn't activate the beacon, though, use @{#BEACON.ActivateTACAN} etc.
|
--- Create a new BEACON Object. This doesn't activate the beacon, though, use @{#BEACON.ActivateTACAN} etc.
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
--
|
--
|
||||||
-- @type RADIOQUEUE
|
-- @type RADIOQUEUE
|
||||||
-- @field #string ClassName Name of the class "RADIOQUEUE".
|
-- @field #string ClassName Name of the class "RADIOQUEUE".
|
||||||
-- @field #boolean Debug Debug mode. More info.
|
-- @field #boolean Debugmode Debug mode. More info.
|
||||||
-- @field #string lid ID for dcs.log.
|
-- @field #string lid ID for dcs.log.
|
||||||
-- @field #number frequency The radio frequency in Hz.
|
-- @field #number frequency The radio frequency in Hz.
|
||||||
-- @field #number modulation The radio modulation. Either radio.modulation.AM or radio.modulation.FM.
|
-- @field #number modulation The radio modulation. Either radio.modulation.AM or radio.modulation.FM.
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
-- @extends Core.Base#BASE
|
-- @extends Core.Base#BASE
|
||||||
RADIOQUEUE = {
|
RADIOQUEUE = {
|
||||||
ClassName = "RADIOQUEUE",
|
ClassName = "RADIOQUEUE",
|
||||||
Debug = nil,
|
Debugmode = nil,
|
||||||
lid = nil,
|
lid = nil,
|
||||||
frequency = nil,
|
frequency = nil,
|
||||||
modulation = nil,
|
modulation = nil,
|
||||||
@@ -55,7 +55,7 @@ RADIOQUEUE = {
|
|||||||
power = nil,
|
power = nil,
|
||||||
numbers = {},
|
numbers = {},
|
||||||
checking = nil,
|
checking = nil,
|
||||||
schedonce = nil,
|
schedonce = false,
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Radio queue transmission data.
|
--- Radio queue transmission data.
|
||||||
@@ -114,17 +114,19 @@ end
|
|||||||
-- @return #RADIOQUEUE self The RADIOQUEUE object.
|
-- @return #RADIOQUEUE self The RADIOQUEUE object.
|
||||||
function RADIOQUEUE:Start(delay, dt)
|
function RADIOQUEUE:Start(delay, dt)
|
||||||
|
|
||||||
|
-- Delay before start.
|
||||||
self.delay=delay or 1
|
self.delay=delay or 1
|
||||||
|
|
||||||
|
-- Time interval for queue check.
|
||||||
self.dt=dt or 0.01
|
self.dt=dt or 0.01
|
||||||
|
|
||||||
self:I(self.lid..string.format("Starting RADIOQUEUE %s on Frequency %.2f MHz [modulation=%d] in %.1f seconds (dt=%.3f sec)", self.alias, self.frequency/1000000, self.modulation, delay, dt))
|
-- Debug message.
|
||||||
|
self:I(self.lid..string.format("Starting RADIOQUEUE %s on Frequency %.2f MHz [modulation=%d] in %.1f seconds (dt=%.3f sec)", self.alias, self.frequency/1000000, self.modulation, self.delay, self.dt))
|
||||||
|
|
||||||
|
-- Start Scheduler.
|
||||||
if self.schedonce then
|
if self.schedonce then
|
||||||
self:_CheckRadioQueueDelayed(self.delta)
|
self:_CheckRadioQueueDelayed(delay)
|
||||||
else
|
else
|
||||||
--self.RQid=self.scheduler:Schedule(self, self._CheckRadioQueue, {}, delay, dt)
|
|
||||||
self.RQid=self.scheduler:Schedule(nil, RADIOQUEUE._CheckRadioQueue, {self}, delay, dt)
|
self.RQid=self.scheduler:Schedule(nil, RADIOQUEUE._CheckRadioQueue, {self}, delay, dt)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -351,13 +353,21 @@ function RADIOQUEUE:Broadcast(transmission)
|
|||||||
self.senderinit=true
|
self.senderinit=true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Set subtitle only if duration>0 sec.
|
||||||
|
local subtitle=nil
|
||||||
|
local duration=nil
|
||||||
|
if transmission.subtitle and transmission.subduration and transmission.subduration>0 then
|
||||||
|
subtitle=transmission.subtitle
|
||||||
|
duration=transmission.subduration
|
||||||
|
end
|
||||||
|
|
||||||
-- Command to tranmit the call.
|
-- Command to tranmit the call.
|
||||||
local commandTransmit={
|
local commandTransmit={
|
||||||
id = "TransmitMessage",
|
id = "TransmitMessage",
|
||||||
params = {
|
params = {
|
||||||
file=filename,
|
file=filename,
|
||||||
duration=transmission.subduration,
|
duration=duration,
|
||||||
subtitle=transmission.subtitle or "",
|
subtitle=subtitle,
|
||||||
loop=false,
|
loop=false,
|
||||||
}}
|
}}
|
||||||
|
|
||||||
@@ -365,8 +375,10 @@ function RADIOQUEUE:Broadcast(transmission)
|
|||||||
sender:SetCommand(commandTransmit)
|
sender:SetCommand(commandTransmit)
|
||||||
|
|
||||||
-- Debug message.
|
-- Debug message.
|
||||||
local text=string.format("file=%s, freq=%.2f MHz, duration=%.2f sec, subtitle=%s", filename, self.frequency/1000000, transmission.duration, transmission.subtitle or "")
|
if self.Debugmode then
|
||||||
MESSAGE:New(text, 2, "RADIOQUEUE "..self.alias):ToAllIf(self.Debug)
|
local text=string.format("file=%s, freq=%.2f MHz, duration=%.2f sec, subtitle=%s", filename, self.frequency/1000000, transmission.duration, transmission.subtitle or "")
|
||||||
|
MESSAGE:New(text, 2, "RADIOQUEUE "..self.alias):ToAll()
|
||||||
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
@@ -378,10 +390,7 @@ function RADIOQUEUE:Broadcast(transmission)
|
|||||||
|
|
||||||
-- Try to get positon from sender unit/static.
|
-- Try to get positon from sender unit/static.
|
||||||
if self.sendername then
|
if self.sendername then
|
||||||
local coord=self:_GetRadioSenderCoord()
|
vec3=self:_GetRadioSenderCoord()
|
||||||
if coord then
|
|
||||||
vec3=coord:GetVec3()
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Try to get fixed positon.
|
-- Try to get fixed positon.
|
||||||
@@ -398,8 +407,10 @@ function RADIOQUEUE:Broadcast(transmission)
|
|||||||
trigger.action.radioTransmission(filename, vec3, self.modulation, false, self.frequency, self.power)
|
trigger.action.radioTransmission(filename, vec3, self.modulation, false, self.frequency, self.power)
|
||||||
|
|
||||||
-- Debug message.
|
-- Debug message.
|
||||||
local text=string.format("file=%s, freq=%.2f MHz, duration=%.2f sec, subtitle=%s", filename, self.frequency/1000000, transmission.duration, transmission.subtitle or "")
|
if self.Debugmode then
|
||||||
MESSAGE:New(string.format(text, filename, transmission.duration, transmission.subtitle or ""), 5, "RADIOQUEUE "..self.alias):ToAllIf(self.Debug)
|
local text=string.format("file=%s, freq=%.2f MHz, duration=%.2f sec, subtitle=%s", filename, self.frequency/1000000, transmission.duration, transmission.subtitle or "")
|
||||||
|
MESSAGE:New(string.format(text, filename, transmission.duration, transmission.subtitle or ""), 5, "RADIOQUEUE "..self.alias):ToAll()
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
@@ -522,6 +533,7 @@ function RADIOQUEUE:_GetRadioSender()
|
|||||||
|
|
||||||
-- Try the general default.
|
-- Try the general default.
|
||||||
if self.sendername then
|
if self.sendername then
|
||||||
|
|
||||||
-- First try to find a unit
|
-- First try to find a unit
|
||||||
sender=UNIT:FindByName(self.sendername)
|
sender=UNIT:FindByName(self.sendername)
|
||||||
|
|
||||||
@@ -537,7 +549,7 @@ end
|
|||||||
|
|
||||||
--- Get unit from which we want to transmit a radio message. This has to be an aircraft for subtitles to work.
|
--- Get unit from which we want to transmit a radio message. This has to be an aircraft for subtitles to work.
|
||||||
-- @param #RADIOQUEUE self
|
-- @param #RADIOQUEUE self
|
||||||
-- @return Core.Point#COORDINATE Coordinate of the sender unit.
|
-- @return DCS#Vec3 Vector 3D.
|
||||||
function RADIOQUEUE:_GetRadioSenderCoord()
|
function RADIOQUEUE:_GetRadioSenderCoord()
|
||||||
|
|
||||||
local vec3=nil
|
local vec3=nil
|
||||||
@@ -550,7 +562,7 @@ function RADIOQUEUE:_GetRadioSenderCoord()
|
|||||||
|
|
||||||
-- Check that sender is alive and an aircraft.
|
-- Check that sender is alive and an aircraft.
|
||||||
if sender and sender:IsAlive() then
|
if sender and sender:IsAlive() then
|
||||||
return sender:GetCoordinate()
|
return sender:GetVec3()
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Now try a static.
|
-- Now try a static.
|
||||||
@@ -558,7 +570,7 @@ function RADIOQUEUE:_GetRadioSenderCoord()
|
|||||||
|
|
||||||
-- Check that sender is alive and an aircraft.
|
-- Check that sender is alive and an aircraft.
|
||||||
if sender then
|
if sender then
|
||||||
return sender:GetCoordinate()
|
return sender:GetVec3()
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
--
|
--
|
||||||
-- 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 thorought 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:
|
||||||
--
|
--
|
||||||
@@ -13,9 +13,10 @@
|
|||||||
-- - 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 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.
|
||||||
-- 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.
|
||||||
@@ -33,13 +34,41 @@
|
|||||||
-- @module Core.ScheduleDispatcher
|
-- @module Core.ScheduleDispatcher
|
||||||
-- @image Core_Schedule_Dispatcher.JPG
|
-- @image Core_Schedule_Dispatcher.JPG
|
||||||
|
|
||||||
|
--- SCHEDULEDISPATCHER class.
|
||||||
|
-- @type SCHEDULEDISPATCHER
|
||||||
|
-- @field #string ClassName Name of the class.
|
||||||
|
-- @field #number CallID Call ID counter.
|
||||||
|
-- @field #table PersistentSchedulers Persistant schedulers.
|
||||||
|
-- @field #table ObjectSchedulers Schedulers that only exist as long as the master object exists.
|
||||||
|
-- @field #table Schedule Meta table setmetatable( {}, { __mode = "k" } ).
|
||||||
|
-- @extends Core.Base#BASE
|
||||||
|
|
||||||
--- The SCHEDULEDISPATCHER structure
|
--- The SCHEDULEDISPATCHER structure
|
||||||
-- @type SCHEDULEDISPATCHER
|
-- @type SCHEDULEDISPATCHER
|
||||||
SCHEDULEDISPATCHER = {
|
SCHEDULEDISPATCHER = {
|
||||||
ClassName = "SCHEDULEDISPATCHER",
|
ClassName = "SCHEDULEDISPATCHER",
|
||||||
CallID = 0,
|
CallID = 0,
|
||||||
|
PersistentSchedulers = {},
|
||||||
|
ObjectSchedulers = {},
|
||||||
|
Schedule = nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
--- Player data table holding all important parameters of each player.
|
||||||
|
-- @type SCHEDULEDISPATCHER.ScheduleData
|
||||||
|
-- @field #function Function The schedule function to be called.
|
||||||
|
-- @field #table Arguments Schedule function arguments.
|
||||||
|
-- @field #number Start Start time in seconds.
|
||||||
|
-- @field #number Repeat Repeat time intervall in seconds.
|
||||||
|
-- @field #number Randomize Randomization factor [0,1].
|
||||||
|
-- @field #number Stop Stop time in seconds.
|
||||||
|
-- @field #number StartTime Time in seconds when the scheduler is created.
|
||||||
|
-- @field #number ScheduleID Schedule ID.
|
||||||
|
-- @field #function CallHandler Function to be passed to the DCS timer.scheduleFunction().
|
||||||
|
-- @field #boolean ShowTrace If true, show tracing info.
|
||||||
|
|
||||||
|
--- Create a new schedule dispatcher object.
|
||||||
|
-- @param #SCHEDULEDISPATCHER self
|
||||||
|
-- @return #SCHEDULEDISPATCHER self
|
||||||
function SCHEDULEDISPATCHER:New()
|
function SCHEDULEDISPATCHER:New()
|
||||||
local self = BASE:Inherit( self, BASE:New() )
|
local self = BASE:Inherit( self, BASE:New() )
|
||||||
self:F3()
|
self:F3()
|
||||||
@@ -51,15 +80,28 @@ end
|
|||||||
-- 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 nillified.
|
||||||
-- 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
|
-- @param Core.Scheduler#SCHEDULER Scheduler Scheduler object.
|
||||||
|
-- @param #function ScheduleFunction Scheduler function.
|
||||||
|
-- @param #table ScheduleArguments Table of arguments passed to the ScheduleFunction.
|
||||||
|
-- @param #number Start Start time in seconds.
|
||||||
|
-- @param #number Repeat Repeat interval in seconds.
|
||||||
|
-- @param #number Randomize Radomization factor [0,1].
|
||||||
|
-- @param #number Stop Stop time in seconds.
|
||||||
|
-- @param #number TraceLevel Trace level [0,3].
|
||||||
|
-- @param Core.Fsm#FSM Fsm Finite state model.
|
||||||
|
-- @return #string Call ID or nil.
|
||||||
function SCHEDULEDISPATCHER:AddSchedule( Scheduler, ScheduleFunction, ScheduleArguments, Start, Repeat, Randomize, Stop, TraceLevel, Fsm )
|
function SCHEDULEDISPATCHER:AddSchedule( Scheduler, ScheduleFunction, ScheduleArguments, Start, Repeat, Randomize, Stop, TraceLevel, Fsm )
|
||||||
self:F2( { Scheduler, ScheduleFunction, ScheduleArguments, Start, Repeat, Randomize, Stop, TraceLevel } )
|
self:F2( { Scheduler, ScheduleFunction, ScheduleArguments, Start, Repeat, Randomize, Stop, TraceLevel, Fsm } )
|
||||||
|
|
||||||
|
-- Increase counter.
|
||||||
self.CallID = self.CallID + 1
|
self.CallID = self.CallID + 1
|
||||||
|
|
||||||
|
-- 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 ""
|
||||||
|
|
||||||
-- Initialize the ObjectSchedulers array, which is a weakly coupled table.
|
self:T2(string.format("Adding schedule #%d CallID=%s", self.CallID, CallID))
|
||||||
-- If the object used as the key is nil, then the garbage collector will remove the item from the Functions array.
|
|
||||||
|
-- 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.
|
||||||
@@ -76,11 +118,11 @@ function SCHEDULEDISPATCHER:AddSchedule( Scheduler, ScheduleFunction, ScheduleAr
|
|||||||
|
|
||||||
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] = {}
|
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 + .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
|
||||||
@@ -118,15 +160,15 @@ function SCHEDULEDISPATCHER:AddSchedule( Scheduler, ScheduleFunction, ScheduleAr
|
|||||||
if name_fsm then
|
if name_fsm then
|
||||||
Info.name = name_fsm
|
Info.name = name_fsm
|
||||||
end
|
end
|
||||||
--env.info( debug.traceback() )
|
|
||||||
end
|
end
|
||||||
|
|
||||||
self:T3( self.Schedule[Scheduler][CallID] )
|
self:T3( self.Schedule[Scheduler][CallID] )
|
||||||
|
|
||||||
|
--- 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
|
local Info = Params.Info or {}
|
||||||
local Source = Info.source or "?"
|
local Source = Info.source or "?"
|
||||||
local Line = Info.currentline or "?"
|
local Line = Info.currentline or "?"
|
||||||
local Name = Info.name or "?"
|
local Name = Info.name or "?"
|
||||||
@@ -139,7 +181,8 @@ function SCHEDULEDISPATCHER:AddSchedule( Scheduler, ScheduleFunction, ScheduleAr
|
|||||||
return errmsg
|
return errmsg
|
||||||
end
|
end
|
||||||
|
|
||||||
local Scheduler = self.ObjectSchedulers[CallID]
|
-- Get object or persistant scheduler object.
|
||||||
|
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
|
||||||
@@ -149,20 +192,23 @@ function SCHEDULEDISPATCHER:AddSchedule( Scheduler, ScheduleFunction, ScheduleAr
|
|||||||
if Scheduler then
|
if Scheduler then
|
||||||
|
|
||||||
local MasterObject = tostring(Scheduler.MasterObject)
|
local MasterObject = tostring(Scheduler.MasterObject)
|
||||||
local Schedule = self.Schedule[Scheduler][CallID]
|
|
||||||
|
-- Schedule object.
|
||||||
|
local Schedule = self.Schedule[Scheduler][CallID] --#SCHEDULEDISPATCHER.ScheduleData
|
||||||
|
|
||||||
--self:T3( { Schedule = Schedule } )
|
--self:T3( { Schedule = Schedule } )
|
||||||
|
|
||||||
local SchedulerObject = Scheduler.SchedulerObject
|
local SchedulerObject = Scheduler.MasterObject --Scheduler.SchedulerObject Now is this the Maste or Scheduler object?
|
||||||
--local ScheduleObjectName = Scheduler.SchedulerObject:GetNameAndClassID()
|
local ShowTrace = Scheduler.ShowTrace
|
||||||
local ScheduleFunction = Schedule.Function
|
|
||||||
local ScheduleArguments = Schedule.Arguments
|
local ScheduleFunction = Schedule.Function
|
||||||
local Start = Schedule.Start
|
local ScheduleArguments = Schedule.Arguments or {}
|
||||||
local Repeat = Schedule.Repeat or 0
|
local Start = Schedule.Start
|
||||||
local Randomize = Schedule.Randomize or 0
|
local Repeat = Schedule.Repeat or 0
|
||||||
local Stop = Schedule.Stop or 0
|
local Randomize = Schedule.Randomize or 0
|
||||||
local ScheduleID = Schedule.ScheduleID
|
local Stop = Schedule.Stop or 0
|
||||||
local ShowTrace = Scheduler.ShowTrace
|
local ScheduleID = Schedule.ScheduleID
|
||||||
|
|
||||||
|
|
||||||
local Prefix = ( Repeat == 0 ) and "--->" or "+++>"
|
local Prefix = ( Repeat == 0 ) and "--->" or "+++>"
|
||||||
|
|
||||||
@@ -189,24 +235,20 @@ function SCHEDULEDISPATCHER:AddSchedule( Scheduler, ScheduleFunction, ScheduleAr
|
|||||||
local CurrentTime = timer.getTime()
|
local CurrentTime = timer.getTime()
|
||||||
local StartTime = Schedule.StartTime
|
local StartTime = Schedule.StartTime
|
||||||
|
|
||||||
self:F3( { Master = MasterObject, CurrentTime = CurrentTime, StartTime = StartTime, Start = Start, Repeat = Repeat, Randomize = Randomize, Stop = Stop } )
|
-- Debug info.
|
||||||
|
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 =
|
local ScheduleTime = CurrentTime + Repeat + math.random(- ( Randomize * Repeat / 2 ), ( Randomize * Repeat / 2 )) + 0.0001 -- Accuracy
|
||||||
CurrentTime +
|
|
||||||
Repeat +
|
|
||||||
math.random(
|
|
||||||
- ( Randomize * Repeat / 2 ),
|
|
||||||
( Randomize * Repeat / 2 )
|
|
||||||
) +
|
|
||||||
0.01
|
|
||||||
--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
|
||||||
@@ -222,6 +264,10 @@ function SCHEDULEDISPATCHER:AddSchedule( Scheduler, ScheduleFunction, ScheduleAr
|
|||||||
return CallID
|
return CallID
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Remove schedule.
|
||||||
|
-- @param #SCHEDULEDISPATCHER self
|
||||||
|
-- @param Core.Scheduler#SCHEDULER Scheduler Scheduler object.
|
||||||
|
-- @param #table CallID Call ID.
|
||||||
function SCHEDULEDISPATCHER:RemoveSchedule( Scheduler, CallID )
|
function SCHEDULEDISPATCHER:RemoveSchedule( Scheduler, CallID )
|
||||||
self:F2( { Remove = CallID, Scheduler = Scheduler } )
|
self:F2( { Remove = CallID, Scheduler = Scheduler } )
|
||||||
|
|
||||||
@@ -231,46 +277,80 @@ function SCHEDULEDISPATCHER:RemoveSchedule( Scheduler, CallID )
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Start dispatcher.
|
||||||
|
-- @param #SCHEDULEDISPATCHER self
|
||||||
|
-- @param Core.Scheduler#SCHEDULER Scheduler Scheduler object.
|
||||||
|
-- @param #table CallID (Optional) Call ID.
|
||||||
|
-- @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]
|
|
||||||
|
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[CallID].ScheduleID then
|
if not Schedule.ScheduleID then
|
||||||
Schedule[CallID].StartTime = timer.getTime() -- Set the StartTime field to indicate when the scheduler started.
|
|
||||||
Schedule[CallID].ScheduleID = timer.scheduleFunction(
|
-- Current time in seconds.
|
||||||
Schedule[CallID].CallHandler,
|
local Tnow=timer.getTime()
|
||||||
{ CallID = CallID, Info = Info },
|
|
||||||
timer.getTime() + Schedule[CallID].Start
|
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
|
||||||
|
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)))
|
||||||
end
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
|
-- 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
|
||||||
|
|
||||||
|
--- Stop dispatcher.
|
||||||
|
-- @param #SCHEDULEDISPATCHER self
|
||||||
|
-- @param Core.Scheduler#SCHEDULER Scheduler Scheduler object.
|
||||||
|
-- @param #table CallID Call ID.
|
||||||
function SCHEDULEDISPATCHER:Stop( Scheduler, CallID )
|
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]
|
|
||||||
-- Only stop when there is a ScheduleID defined for the CallID.
|
local Schedule = self.Schedule[Scheduler][CallID] --#SCHEDULEDISPATCHER.ScheduleData
|
||||||
-- So, when the scheduler was stopped before, do nothing.
|
|
||||||
if Schedule[CallID].ScheduleID then
|
-- Only stop when there is a ScheduleID defined for the CallID. So, when the scheduler was stopped before, do nothing.
|
||||||
timer.removeFunction( Schedule[CallID].ScheduleID )
|
if Schedule.ScheduleID then
|
||||||
Schedule[CallID].ScheduleID = nil
|
|
||||||
|
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
|
||||||
|
timer.removeFunction(Schedule.ScheduleID)
|
||||||
|
|
||||||
|
Schedule.ScheduleID = nil
|
||||||
|
|
||||||
|
else
|
||||||
|
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
|
||||||
|
|
||||||
|
--- Clear all schedules by stopping all dispatchers.
|
||||||
|
-- @param #SCHEDULEDISPATCHER self
|
||||||
|
-- @param Core.Scheduler#SCHEDULER Scheduler Scheduler object.
|
||||||
function SCHEDULEDISPATCHER:Clear( Scheduler )
|
function SCHEDULEDISPATCHER:Clear( Scheduler )
|
||||||
self:F2( { Scheduler = Scheduler } )
|
self:F2( { Scheduler = Scheduler } )
|
||||||
|
|
||||||
@@ -279,9 +359,19 @@ function SCHEDULEDISPATCHER:Clear( Scheduler )
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function SCHEDULEDISPATCHER:NoTrace( Scheduler )
|
--- Shopw tracing info.
|
||||||
|
-- @param #SCHEDULEDISPATCHER self
|
||||||
|
-- @param Core.Scheduler#SCHEDULER Scheduler Scheduler object.
|
||||||
|
function SCHEDULEDISPATCHER:ShowTrace( Scheduler )
|
||||||
self:F2( { Scheduler = Scheduler } )
|
self:F2( { Scheduler = Scheduler } )
|
||||||
|
Scheduler.ShowTrace = true
|
||||||
Scheduler.ShowTrace = nil
|
end
|
||||||
|
|
||||||
|
--- No tracing info.
|
||||||
|
-- @param #SCHEDULEDISPATCHER self
|
||||||
|
-- @param Core.Scheduler#SCHEDULER Scheduler Scheduler object.
|
||||||
|
function SCHEDULEDISPATCHER:NoTrace( Scheduler )
|
||||||
|
self:F2( { Scheduler = Scheduler } )
|
||||||
|
Scheduler.ShowTrace = false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,9 @@
|
|||||||
|
|
||||||
--- The SCHEDULER class
|
--- The SCHEDULER class
|
||||||
-- @type SCHEDULER
|
-- @type SCHEDULER
|
||||||
-- @field #number ScheduleID the ID of the scheduler.
|
-- @field #table Schedules Table of schedules.
|
||||||
|
-- @field #table MasterObject Master object.
|
||||||
|
-- @field #boolean ShowTrace Trace info if true.
|
||||||
-- @extends Core.Base#BASE
|
-- @extends Core.Base#BASE
|
||||||
|
|
||||||
|
|
||||||
@@ -69,53 +71,53 @@
|
|||||||
--
|
--
|
||||||
-- * @{#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.
|
||||||
--
|
--
|
||||||
-- SchedulerObject = SCHEDULER:New()
|
-- MasterObject = SCHEDULER:New()
|
||||||
-- SchedulerID = SchedulerObject:Schedule( nil, ScheduleFunction, {} )
|
-- SchedulerID = MasterObject:Schedule( nil, ScheduleFunction, {} )
|
||||||
--
|
--
|
||||||
-- The above example creates a new SchedulerObject, 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 SchedulerObject 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 nillified or destroyed, the SCHEDULER object will also be destroyed and stopped after garbage collection.
|
||||||
--
|
--
|
||||||
-- ZoneObject = ZONE:New( "ZoneName" )
|
-- ZoneObject = ZONE:New( "ZoneName" )
|
||||||
-- SchedulerObject = SCHEDULER:New( ZoneObject )
|
-- MasterObject = SCHEDULER:New( ZoneObject )
|
||||||
-- SchedulerID = SchedulerObject:Schedule( ZoneObject, ScheduleFunction, {} )
|
-- SchedulerID = MasterObject:Schedule( ZoneObject, ScheduleFunction, {} )
|
||||||
-- ...
|
-- ...
|
||||||
-- ZoneObject = nil
|
-- ZoneObject = nil
|
||||||
-- garbagecollect()
|
-- garbagecollect()
|
||||||
--
|
--
|
||||||
-- The above example creates a new SchedulerObject, 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 SchedulerObject 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 ScheduleObject 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.
|
||||||
--
|
--
|
||||||
-- SchedulerObject, SchedulerID = SCHEDULER:New( nil, ScheduleFunction, {} )
|
-- MasterObject, SchedulerID = SCHEDULER:New( nil, ScheduleFunction, {} )
|
||||||
--
|
--
|
||||||
-- The above example creates a new SchedulerObject, 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: SchedulerObject, 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" )
|
||||||
-- SchedulerObject, SchedulerID = SCHEDULER:New( ZoneObject, ScheduleFunction, {} )
|
-- MasterObject, SchedulerID = SCHEDULER:New( ZoneObject, ScheduleFunction, {} )
|
||||||
-- SchedulerID = SchedulerObject:Schedule( ZoneObject, ScheduleFunction, {} )
|
-- SchedulerID = MasterObject:Schedule( ZoneObject, ScheduleFunction, {} )
|
||||||
-- ...
|
-- ...
|
||||||
-- ZoneObject = nil
|
-- ZoneObject = nil
|
||||||
-- garbagecollect()
|
-- garbagecollect()
|
||||||
--
|
--
|
||||||
-- The above example creates a new SchedulerObject, 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 ScheduleObject 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 ScheduleObject 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.
|
||||||
--
|
--
|
||||||
@@ -125,15 +127,15 @@
|
|||||||
-- * @{#SCHEDULER.Stop}(): Stop the schedules within the SCHEDULER object. If a CallID is provided to :Stop(), then only the schedule referenced by CallID will be stopped.
|
-- * @{#SCHEDULER.Stop}(): Stop the schedules within the SCHEDULER object. If a CallID is provided to :Stop(), then only the schedule referenced by CallID will be stopped.
|
||||||
--
|
--
|
||||||
-- ZoneObject = ZONE:New( "ZoneName" )
|
-- ZoneObject = ZONE:New( "ZoneName" )
|
||||||
-- SchedulerObject, SchedulerID = SCHEDULER:New( ZoneObject, ScheduleFunction, {} )
|
-- MasterObject, SchedulerID = SCHEDULER:New( ZoneObject, ScheduleFunction, {} )
|
||||||
-- SchedulerID = SchedulerObject:Schedule( ZoneObject, ScheduleFunction, {}, 10, 10 )
|
-- SchedulerID = MasterObject:Schedule( ZoneObject, ScheduleFunction, {}, 10, 10 )
|
||||||
-- ...
|
-- ...
|
||||||
-- SchedulerObject:Stop( SchedulerID )
|
-- MasterObject:Stop( SchedulerID )
|
||||||
-- ...
|
-- ...
|
||||||
-- SchedulerObject:Start( SchedulerID )
|
-- MasterObject:Start( SchedulerID )
|
||||||
--
|
--
|
||||||
-- The above example creates a new SchedulerObject, 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: SchedulerObject, 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.
|
||||||
--
|
--
|
||||||
@@ -145,32 +147,32 @@
|
|||||||
-- 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" )
|
||||||
-- SchedulerObject = 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 behaviour of a Schedule.
|
||||||
--
|
--
|
||||||
-- ### A single schedule, immediately executed
|
-- ### A single schedule, immediately executed
|
||||||
--
|
--
|
||||||
-- SchedulerID = SchedulerObject: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 milleseconds ...
|
||||||
--
|
--
|
||||||
-- ### A single schedule, planned over time
|
-- ### A single schedule, planned over time
|
||||||
--
|
--
|
||||||
-- SchedulerID = SchedulerObject: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 = SchedulerObject: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 = SchedulerObject: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 ...
|
||||||
@@ -180,7 +182,7 @@
|
|||||||
--
|
--
|
||||||
-- ### 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 = SchedulerObject: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.
|
||||||
@@ -191,13 +193,15 @@
|
|||||||
--
|
--
|
||||||
-- @field #SCHEDULER
|
-- @field #SCHEDULER
|
||||||
SCHEDULER = {
|
SCHEDULER = {
|
||||||
ClassName = "SCHEDULER",
|
ClassName = "SCHEDULER",
|
||||||
Schedules = {},
|
Schedules = {},
|
||||||
|
MasterObject = nil,
|
||||||
|
ShowTrace = nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
--- SCHEDULER constructor.
|
--- SCHEDULER constructor.
|
||||||
-- @param #SCHEDULER self
|
-- @param #SCHEDULER self
|
||||||
-- @param #table SchedulerObject Specified for which Moose object the timer is setup. If a value of nil is provided, a scheduler will be setup without an object reference.
|
-- @param #table MasterObject Specified for which Moose object the timer is setup. If a value of nil is provided, a scheduler will be setup without an object reference.
|
||||||
-- @param #function SchedulerFunction The event function to be called when a timer event occurs. The event function needs to accept the parameters specified in SchedulerArguments.
|
-- @param #function SchedulerFunction The event function to be called when a timer event occurs. The event function needs to accept the parameters specified in SchedulerArguments.
|
||||||
-- @param #table SchedulerArguments Optional arguments that can be given as part of scheduler. The arguments need to be given as a table { param1, param 2, ... }.
|
-- @param #table SchedulerArguments Optional arguments that can be given as part of scheduler. The arguments need to be given as a table { param1, param 2, ... }.
|
||||||
-- @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.
|
||||||
@@ -205,51 +209,51 @@ SCHEDULER = {
|
|||||||
-- @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 Specifies the amount of seconds when the scheduler will be stopped.
|
-- @param #number Stop Specifies the amount of seconds when the scheduler will be stopped.
|
||||||
-- @return #SCHEDULER self.
|
-- @return #SCHEDULER self.
|
||||||
-- @return #number The ScheduleID of the planned schedule.
|
-- @return #table The ScheduleID of the planned schedule.
|
||||||
function SCHEDULER:New( SchedulerObject, 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 = SchedulerObject
|
self.MasterObject = MasterObject
|
||||||
self.ShowTrace = true
|
self.ShowTrace = false
|
||||||
|
|
||||||
if SchedulerFunction then
|
if SchedulerFunction then
|
||||||
ScheduleID = self:Schedule( SchedulerObject, SchedulerFunction, SchedulerArguments, Start, Repeat, RandomizeFactor, Stop, 4 )
|
ScheduleID = self:Schedule( MasterObject, SchedulerFunction, SchedulerArguments, Start, Repeat, RandomizeFactor, Stop, 3 )
|
||||||
end
|
end
|
||||||
|
|
||||||
return self, ScheduleID
|
return self, ScheduleID
|
||||||
end
|
end
|
||||||
|
|
||||||
--function SCHEDULER:_Destructor()
|
|
||||||
-- --self:E("_Destructor")
|
|
||||||
--
|
|
||||||
-- _SCHEDULEDISPATCHER:RemoveSchedule( self.CallID )
|
|
||||||
--end
|
|
||||||
|
|
||||||
--- Schedule a new time event. Note that the schedule will only take place if the scheduler is *started*. Even for a single schedule event, the scheduler needs to be started also.
|
--- Schedule a new time event. Note that the schedule will only take place if the scheduler is *started*. Even for a single schedule event, the scheduler needs to be started also.
|
||||||
-- @param #SCHEDULER self
|
-- @param #SCHEDULER self
|
||||||
-- @param #table SchedulerObject Specified for which Moose object the timer is setup. If a value of nil is provided, a scheduler will be setup without an object reference.
|
-- @param #table MasterObject Specified for which Moose object the timer is setup. If a value of nil is provided, a scheduler will be setup without an object reference.
|
||||||
-- @param #function SchedulerFunction The event function to be called when a timer event occurs. The event function needs to accept the parameters specified in SchedulerArguments.
|
-- @param #function SchedulerFunction The event function to be called when a timer event occurs. The event function needs to accept the parameters specified in SchedulerArguments.
|
||||||
-- @param #table SchedulerArguments Optional arguments that can be given as part of scheduler. The arguments need to be given as a table { param1, param 2, ... }.
|
-- @param #table SchedulerArguments Optional arguments that can be given as part of scheduler. The arguments need to be given as a table { param1, param 2, ... }.
|
||||||
-- @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 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 Specifies the amount of seconds when the scheduler will be stopped.
|
-- @param #number Stop Time interval in seconds after which the scheduler will be stoppe.
|
||||||
-- @return #number The ScheduleID of the planned schedule.
|
-- @param #number TraceLevel Trace level [0,3]. Default 3.
|
||||||
function SCHEDULER:Schedule( SchedulerObject, SchedulerFunction, SchedulerArguments, Start, Repeat, RandomizeFactor, Stop, TraceLevel, Fsm )
|
-- @param Core.Fsm#FSM Fsm Finite state model.
|
||||||
|
-- @return #table The ScheduleID of the planned schedule.
|
||||||
|
function SCHEDULER:Schedule( MasterObject, SchedulerFunction, SchedulerArguments, Start, Repeat, RandomizeFactor, Stop, TraceLevel, Fsm )
|
||||||
self:F2( { Start, Repeat, RandomizeFactor, Stop } )
|
self:F2( { Start, Repeat, RandomizeFactor, Stop } )
|
||||||
self:T3( { SchedulerArguments } )
|
self:T3( { SchedulerArguments } )
|
||||||
|
|
||||||
|
-- Debug info.
|
||||||
local ObjectName = "-"
|
local ObjectName = "-"
|
||||||
if SchedulerObject and SchedulerObject.ClassName and SchedulerObject.ClassID then
|
if MasterObject and MasterObject.ClassName and MasterObject.ClassID then
|
||||||
ObjectName = SchedulerObject.ClassName .. SchedulerObject.ClassID
|
ObjectName = MasterObject.ClassName .. MasterObject.ClassID
|
||||||
end
|
end
|
||||||
self:F3( { "Schedule :", ObjectName, tostring( SchedulerObject ), Start, Repeat, RandomizeFactor, Stop } )
|
self:F3( { "Schedule :", ObjectName, tostring( MasterObject ), Start, Repeat, RandomizeFactor, Stop } )
|
||||||
self.SchedulerObject = SchedulerObject
|
|
||||||
|
|
||||||
|
-- Set master object.
|
||||||
|
self.MasterObject = MasterObject
|
||||||
|
|
||||||
|
-- Add schedule.
|
||||||
local ScheduleID = _SCHEDULEDISPATCHER:AddSchedule(
|
local ScheduleID = _SCHEDULEDISPATCHER:AddSchedule(
|
||||||
self,
|
self,
|
||||||
SchedulerFunction,
|
SchedulerFunction,
|
||||||
@@ -269,57 +273,47 @@ end
|
|||||||
|
|
||||||
--- (Re-)Starts the schedules or a specific schedule if a valid ScheduleID is provided.
|
--- (Re-)Starts the schedules or a specific schedule if a valid ScheduleID is provided.
|
||||||
-- @param #SCHEDULER self
|
-- @param #SCHEDULER self
|
||||||
-- @param #number 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)))
|
||||||
_SCHEDULEDISPATCHER:Start( self, ScheduleID )
|
_SCHEDULEDISPATCHER:Start( self, ScheduleID )
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Stops the schedules or a specific schedule if a valid ScheduleID is provided.
|
--- Stops the schedules or a specific schedule if a valid ScheduleID is provided.
|
||||||
-- @param #SCHEDULER self
|
-- @param #SCHEDULER self
|
||||||
-- @param #number 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)))
|
||||||
_SCHEDULEDISPATCHER:Stop( self, ScheduleID )
|
_SCHEDULEDISPATCHER:Stop( self, ScheduleID )
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Removes a specific schedule if a valid ScheduleID is provided.
|
--- Removes a specific schedule if a valid ScheduleID is provided.
|
||||||
-- @param #SCHEDULER self
|
-- @param #SCHEDULER self
|
||||||
-- @param #number 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)))
|
||||||
_SCHEDULEDISPATCHER:Remove( 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"))
|
||||||
_SCHEDULEDISPATCHER:Clear( self )
|
_SCHEDULEDISPATCHER:Clear( self )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Show tracing for this scheduler.
|
||||||
|
-- @param #SCHEDULER self
|
||||||
|
function SCHEDULER:ShowTrace()
|
||||||
|
_SCHEDULEDISPATCHER:ShowTrace( self )
|
||||||
|
end
|
||||||
|
|
||||||
--- No tracing for this scheduler.
|
--- No tracing for this scheduler.
|
||||||
-- @param #SCHEDULER self
|
-- @param #SCHEDULER self
|
||||||
-- @param #number ScheduleID (optional) The ScheduleID of the planned (repeating) schedule.
|
|
||||||
function SCHEDULER:NoTrace()
|
function SCHEDULER:NoTrace()
|
||||||
|
|
||||||
_SCHEDULEDISPATCHER:NoTrace( self )
|
_SCHEDULEDISPATCHER:NoTrace( self )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@
|
|||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ### Author: **FlightControl**
|
-- ### Author: **FlightControl**
|
||||||
-- ### Contributions:
|
-- ### Contributions: **funkyfranky**
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
@@ -48,9 +48,10 @@
|
|||||||
do -- SET_BASE
|
do -- SET_BASE
|
||||||
|
|
||||||
--- @type SET_BASE
|
--- @type SET_BASE
|
||||||
-- @field #table Filter
|
-- @field #table Filter Table of filters.
|
||||||
-- @field #table Set
|
-- @field #table Set Table of objects.
|
||||||
-- @field #table List
|
-- @field #table Index Table of indicies.
|
||||||
|
-- @field #table List Unused table.
|
||||||
-- @field Core.Scheduler#SCHEDULER CallScheduler
|
-- @field Core.Scheduler#SCHEDULER CallScheduler
|
||||||
-- @extends Core.Base#BASE
|
-- @extends Core.Base#BASE
|
||||||
|
|
||||||
@@ -77,6 +78,10 @@ do -- SET_BASE
|
|||||||
Set = {},
|
Set = {},
|
||||||
List = {},
|
List = {},
|
||||||
Index = {},
|
Index = {},
|
||||||
|
Database = nil,
|
||||||
|
CallScheduler=nil,
|
||||||
|
TimeInterval=nil,
|
||||||
|
YieldInterval=nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -224,8 +229,8 @@ do -- SET_BASE
|
|||||||
|
|
||||||
--- Adds a @{Core.Base#BASE} object in the @{Core.Set#SET_BASE}, using a given ObjectName as the index.
|
--- Adds a @{Core.Base#BASE} object in the @{Core.Set#SET_BASE}, using a given ObjectName as the index.
|
||||||
-- @param #SET_BASE self
|
-- @param #SET_BASE self
|
||||||
-- @param #string ObjectName
|
-- @param #string ObjectName The name of the object.
|
||||||
-- @param Core.Base#BASE Object
|
-- @param Core.Base#BASE Object The object itself.
|
||||||
-- @return Core.Base#BASE The added BASE Object.
|
-- @return Core.Base#BASE The added BASE Object.
|
||||||
function SET_BASE:Add( ObjectName, Object )
|
function SET_BASE:Add( ObjectName, Object )
|
||||||
self:F2( { ObjectName = ObjectName, Object = Object } )
|
self:F2( { ObjectName = ObjectName, Object = Object } )
|
||||||
@@ -234,9 +239,14 @@ do -- SET_BASE
|
|||||||
if self.Set[ObjectName] then
|
if self.Set[ObjectName] then
|
||||||
self:Remove( ObjectName, true )
|
self:Remove( ObjectName, true )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Add object to set.
|
||||||
self.Set[ObjectName] = Object
|
self.Set[ObjectName] = Object
|
||||||
|
|
||||||
|
-- Add Object name to Index.
|
||||||
table.insert( self.Index, ObjectName )
|
table.insert( self.Index, ObjectName )
|
||||||
|
|
||||||
|
-- Trigger Added event.
|
||||||
self:Added( ObjectName, Object )
|
self:Added( ObjectName, Object )
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -254,6 +264,81 @@ do -- SET_BASE
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Get the *union* of two sets.
|
||||||
|
-- @param #SET_BASE self
|
||||||
|
-- @param Core.Set#SET_BASE SetB Set *B*.
|
||||||
|
-- @return Core.Set#SET_BASE The union set, i.e. contains objects that are in set *A* **or** in set *B*.
|
||||||
|
function SET_BASE:GetSetUnion(SetB)
|
||||||
|
|
||||||
|
local union=SET_BASE:New()
|
||||||
|
|
||||||
|
for _,ObjectA in pairs(self.Set) do
|
||||||
|
union:AddObject(ObjectA)
|
||||||
|
end
|
||||||
|
|
||||||
|
for _,ObjectB in pairs(SetB.Set) do
|
||||||
|
union:AddObject(ObjectB)
|
||||||
|
end
|
||||||
|
|
||||||
|
return union
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get the *intersection* of this set, called *A*, and another set.
|
||||||
|
-- @param #SET_BASE self
|
||||||
|
-- @param Core.Set#SET_BASE SetB Set other set, called *B*.
|
||||||
|
-- @return Core.Set#SET_BASE A set of objects that is included in set *A* **and** in set *B*.
|
||||||
|
function SET_BASE:GetSetIntersection(SetB)
|
||||||
|
|
||||||
|
local intersection=SET_BASE:New()
|
||||||
|
|
||||||
|
local union=self:GetSetUnion(SetB)
|
||||||
|
|
||||||
|
for _,Object in pairs(union.Set) do
|
||||||
|
if self:IsIncludeObject(Object) and SetB:IsIncludeObject(Object) then
|
||||||
|
intersection:AddObject(intersection)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return intersection
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get the *complement* of two sets.
|
||||||
|
-- @param #SET_BASE self
|
||||||
|
-- @param Core.Set#SET_BASE SetB Set other set, called *B*.
|
||||||
|
-- @return Core.Set#SET_BASE The set of objects that are in set *B* but **not** in this set *A*.
|
||||||
|
function SET_BASE:GetSetComplement(SetB)
|
||||||
|
|
||||||
|
local complement=SET_BASE:New()
|
||||||
|
|
||||||
|
local union=self:GetSetUnion(SetA, SetB)
|
||||||
|
|
||||||
|
for _,Object in pairs(union.Set) do
|
||||||
|
if SetA:IsIncludeObject(Object) and SetB:IsIncludeObject(Object) then
|
||||||
|
intersection:Add(intersection)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return intersection
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Compare two sets.
|
||||||
|
-- @param #SET_BASE self
|
||||||
|
-- @param Core.Set#SET_BASE SetA First set.
|
||||||
|
-- @param Core.Set#SET_BASE SetB Set to be merged into first set.
|
||||||
|
-- @return Core.Set#SET_BASE The set of objects that are included in SetA and SetB.
|
||||||
|
function SET_BASE:CompareSets(SetA, SetB)
|
||||||
|
|
||||||
|
for _,ObjectB in pairs(SetB.Set) do
|
||||||
|
if SetA:IsIncludeObject(ObjectB) then
|
||||||
|
SetA:Add(ObjectB)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return SetA
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--- Gets a @{Core.Base#BASE} object from the @{Core.Set#SET_BASE} and derived classes, based on the Object Name.
|
--- Gets a @{Core.Base#BASE} object from the @{Core.Set#SET_BASE} and derived classes, based on the Object Name.
|
||||||
@@ -712,7 +797,7 @@ do -- SET_BASE
|
|||||||
--end
|
--end
|
||||||
|
|
||||||
|
|
||||||
--- Decides whether to include the Object
|
--- Decides whether to include the Object.
|
||||||
-- @param #SET_BASE self
|
-- @param #SET_BASE self
|
||||||
-- @param #table Object
|
-- @param #table Object
|
||||||
-- @return #SET_BASE self
|
-- @return #SET_BASE self
|
||||||
@@ -722,6 +807,16 @@ do -- SET_BASE
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Decides whether to include the Object.
|
||||||
|
-- @param #SET_BASE self
|
||||||
|
-- @param #table Object
|
||||||
|
-- @return #SET_BASE self
|
||||||
|
function SET_BASE:IsInSet(ObjectName)
|
||||||
|
self:F3( Object )
|
||||||
|
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
--- Gets a string with all the object names.
|
--- Gets a string with all the object names.
|
||||||
-- @param #SET_BASE self
|
-- @param #SET_BASE self
|
||||||
-- @return #string A string with the names of the objects.
|
-- @return #string A string with the names of the objects.
|
||||||
@@ -965,7 +1060,7 @@ do -- SET_GROUP
|
|||||||
-- Note that for each unit in the group that is set, a default cargo bay limit is initialized.
|
-- Note that for each unit in the group that is set, a default cargo bay limit is initialized.
|
||||||
-- @param Core.Set#SET_GROUP self
|
-- @param Core.Set#SET_GROUP self
|
||||||
-- @param Wrapper.Group#GROUP group The group which should be added to the set.
|
-- @param Wrapper.Group#GROUP group The group which should be added to the set.
|
||||||
-- @return self
|
-- @return Core.Set#SET_GROUP self
|
||||||
function SET_GROUP:AddGroup( group )
|
function SET_GROUP:AddGroup( group )
|
||||||
|
|
||||||
self:Add( group:GetName(), group )
|
self:Add( group:GetName(), group )
|
||||||
@@ -981,7 +1076,7 @@ do -- SET_GROUP
|
|||||||
--- Add GROUP(s) to SET_GROUP.
|
--- Add GROUP(s) to SET_GROUP.
|
||||||
-- @param Core.Set#SET_GROUP self
|
-- @param Core.Set#SET_GROUP self
|
||||||
-- @param #string AddGroupNames A single name or an array of GROUP names.
|
-- @param #string AddGroupNames A single name or an array of GROUP names.
|
||||||
-- @return self
|
-- @return Core.Set#SET_GROUP self
|
||||||
function SET_GROUP:AddGroupsByName( AddGroupNames )
|
function SET_GROUP:AddGroupsByName( AddGroupNames )
|
||||||
|
|
||||||
local AddGroupNamesArray = ( type( AddGroupNames ) == "table" ) and AddGroupNames or { AddGroupNames }
|
local AddGroupNamesArray = ( type( AddGroupNames ) == "table" ) and AddGroupNames or { AddGroupNames }
|
||||||
@@ -996,7 +1091,7 @@ do -- SET_GROUP
|
|||||||
--- Remove GROUP(s) from SET_GROUP.
|
--- Remove GROUP(s) from SET_GROUP.
|
||||||
-- @param Core.Set#SET_GROUP self
|
-- @param Core.Set#SET_GROUP self
|
||||||
-- @param Wrapper.Group#GROUP RemoveGroupNames A single name or an array of GROUP names.
|
-- @param Wrapper.Group#GROUP RemoveGroupNames A single name or an array of GROUP names.
|
||||||
-- @return self
|
-- @return Core.Set#SET_GROUP self
|
||||||
function SET_GROUP:RemoveGroupsByName( RemoveGroupNames )
|
function SET_GROUP:RemoveGroupsByName( RemoveGroupNames )
|
||||||
|
|
||||||
local RemoveGroupNamesArray = ( type( RemoveGroupNames ) == "table" ) and RemoveGroupNames or { RemoveGroupNames }
|
local RemoveGroupNamesArray = ( type( RemoveGroupNames ) == "table" ) and RemoveGroupNames or { RemoveGroupNames }
|
||||||
@@ -1576,8 +1671,8 @@ do -- SET_GROUP
|
|||||||
|
|
||||||
--- Iterate the SET_GROUP and count how many GROUPs and UNITs are alive.
|
--- Iterate the SET_GROUP and count how many GROUPs and UNITs are alive.
|
||||||
-- @param #SET_GROUP self
|
-- @param #SET_GROUP self
|
||||||
-- @return #number The number of GROUPs completely in the Zone
|
-- @return #number The number of GROUPs alive.
|
||||||
-- @return #number The number of UNITS alive.
|
-- @return #number The number of UNITs alive.
|
||||||
function SET_GROUP:CountAlive()
|
function SET_GROUP:CountAlive()
|
||||||
local CountG = 0
|
local CountG = 0
|
||||||
local CountU = 0
|
local CountU = 0
|
||||||
@@ -1909,8 +2004,8 @@ do -- SET_UNIT
|
|||||||
|
|
||||||
--- Remove UNIT(s) from SET_UNIT.
|
--- Remove UNIT(s) from SET_UNIT.
|
||||||
-- @param Core.Set#SET_UNIT self
|
-- @param Core.Set#SET_UNIT self
|
||||||
-- @param Wrapper.Unit#UNIT RemoveUnitNames A single name or an array of UNIT names.
|
-- @param #table RemoveUnitNames A single name or an array of UNIT names.
|
||||||
-- @return self
|
-- @return Core.Set#SET_UNIT self
|
||||||
function SET_UNIT:RemoveUnitsByName( RemoveUnitNames )
|
function SET_UNIT:RemoveUnitsByName( RemoveUnitNames )
|
||||||
|
|
||||||
local RemoveUnitNamesArray = ( type( RemoveUnitNames ) == "table" ) and RemoveUnitNames or { RemoveUnitNames }
|
local RemoveUnitNamesArray = ( type( RemoveUnitNames ) == "table" ) and RemoveUnitNames or { RemoveUnitNames }
|
||||||
@@ -2080,7 +2175,23 @@ do -- SET_UNIT
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Iterate the SET_UNIT and count how many UNITs are alive.
|
||||||
|
-- @param #SET_UNIT self
|
||||||
|
-- @return #number The number of UNITs alive.
|
||||||
|
function SET_UNIT:CountAlive()
|
||||||
|
|
||||||
|
local Set = self:GetSet()
|
||||||
|
|
||||||
|
local CountU = 0
|
||||||
|
for UnitID, UnitData in pairs(Set) do -- For each GROUP in SET_GROUP
|
||||||
|
if UnitData and UnitData:IsAlive() then
|
||||||
|
CountU = CountU + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
return CountU
|
||||||
|
end
|
||||||
|
|
||||||
--- Starts the filtering.
|
--- Starts the filtering.
|
||||||
-- @param #SET_UNIT self
|
-- @param #SET_UNIT self
|
||||||
@@ -2186,20 +2297,6 @@ do -- SET_UNIT
|
|||||||
return IsNotInZone
|
return IsNotInZone
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Check if minimal one element of the SET_UNIT is in the Zone.
|
|
||||||
-- @param #SET_UNIT self
|
|
||||||
-- @param #function IteratorFunction The function that will be called when there is an alive UNIT in the SET_UNIT. The function needs to accept a UNIT parameter.
|
|
||||||
-- @return #SET_UNIT self
|
|
||||||
function SET_UNIT:ForEachUnitInZone( IteratorFunction, ... )
|
|
||||||
self:F2( arg )
|
|
||||||
|
|
||||||
self:ForEach( IteratorFunction, arg, self:GetSet() )
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -3113,6 +3210,24 @@ do -- SET_STATIC
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Iterate the SET_STATIC and count how many STATICSs are alive.
|
||||||
|
-- @param #SET_STATIC self
|
||||||
|
-- @return #number The number of UNITs alive.
|
||||||
|
function SET_STATIC:CountAlive()
|
||||||
|
|
||||||
|
local Set = self:GetSet()
|
||||||
|
|
||||||
|
local CountU = 0
|
||||||
|
for UnitID, UnitData in pairs(Set) do
|
||||||
|
if UnitData and UnitData:IsAlive() then
|
||||||
|
CountU = CountU + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
return CountU
|
||||||
|
end
|
||||||
|
|
||||||
--- Handles the Database to check on an event (birth) that the Object was added in the Database.
|
--- Handles the Database to check on an event (birth) that the Object was added in the Database.
|
||||||
-- This is required, because sometimes the _DATABASE birth event gets called later than the SET_BASE birth event!
|
-- This is required, because sometimes the _DATABASE birth event gets called later than the SET_BASE birth event!
|
||||||
-- @param #SET_STATIC self
|
-- @param #SET_STATIC self
|
||||||
@@ -3123,13 +3238,13 @@ do -- SET_STATIC
|
|||||||
self:F3( { Event } )
|
self:F3( { Event } )
|
||||||
|
|
||||||
if Event.IniObjectCategory == Object.Category.STATIC then
|
if Event.IniObjectCategory == Object.Category.STATIC then
|
||||||
if not self.Database[Event.IniDCSStaticName] then
|
if not self.Database[Event.IniDCSUnitName] then
|
||||||
self.Database[Event.IniDCSStaticName] = STATIC:Register( Event.IniDCSStaticName )
|
self.Database[Event.IniDCSUnitName] = STATIC:Register( Event.IniDCSUnitName )
|
||||||
self:T3( self.Database[Event.IniDCSStaticName] )
|
self:T3( self.Database[Event.IniDCSUnitName] )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return Event.IniDCSStaticName, self.Database[Event.IniDCSStaticName]
|
return Event.IniDCSUnitName, self.Database[Event.IniDCSUnitName]
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Handles the Database to check on any event that Object exists in the Database.
|
--- Handles the Database to check on any event that Object exists in the Database.
|
||||||
@@ -3139,10 +3254,10 @@ do -- SET_STATIC
|
|||||||
-- @return #string The name of the STATIC
|
-- @return #string The name of the STATIC
|
||||||
-- @return #table The STATIC
|
-- @return #table The STATIC
|
||||||
function SET_STATIC:FindInDatabase( Event )
|
function SET_STATIC:FindInDatabase( Event )
|
||||||
self:F2( { Event.IniDCSStaticName, self.Set[Event.IniDCSStaticName], Event } )
|
self:F2( { Event.IniDCSUnitName, self.Set[Event.IniDCSUnitName], Event } )
|
||||||
|
|
||||||
|
|
||||||
return Event.IniDCSStaticName, self.Set[Event.IniDCSStaticName]
|
return Event.IniDCSUnitName, self.Set[Event.IniDCSUnitName]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -213,6 +213,8 @@
|
|||||||
SETTINGS = {
|
SETTINGS = {
|
||||||
ClassName = "SETTINGS",
|
ClassName = "SETTINGS",
|
||||||
ShowPlayerMenu = true,
|
ShowPlayerMenu = true,
|
||||||
|
MenuShort = false,
|
||||||
|
MenuStatic = false,
|
||||||
}
|
}
|
||||||
|
|
||||||
SETTINGS.__Enum = {}
|
SETTINGS.__Enum = {}
|
||||||
@@ -261,6 +263,20 @@ do -- SETTINGS
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Set short text for menus on (*true*) or off (*false*).
|
||||||
|
-- Short text are better suited for, e.g., VR.
|
||||||
|
-- @param #SETTINGS self
|
||||||
|
-- @param #boolean onoff If *true* use short menu texts. If *false* long ones (default).
|
||||||
|
function SETTINGS:SetMenutextShort(onoff)
|
||||||
|
_SETTINGS.MenuShort = onoff
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set menu to be static.
|
||||||
|
-- @param #SETTINGS self
|
||||||
|
-- @param #boolean onoff If *true* menu is static. If *false* menu will be updated after changes (default).
|
||||||
|
function SETTINGS:SetMenuStatic(onoff)
|
||||||
|
_SETTINGS.MenuStatic = onoff
|
||||||
|
end
|
||||||
|
|
||||||
--- Sets the SETTINGS metric.
|
--- Sets the SETTINGS metric.
|
||||||
-- @param #SETTINGS self
|
-- @param #SETTINGS self
|
||||||
@@ -463,6 +479,8 @@ do -- SETTINGS
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- @param #SETTINGS self
|
--- @param #SETTINGS self
|
||||||
|
-- @param Wrapper.Group#GROUP MenuGroup Group for which to add menus.
|
||||||
|
-- @param #table RootMenu Root menu table
|
||||||
-- @return #SETTINGS
|
-- @return #SETTINGS
|
||||||
function SETTINGS:SetSystemMenu( MenuGroup, RootMenu )
|
function SETTINGS:SetSystemMenu( MenuGroup, RootMenu )
|
||||||
|
|
||||||
@@ -472,31 +490,66 @@ do -- SETTINGS
|
|||||||
|
|
||||||
local SettingsMenu = MENU_GROUP:New( MenuGroup, MenuText, RootMenu ):SetTime( MenuTime )
|
local SettingsMenu = MENU_GROUP:New( MenuGroup, MenuText, RootMenu ):SetTime( MenuTime )
|
||||||
|
|
||||||
local A2GCoordinateMenu = MENU_GROUP:New( MenuGroup, "A2G Coordinate System", SettingsMenu ):SetTime( MenuTime )
|
-------
|
||||||
|
-- A2G Coordinate System
|
||||||
|
-------
|
||||||
|
|
||||||
|
local text="A2G Coordinate System"
|
||||||
|
if _SETTINGS.MenuShort then
|
||||||
|
text="A2G Coordinates"
|
||||||
|
end
|
||||||
|
local A2GCoordinateMenu = MENU_GROUP:New( MenuGroup, text, SettingsMenu ):SetTime( MenuTime )
|
||||||
|
|
||||||
|
-- Set LL DMS
|
||||||
if not self:IsA2G_LL_DMS() then
|
if not self:IsA2G_LL_DMS() then
|
||||||
MENU_GROUP_COMMAND:New( MenuGroup, "Lat/Lon Degree Min Sec (LL DMS)", A2GCoordinateMenu, self.A2GMenuSystem, self, MenuGroup, RootMenu, "LL DMS" ):SetTime( MenuTime )
|
local text="Lat/Lon Degree Min Sec (LL DMS)"
|
||||||
|
if _SETTINGS.MenuShort then
|
||||||
|
text="LL DMS"
|
||||||
|
end
|
||||||
|
MENU_GROUP_COMMAND:New( MenuGroup, text, A2GCoordinateMenu, self.A2GMenuSystem, self, MenuGroup, RootMenu, "LL DMS" ):SetTime( MenuTime )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- 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)"
|
||||||
|
if _SETTINGS.MenuShort then
|
||||||
|
text="LL DDM"
|
||||||
|
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.
|
||||||
if self:IsA2G_LL_DDM() then
|
if self:IsA2G_LL_DDM() then
|
||||||
|
local text1="LL DDM Accuracy 1"
|
||||||
|
local text2="LL DDM Accuracy 2"
|
||||||
|
local text3="LL DDM Accuracy 3"
|
||||||
|
if _SETTINGS.MenuShort then
|
||||||
|
text1="LL DDM"
|
||||||
|
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 )
|
||||||
MENU_GROUP_COMMAND:New( MenuGroup, "LL DDM Accuracy 3", A2GCoordinateMenu, self.MenuLL_DDM_Accuracy, self, MenuGroup, RootMenu, 3 ):SetTime( MenuTime )
|
MENU_GROUP_COMMAND:New( MenuGroup, "LL DDM Accuracy 3", A2GCoordinateMenu, self.MenuLL_DDM_Accuracy, self, MenuGroup, RootMenu, 3 ):SetTime( MenuTime )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Set BR.
|
||||||
if not self:IsA2G_BR() then
|
if not self:IsA2G_BR() then
|
||||||
MENU_GROUP_COMMAND:New( MenuGroup, "Bearing, Range (BR)", A2GCoordinateMenu, self.A2GMenuSystem, self, MenuGroup, RootMenu, "BR" ):SetTime( MenuTime )
|
local text="Bearing, Range (BR)"
|
||||||
|
if _SETTINGS.MenuShort then
|
||||||
|
text="BR"
|
||||||
|
end
|
||||||
|
MENU_GROUP_COMMAND:New( MenuGroup, text , A2GCoordinateMenu, self.A2GMenuSystem, self, MenuGroup, RootMenu, "BR" ):SetTime( MenuTime )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Set MGRS.
|
||||||
if not self:IsA2G_MGRS() then
|
if not self:IsA2G_MGRS() then
|
||||||
MENU_GROUP_COMMAND:New( MenuGroup, "Military Grid (MGRS)", A2GCoordinateMenu, self.A2GMenuSystem, self, MenuGroup, RootMenu, "MGRS" ):SetTime( MenuTime )
|
local text="Military Grid (MGRS)"
|
||||||
|
if _SETTINGS.MenuShort then
|
||||||
|
text="MGRS"
|
||||||
|
end
|
||||||
|
MENU_GROUP_COMMAND:New( MenuGroup, text, A2GCoordinateMenu, self.A2GMenuSystem, self, MenuGroup, RootMenu, "MGRS" ):SetTime( MenuTime )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Set MGRS accuracy.
|
||||||
if self:IsA2G_MGRS() then
|
if self:IsA2G_MGRS() then
|
||||||
MENU_GROUP_COMMAND:New( MenuGroup, "MGRS Accuracy 1", A2GCoordinateMenu, self.MenuMGRS_Accuracy, self, MenuGroup, RootMenu, 1 ):SetTime( MenuTime )
|
MENU_GROUP_COMMAND:New( MenuGroup, "MGRS Accuracy 1", A2GCoordinateMenu, self.MenuMGRS_Accuracy, self, MenuGroup, RootMenu, 1 ):SetTime( MenuTime )
|
||||||
MENU_GROUP_COMMAND:New( MenuGroup, "MGRS Accuracy 2", A2GCoordinateMenu, self.MenuMGRS_Accuracy, self, MenuGroup, RootMenu, 2 ):SetTime( MenuTime )
|
MENU_GROUP_COMMAND:New( MenuGroup, "MGRS Accuracy 2", A2GCoordinateMenu, self.MenuMGRS_Accuracy, self, MenuGroup, RootMenu, 2 ):SetTime( MenuTime )
|
||||||
@@ -505,32 +558,61 @@ do -- SETTINGS
|
|||||||
MENU_GROUP_COMMAND:New( MenuGroup, "MGRS Accuracy 5", A2GCoordinateMenu, self.MenuMGRS_Accuracy, self, MenuGroup, RootMenu, 5 ):SetTime( MenuTime )
|
MENU_GROUP_COMMAND:New( MenuGroup, "MGRS Accuracy 5", A2GCoordinateMenu, self.MenuMGRS_Accuracy, self, MenuGroup, RootMenu, 5 ):SetTime( MenuTime )
|
||||||
end
|
end
|
||||||
|
|
||||||
local A2ACoordinateMenu = MENU_GROUP:New( MenuGroup, "A2A Coordinate System", SettingsMenu ):SetTime( MenuTime )
|
-------
|
||||||
|
-- A2A Coordinate System
|
||||||
|
-------
|
||||||
|
|
||||||
|
local text="A2A Coordinate System"
|
||||||
|
if _SETTINGS.MenuShort then
|
||||||
|
text="A2A Coordinates"
|
||||||
|
end
|
||||||
|
local A2ACoordinateMenu = MENU_GROUP:New( MenuGroup, text, SettingsMenu ):SetTime( MenuTime )
|
||||||
|
|
||||||
if not self:IsA2A_LL_DMS() then
|
if not self:IsA2A_LL_DMS() then
|
||||||
MENU_GROUP_COMMAND:New( MenuGroup, "Lat/Lon Degree Min Sec (LL DMS)", A2ACoordinateMenu, self.A2AMenuSystem, self, MenuGroup, RootMenu, "LL DMS" ):SetTime( MenuTime )
|
local text="Lat/Lon Degree Min Sec (LL DMS)"
|
||||||
|
if _SETTINGS.MenuShort then
|
||||||
|
text="LL DMS"
|
||||||
|
end
|
||||||
|
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
|
||||||
MENU_GROUP_COMMAND:New( MenuGroup, "Lat/Lon Degree Dec Min (LL DDM)", A2ACoordinateMenu, self.A2AMenuSystem, self, MenuGroup, RootMenu, "LL DDM" ):SetTime( MenuTime )
|
local text="Lat/Lon Degree Dec Min (LL DDM)"
|
||||||
|
if _SETTINGS.MenuShort then
|
||||||
|
text="LL DDM"
|
||||||
|
end
|
||||||
|
MENU_GROUP_COMMAND:New( MenuGroup, text, A2ACoordinateMenu, self.A2AMenuSystem, self, MenuGroup, RootMenu, "LL DDM" ):SetTime( MenuTime )
|
||||||
end
|
end
|
||||||
|
|
||||||
if self:IsA2A_LL_DDM() then
|
if self:IsA2A_LL_DDM() or self:IsA2A_LL_DMS() then
|
||||||
MENU_GROUP_COMMAND:New( MenuGroup, "LL DDM Accuracy 1", A2ACoordinateMenu, self.MenuLL_DDM_Accuracy, self, MenuGroup, RootMenu, 1 ):SetTime( MenuTime )
|
MENU_GROUP_COMMAND:New( MenuGroup, "LL Accuracy 0", A2ACoordinateMenu, self.MenuLL_DDM_Accuracy, self, MenuGroup, RootMenu, 0 ):SetTime( MenuTime )
|
||||||
MENU_GROUP_COMMAND:New( MenuGroup, "LL DDM Accuracy 2", A2ACoordinateMenu, self.MenuLL_DDM_Accuracy, self, MenuGroup, RootMenu, 2 ):SetTime( MenuTime )
|
MENU_GROUP_COMMAND:New( MenuGroup, "LL Accuracy 1", A2ACoordinateMenu, self.MenuLL_DDM_Accuracy, self, MenuGroup, RootMenu, 1 ):SetTime( MenuTime )
|
||||||
MENU_GROUP_COMMAND:New( MenuGroup, "LL DDM Accuracy 3", A2ACoordinateMenu, self.MenuLL_DDM_Accuracy, self, MenuGroup, RootMenu, 3 ):SetTime( MenuTime )
|
MENU_GROUP_COMMAND:New( MenuGroup, "LL Accuracy 2", A2ACoordinateMenu, self.MenuLL_DDM_Accuracy, self, MenuGroup, RootMenu, 2 ):SetTime( MenuTime )
|
||||||
|
MENU_GROUP_COMMAND:New( MenuGroup, "LL Accuracy 3", A2ACoordinateMenu, self.MenuLL_DDM_Accuracy, self, MenuGroup, RootMenu, 3 ):SetTime( MenuTime )
|
||||||
end
|
end
|
||||||
|
|
||||||
if not self:IsA2A_BULLS() then
|
if not self:IsA2A_BULLS() then
|
||||||
MENU_GROUP_COMMAND:New( MenuGroup, "Bullseye (BULLS)", A2ACoordinateMenu, self.A2AMenuSystem, self, MenuGroup, RootMenu, "BULLS" ):SetTime( MenuTime )
|
local text="Bullseye (BULLS)"
|
||||||
|
if _SETTINGS.MenuShort then
|
||||||
|
text="Bulls"
|
||||||
|
end
|
||||||
|
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
|
||||||
MENU_GROUP_COMMAND:New( MenuGroup, "Bearing Range Altitude Aspect (BRAA)", A2ACoordinateMenu, self.A2AMenuSystem, self, MenuGroup, RootMenu, "BRAA" ):SetTime( MenuTime )
|
local text="Bearing Range Altitude Aspect (BRAA)"
|
||||||
|
if _SETTINGS.MenuShort then
|
||||||
|
text="BRAA"
|
||||||
|
end
|
||||||
|
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
|
||||||
MENU_GROUP_COMMAND:New( MenuGroup, "Military Grid (MGRS)", A2ACoordinateMenu, self.A2AMenuSystem, self, MenuGroup, RootMenu, "MGRS" ):SetTime( MenuTime )
|
local text="Military Grid (MGRS)"
|
||||||
|
if _SETTINGS.MenuShort then
|
||||||
|
text="MGRS"
|
||||||
|
end
|
||||||
|
MENU_GROUP_COMMAND:New( MenuGroup, text, A2ACoordinateMenu, self.A2AMenuSystem, self, MenuGroup, RootMenu, "MGRS" ):SetTime( MenuTime )
|
||||||
end
|
end
|
||||||
|
|
||||||
if self:IsA2A_MGRS() then
|
if self:IsA2A_MGRS() then
|
||||||
@@ -541,17 +623,33 @@ 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 MetricsMenu = MENU_GROUP:New( MenuGroup, "Measures and Weights System", SettingsMenu ):SetTime( MenuTime )
|
local text="Measures and Weights System"
|
||||||
|
if _SETTINGS.MenuShort then
|
||||||
|
text="Unit System"
|
||||||
|
end
|
||||||
|
local MetricsMenu = MENU_GROUP:New( MenuGroup, text, SettingsMenu ):SetTime( MenuTime )
|
||||||
|
|
||||||
if self:IsMetric() then
|
if self:IsMetric() then
|
||||||
MENU_GROUP_COMMAND:New( MenuGroup, "Imperial (Miles,Feet)", MetricsMenu, self.MenuMWSystem, self, MenuGroup, RootMenu, false ):SetTime( MenuTime )
|
local text="Imperial (Miles,Feet)"
|
||||||
|
if _SETTINGS.MenuShort then
|
||||||
|
text="Imperial"
|
||||||
|
end
|
||||||
|
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
|
||||||
MENU_GROUP_COMMAND:New( MenuGroup, "Metric (Kilometers,Meters)", MetricsMenu, self.MenuMWSystem, self, MenuGroup, RootMenu, true ):SetTime( MenuTime )
|
local text="Metric (Kilometers,Meters)"
|
||||||
|
if _SETTINGS.MenuShort then
|
||||||
|
text="Metric"
|
||||||
|
end
|
||||||
|
MENU_GROUP_COMMAND:New( MenuGroup, text, MetricsMenu, self.MenuMWSystem, self, MenuGroup, RootMenu, true ):SetTime( MenuTime )
|
||||||
end
|
end
|
||||||
|
|
||||||
local MessagesMenu = MENU_GROUP:New( MenuGroup, "Messages and Reports", SettingsMenu ):SetTime( MenuTime )
|
local text="Messages and Reports"
|
||||||
|
if _SETTINGS.MenuShort then
|
||||||
|
text="Messages & Reports"
|
||||||
|
end
|
||||||
|
local MessagesMenu = MENU_GROUP:New( MenuGroup, text, SettingsMenu ):SetTime( MenuTime )
|
||||||
|
|
||||||
local UpdateMessagesMenu = MENU_GROUP:New( MenuGroup, "Update Messages", MessagesMenu ):SetTime( MenuTime )
|
local UpdateMessagesMenu = MENU_GROUP:New( MenuGroup, "Update Messages", MessagesMenu ):SetTime( MenuTime )
|
||||||
MENU_GROUP_COMMAND:New( MenuGroup, "Off", UpdateMessagesMenu, self.MenuMessageTimingsSystem, self, MenuGroup, RootMenu, MESSAGE.Type.Update, 0 ):SetTime( MenuTime )
|
MENU_GROUP_COMMAND:New( MenuGroup, "Off", UpdateMessagesMenu, self.MenuMessageTimingsSystem, self, MenuGroup, RootMenu, MESSAGE.Type.Update, 0 ):SetTime( MenuTime )
|
||||||
@@ -618,8 +716,6 @@ do -- SETTINGS
|
|||||||
self.ShowPlayerMenu = false
|
self.ShowPlayerMenu = false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--- Updates the menu of the player seated in the PlayerUnit.
|
--- Updates the menu of the player seated in the PlayerUnit.
|
||||||
-- @param #SETTINGS self
|
-- @param #SETTINGS self
|
||||||
-- @param Wrapper.Client#CLIENT PlayerUnit
|
-- @param Wrapper.Client#CLIENT PlayerUnit
|
||||||
@@ -636,124 +732,188 @@ do -- SETTINGS
|
|||||||
|
|
||||||
self.PlayerMenu = PlayerMenu
|
self.PlayerMenu = PlayerMenu
|
||||||
|
|
||||||
local A2GCoordinateMenu = MENU_GROUP:New( PlayerGroup, "A2G Coordinate System", PlayerMenu )
|
self:I(string.format("Setting menu for player %s", tostring(PlayerName)))
|
||||||
|
|
||||||
if not self:IsA2G_LL_DMS() then
|
local submenu = MENU_GROUP:New( PlayerGroup, "LL Accuracy", PlayerMenu )
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "Lat/Lon Degree Min Sec (LL DMS)", A2GCoordinateMenu, self.MenuGroupA2GSystem, self, PlayerUnit, PlayerGroup, PlayerName, "LL DMS" )
|
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 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 4 Decimals", submenu, self.MenuGroupLL_DDM_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 4 )
|
||||||
|
|
||||||
|
local submenu = MENU_GROUP:New( PlayerGroup, "MGRS Accuracy", PlayerMenu )
|
||||||
|
MENU_GROUP_COMMAND:New( PlayerGroup, "MRGS Accuracy 0", submenu, self.MenuGroupMGRS_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 0 )
|
||||||
|
MENU_GROUP_COMMAND:New( PlayerGroup, "MRGS Accuracy 1", submenu, self.MenuGroupMGRS_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 1 )
|
||||||
|
MENU_GROUP_COMMAND:New( PlayerGroup, "MRGS Accuracy 2", submenu, self.MenuGroupMGRS_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 2 )
|
||||||
|
MENU_GROUP_COMMAND:New( PlayerGroup, "MRGS Accuracy 3", submenu, self.MenuGroupMGRS_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 3 )
|
||||||
|
MENU_GROUP_COMMAND:New( PlayerGroup, "MRGS Accuracy 4", submenu, self.MenuGroupMGRS_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 4 )
|
||||||
|
MENU_GROUP_COMMAND:New( PlayerGroup, "MRGS Accuracy 5", submenu, self.MenuGroupMGRS_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 5 )
|
||||||
|
|
||||||
|
------
|
||||||
|
-- A2G Coordinate System
|
||||||
|
------
|
||||||
|
|
||||||
|
local text="A2G Coordinate System"
|
||||||
|
if _SETTINGS.MenuShort then
|
||||||
|
text="A2G Coordinates"
|
||||||
|
end
|
||||||
|
local A2GCoordinateMenu = MENU_GROUP:New( PlayerGroup, text, PlayerMenu )
|
||||||
|
|
||||||
|
if not self:IsA2G_LL_DMS() or _SETTINGS.MenuStatic then
|
||||||
|
local text="Lat/Lon Degree Min Sec (LL DMS)"
|
||||||
|
if _SETTINGS.MenuShort then
|
||||||
|
text="A2G LL DMS"
|
||||||
|
end
|
||||||
|
MENU_GROUP_COMMAND:New( PlayerGroup, text, A2GCoordinateMenu, self.MenuGroupA2GSystem, self, PlayerUnit, PlayerGroup, PlayerName, "LL DMS" )
|
||||||
end
|
end
|
||||||
|
|
||||||
if not self:IsA2G_LL_DDM() then
|
if not self:IsA2G_LL_DDM() or _SETTINGS.MenuStatic then
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "Lat/Lon Degree Dec Min (LL DDM)", A2GCoordinateMenu, self.MenuGroupA2GSystem, self, PlayerUnit, PlayerGroup, PlayerName, "LL DDM" )
|
local text="Lat/Lon Degree Dec Min (LL DDM)"
|
||||||
|
if _SETTINGS.MenuShort then
|
||||||
|
text="A2G LL DDM"
|
||||||
|
end
|
||||||
|
MENU_GROUP_COMMAND:New( PlayerGroup, text, A2GCoordinateMenu, self.MenuGroupA2GSystem, self, PlayerUnit, PlayerGroup, PlayerName, "LL DDM" )
|
||||||
end
|
end
|
||||||
|
|
||||||
if self:IsA2G_LL_DDM() then
|
if not self:IsA2G_BR() or _SETTINGS.MenuStatic then
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "LL DDM Accuracy 1", A2GCoordinateMenu, self.MenuGroupLL_DDM_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 1 )
|
local text="Bearing, Range (BR)"
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "LL DDM Accuracy 2", A2GCoordinateMenu, self.MenuGroupLL_DDM_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 2 )
|
if _SETTINGS.MenuShort then
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "LL DDM Accuracy 3", A2GCoordinateMenu, self.MenuGroupLL_DDM_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 3 )
|
text="A2G BR"
|
||||||
|
end
|
||||||
|
MENU_GROUP_COMMAND:New( PlayerGroup, text, A2GCoordinateMenu, self.MenuGroupA2GSystem, self, PlayerUnit, PlayerGroup, PlayerName, "BR" )
|
||||||
end
|
end
|
||||||
|
|
||||||
if not self:IsA2G_BR() then
|
if not self:IsA2G_MGRS() or _SETTINGS.MenuStatic then
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "Bearing, Range (BR)", A2GCoordinateMenu, self.MenuGroupA2GSystem, self, PlayerUnit, PlayerGroup, PlayerName, "BR" )
|
local text="Military Grid (MGRS)"
|
||||||
|
if _SETTINGS.MenuShort then
|
||||||
|
text="A2G MGRS"
|
||||||
|
end
|
||||||
|
MENU_GROUP_COMMAND:New( PlayerGroup, text, A2GCoordinateMenu, self.MenuGroupA2GSystem, self, PlayerUnit, PlayerGroup, PlayerName, "MGRS" )
|
||||||
end
|
end
|
||||||
|
|
||||||
if not self:IsA2G_MGRS() then
|
------
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "Military Grid (MGRS)", A2GCoordinateMenu, self.MenuGroupA2GSystem, self, PlayerUnit, PlayerGroup, PlayerName, "MGRS" )
|
-- A2A Coordinates Menu
|
||||||
|
------
|
||||||
|
|
||||||
|
local text="A2A Coordinate System"
|
||||||
|
if _SETTINGS.MenuShort then
|
||||||
|
text="A2A Coordinates"
|
||||||
|
end
|
||||||
|
local A2ACoordinateMenu = MENU_GROUP:New( PlayerGroup, text, PlayerMenu )
|
||||||
|
|
||||||
|
|
||||||
|
if not self:IsA2A_LL_DMS() or _SETTINGS.MenuStatic then
|
||||||
|
local text="Lat/Lon Degree Min Sec (LL DMS)"
|
||||||
|
if _SETTINGS.MenuShort then
|
||||||
|
text="A2A LL DMS"
|
||||||
|
end
|
||||||
|
MENU_GROUP_COMMAND:New( PlayerGroup, text, A2ACoordinateMenu, self.MenuGroupA2GSystem, self, PlayerUnit, PlayerGroup, PlayerName, "LL DMS" )
|
||||||
end
|
end
|
||||||
|
|
||||||
if self:IsA2G_MGRS() then
|
if not self:IsA2A_LL_DDM() or _SETTINGS.MenuStatic then
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "MGRS Accuracy 1", A2GCoordinateMenu, self.MenuGroupMGRS_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 1 )
|
local text="Lat/Lon Degree Dec Min (LL DDM)"
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "MGRS Accuracy 2", A2GCoordinateMenu, self.MenuGroupMGRS_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 2 )
|
if _SETTINGS.MenuShort then
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "MGRS Accuracy 3", A2GCoordinateMenu, self.MenuGroupMGRS_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 3 )
|
text="A2A LL DDM"
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "MGRS Accuracy 4", A2GCoordinateMenu, self.MenuGroupMGRS_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 4 )
|
end
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "MGRS Accuracy 5", A2GCoordinateMenu, self.MenuGroupMGRS_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 5 )
|
MENU_GROUP_COMMAND:New( PlayerGroup, text, A2ACoordinateMenu, self.MenuGroupA2ASystem, self, PlayerUnit, PlayerGroup, PlayerName, "LL DDM" )
|
||||||
end
|
end
|
||||||
|
|
||||||
local A2ACoordinateMenu = MENU_GROUP:New( PlayerGroup, "A2A Coordinate System", PlayerMenu )
|
if not self:IsA2A_BULLS() or _SETTINGS.MenuStatic then
|
||||||
|
local text="Bullseye (BULLS)"
|
||||||
|
if _SETTINGS.MenuShort then
|
||||||
if not self:IsA2A_LL_DMS() then
|
text="A2A BULLS"
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "Lat/Lon Degree Min Sec (LL DMS)", A2GCoordinateMenu, self.MenuGroupA2GSystem, self, PlayerUnit, PlayerGroup, PlayerName, "LL DMS" )
|
end
|
||||||
|
MENU_GROUP_COMMAND:New( PlayerGroup, text, A2ACoordinateMenu, self.MenuGroupA2ASystem, self, PlayerUnit, PlayerGroup, PlayerName, "BULLS" )
|
||||||
end
|
end
|
||||||
|
|
||||||
if not self:IsA2A_LL_DDM() then
|
if not self:IsA2A_BRAA() or _SETTINGS.MenuStatic then
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "Lat/Lon Degree Dec Min (LL DDM)", A2GCoordinateMenu, self.MenuGroupA2GSystem, self, PlayerUnit, PlayerGroup, PlayerName, "LL DDM" )
|
local text="Bearing Range Altitude Aspect (BRAA)"
|
||||||
|
if _SETTINGS.MenuShort then
|
||||||
|
text="A2A BRAA"
|
||||||
|
end
|
||||||
|
MENU_GROUP_COMMAND:New( PlayerGroup, text, A2ACoordinateMenu, self.MenuGroupA2ASystem, self, PlayerUnit, PlayerGroup, PlayerName, "BRAA" )
|
||||||
end
|
end
|
||||||
|
|
||||||
if self:IsA2A_LL_DDM() then
|
if not self:IsA2A_MGRS() or _SETTINGS.MenuStatic then
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "LL DDM Accuracy 1", A2GCoordinateMenu, self.MenuGroupLL_DDM_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 1 )
|
local text="Military Grid (MGRS)"
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "LL DDM Accuracy 2", A2GCoordinateMenu, self.MenuGroupLL_DDM_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 2 )
|
if _SETTINGS.MenuShort then
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "LL DDM Accuracy 3", A2GCoordinateMenu, self.MenuGroupLL_DDM_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 3 )
|
text="A2A MGRS"
|
||||||
|
end
|
||||||
|
MENU_GROUP_COMMAND:New( PlayerGroup, text, A2ACoordinateMenu, self.MenuGroupA2ASystem, self, PlayerUnit, PlayerGroup, PlayerName, "MGRS" )
|
||||||
end
|
end
|
||||||
|
|
||||||
if not self:IsA2A_BULLS() then
|
---
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "Bullseye (BULLS)", A2ACoordinateMenu, self.MenuGroupA2ASystem, self, PlayerUnit, PlayerGroup, PlayerName, "BULLS" )
|
-- Unit system
|
||||||
|
---
|
||||||
|
|
||||||
|
local text="Measures and Weights System"
|
||||||
|
if _SETTINGS.MenuShort then
|
||||||
|
text="Unit System"
|
||||||
|
end
|
||||||
|
local MetricsMenu = MENU_GROUP:New( PlayerGroup, text, PlayerMenu )
|
||||||
|
|
||||||
|
if self:IsMetric() or _SETTINGS.MenuStatic then
|
||||||
|
local text="Imperial (Miles,Feet)"
|
||||||
|
if _SETTINGS.MenuShort then
|
||||||
|
text="Imperial"
|
||||||
|
end
|
||||||
|
MENU_GROUP_COMMAND:New( PlayerGroup, text, MetricsMenu, self.MenuGroupMWSystem, self, PlayerUnit, PlayerGroup, PlayerName, false )
|
||||||
end
|
end
|
||||||
|
|
||||||
if not self:IsA2A_BRAA() then
|
if self:IsImperial() or _SETTINGS.MenuStatic then
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "Bearing Range Altitude Aspect (BRAA)", A2ACoordinateMenu, self.MenuGroupA2ASystem, self, PlayerUnit, PlayerGroup, PlayerName, "BRAA" )
|
local text="Metric (Kilometers,Meters)"
|
||||||
|
if _SETTINGS.MenuShort then
|
||||||
|
text="Metric"
|
||||||
|
end
|
||||||
|
MENU_GROUP_COMMAND:New( PlayerGroup, text, MetricsMenu, self.MenuGroupMWSystem, self, PlayerUnit, PlayerGroup, PlayerName, true )
|
||||||
end
|
end
|
||||||
|
|
||||||
if not self:IsA2A_MGRS() then
|
---
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "Military Grid (MGRS)", A2ACoordinateMenu, self.MenuGroupA2ASystem, self, PlayerUnit, PlayerGroup, PlayerName, "MGRS" )
|
-- Messages and Reports
|
||||||
|
---
|
||||||
|
|
||||||
|
local text="Messages and Reports"
|
||||||
|
if _SETTINGS.MenuShort then
|
||||||
|
text="Messages & Reports"
|
||||||
end
|
end
|
||||||
|
local MessagesMenu = MENU_GROUP:New( PlayerGroup, text, PlayerMenu )
|
||||||
if self:IsA2A_MGRS() then
|
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "Military Grid (MGRS) Accuracy 1", A2ACoordinateMenu, self.MenuGroupMGRS_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 1 )
|
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "Military Grid (MGRS) Accuracy 2", A2ACoordinateMenu, self.MenuGroupMGRS_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 2 )
|
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "Military Grid (MGRS) Accuracy 3", A2ACoordinateMenu, self.MenuGroupMGRS_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 3 )
|
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "Military Grid (MGRS) Accuracy 4", A2ACoordinateMenu, self.MenuGroupMGRS_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 4 )
|
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "Military Grid (MGRS) Accuracy 5", A2ACoordinateMenu, self.MenuGroupMGRS_AccuracySystem, self, PlayerUnit, PlayerGroup, PlayerName, 5 )
|
|
||||||
end
|
|
||||||
|
|
||||||
local MetricsMenu = MENU_GROUP:New( PlayerGroup, "Measures and Weights System", PlayerMenu )
|
|
||||||
|
|
||||||
if self:IsMetric() then
|
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "Imperial (Miles,Feet)", MetricsMenu, self.MenuGroupMWSystem, self, PlayerUnit, PlayerGroup, PlayerName, false )
|
|
||||||
end
|
|
||||||
|
|
||||||
if self:IsImperial() then
|
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "Metric (Kilometers,Meters)", MetricsMenu, self.MenuGroupMWSystem, self, PlayerUnit, PlayerGroup, PlayerName, true )
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
local MessagesMenu = MENU_GROUP:New( PlayerGroup, "Messages and Reports", PlayerMenu )
|
|
||||||
|
|
||||||
local UpdateMessagesMenu = MENU_GROUP:New( PlayerGroup, "Update Messages", MessagesMenu )
|
local UpdateMessagesMenu = MENU_GROUP:New( PlayerGroup, "Update Messages", MessagesMenu )
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "Off", UpdateMessagesMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Update, 0 )
|
MENU_GROUP_COMMAND:New( PlayerGroup, "Updates Off", UpdateMessagesMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Update, 0 )
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "5 seconds", UpdateMessagesMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Update, 5 )
|
MENU_GROUP_COMMAND:New( PlayerGroup, "Updates 5 sec", UpdateMessagesMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Update, 5 )
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "10 seconds", UpdateMessagesMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Update, 10 )
|
MENU_GROUP_COMMAND:New( PlayerGroup, "Updates 10 sec", UpdateMessagesMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Update, 10 )
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "15 seconds", UpdateMessagesMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Update, 15 )
|
MENU_GROUP_COMMAND:New( PlayerGroup, "Updates 15 sec", UpdateMessagesMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Update, 15 )
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "30 seconds", UpdateMessagesMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Update, 30 )
|
MENU_GROUP_COMMAND:New( PlayerGroup, "Updates 30 sec", UpdateMessagesMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Update, 30 )
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "1 minute", UpdateMessagesMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Update, 60 )
|
MENU_GROUP_COMMAND:New( PlayerGroup, "Updates 1 min", UpdateMessagesMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Update, 60 )
|
||||||
|
|
||||||
local InformationMessagesMenu = MENU_GROUP:New( PlayerGroup, "Information Messages", MessagesMenu )
|
local InformationMessagesMenu = MENU_GROUP:New( PlayerGroup, "Info Messages", MessagesMenu )
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "5 seconds", InformationMessagesMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Information, 5 )
|
MENU_GROUP_COMMAND:New( PlayerGroup, "Info 5 sec", InformationMessagesMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Information, 5 )
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "10 seconds", InformationMessagesMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Information, 10 )
|
MENU_GROUP_COMMAND:New( PlayerGroup, "Info 10 sec", InformationMessagesMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Information, 10 )
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "15 seconds", InformationMessagesMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Information, 15 )
|
MENU_GROUP_COMMAND:New( PlayerGroup, "Info 15 sec", InformationMessagesMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Information, 15 )
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "30 seconds", InformationMessagesMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Information, 30 )
|
MENU_GROUP_COMMAND:New( PlayerGroup, "Info 30 sec", InformationMessagesMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Information, 30 )
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "1 minute", InformationMessagesMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Information, 60 )
|
MENU_GROUP_COMMAND:New( PlayerGroup, "Info 1 min", InformationMessagesMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Information, 60 )
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "2 minutes", InformationMessagesMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Information, 120 )
|
MENU_GROUP_COMMAND:New( PlayerGroup, "Info 2 min", InformationMessagesMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Information, 120 )
|
||||||
|
|
||||||
local BriefingReportsMenu = MENU_GROUP:New( PlayerGroup, "Briefing Reports", MessagesMenu )
|
local BriefingReportsMenu = MENU_GROUP:New( PlayerGroup, "Briefing Reports", MessagesMenu )
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "15 seconds", BriefingReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Briefing, 15 )
|
MENU_GROUP_COMMAND:New( PlayerGroup, "Brief 15 sec", BriefingReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Briefing, 15 )
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "30 seconds", BriefingReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Briefing, 30 )
|
MENU_GROUP_COMMAND:New( PlayerGroup, "Brief 30 sec", BriefingReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Briefing, 30 )
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "1 minute", BriefingReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Briefing, 60 )
|
MENU_GROUP_COMMAND:New( PlayerGroup, "Brief 1 min", BriefingReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Briefing, 60 )
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "2 minutes", BriefingReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Briefing, 120 )
|
MENU_GROUP_COMMAND:New( PlayerGroup, "Brief 2 min", BriefingReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Briefing, 120 )
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "3 minutes", BriefingReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Briefing, 180 )
|
MENU_GROUP_COMMAND:New( PlayerGroup, "Brief 3 min", BriefingReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Briefing, 180 )
|
||||||
|
|
||||||
local OverviewReportsMenu = MENU_GROUP:New( PlayerGroup, "Overview Reports", MessagesMenu )
|
local OverviewReportsMenu = MENU_GROUP:New( PlayerGroup, "Overview Reports", MessagesMenu )
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "15 seconds", OverviewReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Overview, 15 )
|
MENU_GROUP_COMMAND:New( PlayerGroup, "Overview 15 sec", OverviewReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Overview, 15 )
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "30 seconds", OverviewReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Overview, 30 )
|
MENU_GROUP_COMMAND:New( PlayerGroup, "Overview 30 sec", OverviewReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Overview, 30 )
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "1 minute", OverviewReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Overview, 60 )
|
MENU_GROUP_COMMAND:New( PlayerGroup, "Overview 1 min", OverviewReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Overview, 60 )
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "2 minutes", OverviewReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Overview, 120 )
|
MENU_GROUP_COMMAND:New( PlayerGroup, "Overview 2 min", OverviewReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Overview, 120 )
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "3 minutes", OverviewReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Overview, 180 )
|
MENU_GROUP_COMMAND:New( PlayerGroup, "Overview 3 min", OverviewReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.Overview, 180 )
|
||||||
|
|
||||||
local DetailedReportsMenu = MENU_GROUP:New( PlayerGroup, "Detailed Reports", MessagesMenu )
|
local DetailedReportsMenu = MENU_GROUP:New( PlayerGroup, "Detailed Reports", MessagesMenu )
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "15 seconds", DetailedReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.DetailedReportsMenu, 15 )
|
MENU_GROUP_COMMAND:New( PlayerGroup, "Detailed 15 sec", DetailedReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.DetailedReportsMenu, 15 )
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "30 seconds", DetailedReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.DetailedReportsMenu, 30 )
|
MENU_GROUP_COMMAND:New( PlayerGroup, "Detailed 30 sec", DetailedReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.DetailedReportsMenu, 30 )
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "1 minute", DetailedReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.DetailedReportsMenu, 60 )
|
MENU_GROUP_COMMAND:New( PlayerGroup, "Detailed 1 min", DetailedReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.DetailedReportsMenu, 60 )
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "2 minutes", DetailedReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.DetailedReportsMenu, 120 )
|
MENU_GROUP_COMMAND:New( PlayerGroup, "Detailed 2 min", DetailedReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.DetailedReportsMenu, 120 )
|
||||||
MENU_GROUP_COMMAND:New( PlayerGroup, "3 minutes", DetailedReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.DetailedReportsMenu, 180 )
|
MENU_GROUP_COMMAND:New( PlayerGroup, "Detailed 3 min", DetailedReportsMenu, self.MenuGroupMessageTimingsSystem, self, PlayerUnit, PlayerGroup, PlayerName, MESSAGE.Type.DetailedReportsMenu, 180 )
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -822,40 +982,50 @@ do -- SETTINGS
|
|||||||
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 )
|
||||||
self:RemovePlayerMenu(PlayerUnit)
|
if _SETTINGS.MenuStatic==false then
|
||||||
self:SetPlayerMenu(PlayerUnit)
|
self:RemovePlayerMenu(PlayerUnit)
|
||||||
|
self:SetPlayerMenu(PlayerUnit)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #SETTINGS self
|
--- @param #SETTINGS self
|
||||||
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 )
|
||||||
self:RemovePlayerMenu(PlayerUnit)
|
if _SETTINGS.MenuStatic==false then
|
||||||
self:SetPlayerMenu(PlayerUnit)
|
self:RemovePlayerMenu(PlayerUnit)
|
||||||
|
self:SetPlayerMenu(PlayerUnit)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #SETTINGS self
|
--- @param #SETTINGS self
|
||||||
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: A2G LL format accuracy set to %d 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 )
|
||||||
self:RemovePlayerMenu(PlayerUnit)
|
if _SETTINGS.MenuStatic==false then
|
||||||
self:SetPlayerMenu(PlayerUnit)
|
self:RemovePlayerMenu(PlayerUnit)
|
||||||
|
self:SetPlayerMenu(PlayerUnit)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #SETTINGS self
|
--- @param #SETTINGS self
|
||||||
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: A2G 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 )
|
||||||
self:RemovePlayerMenu(PlayerUnit)
|
if _SETTINGS.MenuStatic==false then
|
||||||
self:SetPlayerMenu(PlayerUnit)
|
self:RemovePlayerMenu(PlayerUnit)
|
||||||
|
self:SetPlayerMenu(PlayerUnit)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #SETTINGS self
|
--- @param #SETTINGS self
|
||||||
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 )
|
||||||
self:RemovePlayerMenu(PlayerUnit)
|
if _SETTINGS.MenuStatic==false then
|
||||||
self:SetPlayerMenu(PlayerUnit)
|
self:RemovePlayerMenu(PlayerUnit)
|
||||||
|
self:SetPlayerMenu(PlayerUnit)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #SETTINGS self
|
--- @param #SETTINGS self
|
||||||
@@ -908,5 +1078,3 @@ do -- SETTINGS
|
|||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
-- * Spawn late activated.
|
-- * Spawn late activated.
|
||||||
-- * Spawn with or without an initial delay.
|
-- * Spawn with or without an initial delay.
|
||||||
-- * Respawn after landing, on the runway or at the ramp after engine shutdown.
|
-- * Respawn after landing, on the runway or at the ramp after engine shutdown.
|
||||||
-- * Spawn with custom heading.
|
-- * Spawn with custom heading, both for a group formation and for the units in the group.
|
||||||
-- * Spawn with different skills.
|
-- * Spawn with different skills.
|
||||||
-- * Spawn with different liveries.
|
-- * Spawn with different liveries.
|
||||||
-- * Spawn with an inner and outer radius to set the initial position.
|
-- * Spawn with an inner and outer radius to set the initial position.
|
||||||
@@ -214,9 +214,8 @@
|
|||||||
-- ### **Scheduled** spawning methods
|
-- ### **Scheduled** spawning methods
|
||||||
--
|
--
|
||||||
-- * @{#SPAWN.SpawnScheduled}(): Spawn groups at scheduled but randomized intervals.
|
-- * @{#SPAWN.SpawnScheduled}(): Spawn groups at scheduled but randomized intervals.
|
||||||
-- * @{#SPAWN.SpawnScheduledStart}(): Start or continue to spawn groups at scheduled time intervals.
|
--- * @{#SPAWN.SpawnScheduleStart}(): Start or continue to spawn groups at scheduled time intervals.
|
||||||
-- * @{#SPAWN.SpawnScheduledStop}(): Stop the spawning of groups at scheduled time intervals.
|
-- * @{#SPAWN.SpawnScheduleStop}(): Stop the spawning of groups at scheduled time intervals.
|
||||||
--
|
|
||||||
--
|
--
|
||||||
--
|
--
|
||||||
-- ## Retrieve alive GROUPs spawned by the SPAWN object
|
-- ## Retrieve alive GROUPs spawned by the SPAWN object
|
||||||
@@ -260,7 +259,7 @@
|
|||||||
-- immediately when :SpawnScheduled() is initiated. The methods @{#SPAWN.InitDelayOnOff}() and @{#SPAWN.InitDelayOn}() can be used to
|
-- immediately when :SpawnScheduled() is initiated. The methods @{#SPAWN.InitDelayOnOff}() and @{#SPAWN.InitDelayOn}() can be used to
|
||||||
-- activate a delay before the first @{Wrapper.Group} is spawned. For completeness, a method @{#SPAWN.InitDelayOff}() is also available, that
|
-- activate a delay before the first @{Wrapper.Group} is spawned. For completeness, a method @{#SPAWN.InitDelayOff}() is also available, that
|
||||||
-- can be used to switch off the initial delay. Because there is no delay by default, this method would only be used when a
|
-- can be used to switch off the initial delay. Because there is no delay by default, this method would only be used when a
|
||||||
-- @{#SPAWN.SpawnScheduledStop}() ; @{#SPAWN.SpawnScheduledStart}() sequence would have been used.
|
-- @{#SPAWN.SpawnScheduleStop}() ; @{#SPAWN.SpawnScheduleStart}() sequence would have been used.
|
||||||
--
|
--
|
||||||
--
|
--
|
||||||
-- @field #SPAWN SPAWN
|
-- @field #SPAWN SPAWN
|
||||||
@@ -326,6 +325,8 @@ function SPAWN:New( SpawnTemplatePrefix )
|
|||||||
self.SpawnInitModu = nil -- No special modulation.
|
self.SpawnInitModu = nil -- No special modulation.
|
||||||
self.SpawnInitRadio = nil -- No radio comms setting.
|
self.SpawnInitRadio = nil -- No radio comms setting.
|
||||||
self.SpawnInitModex = nil
|
self.SpawnInitModex = nil
|
||||||
|
self.SpawnInitAirbase = nil
|
||||||
|
self.TweakedTemplate = false -- Check if the user is using self made template.
|
||||||
|
|
||||||
self.SpawnGroups = {} -- Array containing the descriptions of each Group to be Spawned.
|
self.SpawnGroups = {} -- Array containing the descriptions of each Group to be Spawned.
|
||||||
else
|
else
|
||||||
@@ -378,6 +379,8 @@ function SPAWN:NewWithAlias( SpawnTemplatePrefix, SpawnAliasPrefix )
|
|||||||
self.SpawnInitModu = nil -- No special modulation.
|
self.SpawnInitModu = nil -- No special modulation.
|
||||||
self.SpawnInitRadio = nil -- No radio comms setting.
|
self.SpawnInitRadio = nil -- No radio comms setting.
|
||||||
self.SpawnInitModex = nil
|
self.SpawnInitModex = nil
|
||||||
|
self.SpawnInitAirbase = nil
|
||||||
|
self.TweakedTemplate = false -- Check if the user is using self made template.
|
||||||
|
|
||||||
self.SpawnGroups = {} -- Array containing the descriptions of each Group to be Spawned.
|
self.SpawnGroups = {} -- Array containing the descriptions of each Group to be Spawned.
|
||||||
else
|
else
|
||||||
@@ -406,6 +409,10 @@ end
|
|||||||
function SPAWN:NewFromTemplate( SpawnTemplate, SpawnTemplatePrefix, SpawnAliasPrefix )
|
function SPAWN:NewFromTemplate( SpawnTemplate, SpawnTemplatePrefix, SpawnAliasPrefix )
|
||||||
local self = BASE:Inherit( self, BASE:New() )
|
local self = BASE:Inherit( self, BASE:New() )
|
||||||
self:F( { SpawnTemplate, SpawnTemplatePrefix, SpawnAliasPrefix } )
|
self:F( { SpawnTemplate, SpawnTemplatePrefix, SpawnAliasPrefix } )
|
||||||
|
if SpawnAliasPrefix == nil or SpawnAliasPrefix == "" then
|
||||||
|
BASE:I("ERROR: in function NewFromTemplate, required paramter SpawnAliasPrefix is not set")
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
if SpawnTemplate then
|
if SpawnTemplate then
|
||||||
self.SpawnTemplate = SpawnTemplate -- Contains the template structure for a Group Spawn from the Mission Editor. Note that this group must have lateActivation always on!!!
|
self.SpawnTemplate = SpawnTemplate -- Contains the template structure for a Group Spawn from the Mission Editor. Note that this group must have lateActivation always on!!!
|
||||||
@@ -433,6 +440,8 @@ function SPAWN:NewFromTemplate( SpawnTemplate, SpawnTemplatePrefix, SpawnAliasPr
|
|||||||
self.SpawnInitModu = nil -- No special modulation.
|
self.SpawnInitModu = nil -- No special modulation.
|
||||||
self.SpawnInitRadio = nil -- No radio comms setting.
|
self.SpawnInitRadio = nil -- No radio comms setting.
|
||||||
self.SpawnInitModex = nil
|
self.SpawnInitModex = nil
|
||||||
|
self.SpawnInitAirbase = nil
|
||||||
|
self.TweakedTemplate = true -- Check if the user is using self made template.
|
||||||
|
|
||||||
self.SpawnGroups = {} -- Array containing the descriptions of each Group to be Spawned.
|
self.SpawnGroups = {} -- Array containing the descriptions of each Group to be Spawned.
|
||||||
else
|
else
|
||||||
@@ -446,7 +455,8 @@ function SPAWN:NewFromTemplate( SpawnTemplate, SpawnTemplatePrefix, SpawnAliasPr
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Limits the Maximum amount of Units that can be alive at the same time, and the maximum amount of groups that can be spawned.
|
--- Stops any more repeat spawns from happening once the UNIT count of Alive units, spawned by the same SPAWN object, exceeds the first parameter. Also can stop spawns from happening once a total GROUP still alive is met.
|
||||||
|
-- Exceptionally powerful when combined with SpawnSchedule for Respawning.
|
||||||
-- Note that this method is exceptionally important to balance the performance of the mission. Depending on the machine etc, a mission can only process a maximum amount of units.
|
-- Note that this method is exceptionally important to balance the performance of the mission. Depending on the machine etc, a mission can only process a maximum amount of units.
|
||||||
-- If the time interval must be short, but there should not be more Units or Groups alive than a maximum amount of units, then this method should be used...
|
-- If the time interval must be short, but there should not be more Units or Groups alive than a maximum amount of units, then this method should be used...
|
||||||
-- When a @{#SPAWN.New} is executed and the limit of the amount of units alive is reached, then no new spawn will happen of the group, until some of these units of the spawn object will be destroyed.
|
-- When a @{#SPAWN.New} is executed and the limit of the amount of units alive is reached, then no new spawn will happen of the group, until some of these units of the spawn object will be destroyed.
|
||||||
@@ -503,6 +513,24 @@ function SPAWN:InitLateActivated( LateActivated )
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Set spawns to happen at a particular airbase. Only for aircraft, of course.
|
||||||
|
-- @param #SPAWN self
|
||||||
|
-- @param #string AirbaseName Name of the airbase.
|
||||||
|
-- @param #number Takeoff (Optional) Takeoff type. Can be SPAWN.Takeoff.Hot (default), SPAWN.Takeoff.Cold or SPAWN.Takeoff.Runway.
|
||||||
|
-- @param #number TerminalTyple (Optional) The terminal type.
|
||||||
|
-- @return #SPAWN self
|
||||||
|
function SPAWN:InitAirbase( AirbaseName, Takeoff, TerminalType )
|
||||||
|
self:F( )
|
||||||
|
|
||||||
|
self.SpawnInitAirbase=AIRBASE:FindByName(AirbaseName)
|
||||||
|
|
||||||
|
self.SpawnInitTakeoff=Takeoff or SPAWN.Takeoff.Hot
|
||||||
|
|
||||||
|
self.SpawnInitTerminalType=TerminalType
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Defines the Heading for the new spawned units.
|
--- Defines the Heading for the new spawned units.
|
||||||
-- The heading can be given as one fixed degree, or can be randomized between minimum and maximum degrees.
|
-- The heading can be given as one fixed degree, or can be randomized between minimum and maximum degrees.
|
||||||
@@ -530,6 +558,41 @@ function SPAWN:InitHeading( HeadingMin, HeadingMax )
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Defines the heading of the overall formation of the new spawned group.
|
||||||
|
-- The heading can be given as one fixed degree, or can be randomized between minimum and maximum degrees.
|
||||||
|
-- The Group's formation as laid out in its template will be rotated around the first unit in the group
|
||||||
|
-- Group individual units facings will rotate to match. If InitHeading is also applied to this SPAWN then that will take precedence for individual unit facings.
|
||||||
|
-- Note that InitGroupHeading does *not* rotate the groups route; only its initial facing!
|
||||||
|
-- @param #SPAWN self
|
||||||
|
-- @param #number HeadingMin The minimum or fixed heading in degrees.
|
||||||
|
-- @param #number HeadingMax (optional) The maximum heading in degrees. This there is no maximum heading, then the heading for the group will be HeadingMin.
|
||||||
|
-- @param #number unitVar (optional) Individual units within the group will have their heading randomized by +/- unitVar degrees. Default is zero.
|
||||||
|
-- @return #SPAWN self
|
||||||
|
-- @usage
|
||||||
|
--
|
||||||
|
-- mySpawner = SPAWN:New( ... )
|
||||||
|
--
|
||||||
|
-- -- Spawn the Group with the formation rotated +100 degrees around unit #1, compared to the mission template.
|
||||||
|
-- mySpawner:InitGroupHeading( 100 )
|
||||||
|
--
|
||||||
|
-- Spawn the Group with the formation rotated units between +100 and +150 degrees around unit #1, compared to the mission template, and with individual units varying by +/- 10 degrees from their templated facing.
|
||||||
|
-- mySpawner:InitGroupHeading( 100, 150, 10 )
|
||||||
|
--
|
||||||
|
-- Spawn the Group with the formation rotated -60 degrees around unit #1, compared to the mission template, but with all units facing due north regardless of how they were laid out in the template.
|
||||||
|
-- mySpawner:InitGroupHeading(-60):InitHeading(0)
|
||||||
|
-- or
|
||||||
|
-- mySpawner:InitHeading(0):InitGroupHeading(-60)
|
||||||
|
--
|
||||||
|
function SPAWN:InitGroupHeading( HeadingMin, HeadingMax, unitVar )
|
||||||
|
self:F({HeadingMin=HeadingMin, HeadingMax=HeadingMax, unitVar=unitVar})
|
||||||
|
|
||||||
|
self.SpawnInitGroupHeadingMin = HeadingMin
|
||||||
|
self.SpawnInitGroupHeadingMax = HeadingMax
|
||||||
|
self.SpawnInitGroupUnitVar = unitVar
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Sets the coalition of the spawned group. Note that it might be necessary to also set the country explicitly!
|
--- Sets the coalition of the spawned group. Note that it might be necessary to also set the country explicitly!
|
||||||
-- @param #SPAWN self
|
-- @param #SPAWN self
|
||||||
-- @param DCS#coalition.side Coalition Coalition of the group as number of enumerator:
|
-- @param DCS#coalition.side Coalition Coalition of the group as number of enumerator:
|
||||||
@@ -753,9 +816,9 @@ end
|
|||||||
-- Spawn_US_Platoon = { 'US Tank Platoon 1', 'US Tank Platoon 2', 'US Tank Platoon 3', 'US Tank Platoon 4', 'US Tank Platoon 5',
|
-- Spawn_US_Platoon = { 'US Tank Platoon 1', 'US Tank Platoon 2', 'US Tank Platoon 3', 'US Tank Platoon 4', 'US Tank Platoon 5',
|
||||||
-- 'US Tank Platoon 6', 'US Tank Platoon 7', 'US Tank Platoon 8', 'US Tank Platoon 9', 'US Tank Platoon 10',
|
-- 'US Tank Platoon 6', 'US Tank Platoon 7', 'US Tank Platoon 8', 'US Tank Platoon 9', 'US Tank Platoon 10',
|
||||||
-- 'US Tank Platoon 11', 'US Tank Platoon 12', 'US Tank Platoon 13' }
|
-- 'US Tank Platoon 11', 'US Tank Platoon 12', 'US Tank Platoon 13' }
|
||||||
-- Spawn_US_Platoon_Left = SPAWN:New( 'US Tank Platoon Left' ):InitLimit( 12, 150 ):Schedule( 200, 0.4 ):InitRandomizeTemplate( Spawn_US_Platoon ):InitRandomizeRoute( 3, 3, 2000 )
|
-- Spawn_US_Platoon_Left = SPAWN:New( 'US Tank Platoon Left' ):InitLimit( 12, 150 ):SpawnScheduled( 200, 0.4 ):InitRandomizeTemplate( Spawn_US_Platoon ):InitRandomizeRoute( 3, 3, 2000 )
|
||||||
-- Spawn_US_Platoon_Middle = SPAWN:New( 'US Tank Platoon Middle' ):InitLimit( 12, 150 ):Schedule( 200, 0.4 ):InitRandomizeTemplate( Spawn_US_Platoon ):InitRandomizeRoute( 3, 3, 2000 )
|
-- Spawn_US_Platoon_Middle = SPAWN:New( 'US Tank Platoon Middle' ):InitLimit( 12, 150 ):SpawnScheduled( 200, 0.4 ):InitRandomizeTemplate( Spawn_US_Platoon ):InitRandomizeRoute( 3, 3, 2000 )
|
||||||
-- Spawn_US_Platoon_Right = SPAWN:New( 'US Tank Platoon Right' ):InitLimit( 12, 150 ):Schedule( 200, 0.4 ):InitRandomizeTemplate( Spawn_US_Platoon ):InitRandomizeRoute( 3, 3, 2000 )
|
-- Spawn_US_Platoon_Right = SPAWN:New( 'US Tank Platoon Right' ):InitLimit( 12, 150 ):SpawnScheduled( 200, 0.4 ):InitRandomizeTemplate( Spawn_US_Platoon ):InitRandomizeRoute( 3, 3, 2000 )
|
||||||
function SPAWN:InitRandomizeTemplate( SpawnTemplatePrefixTable )
|
function SPAWN:InitRandomizeTemplate( SpawnTemplatePrefixTable )
|
||||||
self:F( { self.SpawnTemplatePrefix, SpawnTemplatePrefixTable } )
|
self:F( { self.SpawnTemplatePrefix, SpawnTemplatePrefixTable } )
|
||||||
|
|
||||||
@@ -789,9 +852,9 @@ end
|
|||||||
-- Spawn_US_PlatoonSet = SET_GROUP:New():FilterPrefixes( "US Tank Platoon Templates" ):FilterOnce()
|
-- Spawn_US_PlatoonSet = SET_GROUP:New():FilterPrefixes( "US Tank Platoon Templates" ):FilterOnce()
|
||||||
--
|
--
|
||||||
-- --- Now use the Spawn_US_PlatoonSet to define the templates using InitRandomizeTemplateSet.
|
-- --- Now use the Spawn_US_PlatoonSet to define the templates using InitRandomizeTemplateSet.
|
||||||
-- Spawn_US_Platoon_Left = SPAWN:New( 'US Tank Platoon Left' ):InitLimit( 12, 150 ):Schedule( 200, 0.4 ):InitRandomizeTemplateSet( Spawn_US_PlatoonSet ):InitRandomizeRoute( 3, 3, 2000 )
|
-- Spawn_US_Platoon_Left = SPAWN:New( 'US Tank Platoon Left' ):InitLimit( 12, 150 ):SpawnScheduled( 200, 0.4 ):InitRandomizeTemplateSet( Spawn_US_PlatoonSet ):InitRandomizeRoute( 3, 3, 2000 )
|
||||||
-- Spawn_US_Platoon_Middle = SPAWN:New( 'US Tank Platoon Middle' ):InitLimit( 12, 150 ):Schedule( 200, 0.4 ):InitRandomizeTemplateSet( Spawn_US_PlatoonSet ):InitRandomizeRoute( 3, 3, 2000 )
|
-- Spawn_US_Platoon_Middle = SPAWN:New( 'US Tank Platoon Middle' ):InitLimit( 12, 150 ):SpawnScheduled( 200, 0.4 ):InitRandomizeTemplateSet( Spawn_US_PlatoonSet ):InitRandomizeRoute( 3, 3, 2000 )
|
||||||
-- Spawn_US_Platoon_Right = SPAWN:New( 'US Tank Platoon Right' ):InitLimit( 12, 150 ):Schedule( 200, 0.4 ):InitRandomizeTemplateSet( Spawn_US_PlatoonSet ):InitRandomizeRoute( 3, 3, 2000 )
|
-- Spawn_US_Platoon_Right = SPAWN:New( 'US Tank Platoon Right' ):InitLimit( 12, 150 ):SpawnScheduled( 200, 0.4 ):InitRandomizeTemplateSet( Spawn_US_PlatoonSet ):InitRandomizeRoute( 3, 3, 2000 )
|
||||||
function SPAWN:InitRandomizeTemplateSet( SpawnTemplateSet ) -- R2.3
|
function SPAWN:InitRandomizeTemplateSet( SpawnTemplateSet ) -- R2.3
|
||||||
self:F( { self.SpawnTemplatePrefix } )
|
self:F( { self.SpawnTemplatePrefix } )
|
||||||
|
|
||||||
@@ -822,9 +885,9 @@ end
|
|||||||
-- -- Each new SPAWN will randomize the route, with a defined time interval of 200 seconds with 40% time variation (randomization) and
|
-- -- Each new SPAWN will randomize the route, with a defined time interval of 200 seconds with 40% time variation (randomization) and
|
||||||
-- -- with a limit set of maximum 12 Units alive simulteneously and 150 Groups to be spawned during the whole mission.
|
-- -- with a limit set of maximum 12 Units alive simulteneously and 150 Groups to be spawned during the whole mission.
|
||||||
--
|
--
|
||||||
-- Spawn_US_Platoon_Left = SPAWN:New( 'US Tank Platoon Left' ):InitLimit( 12, 150 ):Schedule( 200, 0.4 ):InitRandomizeTemplatePrefixes( "US Tank Platoon Templates" ):InitRandomizeRoute( 3, 3, 2000 )
|
-- Spawn_US_Platoon_Left = SPAWN:New( 'US Tank Platoon Left' ):InitLimit( 12, 150 ):SpawnScheduled( 200, 0.4 ):InitRandomizeTemplatePrefixes( "US Tank Platoon Templates" ):InitRandomizeRoute( 3, 3, 2000 )
|
||||||
-- Spawn_US_Platoon_Middle = SPAWN:New( 'US Tank Platoon Middle' ):InitLimit( 12, 150 ):Schedule( 200, 0.4 ):InitRandomizeTemplatePrefixes( "US Tank Platoon Templates" ):InitRandomizeRoute( 3, 3, 2000 )
|
-- Spawn_US_Platoon_Middle = SPAWN:New( 'US Tank Platoon Middle' ):InitLimit( 12, 150 ):SpawnScheduled( 200, 0.4 ):InitRandomizeTemplatePrefixes( "US Tank Platoon Templates" ):InitRandomizeRoute( 3, 3, 2000 )
|
||||||
-- Spawn_US_Platoon_Right = SPAWN:New( 'US Tank Platoon Right' ):InitLimit( 12, 150 ):Schedule( 200, 0.4 ):InitRandomizeTemplatePrefixes( "US Tank Platoon Templates" ):InitRandomizeRoute( 3, 3, 2000 )
|
-- Spawn_US_Platoon_Right = SPAWN:New( 'US Tank Platoon Right' ):InitLimit( 12, 150 ):SpawnScheduled( 200, 0.4 ):InitRandomizeTemplatePrefixes( "US Tank Platoon Templates" ):InitRandomizeRoute( 3, 3, 2000 )
|
||||||
function SPAWN:InitRandomizeTemplatePrefixes( SpawnTemplatePrefixes ) --R2.3
|
function SPAWN:InitRandomizeTemplatePrefixes( SpawnTemplatePrefixes ) --R2.3
|
||||||
self:F( { self.SpawnTemplatePrefix } )
|
self:F( { self.SpawnTemplatePrefix } )
|
||||||
|
|
||||||
@@ -916,11 +979,9 @@ end
|
|||||||
-- -- Re-SPAWN the Group(s) after each landing and Engine Shut-Down automatically.
|
-- -- Re-SPAWN the Group(s) after each landing and Engine Shut-Down automatically.
|
||||||
-- SpawnRU_SU34 = SPAWN
|
-- SpawnRU_SU34 = SPAWN
|
||||||
-- :New( 'Su-34' )
|
-- :New( 'Su-34' )
|
||||||
-- :Schedule( 2, 3, 1800, 0.4 )
|
|
||||||
-- :SpawnUncontrolled()
|
|
||||||
-- :InitRandomizeRoute( 1, 1, 3000 )
|
-- :InitRandomizeRoute( 1, 1, 3000 )
|
||||||
-- :InitRepeatOnLanding()
|
-- :InitRepeatOnLanding()
|
||||||
--
|
-- :Spawn()
|
||||||
function SPAWN:InitRepeatOnLanding()
|
function SPAWN:InitRepeatOnLanding()
|
||||||
self:F( { self.SpawnTemplatePrefix } )
|
self:F( { self.SpawnTemplatePrefix } )
|
||||||
|
|
||||||
@@ -940,11 +1001,10 @@ end
|
|||||||
-- -- Re-SPAWN the Group(s) after each landing and Engine Shut-Down automatically.
|
-- -- Re-SPAWN the Group(s) after each landing and Engine Shut-Down automatically.
|
||||||
-- SpawnRU_SU34 = SPAWN
|
-- SpawnRU_SU34 = SPAWN
|
||||||
-- :New( 'Su-34' )
|
-- :New( 'Su-34' )
|
||||||
-- :Schedule( 2, 3, 1800, 0.4 )
|
|
||||||
-- :SpawnUncontrolled()
|
-- :SpawnUncontrolled()
|
||||||
-- :InitRandomizeRoute( 1, 1, 3000 )
|
-- :InitRandomizeRoute( 1, 1, 3000 )
|
||||||
-- :InitRepeatOnEngineShutDown()
|
-- :InitRepeatOnEngineShutDown()
|
||||||
--
|
-- :Spawn()
|
||||||
function SPAWN:InitRepeatOnEngineShutDown()
|
function SPAWN:InitRepeatOnEngineShutDown()
|
||||||
self:F( { self.SpawnTemplatePrefix } )
|
self:F( { self.SpawnTemplatePrefix } )
|
||||||
|
|
||||||
@@ -956,7 +1016,8 @@ function SPAWN:InitRepeatOnEngineShutDown()
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- CleanUp groups when they are still alive, but inactive.
|
--- Delete groups that have not moved for X seconds - AIR ONLY!!!
|
||||||
|
-- DO NOT USE ON GROUPS THAT DO NOT MOVE OR YOUR SERVER WILL BURN IN HELL (Pikes - April 2020)
|
||||||
-- When groups are still alive and have become inactive due to damage and are unable to contribute anything, then this group will be removed at defined intervals in seconds.
|
-- When groups are still alive and have become inactive due to damage and are unable to contribute anything, then this group will be removed at defined intervals in seconds.
|
||||||
-- @param #SPAWN self
|
-- @param #SPAWN self
|
||||||
-- @param #string SpawnCleanUpInterval The interval to check for inactive groups within seconds.
|
-- @param #string SpawnCleanUpInterval The interval to check for inactive groups within seconds.
|
||||||
@@ -981,6 +1042,7 @@ end
|
|||||||
|
|
||||||
--- Makes the groups visible before start (like a batallion).
|
--- Makes the groups visible before start (like a batallion).
|
||||||
-- The method will take the position of the group as the first position in the array.
|
-- The method will take the position of the group as the first position in the array.
|
||||||
|
-- CAUTION: this directive will NOT work with OnSpawnGroup function.
|
||||||
-- @param #SPAWN self
|
-- @param #SPAWN self
|
||||||
-- @param #number SpawnAngle The angle in degrees how the groups and each unit of the group will be positioned.
|
-- @param #number SpawnAngle The angle in degrees how the groups and each unit of the group will be positioned.
|
||||||
-- @param #number SpawnWidth The amount of Groups that will be positioned on the X axis.
|
-- @param #number SpawnWidth The amount of Groups that will be positioned on the X axis.
|
||||||
@@ -1115,7 +1177,12 @@ end -- Delay methods
|
|||||||
function SPAWN:Spawn()
|
function SPAWN:Spawn()
|
||||||
self:F( { self.SpawnTemplatePrefix, self.SpawnIndex, self.AliveUnits } )
|
self:F( { self.SpawnTemplatePrefix, self.SpawnIndex, self.AliveUnits } )
|
||||||
|
|
||||||
return self:SpawnWithIndex( self.SpawnIndex + 1 )
|
if self.SpawnInitAirbase then
|
||||||
|
return self:SpawnAtAirbase(self.SpawnInitAirbase, self.SpawnInitTakeoff, nil, self.SpawnInitTerminalType)
|
||||||
|
else
|
||||||
|
return self:SpawnWithIndex( self.SpawnIndex + 1 )
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Will re-spawn a group based on a given index.
|
--- Will re-spawn a group based on a given index.
|
||||||
@@ -1130,7 +1197,7 @@ function SPAWN:ReSpawn( SpawnIndex )
|
|||||||
SpawnIndex = 1
|
SpawnIndex = 1
|
||||||
end
|
end
|
||||||
|
|
||||||
-- TODO: This logic makes DCS crash and i don't know why (yet).
|
-- TODO: This logic makes DCS crash and i don't know why (yet). -- ED (Pikes -- not in the least bit scary to see this, right?)
|
||||||
local SpawnGroup = self:GetGroupFromIndex( SpawnIndex )
|
local SpawnGroup = self:GetGroupFromIndex( SpawnIndex )
|
||||||
local WayPoints = SpawnGroup and SpawnGroup.WayPoints or nil
|
local WayPoints = SpawnGroup and SpawnGroup.WayPoints or nil
|
||||||
if SpawnGroup then
|
if SpawnGroup then
|
||||||
@@ -1214,21 +1281,72 @@ function SPAWN:SpawnWithIndex( SpawnIndex, NoBirth )
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Get correct heading.
|
-- Get correct heading in Radians.
|
||||||
local function _Heading(course)
|
local function _Heading(courseDeg)
|
||||||
local h
|
local h
|
||||||
if course<=180 then
|
if courseDeg<=180 then
|
||||||
h=math.rad(course)
|
h=math.rad(courseDeg)
|
||||||
else
|
else
|
||||||
h=-math.rad(360-course)
|
h=-math.rad(360-courseDeg)
|
||||||
end
|
end
|
||||||
return h
|
return h
|
||||||
end
|
end
|
||||||
|
|
||||||
-- If Heading is given, point all the units towards the given Heading.
|
local Rad180 = math.rad(180)
|
||||||
|
local function _HeadingRad(courseRad)
|
||||||
|
if courseRad<=Rad180 then
|
||||||
|
return courseRad
|
||||||
|
else
|
||||||
|
return -((2*Rad180)-courseRad)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Generate a random value somewhere between two floating point values.
|
||||||
|
local function _RandomInRange ( min, max )
|
||||||
|
if min and max then
|
||||||
|
return min + ( math.random()*(max-min) )
|
||||||
|
else
|
||||||
|
return min
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Apply InitGroupHeading rotation if requested.
|
||||||
|
-- We do this before InitHeading unit rotation so that can take precedence
|
||||||
|
-- NOTE: Does *not* rotate the groups route; only its initial facing.
|
||||||
|
if self.SpawnInitGroupHeadingMin and #SpawnTemplate.units > 0 then
|
||||||
|
|
||||||
|
local pivotX = SpawnTemplate.units[1].x -- unit #1 is the pivot point
|
||||||
|
local pivotY = SpawnTemplate.units[1].y
|
||||||
|
|
||||||
|
local headingRad = math.rad(_RandomInRange(self.SpawnInitGroupHeadingMin or 0,self.SpawnInitGroupHeadingMax))
|
||||||
|
local cosHeading = math.cos(headingRad)
|
||||||
|
local sinHeading = math.sin(headingRad)
|
||||||
|
|
||||||
|
local unitVarRad = math.rad(self.SpawnInitGroupUnitVar or 0)
|
||||||
|
|
||||||
|
for UnitID = 1, #SpawnTemplate.units do
|
||||||
|
|
||||||
|
if UnitID > 1 then -- don't rotate position of unit #1
|
||||||
|
local unitXOff = SpawnTemplate.units[UnitID].x - pivotX -- rotate position offset around unit #1
|
||||||
|
local unitYOff = SpawnTemplate.units[UnitID].y - pivotY
|
||||||
|
|
||||||
|
SpawnTemplate.units[UnitID].x = pivotX + (unitXOff*cosHeading) - (unitYOff*sinHeading)
|
||||||
|
SpawnTemplate.units[UnitID].y = pivotY + (unitYOff*cosHeading) + (unitXOff*sinHeading)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- adjust heading of all units, including unit #1
|
||||||
|
local unitHeading = SpawnTemplate.units[UnitID].heading + headingRad -- add group rotation to units default rotation
|
||||||
|
SpawnTemplate.units[UnitID].heading = _HeadingRad(_RandomInRange(unitHeading-unitVarRad, unitHeading+unitVarRad))
|
||||||
|
SpawnTemplate.units[UnitID].psi = -SpawnTemplate.units[UnitID].heading
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
-- If Heading is given, point all the units towards the given Heading. Overrides any heading set in InitGroupHeading above.
|
||||||
if self.SpawnInitHeadingMin then
|
if self.SpawnInitHeadingMin then
|
||||||
for UnitID = 1, #SpawnTemplate.units do
|
for UnitID = 1, #SpawnTemplate.units do
|
||||||
SpawnTemplate.units[UnitID].heading = _Heading(self.SpawnInitHeadingMax and math.random( self.SpawnInitHeadingMin, self.SpawnInitHeadingMax ) or self.SpawnInitHeadingMin)
|
SpawnTemplate.units[UnitID].heading = _Heading(_RandomInRange(self.SpawnInitHeadingMin, self.SpawnInitHeadingMax))
|
||||||
SpawnTemplate.units[UnitID].psi = -SpawnTemplate.units[UnitID].heading
|
SpawnTemplate.units[UnitID].psi = -SpawnTemplate.units[UnitID].heading
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -1319,6 +1437,7 @@ function SPAWN:SpawnWithIndex( SpawnIndex, NoBirth )
|
|||||||
--end
|
--end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
self.SpawnGroups[self.SpawnIndex].Spawned = true
|
self.SpawnGroups[self.SpawnIndex].Spawned = true
|
||||||
return self.SpawnGroups[self.SpawnIndex].Group
|
return self.SpawnGroups[self.SpawnIndex].Group
|
||||||
else
|
else
|
||||||
@@ -1343,7 +1462,7 @@ end
|
|||||||
-- -- Low limit: 600 * ( 1 - 0.5 / 2 ) = 450
|
-- -- Low limit: 600 * ( 1 - 0.5 / 2 ) = 450
|
||||||
-- -- High limit: 600 * ( 1 + 0.5 / 2 ) = 750
|
-- -- High limit: 600 * ( 1 + 0.5 / 2 ) = 750
|
||||||
-- -- Between these two values, a random amount of seconds will be choosen for each new spawn of the helicopters.
|
-- -- Between these two values, a random amount of seconds will be choosen for each new spawn of the helicopters.
|
||||||
-- Spawn_BE_KA50 = SPAWN:New( 'BE KA-50@RAMP-Ground Defense' ):Schedule( 600, 0.5 )
|
-- Spawn_BE_KA50 = SPAWN:New( 'BE KA-50@RAMP-Ground Defense' ):SpawnScheduled( 600, 0.5 )
|
||||||
function SPAWN:SpawnScheduled( SpawnTime, SpawnTimeVariation )
|
function SPAWN:SpawnScheduled( SpawnTime, SpawnTimeVariation )
|
||||||
self:F( { SpawnTime, SpawnTimeVariation } )
|
self:F( { SpawnTime, SpawnTimeVariation } )
|
||||||
|
|
||||||
@@ -1520,7 +1639,7 @@ function SPAWN:SpawnAtAirbase( SpawnAirbase, Takeoff, TakeoffAltitude, TerminalT
|
|||||||
|
|
||||||
-- Get airbase ID and category.
|
-- Get airbase ID and category.
|
||||||
local AirbaseID = SpawnAirbase:GetID()
|
local AirbaseID = SpawnAirbase:GetID()
|
||||||
local AirbaseCategory = SpawnAirbase:GetDesc().category
|
local AirbaseCategory = SpawnAirbase:GetAirbaseCategory()
|
||||||
self:F( { AirbaseCategory = AirbaseCategory } )
|
self:F( { AirbaseCategory = AirbaseCategory } )
|
||||||
|
|
||||||
-- Set airdromeId.
|
-- Set airdromeId.
|
||||||
@@ -1958,7 +2077,7 @@ function SPAWN:ParkAircraft( SpawnAirbase, TerminalType, Parkingdata, SpawnIndex
|
|||||||
|
|
||||||
-- Get airbase ID and category.
|
-- Get airbase ID and category.
|
||||||
local AirbaseID = SpawnAirbase:GetID()
|
local AirbaseID = SpawnAirbase:GetID()
|
||||||
local AirbaseCategory = SpawnAirbase:GetDesc().category
|
local AirbaseCategory = SpawnAirbase:GetAirbaseCategory()
|
||||||
self:F( { AirbaseCategory = AirbaseCategory } )
|
self:F( { AirbaseCategory = AirbaseCategory } )
|
||||||
|
|
||||||
-- Set airdromeId.
|
-- Set airdromeId.
|
||||||
@@ -2207,7 +2326,7 @@ function SPAWN:ParkAircraft( SpawnAirbase, TerminalType, Parkingdata, SpawnIndex
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Set gereral spawnpoint position.
|
-- Set general spawnpoint position.
|
||||||
SpawnPoint.x = PointVec3.x
|
SpawnPoint.x = PointVec3.x
|
||||||
SpawnPoint.y = PointVec3.z
|
SpawnPoint.y = PointVec3.z
|
||||||
SpawnPoint.alt = PointVec3.y
|
SpawnPoint.alt = PointVec3.y
|
||||||
@@ -2866,9 +2985,15 @@ function SPAWN:_Prepare( SpawnTemplatePrefix, SpawnIndex ) --R2.2
|
|||||||
-- self.SpawnTemplate = self:_GetTemplate( SpawnTemplatePrefix )
|
-- self.SpawnTemplate = self:_GetTemplate( SpawnTemplatePrefix )
|
||||||
-- end
|
-- end
|
||||||
|
|
||||||
local SpawnTemplate = self:_GetTemplate( SpawnTemplatePrefix )
|
local SpawnTemplate
|
||||||
--local SpawnTemplate = self.SpawnTemplate
|
if self.TweakedTemplate ~= nil and self.TweakedTemplate == true then
|
||||||
SpawnTemplate.name = self:SpawnGroupName( SpawnIndex )
|
BASE:I("WARNING: You are using a tweaked template.")
|
||||||
|
SpawnTemplate = self.SpawnTemplate
|
||||||
|
else
|
||||||
|
SpawnTemplate = self:_GetTemplate( SpawnTemplatePrefix )
|
||||||
|
SpawnTemplate.name = self:SpawnGroupName( SpawnIndex )
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
SpawnTemplate.groupId = nil
|
SpawnTemplate.groupId = nil
|
||||||
--SpawnTemplate.lateActivation = false
|
--SpawnTemplate.lateActivation = false
|
||||||
@@ -3239,6 +3364,7 @@ end
|
|||||||
|
|
||||||
--- This function is called automatically by the Spawning scheduler.
|
--- This function is called automatically by the Spawning scheduler.
|
||||||
-- It is the internal worker method SPAWNing new Groups on the defined time intervals.
|
-- It is the internal worker method SPAWNing new Groups on the defined time intervals.
|
||||||
|
-- @param #SPAWN self
|
||||||
function SPAWN:_Scheduler()
|
function SPAWN:_Scheduler()
|
||||||
self:F2( { "_Scheduler", self.SpawnTemplatePrefix, self.SpawnAliasPrefix, self.SpawnIndex, self.SpawnMaxGroups, self.SpawnMaxUnitsAlive } )
|
self:F2( { "_Scheduler", self.SpawnTemplatePrefix, self.SpawnAliasPrefix, self.SpawnIndex, self.SpawnMaxGroups, self.SpawnMaxUnitsAlive } )
|
||||||
|
|
||||||
|
|||||||
@@ -1,104 +1,156 @@
|
|||||||
--- **Core** - Spawn new statics in your running missions.
|
--- **Core** - Spawn statics.
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ## Features:
|
-- ## Features:
|
||||||
--
|
--
|
||||||
-- * Spawn new statics from a static already defined using the mission editor.
|
-- * Spawn new statics from a static already defined in the mission editor.
|
||||||
-- * Spawn new statics from a given template.
|
-- * Spawn new statics from a given template.
|
||||||
-- * Spawn new statics from a given type.
|
-- * Spawn new statics from a given type.
|
||||||
-- * Spawn with a custom heading and location.
|
-- * Spawn with a custom heading and location.
|
||||||
-- * Spawn within a zone.
|
-- * Spawn within a zone.
|
||||||
|
-- * Spawn statics linked to units, .e.g on aircraft carriers.
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- # Demo Missions
|
-- # Demo Missions
|
||||||
--
|
--
|
||||||
-- ### [SPAWNSTATIC Demo Missions source code](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master-release/SPS - Spawning Statics)
|
-- ## [SPAWNSTATIC Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/SPS%20-%20Spawning%20Statics)
|
||||||
--
|
--
|
||||||
-- ### [SPAWNSTATIC Demo Missions, only for beta testers](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/SPS%20-%20Spawning%20Statics)
|
|
||||||
--
|
|
||||||
-- ### [ALL Demo Missions pack of the last release](https://github.com/FlightControl-Master/MOOSE_MISSIONS/releases)
|
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- # YouTube Channel
|
-- # YouTube Channel
|
||||||
--
|
--
|
||||||
-- ### [SPAWNSTATIC YouTube Channel]()
|
-- ## [SPAWNSTATIC YouTube Channel]() [No videos yet!]
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ### Author: **FlightControl**
|
-- ### Author: **FlightControl**
|
||||||
-- ### Contributions:
|
-- ### Contributions: **funkyfranky**
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- @module Core.SpawnStatic
|
-- @module Core.SpawnStatic
|
||||||
-- @image Core_Spawnstatic.JPG
|
-- @image Core_Spawnstatic.JPG
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--- @type SPAWNSTATIC
|
--- @type SPAWNSTATIC
|
||||||
|
-- @field #string SpawnTemplatePrefix Name of the template group.
|
||||||
|
-- @field #number CountryID Country ID.
|
||||||
|
-- @field #number CoalitionID Coalition ID.
|
||||||
|
-- @field #number CategoryID Category ID.
|
||||||
|
-- @field #number SpawnIndex Running number increased with each new Spawn.
|
||||||
|
-- @field Wrapper.Unit#UNIT InitLinkUnit The unit the static is linked to.
|
||||||
|
-- @field #number InitOffsetX Link offset X coordinate.
|
||||||
|
-- @field #number InitOffsetY Link offset Y coordinate.
|
||||||
|
-- @field #number InitOffsetAngle Link offset angle in degrees.
|
||||||
|
-- @field #number InitStaticHeading Heading of the static.
|
||||||
|
-- @field #string InitStaticLivery Livery for aircraft.
|
||||||
|
-- @field #string InitStaticShape Shape of teh static.
|
||||||
|
-- @field #string InitStaticType Type of the static.
|
||||||
|
-- @field #string InitStaticCategory Categrory of the static.
|
||||||
|
-- @field #string InitStaticName Name of the static.
|
||||||
|
-- @field Core.Point#COORDINATE InitStaticCoordinate Coordinate where to spawn the static.
|
||||||
|
-- @field #boolean InitDead Set static to be dead if true.
|
||||||
|
-- @field #boolean InitCargo If true, static can act as cargo.
|
||||||
|
-- @field #number InitCargoMass Mass of cargo in kg.
|
||||||
-- @extends Core.Base#BASE
|
-- @extends Core.Base#BASE
|
||||||
|
|
||||||
|
|
||||||
--- Allows to spawn dynamically new @{Static}s.
|
--- Allows to spawn dynamically new @{Static}s into your mission.
|
||||||
-- Through creating a copy of an existing static object template as defined in the Mission Editor (ME),
|
|
||||||
-- SPAWNSTATIC can retireve the properties of the defined static object template (like type, category etc), and "copy"
|
|
||||||
-- these properties to create a new static object and place it at the desired coordinate.
|
|
||||||
--
|
--
|
||||||
-- New spawned @{Static}s get **the same name** as the name of the template Static,
|
-- Through creating a copy of an existing static object template as defined in the Mission Editor (ME), SPAWNSTATIC can retireve the properties of the defined static object template (like type, category etc),
|
||||||
-- or gets the given name when a new name is provided at the Spawn method.
|
-- and "copy" these properties to create a new static object and place it at the desired coordinate.
|
||||||
|
--
|
||||||
|
-- New spawned @{Static}s get **the same name** as the name of the template Static, or gets the given name when a new name is provided at the Spawn method.
|
||||||
-- By default, spawned @{Static}s will follow a naming convention at run-time:
|
-- By default, spawned @{Static}s will follow a naming convention at run-time:
|
||||||
--
|
--
|
||||||
-- * Spawned @{Static}s will have the name _StaticName_#_nnn_, where _StaticName_ is the name of the **Template Static**,
|
-- * Spawned @{Static}s will have the name _StaticName_#_nnn_, where _StaticName_ is the name of the **Template Static**, and _nnn_ is a **counter from 0 to 99999**.
|
||||||
-- and _nnn_ is a **counter from 0 to 99999**.
|
|
||||||
--
|
--
|
||||||
|
-- # SPAWNSTATIC Constructors
|
||||||
--
|
--
|
||||||
-- ## SPAWNSTATIC construction methods
|
-- Firstly, we need to create a SPAWNSTATIC object that will be used to spawn new statics into the mission. There are three ways to do this.
|
||||||
--
|
--
|
||||||
-- Create a new SPAWNSTATIC object with the @{#SPAWNSTATIC.NewFromStatic}():
|
-- ## Use another Static
|
||||||
--
|
--
|
||||||
-- * @{#SPAWNSTATIC.NewFromStatic}(): Creates a new SPAWNSTATIC object given a name that is used as the base of the naming of each spawned Static.
|
-- A new SPAWNSTATIC object can be created using another static by the @{#SPAWNSTATIC.NewFromStatic}() function. All parameters such as position, heading, country will be initialized
|
||||||
|
-- from the static.
|
||||||
--
|
--
|
||||||
-- ## **Spawn** methods
|
-- ## From a Template
|
||||||
--
|
--
|
||||||
-- Groups can be spawned at different times and methods:
|
-- A SPAWNSTATIC object can also be created from a template table using the @{#SPAWNSTATIC.NewFromTemplate}(SpawnTemplate, CountryID) function. All parameters are taken from the template.
|
||||||
--
|
--
|
||||||
-- * @{#SPAWNSTATIC.SpawnFromPointVec2}(): Spawn a new group from a POINT_VEC2 coordinate.
|
-- ## From a Type
|
||||||
-- (The group will be spawned at land height ).
|
--
|
||||||
-- * @{#SPAWNSTATIC.SpawnFromZone}(): Spawn a new group in a @{Zone}.
|
-- A very basic method is to create a SPAWNSTATIC object by just giving the type of the static. All parameters must be initialized from the InitXYZ functions described below. Otherwise default values
|
||||||
|
-- are used. For example, if no spawn coordinate is given, the static will be created at the origin of the map.
|
||||||
|
--
|
||||||
|
-- # Setting Parameters
|
||||||
|
--
|
||||||
|
-- Parameters such as the spawn position, heading, country etc. can be set via :Init*XYZ* functions. Note that these functions must be given before the actual spawn command!
|
||||||
|
--
|
||||||
|
-- * @{#SPAWNSTATIC.InitCoordinate}(Coordinate) Sets the coordinate where the static is spawned. Statics are always spawnd on the ground.
|
||||||
|
-- * @{#SPAWNSTATIC.InitHeading}(Heading) sets the orientation of the static.
|
||||||
|
-- * @{#SPAWNSTATIC.InitLivery}(LiveryName) sets the livery of the static. Not all statics support this.
|
||||||
|
-- * @{#SPAWNSTATIC.InitType}(StaticType) sets the type of the static.
|
||||||
|
-- * @{#SPAWNSTATIC.InitShape}(StaticType) sets the shape of the static. Not all statics have this parameter.
|
||||||
|
-- * @{#SPAWNSTATIC.InitNamePrefix}(NamePrefix) sets the name prefix of the spawned statics.
|
||||||
|
-- * @{#SPAWNSTATIC.InitCountry}(CountryID) sets the country and therefore the coalition of the spawned statics.
|
||||||
|
-- * @{#SPAWNSTATIC.InitLinkToUnit}(Unit, OffsetX, OffsetY, OffsetAngle) links the static to a unit, e.g. to an aircraft carrier.
|
||||||
|
--
|
||||||
|
-- # Spawning the Statics
|
||||||
|
--
|
||||||
|
-- Once the SPAWNSTATIC object is created and parameters are initialized, the spawn command can be given. There are different methods where some can be used to directly set parameters
|
||||||
|
-- such as position and heading.
|
||||||
|
--
|
||||||
|
-- * @{#SPAWNSTATIC.Spawn}(Heading, NewName) spawns the static with the set parameters. Optionally, heading and name can be given. The name **must be unique**!
|
||||||
|
-- * @{#SPAWNSTATIC.SpawnFromCoordinate}(Coordinate, Heading, NewName) spawn the static at the given coordinate. Optionally, heading and name can be given. The name **must be unique**!
|
||||||
|
-- * @{#SPAWNSTATIC.SpawnFromPointVec2}(PointVec2, Heading, NewName) spawns the static at a POINT_VEC2 coordinate. Optionally, heading and name can be given. The name **must be unique**!
|
||||||
|
-- * @{#SPAWNSTATIC.SpawnFromZone}(Zone, Heading, NewName) spawns the static at the center of a @{Zone}. Optionally, heading and name can be given. The name **must be unique**!
|
||||||
--
|
--
|
||||||
-- @field #SPAWNSTATIC SPAWNSTATIC
|
-- @field #SPAWNSTATIC SPAWNSTATIC
|
||||||
--
|
--
|
||||||
SPAWNSTATIC = {
|
SPAWNSTATIC = {
|
||||||
ClassName = "SPAWNSTATIC",
|
ClassName = "SPAWNSTATIC",
|
||||||
|
SpawnIndex = 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
--- Static template table data.
|
||||||
|
-- @type SPAWNSTATIC.TemplateData
|
||||||
|
-- @field #string name Name of the static.
|
||||||
|
-- @field #string type Type of the static.
|
||||||
|
-- @field #string category Category of the static.
|
||||||
|
-- @field #number x X-coordinate of the static.
|
||||||
|
-- @field #number y Y-coordinate of teh static.
|
||||||
|
-- @field #number heading Heading in rad.
|
||||||
|
-- @field #boolean dead Static is dead if true.
|
||||||
|
-- @field #string livery_id Livery name.
|
||||||
|
-- @field #number unitId Unit ID.
|
||||||
|
-- @field #number groupId Group ID.
|
||||||
|
-- @field #table offsets Offset parameters when linked to a unit.
|
||||||
|
-- @field #number mass Cargo mass in kg.
|
||||||
|
-- @field #boolean canCargo Static can be a cargo.
|
||||||
|
|
||||||
--- @type SPAWNSTATIC.SpawnZoneTable
|
--- Creates the main object to spawn a @{Static} defined in the mission editor (ME).
|
||||||
-- @list <Core.Zone#ZONE_BASE> SpawnZone
|
|
||||||
|
|
||||||
|
|
||||||
--- Creates the main object to spawn a @{Static} defined in the ME.
|
|
||||||
-- @param #SPAWNSTATIC self
|
-- @param #SPAWNSTATIC self
|
||||||
-- @param #string SpawnTemplatePrefix is the name of the Group in the ME that defines the Template. Each new group will have the name starting with SpawnTemplatePrefix.
|
-- @param #string SpawnTemplateName Name of the static object in the ME. Each new static will have the name starting with this prefix.
|
||||||
-- @param DCS#country.id SpawnCountryID The ID of the country.
|
-- @param DCS#country.id SpawnCountryID (Optional) The ID of the country.
|
||||||
-- @param DCS#coalition.side SpawnCoalitionID The ID of the coalition.
|
-- @return #SPAWNSTATIC self
|
||||||
-- @return #SPAWNSTATIC
|
function SPAWNSTATIC:NewFromStatic(SpawnTemplateName, SpawnCountryID)
|
||||||
function SPAWNSTATIC:NewFromStatic( SpawnTemplatePrefix, SpawnCountryID, SpawnCoalitionID )
|
|
||||||
local self = BASE:Inherit( self, BASE:New() ) -- #SPAWNSTATIC
|
local self = BASE:Inherit( self, BASE:New() ) -- #SPAWNSTATIC
|
||||||
self:F( { SpawnTemplatePrefix } )
|
|
||||||
|
local TemplateStatic, CoalitionID, CategoryID, CountryID = _DATABASE:GetStaticGroupTemplate(SpawnTemplateName)
|
||||||
|
|
||||||
local TemplateStatic, CoalitionID, CategoryID, CountryID = _DATABASE:GetStaticGroupTemplate( SpawnTemplatePrefix )
|
|
||||||
if TemplateStatic then
|
if TemplateStatic then
|
||||||
self.SpawnTemplatePrefix = SpawnTemplatePrefix
|
self.SpawnTemplatePrefix = SpawnTemplateName
|
||||||
self.CountryID = SpawnCountryID or CountryID
|
self.TemplateStaticUnit = UTILS.DeepCopy(TemplateStatic.units[1])
|
||||||
self.CategoryID = CategoryID
|
self.CountryID = SpawnCountryID or CountryID
|
||||||
self.CoalitionID = SpawnCoalitionID or CoalitionID
|
self.CategoryID = CategoryID
|
||||||
self.SpawnIndex = 0
|
self.CoalitionID = CoalitionID
|
||||||
|
self.SpawnIndex = 0
|
||||||
else
|
else
|
||||||
error( "SPAWNSTATIC:New: There is no static declared in the mission editor with SpawnTemplatePrefix = '" .. SpawnTemplatePrefix .. "'" )
|
error( "SPAWNSTATIC:New: There is no static declared in the mission editor with SpawnTemplatePrefix = '" .. tostring(SpawnTemplateName) .. "'" )
|
||||||
end
|
end
|
||||||
|
|
||||||
self:SetEventPriority( 5 )
|
self:SetEventPriority( 5 )
|
||||||
@@ -106,198 +158,284 @@ function SPAWNSTATIC:NewFromStatic( SpawnTemplatePrefix, SpawnCountryID, SpawnCo
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Creates the main object to spawn a @{Static} based on a type name.
|
--- Creates the main object to spawn a @{Static} given a template table.
|
||||||
-- @param #SPAWNSTATIC self
|
-- @param #SPAWNSTATIC self
|
||||||
-- @param #string SpawnTypeName is the name of the type.
|
-- @param #table SpawnTemplate Template used for spawning.
|
||||||
-- @return #SPAWNSTATIC
|
-- @param DCS#country.id CountryID The ID of the country. Default `country.id.USA`.
|
||||||
function SPAWNSTATIC:NewFromType( SpawnTypeName, SpawnShapeName, SpawnCategory, SpawnCountryID, SpawnCoalitionID )
|
-- @return #SPAWNSTATIC self
|
||||||
|
function SPAWNSTATIC:NewFromTemplate(SpawnTemplate, CountryID)
|
||||||
|
|
||||||
local self = BASE:Inherit( self, BASE:New() ) -- #SPAWNSTATIC
|
local self = BASE:Inherit( self, BASE:New() ) -- #SPAWNSTATIC
|
||||||
self:F( { SpawnTypeName } )
|
|
||||||
|
|
||||||
self.SpawnTypeName = SpawnTypeName
|
self.TemplateStaticUnit = UTILS.DeepCopy(SpawnTemplate)
|
||||||
self.CountryID = SpawnCountryID
|
self.SpawnTemplatePrefix = SpawnTemplate.name
|
||||||
self.CoalitionID = SpawnCoalitionID
|
self.CountryID = CountryID or country.id.USA
|
||||||
self.SpawnIndex = 0
|
|
||||||
|
|
||||||
self:SetEventPriority( 5 )
|
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Creates the main object to spawn a @{Static} from a given type.
|
||||||
--- Creates a new @{Static} at the original position.
|
-- NOTE that you have to init many other parameters as spawn coordinate etc.
|
||||||
-- @param #SPAWNSTATIC self
|
-- @param #SPAWNSTATIC self
|
||||||
-- @param #number Heading The heading of the static, which is a number in degrees from 0 to 360.
|
-- @param #string StaticType Type of the static.
|
||||||
-- @param #string (optional) The name of the new static.
|
-- @param #string StaticCategory Category of the static, e.g. "Planes".
|
||||||
-- @return #SPAWNSTATIC
|
-- @param DCS#country.id CountryID The ID of the country. Default `country.id.USA`.
|
||||||
function SPAWNSTATIC:Spawn( Heading, NewName ) --R2.3
|
-- @return #SPAWNSTATIC self
|
||||||
self:F( { Heading, NewName } )
|
function SPAWNSTATIC:NewFromType(StaticType, StaticCategory, CountryID)
|
||||||
|
|
||||||
local StaticTemplate, CoalitionID, CategoryID, CountryID = _DATABASE:GetStaticGroupTemplate( self.SpawnTemplatePrefix )
|
local self = BASE:Inherit( self, BASE:New() ) -- #SPAWNSTATIC
|
||||||
|
|
||||||
if StaticTemplate then
|
self.InitStaticType=StaticType
|
||||||
|
self.InitStaticCategory=StaticCategory
|
||||||
|
self.CountryID=CountryID or country.id.USA
|
||||||
|
self.SpawnTemplatePrefix=self.InitStaticType
|
||||||
|
|
||||||
local StaticUnitTemplate = StaticTemplate.units[1]
|
self.InitStaticCoordinate=COORDINATE:New(0, 0, 0)
|
||||||
|
self.InitStaticHeading=0
|
||||||
|
|
||||||
StaticTemplate.name = NewName or string.format("%s#%05d", self.SpawnTemplatePrefix, self.SpawnIndex )
|
return self
|
||||||
StaticTemplate.heading = ( Heading / 180 ) * math.pi
|
|
||||||
|
|
||||||
_DATABASE:_RegisterStaticTemplate( StaticTemplate, CoalitionID, CategoryID, CountryID )
|
|
||||||
|
|
||||||
local Static = coalition.addStaticObject( self.CountryID or CountryID, StaticTemplate.units[1] )
|
|
||||||
|
|
||||||
self.SpawnIndex = self.SpawnIndex + 1
|
|
||||||
|
|
||||||
return _DATABASE:FindStatic(Static:getName())
|
|
||||||
end
|
|
||||||
|
|
||||||
return nil
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Initialize heading of the spawned static.
|
||||||
|
-- @param #SPAWNSTATIC self
|
||||||
|
-- @param Core.Point#COORDINATE Coordinate Position where the static is spawned.
|
||||||
|
-- @return #SPAWNSTATIC self
|
||||||
|
function SPAWNSTATIC:InitCoordinate(Coordinate)
|
||||||
|
self.InitStaticCoordinate=Coordinate
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Initialize heading of the spawned static.
|
||||||
|
-- @param #SPAWNSTATIC self
|
||||||
|
-- @param #number Heading The heading in degrees.
|
||||||
|
-- @return #SPAWNSTATIC self
|
||||||
|
function SPAWNSTATIC:InitHeading(Heading)
|
||||||
|
self.InitStaticHeading=Heading
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Initialize livery of the spawned static.
|
||||||
|
-- @param #SPAWNSTATIC self
|
||||||
|
-- @param #string LiveryName Name of the livery to use.
|
||||||
|
-- @return #SPAWNSTATIC self
|
||||||
|
function SPAWNSTATIC:InitLivery(LiveryName)
|
||||||
|
self.InitStaticLivery=LiveryName
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Initialize type of the spawned static.
|
||||||
|
-- @param #SPAWNSTATIC self
|
||||||
|
-- @param #string StaticType Type of the static, e.g. "FA-18C_hornet".
|
||||||
|
-- @return #SPAWNSTATIC self
|
||||||
|
function SPAWNSTATIC:InitType(StaticType)
|
||||||
|
self.InitStaticType=StaticType
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Initialize shape of the spawned static. Required by some but not all statics.
|
||||||
|
-- @param #SPAWNSTATIC self
|
||||||
|
-- @param #string StaticShape Shape of the static, e.g. "carrier_tech_USA".
|
||||||
|
-- @return #SPAWNSTATIC self
|
||||||
|
function SPAWNSTATIC:InitShape(StaticShape)
|
||||||
|
self.InitStaticShape=StaticShape
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Initialize cargo mass.
|
||||||
|
-- @param #SPAWNSTATIC self
|
||||||
|
-- @param #number Mass Mass of the cargo in kg.
|
||||||
|
-- @return #SPAWNSTATIC self
|
||||||
|
function SPAWNSTATIC:InitCargoMass(Mass)
|
||||||
|
self.InitCargoMass=Mass
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Initialize as cargo.
|
||||||
|
-- @param #SPAWNSTATIC self
|
||||||
|
-- @param #boolean IsCargo If true, this static can act as cargo.
|
||||||
|
-- @return #SPAWNSTATIC self
|
||||||
|
function SPAWNSTATIC:InitCargo(IsCargo)
|
||||||
|
self.InitCargo=IsCargo
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Initialize country of the spawned static. This determines the category.
|
||||||
|
-- @param #SPAWNSTATIC self
|
||||||
|
-- @param #string CountryID The country ID, e.g. country.id.USA.
|
||||||
|
-- @return #SPAWNSTATIC self
|
||||||
|
function SPAWNSTATIC:InitCountry(CountryID)
|
||||||
|
self.CountryID=CountryID
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Initialize name prefix statics get. This will be appended by "#0001", "#0002" etc.
|
||||||
|
-- @param #SPAWNSTATIC self
|
||||||
|
-- @param #string NamePrefix Name prefix of statics spawned. Will append #0001, etc to the name.
|
||||||
|
-- @return #SPAWNSTATIC self
|
||||||
|
function SPAWNSTATIC:InitNamePrefix(NamePrefix)
|
||||||
|
self.SpawnTemplatePrefix=NamePrefix
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Init link to a unit.
|
||||||
|
-- @param #SPAWNSTATIC self
|
||||||
|
-- @param Wrapper.Unit#UNIT Unit The unit to which the static is linked.
|
||||||
|
-- @param #number OffsetX Offset in X.
|
||||||
|
-- @param #number OffsetY Offset in Y.
|
||||||
|
-- @param #number OffsetAngle Offset angle in degrees.
|
||||||
|
-- @return #SPAWNSTATIC self
|
||||||
|
function SPAWNSTATIC:InitLinkToUnit(Unit, OffsetX, OffsetY, OffsetAngle)
|
||||||
|
|
||||||
|
self.InitLinkUnit=Unit
|
||||||
|
self.InitOffsetX=OffsetX or 0
|
||||||
|
self.InitOffsetY=OffsetY or 0
|
||||||
|
self.InitOffsetAngle=OffsetAngle or 0
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Spawn a new STATIC object.
|
||||||
|
-- @param #SPAWNSTATIC self
|
||||||
|
-- @param #number Heading (Optional) The heading of the static, which is a number in degrees from 0 to 360. Default is the heading of the template.
|
||||||
|
-- @param #string NewName (Optional) The name of the new static.
|
||||||
|
-- @return Wrapper.Static#STATIC The static spawned.
|
||||||
|
function SPAWNSTATIC:Spawn(Heading, NewName)
|
||||||
|
|
||||||
|
if Heading then
|
||||||
|
self.InitStaticHeading=Heading
|
||||||
|
end
|
||||||
|
|
||||||
|
if NewName then
|
||||||
|
self.InitStaticName=NewName
|
||||||
|
end
|
||||||
|
|
||||||
|
return self:_SpawnStatic(self.TemplateStaticUnit, self.CountryID)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
--- Creates a new @{Static} from a POINT_VEC2.
|
--- Creates a new @{Static} from a POINT_VEC2.
|
||||||
-- @param #SPAWNSTATIC self
|
-- @param #SPAWNSTATIC self
|
||||||
-- @param Core.Point#POINT_VEC2 PointVec2 The 2D coordinate where to spawn the static.
|
-- @param Core.Point#POINT_VEC2 PointVec2 The 2D coordinate where to spawn the static.
|
||||||
-- @param #number Heading The heading of the static, which is a number in degrees from 0 to 360.
|
-- @param #number Heading The heading of the static, which is a number in degrees from 0 to 360.
|
||||||
-- @param #string (optional) The name of the new static.
|
-- @param #string NewName (Optional) The name of the new static.
|
||||||
-- @return #SPAWNSTATIC
|
-- @return Wrapper.Static#STATIC The static spawned.
|
||||||
function SPAWNSTATIC:SpawnFromPointVec2( PointVec2, Heading, NewName ) --R2.1
|
function SPAWNSTATIC:SpawnFromPointVec2(PointVec2, Heading, NewName)
|
||||||
self:F( { PointVec2, Heading, NewName } )
|
|
||||||
|
|
||||||
local StaticTemplate, CoalitionID, CategoryID, CountryID = _DATABASE:GetStaticGroupTemplate( self.SpawnTemplatePrefix )
|
local vec2={x=PointVec2:GetX(), y=PointVec2:GetY()}
|
||||||
|
|
||||||
if StaticTemplate then
|
local Coordinate=COORDINATE:NewFromVec2(vec2)
|
||||||
|
|
||||||
local StaticUnitTemplate = StaticTemplate.units[1]
|
return self:SpawnFromCoordinate(Coordinate, Heading, NewName)
|
||||||
|
|
||||||
StaticUnitTemplate.x = PointVec2.x
|
|
||||||
StaticUnitTemplate.y = PointVec2.z
|
|
||||||
|
|
||||||
StaticTemplate.route = nil
|
|
||||||
StaticTemplate.groupId = nil
|
|
||||||
|
|
||||||
StaticTemplate.name = NewName or string.format("%s#%05d", self.SpawnTemplatePrefix, self.SpawnIndex )
|
|
||||||
StaticUnitTemplate.name = StaticTemplate.name
|
|
||||||
StaticUnitTemplate.heading = ( Heading / 180 ) * math.pi
|
|
||||||
|
|
||||||
_DATABASE:_RegisterStaticTemplate( StaticTemplate, CoalitionID, CategoryID, CountryID)
|
|
||||||
|
|
||||||
self:F({StaticTemplate = StaticTemplate})
|
|
||||||
|
|
||||||
local Static = coalition.addStaticObject( self.CountryID or CountryID, StaticTemplate.units[1] )
|
|
||||||
|
|
||||||
self.SpawnIndex = self.SpawnIndex + 1
|
|
||||||
|
|
||||||
return _DATABASE:FindStatic(Static:getName())
|
|
||||||
end
|
|
||||||
|
|
||||||
return nil
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Creates a new @{Static} from a COORDINATE.
|
--- Creates a new @{Static} from a COORDINATE.
|
||||||
-- @param #SPAWNSTATIC self
|
-- @param #SPAWNSTATIC self
|
||||||
-- @param Core.Point#COORDINATE Coordinate The 3D coordinate where to spawn the static.
|
-- @param Core.Point#COORDINATE Coordinate The 3D coordinate where to spawn the static.
|
||||||
-- @param #number Heading (Optional) Heading The heading of the static, which is a number in degrees from 0 to 360. Default is 0 degrees.
|
-- @param #number Heading (Optional) Heading The heading of the static in degrees. Default is 0 degrees.
|
||||||
-- @param #string NewName (Optional) The name of the new static.
|
-- @param #string NewName (Optional) The name of the new static.
|
||||||
-- @return #SPAWNSTATIC
|
-- @return Wrapper.Static#STATIC The spawned STATIC object.
|
||||||
function SPAWNSTATIC:SpawnFromCoordinate(Coordinate, Heading, NewName) --R2.4
|
function SPAWNSTATIC:SpawnFromCoordinate(Coordinate, Heading, NewName)
|
||||||
self:F( { PointVec2, Heading, NewName } )
|
|
||||||
|
|
||||||
local StaticTemplate, CoalitionID, CategoryID, CountryID = _DATABASE:GetStaticGroupTemplate( self.SpawnTemplatePrefix )
|
-- Set up coordinate.
|
||||||
|
self.InitStaticCoordinate=Coordinate
|
||||||
|
|
||||||
if StaticTemplate then
|
if Heading then
|
||||||
|
self.InitStaticHeading=Heading
|
||||||
Heading=Heading or 0
|
|
||||||
|
|
||||||
local StaticUnitTemplate = StaticTemplate.units[1]
|
|
||||||
|
|
||||||
StaticUnitTemplate.x = Coordinate.x
|
|
||||||
StaticUnitTemplate.y = Coordinate.z
|
|
||||||
StaticUnitTemplate.alt = Coordinate.y
|
|
||||||
|
|
||||||
StaticTemplate.route = nil
|
|
||||||
StaticTemplate.groupId = nil
|
|
||||||
|
|
||||||
StaticTemplate.name = NewName or string.format("%s#%05d", self.SpawnTemplatePrefix, self.SpawnIndex )
|
|
||||||
StaticUnitTemplate.name = StaticTemplate.name
|
|
||||||
StaticUnitTemplate.heading = ( Heading / 180 ) * math.pi
|
|
||||||
|
|
||||||
_DATABASE:_RegisterStaticTemplate( StaticTemplate, CoalitionID, CategoryID, CountryID)
|
|
||||||
|
|
||||||
self:F({StaticTemplate = StaticTemplate})
|
|
||||||
|
|
||||||
local Static = coalition.addStaticObject( self.CountryID or CountryID, StaticTemplate.units[1] )
|
|
||||||
|
|
||||||
self.SpawnIndex = self.SpawnIndex + 1
|
|
||||||
|
|
||||||
return _DATABASE:FindStatic(Static:getName())
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return nil
|
if NewName then
|
||||||
end
|
self.InitStaticName=NewName
|
||||||
|
|
||||||
|
|
||||||
--- Respawns the original @{Static}.
|
|
||||||
-- @param #SPAWNSTATIC self
|
|
||||||
-- @return #SPAWNSTATIC
|
|
||||||
function SPAWNSTATIC:ReSpawn()
|
|
||||||
|
|
||||||
local StaticTemplate, CoalitionID, CategoryID, CountryID = _DATABASE:GetStaticGroupTemplate( self.SpawnTemplatePrefix )
|
|
||||||
|
|
||||||
if StaticTemplate then
|
|
||||||
|
|
||||||
local StaticUnitTemplate = StaticTemplate.units[1]
|
|
||||||
StaticTemplate.route = nil
|
|
||||||
StaticTemplate.groupId = nil
|
|
||||||
|
|
||||||
local Static = coalition.addStaticObject( self.CountryID or CountryID, StaticTemplate.units[1] )
|
|
||||||
|
|
||||||
return _DATABASE:FindStatic(Static:getName())
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return nil
|
return self:_SpawnStatic(self.TemplateStaticUnit, self.CountryID)
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
--- Creates the original @{Static} at a POINT_VEC2.
|
|
||||||
-- @param #SPAWNSTATIC self
|
|
||||||
-- @param Core.Point#COORDINATE Coordinate The 2D coordinate where to spawn the static.
|
|
||||||
-- @param #number Heading The heading of the static, which is a number in degrees from 0 to 360.
|
|
||||||
-- @return #SPAWNSTATIC
|
|
||||||
function SPAWNSTATIC:ReSpawnAt( Coordinate, Heading )
|
|
||||||
|
|
||||||
local StaticTemplate, CoalitionID, CategoryID, CountryID = _DATABASE:GetStaticGroupTemplate( self.SpawnTemplatePrefix )
|
|
||||||
|
|
||||||
if StaticTemplate then
|
|
||||||
|
|
||||||
local StaticUnitTemplate = StaticTemplate.units[1]
|
|
||||||
|
|
||||||
StaticUnitTemplate.x = Coordinate.x
|
|
||||||
StaticUnitTemplate.y = Coordinate.z
|
|
||||||
|
|
||||||
StaticUnitTemplate.heading = Heading and ( ( Heading / 180 ) * math.pi ) or StaticTemplate.heading
|
|
||||||
|
|
||||||
local Static = coalition.addStaticObject( self.CountryID or CountryID, StaticTemplate.units[1] )
|
|
||||||
|
|
||||||
return _DATABASE:FindStatic(Static:getName())
|
|
||||||
end
|
|
||||||
|
|
||||||
return nil
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Creates a new @{Static} from a @{Zone}.
|
--- Creates a new @{Static} from a @{Zone}.
|
||||||
-- @param #SPAWNSTATIC self
|
-- @param #SPAWNSTATIC self
|
||||||
-- @param Core.Zone#ZONE_BASE Zone The Zone where to spawn the static.
|
-- @param Core.Zone#ZONE_BASE Zone The Zone where to spawn the static.
|
||||||
-- @param #number Heading The heading of the static, which is a number in degrees from 0 to 360.
|
-- @param #number Heading (Optional)The heading of the static in degrees. Default is the heading of the template.
|
||||||
-- @param #string NewName (optional) The name of the new static.
|
-- @param #string NewName (Optional) The name of the new static.
|
||||||
-- @return #SPAWNSTATIC
|
-- @return Wrapper.Static#STATIC The static spawned.
|
||||||
function SPAWNSTATIC:SpawnFromZone( Zone, Heading, NewName ) --R2.1
|
function SPAWNSTATIC:SpawnFromZone(Zone, Heading, NewName)
|
||||||
self:F( { Zone, Heading, NewName } )
|
|
||||||
|
|
||||||
|
-- Spawn the new static at the center of the zone.
|
||||||
local Static = self:SpawnFromPointVec2( Zone:GetPointVec2(), Heading, NewName )
|
local Static = self:SpawnFromPointVec2( Zone:GetPointVec2(), Heading, NewName )
|
||||||
|
|
||||||
return Static
|
return Static
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Spawns a new static using a given template. Additionally, the country ID needs to be specified, which also determines the coalition of the spawned static.
|
||||||
|
-- @param #SPAWNSTATIC self
|
||||||
|
-- @param #SPAWNSTATIC.TemplateData Template Spawn unit template.
|
||||||
|
-- @param #number CountryID The country ID.
|
||||||
|
-- @return Wrapper.Static#STATIC The static spawned.
|
||||||
|
function SPAWNSTATIC:_SpawnStatic(Template, CountryID)
|
||||||
|
|
||||||
|
Template=Template or {}
|
||||||
|
|
||||||
|
local CountryID=CountryID or self.CountryID
|
||||||
|
|
||||||
|
if self.InitStaticType then
|
||||||
|
Template.type=self.InitStaticType
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.InitStaticCategory then
|
||||||
|
Template.category=self.InitStaticCategory
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.InitStaticCoordinate then
|
||||||
|
Template.x = self.InitStaticCoordinate.x
|
||||||
|
Template.y = self.InitStaticCoordinate.z
|
||||||
|
Template.alt = self.InitStaticCoordinate.y
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.InitStaticHeading then
|
||||||
|
Template.heading = math.rad(self.InitStaticHeading)
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.InitStaticShape then
|
||||||
|
Template.shape_name=self.InitStaticShape
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.InitStaticLivery then
|
||||||
|
Template.livery_id=self.InitStaticLivery
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.InitDead~=nil then
|
||||||
|
Template.dead=self.InitDead
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.InitCargo~=nil then
|
||||||
|
Template.isCargo=self.InitCargo
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.InitLinkUnit then
|
||||||
|
Template.linkUnit=self.InitLinkUnit:GetID()
|
||||||
|
Template.linkOffset=true
|
||||||
|
Template.offsets={}
|
||||||
|
Template.offsets.y=self.InitOffsetY
|
||||||
|
Template.offsets.x=self.InitOffsetX
|
||||||
|
Template.offsets.angle=self.InitOffsetAngle and math.rad(self.InitOffsetAngle) or 0
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Increase spawn index counter.
|
||||||
|
self.SpawnIndex = self.SpawnIndex + 1
|
||||||
|
|
||||||
|
-- Name of the spawned static.
|
||||||
|
Template.name = self.InitStaticName or string.format("%s#%05d", self.SpawnTemplatePrefix, self.SpawnIndex)
|
||||||
|
|
||||||
|
-- Register the new static.
|
||||||
|
--_DATABASE:_RegisterStaticTemplate(Template, self.CoalitionID, self.CategoryID, CountryID)
|
||||||
|
_DATABASE:AddStatic(Template.name)
|
||||||
|
|
||||||
|
-- Debug output.
|
||||||
|
self:T(Template)
|
||||||
|
|
||||||
|
-- Add static to the game.
|
||||||
|
local Static=coalition.addStaticObject(CountryID, Template)
|
||||||
|
|
||||||
|
|
||||||
|
return _DATABASE:FindStatic(Static:getName())
|
||||||
|
end
|
||||||
|
|||||||
@@ -0,0 +1,274 @@
|
|||||||
|
--- **Core** - Timer scheduler.
|
||||||
|
--
|
||||||
|
-- **Main Features:**
|
||||||
|
--
|
||||||
|
-- * Delay function calls
|
||||||
|
-- * Easy set up and little overhead
|
||||||
|
-- * Set start, stop and time interval
|
||||||
|
-- * Define max function calls
|
||||||
|
--
|
||||||
|
-- ===
|
||||||
|
--
|
||||||
|
-- ### Author: **funkyfranky**
|
||||||
|
-- @module Core.Timer
|
||||||
|
-- @image CORE_Timer.png
|
||||||
|
|
||||||
|
|
||||||
|
--- TIMER class.
|
||||||
|
-- @type TIMER
|
||||||
|
-- @field #string ClassName Name of the class.
|
||||||
|
-- @field #string lid Class id string for output to DCS log file.
|
||||||
|
-- @field #number tid Timer ID returned by the DCS API function.
|
||||||
|
-- @field #function func Timer function.
|
||||||
|
-- @field #table para Parameters passed to the timer function.
|
||||||
|
-- @field #number Tstart Relative start time in seconds.
|
||||||
|
-- @field #number Tstop Relative stop time in seconds.
|
||||||
|
-- @field #number dT Time interval between function calls in seconds.
|
||||||
|
-- @field #number ncalls Counter of function calls.
|
||||||
|
-- @field #number ncallsMax Max number of function calls. If reached, timer is stopped.
|
||||||
|
-- @extends Core.Base#BASE
|
||||||
|
|
||||||
|
--- *Better three hours too soon than a minute too late.* – William Shakespeare
|
||||||
|
--
|
||||||
|
-- ===
|
||||||
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
|
-- # The TIMER Concept
|
||||||
|
--
|
||||||
|
-- The TIMER class is the little sister of the SCHEDULER class. It does the same thing but is a bit easier to use and has less overhead. It should be sufficient in many cases.
|
||||||
|
--
|
||||||
|
-- It provides an easy interface to the DCS [timer.scheduleFunction](https://wiki.hoggitworld.com/view/DCS_func_scheduleFunction).
|
||||||
|
--
|
||||||
|
-- # Construction
|
||||||
|
--
|
||||||
|
-- A new TIMER is created by the @{#TIMER.New}(*func*, *...*) function
|
||||||
|
--
|
||||||
|
-- local mytimer=TIMER:New(myfunction, a, b)
|
||||||
|
--
|
||||||
|
-- The first parameter *func* is the function that is called followed by the necessary comma separeted parameters that are passed to that function.
|
||||||
|
--
|
||||||
|
-- ## Starting the Timer
|
||||||
|
--
|
||||||
|
-- The timer is started by the @{#TIMER.Start}(*Tstart*, *dT*, *Duration*) function
|
||||||
|
--
|
||||||
|
-- mytimer:Start(5, 1, 20)
|
||||||
|
--
|
||||||
|
-- where
|
||||||
|
--
|
||||||
|
-- * *Tstart* is the relative start time in seconds. In the example, the first function call happens after 5 sec.
|
||||||
|
-- * *dT* is the time interval between function calls in seconds. Above, the function is called once per second.
|
||||||
|
-- * *Duration* is the duration in seconds after which the timer is stopped. This is relative to the start time. Here, the timer will run for 20 seconds.
|
||||||
|
--
|
||||||
|
-- Note that
|
||||||
|
--
|
||||||
|
-- * if *Tstart* is not specified (*nil*), the first function call happens immediately.
|
||||||
|
-- * if *dT* is not specified (*nil*), the function is called only once.
|
||||||
|
-- * if *Duration* is not specified (*nil*), the timer runs forever or until stopped manually or until the max function calls are reached (see below).
|
||||||
|
--
|
||||||
|
-- For example,
|
||||||
|
--
|
||||||
|
-- mytimer:Start(3) -- Will call the function once after 3 seconds.
|
||||||
|
-- mytimer:Start(nil, 0.5) -- Will call right now and then every 0.5 sec until all eternaty.
|
||||||
|
-- mytimer:Start(nil, 2.0, 20) -- Will call right now and then every 2.0 sec for 20 sec.
|
||||||
|
-- mytimer:Start(1.0, nil, 10) -- Does not make sense as the function is only called once anyway.
|
||||||
|
--
|
||||||
|
-- ## Stopping the Timer
|
||||||
|
--
|
||||||
|
-- The timer can be stopped manually by the @{#TIMER.Start}(*Delay*) function
|
||||||
|
--
|
||||||
|
-- mytimer:Stop()
|
||||||
|
--
|
||||||
|
-- If the optional paramter *Delay* is specified, the timer is stopped after *delay* seconds.
|
||||||
|
--
|
||||||
|
-- ## Limit Function Calls
|
||||||
|
--
|
||||||
|
-- The timer can be stopped after a certain amount of function calles with the @{#TIMER.SetMaxFunctionCalls}(*Nmax*) function
|
||||||
|
--
|
||||||
|
-- mytimer:SetMaxFunctionCalls(20)
|
||||||
|
--
|
||||||
|
-- where *Nmax* is the number of calls after which the timer is stopped, here 20.
|
||||||
|
--
|
||||||
|
-- For example,
|
||||||
|
--
|
||||||
|
-- mytimer:SetMaxFunctionCalls(66):Start(1.0, 0.1)
|
||||||
|
--
|
||||||
|
-- will start the timer after one second and call the function every 0.1 seconds. Once the function has been called 66 times, the timer is stopped.
|
||||||
|
--
|
||||||
|
--
|
||||||
|
-- @field #TIMER
|
||||||
|
TIMER = {
|
||||||
|
ClassName = "TIMER",
|
||||||
|
lid = nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
--- Timer ID.
|
||||||
|
_TIMERID=0
|
||||||
|
|
||||||
|
--- Timer data base.
|
||||||
|
--_TIMERDB={}
|
||||||
|
|
||||||
|
--- TIMER class version.
|
||||||
|
-- @field #string version
|
||||||
|
TIMER.version="0.1.0"
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-- TODO list
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-- TODO: A lot.
|
||||||
|
-- TODO: Write docs.
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-- Constructor
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- Create a new TIMER object.
|
||||||
|
-- @param #TIMER self
|
||||||
|
-- @param #function Function The function to call.
|
||||||
|
-- @param ... Parameters passed to the function if any.
|
||||||
|
-- @return #TIMER self
|
||||||
|
function TIMER:New(Function, ...)
|
||||||
|
|
||||||
|
-- Inherit BASE.
|
||||||
|
local self=BASE:Inherit(self, BASE:New()) --#TIMER
|
||||||
|
|
||||||
|
-- Function to call.
|
||||||
|
self.func=Function
|
||||||
|
|
||||||
|
-- Function arguments.
|
||||||
|
self.para=arg or {}
|
||||||
|
|
||||||
|
-- Number of function calls.
|
||||||
|
self.ncalls=0
|
||||||
|
|
||||||
|
-- Increase counter
|
||||||
|
_TIMERID=_TIMERID+1
|
||||||
|
|
||||||
|
-- Set UID.
|
||||||
|
self.uid=_TIMERID
|
||||||
|
|
||||||
|
-- Log id.
|
||||||
|
self.lid=string.format("TIMER UID=%d | ", self.uid)
|
||||||
|
|
||||||
|
-- Add to DB.
|
||||||
|
--_TIMERDB[self.uid]=self
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Create a new TIMER object.
|
||||||
|
-- @param #TIMER self
|
||||||
|
-- @param #number Tstart Relative start time in seconds.
|
||||||
|
-- @param #number dT Interval between function calls in seconds. If not specified `nil`, the function is called only once.
|
||||||
|
-- @param #number Duration Time in seconds for how long the timer is running. If not specified `nil`, the timer runs forever or until stopped manually by the `TIMER:Stop()` function.
|
||||||
|
-- @return #TIMER self
|
||||||
|
function TIMER:Start(Tstart, dT, Duration)
|
||||||
|
|
||||||
|
-- Current time.
|
||||||
|
local Tnow=timer.getTime()
|
||||||
|
|
||||||
|
-- Start time in sec.
|
||||||
|
self.Tstart=Tstart and Tnow+Tstart or Tnow+0.001 -- one millisecond delay if Tstart=nil
|
||||||
|
|
||||||
|
-- Set time interval.
|
||||||
|
self.dT=dT
|
||||||
|
|
||||||
|
-- Stop time.
|
||||||
|
if Duration then
|
||||||
|
self.Tstop=self.Tstart+Duration
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Call DCS timer function.
|
||||||
|
self.tid=timer.scheduleFunction(self._Function, self, self.Tstart)
|
||||||
|
|
||||||
|
-- Set log id.
|
||||||
|
self.lid=string.format("TIMER UID=%d/%d | ", self.uid, self.tid)
|
||||||
|
|
||||||
|
-- Debug info.
|
||||||
|
self:T(self.lid..string.format("Starting Timer in %.3f sec, dT=%s, Tstop=%s", self.Tstart-Tnow, tostring(self.dT), tostring(self.Tstop)))
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Stop the timer by removing the timer function.
|
||||||
|
-- @param #TIMER self
|
||||||
|
-- @param #number Delay (Optional) Delay in seconds, before the timer is stopped.
|
||||||
|
-- @return #TIMER self
|
||||||
|
function TIMER:Stop(Delay)
|
||||||
|
|
||||||
|
if Delay and Delay>0 then
|
||||||
|
|
||||||
|
self.Tstop=timer.getTime()+Delay
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
if self.tid then
|
||||||
|
|
||||||
|
-- Remove timer function.
|
||||||
|
self:T(self.lid..string.format("Stopping timer by removing timer function after %d calls!", self.ncalls))
|
||||||
|
timer.removeFunction(self.tid)
|
||||||
|
|
||||||
|
-- Remove DB entry.
|
||||||
|
--_TIMERDB[self.uid]=nil
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set max number of function calls. When the function has been called this many times, the TIMER is stopped.
|
||||||
|
-- @param #TIMER self
|
||||||
|
-- @param #number Nmax Set number of max function calls.
|
||||||
|
-- @return #TIMER self
|
||||||
|
function TIMER:SetMaxFunctionCalls(Nmax)
|
||||||
|
self.ncallsMax=Nmax
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Call timer function.
|
||||||
|
-- @param #TIMER self
|
||||||
|
-- @param #number time DCS model time in seconds.
|
||||||
|
-- @return #number Time when the function is called again or `nil` if the timer is stopped.
|
||||||
|
function TIMER:_Function(time)
|
||||||
|
|
||||||
|
-- Call function.
|
||||||
|
self.func(unpack(self.para))
|
||||||
|
|
||||||
|
-- Increase number of calls.
|
||||||
|
self.ncalls=self.ncalls+1
|
||||||
|
|
||||||
|
-- Next time.
|
||||||
|
local Tnext=self.dT and time+self.dT or nil
|
||||||
|
|
||||||
|
-- Check if we stop the timer.
|
||||||
|
local stopme=false
|
||||||
|
if Tnext==nil then
|
||||||
|
-- No next time.
|
||||||
|
self:T(self.lid..string.format("No next time as dT=nil ==> Stopping timer after %d function calls", self.ncalls))
|
||||||
|
stopme=true
|
||||||
|
elseif self.Tstop and Tnext>self.Tstop then
|
||||||
|
-- Stop time passed.
|
||||||
|
self:T(self.lid..string.format("Stop time passed %.3f > %.3f ==> Stopping timer after %d function calls", Tnext, self.Tstop, self.ncalls))
|
||||||
|
stopme=true
|
||||||
|
elseif self.ncallsMax and self.ncalls>=self.ncallsMax then
|
||||||
|
-- Number of max function calls reached.
|
||||||
|
self:T(self.lid..string.format("Max function calls Nmax=%d reached ==> Stopping timer after %d function calls", self.ncallsMax, self.ncalls))
|
||||||
|
stopme=true
|
||||||
|
end
|
||||||
|
|
||||||
|
if stopme then
|
||||||
|
-- Remove timer function.
|
||||||
|
self:Stop()
|
||||||
|
return nil
|
||||||
|
else
|
||||||
|
-- Call again in Tnext seconds.
|
||||||
|
return Tnext
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
@@ -19,6 +19,8 @@
|
|||||||
do -- UserFlag
|
do -- UserFlag
|
||||||
|
|
||||||
--- @type USERFLAG
|
--- @type USERFLAG
|
||||||
|
-- @field #string ClassName Name of the class
|
||||||
|
-- @field #string UserFlagName Name of the flag.
|
||||||
-- @extends Core.Base#BASE
|
-- @extends Core.Base#BASE
|
||||||
|
|
||||||
|
|
||||||
@@ -30,7 +32,8 @@ do -- UserFlag
|
|||||||
--
|
--
|
||||||
-- @field #USERFLAG
|
-- @field #USERFLAG
|
||||||
USERFLAG = {
|
USERFLAG = {
|
||||||
ClassName = "USERFLAG",
|
ClassName = "USERFLAG",
|
||||||
|
UserFlagName = nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
--- USERFLAG Constructor.
|
--- USERFLAG Constructor.
|
||||||
@@ -46,18 +49,30 @@ do -- UserFlag
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Get the userflag name.
|
||||||
|
-- @param #USERFLAG self
|
||||||
|
-- @return #string Name of the user flag.
|
||||||
|
function USERFLAG:GetName()
|
||||||
|
return self.UserFlagName
|
||||||
|
end
|
||||||
|
|
||||||
--- Set the userflag to a given Number.
|
--- Set the userflag to a given Number.
|
||||||
-- @param #USERFLAG self
|
-- @param #USERFLAG self
|
||||||
-- @param #number Number The number value to be checked if it is the same as the userflag.
|
-- @param #number Number The number value to be checked if it is the same as the userflag.
|
||||||
|
-- @param #number Delay Delay in seconds, before the flag is set.
|
||||||
-- @return #USERFLAG The userflag instance.
|
-- @return #USERFLAG The userflag instance.
|
||||||
-- @usage
|
-- @usage
|
||||||
-- local BlueVictory = USERFLAG:New( "VictoryBlue" )
|
-- local BlueVictory = USERFLAG:New( "VictoryBlue" )
|
||||||
-- BlueVictory:Set( 100 ) -- Set the UserFlag VictoryBlue to 100.
|
-- BlueVictory:Set( 100 ) -- Set the UserFlag VictoryBlue to 100.
|
||||||
--
|
--
|
||||||
function USERFLAG:Set( Number ) --R2.3
|
function USERFLAG:Set( Number, Delay ) --R2.3
|
||||||
|
|
||||||
trigger.action.setUserFlag( self.UserFlagName, Number )
|
if Delay and Delay>0 then
|
||||||
|
self:ScheduleOnce(Delay, USERFLAG.Set, self, Number)
|
||||||
|
else
|
||||||
|
--env.info(string.format("Setting flag \"%s\" to %d at T=%.1f", self.UserFlagName, Number, timer.getTime()))
|
||||||
|
trigger.action.setUserFlag( self.UserFlagName, Number )
|
||||||
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -56,7 +56,7 @@
|
|||||||
--- @type ZONE_BASE
|
--- @type ZONE_BASE
|
||||||
-- @field #string ZoneName Name of the zone.
|
-- @field #string ZoneName Name of the zone.
|
||||||
-- @field #number ZoneProbability A value between 0 and 1. 0 = 0% and 1 = 100% probability.
|
-- @field #number ZoneProbability A value between 0 and 1. 0 = 0% and 1 = 100% probability.
|
||||||
-- @extends Core.Base#BASE
|
-- @extends Core.Fsm#FSM
|
||||||
|
|
||||||
|
|
||||||
--- This class is an abstract BASE class for derived classes, and is not meant to be instantiated.
|
--- This class is an abstract BASE class for derived classes, and is not meant to be instantiated.
|
||||||
@@ -686,29 +686,47 @@ function ZONE_RADIUS:Scan( ObjectCategories, UnitCategories )
|
|||||||
local function EvaluateZone( ZoneObject )
|
local function EvaluateZone( ZoneObject )
|
||||||
--if ZoneObject:isExist() then --FF: isExist always returns false for SCENERY objects since DCS 2.2 and still in DCS 2.5
|
--if ZoneObject:isExist() then --FF: isExist always returns false for SCENERY objects since DCS 2.2 and still in DCS 2.5
|
||||||
if ZoneObject then
|
if ZoneObject then
|
||||||
|
|
||||||
local ObjectCategory = ZoneObject:getCategory()
|
local ObjectCategory = ZoneObject:getCategory()
|
||||||
if ( ObjectCategory == Object.Category.UNIT and ZoneObject:isExist() and ZoneObject:isActive() ) or
|
|
||||||
(ObjectCategory == Object.Category.STATIC and ZoneObject:isExist()) then
|
--local name=ZoneObject:getName()
|
||||||
|
--env.info(string.format("Zone object %s", tostring(name)))
|
||||||
|
--self:E(ZoneObject)
|
||||||
|
|
||||||
|
if ( ObjectCategory == Object.Category.UNIT and ZoneObject:isExist() and ZoneObject:isActive() ) or (ObjectCategory == Object.Category.STATIC and ZoneObject:isExist()) then
|
||||||
|
|
||||||
local CoalitionDCSUnit = ZoneObject:getCoalition()
|
local CoalitionDCSUnit = ZoneObject:getCoalition()
|
||||||
|
|
||||||
local Include = false
|
local Include = false
|
||||||
if not UnitCategories then
|
if not UnitCategories then
|
||||||
|
-- Anythink found is included.
|
||||||
Include = true
|
Include = true
|
||||||
else
|
else
|
||||||
|
-- Check if found object is in specified categories.
|
||||||
local CategoryDCSUnit = ZoneObject:getDesc().category
|
local CategoryDCSUnit = ZoneObject:getDesc().category
|
||||||
|
|
||||||
for UnitCategoryID, UnitCategory in pairs( UnitCategories ) do
|
for UnitCategoryID, UnitCategory in pairs( UnitCategories ) do
|
||||||
if UnitCategory == CategoryDCSUnit then
|
if UnitCategory == CategoryDCSUnit then
|
||||||
Include = true
|
Include = true
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if Include then
|
if Include then
|
||||||
|
|
||||||
local CoalitionDCSUnit = ZoneObject:getCoalition()
|
local CoalitionDCSUnit = ZoneObject:getCoalition()
|
||||||
|
|
||||||
|
-- This coalition is inside the zone.
|
||||||
self.ScanData.Coalitions[CoalitionDCSUnit] = true
|
self.ScanData.Coalitions[CoalitionDCSUnit] = true
|
||||||
|
|
||||||
self.ScanData.Units[ZoneObject] = ZoneObject
|
self.ScanData.Units[ZoneObject] = ZoneObject
|
||||||
|
|
||||||
self:F2( { Name = ZoneObject:getName(), Coalition = CoalitionDCSUnit } )
|
self:F2( { Name = ZoneObject:getName(), Coalition = CoalitionDCSUnit } )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if ObjectCategory == Object.Category.SCENERY then
|
if ObjectCategory == Object.Category.SCENERY then
|
||||||
local SceneryType = ZoneObject:getTypeName()
|
local SceneryType = ZoneObject:getTypeName()
|
||||||
local SceneryName = ZoneObject:getName()
|
local SceneryName = ZoneObject:getName()
|
||||||
@@ -716,21 +734,29 @@ function ZONE_RADIUS:Scan( ObjectCategories, UnitCategories )
|
|||||||
self.ScanData.Scenery[SceneryType][SceneryName] = SCENERY:Register( SceneryName, ZoneObject )
|
self.ScanData.Scenery[SceneryType][SceneryName] = SCENERY:Register( SceneryName, ZoneObject )
|
||||||
self:F2( { SCENERY = self.ScanData.Scenery[SceneryType][SceneryName] } )
|
self:F2( { SCENERY = self.ScanData.Scenery[SceneryType][SceneryName] } )
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Search objects.
|
||||||
world.searchObjects( ObjectCategories, SphereSearch, EvaluateZone )
|
world.searchObjects( ObjectCategories, SphereSearch, EvaluateZone )
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Count the number of different coalitions inside the zone.
|
||||||
|
-- @param #ZONE_RADIUS self
|
||||||
|
-- @return #table Table of DCS units and DCS statics inside the zone.
|
||||||
function ZONE_RADIUS:GetScannedUnits()
|
function ZONE_RADIUS:GetScannedUnits()
|
||||||
|
|
||||||
return self.ScanData.Units
|
return self.ScanData.Units
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Get a set of scanned units.
|
||||||
|
-- @param #ZONE_RADIUS self
|
||||||
|
-- @return Core.Set#SET_UNIT Set of units and statics inside the zone.
|
||||||
function ZONE_RADIUS:GetScannedSetUnit()
|
function ZONE_RADIUS:GetScannedSetUnit()
|
||||||
|
|
||||||
local SetUnit = SET_UNIT:New()
|
local SetUnit = SET_UNIT:New()
|
||||||
@@ -756,6 +782,9 @@ function ZONE_RADIUS:GetScannedSetUnit()
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Count the number of different coalitions inside the zone.
|
||||||
|
-- @param #ZONE_RADIUS self
|
||||||
|
-- @return #number Counted coalitions.
|
||||||
function ZONE_RADIUS:CountScannedCoalitions()
|
function ZONE_RADIUS:CountScannedCoalitions()
|
||||||
|
|
||||||
local Count = 0
|
local Count = 0
|
||||||
@@ -763,14 +792,25 @@ function ZONE_RADIUS:CountScannedCoalitions()
|
|||||||
for CoalitionID, Coalition in pairs( self.ScanData.Coalitions ) do
|
for CoalitionID, Coalition in pairs( self.ScanData.Coalitions ) do
|
||||||
Count = Count + 1
|
Count = Count + 1
|
||||||
end
|
end
|
||||||
|
|
||||||
return Count
|
return Count
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Check if a certain coalition is inside a scanned zone.
|
||||||
|
-- @param #ZONE_RADIUS self
|
||||||
|
-- @param #number Coalition The coalition id, e.g. coalition.side.BLUE.
|
||||||
|
-- @return #boolean If true, the coalition is inside the zone.
|
||||||
|
function ZONE_RADIUS:CheckScannedCoalition( Coalition )
|
||||||
|
if Coalition then
|
||||||
|
return self.ScanData.Coalitions[Coalition]
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
--- Get Coalitions of the units in the Zone, or Check if there are units of the given Coalition in the Zone.
|
--- Get Coalitions of the units in the Zone, or Check if there are units of the given Coalition in the Zone.
|
||||||
-- Returns nil if there are none ot two Coalitions in the zone!
|
-- Returns nil if there are none to two Coalitions in the zone!
|
||||||
-- Returns one Coalition if there are only Units of one Coalition in the Zone.
|
-- Returns one Coalition if there are only Units of one Coalition in the Zone.
|
||||||
-- Returns the Coalition for the given Coalition if there are units of the Coalition in the Zone
|
-- Returns the Coalition for the given Coalition if there are units of the Coalition in the Zone.
|
||||||
-- @param #ZONE_RADIUS self
|
-- @param #ZONE_RADIUS self
|
||||||
-- @return #table
|
-- @return #table
|
||||||
function ZONE_RADIUS:GetScannedCoalition( Coalition )
|
function ZONE_RADIUS:GetScannedCoalition( Coalition )
|
||||||
@@ -795,20 +835,27 @@ function ZONE_RADIUS:GetScannedCoalition( Coalition )
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Get scanned scenery type
|
||||||
|
-- @param #ZONE_RADIUS self
|
||||||
|
-- @return #table Table of DCS scenery type objects.
|
||||||
function ZONE_RADIUS:GetScannedSceneryType( SceneryType )
|
function ZONE_RADIUS:GetScannedSceneryType( SceneryType )
|
||||||
return self.ScanData.Scenery[SceneryType]
|
return self.ScanData.Scenery[SceneryType]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Get scanned scenery table
|
||||||
|
-- @param #ZONE_RADIUS self
|
||||||
|
-- @return #table Table of DCS scenery objects.
|
||||||
function ZONE_RADIUS:GetScannedScenery()
|
function ZONE_RADIUS:GetScannedScenery()
|
||||||
return self.ScanData.Scenery
|
return self.ScanData.Scenery
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Is All in Zone of Coalition?
|
--- Is All in Zone of Coalition?
|
||||||
|
-- Check if only the specifed coalition is inside the zone and noone else.
|
||||||
-- @param #ZONE_RADIUS self
|
-- @param #ZONE_RADIUS self
|
||||||
-- @param Coalition
|
-- @param #number Coalition Coalition ID of the coalition which is checked to be the only one in the zone.
|
||||||
-- @return #boolean
|
-- @return #boolean True, if **only** that coalition is inside the zone and no one else.
|
||||||
-- @usage
|
-- @usage
|
||||||
-- self.Zone:Scan()
|
-- self.Zone:Scan()
|
||||||
-- local IsGuarded = self.Zone:IsAllInZoneOfCoalition( self.Coalition )
|
-- local IsGuarded = self.Zone:IsAllInZoneOfCoalition( self.Coalition )
|
||||||
@@ -820,11 +867,12 @@ end
|
|||||||
|
|
||||||
|
|
||||||
--- Is All in Zone of Other Coalition?
|
--- Is All in Zone of Other Coalition?
|
||||||
|
-- Check if only one coalition is inside the zone and the specified coalition is not the one.
|
||||||
-- You first need to use the @{#ZONE_RADIUS.Scan} method to scan the zone before it can be evaluated!
|
-- You first need to use the @{#ZONE_RADIUS.Scan} method to scan the zone before it can be evaluated!
|
||||||
-- Note that once a zone has been scanned, multiple evaluations can be done on the scan result set.
|
-- Note that once a zone has been scanned, multiple evaluations can be done on the scan result set.
|
||||||
-- @param #ZONE_RADIUS self
|
-- @param #ZONE_RADIUS self
|
||||||
-- @param Coalition
|
-- @param #number Coalition Coalition ID of the coalition which is not supposed to be in the zone.
|
||||||
-- @return #boolean
|
-- @return #boolean True, if and only if only one coalition is inside the zone and the specified coalition is not it.
|
||||||
-- @usage
|
-- @usage
|
||||||
-- self.Zone:Scan()
|
-- self.Zone:Scan()
|
||||||
-- local IsCaptured = self.Zone:IsAllInZoneOfOtherCoalition( self.Coalition )
|
-- local IsCaptured = self.Zone:IsAllInZoneOfOtherCoalition( self.Coalition )
|
||||||
@@ -836,11 +884,12 @@ end
|
|||||||
|
|
||||||
|
|
||||||
--- Is Some in Zone of Coalition?
|
--- Is Some in Zone of Coalition?
|
||||||
|
-- Check if more than one coaltion is inside the zone and the specifed coalition is one of them.
|
||||||
-- You first need to use the @{#ZONE_RADIUS.Scan} method to scan the zone before it can be evaluated!
|
-- You first need to use the @{#ZONE_RADIUS.Scan} method to scan the zone before it can be evaluated!
|
||||||
-- Note that once a zone has been scanned, multiple evaluations can be done on the scan result set.
|
-- Note that once a zone has been scanned, multiple evaluations can be done on the scan result set.
|
||||||
-- @param #ZONE_RADIUS self
|
-- @param #ZONE_RADIUS self
|
||||||
-- @param Coalition
|
-- @param #number Coalition ID of the coaliton which is checked to be inside the zone.
|
||||||
-- @return #boolean
|
-- @return #boolean True if more than one coalition is inside the zone and the specified coalition is one of them.
|
||||||
-- @usage
|
-- @usage
|
||||||
-- self.Zone:Scan()
|
-- self.Zone:Scan()
|
||||||
-- local IsAttacked = self.Zone:IsSomeInZoneOfCoalition( self.Coalition )
|
-- local IsAttacked = self.Zone:IsSomeInZoneOfCoalition( self.Coalition )
|
||||||
@@ -904,7 +953,6 @@ function ZONE_RADIUS:SearchZone( EvaluateFunction, ObjectCategories )
|
|||||||
|
|
||||||
local function EvaluateZone( ZoneDCSUnit )
|
local function EvaluateZone( ZoneDCSUnit )
|
||||||
|
|
||||||
env.info( ZoneDCSUnit:getName() )
|
|
||||||
|
|
||||||
local ZoneUnit = UNIT:Find( ZoneDCSUnit )
|
local ZoneUnit = UNIT:Find( ZoneDCSUnit )
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
--- DCS API prototypes
|
--- **DCS API** Prototypes
|
||||||
-- See [https://wiki.hoggitworld.com/view/Simulator_Scripting_Engine_Documentation](https://wiki.hoggitworld.com/view/Simulator_Scripting_Engine_Documentation)
|
--
|
||||||
-- for further explanation and examples.
|
-- See the [Simulator Scripting Engine Documentation](https://wiki.hoggitworld.com/view/Simulator_Scripting_Engine_Documentation) on Hoggit for further explanation and examples.
|
||||||
|
--
|
||||||
-- @module DCS
|
-- @module DCS
|
||||||
-- @image MOOSE.JPG
|
-- @image MOOSE.JPG
|
||||||
|
|
||||||
@@ -46,9 +47,13 @@ do -- world
|
|||||||
-- @field S_EVENT_PLAYER_COMMENT
|
-- @field S_EVENT_PLAYER_COMMENT
|
||||||
-- @field S_EVENT_SHOOTING_START [https://wiki.hoggitworld.com/view/DCS_event_shooting_start](https://wiki.hoggitworld.com/view/DCS_event_shooting_start)
|
-- @field S_EVENT_SHOOTING_START [https://wiki.hoggitworld.com/view/DCS_event_shooting_start](https://wiki.hoggitworld.com/view/DCS_event_shooting_start)
|
||||||
-- @field S_EVENT_SHOOTING_END [https://wiki.hoggitworld.com/view/DCS_event_shooting_end](https://wiki.hoggitworld.com/view/DCS_event_shooting_end)
|
-- @field S_EVENT_SHOOTING_END [https://wiki.hoggitworld.com/view/DCS_event_shooting_end](https://wiki.hoggitworld.com/view/DCS_event_shooting_end)
|
||||||
-- @field S_EVENT_MARK ADDED [https://wiki.hoggitworld.com/view/DCS_event_mark_added](https://wiki.hoggitworld.com/view/DCS_event_mark_added)
|
-- @field S_EVENT_MARK ADDED [https://wiki.hoggitworld.com/view/DCS_event_mark_added](https://wiki.hoggitworld.com/view/DCS_event_mark_added) DCS>=2.5.1
|
||||||
-- @field S_EVENT_MARK CHANGE [https://wiki.hoggitworld.com/view/DCS_event_mark_change](https://wiki.hoggitworld.com/view/DCS_event_mark_change)
|
-- @field S_EVENT_MARK CHANGE [https://wiki.hoggitworld.com/view/DCS_event_mark_change](https://wiki.hoggitworld.com/view/DCS_event_mark_change) DCS>=2.5.1
|
||||||
-- @field S_EVENT_MARK REMOVE [https://wiki.hoggitworld.com/view/DCS_event_mark_remove](https://wiki.hoggitworld.com/view/DCS_event_mark_remove)
|
-- @field S_EVENT_MARK REMOVE [https://wiki.hoggitworld.com/view/DCS_event_mark_remove](https://wiki.hoggitworld.com/view/DCS_event_mark_remove) DCS>=2.5.1
|
||||||
|
-- @field S_EVENT_KILL [https://wiki.hoggitworld.com/view/DCS_event_kill](https://wiki.hoggitworld.com/view/DCS_event_kill) DCS>=2.5.6
|
||||||
|
-- @field S_EVENT_SCORE [https://wiki.hoggitworld.com/view/DCS_event_score](https://wiki.hoggitworld.com/view/DCS_event_score) DCS>=2.5.6
|
||||||
|
-- @field S_EVENT_UNIT_LOST [https://wiki.hoggitworld.com/view/DCS_event_unit_lost](https://wiki.hoggitworld.com/view/DCS_event_unit_lost) DCS>=2.5.6
|
||||||
|
-- @field S_EVENT_LANDING_AFTER_EJECTION [https://wiki.hoggitworld.com/view/DCS_event_landing_after_ejection](https://wiki.hoggitworld.com/view/DCS_event_landing_after_ejection) DCS>=2.5.6
|
||||||
-- @field S_EVENT_MAX
|
-- @field S_EVENT_MAX
|
||||||
|
|
||||||
--- The birthplace enumerator is used to define where an aircraft or helicopter has spawned in association with birth events.
|
--- The birthplace enumerator is used to define where an aircraft or helicopter has spawned in association with birth events.
|
||||||
@@ -91,6 +96,11 @@ do -- world
|
|||||||
-- @function [parent=#world] getMarkPanels
|
-- @function [parent=#world] getMarkPanels
|
||||||
-- @return #table Table of marks.
|
-- @return #table Table of marks.
|
||||||
|
|
||||||
|
--- Returns a table of DCS airbase objects.
|
||||||
|
-- @function [parent=#world] getAirbases
|
||||||
|
-- @param #number coalitionId The coalition side number ID. Default is all airbases are returned.
|
||||||
|
-- @return #table Table of DCS airbase objects.
|
||||||
|
|
||||||
end -- world
|
end -- world
|
||||||
|
|
||||||
|
|
||||||
@@ -325,9 +335,27 @@ end -- coalition
|
|||||||
do -- Types
|
do -- Types
|
||||||
|
|
||||||
--- @type Desc
|
--- @type Desc
|
||||||
-- @field #TypeName typeName type name
|
-- @field #number speedMax0 Max speed in meters/second at zero altitude.
|
||||||
-- @field #string displayName localized display name
|
-- @field #number massEmpty Empty mass in kg.
|
||||||
-- @field #table attributes object type attributes
|
-- @field #number tankerType Type of refueling system: 0=boom, 1=probe.
|
||||||
|
-- @field #number range Range in km(?).
|
||||||
|
-- @field #table box Bounding box.
|
||||||
|
-- @field #number Hmax Max height in meters.
|
||||||
|
-- @field #number Kmax ?
|
||||||
|
-- @field #number speedMax10K Max speed in meters/second at 10k altitude.
|
||||||
|
-- @field #number NyMin ?
|
||||||
|
-- @field #number NyMax ?
|
||||||
|
-- @field #number fuelMassMax Max fuel mass in kg.
|
||||||
|
-- @field #number speedMax10K Max speed in meters/second.
|
||||||
|
-- @field #number massMax Max mass of unit.
|
||||||
|
-- @field #number RCS ?
|
||||||
|
-- @field #number life Life points.
|
||||||
|
-- @field #number VyMax Max vertical velocity in m/s.
|
||||||
|
-- @field #number Kab ?
|
||||||
|
-- @field #table attributes Table of attributes.
|
||||||
|
-- @field #TypeName typeName Type Name.
|
||||||
|
-- @field #string displayName Localized display name.
|
||||||
|
-- @field #number category Unit category.
|
||||||
|
|
||||||
--- A distance type
|
--- A distance type
|
||||||
-- @type Distance
|
-- @type Distance
|
||||||
@@ -337,7 +365,7 @@ do -- Types
|
|||||||
|
|
||||||
--- Time is given in seconds.
|
--- Time is given in seconds.
|
||||||
-- @type Time
|
-- @type Time
|
||||||
-- @extends #number
|
-- @extends #number Time in seconds.
|
||||||
|
|
||||||
--- Model time is the time that drives the simulation. Model time may be stopped, accelerated and decelerated relative real time.
|
--- Model time is the time that drives the simulation. Model time may be stopped, accelerated and decelerated relative real time.
|
||||||
-- @type ModelTime
|
-- @type ModelTime
|
||||||
@@ -345,20 +373,20 @@ do -- Types
|
|||||||
|
|
||||||
--- Mission time is a model time plus time of the mission start.
|
--- Mission time is a model time plus time of the mission start.
|
||||||
-- @type MissionTime
|
-- @type MissionTime
|
||||||
-- @extends #number
|
-- @extends #number Time in seconds.
|
||||||
|
|
||||||
|
|
||||||
--- Distance is given in meters.
|
--- Distance is given in meters.
|
||||||
-- @type Distance
|
-- @type Distance
|
||||||
-- @extends #number
|
-- @extends #number Distance in meters.
|
||||||
|
|
||||||
--- Angle is given in radians.
|
--- Angle is given in radians.
|
||||||
-- @type Angle
|
-- @type Angle
|
||||||
-- @extends #number
|
-- @extends #number Angle in radians.
|
||||||
|
|
||||||
--- Azimuth is an angle of rotation around world axis y counter-clockwise.
|
--- Azimuth is an angle of rotation around world axis y counter-clockwise.
|
||||||
-- @type Azimuth
|
-- @type Azimuth
|
||||||
-- @extends #number
|
-- @extends #number Angle in radians.
|
||||||
|
|
||||||
--- Mass is given in kilograms.
|
--- Mass is given in kilograms.
|
||||||
-- @type Mass
|
-- @type Mass
|
||||||
@@ -378,15 +406,15 @@ do -- Types
|
|||||||
|
|
||||||
--- Position is a composite structure. It consists of both coordinate vector and orientation matrix. Position3 (also known as "Pos3" for short) is a table that has following format:
|
--- Position is a composite structure. It consists of both coordinate vector and orientation matrix. Position3 (also known as "Pos3" for short) is a table that has following format:
|
||||||
-- @type Position3
|
-- @type Position3
|
||||||
-- @field #Vec3 p
|
-- @field #Vec3 p 3D position vector.
|
||||||
-- @field #Vec3 x
|
-- @field #Vec3 x Orientation component of vector pointing East.
|
||||||
-- @field #Vec3 y
|
-- @field #Vec3 y Orientation component of vector pointing up.
|
||||||
-- @field #Vec3 z
|
-- @field #Vec3 z Orientation component of vector pointing North.
|
||||||
|
|
||||||
--- 3-dimensional box.
|
--- 3-dimensional box.
|
||||||
-- @type Box3
|
-- @type Box3
|
||||||
-- @field #Vec3 min
|
-- @field #Vec3 min Min.
|
||||||
-- @field #Vec3 max
|
-- @field #Vec3 max Max
|
||||||
|
|
||||||
--- Each object belongs to a type. Object type is a named couple of properties those independent of mission and common for all units of the same type. Name of unit type is a string. Samples of unit type: "Su-27", "KAMAZ" and "M2 Bradley".
|
--- Each object belongs to a type. Object type is a named couple of properties those independent of mission and common for all units of the same type. Name of unit type is a string. Samples of unit type: "Su-27", "KAMAZ" and "M2 Bradley".
|
||||||
-- @type TypeName
|
-- @type TypeName
|
||||||
@@ -427,6 +455,10 @@ do -- Types
|
|||||||
-- @type TaskArray
|
-- @type TaskArray
|
||||||
-- @list <#Task>
|
-- @list <#Task>
|
||||||
|
|
||||||
|
---
|
||||||
|
--@type WaypointAir
|
||||||
|
--@field #boolean lateActivated
|
||||||
|
--@field #boolean uncontrolled
|
||||||
|
|
||||||
end --
|
end --
|
||||||
|
|
||||||
@@ -487,7 +519,7 @@ do -- Object
|
|||||||
--- Returns object coordinates for current time.
|
--- Returns object coordinates for current time.
|
||||||
-- @function [parent=#Object] getPoint
|
-- @function [parent=#Object] getPoint
|
||||||
-- @param #Object self
|
-- @param #Object self
|
||||||
-- @return #Vec3
|
-- @return #Vec3 3D position vector with x,y,z components.
|
||||||
|
|
||||||
--- Returns object position for current time.
|
--- Returns object position for current time.
|
||||||
-- @function [parent=#Object] getPosition
|
-- @function [parent=#Object] getPosition
|
||||||
@@ -497,7 +529,7 @@ do -- Object
|
|||||||
--- Returns the unit's velocity vector.
|
--- Returns the unit's velocity vector.
|
||||||
-- @function [parent=#Object] getVelocity
|
-- @function [parent=#Object] getVelocity
|
||||||
-- @param #Object self
|
-- @param #Object self
|
||||||
-- @return #Vec3
|
-- @return #Vec3 3D velocity vector.
|
||||||
|
|
||||||
--- Returns true if the unit is in air.
|
--- Returns true if the unit is in air.
|
||||||
-- @function [parent=#Object] inAir
|
-- @function [parent=#Object] inAir
|
||||||
@@ -1204,6 +1236,7 @@ do -- AI
|
|||||||
-- @field TAKEOFF
|
-- @field TAKEOFF
|
||||||
-- @field TAKEOFF_PARKING
|
-- @field TAKEOFF_PARKING
|
||||||
-- @field TURNING_POINT
|
-- @field TURNING_POINT
|
||||||
|
-- @field TAKEOFF_PARKING_HOT
|
||||||
-- @field LAND
|
-- @field LAND
|
||||||
|
|
||||||
--- @type AI.Task.TurnMethod
|
--- @type AI.Task.TurnMethod
|
||||||
@@ -1241,7 +1274,7 @@ do -- AI
|
|||||||
-- @field #AI.Option.Naval.id id
|
-- @field #AI.Option.Naval.id id
|
||||||
-- @field #AI.Option.Naval.val val
|
-- @field #AI.Option.Naval.val val
|
||||||
|
|
||||||
--TODO: work on formation
|
|
||||||
--- @type AI.Option.Air.id
|
--- @type AI.Option.Air.id
|
||||||
-- @field NO_OPTION
|
-- @field NO_OPTION
|
||||||
-- @field ROE
|
-- @field ROE
|
||||||
@@ -1251,6 +1284,33 @@ do -- AI
|
|||||||
-- @field FORMATION
|
-- @field FORMATION
|
||||||
-- @field RTB_ON_BINGO
|
-- @field RTB_ON_BINGO
|
||||||
-- @field SILENCE
|
-- @field SILENCE
|
||||||
|
-- @field RTB_ON_OUT_OF_AMMO
|
||||||
|
-- @field ECM_USING
|
||||||
|
-- @field PROHIBIT_AA
|
||||||
|
-- @field PROHIBIT_JETT
|
||||||
|
-- @field PROHIBIT_AB
|
||||||
|
-- @field PROHIBIT_AG
|
||||||
|
-- @field MISSILE_ATTACK
|
||||||
|
-- @field PROHIBIT_WP_PASS_REPORT
|
||||||
|
|
||||||
|
--- @type AI.Option.Air.id.FORMATION
|
||||||
|
-- @field LINE_ABREAST
|
||||||
|
-- @field TRAIL
|
||||||
|
-- @field WEDGE
|
||||||
|
-- @field ECHELON_RIGHT
|
||||||
|
-- @field ECHELON_LEFT
|
||||||
|
-- @field FINGER_FOUR
|
||||||
|
-- @field SPREAD_FOUR
|
||||||
|
-- @field WW2_BOMBER_ELEMENT
|
||||||
|
-- @field WW2_BOMBER_ELEMENT_HEIGHT
|
||||||
|
-- @field WW2_FIGHTER_VIC
|
||||||
|
-- @field HEL_WEDGE
|
||||||
|
-- @field HEL_ECHELON
|
||||||
|
-- @field HEL_FRONT
|
||||||
|
-- @field HEL_COLUMN
|
||||||
|
-- @field COMBAT_BOX
|
||||||
|
-- @field JAVELIN_DOWN
|
||||||
|
|
||||||
|
|
||||||
--- @type AI.Option.Air.val
|
--- @type AI.Option.Air.val
|
||||||
-- @field #AI.Option.Air.val.ROE ROE
|
-- @field #AI.Option.Air.val.ROE ROE
|
||||||
@@ -1284,11 +1344,26 @@ do -- AI
|
|||||||
-- @field WHEN_FLYING_IN_SAM_WEZ
|
-- @field WHEN_FLYING_IN_SAM_WEZ
|
||||||
-- @field WHEN_FLYING_NEAR_ENEMIES
|
-- @field WHEN_FLYING_NEAR_ENEMIES
|
||||||
|
|
||||||
|
--- @type AI.Option.Air.val.ECM_USING
|
||||||
|
-- @field NEVER_USE
|
||||||
|
-- @field USE_IF_ONLY_LOCK_BY_RADAR
|
||||||
|
-- @field USE_IF_DETECTED_LOCK_BY_RADAR
|
||||||
|
-- @field ALWAYS_USE
|
||||||
|
|
||||||
|
--- @type AI.Option.Air.val.MISSILE_ATTACK
|
||||||
|
-- @field MAX_RANGE
|
||||||
|
-- @field NEZ_RANGE
|
||||||
|
-- @field HALF_WAY_RMAX_NEZ
|
||||||
|
-- @field TARGET_THREAT_EST
|
||||||
|
-- @field RANDOM_RANGE
|
||||||
|
|
||||||
|
|
||||||
--- @type AI.Option.Ground.id
|
--- @type AI.Option.Ground.id
|
||||||
-- @field NO_OPTION
|
-- @field NO_OPTION
|
||||||
-- @field ROE @{#AI.Option.Ground.val.ROE}
|
-- @field ROE @{#AI.Option.Ground.val.ROE}
|
||||||
-- @field DISPERSE_ON_ATTACK true or false
|
-- @field DISPERSE_ON_ATTACK true or false
|
||||||
-- @field ALARM_STATE @{#AI.Option.Ground.val.ALARM_STATE}
|
-- @field ALARM_STATE @{#AI.Option.Ground.val.ALARM_STATE}
|
||||||
|
-- @field ENGAGE_AIR_WEAPONS
|
||||||
|
|
||||||
--- @type AI.Option.Ground.val
|
--- @type AI.Option.Ground.val
|
||||||
-- @field #AI.Option.Ground.val.ROE ROE
|
-- @field #AI.Option.Ground.val.ROE ROE
|
||||||
|
|||||||
@@ -1052,7 +1052,6 @@ end
|
|||||||
-- * `AIRBASE.Nevada.Laughlin_Airport`
|
-- * `AIRBASE.Nevada.Laughlin_Airport`
|
||||||
-- * `AIRBASE.Nevada.Lincoln_County`
|
-- * `AIRBASE.Nevada.Lincoln_County`
|
||||||
-- * `AIRBASE.Nevada.McCarran_International_Airport`
|
-- * `AIRBASE.Nevada.McCarran_International_Airport`
|
||||||
-- * `AIRBASE.Nevada.Mellan_Airstrip`
|
|
||||||
-- * `AIRBASE.Nevada.Mesquite`
|
-- * `AIRBASE.Nevada.Mesquite`
|
||||||
-- * `AIRBASE.Nevada.Mina_Airport_3Q0`
|
-- * `AIRBASE.Nevada.Mina_Airport_3Q0`
|
||||||
-- * `AIRBASE.Nevada.Nellis_AFB`
|
-- * `AIRBASE.Nevada.Nellis_AFB`
|
||||||
@@ -1097,7 +1096,6 @@ end
|
|||||||
-- -- Monitor specific airbases.
|
-- -- Monitor specific airbases.
|
||||||
-- ATC_Ground = ATC_GROUND_NEVADA:New(
|
-- ATC_Ground = ATC_GROUND_NEVADA:New(
|
||||||
-- { AIRBASE.Nevada.Laughlin_Airport,
|
-- { AIRBASE.Nevada.Laughlin_Airport,
|
||||||
-- AIRBASE.Nevada.Mellan_Airstrip,
|
|
||||||
-- AIRBASE.Nevada.Lincoln_County,
|
-- AIRBASE.Nevada.Lincoln_County,
|
||||||
-- AIRBASE.Nevada.North_Las_Vegas,
|
-- AIRBASE.Nevada.North_Las_Vegas,
|
||||||
-- AIRBASE.Nevada.McCarran_International_Airport
|
-- AIRBASE.Nevada.McCarran_International_Airport
|
||||||
@@ -1621,6 +1619,13 @@ end
|
|||||||
-- * `AIRBASE.Normandy.Sainte_Laurent_sur_Mer`
|
-- * `AIRBASE.Normandy.Sainte_Laurent_sur_Mer`
|
||||||
-- * `AIRBASE.Normandy.Sommervieu`
|
-- * `AIRBASE.Normandy.Sommervieu`
|
||||||
-- * `AIRBASE.Normandy.Tangmere`
|
-- * `AIRBASE.Normandy.Tangmere`
|
||||||
|
-- * `AIRBASE.Normandy.Argentan`
|
||||||
|
-- * `AIRBASE.Normandy.Goulet`
|
||||||
|
-- * `AIRBASE.Normandy.Essay`
|
||||||
|
-- * `AIRBASE.Normandy.Hauterive`
|
||||||
|
-- * `AIRBASE.Normandy.Barville`
|
||||||
|
-- * `AIRBASE.Normandy.Conches`
|
||||||
|
-- * `AIRBASE.Normandy.Vrigny`
|
||||||
--
|
--
|
||||||
-- # Installation
|
-- # Installation
|
||||||
--
|
--
|
||||||
@@ -1834,7 +1839,7 @@ ATC_GROUND_NORMANDY = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
[AIRBASE.Normandy.Ford] = {
|
[AIRBASE.Normandy.Ford_AF] = {
|
||||||
PointsRunways = {
|
PointsRunways = {
|
||||||
[1] = {
|
[1] = {
|
||||||
[1]={["y"]=-26506.13971428,["x"]=147514.39971429,},
|
[1]={["y"]=-26506.13971428,["x"]=147514.39971429,},
|
||||||
@@ -2036,7 +2041,83 @@ ATC_GROUND_NORMANDY = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
[AIRBASE.Normandy.Argentan] = {
|
||||||
|
PointsRunways = {
|
||||||
|
[1] = {
|
||||||
|
[1]={["y"]=22322.280338032,["x"]=-78607.309765269,},
|
||||||
|
[2]={["y"]=23032.778713963,["x"]=-78967.17709893,},
|
||||||
|
[3]={["y"]=23015.27074041,["x"]=-79008.02903722,},
|
||||||
|
[4]={["y"]=22299.944963827,["x"]=-78650.366148928,},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
[AIRBASE.Normandy.Goulet] = {
|
||||||
|
PointsRunways = {
|
||||||
|
[1] = {
|
||||||
|
[1]={["y"]=24901.788373185,["x"]=-89139.367511763,},
|
||||||
|
[2]={["y"]=25459.965967043,["x"]=-89709.67940114,},
|
||||||
|
[3]={["y"]=25422.459962713,["x"]=-89741.669816598,},
|
||||||
|
[4]={["y"]=24857.663662208,["x"]=-89173.56416277,},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
[AIRBASE.Normandy.Essay] = {
|
||||||
|
PointsRunways = {
|
||||||
|
[1] = {
|
||||||
|
[1]={["y"]=44610.072022849,["x"]=-105469.21149064,},
|
||||||
|
[2]={["y"]=45417.939023956,["x"]=-105536.08535277,},
|
||||||
|
[3]={["y"]=45412.558368383,["x"]=-105585.27991801,},
|
||||||
|
[4]={["y"]=44602.38537203,["x"]=-105516.10006064,},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
[AIRBASE.Normandy.Hauterive] = {
|
||||||
|
PointsRunways = {
|
||||||
|
[1] = {
|
||||||
|
[1]={["y"]=40617.185360953,["x"]=-107657.10147517,},
|
||||||
|
[2]={["y"]=41114.628372034,["x"]=-108298.77015609,},
|
||||||
|
[3]={["y"]=41080.006684855,["x"]=-108319.06562788,},
|
||||||
|
[4]={["y"]=40584.558402807,["x"]=-107692.29370481,},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
[AIRBASE.Normandy.Vrigny] = {
|
||||||
|
PointsRunways = {
|
||||||
|
[1] = {
|
||||||
|
[1]={["y"]=24892.131051827,["x"]=-89131.628297486,},
|
||||||
|
[2]={["y"]=25469.738000575,["x"]=-89709.235246234,},
|
||||||
|
[3]={["y"]=25418.869206793,["x"]=-89738.771965204,},
|
||||||
|
[4]={["y"]=24859.312475193,["x"]=-89171.010589446,},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
[AIRBASE.Normandy.Barville] = {
|
||||||
|
PointsRunways = {
|
||||||
|
[1] = {
|
||||||
|
[1]={["y"]=49027.850333166,["x"]=-109217.05049066,},
|
||||||
|
[2]={["y"]=49755.022185805,["x"]=-110346.63783457,},
|
||||||
|
[3]={["y"]=49682.657996586,["x"]=-110401.35222154,},
|
||||||
|
[4]={["y"]=48921.951519675,["x"]=-109285.88471943,},
|
||||||
|
},
|
||||||
|
[2] = {
|
||||||
|
[1]={["y"]=48429.522036941,["x"]=-109818.90874734,},
|
||||||
|
[2]={["y"]=49746.197284681,["x"]=-109954.81222465,},
|
||||||
|
[3]={["y"]=49735.607403332,["x"]=-110032.47135455,},
|
||||||
|
[4]={["y"]=48420.697135816,["x"]=-109900.09783768,},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
[AIRBASE.Normandy.Conches] = {
|
||||||
|
PointsRunways = {
|
||||||
|
[1] = {
|
||||||
|
[1]={["y"]=95099.187473266,["x"]=-56389.619005858,},
|
||||||
|
[2]={["y"]=95181.545025963,["x"]=-56465.440244849,},
|
||||||
|
[3]={["y"]=94071.678958666,["x"]=-57627.596821795,},
|
||||||
|
[4]={["y"]=94005.008558864,["x"]=-57558.31189651,},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2477,7 +2558,7 @@ ATC_GROUND_PERSIANGULF = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
[AIRBASE.PersianGulf.Abu_Musa_Island_Airport] = {
|
[AIRBASE.PersianGulf.Al_Dhafra_AB] = {
|
||||||
PointsRunways = {
|
PointsRunways = {
|
||||||
[1] = {
|
[1] = {
|
||||||
[1]={["y"]=-174672.06004916,["x"]=-209880.97145616,},
|
[1]={["y"]=-174672.06004916,["x"]=-209880.97145616,},
|
||||||
|
|||||||
@@ -693,7 +693,7 @@ ARTY.db={
|
|||||||
|
|
||||||
--- Arty script version.
|
--- Arty script version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
ARTY.version="1.1.5"
|
ARTY.version="1.1.7"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -2555,6 +2555,13 @@ function ARTY:_OnEventMarkChange(Event)
|
|||||||
if not _assigned then
|
if not _assigned then
|
||||||
self:T3(self.lid..string.format("INFO: ARTY group %s was not addressed! Mark text:\n%s", self.groupname, Event.text))
|
self:T3(self.lid..string.format("INFO: ARTY group %s was not addressed! Mark text:\n%s", self.groupname, Event.text))
|
||||||
return
|
return
|
||||||
|
else
|
||||||
|
if self.Controllable and self.Controllable:IsAlive() then
|
||||||
|
|
||||||
|
else
|
||||||
|
self:T3(self.lid..string.format("INFO: ARTY group %s was addressed but is NOT alive! Mark text:\n%s", self.groupname, Event.text))
|
||||||
|
return
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Coordinate was given in text, e.g. as lat, long.
|
-- Coordinate was given in text, e.g. as lat, long.
|
||||||
@@ -3841,26 +3848,23 @@ end
|
|||||||
-- @param #boolean final True if it is the final waypoint.
|
-- @param #boolean final True if it is the final waypoint.
|
||||||
function ARTY._PassingWaypoint(group, arty, i, final)
|
function ARTY._PassingWaypoint(group, arty, i, final)
|
||||||
|
|
||||||
-- Debug message.
|
if group and group:IsAlive() then
|
||||||
local text=string.format("%s, passing waypoint %d.", group:GetName(), i)
|
|
||||||
if final then
|
|
||||||
text=string.format("%s, arrived at destination.", group:GetName())
|
|
||||||
end
|
|
||||||
arty:T(self.lid..text)
|
|
||||||
|
|
||||||
--[[
|
local groupname=tostring(group:GetName())
|
||||||
if final then
|
|
||||||
MESSAGE:New(text, 10):ToCoalitionIf(group:GetCoalition(), arty.Debug or arty.report)
|
|
||||||
else
|
|
||||||
MESSAGE:New(text, 10):ToAllIf(arty.Debug)
|
|
||||||
end
|
|
||||||
]]
|
|
||||||
|
|
||||||
-- Arrived event.
|
-- Debug message.
|
||||||
if final and arty.groupname==group:GetName() then
|
local text=string.format("%s, passing waypoint %d.", groupname, i)
|
||||||
arty:Arrived()
|
if final then
|
||||||
end
|
text=string.format("%s, arrived at destination.", groupname)
|
||||||
|
end
|
||||||
|
arty:T(arty.lid..text)
|
||||||
|
|
||||||
|
-- Arrived event.
|
||||||
|
if final and arty.groupname==groupname then
|
||||||
|
arty:Arrived()
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Relocate to another position, e.g. after an engagement to avoid couter strikes.
|
--- Relocate to another position, e.g. after an engagement to avoid couter strikes.
|
||||||
|
|||||||
@@ -66,7 +66,7 @@
|
|||||||
-- Creates the main object which is preventing the airbase to get polluted with debris on the runway, which halts the airbase.
|
-- Creates the main object which is preventing the airbase to get polluted with debris on the runway, which halts the airbase.
|
||||||
--
|
--
|
||||||
-- -- Clean these Zones.
|
-- -- Clean these Zones.
|
||||||
-- CleanUpAirports = CLEANUP_AIRBASE:New( { AIRBASE.Caucasus.Tbilisi, AIRBASE.Caucasus.Kutaisi )
|
-- CleanUpAirports = CLEANUP_AIRBASE:New( { AIRBASE.Caucasus.Tbilisi, AIRBASE.Caucasus.Kutaisi } )
|
||||||
--
|
--
|
||||||
-- -- or
|
-- -- or
|
||||||
-- CleanUpTbilisi = CLEANUP_AIRBASE:New( AIRBASE.Caucasus.Tbilisi )
|
-- CleanUpTbilisi = CLEANUP_AIRBASE:New( AIRBASE.Caucasus.Tbilisi )
|
||||||
@@ -245,7 +245,7 @@ end
|
|||||||
function CLEANUP_AIRBASE.__:OnEventBirth( EventData )
|
function CLEANUP_AIRBASE.__:OnEventBirth( EventData )
|
||||||
self:F( { EventData } )
|
self:F( { EventData } )
|
||||||
|
|
||||||
if EventData.IniUnit:IsAlive() ~= nil then
|
if EventData and EventData.IniUnit and EventData.IniUnit:IsAlive() ~= nil then
|
||||||
if self:IsInAirbase( EventData.IniUnit:GetVec2() ) then
|
if self:IsInAirbase( EventData.IniUnit:GetVec2() ) then
|
||||||
self.CleanUpList[EventData.IniDCSUnitName] = {}
|
self.CleanUpList[EventData.IniDCSUnitName] = {}
|
||||||
self.CleanUpList[EventData.IniDCSUnitName].CleanUpUnit = EventData.IniUnit
|
self.CleanUpList[EventData.IniDCSUnitName].CleanUpUnit = EventData.IniUnit
|
||||||
@@ -442,4 +442,3 @@ function CLEANUP_AIRBASE.__:CleanUpSchedule()
|
|||||||
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1438,27 +1438,31 @@ do -- DETECTION_BASE
|
|||||||
function( PlayerUnitName )
|
function( PlayerUnitName )
|
||||||
local PlayerUnit = UNIT:FindByName( PlayerUnitName )
|
local PlayerUnit = UNIT:FindByName( PlayerUnitName )
|
||||||
|
|
||||||
if PlayerUnit and PlayerUnit:GetCoordinate():IsInRadius( DetectedUnitCoord, self.FriendliesRange ) then
|
-- Fix for issue https://github.com/FlightControl-Master/MOOSE/issues/1225
|
||||||
--if PlayerUnit and PlayerUnit:IsInZone(DetectionZone) then
|
if PlayerUnit and PlayerUnit:IsAlive() then
|
||||||
|
local coord=PlayerUnit:GetCoordinate()
|
||||||
|
|
||||||
local PlayerUnitCategory = PlayerUnit:GetDesc().category
|
if coord and coord:IsInRadius( DetectedUnitCoord, self.FriendliesRange ) then
|
||||||
|
|
||||||
if ( not self.FriendliesCategory ) or ( self.FriendliesCategory and ( self.FriendliesCategory == PlayerUnitCategory ) ) then
|
local PlayerUnitCategory = PlayerUnit:GetDesc().category
|
||||||
|
|
||||||
local PlayerUnitName = PlayerUnit:GetName()
|
if ( not self.FriendliesCategory ) or ( self.FriendliesCategory and ( self.FriendliesCategory == PlayerUnitCategory ) ) then
|
||||||
|
|
||||||
DetectedItem.PlayersNearBy = DetectedItem.PlayersNearBy or {}
|
local PlayerUnitName = PlayerUnit:GetName()
|
||||||
DetectedItem.PlayersNearBy[PlayerUnitName] = PlayerUnit
|
|
||||||
|
|
||||||
-- Friendlies are sorted per unit category.
|
DetectedItem.PlayersNearBy = DetectedItem.PlayersNearBy or {}
|
||||||
DetectedItem.FriendliesNearBy = DetectedItem.FriendliesNearBy or {}
|
DetectedItem.PlayersNearBy[PlayerUnitName] = PlayerUnit
|
||||||
DetectedItem.FriendliesNearBy[PlayerUnitCategory] = DetectedItem.FriendliesNearBy[PlayerUnitCategory] or {}
|
|
||||||
DetectedItem.FriendliesNearBy[PlayerUnitCategory][PlayerUnitName] = PlayerUnit
|
|
||||||
|
|
||||||
local Distance = DetectedUnitCoord:Get2DDistance( PlayerUnit:GetCoordinate() )
|
-- Friendlies are sorted per unit category.
|
||||||
DetectedItem.FriendliesDistance = DetectedItem.FriendliesDistance or {}
|
DetectedItem.FriendliesNearBy = DetectedItem.FriendliesNearBy or {}
|
||||||
DetectedItem.FriendliesDistance[Distance] = PlayerUnit
|
DetectedItem.FriendliesNearBy[PlayerUnitCategory] = DetectedItem.FriendliesNearBy[PlayerUnitCategory] or {}
|
||||||
|
DetectedItem.FriendliesNearBy[PlayerUnitCategory][PlayerUnitName] = PlayerUnit
|
||||||
|
|
||||||
|
local Distance = DetectedUnitCoord:Get2DDistance( PlayerUnit:GetCoordinate() )
|
||||||
|
DetectedItem.FriendliesDistance = DetectedItem.FriendliesDistance or {}
|
||||||
|
DetectedItem.FriendliesDistance[Distance] = PlayerUnit
|
||||||
|
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -198,7 +198,7 @@ FOX.MenuF10Root=nil
|
|||||||
|
|
||||||
--- FOX class version.
|
--- FOX class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
FOX.version="0.6.0"
|
FOX.version="0.6.1"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- ToDo list
|
-- ToDo list
|
||||||
@@ -243,6 +243,7 @@ function FOX:New()
|
|||||||
self:AddTransition("*", "MissileDestroyed", "*") -- Missile was destroyed before impact.
|
self:AddTransition("*", "MissileDestroyed", "*") -- Missile was destroyed before impact.
|
||||||
self:AddTransition("*", "EnterSafeZone", "*") -- Player enters a safe zone.
|
self:AddTransition("*", "EnterSafeZone", "*") -- Player enters a safe zone.
|
||||||
self:AddTransition("*", "ExitSafeZone", "*") -- Player exists a safe zone.
|
self:AddTransition("*", "ExitSafeZone", "*") -- Player exists a safe zone.
|
||||||
|
self:AddTransition("Running", "Stop", "Stopped") -- Stop FOX script.
|
||||||
|
|
||||||
------------------------
|
------------------------
|
||||||
--- Pseudo Functions ---
|
--- Pseudo Functions ---
|
||||||
@@ -960,7 +961,7 @@ function FOX:onafterMissileLaunch(From, Event, To, missile)
|
|||||||
end
|
end
|
||||||
|
|
||||||
if target then
|
if target then
|
||||||
self:I(self.lid..string.format("Missile %s with NO explicit target got closest unit to missile as target %s. Dist=%s m", missile.missileType, target:GetName(), tostring(mindist)))
|
self:T(self.lid..string.format("Missile %s with NO explicit target got closest unit to missile as target %s. Dist=%s m", missile.missileType, target:GetName(), tostring(mindist)))
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
@@ -1065,7 +1066,7 @@ function FOX:onafterMissileLaunch(From, Event, To, missile)
|
|||||||
else
|
else
|
||||||
|
|
||||||
-- Destroy missile.
|
-- Destroy missile.
|
||||||
self:I(self.lid..string.format("Missile %s(%s) fired by %s has no current target. Checking back in 0.1 sec.", missile.missileType, missile.missileName, missile.shooterName))
|
self:T(self.lid..string.format("Missile %s(%s) fired by %s has no current target. Checking back in 0.1 sec.", missile.missileType, missile.missileName, missile.shooterName))
|
||||||
return timer.getTime()+0.1
|
return timer.getTime()+0.1
|
||||||
|
|
||||||
-- No target ==> terminate timer.
|
-- No target ==> terminate timer.
|
||||||
|
|||||||
@@ -242,7 +242,7 @@
|
|||||||
-- * AIRBASE.TerminalType.OpenMed: Open/Shelter air airplane only.
|
-- * AIRBASE.TerminalType.OpenMed: Open/Shelter air airplane only.
|
||||||
-- * AIRBASE.TerminalType.OpenBig: Open air spawn points. Generally larger but does not guarantee large aircraft are capable of spawning there.
|
-- * AIRBASE.TerminalType.OpenBig: Open air spawn points. Generally larger but does not guarantee large aircraft are capable of spawning there.
|
||||||
-- * AIRBASE.TerminalType.OpenMedOrBig: Combines OpenMed and OpenBig spots.
|
-- * AIRBASE.TerminalType.OpenMedOrBig: Combines OpenMed and OpenBig spots.
|
||||||
-- * AIRBASE.TerminalType.HelicopterUnsable: Combines HelicopterOnly, OpenMed and OpenBig.
|
-- * AIRBASE.TerminalType.HelicopterUsable: Combines HelicopterOnly, OpenMed and OpenBig.
|
||||||
-- * AIRBASE.TerminalType.FighterAircraft: Combines Shelter, OpenMed and OpenBig spots. So effectively all spots usable by fixed wing aircraft.
|
-- * AIRBASE.TerminalType.FighterAircraft: Combines Shelter, OpenMed and OpenBig spots. So effectively all spots usable by fixed wing aircraft.
|
||||||
--
|
--
|
||||||
-- So for example
|
-- So for example
|
||||||
@@ -550,7 +550,7 @@ RAT.id="RAT | "
|
|||||||
--- RAT version.
|
--- RAT version.
|
||||||
-- @list version
|
-- @list version
|
||||||
RAT.version={
|
RAT.version={
|
||||||
version = "2.3.8",
|
version = "2.3.9",
|
||||||
print = true,
|
print = true,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3416,7 +3416,7 @@ function RAT:_GetAirportsOfCoalition()
|
|||||||
for _,coalition in pairs(self.ctable) do
|
for _,coalition in pairs(self.ctable) do
|
||||||
for _,_airport in pairs(self.airports_map) do
|
for _,_airport in pairs(self.airports_map) do
|
||||||
local airport=_airport --Wrapper.Airbase#AIRBASE
|
local airport=_airport --Wrapper.Airbase#AIRBASE
|
||||||
local category=airport:GetDesc().category
|
local category=airport:GetAirbaseCategory()
|
||||||
if airport:GetCoalition()==coalition then
|
if airport:GetCoalition()==coalition then
|
||||||
-- Planes cannot land on FARPs.
|
-- Planes cannot land on FARPs.
|
||||||
--local condition1=self.category==RAT.cat.plane and airport:GetTypeName()=="FARP"
|
--local condition1=self.category==RAT.cat.plane and airport:GetTypeName()=="FARP"
|
||||||
@@ -3847,7 +3847,7 @@ function RAT:_OnBirth(EventData)
|
|||||||
|
|
||||||
-- Check if any unit of the group was spawned on top of another unit in the MOOSE data base.
|
-- Check if any unit of the group was spawned on top of another unit in the MOOSE data base.
|
||||||
local ontop=false
|
local ontop=false
|
||||||
if self.checkontop and (_airbase and _airbase:GetDesc().category==Airbase.Category.AIRDROME) then
|
if self.checkontop and (_airbase and _airbase:GetAirbaseCategory()==Airbase.Category.AIRDROME) then
|
||||||
ontop=self:_CheckOnTop(SpawnGroup, self.ontopradius)
|
ontop=self:_CheckOnTop(SpawnGroup, self.ontopradius)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -4457,7 +4457,7 @@ function RAT:_Waypoint(index, description, Type, Coord, Speed, Altitude, Airport
|
|||||||
|
|
||||||
if (Airport~=nil) and (Type~=RAT.wp.air) then
|
if (Airport~=nil) and (Type~=RAT.wp.air) then
|
||||||
local AirbaseID = Airport:GetID()
|
local AirbaseID = Airport:GetID()
|
||||||
local AirbaseCategory = Airport:GetDesc().category
|
local AirbaseCategory = Airport:GetAirbaseCategory()
|
||||||
if AirbaseCategory == Airbase.Category.SHIP then
|
if AirbaseCategory == Airbase.Category.SHIP then
|
||||||
RoutePoint.linkUnit = AirbaseID
|
RoutePoint.linkUnit = AirbaseID
|
||||||
RoutePoint.helipadId = AirbaseID
|
RoutePoint.helipadId = AirbaseID
|
||||||
@@ -5141,7 +5141,7 @@ function RAT:_ModifySpawnTemplate(waypoints, livery, spawnplace, departure, take
|
|||||||
local spawnonrunway=false
|
local spawnonrunway=false
|
||||||
local spawnonairport=false
|
local spawnonairport=false
|
||||||
if spawnonground then
|
if spawnonground then
|
||||||
local AirbaseCategory = departure:GetDesc().category
|
local AirbaseCategory = departure:GetAirbaseCategory()
|
||||||
if AirbaseCategory == Airbase.Category.SHIP then
|
if AirbaseCategory == Airbase.Category.SHIP then
|
||||||
spawnonship=true
|
spawnonship=true
|
||||||
elseif AirbaseCategory == Airbase.Category.HELIPAD then
|
elseif AirbaseCategory == Airbase.Category.HELIPAD then
|
||||||
@@ -5173,6 +5173,7 @@ function RAT:_ModifySpawnTemplate(waypoints, livery, spawnplace, departure, take
|
|||||||
if self.uncontrolled then
|
if self.uncontrolled then
|
||||||
-- This is used in the SPAWN:SpawnWithIndex() function. Some values are overwritten there!
|
-- This is used in the SPAWN:SpawnWithIndex() function. Some values are overwritten there!
|
||||||
self.SpawnUnControlled=true
|
self.SpawnUnControlled=true
|
||||||
|
SpawnTemplate.uncontrolled=true
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Number of units in the group. With grouping this can actually differ from the template group size!
|
-- Number of units in the group. With grouping this can actually differ from the template group size!
|
||||||
|
|||||||
@@ -93,6 +93,8 @@
|
|||||||
-- @field Core.RadioQueue#RADIOQUEUE instructor Instructor radio queue.
|
-- @field Core.RadioQueue#RADIOQUEUE instructor Instructor radio queue.
|
||||||
-- @field #number rangecontrolfreq Frequency on which the range control transmitts.
|
-- @field #number rangecontrolfreq Frequency on which the range control transmitts.
|
||||||
-- @field Core.RadioQueue#RADIOQUEUE rangecontrol Range control radio queue.
|
-- @field Core.RadioQueue#RADIOQUEUE rangecontrol Range control radio queue.
|
||||||
|
-- @field #string rangecontrolrelayname Name of relay unit.
|
||||||
|
-- @field #string instructorrelayname Name of relay unit.
|
||||||
-- @field #string soundpath Path inside miz file where the sound files are located. Default is "Range Soundfiles/".
|
-- @field #string soundpath Path inside miz file where the sound files are located. Default is "Range Soundfiles/".
|
||||||
-- @extends Core.Fsm#FSM
|
-- @extends Core.Fsm#FSM
|
||||||
|
|
||||||
@@ -516,7 +518,7 @@ RANGE.MenuF10Root=nil
|
|||||||
|
|
||||||
--- Range script version.
|
--- Range script version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
RANGE.version="2.2.0"
|
RANGE.version="2.2.3"
|
||||||
|
|
||||||
--TODO list:
|
--TODO list:
|
||||||
--TODO: Verbosity level for messages.
|
--TODO: Verbosity level for messages.
|
||||||
@@ -754,7 +756,7 @@ function RANGE:onafterStart()
|
|||||||
if self.rangecontrolfreq then
|
if self.rangecontrolfreq then
|
||||||
|
|
||||||
-- Radio queue.
|
-- Radio queue.
|
||||||
self.rangecontrol=RADIOQUEUE:New(self.rangecontrolfreq)
|
self.rangecontrol=RADIOQUEUE:New(self.rangecontrolfreq, nil, self.rangename)
|
||||||
|
|
||||||
-- Init numbers.
|
-- Init numbers.
|
||||||
self.rangecontrol:SetDigit(0, RANGE.Sound.RC0.filename, RANGE.Sound.RC0.duration, self.soundpath)
|
self.rangecontrol:SetDigit(0, RANGE.Sound.RC0.filename, RANGE.Sound.RC0.duration, self.soundpath)
|
||||||
@@ -770,6 +772,7 @@ function RANGE:onafterStart()
|
|||||||
|
|
||||||
-- Set location where the messages are transmitted from.
|
-- Set location where the messages are transmitted from.
|
||||||
self.rangecontrol:SetSenderCoordinate(self.location)
|
self.rangecontrol:SetSenderCoordinate(self.location)
|
||||||
|
self.rangecontrol:SetSenderUnitName(self.rangecontrolrelayname)
|
||||||
|
|
||||||
-- Start range control radio queue.
|
-- Start range control radio queue.
|
||||||
self.rangecontrol:Start(1, 0.1)
|
self.rangecontrol:Start(1, 0.1)
|
||||||
@@ -778,7 +781,7 @@ function RANGE:onafterStart()
|
|||||||
if self.instructorfreq then
|
if self.instructorfreq then
|
||||||
|
|
||||||
-- Radio queue.
|
-- Radio queue.
|
||||||
self.instructor=RADIOQUEUE:New(self.instructorfreq)
|
self.instructor=RADIOQUEUE:New(self.instructorfreq, nil, self.rangename)
|
||||||
|
|
||||||
-- Init numbers.
|
-- Init numbers.
|
||||||
self.instructor:SetDigit(0, RANGE.Sound.IR0.filename, RANGE.Sound.IR0.duration, self.soundpath)
|
self.instructor:SetDigit(0, RANGE.Sound.IR0.filename, RANGE.Sound.IR0.duration, self.soundpath)
|
||||||
@@ -794,6 +797,7 @@ function RANGE:onafterStart()
|
|||||||
|
|
||||||
-- Set location where the messages are transmitted from.
|
-- Set location where the messages are transmitted from.
|
||||||
self.instructor:SetSenderCoordinate(self.location)
|
self.instructor:SetSenderCoordinate(self.location)
|
||||||
|
self.instructor:SetSenderUnitName(self.instructorrelayname)
|
||||||
|
|
||||||
-- Start instructor radio queue.
|
-- Start instructor radio queue.
|
||||||
self.instructor:Start(1, 0.1)
|
self.instructor:Start(1, 0.1)
|
||||||
@@ -1067,18 +1071,22 @@ end
|
|||||||
--- Enable range control and set frequency.
|
--- Enable range control and set frequency.
|
||||||
-- @param #RANGE self
|
-- @param #RANGE self
|
||||||
-- @param #number frequency Frequency in MHz. Default 256 MHz.
|
-- @param #number frequency Frequency in MHz. Default 256 MHz.
|
||||||
|
-- @param #string relayunitname Name of the unit used for transmission.
|
||||||
-- @return #RANGE self
|
-- @return #RANGE self
|
||||||
function RANGE:SetRangeControl(frequency)
|
function RANGE:SetRangeControl(frequency, relayunitname)
|
||||||
self.rangecontrolfreq=frequency or 256
|
self.rangecontrolfreq=frequency or 256
|
||||||
|
self.rangecontrolrelayname=relayunitname
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Enable instructor radio and set frequency.
|
--- Enable instructor radio and set frequency.
|
||||||
-- @param #RANGE self
|
-- @param #RANGE self
|
||||||
-- @param #number frequency Frequency in MHz. Default 305 MHz.
|
-- @param #number frequency Frequency in MHz. Default 305 MHz.
|
||||||
|
-- @param #string relayunitname Name of the unit used for transmission.
|
||||||
-- @return #RANGE self
|
-- @return #RANGE self
|
||||||
function RANGE:SetInstructorRadio(frequency)
|
function RANGE:SetInstructorRadio(frequency, relayunitname)
|
||||||
self.instructorfreq=frequency or 305
|
self.instructorfreq=frequency or 305
|
||||||
|
self.instructorrelayname=relayunitname
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1088,7 +1096,7 @@ end
|
|||||||
-- @return #RANGE self
|
-- @return #RANGE self
|
||||||
function RANGE:SetSoundfilesPath(path)
|
function RANGE:SetSoundfilesPath(path)
|
||||||
self.soundpath=tostring(path or "Range Soundfiles/")
|
self.soundpath=tostring(path or "Range Soundfiles/")
|
||||||
self:I(self.lid..string.format("Setting sound files path to %s", self.soundpath))
|
self:I(self.id..string.format("Setting sound files path to %s", self.soundpath))
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1341,9 +1349,9 @@ function RANGE:AddBombingTargetUnit(unit, goodhitrange, randommove)
|
|||||||
|
|
||||||
-- Debug or error output.
|
-- Debug or error output.
|
||||||
if _isstatic==true then
|
if _isstatic==true then
|
||||||
self:T(self.id..string.format("Adding STATIC bombing target %s with good hit range %d. Random move = %s.", name, goodhitrange, tostring(randommove)))
|
self:I(self.id..string.format("Adding STATIC bombing target %s with good hit range %d. Random move = %s.", name, goodhitrange, tostring(randommove)))
|
||||||
elseif _isstatic==false then
|
elseif _isstatic==false then
|
||||||
self:T(self.id..string.format("Adding UNIT bombing target %s with good hit range %d. Random move = %s.", name, goodhitrange, tostring(randommove)))
|
self:I(self.id..string.format("Adding UNIT bombing target %s with good hit range %d. Random move = %s.", name, goodhitrange, tostring(randommove)))
|
||||||
else
|
else
|
||||||
self:E(self.id..string.format("ERROR! No bombing target with name %s could be found. Carefully check all UNIT and STATIC names defined in the mission editor!", name))
|
self:E(self.id..string.format("ERROR! No bombing target with name %s could be found. Carefully check all UNIT and STATIC names defined in the mission editor!", name))
|
||||||
end
|
end
|
||||||
@@ -1908,8 +1916,35 @@ end
|
|||||||
-- @param #string To To state.
|
-- @param #string To To state.
|
||||||
function RANGE:onafterStatus(From, Event, To)
|
function RANGE:onafterStatus(From, Event, To)
|
||||||
|
|
||||||
|
local fsmstate=self:GetState()
|
||||||
|
|
||||||
|
local text=string.format("Range status: %s", fsmstate)
|
||||||
|
|
||||||
|
if self.instructor then
|
||||||
|
local alive="N/A"
|
||||||
|
if self.instructorrelayname then
|
||||||
|
local relay=UNIT:FindByName(self.instructorrelayname)
|
||||||
|
if relay then
|
||||||
|
alive=tostring(relay:IsAlive())
|
||||||
|
end
|
||||||
|
end
|
||||||
|
text=text..string.format(", Instructor %.3f MHz (Relay=%s alive=%s)", self.instructorfreq, tostring(self.instructorrelayname), alive)
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.rangecontrol then
|
||||||
|
local alive="N/A"
|
||||||
|
if self.rangecontrolrelayname then
|
||||||
|
local relay=UNIT:FindByName(self.rangecontrolrelayname)
|
||||||
|
if relay then
|
||||||
|
alive=tostring(relay:IsAlive())
|
||||||
|
end
|
||||||
|
end
|
||||||
|
text=text..string.format(", Control %.3f MHz (Relay=%s alive=%s)", self.rangecontrolfreq, tostring(self.rangecontrolrelayname), alive)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Check range status.
|
-- Check range status.
|
||||||
self:I(self.id..string.format("Range status: %s", self:GetState()))
|
self:I(self.id..text)
|
||||||
|
|
||||||
-- Check player status.
|
-- Check player status.
|
||||||
self:_CheckPlayers()
|
self:_CheckPlayers()
|
||||||
@@ -2522,9 +2557,16 @@ function RANGE:_DisplayBombTargets(_unitname)
|
|||||||
|
|
||||||
if coord then
|
if coord then
|
||||||
|
|
||||||
|
-- Get elevation
|
||||||
|
local elevation=coord:GetLandHeight()
|
||||||
|
local eltxt=string.format("%d m", elevation)
|
||||||
|
if _settings:IsImperial() then
|
||||||
|
elevation=UTILS.MetersToFeet(elevation)
|
||||||
|
eltxt=string.format("%d ft", elevation)
|
||||||
|
end
|
||||||
|
|
||||||
local ca2g=coord:ToStringA2G(_unit,_settings)
|
local ca2g=coord:ToStringA2G(_unit,_settings)
|
||||||
--local lldms=coord:ToStringLLDMS(_settings)
|
_text=_text..string.format("\n- %s:\n%s @ %s", bombtarget.name or "unknown", ca2g, eltxt)
|
||||||
_text=_text..string.format("\n- %s:\n%s", bombtarget.name or "unknown", ca2g)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -2960,10 +3002,10 @@ function RANGE:_AddF10Commands(_unitName)
|
|||||||
missionCommands.addCommandForGroup(_gid, "Strafe Pits", _infoPath, self._DisplayStrafePits, self, _unitName)
|
missionCommands.addCommandForGroup(_gid, "Strafe Pits", _infoPath, self._DisplayStrafePits, self, _unitName)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
self:T(self.id.."Could not find group or group ID in AddF10Menu() function. Unit name: ".._unitName)
|
self:E(self.id.."Could not find group or group ID in AddF10Menu() function. Unit name: ".._unitName)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
self:T(self.id.."Player unit does not exist in AddF10Menu() function. Unit name: ".._unitName)
|
self:E(self.id.."Player unit does not exist in AddF10Menu() function. Unit name: ".._unitName)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -39,7 +39,7 @@
|
|||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ### Author: **FlightControl**
|
-- ### Author: **FlightControl**
|
||||||
-- ### Contributions: **Millertime** - Concept
|
-- ### Contributions: **Millertime** - Concept, **funkyfranky**
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
@@ -49,6 +49,15 @@
|
|||||||
do -- ZONE_CAPTURE_COALITION
|
do -- ZONE_CAPTURE_COALITION
|
||||||
|
|
||||||
--- @type ZONE_CAPTURE_COALITION
|
--- @type ZONE_CAPTURE_COALITION
|
||||||
|
-- @field #string ClassName Name of the class.
|
||||||
|
-- @field #number MarkBlue ID of blue F10 mark.
|
||||||
|
-- @field #number MarkRed ID of red F10 mark.
|
||||||
|
-- @field #number StartInterval Time in seconds after the status monitor is started.
|
||||||
|
-- @field #number RepeatInterval Time in seconds after which the zone status is updated.
|
||||||
|
-- @field #boolean HitsOn If true, hit events are monitored and trigger the "Attack" event when a defending unit is hit.
|
||||||
|
-- @field #number HitTimeLast Time stamp in seconds when the last unit inside the zone was hit.
|
||||||
|
-- @field #number HitTimeAttackOver Time interval in seconds before the zone goes from "Attacked" to "Guarded" state after the last hit.
|
||||||
|
-- @field #boolean MarkOn If true, create marks of zone status on F10 map.
|
||||||
-- @extends Functional.ZoneGoalCoalition#ZONE_GOAL_COALITION
|
-- @extends Functional.ZoneGoalCoalition#ZONE_GOAL_COALITION
|
||||||
|
|
||||||
|
|
||||||
@@ -197,8 +206,7 @@ do -- ZONE_CAPTURE_COALITION
|
|||||||
--
|
--
|
||||||
-- ### IMPORTANT
|
-- ### IMPORTANT
|
||||||
--
|
--
|
||||||
-- **Each capture zone object must have the monitoring process started specifically.
|
-- **Each capture zone object must have the monitoring process started specifically. The monitoring process is NOT started by default!**
|
||||||
-- The monitoring process is NOT started by default!!!**
|
|
||||||
--
|
--
|
||||||
--
|
--
|
||||||
-- # Full Example
|
-- # Full Example
|
||||||
@@ -338,29 +346,48 @@ do -- ZONE_CAPTURE_COALITION
|
|||||||
--
|
--
|
||||||
-- @field #ZONE_CAPTURE_COALITION
|
-- @field #ZONE_CAPTURE_COALITION
|
||||||
ZONE_CAPTURE_COALITION = {
|
ZONE_CAPTURE_COALITION = {
|
||||||
ClassName = "ZONE_CAPTURE_COALITION",
|
ClassName = "ZONE_CAPTURE_COALITION",
|
||||||
|
MarkBlue = nil,
|
||||||
|
MarkRed = nil,
|
||||||
|
StartInterval = nil,
|
||||||
|
RepeatInterval = nil,
|
||||||
|
HitsOn = nil,
|
||||||
|
HitTimeLast = nil,
|
||||||
|
HitTimeAttackOver = nil,
|
||||||
|
MarkOn = nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
--- @field #table ZONE_CAPTURE_COALITION.States
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
ZONE_CAPTURE_COALITION.States = {}
|
-- Constructor and Start/Stop Functions
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
--- ZONE_CAPTURE_COALITION Constructor.
|
--- ZONE_CAPTURE_COALITION Constructor.
|
||||||
-- @param #ZONE_CAPTURE_COALITION self
|
-- @param #ZONE_CAPTURE_COALITION self
|
||||||
-- @param Core.Zone#ZONE Zone A @{Zone} object with the goal to be achieved.
|
-- @param Core.Zone#ZONE Zone A @{Zone} object with the goal to be achieved.
|
||||||
-- @param DCSCoalition.DCSCoalition#coalition Coalition The initial coalition owning the zone.
|
-- @param DCSCoalition.DCSCoalition#coalition Coalition The initial coalition owning the zone.
|
||||||
|
-- @param #table UnitCategories Table of unit categories. See [DCS Class Unit](https://wiki.hoggitworld.com/view/DCS_Class_Unit). Default {Unit.Category.GROUND_UNIT}.
|
||||||
|
-- @param #table ObjectCategories Table of unit categories. See [DCS Class Object](https://wiki.hoggitworld.com/view/DCS_Class_Object). Default {Object.Category.UNIT, Object.Category.STATIC}, i.e. all UNITS and STATICS.
|
||||||
-- @return #ZONE_CAPTURE_COALITION
|
-- @return #ZONE_CAPTURE_COALITION
|
||||||
-- @usage
|
-- @usage
|
||||||
--
|
--
|
||||||
-- AttackZone = ZONE:New( "AttackZone" )
|
-- AttackZone = ZONE:New( "AttackZone" )
|
||||||
--
|
--
|
||||||
-- ZoneCaptureCoalition = ZONE_CAPTURE_COALITION:New( AttackZone, coalition.side.RED ) -- Create a new ZONE_CAPTURE_COALITION object of zone AttackZone with ownership RED coalition.
|
-- ZoneCaptureCoalition = ZONE_CAPTURE_COALITION:New( AttackZone, coalition.side.RED, {UNITS ) -- Create a new ZONE_CAPTURE_COALITION object of zone AttackZone with ownership RED coalition.
|
||||||
-- ZoneCaptureCoalition:__Guard( 1 ) -- Start the Guarding of the AttackZone.
|
-- ZoneCaptureCoalition:__Guard( 1 ) -- Start the Guarding of the AttackZone.
|
||||||
--
|
--
|
||||||
function ZONE_CAPTURE_COALITION:New( Zone, Coalition, UnitCategories )
|
function ZONE_CAPTURE_COALITION:New( Zone, Coalition, UnitCategories, ObjectCategories )
|
||||||
|
|
||||||
local self = BASE:Inherit( self, ZONE_GOAL_COALITION:New( Zone, Coalition, UnitCategories ) ) -- #ZONE_CAPTURE_COALITION
|
local self = BASE:Inherit( self, ZONE_GOAL_COALITION:New( Zone, Coalition, UnitCategories ) ) -- #ZONE_CAPTURE_COALITION
|
||||||
|
self:F( { Zone = Zone, Coalition = Coalition, UnitCategories = UnitCategories, ObjectCategories = ObjectCategories } )
|
||||||
|
|
||||||
self:F( { Zone = Zone, Coalition = Coalition, UnitCategories = UnitCategories } )
|
self:SetObjectCategories(ObjectCategories)
|
||||||
|
|
||||||
|
-- Default is no smoke.
|
||||||
|
self:SetSmokeZone(false)
|
||||||
|
-- Default is F10 marks ON.
|
||||||
|
self:SetMarkZone(true)
|
||||||
|
-- Start in state "Empty".
|
||||||
|
self:SetStartState("Empty")
|
||||||
|
|
||||||
do
|
do
|
||||||
|
|
||||||
@@ -545,185 +572,13 @@ do -- ZONE_CAPTURE_COALITION
|
|||||||
-- @param #ZONE_CAPTURE_COALITION self
|
-- @param #ZONE_CAPTURE_COALITION self
|
||||||
-- @param #number Delay
|
-- @param #number Delay
|
||||||
|
|
||||||
-- We check if a unit within the zone is hit.
|
|
||||||
-- If it is, then we must move the zone to attack state.
|
|
||||||
self:HandleEvent( EVENTS.Hit, self.OnEventHit )
|
|
||||||
|
|
||||||
-- ZoneGoal objects are added to the _DATABASE.ZONES_GOAL and SET_ZONE_GOAL sets.
|
-- ZoneGoal objects are added to the _DATABASE.ZONES_GOAL and SET_ZONE_GOAL sets.
|
||||||
_EVENTDISPATCHER:CreateEventNewZoneGoal( self )
|
_EVENTDISPATCHER:CreateEventNewZoneGoal(self)
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- @param #ZONE_CAPTURE_COALITION self
|
|
||||||
function ZONE_CAPTURE_COALITION:onenterCaptured()
|
|
||||||
|
|
||||||
self:F({"hello"})
|
|
||||||
|
|
||||||
self:GetParent( self, ZONE_CAPTURE_COALITION ).onenterCaptured( self )
|
|
||||||
|
|
||||||
self.Goal:Achieved()
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function ZONE_CAPTURE_COALITION:IsGuarded()
|
|
||||||
|
|
||||||
local IsGuarded = self:IsAllInZoneOfCoalition( self.Coalition )
|
|
||||||
self:F( { IsGuarded = IsGuarded } )
|
|
||||||
return IsGuarded
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function ZONE_CAPTURE_COALITION:IsEmpty()
|
|
||||||
|
|
||||||
local IsEmpty = self:IsNoneInZone()
|
|
||||||
self:F( { IsEmpty = IsEmpty } )
|
|
||||||
return IsEmpty
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function ZONE_CAPTURE_COALITION:IsCaptured()
|
|
||||||
|
|
||||||
local IsCaptured = self:IsAllInZoneOfOtherCoalition( self.Coalition )
|
|
||||||
self:F( { IsCaptured = IsCaptured } )
|
|
||||||
return IsCaptured
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function ZONE_CAPTURE_COALITION:IsAttacked()
|
|
||||||
|
|
||||||
local IsAttacked = self:IsSomeInZoneOfCoalition( self.Coalition )
|
|
||||||
self:F( { IsAttacked = IsAttacked } )
|
|
||||||
return IsAttacked
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--- Mark.
|
|
||||||
-- @param #ZONE_CAPTURE_COALITION self
|
|
||||||
function ZONE_CAPTURE_COALITION:Mark()
|
|
||||||
|
|
||||||
local Coord = self:GetCoordinate()
|
|
||||||
local ZoneName = self:GetZoneName()
|
|
||||||
local State = self:GetState()
|
|
||||||
|
|
||||||
if self.MarkRed and self.MarkBlue then
|
|
||||||
self:F( { MarkRed = self.MarkRed, MarkBlue = self.MarkBlue } )
|
|
||||||
Coord:RemoveMark( self.MarkRed )
|
|
||||||
Coord:RemoveMark( self.MarkBlue )
|
|
||||||
end
|
|
||||||
|
|
||||||
if self.Coalition == coalition.side.BLUE then
|
|
||||||
self.MarkBlue = Coord:MarkToCoalitionBlue( "Coalition: Blue\nGuard Zone: " .. ZoneName .. "\nStatus: " .. State )
|
|
||||||
self.MarkRed = Coord:MarkToCoalitionRed( "Coalition: Blue\nCapture Zone: " .. ZoneName .. "\nStatus: " .. State )
|
|
||||||
else
|
|
||||||
self.MarkRed = Coord:MarkToCoalitionRed( "Coalition: Red\nGuard Zone: " .. ZoneName .. "\nStatus: " .. State )
|
|
||||||
self.MarkBlue = Coord:MarkToCoalitionBlue( "Coalition: Red\nCapture Zone: " .. ZoneName .. "\nStatus: " .. State )
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Bound.
|
|
||||||
-- @param #ZONE_CAPTURE_COALITION self
|
|
||||||
function ZONE_CAPTURE_COALITION:onenterGuarded()
|
|
||||||
|
|
||||||
--self:GetParent( self ):onenterGuarded()
|
|
||||||
|
|
||||||
if self.Coalition == coalition.side.BLUE then
|
|
||||||
--elf.ProtectZone:BoundZone( 12, country.id.USA )
|
|
||||||
else
|
|
||||||
--self.ProtectZone:BoundZone( 12, country.id.RUSSIA )
|
|
||||||
end
|
|
||||||
|
|
||||||
self:Mark()
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
function ZONE_CAPTURE_COALITION:onenterCaptured()
|
|
||||||
|
|
||||||
--self:GetParent( self ):onenterCaptured()
|
|
||||||
|
|
||||||
local NewCoalition = self:GetScannedCoalition()
|
|
||||||
self:F( { NewCoalition = NewCoalition } )
|
|
||||||
self:SetCoalition( NewCoalition )
|
|
||||||
|
|
||||||
self:Mark()
|
|
||||||
self.Goal:Achieved()
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function ZONE_CAPTURE_COALITION:onenterEmpty()
|
|
||||||
|
|
||||||
--self:GetParent( self ):onenterEmpty()
|
|
||||||
|
|
||||||
self:Mark()
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function ZONE_CAPTURE_COALITION:onenterAttacked()
|
|
||||||
|
|
||||||
--self:GetParent( self ):onenterAttacked()
|
|
||||||
|
|
||||||
self:Mark()
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
--- When started, check the Coalition status.
|
|
||||||
-- @param #ZONE_CAPTURE_COALITION self
|
|
||||||
function ZONE_CAPTURE_COALITION:onafterGuard()
|
|
||||||
|
|
||||||
--self:F({BASE:GetParent( self )})
|
|
||||||
--BASE:GetParent( self ).onafterGuard( self )
|
|
||||||
|
|
||||||
if not self.SmokeScheduler then
|
|
||||||
self.SmokeScheduler = self:ScheduleRepeat( self.StartInterval, self.RepeatInterval, 0.1, nil, self.StatusSmoke, self )
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function ZONE_CAPTURE_COALITION:IsCaptured()
|
|
||||||
|
|
||||||
local IsCaptured = self:IsAllInZoneOfOtherCoalition( self.Coalition )
|
|
||||||
self:F( { IsCaptured = IsCaptured } )
|
|
||||||
return IsCaptured
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function ZONE_CAPTURE_COALITION:IsAttacked()
|
|
||||||
|
|
||||||
local IsAttacked = self:IsSomeInZoneOfCoalition( self.Coalition )
|
|
||||||
self:F( { IsAttacked = IsAttacked } )
|
|
||||||
return IsAttacked
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
--- Check status Coalition ownership.
|
|
||||||
-- @param #ZONE_CAPTURE_COALITION self
|
|
||||||
function ZONE_CAPTURE_COALITION:StatusZone()
|
|
||||||
|
|
||||||
local State = self:GetState()
|
|
||||||
self:F( { State = self:GetState() } )
|
|
||||||
|
|
||||||
self:GetParent( self, ZONE_CAPTURE_COALITION ).StatusZone( self )
|
|
||||||
|
|
||||||
if State ~= "Guarded" and self:IsGuarded() then
|
|
||||||
self:Guard()
|
|
||||||
end
|
|
||||||
|
|
||||||
if State ~= "Empty" and self:IsEmpty() then
|
|
||||||
self:Empty()
|
|
||||||
end
|
|
||||||
|
|
||||||
if State ~= "Attacked" and self:IsAttacked() then
|
|
||||||
self:Attack()
|
|
||||||
end
|
|
||||||
|
|
||||||
if State ~= "Captured" and self:IsCaptured() then
|
|
||||||
self:Capture()
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Starts the zone capturing monitoring process.
|
--- Starts the zone capturing monitoring process.
|
||||||
-- This process can be CPU intensive, ensure that you specify reasonable time intervals for the monitoring process.
|
-- This process can be CPU intensive, ensure that you specify reasonable time intervals for the monitoring process.
|
||||||
-- Note that the monitoring process is NOT started automatically during the `:New()` constructor.
|
-- Note that the monitoring process is NOT started automatically during the `:New()` constructor.
|
||||||
@@ -733,6 +588,7 @@ do -- ZONE_CAPTURE_COALITION
|
|||||||
-- @param #ZONE_CAPTURE_COALITION self
|
-- @param #ZONE_CAPTURE_COALITION self
|
||||||
-- @param #number StartInterval (optional) Specifies the start time interval in seconds when the zone state will be checked for the first time.
|
-- @param #number StartInterval (optional) Specifies the start time interval in seconds when the zone state will be checked for the first time.
|
||||||
-- @param #number RepeatInterval (optional) Specifies the repeat time interval in seconds when the zone state will be checked repeatedly.
|
-- @param #number RepeatInterval (optional) Specifies the repeat time interval in seconds when the zone state will be checked repeatedly.
|
||||||
|
-- @return #ZONE_CAPTURE_COALITION self
|
||||||
-- @usage
|
-- @usage
|
||||||
--
|
--
|
||||||
-- -- Setup the zone.
|
-- -- Setup the zone.
|
||||||
@@ -747,13 +603,23 @@ do -- ZONE_CAPTURE_COALITION
|
|||||||
--
|
--
|
||||||
function ZONE_CAPTURE_COALITION:Start( StartInterval, RepeatInterval )
|
function ZONE_CAPTURE_COALITION:Start( StartInterval, RepeatInterval )
|
||||||
|
|
||||||
self.StartInterval = StartInterval or 15
|
self.StartInterval = StartInterval or 1
|
||||||
self.RepeatInterval = RepeatInterval or 15
|
self.RepeatInterval = RepeatInterval or 15
|
||||||
|
|
||||||
if self.ScheduleStatusZone then
|
if self.ScheduleStatusZone then
|
||||||
self:ScheduleStop( self.ScheduleStatusZone )
|
self:ScheduleStop( self.ScheduleStatusZone )
|
||||||
end
|
end
|
||||||
self.ScheduleStatusZone = self:ScheduleRepeat( self.StartInterval, self.RepeatInterval, 1.5, nil, self.StatusZone, self )
|
|
||||||
|
-- Start Status scheduler.
|
||||||
|
self.ScheduleStatusZone = self:ScheduleRepeat( self.StartInterval, self.RepeatInterval, 0.1, nil, self.StatusZone, self )
|
||||||
|
|
||||||
|
-- We check if a unit within the zone is hit. If it is, then we must move the zone to attack state.
|
||||||
|
self:HandleEvent(EVENTS.Hit, self.OnEventHit)
|
||||||
|
|
||||||
|
-- Create mark on F10 map.
|
||||||
|
self:Mark()
|
||||||
|
|
||||||
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -795,24 +661,281 @@ do -- ZONE_CAPTURE_COALITION
|
|||||||
function ZONE_CAPTURE_COALITION:Stop()
|
function ZONE_CAPTURE_COALITION:Stop()
|
||||||
|
|
||||||
if self.ScheduleStatusZone then
|
if self.ScheduleStatusZone then
|
||||||
self:ScheduleStop( self.ScheduleStatusZone )
|
self:ScheduleStop(self.ScheduleStatusZone)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if self.SmokeScheduler then
|
||||||
|
self:ScheduleStop(self.SmokeScheduler)
|
||||||
|
end
|
||||||
|
|
||||||
|
self:UnHandleEvent(EVENTS.Hit)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #ZONE_CAPTURE_COALITION self
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-- User API Functions
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- Set whether hit events of defending units are monitored and trigger "Attack" events.
|
||||||
|
-- @param #ZONE_CAPTURE_COALITION self
|
||||||
|
-- @param #boolean Switch If *true*, hit events are monitored. If *false* or *nil*, hit events are not monitored.
|
||||||
|
-- @param #number TimeAttackOver (Optional) Time in seconds after an attack is over after the last hit and the zone state goes to "Guarded". Default is 300 sec = 5 min.
|
||||||
|
-- @return #ZONE_CAPTURE_COALITION self
|
||||||
|
function ZONE_CAPTURE_COALITION:SetMonitorHits(Switch, TimeAttackOver)
|
||||||
|
self.HitsOn=Switch
|
||||||
|
self.HitTimeAttackOver=TimeAttackOver or 5*60
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set whether marks on the F10 map are shown, which display the current zone status.
|
||||||
|
-- @param #ZONE_CAPTURE_COALITION self
|
||||||
|
-- @param #boolean Switch If *true* or *nil*, marks are shown. If *false*, marks are not displayed.
|
||||||
|
-- @return #ZONE_CAPTURE_COALITION self
|
||||||
|
function ZONE_CAPTURE_COALITION:SetMarkZone(Switch)
|
||||||
|
if Switch==nil or Switch==true then
|
||||||
|
self.MarkOn=true
|
||||||
|
else
|
||||||
|
self.MarkOn=false
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-- DCS Event Functions
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
--- Monitor hit events.
|
||||||
|
-- @param #ZONE_CAPTURE_COALITION self
|
||||||
-- @param Core.Event#EVENTDATA EventData The event data.
|
-- @param Core.Event#EVENTDATA EventData The event data.
|
||||||
function ZONE_CAPTURE_COALITION:OnEventHit( EventData )
|
function ZONE_CAPTURE_COALITION:OnEventHit( EventData )
|
||||||
|
|
||||||
local UnitHit = EventData.TgtUnit
|
if self.HitsOn then
|
||||||
|
|
||||||
|
local UnitHit = EventData.TgtUnit
|
||||||
|
|
||||||
|
-- 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
|
||||||
|
|
||||||
|
-- Update last hit time.
|
||||||
|
self.HitTimeLast=timer.getTime()
|
||||||
|
|
||||||
|
-- Only trigger attacked event if not already in state "Attacked".
|
||||||
|
if self:GetState()~="Attacked" then
|
||||||
|
self:F2("Hit ==> Attack")
|
||||||
|
self:Attack()
|
||||||
|
end
|
||||||
|
|
||||||
if UnitHit then
|
|
||||||
if UnitHit:IsInZone( self ) then
|
|
||||||
self:Attack()
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-- FSM Event Functions
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- On after "Guard" event.
|
||||||
|
-- @param #ZONE_CAPTURE_COALITION self
|
||||||
|
function ZONE_CAPTURE_COALITION:onafterGuard()
|
||||||
|
self:F2("After Guard")
|
||||||
|
|
||||||
|
if self.SmokeZone and not self.SmokeScheduler then
|
||||||
|
self.SmokeScheduler = self:ScheduleRepeat( self.StartInterval, self.RepeatInterval, 0.1, nil, self.StatusSmoke, self )
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--- On enter "Guarded" state.
|
||||||
|
-- @param #ZONE_CAPTURE_COALITION self
|
||||||
|
function ZONE_CAPTURE_COALITION:onenterGuarded()
|
||||||
|
self:F2("Enter Guarded")
|
||||||
|
self:Mark()
|
||||||
|
end
|
||||||
|
|
||||||
|
--- On enter "Captured" state.
|
||||||
|
-- @param #ZONE_CAPTURE_COALITION self
|
||||||
|
function ZONE_CAPTURE_COALITION:onenterCaptured()
|
||||||
|
self:F2("Enter Captured")
|
||||||
|
|
||||||
|
-- Get new coalition.
|
||||||
|
local NewCoalition = self:GetScannedCoalition()
|
||||||
|
self:F( { NewCoalition = NewCoalition } )
|
||||||
|
|
||||||
|
-- Set new owner of zone.
|
||||||
|
self:SetCoalition(NewCoalition)
|
||||||
|
|
||||||
|
-- Update mark.
|
||||||
|
self:Mark()
|
||||||
|
|
||||||
|
-- Goal achieved.
|
||||||
|
self.Goal:Achieved()
|
||||||
|
end
|
||||||
|
|
||||||
|
--- On enter "Empty" state.
|
||||||
|
-- @param #ZONE_CAPTURE_COALITION self
|
||||||
|
function ZONE_CAPTURE_COALITION:onenterEmpty()
|
||||||
|
self:F2("Enter Empty")
|
||||||
|
self:Mark()
|
||||||
|
end
|
||||||
|
|
||||||
|
--- On enter "Attacked" state.
|
||||||
|
-- @param #ZONE_CAPTURE_COALITION self
|
||||||
|
function ZONE_CAPTURE_COALITION:onenterAttacked()
|
||||||
|
self:F2("Enter Attacked")
|
||||||
|
self:Mark()
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-- Status Check Functions
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- Check if zone is "Empty".
|
||||||
|
-- @param #ZONE_CAPTURE_COALITION self
|
||||||
|
-- @return #boolean self:IsNoneInZone()
|
||||||
|
function ZONE_CAPTURE_COALITION:IsEmpty()
|
||||||
|
|
||||||
|
local IsEmpty = self:IsNoneInZone()
|
||||||
|
self:F( { IsEmpty = IsEmpty } )
|
||||||
|
|
||||||
|
return IsEmpty
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Check if zone is "Guarded", i.e. only one (the defending) coaliton is present inside the zone.
|
||||||
|
-- @param #ZONE_CAPTURE_COALITION self
|
||||||
|
-- @return #boolean self:IsAllInZoneOfCoalition( self.Coalition )
|
||||||
|
function ZONE_CAPTURE_COALITION:IsGuarded()
|
||||||
|
|
||||||
|
local IsGuarded = self:IsAllInZoneOfCoalition( self.Coalition )
|
||||||
|
self:F( { IsGuarded = IsGuarded } )
|
||||||
|
|
||||||
|
return IsGuarded
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Check if zone is "Captured", i.e. another coalition took control over the zone and is the only one present.
|
||||||
|
-- @param #ZONE_CAPTURE_COALITION self
|
||||||
|
-- @return #boolean self:IsAllInZoneOfOtherCoalition( self.Coalition )
|
||||||
|
function ZONE_CAPTURE_COALITION:IsCaptured()
|
||||||
|
|
||||||
|
local IsCaptured = self:IsAllInZoneOfOtherCoalition( self.Coalition )
|
||||||
|
self:F( { IsCaptured = IsCaptured } )
|
||||||
|
|
||||||
|
return IsCaptured
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Check if zone is "Attacked", i.e. another coaliton entered the zone.
|
||||||
|
-- @param #ZONE_CAPTURE_COALITION self
|
||||||
|
-- @return #boolean self:IsSomeInZoneOfCoalition( self.Coalition )
|
||||||
|
function ZONE_CAPTURE_COALITION:IsAttacked()
|
||||||
|
|
||||||
|
local IsAttacked = self:IsSomeInZoneOfCoalition( self.Coalition )
|
||||||
|
self:F( { IsAttacked = IsAttacked } )
|
||||||
|
|
||||||
|
return IsAttacked
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Check status Coalition ownership.
|
||||||
|
-- @param #ZONE_CAPTURE_COALITION self
|
||||||
|
function ZONE_CAPTURE_COALITION:StatusZone()
|
||||||
|
|
||||||
|
-- Get FSM state.
|
||||||
|
local State = self:GetState()
|
||||||
|
|
||||||
|
-- Scan zone in parent class ZONE_GOAL_COALITION
|
||||||
|
self:GetParent( self, ZONE_CAPTURE_COALITION ).StatusZone( self )
|
||||||
|
|
||||||
|
local Tnow=timer.getTime()
|
||||||
|
|
||||||
|
-- Check if zone is guarded.
|
||||||
|
if State ~= "Guarded" and self:IsGuarded() then
|
||||||
|
|
||||||
|
-- Check that there was a sufficient amount of time after the last hit before going back to "Guarded".
|
||||||
|
if self.HitTimeLast==nil or Tnow>=self.HitTimeLast+self.HitTimeAttackOver then
|
||||||
|
self:Guard()
|
||||||
|
self.HitTimeLast=nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check if zone is empty.
|
||||||
|
if State ~= "Empty" and self:IsEmpty() then
|
||||||
|
self:Empty()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check if zone is attacked.
|
||||||
|
if State ~= "Attacked" and self:IsAttacked() then
|
||||||
|
self:Attack()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check if zone is captured.
|
||||||
|
if State ~= "Captured" and self:IsCaptured() then
|
||||||
|
self:Capture()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Count stuff in zone.
|
||||||
|
local unitset=self:GetScannedSetUnit()
|
||||||
|
local nRed=0
|
||||||
|
local nBlue=0
|
||||||
|
for _,object in pairs(unitset:GetSet()) do
|
||||||
|
local coal=object:GetCoalition()
|
||||||
|
if object:IsAlive() then
|
||||||
|
if coal==coalition.side.RED then
|
||||||
|
nRed=nRed+1
|
||||||
|
elseif coal==coalition.side.BLUE then
|
||||||
|
nBlue=nBlue+1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- 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)
|
||||||
|
local NewState = self:GetState()
|
||||||
|
if NewState~=State then
|
||||||
|
text=text..string.format(" --> %s", NewState)
|
||||||
|
end
|
||||||
|
self:I(text)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-- Misc Functions
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
--- Update Mark on F10 map.
|
||||||
|
-- @param #ZONE_CAPTURE_COALITION self
|
||||||
|
function ZONE_CAPTURE_COALITION:Mark()
|
||||||
|
|
||||||
|
if self.MarkOn then
|
||||||
|
|
||||||
|
local Coord = self:GetCoordinate()
|
||||||
|
local ZoneName = self:GetZoneName()
|
||||||
|
local State = self:GetState()
|
||||||
|
|
||||||
|
-- Remove marks.
|
||||||
|
if self.MarkRed then
|
||||||
|
Coord:RemoveMark(self.MarkRed)
|
||||||
|
end
|
||||||
|
if self.MarkBlue then
|
||||||
|
Coord:RemoveMark(self.MarkBlue)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Create new marks for each coaliton.
|
||||||
|
if self.Coalition == coalition.side.BLUE then
|
||||||
|
self.MarkBlue = Coord:MarkToCoalitionBlue( "Coalition: Blue\nGuard Zone: " .. ZoneName .. "\nStatus: " .. State )
|
||||||
|
self.MarkRed = Coord:MarkToCoalitionRed( "Coalition: Blue\nCapture Zone: " .. ZoneName .. "\nStatus: " .. State )
|
||||||
|
elseif self.Coalition == coalition.side.RED then
|
||||||
|
self.MarkRed = Coord:MarkToCoalitionRed( "Coalition: Red\nGuard Zone: " .. ZoneName .. "\nStatus: " .. State )
|
||||||
|
self.MarkBlue = Coord:MarkToCoalitionBlue( "Coalition: Red\nCapture Zone: " .. ZoneName .. "\nStatus: " .. State )
|
||||||
|
else
|
||||||
|
self.MarkRed = Coord:MarkToCoalitionRed( "Coalition: Neutral\nCapture Zone: " .. ZoneName .. "\nStatus: " .. State )
|
||||||
|
self.MarkBlue = Coord:MarkToCoalitionBlue( "Coalition: Neutral\nCapture Zone: " .. ZoneName .. "\nStatus: " .. State )
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ### Author: **FlightControl**
|
-- ### Author: **FlightControl**
|
||||||
|
-- ### Contributions: **funkyfranky**
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
@@ -17,10 +18,16 @@
|
|||||||
do -- Zone
|
do -- Zone
|
||||||
|
|
||||||
--- @type ZONE_GOAL
|
--- @type ZONE_GOAL
|
||||||
-- @extends Core.Fsm#FSM
|
-- @field #string ClassName Name of the class.
|
||||||
|
-- @field Core.Goal#GOAL Goal The goal object.
|
||||||
|
-- @field #number SmokeTime Time stamp in seconds when the last smoke of the zone was triggered.
|
||||||
|
-- @field Core.Scheduler#SCHEDULER SmokeScheduler Scheduler responsible for smoking the zone.
|
||||||
|
-- @field #number SmokeColor Color of the smoke.
|
||||||
|
-- @field #boolean SmokeZone If true, smoke zone.
|
||||||
|
-- @extends Core.Zone#ZONE_RADIUS
|
||||||
|
|
||||||
|
|
||||||
-- Models processes that have a Goal with a defined achievement involving a Zone.
|
--- Models processes that have a Goal with a defined achievement involving a Zone.
|
||||||
-- Derived classes implement the ways how the achievements can be realized.
|
-- Derived classes implement the ways how the achievements can be realized.
|
||||||
--
|
--
|
||||||
-- ## 1. ZONE_GOAL constructor
|
-- ## 1. ZONE_GOAL constructor
|
||||||
@@ -39,7 +46,12 @@ do -- Zone
|
|||||||
--
|
--
|
||||||
-- @field #ZONE_GOAL
|
-- @field #ZONE_GOAL
|
||||||
ZONE_GOAL = {
|
ZONE_GOAL = {
|
||||||
ClassName = "ZONE_GOAL",
|
ClassName = "ZONE_GOAL",
|
||||||
|
Goal = nil,
|
||||||
|
SmokeTime = nil,
|
||||||
|
SmokeScheduler = nil,
|
||||||
|
SmokeColor = nil,
|
||||||
|
SmokeZone = nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
--- ZONE_GOAL Constructor.
|
--- ZONE_GOAL Constructor.
|
||||||
@@ -51,12 +63,25 @@ do -- Zone
|
|||||||
local self = BASE:Inherit( self, ZONE_RADIUS:New( Zone:GetName(), Zone:GetVec2(), Zone:GetRadius() ) ) -- #ZONE_GOAL
|
local self = BASE:Inherit( self, ZONE_RADIUS:New( Zone:GetName(), Zone:GetVec2(), Zone:GetRadius() ) ) -- #ZONE_GOAL
|
||||||
self:F( { Zone = Zone } )
|
self:F( { Zone = Zone } )
|
||||||
|
|
||||||
|
-- Goal object.
|
||||||
self.Goal = GOAL:New()
|
self.Goal = GOAL:New()
|
||||||
|
|
||||||
self.SmokeTime = nil
|
self.SmokeTime = nil
|
||||||
|
|
||||||
|
-- Set smoke ON.
|
||||||
|
self:SetSmokeZone(true)
|
||||||
|
|
||||||
self:AddTransition( "*", "DestroyedUnit", "*" )
|
self:AddTransition( "*", "DestroyedUnit", "*" )
|
||||||
|
|
||||||
|
--- DestroyedUnit event.
|
||||||
|
-- @function [parent=#ZONE_GOAL] DestroyedUnit
|
||||||
|
-- @param #ZONE_GOAL self
|
||||||
|
|
||||||
|
--- DestroyedUnit delayed event
|
||||||
|
-- @function [parent=#ZONE_GOAL] __DestroyedUnit
|
||||||
|
-- @param #ZONE_GOAL self
|
||||||
|
-- @param #number delay Delay in seconds.
|
||||||
|
|
||||||
--- DestroyedUnit Handler OnAfter for ZONE_GOAL
|
--- DestroyedUnit Handler OnAfter for ZONE_GOAL
|
||||||
-- @function [parent=#ZONE_GOAL] OnAfterDestroyedUnit
|
-- @function [parent=#ZONE_GOAL] OnAfterDestroyedUnit
|
||||||
-- @param #ZONE_GOAL self
|
-- @param #ZONE_GOAL self
|
||||||
@@ -66,19 +91,18 @@ do -- Zone
|
|||||||
-- @param Wrapper.Unit#UNIT DestroyedUnit The destroyed unit.
|
-- @param Wrapper.Unit#UNIT DestroyedUnit The destroyed unit.
|
||||||
-- @param #string PlayerName The name of the player.
|
-- @param #string PlayerName The name of the player.
|
||||||
|
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Get the Zone
|
--- Get the Zone.
|
||||||
-- @param #ZONE_GOAL self
|
-- @param #ZONE_GOAL self
|
||||||
-- @return Core.Zone#ZONE_BASE
|
-- @return #ZONE_GOAL
|
||||||
function ZONE_GOAL:GetZone()
|
function ZONE_GOAL:GetZone()
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Get the name of the ProtectZone
|
--- Get the name of the Zone.
|
||||||
-- @param #ZONE_GOAL self
|
-- @param #ZONE_GOAL self
|
||||||
-- @return #string
|
-- @return #string
|
||||||
function ZONE_GOAL:GetZoneName()
|
function ZONE_GOAL:GetZoneName()
|
||||||
@@ -86,36 +110,48 @@ do -- Zone
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Smoke the center of theh zone.
|
--- Activate smoking of zone with the color or the current owner.
|
||||||
-- @param #ZONE_GOAL self
|
-- @param #ZONE_GOAL self
|
||||||
-- @param #SMOKECOLOR.Color SmokeColor
|
-- @param #boolean switch If *true* or *nil* activate smoke. If *false* or *nil*, no smoke.
|
||||||
function ZONE_GOAL:Smoke( SmokeColor )
|
-- @return #ZONE_GOAL
|
||||||
|
function ZONE_GOAL:SetSmokeZone(switch)
|
||||||
|
self.SmokeZone=switch
|
||||||
|
--[[
|
||||||
|
if switch==nil or switch==true then
|
||||||
|
self.SmokeZone=true
|
||||||
|
else
|
||||||
|
self.SmokeZone=false
|
||||||
|
end
|
||||||
|
]]
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set the smoke color.
|
||||||
|
-- @param #ZONE_GOAL self
|
||||||
|
-- @param DCS#SMOKECOLOR.Color SmokeColor
|
||||||
|
function ZONE_GOAL:Smoke( SmokeColor )
|
||||||
self:F( { SmokeColor = SmokeColor} )
|
self:F( { SmokeColor = SmokeColor} )
|
||||||
|
|
||||||
self.SmokeColor = SmokeColor
|
self.SmokeColor = SmokeColor
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Flare the center of the zone.
|
--- Flare the zone boundary.
|
||||||
-- @param #ZONE_GOAL self
|
-- @param #ZONE_GOAL self
|
||||||
-- @param #SMOKECOLOR.Color FlareColor
|
-- @param DCS#SMOKECOLOR.Color FlareColor
|
||||||
function ZONE_GOAL:Flare( FlareColor )
|
function ZONE_GOAL:Flare( FlareColor )
|
||||||
self:FlareZone( FlareColor, math.random( 1, 360 ) )
|
self:FlareZone( FlareColor, 30)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- When started, check the Smoke and the Zone status.
|
--- When started, check the Smoke and the Zone status.
|
||||||
-- @param #ZONE_GOAL self
|
-- @param #ZONE_GOAL self
|
||||||
function ZONE_GOAL:onafterGuard()
|
function ZONE_GOAL:onafterGuard()
|
||||||
|
|
||||||
--self:GetParent( self ):onafterStart()
|
|
||||||
|
|
||||||
self:F("Guard")
|
self:F("Guard")
|
||||||
|
|
||||||
--self:ScheduleRepeat( 15, 15, 0.1, nil, self.StatusZone, self )
|
-- Start smoke
|
||||||
if not self.SmokeScheduler then
|
if self.SmokeZone and not self.SmokeScheduler then
|
||||||
self.SmokeScheduler = self:ScheduleRepeat( 1, 1, 0.1, nil, self.StatusSmoke, self )
|
self.SmokeScheduler = self:ScheduleRepeat(1, 1, 0.1, nil, self.StatusSmoke, self)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -123,42 +159,54 @@ do -- Zone
|
|||||||
--- Check status Smoke.
|
--- Check status Smoke.
|
||||||
-- @param #ZONE_GOAL self
|
-- @param #ZONE_GOAL self
|
||||||
function ZONE_GOAL:StatusSmoke()
|
function ZONE_GOAL:StatusSmoke()
|
||||||
|
|
||||||
self:F({self.SmokeTime, self.SmokeColor})
|
self:F({self.SmokeTime, self.SmokeColor})
|
||||||
|
|
||||||
local CurrentTime = timer.getTime()
|
if self.SmokeZone then
|
||||||
|
|
||||||
if self.SmokeTime == nil or self.SmokeTime + 300 <= CurrentTime then
|
-- Current time.
|
||||||
if self.SmokeColor then
|
local CurrentTime = timer.getTime()
|
||||||
self:GetCoordinate():Smoke( self.SmokeColor )
|
|
||||||
--self.SmokeColor = nil
|
-- Restart smoke every 5 min.
|
||||||
self.SmokeTime = CurrentTime
|
if self.SmokeTime == nil or self.SmokeTime + 300 <= CurrentTime then
|
||||||
|
if self.SmokeColor then
|
||||||
|
self:GetCoordinate():Smoke( self.SmokeColor )
|
||||||
|
self.SmokeTime = CurrentTime
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- @param #ZONE_GOAL self
|
--- @param #ZONE_GOAL self
|
||||||
-- @param Core.Event#EVENTDATA EventData
|
-- @param Core.Event#EVENTDATA EventData Event data table.
|
||||||
function ZONE_GOAL:__Destroyed( EventData )
|
function ZONE_GOAL:__Destroyed( EventData )
|
||||||
self:F( { "EventDead", EventData } )
|
self:F( { "EventDead", EventData } )
|
||||||
|
|
||||||
self:F( { EventData.IniUnit } )
|
self:F( { EventData.IniUnit } )
|
||||||
|
|
||||||
local Vec3 = EventData.IniDCSUnit:getPosition().p
|
|
||||||
self:F( { Vec3 = Vec3 } )
|
|
||||||
|
|
||||||
if EventData.IniDCSUnit then
|
if EventData.IniDCSUnit then
|
||||||
if self:IsVec3InZone(Vec3) then
|
|
||||||
|
local Vec3 = EventData.IniDCSUnit:getPosition().p
|
||||||
|
self:F( { Vec3 = Vec3 } )
|
||||||
|
|
||||||
|
if Vec3 and self:IsVec3InZone(Vec3) then
|
||||||
|
|
||||||
local PlayerHits = _DATABASE.HITS[EventData.IniUnitName]
|
local PlayerHits = _DATABASE.HITS[EventData.IniUnitName]
|
||||||
|
|
||||||
if PlayerHits then
|
if PlayerHits then
|
||||||
|
|
||||||
for PlayerName, PlayerHit in pairs( PlayerHits.Players or {} ) do
|
for PlayerName, PlayerHit in pairs( PlayerHits.Players or {} ) do
|
||||||
self.Goal:AddPlayerContribution( PlayerName )
|
self.Goal:AddPlayerContribution( PlayerName )
|
||||||
self:DestroyedUnit( EventData.IniUnitName, PlayerName )
|
self:DestroyedUnit( EventData.IniUnitName, PlayerName )
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,11 @@
|
|||||||
do -- ZoneGoal
|
do -- ZoneGoal
|
||||||
|
|
||||||
--- @type ZONE_GOAL_COALITION
|
--- @type ZONE_GOAL_COALITION
|
||||||
|
-- @field #string ClassName Name of the Class.
|
||||||
|
-- @field #number Coalition The current coalition ID of the zone owner.
|
||||||
|
-- @field #number PreviousCoalition The previous owner of the zone.
|
||||||
|
-- @field #table UnitCategories Table of unit categories that are able to capture and hold the zone. Default is only GROUND units.
|
||||||
|
-- @field #table ObjectCategories Table of object categories that are able to hold a zone. Default is UNITS and STATICS.
|
||||||
-- @extends Functional.ZoneGoal#ZONE_GOAL
|
-- @extends Functional.ZoneGoal#ZONE_GOAL
|
||||||
|
|
||||||
|
|
||||||
@@ -37,7 +42,11 @@ do -- ZoneGoal
|
|||||||
--
|
--
|
||||||
-- @field #ZONE_GOAL_COALITION
|
-- @field #ZONE_GOAL_COALITION
|
||||||
ZONE_GOAL_COALITION = {
|
ZONE_GOAL_COALITION = {
|
||||||
ClassName = "ZONE_GOAL_COALITION",
|
ClassName = "ZONE_GOAL_COALITION",
|
||||||
|
Coalition = nil,
|
||||||
|
PreviousCoaliton = nil,
|
||||||
|
UnitCategories = nil,
|
||||||
|
ObjectCategories = nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
--- @field #table ZONE_GOAL_COALITION.States
|
--- @field #table ZONE_GOAL_COALITION.States
|
||||||
@@ -46,15 +55,26 @@ do -- ZoneGoal
|
|||||||
--- ZONE_GOAL_COALITION Constructor.
|
--- ZONE_GOAL_COALITION Constructor.
|
||||||
-- @param #ZONE_GOAL_COALITION self
|
-- @param #ZONE_GOAL_COALITION self
|
||||||
-- @param Core.Zone#ZONE Zone A @{Zone} object with the goal to be achieved.
|
-- @param Core.Zone#ZONE Zone A @{Zone} object with the goal to be achieved.
|
||||||
-- @param DCSCoalition.DCSCoalition#coalition Coalition The initial coalition owning the zone.
|
-- @param DCSCoalition.DCSCoalition#coalition Coalition The initial coalition owning the zone. Default coalition.side.NEUTRAL.
|
||||||
|
-- @param #table UnitCategories Table of unit categories. See [DCS Class Unit](https://wiki.hoggitworld.com/view/DCS_Class_Unit). Default {Unit.Category.GROUND_UNIT}.
|
||||||
-- @return #ZONE_GOAL_COALITION
|
-- @return #ZONE_GOAL_COALITION
|
||||||
function ZONE_GOAL_COALITION:New( Zone, Coalition )
|
function ZONE_GOAL_COALITION:New( Zone, Coalition, UnitCategories )
|
||||||
|
|
||||||
|
if not Zone then
|
||||||
|
BASE:E("ERROR: No Zone specified in ZONE_GOAL_COALITON!")
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Inherit ZONE_GOAL.
|
||||||
local self = BASE:Inherit( self, ZONE_GOAL:New( Zone ) ) -- #ZONE_GOAL_COALITION
|
local self = BASE:Inherit( self, ZONE_GOAL:New( Zone ) ) -- #ZONE_GOAL_COALITION
|
||||||
self:F( { Zone = Zone, Coalition = Coalition } )
|
self:F( { Zone = Zone, Coalition = Coalition } )
|
||||||
|
|
||||||
self:SetCoalition( Coalition )
|
-- Set initial owner.
|
||||||
|
self:SetCoalition( Coalition or coalition.side.NEUTRAL)
|
||||||
|
|
||||||
|
-- Set default unit and object categories for the zone scan.
|
||||||
|
self:SetUnitCategories(UnitCategories)
|
||||||
|
self:SetObjectCategories()
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
@@ -62,11 +82,43 @@ do -- ZoneGoal
|
|||||||
|
|
||||||
--- Set the owning coalition of the zone.
|
--- Set the owning coalition of the zone.
|
||||||
-- @param #ZONE_GOAL_COALITION self
|
-- @param #ZONE_GOAL_COALITION self
|
||||||
-- @param DCSCoalition.DCSCoalition#coalition Coalition
|
-- @param DCSCoalition.DCSCoalition#coalition Coalition The coalition ID, e.g. *coalition.side.RED*.
|
||||||
|
-- @return #ZONE_GOAL_COALITION
|
||||||
function ZONE_GOAL_COALITION:SetCoalition( Coalition )
|
function ZONE_GOAL_COALITION:SetCoalition( Coalition )
|
||||||
|
self.PreviousCoalition=self.Coalition or Coalition
|
||||||
self.Coalition = Coalition
|
self.Coalition = Coalition
|
||||||
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Set the owning coalition of the zone.
|
||||||
|
-- @param #ZONE_GOAL_COALITION self
|
||||||
|
-- @param #table UnitCategories Table of unit categories. See [DCS Class Unit](https://wiki.hoggitworld.com/view/DCS_Class_Unit). Default {Unit.Category.GROUND_UNIT}.
|
||||||
|
-- @return #ZONE_GOAL_COALITION
|
||||||
|
function ZONE_GOAL_COALITION:SetUnitCategories( UnitCategories )
|
||||||
|
|
||||||
|
if UnitCategories and type(UnitCategories)~="table" then
|
||||||
|
UnitCategories={UnitCategories}
|
||||||
|
end
|
||||||
|
|
||||||
|
self.UnitCategories=UnitCategories or {Unit.Category.GROUND_UNIT}
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set the owning coalition of the zone.
|
||||||
|
-- @param #ZONE_GOAL_COALITION self
|
||||||
|
-- @param #table ObjectCategories Table of unit categories. See [DCS Class Object](https://wiki.hoggitworld.com/view/DCS_Class_Object). Default {Object.Category.UNIT, Object.Category.STATIC}, i.e. all UNITS and STATICS.
|
||||||
|
-- @return #ZONE_GOAL_COALITION
|
||||||
|
function ZONE_GOAL_COALITION:SetObjectCategories( ObjectCategories )
|
||||||
|
|
||||||
|
if ObjectCategories and type(ObjectCategories)~="table" then
|
||||||
|
ObjectCategories={ObjectCategories}
|
||||||
|
end
|
||||||
|
|
||||||
|
self.ObjectCategories=ObjectCategories or {Object.Category.UNIT, Object.Category.STATIC}
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- Get the owning coalition of the zone.
|
--- Get the owning coalition of the zone.
|
||||||
-- @param #ZONE_GOAL_COALITION self
|
-- @param #ZONE_GOAL_COALITION self
|
||||||
@@ -75,37 +127,38 @@ do -- ZoneGoal
|
|||||||
return self.Coalition
|
return self.Coalition
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Get the previous coaliton, i.e. the one owning the zone before the current one.
|
||||||
|
-- @param #ZONE_GOAL_COALITION self
|
||||||
|
-- @return DCSCoalition.DCSCoalition#coalition Coalition.
|
||||||
|
function ZONE_GOAL_COALITION:GetPreviousCoalition()
|
||||||
|
return self.PreviousCoalition
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Get the owning coalition name of the zone.
|
--- Get the owning coalition name of the zone.
|
||||||
-- @param #ZONE_GOAL_COALITION self
|
-- @param #ZONE_GOAL_COALITION self
|
||||||
-- @return #string Coalition name.
|
-- @return #string Coalition name.
|
||||||
function ZONE_GOAL_COALITION:GetCoalitionName()
|
function ZONE_GOAL_COALITION:GetCoalitionName()
|
||||||
|
return UTILS.GetCoalitionName(self.Coalition)
|
||||||
if self.Coalition == coalition.side.BLUE then
|
|
||||||
return "Blue"
|
|
||||||
end
|
|
||||||
|
|
||||||
if self.Coalition == coalition.side.RED then
|
|
||||||
return "Red"
|
|
||||||
end
|
|
||||||
|
|
||||||
if self.Coalition == coalition.side.NEUTRAL then
|
|
||||||
return "Neutral"
|
|
||||||
end
|
|
||||||
|
|
||||||
return ""
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Check status Coalition ownership.
|
--- Check status Coalition ownership.
|
||||||
-- @param #ZONE_GOAL_COALITION self
|
-- @param #ZONE_GOAL_COALITION self
|
||||||
|
-- @return #ZONE_GOAL_COALITION
|
||||||
function ZONE_GOAL_COALITION:StatusZone()
|
function ZONE_GOAL_COALITION:StatusZone()
|
||||||
|
|
||||||
|
-- Get current state.
|
||||||
local State = self:GetState()
|
local State = self:GetState()
|
||||||
self:F( { State = self:GetState() } )
|
|
||||||
|
|
||||||
self:Scan( { Object.Category.UNIT, Object.Category.STATIC } )
|
-- Debug text.
|
||||||
|
local text=string.format("Zone state=%s, Owner=%s, Scanning...", State, self:GetCoalitionName())
|
||||||
|
self:F(text)
|
||||||
|
|
||||||
|
-- Scan zone.
|
||||||
|
self:Scan( self.ObjectCategories, self.UnitCategories )
|
||||||
|
|
||||||
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
_EVENTDISPATCHER = EVENT:New() -- Core.Event#EVENT
|
_EVENTDISPATCHER = EVENT:New() -- Core.Event#EVENT
|
||||||
|
|
||||||
--- Declare the timer dispatcher based on the SCHEDULEDISPATCHER class
|
--- Declare the timer dispatcher based on the SCHEDULEDISPATCHER class
|
||||||
_SCHEDULEDISPATCHER = SCHEDULEDISPATCHER:New() -- Core.Timer#SCHEDULEDISPATCHER
|
_SCHEDULEDISPATCHER = SCHEDULEDISPATCHER:New() -- Core.ScheduleDispatcher#SCHEDULEDISPATCHER
|
||||||
|
|
||||||
--- Declare the main database object, which is used internally by the MOOSE classes.
|
--- Declare the main database object, which is used internally by the MOOSE classes.
|
||||||
_DATABASE = DATABASE:New() -- Core.Database#DATABASE
|
_DATABASE = DATABASE:New() -- Core.Database#DATABASE
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
__Moose.Include( 'Scripts/Moose/Utilities/Enums.lua' )
|
__Moose.Include( 'Scripts/Moose/Utilities/Enums.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Utilities/Routines.lua' )
|
__Moose.Include( 'Scripts/Moose/Utilities/Routines.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Utilities/Utils.lua' )
|
__Moose.Include( 'Scripts/Moose/Utilities/Utils.lua' )
|
||||||
|
__Moose.Include( 'Scripts/Moose/Utilities/Profiler.lua' )
|
||||||
|
|
||||||
__Moose.Include( 'Scripts/Moose/Core/Base.lua' )
|
__Moose.Include( 'Scripts/Moose/Core/Base.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Core/UserFlag.lua' )
|
__Moose.Include( 'Scripts/Moose/Core/UserFlag.lua' )
|
||||||
@@ -24,6 +25,7 @@ __Moose.Include( 'Scripts/Moose/Core/RadioQueue.lua' )
|
|||||||
__Moose.Include( 'Scripts/Moose/Core/RadioSpeech.lua' )
|
__Moose.Include( 'Scripts/Moose/Core/RadioSpeech.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Core/Spawn.lua' )
|
__Moose.Include( 'Scripts/Moose/Core/Spawn.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Core/SpawnStatic.lua' )
|
__Moose.Include( 'Scripts/Moose/Core/SpawnStatic.lua' )
|
||||||
|
__Moose.Include( 'Scripts/Moose/Core/Timer.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Core/Goal.lua' )
|
__Moose.Include( 'Scripts/Moose/Core/Goal.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Core/Spot.lua' )
|
__Moose.Include( 'Scripts/Moose/Core/Spot.lua' )
|
||||||
|
|
||||||
@@ -37,6 +39,7 @@ __Moose.Include( 'Scripts/Moose/Wrapper/Client.lua' )
|
|||||||
__Moose.Include( 'Scripts/Moose/Wrapper/Static.lua' )
|
__Moose.Include( 'Scripts/Moose/Wrapper/Static.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Wrapper/Airbase.lua' )
|
__Moose.Include( 'Scripts/Moose/Wrapper/Airbase.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Wrapper/Scenery.lua' )
|
__Moose.Include( 'Scripts/Moose/Wrapper/Scenery.lua' )
|
||||||
|
__Moose.Include( 'Scripts/Moose/Wrapper/Marker.lua' )
|
||||||
|
|
||||||
__Moose.Include( 'Scripts/Moose/Cargo/Cargo.lua' )
|
__Moose.Include( 'Scripts/Moose/Cargo/Cargo.lua' )
|
||||||
__Moose.Include( 'Scripts/Moose/Cargo/CargoUnit.lua' )
|
__Moose.Include( 'Scripts/Moose/Cargo/CargoUnit.lua' )
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,4 @@
|
|||||||
--- **Ops** - (R2.5) - Manages aircraft CASE X recoveries for carrier operations (X=I, II, III).
|
--- **Ops** - Manages aircraft CASE X recoveries for carrier operations (X=I, II, III).
|
||||||
--
|
--
|
||||||
-- The AIRBOSS class manages recoveries of human pilots and AI aircraft on aircraft carriers.
|
-- The AIRBOSS class manages recoveries of human pilots and AI aircraft on aircraft carriers.
|
||||||
--
|
--
|
||||||
@@ -39,6 +39,7 @@
|
|||||||
-- * F-14A Tomcat (AI)
|
-- * F-14A Tomcat (AI)
|
||||||
-- * E-2D Hawkeye (AI)
|
-- * E-2D Hawkeye (AI)
|
||||||
-- * S-3B Viking & tanker version (AI)
|
-- * S-3B Viking & tanker version (AI)
|
||||||
|
-- * [C-2A Greyhound](https://forums.eagle.ru/showthread.php?t=255641) (AI)
|
||||||
--
|
--
|
||||||
-- At the moment, optimized parameters are available for the F/A-18C Hornet (Lot 20) and A-4E community mod as aircraft and the USS John C. Stennis as carrier.
|
-- At the moment, optimized parameters are available for the F/A-18C Hornet (Lot 20) and A-4E community mod as aircraft and the USS John C. Stennis as carrier.
|
||||||
--
|
--
|
||||||
@@ -1255,6 +1256,7 @@ AIRBOSS = {
|
|||||||
-- @field #string S3B Lockheed S-3B Viking.
|
-- @field #string S3B Lockheed S-3B Viking.
|
||||||
-- @field #string S3BTANKER Lockheed S-3B Viking tanker.
|
-- @field #string S3BTANKER Lockheed S-3B Viking tanker.
|
||||||
-- @field #string E2D Grumman E-2D Hawkeye AWACS.
|
-- @field #string E2D Grumman E-2D Hawkeye AWACS.
|
||||||
|
-- @field #string C2A Grumman C-2A Greyhound from Military Aircraft Mod.
|
||||||
AIRBOSS.AircraftCarrier={
|
AIRBOSS.AircraftCarrier={
|
||||||
AV8B="AV8BNA",
|
AV8B="AV8BNA",
|
||||||
HORNET="FA-18C_hornet",
|
HORNET="FA-18C_hornet",
|
||||||
@@ -1266,15 +1268,22 @@ AIRBOSS.AircraftCarrier={
|
|||||||
S3B="S-3B",
|
S3B="S-3B",
|
||||||
S3BTANKER="S-3B Tanker",
|
S3BTANKER="S-3B Tanker",
|
||||||
E2D="E-2C",
|
E2D="E-2C",
|
||||||
|
C2A="C2A_Greyhound",
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Carrier types.
|
--- Carrier types.
|
||||||
-- @type AIRBOSS.CarrierType
|
-- @type AIRBOSS.CarrierType
|
||||||
|
-- @field #string ROOSEVELT USS Theodore Roosevelt (CVN-71)
|
||||||
|
-- @field #string LINCOLN USS Abraham Lincoln (CVN-72)
|
||||||
|
-- @field #string WASHINGTON USS George Washington (CVN-73)
|
||||||
-- @field #string STENNIS USS John C. Stennis (CVN-74)
|
-- @field #string STENNIS USS John C. Stennis (CVN-74)
|
||||||
-- @field #string VINSON USS Carl Vinson (CVN-70)
|
-- @field #string VINSON USS Carl Vinson (CVN-70)
|
||||||
-- @field #string TARAWA USS Tarawa (LHA-1)
|
-- @field #string TARAWA USS Tarawa (LHA-1)
|
||||||
-- @field #string KUZNETSOV Admiral Kuznetsov (CV 1143.5)
|
-- @field #string KUZNETSOV Admiral Kuznetsov (CV 1143.5)
|
||||||
AIRBOSS.CarrierType={
|
AIRBOSS.CarrierType={
|
||||||
|
ROOSEVELT="CVN_71",
|
||||||
|
LINCOLN="CVN_72",
|
||||||
|
WASHINGTON="CVN_73",
|
||||||
STENNIS="Stennis",
|
STENNIS="Stennis",
|
||||||
VINSON="VINSON",
|
VINSON="VINSON",
|
||||||
TARAWA="LHA_Tarawa",
|
TARAWA="LHA_Tarawa",
|
||||||
@@ -1688,7 +1697,7 @@ AIRBOSS.MenuF10Root=nil
|
|||||||
|
|
||||||
--- Airboss class version.
|
--- Airboss class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
AIRBOSS.version="1.0.9"
|
AIRBOSS.version="1.1.5"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- TODO list
|
-- TODO list
|
||||||
@@ -1877,6 +1886,9 @@ function AIRBOSS:New(carriername, alias)
|
|||||||
-- Default recovery case. This sets self.defaultcase and self.case. Default Case I.
|
-- Default recovery case. This sets self.defaultcase and self.case. Default Case I.
|
||||||
self:SetRecoveryCase()
|
self:SetRecoveryCase()
|
||||||
|
|
||||||
|
-- Set time the turn starts before the window opens.
|
||||||
|
self:SetRecoveryTurnTime()
|
||||||
|
|
||||||
-- Set holding offset to 0 degrees. This set self.defaultoffset and self.holdingoffset.
|
-- Set holding offset to 0 degrees. This set self.defaultoffset and self.holdingoffset.
|
||||||
self:SetHoldingOffsetAngle()
|
self:SetHoldingOffsetAngle()
|
||||||
|
|
||||||
@@ -1923,6 +1935,12 @@ function AIRBOSS:New(carriername, alias)
|
|||||||
-- Init carrier parameters.
|
-- Init carrier parameters.
|
||||||
if self.carriertype==AIRBOSS.CarrierType.STENNIS then
|
if self.carriertype==AIRBOSS.CarrierType.STENNIS then
|
||||||
self:_InitStennis()
|
self:_InitStennis()
|
||||||
|
elseif self.carriertype==AIRBOSS.CarrierType.ROOSEVELT then
|
||||||
|
self:_InitNimitz()
|
||||||
|
elseif self.carriertype==AIRBOSS.CarrierType.LINCOLN then
|
||||||
|
self:_InitNimitz()
|
||||||
|
elseif self.carriertype==AIRBOSS.CarrierType.WASHINGTON then
|
||||||
|
self:_InitNimitz()
|
||||||
elseif self.carriertype==AIRBOSS.CarrierType.VINSON then
|
elseif self.carriertype==AIRBOSS.CarrierType.VINSON then
|
||||||
-- TODO: Carl Vinson parameters.
|
-- TODO: Carl Vinson parameters.
|
||||||
self:_InitStennis()
|
self:_InitStennis()
|
||||||
@@ -2078,6 +2096,7 @@ function AIRBOSS:New(carriername, alias)
|
|||||||
self:AddTransition("*", "RecoveryCase", "*") -- Switch to another case recovery.
|
self:AddTransition("*", "RecoveryCase", "*") -- Switch to another case recovery.
|
||||||
self:AddTransition("*", "PassingWaypoint", "*") -- Carrier is passing a waypoint.
|
self:AddTransition("*", "PassingWaypoint", "*") -- Carrier is passing a waypoint.
|
||||||
self:AddTransition("*", "LSOGrade", "*") -- LSO grade.
|
self:AddTransition("*", "LSOGrade", "*") -- LSO grade.
|
||||||
|
self:AddTransition("*", "Marshal", "*") -- A flight was send into the marshal stack.
|
||||||
self:AddTransition("*", "Save", "*") -- Save player scores to file.
|
self:AddTransition("*", "Save", "*") -- Save player scores to file.
|
||||||
self:AddTransition("*", "Stop", "Stopped") -- Stop AIRBOSS FMS.
|
self:AddTransition("*", "Stop", "Stopped") -- Stop AIRBOSS FMS.
|
||||||
|
|
||||||
@@ -2251,29 +2270,6 @@ function AIRBOSS:New(carriername, alias)
|
|||||||
-- @param #string filename (Optional) File name. Default is AIRBOSS-*ALIAS*_LSOgrades.csv.
|
-- @param #string filename (Optional) File name. Default is AIRBOSS-*ALIAS*_LSOgrades.csv.
|
||||||
|
|
||||||
|
|
||||||
--- Triggers the FSM event "LSOgrade". Called when the LSO grades a player
|
|
||||||
-- @function [parent=#AIRBOSS] LSOgrade
|
|
||||||
-- @param #AIRBOSS self
|
|
||||||
-- @param #AIRBOSS.PlayerData playerData Player Data.
|
|
||||||
-- @param #AIRBOSS.LSOgrade grade LSO grade.
|
|
||||||
|
|
||||||
--- Triggers the FSM event "LSOgrade". Delayed called when the LSO grades a player.
|
|
||||||
-- @function [parent=#AIRBOSS] __LSOgrade
|
|
||||||
-- @param #AIRBOSS self
|
|
||||||
-- @param #number delay Delay in seconds.
|
|
||||||
-- @param #AIRBOSS.PlayerData playerData Player Data.
|
|
||||||
-- @param #AIRBOSS.LSOgrade grade LSO grade.
|
|
||||||
|
|
||||||
--- On after "LSOgrade" user function. Called when the carrier passes a waypoint of its route.
|
|
||||||
-- @function [parent=#AIRBOSS] OnAfterLSOgrade
|
|
||||||
-- @param #AIRBOSS self
|
|
||||||
-- @param #string From From state.
|
|
||||||
-- @param #string Event Event.
|
|
||||||
-- @param #string To To state.
|
|
||||||
-- @param #AIRBOSS.PlayerData playerData Player Data.
|
|
||||||
-- @param #AIRBOSS.LSOgrade grade LSO grade.
|
|
||||||
|
|
||||||
|
|
||||||
--- Triggers the FSM event "LSOGrade". Called when the LSO grades a player
|
--- Triggers the FSM event "LSOGrade". Called when the LSO grades a player
|
||||||
-- @function [parent=#AIRBOSS] LSOGrade
|
-- @function [parent=#AIRBOSS] LSOGrade
|
||||||
-- @param #AIRBOSS self
|
-- @param #AIRBOSS self
|
||||||
@@ -2297,27 +2293,24 @@ function AIRBOSS:New(carriername, alias)
|
|||||||
-- @param #AIRBOSS.LSOgrade grade LSO grade.
|
-- @param #AIRBOSS.LSOgrade grade LSO grade.
|
||||||
|
|
||||||
|
|
||||||
--- Triggers the FSM event "LSOGrade". Called when the LSO grades a player
|
--- Triggers the FSM event "Marshal". Called when a flight is send to the Marshal stack.
|
||||||
-- @function [parent=#AIRBOSS] LSOGrade
|
-- @function [parent=#AIRBOSS] Marshal
|
||||||
-- @param #AIRBOSS self
|
-- @param #AIRBOSS self
|
||||||
-- @param #AIRBOSS.PlayerData playerData Player Data.
|
-- @param #AIRBOSS.FlightGroup flight The flight group data.
|
||||||
-- @param #AIRBOSS.LSOgrade grade LSO grade.
|
|
||||||
|
|
||||||
--- Triggers the FSM event "LSOGrade". Delayed called when the LSO grades a player.
|
--- Triggers the FSM event "Marshal". Delayed call when a flight is send to the Marshal stack.
|
||||||
-- @function [parent=#AIRBOSS] __LSOGrade
|
-- @function [parent=#AIRBOSS] __Marshal
|
||||||
-- @param #AIRBOSS self
|
-- @param #AIRBOSS self
|
||||||
-- @param #number delay Delay in seconds.
|
-- @param #number delay Delay in seconds.
|
||||||
-- @param #AIRBOSS.PlayerData playerData Player Data.
|
-- @param #AIRBOSS.FlightGroup flight The flight group data.
|
||||||
-- @param #AIRBOSS.LSOgrade grade LSO grade.
|
|
||||||
|
|
||||||
--- On after "LSOGrade" user function. Called when the carrier passes a waypoint of its route.
|
--- On after "Marshal" user function. Called when a flight is send to the Marshal stack.
|
||||||
-- @function [parent=#AIRBOSS] OnAfterLSOGrade
|
-- @function [parent=#AIRBOSS] OnAfterMarshal
|
||||||
-- @param #AIRBOSS self
|
-- @param #AIRBOSS self
|
||||||
-- @param #string From From state.
|
-- @param #string From From state.
|
||||||
-- @param #string Event Event.
|
-- @param #string Event Event.
|
||||||
-- @param #string To To state.
|
-- @param #string To To state.
|
||||||
-- @param #AIRBOSS.PlayerData playerData Player Data.
|
-- @param #AIRBOSS.FlightGroup flight The flight group data.
|
||||||
-- @param #AIRBOSS.LSOgrade grade LSO grade.
|
|
||||||
|
|
||||||
|
|
||||||
--- Triggers the FSM event "Stop" that stops the airboss. Event handlers are stopped.
|
--- Triggers the FSM event "Stop" that stops the airboss. Event handlers are stopped.
|
||||||
@@ -2455,6 +2448,15 @@ function AIRBOSS:AddRecoveryWindow(starttime, stoptime, case, holdingoffset, tur
|
|||||||
-- Absolute mission time in seconds.
|
-- Absolute mission time in seconds.
|
||||||
local Tnow=timer.getAbsTime()
|
local Tnow=timer.getAbsTime()
|
||||||
|
|
||||||
|
if starttime and type(starttime)=="number" then
|
||||||
|
starttime=UTILS.SecondsToClock(Tnow+starttime)
|
||||||
|
end
|
||||||
|
|
||||||
|
if stoptime and type(stoptime)=="number" then
|
||||||
|
stoptime=UTILS.SecondsToClock(Tnow+stoptime)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Input or now.
|
-- Input or now.
|
||||||
starttime=starttime or UTILS.SecondsToClock(Tnow)
|
starttime=starttime or UTILS.SecondsToClock(Tnow)
|
||||||
|
|
||||||
@@ -2620,6 +2622,15 @@ function AIRBOSS:DeleteRecoveryWindow(window, delay)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Set time before carrier turns and recovery window opens.
|
||||||
|
-- @param #AIRBOSS self
|
||||||
|
-- @param #number interval Time interval in seconds. Default 300 sec.
|
||||||
|
-- @return #AIRBOSS self
|
||||||
|
function AIRBOSS:SetRecoveryTurnTime(interval)
|
||||||
|
self.dTturn=interval or 300
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- Set time interval for updating queues and other stuff.
|
--- Set time interval for updating queues and other stuff.
|
||||||
-- @param #AIRBOSS self
|
-- @param #AIRBOSS self
|
||||||
-- @param #number interval Time interval in seconds. Default 30 sec.
|
-- @param #number interval Time interval in seconds. Default 30 sec.
|
||||||
@@ -3248,6 +3259,27 @@ function AIRBOSS:SetDebugModeOFF()
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Get next time the carrier will start recovering aircraft.
|
||||||
|
-- @param #AIRBOSS self
|
||||||
|
-- @param #boolean InSeconds If true, abs. mission time seconds is returned. Default is a clock #string.
|
||||||
|
-- @return #string Clock start (or start time in abs. seconds).
|
||||||
|
-- @return #string Clock stop (or stop time in abs. seconds).
|
||||||
|
function AIRBOSS:GetNextRecoveryTime(InSeconds)
|
||||||
|
if self.recoverywindow then
|
||||||
|
if InSeconds then
|
||||||
|
return self.recoverywindow.START, self.recoverywindow.STOP
|
||||||
|
else
|
||||||
|
return UTILS.SecondsToClock(self.recoverywindow.START), UTILS.SecondsToClock(self.recoverywindow.STOP)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if InSeconds then
|
||||||
|
return -1, -1
|
||||||
|
else
|
||||||
|
return "?", "?"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
--- Check if carrier is recovering aircraft.
|
--- Check if carrier is recovering aircraft.
|
||||||
-- @param #AIRBOSS self
|
-- @param #AIRBOSS self
|
||||||
-- @return #boolean If true, time slot for recovery is open.
|
-- @return #boolean If true, time slot for recovery is open.
|
||||||
@@ -3804,7 +3836,7 @@ function AIRBOSS:_CheckRecoveryTimes()
|
|||||||
self:RecoveryCase(nextwindow.CASE, nextwindow.OFFSET)
|
self:RecoveryCase(nextwindow.CASE, nextwindow.OFFSET)
|
||||||
|
|
||||||
-- Check if time is less than 5 minutes.
|
-- Check if time is less than 5 minutes.
|
||||||
if nextwindow.WIND and nextwindow.START-time<5*60 and not self.turnintowind then
|
if nextwindow.WIND and nextwindow.START-time<self.dTturn and not self.turnintowind then
|
||||||
|
|
||||||
-- Check that wind is blowing from a direction > 5° different from the current heading.
|
-- Check that wind is blowing from a direction > 5° different from the current heading.
|
||||||
local hdg=self:GetHeading()
|
local hdg=self:GetHeading()
|
||||||
@@ -3827,7 +3859,7 @@ function AIRBOSS:_CheckRecoveryTimes()
|
|||||||
self:T(self.lid..string.format("Heading=%03d°, Wind=%03d° %.1f kts, Delta=%03d° ==> U-turn=%s", hdg, wind,UTILS.MpsToKnots(vwind), delta, tostring(uturn)))
|
self:T(self.lid..string.format("Heading=%03d°, Wind=%03d° %.1f kts, Delta=%03d° ==> U-turn=%s", hdg, wind,UTILS.MpsToKnots(vwind), delta, tostring(uturn)))
|
||||||
|
|
||||||
-- Time into the wind 1 day or if longer recovery time + the 5 min early.
|
-- Time into the wind 1 day or if longer recovery time + the 5 min early.
|
||||||
local t=math.max(nextwindow.STOP-nextwindow.START+300, 60*60*24)
|
local t=math.max(nextwindow.STOP-nextwindow.START+self.dTturn, 60*60*24)
|
||||||
|
|
||||||
-- Recovery wind on deck in knots.
|
-- Recovery wind on deck in knots.
|
||||||
local v=UTILS.KnotsToMps(nextwindow.SPEED)
|
local v=UTILS.KnotsToMps(nextwindow.SPEED)
|
||||||
@@ -4062,7 +4094,7 @@ function AIRBOSS:onafterRecoveryUnpause(From, Event, To)
|
|||||||
self:T(self.lid..string.format("Unpausing aircraft recovery."))
|
self:T(self.lid..string.format("Unpausing aircraft recovery."))
|
||||||
|
|
||||||
-- Resume recovery.
|
-- Resume recovery.
|
||||||
self:_MarshalCallRecoveryResume()
|
self:_MarshalCallResumeRecovery()
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -4260,7 +4292,36 @@ function AIRBOSS:_InitStennis()
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Init parameters for USS Stennis carrier.
|
--- Init parameters for Nimitz class super carriers.
|
||||||
|
-- @param #AIRBOSS self
|
||||||
|
function AIRBOSS:_InitNimitz()
|
||||||
|
|
||||||
|
-- Init Stennis as default.
|
||||||
|
self:_InitStennis()
|
||||||
|
|
||||||
|
-- Carrier Parameters.
|
||||||
|
self.carrierparam.sterndist =-164
|
||||||
|
self.carrierparam.deckheight = 20
|
||||||
|
|
||||||
|
-- Total size of the carrier (approx as rectangle).
|
||||||
|
self.carrierparam.totlength=332.8 -- Wiki says 332.8 meters overall length.
|
||||||
|
self.carrierparam.totwidthport=45 -- Wiki says 76.8 meters overall beam.
|
||||||
|
self.carrierparam.totwidthstarboard=35
|
||||||
|
|
||||||
|
-- Landing runway.
|
||||||
|
self.carrierparam.rwyangle = -9
|
||||||
|
self.carrierparam.rwylength = 250
|
||||||
|
self.carrierparam.rwywidth = 25
|
||||||
|
|
||||||
|
-- Wires.
|
||||||
|
self.carrierparam.wire1 = 55 -- Distance from stern to first wire.
|
||||||
|
self.carrierparam.wire2 = 67
|
||||||
|
self.carrierparam.wire3 = 79
|
||||||
|
self.carrierparam.wire4 = 92
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Init parameters for LHA-1 Tarawa carrier.
|
||||||
-- @param #AIRBOSS self
|
-- @param #AIRBOSS self
|
||||||
function AIRBOSS:_InitTarawa()
|
function AIRBOSS:_InitTarawa()
|
||||||
|
|
||||||
@@ -5986,7 +6047,6 @@ function AIRBOSS:_ScanCarrierZone()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Find new flights that are inside CCA.
|
-- Find new flights that are inside CCA.
|
||||||
for groupname,_group in pairs(insideCCA) do
|
for groupname,_group in pairs(insideCCA) do
|
||||||
local group=_group --Wrapper.Group#GROUP
|
local group=_group --Wrapper.Group#GROUP
|
||||||
@@ -6092,7 +6152,6 @@ function AIRBOSS:_ScanCarrierZone()
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Find flights that are not in CCA.
|
-- Find flights that are not in CCA.
|
||||||
local remove={}
|
local remove={}
|
||||||
for _,_flight in pairs(self.flights) do
|
for _,_flight in pairs(self.flights) do
|
||||||
@@ -6184,6 +6243,9 @@ function AIRBOSS:_MarshalPlayer(playerData, stack)
|
|||||||
|
|
||||||
-- Set stack flag.
|
-- Set stack flag.
|
||||||
flight.flag=stack
|
flight.flag=stack
|
||||||
|
|
||||||
|
-- Trigger Marshal event.
|
||||||
|
self:Marshal(flight)
|
||||||
end
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
@@ -6441,6 +6503,9 @@ function AIRBOSS:_MarshalAI(flight, nstack, respawn)
|
|||||||
-- Route group.
|
-- Route group.
|
||||||
flight.group:Route(wp, 1)
|
flight.group:Route(wp, 1)
|
||||||
|
|
||||||
|
-- Trigger Marshal event.
|
||||||
|
self:Marshal(flight)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Tell AI to refuel. Either at the recovery tanker or at the nearest divert airfield.
|
--- Tell AI to refuel. Either at the recovery tanker or at the nearest divert airfield.
|
||||||
@@ -10261,9 +10326,12 @@ function AIRBOSS:_GetSternCoord()
|
|||||||
if self.carriertype==AIRBOSS.CarrierType.TARAWA then
|
if self.carriertype==AIRBOSS.CarrierType.TARAWA then
|
||||||
-- Tarawa: Translate 8 meters port.
|
-- Tarawa: Translate 8 meters port.
|
||||||
stern=stern:Translate(self.carrierparam.sterndist, hdg):Translate(8, FB-90)
|
stern=stern:Translate(self.carrierparam.sterndist, hdg):Translate(8, FB-90)
|
||||||
else
|
elseif self.carriertype==AIRBOSS.CarrierType.STENNIS then
|
||||||
-- Stennis: translate 7 meters starboard wrt Final bearing.
|
-- Stennis: translate 7 meters starboard wrt Final bearing.
|
||||||
stern=stern:Translate(self.carrierparam.sterndist, hdg):Translate(7, FB+90)
|
stern=stern:Translate(self.carrierparam.sterndist, hdg):Translate(7, FB+90)
|
||||||
|
else
|
||||||
|
-- Nimitz SC: translate 8 meters starboard wrt Final bearing.
|
||||||
|
stern=stern:Translate(self.carrierparam.sterndist, hdg):Translate(8.5, FB+90)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Set altitude.
|
-- Set altitude.
|
||||||
@@ -10785,53 +10853,6 @@ function AIRBOSS:_GetZoneCorridor(case, l)
|
|||||||
local zone=ZONE_POLYGON_BASE:New("CASE II/III Approach Corridor", p)
|
local zone=ZONE_POLYGON_BASE:New("CASE II/III Approach Corridor", p)
|
||||||
|
|
||||||
return zone
|
return zone
|
||||||
|
|
||||||
--[[
|
|
||||||
-- OLD
|
|
||||||
|
|
||||||
-- Angle between radial and offset in rad.
|
|
||||||
local alpha=math.rad(self.holdingoffset)
|
|
||||||
|
|
||||||
-- Some math...
|
|
||||||
local y1=d-w2
|
|
||||||
local x1=y1*math.tan(alpha)
|
|
||||||
local y2=d+w2
|
|
||||||
local x2=y2*math.tan(alpha)
|
|
||||||
local b=w2*(1/math.cos(alpha)-1)
|
|
||||||
|
|
||||||
-- This is what we need.
|
|
||||||
local P=x1+b
|
|
||||||
local Q=x2-b
|
|
||||||
|
|
||||||
-- Debug output.
|
|
||||||
self:T3(string.format("FF case %d radial = %d", case, radial))
|
|
||||||
self:T3(string.format("FF case %d offset = %d", case, offset))
|
|
||||||
self:T3(string.format("FF w = %.1f NM", w))
|
|
||||||
self:T3(string.format("FF l = %.1f NM", l))
|
|
||||||
self:T3(string.format("FF d = %.1f NM", d))
|
|
||||||
self:T3(string.format("FF y1 = %.1f NM", y1))
|
|
||||||
self:T3(string.format("FF x1 = %.1f NM", x1))
|
|
||||||
self:T3(string.format("FF y2 = %.1f NM", y2))
|
|
||||||
self:T3(string.format("FF x2 = %.1f NM", x2))
|
|
||||||
self:T3(string.format("FF b = %.1f NM", b))
|
|
||||||
self:T3(string.format("FF P = %.1f NM", P))
|
|
||||||
self:T3(string.format("FF Q = %.1f NM", Q))
|
|
||||||
|
|
||||||
-- Complicated case with an angle.
|
|
||||||
c[2]=c[1]:Translate( UTILS.NMToMeters(w2), radial-90) -- 1 Right of carrier.
|
|
||||||
c[3]=c[2]:Translate( UTILS.NMToMeters(d+dx+w2), radial) -- 13 "south" @ 1 right
|
|
||||||
c[4]=c[3]:Translate( UTILS.NMToMeters(Q), radial+90) --
|
|
||||||
c[5]=c[4]:Translate( UTILS.NMToMeters(l), offset)
|
|
||||||
c[6]=c[5]:Translate( UTILS.NMToMeters(w), offset+90) -- Back wall (angled)
|
|
||||||
c[9]=c[1]:Translate( UTILS.NMToMeters(w2), radial+90) -- 1 left of carrier.
|
|
||||||
c[8]=c[9]:Translate( UTILS.NMToMeters(d+dx-w2), radial) -- 1 left and 11 behind of carrier.
|
|
||||||
c[7]=c[8]:Translate( UTILS.NMToMeters(P), radial+90)
|
|
||||||
|
|
||||||
-- Translate these points a bit for a smoother turn.
|
|
||||||
--c[4]=c[4]:Translate(UTILS.NMToMeters(2), offset)
|
|
||||||
--c[7]=c[7]:Translate(UTILS.NMToMeters(2), offset)
|
|
||||||
]]
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -11330,20 +11351,6 @@ function AIRBOSS:_Lineup(unit, runway)
|
|||||||
---
|
---
|
||||||
local lineup=math.deg(math.atan2(z, x))
|
local lineup=math.deg(math.atan2(z, x))
|
||||||
|
|
||||||
--[[
|
|
||||||
-- Position of the aircraft in the new coordinate system.
|
|
||||||
local a={x=x, y=0, z=z}
|
|
||||||
|
|
||||||
-- Stern position in the new coordinate system, which is simply the origin.
|
|
||||||
local b={x=0, y=0, z=0}
|
|
||||||
|
|
||||||
-- Vector from plane to ref point on the boat.
|
|
||||||
local c=UTILS.VecSubstract(a, b)
|
|
||||||
|
|
||||||
-- Current line up and error wrt to final heading of the runway.
|
|
||||||
local lineup=math.deg(math.atan2(c.z, c.x))
|
|
||||||
]]
|
|
||||||
|
|
||||||
return lineup
|
return lineup
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -11962,9 +11969,13 @@ function AIRBOSS:_LSOgrade(playerData)
|
|||||||
local nS=count(G, '%(')
|
local nS=count(G, '%(')
|
||||||
local nN=N-nS-nL
|
local nN=N-nS-nL
|
||||||
|
|
||||||
|
-- Groove time 16-18 sec for a unicorn.
|
||||||
|
local Tgroove=playerData.Tgroove
|
||||||
|
local TgrooveUnicorn=Tgroove and (Tgroove>=16.0 and Tgroove<=18.0) or false
|
||||||
|
|
||||||
local grade
|
local grade
|
||||||
local points
|
local points
|
||||||
if N==0 then
|
if N==0 and TgrooveUnicorn then
|
||||||
-- No deviations, should be REALLY RARE!
|
-- No deviations, should be REALLY RARE!
|
||||||
grade="_OK_"
|
grade="_OK_"
|
||||||
points=5.0
|
points=5.0
|
||||||
@@ -12035,7 +12046,7 @@ function AIRBOSS:_LSOgrade(playerData)
|
|||||||
-----------------
|
-----------------
|
||||||
grade="OWO"
|
grade="OWO"
|
||||||
points=2.0
|
points=2.0
|
||||||
if G=="Unicorn" then
|
if N==0 then
|
||||||
G="n/a"
|
G="n/a"
|
||||||
end
|
end
|
||||||
elseif playerData.waveoff then
|
elseif playerData.waveoff then
|
||||||
@@ -13527,63 +13538,6 @@ function AIRBOSS:_InitWaypoints()
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
|
||||||
|
|
||||||
--- Patrol carrier.
|
|
||||||
-- @param #AIRBOSS self
|
|
||||||
-- @param #number n Current waypoint.
|
|
||||||
-- @return #AIRBOSS self
|
|
||||||
function AIRBOSS:_PatrolRoute(n)
|
|
||||||
|
|
||||||
-- Get carrier group.
|
|
||||||
local CarrierGroup=self.carrier:GetGroup()
|
|
||||||
|
|
||||||
-- Waypoints of group.
|
|
||||||
local Waypoints = CarrierGroup:GetTemplateRoutePoints()
|
|
||||||
|
|
||||||
-- Loop over waypoints.
|
|
||||||
for n=1,#Waypoints do
|
|
||||||
|
|
||||||
-- Passing waypoint taskfunction
|
|
||||||
local TaskPassingWP=CarrierGroup:TaskFunction("AIRBOSS._PassingWaypoint", self, n, #Waypoints)
|
|
||||||
|
|
||||||
-- Call task function when carrier arrives at waypoint.
|
|
||||||
CarrierGroup:SetTaskWaypoint(Waypoints[n], TaskPassingWP)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Init array.
|
|
||||||
self.waypoints={}
|
|
||||||
|
|
||||||
-- Set waypoint table.
|
|
||||||
for i,point in ipairs(Waypoints) do
|
|
||||||
|
|
||||||
-- Coordinate of the waypoint
|
|
||||||
local coord=COORDINATE:New(point.x, point.alt, point.y)
|
|
||||||
|
|
||||||
-- Set velocity of the coordinate.
|
|
||||||
coord:SetVelocity(point.speed)
|
|
||||||
|
|
||||||
-- Add to table.
|
|
||||||
table.insert(self.waypoints, coord)
|
|
||||||
|
|
||||||
-- Debug info.
|
|
||||||
if self.Debug then
|
|
||||||
coord:MarkToAll(string.format("Carrier Waypoint %d, Speed=%.1f knots", i, UTILS.MpsToKnots(point.speed)))
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Current waypoint is 1.
|
|
||||||
self.currentwp=n or 1
|
|
||||||
|
|
||||||
-- Route carrier group.
|
|
||||||
CarrierGroup:Route(Waypoints)
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
]]
|
|
||||||
|
|
||||||
--- Patrol carrier.
|
--- Patrol carrier.
|
||||||
-- @param #AIRBOSS self
|
-- @param #AIRBOSS self
|
||||||
-- @param #number n Next waypoint number.
|
-- @param #number n Next waypoint number.
|
||||||
@@ -15544,7 +15498,7 @@ end
|
|||||||
function AIRBOSS:_MarshalCallRecoveryStart(case)
|
function AIRBOSS:_MarshalCallRecoveryStart(case)
|
||||||
|
|
||||||
-- Marshal radial.
|
-- Marshal radial.
|
||||||
local radial=self:GetRadial(case, true, true, true)
|
local radial=self:GetRadial(case, true, true, false)
|
||||||
|
|
||||||
-- Debug output.
|
-- Debug output.
|
||||||
local text=string.format("Starting aircraft recovery Case %d ops.", case)
|
local text=string.format("Starting aircraft recovery Case %d ops.", case)
|
||||||
@@ -17013,7 +16967,7 @@ function AIRBOSS:_DisplayCarrierInfo(_unitname)
|
|||||||
if self.case==1 then
|
if self.case==1 then
|
||||||
text=text..string.format("Case %d recovery ops\n", self.case)
|
text=text..string.format("Case %d recovery ops\n", self.case)
|
||||||
else
|
else
|
||||||
local radial=self:GetRadial(self.case, true, true, true)
|
local radial=self:GetRadial(self.case, true, true, false)
|
||||||
text=text..string.format("Case %d recovery ops\nMarshal radial %03d°\n", self.case, radial)
|
text=text..string.format("Case %d recovery ops\nMarshal radial %03d°\n", self.case, radial)
|
||||||
end
|
end
|
||||||
text=text..string.format("BRC %03d° - FB %03d°\n", self:GetBRC(), self:GetFinalBearing(true))
|
text=text..string.format("BRC %03d° - FB %03d°\n", self:GetBRC(), self:GetFinalBearing(true))
|
||||||
@@ -17687,7 +17641,8 @@ function AIRBOSS:_SaveTrapSheet(playerData, grade)
|
|||||||
if self.trapprefix then
|
if self.trapprefix then
|
||||||
filename=string.format("%s_%s-%04d.csv", self.trapprefix, playerData.actype, i)
|
filename=string.format("%s_%s-%04d.csv", self.trapprefix, playerData.actype, i)
|
||||||
else
|
else
|
||||||
filename=string.format("AIRBOSS-%s_Trapsheet-%s_%s-%04d.csv", self.alias, playerData.name, playerData.actype, i)
|
local name=UTILS.ReplaceIllegalCharacters(playerData.name, "_")
|
||||||
|
filename=string.format("AIRBOSS-%s_Trapsheet-%s_%s-%04d.csv", self.alias, name, playerData.actype, i)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Set path.
|
-- Set path.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
--- **Ops** - (R2.5) - Recovery tanker for carrier operations.
|
--- **Ops** - Recovery tanker for carrier operations.
|
||||||
--
|
--
|
||||||
-- Tanker aircraft flying a racetrack pattern overhead an aircraft carrier.
|
-- Tanker aircraft flying a racetrack pattern overhead an aircraft carrier.
|
||||||
--
|
--
|
||||||
@@ -62,6 +62,7 @@
|
|||||||
-- @field #string modex Tail number of the tanker.
|
-- @field #string modex Tail number of the tanker.
|
||||||
-- @field #boolean eplrs If true, enable data link, e.g. if used as AWACS.
|
-- @field #boolean eplrs If true, enable data link, e.g. if used as AWACS.
|
||||||
-- @field #boolean recovery If true, tanker will recover using the AIRBOSS marshal pattern.
|
-- @field #boolean recovery If true, tanker will recover using the AIRBOSS marshal pattern.
|
||||||
|
-- @field #number terminaltype Terminal type of used parking spots on airbases.
|
||||||
-- @extends Core.Fsm#FSM
|
-- @extends Core.Fsm#FSM
|
||||||
|
|
||||||
--- Recovery Tanker.
|
--- Recovery Tanker.
|
||||||
@@ -298,6 +299,7 @@ RECOVERYTANKER = {
|
|||||||
modex = nil,
|
modex = nil,
|
||||||
eplrs = nil,
|
eplrs = nil,
|
||||||
recovery = nil,
|
recovery = nil,
|
||||||
|
terminaltype = nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Unique ID (global).
|
--- Unique ID (global).
|
||||||
@@ -306,7 +308,7 @@ _RECOVERYTANKERID=0
|
|||||||
|
|
||||||
--- Class version.
|
--- Class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
RECOVERYTANKER.version="1.0.8"
|
RECOVERYTANKER.version="1.0.9"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- TODO list
|
-- TODO list
|
||||||
@@ -381,6 +383,7 @@ function RECOVERYTANKER:New(carrierunit, tankergroupname)
|
|||||||
self:SetPatternUpdateInterval()
|
self:SetPatternUpdateInterval()
|
||||||
self:SetAWACS(false)
|
self:SetAWACS(false)
|
||||||
self:SetRecoveryAirboss(false)
|
self:SetRecoveryAirboss(false)
|
||||||
|
self.terminaltype=AIRBASE.TerminalType.OpenMedOrBig
|
||||||
|
|
||||||
-- Debug trace.
|
-- Debug trace.
|
||||||
if false then
|
if false then
|
||||||
@@ -615,8 +618,9 @@ end
|
|||||||
--- Set home airbase of the tanker. This is the airbase where the tanker will go when it is out of fuel.
|
--- Set home airbase of the tanker. This is the airbase where the tanker will go when it is out of fuel.
|
||||||
-- @param #RECOVERYTANKER self
|
-- @param #RECOVERYTANKER self
|
||||||
-- @param Wrapper.Airbase#AIRBASE airbase The home airbase. Can be the airbase name or a Moose AIRBASE object.
|
-- @param Wrapper.Airbase#AIRBASE airbase The home airbase. Can be the airbase name or a Moose AIRBASE object.
|
||||||
|
-- @param #number terminaltype (Optional) The terminal type of parking spots used for spawning at airbases. Default AIRBASE.TerminalType.OpenMedOrBig.
|
||||||
-- @return #RECOVERYTANKER self
|
-- @return #RECOVERYTANKER self
|
||||||
function RECOVERYTANKER:SetHomeBase(airbase)
|
function RECOVERYTANKER:SetHomeBase(airbase, terminaltype)
|
||||||
if type(airbase)=="string" then
|
if type(airbase)=="string" then
|
||||||
self.airbase=AIRBASE:FindByName(airbase)
|
self.airbase=AIRBASE:FindByName(airbase)
|
||||||
else
|
else
|
||||||
@@ -625,6 +629,9 @@ function RECOVERYTANKER:SetHomeBase(airbase)
|
|||||||
if not self.airbase then
|
if not self.airbase then
|
||||||
self:E(self.lid.."ERROR: Airbase is nil!")
|
self:E(self.lid.."ERROR: Airbase is nil!")
|
||||||
end
|
end
|
||||||
|
if terminaltype then
|
||||||
|
self.terminaltype=terminaltype
|
||||||
|
end
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -937,7 +944,7 @@ function RECOVERYTANKER:onafterStart(From, Event, To)
|
|||||||
else
|
else
|
||||||
|
|
||||||
-- Spawn tanker at airbase.
|
-- Spawn tanker at airbase.
|
||||||
self.tanker=Spawn:SpawnAtAirbase(self.airbase, self.takeoff, nil, AIRBASE.TerminalType.OpenMedOrBig)
|
self.tanker=Spawn:SpawnAtAirbase(self.airbase, self.takeoff, nil, self.terminaltype)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1338,7 +1345,6 @@ function RECOVERYTANKER:OnEventEngineShutdown(EventData)
|
|||||||
group:InitModex(self.modex)
|
group:InitModex(self.modex)
|
||||||
|
|
||||||
-- Respawn tanker. Delaying respawn due to DCS bug https://github.com/FlightControl-Master/MOOSE/issues/1076
|
-- Respawn tanker. Delaying respawn due to DCS bug https://github.com/FlightControl-Master/MOOSE/issues/1076
|
||||||
--SCHEDULER:New(nil , group.RespawnAtCurrentAirbase, {group}, 1)
|
|
||||||
self:ScheduleOnce(1, GROUP.RespawnAtCurrentAirbase, group)
|
self:ScheduleOnce(1, GROUP.RespawnAtCurrentAirbase, group)
|
||||||
|
|
||||||
-- Create tanker beacon and activate TACAN.
|
-- Create tanker beacon and activate TACAN.
|
||||||
@@ -1357,7 +1363,6 @@ function RECOVERYTANKER:OnEventEngineShutdown(EventData)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Initial route.
|
-- Initial route.
|
||||||
--SCHEDULER:New(nil, self._InitRoute, {self, -self.distStern+UTILS.NMToMeters(3)}, 2)
|
|
||||||
self:ScheduleOnce(2, RECOVERYTANKER._InitRoute, self, -self.distStern+UTILS.NMToMeters(3))
|
self:ScheduleOnce(2, RECOVERYTANKER._InitRoute, self, -self.distStern+UTILS.NMToMeters(3))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
--- **Ops** - (R2.5) - Rescue helicopter for carrier operations.
|
--- **Ops** - Rescue helicopter for carrier operations.
|
||||||
--
|
--
|
||||||
-- Recue helicopter for carrier operations.
|
-- Recue helicopter for carrier operations.
|
||||||
--
|
--
|
||||||
@@ -237,7 +237,7 @@ _RESCUEHELOID=0
|
|||||||
|
|
||||||
--- Class version.
|
--- Class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
RESCUEHELO.version="1.0.9"
|
RESCUEHELO.version="1.1.0"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- TODO list
|
-- TODO list
|
||||||
@@ -902,7 +902,7 @@ function RESCUEHELO:onafterStart(From, Event, To)
|
|||||||
else
|
else
|
||||||
|
|
||||||
-- Check if an uncontrolled helo group was requested.
|
-- Check if an uncontrolled helo group was requested.
|
||||||
if self.useuncontrolled then
|
if self.uncontrolledac then
|
||||||
|
|
||||||
-- Use an uncontrolled aircraft group.
|
-- Use an uncontrolled aircraft group.
|
||||||
self.helo=GROUP:FindByName(self.helogroupname)
|
self.helo=GROUP:FindByName(self.helogroupname)
|
||||||
|
|||||||
@@ -293,6 +293,8 @@ do -- TASK_A2A
|
|||||||
--- 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 )
|
||||||
|
|
||||||
local Coordinate = self.TaskInfo:GetData( "Coordinate" )
|
local Coordinate = self.TaskInfo:GetData( "Coordinate" )
|
||||||
local Distance = ReportGroup:GetCoordinate():Get2DDistance( Coordinate )
|
local Distance = ReportGroup:GetCoordinate():Get2DDistance( Coordinate )
|
||||||
|
|
||||||
|
|||||||
@@ -295,6 +295,8 @@ do -- TASK_A2G
|
|||||||
--- 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 )
|
||||||
|
|
||||||
local Coordinate = self.TaskInfo:GetData( "Coordinate" )
|
local Coordinate = self.TaskInfo:GetData( "Coordinate" )
|
||||||
local Distance = ReportGroup:GetCoordinate():Get2DDistance( Coordinate )
|
local Distance = ReportGroup:GetCoordinate():Get2DDistance( Coordinate )
|
||||||
|
|
||||||
|
|||||||
@@ -55,7 +55,7 @@
|
|||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- @module Tasking.Task_Zone_Capture_Dispatcher
|
-- @module Tasking.Task_Zone_Capture_Dispatcher
|
||||||
-- @image Task_Zone_Capture_Dispatcher.JPG
|
-- @image MOOSE.JPG
|
||||||
|
|
||||||
do -- TASK_CAPTURE_DISPATCHER
|
do -- TASK_CAPTURE_DISPATCHER
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,313 @@
|
|||||||
|
--- **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.
|
||||||
|
--
|
||||||
|
-- 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
|
||||||
|
-- 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
|
||||||
|
-- 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.
|
||||||
|
--
|
||||||
|
-- Other Moose classe also have enumerators. For example, the AIRBASE class has enumerators for airbase names.
|
||||||
|
--
|
||||||
|
-- @module ENUMS
|
||||||
|
-- @image MOOSE.JPG
|
||||||
|
|
||||||
|
--- [DCS Enum world](https://wiki.hoggitworld.com/view/DCS_enum_world)
|
||||||
|
-- @type ENUMS
|
||||||
|
|
||||||
|
--- Because ENUMS are just better practice.
|
||||||
|
--
|
||||||
|
-- The ENUMS class adds some handy variables, which help you to make your code better and more general.
|
||||||
|
--
|
||||||
|
-- @field #ENUMS
|
||||||
ENUMS = {}
|
ENUMS = {}
|
||||||
|
|
||||||
|
--- Rules of Engagement.
|
||||||
|
-- @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 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 ReturnFire AI will only engage threats that shoot first.
|
||||||
|
-- @field #number WeaponHold AI will hold fire under all circumstances.
|
||||||
ENUMS.ROE = {
|
ENUMS.ROE = {
|
||||||
HoldFire = 1,
|
WeaponFree=0,
|
||||||
ReturnFire = 2,
|
OpenFireWeaponFree=1,
|
||||||
OpenFire = 3,
|
OpenFire=2,
|
||||||
WeaponFree = 4
|
ReturnFire=3,
|
||||||
|
WeaponHold=4,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
--- Reaction On Threat.
|
||||||
|
-- @type ENUMS.ROT
|
||||||
|
-- @field #number NoReaction No defensive actions will take place to counter threats.
|
||||||
|
-- @field #number PassiveDefense AI will use jammers and other countermeasures in an attempt to defeat the threat. AI will not attempt a maneuver to defeat a threat.
|
||||||
|
-- @field #number EvadeFire AI will react by performing defensive maneuvers against incoming threats. AI will also use passive defense.
|
||||||
|
-- @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.
|
||||||
ENUMS.ROT = {
|
ENUMS.ROT = {
|
||||||
NoReaction = 1,
|
NoReaction=0,
|
||||||
PassiveDefense = 2,
|
PassiveDefense=1,
|
||||||
EvadeFire = 3,
|
EvadeFire=2,
|
||||||
Vertical = 4
|
BypassAndEscape=3,
|
||||||
|
AllowAbortMission=4,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
--- Alarm state.
|
||||||
|
-- @type ENUMS.AlarmState
|
||||||
|
-- @field #number Auto AI will automatically switch alarm states based on the presence of threats. The AI kind of cheats in this regard.
|
||||||
|
-- @field #number Green Group is not combat ready. Sensors are stowed if possible.
|
||||||
|
-- @field #number Red Group is combat ready and actively searching for targets. Some groups like infantry will not move in this state.
|
||||||
|
ENUMS.AlarmState = {
|
||||||
|
Auto=0,
|
||||||
|
Green=1,
|
||||||
|
Red=2,
|
||||||
|
}
|
||||||
|
|
||||||
|
--- Weapon types. See the [Weapon Flag](https://wiki.hoggitworld.com/view/DCS_enum_weapon_flag) enumerotor on hoggit wiki.
|
||||||
|
-- @type ENUMS.WeaponFlag
|
||||||
|
ENUMS.WeaponFlag={
|
||||||
|
-- Bombs
|
||||||
|
LGB = 2,
|
||||||
|
TvGB = 4,
|
||||||
|
SNSGB = 8,
|
||||||
|
HEBomb = 16,
|
||||||
|
Penetrator = 32,
|
||||||
|
NapalmBomb = 64,
|
||||||
|
FAEBomb = 128,
|
||||||
|
ClusterBomb = 256,
|
||||||
|
Dispencer = 512,
|
||||||
|
CandleBomb = 1024,
|
||||||
|
ParachuteBomb = 2147483648,
|
||||||
|
-- Rockets
|
||||||
|
LightRocket = 2048,
|
||||||
|
MarkerRocket = 4096,
|
||||||
|
CandleRocket = 8192,
|
||||||
|
HeavyRocket = 16384,
|
||||||
|
-- Air-To-Surface Missiles
|
||||||
|
AntiRadarMissile = 32768,
|
||||||
|
AntiShipMissile = 65536,
|
||||||
|
AntiTankMissile = 131072,
|
||||||
|
FireAndForgetASM = 262144,
|
||||||
|
LaserASM = 524288,
|
||||||
|
TeleASM = 1048576,
|
||||||
|
CruiseMissile = 2097152,
|
||||||
|
AntiRadarMissile2 = 1073741824,
|
||||||
|
-- Air-To-Air Missiles
|
||||||
|
SRAM = 4194304,
|
||||||
|
MRAAM = 8388608,
|
||||||
|
LRAAM = 16777216,
|
||||||
|
IR_AAM = 33554432,
|
||||||
|
SAR_AAM = 67108864,
|
||||||
|
AR_AAM = 134217728,
|
||||||
|
--- Guns
|
||||||
|
GunPod = 268435456,
|
||||||
|
BuiltInCannon = 536870912,
|
||||||
|
---
|
||||||
|
-- Combinations
|
||||||
|
--
|
||||||
|
-- Bombs
|
||||||
|
GuidedBomb = 14, -- (LGB + TvGB + SNSGB)
|
||||||
|
AnyUnguidedBomb = 2147485680, -- (HeBomb + Penetrator + NapalmBomb + FAEBomb + ClusterBomb + Dispencer + CandleBomb + ParachuteBomb)
|
||||||
|
AnyBomb = 2147485694, -- (GuidedBomb + AnyUnguidedBomb)
|
||||||
|
--- Rockets
|
||||||
|
AnyRocket = 30720, -- LightRocket + MarkerRocket + CandleRocket + HeavyRocket
|
||||||
|
--- Air-To-Surface Missiles
|
||||||
|
GuidedASM = 1572864, -- (LaserASM + TeleASM)
|
||||||
|
TacticalASM = 1835008, -- (GuidedASM + FireAndForgetASM)
|
||||||
|
AnyASM = 4161536, -- (AntiRadarMissile + AntiShipMissile + AntiTankMissile + FireAndForgetASM + GuidedASM + CruiseMissile)
|
||||||
|
AnyASM2 = 1077903360, -- 4161536+1073741824,
|
||||||
|
--- Air-To-Air Missiles
|
||||||
|
AnyAAM = 264241152, -- IR_AAM + SAR_AAM + AR_AAM + SRAAM + MRAAM + LRAAM
|
||||||
|
AnyAutonomousMissile = 36012032, -- IR_AAM + AntiRadarMissile + AntiShipMissile + FireAndForgetASM + CruiseMissile
|
||||||
|
AnyMissile = 268402688, -- AnyASM + AnyAAM
|
||||||
|
--- Guns
|
||||||
|
Cannons = 805306368, -- GUN_POD + BuiltInCannon
|
||||||
|
---
|
||||||
|
-- Even More Genral
|
||||||
|
Auto = 3221225470, -- Any Weapon (AnyBomb + AnyRocket + AnyMissile + Cannons)
|
||||||
|
AutoDCS = 1073741822, -- Something if often see
|
||||||
|
AnyAG = 2956984318, -- Any Air-To-Ground Weapon
|
||||||
|
AnyAA = 264241152, -- Any Air-To-Air Weapon
|
||||||
|
AnyUnguided = 2952822768, -- Any Unguided Weapon
|
||||||
|
AnyGuided = 268402702, -- Any Guided Weapon
|
||||||
|
}
|
||||||
|
|
||||||
|
--- Mission tasks.
|
||||||
|
-- @type ENUMS.MissionTask
|
||||||
|
-- @field #string NOTHING No special task. Group can perform the minimal tasks: Orbit, Refuelling, Follow and Aerobatics.
|
||||||
|
-- @field #string AFAC Forward Air Controller Air. Can perform the tasks: Attack Group, Attack Unit, FAC assign group, Bombing, Attack Map Object.
|
||||||
|
-- @field #string ANTISHIPSTRIKE Naval ops. Can perform the tasks: Attack Group, Attack Unit.
|
||||||
|
-- @field #string AWACS AWACS.
|
||||||
|
-- @field #string CAP Combat Air Patrol.
|
||||||
|
-- @field #string CAS Close Air Support.
|
||||||
|
-- @field #string ESCORT Escort another group.
|
||||||
|
-- @field #string FIGHTERSWEEP Fighter sweep.
|
||||||
|
-- @field #string GROUNDATTACK Ground attack.
|
||||||
|
-- @field #string INTERCEPT Intercept.
|
||||||
|
-- @field #string PINPOINTSTRIKE Pinpoint strike.
|
||||||
|
-- @field #string RECONNAISSANCE Reconnaissance mission.
|
||||||
|
-- @field #string REFUELING Refueling mission.
|
||||||
|
-- @field #string RUNWAYATTACK Attack the runway of an airdrome.
|
||||||
|
-- @field #string SEAD Suppression of Enemy Air Defenses.
|
||||||
|
-- @field #string TRANSPORT Troop transport.
|
||||||
|
ENUMS.MissionTask={
|
||||||
|
NOTHING="Nothing",
|
||||||
|
AFAC="AFAC",
|
||||||
|
ANTISHIPSTRIKE="Antiship Strike",
|
||||||
|
AWACS="AWACS",
|
||||||
|
CAP="CAP",
|
||||||
|
CAS="CAS",
|
||||||
|
ESCORT="Escort",
|
||||||
|
FIGHTERSWEEP="Fighter Sweep",
|
||||||
|
GROUNDATTACK="Ground Attack",
|
||||||
|
INTERCEPT="Intercept",
|
||||||
|
PINPOINTSTRIKE="Pinpoint Strike",
|
||||||
|
RECONNAISSANCE="Reconnaissance",
|
||||||
|
REFUELING="Refueling",
|
||||||
|
RUNWAYATTACK="Runway Attack",
|
||||||
|
SEAD="SEAD",
|
||||||
|
TRANSPORT="Transport",
|
||||||
|
}
|
||||||
|
|
||||||
|
--- Formations (new). See the [Formations](https://wiki.hoggitworld.com/view/DCS_enum_formation) on hoggit wiki.
|
||||||
|
-- @type ENUMS.Formation
|
||||||
|
ENUMS.Formation={}
|
||||||
|
ENUMS.Formation.FixedWing={}
|
||||||
|
ENUMS.Formation.FixedWing.LineAbreast={}
|
||||||
|
ENUMS.Formation.FixedWing.LineAbreast.Close = 65537
|
||||||
|
ENUMS.Formation.FixedWing.LineAbreast.Open = 65538
|
||||||
|
ENUMS.Formation.FixedWing.LineAbreast.Group = 65539
|
||||||
|
ENUMS.Formation.FixedWing.Trail={}
|
||||||
|
ENUMS.Formation.FixedWing.Trail.Close = 131073
|
||||||
|
ENUMS.Formation.FixedWing.Trail.Open = 131074
|
||||||
|
ENUMS.Formation.FixedWing.Trail.Group = 131075
|
||||||
|
ENUMS.Formation.FixedWing.Wedge={}
|
||||||
|
ENUMS.Formation.FixedWing.Wedge.Close = 196609
|
||||||
|
ENUMS.Formation.FixedWing.Wedge.Open = 196610
|
||||||
|
ENUMS.Formation.FixedWing.Wedge.Group = 196611
|
||||||
|
ENUMS.Formation.FixedWing.EchelonRight={}
|
||||||
|
ENUMS.Formation.FixedWing.EchelonRight.Close = 262145
|
||||||
|
ENUMS.Formation.FixedWing.EchelonRight.Open = 262146
|
||||||
|
ENUMS.Formation.FixedWing.EchelonRight.Group = 262147
|
||||||
|
ENUMS.Formation.FixedWing.EchelonLeft={}
|
||||||
|
ENUMS.Formation.FixedWing.EchelonLeft.Close = 327681
|
||||||
|
ENUMS.Formation.FixedWing.EchelonLeft.Open = 327682
|
||||||
|
ENUMS.Formation.FixedWing.EchelonLeft.Group = 327683
|
||||||
|
ENUMS.Formation.FixedWing.FingerFour={}
|
||||||
|
ENUMS.Formation.FixedWing.FingerFour.Close = 393217
|
||||||
|
ENUMS.Formation.FixedWing.FingerFour.Open = 393218
|
||||||
|
ENUMS.Formation.FixedWing.FingerFour.Group = 393219
|
||||||
|
ENUMS.Formation.FixedWing.Spread={}
|
||||||
|
ENUMS.Formation.FixedWing.Spread.Close = 458753
|
||||||
|
ENUMS.Formation.FixedWing.Spread.Open = 458754
|
||||||
|
ENUMS.Formation.FixedWing.Spread.Group = 458755
|
||||||
|
ENUMS.Formation.FixedWing.BomberElement={}
|
||||||
|
ENUMS.Formation.FixedWing.BomberElement.Close = 786433
|
||||||
|
ENUMS.Formation.FixedWing.BomberElement.Open = 786434
|
||||||
|
ENUMS.Formation.FixedWing.BomberElement.Group = 786435
|
||||||
|
ENUMS.Formation.FixedWing.BomberElementHeight={}
|
||||||
|
ENUMS.Formation.FixedWing.BomberElementHeight.Close = 851968
|
||||||
|
ENUMS.Formation.FixedWing.FighterVic={}
|
||||||
|
ENUMS.Formation.FixedWing.FighterVic.Close = 917505
|
||||||
|
ENUMS.Formation.FixedWing.FighterVic.Open = 917506
|
||||||
|
ENUMS.Formation.RotaryWing={}
|
||||||
|
ENUMS.Formation.RotaryWing.Column={}
|
||||||
|
ENUMS.Formation.RotaryWing.Column.D70=720896
|
||||||
|
ENUMS.Formation.RotaryWing.Wedge={}
|
||||||
|
ENUMS.Formation.RotaryWing.Wedge.D70=8
|
||||||
|
ENUMS.Formation.RotaryWing.FrontRight={}
|
||||||
|
ENUMS.Formation.RotaryWing.FrontRight.D300=655361
|
||||||
|
ENUMS.Formation.RotaryWing.FrontRight.D600=655362
|
||||||
|
ENUMS.Formation.RotaryWing.FrontLeft={}
|
||||||
|
ENUMS.Formation.RotaryWing.FrontLeft.D300=655617
|
||||||
|
ENUMS.Formation.RotaryWing.FrontLeft.D600=655618
|
||||||
|
ENUMS.Formation.RotaryWing.EchelonRight={}
|
||||||
|
ENUMS.Formation.RotaryWing.EchelonRight.D70 =589825
|
||||||
|
ENUMS.Formation.RotaryWing.EchelonRight.D300=589826
|
||||||
|
ENUMS.Formation.RotaryWing.EchelonRight.D600=589827
|
||||||
|
ENUMS.Formation.RotaryWing.EchelonLeft={}
|
||||||
|
ENUMS.Formation.RotaryWing.EchelonLeft.D70 =590081
|
||||||
|
ENUMS.Formation.RotaryWing.EchelonLeft.D300=590082
|
||||||
|
ENUMS.Formation.RotaryWing.EchelonLeft.D600=590083
|
||||||
|
ENUMS.Formation.Vehicle={}
|
||||||
|
ENUMS.Formation.Vehicle.Vee="Vee"
|
||||||
|
ENUMS.Formation.Vehicle.EchelonRight="EchelonR"
|
||||||
|
ENUMS.Formation.Vehicle.OffRoad="Off Road"
|
||||||
|
ENUMS.Formation.Vehicle.Rank="Rank"
|
||||||
|
ENUMS.Formation.Vehicle.EchelonLeft="EchelonL"
|
||||||
|
ENUMS.Formation.Vehicle.OnRoad="On Road"
|
||||||
|
ENUMS.Formation.Vehicle.Cone="Cone"
|
||||||
|
ENUMS.Formation.Vehicle.Diamond="Diamond"
|
||||||
|
|
||||||
|
--- Formations (old). The old format is a simplified version of the new formation enums, which allow more sophisticated settings.
|
||||||
|
-- See the [Formations](https://wiki.hoggitworld.com/view/DCS_enum_formation) on hoggit wiki.
|
||||||
|
-- @type ENUMS.FormationOld
|
||||||
|
ENUMS.FormationOld={}
|
||||||
|
ENUMS.FormationOld.FixedWing={}
|
||||||
|
ENUMS.FormationOld.FixedWing.LineAbreast=1
|
||||||
|
ENUMS.FormationOld.FixedWing.Trail=2
|
||||||
|
ENUMS.FormationOld.FixedWing.Wedge=3
|
||||||
|
ENUMS.FormationOld.FixedWing.EchelonRight=4
|
||||||
|
ENUMS.FormationOld.FixedWing.EchelonLeft=5
|
||||||
|
ENUMS.FormationOld.FixedWing.FingerFour=6
|
||||||
|
ENUMS.FormationOld.FixedWing.SpreadFour=7
|
||||||
|
ENUMS.FormationOld.FixedWing.BomberElement=12
|
||||||
|
ENUMS.FormationOld.FixedWing.BomberElementHeight=13
|
||||||
|
ENUMS.FormationOld.FixedWing.FighterVic=14
|
||||||
|
ENUMS.FormationOld.RotaryWing={}
|
||||||
|
ENUMS.FormationOld.RotaryWing.Wedge=8
|
||||||
|
ENUMS.FormationOld.RotaryWing.Echelon=9
|
||||||
|
ENUMS.FormationOld.RotaryWing.Front=10
|
||||||
|
ENUMS.FormationOld.RotaryWing.Column=11
|
||||||
|
|
||||||
|
|
||||||
|
--- Morse Code. See the [Wikipedia](https://en.wikipedia.org/wiki/Morse_code).
|
||||||
|
--
|
||||||
|
-- * Short pulse "*"
|
||||||
|
-- * Long pulse "-"
|
||||||
|
--
|
||||||
|
-- Pulses are separated by a blank character " ".
|
||||||
|
--
|
||||||
|
-- @type ENUMS.Morse
|
||||||
|
ENUMS.Morse={}
|
||||||
|
ENUMS.Morse.A="* -"
|
||||||
|
ENUMS.Morse.B="- * * *"
|
||||||
|
ENUMS.Morse.C="- * - *"
|
||||||
|
ENUMS.Morse.D="- * *"
|
||||||
|
ENUMS.Morse.E="*"
|
||||||
|
ENUMS.Morse.F="* * - *"
|
||||||
|
ENUMS.Morse.G="- - *"
|
||||||
|
ENUMS.Morse.H="* * * *"
|
||||||
|
ENUMS.Morse.I="* *"
|
||||||
|
ENUMS.Morse.J="* - - -"
|
||||||
|
ENUMS.Morse.K="- * -"
|
||||||
|
ENUMS.Morse.L="* - * *"
|
||||||
|
ENUMS.Morse.M="- -"
|
||||||
|
ENUMS.Morse.N="- *"
|
||||||
|
ENUMS.Morse.O="- - -"
|
||||||
|
ENUMS.Morse.P="* - - *"
|
||||||
|
ENUMS.Morse.Q="- - * -"
|
||||||
|
ENUMS.Morse.R="* - *"
|
||||||
|
ENUMS.Morse.S="* * *"
|
||||||
|
ENUMS.Morse.T="-"
|
||||||
|
ENUMS.Morse.U="* * -"
|
||||||
|
ENUMS.Morse.V="* * * -"
|
||||||
|
ENUMS.Morse.W="* - -"
|
||||||
|
ENUMS.Morse.X="- * * -"
|
||||||
|
ENUMS.Morse.Y="- * - -"
|
||||||
|
ENUMS.Morse.Z="- - * *"
|
||||||
|
ENUMS.Morse.N1="* - - - -"
|
||||||
|
ENUMS.Morse.N2="* * - - -"
|
||||||
|
ENUMS.Morse.N3="* * * - -"
|
||||||
|
ENUMS.Morse.N4="* * * * -"
|
||||||
|
ENUMS.Morse.N5="* * * * *"
|
||||||
|
ENUMS.Morse.N6="- * * * *"
|
||||||
|
ENUMS.Morse.N7="- - * * *"
|
||||||
|
ENUMS.Morse.N8="- - - * *"
|
||||||
|
ENUMS.Morse.N9="- - - - *"
|
||||||
|
ENUMS.Morse.N0="- - - - -"
|
||||||
|
ENUMS.Morse[" "]=" "
|
||||||
@@ -0,0 +1,539 @@
|
|||||||
|
--- **Utils** - Lua Profiler.
|
||||||
|
--
|
||||||
|
-- Find out how many times functions are called and how much real time it costs.
|
||||||
|
--
|
||||||
|
-- ===
|
||||||
|
--
|
||||||
|
-- ### Author: **TAW CougarNL**, *funkyfranky*
|
||||||
|
--
|
||||||
|
-- @module Utilities.PROFILER
|
||||||
|
-- @image MOOSE.JPG
|
||||||
|
|
||||||
|
|
||||||
|
--- PROFILER class.
|
||||||
|
-- @type PROFILER
|
||||||
|
-- @field #string ClassName Name of the class.
|
||||||
|
-- @field #table Counters Function counters.
|
||||||
|
-- @field #table dInfo Info.
|
||||||
|
-- @field #table fTime Function time.
|
||||||
|
-- @field #table fTimeTotal Total function time.
|
||||||
|
-- @field #table eventhandler Event handler to get mission end event.
|
||||||
|
-- @field #number TstartGame Game start time timer.getTime().
|
||||||
|
-- @field #number TstartOS OS real start time os.clock.
|
||||||
|
-- @field #boolean logUnknown Log unknown functions. Default is off.
|
||||||
|
-- @field #number ThreshCPS Low calls per second threshold. Only write output if function has more calls per second 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 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 PROFILER Concept
|
||||||
|
--
|
||||||
|
-- Profile your lua code. This tells you, which functions are called very often and which consume most real time.
|
||||||
|
-- With this information you can optimize the perfomance of your code.
|
||||||
|
--
|
||||||
|
-- # Prerequisites
|
||||||
|
--
|
||||||
|
-- The modules **os** and **lfs** need to be desanizied.
|
||||||
|
--
|
||||||
|
--
|
||||||
|
-- # Start
|
||||||
|
--
|
||||||
|
-- The profiler can simply be started with the @{#PROFILER.Start}(*Delay, Duration*) function
|
||||||
|
--
|
||||||
|
-- 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
|
||||||
|
-- stop the profiler after a certain amount of seconds.
|
||||||
|
--
|
||||||
|
-- # Stop
|
||||||
|
--
|
||||||
|
-- The profiler automatically stops when the mission ends. But it can be stopped any time with the @{#PROFILER.Stop}(*Delay*) function
|
||||||
|
--
|
||||||
|
-- PROFILER.Stop()
|
||||||
|
--
|
||||||
|
-- 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.
|
||||||
|
--
|
||||||
|
-- # Output
|
||||||
|
--
|
||||||
|
-- The profiler output is written to a file in your DCS home folder
|
||||||
|
--
|
||||||
|
-- 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.
|
||||||
|
--
|
||||||
|
-- ## Data
|
||||||
|
--
|
||||||
|
-- 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.
|
||||||
|
--
|
||||||
|
-- If you only want output for functions that are called more than *X* times per second, you can set
|
||||||
|
--
|
||||||
|
-- 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).
|
||||||
|
--
|
||||||
|
-- Furthermore, you can limit the output for functions that consumed a certain amount of CPU time in total by
|
||||||
|
--
|
||||||
|
-- PROFILER.ThreshTtot=0.005
|
||||||
|
--
|
||||||
|
-- With this setting, which is also the default, only functions which in total used more than 5 milliseconds CPU time.
|
||||||
|
--
|
||||||
|
-- @field #PROFILER
|
||||||
|
PROFILER = {
|
||||||
|
ClassName = "PROFILER",
|
||||||
|
Counters = {},
|
||||||
|
dInfo = {},
|
||||||
|
fTime = {},
|
||||||
|
fTimeTotal = {},
|
||||||
|
eventHandler = {},
|
||||||
|
logUnknown = false,
|
||||||
|
ThreshCPS = 0.0,
|
||||||
|
ThreshTtot = 0.005,
|
||||||
|
fileNamePrefix = "MooseProfiler",
|
||||||
|
fileNameSuffix = "txt"
|
||||||
|
}
|
||||||
|
|
||||||
|
--- Waypoint data.
|
||||||
|
-- @type PROFILER.Data
|
||||||
|
-- @field #string func The function name.
|
||||||
|
-- @field #string src The source file.
|
||||||
|
-- @field #number line The line number
|
||||||
|
-- @field #number count Number of function calls.
|
||||||
|
-- @field #number tm Total time in seconds.
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-- Start/Stop Profiler
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- Start profiler.
|
||||||
|
-- @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.
|
||||||
|
function PROFILER.Start(Delay, Duration)
|
||||||
|
|
||||||
|
-- Check if os, io and lfs are available.
|
||||||
|
local go=true
|
||||||
|
if not os then
|
||||||
|
env.error("ERROR: Profiler needs os to be desanitized!")
|
||||||
|
go=false
|
||||||
|
end
|
||||||
|
if not io then
|
||||||
|
env.error("ERROR: Profiler needs io to be desanitized!")
|
||||||
|
go=false
|
||||||
|
end
|
||||||
|
if not lfs then
|
||||||
|
env.error("ERROR: Profiler needs lfs to be desanitized!")
|
||||||
|
go=false
|
||||||
|
end
|
||||||
|
if not go then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if Delay and Delay>0 then
|
||||||
|
BASE:ScheduleOnce(Delay, PROFILER.Start, 0, Duration)
|
||||||
|
else
|
||||||
|
|
||||||
|
-- Set start time.
|
||||||
|
PROFILER.TstartGame=timer.getTime()
|
||||||
|
PROFILER.TstartOS=os.clock()
|
||||||
|
|
||||||
|
-- Add event handler.
|
||||||
|
world.addEventHandler(PROFILER.eventHandler)
|
||||||
|
|
||||||
|
-- Info in log.
|
||||||
|
env.info('############################ Profiler Started ############################')
|
||||||
|
if Duration then
|
||||||
|
env.info(string.format("- Will be running for %d seconds", Duration))
|
||||||
|
else
|
||||||
|
env.info(string.format("- Will be stopped when mission ends"))
|
||||||
|
end
|
||||||
|
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("- 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('###############################################################################')
|
||||||
|
|
||||||
|
|
||||||
|
-- Message on screen
|
||||||
|
local duration=Duration or 600
|
||||||
|
trigger.action.outText("### Profiler running ###", duration)
|
||||||
|
|
||||||
|
-- Set hook.
|
||||||
|
debug.sethook(PROFILER.hook, "cr")
|
||||||
|
|
||||||
|
-- Auto stop profiler.
|
||||||
|
if Duration then
|
||||||
|
PROFILER.Stop(Duration)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Stop profiler.
|
||||||
|
-- @param #number Delay Delay before stop in seconds.
|
||||||
|
function PROFILER.Stop(Delay)
|
||||||
|
|
||||||
|
if Delay and Delay>0 then
|
||||||
|
|
||||||
|
BASE:ScheduleOnce(Delay, PROFILER.Stop)
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
-- Remove hook.
|
||||||
|
debug.sethook()
|
||||||
|
|
||||||
|
|
||||||
|
-- Run time game.
|
||||||
|
local runTimeGame=timer.getTime()-PROFILER.TstartGame
|
||||||
|
|
||||||
|
-- Run time real OS.
|
||||||
|
local runTimeOS=os.clock()-PROFILER.TstartOS
|
||||||
|
|
||||||
|
-- Show info.
|
||||||
|
PROFILER.showInfo(runTimeGame, runTimeOS)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Event handler.
|
||||||
|
function PROFILER.eventHandler:onEvent(event)
|
||||||
|
if event.id==world.event.S_EVENT_MISSION_END then
|
||||||
|
PROFILER.Stop()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-- Hook
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- Debug hook.
|
||||||
|
-- @param #table event Event.
|
||||||
|
function PROFILER.hook(event)
|
||||||
|
|
||||||
|
local f=debug.getinfo(2, "f").func
|
||||||
|
|
||||||
|
if event=='call' then
|
||||||
|
|
||||||
|
if PROFILER.Counters[f]==nil then
|
||||||
|
|
||||||
|
PROFILER.Counters[f]=1
|
||||||
|
PROFILER.dInfo[f]=debug.getinfo(2,"Sn")
|
||||||
|
|
||||||
|
if PROFILER.fTimeTotal[f]==nil then
|
||||||
|
PROFILER.fTimeTotal[f]=0
|
||||||
|
end
|
||||||
|
|
||||||
|
else
|
||||||
|
PROFILER.Counters[f]=PROFILER.Counters[f]+1
|
||||||
|
end
|
||||||
|
|
||||||
|
if PROFILER.fTime[f]==nil then
|
||||||
|
PROFILER.fTime[f]=os.clock()
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif (event=='return') then
|
||||||
|
|
||||||
|
if PROFILER.fTime[f]~=nil then
|
||||||
|
PROFILER.fTimeTotal[f]=PROFILER.fTimeTotal[f]+(os.clock()-PROFILER.fTime[f])
|
||||||
|
PROFILER.fTime[f]=nil
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-- Data
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- Get data.
|
||||||
|
-- @param #function func Function.
|
||||||
|
-- @return #string Function name.
|
||||||
|
-- @return #string Source file name.
|
||||||
|
-- @return #string Line number.
|
||||||
|
-- @return #number Function time in seconds.
|
||||||
|
function PROFILER.getData(func)
|
||||||
|
|
||||||
|
local n=PROFILER.dInfo[func]
|
||||||
|
|
||||||
|
if n.what=="C" then
|
||||||
|
return n.name, "?", "?", PROFILER.fTimeTotal[func]
|
||||||
|
end
|
||||||
|
|
||||||
|
return n.name, n.short_src, n.linedefined, PROFILER.fTimeTotal[func]
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Write text to log file.
|
||||||
|
-- @param #function f The file.
|
||||||
|
-- @param #string txt The text.
|
||||||
|
function PROFILER._flog(f, txt)
|
||||||
|
f:write(txt.."\r\n")
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Show table.
|
||||||
|
-- @param #table data Data table.
|
||||||
|
-- @param #function f The file.
|
||||||
|
-- @param #number runTimeGame Game run time in seconds.
|
||||||
|
function PROFILER.showTable(data, f, runTimeGame)
|
||||||
|
|
||||||
|
-- Loop over data.
|
||||||
|
for i=1, #data do
|
||||||
|
local t=data[i] --#PROFILER.Data
|
||||||
|
|
||||||
|
-- Calls per second.
|
||||||
|
local cps=t.count/runTimeGame
|
||||||
|
|
||||||
|
local threshCPS=cps>=PROFILER.ThreshCPS
|
||||||
|
local threshTot=t.tm>=PROFILER.ThreshTtot
|
||||||
|
|
||||||
|
if threshCPS and threshTot then
|
||||||
|
|
||||||
|
-- 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))
|
||||||
|
PROFILER._flog(f, text)
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Print csv file.
|
||||||
|
-- @param #table data Data table.
|
||||||
|
-- @param #number runTimeGame Game run time in seconds.
|
||||||
|
function PROFILER.printCSV(data, runTimeGame)
|
||||||
|
|
||||||
|
-- Output file.
|
||||||
|
local file=PROFILER.getfilename("csv")
|
||||||
|
local g=io.open(file, 'w')
|
||||||
|
|
||||||
|
-- Header.
|
||||||
|
local text="Function,Total Calls,Calls per Sec,Total Time,Total in %,Sec per Call,Source File;Line Number,"
|
||||||
|
g:write(text.."\r\n")
|
||||||
|
|
||||||
|
-- Loop over data.
|
||||||
|
for i=1, #data do
|
||||||
|
local t=data[i] --#PROFILER.Data
|
||||||
|
|
||||||
|
-- Calls per second.
|
||||||
|
local cps=t.count/runTimeGame
|
||||||
|
|
||||||
|
-- Output
|
||||||
|
local txt=string.format("%s,%d,%.1f,%.3f,%.3f,%.3f,%s,%s,", t.func, t.count, cps, t.tm, t.tm/runTimeGame*100, t.tm/t.count, tostring(t.src), tostring(t.line))
|
||||||
|
g:write(txt.."\r\n")
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Close file.
|
||||||
|
g:close()
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Write info to output file.
|
||||||
|
-- @param #string ext Extension.
|
||||||
|
-- @return #string File name.
|
||||||
|
function PROFILER.getfilename(ext)
|
||||||
|
|
||||||
|
local dir=lfs.writedir()..[[Logs\]]
|
||||||
|
|
||||||
|
ext=ext or PROFILER.fileNameSuffix
|
||||||
|
|
||||||
|
local file=dir..PROFILER.fileNamePrefix.."."..ext
|
||||||
|
|
||||||
|
if not UTILS.FileExists(file) then
|
||||||
|
return file
|
||||||
|
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
|
||||||
|
return file
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Write info to output file.
|
||||||
|
-- @param #number runTimeGame Game time in seconds.
|
||||||
|
-- @param #number runTimeOS OS time in seconds.
|
||||||
|
function PROFILER.showInfo(runTimeGame, runTimeOS)
|
||||||
|
|
||||||
|
-- Output file.
|
||||||
|
local file=PROFILER.getfilename(PROFILER.fileNameSuffix)
|
||||||
|
local f=io.open(file, 'w')
|
||||||
|
|
||||||
|
-- Gather data.
|
||||||
|
local Ttot=0
|
||||||
|
local Calls=0
|
||||||
|
|
||||||
|
local t={}
|
||||||
|
|
||||||
|
local tcopy=nil --#PROFILER.Data
|
||||||
|
local tserialize=nil --#PROFILER.Data
|
||||||
|
local tforgen=nil --#PROFILER.Data
|
||||||
|
local tpairs=nil --#PROFILER.Data
|
||||||
|
|
||||||
|
|
||||||
|
for func, count in pairs(PROFILER.Counters) do
|
||||||
|
|
||||||
|
local s,src,line,tm=PROFILER.getData(func)
|
||||||
|
|
||||||
|
if PROFILER.logUnknown==true then
|
||||||
|
if s==nil then s="<Unknown>" 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
|
||||||
|
|
||||||
|
-- Add special cases.
|
||||||
|
if tcopy then
|
||||||
|
table.insert(t, tcopy)
|
||||||
|
end
|
||||||
|
if tserialize then
|
||||||
|
table.insert(t, tserialize)
|
||||||
|
end
|
||||||
|
if tforgen then
|
||||||
|
table.insert(t, tforgen)
|
||||||
|
end
|
||||||
|
if tpairs then
|
||||||
|
table.insert(t, tpairs)
|
||||||
|
end
|
||||||
|
|
||||||
|
env.info('############################ Profiler Stopped ############################')
|
||||||
|
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("* 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 func calls : %d", Calls))
|
||||||
|
env.info(string.format("* Writing to file : \"%s\"", file))
|
||||||
|
env.info(string.format("* Writing to file : \"%s\"", PROFILER.getfilename("csv")))
|
||||||
|
env.info("##############################################################################")
|
||||||
|
|
||||||
|
-- Sort by total time.
|
||||||
|
table.sort(t, function(a,b) return a.tm>b.tm end)
|
||||||
|
|
||||||
|
-- Write data.
|
||||||
|
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._flog(f,"")
|
||||||
|
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("* Function time : %s = %.1f sec (%.1f %% of runtime game)", UTILS.SecondsToClock(Ttot, true), Ttot, Ttot/runTimeGame*100))
|
||||||
|
PROFILER._flog(f,"")
|
||||||
|
PROFILER._flog(f,string.format("* Total functions = %d", #t))
|
||||||
|
PROFILER._flog(f,string.format("* Total func calls = %d", Calls))
|
||||||
|
PROFILER._flog(f,"")
|
||||||
|
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,"")
|
||||||
|
PROFILER._flog(f,"************************************************************************************************************************")
|
||||||
|
PROFILER._flog(f,"")
|
||||||
|
PROFILER.showTable(t, f, runTimeGame)
|
||||||
|
|
||||||
|
-- Sort by number of calls.
|
||||||
|
table.sort(t, function(a,b) return a.tm/a.count>b.tm/b.count end)
|
||||||
|
|
||||||
|
-- Detailed data.
|
||||||
|
PROFILER._flog(f,"")
|
||||||
|
PROFILER._flog(f,"************************************************************************************************************************")
|
||||||
|
PROFILER._flog(f,"")
|
||||||
|
PROFILER._flog(f,"--------------------------------------")
|
||||||
|
PROFILER._flog(f,"---- Data Sorted by Time per Call ----")
|
||||||
|
PROFILER._flog(f,"--------------------------------------")
|
||||||
|
PROFILER._flog(f,"")
|
||||||
|
PROFILER.showTable(t, f, runTimeGame)
|
||||||
|
|
||||||
|
-- Sort by number of calls.
|
||||||
|
table.sort(t, function(a,b) return a.count>b.count end)
|
||||||
|
|
||||||
|
-- Detailed data.
|
||||||
|
PROFILER._flog(f,"")
|
||||||
|
PROFILER._flog(f,"************************************************************************************************************************")
|
||||||
|
PROFILER._flog(f,"")
|
||||||
|
PROFILER._flog(f,"------------------------------------")
|
||||||
|
PROFILER._flog(f,"---- Data Sorted by Total Calls ----")
|
||||||
|
PROFILER._flog(f,"------------------------------------")
|
||||||
|
PROFILER._flog(f,"")
|
||||||
|
PROFILER.showTable(t, f, runTimeGame)
|
||||||
|
|
||||||
|
-- Closing.
|
||||||
|
PROFILER._flog(f,"")
|
||||||
|
PROFILER._flog(f,"************************************************************************************************************************")
|
||||||
|
PROFILER._flog(f,"************************************************************************************************************************")
|
||||||
|
PROFILER._flog(f,"************************************************************************************************************************")
|
||||||
|
-- Close file.
|
||||||
|
f:close()
|
||||||
|
|
||||||
|
-- Print csv file.
|
||||||
|
PROFILER.printCSV(t, runTimeGame)
|
||||||
|
end
|
||||||
|
|
||||||
@@ -1631,6 +1631,11 @@ function routines.getGroupRoute(groupIdent, task) -- same as getGroupPoints bu
|
|||||||
|
|
||||||
for point_num, point in pairs(group_data.route.points) do
|
for point_num, point in pairs(group_data.route.points) do
|
||||||
local routeData = {}
|
local routeData = {}
|
||||||
|
if env.mission.version > 7 then
|
||||||
|
routeData.name = env.getValueDictByKey(point.name)
|
||||||
|
else
|
||||||
|
routeData.name = point.name
|
||||||
|
end
|
||||||
if not point.point then
|
if not point.point then
|
||||||
routeData.x = point.x
|
routeData.x = point.x
|
||||||
routeData.y = point.y
|
routeData.y = point.y
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
--- This module contains derived utilities taken from the MIST framework,
|
--- This module contains derived utilities taken from the MIST framework, which are excellent tools to be reused in an OO environment.
|
||||||
-- which are excellent tools to be reused in an OO environment!.
|
|
||||||
--
|
--
|
||||||
-- ### Authors:
|
-- ### Authors:
|
||||||
--
|
--
|
||||||
@@ -33,14 +32,14 @@ FLARECOLOR = trigger.flareColor -- #FLARECOLOR
|
|||||||
--- Big smoke preset enum.
|
--- Big smoke preset enum.
|
||||||
-- @type BIGSMOKEPRESET
|
-- @type BIGSMOKEPRESET
|
||||||
BIGSMOKEPRESET = {
|
BIGSMOKEPRESET = {
|
||||||
SmallSmokeAndFire=0,
|
SmallSmokeAndFire=1,
|
||||||
MediumSmokeAndFire=1,
|
MediumSmokeAndFire=2,
|
||||||
LargeSmokeAndFire=2,
|
LargeSmokeAndFire=3,
|
||||||
HugeSmokeAndFire=3,
|
HugeSmokeAndFire=4,
|
||||||
SmallSmoke=4,
|
SmallSmoke=5,
|
||||||
MediumSmoke=5,
|
MediumSmoke=6,
|
||||||
LargeSmoke=6,
|
LargeSmoke=7,
|
||||||
HugeSmoke=7,
|
HugeSmoke=8,
|
||||||
}
|
}
|
||||||
|
|
||||||
--- DCS map as returned by env.mission.theatre.
|
--- DCS map as returned by env.mission.theatre.
|
||||||
@@ -49,11 +48,15 @@ BIGSMOKEPRESET = {
|
|||||||
-- @field #string Normandy Normandy map.
|
-- @field #string Normandy Normandy map.
|
||||||
-- @field #string NTTR Nevada Test and Training Range map.
|
-- @field #string NTTR Nevada Test and Training Range map.
|
||||||
-- @field #string PersianGulf Persian Gulf map.
|
-- @field #string PersianGulf Persian Gulf map.
|
||||||
|
-- @field #string TheChannel The Channel map.
|
||||||
|
-- @field #string Syria Syria map.
|
||||||
DCSMAP = {
|
DCSMAP = {
|
||||||
Caucasus="Caucasus",
|
Caucasus="Caucasus",
|
||||||
NTTR="Nevada",
|
NTTR="Nevada",
|
||||||
Normandy="Normandy",
|
Normandy="Normandy",
|
||||||
PersianGulf="PersianGulf"
|
PersianGulf="PersianGulf",
|
||||||
|
TheChannel="TheChannel",
|
||||||
|
Syria="Syria",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -65,7 +68,7 @@ CALLSIGN={
|
|||||||
Enfield=1,
|
Enfield=1,
|
||||||
Springfield=2,
|
Springfield=2,
|
||||||
Uzi=3,
|
Uzi=3,
|
||||||
Cold=4,
|
Colt=4,
|
||||||
Dodge=5,
|
Dodge=5,
|
||||||
Ford=6,
|
Ford=6,
|
||||||
Chevy=7,
|
Chevy=7,
|
||||||
@@ -78,7 +81,7 @@ CALLSIGN={
|
|||||||
},
|
},
|
||||||
-- AWACS
|
-- AWACS
|
||||||
AWACS={
|
AWACS={
|
||||||
Overloard=1,
|
Overlord=1,
|
||||||
Magic=2,
|
Magic=2,
|
||||||
Wizard=3,
|
Wizard=3,
|
||||||
Focus=4,
|
Focus=4,
|
||||||
@@ -116,6 +119,7 @@ CALLSIGN={
|
|||||||
|
|
||||||
--- Utilities static class.
|
--- Utilities static class.
|
||||||
-- @type UTILS
|
-- @type UTILS
|
||||||
|
-- @field #number _MarkID Marker index counter. Running number when marker is added.
|
||||||
UTILS = {
|
UTILS = {
|
||||||
_MarkID = 1
|
_MarkID = 1
|
||||||
}
|
}
|
||||||
@@ -183,28 +187,40 @@ UTILS.IsInstanceOf = function( object, className )
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--from http://lua-users.org/wiki/CopyTable
|
--- Deep copy a table. See http://lua-users.org/wiki/CopyTable
|
||||||
|
-- @param #table object The input table.
|
||||||
|
-- @return #table Copy of the input table.
|
||||||
UTILS.DeepCopy = function(object)
|
UTILS.DeepCopy = function(object)
|
||||||
|
|
||||||
local lookup_table = {}
|
local lookup_table = {}
|
||||||
|
|
||||||
|
-- Copy function.
|
||||||
local function _copy(object)
|
local function _copy(object)
|
||||||
if type(object) ~= "table" then
|
if type(object) ~= "table" then
|
||||||
return object
|
return object
|
||||||
elseif lookup_table[object] then
|
elseif lookup_table[object] then
|
||||||
return lookup_table[object]
|
return lookup_table[object]
|
||||||
end
|
end
|
||||||
|
|
||||||
local new_table = {}
|
local new_table = {}
|
||||||
|
|
||||||
lookup_table[object] = new_table
|
lookup_table[object] = new_table
|
||||||
|
|
||||||
for index, value in pairs(object) do
|
for index, value in pairs(object) do
|
||||||
new_table[_copy(index)] = _copy(value)
|
new_table[_copy(index)] = _copy(value)
|
||||||
end
|
end
|
||||||
|
|
||||||
return setmetatable(new_table, getmetatable(object))
|
return setmetatable(new_table, getmetatable(object))
|
||||||
end
|
end
|
||||||
|
|
||||||
local objectreturn = _copy(object)
|
local objectreturn = _copy(object)
|
||||||
|
|
||||||
return objectreturn
|
return objectreturn
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- porting in Slmod's serialize_slmod2
|
--- Porting in Slmod's serialize_slmod2.
|
||||||
|
-- @param #table tbl Input table.
|
||||||
UTILS.OneLineSerialize = function( tbl ) -- serialization of a table all on a single line, no comments, made to replace old get_table_string function
|
UTILS.OneLineSerialize = function( tbl ) -- serialization of a table all on a single line, no comments, made to replace old get_table_string function
|
||||||
|
|
||||||
lookup_table = {}
|
lookup_table = {}
|
||||||
@@ -308,6 +324,10 @@ UTILS.MetersToNM = function(meters)
|
|||||||
return meters/1852
|
return meters/1852
|
||||||
end
|
end
|
||||||
|
|
||||||
|
UTILS.MetersToSM = function(meters)
|
||||||
|
return meters/1609.34
|
||||||
|
end
|
||||||
|
|
||||||
UTILS.MetersToFeet = function(meters)
|
UTILS.MetersToFeet = function(meters)
|
||||||
return meters/0.3048
|
return meters/0.3048
|
||||||
end
|
end
|
||||||
@@ -340,18 +360,30 @@ UTILS.MiphToMps = function( miph )
|
|||||||
return miph * 0.44704
|
return miph * 0.44704
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Convert meters per second to miles per hour.
|
||||||
|
-- @param #number mps Speed in m/s.
|
||||||
|
-- @return #number Speed in miles per hour.
|
||||||
UTILS.MpsToMiph = function( mps )
|
UTILS.MpsToMiph = function( mps )
|
||||||
return mps / 0.44704
|
return mps / 0.44704
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Convert meters per second to knots.
|
||||||
|
-- @param #number mps Speed in m/s.
|
||||||
|
-- @return #number Speed in knots.
|
||||||
UTILS.MpsToKnots = function( mps )
|
UTILS.MpsToKnots = function( mps )
|
||||||
return mps * 1.94384 --3600 / 1852
|
return mps * 1.94384 --3600 / 1852
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Convert knots to meters per second.
|
||||||
|
-- @param #number knots Speed in knots.
|
||||||
|
-- @return #number Speed in m/s.
|
||||||
UTILS.KnotsToMps = function( knots )
|
UTILS.KnotsToMps = function( knots )
|
||||||
return knots / 1.94384 --* 1852 / 3600
|
return knots / 1.94384 --* 1852 / 3600
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Convert temperature from Celsius to Farenheit.
|
||||||
|
-- @param #number Celcius Temperature in degrees Celsius.
|
||||||
|
-- @return #number Temperature in degrees Farenheit.
|
||||||
UTILS.CelciusToFarenheit = function( Celcius )
|
UTILS.CelciusToFarenheit = function( Celcius )
|
||||||
return Celcius * 9/5 + 32
|
return Celcius * 9/5 + 32
|
||||||
end
|
end
|
||||||
@@ -436,9 +468,9 @@ UTILS.tostringLL = function( lat, lon, acc, DMS)
|
|||||||
secFrmtStr = '%0' .. width .. '.' .. acc .. 'f'
|
secFrmtStr = '%0' .. width .. '.' .. acc .. 'f'
|
||||||
end
|
end
|
||||||
|
|
||||||
-- 024° 23' 12"N or 024° 23' 12.03"N
|
-- 024� 23' 12"N or 024� 23' 12.03"N
|
||||||
return string.format('%03d°', latDeg) .. ' ' .. string.format('%02d', latMin) .. '\' ' .. string.format(secFrmtStr, latSec) .. '"' .. latHemi .. ' '
|
return string.format('%03d°', latDeg)..string.format('%02d', latMin)..'\''..string.format(secFrmtStr, latSec)..'"'..latHemi..' '
|
||||||
.. string.format('%03d°', lonDeg) .. ' ' .. string.format('%02d', lonMin) .. '\' ' .. string.format(secFrmtStr, lonSec) .. '"' .. lonHemi
|
.. string.format('%03d°', lonDeg)..string.format('%02d', lonMin)..'\''..string.format(secFrmtStr, lonSec)..'"'..lonHemi
|
||||||
|
|
||||||
else -- degrees, decimal minutes.
|
else -- degrees, decimal minutes.
|
||||||
latMin = UTILS.Round(latMin, acc)
|
latMin = UTILS.Round(latMin, acc)
|
||||||
@@ -471,12 +503,31 @@ end
|
|||||||
|
|
||||||
-- acc- the accuracy of each easting/northing. 0, 1, 2, 3, 4, or 5.
|
-- acc- the accuracy of each easting/northing. 0, 1, 2, 3, 4, or 5.
|
||||||
UTILS.tostringMGRS = function(MGRS, acc) --R2.1
|
UTILS.tostringMGRS = function(MGRS, acc) --R2.1
|
||||||
|
|
||||||
if acc == 0 then
|
if acc == 0 then
|
||||||
return MGRS.UTMZone .. ' ' .. MGRS.MGRSDigraph
|
return MGRS.UTMZone .. ' ' .. MGRS.MGRSDigraph
|
||||||
else
|
else
|
||||||
return MGRS.UTMZone .. ' ' .. MGRS.MGRSDigraph .. ' ' .. string.format('%0' .. acc .. 'd', UTILS.Round(MGRS.Easting/(10^(5-acc)), 0))
|
|
||||||
.. ' ' .. string.format('%0' .. acc .. 'd', UTILS.Round(MGRS.Northing/(10^(5-acc)), 0))
|
-- Test if Easting/Northing have less than 4 digits.
|
||||||
|
--MGRS.Easting=123 -- should be 00123
|
||||||
|
--MGRS.Northing=5432 -- should be 05432
|
||||||
|
|
||||||
|
-- Truncate rather than round MGRS grid!
|
||||||
|
local Easting=tostring(MGRS.Easting)
|
||||||
|
local Northing=tostring(MGRS.Northing)
|
||||||
|
|
||||||
|
-- Count number of missing digits. Easting/Northing should have 5 digits. However, it is passed as a number. Therefore, any leading zeros would not be displayed by lua.
|
||||||
|
local nE=5-string.len(Easting)
|
||||||
|
local nN=5-string.len(Northing)
|
||||||
|
|
||||||
|
-- Get leading zeros (if any).
|
||||||
|
for i=1,nE do Easting="0"..Easting end
|
||||||
|
for i=1,nN do Northing="0"..Northing end
|
||||||
|
|
||||||
|
-- Return MGRS string.
|
||||||
|
return string.format("%s %s %s %s", MGRS.UTMZone, MGRS.MGRSDigraph, string.sub(Easting, 1, acc), string.sub(Northing, 1, acc))
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -684,7 +735,8 @@ function UTILS.SecondsToClock(seconds, short)
|
|||||||
local clock=hours..":"..mins..":"..secs.."+"..days
|
local clock=hours..":"..mins..":"..secs.."+"..days
|
||||||
if short then
|
if short then
|
||||||
if hours=="00" then
|
if hours=="00" then
|
||||||
clock=mins..":"..secs
|
--clock=mins..":"..secs
|
||||||
|
clock=hours..":"..mins..":"..secs
|
||||||
else
|
else
|
||||||
clock=hours..":"..mins..":"..secs
|
clock=hours..":"..mins..":"..secs
|
||||||
end
|
end
|
||||||
@@ -693,6 +745,26 @@ function UTILS.SecondsToClock(seconds, short)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Seconds of today.
|
||||||
|
-- @return #number Seconds passed since last midnight.
|
||||||
|
function UTILS.SecondsOfToday()
|
||||||
|
|
||||||
|
-- Time in seconds.
|
||||||
|
local time=timer.getAbsTime()
|
||||||
|
|
||||||
|
-- Short format without days since mission start.
|
||||||
|
local clock=UTILS.SecondsToClock(time, true)
|
||||||
|
|
||||||
|
-- Time is now the seconds passed since last midnight.
|
||||||
|
return UTILS.ClockToSeconds(clock)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Cound seconds until next midnight.
|
||||||
|
-- @return #number Seconds to midnight.
|
||||||
|
function UTILS.SecondsToMidnight()
|
||||||
|
return 24*60*60-UTILS.SecondsOfToday()
|
||||||
|
end
|
||||||
|
|
||||||
--- Convert clock time from hours, minutes and seconds to seconds.
|
--- Convert clock time from hours, minutes and seconds to seconds.
|
||||||
-- @param #string clock String of clock time. E.g., "06:12:35" or "5:1:30+1". Format is (H)H:(M)M:((S)S)(+D) H=Hours, M=Minutes, S=Seconds, D=Days.
|
-- @param #string clock String of clock time. E.g., "06:12:35" or "5:1:30+1". Format is (H)H:(M)M:((S)S)(+D) H=Hours, M=Minutes, S=Seconds, D=Days.
|
||||||
-- @return #number Seconds. Corresponds to what you cet from timer.getAbsTime() function.
|
-- @return #number Seconds. Corresponds to what you cet from timer.getAbsTime() function.
|
||||||
@@ -749,6 +821,15 @@ function UTILS.DisplayMissionTime(duration)
|
|||||||
MESSAGE:New(text, duration):ToAll()
|
MESSAGE:New(text, duration):ToAll()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Replace illegal characters [<>|/?*:\\] in a string.
|
||||||
|
-- @param #string Text Input text.
|
||||||
|
-- @param #string ReplaceBy Replace illegal characters by this character or string. Default underscore "_".
|
||||||
|
-- @return #string The input text with illegal chars replaced.
|
||||||
|
function UTILS.ReplaceIllegalCharacters(Text, ReplaceBy)
|
||||||
|
ReplaceBy=ReplaceBy or "_"
|
||||||
|
local text=Text:gsub("[<>|/?*:\\]", ReplaceBy)
|
||||||
|
return text
|
||||||
|
end
|
||||||
|
|
||||||
--- Generate a Gaussian pseudo-random number.
|
--- Generate a Gaussian pseudo-random number.
|
||||||
-- @param #number x0 Expectation value of distribution.
|
-- @param #number x0 Expectation value of distribution.
|
||||||
@@ -903,6 +984,22 @@ function UTILS.HdgDiff(h1, h2)
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Translate 3D vector in the 2D (x,z) plane. y-component (usually altitude) unchanged.
|
||||||
|
-- @param DCS#Vec3 a Vector in 3D with x, y, z components.
|
||||||
|
-- @param #number distance The distance to translate.
|
||||||
|
-- @param #number angle Rotation angle in degrees.
|
||||||
|
-- @return DCS#Vec3 Vector rotated in the (x,z) plane.
|
||||||
|
function UTILS.VecTranslate(a, distance, angle)
|
||||||
|
|
||||||
|
local SX = a.x
|
||||||
|
local SY = a.z
|
||||||
|
local Radians=math.rad(angle or 0)
|
||||||
|
local TX=distance*math.cos(Radians)+SX
|
||||||
|
local TY=distance*math.sin(Radians)+SY
|
||||||
|
|
||||||
|
return {x=TX, y=a.y, z=TY}
|
||||||
|
end
|
||||||
|
|
||||||
--- Rotate 3D vector in the 2D (x,z) plane. y-component (usually altitude) unchanged.
|
--- Rotate 3D vector in the 2D (x,z) plane. y-component (usually altitude) unchanged.
|
||||||
-- @param DCS#Vec3 a Vector in 3D with x, y, z components.
|
-- @param DCS#Vec3 a Vector in 3D with x, y, z components.
|
||||||
-- @param #number angle Rotation angle in degrees.
|
-- @param #number angle Rotation angle in degrees.
|
||||||
@@ -924,7 +1021,6 @@ function UTILS.Rotate2D(a, angle)
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--- Converts a TACAN Channel/Mode couple into a frequency in Hz.
|
--- Converts a TACAN Channel/Mode couple into a frequency in Hz.
|
||||||
-- @param #number TACANChannel The TACAN channel, i.e. the 10 in "10X".
|
-- @param #number TACANChannel The TACAN channel, i.e. the 10 in "10X".
|
||||||
-- @param #string TACANMode The TACAN mode, i.e. the "X" in "10X".
|
-- @param #string TACANMode The TACAN mode, i.e. the "X" in "10X".
|
||||||
@@ -963,20 +1059,69 @@ end
|
|||||||
|
|
||||||
|
|
||||||
--- Returns the DCS map/theatre as optained by env.mission.theatre
|
--- Returns the DCS map/theatre as optained by env.mission.theatre
|
||||||
-- @return #string DCS map name .
|
-- @return #string DCS map name.
|
||||||
function UTILS.GetDCSMap()
|
function UTILS.GetDCSMap()
|
||||||
return env.mission.theatre
|
return env.mission.theatre
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Returns the mission date. This is the date the mission started.
|
--- Returns the mission date. This is the date the mission **started**.
|
||||||
-- @return #string Mission date in yyyy/mm/dd format.
|
-- @return #string Mission date in yyyy/mm/dd format.
|
||||||
|
-- @return #number The year anno domini.
|
||||||
|
-- @return #number The month.
|
||||||
|
-- @return #number The day.
|
||||||
function UTILS.GetDCSMissionDate()
|
function UTILS.GetDCSMissionDate()
|
||||||
local year=tostring(env.mission.date.Year)
|
local year=tostring(env.mission.date.Year)
|
||||||
local month=tostring(env.mission.date.Month)
|
local month=tostring(env.mission.date.Month)
|
||||||
local day=tostring(env.mission.date.Day)
|
local day=tostring(env.mission.date.Day)
|
||||||
return string.format("%s/%s/%s", year, month, day)
|
return string.format("%s/%s/%s", year, month, day), tonumber(year), tonumber(month), tonumber(day)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Returns the day of the mission.
|
||||||
|
-- @param #number Time (Optional) Abs. time in seconds. Default now, i.e. the value return from timer.getAbsTime().
|
||||||
|
-- @return #number Day of the mission. Mission starts on day 0.
|
||||||
|
function UTILS.GetMissionDay(Time)
|
||||||
|
|
||||||
|
Time=Time or timer.getAbsTime()
|
||||||
|
|
||||||
|
local clock=UTILS.SecondsToClock(Time, false)
|
||||||
|
|
||||||
|
local x=tonumber(UTILS.Split(clock, "+")[2])
|
||||||
|
|
||||||
|
return x
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Returns the current day of the year of the mission.
|
||||||
|
-- @param #number Time (Optional) Abs. time in seconds. Default now, i.e. the value return from timer.getAbsTime().
|
||||||
|
-- @return #number Current day of year of the mission. For example, January 1st returns 0, January 2nd returns 1 etc.
|
||||||
|
function UTILS.GetMissionDayOfYear(Time)
|
||||||
|
|
||||||
|
local Date, Year, Month, Day=UTILS.GetDCSMissionDate()
|
||||||
|
|
||||||
|
local d=UTILS.GetMissionDay(Time)
|
||||||
|
|
||||||
|
return UTILS.GetDayOfYear(Year, Month, Day)+d
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Returns the current date.
|
||||||
|
-- @return #string Mission date in yyyy/mm/dd format.
|
||||||
|
-- @return #number The year anno domini.
|
||||||
|
-- @return #number The month.
|
||||||
|
-- @return #number The day.
|
||||||
|
function UTILS.GetDate()
|
||||||
|
|
||||||
|
-- Mission start date
|
||||||
|
local date, year, month, day=UTILS.GetDCSMissionDate()
|
||||||
|
|
||||||
|
local time=timer.getAbsTime()
|
||||||
|
|
||||||
|
local clock=UTILS.SecondsToClock(time, false)
|
||||||
|
|
||||||
|
local x=tonumber(UTILS.Split(clock, "+")[2])
|
||||||
|
|
||||||
|
local day=day+x
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
--- Returns the magnetic declination of the map.
|
--- Returns the magnetic declination of the map.
|
||||||
-- Returned values for the current maps are:
|
-- Returned values for the current maps are:
|
||||||
@@ -1001,6 +1146,10 @@ function UTILS.GetMagneticDeclination(map)
|
|||||||
declination=-10
|
declination=-10
|
||||||
elseif map==DCSMAP.PersianGulf then
|
elseif map==DCSMAP.PersianGulf then
|
||||||
declination=2
|
declination=2
|
||||||
|
elseif map==DCSMAP.TheChannel then
|
||||||
|
declination=-10
|
||||||
|
elseif map==DCSMAP.Syria then
|
||||||
|
declination=5
|
||||||
else
|
else
|
||||||
declination=0
|
declination=0
|
||||||
end
|
end
|
||||||
@@ -1037,3 +1186,262 @@ function UTILS.CheckMemory(output)
|
|||||||
end
|
end
|
||||||
return mem
|
return mem
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Get the coalition name from its numerical ID, e.g. coaliton.side.RED.
|
||||||
|
-- @param #number Coalition The coalition ID.
|
||||||
|
-- @return #string The coalition name, i.e. "Neutral", "Red" or "Blue" (or "Unknown").
|
||||||
|
function UTILS.GetCoalitionName(Coalition)
|
||||||
|
|
||||||
|
if Coalition then
|
||||||
|
if Coalition==coalition.side.BLUE then
|
||||||
|
return "Blue"
|
||||||
|
elseif Coalition==coalition.side.RED then
|
||||||
|
return "Red"
|
||||||
|
elseif Coalition==coalition.side.NEUTRAL then
|
||||||
|
return "Neutral"
|
||||||
|
else
|
||||||
|
return "Unknown"
|
||||||
|
end
|
||||||
|
else
|
||||||
|
return "Unknown"
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get the modulation name from its numerical value.
|
||||||
|
-- @param #number Modulation The modulation enumerator number. Can be either 0 or 1.
|
||||||
|
-- @return #string The modulation name, i.e. "AM"=0 or "FM"=1. Anything else will return "Unknown".
|
||||||
|
function UTILS.GetModulationName(Modulation)
|
||||||
|
|
||||||
|
if Modulation then
|
||||||
|
if Modulation==0 then
|
||||||
|
return "AM"
|
||||||
|
elseif Modulation==1 then
|
||||||
|
return "FM"
|
||||||
|
else
|
||||||
|
return "Unknown"
|
||||||
|
end
|
||||||
|
else
|
||||||
|
return "Unknown"
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get the callsign name from its enumerator value
|
||||||
|
-- @param #number Callsign The enumerator callsign.
|
||||||
|
-- @return #string The callsign name or "Ghostrider".
|
||||||
|
function UTILS.GetCallsignName(Callsign)
|
||||||
|
|
||||||
|
for name, value in pairs(CALLSIGN.Aircraft) do
|
||||||
|
if value==Callsign then
|
||||||
|
return name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for name, value in pairs(CALLSIGN.AWACS) do
|
||||||
|
if value==Callsign then
|
||||||
|
return name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for name, value in pairs(CALLSIGN.JTAC) do
|
||||||
|
if value==Callsign then
|
||||||
|
return name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for name, value in pairs(CALLSIGN.Tanker) do
|
||||||
|
if value==Callsign then
|
||||||
|
return name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return "Ghostrider"
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get the time difference between GMT and local time.
|
||||||
|
-- @return #number Local time difference in hours compared to GMT. E.g. Dubai is GMT+4 ==> +4 is returned.
|
||||||
|
function UTILS.GMTToLocalTimeDifference()
|
||||||
|
|
||||||
|
local theatre=UTILS.GetDCSMap()
|
||||||
|
|
||||||
|
if theatre==DCSMAP.Caucasus then
|
||||||
|
return 4 -- Caucasus UTC+4 hours
|
||||||
|
elseif theatre==DCSMAP.PersianGulf then
|
||||||
|
return 4 -- Abu Dhabi UTC+4 hours
|
||||||
|
elseif theatre==DCSMAP.NTTR then
|
||||||
|
return -8 -- Las Vegas UTC-8 hours
|
||||||
|
elseif theatre==DCSMAP.Normandy then
|
||||||
|
return 0 -- Calais UTC+1 hour
|
||||||
|
elseif theatre==DCSMAP.TheChannel then
|
||||||
|
return 2 -- This map currently needs +2
|
||||||
|
elseif theatre==DCSMAP.Syria then
|
||||||
|
return 3 -- Damascus is UTC+3 hours
|
||||||
|
else
|
||||||
|
BASE:E(string.format("ERROR: Unknown Map %s in UTILS.GMTToLocal function. Returning 0", tostring(theatre)))
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Get the day of the year. Counting starts on 1st of January.
|
||||||
|
-- @param #number Year The year.
|
||||||
|
-- @param #number Month The month.
|
||||||
|
-- @param #number Day The day.
|
||||||
|
-- @return #number The day of the year.
|
||||||
|
function UTILS.GetDayOfYear(Year, Month, Day)
|
||||||
|
|
||||||
|
local floor = math.floor
|
||||||
|
|
||||||
|
local n1 = floor(275 * Month / 9)
|
||||||
|
local n2 = floor((Month + 9) / 12)
|
||||||
|
local n3 = (1 + floor((Year - 4 * floor(Year / 4) + 2) / 3))
|
||||||
|
|
||||||
|
return n1 - (n2 * n3) + Day - 30
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get sunrise or sun set of a specific day of the year at a specific location.
|
||||||
|
-- @param #number DayOfYear The day of the year.
|
||||||
|
-- @param #number Latitude Latitude.
|
||||||
|
-- @param #number Longitude Longitude.
|
||||||
|
-- @param #boolean Rising If true, calc sun rise, or sun set otherwise.
|
||||||
|
-- @param #number Tlocal Local time offset in hours. E.g. +4 for a location which has GMT+4.
|
||||||
|
-- @return #number Sun rise/set in seconds of the day.
|
||||||
|
function UTILS.GetSunRiseAndSet(DayOfYear, Latitude, Longitude, Rising, Tlocal)
|
||||||
|
|
||||||
|
-- Defaults
|
||||||
|
local zenith=90.83
|
||||||
|
local latitude=Latitude
|
||||||
|
local longitude=Longitude
|
||||||
|
local rising=Rising
|
||||||
|
local n=DayOfYear
|
||||||
|
Tlocal=Tlocal or 0
|
||||||
|
|
||||||
|
|
||||||
|
-- Short cuts.
|
||||||
|
local rad = math.rad
|
||||||
|
local deg = math.deg
|
||||||
|
local floor = math.floor
|
||||||
|
local frac = function(n) return n - floor(n) end
|
||||||
|
local cos = function(d) return math.cos(rad(d)) end
|
||||||
|
local acos = function(d) return deg(math.acos(d)) end
|
||||||
|
local sin = function(d) return math.sin(rad(d)) end
|
||||||
|
local asin = function(d) return deg(math.asin(d)) end
|
||||||
|
local tan = function(d) return math.tan(rad(d)) end
|
||||||
|
local atan = function(d) return deg(math.atan(d)) end
|
||||||
|
|
||||||
|
local function fit_into_range(val, min, max)
|
||||||
|
local range = max - min
|
||||||
|
local count
|
||||||
|
if val < min then
|
||||||
|
count = floor((min - val) / range) + 1
|
||||||
|
return val + count * range
|
||||||
|
elseif val >= max then
|
||||||
|
count = floor((val - max) / range) + 1
|
||||||
|
return val - count * range
|
||||||
|
else
|
||||||
|
return val
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Convert the longitude to hour value and calculate an approximate time
|
||||||
|
local lng_hour = longitude / 15
|
||||||
|
|
||||||
|
local t
|
||||||
|
if rising then -- Rising time is desired
|
||||||
|
t = n + ((6 - lng_hour) / 24)
|
||||||
|
else -- Setting time is desired
|
||||||
|
t = n + ((18 - lng_hour) / 24)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Calculate the Sun's mean anomaly
|
||||||
|
local M = (0.9856 * t) - 3.289
|
||||||
|
|
||||||
|
-- Calculate the Sun's true longitude
|
||||||
|
local L = fit_into_range(M + (1.916 * sin(M)) + (0.020 * sin(2 * M)) + 282.634, 0, 360)
|
||||||
|
|
||||||
|
-- Calculate the Sun's right ascension
|
||||||
|
local RA = fit_into_range(atan(0.91764 * tan(L)), 0, 360)
|
||||||
|
|
||||||
|
-- Right ascension value needs to be in the same quadrant as L
|
||||||
|
local Lquadrant = floor(L / 90) * 90
|
||||||
|
local RAquadrant = floor(RA / 90) * 90
|
||||||
|
RA = RA + Lquadrant - RAquadrant
|
||||||
|
|
||||||
|
-- Right ascension value needs to be converted into hours
|
||||||
|
RA = RA / 15
|
||||||
|
|
||||||
|
-- Calculate the Sun's declination
|
||||||
|
local sinDec = 0.39782 * sin(L)
|
||||||
|
local cosDec = cos(asin(sinDec))
|
||||||
|
|
||||||
|
-- Calculate the Sun's local hour angle
|
||||||
|
local cosH = (cos(zenith) - (sinDec * sin(latitude))) / (cosDec * cos(latitude))
|
||||||
|
|
||||||
|
if rising and cosH > 1 then
|
||||||
|
return "N/R" -- The sun never rises on this location on the specified date
|
||||||
|
elseif cosH < -1 then
|
||||||
|
return "N/S" -- The sun never sets on this location on the specified date
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Finish calculating H and convert into hours
|
||||||
|
local H
|
||||||
|
if rising then
|
||||||
|
H = 360 - acos(cosH)
|
||||||
|
else
|
||||||
|
H = acos(cosH)
|
||||||
|
end
|
||||||
|
H = H / 15
|
||||||
|
|
||||||
|
-- Calculate local mean time of rising/setting
|
||||||
|
local T = H + RA - (0.06571 * t) - 6.622
|
||||||
|
|
||||||
|
-- Adjust back to UTC
|
||||||
|
local UT = fit_into_range(T - lng_hour +Tlocal, 0, 24)
|
||||||
|
|
||||||
|
return floor(UT)*60*60+frac(UT)*60*60--+Tlocal*60*60
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get sun rise of a specific day of the year at a specific location.
|
||||||
|
-- @param #number Day Day of the year.
|
||||||
|
-- @param #number Month Month of the year.
|
||||||
|
-- @param #number Year Year.
|
||||||
|
-- @param #number Latitude Latitude.
|
||||||
|
-- @param #number Longitude Longitude.
|
||||||
|
-- @param #boolean Rising If true, calc sun rise, or sun set otherwise.
|
||||||
|
-- @param #number Tlocal Local time offset in hours. E.g. +4 for a location which has GMT+4. Default 0.
|
||||||
|
-- @return #number Sun rise in seconds of the day.
|
||||||
|
function UTILS.GetSunrise(Day, Month, Year, Latitude, Longitude, Tlocal)
|
||||||
|
|
||||||
|
local DayOfYear=UTILS.GetDayOfYear(Year, Month, Day)
|
||||||
|
|
||||||
|
return UTILS.GetSunRiseAndSet(DayOfYear, Latitude, Longitude, true, Tlocal)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get sun set of a specific day of the year at a specific location.
|
||||||
|
-- @param #number Day Day of the year.
|
||||||
|
-- @param #number Month Month of the year.
|
||||||
|
-- @param #number Year Year.
|
||||||
|
-- @param #number Latitude Latitude.
|
||||||
|
-- @param #number Longitude Longitude.
|
||||||
|
-- @param #boolean Rising If true, calc sun rise, or sun set otherwise.
|
||||||
|
-- @param #number Tlocal Local time offset in hours. E.g. +4 for a location which has GMT+4. Default 0.
|
||||||
|
-- @return #number Sun rise in seconds of the day.
|
||||||
|
function UTILS.GetSunset(Day, Month, Year, Latitude, Longitude, Tlocal)
|
||||||
|
|
||||||
|
local DayOfYear=UTILS.GetDayOfYear(Year, Month, Day)
|
||||||
|
|
||||||
|
return UTILS.GetSunRiseAndSet(DayOfYear, Latitude, Longitude, false, Tlocal)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get OS time. Needs os to be desanitized!
|
||||||
|
-- @return #number Os time in seconds.
|
||||||
|
function UTILS.GetOSTime()
|
||||||
|
if os then
|
||||||
|
return os.clock()
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
@@ -15,6 +15,15 @@
|
|||||||
--- @type AIRBASE
|
--- @type AIRBASE
|
||||||
-- @field #string ClassName Name of the class, i.e. "AIRBASE".
|
-- @field #string ClassName Name of the class, i.e. "AIRBASE".
|
||||||
-- @field #table CategoryName Names of airbase categories.
|
-- @field #table CategoryName Names of airbase categories.
|
||||||
|
-- @field #string AirbaseName Name of the airbase.
|
||||||
|
-- @field #number AirbaseID Airbase ID.
|
||||||
|
-- @field #number category Airbase category.
|
||||||
|
-- @field #table descriptors DCS descriptors.
|
||||||
|
-- @field #boolean isAirdrome Airbase is an airdrome.
|
||||||
|
-- @field #boolean isHelipad Airbase is a helipad.
|
||||||
|
-- @field #boolean isShip Airbase is a ship.
|
||||||
|
-- @field #table parking Parking spot data.
|
||||||
|
-- @field #table parkingByID Parking spot data table with ID as key.
|
||||||
-- @field #number activerwyno Active runway number (forced).
|
-- @field #number activerwyno Active runway number (forced).
|
||||||
-- @extends Wrapper.Positionable#POSITIONABLE
|
-- @extends Wrapper.Positionable#POSITIONABLE
|
||||||
|
|
||||||
@@ -124,7 +133,6 @@ AIRBASE.Caucasus = {
|
|||||||
-- * AIRBASE.Nevada.Jean_Airport
|
-- * AIRBASE.Nevada.Jean_Airport
|
||||||
-- * AIRBASE.Nevada.Laughlin_Airport
|
-- * AIRBASE.Nevada.Laughlin_Airport
|
||||||
-- * AIRBASE.Nevada.Lincoln_County
|
-- * AIRBASE.Nevada.Lincoln_County
|
||||||
-- * AIRBASE.Nevada.Mellan_Airstrip
|
|
||||||
-- * AIRBASE.Nevada.Mesquite
|
-- * AIRBASE.Nevada.Mesquite
|
||||||
-- * AIRBASE.Nevada.Mina_Airport_3Q0
|
-- * AIRBASE.Nevada.Mina_Airport_3Q0
|
||||||
-- * AIRBASE.Nevada.North_Las_Vegas
|
-- * AIRBASE.Nevada.North_Las_Vegas
|
||||||
@@ -144,7 +152,6 @@ AIRBASE.Nevada = {
|
|||||||
["Jean_Airport"] = "Jean Airport",
|
["Jean_Airport"] = "Jean Airport",
|
||||||
["Laughlin_Airport"] = "Laughlin Airport",
|
["Laughlin_Airport"] = "Laughlin Airport",
|
||||||
["Lincoln_County"] = "Lincoln County",
|
["Lincoln_County"] = "Lincoln County",
|
||||||
["Mellan_Airstrip"] = "Mellan Airstrip",
|
|
||||||
["Mesquite"] = "Mesquite",
|
["Mesquite"] = "Mesquite",
|
||||||
["Mina_Airport_3Q0"] = "Mina Airport 3Q0",
|
["Mina_Airport_3Q0"] = "Mina Airport 3Q0",
|
||||||
["North_Las_Vegas"] = "North Las Vegas",
|
["North_Las_Vegas"] = "North Las Vegas",
|
||||||
@@ -185,7 +192,7 @@ AIRBASE.Nevada = {
|
|||||||
-- * AIRBASE.Normandy.Needs_Oar_Point
|
-- * AIRBASE.Normandy.Needs_Oar_Point
|
||||||
-- * AIRBASE.Normandy.Funtington
|
-- * AIRBASE.Normandy.Funtington
|
||||||
-- * AIRBASE.Normandy.Tangmere
|
-- * AIRBASE.Normandy.Tangmere
|
||||||
-- * AIRBASE.Normandy.Ford
|
-- * AIRBASE.Normandy.Ford_AF
|
||||||
-- @field Normandy
|
-- @field Normandy
|
||||||
AIRBASE.Normandy = {
|
AIRBASE.Normandy = {
|
||||||
["Saint_Pierre_du_Mont"] = "Saint Pierre du Mont",
|
["Saint_Pierre_du_Mont"] = "Saint Pierre du Mont",
|
||||||
@@ -218,8 +225,15 @@ AIRBASE.Normandy = {
|
|||||||
["Needs_Oar_Point"] = "Needs Oar Point",
|
["Needs_Oar_Point"] = "Needs Oar Point",
|
||||||
["Funtington"] = "Funtington",
|
["Funtington"] = "Funtington",
|
||||||
["Tangmere"] = "Tangmere",
|
["Tangmere"] = "Tangmere",
|
||||||
["Ford"] = "Ford",
|
["Ford_AF"] = "Ford_AF",
|
||||||
}
|
["Goulet"] = "Goulet",
|
||||||
|
["Argentan"] = "Argentan",
|
||||||
|
["Vrigny"] = "Vrigny",
|
||||||
|
["Essay"] = "Essay",
|
||||||
|
["Hauterive"] = "Hauterive",
|
||||||
|
["Barville"] = "Barville",
|
||||||
|
["Conches"] = "Conches",
|
||||||
|
}
|
||||||
|
|
||||||
--- These are all airbases of the Persion Gulf Map:
|
--- These are all airbases of the Persion Gulf Map:
|
||||||
--
|
--
|
||||||
@@ -275,7 +289,7 @@ AIRBASE.PersianGulf = {
|
|||||||
["Lavan_Island_Airport"] = "Lavan Island Airport",
|
["Lavan_Island_Airport"] = "Lavan Island Airport",
|
||||||
["Liwa_Airbase"] = "Liwa Airbase",
|
["Liwa_Airbase"] = "Liwa Airbase",
|
||||||
["Qeshm_Island"] = "Qeshm Island",
|
["Qeshm_Island"] = "Qeshm Island",
|
||||||
["Ras_Al_Khaimah_International_Airport"] = "Ras Al Khaimah International Airport",
|
["Ras_Al_Khaimah"] = "Ras Al Khaimah",
|
||||||
["Sas_Al_Nakheel_Airport"] = "Sas Al Nakheel Airport",
|
["Sas_Al_Nakheel_Airport"] = "Sas Al Nakheel Airport",
|
||||||
["Sharjah_Intl"] = "Sharjah Intl",
|
["Sharjah_Intl"] = "Sharjah Intl",
|
||||||
["Shiraz_International_Airport"] = "Shiraz International Airport",
|
["Shiraz_International_Airport"] = "Shiraz International Airport",
|
||||||
@@ -285,6 +299,105 @@ AIRBASE.PersianGulf = {
|
|||||||
["Tunb_Kochak"] = "Tunb Kochak",
|
["Tunb_Kochak"] = "Tunb Kochak",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
--- These are all airbases of the The Channel Map:
|
||||||
|
--
|
||||||
|
-- * AIRBASE.TheChannel.Abbeville_Drucat
|
||||||
|
-- * AIRBASE.TheChannel.Merville_Calonne
|
||||||
|
-- * AIRBASE.TheChannel.Saint_Omer_Longuenesse
|
||||||
|
-- * AIRBASE.TheChannel.Dunkirk_Mardyck
|
||||||
|
-- * AIRBASE.TheChannel.Manston
|
||||||
|
-- * AIRBASE.TheChannel.Hawkinge
|
||||||
|
-- * AIRBASE.TheChannel.Lympne
|
||||||
|
-- * AIRBASE.TheChannel.Detling
|
||||||
|
-- * AIRBASE.TheChannel.High_Halden
|
||||||
|
--
|
||||||
|
-- @field TheChannel
|
||||||
|
AIRBASE.TheChannel = {
|
||||||
|
["Abbeville_Drucat"] = "Abbeville Drucat",
|
||||||
|
["Merville_Calonne"] = "Merville Calonne",
|
||||||
|
["Saint_Omer_Longuenesse"] = "Saint Omer Longuenesse",
|
||||||
|
["Dunkirk_Mardyck"] = "Dunkirk Mardyck",
|
||||||
|
["Manston"] = "Manston",
|
||||||
|
["Hawkinge"] = "Hawkinge",
|
||||||
|
["Lympne"] = "Lympne",
|
||||||
|
["Detling"] = "Detling",
|
||||||
|
["High_Halden"] = "High Halden",
|
||||||
|
}
|
||||||
|
|
||||||
|
--- Airbases of Syria
|
||||||
|
--
|
||||||
|
-- * AIRBASE.Syria.Kuweires
|
||||||
|
-- * AIRBASE.Syria.Marj_Ruhayyil
|
||||||
|
-- * AIRBASE.Syria.Kiryat_Shmona
|
||||||
|
-- * AIRBASE.Syria.Marj_as_Sultan_North
|
||||||
|
-- * AIRBASE.Syria.Eyn_Shemer
|
||||||
|
-- * AIRBASE.Syria.Incirlik
|
||||||
|
-- * AIRBASE.Syria.Damascus
|
||||||
|
-- * AIRBASE.Syria.Bassel_Al_Assad
|
||||||
|
-- * AIRBASE.Syria.Aleppo
|
||||||
|
-- * AIRBASE.Syria.Qabr_as_Sitt
|
||||||
|
-- * AIRBASE.Syria.Wujah_Al_Hajar
|
||||||
|
-- * AIRBASE.Syria.Al_Dumayr
|
||||||
|
-- * AIRBASE.Syria.Hatay
|
||||||
|
-- * AIRBASE.Syria.Haifa
|
||||||
|
-- * AIRBASE.Syria.Khalkhalah
|
||||||
|
-- * AIRBASE.Syria.Megiddo
|
||||||
|
-- * AIRBASE.Syria.Rayak
|
||||||
|
-- * AIRBASE.Syria.Mezzeh
|
||||||
|
-- * AIRBASE.Syria.King_Hussein_Air_College
|
||||||
|
-- * AIRBASE.Syria.Jirah
|
||||||
|
-- * AIRBASE.Syria.Taftanaz
|
||||||
|
-- * AIRBASE.Syria.Rene_Mouawad
|
||||||
|
-- * AIRBASE.Syria.Ramat_David
|
||||||
|
-- * AIRBASE.Syria.Minakh
|
||||||
|
-- * AIRBASE.Syria.Adana_Sakirpasa
|
||||||
|
-- * AIRBASE.Syria.Marj_as_Sultan_South
|
||||||
|
-- * AIRBASE.Syria.Hama
|
||||||
|
-- * AIRBASE.Syria.Al_Qusayr
|
||||||
|
-- * AIRBASE.Syria.Palmyra
|
||||||
|
-- * AIRBASE.Syria.Tabqa
|
||||||
|
-- * AIRBASE.Syria.Beirut_Rafic_Hariri
|
||||||
|
-- * AIRBASE.Syria.An_Nasiriyah
|
||||||
|
-- * AIRBASE.Syria.Abu_al_Duhur
|
||||||
|
--
|
||||||
|
-- @field Syria
|
||||||
|
AIRBASE.Syria={
|
||||||
|
["Kuweires"]="Kuweires",
|
||||||
|
["Marj_Ruhayyil"]="Marj Ruhayyil",
|
||||||
|
["Kiryat_Shmona"]="Kiryat Shmona",
|
||||||
|
["Marj_as_Sultan_North"]="Marj as Sultan North",
|
||||||
|
["Eyn_Shemer"]="Eyn Shemer",
|
||||||
|
["Incirlik"]="Incirlik",
|
||||||
|
["Damascus"]="Damascus",
|
||||||
|
["Bassel_Al_Assad"]="Bassel Al-Assad",
|
||||||
|
["Aleppo"]="Aleppo",
|
||||||
|
["Qabr_as_Sitt"]="Qabr as Sitt",
|
||||||
|
["Wujah_Al_Hajar"]="Wujah Al Hajar",
|
||||||
|
["Al_Dumayr"]="Al-Dumayr",
|
||||||
|
["Hatay"]="Hatay",
|
||||||
|
["Haifa"]="Haifa",
|
||||||
|
["Khalkhalah"]="Khalkhalah",
|
||||||
|
["Megiddo"]="Megiddo",
|
||||||
|
["Rayak"]="Rayak",
|
||||||
|
["Mezzeh"]="Mezzeh",
|
||||||
|
["King_Hussein_Air_College"]="King Hussein Air College",
|
||||||
|
["Jirah"]="Jirah",
|
||||||
|
["Taftanaz"]="Taftanaz",
|
||||||
|
["Rene_Mouawad"]="Rene Mouawad",
|
||||||
|
["Ramat_David"]="Ramat David",
|
||||||
|
["Minakh"]="Minakh",
|
||||||
|
["Adana_Sakirpasa"]="Adana Sakirpasa",
|
||||||
|
["Marj_as_Sultan_South"]="Marj as Sultan South",
|
||||||
|
["Hama"]="Hama",
|
||||||
|
["Al_Qusayr"]="Al Qusayr",
|
||||||
|
["Palmyra"]="Palmyra",
|
||||||
|
["Tabqa"]="Tabqa",
|
||||||
|
["Beirut_Rafic_Hariri"]="Beirut-Rafic Hariri",
|
||||||
|
["An_Nasiriyah"]="An Nasiriyah",
|
||||||
|
["Abu_al_Duhur"]="Abu al-Duhur",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
--- AIRBASE.ParkingSpot ".Coordinate, ".TerminalID", ".TerminalType", ".TOAC", ".Free", ".TerminalID0", ".DistToRwy".
|
--- AIRBASE.ParkingSpot ".Coordinate, ".TerminalID", ".TerminalType", ".TOAC", ".Free", ".TerminalID0", ".DistToRwy".
|
||||||
-- @type AIRBASE.ParkingSpot
|
-- @type AIRBASE.ParkingSpot
|
||||||
-- @field Core.Point#COORDINATE Coordinate Coordinate of the parking spot.
|
-- @field Core.Point#COORDINATE Coordinate Coordinate of the parking spot.
|
||||||
@@ -305,7 +418,7 @@ AIRBASE.PersianGulf = {
|
|||||||
-- * AIRBASE.TerminalType.OpenMed = 72: Open/Shelter air airplane only.
|
-- * AIRBASE.TerminalType.OpenMed = 72: Open/Shelter air airplane only.
|
||||||
-- * AIRBASE.TerminalType.OpenBig = 104: Open air spawn points. Generally larger but does not guarantee large aircraft are capable of spawning there.
|
-- * AIRBASE.TerminalType.OpenBig = 104: Open air spawn points. Generally larger but does not guarantee large aircraft are capable of spawning there.
|
||||||
-- * AIRBASE.TerminalType.OpenMedOrBig = 176: Combines OpenMed and OpenBig spots.
|
-- * AIRBASE.TerminalType.OpenMedOrBig = 176: Combines OpenMed and OpenBig spots.
|
||||||
-- * AIRBASE.TerminalType.HelicopterUnsable = 216: Combines HelicopterOnly, OpenMed and OpenBig.
|
-- * AIRBASE.TerminalType.HelicopterUsable = 216: Combines HelicopterOnly, OpenMed and OpenBig.
|
||||||
-- * AIRBASE.TerminalType.FighterAircraft = 244: Combines Shelter. OpenMed and OpenBig spots. So effectively all spots usable by fixed wing aircraft.
|
-- * AIRBASE.TerminalType.FighterAircraft = 244: Combines Shelter. OpenMed and OpenBig spots. So effectively all spots usable by fixed wing aircraft.
|
||||||
--
|
--
|
||||||
-- @type AIRBASE.TerminalType
|
-- @type AIRBASE.TerminalType
|
||||||
@@ -331,26 +444,67 @@ AIRBASE.TerminalType = {
|
|||||||
--- Runway data.
|
--- Runway data.
|
||||||
-- @type AIRBASE.Runway
|
-- @type AIRBASE.Runway
|
||||||
-- @field #number heading Heading of the runway in degrees.
|
-- @field #number heading Heading of the runway in degrees.
|
||||||
-- @field #string idx Runway ID: heading 070° ==> idx="07".
|
-- @field #string idx Runway ID: heading 070° ==> idx="07".
|
||||||
-- @field #number length Length of runway in meters.
|
-- @field #number length Length of runway in meters.
|
||||||
-- @field Core.Point#COORDINATE position Position of runway start.
|
-- @field Core.Point#COORDINATE position Position of runway start.
|
||||||
-- @field Core.Point#COORDINATE endpoint End point of runway.
|
-- @field Core.Point#COORDINATE endpoint End point of runway.
|
||||||
|
|
||||||
-- Registration.
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-- Registration
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
--- Create a new AIRBASE from DCSAirbase.
|
--- Create a new AIRBASE from DCSAirbase.
|
||||||
-- @param #AIRBASE self
|
-- @param #AIRBASE self
|
||||||
-- @param #string AirbaseName The name of the airbase.
|
-- @param #string AirbaseName The name of the airbase.
|
||||||
-- @return Wrapper.Airbase#AIRBASE
|
-- @return #AIRBASE self
|
||||||
function AIRBASE:Register( AirbaseName )
|
function AIRBASE:Register(AirbaseName)
|
||||||
|
|
||||||
|
-- Inherit everything from positionable.
|
||||||
|
local self=BASE:Inherit(self, POSITIONABLE:New(AirbaseName)) --#AIRBASE
|
||||||
|
|
||||||
|
-- Set airbase name.
|
||||||
|
self.AirbaseName=AirbaseName
|
||||||
|
|
||||||
|
-- Set airbase ID.
|
||||||
|
self.AirbaseID=self:GetID(true)
|
||||||
|
|
||||||
|
-- Get descriptors.
|
||||||
|
self.descriptors=self:GetDesc()
|
||||||
|
|
||||||
|
-- Category.
|
||||||
|
self.category=self.descriptors and self.descriptors.category or Airbase.Category.AIRDROME
|
||||||
|
|
||||||
|
-- Set category.
|
||||||
|
if self.category==Airbase.Category.AIRDROME then
|
||||||
|
self.isAirdrome=true
|
||||||
|
elseif self.category==Airbase.Category.HELIPAD then
|
||||||
|
self.isHelipad=true
|
||||||
|
elseif self.category==Airbase.Category.SHIP then
|
||||||
|
self.isShip=true
|
||||||
|
else
|
||||||
|
self:E("ERROR: Unknown airbase category!")
|
||||||
|
end
|
||||||
|
|
||||||
|
self:_InitParkingSpots()
|
||||||
|
|
||||||
|
local vec2=self:GetVec2()
|
||||||
|
|
||||||
|
-- Init coordinate.
|
||||||
|
self:GetCoordinate()
|
||||||
|
|
||||||
|
if vec2 then
|
||||||
|
-- TODO: For ships we need a moving zone.
|
||||||
|
self.AirbaseZone=ZONE_RADIUS:New( AirbaseName, vec2, 2500 )
|
||||||
|
else
|
||||||
|
self:E(string.format("ERROR: Cound not get position Vec2 of airbase %s", AirbaseName))
|
||||||
|
end
|
||||||
|
|
||||||
local self = BASE:Inherit( self, POSITIONABLE:New( AirbaseName ) )
|
|
||||||
self.AirbaseName = AirbaseName
|
|
||||||
self.AirbaseZone = ZONE_RADIUS:New( AirbaseName, self:GetVec2(), 2500 )
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Reference methods.
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-- Reference methods
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
--- Finds a AIRBASE from the _DATABASE using a DCSAirbase object.
|
--- Finds a AIRBASE from the _DATABASE using a DCSAirbase object.
|
||||||
-- @param #AIRBASE self
|
-- @param #AIRBASE self
|
||||||
@@ -382,7 +536,7 @@ function AIRBASE:FindByID(id)
|
|||||||
for name,_airbase in pairs(_DATABASE.AIRBASES) do
|
for name,_airbase in pairs(_DATABASE.AIRBASES) do
|
||||||
local airbase=_airbase --#AIRBASE
|
local airbase=_airbase --#AIRBASE
|
||||||
|
|
||||||
local aid=tonumber(airbase:GetID())
|
local aid=tonumber(airbase:GetID(true))
|
||||||
|
|
||||||
if aid==id then
|
if aid==id then
|
||||||
return airbase
|
return airbase
|
||||||
@@ -397,7 +551,9 @@ end
|
|||||||
-- @param #AIRBASE self
|
-- @param #AIRBASE self
|
||||||
-- @return DCS#Airbase DCS airbase object.
|
-- @return DCS#Airbase DCS airbase object.
|
||||||
function AIRBASE:GetDCSObject()
|
function AIRBASE:GetDCSObject()
|
||||||
local DCSAirbase = Airbase.getByName( self.AirbaseName )
|
|
||||||
|
-- Get the DCS object.
|
||||||
|
local DCSAirbase = Airbase.getByName(self.AirbaseName)
|
||||||
|
|
||||||
if DCSAirbase then
|
if DCSAirbase then
|
||||||
return DCSAirbase
|
return DCSAirbase
|
||||||
@@ -422,7 +578,7 @@ function AIRBASE.GetAllAirbases(coalition, category)
|
|||||||
local airbases={}
|
local airbases={}
|
||||||
for _,_airbase in pairs(_DATABASE.AIRBASES) do
|
for _,_airbase in pairs(_DATABASE.AIRBASES) do
|
||||||
local airbase=_airbase --#AIRBASE
|
local airbase=_airbase --#AIRBASE
|
||||||
if (coalition~=nil and airbase:GetCoalition()==coalition) or coalition==nil then
|
if coalition==nil or airbase:GetCoalition()==coalition then
|
||||||
if category==nil or category==airbase:GetAirbaseCategory() then
|
if category==nil or category==airbase:GetAirbaseCategory() then
|
||||||
table.insert(airbases, airbase)
|
table.insert(airbases, airbase)
|
||||||
end
|
end
|
||||||
@@ -432,6 +588,95 @@ function AIRBASE.GetAllAirbases(coalition, category)
|
|||||||
return airbases
|
return airbases
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Get all airbase names of the current map. This includes ships and FARPS.
|
||||||
|
-- @param DCS#Coalition coalition (Optional) Return only airbases belonging to the specified coalition. By default, all airbases of the map are returned.
|
||||||
|
-- @param #number category (Optional) Return only airbases of a certain category, e.g. Airbase.Category.FARP
|
||||||
|
-- @return #table Table containing all airbase names of the current map.
|
||||||
|
function AIRBASE.GetAllAirbaseNames(coalition, category)
|
||||||
|
|
||||||
|
local airbases={}
|
||||||
|
for airbasename,_airbase in pairs(_DATABASE.AIRBASES) do
|
||||||
|
local airbase=_airbase --#AIRBASE
|
||||||
|
if coalition==nil or airbase:GetCoalition()==coalition then
|
||||||
|
if category==nil or category==airbase:GetAirbaseCategory() then
|
||||||
|
table.insert(airbases, airbasename)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return airbases
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get ID of the airbase.
|
||||||
|
-- @param #AIRBASE self
|
||||||
|
-- @param #boolean unique (Optional) If true, ships will get a negative sign as the unit ID might be the same as an airbase ID. Default off!
|
||||||
|
-- @return #number The airbase ID.
|
||||||
|
function AIRBASE:GetID(unique)
|
||||||
|
|
||||||
|
if self.AirbaseID then
|
||||||
|
|
||||||
|
return unique and self.AirbaseID or math.abs(self.AirbaseID)
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
for DCSAirbaseId, DCSAirbase in ipairs(world.getAirbases()) do
|
||||||
|
|
||||||
|
-- Get the airbase name.
|
||||||
|
local AirbaseName = DCSAirbase:getName()
|
||||||
|
|
||||||
|
-- This gives the incorrect value to be inserted into the airdromeID for DCS 2.5.6!
|
||||||
|
local airbaseID=tonumber(DCSAirbase:getID())
|
||||||
|
|
||||||
|
local airbaseCategory=self:GetAirbaseCategory()
|
||||||
|
|
||||||
|
if AirbaseName==self.AirbaseName 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.
|
||||||
|
return unique and -airbaseID or airbaseID
|
||||||
|
else
|
||||||
|
return airbaseID
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Get category of airbase.
|
||||||
|
-- @param #AIRBASE self
|
||||||
|
-- @return #number Category of airbase from GetDesc().category.
|
||||||
|
function AIRBASE:GetAirbaseCategory()
|
||||||
|
return self.category
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Check if airbase is an airdrome.
|
||||||
|
-- @param #AIRBASE self
|
||||||
|
-- @return #boolean If true, airbase is an airdrome.
|
||||||
|
function AIRBASE:IsAirdrome()
|
||||||
|
return self.isAirdrome
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Check if airbase is a helipad.
|
||||||
|
-- @param #AIRBASE self
|
||||||
|
-- @return #boolean If true, airbase is a helipad.
|
||||||
|
function AIRBASE:IsHelipad()
|
||||||
|
return self.isHelipad
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Check if airbase is a ship.
|
||||||
|
-- @param #AIRBASE self
|
||||||
|
-- @return #boolean If true, airbase is a ship.
|
||||||
|
function AIRBASE:IsShip()
|
||||||
|
return self.isShip
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-- Parking
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
--- Returns a table of parking data for a given airbase. If the optional parameter *available* is true only available parking will be returned, otherwise all parking at the base is returned. Term types have the following enumerated values:
|
--- Returns a table of parking data for a given airbase. If the optional parameter *available* is true only available parking will be returned, otherwise all parking at the base is returned. Term types have the following enumerated values:
|
||||||
--
|
--
|
||||||
@@ -563,6 +808,58 @@ function AIRBASE:GetParkingSpotsCoordinates(termtype)
|
|||||||
return spots
|
return spots
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Get a table containing the coordinates, terminal index and terminal type of free parking spots at an airbase.
|
||||||
|
-- @param #AIRBASE self
|
||||||
|
-- @return#AIRBASE self
|
||||||
|
function AIRBASE:_InitParkingSpots()
|
||||||
|
|
||||||
|
-- Get parking data of all spots (free or occupied)
|
||||||
|
local parkingdata=self:GetParkingData(false)
|
||||||
|
|
||||||
|
-- Init table.
|
||||||
|
self.parking={}
|
||||||
|
self.parkingByID={}
|
||||||
|
|
||||||
|
self.NparkingTotal=0
|
||||||
|
self.NparkingTerminal={}
|
||||||
|
for _,terminalType in pairs(AIRBASE.TerminalType) do
|
||||||
|
self.NparkingTerminal[terminalType]=0
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Put coordinates of parking spots into table.
|
||||||
|
for _,spot in pairs(parkingdata) do
|
||||||
|
|
||||||
|
-- New parking spot.
|
||||||
|
local park={} --#AIRBASE.ParkingSpot
|
||||||
|
park.Vec3=spot.vTerminalPos
|
||||||
|
park.Coordinate=COORDINATE:NewFromVec3(spot.vTerminalPos)
|
||||||
|
park.DistToRwy=spot.fDistToRW
|
||||||
|
park.Free=nil
|
||||||
|
park.TerminalID=spot.Term_Index
|
||||||
|
park.TerminalID0=spot.Term_Index_0
|
||||||
|
park.TerminalType=spot.Term_Type
|
||||||
|
park.TOAC=spot.TO_AC
|
||||||
|
|
||||||
|
for _,terminalType in pairs(AIRBASE.TerminalType) do
|
||||||
|
if self._CheckTerminalType(terminalType, park.TerminalType) then
|
||||||
|
self.NparkingTerminal[terminalType]=self.NparkingTerminal[terminalType]+1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
self.parkingByID[park.TerminalID]=park
|
||||||
|
table.insert(self.parking, park)
|
||||||
|
end
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get a table containing the coordinates, terminal index and terminal type of free parking spots at an airbase.
|
||||||
|
-- @param #AIRBASE self
|
||||||
|
-- @param #number TerminalID Terminal ID.
|
||||||
|
-- @return #AIRBASE.ParkingSpot Parking spot.
|
||||||
|
function AIRBASE:_GetParkingSpotByID(TerminalID)
|
||||||
|
return self.parkingByID[TerminalID]
|
||||||
|
end
|
||||||
|
|
||||||
--- Get a table containing the coordinates, terminal index and terminal type of free parking spots at an airbase.
|
--- Get a table containing the coordinates, terminal index and terminal type of free parking spots at an airbase.
|
||||||
-- @param #AIRBASE self
|
-- @param #AIRBASE self
|
||||||
@@ -572,6 +869,7 @@ function AIRBASE:GetParkingSpotsTable(termtype)
|
|||||||
|
|
||||||
-- Get parking data of all spots (free or occupied)
|
-- Get parking data of all spots (free or occupied)
|
||||||
local parkingdata=self:GetParkingData(false)
|
local parkingdata=self:GetParkingData(false)
|
||||||
|
|
||||||
-- Get parking data of all free spots.
|
-- Get parking data of all free spots.
|
||||||
local parkingfree=self:GetParkingData(true)
|
local parkingfree=self:GetParkingData(true)
|
||||||
|
|
||||||
@@ -588,15 +886,18 @@ function AIRBASE:GetParkingSpotsTable(termtype)
|
|||||||
-- Put coordinates of parking spots into table.
|
-- Put coordinates of parking spots into table.
|
||||||
local spots={}
|
local spots={}
|
||||||
for _,_spot in pairs(parkingdata) do
|
for _,_spot in pairs(parkingdata) do
|
||||||
if AIRBASE._CheckTerminalType(_spot.Term_Type, termtype) then
|
|
||||||
self:T2({_spot=_spot})
|
|
||||||
local _free=_isfree(_spot)
|
|
||||||
local _coord=COORDINATE:NewFromVec3(_spot.vTerminalPos)
|
|
||||||
table.insert(spots, {Coordinate=_coord, TerminalID=_spot.Term_Index, TerminalType=_spot.Term_Type, TOAC=_spot.TO_AC, Free=_free, TerminalID0=_spot.Term_Index_0, DistToRwy=_spot.fDistToRW})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
self:T2({ spots = spots } )
|
if AIRBASE._CheckTerminalType(_spot.Term_Type, termtype) then
|
||||||
|
|
||||||
|
local spot=self:_GetParkingSpotByID(_spot.Term_Index)
|
||||||
|
|
||||||
|
spot.Free=_isfree(_spot) -- updated
|
||||||
|
spot.TOAC=_spot.TO_AC -- updated
|
||||||
|
|
||||||
|
table.insert(spots, spot)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
return spots
|
return spots
|
||||||
end
|
end
|
||||||
@@ -616,8 +917,14 @@ function AIRBASE:GetFreeParkingSpotsTable(termtype, allowTOAC)
|
|||||||
for _,_spot in pairs(parkingfree) do
|
for _,_spot in pairs(parkingfree) do
|
||||||
if AIRBASE._CheckTerminalType(_spot.Term_Type, termtype) and _spot.Term_Index>0 then
|
if AIRBASE._CheckTerminalType(_spot.Term_Type, termtype) and _spot.Term_Index>0 then
|
||||||
if (allowTOAC and allowTOAC==true) or _spot.TO_AC==false then
|
if (allowTOAC and allowTOAC==true) or _spot.TO_AC==false then
|
||||||
local _coord=COORDINATE:NewFromVec3(_spot.vTerminalPos)
|
|
||||||
table.insert(freespots, {Coordinate=_coord, TerminalID=_spot.Term_Index, TerminalType=_spot.Term_Type, TOAC=_spot.TO_AC, Free=true, TerminalID0=_spot.Term_Index_0, DistToRwy=_spot.fDistToRW})
|
local spot=self:_GetParkingSpotByID(_spot.Term_Index)
|
||||||
|
|
||||||
|
spot.Free=true -- updated
|
||||||
|
spot.TOAC=_spot.TO_AC -- updated
|
||||||
|
|
||||||
|
table.insert(freespots, spot)
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -630,14 +937,10 @@ end
|
|||||||
-- @param #number TerminalID The terminal ID of the parking spot.
|
-- @param #number TerminalID The terminal ID of the parking spot.
|
||||||
-- @return #AIRBASE.ParkingSpot Table free parking spots. Table has the elements ".Coordinate, ".TerminalID", ".TerminalType", ".TOAC", ".Free", ".TerminalID0", ".DistToRwy".
|
-- @return #AIRBASE.ParkingSpot Table free parking spots. Table has the elements ".Coordinate, ".TerminalID", ".TerminalType", ".TOAC", ".Free", ".TerminalID0", ".DistToRwy".
|
||||||
function AIRBASE:GetParkingSpotData(TerminalID)
|
function AIRBASE:GetParkingSpotData(TerminalID)
|
||||||
self:F({TerminalID=TerminalID})
|
|
||||||
|
|
||||||
-- Get parking data.
|
-- Get parking data.
|
||||||
local parkingdata=self:GetParkingSpotsTable()
|
local parkingdata=self:GetParkingSpotsTable()
|
||||||
|
|
||||||
-- Debug output.
|
|
||||||
self:T2({parkingdata=parkingdata})
|
|
||||||
|
|
||||||
for _,_spot in pairs(parkingdata) do
|
for _,_spot in pairs(parkingdata) do
|
||||||
local spot=_spot --#AIRBASE.ParkingSpot
|
local spot=_spot --#AIRBASE.ParkingSpot
|
||||||
self:T({TerminalID=spot.TerminalID,TerminalType=spot.TerminalType})
|
self:T({TerminalID=spot.TerminalID,TerminalType=spot.TerminalType})
|
||||||
@@ -876,91 +1179,6 @@ function AIRBASE:FindFreeParkingSpotForAircraft(group, terminaltype, scanradius,
|
|||||||
return validspots
|
return validspots
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Function that checks if at leat one unit of a group has been spawned close to a spawn point on the runway.
|
|
||||||
-- @param #AIRBASE self
|
|
||||||
-- @param Wrapper.Group#GROUP group Group to be checked.
|
|
||||||
-- @param #number radius Radius around the spawn point to be checked. Default is 50 m.
|
|
||||||
-- @param #boolean despawn If true, the group is destroyed.
|
|
||||||
-- @return #boolean True if group is within radius around spawn points on runway.
|
|
||||||
function AIRBASE:CheckOnRunWay(group, radius, despawn)
|
|
||||||
|
|
||||||
-- Default radius.
|
|
||||||
radius=radius or 50
|
|
||||||
|
|
||||||
-- We only check at real airbases (not FARPS or ships).
|
|
||||||
if self:GetDesc().category~=Airbase.Category.AIRDROME then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
if group and group:IsAlive() then
|
|
||||||
|
|
||||||
-- Debug.
|
|
||||||
self:T(string.format("%s, checking if group %s is on runway?",self:GetName(), group:GetName()))
|
|
||||||
|
|
||||||
-- Get coordinates on runway.
|
|
||||||
local runwaypoints=self:GetParkingSpotsCoordinates(AIRBASE.TerminalType.Runway)
|
|
||||||
|
|
||||||
-- Mark runway spawn points.
|
|
||||||
--[[
|
|
||||||
for _i,_coord in pairs(runwaypoints) do
|
|
||||||
_coord:MarkToAll(string.format("runway %d",_i))
|
|
||||||
end
|
|
||||||
]]
|
|
||||||
|
|
||||||
-- Get units of group.
|
|
||||||
local units=group:GetUnits()
|
|
||||||
|
|
||||||
-- Loop over units.
|
|
||||||
for _,_unit in pairs(units) do
|
|
||||||
|
|
||||||
local unit=_unit --Wrapper.Unit#UNIT
|
|
||||||
|
|
||||||
-- Check if unit is alive and not in air.
|
|
||||||
if unit and unit:IsAlive() and not unit:InAir() then
|
|
||||||
self:T(string.format("%s, checking if unit %s is on runway?",self:GetName(), unit:GetName()))
|
|
||||||
|
|
||||||
-- Loop over runway spawn points.
|
|
||||||
for _i,_coord in pairs(runwaypoints) do
|
|
||||||
|
|
||||||
-- Distance between unit and spawn pos.
|
|
||||||
local dist=unit:GetCoordinate():Get2DDistance(_coord)
|
|
||||||
|
|
||||||
-- Mark unit spawn points for debugging.
|
|
||||||
--unit:GetCoordinate():MarkToAll(string.format("unit %s distance to rwy %d = %d",unit:GetName(),_i, dist))
|
|
||||||
|
|
||||||
-- Check if unit is withing radius.
|
|
||||||
if dist<radius then
|
|
||||||
self:E(string.format("%s, unit %s of group %s was spawned on runway #%d. Distance %.1f < radius %.1f m. Despawn = %s.", self:GetName(), unit:GetName(), group:GetName(),_i, dist, radius, tostring(despawn)))
|
|
||||||
--unit:FlareRed()
|
|
||||||
if despawn then
|
|
||||||
group:Destroy(true)
|
|
||||||
end
|
|
||||||
return true
|
|
||||||
else
|
|
||||||
self:T(string.format("%s, unit %s of group %s was NOT spawned on runway #%d. Distance %.1f > radius %.1f m. Despawn = %s.", self:GetName(), unit:GetName(), group:GetName(),_i, dist, radius, tostring(despawn)))
|
|
||||||
--unit:FlareGreen()
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
else
|
|
||||||
self:T(string.format("%s, checking if unit %s of group %s is on runway. Unit is NOT alive.",self:GetName(), unit:GetName(), group:GetName()))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
self:T(string.format("%s, checking if group %s is on runway. Group is NOT alive.",self:GetName(), group:GetName()))
|
|
||||||
end
|
|
||||||
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Get category of airbase.
|
|
||||||
-- @param #AIRBASE self
|
|
||||||
-- @return #number Category of airbase from GetDesc().category.
|
|
||||||
function AIRBASE:GetAirbaseCategory()
|
|
||||||
return self:GetDesc().category
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
--- Helper function to check for the correct terminal type including "artificial" ones.
|
--- Helper function to check for the correct terminal type including "artificial" ones.
|
||||||
-- @param #number Term_Type Termial type from getParking routine.
|
-- @param #number Term_Type Termial type from getParking routine.
|
||||||
-- @param #AIRBASE.TerminalType termtype Terminal type from AIRBASE.TerminalType enumerator.
|
-- @param #AIRBASE.TerminalType termtype Terminal type from AIRBASE.TerminalType enumerator.
|
||||||
@@ -1007,6 +1225,10 @@ function AIRBASE._CheckTerminalType(Term_Type, termtype)
|
|||||||
return match
|
return match
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-- Runway
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
--- Get runways data. Only for airdromes!
|
--- Get runways data. Only for airdromes!
|
||||||
-- @param #AIRBASE self
|
-- @param #AIRBASE self
|
||||||
-- @param #number magvar (Optional) Magnetic variation in degrees.
|
-- @param #number magvar (Optional) Magnetic variation in degrees.
|
||||||
@@ -1021,46 +1243,129 @@ function AIRBASE:GetRunwayData(magvar, mark)
|
|||||||
return {}
|
return {}
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Get spawn points on runway.
|
-- Get spawn points on runway. These can be used to determine the runway heading.
|
||||||
local runwaycoords=self:GetParkingSpotsCoordinates(AIRBASE.TerminalType.Runway)
|
local runwaycoords=self:GetParkingSpotsCoordinates(AIRBASE.TerminalType.Runway)
|
||||||
|
|
||||||
|
-- Debug: For finding the numbers of the spawn points belonging to each runway.
|
||||||
|
if false then
|
||||||
|
for i,_coord in pairs(runwaycoords) do
|
||||||
|
local coord=_coord --Core.Point#COORDINATE
|
||||||
|
coord:Translate(100, 0):MarkToAll("Runway i="..i)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- Magnetic declination.
|
-- Magnetic declination.
|
||||||
magvar=magvar or UTILS.GetMagneticDeclination()
|
magvar=magvar or UTILS.GetMagneticDeclination()
|
||||||
|
|
||||||
|
-- Number of runways.
|
||||||
local N=#runwaycoords
|
local N=#runwaycoords
|
||||||
local dN=2
|
local N2=N/2
|
||||||
local ex=false
|
local exception=false
|
||||||
|
|
||||||
|
-- Airbase name.
|
||||||
local name=self:GetName()
|
local name=self:GetName()
|
||||||
|
|
||||||
|
|
||||||
|
-- Exceptions
|
||||||
if name==AIRBASE.Nevada.Jean_Airport or
|
if name==AIRBASE.Nevada.Jean_Airport or
|
||||||
name==AIRBASE.Nevada.Creech_AFB or
|
name==AIRBASE.Nevada.Creech_AFB or
|
||||||
name==AIRBASE.PersianGulf.Abu_Dhabi_International_Airport or
|
name==AIRBASE.PersianGulf.Abu_Dhabi_International_Airport or
|
||||||
name==AIRBASE.PersianGulf.Dubai_Intl or
|
name==AIRBASE.PersianGulf.Dubai_Intl or
|
||||||
name==AIRBASE.PersianGulf.Shiraz_International_Airport or
|
name==AIRBASE.PersianGulf.Shiraz_International_Airport or
|
||||||
name==AIRBASE.PersianGulf.Kish_International_Airport then
|
name==AIRBASE.PersianGulf.Kish_International_Airport
|
||||||
|
then
|
||||||
|
|
||||||
N=#runwaycoords/2
|
-- 1-->4, 2-->3, 3-->2, 4-->1
|
||||||
dN=1
|
exception=1
|
||||||
ex=true
|
|
||||||
|
elseif UTILS.GetDCSMap()==DCSMAP.Syria and N>=2 and
|
||||||
|
name~=AIRBASE.Syria.Minakh and
|
||||||
|
name~=AIRBASE.Syria.Damascus and
|
||||||
|
name~=AIRBASE.Syria.Khalkhalah and
|
||||||
|
name~=AIRBASE.Syria.Marj_Ruhayyil and
|
||||||
|
name~=AIRBASE.Syria.Beirut_Rafic_Hariri then
|
||||||
|
|
||||||
|
-- 1-->3, 2-->4, 3-->1, 4-->2
|
||||||
|
exception=2
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
local function f(i)
|
||||||
|
|
||||||
|
local j
|
||||||
|
|
||||||
|
if exception==1 then
|
||||||
|
|
||||||
|
j=N-(i+1) -- 1-->4, 2-->3
|
||||||
|
|
||||||
|
elseif exception==2 then
|
||||||
|
|
||||||
|
if i<=N2 then
|
||||||
|
j=i+N2 -- 1-->3, 2-->4
|
||||||
|
else
|
||||||
|
j=i-N2 -- 3-->1, 4-->3
|
||||||
|
end
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
if i%2==0 then
|
||||||
|
j=i-1 -- even 2-->1, 4-->3
|
||||||
|
else
|
||||||
|
j=i+1 -- odd 1-->2, 3-->4
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Special case where there is no obvious order.
|
||||||
|
if name==AIRBASE.Syria.Beirut_Rafic_Hariri then
|
||||||
|
if i==1 then
|
||||||
|
j=3
|
||||||
|
elseif i==2 then
|
||||||
|
j=6
|
||||||
|
elseif i==3 then
|
||||||
|
j=1
|
||||||
|
elseif i==4 then
|
||||||
|
j=5
|
||||||
|
elseif i==5 then
|
||||||
|
j=4
|
||||||
|
elseif i==6 then
|
||||||
|
j=2
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if name==AIRBASE.Syria.Ramat_David then
|
||||||
|
if i==1 then
|
||||||
|
j=4
|
||||||
|
elseif i==2 then
|
||||||
|
j=6
|
||||||
|
elseif i==3 then
|
||||||
|
j=5
|
||||||
|
elseif i==4 then
|
||||||
|
j=1
|
||||||
|
elseif i==5 then
|
||||||
|
j=3
|
||||||
|
elseif i==6 then
|
||||||
|
j=2
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return j
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
for i=1,N,dN do
|
for i=1,N do
|
||||||
|
|
||||||
local j=i+1
|
-- Get the other spawn point coordinate.
|
||||||
if ex then
|
local j=f(i)
|
||||||
--j=N+i
|
|
||||||
j=#runwaycoords-i+1
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Coordinates of the two runway points.
|
-- Coordinates of the two runway points.
|
||||||
local c1=runwaycoords[i] --Core.Point#COORDINATES
|
local c1=runwaycoords[i] --Core.Point#COORDINATE
|
||||||
local c2=runwaycoords[j] --Core.Point#COORDINATES
|
local c2=runwaycoords[j] --Core.Point#COORDINATE
|
||||||
|
|
||||||
-- Heading of runway.
|
-- Heading of runway.
|
||||||
local hdg=c1:HeadingTo(c2)
|
local hdg=c1:HeadingTo(c2)
|
||||||
|
|
||||||
-- Runway ID: heading=070° ==> idx="07"
|
-- Runway ID: heading=070° ==> idx="07"
|
||||||
local idx=string.format("%02d", UTILS.Round((hdg-magvar)/10, 0))
|
local idx=string.format("%02d", UTILS.Round((hdg-magvar)/10, 0))
|
||||||
|
|
||||||
-- Runway table.
|
-- Runway table.
|
||||||
@@ -1072,11 +1377,11 @@ function AIRBASE:GetRunwayData(magvar, mark)
|
|||||||
runway.endpoint=c2
|
runway.endpoint=c2
|
||||||
|
|
||||||
-- Debug info.
|
-- Debug info.
|
||||||
self:T(string.format("Airbase %s: Adding runway id=%s, heading=%03d, length=%d m", self:GetName(), runway.idx, runway.heading, runway.length))
|
--self:I(string.format("Airbase %s: Adding runway id=%s, heading=%03d, length=%d m i=%d j=%d", self:GetName(), runway.idx, runway.heading, runway.length, i, j))
|
||||||
|
|
||||||
-- Debug mark
|
-- Debug mark
|
||||||
if mark then
|
if mark then
|
||||||
runway.position:MarkToAll(string.format("Runway %s: true heading=%03d (magvar=%d), length=%d m", runway.idx, runway.heading, magvar, runway.length))
|
runway.position:MarkToAll(string.format("Runway %s: true heading=%03d (magvar=%d), length=%d m, i=%d, j=%d", runway.idx, runway.heading, magvar, runway.length, i, j))
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Add runway.
|
-- Add runway.
|
||||||
@@ -1084,38 +1389,6 @@ function AIRBASE:GetRunwayData(magvar, mark)
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Get inverse runways
|
|
||||||
local inverse={}
|
|
||||||
for _,_runway in pairs(runways) do
|
|
||||||
local r=_runway --#AIRBASE.Runway
|
|
||||||
|
|
||||||
local runway={} --#AIRBASE.Runway
|
|
||||||
runway.heading=r.heading-180
|
|
||||||
if runway.heading<0 then
|
|
||||||
runway.heading=runway.heading+360
|
|
||||||
end
|
|
||||||
runway.idx=string.format("%02d", math.max(0, UTILS.Round((runway.heading-magvar)/10, 0)))
|
|
||||||
runway.length=r.length
|
|
||||||
runway.position=r.endpoint
|
|
||||||
runway.endpoint=r.position
|
|
||||||
|
|
||||||
-- Debug info.
|
|
||||||
self:T(string.format("Airbase %s: Adding runway id=%s, heading=%03d, length=%d m", self:GetName(), runway.idx, runway.heading, runway.length))
|
|
||||||
|
|
||||||
-- Debug mark
|
|
||||||
if mark then
|
|
||||||
runway.position:MarkToAll(string.format("Runway %s: true heading=%03d (magvar=%d), length=%d m", runway.idx, runway.heading, magvar, runway.length))
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Add runway.
|
|
||||||
table.insert(inverse, runway)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Add inverse runway.
|
|
||||||
for _,runway in pairs(inverse) do
|
|
||||||
table.insert(runways, runway)
|
|
||||||
end
|
|
||||||
|
|
||||||
return runways
|
return runways
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1170,7 +1443,7 @@ function AIRBASE:GetActiveRunway(magvar)
|
|||||||
local dot=UTILS.VecDot(Vwind, Vrunway)
|
local dot=UTILS.VecDot(Vwind, Vrunway)
|
||||||
|
|
||||||
-- Debug.
|
-- Debug.
|
||||||
--env.info(string.format("runway=%03d° dot=%.3f", runway.heading, dot))
|
--env.info(string.format("runway=%03d° dot=%.3f", runway.heading, dot))
|
||||||
|
|
||||||
-- New min?
|
-- New min?
|
||||||
if dotmin==nil or dot<dotmin then
|
if dotmin==nil or dot<dotmin then
|
||||||
@@ -1186,5 +1459,72 @@ function AIRBASE:GetActiveRunway(magvar)
|
|||||||
return runways[iact]
|
return runways[iact]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Function that checks if at leat one unit of a group has been spawned close to a spawn point on the runway.
|
||||||
|
-- @param #AIRBASE self
|
||||||
|
-- @param Wrapper.Group#GROUP group Group to be checked.
|
||||||
|
-- @param #number radius Radius around the spawn point to be checked. Default is 50 m.
|
||||||
|
-- @param #boolean despawn If true, the group is destroyed.
|
||||||
|
-- @return #boolean True if group is within radius around spawn points on runway.
|
||||||
|
function AIRBASE:CheckOnRunWay(group, radius, despawn)
|
||||||
|
|
||||||
|
-- Default radius.
|
||||||
|
radius=radius or 50
|
||||||
|
|
||||||
|
-- We only check at real airbases (not FARPS or ships).
|
||||||
|
if self:GetAirbaseCategory()~=Airbase.Category.AIRDROME then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
if group and group:IsAlive() then
|
||||||
|
|
||||||
|
-- Debug.
|
||||||
|
self:T(string.format("%s, checking if group %s is on runway?",self:GetName(), group:GetName()))
|
||||||
|
|
||||||
|
-- Get coordinates on runway.
|
||||||
|
local runwaypoints=self:GetParkingSpotsCoordinates(AIRBASE.TerminalType.Runway)
|
||||||
|
|
||||||
|
-- Get units of group.
|
||||||
|
local units=group:GetUnits()
|
||||||
|
|
||||||
|
-- Loop over units.
|
||||||
|
for _,_unit in pairs(units) do
|
||||||
|
|
||||||
|
local unit=_unit --Wrapper.Unit#UNIT
|
||||||
|
|
||||||
|
-- Check if unit is alive and not in air.
|
||||||
|
if unit and unit:IsAlive() and not unit:InAir() then
|
||||||
|
self:T(string.format("%s, checking if unit %s is on runway?",self:GetName(), unit:GetName()))
|
||||||
|
|
||||||
|
-- Loop over runway spawn points.
|
||||||
|
for _i,_coord in pairs(runwaypoints) do
|
||||||
|
|
||||||
|
-- Distance between unit and spawn pos.
|
||||||
|
local dist=unit:GetCoordinate():Get2DDistance(_coord)
|
||||||
|
|
||||||
|
-- Mark unit spawn points for debugging.
|
||||||
|
--unit:GetCoordinate():MarkToAll(string.format("unit %s distance to rwy %d = %d",unit:GetName(),_i, dist))
|
||||||
|
|
||||||
|
-- Check if unit is withing radius.
|
||||||
|
if dist<radius then
|
||||||
|
self:E(string.format("%s, unit %s of group %s was spawned on runway #%d. Distance %.1f < radius %.1f m. Despawn = %s.", self:GetName(), unit:GetName(), group:GetName(),_i, dist, radius, tostring(despawn)))
|
||||||
|
--unit:FlareRed()
|
||||||
|
if despawn then
|
||||||
|
group:Destroy(true)
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
else
|
||||||
|
self:T(string.format("%s, unit %s of group %s was NOT spawned on runway #%d. Distance %.1f > radius %.1f m. Despawn = %s.", self:GetName(), unit:GetName(), group:GetName(),_i, dist, radius, tostring(despawn)))
|
||||||
|
--unit:FlareGreen()
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
else
|
||||||
|
self:T(string.format("%s, checking if unit %s of group %s is on runway. Unit is NOT alive.",self:GetName(), unit:GetName(), group:GetName()))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
self:T(string.format("%s, checking if group %s is on runway. Group is NOT alive.",self:GetName(), group:GetName()))
|
||||||
|
end
|
||||||
|
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -173,6 +173,62 @@ GROUPTEMPLATE.Takeoff = {
|
|||||||
[GROUP.Takeoff.Cold] = { "TakeOffParking", "From Parking Area" }
|
[GROUP.Takeoff.Cold] = { "TakeOffParking", "From Parking Area" }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
--- Generalized group attributes. See [DCS attributes](https://wiki.hoggitworld.com/view/DCS_enum_attributes) on hoggit.
|
||||||
|
-- @type GROUP.Attribute
|
||||||
|
-- @field #string AIR_TRANSPORTPLANE Airplane with transport capability. This can be used to transport other assets.
|
||||||
|
-- @field #string AIR_AWACS Airborne Early Warning and Control System.
|
||||||
|
-- @field #string AIR_FIGHTER Fighter, interceptor, ... airplane.
|
||||||
|
-- @field #string AIR_BOMBER Aircraft which can be used for strategic bombing.
|
||||||
|
-- @field #string AIR_TANKER Airplane which can refuel other aircraft.
|
||||||
|
-- @field #string AIR_TRANSPORTHELO Helicopter with transport capability. This can be used to transport other assets.
|
||||||
|
-- @field #string AIR_ATTACKHELO Attack helicopter.
|
||||||
|
-- @field #string AIR_UAV Unpiloted Aerial Vehicle, e.g. drones.
|
||||||
|
-- @field #string AIR_OTHER Any airborne unit that does not fall into any other airborne category.
|
||||||
|
-- @field #string GROUND_APC Infantry carriers, in particular Amoured Personell Carrier. This can be used to transport other assets.
|
||||||
|
-- @field #string GROUND_TRUCK Unarmed ground vehicles, which has the DCS "Truck" attribute.
|
||||||
|
-- @field #string GROUND_INFANTRY Ground infantry assets.
|
||||||
|
-- @field #string GROUND_ARTILLERY Artillery assets.
|
||||||
|
-- @field #string GROUND_TANK Tanks (modern or old).
|
||||||
|
-- @field #string GROUND_TRAIN Trains. Not that trains are **not** yet properly implemented in DCS and cannot be used currently.
|
||||||
|
-- @field #string GROUND_EWR Early Warning Radar.
|
||||||
|
-- @field #string GROUND_AAA Anti-Aircraft Artillery.
|
||||||
|
-- @field #string GROUND_SAM Surface-to-Air Missile system or components.
|
||||||
|
-- @field #string GROUND_OTHER Any ground unit that does not fall into any other ground category.
|
||||||
|
-- @field #string NAVAL_AIRCRAFTCARRIER Aircraft carrier.
|
||||||
|
-- @field #string NAVAL_WARSHIP War ship, i.e. cruisers, destroyers, firgates and corvettes.
|
||||||
|
-- @field #string NAVAL_ARMEDSHIP Any armed ship that is not an aircraft carrier, a cruiser, destroyer, firgatte or corvette.
|
||||||
|
-- @field #string NAVAL_UNARMEDSHIP Any unarmed naval vessel.
|
||||||
|
-- @field #string NAVAL_OTHER Any naval unit that does not fall into any other naval category.
|
||||||
|
-- @field #string OTHER_UNKNOWN Anything that does not fall into any other category.
|
||||||
|
GROUP.Attribute = {
|
||||||
|
AIR_TRANSPORTPLANE="Air_TransportPlane",
|
||||||
|
AIR_AWACS="Air_AWACS",
|
||||||
|
AIR_FIGHTER="Air_Fighter",
|
||||||
|
AIR_BOMBER="Air_Bomber",
|
||||||
|
AIR_TANKER="Air_Tanker",
|
||||||
|
AIR_TRANSPORTHELO="Air_TransportHelo",
|
||||||
|
AIR_ATTACKHELO="Air_AttackHelo",
|
||||||
|
AIR_UAV="Air_UAV",
|
||||||
|
AIR_OTHER="Air_OtherAir",
|
||||||
|
GROUND_APC="Ground_APC",
|
||||||
|
GROUND_TRUCK="Ground_Truck",
|
||||||
|
GROUND_INFANTRY="Ground_Infantry",
|
||||||
|
GROUND_ARTILLERY="Ground_Artillery",
|
||||||
|
GROUND_TANK="Ground_Tank",
|
||||||
|
GROUND_TRAIN="Ground_Train",
|
||||||
|
GROUND_EWR="Ground_EWR",
|
||||||
|
GROUND_AAA="Ground_AAA",
|
||||||
|
GROUND_SAM="Ground_SAM",
|
||||||
|
GROUND_OTHER="Ground_OtherGround",
|
||||||
|
NAVAL_AIRCRAFTCARRIER="Naval_AircraftCarrier",
|
||||||
|
NAVAL_WARSHIP="Naval_WarShip",
|
||||||
|
NAVAL_ARMEDSHIP="Naval_ArmedShip",
|
||||||
|
NAVAL_UNARMEDSHIP="Naval_UnarmedShip",
|
||||||
|
NAVAL_OTHER="Naval_OtherNaval",
|
||||||
|
OTHER_UNKNOWN="Other_Unknown",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
--- Create a new GROUP from a given GroupTemplate as a parameter.
|
--- Create a new GROUP from a given GroupTemplate as a parameter.
|
||||||
-- Note that the GroupTemplate is NOT spawned into the mission.
|
-- Note that the GroupTemplate is NOT spawned into the mission.
|
||||||
-- It is merely added to the @{Core.Database}.
|
-- It is merely added to the @{Core.Database}.
|
||||||
@@ -205,7 +261,9 @@ end
|
|||||||
-- @param #string GroupName The Group name
|
-- @param #string GroupName The Group name
|
||||||
-- @return #GROUP self
|
-- @return #GROUP self
|
||||||
function GROUP:Register( GroupName )
|
function GROUP:Register( GroupName )
|
||||||
|
|
||||||
local self = BASE:Inherit( self, CONTROLLABLE:New( GroupName ) ) -- #GROUP
|
local self = BASE:Inherit( self, CONTROLLABLE:New( GroupName ) ) -- #GROUP
|
||||||
|
|
||||||
self.GroupName = GroupName
|
self.GroupName = GroupName
|
||||||
|
|
||||||
self:SetEventPriority( 4 )
|
self:SetEventPriority( 4 )
|
||||||
@@ -260,9 +318,12 @@ function GROUP:GetPositionVec3() -- Overridden from POSITIONABLE:GetPositionVec3
|
|||||||
local DCSPositionable = self:GetDCSObject()
|
local DCSPositionable = self:GetDCSObject()
|
||||||
|
|
||||||
if DCSPositionable then
|
if DCSPositionable then
|
||||||
local PositionablePosition = DCSPositionable:getUnits()[1]:getPosition().p
|
local unit = DCSPositionable:getUnits()[1]
|
||||||
|
if unit then
|
||||||
|
local PositionablePosition = unit:getPosition().p
|
||||||
self:T3( PositionablePosition )
|
self:T3( PositionablePosition )
|
||||||
return PositionablePosition
|
return PositionablePosition
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -310,9 +371,11 @@ function GROUP:IsActive()
|
|||||||
local DCSGroup = self:GetDCSObject() -- DCS#Group
|
local DCSGroup = self:GetDCSObject() -- DCS#Group
|
||||||
|
|
||||||
if DCSGroup then
|
if DCSGroup then
|
||||||
|
local unit = DCSGroup:getUnit(1)
|
||||||
local GroupIsActive = DCSGroup:getUnit(1):isActive()
|
if unit then
|
||||||
|
local GroupIsActive = unit:isActive()
|
||||||
return GroupIsActive
|
return GroupIsActive
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -379,9 +442,16 @@ function GROUP:Destroy( GenerateEvent, delay )
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Returns category of the DCS Group.
|
--- Returns category of the DCS Group. Returns one of
|
||||||
|
--
|
||||||
|
-- * Group.Category.AIRPLANE
|
||||||
|
-- * Group.Category.HELICOPTER
|
||||||
|
-- * Group.Category.GROUND
|
||||||
|
-- * Group.Category.SHIP
|
||||||
|
-- * Group.Category.TRAIN
|
||||||
|
--
|
||||||
-- @param #GROUP self
|
-- @param #GROUP self
|
||||||
-- @return DCS#Group.Category The category ID
|
-- @return DCS#Group.Category The category ID.
|
||||||
function GROUP:GetCategory()
|
function GROUP:GetCategory()
|
||||||
self:F2( self.GroupName )
|
self:F2( self.GroupName )
|
||||||
|
|
||||||
@@ -397,7 +467,7 @@ end
|
|||||||
|
|
||||||
--- Returns the category name of the #GROUP.
|
--- Returns the category name of the #GROUP.
|
||||||
-- @param #GROUP self
|
-- @param #GROUP self
|
||||||
-- @return #string Category name = Helicopter, Airplane, Ground Unit, Ship
|
-- @return #string Category name = Helicopter, Airplane, Ground Unit, Ship, Train.
|
||||||
function GROUP:GetCategoryName()
|
function GROUP:GetCategoryName()
|
||||||
self:F2( self.GroupName )
|
self:F2( self.GroupName )
|
||||||
|
|
||||||
@@ -408,6 +478,7 @@ function GROUP:GetCategoryName()
|
|||||||
[Group.Category.HELICOPTER] = "Helicopter",
|
[Group.Category.HELICOPTER] = "Helicopter",
|
||||||
[Group.Category.GROUND] = "Ground Unit",
|
[Group.Category.GROUND] = "Ground Unit",
|
||||||
[Group.Category.SHIP] = "Ship",
|
[Group.Category.SHIP] = "Ship",
|
||||||
|
[Group.Category.TRAIN] = "Train",
|
||||||
}
|
}
|
||||||
local GroupCategory = DCSGroup:getCategory()
|
local GroupCategory = DCSGroup:getCategory()
|
||||||
self:T3( GroupCategory )
|
self:T3( GroupCategory )
|
||||||
@@ -599,14 +670,15 @@ end
|
|||||||
-- @param #number UnitNumber The number of the UNIT wrapper class to be returned.
|
-- @param #number UnitNumber The number of the UNIT wrapper class to be returned.
|
||||||
-- @return Wrapper.Unit#UNIT The UNIT wrapper class.
|
-- @return Wrapper.Unit#UNIT The UNIT wrapper class.
|
||||||
function GROUP:GetUnit( UnitNumber )
|
function GROUP:GetUnit( UnitNumber )
|
||||||
self:F3( { self.GroupName, UnitNumber } )
|
|
||||||
|
|
||||||
local DCSGroup = self:GetDCSObject()
|
local DCSGroup = self:GetDCSObject()
|
||||||
|
|
||||||
if DCSGroup then
|
if DCSGroup then
|
||||||
|
|
||||||
local DCSUnit = DCSGroup:getUnit( UnitNumber )
|
local DCSUnit = DCSGroup:getUnit( UnitNumber )
|
||||||
local UnitFound = UNIT:Find( DCSGroup:getUnit( UnitNumber ) )
|
|
||||||
self:T2( UnitFound )
|
local UnitFound = UNIT:Find(DCSUnit)
|
||||||
|
|
||||||
return UnitFound
|
return UnitFound
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -619,13 +691,11 @@ end
|
|||||||
-- @param #number UnitNumber The number of the DCS Unit to be returned.
|
-- @param #number UnitNumber The number of the DCS Unit to be returned.
|
||||||
-- @return DCS#Unit The DCS Unit.
|
-- @return DCS#Unit The DCS Unit.
|
||||||
function GROUP:GetDCSUnit( UnitNumber )
|
function GROUP:GetDCSUnit( UnitNumber )
|
||||||
self:F3( { self.GroupName, UnitNumber } )
|
|
||||||
|
|
||||||
local DCSGroup = self:GetDCSObject()
|
local DCSGroup=self:GetDCSObject()
|
||||||
|
|
||||||
if DCSGroup then
|
if DCSGroup then
|
||||||
local DCSUnitFound = DCSGroup:getUnit( UnitNumber )
|
local DCSUnitFound=DCSGroup:getUnit( UnitNumber )
|
||||||
self:T3( DCSUnitFound )
|
|
||||||
return DCSUnitFound
|
return DCSUnitFound
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -637,14 +707,14 @@ end
|
|||||||
-- @param #GROUP self
|
-- @param #GROUP self
|
||||||
-- @return #number The DCS Group size.
|
-- @return #number The DCS Group size.
|
||||||
function GROUP:GetSize()
|
function GROUP:GetSize()
|
||||||
self:F3( { self.GroupName } )
|
|
||||||
local DCSGroup = self:GetDCSObject()
|
local DCSGroup = self:GetDCSObject()
|
||||||
|
|
||||||
if DCSGroup then
|
if DCSGroup then
|
||||||
|
|
||||||
local GroupSize = DCSGroup:getSize()
|
local GroupSize = DCSGroup:getSize()
|
||||||
|
|
||||||
if GroupSize then
|
if GroupSize then
|
||||||
self:T3( GroupSize )
|
|
||||||
return GroupSize
|
return GroupSize
|
||||||
else
|
else
|
||||||
return 0
|
return 0
|
||||||
@@ -806,11 +876,16 @@ end
|
|||||||
|
|
||||||
--- Activates a late activated GROUP.
|
--- Activates a late activated GROUP.
|
||||||
-- @param #GROUP self
|
-- @param #GROUP self
|
||||||
|
-- @param #number delay Delay in seconds, before the group is activated.
|
||||||
-- @return #GROUP self
|
-- @return #GROUP self
|
||||||
function GROUP:Activate()
|
function GROUP:Activate(delay)
|
||||||
self:F2( { self.GroupName } )
|
self:F2( { self.GroupName } )
|
||||||
trigger.action.activateGroup( self:GetDCSObject() )
|
if delay and delay>0 then
|
||||||
return self:GetDCSObject()
|
self:ScheduleOnce(delay, GROUP.Activate, self)
|
||||||
|
else
|
||||||
|
trigger.action.activateGroup( self:GetDCSObject() )
|
||||||
|
end
|
||||||
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -872,24 +947,31 @@ end
|
|||||||
-- @param #GROUP self
|
-- @param #GROUP self
|
||||||
-- @return DCS#Vec2 Current Vec2 point of the first DCS Unit of the DCS Group.
|
-- @return DCS#Vec2 Current Vec2 point of the first DCS Unit of the DCS Group.
|
||||||
function GROUP:GetVec2()
|
function GROUP:GetVec2()
|
||||||
self:F2( self.GroupName )
|
|
||||||
|
|
||||||
local UnitPoint = self:GetUnit(1)
|
local Unit=self:GetUnit(1)
|
||||||
UnitPoint:GetVec2()
|
|
||||||
local GroupPointVec2 = UnitPoint:GetVec2()
|
if Unit then
|
||||||
self:T3( GroupPointVec2 )
|
local vec2=Unit:GetVec2()
|
||||||
return GroupPointVec2
|
return vec2
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Returns the current Vec3 vector of the first DCS Unit in the GROUP.
|
--- Returns the current Vec3 vector of the first DCS Unit in the GROUP.
|
||||||
-- @param #GROUP self
|
-- @param #GROUP self
|
||||||
-- @return DCS#Vec3 Current Vec3 of the first DCS Unit of the GROUP.
|
-- @return DCS#Vec3 Current Vec3 of the first DCS Unit of the GROUP.
|
||||||
function GROUP:GetVec3()
|
function GROUP:GetVec3()
|
||||||
self:F2( self.GroupName )
|
|
||||||
|
|
||||||
local GroupVec3 = self:GetUnit(1):GetVec3()
|
-- Get first unit.
|
||||||
self:T3( GroupVec3 )
|
local unit=self:GetUnit(1)
|
||||||
return GroupVec3
|
|
||||||
|
if unit then
|
||||||
|
local vec3=unit:GetVec3()
|
||||||
|
return vec3
|
||||||
|
end
|
||||||
|
|
||||||
|
self:E("ERROR: Cannot get Vec3 of group "..tostring(self.GroupName))
|
||||||
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Returns a POINT_VEC2 object indicating the point in 2D of the first UNIT of the GROUP within the mission.
|
--- Returns a POINT_VEC2 object indicating the point in 2D of the first UNIT of the GROUP within the mission.
|
||||||
@@ -916,13 +998,11 @@ end
|
|||||||
-- @param Wrapper.Group#GROUP self
|
-- @param Wrapper.Group#GROUP self
|
||||||
-- @return Core.Point#COORDINATE The COORDINATE of the GROUP.
|
-- @return Core.Point#COORDINATE The COORDINATE of the GROUP.
|
||||||
function GROUP:GetCoordinate()
|
function GROUP:GetCoordinate()
|
||||||
self:F2( self.PositionableName )
|
|
||||||
|
|
||||||
local FirstUnit = self:GetUnit(1)
|
local FirstUnit = self:GetUnit(1)
|
||||||
|
|
||||||
if FirstUnit then
|
if FirstUnit then
|
||||||
local FirstUnitCoordinate = FirstUnit:GetCoordinate()
|
local FirstUnitCoordinate = FirstUnit:GetCoordinate()
|
||||||
self:T3(FirstUnitCoordinate)
|
|
||||||
return FirstUnitCoordinate
|
return FirstUnitCoordinate
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -965,11 +1045,16 @@ function GROUP:GetHeading()
|
|||||||
local GroupSize = self:GetSize()
|
local GroupSize = self:GetSize()
|
||||||
local HeadingAccumulator = 0
|
local HeadingAccumulator = 0
|
||||||
|
|
||||||
|
local n=0
|
||||||
if GroupSize then
|
if GroupSize then
|
||||||
for i = 1, GroupSize do
|
for i = 1, GroupSize do
|
||||||
HeadingAccumulator = HeadingAccumulator + self:GetUnit(i):GetHeading()
|
local unit=self:GetUnit(i)
|
||||||
|
if unit and unit:IsAlive() then
|
||||||
|
HeadingAccumulator = HeadingAccumulator + unit:GetHeading()
|
||||||
|
n=n+1
|
||||||
|
end
|
||||||
end
|
end
|
||||||
return math.floor(HeadingAccumulator / GroupSize)
|
return math.floor(HeadingAccumulator / n)
|
||||||
end
|
end
|
||||||
|
|
||||||
BASE:E( { "Cannot GetHeading", Group = self, Alive = self:IsAlive() } )
|
BASE:E( { "Cannot GetHeading", Group = self, Alive = self:IsAlive() } )
|
||||||
@@ -1046,8 +1131,76 @@ function GROUP:GetFuel()
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Get the number of shells, rockets, bombs and missiles the whole group currently has.
|
||||||
|
-- @param #GROUP self
|
||||||
|
-- @return #number Total amount of ammo the group has left. This is the sum of shells, rockets, bombs and missiles of all units.
|
||||||
|
-- @return #number Number of shells left.
|
||||||
|
-- @return #number Number of rockets left.
|
||||||
|
-- @return #number Number of bombs left.
|
||||||
|
-- @return #number Number of missiles left.
|
||||||
|
function GROUP:GetAmmunition()
|
||||||
|
self:F( self.ControllableName )
|
||||||
|
|
||||||
|
local DCSControllable = self:GetDCSObject()
|
||||||
|
|
||||||
|
local Ntot=0
|
||||||
|
local Nshells=0
|
||||||
|
local Nrockets=0
|
||||||
|
local Nmissiles=0
|
||||||
|
|
||||||
|
if DCSControllable then
|
||||||
|
|
||||||
|
-- Loop over units.
|
||||||
|
for UnitID, UnitData in pairs( self:GetUnits() ) do
|
||||||
|
local Unit = UnitData -- Wrapper.Unit#UNIT
|
||||||
|
|
||||||
|
-- Get ammo of the unit
|
||||||
|
local ntot, nshells, nrockets, nmissiles = Unit:GetAmmunition()
|
||||||
|
|
||||||
|
Ntot=Ntot+ntot
|
||||||
|
Nshells=Nshells+nshells
|
||||||
|
Nrockets=Nrockets+nrockets
|
||||||
|
Nmissiles=Nmissiles+nmissiles
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
return Ntot, Nshells, Nrockets, Nmissiles
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
do -- Is Zone methods
|
do -- Is Zone methods
|
||||||
|
|
||||||
|
|
||||||
|
--- Check if any unit of a group is inside a @{Zone}.
|
||||||
|
-- @param #GROUP self
|
||||||
|
-- @param Core.Zone#ZONE_BASE Zone The zone to test.
|
||||||
|
-- @return #boolean Returns `true` if *at least one unit* is inside the zone or `false` if *no* unit is inside.
|
||||||
|
function GROUP:IsInZone( Zone )
|
||||||
|
|
||||||
|
if self:IsAlive() then
|
||||||
|
|
||||||
|
for UnitID, UnitData in pairs(self:GetUnits()) do
|
||||||
|
local Unit = UnitData -- Wrapper.Unit#UNIT
|
||||||
|
|
||||||
|
-- Get 2D vector. That's all we need for the zone check.
|
||||||
|
local vec2=Unit:GetVec2()
|
||||||
|
|
||||||
|
if Zone:IsVec2InZone(vec2) then
|
||||||
|
return true -- At least one unit is in the zone. That is enough.
|
||||||
|
else
|
||||||
|
-- This one is not but another could be.
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
--- Returns true if all units of the group are within a @{Zone}.
|
--- Returns true if all units of the group are within a @{Zone}.
|
||||||
-- @param #GROUP self
|
-- @param #GROUP self
|
||||||
-- @param Core.Zone#ZONE_BASE Zone The zone to test.
|
-- @param Core.Zone#ZONE_BASE Zone The zone to test.
|
||||||
@@ -1639,7 +1792,7 @@ function GROUP:Respawn( Template, Reset )
|
|||||||
self:F(GroupUnit:GetName())
|
self:F(GroupUnit:GetName())
|
||||||
|
|
||||||
if GroupUnit:IsAlive() then
|
if GroupUnit:IsAlive() then
|
||||||
self:F("Alive")
|
self:I("FF Alive")
|
||||||
|
|
||||||
-- Get unit position vector.
|
-- Get unit position vector.
|
||||||
local GroupUnitVec3 = GroupUnit:GetVec3()
|
local GroupUnitVec3 = GroupUnit:GetVec3()
|
||||||
@@ -1683,7 +1836,7 @@ function GROUP:Respawn( Template, Reset )
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
else -- Reset=false or nil
|
elseif Reset==false then -- Reset=false or nil
|
||||||
|
|
||||||
-- Loop over template units.
|
-- Loop over template units.
|
||||||
for UnitID, TemplateUnitData in pairs( Template.units ) do
|
for UnitID, TemplateUnitData in pairs( Template.units ) do
|
||||||
@@ -1725,6 +1878,29 @@ function GROUP:Respawn( Template, Reset )
|
|||||||
self:F( { UnitID, Template.units[UnitID], Template.units[UnitID] } )
|
self:F( { UnitID, Template.units[UnitID], Template.units[UnitID] } )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
local units=self:GetUnits()
|
||||||
|
|
||||||
|
-- Loop over template units.
|
||||||
|
for UnitID, Unit in pairs(Template.units) do
|
||||||
|
|
||||||
|
for _,_unit in pairs(units) do
|
||||||
|
local unit=_unit --Wrapper.Unit#UNIT
|
||||||
|
|
||||||
|
if unit:GetName()==Unit.name then
|
||||||
|
local coord=unit:GetCoordinate()
|
||||||
|
local heading=unit:GetHeading()
|
||||||
|
Unit.x=coord.x
|
||||||
|
Unit.y=coord.z
|
||||||
|
Unit.alt=coord.y
|
||||||
|
Unit.heading=math.rad(heading)
|
||||||
|
Unit.psi=-Unit.heading
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
@@ -1804,7 +1980,7 @@ function GROUP:RespawnAtCurrentAirbase(SpawnTemplate, Takeoff, Uncontrolled) --
|
|||||||
|
|
||||||
-- Aibase id and category.
|
-- Aibase id and category.
|
||||||
local AirbaseID = airbase:GetID()
|
local AirbaseID = airbase:GetID()
|
||||||
local AirbaseCategory = airbase:GetDesc().category
|
local AirbaseCategory = airbase:GetAirbaseCategory()
|
||||||
|
|
||||||
if AirbaseCategory == Airbase.Category.SHIP or AirbaseCategory == Airbase.Category.HELIPAD then
|
if AirbaseCategory == Airbase.Category.SHIP or AirbaseCategory == Airbase.Category.HELIPAD then
|
||||||
SpawnPoint.linkUnit = AirbaseID
|
SpawnPoint.linkUnit = AirbaseID
|
||||||
@@ -1959,6 +2135,7 @@ end
|
|||||||
|
|
||||||
--- Calculate the maxium A2G threat level of the Group.
|
--- Calculate the maxium A2G threat level of the Group.
|
||||||
-- @param #GROUP self
|
-- @param #GROUP self
|
||||||
|
-- @return #number Number between 0 and 10.
|
||||||
function GROUP:CalculateThreatLevelA2G()
|
function GROUP:CalculateThreatLevelA2G()
|
||||||
|
|
||||||
local MaxThreatLevelA2G = 0
|
local MaxThreatLevelA2G = 0
|
||||||
@@ -1974,6 +2151,25 @@ function GROUP:CalculateThreatLevelA2G()
|
|||||||
return MaxThreatLevelA2G
|
return MaxThreatLevelA2G
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Get threat level of the group.
|
||||||
|
-- @param #GROUP self
|
||||||
|
-- @return #number Max threat level (a number between 0 and 10).
|
||||||
|
function GROUP:GetThreatLevel()
|
||||||
|
|
||||||
|
local threatlevelMax = 0
|
||||||
|
for UnitName, UnitData in pairs(self:GetUnits()) do
|
||||||
|
local ThreatUnit = UnitData -- Wrapper.Unit#UNIT
|
||||||
|
|
||||||
|
local threatlevel = ThreatUnit:GetThreatLevel()
|
||||||
|
if threatlevel > threatlevelMax then
|
||||||
|
threatlevelMax=threatlevel
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return threatlevelMax
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Returns true if the first unit of the GROUP is in the air.
|
--- Returns true if the first unit of the GROUP is in the air.
|
||||||
-- @param Wrapper.Group#GROUP self
|
-- @param Wrapper.Group#GROUP self
|
||||||
-- @return #boolean true if in the first unit of the group is in the air or #nil if the GROUP is not existing or not alive.
|
-- @return #boolean true if in the first unit of the group is in the air or #nil if the GROUP is not existing or not alive.
|
||||||
@@ -2052,6 +2248,117 @@ function GROUP:GetDCSDesc(n)
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Get the generalized attribute of a self.
|
||||||
|
-- Note that for a heterogenious self, the attribute is determined from the attribute of the first unit!
|
||||||
|
-- @param #GROUP self
|
||||||
|
-- @return #string Generalized attribute of the self.
|
||||||
|
function GROUP:GetAttribute()
|
||||||
|
|
||||||
|
-- Default
|
||||||
|
local attribute=GROUP.Attribute.OTHER_UNKNOWN --#GROUP.Attribute
|
||||||
|
|
||||||
|
if self then
|
||||||
|
|
||||||
|
-----------
|
||||||
|
--- Air ---
|
||||||
|
-----------
|
||||||
|
-- Planes
|
||||||
|
local transportplane=self:HasAttribute("Transports") and self:HasAttribute("Planes")
|
||||||
|
local awacs=self:HasAttribute("AWACS")
|
||||||
|
local fighter=self:HasAttribute("Fighters") or self:HasAttribute("Interceptors") or self:HasAttribute("Multirole fighters") or (self:HasAttribute("Bombers") and not self:HasAttribute("Strategic bombers"))
|
||||||
|
local bomber=self:HasAttribute("Strategic bombers")
|
||||||
|
local tanker=self:HasAttribute("Tankers")
|
||||||
|
local uav=self:HasAttribute("UAVs")
|
||||||
|
-- Helicopters
|
||||||
|
local transporthelo=self:HasAttribute("Transport helicopters")
|
||||||
|
local attackhelicopter=self:HasAttribute("Attack helicopters")
|
||||||
|
|
||||||
|
--------------
|
||||||
|
--- Ground ---
|
||||||
|
--------------
|
||||||
|
-- Ground
|
||||||
|
local apc=self:HasAttribute("Infantry carriers")
|
||||||
|
local truck=self:HasAttribute("Trucks") and self:GetCategory()==Group.Category.GROUND
|
||||||
|
local infantry=self:HasAttribute("Infantry")
|
||||||
|
local artillery=self:HasAttribute("Artillery")
|
||||||
|
local tank=self:HasAttribute("Old Tanks") or self:HasAttribute("Modern Tanks")
|
||||||
|
local aaa=self:HasAttribute("AAA")
|
||||||
|
local ewr=self:HasAttribute("EWR")
|
||||||
|
local sam=self:HasAttribute("SAM elements") and (not self:HasAttribute("AAA"))
|
||||||
|
-- Train
|
||||||
|
local train=self:GetCategory()==Group.Category.TRAIN
|
||||||
|
|
||||||
|
-------------
|
||||||
|
--- Naval ---
|
||||||
|
-------------
|
||||||
|
-- Ships
|
||||||
|
local aircraftcarrier=self:HasAttribute("Aircraft Carriers")
|
||||||
|
local warship=self:HasAttribute("Heavy armed ships")
|
||||||
|
local armedship=self:HasAttribute("Armed ships")
|
||||||
|
local unarmedship=self:HasAttribute("Unarmed ships")
|
||||||
|
|
||||||
|
|
||||||
|
-- Define attribute. Order is important.
|
||||||
|
if transportplane then
|
||||||
|
attribute=GROUP.Attribute.AIR_TRANSPORTPLANE
|
||||||
|
elseif awacs then
|
||||||
|
attribute=GROUP.Attribute.AIR_AWACS
|
||||||
|
elseif fighter then
|
||||||
|
attribute=GROUP.Attribute.AIR_FIGHTER
|
||||||
|
elseif bomber then
|
||||||
|
attribute=GROUP.Attribute.AIR_BOMBER
|
||||||
|
elseif tanker then
|
||||||
|
attribute=GROUP.Attribute.AIR_TANKER
|
||||||
|
elseif transporthelo then
|
||||||
|
attribute=GROUP.Attribute.AIR_TRANSPORTHELO
|
||||||
|
elseif attackhelicopter then
|
||||||
|
attribute=GROUP.Attribute.AIR_ATTACKHELO
|
||||||
|
elseif uav then
|
||||||
|
attribute=GROUP.Attribute.AIR_UAV
|
||||||
|
elseif apc then
|
||||||
|
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
|
||||||
|
attribute=GROUP.Attribute.GROUND_EWR
|
||||||
|
elseif sam then
|
||||||
|
attribute=GROUP.Attribute.GROUND_SAM
|
||||||
|
elseif truck then
|
||||||
|
attribute=GROUP.Attribute.GROUND_TRUCK
|
||||||
|
elseif train then
|
||||||
|
attribute=GROUP.Attribute.GROUND_TRAIN
|
||||||
|
elseif aircraftcarrier then
|
||||||
|
attribute=GROUP.Attribute.NAVAL_AIRCRAFTCARRIER
|
||||||
|
elseif warship then
|
||||||
|
attribute=GROUP.Attribute.NAVAL_WARSHIP
|
||||||
|
elseif armedship then
|
||||||
|
attribute=GROUP.Attribute.NAVAL_ARMEDSHIP
|
||||||
|
elseif unarmedship then
|
||||||
|
attribute=GROUP.Attribute.NAVAL_UNARMEDSHIP
|
||||||
|
else
|
||||||
|
if self:IsGround() then
|
||||||
|
attribute=GROUP.Attribute.GROUND_OTHER
|
||||||
|
elseif self:IsShip() then
|
||||||
|
attribute=GROUP.Attribute.NAVAL_OTHER
|
||||||
|
elseif self:IsAir() then
|
||||||
|
attribute=GROUP.Attribute.AIR_OTHER
|
||||||
|
else
|
||||||
|
attribute=GROUP.Attribute.OTHER_UNKNOWN
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return attribute
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
do -- Route methods
|
do -- Route methods
|
||||||
|
|
||||||
--- (AIR) Return the Group to an @{Wrapper.Airbase#AIRBASE}.
|
--- (AIR) Return the Group to an @{Wrapper.Airbase#AIRBASE}.
|
||||||
|
|||||||
@@ -90,7 +90,6 @@ end
|
|||||||
--- Returns the type name of the DCS Identifiable.
|
--- Returns the type name of the DCS Identifiable.
|
||||||
-- @param #IDENTIFIABLE self
|
-- @param #IDENTIFIABLE self
|
||||||
-- @return #string The type name of the DCS Identifiable.
|
-- @return #string The type name of the DCS Identifiable.
|
||||||
-- @return #nil The DCS Identifiable is not existing or alive.
|
|
||||||
function IDENTIFIABLE:GetTypeName()
|
function IDENTIFIABLE:GetTypeName()
|
||||||
self:F2( self.IdentifiableName )
|
self:F2( self.IdentifiableName )
|
||||||
|
|
||||||
@@ -107,9 +106,17 @@ function IDENTIFIABLE:GetTypeName()
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Returns category of the DCS Identifiable.
|
--- Returns object category of the DCS Identifiable. One of
|
||||||
|
--
|
||||||
|
-- * Object.Category.UNIT = 1
|
||||||
|
-- * Object.Category.WEAPON = 2
|
||||||
|
-- * Object.Category.STATIC = 3
|
||||||
|
-- * Object.Category.BASE = 4
|
||||||
|
-- * Object.Category.SCENERY = 5
|
||||||
|
-- * Object.Category.Cargo = 6
|
||||||
|
--
|
||||||
-- @param #IDENTIFIABLE self
|
-- @param #IDENTIFIABLE self
|
||||||
-- @return DCS#Object.Category The category ID
|
-- @return DCS#Object.Category The category ID, i.e. a number.
|
||||||
function IDENTIFIABLE:GetCategory()
|
function IDENTIFIABLE:GetCategory()
|
||||||
self:F2( self.ObjectName )
|
self:F2( self.ObjectName )
|
||||||
|
|
||||||
@@ -168,20 +175,13 @@ function IDENTIFIABLE:GetCoalitionName()
|
|||||||
local DCSIdentifiable = self:GetDCSObject()
|
local DCSIdentifiable = self:GetDCSObject()
|
||||||
|
|
||||||
if DCSIdentifiable then
|
if DCSIdentifiable then
|
||||||
|
|
||||||
|
-- Get coaliton ID.
|
||||||
local IdentifiableCoalition = DCSIdentifiable:getCoalition()
|
local IdentifiableCoalition = DCSIdentifiable:getCoalition()
|
||||||
self:T3( IdentifiableCoalition )
|
self:T3( IdentifiableCoalition )
|
||||||
|
|
||||||
if IdentifiableCoalition == coalition.side.BLUE then
|
return UTILS.GetCoalitionName(IdentifiableCoalition)
|
||||||
return "Blue"
|
|
||||||
end
|
|
||||||
|
|
||||||
if IdentifiableCoalition == coalition.side.RED then
|
|
||||||
return "Red"
|
|
||||||
end
|
|
||||||
|
|
||||||
if IdentifiableCoalition == coalition.side.NEUTRAL then
|
|
||||||
return "Neutral"
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
self:F( self.ClassName .. " " .. self.IdentifiableName .. " not found!" )
|
self:F( self.ClassName .. " " .. self.IdentifiableName .. " not found!" )
|
||||||
|
|||||||
@@ -0,0 +1,776 @@
|
|||||||
|
--- **Wrapper** - Markers On the F10 map.
|
||||||
|
--
|
||||||
|
-- **Main Features:**
|
||||||
|
--
|
||||||
|
-- * Convenient handling of markers via multiple user API functions.
|
||||||
|
-- * Update text and position of marker easily via scripting.
|
||||||
|
-- * Delay creation and removal of markers via (optional) parameters.
|
||||||
|
-- * Retrieve data such as text and coordinate.
|
||||||
|
-- * Marker specific FSM events when a marker is added, removed or changed.
|
||||||
|
-- * Additional FSM events when marker text or position is changed.
|
||||||
|
--
|
||||||
|
-- ===
|
||||||
|
--
|
||||||
|
-- ### Author: **funkyfranky**
|
||||||
|
-- @module Wrapper.Marker
|
||||||
|
-- @image Wrapper_Marker.png
|
||||||
|
|
||||||
|
|
||||||
|
--- Marker class.
|
||||||
|
-- @type MARKER
|
||||||
|
-- @field #string ClassName Name of the class.
|
||||||
|
-- @field #boolean Debug Debug mode. Messages to all about status.
|
||||||
|
-- @field #string lid Class id string for output to DCS log file.
|
||||||
|
-- @field #number mid Marker ID.
|
||||||
|
-- @field Core.Point#COORDINATE coordinate Coordinate of the mark.
|
||||||
|
-- @field #string text Text displayed in the mark panel.
|
||||||
|
-- @field #string message Message dispayed when the mark is added.
|
||||||
|
-- @field #boolean readonly Marker is read-only.
|
||||||
|
-- @field #number coalition Coalition to which the marker is displayed.
|
||||||
|
-- @extends Core.Fsm#FSM
|
||||||
|
|
||||||
|
--- Just because...
|
||||||
|
--
|
||||||
|
-- ===
|
||||||
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
|
-- # The MARKER Class Idea
|
||||||
|
--
|
||||||
|
-- The MARKER class simplifies creating, updating and removing of markers on the F10 map.
|
||||||
|
--
|
||||||
|
-- # Create a Marker
|
||||||
|
--
|
||||||
|
-- -- Create a MARKER object at Batumi with a trivial text.
|
||||||
|
-- local Coordinate=AIRBASE:FindByName("Batumi"):GetCoordinate()
|
||||||
|
-- mymarker=MARKER:New(Coordinate, "I am Batumi Airfield")
|
||||||
|
--
|
||||||
|
-- Now this does **not** show the marker yet. We still need to specifiy to whom it is shown. There are several options, i.e.
|
||||||
|
-- show the marker to everyone, to a speficic coaliton only, or only to a specific group.
|
||||||
|
--
|
||||||
|
-- ## For Everyone
|
||||||
|
--
|
||||||
|
-- If the marker should be visible to everyone, you can use the :ToAll() function.
|
||||||
|
--
|
||||||
|
-- mymarker=MARKER:New(Coordinate, "I am Batumi Airfield"):ToAll()
|
||||||
|
--
|
||||||
|
-- ## For a Coaliton
|
||||||
|
--
|
||||||
|
-- If the maker should be visible to a specific coalition, you can use the :ToCoalition() function.
|
||||||
|
--
|
||||||
|
-- mymarker=MARKER:New(Coordinate, "I am Batumi Airfield"):ToCoaliton(coaliton.side.BLUE)
|
||||||
|
--
|
||||||
|
-- ### To Blue Coaliton
|
||||||
|
--
|
||||||
|
-- ### To Red Coalition
|
||||||
|
--
|
||||||
|
-- This would show the marker only to the Blue coaliton.
|
||||||
|
--
|
||||||
|
-- ## For a Group
|
||||||
|
--
|
||||||
|
--
|
||||||
|
-- # Removing a Marker
|
||||||
|
--
|
||||||
|
--
|
||||||
|
-- # Updating a Marker
|
||||||
|
--
|
||||||
|
-- The marker text and coordinate can be updated easily as shown below.
|
||||||
|
--
|
||||||
|
-- However, note that **updateing involves to remove and recreate the marker if either text or its coordinate is changed**.
|
||||||
|
-- *This is a DCS scripting engine limitation.*
|
||||||
|
--
|
||||||
|
-- ## Update Text
|
||||||
|
--
|
||||||
|
-- If you created a marker "mymarker" as shown above, you can update the dispayed test by
|
||||||
|
--
|
||||||
|
-- mymarker:UpdateText("I am the new text at Batumi")
|
||||||
|
--
|
||||||
|
-- The update can also be delayed by, e.g. 90 seconds, using
|
||||||
|
--
|
||||||
|
-- mymarker:UpdateText("I am the new text at Batumi", 90)
|
||||||
|
--
|
||||||
|
-- ## Update Coordinate
|
||||||
|
--
|
||||||
|
-- If you created a marker "mymarker" as shown above, you can update its coordinate on the F10 map by
|
||||||
|
--
|
||||||
|
-- mymarker:UpdateCoordinate(NewCoordinate)
|
||||||
|
--
|
||||||
|
-- The update can also be delayed by, e.g. 60 seconds, using
|
||||||
|
--
|
||||||
|
-- mymarker:UpdateCoordinate(NewCoordinate, 60)
|
||||||
|
--
|
||||||
|
-- # Retrieve Data
|
||||||
|
--
|
||||||
|
-- The important data as the displayed text and the coordinate of the marker can be retrieved easily.
|
||||||
|
--
|
||||||
|
-- ## Text
|
||||||
|
--
|
||||||
|
-- local text=mymarker:GetText()
|
||||||
|
-- env.info("Marker Text = " .. text)
|
||||||
|
--
|
||||||
|
-- ## Coordinate
|
||||||
|
--
|
||||||
|
-- local Coordinate=mymarker:GetCoordinate()
|
||||||
|
-- env.info("Marker Coordinate LL DSM = " .. Coordinate:ToStringLLDMS())
|
||||||
|
--
|
||||||
|
--
|
||||||
|
-- # FSM Events
|
||||||
|
--
|
||||||
|
-- Moose creates addditonal events, so called FSM event, when markers are added, changed, removed, and text or the coordianteis updated.
|
||||||
|
--
|
||||||
|
-- These events can be captured and used for processing via OnAfter functions as shown below.
|
||||||
|
--
|
||||||
|
-- ## Added
|
||||||
|
--
|
||||||
|
-- ## Changed
|
||||||
|
--
|
||||||
|
-- ## Removed
|
||||||
|
--
|
||||||
|
-- ## TextUpdate
|
||||||
|
--
|
||||||
|
-- ## CoordUpdate
|
||||||
|
--
|
||||||
|
--
|
||||||
|
-- # Examples
|
||||||
|
--
|
||||||
|
--
|
||||||
|
-- @field #MARKER
|
||||||
|
MARKER = {
|
||||||
|
ClassName = "MARKER",
|
||||||
|
Debug = false,
|
||||||
|
lid = nil,
|
||||||
|
mid = nil,
|
||||||
|
coordinate = nil,
|
||||||
|
text = nil,
|
||||||
|
message = nil,
|
||||||
|
readonly = nil,
|
||||||
|
coalition = nil,
|
||||||
|
}
|
||||||
|
|
||||||
|
--- Marker ID. Running number.
|
||||||
|
_MARKERID=0
|
||||||
|
|
||||||
|
--- Marker class version.
|
||||||
|
-- @field #string version
|
||||||
|
MARKER.version="0.1.0"
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-- TODO list
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-- TODO: User "Get" functions. E.g., :GetCoordinate()
|
||||||
|
-- DONE: Add delay to user functions.
|
||||||
|
-- DONE: Handle events.
|
||||||
|
-- DONE: Create FSM events.
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-- Constructor
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- Create a new MARKER class object.
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @param Core.Point#COORDINATE Coordinate Coordinate where to place the marker.
|
||||||
|
-- @param #string Text Text displayed on the mark panel.
|
||||||
|
-- @return #MARKER self
|
||||||
|
function MARKER:New(Coordinate, Text)
|
||||||
|
|
||||||
|
-- Inherit everything from FSM class.
|
||||||
|
local self=BASE:Inherit(self, FSM:New()) -- #MARKER
|
||||||
|
|
||||||
|
self.coordinate=Coordinate
|
||||||
|
|
||||||
|
self.text=Text
|
||||||
|
|
||||||
|
-- Defaults
|
||||||
|
self.readonly=false
|
||||||
|
self.message=""
|
||||||
|
|
||||||
|
-- New marker ID. This is not the one of the actual marker.
|
||||||
|
_MARKERID=_MARKERID+1
|
||||||
|
|
||||||
|
self.myid=_MARKERID
|
||||||
|
|
||||||
|
-- Log ID.
|
||||||
|
self.lid=string.format("Marker #%d | ", self.myid)
|
||||||
|
|
||||||
|
-- Start State.
|
||||||
|
self:SetStartState("Invisible")
|
||||||
|
|
||||||
|
-- Add FSM transitions.
|
||||||
|
-- From State --> Event --> To State
|
||||||
|
self:AddTransition("Invisible", "Added", "Visible") -- Marker was added.
|
||||||
|
self:AddTransition("Visible", "Removed", "Invisible") -- Marker was removed.
|
||||||
|
self:AddTransition("*", "Changed", "*") -- Marker was changed.
|
||||||
|
|
||||||
|
self:AddTransition("*", "TextUpdate", "*") -- Text updated.
|
||||||
|
self:AddTransition("*", "CoordUpdate", "*") -- Coordinates updated.
|
||||||
|
|
||||||
|
--- Triggers the FSM event "Added".
|
||||||
|
-- @function [parent=#MARKER] Added
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @param Core.Event#EVENTDATA EventData Event data table.
|
||||||
|
|
||||||
|
--- Triggers the delayed FSM event "Added".
|
||||||
|
-- @function [parent=#MARKER] __Added
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @param Core.Event#EVENTDATA EventData Event data table.
|
||||||
|
|
||||||
|
--- On after "Added" event user function.
|
||||||
|
-- @function [parent=#MARKER] OnAfterAdded
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To To state.
|
||||||
|
-- @param Core.Event#EVENTDATA EventData Event data table.
|
||||||
|
|
||||||
|
|
||||||
|
--- Triggers the FSM event "Removed".
|
||||||
|
-- @function [parent=#MARKER] Removed
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @param Core.Event#EVENTDATA EventData Event data table.
|
||||||
|
|
||||||
|
--- Triggers the delayed FSM event "Removed".
|
||||||
|
-- @function [parent=#MARKER] __Removed
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @param Core.Event#EVENTDATA EventData Event data table.
|
||||||
|
|
||||||
|
--- On after "Removed" event user function.
|
||||||
|
-- @function [parent=#MARKER] OnAfterRemoved
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To To state.
|
||||||
|
-- @param Core.Event#EVENTDATA EventData Event data table.
|
||||||
|
|
||||||
|
|
||||||
|
--- Triggers the FSM event "Changed".
|
||||||
|
-- @function [parent=#MARKER] Changed
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @param Core.Event#EVENTDATA EventData Event data table.
|
||||||
|
|
||||||
|
--- Triggers the delayed FSM event "Changed".
|
||||||
|
-- @function [parent=#MARKER] __Changed
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @param Core.Event#EVENTDATA EventData Event data table.
|
||||||
|
|
||||||
|
--- On after "Changed" event user function.
|
||||||
|
-- @function [parent=#MARKER] OnAfterChanged
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To To state.
|
||||||
|
-- @param Core.Event#EVENTDATA EventData Event data table.
|
||||||
|
|
||||||
|
|
||||||
|
--- Triggers the FSM event "TextUpdate".
|
||||||
|
-- @function [parent=#MARKER] TextUpdate
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @param #string Text The new text.
|
||||||
|
|
||||||
|
--- Triggers the delayed FSM event "TextUpdate".
|
||||||
|
-- @function [parent=#MARKER] __TextUpdate
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @param #string Text The new text.
|
||||||
|
|
||||||
|
--- On after "TextUpdate" event user function.
|
||||||
|
-- @function [parent=#MARKER] OnAfterTextUpdate
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To To state.
|
||||||
|
-- @param #string Text The new text.
|
||||||
|
|
||||||
|
|
||||||
|
--- Triggers the FSM event "CoordUpdate".
|
||||||
|
-- @function [parent=#MARKER] CoordUpdate
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @param Core.Point#COORDINATE Coordinate The new Coordinate.
|
||||||
|
|
||||||
|
--- Triggers the delayed FSM event "CoordUpdate".
|
||||||
|
-- @function [parent=#MARKER] __CoordUpdate
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @param Core.Point#COORDINATE Coordinate The updated Coordinate.
|
||||||
|
|
||||||
|
--- On after "CoordUpdate" event user function.
|
||||||
|
-- @function [parent=#MARKER] OnAfterCoordUpdate
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To To state.
|
||||||
|
-- @param Core.Point#COORDINATE Coordinate The updated Coordinate.
|
||||||
|
|
||||||
|
|
||||||
|
-- Handle events.
|
||||||
|
self:HandleEvent(EVENTS.MarkAdded)
|
||||||
|
self:HandleEvent(EVENTS.MarkRemoved)
|
||||||
|
self:HandleEvent(EVENTS.MarkChange)
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-- User API Functions
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- Marker is readonly. Text cannot be changed and marker cannot be removed.
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @return #MARKER self
|
||||||
|
function MARKER:ReadOnly()
|
||||||
|
|
||||||
|
self.readonly=true
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set message that is displayed on screen if the marker is added.
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @param #string Text Message displayed when the marker is added.
|
||||||
|
-- @return #MARKER self
|
||||||
|
function MARKER:Message(Text)
|
||||||
|
|
||||||
|
self.message=Text or ""
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Place marker visible for everyone.
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @param #number Delay (Optional) Delay in seconds, before the marker is created.
|
||||||
|
-- @return #MARKER self
|
||||||
|
function MARKER:ToAll(Delay)
|
||||||
|
|
||||||
|
if Delay and Delay>0 then
|
||||||
|
self:ScheduleOnce(Delay, MARKER.ToAll, self)
|
||||||
|
else
|
||||||
|
|
||||||
|
self.toall=true
|
||||||
|
self.tocoaliton=nil
|
||||||
|
self.coalition=nil
|
||||||
|
self.togroup=nil
|
||||||
|
self.groupname=nil
|
||||||
|
self.groupid=nil
|
||||||
|
|
||||||
|
-- First remove an existing mark.
|
||||||
|
if self.shown then
|
||||||
|
self:Remove()
|
||||||
|
end
|
||||||
|
|
||||||
|
self.mid=UTILS.GetMarkID()
|
||||||
|
|
||||||
|
-- Call DCS function.
|
||||||
|
trigger.action.markToAll(self.mid, self.text, self.coordinate:GetVec3(), self.readonly, self.message)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Place marker visible for a specific coalition only.
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @param #number Coalition Coalition 1=Red, 2=Blue, 0=Neutral. See `coaliton.side.RED`.
|
||||||
|
-- @param #number Delay (Optional) Delay in seconds, before the marker is created.
|
||||||
|
-- @return #MARKER self
|
||||||
|
function MARKER:ToCoalition(Coalition, Delay)
|
||||||
|
|
||||||
|
if Delay and Delay>0 then
|
||||||
|
self:ScheduleOnce(Delay, MARKER.ToCoalition, self, Coalition)
|
||||||
|
else
|
||||||
|
|
||||||
|
self.coalition=Coalition
|
||||||
|
|
||||||
|
self.tocoaliton=true
|
||||||
|
self.toall=false
|
||||||
|
self.togroup=false
|
||||||
|
self.groupname=nil
|
||||||
|
self.groupid=nil
|
||||||
|
|
||||||
|
-- First remove an existing mark.
|
||||||
|
if self.shown then
|
||||||
|
self:Remove()
|
||||||
|
end
|
||||||
|
|
||||||
|
self.mid=UTILS.GetMarkID()
|
||||||
|
|
||||||
|
-- Call DCS function.
|
||||||
|
trigger.action.markToCoalition(self.mid, self.text, self.coordinate:GetVec3(), self.coalition, self.readonly, self.message)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Place marker visible for the blue coalition only.
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @param #number Delay (Optional) Delay in seconds, before the marker is created.
|
||||||
|
-- @return #MARKER self
|
||||||
|
function MARKER:ToBlue(Delay)
|
||||||
|
self:ToCoalition(coalition.side.BLUE, Delay)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Place marker visible for the blue coalition only.
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @param #number Delay (Optional) Delay in seconds, before the marker is created.
|
||||||
|
-- @return #MARKER self
|
||||||
|
function MARKER:ToRed(Delay)
|
||||||
|
self:ToCoalition(coalition.side.RED, Delay)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Place marker visible for the neutral coalition only.
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @param #number Delay (Optional) Delay in seconds, before the marker is created.
|
||||||
|
-- @return #MARKER self
|
||||||
|
function MARKER:ToNeutral(Delay)
|
||||||
|
self:ToCoalition(coalition.side.NEUTRAL, Delay)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Place marker visible for a specific group only.
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @param Wrapper.Group#GROUP Group The group to which the marker is displayed.
|
||||||
|
-- @param #number Delay (Optional) Delay in seconds, before the marker is created.
|
||||||
|
-- @return #MARKER self
|
||||||
|
function MARKER:ToGroup(Group, Delay)
|
||||||
|
|
||||||
|
if Delay and Delay>0 then
|
||||||
|
self:ScheduleOnce(Delay, MARKER.ToGroup, self, Group)
|
||||||
|
else
|
||||||
|
|
||||||
|
-- Check if group exists.
|
||||||
|
if Group and Group:IsAlive()~=nil then
|
||||||
|
|
||||||
|
self.groupid=Group:GetID()
|
||||||
|
|
||||||
|
if self.groupid then
|
||||||
|
|
||||||
|
self.groupname=Group:GetName()
|
||||||
|
|
||||||
|
self.togroup=true
|
||||||
|
self.tocoaliton=nil
|
||||||
|
self.coalition=nil
|
||||||
|
self.toall=nil
|
||||||
|
|
||||||
|
-- First remove an existing mark.
|
||||||
|
if self.shown then
|
||||||
|
self:Remove()
|
||||||
|
end
|
||||||
|
|
||||||
|
self.mid=UTILS.GetMarkID()
|
||||||
|
|
||||||
|
-- Call DCS function.
|
||||||
|
trigger.action.markToGroup(self.mid, self.text, self.coordinate:GetVec3(), self.groupid, self.readonly, self.message)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
else
|
||||||
|
--TODO: Warning!
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Update the text displayed on the mark panel.
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @param #string Text Updated text.
|
||||||
|
-- @param #number Delay (Optional) Delay in seconds, before the marker is created.
|
||||||
|
-- @return #MARKER self
|
||||||
|
function MARKER:UpdateText(Text, Delay)
|
||||||
|
|
||||||
|
if Delay and Delay>0 then
|
||||||
|
self:ScheduleOnce(Delay, MARKER.UpdateText, self, Text)
|
||||||
|
else
|
||||||
|
|
||||||
|
self.text=tostring(Text)
|
||||||
|
|
||||||
|
self:Refresh()
|
||||||
|
|
||||||
|
self:TextUpdate(tostring(Text))
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Update the coordinate where the marker is displayed.
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @param Core.Point#COORDINATE Coordinate The new coordinate.
|
||||||
|
-- @param #number Delay (Optional) Delay in seconds, before the marker is created.
|
||||||
|
-- @return #MARKER self
|
||||||
|
function MARKER:UpdateCoordinate(Coordinate, Delay)
|
||||||
|
|
||||||
|
if Delay and Delay>0 then
|
||||||
|
self:ScheduleOnce(Delay, MARKER.UpdateCoordinate, self, Coordinate)
|
||||||
|
else
|
||||||
|
|
||||||
|
self.coordinate=Coordinate
|
||||||
|
|
||||||
|
self:Refresh()
|
||||||
|
|
||||||
|
self:CoordUpdate(Coordinate)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Refresh the marker.
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @param #number Delay (Optional) Delay in seconds, before the marker is created.
|
||||||
|
-- @return #MARKER self
|
||||||
|
function MARKER:Refresh(Delay)
|
||||||
|
|
||||||
|
if Delay and Delay>0 then
|
||||||
|
self:ScheduleOnce(Delay, MARKER.Refresh, self)
|
||||||
|
else
|
||||||
|
|
||||||
|
if self.toall then
|
||||||
|
|
||||||
|
self:ToAll()
|
||||||
|
|
||||||
|
elseif self.tocoaliton then
|
||||||
|
|
||||||
|
self:ToCoalition(self.coalition)
|
||||||
|
|
||||||
|
elseif self.togroup then
|
||||||
|
|
||||||
|
local group=GROUP:FindByName(self.groupname)
|
||||||
|
|
||||||
|
self:ToGroup(group)
|
||||||
|
|
||||||
|
else
|
||||||
|
self:E(self.lid.."ERROR: unknown To in :Refresh()!")
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Remove a marker.
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @param #number Delay (Optional) Delay in seconds, before the marker is removed.
|
||||||
|
-- @return #MARKER self
|
||||||
|
function MARKER:Remove(Delay)
|
||||||
|
|
||||||
|
if Delay and Delay>0 then
|
||||||
|
self:ScheduleOnce(Delay, MARKER.Remove, self)
|
||||||
|
else
|
||||||
|
|
||||||
|
if self.shown then
|
||||||
|
|
||||||
|
-- Call DCS function.
|
||||||
|
trigger.action.removeMark(self.mid)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get position of the marker.
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @return Core.Point#COORDINATE The coordinate of the marker.
|
||||||
|
function MARKER:GetCoordinate()
|
||||||
|
return self.coordinate
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get text that is displayed in the marker panel.
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @return #string Marker text.
|
||||||
|
function MARKER:GetText()
|
||||||
|
return self.text
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set text that is displayed in the marker panel. Note this does not show the marker.
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @param #string Text Marker text. Default is an empty sting "".
|
||||||
|
-- @return #MARKER self
|
||||||
|
function MARKER:SetText(Text)
|
||||||
|
self.text=Text and tostring(Text) or ""
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Check if marker is currently visible on the F10 map.
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @return #boolean True if the marker is currently visible.
|
||||||
|
function MARKER:IsVisible()
|
||||||
|
return self:Is("Visible")
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Check if marker is currently invisible on the F10 map.
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @return
|
||||||
|
function MARKER:IsInvisible()
|
||||||
|
return self:Is("Invisible")
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-- Event Functions
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- Event function when a MARKER is added.
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @param Core.Event#EVENTDATA EventData
|
||||||
|
function MARKER:OnEventMarkAdded(EventData)
|
||||||
|
|
||||||
|
if EventData and EventData.MarkID then
|
||||||
|
|
||||||
|
local MarkID=EventData.MarkID
|
||||||
|
|
||||||
|
self:T3(self.lid..string.format("Captured event MarkAdded for Mark ID=%s", tostring(MarkID)))
|
||||||
|
|
||||||
|
if MarkID==self.mid then
|
||||||
|
|
||||||
|
self.shown=true
|
||||||
|
|
||||||
|
self:Added(EventData)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Event function when a MARKER is removed.
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @param Core.Event#EVENTDATA EventData
|
||||||
|
function MARKER:OnEventMarkRemoved(EventData)
|
||||||
|
|
||||||
|
if EventData and EventData.MarkID then
|
||||||
|
|
||||||
|
local MarkID=EventData.MarkID
|
||||||
|
|
||||||
|
self:T3(self.lid..string.format("Captured event MarkAdded for Mark ID=%s", tostring(MarkID)))
|
||||||
|
|
||||||
|
if MarkID==self.mid then
|
||||||
|
|
||||||
|
self.shown=false
|
||||||
|
|
||||||
|
self:Removed(EventData)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Event function when a MARKER changed.
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @param Core.Event#EVENTDATA EventData
|
||||||
|
function MARKER:OnEventMarkChange(EventData)
|
||||||
|
|
||||||
|
if EventData and EventData.MarkID then
|
||||||
|
|
||||||
|
local MarkID=EventData.MarkID
|
||||||
|
|
||||||
|
self:T3(self.lid..string.format("Captured event MarkChange for Mark ID=%s", tostring(MarkID)))
|
||||||
|
|
||||||
|
if MarkID==self.mid then
|
||||||
|
|
||||||
|
self:Changed(EventData)
|
||||||
|
|
||||||
|
self:TextChanged(tostring(EventData.MarkText))
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-- FSM Event Functions
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- On after "Added" event.
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To To state.
|
||||||
|
-- @param Core.Event#EVENTDATA EventData Event data table.
|
||||||
|
function MARKER:onafterAdded(From, Event, To, EventData)
|
||||||
|
|
||||||
|
-- Debug info.
|
||||||
|
local text=string.format("Captured event MarkAdded for myself:\n")
|
||||||
|
text=text..string.format("Marker ID = %s\n", tostring(EventData.MarkID))
|
||||||
|
text=text..string.format("Coalition = %s\n", tostring(EventData.MarkCoalition))
|
||||||
|
text=text..string.format("Group ID = %s\n", tostring(EventData.MarkGroupID))
|
||||||
|
text=text..string.format("Initiator = %s\n", EventData.IniUnit and EventData.IniUnit:GetName() or "Nobody")
|
||||||
|
text=text..string.format("Coordinate = %s\n", EventData.MarkCoordinate and EventData.MarkCoordinate:ToStringLLDMS() or "Nowhere")
|
||||||
|
text=text..string.format("Text: \n%s", tostring(EventData.MarkText))
|
||||||
|
self:T2(self.lid..text)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--- On after "Removed" event.
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To To state.
|
||||||
|
-- @param Core.Event#EVENTDATA EventData Event data table.
|
||||||
|
function MARKER:onafterRemoved(From, Event, To, EventData)
|
||||||
|
|
||||||
|
-- Debug info.
|
||||||
|
local text=string.format("Captured event MarkRemoved for myself:\n")
|
||||||
|
text=text..string.format("Marker ID = %s\n", tostring(EventData.MarkID))
|
||||||
|
text=text..string.format("Coalition = %s\n", tostring(EventData.MarkCoalition))
|
||||||
|
text=text..string.format("Group ID = %s\n", tostring(EventData.MarkGroupID))
|
||||||
|
text=text..string.format("Initiator = %s\n", EventData.IniUnit and EventData.IniUnit:GetName() or "Nobody")
|
||||||
|
text=text..string.format("Coordinate = %s\n", EventData.MarkCoordinate and EventData.MarkCoordinate:ToStringLLDMS() or "Nowhere")
|
||||||
|
text=text..string.format("Text: \n%s", tostring(EventData.MarkText))
|
||||||
|
self:T2(self.lid..text)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--- On after "Changed" event.
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To To state.
|
||||||
|
-- @param Core.Event#EVENTDATA EventData Event data table.
|
||||||
|
function MARKER:onafterChanged(From, Event, To, EventData)
|
||||||
|
|
||||||
|
-- Debug info.
|
||||||
|
local text=string.format("Captured event MarkChange for myself:\n")
|
||||||
|
text=text..string.format("Marker ID = %s\n", tostring(EventData.MarkID))
|
||||||
|
text=text..string.format("Coalition = %s\n", tostring(EventData.MarkCoalition))
|
||||||
|
text=text..string.format("Group ID = %s\n", tostring(EventData.MarkGroupID))
|
||||||
|
text=text..string.format("Initiator = %s\n", EventData.IniUnit and EventData.IniUnit:GetName() or "Nobody")
|
||||||
|
text=text..string.format("Coordinate = %s\n", EventData.MarkCoordinate and EventData.MarkCoordinate:ToStringLLDMS() or "Nowhere")
|
||||||
|
text=text..string.format("Text: \n%s", tostring(EventData.MarkText))
|
||||||
|
self:T2(self.lid..text)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--- On after "TextUpdate" event.
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To To state.
|
||||||
|
-- @param #string Text The updated text, displayed in the mark panel.
|
||||||
|
function MARKER:onafterTextUpdate(From, Event, To, Text)
|
||||||
|
|
||||||
|
self:T(self.lid..string.format("New Marker Text:\n%s", Text))
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--- On after "CoordUpdate" event.
|
||||||
|
-- @param #MARKER self
|
||||||
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To To state.
|
||||||
|
-- @param Core.Point#COORDINATE Coordinate The updated coordinates.
|
||||||
|
function MARKER:onafterCoordUpdate(From, Event, To, Coordinate)
|
||||||
|
|
||||||
|
self:T(self.lid..string.format("New Marker Coordinate in LL DMS: %s", Coordinate:ToStringLLDMS()))
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
@@ -15,6 +15,8 @@
|
|||||||
-- @extends Wrapper.Identifiable#IDENTIFIABLE
|
-- @extends Wrapper.Identifiable#IDENTIFIABLE
|
||||||
|
|
||||||
--- @type POSITIONABLE
|
--- @type POSITIONABLE
|
||||||
|
-- @field Core.Point#COORDINATE coordinate Coordinate object.
|
||||||
|
-- @field Core.Point#POINT_VEC3 pointvec3 Point Vec3 object.
|
||||||
-- @extends Wrapper.Identifiable#IDENTIFIABLE
|
-- @extends Wrapper.Identifiable#IDENTIFIABLE
|
||||||
|
|
||||||
|
|
||||||
@@ -45,6 +47,8 @@
|
|||||||
POSITIONABLE = {
|
POSITIONABLE = {
|
||||||
ClassName = "POSITIONABLE",
|
ClassName = "POSITIONABLE",
|
||||||
PositionableName = "",
|
PositionableName = "",
|
||||||
|
coordinate = nil,
|
||||||
|
pointvec3 = nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
--- @field #POSITIONABLE.__
|
--- @field #POSITIONABLE.__
|
||||||
@@ -121,10 +125,17 @@ function POSITIONABLE:Destroy( GenerateEvent )
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Returns the DCS object. Polymorphic for other classes like UNIT, STATIC, GROUP, AIRBASE.
|
||||||
|
-- @param #POSITIONABLE self
|
||||||
|
-- @return DCS#Object The DCS object.
|
||||||
|
function POSITIONABLE:GetDCSObject()
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
--- Returns a pos3 table of the objects current position and orientation in 3D space. X, Y, Z values are unit vectors defining the objects orientation.
|
--- Returns a pos3 table of the objects current position and orientation in 3D space. X, Y, Z values are unit vectors defining the objects orientation.
|
||||||
-- Coordinates are dependent on the position of the maps origin.
|
-- Coordinates are dependent on the position of the maps origin.
|
||||||
-- @param Wrapper.Positionable#POSITIONABLE self
|
-- @param Wrapper.Positionable#POSITIONABLE self
|
||||||
-- @return DCS#Position Table consisting of the point and orientation tables.
|
-- @return DCS#Position3 Table consisting of the point and orientation tables.
|
||||||
function POSITIONABLE:GetPosition()
|
function POSITIONABLE:GetPosition()
|
||||||
self:F2( self.PositionableName )
|
self:F2( self.PositionableName )
|
||||||
|
|
||||||
@@ -215,27 +226,44 @@ function POSITIONABLE:GetPositionVec3()
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Returns the @{DCS#Vec2} vector indicating the point in 2D of the POSITIONABLE within the mission.
|
--- Returns the @{DCS#Vec3} vector indicating the 3D vector of the POSITIONABLE within the mission.
|
||||||
-- @param Wrapper.Positionable#POSITIONABLE self
|
-- @param Wrapper.Positionable#POSITIONABLE self
|
||||||
-- @return DCS#Vec2 The 2D point vector of the POSITIONABLE.
|
-- @return DCS#Vec3 The 3D point vector of the POSITIONABLE or `nil` if it is not existing or alive.
|
||||||
-- @return #nil The POSITIONABLE is not existing or alive.
|
function POSITIONABLE:GetVec3()
|
||||||
function POSITIONABLE:GetVec2()
|
|
||||||
self:F2( self.PositionableName )
|
|
||||||
|
|
||||||
local DCSPositionable = self:GetDCSObject()
|
local DCSPositionable = self:GetDCSObject()
|
||||||
|
|
||||||
if DCSPositionable then
|
if DCSPositionable then
|
||||||
local PositionableVec3 = DCSPositionable:getPosition().p
|
|
||||||
|
|
||||||
local PositionableVec2 = {}
|
local vec3=DCSPositionable:getPoint()
|
||||||
PositionableVec2.x = PositionableVec3.x
|
|
||||||
PositionableVec2.y = PositionableVec3.z
|
|
||||||
|
|
||||||
self:T2( PositionableVec2 )
|
if vec3 then
|
||||||
return PositionableVec2
|
return vec3
|
||||||
|
else
|
||||||
|
self:E("ERROR: Cannot get vec3!")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
BASE:E( { "Cannot GetVec2", Positionable = self, Alive = self:IsAlive() } )
|
-- ERROR!
|
||||||
|
self:E( { "Cannot GetVec3", Positionable = self, Alive = self:IsAlive() } )
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Returns the @{DCS#Vec2} vector indicating the point in 2D of the POSITIONABLE within the mission.
|
||||||
|
-- @param Wrapper.Positionable#POSITIONABLE self
|
||||||
|
-- @return DCS#Vec2 The 2D point vector of the POSITIONABLE or #nil if it is not existing or alive.
|
||||||
|
function POSITIONABLE:GetVec2()
|
||||||
|
|
||||||
|
local DCSPositionable = self:GetDCSObject()
|
||||||
|
|
||||||
|
if DCSPositionable then
|
||||||
|
|
||||||
|
local Vec3=DCSPositionable:getPoint() --DCS#Vec3
|
||||||
|
|
||||||
|
return {x=Vec3.x, y=Vec3.z}
|
||||||
|
end
|
||||||
|
|
||||||
|
self:E( { "Cannot GetVec2", Positionable = self, Alive = self:IsAlive() } )
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
@@ -258,7 +286,7 @@ function POSITIONABLE:GetPointVec2()
|
|||||||
return PositionablePointVec2
|
return PositionablePointVec2
|
||||||
end
|
end
|
||||||
|
|
||||||
BASE:E( { "Cannot GetPointVec2", Positionable = self, Alive = self:IsAlive() } )
|
self:E( { "Cannot GetPointVec2", Positionable = self, Alive = self:IsAlive() } )
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
@@ -268,17 +296,29 @@ end
|
|||||||
-- @return Core.Point#POINT_VEC3 The 3D point vector of the POSITIONABLE.
|
-- @return Core.Point#POINT_VEC3 The 3D point vector of the POSITIONABLE.
|
||||||
-- @return #nil The POSITIONABLE is not existing or alive.
|
-- @return #nil The POSITIONABLE is not existing or alive.
|
||||||
function POSITIONABLE:GetPointVec3()
|
function POSITIONABLE:GetPointVec3()
|
||||||
self:F2( self.PositionableName )
|
|
||||||
|
|
||||||
local DCSPositionable = self:GetDCSObject()
|
local DCSPositionable = self:GetDCSObject()
|
||||||
|
|
||||||
if DCSPositionable then
|
if DCSPositionable then
|
||||||
|
|
||||||
|
-- Get 3D vector.
|
||||||
local PositionableVec3 = self:GetPositionVec3()
|
local PositionableVec3 = self:GetPositionVec3()
|
||||||
|
|
||||||
local PositionablePointVec3 = POINT_VEC3:NewFromVec3( PositionableVec3 )
|
if false and self.pointvec3 then
|
||||||
|
|
||||||
self:T2( PositionablePointVec3 )
|
-- Update vector.
|
||||||
return PositionablePointVec3
|
self.pointvec3.x=PositionableVec3.x
|
||||||
|
self.pointvec3.y=PositionableVec3.y
|
||||||
|
self.pointvec3.z=PositionableVec3.z
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
-- Create a new POINT_VEC3 object.
|
||||||
|
self.pointvec3=POINT_VEC3:NewFromVec3(PositionableVec3)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
return self.pointvec3
|
||||||
end
|
end
|
||||||
|
|
||||||
BASE:E( { "Cannot GetPointVec3", Positionable = self, Alive = self:IsAlive() } )
|
BASE:E( { "Cannot GetPointVec3", Positionable = self, Alive = self:IsAlive() } )
|
||||||
@@ -289,27 +329,64 @@ end
|
|||||||
--- Returns a COORDINATE object indicating the point in 3D of the POSITIONABLE within the mission.
|
--- Returns a COORDINATE object indicating the point in 3D of the POSITIONABLE within the mission.
|
||||||
-- @param Wrapper.Positionable#POSITIONABLE self
|
-- @param Wrapper.Positionable#POSITIONABLE self
|
||||||
-- @return Core.Point#COORDINATE The COORDINATE of the POSITIONABLE.
|
-- @return Core.Point#COORDINATE The COORDINATE of the POSITIONABLE.
|
||||||
function POSITIONABLE:GetCoordinate()
|
function POSITIONABLE:GetCoord()
|
||||||
self:F2( self.PositionableName )
|
|
||||||
|
|
||||||
|
-- Get DCS object.
|
||||||
local DCSPositionable = self:GetDCSObject()
|
local DCSPositionable = self:GetDCSObject()
|
||||||
|
|
||||||
if DCSPositionable then
|
if DCSPositionable then
|
||||||
local PositionableVec3 = self:GetPositionVec3()
|
|
||||||
|
|
||||||
local PositionableCoordinate = COORDINATE:NewFromVec3( PositionableVec3 )
|
-- Get the current position.
|
||||||
PositionableCoordinate:SetHeading( self:GetHeading() )
|
local Vec3 = self:GetVec3()
|
||||||
PositionableCoordinate:SetVelocity( self:GetVelocityMPS() )
|
|
||||||
|
|
||||||
self:T2( PositionableCoordinate )
|
if self.coordinate then
|
||||||
return PositionableCoordinate
|
|
||||||
|
-- Update vector.
|
||||||
|
self.coordinate.x=Vec3.x
|
||||||
|
self.coordinate.y=Vec3.y
|
||||||
|
self.coordinate.z=Vec3.z
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
-- New COORDINATE.
|
||||||
|
self.coordinate=COORDINATE:NewFromVec3(Vec3)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
return self.coordinate
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Error message.
|
||||||
BASE:E( { "Cannot GetCoordinate", Positionable = self, Alive = self:IsAlive() } )
|
BASE:E( { "Cannot GetCoordinate", Positionable = self, Alive = self:IsAlive() } )
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Returns a COORDINATE object indicating the point in 3D of the POSITIONABLE within the mission.
|
||||||
|
-- @param Wrapper.Positionable#POSITIONABLE self
|
||||||
|
-- @return Core.Point#COORDINATE The COORDINATE of the POSITIONABLE.
|
||||||
|
function POSITIONABLE:GetCoordinate()
|
||||||
|
|
||||||
|
-- Get DCS object.
|
||||||
|
local DCSPositionable = self:GetDCSObject()
|
||||||
|
|
||||||
|
if DCSPositionable then
|
||||||
|
|
||||||
|
-- Get the current position.
|
||||||
|
local PositionableVec3 = self:GetVec3()
|
||||||
|
|
||||||
|
local coord=COORDINATE:NewFromVec3(PositionableVec3)
|
||||||
|
|
||||||
|
-- Return a new coordiante object.
|
||||||
|
return coord
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Error message.
|
||||||
|
self:E( { "Cannot GetCoordinate", Positionable = self, Alive = self:IsAlive() } )
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
--- Returns a COORDINATE object, which is offset with respect to the orientation of the POSITIONABLE.
|
--- Returns a COORDINATE object, which is offset with respect to the orientation of the POSITIONABLE.
|
||||||
-- @param Wrapper.Positionable#POSITIONABLE self
|
-- @param Wrapper.Positionable#POSITIONABLE self
|
||||||
-- @param #number x Offset in the direction "the nose" of the unit is pointing in meters. Default 0 m.
|
-- @param #number x Offset in the direction "the nose" of the unit is pointing in meters. Default 0 m.
|
||||||
@@ -345,8 +422,10 @@ function POSITIONABLE:GetOffsetCoordinate(x,y,z)
|
|||||||
-- Translate offset vector from map origin to the unit: v=u+a.
|
-- Translate offset vector from map origin to the unit: v=u+a.
|
||||||
local v={x=a.x+u.x, y=a.y+u.y, z=a.z+u.z}
|
local v={x=a.x+u.x, y=a.y+u.y, z=a.z+u.z}
|
||||||
|
|
||||||
|
local coord=COORDINATE:NewFromVec3(v)
|
||||||
|
|
||||||
-- Return the offset coordinate.
|
-- Return the offset coordinate.
|
||||||
return COORDINATE:NewFromVec3(v)
|
return coord
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Returns a random @{DCS#Vec3} vector within a range, indicating the point in 3D of the POSITIONABLE within the mission.
|
--- Returns a random @{DCS#Vec3} vector within a range, indicating the point in 3D of the POSITIONABLE within the mission.
|
||||||
@@ -384,26 +463,6 @@ function POSITIONABLE:GetRandomVec3( Radius )
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Returns the @{DCS#Vec3} vector indicating the 3D vector of the POSITIONABLE within the mission.
|
|
||||||
-- @param Wrapper.Positionable#POSITIONABLE self
|
|
||||||
-- @return DCS#Vec3 The 3D point vector of the POSITIONABLE.
|
|
||||||
-- @return #nil The POSITIONABLE is not existing or alive.
|
|
||||||
function POSITIONABLE:GetVec3()
|
|
||||||
self:F2( self.PositionableName )
|
|
||||||
|
|
||||||
local DCSPositionable = self:GetDCSObject()
|
|
||||||
|
|
||||||
if DCSPositionable then
|
|
||||||
local PositionableVec3 = DCSPositionable:getPosition().p
|
|
||||||
self:T3( PositionableVec3 )
|
|
||||||
return PositionableVec3
|
|
||||||
end
|
|
||||||
|
|
||||||
BASE:E( { "Cannot GetVec3", Positionable = self, Alive = self:IsAlive() } )
|
|
||||||
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
--- Get the bounding box of the underlying POSITIONABLE DCS Object.
|
--- Get the bounding box of the underlying POSITIONABLE DCS Object.
|
||||||
-- @param #POSITIONABLE self
|
-- @param #POSITIONABLE self
|
||||||
@@ -602,6 +661,26 @@ function POSITIONABLE:IsGround()
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Returns if the unit is of ship category.
|
||||||
|
-- @param #POSITIONABLE self
|
||||||
|
-- @return #boolean Ship category evaluation result.
|
||||||
|
function POSITIONABLE:IsShip()
|
||||||
|
self:F2()
|
||||||
|
|
||||||
|
local DCSUnit = self:GetDCSObject()
|
||||||
|
|
||||||
|
if DCSUnit then
|
||||||
|
local UnitDescriptor = DCSUnit:getDesc()
|
||||||
|
|
||||||
|
local IsShip = ( UnitDescriptor.category == Unit.Category.SHIP )
|
||||||
|
|
||||||
|
return IsShip
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Returns true if the POSITIONABLE is in the air.
|
--- Returns true if the POSITIONABLE is in the air.
|
||||||
-- Polymorphic, is overridden in GROUP and UNIT.
|
-- Polymorphic, is overridden in GROUP and UNIT.
|
||||||
-- @param Wrapper.Positionable#POSITIONABLE self
|
-- @param Wrapper.Positionable#POSITIONABLE self
|
||||||
@@ -1513,7 +1592,7 @@ end
|
|||||||
|
|
||||||
|
|
||||||
--- Returns true if the unit is within a @{Zone}.
|
--- Returns true if the unit is within a @{Zone}.
|
||||||
-- @param #STPOSITIONABLEATIC self
|
-- @param #POSITIONABLE self
|
||||||
-- @param Core.Zone#ZONE_BASE Zone The zone to test.
|
-- @param Core.Zone#ZONE_BASE Zone The zone to test.
|
||||||
-- @return #boolean Returns true if the unit is within the @{Core.Zone#ZONE_BASE}
|
-- @return #boolean Returns true if the unit is within the @{Core.Zone#ZONE_BASE}
|
||||||
function POSITIONABLE:IsInZone( Zone )
|
function POSITIONABLE:IsInZone( Zone )
|
||||||
|
|||||||
@@ -31,6 +31,11 @@ SCENERY = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
--- Register scenery object as POSITIONABLE.
|
||||||
|
--@param #SCENERY self
|
||||||
|
--@param #string SceneryName Scenery name.
|
||||||
|
--@param #DCS.Object SceneryObject DCS scenery object.
|
||||||
|
--@return #SCENERY Scenery object.
|
||||||
function SCENERY:Register( SceneryName, SceneryObject )
|
function SCENERY:Register( SceneryName, SceneryObject )
|
||||||
local self = BASE:Inherit( self, POSITIONABLE:New( SceneryName ) )
|
local self = BASE:Inherit( self, POSITIONABLE:New( SceneryName ) )
|
||||||
self.SceneryName = SceneryName
|
self.SceneryName = SceneryName
|
||||||
@@ -38,11 +43,17 @@ function SCENERY:Register( SceneryName, SceneryObject )
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Register scenery object as POSITIONABLE.
|
||||||
|
--@param #SCENERY self
|
||||||
|
--@return #DCS.Object DCS scenery object.
|
||||||
function SCENERY:GetDCSObject()
|
function SCENERY:GetDCSObject()
|
||||||
return self.SceneryObject
|
return self.SceneryObject
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Register scenery object as POSITIONABLE.
|
||||||
|
--@param #SCENERY self
|
||||||
|
--@return #number Threat level 0.
|
||||||
|
--@return #string "Scenery".
|
||||||
function SCENERY:GetThreatLevel()
|
function SCENERY:GetThreatLevel()
|
||||||
|
|
||||||
return 0, "Scenery"
|
return 0, "Scenery"
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
--
|
--
|
||||||
-- ### Author: **FlightControl**
|
-- ### Author: **FlightControl**
|
||||||
--
|
--
|
||||||
-- ### Contributions:
|
-- ### Contributions: **funkyfranky**
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
@@ -48,6 +48,10 @@ STATIC = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
--- Register a static object.
|
||||||
|
-- @param #STATIC self
|
||||||
|
-- @param #string StaticName Name of the static object.
|
||||||
|
-- @return #STATIC self
|
||||||
function STATIC:Register( StaticName )
|
function STATIC:Register( StaticName )
|
||||||
local self = BASE:Inherit( self, POSITIONABLE:New( StaticName ) )
|
local self = BASE:Inherit( self, POSITIONABLE:New( StaticName ) )
|
||||||
self.StaticName = StaticName
|
self.StaticName = StaticName
|
||||||
@@ -71,14 +75,16 @@ end
|
|||||||
-- @param #STATIC self
|
-- @param #STATIC self
|
||||||
-- @param #string StaticName Name of the DCS **Static** as defined within the Mission Editor.
|
-- @param #string StaticName Name of the DCS **Static** as defined within the Mission Editor.
|
||||||
-- @param #boolean RaiseError Raise an error if not found.
|
-- @param #boolean RaiseError Raise an error if not found.
|
||||||
-- @return #STATIC
|
-- @return #STATIC self or *nil*
|
||||||
function STATIC:FindByName( StaticName, RaiseError )
|
function STATIC:FindByName( StaticName, RaiseError )
|
||||||
|
|
||||||
|
-- Find static in DB.
|
||||||
local StaticFound = _DATABASE:FindStatic( StaticName )
|
local StaticFound = _DATABASE:FindStatic( StaticName )
|
||||||
|
|
||||||
|
-- Set static name.
|
||||||
self.StaticName = StaticName
|
self.StaticName = StaticName
|
||||||
|
|
||||||
if StaticFound then
|
if StaticFound then
|
||||||
StaticFound:F3( { StaticName } )
|
|
||||||
return StaticFound
|
return StaticFound
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -188,7 +194,7 @@ 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
|
||||||
|
|
||||||
@@ -196,51 +202,58 @@ function STATIC:SpawnAt( Coordinate, Heading, Delay )
|
|||||||
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
|
||||||
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 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 Delay in seconds before static is respawned.
|
-- @param #number Delay (Optional) Delay in seconds before static is respawned. Default now.
|
||||||
function STATIC:ReSpawn(countryid, Delay)
|
function STATIC:ReSpawn(CountryID, Delay)
|
||||||
|
|
||||||
countryid=countryid or self:GetCountry()
|
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
local SpawnStatic = SPAWNSTATIC:NewFromStatic( self.StaticName, countryid )
|
CountryID=CountryID or self:GetCountry()
|
||||||
|
|
||||||
SpawnStatic:ReSpawn()
|
local SpawnStatic=SPAWNSTATIC:NewFromStatic(self.StaticName, CountryID)
|
||||||
|
|
||||||
|
SpawnStatic:Spawn(nil, self.StaticName)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
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 The heading of the static respawn in degrees. Default is 0 deg.
|
-- @param #number Heading (Optional) The heading of the static respawn in degrees. Default the current heading.
|
||||||
-- @param #number Delay Delay in seconds before static is respawned.
|
-- @param #number Delay (Optional) Delay in seconds before static is respawned. Default 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 )
|
local SpawnStatic=SPAWNSTATIC:NewFromStatic(self.StaticName, self:GetCountry())
|
||||||
|
|
||||||
|
SpawnStatic:SpawnFromCoordinate(Coordinate, Heading, self.StaticName)
|
||||||
|
|
||||||
SpawnStatic:ReSpawnAt( Coordinate, Heading )
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -258,8 +258,7 @@ 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.
|
-- @return #boolean `true` if Unit is activated. `nil` The DCS Unit is not existing or alive.
|
||||||
-- @return #nil The DCS Unit is not existing or alive.
|
|
||||||
function UNIT:IsActive()
|
function UNIT:IsActive()
|
||||||
self:F2( self.UnitName )
|
self:F2( self.UnitName )
|
||||||
|
|
||||||
@@ -279,9 +278,7 @@ end
|
|||||||
-- If the Unit is alive and active, true is returned.
|
-- If the Unit is alive and active, true is returned.
|
||||||
-- If the Unit is alive but not active, false is returned.
|
-- If the Unit is alive but not active, false is returned.
|
||||||
-- @param #UNIT self
|
-- @param #UNIT self
|
||||||
-- @return #boolean true if Unit is alive and active.
|
-- @return #boolean `true` if Unit is alive and active. `false` if Unit is alive but not active. `nil` if the Unit is not existing or is not alive.
|
||||||
-- @return #boolean false if Unit is alive but not active.
|
|
||||||
-- @return #nil if the Unit is not existing or is not alive.
|
|
||||||
function UNIT:IsAlive()
|
function UNIT:IsAlive()
|
||||||
self:F3( self.UnitName )
|
self:F3( self.UnitName )
|
||||||
|
|
||||||
@@ -300,7 +297,6 @@ 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.
|
||||||
-- @return #nil The DCS Unit is not existing or alive.
|
|
||||||
function UNIT:GetCallsign()
|
function UNIT:GetCallsign()
|
||||||
self:F2( self.UnitName )
|
self:F2( self.UnitName )
|
||||||
|
|
||||||
@@ -424,9 +420,9 @@ function UNIT:GetRange()
|
|||||||
local Desc = self:GetDesc()
|
local Desc = self:GetDesc()
|
||||||
|
|
||||||
if Desc then
|
if Desc then
|
||||||
local Range = Desc.range --This is in nautical miles for some reason. But should check again!
|
local Range = Desc.range --This is in kilometers (not meters) for some reason. But should check again!
|
||||||
if Range then
|
if Range then
|
||||||
Range=UTILS.NMToMeters(Range)
|
Range=Range*1000 -- convert to meters.
|
||||||
else
|
else
|
||||||
Range=10000000 --10.000 km if no range
|
Range=10000000 --10.000 km if no range
|
||||||
end
|
end
|
||||||
@@ -436,6 +432,64 @@ function UNIT:GetRange()
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Check if the unit is refuelable. Also retrieves the refuelling system (boom or probe) if applicable.
|
||||||
|
-- @param #UNIT self
|
||||||
|
-- @return #boolean If true, unit is refuelable (checks for the attribute "Refuelable").
|
||||||
|
-- @return #number Refueling system (if any): 0=boom, 1=probe.
|
||||||
|
function UNIT:IsRefuelable()
|
||||||
|
self:F2( self.UnitName )
|
||||||
|
|
||||||
|
local refuelable=self:HasAttribute("Refuelable")
|
||||||
|
|
||||||
|
local system=nil
|
||||||
|
|
||||||
|
local Desc=self:GetDesc()
|
||||||
|
if Desc and Desc.tankerType then
|
||||||
|
system=Desc.tankerType
|
||||||
|
end
|
||||||
|
|
||||||
|
return refuelable, system
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Check if the unit is a tanker. Also retrieves the refuelling system (boom or probe) if applicable.
|
||||||
|
-- @param #UNIT self
|
||||||
|
-- @return #boolean If true, unit is refuelable (checks for the attribute "Refuelable").
|
||||||
|
-- @return #number Refueling system (if any): 0=boom, 1=probe.
|
||||||
|
function UNIT:IsTanker()
|
||||||
|
self:F2( self.UnitName )
|
||||||
|
|
||||||
|
local tanker=self:HasAttribute("Tankers")
|
||||||
|
|
||||||
|
local system=nil
|
||||||
|
|
||||||
|
if tanker then
|
||||||
|
|
||||||
|
local Desc=self:GetDesc()
|
||||||
|
if Desc and Desc.tankerType then
|
||||||
|
system=Desc.tankerType
|
||||||
|
end
|
||||||
|
|
||||||
|
local typename=self:GetTypeName()
|
||||||
|
|
||||||
|
-- Some hard coded data as this is not in the descriptors...
|
||||||
|
if typename=="IL-78M" then
|
||||||
|
system=1 --probe
|
||||||
|
elseif typename=="KC130" then
|
||||||
|
system=1 --probe
|
||||||
|
elseif typename=="KC135BDA" then
|
||||||
|
system=1 --probe
|
||||||
|
elseif typename=="KC135MPRS" then
|
||||||
|
system=1 --probe
|
||||||
|
elseif typename=="S-3B Tanker" then
|
||||||
|
system=1 --probe
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
return tanker, system
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Returns the unit's group if it exist and nil otherwise.
|
--- Returns the unit's group if it exist and nil otherwise.
|
||||||
-- @param Wrapper.Unit#UNIT self
|
-- @param Wrapper.Unit#UNIT self
|
||||||
-- @return Wrapper.Group#GROUP The Group of the Unit.
|
-- @return Wrapper.Group#GROUP The Group of the Unit.
|
||||||
@@ -478,8 +532,7 @@ end
|
|||||||
|
|
||||||
--- Returns the Unit's ammunition.
|
--- Returns the Unit's ammunition.
|
||||||
-- @param #UNIT self
|
-- @param #UNIT self
|
||||||
-- @return DCS#Unit.Ammo
|
-- @return DCS#Unit.Ammo Table with ammuntion of the unit (or nil). This can be a complex table!
|
||||||
-- @return #nil The DCS Unit is not existing or alive.
|
|
||||||
function UNIT:GetAmmo()
|
function UNIT:GetAmmo()
|
||||||
self:F2( self.UnitName )
|
self:F2( self.UnitName )
|
||||||
|
|
||||||
@@ -493,10 +546,97 @@ function UNIT:GetAmmo()
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Get the number of ammunition and in particular the number of shells, rockets, bombs and missiles a unit currently has.
|
||||||
|
-- @param #UNIT self
|
||||||
|
-- @return #number Total amount of ammo the unit has left. This is the sum of shells, rockets, bombs and missiles.
|
||||||
|
-- @return #number Number of shells left.
|
||||||
|
-- @return #number Number of rockets left.
|
||||||
|
-- @return #number Number of bombs left.
|
||||||
|
-- @return #number Number of missiles left.
|
||||||
|
function UNIT:GetAmmunition()
|
||||||
|
|
||||||
|
-- Init counter.
|
||||||
|
local nammo=0
|
||||||
|
local nshells=0
|
||||||
|
local nrockets=0
|
||||||
|
local nmissiles=0
|
||||||
|
local nbombs=0
|
||||||
|
|
||||||
|
local unit=self
|
||||||
|
|
||||||
|
-- Get ammo table.
|
||||||
|
local ammotable=unit:GetAmmo()
|
||||||
|
|
||||||
|
if ammotable then
|
||||||
|
|
||||||
|
local weapons=#ammotable
|
||||||
|
|
||||||
|
-- Loop over all weapons.
|
||||||
|
for w=1,weapons do
|
||||||
|
|
||||||
|
-- Number of current weapon.
|
||||||
|
local Nammo=ammotable[w]["count"]
|
||||||
|
|
||||||
|
-- Type name of current weapon.
|
||||||
|
local Tammo=ammotable[w]["desc"]["typeName"]
|
||||||
|
|
||||||
|
local _weaponString = UTILS.Split(Tammo,"%.")
|
||||||
|
local _weaponName = _weaponString[#_weaponString]
|
||||||
|
|
||||||
|
-- Get the weapon category: shell=0, missile=1, rocket=2, bomb=3
|
||||||
|
local Category=ammotable[w].desc.category
|
||||||
|
|
||||||
|
-- Get missile category: Weapon.MissileCategory AAM=1, SAM=2, BM=3, ANTI_SHIP=4, CRUISE=5, OTHER=6
|
||||||
|
local MissileCategory=nil
|
||||||
|
if Category==Weapon.Category.MISSILE then
|
||||||
|
MissileCategory=ammotable[w].desc.missileCategory
|
||||||
|
end
|
||||||
|
|
||||||
|
-- We are specifically looking for shells or rockets here.
|
||||||
|
if Category==Weapon.Category.SHELL then
|
||||||
|
|
||||||
|
-- Add up all shells.
|
||||||
|
nshells=nshells+Nammo
|
||||||
|
|
||||||
|
elseif Category==Weapon.Category.ROCKET then
|
||||||
|
|
||||||
|
-- Add up all rockets.
|
||||||
|
nrockets=nrockets+Nammo
|
||||||
|
|
||||||
|
elseif Category==Weapon.Category.BOMB then
|
||||||
|
|
||||||
|
-- Add up all rockets.
|
||||||
|
nbombs=nbombs+Nammo
|
||||||
|
|
||||||
|
elseif Category==Weapon.Category.MISSILE then
|
||||||
|
|
||||||
|
-- Add up all cruise missiles (category 5)
|
||||||
|
if MissileCategory==Weapon.MissileCategory.AAM then
|
||||||
|
nmissiles=nmissiles+Nammo
|
||||||
|
elseif MissileCategory==Weapon.MissileCategory.ANTI_SHIP then
|
||||||
|
nmissiles=nmissiles+Nammo
|
||||||
|
elseif MissileCategory==Weapon.MissileCategory.BM then
|
||||||
|
nmissiles=nmissiles+Nammo
|
||||||
|
elseif MissileCategory==Weapon.MissileCategory.OTHER then
|
||||||
|
nmissiles=nmissiles+Nammo
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Total amount of ammunition.
|
||||||
|
nammo=nshells+nrockets+nmissiles+nbombs
|
||||||
|
|
||||||
|
return nammo, nshells, nrockets, nbombs, nmissiles
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--- Returns the unit sensors.
|
--- Returns the unit sensors.
|
||||||
-- @param #UNIT self
|
-- @param #UNIT self
|
||||||
-- @return DCS#Unit.Sensors
|
-- @return DCS#Unit.Sensors Table of sensors.
|
||||||
-- @return #nil The DCS Unit is not existing or alive.
|
|
||||||
function UNIT:GetSensors()
|
function UNIT:GetSensors()
|
||||||
self:F2( self.UnitName )
|
self:F2( self.UnitName )
|
||||||
|
|
||||||
@@ -516,7 +656,6 @@ end
|
|||||||
--- Returns if the unit has sensors of a certain type.
|
--- Returns if the unit has sensors of a certain type.
|
||||||
-- @param #UNIT self
|
-- @param #UNIT self
|
||||||
-- @return #boolean returns true if the unit has specified types of sensors. This function is more preferable than Unit.getSensors() if you don't want to get information about all the unit's sensors, and just want to check if the unit has specified types of sensors.
|
-- @return #boolean returns true if the unit has specified types of sensors. This function is more preferable than Unit.getSensors() if you don't want to get information about all the unit's sensors, and just want to check if the unit has specified types of sensors.
|
||||||
-- @return #nil The DCS Unit is not existing or alive.
|
|
||||||
function UNIT:HasSensors( ... )
|
function UNIT:HasSensors( ... )
|
||||||
self:F2( arg )
|
self:F2( arg )
|
||||||
|
|
||||||
@@ -533,7 +672,6 @@ end
|
|||||||
--- Returns if the unit is SEADable.
|
--- Returns if the unit is SEADable.
|
||||||
-- @param #UNIT self
|
-- @param #UNIT self
|
||||||
-- @return #boolean returns true if the unit is SEADable.
|
-- @return #boolean returns true if the unit is SEADable.
|
||||||
-- @return #nil The DCS Unit is not existing or alive.
|
|
||||||
function UNIT:HasSEAD()
|
function UNIT:HasSEAD()
|
||||||
self:F2()
|
self:F2()
|
||||||
|
|
||||||
@@ -560,7 +698,6 @@ end
|
|||||||
-- @param #UNIT self
|
-- @param #UNIT self
|
||||||
-- @return #boolean Indicates if at least one of the unit's radar(s) is on.
|
-- @return #boolean Indicates if at least one of the unit's radar(s) is on.
|
||||||
-- @return DCS#Object The object of the radar's interest. Not nil only if at least one radar of the unit is tracking a target.
|
-- @return DCS#Object The object of the radar's interest. Not nil only if at least one radar of the unit is tracking a target.
|
||||||
-- @return #nil The DCS Unit is not existing or alive.
|
|
||||||
function UNIT:GetRadar()
|
function UNIT:GetRadar()
|
||||||
self:F2( self.UnitName )
|
self:F2( self.UnitName )
|
||||||
|
|
||||||
@@ -576,8 +713,7 @@ end
|
|||||||
|
|
||||||
--- Returns relative amount of fuel (from 0.0 to 1.0) the UNIT has in its internal tanks. If there are additional fuel tanks the value may be greater than 1.0.
|
--- Returns relative amount of fuel (from 0.0 to 1.0) the UNIT has in its internal tanks. If there are additional fuel tanks the value may be greater than 1.0.
|
||||||
-- @param #UNIT self
|
-- @param #UNIT self
|
||||||
-- @return #number The relative amount of fuel (from 0.0 to 1.0).
|
-- @return #number The relative amount of fuel (from 0.0 to 1.0) or *nil* if the DCS Unit is not existing or alive.
|
||||||
-- @return #nil The DCS Unit is not existing or alive.
|
|
||||||
function UNIT:GetFuel()
|
function UNIT:GetFuel()
|
||||||
self:F3( self.UnitName )
|
self:F3( self.UnitName )
|
||||||
|
|
||||||
@@ -670,6 +806,27 @@ function UNIT:GetDamageRelative()
|
|||||||
return 1
|
return 1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Returns the category of the #UNIT from descriptor. Returns one of
|
||||||
|
--
|
||||||
|
-- * Unit.Category.AIRPLANE
|
||||||
|
-- * Unit.Category.HELICOPTER
|
||||||
|
-- * Unit.Category.GROUND_UNIT
|
||||||
|
-- * Unit.Category.SHIP
|
||||||
|
-- * Unit.Category.STRUCTURE
|
||||||
|
--
|
||||||
|
-- @param #UNIT self
|
||||||
|
-- @return #number Unit category from `getDesc().category`.
|
||||||
|
function UNIT:GetUnitCategory()
|
||||||
|
self:F3( self.UnitName )
|
||||||
|
|
||||||
|
local DCSUnit = self:GetDCSObject()
|
||||||
|
if DCSUnit then
|
||||||
|
return DCSUnit:getDesc().category
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
--- Returns the category name of the #UNIT.
|
--- Returns the category name of the #UNIT.
|
||||||
-- @param #UNIT self
|
-- @param #UNIT self
|
||||||
-- @return #string Category name = Helicopter, Airplane, Ground Unit, Ship
|
-- @return #string Category name = Helicopter, Airplane, Ground Unit, Ship
|
||||||
@@ -747,7 +904,9 @@ end
|
|||||||
-- * Threat level 10: Unit is AAA.
|
-- * Threat level 10: Unit is AAA.
|
||||||
--
|
--
|
||||||
--
|
--
|
||||||
-- @param #UNIT self
|
-- @param #UNIT self
|
||||||
|
-- @return #number Number between 0 (low threat level) and 10 (high threat level).
|
||||||
|
-- @return #string Some text.
|
||||||
function UNIT:GetThreatLevel()
|
function UNIT:GetThreatLevel()
|
||||||
|
|
||||||
|
|
||||||
@@ -1078,5 +1237,121 @@ do -- Detection
|
|||||||
return IsLOS
|
return IsLOS
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Forces the unit to become aware of the specified target, without the unit manually detecting the other unit itself.
|
||||||
|
-- Applies only to a Unit Controller. Cannot be used at the group level.
|
||||||
|
-- @param #UNIT self
|
||||||
|
-- @param #UNIT TargetUnit The unit to be known.
|
||||||
|
-- @param #boolean TypeKnown The target type is known. If *false*, the type is not known.
|
||||||
|
-- @param #boolean DistanceKnown The distance to the target is known. If *false*, distance is unknown.
|
||||||
|
function UNIT:KnowUnit(TargetUnit, TypeKnown, DistanceKnown)
|
||||||
|
|
||||||
|
-- Defaults.
|
||||||
|
if TypeKnown~=false then
|
||||||
|
TypeKnown=true
|
||||||
|
end
|
||||||
|
if DistanceKnown~=false then
|
||||||
|
DistanceKnown=true
|
||||||
|
end
|
||||||
|
|
||||||
|
local DCSControllable = self:GetDCSObject()
|
||||||
|
|
||||||
|
if DCSControllable then
|
||||||
|
|
||||||
|
local Controller = DCSControllable:getController() --self:_GetController()
|
||||||
|
|
||||||
|
if Controller then
|
||||||
|
|
||||||
|
local object=TargetUnit:GetDCSObject()
|
||||||
|
|
||||||
|
if object then
|
||||||
|
|
||||||
|
self:I(string.format("Unit %s now knows target unit %s. Type known=%s, distance known=%s", self:GetName(), TargetUnit:GetName(), tostring(TypeKnown), tostring(DistanceKnown)))
|
||||||
|
|
||||||
|
Controller:knowTarget(object, TypeKnown, DistanceKnown)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Get the unit table from a unit's template.
|
||||||
|
-- @param #UNIT self
|
||||||
|
-- @return #table Table of the unit template (deep copy) or #nil.
|
||||||
|
function UNIT:GetTemplate()
|
||||||
|
|
||||||
|
local group=self:GetGroup()
|
||||||
|
|
||||||
|
local name=self:GetName()
|
||||||
|
|
||||||
|
if group then
|
||||||
|
local template=group:GetTemplate()
|
||||||
|
|
||||||
|
if template then
|
||||||
|
|
||||||
|
for _,unit in pairs(template.units) do
|
||||||
|
|
||||||
|
if unit.name==name then
|
||||||
|
return UTILS.DeepCopy(unit)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Get the payload table from a unit's template.
|
||||||
|
-- The payload table has elements:
|
||||||
|
--
|
||||||
|
-- * pylons
|
||||||
|
-- * fuel
|
||||||
|
-- * chaff
|
||||||
|
-- * gun
|
||||||
|
--
|
||||||
|
-- @param #UNIT self
|
||||||
|
-- @return #table Payload table (deep copy) or #nil.
|
||||||
|
function UNIT:GetTemplatePayload()
|
||||||
|
|
||||||
|
local unit=self:GetTemplate()
|
||||||
|
|
||||||
|
if unit then
|
||||||
|
return unit.payload
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get the pylons table from a unit's template. This can be a complex table depending on the weapons the unit is carrying.
|
||||||
|
-- @param #UNIT self
|
||||||
|
-- @return #table Table of pylons (deepcopy) or #nil.
|
||||||
|
function UNIT:GetTemplatePylons()
|
||||||
|
|
||||||
|
local payload=self:GetTemplatePayload()
|
||||||
|
|
||||||
|
if payload then
|
||||||
|
return payload.pylons
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get the fuel of the unit from its template.
|
||||||
|
-- @param #UNIT self
|
||||||
|
-- @return #number Fuel of unit in kg.
|
||||||
|
function UNIT:GetTemplateFuel()
|
||||||
|
|
||||||
|
local payload=self:GetTemplatePayload()
|
||||||
|
|
||||||
|
if payload then
|
||||||
|
return payload.fuel
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
Utilities/Routines.lua
|
Utilities/Routines.lua
|
||||||
Utilities/Utils.lua
|
Utilities/Utils.lua
|
||||||
|
Utilities/Enums.lua
|
||||||
|
Utilities/Profiler.lua
|
||||||
|
|
||||||
Core/Base.lua
|
Core/Base.lua
|
||||||
Core/UserFlag.lua
|
Core/UserFlag.lua
|
||||||
@@ -20,6 +22,7 @@ Core/Fsm.lua
|
|||||||
Core/Radio.lua
|
Core/Radio.lua
|
||||||
Core/Spawn.lua
|
Core/Spawn.lua
|
||||||
Core/SpawnStatic.lua
|
Core/SpawnStatic.lua
|
||||||
|
Core/Timer.lua
|
||||||
Core/Goal.lua
|
Core/Goal.lua
|
||||||
Core/Spot.lua
|
Core/Spot.lua
|
||||||
|
|
||||||
@@ -33,6 +36,7 @@ Wrapper/Client.lua
|
|||||||
Wrapper/Static.lua
|
Wrapper/Static.lua
|
||||||
Wrapper/Airbase.lua
|
Wrapper/Airbase.lua
|
||||||
Wrapper/Scenery.lua
|
Wrapper/Scenery.lua
|
||||||
|
Wrapper/Marker.lua
|
||||||
|
|
||||||
Cargo/Cargo.lua
|
Cargo/Cargo.lua
|
||||||
Cargo/CargoUnit.lua
|
Cargo/CargoUnit.lua
|
||||||
|
|||||||
@@ -73,18 +73,6 @@ MOOSE has a living (chat and video) community of users, beta testers and contrib
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# [Please DONATE ...](https://donorbox.org/fund-github-subscriptionfor-moose)
|
|
||||||
|
|
||||||
If you appreciate this development, please support to extend the framework. The development of this framework takes a lot of time.
|
|
||||||
A small gift would help me to buy a new small laptop that I can use to extend this framework while commuting to and from work ...
|
|
||||||
Also, your donations will be saved and spent wisely to the advantage of the community!
|
|
||||||
|
|
||||||
If everyone helps with a small amount, it would be really great!
|
|
||||||
|
|
||||||
<a class="dbox-donation-button" href="https://donorbox.org/fund-github-subscriptionfor-moose" style="background:#2d81c5 url(https://raw.githubusercontent.com/FlightControl-Master/MOOSE_DOCS/master/Configuration/Donate.png) no-repeat 37px center; color: #fff;text-decoration: none;font-family: Verdana,sans-serif;display: inline-block;font-size: 16px;padding: 15px 38px 15px 75px; -webkit-border-radius: 2px; -moz-border-radius: 2px; border-radius: 2px; box-shadow: 0 1px 0 0 #1f5a89; text-shadow: 0 1px rgba(0, 0, 0, 0.3);" >Donate</a>
|
|
||||||
|
|
||||||
|
|
||||||
Kind regards,
|
Kind regards,
|
||||||
FlightControl (FC)
|
FlightControl (FC)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user