mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-08-15 10:47:21 +00:00
Compare commits
152 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b9cf1e46af | ||
|
|
4a04d7cce7 | ||
|
|
35f15435a3 | ||
|
|
4c97d966a2 | ||
|
|
674c6eec81 | ||
|
|
c75c3d8777 | ||
|
|
4fa63986dc | ||
|
|
029f7a3f5c | ||
|
|
e9194c59f4 | ||
|
|
c8d693c8e7 | ||
|
|
2341014882 | ||
|
|
eb15fadcfe | ||
|
|
13fa8f373e | ||
|
|
b318e8ae13 | ||
|
|
7e963bef41 | ||
|
|
933000ffc7 | ||
|
|
9b217e1c97 | ||
|
|
324f4944b4 | ||
|
|
f735f1eb53 | ||
|
|
7149226283 | ||
|
|
4164a5288a | ||
|
|
1992276b07 | ||
|
|
21a7023b7b | ||
|
|
f094716b73 | ||
|
|
4b1888a34d | ||
|
|
b9be3aa7f8 | ||
|
|
fd2dacaefb | ||
|
|
cc60e85901 | ||
|
|
f172f6efeb | ||
|
|
b6b6686873 | ||
|
|
5e724e7a3f | ||
|
|
90f1d1df2a | ||
|
|
a5726c0ed8 | ||
|
|
23ff128ac8 | ||
|
|
7d3fc1740a | ||
|
|
b2a084d669 | ||
|
|
30203668e4 | ||
|
|
ebecc70693 | ||
|
|
74712b6e27 | ||
|
|
40253ea8bb | ||
|
|
4e56078d2a | ||
|
|
4bbf20ca4e | ||
|
|
a462c5a493 | ||
|
|
367014ebf3 | ||
|
|
326b20b08d | ||
|
|
11b0ce6275 | ||
|
|
03763e16d6 | ||
|
|
c1e8ee12e0 | ||
|
|
ac8cc408c1 | ||
|
|
ada38fa3ea | ||
|
|
2ee0597d48 | ||
|
|
7ae4cdc8f1 | ||
|
|
8c92a578ed | ||
|
|
096f2caf9c | ||
|
|
0b37c909b3 | ||
|
|
1b18ae1597 | ||
|
|
c9ac6d73e6 | ||
|
|
0e836973fd | ||
|
|
be40d7be9a | ||
|
|
f3b7740041 | ||
|
|
7d7488db6f | ||
|
|
4964cc2f2d | ||
|
|
f0a4c5b008 | ||
|
|
1b6412821b | ||
|
|
926a0733e4 | ||
|
|
da70f4ce6c | ||
|
|
727cb3276c | ||
|
|
33e63a4819 | ||
|
|
3543b2c79a | ||
|
|
4489efff94 | ||
|
|
6a4bddde99 | ||
|
|
dc2511942c | ||
|
|
f0c257c4a5 | ||
|
|
068d21612f | ||
|
|
773461aad9 | ||
|
|
f9257b2b0d | ||
|
|
9e0f03a3cd | ||
|
|
a467fabdc8 | ||
|
|
a2ab84c45a | ||
|
|
9fd6729967 | ||
|
|
f1d4f1753a | ||
|
|
6d9c3fd0aa | ||
|
|
28ae63bd8d | ||
|
|
42e7e3f94f | ||
|
|
6466c5e95e | ||
|
|
829f5af25f | ||
|
|
0d1147bac4 | ||
|
|
24b47b02e0 | ||
|
|
3cabc07d58 | ||
|
|
b0546b1e60 | ||
|
|
a988e67490 | ||
|
|
2594c5bbf0 | ||
|
|
db70fa341c | ||
|
|
763e3852ac | ||
|
|
8ec86973c6 | ||
|
|
eb2c6ac6f2 | ||
|
|
cbcc893ce5 | ||
|
|
382b049c5f | ||
|
|
a53763221c | ||
|
|
b7bac28113 | ||
|
|
a9edb16554 | ||
|
|
0aeb1fc6af | ||
|
|
eeeeda4e5e | ||
|
|
f5881eda53 | ||
|
|
c1997d9f70 | ||
|
|
bb1caa6642 | ||
|
|
dd5ca93f26 | ||
|
|
1889df4952 | ||
|
|
7ca219748d | ||
|
|
2fc16ba694 | ||
|
|
a4feafab8e | ||
|
|
997baf21a0 | ||
|
|
b126cc00d0 | ||
|
|
09b7922b84 | ||
|
|
7a5b9a75f3 | ||
|
|
4bab2ee1de | ||
|
|
d7defe6f7f | ||
|
|
db869bcb6d | ||
|
|
ea4a1f9ff9 | ||
|
|
20406e40ca | ||
|
|
3b50fee5a0 | ||
|
|
804004198b | ||
|
|
5b8b8a5566 | ||
|
|
0468bacc0b | ||
|
|
7eba1349ae | ||
|
|
b6074a4795 | ||
|
|
36c9f551d9 | ||
|
|
89c3f7310b | ||
|
|
a6b622ed31 | ||
|
|
f1af3a50b8 | ||
|
|
0c90e90c18 | ||
|
|
f97ef25104 | ||
|
|
069c0aa03f | ||
|
|
b145588ed5 | ||
|
|
3ad60a95ce | ||
|
|
ac4b620f16 | ||
|
|
ccada18a6a | ||
|
|
1547d66327 | ||
|
|
8042e8bfaf | ||
|
|
dd7b87e9cd | ||
|
|
460d2768ff | ||
|
|
3c74272749 | ||
|
|
82c409d77a | ||
|
|
195aac4504 | ||
|
|
08d8f3e25f | ||
|
|
6f72697e26 | ||
|
|
0f6439cf9f | ||
|
|
2c10943cb1 | ||
|
|
544db963ea | ||
|
|
207698a2dd | ||
|
|
d1ae2c0f5e | ||
|
|
0392417189 |
@@ -1953,7 +1953,7 @@ local function refct_from_id(id) -- refct = refct_from_id(CTypeID)
|
|||||||
unsigned = refct.unsigned,
|
unsigned = refct.unsigned,
|
||||||
size = bit.band(bit.rshift(ctype.info, 16), 127),
|
size = bit.band(bit.rshift(ctype.info, 16), 127),
|
||||||
}
|
}
|
||||||
refct.bool, refct.const, refct.volatile, refct.unsigned = nil
|
refct.bool, refct.const, refct.volatile, refct.unsigned = nil, nil, nil, nil
|
||||||
end
|
end
|
||||||
|
|
||||||
if CT[4] then -- Merge sibling attributes onto this type.
|
if CT[4] then -- Merge sibling attributes onto this type.
|
||||||
|
|||||||
@@ -18,6 +18,8 @@
|
|||||||
--- The AI_A2A_CAP class implements the core functions to patrol a @{Core.Zone} by an AI @{Wrapper.Group} or @{Wrapper.Group}
|
--- The AI_A2A_CAP class implements the core functions to patrol a @{Core.Zone} by an AI @{Wrapper.Group} or @{Wrapper.Group}
|
||||||
-- and automatically engage any airborne enemies that are within a certain range or within a certain zone.
|
-- and automatically engage any airborne enemies that are within a certain range or within a certain zone.
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- 
|
-- 
|
||||||
--
|
--
|
||||||
-- The AI_A2A_CAP is assigned a @{Wrapper.Group} and this must be done before the AI_A2A_CAP process can be started using the **Start** event.
|
-- The AI_A2A_CAP is assigned a @{Wrapper.Group} and this must be done before the AI_A2A_CAP process can be started using the **Start** event.
|
||||||
|
|||||||
@@ -33,6 +33,8 @@
|
|||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- # QUICK START GUIDE
|
-- # QUICK START GUIDE
|
||||||
--
|
--
|
||||||
-- There are basically two classes available to model an A2A defense system.
|
-- There are basically two classes available to model an A2A defense system.
|
||||||
|
|||||||
@@ -19,6 +19,8 @@
|
|||||||
|
|
||||||
--- Implements the core functions to intercept intruders. Use the Engage trigger to intercept intruders.
|
--- Implements the core functions to intercept intruders. Use the Engage trigger to intercept intruders.
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- The AI_A2A_GCI is assigned a @{Wrapper.Group} and this must be done before the AI_A2A_GCI process can be started using the **Start** event.
|
-- The AI_A2A_GCI is assigned a @{Wrapper.Group} and this must be done before the AI_A2A_GCI process can be started using the **Start** event.
|
||||||
--
|
--
|
||||||
-- The AI will fly towards the random 3D point within the patrol zone, using a random speed within the given altitude and speed limits.
|
-- The AI will fly towards the random 3D point within the patrol zone, using a random speed within the given altitude and speed limits.
|
||||||
|
|||||||
@@ -15,6 +15,8 @@
|
|||||||
|
|
||||||
--- Implements the core functions to patrol a @{Core.Zone} by an AI @{Wrapper.Group} or @{Wrapper.Group}.
|
--- Implements the core functions to patrol a @{Core.Zone} by an AI @{Wrapper.Group} or @{Wrapper.Group}.
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- 
|
-- 
|
||||||
--
|
--
|
||||||
-- The AI_A2A_PATROL is assigned a @{Wrapper.Group} and this must be done before the AI_A2A_PATROL process can be started using the **Start** event.
|
-- The AI_A2A_PATROL is assigned a @{Wrapper.Group} and this must be done before the AI_A2A_PATROL process can be started using the **Start** event.
|
||||||
|
|||||||
@@ -17,6 +17,8 @@
|
|||||||
|
|
||||||
--- Implements the core functions to intercept intruders. Use the Engage trigger to intercept intruders.
|
--- Implements the core functions to intercept intruders. Use the Engage trigger to intercept intruders.
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- # Developer Note
|
-- # Developer Note
|
||||||
--
|
--
|
||||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||||
|
|||||||
@@ -19,6 +19,8 @@
|
|||||||
--
|
--
|
||||||
-- # Developer Note
|
-- # Developer Note
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||||
-- Therefore, this class is considered to be deprecated
|
-- Therefore, this class is considered to be deprecated
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -36,6 +36,8 @@
|
|||||||
--
|
--
|
||||||
-- # QUICK START GUIDE
|
-- # QUICK START GUIDE
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- The following class is available to model an A2G defense system.
|
-- The following class is available to model an A2G defense system.
|
||||||
--
|
--
|
||||||
-- AI_A2G_DISPATCHER is the main A2G defense class that models the A2G defense system.
|
-- AI_A2G_DISPATCHER is the main A2G defense class that models the A2G defense system.
|
||||||
|
|||||||
@@ -20,6 +20,8 @@
|
|||||||
|
|
||||||
--- Implements the core functions to SEAD intruders. Use the Engage trigger to intercept intruders.
|
--- Implements the core functions to SEAD intruders. Use the Engage trigger to intercept intruders.
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- The AI_A2G_SEAD is assigned a @{Wrapper.Group} and this must be done before the AI_A2G_SEAD process can be started using the **Start** event.
|
-- The AI_A2G_SEAD is assigned a @{Wrapper.Group} and this must be done before the AI_A2G_SEAD process can be started using the **Start** event.
|
||||||
--
|
--
|
||||||
-- The AI will fly towards the random 3D point within the patrol zone, using a random speed within the given altitude and speed limits.
|
-- The AI will fly towards the random 3D point within the patrol zone, using a random speed within the given altitude and speed limits.
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
--- The AI_AIR class implements the core functions to operate an AI @{Wrapper.Group}.
|
--- The AI_AIR class implements the core functions to operate an AI @{Wrapper.Group}.
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
--
|
--
|
||||||
-- # 1) AI_AIR constructor
|
-- # 1) AI_AIR constructor
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -36,6 +36,8 @@
|
|||||||
--
|
--
|
||||||
-- # QUICK START GUIDE
|
-- # QUICK START GUIDE
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- The following class is available to model an AIR defense system.
|
-- The following class is available to model an AIR defense system.
|
||||||
--
|
--
|
||||||
-- AI_AIR_DISPATCHER is the main AIR defense class that models the AIR defense system.
|
-- AI_AIR_DISPATCHER is the main AIR defense class that models the AIR defense system.
|
||||||
|
|||||||
@@ -13,12 +13,14 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
-- @type AI_AIR_ENGAGE
|
--- @type AI_AIR_ENGAGE
|
||||||
-- @extends AI.AI_AIR#AI_AIR
|
-- @extends AI.AI_AIR#AI_AIR
|
||||||
|
|
||||||
|
|
||||||
--- Implements the core functions to intercept intruders. Use the Engage trigger to intercept intruders.
|
--- Implements the core functions to intercept intruders. Use the Engage trigger to intercept intruders.
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- The AI_AIR_ENGAGE is assigned a @{Wrapper.Group} and this must be done before the AI_AIR_ENGAGE process can be started using the **Start** event.
|
-- The AI_AIR_ENGAGE is assigned a @{Wrapper.Group} and this must be done before the AI_AIR_ENGAGE process can be started using the **Start** event.
|
||||||
--
|
--
|
||||||
-- The AI will fly towards the random 3D point within the patrol zone, using a random speed within the given altitude and speed limits.
|
-- The AI will fly towards the random 3D point within the patrol zone, using a random speed within the given altitude and speed limits.
|
||||||
|
|||||||
@@ -15,6 +15,8 @@
|
|||||||
--- The AI_AIR_PATROL class implements the core functions to patrol a @{Core.Zone} by an AI @{Wrapper.Group}
|
--- The AI_AIR_PATROL class implements the core functions to patrol a @{Core.Zone} by an AI @{Wrapper.Group}
|
||||||
-- and automatically engage any airborne enemies that are within a certain range or within a certain zone.
|
-- and automatically engage any airborne enemies that are within a certain range or within a certain zone.
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- 
|
-- 
|
||||||
--
|
--
|
||||||
-- The AI_AIR_PATROL is assigned a @{Wrapper.Group} and this must be done before the AI_AIR_PATROL process can be started using the **Start** event.
|
-- The AI_AIR_PATROL is assigned a @{Wrapper.Group} and this must be done before the AI_AIR_PATROL process can be started using the **Start** event.
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
-- @type AI_AIR_SQUADRON
|
--- @type AI_AIR_SQUADRON
|
||||||
-- @extends Core.Base#BASE
|
-- @extends Core.Base#BASE
|
||||||
|
|
||||||
|
|
||||||
@@ -21,6 +21,8 @@
|
|||||||
--
|
--
|
||||||
-- # Developer Note
|
-- # Developer Note
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||||
-- Therefore, this class is considered to be deprecated
|
-- Therefore, this class is considered to be deprecated
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -38,6 +38,8 @@
|
|||||||
|
|
||||||
--- Implements the core functions to provide BattleGround Air Interdiction in an Engage @{Core.Zone} by an AIR @{Wrapper.Controllable} or @{Wrapper.Group}.
|
--- Implements the core functions to provide BattleGround Air Interdiction in an Engage @{Core.Zone} by an AIR @{Wrapper.Controllable} or @{Wrapper.Group}.
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- The AI_BAI_ZONE runs a process. It holds an AI in a Patrol Zone and when the AI is commanded to engage, it will fly to an Engage Zone.
|
-- The AI_BAI_ZONE runs a process. It holds an AI in a Patrol Zone and when the AI is commanded to engage, it will fly to an Engage Zone.
|
||||||
--
|
--
|
||||||
-- 
|
-- 
|
||||||
|
|||||||
@@ -33,8 +33,9 @@
|
|||||||
-- @field Wrapper.Group#GROUP Test
|
-- @field Wrapper.Group#GROUP Test
|
||||||
-- @extends Core.Fsm#FSM_SET
|
-- @extends Core.Fsm#FSM_SET
|
||||||
|
|
||||||
|
--- 
|
||||||
--- Monitors and manages as many replacement AI groups as there are
|
--
|
||||||
|
-- Monitors and manages as many replacement AI groups as there are
|
||||||
-- CLIENTS in a SET\_CLIENT collection, which are not occupied by human players.
|
-- CLIENTS in a SET\_CLIENT collection, which are not occupied by human players.
|
||||||
-- In other words, use AI_BALANCER to simulate human behaviour by spawning in replacement AI in multi player missions.
|
-- In other words, use AI_BALANCER to simulate human behaviour by spawning in replacement AI in multi player missions.
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -39,6 +39,8 @@
|
|||||||
--- Implements the core functions to patrol a @{Core.Zone} by an AI @{Wrapper.Controllable} or @{Wrapper.Group}
|
--- Implements the core functions to patrol a @{Core.Zone} by an AI @{Wrapper.Controllable} or @{Wrapper.Group}
|
||||||
-- and automatically engage any airborne enemies that are within a certain range or within a certain zone.
|
-- and automatically engage any airborne enemies that are within a certain range or within a certain zone.
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- 
|
-- 
|
||||||
--
|
--
|
||||||
-- The AI_CAP_ZONE is assigned a @{Wrapper.Group} and this must be done before the AI_CAP_ZONE process can be started using the **Start** event.
|
-- The AI_CAP_ZONE is assigned a @{Wrapper.Group} and this must be done before the AI_CAP_ZONE process can be started using the **Start** event.
|
||||||
|
|||||||
@@ -38,6 +38,9 @@
|
|||||||
-- @extends AI.AI_Patrol#AI_PATROL_ZONE
|
-- @extends AI.AI_Patrol#AI_PATROL_ZONE
|
||||||
|
|
||||||
--- Implements the core functions to provide Close Air Support in an Engage @{Core.Zone} by an AIR @{Wrapper.Controllable} or @{Wrapper.Group}.
|
--- Implements the core functions to provide Close Air Support in an Engage @{Core.Zone} by an AIR @{Wrapper.Controllable} or @{Wrapper.Group}.
|
||||||
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- The AI_CAS_ZONE runs a process. It holds an AI in a Patrol Zone and when the AI is commanded to engage, it will fly to an Engage Zone.
|
-- The AI_CAS_ZONE runs a process. It holds an AI in a Patrol Zone and when the AI is commanded to engage, it will fly to an Engage Zone.
|
||||||
--
|
--
|
||||||
-- 
|
-- 
|
||||||
|
|||||||
@@ -9,12 +9,14 @@
|
|||||||
-- @module AI.AI_Cargo
|
-- @module AI.AI_Cargo
|
||||||
-- @image Cargo.JPG
|
-- @image Cargo.JPG
|
||||||
|
|
||||||
-- @type AI_CARGO
|
--- @type AI_CARGO
|
||||||
-- @extends Core.Fsm#FSM_CONTROLLABLE
|
-- @extends Core.Fsm#FSM_CONTROLLABLE
|
||||||
|
|
||||||
|
|
||||||
--- Base class for the dynamic cargo handling capability for AI groups.
|
--- Base class for the dynamic cargo handling capability for AI groups.
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- Carriers can be mobilized to intelligently transport infantry and other cargo within the simulation.
|
-- Carriers can be mobilized to intelligently transport infantry and other cargo within the simulation.
|
||||||
-- The AI_CARGO module uses the @{Cargo.Cargo} capabilities within the MOOSE framework.
|
-- The AI_CARGO module uses the @{Cargo.Cargo} capabilities within the MOOSE framework.
|
||||||
-- CARGO derived objects must be declared within the mission to make the AI_CARGO object recognize the cargo.
|
-- CARGO derived objects must be declared within the mission to make the AI_CARGO object recognize the cargo.
|
||||||
|
|||||||
@@ -15,6 +15,8 @@
|
|||||||
|
|
||||||
--- Brings a dynamic cargo handling capability for an AI vehicle group.
|
--- Brings a dynamic cargo handling capability for an AI vehicle group.
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- Armoured Personnel Carriers (APC), Trucks, Jeeps and other ground based carrier equipment can be mobilized to intelligently transport infantry and other cargo within the simulation.
|
-- Armoured Personnel Carriers (APC), Trucks, Jeeps and other ground based carrier equipment can be mobilized to intelligently transport infantry and other cargo within the simulation.
|
||||||
--
|
--
|
||||||
-- The AI_CARGO_APC class uses the @{Cargo.Cargo} capabilities within the MOOSE framework.
|
-- The AI_CARGO_APC class uses the @{Cargo.Cargo} capabilities within the MOOSE framework.
|
||||||
|
|||||||
@@ -15,6 +15,8 @@
|
|||||||
|
|
||||||
--- Brings a dynamic cargo handling capability for an AI airplane group.
|
--- Brings a dynamic cargo handling capability for an AI airplane group.
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- Airplane carrier equipment can be mobilized to intelligently transport infantry and other cargo within the simulation between airbases.
|
-- Airplane carrier equipment can be mobilized to intelligently transport infantry and other cargo within the simulation between airbases.
|
||||||
--
|
--
|
||||||
-- The AI_CARGO_AIRPLANE module uses the @{Cargo.Cargo} capabilities within the MOOSE framework.
|
-- The AI_CARGO_AIRPLANE module uses the @{Cargo.Cargo} capabilities within the MOOSE framework.
|
||||||
|
|||||||
@@ -22,6 +22,8 @@
|
|||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- # The dispatcher concept.
|
-- # The dispatcher concept.
|
||||||
--
|
--
|
||||||
-- Carrier equipment can be mobilized to intelligently transport infantry and other cargo within the simulation.
|
-- Carrier equipment can be mobilized to intelligently transport infantry and other cargo within the simulation.
|
||||||
|
|||||||
@@ -36,6 +36,8 @@
|
|||||||
|
|
||||||
--- A dynamic cargo transportation capability for AI groups.
|
--- A dynamic cargo transportation capability for AI groups.
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- Armoured Personnel APCs (APC), Trucks, Jeeps and other carrier equipment can be mobilized to intelligently transport infantry and other cargo within the simulation.
|
-- Armoured Personnel APCs (APC), Trucks, Jeeps and other carrier equipment can be mobilized to intelligently transport infantry and other cargo within the simulation.
|
||||||
--
|
--
|
||||||
-- The AI_CARGO_DISPATCHER_APC module is derived from the AI_CARGO_DISPATCHER module.
|
-- The AI_CARGO_DISPATCHER_APC module is derived from the AI_CARGO_DISPATCHER module.
|
||||||
|
|||||||
@@ -30,6 +30,8 @@
|
|||||||
|
|
||||||
--- Brings a dynamic cargo handling capability for AI groups.
|
--- Brings a dynamic cargo handling capability for AI groups.
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- Airplanes can be mobilized to intelligently transport infantry and other cargo within the simulation.
|
-- Airplanes can be mobilized to intelligently transport infantry and other cargo within the simulation.
|
||||||
--
|
--
|
||||||
-- The AI_CARGO_DISPATCHER_AIRPLANE module is derived from the AI_CARGO_DISPATCHER module.
|
-- The AI_CARGO_DISPATCHER_AIRPLANE module is derived from the AI_CARGO_DISPATCHER module.
|
||||||
|
|||||||
@@ -31,6 +31,8 @@
|
|||||||
|
|
||||||
--- A dynamic cargo handling capability for AI helicopter groups.
|
--- A dynamic cargo handling capability for AI helicopter groups.
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- Helicopters can be mobilized to intelligently transport infantry and other cargo within the simulation.
|
-- Helicopters can be mobilized to intelligently transport infantry and other cargo within the simulation.
|
||||||
--
|
--
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -29,6 +29,8 @@
|
|||||||
|
|
||||||
--- A dynamic cargo transportation capability for AI groups.
|
--- A dynamic cargo transportation capability for AI groups.
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- Naval vessels can be mobilized to semi-intelligently transport cargo within the simulation.
|
-- Naval vessels can be mobilized to semi-intelligently transport cargo within the simulation.
|
||||||
--
|
--
|
||||||
-- The AI_CARGO_DISPATCHER_SHIP module is derived from the AI_CARGO_DISPATCHER module.
|
-- The AI_CARGO_DISPATCHER_SHIP module is derived from the AI_CARGO_DISPATCHER module.
|
||||||
|
|||||||
@@ -15,6 +15,8 @@
|
|||||||
|
|
||||||
--- Brings a dynamic cargo handling capability for an AI helicopter group.
|
--- Brings a dynamic cargo handling capability for an AI helicopter group.
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- Helicopter carriers can be mobilized to intelligently transport infantry and other cargo within the simulation.
|
-- Helicopter carriers can be mobilized to intelligently transport infantry and other cargo within the simulation.
|
||||||
--
|
--
|
||||||
-- The AI_CARGO_HELICOPTER class uses the @{Cargo.Cargo} capabilities within the MOOSE framework.
|
-- The AI_CARGO_HELICOPTER class uses the @{Cargo.Cargo} capabilities within the MOOSE framework.
|
||||||
|
|||||||
@@ -14,6 +14,8 @@
|
|||||||
|
|
||||||
--- Brings a dynamic cargo handling capability for an AI naval group.
|
--- Brings a dynamic cargo handling capability for an AI naval group.
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- Naval ships can be utilized to transport cargo around the map following naval shipping lanes.
|
-- Naval ships can be utilized to transport cargo around the map following naval shipping lanes.
|
||||||
-- The AI_CARGO_SHIP class uses the @{Cargo.Cargo} capabilities within the MOOSE framework.
|
-- The AI_CARGO_SHIP class uses the @{Cargo.Cargo} capabilities within the MOOSE framework.
|
||||||
-- @{Cargo.Cargo} must be declared within the mission or warehouse to make the AI_CARGO_SHIP recognize the cargo.
|
-- @{Cargo.Cargo} must be declared within the mission or warehouse to make the AI_CARGO_SHIP recognize the cargo.
|
||||||
|
|||||||
@@ -25,6 +25,8 @@
|
|||||||
--
|
--
|
||||||
-- Allows you to interact with escorting AI on your flight and take the lead.
|
-- Allows you to interact with escorting AI on your flight and take the lead.
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- Each escorting group can be commanded with a complete set of radio commands (radio menu in your flight, and then F10).
|
-- Each escorting group can be commanded with a complete set of radio commands (radio menu in your flight, and then F10).
|
||||||
--
|
--
|
||||||
-- The radio commands will vary according the category of the group. The richest set of commands are with helicopters and airPlanes.
|
-- The radio commands will vary according the category of the group. The richest set of commands are with helicopters and airPlanes.
|
||||||
|
|||||||
@@ -23,6 +23,8 @@
|
|||||||
--
|
--
|
||||||
-- # Developer Note
|
-- # Developer Note
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||||
-- Therefore, this class is considered to be deprecated
|
-- Therefore, this class is considered to be deprecated
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -21,6 +21,8 @@
|
|||||||
|
|
||||||
--- Models the assignment of AI escorts to player flights upon request using the radio menu.
|
--- Models the assignment of AI escorts to player flights upon request using the radio menu.
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- # Developer Note
|
-- # Developer Note
|
||||||
--
|
--
|
||||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||||
|
|||||||
@@ -25,6 +25,8 @@
|
|||||||
--
|
--
|
||||||
-- Allows you to interact with escorting AI on your flight and take the lead.
|
-- Allows you to interact with escorting AI on your flight and take the lead.
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- Each escorting group can be commanded with a complete set of radio commands (radio menu in your flight, and then F10).
|
-- Each escorting group can be commanded with a complete set of radio commands (radio menu in your flight, and then F10).
|
||||||
--
|
--
|
||||||
-- The radio commands will vary according the category of the group. The richest set of commands are with helicopters and airPlanes.
|
-- The radio commands will vary according the category of the group. The richest set of commands are with helicopters and airPlanes.
|
||||||
|
|||||||
@@ -41,6 +41,8 @@
|
|||||||
|
|
||||||
--- Build large formations, make AI follow a @{Wrapper.Client#CLIENT} (player) leader or a @{Wrapper.Unit#UNIT} (AI) leader.
|
--- Build large formations, make AI follow a @{Wrapper.Client#CLIENT} (player) leader or a @{Wrapper.Unit#UNIT} (AI) leader.
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- AI_FORMATION makes AI @{Wrapper.Group#GROUP}s fly in formation of various compositions.
|
-- AI_FORMATION makes AI @{Wrapper.Group#GROUP}s fly in formation of various compositions.
|
||||||
-- The AI_FORMATION class models formations in a different manner than the internal DCS formation logic!!!
|
-- The AI_FORMATION class models formations in a different manner than the internal DCS formation logic!!!
|
||||||
-- The purpose of the class is to:
|
-- The purpose of the class is to:
|
||||||
@@ -158,7 +160,6 @@ AI_FORMATION.__Enum.Mode = {
|
|||||||
-- @field #number GroundRadar
|
-- @field #number GroundRadar
|
||||||
-- @field #number Ground
|
-- @field #number Ground
|
||||||
AI_FORMATION.__Enum.ReportType = {
|
AI_FORMATION.__Enum.ReportType = {
|
||||||
Airborne = "*",
|
|
||||||
Airborne = "A",
|
Airborne = "A",
|
||||||
GroundRadar = "R",
|
GroundRadar = "R",
|
||||||
Ground = "G",
|
Ground = "G",
|
||||||
@@ -1222,7 +1223,6 @@ function AI_FORMATION:FollowMe(FollowGroup, ClientUnit, CT1, CV1, CT2, CV2)
|
|||||||
local CVI = {
|
local CVI = {
|
||||||
x = CV2.x + CS * 10 * math.sin(Ca),
|
x = CV2.x + CS * 10 * math.sin(Ca),
|
||||||
y = GH2.y + Inclination, -- + FollowFormation.y,
|
y = GH2.y + Inclination, -- + FollowFormation.y,
|
||||||
y = GH2.y,
|
|
||||||
z = CV2.z + CS * 10 * math.cos(Ca),
|
z = CV2.z + CS * 10 * math.cos(Ca),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -48,6 +48,8 @@
|
|||||||
|
|
||||||
--- Implements the core functions to patrol a @{Core.Zone} by an AI @{Wrapper.Controllable} or @{Wrapper.Group}.
|
--- Implements the core functions to patrol a @{Core.Zone} by an AI @{Wrapper.Controllable} or @{Wrapper.Group}.
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- 
|
-- 
|
||||||
--
|
--
|
||||||
-- The AI_PATROL_ZONE is assigned a @{Wrapper.Group} and this must be done before the AI_PATROL_ZONE process can be started using the **Start** event.
|
-- The AI_PATROL_ZONE is assigned a @{Wrapper.Group} and this must be done before the AI_PATROL_ZONE process can be started using the **Start** event.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
--- **Actions** - ACT_ACCOUNT_ classes **account for** (detect, count & report) various DCS events occurring on UNITs.
|
--- **Actions** - ACT_ACCOUNT_ classes **account for** (detect, count & report) various DCS events occurring on UNITs.
|
||||||
--
|
--
|
||||||
-- 
|
-- 
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
@@ -11,6 +11,8 @@ do -- ACT_ACCOUNT
|
|||||||
|
|
||||||
--- # @{#ACT_ACCOUNT} FSM class, extends @{Core.Fsm#FSM_PROCESS}
|
--- # @{#ACT_ACCOUNT} FSM class, extends @{Core.Fsm#FSM_PROCESS}
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- ## ACT_ACCOUNT state machine:
|
-- ## ACT_ACCOUNT state machine:
|
||||||
--
|
--
|
||||||
-- This class is a state machine: it manages a process that is triggered by events causing state transitions to occur.
|
-- This class is a state machine: it manages a process that is triggered by events causing state transitions to occur.
|
||||||
@@ -133,7 +135,7 @@ do -- ACT_ACCOUNT
|
|||||||
-- @param #string Event
|
-- @param #string Event
|
||||||
-- @param #string From
|
-- @param #string From
|
||||||
-- @param #string To
|
-- @param #string To
|
||||||
function ACT_ACCOUNT:onafterEvent( ProcessUnit, From, Event, To, Event )
|
function ACT_ACCOUNT:onafterEvent( ProcessUnit, From, Event, To )
|
||||||
|
|
||||||
self:__NoMore( 1 )
|
self:__NoMore( 1 )
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- # @{#ACT_ASSIGN} FSM template class, extends @{Core.Fsm#FSM_PROCESS}
|
-- # @{#ACT_ASSIGN} FSM template class, extends @{Core.Fsm#FSM_PROCESS}
|
||||||
--
|
--
|
||||||
-- ## ACT_ASSIGN state machine:
|
-- ## ACT_ASSIGN state machine:
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
--- (SP) (MP) (FSM) Route AI or players through waypoints or to zones.
|
--- (SP) (MP) (FSM) Route AI or players through waypoints or to zones.
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
-- ## ACT_ASSIST state machine:
|
-- ## ACT_ASSIST state machine:
|
||||||
--
|
--
|
||||||
-- This class is a state machine: it manages a process that is triggered by events causing state transitions to occur.
|
-- This class is a state machine: it manages a process that is triggered by events causing state transitions to occur.
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- # @{#ACT_ROUTE} FSM class, extends @{Core.Fsm#FSM_PROCESS}
|
-- # @{#ACT_ROUTE} FSM class, extends @{Core.Fsm#FSM_PROCESS}
|
||||||
--
|
--
|
||||||
-- ## ACT_ROUTE state machine:
|
-- ## ACT_ROUTE state machine:
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- # 1) MOOSE Cargo System.
|
-- # 1) MOOSE Cargo System.
|
||||||
--
|
--
|
||||||
-- #### Those who have used the mission editor, know that the DCS mission editor provides cargo facilities.
|
-- #### Those who have used the mission editor, know that the DCS mission editor provides cargo facilities.
|
||||||
|
|||||||
@@ -22,6 +22,9 @@ do -- CARGO_CRATE
|
|||||||
-- @type CARGO_CRATE
|
-- @type CARGO_CRATE
|
||||||
-- @extends Cargo.Cargo#CARGO_REPRESENTABLE
|
-- @extends Cargo.Cargo#CARGO_REPRESENTABLE
|
||||||
|
|
||||||
|
---
|
||||||
|
-- 
|
||||||
|
--
|
||||||
--- Defines a cargo that is represented by a UNIT object within the simulator, and can be transported by a carrier.
|
--- Defines a cargo that is represented by a UNIT object within the simulator, and can be transported by a carrier.
|
||||||
-- Use the event functions as described above to Load, UnLoad, Board, UnBoard the CARGO\_CRATE objects to and from carriers.
|
-- Use the event functions as described above to Load, UnLoad, Board, UnBoard the CARGO\_CRATE objects to and from carriers.
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ do -- CARGO_GROUP
|
|||||||
-- @extends Cargo.Cargo#CARGO_REPORTABLE
|
-- @extends Cargo.Cargo#CARGO_REPORTABLE
|
||||||
|
|
||||||
--- Defines a cargo that is represented by a @{Wrapper.Group} object within the simulator.
|
--- Defines a cargo that is represented by a @{Wrapper.Group} object within the simulator.
|
||||||
|
--
|
||||||
|
-- 
|
||||||
-- The cargo can be Loaded, UnLoaded, Boarded, UnBoarded to and from Carriers.
|
-- The cargo can be Loaded, UnLoaded, Boarded, UnBoarded to and from Carriers.
|
||||||
--
|
--
|
||||||
-- The above cargo classes are used by the following AI_CARGO_ classes to allow AI groups to transport cargo:
|
-- The above cargo classes are used by the following AI_CARGO_ classes to allow AI groups to transport cargo:
|
||||||
|
|||||||
@@ -32,6 +32,8 @@ do -- CARGO_SLINGLOAD
|
|||||||
--
|
--
|
||||||
-- # Developer Note
|
-- # Developer Note
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||||
-- Therefore, this class is considered to be deprecated
|
-- Therefore, this class is considered to be deprecated
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -30,6 +30,8 @@ do -- CARGO_UNIT
|
|||||||
--
|
--
|
||||||
-- # Developer Note
|
-- # Developer Note
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||||
-- Therefore, this class is considered to be deprecated
|
-- Therefore, this class is considered to be deprecated
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -974,7 +974,7 @@ do -- Scheduling
|
|||||||
-- @param #BASE self
|
-- @param #BASE self
|
||||||
-- @param #number Start Specifies the amount of seconds that will be waited before the scheduling is started, and the event function is called.
|
-- @param #number Start Specifies the amount of seconds that will be waited before the scheduling is started, and the event function is called.
|
||||||
-- @param #function SchedulerFunction The event function to be called when a timer event occurs. The event function needs to accept the parameters specified in SchedulerArguments.
|
-- @param #function SchedulerFunction The event function to be called when a timer event occurs. The event function needs to accept the parameters specified in SchedulerArguments.
|
||||||
-- @param #table ... Optional arguments that can be given as part of scheduler. The arguments need to be given as a table { param1, param 2, ... }.
|
-- @param ... Optional arguments that can be given as part of scheduler. The arguments need to be given as a table { param1, param 2, ... }.
|
||||||
-- @return #string The Schedule ID of the planned schedule.
|
-- @return #string The Schedule ID of the planned schedule.
|
||||||
function BASE:ScheduleOnce( Start, SchedulerFunction, ... )
|
function BASE:ScheduleOnce( Start, SchedulerFunction, ... )
|
||||||
|
|
||||||
|
|||||||
@@ -872,6 +872,8 @@ end
|
|||||||
-- @return Wrapper.Group#GROUP The found GROUP.
|
-- @return Wrapper.Group#GROUP The found GROUP.
|
||||||
function DATABASE:FindGroup( GroupName )
|
function DATABASE:FindGroup( GroupName )
|
||||||
|
|
||||||
|
if type(GroupName) ~= "string" or GroupName == "" then return end
|
||||||
|
|
||||||
local GroupFound = self.GROUPS[GroupName]
|
local GroupFound = self.GROUPS[GroupName]
|
||||||
|
|
||||||
if GroupFound == nil and GroupName ~= nil and self.Templates.Groups[GroupName] == nil then
|
if GroupFound == nil and GroupName ~= nil and self.Templates.Groups[GroupName] == nil then
|
||||||
@@ -1110,7 +1112,7 @@ function DATABASE:_RegisterGroupTemplate( GroupTemplate, CoalitionSide, Category
|
|||||||
self:E("WARNING: Invalid STN "..tostring(UnitTemplate.AddPropAircraft.STN_L16).." for ".. UnitTemplate.name)
|
self:E("WARNING: Invalid STN "..tostring(UnitTemplate.AddPropAircraft.STN_L16).." for ".. UnitTemplate.name)
|
||||||
else
|
else
|
||||||
self.STNS[stn] = UnitTemplate.name
|
self.STNS[stn] = UnitTemplate.name
|
||||||
self:I("Register STN "..tostring(UnitTemplate.AddPropAircraft.STN_L16).." for ".. UnitTemplate.name)
|
self:T("Register STN "..tostring(UnitTemplate.AddPropAircraft.STN_L16).." for ".. UnitTemplate.name)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if UnitTemplate.AddPropAircraft.SADL_TN then
|
if UnitTemplate.AddPropAircraft.SADL_TN then
|
||||||
@@ -1119,7 +1121,7 @@ function DATABASE:_RegisterGroupTemplate( GroupTemplate, CoalitionSide, Category
|
|||||||
self:E("WARNING: Invalid SADL "..tostring(UnitTemplate.AddPropAircraft.SADL_TN).." for ".. UnitTemplate.name)
|
self:E("WARNING: Invalid SADL "..tostring(UnitTemplate.AddPropAircraft.SADL_TN).." for ".. UnitTemplate.name)
|
||||||
else
|
else
|
||||||
self.SADL[sadl] = UnitTemplate.name
|
self.SADL[sadl] = UnitTemplate.name
|
||||||
self:I("Register SADL "..tostring(UnitTemplate.AddPropAircraft.SADL_TN).." for ".. UnitTemplate.name)
|
self:T("Register SADL "..tostring(UnitTemplate.AddPropAircraft.SADL_TN).." for ".. UnitTemplate.name)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -1380,7 +1382,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("WARNING: Template does not exist for client "..tostring(ClientName))
|
self:T("WARNING: Template does not exist for client "..tostring(ClientName))
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1392,7 +1394,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("WARNING: Template does not exist for client "..tostring(ClientName))
|
self:T("WARNING: Template does not exist for client "..tostring(ClientName))
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1404,7 +1406,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("WARNING: Template does not exist for client "..tostring(ClientName))
|
self:T("WARNING: Template does not exist for client "..tostring(ClientName))
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1697,7 +1699,7 @@ function DATABASE:_EventOnBirth( Event )
|
|||||||
if PlayerName then
|
if PlayerName then
|
||||||
|
|
||||||
-- Debug info.
|
-- Debug info.
|
||||||
self:I(string.format("Player '%s' joined unit '%s' of group '%s'", tostring(PlayerName), tostring(Event.IniDCSUnitName), tostring(Event.IniDCSGroupName)))
|
self:I(string.format("Player '%s' joined unit '%s' (%s) of group '%s'", tostring(PlayerName), tostring(Event.IniDCSUnitName), tostring(Event.IniTypeName), tostring(Event.IniDCSGroupName)))
|
||||||
|
|
||||||
-- Add client in case it does not exist already.
|
-- Add client in case it does not exist already.
|
||||||
if client == nil or (client and client:CountPlayers() == 0) then
|
if client == nil or (client and client:CountPlayers() == 0) then
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ MARKEROPS_BASE = {
|
|||||||
ClassName = "MARKEROPS",
|
ClassName = "MARKEROPS",
|
||||||
Tag = "mytag",
|
Tag = "mytag",
|
||||||
Keywords = {},
|
Keywords = {},
|
||||||
version = "0.1.3",
|
version = "0.1.4",
|
||||||
debug = false,
|
debug = false,
|
||||||
Casesensitive = true,
|
Casesensitive = true,
|
||||||
}
|
}
|
||||||
@@ -154,14 +154,7 @@ function MARKEROPS_BASE:OnEventMark(Event)
|
|||||||
self:E("Skipping onEvent. Event or Event.idx unknown.")
|
self:E("Skipping onEvent. Event or Event.idx unknown.")
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
--position
|
|
||||||
local vec3={y=Event.pos.y, x=Event.pos.x, z=Event.pos.z}
|
|
||||||
local coord=COORDINATE:NewFromVec3(vec3)
|
|
||||||
if self.debug then
|
|
||||||
local coordtext = coord:ToStringLLDDM()
|
|
||||||
local text = tostring(Event.text)
|
|
||||||
local m = MESSAGE:New(string.format("Mark added at %s with text: %s",coordtext,text),10,"Info",false):ToAll()
|
|
||||||
end
|
|
||||||
local coalition = Event.MarkCoalition
|
local coalition = Event.MarkCoalition
|
||||||
-- decision
|
-- decision
|
||||||
if Event.id==world.event.S_EVENT_MARK_ADDED then
|
if Event.id==world.event.S_EVENT_MARK_ADDED then
|
||||||
@@ -170,6 +163,12 @@ function MARKEROPS_BASE:OnEventMark(Event)
|
|||||||
local Eventtext = tostring(Event.text)
|
local Eventtext = tostring(Event.text)
|
||||||
if Eventtext~=nil then
|
if Eventtext~=nil then
|
||||||
if self:_MatchTag(Eventtext) then
|
if self:_MatchTag(Eventtext) then
|
||||||
|
local coord=COORDINATE:NewFromVec3({y=Event.pos.y, x=Event.pos.x, z=Event.pos.z})
|
||||||
|
if self.debug then
|
||||||
|
local coordtext = coord:ToStringLLDDM()
|
||||||
|
local text = tostring(Event.text)
|
||||||
|
local m = MESSAGE:New(string.format("Mark added at %s with text: %s",coordtext,text),10,"Info",false):ToAll()
|
||||||
|
end
|
||||||
local matchtable = self:_MatchKeywords(Eventtext)
|
local matchtable = self:_MatchKeywords(Eventtext)
|
||||||
self:MarkAdded(Eventtext,matchtable,coord,Event.idx,coalition,Event.PlayerName,Event)
|
self:MarkAdded(Eventtext,matchtable,coord,Event.idx,coalition,Event.PlayerName,Event)
|
||||||
end
|
end
|
||||||
@@ -180,6 +179,12 @@ function MARKEROPS_BASE:OnEventMark(Event)
|
|||||||
local Eventtext = tostring(Event.text)
|
local Eventtext = tostring(Event.text)
|
||||||
if Eventtext~=nil then
|
if Eventtext~=nil then
|
||||||
if self:_MatchTag(Eventtext) then
|
if self:_MatchTag(Eventtext) then
|
||||||
|
local coord=COORDINATE:NewFromVec3({y=Event.pos.y, x=Event.pos.x, z=Event.pos.z})
|
||||||
|
if self.debug then
|
||||||
|
local coordtext = coord:ToStringLLDDM()
|
||||||
|
local text = tostring(Event.text)
|
||||||
|
local m = MESSAGE:New(string.format("Mark changed at %s with text: %s",coordtext,text),10,"Info",false):ToAll()
|
||||||
|
end
|
||||||
local matchtable = self:_MatchKeywords(Eventtext)
|
local matchtable = self:_MatchKeywords(Eventtext)
|
||||||
self:MarkChanged(Eventtext,matchtable,coord,Event.idx,coalition,Event.PlayerName,Event)
|
self:MarkChanged(Eventtext,matchtable,coord,Event.idx,coalition,Event.PlayerName,Event)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -206,7 +206,7 @@ end
|
|||||||
function MESSAGE:ToGroup( Group, Settings )
|
function MESSAGE:ToGroup( Group, Settings )
|
||||||
self:F( Group.GroupName )
|
self:F( Group.GroupName )
|
||||||
|
|
||||||
if Group then
|
if Group and Group:IsAlive() then
|
||||||
|
|
||||||
if self.MessageType then
|
if self.MessageType then
|
||||||
local Settings = Settings or (Group and _DATABASE:GetPlayerSettings( Group:GetPlayerName() )) or _SETTINGS -- Core.Settings#SETTINGS
|
local Settings = Settings or (Group and _DATABASE:GetPlayerSettings( Group:GetPlayerName() )) or _SETTINGS -- Core.Settings#SETTINGS
|
||||||
@@ -231,7 +231,7 @@ end
|
|||||||
function MESSAGE:ToUnit( Unit, Settings )
|
function MESSAGE:ToUnit( Unit, Settings )
|
||||||
self:F( Unit.IdentifiableName )
|
self:F( Unit.IdentifiableName )
|
||||||
|
|
||||||
if Unit then
|
if Unit and Unit:IsAlive() then
|
||||||
|
|
||||||
if self.MessageType then
|
if self.MessageType then
|
||||||
local Settings = Settings or ( Unit and _DATABASE:GetPlayerSettings( Unit:GetPlayerName() ) ) or _SETTINGS -- Core.Settings#SETTINGS
|
local Settings = Settings or ( Unit and _DATABASE:GetPlayerSettings( Unit:GetPlayerName() ) ) or _SETTINGS -- Core.Settings#SETTINGS
|
||||||
@@ -452,7 +452,7 @@ end
|
|||||||
_MESSAGESRS = {}
|
_MESSAGESRS = {}
|
||||||
|
|
||||||
--- Set up MESSAGE generally to allow Text-To-Speech via SRS and TTS functions. `SetMSRS()` will try to use as many attributes configured with @{Sound.SRS#MSRS.LoadConfigFile}() as possible.
|
--- Set up MESSAGE generally to allow Text-To-Speech via SRS and TTS functions. `SetMSRS()` will try to use as many attributes configured with @{Sound.SRS#MSRS.LoadConfigFile}() as possible.
|
||||||
-- @param #string PathToSRS (optional) Path to SRS Folder, defaults to "C:\\\\Program Files\\\\DCS-SimpleRadio-Standalone" or your configuration file setting.
|
-- @param #string PathToSRS (optional) Path to SRS TTS Folder, defaults to "C:\\\\Program Files\\\\DCS-SimpleRadio-Standalone\\ExternalAudio" or your configuration file setting.
|
||||||
-- @param #number Port Port (optional) number of SRS, defaults to 5002 or your configuration file setting.
|
-- @param #number Port Port (optional) number of SRS, defaults to 5002 or your configuration file setting.
|
||||||
-- @param #string PathToCredentials (optional) Path to credentials file for Google.
|
-- @param #string PathToCredentials (optional) Path to credentials file for Google.
|
||||||
-- @param #number Frequency Frequency in MHz. Can also be given as a #table of frequencies.
|
-- @param #number Frequency Frequency in MHz. Can also be given as a #table of frequencies.
|
||||||
@@ -468,13 +468,13 @@ _MESSAGESRS = {}
|
|||||||
-- @usage
|
-- @usage
|
||||||
-- -- Mind the dot here, not using the colon this time around!
|
-- -- Mind the dot here, not using the colon this time around!
|
||||||
-- -- Needed once only
|
-- -- Needed once only
|
||||||
-- MESSAGE.SetMSRS("D:\\Program Files\\DCS-SimpleRadio-Standalone",5012,nil,127,radio.modulation.FM,"female","en-US",nil,coalition.side.BLUE)
|
-- MESSAGE.SetMSRS("D:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio",5012,nil,127,radio.modulation.FM,"female","en-US",nil,coalition.side.BLUE)
|
||||||
-- -- later on in your code
|
-- -- later on in your code
|
||||||
-- MESSAGE:New("Test message!",15,"SPAWN"):ToSRS()
|
-- MESSAGE:New("Test message!",15,"SPAWN"):ToSRS()
|
||||||
--
|
--
|
||||||
function MESSAGE.SetMSRS(PathToSRS,Port,PathToCredentials,Frequency,Modulation,Gender,Culture,Voice,Coalition,Volume,Label,Coordinate,Backend)
|
function MESSAGE.SetMSRS(PathToSRS,Port,PathToCredentials,Frequency,Modulation,Gender,Culture,Voice,Coalition,Volume,Label,Coordinate,Backend)
|
||||||
|
|
||||||
_MESSAGESRS.PathToSRS = PathToSRS or MSRS.path or "C:\\Program Files\\DCS-SimpleRadio-Standalone"
|
_MESSAGESRS.PathToSRS = PathToSRS or MSRS.path or "C:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio"
|
||||||
|
|
||||||
_MESSAGESRS.frequency = Frequency or MSRS.frequencies or 243
|
_MESSAGESRS.frequency = Frequency or MSRS.frequencies or 243
|
||||||
_MESSAGESRS.modulation = Modulation or MSRS.modulations or radio.modulation.AM
|
_MESSAGESRS.modulation = Modulation or MSRS.modulations or radio.modulation.AM
|
||||||
@@ -535,7 +535,7 @@ end
|
|||||||
-- @usage
|
-- @usage
|
||||||
-- -- Mind the dot here, not using the colon this time around!
|
-- -- Mind the dot here, not using the colon this time around!
|
||||||
-- -- Needed once only
|
-- -- Needed once only
|
||||||
-- MESSAGE.SetMSRS("D:\\Program Files\\DCS-SimpleRadio-Standalone",5012,nil,127,radio.modulation.FM,"female","en-US",nil,coalition.side.BLUE)
|
-- MESSAGE.SetMSRS("D:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio",5012,nil,127,radio.modulation.FM,"female","en-US",nil,coalition.side.BLUE)
|
||||||
-- -- later on in your code
|
-- -- later on in your code
|
||||||
-- MESSAGE:New("Test message!",15,"SPAWN"):ToSRS()
|
-- MESSAGE:New("Test message!",15,"SPAWN"):ToSRS()
|
||||||
--
|
--
|
||||||
@@ -567,7 +567,7 @@ end
|
|||||||
-- @usage
|
-- @usage
|
||||||
-- -- Mind the dot here, not using the colon this time around!
|
-- -- Mind the dot here, not using the colon this time around!
|
||||||
-- -- Needed once only
|
-- -- Needed once only
|
||||||
-- MESSAGE.SetMSRS("D:\\Program Files\\DCS-SimpleRadio-Standalone",5012,nil,127,radio.modulation.FM,"female","en-US",nil,coalition.side.BLUE)
|
-- MESSAGE.SetMSRS("D:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio",5012,nil,127,radio.modulation.FM,"female","en-US",nil,coalition.side.BLUE)
|
||||||
-- -- later on in your code
|
-- -- later on in your code
|
||||||
-- MESSAGE:New("Test message!",15,"SPAWN"):ToSRSBlue()
|
-- MESSAGE:New("Test message!",15,"SPAWN"):ToSRSBlue()
|
||||||
--
|
--
|
||||||
@@ -589,7 +589,7 @@ end
|
|||||||
-- @usage
|
-- @usage
|
||||||
-- -- Mind the dot here, not using the colon this time around!
|
-- -- Mind the dot here, not using the colon this time around!
|
||||||
-- -- Needed once only
|
-- -- Needed once only
|
||||||
-- MESSAGE.SetMSRS("D:\\Program Files\\DCS-SimpleRadio-Standalone",5012,nil,127,radio.modulation.FM,"female","en-US",nil,coalition.side.RED)
|
-- MESSAGE.SetMSRS("D:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio",5012,nil,127,radio.modulation.FM,"female","en-US",nil,coalition.side.RED)
|
||||||
-- -- later on in your code
|
-- -- later on in your code
|
||||||
-- MESSAGE:New("Test message!",15,"SPAWN"):ToSRSRed()
|
-- MESSAGE:New("Test message!",15,"SPAWN"):ToSRSRed()
|
||||||
--
|
--
|
||||||
@@ -611,7 +611,7 @@ end
|
|||||||
-- @usage
|
-- @usage
|
||||||
-- -- Mind the dot here, not using the colon this time around!
|
-- -- Mind the dot here, not using the colon this time around!
|
||||||
-- -- Needed once only
|
-- -- Needed once only
|
||||||
-- MESSAGE.SetMSRS("D:\\Program Files\\DCS-SimpleRadio-Standalone",5012,nil,127,radio.modulation.FM,"female","en-US",nil,coalition.side.NEUTRAL)
|
-- MESSAGE.SetMSRS("D:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio",5012,nil,127,radio.modulation.FM,"female","en-US",nil,coalition.side.NEUTRAL)
|
||||||
-- -- later on in your code
|
-- -- later on in your code
|
||||||
-- MESSAGE:New("Test message!",15,"SPAWN"):ToSRSAll()
|
-- MESSAGE:New("Test message!",15,"SPAWN"):ToSRSAll()
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
do -- COORDINATE
|
do -- COORDINATE
|
||||||
|
|
||||||
---
|
--- Coordinate class
|
||||||
-- @type COORDINATE
|
-- @type COORDINATE
|
||||||
-- @field #string ClassName Name of the class
|
-- @field #string ClassName Name of the class
|
||||||
-- @field #number x Component of the 3D vector.
|
-- @field #number x Component of the 3D vector.
|
||||||
@@ -59,6 +59,10 @@ do -- COORDINATE
|
|||||||
-- * @{#COORDINATE.SmokeOrange}(): To smoke the point in orange.
|
-- * @{#COORDINATE.SmokeOrange}(): To smoke the point in orange.
|
||||||
-- * @{#COORDINATE.SmokeWhite}(): To smoke the point in white.
|
-- * @{#COORDINATE.SmokeWhite}(): To smoke the point in white.
|
||||||
-- * @{#COORDINATE.SmokeGreen}(): To smoke the point in green.
|
-- * @{#COORDINATE.SmokeGreen}(): To smoke the point in green.
|
||||||
|
-- * @{#COORDINATE.SetSmokeOffsetDirection}(): To set an offset point direction for smoke.
|
||||||
|
-- * @{#COORDINATE.SetSmokeOffsetDistance}(): To set an offset point distance for smoke.
|
||||||
|
-- * @{#COORDINATE.SwitchSmokeOffsetOn}(): To set an offset point for smoke to on.
|
||||||
|
-- * @{#COORDINATE.SwitchSmokeOffsetOff}(): To set an offset point for smoke to off.
|
||||||
--
|
--
|
||||||
-- ## 2.2) Flare
|
-- ## 2.2) Flare
|
||||||
--
|
--
|
||||||
@@ -773,7 +777,9 @@ do -- COORDINATE
|
|||||||
-- @return DCS#Vec2 Vec2
|
-- @return DCS#Vec2 Vec2
|
||||||
function COORDINATE:GetRandomVec2InRadius( OuterRadius, InnerRadius )
|
function COORDINATE:GetRandomVec2InRadius( OuterRadius, InnerRadius )
|
||||||
self:F2( { OuterRadius, InnerRadius } )
|
self:F2( { OuterRadius, InnerRadius } )
|
||||||
|
math.random()
|
||||||
|
math.random()
|
||||||
|
math.random()
|
||||||
local Theta = 2 * math.pi * math.random()
|
local Theta = 2 * math.pi * math.random()
|
||||||
local Radials = math.random() + math.random()
|
local Radials = math.random() + math.random()
|
||||||
if Radials > 1 then
|
if Radials > 1 then
|
||||||
@@ -833,6 +839,26 @@ do -- COORDINATE
|
|||||||
return land.getHeight( Vec2 )
|
return land.getHeight( Vec2 )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Returns a table of DCS#Vec3 points representing the terrain profile between two points.
|
||||||
|
-- @param #COORDINATE self
|
||||||
|
-- @param Destination DCS#Vec3 Ending point of the profile.
|
||||||
|
-- @return #table DCS#Vec3 table of the profile
|
||||||
|
function COORDINATE:GetLandProfileVec3(Destination)
|
||||||
|
return land.profile(self:GetVec3(), Destination)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Returns a table of #COORDINATE representing the terrain profile between two points.
|
||||||
|
-- @param #COORDINATE self
|
||||||
|
-- @param Destination #COORDINATE Ending coordinate of the profile.
|
||||||
|
-- @return #table #COORDINATE table of the profile
|
||||||
|
function COORDINATE:GetLandProfileCoordinates(Destination)
|
||||||
|
local points = self:GetLandProfileVec3(Destination:GetVec3())
|
||||||
|
local coords = {}
|
||||||
|
for _, point in ipairs(points) do
|
||||||
|
table.insert(coords, COORDINATE:NewFromVec3(point))
|
||||||
|
end
|
||||||
|
return coords
|
||||||
|
end
|
||||||
|
|
||||||
--- Set the heading of the coordinate, if applicable.
|
--- Set the heading of the coordinate, if applicable.
|
||||||
-- @param #COORDINATE self
|
-- @param #COORDINATE self
|
||||||
@@ -2118,16 +2144,114 @@ do -- COORDINATE
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Smokes the point in a color.
|
--- Create colored smoke the point. The smoke we last up to 5 min (DCS limitation) but you can optionally specify a shorter duration or stop it manually.
|
||||||
-- @param #COORDINATE self
|
-- @param #COORDINATE self
|
||||||
-- @param Utilities.Utils#SMOKECOLOR SmokeColor
|
-- @param #number SmokeColor Color of smoke, e.g. `SMOKECOLOR.Green` for green smoke.
|
||||||
-- @param #string name (Optional) Name if you want to stop the smoke early (normal duration: 5mins)
|
-- @param #number Duration (Optional) Duration of the smoke in seconds. DCS stopps the smoke automatically after 5 min.
|
||||||
function COORDINATE:Smoke( SmokeColor, name )
|
-- @param #number Delay (Optional) Delay before the smoke is started in seconds.
|
||||||
self:F2( { SmokeColor } )
|
-- @param #string Name (Optional) Name if you want to stop the smoke early (normal duration: 5mins)
|
||||||
self.firename = name or "Smoke-"..math.random(1,100000)
|
-- @param #boolean Offset (Optional) If true, offset the smokle a bit.
|
||||||
|
-- @param #number Direction (Optional) If Offset is true this is the direction of the offset, 1-359 (degrees). Default random.
|
||||||
|
-- @param #number Distance (Optional) If Offset is true this is the distance of the offset in meters. Default random 10-20.
|
||||||
|
-- @return #COORDINATE self
|
||||||
|
function COORDINATE:Smoke( SmokeColor, Duration, Delay, Name, Offset,Direction,Distance)
|
||||||
|
self:F2( { SmokeColor, Name, Duration, Delay, Offset } )
|
||||||
|
|
||||||
|
SmokeColor=SmokeColor or SMOKECOLOR.Green
|
||||||
|
|
||||||
|
if Delay and Delay>0 then
|
||||||
|
self:ScheduleOnce(Delay, COORDINATE.Smoke, self, SmokeColor, Duration, 0, Name, Direction,Distance)
|
||||||
|
else
|
||||||
|
|
||||||
|
-- Create a name which is used to stop the smoke manually
|
||||||
|
self.firename = Name or "Smoke-"..math.random(1,100000)
|
||||||
|
|
||||||
|
-- Create smoke
|
||||||
|
if Offset or self.SmokeOffset then
|
||||||
|
local Angle = Direction or self:GetSmokeOffsetDirection()
|
||||||
|
local Distance = Distance or self:GetSmokeOffsetDistance()
|
||||||
|
local newpos = self:Translate(Distance,Angle,true,false)
|
||||||
|
local newvec3 = newpos:GetVec3()
|
||||||
|
trigger.action.smoke( newvec3, SmokeColor, self.firename )
|
||||||
|
else
|
||||||
trigger.action.smoke( self:GetVec3(), SmokeColor, self.firename )
|
trigger.action.smoke( self:GetVec3(), SmokeColor, self.firename )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Stop smoke
|
||||||
|
if Duration and Duration>0 then
|
||||||
|
self:ScheduleOnce(Duration, COORDINATE.StopSmoke, self, self.firename )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get the offset direction when using `COORDINATE:Smoke()`.
|
||||||
|
-- @param #COORDINATE self
|
||||||
|
-- @return #number Direction in degrees.
|
||||||
|
function COORDINATE:GetSmokeOffsetDirection()
|
||||||
|
local direction = self.SmokeOffsetDirection or math.random(1,359)
|
||||||
|
return direction
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set the offset direction when using `COORDINATE:Smoke()`.
|
||||||
|
-- @param #COORDINATE self
|
||||||
|
-- @param #number Direction (Optional) This is the direction of the offset, 1-359 (degrees). Default random.
|
||||||
|
-- @return #COORDINATE self
|
||||||
|
function COORDINATE:SetSmokeOffsetDirection(Direction)
|
||||||
|
if self then
|
||||||
|
self.SmokeOffsetDirection = Direction or math.random(1,359)
|
||||||
|
return self
|
||||||
|
else
|
||||||
|
COORDINATE.SmokeOffsetDirection = Direction or math.random(1,359)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get the offset distance when using `COORDINATE:Smoke()`.
|
||||||
|
-- @param #COORDINATE self
|
||||||
|
-- @return #number Distance Distance in meters.
|
||||||
|
function COORDINATE:GetSmokeOffsetDistance()
|
||||||
|
local distance = self.SmokeOffsetDistance or math.random(10,20)
|
||||||
|
return distance
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set the offset distance when using `COORDINATE:Smoke()`.
|
||||||
|
-- @param #COORDINATE self
|
||||||
|
-- @param #number Distance (Optional) This is the distance of the offset in meters. Default random 10-20.
|
||||||
|
-- @return #COORDINATE self
|
||||||
|
function COORDINATE:SetSmokeOffsetDistance(Distance)
|
||||||
|
if self then
|
||||||
|
self.SmokeOffsetDistance = Distance or math.random(10,20)
|
||||||
|
return self
|
||||||
|
else
|
||||||
|
COORDINATE.SmokeOffsetDistance = Distance or math.random(10,20)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set the offset on when using `COORDINATE:Smoke()`.
|
||||||
|
-- @param #COORDINATE self
|
||||||
|
-- @return #COORDINATE self
|
||||||
|
function COORDINATE:SwitchSmokeOffsetOn()
|
||||||
|
if self then
|
||||||
|
self.SmokeOffset = true
|
||||||
|
return self
|
||||||
|
else
|
||||||
|
COORDINATE.SmokeOffset = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set the offset off when using `COORDINATE:Smoke()`.
|
||||||
|
-- @param #COORDINATE self
|
||||||
|
-- @return #COORDINATE self
|
||||||
|
function COORDINATE:SwitchSmokeOffsetOff()
|
||||||
|
if self then
|
||||||
|
self.SmokeOffset = false
|
||||||
|
return self
|
||||||
|
else
|
||||||
|
COORDINATE.SmokeOffset = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
--- Stops smoking the point in a color.
|
--- Stops smoking the point in a color.
|
||||||
-- @param #COORDINATE self
|
-- @param #COORDINATE self
|
||||||
-- @param #string name (Optional) Name if you want to stop the smoke early (normal duration: 5mins)
|
-- @param #string name (Optional) Name if you want to stop the smoke early (normal duration: 5mins)
|
||||||
@@ -2137,49 +2261,83 @@ do -- COORDINATE
|
|||||||
|
|
||||||
--- Smoke the COORDINATE Green.
|
--- Smoke the COORDINATE Green.
|
||||||
-- @param #COORDINATE self
|
-- @param #COORDINATE self
|
||||||
function COORDINATE:SmokeGreen()
|
-- @param #number Duration (Optional) Duration of the smoke in seconds. DCS stopps the smoke automatically after 5 min.
|
||||||
self:F2()
|
-- @param #number Delay (Optional) Delay before the smoke is started in seconds.
|
||||||
self:Smoke( SMOKECOLOR.Green )
|
-- @return #COORDINATE self
|
||||||
|
function COORDINATE:SmokeGreen(Duration, Delay)
|
||||||
|
self:Smoke( SMOKECOLOR.Green, Duration, Delay )
|
||||||
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Smoke the COORDINATE Red.
|
--- Smoke the COORDINATE Red.
|
||||||
-- @param #COORDINATE self
|
-- @param #COORDINATE self
|
||||||
function COORDINATE:SmokeRed()
|
-- @param #number Duration (Optional) Duration of the smoke in seconds. DCS stopps the smoke automatically after 5 min.
|
||||||
self:F2()
|
-- @param #number Delay (Optional) Delay before the smoke is started in seconds.
|
||||||
self:Smoke( SMOKECOLOR.Red )
|
-- @return #COORDINATE self
|
||||||
|
function COORDINATE:SmokeRed(Duration, Delay)
|
||||||
|
self:Smoke( SMOKECOLOR.Red, Duration, Delay )
|
||||||
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Smoke the COORDINATE White.
|
--- Smoke the COORDINATE White.
|
||||||
-- @param #COORDINATE self
|
-- @param #COORDINATE self
|
||||||
function COORDINATE:SmokeWhite()
|
-- @param #number Duration (Optional) Duration of the smoke in seconds. DCS stopps the smoke automatically after 5 min.
|
||||||
self:F2()
|
-- @param #number Delay (Optional) Delay before the smoke is started in seconds.
|
||||||
self:Smoke( SMOKECOLOR.White )
|
-- @return #COORDINATE self
|
||||||
|
function COORDINATE:SmokeWhite(Duration, Delay)
|
||||||
|
self:Smoke( SMOKECOLOR.White, Duration, Delay )
|
||||||
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Smoke the COORDINATE Orange.
|
--- Smoke the COORDINATE Orange.
|
||||||
-- @param #COORDINATE self
|
-- @param #COORDINATE self
|
||||||
function COORDINATE:SmokeOrange()
|
-- @param #number Duration (Optional) Duration of the smoke in seconds. DCS stopps the smoke automatically after 5 min.
|
||||||
self:F2()
|
-- @param #number Delay (Optional) Delay before the smoke is started in seconds.
|
||||||
self:Smoke( SMOKECOLOR.Orange )
|
-- @return #COORDINATE self
|
||||||
|
function COORDINATE:SmokeOrange(Duration, Delay)
|
||||||
|
self:Smoke( SMOKECOLOR.Orange, Duration, Delay )
|
||||||
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Smoke the COORDINATE Blue.
|
--- Smoke the COORDINATE Blue.
|
||||||
-- @param #COORDINATE self
|
-- @param #COORDINATE self
|
||||||
function COORDINATE:SmokeBlue()
|
-- @param #number Duration (Optional) Duration of the smoke in seconds. DCS stopps the smoke automatically after 5 min.
|
||||||
self:F2()
|
-- @param #number Delay (Optional) Delay before the smoke is started in seconds.
|
||||||
self:Smoke( SMOKECOLOR.Blue )
|
-- @return #COORDINATE self
|
||||||
|
function COORDINATE:SmokeBlue(Duration, Delay)
|
||||||
|
self:Smoke( SMOKECOLOR.Blue, Duration, Delay )
|
||||||
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Big smoke and fire at the coordinate.
|
--- Big smoke and fire at the coordinate.
|
||||||
-- @param #COORDINATE self
|
-- @param #COORDINATE self
|
||||||
-- @param Utilities.Utils#BIGSMOKEPRESET preset Smoke preset (1=small smoke and fire, 2=medium smoke and fire, 3=large smoke and fire, 4=huge smoke and fire, 5=small smoke, 6=medium smoke, 7=large smoke, 8=huge smoke).
|
-- @param #number Preset Smoke preset (1=small smoke and fire, 2=medium smoke and fire, 3=large smoke and fire, 4=huge smoke and fire, 5=small smoke, 6=medium smoke, 7=large smoke, 8=huge smoke).
|
||||||
-- @param #number density (Optional) Smoke density. Number in [0,...,1]. Default 0.5.
|
-- @param #number Density (Optional) Smoke density. Number in [0,...,1]. Default 0.5.
|
||||||
-- @param #string name (Optional) Name of the fire to stop it later again if not using the same COORDINATE object. Defaults to "Fire-" plus a random 5-digit-number.
|
-- @param #number Duration (Optional) Duration of the smoke and fire in seconds.
|
||||||
function COORDINATE:BigSmokeAndFire( preset, density, name )
|
-- @param #number Delay (Optional) Delay before the smoke and fire is started in seconds.
|
||||||
self:F2( { preset=preset, density=density } )
|
-- @param #string Name (Optional) Name of the fire to stop it later again if not using the same COORDINATE object. Defaults to "Fire-" plus a random 5-digit-number.
|
||||||
density=density or 0.5
|
-- @return #COORDINATE self
|
||||||
self.firename = name or "Fire-"..math.random(1,10000)
|
function COORDINATE:BigSmokeAndFire( Preset, Density, Duration, Delay, Name )
|
||||||
trigger.action.effectSmokeBig( self:GetVec3(), preset, density, self.firename )
|
self:F2( { preset=Preset, density=Density } )
|
||||||
|
|
||||||
|
Preset=Preset or BIGSMOKEPRESET.SmallSmokeAndFire
|
||||||
|
Density=Density or 0.5
|
||||||
|
|
||||||
|
if Delay and Delay>0 then
|
||||||
|
self:ScheduleOnce(Delay, COORDINATE.BigSmokeAndFire, self, Preset, Density, Duration, 0, Name)
|
||||||
|
else
|
||||||
|
|
||||||
|
self.firename = Name or "Fire-"..math.random(1,10000)
|
||||||
|
|
||||||
|
trigger.action.effectSmokeBig( self:GetVec3(), Preset, Density, self.firename )
|
||||||
|
|
||||||
|
-- Stop smoke
|
||||||
|
if Duration and Duration>0 then
|
||||||
|
self:ScheduleOnce(Duration, COORDINATE.StopBigSmokeAndFire, self, self.firename )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Stop big smoke and fire at the coordinate.
|
--- Stop big smoke and fire at the coordinate.
|
||||||
@@ -2192,82 +2350,98 @@ do -- COORDINATE
|
|||||||
|
|
||||||
--- Small smoke and fire at the coordinate.
|
--- Small smoke and fire at the coordinate.
|
||||||
-- @param #COORDINATE self
|
-- @param #COORDINATE self
|
||||||
-- @param #number density (Optional) Smoke density. Number between 0 and 1. Default 0.5.
|
-- @param #number Density (Optional) Smoke density. Number between 0 and 1. Default 0.5.
|
||||||
-- @param #string name (Optional) Name of the fire to stop it later again if not using the same COORDINATE object. Defaults to "Fire-" plus a random 5-digit-number.
|
-- @param #number Duration (Optional) Duration of the smoke and fire in seconds.
|
||||||
function COORDINATE:BigSmokeAndFireSmall( density, name )
|
-- @param #number Delay (Optional) Delay before the smoke and fire is started in seconds.
|
||||||
self:F2( { density=density } )
|
-- @param #string Name (Optional) Name of the fire to stop it later again if not using the same COORDINATE object. Defaults to "Fire-" plus a random 5-digit-number.
|
||||||
density=density or 0.5
|
-- @return #COORDINATE self
|
||||||
self:BigSmokeAndFire(BIGSMOKEPRESET.SmallSmokeAndFire, density, name)
|
function COORDINATE:BigSmokeAndFireSmall( Density, Duration, Delay, Name )
|
||||||
|
self:BigSmokeAndFire(BIGSMOKEPRESET.SmallSmokeAndFire, Density, Duration, Delay, Name)
|
||||||
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Medium smoke and fire at the coordinate.
|
--- Medium smoke and fire at the coordinate.
|
||||||
-- @param #COORDINATE self
|
-- @param #COORDINATE self
|
||||||
-- @param #number density (Optional) Smoke density. Number between 0 and 1. Default 0.5.
|
-- @param #number density (Optional) Smoke density. Number between 0 and 1. Default 0.5.
|
||||||
|
-- @param #number Duration (Optional) Duration of the smoke and fire in seconds.
|
||||||
|
-- @param #number Delay (Optional) Delay before the smoke and fire is started in seconds.
|
||||||
-- @param #string name (Optional) Name of the fire to stop it later again if not using the same COORDINATE object. Defaults to "Fire-" plus a random 5-digit-number.
|
-- @param #string name (Optional) Name of the fire to stop it later again if not using the same COORDINATE object. Defaults to "Fire-" plus a random 5-digit-number.
|
||||||
function COORDINATE:BigSmokeAndFireMedium( density, name )
|
-- @return #COORDINATE self
|
||||||
self:F2( { density=density } )
|
function COORDINATE:BigSmokeAndFireMedium( Density, Duration, Delay, Name )
|
||||||
density=density or 0.5
|
self:BigSmokeAndFire(BIGSMOKEPRESET.MediumSmokeAndFire, Density, Duration, Delay, Name)
|
||||||
self:BigSmokeAndFire(BIGSMOKEPRESET.MediumSmokeAndFire, density, name)
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Large smoke and fire at the coordinate.
|
--- Large smoke and fire at the coordinate.
|
||||||
-- @param #COORDINATE self
|
-- @param #COORDINATE self
|
||||||
-- @param #number density (Optional) Smoke density. Number between 0 and 1. Default 0.5.
|
-- @param #number density (Optional) Smoke density. Number between 0 and 1. Default 0.5.
|
||||||
|
-- @param #number Duration (Optional) Duration of the smoke and fire in seconds.
|
||||||
|
-- @param #number Delay (Optional) Delay before the smoke and fire is started in seconds.
|
||||||
-- @param #string name (Optional) Name of the fire to stop it later again if not using the same COORDINATE object. Defaults to "Fire-" plus a random 5-digit-number.
|
-- @param #string name (Optional) Name of the fire to stop it later again if not using the same COORDINATE object. Defaults to "Fire-" plus a random 5-digit-number.
|
||||||
function COORDINATE:BigSmokeAndFireLarge( density, name )
|
-- @return #COORDINATE self
|
||||||
self:F2( { density=density } )
|
function COORDINATE:BigSmokeAndFireLarge( Density, Duration, Delay, Name )
|
||||||
density=density or 0.5
|
self:BigSmokeAndFire(BIGSMOKEPRESET.LargeSmokeAndFire, Density, Duration, Delay, Name)
|
||||||
self:BigSmokeAndFire(BIGSMOKEPRESET.LargeSmokeAndFire, density, name)
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Huge smoke and fire at the coordinate.
|
--- Huge smoke and fire at the coordinate.
|
||||||
-- @param #COORDINATE self
|
-- @param #COORDINATE self
|
||||||
-- @param #number density (Optional) Smoke density. Number between 0 and 1. Default 0.5.
|
-- @param #number density (Optional) Smoke density. Number between 0 and 1. Default 0.5.
|
||||||
|
-- @param #number Duration (Optional) Duration of the smoke and fire in seconds.
|
||||||
|
-- @param #number Delay (Optional) Delay before the smoke and fire is started in seconds.
|
||||||
-- @param #string name (Optional) Name of the fire to stop it later again if not using the same COORDINATE object. Defaults to "Fire-" plus a random 5-digit-number.
|
-- @param #string name (Optional) Name of the fire to stop it later again if not using the same COORDINATE object. Defaults to "Fire-" plus a random 5-digit-number.
|
||||||
function COORDINATE:BigSmokeAndFireHuge( density, name )
|
-- @return #COORDINATE self
|
||||||
self:F2( { density=density } )
|
function COORDINATE:BigSmokeAndFireHuge( Density, Duration, Delay, Name )
|
||||||
density=density or 0.5
|
self:BigSmokeAndFire(BIGSMOKEPRESET.HugeSmokeAndFire, Density, Duration, Delay, Name)
|
||||||
self:BigSmokeAndFire(BIGSMOKEPRESET.HugeSmokeAndFire, density, name)
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Small smoke at the coordinate.
|
--- Small smoke at the coordinate.
|
||||||
-- @param #COORDINATE self
|
-- @param #COORDINATE self
|
||||||
-- @param #number density (Optional) Smoke density. Number between 0 and 1. Default 0.5.
|
-- @param #number density (Optional) Smoke density. Number between 0 and 1. Default 0.5.
|
||||||
|
-- @param #number Duration (Optional) Duration of the smoke and fire in seconds.
|
||||||
|
-- @param #number Delay (Optional) Delay before the smoke and fire is started in seconds.
|
||||||
-- @param #string name (Optional) Name of the fire to stop it later again if not using the same COORDINATE object. Defaults to "Fire-" plus a random 5-digit-number.
|
-- @param #string name (Optional) Name of the fire to stop it later again if not using the same COORDINATE object. Defaults to "Fire-" plus a random 5-digit-number.
|
||||||
function COORDINATE:BigSmokeSmall( density, name )
|
-- @return #COORDINATE self
|
||||||
self:F2( { density=density } )
|
function COORDINATE:BigSmokeSmall( Density, Duration, Delay, Name )
|
||||||
density=density or 0.5
|
self:BigSmokeAndFire(BIGSMOKEPRESET.SmallSmoke, Density, Duration, Delay, Name)
|
||||||
self:BigSmokeAndFire(BIGSMOKEPRESET.SmallSmoke, density, name)
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Medium smoke at the coordinate.
|
--- Medium smoke at the coordinate.
|
||||||
-- @param #COORDINATE self
|
-- @param #COORDINATE self
|
||||||
-- @param number density (Optional) Smoke density. Number between 0 and 1. Default 0.5.
|
-- @param number density (Optional) Smoke density. Number between 0 and 1. Default 0.5.
|
||||||
|
-- @param #number Duration (Optional) Duration of the smoke and fire in seconds.
|
||||||
|
-- @param #number Delay (Optional) Delay before the smoke and fire is started in seconds.
|
||||||
-- @param #string name (Optional) Name of the fire to stop it later again if not using the same COORDINATE object. Defaults to "Fire-" plus a random 5-digit-number.
|
-- @param #string name (Optional) Name of the fire to stop it later again if not using the same COORDINATE object. Defaults to "Fire-" plus a random 5-digit-number.
|
||||||
function COORDINATE:BigSmokeMedium( density, name )
|
-- @return #COORDINATE self
|
||||||
self:F2( { density=density } )
|
function COORDINATE:BigSmokeMedium( Density, Duration, Delay, Name )
|
||||||
density=density or 0.5
|
self:BigSmokeAndFire(BIGSMOKEPRESET.MediumSmoke, Density, Duration, Delay, Name)
|
||||||
self:BigSmokeAndFire(BIGSMOKEPRESET.MediumSmoke, density, name)
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Large smoke at the coordinate.
|
--- Large smoke at the coordinate.
|
||||||
-- @param #COORDINATE self
|
-- @param #COORDINATE self
|
||||||
-- @param #number density (Optional) Smoke density. Number between 0 and 1. Default 0.5.
|
-- @param #number density (Optional) Smoke density. Number between 0 and 1. Default 0.5.
|
||||||
|
-- @param #number Duration (Optional) Duration of the smoke and fire in seconds.
|
||||||
|
-- @param #number Delay (Optional) Delay before the smoke and fire is started in seconds.
|
||||||
-- @param #string name (Optional) Name of the fire to stop it later again if not using the same COORDINATE object. Defaults to "Fire-" plus a random 5-digit-number.
|
-- @param #string name (Optional) Name of the fire to stop it later again if not using the same COORDINATE object. Defaults to "Fire-" plus a random 5-digit-number.
|
||||||
function COORDINATE:BigSmokeLarge( density, name )
|
-- @return #COORDINATE self
|
||||||
self:F2( { density=density } )
|
function COORDINATE:BigSmokeLarge( Density, Duration, Delay, Name )
|
||||||
density=density or 0.5
|
self:BigSmokeAndFire(BIGSMOKEPRESET.LargeSmoke, Density, Duration, Delay, Name)
|
||||||
self:BigSmokeAndFire(BIGSMOKEPRESET.LargeSmoke, density,name)
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Huge smoke at the coordinate.
|
--- Huge smoke at the coordinate.
|
||||||
-- @param #COORDINATE self
|
-- @param #COORDINATE self
|
||||||
-- @param #number density (Optional) Smoke density. Number between 0 and 1. Default 0.5.
|
-- @param #number density (Optional) Smoke density. Number between 0 and 1. Default 0.5.
|
||||||
|
-- @param #number Duration (Optional) Duration of the smoke and fire in seconds.
|
||||||
|
-- @param #number Delay (Optional) Delay before the smoke and fire is started in seconds.
|
||||||
-- @param #string name (Optional) Name of the fire to stop it later again if not using the same COORDINATE object. Defaults to "Fire-" plus a random 5-digit-number.
|
-- @param #string name (Optional) Name of the fire to stop it later again if not using the same COORDINATE object. Defaults to "Fire-" plus a random 5-digit-number.
|
||||||
function COORDINATE:BigSmokeHuge( density, name )
|
-- @return #COORDINATE self
|
||||||
self:F2( { density=density } )
|
function COORDINATE:BigSmokeHuge( Density, Duration, Delay, Name )
|
||||||
density=density or 0.5
|
self:BigSmokeAndFire(BIGSMOKEPRESET.HugeSmoke, Density, Duration, Delay, Name)
|
||||||
self:BigSmokeAndFire(BIGSMOKEPRESET.HugeSmoke, density,name)
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Flares the point in a color.
|
--- Flares the point in a color.
|
||||||
@@ -2921,8 +3095,10 @@ do -- COORDINATE
|
|||||||
local sunrise=UTILS.GetSunRiseAndSet(DayOfYear, Latitude, Longitude, true, Tdiff)
|
local sunrise=UTILS.GetSunRiseAndSet(DayOfYear, Latitude, Longitude, true, Tdiff)
|
||||||
local sunset=UTILS.GetSunRiseAndSet(DayOfYear, Latitude, Longitude, false, Tdiff)
|
local sunset=UTILS.GetSunRiseAndSet(DayOfYear, Latitude, Longitude, false, Tdiff)
|
||||||
|
|
||||||
|
if type(sunrise) == "string" or type(sunset) == "string" then
|
||||||
if sunrise == "N/R" then return false end
|
if sunrise == "N/R" then return false end
|
||||||
if sunrise == "N/S" then return true end
|
if sunset == "N/S" then return true end
|
||||||
|
end
|
||||||
|
|
||||||
local time=UTILS.ClockToSeconds(clock)
|
local time=UTILS.ClockToSeconds(clock)
|
||||||
|
|
||||||
@@ -2941,6 +3117,11 @@ do -- COORDINATE
|
|||||||
-- Todays sun set in sec.
|
-- Todays sun set in sec.
|
||||||
local sunset=self:GetSunset(true)
|
local sunset=self:GetSunset(true)
|
||||||
|
|
||||||
|
if type(sunrise) == "string" or type(sunset) == "string" then
|
||||||
|
if sunrise == "N/R" then return false end
|
||||||
|
if sunset == "N/S" then return true end
|
||||||
|
end
|
||||||
|
|
||||||
-- Seconds passed since midnight.
|
-- Seconds passed since midnight.
|
||||||
local time=UTILS.SecondsOfToday()
|
local time=UTILS.SecondsOfToday()
|
||||||
|
|
||||||
@@ -3639,6 +3820,25 @@ do -- COORDINATE
|
|||||||
return COORDINATE:NewFromVec3( self:GetRandomVec3InRadius( OuterRadius, InnerRadius ) )
|
return COORDINATE:NewFromVec3( self:GetRandomVec3InRadius( OuterRadius, InnerRadius ) )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Search for clear zones in a given area. A powerful and efficient function using Disposition to find clear areas for spawning ground units avoiding trees, water and map scenery.
|
||||||
|
-- @param #number SearchRadius Radius of the search area.
|
||||||
|
-- @param #number PosRadius Required clear radius around each position.
|
||||||
|
-- @param #number NumPositions Number of positions to find.
|
||||||
|
-- @return #table A table of Core.Point#COORDINATE that are clear of map objects within the given PosRadius. nil if no positions are found.
|
||||||
|
function COORDINATE:GetSimpleZones(SearchRadius, PosRadius, NumPositions)
|
||||||
|
local clearPositions = UTILS.GetSimpleZones(self:GetVec3(), SearchRadius, PosRadius, NumPositions)
|
||||||
|
if clearPositions and #clearPositions > 0 then
|
||||||
|
local coords = {}
|
||||||
|
for _, pos in pairs(clearPositions) do
|
||||||
|
local coord = COORDINATE:NewFromVec2(pos)
|
||||||
|
table.insert(coords, coord)
|
||||||
|
end
|
||||||
|
return coords
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
do
|
do
|
||||||
|
|||||||
@@ -175,7 +175,7 @@ function SCHEDULEDISPATCHER:AddSchedule( Scheduler, ScheduleFunction, ScheduleAr
|
|||||||
local Name = Info.name or "?"
|
local Name = Info.name or "?"
|
||||||
|
|
||||||
local ErrorHandler = function( errmsg )
|
local ErrorHandler = function( errmsg )
|
||||||
env.info( "Error in timer function: " .. errmsg )
|
env.info( "Error in timer function: " .. errmsg or "" )
|
||||||
if BASE.Debug ~= nil then
|
if BASE.Debug ~= nil then
|
||||||
env.info( BASE.Debug.traceback() )
|
env.info( BASE.Debug.traceback() )
|
||||||
end
|
end
|
||||||
@@ -326,7 +326,7 @@ function SCHEDULEDISPATCHER:Stop( Scheduler, CallID )
|
|||||||
local Schedule = self.Schedule[Scheduler][CallID] -- #SCHEDULEDISPATCHER.ScheduleData
|
local Schedule = self.Schedule[Scheduler][CallID] -- #SCHEDULEDISPATCHER.ScheduleData
|
||||||
|
|
||||||
-- Only stop when there is a ScheduleID defined for the CallID. So, when the scheduler was stopped before, do nothing.
|
-- Only stop when there is a ScheduleID defined for the CallID. So, when the scheduler was stopped before, do nothing.
|
||||||
if Schedule.ScheduleID then
|
if Schedule and Schedule.ScheduleID then
|
||||||
|
|
||||||
self:T( string.format( "SCHEDULEDISPATCHER stopping scheduler CallID=%s, ScheduleID=%s", tostring( CallID ), tostring( Schedule.ScheduleID ) ) )
|
self:T( string.format( "SCHEDULEDISPATCHER stopping scheduler CallID=%s, ScheduleID=%s", tostring( CallID ), tostring( Schedule.ScheduleID ) ) )
|
||||||
|
|
||||||
|
|||||||
@@ -959,6 +959,25 @@ do -- SET_BASE
|
|||||||
return ObjectNames
|
return ObjectNames
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Get a *new* set table that only contains alive objects.
|
||||||
|
-- @param #SET_BASE self
|
||||||
|
-- @return #table Set table of alive objects.
|
||||||
|
function SET_BASE:GetAliveSet()
|
||||||
|
--self:F2()
|
||||||
|
|
||||||
|
local AliveSet = {}
|
||||||
|
-- Clean the Set before returning with only the alive Objects.
|
||||||
|
for ObjectName, Object in pairs( self.Set ) do
|
||||||
|
if Object then
|
||||||
|
if Object:IsAlive() then
|
||||||
|
AliveSet[#AliveSet+1] = Object
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return AliveSet or {}
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
do
|
do
|
||||||
@@ -1125,25 +1144,25 @@ do
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Get a *new* set that only contains alive groups.
|
--- Get a *new* set table that only contains alive groups.
|
||||||
-- @param #SET_GROUP self
|
-- @param #SET_GROUP self
|
||||||
-- @return #SET_GROUP Set of alive groups.
|
-- @return #table Set of alive groups.
|
||||||
function SET_GROUP:GetAliveSet()
|
function SET_GROUP:GetAliveSet()
|
||||||
--self:F2()
|
--self:F2()
|
||||||
|
|
||||||
local AliveSet = SET_GROUP:New()
|
--local AliveSet = SET_GROUP:New()
|
||||||
|
local AliveSet = {}
|
||||||
-- Clean the Set before returning with only the alive Groups.
|
-- Clean the Set before returning with only the alive Groups.
|
||||||
for GroupName, GroupObject in pairs( self.Set ) do
|
for GroupName, GroupObject in pairs( self.Set ) do
|
||||||
local GroupObject = GroupObject -- Wrapper.Group#GROUP
|
local GroupObject = GroupObject -- Wrapper.Group#GROUP
|
||||||
if GroupObject then
|
if GroupObject then
|
||||||
if GroupObject:IsAlive() then
|
if GroupObject:IsAlive() then
|
||||||
AliveSet:Add( GroupName, GroupObject )
|
AliveSet[GroupName] = GroupObject
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return AliveSet.Set or {}
|
return AliveSet or {}
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Returns a report of of unit types.
|
--- Returns a report of of unit types.
|
||||||
@@ -2595,7 +2614,7 @@ do -- SET_UNIT
|
|||||||
|
|
||||||
--- Gets the alive set.
|
--- Gets the alive set.
|
||||||
-- @param #SET_UNIT self
|
-- @param #SET_UNIT self
|
||||||
-- @return #table Table of SET objects
|
-- @return #table Table of alive UNIT objects
|
||||||
-- @return #SET_UNIT AliveSet
|
-- @return #SET_UNIT AliveSet
|
||||||
function SET_UNIT:GetAliveSet()
|
function SET_UNIT:GetAliveSet()
|
||||||
|
|
||||||
@@ -2603,10 +2622,8 @@ do -- SET_UNIT
|
|||||||
|
|
||||||
-- Clean the Set before returning with only the alive Groups.
|
-- Clean the Set before returning with only the alive Groups.
|
||||||
for GroupName, GroupObject in pairs(self.Set) do
|
for GroupName, GroupObject in pairs(self.Set) do
|
||||||
local GroupObject=GroupObject --Wrapper.Client#CLIENT
|
|
||||||
|
|
||||||
if GroupObject and GroupObject:IsAlive() then
|
if GroupObject and GroupObject:IsAlive() then
|
||||||
AliveSet:Add(GroupName, GroupObject)
|
AliveSet[GroupName] = GroupObject
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -4784,18 +4801,16 @@ do -- SET_CLIENT
|
|||||||
-- @return #table Table of SET objects
|
-- @return #table Table of SET objects
|
||||||
function SET_CLIENT:GetAliveSet()
|
function SET_CLIENT:GetAliveSet()
|
||||||
|
|
||||||
local AliveSet = SET_CLIENT:New()
|
local AliveSet = {}
|
||||||
|
|
||||||
-- Clean the Set before returning with only the alive Groups.
|
-- Clean the Set before returning with only the alive Groups.
|
||||||
for GroupName, GroupObject in pairs(self.Set) do
|
for GroupName, GroupObject in pairs(self.Set) do
|
||||||
local GroupObject=GroupObject --Wrapper.Client#CLIENT
|
|
||||||
|
|
||||||
if GroupObject and GroupObject:IsAlive() then
|
if GroupObject and GroupObject:IsAlive() then
|
||||||
AliveSet:Add(GroupName, GroupObject)
|
AliveSet[GroupName] = GroupObject
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return AliveSet.Set or {}
|
return AliveSet or {}
|
||||||
end
|
end
|
||||||
|
|
||||||
--- [User] Add a custom condition function.
|
--- [User] Add a custom condition function.
|
||||||
@@ -6676,6 +6691,8 @@ do -- SET_ZONE
|
|||||||
--
|
--
|
||||||
-- -- Stop watching after 1 hour
|
-- -- Stop watching after 1 hour
|
||||||
-- zoneset:__TriggerStop(3600)
|
-- zoneset:__TriggerStop(3600)
|
||||||
|
-- -- Call :SetPartlyInside() on any zone (or SET_ZONE) if you want GROUPs to count as inside when any of their units enters even if they are far apart.
|
||||||
|
-- -- Make sure to call :SetPartlyInside() before :Trigger()!.
|
||||||
function SET_ZONE:Trigger(Objects)
|
function SET_ZONE:Trigger(Objects)
|
||||||
--self:I("Added Set_Zone Trigger")
|
--self:I("Added Set_Zone Trigger")
|
||||||
self:AddTransition("*","TriggerStart","TriggerRunning")
|
self:AddTransition("*","TriggerStart","TriggerRunning")
|
||||||
@@ -6726,6 +6743,20 @@ do -- SET_ZONE
|
|||||||
-- @param Core.Zone#ZONE_BASE Zone The zone left.
|
-- @param Core.Zone#ZONE_BASE Zone The zone left.
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Toggle “partly-inside” handling for every zone in the set when those zones are used with :Trigger().
|
||||||
|
-- * Call with no argument or **true** → enable for all.
|
||||||
|
-- * Call with **false** → disable again (handy if it was enabled before).
|
||||||
|
-- @param #SET_ZONE self
|
||||||
|
-- @return #SET_ZONE self
|
||||||
|
function SET_ZONE:SetPartlyInside(state)
|
||||||
|
for _,Zone in pairs(self.Set) do
|
||||||
|
if Zone.SetPartlyInside then
|
||||||
|
Zone:SetPartlyInside(state)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- (Internal) Check the assigned objects for being in/out of the zone
|
--- (Internal) Check the assigned objects for being in/out of the zone
|
||||||
-- @param #SET_ZONE self
|
-- @param #SET_ZONE self
|
||||||
-- @param #boolean fromstart If true, do the init of the objects
|
-- @param #boolean fromstart If true, do the init of the objects
|
||||||
@@ -6761,8 +6792,13 @@ do -- SET_ZONE
|
|||||||
-- has not been tagged previously - wasn't in set!
|
-- has not been tagged previously - wasn't in set!
|
||||||
obj.TriggerInZone[_zone.ZoneName] = false
|
obj.TriggerInZone[_zone.ZoneName] = false
|
||||||
end
|
end
|
||||||
-- is obj in zone?
|
-- is obj in this zone?
|
||||||
local inzone = _zone:IsCoordinateInZone(obj:GetCoordinate())
|
local inzone
|
||||||
|
if _zone.PartlyInside and obj.ClassName == "GROUP" then
|
||||||
|
inzone = obj:IsAnyInZone(_zone) -- TRUE as soon as any unit is inside
|
||||||
|
else
|
||||||
|
inzone = _zone:IsCoordinateInZone(obj:GetCoordinate()) -- original centroid test
|
||||||
|
end
|
||||||
--self:I("Object "..obj:GetName().." is in zone: "..tostring(inzone))
|
--self:I("Object "..obj:GetName().." is in zone: "..tostring(inzone))
|
||||||
if inzone and not obj.TriggerInZone[_zone.ZoneName] then
|
if inzone and not obj.TriggerInZone[_zone.ZoneName] then
|
||||||
-- wasn't in zone before
|
-- wasn't in zone before
|
||||||
|
|||||||
@@ -149,6 +149,7 @@ function SPAWNSTATIC:NewFromStatic(SpawnTemplateName, SpawnCountryID)
|
|||||||
self.CategoryID = CategoryID
|
self.CategoryID = CategoryID
|
||||||
self.CoalitionID = CoalitionID
|
self.CoalitionID = CoalitionID
|
||||||
self.SpawnIndex = 0
|
self.SpawnIndex = 0
|
||||||
|
self.StaticCopyFrom = SpawnTemplateName
|
||||||
else
|
else
|
||||||
error( "SPAWNSTATIC:New: There is no static declared in the mission editor with SpawnTemplatePrefix = '" .. tostring(SpawnTemplateName) .. "'" )
|
error( "SPAWNSTATIC:New: There is no static declared in the mission editor with SpawnTemplatePrefix = '" .. tostring(SpawnTemplateName) .. "'" )
|
||||||
end
|
end
|
||||||
@@ -302,12 +303,16 @@ end
|
|||||||
-- @param #number CallsignID Callsign ID. Default 1 (="London").
|
-- @param #number CallsignID Callsign ID. Default 1 (="London").
|
||||||
-- @param #number Frequency Frequency in MHz. Default 127.5 MHz.
|
-- @param #number Frequency Frequency in MHz. Default 127.5 MHz.
|
||||||
-- @param #number Modulation Modulation 0=AM, 1=FM.
|
-- @param #number Modulation Modulation 0=AM, 1=FM.
|
||||||
|
-- @param #boolean DynamicSpawns If true, allow Dynamic Spawns
|
||||||
|
-- @param #boolean DynamicHotStarts If true, and DynamicSpawns is true, then allow Dynamic Spawns with hot starts.
|
||||||
-- @return #SPAWNSTATIC self
|
-- @return #SPAWNSTATIC self
|
||||||
function SPAWNSTATIC:InitFARP(CallsignID, Frequency, Modulation)
|
function SPAWNSTATIC:InitFARP(CallsignID, Frequency, Modulation, DynamicSpawns,DynamicHotStarts)
|
||||||
self.InitFarp=true
|
self.InitFarp=true
|
||||||
self.InitFarpCallsignID=CallsignID or 1
|
self.InitFarpCallsignID=CallsignID or 1
|
||||||
self.InitFarpFreq=Frequency or 127.5
|
self.InitFarpFreq=Frequency or 127.5
|
||||||
self.InitFarpModu=Modulation or 0
|
self.InitFarpModu=Modulation or 0
|
||||||
|
self.InitFarpDynamicSpawns = DynamicSpawns
|
||||||
|
self.InitFarpDynamicHotStarts = (DynamicSpawns == true and DynamicHotStarts == true) and true or nil
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -459,7 +464,8 @@ end
|
|||||||
function SPAWNSTATIC:SpawnFromZone(Zone, Heading, NewName)
|
function SPAWNSTATIC:SpawnFromZone(Zone, Heading, NewName)
|
||||||
|
|
||||||
-- Spawn the new static at the center of the zone.
|
-- Spawn the new static at the center of the zone.
|
||||||
local Static = self:SpawnFromPointVec2( Zone:GetPointVec2(), Heading, NewName )
|
--local Static = self:SpawnFromPointVec2( Zone:GetPointVec2(), Heading, NewName )
|
||||||
|
local Static = self:SpawnFromCoordinate(Zone:GetCoordinate(), Heading, NewName)
|
||||||
|
|
||||||
return Static
|
return Static
|
||||||
end
|
end
|
||||||
@@ -550,12 +556,20 @@ function SPAWNSTATIC:_SpawnStatic(Template, CountryID)
|
|||||||
TemplateGroup.y=Template.y
|
TemplateGroup.y=Template.y
|
||||||
TemplateGroup.name=Template.name
|
TemplateGroup.name=Template.name
|
||||||
|
|
||||||
|
if self.InitFarpDynamicSpawns == true then
|
||||||
|
TemplateGroup.units[1].dynamicSpawn = true
|
||||||
|
if self.InitFarpDynamicHotStarts == true then
|
||||||
|
TemplateGroup.units[1].allowHotStart = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
self:T("Spawning FARP")
|
self:T("Spawning FARP")
|
||||||
self:T({Template=Template})
|
self:T({Template=Template})
|
||||||
self:T({TemplateGroup=TemplateGroup})
|
self:T({TemplateGroup=TemplateGroup})
|
||||||
|
|
||||||
-- ED's dirty way to spawn FARPS.
|
-- ED's dirty way to spawn FARPS.
|
||||||
Static=coalition.addGroup(CountryID, -1, TemplateGroup)
|
Static=coalition.addGroup(CountryID, -1, TemplateGroup)
|
||||||
|
--Static=coalition.addStaticObject(CountryID, Template)
|
||||||
|
|
||||||
-- Currently DCS 2.8 does not trigger birth events if FARPS are spawned!
|
-- Currently DCS 2.8 does not trigger birth events if FARPS are spawned!
|
||||||
-- We create such an event. The airbase is registered in Core.Event
|
-- We create such an event. The airbase is registered in Core.Event
|
||||||
@@ -595,5 +609,18 @@ function SPAWNSTATIC:_SpawnStatic(Template, CountryID)
|
|||||||
self:ScheduleOnce(0.3, self.SpawnFunctionHook, mystatic, unpack(self.SpawnFunctionArguments))
|
self:ScheduleOnce(0.3, self.SpawnFunctionHook, mystatic, unpack(self.SpawnFunctionArguments))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if self.StaticCopyFrom ~= nil then
|
||||||
|
mystatic.StaticCopyFrom = self.StaticCopyFrom
|
||||||
|
if not _DATABASE.Templates.Statics[Template.name] then
|
||||||
|
local TemplateGroup={}
|
||||||
|
TemplateGroup.units={}
|
||||||
|
TemplateGroup.units[1]=Template
|
||||||
|
TemplateGroup.x=Template.x
|
||||||
|
TemplateGroup.y=Template.y
|
||||||
|
TemplateGroup.name=Template.name
|
||||||
|
_DATABASE:_RegisterStaticTemplate( TemplateGroup, self.CoalitionID, self.CategoryID, CountryID )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
return mystatic
|
return mystatic
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -70,6 +70,7 @@
|
|||||||
-- @field #table Table of any trigger zone properties from the ME. The key is the Name of the property, and the value is the property's Value.
|
-- @field #table Table of any trigger zone properties from the ME. The key is the Name of the property, and the value is the property's Value.
|
||||||
-- @field #number Surface Type of surface. Only determined at the center of the zone!
|
-- @field #number Surface Type of surface. Only determined at the center of the zone!
|
||||||
-- @field #number Checktime Check every Checktime seconds, used for ZONE:Trigger()
|
-- @field #number Checktime Check every Checktime seconds, used for ZONE:Trigger()
|
||||||
|
-- @field #boolean PartlyInside When called, a GROUP is considered inside as soon as any of its units enters the zone even if they are far apart.
|
||||||
-- @extends Core.Fsm#FSM
|
-- @extends Core.Fsm#FSM
|
||||||
|
|
||||||
|
|
||||||
@@ -534,6 +535,19 @@ function ZONE_BASE:GetZoneProbability()
|
|||||||
return self.ZoneProbability
|
return self.ZoneProbability
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Get the coordinate on the radius of the zone nearest to Outsidecoordinate. Useto e.g. find an ingress point.
|
||||||
|
-- @param #ZONE_BASE self
|
||||||
|
-- @param Core.Point#COORDINATE Outsidecoordinate The coordinate outside of the zone from where to look.
|
||||||
|
-- @return Core.Point#COORDINATE CoordinateOnRadius
|
||||||
|
function ZONE_BASE:FindNearestCoordinateOnRadius(Outsidecoordinate)
|
||||||
|
local Vec1 = self:GetVec2()
|
||||||
|
local Radius = self:GetRadius()
|
||||||
|
local Vec2 = Outsidecoordinate:GetVec2()
|
||||||
|
local Point = UTILS.FindNearestPointOnCircle(Vec1,Radius,Vec2)
|
||||||
|
local rc = COORDINATE:NewFromVec2(Point)
|
||||||
|
return rc
|
||||||
|
end
|
||||||
|
|
||||||
--- Get the zone taking into account the randomization probability of a zone to be selected.
|
--- Get the zone taking into account the randomization probability of a zone to be selected.
|
||||||
-- @param #ZONE_BASE self
|
-- @param #ZONE_BASE self
|
||||||
-- @return #ZONE_BASE The zone is selected taking into account the randomization probability factor.
|
-- @return #ZONE_BASE The zone is selected taking into account the randomization probability factor.
|
||||||
@@ -599,6 +613,8 @@ end
|
|||||||
--
|
--
|
||||||
-- -- Stop watching the zone after 1 hour
|
-- -- Stop watching the zone after 1 hour
|
||||||
-- triggerzone:__TriggerStop(3600)
|
-- triggerzone:__TriggerStop(3600)
|
||||||
|
-- -- Call :SetPartlyInside() if you use SET_GROUP to count as inside when any of their units enters even when they are far apart.
|
||||||
|
-- -- Make sure to call :SetPartlyInside() before :Trigger()!
|
||||||
function ZONE_BASE:Trigger(Objects)
|
function ZONE_BASE:Trigger(Objects)
|
||||||
--self:I("Added Zone Trigger")
|
--self:I("Added Zone Trigger")
|
||||||
self:SetStartState("TriggerStopped")
|
self:SetStartState("TriggerStopped")
|
||||||
@@ -667,6 +683,16 @@ function ZONE_BASE:Trigger(Objects)
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Toggle “partly-inside” handling for this zone. To be used before :Trigger().
|
||||||
|
-- * Default:* flag is **false** until you call the method.
|
||||||
|
-- * Call with no argument or with **true** → enable.
|
||||||
|
-- * Call with **false** → disable again (handy if it was enabled before).
|
||||||
|
-- @param #ZONE_BASE self
|
||||||
|
-- @return #ZONE_BASE self
|
||||||
|
function ZONE_BASE:SetPartlyInside(state)
|
||||||
|
self.PartlyInside = state or not ( state == false )
|
||||||
|
return self
|
||||||
|
end
|
||||||
--- (Internal) Check the assigned objects for being in/out of the zone
|
--- (Internal) Check the assigned objects for being in/out of the zone
|
||||||
-- @param #ZONE_BASE self
|
-- @param #ZONE_BASE self
|
||||||
-- @param #boolean fromstart If true, do the init of the objects
|
-- @param #boolean fromstart If true, do the init of the objects
|
||||||
@@ -705,7 +731,12 @@ function ZONE_BASE:_TriggerCheck(fromstart)
|
|||||||
obj.TriggerInZone[self.ZoneName] = false
|
obj.TriggerInZone[self.ZoneName] = false
|
||||||
end
|
end
|
||||||
-- is obj in zone?
|
-- is obj in zone?
|
||||||
local inzone = self:IsCoordinateInZone(obj:GetCoordinate())
|
local inzone
|
||||||
|
if self.PartlyInside and obj.ClassName == "GROUP" then
|
||||||
|
inzone = obj:IsAnyInZone(self) -- TRUE if any unit is inside
|
||||||
|
else
|
||||||
|
inzone = self:IsCoordinateInZone(obj:GetCoordinate()) -- original barycentre test
|
||||||
|
end
|
||||||
--self:I("Object "..obj:GetName().." is in zone: "..tostring(inzone))
|
--self:I("Object "..obj:GetName().." is in zone: "..tostring(inzone))
|
||||||
if inzone and obj.TriggerInZone[self.ZoneName] then
|
if inzone and obj.TriggerInZone[self.ZoneName] then
|
||||||
-- just count
|
-- just count
|
||||||
@@ -1509,6 +1540,26 @@ function ZONE_RADIUS:IsVec3InZone( Vec3 )
|
|||||||
return InZone
|
return InZone
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Search for clear ground spawn zones within this zone. A powerful and efficient function using Disposition to find clear areas for spawning ground units avoiding trees, water and map scenery.
|
||||||
|
-- @param #ZONE_RADIUS self
|
||||||
|
-- @param #number PosRadius Required clear radius around each position.
|
||||||
|
-- @param #number NumPositions Number of positions to find.
|
||||||
|
-- @return #table A table of DCS#Vec2 positions that are clear of map objects within the given PosRadius. nil if no clear positions are found.
|
||||||
|
function ZONE_RADIUS:GetClearZonePositions(PosRadius, NumPositions)
|
||||||
|
return UTILS.GetClearZonePositions(self, PosRadius, NumPositions)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Search for a random clear ground spawn coordinate within this zone. A powerful and efficient function using Disposition to find clear areas for spawning ground units avoiding trees, water and map scenery.
|
||||||
|
-- @param #ZONE_RADIUS self
|
||||||
|
-- @param #number PosRadius (Optional) Required clear radius around each position. (Default is math.min(Radius/10, 200))
|
||||||
|
-- @param #number NumPositions (Optional) Number of positions to find. (Default 50)
|
||||||
|
-- @return Core.Point#COORDINATE A random coordinate for a clear zone. nil if no clear positions are found.
|
||||||
|
-- @return #number Assigned radius for the found zones. nil if no clear positions are found.
|
||||||
|
function ZONE_RADIUS:GetRandomClearZoneCoordinate(PosRadius, NumPositions)
|
||||||
|
return UTILS.GetRandomClearZoneCoordinate(self, PosRadius, NumPositions)
|
||||||
|
end
|
||||||
|
|
||||||
--- Returns a random Vec2 location within the zone.
|
--- Returns a random Vec2 location within the zone.
|
||||||
-- @param #ZONE_RADIUS self
|
-- @param #ZONE_RADIUS self
|
||||||
-- @param #number inner (Optional) Minimal distance from the center of the zone. Default is 0.
|
-- @param #number inner (Optional) Minimal distance from the center of the zone. Default is 0.
|
||||||
@@ -1521,6 +1572,10 @@ function ZONE_RADIUS:GetRandomVec2(inner, outer, surfacetypes)
|
|||||||
local _inner = inner or 0
|
local _inner = inner or 0
|
||||||
local _outer = outer or self:GetRadius()
|
local _outer = outer or self:GetRadius()
|
||||||
|
|
||||||
|
math.random()
|
||||||
|
math.random()
|
||||||
|
math.random()
|
||||||
|
|
||||||
if surfacetypes and type(surfacetypes)~="table" then
|
if surfacetypes and type(surfacetypes)~="table" then
|
||||||
surfacetypes={surfacetypes}
|
surfacetypes={surfacetypes}
|
||||||
end
|
end
|
||||||
@@ -2487,6 +2542,26 @@ function ZONE_POLYGON_BASE:Flush()
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Search for clear ground spawn zones within this zone. A powerful and efficient function using Disposition to find clear areas for spawning ground units avoiding trees, water and map scenery.
|
||||||
|
-- @param #ZONE_POLYGON_BASE self
|
||||||
|
-- @param #number PosRadius Required clear radius around each position.
|
||||||
|
-- @param #number NumPositions Number of positions to find.
|
||||||
|
-- @return #table A table of DCS#Vec2 positions that are clear of map objects within the given PosRadius. nil if no clear positions are found.
|
||||||
|
function ZONE_POLYGON_BASE:GetClearZonePositions(PosRadius, NumPositions)
|
||||||
|
return UTILS.GetClearZonePositions(self, PosRadius, NumPositions)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Search for a random clear ground spawn coordinate within this zone. A powerful and efficient function using Disposition to find clear areas for spawning ground units avoiding trees, water and map scenery.
|
||||||
|
-- @param #ZONE_POLYGON_BASE self
|
||||||
|
-- @param #number PosRadius (Optional) Required clear radius around each position. (Default is math.min(Radius/10, 200))
|
||||||
|
-- @param #number NumPositions (Optional) Number of positions to find. (Default 50)
|
||||||
|
-- @return Core.Point#COORDINATE A random coordinate for a clear zone. nil if no clear positions are found.
|
||||||
|
-- @return #number Assigned radius for the found zones. nil if no clear positions are found.
|
||||||
|
function ZONE_POLYGON_BASE:GetRandomClearZoneCoordinate(PosRadius, NumPositions)
|
||||||
|
return UTILS.GetRandomClearZoneCoordinate(self, PosRadius, NumPositions)
|
||||||
|
end
|
||||||
|
|
||||||
--- Smokes the zone boundaries in a color.
|
--- Smokes the zone boundaries in a color.
|
||||||
-- @param #ZONE_POLYGON_BASE self
|
-- @param #ZONE_POLYGON_BASE self
|
||||||
-- @param #boolean UnBound If true, the tyres will be destroyed.
|
-- @param #boolean UnBound If true, the tyres will be destroyed.
|
||||||
@@ -2865,6 +2940,11 @@ end
|
|||||||
function ZONE_POLYGON_BASE:GetRandomVec2()
|
function ZONE_POLYGON_BASE:GetRandomVec2()
|
||||||
-- make sure we assign weights to the triangles based on their surface area, otherwise
|
-- make sure we assign weights to the triangles based on their surface area, otherwise
|
||||||
-- we'll be more likely to generate random points in smaller triangles
|
-- we'll be more likely to generate random points in smaller triangles
|
||||||
|
|
||||||
|
math.random()
|
||||||
|
math.random()
|
||||||
|
math.random()
|
||||||
|
|
||||||
local weights = {}
|
local weights = {}
|
||||||
for _, triangle in pairs(self._Triangles) do
|
for _, triangle in pairs(self._Triangles) do
|
||||||
weights[triangle] = triangle.SurfaceArea / self.SurfaceArea
|
weights[triangle] = triangle.SurfaceArea / self.SurfaceArea
|
||||||
@@ -3204,12 +3284,7 @@ function ZONE_POLYGON:Scan( ObjectCategories, UnitCategories )
|
|||||||
|
|
||||||
local vectors = self:GetBoundingSquare()
|
local vectors = self:GetBoundingSquare()
|
||||||
|
|
||||||
local minVec3 = {x=vectors.x1, y=0, z=vectors.y1}
|
local ZoneRadius = UTILS.VecDist2D({x=vectors.x1, y=vectors.y1}, {x=vectors.x2, y=vectors.y2})/2
|
||||||
local maxVec3 = {x=vectors.x2, y=0, z=vectors.y2}
|
|
||||||
|
|
||||||
local minmarkcoord = COORDINATE:NewFromVec3(minVec3)
|
|
||||||
local maxmarkcoord = COORDINATE:NewFromVec3(maxVec3)
|
|
||||||
local ZoneRadius = minmarkcoord:Get2DDistance(maxmarkcoord)/2
|
|
||||||
-- self:I("Scan Radius:" ..ZoneRadius)
|
-- self:I("Scan Radius:" ..ZoneRadius)
|
||||||
local CenterVec3 = self:GetCoordinate():GetVec3()
|
local CenterVec3 = self:GetCoordinate():GetVec3()
|
||||||
|
|
||||||
|
|||||||
@@ -198,7 +198,7 @@ end -- env
|
|||||||
|
|
||||||
do -- radio
|
do -- radio
|
||||||
|
|
||||||
---@type radio
|
--@type radio
|
||||||
-- @field #radio.modulation modulation
|
-- @field #radio.modulation modulation
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -141,7 +141,6 @@ FOX = {
|
|||||||
explosiondist = 200,
|
explosiondist = 200,
|
||||||
explosiondist2 = 500,
|
explosiondist2 = 500,
|
||||||
bigmissilemass = 50,
|
bigmissilemass = 50,
|
||||||
destroy = nil,
|
|
||||||
dt50 = 5,
|
dt50 = 5,
|
||||||
dt10 = 1,
|
dt10 = 1,
|
||||||
dt05 = 0.5,
|
dt05 = 0.5,
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
-- @module Functional.Mantis
|
-- @module Functional.Mantis
|
||||||
-- @image Functional.Mantis.jpg
|
-- @image Functional.Mantis.jpg
|
||||||
--
|
--
|
||||||
-- Last Update: Mar 2025
|
-- Last Update: August 2025
|
||||||
|
|
||||||
-------------------------------------------------------------------------
|
-------------------------------------------------------------------------
|
||||||
--- **MANTIS** class, extends Core.Base#BASE
|
--- **MANTIS** class, extends Core.Base#BASE
|
||||||
@@ -62,7 +62,9 @@
|
|||||||
-- @field #table FilterZones Table of Core.Zone#ZONE Zones Consider SAM groups in this zone(s) only for this MANTIS instance, must be handed as #table of Zone objects.
|
-- @field #table FilterZones Table of Core.Zone#ZONE Zones Consider SAM groups in this zone(s) only for this MANTIS instance, must be handed as #table of Zone objects.
|
||||||
-- @field #boolean SmokeDecoy If true, smoke short range SAM units as decoy if a plane is in firing range.
|
-- @field #boolean SmokeDecoy If true, smoke short range SAM units as decoy if a plane is in firing range.
|
||||||
-- @field #number SmokeDecoyColor Color to use, defaults to SMOKECOLOR.White
|
-- @field #number SmokeDecoyColor Color to use, defaults to SMOKECOLOR.White
|
||||||
-- @field #number checkcounter Counter for SAM Table refreshes
|
-- @field #number checkcounter Counter for SAM Table refreshes.
|
||||||
|
-- @field #number DLinkCacheTime Seconds after which cached contacts in DLink will decay.
|
||||||
|
-- @field #boolean logsamstatus Log SAM status in dcs.log every cycle if true
|
||||||
-- @extends Core.Base#BASE
|
-- @extends Core.Base#BASE
|
||||||
|
|
||||||
|
|
||||||
@@ -74,10 +76,9 @@
|
|||||||
--
|
--
|
||||||
-- * Moose derived Modular, Automatic and Network capable Targeting and Interception System.
|
-- * Moose derived Modular, Automatic and Network capable Targeting and Interception System.
|
||||||
-- * Controls a network of SAM sites. Uses detection to switch on the SAM site closest to the enemy.
|
-- * Controls a network of SAM sites. Uses detection to switch on the SAM site closest to the enemy.
|
||||||
-- * **Automatic mode** (default since 0.8) will set-up your SAM site network automatically for you
|
-- * **Automatic mode** (default) will set-up your SAM site network automatically for you.
|
||||||
-- * **Classic mode** behaves like before
|
-- * Leverage evasiveness from SEAD, leverage attack range setting.
|
||||||
-- * Leverage evasiveness from SEAD, leverage attack range setting
|
-- * Automatic setup of SHORAD based on groups of the class "short-range".
|
||||||
-- * Automatic setup of SHORAD based on groups of the class "short-range"
|
|
||||||
--
|
--
|
||||||
-- # 0. Base considerations and naming conventions
|
-- # 0. Base considerations and naming conventions
|
||||||
--
|
--
|
||||||
@@ -107,10 +108,15 @@
|
|||||||
-- * Patriot
|
-- * Patriot
|
||||||
-- * Rapier
|
-- * Rapier
|
||||||
-- * Roland
|
-- * Roland
|
||||||
|
-- * IRIS-T SLM
|
||||||
|
-- * Pantsir S1
|
||||||
|
-- * TOR M2
|
||||||
|
-- * C-RAM
|
||||||
-- * Silkworm (though strictly speaking this is a surface to ship missile)
|
-- * Silkworm (though strictly speaking this is a surface to ship missile)
|
||||||
-- * SA-2, SA-3, SA-5, SA-6, SA-7, SA-8, SA-9, SA-10, SA-11, SA-13, SA-15, SA-19
|
-- * SA-2, SA-3, SA-5, SA-6, SA-7, SA-8, SA-9, SA-10, SA-11, SA-13, SA-15, SA-19
|
||||||
-- * From IDF mod: STUNNER IDFA, TAMIR IDFA (Note all caps!)
|
-- * From IDF mod: STUNNER IDFA, TAMIR IDFA (Note all caps!)
|
||||||
-- * From HDS (see note on HDS below): SA-2, SA-3, SA-10B, SA-10C, SA-12, SA-17, SA-20A, SA-20B, SA-23, HQ-2
|
-- * From HDS (see note on HDS below): SA-2, SA-3, SA-10B, SA-10C, SA-12, SA-17, SA-20A, SA-20B, SA-23, HQ-2, SAMP/T Block 1, SAMP/T Block 1INT, SAMP/T Block2
|
||||||
|
-- * Other Mods: Nike
|
||||||
--
|
--
|
||||||
-- * From SMA: RBS98M, RBS70, RBS90, RBS90M, RBS103A, RBS103B, RBS103AM, RBS103BM, Lvkv9040M
|
-- * From SMA: RBS98M, RBS70, RBS90, RBS90M, RBS103A, RBS103B, RBS103AM, RBS103BM, Lvkv9040M
|
||||||
-- **NOTE** If you are using the Swedish Military Assets (SMA), please note that the **group name** for RBS-SAM types also needs to contain the keyword "SMA"
|
-- **NOTE** If you are using the Swedish Military Assets (SMA), please note that the **group name** for RBS-SAM types also needs to contain the keyword "SMA"
|
||||||
@@ -124,19 +130,20 @@
|
|||||||
-- * SA-2 (with V759 missile, e.g. "Red SAM SA-2 HDS")
|
-- * SA-2 (with V759 missile, e.g. "Red SAM SA-2 HDS")
|
||||||
-- * SA-2 (with HQ-2 launcher, use HQ-2 in the group name, e.g. "Red SAM HQ-2" )
|
-- * SA-2 (with HQ-2 launcher, use HQ-2 in the group name, e.g. "Red SAM HQ-2" )
|
||||||
-- * SA-3 (with V601P missile, e.g. "Red SAM SA-3 HDS")
|
-- * SA-3 (with V601P missile, e.g. "Red SAM SA-3 HDS")
|
||||||
-- * SA-10B (overlap with other SA-10 types, e.g. "Red SAM SA-10B HDS")
|
-- * SA-10B (overlap with other SA-10 types, e.g. "Red SAM SA-10B HDS" with 5P85CE launcher)
|
||||||
-- * SA-10C (overlap with other SA-10 types, e.g. "Red SAM SA-10C HDS")
|
-- * SA-10C (overlap with other SA-10 types, e.g. "Red SAM SA-10C HDS" with 5P85SE launcher)
|
||||||
-- * SA-12 (launcher dependent range, e.g. "Red SAM SA-12 HDS")
|
-- * SA-12 (launcher dependent range, e.g. "Red SAM SA-12 HDS 2" for the 9A82 variant and "Red SAM SA-12 HDS 1" for the 9A83 variant)
|
||||||
-- * SA-23 (launcher dependent range, e.g. "Red SAM SA-23 HDS")
|
-- * SA-23 (launcher dependent range, e.g. "Red SAM SA-23 HDS 2" for the 9A82ME variant and "Red SAM SA-23 HDS 1" for the 9A83ME variant)
|
||||||
|
-- * SAMP/T (launcher dependent range, e.g. "Blue SAM SAMPT Block 1 HDS" for Block 1, "Blue SAM SAMPT Block 1INT HDS", "Blue SAM SAMPT Block 2 HDS")
|
||||||
--
|
--
|
||||||
-- The other HDS types work like the rest of the known SAM systems.
|
-- The other HDS types work like the rest of the known SAM systems.
|
||||||
--
|
--
|
||||||
-- # 0.1 Set-up in the mission editor
|
-- # 0.1 Set-up in the mission editor
|
||||||
--
|
--
|
||||||
-- Set up your SAM sites in the mission editor. Name the groups using a systematic approach like above.
|
-- Set up your SAM sites in the mission editor. Name the groups using a systematic approach like above.Can be e.g. AWACS or a combination of AWACS and Search Radars like e.g. EWR 1L13 etc.
|
||||||
-- Set up your EWR system in the mission editor. Name the groups using a systematic approach like above. Can be e.g. AWACS or a combination of AWACS and Search Radars like e.g. EWR 1L13 etc.
|
|
||||||
-- Search Radars usually have "SR" or "STR" in their names. Use the encyclopedia in the mission editor to inform yourself.
|
-- Search Radars usually have "SR" or "STR" in their names. Use the encyclopedia in the mission editor to inform yourself.
|
||||||
-- Set up your SHORAD systems. They need to be **close** to (i.e. around) the SAM sites to be effective. Use **one** group per SAM location. SA-15 TOR systems offer a good missile defense.
|
-- Set up your SHORAD systems. They need to be **close** to (i.e. around) the SAM sites to be effective. Use **one unit ** per group (multiple groups) for the SAM location.
|
||||||
|
-- Else, evasive manoevers might club up all defenders in one place. Red SA-15 TOR systems offer a good missile defense.
|
||||||
--
|
--
|
||||||
-- [optional] Set up your HQ. Can be any group, e.g. a command vehicle.
|
-- [optional] Set up your HQ. Can be any group, e.g. a command vehicle.
|
||||||
--
|
--
|
||||||
@@ -188,7 +195,7 @@
|
|||||||
--
|
--
|
||||||
-- ## 2.1 Auto mode features
|
-- ## 2.1 Auto mode features
|
||||||
--
|
--
|
||||||
-- ### 2.1.1 You can now add Accept-, Reject- and Conflict-Zones to your setup, e.g. to consider borders or de-militarized zones:
|
-- ### 2.1.1 You can add Accept-, Reject- and Conflict-Zones to your setup, e.g. to consider borders or de-militarized zones:
|
||||||
--
|
--
|
||||||
-- -- Parameters are tables of Core.Zone#ZONE objects!
|
-- -- Parameters are tables of Core.Zone#ZONE objects!
|
||||||
-- -- This is effectively a 3-stage filter allowing for zone overlap. A coordinate is accepted first when
|
-- -- This is effectively a 3-stage filter allowing for zone overlap. A coordinate is accepted first when
|
||||||
@@ -206,9 +213,6 @@
|
|||||||
--
|
--
|
||||||
-- ### 2.1.4 Advanced features
|
-- ### 2.1.4 Advanced features
|
||||||
--
|
--
|
||||||
-- -- Option to switch off auto mode **before** you start MANTIS (not recommended)
|
|
||||||
-- mybluemantis.automode = false
|
|
||||||
--
|
|
||||||
-- -- Option to set the scale of the activation range, i.e. don't activate at the fringes of max range, defaults below.
|
-- -- Option to set the scale of the activation range, i.e. don't activate at the fringes of max range, defaults below.
|
||||||
-- -- also see engagerange below.
|
-- -- also see engagerange below.
|
||||||
-- self.radiusscale[MANTIS.SamType.LONG] = 1.1
|
-- self.radiusscale[MANTIS.SamType.LONG] = 1.1
|
||||||
@@ -221,6 +225,12 @@
|
|||||||
-- -- For some scenarios, like Cold War, it might be useful not to activate SAMs if friendly aircraft are around to avoid death by friendly fire.
|
-- -- For some scenarios, like Cold War, it might be useful not to activate SAMs if friendly aircraft are around to avoid death by friendly fire.
|
||||||
-- mybluemantis.checkforfriendlies = true
|
-- mybluemantis.checkforfriendlies = true
|
||||||
--
|
--
|
||||||
|
-- ### 2.1.6 Shoot & Scoot
|
||||||
|
--
|
||||||
|
-- -- Option to make the (driveable) SHORAD units drive around and shuffle positions
|
||||||
|
-- -- We use a SET_ZONE for that, number of zones to consider defaults to three, Random is true for random coordinates and Formation is e.g. "Vee".
|
||||||
|
-- mybluemantis:AddScootZones(ZoneSet, Number, Random, Formation)
|
||||||
|
--
|
||||||
-- # 3. Default settings [both modes unless stated otherwise]
|
-- # 3. Default settings [both modes unless stated otherwise]
|
||||||
--
|
--
|
||||||
-- By default, the following settings are active:
|
-- By default, the following settings are active:
|
||||||
@@ -243,25 +253,7 @@
|
|||||||
--
|
--
|
||||||
-- Use this option if you want to make use of or allow advanced SEAD tactics.
|
-- Use this option if you want to make use of or allow advanced SEAD tactics.
|
||||||
--
|
--
|
||||||
-- # 5. Integrate SHORAD [classic mode, not necessary in automode, not recommended for manual setup]
|
-- # 5. Integrated SEAD
|
||||||
--
|
|
||||||
-- You can also choose to integrate Mantis with @{Functional.Shorad#SHORAD} for protection against HARMs and AGMs manually. When SHORAD detects a missile fired at one of MANTIS' SAM sites, it will activate SHORAD systems in
|
|
||||||
-- the given defense checkradius around that SAM site. Create a SHORAD object first, then integrate with MANTIS like so:
|
|
||||||
--
|
|
||||||
-- local SamSet = SET_GROUP:New():FilterPrefixes("Blue SAM"):FilterCoalitions("blue"):FilterStart()
|
|
||||||
-- myshorad = SHORAD:New("BlueShorad", "Blue SHORAD", SamSet, 22000, 600, "blue")
|
|
||||||
-- -- now set up MANTIS
|
|
||||||
-- mymantis = MANTIS:New("BlueMantis","Blue SAM","Blue EWR",nil,"blue",false,"Blue Awacs")
|
|
||||||
-- mymantis:AddShorad(myshorad,720)
|
|
||||||
-- mymantis:Start()
|
|
||||||
--
|
|
||||||
-- If you systematically name your SHORAD groups starting with "Blue SHORAD" you'll need exactly **one** SHORAD instance to manage all SHORAD groups.
|
|
||||||
--
|
|
||||||
-- (Optionally) you can remove the link later on with
|
|
||||||
--
|
|
||||||
-- mymantis:RemoveShorad()
|
|
||||||
--
|
|
||||||
-- # 6. Integrated SEAD
|
|
||||||
--
|
--
|
||||||
-- MANTIS is using @{Functional.Sead#SEAD} internally to both detect and evade HARM attacks. No extra efforts needed to set this up!
|
-- MANTIS is using @{Functional.Sead#SEAD} internally to both detect and evade HARM attacks. No extra efforts needed to set this up!
|
||||||
-- Once a HARM attack is detected, MANTIS (via SEAD) will shut down the radars of the attacked SAM site and take evasive action by moving the SAM
|
-- Once a HARM attack is detected, MANTIS (via SEAD) will shut down the radars of the attacked SAM site and take evasive action by moving the SAM
|
||||||
@@ -288,6 +280,7 @@
|
|||||||
MANTIS = {
|
MANTIS = {
|
||||||
ClassName = "MANTIS",
|
ClassName = "MANTIS",
|
||||||
name = "mymantis",
|
name = "mymantis",
|
||||||
|
version = "0.9.34",
|
||||||
SAM_Templates_Prefix = "",
|
SAM_Templates_Prefix = "",
|
||||||
SAM_Group = nil,
|
SAM_Group = nil,
|
||||||
EWR_Templates_Prefix = "",
|
EWR_Templates_Prefix = "",
|
||||||
@@ -336,6 +329,8 @@ MANTIS = {
|
|||||||
SmokeDecoy = false,
|
SmokeDecoy = false,
|
||||||
SmokeDecoyColor = SMOKECOLOR.White,
|
SmokeDecoyColor = SMOKECOLOR.White,
|
||||||
checkcounter = 1,
|
checkcounter = 1,
|
||||||
|
DLinkCacheTime = 120,
|
||||||
|
logsamstatus = false,
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Advanced state enumerator
|
--- Advanced state enumerator
|
||||||
@@ -374,7 +369,7 @@ MANTIS.radiusscale[MANTIS.SamType.POINT] = 3
|
|||||||
MANTIS.SamData = {
|
MANTIS.SamData = {
|
||||||
["Hawk"] = { Range=35, Blindspot=0, Height=12, Type="Medium", Radar="Hawk" }, -- measures in km
|
["Hawk"] = { Range=35, Blindspot=0, Height=12, Type="Medium", Radar="Hawk" }, -- measures in km
|
||||||
["NASAMS"] = { Range=14, Blindspot=0, Height=7, Type="Short", Radar="NSAMS" }, -- AIM 120B
|
["NASAMS"] = { Range=14, Blindspot=0, Height=7, Type="Short", Radar="NSAMS" }, -- AIM 120B
|
||||||
["Patriot"] = { Range=99, Blindspot=0, Height=25, Type="Long", Radar="Patriot" },
|
["Patriot"] = { Range=99, Blindspot=0, Height=25, Type="Long", Radar="Patriot str" },
|
||||||
["Rapier"] = { Range=10, Blindspot=0, Height=3, Type="Short", Radar="rapier" },
|
["Rapier"] = { Range=10, Blindspot=0, Height=3, Type="Short", Radar="rapier" },
|
||||||
["SA-2"] = { Range=40, Blindspot=7, Height=25, Type="Medium", Radar="S_75M_Volhov" },
|
["SA-2"] = { Range=40, Blindspot=7, Height=25, Type="Medium", Radar="S_75M_Volhov" },
|
||||||
["SA-3"] = { Range=18, Blindspot=6, Height=18, Type="Short", Radar="5p73 s-125 ln" },
|
["SA-3"] = { Range=18, Blindspot=6, Height=18, Type="Short", Radar="5p73 s-125 ln" },
|
||||||
@@ -382,7 +377,8 @@ MANTIS.SamData = {
|
|||||||
["SA-6"] = { Range=25, Blindspot=0, Height=8, Type="Medium", Radar="1S91" },
|
["SA-6"] = { Range=25, Blindspot=0, Height=8, Type="Medium", Radar="1S91" },
|
||||||
["SA-10"] = { Range=119, Blindspot=0, Height=18, Type="Long" , Radar="S-300PS 4"},
|
["SA-10"] = { Range=119, Blindspot=0, Height=18, Type="Long" , Radar="S-300PS 4"},
|
||||||
["SA-11"] = { Range=35, Blindspot=0, Height=20, Type="Medium", Radar="SA-11" },
|
["SA-11"] = { Range=35, Blindspot=0, Height=20, Type="Medium", Radar="SA-11" },
|
||||||
["Roland"] = { Range=5, Blindspot=0, Height=5, Type="Point", Radar="Roland" },
|
["Roland"] = { Range=6, Blindspot=0, Height=5, Type="Short", Radar="Roland" },
|
||||||
|
["Gepard"] = { Range=5, Blindspot=0, Height=4, Type="Point", Radar="Gepard" },
|
||||||
["HQ-7"] = { Range=12, Blindspot=0, Height=3, Type="Short", Radar="HQ-7" },
|
["HQ-7"] = { Range=12, Blindspot=0, Height=3, Type="Short", Radar="HQ-7" },
|
||||||
["SA-9"] = { Range=4, Blindspot=0, Height=3, Type="Point", Radar="Strela", Point="true" },
|
["SA-9"] = { Range=4, Blindspot=0, Height=3, Type="Point", Radar="Strela", Point="true" },
|
||||||
["SA-8"] = { Range=10, Blindspot=0, Height=5, Type="Short", Radar="Osa 9A33" },
|
["SA-8"] = { Range=10, Blindspot=0, Height=5, Type="Short", Radar="Osa 9A33" },
|
||||||
@@ -393,14 +389,21 @@ MANTIS.SamData = {
|
|||||||
["Chaparral"] = { Range=8, Blindspot=0, Height=3, Type="Short", Radar="Chaparral" },
|
["Chaparral"] = { Range=8, Blindspot=0, Height=3, Type="Short", Radar="Chaparral" },
|
||||||
["Linebacker"] = { Range=4, Blindspot=0, Height=3, Type="Point", Radar="Linebacker", Point="true" },
|
["Linebacker"] = { Range=4, Blindspot=0, Height=3, Type="Point", Radar="Linebacker", Point="true" },
|
||||||
["Silkworm"] = { Range=90, Blindspot=1, Height=0.2, Type="Long", Radar="Silkworm" },
|
["Silkworm"] = { Range=90, Blindspot=1, Height=0.2, Type="Long", Radar="Silkworm" },
|
||||||
|
["C-RAM"] = { Range=2, Blindspot=0, Height=2, Type="Point", Radar="HEMTT_C-RAM_Phalanx", Point="true" },
|
||||||
-- units from HDS Mod, multi launcher options is tricky
|
-- units from HDS Mod, multi launcher options is tricky
|
||||||
["SA-10B"] = { Range=75, Blindspot=0, Height=18, Type="Medium" , Radar="SA-10B"},
|
["SA-10B"] = { Range=75, Blindspot=0, Height=18, Type="Medium" , Radar="SA-10B"},
|
||||||
["SA-17"] = { Range=50, Blindspot=3, Height=30, Type="Medium", Radar="SA-17" },
|
["SA-17"] = { Range=50, Blindspot=3, Height=50, Type="Medium", Radar="SA-17" },
|
||||||
["SA-20A"] = { Range=150, Blindspot=5, Height=27, Type="Long" , Radar="S-300PMU1"},
|
["SA-20A"] = { Range=150, Blindspot=5, Height=27, Type="Long" , Radar="S-300PMU1"},
|
||||||
["SA-20B"] = { Range=200, Blindspot=4, Height=27, Type="Long" , Radar="S-300PMU2"},
|
["SA-20B"] = { Range=200, Blindspot=4, Height=27, Type="Long" , Radar="S-300PMU2"},
|
||||||
["HQ-2"] = { Range=50, Blindspot=6, Height=35, Type="Medium", Radar="HQ_2_Guideline_LN" },
|
["HQ-2"] = { Range=50, Blindspot=6, Height=35, Type="Medium", Radar="HQ_2_Guideline_LN" },
|
||||||
["TAMIR IDFA"] = { Range=20, Blindspot=0.6, Height=12.3, Type="Short", Radar="IRON_DOME_LN" },
|
["TAMIR IDFA"] = { Range=20, Blindspot=0.6, Height=12.3, Type="Short", Radar="IRON_DOME_LN" },
|
||||||
["STUNNER IDFA"] = { Range=250, Blindspot=1, Height=45, Type="Long", Radar="DAVID_SLING_LN" },
|
["STUNNER IDFA"] = { Range=250, Blindspot=1, Height=45, Type="Long", Radar="DAVID_SLING_LN" },
|
||||||
|
["NIKE"] = { Range=155, Blindspot=6, Height=30, Type="Long", Radar="HIPAR" },
|
||||||
|
["Dog Ear"] = { Range=11, Blindspot=0, Height=9, Type="Point", Radar="Dog Ear", Point="true" },
|
||||||
|
-- CH Added to DCS core 2.9.19.x
|
||||||
|
["Pantsir S1"] = { Range=20, Blindspot=1.2, Height=15, Type="Point", Radar="PantsirS1" , Point="true" },
|
||||||
|
["Tor M2"] = { Range=12, Blindspot=1, Height=10, Type="Point", Radar="TorM2", Point="true" },
|
||||||
|
["IRIS-T SLM"] = { Range=40, Blindspot=0.5, Height=20, Type="Medium", Radar="CH_IRIST_SLM" },
|
||||||
}
|
}
|
||||||
|
|
||||||
--- SAM data HDS
|
--- SAM data HDS
|
||||||
@@ -416,13 +419,17 @@ MANTIS.SamDataHDS = {
|
|||||||
-- group name MUST contain HDS to ID launcher type correctly!
|
-- group name MUST contain HDS to ID launcher type correctly!
|
||||||
["SA-2 HDS"] = { Range=56, Blindspot=7, Height=30, Type="Medium", Radar="V759" },
|
["SA-2 HDS"] = { Range=56, Blindspot=7, Height=30, Type="Medium", Radar="V759" },
|
||||||
["SA-3 HDS"] = { Range=20, Blindspot=6, Height=30, Type="Short", Radar="V-601P" },
|
["SA-3 HDS"] = { Range=20, Blindspot=6, Height=30, Type="Short", Radar="V-601P" },
|
||||||
["SA-10C HDS 2"] = { Range=90, Blindspot=5, Height=25, Type="Long" , Radar="5P85DE ln"}, -- V55RUD
|
["SA-10B HDS"] = { Range=90, Blindspot=5, Height=25, Type="Long" , Radar="5P85CE ln"}, -- V55RUD
|
||||||
["SA-10C HDS 1"] = { Range=90, Blindspot=5, Height=25, Type="Long" , Radar="5P85CE ln"}, -- V55RUD
|
["SA-10C HDS"] = { Range=75, Blindspot=5, Height=25, Type="Long" , Radar="5P85SE ln"}, -- V55RUD
|
||||||
["SA-12 HDS 2"] = { Range=100, Blindspot=10, Height=25, Type="Long" , Radar="S-300V 9A82 l"},
|
["SA-17 HDS"] = { Range=50, Blindspot=3, Height=50, Type="Medium", Radar="SA-17 " },
|
||||||
["SA-12 HDS 1"] = { Range=75, Blindspot=1, Height=25, Type="Long" , Radar="S-300V 9A83 l"},
|
["SA-12 HDS 2"] = { Range=100, Blindspot=13, Height=30, Type="Long" , Radar="S-300V 9A82 l"},
|
||||||
|
["SA-12 HDS 1"] = { Range=75, Blindspot=6, Height=25, Type="Long" , Radar="S-300V 9A83 l"},
|
||||||
["SA-23 HDS 2"] = { Range=200, Blindspot=5, Height=37, Type="Long", Radar="S-300VM 9A82ME" },
|
["SA-23 HDS 2"] = { Range=200, Blindspot=5, Height=37, Type="Long", Radar="S-300VM 9A82ME" },
|
||||||
["SA-23 HDS 1"] = { Range=100, Blindspot=1, Height=50, Type="Long", Radar="S-300VM 9A83ME" },
|
["SA-23 HDS 1"] = { Range=100, Blindspot=1, Height=50, Type="Long", Radar="S-300VM 9A83ME" },
|
||||||
["HQ-2 HDS"] = { Range=50, Blindspot=6, Height=35, Type="Medium", Radar="HQ_2_Guideline_LN" },
|
["HQ-2 HDS"] = { Range=50, Blindspot=6, Height=35, Type="Medium", Radar="HQ_2_Guideline_LN" },
|
||||||
|
["SAMPT Block 1 HDS"] = { Range=120, Blindspot=1, Height=20, Type="long", Radar="SAMPT_MLT_Blk1" }, -- Block 1 Launcher
|
||||||
|
["SAMPT Block 1INT HDS"] = { Range=150, Blindspot=1, Height=25, Type="long", Radar="SAMPT_MLT_Blk1NT" }, -- Block 1-INT Launcher
|
||||||
|
["SAMPT Block 2 HDS"] = { Range=200, Blindspot=10, Height=70, Type="long", Radar="SAMPT_MLT_Blk2" }, -- Block 2 Launcher
|
||||||
}
|
}
|
||||||
|
|
||||||
--- SAM data SMA
|
--- SAM data SMA
|
||||||
@@ -462,15 +469,15 @@ MANTIS.SamDataCH = {
|
|||||||
-- https://www.currenthill.com/
|
-- https://www.currenthill.com/
|
||||||
-- group name MUST contain CHM to ID launcher type correctly!
|
-- group name MUST contain CHM to ID launcher type correctly!
|
||||||
["2S38 CHM"] = { Range=6, Blindspot=0.1, Height=4.5, Type="Short", Radar="2S38" },
|
["2S38 CHM"] = { Range=6, Blindspot=0.1, Height=4.5, Type="Short", Radar="2S38" },
|
||||||
["PantsirS1 CHM"] = { Range=20, Blindspot=1.2, Height=15, Type="Short", Radar="PantsirS1" },
|
["PantsirS1 CHM"] = { Range=20, Blindspot=1.2, Height=15, Type="Point", Radar="PantsirS1", Point="true" },
|
||||||
["PantsirS2 CHM"] = { Range=30, Blindspot=1.2, Height=18, Type="Medium", Radar="PantsirS2" },
|
["PantsirS2 CHM"] = { Range=30, Blindspot=1.2, Height=18, Type="Medium", Radar="PantsirS2" },
|
||||||
["PGL-625 CHM"] = { Range=10, Blindspot=1, Height=5, Type="Short", Radar="PGL_625" },
|
["PGL-625 CHM"] = { Range=10, Blindspot=1, Height=5, Type="Short", Radar="PGL_625" },
|
||||||
["HQ-17A CHM"] = { Range=15, Blindspot=1.5, Height=10, Type="Short", Radar="HQ17A" },
|
["HQ-17A CHM"] = { Range=15, Blindspot=1.5, Height=10, Type="Short", Radar="HQ17A" },
|
||||||
["M903PAC2 CHM"] = { Range=120, Blindspot=3, Height=24.5, Type="Long", Radar="MIM104_M903_PAC2" },
|
["M903PAC2 CHM"] = { Range=120, Blindspot=3, Height=24.5, Type="Long", Radar="MIM104_M903_PAC2" },
|
||||||
["M903PAC3 CHM"] = { Range=160, Blindspot=1, Height=40, Type="Long", Radar="MIM104_M903_PAC3" },
|
["M903PAC3 CHM"] = { Range=160, Blindspot=1, Height=40, Type="Long", Radar="MIM104_M903_PAC3" },
|
||||||
["TorM2 CHM"] = { Range=12, Blindspot=1, Height=10, Type="Short", Radar="TorM2" },
|
["TorM2 CHM"] = { Range=12, Blindspot=1, Height=10, Type="Point", Radar="TorM2", Point="true" },
|
||||||
["TorM2K CHM"] = { Range=12, Blindspot=1, Height=10, Type="Short", Radar="TorM2K" },
|
["TorM2K CHM"] = { Range=12, Blindspot=1, Height=10, Type="Point", Radar="TorM2K", Point="true" },
|
||||||
["TorM2M CHM"] = { Range=16, Blindspot=1, Height=10, Type="Short", Radar="TorM2M" },
|
["TorM2M CHM"] = { Range=16, Blindspot=1, Height=10, Type="Point", Radar="TorM2M", Point="true" },
|
||||||
["NASAMS3-AMRAAMER CHM"] = { Range=50, Blindspot=2, Height=35.7, Type="Medium", Radar="CH_NASAMS3_LN_AMRAAM_ER" },
|
["NASAMS3-AMRAAMER CHM"] = { Range=50, Blindspot=2, Height=35.7, Type="Medium", Radar="CH_NASAMS3_LN_AMRAAM_ER" },
|
||||||
["NASAMS3-AIM9X2 CHM"] = { Range=20, Blindspot=0.2, Height=18, Type="Short", Radar="CH_NASAMS3_LN_AIM9X2" },
|
["NASAMS3-AIM9X2 CHM"] = { Range=20, Blindspot=0.2, Height=18, Type="Short", Radar="CH_NASAMS3_LN_AIM9X2" },
|
||||||
["C-RAM CHM"] = { Range=2, Blindspot=0, Height=2, Type="Point", Radar="CH_Centurion_C_RAM", Point="true" },
|
["C-RAM CHM"] = { Range=2, Blindspot=0, Height=2, Type="Point", Radar="CH_Centurion_C_RAM", Point="true" },
|
||||||
@@ -625,6 +632,7 @@ do
|
|||||||
self.advAwacs = false
|
self.advAwacs = false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
self:SetDLinkCacheTime()
|
||||||
|
|
||||||
-- Set the string id for output to DCS.log file.
|
-- Set the string id for output to DCS.log file.
|
||||||
self.lid=string.format("MANTIS %s | ", self.name)
|
self.lid=string.format("MANTIS %s | ", self.name)
|
||||||
@@ -658,6 +666,8 @@ do
|
|||||||
table.insert(self.ewr_templates,awacs)
|
table.insert(self.ewr_templates,awacs)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
self.logsamstatus = false
|
||||||
|
|
||||||
self:T({self.ewr_templates})
|
self:T({self.ewr_templates})
|
||||||
|
|
||||||
self.SAM_Group = SET_GROUP:New():FilterPrefixes(self.SAM_Templates_Prefix):FilterCoalitions(self.Coalition)
|
self.SAM_Group = SET_GROUP:New():FilterPrefixes(self.SAM_Templates_Prefix):FilterCoalitions(self.Coalition)
|
||||||
@@ -687,9 +697,6 @@ do
|
|||||||
-- counter for SAM table updates
|
-- counter for SAM table updates
|
||||||
self.checkcounter = 1
|
self.checkcounter = 1
|
||||||
|
|
||||||
-- TODO Version
|
|
||||||
-- @field #string version
|
|
||||||
self.version="0.9.27"
|
|
||||||
self:I(string.format("***** Starting MANTIS Version %s *****", self.version))
|
self:I(string.format("***** Starting MANTIS Version %s *****", self.version))
|
||||||
|
|
||||||
--- FSM Functions ---
|
--- FSM Functions ---
|
||||||
@@ -886,7 +893,11 @@ do
|
|||||||
self.AcceptZones = AcceptZones or {}
|
self.AcceptZones = AcceptZones or {}
|
||||||
self.RejectZones = RejectZones or {}
|
self.RejectZones = RejectZones or {}
|
||||||
self.ConflictZones = ConflictZones or {}
|
self.ConflictZones = ConflictZones or {}
|
||||||
if #self.AcceptZones > 0 or #self.RejectZones > 0 or #self.ConflictZones > 0 then
|
self.AcceptZonesNo = UTILS.TableLength(self.AcceptZones)
|
||||||
|
self.RejectZonesNo = UTILS.TableLength(self.RejectZones)
|
||||||
|
self.ConflictZonesNo = UTILS.TableLength(self.ConflictZones)
|
||||||
|
self:T(string.format("AcceptZonesNo = %d | RejectZonesNo = %d | ConflictZonesNo = %d",self.AcceptZonesNo,self.RejectZonesNo,self.ConflictZonesNo))
|
||||||
|
if self.AcceptZonesNo > 0 or self.RejectZonesNo > 0 or self.ConflictZonesNo > 0 then
|
||||||
self.usezones = true
|
self.usezones = true
|
||||||
end
|
end
|
||||||
return self
|
return self
|
||||||
@@ -1040,6 +1051,16 @@ do
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Function to set how long INTEL DLINK remembers contacts.
|
||||||
|
-- @param #MANTIS self
|
||||||
|
-- @param #number seconds Remember this many seconds, at least 5 seconds.
|
||||||
|
-- @return #MANTIS self
|
||||||
|
function MANTIS:SetDLinkCacheTime(seconds)
|
||||||
|
self.DLinkCacheTime = math.abs(seconds or 120)
|
||||||
|
if self.DLinkCacheTime < 5 then self.DLinkCacheTime = 5 end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- Function to set the detection interval
|
--- Function to set the detection interval
|
||||||
-- @param #MANTIS self
|
-- @param #MANTIS self
|
||||||
-- @param #number interval The interval in seconds
|
-- @param #number interval The interval in seconds
|
||||||
@@ -1268,7 +1289,8 @@ do
|
|||||||
self:T(self.lid.."_CheckCoordinateInZones")
|
self:T(self.lid.."_CheckCoordinateInZones")
|
||||||
local inzone = false
|
local inzone = false
|
||||||
-- acceptzones
|
-- acceptzones
|
||||||
if #self.AcceptZones > 0 then
|
self:T(string.format("AcceptZonesNo = %d | RejectZonesNo = %d | ConflictZonesNo = %d",self.AcceptZonesNo,self.RejectZonesNo,self.ConflictZonesNo))
|
||||||
|
if self.AcceptZonesNo > 0 then
|
||||||
for _,_zone in pairs(self.AcceptZones) do
|
for _,_zone in pairs(self.AcceptZones) do
|
||||||
local zone = _zone -- Core.Zone#ZONE
|
local zone = _zone -- Core.Zone#ZONE
|
||||||
if zone:IsCoordinateInZone(coord) then
|
if zone:IsCoordinateInZone(coord) then
|
||||||
@@ -1279,7 +1301,7 @@ do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
-- rejectzones
|
-- rejectzones
|
||||||
if #self.RejectZones > 0 and inzone then -- maybe in accept zone, but check the overlaps
|
if self.RejectZonesNo > 0 then
|
||||||
for _,_zone in pairs(self.RejectZones) do
|
for _,_zone in pairs(self.RejectZones) do
|
||||||
local zone = _zone -- Core.Zone#ZONE
|
local zone = _zone -- Core.Zone#ZONE
|
||||||
if zone:IsCoordinateInZone(coord) then
|
if zone:IsCoordinateInZone(coord) then
|
||||||
@@ -1290,7 +1312,7 @@ do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
-- conflictzones
|
-- conflictzones
|
||||||
if #self.ConflictZones > 0 and not inzone then -- if not already accepted, might be in conflict zones
|
if self.ConflictZonesNo > 0 then
|
||||||
for _,_zone in pairs(self.ConflictZones) do
|
for _,_zone in pairs(self.ConflictZones) do
|
||||||
local zone = _zone -- Core.Zone#ZONE
|
local zone = _zone -- Core.Zone#ZONE
|
||||||
if zone:IsCoordinateInZone(coord) then
|
if zone:IsCoordinateInZone(coord) then
|
||||||
@@ -1356,6 +1378,7 @@ do
|
|||||||
end
|
end
|
||||||
-- check accept/reject zones
|
-- check accept/reject zones
|
||||||
local zonecheck = true
|
local zonecheck = true
|
||||||
|
self:T("self.usezones = "..tostring(self.usezones))
|
||||||
if self.usezones then
|
if self.usezones then
|
||||||
-- DONE
|
-- DONE
|
||||||
zonecheck = self:_CheckCoordinateInZones(coord)
|
zonecheck = self:_CheckCoordinateInZones(coord)
|
||||||
@@ -1431,7 +1454,9 @@ do
|
|||||||
--IntelTwo:SetClusterRadius(5000)
|
--IntelTwo:SetClusterRadius(5000)
|
||||||
IntelTwo:Start()
|
IntelTwo:Start()
|
||||||
|
|
||||||
local IntelDlink = INTEL_DLINK:New({IntelOne,IntelTwo},self.name.." DLINK",22,300)
|
local CacheTime = self.DLinkCacheTime or 120
|
||||||
|
local IntelDlink = INTEL_DLINK:New({IntelOne,IntelTwo},self.name.." DLINK",22,CacheTime)
|
||||||
|
|
||||||
IntelDlink:__Start(1)
|
IntelDlink:__Start(1)
|
||||||
|
|
||||||
self:SetUsingDLink(IntelDlink)
|
self:SetUsingDLink(IntelDlink)
|
||||||
@@ -1493,7 +1518,7 @@ do
|
|||||||
elseif chm then
|
elseif chm then
|
||||||
SAMData = self.SamDataCH
|
SAMData = self.SamDataCH
|
||||||
end
|
end
|
||||||
--self:T("Looking to auto-match for "..grpname)
|
--self:I("Looking to auto-match for "..grpname)
|
||||||
for _,_unit in pairs(units) do
|
for _,_unit in pairs(units) do
|
||||||
local unit = _unit -- Wrapper.Unit#UNIT
|
local unit = _unit -- Wrapper.Unit#UNIT
|
||||||
local type = string.lower(unit:GetTypeName())
|
local type = string.lower(unit:GetTypeName())
|
||||||
@@ -1694,7 +1719,9 @@ do
|
|||||||
local grpname = group:GetName()
|
local grpname = group:GetName()
|
||||||
local grpcoord = group:GetCoordinate()
|
local grpcoord = group:GetCoordinate()
|
||||||
local grprange, grpheight,type,blind = self:_GetSAMRange(grpname)
|
local grprange, grpheight,type,blind = self:_GetSAMRange(grpname)
|
||||||
local radaralive = group:IsSAM()
|
-- TODO the below might stop working at some point after some hours, needs testing
|
||||||
|
--local radaralive = group:IsSAM()
|
||||||
|
local radaralive = true
|
||||||
table.insert( SAM_Tbl, {grpname, grpcoord, grprange, grpheight, blind, type}) -- make the table lighter, as I don't really use the zone here
|
table.insert( SAM_Tbl, {grpname, grpcoord, grprange, grpheight, blind, type}) -- make the table lighter, as I don't really use the zone here
|
||||||
table.insert( SEAD_Grps, grpname )
|
table.insert( SEAD_Grps, grpname )
|
||||||
if type == MANTIS.SamType.LONG and radaralive then
|
if type == MANTIS.SamType.LONG and radaralive then
|
||||||
@@ -1791,7 +1818,7 @@ do
|
|||||||
if self.Shorad and self.Shorad.ActiveGroups and self.Shorad.ActiveGroups[name] then
|
if self.Shorad and self.Shorad.ActiveGroups and self.Shorad.ActiveGroups[name] then
|
||||||
activeshorad = true
|
activeshorad = true
|
||||||
end
|
end
|
||||||
if IsInZone and not suppressed and not activeshorad then --check any target in zone and not currently managed by SEAD
|
if IsInZone and (not suppressed) and (not activeshorad) then --check any target in zone and not currently managed by SEAD
|
||||||
if samgroup:IsAlive() then
|
if samgroup:IsAlive() then
|
||||||
-- switch on SAM
|
-- switch on SAM
|
||||||
local switch = false
|
local switch = false
|
||||||
@@ -1823,7 +1850,7 @@ do
|
|||||||
-- link in to SHORAD if available
|
-- link in to SHORAD if available
|
||||||
-- DONE: Test integration fully
|
-- DONE: Test integration fully
|
||||||
if self.ShoradLink and (Distance < self.ShoradActDistance or Distance < blind ) then -- don't give SHORAD position away too early
|
if self.ShoradLink and (Distance < self.ShoradActDistance or Distance < blind ) then -- don't give SHORAD position away too early
|
||||||
local Shorad = self.Shorad
|
local Shorad = self.Shorad --Functional.Shorad#SHORAD
|
||||||
local radius = self.checkradius
|
local radius = self.checkradius
|
||||||
local ontime = self.ShoradTime
|
local ontime = self.ShoradTime
|
||||||
Shorad:WakeUpShorad(name, radius, ontime)
|
Shorad:WakeUpShorad(name, radius, ontime)
|
||||||
@@ -1856,7 +1883,7 @@ do
|
|||||||
end --end alive
|
end --end alive
|
||||||
end --end check
|
end --end check
|
||||||
end --for loop
|
end --for loop
|
||||||
if self.debug or self.verbose then
|
if self.debug or self.verbose or self.logsamstatus then
|
||||||
for _,_status in pairs(self.SamStateTracker) do
|
for _,_status in pairs(self.SamStateTracker) do
|
||||||
if _status == "GREEN" then
|
if _status == "GREEN" then
|
||||||
instatusgreen=instatusgreen+1
|
instatusgreen=instatusgreen+1
|
||||||
@@ -1877,8 +1904,9 @@ do
|
|||||||
-- @param #MANTIS self
|
-- @param #MANTIS self
|
||||||
-- @param Functional.Detection#DETECTION_AREAS detection Detection object
|
-- @param Functional.Detection#DETECTION_AREAS detection Detection object
|
||||||
-- @param #boolean dlink
|
-- @param #boolean dlink
|
||||||
|
-- @param #boolean reporttolog
|
||||||
-- @return #MANTIS self
|
-- @return #MANTIS self
|
||||||
function MANTIS:_Check(detection,dlink)
|
function MANTIS:_Check(detection,dlink,reporttolog)
|
||||||
self:T(self.lid .. "Check")
|
self:T(self.lid .. "Check")
|
||||||
--get detected set
|
--get detected set
|
||||||
local detset = detection:GetDetectedItemCoordinates()
|
local detset = detection:GetDetectedItemCoordinates()
|
||||||
@@ -1905,7 +1933,8 @@ do
|
|||||||
local samset = self:_GetSAMTable() -- table of i.1=names, i.2=coordinates, i.3=firing range, i.4=firing height
|
local samset = self:_GetSAMTable() -- table of i.1=names, i.2=coordinates, i.3=firing range, i.4=firing height
|
||||||
instatusred, instatusgreen, activeshorads = self:_CheckLoop(samset,detset,dlink,self.maxclassic)
|
instatusred, instatusgreen, activeshorads = self:_CheckLoop(samset,detset,dlink,self.maxclassic)
|
||||||
end
|
end
|
||||||
if self.debug or self.verbose then
|
|
||||||
|
local function GetReport()
|
||||||
local statusreport = REPORT:New("\nMANTIS Status "..self.name)
|
local statusreport = REPORT:New("\nMANTIS Status "..self.name)
|
||||||
statusreport:Add("+-----------------------------+")
|
statusreport:Add("+-----------------------------+")
|
||||||
statusreport:Add(string.format("+ SAM in RED State: %2d",instatusred))
|
statusreport:Add(string.format("+ SAM in RED State: %2d",instatusred))
|
||||||
@@ -1914,7 +1943,15 @@ do
|
|||||||
statusreport:Add(string.format("+ SHORAD active: %2d",activeshorads))
|
statusreport:Add(string.format("+ SHORAD active: %2d",activeshorads))
|
||||||
end
|
end
|
||||||
statusreport:Add("+-----------------------------+")
|
statusreport:Add("+-----------------------------+")
|
||||||
|
return statusreport
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.debug or self.verbose then
|
||||||
|
local statusreport = GetReport()
|
||||||
MESSAGE:New(statusreport:Text(),10):ToAll():ToLog()
|
MESSAGE:New(statusreport:Text(),10):ToAll():ToLog()
|
||||||
|
elseif reporttolog == true then
|
||||||
|
local statusreport = GetReport()
|
||||||
|
MESSAGE:New(statusreport:Text(),10):ToLog()
|
||||||
end
|
end
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
@@ -2022,7 +2059,7 @@ do
|
|||||||
self:T({From, Event, To})
|
self:T({From, Event, To})
|
||||||
-- check detection
|
-- check detection
|
||||||
if not self.state2flag then
|
if not self.state2flag then
|
||||||
self:_Check(self.Detection,self.DLink)
|
self:_Check(self.Detection,self.DLink,self.logsamstatus)
|
||||||
end
|
end
|
||||||
|
|
||||||
local EWRAlive = self:_CheckAnyEWRAlive()
|
local EWRAlive = self:_CheckAnyEWRAlive()
|
||||||
@@ -2093,7 +2130,7 @@ do
|
|||||||
if self.debug and self.verbose then
|
if self.debug and self.verbose then
|
||||||
self:I(self.lid .. "Status Report")
|
self:I(self.lid .. "Status Report")
|
||||||
for _name,_state in pairs(self.SamStateTracker) do
|
for _name,_state in pairs(self.SamStateTracker) do
|
||||||
self:I(string.format("Site %s\tStatus %s",_name,_state))
|
self:I(string.format("Site %s | Status %s",_name,_state))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local interval = self.detectinterval * -1
|
local interval = self.detectinterval * -1
|
||||||
|
|||||||
@@ -53,6 +53,8 @@
|
|||||||
--
|
--
|
||||||
-- # Developer Note
|
-- # Developer Note
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE.
|
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE.
|
||||||
-- Therefore, this class is considered to be deprecated and superseded by the [Functional.Fox](https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Functional.Fox.html) class, which provides the same functionality.
|
-- Therefore, this class is considered to be deprecated and superseded by the [Functional.Fox](https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Functional.Fox.html) class, which provides the same functionality.
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -2102,7 +2102,12 @@ function RANGE._OnImpact(weapon, self, playerData, attackHdg, attackAlt, attackV
|
|||||||
result.attackHdg = attackHdg
|
result.attackHdg = attackHdg
|
||||||
result.attackVel = attackVel
|
result.attackVel = attackVel
|
||||||
result.attackAlt = attackAlt
|
result.attackAlt = attackAlt
|
||||||
result.date=os and os.date() or "n/a"
|
if os and os.date then
|
||||||
|
result.date=os.date()
|
||||||
|
else
|
||||||
|
self:E(self.lid.."os or os.date() not available")
|
||||||
|
result.date = "n/a"
|
||||||
|
end
|
||||||
|
|
||||||
-- Add to table.
|
-- Add to table.
|
||||||
table.insert( _results, result )
|
table.insert( _results, result )
|
||||||
|
|||||||
@@ -985,6 +985,7 @@ function SCORING:_EventOnHit( Event )
|
|||||||
local TargetUnitCoalition = nil
|
local TargetUnitCoalition = nil
|
||||||
local TargetUnitCategory = nil
|
local TargetUnitCategory = nil
|
||||||
local TargetUnitType = nil
|
local TargetUnitType = nil
|
||||||
|
local TargetIsScenery = false
|
||||||
|
|
||||||
if Event.IniDCSUnit then
|
if Event.IniDCSUnit then
|
||||||
|
|
||||||
@@ -1025,6 +1026,12 @@ function SCORING:_EventOnHit( Event )
|
|||||||
TargetCategory = Event.TgtCategory
|
TargetCategory = Event.TgtCategory
|
||||||
TargetType = Event.TgtTypeName
|
TargetType = Event.TgtTypeName
|
||||||
|
|
||||||
|
-- Scenery hit
|
||||||
|
if (not TargetCategory) and TargetUNIT ~= nil and TargetUnit:IsInstanceOf("SCENERY") then
|
||||||
|
TargetCategory = Unit.Category.STRUCTURE
|
||||||
|
TargetIsScenery = true
|
||||||
|
end
|
||||||
|
|
||||||
TargetUnitCoalition = _SCORINGCoalition[TargetCoalition]
|
TargetUnitCoalition = _SCORINGCoalition[TargetCoalition]
|
||||||
TargetUnitCategory = _SCORINGCategory[TargetCategory]
|
TargetUnitCategory = _SCORINGCategory[TargetCategory]
|
||||||
TargetUnitType = TargetType
|
TargetUnitType = TargetType
|
||||||
@@ -1117,17 +1124,22 @@ function SCORING:_EventOnHit( Event )
|
|||||||
MESSAGE.Type.Update )
|
MESSAGE.Type.Update )
|
||||||
:ToAllIf( self:IfMessagesHit() and self:IfMessagesToAll() )
|
:ToAllIf( self:IfMessagesHit() and self:IfMessagesToAll() )
|
||||||
:ToCoalitionIf( InitCoalition, self:IfMessagesHit() and self:IfMessagesToCoalition() )
|
:ToCoalitionIf( InitCoalition, self:IfMessagesHit() and self:IfMessagesToCoalition() )
|
||||||
else
|
elseif TargetIsScenery ~= true then
|
||||||
MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. InitPlayerName .. "' hit enemy target " .. TargetUnitCategory .. " ( " .. TargetType .. " ) " .. PlayerHit.ScoreHit .. " times. " ..
|
MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. InitPlayerName .. "' hit enemy target " .. TargetUnitCategory .. " ( " .. TargetType .. " ) " .. PlayerHit.ScoreHit .. " times. " ..
|
||||||
"Score: " .. PlayerHit.Score .. ". Score Total:" .. Player.Score - Player.Penalty,
|
"Score: " .. PlayerHit.Score .. ". Score Total:" .. Player.Score - Player.Penalty,
|
||||||
MESSAGE.Type.Update )
|
MESSAGE.Type.Update )
|
||||||
:ToAllIf( self:IfMessagesHit() and self:IfMessagesToAll() )
|
:ToAllIf( self:IfMessagesHit() and self:IfMessagesToAll() )
|
||||||
:ToCoalitionIf( InitCoalition, self:IfMessagesHit() and self:IfMessagesToCoalition() )
|
:ToCoalitionIf( InitCoalition, self:IfMessagesHit() and self:IfMessagesToCoalition() )
|
||||||
|
elseif TargetIsScenery == true then
|
||||||
|
MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. InitPlayerName .. "' hit scenery object." .. " Score: " .. PlayerHit.Score .. ". Score Total:" .. Player.Score - Player.Penalty,
|
||||||
|
MESSAGE.Type.Update )
|
||||||
|
:ToAllIf( self:IfMessagesHit() and self:IfMessagesToAll() )
|
||||||
|
:ToCoalitionIf( InitCoalition, self:IfMessagesHit() and self:IfMessagesToCoalition() )
|
||||||
end
|
end
|
||||||
self:ScoreCSV( InitPlayerName, TargetPlayerName, "HIT_SCORE", 1, 1, InitUnitName, InitUnitCoalition, InitUnitCategory, InitUnitType, TargetUnitName, TargetUnitCoalition, TargetUnitCategory, TargetUnitType )
|
self:ScoreCSV( InitPlayerName, TargetPlayerName, "HIT_SCORE", 1, 1, InitUnitName, InitUnitCoalition, InitUnitCategory, InitUnitType, TargetUnitName, TargetUnitCoalition, TargetUnitCategory, TargetUnitType )
|
||||||
end
|
end
|
||||||
else -- A scenery object was hit.
|
else -- A scenery object was hit.
|
||||||
MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. InitPlayerName .. "' hit scenery object.",
|
MESSAGE:NewType( self.DisplayMessagePrefix .. "Player '" .. InitPlayerName .. "' hit nothing special.",
|
||||||
MESSAGE.Type.Update )
|
MESSAGE.Type.Update )
|
||||||
:ToAllIf( self:IfMessagesHit() and self:IfMessagesToAll() )
|
:ToAllIf( self:IfMessagesHit() and self:IfMessagesToAll() )
|
||||||
:ToCoalitionIf( InitCoalition, self:IfMessagesHit() and self:IfMessagesToCoalition() )
|
:ToCoalitionIf( InitCoalition, self:IfMessagesHit() and self:IfMessagesToCoalition() )
|
||||||
|
|||||||
@@ -3153,7 +3153,7 @@ end
|
|||||||
-- @param #WAREHOUSE self
|
-- @param #WAREHOUSE self
|
||||||
-- @return Core.Point#COORDINATE The coordinate of the warehouse.
|
-- @return Core.Point#COORDINATE The coordinate of the warehouse.
|
||||||
function WAREHOUSE:GetCoordinate()
|
function WAREHOUSE:GetCoordinate()
|
||||||
return self.warehouse:GetCoordinate()
|
return self.warehouse:GetCoord()
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Get 3D vector of warehouse static.
|
--- Get 3D vector of warehouse static.
|
||||||
@@ -6893,7 +6893,7 @@ function WAREHOUSE:_CheckConquered()
|
|||||||
for _,_unit in pairs(units) do
|
for _,_unit in pairs(units) do
|
||||||
local unit=_unit --Wrapper.Unit#UNIT
|
local unit=_unit --Wrapper.Unit#UNIT
|
||||||
|
|
||||||
local distance=coord:Get2DDistance(unit:GetCoordinate())
|
local distance=coord:Get2DDistance(unit:GetCoord())
|
||||||
|
|
||||||
-- Filter only alive groud units. Also check distance again, because the scan routine might give some larger distances.
|
-- Filter only alive groud units. Also check distance again, because the scan routine might give some larger distances.
|
||||||
if unit:IsGround() and unit:IsAlive() and distance <= radius then
|
if unit:IsGround() and unit:IsAlive() and distance <= radius then
|
||||||
|
|||||||
@@ -7,6 +7,8 @@
|
|||||||
--
|
--
|
||||||
-- # Developer Note
|
-- # Developer Note
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||||
-- Therefore, this class is considered to be deprecated
|
-- Therefore, this class is considered to be deprecated
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -2798,7 +2798,7 @@ function ATIS:onafterBroadcast( From, Event, To )
|
|||||||
|
|
||||||
end
|
end
|
||||||
_RUNACT = subtitle
|
_RUNACT = subtitle
|
||||||
alltext = alltext .. ";\n" .. subtitle
|
--alltext = alltext .. ";\n" .. subtitle
|
||||||
|
|
||||||
-- Runway length.
|
-- Runway length.
|
||||||
if self.rwylength then
|
if self.rwylength then
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -31,7 +31,7 @@
|
|||||||
-- @image OPS_CSAR.jpg
|
-- @image OPS_CSAR.jpg
|
||||||
|
|
||||||
---
|
---
|
||||||
-- Last Update Jan 2025
|
-- Last Update July 2025
|
||||||
|
|
||||||
-------------------------------------------------------------------------
|
-------------------------------------------------------------------------
|
||||||
--- **CSAR** class, extends Core.Base#BASE, Core.Fsm#FSM
|
--- **CSAR** class, extends Core.Base#BASE, Core.Fsm#FSM
|
||||||
@@ -130,7 +130,7 @@
|
|||||||
-- ## 2.2 SRS Features and Other Features
|
-- ## 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\\ExternalAudio\\" -- adjust your own path in your SRS installation -- server(!)
|
||||||
-- mycsar.SRSchannel = 300 -- radio channel
|
-- mycsar.SRSchannel = 300 -- radio channel
|
||||||
-- mycsar.SRSModulation = radio.modulation.AM -- modulation
|
-- mycsar.SRSModulation = radio.modulation.AM -- modulation
|
||||||
-- mycsar.SRSport = 5002 -- and SRS Server port
|
-- mycsar.SRSport = 5002 -- and SRS Server port
|
||||||
@@ -263,6 +263,7 @@ CSAR = {
|
|||||||
rescuedpilots = 0,
|
rescuedpilots = 0,
|
||||||
limitmaxdownedpilots = true,
|
limitmaxdownedpilots = true,
|
||||||
maxdownedpilots = 10,
|
maxdownedpilots = 10,
|
||||||
|
useFIFOLimitReplacement = false, -- If true, it will remove the oldest downed pilot when a new one is added, if the limit is reached.
|
||||||
allheligroupset = nil,
|
allheligroupset = nil,
|
||||||
topmenuname = "CSAR",
|
topmenuname = "CSAR",
|
||||||
ADFRadioPwr = 1000,
|
ADFRadioPwr = 1000,
|
||||||
@@ -313,7 +314,7 @@ CSAR.AircraftType["CH-47Fbl1"] = 31
|
|||||||
|
|
||||||
--- CSAR class version.
|
--- CSAR class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
CSAR.version="1.0.30"
|
CSAR.version="1.0.33"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- ToDo list
|
-- ToDo list
|
||||||
@@ -468,7 +469,7 @@ function CSAR:New(Coalition, Template, Alias)
|
|||||||
-- added 1.0.15
|
-- added 1.0.15
|
||||||
self.allowbronco = false -- set to true to use the Bronco mod as a CSAR plane
|
self.allowbronco = false -- set to true to use the Bronco mod as a CSAR plane
|
||||||
|
|
||||||
self.ADFRadioPwr = 1000
|
self.ADFRadioPwr = 500
|
||||||
|
|
||||||
-- added 1.0.16
|
-- added 1.0.16
|
||||||
self.PilotWeight = 80
|
self.PilotWeight = 80
|
||||||
@@ -480,7 +481,7 @@ function CSAR:New(Coalition, Template, Alias)
|
|||||||
-- 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)
|
||||||
self.useSRS = false -- Use FF\'s SRS integration
|
self.useSRS = false -- Use FF\'s SRS integration
|
||||||
self.SRSPath = "E:\\Program Files\\DCS-SimpleRadio-Standalone" -- adjust your own path in your server(!)
|
self.SRSPath = "E:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio" -- adjust your own path in your server(!)
|
||||||
self.SRSchannel = 300 -- radio channel
|
self.SRSchannel = 300 -- radio channel
|
||||||
self.SRSModulation = radio.modulation.AM -- modulation
|
self.SRSModulation = radio.modulation.AM -- modulation
|
||||||
self.SRSport = 5002 -- port
|
self.SRSport = 5002 -- port
|
||||||
@@ -1145,17 +1146,6 @@ function CSAR:_EventHandler(EventData)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
-- limit no of pilots in the field.
|
|
||||||
if self.limitmaxdownedpilots and self:_ReachedPilotLimit() then
|
|
||||||
self:T("Maxed Downed Pilot!")
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
-- TODO: Over water check --- EVENTS.LandingAfterEjection NOT triggered by DCS, so handle csarUsePara = true case
|
|
||||||
-- might create dual pilots in edge cases
|
|
||||||
|
|
||||||
local wetfeet = false
|
|
||||||
|
|
||||||
local initdcscoord = nil
|
local initdcscoord = nil
|
||||||
local initcoord = nil
|
local initcoord = nil
|
||||||
@@ -1169,6 +1159,36 @@ function CSAR:_EventHandler(EventData)
|
|||||||
self:T({initdcscoord})
|
self:T({initdcscoord})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Remove downed pilot if already exists to replace with new one.
|
||||||
|
if _event.IniPlayerName then
|
||||||
|
local PilotTable = self.downedPilots --#CSAR.DownedPilot
|
||||||
|
local _foundPilot = nil
|
||||||
|
for _,_pilot in pairs(PilotTable) do
|
||||||
|
if _pilot.player == _event.IniPlayerName and _pilot.alive == true then
|
||||||
|
_foundPilot = _pilot
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if _foundPilot then
|
||||||
|
self:T("Downed pilot already exists!")
|
||||||
|
_foundPilot.group:Destroy(false)
|
||||||
|
self:_RemoveNameFromDownedPilots(_foundPilot.name)
|
||||||
|
self:_CheckDownedPilotTable()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- limit no of pilots in the field.
|
||||||
|
if self.limitmaxdownedpilots and self:_ReachedPilotLimit() then
|
||||||
|
self:T("Maxed Downed Pilot!")
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- TODO: Over water check --- EVENTS.LandingAfterEjection NOT triggered by DCS, so handle csarUsePara = true case
|
||||||
|
-- might create dual pilots in edge cases
|
||||||
|
|
||||||
|
local wetfeet = false
|
||||||
|
|
||||||
--local surface = _unit:GetCoordinate():GetSurfaceType()
|
--local surface = _unit:GetCoordinate():GetSurfaceType()
|
||||||
local surface = initcoord:GetSurfaceType()
|
local surface = initcoord:GetSurfaceType()
|
||||||
|
|
||||||
@@ -1179,7 +1199,7 @@ function CSAR:_EventHandler(EventData)
|
|||||||
-- all checks passed, get going.
|
-- all checks passed, get going.
|
||||||
if self.csarUsePara == false or (self.csarUsePara and wetfeet ) then --shagrat check parameter LandingAfterEjection, if true don't spawn a Pilot from EJECTION event, wait for the Chute to land
|
if self.csarUsePara == false or (self.csarUsePara and wetfeet ) then --shagrat check parameter LandingAfterEjection, if true don't spawn a Pilot from EJECTION event, wait for the Chute to land
|
||||||
local _freq = self:_GenerateADFFrequency()
|
local _freq = self:_GenerateADFFrequency()
|
||||||
self:_AddCsar(_coalition, _unit:GetCountry(), initcoord , _unit:GetTypeName(), _unit:GetName(), _event.IniPlayerName, _freq, false, "none")
|
self:_AddCsar(_coalition, _unit:GetCountry(), initcoord , _unit:GetTypeName(), _unit:GetName(), _event.IniPlayerName, _freq, self.suppressmessages, "none")
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1244,7 +1264,7 @@ function CSAR:_EventHandler(EventData)
|
|||||||
if _coalition == self.coalition then
|
if _coalition == self.coalition then
|
||||||
local _freq = self:_GenerateADFFrequency()
|
local _freq = self:_GenerateADFFrequency()
|
||||||
self:I({coalition=_coalition,country= _country, coord=_LandingPos, name=_unitname, player=_event.IniPlayerName, freq=_freq})
|
self:I({coalition=_coalition,country= _country, coord=_LandingPos, name=_unitname, player=_event.IniPlayerName, freq=_freq})
|
||||||
self:_AddCsar(_coalition, _country, _LandingPos, nil, _unitname, _event.IniPlayerName, _freq, false, "none")--shagrat add CSAR at Parachute location.
|
self:_AddCsar(_coalition, _country, _LandingPos, nil, _unitname, _event.IniPlayerName, _freq, self.suppressmessages, "none")--shagrat add CSAR at Parachute location.
|
||||||
|
|
||||||
Unit.destroy(_event.initiator) -- shagrat remove static Pilot model
|
Unit.destroy(_event.initiator) -- shagrat remove static Pilot model
|
||||||
end
|
end
|
||||||
@@ -2116,56 +2136,50 @@ end
|
|||||||
--- (Internal) Determine distance to closest MASH.
|
--- (Internal) Determine distance to closest MASH.
|
||||||
-- @param #CSAR self
|
-- @param #CSAR self
|
||||||
-- @param Wrapper.Unit#UNIT _heli Helicopter #UNIT
|
-- @param Wrapper.Unit#UNIT _heli Helicopter #UNIT
|
||||||
-- @return #CSAR self
|
-- @return #number Distance in meters
|
||||||
|
-- @return #string MASH Name as string
|
||||||
function CSAR:_GetClosestMASH(_heli)
|
function CSAR:_GetClosestMASH(_heli)
|
||||||
self:T(self.lid .. " _GetClosestMASH")
|
self:T(self.lid .. " _GetClosestMASH")
|
||||||
local _mashset = self.mash -- Core.Set#SET_GROUP
|
local _mashset = self.mash -- Core.Set#SET_GROUP
|
||||||
local _mashes = _mashset:GetSetObjects() -- #table
|
local MashSets = {}
|
||||||
|
--local _mashes = _mashset.Set-- #table
|
||||||
|
table.insert(MashSets,_mashset.Set)
|
||||||
|
table.insert(MashSets,self.zonemashes.Set)
|
||||||
|
table.insert(MashSets,self.staticmashes.Set)
|
||||||
local _shortestDistance = -1
|
local _shortestDistance = -1
|
||||||
local _distance = 0
|
local _distance = 0
|
||||||
local _helicoord = _heli:GetCoordinate()
|
local _helicoord = _heli:GetCoordinate()
|
||||||
|
local MashName = nil
|
||||||
local function GetCloseAirbase(coordinate,Coalition,Category)
|
|
||||||
|
|
||||||
local a=coordinate:GetVec3()
|
|
||||||
local distmin=math.huge
|
|
||||||
local airbase=nil
|
|
||||||
for DCSairbaseID, DCSairbase in pairs(world.getAirbases(Coalition)) do
|
|
||||||
local b=DCSairbase:getPoint()
|
|
||||||
|
|
||||||
local c=UTILS.VecSubstract(a,b)
|
|
||||||
local dist=UTILS.VecNorm(c)
|
|
||||||
|
|
||||||
if dist<distmin and (Category==nil or Category==DCSairbase:getDesc().category) then
|
|
||||||
distmin=dist
|
|
||||||
airbase=DCSairbase
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
return distmin
|
|
||||||
end
|
|
||||||
|
|
||||||
if self.allowFARPRescue then
|
if self.allowFARPRescue then
|
||||||
local position = _heli:GetCoordinate()
|
local position = _heli:GetCoordinate()
|
||||||
local afb,distance = position:GetClosestAirbase(nil,self.coalition)
|
local afb,distance = position:GetClosestAirbase(nil,self.coalition)
|
||||||
_shortestDistance = distance
|
_shortestDistance = distance
|
||||||
|
MashName = (afb ~= nil) and afb:GetName() or "Unknown"
|
||||||
end
|
end
|
||||||
|
|
||||||
for _, _mashUnit in pairs(_mashes) do
|
for _,_mashes in pairs(MashSets) do
|
||||||
if _mashUnit and _mashUnit:IsAlive() then
|
for _, _mashUnit in pairs(_mashes or {}) do
|
||||||
local _mashcoord = _mashUnit:GetCoordinate()
|
local _mashcoord
|
||||||
|
if _mashUnit and (not _mashUnit:IsInstanceOf("ZONE_BASE")) and _mashUnit:IsAlive() then
|
||||||
|
_mashcoord = _mashUnit:GetCoordinate()
|
||||||
|
elseif _mashUnit and _mashUnit:IsInstanceOf("ZONE_BASE") then
|
||||||
|
_mashcoord = _mashUnit:GetCoordinate()
|
||||||
|
end
|
||||||
_distance = self:_GetDistance(_helicoord, _mashcoord)
|
_distance = self:_GetDistance(_helicoord, _mashcoord)
|
||||||
if _distance ~= nil and (_shortestDistance == -1 or _distance < _shortestDistance) then
|
if _distance ~= nil and (_shortestDistance == -1 or _distance < _shortestDistance) then
|
||||||
_shortestDistance = _distance
|
_shortestDistance = _distance
|
||||||
|
MashName = _mashUnit:GetName() or "Unknown"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if _shortestDistance ~= -1 then
|
if _shortestDistance ~= -1 then
|
||||||
return _shortestDistance
|
return _shortestDistance, MashName
|
||||||
else
|
else
|
||||||
return -1
|
return -1
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- (Internal) Display onboarded rescued pilots.
|
--- (Internal) Display onboarded rescued pilots.
|
||||||
@@ -2323,9 +2337,9 @@ 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
|
||||||
-- @param #string _name Beacon Name to use
|
-- @param #string BeaconName Beacon Name to use
|
||||||
-- @return #CSAR self
|
-- @return #CSAR self
|
||||||
function CSAR:_AddBeaconToGroup(_group, _freq, _name)
|
function CSAR:_AddBeaconToGroup(_group, _freq, BeaconName)
|
||||||
self:T(self.lid .. " _AddBeaconToGroup")
|
self:T(self.lid .. " _AddBeaconToGroup")
|
||||||
if self.CreateRadioBeacons == false then return end
|
if self.CreateRadioBeacons == false then return end
|
||||||
local _group = _group
|
local _group = _group
|
||||||
@@ -2346,10 +2360,11 @@ function CSAR:_AddBeaconToGroup(_group, _freq, _name)
|
|||||||
if _radioUnit then
|
if _radioUnit then
|
||||||
local name = _radioUnit:GetName()
|
local name = _radioUnit:GetName()
|
||||||
local Frequency = _freq -- Freq in Hertz
|
local Frequency = _freq -- Freq in Hertz
|
||||||
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) -- Beacon in MP only runs for exactly 30secs straight
|
self:I(self.lid..string.format("Added Radio Beacon %d Hertz | Name %s | Position {%d,%d,%d}",Frequency,BeaconName,vec3.x,vec3.y,vec3.z))
|
||||||
|
trigger.action.radioTransmission(Sound, vec3, 0, true, Frequency, self.ADFRadioPwr or 500,BeaconName) -- Beacon in MP only runs for exactly 30secs straight
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -2370,9 +2385,13 @@ function CSAR:_RefreshRadioBeacons()
|
|||||||
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)
|
local bname = pilot.BeaconName or pilot.name..math.random(1,100000)
|
||||||
trigger.action.stopRadioTransmission(bname)
|
--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,bname)
|
--self:_AddBeaconToGroup(group,frequency,bname)
|
||||||
|
else
|
||||||
|
if frequency > 0 then
|
||||||
|
trigger.action.stopRadioTransmission(bname)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -2403,6 +2422,21 @@ function CSAR:_ReachedPilotLimit()
|
|||||||
local islimited = self.limitmaxdownedpilots
|
local islimited = self.limitmaxdownedpilots
|
||||||
local count = self:_CountActiveDownedPilots()
|
local count = self:_CountActiveDownedPilots()
|
||||||
if islimited and (count >= limit) then
|
if islimited and (count >= limit) then
|
||||||
|
if self.useFIFOLimitReplacement then
|
||||||
|
local oldIndex = -1
|
||||||
|
local oldDownedPilot = nil
|
||||||
|
for _index, _downedpilot in pairs(self.downedPilots) do
|
||||||
|
oldIndex = _index
|
||||||
|
oldDownedPilot = _downedpilot
|
||||||
|
break
|
||||||
|
end
|
||||||
|
if oldDownedPilot then
|
||||||
|
oldDownedPilot.group:Destroy(false)
|
||||||
|
oldDownedPilot.alive = false
|
||||||
|
self:_CheckDownedPilotTable()
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
end
|
||||||
return true
|
return true
|
||||||
else
|
else
|
||||||
return false
|
return false
|
||||||
@@ -2454,9 +2488,10 @@ function CSAR:onafterStart(From, Event, To)
|
|||||||
|
|
||||||
self.mash = SET_GROUP:New():FilterCoalitions(self.coalitiontxt):FilterPrefixes(self.mashprefix):FilterStart()
|
self.mash = SET_GROUP:New():FilterCoalitions(self.coalitiontxt):FilterPrefixes(self.mashprefix):FilterStart()
|
||||||
|
|
||||||
local staticmashes = SET_STATIC:New():FilterCoalitions(self.coalitiontxt):FilterPrefixes(self.mashprefix):FilterOnce()
|
self.staticmashes = SET_STATIC:New():FilterCoalitions(self.coalitiontxt):FilterPrefixes(self.mashprefix):FilterStart()
|
||||||
local zonemashes = SET_ZONE:New():FilterPrefixes(self.mashprefix):FilterOnce()
|
self.zonemashes = SET_ZONE:New():FilterPrefixes(self.mashprefix):FilterStart()
|
||||||
|
|
||||||
|
--[[
|
||||||
if staticmashes:Count() > 0 then
|
if staticmashes:Count() > 0 then
|
||||||
for _,_mash in pairs(staticmashes.Set) do
|
for _,_mash in pairs(staticmashes.Set) do
|
||||||
self.mash:AddObject(_mash)
|
self.mash:AddObject(_mash)
|
||||||
@@ -2464,10 +2499,13 @@ function CSAR:onafterStart(From, Event, To)
|
|||||||
end
|
end
|
||||||
|
|
||||||
if zonemashes:Count() > 0 then
|
if zonemashes:Count() > 0 then
|
||||||
|
self:T("Adding zones to self.mash SET")
|
||||||
for _,_mash in pairs(zonemashes.Set) do
|
for _,_mash in pairs(zonemashes.Set) do
|
||||||
self.mash:AddObject(_mash)
|
self.mash:AddObject(_mash)
|
||||||
end
|
end
|
||||||
|
self:T("Objects in SET: "..self.mash:Count())
|
||||||
end
|
end
|
||||||
|
--]]
|
||||||
|
|
||||||
if not self.coordinate then
|
if not self.coordinate then
|
||||||
local csarhq = self.mash:GetRandom()
|
local csarhq = self.mash:GetRandom()
|
||||||
@@ -2968,7 +3006,7 @@ function CSAR:onafterLoad(From, Event, To, path, filename)
|
|||||||
local unitName = dataset[9]
|
local unitName = dataset[9]
|
||||||
local freq = tonumber(dataset[10])
|
local freq = tonumber(dataset[10])
|
||||||
|
|
||||||
self:_AddCsar(coalition, country, point, typeName, unitName, playerName, freq, nil, description, nil)
|
self:_AddCsar(coalition, country, point, typeName, unitName, playerName, freq, false, description, nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
|
|||||||
@@ -20,11 +20,12 @@
|
|||||||
--
|
--
|
||||||
-- ### Author: **Applevangelist** (Moose Version), ***Ciribob*** (original), Thanks to: Shadowze, Cammel (testing), bbirchnz (additional code!!)
|
-- ### Author: **Applevangelist** (Moose Version), ***Ciribob*** (original), Thanks to: Shadowze, Cammel (testing), bbirchnz (additional code!!)
|
||||||
-- ### Repack addition for crates: **Raiden**
|
-- ### Repack addition for crates: **Raiden**
|
||||||
|
-- ### Additional cool features: **Lekaa**
|
||||||
--
|
--
|
||||||
-- @module Ops.CTLD
|
-- @module Ops.CTLD
|
||||||
-- @image OPS_CTLD.jpg
|
-- @image OPS_CTLD.jpg
|
||||||
|
|
||||||
-- Last Update April 2025
|
-- Last Update July 2025
|
||||||
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
@@ -865,6 +866,8 @@ do
|
|||||||
-- my_ctld.TroopUnloadDistGroundHook = 15 -- On the ground, unload troops this far behind the Chinook
|
-- my_ctld.TroopUnloadDistGroundHook = 15 -- On the ground, unload troops this far behind the Chinook
|
||||||
-- my_ctld.TroopUnloadDistHoverHook = 5 -- When hovering, unload troops this far behind the Chinook
|
-- my_ctld.TroopUnloadDistHoverHook = 5 -- When hovering, unload troops this far behind the Chinook
|
||||||
-- my_ctld.showstockinmenuitems = false -- When set to true, the menu lines will also show the remaining items in stock (that is, if you set any), downside is that the menu for all will be build every 30 seconds anew.
|
-- my_ctld.showstockinmenuitems = false -- When set to true, the menu lines will also show the remaining items in stock (that is, if you set any), downside is that the menu for all will be build every 30 seconds anew.
|
||||||
|
-- my_ctld.onestepmenu = false -- When set to true, the menu will create Drop and build, Get and load, Pack and remove, Pack and load, Pack. it will be a 1 step solution.
|
||||||
|
-- my_ctld.VehicleMoveFormation = AI.Task.VehicleFormation.VEE -- When a group moves to a MOVE zone, then it takes this formation. Can be a table of formations, which are then randomly chosen. Defaults to "Vee".
|
||||||
--
|
--
|
||||||
-- ## 2.1 CH-47 Chinook support
|
-- ## 2.1 CH-47 Chinook support
|
||||||
--
|
--
|
||||||
@@ -1292,6 +1295,7 @@ CTLD = {
|
|||||||
LoadedGroupsTable = {},
|
LoadedGroupsTable = {},
|
||||||
keeploadtable = true,
|
keeploadtable = true,
|
||||||
allowCATransport = false,
|
allowCATransport = false,
|
||||||
|
VehicleMoveFormation = AI.Task.VehicleFormation.VEE,
|
||||||
}
|
}
|
||||||
|
|
||||||
------------------------------
|
------------------------------
|
||||||
@@ -1412,7 +1416,7 @@ CTLD.FixedWingTypes = {
|
|||||||
|
|
||||||
--- CTLD class version.
|
--- CTLD class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
CTLD.version="1.2.33"
|
CTLD.version="1.3.37"
|
||||||
|
|
||||||
--- Instantiate a new CTLD.
|
--- Instantiate a new CTLD.
|
||||||
-- @param #CTLD self
|
-- @param #CTLD self
|
||||||
@@ -1479,6 +1483,7 @@ function CTLD:New(Coalition, Prefixes, Alias)
|
|||||||
self:AddTransition("*", "CratesRepaired", "*") -- CTLD repair event.
|
self:AddTransition("*", "CratesRepaired", "*") -- CTLD repair event.
|
||||||
self:AddTransition("*", "CratesBuildStarted", "*") -- CTLD build event.
|
self:AddTransition("*", "CratesBuildStarted", "*") -- CTLD build event.
|
||||||
self:AddTransition("*", "CratesRepairStarted", "*") -- CTLD repair event.
|
self:AddTransition("*", "CratesRepairStarted", "*") -- CTLD repair event.
|
||||||
|
self:AddTransition("*", "CratesPacked", "*") -- CTLD repack event.
|
||||||
self:AddTransition("*", "HelicopterLost", "*") -- CTLD lost event.
|
self:AddTransition("*", "HelicopterLost", "*") -- CTLD lost event.
|
||||||
self:AddTransition("*", "Load", "*") -- CTLD load event.
|
self:AddTransition("*", "Load", "*") -- CTLD load event.
|
||||||
self:AddTransition("*", "Loaded", "*") -- CTLD load event.
|
self:AddTransition("*", "Loaded", "*") -- CTLD load event.
|
||||||
@@ -1551,6 +1556,8 @@ function CTLD:New(Coalition, Prefixes, Alias)
|
|||||||
self.movetroopsdistance = 5000
|
self.movetroopsdistance = 5000
|
||||||
self.troopdropzoneradius = 100
|
self.troopdropzoneradius = 100
|
||||||
|
|
||||||
|
self.VehicleMoveFormation = AI.Task.VehicleFormation.VEE
|
||||||
|
|
||||||
-- added support Hercules Mod
|
-- added support Hercules Mod
|
||||||
self.enableHercules = false -- deprecated
|
self.enableHercules = false -- deprecated
|
||||||
self.enableFixedWing = false
|
self.enableFixedWing = false
|
||||||
@@ -1591,6 +1598,7 @@ function CTLD:New(Coalition, Prefixes, Alias)
|
|||||||
self.subcats = {}
|
self.subcats = {}
|
||||||
self.subcatsTroop = {}
|
self.subcatsTroop = {}
|
||||||
self.showstockinmenuitems = false
|
self.showstockinmenuitems = false
|
||||||
|
self.onestepmenu = false
|
||||||
|
|
||||||
-- disallow building in loadzones
|
-- disallow building in loadzones
|
||||||
self.nobuildinloadzones = true
|
self.nobuildinloadzones = true
|
||||||
@@ -1757,6 +1765,17 @@ function CTLD:New(Coalition, Prefixes, Alias)
|
|||||||
-- @param Wrapper.Group#GROUP Vehicle The #GROUP object of the vehicle or FOB repaired.
|
-- @param Wrapper.Group#GROUP Vehicle The #GROUP object of the vehicle or FOB repaired.
|
||||||
-- @return #CTLD self
|
-- @return #CTLD self
|
||||||
|
|
||||||
|
--- FSM Function OnBeforeCratesPacked.
|
||||||
|
-- @function [parent=#CTLD] OnBeforeCratesPacked
|
||||||
|
-- @param #CTLD self
|
||||||
|
-- @param #string From State.
|
||||||
|
-- @param #string Event Trigger.
|
||||||
|
-- @param #string To State.
|
||||||
|
-- @param Wrapper.Group#GROUP Group Group Object.
|
||||||
|
-- @param Wrapper.Unit#UNIT Unit Unit Object.
|
||||||
|
-- @param #CTLD_CARGO Cargo Cargo crate that was repacked.
|
||||||
|
-- @return #CTLD self
|
||||||
|
|
||||||
--- FSM Function OnBeforeTroopsRTB.
|
--- FSM Function OnBeforeTroopsRTB.
|
||||||
-- @function [parent=#CTLD] OnBeforeTroopsRTB
|
-- @function [parent=#CTLD] OnBeforeTroopsRTB
|
||||||
-- @param #CTLD self
|
-- @param #CTLD self
|
||||||
@@ -1843,6 +1862,7 @@ function CTLD:New(Coalition, Prefixes, Alias)
|
|||||||
-- @param #string To State.
|
-- @param #string To State.
|
||||||
-- @param Wrapper.Group#GROUP Group Group Object.
|
-- @param Wrapper.Group#GROUP Group Group Object.
|
||||||
-- @param Wrapper.Unit#UNIT Unit Unit Object.
|
-- @param Wrapper.Unit#UNIT Unit Unit Object.
|
||||||
|
-- @param CargoName The name of the cargo being built.
|
||||||
-- @return #CTLD self
|
-- @return #CTLD self
|
||||||
|
|
||||||
--- FSM Function OnAfterCratesRepairStarted. Info event that a repair has been started.
|
--- FSM Function OnAfterCratesRepairStarted. Info event that a repair has been started.
|
||||||
@@ -1886,6 +1906,17 @@ function CTLD:New(Coalition, Prefixes, Alias)
|
|||||||
-- @param Wrapper.Group#GROUP Vehicle The #GROUP object of the vehicle or FOB repaired.
|
-- @param Wrapper.Group#GROUP Vehicle The #GROUP object of the vehicle or FOB repaired.
|
||||||
-- @return #CTLD self
|
-- @return #CTLD self
|
||||||
|
|
||||||
|
--- FSM Function OnAfterCratesPacked.
|
||||||
|
-- @function [parent=#CTLD] OnAfterCratesPacked
|
||||||
|
-- @param #CTLD self
|
||||||
|
-- @param #string From State.
|
||||||
|
-- @param #string Event Trigger.
|
||||||
|
-- @param #string To State.
|
||||||
|
-- @param Wrapper.Group#GROUP Group Group Object.
|
||||||
|
-- @param Wrapper.Unit#UNIT Unit Unit Object.
|
||||||
|
-- @param #CTLD_CARGO Cargo Cargo crate that was repacked.
|
||||||
|
-- @return #CTLD self
|
||||||
|
|
||||||
--- FSM Function OnAfterTroopsRTB.
|
--- FSM Function OnAfterTroopsRTB.
|
||||||
-- @function [parent=#CTLD] OnAfterTroopsRTB
|
-- @function [parent=#CTLD] OnAfterTroopsRTB
|
||||||
-- @param #CTLD self
|
-- @param #CTLD self
|
||||||
@@ -2072,6 +2103,9 @@ function CTLD:_EventHandler(EventData)
|
|||||||
local _group = event.IniGroup
|
local _group = event.IniGroup
|
||||||
local _unit = event.IniUnit
|
local _unit = event.IniUnit
|
||||||
self:_RefreshLoadCratesMenu(_group, _unit)
|
self:_RefreshLoadCratesMenu(_group, _unit)
|
||||||
|
if self:IsFixedWing(_unit) and self.enableFixedWing then
|
||||||
|
self:_RefreshDropCratesMenu(_group, _unit)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
elseif event.id == EVENTS.PlayerLeaveUnit or event.id == EVENTS.UnitLost then
|
elseif event.id == EVENTS.PlayerLeaveUnit or event.id == EVENTS.UnitLost then
|
||||||
-- remove from pilot table
|
-- remove from pilot table
|
||||||
@@ -2821,7 +2855,11 @@ function CTLD:_GetCrates(Group, Unit, Cargo, number, drop, pack)
|
|||||||
if cratedistance > self.CrateDistance then cratedistance = self.CrateDistance end
|
if cratedistance > self.CrateDistance then cratedistance = self.CrateDistance end
|
||||||
-- altered heading logic
|
-- altered heading logic
|
||||||
-- DONE: right standard deviation?
|
-- DONE: right standard deviation?
|
||||||
|
if self:IsUnitInAir(Unit) and self:IsFixedWing(Unit) then
|
||||||
|
rheading = math.random(20,60)
|
||||||
|
else
|
||||||
rheading = UTILS.RandomGaussian(0, 30, -90, 90, 100)
|
rheading = UTILS.RandomGaussian(0, 30, -90, 90, 100)
|
||||||
|
end
|
||||||
rheading=math.fmod((heading+rheading),360)
|
rheading=math.fmod((heading+rheading),360)
|
||||||
cratecoord = position:Translate(cratedistance,rheading)
|
cratecoord = position:Translate(cratedistance,rheading)
|
||||||
else
|
else
|
||||||
@@ -2913,10 +2951,10 @@ function CTLD:_GetCrates(Group, Unit, Cargo, number, drop, pack)
|
|||||||
if drop then
|
if drop then
|
||||||
text = string.format("Crates for %s have been dropped!",cratename)
|
text = string.format("Crates for %s have been dropped!",cratename)
|
||||||
self:__CratesDropped(1, Group, Unit, droppedcargo)
|
self:__CratesDropped(1, Group, Unit, droppedcargo)
|
||||||
end
|
else
|
||||||
self:_SendMessage(text, 10, false, Group)
|
self:_SendMessage(text, 10, false, Group)
|
||||||
|
end
|
||||||
self:_RefreshLoadCratesMenu(Group, Unit)
|
self:_RefreshLoadCratesMenu(Group, Unit)
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -3564,7 +3602,7 @@ end
|
|||||||
function CTLD:IsFixedWing(Unit)
|
function CTLD:IsFixedWing(Unit)
|
||||||
local typename = Unit:GetTypeName() or "none"
|
local typename = Unit:GetTypeName() or "none"
|
||||||
for _,_name in pairs(self.FixedWingTypes or {}) do
|
for _,_name in pairs(self.FixedWingTypes or {}) do
|
||||||
if typename == _name or string.find(typename,_name,1,true) then
|
if _name and (typename==_name or string.find(typename,_name,1,true))then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -3576,7 +3614,10 @@ end
|
|||||||
-- @param Wrapper.Unit#UNIT Unit
|
-- @param Wrapper.Unit#UNIT Unit
|
||||||
-- @return #boolean Outcome
|
-- @return #boolean Outcome
|
||||||
function CTLD:IsHook(Unit)
|
function CTLD:IsHook(Unit)
|
||||||
if Unit and string.find(Unit:GetTypeName(),"CH.47") then
|
if not Unit then return false end
|
||||||
|
local typeName = Unit:GetTypeName()
|
||||||
|
if not typeName then return false end
|
||||||
|
if string.find(typeName, "CH.47") then
|
||||||
return true
|
return true
|
||||||
else
|
else
|
||||||
return false
|
return false
|
||||||
@@ -3766,7 +3807,6 @@ function CTLD:_UnloadCrates(Group, Unit)
|
|||||||
self:T(self.lid .. " _UnloadCrates")
|
self:T(self.lid .. " _UnloadCrates")
|
||||||
|
|
||||||
if not self.dropcratesanywhere then -- #1570
|
if not self.dropcratesanywhere then -- #1570
|
||||||
-- check if we are in DROP zone
|
|
||||||
local inzone, zonename, zone, distance = self:IsUnitInZone(Unit,CTLD.CargoZoneType.DROP)
|
local inzone, zonename, zone, distance = self:IsUnitInZone(Unit,CTLD.CargoZoneType.DROP)
|
||||||
if not inzone then
|
if not inzone then
|
||||||
self:_SendMessage("You are not close enough to a drop zone!", 10, false, Group)
|
self:_SendMessage("You are not close enough to a drop zone!", 10, false, Group)
|
||||||
@@ -3775,46 +3815,60 @@ function CTLD:_UnloadCrates(Group, Unit)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
-- Door check
|
|
||||||
if self.pilotmustopendoors and not UTILS.IsLoadingDoorOpen(Unit:GetName()) then
|
if self.pilotmustopendoors and not UTILS.IsLoadingDoorOpen(Unit:GetName()) then
|
||||||
self:_SendMessage("You need to open the door(s) to drop cargo!", 10, false, Group)
|
self:_SendMessage("You need to open the door(s) to drop cargo!", 10, false, Group)
|
||||||
if not self.debug then return self end
|
if not self.debug then return self end
|
||||||
end
|
end
|
||||||
-- check for hover unload
|
local hoverunload = self:IsCorrectHover(Unit)
|
||||||
local hoverunload = self:IsCorrectHover(Unit) --if true we\'re hovering in parameters
|
|
||||||
local IsHerc = self:IsFixedWing(Unit)
|
local IsHerc = self:IsFixedWing(Unit)
|
||||||
local IsHook = self:IsHook(Unit)
|
local IsHook = self:IsHook(Unit)
|
||||||
if IsHerc and (not IsHook) then
|
if IsHerc and (not IsHook) then
|
||||||
-- no hover but airdrop here
|
|
||||||
hoverunload = self:IsCorrectFlightParameters(Unit)
|
hoverunload = self:IsCorrectFlightParameters(Unit)
|
||||||
end
|
end
|
||||||
-- check if we\'re landed
|
|
||||||
local grounded = not self:IsUnitInAir(Unit)
|
local grounded = not self:IsUnitInAir(Unit)
|
||||||
-- Get what we have loaded
|
|
||||||
local unitname = Unit:GetName()
|
local unitname = Unit:GetName()
|
||||||
if self.Loaded_Cargo[unitname] and (grounded or hoverunload) then
|
if self.Loaded_Cargo[unitname] and (grounded or hoverunload) then
|
||||||
local loadedcargo = self.Loaded_Cargo[unitname] or {} -- #CTLD.LoadedCargo
|
local loadedcargo = self.Loaded_Cargo[unitname] or {}
|
||||||
-- looking for crate
|
|
||||||
local cargotable = loadedcargo.Cargo
|
local cargotable = loadedcargo.Cargo
|
||||||
|
local droppedCount = {}
|
||||||
|
local neededMap = {}
|
||||||
for _,_cargo in pairs (cargotable) do
|
for _,_cargo in pairs (cargotable) do
|
||||||
local cargo = _cargo -- #CTLD_CARGO
|
local cargo = _cargo
|
||||||
local type = cargo:GetType() -- #CTLD_CARGO.Enum
|
local type = cargo:GetType()
|
||||||
if type ~= CTLD_CARGO.Enum.TROOPS and type ~= CTLD_CARGO.Enum.ENGINEERS and type ~= CTLD_CARGO.Enum.GCLOADABLE and (not cargo:WasDropped() or self.allowcratepickupagain) then
|
if type ~= CTLD_CARGO.Enum.TROOPS and type ~= CTLD_CARGO.Enum.ENGINEERS and type ~= CTLD_CARGO.Enum.GCLOADABLE and (not cargo:WasDropped() or self.allowcratepickupagain) then
|
||||||
-- unload crates
|
|
||||||
self:_GetCrates(Group, Unit, cargo, 1, true)
|
self:_GetCrates(Group, Unit, cargo, 1, true)
|
||||||
cargo:SetWasDropped(true)
|
cargo:SetWasDropped(true)
|
||||||
cargo:SetHasMoved(true)
|
cargo:SetHasMoved(true)
|
||||||
|
local cname = cargo:GetName() or "Unknown"
|
||||||
|
droppedCount[cname] = (droppedCount[cname] or 0) + 1
|
||||||
|
if not neededMap[cname] then
|
||||||
|
neededMap[cname] = cargo:GetCratesNeeded() or 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
-- cleanup load list
|
end
|
||||||
local loaded = {} -- #CTLD.LoadedCargo
|
for cname,count in pairs(droppedCount) do
|
||||||
|
local needed = neededMap[cname] or 1
|
||||||
|
if needed > 1 then
|
||||||
|
local full = math.floor(count/needed)
|
||||||
|
local left = count % needed
|
||||||
|
if full > 0 and left == 0 then
|
||||||
|
self:_SendMessage(string.format("Dropped %d %s.",full,cname),10,false,Group)
|
||||||
|
elseif full > 0 and left > 0 then
|
||||||
|
self:_SendMessage(string.format("Dropped %d %s(s), with %d leftover crate(s).",full,cname,left),10,false,Group)
|
||||||
|
else
|
||||||
|
self:_SendMessage(string.format("Dropped %d/%d crate(s) of %s.",count,needed,cname),15,false,Group)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
self:_SendMessage(string.format("Dropped %d %s(s).",count,cname),10,false,Group)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local loaded = {}
|
||||||
loaded.Troopsloaded = 0
|
loaded.Troopsloaded = 0
|
||||||
loaded.Cratesloaded = 0
|
loaded.Cratesloaded = 0
|
||||||
loaded.Cargo = {}
|
loaded.Cargo = {}
|
||||||
|
|
||||||
for _,_cargo in pairs (cargotable) do
|
for _,_cargo in pairs (cargotable) do
|
||||||
local cargo = _cargo -- #CTLD_CARGO
|
local cargo = _cargo
|
||||||
local type = cargo:GetType() -- #CTLD_CARGO.Enum
|
local type = cargo:GetType()
|
||||||
local size = cargo:GetCratesNeeded()
|
local size = cargo:GetCratesNeeded()
|
||||||
if type == CTLD_CARGO.Enum.TROOPS or type == CTLD_CARGO.Enum.ENGINEERS then
|
if type == CTLD_CARGO.Enum.TROOPS or type == CTLD_CARGO.Enum.ENGINEERS then
|
||||||
table.insert(loaded.Cargo,_cargo)
|
table.insert(loaded.Cargo,_cargo)
|
||||||
@@ -3845,7 +3899,8 @@ end
|
|||||||
-- @param Wrapper.Group#GROUP Group
|
-- @param Wrapper.Group#GROUP Group
|
||||||
-- @param Wrapper.Unit#UNIT Unit
|
-- @param Wrapper.Unit#UNIT Unit
|
||||||
-- @param #boolean Engineering If true build is by an engineering team.
|
-- @param #boolean Engineering If true build is by an engineering team.
|
||||||
function CTLD:_BuildCrates(Group, Unit,Engineering)
|
-- @param #boolean MultiDrop If true and not engineering or FOB, vary position a bit.
|
||||||
|
function CTLD:_BuildCrates(Group, Unit,Engineering,MultiDrop)
|
||||||
self:T(self.lid .. " _BuildCrates")
|
self:T(self.lid .. " _BuildCrates")
|
||||||
-- avoid users trying to build from flying Hercs
|
-- avoid users trying to build from flying Hercs
|
||||||
if self:IsFixedWing(Unit) and self.enableFixedWing and not Engineering then
|
if self:IsFixedWing(Unit) and self.enableFixedWing and not Engineering then
|
||||||
@@ -3939,12 +3994,13 @@ function CTLD:_BuildCrates(Group, Unit,Engineering)
|
|||||||
if build.CanBuild then
|
if build.CanBuild then
|
||||||
self:_CleanUpCrates(crates,build,number)
|
self:_CleanUpCrates(crates,build,number)
|
||||||
if self.buildtime and self.buildtime > 0 then
|
if self.buildtime and self.buildtime > 0 then
|
||||||
local buildtimer = TIMER:New(self._BuildObjectFromCrates,self,Group,Unit,build,false,Group:GetCoordinate())
|
local buildtimer = TIMER:New(self._BuildObjectFromCrates,self,Group,Unit,build,false,Group:GetCoordinate(),MultiDrop)
|
||||||
buildtimer:Start(self.buildtime)
|
buildtimer:Start(self.buildtime)
|
||||||
self:_SendMessage(string.format("Build started, ready in %d seconds!",self.buildtime),15,false,Group)
|
self:_SendMessage(string.format("Build started, ready in %d seconds!",self.buildtime),15,false,Group)
|
||||||
self:__CratesBuildStarted(1,Group,Unit)
|
self:__CratesBuildStarted(1,Group,Unit,build.Name)
|
||||||
|
self:_RefreshDropTroopsMenu(Group,Unit)
|
||||||
else
|
else
|
||||||
self:_BuildObjectFromCrates(Group,Unit,build)
|
self:_BuildObjectFromCrates(Group,Unit,build,false,nil,MultiDrop)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -3983,13 +4039,15 @@ function CTLD:_PackCratesNearby(Group, Unit)
|
|||||||
_Group:Destroy() -- if a match is found destroy the Wrapper.Group#GROUP near the player
|
_Group:Destroy() -- if a match is found destroy the Wrapper.Group#GROUP near the player
|
||||||
self:_GetCrates(Group, Unit, _entry, nil, false, true) -- spawn the appropriate crates near the player
|
self:_GetCrates(Group, Unit, _entry, nil, false, true) -- spawn the appropriate crates near the player
|
||||||
self:_RefreshLoadCratesMenu(Group,Unit) -- call the refresher to show the crates in the menu
|
self:_RefreshLoadCratesMenu(Group,Unit) -- call the refresher to show the crates in the menu
|
||||||
return self
|
self:__CratesPacked(1,Group,Unit,_entry)
|
||||||
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return self
|
self:_SendMessage("Nothing to pack at this distance pilot!",10,false,Group)
|
||||||
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
--- (Internal) Function to repair nearby vehicles / FOBs
|
--- (Internal) Function to repair nearby vehicles / FOBs
|
||||||
@@ -4082,7 +4140,8 @@ end
|
|||||||
-- @param #CTLD.Buildable Build
|
-- @param #CTLD.Buildable Build
|
||||||
-- @param #boolean Repair If true this is a repair and not a new build
|
-- @param #boolean Repair If true this is a repair and not a new build
|
||||||
-- @param Core.Point#COORDINATE RepairLocation Location for repair (e.g. where the destroyed unit was)
|
-- @param Core.Point#COORDINATE RepairLocation Location for repair (e.g. where the destroyed unit was)
|
||||||
function CTLD:_BuildObjectFromCrates(Group,Unit,Build,Repair,RepairLocation)
|
-- @param #boolean MultiDrop if true and not a repair, vary location a bit if not a FOB
|
||||||
|
function CTLD:_BuildObjectFromCrates(Group,Unit,Build,Repair,RepairLocation,MultiDrop)
|
||||||
self:T(self.lid .. " _BuildObjectFromCrates")
|
self:T(self.lid .. " _BuildObjectFromCrates")
|
||||||
-- Spawn-a-crate-content
|
-- Spawn-a-crate-content
|
||||||
if Group and Group:IsAlive() or (RepairLocation and not Repair) then
|
if Group and Group:IsAlive() or (RepairLocation and not Repair) then
|
||||||
@@ -4099,7 +4158,7 @@ function CTLD:_BuildObjectFromCrates(Group,Unit,Build,Repair,RepairLocation)
|
|||||||
if type(temptable) == "string" then
|
if type(temptable) == "string" then
|
||||||
temptable = {temptable}
|
temptable = {temptable}
|
||||||
end
|
end
|
||||||
local zone = nil
|
local zone = nil -- Core.Zone#ZONE_RADIUS
|
||||||
if RepairLocation and not Repair then
|
if RepairLocation and not Repair then
|
||||||
-- timed build
|
-- timed build
|
||||||
zone = ZONE_RADIUS:New(string.format("Build zone-%d",math.random(1,10000)),RepairLocation:GetVec2(),100)
|
zone = ZONE_RADIUS:New(string.format("Build zone-%d",math.random(1,10000)),RepairLocation:GetVec2(),100)
|
||||||
@@ -4108,6 +4167,10 @@ function CTLD:_BuildObjectFromCrates(Group,Unit,Build,Repair,RepairLocation)
|
|||||||
end
|
end
|
||||||
--local randomcoord = zone:GetRandomCoordinate(35):GetVec2()
|
--local randomcoord = zone:GetRandomCoordinate(35):GetVec2()
|
||||||
local randomcoord = Build.Coord or zone:GetRandomCoordinate(35):GetVec2()
|
local randomcoord = Build.Coord or zone:GetRandomCoordinate(35):GetVec2()
|
||||||
|
if MultiDrop and (not Repair) and canmove then
|
||||||
|
-- coordinate may be the same, avoid
|
||||||
|
local randomcoord = zone:GetRandomCoordinate(35):GetVec2()
|
||||||
|
end
|
||||||
if Repair then
|
if Repair then
|
||||||
randomcoord = RepairLocation:GetVec2()
|
randomcoord = RepairLocation:GetVec2()
|
||||||
end
|
end
|
||||||
@@ -4138,6 +4201,17 @@ function CTLD:_BuildObjectFromCrates(Group,Unit,Build,Repair,RepairLocation)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- (Internal) Function to get a vehicle formation for a moving group
|
||||||
|
-- @param #CTLD self
|
||||||
|
-- @return #string Formation
|
||||||
|
function CTLD:_GetVehicleFormation()
|
||||||
|
local VehicleMoveFormation = self.VehicleMoveFormation or AI.Task.VehicleFormation.VEE
|
||||||
|
if type(self.VehicleMoveFormation)=="table" then
|
||||||
|
VehicleMoveFormation = self.VehicleMoveFormation[math.random(1,#self.VehicleMoveFormation)]
|
||||||
|
end
|
||||||
|
return VehicleMoveFormation
|
||||||
|
end
|
||||||
|
|
||||||
--- (Internal) Function to move group to WP zone.
|
--- (Internal) Function to move group to WP zone.
|
||||||
-- @param #CTLD self
|
-- @param #CTLD self
|
||||||
-- @param Wrapper.Group#GROUP Group The Group to move.
|
-- @param Wrapper.Group#GROUP Group The Group to move.
|
||||||
@@ -4152,18 +4226,20 @@ function CTLD:_MoveGroupToZone(Group)
|
|||||||
-- yes, we can ;)
|
-- yes, we can ;)
|
||||||
local groupname = Group:GetName()
|
local groupname = Group:GetName()
|
||||||
local zonecoord = zone:GetRandomCoordinate(20,125) -- Core.Point#COORDINATE
|
local zonecoord = zone:GetRandomCoordinate(20,125) -- Core.Point#COORDINATE
|
||||||
local coordinate = zonecoord:GetVec2()
|
local formation = self:_GetVehicleFormation()
|
||||||
|
--local coordinate = zonecoord:GetVec2()
|
||||||
Group:SetAIOn()
|
Group:SetAIOn()
|
||||||
Group:OptionAlarmStateAuto()
|
Group:OptionAlarmStateAuto()
|
||||||
Group:OptionDisperseOnAttack(30)
|
Group:OptionDisperseOnAttack(30)
|
||||||
Group:OptionROEOpenFirePossible()
|
Group:OptionROEOpenFire()
|
||||||
Group:RouteToVec2(coordinate,5)
|
Group:RouteGroundTo(zonecoord,25,formation)
|
||||||
end
|
end
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- (Internal) Housekeeping - Cleanup crates when build
|
--- (Internal) Housekeeping - Cleanup crates when build
|
||||||
-- @param #CTLD self
|
-- @param #CTLD self
|
||||||
|
--
|
||||||
-- @param #table Crates Table of #CTLD_CARGO objects near the unit.
|
-- @param #table Crates Table of #CTLD_CARGO objects near the unit.
|
||||||
-- @param #CTLD.Buildable Build Table build object.
|
-- @param #CTLD.Buildable Build Table build object.
|
||||||
-- @param #number Number Number of objects in Crates (found) to limit search.
|
-- @param #number Number Number of objects in Crates (found) to limit search.
|
||||||
@@ -4199,11 +4275,91 @@ function CTLD:_CleanUpCrates(Crates,Build,Number)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- (Internal) Helper - Drop **all** loaded crates nearby and build them.
|
||||||
|
-- @param Wrapper.Group#GROUP Group The calling group
|
||||||
|
-- @param Wrapper.Unit#UNIT Unit The calling unit
|
||||||
|
function CTLD:_DropAndBuild(Group,Unit)
|
||||||
|
if self.nobuildinloadzones then
|
||||||
|
if self:IsUnitInZone(Unit,CTLD.CargoZoneType.LOAD) then
|
||||||
|
self:_SendMessage("You cannot build in a loading area, Pilot!",10,false,Group)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
end
|
||||||
|
self:_UnloadCrates(Group,Unit)
|
||||||
|
timer.scheduleFunction(function() self:_BuildCrates(Group,Unit,false,true) end,{},timer.getTime()+1)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- (Internal) Helper - Drop a **single** crate set and build it.
|
||||||
|
-- @param Wrapper.Group#GROUP Group The calling group
|
||||||
|
-- @param Wrapper.Unit#UNIT Unit The calling unit
|
||||||
|
-- @param number setIndex Index of the crate-set to drop
|
||||||
|
function CTLD:_DropSingleAndBuild(Group,Unit,setIndex)
|
||||||
|
if self.nobuildinloadzones then
|
||||||
|
if self:IsUnitInZone(Unit,CTLD.CargoZoneType.LOAD) then
|
||||||
|
self:_SendMessage("You cannot build in a loading area, Pilot!",10,false,Group)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
end
|
||||||
|
self:_UnloadSingleCrateSet(Group,Unit,setIndex)
|
||||||
|
timer.scheduleFunction(function() self:_BuildCrates(Group,Unit,false) end,{},timer.getTime()+1)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- (Internal) Helper - Pack crates near the unit and load them.
|
||||||
|
-- @param Wrapper.Group#GROUP Group The calling group
|
||||||
|
-- @param Wrapper.Unit#UNIT Unit The calling unit
|
||||||
|
function CTLD:_PackAndLoad(Group,Unit)
|
||||||
|
if self.pilotmustopendoors and not UTILS.IsLoadingDoorOpen(Unit:GetName()) then
|
||||||
|
self:_SendMessage("You need to open the door(s) to load cargo!",10,false,Group)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
if not self:_PackCratesNearby(Group,Unit) then
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
timer.scheduleFunction(function() self:_LoadCratesNearby(Group,Unit) end,{},timer.getTime()+1)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- (Internal) Helper - Pack crates near the unit and then remove them.
|
||||||
|
-- @param Wrapper.Group#GROUP Group The calling group
|
||||||
|
-- @param Wrapper.Unit#UNIT Unit The calling unit
|
||||||
|
function CTLD:_PackAndRemove(Group,Unit)
|
||||||
|
if not self:_PackCratesNearby(Group,Unit) then
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
timer.scheduleFunction(function() self:_RemoveCratesNearby(Group,Unit) end,{},timer.getTime()+1)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- (Internal) Helper - get and load in one step
|
||||||
|
-- @param Wrapper.Group#GROUP Group The calling group
|
||||||
|
-- @param Wrapper.Unit#UNIT Unit The calling unit
|
||||||
|
function CTLD:_GetAndLoad(Group,Unit,cargoObj)
|
||||||
|
if self.pilotmustopendoors and not UTILS.IsLoadingDoorOpen(Unit:GetName()) then
|
||||||
|
self:_SendMessage("You need to open the door(s) to load cargo!",10,false,Group)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
self:_GetCrates(Group,Unit,cargoObj)
|
||||||
|
|
||||||
|
timer.scheduleFunction(function() self:_LoadSingleCrateSet(Group,Unit,cargoObj.Name) end,{},timer.getTime()+1)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- @param Wrapper.Group#GROUP Group The player’s group that triggered the action
|
||||||
|
-- @param Wrapper.Unit#UNIT Unit The unit performing the pack-and-load
|
||||||
|
function CTLD:_GetAllAndLoad(Group,Unit)
|
||||||
|
if self.pilotmustopendoors and not UTILS.IsLoadingDoorOpen(Unit:GetName()) then
|
||||||
|
self:_SendMessage("You need to open the door(s) to load cargo!",10,false,Group)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
timer.scheduleFunction(function() self:_LoadCratesNearby(Group,Unit) end,{},timer.getTime()+1)
|
||||||
|
end
|
||||||
|
|
||||||
--- (Internal) Housekeeping - Function to refresh F10 menus.
|
--- (Internal) Housekeeping - Function to refresh F10 menus.
|
||||||
-- @param #CTLD self
|
-- @param #CTLD self
|
||||||
-- @return #CTLD self
|
-- @return #CTLD self
|
||||||
function CTLD:_RefreshF10Menus()
|
function CTLD:_RefreshF10Menus()
|
||||||
self:T(self.lid .. " _RefreshF10Menus")
|
self:T(self.lid .. " _RefreshF10Menus")
|
||||||
|
self.onestepmenu = self.onestepmenu or false -- hybrid toggle (default = false)
|
||||||
|
|
||||||
-- 1) Gather all the pilot groups from our Set
|
-- 1) Gather all the pilot groups from our Set
|
||||||
local PlayerSet = self.PilotGroups
|
local PlayerSet = self.PilotGroups
|
||||||
@@ -4314,7 +4470,6 @@ function CTLD:_RefreshF10Menus()
|
|||||||
local menutext = cargoObj.Name
|
local menutext = cargoObj.Name
|
||||||
if (stock >= 0) and (self.showstockinmenuitems == true) then menutext = menutext.." ["..stock.."]" end
|
if (stock >= 0) and (self.showstockinmenuitems == true) then menutext = menutext.." ["..stock.."]" end
|
||||||
MENU_GROUP_COMMAND:New(_group, menutext, troopsmenu, self._LoadTroops, self, _group, _unit, cargoObj)
|
MENU_GROUP_COMMAND:New(_group, menutext, troopsmenu, self._LoadTroops, self, _group, _unit, cargoObj)
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -4341,11 +4496,66 @@ function CTLD:_RefreshF10Menus()
|
|||||||
|
|
||||||
-- Build the “Get Crates” sub-menu items
|
-- Build the “Get Crates” sub-menu items
|
||||||
local cratesmenu = MENU_GROUP:New(_group,"Get Crates",topcrates)
|
local cratesmenu = MENU_GROUP:New(_group,"Get Crates",topcrates)
|
||||||
|
|
||||||
|
if self.onestepmenu then
|
||||||
if self.usesubcats then
|
if self.usesubcats then
|
||||||
local subcatmenus = {}
|
local subcatmenus = {}
|
||||||
for catName,_ in pairs(self.subcats) do
|
for catName,_ in pairs(self.subcats) do
|
||||||
subcatmenus[catName] = MENU_GROUP:New(_group,catName,cratesmenu)
|
subcatmenus[catName] = MENU_GROUP:New(_group,catName,cratesmenu)
|
||||||
end
|
end
|
||||||
|
for _,cargoObj in pairs(self.Cargo_Crates) do
|
||||||
|
if not cargoObj.DontShowInMenu then
|
||||||
|
local txt = string.format("Crate %s (%dkg)",cargoObj.Name,cargoObj.PerCrateMass or 0)
|
||||||
|
if cargoObj.Location then txt = txt.."[R]" end
|
||||||
|
local stock = cargoObj:GetStock()
|
||||||
|
if stock>=0 and self.showstockinmenuitems then txt = txt.."["..stock.."]" end
|
||||||
|
local mSet = MENU_GROUP:New(_group,txt,subcatmenus[cargoObj.Subcategory])
|
||||||
|
MENU_GROUP_COMMAND:New(_group,"Get",mSet,self._GetCrates,self,_group,_unit,cargoObj)
|
||||||
|
MENU_GROUP_COMMAND:New(_group,"Get and Load",mSet,self._GetAndLoad,self,_group,_unit,cargoObj)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for _,cargoObj in pairs(self.Cargo_Statics) do
|
||||||
|
if not cargoObj.DontShowInMenu then
|
||||||
|
local txt = string.format("Crate %s (%dkg)",cargoObj.Name,cargoObj.PerCrateMass or 0)
|
||||||
|
if cargoObj.Location then txt = txt.."[R]" end
|
||||||
|
local stock = cargoObj:GetStock()
|
||||||
|
if stock>=0 and self.showstockinmenuitems then txt = txt.."["..stock.."]" end
|
||||||
|
local mSet = MENU_GROUP:New(_group,txt,subcatmenus[cargoObj.Subcategory])
|
||||||
|
MENU_GROUP_COMMAND:New(_group,"Get",mSet,self._GetCrates,self,_group,_unit,cargoObj)
|
||||||
|
MENU_GROUP_COMMAND:New(_group,"Get and Load",mSet,self._GetAndLoad,self,_group,_unit,cargoObj)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
for _,cargoObj in pairs(self.Cargo_Crates) do
|
||||||
|
if not cargoObj.DontShowInMenu then
|
||||||
|
local txt = string.format("Crate %s (%dkg)",cargoObj.Name,cargoObj.PerCrateMass or 0)
|
||||||
|
if cargoObj.Location then txt = txt.."[R]" end
|
||||||
|
local stock = cargoObj:GetStock()
|
||||||
|
if stock>=0 and self.showstockinmenuitems then txt = txt.."["..stock.."]" end
|
||||||
|
local mSet = MENU_GROUP:New(_group,txt,cratesmenu)
|
||||||
|
MENU_GROUP_COMMAND:New(_group,"Get",mSet,self._GetCrates,self,_group,_unit,cargoObj)
|
||||||
|
MENU_GROUP_COMMAND:New(_group,"Get and Load",mSet,self._GetAndLoad,self,_group,_unit,cargoObj)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for _,cargoObj in pairs(self.Cargo_Statics) do
|
||||||
|
if not cargoObj.DontShowInMenu then
|
||||||
|
local txt = string.format("Crate %s (%dkg)",cargoObj.Name,cargoObj.PerCrateMass or 0)
|
||||||
|
if cargoObj.Location then txt = txt.."[R]" end
|
||||||
|
local stock = cargoObj:GetStock()
|
||||||
|
if stock>=0 and self.showstockinmenuitems then txt = txt.."["..stock.."]" end
|
||||||
|
local mSet = MENU_GROUP:New(_group,txt,cratesmenu)
|
||||||
|
MENU_GROUP_COMMAND:New(_group,"Get",mSet,self._GetCrates,self,_group,_unit,cargoObj)
|
||||||
|
MENU_GROUP_COMMAND:New(_group,"Get and Load",mSet,self._GetAndLoad,self,_group,_unit,cargoObj)
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if self.usesubcats then
|
||||||
|
local subcatmenus = {}
|
||||||
|
for catName, _ in pairs(self.subcats) do
|
||||||
|
subcatmenus[catName] = MENU_GROUP:New(_group, catName, cratesmenu) -- fixed variable case
|
||||||
|
end
|
||||||
for _, cargoObj in pairs(self.Cargo_Crates) do
|
for _, cargoObj in pairs(self.Cargo_Crates) do
|
||||||
if not cargoObj.DontShowInMenu then
|
if not cargoObj.DontShowInMenu then
|
||||||
local txt = string.format("Crate %s (%dkg)", cargoObj.Name, cargoObj.PerCrateMass or 0)
|
local txt = string.format("Crate %s (%dkg)", cargoObj.Name, cargoObj.PerCrateMass or 0)
|
||||||
@@ -4384,6 +4594,7 @@ function CTLD:_RefreshF10Menus()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local loadCratesMenu=MENU_GROUP:New(_group,"Load Crates",topcrates)
|
local loadCratesMenu=MENU_GROUP:New(_group,"Load Crates",topcrates)
|
||||||
_group.MyLoadCratesMenu=loadCratesMenu
|
_group.MyLoadCratesMenu=loadCratesMenu
|
||||||
@@ -4401,8 +4612,16 @@ function CTLD:_RefreshF10Menus()
|
|||||||
local removecratesmenu = MENU_GROUP:New(_group, "Remove crates", topcrates)
|
local removecratesmenu = MENU_GROUP:New(_group, "Remove crates", topcrates)
|
||||||
MENU_GROUP_COMMAND:New(_group, "Remove crates nearby", removecratesmenu, self._RemoveCratesNearby, self, _group, _unit)
|
MENU_GROUP_COMMAND:New(_group, "Remove crates nearby", removecratesmenu, self._RemoveCratesNearby, self, _group, _unit)
|
||||||
|
|
||||||
|
if self.onestepmenu then
|
||||||
|
local mPack=MENU_GROUP:New(_group,"Pack crates",topcrates)
|
||||||
|
MENU_GROUP_COMMAND:New(_group,"Pack",mPack,self._PackCratesNearby,self,_group,_unit)
|
||||||
|
MENU_GROUP_COMMAND:New(_group,"Pack and Load",mPack,self._PackAndLoad,self,_group,_unit)
|
||||||
|
MENU_GROUP_COMMAND:New(_group,"Pack and Remove",mPack,self._PackAndRemove,self,_group,_unit)
|
||||||
|
MENU_GROUP_COMMAND:New(_group, "List crates nearby", topcrates, self._ListCratesNearby, self, _group, _unit)
|
||||||
|
else
|
||||||
MENU_GROUP_COMMAND:New(_group, "Pack crates", topcrates, self._PackCratesNearby, self, _group, _unit)
|
MENU_GROUP_COMMAND:New(_group, "Pack crates", topcrates, self._PackCratesNearby, self, _group, _unit)
|
||||||
MENU_GROUP_COMMAND:New(_group, "List crates nearby", topcrates, self._ListCratesNearby, self, _group, _unit)
|
MENU_GROUP_COMMAND:New(_group, "List crates nearby", topcrates, self._ListCratesNearby, self, _group, _unit)
|
||||||
|
end
|
||||||
|
|
||||||
local uName = _unit:GetName()
|
local uName = _unit:GetName()
|
||||||
local loadedData = self.Loaded_Cargo[uName]
|
local loadedData = self.Loaded_Cargo[uName]
|
||||||
@@ -4423,8 +4642,6 @@ function CTLD:_RefreshF10Menus()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-----------------------------------------------------
|
-----------------------------------------------------
|
||||||
-- Misc sub‐menus
|
-- Misc sub‐menus
|
||||||
-----------------------------------------------------
|
-----------------------------------------------------
|
||||||
@@ -4482,27 +4699,35 @@ function CTLD:_RefreshLoadCratesMenu(Group, Unit)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
MENU_GROUP_COMMAND:New(Group,"Load ALL",Group.MyLoadCratesMenu,self._LoadCratesNearby,self,Group,Unit)
|
MENU_GROUP_COMMAND:New(Group,"Load ALL",Group.MyLoadCratesMenu,self._LoadCratesNearby,self,Group,Unit)
|
||||||
|
|
||||||
local cargoByName={}
|
local cargoByName={}
|
||||||
for _,crate in pairs(nearby) do
|
for _,crate in pairs(nearby) do
|
||||||
local cName = crate:GetName()
|
local name=crate:GetName()
|
||||||
cargoByName[cName] = cargoByName[cName] or {}
|
cargoByName[name]=cargoByName[name] or{}
|
||||||
table.insert(cargoByName[cName], crate)
|
table.insert(cargoByName[name],crate)
|
||||||
end
|
end
|
||||||
|
|
||||||
for cName, cList in pairs(cargoByName) do
|
local lineIndex=1
|
||||||
local needed = cList[1]:GetCratesNeeded() or 1
|
for cName,list in pairs(cargoByName) do
|
||||||
local found = #cList
|
local needed=list[1]:GetCratesNeeded() or 1
|
||||||
|
table.sort(list,function(a,b)return a:GetID()<b:GetID() end)
|
||||||
local line
|
local i=1
|
||||||
if found >= needed then
|
while i<=#list do
|
||||||
line = string.format("Load %s", cName)
|
local left=#list-i+1
|
||||||
|
local label
|
||||||
|
if left>=needed then
|
||||||
|
label=string.format("%d. Load %s",lineIndex,cName)
|
||||||
|
i=i+needed
|
||||||
else
|
else
|
||||||
MENU_GROUP_COMMAND:New(Group, "Rescan?", Group.MyLoadCratesMenu, function() self:_RefreshLoadCratesMenu(Group, Unit) end)
|
label=string.format("%d. Load %s (%d/%d)",lineIndex,cName,left,needed)
|
||||||
line = string.format("Load %s (%d/%d)", cName, found, needed)
|
i=#list+1
|
||||||
end
|
end
|
||||||
MENU_GROUP_COMMAND:New(Group, line, Group.MyLoadCratesMenu, self._LoadSingleCrateSet, self, Group, Unit, cName)
|
MENU_GROUP_COMMAND:New(Group,label,Group.MyLoadCratesMenu,self._LoadSingleCrateSet,self,Group,Unit,cName)
|
||||||
|
lineIndex=lineIndex+1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
-- Loads exactly `CratesNeeded` crates for one cargoName in range.
|
-- Loads exactly `CratesNeeded` crates for one cargoName in range.
|
||||||
@@ -4712,7 +4937,17 @@ function CTLD:_UnloadSingleCrateSet(Group, Unit, setIndex)
|
|||||||
cObj:SetWasDropped(true)
|
cObj:SetWasDropped(true)
|
||||||
cObj:SetHasMoved(true)
|
cObj:SetHasMoved(true)
|
||||||
end
|
end
|
||||||
|
local cname = crateObj:GetName() or "Unknown"
|
||||||
|
local count = #chunk
|
||||||
|
if needed > 1 then
|
||||||
|
if count == needed then
|
||||||
|
self:_SendMessage(string.format("Dropped %d %s.", 1, cname), 10, false, Group)
|
||||||
|
else
|
||||||
|
self:_SendMessage(string.format("Dropped %d/%d crate(s) of %s.", count, needed, cname), 15, false, Group)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
self:_SendMessage(string.format("Dropped %d %s(s).", count, cname), 10, false, Group)
|
||||||
|
end
|
||||||
-- Rebuild the cargo list to remove the dropped crates
|
-- Rebuild the cargo list to remove the dropped crates
|
||||||
local loadedData = self.Loaded_Cargo[unitName]
|
local loadedData = self.Loaded_Cargo[unitName]
|
||||||
if loadedData and loadedData.Cargo then
|
if loadedData and loadedData.Cargo then
|
||||||
@@ -4745,6 +4980,7 @@ end
|
|||||||
-- @param Wrapper.Unit#UNIT Unit The calling unit.
|
-- @param Wrapper.Unit#UNIT Unit The calling unit.
|
||||||
-- @return #CTLD self
|
-- @return #CTLD self
|
||||||
function CTLD:_RefreshDropCratesMenu(Group, Unit)
|
function CTLD:_RefreshDropCratesMenu(Group, Unit)
|
||||||
|
|
||||||
if not Group.CTLDTopmenu then return end
|
if not Group.CTLDTopmenu then return end
|
||||||
local topCrates = Group.MyTopCratesMenu
|
local topCrates = Group.MyTopCratesMenu
|
||||||
if not topCrates then return end
|
if not topCrates then return end
|
||||||
@@ -4780,7 +5016,15 @@ function CTLD:_RefreshDropCratesMenu(Group, Unit)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
-- DEFAULT (“classic”) versus ONE-STEP behaviour
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
if not self.onestepmenu then
|
||||||
|
--------------------------------------------------------------------
|
||||||
|
-- classic menu
|
||||||
|
--------------------------------------------------------------------
|
||||||
MENU_GROUP_COMMAND:New(Group,"Drop ALL crates",dropCratesMenu,self._UnloadCrates,self,Group,Unit)
|
MENU_GROUP_COMMAND:New(Group,"Drop ALL crates",dropCratesMenu,self._UnloadCrates,self,Group,Unit)
|
||||||
|
|
||||||
self.CrateGroupList=self.CrateGroupList or{}
|
self.CrateGroupList=self.CrateGroupList or{}
|
||||||
self.CrateGroupList[Unit:GetName()]={}
|
self.CrateGroupList[Unit:GetName()]={}
|
||||||
|
|
||||||
@@ -4815,6 +5059,56 @@ function CTLD:_RefreshDropCratesMenu(Group, Unit)
|
|||||||
lineIndex=lineIndex+1
|
lineIndex=lineIndex+1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
else
|
||||||
|
--------------------------------------------------------------------
|
||||||
|
-- one-step (enhanced) menu
|
||||||
|
--------------------------------------------------------------------
|
||||||
|
local mAll=MENU_GROUP:New(Group,"Drop ALL crates",dropCratesMenu)
|
||||||
|
MENU_GROUP_COMMAND:New(Group,"Drop",mAll,self._UnloadCrates,self,Group,Unit)
|
||||||
|
if not ( self:IsUnitInAir(Unit) and self:IsFixedWing(Unit) ) then
|
||||||
|
MENU_GROUP_COMMAND:New(Group,"Drop and build",mAll,self._DropAndBuild,self,Group,Unit)
|
||||||
|
end
|
||||||
|
|
||||||
|
self.CrateGroupList=self.CrateGroupList or{}
|
||||||
|
self.CrateGroupList[Unit:GetName()]={}
|
||||||
|
|
||||||
|
local lineIndex=1
|
||||||
|
for cName,list in pairs(cargoByName) do
|
||||||
|
local needed=list[1]:GetCratesNeeded() or 1
|
||||||
|
table.sort(list,function(a,b)return a:GetID()<b:GetID()end)
|
||||||
|
local i=1
|
||||||
|
while i<=#list do
|
||||||
|
local left=(#list-i+1)
|
||||||
|
if left>=needed then
|
||||||
|
local chunk={}
|
||||||
|
for n=i,i+needed-1 do
|
||||||
|
table.insert(chunk,list[n])
|
||||||
|
end
|
||||||
|
local label=string.format("%d. %s",lineIndex,cName)
|
||||||
|
table.insert(self.CrateGroupList[Unit:GetName()],chunk)
|
||||||
|
local setIndex=#self.CrateGroupList[Unit:GetName()]
|
||||||
|
local mSet=MENU_GROUP:New(Group,label,dropCratesMenu)
|
||||||
|
MENU_GROUP_COMMAND:New(Group,"Drop",mSet,self._UnloadSingleCrateSet,self,Group,Unit,setIndex)
|
||||||
|
if not ( self:IsUnitInAir(Unit) and self:IsFixedWing(Unit) ) then
|
||||||
|
MENU_GROUP_COMMAND:New(Group,"Drop and build",mSet,self._DropSingleAndBuild,self,Group,Unit,setIndex)
|
||||||
|
end
|
||||||
|
i=i+needed
|
||||||
|
else
|
||||||
|
local chunk={}
|
||||||
|
for n=i,#list do
|
||||||
|
table.insert(chunk,list[n])
|
||||||
|
end
|
||||||
|
local label=string.format("%d. %s %d/%d",lineIndex,cName,left,needed)
|
||||||
|
table.insert(self.CrateGroupList[Unit:GetName()],chunk)
|
||||||
|
local setIndex=#self.CrateGroupList[Unit:GetName()]
|
||||||
|
MENU_GROUP_COMMAND:New(Group,label,dropCratesMenu,self._UnloadSingleCrateSet,self,Group,Unit,setIndex)
|
||||||
|
i=#list+1
|
||||||
|
end
|
||||||
|
lineIndex=lineIndex+1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- (Internal) Function to unload a single Troop group by ID.
|
--- (Internal) Function to unload a single Troop group by ID.
|
||||||
@@ -4864,7 +5158,7 @@ function CTLD:_UnloadSingleTroopByID(Group, Unit, chunkID)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Drop ONLY the FIRST cargo in that chunk
|
-- Drop the FIRST cargo in that chunk
|
||||||
local foundCargo = chunk[1]
|
local foundCargo = chunk[1]
|
||||||
if not foundCargo then
|
if not foundCargo then
|
||||||
self:_SendMessage(string.format("No troop cargo at chunk %d!", chunkID), 10, false, Group)
|
self:_SendMessage(string.format("No troop cargo at chunk %d!", chunkID), 10, false, Group)
|
||||||
@@ -4925,6 +5219,8 @@ function CTLD:_UnloadSingleTroopByID(Group, Unit, chunkID)
|
|||||||
foundCargo:SetWasDropped(true)
|
foundCargo:SetWasDropped(true)
|
||||||
if cType == CTLD_CARGO.Enum.ENGINEERS then
|
if cType == CTLD_CARGO.Enum.ENGINEERS then
|
||||||
self.Engineers = self.Engineers + 1
|
self.Engineers = self.Engineers + 1
|
||||||
|
local grpname = self.DroppedTroops[self.TroopCounter]:GetName()
|
||||||
|
self.EngineersInField[self.Engineers] = CTLD_ENGINEERING:New(name, grpname)
|
||||||
self:_SendMessage(string.format("Dropped Engineers %s into action!", name), 10, false, Group)
|
self:_SendMessage(string.format("Dropped Engineers %s into action!", name), 10, false, Group)
|
||||||
else
|
else
|
||||||
self:_SendMessage(string.format("Dropped Troops %s into action!", name), 10, false, Group)
|
self:_SendMessage(string.format("Dropped Troops %s into action!", name), 10, false, Group)
|
||||||
@@ -5662,6 +5958,7 @@ function CTLD:IsUnitInZone(Unit,Zonetype)
|
|||||||
if Zonetype == CTLD.CargoZoneType.SHIP then
|
if Zonetype == CTLD.CargoZoneType.SHIP then
|
||||||
self:T("Checking Type Ship: "..zonename)
|
self:T("Checking Type Ship: "..zonename)
|
||||||
local ZoneUNIT = UNIT:FindByName(zonename)
|
local ZoneUNIT = UNIT:FindByName(zonename)
|
||||||
|
if not ZoneUNIT then return false end
|
||||||
zonecoord = ZoneUNIT:GetCoordinate()
|
zonecoord = ZoneUNIT:GetCoordinate()
|
||||||
zoneradius = czone.shiplength
|
zoneradius = czone.shiplength
|
||||||
zonewidth = czone.shipwidth
|
zonewidth = czone.shipwidth
|
||||||
@@ -5739,16 +6036,23 @@ function CTLD:SmokeZoneNearBy(Unit, Flare)
|
|||||||
for index,cargozone in pairs(zones[i]) do
|
for index,cargozone in pairs(zones[i]) do
|
||||||
local CZone = cargozone --#CTLD.CargoZone
|
local CZone = cargozone --#CTLD.CargoZone
|
||||||
local zonename = CZone.name
|
local zonename = CZone.name
|
||||||
local zone = nil
|
local zone = nil -- Core.Zone#ZONE_RADIUS
|
||||||
|
local airbasezone = false
|
||||||
if i == 4 then
|
if i == 4 then
|
||||||
zone = UNIT:FindByName(zonename)
|
zone = UNIT:FindByName(zonename)
|
||||||
else
|
else
|
||||||
zone = ZONE:FindByName(zonename)
|
zone = ZONE:FindByName(zonename)
|
||||||
if not zone then
|
if not zone then
|
||||||
zone = AIRBASE:FindByName(zonename):GetZone()
|
zone = AIRBASE:FindByName(zonename):GetZone()
|
||||||
|
airbasezone = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local zonecoord = zone:GetCoordinate()
|
local zonecoord = zone:GetCoordinate()
|
||||||
|
-- Avoid smoke/flares on runways
|
||||||
|
if (i==1 or 1==3) and airbasezone==true and zone:IsInstanceOf("ZONE_BASE") then
|
||||||
|
zonecoord = zone:GetRandomCoordinate(inner,outer,{land.SurfaceType.LAND})
|
||||||
|
end
|
||||||
|
if zonecoord then
|
||||||
local active = CZone.active
|
local active = CZone.active
|
||||||
local color = CZone.color
|
local color = CZone.color
|
||||||
local distance = self:_GetDistance(zonecoord,unitcoord)
|
local distance = self:_GetDistance(zonecoord,unitcoord)
|
||||||
@@ -5767,6 +6071,7 @@ function CTLD:SmokeZoneNearBy(Unit, Flare)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
if not smoked then
|
if not smoked then
|
||||||
local distance = UTILS.MetersToNM(self.smokedistance)
|
local distance = UTILS.MetersToNM(self.smokedistance)
|
||||||
self:_SendMessage(string.format("Negative, need to be closer than %dnm to a zone!",distance), 10, false, Group)
|
self:_SendMessage(string.format("Negative, need to be closer than %dnm to a zone!",distance), 10, false, Group)
|
||||||
@@ -6846,6 +7151,16 @@ end
|
|||||||
local filepath = self.filepath
|
local filepath = self.filepath
|
||||||
self:__Save(interval,filepath,filename)
|
self:__Save(interval,filepath,filename)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if type(self.VehicleMoveFormation) == "table" then
|
||||||
|
local Formations = {}
|
||||||
|
for _,_formation in pairs(self.VehicleMoveFormation) do
|
||||||
|
table.insert(Formations,_formation)
|
||||||
|
end
|
||||||
|
self.VehicleMoveFormation = nil
|
||||||
|
self.VehicleMoveFormation = Formations
|
||||||
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -6983,7 +7298,8 @@ end
|
|||||||
-- right subtype?
|
-- right subtype?
|
||||||
if Event == subtype and not task:IsDone() then
|
if Event == subtype and not task:IsDone() then
|
||||||
local targetzone = task.Target:GetObject() -- Core.Zone#ZONE should be a zone in this case ....
|
local targetzone = task.Target:GetObject() -- Core.Zone#ZONE should be a zone in this case ....
|
||||||
--self:T2({Name=Groupname,Property=task:GetProperty("ExtractName")})
|
self:T2({Name=Groupname,Property=task:GetProperty("ExtractName")})
|
||||||
|
if task:GetProperty("ExtractName") then
|
||||||
local okaygroup = string.find(Groupname,task:GetProperty("ExtractName"),1,true)
|
local okaygroup = string.find(Groupname,task:GetProperty("ExtractName"),1,true)
|
||||||
if targetzone and targetzone.ClassName and string.match(targetzone.ClassName,"ZONE") and okaygroup then
|
if targetzone and targetzone.ClassName and string.match(targetzone.ClassName,"ZONE") and okaygroup then
|
||||||
if task.Clients:HasUniqueID(playername) then
|
if task.Clients:HasUniqueID(playername) then
|
||||||
@@ -6991,6 +7307,9 @@ end
|
|||||||
task:__Success(-1)
|
task:__Success(-1)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
self:T({Text="'ExtractName' Property not set",Name=Groupname,Property=task.Type})
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ end
|
|||||||
|
|
||||||
--- Checks if a point is contained within the circle.
|
--- Checks if a point is contained within the circle.
|
||||||
-- @param #table point The point to check
|
-- @param #table point The point to check
|
||||||
-- @return #bool True if the point is contained, false otherwise
|
-- @return #boolean True if the point is contained, false otherwise
|
||||||
function CIRCLE:ContainsPoint(point)
|
function CIRCLE:ContainsPoint(point)
|
||||||
if ((point.x - self.CenterVec2.x) ^ 2 + (point.y - self.CenterVec2.y) ^ 2) ^ 0.5 <= self.Radius then
|
if ((point.x - self.CenterVec2.x) ^ 2 + (point.y - self.CenterVec2.y) ^ 2) ^ 0.5 <= self.Radius then
|
||||||
return true
|
return true
|
||||||
@@ -226,6 +226,11 @@ end
|
|||||||
--- Returns a random Vec2 within the circle.
|
--- Returns a random Vec2 within the circle.
|
||||||
-- @return #table The random Vec2
|
-- @return #table The random Vec2
|
||||||
function CIRCLE:GetRandomVec2()
|
function CIRCLE:GetRandomVec2()
|
||||||
|
|
||||||
|
math.random()
|
||||||
|
math.random()
|
||||||
|
math.random()
|
||||||
|
|
||||||
local angle = math.random() * 2 * math.pi
|
local angle = math.random() * 2 * math.pi
|
||||||
|
|
||||||
local rx = math.random(0, self.Radius) * math.cos(angle) + self.CenterVec2.x
|
local rx = math.random(0, self.Radius) * math.cos(angle) + self.CenterVec2.x
|
||||||
@@ -237,6 +242,11 @@ end
|
|||||||
--- Returns a random Vec2 on the border of the circle.
|
--- Returns a random Vec2 on the border of the circle.
|
||||||
-- @return #table The random Vec2
|
-- @return #table The random Vec2
|
||||||
function CIRCLE:GetRandomVec2OnBorder()
|
function CIRCLE:GetRandomVec2OnBorder()
|
||||||
|
|
||||||
|
math.random()
|
||||||
|
math.random()
|
||||||
|
math.random()
|
||||||
|
|
||||||
local angle = math.random() * 2 * math.pi
|
local angle = math.random() * 2 * math.pi
|
||||||
|
|
||||||
local rx = self.Radius * math.cos(angle) + self.CenterVec2.x
|
local rx = self.Radius * math.cos(angle) + self.CenterVec2.x
|
||||||
|
|||||||
@@ -352,6 +352,7 @@ end
|
|||||||
--- Returns a random Vec2 within the polygon. The Vec2 is weighted by the areas of the triangles that make up the polygon.
|
--- Returns a random Vec2 within the polygon. The Vec2 is weighted by the areas of the triangles that make up the polygon.
|
||||||
-- @return #table The random Vec2
|
-- @return #table The random Vec2
|
||||||
function POLYGON:GetRandomVec2()
|
function POLYGON:GetRandomVec2()
|
||||||
|
|
||||||
local weights = {}
|
local weights = {}
|
||||||
for _, triangle in pairs(self.Triangles) do
|
for _, triangle in pairs(self.Triangles) do
|
||||||
weights[triangle] = triangle.SurfaceArea / self.SurfaceArea
|
weights[triangle] = triangle.SurfaceArea / self.SurfaceArea
|
||||||
|
|||||||
@@ -73,6 +73,11 @@ end
|
|||||||
-- @param #table points The points of the triangle, or 3 other points if you're just using the TRIANGLE class without an object of it
|
-- @param #table points The points of the triangle, or 3 other points if you're just using the TRIANGLE class without an object of it
|
||||||
-- @return #table The random Vec2
|
-- @return #table The random Vec2
|
||||||
function TRIANGLE:GetRandomVec2(points)
|
function TRIANGLE:GetRandomVec2(points)
|
||||||
|
|
||||||
|
math.random()
|
||||||
|
math.random()
|
||||||
|
math.random()
|
||||||
|
|
||||||
points = points or self.Points
|
points = points or self.Points
|
||||||
local pt = {math.random(), math.random()}
|
local pt = {math.random(), math.random()}
|
||||||
table.sort(pt)
|
table.sort(pt)
|
||||||
|
|||||||
@@ -443,28 +443,32 @@ MSRS.Voices = {
|
|||||||
["en_AU_Standard_B"] = 'en-AU-Standard-B', -- [2] MALE
|
["en_AU_Standard_B"] = 'en-AU-Standard-B', -- [2] MALE
|
||||||
["en_AU_Standard_C"] = 'en-AU-Standard-C', -- [3] FEMALE
|
["en_AU_Standard_C"] = 'en-AU-Standard-C', -- [3] FEMALE
|
||||||
["en_AU_Standard_D"] = 'en-AU-Standard-D', -- [4] MALE
|
["en_AU_Standard_D"] = 'en-AU-Standard-D', -- [4] MALE
|
||||||
["en_IN_Standard_A"] = 'en-IN-Standard-A', -- [5] FEMALE
|
-- IN
|
||||||
["en_IN_Standard_B"] = 'en-IN-Standard-B', -- [6] MALE
|
["en_IN_Standard_A"] = 'en-IN-Standard-A', -- Female
|
||||||
["en_IN_Standard_C"] = 'en-IN-Standard-C', -- [7] MALE
|
["en_IN_Standard_B"] = 'en-IN-Standard-B', -- Male
|
||||||
["en_IN_Standard_D"] = 'en-IN-Standard-D', -- [8] FEMALE
|
["en_IN_Standard_C"] = 'en-IN-Standard-C', -- Male
|
||||||
|
["en_IN_Standard_D"] = 'en-IN-Standard-D', -- Female
|
||||||
|
["en_IN_Standard_E"] = 'en-IN-Standard-E', -- Female
|
||||||
|
["en_IN_Standard_F"] = 'en-IN-Standard-F', -- Male
|
||||||
-- 2025 changes
|
-- 2025 changes
|
||||||
["en_GB_Standard_A"] = 'en-GB-Standard-N', -- [9] FEMALE
|
["en_GB_Standard_A"] = 'en-GB-Standard-A', -- Female
|
||||||
["en_GB_Standard_B"] = 'en-GB-Standard-O', -- [10] MALE
|
["en_GB_Standard_B"] = 'en-GB-Standard-B', -- Male
|
||||||
["en_GB_Standard_C"] = 'en-GB-Standard-N', -- [11] FEMALE
|
["en_GB_Standard_C"] = 'en-GB-Standard-C', -- Female
|
||||||
["en_GB_Standard_D"] = 'en-GB-Standard-O', -- [12] MALE
|
["en_GB_Standard_D"] = 'en-GB-Standard-D', -- Male
|
||||||
["en_GB_Standard_F"] = 'en-GB-Standard-N', -- [13] FEMALE
|
["en_GB_Standard_F"] = 'en-GB-Standard-F', -- Female
|
||||||
["en_GB_Standard_O"] = 'en-GB-Standard-O', -- [12] MALE
|
["en_GB_Standard_N"] = 'en-GB-Standard-N', -- Female
|
||||||
["en_GB_Standard_N"] = 'en-GB-Standard-N', -- [13] FEMALE
|
["en_GB_Standard_O"] = 'en-GB-Standard-O', -- Male
|
||||||
["en_US_Standard_A"] = 'en-US-Standard-A', -- [14] MALE
|
-- US
|
||||||
["en_US_Standard_B"] = 'en-US-Standard-B', -- [15] MALE
|
["en_US_Standard_A"] = 'en-US-Standard-A', -- Male
|
||||||
["en_US_Standard_C"] = 'en-US-Standard-C', -- [16] FEMALE
|
["en_US_Standard_B"] = 'en-US-Standard-B', -- Male
|
||||||
["en_US_Standard_D"] = 'en-US-Standard-D', -- [17] MALE
|
["en_US_Standard_C"] = 'en-US-Standard-C', -- Female
|
||||||
["en_US_Standard_E"] = 'en-US-Standard-E', -- [18] FEMALE
|
["en_US_Standard_D"] = 'en-US-Standard-D', -- Male
|
||||||
["en_US_Standard_F"] = 'en-US-Standard-F', -- [19] FEMALE
|
["en_US_Standard_E"] = 'en-US-Standard-E', -- Female
|
||||||
["en_US_Standard_G"] = 'en-US-Standard-G', -- [20] FEMALE
|
["en_US_Standard_F"] = 'en-US-Standard-F', -- Female
|
||||||
["en_US_Standard_H"] = 'en-US-Standard-H', -- [21] FEMALE
|
["en_US_Standard_G"] = 'en-US-Standard-G', -- Female
|
||||||
["en_US_Standard_I"] = 'en-US-Standard-I', -- [22] MALE
|
["en_US_Standard_H"] = 'en-US-Standard-H', -- Female
|
||||||
["en_US_Standard_J"] = 'en-US-Standard-J', -- [23] MALE
|
["en_US_Standard_I"] = 'en-US-Standard-I', -- Male
|
||||||
|
["en_US_Standard_J"] = 'en-US-Standard-J', -- Male
|
||||||
-- 2025 catalog changes
|
-- 2025 catalog changes
|
||||||
["fr_FR_Standard_A"] = "fr-FR-Standard-F", -- Female
|
["fr_FR_Standard_A"] = "fr-FR-Standard-F", -- Female
|
||||||
["fr_FR_Standard_B"] = "fr-FR-Standard-G", -- Male
|
["fr_FR_Standard_B"] = "fr-FR-Standard-G", -- Male
|
||||||
@@ -474,14 +478,15 @@ MSRS.Voices = {
|
|||||||
["fr_FR_Standard_G"] = "fr-FR-Standard-G", -- Male
|
["fr_FR_Standard_G"] = "fr-FR-Standard-G", -- Male
|
||||||
["fr_FR_Standard_F"] = "fr-FR-Standard-F", -- Female
|
["fr_FR_Standard_F"] = "fr-FR-Standard-F", -- Female
|
||||||
-- 2025 catalog changes
|
-- 2025 catalog changes
|
||||||
["de_DE_Standard_A"] = "de-DE-Standard-G", -- Female
|
["de_DE_Standard_A"] = 'de-DE-Standard-A', -- Female
|
||||||
["de_DE_Standard_B"] = "de-DE-Standard-H", -- Male
|
["de_DE_Standard_B"] = 'de-DE-Standard-B', -- Male
|
||||||
["de_DE_Standard_C"] = "de-DE-Standard-G", -- Female
|
["de_DE_Standard_C"] = 'de-DE-Standard-C', -- Female
|
||||||
["de_DE_Standard_D"] = "de-DE-Standard-H", -- Male
|
["de_DE_Standard_D"] = 'de-DE-Standard-D', -- Male
|
||||||
["de_DE_Standard_E"] = "de-DE-Standard-H", -- Male
|
["de_DE_Standard_E"] = 'de-DE-Standard-E', -- Male
|
||||||
["de_DE_Standard_F"] = "de-DE-Standard-G", -- Female
|
["de_DE_Standard_F"] = 'de-DE-Standard-F', -- Female
|
||||||
["de_DE_Standard_H"] = "de-DE-Standard-H", -- Male
|
["de_DE_Standard_G"] = 'de-DE-Standard-G', -- Female
|
||||||
["de_DE_Standard_G"] = "de-DE-Standard-G", -- Female
|
["de_DE_Standard_H"] = 'de-DE-Standard-H', -- Male
|
||||||
|
-- ES
|
||||||
["es_ES_Standard_A"] = "es-ES-Standard-E", -- Female
|
["es_ES_Standard_A"] = "es-ES-Standard-E", -- Female
|
||||||
["es_ES_Standard_B"] = "es-ES-Standard-F", -- Male
|
["es_ES_Standard_B"] = "es-ES-Standard-F", -- Male
|
||||||
["es_ES_Standard_C"] = "es-ES-Standard-E", -- Female
|
["es_ES_Standard_C"] = "es-ES-Standard-E", -- Female
|
||||||
@@ -497,32 +502,36 @@ MSRS.Voices = {
|
|||||||
["it_IT_Standard_F"] = "it-IT-Standard-F", -- Male
|
["it_IT_Standard_F"] = "it-IT-Standard-F", -- Male
|
||||||
},
|
},
|
||||||
Wavenet = {
|
Wavenet = {
|
||||||
["en_AU_Wavenet_A"] = 'en-AU-Wavenet-A', -- [1] FEMALE
|
["en_AU_Wavenet_A"] = 'en-AU-Wavenet-A', -- Female
|
||||||
["en_AU_Wavenet_B"] = 'en-AU-Wavenet-B', -- [2] MALE
|
["en_AU_Wavenet_B"] = 'en-AU-Wavenet-B', -- Male
|
||||||
["en_AU_Wavenet_C"] = 'en-AU-Wavenet-C', -- [3] FEMALE
|
["en_AU_Wavenet_C"] = 'en-AU-Wavenet-C', -- Female
|
||||||
["en_AU_Wavenet_D"] = 'en-AU-Wavenet-D', -- [4] MALE
|
["en_AU_Wavenet_D"] = 'en-AU-Wavenet-D', -- Male
|
||||||
["en_IN_Wavenet_A"] = 'en-IN-Wavenet-A', -- [5] FEMALE
|
-- IN
|
||||||
["en_IN_Wavenet_B"] = 'en-IN-Wavenet-B', -- [6] MALE
|
["en_IN_Wavenet_A"] = 'en-IN-Wavenet-A', -- Female
|
||||||
["en_IN_Wavenet_C"] = 'en-IN-Wavenet-C', -- [7] MALE
|
["en_IN_Wavenet_B"] = 'en-IN-Wavenet-B', -- Male
|
||||||
["en_IN_Wavenet_D"] = 'en-IN-Wavenet-D', -- [8] FEMALE
|
["en_IN_Wavenet_C"] = 'en-IN-Wavenet-C', -- Male
|
||||||
|
["en_IN_Wavenet_D"] = 'en-IN-Wavenet-D', -- Female
|
||||||
|
["en_IN_Wavenet_E"] = 'en-IN-Wavenet-E', -- Female
|
||||||
|
["en_IN_Wavenet_F"] = 'en-IN-Wavenet-F', -- Male
|
||||||
-- 2025 changes
|
-- 2025 changes
|
||||||
["en_GB_Wavenet_A"] = 'en-GB-Wavenet-N', -- [9] FEMALE
|
["en_GB_Wavenet_A"] = 'en-GB-Wavenet-A', -- [9] FEMALE
|
||||||
["en_GB_Wavenet_B"] = 'en-GB-Wavenet-O', -- [10] MALE
|
["en_GB_Wavenet_B"] = 'en-GB-Wavenet-B', -- [10] MALE
|
||||||
["en_GB_Wavenet_C"] = 'en-GB-Wavenet-N', -- [11] FEMALE
|
["en_GB_Wavenet_C"] = 'en-GB-Wavenet-C', -- [11] FEMALE
|
||||||
["en_GB_Wavenet_D"] = 'en-GB-Wavenet-O', -- [12] MALE
|
["en_GB_Wavenet_D"] = 'en-GB-Wavenet-D', -- [12] MALE
|
||||||
["en_GB_Wavenet_F"] = 'en-GB-Wavenet-N', -- [13] FEMALE
|
["en_GB_Wavenet_F"] = 'en-GB-Wavenet-F', -- [13] FEMALE
|
||||||
["en_GB_Wavenet_O"] = 'en-GB-Wavenet-O', -- [12] MALE
|
["en_GB_Wavenet_O"] = 'en-GB-Wavenet-O', -- [12] MALE
|
||||||
["en_GB_Wavenet_N"] = 'en-GB-Wavenet-N', -- [13] FEMALE
|
["en_GB_Wavenet_N"] = 'en-GB-Wavenet-N', -- [13] FEMALE
|
||||||
["en_US_Wavenet_A"] = 'en-US-Wavenet-N', -- [14] MALE
|
-- US
|
||||||
["en_US_Wavenet_B"] = 'en-US-Wavenet-B', -- [15] MALE
|
["en_US_Wavenet_A"] = 'en-US-Wavenet-A', -- Male
|
||||||
["en_US_Wavenet_C"] = 'en-US-Wavenet-C', -- [16] FEMALE
|
["en_US_Wavenet_B"] = 'en-US-Wavenet-B', -- Male
|
||||||
["en_US_Wavenet_D"] = 'en-US-Wavenet-D', -- [17] MALE
|
["en_US_Wavenet_C"] = 'en-US-Wavenet-C', -- Female
|
||||||
["en_US_Wavenet_E"] = 'en-US-Wavenet-E', -- [18] FEMALE
|
["en_US_Wavenet_D"] = 'en-US-Wavenet-D', -- Male
|
||||||
["en_US_Wavenet_F"] = 'en-US-Wavenet-F', -- [19] FEMALE
|
["en_US_Wavenet_E"] = 'en-US-Wavenet-E', -- Female
|
||||||
["en_US_Wavenet_G"] = 'en-US-Wavenet-G', -- [20] FEMALE
|
["en_US_Wavenet_F"] = 'en-US-Wavenet-F', -- Female
|
||||||
["en_US_Wavenet_H"] = 'en-US-Wavenet-H', -- [21] FEMALE
|
["en_US_Wavenet_G"] = 'en-US-Wavenet-G', -- Female
|
||||||
["en_US_Wavenet_I"] = 'en-US-Wavenet-I', -- [22] MALE
|
["en_US_Wavenet_H"] = 'en-US-Wavenet-H', -- Female
|
||||||
["en_US_Wavenet_J"] = 'en-US-Wavenet-J', -- [23] MALE
|
["en_US_Wavenet_I"] = 'en-US-Wavenet-I', -- Male
|
||||||
|
["en_US_Wavenet_J"] = 'en-US-Wavenet-J', -- Male
|
||||||
-- 2025 catalog changes
|
-- 2025 catalog changes
|
||||||
["fr_FR_Wavenet_A"] = "fr-FR-Wavenet-F", -- Female
|
["fr_FR_Wavenet_A"] = "fr-FR-Wavenet-F", -- Female
|
||||||
["fr_FR_Wavenet_B"] = "fr-FR-Wavenet-G", -- Male
|
["fr_FR_Wavenet_B"] = "fr-FR-Wavenet-G", -- Male
|
||||||
@@ -532,14 +541,15 @@ MSRS.Voices = {
|
|||||||
["fr_FR_Wavenet_G"] = "fr-FR-Wavenet-G", -- Male
|
["fr_FR_Wavenet_G"] = "fr-FR-Wavenet-G", -- Male
|
||||||
["fr_FR_Wavenet_F"] = "fr-FR-Wavenet-F", -- Female
|
["fr_FR_Wavenet_F"] = "fr-FR-Wavenet-F", -- Female
|
||||||
-- 2025 catalog changes
|
-- 2025 catalog changes
|
||||||
["de_DE_Wavenet_A"] = "de-DE-Wavenet-G", -- Female
|
["de_DE_Wavenet_A"] = 'de-DE-Wavenet-A', -- Female
|
||||||
["de_DE_Wavenet_B"] = "de-DE-Wavenet-H", -- Male
|
["de_DE_Wavenet_B"] = 'de-DE-Wavenet-B', -- Male
|
||||||
["de_DE_Wavenet_C"] = "de-DE-Wavenet-G", -- Female
|
["de_DE_Wavenet_C"] = 'de-DE-Wavenet-C', -- Female
|
||||||
["de_DE_Wavenet_D"] = "de-DE-Wavenet-H", -- Male
|
["de_DE_Wavenet_D"] = 'de-DE-Wavenet-D', -- Male
|
||||||
["de_DE_Wavenet_E"] = "de-DE-Wavenet-H", -- Male
|
["de_DE_Wavenet_E"] = 'de-DE-Wavenet-E', -- Male
|
||||||
["de_DE_Wavenet_F"] = "de-DE-Wavenet-G", -- Female
|
["de_DE_Wavenet_F"] = 'de-DE-Wavenet-F', -- Female
|
||||||
["de_DE_Wavenet_H"] = "de-DE-Wavenet-H", -- Male
|
["de_DE_Wavenet_G"] = 'de-DE-Wavenet-G', -- Female
|
||||||
["de_DE_Wavenet_G"] = "de-DE-Wavenet-G", -- Female
|
["de_DE_Wavenet_H"] = 'de-DE-Wavenet-H', -- Male
|
||||||
|
-- ES
|
||||||
["es_ES_Wavenet_B"] = "es-ES-Wavenet-E", -- Male
|
["es_ES_Wavenet_B"] = "es-ES-Wavenet-E", -- Male
|
||||||
["es_ES_Wavenet_C"] = "es-ES-Wavenet-F", -- Female
|
["es_ES_Wavenet_C"] = "es-ES-Wavenet-F", -- Female
|
||||||
["es_ES_Wavenet_D"] = "es-ES-Wavenet-E", -- Female
|
["es_ES_Wavenet_D"] = "es-ES-Wavenet-E", -- Female
|
||||||
@@ -553,6 +563,134 @@ MSRS.Voices = {
|
|||||||
["it_IT_Wavenet_E"] = "it-IT-Wavenet-E", -- Female
|
["it_IT_Wavenet_E"] = "it-IT-Wavenet-E", -- Female
|
||||||
["it_IT_Wavenet_F"] = "it-IT-Wavenet-F", -- Male
|
["it_IT_Wavenet_F"] = "it-IT-Wavenet-F", -- Male
|
||||||
} ,
|
} ,
|
||||||
|
Chirp3HD = {
|
||||||
|
["en_GB_Chirp3_HD_Aoede"] = 'en-GB-Chirp3-HD-Aoede', -- Female
|
||||||
|
["en_GB_Chirp3_HD_Charon"] = 'en-GB-Chirp3-HD-Charon', -- Male
|
||||||
|
["en_GB_Chirp3_HD_Fenrir"] = 'en-GB-Chirp3-HD-Fenrir', -- Male
|
||||||
|
["en_GB_Chirp3_HD_Kore"] = 'en-GB-Chirp3-HD-Kore', -- Female
|
||||||
|
["en_GB_Chirp3_HD_Leda"] = 'en-GB-Chirp3-HD-Leda', -- Female
|
||||||
|
["en_GB_Chirp3_HD_Orus"] = 'en-GB-Chirp3-HD-Orus', -- Male
|
||||||
|
["en_GB_Chirp3_HD_Puck"] = 'en-GB-Chirp3-HD-Puck', -- Male
|
||||||
|
["en_GB_Chirp3_HD_Zephyr"] = 'en-GB-Chirp3-HD-Zephyr', -- Female
|
||||||
|
--["de_DE_Chirp3_HD_Aoede"] = 'de-DE-Chirp3-HD-Aoede', -- Female (Datenfehler im Original)
|
||||||
|
["en_US_Chirp3_HD_Charon"] = 'en-US-Chirp3-HD-Charon', -- Male
|
||||||
|
["en_US_Chirp3_HD_Fenrir"] = 'en-US-Chirp3-HD-Fenrir', -- Male
|
||||||
|
["en_US_Chirp3_HD_Kore"] = 'en-US-Chirp3-HD-Kore', -- Female
|
||||||
|
["en_US_Chirp3_HD_Leda"] = 'en-US-Chirp3-HD-Leda', -- Female
|
||||||
|
["en_US_Chirp3_HD_Orus"] = 'en-US-Chirp3-HD-Orus', -- Male
|
||||||
|
["en_US_Chirp3_HD_Puck"] = 'en-US-Chirp3-HD-Puck', -- Male
|
||||||
|
--["de_DE_Chirp3_HD_Zephyr"] = 'de-DE-Chirp3-HD-Zephyr', -- Female (Datenfehler im Original)
|
||||||
|
-- DE
|
||||||
|
["de_DE_Chirp3_HD_Aoede"] = 'de-DE-Chirp3-HD-Aoede', -- Female
|
||||||
|
["de_DE_Chirp3_HD_Charon"] = 'de-DE-Chirp3-HD-Charon', -- Male
|
||||||
|
["de_DE_Chirp3_HD_Fenrir"] = 'de-DE-Chirp3-HD-Fenrir', -- Male
|
||||||
|
["de_DE_Chirp3_HD_Kore"] = 'de-DE-Chirp3-HD-Kore', -- Female
|
||||||
|
["de_DE_Chirp3_HD_Leda"] = 'de-DE-Chirp3-HD-Leda', -- Female
|
||||||
|
["de_DE_Chirp3_HD_Orus"] = 'de-DE-Chirp3-HD-Orus', -- Male
|
||||||
|
["de_DE_Chirp3_HD_Puck"] = 'de-DE-Chirp3-HD-Puck', -- Male
|
||||||
|
["de_DE_Chirp3_HD_Zephyr"] = 'de-DE-Chirp3-HD-Zephyr', -- Female
|
||||||
|
-- AU
|
||||||
|
["en_AU_Chirp3_HD_Aoede"] = 'en-AU-Chirp3-HD-Aoede', -- Female
|
||||||
|
["en_AU_Chirp3_HD_Charon"] = 'en-AU-Chirp3-HD-Charon', -- Male
|
||||||
|
["en_AU_Chirp3_HD_Fenrir"] = 'en-AU-Chirp3-HD-Fenrir', -- Male
|
||||||
|
["en_AU_Chirp3_HD_Kore"] = 'en-AU-Chirp3-HD-Kore', -- Female
|
||||||
|
["en_AU_Chirp3_HD_Leda"] = 'en-AU-Chirp3-HD-Leda', -- Female
|
||||||
|
["en_AU_Chirp3_HD_Orus"] = 'en-AU-Chirp3-HD-Orus', -- Male
|
||||||
|
["en_AU_Chirp3_HD_Puck"] = 'en-AU-Chirp3-HD-Puck', -- Male
|
||||||
|
["en_AU_Chirp3_HD_Zephyr"] = 'en-AU-Chirp3-HD-Zephyr', -- Female
|
||||||
|
-- IN
|
||||||
|
["en_IN_Chirp3_HD_Aoede"] = 'en-IN-Chirp3-HD-Aoede', -- Female
|
||||||
|
["en_IN_Chirp3_HD_Charon"] = 'en-IN-Chirp3-HD-Charon', -- Male
|
||||||
|
["en_IN_Chirp3_HD_Fenrir"] = 'en-IN-Chirp3-HD-Fenrir', -- Male
|
||||||
|
["en_IN_Chirp3_HD_Kore"] = 'en-IN-Chirp3-HD-Kore', -- Female
|
||||||
|
["en_IN_Chirp3_HD_Leda"] = 'en-IN-Chirp3-HD-Leda', -- Female
|
||||||
|
["en_IN_Chirp3_HD_Orus"] = 'en-IN-Chirp3-HD-Orus', -- Male
|
||||||
|
},
|
||||||
|
ChirpHD = {
|
||||||
|
["en_US_Chirp_HD_D"] = 'en-US-Chirp-HD-D', -- Male
|
||||||
|
["en_US_Chirp_HD_F"] = 'en-US-Chirp-HD-F', -- Female
|
||||||
|
["en_US_Chirp_HD_O"] = 'en-US-Chirp-HD-O', -- Female
|
||||||
|
-- DE
|
||||||
|
["de_DE_Chirp_HD_D"] = 'de-DE-Chirp-HD-D', -- Male
|
||||||
|
["de_DE_Chirp_HD_F"] = 'de-DE-Chirp-HD-F', -- Female
|
||||||
|
["de_DE_Chirp_HD_O"] = 'de-DE-Chirp-HD-O', -- Female
|
||||||
|
-- AU
|
||||||
|
["en_AU_Chirp_HD_D"] = 'en-AU-Chirp-HD-D', -- Male
|
||||||
|
["en_AU_Chirp_HD_F"] = 'en-AU-Chirp-HD-F', -- Female
|
||||||
|
["en_AU_Chirp_HD_O"] = 'en-AU-Chirp-HD-O', -- Female
|
||||||
|
-- IN
|
||||||
|
["en_IN_Chirp_HD_D"] = 'en-IN-Chirp-HD-D', -- Male
|
||||||
|
["en_IN_Chirp_HD_F"] = 'en-IN-Chirp-HD-F', -- Female
|
||||||
|
["en_IN_Chirp_HD_O"] = 'en-IN-Chirp-HD-O', -- Female
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Neural2 = {
|
||||||
|
["en_GB_Neural2_A"] = 'en-GB-Neural2-A', -- Female
|
||||||
|
["en_GB_Neural2_B"] = 'en-GB-Neural2-B', -- Male
|
||||||
|
["en_GB_Neural2_C"] = 'en-GB-Neural2-C', -- Female
|
||||||
|
["en_GB_Neural2_D"] = 'en-GB-Neural2-D', -- Male
|
||||||
|
["en_GB_Neural2_F"] = 'en-GB-Neural2-F', -- Female
|
||||||
|
["en_GB_Neural2_N"] = 'en-GB-Neural2-N', -- Female
|
||||||
|
["en_GB_Neural2_O"] = 'en-GB-Neural2-O', -- Male
|
||||||
|
-- US
|
||||||
|
["en_US_Neural2_A"] = 'en-US-Neural2-A', -- Male
|
||||||
|
["en_US_Neural2_C"] = 'en-US-Neural2-C', -- Female
|
||||||
|
["en_US_Neural2_D"] = 'en-US-Neural2-D', -- Male
|
||||||
|
["en_US_Neural2_E"] = 'en-US-Neural2-E', -- Female
|
||||||
|
["en_US_Neural2_F"] = 'en-US-Neural2-F', -- Female
|
||||||
|
["en_US_Neural2_G"] = 'en-US-Neural2-G', -- Female
|
||||||
|
["en_US_Neural2_H"] = 'en-US-Neural2-H', -- Female
|
||||||
|
["en_US_Neural2_I"] = 'en-US-Neural2-I', -- Male
|
||||||
|
["en_US_Neural2_J"] = 'en-US-Neural2-J', -- Male
|
||||||
|
-- DE
|
||||||
|
["de_DE_Neural2_G"] = 'de-DE-Neural2-G', -- Female
|
||||||
|
["de_DE_Neural2_H"] = 'de-DE-Neural2-H', -- Male
|
||||||
|
-- AU
|
||||||
|
["en_AU_Neural2_A"] = 'en-AU-Neural2-A', -- Female
|
||||||
|
["en_AU_Neural2_B"] = 'en-AU-Neural2-B', -- Male
|
||||||
|
["en_AU_Neural2_C"] = 'en-AU-Neural2-C', -- Female
|
||||||
|
["en_AU_Neural2_D"] = 'en-AU-Neural2-D', -- Male
|
||||||
|
-- IN
|
||||||
|
["en_IN_Neural2_A"] = 'en-IN-Neural2-A', -- Female
|
||||||
|
["en_IN_Neural2_B"] = 'en-IN-Neural2-B', -- Male
|
||||||
|
["en_IN_Neural2_C"] = 'en-IN-Neural2-C', -- Male
|
||||||
|
["en_IN_Neural2_D"] = 'en-IN-Neural2-D', -- Female
|
||||||
|
},
|
||||||
|
News = {
|
||||||
|
["en_GB_News_G"] = 'en-GB-News-G', -- Female
|
||||||
|
["en_GB_News_H"] = 'en-GB-News-H', -- Female
|
||||||
|
["en_GB_News_I"] = 'en-GB-News-I', -- Female
|
||||||
|
["en_GB_News_J"] = 'en-GB-News-J', -- Male
|
||||||
|
["en_GB_News_K"] = 'en-GB-News-K', -- Male
|
||||||
|
["en_GB_News_L"] = 'en-GB-News-L', -- Male
|
||||||
|
["en_GB_News_M"] = 'en-GB-News-M', -- Male
|
||||||
|
-- US
|
||||||
|
["en_US_News_K"] = 'en-US-News-K', -- Female
|
||||||
|
["en_US_News_L"] = 'en-US-News-L', -- Female
|
||||||
|
["en_US_News_N"] = 'en-US-News-N', -- Male
|
||||||
|
-- AU
|
||||||
|
["en_AU_News_E"] = 'en-AU-News-E', -- Female
|
||||||
|
["en_AU_News_F"] = 'en-AU-News-F', -- Female
|
||||||
|
["en_AU_News_G"] = 'en-AU-News-G', -- Male
|
||||||
|
},
|
||||||
|
Casual = {
|
||||||
|
["en_US_Casual_K"] = 'en-US-Casual-K', -- Male
|
||||||
|
},
|
||||||
|
Polyglot = {
|
||||||
|
["en_US_Polyglot_1"] = 'en-US-Polyglot-1', -- Male
|
||||||
|
["de_DE_Polyglot_1"] = 'de-DE-Polyglot-1', -- Male
|
||||||
|
["en_AU_Polyglot_1"] = 'en-AU-Polyglot-1', -- Male
|
||||||
|
},
|
||||||
|
Studio = {
|
||||||
|
-- Englisch (UK) - Studio
|
||||||
|
["en_GB_Studio_B"] = 'en-GB-Studio-B', -- Male
|
||||||
|
["en_GB_Studio_C"] = 'en-GB-Studio-C', -- Female
|
||||||
|
-- Englisch (USA) - Studio
|
||||||
|
["en_US_Studio_O"] = 'en-US-Studio-O', -- Female
|
||||||
|
["en_US_Studio_Q"] = 'en-US-Studio-Q', -- Male
|
||||||
|
-- DE
|
||||||
|
["de_DE_Studio_B"] = 'de-DE-Studio-B', -- Male
|
||||||
|
["de_DE_Studio_C"] = 'de-DE-Studio-C', -- Female
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -632,7 +770,7 @@ end
|
|||||||
-- set the path to the exe file via @{#MSRS.SetPath}.
|
-- set the path to the exe file via @{#MSRS.SetPath}.
|
||||||
--
|
--
|
||||||
-- @param #MSRS self
|
-- @param #MSRS self
|
||||||
-- @param #string Path Path to SRS directory. Default `C:\\Program Files\\DCS-SimpleRadio-Standalone`.
|
-- @param #string Path Path to SRS directory. Default `C:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio`.
|
||||||
-- @param #number Frequency Radio frequency in MHz. Default 143.00 MHz. Can also be given as a #table of multiple frequencies.
|
-- @param #number Frequency Radio frequency in MHz. Default 143.00 MHz. Can also be given as a #table of multiple frequencies.
|
||||||
-- @param #number Modulation Radio modulation: 0=AM (default), 1=FM. See `radio.modulation.AM` and `radio.modulation.FM` enumerators. Can also be given as a #table of multiple modulations.
|
-- @param #number Modulation Radio modulation: 0=AM (default), 1=FM. See `radio.modulation.AM` and `radio.modulation.FM` enumerators. Can also be given as a #table of multiple modulations.
|
||||||
-- @param #string Backend Backend used: `MSRS.Backend.SRSEXE` (default) or `MSRS.Backend.GRPC`.
|
-- @param #string Backend Backend used: `MSRS.Backend.SRSEXE` (default) or `MSRS.Backend.GRPC`.
|
||||||
@@ -767,13 +905,13 @@ end
|
|||||||
|
|
||||||
--- Set path to SRS install directory. More precisely, path to where the `DCS-SR-ExternalAudio.exe` is located.
|
--- Set path to SRS install directory. More precisely, path to where the `DCS-SR-ExternalAudio.exe` is located.
|
||||||
-- @param #MSRS self
|
-- @param #MSRS self
|
||||||
-- @param #string Path Path to the directory, where the sound file is located. Default is `C:\\Program Files\\DCS-SimpleRadio-Standalone`.
|
-- @param #string Path Path to the directory, where the sound file is located. Default is `C:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio`.
|
||||||
-- @return #MSRS self
|
-- @return #MSRS self
|
||||||
function MSRS:SetPath(Path)
|
function MSRS:SetPath(Path)
|
||||||
self:F( {Path=Path} )
|
self:F( {Path=Path} )
|
||||||
|
|
||||||
-- Set path.
|
-- Set path.
|
||||||
self.path=Path or "C:\\Program Files\\DCS-SimpleRadio-Standalone"
|
self.path=Path or "C:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio"
|
||||||
|
|
||||||
-- Remove (back)slashes.
|
-- Remove (back)slashes.
|
||||||
local n=1 ; local nmax=1000
|
local n=1 ; local nmax=1000
|
||||||
@@ -1817,7 +1955,7 @@ end
|
|||||||
--
|
--
|
||||||
-- -- Moose MSRS default Config
|
-- -- Moose MSRS default Config
|
||||||
-- MSRS_Config = {
|
-- MSRS_Config = {
|
||||||
-- Path = "C:\\Program Files\\DCS-SimpleRadio-Standalone", -- Path to SRS install directory.
|
-- Path = "C:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio", -- Path to SRS install directory.
|
||||||
-- Port = 5002, -- Port of SRS server. Default 5002.
|
-- Port = 5002, -- Port of SRS server. Default 5002.
|
||||||
-- Backend = "srsexe", -- Interface to SRS: "srsexe" or "grpc".
|
-- Backend = "srsexe", -- Interface to SRS: "srsexe" or "grpc".
|
||||||
-- Frequency = {127, 243}, -- Default frequences. Must be a table 1..n entries!
|
-- Frequency = {127, 243}, -- Default frequences. Must be a table 1..n entries!
|
||||||
@@ -1837,7 +1975,7 @@ end
|
|||||||
-- -- Google Cloud
|
-- -- Google Cloud
|
||||||
-- gcloud = {
|
-- gcloud = {
|
||||||
-- voice = "en-GB-Standard-A", -- The Google Cloud voice to use (see https://cloud.google.com/text-to-speech/docs/voices).
|
-- voice = "en-GB-Standard-A", -- The Google Cloud voice to use (see https://cloud.google.com/text-to-speech/docs/voices).
|
||||||
-- credentials="C:\\Program Files\\DCS-SimpleRadio-Standalone\\yourfilename.json", -- Full path to credentials JSON file (only for SRS-TTS.exe backend)
|
-- credentials="C:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio\\yourfilename.json", -- Full path to credentials JSON file (only for SRS-TTS.exe backend)
|
||||||
-- key="Your access Key", -- Google API access key (only for DCS-gRPC backend)
|
-- key="Your access Key", -- Google API access key (only for DCS-gRPC backend)
|
||||||
-- },
|
-- },
|
||||||
-- -- Amazon Web Service
|
-- -- Amazon Web Service
|
||||||
@@ -1905,7 +2043,7 @@ function MSRS:LoadConfigFile(Path,Filename)
|
|||||||
|
|
||||||
local Self = self or MSRS --#MSRS
|
local Self = self or MSRS --#MSRS
|
||||||
|
|
||||||
Self.path = MSRS_Config.Path or "C:\\Program Files\\DCS-SimpleRadio-Standalone"
|
Self.path = MSRS_Config.Path or "C:\\Program Files\\DCS-SimpleRadio-Standalone\\ExternalAudio"
|
||||||
Self.port = MSRS_Config.Port or 5002
|
Self.port = MSRS_Config.Port or 5002
|
||||||
Self.backend = MSRS_Config.Backend or MSRS.Backend.SRSEXE
|
Self.backend = MSRS_Config.Backend or MSRS.Backend.SRSEXE
|
||||||
Self.frequencies = MSRS_Config.Frequency or {127,243}
|
Self.frequencies = MSRS_Config.Frequency or {127,243}
|
||||||
|
|||||||
@@ -30,6 +30,8 @@
|
|||||||
|
|
||||||
--- Governs multiple missions, the tasking and the reporting.
|
--- Governs multiple missions, the tasking and the reporting.
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- Command centers govern missions, communicates the task assignments between human players of the coalition, and manages the menu flow.
|
-- Command centers govern missions, communicates the task assignments between human players of the coalition, and manages the menu flow.
|
||||||
-- It can assign a random task to a player when requested.
|
-- It can assign a random task to a player when requested.
|
||||||
-- The commandcenter provides the facilitites to communicate between human players online, executing a task.
|
-- The commandcenter provides the facilitites to communicate between human players online, executing a task.
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
-- The @{#DETECTION_MANAGER} class defines the core functions to report detected objects to groups.
|
-- The @{#DETECTION_MANAGER} class defines the core functions to report detected objects to groups.
|
||||||
-- Reportings can be done in several manners, and it is up to the derived classes if DETECTION_MANAGER to model the reporting behaviour.
|
-- Reportings can be done in several manners, and it is up to the derived classes if DETECTION_MANAGER to model the reporting behaviour.
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- 1.1) DETECTION_MANAGER constructor:
|
-- 1.1) DETECTION_MANAGER constructor:
|
||||||
-- -----------------------------------
|
-- -----------------------------------
|
||||||
-- * @{#DETECTION_MANAGER.New}(): Create a new DETECTION_MANAGER instance.
|
-- * @{#DETECTION_MANAGER.New}(): Create a new DETECTION_MANAGER instance.
|
||||||
|
|||||||
@@ -27,6 +27,8 @@
|
|||||||
|
|
||||||
--- Models goals to be achieved and can contain multiple tasks to be executed to achieve the goals.
|
--- Models goals to be achieved and can contain multiple tasks to be executed to achieve the goals.
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- A mission contains multiple tasks and can be of different task types.
|
-- A mission contains multiple tasks and can be of different task types.
|
||||||
-- These tasks need to be assigned to human players to be executed.
|
-- These tasks need to be assigned to human players to be executed.
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -12,6 +12,8 @@
|
|||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- # 1) Tasking from a player perspective.
|
-- # 1) Tasking from a player perspective.
|
||||||
--
|
--
|
||||||
-- Tasking can be controlled by using the "other" menu in the radio menu of the player group.
|
-- Tasking can be controlled by using the "other" menu in the radio menu of the player group.
|
||||||
|
|||||||
@@ -17,6 +17,8 @@
|
|||||||
---
|
---
|
||||||
-- # TASKINFO class, extends @{Core.Base#BASE}
|
-- # TASKINFO class, extends @{Core.Base#BASE}
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- ## The TASKINFO class implements the methods to contain information and display information of a task.
|
-- ## The TASKINFO class implements the methods to contain information and display information of a task.
|
||||||
--
|
--
|
||||||
-- # Developer Note
|
-- # Developer Note
|
||||||
|
|||||||
@@ -20,6 +20,9 @@ do -- TASK_A2A
|
|||||||
|
|
||||||
--- Defines Air To Air tasks for a @{Core.Set} of Target Units,
|
--- Defines Air To Air tasks for a @{Core.Set} of Target Units,
|
||||||
-- based on the tasking capabilities defined in @{Tasking.Task#TASK}.
|
-- based on the tasking capabilities defined in @{Tasking.Task#TASK}.
|
||||||
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- The TASK_A2A is implemented using a @{Core.Fsm#FSM_TASK}, and has the following statuses:
|
-- The TASK_A2A is implemented using a @{Core.Fsm#FSM_TASK}, and has the following statuses:
|
||||||
--
|
--
|
||||||
-- * **None**: Start of the process
|
-- * **None**: Start of the process
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ do -- TASK_A2A_DISPATCHER
|
|||||||
|
|
||||||
--- Orchestrates the dynamic dispatching of tasks upon groups of detected units determined a @{Core.Set} of EWR installation groups.
|
--- Orchestrates the dynamic dispatching of tasks upon groups of detected units determined a @{Core.Set} of EWR installation groups.
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- 
|
-- 
|
||||||
--
|
--
|
||||||
-- The EWR will detect units, will group them, and will dispatch @{Tasking.Task}s to groups. Depending on the type of target detected, different tasks will be dispatched.
|
-- The EWR will detect units, will group them, and will dispatch @{Tasking.Task}s to groups. Depending on the type of target detected, different tasks will be dispatched.
|
||||||
|
|||||||
@@ -20,6 +20,9 @@ do -- TASK_A2G
|
|||||||
|
|
||||||
--- The TASK_A2G class defines Air To Ground tasks for a @{Core.Set} of Target Units,
|
--- The TASK_A2G class defines Air To Ground tasks for a @{Core.Set} of Target Units,
|
||||||
-- based on the tasking capabilities defined in @{Tasking.Task#TASK}.
|
-- based on the tasking capabilities defined in @{Tasking.Task#TASK}.
|
||||||
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- The TASK_A2G is implemented using a @{Core.Fsm#FSM_TASK}, and has the following statuses:
|
-- The TASK_A2G is implemented using a @{Core.Fsm#FSM_TASK}, and has the following statuses:
|
||||||
--
|
--
|
||||||
-- * **None**: Start of the process
|
-- * **None**: Start of the process
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ do -- TASK_A2G_DISPATCHER
|
|||||||
|
|
||||||
--- Orchestrates dynamic **A2G Task Dispatching** based on the detection results of a linked @{Functional.Detection} object.
|
--- Orchestrates dynamic **A2G Task Dispatching** based on the detection results of a linked @{Functional.Detection} object.
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- It uses the Tasking System within the MOOSE framework, which is a multi-player Tasking Orchestration system.
|
-- It uses the Tasking System within the MOOSE framework, which is a multi-player Tasking Orchestration system.
|
||||||
-- It provides a truly dynamic battle environment for pilots and ground commanders to engage upon,
|
-- It provides a truly dynamic battle environment for pilots and ground commanders to engage upon,
|
||||||
-- in a true co-operation environment wherein **Multiple Teams** will collaborate in Missions to **achieve a common Mission Goal**.
|
-- in a true co-operation environment wherein **Multiple Teams** will collaborate in Missions to **achieve a common Mission Goal**.
|
||||||
|
|||||||
@@ -10,6 +10,8 @@
|
|||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- ## Test Missions:
|
-- ## Test Missions:
|
||||||
--
|
--
|
||||||
-- Test missions can be located on the main GITHUB site.
|
-- Test missions can be located on the main GITHUB site.
|
||||||
@@ -1176,7 +1178,7 @@ do -- TASK_CARGO
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
---@param Color Might be SMOKECOLOR.Blue, SMOKECOLOR.Red SMOKECOLOR.Orange, SMOKECOLOR.White or SMOKECOLOR.Green
|
--@param Color Might be SMOKECOLOR.Blue, SMOKECOLOR.Red SMOKECOLOR.Orange, SMOKECOLOR.White or SMOKECOLOR.Green
|
||||||
function TASK_CARGO:SetSmokeColor(SmokeColor)
|
function TASK_CARGO:SetSmokeColor(SmokeColor)
|
||||||
-- Makes sure Coloe is set
|
-- Makes sure Coloe is set
|
||||||
if SmokeColor == nil then
|
if SmokeColor == nil then
|
||||||
|
|||||||
@@ -76,6 +76,8 @@ do -- TASK_CAPTURE_DISPATCHER
|
|||||||
|
|
||||||
--- Implements the dynamic dispatching of capture zone tasks.
|
--- Implements the dynamic dispatching of capture zone tasks.
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- The **TASK_CAPTURE_DISPATCHER** allows you to setup various tasks for let human
|
-- The **TASK_CAPTURE_DISPATCHER** allows you to setup various tasks for let human
|
||||||
-- players capture zones in a co-operation effort.
|
-- players capture zones in a co-operation effort.
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ do -- TASK_ZONE_GOAL
|
|||||||
|
|
||||||
--- # TASK_ZONE_GOAL class, extends @{Tasking.Task#TASK}
|
--- # TASK_ZONE_GOAL class, extends @{Tasking.Task#TASK}
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- The TASK_ZONE_GOAL class defines the task to protect or capture a protection zone.
|
-- The TASK_ZONE_GOAL class defines the task to protect or capture a protection zone.
|
||||||
-- The TASK_ZONE_GOAL is implemented using a @{Core.Fsm#FSM_TASK}, and has the following statuses:
|
-- The TASK_ZONE_GOAL is implemented using a @{Core.Fsm#FSM_TASK}, and has the following statuses:
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -44,6 +44,8 @@
|
|||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- Please read through the @{Tasking.Task_CARGO} process to understand the mechanisms of tasking and cargo tasking and handling.
|
-- Please read through the @{Tasking.Task_CARGO} process to understand the mechanisms of tasking and cargo tasking and handling.
|
||||||
--
|
--
|
||||||
-- The cargo will be a downed pilot, which is located somwhere on the battlefield. Use the menus system and facilities to
|
-- The cargo will be a downed pilot, which is located somwhere on the battlefield. Use the menus system and facilities to
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
-- The **TASK_CARGO_DISPATCHER** allows you to setup various tasks for let human
|
-- The **TASK_CARGO_DISPATCHER** allows you to setup various tasks for let human
|
||||||
-- players transport cargo as part of a task.
|
-- players transport cargo as part of a task.
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- The cargo dispatcher will implement for you mechanisms to create cargo transportation tasks:
|
-- The cargo dispatcher will implement for you mechanisms to create cargo transportation tasks:
|
||||||
--
|
--
|
||||||
-- * As setup by the mission designer.
|
-- * As setup by the mission designer.
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
--- **Tasking** - Models tasks for players to transport cargo.
|
--- **Tasking** - Models tasks for players to transport cargo.
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- **Specific features:**
|
-- **Specific features:**
|
||||||
--
|
--
|
||||||
-- * Creates a task to transport #Cargo.Cargo to and between deployment zones.
|
-- * Creates a task to transport #Cargo.Cargo to and between deployment zones.
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- 1) @{Tasking.Task_Manager#TASK_MANAGER} class, extends @{Core.Fsm#FSM}
|
-- 1) @{Tasking.Task_Manager#TASK_MANAGER} class, extends @{Core.Fsm#FSM}
|
||||||
-- ===
|
-- ===
|
||||||
-- The @{Tasking.Task_Manager#TASK_MANAGER} class defines the core functions to report tasks to groups.
|
-- The @{Tasking.Task_Manager#TASK_MANAGER} class defines the core functions to report tasks to groups.
|
||||||
|
|||||||
@@ -12,27 +12,35 @@
|
|||||||
-- @module Utilities.Utils
|
-- @module Utilities.Utils
|
||||||
-- @image MOOSE.JPG
|
-- @image MOOSE.JPG
|
||||||
|
|
||||||
---
|
--- Smoke color enum `trigger.smokeColor`.
|
||||||
-- @type SMOKECOLOR
|
-- @type SMOKECOLOR
|
||||||
-- @field Green
|
-- @field #number Green Green smoke (0)
|
||||||
-- @field Red
|
-- @field #number Red Red smoke (1)
|
||||||
-- @field White
|
-- @field #number White White smoke (2)
|
||||||
-- @field Orange
|
-- @field #number Orange Orange smoke (3)
|
||||||
-- @field Blue
|
-- @field #number Blue Blue smoke (4)
|
||||||
|
|
||||||
SMOKECOLOR = trigger.smokeColor -- #SMOKECOLOR
|
SMOKECOLOR = trigger.smokeColor -- #SMOKECOLOR
|
||||||
|
|
||||||
---
|
--- Flare colur enum `trigger.flareColor`.
|
||||||
-- @type FLARECOLOR
|
-- @type FLARECOLOR
|
||||||
-- @field Green
|
-- @field #number Green (0)
|
||||||
-- @field Red
|
-- @field #number Red Red flare (1)
|
||||||
-- @field White
|
-- @field #number White White flare (2)
|
||||||
-- @field Yellow
|
-- @field #number Yellow Yellow flare (3)
|
||||||
|
|
||||||
FLARECOLOR = trigger.flareColor -- #FLARECOLOR
|
FLARECOLOR = trigger.flareColor -- #FLARECOLOR
|
||||||
|
|
||||||
--- Big smoke preset enum.
|
--- Big smoke preset enum.
|
||||||
-- @type BIGSMOKEPRESET
|
-- @type BIGSMOKEPRESET
|
||||||
|
-- @field #number SmallSmokeAndFire Small moke and fire (1)
|
||||||
|
-- @field #number MediumSmokeAndFire Medium smoke and fire (2)
|
||||||
|
-- @field #number LargeSmokeAndFire Large smoke and fire (3)
|
||||||
|
-- @field #number HugeSmokeAndFire Huge smoke and fire (4)
|
||||||
|
-- @field #number SmallSmoke Small smoke (5)
|
||||||
|
-- @field #number MediumSmoke Medium smoke (6)
|
||||||
|
-- @field #number LargeSmoke Large smoke (7)
|
||||||
|
-- @field #number HugeSmoke Huge smoke (8)
|
||||||
BIGSMOKEPRESET = {
|
BIGSMOKEPRESET = {
|
||||||
SmallSmokeAndFire=1,
|
SmallSmokeAndFire=1,
|
||||||
MediumSmokeAndFire=2,
|
MediumSmokeAndFire=2,
|
||||||
@@ -351,7 +359,7 @@ end
|
|||||||
-- @return #string Table as a string.
|
-- @return #string Table as a string.
|
||||||
UTILS.OneLineSerialize = function( tbl ) -- serialization of a table all on a single line, no comments, made to replace old get_table_string function
|
UTILS.OneLineSerialize = function( tbl ) -- serialization of a table all on a single line, no comments, made to replace old get_table_string function
|
||||||
|
|
||||||
lookup_table = {}
|
local lookup_table = {}
|
||||||
|
|
||||||
local function _Serialize( tbl )
|
local function _Serialize( tbl )
|
||||||
|
|
||||||
@@ -490,7 +498,7 @@ end
|
|||||||
|
|
||||||
--- Counts the number of elements in a table.
|
--- Counts the number of elements in a table.
|
||||||
-- @param #table T Table to count
|
-- @param #table T Table to count
|
||||||
-- @return #int Number of elements in the table
|
-- @return #number Number of elements in the table
|
||||||
function UTILS.TableLength(T)
|
function UTILS.TableLength(T)
|
||||||
local count = 0
|
local count = 0
|
||||||
for _ in pairs(T or {}) do count = count + 1 end
|
for _ in pairs(T or {}) do count = count + 1 end
|
||||||
@@ -1906,6 +1914,13 @@ function UTILS.GetReportingName(Typename)
|
|||||||
|
|
||||||
local typename = string.lower(Typename)
|
local typename = string.lower(Typename)
|
||||||
|
|
||||||
|
-- special cases - Shark and Manstay have "A-50" in the name
|
||||||
|
if string.find(typename,"ka-50",1,true) then
|
||||||
|
return "Shark"
|
||||||
|
elseif string.find(typename,"a-50",1,true) then
|
||||||
|
return "Mainstay"
|
||||||
|
end
|
||||||
|
|
||||||
for name, value in pairs(ENUMS.ReportingName.NATO) do
|
for name, value in pairs(ENUMS.ReportingName.NATO) do
|
||||||
local svalue = string.lower(value)
|
local svalue = string.lower(value)
|
||||||
if string.find(typename,svalue,1,true) then
|
if string.find(typename,svalue,1,true) then
|
||||||
@@ -2137,9 +2152,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/S" -- The sun never rises on this location on the specified date
|
return "N/R" -- The sun never rises on this location on the specified date
|
||||||
elseif cosH < -1 then
|
elseif cosH < -1 then
|
||||||
return "N/R" -- The sun never sets on this location on the specified date
|
return "N/S" -- 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
|
||||||
@@ -4128,9 +4143,14 @@ end
|
|||||||
-- @param #string VehicleTemplate, template name for additional vehicles. Can be nil for no additional vehicles.
|
-- @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 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.
|
-- @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.
|
||||||
|
-- @param #number Airframes Number of helicopter airframes per known type in Ops.CSAR#CSAR.AircraftType to be added initially to the FARP. Set to 0 for no airframes.
|
||||||
|
-- @param #string F10Text Text to display on F10 map if given. Handy to post things like the ADF beacon Frequency, Callsign and ATC Frequency.
|
||||||
|
-- @param #boolean DynamicSpawns If true, allow Dynamic Spawns from this FARP.
|
||||||
|
-- @param #boolean HotStart If true and DynamicSpawns is true, allow hot starts for Dynamic Spawns from this FARP.
|
||||||
-- @return #list<Wrapper.Static#STATIC> Table of spawned objects and vehicle object (if given).
|
-- @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.
|
-- @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)
|
-- @return #number MarkerID ID of the F10 Text, to be able to remove it later.
|
||||||
|
function UTILS.SpawnFARPAndFunctionalStatics(Name,Coordinate,FARPType,Coalition,Country,CallSign,Frequency,Modulation,ADF,SpawnRadius,VehicleTemplate,Liquids,Equipment,Airframes,F10Text,DynamicSpawns,HotStart)
|
||||||
|
|
||||||
-- Set Defaults
|
-- Set Defaults
|
||||||
local farplocation = Coordinate
|
local farplocation = Coordinate
|
||||||
@@ -4144,6 +4164,7 @@ function UTILS.SpawnFARPAndFunctionalStatics(Name,Coordinate,FARPType,Coalition,
|
|||||||
local liquids = Liquids or 10
|
local liquids = Liquids or 10
|
||||||
liquids = liquids * 1000 -- tons to kg
|
liquids = liquids * 1000 -- tons to kg
|
||||||
local equip = Equipment or 10
|
local equip = Equipment or 10
|
||||||
|
local airframes = Airframes or 10
|
||||||
local statictypes = ENUMS.FARPObjectTypeNamesAndShape[farptype] or {TypeName="FARP", ShapeName="FARPS"}
|
local statictypes = ENUMS.FARPObjectTypeNamesAndShape[farptype] or {TypeName="FARP", ShapeName="FARPS"}
|
||||||
local STypeName = statictypes.TypeName
|
local STypeName = statictypes.TypeName
|
||||||
local SShapeName = statictypes.ShapeName
|
local SShapeName = statictypes.ShapeName
|
||||||
@@ -4153,7 +4174,7 @@ function UTILS.SpawnFARPAndFunctionalStatics(Name,Coordinate,FARPType,Coalition,
|
|||||||
-- Spawn FARP
|
-- Spawn FARP
|
||||||
local newfarp = SPAWNSTATIC:NewFromType(STypeName,"Heliports",Country) -- "Invisible FARP" "FARP"
|
local newfarp = SPAWNSTATIC:NewFromType(STypeName,"Heliports",Country) -- "Invisible FARP" "FARP"
|
||||||
newfarp:InitShape(SShapeName) -- "invisiblefarp" "FARPS"
|
newfarp:InitShape(SShapeName) -- "invisiblefarp" "FARPS"
|
||||||
newfarp:InitFARP(callsign,freq,mod)
|
newfarp:InitFARP(callsign,freq,mod,DynamicSpawns,HotStart)
|
||||||
local spawnedfarp = newfarp:SpawnFromCoordinate(farplocation,0,Name)
|
local spawnedfarp = newfarp:SpawnFromCoordinate(farplocation,0,Name)
|
||||||
table.insert(ReturnObjects,spawnedfarp)
|
table.insert(ReturnObjects,spawnedfarp)
|
||||||
-- Spawn Objects
|
-- Spawn Objects
|
||||||
@@ -4206,6 +4227,12 @@ function UTILS.SpawnFARPAndFunctionalStatics(Name,Coordinate,FARPType,Coalition,
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if airframes and airframes > 0 then
|
||||||
|
for typename in pairs (CSAR.AircraftType) do
|
||||||
|
newWH:SetItem(typename,airframes)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local ADFName
|
local ADFName
|
||||||
if ADF and type(ADF) == "number" then
|
if ADF and type(ADF) == "number" then
|
||||||
local ADFFreq = ADF*1000 -- KHz to Hz
|
local ADFFreq = ADF*1000 -- KHz to Hz
|
||||||
@@ -4216,7 +4243,150 @@ function UTILS.SpawnFARPAndFunctionalStatics(Name,Coordinate,FARPType,Coalition,
|
|||||||
trigger.action.radioTransmission(Sound, vec3, 0, true, ADFFreq, 250, ADFName)
|
trigger.action.radioTransmission(Sound, vec3, 0, true, ADFFreq, 250, ADFName)
|
||||||
end
|
end
|
||||||
|
|
||||||
return ReturnObjects, ADFName
|
local MarkerID = nil
|
||||||
|
if F10Text then
|
||||||
|
local Color = {0,0,1}
|
||||||
|
if Coalition == coalition.side.RED then
|
||||||
|
Color = {1,0,0}
|
||||||
|
elseif Coalition == coalition.side.NEUTRAL then
|
||||||
|
Color = {0,1,0}
|
||||||
|
end
|
||||||
|
local Alpha = 0.75
|
||||||
|
local coordinate = Coordinate:Translate(600,0)
|
||||||
|
MarkerID = coordinate:TextToAll(F10Text,Coalition,Color,1,{1,1,1},Alpha,14,true)
|
||||||
|
end
|
||||||
|
|
||||||
|
return ReturnObjects, ADFName, MarkerID
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Spawn a MASH at a given coordinate, optionally, add an ADF Beacon.
|
||||||
|
-- @param #string Name Unique Name of the Mash.
|
||||||
|
-- @param Core.Point#COORDINATE Coordinate Coordinate where to spawn the MASH. Can be given as a Core.Zone#ZONE object, in this case we take the center coordinate.
|
||||||
|
-- @param #number Country Country ID the MASH belongs to, e.g. country.id.USA or country.id.RUSSIA.
|
||||||
|
-- @param #number ADF (Optional) ADF Frequency in kHz (Kilohertz), if given activate an ADF Beacon at the location of the MASH.
|
||||||
|
-- @param #string Livery (Optional) The livery of the static CH-47, defaults to dark green.
|
||||||
|
-- @param #boolean DeployHelo (Optional) If true, deploy the helicopter static.
|
||||||
|
-- @param #number MASHRadio MASH Radio Frequency, defaults to 127.5.
|
||||||
|
-- @param #number MASHRadioModulation MASH Radio Modulation, defaults to radio.modulation.AM.
|
||||||
|
-- @param #number MASHCallsign Defaults to CALLSIGN.FARP.Berlin.
|
||||||
|
-- @param #table Templates (Optional) You can hand in your own template table of numbered(!) entries. Each entry consist of a relative(!) x,y position and data of a
|
||||||
|
-- static, shape_name is optional. Also, livery_id is optional, but is applied to the helicopter static only.
|
||||||
|
-- @return #table Table of Wrapper.Static#STATIC objects that were spawned.
|
||||||
|
-- @return #string ADFName Name of the ADF Beacon to remove it later.
|
||||||
|
-- @usage
|
||||||
|
-- -- MASH Template example, this one is the built in one used in the function:
|
||||||
|
-- MASHTemplates = {
|
||||||
|
-- [1]={category='Infantry',type='Soldier M4',shape_name='none',heading=0,x=0.000000,y=0.000000,},
|
||||||
|
-- [2]={category='Infantry',type='Soldier M4',shape_name='none',heading=0,x=0.313533,y=8.778935,},
|
||||||
|
-- [3]={category='Infantry',type='Soldier M4',shape_name='none',heading=0,x=16.303737,y=20.379671,},
|
||||||
|
-- [4]={category='Helicopters',type='CH-47Fbl1',shape_name='none',heading=0,x=-20.047735,y=-63.166179,livery_id = "us army dark green",},
|
||||||
|
-- [5]={category='Infantry',type='Soldier M4',shape_name='none',heading=0,x=26.650339,y=20.066138,},
|
||||||
|
-- [6]={category='Heliports',type='FARP_SINGLE_01',shape_name='FARP_SINGLE_01',heading=0,x=-25.432292,y=9.077099,},
|
||||||
|
-- [7]={category='Heliports',type='FARP_SINGLE_01',shape_name='FARP_SINGLE_01',heading=0,x=-12.717421,y=-3.216114,},
|
||||||
|
-- [8]={category='Heliports',type='FARP_SINGLE_01',shape_name='FARP_SINGLE_01',heading=0,x=-25.439281,y=-3.216114,},
|
||||||
|
-- [9]={category='Heliports',type='FARP_SINGLE_01',shape_name='FARP_SINGLE_01',heading=0,x=-12.717421,y=9.155603,},
|
||||||
|
-- [10]={category='Fortifications',type='TACAN_beacon',shape_name='none',heading=0,x=-2.329847,y=-16.579903,},
|
||||||
|
-- [11]={category='Fortifications',type='FARP Fuel Depot',shape_name='GSM Rus',heading=0,x=2.222011,y=4.487030,},
|
||||||
|
-- [12]={category='Fortifications',type='APFC fuel',shape_name='M92_APFCfuel',heading=0,x=3.614927,y=0.367838,},
|
||||||
|
-- [13]={category='Fortifications',type='Camouflage03',shape_name='M92_Camouflage03',heading=0,x=21.544148,y=21.998879,},
|
||||||
|
-- [14]={category='Fortifications',type='Container_generator',shape_name='M92_Container_generator',heading=0,x=20.989192,y=37.314334,},
|
||||||
|
-- [15]={category='Fortifications',type='FireExtinguisher02',shape_name='M92_FireExtinguisher02',heading=0,x=3.988003,y=8.362333,},
|
||||||
|
-- [16]={category='Fortifications',type='FireExtinguisher02',shape_name='M92_FireExtinguisher02',heading=0,x=-3.953195,y=12.945844,},
|
||||||
|
-- [17]={category='Fortifications',type='Windsock',shape_name='H-Windsock_RW',heading=0,x=-18.944173,y=-33.042196,},
|
||||||
|
-- [18]={category='Fortifications',type='Tent04',shape_name='M92_Tent04',heading=0,x=21.220671,y=30.247529,},
|
||||||
|
-- }
|
||||||
|
--
|
||||||
|
function UTILS.SpawnMASHStatics(Name,Coordinate,Country,ADF,Livery,DeployHelo,MASHRadio,MASHRadioModulation,MASHCallsign,Templates)
|
||||||
|
|
||||||
|
-- Basic objects table
|
||||||
|
|
||||||
|
local MASHTemplates = {
|
||||||
|
[1]={category='Infantry',type='Soldier M4',shape_name='none',heading=0,x=0.000000,y=0.000000,},
|
||||||
|
[2]={category='Infantry',type='Soldier M4',shape_name='none',heading=0,x=0.313533,y=8.778935,},
|
||||||
|
[3]={category='Infantry',type='Soldier M4',shape_name='none',heading=0,x=16.303737,y=20.379671,},
|
||||||
|
[4]={category='Helicopters',type='CH-47Fbl1',shape_name='none',heading=0,x=-20.047735,y=-63.166179,livery_id = "us army dark green",},
|
||||||
|
[5]={category='Infantry',type='Soldier M4',shape_name='none',heading=0,x=26.650339,y=20.066138,},
|
||||||
|
[6]={category='Heliports',type='FARP_SINGLE_01',shape_name='FARP_SINGLE_01',heading=0,x=-25.432292,y=9.077099,},
|
||||||
|
[7]={category='Heliports',type='FARP_SINGLE_01',shape_name='FARP_SINGLE_01',heading=0,x=-12.717421,y=-3.216114,},
|
||||||
|
[8]={category='Heliports',type='FARP_SINGLE_01',shape_name='FARP_SINGLE_01',heading=0,x=-25.439281,y=-3.216114,},
|
||||||
|
[9]={category='Heliports',type='FARP_SINGLE_01',shape_name='FARP_SINGLE_01',heading=0,x=-12.717421,y=9.155603,},
|
||||||
|
[10]={category='Fortifications',type='TACAN_beacon',shape_name='none',heading=0,x=-2.329847,y=-16.579903,},
|
||||||
|
[11]={category='Fortifications',type='FARP Fuel Depot',shape_name='GSM Rus',heading=0,x=2.222011,y=4.487030,},
|
||||||
|
[12]={category='Fortifications',type='APFC fuel',shape_name='M92_APFCfuel',heading=0,x=3.614927,y=0.367838,},
|
||||||
|
[13]={category='Fortifications',type='Camouflage03',shape_name='M92_Camouflage03',heading=0,x=21.544148,y=21.998879,},
|
||||||
|
[14]={category='Fortifications',type='Container_generator',shape_name='M92_Container_generator',heading=0,x=20.989192,y=37.314334,},
|
||||||
|
[15]={category='Fortifications',type='FireExtinguisher02',shape_name='M92_FireExtinguisher02',heading=0,x=3.988003,y=8.362333,},
|
||||||
|
[16]={category='Fortifications',type='FireExtinguisher02',shape_name='M92_FireExtinguisher02',heading=0,x=-3.953195,y=12.945844,},
|
||||||
|
[17]={category='Fortifications',type='Windsock',shape_name='H-Windsock_RW',heading=0,x=-18.944173,y=-33.042196,},
|
||||||
|
[18]={category='Fortifications',type='Tent04',shape_name='M92_Tent04',heading=0,x=21.220671,y=30.247529,},
|
||||||
|
}
|
||||||
|
|
||||||
|
if Templates then MASHTemplates=Templates end
|
||||||
|
|
||||||
|
-- locals
|
||||||
|
local name = Name or "Florence Nightingale"
|
||||||
|
local positionVec2
|
||||||
|
local positionVec3
|
||||||
|
local ReturnStatics = {}
|
||||||
|
local CountryID = Country or country.id.USA
|
||||||
|
local livery = "us army dark green"
|
||||||
|
local MASHRadio = MASHRadio or 127.5
|
||||||
|
local MASHRadioModulation = MASHRadioModulation or radio.modulation.AM
|
||||||
|
local MASHCallsign = MASHCallsign or CALLSIGN.FARP.Berlin
|
||||||
|
|
||||||
|
-- check for coordinate or zone
|
||||||
|
if type(Coordinate) == "table" then
|
||||||
|
if Coordinate:IsInstanceOf("COORDINATE") or Coordinate:IsInstanceOf("ZONE_BASE") then
|
||||||
|
positionVec2 = Coordinate:GetVec2()
|
||||||
|
positionVec3 = Coordinate:GetVec3()
|
||||||
|
end
|
||||||
|
else
|
||||||
|
BASE:E("Spawn MASH - no ZONE or COORDINATE handed!")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- position
|
||||||
|
local BaseX = positionVec2.x
|
||||||
|
local BaseY = positionVec2.y
|
||||||
|
|
||||||
|
-- Statics
|
||||||
|
for id,object in pairs(MASHTemplates) do
|
||||||
|
local NewName = string.format("%s#%3d",name,id)
|
||||||
|
local vec2 = {x=BaseX+object.x,y=BaseY+object.y}
|
||||||
|
local Coordinate=COORDINATE:NewFromVec2(vec2)
|
||||||
|
local static = SPAWNSTATIC:NewFromType(object.type,object.category,CountryID)
|
||||||
|
if object.shape_name and object.shape_name ~= "none" then
|
||||||
|
static:InitShape(object.shape_name)
|
||||||
|
end
|
||||||
|
if object.category == "Helicopters" and DeployHelo == true then
|
||||||
|
if object.livery_id ~= nil then
|
||||||
|
livery = object.livery_id
|
||||||
|
end
|
||||||
|
static:InitLivery(livery)
|
||||||
|
local newstatic = static:SpawnFromCoordinate(Coordinate,object.heading,NewName)
|
||||||
|
table.insert(ReturnStatics,newstatic)
|
||||||
|
elseif object.category == "Heliports" then
|
||||||
|
static:InitFARP(MASHCallsign,MASHRadio,MASHRadioModulation,false,false)
|
||||||
|
local newstatic = static:SpawnFromCoordinate(Coordinate,object.heading,NewName)
|
||||||
|
table.insert(ReturnStatics,newstatic)
|
||||||
|
elseif object.category ~= "Helicopters" and object.category ~= "Heliports" then
|
||||||
|
local newstatic = static:SpawnFromCoordinate(Coordinate,object.heading,NewName)
|
||||||
|
table.insert(ReturnStatics,newstatic)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Beacon
|
||||||
|
local ADFName
|
||||||
|
if ADF and type(ADF) == "number" then
|
||||||
|
local ADFFreq = ADF*1000 -- KHz to Hz
|
||||||
|
local Sound = "l10n/DEFAULT/beacon.ogg"
|
||||||
|
ADFName = Name .. " ADF "..tostring(ADF).."KHz"
|
||||||
|
--BASE:I(string.format("Adding MASH Beacon %d KHz Name %s",ADF,ADFName))
|
||||||
|
trigger.action.radioTransmission(Sound, positionVec3, 0, true, ADFFreq, 250, ADFName)
|
||||||
|
end
|
||||||
|
|
||||||
|
return ReturnStatics, ADFName
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Converts a Vec2 to a Vec3.
|
--- Converts a Vec2 to a Vec3.
|
||||||
@@ -4413,3 +4583,291 @@ end
|
|||||||
function UTILS.Weather.StopFogAnimation()
|
function UTILS.Weather.StopFogAnimation()
|
||||||
return world.weather.setFogAnimation({})
|
return world.weather.setFogAnimation({})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Find a ME created zone by its name
|
||||||
|
function UTILS.GetEnvZone(name)
|
||||||
|
for _,v in ipairs(env.mission.triggers.zones) do
|
||||||
|
if v.name == name then
|
||||||
|
return v
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- net.dostring_in
|
||||||
|
function UTILS.DoStringIn(State,DoString)
|
||||||
|
return net.dostring_in(State,DoString)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Show a picture on the screen to all
|
||||||
|
-- @param #string FileName File name of the picture
|
||||||
|
-- @param #number Duration Duration in seconds, defaults to 10
|
||||||
|
-- @param #boolean ClearView If true, clears the view before showing the picture, defaults to false
|
||||||
|
-- @param #number StartDelay Delay in seconds before showing the picture, defaults to 0
|
||||||
|
-- @param #number HorizontalAlign Horizontal alignment of the picture, 0: Left, 1: Center, 2: Right
|
||||||
|
-- @param #number VerticalAlign Vertical alignment of the picture, 0: Top, 1: Center, 2: Bottom
|
||||||
|
-- @param #number Size Size of the picture in percent, defaults to 100
|
||||||
|
-- @param #number SizeUnits Size units, 0 for % of original picture size, and 1 for % of window size
|
||||||
|
function UTILS.ShowPictureToAll(FilePath, Duration, ClearView, StartDelay, HorizontalAlign, VerticalAlign, Size, SizeUnits)
|
||||||
|
ClearView = ClearView or false
|
||||||
|
StartDelay = StartDelay or 0
|
||||||
|
HorizontalAlign = HorizontalAlign or 1
|
||||||
|
VerticalAlign = VerticalAlign or 1
|
||||||
|
Size = Size or 100
|
||||||
|
SizeUnits = SizeUnits or 0
|
||||||
|
|
||||||
|
if ClearView then ClearView = "true" else ClearView = "false" end
|
||||||
|
|
||||||
|
net.dostring_in("mission", string.format("a_out_picture(\"%s\", %d, %s, %d, \"%d\", \"%d\", %d, \"%d\")", FilePath, Duration or 10, ClearView, StartDelay, HorizontalAlign, VerticalAlign, Size, SizeUnits))
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Show a picture on the screen to Coalition
|
||||||
|
-- @param #number Coalition Coalition ID, can be coalition.side.BLUE, coalition.side.RED or coalition.side.NEUTRAL
|
||||||
|
-- @param #string FileName File name of the picture
|
||||||
|
-- @param #number Duration Duration in seconds, defaults to 10
|
||||||
|
-- @param #boolean ClearView If true, clears the view before showing the picture, defaults to false
|
||||||
|
-- @param #number StartDelay Delay in seconds before showing the picture, defaults to 0
|
||||||
|
-- @param #number HorizontalAlign Horizontal alignment of the picture, 0: Left, 1: Center, 2: Right
|
||||||
|
-- @param #number VerticalAlign Vertical alignment of the picture, 0: Top, 1: Center, 2: Bottom
|
||||||
|
-- @param #number Size Size of the picture in percent, defaults to 100
|
||||||
|
-- @param #number SizeUnits Size units, 0 for % of original picture size, and 1 for % of window size
|
||||||
|
function UTILS.ShowPictureToCoalition(Coalition, FilePath, Duration, ClearView, StartDelay, HorizontalAlign, VerticalAlign, Size, SizeUnits)
|
||||||
|
ClearView = ClearView or false
|
||||||
|
StartDelay = StartDelay or 0
|
||||||
|
HorizontalAlign = HorizontalAlign or 1
|
||||||
|
VerticalAlign = VerticalAlign or 1
|
||||||
|
Size = Size or 100
|
||||||
|
SizeUnits = SizeUnits or 0
|
||||||
|
|
||||||
|
if ClearView then ClearView = "true" else ClearView = "false" end
|
||||||
|
|
||||||
|
local coalName = string.lower(UTILS.GetCoalitionName(Coalition))
|
||||||
|
|
||||||
|
net.dostring_in("mission", string.format("a_out_picture_s(\"%s\", \"%s\", %d, %s, %d, \"%d\", \"%d\", %d, \"%d\")", coalName, FilePath, Duration or 10, ClearView, StartDelay, HorizontalAlign, VerticalAlign, Size, SizeUnits))
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Show a picture on the screen to Country
|
||||||
|
-- @param #number Country Country ID, can be country.id.USA, country.id.RUSSIA, etc.
|
||||||
|
-- @param #string FileName File name of the picture
|
||||||
|
-- @param #number Duration Duration in seconds, defaults to 10
|
||||||
|
-- @param #boolean ClearView If true, clears the view before showing the picture, defaults to false
|
||||||
|
-- @param #number StartDelay Delay in seconds before showing the picture, defaults to 0
|
||||||
|
-- @param #number HorizontalAlign Horizontal alignment of the picture, 0: Left, 1: Center, 2: Right
|
||||||
|
-- @param #number VerticalAlign Vertical alignment of the picture, 0: Top, 1: Center, 2: Bottom
|
||||||
|
-- @param #number Size Size of the picture in percent, defaults to 100
|
||||||
|
-- @param #number SizeUnits Size units, 0 for % of original picture size, and 1 for % of window size
|
||||||
|
function UTILS.ShowPictureToCountry(Country, FilePath, Duration, ClearView, StartDelay, HorizontalAlign, VerticalAlign, Size, SizeUnits)
|
||||||
|
ClearView = ClearView or false
|
||||||
|
StartDelay = StartDelay or 0
|
||||||
|
HorizontalAlign = HorizontalAlign or 1
|
||||||
|
VerticalAlign = VerticalAlign or 1
|
||||||
|
Size = Size or 100
|
||||||
|
SizeUnits = SizeUnits or 0
|
||||||
|
|
||||||
|
if ClearView then ClearView = "true" else ClearView = "false" end
|
||||||
|
|
||||||
|
net.dostring_in("mission", string.format("a_out_picture_c(%d, \"%s\", %d, %s, %d, \"%d\", \"%d\", %d, \"%d\")", Country, FilePath, Duration or 10, ClearView, StartDelay, HorizontalAlign, VerticalAlign, Size, SizeUnits))
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Show a picture on the screen to Group
|
||||||
|
-- @param Wrapper.Group#GROUP Group Group to show the picture to
|
||||||
|
-- @param #string FileName File name of the picture
|
||||||
|
-- @param #number Duration Duration in seconds, defaults to 10
|
||||||
|
-- @param #boolean ClearView If true, clears the view before showing the picture, defaults to false
|
||||||
|
-- @param #number StartDelay Delay in seconds before showing the picture, defaults to 0
|
||||||
|
-- @param #number HorizontalAlign Horizontal alignment of the picture, 0: Left, 1: Center, 2: Right
|
||||||
|
-- @param #number VerticalAlign Vertical alignment of the picture, 0: Top, 1: Center, 2: Bottom
|
||||||
|
-- @param #number Size Size of the picture in percent, defaults to 100
|
||||||
|
-- @param #number SizeUnits Size units, 0 for % of original picture size, and 1 for % of window size
|
||||||
|
function UTILS.ShowPictureToGroup(Group, FilePath, Duration, ClearView, StartDelay, HorizontalAlign, VerticalAlign, Size, SizeUnits)
|
||||||
|
ClearView = ClearView or false
|
||||||
|
StartDelay = StartDelay or 0
|
||||||
|
HorizontalAlign = HorizontalAlign or 1
|
||||||
|
VerticalAlign = VerticalAlign or 1
|
||||||
|
Size = Size or 100
|
||||||
|
SizeUnits = SizeUnits or 0
|
||||||
|
|
||||||
|
if ClearView then ClearView = "true" else ClearView = "false" end
|
||||||
|
|
||||||
|
net.dostring_in("mission", string.format("a_out_picture_g(%d, \"%s\", %d, %s, %d, \"%d\", \"%d\", %d, \"%d\")", Group:GetID(), FilePath, Duration or 10, ClearView, StartDelay, HorizontalAlign, VerticalAlign, Size, SizeUnits))
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Show a picture on the screen to Unit
|
||||||
|
-- @param Wrapper.Unit#UNIT Unit Unit to show the picture to
|
||||||
|
-- @param #string FileName File name of the picture
|
||||||
|
-- @param #number Duration Duration in seconds, defaults to 10
|
||||||
|
-- @param #boolean ClearView If true, clears the view before showing the picture, defaults to false
|
||||||
|
-- @param #number StartDelay Delay in seconds before showing the picture, defaults to 0
|
||||||
|
-- @param #number HorizontalAlign Horizontal alignment of the picture, 0: Left, 1: Center, 2: Right
|
||||||
|
-- @param #number VerticalAlign Vertical alignment of the picture, 0: Top, 1: Center, 2: Bottom
|
||||||
|
-- @param #number Size Size of the picture in percent, defaults to 100
|
||||||
|
-- @param #number SizeUnits Size units, 0 for % of original picture size, and 1 for % of window size
|
||||||
|
function UTILS.ShowPictureToUnit(Unit, FilePath, Duration, ClearView, StartDelay, HorizontalAlign, VerticalAlign, Size, SizeUnits)
|
||||||
|
ClearView = ClearView or false
|
||||||
|
StartDelay = StartDelay or 0
|
||||||
|
HorizontalAlign = HorizontalAlign or 1
|
||||||
|
VerticalAlign = VerticalAlign or 1
|
||||||
|
Size = Size or 100
|
||||||
|
SizeUnits = SizeUnits or 0
|
||||||
|
|
||||||
|
if ClearView then ClearView = "true" else ClearView = "false" end
|
||||||
|
|
||||||
|
net.dostring_in("mission", string.format("a_out_picture_u(%d, \"%s\", %d, %s, %d, \"%d\", \"%d\", %d, \"%d\")", Unit:GetID(), FilePath, Duration or 10, ClearView, StartDelay, HorizontalAlign, VerticalAlign, Size, SizeUnits))
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Load a mission file. This will replace the current mission with the one given carrying along the online clients.
|
||||||
|
-- @param #string FileName Mission filename
|
||||||
|
function UTILS.LoadMission(FileName)
|
||||||
|
net.dostring_in("mission", string.format("a_load_mission(\"%s\")", FileName))
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set the mission briefing for a coalition.
|
||||||
|
-- @param #number Coalition Briefing coalition ID, can be coalition.side.BLUE, coalition.side.RED or coalition.side.NEUTRAL
|
||||||
|
-- @param #string Text Briefing text, can contain newlines, will be converted formatted properly for DCS
|
||||||
|
-- @param #string Picture Picture file path, can be a file in the DEFAULT folder inside the .miz
|
||||||
|
function UTILS.SetMissionBriefing(Coalition, Text, Picture)
|
||||||
|
Text = Text or ""
|
||||||
|
Text = Text:gsub("\n", "\\n")
|
||||||
|
Picture = Picture or ""
|
||||||
|
local coalName = string.lower(UTILS.GetCoalitionName(Coalition))
|
||||||
|
net.dostring_in("mission", string.format("a_set_briefing(\"%s\", \"%s\", \"%s\")", coalName, Picture, Text))
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Show a helper gate at a DCS#Vec3 position
|
||||||
|
-- @param DCS#Vec3 pos The position
|
||||||
|
-- @param #number heading Heading in degrees, can be 0..359 degrees
|
||||||
|
function UTILS.ShowHelperGate(pos, heading)
|
||||||
|
net.dostring_in("mission",string.format("a_show_helper_gate(%s, %s, %s, %f)", pos.x, pos.y, pos.z, math.rad(heading)))
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Show a helper gate for a unit.
|
||||||
|
-- @param Wrapper.Unit#UNIT Unit The unit to show the gate for
|
||||||
|
-- @param #number Flag Helper gate flag
|
||||||
|
function UTILS.ShowHelperGateForUnit(Unit, Flag)
|
||||||
|
net.dostring_in("mission",string.format("a_show_route_gates_for_unit(%d, \"%d\")", Unit:GetID(), Flag))
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set the carrier illumination mode. -2: OFF, -1: AUTO, 0: NAVIGATION, 1: AC LAUNCH, 2: AC RECOVERY
|
||||||
|
-- @param #number UnitID Carrier unit ID ( UNIT:GetID() )
|
||||||
|
-- @param #number Mode Illumination mode, can be -2: OFF, -1: AUTO, 0: NAVIGATION, 1: AC LAUNCH, 2: AC RECOVERY
|
||||||
|
function UTILS.SetCarrierIlluminationMode(UnitID, Mode)
|
||||||
|
net.dostring_in("mission",string.format("a_set_carrier_illumination_mode(%d, %d)", UnitID, Mode))
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Shell a zone, zone must ME created
|
||||||
|
-- @param #string name The name of the ME created zone
|
||||||
|
-- @param #number power Equals kg of TNT, e.g. 75
|
||||||
|
-- @param #count Number of shells simulated
|
||||||
|
function UTILS.ShellZone(name, power, count)
|
||||||
|
local z = UTILS.GetEnvZone(name)
|
||||||
|
if z then
|
||||||
|
net.dostring_in("mission",string.format("a_shelling_zone(%d, %d, %d)", z.zoneId, power, count))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Remove objects from a zone, zone must ME created
|
||||||
|
-- @param #string name The name of the ME created zone
|
||||||
|
-- @param #number type Type of objects to remove can be 0:all, 1: trees, 2:objects
|
||||||
|
function UTILS.RemoveObjects(name, type)
|
||||||
|
local z = UTILS.GetEnvZone(name)
|
||||||
|
if z then
|
||||||
|
net.dostring_in("mission",string.format("a_remove_scene_objects(%d, %d)", z.zoneId, type))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Remove scenery objects from a zone, zone must ME created
|
||||||
|
-- @param #string name The name of the ME created zone
|
||||||
|
-- @param #number level Level of removal
|
||||||
|
function UTILS.DestroyScenery(name, level)
|
||||||
|
local z = UTILS.GetEnvZone(name)
|
||||||
|
if z then
|
||||||
|
net.dostring_in("mission",string.format("a_scenery_destruction_zone(%d, %d)", z.zoneId, level))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Search for clear zones in a given area. A powerful and efficient function using Disposition to find clear areas for spawning ground units avoiding trees, water and map scenery.
|
||||||
|
-- @param DCS##Vec3 Center position vector for the search area.
|
||||||
|
-- @param #number SearchRadius Radius of the search area.
|
||||||
|
-- @param #number PosRadius Required clear radius around each position.
|
||||||
|
-- @param #number NumPositions Number of positions to find.
|
||||||
|
-- @return #table A table of DCS#Vec2 positions that are clear of map objects within the given PosRadius.
|
||||||
|
function UTILS.GetSimpleZones(Vec3, SearchRadius, PosRadius, NumPositions)
|
||||||
|
return Disposition.getSimpleZones(Vec3, SearchRadius, PosRadius, NumPositions)
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Search for clear ground spawn zones within this zone. A powerful and efficient function using Disposition to find clear areas for spawning ground units avoiding trees, water and map scenery.
|
||||||
|
-- @param Core.Zone#ZONE Zone to search.
|
||||||
|
-- @param #number (Optional) PosRadius Required clear radius around each position. (Default is math.min(Radius/10, 200))
|
||||||
|
-- @param #number (Optional) NumPositions Number of positions to find. (Default 50)
|
||||||
|
-- @return #table A table of DCS#Vec2 positions that are clear of map objects within the given PosRadius. nil if no clear positions are found.
|
||||||
|
function UTILS.GetClearZonePositions(Zone, PosRadius, NumPositions)
|
||||||
|
local radius = PosRadius or math.min(Zone:GetRadius()/10, 200)
|
||||||
|
local clearPositions = UTILS.GetSimpleZones(Zone:GetVec3(), Zone:GetRadius(), radius, NumPositions or 50)
|
||||||
|
if clearPositions and #clearPositions > 0 then
|
||||||
|
local validZones = {}
|
||||||
|
for _, vec2 in pairs(clearPositions) do
|
||||||
|
if Zone:IsVec2InZone(vec2) then
|
||||||
|
table.insert(validZones, vec2)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if #validZones > 0 then
|
||||||
|
return validZones, radius
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Search for a random clear ground spawn coordinate within this zone. A powerful and efficient function using Disposition to find clear areas for spawning ground units avoiding trees, water and map scenery.
|
||||||
|
-- @param Core.Zone#ZONE Zone to search.
|
||||||
|
-- @param #number PosRadius (Optional) Required clear radius around each position. (Default is math.min(Radius/10, 200))
|
||||||
|
-- @param #number NumPositions (Optional) Number of positions to find. (Default 50)
|
||||||
|
-- @return Core.Point#COORDINATE A random coordinate for a clear zone. nil if no clear positions are found.
|
||||||
|
-- @return #number Assigned radius for the found zones. nil if no clear positions are found.
|
||||||
|
function UTILS.GetRandomClearZoneCoordinate(Zone, PosRadius, NumPositions)
|
||||||
|
local clearPositions = UTILS.GetClearZonePositions(Zone, PosRadius, NumPositions)
|
||||||
|
if clearPositions and #clearPositions > 0 then
|
||||||
|
local randomPosition, radius = clearPositions[math.random(1, #clearPositions)]
|
||||||
|
return COORDINATE:NewFromVec2(randomPosition), radius
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Find the point on the radius of a circle closest to a point outside of the radius.
|
||||||
|
-- @param DCS#Vec2 Vec1 Simple Vec2 marking the middle of the circle.
|
||||||
|
-- @param #number Radius The radius of the circle.
|
||||||
|
-- @param DCS#Vec2 Vec2 Simple Vec2 marking the point outside of the circle.
|
||||||
|
-- @return DCS#Vec2 Vec2 point on the radius.
|
||||||
|
function UTILS.FindNearestPointOnCircle(Vec1,Radius,Vec2)
|
||||||
|
local r = Radius
|
||||||
|
local cx = Vec1.x or 1
|
||||||
|
local cy = Vec1.y or 1
|
||||||
|
local px = Vec2.x or 1
|
||||||
|
local py = Vec2.y or 1
|
||||||
|
|
||||||
|
-- Berechne den Vektor vom Mittelpunkt zum externen Punkt
|
||||||
|
local dx = px - cx
|
||||||
|
local dy = py - cy
|
||||||
|
|
||||||
|
-- Berechne die Länge des Vektors
|
||||||
|
local dist = math.sqrt(dx * dx + dy * dy)
|
||||||
|
|
||||||
|
-- Wenn der Punkt im Mittelpunkt liegt, wähle einen Punkt auf der X-Achse
|
||||||
|
if dist == 0 then
|
||||||
|
return {x=cx + r, y=cy}
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Normalisiere den Vektor (richtungsweise Vektor mit Länge 1)
|
||||||
|
local norm_dx = dx / dist
|
||||||
|
local norm_dy = dy / dist
|
||||||
|
|
||||||
|
-- Berechne den Punkt auf dem Rand des Kreises
|
||||||
|
local qx = cx + r * norm_dx
|
||||||
|
local qy = cy + r * norm_dy
|
||||||
|
|
||||||
|
local shift_factor = 1
|
||||||
|
qx = qx + shift_factor * norm_dx
|
||||||
|
qy = qy + shift_factor * norm_dy
|
||||||
|
|
||||||
|
return {x=qx, y=qy}
|
||||||
|
end
|
||||||
|
|||||||
@@ -449,7 +449,6 @@ AIRBASE.TheChannel = {
|
|||||||
-- * AIRBASE.Syria.Al_Dumayr
|
-- * AIRBASE.Syria.Al_Dumayr
|
||||||
-- * AIRBASE.Syria.Al_Qusayr
|
-- * AIRBASE.Syria.Al_Qusayr
|
||||||
-- * AIRBASE.Syria.Aleppo
|
-- * AIRBASE.Syria.Aleppo
|
||||||
-- * AIRBASE.Syria.Amman
|
|
||||||
-- * AIRBASE.Syria.An_Nasiriyah
|
-- * AIRBASE.Syria.An_Nasiriyah
|
||||||
-- * AIRBASE.Syria.At_Tanf
|
-- * AIRBASE.Syria.At_Tanf
|
||||||
-- * AIRBASE.Syria.Bassel_Al_Assad
|
-- * AIRBASE.Syria.Bassel_Al_Assad
|
||||||
@@ -511,8 +510,9 @@ AIRBASE.TheChannel = {
|
|||||||
-- * AIRBASE.Syria.Wujah_Al_Hajar
|
-- * AIRBASE.Syria.Wujah_Al_Hajar
|
||||||
-- * AIRBASE.Syria.Ben_Gurion
|
-- * AIRBASE.Syria.Ben_Gurion
|
||||||
-- * AIRBASE.Syria.Hatzor
|
-- * AIRBASE.Syria.Hatzor
|
||||||
-- * AIRBASE.Syria.Palmashim
|
-- * AIRBASE.Syria.Palmachim
|
||||||
-- * AIRBASE.Syria.Tel_Nof
|
-- * AIRBASE.Syria.Tel_Nof
|
||||||
|
-- * AIRBASE.Syria.Marka
|
||||||
--
|
--
|
||||||
--@field Syria
|
--@field Syria
|
||||||
AIRBASE.Syria={
|
AIRBASE.Syria={
|
||||||
@@ -522,7 +522,6 @@ AIRBASE.Syria={
|
|||||||
["Al_Dumayr"] = "Al-Dumayr",
|
["Al_Dumayr"] = "Al-Dumayr",
|
||||||
["Al_Qusayr"] = "Al Qusayr",
|
["Al_Qusayr"] = "Al Qusayr",
|
||||||
["Aleppo"] = "Aleppo",
|
["Aleppo"] = "Aleppo",
|
||||||
["Amman"] = "Amman",
|
|
||||||
["An_Nasiriyah"] = "An Nasiriyah",
|
["An_Nasiriyah"] = "An Nasiriyah",
|
||||||
["At_Tanf"] = "At Tanf",
|
["At_Tanf"] = "At Tanf",
|
||||||
["Bassel_Al_Assad"] = "Bassel Al-Assad",
|
["Bassel_Al_Assad"] = "Bassel Al-Assad",
|
||||||
@@ -554,6 +553,7 @@ AIRBASE.Syria={
|
|||||||
["Kuweires"] = "Kuweires",
|
["Kuweires"] = "Kuweires",
|
||||||
["Lakatamia"] = "Lakatamia",
|
["Lakatamia"] = "Lakatamia",
|
||||||
["Larnaca"] = "Larnaca",
|
["Larnaca"] = "Larnaca",
|
||||||
|
["Marka"] = "Marka",
|
||||||
["Marj_Ruhayyil"] = "Marj Ruhayyil",
|
["Marj_Ruhayyil"] = "Marj Ruhayyil",
|
||||||
["Marj_as_Sultan_North"] = "Marj as Sultan North",
|
["Marj_as_Sultan_North"] = "Marj as Sultan North",
|
||||||
["Marj_as_Sultan_South"] = "Marj as Sultan South",
|
["Marj_as_Sultan_South"] = "Marj as Sultan South",
|
||||||
@@ -584,7 +584,7 @@ AIRBASE.Syria={
|
|||||||
["Wujah_Al_Hajar"] = "Wujah Al Hajar",
|
["Wujah_Al_Hajar"] = "Wujah Al Hajar",
|
||||||
["Ben_Gurion"] = "Ben Gurion",
|
["Ben_Gurion"] = "Ben Gurion",
|
||||||
["Hatzor"] = "Hatzor",
|
["Hatzor"] = "Hatzor",
|
||||||
["Palmashim"] = "Palmashim",
|
["Palmachim"] = "Palmachim",
|
||||||
["Tel_Nof"] = "Tel Nof",
|
["Tel_Nof"] = "Tel Nof",
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -611,6 +611,35 @@ AIRBASE.MarianaIslands = {
|
|||||||
["Tinian_Intl"] = "Tinian Intl",
|
["Tinian_Intl"] = "Tinian Intl",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
--- Airbase of the Marianas WWII map
|
||||||
|
--
|
||||||
|
-- * AIRBASE.MarianaIslandsWWII.Agana
|
||||||
|
-- * AIRBASE.MarianaIslandsWWII.Airfield_3
|
||||||
|
-- * AIRBASE.MarianaIslandsWWII.Charon_Kanoa
|
||||||
|
-- * AIRBASE.MarianaIslandsWWII.Gurguan_Point
|
||||||
|
-- * AIRBASE.MarianaIslandsWWII.Isley
|
||||||
|
-- * AIRBASE.MarianaIslandsWWII.Kagman
|
||||||
|
-- * AIRBASE.MarianaIslandsWWII.Marpi
|
||||||
|
-- * AIRBASE.MarianaIslandsWWII.Orote
|
||||||
|
-- * AIRBASE.MarianaIslandsWWII.Pagan
|
||||||
|
-- * AIRBASE.MarianaIslandsWWII.Rota
|
||||||
|
-- * AIRBASE.MarianaIslandsWWII.Ushi
|
||||||
|
-- @field AIRBASE.MarianaIslandsWWII
|
||||||
|
AIRBASE.MarianaIslandsWWII =
|
||||||
|
{
|
||||||
|
["Agana"] = "Agana",
|
||||||
|
["Airfield_3"] = "Airfield 3",
|
||||||
|
["Charon_Kanoa"] = "Charon Kanoa",
|
||||||
|
["Gurguan_Point"] = "Gurguan Point",
|
||||||
|
["Isley"] = "Isley",
|
||||||
|
["Kagman"] = "Kagman",
|
||||||
|
["Marpi"] = "Marpi",
|
||||||
|
["Orote"] = "Orote",
|
||||||
|
["Pagan"] = "Pagan",
|
||||||
|
["Rota"] = "Rota",
|
||||||
|
["Ushi"] = "Ushi",
|
||||||
|
}
|
||||||
|
|
||||||
--- Airbases of the South Atlantic map:
|
--- Airbases of the South Atlantic map:
|
||||||
--
|
--
|
||||||
-- * AIRBASE.SouthAtlantic.Almirante_Schroeders
|
-- * AIRBASE.SouthAtlantic.Almirante_Schroeders
|
||||||
@@ -689,7 +718,7 @@ AIRBASE.SouthAtlantic={
|
|||||||
-- * AIRBASE.Sinai.Bilbeis_Air_Base
|
-- * AIRBASE.Sinai.Bilbeis_Air_Base
|
||||||
-- * AIRBASE.Sinai.Bir_Hasanah
|
-- * AIRBASE.Sinai.Bir_Hasanah
|
||||||
-- * AIRBASE.Sinai.Birma_Air_Base
|
-- * AIRBASE.Sinai.Birma_Air_Base
|
||||||
-- * AIRBASE.Sinai.Borj_El_Arab_International_Airport
|
-- * AIRBASE.Sinai.Borg_El_Arab_International_Airport
|
||||||
-- * AIRBASE.Sinai.Cairo_International_Airport
|
-- * AIRBASE.Sinai.Cairo_International_Airport
|
||||||
-- * AIRBASE.Sinai.Cairo_West
|
-- * AIRBASE.Sinai.Cairo_West
|
||||||
-- * AIRBASE.Sinai.Difarsuwar_Airfield
|
-- * AIRBASE.Sinai.Difarsuwar_Airfield
|
||||||
@@ -707,15 +736,19 @@ AIRBASE.SouthAtlantic={
|
|||||||
-- * AIRBASE.Sinai.Kibrit_Air_Base
|
-- * AIRBASE.Sinai.Kibrit_Air_Base
|
||||||
-- * AIRBASE.Sinai.Kom_Awshim
|
-- * AIRBASE.Sinai.Kom_Awshim
|
||||||
-- * AIRBASE.Sinai.Melez
|
-- * AIRBASE.Sinai.Melez
|
||||||
|
-- * AIRBASE.Sinai.Mezzeh_Air_Base
|
||||||
-- * AIRBASE.Sinai.Nevatim
|
-- * AIRBASE.Sinai.Nevatim
|
||||||
-- * AIRBASE.Sinai.Ovda
|
-- * AIRBASE.Sinai.Ovda
|
||||||
-- * AIRBASE.Sinai.Palmachim
|
-- * AIRBASE.Sinai.Palmachim
|
||||||
-- * AIRBASE.Sinai.Quwaysina
|
-- * AIRBASE.Sinai.Quwaysina
|
||||||
|
-- * AIRBASE.Sinai.Rafic_Hariri_Intl
|
||||||
|
-- * AIRBASE.Sinai.Ramat_David
|
||||||
-- * AIRBASE.Sinai.Ramon_Airbase
|
-- * AIRBASE.Sinai.Ramon_Airbase
|
||||||
-- * AIRBASE.Sinai.Ramon_International_Airport
|
-- * AIRBASE.Sinai.Ramon_International_Airport
|
||||||
-- * AIRBASE.Sinai.Sde_Dov
|
-- * AIRBASE.Sinai.Sde_Dov
|
||||||
-- * AIRBASE.Sinai.Sharm_El_Sheikh_International_Airport
|
-- * AIRBASE.Sinai.Sharm_El_Sheikh_International_Airport
|
||||||
-- * AIRBASE.Sinai.St_Catherine
|
-- * AIRBASE.Sinai.St_Catherine
|
||||||
|
-- * AIRBASE.Sinai.Tabuk
|
||||||
-- * AIRBASE.Sinai.Tel_Nof
|
-- * AIRBASE.Sinai.Tel_Nof
|
||||||
-- * AIRBASE.Sinai.Wadi_Abu_Rish
|
-- * AIRBASE.Sinai.Wadi_Abu_Rish
|
||||||
-- * AIRBASE.Sinai.Wadi_al_Jandali
|
-- * AIRBASE.Sinai.Wadi_al_Jandali
|
||||||
@@ -737,7 +770,7 @@ AIRBASE.Sinai = {
|
|||||||
["Bilbeis_Air_Base"] = "Bilbeis Air Base",
|
["Bilbeis_Air_Base"] = "Bilbeis Air Base",
|
||||||
["Bir_Hasanah"] = "Bir Hasanah",
|
["Bir_Hasanah"] = "Bir Hasanah",
|
||||||
["Birma_Air_Base"] = "Birma Air Base",
|
["Birma_Air_Base"] = "Birma Air Base",
|
||||||
["Borj_El_Arab_International_Airport"] = "Borj El Arab International Airport",
|
["Borg_El_Arab_International_Airport"] = "Borg El Arab International Airport",
|
||||||
["Cairo_International_Airport"] = "Cairo International Airport",
|
["Cairo_International_Airport"] = "Cairo International Airport",
|
||||||
["Cairo_West"] = "Cairo West",
|
["Cairo_West"] = "Cairo West",
|
||||||
["Difarsuwar_Airfield"] = "Difarsuwar Airfield",
|
["Difarsuwar_Airfield"] = "Difarsuwar Airfield",
|
||||||
@@ -755,15 +788,19 @@ AIRBASE.Sinai = {
|
|||||||
["Kibrit_Air_Base"] = "Kibrit Air Base",
|
["Kibrit_Air_Base"] = "Kibrit Air Base",
|
||||||
["Kom_Awshim"] = "Kom Awshim",
|
["Kom_Awshim"] = "Kom Awshim",
|
||||||
["Melez"] = "Melez",
|
["Melez"] = "Melez",
|
||||||
|
["Mezzeh_Air_Base"] = "Mezzeh Air Base",
|
||||||
["Nevatim"] = "Nevatim",
|
["Nevatim"] = "Nevatim",
|
||||||
["Ovda"] = "Ovda",
|
["Ovda"] = "Ovda",
|
||||||
["Palmachim"] = "Palmachim",
|
["Palmachim"] = "Palmachim",
|
||||||
["Quwaysina"] = "Quwaysina",
|
["Quwaysina"] = "Quwaysina",
|
||||||
|
["Rafic_Hariri_Intl"] = "Rafic Hariri Intl",
|
||||||
|
["Ramat_David"] = "Ramat David",
|
||||||
["Ramon_Airbase"] = "Ramon Airbase",
|
["Ramon_Airbase"] = "Ramon Airbase",
|
||||||
["Ramon_International_Airport"] = "Ramon International Airport",
|
["Ramon_International_Airport"] = "Ramon International Airport",
|
||||||
["Sde_Dov"] = "Sde Dov",
|
["Sde_Dov"] = "Sde Dov",
|
||||||
["Sharm_El_Sheikh_International_Airport"] = "Sharm El Sheikh International Airport",
|
["Sharm_El_Sheikh_International_Airport"] = "Sharm El Sheikh International Airport",
|
||||||
["St_Catherine"] = "St Catherine",
|
["St_Catherine"] = "St Catherine",
|
||||||
|
["Tabuk"] = "Tabuk",
|
||||||
["Tel_Nof"] = "Tel Nof",
|
["Tel_Nof"] = "Tel Nof",
|
||||||
["Wadi_Abu_Rish"] = "Wadi Abu Rish",
|
["Wadi_Abu_Rish"] = "Wadi Abu Rish",
|
||||||
["Wadi_al_Jandali"] = "Wadi al Jandali",
|
["Wadi_al_Jandali"] = "Wadi al Jandali",
|
||||||
@@ -790,9 +827,14 @@ AIRBASE.Sinai = {
|
|||||||
-- * AIRBASE.Kola.Vidsel
|
-- * AIRBASE.Kola.Vidsel
|
||||||
-- * AIRBASE.Kola.Vuojarvi
|
-- * AIRBASE.Kola.Vuojarvi
|
||||||
-- * AIRBASE.Kola.Andoya
|
-- * AIRBASE.Kola.Andoya
|
||||||
-- * AIRBASE.Kola.Alakourtti
|
-- * AIRBASE.Kola.Alakurtti
|
||||||
-- * AIRBASE.Kola.Kittila
|
-- * AIRBASE.Kola.Kittila
|
||||||
-- * AIRBASE.Kola.Bardufoss
|
-- * AIRBASE.Kola.Bardufoss
|
||||||
|
-- * AIRBASE.Kola.Alta
|
||||||
|
-- * AIRBASE.Kola.Sodankyla
|
||||||
|
-- * AIRBASE.Kola.Enontekio
|
||||||
|
-- * AIRBASE.Kola.Evenes
|
||||||
|
-- * AIRBASE.Kola.Hosio
|
||||||
--
|
--
|
||||||
-- @field Kola
|
-- @field Kola
|
||||||
AIRBASE.Kola = {
|
AIRBASE.Kola = {
|
||||||
@@ -815,9 +857,20 @@ AIRBASE.Kola = {
|
|||||||
["Vidsel"] = "Vidsel",
|
["Vidsel"] = "Vidsel",
|
||||||
["Vuojarvi"] = "Vuojarvi",
|
["Vuojarvi"] = "Vuojarvi",
|
||||||
["Andoya"] = "Andoya",
|
["Andoya"] = "Andoya",
|
||||||
["Alakourtti"] = "Alakourtti",
|
["Alakurtti"] = "Alakurtti",
|
||||||
["Kittila"] = "Kittila",
|
["Kittila"] = "Kittila",
|
||||||
["Bardufoss"] = "Bardufoss",
|
["Bardufoss"] = "Bardufoss",
|
||||||
|
["Alta"] = "Alta",
|
||||||
|
["Sodankyla"] = "Sodankyla",
|
||||||
|
["Enontekio"] = "Enontekio",
|
||||||
|
["Evenes"] = "Evenes",
|
||||||
|
["Hosio"] = "Hosio",
|
||||||
|
["Kilpyavr"] = "Kilpyavr",
|
||||||
|
["Afrikanda"] = "Afrikanda",
|
||||||
|
["Kalevala"] = "Kalevala",
|
||||||
|
["Koshka_Yavr"] = "Koshka Yavr",
|
||||||
|
["Poduzhemye"] = "Poduzhemye",
|
||||||
|
["Luostari_Pechenga"] = "Luostari Pechenga",
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Airbases of the Afghanistan map
|
--- Airbases of the Afghanistan map
|
||||||
@@ -911,10 +964,10 @@ AIRBASE.Iraq = {
|
|||||||
|
|
||||||
--- Airbases of the Germany Cold War map
|
--- Airbases of the Germany Cold War map
|
||||||
-- * AIRBASE.GermanyCW.Airracing_Frankfurt
|
-- * AIRBASE.GermanyCW.Airracing_Frankfurt
|
||||||
|
-- * AIRBASE.GermanyCW.Airracing_Frankfurt
|
||||||
-- * AIRBASE.GermanyCW.Airracing_Koblenz
|
-- * AIRBASE.GermanyCW.Airracing_Koblenz
|
||||||
-- * AIRBASE.GermanyCW.Airracing_Luebeck
|
-- * AIRBASE.GermanyCW.Airracing_Luebeck
|
||||||
-- * AIRBASE.GermanyCW.Allstedt
|
-- * AIRBASE.GermanyCW.Allstedt
|
||||||
-- * AIRBASE.GermanyCW.Alt_Daber
|
|
||||||
-- * AIRBASE.GermanyCW.Altes_Lager
|
-- * AIRBASE.GermanyCW.Altes_Lager
|
||||||
-- * AIRBASE.GermanyCW.Bad_Duerkheim
|
-- * AIRBASE.GermanyCW.Bad_Duerkheim
|
||||||
-- * AIRBASE.GermanyCW.Barth
|
-- * AIRBASE.GermanyCW.Barth
|
||||||
@@ -937,14 +990,13 @@ AIRBASE.Iraq = {
|
|||||||
-- * AIRBASE.GermanyCW.Fritzlar
|
-- * AIRBASE.GermanyCW.Fritzlar
|
||||||
-- * AIRBASE.GermanyCW.Fulda
|
-- * AIRBASE.GermanyCW.Fulda
|
||||||
-- * AIRBASE.GermanyCW.Gardelegen
|
-- * AIRBASE.GermanyCW.Gardelegen
|
||||||
|
-- * AIRBASE.GermanyCW.Garz
|
||||||
-- * AIRBASE.GermanyCW.Gatow
|
-- * AIRBASE.GermanyCW.Gatow
|
||||||
-- * AIRBASE.GermanyCW.Gelnhausen
|
-- * AIRBASE.GermanyCW.Gelnhausen
|
||||||
-- * AIRBASE.GermanyCW.Giebelstadt
|
-- * AIRBASE.GermanyCW.Giebelstadt
|
||||||
-- * AIRBASE.GermanyCW.Glindbruchkippe
|
-- * AIRBASE.GermanyCW.Glindbruchkippe
|
||||||
-- * AIRBASE.GermanyCW.Gross_Doelln
|
|
||||||
-- * AIRBASE.GermanyCW.Gross_Mohrdorf
|
-- * AIRBASE.GermanyCW.Gross_Mohrdorf
|
||||||
-- * AIRBASE.GermanyCW.Grosse_Wiese
|
-- * AIRBASE.GermanyCW.Grosse_Wiese
|
||||||
-- * AIRBASE.GermanyCW.Gaerz
|
|
||||||
-- * AIRBASE.GermanyCW.Guetersloh
|
-- * AIRBASE.GermanyCW.Guetersloh
|
||||||
-- * AIRBASE.GermanyCW.H_FRG_01
|
-- * AIRBASE.GermanyCW.H_FRG_01
|
||||||
-- * AIRBASE.GermanyCW.H_FRG_02
|
-- * AIRBASE.GermanyCW.H_FRG_02
|
||||||
@@ -1016,10 +1068,11 @@ AIRBASE.Iraq = {
|
|||||||
-- * AIRBASE.GermanyCW.H_GDR_31
|
-- * AIRBASE.GermanyCW.H_GDR_31
|
||||||
-- * AIRBASE.GermanyCW.H_GDR_32
|
-- * AIRBASE.GermanyCW.H_GDR_32
|
||||||
-- * AIRBASE.GermanyCW.H_GDR_33
|
-- * AIRBASE.GermanyCW.H_GDR_33
|
||||||
|
-- * AIRBASE.GermanyCW.H_GDR_34
|
||||||
|
-- * AIRBASE.GermanyCW.H_Med_FRG_01
|
||||||
-- * AIRBASE.GermanyCW.H_Med_FRG_02
|
-- * AIRBASE.GermanyCW.H_Med_FRG_02
|
||||||
-- * AIRBASE.GermanyCW.H_Med_FRG_04
|
-- * AIRBASE.GermanyCW.H_Med_FRG_04
|
||||||
-- * AIRBASE.GermanyCW.H_Med_FRG_06
|
-- * AIRBASE.GermanyCW.H_Med_FRG_06
|
||||||
-- * AIRBASE.GermanyCW.H_Med_FRG_09
|
|
||||||
-- * AIRBASE.GermanyCW.H_Med_FRG_11
|
-- * AIRBASE.GermanyCW.H_Med_FRG_11
|
||||||
-- * AIRBASE.GermanyCW.H_Med_FRG_12
|
-- * AIRBASE.GermanyCW.H_Med_FRG_12
|
||||||
-- * AIRBASE.GermanyCW.H_Med_FRG_13
|
-- * AIRBASE.GermanyCW.H_Med_FRG_13
|
||||||
@@ -1067,9 +1120,9 @@ AIRBASE.Iraq = {
|
|||||||
-- * AIRBASE.GermanyCW.Koethen
|
-- * AIRBASE.GermanyCW.Koethen
|
||||||
-- * AIRBASE.GermanyCW.Laage
|
-- * AIRBASE.GermanyCW.Laage
|
||||||
-- * AIRBASE.GermanyCW.Langenselbold
|
-- * AIRBASE.GermanyCW.Langenselbold
|
||||||
|
-- * AIRBASE.GermanyCW.Laerz
|
||||||
-- * AIRBASE.GermanyCW.Leipzig_Halle
|
-- * AIRBASE.GermanyCW.Leipzig_Halle
|
||||||
-- * AIRBASE.GermanyCW.Leipzig_Mockau
|
-- * AIRBASE.GermanyCW.Leipzig_Mockau
|
||||||
-- * AIRBASE.GermanyCW.Laerz
|
|
||||||
-- * AIRBASE.GermanyCW.Luebeck
|
-- * AIRBASE.GermanyCW.Luebeck
|
||||||
-- * AIRBASE.GermanyCW.Lueneburg
|
-- * AIRBASE.GermanyCW.Lueneburg
|
||||||
-- * AIRBASE.GermanyCW.Mahlwinkel
|
-- * AIRBASE.GermanyCW.Mahlwinkel
|
||||||
@@ -1087,14 +1140,15 @@ AIRBASE.Iraq = {
|
|||||||
-- * AIRBASE.GermanyCW.Pottschutthoehe
|
-- * AIRBASE.GermanyCW.Pottschutthoehe
|
||||||
-- * AIRBASE.GermanyCW.Ramstein
|
-- * AIRBASE.GermanyCW.Ramstein
|
||||||
-- * AIRBASE.GermanyCW.Rinteln
|
-- * AIRBASE.GermanyCW.Rinteln
|
||||||
-- * AIRBASE.GermanyCW.Schweinfurt
|
|
||||||
-- * AIRBASE.GermanyCW.Schoenefeld
|
-- * AIRBASE.GermanyCW.Schoenefeld
|
||||||
|
-- * AIRBASE.GermanyCW.Schweinfurt
|
||||||
-- * AIRBASE.GermanyCW.Sembach
|
-- * AIRBASE.GermanyCW.Sembach
|
||||||
-- * AIRBASE.GermanyCW.Spangdahlem
|
-- * AIRBASE.GermanyCW.Spangdahlem
|
||||||
-- * AIRBASE.GermanyCW.Sperenberg
|
-- * AIRBASE.GermanyCW.Sperenberg
|
||||||
-- * AIRBASE.GermanyCW.Stendal
|
-- * AIRBASE.GermanyCW.Stendal
|
||||||
-- * AIRBASE.GermanyCW.Tegel
|
-- * AIRBASE.GermanyCW.Tegel
|
||||||
-- * AIRBASE.GermanyCW.Tempelhof
|
-- * AIRBASE.GermanyCW.Tempelhof
|
||||||
|
-- * AIRBASE.GermanyCW.Templin
|
||||||
-- * AIRBASE.GermanyCW.Tutow
|
-- * AIRBASE.GermanyCW.Tutow
|
||||||
-- * AIRBASE.GermanyCW.Uelzen
|
-- * AIRBASE.GermanyCW.Uelzen
|
||||||
-- * AIRBASE.GermanyCW.Uetersen
|
-- * AIRBASE.GermanyCW.Uetersen
|
||||||
@@ -1106,6 +1160,7 @@ AIRBASE.Iraq = {
|
|||||||
-- * AIRBASE.GermanyCW.Weser_Wuemme
|
-- * AIRBASE.GermanyCW.Weser_Wuemme
|
||||||
-- * AIRBASE.GermanyCW.Wiesbaden
|
-- * AIRBASE.GermanyCW.Wiesbaden
|
||||||
-- * AIRBASE.GermanyCW.Wismar
|
-- * AIRBASE.GermanyCW.Wismar
|
||||||
|
-- * AIRBASE.GermanyCW.Wittstock
|
||||||
-- * AIRBASE.GermanyCW.Worms
|
-- * AIRBASE.GermanyCW.Worms
|
||||||
-- * AIRBASE.GermanyCW.Wunstorf
|
-- * AIRBASE.GermanyCW.Wunstorf
|
||||||
-- * AIRBASE.GermanyCW.Zerbst
|
-- * AIRBASE.GermanyCW.Zerbst
|
||||||
@@ -1117,7 +1172,6 @@ AIRBASE.GermanyCW = {
|
|||||||
["Airracing_Koblenz"] = "Airracing Koblenz",
|
["Airracing_Koblenz"] = "Airracing Koblenz",
|
||||||
["Airracing_Luebeck"] = "Airracing Lubeck",
|
["Airracing_Luebeck"] = "Airracing Lubeck",
|
||||||
["Allstedt"] = "Allstedt",
|
["Allstedt"] = "Allstedt",
|
||||||
["Alt_Daber"] = "Alt Daber",
|
|
||||||
["Altes_Lager"] = "Altes Lager",
|
["Altes_Lager"] = "Altes Lager",
|
||||||
["Bad_Duerkheim"] = "Bad Durkheim",
|
["Bad_Duerkheim"] = "Bad Durkheim",
|
||||||
["Barth"] = "Barth",
|
["Barth"] = "Barth",
|
||||||
@@ -1140,14 +1194,13 @@ AIRBASE.GermanyCW = {
|
|||||||
["Fritzlar"] = "Fritzlar",
|
["Fritzlar"] = "Fritzlar",
|
||||||
["Fulda"] = "Fulda",
|
["Fulda"] = "Fulda",
|
||||||
["Gardelegen"] = "Gardelegen",
|
["Gardelegen"] = "Gardelegen",
|
||||||
|
["Garz"] = "Garz",
|
||||||
["Gatow"] = "Gatow",
|
["Gatow"] = "Gatow",
|
||||||
["Gelnhausen"] = "Gelnhausen",
|
["Gelnhausen"] = "Gelnhausen",
|
||||||
["Giebelstadt"] = "Giebelstadt",
|
["Giebelstadt"] = "Giebelstadt",
|
||||||
["Glindbruchkippe_"] = "Glindbruchkippe ",
|
["Glindbruchkippe"] = "Glindbruchkippe ",
|
||||||
["Gross_Doelln"] = "Gross Dolln",
|
|
||||||
["Gross_Mohrdorf"] = "Gross Mohrdorf",
|
["Gross_Mohrdorf"] = "Gross Mohrdorf",
|
||||||
["Grosse_Wiese"] = "Grosse Wiese",
|
["Grosse_Wiese"] = "Grosse Wiese",
|
||||||
["Gaerz"] = "Garz",
|
|
||||||
["Guetersloh"] = "Gutersloh",
|
["Guetersloh"] = "Gutersloh",
|
||||||
["H_FRG_01"] = "H FRG 01",
|
["H_FRG_01"] = "H FRG 01",
|
||||||
["H_FRG_02"] = "H FRG 02",
|
["H_FRG_02"] = "H FRG 02",
|
||||||
@@ -1219,10 +1272,11 @@ AIRBASE.GermanyCW = {
|
|||||||
["H_GDR_31"] = "H GDR 31",
|
["H_GDR_31"] = "H GDR 31",
|
||||||
["H_GDR_32"] = "H GDR 32",
|
["H_GDR_32"] = "H GDR 32",
|
||||||
["H_GDR_33"] = "H GDR 33",
|
["H_GDR_33"] = "H GDR 33",
|
||||||
|
["H_GDR_34"] = "H GDR 34",
|
||||||
|
["H_Med_FRG_01"] = "H Med FRG 01",
|
||||||
["H_Med_FRG_02"] = "H Med FRG 02",
|
["H_Med_FRG_02"] = "H Med FRG 02",
|
||||||
["H_Med_FRG_04"] = "H Med FRG 04",
|
["H_Med_FRG_04"] = "H Med FRG 04",
|
||||||
["H_Med_FRG_06"] = "H Med FRG 06",
|
["H_Med_FRG_06"] = "H Med FRG 06",
|
||||||
["H_Med_FRG_09"] = "H Med FRG 09",
|
|
||||||
["H_Med_FRG_11"] = "H Med FRG 11",
|
["H_Med_FRG_11"] = "H Med FRG 11",
|
||||||
["H_Med_FRG_12"] = "H Med FRG 12",
|
["H_Med_FRG_12"] = "H Med FRG 12",
|
||||||
["H_Med_FRG_13"] = "H Med FRG 13",
|
["H_Med_FRG_13"] = "H Med FRG 13",
|
||||||
@@ -1270,9 +1324,9 @@ AIRBASE.GermanyCW = {
|
|||||||
["Koethen"] = "Kothen",
|
["Koethen"] = "Kothen",
|
||||||
["Laage"] = "Laage",
|
["Laage"] = "Laage",
|
||||||
["Langenselbold"] = "Langenselbold",
|
["Langenselbold"] = "Langenselbold",
|
||||||
|
["Laerz"] = "Larz",
|
||||||
["Leipzig_Halle"] = "Leipzig Halle",
|
["Leipzig_Halle"] = "Leipzig Halle",
|
||||||
["Leipzig_Mockau"] = "Leipzig Mockau",
|
["Leipzig_Mockau"] = "Leipzig Mockau",
|
||||||
["Laerz"] = "Larz",
|
|
||||||
["Luebeck"] = "Lubeck",
|
["Luebeck"] = "Lubeck",
|
||||||
["Lueneburg"] = "Luneburg",
|
["Lueneburg"] = "Luneburg",
|
||||||
["Mahlwinkel"] = "Mahlwinkel",
|
["Mahlwinkel"] = "Mahlwinkel",
|
||||||
@@ -1290,14 +1344,15 @@ AIRBASE.GermanyCW = {
|
|||||||
["Pottschutthoehe"] = "Pottschutthohe",
|
["Pottschutthoehe"] = "Pottschutthohe",
|
||||||
["Ramstein"] = "Ramstein",
|
["Ramstein"] = "Ramstein",
|
||||||
["Rinteln"] = "Rinteln",
|
["Rinteln"] = "Rinteln",
|
||||||
["Schweinfurt"] = "Schweinfurt",
|
|
||||||
["Schoenefeld"] = "Schonefeld",
|
["Schoenefeld"] = "Schonefeld",
|
||||||
|
["Schweinfurt"] = "Schweinfurt",
|
||||||
["Sembach"] = "Sembach",
|
["Sembach"] = "Sembach",
|
||||||
["Spangdahlem"] = "Spangdahlem",
|
["Spangdahlem"] = "Spangdahlem",
|
||||||
["Sperenberg"] = "Sperenberg",
|
["Sperenberg"] = "Sperenberg",
|
||||||
["Stendal"] = "Stendal",
|
["Stendal"] = "Stendal",
|
||||||
["Tegel"] = "Tegel",
|
["Tegel"] = "Tegel",
|
||||||
["Tempelhof"] = "Tempelhof",
|
["Tempelhof"] = "Tempelhof",
|
||||||
|
["Templin"] = "Templin",
|
||||||
["Tutow"] = "Tutow",
|
["Tutow"] = "Tutow",
|
||||||
["Uelzen"] = "Uelzen",
|
["Uelzen"] = "Uelzen",
|
||||||
["Uetersen"] = "Uetersen",
|
["Uetersen"] = "Uetersen",
|
||||||
@@ -1309,6 +1364,7 @@ AIRBASE.GermanyCW = {
|
|||||||
["Weser_Wuemme"] = "Weser Wumme",
|
["Weser_Wuemme"] = "Weser Wumme",
|
||||||
["Wiesbaden"] = "Wiesbaden",
|
["Wiesbaden"] = "Wiesbaden",
|
||||||
["Wismar"] = "Wismar",
|
["Wismar"] = "Wismar",
|
||||||
|
["Wittstock"] = "Wittstock",
|
||||||
["Worms"] = "Worms",
|
["Worms"] = "Worms",
|
||||||
["Wunstorf"] = "Wunstorf",
|
["Wunstorf"] = "Wunstorf",
|
||||||
["Zerbst"] = "Zerbst",
|
["Zerbst"] = "Zerbst",
|
||||||
@@ -1419,7 +1475,7 @@ function AIRBASE:Register(AirbaseName)
|
|||||||
self.descriptors=self:GetDesc()
|
self.descriptors=self:GetDesc()
|
||||||
|
|
||||||
-- Debug info.
|
-- Debug info.
|
||||||
--self:I({airbase=AirbaseName, descriptors=self.descriptors})
|
--self:T({airbase=AirbaseName, descriptors=self.descriptors})
|
||||||
|
|
||||||
-- Category.
|
-- Category.
|
||||||
self.category=self.descriptors and self.descriptors.category or Airbase.Category.AIRDROME
|
self.category=self.descriptors and self.descriptors.category or Airbase.Category.AIRDROME
|
||||||
@@ -2581,11 +2637,12 @@ function AIRBASE:_InitRunways(IncludeInverse)
|
|||||||
runway.name=string.format("%02d", tonumber(namefromheading))
|
runway.name=string.format("%02d", tonumber(namefromheading))
|
||||||
else
|
else
|
||||||
runway.name=string.format("%02d", tonumber(name))
|
runway.name=string.format("%02d", tonumber(name))
|
||||||
self:I("RunwayName: "..runway.name)
|
--self:I("RunwayName: "..runway.name)
|
||||||
end
|
end
|
||||||
|
|
||||||
--runway.name=string.format("%02d", tonumber(name))
|
--runway.name=string.format("%02d", tonumber(name))
|
||||||
runway.magheading=tonumber(runway.name)*10
|
runway.magheading=tonumber(runway.name)*10
|
||||||
|
runway.idx=runway.magheading
|
||||||
runway.heading=heading
|
runway.heading=heading
|
||||||
runway.width=width or 0
|
runway.width=width or 0
|
||||||
runway.length=length or 0
|
runway.length=length or 0
|
||||||
@@ -2898,6 +2955,7 @@ function AIRBASE:GetRunwayData(magvar, mark)
|
|||||||
local runway={} --#AIRBASE.Runway
|
local runway={} --#AIRBASE.Runway
|
||||||
runway.heading=hdg
|
runway.heading=hdg
|
||||||
runway.idx=idx
|
runway.idx=idx
|
||||||
|
runway.magheading=idx
|
||||||
runway.length=c1:Get2DDistance(c2)
|
runway.length=c1:Get2DDistance(c2)
|
||||||
runway.position=c1
|
runway.position=c1
|
||||||
runway.endpoint=c2
|
runway.endpoint=c2
|
||||||
@@ -2915,6 +2973,57 @@ function AIRBASE:GetRunwayData(magvar, mark)
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Look for identical (parallel) runways, e.g. 03L and 03R at Nellis.
|
||||||
|
local rpairs={}
|
||||||
|
for i,_ri in pairs(runways) do
|
||||||
|
local ri=_ri --#AIRBASE.Runway
|
||||||
|
for j,_rj in pairs(runways) do
|
||||||
|
local rj=_rj --#AIRBASE.Runway
|
||||||
|
if i<j then
|
||||||
|
if ri.name==rj.name then
|
||||||
|
rpairs[i]=j
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function isLeft(a, b, c)
|
||||||
|
--return ((b.x - a.x)*(c.z - a.z) - (b.z - a.z)*(c.x - a.x)) > 0
|
||||||
|
return ((b.z - a.z)*(c.x - a.x) - (b.x - a.x)*(c.z - a.z)) > 0
|
||||||
|
end
|
||||||
|
|
||||||
|
for i,j in pairs(rpairs) do
|
||||||
|
local ri=runways[i] --#AIRBASE.Runway
|
||||||
|
local rj=runways[j] --#AIRBASE.Runway
|
||||||
|
|
||||||
|
-- Draw arrow.
|
||||||
|
--ri.center:ArrowToAll(rj.center)
|
||||||
|
|
||||||
|
local c0=ri.position
|
||||||
|
|
||||||
|
-- Vector in the direction of the runway.
|
||||||
|
local a=UTILS.VecTranslate(c0, 1000, ri.heading)
|
||||||
|
|
||||||
|
-- Vector from runway i to runway j.
|
||||||
|
local b=UTILS.VecSubstract(rj.position, ri.position)
|
||||||
|
b=UTILS.VecAdd(ri.position, b)
|
||||||
|
|
||||||
|
-- Check if rj is left of ri.
|
||||||
|
local left=isLeft(c0, a, b)
|
||||||
|
|
||||||
|
--env.info(string.format("Found pair %s: i=%d, j=%d, left==%s", ri.name, i, j, tostring(left)))
|
||||||
|
|
||||||
|
if left then
|
||||||
|
ri.isLeft=false
|
||||||
|
rj.isLeft=true
|
||||||
|
else
|
||||||
|
ri.isLeft=true
|
||||||
|
rj.isLeft=false
|
||||||
|
end
|
||||||
|
|
||||||
|
--break
|
||||||
|
end
|
||||||
|
|
||||||
return runways
|
return runways
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -168,17 +168,26 @@
|
|||||||
-- * @{#CONTROLLABLE.OptionAlarmStateGreen}
|
-- * @{#CONTROLLABLE.OptionAlarmStateGreen}
|
||||||
-- * @{#CONTROLLABLE.OptionAlarmStateRed}
|
-- * @{#CONTROLLABLE.OptionAlarmStateRed}
|
||||||
--
|
--
|
||||||
-- ## 5.4) Jettison weapons:
|
-- ## 5.4) [AIR] Jettison weapons:
|
||||||
--
|
--
|
||||||
-- * @{#CONTROLLABLE.OptionAllowJettisonWeaponsOnThreat}
|
-- * @{#CONTROLLABLE.OptionAllowJettisonWeaponsOnThreat}
|
||||||
-- * @{#CONTROLLABLE.OptionKeepWeaponsOnThreat}
|
-- * @{#CONTROLLABLE.OptionKeepWeaponsOnThreat}
|
||||||
--
|
--
|
||||||
-- ## 5.5) Air-2-Air missile attack range:
|
-- ## 5.5) [AIR] 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
|
-- # 6) [GROUND] IR Maker Beacons for GROUPs and UNITs
|
||||||
-- * @{#CONTROLLABLE:NewIRMarker}(): Create a blinking IR Marker on a GROUP or UNIT.
|
-- * @{#CONTROLLABLE:NewIRMarker}(): Create a blinking IR Marker on a GROUP or UNIT.
|
||||||
--
|
--
|
||||||
|
-- # 7) [HELICOPTER] Units prefer vertical landing and takeoffs:
|
||||||
|
-- * @{#CONTROLLABLE.OptionPreferVerticalLanding}(): Set aircraft to prefer vertical landing and takeoff.
|
||||||
|
--
|
||||||
|
-- # 8) [AIRCRAFT] Landing approach options
|
||||||
|
-- * @{#CONTROLLABLE.SetOptionLandingStraightIn}(): Landing approach straight in.
|
||||||
|
-- * @{#CONTROLLABLE.SetOptionLandingForcePair}(): Landing approach in pairs for groups > 1 unit.
|
||||||
|
-- * @{#CONTROLLABLE.SetOptionLandingRestrictPair}(): Landing approach single.
|
||||||
|
-- * @{#CONTROLLABLE.SetOptionLandingOverheadBreak}(): Landing approach overhead break.
|
||||||
|
--
|
||||||
-- @field #CONTROLLABLE
|
-- @field #CONTROLLABLE
|
||||||
CONTROLLABLE = {
|
CONTROLLABLE = {
|
||||||
ClassName = "CONTROLLABLE",
|
ClassName = "CONTROLLABLE",
|
||||||
@@ -1432,7 +1441,7 @@ end
|
|||||||
-- @param #number Speed The speed [m/s] flying when holding the position.
|
-- @param #number Speed The speed [m/s] flying when holding the position.
|
||||||
-- @return #CONTROLLABLE self
|
-- @return #CONTROLLABLE self
|
||||||
function CONTROLLABLE:TaskOrbitCircleAtVec2( Point, Altitude, Speed )
|
function CONTROLLABLE:TaskOrbitCircleAtVec2( Point, Altitude, Speed )
|
||||||
self:F2( { self.ControllableName, Point, Altitude, Speed } )
|
--self:F2( { self.ControllableName, Point, Altitude, Speed } )
|
||||||
|
|
||||||
local DCSTask = {
|
local DCSTask = {
|
||||||
id = 'Orbit',
|
id = 'Orbit',
|
||||||
@@ -3629,6 +3638,26 @@ function CONTROLLABLE:OptionROTPassiveDefense()
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Helicopter - prefer vertical landing.
|
||||||
|
-- @param #CONTROLLABLE self
|
||||||
|
-- @return #CONTROLLABLE self
|
||||||
|
function CONTROLLABLE:OptionPreferVerticalLanding()
|
||||||
|
self:F2( { self.ControllableName } )
|
||||||
|
|
||||||
|
local DCSControllable = self:GetDCSObject()
|
||||||
|
if DCSControllable then
|
||||||
|
local Controller = self:_GetController()
|
||||||
|
|
||||||
|
if self:IsAir() then
|
||||||
|
Controller:setOption( AI.Option.Air.id.PREFER_VERTICAL, true )
|
||||||
|
end
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
--- Can the CONTROLLABLE evade on enemy fire?
|
--- Can the CONTROLLABLE evade on enemy fire?
|
||||||
-- @param #CONTROLLABLE self
|
-- @param #CONTROLLABLE self
|
||||||
-- @return #boolean
|
-- @return #boolean
|
||||||
@@ -4183,6 +4212,50 @@ function CONTROLLABLE:OptionEngageRange( EngageRange )
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- [AIR] Set how the AI lands on an airfield. Here: Straight in.
|
||||||
|
-- @param #CONTROLLABLE self
|
||||||
|
-- @return #CONTROLLABLE self
|
||||||
|
function CONTROLLABLE:SetOptionLandingStraightIn()
|
||||||
|
self:F2( { self.ControllableName } )
|
||||||
|
if self:IsAir() then
|
||||||
|
self:SetOption("36","0")
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [AIR] Set how the AI lands on an airfield. Here: In pairs (if > 1 aircraft in group)
|
||||||
|
-- @param #CONTROLLABLE self
|
||||||
|
-- @return #CONTROLLABLE self
|
||||||
|
function CONTROLLABLE:SetOptionLandingForcePair()
|
||||||
|
self:F2( { self.ControllableName } )
|
||||||
|
if self:IsAir() then
|
||||||
|
self:SetOption("36","1")
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [AIR] Set how the AI lands on an airfield. Here: No landing in pairs.
|
||||||
|
-- @param #CONTROLLABLE self
|
||||||
|
-- @return #CONTROLLABLE self
|
||||||
|
function CONTROLLABLE:SetOptionLandingRestrictPair()
|
||||||
|
self:F2( { self.ControllableName } )
|
||||||
|
if self:IsAir() then
|
||||||
|
self:SetOption("36","2")
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [AIR] Set how the AI lands on an airfield. Here: Overhead break.
|
||||||
|
-- @param #CONTROLLABLE self
|
||||||
|
-- @return #CONTROLLABLE self
|
||||||
|
function CONTROLLABLE:SetOptionLandingOverheadBreak()
|
||||||
|
self:F2( { self.ControllableName } )
|
||||||
|
if self:IsAir() then
|
||||||
|
self:SetOption("36","3")
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- [AIR] Set how the AI uses the onboard radar.
|
--- [AIR] Set how the AI uses the onboard radar.
|
||||||
-- @param #CONTROLLABLE self
|
-- @param #CONTROLLABLE self
|
||||||
-- @param #number Option Options are: `NEVER = 0, FOR_ATTACK_ONLY = 1,FOR_SEARCH_IF_REQUIRED = 2, FOR_CONTINUOUS_SEARCH = 3`
|
-- @param #number Option Options are: `NEVER = 0, FOR_ATTACK_ONLY = 1,FOR_SEARCH_IF_REQUIRED = 2, FOR_CONTINUOUS_SEARCH = 3`
|
||||||
|
|||||||
@@ -230,6 +230,7 @@ GROUP.Attribute = {
|
|||||||
GROUND_EWR="Ground_EWR",
|
GROUND_EWR="Ground_EWR",
|
||||||
GROUND_AAA="Ground_AAA",
|
GROUND_AAA="Ground_AAA",
|
||||||
GROUND_SAM="Ground_SAM",
|
GROUND_SAM="Ground_SAM",
|
||||||
|
GROUND_SHORAD="Ground_SHORAD",
|
||||||
GROUND_OTHER="Ground_OtherGround",
|
GROUND_OTHER="Ground_OtherGround",
|
||||||
NAVAL_AIRCRAFTCARRIER="Naval_AircraftCarrier",
|
NAVAL_AIRCRAFTCARRIER="Naval_AircraftCarrier",
|
||||||
NAVAL_WARSHIP="Naval_WarShip",
|
NAVAL_WARSHIP="Naval_WarShip",
|
||||||
@@ -912,15 +913,18 @@ function GROUP:GetVelocityVec3()
|
|||||||
|
|
||||||
if DCSGroup and DCSGroup:isExist() then
|
if DCSGroup and DCSGroup:isExist() then
|
||||||
local GroupUnits = DCSGroup:getUnits()
|
local GroupUnits = DCSGroup:getUnits()
|
||||||
local GroupCount = #GroupUnits
|
local GroupCount = 0
|
||||||
|
|
||||||
local VelocityVec3 = { x = 0, y = 0, z = 0 }
|
local VelocityVec3 = { x = 0, y = 0, z = 0 }
|
||||||
|
|
||||||
for _, DCSUnit in pairs( GroupUnits ) do
|
for _, DCSUnit in pairs( GroupUnits ) do
|
||||||
|
if DCSUnit:isExist() and DCSUnit:isActive() then
|
||||||
local UnitVelocityVec3 = DCSUnit:getVelocity()
|
local UnitVelocityVec3 = DCSUnit:getVelocity()
|
||||||
VelocityVec3.x = VelocityVec3.x + UnitVelocityVec3.x
|
VelocityVec3.x = VelocityVec3.x + UnitVelocityVec3.x
|
||||||
VelocityVec3.y = VelocityVec3.y + UnitVelocityVec3.y
|
VelocityVec3.y = VelocityVec3.y + UnitVelocityVec3.y
|
||||||
VelocityVec3.z = VelocityVec3.z + UnitVelocityVec3.z
|
VelocityVec3.z = VelocityVec3.z + UnitVelocityVec3.z
|
||||||
|
GroupCount = GroupCount + 1
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
VelocityVec3.x = VelocityVec3.x / GroupCount
|
VelocityVec3.x = VelocityVec3.x / GroupCount
|
||||||
@@ -1754,6 +1758,7 @@ function GROUP:GetMaxVelocity()
|
|||||||
|
|
||||||
for Index, UnitData in pairs( DCSGroup:getUnits() ) do
|
for Index, UnitData in pairs( DCSGroup:getUnits() ) do
|
||||||
|
|
||||||
|
if UnitData:isExist() and UnitData:isActive() then
|
||||||
local UnitVelocityVec3 = UnitData:getVelocity()
|
local UnitVelocityVec3 = UnitData:getVelocity()
|
||||||
local UnitVelocity = math.abs( UnitVelocityVec3.x ) + math.abs( UnitVelocityVec3.y ) + math.abs( UnitVelocityVec3.z )
|
local UnitVelocity = math.abs( UnitVelocityVec3.x ) + math.abs( UnitVelocityVec3.y ) + math.abs( UnitVelocityVec3.z )
|
||||||
|
|
||||||
@@ -1761,6 +1766,7 @@ function GROUP:GetMaxVelocity()
|
|||||||
GroupVelocityMax = UnitVelocity
|
GroupVelocityMax = UnitVelocity
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
return GroupVelocityMax
|
return GroupVelocityMax
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -246,18 +246,20 @@ end
|
|||||||
function POSITIONABLE:GetVec3()
|
function POSITIONABLE:GetVec3()
|
||||||
local DCSPositionable = self:GetDCSObject()
|
local DCSPositionable = self:GetDCSObject()
|
||||||
if DCSPositionable then
|
if DCSPositionable then
|
||||||
--local status, vec3 = pcall(
|
|
||||||
-- function()
|
|
||||||
-- local vec3 = DCSPositionable:getPoint()
|
|
||||||
-- return vec3
|
|
||||||
--end
|
|
||||||
--)
|
|
||||||
local vec3 = DCSPositionable:getPoint()
|
local vec3 = DCSPositionable:getPoint()
|
||||||
--if status then
|
|
||||||
|
if not vec3 then
|
||||||
|
local pos = DCSPositionable:getPosition()
|
||||||
|
if pos and pos.p then
|
||||||
|
vec3 = pos.p
|
||||||
|
else
|
||||||
|
self:E( { "Cannot get the position from DCS Object for GetVec3", Positionable = self, Alive = self:IsAlive() } )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
return vec3
|
return vec3
|
||||||
--else
|
|
||||||
--self:E( { "Cannot get Vec3 from DCS Object", Positionable = self, Alive = self:IsAlive() } )
|
|
||||||
--end
|
|
||||||
end
|
end
|
||||||
-- ERROR!
|
-- ERROR!
|
||||||
self:E( { "Cannot get the Positionable DCS Object for GetVec3", Positionable = self, Alive = self:IsAlive() } )
|
self:E( { "Cannot get the Positionable DCS Object for GetVec3", Positionable = self, Alive = self:IsAlive() } )
|
||||||
@@ -388,13 +390,13 @@ function POSITIONABLE:GetCoordinate()
|
|||||||
|
|
||||||
-- Get the current position.
|
-- Get the current position.
|
||||||
local PositionableVec3 = self:GetVec3()
|
local PositionableVec3 = self:GetVec3()
|
||||||
|
if PositionableVec3 then
|
||||||
local coord=COORDINATE:NewFromVec3(PositionableVec3)
|
local coord=COORDINATE:NewFromVec3(PositionableVec3)
|
||||||
local heading = self:GetHeading()
|
local heading = self:GetHeading()
|
||||||
coord.Heading = heading
|
coord.Heading = heading
|
||||||
-- Return a new coordiante object.
|
-- Return a new coordiante object.
|
||||||
return coord
|
return coord
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Error message.
|
-- Error message.
|
||||||
|
|||||||
@@ -897,7 +897,7 @@ function UNIT:GetAmmunition()
|
|||||||
nAPshells = nAPshells + Nammo
|
nAPshells = nAPshells + Nammo
|
||||||
end
|
end
|
||||||
|
|
||||||
if ammotable[w].desc.typeName and string.find(ammotable[w].desc.typeName, "_HE", 1, true) then
|
if ammotable[w].desc.typeName and (string.find(ammotable[w].desc.typeName, "_HE", 1, true) or string.find(ammotable[w].desc.typeName, "HESH", 1, true)) then
|
||||||
nHEshells = nHEshells + Nammo
|
nHEshells = nHEshells + Nammo
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1107,7 +1107,6 @@ function UNIT:GetUnits()
|
|||||||
|
|
||||||
if DCSUnit then
|
if DCSUnit then
|
||||||
Units[1] = UNIT:Find(DCSUnit)
|
Units[1] = UNIT:Find(DCSUnit)
|
||||||
- self:T3(Units)
|
|
||||||
return Units
|
return Units
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1925,3 +1924,17 @@ function UNIT:IsAAA()
|
|||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Set the relative life points of a UNIT object
|
||||||
|
-- @param #UNIT self
|
||||||
|
-- @param #number Percent Percent to set, can be 0..100.
|
||||||
|
function UNIT:SetLife(Percent)
|
||||||
|
net.dostring_in("mission",string.format("a_unit_set_life_percentage(%d, %f)", self:GetID(), Percent))
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set the carrier illumination mode. -2: OFF, -1: AUTO, 0: NAVIGATION, 1: AC LAUNCH, 2: AC RECOVERY
|
||||||
|
-- @param #UNIT self
|
||||||
|
-- @param #number Mode Illumination mode, can be -2: OFF, -1: AUTO, 0: NAVIGATION, 1: AC LAUNCH, 2: AC RECOVERY
|
||||||
|
function UNIT:SetCarrierIlluminationMode(Mode)
|
||||||
|
UTILS.SetCarrierIlluminationMode(self:GetID(), Mode)
|
||||||
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user