Compare commits

..

114 Commits

Author SHA1 Message Date
Applevangelist d6d9c9d8cf Merge remote-tracking branch 'origin/master' into develop 2024-09-08 13:22:34 +02:00
Applevangelist 7f572a1a9b Small changes
#CSAR - add option for IR strobe
2024-09-08 13:22:10 +02:00
Applevangelist 68007306b3 Merge remote-tracking branch 'origin/develop' into develop 2024-09-08 11:44:47 +02:00
Applevangelist 0c3f97370c Merge remote-tracking branch 'origin/master' into develop
# Conflicts:
#	Moose Development/Moose/Wrapper/Group.lua
2024-09-08 11:44:44 +02:00
Applevangelist d62025dfe0 Small fixes 2024-09-08 11:43:33 +02:00
Thomas 6bc766e95f Merge pull request #2175 from FlightControl-Master/master
Update CSAR.lua
2024-09-07 09:03:00 +02:00
Thomas 07009630c6 Update CSAR.lua
Small fix
2024-09-07 09:01:58 +02:00
Applevangelist c2aeb1ebcd Merge remote-tracking branch 'origin/master' into develop 2024-09-06 16:41:11 +02:00
Applevangelist 865042a843 #CTLD #CSAR Function to add own SET_GROUP for pilots 2024-09-06 16:40:41 +02:00
Applevangelist 6243137d4c QoL 2024-09-06 13:42:14 +02:00
Applevangelist f00d0dc871 QoL 2024-09-06 13:40:27 +02:00
Applevangelist 8695953d5a #SPAWN - performance tuning for event workaround 2024-09-03 16:47:17 +02:00
Applevangelist 6afb68390b Merge remote-tracking branch 'origin/master' into develop 2024-09-01 15:37:31 +02:00
Applevangelist d6adcdf8bd #CONTROLLABLE - Added IR Marker Beacons for UNIT and GROUP objects 2024-09-01 15:36:41 +02:00
Applevangelist 8151700ad7 Merge remote-tracking branch 'origin/master' into develop
# Conflicts:
#	Moose Development/Moose/Ops/CTLD.lua
2024-09-01 13:37:34 +02:00
Applevangelist 2c192fba30 #SET - include checking functional filters in all sub-classes 2024-09-01 13:36:47 +02:00
Applevangelist 97f11c93bb #CTLD 2024-09-01 12:41:36 +02:00
Thomas a3102a7381 Merge pull request #2172 from DarthZyll/patch-5
Update CTLD.lua for missing self.ChinookTroopCircleRadius
2024-09-01 08:55:18 +02:00
Mike Young d41b5e8ede Update CTLD.lua for missing self.ChinookTroopCircleRadius
self.ChinookTroopCircleRadius was not being set
2024-09-01 02:52:33 -04:00
Applevangelist a45856c925 Merge remote-tracking branch 'origin/master' into develop 2024-08-29 10:25:40 +02:00
Applevangelist f531fdaa70 #RANGE less noise 2024-08-29 10:25:13 +02:00
Applevangelist f4b2f07656 Merge remote-tracking branch 'origin/master' into develop 2024-08-29 10:22:32 +02:00
Applevangelist 81f8e84ca4 xx 2024-08-29 10:22:14 +02:00
Applevangelist f7e64d98bc Merge remote-tracking branch 'origin/master' into develop 2024-08-27 18:37:56 +02:00
Applevangelist d74de11b8b CTLD small fix of container shape 2024-08-27 18:37:21 +02:00
Applevangelist 4380c1be2e Merge remote-tracking branch 'origin/master' into develop 2024-08-27 13:19:24 +02:00
Applevangelist 30f2097d7a #AIRBOSS - small fix in Numer2Sound etc 2024-08-27 13:18:53 +02:00
Applevangelist db2d4e97a6 Merge remote-tracking branch 'origin/master' into develop 2024-08-27 10:56:46 +02:00
Applevangelist f903844059 #CTLD - fix for type name restrictions in other functions 2024-08-27 10:56:14 +02:00
Applevangelist b4653be54e Merge remote-tracking branch 'origin/master' into develop 2024-08-26 18:31:07 +02:00
Applevangelist 68b2b452cc xx 2024-08-26 18:30:41 +02:00
Applevangelist e2b6efde7a Merge remote-tracking branch 'origin/master' into develop 2024-08-26 18:22:59 +02:00
Applevangelist 668d120d60 CTLD Small fix for crate removal 2024-08-26 18:22:32 +02:00
Applevangelist 3eea17bc76 Merge remote-tracking branch 'origin/develop' into develop 2024-08-26 15:53:23 +02:00
Applevangelist 2894bcc833 Merge remote-tracking branch 'origin/master' into develop 2024-08-26 15:53:20 +02:00
Applevangelist 7543f31c85 #CTLD
* Added option for crates to have any static shape (per crate type option)
* Added option for crates only to be transported by defined helo type names (per crate type option)
2024-08-26 15:52:50 +02:00
Thomas ff52197707 Merge pull request #2171 from FlightControl-Master/master
Update Utils.lua
2024-08-25 11:23:42 +02:00
Thomas 56d84e7b25 Update Utils.lua
Small fix
2024-08-25 11:22:30 +02:00
Applevangelist b025abaa88 Merge remote-tracking branch 'origin/master' into develop 2024-08-24 18:18:36 +02:00
Applevangelist ed2d3d856b Small fix 2024-08-24 18:18:08 +02:00
Applevangelist dac637f360 Merge remote-tracking branch 'origin/master' into develop 2024-08-23 16:29:18 +02:00
Applevangelist 1e5c3a3c21 #ENUMS storage AH64D weapons additions 2024-08-23 16:28:35 +02:00
Applevangelist 861588205a Merge remote-tracking branch 'origin/master' into develop 2024-08-23 13:56:58 +02:00
Applevangelist 37d5b6a0fc #Add'l storage items 2024-08-23 13:55:18 +02:00
Applevangelist 4d3fb2990e Merge remote-tracking branch 'origin/master' into develop 2024-08-23 12:47:37 +02:00
Applevangelist c58a954d18 #CTLD
* Fix for spawning the correct number of crates on inject
* Simplified example docu section 7 on how to build a FARP
* Some prep work for additional stuff
2024-08-23 12:44:17 +02:00
Applevangelist cce878e759 Merge remote-tracking branch 'origin/master' into develop 2024-08-22 18:27:00 +02:00
Applevangelist 0d481afa16 #SET_GROUP - small fix for FilterPrefixes compute 2024-08-22 18:26:34 +02:00
Applevangelist 2dbad7cb1b Merge remote-tracking branch 'origin/master' into develop 2024-08-22 17:18:13 +02:00
Applevangelist 016875d724 #ENUMS - added a couple of items to ENUMS.Storage.weapons for the Gazelle and CH-47 which do not have a name representation in the object warehouse
#UTILS Added function `UTILS.SpawnFARPAndFunctionalStatics()` to spawn a functional FARP with static items (and some options)
#UTILS Added VHF Beacon Frequencies for newer maps to avoid overlaps in `UTILS.GenerateVHFrequencies()`
2024-08-22 17:17:10 +02:00
Applevangelist 7a0fa629b5 Merge remote-tracking branch 'origin/master' into develop 2024-08-20 18:03:59 +02:00
Applevangelist 5df0d60135 Smaller Fixes 2024-08-20 18:03:18 +02:00
Applevangelist aee7bd8bb6 Merge remote-tracking branch 'origin/master' into develop 2024-08-20 10:56:08 +02:00
Applevangelist e77d61c4cb small correction 2024-08-20 10:55:41 +02:00
Applevangelist b1a40407b3 Merge remote-tracking branch 'origin/master' into develop 2024-08-20 10:47:56 +02:00
Applevangelist 504142c585 #CTLD Added self.TroopUnloadDistGround = 1.5, and self.TroopUnloadDistHover = 5,
#CSAR Added option to switch off ADF beacons
2024-08-20 10:47:28 +02:00
Thomas 0496571c92 Merge pull request #2170 from DarthZyll/patch-4
Update CSAR.lua - remove luadoc param addBeacon on SpawnCASEVAC()
2024-08-20 09:35:34 +02:00
Mike Young 62a0adce5a Update CSAR.lua - remove luadoc param addBeacon on SpawnCASEVAC()
this param doesn't actually exist, purely a luadoc correction
2024-08-19 13:46:21 -04:00
Applevangelist d1a1be1a9e Merge remote-tracking branch 'origin/develop' into develop 2024-08-18 19:38:27 +02:00
Applevangelist 80011f4e4e Merge remote-tracking branch 'origin/master' into develop 2024-08-18 19:38:24 +02:00
Applevangelist 80df849d18 #SET_GROUP small enhancement for prefix filter 2024-08-18 19:37:00 +02:00
Frank c2933b6bed Update Legion.lua
- commented out debug info line
2024-08-18 18:19:05 +02:00
Frank fc4ba9f21d Merge branch 'master' into develop 2024-08-18 18:06:30 +02:00
Frank e74c79b5d6 Merge branch 'master' of https://github.com/FlightControl-Master/MOOSE 2024-08-18 16:56:44 +02:00
Frank f738ddfca8 Update Positionable.lua
- Added cargo bay of "MaxxPro_MRAP"
2024-08-18 16:56:42 +02:00
Applevangelist 5bbd122fa4 Merge remote-tracking branch 'origin/master' into develop 2024-08-18 14:09:10 +02:00
Applevangelist af45b0d709 #EVENT DynamicCargoRemove fix is name is empty 2024-08-18 14:08:46 +02:00
Applevangelist 928c20c867 Merge remote-tracking branch 'origin/develop' into develop 2024-08-18 13:58:58 +02:00
Applevangelist 4bd36a4786 Merge remote-tracking branch 'origin/master' into develop 2024-08-18 13:58:55 +02:00
Applevangelist e746617139 #Rap up changes 2024-08-18 13:58:18 +02:00
Thomas 3105f7407d Merge pull request #2169 from FlightControl-Master/Applevangelist-patch-1
Update ATIS.lua
2024-08-18 13:14:13 +02:00
Thomas 2f568bca17 Update ATIS.lua
#ATIS New Light Rain presets
2024-08-18 13:11:58 +02:00
Frank ad7dba6fac Merge pull request #2168 from FlightControl-Master/FF/Ops
CHIEF v0.6.1
2024-08-17 23:56:07 +02:00
Frank 9efe0fe243 CHIEF v0.6.1
- Strategic zone: If zero transports are available and min carriers is zero, cargo assets need to go by themselfs.
2024-08-17 23:50:52 +02:00
Thomas 2836d7a40f Merge pull request #2167 from FlightControl-Master/Applevangelist-DC-1
Update DynamicCargo.lua
2024-08-17 14:20:51 +02:00
Thomas f1bf62e3c1 Update DynamicCargo.lua
#DYNAMICCARGO
2024-08-17 14:20:31 +02:00
Applevangelist a560d65ce7 Merge remote-tracking branch 'origin/master' into develop 2024-08-17 11:37:11 +02:00
Applevangelist 9de3cb73f7 Merge remote-tracking branch 'origin/develop' into develop 2024-08-17 11:36:17 +02:00
Applevangelist 757cc86a68 xx 2024-08-17 11:36:13 +02:00
Applevangelist aeb1664134 CTLD 2024-08-17 11:36:01 +02:00
Frank 2af1483724 Merge branch 'master' into develop 2024-08-16 23:13:22 +02:00
Frank b7702ab933 Merge pull request #2166 from FlightControl-Master/Statua-patch-1
Update ClientWatch.lua
2024-08-16 23:10:25 +02:00
Statua cc14f82e85 Update ClientWatch.lua
-Added check to verify the aircraft is controlled by a player
-Added :FilterByCoalition() and :FilterByCategory()
-Added ability to get ALL CLIENTS by leaving param1 of :New() blank
-Added more console outputs if CLIENTWATCH.Debug is true
-Minor documentation fixes
2024-08-16 15:19:26 -05:00
Applevangelist f23dd0a5dd Merge remote-tracking branch 'origin/master' into develop 2024-08-16 16:23:42 +02:00
Applevangelist 5aea17e20e #SET_DYNAMICCARGO Docu 2024-08-16 16:23:13 +02:00
Applevangelist 8336b744bb Merge remote-tracking branch 'origin/master' into develop 2024-08-16 15:46:34 +02:00
Applevangelist ad9eaea010 #SET - many less calls 2024-08-16 15:46:07 +02:00
Applevangelist 9c47e35d54 Merge remote-tracking branch 'origin/master' into develop
# Conflicts:
#	Moose Development/Moose/Wrapper/DynamicCargo.lua
2024-08-16 15:22:45 +02:00
Applevangelist 284a770daa Added #SET_DYNAMICCARGO 2024-08-16 15:21:46 +02:00
Applevangelist 16030d4fa1 Delete some non ready classes 2024-08-16 11:28:50 +02:00
Applevangelist 37d2dd17d7 Merge remote-tracking branch 'origin/master' into develop 2024-08-16 09:44:42 +02:00
Applevangelist ccd190a8b1 xx 2024-08-16 09:44:00 +02:00
Applevangelist 36bf2436b6 Merge remote-tracking branch 'origin/master' into develop
# Conflicts:
#	Moose Development/Moose/Core/Event.lua
#	Moose Development/Moose/Ops/CTLD.lua
#	Moose Development/Moose/Wrapper/DynamicCargo.lua
2024-08-16 09:39:48 +02:00
Applevangelist 19f6a8d8f6 #DYNAMICCARGO - Added functionalty 2024-08-16 09:36:29 +02:00
Applevangelist b8e09afcce Merge remote-tracking branch 'origin/master' into develop 2024-08-14 15:43:24 +02:00
Applevangelist 24264bd885 #ATIS French Translations 2024-08-14 15:42:46 +02:00
Applevangelist ed690ee6e9 Merge remote-tracking branch 'origin/master' into develop 2024-08-14 11:34:27 +02:00
Applevangelist 872bb3d775 #RANGE Fix trying to get a playername on dynamic cargo spawns 2024-08-14 11:33:13 +02:00
Applevangelist c0dcd12ada Merge remote-tracking branch 'origin/master' into develop 2024-08-14 09:47:39 +02:00
Applevangelist d36cd8e284 #UNIT - Fix getting skill from N/A Templates 2024-08-14 09:46:10 +02:00
Applevangelist 5d98672de5 #ATIS - Polar circle fixes 2024-08-13 10:31:26 +02:00
Applevangelist eab643268f #ATIS - Polar circle fixes 2024-08-13 10:30:46 +02:00
Applevangelist e2fa1f992b Merge remote-tracking branch 'origin/master' into develop 2024-08-12 19:06:01 +02:00
Applevangelist 9356794112 bit of performance tuning 2024-08-12 19:05:32 +02:00
Applevangelist bb865aef38 Merge branch 'master' into develop 2024-08-12 17:01:13 +02:00
Applevangelist 35c24810f9 xx 2024-08-12 17:00:52 +02:00
Applevangelist 875b5fb34d Merge remote-tracking branch 'origin/develop' into develop 2024-08-12 16:17:30 +02:00
Applevangelist 19187bcb14 xx 2024-08-12 16:17:21 +02:00
Thomas ebe6e9fb9f Merge pull request #2165 from FlightControl-Master/master
Various
2024-08-12 11:40:43 +02:00
Thomas a54944b021 Update CTLD.lua (#2164)
#CTLD 
* Fix for helo being no Chinook not finding crates e.g. on a ship or FARP
* `nil` check for static cargo position check
2024-08-12 11:39:03 +02:00
Thomas 5f7f75b1c9 BASE and SPAWN tuning (#2162)
* Update Base.lua (#2159)

Performance tuning - the BASE:I, F, T calls rank very high in overall number of calls taken from Moose. Ensure only the minimum number of actions based on trace state and level is taken

* Update Spawn.lua (#2161)

Updating this class as it calls BASE I,F,T a lot. Making it less noisy for some performance tuning
2024-08-12 10:18:14 +02:00
Thomas bc9938d08a Update Spawn.lua (#2161)
Updating this class as it calls BASE I,F,T a lot. Making it less noisy for some performance tuning
2024-08-12 10:16:40 +02:00
Thomas 59963e152d Update Base.lua (#2159) (#2160)
Performance tuning - the BASE:I, F, T calls rank very high in overall number of calls taken from Moose. Ensure only the minimum number of actions based on trace state and level is taken
2024-08-12 09:47:38 +02:00
Thomas b77f179acc Update Base.lua (#2159)
Performance tuning - the BASE:I, F, T calls rank very high in overall number of calls taken from Moose. Ensure only the minimum number of actions based on trace state and level is taken
2024-08-12 09:44:13 +02:00
34 changed files with 3514 additions and 5714 deletions
@@ -3895,10 +3895,14 @@ do -- AI_A2G_DISPATCHER
if Squadron then if Squadron then
local FirstUnit = AttackSetUnit:GetRandomSurely() local FirstUnit = AttackSetUnit:GetRandomSurely()
if FirstUnit then
local Coordinate = FirstUnit:GetCoordinate() -- Core.Point#COORDINATE local Coordinate = FirstUnit:GetCoordinate() -- Core.Point#COORDINATE
if self.SetSendPlayerMessages then if self.SetSendPlayerMessages then
Dispatcher:MessageToPlayers( Squadron, DefenderName .. ", on route to ground target at " .. Coordinate:ToStringA2G( DefenderGroup ), DefenderGroup ) Dispatcher:MessageToPlayers( Squadron, DefenderName .. ", on route to ground target at " .. Coordinate:ToStringA2G( DefenderGroup ), DefenderGroup )
end end
else
return
end
end end
self:GetParent(self).onafterEngageRoute( self, DefenderGroup, From, Event, To, AttackSetUnit ) self:GetParent(self).onafterEngageRoute( self, DefenderGroup, From, Event, To, AttackSetUnit )
end end
@@ -4785,3 +4789,4 @@ end
end end
self:T({Squadron = Squadron.Name,SquadronResourceCount = Squadron.ResourceCount}) self:T({Squadron = Squadron.Name,SquadronResourceCount = Squadron.ResourceCount})
end end
+1
View File
@@ -9,6 +9,7 @@
-- @module AI.AI_Air -- @module AI.AI_Air
-- @image MOOSE.JPG -- @image MOOSE.JPG
---
-- @type AI_AIR -- @type AI_AIR
-- @extends Core.Fsm#FSM_CONTROLLABLE -- @extends Core.Fsm#FSM_CONTROLLABLE
+87 -7
View File
@@ -26,7 +26,7 @@
-- @module Core.Base -- @module Core.Base
-- @image Core_Base.JPG -- @image Core_Base.JPG
local _TraceOnOff = true local _TraceOnOff = false -- default to no tracing
local _TraceLevel = 1 local _TraceLevel = 1
local _TraceAll = false local _TraceAll = false
local _TraceClass = {} local _TraceClass = {}
@@ -742,6 +742,30 @@ 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.
--- Occurs when a player creates a dynamic cargo object from the F8 ground crew menu.
-- *** NOTE *** this is a workarounf for DCS not creating these events as of Aug 2024.
-- @function [parent=#BASE] OnEventNewDynamicCargo
-- @param #BASE self
-- @param Core.Event#EVENTDATA EventData The EventData structure.
--- Occurs when a player loads a dynamic cargo object with the F8 ground crew menu into a helo.
-- *** NOTE *** this is a workarounf for DCS not creating these events as of Aug 2024.
-- @function [parent=#BASE] OnEventDynamicCargoLoaded
-- @param #BASE self
-- @param Core.Event#EVENTDATA EventData The EventData structure.
--- Occurs when a player unloads a dynamic cargo object with the F8 ground crew menu from a helo.
-- *** NOTE *** this is a workarounf for DCS not creating these events as of Aug 2024.
-- @function [parent=#BASE] OnEventDynamicCargoUnloaded
-- @param #BASE self
-- @param Core.Event#EVENTDATA EventData The EventData structure.
--- Occurs when a dynamic cargo crate is removed.
-- *** NOTE *** this is a workarounf for DCS not creating these events as of Aug 2024.
-- @function [parent=#BASE] OnEventDynamicCargoRemoved
-- @param #BASE self
-- @param Core.Event#EVENTDATA EventData The EventData structure.
end end
--- Creation of a Birth Event. --- Creation of a Birth Event.
@@ -863,6 +887,62 @@ end
world.onEvent(Event) world.onEvent(Event)
end end
--- Creation of a S_EVENT_NEW_DYNAMIC_CARGO event.
-- @param #BASE self
-- @param Wrapper.DynamicCargo#DYNAMICCARGO DynamicCargo the dynamic cargo object
function BASE:CreateEventNewDynamicCargo(DynamicCargo)
self:F({DynamicCargo})
local Event = {
id = EVENTS.NewDynamicCargo,
time = timer.getTime(),
dynamiccargo = DynamicCargo,
initiator = DynamicCargo:GetDCSObject(),
}
world.onEvent( Event )
end
--- Creation of a S_EVENT_DYNAMIC_CARGO_LOADED event.
-- @param #BASE self
-- @param Wrapper.DynamicCargo#DYNAMICCARGO DynamicCargo the dynamic cargo object
function BASE:CreateEventDynamicCargoLoaded(DynamicCargo)
self:F({DynamicCargo})
local Event = {
id = EVENTS.DynamicCargoLoaded,
time = timer.getTime(),
dynamiccargo = DynamicCargo,
initiator = DynamicCargo:GetDCSObject(),
}
world.onEvent( Event )
end
--- Creation of a S_EVENT_DYNAMIC_CARGO_UNLOADED event.
-- @param #BASE self
-- @param Wrapper.DynamicCargo#DYNAMICCARGO DynamicCargo the dynamic cargo object
function BASE:CreateEventDynamicCargoUnloaded(DynamicCargo)
self:F({DynamicCargo})
local Event = {
id = EVENTS.DynamicCargoUnloaded,
time = timer.getTime(),
dynamiccargo = DynamicCargo,
initiator = DynamicCargo:GetDCSObject(),
}
world.onEvent( Event )
end
--- Creation of a S_EVENT_DYNAMIC_CARGO_REMOVED event.
-- @param #BASE self
-- @param Wrapper.DynamicCargo#DYNAMICCARGO DynamicCargo the dynamic cargo object
function BASE:CreateEventDynamicCargoRemoved(DynamicCargo)
self:F({DynamicCargo})
local Event = {
id = EVENTS.DynamicCargoRemoved,
time = timer.getTime(),
dynamiccargo = DynamicCargo,
initiator = DynamicCargo:GetDCSObject(),
}
world.onEvent( Event )
end
--- The main event handling function... This function captures all events generated for the class. --- The main event handling function... This function captures all events generated for the class.
-- @param #BASE self -- @param #BASE self
-- @param DCS#Event event -- @param DCS#Event event
@@ -1200,7 +1280,7 @@ end
-- @param Arguments A #table or any field. -- @param Arguments A #table or any field.
function BASE:F( Arguments ) function BASE:F( Arguments )
if BASE.Debug and _TraceOnOff then if BASE.Debug and _TraceOnOff == true then
local DebugInfoCurrent = BASE.Debug.getinfo( 2, "nl" ) local DebugInfoCurrent = BASE.Debug.getinfo( 2, "nl" )
local DebugInfoFrom = BASE.Debug.getinfo( 3, "l" ) local DebugInfoFrom = BASE.Debug.getinfo( 3, "l" )
@@ -1215,7 +1295,7 @@ end
-- @param Arguments A #table or any field. -- @param Arguments A #table or any field.
function BASE:F2( Arguments ) function BASE:F2( Arguments )
if BASE.Debug and _TraceOnOff then if BASE.Debug and _TraceOnOff == true and _TraceLevel >= 2 then
local DebugInfoCurrent = BASE.Debug.getinfo( 2, "nl" ) local DebugInfoCurrent = BASE.Debug.getinfo( 2, "nl" )
local DebugInfoFrom = BASE.Debug.getinfo( 3, "l" ) local DebugInfoFrom = BASE.Debug.getinfo( 3, "l" )
@@ -1230,7 +1310,7 @@ end
-- @param Arguments A #table or any field. -- @param Arguments A #table or any field.
function BASE:F3( Arguments ) function BASE:F3( Arguments )
if BASE.Debug and _TraceOnOff then if BASE.Debug and _TraceOnOff == true and _TraceLevel >= 3 then
local DebugInfoCurrent = BASE.Debug.getinfo( 2, "nl" ) local DebugInfoCurrent = BASE.Debug.getinfo( 2, "nl" )
local DebugInfoFrom = BASE.Debug.getinfo( 3, "l" ) local DebugInfoFrom = BASE.Debug.getinfo( 3, "l" )
@@ -1274,7 +1354,7 @@ end
-- @param Arguments A #table or any field. -- @param Arguments A #table or any field.
function BASE:T( Arguments ) function BASE:T( Arguments )
if BASE.Debug and _TraceOnOff then if BASE.Debug and _TraceOnOff == true then
local DebugInfoCurrent = BASE.Debug.getinfo( 2, "nl" ) local DebugInfoCurrent = BASE.Debug.getinfo( 2, "nl" )
local DebugInfoFrom = BASE.Debug.getinfo( 3, "l" ) local DebugInfoFrom = BASE.Debug.getinfo( 3, "l" )
@@ -1289,7 +1369,7 @@ end
-- @param Arguments A #table or any field. -- @param Arguments A #table or any field.
function BASE:T2( Arguments ) function BASE:T2( Arguments )
if BASE.Debug and _TraceOnOff then if BASE.Debug and _TraceOnOff == true and _TraceLevel >= 2 then
local DebugInfoCurrent = BASE.Debug.getinfo( 2, "nl" ) local DebugInfoCurrent = BASE.Debug.getinfo( 2, "nl" )
local DebugInfoFrom = BASE.Debug.getinfo( 3, "l" ) local DebugInfoFrom = BASE.Debug.getinfo( 3, "l" )
@@ -1304,7 +1384,7 @@ end
-- @param Arguments A #table or any field. -- @param Arguments A #table or any field.
function BASE:T3( Arguments ) function BASE:T3( Arguments )
if BASE.Debug and _TraceOnOff then if BASE.Debug and _TraceOnOff == true and _TraceLevel >= 3 then
local DebugInfoCurrent = BASE.Debug.getinfo( 2, "nl" ) local DebugInfoCurrent = BASE.Debug.getinfo( 2, "nl" )
local DebugInfoFrom = BASE.Debug.getinfo( 3, "l" ) local DebugInfoFrom = BASE.Debug.getinfo( 3, "l" )
+92 -14
View File
@@ -20,6 +20,7 @@
-- * Manage database of hits to units and statics. -- * Manage database of hits to units and statics.
-- * Manage database of destroys of units and statics. -- * Manage database of destroys of units and statics.
-- * Manage database of @{Core.Zone#ZONE_BASE} objects. -- * Manage database of @{Core.Zone#ZONE_BASE} objects.
-- * Manage database of @{Wrapper.DynamicCargo#DYNAMICCARGO} objects alive in the mission.
-- --
-- === -- ===
-- --
@@ -39,6 +40,7 @@
-- @field #table STORAGES DCS warehouse storages. -- @field #table STORAGES DCS warehouse storages.
-- @field #table STNS Used Link16 octal numbers for F16/15/18/AWACS planes. -- @field #table STNS Used Link16 octal numbers for F16/15/18/AWACS planes.
-- @field #table SADL Used Link16 octal numbers for A10/C-II planes. -- @field #table SADL Used Link16 octal numbers for A10/C-II planes.
-- @field #table DYNAMICCARGO Dynamic Cargo objects.
-- @extends Core.Base#BASE -- @extends Core.Base#BASE
--- Contains collections of wrapper objects defined within MOOSE that reflect objects within the simulator. --- Contains collections of wrapper objects defined within MOOSE that reflect objects within the simulator.
@@ -54,6 +56,7 @@
-- * PLAYERS -- * PLAYERS
-- * CARGOS -- * CARGOS
-- * STORAGES (DCS warehouses) -- * STORAGES (DCS warehouses)
-- * DYNAMICCARGO
-- --
-- On top, for internal MOOSE administration purposes, the DATABASE administers the Unit and Group TEMPLATES as defined within the Mission Editor. -- On top, for internal MOOSE administration purposes, the DATABASE administers the Unit and Group TEMPLATES as defined within the Mission Editor.
-- --
@@ -97,6 +100,7 @@ DATABASE = {
STORAGES = {}, STORAGES = {},
STNS={}, STNS={},
SADL={}, SADL={},
DYNAMICCARGO={},
} }
local _DATABASECoalition = local _DATABASECoalition =
@@ -143,6 +147,8 @@ function DATABASE:New()
self:HandleEvent( EVENTS.DeleteZone ) self:HandleEvent( EVENTS.DeleteZone )
--self:HandleEvent( EVENTS.PlayerEnterUnit, self._EventOnPlayerEnterUnit ) -- This is not working anymore!, handling this through the birth event. --self:HandleEvent( EVENTS.PlayerEnterUnit, self._EventOnPlayerEnterUnit ) -- This is not working anymore!, handling this through the birth event.
self:HandleEvent( EVENTS.PlayerLeaveUnit, self._EventOnPlayerLeaveUnit ) self:HandleEvent( EVENTS.PlayerLeaveUnit, self._EventOnPlayerLeaveUnit )
-- DCS 2.9.7 Moose own dynamic cargo events
self:HandleEvent( EVENTS.DynamicCargoRemoved, self._EventOnDynamicCargoRemoved)
self:_RegisterTemplates() self:_RegisterTemplates()
self:_RegisterGroupsAndUnits() self:_RegisterGroupsAndUnits()
@@ -174,15 +180,19 @@ end
-- @return Wrapper.Unit#UNIT The added unit. -- @return Wrapper.Unit#UNIT The added unit.
function DATABASE:AddUnit( DCSUnitName, force ) function DATABASE:AddUnit( DCSUnitName, force )
if not self.UNITS[DCSUnitName] or force == true then local DCSunitName = DCSUnitName
if type(DCSunitName) == "number" then DCSunitName = string.format("%d",DCSUnitName) end
if not self.UNITS[DCSunitName] or force == true then
-- Debug info. -- Debug info.
self:T( { "Add UNIT:", DCSUnitName } ) self:T( { "Add UNIT:", DCSunitName } )
-- Register unit -- Register unit
self.UNITS[DCSUnitName]=UNIT:Register(DCSUnitName) self.UNITS[DCSunitName]=UNIT:Register(DCSunitName)
end end
return self.UNITS[DCSUnitName] return self.UNITS[DCSunitName]
end end
@@ -224,6 +234,34 @@ function DATABASE:FindStatic( StaticName )
return StaticFound return StaticFound
end end
--- Add a DynamicCargo to the database.
-- @param #DATABASE self
-- @param #string Name Name of the dynamic cargo.
-- @return Wrapper.DynamicCargo#DYNAMICCARGO The dynamic cargo object.
function DATABASE:AddDynamicCargo( Name )
if not self.DYNAMICCARGO[Name] then
self.DYNAMICCARGO[Name] = DYNAMICCARGO:Register(Name)
return self.DYNAMICCARGO[Name]
end
return nil
end
--- Finds a DYNAMICCARGO based on the Dynamic Cargo Name.
-- @param #DATABASE self
-- @param #string DynamicCargoName
-- @return Wrapper.DynamicCargo#DYNAMICCARGO The found DYNAMICCARGO.
function DATABASE:FindDynamicCargo( DynamicCargoName )
local StaticFound = self.DYNAMICCARGO[DynamicCargoName]
return StaticFound
end
--- Deletes a DYNAMICCARGO from the DATABASE based on the Dynamic Cargo Name.
-- @param #DATABASE self
function DATABASE:DeleteDynamicCargo( DynamicCargoName )
self.DYNAMICCARGO[DynamicCargoName] = nil
return self
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.
@@ -819,11 +857,15 @@ end
-- @return Wrapper.Client#CLIENT The client object. -- @return Wrapper.Client#CLIENT The client object.
function DATABASE:AddClient( ClientName, Force ) function DATABASE:AddClient( ClientName, Force )
if not self.CLIENTS[ClientName] or Force == true then local DCSUnitName = ClientName
self.CLIENTS[ClientName] = CLIENT:Register( ClientName )
if type(DCSUnitName) == "number" then DCSUnitName = string.format("%d",ClientName) end
if not self.CLIENTS[DCSUnitName] or Force == true then
self.CLIENTS[DCSUnitName] = CLIENT:Register( DCSUnitName )
end end
return self.CLIENTS[ClientName] return self.CLIENTS[DCSUnitName]
end end
@@ -864,8 +906,10 @@ end
-- @param #DATABASE self -- @param #DATABASE self
function DATABASE:AddPlayer( UnitName, PlayerName ) function DATABASE:AddPlayer( UnitName, PlayerName )
if type(UnitName) == "number" then UnitName = string.format("%d",UnitName) end
if PlayerName then if PlayerName then
self:T( { "Add player for unit:", UnitName, PlayerName } ) self:I( { "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
@@ -873,6 +917,21 @@ function DATABASE:AddPlayer( UnitName, PlayerName )
end end
--- Get a PlayerName by UnitName from PLAYERS in DATABASE.
-- @param #DATABASE self
-- @return #string PlayerName
-- @return Wrapper.Unit#UNIT PlayerUnit
function DATABASE:_FindPlayerNameByUnitName(UnitName)
if UnitName then
for playername,unitname in pairs(self.PLAYERS) do
if unitname == UnitName and self.PLAYERUNITS[playername] and self.PLAYERUNITS[playername]:IsAlive() then
return playername, self.PLAYERUNITS[playername]
end
end
end
return nil
end
--- Deletes a player from the DATABASE based on the Player Name. --- Deletes a player from the DATABASE based on the Player Name.
-- @param #DATABASE self -- @param #DATABASE self
function DATABASE:DeletePlayer( UnitName, PlayerName ) function DATABASE:DeletePlayer( UnitName, PlayerName )
@@ -1244,7 +1303,7 @@ function DATABASE:_GetGenericStaticCargoGroupTemplate(Name,Typename,Mass,Coaliti
StaticTemplate.CategoryID = "static" StaticTemplate.CategoryID = "static"
StaticTemplate.CoalitionID = Coalition or coalition.side.BLUE StaticTemplate.CoalitionID = Coalition or coalition.side.BLUE
StaticTemplate.CountryID = Country or country.id.GERMANY StaticTemplate.CountryID = Country or country.id.GERMANY
UTILS.PrintTableToLog(StaticTemplate) --UTILS.PrintTableToLog(StaticTemplate)
return StaticTemplate return StaticTemplate
end end
@@ -1324,7 +1383,7 @@ function DATABASE:GetCoalitionFromClientTemplate( ClientName )
if self.Templates.ClientsByName[ClientName] then if self.Templates.ClientsByName[ClientName] then
return self.Templates.ClientsByName[ClientName].CoalitionID return self.Templates.ClientsByName[ClientName].CoalitionID
end end
self:E("ERROR: Template does not exist for client "..tostring(ClientName)) self:E("WARNING: Template does not exist for client "..tostring(ClientName))
return nil return nil
end end
@@ -1336,7 +1395,7 @@ function DATABASE:GetCategoryFromClientTemplate( ClientName )
if self.Templates.ClientsByName[ClientName] then if self.Templates.ClientsByName[ClientName] then
return self.Templates.ClientsByName[ClientName].CategoryID return self.Templates.ClientsByName[ClientName].CategoryID
end end
self:E("ERROR: Template does not exist for client "..tostring(ClientName)) self:E("WARNING: Template does not exist for client "..tostring(ClientName))
return nil return nil
end end
@@ -1348,7 +1407,7 @@ function DATABASE:GetCountryFromClientTemplate( ClientName )
if self.Templates.ClientsByName[ClientName] then if self.Templates.ClientsByName[ClientName] then
return self.Templates.ClientsByName[ClientName].CountryID return self.Templates.ClientsByName[ClientName].CountryID
end end
self:E("ERROR: Template does not exist for client "..tostring(ClientName)) self:E("WARNING: Template does not exist for client "..tostring(ClientName))
return nil return nil
end end
@@ -1417,7 +1476,7 @@ function DATABASE:_RegisterDynamicGroup(Groupname)
-- Add unit. -- Add unit.
self:I(string.format("Register Unit: %s", tostring(DCSUnitName))) self:I(string.format("Register Unit: %s", tostring(DCSUnitName)))
self:AddUnit( DCSUnitName, true ) self:AddUnit( tostring(DCSUnitName), true )
end end
else else
@@ -1568,7 +1627,7 @@ end
-- @param #DATABASE self -- @param #DATABASE self
-- @param Core.Event#EVENTDATA Event -- @param Core.Event#EVENTDATA Event
function DATABASE:_EventOnBirth( Event ) function DATABASE:_EventOnBirth( Event )
self:F( { Event } ) self:T( { Event } )
if Event.IniDCSUnit then if Event.IniDCSUnit then
@@ -1577,6 +1636,16 @@ function DATABASE:_EventOnBirth( Event )
-- Add static object to DB. -- Add static object to DB.
self:AddStatic( Event.IniDCSUnitName ) self:AddStatic( Event.IniDCSUnitName )
elseif Event.IniObjectCategory == Object.Category.CARGO and string.match(Event.IniUnitName,".+|%d%d:%d%d|PKG%d+") then
-- Add dynamic cargo object to DB
local cargo = self:AddDynamicCargo(Event.IniDCSUnitName)
self:I(string.format("Adding dynamic cargo %s", tostring(Event.IniDCSUnitName)))
self:CreateEventNewDynamicCargo( cargo )
else else
if Event.IniObjectCategory == Object.Category.UNIT then if Event.IniObjectCategory == Object.Category.UNIT then
@@ -1762,6 +1831,15 @@ function DATABASE:_EventOnPlayerEnterUnit( Event )
end end
end end
--- Handles the OnDynamicCargoRemoved event to clean the active dynamic cargo table.
-- @param #DATABASE self
-- @param Core.Event#EVENTDATA Event
function DATABASE:_EventOnDynamicCargoRemoved( Event )
self:T( { Event } )
if Event.IniDynamicCargoName then
self:DeleteDynamicCargo(Event.IniDynamicCargoName)
end
end
--- Handles the OnPlayerLeaveUnit event to clean the active players table. --- Handles the OnPlayerLeaveUnit event to clean the active players table.
-- @param #DATABASE self -- @param #DATABASE self
+110 -1
View File
@@ -194,6 +194,11 @@ world.event.S_EVENT_NEW_ZONE_GOAL = world.event.S_EVENT_MAX + 1004
world.event.S_EVENT_DELETE_ZONE_GOAL = world.event.S_EVENT_MAX + 1005 world.event.S_EVENT_DELETE_ZONE_GOAL = world.event.S_EVENT_MAX + 1005
world.event.S_EVENT_REMOVE_UNIT = world.event.S_EVENT_MAX + 1006 world.event.S_EVENT_REMOVE_UNIT = world.event.S_EVENT_MAX + 1006
world.event.S_EVENT_PLAYER_ENTER_AIRCRAFT = world.event.S_EVENT_MAX + 1007 world.event.S_EVENT_PLAYER_ENTER_AIRCRAFT = world.event.S_EVENT_MAX + 1007
-- dynamic cargo
world.event.S_EVENT_NEW_DYNAMIC_CARGO = world.event.S_EVENT_MAX + 1008
world.event.S_EVENT_DYNAMIC_CARGO_LOADED = world.event.S_EVENT_MAX + 1009
world.event.S_EVENT_DYNAMIC_CARGO_UNLOADED = world.event.S_EVENT_MAX + 1010
world.event.S_EVENT_DYNAMIC_CARGO_REMOVED = world.event.S_EVENT_MAX + 1011
--- The different types of events supported by MOOSE. --- The different types of events supported by MOOSE.
@@ -276,6 +281,11 @@ EVENTS = {
SimulationUnfreeze = world.event.S_EVENT_SIMULATION_UNFREEZE or -1, SimulationUnfreeze = world.event.S_EVENT_SIMULATION_UNFREEZE or -1,
HumanAircraftRepairStart = world.event.S_EVENT_HUMAN_AIRCRAFT_REPAIR_START or -1, HumanAircraftRepairStart = world.event.S_EVENT_HUMAN_AIRCRAFT_REPAIR_START or -1,
HumanAircraftRepairFinish = world.event.S_EVENT_HUMAN_AIRCRAFT_REPAIR_FINISH or -1, HumanAircraftRepairFinish = world.event.S_EVENT_HUMAN_AIRCRAFT_REPAIR_FINISH or -1,
-- dynamic cargo
NewDynamicCargo = world.event.S_EVENT_NEW_DYNAMIC_CARGO or -1,
DynamicCargoLoaded = world.event.S_EVENT_DYNAMIC_CARGO_LOADED or -1,
DynamicCargoUnloaded = world.event.S_EVENT_DYNAMIC_CARGO_UNLOADED or -1,
DynamicCargoRemoved = world.event.S_EVENT_DYNAMIC_CARGO_REMOVED or -1,
} }
@@ -334,6 +344,9 @@ EVENTS = {
-- --
-- @field Core.Zone#ZONE Zone The zone object. -- @field Core.Zone#ZONE Zone The zone object.
-- @field #string ZoneName The name of the zone. -- @field #string ZoneName The name of the zone.
--
-- @field Wrapper.DynamicCargo#DYNAMICCARGO IniDynamicCargo The dynamic cargo object.
-- @field #string IniDynamicCargoName The dynamic cargo unit name.
@@ -731,6 +744,31 @@ local _EVENTMETA = {
Event = "OnEventHumanAircraftRepairFinish", Event = "OnEventHumanAircraftRepairFinish",
Text = "S_EVENT_HUMAN_AIRCRAFT_REPAIR_FINISH" Text = "S_EVENT_HUMAN_AIRCRAFT_REPAIR_FINISH"
}, },
-- dynamic cargo
[EVENTS.NewDynamicCargo] = {
Order = 1,
Side = "I",
Event = "OnEventNewDynamicCargo",
Text = "S_EVENT_NEW_DYNAMIC_CARGO"
},
[EVENTS.DynamicCargoLoaded] = {
Order = 1,
Side = "I",
Event = "OnEventDynamicCargoLoaded",
Text = "S_EVENT_DYNAMIC_CARGO_LOADED"
},
[EVENTS.DynamicCargoUnloaded] = {
Order = 1,
Side = "I",
Event = "OnEventDynamicCargoUnloaded",
Text = "S_EVENT_DYNAMIC_CARGO_UNLOADED"
},
[EVENTS.DynamicCargoRemoved] = {
Order = 1,
Side = "I",
Event = "OnEventDynamicCargoRemoved",
Text = "S_EVENT_DYNAMIC_CARGO_REMOVED"
},
} }
@@ -1147,6 +1185,62 @@ do -- Event Creation
world.onEvent( Event ) world.onEvent( Event )
end end
--- Creation of a S_EVENT_NEW_DYNAMIC_CARGO event.
-- @param #EVENT self
-- @param Wrapper.DynamicCargo#DYNAMICCARGO DynamicCargo the dynamic cargo object
function EVENT:CreateEventNewDynamicCargo(DynamicCargo)
self:F({DynamicCargo})
local Event = {
id = EVENTS.NewDynamicCargo,
time = timer.getTime(),
dynamiccargo = DynamicCargo,
initiator = DynamicCargo:GetDCSObject(),
}
world.onEvent( Event )
end
--- Creation of a S_EVENT_DYNAMIC_CARGO_LOADED event.
-- @param #EVENT self
-- @param Wrapper.DynamicCargo#DYNAMICCARGO DynamicCargo the dynamic cargo object
function EVENT:CreateEventDynamicCargoLoaded(DynamicCargo)
self:F({DynamicCargo})
local Event = {
id = EVENTS.DynamicCargoLoaded,
time = timer.getTime(),
dynamiccargo = DynamicCargo,
initiator = DynamicCargo:GetDCSObject(),
}
world.onEvent( Event )
end
--- Creation of a S_EVENT_DYNAMIC_CARGO_UNLOADED event.
-- @param #EVENT self
-- @param Wrapper.DynamicCargo#DYNAMICCARGO DynamicCargo the dynamic cargo object
function EVENT:CreateEventDynamicCargoUnloaded(DynamicCargo)
self:F({DynamicCargo})
local Event = {
id = EVENTS.DynamicCargoUnloaded,
time = timer.getTime(),
dynamiccargo = DynamicCargo,
initiator = DynamicCargo:GetDCSObject(),
}
world.onEvent( Event )
end
--- Creation of a S_EVENT_DYNAMIC_CARGO_REMOVED event.
-- @param #EVENT self
-- @param Wrapper.DynamicCargo#DYNAMICCARGO DynamicCargo the dynamic cargo object
function EVENT:CreateEventDynamicCargoRemoved(DynamicCargo)
self:F({DynamicCargo})
local Event = {
id = EVENTS.DynamicCargoRemoved,
time = timer.getTime(),
dynamiccargo = DynamicCargo,
initiator = DynamicCargo:GetDCSObject(),
}
world.onEvent( Event )
end
end end
--- Main event function. --- Main event function.
@@ -1261,7 +1355,13 @@ function EVENT:onEvent( Event )
Event.IniDCSUnit = Event.initiator Event.IniDCSUnit = Event.initiator
Event.IniDCSUnitName = Event.IniDCSUnit:getName() Event.IniDCSUnitName = Event.IniDCSUnit:getName()
Event.IniUnitName = Event.IniDCSUnitName Event.IniUnitName = Event.IniDCSUnitName
if string.match(Event.IniUnitName,".+|%d%d:%d%d|PKG%d+") then
Event.IniDynamicCargo = DYNAMICCARGO:FindByName(Event.IniUnitName)
Event.IniDynamicCargoName = Event.IniUnitName
Event.IniPlayerName = string.match(Event.IniUnitName,"^(.+)|%d%d:%d%d|PKG%d+")
else
Event.IniUnit = CARGO:FindByName( Event.IniDCSUnitName ) Event.IniUnit = CARGO:FindByName( Event.IniDCSUnitName )
end
Event.IniCoalition = Event.IniDCSUnit:getCoalition() Event.IniCoalition = Event.IniDCSUnit:getCoalition()
Event.IniCategory = Event.IniDCSUnit:getDesc().category Event.IniCategory = Event.IniDCSUnit:getDesc().category
Event.IniTypeName = Event.IniDCSUnit:getTypeName() Event.IniTypeName = Event.IniDCSUnit:getTypeName()
@@ -1382,7 +1482,7 @@ function EVENT:onEvent( Event )
end end
-- Weapon. -- Weapon.
if Event.weapon and type(Event.weapon) == "table" then if Event.weapon and type(Event.weapon) == "table" and Event.weapon.isExist and Event.weapon:isExist() then
Event.Weapon = Event.weapon Event.Weapon = Event.weapon
Event.WeaponName = Event.weapon:isExist() and Event.weapon:getTypeName() or "Unknown Weapon" Event.WeaponName = Event.weapon:isExist() and Event.weapon:getTypeName() or "Unknown Weapon"
Event.WeaponUNIT = CLIENT:Find( Event.Weapon, '', true ) -- Sometimes, the weapon is a player unit! Event.WeaponUNIT = CLIENT:Find( Event.Weapon, '', true ) -- Sometimes, the weapon is a player unit!
@@ -1426,6 +1526,15 @@ function EVENT:onEvent( Event )
Event.CargoName = Event.cargo.Name Event.CargoName = Event.cargo.Name
end end
-- Dynamic cargo Object
if Event.dynamiccargo then
Event.IniDynamicCargo = Event.dynamiccargo
Event.IniDynamicCargoName = Event.IniDynamicCargo.StaticName
if Event.IniDynamicCargo.Owner or Event.IniUnitName then
Event.IniPlayerName = Event.IniDynamicCargo.Owner or string.match(Event.IniUnitName or "None|00:00|PKG00","^(.+)|%d%d:%d%d|PKG%d+")
end
end
-- Zone object. -- Zone object.
if Event.zone then if Event.zone then
Event.Zone = Event.zone Event.Zone = Event.zone
+4 -4
View File
@@ -2669,9 +2669,9 @@ do -- COORDINATE
local date=UTILS.GetDCSMissionDate() local date=UTILS.GetDCSMissionDate()
-- Debug output. -- 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)) --self:I(string.format("Sun rise at lat=%.3f long=%.3f on %s (DayOfYear=%d): %s (%s sec of the day) (GMT %d)", Latitude, Longitude, date, DayOfYear, tostring(UTILS.SecondsToClock(sunrise)), tonumber(sunrise) or "0", Tdiff))
if InSeconds then if InSeconds or type(sunrise) == "string" then
return sunrise return sunrise
else else
return UTILS.SecondsToClock(sunrise, true) return UTILS.SecondsToClock(sunrise, true)
@@ -2837,9 +2837,9 @@ do -- COORDINATE
local date=UTILS.GetDCSMissionDate() local date=UTILS.GetDCSMissionDate()
-- Debug output. -- 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)) --self:I(string.format("Sun set at lat=%.3f long=%.3f on %s (DayOfYear=%d): %s (%s sec of the day) (GMT %d)", Latitude, Longitude, date, DayOfYear, tostring(UTILS.SecondsToClock(sunrise)), tostring(sunrise) or "0", Tdiff))
if InSeconds then if InSeconds or type(sunrise) == "string" then
return sunrise return sunrise
else else
return UTILS.SecondsToClock(sunrise, true) return UTILS.SecondsToClock(sunrise, true)
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+89 -89
View File
@@ -144,7 +144,7 @@ ZONE_BASE = {
-- @return #ZONE_BASE self -- @return #ZONE_BASE self
function ZONE_BASE:New( ZoneName ) function ZONE_BASE:New( ZoneName )
local self = BASE:Inherit( self, FSM:New() ) local self = BASE:Inherit( self, FSM:New() )
self:F( ZoneName ) --self:F( ZoneName )
self.ZoneName = ZoneName self.ZoneName = ZoneName
@@ -157,7 +157,7 @@ end
-- @param #ZONE_BASE self -- @param #ZONE_BASE self
-- @return #string The name of the zone. -- @return #string The name of the zone.
function ZONE_BASE:GetName() function ZONE_BASE:GetName()
self:F2() --self:F2()
return self.ZoneName return self.ZoneName
end end
@@ -167,7 +167,7 @@ end
-- @param #string ZoneName The name of the zone. -- @param #string ZoneName The name of the zone.
-- @return #ZONE_BASE -- @return #ZONE_BASE
function ZONE_BASE:SetName( ZoneName ) function ZONE_BASE:SetName( ZoneName )
self:F2() --self:F2()
self.ZoneName = ZoneName self.ZoneName = ZoneName
end end
@@ -177,7 +177,7 @@ end
-- @param DCS#Vec2 Vec2 The Vec2 to test. -- @param DCS#Vec2 Vec2 The Vec2 to test.
-- @return #boolean true if the Vec2 is within the zone. -- @return #boolean true if the Vec2 is within the zone.
function ZONE_BASE:IsVec2InZone( Vec2 ) function ZONE_BASE:IsVec2InZone( Vec2 )
self:F2( Vec2 ) --self:F2( Vec2 )
return false return false
end end
@@ -232,13 +232,13 @@ end
-- @param DCS#Distance Height The height to add to the land height where the center of the zone is located. -- @param DCS#Distance Height The height to add to the land height where the center of the zone is located.
-- @return Core.Point#POINT_VEC2 The PointVec2 of the zone. -- @return Core.Point#POINT_VEC2 The PointVec2 of the zone.
function ZONE_BASE:GetPointVec2() function ZONE_BASE:GetPointVec2()
self:F2( self.ZoneName ) --self:F2( self.ZoneName )
local Vec2 = self:GetVec2() local Vec2 = self:GetVec2()
local PointVec2 = POINT_VEC2:NewFromVec2( Vec2 ) local PointVec2 = POINT_VEC2:NewFromVec2( Vec2 )
self:T2( { PointVec2 } ) --self:T2( { PointVec2 } )
return PointVec2 return PointVec2
end end
@@ -248,7 +248,7 @@ end
-- @param DCS#Distance Height The height to add to the land height where the center of the zone is located. -- @param DCS#Distance Height The height to add to the land height where the center of the zone is located.
-- @return DCS#Vec3 The Vec3 of the zone. -- @return DCS#Vec3 The Vec3 of the zone.
function ZONE_BASE:GetVec3( Height ) function ZONE_BASE:GetVec3( Height )
self:F2( self.ZoneName ) --self:F2( self.ZoneName )
Height = Height or 0 Height = Height or 0
@@ -256,7 +256,7 @@ function ZONE_BASE:GetVec3( Height )
local Vec3 = { x = Vec2.x, y = Height and Height or land.getHeight( self:GetVec2() ), z = Vec2.y } local Vec3 = { x = Vec2.x, y = Height and Height or land.getHeight( self:GetVec2() ), z = Vec2.y }
self:T2( { Vec3 } ) --self:T2( { Vec3 } )
return Vec3 return Vec3
end end
@@ -266,13 +266,13 @@ end
-- @param DCS#Distance Height The height to add to the land height where the center of the zone is located. -- @param DCS#Distance Height The height to add to the land height where the center of the zone is located.
-- @return Core.Point#POINT_VEC3 The PointVec3 of the zone. -- @return Core.Point#POINT_VEC3 The PointVec3 of the zone.
function ZONE_BASE:GetPointVec3( Height ) function ZONE_BASE:GetPointVec3( Height )
self:F2( self.ZoneName ) --self:F2( self.ZoneName )
local Vec3 = self:GetVec3( Height ) local Vec3 = self:GetVec3( Height )
local PointVec3 = POINT_VEC3:NewFromVec3( Vec3 ) local PointVec3 = POINT_VEC3:NewFromVec3( Vec3 )
self:T2( { PointVec3 } ) --self:T2( { PointVec3 } )
return PointVec3 return PointVec3
end end
@@ -282,7 +282,7 @@ end
-- @param DCS#Distance Height The height to add to the land height where the center of the zone is located. -- @param DCS#Distance Height The height to add to the land height where the center of the zone is located.
-- @return Core.Point#COORDINATE The Coordinate of the zone. -- @return Core.Point#COORDINATE The Coordinate of the zone.
function ZONE_BASE:GetCoordinate( Height ) --R2.1 function ZONE_BASE:GetCoordinate( Height ) --R2.1
self:F2(self.ZoneName) --self:F2(self.ZoneName)
local Vec3 = self:GetVec3( Height ) local Vec3 = self:GetVec3( Height )
@@ -363,7 +363,7 @@ end
--- Bound the zone boundaries with a tires. --- Bound the zone boundaries with a tires.
-- @param #ZONE_BASE self -- @param #ZONE_BASE self
function ZONE_BASE:BoundZone() function ZONE_BASE:BoundZone()
self:F2() --self:F2()
end end
--- Set draw coalition of zone. --- Set draw coalition of zone.
@@ -510,7 +510,7 @@ end
-- @param #ZONE_BASE self -- @param #ZONE_BASE self
-- @param Utilities.Utils#SMOKECOLOR SmokeColor The smoke color. -- @param Utilities.Utils#SMOKECOLOR SmokeColor The smoke color.
function ZONE_BASE:SmokeZone( SmokeColor ) function ZONE_BASE:SmokeZone( SmokeColor )
self:F2( SmokeColor ) --self:F2( SmokeColor )
end end
@@ -519,7 +519,7 @@ end
-- @param #number ZoneProbability A value between 0 and 1. 0 = 0% and 1 = 100% probability. -- @param #number ZoneProbability A value between 0 and 1. 0 = 0% and 1 = 100% probability.
-- @return #ZONE_BASE self -- @return #ZONE_BASE self
function ZONE_BASE:SetZoneProbability( ZoneProbability ) function ZONE_BASE:SetZoneProbability( ZoneProbability )
self:F( { self:GetName(), ZoneProbability = ZoneProbability } ) --self:F( { self:GetName(), ZoneProbability = ZoneProbability } )
self.ZoneProbability = ZoneProbability or 1 self.ZoneProbability = ZoneProbability or 1
return self return self
@@ -529,7 +529,7 @@ end
-- @param #ZONE_BASE self -- @param #ZONE_BASE self
-- @return #number A value between 0 and 1. 0 = 0% and 1 = 100% probability. -- @return #number A value between 0 and 1. 0 = 0% and 1 = 100% probability.
function ZONE_BASE:GetZoneProbability() function ZONE_BASE:GetZoneProbability()
self:F2() --self:F2()
return self.ZoneProbability return self.ZoneProbability
end end
@@ -560,7 +560,7 @@ end
-- -- The result should be that Zone1 would be more probable selected than Zone2. -- -- The result should be that Zone1 would be more probable selected than Zone2.
-- --
function ZONE_BASE:GetZoneMaybe() function ZONE_BASE:GetZoneMaybe()
self:F2() --self:F2()
local Randomization = math.random() local Randomization = math.random()
if Randomization <= self.ZoneProbability then if Randomization <= self.ZoneProbability then
@@ -791,7 +791,7 @@ function ZONE_RADIUS:New( ZoneName, Vec2, Radius, DoNotRegisterZone )
-- Inherit ZONE_BASE. -- Inherit ZONE_BASE.
local self = BASE:Inherit( self, ZONE_BASE:New( ZoneName ) ) -- #ZONE_RADIUS local self = BASE:Inherit( self, ZONE_BASE:New( ZoneName ) ) -- #ZONE_RADIUS
self:F( { ZoneName, Vec2, Radius } ) --self:F( { ZoneName, Vec2, Radius } )
self.Radius = Radius self.Radius = Radius
self.Vec2 = Vec2 self.Vec2 = Vec2
@@ -947,7 +947,7 @@ end
-- @param #number AddOffSet (optional) The angle to be added for the smoking start position. -- @param #number AddOffSet (optional) The angle to be added for the smoking start position.
-- @return #ZONE_RADIUS self -- @return #ZONE_RADIUS self
function ZONE_RADIUS:SmokeZone( SmokeColor, Points, AddHeight, AngleOffset ) function ZONE_RADIUS:SmokeZone( SmokeColor, Points, AddHeight, AngleOffset )
self:F2( SmokeColor ) --self:F2( SmokeColor )
local Point = {} local Point = {}
local Vec2 = self:GetVec2() local Vec2 = self:GetVec2()
@@ -978,7 +978,7 @@ end
-- @param #number AddHeight (optional) The height to be added for the smoke. -- @param #number AddHeight (optional) The height to be added for the smoke.
-- @return #ZONE_RADIUS self -- @return #ZONE_RADIUS self
function ZONE_RADIUS:FlareZone( FlareColor, Points, Azimuth, AddHeight ) function ZONE_RADIUS:FlareZone( FlareColor, Points, Azimuth, AddHeight )
self:F2( { FlareColor, Azimuth } ) --self:F2( { FlareColor, Azimuth } )
local Point = {} local Point = {}
local Vec2 = self:GetVec2() local Vec2 = self:GetVec2()
@@ -1004,9 +1004,9 @@ end
-- @param #ZONE_RADIUS self -- @param #ZONE_RADIUS self
-- @return DCS#Distance The radius of the zone. -- @return DCS#Distance The radius of the zone.
function ZONE_RADIUS:GetRadius() function ZONE_RADIUS:GetRadius()
self:F2( self.ZoneName ) --self:F2( self.ZoneName )
self:T2( { self.Radius } ) --self:T2( { self.Radius } )
return self.Radius return self.Radius
end end
@@ -1016,10 +1016,10 @@ end
-- @param DCS#Distance Radius The radius of the zone. -- @param DCS#Distance Radius The radius of the zone.
-- @return DCS#Distance The radius of the zone. -- @return DCS#Distance The radius of the zone.
function ZONE_RADIUS:SetRadius( Radius ) function ZONE_RADIUS:SetRadius( Radius )
self:F2( self.ZoneName ) --self:F2( self.ZoneName )
self.Radius = Radius self.Radius = Radius
self:T2( { self.Radius } ) --self:T2( { self.Radius } )
return self.Radius return self.Radius
end end
@@ -1028,9 +1028,9 @@ end
-- @param #ZONE_RADIUS self -- @param #ZONE_RADIUS self
-- @return DCS#Vec2 The location of the zone. -- @return DCS#Vec2 The location of the zone.
function ZONE_RADIUS:GetVec2() function ZONE_RADIUS:GetVec2()
self:F2( self.ZoneName ) --self:F2( self.ZoneName )
self:T2( { self.Vec2 } ) --self:T2( { self.Vec2 } )
return self.Vec2 return self.Vec2
end end
@@ -1040,11 +1040,11 @@ end
-- @param DCS#Vec2 Vec2 The new location of the zone. -- @param DCS#Vec2 Vec2 The new location of the zone.
-- @return DCS#Vec2 The new location of the zone. -- @return DCS#Vec2 The new location of the zone.
function ZONE_RADIUS:SetVec2( Vec2 ) function ZONE_RADIUS:SetVec2( Vec2 )
self:F2( self.ZoneName ) --self:F2( self.ZoneName )
self.Vec2 = Vec2 self.Vec2 = Vec2
self:T2( { self.Vec2 } ) --self:T2( { self.Vec2 } )
return self.Vec2 return self.Vec2
end end
@@ -1054,14 +1054,14 @@ end
-- @param DCS#Distance Height The height to add to the land height where the center of the zone is located. -- @param DCS#Distance Height The height to add to the land height where the center of the zone is located.
-- @return DCS#Vec3 The point of the zone. -- @return DCS#Vec3 The point of the zone.
function ZONE_RADIUS:GetVec3( Height ) function ZONE_RADIUS:GetVec3( Height )
self:F2( { self.ZoneName, Height } ) --self:F2( { self.ZoneName, Height } )
Height = Height or 0 Height = Height or 0
local Vec2 = self:GetVec2() local Vec2 = self:GetVec2()
local Vec3 = { x = Vec2.x, y = land.getHeight( self:GetVec2() ) + Height, z = Vec2.y } local Vec3 = { x = Vec2.x, y = land.getHeight( self:GetVec2() ) + Height, z = Vec2.y }
self:T2( { Vec3 } ) --self:T2( { Vec3 } )
return Vec3 return Vec3
end end
@@ -1138,7 +1138,7 @@ function ZONE_RADIUS:Scan( ObjectCategories, UnitCategories )
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
@@ -1149,7 +1149,7 @@ function ZONE_RADIUS:Scan( ObjectCategories, UnitCategories )
self.ScanData.Scenery[SceneryType] = self.ScanData.Scenery[SceneryType] or {} self.ScanData.Scenery[SceneryType] = self.ScanData.Scenery[SceneryType] or {}
self.ScanData.Scenery[SceneryType][SceneryName] = SCENERY:Register( tostring(SceneryName), ZoneObject) self.ScanData.Scenery[SceneryType][SceneryName] = SCENERY:Register( tostring(SceneryName), ZoneObject)
table.insert(self.ScanData.SceneryTable,self.ScanData.Scenery[SceneryType][SceneryName] ) table.insert(self.ScanData.SceneryTable,self.ScanData.Scenery[SceneryType][SceneryName] )
self:T( { SCENERY = self.ScanData.Scenery[SceneryType][SceneryName] } ) --self:T( { SCENERY = self.ScanData.Scenery[SceneryType][SceneryName] } )
end end
end end
@@ -1409,7 +1409,7 @@ function ZONE_RADIUS:SearchZone( EvaluateFunction, ObjectCategories )
local ZoneCoord = self:GetCoordinate() local ZoneCoord = self:GetCoordinate()
local ZoneRadius = self:GetRadius() local ZoneRadius = self:GetRadius()
self:F({ZoneCoord = ZoneCoord, ZoneRadius = ZoneRadius, ZoneCoordLL = ZoneCoord:ToStringLLDMS()}) --self:F({ZoneCoord = ZoneCoord, ZoneRadius = ZoneRadius, ZoneCoordLL = ZoneCoord:ToStringLLDMS()})
local SphereSearch = { local SphereSearch = {
id = world.VolumeType.SPHERE, id = world.VolumeType.SPHERE,
@@ -1436,7 +1436,7 @@ end
-- @param DCS#Vec2 Vec2 The location to test. -- @param DCS#Vec2 Vec2 The location to test.
-- @return #boolean true if the location is within the zone. -- @return #boolean true if the location is within the zone.
function ZONE_RADIUS:IsVec2InZone( Vec2 ) function ZONE_RADIUS:IsVec2InZone( Vec2 )
self:F2( Vec2 ) --self:F2( Vec2 )
if not Vec2 then return false end if not Vec2 then return false end
@@ -1456,7 +1456,7 @@ end
-- @param DCS#Vec3 Vec3 The point to test. -- @param DCS#Vec3 Vec3 The point to test.
-- @return #boolean true if the point is within the zone. -- @return #boolean true if the point is within the zone.
function ZONE_RADIUS:IsVec3InZone( Vec3 ) function ZONE_RADIUS:IsVec3InZone( Vec3 )
self:F2( Vec3 ) --self:F2( Vec3 )
if not Vec3 then return false end if not Vec3 then return false end
local InZone = self:IsVec2InZone( { x = Vec3.x, y = Vec3.z } ) local InZone = self:IsVec2InZone( { x = Vec3.x, y = Vec3.z } )
@@ -1521,11 +1521,11 @@ end
-- @param #number outer (optional) Maximal distance from the outer edge of the zone. Default is the radius of the zone. -- @param #number outer (optional) Maximal distance from the outer edge of the zone. Default is the radius of the zone.
-- @return Core.Point#POINT_VEC2 The @{Core.Point#POINT_VEC2} object reflecting the random 3D location within the zone. -- @return Core.Point#POINT_VEC2 The @{Core.Point#POINT_VEC2} object reflecting the random 3D location within the zone.
function ZONE_RADIUS:GetRandomPointVec2( inner, outer ) function ZONE_RADIUS:GetRandomPointVec2( inner, outer )
self:F( self.ZoneName, inner, outer ) --self:F( self.ZoneName, inner, outer )
local PointVec2 = POINT_VEC2:NewFromVec2( self:GetRandomVec2( inner, outer ) ) local PointVec2 = POINT_VEC2:NewFromVec2( self:GetRandomVec2( inner, outer ) )
self:T3( { PointVec2 } ) --self:T3( { PointVec2 } )
return PointVec2 return PointVec2
end end
@@ -1536,11 +1536,11 @@ end
-- @param #number outer (optional) Maximal distance from the outer edge of the zone. Default is the radius of the zone. -- @param #number outer (optional) Maximal distance from the outer edge of the zone. Default is the radius of the zone.
-- @return DCS#Vec3 The random location within the zone. -- @return DCS#Vec3 The random location within the zone.
function ZONE_RADIUS:GetRandomVec3( inner, outer ) function ZONE_RADIUS:GetRandomVec3( inner, outer )
self:F( self.ZoneName, inner, outer ) --self:F( self.ZoneName, inner, outer )
local Vec2 = self:GetRandomVec2( inner, outer ) local Vec2 = self:GetRandomVec2( inner, outer )
self:T3( { x = Vec2.x, y = self.y, z = Vec2.y } ) --self:T3( { x = Vec2.x, y = self.y, z = Vec2.y } )
return { x = Vec2.x, y = self.y, z = Vec2.y } return { x = Vec2.x, y = self.y, z = Vec2.y }
end end
@@ -1552,11 +1552,11 @@ end
-- @param #number outer (optional) Maximal distance from the outer edge of the zone. Default is the radius of the zone. -- @param #number outer (optional) Maximal distance from the outer edge of the zone. Default is the radius of the zone.
-- @return Core.Point#POINT_VEC3 The @{Core.Point#POINT_VEC3} object reflecting the random 3D location within the zone. -- @return Core.Point#POINT_VEC3 The @{Core.Point#POINT_VEC3} object reflecting the random 3D location within the zone.
function ZONE_RADIUS:GetRandomPointVec3( inner, outer ) function ZONE_RADIUS:GetRandomPointVec3( inner, outer )
self:F( self.ZoneName, inner, outer ) --self:F( self.ZoneName, inner, outer )
local PointVec3 = POINT_VEC3:NewFromVec2( self:GetRandomVec2( inner, outer ) ) local PointVec3 = POINT_VEC3:NewFromVec2( self:GetRandomVec2( inner, outer ) )
self:T3( { PointVec3 } ) --self:T3( { PointVec3 } )
return PointVec3 return PointVec3
end end
@@ -1685,7 +1685,7 @@ function ZONE_RADIUS:GetRandomCoordinateWithoutBuildings(inner,outer,distance,ma
T1=timer.getTime() T1=timer.getTime()
self:T(string.format("Found a coordinate: %s | Iterations: %d | Time: %.3f",tostring(found),iterations,T1-T0)) --self:T(string.format("Found a coordinate: %s | Iterations: %d | Time: %.3f",tostring(found),iterations,T1-T0))
if found then return rcoord else return nil end if found then return rcoord else return nil end
@@ -1754,7 +1754,7 @@ function ZONE:New( ZoneName )
-- Create a new ZONE_RADIUS. -- Create a new ZONE_RADIUS.
local self=BASE:Inherit( self, ZONE_RADIUS:New(ZoneName, {x=Zone.point.x, y=Zone.point.z}, Zone.radius, true)) local self=BASE:Inherit( self, ZONE_RADIUS:New(ZoneName, {x=Zone.point.x, y=Zone.point.z}, Zone.radius, true))
self:F(ZoneName) --self:F(ZoneName)
-- Color of zone. -- Color of zone.
self.Color={1, 0, 0, 0.15} self.Color={1, 0, 0, 0.15}
@@ -1824,7 +1824,7 @@ function ZONE_UNIT:New( ZoneName, ZoneUNIT, Radius, Offset)
self.relative_to_unit = Offset.relative_to_unit or false self.relative_to_unit = Offset.relative_to_unit or false
end end
self:F( { ZoneName, ZoneUNIT:GetVec2(), Radius } ) --self:F( { ZoneName, ZoneUNIT:GetVec2(), Radius } )
self.ZoneUNIT = ZoneUNIT self.ZoneUNIT = ZoneUNIT
self.LastVec2 = ZoneUNIT:GetVec2() self.LastVec2 = ZoneUNIT:GetVec2()
@@ -1840,7 +1840,7 @@ end
-- @param #ZONE_UNIT self -- @param #ZONE_UNIT self
-- @return DCS#Vec2 The location of the zone based on the @{Wrapper.Unit#UNIT}location and the offset, if any. -- @return DCS#Vec2 The location of the zone based on the @{Wrapper.Unit#UNIT}location and the offset, if any.
function ZONE_UNIT:GetVec2() function ZONE_UNIT:GetVec2()
self:F2( self.ZoneName ) --self:F2( self.ZoneName )
local ZoneVec2 = self.ZoneUNIT:GetVec2() local ZoneVec2 = self.ZoneUNIT:GetVec2()
if ZoneVec2 then if ZoneVec2 then
@@ -1873,7 +1873,7 @@ function ZONE_UNIT:GetVec2()
return self.LastVec2 return self.LastVec2
end end
self:T2( { ZoneVec2 } ) --self:T2( { ZoneVec2 } )
return nil return nil
end end
@@ -1882,7 +1882,7 @@ end
-- @param #ZONE_UNIT self -- @param #ZONE_UNIT self
-- @return DCS#Vec2 The random location within the zone. -- @return DCS#Vec2 The random location within the zone.
function ZONE_UNIT:GetRandomVec2() function ZONE_UNIT:GetRandomVec2()
self:F( self.ZoneName ) --self:F( self.ZoneName )
local RandomVec2 = {} local RandomVec2 = {}
--local Vec2 = self.ZoneUNIT:GetVec2() -- FF: This does not take care of the new offset feature! --local Vec2 = self.ZoneUNIT:GetVec2() -- FF: This does not take care of the new offset feature!
@@ -1896,7 +1896,7 @@ function ZONE_UNIT:GetRandomVec2()
RandomVec2.x = Vec2.x + math.cos( angle ) * math.random() * self:GetRadius(); RandomVec2.x = Vec2.x + math.cos( angle ) * math.random() * self:GetRadius();
RandomVec2.y = Vec2.y + math.sin( angle ) * math.random() * self:GetRadius(); RandomVec2.y = Vec2.y + math.sin( angle ) * math.random() * self:GetRadius();
self:T( { RandomVec2 } ) --self:T( { RandomVec2 } )
return RandomVec2 return RandomVec2
end end
@@ -1906,7 +1906,7 @@ end
-- @param DCS#Distance Height The height to add to the land height where the center of the zone is located. -- @param DCS#Distance Height The height to add to the land height where the center of the zone is located.
-- @return DCS#Vec3 The point of the zone. -- @return DCS#Vec3 The point of the zone.
function ZONE_UNIT:GetVec3( Height ) function ZONE_UNIT:GetVec3( Height )
self:F2( self.ZoneName ) --self:F2( self.ZoneName )
Height = Height or 0 Height = Height or 0
@@ -1914,7 +1914,7 @@ function ZONE_UNIT:GetVec3( Height )
local Vec3 = { x = Vec2.x, y = land.getHeight( self:GetVec2() ) + Height, z = Vec2.y } local Vec3 = { x = Vec2.x, y = land.getHeight( self:GetVec2() ) + Height, z = Vec2.y }
self:T2( { Vec3 } ) --self:T2( { Vec3 } )
return Vec3 return Vec3
end end
@@ -1940,7 +1940,7 @@ ZONE_GROUP = {
-- @return #ZONE_GROUP self -- @return #ZONE_GROUP self
function ZONE_GROUP:New( ZoneName, ZoneGROUP, Radius ) function ZONE_GROUP:New( ZoneName, ZoneGROUP, Radius )
local self = BASE:Inherit( self, ZONE_RADIUS:New( ZoneName, ZoneGROUP:GetVec2(), Radius, true ) ) local self = BASE:Inherit( self, ZONE_RADIUS:New( ZoneName, ZoneGROUP:GetVec2(), Radius, true ) )
self:F( { ZoneName, ZoneGROUP:GetVec2(), Radius } ) --self:F( { ZoneName, ZoneGROUP:GetVec2(), Radius } )
self._.ZoneGROUP = ZoneGROUP self._.ZoneGROUP = ZoneGROUP
self._.ZoneVec2Cache = self._.ZoneGROUP:GetVec2() self._.ZoneVec2Cache = self._.ZoneGROUP:GetVec2()
@@ -1956,7 +1956,7 @@ end
-- @param #ZONE_GROUP self -- @param #ZONE_GROUP self
-- @return DCS#Vec2 The location of the zone based on the @{Wrapper.Group} location. -- @return DCS#Vec2 The location of the zone based on the @{Wrapper.Group} location.
function ZONE_GROUP:GetVec2() function ZONE_GROUP:GetVec2()
self:F( self.ZoneName ) --self:F( self.ZoneName )
local ZoneVec2 = nil local ZoneVec2 = nil
@@ -1967,7 +1967,7 @@ function ZONE_GROUP:GetVec2()
ZoneVec2 = self._.ZoneVec2Cache ZoneVec2 = self._.ZoneVec2Cache
end end
self:T( { ZoneVec2 } ) --self:T( { ZoneVec2 } )
return ZoneVec2 return ZoneVec2
end end
@@ -1976,7 +1976,7 @@ end
-- @param #ZONE_GROUP self -- @param #ZONE_GROUP self
-- @return DCS#Vec2 The random location of the zone based on the @{Wrapper.Group} location. -- @return DCS#Vec2 The random location of the zone based on the @{Wrapper.Group} location.
function ZONE_GROUP:GetRandomVec2() function ZONE_GROUP:GetRandomVec2()
self:F( self.ZoneName ) --self:F( self.ZoneName )
local Point = {} local Point = {}
local Vec2 = self._.ZoneGROUP:GetVec2() local Vec2 = self._.ZoneGROUP:GetVec2()
@@ -1985,7 +1985,7 @@ function ZONE_GROUP:GetRandomVec2()
Point.x = Vec2.x + math.cos( angle ) * math.random() * self:GetRadius(); Point.x = Vec2.x + math.cos( angle ) * math.random() * self:GetRadius();
Point.y = Vec2.y + math.sin( angle ) * math.random() * self:GetRadius(); Point.y = Vec2.y + math.sin( angle ) * math.random() * self:GetRadius();
self:T( { Point } ) --self:T( { Point } )
return Point return Point
end end
@@ -1996,11 +1996,11 @@ end
-- @param #number outer (optional) Maximal distance from the outer edge of the zone. Default is the radius of the zone. -- @param #number outer (optional) Maximal distance from the outer edge of the zone. Default is the radius of the zone.
-- @return Core.Point#POINT_VEC2 The @{Core.Point#POINT_VEC2} object reflecting the random 3D location within the zone. -- @return Core.Point#POINT_VEC2 The @{Core.Point#POINT_VEC2} object reflecting the random 3D location within the zone.
function ZONE_GROUP:GetRandomPointVec2( inner, outer ) function ZONE_GROUP:GetRandomPointVec2( inner, outer )
self:F( self.ZoneName, inner, outer ) --self:F( self.ZoneName, inner, outer )
local PointVec2 = POINT_VEC2:NewFromVec2( self:GetRandomVec2() ) local PointVec2 = POINT_VEC2:NewFromVec2( self:GetRandomVec2() )
self:T3( { PointVec2 } ) --self:T3( { PointVec2 } )
return PointVec2 return PointVec2
end end
@@ -2183,7 +2183,7 @@ function ZONE_POLYGON_BASE:New( ZoneName, PointsArray )
-- Inherit ZONE_BASE. -- Inherit ZONE_BASE.
local self = BASE:Inherit( self, ZONE_BASE:New( ZoneName ) ) local self = BASE:Inherit( self, ZONE_BASE:New( ZoneName ) )
self:F( { ZoneName, PointsArray } ) --self:F( { ZoneName, PointsArray } )
if PointsArray then if PointsArray then
@@ -2351,7 +2351,7 @@ end
-- @param #ZONE_POLYGON_BASE self -- @param #ZONE_POLYGON_BASE self
-- @return DCS#Vec2 The location of the zone based on the @{Wrapper.Group} location. -- @return DCS#Vec2 The location of the zone based on the @{Wrapper.Group} location.
function ZONE_POLYGON_BASE:GetVec2() function ZONE_POLYGON_BASE:GetVec2()
self:F( self.ZoneName ) --self:F( self.ZoneName )
local Bounds = self:GetBoundingSquare() local Bounds = self:GetBoundingSquare()
@@ -2434,9 +2434,9 @@ end
-- @param #ZONE_POLYGON_BASE self -- @param #ZONE_POLYGON_BASE self
-- @return #ZONE_POLYGON_BASE self -- @return #ZONE_POLYGON_BASE self
function ZONE_POLYGON_BASE:Flush() function ZONE_POLYGON_BASE:Flush()
self:F2() --self:F2()
self:F( { Polygon = self.ZoneName, Coordinates = self._.Polygon } ) --self:F( { Polygon = self.ZoneName, Coordinates = self._.Polygon } )
return self return self
end end
@@ -2455,7 +2455,7 @@ function ZONE_POLYGON_BASE:BoundZone( UnBound )
j = #self._.Polygon j = #self._.Polygon
while i <= #self._.Polygon do while i <= #self._.Polygon do
self:T( { i, j, self._.Polygon[i], self._.Polygon[j] } ) --self:T( { i, j, self._.Polygon[i], self._.Polygon[j] } )
local DeltaX = self._.Polygon[j].x - self._.Polygon[i].x local DeltaX = self._.Polygon[j].x - self._.Polygon[i].x
local DeltaY = self._.Polygon[j].y - self._.Polygon[i].y local DeltaY = self._.Polygon[j].y - self._.Polygon[i].y
@@ -2707,7 +2707,7 @@ end
-- @param #number Segments (Optional) Number of segments within boundary line. Default 10. -- @param #number Segments (Optional) Number of segments within boundary line. Default 10.
-- @return #ZONE_POLYGON_BASE self -- @return #ZONE_POLYGON_BASE self
function ZONE_POLYGON_BASE:SmokeZone( SmokeColor, Segments ) function ZONE_POLYGON_BASE:SmokeZone( SmokeColor, Segments )
self:F2( SmokeColor ) --self:F2( SmokeColor )
Segments=Segments or 10 Segments=Segments or 10
@@ -2715,7 +2715,7 @@ function ZONE_POLYGON_BASE:SmokeZone( SmokeColor, Segments )
local j=#self._.Polygon local j=#self._.Polygon
while i <= #self._.Polygon do while i <= #self._.Polygon do
self:T( { i, j, self._.Polygon[i], self._.Polygon[j] } ) --self:T( { i, j, self._.Polygon[i], self._.Polygon[j] } )
local DeltaX = self._.Polygon[j].x - self._.Polygon[i].x local DeltaX = self._.Polygon[j].x - self._.Polygon[i].x
local DeltaY = self._.Polygon[j].y - self._.Polygon[i].y local DeltaY = self._.Polygon[j].y - self._.Polygon[i].y
@@ -2740,7 +2740,7 @@ end
-- @param #number AddHeight (optional) The height to be added for the smoke. -- @param #number AddHeight (optional) The height to be added for the smoke.
-- @return #ZONE_POLYGON_BASE self -- @return #ZONE_POLYGON_BASE self
function ZONE_POLYGON_BASE:FlareZone( FlareColor, Segments, Azimuth, AddHeight ) function ZONE_POLYGON_BASE:FlareZone( FlareColor, Segments, Azimuth, AddHeight )
self:F2(FlareColor) --self:F2(FlareColor)
Segments=Segments or 10 Segments=Segments or 10
@@ -2750,7 +2750,7 @@ function ZONE_POLYGON_BASE:FlareZone( FlareColor, Segments, Azimuth, AddHeight )
local j=#self._.Polygon local j=#self._.Polygon
while i <= #self._.Polygon do while i <= #self._.Polygon do
self:T( { i, j, self._.Polygon[i], self._.Polygon[j] } ) --self:T( { i, j, self._.Polygon[i], self._.Polygon[j] } )
local DeltaX = self._.Polygon[j].x - self._.Polygon[i].x local DeltaX = self._.Polygon[j].x - self._.Polygon[i].x
local DeltaY = self._.Polygon[j].y - self._.Polygon[i].y local DeltaY = self._.Polygon[j].y - self._.Polygon[i].y
@@ -2773,7 +2773,7 @@ end
-- @param DCS#Vec2 Vec2 The location to test. -- @param DCS#Vec2 Vec2 The location to test.
-- @return #boolean true if the location is within the zone. -- @return #boolean true if the location is within the zone.
function ZONE_POLYGON_BASE:IsVec2InZone( Vec2 ) function ZONE_POLYGON_BASE:IsVec2InZone( Vec2 )
self:F2( Vec2 ) --self:F2( Vec2 )
if not Vec2 then return false end if not Vec2 then return false end
local Next local Next
local Prev local Prev
@@ -2783,18 +2783,18 @@ function ZONE_POLYGON_BASE:IsVec2InZone( Vec2 )
Prev = #self._.Polygon Prev = #self._.Polygon
while Next <= #self._.Polygon do while Next <= #self._.Polygon do
self:T( { Next, Prev, self._.Polygon[Next], self._.Polygon[Prev] } ) --self:T( { Next, Prev, self._.Polygon[Next], self._.Polygon[Prev] } )
if ( ( ( self._.Polygon[Next].y > Vec2.y ) ~= ( self._.Polygon[Prev].y > Vec2.y ) ) and if ( ( ( self._.Polygon[Next].y > Vec2.y ) ~= ( self._.Polygon[Prev].y > Vec2.y ) ) and
( Vec2.x < ( self._.Polygon[Prev].x - self._.Polygon[Next].x ) * ( Vec2.y - self._.Polygon[Next].y ) / ( self._.Polygon[Prev].y - self._.Polygon[Next].y ) + self._.Polygon[Next].x ) ( Vec2.x < ( self._.Polygon[Prev].x - self._.Polygon[Next].x ) * ( Vec2.y - self._.Polygon[Next].y ) / ( self._.Polygon[Prev].y - self._.Polygon[Next].y ) + self._.Polygon[Next].x )
) then ) then
InPolygon = not InPolygon InPolygon = not InPolygon
end end
self:T2( { InPolygon = InPolygon } ) --self:T2( { InPolygon = InPolygon } )
Prev = Next Prev = Next
Next = Next + 1 Next = Next + 1
end end
self:T( { InPolygon = InPolygon } ) --self:T( { InPolygon = InPolygon } )
return InPolygon return InPolygon
end end
@@ -2803,7 +2803,7 @@ end
-- @param DCS#Vec3 Vec3 The point to test. -- @param DCS#Vec3 Vec3 The point to test.
-- @return #boolean true if the point is within the zone. -- @return #boolean true if the point is within the zone.
function ZONE_POLYGON_BASE:IsVec3InZone( Vec3 ) function ZONE_POLYGON_BASE:IsVec3InZone( Vec3 )
self:F2( Vec3 ) --self:F2( Vec3 )
if not Vec3 then return false end if not Vec3 then return false end
@@ -2838,11 +2838,11 @@ end
-- @param #ZONE_POLYGON_BASE self -- @param #ZONE_POLYGON_BASE self
-- @return @{Core.Point#POINT_VEC2} -- @return @{Core.Point#POINT_VEC2}
function ZONE_POLYGON_BASE:GetRandomPointVec2() function ZONE_POLYGON_BASE:GetRandomPointVec2()
self:F2() --self:F2()
local PointVec2 = POINT_VEC2:NewFromVec2( self:GetRandomVec2() ) local PointVec2 = POINT_VEC2:NewFromVec2( self:GetRandomVec2() )
self:T2( PointVec2 ) --self:T2( PointVec2 )
return PointVec2 return PointVec2
end end
@@ -2851,11 +2851,11 @@ end
-- @param #ZONE_POLYGON_BASE self -- @param #ZONE_POLYGON_BASE self
-- @return @{Core.Point#POINT_VEC3} -- @return @{Core.Point#POINT_VEC3}
function ZONE_POLYGON_BASE:GetRandomPointVec3() function ZONE_POLYGON_BASE:GetRandomPointVec3()
self:F2() --self:F2()
local PointVec3 = POINT_VEC3:NewFromVec2( self:GetRandomVec2() ) local PointVec3 = POINT_VEC3:NewFromVec2( self:GetRandomVec2() )
self:T2( PointVec3 ) --self:T2( PointVec3 )
return PointVec3 return PointVec3
end end
@@ -2865,11 +2865,11 @@ end
-- @param #ZONE_POLYGON_BASE self -- @param #ZONE_POLYGON_BASE self
-- @return Core.Point#COORDINATE -- @return Core.Point#COORDINATE
function ZONE_POLYGON_BASE:GetRandomCoordinate() function ZONE_POLYGON_BASE:GetRandomCoordinate()
self:F2() --self:F2()
local Coordinate = COORDINATE:NewFromVec2( self:GetRandomVec2() ) local Coordinate = COORDINATE:NewFromVec2( self:GetRandomVec2() )
self:T2( Coordinate ) --self:T2( Coordinate )
return Coordinate return Coordinate
end end
@@ -2886,7 +2886,7 @@ function ZONE_POLYGON_BASE:GetBoundingSquare()
local y2 = self._.Polygon[1].y local y2 = self._.Polygon[1].y
for i = 2, #self._.Polygon do for i = 2, #self._.Polygon do
self:T2( { self._.Polygon[i], x1, y1, x2, y2 } ) --self:T2( { self._.Polygon[i], x1, y1, x2, y2 } )
x1 = ( x1 > self._.Polygon[i].x ) and self._.Polygon[i].x or x1 x1 = ( x1 > self._.Polygon[i].x ) and self._.Polygon[i].x or x1
x2 = ( x2 < self._.Polygon[i].x ) and self._.Polygon[i].x or x2 x2 = ( x2 < self._.Polygon[i].x ) and self._.Polygon[i].x or x2
y1 = ( y1 > self._.Polygon[i].y ) and self._.Polygon[i].y or y1 y1 = ( y1 > self._.Polygon[i].y ) and self._.Polygon[i].y or y1
@@ -2909,7 +2909,7 @@ function ZONE_POLYGON_BASE:GetBoundingVec2()
local y2 = self._.Polygon[1].y local y2 = self._.Polygon[1].y
for i = 2, #self._.Polygon do for i = 2, #self._.Polygon do
self:T2( { self._.Polygon[i], x1, y1, x2, y2 } ) --self:T2( { self._.Polygon[i], x1, y1, x2, y2 } )
x1 = ( x1 > self._.Polygon[i].x ) and self._.Polygon[i].x or x1 x1 = ( x1 > self._.Polygon[i].x ) and self._.Polygon[i].x or x1
x2 = ( x2 < self._.Polygon[i].x ) and self._.Polygon[i].x or x2 x2 = ( x2 < self._.Polygon[i].x ) and self._.Polygon[i].x or x2
y1 = ( y1 > self._.Polygon[i].y ) and self._.Polygon[i].y or y1 y1 = ( y1 > self._.Polygon[i].y ) and self._.Polygon[i].y or y1
@@ -2948,7 +2948,7 @@ function ZONE_POLYGON_BASE:Boundary(Coalition, Color, Radius, Alpha, Segments, C
Limit = #self._.Polygon Limit = #self._.Polygon
end end
while i <= #self._.Polygon do while i <= #self._.Polygon do
self:T( { i, j, self._.Polygon[i], self._.Polygon[j] } ) --self:T( { i, j, self._.Polygon[i], self._.Polygon[j] } )
if j ~= Limit then if j ~= Limit then
local DeltaX = self._.Polygon[j].x - self._.Polygon[i].x local DeltaX = self._.Polygon[j].x - self._.Polygon[i].x
local DeltaY = self._.Polygon[j].y - self._.Polygon[i].y local DeltaY = self._.Polygon[j].y - self._.Polygon[i].y
@@ -3019,7 +3019,7 @@ function ZONE_POLYGON:New( ZoneName, ZoneGroup )
local GroupPoints = ZoneGroup:GetTaskRoute() local GroupPoints = ZoneGroup:GetTaskRoute()
local self = BASE:Inherit( self, ZONE_POLYGON_BASE:New( ZoneName, GroupPoints ) ) local self = BASE:Inherit( self, ZONE_POLYGON_BASE:New( ZoneName, GroupPoints ) )
self:F( { ZoneName, ZoneGroup, self._.Polygon } ) --self:F( { ZoneName, ZoneGroup, self._.Polygon } )
-- Zone objects are added to the _DATABASE and SET_ZONE objects. -- Zone objects are added to the _DATABASE and SET_ZONE objects.
_EVENTDISPATCHER:CreateEventNewZone( self ) _EVENTDISPATCHER:CreateEventNewZone( self )
@@ -3035,7 +3035,7 @@ end
function ZONE_POLYGON:NewFromPointsArray( ZoneName, PointsArray ) function ZONE_POLYGON:NewFromPointsArray( ZoneName, PointsArray )
local self = BASE:Inherit( self, ZONE_POLYGON_BASE:New( ZoneName, PointsArray ) ) local self = BASE:Inherit( self, ZONE_POLYGON_BASE:New( ZoneName, PointsArray ) )
self:F( { ZoneName, self._.Polygon } ) --self:F( { ZoneName, self._.Polygon } )
-- Zone objects are added to the _DATABASE and SET_ZONE objects. -- Zone objects are added to the _DATABASE and SET_ZONE objects.
_EVENTDISPATCHER:CreateEventNewZone( self ) _EVENTDISPATCHER:CreateEventNewZone( self )
@@ -3055,7 +3055,7 @@ function ZONE_POLYGON:NewFromGroupName( GroupName )
local GroupPoints = ZoneGroup:GetTaskRoute() local GroupPoints = ZoneGroup:GetTaskRoute()
local self = BASE:Inherit( self, ZONE_POLYGON_BASE:New( GroupName, GroupPoints ) ) local self = BASE:Inherit( self, ZONE_POLYGON_BASE:New( GroupName, GroupPoints ) )
self:F( { GroupName, ZoneGroup, self._.Polygon } ) --self:F( { GroupName, ZoneGroup, self._.Polygon } )
-- Zone objects are added to the _DATABASE and SET_ZONE objects. -- Zone objects are added to the _DATABASE and SET_ZONE objects.
_EVENTDISPATCHER:CreateEventNewZone( self ) _EVENTDISPATCHER:CreateEventNewZone( self )
@@ -3221,7 +3221,7 @@ function ZONE_POLYGON:Scan( ObjectCategories, UnitCategories )
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
@@ -3232,7 +3232,7 @@ function ZONE_POLYGON:Scan( ObjectCategories, UnitCategories )
self.ScanData.Scenery[SceneryType] = self.ScanData.Scenery[SceneryType] or {} self.ScanData.Scenery[SceneryType] = self.ScanData.Scenery[SceneryType] or {}
self.ScanData.Scenery[SceneryType][SceneryName] = SCENERY:Register( SceneryName, ZoneObject ) self.ScanData.Scenery[SceneryType][SceneryName] = SCENERY:Register( SceneryName, ZoneObject )
table.insert(self.ScanData.SceneryTable,self.ScanData.Scenery[SceneryType][SceneryName]) table.insert(self.ScanData.SceneryTable,self.ScanData.Scenery[SceneryType][SceneryName])
self:T( { SCENERY = self.ScanData.Scenery[SceneryType][SceneryName] } ) --self:T( { SCENERY = self.ScanData.Scenery[SceneryType][SceneryName] } )
end end
end end
@@ -3573,7 +3573,7 @@ do -- ZONE_ELASTIC
function ZONE_ELASTIC:Update(Delay, Draw) function ZONE_ELASTIC:Update(Delay, Draw)
-- Debug info. -- Debug info.
self:T(string.format("Updating ZONE_ELASTIC %s", tostring(self.ZoneName))) --self:T(string.format("Updating ZONE_ELASTIC %s", tostring(self.ZoneName)))
-- Copy all points. -- Copy all points.
local points=UTILS.DeepCopy(self.points or {}) local points=UTILS.DeepCopy(self.points or {})
@@ -3987,7 +3987,7 @@ do -- ZONE_AIRBASE
-- @param #ZONE_AIRBASE self -- @param #ZONE_AIRBASE self
-- @return DCS#Vec2 The location of the zone based on the AIRBASE location. -- @return DCS#Vec2 The location of the zone based on the AIRBASE location.
function ZONE_AIRBASE:GetVec2() function ZONE_AIRBASE:GetVec2()
self:F( self.ZoneName ) --self:F( self.ZoneName )
local ZoneVec2 = nil local ZoneVec2 = nil
@@ -3998,7 +3998,7 @@ do -- ZONE_AIRBASE
ZoneVec2 = self._.ZoneVec2Cache ZoneVec2 = self._.ZoneVec2Cache
end end
self:T( { ZoneVec2 } ) --self:T( { ZoneVec2 } )
return ZoneVec2 return ZoneVec2
end end
@@ -4009,11 +4009,11 @@ do -- ZONE_AIRBASE
-- @param #number outer (optional) Maximal distance from the outer edge of the zone. Default is the radius of the zone. -- @param #number outer (optional) Maximal distance from the outer edge of the zone. Default is the radius of the zone.
-- @return Core.Point#POINT_VEC2 The @{Core.Point#POINT_VEC2} object reflecting the random 3D location within the zone. -- @return Core.Point#POINT_VEC2 The @{Core.Point#POINT_VEC2} object reflecting the random 3D location within the zone.
function ZONE_AIRBASE:GetRandomPointVec2( inner, outer ) function ZONE_AIRBASE:GetRandomPointVec2( inner, outer )
self:F( self.ZoneName, inner, outer ) --self:F( self.ZoneName, inner, outer )
local PointVec2 = POINT_VEC2:NewFromVec2( self:GetRandomVec2() ) local PointVec2 = POINT_VEC2:NewFromVec2( self:GetRandomVec2() )
self:T3( { PointVec2 } ) --self:T3( { PointVec2 } )
return PointVec2 return PointVec2
end end
@@ -20,7 +20,7 @@
-- --
-- ==== -- ====
-- @module Functional.ClientWatch -- @module Functional.ClientWatch
-- @image ClientWatch.JPG -- @image clientwatch.jpg
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- CLIENTWATCH class --- CLIENTWATCH class
@@ -28,6 +28,8 @@
-- @field #string ClassName Name of the class. -- @field #string ClassName Name of the class.
-- @field #boolean Debug Write Debug messages to DCS log file and send Debug messages to all players. -- @field #boolean Debug Write Debug messages to DCS log file and send Debug messages to all players.
-- @field #string lid String for DCS log file. -- @field #string lid String for DCS log file.
-- @field #number FilterCoalition If not nil, will only activate for aircraft of the given coalition value.
-- @field #number FilterCategory If not nil, will only activate for aircraft of the given category value.
-- @extends Core.Fsm#FSM_CONTROLLABLE -- @extends Core.Fsm#FSM_CONTROLLABLE
--- Manage and track client slots easily to add your own client-based menus and modules to. --- Manage and track client slots easily to add your own client-based menus and modules to.
@@ -66,7 +68,7 @@
-- --
-- -- Create an instance with a client unit prefix and send them a message when they spawn -- -- Create an instance with a client unit prefix and send them a message when they spawn
-- local clientInstance = CLIENTWATCH:New("Rotary") -- local clientInstance = CLIENTWATCH:New("Rotary")
-- function clientInstance:OnAfterSpawn(From,Event,To,ClientObject) -- function clientInstance:OnAfterSpawn(From,Event,To,ClientObject,EventData)
-- MESSAGE:New("Welcome to your aircraft!",10):ToUnit(ClientObject.Unit) -- MESSAGE:New("Welcome to your aircraft!",10):ToUnit(ClientObject.Unit)
-- end -- end
-- --
@@ -108,7 +110,7 @@
-- --
-- -- Show a message to player when they take damage from a weapon -- -- Show a message to player when they take damage from a weapon
-- local clientInstance = CLIENTWATCH:New("Rotary") -- local clientInstance = CLIENTWATCH:New("Rotary")
-- function clientInstance:OnAfterSpawn(From,Event,To,ClientObject) -- function clientInstance:OnAfterSpawn(From,Event,To,ClientObject,EventData)
-- function ClientObject:OnAfterHit(From,Event,To,EventData) -- function ClientObject:OnAfterHit(From,Event,To,EventData)
-- local typeShooter = EventData.IniTypeName -- local typeShooter = EventData.IniTypeName
-- local nameWeapon = EventData.weapon_name -- local nameWeapon = EventData.weapon_name
@@ -120,6 +122,7 @@
CLIENTWATCH = {} CLIENTWATCH = {}
CLIENTWATCH.ClassName = "CLIENTWATCH" CLIENTWATCH.ClassName = "CLIENTWATCH"
CLIENTWATCH.Debug = false CLIENTWATCH.Debug = false
CLIENTWATCH.DebugEventData = false
CLIENTWATCH.lid = nil CLIENTWATCH.lid = nil
-- @type CLIENTWATCHTools -- @type CLIENTWATCHTools
@@ -139,7 +142,10 @@ CLIENTWATCH.version="1.0.1"
--- Creates a new instance of CLIENTWATCH to add scripts to. Can be used multiple times with the same client/prefixes if you need it for multiple scripts. --- Creates a new instance of CLIENTWATCH to add scripts to. Can be used multiple times with the same client/prefixes if you need it for multiple scripts.
-- @param #CLIENTWATCH self -- @param #CLIENTWATCH self
-- @param #string, #table, or Wrapper.Client#CLIENT client Takes multiple inputs. If provided a #string, it will watch for clients whos UNIT NAME or GROUP NAME matches part of the #string as a prefix. You can also provide it with a #table containing multiple #string prefixes. Lastly, you can provide it with a Wrapper.Client#CLIENT of the specific client you want to apply this to. -- @param #string Will watch for clients whos UNIT NAME or GROUP NAME matches part of the #string as a prefix.
-- @param #table Put strings in a table to use multiple prefixes for the above method.
-- @param Wrapper.Client#CLIENT Provide a Moose CLIENT object to apply to that specific aircraft slot (static slots only!)
-- @param #nil Leave blank to activate for ALL CLIENTS
-- @return #CLIENTWATCH self -- @return #CLIENTWATCH self
function CLIENTWATCH:New(client) function CLIENTWATCH:New(client)
--Init FSM --Init FSM
@@ -147,6 +153,9 @@ function CLIENTWATCH:New(client)
self:SetStartState( "Idle" ) self:SetStartState( "Idle" )
self:AddTransition( "*", "Spawn", "*" ) self:AddTransition( "*", "Spawn", "*" )
self.FilterCoalition = nil
self.FilterCategory = nil
--- User function for OnAfter "Spawn" event. --- User function for OnAfter "Spawn" event.
-- @function [parent=#CLIENTWATCH] OnAfterSpawn -- @function [parent=#CLIENTWATCH] OnAfterSpawn
-- @param #CLIENTWATCH self -- @param #CLIENTWATCH self
@@ -155,27 +164,50 @@ function CLIENTWATCH:New(client)
-- @param #string Event Event. -- @param #string Event Event.
-- @param #string To To state. -- @param #string To To state.
-- @param #table clientObject Custom object that handles events and stores Moose object data. See top documentation for more details. -- @param #table clientObject Custom object that handles events and stores Moose object data. See top documentation for more details.
-- @param #table eventdata Data from EVENTS.Birth.
--Set up spawn tracking --Set up spawn tracking
if type(client) == "table" or type(client) == "string" then if not client then
if self.Debug then self:I({"New client instance created. ClientType = All clients"}) end
self:HandleEvent(EVENTS.Birth)
function self:OnEventBirth(eventdata)
if (eventdata.IniCategory == 0 or eventdata.IniCategory == 1) and eventdata.IniPlayerName
and (not self.FilterCoalition or self.FilterCoalition == eventdata.IniCoalition)
and (not self.FilterCategory or self.FilterCategory == eventdata.IniCategory) then
if self.Debug then
self:I({"Client spawned in.",IniCategory = eventdata.IniCategory})
end
local clientWatchDebug = self.Debug
local clientObject = CLIENTWATCHTools:_newClient(clientWatchDebug,eventdata)
self:Spawn(clientObject,eventdata)
end
end
elseif type(client) == "table" or type(client) == "string" then
if type(client) == "table" then if type(client) == "table" then
--CLIENT TABLE --CLIENT TABLE
if client.ClassName == "CLIENT" then if client.ClassName == "CLIENT" then
if self.Debug then self:I({"New client instance created. ClientType = Wrapper.CLIENT",client}) end
self.ClientName = client:GetName() self.ClientName = client:GetName()
self:HandleEvent(EVENTS.Birth) self:HandleEvent(EVENTS.Birth)
function self:OnEventBirth(eventdata) function self:OnEventBirth(eventdata)
if self.Debug then UTILS.PrintTableToLog(eventdata) end if (eventdata.IniCategory == 0 or eventdata.IniCategory == 1) and eventdata.IniPlayerName
if eventdata.IniCategory and eventdata.IniCategory <= 1 then and (not self.FilterCoalition or self.FilterCoalition == eventdata.IniCoalition)
and (not self.FilterCategory or self.FilterCategory == eventdata.IniCategory) then
if self.ClientName == eventdata.IniUnitName then if self.ClientName == eventdata.IniUnitName then
local clientObject = CLIENTWATCHTools:_newClient(eventdata) if self.Debug then
self:Spawn(clientObject) self:I({"Client spawned in.",IniCategory = eventdata.IniCategory})
end
local clientWatchDebug = self.Debug
local clientObject = CLIENTWATCHTools:_newClient(clientWatchDebug,eventdata)
self:Spawn(clientObject,eventdata)
end end
end end
end end
--STRING TABLE --STRING TABLE
else else
if self.Debug then self:I({"New client instance created. ClientType = Multiple Prefixes",client}) end
local tableValid = true local tableValid = true
for _,entry in pairs(client) do for _,entry in pairs(client) do
if type(entry) ~= "string" then if type(entry) ~= "string" then
@@ -187,12 +219,17 @@ function CLIENTWATCH:New(client)
if tableValid then if tableValid then
self:HandleEvent(EVENTS.Birth) self:HandleEvent(EVENTS.Birth)
function self:OnEventBirth(eventdata) function self:OnEventBirth(eventdata)
if self.Debug then UTILS.PrintTableToLog(eventdata) end
for _,entry in pairs(client) do for _,entry in pairs(client) do
if eventdata.IniCategory and eventdata.IniCategory <= 1 then if (eventdata.IniCategory == 0 or eventdata.IniCategory == 1) and eventdata.IniPlayerName
and (not self.FilterCoalition or self.FilterCoalition == eventdata.IniCoalition)
and (not self.FilterCategory or self.FilterCategory == eventdata.IniCategory) then
if string.match(eventdata.IniUnitName,entry) or string.match(eventdata.IniGroupName,entry) then if string.match(eventdata.IniUnitName,entry) or string.match(eventdata.IniGroupName,entry) then
local clientObject = CLIENTWATCHTools:_newClient(eventdata) if self.Debug then
self:Spawn(clientObject) self:I({"Client spawned in.",IniCategory = eventdata.IniCategory})
end
local clientWatchDebug = self.Debug
local clientObject = CLIENTWATCHTools:_newClient(clientWatchDebug,eventdata)
self:Spawn(clientObject,eventdata)
break break
end end
end end
@@ -201,15 +238,21 @@ function CLIENTWATCH:New(client)
end end
end end
else else
if self.Debug then self:I({"New client instance created. ClientType = Single Prefix",client}) end
--SOLO STRING --SOLO STRING
self:HandleEvent(EVENTS.Birth) self:HandleEvent(EVENTS.Birth)
function self:OnEventBirth(eventdata) function self:OnEventBirth(eventdata)
if self.Debug then UTILS.PrintTableToLog(eventdata) end if (eventdata.IniCategory == 0 or eventdata.IniCategory == 1) and eventdata.IniPlayerName
if eventdata.IniCategory and eventdata.IniCategory <= 1 then and (not self.FilterCoalition or self.FilterCoalition == eventdata.IniCoalition)
and (not self.FilterCategory or self.FilterCategory == eventdata.IniCategory) then
if string.match(eventdata.IniUnitName,client) or string.match(eventdata.IniGroupName,client) then if string.match(eventdata.IniUnitName,client) or string.match(eventdata.IniGroupName,client) then
local clientObject = CLIENTWATCHTools:_newClient(eventdata) if self.Debug then
self:Spawn(clientObject) self:I({"Client spawned in.",IniCategory = eventdata.IniCategory})
end
local clientWatchDebug = self.Debug
local clientObject = CLIENTWATCHTools:_newClient(clientWatchDebug,eventdata)
self:Spawn(clientObject,eventdata)
end end
end end
end end
@@ -222,13 +265,41 @@ function CLIENTWATCH:New(client)
return self return self
end end
--- Filter out all clients not belonging to the provided coalition
-- @param #CLIENTWATCH self
-- @param #number Coalition number (1 = red, 2 = blue)
-- @param #string Coalition string ('red' or 'blue')
function CLIENTWATCH:FilterByCoalition(value)
if value == 1 or value == "red" then
self.FilterCoalition = 1
else
self.FilterCoalition = 2
end
return self
end
--- Filter out all clients that are not of the given category
-- @param #CLIENTWATCH self
-- @param #number Category number (0 = airplane, 1 = helicopter)
-- @param #string Category string ('airplane' or 'helicopter')
function CLIENTWATCH:FilterByCategory(value)
if value == 1 or value == "helicopter" then
self.FilterCategory = 1
else
self.FilterCategory = 0
end
return self
end
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Internal function for creating a new client on birth. Do not use!!!. --- Internal function for creating a new client on birth. Do not use!!!.
-- @param #CLIENTWATCHTools self -- @param #CLIENTWATCHTools self
-- @param #EVENTS.Birth EventData -- @param #EVENTS.Birth EventData
-- @return #CLIENTWATCHTools self -- @return #CLIENTWATCHTools self
function CLIENTWATCHTools:_newClient(eventdata) function CLIENTWATCHTools:_newClient(clientWatchDebug,eventdata)
--Init FSM --Init FSM
local self=BASE:Inherit(self, FSM:New()) local self=BASE:Inherit(self, FSM:New())
self:SetStartState( "Alive" ) self:SetStartState( "Alive" )
@@ -299,78 +370,130 @@ function CLIENTWATCHTools:_newClient(eventdata)
function self:OnEventHit(EventData) function self:OnEventHit(EventData)
if EventData.TgtUnitName == self.UnitName then if EventData.TgtUnitName == self.UnitName then
if clientWatchDebug then
self:I({"Client triggered hit event.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
end
self:Hit(EventData) self:Hit(EventData)
end end
end end
function self:OnEventKill(EventData) function self:OnEventKill(EventData)
if EventData.IniUnitName == self.UnitName then if EventData.IniUnitName == self.UnitName then
if clientWatchDebug then
self:I({"Client triggered kill event.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
end
self:Kill(EventData) self:Kill(EventData)
end end
end end
function self:OnEventScore(EventData) function self:OnEventScore(EventData)
if EventData.IniUnitName == self.UnitName then if EventData.IniUnitName == self.UnitName then
if clientWatchDebug then
self:I({"Client triggered score event.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
end
self:Score(EventData) self:Score(EventData)
end end
end end
function self:OnEventShot(EventData) function self:OnEventShot(EventData)
if EventData.IniUnitName == self.UnitName then if EventData.IniUnitName == self.UnitName then
if clientWatchDebug then
self:I({"Client triggered shot event.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
end
self:Shot(EventData) self:Shot(EventData)
end end
end end
function self:OnEventShootingStart(EventData) function self:OnEventShootingStart(EventData)
if EventData.IniUnitName == self.UnitName then if EventData.IniUnitName == self.UnitName then
if clientWatchDebug then
self:I({"Client triggered shooting start event.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
end
self:ShootingStart(EventData) self:ShootingStart(EventData)
end end
end end
function self:OnEventShootingEnd(EventData) function self:OnEventShootingEnd(EventData)
if EventData.IniUnitName == self.UnitName then if EventData.IniUnitName == self.UnitName then
if clientWatchDebug then
self:I({"Client triggered shooting end event.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
end
self:ShootingEnd(EventData) self:ShootingEnd(EventData)
end end
end end
function self:OnEventLand(EventData) function self:OnEventLand(EventData)
if EventData.IniUnitName == self.UnitName then if EventData.IniUnitName == self.UnitName then
if clientWatchDebug then
self:I({"Client triggered land event.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
end
self:Land(EventData) self:Land(EventData)
end end
end end
function self:OnEventTakeoff(EventData) function self:OnEventTakeoff(EventData)
if EventData.IniUnitName == self.UnitName then if EventData.IniUnitName == self.UnitName then
if clientWatchDebug then
self:I({"Client triggered takeoff event.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
end
self:Takeoff(EventData) self:Takeoff(EventData)
end end
end end
function self:OnEventRunwayTakeoff(EventData) function self:OnEventRunwayTakeoff(EventData)
if EventData.IniUnitName == self.UnitName then if EventData.IniUnitName == self.UnitName then
if clientWatchDebug then
self:I({"Client triggered runway takeoff event.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
end
self:RunwayTakeoff(EventData) self:RunwayTakeoff(EventData)
end end
end end
function self:OnEventRunwayTouch(EventData) function self:OnEventRunwayTouch(EventData)
if EventData.IniUnitName == self.UnitName then if EventData.IniUnitName == self.UnitName then
if clientWatchDebug then
self:I({"Client triggered runway touch event.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
end
self:RunwayTouch(EventData) self:RunwayTouch(EventData)
end end
end end
function self:OnEventRefueling(EventData) function self:OnEventRefueling(EventData)
if EventData.IniUnitName == self.UnitName then if EventData.IniUnitName == self.UnitName then
if clientWatchDebug then
self:I({"Client triggered refueling event.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
end
self:Refueling(EventData) self:Refueling(EventData)
end end
end end
function self:OnEventRefuelingStop(EventData) function self:OnEventRefuelingStop(EventData)
if EventData.IniUnitName == self.UnitName then if EventData.IniUnitName == self.UnitName then
if clientWatchDebug then
self:I({"Client triggered refueling event.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
end
self:RefuelingStop(EventData) self:RefuelingStop(EventData)
end end
end end
function self:OnEventPlayerLeaveUnit(EventData) function self:OnEventPlayerLeaveUnit(EventData)
if EventData.IniUnitName == self.UnitName then if EventData.IniUnitName == self.UnitName then
if clientWatchDebug then
self:I({"Client triggered leave unit event.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
end
self:PlayerLeaveUnit(EventData) self:PlayerLeaveUnit(EventData)
self._deadRoutine() self._deadRoutine()
end end
@@ -378,6 +501,10 @@ function CLIENTWATCHTools:_newClient(eventdata)
function self:OnEventCrash(EventData) function self:OnEventCrash(EventData)
if EventData.IniUnitName == self.UnitName then if EventData.IniUnitName == self.UnitName then
if clientWatchDebug then
self:I({"Client triggered crash event.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
end
self:Crash(EventData) self:Crash(EventData)
self._deadRoutine() self._deadRoutine()
end end
@@ -385,6 +512,10 @@ function CLIENTWATCHTools:_newClient(eventdata)
function self:OnEventDead(EventData) function self:OnEventDead(EventData)
if EventData.IniUnitName == self.UnitName then if EventData.IniUnitName == self.UnitName then
if clientWatchDebug then
self:I({"Client triggered dead event.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
end
self:Dead(EventData) self:Dead(EventData)
self._deadRoutine() self._deadRoutine()
end end
@@ -392,6 +523,10 @@ function CLIENTWATCHTools:_newClient(eventdata)
function self:OnEventPilotDead(EventData) function self:OnEventPilotDead(EventData)
if EventData.IniUnitName == self.UnitName then if EventData.IniUnitName == self.UnitName then
if clientWatchDebug then
self:I({"Client triggered pilot dead event.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
end
self:PilotDead(EventData) self:PilotDead(EventData)
self._deadRoutine() self._deadRoutine()
end end
@@ -399,6 +534,10 @@ function CLIENTWATCHTools:_newClient(eventdata)
function self:OnEventUnitLost(EventData) function self:OnEventUnitLost(EventData)
if EventData.IniUnitName == self.UnitName then if EventData.IniUnitName == self.UnitName then
if clientWatchDebug then
self:I({"Client triggered unit lost event.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
end
self:UnitLost(EventData) self:UnitLost(EventData)
self._deadRoutine() self._deadRoutine()
end end
@@ -406,6 +545,10 @@ function CLIENTWATCHTools:_newClient(eventdata)
function self:OnEventEjection(EventData) function self:OnEventEjection(EventData)
if EventData.IniUnitName == self.UnitName then if EventData.IniUnitName == self.UnitName then
if clientWatchDebug then
self:I({"Client triggered ejection event.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
end
self:Ejection(EventData) self:Ejection(EventData)
self._deadRoutine() self._deadRoutine()
end end
@@ -413,6 +556,10 @@ function CLIENTWATCHTools:_newClient(eventdata)
function self:OnEventHumanFailure(EventData) function self:OnEventHumanFailure(EventData)
if EventData.IniUnitName == self.UnitName then if EventData.IniUnitName == self.UnitName then
if clientWatchDebug then
self:I({"Client triggered human failure event.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
end
self:HumanFailure(EventData) self:HumanFailure(EventData)
if not self.Unit:IsAlive() then if not self.Unit:IsAlive() then
self._deadRoutine() self._deadRoutine()
@@ -422,42 +569,70 @@ function CLIENTWATCHTools:_newClient(eventdata)
function self:OnEventHumanAircraftRepairFinish(EventData) function self:OnEventHumanAircraftRepairFinish(EventData)
if EventData.IniUnitName == self.UnitName then if EventData.IniUnitName == self.UnitName then
if clientWatchDebug then
self:I({"Client triggered repair finished event.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
end
self:HumanAircraftRepairFinish(EventData) self:HumanAircraftRepairFinish(EventData)
end end
end end
function self:OnEventHumanAircraftRepairStart(EventData) function self:OnEventHumanAircraftRepairStart(EventData)
if EventData.IniUnitName == self.UnitName then if EventData.IniUnitName == self.UnitName then
if clientWatchDebug then
self:I({"Client triggered repair start event.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
end
self:HumanAircraftRepairStart(EventData) self:HumanAircraftRepairStart(EventData)
end end
end end
function self:OnEventEngineShutdown(EventData) function self:OnEventEngineShutdown(EventData)
if EventData.IniUnitName == self.UnitName then if EventData.IniUnitName == self.UnitName then
if clientWatchDebug then
self:I({"Client triggered engine shutdown event.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
end
self:EngineShutdown(EventData) self:EngineShutdown(EventData)
end end
end end
function self:OnEventEngineStartup(EventData) function self:OnEventEngineStartup(EventData)
if EventData.IniUnitName == self.UnitName then if EventData.IniUnitName == self.UnitName then
if clientWatchDebug then
self:I({"Client triggered engine startup event.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
end
self:EngineStartup(EventData) self:EngineStartup(EventData)
end end
end end
function self:OnEventWeaponAdd(EventData) function self:OnEventWeaponAdd(EventData)
if EventData.IniUnitName == self.UnitName then if EventData.IniUnitName == self.UnitName then
if clientWatchDebug then
self:I({"Client triggered weapon add event.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
end
self:WeaponAdd(EventData) self:WeaponAdd(EventData)
end end
end end
function self:OnEventWeaponDrop(EventData) function self:OnEventWeaponDrop(EventData)
if EventData.IniUnitName == self.UnitName then if EventData.IniUnitName == self.UnitName then
if clientWatchDebug then
self:I({"Client triggered weapon drop event.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
end
self:WeaponDrop(EventData) self:WeaponDrop(EventData)
end end
end end
function self:OnEventWeaponRearm(EventData) function self:OnEventWeaponRearm(EventData)
if EventData.IniUnitName == self.UnitName then if EventData.IniUnitName == self.UnitName then
if clientWatchDebug then
self:I({"Client triggered weapon rearm event.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
end
self:WeaponRearm(EventData) self:WeaponRearm(EventData)
end end
end end
@@ -466,6 +641,9 @@ function CLIENTWATCHTools:_newClient(eventdata)
--Fallback timer --Fallback timer
self.FallbackTimer = TIMER:New(function() self.FallbackTimer = TIMER:New(function()
if not self.Unit:IsAlive() then if not self.Unit:IsAlive() then
if clientWatchDebug then
self:I({"Client is registered as dead without an event trigger. Running fallback dead routine.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
end
self._deadRoutine() self._deadRoutine()
end end
end) end)
@@ -473,6 +651,7 @@ function CLIENTWATCHTools:_newClient(eventdata)
--Stop event handlers and trigger Despawn --Stop event handlers and trigger Despawn
function self._deadRoutine() function self._deadRoutine()
if clientWatchDebug then self:I({"Client dead routine triggered. Shutting down tracking...",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName}) end
self:UnHandleEvent( EVENTS.Hit ) self:UnHandleEvent( EVENTS.Hit )
self:UnHandleEvent( EVENTS.Kill ) self:UnHandleEvent( EVENTS.Kill )
self:UnHandleEvent( EVENTS.Score ) self:UnHandleEvent( EVENTS.Score )
@@ -503,6 +682,6 @@ function CLIENTWATCHTools:_newClient(eventdata)
self:Despawn() self:Despawn()
end end
self:I({"CLIENT SPAWN EVENT", PlayerName = self.PlayerName, UnitName = self.UnitName, GroupName = self.GroupName}) self:I({"Detected client spawn and applied internal functions and events.", PlayerName = self.PlayerName, UnitName = self.UnitName, GroupName = self.GroupName})
return self return self
end end
@@ -596,6 +596,7 @@ do -- DETECTION_BASE
return self return self
end end
---
-- @param #DETECTION_BASE self -- @param #DETECTION_BASE self
-- @param #string From The From State string. -- @param #string From The From State string.
-- @param #string Event The Event string. -- @param #string Event The Event string.
@@ -615,7 +616,7 @@ do -- DETECTION_BASE
self:T( { "DetectionGroup is Alive", Detection:GetName() } ) self:T( { "DetectionGroup is Alive", Detection:GetName() } )
local DetectionGroupName = Detection:GetName() local DetectionGroupName = Detection:GetName()
local DetectionUnit = Detection:GetUnit( 1 ) local DetectionUnit = Detection:GetFirstUnitAlive()
local DetectedUnits = {} local DetectedUnits = {}
@@ -632,7 +633,7 @@ do -- DETECTION_BASE
--self:T(UTILS.PrintTableToLog(DetectedTargets)) --self:T(UTILS.PrintTableToLog(DetectedTargets))
for DetectionObjectID, Detection in pairs( DetectedTargets ) do for DetectionObjectID, Detection in pairs( DetectedTargets or {}) do
local DetectedObject = Detection.object -- DCS#Object local DetectedObject = Detection.object -- DCS#Object
if DetectedObject and DetectedObject:isExist() and DetectedObject.id_ < 50000000 then -- and ( DetectedObject:getCategory() == Object.Category.UNIT or DetectedObject:getCategory() == Object.Category.STATIC ) then if DetectedObject and DetectedObject:isExist() and DetectedObject.id_ < 50000000 then -- and ( DetectedObject:getCategory() == Object.Category.UNIT or DetectedObject:getCategory() == Object.Category.STATIC ) then
@@ -645,7 +646,7 @@ do -- DETECTION_BASE
end end
end end
for DetectionObjectName, DetectedObjectData in pairs( self.DetectedObjects ) do for DetectionObjectName, DetectedObjectData in pairs( self.DetectedObjects or {}) do
local DetectedObject = DetectedObjectData.Object local DetectedObject = DetectedObjectData.Object
+22 -18
View File
@@ -1340,7 +1340,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:T2( self.lid .. string.format( "Setting sound files path to %s", self.soundpath ) )
return self return self
end end
@@ -1636,9 +1636,9 @@ function RANGE:AddBombingTargetUnit( unit, goodhitrange, randommove )
-- Debug or error output. -- Debug or error output.
if _isstatic == true then if _isstatic == true then
self:I( self.lid .. string.format( "Adding STATIC bombing target %s with good hit range %d. Random move = %s.", name, goodhitrange, tostring( randommove ) ) ) self:T( self.lid .. 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:I( self.lid .. string.format( "Adding UNIT bombing target %s with good hit range %d. Random move = %s.", name, goodhitrange, tostring( randommove ) ) ) self:T( self.lid .. string.format( "Adding UNIT bombing target %s with good hit range %d. Random move = %s.", name, goodhitrange, tostring( randommove ) ) )
else else
self:E( self.lid .. 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.lid .. 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
@@ -1706,7 +1706,7 @@ function RANGE:AddBombingTargetScenery( scenery, goodhitrange)
-- Debug or error output. -- Debug or error output.
if name then if name then
self:I( self.lid .. string.format( "Adding SCENERY bombing target %s with good hit range %d", name, goodhitrange) ) self:T( self.lid .. string.format( "Adding SCENERY bombing target %s with good hit range %d", name, goodhitrange) )
else else
self:E( self.lid .. string.format( "ERROR! No bombing target with name %s could be found!", name ) ) self:E( self.lid .. string.format( "ERROR! No bombing target with name %s could be found!", name ) )
end end
@@ -1811,7 +1811,7 @@ function RANGE:OnEventBirth( EventData )
if not EventData.IniPlayerName then return end if not EventData.IniPlayerName then return end
local _unitName = EventData.IniUnitName local _unitName = EventData.IniUnitName
local _unit, _playername = self:_GetPlayerUnitAndName( _unitName ) local _unit, _playername = self:_GetPlayerUnitAndName( _unitName, EventData.IniPlayerName )
self:T3( self.lid .. "BIRTH: unit = " .. tostring( EventData.IniUnitName ) ) self:T3( self.lid .. "BIRTH: unit = " .. tostring( EventData.IniUnitName ) )
self:T3( self.lid .. "BIRTH: group = " .. tostring( EventData.IniGroupName ) ) self:T3( self.lid .. "BIRTH: group = " .. tostring( EventData.IniGroupName ) )
@@ -1968,6 +1968,8 @@ end
-- @param #number attackVel Attack velocity. -- @param #number attackVel Attack velocity.
function RANGE._OnImpact(weapon, self, playerData, attackHdg, attackAlt, attackVel) function RANGE._OnImpact(weapon, self, playerData, attackHdg, attackAlt, attackVel)
if not playerData then return end
-- Get closet target to last position. -- Get closet target to last position.
local _closetTarget = nil -- #RANGE.BombTarget local _closetTarget = nil -- #RANGE.BombTarget
local _distance = nil local _distance = nil
@@ -1984,13 +1986,13 @@ function RANGE._OnImpact(weapon, self, playerData, attackHdg, attackAlt, attackV
-- Coordinate of impact point. -- Coordinate of impact point.
local impactcoord = weapon:GetImpactCoordinate() local impactcoord = weapon:GetImpactCoordinate()
-- Check if impact happened in range zone. -- Check if impact happened in range zone.+
local insidezone = self.rangezone:IsCoordinateInZone( impactcoord ) local insidezone = self.rangezone:IsCoordinateInZone( impactcoord )
-- Smoke impact point of bomb. -- Smoke impact point of bomb.
if playerData.smokebombimpact and insidezone then if playerData and playerData.smokebombimpact and insidezone then
if playerData.delaysmoke then if playerData and playerData.delaysmoke then
timer.scheduleFunction( self._DelayedSmoke, { coord = impactcoord, color = playerData.smokecolor }, timer.getTime() + self.TdelaySmoke ) timer.scheduleFunction( self._DelayedSmoke, { coord = impactcoord, color = playerData.smokecolor }, timer.getTime() + self.TdelaySmoke )
else else
impactcoord:Smoke( playerData.smokecolor ) impactcoord:Smoke( playerData.smokecolor )
@@ -2115,7 +2117,7 @@ function RANGE:OnEventShot( EventData )
local _unitName = EventData.IniUnitName local _unitName = EventData.IniUnitName
-- Get player unit and name. -- Get player unit and name.
local _unit, _playername = self:_GetPlayerUnitAndName( _unitName ) local _unit, _playername = self:_GetPlayerUnitAndName( _unitName, EventData.IniPlayerName )
-- Distance Player-to-Range. Set this to larger value than the threshold. -- Distance Player-to-Range. Set this to larger value than the threshold.
local dPR = self.BombtrackThreshold * 2 local dPR = self.BombtrackThreshold * 2
@@ -2127,11 +2129,13 @@ function RANGE:OnEventShot( EventData )
end end
-- Only track if distance player to range is < 25 km. Also check that a player shot. No need to track AI weapons. -- Only track if distance player to range is < 25 km. Also check that a player shot. No need to track AI weapons.
if _track and dPR <= self.BombtrackThreshold and _unit and _playername then if _track and dPR <= self.BombtrackThreshold and _unit and _playername and self.PlayerSettings[_playername] then
-- Player data. -- Player data.
local playerData = self.PlayerSettings[_playername] -- #RANGE.PlayerData local playerData = self.PlayerSettings[_playername] -- #RANGE.PlayerData
if not playerData then return end
-- Attack parameters. -- Attack parameters.
local attackHdg=_unit:GetHeading() local attackHdg=_unit:GetHeading()
local attackAlt=_unit:GetHeight() local attackAlt=_unit:GetHeight()
@@ -2192,7 +2196,7 @@ function RANGE:onafterStatus( From, Event, To )
end end
-- Check range status. -- Check range status.
self:I( self.lid .. text ) self:T( self.lid .. text )
end end
@@ -2393,7 +2397,7 @@ function RANGE:onafterSave( From, Event, To )
if f then if f then
f:write( data ) f:write( data )
f:close() f:close()
self:I( self.lid .. string.format( "Saving player results to file %s", tostring( filename ) ) ) self:T( self.lid .. string.format( "Saving player results to file %s", tostring( filename ) ) )
else else
self:E( self.lid .. string.format( "ERROR: Could not save results to file %s", tostring( filename ) ) ) self:E( self.lid .. string.format( "ERROR: Could not save results to file %s", tostring( filename ) ) )
end end
@@ -2472,7 +2476,7 @@ function RANGE:onafterLoad( From, Event, To )
-- Info message. -- Info message.
local text = string.format( "Loading player bomb results from file %s", filename ) local text = string.format( "Loading player bomb results from file %s", filename )
self:I( self.lid .. text ) self:T( self.lid .. text )
-- Load asset data from file. -- Load asset data from file.
local data = _loadfile( filename ) local data = _loadfile( filename )
@@ -2845,7 +2849,7 @@ function RANGE:_DisplayRangeInfo( _unitname )
-- Check if we have a player. -- Check if we have a player.
if unit and playername then if unit and playername then
self:I(playername) --self:I(playername)
-- Message text. -- Message text.
local text = "" local text = ""
@@ -4099,8 +4103,8 @@ end
-- @return Wrapper.Unit#UNIT Unit of player. -- @return Wrapper.Unit#UNIT Unit of player.
-- @return #string Name of the player. -- @return #string Name of the player.
-- @return #boolean If true, group has > 1 player in it -- @return #boolean If true, group has > 1 player in it
function RANGE:_GetPlayerUnitAndName( _unitName ) function RANGE:_GetPlayerUnitAndName( _unitName, PlayerName )
self:F2( _unitName ) --self:I( _unitName )
if _unitName ~= nil then if _unitName ~= nil then
@@ -4109,9 +4113,9 @@ function RANGE:_GetPlayerUnitAndName( _unitName )
-- Get DCS unit from its name. -- Get DCS unit from its name.
local DCSunit = Unit.getByName( _unitName ) local DCSunit = Unit.getByName( _unitName )
if DCSunit then if DCSunit and DCSunit.getPlayerName then
local playername = DCSunit:getPlayerName() local playername = DCSunit:getPlayerName() or PlayerName or "None"
local unit = UNIT:Find( DCSunit ) local unit = UNIT:Find( DCSunit )
self:T2( { DCSunit = DCSunit, unit = unit, playername = playername } ) self:T2( { DCSunit = DCSunit, unit = unit, playername = playername } )
File diff suppressed because it is too large Load Diff
@@ -6732,7 +6732,7 @@ end
-- @param Wrapper.Group#GROUP deadgroup Group of unit that died. -- @param Wrapper.Group#GROUP deadgroup Group of unit that died.
-- @param #WAREHOUSE.Pendingitem request Request that needs to be updated. -- @param #WAREHOUSE.Pendingitem request Request that needs to be updated.
function WAREHOUSE:_UnitDead(deadunit, deadgroup, request) function WAREHOUSE:_UnitDead(deadunit, deadgroup, request)
self:F(self.lid.."FF unit dead "..deadunit:GetName()) --self:F(self.lid.."FF unit dead "..deadunit:GetName())
-- Find opsgroup. -- Find opsgroup.
local opsgroup=_DATABASE:FindOpsGroup(deadgroup) local opsgroup=_DATABASE:FindOpsGroup(deadgroup)
+1
View File
@@ -49,6 +49,7 @@ __Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Wrapper/Marker.lua' )
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Wrapper/Weapon.lua' ) __Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Wrapper/Weapon.lua' )
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Wrapper/Net.lua' ) __Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Wrapper/Net.lua' )
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Wrapper/Storage.lua' ) __Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Wrapper/Storage.lua' )
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Wrapper/DynamicCargo.lua' )
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Cargo/Cargo.lua' ) __Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Cargo/Cargo.lua' )
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Cargo/CargoUnit.lua' ) __Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Cargo/CargoUnit.lua' )
@@ -47,6 +47,7 @@ __Moose.Include( 'Wrapper\\Marker.lua' )
__Moose.Include( 'Wrapper\\Net.lua' ) __Moose.Include( 'Wrapper\\Net.lua' )
__Moose.Include( 'Wrapper\\Weapon.lua' ) __Moose.Include( 'Wrapper\\Weapon.lua' )
__Moose.Include( 'Wrapper\\Storage.lua' ) __Moose.Include( 'Wrapper\\Storage.lua' )
__Moose.Include( 'Wrapper\\DynamicCargo.lua' )
__Moose.Include( 'Cargo\\Cargo.lua' ) __Moose.Include( 'Cargo\\Cargo.lua' )
__Moose.Include( 'Cargo\\CargoUnit.lua' ) __Moose.Include( 'Cargo\\CargoUnit.lua' )
@@ -81,6 +82,7 @@ __Moose.Include( 'Functional\\AICSAR.lua' )
__Moose.Include( 'Functional\\AmmoTruck.lua' ) __Moose.Include( 'Functional\\AmmoTruck.lua' )
__Moose.Include( 'Functional\\Tiresias.lua' ) __Moose.Include( 'Functional\\Tiresias.lua' )
__Moose.Include( 'Functional\\Stratego.lua' ) __Moose.Include( 'Functional\\Stratego.lua' )
__Moose.Include( 'Functional\\ClientWatch.lua' )
__Moose.Include( 'Ops\\Airboss.lua' ) __Moose.Include( 'Ops\\Airboss.lua' )
__Moose.Include( 'Ops\\RecoveryTanker.lua' ) __Moose.Include( 'Ops\\RecoveryTanker.lua' )
+104 -3
View File
@@ -882,6 +882,66 @@ ATIS.Messages = {
FARP = "Farp", FARP = "Farp",
DELIMITER = "Punto", -- decimal delimiter DELIMITER = "Punto", -- decimal delimiter
}, },
-- French messages thanks to @Wojtech and Bing
FR = {
HOURS = "Heures",
TIME = "Temps",
NOCLOUDINFO = "Informations sur la couverture nuageuse non disponibles",
OVERCAST = "Ciel couvert",
BROKEN = "Nuages fragmentés",
SCATTERED = "Nuages épars",
FEWCLOUDS = "Nuages rares",
NOCLOUDS = "Clair",
AIRPORT = "Aéroport",
INFORMATION ="Information",
SUNRISEAT = "Levé du soleil à %s heure locale",
SUNSETAT = "Couché du soleil à %s heure locale",
WINDFROMMS = "Vent du %s pour %s mètres par seconde",
WINDFROMKNOTS = "Vent du %s pour %s noeuds",
GUSTING = "Rafale de vent",
VISIKM = "Visibilité %s kilomètres",
VISISM = "Visibilité %s Miles",
RAIN = "Pluie",
TSTORM = "Orage",
SNOW = "Neige",
SSTROM = "Tempête de neige",
FOG = "Brouillard",
DUST = "Poussière",
PHENOMENA = "Phénomène météorologique",
CLOUDBASEM = "Couverture nuageuse de %s à %s mètres",
CLOUDBASEFT = "Couverture nuageuse de %s à %s pieds",
TEMPERATURE = "Température",
DEWPOINT = "Point de rosée",
ALTIMETER = "Altimètre",
ACTIVERUN = "Décollages piste",
ACTIVELANDING = "Atterrissages piste",
LEFT = "Gauche",
RIGHT = "Droite",
RWYLENGTH = "Longueur de piste",
METERS = "Mètre",
FEET = "Pieds",
ELEVATION = "Hauteur",
TOWERFREQ = "Fréquences de la tour",
ILSFREQ = "Fréquences ILS",
OUTERNDB = "Fréquences Outer NDB",
INNERNDB = "Fréquences Inner NDB",
VORFREQ = "Fréquences VOR",
VORFREQTTS = "Fréquences V O R",
TACANCH = "Canal TACAN %d",
RSBNCH = "Canal RSBN",
PRMGCH = "Canal PRMG",
ADVISE = "Informez le contrôle que vous avez copié l'information",
STATUTE = "Statute Miles",
DEGREES = "Degré celcius",
FAHRENHEIT = "Degré Fahrenheit",
INCHHG = "Pouces de mercure",
MMHG = "Millimètres de mercure",
HECTO = "Hectopascals",
METERSPER = "Mètres par seconde",
TACAN = "TAKAN",
FARP = "FARPE",
DELIMITER = "Décimal", -- decimal delimiter
}
} }
--- ---
@@ -1061,7 +1121,7 @@ end
-- @return #ATIS self -- @return #ATIS self
function ATIS:_InitLocalization() function ATIS:_InitLocalization()
self:T(self.lid.."_InitLocalization") self:T(self.lid.."_InitLocalization")
self.gettext = TEXTANDSOUND:New("AWACS","en") -- Core.TextAndSound#TEXTANDSOUND self.gettext = TEXTANDSOUND:New("ATIS","en") -- Core.TextAndSound#TEXTANDSOUND
self.locale = "en" self.locale = "en"
for locale,table in pairs(self.Messages) do for locale,table in pairs(self.Messages) do
local Locale = string.lower(tostring(locale)) local Locale = string.lower(tostring(locale))
@@ -1975,18 +2035,26 @@ function ATIS:onafterBroadcast( From, Event, To )
local hours = self.gettext:GetEntry("HOURS",self.locale) local hours = self.gettext:GetEntry("HOURS",self.locale)
local sunrise = coord:GetSunrise() local sunrise = coord:GetSunrise()
--self:I(sunrise)
local SUNRISE = "no time"
if tostring(sunrise) ~= "N/S" and tostring(sunrise) ~= "N/R" then
sunrise = UTILS.Split( sunrise, ":" ) sunrise = UTILS.Split( sunrise, ":" )
local SUNRISE = string.format( "%s%s", sunrise[1], sunrise[2] ) SUNRISE = string.format( "%s%s", sunrise[1], sunrise[2] )
if self.useSRS then if self.useSRS then
SUNRISE = string.format( "%s %s %s", sunrise[1], sunrise[2], hours ) SUNRISE = string.format( "%s %s %s", sunrise[1], sunrise[2], hours )
end end
end
local sunset = coord:GetSunset() local sunset = coord:GetSunset()
--self:I(sunset)
local SUNSET = "no time"
if tostring(sunset) ~= "N/S" and tostring(sunset) ~= "N/R" then
sunset = UTILS.Split( sunset, ":" ) sunset = UTILS.Split( sunset, ":" )
local SUNSET = string.format( "%s%s", sunset[1], sunset[2] ) SUNSET = string.format( "%s%s", sunset[1], sunset[2] )
if self.useSRS then if self.useSRS then
SUNSET = string.format( "%s %s %s", sunset[1], sunset[2], hours ) SUNSET = string.format( "%s %s %s", sunset[1], sunset[2], hours )
end end
end
--------------------------------- ---------------------------------
--- Temperature and Dew Point --- --- Temperature and Dew Point ---
@@ -2100,6 +2168,39 @@ function ATIS:onafterBroadcast( From, Event, To )
else else
precepitation = 3 -- snow precepitation = 3 -- snow
end end
elseif cloudspreset:find( "RainyPreset4" ) then
-- Overcast + Rain
clouddens = 5
if temperature > 5 then
precepitation = 1 -- rain
else
precepitation = 3 -- snow
end
elseif cloudspreset:find( "RainyPreset5" ) then
-- Overcast + Rain
clouddens = 5
if temperature > 5 then
precepitation = 1 -- rain
else
precepitation = 3 -- snow
end
elseif cloudspreset:find( "RainyPreset6" ) then
-- Overcast + Rain
clouddens = 5
if temperature > 5 then
precepitation = 1 -- rain
else
precepitation = 3 -- snow
end
-- NEWRAINPRESET4
elseif cloudspreset:find( "NEWRAINPRESET4" ) then
-- Overcast + Rain
clouddens = 5
if temperature > 5 then
precepitation = 1 -- rain
else
precepitation = 3 -- snow
end
elseif cloudspreset:find( "RainyPreset" ) then elseif cloudspreset:find( "RainyPreset" ) then
-- Overcast + Rain -- Overcast + Rain
clouddens = 9 clouddens = 9
+5 -5
View File
@@ -14680,7 +14680,7 @@ function AIRBOSS:_GetPlayerUnitAndName( _unitName )
-- Get DCS unit from its name. -- Get DCS unit from its name.
local DCSunit = Unit.getByName( _unitName ) local DCSunit = Unit.getByName( _unitName )
if DCSunit then if DCSunit and DCSunit.getPlayerName then
-- Get player name if any. -- Get player name if any.
local playername = DCSunit:getPlayerName() local playername = DCSunit:getPlayerName()
@@ -15651,7 +15651,7 @@ function AIRBOSS:_Number2Sound( playerData, sender, number, delay )
end end
-- Split string into characters. -- Split string into characters.
local numbers = _split( number ) local numbers = _split( tostring(number) )
local wait = 0 local wait = 0
for i = 1, #numbers do for i = 1, #numbers do
@@ -15719,7 +15719,7 @@ function AIRBOSS:_Number2Radio( radio, number, delay, interval, pilotcall )
end end
-- Split string into characters. -- Split string into characters.
local numbers = _split( number ) local numbers = _split( tostring(number) )
local wait = 0 local wait = 0
for i = 1, #numbers do for i = 1, #numbers do
@@ -18087,7 +18087,7 @@ function AIRBOSS:_MarkCaseZones( _unitName, flare )
self:_GetZoneArcIn( case ):FlareZone( FLARECOLOR.White, 45 ) self:_GetZoneArcIn( case ):FlareZone( FLARECOLOR.White, 45 )
text = text .. "\n* arc turn in with WHITE flares" text = text .. "\n* arc turn in with WHITE flares"
self:_GetZoneArcOut( case ):FlareZone( FLARECOLOR.White, 45 ) self:_GetZoneArcOut( case ):FlareZone( FLARECOLOR.White, 45 )
text = text .. "\n* arc trun out with WHITE flares" text = text .. "\n* arc turn out with WHITE flares"
end end
end end
@@ -18139,7 +18139,7 @@ function AIRBOSS:_MarkCaseZones( _unitName, flare )
self:_GetZoneArcIn( case ):SmokeZone( SMOKECOLOR.Blue, 45 ) self:_GetZoneArcIn( case ):SmokeZone( SMOKECOLOR.Blue, 45 )
text = text .. "\n* arc turn in with BLUE smoke" text = text .. "\n* arc turn in with BLUE smoke"
self:_GetZoneArcOut( case ):SmokeZone( SMOKECOLOR.Blue, 45 ) self:_GetZoneArcOut( case ):SmokeZone( SMOKECOLOR.Blue, 45 )
text = text .. "\n* arc trun out with BLUE smoke" text = text .. "\n* arc turn out with BLUE smoke"
end end
end end
+108 -21
View File
@@ -31,7 +31,7 @@
-- @image OPS_CSAR.jpg -- @image OPS_CSAR.jpg
--- ---
-- Last Update July 2024 -- Last Update Sep 2024
------------------------------------------------------------------------- -------------------------------------------------------------------------
--- **CSAR** class, extends Core.Base#BASE, Core.Fsm#FSM --- **CSAR** class, extends Core.Base#BASE, Core.Fsm#FSM
@@ -41,6 +41,7 @@
-- @field #string lid Class id string for output to DCS log file. -- @field #string lid Class id string for output to DCS log file.
-- @field #number coalition Coalition side number, e.g. `coalition.side.RED`. -- @field #number coalition Coalition side number, e.g. `coalition.side.RED`.
-- @field Core.Set#SET_GROUP allheligroupset Set of CSAR heli groups. -- @field Core.Set#SET_GROUP allheligroupset Set of CSAR heli groups.
-- @field Core.Set#SET_GROUP UserSetGroup Set of CSAR heli groups as designed by the mission designer (if any set).
-- @extends Core.Fsm#FSM -- @extends Core.Fsm#FSM
--- *Combat search and rescue (CSAR) are search and rescue operations that are carried out during war that are within or near combat zones.* (Wikipedia) --- *Combat search and rescue (CSAR) are search and rescue operations that are carried out during war that are within or near combat zones.* (Wikipedia)
@@ -116,8 +117,17 @@
-- mycsar.topmenuname = "CSAR" -- set the menu entry name -- mycsar.topmenuname = "CSAR" -- set the menu entry name
-- mycsar.ADFRadioPwr = 1000 -- ADF Beacons sending with 1KW as default -- mycsar.ADFRadioPwr = 1000 -- ADF Beacons sending with 1KW as default
-- mycsar.PilotWeight = 80 -- Loaded pilots weigh 80kgs each -- mycsar.PilotWeight = 80 -- Loaded pilots weigh 80kgs each
-- mycsar.AllowIRStrobe = false -- Allow a menu item to request an IR strobe to find a downed pilot at night (requires NVGs to see it).
-- mycsar.IRStrobeRuntime = 300 -- If an IR Strobe is activated, it runs for 300 seconds (5 mins).
-- --
-- ## 2.1 SRS Features and Other Features -- ## 2.1 Create own SET_GROUP to manage CTLD Pilot groups
--
-- -- Parameter: Set The SET_GROUP object created by the mission designer/user to represent the CSAR pilot groups.
-- -- Needs to be set before starting the CSAR instance.
-- local myset = SET_GROUP:New():FilterPrefixes("Helikopter"):FilterCoalitions("red"):FilterStart()
-- mycsar:SetOwnSetPilotGroups(myset)
--
-- ## 2.2 SRS Features and Other Features
-- --
-- mycsar.useSRS = false -- Set true to use FF\'s SRS integration -- mycsar.useSRS = false -- Set true to use FF\'s SRS integration
-- mycsar.SRSPath = "C:\\Progra~1\\DCS-SimpleRadio-Standalone\\" -- adjust your own path in your SRS installation -- server(!) -- mycsar.SRSPath = "C:\\Progra~1\\DCS-SimpleRadio-Standalone\\" -- adjust your own path in your SRS installation -- server(!)
@@ -136,6 +146,7 @@
-- mycsar.csarUsePara = false -- If set to true, will use the LandingAfterEjection Event instead of Ejection. Requires mycsar.enableForAI to be set to true. --shagrat -- mycsar.csarUsePara = false -- If set to true, will use the LandingAfterEjection Event instead of Ejection. Requires mycsar.enableForAI to be set to true. --shagrat
-- mycsar.wetfeettemplate = "man in floating thingy" -- if you use a mod to have a pilot in a rescue float, put the template name in here for wet feet spawns. Note: in conjunction with csarUsePara this might create dual ejected pilots in edge cases. -- mycsar.wetfeettemplate = "man in floating thingy" -- if you use a mod to have a pilot in a rescue float, put the template name in here for wet feet spawns. Note: in conjunction with csarUsePara this might create dual ejected pilots in edge cases.
-- mycsar.allowbronco = false -- set to true to use the Bronco mod as a CSAR plane -- mycsar.allowbronco = false -- set to true to use the Bronco mod as a CSAR plane
-- mycsar.CreateRadioBeacons = true -- set to false to disallow creating ADF radio beacons.
-- --
-- ## 3. Results -- ## 3. Results
-- --
@@ -256,6 +267,10 @@ CSAR = {
topmenuname = "CSAR", topmenuname = "CSAR",
ADFRadioPwr = 1000, ADFRadioPwr = 1000,
PilotWeight = 80, PilotWeight = 80,
CreateRadioBeacons = true,
UserSetGroup = nil,
AllowIRStrobe = false,
IRStrobeRuntime = 300,
} }
--- Downed pilots info. --- Downed pilots info.
@@ -272,6 +287,7 @@ CSAR = {
-- @field #number timestamp Timestamp for approach process. -- @field #number timestamp Timestamp for approach process.
-- @field #boolean alive Group is alive or dead/rescued. -- @field #boolean alive Group is alive or dead/rescued.
-- @field #boolean wetfeet Group is spawned over (deep) water. -- @field #boolean wetfeet Group is spawned over (deep) water.
-- @field #string BeaconName Name of radio beacon - if any.
--- All slot / Limit settings --- All slot / Limit settings
-- @type CSAR.AircraftType -- @type CSAR.AircraftType
@@ -297,7 +313,7 @@ CSAR.AircraftType["CH-47Fbl1"] = 31
--- CSAR class version. --- CSAR class version.
-- @field #string version -- @field #string version
CSAR.version="1.0.26" CSAR.version="1.0.29"
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- ToDo list -- ToDo list
@@ -457,6 +473,9 @@ function CSAR:New(Coalition, Template, Alias)
-- added 1.0.16 -- added 1.0.16
self.PilotWeight = 80 self.PilotWeight = 80
-- Own SET_GROUP if any
self.UserSetGroup = nil
-- WARNING - here\'ll be dragons -- WARNING - here\'ll be dragons
-- for this to work you need to de-sanitize your mission environment in <DCS root>\Scripts\MissionScripting.lua -- for this to work you need to de-sanitize your mission environment in <DCS root>\Scripts\MissionScripting.lua
-- needs SRS => 1.9.6 to work (works on the *server* side) -- needs SRS => 1.9.6 to work (works on the *server* side)
@@ -634,7 +653,7 @@ end
-- @param #string Playername Name of Player (if applicable) -- @param #string Playername Name of Player (if applicable)
-- @param #boolean Wetfeet Ejected over water -- @param #boolean Wetfeet Ejected over water
-- @return #CSAR self. -- @return #CSAR self.
function CSAR:_CreateDownedPilotTrack(Group,Groupname,Side,OriginalUnit,Description,Typename,Frequency,Playername,Wetfeet) function CSAR:_CreateDownedPilotTrack(Group,Groupname,Side,OriginalUnit,Description,Typename,Frequency,Playername,Wetfeet,BeaconName)
self:T({"_CreateDownedPilotTrack",Groupname,Side,OriginalUnit,Description,Typename,Frequency,Playername}) self:T({"_CreateDownedPilotTrack",Groupname,Side,OriginalUnit,Description,Typename,Frequency,Playername})
-- create new entry -- create new entry
@@ -642,7 +661,7 @@ function CSAR:_CreateDownedPilotTrack(Group,Groupname,Side,OriginalUnit,Descript
DownedPilot.desc = Description or "" DownedPilot.desc = Description or ""
DownedPilot.frequency = Frequency or 0 DownedPilot.frequency = Frequency or 0
DownedPilot.index = self.downedpilotcounter DownedPilot.index = self.downedpilotcounter
DownedPilot.name = Groupname or "" DownedPilot.name = Groupname or Playername or ""
DownedPilot.originalUnit = OriginalUnit or "" DownedPilot.originalUnit = OriginalUnit or ""
DownedPilot.player = Playername or "" DownedPilot.player = Playername or ""
DownedPilot.side = Side or 0 DownedPilot.side = Side or 0
@@ -651,6 +670,7 @@ function CSAR:_CreateDownedPilotTrack(Group,Groupname,Side,OriginalUnit,Descript
DownedPilot.timestamp = 0 DownedPilot.timestamp = 0
DownedPilot.alive = true DownedPilot.alive = true
DownedPilot.wetfeet = Wetfeet or false DownedPilot.wetfeet = Wetfeet or false
DownedPilot.BeaconName = BeaconName
-- Add Pilot -- Add Pilot
local PilotTable = self.downedPilots local PilotTable = self.downedPilots
@@ -737,7 +757,6 @@ function CSAR:_SpawnPilotInField(country,point,frequency,wetfeet)
:NewWithAlias(template,alias) :NewWithAlias(template,alias)
:InitCoalition(coalition) :InitCoalition(coalition)
:InitCountry(country) :InitCountry(country)
--:InitAIOnOff(pilotcacontrol)
:InitDelayOff() :InitDelayOff()
:SpawnFromCoordinate(point) :SpawnFromCoordinate(point)
@@ -819,8 +838,18 @@ function CSAR:_AddCsar(_coalition , _country, _point, _typeName, _unitName, _pla
end end
end end
local BeaconName
if _playerName then
BeaconName = _unitName..math.random(1,10000)
elseif _unitName then
BeaconName = _playerName..math.random(1,10000)
else
BeaconName = "Ghost-1-1"..math.random(1,10000)
end
if (_freq and _freq ~= 0) then --shagrat only add beacon if _freq is NOT 0 if (_freq and _freq ~= 0) then --shagrat only add beacon if _freq is NOT 0
self:_AddBeaconToGroup(_spawnedGroup, _freq) self:_AddBeaconToGroup(_spawnedGroup, _freq, BeaconName)
end end
self:_AddSpecialOptions(_spawnedGroup) self:_AddSpecialOptions(_spawnedGroup)
@@ -845,7 +874,7 @@ function CSAR:_AddCsar(_coalition , _country, _point, _typeName, _unitName, _pla
local _GroupName = _spawnedGroup:GetName() or _alias local _GroupName = _spawnedGroup:GetName() or _alias
self:_CreateDownedPilotTrack(_spawnedGroup,_GroupName,_coalition,_unitName,_text,_typeName,_freq,_playerName,wetfeet) self:_CreateDownedPilotTrack(_spawnedGroup,_GroupName,_coalition,_unitName,_text,_typeName,_freq,_playerName,wetfeet,BeaconName)
self:_InitSARForPilot(_spawnedGroup, _unitName, _freq, noMessage, _playerName) --shagrat use unitName to have the aircraft callsign / descriptive "name" etc. self:_InitSARForPilot(_spawnedGroup, _unitName, _freq, noMessage, _playerName) --shagrat use unitName to have the aircraft callsign / descriptive "name" etc.
@@ -963,7 +992,6 @@ end
-- @param Core.Point#COORDINATE Point -- @param Core.Point#COORDINATE Point
-- @param #number Coalition Coalition. -- @param #number Coalition Coalition.
-- @param #string Description (optional) Description. -- @param #string Description (optional) Description.
-- @param #boolean addBeacon (optional) yes or no.
-- @param #boolean Nomessage (optional) If true, don\'t send a message to SAR. -- @param #boolean Nomessage (optional) If true, don\'t send a message to SAR.
-- @param #string Unitname (optional) Name of the lost unit. -- @param #string Unitname (optional) Name of the lost unit.
-- @param #string Typename (optional) Type of plane. -- @param #string Typename (optional) Type of plane.
@@ -1793,9 +1821,6 @@ function CSAR:_DisplayMessageToSAR(_unit, _text, _time, _clear, _speak, _overrid
end end
_text = string.gsub(_text,"km"," kilometer") _text = string.gsub(_text,"km"," kilometer")
_text = string.gsub(_text,"nm"," nautical miles") _text = string.gsub(_text,"nm"," nautical miles")
--self.msrs:SetVoice(self.SRSVoice)
--self.SRSQueue:NewTransmission(_text,nil,self.msrs,nil,1)
--self:I("Voice = "..self.SRSVoice)
self.SRSQueue:NewTransmission(_text,duration,self.msrs,tstart,2,subgroups,subtitle,subduration,self.SRSchannel,self.SRSModulation,gender,culture,self.SRSVoice,volume,label,coord) self.SRSQueue:NewTransmission(_text,duration,self.msrs,tstart,2,subgroups,subtitle,subduration,self.SRSchannel,self.SRSModulation,gender,culture,self.SRSVoice,volume,label,coord)
end end
return self return self
@@ -1856,7 +1881,7 @@ function CSAR:_DisplayActiveSAR(_unitName)
else else
distancetext = string.format("%.1fkm", _distance/1000.0) distancetext = string.format("%.1fkm", _distance/1000.0)
end end
if _value.frequency == 0 then--shagrat insert CASEVAC without Frequency if _value.frequency == 0 or self.CreateRadioBeacons == false then--shagrat insert CASEVAC without Frequency
table.insert(_csarList, { dist = _distance, msg = string.format("%s at %s - %s ", _value.desc, _coordinatesText, distancetext) }) table.insert(_csarList, { dist = _distance, msg = string.format("%s at %s - %s ", _value.desc, _coordinatesText, distancetext) })
else else
table.insert(_csarList, { dist = _distance, msg = string.format("%s at %s - %.2f KHz ADF - %s ", _value.desc, _coordinatesText, _value.frequency / 1000, distancetext) }) table.insert(_csarList, { dist = _distance, msg = string.format("%s at %s - %.2f KHz ADF - %s ", _value.desc, _coordinatesText, _value.frequency / 1000, distancetext) })
@@ -1941,7 +1966,7 @@ function CSAR:_SignalFlare(_unitName)
else else
_distance = string.format("%.1fkm",_closest.distance/1000) _distance = string.format("%.1fkm",_closest.distance/1000)
end end
local _msg = string.format("%s - Popping signal flare at your %s o\'clock. Distance %s", self:_GetCustomCallSign(_unitName), _clockDir, _distance) local _msg = string.format("%s - Firing signal flare at your %s o\'clock. Distance %s", self:_GetCustomCallSign(_unitName), _clockDir, _distance)
self:_DisplayMessageToSAR(_heli, _msg, self.messageTime, false, true, true) self:_DisplayMessageToSAR(_heli, _msg, self.messageTime, false, true, true)
local _coord = _closest.pilot:GetCoordinate() local _coord = _closest.pilot:GetCoordinate()
@@ -1975,7 +2000,7 @@ function CSAR:_DisplayToAllSAR(_message, _side, _messagetime,ToSRS,ToScreen)
if self.msrs:GetProvider() == MSRS.Provider.WINDOWS then if self.msrs:GetProvider() == MSRS.Provider.WINDOWS then
voice = self.CSARVoiceMS or MSRS.Voices.Microsoft.Hedda voice = self.CSARVoiceMS or MSRS.Voices.Microsoft.Hedda
end end
self:F("Voice = "..voice) --self:F("Voice = "..voice)
self.SRSQueue:NewTransmission(_message,duration,self.msrs,tstart,2,subgroups,subtitle,subduration,self.SRSchannel,self.SRSModulation,gender,culture,voice,volume,label,self.coordinate) self.SRSQueue:NewTransmission(_message,duration,self.msrs,tstart,2,subgroups,subtitle,subduration,self.SRSchannel,self.SRSModulation,gender,culture,voice,volume,label,self.coordinate)
end end
if ToScreen == true or ToScreen == nil then if ToScreen == true or ToScreen == nil then
@@ -1989,6 +2014,41 @@ function CSAR:_DisplayToAllSAR(_message, _side, _messagetime,ToSRS,ToScreen)
return self return self
end end
---(Internal) Request IR Strobe at closest downed pilot.
--@param #CSAR self
--@param #string _unitName Name of the helicopter
function CSAR:_ReqIRStrobe( _unitName )
self:T(self.lid .. " _ReqIRStrobe")
local _heli = self:_GetSARHeli(_unitName)
if _heli == nil then
return
end
local smokedist = 8000
if smokedist < self.approachdist_far then smokedist = self.approachdist_far end
local _closest = self:_GetClosestDownedPilot(_heli)
if _closest ~= nil and _closest.pilot ~= nil and _closest.distance > 0 and _closest.distance < smokedist then
local _clockDir = self:_GetClockDirection(_heli, _closest.pilot)
local _distance = string.format("%.1fkm",_closest.distance/1000)
if _SETTINGS:IsImperial() then
_distance = string.format("%.1fnm",UTILS.MetersToNM(_closest.distance))
else
_distance = string.format("%.1fkm",_closest.distance/1000)
end
local _msg = string.format("%s - IR Strobe active at your %s o\'clock. Distance %s", self:_GetCustomCallSign(_unitName), _clockDir, _distance)
self:_DisplayMessageToSAR(_heli, _msg, self.messageTime, false, true, true)
_closest.pilot:NewIRMarker(true,self.IRStrobeRuntime or 300)
else
local _distance = string.format("%.1fkm",smokedist/1000)
if _SETTINGS:IsImperial() then
_distance = string.format("%.1fnm",UTILS.MetersToNM(smokedist))
else
_distance = string.format("%.1fkm",smokedist/1000)
end
self:_DisplayMessageToSAR(_heli, string.format("No Pilots within %s",_distance), self.messageTime, false, false, true)
end
return self
end
---(Internal) Request smoke at closest downed pilot. ---(Internal) Request smoke at closest downed pilot.
--@param #CSAR self --@param #CSAR self
--@param #string _unitName Name of the helicopter --@param #string _unitName Name of the helicopter
@@ -2140,7 +2200,12 @@ function CSAR:_AddMedevacMenuItem()
local _rootMenu1 = MENU_GROUP_COMMAND:New(_group,"List Active CSAR",_rootPath, self._DisplayActiveSAR,self,_unitName) local _rootMenu1 = MENU_GROUP_COMMAND:New(_group,"List Active CSAR",_rootPath, self._DisplayActiveSAR,self,_unitName)
local _rootMenu2 = MENU_GROUP_COMMAND:New(_group,"Check Onboard",_rootPath, self._CheckOnboard,self,_unitName) local _rootMenu2 = MENU_GROUP_COMMAND:New(_group,"Check Onboard",_rootPath, self._CheckOnboard,self,_unitName)
local _rootMenu3 = MENU_GROUP_COMMAND:New(_group,"Request Signal Flare",_rootPath, self._SignalFlare,self,_unitName) local _rootMenu3 = MENU_GROUP_COMMAND:New(_group,"Request Signal Flare",_rootPath, self._SignalFlare,self,_unitName)
local _rootMenu4 = MENU_GROUP_COMMAND:New(_group,"Request Smoke",_rootPath, self._Reqsmoke,self,_unitName):Refresh() local _rootMenu4 = MENU_GROUP_COMMAND:New(_group,"Request Smoke",_rootPath, self._Reqsmoke,self,_unitName)
if self.AllowIRStrobe then
local _rootMenu5 = MENU_GROUP_COMMAND:New(_group,"Request IR Strobe",_rootPath, self._ReqIRStrobe,self,_unitName):Refresh()
else
_rootMenu4:Refresh()
end
end end
end end
end end
@@ -2231,9 +2296,13 @@ end
-- @param #CSAR self -- @param #CSAR self
-- @param Wrapper.Group#GROUP _group Group #GROUP object. -- @param Wrapper.Group#GROUP _group Group #GROUP object.
-- @param #number _freq Frequency to use -- @param #number _freq Frequency to use
function CSAR:_AddBeaconToGroup(_group, _freq) -- @param #string _name Beacon Name to use
-- @return #CSAR self
function CSAR:_AddBeaconToGroup(_group, _freq, _name)
self:T(self.lid .. " _AddBeaconToGroup") self:T(self.lid .. " _AddBeaconToGroup")
if self.CreateRadioBeacons == false then return end
local _group = _group local _group = _group
if _group == nil then if _group == nil then
--return frequency to pool of available --return frequency to pool of available
for _i, _current in ipairs(self.UsedVHFFrequencies) do for _i, _current in ipairs(self.UsedVHFFrequencies) do
@@ -2253,17 +2322,19 @@ function CSAR:_AddBeaconToGroup(_group, _freq)
local name = _radioUnit:GetName() local name = _radioUnit:GetName()
local Sound = "l10n/DEFAULT/"..self.radioSound local Sound = "l10n/DEFAULT/"..self.radioSound
local vec3 = _radioUnit:GetVec3() or _radioUnit:GetPositionVec3() or {x=0,y=0,z=0} local vec3 = _radioUnit:GetVec3() or _radioUnit:GetPositionVec3() or {x=0,y=0,z=0}
trigger.action.radioTransmission(Sound, vec3, 0, false, Frequency, self.ADFRadioPwr or 1000,name..math.random(1,10000)) -- Beacon in MP only runs for exactly 30secs straight trigger.action.radioTransmission(Sound, vec3, 0, false, Frequency, self.ADFRadioPwr or 1000,_name) -- Beacon in MP only runs for exactly 30secs straight
end end
end end
return self return self
end end
--- (Internal) Helper function to (re-)add beacon to downed pilot. --- (Internal) Helper function to (re-)add beacon to downed pilot.
-- @param #CSAR self -- @param #CSAR self
-- @param #table _args Arguments -- @return #CSAR self
function CSAR:_RefreshRadioBeacons() function CSAR:_RefreshRadioBeacons()
self:T(self.lid .. " _RefreshRadioBeacons") self:T(self.lid .. " _RefreshRadioBeacons")
if self.CreateRadioBeacons == false then return end
if self:_CountActiveDownedPilots() > 0 then if self:_CountActiveDownedPilots() > 0 then
local PilotTable = self.downedPilots local PilotTable = self.downedPilots
for _,_pilot in pairs (PilotTable) do for _,_pilot in pairs (PilotTable) do
@@ -2271,8 +2342,10 @@ function CSAR:_RefreshRadioBeacons()
local pilot = _pilot -- #CSAR.DownedPilot local pilot = _pilot -- #CSAR.DownedPilot
local group = pilot.group local group = pilot.group
local frequency = pilot.frequency or 0 -- thanks to @Thrud local frequency = pilot.frequency or 0 -- thanks to @Thrud
local bname = pilot.BeaconName or pilot.name..math.random(1,100000)
trigger.action.stopRadioTransmission(bname)
if group and group:IsAlive() and frequency > 0 then if group and group:IsAlive() and frequency > 0 then
self:_AddBeaconToGroup(group,frequency) self:_AddBeaconToGroup(group,frequency,bname)
end end
end end
end end
@@ -2309,6 +2382,16 @@ function CSAR:_ReachedPilotLimit()
end end
end end
--- User - Function to add onw SET_GROUP Set-up for pilot filtering and assignment.
-- Needs to be set before starting the CSAR instance.
-- @param #CSAR self
-- @param Core.Set#SET_GROUP Set The SET_GROUP object created by the mission designer/user to represent the CSAR pilot groups.
-- @return #CSAR self
function CSAR:SetOwnSetPilotGroups(Set)
self.UserSetGroup = Set
return self
end
------------------------------ ------------------------------
--- FSM internal Functions --- --- FSM internal Functions ---
------------------------------ ------------------------------
@@ -2330,7 +2413,9 @@ function CSAR:onafterStart(From, Event, To)
self:HandleEvent(EVENTS.PlayerEnterUnit, self._EventHandler) self:HandleEvent(EVENTS.PlayerEnterUnit, self._EventHandler)
self:HandleEvent(EVENTS.PilotDead, self._EventHandler) self:HandleEvent(EVENTS.PilotDead, self._EventHandler)
if self.allowbronco then if self.UserSetGroup then
self.allheligroupset = self.UserSetGroup
elseif self.allowbronco then
local prefixes = self.csarPrefix or {} local prefixes = self.csarPrefix or {}
self.allheligroupset = SET_GROUP:New():FilterCoalitions(self.coalitiontxt):FilterPrefixes(prefixes):FilterStart() self.allheligroupset = SET_GROUP:New():FilterCoalitions(self.coalitiontxt):FilterPrefixes(prefixes):FilterStart()
elseif self.useprefix then elseif self.useprefix then
@@ -2339,7 +2424,9 @@ function CSAR:onafterStart(From, Event, To)
else else
self.allheligroupset = SET_GROUP:New():FilterCoalitions(self.coalitiontxt):FilterCategoryHelicopter():FilterStart() self.allheligroupset = SET_GROUP:New():FilterCoalitions(self.coalitiontxt):FilterCategoryHelicopter():FilterStart()
end end
self.mash = SET_GROUP:New():FilterCoalitions(self.coalitiontxt):FilterPrefixes(self.mashprefix):FilterStart() -- currently only GROUP objects, maybe support STATICs also? self.mash = SET_GROUP:New():FilterCoalitions(self.coalitiontxt):FilterPrefixes(self.mashprefix):FilterStart() -- currently only GROUP objects, maybe support STATICs also?
if not self.coordinate then if not self.coordinate then
local csarhq = self.mash:GetRandom() local csarhq = self.mash:GetRandom()
if csarhq then if csarhq then
File diff suppressed because it is too large Load Diff
+21 -5
View File
@@ -34,6 +34,7 @@
-- @field Ops.Commander#COMMANDER commander Commander of assigned legions. -- @field Ops.Commander#COMMANDER commander Commander of assigned legions.
-- @field #number Nsuccess Number of successful missions. -- @field #number Nsuccess Number of successful missions.
-- @field #number Nfailure Number of failed mission. -- @field #number Nfailure Number of failed mission.
-- @field #table assetNumbers Asset numbers. Each entry is a table of data type `#CHIEF.AssetNumber`.
-- @extends Ops.Intel#INTEL -- @extends Ops.Intel#INTEL
--- *In preparing for battle I have always found that plans are useless, but planning is indispensable* -- Dwight D Eisenhower --- *In preparing for battle I have always found that plans are useless, but planning is indispensable* -- Dwight D Eisenhower
@@ -331,7 +332,7 @@ CHIEF.Strategy = {
--- CHIEF class version. --- CHIEF class version.
-- @field #string version -- @field #string version
CHIEF.version="0.6.0" CHIEF.version="0.6.1"
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO list -- TODO list
@@ -1284,8 +1285,10 @@ end
-- --
-- Empty: -- Empty:
-- --
-- * `AUFTRAG.Type.ONGURAD` with Nmin=1 and Nmax=1 assets, Attribute=`GROUP.Attribute.GROUND_TANK`. -- * `AUFTRAG.Type.ONGURAD` with Nmin=0 and Nmax=1 assets, Attribute=`GROUP.Attribute.GROUND_TANK`.
-- * `AUFTRAG.Type.ONGURAD` with Nmin=0 and Nmax=1 assets, Attribute=`GROUP.Attribute.GROUND_IFV`.
-- * `AUFTRAG.Type.ONGUARD` with Nmin=1 and Nmax=3 assets, Attribute=`GROUP.Attribute.GROUND_INFANTRY`. -- * `AUFTRAG.Type.ONGUARD` with Nmin=1 and Nmax=3 assets, Attribute=`GROUP.Attribute.GROUND_INFANTRY`.
-- * `AUFTRAG.Type.OPSTRANSPORT` with Nmin=0 and Nmax=1 assets, Attribute=`GROUP.Attribute.AIR_TRANSPORTHELO` or `GROUP.Attribute.GROUND_APC`. This asset is used to transport the infantry groups.
-- --
-- Resources can be created with the @{#CHIEF.CreateResource} and @{#CHIEF.AddToResource} functions. -- Resources can be created with the @{#CHIEF.CreateResource} and @{#CHIEF.AddToResource} functions.
-- --
@@ -3033,10 +3036,13 @@ function CHIEF:RecruitAssetsForZone(StratZone, Resource)
end end
-- Recruite infantry assets. -- Recruite infantry assets.
self:T(self.lid..string.format("Recruiting assets for zone %s", StratZone.opszone:GetName()))
self:T(self.lid.."Missiontype="..MissionType) self:T(self.lid.."Missiontype="..MissionType)
self:T({categories=Categories}) self:T({categories=Categories})
self:T({attributes=Attributes}) self:T({attributes=Attributes})
self:T({properties=Properties}) self:T({properties=Properties})
local recruited, assets, legions=LEGION.RecruitCohortAssets(Cohorts, MissionType, nil, NassetsMin, NassetsMax, TargetVec2, nil, RangeMax, nil, nil, nil, nil, Categories, Attributes, Properties) local recruited, assets, legions=LEGION.RecruitCohortAssets(Cohorts, MissionType, nil, NassetsMin, NassetsMax, TargetVec2, nil, RangeMax, nil, nil, nil, nil, Categories, Attributes, Properties)
if recruited then if recruited then
@@ -3052,9 +3058,12 @@ function CHIEF:RecruitAssetsForZone(StratZone, Resource)
local TargetCoord = TargetZone:GetCoordinate() local TargetCoord = TargetZone:GetCoordinate()
-- First check if we need a transportation. -- First check if we need a transportation.
local transport=nil local transport=nil --Ops.OpsTransport#OPSTRANSPORT
local Ntransports=0
if Resource.carrierNmin and Resource.carrierNmax and Resource.carrierNmax>0 then if Resource.carrierNmin and Resource.carrierNmax and Resource.carrierNmax>0 then
self:T(self.lid..string.format("Recruiting carrier assets: Nmin=%s, Nmax=%s", tostring(Resource.carrierNmin), tostring(Resource.carrierNmax)))
-- Filter only those assets that shall be transported. -- Filter only those assets that shall be transported.
local cargoassets=CHIEF._FilterAssets(assets, Resource.Categories, Resource.Attributes, Resource.Properties) local cargoassets=CHIEF._FilterAssets(assets, Resource.Categories, Resource.Attributes, Resource.Properties)
@@ -3064,6 +3073,10 @@ function CHIEF:RecruitAssetsForZone(StratZone, Resource)
recruited, transport=LEGION.AssignAssetsForTransport(self.commander, self.commander.legions, cargoassets, recruited, transport=LEGION.AssignAssetsForTransport(self.commander, self.commander.legions, cargoassets,
Resource.carrierNmin, Resource.carrierNmax, TargetZone, nil, Resource.carrierCategories, Resource.carrierAttributes, Resource.carrierProperties) Resource.carrierNmin, Resource.carrierNmax, TargetZone, nil, Resource.carrierCategories, Resource.carrierAttributes, Resource.carrierProperties)
Ntransports=transport~=nil and #transport.assets or 0
self:T(self.lid..string.format("Recruited %d transport carrier assets success=%s", Ntransports, tostring(recruited)))
end end
end end
@@ -3076,7 +3089,7 @@ function CHIEF:RecruitAssetsForZone(StratZone, Resource)
return false return false
end end
-- Debug messgage. -- Debug message
self:T2(self.lid..string.format("Recruited %d assets for mission %s", #assets, MissionType)) self:T2(self.lid..string.format("Recruited %d assets for mission %s", #assets, MissionType))
@@ -3224,10 +3237,13 @@ function CHIEF:RecruitAssetsForZone(StratZone, Resource)
-- Attach mission to ops zone. -- Attach mission to ops zone.
StratZone.opszone:_AddMission(self.coalition, MissionType, mission) StratZone.opszone:_AddMission(self.coalition, MissionType, mission)
mission:SetName(string.format("Stratzone %s-%d", StratZone.opszone:GetName(), mission.auftragsnummer))
-- Attach mission to resource. -- Attach mission to resource.
Resource.mission=mission Resource.mission=mission
if transport then -- Check if transport assets could be allocated. If carrier Nmin=0 and 0 assets could be allocated, transport would still be created but not usefull obviously
if transport and Ntransports>0 then
-- Attach OPS transport to mission. -- Attach OPS transport to mission.
mission.opstransport=transport mission.opstransport=transport
-- Set ops zone to transport. -- Set ops zone to transport.
File diff suppressed because it is too large Load Diff
+10
View File
@@ -2619,6 +2619,8 @@ function LEGION._CohortCan(Cohort, MissionType, Categories, Attributes, Properti
local RangeMax = RangeMax or 0 local RangeMax = RangeMax or 0
local InRange=(RangeMax and math.max(RangeMax, Rmax) or Rmax) >= TargetDistance local InRange=(RangeMax and math.max(RangeMax, Rmax) or Rmax) >= TargetDistance
--env.info(string.format("Range TargetDist=%.1f Rmax=%.1f RangeMax=%.1f InRange=%s", TargetDistance, Rmax, RangeMax, tostring(InRange)))
return InRange return InRange
end end
@@ -2785,6 +2787,8 @@ function LEGION.RecruitCohortAssets(Cohorts, MissionTypeRecruit, MissionTypeOpt,
-- Check if cohort can do the mission. -- Check if cohort can do the mission.
local can=LEGION._CohortCan(cohort, MissionTypeRecruit, Categories, Attributes, Properties, WeaponTypes, TargetVec2, RangeMax, RefuelSystem, CargoWeight, MaxWeight) local can=LEGION._CohortCan(cohort, MissionTypeRecruit, Categories, Attributes, Properties, WeaponTypes, TargetVec2, RangeMax, RefuelSystem, CargoWeight, MaxWeight)
--env.info(string.format("RecruitCohortAssets %s Cohort=%s can=%s", MissionTypeRecruit, cohort:GetName(), tostring(can)))
-- Check OnDuty, capable, in range and refueling type (if TANKER). -- Check OnDuty, capable, in range and refueling type (if TANKER).
if can then if can then
@@ -2800,6 +2804,12 @@ function LEGION.RecruitCohortAssets(Cohorts, MissionTypeRecruit, MissionTypeOpt,
end end
-- Break if no assets could be found
if #Assets==0 then
--env.info(string.format("LEGION.RecruitCohortAssets: No assets could be recruited for mission type %s [Nmin=%s, Nmax=%s]", MissionTypeRecruit, tostring(NreqMin), tostring(NreqMax)))
return false, {}, {}
end
-- Now we have a long list with assets. -- Now we have a long list with assets.
LEGION._OptimizeAssetSelection(Assets, MissionTypeOpt, TargetVec2, false, TotalWeight) LEGION._OptimizeAssetSelection(Assets, MissionTypeOpt, TargetVec2, false, TotalWeight)
+5 -6
View File
@@ -271,11 +271,11 @@ MSRS.Voices = {
["David"] = "Microsoft David Desktop", -- en-US ["David"] = "Microsoft David Desktop", -- en-US
["Zira"] = "Microsoft Zira Desktop", -- en-US ["Zira"] = "Microsoft Zira Desktop", -- en-US
["Hortense"] = "Microsoft Hortense Desktop", --fr-FR ["Hortense"] = "Microsoft Hortense Desktop", --fr-FR
["de-DE-Hedda"] = "Microsoft Hedda Desktop", -- de-DE ["de_DE_Hedda"] = "Microsoft Hedda Desktop", -- de-DE
["en-GB-Hazel"] = "Microsoft Hazel Desktop", -- en-GB ["en_GB_Hazel"] = "Microsoft Hazel Desktop", -- en-GB
["en-US-David"] = "Microsoft David Desktop", -- en-US ["en_US_David"] = "Microsoft David Desktop", -- en-US
["en-US-Zira"] = "Microsoft Zira Desktop", -- en-US ["en_US_Zira"] = "Microsoft Zira Desktop", -- en-US
["fr-FR-Hortense"] = "Microsoft Hortense Desktop", --fr-FR ["fr_FR_Hortense"] = "Microsoft Hortense Desktop", --fr-FR
}, },
MicrosoftGRPC = { -- en-US/GB voices only as of Jan 2024, working ones if using gRPC and MS, if voice packs are installed MicrosoftGRPC = { -- en-US/GB voices only as of Jan 2024, working ones if using gRPC and MS, if voice packs are installed
--["Hedda"] = "Hedda", -- de-DE --["Hedda"] = "Hedda", -- de-DE
@@ -305,7 +305,6 @@ MSRS.Voices = {
["en_IN_Ravi"] = "Ravi", --en-IN ["en_IN_Ravi"] = "Ravi", --en-IN
["en_IN_Heera"] = "Heera", --en-IN ["en_IN_Heera"] = "Heera", --en-IN
["en_IR_Sean"] = "Sean", --en-IR ["en_IR_Sean"] = "Sean", --en-IR
--]]
}, },
Google = { Google = {
Standard = { Standard = {
@@ -580,6 +580,18 @@ ENUMS.Link16Power = {
--- Enums for the STORAGE class for stores - which need to be in "" --- Enums for the STORAGE class for stores - which need to be in ""
-- @type ENUMS.Storage -- @type ENUMS.Storage
-- @type ENUMS.Storage.weapons -- @type ENUMS.Storage.weapons
-- @type ENUMS.Storage.weapons.missiles
-- @type ENUMS.Storage.weapons.bombs
-- @type ENUMS.Storage.weapons.nurs
-- @type ENUMS.Storage.weapons.containers
-- @type ENUMS.Storage.weapons.droptanks
-- @type ENUMS.Storage.weapons.adapters
-- @type ENUMS.Storage.weapons.torpedoes
-- @type ENUMS.Storage.weapons.Gazelle
-- @type ENUMS.Storage.weapons.CH47
-- @type ENUMS.Storage.weapons.OH58
-- @type ENUMS.Storage.weapons.UH1H
-- @type ENUMS.Storage.weapons.AH64D
ENUMS.Storage = { ENUMS.Storage = {
weapons = { weapons = {
missiles = {}, -- Missiles missiles = {}, -- Missiles
@@ -589,6 +601,11 @@ ENUMS.Storage = {
droptanks = {}, -- Droptanks droptanks = {}, -- Droptanks
adapters = {}, -- Adapter adapters = {}, -- Adapter
torpedoes = {}, -- Torpedoes torpedoes = {}, -- Torpedoes
Gazelle = {}, -- Gazelle specifics
CH47 = {}, -- Chinook specifics
OH58 = {}, -- Kiowa specifics
UH1H = {}, -- Huey specifics
AH64D = {}, -- Huey specifics
} }
} }
@@ -1149,3 +1166,74 @@ ENUMS.Storage.weapons.bombs.AGM_62 = "weapons.bombs.AGM_62"
ENUMS.Storage.weapons.containers.US_M10_SMOKE_TANK_WHITE = "weapons.containers.{US_M10_SMOKE_TANK_WHITE}" ENUMS.Storage.weapons.containers.US_M10_SMOKE_TANK_WHITE = "weapons.containers.{US_M10_SMOKE_TANK_WHITE}"
ENUMS.Storage.weapons.missiles.MICA_T = "weapons.missiles.MICA_T" ENUMS.Storage.weapons.missiles.MICA_T = "weapons.missiles.MICA_T"
ENUMS.Storage.weapons.containers.HVAR_rocket = "weapons.containers.HVAR_rocket" ENUMS.Storage.weapons.containers.HVAR_rocket = "weapons.containers.HVAR_rocket"
-- Gazelle
ENUMS.Storage.weapons.Gazelle.HMP400_100RDS = {4,15,46,1771}
ENUMS.Storage.weapons.Gazelle.HMP400_200RDS = {4,15,46,1770}
ENUMS.Storage.weapons.Gazelle.HMP400_400RDS = {4,15,46,1769}
ENUMS.Storage.weapons.Gazelle.GIAT_M261_AP = {4,15,46,1768}
ENUMS.Storage.weapons.Gazelle.GIAT_M261_SAPHEI = {4,15,46,1767}
ENUMS.Storage.weapons.Gazelle.GIAT_M261_HE = {4,15,46,1766}
ENUMS.Storage.weapons.Gazelle.GIAT_M261_HEAP = {4,15,46,1765}
ENUMS.Storage.weapons.Gazelle.GIAT_M261_APHE = {4,15,46,1764}
ENUMS.Storage.weapons.Gazelle.GAZELLE_IR_DEFLECTOR = {4,15,47,680}
ENUMS.Storage.weapons.Gazelle.GAZELLE_FAS_SANDFILTER = {4,15,47,679}
-- Chinook
ENUMS.Storage.weapons.CH47.CH47_PORT_M60D = {4,15,46,2476}
ENUMS.Storage.weapons.CH47.CH47_STBD_M60D = {4,15,46,2477}
ENUMS.Storage.weapons.CH47.CH47_AFT_M60D = {4,15,46,2478}
ENUMS.Storage.weapons.CH47.CH47_PORT_M134D = {4,15,46,2482}
ENUMS.Storage.weapons.CH47.CH47_STBD_M134D = {4,15,46,2483}
ENUMS.Storage.weapons.CH47.CH47_AFT_M3M = {4,15,46,2484}
ENUMS.Storage.weapons.CH47.CH47_PORT_M240H = {4,15,46,2479}
ENUMS.Storage.weapons.CH47.CH47_STBD_M240H = {4,15,46,2480}
ENUMS.Storage.weapons.CH47.CH47_AFT_M240H = {4,15,46,2481}
-- Huey
ENUMS.Storage.weapons.UH1H.M134_MiniGun_Right = {4,15,46,161}
ENUMS.Storage.weapons.UH1H.M134_MiniGun_Left = {4,15,46,160}
ENUMS.Storage.weapons.UH1H.M134_MiniGun_Right_Door = {4,15,46,175}
ENUMS.Storage.weapons.UH1H.M60_MG_Right_Door = {4,15,46,177}
ENUMS.Storage.weapons.UH1H.M134_MiniGun_Left_Door = {4,15,46,174}
ENUMS.Storage.weapons.UH1H.M60_MG_Left_Door = {4,15,46,176}
-- Kiowa
ENUMS.Storage.weapons.OH58.FIM92 = {4,4,7,446}
ENUMS.Storage.weapons.OH58.MG_M3P100 = {4,15,46,2578}
ENUMS.Storage.weapons.OH58.MG_M3P200 = {4,15,46,2577}
ENUMS.Storage.weapons.OH58.MG_M3P300 = {4,15,46,2576}
ENUMS.Storage.weapons.OH58.MG_M3P400 = {4,15,46,2575}
ENUMS.Storage.weapons.OH58.MG_M3P500 = {4,15,46,2574}
ENUMS.Storage.weapons.OH58.Smk_Grenade_Blue = {4,5,9,484}
ENUMS.Storage.weapons.OH58.Smk_Grenade_Green = {4,5,9,485}
ENUMS.Storage.weapons.OH58.Smk_Grenade_Red = {4,5,9,483}
ENUMS.Storage.weapons.OH58.Smk_Grenade_Violet = {4,5,9,486}
ENUMS.Storage.weapons.OH58.Smk_Grenade_White = {4,5,9,488}
ENUMS.Storage.weapons.OH58.Smk_Grenade_Yellow = {4,5,9,487}
-- Apache
ENUMS.Storage.weapons.AH64D.AN_APG78 = {4,15,44,2138}
ENUMS.Storage.weapons.AH64D.Internal_Aux_FuelTank = {1,3,43,1700}
---
-- @type ENUMS.FARPType
-- @field #string FARP
-- @field #string INVISIBLE
-- @field #string HELIPADSINGLE
-- @field #string PADSINGLE
ENUMS.FARPType = {
FARP = "FARP",
INVISIBLE = "INVISIBLE",
HELIPADSINGLE = "HELIPADSINGLE",
PADSINGLE = "PADSINGLE",
}
---
-- @type ENUMS.FARPObjectTypeNamesAndShape
-- @field #string FARP
-- @field #string INVISIBLE
-- @field #string HELIPADSINGLE
-- @field #string PADSINGLE
ENUMS.FARPObjectTypeNamesAndShape ={
[ENUMS.FARPType.FARP] = { TypeName="FARP", ShapeName="FARPS"},
[ENUMS.FARPType.INVISIBLE] = { TypeName="Invisible FARP", ShapeName="invisiblefarp"},
[ENUMS.FARPType.HELIPADSINGLE] = { TypeName="SINGLE_HELIPAD", ShapeName="FARP"},
[ENUMS.FARPType.PADSINGLE] = { TypeName="FARP_SINGLE_01", ShapeName="FARP_SINGLE_01"},
}
+120 -11
View File
@@ -1221,7 +1221,7 @@ function UTILS.SecondsToClock(seconds, short)
end end
-- Seconds -- Seconds
local seconds = tonumber(seconds) local seconds = tonumber(seconds) or 0
-- Seconds of this day. -- Seconds of this day.
local _seconds=seconds%(60*60*24) local _seconds=seconds%(60*60*24)
@@ -2122,9 +2122,9 @@ function UTILS.GetSunRiseAndSet(DayOfYear, Latitude, Longitude, Rising, Tlocal)
local cosH = (cos(zenith) - (sinDec * sin(latitude))) / (cosDec * cos(latitude)) local cosH = (cos(zenith) - (sinDec * sin(latitude))) / (cosDec * cos(latitude))
if rising and cosH > 1 then if rising and cosH > 1 then
return "N/R" -- The sun never rises on this location on the specified date return "N/S" -- The sun never rises on this location on the specified date
elseif cosH < -1 then elseif cosH < -1 then
return "N/S" -- The sun never sets on this location on the specified date return "N/R" -- The sun never sets on this location on the specified date
end end
-- Finish calculating H and convert into hours -- Finish calculating H and convert into hours
@@ -2353,14 +2353,16 @@ function UTILS.GenerateVHFrequencies()
-- known and sorted map-wise NDBs in kHz -- known and sorted map-wise NDBs in kHz
local _skipFrequencies = { local _skipFrequencies = {
214,274,291.5,295,297.5, 214,243,264,273,274,288,291.5,295,297.5,
300.5,304,305,307,309.5,311,312,312.5,316, 300.5,304,305,307,309.5,310,311,312,312.5,316,317,
320,324,328,329,330,332,336,337, 320,323,324,325,326,328,329,330,332,335,336,337,
342,343,348,351,352,353,358, 340,342,343,346,348,351,352,353,358,
363,365,368,372.5,374, 360,363,364,365,368,372.5,373,374,
380,381,384,385,389,395,396, 380,381,384,385,387,389,391,395,396,399,
414,420,430,432,435,440,450,455,462,470,485, 403,404,410,412,414,418,420,423,
507,515,520,525,528,540,550,560,570,577,580, 430,432,435,440,445,
450,455,462,470,485,490,
507,515,520,525,528,540,550,560,563,570,577,580,595,
602,625,641,662,670,680,682,690, 602,625,641,662,670,680,682,690,
705,720,722,730,735,740,745,750,770,795, 705,720,722,730,735,740,745,750,770,795,
822,830,862,866, 822,830,862,866,
@@ -4090,3 +4092,110 @@ function UTILS.LCGRandom()
UTILS.lcg.seed = (UTILS.lcg.a * UTILS.lcg.seed + UTILS.lcg.c) % UTILS.lcg.m UTILS.lcg.seed = (UTILS.lcg.a * UTILS.lcg.seed + UTILS.lcg.c) % UTILS.lcg.m
return UTILS.lcg.seed / UTILS.lcg.m return UTILS.lcg.seed / UTILS.lcg.m
end end
--- Spawns a new FARP of a defined type and coalition and functional statics (fuel depot, ammo storage, tent, windsock) around that FARP to make it operational.
-- Adds vehicles from template if given. Fills the FARP warehouse with liquids and known materiels.
-- References: [DCS Forum Topic](https://forum.dcs.world/topic/282989-farp-equipment-to-run-it)
-- @param #string Name Name of this FARP installation. Must be unique.
-- @param Core.Point#COORDINATE Coordinate Where to spawn the FARP.
-- @param #string FARPType Type of FARP, can be one of the known types ENUMS.FARPType.FARP, ENUMS.FARPType.INVISIBLE, ENUMS.FARPType.HELIPADSINGLE, ENUMS.FARPType.PADSINGLE. Defaults to ENUMS.FARPType.FARP.
-- @param #number Coalition Coalition of this FARP, i.e. coalition.side.BLUE or coalition.side.RED, defaults to coalition.side.BLUE.
-- @param #number Country Country of this FARP, defaults to country.id.USA (blue) or country.id.RUSSIA (red).
-- @param #number CallSign Callsign of the FARP ATC, defaults to CALLSIGN.FARP.Berlin.
-- @param #number Frequency Frequency of the FARP ATC Radio, defaults to 127.5 (MHz).
-- @param #number Modulation Modulation of the FARP ATC Radio, defaults to radio.modulation.AM.
-- @param #number ADF ADF Beacon (FM) Frequency in KHz, e.g. 428. If not nil, creates an VHF/FM ADF Beacon for this FARP. Requires a sound called "beacon.ogg" to be in the mission (trigger "sound to" ...)
-- @param #number SpawnRadius Radius of the FARP, i.e. where the FARP objects will be placed in meters, not more than 150m away. Defaults to 100.
-- @param #string VehicleTemplate, template name for additional vehicles. Can be nil for no additional vehicles.
-- @param #number Liquids Tons of fuel to be added initially to the FARP. Defaults to 10 (tons). Set to 0 for no fill.
-- @param #number Equipment Number of equipment items per known item to be added initially to the FARP. Defaults to 10 (items). Set to 0 for no fill.
-- @return #list<Wrapper.Static#STATIC> Table of spawned objects and vehicle object (if given).
-- @return #string ADFBeaconName Name of the ADF beacon, to be able to remove/stop it later.
function UTILS.SpawnFARPAndFunctionalStatics(Name,Coordinate,FARPType,Coalition,Country,CallSign,Frequency,Modulation,ADF,SpawnRadius,VehicleTemplate,Liquids,Equipment)
-- Set Defaults
local farplocation = Coordinate
local farptype = FARPType or ENUMS.FARPType.FARP
local Coalition = Coalition or coalition.side.BLUE
local callsign = CallSign or CALLSIGN.FARP.Berlin
local freq = Frequency or 127.5
local mod = Modulation or radio.modulation.AM
local radius = SpawnRadius or 100
if radius < 0 or radius > 150 then radius = 100 end
local liquids = Liquids or 10
liquids = liquids * 1000 -- tons to kg
local equip = Equipment or 10
local statictypes = ENUMS.FARPObjectTypeNamesAndShape[farptype] or {TypeName="FARP", ShapeName="FARPS"}
local STypeName = statictypes.TypeName
local SShapeName = statictypes.ShapeName
local Country = Country or (Coalition == coalition.side.BLUE and country.id.USA or country.id.RUSSIA)
local ReturnObjects = {}
-- Spawn FARP
local newfarp = SPAWNSTATIC:NewFromType(STypeName,"Heliports",Country) -- "Invisible FARP" "FARP"
newfarp:InitShape(SShapeName) -- "invisiblefarp" "FARPS"
newfarp:InitFARP(callsign,freq,mod)
local spawnedfarp = newfarp:SpawnFromCoordinate(farplocation,0,Name)
table.insert(ReturnObjects,spawnedfarp)
-- Spawn Objects
local FARPStaticObjectsNato = {
["FUEL"] = { TypeName = "FARP Fuel Depot", ShapeName = "GSM Rus", Category = "Fortifications"},
["AMMO"] = { TypeName = "FARP Ammo Dump Coating", ShapeName = "SetkaKP", Category = "Fortifications"},
["TENT"] = { TypeName = "FARP Tent", ShapeName = "PalatkaB", Category = "Fortifications"},
["WINDSOCK"] = { TypeName = "Windsock", ShapeName = "H-Windsock_RW", Category = "Fortifications"},
}
local farpobcount = 0
for _name,_object in pairs(FARPStaticObjectsNato) do
local objloc = farplocation:Translate(radius,farpobcount*30)
local heading = objloc:HeadingTo(farplocation)
local newobject = SPAWNSTATIC:NewFromType(_object.TypeName,_object.Category,Country)
newobject:InitShape(_object.ShapeName)
newobject:InitHeading(heading)
newobject:SpawnFromCoordinate(objloc,farpobcount*30,_name.." - "..Name)
table.insert(ReturnObjects,newobject)
farpobcount = farpobcount + 1
end
-- Vehicle if any
if VehicleTemplate and type(VehicleTemplate) == "string" then
local vcoordinate = farplocation:Translate(radius,farpobcount*30)
local heading = vcoordinate:HeadingTo(farplocation)
local vehicles = SPAWN:NewWithAlias(VehicleTemplate,"FARP Vehicles - "..Name)
vehicles:InitGroupHeading(heading)
vehicles:InitCountry(Country)
vehicles:InitCoalition(Coalition)
vehicles:InitDelayOff()
local spawnedvehicle = vehicles:SpawnFromCoordinate(vcoordinate)
table.insert(ReturnObjects,spawnedvehicle)
end
local newWH = STORAGE:New(Name)
if liquids and liquids > 0 then
-- Storage fill-up
newWH:SetLiquid(STORAGE.Liquid.DIESEL,liquids) -- kgs to tons
newWH:SetLiquid(STORAGE.Liquid.GASOLINE,liquids)
newWH:SetLiquid(STORAGE.Liquid.JETFUEL,liquids)
newWH:SetLiquid(STORAGE.Liquid.MW50,liquids)
end
if equip and equip > 0 then
for cat,nitem in pairs(ENUMS.Storage.weapons) do
for name,item in pairs(nitem) do
newWH:SetItem(item,equip)
end
end
end
local ADFName
if ADF and type(ADF) == "number" then
local ADFFreq = ADF*1000 -- KHz to Hz
local Sound = "l10n/DEFAULT/beacon.ogg"
local vec3 = farplocation:GetVec3()
ADFName = Name .. " ADF "..tostring(ADF).."KHz"
--BASE:I(string.format("Adding FARP Beacon %d KHz Name %s",ADF,ADFName))
trigger.action.radioTransmission(Sound, vec3, 0, true, ADFFreq, 250, ADFName)
end
return ReturnObjects, ADFName
end
@@ -176,6 +176,9 @@
-- ## 5.5) Air-2-Air missile attack range: -- ## 5.5) Air-2-Air missile attack range:
-- * @{#CONTROLLABLE.OptionAAAttackRange}(): Defines the usage of A2A missiles against possible targets. -- * @{#CONTROLLABLE.OptionAAAttackRange}(): Defines the usage of A2A missiles against possible targets.
-- --
-- # 6) [GROUND] IR Maker Beacons for GROUPs and UNITs
-- * @{#CONTROLLABLE:NewIRMarker}(): Create a blinking IR Marker on a GROUP or UNIT.
--
-- @field #CONTROLLABLE -- @field #CONTROLLABLE
CONTROLLABLE = { CONTROLLABLE = {
ClassName = "CONTROLLABLE", ClassName = "CONTROLLABLE",
@@ -5619,3 +5622,128 @@ function CONTROLLABLE:PatrolRaceTrack(Point1, Point2, Altitude, Speed, Formation
return self return self
end end
--- IR Marker courtesy Florian Brinker (fbrinker)
--- [GROUND] Create and enable a new IR Marker for the given controllable UNIT or GROUP.
-- @param #CONTROLLABLE self
-- @param #boolean EnableImmediately (Optionally) If true start up the IR Marker immediately. Else you need to call `myobject:EnableIRMarker()` later on.
-- @param #number Runtime (Optionally) Run this IR Marker for the given number of seconds, then stop. Use in conjunction with EnableImmediately.
-- @return #CONTROLLABLE self
function CONTROLLABLE:NewIRMarker(EnableImmediately, Runtime)
--sefl:F("NewIRMarker")
if self.ClassName == "GROUP" then
self.IRMarkerGroup = true
self.IRMarkerUnit = false
elseif self.ClassName == "UNIT" then
self.IRMarkerGroup = false
self.IRMarkerUnit = true
end
self.spot = nil
self.timer = nil
self.stoptimer = nil
if EnableImmediately and EnableImmediately == true then
self:EnableIRMarker(Runtime)
end
return self
end
--- [GROUND] Enable the IR marker.
-- @param #CONTROLLABLE self
-- @param #number Runtime (Optionally) Run this IR Marker for the given number of seconds, then stop. Else run until you call `myobject:DisableIRMarker()`.
-- @return #CONTROLLABLE self
function CONTROLLABLE:EnableIRMarker(Runtime)
--sefl:F("EnableIRMarker")
if self.IRMarkerGroup == nil then
self:NewIRMarker(true,Runtime)
return
end
if (self.IRMarkerGroup == true) then
self:EnableIRMarkerForGroup()
return
end
self.timer = TIMER:New(CONTROLLABLE._MarkerBlink, self)
self.timer:Start(nil, 1 - math.random(1, 5) / 10 / 2, Runtime) -- start randomized
return self
end
--- [GROUND] Disable the IR marker.
-- @param #CONTROLLABLE self
-- @return #CONTROLLABLE self
function CONTROLLABLE:DisableIRMarker()
--sefl:F("DisableIRMarker")
if (self.IRMarkerGroup == true) then
self:DisableIRMarkerForGroup()
return
end
if self.spot then
self.spot:destroy()
self.spot = nil
if self.timer and self.timer:IsRunning() then
self.timer:Stop()
self.timer = nil
end
end
return self
end
--- [GROUND] Enable the IR markers for a whole group.
-- @param #CONTROLLABLE self
-- @return #CONTROLLABLE self
function CONTROLLABLE:EnableIRMarkerForGroup()
--sefl:F("EnableIRMarkerForGroup")
if self.ClassName == "GROUP" then
local units = self:GetUnits() or {}
for _,_unit in pairs(units) do
_unit:EnableIRMarker()
end
end
return self
end
--- [GROUND] Disable the IR markers for a whole group.
-- @param #CONTROLLABLE self
-- @return #CONTROLLABLE self
function CONTROLLABLE:DisableIRMarkerForGroup()
--sefl:F("DisableIRMarkerForGroup")
if self.ClassName == "GROUP" then
local units = self:GetUnits() or {}
for _,_unit in pairs(units) do
_unit:DisableIRMarker()
end
end
return self
end
--- [Internal] This method is called by the scheduler after enabling the IR marker.
-- @param #CONTROLLABLE self
-- @return #CONTROLLABLE self
function CONTROLLABLE:_MarkerBlink()
--sefl:F("_MarkerBlink")
if self:IsAlive() ~= true then
self:DisableIRMarker()
return
end
self.timer.dT = 1 - (math.random(1, 2) / 10 / 2) -- randomize the blinking by a small amount
local _, _, unitBBHeight, _ = self:GetObjectSize()
local unitPos = self:GetPositionVec3()
self.spot = Spot.createInfraRed(
self.DCSUnit,
{ x = 0, y = (unitBBHeight + 1), z = 0 },
{ x = unitPos.x, y = (unitPos.y + unitBBHeight), z = unitPos.z }
)
local offTimer = TIMER:New(function() if self.spot then self.spot:destroy() end end)
offTimer:Start(0.5)
return self
end
@@ -0,0 +1,501 @@
--- **Wrapper** - Dynamic Cargo create from the F8 menu.
--
-- ## Main Features:
--
-- * Convenient access to DCS API functions
--
-- ===
--
-- ## Example Missions:
--
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_Demos/tree/master/Wrapper/Storage).
--
-- ===
--
-- ### Author: **Applevangelist**
--
-- ===
-- @module Wrapper.DynamicCargo
-- @image Wrapper_Storage.png
--- DYNAMICCARGO class.
-- @type DYNAMICCARGO
-- @field #string ClassName Name of the class.
-- @field #number verbose Verbosity level.
-- @field #string lid Class id string for output to DCS log file.
-- @field Wrapper.Storage#STORAGE warehouse The STORAGE object.
-- @field #string version.
-- @field #string CargoState.
-- @field #table DCS#Vec3 LastPosition.
-- @field #number Interval Check Interval. 20 secs default.
-- @field #boolean testing
-- @field Core.Timer#TIMER timer Timmer to run intervals
-- @field #string Owner The playername who has created, loaded or unloaded this cargo. Depends on state.
-- @extends Wrapper.Positionable#POSITIONABLE
--- *The capitalist cannot store labour-power in warehouses after he has bought it, as he may do with the raw material.* -- Karl Marx
--
-- ===
--
-- # The DYNAMICCARGO Concept
--
-- The DYNAMICCARGO class offers an easy-to-use wrapper interface to all DCS API functions of DCS dynamically spawned cargo crates.
-- We named the class DYNAMICCARGO, because the name WAREHOUSE is already taken by another MOOSE class..
--
-- # Constructor
--
-- @field #DYNAMICCARGO
DYNAMICCARGO = {
ClassName = "DYNAMICCARGO",
verbose = 0,
testing = false,
Interval = 10,
}
--- Liquid types.
-- @type DYNAMICCARGO.Liquid
-- @field #number JETFUEL Jet fuel (0).
-- @field #number GASOLINE Aviation gasoline (1).
-- @field #number MW50 MW50 (2).
-- @field #number DIESEL Diesel (3).
DYNAMICCARGO.Liquid = {
JETFUEL = 0,
GASOLINE = 1,
MW50 = 2,
DIESEL = 3,
}
--- Liquid Names for the static cargo resource table.
-- @type DYNAMICCARGO.LiquidName
-- @field #number JETFUEL "jet_fuel".
-- @field #number GASOLINE "gasoline".
-- @field #number MW50 "methanol_mixture".
-- @field #number DIESEL "diesel".
DYNAMICCARGO.LiquidName = {
GASOLINE = "gasoline",
DIESEL = "diesel",
MW50 = "methanol_mixture",
JETFUEL = "jet_fuel",
}
--- Storage types.
-- @type DYNAMICCARGO.Type
-- @field #number WEAPONS weapons.
-- @field #number LIQUIDS liquids. Also see #list<#DYNAMICCARGO.Liquid> for types of liquids.
-- @field #number AIRCRAFT aircraft.
DYNAMICCARGO.Type = {
WEAPONS = "weapons",
LIQUIDS = "liquids",
AIRCRAFT = "aircrafts",
}
--- State types
-- @type DYNAMICCARGO.State
-- @field #string NEW
-- @field #string LOADED
-- @field #string UNLOADED
-- @field #string REMOVED
DYNAMICCARGO.State = {
NEW = "NEW",
LOADED = "LOADED",
UNLOADED = "UNLOADED",
REMOVED = "REMOVED",
}
--- Helo types possible.
-- @type DYNAMICCARGO.AircraftTypes
DYNAMICCARGO.AircraftTypes = {
["CH-47Fbl1"] = "CH-47Fbl1",
}
--- Helo types possible.
-- @type DYNAMICCARGO.AircraftDimensions
DYNAMICCARGO.AircraftDimensions = {
-- CH-47 model start coordinate is quite exactly in the middle of the model, so half values here
["CH-47Fbl1"] = {
["width"] = 4,
["height"] = 6,
["length"] = 11,
["ropelength"] = 30,
},
}
--- DYNAMICCARGO class version.
-- @field #string version
DYNAMICCARGO.version="0.0.5"
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO list
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO: A lot...
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Constructor
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Create a new DYNAMICCARGO object from the DCS static cargo object.
-- @param #DYNAMICCARGO self
-- @param #string CargoName Name of the Cargo.
-- @return #DYNAMICCARGO self
function DYNAMICCARGO:Register(CargoName)
-- Inherit everything from a BASE class.
local self=BASE:Inherit(self, POSITIONABLE:New(CargoName)) -- #DYNAMICCARGO
self.StaticName = CargoName
self.LastPosition = self:GetCoordinate()
self.CargoState = DYNAMICCARGO.State.NEW
self.Interval = DYNAMICCARGO.Interval or 10
local DCSObject = self:GetDCSObject()
if DCSObject then
local warehouse = STORAGE:NewFromDynamicCargo(CargoName)
self.warehouse = warehouse
end
self.lid = string.format("DYNAMICCARGO %s", CargoName)
self.Owner = string.match(CargoName,"^(.+)|%d%d:%d%d|PKG%d+") or "None"
self.timer = TIMER:New(DYNAMICCARGO._UpdatePosition,self)
self.timer:Start(self.Interval,self.Interval)
if not _DYNAMICCARGO_HELOS then
_DYNAMICCARGO_HELOS = SET_CLIENT:New():FilterAlive():FilterFunction(DYNAMICCARGO._FilterHeloTypes):FilterStart()
end
if self.testing then
BASE:TraceOn()
BASE:TraceClass("DYNAMICCARGO")
end
return self
end
--- Get DCS object.
-- @param #DYNAMICCARGO self
-- @return DCS static object
function DYNAMICCARGO:GetDCSObject()
local DCSStatic = Unit.getByName( self.StaticName )
if DCSStatic then
return DCSStatic
end
return nil
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- User API Functions
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Get last known owner name of this DYNAMICCARGO
-- @param #DYNAMICCARGO self
-- @return #string Owner
function DYNAMICCARGO:GetLastOwner()
return self.Owner
end
--- Returns true if the cargo is new and has never been loaded into a Helo.
-- @param #DYNAMICCARGO self
-- @return #boolean Outcome
function DYNAMICCARGO:IsNew()
if self.CargoState and self.CargoState == DYNAMICCARGO.State.NEW then
return true
else
return false
end
end
--- Returns true if the cargo been loaded into a Helo.
-- @param #DYNAMICCARGO self
-- @return #boolean Outcome
function DYNAMICCARGO:IsLoaded()
if self.CargoState and self.CargoState == DYNAMICCARGO.State.LOADED then
return true
else
return false
end
end
--- Returns true if the cargo has been unloaded from a Helo.
-- @param #DYNAMICCARGO self
-- @return #boolean Outcome
function DYNAMICCARGO:IsUnloaded()
if self.CargoState and self.CargoState == DYNAMICCARGO.State.REMOVED then
return true
else
return false
end
end
--- Returns true if the cargo has been removed.
-- @param #DYNAMICCARGO self
-- @return #boolean Outcome
function DYNAMICCARGO:IsRemoved()
if self.CargoState and self.CargoState == DYNAMICCARGO.State.UNLOADED then
return true
else
return false
end
end
--- [CTLD] Get number of crates this DYNAMICCARGO consists of. Always one.
-- @param #DYNAMICCARGO self
-- @return #number crate number, always one
function DYNAMICCARGO:GetCratesNeeded()
return 1
end
--- [CTLD] Get this DYNAMICCARGO drop state. True if DYNAMICCARGO.State.UNLOADED
-- @param #DYNAMICCARGO self
-- @return #boolean Dropped
function DYNAMICCARGO:WasDropped()
return self.CargoState == DYNAMICCARGO.State.UNLOADED and true or false
end
--- [CTLD] Get CTLD_CARGO.Enum type of this DYNAMICCARGO
-- @param #DYNAMICCARGO self
-- @return #string Type, only one at the moment is CTLD_CARGO.Enum.GCLOADABLE
function DYNAMICCARGO:GetType()
return CTLD_CARGO.Enum.GCLOADABLE
end
--- Find last known position of this DYNAMICCARGO
-- @param #DYNAMICCARGO self
-- @return DCS#Vec3 Position in 3D space
function DYNAMICCARGO:GetLastPosition()
return self.LastPosition
end
--- Find current state of this DYNAMICCARGO
-- @param #DYNAMICCARGO self
-- @return string The current state
function DYNAMICCARGO:GetState()
return self.CargoState
end
--- Find a DYNAMICCARGO in the **_DATABASE** using the name associated with it.
-- @param #DYNAMICCARGO self
-- @param #string Name The dynamic cargo name
-- @return #DYNAMICCARGO self
function DYNAMICCARGO:FindByName( Name )
local storage = _DATABASE:FindDynamicCargo( Name )
return storage
end
--- Find the first(!) DYNAMICCARGO matching using patterns. Note that this is **a lot** slower than `:FindByName()`!
-- @param #DYNAMICCARGO self
-- @param #string Pattern The pattern to look for. Refer to [LUA patterns](http://www.easyuo.com/openeuo/wiki/index.php/Lua_Patterns_and_Captures_\(Regular_Expressions\)) for regular expressions in LUA.
-- @return #DYNAMICCARGO The DYNAMICCARGO.
-- @usage
-- -- Find a dynamic cargo with a partial dynamic cargo name
-- local grp = DYNAMICCARGO:FindByMatching( "Apple" )
-- -- will return e.g. a dynamic cargo named "Apple|08:00|PKG08"
--
-- -- using a pattern
-- local grp = DYNAMICCARGO:FindByMatching( ".%d.%d$" )
-- -- will return the first dynamic cargo found ending in "-1-1" to "-9-9", but not e.g. "-10-1"
function DYNAMICCARGO:FindByMatching( Pattern )
local GroupFound = nil
for name,static in pairs(_DATABASE.DYNAMICCARGO) do
if string.match(name, Pattern ) then
GroupFound = static
break
end
end
return GroupFound
end
--- Find all DYNAMICCARGO objects matching using patterns. Note that this is **a lot** slower than `:FindByName()`!
-- @param #DYNAMICCARGO self
-- @param #string Pattern The pattern to look for. Refer to [LUA patterns](http://www.easyuo.com/openeuo/wiki/index.php/Lua_Patterns_and_Captures_\(Regular_Expressions\)) for regular expressions in LUA.
-- @return #table Groups Table of matching #DYNAMICCARGO objects found
-- @usage
-- -- Find all dynamic cargo with a partial dynamic cargo name
-- local grptable = DYNAMICCARGO:FindAllByMatching( "Apple" )
-- -- will return all dynamic cargos with "Apple" in the name
--
-- -- using a pattern
-- local grp = DYNAMICCARGO:FindAllByMatching( ".%d.%d$" )
-- -- will return the all dynamic cargos found ending in "-1-1" to "-9-9", but not e.g. "-10-1" or "-1-10"
function DYNAMICCARGO:FindAllByMatching( Pattern )
local GroupsFound = {}
for name,static in pairs(_DATABASE.DYNAMICCARGO) do
if string.match(name, Pattern ) then
GroupsFound[#GroupsFound+1] = static
end
end
return GroupsFound
end
--- Get the #STORAGE object from this dynamic cargo.
-- @param #DYNAMICCARGO self
-- @return Wrapper.Storage#STORAGE Storage The #STORAGE object
function DYNAMICCARGO:GetStorageObject()
return self.warehouse
end
--- Get the weight in kgs from this dynamic cargo.
-- @param #DYNAMICCARGO self
-- @return #number Weight in kgs.
function DYNAMICCARGO:GetCargoWeight()
local DCSObject = self:GetDCSObject()
if DCSObject then
local weight = DCSObject:getCargoWeight()
return weight
else
return 0
end
end
--- Get the cargo display name from this dynamic cargo.
-- @param #DYNAMICCARGO self
-- @return #string The display name
function DYNAMICCARGO:GetCargoDisplayName()
local DCSObject = self:GetDCSObject()
if DCSObject then
local weight = DCSObject:getCargoDisplayName()
return weight
else
return self.StaticName
end
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Private Functions
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- [Internal] _Get Possible Player Helo Nearby
-- @param #DYNAMICCARGO self
-- @param Core.Point#COORDINATE pos
-- @param #boolean loading If true measure distance for loading else for unloading
-- @return #boolean Success
-- @return Wrapper.Client#CLIENT Helo
-- @return #string PlayerName
function DYNAMICCARGO:_GetPossibleHeloNearby(pos,loading)
local set = _DYNAMICCARGO_HELOS:GetAliveSet()
local success = false
local Helo = nil
local Playername = nil
for _,_helo in pairs (set or {}) do
local helo = _helo -- Wrapper.Client#CLIENT
local name = helo:GetPlayerName() or _DATABASE:_FindPlayerNameByUnitName(helo:GetName()) or "None"
self:T(self.lid.." Checking: "..name)
local hpos = helo:GetCoordinate()
-- TODO Unloading via sling load?
--local inair = hpos.y-hpos:GetLandHeight() > 4.5 and true or false -- Standard FARP is 4.5m
local inair = helo:InAir()
self:T(self.lid.." InAir: AGL/InAir: "..hpos.y-hpos:GetLandHeight().."/"..tostring(inair))
local typename = helo:GetTypeName()
if hpos and typename and inair == false then
local dimensions = DYNAMICCARGO.AircraftDimensions[typename]
if dimensions then
local delta2D = hpos:Get2DDistance(pos)
local delta3D = hpos:Get3DDistance(pos)
if self.testing then
self:T(string.format("Cargo relative position: 2D %dm | 3D %dm",delta2D,delta3D))
self:T(string.format("Helo dimension: length %dm | width %dm | rope %dm",dimensions.length,dimensions.width,dimensions.ropelength))
end
if loading~=true and delta2D > dimensions.length or delta2D > dimensions.width or delta3D > dimensions.ropelength then
success = true
Helo = helo
Playername = name
end
if loading == true and delta2D < dimensions.length or delta2D < dimensions.width or delta3D < dimensions.ropelength then
success = true
Helo = helo
Playername = name
end
end
end
end
return success,Helo,Playername
end
--- [Internal] Update internal states.
-- @param #DYNAMICCARGO self
-- @return #DYNAMICCARGO self
function DYNAMICCARGO:_UpdatePosition()
self:T(self.lid.." _UpdatePositionAndState")
if self:IsAlive() then
local pos = self:GetCoordinate()
if self.testing then
self:T(string.format("Cargo position: x=%d, y=%d, z=%d",pos.x,pos.y,pos.z))
self:T(string.format("Last position: x=%d, y=%d, z=%d",self.LastPosition.x,self.LastPosition.y,self.LastPosition.z))
end
if UTILS.Round(UTILS.VecDist3D(pos,self.LastPosition),2) > 0.5 then
---------------
-- LOAD Cargo
---------------
if self.CargoState == DYNAMICCARGO.State.NEW then
local isloaded, client, playername = self:_GetPossibleHeloNearby(pos,true)
self:T(self.lid.." moved! NEW -> LOADED by "..tostring(playername))
self.CargoState = DYNAMICCARGO.State.LOADED
self.Owner = playername
_DATABASE:CreateEventDynamicCargoLoaded(self)
---------------
-- UNLOAD Cargo
---------------
elseif self.CargoState == DYNAMICCARGO.State.LOADED then
-- TODO add checker if we are in flight somehow
-- ensure not just the helo is moving
local count = _DYNAMICCARGO_HELOS:CountAlive()
-- Testing
local landheight = pos:GetLandHeight()
local agl = pos.y-landheight
agl = UTILS.Round(agl,2)
self:T(self.lid.." AGL: "..agl or -1)
local isunloaded = true
local client
local playername
if count > 0 and (agl > 0 or self.testing) then
self:T(self.lid.." Possible alive helos: "..count or -1)
if agl ~= 0 or self.testing then
isunloaded, client, playername = self:_GetPossibleHeloNearby(pos,false)
end
if isunloaded then
self:T(self.lid.." moved! LOADED -> UNLOADED by "..tostring(playername))
self.CargoState = DYNAMICCARGO.State.UNLOADED
self.Owner = playername
_DATABASE:CreateEventDynamicCargoUnloaded(self)
end
end
end
self.LastPosition = pos
end
else
---------------
-- REMOVED Cargo
---------------
if self.timer and self.timer:IsRunning() then self.timer:Stop() end
self:T(self.lid.." dead! " ..self.CargoState.."-> REMOVED")
self.CargoState = DYNAMICCARGO.State.REMOVED
_DATABASE:CreateEventDynamicCargoRemoved(self)
end
return self
end
--- [Internal] Track helos for loaded/unloaded decision making.
-- @param Wrapper.Client#CLIENT client
-- @return #boolean IsIn
function DYNAMICCARGO._FilterHeloTypes(client)
if not client then return false end
local typename = client:GetTypeName()
local isinclude = DYNAMICCARGO.AircraftTypes[typename] ~= nil and true or false
return isinclude
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+129 -102
View File
@@ -360,14 +360,25 @@ end
-- @return DCS#Group The DCS Group. -- @return DCS#Group The DCS Group.
function GROUP:GetDCSObject() function GROUP:GetDCSObject()
if (not self.LastCallDCSObject) or (self.LastCallDCSObject and timer.getTime() - self.LastCallDCSObject > 1) then
-- Get DCS group. -- Get DCS group.
local DCSGroup = Group.getByName( self.GroupName ) local DCSGroup = Group.getByName( self.GroupName )
if DCSGroup then if DCSGroup then
self.LastCallDCSObject = timer.getTime()
self.DCSObject = DCSGroup
return DCSGroup return DCSGroup
else
self.DCSObject = nil
self.LastCallDCSObject = nil
end end
self:T2(string.format("ERROR: Could not get DCS group object of group %s because DCS object could not be found!", tostring(self.GroupName))) else
return self.DCSObject
end
--self:E(string.format("ERROR: Could not get DCS group object of group %s because DCS object could not be found!", tostring(self.GroupName)))
return nil return nil
end end
@@ -375,7 +386,7 @@ end
-- @param Wrapper.Positionable#POSITIONABLE self -- @param Wrapper.Positionable#POSITIONABLE self
-- @return DCS#Position The 3D position vectors of the POSITIONABLE or #nil if the groups not existing or alive. -- @return DCS#Position The 3D position vectors of the POSITIONABLE or #nil if the groups not existing or alive.
function GROUP:GetPositionVec3() -- Overridden from POSITIONABLE:GetPositionVec3() function GROUP:GetPositionVec3() -- Overridden from POSITIONABLE:GetPositionVec3()
self:F2( self.PositionableName ) --self:F2( self.PositionableName )
local DCSPositionable = self:GetDCSObject() local DCSPositionable = self:GetDCSObject()
@@ -383,7 +394,7 @@ function GROUP:GetPositionVec3() -- Overridden from POSITIONABLE:GetPositionVec3
local unit = DCSPositionable:getUnits()[1] local unit = DCSPositionable:getUnits()[1]
if unit then if unit then
local PositionablePosition = unit:getPosition().p local PositionablePosition = unit:getPosition().p
self:T3( PositionablePosition ) --self:T3( PositionablePosition )
return PositionablePosition return PositionablePosition
end end
end end
@@ -403,7 +414,7 @@ end
-- @param #GROUP self -- @param #GROUP self
-- @return #boolean `true` if the group is alive *and* active, `false` if the group is alive but inactive or `#nil` if the group does not exist anymore. -- @return #boolean `true` if the group is alive *and* active, `false` if the group is alive but inactive or `#nil` if the group does not exist anymore.
function GROUP:IsAlive() function GROUP:IsAlive()
self:F2( self.GroupName ) --self:F2( self.GroupName )
local DCSGroup = self:GetDCSObject() -- DCS#Group local DCSGroup = self:GetDCSObject() -- DCS#Group
@@ -412,7 +423,7 @@ function GROUP:IsAlive()
local DCSUnit = DCSGroup:getUnit(1) -- DCS#Unit local DCSUnit = DCSGroup:getUnit(1) -- DCS#Unit
if DCSUnit then if DCSUnit then
local GroupIsAlive = DCSUnit:isActive() local GroupIsAlive = DCSUnit:isActive()
self:T3( GroupIsAlive ) --self:T3( GroupIsAlive )
return GroupIsAlive return GroupIsAlive
end end
end end
@@ -425,7 +436,7 @@ end
-- @param #GROUP self -- @param #GROUP self
-- @return #boolean `true` if group is activated or `#nil` The group is not existing or alive. -- @return #boolean `true` if group is activated or `#nil` The group is not existing or alive.
function GROUP:IsActive() function GROUP:IsActive()
self:F2( self.GroupName ) --self:F2( self.GroupName )
local DCSGroup = self:GetDCSObject() -- DCS#Group local DCSGroup = self:GetDCSObject() -- DCS#Group
@@ -468,7 +479,7 @@ end
-- Ship:Destroy( false ) -- Don't generate an event upon destruction. -- Ship:Destroy( false ) -- Don't generate an event upon destruction.
-- --
function GROUP:Destroy( GenerateEvent, delay ) function GROUP:Destroy( GenerateEvent, delay )
self:F2( self.GroupName ) --self:F2( self.GroupName )
if delay and delay>0 then if delay and delay>0 then
self:ScheduleOnce(delay, GROUP.Destroy, self, GenerateEvent) self:ScheduleOnce(delay, GROUP.Destroy, self, GenerateEvent)
@@ -511,12 +522,12 @@ end
-- @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 )
local DCSGroup = self:GetDCSObject() local DCSGroup = self:GetDCSObject()
if DCSGroup then if DCSGroup then
local GroupCategory = DCSGroup:getCategory() local GroupCategory = DCSGroup:getCategory()
self:T3( GroupCategory ) --self:T3( GroupCategory )
return GroupCategory return GroupCategory
end end
@@ -527,7 +538,7 @@ end
-- @param #GROUP self -- @param #GROUP self
-- @return #string Category name = Helicopter, Airplane, Ground Unit, Ship, Train. -- @return #string Category name = Helicopter, Airplane, Ground Unit, Ship, Train.
function GROUP:GetCategoryName() function GROUP:GetCategoryName()
self:F2( self.GroupName ) --self:F2( self.GroupName )
local DCSGroup = self:GetDCSObject() local DCSGroup = self:GetDCSObject()
if DCSGroup then if DCSGroup then
@@ -539,7 +550,7 @@ function GROUP:GetCategoryName()
[Group.Category.TRAIN] = "Train", [Group.Category.TRAIN] = "Train",
} }
local GroupCategory = DCSGroup:getCategory() local GroupCategory = DCSGroup:getCategory()
self:T3( GroupCategory ) --self:T3( GroupCategory )
return CategoryNames[GroupCategory] return CategoryNames[GroupCategory]
end end
@@ -547,20 +558,22 @@ function GROUP:GetCategoryName()
return nil return nil
end end
--- Returns the coalition of the DCS Group. --- Returns the coalition of the DCS Group.
-- @param #GROUP self -- @param #GROUP self
-- @return DCS#coalition.side The coalition side of the DCS Group. -- @return DCS#coalition.side The coalition side of the DCS Group.
function GROUP:GetCoalition() function GROUP:GetCoalition()
self:F2( self.GroupName ) --self:F2( self.GroupName )
if self.GroupCoalition ~= nil then
return self.GroupCoalition
else
local DCSGroup = self:GetDCSObject() local DCSGroup = self:GetDCSObject()
if DCSGroup then if DCSGroup then
local GroupCoalition = DCSGroup:getCoalition() local GroupCoalition = DCSGroup:getCoalition()
self:T3( GroupCoalition ) --self:T3( GroupCoalition )
self.GroupCoalition = GroupCoalition
return GroupCoalition return GroupCoalition
end end
end
return nil return nil
end end
@@ -568,12 +581,12 @@ end
-- @param #GROUP self -- @param #GROUP self
-- @return DCS#country.id The country identifier or nil if the DCS Group is not existing or alive. -- @return DCS#country.id The country identifier or nil if the DCS Group is not existing or alive.
function GROUP:GetCountry() function GROUP:GetCountry()
self:F2( self.GroupName ) --self:F2( self.GroupName )
local DCSGroup = self:GetDCSObject() local DCSGroup = self:GetDCSObject()
if DCSGroup then if DCSGroup then
local GroupCountry = DCSGroup:getUnit(1):getCountry() local GroupCountry = DCSGroup:getUnit(1):getCountry()
self:T3( GroupCountry ) --self:T3( GroupCountry )
return GroupCountry return GroupCountry
end end
@@ -625,7 +638,7 @@ end
-- @param #GROUP self -- @param #GROUP self
-- @return #number Speed in km/h. -- @return #number Speed in km/h.
function GROUP:GetSpeedMax() function GROUP:GetSpeedMax()
self:F2( self.GroupName ) --self:F2( self.GroupName )
local DCSGroup = self:GetDCSObject() local DCSGroup = self:GetDCSObject()
if DCSGroup then if DCSGroup then
@@ -658,7 +671,7 @@ end
-- @param #GROUP self -- @param #GROUP self
-- @return #number Range in meters. -- @return #number Range in meters.
function GROUP:GetRange() function GROUP:GetRange()
self:F2( self.GroupName ) --self:F2( self.GroupName )
local DCSGroup = self:GetDCSObject() local DCSGroup = self:GetDCSObject()
if DCSGroup then if DCSGroup then
@@ -689,7 +702,7 @@ end
-- @param #GROUP self -- @param #GROUP self
-- @return #table of Wrapper.Unit#UNIT objects, indexed by number. -- @return #table of Wrapper.Unit#UNIT objects, indexed by number.
function GROUP:GetUnits() function GROUP:GetUnits()
self:F2( { self.GroupName } ) --self:F2( { self.GroupName } )
local DCSGroup = self:GetDCSObject() local DCSGroup = self:GetDCSObject()
if DCSGroup then if DCSGroup then
@@ -706,7 +719,7 @@ function GROUP:GetUnits()
Units[#Units+1]=unit Units[#Units+1]=unit
end end
end end
self:T3( Units ) --self:T3( Units )
return Units return Units
end end
@@ -717,7 +730,7 @@ end
-- @param #GROUP self -- @param #GROUP self
-- @return #list<Wrapper.Unit#UNIT> The list of player occupied @{Wrapper.Unit} objects of the @{Wrapper.Group}. -- @return #list<Wrapper.Unit#UNIT> The list of player occupied @{Wrapper.Unit} objects of the @{Wrapper.Group}.
function GROUP:GetPlayerUnits() function GROUP:GetPlayerUnits()
self:F2( { self.GroupName } ) --self:F2( { self.GroupName } )
local DCSGroup = self:GetDCSObject() local DCSGroup = self:GetDCSObject()
if DCSGroup then if DCSGroup then
@@ -729,7 +742,7 @@ function GROUP:GetPlayerUnits()
Units[#Units+1] = PlayerUnit Units[#Units+1] = PlayerUnit
end end
end end
self:T3( Units ) --self:T3( Units )
return Units return Units
end end
@@ -828,7 +841,7 @@ end
-- @param #GROUP self -- @param #GROUP self
-- @return #number Number of alive units. If DCS group is nil, 0 is returned. -- @return #number Number of alive units. If DCS group is nil, 0 is returned.
function GROUP:CountAliveUnits() function GROUP:CountAliveUnits()
self:F3( { self.GroupName } ) --self:F3( { self.GroupName } )
local DCSGroup = self:GetDCSObject() local DCSGroup = self:GetDCSObject()
if DCSGroup then if DCSGroup then
@@ -850,7 +863,7 @@ end
-- @param #GROUP self -- @param #GROUP self
-- @return Wrapper.Unit#UNIT First unit alive. -- @return Wrapper.Unit#UNIT First unit alive.
function GROUP:GetFirstUnitAlive() function GROUP:GetFirstUnitAlive()
self:F3({self.GroupName}) --self:F3({self.GroupName})
local DCSGroup = self:GetDCSObject() local DCSGroup = self:GetDCSObject()
if DCSGroup then if DCSGroup then
@@ -870,7 +883,7 @@ end
-- @param #GROUP self -- @param #GROUP self
-- @return Wrapper.Unit#UNIT First unit or nil if it does not exist. -- @return Wrapper.Unit#UNIT First unit or nil if it does not exist.
function GROUP:GetFirstUnit() function GROUP:GetFirstUnit()
self:F3({self.GroupName}) --self:F3({self.GroupName})
local DCSGroup = self:GetDCSObject() local DCSGroup = self:GetDCSObject()
if DCSGroup then if DCSGroup then
@@ -885,7 +898,7 @@ end
-- @param Wrapper.Group#GROUP self -- @param Wrapper.Group#GROUP self
-- @return DCS#Vec3 The velocity Vec3 vector or `#nil` if the GROUP is not existing or alive. -- @return DCS#Vec3 The velocity Vec3 vector or `#nil` if the GROUP is not existing or alive.
function GROUP:GetVelocityVec3() function GROUP:GetVelocityVec3()
self:F2( self.GroupName ) --self:F2( self.GroupName )
local DCSGroup = self:GetDCSObject() local DCSGroup = self:GetDCSObject()
@@ -919,7 +932,7 @@ end
-- @param #boolean FromGround Measure from the ground or from sea level (ASL). Provide **true** for measuring from the ground (AGL). **false** or **nil** if you measure from sea level. -- @param #boolean FromGround Measure from the ground or from sea level (ASL). Provide **true** for measuring from the ground (AGL). **false** or **nil** if you measure from sea level.
-- @return #number The altitude of the group or nil if is not existing or alive. -- @return #number The altitude of the group or nil if is not existing or alive.
function GROUP:GetAltitude(FromGround) function GROUP:GetAltitude(FromGround)
self:F2( self.GroupName ) --self:F2( self.GroupName )
return self:GetHeight(FromGround) return self:GetHeight(FromGround)
end end
@@ -928,7 +941,7 @@ end
-- @param #boolean FromGround Measure from the ground or from sea level (ASL). Provide **true** for measuring from the ground (AGL). **false** or **nil** if you measure from sea level. -- @param #boolean FromGround Measure from the ground or from sea level (ASL). Provide **true** for measuring from the ground (AGL). **false** or **nil** if you measure from sea level.
-- @return #number The height of the group or nil if is not existing or alive. -- @return #number The height of the group or nil if is not existing or alive.
function GROUP:GetHeight( FromGround ) function GROUP:GetHeight( FromGround )
self:F2( self.GroupName ) --self:F2( self.GroupName )
local DCSGroup = self:GetDCSObject() local DCSGroup = self:GetDCSObject()
@@ -964,12 +977,12 @@ end
-- @param #GROUP self -- @param #GROUP self
-- @return #number The DCS Group initial size. -- @return #number The DCS Group initial size.
function GROUP:GetInitialSize() function GROUP:GetInitialSize()
self:F3( { self.GroupName } ) --self:F3( { self.GroupName } )
local DCSGroup = self:GetDCSObject() local DCSGroup = self:GetDCSObject()
if DCSGroup then if DCSGroup then
local GroupInitialSize = DCSGroup:getInitialSize() local GroupInitialSize = DCSGroup:getInitialSize()
self:T3( GroupInitialSize ) --self:T3( GroupInitialSize )
return GroupInitialSize return GroupInitialSize
end end
@@ -981,12 +994,12 @@ end
-- @param #GROUP self -- @param #GROUP self
-- @return #table The DCS Units. -- @return #table The DCS Units.
function GROUP:GetDCSUnits() function GROUP:GetDCSUnits()
self:F2( { self.GroupName } ) --self:F2( { self.GroupName } )
local DCSGroup = self:GetDCSObject() local DCSGroup = self:GetDCSObject()
if DCSGroup then if DCSGroup then
local DCSUnits = DCSGroup:getUnits() local DCSUnits = DCSGroup:getUnits()
self:T3( DCSUnits ) --self:T3( DCSUnits )
return DCSUnits return DCSUnits
end end
@@ -999,7 +1012,7 @@ end
-- @param #number delay Delay in seconds, before the group is activated. -- @param #number delay Delay in seconds, before the group is activated.
-- @return #GROUP self -- @return #GROUP self
function GROUP:Activate(delay) function GROUP:Activate(delay)
self:F2( { self.GroupName } ) --self:F2( { self.GroupName } )
if delay and delay>0 then if delay and delay>0 then
self:ScheduleOnce(delay, GROUP.Activate, self) self:ScheduleOnce(delay, GROUP.Activate, self)
else else
@@ -1008,18 +1021,32 @@ function GROUP:Activate(delay)
return self return self
end end
--- Deactivates an activated GROUP.
-- @param #GROUP self
-- @param #number delay Delay in seconds, before the group is activated.
-- @return #GROUP self
function GROUP:Deactivate(delay)
--self:F2( { self.GroupName } )
if delay and delay>0 then
self:ScheduleOnce(delay, GROUP.Deactivate, self)
else
trigger.action.deactivateGroup( self:GetDCSObject() )
end
return self
end
--- Gets the type name of the group. --- Gets the type name of the group.
-- @param #GROUP self -- @param #GROUP self
-- @return #string The type name of the group. -- @return #string The type name of the group.
function GROUP:GetTypeName() function GROUP:GetTypeName()
self:F2( self.GroupName ) --self:F2( self.GroupName )
local DCSGroup = self:GetDCSObject() local DCSGroup = self:GetDCSObject()
if DCSGroup then if DCSGroup then
local GroupTypeName = DCSGroup:getUnit(1):getTypeName() local GroupTypeName = DCSGroup:getUnit(1):getTypeName()
self:T3( GroupTypeName ) --self:T3( GroupTypeName )
return( GroupTypeName ) return( GroupTypeName )
end end
@@ -1030,13 +1057,13 @@ end
--@param #GROUP self --@param #GROUP self
--@return #string NatoReportingName or "Bogey" if unknown. --@return #string NatoReportingName or "Bogey" if unknown.
function GROUP:GetNatoReportingName() function GROUP:GetNatoReportingName()
self:F2( self.GroupName ) --self:F2( self.GroupName )
local DCSGroup = self:GetDCSObject() local DCSGroup = self:GetDCSObject()
if DCSGroup then if DCSGroup then
local GroupTypeName = DCSGroup:getUnit(1):getTypeName() local GroupTypeName = DCSGroup:getUnit(1):getTypeName()
self:T3( GroupTypeName ) --self:T3( GroupTypeName )
return UTILS.GetReportingName(GroupTypeName) return UTILS.GetReportingName(GroupTypeName)
end end
@@ -1048,13 +1075,13 @@ end
-- @param #GROUP self -- @param #GROUP self
-- @return #string The player name of the group. -- @return #string The player name of the group.
function GROUP:GetPlayerName() function GROUP:GetPlayerName()
self:F2( self.GroupName ) --self:F2( self.GroupName )
local DCSGroup = self:GetDCSObject() local DCSGroup = self:GetDCSObject()
if DCSGroup then if DCSGroup then
local PlayerName = DCSGroup:getUnit(1):getPlayerName() local PlayerName = DCSGroup:getUnit(1):getPlayerName()
self:T3( PlayerName ) --self:T3( PlayerName )
return( PlayerName ) return( PlayerName )
end end
@@ -1066,13 +1093,13 @@ end
-- @param #GROUP self -- @param #GROUP self
-- @return #string The CallSign of the first DCS Unit of the DCS Group. -- @return #string The CallSign of the first DCS Unit of the DCS Group.
function GROUP:GetCallsign() function GROUP:GetCallsign()
self:F2( self.GroupName ) --self:F2( self.GroupName )
local DCSGroup = self:GetDCSObject() local DCSGroup = self:GetDCSObject()
if DCSGroup then if DCSGroup then
local GroupCallSign = DCSGroup:getUnit(1):getCallsign() local GroupCallSign = DCSGroup:getUnit(1):getCallsign()
self:T3( GroupCallSign ) --self:T3( GroupCallSign )
return GroupCallSign return GroupCallSign
end end
@@ -1149,13 +1176,13 @@ end
-- @return Core.Point#POINT_VEC2 The 2D point vector of the first DCS Unit of the GROUP. -- @return Core.Point#POINT_VEC2 The 2D point vector of the first DCS Unit of the GROUP.
-- @return #nil The first UNIT is not existing or alive. -- @return #nil The first UNIT is not existing or alive.
function GROUP:GetPointVec2() function GROUP:GetPointVec2()
self:F2(self.GroupName) --self:F2(self.GroupName)
local FirstUnit = self:GetUnit(1) local FirstUnit = self:GetUnit(1)
if FirstUnit then if FirstUnit then
local FirstUnitPointVec2 = FirstUnit:GetPointVec2() local FirstUnitPointVec2 = FirstUnit:GetPointVec2()
self:T3(FirstUnitPointVec2) --self:T3(FirstUnitPointVec2)
return FirstUnitPointVec2 return FirstUnitPointVec2
end end
@@ -1237,13 +1264,13 @@ end
-- @usage -- @usage
-- -- If Radius is ignored, returns the DCS#Vec3 of first UNIT of the GROUP -- -- If Radius is ignored, returns the DCS#Vec3 of first UNIT of the GROUP
function GROUP:GetRandomVec3(Radius) function GROUP:GetRandomVec3(Radius)
self:F2(self.GroupName) --self:F2(self.GroupName)
local FirstUnit = self:GetUnit(1) local FirstUnit = self:GetUnit(1)
if FirstUnit then if FirstUnit then
local FirstUnitRandomPointVec3 = FirstUnit:GetRandomVec3(Radius) local FirstUnitRandomPointVec3 = FirstUnit:GetRandomVec3(Radius)
self:T3(FirstUnitRandomPointVec3) --self:T3(FirstUnitRandomPointVec3)
return FirstUnitRandomPointVec3 return FirstUnitRandomPointVec3
end end
@@ -1256,9 +1283,9 @@ end
-- @param #GROUP self -- @param #GROUP self
-- @return #number Mean heading of the GROUP in degrees or #nil The first UNIT is not existing or alive. -- @return #number Mean heading of the GROUP in degrees or #nil The first UNIT is not existing or alive.
function GROUP:GetHeading() function GROUP:GetHeading()
self:F2(self.GroupName) --self:F2(self.GroupName)
self:F2(self.GroupName) --self:F2(self.GroupName)
local GroupSize = self:GetSize() local GroupSize = self:GetSize()
local HeadingAccumulator = 0 local HeadingAccumulator = 0
@@ -1287,7 +1314,7 @@ end
-- @return #number The fuel state of the unit with the least amount of fuel. -- @return #number The fuel state of the unit with the least amount of fuel.
-- @return Wrapper.Unit#UNIT reference to #Unit object for further processing. -- @return Wrapper.Unit#UNIT reference to #Unit object for further processing.
function GROUP:GetFuelMin() function GROUP:GetFuelMin()
self:F3(self.ControllableName) --self:F3(self.ControllableName)
if not self:GetDCSObject() then if not self:GetDCSObject() then
BASE:E( { "Cannot GetFuel", Group = self, Alive = self:IsAlive() } ) BASE:E( { "Cannot GetFuel", Group = self, Alive = self:IsAlive() } )
@@ -1318,7 +1345,7 @@ end
-- @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).
-- @return #nil The GROUP is not existing or alive. -- @return #nil The GROUP is not existing or alive.
function GROUP:GetFuelAvg() function GROUP:GetFuelAvg()
self:F( self.ControllableName ) --self:F( self.ControllableName )
local DCSControllable = self:GetDCSObject() local DCSControllable = self:GetDCSObject()
@@ -1328,7 +1355,7 @@ function GROUP:GetFuelAvg()
for UnitID, UnitData in pairs( self:GetUnits() ) do for UnitID, UnitData in pairs( self:GetUnits() ) do
local Unit = UnitData -- Wrapper.Unit#UNIT local Unit = UnitData -- Wrapper.Unit#UNIT
local UnitFuel = Unit:GetFuel() or 0 local UnitFuel = Unit:GetFuel() or 0
self:F( { Fuel = UnitFuel } ) --self:F( { Fuel = UnitFuel } )
TotalFuel = TotalFuel + UnitFuel TotalFuel = TotalFuel + UnitFuel
end end
local GroupFuel = TotalFuel / GroupSize local GroupFuel = TotalFuel / GroupSize
@@ -1358,7 +1385,7 @@ end
-- @return #number Number of missiles left. -- @return #number Number of missiles left.
-- @return #number Number of artillery shells left (with explosive mass, included in shells; shells can also be machine gun ammo) -- @return #number Number of artillery shells left (with explosive mass, included in shells; shells can also be machine gun ammo)
function GROUP:GetAmmunition() function GROUP:GetAmmunition()
self:F( self.ControllableName ) --self:F( self.ControllableName )
local DCSControllable = self:GetDCSObject() local DCSControllable = self:GetDCSObject()
@@ -1429,7 +1456,7 @@ end
-- @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 Group is completely within the @{Core.Zone#ZONE_BASE} -- @return #boolean Returns true if the Group is completely within the @{Core.Zone#ZONE_BASE}
function GROUP:IsCompletelyInZone( Zone ) function GROUP:IsCompletelyInZone( Zone )
self:F2( { self.GroupName, Zone } ) --self:F2( { self.GroupName, Zone } )
if not self:IsAlive() then return false end if not self:IsAlive() then return false end
@@ -1449,7 +1476,7 @@ end
-- @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 Group is partially within the @{Core.Zone#ZONE_BASE} -- @return #boolean Returns true if the Group is partially within the @{Core.Zone#ZONE_BASE}
function GROUP:IsPartlyInZone( Zone ) function GROUP:IsPartlyInZone( Zone )
self:F2( { self.GroupName, Zone } ) --self:F2( { self.GroupName, Zone } )
local IsOneUnitInZone = false local IsOneUnitInZone = false
local IsOneUnitOutsideZone = false local IsOneUnitOutsideZone = false
@@ -1485,7 +1512,7 @@ end
-- @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 Group is not within the @{Core.Zone#ZONE_BASE} -- @return #boolean Returns true if the Group is not within the @{Core.Zone#ZONE_BASE}
function GROUP:IsNotInZone( Zone ) function GROUP:IsNotInZone( Zone )
self:F2( { self.GroupName, Zone } ) --self:F2( { self.GroupName, Zone } )
if not self:IsAlive() then return true end if not self:IsAlive() then return true end
@@ -1521,7 +1548,7 @@ end
-- @param Core.Zone#ZONE_BASE Zone The zone to test. -- @param Core.Zone#ZONE_BASE Zone The zone to test.
-- @return #number The number of UNITs that are in the @{Core.Zone} -- @return #number The number of UNITs that are in the @{Core.Zone}
function GROUP:CountInZone( Zone ) function GROUP:CountInZone( Zone )
self:F2( {self.GroupName, Zone} ) --self:F2( {self.GroupName, Zone} )
local Count = 0 local Count = 0
if not self:IsAlive() then return Count end if not self:IsAlive() then return Count end
@@ -1541,13 +1568,13 @@ end
-- @param #GROUP self -- @param #GROUP self
-- @return #boolean Air category evaluation result. -- @return #boolean Air category evaluation result.
function GROUP:IsAir() function GROUP:IsAir()
self:F2( self.GroupName ) --self:F2( self.GroupName )
local DCSGroup = self:GetDCSObject() local DCSGroup = self:GetDCSObject()
if DCSGroup then if DCSGroup then
local IsAirResult = DCSGroup:getCategory() == Group.Category.AIRPLANE or DCSGroup:getCategory() == Group.Category.HELICOPTER local IsAirResult = DCSGroup:getCategory() == Group.Category.AIRPLANE or DCSGroup:getCategory() == Group.Category.HELICOPTER
self:T3( IsAirResult ) --self:T3( IsAirResult )
return IsAirResult return IsAirResult
end end
@@ -1558,13 +1585,13 @@ end
-- @param #GROUP self -- @param #GROUP self
-- @return #boolean true if DCS Group contains Helicopters. -- @return #boolean true if DCS Group contains Helicopters.
function GROUP:IsHelicopter() function GROUP:IsHelicopter()
self:F2( self.GroupName ) --self:F2( self.GroupName )
local DCSGroup = self:GetDCSObject() local DCSGroup = self:GetDCSObject()
if DCSGroup then if DCSGroup then
local GroupCategory = DCSGroup:getCategory() local GroupCategory = DCSGroup:getCategory()
self:T2( GroupCategory ) --self:T2( GroupCategory )
return GroupCategory == Group.Category.HELICOPTER return GroupCategory == Group.Category.HELICOPTER
end end
@@ -1575,13 +1602,13 @@ end
-- @param #GROUP self -- @param #GROUP self
-- @return #boolean true if DCS Group contains AirPlanes. -- @return #boolean true if DCS Group contains AirPlanes.
function GROUP:IsAirPlane() function GROUP:IsAirPlane()
self:F2() --self:F2()
local DCSGroup = self:GetDCSObject() local DCSGroup = self:GetDCSObject()
if DCSGroup then if DCSGroup then
local GroupCategory = DCSGroup:getCategory() local GroupCategory = DCSGroup:getCategory()
self:T2( GroupCategory ) --self:T2( GroupCategory )
return GroupCategory == Group.Category.AIRPLANE return GroupCategory == Group.Category.AIRPLANE
end end
@@ -1592,13 +1619,13 @@ end
-- @param #GROUP self -- @param #GROUP self
-- @return #boolean true if DCS Group contains Ground troops. -- @return #boolean true if DCS Group contains Ground troops.
function GROUP:IsGround() function GROUP:IsGround()
self:F2() --self:F2()
local DCSGroup = self:GetDCSObject() local DCSGroup = self:GetDCSObject()
if DCSGroup then if DCSGroup then
local GroupCategory = DCSGroup:getCategory() local GroupCategory = DCSGroup:getCategory()
self:T2( GroupCategory ) --self:T2( GroupCategory )
return GroupCategory == Group.Category.GROUND return GroupCategory == Group.Category.GROUND
end end
@@ -1609,13 +1636,13 @@ end
-- @param #GROUP self -- @param #GROUP self
-- @return #boolean true if DCS Group contains Ships. -- @return #boolean true if DCS Group contains Ships.
function GROUP:IsShip() function GROUP:IsShip()
self:F2() --self:F2()
local DCSGroup = self:GetDCSObject() local DCSGroup = self:GetDCSObject()
if DCSGroup then if DCSGroup then
local GroupCategory = DCSGroup:getCategory() local GroupCategory = DCSGroup:getCategory()
self:T2( GroupCategory ) --self:T2( GroupCategory )
return GroupCategory == Group.Category.SHIP return GroupCategory == Group.Category.SHIP
end end
@@ -1627,7 +1654,7 @@ end
-- @param #GROUP self -- @param #GROUP self
-- @return #boolean All units on the ground result. -- @return #boolean All units on the ground result.
function GROUP:AllOnGround() function GROUP:AllOnGround()
self:F2() --self:F2()
local DCSGroup = self:GetDCSObject() local DCSGroup = self:GetDCSObject()
@@ -1640,7 +1667,7 @@ function GROUP:AllOnGround()
end end
end end
self:T3( AllOnGroundResult ) --self:T3( AllOnGroundResult )
return AllOnGroundResult return AllOnGroundResult
end end
@@ -1695,7 +1722,7 @@ end
-- @param #GROUP self -- @param #GROUP self
-- @return #number Maximum velocity found. -- @return #number Maximum velocity found.
function GROUP:GetMaxVelocity() function GROUP:GetMaxVelocity()
self:F2() --self:F2()
local DCSGroup = self:GetDCSObject() local DCSGroup = self:GetDCSObject()
@@ -1723,7 +1750,7 @@ end
-- @param #GROUP self -- @param #GROUP self
-- @return #number Minimum height found. -- @return #number Minimum height found.
function GROUP:GetMinHeight() function GROUP:GetMinHeight()
self:F2() --self:F2()
local DCSGroup = self:GetDCSObject() local DCSGroup = self:GetDCSObject()
@@ -1751,7 +1778,7 @@ end
-- @param #GROUP self -- @param #GROUP self
-- @return #number Maximum height found. -- @return #number Maximum height found.
function GROUP:GetMaxHeight() function GROUP:GetMaxHeight()
self:F2() --self:F2()
local DCSGroup = self:GetDCSObject() local DCSGroup = self:GetDCSObject()
@@ -1893,7 +1920,7 @@ end
-- @param Core.Point#COORDINATE coordinate Coordinate where the group should be respawned. -- @param Core.Point#COORDINATE coordinate Coordinate where the group should be respawned.
-- @return #GROUP self -- @return #GROUP self
function GROUP:InitCoordinate(coordinate) function GROUP:InitCoordinate(coordinate)
self:F({coordinate=coordinate}) --self:F({coordinate=coordinate})
self.InitCoord=coordinate self.InitCoord=coordinate
return self return self
end end
@@ -1903,7 +1930,7 @@ end
-- @param #boolean switch If true (or nil), enables the radio comms. If false, disables the radio for the spawned group. -- @param #boolean switch If true (or nil), enables the radio comms. If false, disables the radio for the spawned group.
-- @return #GROUP self -- @return #GROUP self
function GROUP:InitRadioCommsOnOff(switch) function GROUP:InitRadioCommsOnOff(switch)
self:F({switch=switch}) --self:F({switch=switch})
if switch==true or switch==nil then if switch==true or switch==nil then
self.InitRespawnRadio=true self.InitRespawnRadio=true
else else
@@ -1917,7 +1944,7 @@ end
-- @param #number frequency The frequency in MHz. -- @param #number frequency The frequency in MHz.
-- @return #GROUP self -- @return #GROUP self
function GROUP:InitRadioFrequency(frequency) function GROUP:InitRadioFrequency(frequency)
self:F({frequency=frequency}) --self:F({frequency=frequency})
self.InitRespawnFreq=frequency self.InitRespawnFreq=frequency
@@ -1929,7 +1956,7 @@ end
-- @param #string modulation Either "FM" or "AM". If no value is given, modulation is set to AM. -- @param #string modulation Either "FM" or "AM". If no value is given, modulation is set to AM.
-- @return #GROUP self -- @return #GROUP self
function GROUP:InitRadioModulation(modulation) function GROUP:InitRadioModulation(modulation)
self:F({modulation=modulation}) --self:F({modulation=modulation})
if modulation and modulation:lower()=="fm" then if modulation and modulation:lower()=="fm" then
self.InitRespawnModu=radio.modulation.FM self.InitRespawnModu=radio.modulation.FM
else else
@@ -1943,7 +1970,7 @@ end
-- @param #string modex Tail number of the first unit. -- @param #string modex Tail number of the first unit.
-- @return #GROUP self -- @return #GROUP self
function GROUP:InitModex(modex) function GROUP:InitModex(modex)
self:F({modex=modex}) --self:F({modex=modex})
if modex then if modex then
self.InitRespawnModex=tonumber(modex) self.InitRespawnModex=tonumber(modex)
end end
@@ -2009,7 +2036,7 @@ function GROUP:Respawn( Template, Reset )
--Template.y = nil --Template.y = nil
-- Debug number of units. -- Debug number of units.
self:F( #Template.units ) --self:F( #Template.units )
-- Reset position etc? -- Reset position etc?
if Reset == true then if Reset == true then
@@ -2017,10 +2044,10 @@ function GROUP:Respawn( Template, Reset )
-- Loop over units in group. -- Loop over units in group.
for UnitID, UnitData in pairs( self:GetUnits() ) do for UnitID, UnitData in pairs( self:GetUnits() ) do
local GroupUnit = UnitData -- Wrapper.Unit#UNIT local GroupUnit = UnitData -- Wrapper.Unit#UNIT
self:F(GroupUnit:GetName()) --self:F(GroupUnit:GetName())
if GroupUnit:IsAlive() then if GroupUnit:IsAlive() then
self:I("FF Alive") --self:I("FF Alive")
-- Get unit position vector. -- Get unit position vector.
local GroupUnitVec3 = GroupUnit:GetVec3() local GroupUnitVec3 = GroupUnit:GetVec3()
@@ -2060,7 +2087,7 @@ function GROUP:Respawn( Template, Reset )
Template.units[UnitID].psi = -Template.units[UnitID].heading Template.units[UnitID].psi = -Template.units[UnitID].heading
-- Debug. -- Debug.
self:F( { UnitID, Template.units[UnitID], Template.units[UnitID] } ) --self:F( { UnitID, Template.units[UnitID], Template.units[UnitID] } )
end end
end end
@@ -2069,7 +2096,7 @@ function GROUP:Respawn( Template, Reset )
-- Loop over template units. -- Loop over template units.
for UnitID, TemplateUnitData in pairs( Template.units ) do for UnitID, TemplateUnitData in pairs( Template.units ) do
self:F( "Reset" ) --self:F( "Reset" )
-- Position from template. -- Position from template.
local GroupUnitVec3 = { x = TemplateUnitData.x, y = TemplateUnitData.alt, z = TemplateUnitData.y } local GroupUnitVec3 = { x = TemplateUnitData.x, y = TemplateUnitData.alt, z = TemplateUnitData.y }
@@ -2103,7 +2130,7 @@ function GROUP:Respawn( Template, Reset )
Template.units[UnitID].heading = self.InitRespawnHeading and self.InitRespawnHeading or TemplateUnitData.heading Template.units[UnitID].heading = self.InitRespawnHeading and self.InitRespawnHeading or TemplateUnitData.heading
-- Debug. -- Debug.
self:F( { UnitID, Template.units[UnitID], Template.units[UnitID] } ) --self:F( { UnitID, Template.units[UnitID], Template.units[UnitID] } )
end end
else else
@@ -2154,7 +2181,7 @@ function GROUP:Respawn( Template, Reset )
-- Destroy old group. Dont trigger any dead/crash events since this is a respawn. -- Destroy old group. Dont trigger any dead/crash events since this is a respawn.
self:Destroy(false) self:Destroy(false)
self:T({Template=Template}) --self:T({Template=Template})
-- Spawn new group. -- Spawn new group.
_DATABASE:Spawn(Template) _DATABASE:Spawn(Template)
@@ -2175,7 +2202,7 @@ end
-- @param #boolean Uncontrolled (Optional) If true, spawn in uncontrolled state. -- @param #boolean Uncontrolled (Optional) If true, spawn in uncontrolled state.
-- @return Wrapper.Group#GROUP Group spawned at airbase or nil if group could not be spawned. -- @return Wrapper.Group#GROUP Group spawned at airbase or nil if group could not be spawned.
function GROUP:RespawnAtCurrentAirbase(SpawnTemplate, Takeoff, Uncontrolled) -- R2.4 function GROUP:RespawnAtCurrentAirbase(SpawnTemplate, Takeoff, Uncontrolled) -- R2.4
self:F2( { SpawnTemplate, Takeoff, Uncontrolled} ) --self:F2( { SpawnTemplate, Takeoff, Uncontrolled} )
if self and self:IsAlive() then if self and self:IsAlive() then
@@ -2183,7 +2210,7 @@ function GROUP:RespawnAtCurrentAirbase(SpawnTemplate, Takeoff, Uncontrolled) --
local airbase=self:GetCoordinate():GetClosestAirbase() local airbase=self:GetCoordinate():GetClosestAirbase()
if airbase then if airbase then
self:F2("Closest airbase = "..airbase:GetName()) --self:F2("Closest airbase = "..airbase:GetName())
else else
self:E("ERROR: could not find closest airbase!") self:E("ERROR: could not find closest airbase!")
return nil return nil
@@ -2234,7 +2261,7 @@ function GROUP:RespawnAtCurrentAirbase(SpawnTemplate, Takeoff, Uncontrolled) --
local Parkingspot, TermialID, Distance=unit:GetCoordinate():GetClosestParkingSpot(airbase) local Parkingspot, TermialID, Distance=unit:GetCoordinate():GetClosestParkingSpot(airbase)
--Parkingspot:MarkToAll("parking spot") --Parkingspot:MarkToAll("parking spot")
self:T2(string.format("Closest parking spot distance = %s, terminal ID=%s", tostring(Distance), tostring(TermialID))) --self:T2(string.format("Closest parking spot distance = %s, terminal ID=%s", tostring(Distance), tostring(TermialID)))
-- Get unit coordinates for respawning position. -- Get unit coordinates for respawning position.
local uc=unit:GetCoordinate() local uc=unit:GetCoordinate()
@@ -2296,7 +2323,7 @@ end
-- @param #GROUP self -- @param #GROUP self
-- @return #table The MissionTemplate -- @return #table The MissionTemplate
function GROUP:GetTaskMission() function GROUP:GetTaskMission()
self:F2( self.GroupName ) --self:F2( self.GroupName )
return UTILS.DeepCopy( _DATABASE.Templates.Groups[self.GroupName].Template ) return UTILS.DeepCopy( _DATABASE.Templates.Groups[self.GroupName].Template )
end end
@@ -2305,7 +2332,7 @@ end
-- @param #GROUP self -- @param #GROUP self
-- @return #table The mission route defined by points. -- @return #table The mission route defined by points.
function GROUP:GetTaskRoute() function GROUP:GetTaskRoute()
self:F2( self.GroupName ) --self:F2( self.GroupName )
return UTILS.DeepCopy( _DATABASE.Templates.Groups[self.GroupName].Template.route.points ) return UTILS.DeepCopy( _DATABASE.Templates.Groups[self.GroupName].Template.route.points )
end end
@@ -2317,7 +2344,7 @@ end
-- @param #boolean Randomize Randomization of the route, when true. -- @param #boolean Randomize Randomization of the route, when true.
-- @param #number Radius When randomization is on, the randomization is within the radius. -- @param #number Radius When randomization is on, the randomization is within the radius.
function GROUP:CopyRoute( Begin, End, Randomize, Radius ) function GROUP:CopyRoute( Begin, End, Randomize, Radius )
self:F2( { Begin, End } ) --self:F2( { Begin, End } )
local Points = {} local Points = {}
@@ -2329,7 +2356,7 @@ function GROUP:CopyRoute( Begin, End, Randomize, Radius )
GroupName = self:GetName() GroupName = self:GetName()
end end
self:T3( { GroupName } ) --self:T3( { GroupName } )
local Template = _DATABASE.Templates.Groups[GroupName].Template local Template = _DATABASE.Templates.Groups[GroupName].Template
@@ -2375,7 +2402,7 @@ function GROUP:CalculateThreatLevelA2G()
end end
end end
self:T3( MaxThreatLevelA2G ) --self:T3( MaxThreatLevelA2G )
return MaxThreatLevelA2G return MaxThreatLevelA2G
end end
@@ -2402,7 +2429,7 @@ end
-- @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.
function GROUP:InAir() function GROUP:InAir()
self:F2( self.GroupName ) --self:F2( self.GroupName )
local DCSGroup = self:GetDCSObject() local DCSGroup = self:GetDCSObject()
@@ -2410,7 +2437,7 @@ function GROUP:InAir()
local DCSUnit = DCSGroup:getUnit(1) local DCSUnit = DCSGroup:getUnit(1)
if DCSUnit then if DCSUnit then
local GroupInAir = DCSGroup:getUnit(1):inAir() local GroupInAir = DCSGroup:getUnit(1):inAir()
self:T3( GroupInAir ) --self:T3( GroupInAir )
return GroupInAir return GroupInAir
end end
end end
@@ -2423,7 +2450,7 @@ end
-- @param #boolean AllUnits (Optional) If true, check whether all units of the group are airborne. -- @param #boolean AllUnits (Optional) If true, check whether all units of the group are airborne.
-- @return #boolean True if at least one (optionally all) unit(s) is(are) airborne or false otherwise. Nil if no unit exists or is alive. -- @return #boolean True if at least one (optionally all) unit(s) is(are) airborne or false otherwise. Nil if no unit exists or is alive.
function GROUP:IsAirborne(AllUnits) function GROUP:IsAirborne(AllUnits)
self:F2( self.GroupName ) --self:F2( self.GroupName )
-- Get all units of the group. -- Get all units of the group.
local units=self:GetUnits() local units=self:GetUnits()
@@ -2634,7 +2661,7 @@ do -- Route methods
-- @param #number Speed (optional) The Speed, if no Speed is given, 80% of maximum Speed of the group is selected. -- @param #number Speed (optional) The Speed, if no Speed is given, 80% of maximum Speed of the group is selected.
-- @return #GROUP self -- @return #GROUP self
function GROUP:RouteRTB( RTBAirbase, Speed ) function GROUP:RouteRTB( RTBAirbase, Speed )
self:F( { RTBAirbase:GetName(), Speed } ) --self:F( { RTBAirbase:GetName(), Speed } )
local DCSGroup = self:GetDCSObject() local DCSGroup = self:GetDCSObject()
@@ -2660,7 +2687,7 @@ do -- Route methods
--local Points={PointFrom, PointAirbase, PointLanding} --local Points={PointFrom, PointAirbase, PointLanding}
-- Debug info. -- Debug info.
self:T3(Points) --self:T3(Points)
-- Get group template. -- Get group template.
local Template=self:GetTemplate() local Template=self:GetTemplate()
@@ -2756,7 +2783,7 @@ do -- Players
end end
if HasPlayers == true then if HasPlayers == true then
self:F2( PlayerNames ) --self:F2( PlayerNames )
return PlayerNames return PlayerNames
end end
@@ -2790,7 +2817,7 @@ end
-- @param #boolean switch If true, emission is enabled. If false, emission is disabled. -- @param #boolean switch If true, emission is enabled. If false, emission is disabled.
-- @return #GROUP self -- @return #GROUP self
function GROUP:EnableEmission(switch) function GROUP:EnableEmission(switch)
self:F2( self.GroupName ) --self:F2( self.GroupName )
local switch = switch or false local switch = switch or false
local DCSUnit = self:GetDCSObject() local DCSUnit = self:GetDCSObject()
@@ -2817,7 +2844,7 @@ end
-- @param #boolean switch If true, Invisible is enabled. If false, Invisible is disabled. -- @param #boolean switch If true, Invisible is enabled. If false, Invisible is disabled.
-- @return #GROUP self -- @return #GROUP self
function GROUP:CommandSetInvisible(switch) function GROUP:CommandSetInvisible(switch)
self:F2( self.GroupName ) --self:F2( self.GroupName )
if switch==nil then if switch==nil then
switch=false switch=false
end end
@@ -2839,7 +2866,7 @@ end
-- @param #boolean switch If true, Immortal is enabled. If false, Immortal is disabled. -- @param #boolean switch If true, Immortal is enabled. If false, Immortal is disabled.
-- @return #GROUP self -- @return #GROUP self
function GROUP:CommandSetImmortal(switch) function GROUP:CommandSetImmortal(switch)
self:F2( self.GroupName ) --self:F2( self.GroupName )
if switch==nil then if switch==nil then
switch=false switch=false
end end
@@ -2852,7 +2879,7 @@ end
-- @param #GROUP self -- @param #GROUP self
-- @return #string Skill String of skill name. -- @return #string Skill String of skill name.
function GROUP:GetSkill() function GROUP:GetSkill()
self:F2( self.GroupName ) --self:F2( self.GroupName )
local unit = self:GetUnit(1) local unit = self:GetUnit(1)
local name = unit:GetName() local name = unit:GetName()
local skill = _DATABASE.Templates.Units[name].Template.skill or "Random" local skill = _DATABASE.Templates.Units[name].Template.skill or "Random"
+2
View File
@@ -528,6 +528,7 @@ function NET:SendChatToPlayer(Message, ToPlayer, FromPlayer)
return self return self
end end
--[[ not in 2.97 MSE any longer
--- Load a specific mission. --- Load a specific mission.
-- @param #NET self -- @param #NET self
-- @param #string Path and Mission -- @param #string Path and Mission
@@ -550,6 +551,7 @@ function NET:LoadNextMission()
outcome = net.load_next_mission() outcome = net.load_next_mission()
return outcome return outcome
end end
--]]
--- Return a table of players currently connected to the server. --- Return a table of players currently connected to the server.
-- @param #NET self -- @param #NET self
@@ -1853,6 +1853,7 @@ do -- Cargo
["HL_KORD"] = 6*POSITIONABLE.DefaultInfantryWeight, ["HL_KORD"] = 6*POSITIONABLE.DefaultInfantryWeight,
["HL_DSHK"] = 6*POSITIONABLE.DefaultInfantryWeight, ["HL_DSHK"] = 6*POSITIONABLE.DefaultInfantryWeight,
["CCKW_353"] = 16*POSITIONABLE.DefaultInfantryWeight, --GMC CCKW 2½-ton 6×6 truck, estimating 16 soldiers, ["CCKW_353"] = 16*POSITIONABLE.DefaultInfantryWeight, --GMC CCKW 2½-ton 6×6 truck, estimating 16 soldiers,
["MaxxPro_MRAP"] = 7*POSITIONABLE.DefaultInfantryWeight,
} }
} }
@@ -226,6 +226,26 @@ function STORAGE:NewFromStaticCargo(StaticCargoName)
return self return self
end end
--- Create a new STORAGE object from an DCS static cargo object.
-- @param #STORAGE self
-- @param #string DynamicCargoName Unit name of the dynamic cargo.
-- @return #STORAGE self
function STORAGE:NewFromDynamicCargo(DynamicCargoName)
-- Inherit everything from BASE class.
local self=BASE:Inherit(self, BASE:New()) -- #STORAGE
self.airbase=Unit.getByName(DynamicCargoName)
if Airbase.getWarehouse then
self.warehouse=Warehouse.getCargoAsWarehouse(self.airbase)
end
self.lid = string.format("STORAGE %s", DynamicCargoName)
return self
end
--- Airbases only - Find a STORAGE in the **_DATABASE** using the name associated airbase. --- Airbases only - Find a STORAGE in the **_DATABASE** using the name associated airbase.
-- @param #STORAGE self -- @param #STORAGE self
+89 -61
View File
@@ -219,6 +219,7 @@ function UNIT:Name()
return self.UnitName return self.UnitName
end end
--[[
--- Get the DCS unit object. --- Get the DCS unit object.
-- @param #UNIT self -- @param #UNIT self
-- @return DCS#Unit The DCS unit object. -- @return DCS#Unit The DCS unit object.
@@ -230,10 +231,34 @@ function UNIT:GetDCSObject()
return DCSUnit return DCSUnit
end end
--if self.DCSUnit then return nil
--return self.DCSUnit end
--end --]]
--- Returns the DCS Unit.
-- @param #UNIT self
-- @return DCS#Unit The DCS Group.
function UNIT:GetDCSObject()
if (not self.LastCallDCSObject) or (self.LastCallDCSObject and timer.getTime() - self.LastCallDCSObject > 1) then
-- Get DCS group.
local DCSUnit = Unit.getByName( self.UnitName )
if DCSUnit then
self.LastCallDCSObject = timer.getTime()
self.DCSObject = DCSUnit
return DCSUnit
else
self.DCSObject = nil
self.LastCallDCSObject = nil
end
else
return self.DCSObject
end
--self:E(string.format("ERROR: Could not get DCS group object of group %s because DCS object could not be found!", tostring(self.UnitName)))
return nil return nil
end end
@@ -243,7 +268,7 @@ end
-- @return #number The height of the group or nil if is not existing or alive. -- @return #number The height of the group or nil if is not existing or alive.
function UNIT:GetAltitude(FromGround) function UNIT:GetAltitude(FromGround)
local DCSUnit = Unit.getByName( self.UnitName ) local DCSUnit = self:GetDCSObject()
if DCSUnit then if DCSUnit then
local altitude = 0 local altitude = 0
@@ -273,12 +298,12 @@ end
-- @param #number Heading The heading of the unit respawn. -- @param #number Heading The heading of the unit respawn.
function UNIT:ReSpawnAt( Coordinate, Heading ) function UNIT:ReSpawnAt( Coordinate, Heading )
self:T( self:Name() ) --self:T( self:Name() )
local SpawnGroupTemplate = UTILS.DeepCopy( _DATABASE:GetGroupTemplateFromUnitName( self:Name() ) ) local SpawnGroupTemplate = UTILS.DeepCopy( _DATABASE:GetGroupTemplateFromUnitName( self:Name() ) )
self:T( SpawnGroupTemplate ) --self:T( SpawnGroupTemplate )
local SpawnGroup = self:GetGroup() local SpawnGroup = self:GetGroup()
self:T( { SpawnGroup = SpawnGroup } ) --self:T( { SpawnGroup = SpawnGroup } )
if SpawnGroup then if SpawnGroup then
@@ -286,10 +311,10 @@ function UNIT:ReSpawnAt( Coordinate, Heading )
SpawnGroupTemplate.x = Coordinate.x SpawnGroupTemplate.x = Coordinate.x
SpawnGroupTemplate.y = Coordinate.z SpawnGroupTemplate.y = Coordinate.z
self:F( #SpawnGroupTemplate.units ) --self:F( #SpawnGroupTemplate.units )
for UnitID, UnitData in pairs( SpawnGroup:GetUnits() or {} ) do for UnitID, UnitData in pairs( SpawnGroup:GetUnits() or {} ) do
local GroupUnit = UnitData -- #UNIT local GroupUnit = UnitData -- #UNIT
self:F( GroupUnit:GetName() ) --self:F( GroupUnit:GetName() )
if GroupUnit:IsAlive() then if GroupUnit:IsAlive() then
local GroupUnitVec3 = GroupUnit:GetVec3() local GroupUnitVec3 = GroupUnit:GetVec3()
local GroupUnitHeading = GroupUnit:GetHeading() local GroupUnitHeading = GroupUnit:GetHeading()
@@ -297,23 +322,23 @@ function UNIT:ReSpawnAt( Coordinate, Heading )
SpawnGroupTemplate.units[UnitID].x = GroupUnitVec3.x SpawnGroupTemplate.units[UnitID].x = GroupUnitVec3.x
SpawnGroupTemplate.units[UnitID].y = GroupUnitVec3.z SpawnGroupTemplate.units[UnitID].y = GroupUnitVec3.z
SpawnGroupTemplate.units[UnitID].heading = GroupUnitHeading SpawnGroupTemplate.units[UnitID].heading = GroupUnitHeading
self:F( { UnitID, SpawnGroupTemplate.units[UnitID], SpawnGroupTemplate.units[UnitID] } ) --self:F( { UnitID, SpawnGroupTemplate.units[UnitID], SpawnGroupTemplate.units[UnitID] } )
end end
end end
end end
for UnitTemplateID, UnitTemplateData in pairs( SpawnGroupTemplate.units ) do for UnitTemplateID, UnitTemplateData in pairs( SpawnGroupTemplate.units ) do
self:T( { UnitTemplateData.name, self:Name() } ) --self:T( { UnitTemplateData.name, self:Name() } )
SpawnGroupTemplate.units[UnitTemplateID].unitId = nil SpawnGroupTemplate.units[UnitTemplateID].unitId = nil
if UnitTemplateData.name == self:Name() then if UnitTemplateData.name == self:Name() then
self:T("Adjusting") --self:T("Adjusting")
SpawnGroupTemplate.units[UnitTemplateID].alt = Coordinate.y SpawnGroupTemplate.units[UnitTemplateID].alt = Coordinate.y
SpawnGroupTemplate.units[UnitTemplateID].x = Coordinate.x SpawnGroupTemplate.units[UnitTemplateID].x = Coordinate.x
SpawnGroupTemplate.units[UnitTemplateID].y = Coordinate.z SpawnGroupTemplate.units[UnitTemplateID].y = Coordinate.z
SpawnGroupTemplate.units[UnitTemplateID].heading = Heading SpawnGroupTemplate.units[UnitTemplateID].heading = Heading
self:F( { UnitTemplateID, SpawnGroupTemplate.units[UnitTemplateID], SpawnGroupTemplate.units[UnitTemplateID] } ) --self:F( { UnitTemplateID, SpawnGroupTemplate.units[UnitTemplateID], SpawnGroupTemplate.units[UnitTemplateID] } )
else else
self:F( SpawnGroupTemplate.units[UnitTemplateID].name ) --self:F( SpawnGroupTemplate.units[UnitTemplateID].name )
local GroupUnit = UNIT:FindByName( SpawnGroupTemplate.units[UnitTemplateID].name ) -- #UNIT local GroupUnit = UNIT:FindByName( SpawnGroupTemplate.units[UnitTemplateID].name ) -- #UNIT
if GroupUnit and GroupUnit:IsAlive() then if GroupUnit and GroupUnit:IsAlive() then
local GroupUnitVec3 = GroupUnit:GetVec3() local GroupUnitVec3 = GroupUnit:GetVec3()
@@ -324,7 +349,7 @@ function UNIT:ReSpawnAt( Coordinate, Heading )
UnitTemplateData.heading = GroupUnitHeading UnitTemplateData.heading = GroupUnitHeading
else else
if SpawnGroupTemplate.units[UnitTemplateID].name ~= self:Name() then if SpawnGroupTemplate.units[UnitTemplateID].name ~= self:Name() then
self:T("nilling") --self:T("nilling")
SpawnGroupTemplate.units[UnitTemplateID].delete = true SpawnGroupTemplate.units[UnitTemplateID].delete = true
end end
end end
@@ -336,7 +361,7 @@ function UNIT:ReSpawnAt( Coordinate, Heading )
while i <= #SpawnGroupTemplate.units do while i <= #SpawnGroupTemplate.units do
local UnitTemplateData = SpawnGroupTemplate.units[i] local UnitTemplateData = SpawnGroupTemplate.units[i]
self:T( UnitTemplateData.name ) --self:T( UnitTemplateData.name )
if UnitTemplateData.delete then if UnitTemplateData.delete then
table.remove( SpawnGroupTemplate.units, i ) table.remove( SpawnGroupTemplate.units, i )
@@ -347,7 +372,7 @@ function UNIT:ReSpawnAt( Coordinate, Heading )
SpawnGroupTemplate.groupId = nil SpawnGroupTemplate.groupId = nil
self:T( SpawnGroupTemplate ) --self:T( SpawnGroupTemplate )
_DATABASE:Spawn( SpawnGroupTemplate ) _DATABASE:Spawn( SpawnGroupTemplate )
end end
@@ -358,7 +383,7 @@ end
-- @param #UNIT self -- @param #UNIT self
-- @return #boolean `true` if Unit is activated. `nil` The DCS Unit is not existing or alive. -- @return #boolean `true` if Unit is activated. `nil` The DCS Unit is not existing or alive.
function UNIT:IsActive() function UNIT:IsActive()
self:F2( self.UnitName ) --self:F2( self.UnitName )
local DCSUnit = self:GetDCSObject() local DCSUnit = self:GetDCSObject()
@@ -395,7 +420,7 @@ end
-- @param #UNIT self -- @param #UNIT self
-- @return #boolean Returns `true` if Unit is alive and active, `false` if it exists but is not active and `nil` if the object does not exist or DCS `isExist` function returns false. -- @return #boolean Returns `true` if Unit is alive and active, `false` if it exists but is not active and `nil` if the object does not exist or DCS `isExist` function returns false.
function UNIT:IsAlive() function UNIT:IsAlive()
self:F3( self.UnitName ) --self:F3( self.UnitName )
local DCSUnit = self:GetDCSObject() -- DCS#Unit local DCSUnit = self:GetDCSObject() -- DCS#Unit
@@ -418,7 +443,7 @@ end
-- @param #UNIT self -- @param #UNIT self
-- @return #string The Callsign of the Unit. -- @return #string The Callsign of the Unit.
function UNIT:GetCallsign() function UNIT:GetCallsign()
self:F2( self.UnitName ) --self:F2( self.UnitName )
local DCSUnit = self:GetDCSObject() local DCSUnit = self:GetDCSObject()
@@ -430,7 +455,7 @@ function UNIT:GetCallsign()
return UnitCallSign return UnitCallSign
end end
self:F( self.ClassName .. " " .. self.UnitName .. " not found!" ) --self:F( self.ClassName .. " " .. self.UnitName .. " not found!" )
return nil return nil
end end
@@ -477,7 +502,7 @@ end
-- @return #string Player Name -- @return #string Player Name
-- @return #nil The DCS Unit is not existing or alive. -- @return #nil The DCS Unit is not existing or alive.
function UNIT:GetPlayerName() function UNIT:GetPlayerName()
self:F( self.UnitName ) --self:F( self.UnitName )
local DCSUnit = self:GetDCSObject() -- DCS#Unit local DCSUnit = self:GetDCSObject() -- DCS#Unit
@@ -551,7 +576,7 @@ end
-- @return #number The Unit number. -- @return #number The Unit number.
-- @return #nil The DCS Unit is not existing or alive. -- @return #nil The DCS Unit is not existing or alive.
function UNIT:GetNumber() function UNIT:GetNumber()
self:F2( self.UnitName ) --self:F2( self.UnitName )
local DCSUnit = self:GetDCSObject() local DCSUnit = self:GetDCSObject()
@@ -568,7 +593,7 @@ end
-- @param #UNIT self -- @param #UNIT self
-- @return #number Speed in km/h. -- @return #number Speed in km/h.
function UNIT:GetSpeedMax() function UNIT:GetSpeedMax()
self:F2( self.UnitName ) --self:F2( self.UnitName )
local Desc = self:GetDesc() local Desc = self:GetDesc()
@@ -585,7 +610,7 @@ end
-- @param #UNIT self -- @param #UNIT self
-- @return #number Range in meters. -- @return #number Range in meters.
function UNIT:GetRange() function UNIT:GetRange()
self:F2( self.UnitName ) --self:F2( self.UnitName )
local Desc = self:GetDesc() local Desc = self:GetDesc()
@@ -607,7 +632,7 @@ end
-- @return #boolean If true, unit is refuelable (checks for the attribute "Refuelable"). -- @return #boolean If true, unit is refuelable (checks for the attribute "Refuelable").
-- @return #number Refueling system (if any): 0=boom, 1=probe. -- @return #number Refueling system (if any): 0=boom, 1=probe.
function UNIT:IsRefuelable() function UNIT:IsRefuelable()
self:F2( self.UnitName ) --self:F2( self.UnitName )
local refuelable=self:HasAttribute("Refuelable") local refuelable=self:HasAttribute("Refuelable")
@@ -626,7 +651,7 @@ end
-- @return #boolean If true, unit is a tanker (checks for the attribute "Tankers"). -- @return #boolean If true, unit is a tanker (checks for the attribute "Tankers").
-- @return #number Refueling system (if any): 0=boom, 1=probe. -- @return #number Refueling system (if any): 0=boom, 1=probe.
function UNIT:IsTanker() function UNIT:IsTanker()
self:F2( self.UnitName ) --self:F2( self.UnitName )
local tanker=self:HasAttribute("Tankers") local tanker=self:HasAttribute("Tankers")
@@ -725,7 +750,7 @@ end
-- @param Wrapper.Unit#UNIT self -- @param Wrapper.Unit#UNIT self
-- @return Wrapper.Group#GROUP The Group of the Unit or `nil` if the unit does not exist. -- @return Wrapper.Group#GROUP The Group of the Unit or `nil` if the unit does not exist.
function UNIT:GetGroup() function UNIT:GetGroup()
self:F2( self.UnitName ) --self:F2( self.UnitName )
local UnitGroup = GROUP:FindByName(self.GroupName) local UnitGroup = GROUP:FindByName(self.GroupName)
if UnitGroup then if UnitGroup then
return UnitGroup return UnitGroup
@@ -749,13 +774,13 @@ end
-- @return #string The name of the DCS Unit. -- @return #string The name of the DCS Unit.
-- @return #nil The DCS Unit is not existing or alive. -- @return #nil The DCS Unit is not existing or alive.
function UNIT:GetPrefix() function UNIT:GetPrefix()
self:F2( self.UnitName ) --self:F2( self.UnitName )
local DCSUnit = self:GetDCSObject() local DCSUnit = self:GetDCSObject()
if DCSUnit then if DCSUnit then
local UnitPrefix = string.match( self.UnitName, ".*#" ):sub( 1, -2 ) local UnitPrefix = string.match( self.UnitName, ".*#" ):sub( 1, -2 )
self:T3( UnitPrefix ) --self:T3( UnitPrefix )
return UnitPrefix return UnitPrefix
end end
@@ -766,7 +791,7 @@ end
-- @param #UNIT self -- @param #UNIT self
-- @return DCS#Unit.Ammo Table with ammuntion of the unit (or nil). This can be a complex table! -- @return DCS#Unit.Ammo Table with ammuntion of the unit (or nil). This can be a complex table!
function UNIT:GetAmmo() function UNIT:GetAmmo()
self:F2( self.UnitName ) --self:F2( self.UnitName )
local DCSUnit = self:GetDCSObject() local DCSUnit = self:GetDCSObject()
if DCSUnit then if DCSUnit then
--local status, unitammo = pcall( --local status, unitammo = pcall(
@@ -958,7 +983,7 @@ end
-- @param #UNIT self -- @param #UNIT self
-- @return DCS#Unit.Sensors Table of sensors. -- @return DCS#Unit.Sensors Table of sensors.
function UNIT:GetSensors() function UNIT:GetSensors()
self:F2( self.UnitName ) --self:F2( self.UnitName )
local DCSUnit = self:GetDCSObject() local DCSUnit = self:GetDCSObject()
@@ -977,7 +1002,7 @@ end
-- @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.
function UNIT:HasSensors( ... ) function UNIT:HasSensors( ... )
self:F2( arg ) --self:F2( arg )
local DCSUnit = self:GetDCSObject() local DCSUnit = self:GetDCSObject()
@@ -993,7 +1018,7 @@ end
-- @param #UNIT self -- @param #UNIT self
-- @return #boolean returns true if the unit is SEADable. -- @return #boolean returns true if the unit is SEADable.
function UNIT:HasSEAD() function UNIT:HasSEAD()
self:F2() --self:F2()
local DCSUnit = self:GetDCSObject() local DCSUnit = self:GetDCSObject()
@@ -1021,7 +1046,7 @@ end
-- @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.
function UNIT:GetRadar() function UNIT:GetRadar()
self:F2( self.UnitName ) --self:F2( self.UnitName )
local DCSUnit = self:GetDCSObject() local DCSUnit = self:GetDCSObject()
@@ -1037,7 +1062,7 @@ end
-- @param #UNIT self -- @param #UNIT self
-- @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 #number The relative amount of fuel (from 0.0 to 1.0) or *nil* if the DCS Unit is not existing or alive.
function UNIT:GetFuel() function UNIT:GetFuel()
self:F3( self.UnitName ) --self:F3( self.UnitName )
local DCSUnit = self:GetDCSObject() local DCSUnit = self:GetDCSObject()
@@ -1054,14 +1079,14 @@ end
-- @param #UNIT self -- @param #UNIT self
-- @return #list<Wrapper.Unit#UNIT> A list of one @{Wrapper.Unit}. -- @return #list<Wrapper.Unit#UNIT> A list of one @{Wrapper.Unit}.
function UNIT:GetUnits() function UNIT:GetUnits()
self:F3( { self.UnitName } ) --self:F3( { self.UnitName } )
local DCSUnit = self:GetDCSObject() local DCSUnit = self:GetDCSObject()
local Units = {} local Units = {}
if DCSUnit then if DCSUnit then
Units[1] = UNIT:Find( DCSUnit ) Units[1] = UNIT:Find( DCSUnit )
self:T3( Units ) -self:T3( Units )
return Units return Units
end end
@@ -1073,7 +1098,7 @@ end
-- @param #UNIT self -- @param #UNIT self
-- @return #number The Unit's health value or -1 if unit does not exist any more. -- @return #number The Unit's health value or -1 if unit does not exist any more.
function UNIT:GetLife() function UNIT:GetLife()
self:F2( self.UnitName ) --self:F2( self.UnitName )
local DCSUnit = self:GetDCSObject() local DCSUnit = self:GetDCSObject()
@@ -1089,7 +1114,7 @@ end
-- @param #UNIT self -- @param #UNIT self
-- @return #number The Unit's initial health value or 0 if unit does not exist any more. -- @return #number The Unit's initial health value or 0 if unit does not exist any more.
function UNIT:GetLife0() function UNIT:GetLife0()
self:F2( self.UnitName ) --self:F2( self.UnitName )
local DCSUnit = self:GetDCSObject() local DCSUnit = self:GetDCSObject()
@@ -1105,7 +1130,7 @@ end
-- @param #UNIT self -- @param #UNIT self
-- @return #number The Unit's relative health value, i.e. a number in [0,1] or -1 if unit does not exist any more. -- @return #number The Unit's relative health value, i.e. a number in [0,1] or -1 if unit does not exist any more.
function UNIT:GetLifeRelative() function UNIT:GetLifeRelative()
self:F2(self.UnitName) --self:F2(self.UnitName)
if self and self:IsAlive() then if self and self:IsAlive() then
local life0=self:GetLife0() local life0=self:GetLife0()
@@ -1120,7 +1145,7 @@ end
-- @param #UNIT self -- @param #UNIT self
-- @return #number The Unit's relative health value, i.e. a number in [0,1] or 1 if unit does not exist any more. -- @return #number The Unit's relative health value, i.e. a number in [0,1] or 1 if unit does not exist any more.
function UNIT:GetDamageRelative() function UNIT:GetDamageRelative()
self:F2(self.UnitName) --self:F2(self.UnitName)
if self and self:IsAlive() then if self and self:IsAlive() then
return 1-self:GetLifeRelative() return 1-self:GetLifeRelative()
@@ -1158,7 +1183,7 @@ end
-- @param #UNIT self -- @param #UNIT self
-- @return #number Unit category from `getDesc().category`. -- @return #number Unit category from `getDesc().category`.
function UNIT:GetUnitCategory() function UNIT:GetUnitCategory()
self:F3( self.UnitName ) --self:F3( self.UnitName )
local DCSUnit = self:GetDCSObject() local DCSUnit = self:GetDCSObject()
if DCSUnit then if DCSUnit then
@@ -1172,7 +1197,7 @@ end
-- @param #UNIT self -- @param #UNIT self
-- @return #string Category name = Helicopter, Airplane, Ground Unit, Ship -- @return #string Category name = Helicopter, Airplane, Ground Unit, Ship
function UNIT:GetCategoryName() function UNIT:GetCategoryName()
self:F3( self.UnitName ) --self:F3( self.UnitName )
local DCSUnit = self:GetDCSObject() local DCSUnit = self:GetDCSObject()
if DCSUnit then if DCSUnit then
@@ -1184,7 +1209,7 @@ function UNIT:GetCategoryName()
[Unit.Category.STRUCTURE] = "Structure", [Unit.Category.STRUCTURE] = "Structure",
} }
local UnitCategory = DCSUnit:getDesc().category local UnitCategory = DCSUnit:getDesc().category
self:T3( UnitCategory ) --self:T3( UnitCategory )
return CategoryNames[UnitCategory] return CategoryNames[UnitCategory]
end end
@@ -1412,7 +1437,7 @@ end
-- @return true If the other DCS Unit is within the radius of the 2D point of the DCS Unit. -- @return true If the other DCS Unit is within the radius of the 2D point of the DCS Unit.
-- @return #nil The DCS Unit is not existing or alive. -- @return #nil The DCS Unit is not existing or alive.
function UNIT:OtherUnitInRadius( AwaitUnit, Radius ) function UNIT:OtherUnitInRadius( AwaitUnit, Radius )
self:F2( { self.UnitName, AwaitUnit.UnitName, Radius } ) --self:F2( { self.UnitName, AwaitUnit.UnitName, Radius } )
local DCSUnit = self:GetDCSObject() local DCSUnit = self:GetDCSObject()
@@ -1421,10 +1446,10 @@ function UNIT:OtherUnitInRadius( AwaitUnit, Radius )
local AwaitUnitVec3 = AwaitUnit:GetVec3() local AwaitUnitVec3 = AwaitUnit:GetVec3()
if (((UnitVec3.x - AwaitUnitVec3.x)^2 + (UnitVec3.z - AwaitUnitVec3.z)^2)^0.5 <= Radius) then if (((UnitVec3.x - AwaitUnitVec3.x)^2 + (UnitVec3.z - AwaitUnitVec3.z)^2)^0.5 <= Radius) then
self:T3( "true" ) --self:T3( "true" )
return true return true
else else
self:T3( "false" ) --self:T3( "false" )
return false return false
end end
end end
@@ -1442,17 +1467,17 @@ end
-- @param #UNIT self -- @param #UNIT self
-- @return #boolean IsFriendly evaluation result. -- @return #boolean IsFriendly evaluation result.
function UNIT:IsFriendly( FriendlyCoalition ) function UNIT:IsFriendly( FriendlyCoalition )
self:F2() --self:F2()
local DCSUnit = self:GetDCSObject() local DCSUnit = self:GetDCSObject()
if DCSUnit then if DCSUnit then
local UnitCoalition = DCSUnit:getCoalition() local UnitCoalition = DCSUnit:getCoalition()
self:T3( { UnitCoalition, FriendlyCoalition } ) --self:T3( { UnitCoalition, FriendlyCoalition } )
local IsFriendlyResult = ( UnitCoalition == FriendlyCoalition ) local IsFriendlyResult = ( UnitCoalition == FriendlyCoalition )
self:F( IsFriendlyResult ) --self:F( IsFriendlyResult )
return IsFriendlyResult return IsFriendlyResult
end end
@@ -1464,17 +1489,17 @@ end
-- @param #UNIT self -- @param #UNIT self
-- @return #boolean Ship category evaluation result. -- @return #boolean Ship category evaluation result.
function UNIT:IsShip() function UNIT:IsShip()
self:F2() --self:F2()
local DCSUnit = self:GetDCSObject() local DCSUnit = self:GetDCSObject()
if DCSUnit then if DCSUnit then
local UnitDescriptor = DCSUnit:getDesc() local UnitDescriptor = DCSUnit:getDesc()
self:T3( { UnitDescriptor.category, Unit.Category.SHIP } ) --self:T3( { UnitDescriptor.category, Unit.Category.SHIP } )
local IsShipResult = ( UnitDescriptor.category == Unit.Category.SHIP ) local IsShipResult = ( UnitDescriptor.category == Unit.Category.SHIP )
self:T3( IsShipResult ) --self:T3( IsShipResult )
return IsShipResult return IsShipResult
end end
@@ -1486,7 +1511,7 @@ end
-- @param #boolean NoHeloCheck If true, no additonal checks for helos are performed. -- @param #boolean NoHeloCheck If true, no additonal checks for helos are performed.
-- @return #boolean Return true if in the air or #nil if the UNIT is not existing or alive. -- @return #boolean Return true if in the air or #nil if the UNIT is not existing or alive.
function UNIT:InAir(NoHeloCheck) function UNIT:InAir(NoHeloCheck)
self:F2( self.UnitName ) --self:F2( self.UnitName )
-- Get DCS unit object. -- Get DCS unit object.
local DCSUnit = self:GetDCSObject() --DCS#Unit local DCSUnit = self:GetDCSObject() --DCS#Unit
@@ -1500,7 +1525,7 @@ function UNIT:InAir(NoHeloCheck)
local UnitCategory = DCSUnit:getDesc().category local UnitCategory = DCSUnit:getDesc().category
-- If DCS says that it is in air, check if this is really the case, since we might have landed on a building where inAir()=true but actually is not. -- If DCS says that it is in air, check if this is really the case, since we might have landed on a building where inAir()=true but actually is not.
-- This is a workaround since DCS currently does not acknoledge that helos land on buildings. -- This is a workaround since DCS currently does not acknowledge that helos land on buildings.
-- Note however, that the velocity check will fail if the ground is moving, e.g. on an aircraft carrier! -- Note however, that the velocity check will fail if the ground is moving, e.g. on an aircraft carrier!
if UnitInAir==true and UnitCategory == Unit.Category.HELICOPTER and (not NoHeloCheck) then if UnitInAir==true and UnitCategory == Unit.Category.HELICOPTER and (not NoHeloCheck) then
local VelocityVec3 = DCSUnit:getVelocity() local VelocityVec3 = DCSUnit:getVelocity()
@@ -1513,7 +1538,7 @@ function UNIT:InAir(NoHeloCheck)
end end
end end
self:T3( UnitInAir ) --self:T3( UnitInAir )
return UnitInAir return UnitInAir
end end
@@ -1708,7 +1733,7 @@ end
-- @param #boolean switch If true, emission is enabled. If false, emission is disabled. -- @param #boolean switch If true, emission is enabled. If false, emission is disabled.
-- @return #UNIT self -- @return #UNIT self
function UNIT:EnableEmission(switch) function UNIT:EnableEmission(switch)
self:F2( self.UnitName ) --self:F2( self.UnitName )
local switch = switch or false local switch = switch or false
@@ -1727,9 +1752,12 @@ end
-- @param #UNIT self -- @param #UNIT self
-- @return #string Skill String of skill name. -- @return #string Skill String of skill name.
function UNIT:GetSkill() function UNIT:GetSkill()
self:F2( self.UnitName ) --self:F2( self.UnitName )
local name = self.UnitName local name = self.UnitName
local skill = _DATABASE.Templates.Units[name].Template.skill or "Random" local skill = "Random"
if _DATABASE.Templates.Units[name] and _DATABASE.Templates.Units[name].Template and _DATABASE.Templates.Units[name].Template.skill then
skill = _DATABASE.Templates.Units[name].Template.skill or "Random"
end
return skill return skill
end end
@@ -1740,7 +1768,7 @@ end
-- @return #string VCN Voice Callsign Number or nil if not set/capable. -- @return #string VCN Voice Callsign Number or nil if not set/capable.
-- @return #string Lead If true, unit is Flight Lead, else false or nil. -- @return #string Lead If true, unit is Flight Lead, else false or nil.
function UNIT:GetSTN() function UNIT:GetSTN()
self:F2(self.UnitName) --self:F2(self.UnitName)
local STN = nil -- STN/TN local STN = nil -- STN/TN
local VCL = nil -- VoiceCallsignLabel local VCL = nil -- VoiceCallsignLabel
local VCN = nil -- VoiceCallsignNumber local VCN = nil -- VoiceCallsignNumber
+1
View File
@@ -47,6 +47,7 @@ Wrapper/Marker.lua
Wrapper/Weapon.lua Wrapper/Weapon.lua
Wrapper/Net.lua Wrapper/Net.lua
Wrapper/Storage.lua Wrapper/Storage.lua
Wrapper/DynamicCargo.lua
Functional/Scoring.lua Functional/Scoring.lua
Functional/CleanUp.lua Functional/CleanUp.lua