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 |
1
.github/workflows/build-docs.yml
vendored
1
.github/workflows/build-docs.yml
vendored
@@ -57,7 +57,6 @@ jobs:
|
|||||||
|
|
||||||
- name: Update apt-get (needed for act docker image)
|
- name: Update apt-get (needed for act docker image)
|
||||||
run: |
|
run: |
|
||||||
sudo rm /etc/apt/sources.list.d/microsoft-prod.list
|
|
||||||
sudo apt-get -qq update
|
sudo apt-get -qq update
|
||||||
|
|
||||||
- name: Install tree
|
- name: Install tree
|
||||||
|
|||||||
2
.github/workflows/build-includes.yml
vendored
2
.github/workflows/build-includes.yml
vendored
@@ -110,7 +110,7 @@ jobs:
|
|||||||
- name: Run LuaSrcDiet
|
- name: Run LuaSrcDiet
|
||||||
run: |
|
run: |
|
||||||
luasrcdiet --basic --opt-emptylines ./build/result/Moose_Include_Static/Moose.lua -o ./build/result/Moose_Include_Static/Moose_.lua
|
luasrcdiet --basic --opt-emptylines ./build/result/Moose_Include_Static/Moose.lua -o ./build/result/Moose_Include_Static/Moose_.lua
|
||||||
|
|
||||||
#########################################################################
|
#########################################################################
|
||||||
# Push to MOOSE_INCLUDE
|
# Push to MOOSE_INCLUDE
|
||||||
#########################################################################
|
#########################################################################
|
||||||
|
|||||||
7
.gitignore
vendored
7
.gitignore
vendored
@@ -28,13 +28,6 @@ local.properties
|
|||||||
.buildpath
|
.buildpath
|
||||||
|
|
||||||
|
|
||||||
#####################
|
|
||||||
## Visual Studio Code
|
|
||||||
#####################
|
|
||||||
*.code-workspace
|
|
||||||
.vscode/
|
|
||||||
|
|
||||||
|
|
||||||
#################
|
#################
|
||||||
## Visual Studio
|
## Visual Studio
|
||||||
#################
|
#################
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
14
Moose Development/Moose/.vscode/settings.json
vendored
14
Moose Development/Moose/.vscode/settings.json
vendored
@@ -1,17 +1,7 @@
|
|||||||
{
|
{
|
||||||
"Lua.workspace.preloadFileSize": 10000,
|
"Lua.workspace.preloadFileSize": 1000,
|
||||||
"Lua.diagnostics.disable": [
|
"Lua.diagnostics.disable": [
|
||||||
"undefined-doc-name",
|
"undefined-doc-name"
|
||||||
"duplicate-set-field",
|
|
||||||
"trailing-space",
|
|
||||||
"need-check-nil",
|
|
||||||
"ambiguity-1",
|
|
||||||
"undefined-doc-param",
|
|
||||||
"redundant-parameter",
|
|
||||||
"param-type-mismatch",
|
|
||||||
"deprecated",
|
|
||||||
"undefined-global",
|
|
||||||
"lowercase-global"
|
|
||||||
],
|
],
|
||||||
"Lua.diagnostics.globals": [
|
"Lua.diagnostics.globals": [
|
||||||
"BASE",
|
"BASE",
|
||||||
|
|||||||
@@ -11,13 +11,15 @@
|
|||||||
-- @module AI.AI_A2A_Cap
|
-- @module AI.AI_A2A_Cap
|
||||||
-- @image AI_Combat_Air_Patrol.JPG
|
-- @image AI_Combat_Air_Patrol.JPG
|
||||||
|
|
||||||
-- @type AI_A2A_CAP
|
--- @type AI_A2A_CAP
|
||||||
-- @extends AI.AI_Air_Patrol#AI_AIR_PATROL
|
-- @extends AI.AI_Air_Patrol#AI_AIR_PATROL
|
||||||
-- @extends AI.AI_Air_Engage#AI_AIR_ENGAGE
|
-- @extends AI.AI_Air_Engage#AI_AIR_ENGAGE
|
||||||
|
|
||||||
--- 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.
|
||||||
|
|||||||
@@ -32,7 +32,9 @@
|
|||||||
-- [DCS WORLD - MOOSE - A2A GCICAP - Build an automatic A2A Defense System](https://www.youtube.com/playlist?list=PL7ZUrU4zZUl0S4KMNUUJpaUs6zZHjLKNx)
|
-- [DCS WORLD - MOOSE - A2A GCICAP - Build an automatic A2A Defense System](https://www.youtube.com/playlist?list=PL7ZUrU4zZUl0S4KMNUUJpaUs6zZHjLKNx)
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- # 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.
|
||||||
|
|||||||
@@ -13,12 +13,14 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
-- @type AI_A2A_GCI
|
--- @type AI_A2A_GCI
|
||||||
-- @extends AI.AI_A2A#AI_A2A
|
-- @extends AI.AI_Air_Engage#AI_AIR_ENGAGE
|
||||||
|
|
||||||
|
|
||||||
--- 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.
|
||||||
@@ -39,8 +41,6 @@
|
|||||||
--
|
--
|
||||||
-- ## 2. AI_A2A_GCI is a FSM
|
-- ## 2. AI_A2A_GCI is a FSM
|
||||||
--
|
--
|
||||||
-- 
|
|
||||||
--
|
|
||||||
-- ### 2.1 AI_A2A_GCI States
|
-- ### 2.1 AI_A2A_GCI States
|
||||||
--
|
--
|
||||||
-- * **None** ( Group ): The process is not started yet.
|
-- * **None** ( Group ): The process is not started yet.
|
||||||
|
|||||||
@@ -10,11 +10,13 @@
|
|||||||
-- @image AI_Air_Patrolling.JPG
|
-- @image AI_Air_Patrolling.JPG
|
||||||
|
|
||||||
|
|
||||||
-- @type AI_A2A_PATROL
|
--- @type AI_A2A_PATROL
|
||||||
-- @extends AI.AI_A2A#AI_A2A
|
-- @extends AI.AI_Air_Patrol#AI_AIR_PATROL
|
||||||
|
|
||||||
--- 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.
|
||||||
|
|||||||
@@ -11,11 +11,14 @@
|
|||||||
-- @module AI.AI_A2G_BAI
|
-- @module AI.AI_A2G_BAI
|
||||||
-- @image AI_Air_To_Ground_Engage.JPG
|
-- @image AI_Air_To_Ground_Engage.JPG
|
||||||
|
|
||||||
-- @type AI_A2G_BAI
|
--- @type AI_A2G_BAI
|
||||||
-- @extends AI.AI_A2A_Engage#AI_A2A_Engage -- TODO: Documentation. This class does not exist, unable to determine what it extends.
|
-- @extends AI.AI_Air_Patrol#AI_AIR_PATROL
|
||||||
|
-- @extends AI.AI_Air_Engage#AI_AIR_ENGAGE
|
||||||
|
|
||||||
--- 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
|
||||||
@@ -46,7 +49,7 @@ AI_A2G_BAI = {
|
|||||||
function AI_A2G_BAI:New2( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType )
|
function AI_A2G_BAI:New2( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType )
|
||||||
|
|
||||||
local AI_Air = AI_AIR:New( AIGroup )
|
local AI_Air = AI_AIR:New( AIGroup )
|
||||||
local AI_Air_Patrol = AI_AIR_PATROL:New( AI_Air, AIGroup, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType ) -- #AI_AIR_PATROL
|
local AI_Air_Patrol = AI_AIR_PATROL:New( AI_Air, AIGroup, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType )
|
||||||
local AI_Air_Engage = AI_AIR_ENGAGE:New( AI_Air_Patrol, AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType )
|
local AI_Air_Engage = AI_AIR_ENGAGE:New( AI_Air_Patrol, AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType )
|
||||||
local self = BASE:Inherit( self, AI_Air_Engage )
|
local self = BASE:Inherit( self, AI_Air_Engage )
|
||||||
|
|
||||||
|
|||||||
@@ -11,13 +11,16 @@
|
|||||||
-- @module AI.AI_A2G_CAS
|
-- @module AI.AI_A2G_CAS
|
||||||
-- @image AI_Air_To_Ground_Engage.JPG
|
-- @image AI_Air_To_Ground_Engage.JPG
|
||||||
|
|
||||||
-- @type AI_A2G_CAS
|
--- @type AI_A2G_CAS
|
||||||
-- @extends AI.AI_A2G_Patrol#AI_AIR_PATROL TODO: Documentation. This class does not exist, unable to determine what it extends.
|
-- @extends AI.AI_Air_Patrol#AI_AIR_PATROL
|
||||||
|
-- @extends AI.AI_Air_Engage#AI_AIR_ENGAGE
|
||||||
|
|
||||||
--- 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
|
||||||
-- Therefore, this class is considered to be deprecated
|
-- Therefore, this class is considered to be deprecated
|
||||||
--
|
--
|
||||||
@@ -46,7 +49,7 @@ AI_A2G_CAS = {
|
|||||||
function AI_A2G_CAS:New2( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType )
|
function AI_A2G_CAS:New2( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType )
|
||||||
|
|
||||||
local AI_Air = AI_AIR:New( AIGroup )
|
local AI_Air = AI_AIR:New( AIGroup )
|
||||||
local AI_Air_Patrol = AI_AIR_PATROL:New( AI_Air, AIGroup, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType ) -- #AI_AIR_PATROL
|
local AI_Air_Patrol = AI_AIR_PATROL:New( AI_Air, AIGroup, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType )
|
||||||
local AI_Air_Engage = AI_AIR_ENGAGE:New( AI_Air_Patrol, AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType )
|
local AI_Air_Engage = AI_AIR_ENGAGE:New( AI_Air_Patrol, AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType )
|
||||||
local self = BASE:Inherit( self, AI_Air_Engage )
|
local self = BASE:Inherit( self, AI_Air_Engage )
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -13,12 +13,15 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
-- @type AI_A2G_SEAD
|
--- @type AI_A2G_SEAD
|
||||||
-- @extends AI.AI_A2G_Patrol#AI_AIR_PATROL
|
-- @extends AI.AI_Air_Patrol#AI_AIR_PATROL
|
||||||
|
-- @extends AI.AI_Air_Engage#AI_AIR_ENGAGE
|
||||||
|
|
||||||
|
|
||||||
--- 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.
|
||||||
|
|||||||
@@ -9,12 +9,14 @@
|
|||||||
-- @module AI.AI_Air_Patrol
|
-- @module AI.AI_Air_Patrol
|
||||||
-- @image AI_Air_To_Ground_Patrol.JPG
|
-- @image AI_Air_To_Ground_Patrol.JPG
|
||||||
|
|
||||||
-- @type AI_AIR_PATROL
|
--- @type AI_AIR_PATROL
|
||||||
-- @extends AI.AI_Air#AI_AIR
|
-- @extends AI.AI_Air#AI_AIR
|
||||||
|
|
||||||
--- 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.
|
||||||
--
|
--
|
||||||
-- 
|
-- 
|
||||||
@@ -407,7 +409,7 @@ function AI_BAI_ZONE:onafterStart( Controllable, From, Event, To )
|
|||||||
self:SetDetectionDeactivated() -- When not engaging, set the detection off.
|
self:SetDetectionDeactivated() -- When not engaging, set the detection off.
|
||||||
end
|
end
|
||||||
|
|
||||||
-- @param Wrapper.Controllable#CONTROLLABLE AIControllable
|
--- @param Wrapper.Controllable#CONTROLLABLE AIControllable
|
||||||
function _NewEngageRoute( AIControllable )
|
function _NewEngageRoute( AIControllable )
|
||||||
|
|
||||||
AIControllable:T( "NewEngageRoute" )
|
AIControllable:T( "NewEngageRoute" )
|
||||||
@@ -416,7 +418,7 @@ function _NewEngageRoute( AIControllable )
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- @param #AI_BAI_ZONE self
|
--- @param #AI_BAI_ZONE self
|
||||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||||
-- @param #string From The From State string.
|
-- @param #string From The From State string.
|
||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
@@ -428,7 +430,7 @@ function AI_BAI_ZONE:onbeforeEngage( Controllable, From, Event, To )
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- @param #AI_BAI_ZONE self
|
--- @param #AI_BAI_ZONE self
|
||||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||||
-- @param #string From The From State string.
|
-- @param #string From The From State string.
|
||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
@@ -477,7 +479,7 @@ function AI_BAI_ZONE:onafterTarget( Controllable, From, Event, To )
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- @param #AI_BAI_ZONE self
|
--- @param #AI_BAI_ZONE self
|
||||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||||
-- @param #string From The From State string.
|
-- @param #string From The From State string.
|
||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
@@ -487,7 +489,7 @@ function AI_BAI_ZONE:onafterAbort( Controllable, From, Event, To )
|
|||||||
self:__Route( 1 )
|
self:__Route( 1 )
|
||||||
end
|
end
|
||||||
|
|
||||||
-- @param #AI_BAI_ZONE self
|
--- @param #AI_BAI_ZONE self
|
||||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||||
-- @param #string From The From State string.
|
-- @param #string From The From State string.
|
||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
@@ -611,7 +613,7 @@ function AI_BAI_ZONE:onafterEngage( Controllable, From, Event, To,
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- @param #AI_BAI_ZONE self
|
--- @param #AI_BAI_ZONE self
|
||||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||||
-- @param #string From The From State string.
|
-- @param #string From The From State string.
|
||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
@@ -622,7 +624,7 @@ function AI_BAI_ZONE:onafterAccomplish( Controllable, From, Event, To )
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- @param #AI_BAI_ZONE self
|
--- @param #AI_BAI_ZONE self
|
||||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||||
-- @param #string From The From State string.
|
-- @param #string From The From State string.
|
||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
@@ -636,7 +638,7 @@ function AI_BAI_ZONE:onafterDestroy( Controllable, From, Event, To, EventData )
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- @param #AI_BAI_ZONE self
|
--- @param #AI_BAI_ZONE self
|
||||||
-- @param Core.Event#EVENTDATA EventData
|
-- @param Core.Event#EVENTDATA EventData
|
||||||
function AI_BAI_ZONE:OnEventDead( EventData )
|
function AI_BAI_ZONE:OnEventDead( EventData )
|
||||||
self:F( { "EventDead", EventData } )
|
self:F( { "EventDead", EventData } )
|
||||||
|
|||||||
@@ -27,14 +27,15 @@
|
|||||||
-- @module AI.AI_Balancer
|
-- @module AI.AI_Balancer
|
||||||
-- @image AI_Balancing.JPG
|
-- @image AI_Balancing.JPG
|
||||||
|
|
||||||
-- @type AI_BALANCER
|
--- @type AI_BALANCER
|
||||||
-- @field Core.Set#SET_CLIENT SetClient
|
-- @field Core.Set#SET_CLIENT SetClient
|
||||||
-- @field Core.Spawn#SPAWN SpawnAI
|
-- @field Core.Spawn#SPAWN SpawnAI
|
||||||
-- @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.
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
-- @module AI.AI_CAP
|
-- @module AI.AI_CAP
|
||||||
-- @image AI_Combat_Air_Patrol.JPG
|
-- @image AI_Combat_Air_Patrol.JPG
|
||||||
|
|
||||||
-- @type AI_CAP_ZONE
|
--- @type AI_CAP_ZONE
|
||||||
-- @field Wrapper.Controllable#CONTROLLABLE AIControllable The @{Wrapper.Controllable} patrolling.
|
-- @field Wrapper.Controllable#CONTROLLABLE AIControllable The @{Wrapper.Controllable} patrolling.
|
||||||
-- @field Core.Zone#ZONE_BASE TargetZone The @{Core.Zone} where the patrol needs to be executed.
|
-- @field Core.Zone#ZONE_BASE TargetZone The @{Core.Zone} where the patrol needs to be executed.
|
||||||
-- @extends AI.AI_Patrol#AI_PATROL_ZONE
|
-- @extends AI.AI_Patrol#AI_PATROL_ZONE
|
||||||
@@ -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.
|
||||||
@@ -344,7 +346,7 @@ function AI_CAP_ZONE:onafterStart( Controllable, From, Event, To )
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- @param AI.AI_CAP#AI_CAP_ZONE
|
--- @param AI.AI_CAP#AI_CAP_ZONE
|
||||||
-- @param Wrapper.Group#GROUP EngageGroup
|
-- @param Wrapper.Group#GROUP EngageGroup
|
||||||
function AI_CAP_ZONE.EngageRoute( EngageGroup, Fsm )
|
function AI_CAP_ZONE.EngageRoute( EngageGroup, Fsm )
|
||||||
|
|
||||||
@@ -355,7 +357,7 @@ function AI_CAP_ZONE.EngageRoute( EngageGroup, Fsm )
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- @param #AI_CAP_ZONE self
|
--- @param #AI_CAP_ZONE self
|
||||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||||
-- @param #string From The From State string.
|
-- @param #string From The From State string.
|
||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
@@ -367,7 +369,7 @@ function AI_CAP_ZONE:onbeforeEngage( Controllable, From, Event, To )
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- @param #AI_CAP_ZONE self
|
--- @param #AI_CAP_ZONE self
|
||||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||||
-- @param #string From The From State string.
|
-- @param #string From The From State string.
|
||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
@@ -395,7 +397,7 @@ function AI_CAP_ZONE:onafterDetected( Controllable, From, Event, To )
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- @param #AI_CAP_ZONE self
|
--- @param #AI_CAP_ZONE self
|
||||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||||
-- @param #string From The From State string.
|
-- @param #string From The From State string.
|
||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
@@ -405,7 +407,7 @@ function AI_CAP_ZONE:onafterAbort( Controllable, From, Event, To )
|
|||||||
self:__Route( 1 )
|
self:__Route( 1 )
|
||||||
end
|
end
|
||||||
|
|
||||||
-- @param #AI_CAP_ZONE self
|
--- @param #AI_CAP_ZONE self
|
||||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||||
-- @param #string From The From State string.
|
-- @param #string From The From State string.
|
||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
@@ -505,7 +507,7 @@ function AI_CAP_ZONE:onafterEngage( Controllable, From, Event, To )
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- @param #AI_CAP_ZONE self
|
--- @param #AI_CAP_ZONE self
|
||||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||||
-- @param #string From The From State string.
|
-- @param #string From The From State string.
|
||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
@@ -515,7 +517,7 @@ function AI_CAP_ZONE:onafterAccomplish( Controllable, From, Event, To )
|
|||||||
self:SetDetectionOff()
|
self:SetDetectionOff()
|
||||||
end
|
end
|
||||||
|
|
||||||
-- @param #AI_CAP_ZONE self
|
--- @param #AI_CAP_ZONE self
|
||||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||||
-- @param #string From The From State string.
|
-- @param #string From The From State string.
|
||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
@@ -528,7 +530,7 @@ function AI_CAP_ZONE:onafterDestroy( Controllable, From, Event, To, EventData )
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- @param #AI_CAP_ZONE self
|
--- @param #AI_CAP_ZONE self
|
||||||
-- @param Core.Event#EVENTDATA EventData
|
-- @param Core.Event#EVENTDATA EventData
|
||||||
function AI_CAP_ZONE:OnEventDead( EventData )
|
function AI_CAP_ZONE:OnEventDead( EventData )
|
||||||
self:F( { "EventDead", EventData } )
|
self:F( { "EventDead", EventData } )
|
||||||
|
|||||||
@@ -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.
|
||||||
--
|
--
|
||||||
-- 
|
-- 
|
||||||
@@ -162,6 +165,7 @@ function AI_CAS_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude
|
|||||||
-- @param #string From The From State string.
|
-- @param #string From The From State string.
|
||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
-- @param #string To The To State string.
|
-- @param #string To The To State string.
|
||||||
|
|
||||||
-- @return #boolean Return false to cancel Transition.
|
-- @return #boolean Return false to cancel Transition.
|
||||||
|
|
||||||
--- OnAfter Transition Handler for Event Engage.
|
--- OnAfter Transition Handler for Event Engage.
|
||||||
@@ -362,7 +366,7 @@ function AI_CAS_ZONE:onafterStart( Controllable, From, Event, To )
|
|||||||
self:SetDetectionDeactivated() -- When not engaging, set the detection off.
|
self:SetDetectionDeactivated() -- When not engaging, set the detection off.
|
||||||
end
|
end
|
||||||
|
|
||||||
-- @param AI.AI_CAS#AI_CAS_ZONE
|
--- @param AI.AI_CAS#AI_CAS_ZONE
|
||||||
-- @param Wrapper.Group#GROUP EngageGroup
|
-- @param Wrapper.Group#GROUP EngageGroup
|
||||||
function AI_CAS_ZONE.EngageRoute( EngageGroup, Fsm )
|
function AI_CAS_ZONE.EngageRoute( EngageGroup, Fsm )
|
||||||
|
|
||||||
@@ -374,7 +378,7 @@ function AI_CAS_ZONE.EngageRoute( EngageGroup, Fsm )
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- @param #AI_CAS_ZONE self
|
--- @param #AI_CAS_ZONE self
|
||||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||||
-- @param #string From The From State string.
|
-- @param #string From The From State string.
|
||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
@@ -386,7 +390,7 @@ function AI_CAS_ZONE:onbeforeEngage( Controllable, From, Event, To )
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- @param #AI_CAS_ZONE self
|
--- @param #AI_CAS_ZONE self
|
||||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||||
-- @param #string From The From State string.
|
-- @param #string From The From State string.
|
||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
@@ -419,7 +423,7 @@ function AI_CAS_ZONE:onafterTarget( Controllable, From, Event, To )
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- @param #AI_CAS_ZONE self
|
--- @param #AI_CAS_ZONE self
|
||||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||||
-- @param #string From The From State string.
|
-- @param #string From The From State string.
|
||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
@@ -429,7 +433,7 @@ function AI_CAS_ZONE:onafterAbort( Controllable, From, Event, To )
|
|||||||
self:__Route( 1 )
|
self:__Route( 1 )
|
||||||
end
|
end
|
||||||
|
|
||||||
-- @param #AI_CAS_ZONE self
|
--- @param #AI_CAS_ZONE self
|
||||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||||
-- @param #string From The From State string.
|
-- @param #string From The From State string.
|
||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
@@ -529,7 +533,7 @@ function AI_CAS_ZONE:onafterEngage( Controllable, From, Event, To,
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- @param #AI_CAS_ZONE self
|
--- @param #AI_CAS_ZONE self
|
||||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||||
-- @param #string From The From State string.
|
-- @param #string From The From State string.
|
||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
@@ -540,7 +544,7 @@ function AI_CAS_ZONE:onafterAccomplish( Controllable, From, Event, To )
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- @param #AI_CAS_ZONE self
|
--- @param #AI_CAS_ZONE self
|
||||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||||
-- @param #string From The From State string.
|
-- @param #string From The From State string.
|
||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
@@ -554,7 +558,7 @@ function AI_CAS_ZONE:onafterDestroy( Controllable, From, Event, To, EventData )
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- @param #AI_CAS_ZONE self
|
--- @param #AI_CAS_ZONE self
|
||||||
-- @param Core.Event#EVENTDATA EventData
|
-- @param Core.Event#EVENTDATA EventData
|
||||||
function AI_CAS_ZONE:OnEventDead( EventData )
|
function AI_CAS_ZONE:OnEventDead( EventData )
|
||||||
self:F( { "EventDead", EventData } )
|
self:F( { "EventDead", EventData } )
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -9,12 +9,14 @@
|
|||||||
-- @module AI.AI_Cargo_APC
|
-- @module AI.AI_Cargo_APC
|
||||||
-- @image AI_Cargo_Dispatching_For_APC.JPG
|
-- @image AI_Cargo_Dispatching_For_APC.JPG
|
||||||
|
|
||||||
-- @type AI_CARGO_APC
|
--- @type AI_CARGO_APC
|
||||||
-- @extends AI.AI_Cargo#AI_CARGO
|
-- @extends AI.AI_Cargo#AI_CARGO
|
||||||
|
|
||||||
|
|
||||||
--- 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.
|
||||||
|
|||||||
@@ -9,11 +9,13 @@
|
|||||||
-- @module AI.AI_Cargo_Airplane
|
-- @module AI.AI_Cargo_Airplane
|
||||||
-- @image AI_Cargo_Dispatching_For_Airplanes.JPG
|
-- @image AI_Cargo_Dispatching_For_Airplanes.JPG
|
||||||
|
|
||||||
-- @type AI_CARGO_AIRPLANE
|
--- @type AI_CARGO_AIRPLANE
|
||||||
-- @extends Core.Fsm#FSM_CONTROLLABLE
|
-- @extends Core.Fsm#FSM_CONTROLLABLE
|
||||||
|
|
||||||
|
|
||||||
--- 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.
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -30,12 +30,14 @@
|
|||||||
-- @module AI.AI_Cargo_Dispatcher_APC
|
-- @module AI.AI_Cargo_Dispatcher_APC
|
||||||
-- @image AI_Cargo_Dispatching_For_APC.JPG
|
-- @image AI_Cargo_Dispatching_For_APC.JPG
|
||||||
|
|
||||||
-- @type AI_CARGO_DISPATCHER_APC
|
--- @type AI_CARGO_DISPATCHER_APC
|
||||||
-- @extends AI.AI_Cargo_Dispatcher#AI_CARGO_DISPATCHER
|
-- @extends AI.AI_Cargo_Dispatcher#AI_CARGO_DISPATCHER
|
||||||
|
|
||||||
|
|
||||||
--- 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.
|
||||||
|
|||||||
@@ -24,12 +24,14 @@
|
|||||||
-- @image AI_Cargo_Dispatching_For_Airplanes.JPG
|
-- @image AI_Cargo_Dispatching_For_Airplanes.JPG
|
||||||
|
|
||||||
|
|
||||||
-- @type AI_CARGO_DISPATCHER_AIRPLANE
|
--- @type AI_CARGO_DISPATCHER_AIRPLANE
|
||||||
-- @extends AI.AI_Cargo_Dispatcher#AI_CARGO_DISPATCHER
|
-- @extends AI.AI_Cargo_Dispatcher#AI_CARGO_DISPATCHER
|
||||||
|
|
||||||
|
|
||||||
--- 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.
|
||||||
|
|||||||
@@ -25,12 +25,14 @@
|
|||||||
-- @module AI.AI_Cargo_Dispatcher_Helicopter
|
-- @module AI.AI_Cargo_Dispatcher_Helicopter
|
||||||
-- @image AI_Cargo_Dispatching_For_Helicopters.JPG
|
-- @image AI_Cargo_Dispatching_For_Helicopters.JPG
|
||||||
|
|
||||||
-- @type AI_CARGO_DISPATCHER_HELICOPTER
|
--- @type AI_CARGO_DISPATCHER_HELICOPTER
|
||||||
-- @extends AI.AI_Cargo_Dispatcher#AI_CARGO_DISPATCHER
|
-- @extends AI.AI_Cargo_Dispatcher#AI_CARGO_DISPATCHER
|
||||||
|
|
||||||
|
|
||||||
--- 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.
|
||||||
--
|
--
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -23,12 +23,14 @@
|
|||||||
-- @module AI.AI_Cargo_Dispatcher_Ship
|
-- @module AI.AI_Cargo_Dispatcher_Ship
|
||||||
-- @image AI_Cargo_Dispatcher.JPG
|
-- @image AI_Cargo_Dispatcher.JPG
|
||||||
|
|
||||||
-- @type AI_CARGO_DISPATCHER_SHIP
|
--- @type AI_CARGO_DISPATCHER_SHIP
|
||||||
-- @extends AI.AI_Cargo_Dispatcher#AI_CARGO_DISPATCHER
|
-- @extends AI.AI_Cargo_Dispatcher#AI_CARGO_DISPATCHER
|
||||||
|
|
||||||
|
|
||||||
--- 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.
|
||||||
@@ -160,7 +162,7 @@ AI_CARGO_DISPATCHER_SHIP = {
|
|||||||
-- local SetPickupZones = SET_ZONE:New():FilterPrefixes( "Pickup" ):FilterStart()
|
-- local SetPickupZones = SET_ZONE:New():FilterPrefixes( "Pickup" ):FilterStart()
|
||||||
-- local SetDeployZones = SET_ZONE:New():FilterPrefixes( "Deploy" ):FilterStart()
|
-- local SetDeployZones = SET_ZONE:New():FilterPrefixes( "Deploy" ):FilterStart()
|
||||||
-- NEED MORE THOUGHT - ShippingLane is part of Warehouse.......
|
-- NEED MORE THOUGHT - ShippingLane is part of Warehouse.......
|
||||||
-- local ShippingLane = SET_GROUP:New():FilterPrefixes( "ShippingLane" ):FilterOnce():GetSetObjects()
|
-- local ShippingLane = GROUP:New():FilterPrefixes( "ShippingLane" ):FilterStart()
|
||||||
--
|
--
|
||||||
-- AICargoDispatcherShip = AI_CARGO_DISPATCHER_SHIP:New( SetShip, SetCargoInfantry, SetPickupZones, SetDeployZones, ShippingLane )
|
-- AICargoDispatcherShip = AI_CARGO_DISPATCHER_SHIP:New( SetShip, SetCargoInfantry, SetPickupZones, SetDeployZones, ShippingLane )
|
||||||
-- AICargoDispatcherShip:Start()
|
-- AICargoDispatcherShip:Start()
|
||||||
|
|||||||
@@ -9,12 +9,14 @@
|
|||||||
-- @module AI.AI_Cargo_Helicopter
|
-- @module AI.AI_Cargo_Helicopter
|
||||||
-- @image AI_Cargo_Dispatching_For_Helicopters.JPG
|
-- @image AI_Cargo_Dispatching_For_Helicopters.JPG
|
||||||
|
|
||||||
-- @type AI_CARGO_HELICOPTER
|
--- @type AI_CARGO_HELICOPTER
|
||||||
-- @extends Core.Fsm#FSM_CONTROLLABLE
|
-- @extends Core.Fsm#FSM_CONTROLLABLE
|
||||||
|
|
||||||
|
|
||||||
--- 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.
|
||||||
@@ -287,7 +289,7 @@ function AI_CARGO_HELICOPTER:SetLandingSpeedAndHeight(speed, height)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
-- @param #AI_CARGO_HELICOPTER self
|
--- @param #AI_CARGO_HELICOPTER self
|
||||||
-- @param Wrapper.Group#GROUP Helicopter
|
-- @param Wrapper.Group#GROUP Helicopter
|
||||||
-- @param From
|
-- @param From
|
||||||
-- @param Event
|
-- @param Event
|
||||||
@@ -326,7 +328,7 @@ function AI_CARGO_HELICOPTER:onafterLanded( Helicopter, From, Event, To )
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- @param #AI_CARGO_HELICOPTER self
|
--- @param #AI_CARGO_HELICOPTER self
|
||||||
-- @param Wrapper.Group#GROUP Helicopter
|
-- @param Wrapper.Group#GROUP Helicopter
|
||||||
-- @param From
|
-- @param From
|
||||||
-- @param Event
|
-- @param Event
|
||||||
@@ -409,7 +411,7 @@ function AI_CARGO_HELICOPTER:onafterQueue( Helicopter, From, Event, To, Coordina
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- @param #AI_CARGO_HELICOPTER self
|
--- @param #AI_CARGO_HELICOPTER self
|
||||||
-- @param Wrapper.Group#GROUP Helicopter
|
-- @param Wrapper.Group#GROUP Helicopter
|
||||||
-- @param From
|
-- @param From
|
||||||
-- @param Event
|
-- @param Event
|
||||||
|
|||||||
@@ -9,11 +9,13 @@
|
|||||||
-- @module AI.AI_Cargo_Ship
|
-- @module AI.AI_Cargo_Ship
|
||||||
-- @image AI_Cargo_Dispatcher.JPG
|
-- @image AI_Cargo_Dispatcher.JPG
|
||||||
|
|
||||||
-- @type AI_CARGO_SHIP
|
--- @type AI_CARGO_SHIP
|
||||||
-- @extends AI.AI_Cargo#AI_CARGO
|
-- @extends AI.AI_Cargo#AI_CARGO
|
||||||
|
|
||||||
--- 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
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -15,12 +15,14 @@
|
|||||||
-- @image MOOSE.JPG
|
-- @image MOOSE.JPG
|
||||||
|
|
||||||
|
|
||||||
-- @type AI_ESCORT_DISPATCHER_REQUEST
|
--- @type AI_ESCORT_DISPATCHER_REQUEST
|
||||||
-- @extends Core.Fsm#FSM
|
-- @extends Core.Fsm#FSM
|
||||||
|
|
||||||
|
|
||||||
--- 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
|
||||||
@@ -33,7 +35,7 @@ AI_ESCORT_DISPATCHER_REQUEST = {
|
|||||||
ClassName = "AI_ESCORT_DISPATCHER_REQUEST",
|
ClassName = "AI_ESCORT_DISPATCHER_REQUEST",
|
||||||
}
|
}
|
||||||
|
|
||||||
-- @field #list
|
--- @field #list
|
||||||
AI_ESCORT_DISPATCHER_REQUEST.AI_Escorts = {}
|
AI_ESCORT_DISPATCHER_REQUEST.AI_Escorts = {}
|
||||||
|
|
||||||
|
|
||||||
@@ -80,7 +82,7 @@ function AI_ESCORT_DISPATCHER_REQUEST:onafterStart( From, Event, To )
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- @param #AI_ESCORT_DISPATCHER_REQUEST self
|
--- @param #AI_ESCORT_DISPATCHER_REQUEST self
|
||||||
-- @param Core.Event#EVENTDATA EventData
|
-- @param Core.Event#EVENTDATA EventData
|
||||||
function AI_ESCORT_DISPATCHER_REQUEST:OnEventExit( EventData )
|
function AI_ESCORT_DISPATCHER_REQUEST:OnEventExit( EventData )
|
||||||
|
|
||||||
@@ -97,7 +99,7 @@ function AI_ESCORT_DISPATCHER_REQUEST:OnEventExit( EventData )
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- @param #AI_ESCORT_DISPATCHER_REQUEST self
|
--- @param #AI_ESCORT_DISPATCHER_REQUEST self
|
||||||
-- @param Core.Event#EVENTDATA EventData
|
-- @param Core.Event#EVENTDATA EventData
|
||||||
function AI_ESCORT_DISPATCHER_REQUEST:OnEventBirth( EventData )
|
function AI_ESCORT_DISPATCHER_REQUEST:OnEventBirth( EventData )
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
||||||
@@ -136,12 +138,12 @@
|
|||||||
--
|
--
|
||||||
-- Escort groups can have their own mission. This menu item will allow the escort group to resume their Mission from a given waypoint.
|
-- Escort groups can have their own mission. This menu item will allow the escort group to resume their Mission from a given waypoint.
|
||||||
-- Note that this is really fantastic, as you now have the dynamic of taking control of the escort groups, and allowing them to resume their path or mission.
|
-- Note that this is really fantastic, as you now have the dynamic of taking control of the escort groups, and allowing them to resume their path or mission.
|
||||||
--
|
--
|
||||||
-- # 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
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ### Authors: **FlightControl**
|
-- ### Authors: **FlightControl**
|
||||||
@@ -153,7 +155,7 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
-- @type AI_ESCORT_REQUEST
|
--- @type AI_ESCORT_REQUEST
|
||||||
-- @extends AI.AI_Escort#AI_ESCORT
|
-- @extends AI.AI_Escort#AI_ESCORT
|
||||||
|
|
||||||
--- AI_ESCORT_REQUEST class
|
--- AI_ESCORT_REQUEST class
|
||||||
@@ -228,7 +230,7 @@ function AI_ESCORT_REQUEST:New( EscortUnit, EscortSpawn, EscortAirbase, EscortNa
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
-- @param #AI_ESCORT_REQUEST self
|
--- @param #AI_ESCORT_REQUEST self
|
||||||
function AI_ESCORT_REQUEST:SpawnEscort()
|
function AI_ESCORT_REQUEST:SpawnEscort()
|
||||||
|
|
||||||
local EscortGroup = self.EscortSpawn:SpawnAtAirbase( self.EscortAirbase, SPAWN.Takeoff.Hot )
|
local EscortGroup = self.EscortSpawn:SpawnAtAirbase( self.EscortAirbase, SPAWN.Takeoff.Hot )
|
||||||
@@ -253,7 +255,7 @@ function AI_ESCORT_REQUEST:SpawnEscort()
|
|||||||
self:_InitEscortMenus( EscortGroup )
|
self:_InitEscortMenus( EscortGroup )
|
||||||
self:_InitEscortRoute( EscortGroup )
|
self:_InitEscortRoute( EscortGroup )
|
||||||
|
|
||||||
-- @param #AI_ESCORT self
|
--- @param #AI_ESCORT self
|
||||||
-- @param Core.Event#EVENTDATA EventData
|
-- @param Core.Event#EVENTDATA EventData
|
||||||
function EscortGroup:OnEventDeadOrCrash( EventData )
|
function EscortGroup:OnEventDeadOrCrash( EventData )
|
||||||
self:F( { "EventDead", EventData } )
|
self:F( { "EventDead", EventData } )
|
||||||
@@ -268,7 +270,7 @@ function AI_ESCORT_REQUEST:SpawnEscort()
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- @param #AI_ESCORT_REQUEST self
|
--- @param #AI_ESCORT_REQUEST self
|
||||||
-- @param Core.Set#SET_GROUP EscortGroupSet
|
-- @param Core.Set#SET_GROUP EscortGroupSet
|
||||||
function AI_ESCORT_REQUEST:onafterStart( EscortGroupSet )
|
function AI_ESCORT_REQUEST:onafterStart( EscortGroupSet )
|
||||||
|
|
||||||
@@ -290,14 +292,14 @@ function AI_ESCORT_REQUEST:onafterStart( EscortGroupSet )
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- @param #AI_ESCORT_REQUEST self
|
--- @param #AI_ESCORT_REQUEST self
|
||||||
-- @param Core.Set#SET_GROUP EscortGroupSet
|
-- @param Core.Set#SET_GROUP EscortGroupSet
|
||||||
function AI_ESCORT_REQUEST:onafterStop( EscortGroupSet )
|
function AI_ESCORT_REQUEST:onafterStop( EscortGroupSet )
|
||||||
|
|
||||||
self:F()
|
self:F()
|
||||||
|
|
||||||
EscortGroupSet:ForEachGroup(
|
EscortGroupSet:ForEachGroup(
|
||||||
-- @param Core.Group#GROUP EscortGroup
|
--- @param Wrapper.Group#GROUP EscortGroup
|
||||||
function( EscortGroup )
|
function( EscortGroup )
|
||||||
EscortGroup:WayPointInitialize()
|
EscortGroup:WayPointInitialize()
|
||||||
|
|
||||||
|
|||||||
@@ -34,12 +34,14 @@
|
|||||||
-- @field Core.Scheduler#SCHEDULER FollowScheduler The instance of the SCHEDULER class.
|
-- @field Core.Scheduler#SCHEDULER FollowScheduler The instance of the SCHEDULER class.
|
||||||
-- @field #number FollowDistance The current follow distance.
|
-- @field #number FollowDistance The current follow distance.
|
||||||
-- @field #boolean ReportTargets If true, nearby targets are reported.
|
-- @field #boolean ReportTargets If true, nearby targets are reported.
|
||||||
-- @Field DCSTypes#AI.Option.Air.val.ROE OptionROE Which ROE is set to the FollowGroup.
|
-- @field DCS#AI.Option.Air.val.ROE OptionROE Which ROE is set to the FollowGroup.
|
||||||
-- @field DCSTypes#AI.Option.Air.val.REACTION_ON_THREAT OptionReactionOnThreat Which REACTION_ON_THREAT is set to the FollowGroup.
|
-- @field DCS#AI.Option.Air.val.REACTION_ON_THREAT OptionReactionOnThreat Which REACTION_ON_THREAT is set to the FollowGroup.
|
||||||
-- @field #number dtFollow Time step between position updates.
|
-- @field #number dtFollow Time step between position updates.
|
||||||
|
|
||||||
|
|
||||||
--- 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!!!
|
||||||
@@ -92,12 +94,12 @@
|
|||||||
-- local LargeFormation = AI_FORMATION:New( LeaderUnit, FollowGroupSet, "Center Wing Formation", "Briefing" )
|
-- local LargeFormation = AI_FORMATION:New( LeaderUnit, FollowGroupSet, "Center Wing Formation", "Briefing" )
|
||||||
-- LargeFormation:FormationCenterWing( 500, 50, 0, 250, 250 )
|
-- LargeFormation:FormationCenterWing( 500, 50, 0, 250, 250 )
|
||||||
-- LargeFormation:__Start( 1 )
|
-- LargeFormation:__Start( 1 )
|
||||||
--
|
--
|
||||||
-- # 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
|
||||||
--
|
--
|
||||||
-- @field #AI_FORMATION
|
-- @field #AI_FORMATION
|
||||||
AI_FORMATION = {
|
AI_FORMATION = {
|
||||||
ClassName = "AI_FORMATION",
|
ClassName = "AI_FORMATION",
|
||||||
@@ -117,7 +119,7 @@ AI_FORMATION = {
|
|||||||
|
|
||||||
AI_FORMATION.__Enum = {}
|
AI_FORMATION.__Enum = {}
|
||||||
|
|
||||||
-- @type AI_FORMATION.__Enum.Formation
|
--- @type AI_FORMATION.__Enum.Formation
|
||||||
-- @field #number None
|
-- @field #number None
|
||||||
-- @field #number Line
|
-- @field #number Line
|
||||||
-- @field #number Trail
|
-- @field #number Trail
|
||||||
@@ -142,7 +144,7 @@ AI_FORMATION.__Enum.Formation = {
|
|||||||
Box = 10,
|
Box = 10,
|
||||||
}
|
}
|
||||||
|
|
||||||
-- @type AI_FORMATION.__Enum.Mode
|
--- @type AI_FORMATION.__Enum.Mode
|
||||||
-- @field #number Mission
|
-- @field #number Mission
|
||||||
-- @field #number Formation
|
-- @field #number Formation
|
||||||
AI_FORMATION.__Enum.Mode = {
|
AI_FORMATION.__Enum.Mode = {
|
||||||
@@ -152,13 +154,12 @@ AI_FORMATION.__Enum.Mode = {
|
|||||||
Reconnaissance = "R",
|
Reconnaissance = "R",
|
||||||
}
|
}
|
||||||
|
|
||||||
-- @type AI_FORMATION.__Enum.ReportType
|
--- @type AI_FORMATION.__Enum.ReportType
|
||||||
-- @field #number All
|
-- @field #number All
|
||||||
-- @field #number Airborne
|
-- @field #number Airborne
|
||||||
-- @field #number GroundRadar
|
-- @field #number GroundRadar
|
||||||
-- @field #number Ground
|
-- @field #number Ground
|
||||||
AI_FORMATION.__Enum.ReportType = {
|
AI_FORMATION.__Enum.ReportType = {
|
||||||
All = "*",
|
|
||||||
Airborne = "A",
|
Airborne = "A",
|
||||||
GroundRadar = "R",
|
GroundRadar = "R",
|
||||||
Ground = "G",
|
Ground = "G",
|
||||||
@@ -996,7 +997,7 @@ function AI_FORMATION:SetFlightModeMission( FollowGroup )
|
|||||||
FollowGroup:SetState( FollowGroup, "Mode", self.__Enum.Mode.Mission )
|
FollowGroup:SetState( FollowGroup, "Mode", self.__Enum.Mode.Mission )
|
||||||
else
|
else
|
||||||
self.FollowGroupSet:ForSomeGroupAlive(
|
self.FollowGroupSet:ForSomeGroupAlive(
|
||||||
-- @param Core.Group#GROUP EscortGroup
|
--- @param Wrapper.Group#GROUP EscortGroup
|
||||||
function( FollowGroup )
|
function( FollowGroup )
|
||||||
FollowGroup:SetState( FollowGroup, "PreviousMode", FollowGroup:GetState( FollowGroup, "Mode" ) )
|
FollowGroup:SetState( FollowGroup, "PreviousMode", FollowGroup:GetState( FollowGroup, "Mode" ) )
|
||||||
FollowGroup:SetState( FollowGroup, "Mode", self.__Enum.Mode.Mission )
|
FollowGroup:SetState( FollowGroup, "Mode", self.__Enum.Mode.Mission )
|
||||||
@@ -1020,7 +1021,7 @@ function AI_FORMATION:SetFlightModeAttack( FollowGroup )
|
|||||||
FollowGroup:SetState( FollowGroup, "Mode", self.__Enum.Mode.Attack )
|
FollowGroup:SetState( FollowGroup, "Mode", self.__Enum.Mode.Attack )
|
||||||
else
|
else
|
||||||
self.FollowGroupSet:ForSomeGroupAlive(
|
self.FollowGroupSet:ForSomeGroupAlive(
|
||||||
-- @param Core.Group#GROUP EscortGroup
|
--- @param Wrapper.Group#GROUP EscortGroup
|
||||||
function( FollowGroup )
|
function( FollowGroup )
|
||||||
FollowGroup:SetState( FollowGroup, "PreviousMode", FollowGroup:GetState( FollowGroup, "Mode" ) )
|
FollowGroup:SetState( FollowGroup, "PreviousMode", FollowGroup:GetState( FollowGroup, "Mode" ) )
|
||||||
FollowGroup:SetState( FollowGroup, "Mode", self.__Enum.Mode.Attack )
|
FollowGroup:SetState( FollowGroup, "Mode", self.__Enum.Mode.Attack )
|
||||||
@@ -1044,7 +1045,7 @@ function AI_FORMATION:SetFlightModeFormation( FollowGroup )
|
|||||||
FollowGroup:SetState( FollowGroup, "Mode", self.__Enum.Mode.Formation )
|
FollowGroup:SetState( FollowGroup, "Mode", self.__Enum.Mode.Formation )
|
||||||
else
|
else
|
||||||
self.FollowGroupSet:ForSomeGroupAlive(
|
self.FollowGroupSet:ForSomeGroupAlive(
|
||||||
-- @param Core.Group#GROUP EscortGroup
|
--- @param Wrapper.Group#GROUP EscortGroup
|
||||||
function( FollowGroup )
|
function( FollowGroup )
|
||||||
FollowGroup:SetState( FollowGroup, "PreviousMode", FollowGroup:GetState( FollowGroup, "Mode" ) )
|
FollowGroup:SetState( FollowGroup, "PreviousMode", FollowGroup:GetState( FollowGroup, "Mode" ) )
|
||||||
FollowGroup:SetState( FollowGroup, "Mode", self.__Enum.Mode.Formation )
|
FollowGroup:SetState( FollowGroup, "Mode", self.__Enum.Mode.Formation )
|
||||||
@@ -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.
|
||||||
--
|
--
|
||||||
-- 
|
-- 
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
@@ -8,9 +8,11 @@
|
|||||||
-- @image MOOSE.JPG
|
-- @image MOOSE.JPG
|
||||||
|
|
||||||
do -- ACT_ACCOUNT
|
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
|
||||||
@@ -274,7 +276,7 @@ do -- ACT_ACCOUNT_DEADS
|
|||||||
|
|
||||||
--- DCS Events
|
--- DCS Events
|
||||||
|
|
||||||
-- @param #ACT_ACCOUNT_DEADS self
|
--- @param #ACT_ACCOUNT_DEADS self
|
||||||
-- @param Core.Event#EVENTDATA EventData
|
-- @param Core.Event#EVENTDATA EventData
|
||||||
function ACT_ACCOUNT_DEADS:OnEventHit( EventData )
|
function ACT_ACCOUNT_DEADS:OnEventHit( EventData )
|
||||||
self:T( { "EventDead", EventData } )
|
self:T( { "EventDead", EventData } )
|
||||||
@@ -285,7 +287,7 @@ do -- ACT_ACCOUNT_DEADS
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- @param #ACT_ACCOUNT_DEADS self
|
--- @param #ACT_ACCOUNT_DEADS self
|
||||||
-- @param Core.Event#EVENTDATA EventData
|
-- @param Core.Event#EVENTDATA EventData
|
||||||
function ACT_ACCOUNT_DEADS:onfuncEventDead( EventData )
|
function ACT_ACCOUNT_DEADS:onfuncEventDead( EventData )
|
||||||
self:T( { "EventDead", EventData } )
|
self:T( { "EventDead", EventData } )
|
||||||
@@ -297,7 +299,7 @@ do -- ACT_ACCOUNT_DEADS
|
|||||||
|
|
||||||
--- DCS Events
|
--- DCS Events
|
||||||
|
|
||||||
-- @param #ACT_ACCOUNT_DEADS self
|
--- @param #ACT_ACCOUNT_DEADS self
|
||||||
-- @param Core.Event#EVENTDATA EventData
|
-- @param Core.Event#EVENTDATA EventData
|
||||||
function ACT_ACCOUNT_DEADS:onfuncEventCrash( EventData )
|
function ACT_ACCOUNT_DEADS:onfuncEventCrash( EventData )
|
||||||
self:T( { "EventDead", EventData } )
|
self:T( { "EventDead", EventData } )
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
--- (SP) (MP) (FSM) Accept or reject process for player (task) assignments.
|
--- (SP) (MP) (FSM) Accept or reject process for player (task) assignments.
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
|
--
|
||||||
|
-- 
|
||||||
--
|
--
|
||||||
-- # @{#ACT_ASSIGN} FSM template class, extends @{Core.Fsm#FSM_PROCESS}
|
-- # @{#ACT_ASSIGN} FSM template class, extends @{Core.Fsm#FSM_PROCESS}
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -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.
|
||||||
@@ -200,7 +201,7 @@ do -- ACT_ASSIST_SMOKE_TARGETS_ZONE
|
|||||||
function ACT_ASSIST_SMOKE_TARGETS_ZONE:onenterSmoking( ProcessUnit, From, Event, To )
|
function ACT_ASSIST_SMOKE_TARGETS_ZONE:onenterSmoking( ProcessUnit, From, Event, To )
|
||||||
|
|
||||||
self.TargetSetUnit:ForEachUnit(
|
self.TargetSetUnit:ForEachUnit(
|
||||||
-- @param Wrapper.Unit#UNIT SmokeUnit
|
--- @param Wrapper.Unit#UNIT SmokeUnit
|
||||||
function( SmokeUnit )
|
function( SmokeUnit )
|
||||||
if math.random( 1, ( 100 * self.TargetSetUnit:Count() ) / 4 ) <= 100 then
|
if math.random( 1, ( 100 * self.TargetSetUnit:Count() ) / 4 ) <= 100 then
|
||||||
SCHEDULER:New( self,
|
SCHEDULER:New( self,
|
||||||
|
|||||||
@@ -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.
|
||||||
--
|
--
|
||||||
@@ -78,7 +81,7 @@ do -- CARGO_CRATE
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
-- @param #CARGO_CRATE self
|
--- @param #CARGO_CRATE self
|
||||||
-- @param Core.Event#EVENTDATA EventData
|
-- @param Core.Event#EVENTDATA EventData
|
||||||
function CARGO_CRATE:OnEventCargoDead( EventData )
|
function CARGO_CRATE:OnEventCargoDead( EventData )
|
||||||
|
|
||||||
|
|||||||
@@ -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:
|
||||||
@@ -599,7 +601,7 @@ do -- CARGO_GROUP
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Get the underlying GROUP object from the CARGO_GROUP.
|
--- Get the amount of cargo units in the group.
|
||||||
-- @param #CARGO_GROUP self
|
-- @param #CARGO_GROUP self
|
||||||
-- @return #CARGO_GROUP
|
-- @return #CARGO_GROUP
|
||||||
function CARGO_GROUP:GetGroup( Cargo )
|
function CARGO_GROUP:GetGroup( 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
|
||||||
--
|
--
|
||||||
@@ -72,7 +74,7 @@ do -- CARGO_SLINGLOAD
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- @param #CARGO_SLINGLOAD self
|
--- @param #CARGO_SLINGLOAD self
|
||||||
-- @param Core.Event#EVENTDATA EventData
|
-- @param Core.Event#EVENTDATA EventData
|
||||||
function CARGO_SLINGLOAD:OnEventCargoDead( EventData )
|
function CARGO_SLINGLOAD:OnEventCargoDead( EventData )
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -157,8 +157,6 @@ ASTAR = {
|
|||||||
-- @field #number surfacetype Surface type.
|
-- @field #number surfacetype Surface type.
|
||||||
-- @field #table valid Cached valid/invalid nodes.
|
-- @field #table valid Cached valid/invalid nodes.
|
||||||
-- @field #table cost Cached cost.
|
-- @field #table cost Cached cost.
|
||||||
-- @field Core.Pathline#PATHLINE pathline Pathline that node is part of.
|
|
||||||
-- @field Core.Pathline#PATHLINE.Point pathpoint Pathline point.
|
|
||||||
|
|
||||||
--- ASTAR infinity.
|
--- ASTAR infinity.
|
||||||
-- @field #number INF
|
-- @field #number INF
|
||||||
@@ -166,7 +164,7 @@ ASTAR.INF=1/0
|
|||||||
|
|
||||||
--- ASTAR class version.
|
--- ASTAR class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
ASTAR.version="0.5.0"
|
ASTAR.version="0.4.0"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- TODO list
|
-- TODO list
|
||||||
@@ -174,7 +172,6 @@ ASTAR.version="0.5.0"
|
|||||||
|
|
||||||
-- TODO: Add more valid neighbour functions.
|
-- TODO: Add more valid neighbour functions.
|
||||||
-- TODO: Write docs.
|
-- TODO: Write docs.
|
||||||
-- DONE: Add pathlines for seach/valid neighbours.
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- Constructor
|
-- Constructor
|
||||||
@@ -247,10 +244,7 @@ end
|
|||||||
function ASTAR:AddNode(Node)
|
function ASTAR:AddNode(Node)
|
||||||
|
|
||||||
self.nodes[Node.id]=Node
|
self.nodes[Node.id]=Node
|
||||||
self.Nnodes=self.Nnodes+1
|
self.Nnodes=self.Nnodes+1
|
||||||
|
|
||||||
self:T3(self.lid..string.format("Adding node UID=%d", Node.id))
|
|
||||||
--Node.coordinate:MarkToAll(string.format("Node ID=%d", Node.id))
|
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
@@ -268,47 +262,6 @@ function ASTAR:AddNodeFromCoordinate(Coordinate)
|
|||||||
return node
|
return node
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Adds nodes to the table of grid nodes from a PATHLINE.
|
|
||||||
-- @param #ASTAR self
|
|
||||||
-- @param Core.Pathline#PATHLINE Pathline Pathline or name of pathline. Has to exist.
|
|
||||||
-- @return #ASTAR self
|
|
||||||
function ASTAR:AddNodeFromPathlineName(Pathline)
|
|
||||||
|
|
||||||
if type(Pathline)=="string" then
|
|
||||||
Pathline=PATHLINE:FindByName(Pathline)
|
|
||||||
end
|
|
||||||
|
|
||||||
if Pathline then
|
|
||||||
|
|
||||||
for i,_point in pairs(Pathline.points) do
|
|
||||||
local point=_point --Core.Pathline#PATHLINE.Point
|
|
||||||
|
|
||||||
-- Create node from point coordinate.
|
|
||||||
local node=self:AddNodeFromCoordinate(COORDINATE:NewFromVec3(point.vec3))
|
|
||||||
|
|
||||||
-- Add pathline parameters.
|
|
||||||
node.pathline=Pathline
|
|
||||||
node.pathpoint=point
|
|
||||||
|
|
||||||
-- Debug.
|
|
||||||
local name=node.pathline and node.pathline.name or "N/A"
|
|
||||||
local idx=node.pathline and node.pathline:_GetPointIndex(node.pathpoint) or "N/A"
|
|
||||||
|
|
||||||
-- Debug message.
|
|
||||||
self:T(self.lid..string.format("Adding node UID=%d pathline=%s [%s]", node.id, name, tostring(idx)))
|
|
||||||
|
|
||||||
-- Debug mark
|
|
||||||
--node.coordinate:MarkToAll(string.format("Node ID=%d\npathline=%s [%s]", node.id, name, tostring(idx)))
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
else
|
|
||||||
env.error("FF error pathline")
|
|
||||||
end
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Check if the coordinate of a node has is at a valid surface type.
|
--- Check if the coordinate of a node has is at a valid surface type.
|
||||||
-- @param #ASTAR self
|
-- @param #ASTAR self
|
||||||
-- @param #ASTAR.Node Node The node to be added.
|
-- @param #ASTAR.Node Node The node to be added.
|
||||||
@@ -387,18 +340,6 @@ function ASTAR:SetValidNeighbourRoad(MaxDistance)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Set valid neighbours to be on the same pathline or not further apart than 10 meters to jump from one pathline to another.
|
|
||||||
-- @param #ASTAR self
|
|
||||||
-- @param #number MaxDistance Max allowed distance between nodes of different pathlines in meters. Default is 10 m.
|
|
||||||
-- @return #ASTAR self
|
|
||||||
function ASTAR:SetValidNeighbourPathline(MaxDistance)
|
|
||||||
|
|
||||||
self:SetValidNeighbourFunction(ASTAR.Pathline, MaxDistance)
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
--- Set the function which calculates the "cost" to go from one to another node.
|
--- Set the function which calculates the "cost" to go from one to another node.
|
||||||
-- The first to arguments of this function are always the two nodes under consideration. But you can add optional arguments.
|
-- The first to arguments of this function are always the two nodes under consideration. But you can add optional arguments.
|
||||||
-- Very often the distance between nodes is a good measure for the cost.
|
-- Very often the distance between nodes is a good measure for the cost.
|
||||||
@@ -443,7 +384,7 @@ end
|
|||||||
-- @return #ASTAR self
|
-- @return #ASTAR self
|
||||||
function ASTAR:SetCostRoad()
|
function ASTAR:SetCostRoad()
|
||||||
|
|
||||||
self:SetCostFunction(ASTAR.Road)
|
self:SetCostFunction(ASTAR)
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
@@ -603,55 +544,6 @@ function ASTAR.Road(nodeA, nodeB)
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Function to check if two nodes are on the same pathline or if nodes are less than 10 meters apart.
|
|
||||||
-- @param #ASTAR.Node nodeA First node.
|
|
||||||
-- @param #ASTAR.Node nodeB Other node.
|
|
||||||
-- @param #number distmax Max distance in meters. Default is 10 m.
|
|
||||||
-- @return #boolean If true, two nodes are connected.
|
|
||||||
function ASTAR.Pathline(nodeA, nodeB, distmax)
|
|
||||||
|
|
||||||
distmax=distmax or 10
|
|
||||||
|
|
||||||
if nodeA.pathline.name==nodeB.pathline.name then
|
|
||||||
|
|
||||||
-- Nodes are on the same pathline. We use the index to check if they are neighbours.
|
|
||||||
|
|
||||||
local pathline=nodeA.pathline
|
|
||||||
|
|
||||||
local idxA=pathline:_GetPointIndex(nodeA.pathpoint)
|
|
||||||
local idxB=pathline:_GetPointIndex(nodeB.pathpoint)
|
|
||||||
|
|
||||||
if math.abs(idxA-idxB)<=1 then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
else
|
|
||||||
|
|
||||||
-- Check if nodeB is close to pathline of nodeA.
|
|
||||||
local c, dist, segA=nodeA.pathline:GetClosestPoint3D(nodeB.coordinate)
|
|
||||||
local seg=segA --Core.Pathline#PATHLINE.Segment
|
|
||||||
|
|
||||||
if dist<distmax and (nodeA.pathpoint.uid==seg.p1.uid or nodeA.pathpoint.uid==seg.p2.uid) then
|
|
||||||
--env.info(string.format("FF NodeB=%d [pathline=%s] is close to NodeA=%d [pathline=%s] ==> valid neighbour", nodeB.id, nodeB.pathline.name, nodeA.id, nodeA.pathline.name))
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
-- Check if nodeA is close to pathline of nodeB.
|
|
||||||
local c, dist, segB=nodeB.pathline:GetClosestPoint3D(nodeA.coordinate)
|
|
||||||
local seg=segB --Core.Pathline#PATHLINE.Segment
|
|
||||||
|
|
||||||
if dist<distmax and (nodeB.pathpoint.uid==seg.p1.uid or nodeB.pathpoint.uid==seg.p2.uid) then
|
|
||||||
--env.info(string.format("FF NodeA=%d [pathline=%s] is close to NodeB=%d [pathline=%s] ==> valid neighbour", nodeA.id, nodeA.pathline.name, nodeB.id, nodeB.pathline.name))
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
--- Function to check if distance between two nodes is less than a threshold distance.
|
--- Function to check if distance between two nodes is less than a threshold distance.
|
||||||
-- @param #ASTAR.Node nodeA First node.
|
-- @param #ASTAR.Node nodeA First node.
|
||||||
-- @param #ASTAR.Node nodeB Other node.
|
-- @param #ASTAR.Node nodeB Other node.
|
||||||
@@ -675,9 +567,7 @@ end
|
|||||||
-- @param #ASTAR.Node nodeB Other node.
|
-- @param #ASTAR.Node nodeB Other node.
|
||||||
-- @return #number Distance between the two nodes.
|
-- @return #number Distance between the two nodes.
|
||||||
function ASTAR.Dist2D(nodeA, nodeB)
|
function ASTAR.Dist2D(nodeA, nodeB)
|
||||||
local dist=nodeA.coordinate:Get2DDistance(nodeB.coordinate)
|
local dist=nodeA.coordinate:Get2DDistance(nodeB)
|
||||||
--local text=string.format("FF Cost Dist2D NodeA=%d-->NodeB=%d = %.1f", nodeA.id, nodeB.id, dist)
|
|
||||||
--env.info(text)
|
|
||||||
return dist
|
return dist
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -704,7 +594,7 @@ function ASTAR.DistRoad(nodeA, nodeB)
|
|||||||
local dist=0
|
local dist=0
|
||||||
|
|
||||||
for i=2,#path do
|
for i=2,#path do
|
||||||
local b=path[i] --DCS#Vec2
|
local b=path[i] --DCS#Vec2
|
||||||
local a=path[i-1] --DCS#Vec2
|
local a=path[i-1] --DCS#Vec2
|
||||||
|
|
||||||
dist=dist+UTILS.VecDist2D(a,b)
|
dist=dist+UTILS.VecDist2D(a,b)
|
||||||
@@ -714,6 +604,7 @@ function ASTAR.DistRoad(nodeA, nodeB)
|
|||||||
return dist
|
return dist
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
return math.huge
|
return math.huge
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -723,11 +614,10 @@ end
|
|||||||
|
|
||||||
--- Find the closest node from a given coordinate.
|
--- Find the closest node from a given coordinate.
|
||||||
-- @param #ASTAR self
|
-- @param #ASTAR self
|
||||||
-- @param Core.Point#COORDINATE Coordinate Reference coordinate.
|
-- @param Core.Point#COORDINATE Coordinate.
|
||||||
-- @param #table ExcludeNodes Table of nodes that are excluded.
|
-- @return #ASTAR.Node Cloest node to the coordinate.
|
||||||
-- @return #ASTAR.Node Closest node to the coordinate.
|
|
||||||
-- @return #number Distance to closest node in meters.
|
-- @return #number Distance to closest node in meters.
|
||||||
function ASTAR:FindClosestNode(Coordinate, ExcludeNodes)
|
function ASTAR:FindClosestNode(Coordinate)
|
||||||
|
|
||||||
local distMin=math.huge
|
local distMin=math.huge
|
||||||
local closeNode=nil
|
local closeNode=nil
|
||||||
@@ -735,15 +625,11 @@ function ASTAR:FindClosestNode(Coordinate, ExcludeNodes)
|
|||||||
for _,_node in pairs(self.nodes) do
|
for _,_node in pairs(self.nodes) do
|
||||||
local node=_node --#ASTAR.Node
|
local node=_node --#ASTAR.Node
|
||||||
|
|
||||||
if ExcludeNodes==nil or self:_IsNodeNotInTable(ExcludeNodes, node) then
|
local dist=node.coordinate:Get2DDistance(Coordinate)
|
||||||
|
|
||||||
local dist=node.coordinate:Get2DDistance(Coordinate)
|
if dist<distMin then
|
||||||
|
distMin=dist
|
||||||
if dist<distMin then
|
closeNode=node
|
||||||
distMin=dist
|
|
||||||
closeNode=node
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
@@ -751,162 +637,38 @@ function ASTAR:FindClosestNode(Coordinate, ExcludeNodes)
|
|||||||
return closeNode, distMin
|
return closeNode, distMin
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Find the closest pathline to a given reference coordinate.
|
|
||||||
-- @param #ASTAR self
|
|
||||||
-- @param Core.Point#COORDINATE Coordinate Reference coordinate.
|
|
||||||
-- @return Core.Pathline#PATHLINE Closest pathline
|
|
||||||
-- @return #number Distance in meters.
|
|
||||||
-- @return DCS#Vec3 Closest point on pathline to the ref coordinate.
|
|
||||||
-- @return Core.Pathline#PATHLINE.Segment Segment.
|
|
||||||
function ASTAR:FindClosestPathline(Coordinate)
|
|
||||||
|
|
||||||
local pathline=nil --Core.Pathline#PATHLINE
|
|
||||||
local dist=math.huge
|
|
||||||
local vec3=nil
|
|
||||||
local S=nil
|
|
||||||
|
|
||||||
for _,_node in pairs(self.nodes) do
|
|
||||||
local node=_node --#ASTAR.Node
|
|
||||||
|
|
||||||
if node.pathline then
|
|
||||||
|
|
||||||
local vec, d, s=node.pathline:GetClosestPoint3D(Coordinate)
|
|
||||||
|
|
||||||
if d<dist then
|
|
||||||
pathline=node.pathline
|
|
||||||
dist=d
|
|
||||||
vec3=vec
|
|
||||||
S=s
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if pathline then
|
|
||||||
-- Debug info.
|
|
||||||
self:T(self.lid..string.format("Closest pathline %s: dist=%.1f", pathline.name, dist))
|
|
||||||
end
|
|
||||||
|
|
||||||
return pathline, dist, vec3, S
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Find the closest node to the given coordinate.
|
|
||||||
-- @param #ASTAR self
|
|
||||||
-- @param Core.Point#COORDINATE Coord Reference coordinate.
|
|
||||||
-- @param #table ExcludeNodes Nodes that are excluded.
|
|
||||||
-- @return #ASTAR.Node The node that was fround
|
|
||||||
function ASTAR:_FindClosestTerminalNode(Coord, ExcludeNodes)
|
|
||||||
|
|
||||||
-- Find the closest pathline to the ref coordinate.
|
|
||||||
local pathline, dist, vec3, s=self:FindClosestPathline(Coord)
|
|
||||||
|
|
||||||
-- Find the closest node to the given start coordinate.
|
|
||||||
local node, dist2=self:FindClosestNode(Coord)
|
|
||||||
|
|
||||||
if pathline and vec3 and dist and dist2>dist then
|
|
||||||
|
|
||||||
-- Create a node on the closest pathline so we first go straight there and then along the pathline.
|
|
||||||
local node=self:AddNodeFromCoordinate(COORDINATE:NewFromVec3(vec3))
|
|
||||||
|
|
||||||
-- We also need the pathline point.
|
|
||||||
local point=pathline:AddPointFromVec3(vec3, nil, s.p1)
|
|
||||||
|
|
||||||
node.pathline=pathline
|
|
||||||
node.pathpoint=point
|
|
||||||
|
|
||||||
self:T2(self.lid..string.format("Added new node=%d, which is closest to start coord. dist=%.1f m", node.id, dist))
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Find the closest node to the given start coordinate.
|
|
||||||
local Node, dist3=self:FindClosestNode(Coord, ExcludeNodes)
|
|
||||||
|
|
||||||
-- Debug info.
|
|
||||||
self:T(self.lid..string.format("CLOSEST node ID=%d, distance=%.1f", Node.id, dist3))
|
|
||||||
|
|
||||||
return Node, dist3
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
--- Find the start node.
|
--- Find the start node.
|
||||||
-- @param #ASTAR self
|
-- @param #ASTAR self
|
||||||
|
-- @param #ASTAR.Node Node The node to be added to the nodes table.
|
||||||
-- @return #ASTAR self
|
-- @return #ASTAR self
|
||||||
function ASTAR:FindStartNode()
|
function ASTAR:FindStartNode()
|
||||||
|
|
||||||
|
local node, dist=self:FindClosestNode(self.startCoord)
|
||||||
|
|
||||||
-- Find the closest pathline to the
|
self.startNode=node
|
||||||
local pathline, dist, vec3, s=self:FindClosestPathline(self.startCoord)
|
|
||||||
|
|
||||||
-- Find the closest node to the given start coordinate.
|
|
||||||
local node, dist2=self:FindClosestNode(self.startCoord)
|
|
||||||
|
|
||||||
if pathline and vec3 and dist and dist2>dist then
|
if dist>1000 then
|
||||||
|
self:T(self.lid.."Adding start node to node grid!")
|
||||||
-- Create a node on the closest pathline so we first go straight there and then along the pathline.
|
self:AddNode(node)
|
||||||
local node=self:AddNodeFromCoordinate(COORDINATE:NewFromVec3(vec3))
|
|
||||||
|
|
||||||
-- We also need the pathline point.
|
|
||||||
local point=pathline:AddPointFromVec3(vec3, nil, s.p1)
|
|
||||||
|
|
||||||
node.pathline=pathline
|
|
||||||
node.pathpoint=point
|
|
||||||
|
|
||||||
self:T2(self.lid..string.format("Added new node=%d, which is closest to start coord. dist=%.1f m", node.id, dist))
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Find the closest node to the given start coordinate.
|
|
||||||
self.startNode, dist2=self:FindClosestNode(self.startCoord)
|
|
||||||
|
|
||||||
--self.startNode.coordinate:MarkToAll("Start Node")
|
|
||||||
|
|
||||||
-- Debug info.
|
|
||||||
self:T(self.lid..string.format("START node ID=%d", self.startNode.id))
|
|
||||||
|
|
||||||
-- Not sure why I did this. The node does not need to be added again as it is already contained in self.nodes!
|
|
||||||
-- if dist>1000 then
|
|
||||||
-- self:T(self.lid.."Adding start node to node grid!")
|
|
||||||
-- self:AddNode(node)
|
|
||||||
-- end
|
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Find the end node.
|
--- Add a node.
|
||||||
-- @param #ASTAR self
|
-- @param #ASTAR self
|
||||||
|
-- @param #ASTAR.Node Node The node to be added to the nodes table.
|
||||||
-- @return #ASTAR self
|
-- @return #ASTAR self
|
||||||
function ASTAR:FindEndNode()
|
function ASTAR:FindEndNode()
|
||||||
|
|
||||||
local pathline, dist, vec3, s=self:FindClosestPathline(self.endCoord)
|
|
||||||
|
|
||||||
-- Find the closest node to the given start coordinate.
|
|
||||||
local node, dist2=self:FindClosestNode(self.endCoord)
|
|
||||||
|
|
||||||
if pathline and vec3 and dist and dist2>dist then
|
|
||||||
|
|
||||||
-- Create a node on the closest pathline so we first go straight there and then along the pathline.
|
local node, dist=self:FindClosestNode(self.endCoord)
|
||||||
local node=self:AddNodeFromCoordinate(COORDINATE:NewFromVec3(vec3))
|
|
||||||
|
self.endNode=node
|
||||||
-- We also need the point.
|
|
||||||
local point=pathline:AddPointFromVec3(vec3, nil, s.p1)
|
if dist>1000 then
|
||||||
|
self:T(self.lid.."Adding end node to node grid!")
|
||||||
-- Add pathline parameters to node.
|
self:AddNode(node)
|
||||||
node.pathline=pathline
|
|
||||||
node.pathpoint=point
|
|
||||||
|
|
||||||
self:T2(self.lid..string.format("Added new node=%d, which is closest to END coord: dist=%.1f m", node.id, dist))
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Find closest node to the end coordinate (exclude the start coordinate.
|
|
||||||
self.endNode, dist=self:FindClosestNode(self.endCoord, {self.startNode})
|
|
||||||
|
|
||||||
--self.endNode.coordinate:MarkToAll("End Node")
|
|
||||||
|
|
||||||
-- Debug info.
|
|
||||||
self:T(self.lid..string.format("END node ID=%d", self.endNode.id))
|
|
||||||
|
|
||||||
-- Not sure why I did this. The node does not need to be added again as it is already contained in self.nodes!
|
|
||||||
-- if dist>1000 then
|
|
||||||
-- self:T(self.lid.."Adding end node to node grid!")
|
|
||||||
-- self:AddNode(node)
|
|
||||||
-- end
|
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
@@ -922,21 +684,12 @@ end
|
|||||||
-- @return #table Table of nodes from start to finish.
|
-- @return #table Table of nodes from start to finish.
|
||||||
function ASTAR:GetPath(ExcludeStartNode, ExcludeEndNode)
|
function ASTAR:GetPath(ExcludeStartNode, ExcludeEndNode)
|
||||||
|
|
||||||
-- self:FindStartNode()
|
self:FindStartNode()
|
||||||
-- self:FindEndNode()
|
self:FindEndNode()
|
||||||
|
|
||||||
-- Find start Node (closest node to start coordinate).
|
|
||||||
self.startNode=self:_FindClosestTerminalNode(self.startCoord)
|
|
||||||
|
|
||||||
-- Find end node, which is not the start node (excluded).
|
|
||||||
self.endNode=self:_FindClosestTerminalNode(self.endCoord, {self.startNode})
|
|
||||||
|
|
||||||
local nodes=self.nodes
|
local nodes=self.nodes
|
||||||
local start=self.startNode
|
local start=self.startNode
|
||||||
local goal=self.endNode
|
local goal=self.endNode
|
||||||
|
|
||||||
-- Debug info.
|
|
||||||
self:T(self.lid..string.format("GetPath Start Node=%d, End Node=%d", start.id, goal.id))
|
|
||||||
|
|
||||||
-- Sets.
|
-- Sets.
|
||||||
local openset = {}
|
local openset = {}
|
||||||
@@ -993,12 +746,7 @@ function ASTAR:GetPath(ExcludeStartNode, ExcludeEndNode)
|
|||||||
text=text..string.format(", OS Time %.6f sec", dT)
|
text=text..string.format(", OS Time %.6f sec", dT)
|
||||||
end
|
end
|
||||||
text=text..string.format(", Nvalid=%d [%d cached]", self.nvalid, self.nvalidcache)
|
text=text..string.format(", Nvalid=%d [%d cached]", self.nvalid, self.nvalidcache)
|
||||||
text=text..string.format(", Ncost=%d [%d cached]", self.ncost, self.ncostcache)
|
text=text..string.format(", Ncost=%d [%d cached]", self.ncost, self.ncostcache)
|
||||||
text=text..string.format("\nNodes:")
|
|
||||||
for i,_node in ipairs(path) do
|
|
||||||
local node=_node --#ASTAR.Node
|
|
||||||
text=text..string.format("\n[%d] Node ID=%d", i, node.id)
|
|
||||||
end
|
|
||||||
self:T(self.lid..text)
|
self:T(self.lid..text)
|
||||||
|
|
||||||
return path
|
return path
|
||||||
@@ -1011,16 +759,13 @@ function ASTAR:GetPath(ExcludeStartNode, ExcludeEndNode)
|
|||||||
|
|
||||||
-- Get neighbour nodes.
|
-- Get neighbour nodes.
|
||||||
local neighbors=self:_NeighbourNodes(current, nodes)
|
local neighbors=self:_NeighbourNodes(current, nodes)
|
||||||
|
|
||||||
-- Loop over neighbours.
|
-- Loop over neighbours.
|
||||||
for _,neighbor in pairs(neighbors) do
|
for _,neighbor in pairs(neighbors) do
|
||||||
|
|
||||||
-- Node is not in closed set.
|
|
||||||
if self:_NotIn(closedset, neighbor.id) then
|
if self:_NotIn(closedset, neighbor.id) then
|
||||||
|
|
||||||
-- Calculate tentative_g_score.
|
local tentative_g_score=g_score[current.id]+self:_DistNodes(current, neighbor)
|
||||||
--local tentative_g_score=g_score[current.id] + self:_DistNodes(current, neighbor)
|
|
||||||
local tentative_g_score=g_score[current.id] + self:_HeuristicCost(current, neighbor)
|
|
||||||
|
|
||||||
if self:_NotIn(openset, neighbor.id) or tentative_g_score < g_score[neighbor.id] then
|
if self:_NotIn(openset, neighbor.id) or tentative_g_score < g_score[neighbor.id] then
|
||||||
|
|
||||||
@@ -1048,73 +793,6 @@ function ASTAR:GetPath(ExcludeStartNode, ExcludeEndNode)
|
|||||||
return nil -- no valid path
|
return nil -- no valid path
|
||||||
end
|
end
|
||||||
|
|
||||||
--- A* pathfinding function. This seaches the path along nodes between start and end nodes/coordinates.
|
|
||||||
-- It automatically creates a PATHLINE object that is returned in combination with the nodes of the optimal path.
|
|
||||||
-- @param #ASTAR self
|
|
||||||
-- @param #boolean ExcludeStartNode If *true*, do not include start node in found path. Default is to include it.
|
|
||||||
-- @param #boolean ExcludeEndNode If *true*, do not include end node in found path. Default is to include it.
|
|
||||||
-- @return Core.Pathline#PATHLINE Pathline.
|
|
||||||
-- @return #table Nodes of path.
|
|
||||||
function ASTAR:GetPathline(ExcludeStartNode, ExcludeEndNode)
|
|
||||||
|
|
||||||
local nodes=self:GetPath(ExcludeStartNode, ExcludeEndNode)
|
|
||||||
|
|
||||||
local pathline=nil --Core.Pathline#PATHLINE
|
|
||||||
if nodes then
|
|
||||||
|
|
||||||
pathline=PATHLINE:New("Astar")
|
|
||||||
|
|
||||||
for _,_node in pairs(nodes) do
|
|
||||||
local node=_node --#ASTAR.Node
|
|
||||||
|
|
||||||
local point=pathline:AddPointFromVec3(node.coordinate)
|
|
||||||
point.name=node.pathline.name
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
return pathline, nodes
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Get pathlines from nodes.
|
|
||||||
-- @param #ASTAR self
|
|
||||||
-- @param #table Nodes Given nodes.
|
|
||||||
-- @return #table Table of PATHLINES used in the path.
|
|
||||||
function ASTAR:GetPathlinesFromNodes(Nodes)
|
|
||||||
|
|
||||||
local pathlines={}
|
|
||||||
|
|
||||||
--for _,_node in pairs(Nodes or {}) do
|
|
||||||
for i=1,#Nodes do
|
|
||||||
local node=Nodes[i] --#ASTAR.Node
|
|
||||||
|
|
||||||
-- Pathline.
|
|
||||||
local pathline=node.pathline
|
|
||||||
|
|
||||||
if pathline and i>1 and i<#Nodes then
|
|
||||||
|
|
||||||
-- Previous and next nodes.
|
|
||||||
local n=Nodes[i-1] --#ASTAR.Node
|
|
||||||
local N=Nodes[i+1] --#ASTAR.Node
|
|
||||||
|
|
||||||
-- Check if previous and next nodes are on the same pathline.
|
|
||||||
-- If only one point in beteen is of another pathline, this is a junction and we dont actually switch to the other pathline.
|
|
||||||
if n.pathline and N.pathline and n.pathline.name==N.pathline.name and n.pathline.name~=pathline.name then
|
|
||||||
pathline=n.pathline
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
-- We do not want to add the same pathline two times in a row.
|
|
||||||
if #pathlines==0 or (#pathlines>0 and pathlines[#pathlines].name~=pathline.name) then
|
|
||||||
table.insert(pathlines, pathline)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return pathlines
|
|
||||||
end
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- A* pathfinding helper functions
|
-- A* pathfinding helper functions
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
@@ -1133,18 +811,16 @@ function ASTAR:_HeuristicCost(nodeA, nodeB)
|
|||||||
local cost=nodeA.cost[nodeB.id]
|
local cost=nodeA.cost[nodeB.id]
|
||||||
if cost~=nil then
|
if cost~=nil then
|
||||||
self.ncostcache=self.ncostcache+1
|
self.ncostcache=self.ncostcache+1
|
||||||
self:T(self.lid..string.format("Cost nodeA=%d --> nodeB=%d = %.1f (Cashed!)", nodeA.id, nodeB.id, cost))
|
|
||||||
return cost
|
return cost
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local cost=nil
|
||||||
if self.CostFunc then
|
if self.CostFunc then
|
||||||
cost=self.CostFunc(nodeA, nodeB, unpack(self.CostArg))
|
cost=self.CostFunc(nodeA, nodeB, unpack(self.CostArg))
|
||||||
else
|
else
|
||||||
cost=self:_DistNodes(nodeA, nodeB)
|
cost=self:_DistNodes(nodeA, nodeB)
|
||||||
end
|
end
|
||||||
|
|
||||||
self:T(self.lid..string.format("Cost nodeA=%d --> nodeB=%d = %.1f", nodeA.id, nodeB.id, cost))
|
|
||||||
|
|
||||||
nodeA.cost[nodeB.id]=cost
|
nodeA.cost[nodeB.id]=cost
|
||||||
nodeB.cost[nodeA.id]=cost -- Symmetric problem.
|
nodeB.cost[nodeA.id]=cost -- Symmetric problem.
|
||||||
|
|
||||||
@@ -1158,10 +834,9 @@ end
|
|||||||
-- @return #boolean If true, transition between nodes is possible.
|
-- @return #boolean If true, transition between nodes is possible.
|
||||||
function ASTAR:_IsValidNeighbour(node, neighbor)
|
function ASTAR:_IsValidNeighbour(node, neighbor)
|
||||||
|
|
||||||
-- Counter of function calls.
|
-- Counter.
|
||||||
self.nvalid=self.nvalid+1
|
self.nvalid=self.nvalid+1
|
||||||
|
|
||||||
-- Check if neighbour is in cached set.
|
|
||||||
local valid=node.valid[neighbor.id]
|
local valid=node.valid[neighbor.id]
|
||||||
if valid~=nil then
|
if valid~=nil then
|
||||||
--env.info(string.format("Node %d has valid=%s neighbour %d", node.id, tostring(valid), neighbor.id))
|
--env.info(string.format("Node %d has valid=%s neighbour %d", node.id, tostring(valid), neighbor.id))
|
||||||
@@ -1169,16 +844,13 @@ function ASTAR:_IsValidNeighbour(node, neighbor)
|
|||||||
return valid
|
return valid
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Check if this is a valid neighbour.
|
|
||||||
local valid=nil
|
local valid=nil
|
||||||
if self.ValidNeighbourFunc then
|
if self.ValidNeighbourFunc then
|
||||||
valid=self.ValidNeighbourFunc(node, neighbor, unpack(self.ValidNeighbourArg))
|
valid=self.ValidNeighbourFunc(node, neighbor, unpack(self.ValidNeighbourArg))
|
||||||
else
|
else
|
||||||
-- If no valid neighbour function is defined, we assume all nodes are valid neighbours.
|
|
||||||
valid=true
|
valid=true
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Cache valid neighbour.
|
|
||||||
node.valid[neighbor.id]=valid
|
node.valid[neighbor.id]=valid
|
||||||
neighbor.valid[node.id]=valid -- Symmetric problem.
|
neighbor.valid[node.id]=valid -- Symmetric problem.
|
||||||
|
|
||||||
@@ -1212,9 +884,6 @@ function ASTAR:_LowestFscore(set, f_score)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Debug info.
|
|
||||||
self:T(self.lid..string.format("Lowest Fscore=%.1f, Node=%s", lowest, tostring(bestNode)))
|
|
||||||
|
|
||||||
return self.nodes[bestNode]
|
return self.nodes[bestNode]
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1259,46 +928,16 @@ end
|
|||||||
-- @param #table map Map.
|
-- @param #table map Map.
|
||||||
-- @param #ASTAR.Node current_node The current node.
|
-- @param #ASTAR.Node current_node The current node.
|
||||||
-- @return #table Unwinded path.
|
-- @return #table Unwinded path.
|
||||||
function ASTAR:_UnwindPath(flat_path, map, current_node)
|
function ASTAR:_UnwindPath( flat_path, map, current_node )
|
||||||
|
|
||||||
local previous_node=map[current_node]
|
if map [current_node] then
|
||||||
|
table.insert (flat_path, 1, map[current_node])
|
||||||
if previous_node then
|
return self:_UnwindPath(flat_path, map, map[current_node])
|
||||||
table.insert(flat_path, 1, previous_node)
|
|
||||||
return self:_UnwindPath(flat_path, map, previous_node)
|
|
||||||
else
|
else
|
||||||
-- No previous node ==> return path.
|
|
||||||
return flat_path
|
return flat_path
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Function to check if a certain node is in a given table.
|
|
||||||
-- @param #ASTAR self
|
|
||||||
-- @param #table Nodes Nodes table.
|
|
||||||
-- @param #ASTAR.Node Node The node to check.
|
|
||||||
-- @return #boolean If true, the node is not in the set.
|
|
||||||
function ASTAR:_IsNodeInTable(Nodes, Node)
|
|
||||||
|
|
||||||
for _,_node in pairs(Nodes) do
|
|
||||||
local node=_node --#ASTAR.Node
|
|
||||||
if node.id==Node.id then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Function to check if a certain node is **not** in a given table.
|
|
||||||
-- @param #ASTAR self
|
|
||||||
-- @param #table Nodes Nodes table.
|
|
||||||
-- @param #ASTAR.Node Node The node to check.
|
|
||||||
-- @return #boolean If true, the node is not in the set.
|
|
||||||
function ASTAR:_IsNodeNotInTable(Nodes, Node)
|
|
||||||
local is=self:_IsNodeInTable(Nodes, Node)
|
|
||||||
return not is
|
|
||||||
end
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
@@ -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, ... )
|
||||||
|
|
||||||
|
|||||||
@@ -1,924 +0,0 @@
|
|||||||
--- **Core** - Client Menu Management.
|
|
||||||
--
|
|
||||||
-- **Main Features:**
|
|
||||||
--
|
|
||||||
-- * For complex, non-static menu structures
|
|
||||||
-- * Lightweigt implementation as alternative to MENU
|
|
||||||
-- * Separation of menu tree creation from menu on the clients's side
|
|
||||||
-- * Works with a SET_CLIENT set of clients
|
|
||||||
-- * Allow manipulation of the shadow tree in various ways
|
|
||||||
-- * Push to all or only one client
|
|
||||||
-- * Change entries' menu text
|
|
||||||
-- * Option to make an entry usable once only across all clients
|
|
||||||
-- * Auto appends GROUP and CLIENT objects to menu calls
|
|
||||||
--
|
|
||||||
-- ===
|
|
||||||
--
|
|
||||||
-- ### Author: **applevangelist**
|
|
||||||
--
|
|
||||||
-- ===
|
|
||||||
--
|
|
||||||
-- @module Core.ClientMenu
|
|
||||||
-- @image Core_Menu.JPG
|
|
||||||
-- last change: Jan 2025
|
|
||||||
|
|
||||||
-- TODO
|
|
||||||
----------------------------------------------------------------------------------------------------------------
|
|
||||||
--
|
|
||||||
-- CLIENTMENU
|
|
||||||
--
|
|
||||||
----------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
---
|
|
||||||
-- @type CLIENTMENU
|
|
||||||
-- @field #string ClassName Class Name
|
|
||||||
-- @field #string lid Lid for log entries
|
|
||||||
-- @field #string version Version string
|
|
||||||
-- @field #string name Name
|
|
||||||
-- @field #string groupname Group name
|
|
||||||
-- @field #table path
|
|
||||||
-- @field #table parentpath
|
|
||||||
-- @field #CLIENTMENU Parent
|
|
||||||
-- @field Wrapper.Client#CLIENT client
|
|
||||||
-- @field #number GroupID Group ID
|
|
||||||
-- @field #number ID Entry ID
|
|
||||||
-- @field Wrapper.Group#GROUP group
|
|
||||||
-- @field #string UUID Unique ID based on path+name
|
|
||||||
-- @field #string Function
|
|
||||||
-- @field #table Functionargs
|
|
||||||
-- @field #table Children
|
|
||||||
-- @field #boolean Once
|
|
||||||
-- @field #boolean Generic
|
|
||||||
-- @field #boolean debug
|
|
||||||
-- @field #CLIENTMENUMANAGER Controller
|
|
||||||
-- @field #active boolean
|
|
||||||
-- @extends Core.Base#BASE
|
|
||||||
|
|
||||||
---
|
|
||||||
-- @field #CLIENTMENU
|
|
||||||
CLIENTMENU = {
|
|
||||||
ClassName = "CLIENTMENU",
|
|
||||||
lid = "",
|
|
||||||
version = "0.1.3",
|
|
||||||
name = nil,
|
|
||||||
path = nil,
|
|
||||||
group = nil,
|
|
||||||
client = nil,
|
|
||||||
GroupID = nil,
|
|
||||||
Children = {},
|
|
||||||
Once = false,
|
|
||||||
Generic = false,
|
|
||||||
debug = false,
|
|
||||||
Controller = nil,
|
|
||||||
groupname = nil,
|
|
||||||
active = false,
|
|
||||||
}
|
|
||||||
|
|
||||||
---
|
|
||||||
-- @field #CLIENTMENU_ID
|
|
||||||
CLIENTMENU_ID = 0
|
|
||||||
|
|
||||||
--- Create an new CLIENTMENU object.
|
|
||||||
-- @param #CLIENTMENU self
|
|
||||||
-- @param Wrapper.Client#CLIENT Client The client for whom this entry is. Leave as nil for a generic entry.
|
|
||||||
-- @param #string Text Text of the F10 menu entry.
|
|
||||||
-- @param #CLIENTMENU Parent The parent menu entry.
|
|
||||||
-- @param #string Function (optional) Function to call when the entry is used.
|
|
||||||
-- @param ... (optional) Arguments for the Function, comma separated
|
|
||||||
-- @return #CLIENTMENU self
|
|
||||||
function CLIENTMENU:NewEntry(Client,Text,Parent,Function,...)
|
|
||||||
-- Inherit everything from BASE class.
|
|
||||||
local self=BASE:Inherit(self, BASE:New()) -- #CLIENTMENU
|
|
||||||
CLIENTMENU_ID = CLIENTMENU_ID + 1
|
|
||||||
self.ID = CLIENTMENU_ID
|
|
||||||
if Client then
|
|
||||||
self.group = Client:GetGroup()
|
|
||||||
self.client = Client
|
|
||||||
self.GroupID = self.group:GetID()
|
|
||||||
self.groupname = self.group:GetName() or "Unknown Groupname"
|
|
||||||
else
|
|
||||||
self.Generic = true
|
|
||||||
end
|
|
||||||
self.name = Text or "unknown entry"
|
|
||||||
if Parent then
|
|
||||||
if Parent:IsInstanceOf("MENU_BASE") then
|
|
||||||
self.parentpath = Parent.MenuPath
|
|
||||||
else
|
|
||||||
self.parentpath = Parent:GetPath()
|
|
||||||
Parent:AddChild(self)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
self.Parent = Parent
|
|
||||||
self.Function = Function
|
|
||||||
self.Functionargs = arg or {}
|
|
||||||
table.insert(self.Functionargs,self.group)
|
|
||||||
table.insert(self.Functionargs,self.client)
|
|
||||||
if self.Functionargs and self.debug then
|
|
||||||
self:T({"Functionargs",self.Functionargs})
|
|
||||||
end
|
|
||||||
if not self.Generic and self.active == false then
|
|
||||||
if Function ~= nil then
|
|
||||||
local ErrorHandler = function( errmsg )
|
|
||||||
env.info( "MOOSE Error in CLIENTMENU COMMAND function: " .. errmsg )
|
|
||||||
if BASE.Debug ~= nil then
|
|
||||||
env.info( BASE.Debug.traceback() )
|
|
||||||
end
|
|
||||||
return errmsg
|
|
||||||
end
|
|
||||||
self.CallHandler = function()
|
|
||||||
local function MenuFunction()
|
|
||||||
return self.Function( unpack( self.Functionargs ) )
|
|
||||||
end
|
|
||||||
local Status, Result = xpcall( MenuFunction, ErrorHandler)
|
|
||||||
if self.Once == true then
|
|
||||||
self:Clear()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
self.path = missionCommands.addCommandForGroup(self.GroupID,Text,self.parentpath, self.CallHandler)
|
|
||||||
self.active = true
|
|
||||||
else
|
|
||||||
self.path = missionCommands.addSubMenuForGroup(self.GroupID,Text,self.parentpath)
|
|
||||||
self.active = true
|
|
||||||
end
|
|
||||||
else
|
|
||||||
if self.parentpath then
|
|
||||||
self.path = UTILS.DeepCopy(self.parentpath)
|
|
||||||
else
|
|
||||||
self.path = {}
|
|
||||||
end
|
|
||||||
self.path[#self.path+1] = Text
|
|
||||||
end
|
|
||||||
self.UUID = table.concat(self.path,";")
|
|
||||||
self:T({self.UUID})
|
|
||||||
self.Once = false
|
|
||||||
-- Log id.
|
|
||||||
self.lid=string.format("CLIENTMENU %s | %s | ", self.ID, self.name)
|
|
||||||
self:T(self.lid.."Created")
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Create a UUID
|
|
||||||
-- @param #CLIENTMENU self
|
|
||||||
-- @param #CLIENTMENU Parent The parent object if any
|
|
||||||
-- @param #string Text The menu entry text
|
|
||||||
-- @return #string UUID
|
|
||||||
function CLIENTMENU:CreateUUID(Parent,Text)
|
|
||||||
local path = {}
|
|
||||||
if Parent and Parent.path then
|
|
||||||
path = Parent.path
|
|
||||||
end
|
|
||||||
path[#path+1] = Text
|
|
||||||
local UUID = table.concat(path,";")
|
|
||||||
return UUID
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Set the CLIENTMENUMANAGER for this entry.
|
|
||||||
-- @param #CLIENTMENU self
|
|
||||||
-- @param #CLIENTMENUMANAGER Controller The controlling object.
|
|
||||||
-- @return #CLIENTMENU self
|
|
||||||
function CLIENTMENU:SetController(Controller)
|
|
||||||
self.Controller = Controller
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- The entry will be deleted after being used used - for menu entries with functions only.
|
|
||||||
-- @param #CLIENTMENU self
|
|
||||||
-- @return #CLIENTMENU self
|
|
||||||
function CLIENTMENU:SetOnce()
|
|
||||||
self:T(self.lid.."SetOnce")
|
|
||||||
self.Once = true
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Remove the entry from the F10 menu.
|
|
||||||
-- @param #CLIENTMENU self
|
|
||||||
-- @return #CLIENTMENU self
|
|
||||||
function CLIENTMENU:RemoveF10()
|
|
||||||
self:T(self.lid.."RemoveF10")
|
|
||||||
if self.GroupID then
|
|
||||||
--self:I(self.lid.."Removing "..table.concat(self.path,";"))
|
|
||||||
local function RemoveFunction()
|
|
||||||
return missionCommands.removeItemForGroup(self.GroupID , self.path )
|
|
||||||
end
|
|
||||||
local status, err = pcall(RemoveFunction)
|
|
||||||
if not status then
|
|
||||||
self:I(string.format("**** Error Removing Menu Entry %s for %s!",tostring(self.name),self.groupname))
|
|
||||||
end
|
|
||||||
self.active = false
|
|
||||||
end
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Get the menu path table.
|
|
||||||
-- @param #CLIENTMENU self
|
|
||||||
-- @return #table Path
|
|
||||||
function CLIENTMENU:GetPath()
|
|
||||||
self:T(self.lid.."GetPath")
|
|
||||||
return self.path
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Get the UUID.
|
|
||||||
-- @param #CLIENTMENU self
|
|
||||||
-- @return #string UUID
|
|
||||||
function CLIENTMENU:GetUUID()
|
|
||||||
self:T(self.lid.."GetUUID")
|
|
||||||
return self.UUID
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Link a child entry.
|
|
||||||
-- @param #CLIENTMENU self
|
|
||||||
-- @param #CLIENTMENU Child The entry to link as a child.
|
|
||||||
-- @return #CLIENTMENU self
|
|
||||||
function CLIENTMENU:AddChild(Child)
|
|
||||||
self:T(self.lid.."AddChild "..Child.ID)
|
|
||||||
table.insert(self.Children,Child.ID,Child)
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Remove a child entry.
|
|
||||||
-- @param #CLIENTMENU self
|
|
||||||
-- @param #CLIENTMENU Child The entry to remove from the children.
|
|
||||||
-- @return #CLIENTMENU self
|
|
||||||
function CLIENTMENU:RemoveChild(Child)
|
|
||||||
self:T(self.lid.."RemoveChild "..Child.ID)
|
|
||||||
table.remove(self.Children,Child.ID)
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Remove all subentries (children) from this entry.
|
|
||||||
-- @param #CLIENTMENU self
|
|
||||||
-- @return #CLIENTMENU self
|
|
||||||
function CLIENTMENU:RemoveSubEntries()
|
|
||||||
self:T(self.lid.."RemoveSubEntries")
|
|
||||||
self:T({self.Children})
|
|
||||||
for _id,_entry in pairs(self.Children) do
|
|
||||||
self:T("Removing ".._id)
|
|
||||||
if _entry then
|
|
||||||
_entry:RemoveSubEntries()
|
|
||||||
_entry:RemoveF10()
|
|
||||||
if _entry.Parent then
|
|
||||||
_entry.Parent:RemoveChild(self)
|
|
||||||
end
|
|
||||||
--if self.Controller then
|
|
||||||
--self.Controller:_RemoveByID(_entry.ID)
|
|
||||||
--end
|
|
||||||
--_entry = nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Remove this entry and all subentries (children) from this entry.
|
|
||||||
-- @param #CLIENTMENU self
|
|
||||||
-- @return #CLIENTMENU self
|
|
||||||
function CLIENTMENU:Clear()
|
|
||||||
self:T(self.lid.."Clear")
|
|
||||||
for _id,_entry in pairs(self.Children) do
|
|
||||||
if _entry then
|
|
||||||
_entry:RemoveSubEntries()
|
|
||||||
_entry = nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
self:RemoveF10()
|
|
||||||
if self.Parent then
|
|
||||||
self.Parent:RemoveChild(self)
|
|
||||||
end
|
|
||||||
--if self.Controller then
|
|
||||||
--self.Controller:_RemoveByID(self.ID)
|
|
||||||
--end
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
-- TODO
|
|
||||||
----------------------------------------------------------------------------------------------------------------
|
|
||||||
--
|
|
||||||
-- CLIENTMENUMANAGER
|
|
||||||
--
|
|
||||||
----------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
--- Class CLIENTMENUMANAGER
|
|
||||||
-- @type CLIENTMENUMANAGER
|
|
||||||
-- @field #string ClassName Class Name
|
|
||||||
-- @field #string lid Lid for log entries
|
|
||||||
-- @field #string version Version string
|
|
||||||
-- @field #string name Name
|
|
||||||
-- @field Core.Set#SET_CLIENT clientset The set of clients this menu manager is for
|
|
||||||
-- @field #table flattree
|
|
||||||
-- @field #table rootentries
|
|
||||||
-- @field #table menutree
|
|
||||||
-- @field #number entrycount
|
|
||||||
-- @field #boolean debug
|
|
||||||
-- @field #table PlayerMenu
|
|
||||||
-- @field #number Coalition
|
|
||||||
-- @extends Core.Base#BASE
|
|
||||||
|
|
||||||
--- *As a child my family's menu consisted of two choices: take it, or leave it.*
|
|
||||||
--
|
|
||||||
-- ===
|
|
||||||
--
|
|
||||||
-- ## CLIENTMENU and CLIENTMENUMANAGER
|
|
||||||
--
|
|
||||||
-- Manage menu structures for a SET_CLIENT of clients.
|
|
||||||
--
|
|
||||||
-- ## Concept
|
|
||||||
--
|
|
||||||
-- Separate creation of a menu tree structure from pushing it to each client. Create a shadow "reference" menu structure tree for your client pilot's in a mission.
|
|
||||||
-- This can then be propagated to all clients. Manipulate the entries in the structure with removing, clearing or changing single entries, create replacement sub-structures
|
|
||||||
-- for entries etc, push to one or all clients.
|
|
||||||
--
|
|
||||||
-- Many functions can either change the tree for one client or for all clients.
|
|
||||||
--
|
|
||||||
-- ## Conceptual remarks
|
|
||||||
--
|
|
||||||
-- There's a couple of things to fully understand:
|
|
||||||
--
|
|
||||||
-- 1) **CLIENTMENUMANAGER** manages a set of entries from **CLIENTMENU**, it's main purpose is to administer the *shadow menu tree*, ie. a menu structure which is not
|
|
||||||
-- (yet) visible to any client
|
|
||||||
-- 2) The entries are **CLIENTMENU** objects, which are linked in a tree form. There's two ways to create them:
|
|
||||||
-- A) in the manager with ":NewEntry()" which initially
|
|
||||||
-- adds it to the shadow menu **only**
|
|
||||||
-- B) stand-alone directly as `CLIENTMENU:NewEntry()` - here it depends on whether or not you gave a CLIENT object if the entry is created as generic entry or pushed
|
|
||||||
-- a **specific** client. **Be aware** though that the entries are not managed by the CLIENTMANAGER before the next step!
|
|
||||||
-- A generic entry can be added to the manager (and the shadow tree) with `:AddEntry()` - this will also push it to all clients(!) if no client is given, or a specific client only.
|
|
||||||
-- 3) Pushing only works for alive clients.
|
|
||||||
-- 4) Live and shadow tree entries are managed via the CLIENTMENUMANAGER object.
|
|
||||||
-- 5) `Propagate()`refreshes the menu tree for all, or a single client.
|
|
||||||
--
|
|
||||||
-- ## Create a base reference tree and send to all clients
|
|
||||||
--
|
|
||||||
-- local clientset = SET_CLIENT:New():FilterStart()
|
|
||||||
--
|
|
||||||
-- local menumgr = CLIENTMENUMANAGER:New(clientset,"Dayshift")
|
|
||||||
-- local mymenu = menumgr:NewEntry("Top")
|
|
||||||
-- local mymenu_lv1a = menumgr:NewEntry("Level 1 a",mymenu)
|
|
||||||
-- local mymenu_lv1b = menumgr:NewEntry("Level 1 b",mymenu)
|
|
||||||
-- -- next one is a command menu entry, which can only be used once
|
|
||||||
-- local mymenu_lv1c = menumgr:NewEntry("Action Level 1 c",mymenu, testfunction, "testtext"):SetOnce()
|
|
||||||
--
|
|
||||||
-- local mymenu_lv2a = menumgr:NewEntry("Go here",mymenu_lv1a)
|
|
||||||
-- local mymenu_lv2b = menumgr:NewEntry("Level 2 ab",mymenu_lv1a)
|
|
||||||
-- local mymenu_lv2c = menumgr:NewEntry("Level 2 ac",mymenu_lv1a)
|
|
||||||
--
|
|
||||||
-- local mymenu_lv2ba = menumgr:NewEntry("Level 2 ba",mymenu_lv1b)
|
|
||||||
-- local mymenu_lv2bb = menumgr:NewEntry("Level 2 bb",mymenu_lv1b)
|
|
||||||
-- local mymenu_lv2bc = menumgr:NewEntry("Level 2 bc",mymenu_lv1b)
|
|
||||||
--
|
|
||||||
-- local mymenu_lv3a = menumgr:NewEntry("Level 3 aaa",mymenu_lv2a)
|
|
||||||
-- local mymenu_lv3b = menumgr:NewEntry("Level 3 aab",mymenu_lv2a)
|
|
||||||
-- local mymenu_lv3c = menumgr:NewEntry("Level 3 aac",mymenu_lv2a)
|
|
||||||
--
|
|
||||||
-- menumgr:Propagate() -- propagate **once** to all clients in the SET_CLIENT
|
|
||||||
--
|
|
||||||
-- ## Remove a single entry's subtree
|
|
||||||
--
|
|
||||||
-- menumgr:RemoveSubEntries(mymenu_lv3a)
|
|
||||||
--
|
|
||||||
-- ## Remove a single entry and also it's subtree
|
|
||||||
--
|
|
||||||
-- menumgr:DeleteEntry(mymenu_lv3a)
|
|
||||||
--
|
|
||||||
-- ## Add a single entry
|
|
||||||
--
|
|
||||||
-- local baimenu = menumgr:NewEntry("BAI",mymenu_lv1b)
|
|
||||||
--
|
|
||||||
-- menumgr:AddEntry(baimenu)
|
|
||||||
--
|
|
||||||
-- ## Add an entry with a function
|
|
||||||
--
|
|
||||||
-- local baimenu = menumgr:NewEntry("Task Action", mymenu_lv1b, TestFunction, Argument1, Argument1)
|
|
||||||
--
|
|
||||||
-- Now, the class will **automatically append the call with GROUP and CLIENT objects**, as this is can only be done when pushing the entry to the clients. So, the actual function implementation needs to look like this:
|
|
||||||
--
|
|
||||||
-- function TestFunction( Argument1, Argument2, Group, Client)
|
|
||||||
--
|
|
||||||
-- **Caveat is**, that you need to ensure your arguments are not **nil** or **false**, as LUA will optimize those away. You would end up having Group and Client in wrong places in the function call. Hence,
|
|
||||||
-- if you need/ want to send **nil** or **false**, send a place holder instead and ensure your function can handle this, e.g.
|
|
||||||
--
|
|
||||||
-- local baimenu = menumgr:NewEntry("Task Action", mymenu_lv1b, TestFunction, "nil", Argument1)
|
|
||||||
--
|
|
||||||
-- ## Change the text of a leaf entry in the menu tree
|
|
||||||
--
|
|
||||||
-- menumgr:ChangeEntryTextForAll(mymenu_lv1b,"Attack")
|
|
||||||
--
|
|
||||||
-- ## Reset a single clients menu tree
|
|
||||||
--
|
|
||||||
-- menumgr:ResetMenu(client)
|
|
||||||
--
|
|
||||||
-- ## Reset all and clear the reference tree
|
|
||||||
--
|
|
||||||
-- menumgr:ResetMenuComplete()
|
|
||||||
--
|
|
||||||
-- ## Set to auto-propagate for CLIENTs joining the SET_CLIENT **after** the script is loaded - handy if you have a single menu tree.
|
|
||||||
--
|
|
||||||
-- menumgr:InitAutoPropagation()
|
|
||||||
--
|
|
||||||
-- @field #CLIENTMENUMANAGER
|
|
||||||
CLIENTMENUMANAGER = {
|
|
||||||
ClassName = "CLIENTMENUMANAGER",
|
|
||||||
lid = "",
|
|
||||||
version = "0.1.6",
|
|
||||||
name = nil,
|
|
||||||
clientset = nil,
|
|
||||||
menutree = {},
|
|
||||||
flattree = {},
|
|
||||||
playertree = {},
|
|
||||||
entrycount = 0,
|
|
||||||
rootentries = {},
|
|
||||||
debug = true,
|
|
||||||
PlayerMenu = {},
|
|
||||||
Coalition = nil,
|
|
||||||
}
|
|
||||||
|
|
||||||
--- Create a new ClientManager instance.
|
|
||||||
-- @param #CLIENTMENUMANAGER self
|
|
||||||
-- @param Core.Set#SET_CLIENT ClientSet The set of clients to manage.
|
|
||||||
-- @param #string Alias The name of this manager.
|
|
||||||
-- @param #number Coalition (Optional) Coalition of this Manager, defaults to coalition.side.BLUE
|
|
||||||
-- @return #CLIENTMENUMANAGER self
|
|
||||||
function CLIENTMENUMANAGER:New(ClientSet, Alias, Coalition)
|
|
||||||
-- Inherit everything from FSM class.
|
|
||||||
local self=BASE:Inherit(self, BASE:New()) -- #CLIENTMENUMANAGER
|
|
||||||
self.clientset = ClientSet
|
|
||||||
self.PlayerMenu = {}
|
|
||||||
self.name = Alias or "Nightshift"
|
|
||||||
self.Coalition = Coalition or coalition.side.BLUE
|
|
||||||
-- Log id.
|
|
||||||
self.lid=string.format("CLIENTMENUMANAGER %s | %s | ", self.version, self.name)
|
|
||||||
if self.debug then
|
|
||||||
self:I(self.lid.."Created")
|
|
||||||
end
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- [Internal] Event handling
|
|
||||||
-- @param #CLIENTMENUMANAGER self
|
|
||||||
-- @param Core.Event#EVENTDATA EventData
|
|
||||||
-- @return #CLIENTMENUMANAGER self
|
|
||||||
function CLIENTMENUMANAGER:_EventHandler(EventData,Retry)
|
|
||||||
self:T(self.lid.."_EventHandler: "..EventData.id)
|
|
||||||
--self:I(self.lid.."_EventHandler: "..tostring(EventData.IniPlayerName))
|
|
||||||
if EventData.id == EVENTS.PlayerLeaveUnit or EventData.id == EVENTS.Ejection or EventData.id == EVENTS.Crash or EventData.id == EVENTS.PilotDead then
|
|
||||||
self:T(self.lid.."Leave event for player: "..tostring(EventData.IniPlayerName))
|
|
||||||
local Client = _DATABASE:FindClient( EventData.IniUnitName )
|
|
||||||
if Client then
|
|
||||||
self:ResetMenu(Client)
|
|
||||||
end
|
|
||||||
elseif (EventData.id == EVENTS.PlayerEnterAircraft) and EventData.IniCoalition == self.Coalition then
|
|
||||||
if EventData.IniPlayerName and EventData.IniGroup then
|
|
||||||
if (not self.clientset:IsIncludeObject(_DATABASE:FindClient( EventData.IniUnitName ))) then
|
|
||||||
self:T(self.lid.."Client not in SET: "..EventData.IniPlayerName)
|
|
||||||
if not Retry then
|
|
||||||
-- try again in 2 secs
|
|
||||||
self:ScheduleOnce(2,CLIENTMENUMANAGER._EventHandler,self,EventData,true)
|
|
||||||
end
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
--self:I(self.lid.."Join event for player: "..EventData.IniPlayerName)
|
|
||||||
local player = _DATABASE:FindClient( EventData.IniUnitName )
|
|
||||||
self:Propagate(player)
|
|
||||||
end
|
|
||||||
elseif EventData.id == EVENTS.PlayerEnterUnit then
|
|
||||||
-- special for CA slots
|
|
||||||
local grp = GROUP:FindByName(EventData.IniGroupName)
|
|
||||||
if grp:IsGround() then
|
|
||||||
self:T(string.format("Player %s entered GROUND unit %s!",EventData.IniPlayerName,EventData.IniUnitName))
|
|
||||||
local IsPlayer = EventData.IniDCSUnit:getPlayerName()
|
|
||||||
if IsPlayer then
|
|
||||||
|
|
||||||
local client=_DATABASE.CLIENTS[EventData.IniDCSUnitName] --Wrapper.Client#CLIENT
|
|
||||||
|
|
||||||
-- Add client in case it does not exist already.
|
|
||||||
if not client then
|
|
||||||
|
|
||||||
-- Debug info.
|
|
||||||
self:I(string.format("Player '%s' joined ground unit '%s' of group '%s'", tostring(EventData.IniPlayerName), tostring(EventData.IniDCSUnitName), tostring(EventData.IniDCSGroupName)))
|
|
||||||
|
|
||||||
client=_DATABASE:AddClient(EventData.IniDCSUnitName)
|
|
||||||
|
|
||||||
-- Add player.
|
|
||||||
client:AddPlayer(EventData.IniPlayerName)
|
|
||||||
|
|
||||||
-- Add player.
|
|
||||||
if not _DATABASE.PLAYERS[EventData.IniPlayerName] then
|
|
||||||
_DATABASE:AddPlayer( EventData.IniUnitName, EventData.IniPlayerName )
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Player settings.
|
|
||||||
local Settings = SETTINGS:Set( EventData.IniPlayerName )
|
|
||||||
Settings:SetPlayerMenu(EventData.IniUnit)
|
|
||||||
end
|
|
||||||
--local player = _DATABASE:FindClient( EventData.IniPlayerName )
|
|
||||||
self:Propagate(client)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Set this Client Manager to auto-propagate menus **once** to newly joined players. Useful if you have **one** menu structure only. Does not automatically push follow-up changes to the client(s).
|
|
||||||
-- @param #CLIENTMENUMANAGER self
|
|
||||||
-- @return #CLIENTMENUMANAGER self
|
|
||||||
function CLIENTMENUMANAGER:InitAutoPropagation()
|
|
||||||
-- Player Events
|
|
||||||
self:HandleEvent(EVENTS.PlayerLeaveUnit, self._EventHandler)
|
|
||||||
self:HandleEvent(EVENTS.Ejection, self._EventHandler)
|
|
||||||
self:HandleEvent(EVENTS.Crash, self._EventHandler)
|
|
||||||
self:HandleEvent(EVENTS.PilotDead, self._EventHandler)
|
|
||||||
self:HandleEvent(EVENTS.PlayerEnterAircraft, self._EventHandler)
|
|
||||||
self:HandleEvent(EVENTS.PlayerEnterUnit, self._EventHandler)
|
|
||||||
self:SetEventPriority(6)
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Create a new entry in the **generic** structure.
|
|
||||||
-- @param #CLIENTMENUMANAGER self
|
|
||||||
-- @param #string Text Text of the F10 menu entry.
|
|
||||||
-- @param #CLIENTMENU Parent The parent menu entry.
|
|
||||||
-- @param #string Function (optional) Function to call when the entry is used.
|
|
||||||
-- @param ... (optional) Arguments for the Function, comma separated.
|
|
||||||
-- @return #CLIENTMENU Entry
|
|
||||||
function CLIENTMENUMANAGER:NewEntry(Text,Parent,Function,...)
|
|
||||||
self:T(self.lid.."NewEntry "..Text or "None")
|
|
||||||
self.entrycount = self.entrycount + 1
|
|
||||||
local entry = CLIENTMENU:NewEntry(nil,Text,Parent,Function,unpack(arg))
|
|
||||||
if not Parent then
|
|
||||||
self.rootentries[self.entrycount] = entry
|
|
||||||
end
|
|
||||||
local depth = #entry.path
|
|
||||||
if not self.menutree[depth] then self.menutree[depth] = {} end
|
|
||||||
table.insert(self.menutree[depth],entry.UUID)
|
|
||||||
self.flattree[entry.UUID] = entry
|
|
||||||
return entry
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Check matching entry in the generic structure by UUID.
|
|
||||||
-- @param #CLIENTMENUMANAGER self
|
|
||||||
-- @param #string UUID UUID of the menu entry.
|
|
||||||
-- @return #boolean Exists
|
|
||||||
function CLIENTMENUMANAGER:EntryUUIDExists(UUID)
|
|
||||||
local exists = self.flattree[UUID] and true or false
|
|
||||||
return exists
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Find matching entry in the generic structure by UUID.
|
|
||||||
-- @param #CLIENTMENUMANAGER self
|
|
||||||
-- @param #string UUID UUID of the menu entry.
|
|
||||||
-- @return #CLIENTMENU Entry The #CLIENTMENU object found or nil.
|
|
||||||
function CLIENTMENUMANAGER:FindEntryByUUID(UUID)
|
|
||||||
self:T(self.lid.."FindEntryByUUID "..UUID or "None")
|
|
||||||
local entry = nil
|
|
||||||
for _gid,_entry in pairs(self.flattree) do
|
|
||||||
local Entry = _entry -- #CLIENTMENU
|
|
||||||
if Entry and Entry.UUID == UUID then
|
|
||||||
entry = Entry
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return entry
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Find matching entries by text in the generic structure by UUID.
|
|
||||||
-- @param #CLIENTMENUMANAGER self
|
|
||||||
-- @param #string Text Text or partial text of the menu entry to find.
|
|
||||||
-- @param #CLIENTMENU Parent (Optional) Only find entries under this parent entry.
|
|
||||||
-- @return #table Table of matching UUIDs of #CLIENTMENU objects
|
|
||||||
-- @return #table Table of matching #CLIENTMENU objects
|
|
||||||
-- @return #number Number of matches
|
|
||||||
function CLIENTMENUMANAGER:FindUUIDsByText(Text,Parent)
|
|
||||||
self:T(self.lid.."FindUUIDsByText "..Text or "None")
|
|
||||||
local matches = {}
|
|
||||||
local entries = {}
|
|
||||||
local n = 0
|
|
||||||
for _uuid,_entry in pairs(self.flattree) do
|
|
||||||
local Entry = _entry -- #CLIENTMENU
|
|
||||||
if Parent then
|
|
||||||
if Entry and string.find(Entry.name,Text,1,true) and string.find(Entry.UUID,Parent.UUID,1,true) then
|
|
||||||
table.insert(matches,_uuid)
|
|
||||||
table.insert(entries,Entry )
|
|
||||||
n=n+1
|
|
||||||
end
|
|
||||||
else
|
|
||||||
if Entry and string.find(Entry.name,Text,1,true) then
|
|
||||||
table.insert(matches,_uuid)
|
|
||||||
table.insert(entries,Entry )
|
|
||||||
n=n+1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return matches, entries, n
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Find matching entries in the generic structure by the menu text.
|
|
||||||
-- @param #CLIENTMENUMANAGER self
|
|
||||||
-- @param #string Text Text or partial text of the F10 menu entry.
|
|
||||||
-- @param #CLIENTMENU Parent (Optional) Only find entries under this parent entry.
|
|
||||||
-- @return #table Table of matching #CLIENTMENU objects.
|
|
||||||
-- @return #number Number of matches
|
|
||||||
function CLIENTMENUMANAGER:FindEntriesByText(Text,Parent)
|
|
||||||
self:T(self.lid.."FindEntriesByText "..Text or "None")
|
|
||||||
local matches, objects, number = self:FindUUIDsByText(Text, Parent)
|
|
||||||
return objects, number
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Find matching entries under a parent in the generic structure by UUID.
|
|
||||||
-- @param #CLIENTMENUMANAGER self
|
|
||||||
-- @param #CLIENTMENU Parent Find entries under this parent entry.
|
|
||||||
-- @return #table Table of matching UUIDs of #CLIENTMENU objects
|
|
||||||
-- @return #table Table of matching #CLIENTMENU objects
|
|
||||||
-- @return #number Number of matches
|
|
||||||
function CLIENTMENUMANAGER:FindUUIDsByParent(Parent)
|
|
||||||
self:T(self.lid.."FindUUIDsByParent")
|
|
||||||
local matches = {}
|
|
||||||
local entries = {}
|
|
||||||
local n = 0
|
|
||||||
for _uuid,_entry in pairs(self.flattree) do
|
|
||||||
local Entry = _entry -- #CLIENTMENU
|
|
||||||
if Parent then
|
|
||||||
if Entry and string.find(Entry.UUID,Parent.UUID,1,true) then
|
|
||||||
table.insert(matches,_uuid)
|
|
||||||
table.insert(entries,Entry )
|
|
||||||
n=n+1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return matches, entries, n
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Find matching entries in the generic structure under a parent.
|
|
||||||
-- @param #CLIENTMENUMANAGER self
|
|
||||||
-- @param #CLIENTMENU Parent Find entries under this parent entry.
|
|
||||||
-- @return #table Table of matching #CLIENTMENU objects.
|
|
||||||
-- @return #number Number of matches
|
|
||||||
function CLIENTMENUMANAGER:FindEntriesByParent(Parent)
|
|
||||||
self:T(self.lid.."FindEntriesByParent")
|
|
||||||
local matches, objects, number = self:FindUUIDsByParent(Parent)
|
|
||||||
return objects, number
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Alter the text of a leaf entry in the generic structure and push to one specific client's F10 menu.
|
|
||||||
-- @param #CLIENTMENUMANAGER self
|
|
||||||
-- @param #CLIENTMENU Entry The menu entry.
|
|
||||||
-- @param #string Text New Text of the F10 menu entry.
|
|
||||||
-- @param Wrapper.Client#CLIENT Client (optional) The client for whom to alter the entry, if nil done for all clients.
|
|
||||||
-- @return #CLIENTMENUMANAGER self
|
|
||||||
function CLIENTMENUMANAGER:ChangeEntryText(Entry, Text, Client)
|
|
||||||
self:T(self.lid.."ChangeEntryText "..Text or "None")
|
|
||||||
local newentry = CLIENTMENU:NewEntry(nil,Text,Entry.Parent,Entry.Function,unpack(Entry.Functionargs))
|
|
||||||
self:DeleteF10Entry(Entry,Client)
|
|
||||||
self:DeleteGenericEntry(Entry)
|
|
||||||
if not Entry.Parent then
|
|
||||||
self.rootentries[self.entrycount] = newentry
|
|
||||||
end
|
|
||||||
local depth = #newentry.path
|
|
||||||
if not self.menutree[depth] then self.menutree[depth] = {} end
|
|
||||||
table.insert(self.menutree[depth],newentry.UUID)
|
|
||||||
self.flattree[newentry.UUID] = newentry
|
|
||||||
self:AddEntry(newentry,Client)
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Push the complete menu structure to each of the clients in the set - refresh the menu tree of the clients.
|
|
||||||
-- @param #CLIENTMENUMANAGER self
|
|
||||||
-- @param Wrapper.Client#CLIENT Client (optional) If given, propagate only for this client.
|
|
||||||
-- @return #CLIENTMENU Entry
|
|
||||||
function CLIENTMENUMANAGER:Propagate(Client)
|
|
||||||
self:T(self.lid.."Propagate")
|
|
||||||
--self:I(UTILS.PrintTableToLog(Client,1))
|
|
||||||
local knownunits = {} -- track so we can ID multi seated
|
|
||||||
local Set = self.clientset.Set
|
|
||||||
if Client then
|
|
||||||
Set = {Client}
|
|
||||||
end
|
|
||||||
self:ResetMenu(Client)
|
|
||||||
for _,_client in pairs(Set) do
|
|
||||||
local client = _client -- Wrapper.Client#CLIENT
|
|
||||||
if client and client:IsAlive() then
|
|
||||||
local playerunit = client:GetName()
|
|
||||||
--local playergroup = client:GetGroup()
|
|
||||||
local playername = client:GetPlayerName() or "none"
|
|
||||||
if not knownunits[playerunit] then
|
|
||||||
knownunits[playerunit] = true
|
|
||||||
else
|
|
||||||
self:I("Player in multi seat unit: "..playername)
|
|
||||||
break -- multi seat already build
|
|
||||||
end
|
|
||||||
if not self.playertree[playername] then
|
|
||||||
self.playertree[playername] = {}
|
|
||||||
end
|
|
||||||
for level,branch in pairs (self.menutree) do
|
|
||||||
self:T("Building branch:" .. level)
|
|
||||||
for _,leaf in pairs(branch) do
|
|
||||||
self:T("Building leaf:" .. leaf)
|
|
||||||
local entry = self:FindEntryByUUID(leaf)
|
|
||||||
if entry then
|
|
||||||
self:T("Found generic entry:" .. entry.UUID)
|
|
||||||
local parent = nil
|
|
||||||
if entry.Parent and entry.Parent.UUID then
|
|
||||||
parent = self.playertree[playername][entry.Parent.UUID] or self:FindEntryByUUID(entry.Parent.UUID)
|
|
||||||
end
|
|
||||||
self.playertree[playername][entry.UUID] = CLIENTMENU:NewEntry(client,entry.name,parent,entry.Function,unpack(entry.Functionargs))
|
|
||||||
self.playertree[playername][entry.UUID].Once = entry.Once
|
|
||||||
else
|
|
||||||
self:T("NO generic entry for:" .. leaf)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Push a single previously created entry into the F10 menu structure of all clients.
|
|
||||||
-- @param #CLIENTMENUMANAGER self
|
|
||||||
-- @param #CLIENTMENU Entry The entry to add.
|
|
||||||
-- @param Wrapper.Client#CLIENT Client (optional) If given, make this change only for this client.
|
|
||||||
-- @return #CLIENTMENUMANAGER self
|
|
||||||
function CLIENTMENUMANAGER:AddEntry(Entry,Client)
|
|
||||||
self:T(self.lid.."AddEntry")
|
|
||||||
local Set = self.clientset.Set
|
|
||||||
local knownunits = {}
|
|
||||||
if Client then
|
|
||||||
Set = {Client}
|
|
||||||
end
|
|
||||||
for _,_client in pairs(Set) do
|
|
||||||
local client = _client -- Wrapper.Client#CLIENT
|
|
||||||
if client and client:IsAlive() then
|
|
||||||
local playername = client:GetPlayerName() or "None"
|
|
||||||
local unitname = client:GetName()
|
|
||||||
if not knownunits[unitname] then
|
|
||||||
knownunits[unitname] = true
|
|
||||||
else
|
|
||||||
self:I("Player in multi seat unit: "..playername)
|
|
||||||
break
|
|
||||||
end
|
|
||||||
if Entry then
|
|
||||||
self:T("Adding generic entry:" .. Entry.UUID)
|
|
||||||
local parent = nil
|
|
||||||
if not self.playertree[playername] then
|
|
||||||
self.playertree[playername] = {}
|
|
||||||
end
|
|
||||||
if Entry.Parent and Entry.Parent.UUID then
|
|
||||||
parent = self.playertree[playername][Entry.Parent.UUID] or self:FindEntryByUUID(Entry.Parent.UUID)
|
|
||||||
end
|
|
||||||
self.playertree[playername][Entry.UUID] = CLIENTMENU:NewEntry(client,Entry.name,parent,Entry.Function,unpack(Entry.Functionargs))
|
|
||||||
self.playertree[playername][Entry.UUID].Once = Entry.Once
|
|
||||||
else
|
|
||||||
self:T("NO generic entry given")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Blank out the menu - remove **all root entries** and all entries below from the client's F10 menus, leaving the generic structure untouched.
|
|
||||||
-- @param #CLIENTMENUMANAGER self
|
|
||||||
-- @param Wrapper.Client#CLIENT Client (optional) If given, remove only for this client.
|
|
||||||
-- @return #CLIENTMENUMANAGER self
|
|
||||||
function CLIENTMENUMANAGER:ResetMenu(Client)
|
|
||||||
self:T(self.lid.."ResetMenu")
|
|
||||||
for _,_entry in pairs(self.rootentries) do
|
|
||||||
--local RootEntry = self.structure.generic[_entry]
|
|
||||||
if _entry then
|
|
||||||
self:DeleteF10Entry(_entry,Client)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Blank out the menu - remove **all root entries** and all entries below from all clients' F10 menus, and **delete** the generic structure.
|
|
||||||
-- @param #CLIENTMENUMANAGER self
|
|
||||||
-- @return #CLIENTMENUMANAGER self
|
|
||||||
function CLIENTMENUMANAGER:ResetMenuComplete()
|
|
||||||
self:T(self.lid.."ResetMenuComplete")
|
|
||||||
for _,_entry in pairs(self.rootentries) do
|
|
||||||
--local RootEntry = self.structure.generic[_entry]
|
|
||||||
if _entry then
|
|
||||||
self:DeleteF10Entry(_entry)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
self.playertree = nil
|
|
||||||
self.playertree = {}
|
|
||||||
self.rootentries = nil
|
|
||||||
self.rootentries = {}
|
|
||||||
self.menutree = nil
|
|
||||||
self.menutree = {}
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Remove the entry and all entries below the given entry from the client's F10 menus.
|
|
||||||
-- @param #CLIENTMENUMANAGER self
|
|
||||||
-- @param #CLIENTMENU Entry The entry to remove
|
|
||||||
-- @param Wrapper.Client#CLIENT Client (optional) If given, make this change only for this client.
|
|
||||||
-- @return #CLIENTMENUMANAGER self
|
|
||||||
function CLIENTMENUMANAGER:DeleteF10Entry(Entry,Client)
|
|
||||||
self:T(self.lid.."DeleteF10Entry")
|
|
||||||
local Set = self.clientset.Set
|
|
||||||
if Client then
|
|
||||||
Set = {Client}
|
|
||||||
end
|
|
||||||
for _,_client in pairs(Set) do
|
|
||||||
if _client and _client:IsAlive() then
|
|
||||||
local playername = _client:GetPlayerName()
|
|
||||||
if self.playertree[playername] then
|
|
||||||
local centry = self.playertree[playername][Entry.UUID] -- #CLIENTMENU
|
|
||||||
if centry then
|
|
||||||
--self:I("Match for "..Entry.UUID)
|
|
||||||
centry:Clear()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Remove the entry and all entries below the given entry from the generic tree.
|
|
||||||
-- @param #CLIENTMENUMANAGER self
|
|
||||||
-- @param #CLIENTMENU Entry The entry to remove
|
|
||||||
-- @return #CLIENTMENUMANAGER self
|
|
||||||
function CLIENTMENUMANAGER:DeleteGenericEntry(Entry)
|
|
||||||
self:T(self.lid.."DeleteGenericEntry")
|
|
||||||
|
|
||||||
if Entry.Children and #Entry.Children > 0 then
|
|
||||||
self:RemoveGenericSubEntries(Entry)
|
|
||||||
end
|
|
||||||
|
|
||||||
local depth = #Entry.path
|
|
||||||
local uuid = Entry.UUID
|
|
||||||
|
|
||||||
local tbl = UTILS.DeepCopy(self.menutree)
|
|
||||||
|
|
||||||
if tbl[depth] then
|
|
||||||
for i=depth,#tbl do
|
|
||||||
--self:I("Level = "..i)
|
|
||||||
for _id,_uuid in pairs(tbl[i]) do
|
|
||||||
self:T(_uuid)
|
|
||||||
if string.find(_uuid,uuid,1,true) or _uuid == uuid then
|
|
||||||
--self:I("Match for ".._uuid)
|
|
||||||
self.menutree[i][_id] = nil
|
|
||||||
self.flattree[_uuid] = nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Remove all entries below the given entry from the generic tree.
|
|
||||||
-- @param #CLIENTMENUMANAGER self
|
|
||||||
-- @param #CLIENTMENU Entry The entry where to start. This entry stays.
|
|
||||||
-- @return #CLIENTMENUMANAGER self
|
|
||||||
function CLIENTMENUMANAGER:RemoveGenericSubEntries(Entry)
|
|
||||||
self:T(self.lid.."RemoveGenericSubEntries")
|
|
||||||
|
|
||||||
local depth = #Entry.path + 1
|
|
||||||
local uuid = Entry.UUID
|
|
||||||
|
|
||||||
local tbl = UTILS.DeepCopy(self.menutree)
|
|
||||||
|
|
||||||
if tbl[depth] then
|
|
||||||
for i=depth,#tbl do
|
|
||||||
self:T("Level = "..i)
|
|
||||||
for _id,_uuid in pairs(tbl[i]) do
|
|
||||||
self:T(_uuid)
|
|
||||||
if string.find(_uuid,uuid,1,true) then
|
|
||||||
self:T("Match for ".._uuid)
|
|
||||||
self.menutree[i][_id] = nil
|
|
||||||
self.flattree[_uuid] = nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
--- Remove all entries below the given entry from the client's F10 menus.
|
|
||||||
-- @param #CLIENTMENUMANAGER self
|
|
||||||
-- @param #CLIENTMENU Entry The entry where to start. This entry stays.
|
|
||||||
-- @param Wrapper.Client#CLIENT Client (optional) If given, make this change only for this client. In this case the generic structure will not be touched.
|
|
||||||
-- @return #CLIENTMENUMANAGER self
|
|
||||||
function CLIENTMENUMANAGER:RemoveF10SubEntries(Entry,Client)
|
|
||||||
self:T(self.lid.."RemoveSubEntries")
|
|
||||||
local Set = self.clientset.Set
|
|
||||||
if Client then
|
|
||||||
Set = {Client}
|
|
||||||
end
|
|
||||||
for _,_client in pairs(Set) do
|
|
||||||
if _client and _client:IsAlive() then
|
|
||||||
local playername = _client:GetPlayerName()
|
|
||||||
if self.playertree[playername] then
|
|
||||||
local centry = self.playertree[playername][Entry.UUID] -- #CLIENTMENU
|
|
||||||
centry:RemoveSubEntries()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
----------------------------------------------------------------------------------------------------------------
|
|
||||||
--
|
|
||||||
-- End ClientMenu
|
|
||||||
--
|
|
||||||
----------------------------------------------------------------------------------------------------------------
|
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -79,7 +79,7 @@
|
|||||||
|
|
||||||
do -- FSM
|
do -- FSM
|
||||||
|
|
||||||
-- @type FSM
|
--- @type FSM
|
||||||
-- @field #string ClassName Name of the class.
|
-- @field #string ClassName Name of the class.
|
||||||
-- @field Core.Scheduler#SCHEDULER CallScheduler Call scheduler.
|
-- @field Core.Scheduler#SCHEDULER CallScheduler Call scheduler.
|
||||||
-- @field #table options Options.
|
-- @field #table options Options.
|
||||||
@@ -948,9 +948,8 @@ do -- FSM
|
|||||||
end
|
end
|
||||||
|
|
||||||
do -- FSM_CONTROLLABLE
|
do -- FSM_CONTROLLABLE
|
||||||
|
|
||||||
---
|
--- @type FSM_CONTROLLABLE
|
||||||
-- @type FSM_CONTROLLABLE
|
|
||||||
-- @field Wrapper.Controllable#CONTROLLABLE Controllable
|
-- @field Wrapper.Controllable#CONTROLLABLE Controllable
|
||||||
-- @extends Core.Fsm#FSM
|
-- @extends Core.Fsm#FSM
|
||||||
|
|
||||||
@@ -1082,9 +1081,8 @@ do -- FSM_CONTROLLABLE
|
|||||||
end
|
end
|
||||||
|
|
||||||
do -- FSM_PROCESS
|
do -- FSM_PROCESS
|
||||||
|
|
||||||
---
|
--- @type FSM_PROCESS
|
||||||
-- @type FSM_PROCESS
|
|
||||||
-- @field Tasking.Task#TASK Task
|
-- @field Tasking.Task#TASK Task
|
||||||
-- @extends Core.Fsm#FSM_CONTROLLABLE
|
-- @extends Core.Fsm#FSM_CONTROLLABLE
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
do -- Goal
|
do -- Goal
|
||||||
|
|
||||||
-- @type GOAL
|
--- @type GOAL
|
||||||
-- @extends Core.Fsm#FSM
|
-- @extends Core.Fsm#FSM
|
||||||
|
|
||||||
--- Models processes that have an objective with a defined achievement. Derived classes implement the ways how the achievements can be realized.
|
--- Models processes that have an objective with a defined achievement. Derived classes implement the ways how the achievements can be realized.
|
||||||
@@ -71,10 +71,10 @@ do -- Goal
|
|||||||
ClassName = "GOAL",
|
ClassName = "GOAL",
|
||||||
}
|
}
|
||||||
|
|
||||||
-- @field #table GOAL.Players
|
--- @field #table GOAL.Players
|
||||||
GOAL.Players = {}
|
GOAL.Players = {}
|
||||||
|
|
||||||
-- @field #number GOAL.TotalContributions
|
--- @field #number GOAL.TotalContributions
|
||||||
GOAL.TotalContributions = 0
|
GOAL.TotalContributions = 0
|
||||||
|
|
||||||
--- GOAL Constructor.
|
--- GOAL Constructor.
|
||||||
@@ -145,7 +145,7 @@ do -- Goal
|
|||||||
self.TotalContributions = self.TotalContributions + 1
|
self.TotalContributions = self.TotalContributions + 1
|
||||||
end
|
end
|
||||||
|
|
||||||
-- @param #GOAL self
|
--- @param #GOAL self
|
||||||
-- @param #number Player contribution.
|
-- @param #number Player contribution.
|
||||||
function GOAL:GetPlayerContribution( PlayerName )
|
function GOAL:GetPlayerContribution( PlayerName )
|
||||||
return self.Players[PlayerName] or 0
|
return self.Players[PlayerName] or 0
|
||||||
|
|||||||
@@ -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,8 +163,14 @@ 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 matchtable = self:_MatchKeywords(Eventtext)
|
local coord=COORDINATE:NewFromVec3({y=Event.pos.y, x=Event.pos.x, z=Event.pos.z})
|
||||||
self:MarkAdded(Eventtext,matchtable,coord,Event.idx,coalition,Event.PlayerName,Event)
|
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)
|
||||||
|
self:MarkAdded(Eventtext,matchtable,coord,Event.idx,coalition,Event.PlayerName,Event)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
elseif Event.id==world.event.S_EVENT_MARK_CHANGE then
|
elseif Event.id==world.event.S_EVENT_MARK_CHANGE then
|
||||||
@@ -180,8 +179,14 @@ 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 matchtable = self:_MatchKeywords(Eventtext)
|
local coord=COORDINATE:NewFromVec3({y=Event.pos.y, x=Event.pos.x, z=Event.pos.z})
|
||||||
self:MarkChanged(Eventtext,matchtable,coord,Event.idx,coalition,Event.PlayerName,Event)
|
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)
|
||||||
|
self:MarkChanged(Eventtext,matchtable,coord,Event.idx,coalition,Event.PlayerName,Event)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
elseif Event.id==world.event.S_EVENT_MARK_REMOVED then
|
elseif Event.id==world.event.S_EVENT_MARK_REMOVED then
|
||||||
|
|||||||
@@ -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()
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -5,13 +5,11 @@
|
|||||||
-- * Path from A to B
|
-- * Path from A to B
|
||||||
-- * Arbitrary number of points
|
-- * Arbitrary number of points
|
||||||
-- * Automatically from lines drawtool
|
-- * Automatically from lines drawtool
|
||||||
-- * Draw line or mark points on F10 map
|
|
||||||
-- * Find closest points to path
|
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ### Author: **funkyfranky**
|
-- ### Author: **funkyfranky**
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
-- @module Core.Pathline
|
-- @module Core.Pathline
|
||||||
-- @image CORE_Pathline.png
|
-- @image CORE_Pathline.png
|
||||||
@@ -23,7 +21,6 @@
|
|||||||
-- @field #string lid Class id string for output to DCS log file.
|
-- @field #string lid Class id string for output to DCS log file.
|
||||||
-- @field #string name Name of the path line.
|
-- @field #string name Name of the path line.
|
||||||
-- @field #table points List of 3D points defining the path.
|
-- @field #table points List of 3D points defining the path.
|
||||||
-- @field #number counter Running number counting the point IDs.
|
|
||||||
-- @extends Core.Base#BASE
|
-- @extends Core.Base#BASE
|
||||||
|
|
||||||
--- *The shortest distance between two points is a straight line.* -- Archimedes
|
--- *The shortest distance between two points is a straight line.* -- Archimedes
|
||||||
@@ -31,30 +28,30 @@
|
|||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- # The PATHLINE Concept
|
-- # The PATHLINE Concept
|
||||||
--
|
--
|
||||||
-- List of points defining a path from A to B. The pathline can consist of multiple points. Each point holds the information of its position, the surface type, the land height
|
-- List of points defining a path from A to B. The pathline can consist of multiple points. Each point holds the information of its position, the surface type, the land height
|
||||||
-- and the water depth (if over sea).
|
-- and the water depth (if over sea).
|
||||||
--
|
--
|
||||||
-- Line drawings created in the mission editor are automatically registered as pathlines and stored in the MOOSE database.
|
-- Line drawings created in the mission editor are automatically registered as pathlines and stored in the MOOSE database.
|
||||||
-- They can be accessed with the @{#PATHLINE.FindByName) function.
|
-- They can be accessed with the @{#PATHLINE.FindByName) function.
|
||||||
--
|
--
|
||||||
-- # Constructor
|
-- # Constructor
|
||||||
--
|
--
|
||||||
-- The @{PATHLINE.New) function creates a new PATHLINE object. This does not hold any points. Points can be added with the @{#PATHLINE.AddPointFromVec2} and @{#PATHLINE.AddPointFromVec3}
|
-- The @{PATHLINE.New) function creates a new PATHLINE object. This does not hold any points. Points can be added with the @{#PATHLINE.AddPointFromVec2} and @{#PATHLINE.AddPointFromVec3}
|
||||||
--
|
--
|
||||||
-- For a given table of 2D or 3D positions, a new PATHLINE object can be created with the @{#PATHLINE.NewFromVec2Array} or @{#PATHLINE.NewFromVec3Array}, respectively.
|
-- For a given table of 2D or 3D positions, a new PATHLINE object can be created with the @{#PATHLINE.NewFromVec2Array} or @{#PATHLINE.NewFromVec3Array}, respectively.
|
||||||
--
|
--
|
||||||
-- # Line Drawings
|
-- # Line Drawings
|
||||||
--
|
--
|
||||||
-- The most convenient way to create a pathline is the draw panel feature in the DCS mission editor. You can select "Line" and then "Segments", "Segment" or "Free" to draw your lines.
|
-- The most convenient way to create a pathline is the draw panel feature in the DCS mission editor. You can select "Line" and then "Segments", "Segment" or "Free" to draw your lines.
|
||||||
-- These line drawings are then automatically added to the MOOSE database as PATHLINE objects and can be retrieved with the @{#PATHLINE.FindByName) function, where the name is the one
|
-- These line drawings are then automatically added to the MOOSE database as PATHLINE objects and can be retrieved with the @{#PATHLINE.FindByName) function, where the name is the one
|
||||||
-- you specify in the draw panel.
|
-- you specify in the draw panel.
|
||||||
--
|
--
|
||||||
-- # Mark on F10 map
|
-- # Mark on F10 map
|
||||||
--
|
--
|
||||||
-- The ponints of the PATHLINE can be marked on the F10 map with the @{#PATHLINE.MarkPoints}(`true`) function. The mark points contain information of the surface type, land height and
|
-- The ponints of the PATHLINE can be marked on the F10 map with the @{#PATHLINE.MarkPoints}(`true`) function. The mark points contain information of the surface type, land height and
|
||||||
-- water depth.
|
-- water depth.
|
||||||
--
|
--
|
||||||
-- To remove the marks, use @{#PATHLINE.MarkPoints}(`false`).
|
-- To remove the marks, use @{#PATHLINE.MarkPoints}(`false`).
|
||||||
--
|
--
|
||||||
-- @field #PATHLINE
|
-- @field #PATHLINE
|
||||||
@@ -62,39 +59,27 @@ PATHLINE = {
|
|||||||
ClassName = "PATHLINE",
|
ClassName = "PATHLINE",
|
||||||
lid = nil,
|
lid = nil,
|
||||||
points = {},
|
points = {},
|
||||||
counter = 0,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Point of line.
|
--- Point of line.
|
||||||
-- @type PATHLINE.Point
|
-- @type PATHLINE.Point
|
||||||
-- @field #number uid Unique ID of this point.
|
|
||||||
-- @field #string mother Name of the pathline this point belongs to.
|
|
||||||
-- @field #string name Name of this point.
|
|
||||||
-- @field DCS#Vec3 vec3 3D position.
|
-- @field DCS#Vec3 vec3 3D position.
|
||||||
-- @field DCS#Vec2 vec2 2D position.
|
-- @field DCS#Vec2 vec2 2D position.
|
||||||
-- @field #number surfaceType Surface type.
|
-- @field #number surfaceType Surface type.
|
||||||
-- @field #number landHeight Land height in meters.
|
-- @field #number landHeight Land height in meters.
|
||||||
-- @field #number depth Water depth in meters.
|
-- @field #number depth Water depth in meters.
|
||||||
-- @field #number markerID Marker ID.
|
-- @field #number markerID Marker ID.
|
||||||
-- @field #number lineID Marker of pathline ID.
|
|
||||||
|
|
||||||
--- Segment of line.
|
|
||||||
-- @type PATHLINE.Segment
|
|
||||||
-- @field #PATHLINE.Point p1 First point.
|
|
||||||
-- @field #PATHLINE.Point p2 Second point.
|
|
||||||
|
|
||||||
|
|
||||||
--- PATHLINE class version.
|
--- PATHLINE class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
PATHLINE.version="0.3.0"
|
PATHLINE.version="0.1.1"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- TODO list
|
-- TODO list
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
-- TODO: Read/write to JSON file
|
-- TODO: A lot...
|
||||||
-- TODO: Translate/rotate pathline
|
|
||||||
-- TODO: Add color.
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- Constructor
|
-- Constructor
|
||||||
@@ -108,10 +93,10 @@ function PATHLINE:New(Name)
|
|||||||
|
|
||||||
-- Inherit everything from INTEL class.
|
-- Inherit everything from INTEL class.
|
||||||
local self=BASE:Inherit(self, BASE:New()) --#PATHLINE
|
local self=BASE:Inherit(self, BASE:New()) --#PATHLINE
|
||||||
|
|
||||||
self.name=Name or "Unknown Path"
|
self.name=Name or "Unknown Path"
|
||||||
|
|
||||||
self.lid=string.format("PATHLINE %s | ", self.name)
|
self.lid=string.format("PATHLINE %s | ", Name)
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
@@ -166,70 +151,41 @@ end
|
|||||||
--- Add a point to the path from a given 2D position. The third dimension is determined from the land height.
|
--- Add a point to the path from a given 2D position. The third dimension is determined from the land height.
|
||||||
-- @param #PATHLINE self
|
-- @param #PATHLINE self
|
||||||
-- @param DCS#Vec2 Vec2 The 2D vector (x,y) to add.
|
-- @param DCS#Vec2 Vec2 The 2D vector (x,y) to add.
|
||||||
-- @param #number Index Index to add this point, *e.g.* 1 for first point or 2 for second point. Default is at the end.
|
|
||||||
-- @param #PATHLINE.Point Point Add point after given point. Default is at the end or at given index.
|
|
||||||
-- @return #PATHLINE self
|
-- @return #PATHLINE self
|
||||||
function PATHLINE:AddPointFromVec2(Vec2, Index, Point)
|
function PATHLINE:AddPointFromVec2(Vec2)
|
||||||
|
|
||||||
if Vec2 then
|
if Vec2 then
|
||||||
|
|
||||||
-- Create a new point.
|
|
||||||
local point=self:_CreatePoint(Vec2)
|
local point=self:_CreatePoint(Vec2)
|
||||||
|
|
||||||
if Index then
|
table.insert(self.points, point)
|
||||||
-- Add at given index.
|
|
||||||
table.insert(self.points, Index, point)
|
|
||||||
else
|
|
||||||
if Point then
|
|
||||||
-- Get index of given point.
|
|
||||||
local i=self:_GetPointIndex(Point)
|
|
||||||
-- Add new point after given point.
|
|
||||||
table.insert(self.points, i+1, point)
|
|
||||||
else
|
|
||||||
-- Add add the end.
|
|
||||||
table.insert(self.points, point)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Add a point to the path from a given 3D position.
|
--- Add a point to the path from a given 3D position.
|
||||||
-- @param #PATHLINE self
|
-- @param #PATHLINE self
|
||||||
-- @param DCS#Vec3 Vec3 The 3D vector (x,y) to add.
|
-- @param DCS#Vec3 Vec3 The 3D vector (x,y) to add.
|
||||||
-- @param #number Index Index to add this point, *e.g.* 1 for first point or 2 for second point. Default is at the end.
|
-- @return #PATHLINE self
|
||||||
-- @param #PATHLINE.Point Point Add point after given point. Default is at the end or at given index.
|
function PATHLINE:AddPointFromVec3(Vec3)
|
||||||
-- @return #PATHLINE.Point Point that was added.
|
|
||||||
function PATHLINE:AddPointFromVec3(Vec3, Index, Point)
|
|
||||||
|
|
||||||
if Vec3 then
|
if Vec3 then
|
||||||
|
|
||||||
local point=self:_CreatePoint(Vec3)
|
local point=self:_CreatePoint(Vec3)
|
||||||
|
|
||||||
if Index then
|
table.insert(self.points, point)
|
||||||
-- Add add given index.
|
|
||||||
table.insert(self.points, Index, point)
|
|
||||||
else
|
|
||||||
if Point then
|
|
||||||
local i=self:_GetPointIndex(Point)
|
|
||||||
table.insert(self.points, i+1, point)
|
|
||||||
else
|
|
||||||
-- Add add the end.
|
|
||||||
table.insert(self.points, point)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return point
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return nil
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Get name of pathline.
|
--- Get name of pathline.
|
||||||
-- @param #PATHLINE self
|
-- @param #PATHLINE self
|
||||||
-- @return #string Name of the pathline.
|
-- @return #string Name of the pathline.
|
||||||
function PATHLINE:GetName()
|
function PATHLINE:GetName()
|
||||||
return self.name
|
return self.name
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -243,35 +199,18 @@ end
|
|||||||
|
|
||||||
--- Get points of pathline. Not that points are tables, that contain more information as just the 2D or 3D position but also the surface type etc.
|
--- Get points of pathline. Not that points are tables, that contain more information as just the 2D or 3D position but also the surface type etc.
|
||||||
-- @param #PATHLINE self
|
-- @param #PATHLINE self
|
||||||
-- @return #list <Core.Pathline#PATHLINE.Point> List of points.
|
-- @return #list <#PATHLINE.Point> List of points.
|
||||||
function PATHLINE:GetPoints()
|
function PATHLINE:GetPoints()
|
||||||
return self.points
|
return self.points
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Get segments of pathline.
|
|
||||||
-- @param #PATHLINE self
|
|
||||||
-- @return #list <Core.Pathline#PATHLINE.Segment> List of points.
|
|
||||||
function PATHLINE:GetSetments()
|
|
||||||
|
|
||||||
local segments={}
|
|
||||||
|
|
||||||
for i=1,#self.points-1 do
|
|
||||||
local segment={} --#PATHLINE.Segment
|
|
||||||
segment.p1=self.points[i]
|
|
||||||
segment.p2=self.points[i+1]
|
|
||||||
table.insert(segments, segment)
|
|
||||||
end
|
|
||||||
|
|
||||||
return segments
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Get 3D points of pathline.
|
--- Get 3D points of pathline.
|
||||||
-- @param #PATHLINE self
|
-- @param #PATHLINE self
|
||||||
-- @return #list <DCS#Vec3> List of DCS#Vec3 points.
|
-- @return <DCS#Vec3> List of DCS#Vec3 points.
|
||||||
function PATHLINE:GetPoints3D()
|
function PATHLINE:GetPoints3D()
|
||||||
|
|
||||||
local vecs={}
|
local vecs={}
|
||||||
|
|
||||||
for _,_point in pairs(self.points) do
|
for _,_point in pairs(self.points) do
|
||||||
local point=_point --#PATHLINE.Point
|
local point=_point --#PATHLINE.Point
|
||||||
table.insert(vecs, point.vec3)
|
table.insert(vecs, point.vec3)
|
||||||
@@ -282,11 +221,11 @@ end
|
|||||||
|
|
||||||
--- Get 2D points of pathline.
|
--- Get 2D points of pathline.
|
||||||
-- @param #PATHLINE self
|
-- @param #PATHLINE self
|
||||||
-- @return #list <DCS#Vec2> List of DCS#Vec2 points.
|
-- @return <DCS#Vec2> List of DCS#Vec2 points.
|
||||||
function PATHLINE:GetPoints2D()
|
function PATHLINE:GetPoints2D()
|
||||||
|
|
||||||
local vecs={}
|
local vecs={}
|
||||||
|
|
||||||
for _,_point in pairs(self.points) do
|
for _,_point in pairs(self.points) do
|
||||||
local point=_point --#PATHLINE.Point
|
local point=_point --#PATHLINE.Point
|
||||||
table.insert(vecs, point.vec2)
|
table.insert(vecs, point.vec2)
|
||||||
@@ -301,11 +240,11 @@ end
|
|||||||
function PATHLINE:GetCoordinates()
|
function PATHLINE:GetCoordinates()
|
||||||
|
|
||||||
local vecs={}
|
local vecs={}
|
||||||
|
|
||||||
for _,_point in pairs(self.points) do
|
for _,_point in pairs(self.points) do
|
||||||
local point=_point --#PATHLINE.Point
|
local point=_point --#PATHLINE.Point
|
||||||
local coord=COORDINATE:NewFromVec3(point.vec3)
|
local coord=COORDINATE:NewFromVec3(point.vec3)
|
||||||
table.insert(vecs, coord)
|
table.insert(vecs,coord)
|
||||||
end
|
end
|
||||||
|
|
||||||
return vecs
|
return vecs
|
||||||
@@ -318,11 +257,11 @@ end
|
|||||||
function PATHLINE:GetPointFromIndex(n)
|
function PATHLINE:GetPointFromIndex(n)
|
||||||
|
|
||||||
local N=self:GetNumberOfPoints()
|
local N=self:GetNumberOfPoints()
|
||||||
|
|
||||||
n=n or 1
|
n=n or 1
|
||||||
|
|
||||||
local point=nil --#PATHLINE.Point
|
local point=nil --#PATHLINE.Point
|
||||||
|
|
||||||
if n>=1 and n<=N then
|
if n>=1 and n<=N then
|
||||||
point=self.points[n]
|
point=self.points[n]
|
||||||
else
|
else
|
||||||
@@ -339,11 +278,11 @@ end
|
|||||||
function PATHLINE:GetPoint3DFromIndex(n)
|
function PATHLINE:GetPoint3DFromIndex(n)
|
||||||
|
|
||||||
local point=self:GetPointFromIndex(n)
|
local point=self:GetPointFromIndex(n)
|
||||||
|
|
||||||
if point then
|
if point then
|
||||||
return point.vec3
|
return point.vec3
|
||||||
end
|
end
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -354,11 +293,11 @@ end
|
|||||||
function PATHLINE:GetPoint2DFromIndex(n)
|
function PATHLINE:GetPoint2DFromIndex(n)
|
||||||
|
|
||||||
local point=self:GetPointFromIndex(n)
|
local point=self:GetPointFromIndex(n)
|
||||||
|
|
||||||
if point then
|
if point then
|
||||||
return point.vec2
|
return point.vec2
|
||||||
end
|
end
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -366,314 +305,33 @@ end
|
|||||||
--- Mark points on F10 map.
|
--- Mark points on F10 map.
|
||||||
-- @param #PATHLINE self
|
-- @param #PATHLINE self
|
||||||
-- @param #boolean Switch If `true` or nil, set marks. If `false`, remove marks.
|
-- @param #boolean Switch If `true` or nil, set marks. If `false`, remove marks.
|
||||||
-- @return #PATHLINE self
|
-- @return <DCS#Vec3> List of DCS#Vec3 points.
|
||||||
function PATHLINE:MarkPoints(Switch)
|
function PATHLINE:MarkPoints(Switch)
|
||||||
|
|
||||||
for i,_point in pairs(self.points) do
|
for i,_point in pairs(self.points) do
|
||||||
local point=_point --#PATHLINE.Point
|
local point=_point --#PATHLINE.Point
|
||||||
|
|
||||||
if Switch==false then
|
if Switch==false then
|
||||||
|
|
||||||
if point.markerID then
|
if point.markerID then
|
||||||
UTILS.RemoveMark(point.markerID)
|
UTILS.RemoveMark(point.markerID, Delay)
|
||||||
end
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
if point.markerID then
|
if point.markerID then
|
||||||
UTILS.RemoveMark(point.markerID)
|
UTILS.RemoveMark(point.markerID)
|
||||||
end
|
end
|
||||||
|
|
||||||
point.markerID=UTILS.GetMarkID()
|
point.markerID=UTILS.GetMarkID()
|
||||||
|
|
||||||
local text=string.format("Pathline %s: Point #%d [UID=%d]\nSurface Type=%d\nHeight=%.1f m\nDepth=%.1f m", self.name, i, point.uid, point.surfaceType, point.landHeight, point.depth)
|
local text=string.format("Pathline %s: Point #%d\nSurface Type=%d\nHeight=%.1f m\nDepth=%.1f m", self.name, i, point.surfaceType, point.landHeight, point.depth)
|
||||||
|
|
||||||
trigger.action.markToAll(point.markerID, text, point.vec3, "")
|
trigger.action.markToAll(point.markerID, text, point.vec3, "")
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Draw line on F10 map.
|
|
||||||
-- @param #PATHLINE self
|
|
||||||
-- @param #boolean Switch If `true` or nil, draw pathline. If `false`, remove drawing.
|
|
||||||
-- @param #number Coalition Coalition side. Default -1 for all.
|
|
||||||
-- @param #table Color RGB color and alpha `{r, g, b, a}`. Default {0, 1, 0, 0.5}.
|
|
||||||
-- @param #number LineType Line type. Default 1=solid.
|
|
||||||
-- @return #PATHLINE self
|
|
||||||
function PATHLINE:Draw(Switch, Coalition, Color, LineType)
|
|
||||||
|
|
||||||
Coalition=Coalition or -1
|
|
||||||
Color=Color or {0, 1, 0, 0.5}
|
|
||||||
LineType=LineType or 1
|
|
||||||
|
|
||||||
if Switch==false then
|
|
||||||
|
|
||||||
for i,_point in pairs(self.points) do
|
|
||||||
local point=_point --#PATHLINE.Point
|
|
||||||
|
|
||||||
if point.lineID then
|
|
||||||
UTILS.RemoveMark(point.lineID)
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
else
|
|
||||||
|
|
||||||
for i=2,#self.points do
|
|
||||||
|
|
||||||
local p1=self.points[i-1] --#PATHLINE.Point
|
|
||||||
local p2=self.points[i] --#PATHLINE.Point
|
|
||||||
|
|
||||||
if p2.lineID then
|
|
||||||
UTILS.RemoveMark(p2.lineID)
|
|
||||||
end
|
|
||||||
|
|
||||||
p2.lineID=UTILS.GetMarkID()
|
|
||||||
|
|
||||||
trigger.action.lineToAll(Coalition, p2.lineID, p1.vec3, p2.vec3, Color, LineType)
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Get the closest point on the pathline for a given reference point.
|
|
||||||
-- @param #PATHLINE self
|
|
||||||
-- @param DCS#Vec2 Vec2 Reference Point in 2D.
|
|
||||||
-- @return DCS#Vec2 Cloest point on pathline.
|
|
||||||
-- @return #number Distance from closest point to ref point in meters.
|
|
||||||
-- @return #PATHLINE.Segment Closest segment of ref point.
|
|
||||||
function PATHLINE:GetClosestPoint2D(Vec2)
|
|
||||||
|
|
||||||
local P=nil --DCS#Vec2
|
|
||||||
local D=math.huge
|
|
||||||
local S={} --#PATHLINE.Segment
|
|
||||||
|
|
||||||
for i=2,#self.points do
|
|
||||||
|
|
||||||
local A=self.points[i-1] --#PATHLINE.Point
|
|
||||||
local B=self.points[i] --#PATHLINE.Point
|
|
||||||
|
|
||||||
local a=A.vec2
|
|
||||||
local b=B.vec2
|
|
||||||
|
|
||||||
local ab=UTILS.Vec2Substract(b, a)
|
|
||||||
local ap=UTILS.Vec2Substract(Vec2, a)
|
|
||||||
|
|
||||||
local proj=UTILS.Vec2Dot(ap, ab)
|
|
||||||
|
|
||||||
local lab=UTILS.Vec2Norm(ab)
|
|
||||||
|
|
||||||
local f=proj/lab/lab
|
|
||||||
|
|
||||||
-- Debug info.
|
|
||||||
local text=string.format("FF Proj=%.1f, |ab|=%.1f, f=%.1f", proj, lab, f)
|
|
||||||
self:T(self.lid..text)
|
|
||||||
|
|
||||||
-- Cases for finite segment.
|
|
||||||
local p=nil --DCS#Vec2
|
|
||||||
if f<0 then
|
|
||||||
p=a
|
|
||||||
elseif f>1 then
|
|
||||||
p=b
|
|
||||||
else
|
|
||||||
local r=UTILS.Vec2Mult(ab, f)
|
|
||||||
p=UTILS.Vec2Add(a, r)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Distance.
|
|
||||||
local d=UTILS.VecDist2D(p, Vec2)
|
|
||||||
|
|
||||||
if d<=D then
|
|
||||||
D=d
|
|
||||||
P=p
|
|
||||||
S.p1=A
|
|
||||||
S.p2=B
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
return P, D, S
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Get the closest point on the pathline for a given reference point.
|
|
||||||
-- This point does not necessarily is a node of the pathline. In general it will be somewhere in between the nodes defining the pathline.
|
|
||||||
-- @param #PATHLINE self
|
|
||||||
-- @param DCS#Vec3 Vec3 Reference Point in 3D. Can also be a `COORDINATE`.
|
|
||||||
-- @return DCS#Vec3 Closest point on pathline.
|
|
||||||
-- @return #number Distance from closest point to ref point in meters.
|
|
||||||
-- @return #PATHLINE.Segment Closest segment of ref point.
|
|
||||||
function PATHLINE:GetClosestPoint3D(Vec3)
|
|
||||||
|
|
||||||
local P=nil --DCS#Vec3
|
|
||||||
local D=math.huge
|
|
||||||
local S={} --#PATHLINE.Segment
|
|
||||||
|
|
||||||
if not Vec3 then
|
|
||||||
self:E(self.lid.."ERROR: input Vec3 is nil!")
|
|
||||||
return nil, nil, nil
|
|
||||||
end
|
|
||||||
|
|
||||||
for i=2,#self.points do
|
|
||||||
|
|
||||||
local A=self.points[i-1] --#PATHLINE.Point
|
|
||||||
local B=self.points[i] --#PATHLINE.Point
|
|
||||||
|
|
||||||
local a=A.vec3
|
|
||||||
local b=B.vec3
|
|
||||||
|
|
||||||
local ab=UTILS.VecSubstract(b, a)
|
|
||||||
local ap=UTILS.VecSubstract(Vec3, a)
|
|
||||||
|
|
||||||
local proj=UTILS.VecDot(ap, ab)
|
|
||||||
|
|
||||||
local lab=UTILS.VecNorm(ab)
|
|
||||||
|
|
||||||
local f=proj/lab/lab
|
|
||||||
|
|
||||||
-- Debug info.
|
|
||||||
self:T(self.lid..string.format("Proj=%.1f, |ab|=%.1f, f=%.1f", proj, lab, f))
|
|
||||||
|
|
||||||
-- Cases for finite segment.
|
|
||||||
local p=nil --DCS#Vec2
|
|
||||||
if f<0 then
|
|
||||||
p=a
|
|
||||||
elseif f>1 then
|
|
||||||
p=b
|
|
||||||
else
|
|
||||||
local r=UTILS.VecMult(ab, f)
|
|
||||||
p=UTILS.VecAdd(a, r)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Distance.
|
|
||||||
local d=UTILS.VecDist3D(p, Vec3)
|
|
||||||
|
|
||||||
if d<=D then
|
|
||||||
D=d
|
|
||||||
P=p
|
|
||||||
S.p1=A
|
|
||||||
S.p2=B
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
return P, D, S
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
--- Write PATHLINE to JSON file.
|
|
||||||
-- **NOTE**: Requires `io` and `lfs` to be de-sanitized!
|
|
||||||
-- @param #PATHLINE self
|
|
||||||
-- @param #string FileName Name of the file. Default is the name of the pathline.
|
|
||||||
-- @return #PATHLINE self
|
|
||||||
function PATHLINE:WriteJSON(FileName)
|
|
||||||
|
|
||||||
if io and lfs then
|
|
||||||
|
|
||||||
-- JSON script.
|
|
||||||
local json=loadfile("Scripts\\JSON.lua")()
|
|
||||||
|
|
||||||
local data={}
|
|
||||||
|
|
||||||
-- We store the name and the points.
|
|
||||||
data.name=self.name
|
|
||||||
data.points=self.points
|
|
||||||
for i,_point in pairs(self.points) do
|
|
||||||
local point=_point --#PATHLINE.Point
|
|
||||||
--point.markerID=nil
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Encode data to raw JSON. Encode converts a lua table into JSON string that can be written to file.
|
|
||||||
local raw_json=json:encode(data)
|
|
||||||
|
|
||||||
-- Debug data.
|
|
||||||
self:T(data)
|
|
||||||
|
|
||||||
-- Write in "User/Saved Games/" Folder.
|
|
||||||
local filepath=lfs.writedir() .. FileName
|
|
||||||
|
|
||||||
-- Open file for writing.
|
|
||||||
local f = io.open(filepath, "wb")
|
|
||||||
if f then
|
|
||||||
f:write(raw_json)
|
|
||||||
f:close()
|
|
||||||
self:T(self.lid .. string.format("Saving PATHLINE %s file %s", self.name, tostring(filepath)))
|
|
||||||
else
|
|
||||||
self:E(self.lid .. string.format( "ERROR: Could not save PATHLINE to file %s", tostring(filepath)))
|
|
||||||
end
|
|
||||||
|
|
||||||
else
|
|
||||||
self:E(self.lid .. string.format( "ERROR: Could not save results because IO and/or LFS are not de-sanitized!"))
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Read PATHLINE from JSON file.
|
|
||||||
-- **NOTE**: Requires `io` and `lfs` to be de-sanitized!
|
|
||||||
-- @param #PATHLINE self
|
|
||||||
-- @param #string FileName Name of the file.
|
|
||||||
-- @return #PATHLINE self
|
|
||||||
function PATHLINE:NewFromJSON(FileName)
|
|
||||||
|
|
||||||
if io and lfs then
|
|
||||||
|
|
||||||
-- JSON script.
|
|
||||||
local json=loadfile("Scripts\\JSON.lua")()
|
|
||||||
|
|
||||||
local data={}
|
|
||||||
|
|
||||||
-- Write in "User/Saved Games/" Folder.
|
|
||||||
local filepath=lfs.writedir() .. FileName
|
|
||||||
|
|
||||||
--env.info(filepath)
|
|
||||||
|
|
||||||
-- Open file in binary mode for reading.
|
|
||||||
local f = io.open(filepath, "rb")
|
|
||||||
if f then
|
|
||||||
data = f:read("*all")
|
|
||||||
f:close()
|
|
||||||
else
|
|
||||||
env.info(string.format("WARNING: Could not load PATHLINE from file %s!", tostring(filepath)))
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Decode JSON data to get a lua table.
|
|
||||||
local data=json:decode(data)
|
|
||||||
|
|
||||||
if data and data.name then
|
|
||||||
|
|
||||||
-- Create a new pathline instance.
|
|
||||||
local self=PATHLINE:New(data.name)
|
|
||||||
|
|
||||||
for i=1,#data.points do
|
|
||||||
local point=data.points[i] --#PATHLINE.Point
|
|
||||||
|
|
||||||
-- Create new point from data.
|
|
||||||
local p=self:AddPointFromVec3(point.vec3)
|
|
||||||
|
|
||||||
-- Set name.
|
|
||||||
p.name=point.name
|
|
||||||
|
|
||||||
-- Remove marker ID.
|
|
||||||
p.markerID=nil
|
|
||||||
end
|
|
||||||
|
|
||||||
return self
|
|
||||||
else
|
|
||||||
BASE:E("ERROR: Cannot find pathline name in data from JSON file. File may be corrupted!")
|
|
||||||
end
|
|
||||||
else
|
|
||||||
BASE:E("ERROR: IO and/or LFS not de-sanitized! Cannot read file.")
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- Private functions
|
-- Private functions
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
@@ -681,56 +339,32 @@ end
|
|||||||
--- Get 3D points of pathline.
|
--- Get 3D points of pathline.
|
||||||
-- @param #PATHLINE self
|
-- @param #PATHLINE self
|
||||||
-- @param DCS#Vec3 Vec Position vector. Can also be a DCS#Vec2 in which case the altitude at landheight is taken.
|
-- @param DCS#Vec3 Vec Position vector. Can also be a DCS#Vec2 in which case the altitude at landheight is taken.
|
||||||
-- @return #PATHLINE.Point Pathline Point.
|
-- @return #PATHLINE.Point
|
||||||
function PATHLINE:_CreatePoint(Vec)
|
function PATHLINE:_CreatePoint(Vec)
|
||||||
|
|
||||||
local point={} --#PATHLINE.Point
|
local point={} --#PATHLINE.Point
|
||||||
|
|
||||||
self.counter=self.counter+1
|
|
||||||
|
|
||||||
point.uid=self.counter
|
|
||||||
point.mother=self.name
|
|
||||||
|
|
||||||
point.name=string.format("%s #%d", self.name, point.uid)
|
|
||||||
|
|
||||||
if Vec.z then
|
if Vec.z then
|
||||||
-- Given vec is 3D
|
-- Given vec is 3D
|
||||||
point.vec3=UTILS.DeepCopy(Vec)
|
point.vec3=UTILS.DeepCopy(Vec)
|
||||||
point.vec2={x=Vec.x, y=Vec.z}
|
point.vec2={x=Vec.x, y=Vec.z}
|
||||||
else
|
else
|
||||||
-- Given vec is 2D
|
-- Given vec is 2D
|
||||||
point.vec2=UTILS.DeepCopy(Vec)
|
point.vec2=UTILS.DeepCopy(Vec)
|
||||||
point.vec3={x=Vec.x, y=land.getHeight(Vec), z=Vec.y}
|
point.vec3={x=Vec.x, y=land.getHeight(Vec), z=Vec.y}
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Get surface type.
|
-- Get surface type.
|
||||||
point.surfaceType=land.getSurfaceType(point.vec2)
|
point.surfaceType=land.getSurfaceType(point.vec2)
|
||||||
|
|
||||||
-- Get land height and depth.
|
-- Get land height and depth.
|
||||||
point.landHeight, point.depth=land.getSurfaceHeightWithSeabed(point.vec2)
|
point.landHeight, point.depth=land.getSurfaceHeightWithSeabed(point.vec2)
|
||||||
|
|
||||||
point.markerID=nil
|
point.markerID=nil
|
||||||
|
|
||||||
return point
|
return point
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Get index of point in the lua table.
|
|
||||||
-- @param #PATHLINE self
|
|
||||||
-- @param #PATHLINE.Point Point Given point.
|
|
||||||
-- @return #number index
|
|
||||||
function PATHLINE:_GetPointIndex(Point)
|
|
||||||
|
|
||||||
for i,_point in pairs(self.points) do
|
|
||||||
local point=_point --#PATHLINE.Point
|
|
||||||
|
|
||||||
if point.uid==Point.uid then
|
|
||||||
return i
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -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
|
||||||
--
|
--
|
||||||
@@ -453,23 +457,6 @@ do -- COORDINATE
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Returns the coordinate from the latitude and longitude given in degrees, minutes and seconds (DMS).
|
|
||||||
-- @param #COORDINATE self
|
|
||||||
-- @param #string Latitude Latitude in DMS as string, e.g. "`42° 24' 14.3"`". Not that the characters `°`, `'` and `"` are important.
|
|
||||||
-- @param #string Longitude Longitude in DMS as string, e.g. "`42° 24' 14.3"`". Not that the characters `°`, `'` and `"` are important.
|
|
||||||
-- @param #number Altitude (Optional) Altitude in meters. Default is the land height at the coordinate.
|
|
||||||
-- @return #COORDINATE
|
|
||||||
function COORDINATE:NewFromLLDMS(Latitude, Longitude, Altitude)
|
|
||||||
|
|
||||||
local lat=UTILS.LLDMSstringToDD(Latitude)
|
|
||||||
local lon=UTILS.LLDMSstringToDD(Longitude)
|
|
||||||
|
|
||||||
self=COORDINATE:NewFromLLDD(lat, lon, Altitude)
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
--- Returns if the 2 coordinates are at the same 2D position.
|
--- Returns if the 2 coordinates are at the same 2D position.
|
||||||
-- @param #COORDINATE self
|
-- @param #COORDINATE self
|
||||||
-- @param #COORDINATE Coordinate
|
-- @param #COORDINATE Coordinate
|
||||||
@@ -678,7 +665,7 @@ do -- COORDINATE
|
|||||||
local _,_,_,_,_,scenerys=self:ScanObjects(radius, false, false, true)
|
local _,_,_,_,_,scenerys=self:ScanObjects(radius, false, false, true)
|
||||||
|
|
||||||
local set={}
|
local set={}
|
||||||
|
|
||||||
for _,_scenery in pairs(scenerys) do
|
for _,_scenery in pairs(scenerys) do
|
||||||
local scenery=_scenery --DCS#Object
|
local scenery=_scenery --DCS#Object
|
||||||
|
|
||||||
@@ -790,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
|
||||||
@@ -850,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
|
||||||
@@ -2135,14 +2144,112 @@ 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.
|
||||||
trigger.action.smoke( self:GetVec3(), SmokeColor, self.firename )
|
-- @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 )
|
||||||
|
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
|
end
|
||||||
|
|
||||||
--- Stops smoking the point in a color.
|
--- Stops smoking the point in a color.
|
||||||
@@ -2154,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.
|
||||||
@@ -2209,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.
|
||||||
@@ -2938,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 sunrise == "N/R" then return false end
|
if type(sunrise) == "string" or type(sunset) == "string" then
|
||||||
if sunrise == "N/S" then return true end
|
if sunrise == "N/R" then return false end
|
||||||
|
if sunset == "N/S" then return true end
|
||||||
|
end
|
||||||
|
|
||||||
local time=UTILS.ClockToSeconds(clock)
|
local time=UTILS.ClockToSeconds(clock)
|
||||||
|
|
||||||
@@ -2957,6 +3116,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()
|
||||||
@@ -3655,7 +3819,26 @@ do -- COORDINATE
|
|||||||
function COORDINATE:GetRandomPointVec3InRadius( OuterRadius, InnerRadius )
|
function COORDINATE:GetRandomPointVec3InRadius( OuterRadius, InnerRadius )
|
||||||
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
|
||||||
|
|||||||
@@ -15,8 +15,7 @@
|
|||||||
-- @module Core.Report
|
-- @module Core.Report
|
||||||
-- @image Core_Report.JPG
|
-- @image Core_Report.JPG
|
||||||
|
|
||||||
---
|
--- @type REPORT
|
||||||
-- @type REPORT
|
|
||||||
-- @extends Core.Base#BASE
|
-- @extends Core.Base#BASE
|
||||||
|
|
||||||
--- Provides a handy means to create messages and reports.
|
--- Provides a handy means to create messages and reports.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
---- **Core** - SCHEDULEDISPATCHER dispatches the different schedules.
|
--- **Core** - SCHEDULEDISPATCHER dispatches the different schedules.
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
@@ -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 ) ) )
|
||||||
|
|
||||||
|
|||||||
@@ -958,7 +958,26 @@ 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,18 +2614,16 @@ 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()
|
||||||
|
|
||||||
local AliveSet = SET_UNIT:New()
|
local AliveSet = SET_UNIT:New()
|
||||||
|
|
||||||
-- 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,8 +464,9 @@ 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
|
||||||
|
|
||||||
@@ -549,6 +555,13 @@ function SPAWNSTATIC:_SpawnStatic(Template, CountryID)
|
|||||||
TemplateGroup.x=Template.x
|
TemplateGroup.x=Template.x
|
||||||
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})
|
||||||
@@ -556,7 +569,8 @@ function SPAWNSTATIC:_SpawnStatic(Template, CountryID)
|
|||||||
|
|
||||||
-- 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
|
||||||
local Event = {
|
local Event = {
|
||||||
@@ -594,6 +608,19 @@ function SPAWNSTATIC:_SpawnStatic(Template, CountryID)
|
|||||||
-- delay calling this for .3 seconds so that it hopefully comes after the BIRTH event of the group.
|
-- delay calling this for .3 seconds so that it hopefully comes after the BIRTH event of the group.
|
||||||
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
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
do -- UserFlag
|
do -- UserFlag
|
||||||
|
|
||||||
-- @type USERFLAG
|
--- @type USERFLAG
|
||||||
-- @field #string ClassName Name of the class
|
-- @field #string ClassName Name of the class
|
||||||
-- @field #string UserFlagName Name of the flag.
|
-- @field #string UserFlagName Name of the flag.
|
||||||
-- @extends Core.Base#BASE
|
-- @extends Core.Base#BASE
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
do -- Velocity
|
do -- Velocity
|
||||||
|
|
||||||
-- @type VELOCITY
|
--- @type VELOCITY
|
||||||
-- @extends Core.Base#BASE
|
-- @extends Core.Base#BASE
|
||||||
|
|
||||||
|
|
||||||
@@ -127,7 +127,7 @@ end
|
|||||||
|
|
||||||
do -- VELOCITY_POSITIONABLE
|
do -- VELOCITY_POSITIONABLE
|
||||||
|
|
||||||
-- @type VELOCITY_POSITIONABLE
|
--- @type VELOCITY_POSITIONABLE
|
||||||
-- @extends Core.Base#BASE
|
-- @extends Core.Base#BASE
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|
||||||
@@ -305,20 +306,6 @@ function ZONE_BASE:GetCoordinate( Height ) --R2.1
|
|||||||
return self.Coordinate
|
return self.Coordinate
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Returns the @{Core.Vector#VECTOR} of the zone.
|
|
||||||
-- @param #ZONE_BASE self
|
|
||||||
-- @param DCS#Distance Height The height in meters to add to the land height where the center of the zone is located.
|
|
||||||
-- @return Core.Vector#VECTOR The vector of the zone.
|
|
||||||
function ZONE_BASE:GetVector( Height )
|
|
||||||
self:F2(self.ZoneName)
|
|
||||||
|
|
||||||
local Vec3 = self:GetVec3( Height )
|
|
||||||
|
|
||||||
local vector=VECTOR:NewFromVec(Vec3)
|
|
||||||
|
|
||||||
return vector
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Get 2D distance to a coordinate.
|
--- Get 2D distance to a coordinate.
|
||||||
-- @param #ZONE_BASE self
|
-- @param #ZONE_BASE self
|
||||||
-- @param Core.Point#COORDINATE Coordinate Reference coordinate. Can also be a DCS#Vec2 or DCS#Vec3 object.
|
-- @param Core.Point#COORDINATE Coordinate Reference coordinate. Can also be a DCS#Vec2 or DCS#Vec3 object.
|
||||||
@@ -548,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.
|
||||||
@@ -613,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")
|
||||||
@@ -681,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
|
||||||
@@ -719,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
|
||||||
@@ -1523,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.
|
||||||
@@ -1534,6 +1571,10 @@ function ZONE_RADIUS:GetRandomVec2(inner, outer, surfacetypes)
|
|||||||
local Vec2 = self:GetVec2()
|
local Vec2 = self:GetVec2()
|
||||||
local _inner = inner or 0
|
local _inner = inner or 0
|
||||||
local _outer = outer or self:GetRadius()
|
local _outer = outer or self:GetRadius()
|
||||||
|
|
||||||
|
math.random()
|
||||||
|
math.random()
|
||||||
|
math.random()
|
||||||
|
|
||||||
if surfacetypes and type(surfacetypes)~="table" then
|
if surfacetypes and type(surfacetypes)~="table" then
|
||||||
surfacetypes={surfacetypes}
|
surfacetypes={surfacetypes}
|
||||||
@@ -2501,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.
|
||||||
@@ -2879,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
|
||||||
@@ -3218,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
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,806 +0,0 @@
|
|||||||
--- **Functional** -- Send a truck to supply artillery groups.
|
|
||||||
--
|
|
||||||
-- ===
|
|
||||||
--
|
|
||||||
-- **AMMOTRUCK** - Send a truck to supply artillery groups.
|
|
||||||
--
|
|
||||||
-- ===
|
|
||||||
--
|
|
||||||
-- ## Missions:
|
|
||||||
--
|
|
||||||
-- Demo missions can be found on [GitHub](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/Functional/AmmoTruck)
|
|
||||||
--
|
|
||||||
-- ===
|
|
||||||
--
|
|
||||||
-- ### Author : **applevangelist**
|
|
||||||
--
|
|
||||||
-- @module Functional.AmmoTruck
|
|
||||||
-- @image Artillery.JPG
|
|
||||||
--
|
|
||||||
-- Last update: July 2023
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------
|
|
||||||
--- **AMMOTRUCK** class, extends Core.Fsm#FSM
|
|
||||||
-- @type AMMOTRUCK
|
|
||||||
-- @field #string ClassName Class Name
|
|
||||||
-- @field #string lid Lid for log entries
|
|
||||||
-- @field #string version Version string
|
|
||||||
-- @field #string alias Alias name
|
|
||||||
-- @field #boolean debug Debug flag
|
|
||||||
-- @field #table trucklist List of (alive) #AMMOTRUCK.data trucks
|
|
||||||
-- @field #table targetlist List of (alive) #AMMOTRUCK.data artillery
|
|
||||||
-- @field #number coalition Coalition this is for
|
|
||||||
-- @field Core.Set#SET_GROUP truckset SET of trucks
|
|
||||||
-- @field Core.Set#SET_GROUP targetset SET of artillery
|
|
||||||
-- @field #table remunitionqueue List of (alive) #AMMOTRUCK.data artillery to be reloaded
|
|
||||||
-- @field #table waitingtargets List of (alive) #AMMOTRUCK.data artillery waiting
|
|
||||||
-- @field #number ammothreshold Threshold (min) ammo before sending a truck
|
|
||||||
-- @field #number remunidist Max distance trucks will go
|
|
||||||
-- @field #number monitor Monitor interval in seconds
|
|
||||||
-- @field #number unloadtime Unload time in seconds
|
|
||||||
-- @field #number waitingtime Max waiting time in seconds
|
|
||||||
-- @field #boolean routeonroad Route truck on road if true (default)
|
|
||||||
-- @field #number reloads Number of reloads a single truck can do before he must return home
|
|
||||||
-- @extends Core.Fsm#FSM
|
|
||||||
|
|
||||||
--- *Amateurs talk about tactics, but professionals study logistics.* - General Robert H Barrow, USMC
|
|
||||||
--
|
|
||||||
-- Simple Class to re-arm your artillery with trucks.
|
|
||||||
--
|
|
||||||
-- #AMMOTRUCK
|
|
||||||
--
|
|
||||||
-- * Controls a SET\_GROUP of trucks which will re-arm a SET\_GROUP of artillery groups when they run out of ammunition.
|
|
||||||
--
|
|
||||||
-- ## 1 The AMMOTRUCK concept
|
|
||||||
--
|
|
||||||
-- A SET\_GROUP of trucks which will re-arm a SET\_GROUP of artillery groups when they run out of ammunition. They will be based on a
|
|
||||||
-- homebase and drive from there to the artillery groups and then back home.
|
|
||||||
-- Trucks are the **only known in-game mechanic** to re-arm artillery and other units in DCS. Working units are e.g.: M-939 (blue), Ural-375 and ZIL-135 (both red).
|
|
||||||
--
|
|
||||||
-- ## 2 Set-up
|
|
||||||
--
|
|
||||||
-- Define a set of trucks and a set of artillery:
|
|
||||||
--
|
|
||||||
-- local truckset = SET_GROUP:New():FilterCoalitions("blue"):FilterActive(true):FilterCategoryGround():FilterPrefixes("Ammo Truck"):FilterStart()
|
|
||||||
-- local ariset = SET_GROUP:New():FilterCoalitions("blue"):FilterActive(true):FilterCategoryGround():FilterPrefixes("Artillery"):FilterStart()
|
|
||||||
--
|
|
||||||
-- Create an AMMOTRUCK object to take care of the artillery using the trucks, with a homezone:
|
|
||||||
--
|
|
||||||
-- local ammotruck = AMMOTRUCK:New(truckset,ariset,coalition.side.BLUE,"Logistics",ZONE:FindByName("HomeZone")
|
|
||||||
--
|
|
||||||
-- ## 2 Options and their default values
|
|
||||||
--
|
|
||||||
-- ammotruck.ammothreshold = 5 -- send a truck when down to this many rounds
|
|
||||||
-- ammotruck.remunidist = 20000 -- 20km - send trucks max this far from home
|
|
||||||
-- ammotruck.unloadtime = 600 -- 10 minutes - min time to unload ammunition
|
|
||||||
-- ammotruck.waitingtime = 1800 -- 30 mintes - wait max this long until remunition is done
|
|
||||||
-- ammotruck.monitor = -60 -- 1 minute - AMMOTRUCK checks run every one minute
|
|
||||||
-- ammotruck.routeonroad = true -- Trucks will **try** to drive on roads
|
|
||||||
-- ammotruck.usearmygroup = false -- If true, will make use of ARMYGROUP in the background (if used in DEV branch)
|
|
||||||
-- ammotruck.reloads = 5 -- Maxn re-arms a truck can do before he needs to go home and restock. Set to -1 for unlimited
|
|
||||||
--
|
|
||||||
-- ## 3 FSM Events to shape mission
|
|
||||||
--
|
|
||||||
-- Truck has been sent off:
|
|
||||||
--
|
|
||||||
-- function ammotruck:OnAfterRouteTruck(From, Event, To, Truckdata, Aridata)
|
|
||||||
-- ...
|
|
||||||
-- end
|
|
||||||
--
|
|
||||||
-- Truck has arrived:
|
|
||||||
--
|
|
||||||
-- function ammotruck:OnAfterTruckArrived(From, Event, To, Truckdata)
|
|
||||||
-- ...
|
|
||||||
-- end
|
|
||||||
--
|
|
||||||
-- Truck is unloading:
|
|
||||||
--
|
|
||||||
-- function ammotruck:OnAfterTruckUnloading(From, Event, To, Truckdata)
|
|
||||||
-- ...
|
|
||||||
-- end
|
|
||||||
--
|
|
||||||
-- Truck is returning home:
|
|
||||||
--
|
|
||||||
-- function ammotruck:OnAfterTruckReturning(From, Event, To, Truckdata)
|
|
||||||
-- ...
|
|
||||||
-- end
|
|
||||||
--
|
|
||||||
-- Truck is arrived at home:
|
|
||||||
--
|
|
||||||
-- function ammotruck:OnAfterTruckHome(From, Event, To, Truckdata)
|
|
||||||
-- ...
|
|
||||||
-- end
|
|
||||||
--
|
|
||||||
-- @field #AMMOTRUCK
|
|
||||||
AMMOTRUCK = {
|
|
||||||
ClassName = "AMMOTRUCK",
|
|
||||||
lid = "",
|
|
||||||
version = "0.0.12",
|
|
||||||
alias = "",
|
|
||||||
debug = false,
|
|
||||||
trucklist = {},
|
|
||||||
targetlist = {},
|
|
||||||
coalition = nil,
|
|
||||||
truckset = nil,
|
|
||||||
targetset = nil,
|
|
||||||
remunitionqueue = {},
|
|
||||||
waitingtargets = {},
|
|
||||||
ammothreshold = 5,
|
|
||||||
remunidist = 20000,
|
|
||||||
monitor = -60,
|
|
||||||
unloadtime = 600,
|
|
||||||
waitingtime = 1800,
|
|
||||||
routeonroad = true,
|
|
||||||
reloads = 5,
|
|
||||||
}
|
|
||||||
|
|
||||||
---
|
|
||||||
-- @type AMMOTRUCK.State
|
|
||||||
AMMOTRUCK.State = {
|
|
||||||
IDLE = "idle",
|
|
||||||
DRIVING = "driving",
|
|
||||||
ARRIVED = "arrived",
|
|
||||||
UNLOADING = "unloading",
|
|
||||||
RETURNING = "returning",
|
|
||||||
WAITING = "waiting",
|
|
||||||
RELOADING = "reloading",
|
|
||||||
OUTOFAMMO = "outofammo",
|
|
||||||
REQUESTED = "requested",
|
|
||||||
}
|
|
||||||
|
|
||||||
---
|
|
||||||
--@type AMMOTRUCK.data
|
|
||||||
--@field Wrapper.Group#GROUP group
|
|
||||||
--@field #string name
|
|
||||||
--@field #AMMOTRUCK.State statusquo
|
|
||||||
--@field #number timestamp
|
|
||||||
--@field #number ammo
|
|
||||||
--@field Core.Point#COORDINATE coordinate
|
|
||||||
--@field #string targetname
|
|
||||||
--@field Wrapper.Group#GROUP targetgroup
|
|
||||||
--@field Core.Point#COORDINATE targetcoordinate
|
|
||||||
--@field #number reloads
|
|
||||||
|
|
||||||
---
|
|
||||||
-- @param #AMMOTRUCK self
|
|
||||||
-- @param Core.Set#SET_GROUP Truckset Set of truck groups
|
|
||||||
-- @param Core.Set#SET_GROUP Targetset Set of artillery groups
|
|
||||||
-- @param #number Coalition Coalition
|
|
||||||
-- @param #string Alias Alias Name
|
|
||||||
-- @param Core.Zone#ZONE Homezone Home, return zone for trucks
|
|
||||||
-- @return #AMMOTRUCK self
|
|
||||||
-- @usage
|
|
||||||
-- Define a set of trucks and a set of artillery:
|
|
||||||
-- local truckset = SET_GROUP:New():FilterCoalitions("blue"):FilterActive(true):FilterCategoryGround():FilterPrefixes("Ammo Truck"):FilterStart()
|
|
||||||
-- local ariset = SET_GROUP:New():FilterCoalitions("blue"):FilterActive(true):FilterCategoryGround():FilterPrefixes("Artillery"):FilterStart()
|
|
||||||
--
|
|
||||||
-- Create an AMMOTRUCK object to take care of the artillery using the trucks, with a homezone:
|
|
||||||
-- local ammotruck = AMMOTRUCK:New(truckset,ariset,coalition.side.BLUE,"Logistics",ZONE:FindByName("HomeZone")
|
|
||||||
function AMMOTRUCK:New(Truckset,Targetset,Coalition,Alias,Homezone)
|
|
||||||
|
|
||||||
-- Inherit everything from BASE class.
|
|
||||||
local self=BASE:Inherit(self, FSM:New()) -- #AMMOTRUCK
|
|
||||||
|
|
||||||
self.truckset = Truckset -- Core.Set#SET_GROUP
|
|
||||||
self.targetset = Targetset -- Core.Set#SET_GROUP
|
|
||||||
self.coalition = Coalition -- #number
|
|
||||||
self.alias = Alias -- #string
|
|
||||||
self.debug = false
|
|
||||||
self.remunitionqueue = {}
|
|
||||||
self.trucklist = {}
|
|
||||||
self.targetlist = {}
|
|
||||||
self.ammothreshold = 5
|
|
||||||
self.remunidist = 20000
|
|
||||||
self.homezone = Homezone -- Core.Zone#ZONE
|
|
||||||
self.waitingtime = 1800
|
|
||||||
self.usearmygroup = false
|
|
||||||
self.hasarmygroup = false
|
|
||||||
|
|
||||||
-- Log id.
|
|
||||||
self.lid=string.format("AMMOTRUCK %s | %s | ", self.version, self.alias)
|
|
||||||
|
|
||||||
self:SetStartState("Stopped")
|
|
||||||
self:AddTransition("Stopped", "Start", "Running")
|
|
||||||
self:AddTransition("*", "Monitor", "*")
|
|
||||||
self:AddTransition("*", "RouteTruck", "*")
|
|
||||||
self:AddTransition("*", "TruckArrived", "*")
|
|
||||||
self:AddTransition("*", "TruckUnloading", "*")
|
|
||||||
self:AddTransition("*", "TruckReturning", "*")
|
|
||||||
self:AddTransition("*", "TruckHome", "*")
|
|
||||||
self:AddTransition("*", "Stop", "Stopped")
|
|
||||||
|
|
||||||
self:__Start(math.random(5,10))
|
|
||||||
|
|
||||||
self:I(self.lid .. "Started")
|
|
||||||
|
|
||||||
------------------------
|
|
||||||
--- Pseudo Functions ---
|
|
||||||
------------------------
|
|
||||||
|
|
||||||
--- Triggers the FSM event "Stop". Stops the AMMOTRUCK and all its event handlers.
|
|
||||||
-- @function [parent=#AMMOTRUCK] Stop
|
|
||||||
-- @param #AMMOTRUCK self
|
|
||||||
|
|
||||||
--- Triggers the FSM event "Stop" after a delay. Stops the AMMOTRUCK and all its event handlers.
|
|
||||||
-- @function [parent=#AMMOTRUCK] __Stop
|
|
||||||
-- @param #AMMOTRUCK self
|
|
||||||
-- @param #number delay Delay in seconds.
|
|
||||||
|
|
||||||
--- On after "RouteTruck" event.
|
|
||||||
-- @function [parent=#AMMOTRUCK] OnAfterRouteTruck
|
|
||||||
-- @param #AMMOTRUCK self
|
|
||||||
-- @param #string From From state.
|
|
||||||
-- @param #string Event Event.
|
|
||||||
-- @param #string To To state.
|
|
||||||
-- @param #AMMOTRUCK.data Truck
|
|
||||||
-- @param #AMMOTRUCK.data Artillery
|
|
||||||
|
|
||||||
--- On after "TruckUnloading" event.
|
|
||||||
-- @function [parent=#AMMOTRUCK] OnAfterTruckUnloading
|
|
||||||
-- @param #AMMOTRUCK self
|
|
||||||
-- @param #string From From state.
|
|
||||||
-- @param #string Event Event.
|
|
||||||
-- @param #string To To state.
|
|
||||||
-- @param #AMMOTRUCK.data Truck
|
|
||||||
|
|
||||||
--- On after "TruckReturning" event.
|
|
||||||
-- @function [parent=#AMMOTRUCK] OnAfterTruckReturning
|
|
||||||
-- @param #AMMOTRUCK self
|
|
||||||
-- @param #string From From state.
|
|
||||||
-- @param #string Event Event.
|
|
||||||
-- @param #string To To state.
|
|
||||||
-- @param #AMMOTRUCK.data Truck
|
|
||||||
|
|
||||||
--- On after "RouteTruck" event.
|
|
||||||
-- @function [parent=#AMMOTRUCK] OnAfterRouteTruck
|
|
||||||
-- @param #AMMOTRUCK self
|
|
||||||
-- @param #string From From state.
|
|
||||||
-- @param #string Event Event.
|
|
||||||
-- @param #string To To state.
|
|
||||||
-- @param #AMMOTRUCK.data Truck
|
|
||||||
|
|
||||||
--- On after "TruckHome" event.
|
|
||||||
-- @function [parent=#AMMOTRUCK] OnAfterTruckHome
|
|
||||||
-- @param #AMMOTRUCK self
|
|
||||||
-- @param #string From From state.
|
|
||||||
-- @param #string Event Event.
|
|
||||||
-- @param #string To To state.
|
|
||||||
-- @param #AMMOTRUCK.data Truck
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
---
|
|
||||||
-- @param #AMMOTRUCK self
|
|
||||||
-- @param #table dataset table of #AMMOTRUCK.data entries
|
|
||||||
-- @return #AMMOTRUCK self
|
|
||||||
function AMMOTRUCK:CheckDrivingTrucks(dataset)
|
|
||||||
self:T(self.lid .. " CheckDrivingTrucks")
|
|
||||||
local data = dataset
|
|
||||||
for _,_data in pairs (data) do
|
|
||||||
local truck = _data -- #AMMOTRUCK.data
|
|
||||||
-- see if we arrived at destination
|
|
||||||
local coord = truck.group:GetCoordinate()
|
|
||||||
local tgtcoord = truck.targetcoordinate
|
|
||||||
local dist = coord:Get2DDistance(tgtcoord)
|
|
||||||
if dist <= 150 then
|
|
||||||
-- arrived
|
|
||||||
truck.statusquo = AMMOTRUCK.State.ARRIVED
|
|
||||||
truck.timestamp = timer.getAbsTime()
|
|
||||||
truck.coordinate = coord
|
|
||||||
self:__TruckArrived(1,truck)
|
|
||||||
end
|
|
||||||
-- still driving?
|
|
||||||
local Tnow = timer.getAbsTime()
|
|
||||||
if Tnow - truck.timestamp > 30 then
|
|
||||||
local group = truck.group
|
|
||||||
if self.usearmygroup then
|
|
||||||
group = truck.group:GetGroup()
|
|
||||||
end
|
|
||||||
local currspeed = group:GetVelocityKMH()
|
|
||||||
if truck.lastspeed then
|
|
||||||
if truck.lastspeed == 0 and currspeed == 0 then
|
|
||||||
self:T(truck.group:GetName().." Is not moving!")
|
|
||||||
-- try and move it
|
|
||||||
truck.timestamp = timer.getAbsTime()
|
|
||||||
if self.routeonroad then
|
|
||||||
group:RouteGroundOnRoad(truck.targetcoordinate,30,2,"Vee")
|
|
||||||
else
|
|
||||||
group:RouteGroundTo(truck.targetcoordinate,30,"Vee",2)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
truck.lastspeed = currspeed
|
|
||||||
else
|
|
||||||
truck.lastspeed = currspeed
|
|
||||||
truck.timestamp = timer.getAbsTime()
|
|
||||||
end
|
|
||||||
self:I({truck=truck.group:GetName(),currspeed=currspeed,lastspeed=truck.lastspeed})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
---
|
|
||||||
-- @param #AMMOTRUCK self
|
|
||||||
-- @param Wrapper.Group#GROUP Group
|
|
||||||
-- @return #AMMOTRUCK self
|
|
||||||
function AMMOTRUCK:GetAmmoStatus(Group)
|
|
||||||
local ammotot, shells, rockets, bombs, missiles, narti = Group:GetAmmunition()
|
|
||||||
return rockets+missiles+narti
|
|
||||||
end
|
|
||||||
|
|
||||||
---
|
|
||||||
-- @param #AMMOTRUCK self
|
|
||||||
-- @param #table dataset table of #AMMOTRUCK.data entries
|
|
||||||
-- @return #AMMOTRUCK self
|
|
||||||
function AMMOTRUCK:CheckWaitingTargets(dataset)
|
|
||||||
self:T(self.lid .. " CheckWaitingTargets")
|
|
||||||
local data = dataset
|
|
||||||
for _,_data in pairs (data) do
|
|
||||||
local truck = _data -- #AMMOTRUCK.data
|
|
||||||
-- see how long we're waiting - maybe ammo truck is dead?
|
|
||||||
local Tnow = timer.getAbsTime()
|
|
||||||
local Tdiff = Tnow - truck.timestamp
|
|
||||||
if Tdiff > self.waitingtime then
|
|
||||||
local hasammo = self:GetAmmoStatus(truck.group)
|
|
||||||
if hasammo <= self.ammothreshold then
|
|
||||||
truck.statusquo = AMMOTRUCK.State.OUTOFAMMO
|
|
||||||
else
|
|
||||||
truck.statusquo = AMMOTRUCK.State.IDLE
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
---
|
|
||||||
-- @param #AMMOTRUCK self
|
|
||||||
-- @param #table dataset table of #AMMOTRUCK.data entries
|
|
||||||
-- @return #AMMOTRUCK self
|
|
||||||
function AMMOTRUCK:CheckReturningTrucks(dataset)
|
|
||||||
self:T(self.lid .. " CheckReturningTrucks")
|
|
||||||
local data = dataset
|
|
||||||
local tgtcoord = self.homezone:GetCoordinate()
|
|
||||||
local radius = self.homezone:GetRadius()
|
|
||||||
for _,_data in pairs (data) do
|
|
||||||
local truck = _data -- #AMMOTRUCK.data
|
|
||||||
-- see if we arrived at destination
|
|
||||||
local coord = truck.group:GetCoordinate()
|
|
||||||
local dist = coord:Get2DDistance(tgtcoord)
|
|
||||||
self:T({name=truck.name,radius=radius,distance=dist})
|
|
||||||
if dist <= radius then
|
|
||||||
-- arrived
|
|
||||||
truck.statusquo = AMMOTRUCK.State.IDLE
|
|
||||||
truck.timestamp = timer.getAbsTime()
|
|
||||||
truck.coordinate = coord
|
|
||||||
truck.reloads = self.reloads or 5
|
|
||||||
self:__TruckHome(1,truck)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
---
|
|
||||||
-- @param #AMMOTRUCK self
|
|
||||||
-- @param #string name Artillery group name to find
|
|
||||||
-- @return #AMMOTRUCK.data Data
|
|
||||||
function AMMOTRUCK:FindTarget(name)
|
|
||||||
self:T(self.lid .. " FindTarget")
|
|
||||||
local data = nil
|
|
||||||
local dataset = self.targetlist
|
|
||||||
for _,_entry in pairs(dataset) do
|
|
||||||
local entry = _entry -- #AMMOTRUCK.data
|
|
||||||
if entry.name == name then
|
|
||||||
data = entry
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return data
|
|
||||||
end
|
|
||||||
|
|
||||||
---
|
|
||||||
-- @param #AMMOTRUCK self
|
|
||||||
-- @param #string name Truck group name to find
|
|
||||||
-- @return #AMMOTRUCK.data Data
|
|
||||||
function AMMOTRUCK:FindTruck(name)
|
|
||||||
self:T(self.lid .. " FindTruck")
|
|
||||||
local data = nil
|
|
||||||
local dataset = self.trucklist
|
|
||||||
for _,_entry in pairs(dataset) do
|
|
||||||
local entry = _entry -- #AMMOTRUCK.data
|
|
||||||
if entry.name == name then
|
|
||||||
data = entry
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return data
|
|
||||||
end
|
|
||||||
|
|
||||||
---
|
|
||||||
-- @param #AMMOTRUCK self
|
|
||||||
-- @param #table dataset table of #AMMOTRUCK.data entries
|
|
||||||
-- @return #AMMOTRUCK self
|
|
||||||
function AMMOTRUCK:CheckArrivedTrucks(dataset)
|
|
||||||
self:T(self.lid .. " CheckArrivedTrucks")
|
|
||||||
local data = dataset
|
|
||||||
for _,_data in pairs (data) do
|
|
||||||
-- set to unloading
|
|
||||||
local truck = _data -- #AMMOTRUCK.data
|
|
||||||
truck.statusquo = AMMOTRUCK.State.UNLOADING
|
|
||||||
truck.timestamp = timer.getAbsTime()
|
|
||||||
self:__TruckUnloading(2,truck)
|
|
||||||
-- set target to reloading
|
|
||||||
local aridata = self:FindTarget(truck.targetname) -- #AMMOTRUCK.data
|
|
||||||
if aridata then
|
|
||||||
aridata.statusquo = AMMOTRUCK.State.RELOADING
|
|
||||||
aridata.timestamp = timer.getAbsTime()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
---
|
|
||||||
-- @param #AMMOTRUCK self
|
|
||||||
-- @param #table dataset table of #AMMOTRUCK.data entries
|
|
||||||
-- @return #AMMOTRUCK self
|
|
||||||
function AMMOTRUCK:CheckUnloadingTrucks(dataset)
|
|
||||||
self:T(self.lid .. " CheckUnloadingTrucks")
|
|
||||||
local data = dataset
|
|
||||||
for _,_data in pairs (data) do
|
|
||||||
-- check timestamp
|
|
||||||
local truck = _data -- #AMMOTRUCK.data
|
|
||||||
local Tnow = timer.getAbsTime()
|
|
||||||
local Tpassed = Tnow - truck.timestamp
|
|
||||||
local hasammo = self:GetAmmoStatus(truck.targetgroup)
|
|
||||||
if Tpassed > self.unloadtime and hasammo > self.ammothreshold then
|
|
||||||
truck.statusquo = AMMOTRUCK.State.RETURNING
|
|
||||||
truck.timestamp = timer.getAbsTime()
|
|
||||||
self:__TruckReturning(2,truck)
|
|
||||||
-- set target to reloaded
|
|
||||||
local aridata = self:FindTarget(truck.targetname) -- #AMMOTRUCK.data
|
|
||||||
if aridata then
|
|
||||||
aridata.statusquo = AMMOTRUCK.State.IDLE
|
|
||||||
aridata.timestamp = timer.getAbsTime()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
---
|
|
||||||
-- @param #AMMOTRUCK self
|
|
||||||
-- @return #AMMOTRUCK self
|
|
||||||
function AMMOTRUCK:CheckTargetsAlive()
|
|
||||||
self:T(self.lid .. " CheckTargetsAlive")
|
|
||||||
local arilist = self.targetlist
|
|
||||||
for _,_ari in pairs(arilist) do
|
|
||||||
local ari = _ari -- #AMMOTRUCK.data
|
|
||||||
if ari.group and ari.group:IsAlive() then
|
|
||||||
-- everything fine
|
|
||||||
else
|
|
||||||
-- ari dead
|
|
||||||
self.targetlist[ari.name] = nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-- new arrivals?
|
|
||||||
local aritable = self.targetset:GetSetObjects() --#table
|
|
||||||
for _,_ari in pairs(aritable) do
|
|
||||||
local ari = _ari -- Wrapper.Group#GROUP
|
|
||||||
if ari and ari:IsAlive() and not self.targetlist[ari:GetName()] then
|
|
||||||
local name = ari:GetName()
|
|
||||||
local newari = {} -- #AMMOTRUCK.data
|
|
||||||
newari.name = name
|
|
||||||
newari.group = ari
|
|
||||||
newari.statusquo = AMMOTRUCK.State.IDLE
|
|
||||||
newari.timestamp = timer.getAbsTime()
|
|
||||||
newari.coordinate = ari:GetCoordinate()
|
|
||||||
local hasammo = self:GetAmmoStatus(ari)
|
|
||||||
--newari.ammo = ari:GetAmmunition()
|
|
||||||
newari.ammo = hasammo
|
|
||||||
self.targetlist[name] = newari
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
---
|
|
||||||
-- @param #AMMOTRUCK self
|
|
||||||
-- @return #AMMOTRUCK self
|
|
||||||
function AMMOTRUCK:CheckTrucksAlive()
|
|
||||||
self:T(self.lid .. " CheckTrucksAlive")
|
|
||||||
local trucklist = self.trucklist
|
|
||||||
for _,_truck in pairs(trucklist) do
|
|
||||||
local truck = _truck -- #AMMOTRUCK.data
|
|
||||||
if truck.group and truck.group:IsAlive() then
|
|
||||||
-- everything fine
|
|
||||||
else
|
|
||||||
-- truck dead
|
|
||||||
local tgtname = truck.targetname
|
|
||||||
local targetdata = self:FindTarget(tgtname) -- #AMMOTRUCK.data
|
|
||||||
if targetdata then
|
|
||||||
if targetdata.statusquo ~= AMMOTRUCK.State.IDLE then
|
|
||||||
targetdata.statusquo = AMMOTRUCK.State.IDLE
|
|
||||||
end
|
|
||||||
end
|
|
||||||
self.trucklist[truck.name] = nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-- new arrivals?
|
|
||||||
local trucktable = self.truckset:GetSetObjects() --#table
|
|
||||||
for _,_truck in pairs(trucktable) do
|
|
||||||
local truck = _truck -- Wrapper.Group#GROUP
|
|
||||||
if truck and truck:IsAlive() and not self.trucklist[truck:GetName()] then
|
|
||||||
local name = truck:GetName()
|
|
||||||
local newtruck = {} -- #AMMOTRUCK.data
|
|
||||||
newtruck.name = name
|
|
||||||
newtruck.group = truck
|
|
||||||
if self.hasarmygroup then
|
|
||||||
-- is (not) already ARMYGROUP?
|
|
||||||
if truck.ClassName and truck.ClassName == "GROUP" then
|
|
||||||
local trucker = ARMYGROUP:New(truck)
|
|
||||||
trucker:Activate()
|
|
||||||
newtruck.group = trucker
|
|
||||||
end
|
|
||||||
end
|
|
||||||
newtruck.statusquo = AMMOTRUCK.State.IDLE
|
|
||||||
newtruck.timestamp = timer.getAbsTime()
|
|
||||||
newtruck.coordinate = truck:GetCoordinate()
|
|
||||||
newtruck.reloads = self.reloads or 5
|
|
||||||
self.trucklist[name] = newtruck
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
---
|
|
||||||
-- @param #AMMOTRUCK self
|
|
||||||
-- @param #string From
|
|
||||||
-- @param #string Event
|
|
||||||
-- @param #string To
|
|
||||||
-- @return #AMMOTRUCK self
|
|
||||||
function AMMOTRUCK:onafterStart(From, Event, To)
|
|
||||||
self:T({From, Event, To})
|
|
||||||
if ARMYGROUP and self.usearmygroup then
|
|
||||||
self.hasarmygroup = true
|
|
||||||
else
|
|
||||||
self.hasarmygroup = false
|
|
||||||
end
|
|
||||||
if self.debug then
|
|
||||||
BASE:TraceOn()
|
|
||||||
BASE:TraceClass("AMMOTRUCK")
|
|
||||||
end
|
|
||||||
self:CheckTargetsAlive()
|
|
||||||
self:CheckTrucksAlive()
|
|
||||||
self:__Monitor(-30)
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
---
|
|
||||||
-- @param #AMMOTRUCK self
|
|
||||||
-- @param #string From
|
|
||||||
-- @param #string Event
|
|
||||||
-- @param #string To
|
|
||||||
-- @return #AMMOTRUCK self
|
|
||||||
function AMMOTRUCK:onafterMonitor(From, Event, To)
|
|
||||||
self:T({From, Event, To})
|
|
||||||
self:CheckTargetsAlive()
|
|
||||||
self:CheckTrucksAlive()
|
|
||||||
-- update ammo state
|
|
||||||
local remunition = false
|
|
||||||
local remunitionqueue = {}
|
|
||||||
local waitingtargets = {}
|
|
||||||
for _,_ari in pairs(self.targetlist) do
|
|
||||||
local data = _ari -- #AMMOTRUCK.data
|
|
||||||
if data.group and data.group:IsAlive() then
|
|
||||||
data.ammo = self:GetAmmoStatus(data.group)
|
|
||||||
data.timestamp = timer.getAbsTime()
|
|
||||||
local text = string.format("Ari %s | Ammo %d | State %s",data.name,data.ammo,data.statusquo)
|
|
||||||
self:T(text)
|
|
||||||
if data.ammo <= self.ammothreshold and (data.statusquo == AMMOTRUCK.State.IDLE or data.statusquo == AMMOTRUCK.State.OUTOFAMMO) then
|
|
||||||
-- add to remu queue
|
|
||||||
data.statusquo = AMMOTRUCK.State.OUTOFAMMO
|
|
||||||
remunitionqueue[#remunitionqueue+1] = data
|
|
||||||
remunition = true
|
|
||||||
elseif data.statusquo == AMMOTRUCK.State.WAITING then
|
|
||||||
waitingtargets[#waitingtargets+1] = data
|
|
||||||
end
|
|
||||||
else
|
|
||||||
self.targetlist[data.name] = nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-- sort trucks in buckets
|
|
||||||
local idletrucks = {}
|
|
||||||
local drivingtrucks = {}
|
|
||||||
local unloadingtrucks = {}
|
|
||||||
local arrivedtrucks = {}
|
|
||||||
local returningtrucks = {}
|
|
||||||
local found = false
|
|
||||||
for _,_truckdata in pairs(self.trucklist) do
|
|
||||||
local data = _truckdata -- #AMMOTRUCK.data
|
|
||||||
if data.group and data.group:IsAlive() then
|
|
||||||
-- check state
|
|
||||||
local text = string.format("Truck %s | State %s",data.name,data.statusquo)
|
|
||||||
self:T(text)
|
|
||||||
if data.statusquo == AMMOTRUCK.State.IDLE then
|
|
||||||
idletrucks[#idletrucks+1] = data
|
|
||||||
found = true
|
|
||||||
elseif data.statusquo == AMMOTRUCK.State.DRIVING then
|
|
||||||
drivingtrucks[#drivingtrucks+1] = data
|
|
||||||
elseif data.statusquo == AMMOTRUCK.State.ARRIVED then
|
|
||||||
arrivedtrucks[#arrivedtrucks+1] = data
|
|
||||||
elseif data.statusquo == AMMOTRUCK.State.UNLOADING then
|
|
||||||
unloadingtrucks[#unloadingtrucks+1] = data
|
|
||||||
elseif data.statusquo == AMMOTRUCK.State.RETURNING then
|
|
||||||
returningtrucks[#returningtrucks+1] = data
|
|
||||||
if data.reloads > 0 or data.reloads == -1 then
|
|
||||||
idletrucks[#idletrucks+1] = data
|
|
||||||
found = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
self.truckset[data.name] = nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-- see if we can/need route one
|
|
||||||
local n=0
|
|
||||||
if found and remunition then
|
|
||||||
-- match
|
|
||||||
--local match = false
|
|
||||||
for _,_truckdata in pairs(idletrucks) do
|
|
||||||
local truckdata = _truckdata -- #AMMOTRUCK.data
|
|
||||||
local truckcoord = truckdata.group:GetCoordinate() -- Core.Point#COORDINATE
|
|
||||||
for _,_aridata in pairs(remunitionqueue) do
|
|
||||||
local aridata = _aridata -- #AMMOTRUCK.data
|
|
||||||
local aricoord = aridata.coordinate
|
|
||||||
local distance = truckcoord:Get2DDistance(aricoord)
|
|
||||||
if distance <= self.remunidist and aridata.statusquo == AMMOTRUCK.State.OUTOFAMMO and n <= #idletrucks then
|
|
||||||
n = n + 1
|
|
||||||
aridata.statusquo = AMMOTRUCK.State.REQUESTED
|
|
||||||
self:__RouteTruck(n*5,truckdata,aridata)
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- check driving trucks
|
|
||||||
if #drivingtrucks > 0 then
|
|
||||||
self:CheckDrivingTrucks(drivingtrucks)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- check arrived trucks
|
|
||||||
if #arrivedtrucks > 0 then
|
|
||||||
self:CheckArrivedTrucks(arrivedtrucks)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- check unloading trucks
|
|
||||||
if #unloadingtrucks > 0 then
|
|
||||||
self:CheckUnloadingTrucks(unloadingtrucks)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- check returningtrucks trucks
|
|
||||||
if #returningtrucks > 0 then
|
|
||||||
self:CheckReturningTrucks(returningtrucks)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- check waiting targets
|
|
||||||
if #waitingtargets > 0 then
|
|
||||||
self:CheckWaitingTargets(waitingtargets)
|
|
||||||
end
|
|
||||||
|
|
||||||
self:__Monitor(self.monitor)
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
---
|
|
||||||
-- @param #AMMOTRUCK self
|
|
||||||
-- @param #string From
|
|
||||||
-- @param #string Event
|
|
||||||
-- @param #string To
|
|
||||||
-- @param #AMMOTRUCK.data Truckdata
|
|
||||||
-- @param #AMMOTRUCK.data Aridata
|
|
||||||
-- @return #AMMOTRUCK self
|
|
||||||
function AMMOTRUCK:onafterRouteTruck(From, Event, To, Truckdata, Aridata)
|
|
||||||
self:T({From, Event, To, Truckdata.name, Aridata.name})
|
|
||||||
local truckdata = Truckdata -- #AMMOTRUCK.data
|
|
||||||
local aridata = Aridata -- #AMMOTRUCK.data
|
|
||||||
local tgtgrp = aridata.group
|
|
||||||
local tgtzone = ZONE_GROUP:New(aridata.name,tgtgrp,30)
|
|
||||||
local tgtcoord = tgtzone:GetRandomCoordinate(15)
|
|
||||||
if self.hasarmygroup then
|
|
||||||
local mission = AUFTRAG:NewONGUARD(tgtcoord)
|
|
||||||
local oldmission = truckdata.group:GetMissionCurrent()
|
|
||||||
if oldmission then oldmission:Cancel() end
|
|
||||||
mission:SetTime(5)
|
|
||||||
mission:SetTeleport(false)
|
|
||||||
truckdata.group:AddMission(mission)
|
|
||||||
elseif self.routeonroad then
|
|
||||||
truckdata.group:RouteGroundOnRoad(tgtcoord,30)
|
|
||||||
else
|
|
||||||
truckdata.group:RouteGroundTo(tgtcoord,30)
|
|
||||||
end
|
|
||||||
truckdata.statusquo = AMMOTRUCK.State.DRIVING
|
|
||||||
truckdata.targetgroup = tgtgrp
|
|
||||||
truckdata.targetname = aridata.name
|
|
||||||
truckdata.targetcoordinate = tgtcoord
|
|
||||||
aridata.statusquo = AMMOTRUCK.State.WAITING
|
|
||||||
aridata.timestamp = timer.getAbsTime()
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
---
|
|
||||||
-- @param #AMMOTRUCK self
|
|
||||||
-- @param #string From
|
|
||||||
-- @param #string Event
|
|
||||||
-- @param #string To
|
|
||||||
-- @param #AMMOTRUCK.data Truckdata
|
|
||||||
-- @return #AMMOTRUCK self
|
|
||||||
function AMMOTRUCK:onafterTruckUnloading(From, Event, To, Truckdata)
|
|
||||||
local m = MESSAGE:New("Truck "..Truckdata.name.." unloading!",15,"AmmoTruck"):ToCoalitionIf(self.coalition,self.debug)
|
|
||||||
local truck = Truckdata -- Functional.AmmoTruck#AMMOTRUCK.data
|
|
||||||
local coord = truck.group:GetCoordinate()
|
|
||||||
local heading = truck.group:GetHeading()
|
|
||||||
heading = heading < 180 and (360-heading) or (heading - 180)
|
|
||||||
local cid = self.coalition == coalition.side.BLUE and country.id.USA or country.id.RUSSIA
|
|
||||||
cid = self.coalition == coalition.side.NEUTRAL and country.id.UN_PEACEKEEPERS or cid
|
|
||||||
|
|
||||||
local ammo = {}
|
|
||||||
for i=1,5 do
|
|
||||||
ammo[i] = SPAWNSTATIC:NewFromType("ammo_cargo","Cargos",cid)
|
|
||||||
:InitCoordinate(coord:Translate((15+((i-1)*4)),heading))
|
|
||||||
:Spawn(0,"AmmoCrate-"..math.random(1,10000))
|
|
||||||
end
|
|
||||||
|
|
||||||
local function destroyammo(ammo)
|
|
||||||
for _,_crate in pairs(ammo) do
|
|
||||||
_crate:Destroy(false)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local scheduler = SCHEDULER:New(nil,destroyammo,{ammo},self.waitingtime)
|
|
||||||
|
|
||||||
-- one reload less
|
|
||||||
if truck.reloads ~= -1 then
|
|
||||||
truck.reloads = truck.reloads - 1
|
|
||||||
end
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
---
|
|
||||||
-- @param #AMMOTRUCK self
|
|
||||||
-- @param #string From
|
|
||||||
-- @param #string Event
|
|
||||||
-- @param #string To
|
|
||||||
-- @param #AMMOTRUCK.data Truck
|
|
||||||
-- @return #AMMOTRUCK self
|
|
||||||
function AMMOTRUCK:onafterTruckReturning(From, Event, To, Truck)
|
|
||||||
self:T({From, Event, To, Truck.name})
|
|
||||||
-- route home
|
|
||||||
local truckdata = Truck -- #AMMOTRUCK.data
|
|
||||||
local tgtzone = self.homezone
|
|
||||||
local tgtcoord = tgtzone:GetRandomCoordinate()
|
|
||||||
if self.hasarmygroup then
|
|
||||||
local mission = AUFTRAG:NewONGUARD(tgtcoord)
|
|
||||||
local oldmission = truckdata.group:GetMissionCurrent()
|
|
||||||
if oldmission then oldmission:Cancel() end
|
|
||||||
mission:SetTime(5)
|
|
||||||
mission:SetTeleport(false)
|
|
||||||
truckdata.group:AddMission(mission)
|
|
||||||
elseif self.routeonroad then
|
|
||||||
truckdata.group:RouteGroundOnRoad(tgtcoord,30,1,"Cone")
|
|
||||||
else
|
|
||||||
truckdata.group:RouteGroundTo(tgtcoord,30,"Cone",1)
|
|
||||||
end
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
---
|
|
||||||
-- @param #AMMOTRUCK self
|
|
||||||
-- @param #string From
|
|
||||||
-- @param #string Event
|
|
||||||
-- @param #string To
|
|
||||||
-- @return #AMMOTRUCK self
|
|
||||||
function AMMOTRUCK:onafterStop(From, Event, To)
|
|
||||||
self:T({From, Event, To})
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
@@ -2386,12 +2386,12 @@ function ARTY:OnEventShot(EventData)
|
|||||||
self.Nukes=self.Nukes-1
|
self.Nukes=self.Nukes-1
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Decrease available illumination shells because we just fired one.
|
-- Decrease available illuminatin shells because we just fired one.
|
||||||
if self.currentTarget.weapontype==ARTY.WeaponType.IlluminationShells then
|
if self.currentTarget.weapontype==ARTY.WeaponType.IlluminationShells then
|
||||||
self.Nillu=self.Nillu-1
|
self.Nillu=self.Nillu-1
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Decrease available smoke shells because we just fired one.
|
-- Decrease available illuminatin shells because we just fired one.
|
||||||
if self.currentTarget.weapontype==ARTY.WeaponType.SmokeShells then
|
if self.currentTarget.weapontype==ARTY.WeaponType.SmokeShells then
|
||||||
self.Nsmoke=self.Nsmoke-1
|
self.Nsmoke=self.Nsmoke-1
|
||||||
end
|
end
|
||||||
@@ -3804,6 +3804,51 @@ function ARTY:_NuclearBlast(_coord)
|
|||||||
ignite(_fires)
|
ignite(_fires)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--[[
|
||||||
|
local ZoneNuke=ZONE_RADIUS:New("Nukezone", _coord:GetVec2(), 2000)
|
||||||
|
|
||||||
|
-- Scan for Scenery objects.
|
||||||
|
ZoneNuke:Scan(Object.Category.SCENERY)
|
||||||
|
|
||||||
|
-- Array with all possible hideouts, i.e. scenery objects in the vicinity of the group.
|
||||||
|
local scenery={}
|
||||||
|
|
||||||
|
for SceneryTypeName, SceneryData in pairs(ZoneNuke:GetScannedScenery()) do
|
||||||
|
for SceneryName, SceneryObject in pairs(SceneryData) do
|
||||||
|
|
||||||
|
local SceneryObject = SceneryObject -- Wrapper.Scenery#SCENERY
|
||||||
|
|
||||||
|
-- Position of the scenery object.
|
||||||
|
local spos=SceneryObject:GetCoordinate()
|
||||||
|
|
||||||
|
-- Distance from group to impact point.
|
||||||
|
local distance= spos:Get2DDistance(_coord)
|
||||||
|
|
||||||
|
-- Place markers on every possible scenery object.
|
||||||
|
if self.Debug then
|
||||||
|
local MarkerID=spos:MarkToAll(string.format("%s scenery object %s", self.Controllable:GetName(), SceneryObject:GetTypeName()))
|
||||||
|
local text=string.format("%s scenery: %s, Coord %s", self.Controllable:GetName(), SceneryObject:GetTypeName(), SceneryObject:GetCoordinate():ToStringLLDMS())
|
||||||
|
self:T2(SUPPRESSION.id..text)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Add to table.
|
||||||
|
table.insert(scenery, {object=SceneryObject, distance=distance})
|
||||||
|
|
||||||
|
--SceneryObject:Destroy()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Sort scenery wrt to distance from impact point.
|
||||||
|
-- local _sort = function(a,b) return a.distance < b.distance end
|
||||||
|
-- table.sort(scenery,_sort)
|
||||||
|
|
||||||
|
-- for _,object in pairs(scenery) do
|
||||||
|
-- local sobject=object -- Wrapper.Scenery#SCENERY
|
||||||
|
-- sobject:Destroy()
|
||||||
|
-- end
|
||||||
|
|
||||||
|
]]
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Route group to a certain point.
|
--- Route group to a certain point.
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -52,13 +52,11 @@
|
|||||||
-- @module Functional.CleanUp
|
-- @module Functional.CleanUp
|
||||||
-- @image CleanUp_Airbases.JPG
|
-- @image CleanUp_Airbases.JPG
|
||||||
|
|
||||||
---
|
--- @type CLEANUP_AIRBASE.__ Methods which are not intended for mission designers, but which are used interally by the moose designer :-)
|
||||||
-- @type CLEANUP_AIRBASE.__ Methods which are not intended for mission designers, but which are used interally by the moose designer :-)
|
|
||||||
-- @field #map<#string,Wrapper.Airbase#AIRBASE> Airbases Map of Airbases.
|
-- @field #map<#string,Wrapper.Airbase#AIRBASE> Airbases Map of Airbases.
|
||||||
-- @extends Core.Base#BASE
|
-- @extends Core.Base#BASE
|
||||||
|
|
||||||
---
|
--- @type CLEANUP_AIRBASE
|
||||||
-- @type CLEANUP_AIRBASE
|
|
||||||
-- @extends #CLEANUP_AIRBASE.__
|
-- @extends #CLEANUP_AIRBASE.__
|
||||||
|
|
||||||
--- Keeps airbases clean, and tries to guarantee continuous airbase operations, even under combat.
|
--- Keeps airbases clean, and tries to guarantee continuous airbase operations, even under combat.
|
||||||
@@ -95,7 +93,7 @@ CLEANUP_AIRBASE = {
|
|||||||
-- @field #CLEANUP_AIRBASE.__
|
-- @field #CLEANUP_AIRBASE.__
|
||||||
CLEANUP_AIRBASE.__ = {}
|
CLEANUP_AIRBASE.__ = {}
|
||||||
|
|
||||||
-- @field #CLEANUP_AIRBASE.__.Airbases
|
--- @field #CLEANUP_AIRBASE.__.Airbases
|
||||||
CLEANUP_AIRBASE.__.Airbases = {}
|
CLEANUP_AIRBASE.__.Airbases = {}
|
||||||
|
|
||||||
--- Creates the main object which is handling the cleaning of the debris within the given Zone Names.
|
--- Creates the main object which is handling the cleaning of the debris within the given Zone Names.
|
||||||
@@ -242,8 +240,7 @@ function CLEANUP_AIRBASE.__:DestroyMissile( MissileObject )
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
---
|
--- @param #CLEANUP_AIRBASE self
|
||||||
-- @param #CLEANUP_AIRBASE self
|
|
||||||
-- @param Core.Event#EVENTDATA EventData
|
-- @param Core.Event#EVENTDATA EventData
|
||||||
function CLEANUP_AIRBASE.__:OnEventBirth( EventData )
|
function CLEANUP_AIRBASE.__:OnEventBirth( EventData )
|
||||||
self:F( { EventData } )
|
self:F( { EventData } )
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
do -- DETECTION_ZONES
|
do -- DETECTION_ZONES
|
||||||
|
|
||||||
-- @type DETECTION_ZONES
|
--- @type DETECTION_ZONES
|
||||||
-- @field DCS#Distance DetectionZoneRange The range till which targets are grouped upon the first detected target.
|
-- @field DCS#Distance DetectionZoneRange The range till which targets are grouped upon the first detected target.
|
||||||
-- @field #DETECTION_BASE.DetectedItems DetectedItems A list of areas containing the set of @{Wrapper.Unit}s, @{Core.Zone}s, the center @{Wrapper.Unit} within the zone, and ID of each area that was detected within a DetectionZoneRange.
|
-- @field #DETECTION_BASE.DetectedItems DetectedItems A list of areas containing the set of @{Wrapper.Unit}s, @{Core.Zone}s, the center @{Wrapper.Unit} within the zone, and ID of each area that was detected within a DetectionZoneRange.
|
||||||
-- @extends Functional.Detection#DETECTION_BASE
|
-- @extends Functional.Detection#DETECTION_BASE
|
||||||
@@ -68,7 +68,7 @@ do -- DETECTION_ZONES
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
-- @param #DETECTION_ZONES self
|
--- @param #DETECTION_ZONES self
|
||||||
-- @param #number The amount of alive recce.
|
-- @param #number The amount of alive recce.
|
||||||
function DETECTION_ZONES:CountAliveRecce()
|
function DETECTION_ZONES:CountAliveRecce()
|
||||||
|
|
||||||
@@ -76,7 +76,7 @@ do -- DETECTION_ZONES
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- @param #DETECTION_ZONES self
|
--- @param #DETECTION_ZONES self
|
||||||
function DETECTION_ZONES:ForEachAliveRecce( IteratorFunction, ... )
|
function DETECTION_ZONES:ForEachAliveRecce( IteratorFunction, ... )
|
||||||
self:F2( arg )
|
self:F2( arg )
|
||||||
|
|
||||||
@@ -352,7 +352,7 @@ do -- DETECTION_ZONES
|
|||||||
--DetectedSet:Flush( self )
|
--DetectedSet:Flush( self )
|
||||||
|
|
||||||
DetectedSet:ForEachUnit(
|
DetectedSet:ForEachUnit(
|
||||||
-- @param Wrapper.Unit#UNIT DetectedUnit
|
--- @param Wrapper.Unit#UNIT DetectedUnit
|
||||||
function( DetectedUnit )
|
function( DetectedUnit )
|
||||||
if DetectedUnit:IsAlive() then
|
if DetectedUnit:IsAlive() then
|
||||||
--self:T( "Detected Set #" .. DetectedItem.ID .. ":" .. DetectedUnit:GetName() )
|
--self:T( "Detected Set #" .. DetectedItem.ID .. ":" .. DetectedUnit:GetName() )
|
||||||
@@ -380,7 +380,7 @@ do -- DETECTION_ZONES
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- @param #DETECTION_ZONES self
|
--- @param #DETECTION_ZONES self
|
||||||
-- @param #string From The From State string.
|
-- @param #string From The From State string.
|
||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
-- @param #string To The To State string.
|
-- @param #string To The To State string.
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -205,9 +212,6 @@
|
|||||||
-- ### 2.1.3 SHORAD/Point defense will automatically be added from SAM sites of type "point" or if the range is less than 5km or if the type is AAA.
|
-- ### 2.1.3 SHORAD/Point defense will automatically be added from SAM sites of type "point" or if the range is less than 5km or if the type is AAA.
|
||||||
--
|
--
|
||||||
-- ### 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.
|
||||||
@@ -220,6 +224,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]
|
||||||
--
|
--
|
||||||
@@ -242,26 +252,8 @@
|
|||||||
-- E.g. mymantis:SetAdvancedMode( true, 90 )
|
-- E.g. mymantis:SetAdvancedMode( true, 90 )
|
||||||
--
|
--
|
||||||
-- 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]
|
|
||||||
--
|
|
||||||
-- 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.
|
-- # 5. Integrated SEAD
|
||||||
--
|
|
||||||
-- (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,7 +632,8 @@ 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
|
||||||
@@ -1039,6 +1050,16 @@ do
|
|||||||
end
|
end
|
||||||
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
|
||||||
@@ -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.
|
||||||
--
|
--
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -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() )
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,593 +0,0 @@
|
|||||||
--- **Functional** - TIRESIAS - manages AI behaviour.
|
|
||||||
--
|
|
||||||
-- ===
|
|
||||||
--
|
|
||||||
-- The @{#TIRESIAS} class is working in the back to keep your large-scale ground units in check.
|
|
||||||
--
|
|
||||||
-- ## Features:
|
|
||||||
--
|
|
||||||
-- * Designed to keep CPU and Network usage lower on missions with a lot of ground units.
|
|
||||||
-- * Does not affect ships to keep the Navy guys happy.
|
|
||||||
-- * Does not affect OpsGroup type groups.
|
|
||||||
-- * Distinguishes between SAM groups, AAA groups and other ground groups.
|
|
||||||
-- * Exceptions can be defined to keep certain actions going.
|
|
||||||
-- * Works coalition-independent in the back
|
|
||||||
-- * Easy setup.
|
|
||||||
--
|
|
||||||
-- ===
|
|
||||||
--
|
|
||||||
-- ## Missions:
|
|
||||||
--
|
|
||||||
-- ### [TIRESIAS](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master)
|
|
||||||
--
|
|
||||||
-- ===
|
|
||||||
--
|
|
||||||
-- ### Author : **applevangelist **
|
|
||||||
--
|
|
||||||
-- @module Functional.Tiresias
|
|
||||||
-- @image Functional.Tiresias.jpg
|
|
||||||
--
|
|
||||||
-- Last Update: Dec 2023
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------
|
|
||||||
--- **TIRESIAS** class, extends Core.Base#BASE
|
|
||||||
-- @type TIRESIAS
|
|
||||||
-- @field #string ClassName
|
|
||||||
-- @field #booelan debug
|
|
||||||
-- @field #string version
|
|
||||||
-- @field #number Interval
|
|
||||||
-- @field Core.Set#SET_GROUP GroundSet
|
|
||||||
-- @field #number Coalition
|
|
||||||
-- @field Core.Set#SET_GROUP VehicleSet
|
|
||||||
-- @field Core.Set#SET_GROUP AAASet
|
|
||||||
-- @field Core.Set#SET_GROUP SAMSet
|
|
||||||
-- @field Core.Set#SET_GROUP ExceptionSet
|
|
||||||
-- @field Core.Set#SET_OPSGROUP OpsGroupSet
|
|
||||||
-- @field #number AAARange
|
|
||||||
-- @field #number HeloSwitchRange
|
|
||||||
-- @field #number PlaneSwitchRange
|
|
||||||
-- @field Core.Set#SET_GROUP FlightSet
|
|
||||||
-- @field #boolean SwitchAAA
|
|
||||||
-- @extends Core.Fsm#FSM
|
|
||||||
|
|
||||||
---
|
|
||||||
-- @type TIRESIAS.Data
|
|
||||||
-- @field #string type
|
|
||||||
-- @field #number range
|
|
||||||
-- @field #boolean invisible
|
|
||||||
-- @field #boolean AIOff
|
|
||||||
-- @field #boolean exception
|
|
||||||
|
|
||||||
|
|
||||||
--- *Tiresias, Greek demi-god and shapeshifter, blinded by the Gods, works as oracle for you.* (Wiki)
|
|
||||||
--
|
|
||||||
-- ===
|
|
||||||
--
|
|
||||||
-- ## TIRESIAS Concept
|
|
||||||
--
|
|
||||||
-- * Designed to keep CPU and Network usage lower on missions with a lot of ground units.
|
|
||||||
-- * Does not affect ships to keep the Navy guys happy.
|
|
||||||
-- * Does not affect OpsGroup type groups.
|
|
||||||
-- * Distinguishes between SAM groups, AAA groups and other ground groups.
|
|
||||||
-- * Exceptions can be defined in SET_GROUP objects to keep certain actions going.
|
|
||||||
-- * Works coalition-independent in the back
|
|
||||||
-- * Easy setup.
|
|
||||||
--
|
|
||||||
-- ## Setup
|
|
||||||
--
|
|
||||||
-- Setup is a one-liner:
|
|
||||||
--
|
|
||||||
-- local blinder = TIRESIAS:New()
|
|
||||||
--
|
|
||||||
-- Optionally you can set up exceptions, e.g. for convoys driving around
|
|
||||||
--
|
|
||||||
-- local exceptionset = SET_GROUP:New():FilterCoalitions("red"):FilterPrefixes("Convoy"):FilterStart()
|
|
||||||
-- local blinder = TIRESIAS:New()
|
|
||||||
-- blinder:AddExceptionSet(exceptionset)
|
|
||||||
--
|
|
||||||
-- Options
|
|
||||||
--
|
|
||||||
-- -- Setup different radius for activation around helo and airplane groups (applies to AI and humans)
|
|
||||||
-- blinder:SetActivationRanges(10,25) -- defaults are 10, and 25
|
|
||||||
--
|
|
||||||
-- -- Setup engagement ranges for AAA (non-advanced SAM units like Flaks etc) and if you want them to be AIOff
|
|
||||||
-- blinder:SetAAARanges(60,true) -- defaults are 60, and true
|
|
||||||
--
|
|
||||||
-- @field #TIRESIAS
|
|
||||||
TIRESIAS = {
|
|
||||||
ClassName = "TIRESIAS",
|
|
||||||
debug = false,
|
|
||||||
version = "0.0.5",
|
|
||||||
Interval = 20,
|
|
||||||
GroundSet = nil,
|
|
||||||
VehicleSet = nil,
|
|
||||||
AAASet = nil,
|
|
||||||
SAMSet = nil,
|
|
||||||
ExceptionSet = nil,
|
|
||||||
AAARange = 60, -- 60%
|
|
||||||
HeloSwitchRange = 10, -- NM
|
|
||||||
PlaneSwitchRange = 25, -- NM
|
|
||||||
SwitchAAA = true,
|
|
||||||
}
|
|
||||||
|
|
||||||
--- [USER] Create a new Tiresias object and start it up.
|
|
||||||
-- @param #TIRESIAS self
|
|
||||||
-- @return #TIRESIAS self
|
|
||||||
function TIRESIAS:New()
|
|
||||||
|
|
||||||
-- Inherit everything from FSM class.
|
|
||||||
local self = BASE:Inherit(self, FSM:New()) -- #TIRESIAS
|
|
||||||
|
|
||||||
--- FSM Functions ---
|
|
||||||
|
|
||||||
-- Start State.
|
|
||||||
self:SetStartState("Stopped")
|
|
||||||
|
|
||||||
-- Add FSM transitions.
|
|
||||||
-- From State --> Event --> To State
|
|
||||||
self:AddTransition("Stopped", "Start", "Running") -- Start FSM.
|
|
||||||
self:AddTransition("*", "Status", "*") -- TIRESIAS status update.
|
|
||||||
self:AddTransition("*", "Stop", "Stopped") -- Stop FSM.
|
|
||||||
|
|
||||||
self.ExceptionSet = SET_GROUP:New():Clear(false)
|
|
||||||
|
|
||||||
self:HandleEvent(EVENTS.PlayerEnterAircraft,self._EventHandler)
|
|
||||||
|
|
||||||
self.lid = string.format("TIRESIAS %s | ",self.version)
|
|
||||||
|
|
||||||
self:I(self.lid.."Managing ground groups!")
|
|
||||||
|
|
||||||
--- Triggers the FSM event "Stop". Stops TIRESIAS and all its event handlers.
|
|
||||||
-- @function [parent=#TIRESIAS] Stop
|
|
||||||
-- @param #TIRESIAS self
|
|
||||||
|
|
||||||
--- Triggers the FSM event "Stop" after a delay. Stops TIRESIAS and all its event handlers.
|
|
||||||
-- @function [parent=#TIRESIAS] __Stop
|
|
||||||
-- @param #TIRESIAS self
|
|
||||||
-- @param #number delay Delay in seconds.
|
|
||||||
|
|
||||||
--- Triggers the FSM event "Start". Starts TIRESIAS and all its event handlers. Note - `:New()` already starts the instance.
|
|
||||||
-- @function [parent=#TIRESIAS] Start
|
|
||||||
-- @param #TIRESIAS self
|
|
||||||
|
|
||||||
--- Triggers the FSM event "Start" after a delay. Starts TIRESIAS and all its event handlers. Note - `:New()` already starts the instance.
|
|
||||||
-- @function [parent=#TIRESIAS] __Start
|
|
||||||
-- @param #TIRESIAS self
|
|
||||||
-- @param #number delay Delay in seconds.
|
|
||||||
|
|
||||||
self:__Start(1)
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------
|
|
||||||
--
|
|
||||||
-- Helper Functions
|
|
||||||
--
|
|
||||||
-------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
---[USER] Set activation radius for Helos and Planes in Nautical Miles.
|
|
||||||
-- @param #TIRESIAS self
|
|
||||||
-- @param #number HeloMiles Radius around a Helicopter in which AI ground units will be activated. Defaults to 10NM.
|
|
||||||
-- @param #number PlaneMiles Radius around an Airplane in which AI ground units will be activated. Defaults to 25NM.
|
|
||||||
-- @return #TIRESIAS self
|
|
||||||
function TIRESIAS:SetActivationRanges(HeloMiles,PlaneMiles)
|
|
||||||
self.HeloSwitchRange = HeloMiles or 10
|
|
||||||
self.PlaneSwitchRange = PlaneMiles or 25
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
---[USER] Set AAA Ranges - AAA equals non-SAM systems which qualify as AAA in DCS world.
|
|
||||||
-- @param #TIRESIAS self
|
|
||||||
-- @param #number FiringRange The engagement range that AAA units will be set to. Can be 0 to 100 (percent). Defaults to 60.
|
|
||||||
-- @param #boolean SwitchAAA Decide if these system will have their AI switched off, too. Defaults to true.
|
|
||||||
-- @return #TIRESIAS self
|
|
||||||
function TIRESIAS:SetAAARanges(FiringRange,SwitchAAA)
|
|
||||||
self.AAARange = FiringRange or 60
|
|
||||||
self.SwitchAAA = (SwitchAAA == false) and false or true
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- [USER] Add a SET_GROUP of GROUP objects as exceptions. Can be done multiple times. Does **not** work work for GROUP objects spawned into the SET after start, i.e. the groups need to exist in the game already.
|
|
||||||
-- @param #TIRESIAS self
|
|
||||||
-- @param Core.Set#SET_GROUP Set to add to the exception list.
|
|
||||||
-- @return #TIRESIAS self
|
|
||||||
function TIRESIAS:AddExceptionSet(Set)
|
|
||||||
self:T(self.lid.."AddExceptionSet")
|
|
||||||
local exceptions = self.ExceptionSet
|
|
||||||
Set:ForEachGroupAlive(
|
|
||||||
function(grp)
|
|
||||||
if not grp.Tiresias then
|
|
||||||
grp.Tiresias = { -- #TIRESIAS.Data
|
|
||||||
type = "Exception",
|
|
||||||
exception = true,
|
|
||||||
}
|
|
||||||
exceptions:AddGroup(grp,true)
|
|
||||||
end
|
|
||||||
BASE:T("TIRESIAS: Added exception group: "..grp:GetName())
|
|
||||||
end
|
|
||||||
)
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- [INTERNAL] Filter Function
|
|
||||||
-- @param Wrapper.Group#GROUP Group
|
|
||||||
-- @return #boolean isin
|
|
||||||
function TIRESIAS._FilterNotAAA(Group)
|
|
||||||
local grp = Group -- Wrapper.Group#GROUP
|
|
||||||
local isaaa = grp:IsAAA()
|
|
||||||
if isaaa == true and grp:IsGround() and not grp:IsShip() then
|
|
||||||
return false -- remove from SET
|
|
||||||
else
|
|
||||||
return true -- keep in SET
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--- [INTERNAL] Filter Function
|
|
||||||
-- @param Wrapper.Group#GROUP Group
|
|
||||||
-- @return #boolean isin
|
|
||||||
function TIRESIAS._FilterNotSAM(Group)
|
|
||||||
local grp = Group -- Wrapper.Group#GROUP
|
|
||||||
local issam = grp:IsSAM()
|
|
||||||
if issam == true and grp:IsGround() and not grp:IsShip() then
|
|
||||||
return false -- remove from SET
|
|
||||||
else
|
|
||||||
return true -- keep in SET
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--- [INTERNAL] Filter Function
|
|
||||||
-- @param Wrapper.Group#GROUP Group
|
|
||||||
-- @return #boolean isin
|
|
||||||
function TIRESIAS._FilterAAA(Group)
|
|
||||||
local grp = Group -- Wrapper.Group#GROUP
|
|
||||||
local isaaa = grp:IsAAA()
|
|
||||||
if isaaa == true and grp:IsGround() and not grp:IsShip() then
|
|
||||||
return true -- remove from SET
|
|
||||||
else
|
|
||||||
return false -- keep in SET
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--- [INTERNAL] Filter Function
|
|
||||||
-- @param Wrapper.Group#GROUP Group
|
|
||||||
-- @return #boolean isin
|
|
||||||
function TIRESIAS._FilterSAM(Group)
|
|
||||||
local grp = Group -- Wrapper.Group#GROUP
|
|
||||||
local issam = grp:IsSAM()
|
|
||||||
if issam == true and grp:IsGround() and not grp:IsShip() then
|
|
||||||
return true -- remove from SET
|
|
||||||
else
|
|
||||||
return false -- keep in SET
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--- [INTERNAL] Init Groups
|
|
||||||
-- @param #TIRESIAS self
|
|
||||||
-- @return #TIRESIAS self
|
|
||||||
function TIRESIAS:_InitGroups()
|
|
||||||
self:T(self.lid.."_InitGroups")
|
|
||||||
-- Set all groups invisible/motionless
|
|
||||||
local EngageRange = self.AAARange
|
|
||||||
local SwitchAAA = self.SwitchAAA
|
|
||||||
--- AAA
|
|
||||||
self.AAASet:ForEachGroupAlive(
|
|
||||||
function(grp)
|
|
||||||
if not grp.Tiresias then
|
|
||||||
grp:OptionEngageRange(EngageRange)
|
|
||||||
grp:SetCommandInvisible(true)
|
|
||||||
if SwitchAAA then
|
|
||||||
grp:SetAIOff()
|
|
||||||
grp:EnableEmission(false)
|
|
||||||
end
|
|
||||||
grp.Tiresias = { -- #TIRESIAS.Data
|
|
||||||
type = "AAA",
|
|
||||||
invisible = true,
|
|
||||||
range = EngageRange,
|
|
||||||
exception = false,
|
|
||||||
AIOff = SwitchAAA,
|
|
||||||
}
|
|
||||||
end
|
|
||||||
if grp.Tiresias and (not grp.Tiresias.exception == true) then
|
|
||||||
if grp.Tiresias.invisible == false then
|
|
||||||
grp:SetCommandInvisible(true)
|
|
||||||
grp.Tiresias.invisible = true
|
|
||||||
if SwitchAAA then
|
|
||||||
grp:SetAIOff()
|
|
||||||
grp:EnableEmission(false)
|
|
||||||
grp.Tiresias.AIOff = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
--BASE:I(string.format("Init/Switch off AAA %s (Exception %s)",grp:GetName(),tostring(grp.Tiresias.exception)))
|
|
||||||
end
|
|
||||||
)
|
|
||||||
--- Vehicles
|
|
||||||
self.VehicleSet:ForEachGroupAlive(
|
|
||||||
function(grp)
|
|
||||||
if not grp.Tiresias then
|
|
||||||
grp:SetAIOff()
|
|
||||||
grp:SetCommandInvisible(true)
|
|
||||||
grp.Tiresias = { -- #TIRESIAS.Data
|
|
||||||
type = "Vehicle",
|
|
||||||
invisible = true,
|
|
||||||
AIOff = true,
|
|
||||||
exception = false,
|
|
||||||
}
|
|
||||||
end
|
|
||||||
if grp.Tiresias and (not grp.Tiresias.exception == true) then
|
|
||||||
if grp.Tiresias and grp.Tiresias.invisible == false then
|
|
||||||
grp:SetCommandInvisible(true)
|
|
||||||
grp:SetAIOff()
|
|
||||||
grp.Tiresias.invisible = true
|
|
||||||
grp.Tiresias.AIOff = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
--BASE:I(string.format("Init/Switch off Vehicle %s (Exception %s)",grp:GetName(),tostring(grp.Tiresias.exception)))
|
|
||||||
end
|
|
||||||
)
|
|
||||||
--- SAM
|
|
||||||
self.SAMSet:ForEachGroupAlive(
|
|
||||||
function(grp)
|
|
||||||
if not grp.Tiresias then
|
|
||||||
grp:SetCommandInvisible(true)
|
|
||||||
grp.Tiresias = { -- #TIRESIAS.Data
|
|
||||||
type = "SAM",
|
|
||||||
invisible = true,
|
|
||||||
exception = false,
|
|
||||||
}
|
|
||||||
end
|
|
||||||
if grp.Tiresias and (not grp.Tiresias.exception == true) then
|
|
||||||
if grp.Tiresias and grp.Tiresias.invisible == false then
|
|
||||||
grp:SetCommandInvisible(true)
|
|
||||||
grp.Tiresias.invisible = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
--BASE:I(string.format("Init/Switch off SAM %s (Exception %s)",grp:GetName(),tostring(grp.Tiresias.exception)))
|
|
||||||
end
|
|
||||||
)
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- [INTERNAL] Event handler function
|
|
||||||
-- @param #TIRESIAS self
|
|
||||||
-- @param Core.Event#EVENTDATA EventData
|
|
||||||
-- @return #TIRESIAS self
|
|
||||||
function TIRESIAS:_EventHandler(EventData)
|
|
||||||
self:T(string.format("%s Event = %d",self.lid, EventData.id))
|
|
||||||
local event = EventData -- Core.Event#EVENTDATA
|
|
||||||
if event.id == EVENTS.PlayerEnterAircraft or event.id == EVENTS.PlayerEnterUnit then
|
|
||||||
--local _coalition = event.IniCoalition
|
|
||||||
--if _coalition ~= self.Coalition then
|
|
||||||
-- return --ignore!
|
|
||||||
--end
|
|
||||||
local unitname = event.IniUnitName or "none"
|
|
||||||
local _unit = event.IniUnit
|
|
||||||
local _group = event.IniGroup
|
|
||||||
if _group and _group:IsAlive() then
|
|
||||||
local radius = self.PlaneSwitchRange
|
|
||||||
if _group:IsHelicopter() then
|
|
||||||
radius = self.HeloSwitchRange
|
|
||||||
end
|
|
||||||
self:_SwitchOnGroups(_group,radius)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- [INTERNAL] Switch Groups Behaviour
|
|
||||||
-- @param #TIRESIAS self
|
|
||||||
-- @param Wrapper.Group#GROUP group
|
|
||||||
-- @param #number radius Radius in NM
|
|
||||||
-- @return #TIRESIAS self
|
|
||||||
function TIRESIAS:_SwitchOnGroups(group,radius)
|
|
||||||
self:T(self.lid.."_SwitchOnGroups "..group:GetName().." Radius "..radius.." NM")
|
|
||||||
local zone = ZONE_GROUP:New("Zone-"..group:GetName(),group,UTILS.NMToMeters(radius))
|
|
||||||
local ground = SET_GROUP:New():FilterCategoryGround():FilterZones({zone}):FilterOnce()
|
|
||||||
local count = ground:CountAlive()
|
|
||||||
if self.debug then
|
|
||||||
local text = string.format("There are %d groups around this plane or helo!",count)
|
|
||||||
self:I(text)
|
|
||||||
end
|
|
||||||
local SwitchAAA = self.SwitchAAA
|
|
||||||
if ground:CountAlive() > 0 then
|
|
||||||
ground:ForEachGroupAlive(
|
|
||||||
function(grp)
|
|
||||||
local name = grp:GetName()
|
|
||||||
if grp:GetCoalition() ~= group:GetCoalition()
|
|
||||||
and grp.Tiresias and grp.Tiresias.type and (not grp.Tiresias.exception == true ) then
|
|
||||||
if grp.Tiresias.invisible == true then
|
|
||||||
grp:SetCommandInvisible(false)
|
|
||||||
grp.Tiresias.invisible = false
|
|
||||||
end
|
|
||||||
if grp.Tiresias.type == "Vehicle" and grp.Tiresias.AIOff and grp.Tiresias.AIOff == true then
|
|
||||||
grp:SetAIOn()
|
|
||||||
grp.Tiresias.AIOff = false
|
|
||||||
end
|
|
||||||
if SwitchAAA and grp.Tiresias.type == "AAA" and grp.Tiresias.AIOff and grp.Tiresias.AIOff == true then
|
|
||||||
grp:SetAIOn()
|
|
||||||
grp:EnableEmission(true)
|
|
||||||
grp.Tiresias.AIOff = false
|
|
||||||
end
|
|
||||||
--BASE:I(string.format("TIRESIAS - Switch on %s %s (Exception %s)",tostring(grp.Tiresias.type),grp:GetName(),tostring(grp.Tiresias.exception)))
|
|
||||||
else
|
|
||||||
BASE:T("TIRESIAS - This group "..tostring(name).. " has not been initialized or is an exception!")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
)
|
|
||||||
end
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------
|
|
||||||
--
|
|
||||||
-- FSM Functions
|
|
||||||
--
|
|
||||||
-------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
--- [INTERNAL] FSM Function
|
|
||||||
-- @param #TIRESIAS self
|
|
||||||
-- @param #string From
|
|
||||||
-- @param #string Event
|
|
||||||
-- @param #string To
|
|
||||||
-- @return #TIRESIAS self
|
|
||||||
function TIRESIAS:onafterStart(From, Event, To)
|
|
||||||
self:T({From, Event, To})
|
|
||||||
|
|
||||||
local VehicleSet = SET_GROUP:New():FilterCategoryGround():FilterFunction(TIRESIAS._FilterNotAAA):FilterFunction(TIRESIAS._FilterNotSAM):FilterStart()
|
|
||||||
local AAASet = SET_GROUP:New():FilterCategoryGround():FilterFunction(TIRESIAS._FilterAAA):FilterStart()
|
|
||||||
local SAMSet = SET_GROUP:New():FilterCategoryGround():FilterFunction(TIRESIAS._FilterSAM):FilterStart()
|
|
||||||
local OpsGroupSet = SET_OPSGROUP:New():FilterActive(true):FilterStart()
|
|
||||||
self.FlightSet = SET_GROUP:New():FilterCategories({"plane","helicopter"}):FilterStart()
|
|
||||||
|
|
||||||
local EngageRange = self.AAARange
|
|
||||||
|
|
||||||
local ExceptionSet = self.ExceptionSet
|
|
||||||
if self.ExceptionSet then
|
|
||||||
function ExceptionSet:OnAfterAdded(From,Event,To,ObjectName,Object)
|
|
||||||
BASE:I("TIRESIAS: EXCEPTION Object Added: "..Object:GetName())
|
|
||||||
if Object and Object:IsAlive() then
|
|
||||||
Object.Tiresias = { -- #TIRESIAS.Data
|
|
||||||
type = "Exception",
|
|
||||||
exception = true,
|
|
||||||
}
|
|
||||||
Object:SetAIOn()
|
|
||||||
Object:SetCommandInvisible(false)
|
|
||||||
Object:EnableEmission(true)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local OGS = OpsGroupSet:GetAliveSet()
|
|
||||||
for _,_OG in pairs(OGS or {}) do
|
|
||||||
local OG = _OG -- Ops.OpsGroup#OPSGROUP
|
|
||||||
local grp = OG:GetGroup()
|
|
||||||
ExceptionSet:AddGroup(grp,true)
|
|
||||||
end
|
|
||||||
|
|
||||||
function OpsGroupSet:OnAfterAdded(From,Event,To,ObjectName,Object)
|
|
||||||
local grp = Object:GetGroup()
|
|
||||||
ExceptionSet:AddGroup(grp,true)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function VehicleSet:OnAfterAdded(From,Event,To,ObjectName,Object)
|
|
||||||
BASE:I("TIRESIAS: VEHCILE Object Added: "..Object:GetName())
|
|
||||||
if Object and Object:IsAlive() then
|
|
||||||
Object:SetAIOff()
|
|
||||||
Object:SetCommandInvisible(true)
|
|
||||||
Object.Tiresias = { -- #TIRESIAS.Data
|
|
||||||
type = "Vehicle",
|
|
||||||
invisible = true,
|
|
||||||
AIOff = true,
|
|
||||||
exception = false,
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local SwitchAAA = self.SwitchAAA
|
|
||||||
|
|
||||||
function AAASet:OnAfterAdded(From,Event,To,ObjectName,Object)
|
|
||||||
if Object and Object:IsAlive() then
|
|
||||||
BASE:I("TIRESIAS: AAA Object Added: "..Object:GetName())
|
|
||||||
Object:OptionEngageRange(EngageRange)
|
|
||||||
Object:SetCommandInvisible(true)
|
|
||||||
if SwitchAAA then
|
|
||||||
Object:SetAIOff()
|
|
||||||
Object:EnableEmission(false)
|
|
||||||
end
|
|
||||||
Object.Tiresias = { -- #TIRESIAS.Data
|
|
||||||
type = "AAA",
|
|
||||||
invisible = true,
|
|
||||||
range = EngageRange,
|
|
||||||
exception = false,
|
|
||||||
AIOff = SwitchAAA,
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function SAMSet:OnAfterAdded(From,Event,To,ObjectName,Object)
|
|
||||||
if Object and Object:IsAlive() then
|
|
||||||
BASE:I("TIRESIAS: SAM Object Added: "..Object:GetName())
|
|
||||||
Object:SetCommandInvisible(true)
|
|
||||||
Object.Tiresias = { -- #TIRESIAS.Data
|
|
||||||
type = "SAM",
|
|
||||||
invisible = true,
|
|
||||||
exception = false,
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
self.VehicleSet = VehicleSet
|
|
||||||
self.AAASet = AAASet
|
|
||||||
self.SAMSet = SAMSet
|
|
||||||
self.OpsGroupSet = OpsGroupSet
|
|
||||||
|
|
||||||
self:_InitGroups()
|
|
||||||
|
|
||||||
self:__Status(1)
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- [INTERNAL] FSM Function
|
|
||||||
-- @param #TIRESIAS self
|
|
||||||
-- @param #string From
|
|
||||||
-- @param #string Event
|
|
||||||
-- @param #string To
|
|
||||||
-- @return #TIRESIAS self
|
|
||||||
function TIRESIAS:onbeforeStatus(From, Event, To)
|
|
||||||
self:T({From, Event, To})
|
|
||||||
if self:GetState() == "Stopped" then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- [INTERNAL] FSM Function
|
|
||||||
-- @param #TIRESIAS self
|
|
||||||
-- @param #string From
|
|
||||||
-- @param #string Event
|
|
||||||
-- @param #string To
|
|
||||||
-- @return #TIRESIAS self
|
|
||||||
function TIRESIAS:onafterStatus(From, Event, To)
|
|
||||||
self:T({From, Event, To})
|
|
||||||
if self.debug then
|
|
||||||
local count = self.VehicleSet:CountAlive()
|
|
||||||
local AAAcount = self.AAASet:CountAlive()
|
|
||||||
local SAMcount = self.SAMSet:CountAlive()
|
|
||||||
local text = string.format("Overall: %d | Vehicles: %d | AAA: %d | SAM: %d",count+AAAcount+SAMcount,count,AAAcount,SAMcount)
|
|
||||||
self:I(text)
|
|
||||||
end
|
|
||||||
self:_InitGroups()
|
|
||||||
if self.FlightSet:CountAlive() > 0 then
|
|
||||||
local Set = self.FlightSet:GetAliveSet()
|
|
||||||
for _,_plane in pairs(Set) do
|
|
||||||
local plane = _plane -- Wrapper.Group#GROUP
|
|
||||||
local radius = self.PlaneSwitchRange
|
|
||||||
if plane:IsHelicopter() then
|
|
||||||
radius = self.HeloSwitchRange
|
|
||||||
end
|
|
||||||
self:_SwitchOnGroups(_plane,radius)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if self:GetState() ~= "Stopped" then
|
|
||||||
self:__Status(self.Interval)
|
|
||||||
end
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- [INTERNAL] FSM Function
|
|
||||||
-- @param #TIRESIAS self
|
|
||||||
-- @param #string From
|
|
||||||
-- @param #string Event
|
|
||||||
-- @param #string To
|
|
||||||
-- @return #TIRESIAS self
|
|
||||||
function TIRESIAS:onafterStop(From, Event, To)
|
|
||||||
self:T({From, Event, To})
|
|
||||||
self:UnHandleEvent(EVENTS.PlayerEnterAircraft)
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------
|
|
||||||
--
|
|
||||||
-- End
|
|
||||||
--
|
|
||||||
-------------------------------------------------------------------------------------------------------------
|
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -48,7 +48,7 @@
|
|||||||
|
|
||||||
do -- ZONE_CAPTURE_COALITION
|
do -- ZONE_CAPTURE_COALITION
|
||||||
|
|
||||||
-- @type ZONE_CAPTURE_COALITION
|
--- @type ZONE_CAPTURE_COALITION
|
||||||
-- @field #string ClassName Name of the class.
|
-- @field #string ClassName Name of the class.
|
||||||
-- @field #number MarkBlue ID of blue F10 mark.
|
-- @field #number MarkBlue ID of blue F10 mark.
|
||||||
-- @field #number MarkRed ID of red F10 mark.
|
-- @field #number MarkRed ID of red F10 mark.
|
||||||
@@ -161,7 +161,7 @@ do -- ZONE_CAPTURE_COALITION
|
|||||||
-- The mission designer can use these values to alter the logic.
|
-- The mission designer can use these values to alter the logic.
|
||||||
-- For example:
|
-- For example:
|
||||||
--
|
--
|
||||||
-- -- @param Functional.ZoneCaptureCoalition#ZONE_CAPTURE_COALITION self
|
-- --- @param Functional.ZoneCaptureCoalition#ZONE_CAPTURE_COALITION self
|
||||||
-- function ZoneCaptureCoalition:OnEnterGuarded( From, Event, To )
|
-- function ZoneCaptureCoalition:OnEnterGuarded( From, Event, To )
|
||||||
-- if From ~= "Empty" then
|
-- if From ~= "Empty" then
|
||||||
-- -- Display a message
|
-- -- Display a message
|
||||||
@@ -172,7 +172,7 @@ do -- ZONE_CAPTURE_COALITION
|
|||||||
--
|
--
|
||||||
-- ## Example Event Handler.
|
-- ## Example Event Handler.
|
||||||
--
|
--
|
||||||
-- -- @param Functional.ZoneCaptureCoalition#ZONE_CAPTURE_COALITION self
|
-- --- @param Functional.ZoneCaptureCoalition#ZONE_CAPTURE_COALITION self
|
||||||
-- function ZoneCaptureCoalition:OnEnterGuarded( From, Event, To )
|
-- function ZoneCaptureCoalition:OnEnterGuarded( From, Event, To )
|
||||||
-- if From ~= To then
|
-- if From ~= To then
|
||||||
-- local Coalition = self:GetCoalition()
|
-- local Coalition = self:GetCoalition()
|
||||||
@@ -273,7 +273,7 @@ do -- ZONE_CAPTURE_COALITION
|
|||||||
-- Depending on the zone ownership, different messages are sent.
|
-- Depending on the zone ownership, different messages are sent.
|
||||||
-- Note the methods `ZoneCaptureCoalition:GetZoneName()`.
|
-- Note the methods `ZoneCaptureCoalition:GetZoneName()`.
|
||||||
--
|
--
|
||||||
-- -- @param Functional.ZoneCaptureCoalition#ZONE_CAPTURE_COALITION self
|
-- --- @param Functional.ZoneCaptureCoalition#ZONE_CAPTURE_COALITION self
|
||||||
-- function ZoneCaptureCoalition:OnEnterGuarded( From, Event, To )
|
-- function ZoneCaptureCoalition:OnEnterGuarded( From, Event, To )
|
||||||
-- if From ~= To then
|
-- if From ~= To then
|
||||||
-- local Coalition = self:GetCoalition()
|
-- local Coalition = self:GetCoalition()
|
||||||
@@ -294,7 +294,7 @@ do -- ZONE_CAPTURE_COALITION
|
|||||||
-- Next is the Event Handler when the **Empty** state transition is triggered.
|
-- Next is the Event Handler when the **Empty** state transition is triggered.
|
||||||
-- Now we smoke the ZoneCaptureCoalition with a green color, using `self:Smoke( SMOKECOLOR.Green )`.
|
-- Now we smoke the ZoneCaptureCoalition with a green color, using `self:Smoke( SMOKECOLOR.Green )`.
|
||||||
--
|
--
|
||||||
-- -- @param Functional.Protect#ZONE_CAPTURE_COALITION self
|
-- --- @param Functional.Protect#ZONE_CAPTURE_COALITION self
|
||||||
-- function ZoneCaptureCoalition:OnEnterEmpty()
|
-- function ZoneCaptureCoalition:OnEnterEmpty()
|
||||||
-- self:Smoke( SMOKECOLOR.Green )
|
-- self:Smoke( SMOKECOLOR.Green )
|
||||||
-- US_CC:MessageTypeToCoalition( string.format( "%s is unprotected, and can be captured!", ZoneCaptureCoalition:GetZoneName() ), MESSAGE.Type.Information )
|
-- US_CC:MessageTypeToCoalition( string.format( "%s is unprotected, and can be captured!", ZoneCaptureCoalition:GetZoneName() ), MESSAGE.Type.Information )
|
||||||
@@ -304,7 +304,7 @@ do -- ZONE_CAPTURE_COALITION
|
|||||||
-- The next Event Handlers speak for itself.
|
-- The next Event Handlers speak for itself.
|
||||||
-- When the zone is Attacked, we smoke the zone white and send some messages to each coalition.
|
-- When the zone is Attacked, we smoke the zone white and send some messages to each coalition.
|
||||||
--
|
--
|
||||||
-- -- @param Functional.Protect#ZONE_CAPTURE_COALITION self
|
-- --- @param Functional.Protect#ZONE_CAPTURE_COALITION self
|
||||||
-- function ZoneCaptureCoalition:OnEnterAttacked()
|
-- function ZoneCaptureCoalition:OnEnterAttacked()
|
||||||
-- ZoneCaptureCoalition:Smoke( SMOKECOLOR.White )
|
-- ZoneCaptureCoalition:Smoke( SMOKECOLOR.White )
|
||||||
-- local Coalition = self:GetCoalition()
|
-- local Coalition = self:GetCoalition()
|
||||||
@@ -321,7 +321,7 @@ do -- ZONE_CAPTURE_COALITION
|
|||||||
-- When the zone is Captured, we send some victory or loss messages to the correct coalition.
|
-- When the zone is Captured, we send some victory or loss messages to the correct coalition.
|
||||||
-- And we add some score.
|
-- And we add some score.
|
||||||
--
|
--
|
||||||
-- -- @param Functional.Protect#ZONE_CAPTURE_COALITION self
|
-- --- @param Functional.Protect#ZONE_CAPTURE_COALITION self
|
||||||
-- function ZoneCaptureCoalition:OnEnterCaptured()
|
-- function ZoneCaptureCoalition:OnEnterCaptured()
|
||||||
-- local Coalition = self:GetCoalition()
|
-- local Coalition = self:GetCoalition()
|
||||||
-- self:E({Coalition = Coalition})
|
-- self:E({Coalition = Coalition})
|
||||||
@@ -641,7 +641,7 @@ do -- ZONE_CAPTURE_COALITION
|
|||||||
--
|
--
|
||||||
-- @usage
|
-- @usage
|
||||||
-- -- For example, one could stop the monitoring when the zone was captured!
|
-- -- For example, one could stop the monitoring when the zone was captured!
|
||||||
-- -- @param Functional.Protect#ZONE_CAPTURE_COALITION self
|
-- --- @param Functional.Protect#ZONE_CAPTURE_COALITION self
|
||||||
-- function ZoneCaptureCoalition:OnEnterCaptured()
|
-- function ZoneCaptureCoalition:OnEnterCaptured()
|
||||||
-- local Coalition = self:GetCoalition()
|
-- local Coalition = self:GetCoalition()
|
||||||
-- self:E({Coalition = Coalition})
|
-- self:E({Coalition = Coalition})
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
do -- Zone
|
do -- Zone
|
||||||
|
|
||||||
-- @type ZONE_GOAL
|
--- @type ZONE_GOAL
|
||||||
-- @field #string ClassName Name of the class.
|
-- @field #string ClassName Name of the class.
|
||||||
-- @field Core.Goal#GOAL Goal The goal object.
|
-- @field Core.Goal#GOAL Goal The goal object.
|
||||||
-- @field #number SmokeTime Time stamp in seconds when the last smoke of the zone was triggered.
|
-- @field #number SmokeTime Time stamp in seconds when the last smoke of the zone was triggered.
|
||||||
@@ -178,7 +178,7 @@ do -- Zone
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- @param #ZONE_GOAL self
|
--- @param #ZONE_GOAL self
|
||||||
-- @param Core.Event#EVENTDATA EventData Event data table.
|
-- @param Core.Event#EVENTDATA EventData Event data table.
|
||||||
function ZONE_GOAL:__Destroyed( EventData )
|
function ZONE_GOAL:__Destroyed( EventData )
|
||||||
self:F( { "EventDead", EventData } )
|
self:F( { "EventDead", EventData } )
|
||||||
|
|||||||
@@ -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
|
||||||
--
|
--
|
||||||
@@ -21,7 +23,7 @@
|
|||||||
|
|
||||||
do -- ZoneGoal
|
do -- ZoneGoal
|
||||||
|
|
||||||
-- @type ZONE_GOAL_CARGO
|
--- @type ZONE_GOAL_CARGO
|
||||||
-- @extends Functional.ZoneGoal#ZONE_GOAL
|
-- @extends Functional.ZoneGoal#ZONE_GOAL
|
||||||
|
|
||||||
|
|
||||||
@@ -55,7 +57,7 @@ do -- ZoneGoal
|
|||||||
ClassName = "ZONE_GOAL_CARGO",
|
ClassName = "ZONE_GOAL_CARGO",
|
||||||
}
|
}
|
||||||
|
|
||||||
-- @field #table ZONE_GOAL_CARGO.States
|
--- @field #table ZONE_GOAL_CARGO.States
|
||||||
ZONE_GOAL_CARGO.States = {}
|
ZONE_GOAL_CARGO.States = {}
|
||||||
|
|
||||||
--- ZONE_GOAL_CARGO Constructor.
|
--- ZONE_GOAL_CARGO Constructor.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
--- **Functional (WIP)** - Base class modeling processes to achieve goals involving coalition zones.
|
--- **Functional** - Base class that models processes to achieve goals involving a Zone for a Coalition.
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
do -- ZoneGoal
|
do -- ZoneGoal
|
||||||
|
|
||||||
-- @type ZONE_GOAL_COALITION
|
--- @type ZONE_GOAL_COALITION
|
||||||
-- @field #string ClassName Name of the Class.
|
-- @field #string ClassName Name of the Class.
|
||||||
-- @field #number Coalition The current coalition ID of the zone owner.
|
-- @field #number Coalition The current coalition ID of the zone owner.
|
||||||
-- @field #number PreviousCoalition The previous owner of the zone.
|
-- @field #number PreviousCoalition The previous owner of the zone.
|
||||||
@@ -48,7 +48,7 @@ do -- ZoneGoal
|
|||||||
ObjectCategories = nil,
|
ObjectCategories = nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
-- @field #table ZONE_GOAL_COALITION.States
|
--- @field #table ZONE_GOAL_COALITION.States
|
||||||
ZONE_GOAL_COALITION.States = {}
|
ZONE_GOAL_COALITION.States = {}
|
||||||
|
|
||||||
--- ZONE_GOAL_COALITION Constructor.
|
--- ZONE_GOAL_COALITION Constructor.
|
||||||
|
|||||||
@@ -31,8 +31,6 @@ __Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Core/Spot.lua' )
|
|||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Core/MarkerOps_Base.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Core/MarkerOps_Base.lua' )
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Core/TextAndSound.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Core/TextAndSound.lua' )
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Core/Pathline.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Core/Pathline.lua' )
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Core/ClientMenu.lua')
|
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Core/Vector.lua')
|
|
||||||
|
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Wrapper/Object.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Wrapper/Object.lua' )
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Wrapper/Identifiable.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Wrapper/Identifiable.lua' )
|
||||||
@@ -78,13 +76,7 @@ __Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/Warehouse.lua' )
|
|||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/Fox.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/Fox.lua' )
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/Mantis.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/Mantis.lua' )
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/Shorad.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/Shorad.lua' )
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/AICSAR.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/ClientWatch.lua' )
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/AmmoTruck.lua' )
|
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/Autolase.lua' )
|
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/ZoneGoalCargo.lua' )
|
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/Tiresias.lua' )
|
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/Stratego.lua' )
|
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/ClientWatch.lua')
|
|
||||||
|
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/Airboss.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/Airboss.lua' )
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/RecoveryTanker.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/RecoveryTanker.lua' )
|
||||||
@@ -92,31 +84,6 @@ __Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/RescueHelo.lua' )
|
|||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/ATIS.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/ATIS.lua' )
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/CTLD.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/CTLD.lua' )
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/CSAR.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/CSAR.lua' )
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/AirWing.lua' )
|
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/ArmyGroup.lua' )
|
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/Auftrag.lua' )
|
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/Awacs.lua' )
|
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/Brigade.lua' )
|
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/Chief.lua' )
|
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/Cohort.lua' )
|
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/Commander.lua' )
|
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/Fleet.lua' )
|
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/FlightControl.lua' )
|
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/FlightGroup.lua' )
|
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/Flotilla.lua' )
|
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/Intelligence.lua' )
|
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/Legion.lua' )
|
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/NavyGroup.lua' )
|
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/Operation.lua' )
|
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/OpsGroup.lua' )
|
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/OpsTransport.lua' )
|
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/OpsZone.lua' )
|
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/Platoon.lua' )
|
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/PlayerTask.lua' )
|
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/PlayerRecce.lua' )
|
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/Squadron.lua' )
|
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/Target.lua' )
|
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/EasyGCICAP.lua' )
|
|
||||||
|
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/AI/AI_Balancer.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/AI/AI_Balancer.lua' )
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/AI/AI_Air.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/AI/AI_Air.lua' )
|
||||||
@@ -187,9 +154,4 @@ __Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Tasking/Task_Cargo_Dispatcher
|
|||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Tasking/Task_Capture_Zone.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Tasking/Task_Capture_Zone.lua' )
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Tasking/Task_Capture_Dispatcher.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Tasking/Task_Capture_Dispatcher.lua' )
|
||||||
|
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Navigation/Beacons.lua' )
|
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Navigation/Point.lua' )
|
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Navigation/Procedure.lua' )
|
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Navigation/FlightPlan.lua' )
|
|
||||||
|
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Globals.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Globals.lua' )
|
||||||
|
|||||||
@@ -1,185 +0,0 @@
|
|||||||
__Moose.Include( 'Utilities\\Enums.lua' )
|
|
||||||
__Moose.Include( 'Utilities\\Utils.lua' )
|
|
||||||
__Moose.Include( 'Utilities\\Profiler.lua' )
|
|
||||||
--__Moose.Include( 'Utilities\\STTS.lua' )
|
|
||||||
__Moose.Include( 'Utilities\\FiFo.lua' )
|
|
||||||
__Moose.Include( 'Utilities\\Socket.lua' )
|
|
||||||
|
|
||||||
__Moose.Include( 'Core\\Base.lua' )
|
|
||||||
__Moose.Include( 'Core\\Beacon.lua' )
|
|
||||||
__Moose.Include( 'Core\\UserFlag.lua' )
|
|
||||||
__Moose.Include( 'Core\\Report.lua' )
|
|
||||||
__Moose.Include( 'Core\\Scheduler.lua' )
|
|
||||||
__Moose.Include( 'Core\\ScheduleDispatcher.lua' )
|
|
||||||
__Moose.Include( 'Core\\Event.lua' )
|
|
||||||
__Moose.Include( 'Core\\Settings.lua' )
|
|
||||||
__Moose.Include( 'Core\\Menu.lua' )
|
|
||||||
__Moose.Include( 'Core\\Zone.lua' )
|
|
||||||
__Moose.Include( 'Core\\Velocity.lua' )
|
|
||||||
__Moose.Include( 'Core\\Database.lua' )
|
|
||||||
__Moose.Include( 'Core\\Set.lua' )
|
|
||||||
__Moose.Include( 'Core\\Point.lua' )
|
|
||||||
__Moose.Include( 'Core\\Pathline.lua' )
|
|
||||||
__Moose.Include( 'Core\\Message.lua' )
|
|
||||||
__Moose.Include( 'Core\\Fsm.lua' )
|
|
||||||
__Moose.Include( 'Core\\Spawn.lua' )
|
|
||||||
__Moose.Include( 'Core\\SpawnStatic.lua' )
|
|
||||||
__Moose.Include( 'Core\\Timer.lua' )
|
|
||||||
__Moose.Include( 'Core\\Goal.lua' )
|
|
||||||
__Moose.Include( 'Core\\Spot.lua' )
|
|
||||||
__Moose.Include( 'Core\\Astar.lua' )
|
|
||||||
__Moose.Include( 'Core\\MarkerOps_Base.lua' )
|
|
||||||
__Moose.Include( 'Core\\TextAndSound.lua' )
|
|
||||||
__Moose.Include( 'Core\\Condition.lua' )
|
|
||||||
__Moose.Include( 'Core\\ClientMenu.lua' )
|
|
||||||
__Moose.Include( 'Core\\Vector.lua' )
|
|
||||||
|
|
||||||
__Moose.Include( 'Wrapper\\Object.lua' )
|
|
||||||
__Moose.Include( 'Wrapper\\Identifiable.lua' )
|
|
||||||
__Moose.Include( 'Wrapper\\Positionable.lua' )
|
|
||||||
__Moose.Include( 'Wrapper\\Controllable.lua' )
|
|
||||||
__Moose.Include( 'Wrapper\\Group.lua' )
|
|
||||||
__Moose.Include( 'Wrapper\\Unit.lua' )
|
|
||||||
__Moose.Include( 'Wrapper\\Client.lua' )
|
|
||||||
__Moose.Include( 'Wrapper\\Static.lua' )
|
|
||||||
__Moose.Include( 'Wrapper\\Airbase.lua' )
|
|
||||||
__Moose.Include( 'Wrapper\\Scenery.lua' )
|
|
||||||
__Moose.Include( 'Wrapper\\Marker.lua' )
|
|
||||||
__Moose.Include( 'Wrapper\\Net.lua' )
|
|
||||||
__Moose.Include( 'Wrapper\\Weapon.lua' )
|
|
||||||
__Moose.Include( 'Wrapper\\Storage.lua' )
|
|
||||||
__Moose.Include( 'Wrapper\\DynamicCargo.lua' )
|
|
||||||
|
|
||||||
__Moose.Include( 'Cargo\\Cargo.lua' )
|
|
||||||
__Moose.Include( 'Cargo\\CargoUnit.lua' )
|
|
||||||
__Moose.Include( 'Cargo\\CargoSlingload.lua' )
|
|
||||||
__Moose.Include( 'Cargo\\CargoCrate.lua' )
|
|
||||||
__Moose.Include( 'Cargo\\CargoGroup.lua' )
|
|
||||||
|
|
||||||
__Moose.Include( 'Functional\\Scoring.lua' )
|
|
||||||
__Moose.Include( 'Functional\\CleanUp.lua' )
|
|
||||||
__Moose.Include( 'Functional\\Movement.lua' )
|
|
||||||
__Moose.Include( 'Functional\\Sead.lua' )
|
|
||||||
__Moose.Include( 'Functional\\Escort.lua' )
|
|
||||||
__Moose.Include( 'Functional\\MissileTrainer.lua' )
|
|
||||||
__Moose.Include( 'Functional\\ATC_Ground.lua' )
|
|
||||||
__Moose.Include( 'Functional\\Detection.lua' )
|
|
||||||
__Moose.Include( 'Functional\\DetectionZones.lua' )
|
|
||||||
__Moose.Include( 'Functional\\Designate.lua' )
|
|
||||||
__Moose.Include( 'Functional\\RAT.lua' )
|
|
||||||
__Moose.Include( 'Functional\\Range.lua' )
|
|
||||||
__Moose.Include( 'Functional\\ZoneGoal.lua' )
|
|
||||||
__Moose.Include( 'Functional\\ZoneGoalCoalition.lua' )
|
|
||||||
__Moose.Include( 'Functional\\ZoneCaptureCoalition.lua' )
|
|
||||||
__Moose.Include( 'Functional\\Artillery.lua' )
|
|
||||||
__Moose.Include( 'Functional\\Suppression.lua' )
|
|
||||||
__Moose.Include( 'Functional\\PseudoATC.lua' )
|
|
||||||
__Moose.Include( 'Functional\\Warehouse.lua' )
|
|
||||||
__Moose.Include( 'Functional\\Fox.lua' )
|
|
||||||
__Moose.Include( 'Functional\\Mantis.lua' )
|
|
||||||
__Moose.Include( 'Functional\\Shorad.lua' )
|
|
||||||
__Moose.Include( 'Functional\\Autolase.lua' )
|
|
||||||
__Moose.Include( 'Functional\\AICSAR.lua' )
|
|
||||||
__Moose.Include( 'Functional\\AmmoTruck.lua' )
|
|
||||||
__Moose.Include( 'Functional\\Tiresias.lua' )
|
|
||||||
__Moose.Include( 'Functional\\Stratego.lua' )
|
|
||||||
__Moose.Include( 'Functional\\ClientWatch.lua' )
|
|
||||||
|
|
||||||
__Moose.Include( 'Ops\\Airboss.lua' )
|
|
||||||
__Moose.Include( 'Ops\\RecoveryTanker.lua' )
|
|
||||||
__Moose.Include( 'Ops\\RescueHelo.lua' )
|
|
||||||
__Moose.Include( 'Ops\\ATIS.lua' )
|
|
||||||
__Moose.Include( 'Ops\\Auftrag.lua' )
|
|
||||||
__Moose.Include( 'Ops\\Target.lua' )
|
|
||||||
__Moose.Include( 'Ops\\OpsGroup.lua' )
|
|
||||||
__Moose.Include( 'Ops\\FlightGroup.lua' )
|
|
||||||
__Moose.Include( 'Ops\\NavyGroup.lua' )
|
|
||||||
__Moose.Include( 'Ops\\ArmyGroup.lua' )
|
|
||||||
__Moose.Include( 'Ops\\Cohort.lua' )
|
|
||||||
__Moose.Include( 'Ops\\Squadron.lua' )
|
|
||||||
__Moose.Include( 'Ops\\Platoon.lua' )
|
|
||||||
__Moose.Include( 'Ops\\Legion.lua' )
|
|
||||||
__Moose.Include( 'Ops\\AirWing.lua' )
|
|
||||||
__Moose.Include( 'Ops\\Brigade.lua' )
|
|
||||||
__Moose.Include( 'Ops\\Intelligence.lua' )
|
|
||||||
__Moose.Include( 'Ops\\Commander.lua' )
|
|
||||||
__Moose.Include( 'Ops\\OpsTransport.lua' )
|
|
||||||
__Moose.Include( 'Ops\\CSAR.lua' )
|
|
||||||
__Moose.Include( 'Ops\\CTLD.lua' )
|
|
||||||
__Moose.Include( 'Ops\\OpsZone.lua' )
|
|
||||||
__Moose.Include( 'Ops\\Chief.lua' )
|
|
||||||
__Moose.Include( 'Ops\\Flotilla.lua' )
|
|
||||||
__Moose.Include( 'Ops\\Fleet.lua' )
|
|
||||||
__Moose.Include( 'Ops\\Awacs.lua' )
|
|
||||||
__Moose.Include( 'Ops\\PlayerTask.lua' )
|
|
||||||
__Moose.Include( 'Ops\\Operation.lua' )
|
|
||||||
__Moose.Include( 'Ops\\FlightControl.lua' )
|
|
||||||
__Moose.Include( 'Ops\\PlayerRecce.lua' )
|
|
||||||
__Moose.Include( 'Ops\\EasyGCICAP.lua' )
|
|
||||||
__Moose.Include( 'Ops\\EasyA2G.lua' )
|
|
||||||
|
|
||||||
__Moose.Include( 'AI\\AI_Balancer.lua' )
|
|
||||||
__Moose.Include( 'AI\\AI_Air.lua' )
|
|
||||||
__Moose.Include( 'AI\\AI_Air_Patrol.lua' )
|
|
||||||
__Moose.Include( 'AI\\AI_Air_Engage.lua' )
|
|
||||||
__Moose.Include( 'AI\\AI_A2A_Patrol.lua' )
|
|
||||||
__Moose.Include( 'AI\\AI_A2A_Cap.lua' )
|
|
||||||
__Moose.Include( 'AI\\AI_A2A_Gci.lua' )
|
|
||||||
__Moose.Include( 'AI\\AI_A2A_Dispatcher.lua' )
|
|
||||||
__Moose.Include( 'AI\\AI_A2G_BAI.lua' )
|
|
||||||
__Moose.Include( 'AI\\AI_A2G_CAS.lua' )
|
|
||||||
__Moose.Include( 'AI\\AI_A2G_SEAD.lua' )
|
|
||||||
__Moose.Include( 'AI\\AI_A2G_Dispatcher.lua' )
|
|
||||||
__Moose.Include( 'AI\\AI_Patrol.lua' )
|
|
||||||
__Moose.Include( 'AI\\AI_Cap.lua' )
|
|
||||||
__Moose.Include( 'AI\\AI_Cas.lua' )
|
|
||||||
__Moose.Include( 'AI\\AI_Bai.lua' )
|
|
||||||
__Moose.Include( 'AI\\AI_Formation.lua' )
|
|
||||||
__Moose.Include( 'AI\\AI_Escort.lua' )
|
|
||||||
__Moose.Include( 'AI\\AI_Escort_Request.lua' )
|
|
||||||
__Moose.Include( 'AI\\AI_Escort_Dispatcher.lua' )
|
|
||||||
__Moose.Include( 'AI\\AI_Escort_Dispatcher_Request.lua' )
|
|
||||||
__Moose.Include( 'AI\\AI_Cargo.lua' )
|
|
||||||
__Moose.Include( 'AI\\AI_Cargo_APC.lua' )
|
|
||||||
__Moose.Include( 'AI\\AI_Cargo_Helicopter.lua' )
|
|
||||||
__Moose.Include( 'AI\\AI_Cargo_Airplane.lua' )
|
|
||||||
__Moose.Include( 'AI\\AI_Cargo_Ship.lua' )
|
|
||||||
__Moose.Include( 'AI\\AI_Cargo_Dispatcher.lua' )
|
|
||||||
__Moose.Include( 'AI\\AI_Cargo_Dispatcher_APC.lua' )
|
|
||||||
__Moose.Include( 'AI\\AI_Cargo_Dispatcher_Helicopter.lua' )
|
|
||||||
__Moose.Include( 'AI\\AI_Cargo_Dispatcher_Airplane.lua' )
|
|
||||||
__Moose.Include( 'AI\\AI_Cargo_Dispatcher_Ship.lua' )
|
|
||||||
|
|
||||||
__Moose.Include( 'Actions\\Act_Assign.lua' )
|
|
||||||
__Moose.Include( 'Actions\\Act_Route.lua' )
|
|
||||||
__Moose.Include( 'Actions\\Act_Account.lua' )
|
|
||||||
__Moose.Include( 'Actions\\Act_Assist.lua' )
|
|
||||||
|
|
||||||
__Moose.Include( 'Sound\\UserSound.lua' )
|
|
||||||
__Moose.Include( 'Sound\\SoundOutput.lua' )
|
|
||||||
__Moose.Include( 'Sound\\Radio.lua' )
|
|
||||||
__Moose.Include( 'Sound\\RadioQueue.lua' )
|
|
||||||
__Moose.Include( 'Sound\\RadioSpeech.lua' )
|
|
||||||
__Moose.Include( 'Sound\\SRS.lua' )
|
|
||||||
|
|
||||||
__Moose.Include( 'Tasking\\CommandCenter.lua' )
|
|
||||||
__Moose.Include( 'Tasking\\Mission.lua' )
|
|
||||||
__Moose.Include( 'Tasking\\Task.lua' )
|
|
||||||
__Moose.Include( 'Tasking\\TaskInfo.lua' )
|
|
||||||
__Moose.Include( 'Tasking\\Task_Manager.lua' )
|
|
||||||
__Moose.Include( 'Tasking\\DetectionManager.lua' )
|
|
||||||
__Moose.Include( 'Tasking\\Task_A2G_Dispatcher.lua' )
|
|
||||||
__Moose.Include( 'Tasking\\Task_A2G.lua' )
|
|
||||||
__Moose.Include( 'Tasking\\Task_A2A_Dispatcher.lua' )
|
|
||||||
__Moose.Include( 'Tasking\\Task_A2A.lua' )
|
|
||||||
__Moose.Include( 'Tasking\\Task_Cargo.lua' )
|
|
||||||
__Moose.Include( 'Tasking\\Task_Cargo_Transport.lua' )
|
|
||||||
__Moose.Include( 'Tasking\\Task_Cargo_CSAR.lua' )
|
|
||||||
__Moose.Include( 'Tasking\\Task_Cargo_Dispatcher.lua' )
|
|
||||||
__Moose.Include( 'Tasking\\Task_Capture_Zone.lua' )
|
|
||||||
__Moose.Include( 'Tasking\\Task_Capture_Dispatcher.lua' )
|
|
||||||
|
|
||||||
__Moose.Include( 'Navigation\\Point.lua' )
|
|
||||||
__Moose.Include( 'Navigation\\Beacons.lua' )
|
|
||||||
|
|
||||||
__Moose.Include( 'Globals.lua' )
|
|
||||||
@@ -1,139 +0,0 @@
|
|||||||
--- **NAVIGATION** - Beacons of the map/theatre.
|
|
||||||
--
|
|
||||||
-- **Main Features:**
|
|
||||||
--
|
|
||||||
-- * Beacons of the map
|
|
||||||
--
|
|
||||||
-- ===
|
|
||||||
--
|
|
||||||
-- ## Example Missions:
|
|
||||||
--
|
|
||||||
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/Navigation%20-%20Beacons).
|
|
||||||
--
|
|
||||||
-- ===
|
|
||||||
--
|
|
||||||
-- ### Author: **funkyfranky**
|
|
||||||
--
|
|
||||||
-- ===
|
|
||||||
-- @module Navigation.Beacons
|
|
||||||
-- @image NAVIGATION_Beacons.png
|
|
||||||
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
--- BEACONS class.
|
|
||||||
-- @type BEACONS
|
|
||||||
--
|
|
||||||
-- @field #string ClassName Name of the class.
|
|
||||||
-- @field #number verbose Verbosity of output.
|
|
||||||
-- @field #table beacons Beacons.
|
|
||||||
--
|
|
||||||
-- @extends Core.Base#BASE
|
|
||||||
|
|
||||||
--- *A fleet of British ships at war are the best negotiators.* -- Horatio Nelson
|
|
||||||
--
|
|
||||||
-- ===
|
|
||||||
--
|
|
||||||
-- # The BEACONS Concept
|
|
||||||
--
|
|
||||||
-- The NAVFIX class has a great concept!
|
|
||||||
--
|
|
||||||
-- Bla, bla...
|
|
||||||
--
|
|
||||||
-- # Basic Setup
|
|
||||||
--
|
|
||||||
-- A new `BEACONS` object can be created with the @{#BEACONS.New}() function.
|
|
||||||
--
|
|
||||||
-- local beacons=BEACONS:New("G:\Games\DCS World Testing\Mods\terrains\GermanyColdWar\beacons.lua")
|
|
||||||
--
|
|
||||||
-- This is how it works.
|
|
||||||
--
|
|
||||||
-- @field #BEACONS
|
|
||||||
BEACONS = {
|
|
||||||
ClassName = "BEACONS",
|
|
||||||
verbose = 0,
|
|
||||||
beacons = {},
|
|
||||||
}
|
|
||||||
|
|
||||||
--- BEACONS class version.
|
|
||||||
-- @field #string version
|
|
||||||
BEACONS.version="0.0.0"
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-- ToDo list
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
-- TODO: A lot...
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-- Constructor(s)
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
--- Create a new BECAONS class instance from a given file.
|
|
||||||
-- @param #BEACONS self
|
|
||||||
-- @param #string FileName Full path to the file containing the map beacons.
|
|
||||||
-- @return #BEACONS self
|
|
||||||
function BEACONS:NewFromFile(FileName)
|
|
||||||
|
|
||||||
-- Inherit everything from BASE class.
|
|
||||||
self=BASE:Inherit(self, BASE:New()) -- #BEACONS
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-- User Functions
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
--- Add marker all beacons on the F10 map.
|
|
||||||
-- @param #BEACONS self
|
|
||||||
-- @return #BEACONS self
|
|
||||||
function BEACONS:MarkerShow()
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Remove markers of all beacons from the F10 map.
|
|
||||||
-- @param #BEACONS self
|
|
||||||
-- @return #BEACONS self
|
|
||||||
function BEACONS:MarkerRemove()
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-- Private Functions
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
--- Get text displayed in the F10 marker.
|
|
||||||
-- @param #BEACONS self
|
|
||||||
-- @return #string Marker text.
|
|
||||||
function BEACONS:_GetMarkerText(beacon)
|
|
||||||
|
|
||||||
local altmin=self.altMin and tostring(self.altMin) or ""
|
|
||||||
local altmax=self.altMax and tostring(self.altMax) or ""
|
|
||||||
local speedmin=self.speedMin and tostring(self.speedMin) or ""
|
|
||||||
local speedmax=self.speedMax and tostring(self.speedMax) or ""
|
|
||||||
|
|
||||||
|
|
||||||
local text=string.format("NAVFIX %s", self.name)
|
|
||||||
if self.isIAF then
|
|
||||||
text=text..string.format(" (IAF)")
|
|
||||||
end
|
|
||||||
if self.isIF then
|
|
||||||
text=text..string.format(" (IF)")
|
|
||||||
end
|
|
||||||
text=text..string.format("\nAltitude [ft]: %s - %s", altmin, altmax)
|
|
||||||
text=text..string.format("\nSpeed [knots]: %s - %s", speedmin, speedmax)
|
|
||||||
text=text..string.format("\nCompulsory: %s", tostring(self.isCompulsory))
|
|
||||||
text=text..string.format("\nFly Over: %s", tostring(self.isFlyover))
|
|
||||||
|
|
||||||
return text
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
@@ -1,481 +0,0 @@
|
|||||||
--- **NAVIGATION** - Flight Plan.
|
|
||||||
--
|
|
||||||
-- **Main Features:**
|
|
||||||
--
|
|
||||||
-- * Manage navigation aids
|
|
||||||
-- * VOR, NDB
|
|
||||||
--
|
|
||||||
-- ===
|
|
||||||
--
|
|
||||||
-- ## Example Missions:
|
|
||||||
--
|
|
||||||
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/Ops%20-%20FlightPlan).
|
|
||||||
--
|
|
||||||
-- ===
|
|
||||||
--
|
|
||||||
-- ### Author: **funkyfranky**
|
|
||||||
--
|
|
||||||
-- ===
|
|
||||||
-- @module Navigation.FlightPlan
|
|
||||||
-- @image NAVIGATION_FlightPlan.png
|
|
||||||
|
|
||||||
|
|
||||||
--- FLIGHTPLAN class.
|
|
||||||
-- @type FLIGHTPLAN
|
|
||||||
-- @field #string ClassName Name of the class.
|
|
||||||
-- @field #number verbose Verbosity of output.
|
|
||||||
-- @field #table fixes Navigation fixes.
|
|
||||||
-- @field Core.Pathline#PATHLINE pathline Pathline of the plan.
|
|
||||||
-- @field Wrapper.Airbase#AIRBASE departureAirbase Departure airbase.
|
|
||||||
-- @field Wrapper.Airbase#AIRBASE destinationAirbase Destination airbase.
|
|
||||||
-- @field #number altitudeCruiseMin Minimum cruise altitude in feet MSL.
|
|
||||||
-- @field #number altitudeCruiseMax Maximum cruise altitude in feet MSL.
|
|
||||||
-- @extends Core.Pathline#PATHLINE
|
|
||||||
|
|
||||||
--- *Life is what happens to us while we are making other plans.* -- Allen Saunders
|
|
||||||
--
|
|
||||||
-- ===
|
|
||||||
--
|
|
||||||
-- # The FLIGHTPLAN Concept
|
|
||||||
--
|
|
||||||
-- This class has a great concept!
|
|
||||||
--
|
|
||||||
-- # Basic Setup
|
|
||||||
--
|
|
||||||
-- A new `FLIGHTPLAN` object can be created with the @{#FLIGHTPLAN.New}() function.
|
|
||||||
--
|
|
||||||
-- myFlightplan=FLIGHTPLAN:New("Plan A")
|
|
||||||
-- myFleet:SetPortZone(ZonePort1stFleet)
|
|
||||||
-- myFleet:Start()
|
|
||||||
--
|
|
||||||
-- A fleet needs a *port zone*, which is set via the @{#FLIGHTPLAN.SetPortZone}(`PortZone`) function. This is the zone where the naval assets are spawned and return to.
|
|
||||||
--
|
|
||||||
-- Finally, the fleet needs to be started using the @{#FLIGHTPLAN.Start}() function. If the fleet is not started, it will not process any requests.
|
|
||||||
--
|
|
||||||
-- @field #FLIGHTPLAN
|
|
||||||
FLIGHTPLAN = {
|
|
||||||
ClassName = "FLIGHTPLAN",
|
|
||||||
verbose = 0,
|
|
||||||
fixes = {}
|
|
||||||
}
|
|
||||||
|
|
||||||
--- Type of flightplan.
|
|
||||||
-- @type FLIGHTPLAN.Type
|
|
||||||
-- @field #string IFRH Instrument Flying Rules High Altitude.
|
|
||||||
-- @field #string IFRL Instrument Flying Rules Low Altitude.
|
|
||||||
-- @field #string VFR Visual Flight Rules.
|
|
||||||
FLIGHTPLAN.Type={
|
|
||||||
IFRH = "IFR High",
|
|
||||||
IFRL = "IFR Low",
|
|
||||||
VFR = "VFR",
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--- FLIGHTPLAN class version.
|
|
||||||
-- @field #string version
|
|
||||||
FLIGHTPLAN.version="0.0.1"
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-- ToDo list
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
-- TODO: How to connect SID, STAR, ENROUTE, TRANSITION, APPROACH. Typical flightplan SID --> ENROUTE --> STAR --> APPROACH
|
|
||||||
-- TODO: Add approach.
|
|
||||||
-- DONE: How to handle the FLIGHTGROUP:_LandAtAirBase
|
|
||||||
-- TODO: Do we always need a holding pattern? https://www.faa.gov/air_traffic/publications/atpubs/aip_html/part2_enr_section_1.5.html#:~:text=If%20no%20holding%20pattern%20is,than%20that%20desired%20by%20ATC.
|
|
||||||
-- DOEN: Read from MSFS file.
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-- Constructor
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
--- Create a new FLIGHTPLAN instance.
|
|
||||||
-- @param #FLIGHTPLAN self
|
|
||||||
-- @param #string Name Name of this flight plan.
|
|
||||||
-- @return #FLIGHTPLAN self
|
|
||||||
function FLIGHTPLAN:New(Name)
|
|
||||||
|
|
||||||
-- Inherit everything from BASE class.
|
|
||||||
self=BASE:Inherit(self, PATHLINE:New(Name)) -- #FLIGHTPLAN
|
|
||||||
|
|
||||||
-- Set alias.
|
|
||||||
self.alias=tostring(Name)
|
|
||||||
|
|
||||||
-- Set some string id for output to DCS.log file.
|
|
||||||
self.lid=string.format("FLIGHTPLAN %s | ", self.alias)
|
|
||||||
|
|
||||||
--self.pathline=PATHLINE:New(Name)
|
|
||||||
|
|
||||||
-- Debug info.
|
|
||||||
self:I(self.lid..string.format("Created FLIGHTPLAN!"))
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Create a new FLIGHTPLAN instance from another FLIGHTPLAN acting as blue print.
|
|
||||||
-- The newly created flight plan is deep copied from the given one.
|
|
||||||
-- @param #FLIGHTPLAN self
|
|
||||||
-- @param #FLIGHTPLAN FlightPlan Blue print of the flight plan to copy.
|
|
||||||
-- @return #FLIGHTPLAN self
|
|
||||||
function FLIGHTPLAN:NewFromFlightPlan(FlightPlan)
|
|
||||||
self=UTILS.DeepCopy(FlightPlan)
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
--- Create a new FLIGHTPLAN instance from a given file.
|
|
||||||
-- Currently, the file has to be an MSFS 2020 .pln file as, *e.g.*, exported from [Navigraph](https://navigraph.com/).
|
|
||||||
--
|
|
||||||
-- **Note** that the flight plan does only cover the departure, enroute and arrival portions but **not the approach** part!
|
|
||||||
-- @param #FLIGHTPLAN self
|
|
||||||
-- @param #string FileName Full path to file.
|
|
||||||
-- @return #FLIGHTPLAN self
|
|
||||||
function FLIGHTPLAN:NewFromFile(FileName)
|
|
||||||
|
|
||||||
if UTILS.FileExists(FileName) then
|
|
||||||
|
|
||||||
self=FLIGHTPLAN._ReadFileMSFS(FileName)
|
|
||||||
|
|
||||||
else
|
|
||||||
error(string.format("ERROR: File not found! File name=%s", tostring(FileName)))
|
|
||||||
end
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-- User Functions
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
--- Add navigation fix to the flight plan.
|
|
||||||
-- @param #FLIGHTPLAN self
|
|
||||||
-- @param Navigation.Point#NAVPOINT NavFix The nav fix.
|
|
||||||
-- @return #FLIGHTPLAN self
|
|
||||||
function FLIGHTPLAN:AddNavFix(NavFix)
|
|
||||||
|
|
||||||
table.insert(self.fixes, NavFix)
|
|
||||||
|
|
||||||
local point=self:AddPointFromVec3(NavFix.vector:GetVec3(true))
|
|
||||||
|
|
||||||
point.navpoint=NavFix
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
--- Set departure airbase.
|
|
||||||
-- @param #FLIGHTPLAN self
|
|
||||||
-- @param #string AirbaseName Name of the airbase or AIRBASE object.
|
|
||||||
-- @return #FLIGHTPLAN self
|
|
||||||
function FLIGHTPLAN:SetDepartureAirbase(AirbaseName)
|
|
||||||
|
|
||||||
self.departureAirbase=AIRBASE:FindByName(AirbaseName)
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Set destination airbase.
|
|
||||||
-- @param #FLIGHTPLAN self
|
|
||||||
-- @param #string AirbaseName Name of the airbase or AIRBASE object.
|
|
||||||
-- @return #FLIGHTPLAN self
|
|
||||||
function FLIGHTPLAN:SetDestinationAirbase(AirbaseName)
|
|
||||||
|
|
||||||
self.destinationAirbase=AIRBASE:FindByName(AirbaseName)
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
--- Set cruise altitude.
|
|
||||||
-- @param #FLIGHTPLAN self
|
|
||||||
-- @param #number AltMin Minimum altitude in feet MSL.
|
|
||||||
-- @param #number AltMax Maximum altitude in feet MSL. Default is `AltMin`.
|
|
||||||
-- @return #FLIGHTPLAN self
|
|
||||||
function FLIGHTPLAN:SetCruiseAltitude(AltMin, AltMax)
|
|
||||||
|
|
||||||
self.altitudeCruiseMin=AltMin
|
|
||||||
self.altitudeCruiseMax=AltMax or self.altitudeCruiseMin
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Set cruise speed.
|
|
||||||
-- @param #FLIGHTPLAN self
|
|
||||||
-- @param #number SpeedMin Minimum speed in knots.
|
|
||||||
-- @param #number SpeedMax Maximum speed in knots. Default is `SpeedMin`.
|
|
||||||
-- @return #FLIGHTPLAN self
|
|
||||||
function FLIGHTPLAN:SetCruiseSpeed(SpeedMin, SpeedMax)
|
|
||||||
|
|
||||||
self.speedCruiseMin=SpeedMin
|
|
||||||
self.speedCruiseMax=SpeedMax or self.speedCruiseMin
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
--- Get the name of this flight plan.
|
|
||||||
-- @param #FLIGHTPLAN self
|
|
||||||
-- @return #string The name.
|
|
||||||
function FLIGHTPLAN:GetName()
|
|
||||||
return self.alias
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
--- Get cruise altitude. This returns a random altitude between the set min/max cruise altitudes.
|
|
||||||
-- @param #FLIGHTPLAN self
|
|
||||||
-- @return #number Cruise altitude in feet MSL.
|
|
||||||
function FLIGHTPLAN:GetCruiseAltitude()
|
|
||||||
|
|
||||||
local alt=10000
|
|
||||||
if self.altitudeCruiseMin and self.altitudeCruiseMax then
|
|
||||||
alt=math.random(self.altitudeCruiseMin, self.altitudeCruiseMax)
|
|
||||||
elseif self.altitudeCruiseMin then
|
|
||||||
alt=self.altitudeCruiseMin
|
|
||||||
elseif self.altitudeCruiseMax then
|
|
||||||
alt=self.altitudeCruiseMax
|
|
||||||
end
|
|
||||||
|
|
||||||
return alt
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Get cruise speed. This returns a random speed between the set min/max cruise speeds.
|
|
||||||
-- @param #FLIGHTPLAN self
|
|
||||||
-- @return #number Cruise speed in knots.
|
|
||||||
function FLIGHTPLAN:GetCruiseSpeed()
|
|
||||||
|
|
||||||
local speed=250
|
|
||||||
|
|
||||||
if self.speedCruiseMin and self.speedCruiseMax then
|
|
||||||
speed=math.random(self.speedCruiseMin, self.speedCruiseMax)
|
|
||||||
elseif self.speedCruiseMin then
|
|
||||||
speed=self.speedCruiseMin
|
|
||||||
elseif self.altitudeCruiseMax then
|
|
||||||
speed=self.speedCruiseMax
|
|
||||||
end
|
|
||||||
|
|
||||||
return speed
|
|
||||||
end
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-- Private Functions
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
--- Read flight plan from a given MSFS 2020 .plt file.
|
|
||||||
-- @param #string FileName Name of the file.
|
|
||||||
-- @return #FLIGHTPLAN The flight plan.
|
|
||||||
function FLIGHTPLAN._ReadFileMSFS(FileName)
|
|
||||||
|
|
||||||
local function readfile(filename)
|
|
||||||
|
|
||||||
local lines = {}
|
|
||||||
|
|
||||||
-- Open file in read binary mode.
|
|
||||||
local file=assert(io.open(filename, "rb"), string.format("File not found! File name = %s", tostring(filename)))
|
|
||||||
|
|
||||||
for line in file:lines() do
|
|
||||||
lines[#lines+1] = line
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Close file.
|
|
||||||
file:close()
|
|
||||||
|
|
||||||
-- Return data
|
|
||||||
return lines
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
--- This function returns an XML element, i.e. the string between <...> and </...>.
|
|
||||||
local function getXMLelement(line)
|
|
||||||
local element=string.match(line, ">(.+)<")
|
|
||||||
return element
|
|
||||||
end
|
|
||||||
|
|
||||||
--- This function returns Latitude and Longitude
|
|
||||||
local function getLatLong(line)
|
|
||||||
local latlong=getXMLelement(line)
|
|
||||||
-- The format is "N41° 38' 20.00",E41° 33' 19.00",+000000.00" so we still need to process that.
|
|
||||||
local lat,long=string.match(latlong, "(.+),(.+),")
|
|
||||||
return lat,long
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Read data from file.
|
|
||||||
local data=readfile(FileName)
|
|
||||||
|
|
||||||
local flightplan={}
|
|
||||||
local waypoints={}
|
|
||||||
local wp=nil
|
|
||||||
|
|
||||||
local gotwaypoint=false
|
|
||||||
for i,line in pairs(data) do
|
|
||||||
|
|
||||||
|
|
||||||
--print(line)
|
|
||||||
|
|
||||||
-- Title
|
|
||||||
if string.find(line, "<Title>") then
|
|
||||||
flightplan.title=getXMLelement(line)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Departure ICAO
|
|
||||||
if string.find(line, "<DepartureID>") then
|
|
||||||
flightplan.departureICAO=getXMLelement(line)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Destination ICAO
|
|
||||||
if string.find(line, "<DestinationID>") then
|
|
||||||
flightplan.destinationICAO=getXMLelement(line)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- FPType
|
|
||||||
if string.find(line, "<FPType>") then
|
|
||||||
flightplan.plantype=getXMLelement(line)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Route type
|
|
||||||
if string.find(line, "<RouteType>") then
|
|
||||||
flightplan.routetype=getXMLelement(line)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Cruise alt in feet
|
|
||||||
if string.find(line, "<CruisingAlt>") then
|
|
||||||
flightplan.altCruise=getXMLelement(line)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Departure LLA
|
|
||||||
if string.find(line, "<DepartureLLA>") then
|
|
||||||
local lat,long=getLatLong(line)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Destination LLA
|
|
||||||
if string.find(line, "<DestinationLLA>") then
|
|
||||||
local lat,long=getLatLong(line)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Departure Name
|
|
||||||
if string.find(line, "<DepartureName>") then
|
|
||||||
local DepartureName=getXMLelement(line)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- DestinationName
|
|
||||||
if string.find(line, "<DestinationName>") then
|
|
||||||
local DestinationName=getXMLelement(line)
|
|
||||||
end
|
|
||||||
|
|
||||||
---
|
|
||||||
-- Waypoint stuff
|
|
||||||
---
|
|
||||||
|
|
||||||
-- New waypoint starts.
|
|
||||||
if string.find(line, "ATCWaypoint id") then
|
|
||||||
|
|
||||||
--Get string inside quotes " and ".
|
|
||||||
local wpid=string.match(line, [["(.+)"]])
|
|
||||||
|
|
||||||
-- Create a new wp table.
|
|
||||||
wp={}
|
|
||||||
|
|
||||||
-- Set waypoint name.
|
|
||||||
wp.name=wpid
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Waypoint info ends.
|
|
||||||
if string.find(line, "</ATCWaypoint>") then
|
|
||||||
-- This is the end of the waypoint.
|
|
||||||
|
|
||||||
-- Add info to waypoints table.
|
|
||||||
table.insert(waypoints, wp)
|
|
||||||
|
|
||||||
-- Set waypoint to nil. We create an empty table if the next wp starts.
|
|
||||||
wp=nil
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Waypoint type (Airport, Intersection, NDB, VORTAC)
|
|
||||||
if string.find(line, "<ATCWaypointType>") then
|
|
||||||
local wptype=getXMLelement(line)
|
|
||||||
wp.type=wptype
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Waypoint position.
|
|
||||||
if string.find(line, "<WorldPosition>") then
|
|
||||||
wp.lat, wp.long=getLatLong(line)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Runway should exist for initial and final WP if it is an airport.
|
|
||||||
if string.find(line, "RunwayNumberFP") then
|
|
||||||
wp.runway=getXMLelement(line)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Runway designator: LEFT, RIGHT, CENTER
|
|
||||||
if string.find(line, "RunwayDesignatorFP") then
|
|
||||||
wp.runwayDesignator=getXMLelement(line)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Segment is Departure
|
|
||||||
if string.find(line, "<DepartureFP>") then
|
|
||||||
wp.segment="Departure"
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Segment is Arrival
|
|
||||||
if string.find(line, "<ArrivalFP>") then
|
|
||||||
wp.segment="Arrival"
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Segment is Enroute
|
|
||||||
if string.find(line, "<ATCAirway>") then
|
|
||||||
wp.segment="Enroute"
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Approach type: VORDME, LOCALIZER
|
|
||||||
if string.find(line, "ApproachTypeFP") then
|
|
||||||
flightplan.approachtype=getXMLelement(line)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Approach type suffic: Z
|
|
||||||
if string.find(line, "SuffixFP") then
|
|
||||||
local SuffixFP=getXMLelement(line)
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
for key, value in pairs(flightplan) do
|
|
||||||
env.info(string.format("Flightplan %s=%s", key, tostring(value)))
|
|
||||||
end
|
|
||||||
|
|
||||||
env.info(string.format("Number of waypoints=%d", #waypoints))
|
|
||||||
for i,wp in pairs(waypoints) do
|
|
||||||
env.info(string.format("Waypoint name=%s type=%s segment=%s runway=%s lat=%s long=%s", wp.name, wp.type, tostring(wp.segment), tostring(wp.runway)..tostring(wp.runwayDesignator or ""), wp.lat, wp.long))
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Create a new flightplan.
|
|
||||||
local fp=FLIGHTPLAN:New(flightplan.title)
|
|
||||||
|
|
||||||
-- Set cruise altitude.
|
|
||||||
fp:SetCruiseAltitude(flightplan.altCruise)
|
|
||||||
|
|
||||||
-- Set departure and destination airports.
|
|
||||||
fp:SetDepartureAirbase(flightplan.departureICAO)
|
|
||||||
fp:SetDestinationAirbase(flightplan.destinationICAO)
|
|
||||||
|
|
||||||
--TODO: Remove first and last waypoint if they are identical to the departure/destination airport!
|
|
||||||
|
|
||||||
for i,wp in pairs(waypoints) do
|
|
||||||
|
|
||||||
-- Create a navpoint.
|
|
||||||
local navpoint=NAVPOINT:NewFromLLDMS(wp.name, wp.type, wp.lat, wp.long)
|
|
||||||
|
|
||||||
navpoint:SetAltMin(flightplan.altCruise)
|
|
||||||
|
|
||||||
-- Add point to flightplan.
|
|
||||||
-- TODO: section departure, enroute, arrival.
|
|
||||||
fp:AddNavFix(navpoint)
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return fp
|
|
||||||
end
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
@@ -1,587 +0,0 @@
|
|||||||
--- **NAVIGATION** - Navigation Airspace Points, Fixes and Aids.
|
|
||||||
--
|
|
||||||
-- **Main Features:**
|
|
||||||
--
|
|
||||||
-- * Stuff
|
|
||||||
-- * More Stuff
|
|
||||||
--
|
|
||||||
-- ===
|
|
||||||
--
|
|
||||||
-- ## Example Missions:
|
|
||||||
--
|
|
||||||
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/Navigation%20-%20NavFix).
|
|
||||||
--
|
|
||||||
-- ===
|
|
||||||
--
|
|
||||||
-- ### Author: **funkyfranky**
|
|
||||||
--
|
|
||||||
-- ===
|
|
||||||
-- @module Navigation.Point
|
|
||||||
-- @image NAVIGATION_Point.png
|
|
||||||
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
--- NAVFIX class.
|
|
||||||
-- @type NAVFIX
|
|
||||||
--
|
|
||||||
-- @field #string ClassName Name of the class.
|
|
||||||
-- @field #number verbose Verbosity of output.
|
|
||||||
-- @field #string name Name of the point.
|
|
||||||
-- @field #string typePoint Type of the point, *e.g. "Intersection", "VOR", "Airport".
|
|
||||||
-- @field Core.Vector#VECTOR vector Position vector of the fix.
|
|
||||||
-- @field Wrapper.Marker#MARKER marker Marker on F10 map.
|
|
||||||
-- @field #number altMin Minimum altitude in meters.
|
|
||||||
-- @field #number altMax Maximum altitude in meters.
|
|
||||||
-- @field #number speedMin Minimum speed in knots.
|
|
||||||
-- @field #number speedMax Maximum speed in knots.
|
|
||||||
--
|
|
||||||
-- @field #boolean isCompulsory Is this a compulsory fix.
|
|
||||||
-- @field #boolean isFlyover Is this a flyover fix (`true`) or turning point otherwise.
|
|
||||||
-- @field #boolean isFAF Is this a final approach fix.
|
|
||||||
-- @field #boolean isIAF Is this an initial approach fix.
|
|
||||||
-- @field #boolean isIF Is this an initial fix.
|
|
||||||
-- @field #boolean isMAF Is this an initial fix.
|
|
||||||
--
|
|
||||||
-- @extends Core.Base#BASE
|
|
||||||
|
|
||||||
--- *A fleet of British ships at war are the best negotiators.* -- Horatio Nelson
|
|
||||||
--
|
|
||||||
-- ===
|
|
||||||
--
|
|
||||||
-- # The NAVFIX Concept
|
|
||||||
--
|
|
||||||
-- The NAVFIX class has a great concept!
|
|
||||||
--
|
|
||||||
-- A NAVFIX describes a geo position and can, *e.g.*, be part of a FLIGHTPLAN. It has a unique name and is of a certain type, *e.g.* "Intersection", "VOR", "Airbase" etc.
|
|
||||||
-- It can also have further properties as min/max altitudes and speeds that aircraft need to obey when they pass the point.
|
|
||||||
--
|
|
||||||
-- # Basic Setup
|
|
||||||
--
|
|
||||||
-- A new `NAVFIX` object can be created with the @{#NAVFIX.New}() function.
|
|
||||||
--
|
|
||||||
-- myNavPoint=NAVFIX:New()
|
|
||||||
-- myTemplate:SetXYZ(X, Y, Z)
|
|
||||||
--
|
|
||||||
-- This is how it works.
|
|
||||||
--
|
|
||||||
-- @field #NAVFIX
|
|
||||||
NAVFIX = {
|
|
||||||
ClassName = "NAVFIX",
|
|
||||||
verbose = 0,
|
|
||||||
}
|
|
||||||
|
|
||||||
--- Type of point.
|
|
||||||
-- @type NAVFIX.Type
|
|
||||||
-- @field #string POINT Waypoint.
|
|
||||||
-- @field #string INTERSECTION Intersection of airway.
|
|
||||||
-- @field #string AIRPORT Airport.
|
|
||||||
-- @field #string VOR Very High Frequency Omnidirectional Range Station.
|
|
||||||
-- @field #string DME Distance Measuring Equipment.
|
|
||||||
-- @field #string NDB Non-Directional Beacon.
|
|
||||||
-- @field #string VORDME Combined VHF omnidirectional range (VOR) with a distance-measuring equipment (DME).
|
|
||||||
-- @field #string LOC Localizer.
|
|
||||||
-- @field #string ILS Instrument Landing System.
|
|
||||||
-- @field #string TACAN TACtical Air Navigation System (TACAN).
|
|
||||||
NAVFIX.Type={
|
|
||||||
POINT="Point",
|
|
||||||
INTERSECTION="Intersection",
|
|
||||||
AIRPORT="Airport",
|
|
||||||
NDB="NDB",
|
|
||||||
VOR="VOR",
|
|
||||||
DME="DME",
|
|
||||||
VORDME="VOR/DME",
|
|
||||||
LOC="Localizer",
|
|
||||||
ILS="ILS",
|
|
||||||
TACAN="TACAN"
|
|
||||||
}
|
|
||||||
|
|
||||||
--- NAVFIX class version.
|
|
||||||
-- @field #string version
|
|
||||||
NAVFIX.version="0.0.1"
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-- ToDo list
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
-- TODO: A lot...
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-- Constructor(s)
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
--- Create a new NAVFIX class instance from a given VECTOR.
|
|
||||||
-- @param #NAVFIX self
|
|
||||||
-- @param #string Name Name/ident of the point. Should be unique!
|
|
||||||
-- @param #string Type Type of the point. Default `NAVFIX.Type.POINT`.
|
|
||||||
-- @param Core.Vector#VECTOR Vector Position vector of the navpoint.
|
|
||||||
-- @return #NAVFIX self
|
|
||||||
function NAVFIX:NewFromVector(Name, Type, Vector)
|
|
||||||
|
|
||||||
-- Inherit everything from BASE class.
|
|
||||||
self=BASE:Inherit(self, BASE:New()) -- #NAVFIX
|
|
||||||
|
|
||||||
-- Vector of point.
|
|
||||||
self.vector=Vector
|
|
||||||
|
|
||||||
-- Name of point.
|
|
||||||
self.name=Name
|
|
||||||
|
|
||||||
-- Type of the point.
|
|
||||||
self.typePoint=Type or NAVFIX.Type.POINT
|
|
||||||
|
|
||||||
local coord=COORDINATE:NewFromVec3(self.vector)
|
|
||||||
|
|
||||||
-- Marker on F10.
|
|
||||||
self.marker=MARKER:New(coord, self:_GetMarkerText())
|
|
||||||
|
|
||||||
-- Log ID string.
|
|
||||||
self.lid=string.format("NAVFIX %s [%s] | ", tostring(self.name), tostring(self.typePoint))
|
|
||||||
|
|
||||||
-- Debug info.
|
|
||||||
self:I(self.lid..string.format("Created NAVFIX"))
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
--- Create a new NAVFIX class instance from a given COORDINATE.
|
|
||||||
-- @param #NAVFIX self
|
|
||||||
-- @param #string Name Name of the fix. Should be unique!
|
|
||||||
-- @param #string Type Type of the point. Default `NAVFIX.Type.POINT`.
|
|
||||||
-- @param Core.Point#COORDINATE Coordinate Coordinate of the point.
|
|
||||||
-- @return #NAVFIX self
|
|
||||||
function NAVFIX:NewFromCoordinate(Name, Type, Coordinate)
|
|
||||||
|
|
||||||
-- Create a VECTOR from the coordinate.
|
|
||||||
local Vector=VECTOR:NewFromVec(Coordinate)
|
|
||||||
|
|
||||||
-- Create NAVFIX.
|
|
||||||
self=NAVFIX:NewFromVector(Name, Type, Vector)
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
--- Create a new NAVFIX instance from given latitude and longitude in degrees, minutes and seconds (DMS).
|
|
||||||
-- @param #NAVFIX self
|
|
||||||
-- @param #string Name Name of the fix. Should be unique!
|
|
||||||
-- @param #string Type Type of the point. Default `NAVFIX.Type.POINT`.
|
|
||||||
-- @param #string Latitude Latitude in DMS as string.
|
|
||||||
-- @param #string Longitude Longitude in DMS as string.
|
|
||||||
-- @return #NAVFIX self
|
|
||||||
function NAVFIX:NewFromLLDMS(Name, Type, Latitude, Longitude)
|
|
||||||
|
|
||||||
-- Create a VECTOR from the coordinate.
|
|
||||||
local Vector=VECTOR:NewFromLLDMS(Latitude, Longitude)
|
|
||||||
|
|
||||||
-- Create NAVFIX.
|
|
||||||
self=NAVFIX:NewFromVector(Name, Type, Vector)
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Create a new NAVFIX instance from given latitude and longitude in decimal degrees (DD).
|
|
||||||
-- @param #NAVFIX self
|
|
||||||
-- @param #string Name Name of the fix. Should be unique!
|
|
||||||
-- @param #string Type Type of the point. Default `NAVFIX.Type.POINT`.
|
|
||||||
-- @param #number Latitude Latitude in DD.
|
|
||||||
-- @param #number Longitude Longitude in DD.
|
|
||||||
-- @return #NAVFIX self
|
|
||||||
function NAVFIX:NewFromLLDD(Name, Type, Latitude, Longitude)
|
|
||||||
|
|
||||||
-- Create a VECTOR from the coordinate.
|
|
||||||
local Vector=VECTOR:NewFromLLDD(Latitude, Longitude)
|
|
||||||
|
|
||||||
-- Create NAVFIX.
|
|
||||||
self=NAVFIX:NewFromVector(Name, Type, Vector)
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
--- Create a new NAVFIX class instance relative to a given other NAVFIX.
|
|
||||||
-- You have to specify the distance and bearing from the new point to the given point. *E.g.*, for a distance of 5 NM and a bearing of 090° (West), the
|
|
||||||
-- new nav point is created 5 NM East of the given nav point. The reason is that this corresponts to convention used in most maps.
|
|
||||||
-- You can, however, use the `Reciprocal` switch to create the new point in the direction you specify.
|
|
||||||
-- @param #NAVFIX self
|
|
||||||
-- @param #string Name Name of the fix. Should be unique!
|
|
||||||
-- @param #string Type Type of navfix.
|
|
||||||
-- @param #NAVFIX NavFix The given/existing navigation fix relative to which the new fix is created.
|
|
||||||
-- @param #number Distance Distance from the given to the new point in nautical miles.
|
|
||||||
-- @param #number Bearing Bearing [Deg] from the new point to the given one.
|
|
||||||
-- @param #boolean Reciprocal If `true` the reciprocal `Bearing` is taken so it specifies the direction from the given point to the new one.
|
|
||||||
-- @return #NAVFIX self
|
|
||||||
function NAVFIX:NewFromNavFix(Name, Type, NavFix, Distance, Bearing, Reciprocal)
|
|
||||||
|
|
||||||
-- Convert magnetic to true bearing by adding magnetic declination, e.g. mag. bearing 10°M ==> true bearing 16°M (for 6° variation on Caucasus map)
|
|
||||||
Bearing=Bearing+UTILS.GetMagneticDeclination()
|
|
||||||
|
|
||||||
if Reciprocal then
|
|
||||||
Bearing=Bearing-180
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Translate.
|
|
||||||
local Vector=NavFix.vector:Translate(UTILS.NMToMeters(Distance), Bearing, true)
|
|
||||||
|
|
||||||
self=NAVFIX:NewFromVector(Name, Type, Vector)
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-- User Functions
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
--- Set whether this is the intermediate fix (IF).
|
|
||||||
-- @param #NAVFIX self
|
|
||||||
-- @return #NAVFIX self
|
|
||||||
function NAVFIX:SetIntermediateFix(IntermediateFix)
|
|
||||||
self.isIF=IntermediateFix
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Set whether this is an initial approach fix (IAF).
|
|
||||||
-- The IAF is the point where the initial approach segment of an instrument approach begins.
|
|
||||||
-- It is usually a designated intersection, VHF omidirectional range (VOR) non-directional beacon (NDB)
|
|
||||||
-- or distance measuring equipment (DME) fix.
|
|
||||||
-- The IAF may be collocated with the intermediate fix (IF) of the instrument apprach an in such case they designate the
|
|
||||||
-- beginning of the intermediate segment of the approach. When the IAF and the IF are combined, there is no inital approach segment.
|
|
||||||
-- @param #NAVFIX self
|
|
||||||
-- @param #boolean IntermediateFix If `true`, this is an intermediate fix.
|
|
||||||
-- @return #NAVFIX self
|
|
||||||
function NAVFIX:SetInitialApproachFix(IntermediateFix)
|
|
||||||
self.isIAF=IntermediateFix
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
--- Set whether this is the final approach fix (FAF).
|
|
||||||
-- @param #NAVFIX self
|
|
||||||
-- @param #boolean FinalApproachFix If `true`, this is a final approach fix.
|
|
||||||
-- @return #NAVFIX self
|
|
||||||
function NAVFIX:SetFinalApproachFix(FinalApproachFix)
|
|
||||||
self.isFAF=FinalApproachFix
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Set whether this is the final approach fix (FAF).
|
|
||||||
-- @param #NAVFIX self
|
|
||||||
-- @param #boolean FinalApproachFix If `true`, this is a final approach fix.
|
|
||||||
-- @return #NAVFIX self
|
|
||||||
function NAVFIX:SetMissedApproachFix(MissedApproachFix)
|
|
||||||
self.isMAF=MissedApproachFix
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
--- Set minimum altitude.
|
|
||||||
-- @param #NAVFIX self
|
|
||||||
-- @param #number Altitude Min altitude in feet.
|
|
||||||
-- @return #NAVFIX self
|
|
||||||
function NAVFIX:SetAltMin(Altitude)
|
|
||||||
|
|
||||||
self.altMin=Altitude
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Set maximum altitude.
|
|
||||||
-- @param #NAVFIX self
|
|
||||||
-- @param #number Altitude Max altitude in feet.
|
|
||||||
-- @return #NAVFIX self
|
|
||||||
function NAVFIX:SetAltMax(Altitude)
|
|
||||||
|
|
||||||
self.altMax=Altitude
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Set mandatory altitude (min alt = max alt).
|
|
||||||
-- @param #NAVFIX self
|
|
||||||
-- @param #number Altitude Altitude in feet.
|
|
||||||
-- @return #NAVFIX self
|
|
||||||
function NAVFIX:SetAltMandatory(Altitude)
|
|
||||||
|
|
||||||
self.altMin=Altitude
|
|
||||||
self.altMax=Altitude
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Set minimum allowed speed at this fix.
|
|
||||||
-- @param #NAVFIX self
|
|
||||||
-- @param #number Speed Min speed in knots.
|
|
||||||
-- @return #NAVFIX self
|
|
||||||
function NAVFIX:SetSpeedMin(Speed)
|
|
||||||
|
|
||||||
self.speedMin=Speed
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Set maximum allowed speed at this fix.
|
|
||||||
-- @param #NAVFIX self
|
|
||||||
-- @param #number Speed Max speed in knots.
|
|
||||||
-- @return #NAVFIX self
|
|
||||||
function NAVFIX:SetSpeedMax(Speed)
|
|
||||||
|
|
||||||
self.speedMax=Speed
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Set mandatory speed (min speed = max speed) at this fix.
|
|
||||||
-- @param #NAVFIX self
|
|
||||||
-- @param #number Speed Mandatory speed in knots.
|
|
||||||
-- @return #NAVFIX self
|
|
||||||
function NAVFIX:SetSpeedMandatory(Speed)
|
|
||||||
|
|
||||||
self.speedMin=Speed
|
|
||||||
self.speedMax=Speed
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
--- Set whether this fix is compulsory.
|
|
||||||
-- @param #NAVFIX self
|
|
||||||
-- @param #boolean Compulsory If `true`, this is a compusory fix. If `false` or nil, it is non-compulsory.
|
|
||||||
-- @return #NAVFIX self
|
|
||||||
function NAVFIX:SetCompulsory(Compulsory)
|
|
||||||
self.isCompulsory=Compulsory
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Set whether this is a fly-over fix fix.
|
|
||||||
-- @param #NAVFIX self
|
|
||||||
-- @param #boolean FlyOver If `true`, this is a fly over fix. If `false` or nil, it is not.
|
|
||||||
-- @return #NAVFIX self
|
|
||||||
function NAVFIX:SetFlyOver(FlyOver)
|
|
||||||
self.isFlyover=FlyOver
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
--- Get the altitude in feet MSL. If min and max altitudes are set, it will return a random altitude between min and max.
|
|
||||||
-- @param #NAVFIX self
|
|
||||||
-- @return #number Altitude in feet MSL. Can be `nil`, if neither min nor max altitudes have beeen set.
|
|
||||||
function NAVFIX:GetAltitude()
|
|
||||||
|
|
||||||
local alt=nil
|
|
||||||
if self.altMin and self.altMax and self.altMin~=self.altMax then
|
|
||||||
alt=math.random(self.altMin, self.altMax)
|
|
||||||
elseif self.altMin then
|
|
||||||
alt=self.altMin
|
|
||||||
elseif self.altMax then
|
|
||||||
alt=self.altMax
|
|
||||||
end
|
|
||||||
|
|
||||||
return alt
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
--- Get the speed. If min and max speeds are set, it will return a random speed between min and max.
|
|
||||||
-- @param #NAVFIX self
|
|
||||||
-- @return #number Speed in knots. Can be `nil`, if neither min nor max speeds have beeen set.
|
|
||||||
function NAVFIX:GetSpeed()
|
|
||||||
|
|
||||||
local speed=nil
|
|
||||||
if self.speedMin and self.speedMax and self.speedMin~=self.speedMax then
|
|
||||||
speed=math.random(self.speedMin, self.speedMax)
|
|
||||||
elseif self.speedMin then
|
|
||||||
speed=self.speedMin
|
|
||||||
elseif self.speedMax then
|
|
||||||
speed=self.speedMax
|
|
||||||
end
|
|
||||||
|
|
||||||
return speed
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--- Add marker the NAVFIX on the F10 map.
|
|
||||||
-- @param #NAVFIX self
|
|
||||||
-- @return #NAVFIX self
|
|
||||||
function NAVFIX:MarkerShow()
|
|
||||||
|
|
||||||
self.marker:ToAll()
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Remove marker of the NAVFIX from the F10 map.
|
|
||||||
-- @param #NAVFIX self
|
|
||||||
-- @return #NAVFIX self
|
|
||||||
function NAVFIX:MarkerRemove()
|
|
||||||
|
|
||||||
self.marker:Remove()
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-- Private Functions
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
--- Get text displayed in the F10 marker.
|
|
||||||
-- @param #NAVFIX self
|
|
||||||
-- @return #string Marker text.
|
|
||||||
function NAVFIX:_GetMarkerText()
|
|
||||||
|
|
||||||
local altmin=self.altMin and tostring(self.altMin) or ""
|
|
||||||
local altmax=self.altMax and tostring(self.altMax) or ""
|
|
||||||
local speedmin=self.speedMin and tostring(self.speedMin) or ""
|
|
||||||
local speedmax=self.speedMax and tostring(self.speedMax) or ""
|
|
||||||
|
|
||||||
|
|
||||||
local text=string.format("NAVFIX %s", self.name)
|
|
||||||
if self.isIAF then
|
|
||||||
text=text..string.format(" (IAF)")
|
|
||||||
end
|
|
||||||
if self.isIF then
|
|
||||||
text=text..string.format(" (IF)")
|
|
||||||
end
|
|
||||||
text=text..string.format("\nAltitude [ft]: %s - %s", altmin, altmax)
|
|
||||||
text=text..string.format("\nSpeed [knots]: %s - %s", speedmin, speedmax)
|
|
||||||
text=text..string.format("\nCompulsory: %s", tostring(self.isCompulsory))
|
|
||||||
text=text..string.format("\nFly Over: %s", tostring(self.isFlyover))
|
|
||||||
|
|
||||||
return text
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
--- NAVAID class.
|
|
||||||
-- @type NAVAID
|
|
||||||
-- @field #string ClassName Name of the class.
|
|
||||||
-- @field #number verbose Verbosity of output.
|
|
||||||
-- @extends Navigation.Point#NAVFIX
|
|
||||||
|
|
||||||
--- *A fleet of British ships at war are the best negotiators.* -- Horatio Nelson
|
|
||||||
--
|
|
||||||
-- ===
|
|
||||||
--
|
|
||||||
-- # The NAVAID Concept
|
|
||||||
--
|
|
||||||
-- A NAVAID consists of one or multiple FLOTILLAs. These flotillas "live" in a WAREHOUSE that has a phyiscal struction (STATIC or UNIT) and can be captured or destroyed.
|
|
||||||
--
|
|
||||||
-- # Basic Setup
|
|
||||||
--
|
|
||||||
-- A new `NAVAID` object can be created with the @{#NAVAID.New}(`WarehouseName`, `FleetName`) function, where `WarehouseName` is the name of the static or unit object hosting the fleet
|
|
||||||
-- and `FleetName` is the name you want to give the fleet. This must be *unique*!
|
|
||||||
--
|
|
||||||
-- myFleet=NAVAID:New("myWarehouseName", "1st Fleet")
|
|
||||||
-- myFleet:SetPortZone(ZonePort1stFleet)
|
|
||||||
-- myFleet:Start()
|
|
||||||
--
|
|
||||||
-- A fleet needs a *port zone*, which is set via the @{#NAVAID.SetPortZone}(`PortZone`) function. This is the zone where the naval assets are spawned and return to.
|
|
||||||
--
|
|
||||||
-- Finally, the fleet needs to be started using the @{#NAVAID.Start}() function. If the fleet is not started, it will not process any requests.
|
|
||||||
--
|
|
||||||
-- @field #NAVAID
|
|
||||||
NAVAID = {
|
|
||||||
ClassName = "NAVAID",
|
|
||||||
verbose = 0,
|
|
||||||
}
|
|
||||||
|
|
||||||
--- NAVAID class version.
|
|
||||||
-- @field #string version
|
|
||||||
NAVAID.version="0.0.1"
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-- ToDo list
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
-- TODO: Add frequencies. Which unit MHz, kHz, Hz?
|
|
||||||
-- TODO: Add radial function
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-- Constructor
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
--- Create a new NAVAID class instance.
|
|
||||||
-- @param #NAVAID self
|
|
||||||
-- @param #string Name Name/ident of this navaid.
|
|
||||||
-- @param #string Type Type of the point. Default `NAVFIX.Type.POINT`.
|
|
||||||
-- @param #string ZoneName Name of the zone to scan the scenery.
|
|
||||||
-- @param #string SceneryName Name of the scenery object.
|
|
||||||
-- @return #NAVAID self
|
|
||||||
function NAVAID:NewFromScenery(Name, Type, ZoneName, SceneryName)
|
|
||||||
|
|
||||||
-- Get the zone.
|
|
||||||
local zone=ZONE:FindByName(ZoneName)
|
|
||||||
|
|
||||||
-- Get coordinate.
|
|
||||||
local Coordinate=zone:GetCoordinate()
|
|
||||||
|
|
||||||
-- Inherit everything from NAVFIX class.
|
|
||||||
self=BASE:Inherit(self, NAVFIX:NewFromCoordinate(Name, Type, Coordinate)) -- #NAVAID
|
|
||||||
|
|
||||||
-- Set zone.
|
|
||||||
self.zone=ZONE:FindByName(ZoneName)
|
|
||||||
|
|
||||||
-- Try to get the scenery object. Note not all can be found unfortunately.
|
|
||||||
if SceneryName then
|
|
||||||
self.scenery=SCENERY:FindByNameInZone(SceneryName, ZoneName)
|
|
||||||
if not self.scenery then
|
|
||||||
self:E(string.format("ERROR: Could not find scenery object %s in zone %s", SceneryName, ZoneName))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Alias.
|
|
||||||
self.alias=string.format("%s %s %s", tostring(ZoneName), tostring(SceneryName), tostring(Type))
|
|
||||||
|
|
||||||
-- Set some string id for output to DCS.log file.
|
|
||||||
self.lid=string.format("NAVAID %s | ", self.alias)
|
|
||||||
|
|
||||||
-- Debug info.
|
|
||||||
self:I(self.lid..string.format("Created NAVAID!"))
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-- User Functions
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
--- Set frequency the beacon transmits on.
|
|
||||||
-- @param #NAVAID self
|
|
||||||
-- @param #number Frequency Frequency in Hz.
|
|
||||||
-- @return #NAVAID self
|
|
||||||
function NAVAID:SetFrequency(Frequency)
|
|
||||||
|
|
||||||
self.frequency=Frequency
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Set channel of, *e.g.*, TACAN beacons.
|
|
||||||
-- @param #NAVAID self
|
|
||||||
-- @param #number Channel The channel.
|
|
||||||
-- @param #string Band The band either `"X"` (default) or `"Y"`.
|
|
||||||
-- @return #NAVAID self
|
|
||||||
function NAVAID:SetChannel(Channel, Band)
|
|
||||||
|
|
||||||
self.channel=Channel
|
|
||||||
self.band=Band or "X"
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-- Private Functions
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
-- Add private CLASS functions here.
|
|
||||||
-- No private NAVAID functions yet.
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
@@ -1,333 +0,0 @@
|
|||||||
--- **NAVIGATION** - Prodedures for Departure (*e.g.* SID), Enroute, Arrival (*e.g.* STAR) and Approach.
|
|
||||||
--
|
|
||||||
-- **Main Features:**
|
|
||||||
--
|
|
||||||
-- * Stuff
|
|
||||||
-- * More Stuff
|
|
||||||
--
|
|
||||||
-- ===
|
|
||||||
--
|
|
||||||
-- ## Example Missions:
|
|
||||||
--
|
|
||||||
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/Navigation%20-%20Template).
|
|
||||||
--
|
|
||||||
-- ===
|
|
||||||
--
|
|
||||||
-- ### Author: **funkyfranky**
|
|
||||||
--
|
|
||||||
-- ===
|
|
||||||
-- @module Navigation.Procedure
|
|
||||||
-- @image NAVIGATION_Procedure.png
|
|
||||||
|
|
||||||
|
|
||||||
--- APPROACH class.
|
|
||||||
-- @type APPROACH
|
|
||||||
-- @field #string ClassName Name of the class.
|
|
||||||
-- @field #number verbose Verbosity of output.
|
|
||||||
-- @field #string apptype Approach type (ILS, VOR, LOC).
|
|
||||||
-- @field Wrapper.Airbase#AIRBASE airbase Airbase of this approach.
|
|
||||||
-- @field Wrapper.Airbase#AIRBASE.Runway runway Runway of this approach.
|
|
||||||
-- @field Navigation.Point#NAVAID navaid Primary navigation aid.
|
|
||||||
-- @field #number wpcounter Running number counting the waypoints to generate its UID.
|
|
||||||
-- @list <#APPROACH.Waypoint> path Path of approach consisting of waypoints.
|
|
||||||
-- @extends Core.Base#BASE
|
|
||||||
|
|
||||||
--- *A fleet of British ships at war are the best negotiators.* -- Horatio Nelson
|
|
||||||
--
|
|
||||||
-- ===
|
|
||||||
--
|
|
||||||
-- # The APPROACH Concept
|
|
||||||
--
|
|
||||||
-- A typical approach has (up to) four segments. It starts with the initial approach segment, followed by the intermediate approach segment, followed
|
|
||||||
-- by the final approach segment. In case something goes wrong during the final approach, the missed approach segment kicks in.
|
|
||||||
--
|
|
||||||
-- The initial approach segment starts at the initial approach fix (IAF). The segment can contain multiple other fixes, that need to be passed.
|
|
||||||
-- Note, that an approach procedure can have more than one intitial approach segment and IAF.
|
|
||||||
--
|
|
||||||
-- The intermediate approach segment starts at the intermediate fix (IF). The intermediate approach segment blends the initial approach segment into the final approach segment.
|
|
||||||
-- It is the segment in which aircraft configuration, speed, and positioning adjustments are made for entry into the final approach segment.
|
|
||||||
--
|
|
||||||
--
|
|
||||||
-- https://en.wikipedia.org/wiki/Visual_approach
|
|
||||||
-- https://en.wikipedia.org/wiki/Instrument_approach
|
|
||||||
--
|
|
||||||
-- # Basic Setup
|
|
||||||
--
|
|
||||||
-- A new `APPROACH` object can be created with the @{#APPROACH.New}() function.
|
|
||||||
--
|
|
||||||
-- myTemplate=APPROACH:New()
|
|
||||||
-- myTemplate:SetXYZ(X, Y, Z)
|
|
||||||
--
|
|
||||||
-- This is how it works.
|
|
||||||
--
|
|
||||||
-- @field #APPROACH
|
|
||||||
APPROACH = {
|
|
||||||
ClassName = "APPROACH",
|
|
||||||
verbose = 0,
|
|
||||||
wpcounter = 0,
|
|
||||||
}
|
|
||||||
|
|
||||||
--- Type of approach.
|
|
||||||
-- @type APPROACH.Type
|
|
||||||
-- @field #string VFR Visual Flight Rules.
|
|
||||||
-- @field #string VOR VOR
|
|
||||||
-- @field #string NDB NDB
|
|
||||||
APPROACH.Type={
|
|
||||||
VFR="VFR",
|
|
||||||
VOR="VOR",
|
|
||||||
ILS="ILS",
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
--- Setments of approach.
|
|
||||||
-- @type APPROACH.Segment
|
|
||||||
-- @field #string INITIAL Initial approach segment.
|
|
||||||
-- @field #string INTERMEDIATE Intermediate approach segment.
|
|
||||||
-- @field #string FINAL Final approach segment.
|
|
||||||
-- @field #string MISSED Missed approach segment.
|
|
||||||
APPROACH.Segment={
|
|
||||||
INITIAL="Initial",
|
|
||||||
INTERMEDIATE="Intermediate",
|
|
||||||
FINAL="Final",
|
|
||||||
MISSED="Missed",
|
|
||||||
}
|
|
||||||
|
|
||||||
--- Waypoint of the approach.
|
|
||||||
-- @type APPROACH.Waypoint
|
|
||||||
-- @field #number uid Unique ID of the point.
|
|
||||||
-- @field #string segment The segment this point belongs to.
|
|
||||||
-- @field Navigation.Point#NAVFIX navfix The navigation fix that determines the coordinates of this point.
|
|
||||||
|
|
||||||
--- APPROACH class version.
|
|
||||||
-- @field #string version
|
|
||||||
APPROACH.version="0.0.1"
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-- ToDo list
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
-- TODO: A lot...
|
|
||||||
-- Initial approach segment --> Intermediate approach segment: starts at IF --> Final approach segment
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-- Constructor
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
--- Create a new APPROACH class instance.
|
|
||||||
-- @param #APPROACH self
|
|
||||||
-- @param #string Type Type of approach (ILS, VOR, LOC).
|
|
||||||
-- @param Wrapper.Airbase#AIRBASE Airbase The airbase or name of the airbase.
|
|
||||||
-- @param Wrapper.Airbase#AIRBASE.Runway Runway The runway or name of the runway.
|
|
||||||
-- @return #APPROACH self
|
|
||||||
function APPROACH:New(Type, Airbase, Runway)
|
|
||||||
|
|
||||||
-- Inherit everything from BASE class.
|
|
||||||
self=BASE:Inherit(self, BASE:New()) -- #APPROACH
|
|
||||||
|
|
||||||
-- Set approach type.
|
|
||||||
-- TODO: Check if this is a valid/known approach type.
|
|
||||||
self.apptype=Type
|
|
||||||
|
|
||||||
if type(Airbase)=="string" then
|
|
||||||
self.airbase=AIRBASE:FindByName(Airbase)
|
|
||||||
else
|
|
||||||
self.airbase=Airbase
|
|
||||||
end
|
|
||||||
|
|
||||||
if type(Runway)=="string" then
|
|
||||||
self.runway=self.airbase:GetRunwayByName(Runway)
|
|
||||||
else
|
|
||||||
self.runway=Runway
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Debug info.
|
|
||||||
self:I("Created new approach for airbase %s: type=%s, runway=%s", self.airbase:GetName(), self.apptype, self.runway.name)
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-- User Functions
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
--- Set the primary navigation aid used in the approach.
|
|
||||||
-- @param #APPROACH self
|
|
||||||
-- @param Navigation.Point#NAVAID NavAid The NAVAID.
|
|
||||||
-- @return #APPROACH self
|
|
||||||
function APPROACH:SetNavAid(NavAid)
|
|
||||||
|
|
||||||
self.navaid=NavAid
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Add a waypoint to the path of the approach.
|
|
||||||
-- @param #APPROACH self
|
|
||||||
-- @param Navigation.Point#NAVFIX NavFix The navigation fix.
|
|
||||||
-- @param #string Segment The approach segment this fix belongs to.
|
|
||||||
-- @return #APPROACH.Waypoint The waypoint data table.
|
|
||||||
function APPROACH:AddNavFix(NavFix, Segment)
|
|
||||||
|
|
||||||
self.wpcounter=self.wpcounter+1
|
|
||||||
|
|
||||||
local point={} --#APPROACH.Waypoint
|
|
||||||
point.uid=self.wpcounter
|
|
||||||
point.segment=Segment
|
|
||||||
point.navfix=NavFix
|
|
||||||
|
|
||||||
table.insert(self.path, point)
|
|
||||||
|
|
||||||
return point
|
|
||||||
end
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-- Private Functions
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
-- Add private functions here.
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
--- DEPARTURE class.
|
|
||||||
-- @type DEPARTURE
|
|
||||||
-- @field #string ClassName Name of the class.
|
|
||||||
-- @field #number verbose Verbosity of output.
|
|
||||||
-- @field #string apptype DEPARTURE type (ILS, VOR, LOC).
|
|
||||||
-- @field Wrapper.Airbase#AIRBASE airbase Airbase of this DEPARTURE.
|
|
||||||
-- @field Wrapper.Airbase#AIRBASE.Runway runway Runway of this DEPARTURE.
|
|
||||||
-- @field Navigation.Point#NAVAID navaid Primary navigation aid.
|
|
||||||
-- @field #number wpcounter Running number counting the waypoints to generate its UID.
|
|
||||||
-- @list <#DEPARTURE.Waypoint> path Path of DEPARTURE consisting of waypoints.
|
|
||||||
-- @extends Core.Base#BASE
|
|
||||||
|
|
||||||
--- *A fleet of British ships at war are the best negotiators.* -- Horatio Nelson
|
|
||||||
--
|
|
||||||
-- ===
|
|
||||||
--
|
|
||||||
-- # The DEPARTURE Concept
|
|
||||||
--
|
|
||||||
-- Bla.
|
|
||||||
--
|
|
||||||
-- @field #DEPARTURE
|
|
||||||
DEPARTURE = {
|
|
||||||
ClassName = "DEPARTURE",
|
|
||||||
verbose = 0,
|
|
||||||
wpcounter = 0,
|
|
||||||
}
|
|
||||||
|
|
||||||
--- Type of DEPARTURE.
|
|
||||||
-- @type DEPARTURE.Type
|
|
||||||
-- @field #string VOR VOR
|
|
||||||
-- @field #string NDB NDB
|
|
||||||
DEPARTURE.Type={
|
|
||||||
VOR="VOR",
|
|
||||||
ILS="ILS",
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
--- Setments of DEPARTURE.
|
|
||||||
-- @type DEPARTURE.Segment
|
|
||||||
-- @field #string INITIAL Initial DEPARTURE segment.
|
|
||||||
-- @field #string INTERMEDIATE Intermediate DEPARTURE segment.
|
|
||||||
-- @field #string FINAL Final DEPARTURE segment.
|
|
||||||
-- @field #string MISSED Missed DEPARTURE segment.
|
|
||||||
DEPARTURE.Segment={
|
|
||||||
INITIAL="Initial",
|
|
||||||
INTERMEDIATE="Intermediate",
|
|
||||||
FINAL="Final",
|
|
||||||
MISSED="Missed",
|
|
||||||
}
|
|
||||||
|
|
||||||
--- Waypoint of the DEPARTURE.
|
|
||||||
-- @type DEPARTURE.Waypoint
|
|
||||||
-- @field #number uid Unique ID of the point.
|
|
||||||
-- @field #string segment The segment this point belongs to.
|
|
||||||
-- @field Navigation.Point#NAVFIX navfix The navigation fix that determines the coordinates of this point.
|
|
||||||
|
|
||||||
--- DEPARTURE class version.
|
|
||||||
-- @field #string version
|
|
||||||
DEPARTURE.version="0.0.1"
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-- ToDo list
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
-- TODO: A lot...
|
|
||||||
-- Initial DEPARTURE segment --> Intermediate DEPARTURE segment: starts at IF --> Final DEPARTURE segment
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-- Constructor
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
--- Create a new DEPARTURE class instance.
|
|
||||||
-- @param #DEPARTURE self
|
|
||||||
-- @param Wrapper.Airbase#AIRBASE Airbase The airbase or name of the airbase.
|
|
||||||
-- @param Wrapper.Airbase#AIRBASE.Runway Runway The runway or name of the runway.
|
|
||||||
-- @param #string Type Type of DEPARTURE (ILS, VOR, LOC).
|
|
||||||
-- @return #DEPARTURE self
|
|
||||||
function DEPARTURE:New(Airbase, Runway)
|
|
||||||
|
|
||||||
-- Inherit everything from BASE class.
|
|
||||||
self=BASE:Inherit(self, BASE:New()) -- #DEPARTURE
|
|
||||||
|
|
||||||
if type(Airbase)=="string" then
|
|
||||||
self.airbase=AIRBASE:FindByName(Airbase)
|
|
||||||
else
|
|
||||||
self.airbase=Airbase
|
|
||||||
end
|
|
||||||
|
|
||||||
if type(Runway)=="string" then
|
|
||||||
self.runway=self.airbase:GetRunwayByName(Runway)
|
|
||||||
else
|
|
||||||
self.runway=Runway
|
|
||||||
end
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-- User Functions
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
--- Set the primary navigation aid used in the DEPARTURE.
|
|
||||||
-- @param #DEPARTURE self
|
|
||||||
-- @param Navigation.Point#NAVAID NavAid The NAVAID.
|
|
||||||
-- @return #DEPARTURE self
|
|
||||||
function DEPARTURE:SetNavAid(NavAid)
|
|
||||||
|
|
||||||
self.navaid=NavAid
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Add a waypoint to the path of the DEPARTURE.
|
|
||||||
-- @param #DEPARTURE self
|
|
||||||
-- @param Navigation.Point#NAVFIX NavFix The navigation fix.
|
|
||||||
-- @param #string Segment The DEPARTURE segment this fix belongs to.
|
|
||||||
-- @return #DEPARTURE.Waypoint The waypoint data.
|
|
||||||
function DEPARTURE:AddWaypoint(NavFix, Segment)
|
|
||||||
|
|
||||||
self.wpcounter=self.wpcounter+1
|
|
||||||
|
|
||||||
local point={} --#DEPARTURE.Waypoint
|
|
||||||
point.uid=self.wpcounter
|
|
||||||
point.segment=Segment
|
|
||||||
point.navfix=NavFix
|
|
||||||
|
|
||||||
table.insert(self.path, point)
|
|
||||||
|
|
||||||
return point
|
|
||||||
end
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-- Private Functions
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
-- Add DEPARTURE private functions here.
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
@@ -1,108 +0,0 @@
|
|||||||
--- **NAVIGATION** - Template.
|
|
||||||
--
|
|
||||||
-- **Main Features:**
|
|
||||||
--
|
|
||||||
-- * Stuff
|
|
||||||
-- * More Stuff
|
|
||||||
--
|
|
||||||
-- ===
|
|
||||||
--
|
|
||||||
-- ## Example Missions:
|
|
||||||
--
|
|
||||||
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/Navigation%20-%20Template).
|
|
||||||
--
|
|
||||||
-- ===
|
|
||||||
--
|
|
||||||
-- ### Author: **funkyfranky**
|
|
||||||
--
|
|
||||||
-- ===
|
|
||||||
-- @module Navigation.Template
|
|
||||||
-- @image NAVIGATION_Template.png
|
|
||||||
|
|
||||||
|
|
||||||
--- TEMPLATE class.
|
|
||||||
-- @type TEMPLATE
|
|
||||||
-- @field #string ClassName Name of the class.
|
|
||||||
-- @field #number verbose Verbosity of output.
|
|
||||||
-- @extends Core.Base#BASE
|
|
||||||
|
|
||||||
--- *A fleet of British ships at war are the best negotiators.* -- Horatio Nelson
|
|
||||||
--
|
|
||||||
-- ===
|
|
||||||
--
|
|
||||||
-- # The TEMPLATE Concept
|
|
||||||
--
|
|
||||||
-- The TEMPLATE class has a great concept!
|
|
||||||
--
|
|
||||||
-- # Basic Setup
|
|
||||||
--
|
|
||||||
-- A new `TEMPLATE` object can be created with the @{#TEMPLATE.New}() function.
|
|
||||||
--
|
|
||||||
-- myTemplate=TEMPLATE:New()
|
|
||||||
-- myTemplate:SetXYZ(X, Y, Z)
|
|
||||||
--
|
|
||||||
-- This is how it works.
|
|
||||||
--
|
|
||||||
-- @field #TEMPLATE
|
|
||||||
TEMPLATE = {
|
|
||||||
ClassName = "TEMPLATE",
|
|
||||||
verbose = 0,
|
|
||||||
}
|
|
||||||
|
|
||||||
--- Type of navaid
|
|
||||||
-- @type TEMPLATE.Type
|
|
||||||
-- @field #string VOR VOR
|
|
||||||
-- @field #string NDB NDB
|
|
||||||
TEMPLATE.TYPE={
|
|
||||||
VOR="VOR",
|
|
||||||
NDB="NDB",
|
|
||||||
}
|
|
||||||
|
|
||||||
--- TEMPLATE class version.
|
|
||||||
-- @field #string version
|
|
||||||
TEMPLATE.version="0.0.1"
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-- ToDo list
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
-- TODO: A lot...
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-- Constructor
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
--- Create a new TEMPLATE class instance.
|
|
||||||
-- @param #TEMPLATE self
|
|
||||||
-- @return #TEMPLATE self
|
|
||||||
function TEMPLATE:New()
|
|
||||||
|
|
||||||
-- Inherit everything from SCENERY class.
|
|
||||||
self=BASE:Inherit(self, BASE:New()) -- #TEMPLATE
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-- User Functions
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
--- Set frequency.
|
|
||||||
-- @param #TEMPLATE self
|
|
||||||
-- @param #number Frequency Frequency in Hz.
|
|
||||||
-- @return #TEMPLATE self
|
|
||||||
function TEMPLATE:SetFrequency(Frequency)
|
|
||||||
|
|
||||||
self.frequency=Frequency
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-- Private Functions
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
@@ -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
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,697 +0,0 @@
|
|||||||
--- **Ops** - Brigade Warehouse.
|
|
||||||
--
|
|
||||||
-- **Main Features:**
|
|
||||||
--
|
|
||||||
-- * Manage platoons
|
|
||||||
-- * Carry out ARTY and PATROLZONE missions (AUFTRAG)
|
|
||||||
-- * Define rearming zones
|
|
||||||
--
|
|
||||||
-- ===
|
|
||||||
--
|
|
||||||
-- ## Example Missions:
|
|
||||||
--
|
|
||||||
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/Ops/Brigade).
|
|
||||||
--
|
|
||||||
-- ===
|
|
||||||
--
|
|
||||||
-- ### Author: **funkyfranky**
|
|
||||||
--
|
|
||||||
-- ===
|
|
||||||
-- @module Ops.Brigade
|
|
||||||
-- @image OPS_Brigade_.png
|
|
||||||
|
|
||||||
|
|
||||||
--- BRIGADE class.
|
|
||||||
-- @type BRIGADE
|
|
||||||
-- @field #string ClassName Name of the class.
|
|
||||||
-- @field #number verbose Verbosity of output.
|
|
||||||
-- @field #table rearmingZones Rearming zones. Each element is of type `#BRIGADE.SupplyZone`.
|
|
||||||
-- @field #table refuellingZones Refuelling zones. Each element is of type `#BRIGADE.SupplyZone`.
|
|
||||||
-- @field Core.Set#SET_ZONE retreatZones Retreat zone set.
|
|
||||||
-- @extends Ops.Legion#LEGION
|
|
||||||
|
|
||||||
--- *I am not afraid of an Army of lions lead by a sheep; I am afraid of sheep lead by a lion* -- Alexander the Great
|
|
||||||
--
|
|
||||||
-- ===
|
|
||||||
--
|
|
||||||
-- # The BRIGADE Concept
|
|
||||||
--
|
|
||||||
-- A BRIGADE consists of one or multiple PLATOONs. These platoons "live" in a WAREHOUSE that has a phyiscal struction (STATIC or UNIT) and can be captured or destroyed.
|
|
||||||
--
|
|
||||||
--
|
|
||||||
-- @field #BRIGADE
|
|
||||||
BRIGADE = {
|
|
||||||
ClassName = "BRIGADE",
|
|
||||||
verbose = 0,
|
|
||||||
rearmingZones = {},
|
|
||||||
refuellingZones = {},
|
|
||||||
}
|
|
||||||
|
|
||||||
--- Supply Zone.
|
|
||||||
-- @type BRIGADE.SupplyZone
|
|
||||||
-- @field Core.Zone#ZONE zone The zone.
|
|
||||||
-- @field Ops.Auftrag#AUFTRAG mission Mission assigned to supply ammo or fuel.
|
|
||||||
-- @field #boolean markerOn If `true`, marker is on.
|
|
||||||
-- @field Wrapper.Marker#MARKER marker F10 marker.
|
|
||||||
|
|
||||||
--- BRIGADE class version.
|
|
||||||
-- @field #string version
|
|
||||||
BRIGADE.version="0.1.1"
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-- ToDo list
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
-- TODO: Spawn when hosting warehouse is a ship or oil rig or gas platform.
|
|
||||||
-- TODO: Rearming zones.
|
|
||||||
-- TODO: Retreat zones.
|
|
||||||
-- DONE: Add weapon range.
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-- Constructor
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
--- Create a new BRIGADE class object.
|
|
||||||
-- @param #BRIGADE self
|
|
||||||
-- @param #string WarehouseName Name of the warehouse STATIC or UNIT object representing the warehouse.
|
|
||||||
-- @param #string BrigadeName Name of the brigade.
|
|
||||||
-- @return #BRIGADE self
|
|
||||||
function BRIGADE:New(WarehouseName, BrigadeName)
|
|
||||||
|
|
||||||
-- Inherit everything from LEGION class.
|
|
||||||
local self=BASE:Inherit(self, LEGION:New(WarehouseName, BrigadeName)) -- #BRIGADE
|
|
||||||
|
|
||||||
-- Nil check.
|
|
||||||
if not self then
|
|
||||||
BASE:E(string.format("ERROR: Could not find warehouse %s!", WarehouseName))
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Set some string id for output to DCS.log file.
|
|
||||||
self.lid=string.format("BRIGADE %s | ", self.alias)
|
|
||||||
|
|
||||||
-- Defaults
|
|
||||||
self:SetRetreatZones()
|
|
||||||
|
|
||||||
-- Turn ship into NAVYGROUP.
|
|
||||||
if self:IsShip() then
|
|
||||||
local wh=self.warehouse --Wrapper.Unit#UNIT
|
|
||||||
local group=wh:GetGroup()
|
|
||||||
self.warehouseOpsGroup=NAVYGROUP:New(group) --Ops.NavyGroup#NAVYGROUP
|
|
||||||
self.warehouseOpsElement=self.warehouseOpsGroup:GetElementByName(wh:GetName())
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Add FSM transitions.
|
|
||||||
-- From State --> Event --> To State
|
|
||||||
self:AddTransition("*", "ArmyOnMission", "*") -- An ARMYGROUP was send on a Mission (AUFTRAG).
|
|
||||||
|
|
||||||
------------------------
|
|
||||||
--- Pseudo Functions ---
|
|
||||||
------------------------
|
|
||||||
|
|
||||||
--- Triggers the FSM event "Start". Starts the BRIGADE. Initializes parameters and starts event handlers.
|
|
||||||
-- @function [parent=#BRIGADE] Start
|
|
||||||
-- @param #BRIGADE self
|
|
||||||
|
|
||||||
--- Triggers the FSM event "Start" after a delay. Starts the BRIGADE. Initializes parameters and starts event handlers.
|
|
||||||
-- @function [parent=#BRIGADE] __Start
|
|
||||||
-- @param #BRIGADE self
|
|
||||||
-- @param #number delay Delay in seconds.
|
|
||||||
|
|
||||||
|
|
||||||
--- Triggers the FSM event "Stop". Stops the BRIGADE and all its event handlers.
|
|
||||||
-- @param #BRIGADE self
|
|
||||||
|
|
||||||
--- Triggers the FSM event "Stop" after a delay. Stops the BRIGADE and all its event handlers.
|
|
||||||
-- @function [parent=#BRIGADE] __Stop
|
|
||||||
-- @param #BRIGADE self
|
|
||||||
-- @param #number delay Delay in seconds.
|
|
||||||
|
|
||||||
|
|
||||||
--- Triggers the FSM event "ArmyOnMission".
|
|
||||||
-- @function [parent=#BRIGADE] ArmyOnMission
|
|
||||||
-- @param #BRIGADE self
|
|
||||||
-- @param Ops.ArmyGroup#ARMYGROUP ArmyGroup The ARMYGROUP on mission.
|
|
||||||
-- @param Ops.Auftrag#AUFTRAG Mission The mission.
|
|
||||||
|
|
||||||
--- Triggers the FSM event "ArmyOnMission" after a delay.
|
|
||||||
-- @function [parent=#BRIGADE] __ArmyOnMission
|
|
||||||
-- @param #BRIGADE self
|
|
||||||
-- @param #number delay Delay in seconds.
|
|
||||||
-- @param Ops.ArmyGroup#ARMYGROUP ArmyGroup The ARMYGROUP on mission.
|
|
||||||
-- @param Ops.Auftrag#AUFTRAG Mission The mission.
|
|
||||||
|
|
||||||
--- On after "ArmyOnMission" event.
|
|
||||||
-- @function [parent=#BRIGADE] OnAfterArmyOnMission
|
|
||||||
-- @param #BRIGADE self
|
|
||||||
-- @param #string From From state.
|
|
||||||
-- @param #string Event Event.
|
|
||||||
-- @param #string To To state.
|
|
||||||
-- @param Ops.ArmyGroup#ARMYGROUP ArmyGroup The ARMYGROUP on mission.
|
|
||||||
-- @param Ops.Auftrag#AUFTRAG Mission The mission.
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-- User Functions
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
--- Add a platoon to the brigade.
|
|
||||||
-- @param #BRIGADE self
|
|
||||||
-- @param Ops.Platoon#PLATOON Platoon The platoon object.
|
|
||||||
-- @return #BRIGADE self
|
|
||||||
function BRIGADE:AddPlatoon(Platoon)
|
|
||||||
|
|
||||||
-- Add platoon to brigade.
|
|
||||||
table.insert(self.cohorts, Platoon)
|
|
||||||
|
|
||||||
-- Add assets to platoon.
|
|
||||||
self:AddAssetToPlatoon(Platoon, Platoon.Ngroups)
|
|
||||||
|
|
||||||
-- Set brigade of platoon.
|
|
||||||
Platoon:SetBrigade(self)
|
|
||||||
|
|
||||||
-- Start platoon.
|
|
||||||
if Platoon:IsStopped() then
|
|
||||||
Platoon:Start()
|
|
||||||
end
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Add asset group(s) to platoon.
|
|
||||||
-- @param #BRIGADE self
|
|
||||||
-- @param Ops.Platoon#PLATOON Platoon The platoon object.
|
|
||||||
-- @param #number Nassets Number of asset groups to add.
|
|
||||||
-- @return #BRIGADE self
|
|
||||||
function BRIGADE:AddAssetToPlatoon(Platoon, Nassets)
|
|
||||||
|
|
||||||
if Platoon then
|
|
||||||
|
|
||||||
-- Get the template group of the platoon.
|
|
||||||
local Group=GROUP:FindByName(Platoon.templatename)
|
|
||||||
|
|
||||||
if Group then
|
|
||||||
|
|
||||||
-- Debug text.
|
|
||||||
local text=string.format("Adding asset %s to platoon %s", Group:GetName(), Platoon.name)
|
|
||||||
self:T(self.lid..text)
|
|
||||||
|
|
||||||
-- Add assets to airwing warehouse.
|
|
||||||
self:AddAsset(Group, Nassets, nil, nil, nil, nil, Platoon.skill, Platoon.livery, Platoon.name)
|
|
||||||
|
|
||||||
else
|
|
||||||
self:E(self.lid.."ERROR: Group does not exist!")
|
|
||||||
end
|
|
||||||
|
|
||||||
else
|
|
||||||
self:E(self.lid.."ERROR: Platoon does not exit!")
|
|
||||||
end
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Define a set of retreat zones.
|
|
||||||
-- @param #BRIGADE self
|
|
||||||
-- @param Core.Set#SET_ZONE RetreatZoneSet Set of retreat zones.
|
|
||||||
-- @return #BRIGADE self
|
|
||||||
function BRIGADE:SetRetreatZones(RetreatZoneSet)
|
|
||||||
self.retreatZones=RetreatZoneSet or SET_ZONE:New()
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Add a retreat zone.
|
|
||||||
-- @param #BRIGADE self
|
|
||||||
-- @param Core.Zone#ZONE RetreatZone Retreat zone.
|
|
||||||
-- @return #BRIGADE self
|
|
||||||
function BRIGADE:AddRetreatZone(RetreatZone)
|
|
||||||
self.retreatZones:AddZone(RetreatZone)
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Get retreat zones.
|
|
||||||
-- @param #BRIGADE self
|
|
||||||
-- @return Core.Set#SET_ZONE Set of retreat zones.
|
|
||||||
function BRIGADE:GetRetreatZones()
|
|
||||||
return self.retreatZones
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Add a rearming zone.
|
|
||||||
-- @param #BRIGADE self
|
|
||||||
-- @param Core.Zone#ZONE RearmingZone Rearming zone.
|
|
||||||
-- @return #BRIGADE.SupplyZone The rearming zone data.
|
|
||||||
function BRIGADE:AddRearmingZone(RearmingZone)
|
|
||||||
|
|
||||||
local rearmingzone={} --#BRIGADE.SupplyZone
|
|
||||||
|
|
||||||
rearmingzone.zone=RearmingZone
|
|
||||||
rearmingzone.mission=nil
|
|
||||||
rearmingzone.marker=MARKER:New(rearmingzone.zone:GetCoordinate(), "Rearming Zone"):ToCoalition(self:GetCoalition())
|
|
||||||
|
|
||||||
table.insert(self.rearmingZones, rearmingzone)
|
|
||||||
|
|
||||||
return rearmingzone
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
--- Add a refuelling zone.
|
|
||||||
-- @param #BRIGADE self
|
|
||||||
-- @param Core.Zone#ZONE RefuellingZone Refuelling zone.
|
|
||||||
-- @return #BRIGADE.SupplyZone The refuelling zone data.
|
|
||||||
function BRIGADE:AddRefuellingZone(RefuellingZone)
|
|
||||||
|
|
||||||
local supplyzone={} --#BRIGADE.SupplyZone
|
|
||||||
|
|
||||||
supplyzone.zone=RefuellingZone
|
|
||||||
supplyzone.mission=nil
|
|
||||||
supplyzone.marker=MARKER:New(supplyzone.zone:GetCoordinate(), "Refuelling Zone"):ToCoalition(self:GetCoalition())
|
|
||||||
|
|
||||||
table.insert(self.refuellingZones, supplyzone)
|
|
||||||
|
|
||||||
return supplyzone
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
--- Get platoon by name.
|
|
||||||
-- @param #BRIGADE self
|
|
||||||
-- @param #string PlatoonName Name of the platoon.
|
|
||||||
-- @return Ops.Platoon#PLATOON The Platoon object.
|
|
||||||
function BRIGADE:GetPlatoon(PlatoonName)
|
|
||||||
local platoon=self:_GetCohort(PlatoonName)
|
|
||||||
return platoon
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Get platoon of an asset.
|
|
||||||
-- @param #BRIGADE self
|
|
||||||
-- @param Functional.Warehouse#WAREHOUSE.Assetitem Asset The platoon asset.
|
|
||||||
-- @return Ops.Platoon#PLATOON The platoon object.
|
|
||||||
function BRIGADE:GetPlatoonOfAsset(Asset)
|
|
||||||
local platoon=self:GetPlatoon(Asset.squadname)
|
|
||||||
return platoon
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Remove asset from platoon.
|
|
||||||
-- @param #BRIGADE self
|
|
||||||
-- @param Functional.Warehouse#WAREHOUSE.Assetitem Asset The platoon asset.
|
|
||||||
function BRIGADE:RemoveAssetFromPlatoon(Asset)
|
|
||||||
local platoon=self:GetPlatoonOfAsset(Asset)
|
|
||||||
if platoon then
|
|
||||||
platoon:DelAsset(Asset)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
--- [ GROUND ] Function to load back an asset in the field that has been filed before.
|
|
||||||
-- @param #BRIGADE self
|
|
||||||
-- @param #string Templatename e.g."1 PzDv LogRg I\_AID-976" - that's the alias (name) of an platoon spawned as `"platoon - alias"_AID-"asset-ID"`
|
|
||||||
-- @param Core.Point#COORDINATE Position where to spawn the platoon
|
|
||||||
-- @return #BRIGADE self
|
|
||||||
-- @usage
|
|
||||||
-- Prerequisites:
|
|
||||||
-- Save the assets spawned by BRIGADE/CHIEF regularly (~every 5 mins) into a file, e.g. like this:
|
|
||||||
--
|
|
||||||
-- local Path = FilePath or "C:\\Users\\<yourname>\\Saved Games\\DCS\\Missions\\" -- example path
|
|
||||||
-- local BlueOpsFilename = BlueFileName or "ExamplePlatoonSave.csv" -- example filename
|
|
||||||
-- local BlueSaveOps = SET_OPSGROUP:New():FilterCoalitions("blue"):FilterCategoryGround():FilterOnce()
|
|
||||||
-- UTILS.SaveSetOfOpsGroups(BlueSaveOps,Path,BlueOpsFilename)
|
|
||||||
--
|
|
||||||
-- where Path and Filename are strings, as chosen by you.
|
|
||||||
-- You can then load back the assets at the start of your next mission run. Be aware that it takes a couple of seconds for the
|
|
||||||
-- platoon data to arrive in brigade, so make this an action after ~20 seconds, e.g. like so:
|
|
||||||
--
|
|
||||||
-- function LoadBackAssets()
|
|
||||||
-- local Path = FilePath or "C:\\Users\\<yourname>\\Saved Games\\DCS\\Missions\\" -- example path
|
|
||||||
-- local BlueOpsFilename = BlueFileName or "ExamplePlatoonSave.csv" -- example filename
|
|
||||||
-- if UTILS.CheckFileExists(Path,BlueOpsFilename) then
|
|
||||||
-- local loadback = UTILS.LoadSetOfOpsGroups(Path,BlueOpsFilename,false)
|
|
||||||
-- for _,_platoondata in pairs (loadback) do
|
|
||||||
-- local groupname = _platoondata.groupname -- #string
|
|
||||||
-- local coordinate = _platoondata.coordinate -- Core.Point#COORDINATE
|
|
||||||
-- Your_Brigade:LoadBackAssetInPosition(groupname,coordinate)
|
|
||||||
-- end
|
|
||||||
-- end
|
|
||||||
-- end
|
|
||||||
--
|
|
||||||
-- local AssetLoader = TIMER:New(LoadBackAssets)
|
|
||||||
-- AssetLoader:Start(20)
|
|
||||||
--
|
|
||||||
-- The assets loaded back into the mission will be considered for AUFTRAG type missions from CHIEF and BRIGADE.
|
|
||||||
function BRIGADE:LoadBackAssetInPosition(Templatename,Position)
|
|
||||||
self:T(self.lid .. "LoadBackAssetInPosition: " .. tostring(Templatename))
|
|
||||||
|
|
||||||
-- get Platoon alias from Templatename
|
|
||||||
local nametbl = UTILS.Split(Templatename,"_")
|
|
||||||
|
|
||||||
local name = nametbl[1]
|
|
||||||
|
|
||||||
self:T(string.format("*** Target Platoon = %s ***",name))
|
|
||||||
|
|
||||||
-- find a matching asset table from BRIGADE
|
|
||||||
local cohorts = self.cohorts or {}
|
|
||||||
local thisasset = nil --Functional.Warehouse#WAREHOUSE.Assetitem
|
|
||||||
local found = false
|
|
||||||
|
|
||||||
for _,_cohort in pairs(cohorts) do
|
|
||||||
local asset = _cohort:GetName()
|
|
||||||
self:T(string.format("*** Looking at Platoon = %s ***",asset))
|
|
||||||
if asset == name then
|
|
||||||
self:T("**** Found Platoon ****")
|
|
||||||
local cohassets = _cohort.assets or {}
|
|
||||||
for _,_zug in pairs (cohassets) do
|
|
||||||
local zug = _zug -- Functional.Warehouse#WAREHOUSE.Assetitem
|
|
||||||
if zug.assignment == name and zug.requested == false then
|
|
||||||
self:T("**** Found Asset ****")
|
|
||||||
found = true
|
|
||||||
thisasset = zug --Functional.Warehouse#WAREHOUSE.Assetitem
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if found then
|
|
||||||
|
|
||||||
-- prep asset
|
|
||||||
thisasset.rid = thisasset.uid
|
|
||||||
thisasset.requested = false
|
|
||||||
thisasset.score=100
|
|
||||||
thisasset.missionTask="CAS"
|
|
||||||
thisasset.spawned = true
|
|
||||||
local template = thisasset.templatename
|
|
||||||
local alias = thisasset.spawngroupname
|
|
||||||
|
|
||||||
-- Spawn group
|
|
||||||
local spawnasset = SPAWN:NewWithAlias(template,alias)
|
|
||||||
:InitDelayOff()
|
|
||||||
:SpawnFromCoordinate(Position)
|
|
||||||
|
|
||||||
-- build a new self request
|
|
||||||
local request = {} --Functional.Warehouse#WAREHOUSE.Pendingitem
|
|
||||||
request.assignment = name
|
|
||||||
request.warehouse = self
|
|
||||||
request.assets = {thisasset}
|
|
||||||
request.ntransporthome = 0
|
|
||||||
request.ndelivered = 0
|
|
||||||
request.ntransport = 0
|
|
||||||
request.cargoattribute = thisasset.attribute
|
|
||||||
request.category = thisasset.category
|
|
||||||
request.cargoassets = {thisasset}
|
|
||||||
request.assetdesc = WAREHOUSE.Descriptor.ASSETLIST
|
|
||||||
request.cargocategory = thisasset.category
|
|
||||||
request.toself = true
|
|
||||||
request.transporttype = WAREHOUSE.TransportType.SELFPROPELLED
|
|
||||||
request.assetproblem = {}
|
|
||||||
request.born = true
|
|
||||||
request.prio = 50
|
|
||||||
request.uid = thisasset.uid
|
|
||||||
request.airbase = nil
|
|
||||||
request.timestamp = timer.getAbsTime()
|
|
||||||
request.assetdescval = {thisasset}
|
|
||||||
request.nasset = 1
|
|
||||||
request.cargogroupset = SET_GROUP:New()
|
|
||||||
request.cargogroupset:AddGroup(spawnasset)
|
|
||||||
request.iscargo = true
|
|
||||||
|
|
||||||
-- Call Brigade self
|
|
||||||
self:__AssetSpawned(2, spawnasset, thisasset, request)
|
|
||||||
|
|
||||||
end
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-- FSM Functions
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
--- Start BRIGADE FSM.
|
|
||||||
-- @param #BRIGADE self
|
|
||||||
function BRIGADE:onafterStart(From, Event, To)
|
|
||||||
|
|
||||||
-- Start parent Warehouse.
|
|
||||||
self:GetParent(self, BRIGADE).onafterStart(self, From, Event, To)
|
|
||||||
|
|
||||||
-- Info.
|
|
||||||
self:I(self.lid..string.format("Starting BRIGADE v%s", BRIGADE.version))
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Update status.
|
|
||||||
-- @param #BRIGADE self
|
|
||||||
function BRIGADE:onafterStatus(From, Event, To)
|
|
||||||
|
|
||||||
-- Status of parent Warehouse.
|
|
||||||
self:GetParent(self).onafterStatus(self, From, Event, To)
|
|
||||||
|
|
||||||
-- FSM state.
|
|
||||||
local fsmstate=self:GetState()
|
|
||||||
|
|
||||||
----------------
|
|
||||||
-- Transport ---
|
|
||||||
----------------
|
|
||||||
|
|
||||||
self:CheckTransportQueue()
|
|
||||||
|
|
||||||
--------------
|
|
||||||
-- Mission ---
|
|
||||||
--------------
|
|
||||||
|
|
||||||
-- Check if any missions should be cancelled.
|
|
||||||
self:CheckMissionQueue()
|
|
||||||
|
|
||||||
---------------------
|
|
||||||
-- Rearming Zones ---
|
|
||||||
---------------------
|
|
||||||
|
|
||||||
for _,_rearmingzone in pairs(self.rearmingZones) do
|
|
||||||
local rearmingzone=_rearmingzone --#BRIGADE.SupplyZone
|
|
||||||
if (not rearmingzone.mission) or rearmingzone.mission:IsOver() then
|
|
||||||
rearmingzone.mission=AUFTRAG:NewAMMOSUPPLY(rearmingzone.zone)
|
|
||||||
self:AddMission(rearmingzone.mission)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-----------------------
|
|
||||||
-- Refuelling Zones ---
|
|
||||||
-----------------------
|
|
||||||
|
|
||||||
-- Check refuelling zones.
|
|
||||||
for _,_supplyzone in pairs(self.refuellingZones) do
|
|
||||||
local supplyzone=_supplyzone --#BRIGADE.SupplyZone
|
|
||||||
-- Check if mission is nil or over.
|
|
||||||
if (not supplyzone.mission) or supplyzone.mission:IsOver() then
|
|
||||||
supplyzone.mission=AUFTRAG:NewFUELSUPPLY(supplyzone.zone)
|
|
||||||
self:AddMission(supplyzone.mission)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
-----------
|
|
||||||
-- Info ---
|
|
||||||
-----------
|
|
||||||
|
|
||||||
-- Display tactival overview.
|
|
||||||
self:_TacticalOverview()
|
|
||||||
|
|
||||||
-- General info:
|
|
||||||
if self.verbose>=1 then
|
|
||||||
|
|
||||||
-- Count missions not over yet.
|
|
||||||
local Nmissions=self:CountMissionsInQueue()
|
|
||||||
|
|
||||||
-- Asset count.
|
|
||||||
local Npq, Np, Nq=self:CountAssetsOnMission()
|
|
||||||
|
|
||||||
-- Asset string.
|
|
||||||
local assets=string.format("%d [OnMission: Total=%d, Active=%d, Queued=%d]", self:CountAssets(), Npq, Np, Nq)
|
|
||||||
|
|
||||||
-- Output.
|
|
||||||
local text=string.format("%s: Missions=%d, Platoons=%d, Assets=%s", fsmstate, Nmissions, #self.cohorts, assets)
|
|
||||||
self:I(self.lid..text)
|
|
||||||
end
|
|
||||||
|
|
||||||
------------------
|
|
||||||
-- Mission Info --
|
|
||||||
------------------
|
|
||||||
if self.verbose>=2 then
|
|
||||||
local text=string.format("Missions Total=%d:", #self.missionqueue)
|
|
||||||
for i,_mission in pairs(self.missionqueue) do
|
|
||||||
local mission=_mission --Ops.Auftrag#AUFTRAG
|
|
||||||
|
|
||||||
local prio=string.format("%d/%s", mission.prio, tostring(mission.importance)) ; if mission.urgent then prio=prio.." (!)" end
|
|
||||||
local assets=string.format("%d/%d", mission:CountOpsGroups(), mission.Nassets or 0)
|
|
||||||
local target=string.format("%d/%d Damage=%.1f", mission:CountMissionTargets(), mission:GetTargetInitialNumber(), mission:GetTargetDamage())
|
|
||||||
|
|
||||||
text=text..string.format("\n[%d] %s %s: Status=%s, Prio=%s, Assets=%s, Targets=%s", i, mission.name, mission.type, mission.status, prio, assets, target)
|
|
||||||
end
|
|
||||||
self:I(self.lid..text)
|
|
||||||
end
|
|
||||||
|
|
||||||
--------------------
|
|
||||||
-- Transport Info --
|
|
||||||
--------------------
|
|
||||||
if self.verbose>=2 then
|
|
||||||
local text=string.format("Transports Total=%d:", #self.transportqueue)
|
|
||||||
for i,_transport in pairs(self.transportqueue) do
|
|
||||||
local transport=_transport --Ops.OpsTransport#OPSTRANSPORT
|
|
||||||
|
|
||||||
local prio=string.format("%d/%s", transport.prio, tostring(transport.importance)) ; if transport.urgent then prio=prio.." (!)" end
|
|
||||||
local carriers=string.format("Ncargo=%d/%d, Ncarriers=%d", transport.Ncargo, transport.Ndelivered, transport.Ncarrier)
|
|
||||||
|
|
||||||
text=text..string.format("\n[%d] UID=%d: Status=%s, Prio=%s, Cargo: %s", i, transport.uid, transport:GetState(), prio, carriers)
|
|
||||||
end
|
|
||||||
self:I(self.lid..text)
|
|
||||||
end
|
|
||||||
|
|
||||||
-------------------
|
|
||||||
-- Platoon Info --
|
|
||||||
-------------------
|
|
||||||
if self.verbose>=3 then
|
|
||||||
local text="Platoons:"
|
|
||||||
for i,_platoon in pairs(self.cohorts) do
|
|
||||||
local platoon=_platoon --Ops.Platoon#PLATOON
|
|
||||||
|
|
||||||
local callsign=platoon.callsignName and UTILS.GetCallsignName(platoon.callsignName) or "N/A"
|
|
||||||
local modex=platoon.modex and platoon.modex or -1
|
|
||||||
local skill=platoon.skill and tostring(platoon.skill) or "N/A"
|
|
||||||
|
|
||||||
-- Platoon text.
|
|
||||||
text=text..string.format("\n* %s %s: %s*%d/%d, Callsign=%s, Modex=%d, Skill=%s", platoon.name, platoon:GetState(), platoon.aircrafttype, platoon:CountAssets(true), #platoon.assets, callsign, modex, skill)
|
|
||||||
end
|
|
||||||
self:I(self.lid..text)
|
|
||||||
end
|
|
||||||
|
|
||||||
-------------------
|
|
||||||
-- Rearming Info --
|
|
||||||
-------------------
|
|
||||||
if self.verbose>=4 then
|
|
||||||
local text="Rearming Zones:"
|
|
||||||
for i,_rearmingzone in pairs(self.rearmingZones) do
|
|
||||||
local rearmingzone=_rearmingzone --#BRIGADE.SupplyZone
|
|
||||||
-- Info text.
|
|
||||||
text=text..string.format("\n* %s: Mission status=%s, suppliers=%d", rearmingzone.zone:GetName(), rearmingzone.mission:GetState(), rearmingzone.mission:CountOpsGroups())
|
|
||||||
end
|
|
||||||
self:I(self.lid..text)
|
|
||||||
end
|
|
||||||
|
|
||||||
---------------------
|
|
||||||
-- Refuelling Info --
|
|
||||||
---------------------
|
|
||||||
if self.verbose>=4 then
|
|
||||||
local text="Refuelling Zones:"
|
|
||||||
for i,_refuellingzone in pairs(self.refuellingZones) do
|
|
||||||
local refuellingzone=_refuellingzone --#BRIGADE.SupplyZone
|
|
||||||
-- Info text.
|
|
||||||
text=text..string.format("\n* %s: Mission status=%s, suppliers=%d", refuellingzone.zone:GetName(), refuellingzone.mission:GetState(), refuellingzone.mission:CountOpsGroups())
|
|
||||||
end
|
|
||||||
self:I(self.lid..text)
|
|
||||||
end
|
|
||||||
|
|
||||||
----------------
|
|
||||||
-- Asset Info --
|
|
||||||
----------------
|
|
||||||
if self.verbose>=5 then
|
|
||||||
local text="Assets in stock:"
|
|
||||||
for i,_asset in pairs(self.stock) do
|
|
||||||
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
|
|
||||||
-- Info text.
|
|
||||||
text=text..string.format("\n* %s: spawned=%s", asset.spawngroupname, tostring(asset.spawned))
|
|
||||||
end
|
|
||||||
self:I(self.lid..text)
|
|
||||||
end
|
|
||||||
|
|
||||||
if self.verbose>=3 then
|
|
||||||
|
|
||||||
-- Count numbers
|
|
||||||
local Ntotal=0
|
|
||||||
local Nspawned=0
|
|
||||||
local Nrequested=0
|
|
||||||
local Nreserved=0
|
|
||||||
local Nstock=0
|
|
||||||
|
|
||||||
local text="\n===========================================\n"
|
|
||||||
text=text.."Assets:"
|
|
||||||
local legion=self --Ops.Legion#LEGION
|
|
||||||
|
|
||||||
for _,_cohort in pairs(legion.cohorts) do
|
|
||||||
local cohort=_cohort --Ops.Cohort#COHORT
|
|
||||||
|
|
||||||
for _,_asset in pairs(cohort.assets) do
|
|
||||||
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
|
|
||||||
|
|
||||||
local state="In Stock"
|
|
||||||
if asset.flightgroup then
|
|
||||||
state=asset.flightgroup:GetState()
|
|
||||||
local mission=legion:GetAssetCurrentMission(asset)
|
|
||||||
if mission then
|
|
||||||
state=state..string.format(", Mission \"%s\" [%s]", mission:GetName(), mission:GetType())
|
|
||||||
end
|
|
||||||
else
|
|
||||||
if asset.spawned then
|
|
||||||
env.info("FF ERROR: asset has opsgroup but is NOT spawned!")
|
|
||||||
end
|
|
||||||
if asset.requested and asset.isReserved then
|
|
||||||
env.info("FF ERROR: asset is requested and reserved. Should not be both!")
|
|
||||||
state="Reserved+Requested!"
|
|
||||||
elseif asset.isReserved then
|
|
||||||
state="Reserved"
|
|
||||||
elseif asset.requested then
|
|
||||||
state="Requested"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Text.
|
|
||||||
text=text..string.format("\n[UID=%03d] %s Legion=%s [%s]: State=%s [RID=%s]",
|
|
||||||
asset.uid, asset.spawngroupname, legion.alias, cohort.name, state, tostring(asset.rid))
|
|
||||||
|
|
||||||
|
|
||||||
if asset.spawned then
|
|
||||||
Nspawned=Nspawned+1
|
|
||||||
end
|
|
||||||
if asset.requested then
|
|
||||||
Nrequested=Nrequested+1
|
|
||||||
end
|
|
||||||
if asset.isReserved then
|
|
||||||
Nreserved=Nreserved+1
|
|
||||||
end
|
|
||||||
if not (asset.spawned or asset.requested or asset.isReserved) then
|
|
||||||
Nstock=Nstock+1
|
|
||||||
end
|
|
||||||
|
|
||||||
Ntotal=Ntotal+1
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
text=text.."\n-------------------------------------------"
|
|
||||||
text=text..string.format("\nNstock = %d", Nstock)
|
|
||||||
text=text..string.format("\nNreserved = %d", Nreserved)
|
|
||||||
text=text..string.format("\nNrequested = %d", Nrequested)
|
|
||||||
text=text..string.format("\nNspawned = %d", Nspawned)
|
|
||||||
text=text..string.format("\nNtotal = %d (=%d)", Ntotal, Nstock+Nspawned+Nrequested+Nreserved)
|
|
||||||
text=text.."\n==========================================="
|
|
||||||
self:I(self.lid..text)
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-- FSM Functions
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
--- On after "ArmyOnMission".
|
|
||||||
-- @param #BRIGADE self
|
|
||||||
-- @param #string From From state.
|
|
||||||
-- @param #string Event Event.
|
|
||||||
-- @param #string To To state.
|
|
||||||
-- @param Ops.ArmyGroup#ARMYGROUP ArmyGroup Ops army group on mission.
|
|
||||||
-- @param Ops.Auftrag#AUFTRAG Mission The requested mission.
|
|
||||||
function BRIGADE:onafterArmyOnMission(From, Event, To, ArmyGroup, Mission)
|
|
||||||
-- Debug info.
|
|
||||||
self:T(self.lid..string.format("Group %s on %s mission %s", ArmyGroup:GetName(), Mission:GetType(), Mission:GetName()))
|
|
||||||
end
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
||||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user