mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-08-15 10:47:21 +00:00
Compare commits
461 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d2bdb2a791 | ||
|
|
f8f0114f06 | ||
|
|
8619d48c80 | ||
|
|
4171cc45f5 | ||
|
|
5bccd2c6c9 | ||
|
|
a60626468c | ||
|
|
cad1c8c462 | ||
|
|
19e2af08e0 | ||
|
|
4386b19b06 | ||
|
|
da90826bd0 | ||
|
|
514d9f3eb3 | ||
|
|
690805d7ca | ||
|
|
f1f37b6598 | ||
|
|
08c593578f | ||
|
|
6625de9005 | ||
|
|
804a356f13 | ||
|
|
f03a2e3657 | ||
|
|
e6f51af34c | ||
|
|
db85883026 | ||
|
|
a3e29a8d5c | ||
|
|
e5e9bc2ef7 | ||
|
|
41aee35b5d | ||
|
|
7081a9eff5 | ||
|
|
be839f3a3b | ||
|
|
f35b27451f | ||
|
|
016e59860f | ||
|
|
d9719923c1 | ||
|
|
15a6c5f6a8 | ||
|
|
88d4580f9e | ||
|
|
87d82aa674 | ||
|
|
d58c7f8fab | ||
|
|
8d30dfacd5 | ||
|
|
7340b0aad3 | ||
|
|
03fd8c93eb | ||
|
|
f727aa0a17 | ||
|
|
502c356784 | ||
|
|
0e7291a912 | ||
|
|
2dc14097b8 | ||
|
|
9655d60bf8 | ||
|
|
cc920682fd | ||
|
|
205f69b3ab | ||
|
|
c4376f081b | ||
|
|
1ae062dc6e | ||
|
|
ea3bae39cc | ||
|
|
0bb62ce43f | ||
|
|
a4595090c4 | ||
|
|
9df3f52fd5 | ||
|
|
6f37ff1831 | ||
|
|
7d4b773b48 | ||
|
|
cba7bec477 | ||
|
|
e990db8070 | ||
|
|
ec9a5efdde | ||
|
|
8f6a3d5c49 | ||
|
|
d037614861 | ||
|
|
f8404f336d | ||
|
|
86fab3985b | ||
|
|
8c524f160e | ||
|
|
064111407b | ||
|
|
31207c3368 | ||
|
|
7e5495bcd8 | ||
|
|
a84f0e228a | ||
|
|
dc41852e45 | ||
|
|
3a8530227d | ||
|
|
ffee1b119b | ||
|
|
9637d0e545 | ||
|
|
2af52b294c | ||
|
|
a744e08a75 | ||
|
|
9bfbfcfd6a | ||
|
|
5becf001ba | ||
|
|
4625bc73a9 | ||
|
|
8fb1807ec0 | ||
|
|
f09443c949 | ||
|
|
2dc7ca0cb2 | ||
|
|
a76ea8f393 | ||
|
|
3275fd2e5b | ||
|
|
1d5ddb3928 | ||
|
|
7ab14e0bf9 | ||
|
|
98f51116bb | ||
|
|
159c3a21c0 | ||
|
|
51b6703b58 | ||
|
|
125dc09e4d | ||
|
|
49d2f5eef1 | ||
|
|
71415a9796 | ||
|
|
483c5deddd | ||
|
|
def7a1513e | ||
|
|
954ca31c79 | ||
|
|
762ce9a6b1 | ||
|
|
fd70ffc836 | ||
|
|
ddeb832f12 | ||
|
|
bef91cea35 | ||
|
|
163e42ee6e | ||
|
|
9ca61c680e | ||
|
|
d86419f893 | ||
|
|
6e67da1672 | ||
|
|
6b2e9fcb5f | ||
|
|
136a2ce5f2 | ||
|
|
e274ac3151 | ||
|
|
c8f2786611 | ||
|
|
8516cb349c | ||
|
|
fc5cbb7862 | ||
|
|
99b1532974 | ||
|
|
3625ad37b4 | ||
|
|
1345bdcb10 | ||
|
|
337e7eab53 | ||
|
|
f655e7e652 | ||
|
|
35e41570df | ||
|
|
bab1d21cc0 | ||
|
|
f5022a12f8 | ||
|
|
08fffb9004 | ||
|
|
02aff87b9f | ||
|
|
ab5f080191 | ||
|
|
3bf9198b6f | ||
|
|
e0c8d55a5d | ||
|
|
7cd40e2d2c | ||
|
|
ea851af6ea | ||
|
|
94c21db81c | ||
|
|
0275ba8b6b | ||
|
|
f4f942d8d4 | ||
|
|
85640c5884 | ||
|
|
6de86ac708 | ||
|
|
f8e1c21a13 | ||
|
|
14e1ab9497 | ||
|
|
98b427a26f | ||
|
|
f5a68db7ef | ||
|
|
a0502a12fa | ||
|
|
2d029c6405 | ||
|
|
8f08fd87be | ||
|
|
e16d6c0ca4 | ||
|
|
d9bcb8b168 | ||
|
|
f8f000eae5 | ||
|
|
47aaf6f6b2 | ||
|
|
88734fa9fc | ||
|
|
4ab94ecf26 | ||
|
|
06ff755702 | ||
|
|
c7c63b37fe | ||
|
|
7fa7f0fb79 | ||
|
|
fdfb5266b3 | ||
|
|
3b630be4f4 | ||
|
|
36aa36398c | ||
|
|
337b7a69b2 | ||
|
|
44866e6d58 | ||
|
|
80545fa208 | ||
|
|
956d4fa248 | ||
|
|
54ae3ed62b | ||
|
|
a6ea157b4f | ||
|
|
3d0f1faadc | ||
|
|
a0ac366bec | ||
|
|
d6cbd40575 | ||
|
|
b7644efea5 | ||
|
|
9c9633ba23 | ||
|
|
d5e2365bb3 | ||
|
|
9647a1a84e | ||
|
|
c1191e286a | ||
|
|
552718e303 | ||
|
|
85505f3feb | ||
|
|
cc9b695b68 | ||
|
|
64ed3a119f | ||
|
|
53ac9ca500 | ||
|
|
72538597ad | ||
|
|
5c5b9df470 | ||
|
|
7c3a8f448c | ||
|
|
bd1aec6deb | ||
|
|
492563d6f3 | ||
|
|
3ec2d525a9 | ||
|
|
dbd358be35 | ||
|
|
69934a8cae | ||
|
|
e13cf07999 | ||
|
|
0948229335 | ||
|
|
a0e77c04e0 | ||
|
|
718679b5dd | ||
|
|
107c2da635 | ||
|
|
c2064690f1 | ||
|
|
3f875ce276 | ||
|
|
703dac8251 | ||
|
|
5bd6f4901f | ||
|
|
5c29f48a88 | ||
|
|
012122e8da | ||
|
|
a039745b0f | ||
|
|
e97badd092 | ||
|
|
c160ecbce5 | ||
|
|
ea60e43584 | ||
|
|
ab19c696c3 | ||
|
|
da4664eff5 | ||
|
|
415b740196 | ||
|
|
7ab11d8fef | ||
|
|
01add98b7a | ||
|
|
31fba973e5 | ||
|
|
81b0c3a050 | ||
|
|
c790f71002 | ||
|
|
61a304f861 | ||
|
|
13451ed602 | ||
|
|
14bc7922d0 | ||
|
|
c9e44dd865 | ||
|
|
08cdb8b080 | ||
|
|
c1dee54493 | ||
|
|
ed3345b00a | ||
|
|
1097c02b06 | ||
|
|
8d41e4699c | ||
|
|
89051d5439 | ||
|
|
075fe729aa | ||
|
|
d51690a3cf | ||
|
|
97feeaeaf3 | ||
|
|
d4d05f4693 | ||
|
|
0ebbbde6c3 | ||
|
|
1ba84003d3 | ||
|
|
42b04dedaa | ||
|
|
6fbf584e81 | ||
|
|
8e6fc439ec | ||
|
|
25777afdd1 | ||
|
|
46edf5ce32 | ||
|
|
ae04196584 | ||
|
|
7b338ca9d0 | ||
|
|
daaedd24d2 | ||
|
|
a8d96d332f | ||
|
|
6b7a778eac | ||
|
|
2112915dd2 | ||
|
|
46cfcddf68 | ||
|
|
1aabb1bfbd | ||
|
|
8e16fbd000 | ||
|
|
a9a040626e | ||
|
|
508e35aec3 | ||
|
|
171f20e898 | ||
|
|
64355fb772 | ||
|
|
dffd66940d | ||
|
|
185c27013d | ||
|
|
d9a5618773 | ||
|
|
b8a83aadb2 | ||
|
|
5b7852ef6c | ||
|
|
76f34e448c | ||
|
|
743b595465 | ||
|
|
448110de08 | ||
|
|
7148fe0c12 | ||
|
|
b0ac01f25a | ||
|
|
4f38d8109d | ||
|
|
bf903c0cc7 | ||
|
|
c46d687990 | ||
|
|
64e67494b6 | ||
|
|
31a5bfee9e | ||
|
|
e40105495a | ||
|
|
f9b4eeef67 | ||
|
|
d1aa5d5de3 | ||
|
|
7a2dee4162 | ||
|
|
8bcdbef426 | ||
|
|
76ce28cdcc | ||
|
|
6c586d69ac | ||
|
|
a02d3c1950 | ||
|
|
5a2e1f01b4 | ||
|
|
22da329fca | ||
|
|
3ce59eee35 | ||
|
|
4e63bf6a22 | ||
|
|
7599459779 | ||
|
|
7a5aa3a4f9 | ||
|
|
9650129769 | ||
|
|
e4f8b5afc3 | ||
|
|
7e4c1d8d3d | ||
|
|
d21cee9358 | ||
|
|
4d7812b368 | ||
|
|
ab5b74cf31 | ||
|
|
74e9599df9 | ||
|
|
d91166c3c4 | ||
|
|
7f9f9b33fd | ||
|
|
195459d6d8 | ||
|
|
06688366c6 | ||
|
|
a2aa482bc1 | ||
|
|
498ec4f86b | ||
|
|
a14c2ef589 | ||
|
|
b438df27a4 | ||
|
|
009e38b6f7 | ||
|
|
b46c238dda | ||
|
|
a71c7dc181 | ||
|
|
86e4654474 | ||
|
|
891a725ccb | ||
|
|
aa53004ec8 | ||
|
|
321803730d | ||
|
|
d53c444c62 | ||
|
|
d3273b631f | ||
|
|
1ce55f3d3d | ||
|
|
e93f2c54b2 | ||
|
|
77f7826084 | ||
|
|
4a424dd3d8 | ||
|
|
f8b1056c98 | ||
|
|
52e69cb697 | ||
|
|
d4449f7913 | ||
|
|
e0564876f4 | ||
|
|
12be42ee2f | ||
|
|
5a034ecf4f | ||
|
|
9a6be14fab | ||
|
|
1146684144 | ||
|
|
12dc173aea | ||
|
|
0a68e7e2f1 | ||
|
|
849120a885 | ||
|
|
1dc6b91d37 | ||
|
|
e7f0aad920 | ||
|
|
fa785a06bb | ||
|
|
ef45e9b4c9 | ||
|
|
52f429a991 | ||
|
|
4dbcaf120f | ||
|
|
a09cd6e667 | ||
|
|
ea51622213 | ||
|
|
3526203ccb | ||
|
|
dc39107daa | ||
|
|
79cfe13035 | ||
|
|
6991550d1b | ||
|
|
c22d598b8f | ||
|
|
53c0599075 | ||
|
|
c7aa799378 | ||
|
|
b669ce6d98 | ||
|
|
267401a1f3 | ||
|
|
6d8b8f41ad | ||
|
|
6aa30f91e6 | ||
|
|
c60bb29303 | ||
|
|
72343bce29 | ||
|
|
258e3d2921 | ||
|
|
fda061d8c8 | ||
|
|
9e13ac3f68 | ||
|
|
9f644b65fd | ||
|
|
727aea604f | ||
|
|
1062d512d1 | ||
|
|
b3e62fbd50 | ||
|
|
fdb1db6f85 | ||
|
|
86633597b9 | ||
|
|
2faf7631cb | ||
|
|
8fb6fc8c6d | ||
|
|
8bee670bc9 | ||
|
|
5124b842f5 | ||
|
|
3c2ff2d7a1 | ||
|
|
61761c2fc8 | ||
|
|
7b1825aca5 | ||
|
|
ce6cb9c3e6 | ||
|
|
5d87672657 | ||
|
|
5e92b822d7 | ||
|
|
4452cbd2ab | ||
|
|
4bdb75245b | ||
|
|
e85c320844 | ||
|
|
1a4370d433 | ||
|
|
d46da07f61 | ||
|
|
c952f134d8 | ||
|
|
169dcfe3f6 | ||
|
|
a7afb43ab6 | ||
|
|
08ea3cd219 | ||
|
|
bfbdb37b65 | ||
|
|
f5eb77cbf5 | ||
|
|
3ed9555705 | ||
|
|
17e9538740 | ||
|
|
d6cdc098ce | ||
|
|
6b04237a3f | ||
|
|
07aff74126 | ||
|
|
ea89c6255b | ||
|
|
18450acea1 | ||
|
|
7d90a94927 | ||
|
|
82d40759b5 | ||
|
|
19197bf234 | ||
|
|
64c4d57a7b | ||
|
|
99963c28e9 | ||
|
|
9360513831 | ||
|
|
20c1f6bab4 | ||
|
|
6bdf0122e4 | ||
|
|
16b279c5db | ||
|
|
5290ad8b2e | ||
|
|
8c76314884 | ||
|
|
79d8113df3 | ||
|
|
601c00e637 | ||
|
|
58e5ffa283 | ||
|
|
ec0b32321a | ||
|
|
ca2eec8878 | ||
|
|
851c55e985 | ||
|
|
6c9c4432cc | ||
|
|
5c7312cd41 | ||
|
|
6bce3ebb8b | ||
|
|
89e67ba54d | ||
|
|
e5c481c161 | ||
|
|
3fee4a87da | ||
|
|
87a13f3784 | ||
|
|
d5d2de7577 | ||
|
|
8241f9de60 | ||
|
|
ba2d359af2 | ||
|
|
5ebf0b8d6c | ||
|
|
804b8a800e | ||
|
|
e8ff153427 | ||
|
|
403f22bd2b | ||
|
|
c6fc571c95 | ||
|
|
8b3d7ebf04 | ||
|
|
38a03f4cbc | ||
|
|
a2790f500c | ||
|
|
927ae59f75 | ||
|
|
8b667071b7 | ||
|
|
0a34cfdafa | ||
|
|
2d43af7c0d | ||
|
|
83fab80d88 | ||
|
|
6a71921270 | ||
|
|
8ff3530916 | ||
|
|
bd7c822def | ||
|
|
7b3f84f468 | ||
|
|
bf7523fa85 | ||
|
|
0d246d3f49 | ||
|
|
e9a055219e | ||
|
|
d9d53db53f | ||
|
|
e9473e9179 | ||
|
|
0b95930674 | ||
|
|
43a4052dc8 | ||
|
|
18098d402b | ||
|
|
f556077ff6 | ||
|
|
da452ed8ce | ||
|
|
9d62c60071 | ||
|
|
fd4d7f49a5 | ||
|
|
43b320ca90 | ||
|
|
ae4d4ca97d | ||
|
|
b6ac79a9df | ||
|
|
f03f9a3308 | ||
|
|
d4fead8294 | ||
|
|
1861e742b0 | ||
|
|
d11d4e09a4 | ||
|
|
8927504801 | ||
|
|
cb6673332d | ||
|
|
21ce0cac8d | ||
|
|
7ce20d92cb | ||
|
|
c5dcd63dea | ||
|
|
0553e4b14e | ||
|
|
6dc4a122f3 | ||
|
|
4941b5ee98 | ||
|
|
4c5d5a32dc | ||
|
|
073bfbf9c9 | ||
|
|
950c121f38 | ||
|
|
ad75a7ddb5 | ||
|
|
11516228fa | ||
|
|
d98f207bcf | ||
|
|
369ea08fd1 | ||
|
|
7013db0b67 | ||
|
|
5e2a5cf5e8 | ||
|
|
1b39f5d6e6 | ||
|
|
b560aaa147 | ||
|
|
9585959431 | ||
|
|
fe2f59660d | ||
|
|
e78cd56752 | ||
|
|
3d48dee23f | ||
|
|
51192f9a4c | ||
|
|
9dc329f151 | ||
|
|
6a4741d0dc | ||
|
|
25e4d171ab | ||
|
|
be48f7751c | ||
|
|
f7403758ce | ||
|
|
d8a189b1fd | ||
|
|
5bde59b7e3 | ||
|
|
adbbeafef9 | ||
|
|
3d5fbdf42d | ||
|
|
a408f45078 | ||
|
|
c1fb803780 | ||
|
|
0b378063c0 | ||
|
|
0d6117e5b4 | ||
|
|
cdecf4a4c9 | ||
|
|
d5d5d52bd5 | ||
|
|
d05973f487 | ||
|
|
623c907900 | ||
|
|
d07d063265 | ||
|
|
533b5d035e | ||
|
|
b82e85997f | ||
|
|
4309aa326f | ||
|
|
ac72e6fad2 | ||
|
|
48384ac758 | ||
|
|
7598a6ce5c | ||
|
|
000d7d3ce2 |
@@ -1,4 +1,4 @@
|
||||
version: 3.9.1.{build}
|
||||
version: 2.4.a.{build}
|
||||
shallow_clone: true
|
||||
skip_branch_with_pr: false
|
||||
skip_commits:
|
||||
@@ -17,6 +17,7 @@ environment:
|
||||
platform:
|
||||
- x64
|
||||
|
||||
|
||||
init:
|
||||
- ps: if ($env:APPVEYOR_PULL_REQUEST_NUMBER -and $env:APPVEYOR_BUILD_NUMBER -ne ((Invoke-RestMethod `
|
||||
https://ci.appveyor.com/api/projects/$env:APPVEYOR_ACCOUNT_NAME/$env:APPVEYOR_PROJECT_SLUG/history?recordsNumber=50).builds | `
|
||||
@@ -61,7 +62,7 @@ build_script:
|
||||
$project = Invoke-RestMethod -method Post -Uri "$apiUrl/builds" -Headers $headers -Body $RequestBody
|
||||
}
|
||||
- ps: |
|
||||
if( $env:appveyor_repo_branch -eq 'master' )
|
||||
if( $env:appveyor_repo_branch -eq 'master' -or $env:appveyor_repo_branch -eq 'develop' )
|
||||
{
|
||||
$apiUrl = 'https://ci.appveyor.com/api'
|
||||
$token = 'qts80b5kpq0ooj4x6vvw'
|
||||
@@ -69,13 +70,12 @@ build_script:
|
||||
"Authorization" = "Bearer $token"
|
||||
"Content-type" = "application/json"
|
||||
}
|
||||
$RequestBody = @{ accountName = 'FlightControl-Master'; projectSlug = 'moose-docs'; branch = 'master'; environmentVariables = @{} } | ConvertTo-Json
|
||||
$RequestBody = @{ accountName = 'FlightControl-Master'; projectSlug = 'moose-docs'; branch = "$env:appveyor_repo_branch"; environmentVariables = @{} } | ConvertTo-Json
|
||||
# get project with last build details
|
||||
$project = Invoke-RestMethod -method Post -Uri "$apiUrl/builds" -Headers $headers -Body $RequestBody
|
||||
}
|
||||
|
||||
|
||||
|
||||
test: off
|
||||
# test_script:
|
||||
# - cmd: luacheck "Moose Development\Moose\moose.lua" "Moose Mission Setup\moose.lua"
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
--- **AI** -- (R2.2) - Models the process of air operations for airplanes.
|
||||
--
|
||||
-- This is a class used in the @{AI_A2A_Dispatcher}.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **FlightControl**
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module AI_A2A
|
||||
-- @module AI.AI_A2A
|
||||
-- @image AI_Air_To_Air_Dispatching.JPG
|
||||
|
||||
--BASE:TraceClass("AI_A2A")
|
||||
|
||||
@@ -16,9 +15,7 @@
|
||||
--- @type AI_A2A
|
||||
-- @extends Core.Fsm#FSM_CONTROLLABLE
|
||||
|
||||
--- # AI_A2A class, extends @{Fsm#FSM_CONTROLLABLE}
|
||||
--
|
||||
-- The AI_A2A class implements the core functions to operate an AI @{Group} A2A tasking.
|
||||
--- The AI_A2A class implements the core functions to operate an AI @{Wrapper.Group} A2A tasking.
|
||||
--
|
||||
--
|
||||
-- ## AI_A2A constructor
|
||||
@@ -295,8 +292,8 @@ end
|
||||
|
||||
--- Sets (modifies) the minimum and maximum speed of the patrol.
|
||||
-- @param #AI_A2A self
|
||||
-- @param Dcs.DCSTypes#Speed PatrolMinSpeed The minimum speed of the @{Controllable} in km/h.
|
||||
-- @param Dcs.DCSTypes#Speed PatrolMaxSpeed The maximum speed of the @{Controllable} in km/h.
|
||||
-- @param DCS#Speed PatrolMinSpeed The minimum speed of the @{Wrapper.Controllable} in km/h.
|
||||
-- @param DCS#Speed PatrolMaxSpeed The maximum speed of the @{Wrapper.Controllable} in km/h.
|
||||
-- @return #AI_A2A self
|
||||
function AI_A2A:SetSpeed( PatrolMinSpeed, PatrolMaxSpeed )
|
||||
self:F2( { PatrolMinSpeed, PatrolMaxSpeed } )
|
||||
@@ -308,8 +305,8 @@ end
|
||||
|
||||
--- Sets the floor and ceiling altitude of the patrol.
|
||||
-- @param #AI_A2A self
|
||||
-- @param Dcs.DCSTypes#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
|
||||
-- @param Dcs.DCSTypes#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
|
||||
-- @param DCS#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
|
||||
-- @param DCS#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
|
||||
-- @return #AI_A2A self
|
||||
function AI_A2A:SetAltitude( PatrolFloorAltitude, PatrolCeilingAltitude )
|
||||
self:F2( { PatrolFloorAltitude, PatrolCeilingAltitude } )
|
||||
@@ -370,7 +367,6 @@ end
|
||||
-- @return #AI_A2A self
|
||||
function AI_A2A:SetFuelThreshold( PatrolFuelThresholdPercentage, PatrolOutOfFuelOrbitTime )
|
||||
|
||||
self.PatrolManageFuel = true
|
||||
self.PatrolFuelThresholdPercentage = PatrolFuelThresholdPercentage
|
||||
self.PatrolOutOfFuelOrbitTime = PatrolOutOfFuelOrbitTime
|
||||
|
||||
@@ -404,7 +400,6 @@ end
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
function AI_A2A:onafterStart( Controllable, From, Event, To )
|
||||
self:F2()
|
||||
|
||||
self:__Status( 10 ) -- Check status status every 30 seconds.
|
||||
|
||||
@@ -427,8 +422,6 @@ end
|
||||
--- @param #AI_A2A self
|
||||
function AI_A2A:onafterStatus()
|
||||
|
||||
self:F( " Checking Status" )
|
||||
|
||||
if self.Controllable and self.Controllable:IsAlive() then
|
||||
|
||||
local RTB = false
|
||||
@@ -455,8 +448,8 @@ function AI_A2A:onafterStatus()
|
||||
|
||||
|
||||
if not self:Is( "Fuel" ) and not self:Is( "Home" ) then
|
||||
local Fuel = self.Controllable:GetFuel()
|
||||
self:F({Fuel=Fuel})
|
||||
local Fuel = self.Controllable:GetFuelMin()
|
||||
self:F({Fuel=Fuel, PatrolFuelThresholdPercentage=self.PatrolFuelThresholdPercentage})
|
||||
if Fuel < self.PatrolFuelThresholdPercentage then
|
||||
if self.TankerName then
|
||||
self:E( self.Controllable:GetName() .. " is out of fuel: " .. Fuel .. " ... Refuelling at Tanker!" )
|
||||
|
||||
@@ -1,29 +1,24 @@
|
||||
--- **AI** -- (R2.2) - Models the process of Combat Air Patrol (CAP) for airplanes.
|
||||
--
|
||||
-- This is a class used in the @{AI_A2A_Dispatcher}.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **FlightControl**
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module AI_A2A_Cap
|
||||
|
||||
--BASE:TraceClass("AI_A2A_CAP")
|
||||
-- @module AI.AI_A2A_Cap
|
||||
-- @image AI_Combat_Air_Patrol.JPG
|
||||
|
||||
--- @type AI_A2A_CAP
|
||||
-- @extends AI.AI_A2A_Patrol#AI_A2A_PATROL
|
||||
|
||||
|
||||
--- # AI_A2A_CAP class, extends @{AI_CAP#AI_PATROL_ZONE}
|
||||
--
|
||||
-- The AI_A2A_CAP class implements the core functions to patrol a @{Zone} by an AI @{Group} or @{Group}
|
||||
--- The AI_A2A_CAP class implements the core functions to patrol a @{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.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- The AI_A2A_CAP is assigned a @{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.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
@@ -66,15 +61,15 @@
|
||||
--
|
||||
-- ### 2.2 AI_A2A_CAP Events
|
||||
--
|
||||
-- * **@{AI_Patrol#AI_PATROL_ZONE.Start}**: Start the process.
|
||||
-- * **@{AI_Patrol#AI_PATROL_ZONE.Route}**: Route the AI to a new random 3D point within the Patrol Zone.
|
||||
-- * **@{AI.AI_Patrol#AI_PATROL_ZONE.Start}**: Start the process.
|
||||
-- * **@{AI.AI_Patrol#AI_PATROL_ZONE.Route}**: Route the AI to a new random 3D point within the Patrol Zone.
|
||||
-- * **@{#AI_A2A_CAP.Engage}**: Let the AI engage the bogeys.
|
||||
-- * **@{#AI_A2A_CAP.Abort}**: Aborts the engagement and return patrolling in the patrol zone.
|
||||
-- * **@{AI_Patrol#AI_PATROL_ZONE.RTB}**: Route the AI to the home base.
|
||||
-- * **@{AI_Patrol#AI_PATROL_ZONE.Detect}**: The AI is detecting targets.
|
||||
-- * **@{AI_Patrol#AI_PATROL_ZONE.Detected}**: The AI has detected new targets.
|
||||
-- * **@{#AI_A2A_CAP.Destroy}**: The AI has destroyed a bogey @{Unit}.
|
||||
-- * **@{#AI_A2A_CAP.Destroyed}**: The AI has destroyed all bogeys @{Unit}s assigned in the CAS task.
|
||||
-- * **@{AI.AI_Patrol#AI_PATROL_ZONE.RTB}**: Route the AI to the home base.
|
||||
-- * **@{AI.AI_Patrol#AI_PATROL_ZONE.Detect}**: The AI is detecting targets.
|
||||
-- * **@{AI.AI_Patrol#AI_PATROL_ZONE.Detected}**: The AI has detected new targets.
|
||||
-- * **@{#AI_A2A_CAP.Destroy}**: The AI has destroyed a bogey @{Wrapper.Unit}.
|
||||
-- * **@{#AI_A2A_CAP.Destroyed}**: The AI has destroyed all bogeys @{Wrapper.Unit}s assigned in the CAS task.
|
||||
-- * **Status** ( Group ): The AI is checking status (fuel and damage). When the tresholds have been reached, the AI will RTB.
|
||||
--
|
||||
-- ## 3. Set the Range of Engagement
|
||||
@@ -85,7 +80,7 @@
|
||||
-- that will define when the AI will engage with the detected airborne enemy targets.
|
||||
-- The range can be beyond or smaller than the range of the Patrol Zone.
|
||||
-- The range is applied at the position of the AI.
|
||||
-- Use the method @{AI_CAP#AI_A2A_CAP.SetEngageRange}() to define that range.
|
||||
-- Use the method @{AI.AI_CAP#AI_A2A_CAP.SetEngageRange}() to define that range.
|
||||
--
|
||||
-- ## 4. Set the Zone of Engagement
|
||||
--
|
||||
@@ -93,7 +88,7 @@
|
||||
--
|
||||
-- An optional @{Zone} can be set,
|
||||
-- that will define when the AI will engage with the detected airborne enemy targets.
|
||||
-- Use the method @{AI_Cap#AI_A2A_CAP.SetEngageZone}() to define that Zone.
|
||||
-- Use the method @{AI.AI_Cap#AI_A2A_CAP.SetEngageZone}() to define that Zone.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
@@ -106,13 +101,13 @@ AI_A2A_CAP = {
|
||||
-- @param #AI_A2A_CAP self
|
||||
-- @param Wrapper.Group#GROUP AICap
|
||||
-- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed.
|
||||
-- @param Dcs.DCSTypes#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
|
||||
-- @param Dcs.DCSTypes#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
|
||||
-- @param Dcs.DCSTypes#Speed PatrolMinSpeed The minimum speed of the @{Group} in km/h.
|
||||
-- @param Dcs.DCSTypes#Speed PatrolMaxSpeed The maximum speed of the @{Group} in km/h.
|
||||
-- @param Dcs.DCSTypes#Speed EngageMinSpeed The minimum speed of the @{Group} in km/h when engaging a target.
|
||||
-- @param Dcs.DCSTypes#Speed EngageMaxSpeed The maximum speed of the @{Group} in km/h when engaging a target.
|
||||
-- @param Dcs.DCSTypes#AltitudeType PatrolAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to RADIO
|
||||
-- @param DCS#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
|
||||
-- @param DCS#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
|
||||
-- @param DCS#Speed PatrolMinSpeed The minimum speed of the @{Wrapper.Group} in km/h.
|
||||
-- @param DCS#Speed PatrolMaxSpeed The maximum speed of the @{Wrapper.Group} in km/h.
|
||||
-- @param DCS#Speed EngageMinSpeed The minimum speed of the @{Wrapper.Group} in km/h when engaging a target.
|
||||
-- @param DCS#Speed EngageMaxSpeed The maximum speed of the @{Wrapper.Group} in km/h when engaging a target.
|
||||
-- @param DCS#AltitudeType PatrolAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to RADIO
|
||||
-- @return #AI_A2A_CAP
|
||||
function AI_A2A_CAP:New( AICap, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, EngageMinSpeed, EngageMaxSpeed, PatrolAltType )
|
||||
|
||||
@@ -287,13 +282,14 @@ function AI_A2A_CAP:New( AICap, PatrolZone, PatrolFloorAltitude, PatrolCeilingAl
|
||||
end
|
||||
|
||||
--- onafter State Transition for Event Patrol.
|
||||
-- @param #AI_A2A_GCI self
|
||||
-- @param #AI_A2A_CAP self
|
||||
-- @param Wrapper.Group#GROUP AICap The AI Group managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
function AI_A2A_CAP:onafterStart( AICap, From, Event, To )
|
||||
|
||||
self:GetParent( self ).onafterStart( self, AICap, From, Event, To )
|
||||
AICap:HandleEvent( EVENTS.Takeoff, nil, self )
|
||||
|
||||
end
|
||||
|
||||
@@ -2,10 +2,37 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- 
|
||||
-- Features:
|
||||
--
|
||||
-- * Setup quickly an A2A defense system for a coalition.
|
||||
-- * Setup (CAP) Control Air Patrols at defined zones to enhance your A2A defenses.
|
||||
-- * Setup (GCI) Ground Control Intercept at defined airbases to enhance your A2A defenses.
|
||||
-- * Define and use an EWR (Early Warning Radar) network.
|
||||
-- * Define squadrons at airbases.
|
||||
-- * Enable airbases for A2A defenses.
|
||||
-- * Add different plane types to different squadrons.
|
||||
-- * Add multiple squadrons to different airbases.
|
||||
-- * Define different ranges to engage upon intruders.
|
||||
-- * Establish an automatic in air refuel process for CAP using refuel tankers.
|
||||
-- * Setup default settings for all squadrons and A2A defenses.
|
||||
-- * Setup specific settings for specific squadrons.
|
||||
-- * Quickly setup an A2A defense system using @{#AI_A2A_GCICAP}.
|
||||
-- * Setup a more advanced defense system using @{#AI_A2A_DISPATCHER}.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
--
|
||||
-- ## Missions:
|
||||
--
|
||||
-- [AID-A2A - AI A2A Dispatching](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/AID%20-%20AI%20Dispatching/AID-A2A%20-%20AI%20A2A%20Dispatching)
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ## YouTube Channel:
|
||||
--
|
||||
-- [DCS WORLD - MOOSE - A2A GCICAP - Build an automatic A2A Defense System](https://www.youtube.com/playlist?list=PL7ZUrU4zZUl0S4KMNUUJpaUs6zZHjLKNx)
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- # QUICK START GUIDE
|
||||
--
|
||||
-- There are basically two classes available to model an A2A defense system.
|
||||
@@ -155,7 +182,8 @@
|
||||
-- ### Authors: **FlightControl** rework of GCICAP + introduction of new concepts (squadrons).
|
||||
-- ### Authors: **Stonehouse**, **SNAFU** in terms of the advice, documentation, and the original GCICAP script.
|
||||
--
|
||||
-- @module AI_A2A_Dispatcher
|
||||
-- @module AI.AI_A2A_Dispatcher
|
||||
-- @image AI_Air_To_Air_Dispatching.JPG
|
||||
|
||||
|
||||
|
||||
@@ -165,23 +193,7 @@ do -- AI_A2A_DISPATCHER
|
||||
-- @type AI_A2A_DISPATCHER
|
||||
-- @extends Tasking.DetectionManager#DETECTION_MANAGER
|
||||
|
||||
--- # AI\_A2A\_DISPATCHER class, extends @{Tasking#DETECTION_MANAGER}
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- The @{#AI_A2A_DISPATCHER} class is designed to create an automatic air defence system for a coalition.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- # Demo Missions
|
||||
--
|
||||
-- ### [AI\_A2A\_DISPATCHER Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/release-2-2-pre/AID%20-%20AI%20Dispatching)
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- # YouTube Channel
|
||||
--
|
||||
-- ### [DCS WORLD - MOOSE - A2A GCICAP - Build an automatic A2A Defense System](https://www.youtube.com/playlist?list=PL7ZUrU4zZUl0S4KMNUUJpaUs6zZHjLKNx)
|
||||
--- Create an automatic air defence system for a coalition.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
@@ -229,7 +241,7 @@ do -- AI_A2A_DISPATCHER
|
||||
-- therefore less CAP and GCI flights will spawn and this will tend to make just the border area active rather than a melee over the whole map.
|
||||
-- It all depends on what the desired effect is.
|
||||
--
|
||||
-- EWR networks are **dynamically constructed**, that is, they form part of the @{Functional#DETECTION_BASE} object that is given as the input parameter of the AI\_A2A\_DISPATCHER class.
|
||||
-- EWR networks are **dynamically constructed**, that is, they form part of the @{Functional.Detection#DETECTION_BASE} object that is given as the input parameter of the AI\_A2A\_DISPATCHER class.
|
||||
-- By defining in a **smart way the names or name prefixes of the groups** with EWR capable units, these groups will be **automatically added or deleted** from the EWR network,
|
||||
-- increasing or decreasing the radar coverage of the Early Warning System.
|
||||
--
|
||||
@@ -346,7 +358,7 @@ do -- AI_A2A_DISPATCHER
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- If it’s a cold war then the **borders of red and blue territory** need to be defined using a @{zone} object derived from @{Zone#ZONE_BASE}.
|
||||
-- If it's a cold war then the **borders of red and blue territory** need to be defined using a @{zone} object derived from @{Core.Zone#ZONE_BASE}.
|
||||
-- If a hot war is chosen then **no borders** actually need to be defined using the helicopter units other than
|
||||
-- it makes it easier sometimes for the mission maker to envisage where the red and blue territories roughly are.
|
||||
-- In a hot war the borders are effectively defined by the ground based radar coverage of a coalition.
|
||||
@@ -544,18 +556,18 @@ do -- AI_A2A_DISPATCHER
|
||||
-- * As the CAP flights wander around within the zone waiting to be tasked, these zones need to be large enough that the aircraft are not constantly turning
|
||||
-- but do not have to be big and numerous enough to completely cover a border.
|
||||
--
|
||||
-- * CAP zones can be of any type, and are derived from the @{Zone#ZONE_BASE} class. Zones can be @{Zone#ZONE}, @{Zone#ZONE_POLYGON}, @{Zone#ZONE_UNIT}, @{Zone#ZONE_GROUP}, etc.
|
||||
-- * CAP zones can be of any type, and are derived from the @{Core.Zone#ZONE_BASE} class. Zones can be @{Core.Zone#ZONE}, @{Core.Zone#ZONE_POLYGON}, @{Core.Zone#ZONE_UNIT}, @{Core.Zone#ZONE_GROUP}, etc.
|
||||
-- This allows to setup **static, moving and/or complex zones** wherein aircraft will perform the CAP.
|
||||
--
|
||||
-- * Typically 20000-50000 metres width is used and they are spaced so that aircraft in the zone waiting for tasks don’t have to far to travel to protect their coalitions important targets.
|
||||
-- * Typically 20000-50000 metres width is used and they are spaced so that aircraft in the zone waiting for tasks don't have to far to travel to protect their coalitions important targets.
|
||||
-- These targets are chosen as part of the mission design and might be an important airfield or town etc.
|
||||
-- Zone size is also determined somewhat by territory size, plane types
|
||||
-- (eg WW2 aircraft might mean smaller zones or more zones because they are slower and take longer to intercept enemy aircraft).
|
||||
--
|
||||
-- * In a **cold war** it is important to make sure a CAP zone doesn’t intrude into enemy territory as otherwise CAP flights will likely cross borders
|
||||
-- * In a **cold war** it is important to make sure a CAP zone doesn't intrude into enemy territory as otherwise CAP flights will likely cross borders
|
||||
-- and spark a full scale conflict which will escalate rapidly.
|
||||
--
|
||||
-- * CAP flights do not need to be in the CAP zone before they are “on station” and ready for tasking.
|
||||
-- * CAP flights do not need to be in the CAP zone before they are "on station" and ready for tasking.
|
||||
--
|
||||
-- * Typically if a CAP flight is tasked and therefore leaves their zone empty while they go off and intercept their target another CAP flight will spawn to take their place.
|
||||
--
|
||||
@@ -740,7 +752,7 @@ do -- AI_A2A_DISPATCHER
|
||||
--
|
||||
-- In the mission editor, setup a group with task Refuelling. A tanker unit of the correct coalition will be automatically selected.
|
||||
-- Then, use the method @{#AI_A2A_DISPATCHER.SetDefaultTanker}() to set the tanker for the dispatcher.
|
||||
-- Use the method @{#AI_A2A_DISPATCHER.SetDefaultFuelTreshold}() to set the %-tage left in the defender airplane tanks when a refuel action is needed.
|
||||
-- Use the method @{#AI_A2A_DISPATCHER.SetDefaultFuelThreshold}() to set the %-tage left in the defender airplane tanks when a refuel action is needed.
|
||||
--
|
||||
-- When the tanker specified is alive and in the air, the tanker will be used for refuelling.
|
||||
--
|
||||
@@ -786,20 +798,27 @@ do -- AI_A2A_DISPATCHER
|
||||
--
|
||||
-- Use the method @{#AI_A2A_DISPATCHER.SetDisengageRadius}() to modify the default Disengage Radius to another distance setting.
|
||||
--
|
||||
-- ## 11. Airbase capture:
|
||||
--
|
||||
-- ## 11. Q & A:
|
||||
-- Different squadrons can be located at one airbase.
|
||||
-- If the airbase gets captured, that is, when there is an enemy unit near the airbase, and there aren't anymore friendlies at the airbase, the airbase will change coalition ownership.
|
||||
-- As a result, the GCI and CAP will stop!
|
||||
-- However, the squadron will still stay alive. Any airplane that is airborne will continue its operations until all airborne airplanes
|
||||
-- of the squadron will be destroyed. This to keep consistency of air operations not to confuse the players.
|
||||
--
|
||||
-- ### 11.1. Which countries will be selected for each coalition?
|
||||
-- ## 12. Q & A:
|
||||
--
|
||||
-- ### 12.1. Which countries will be selected for each coalition?
|
||||
--
|
||||
-- Which countries are assigned to a coalition influences which units are available to the coalition.
|
||||
-- For example because the mission calls for a EWR radar on the blue side the Ukraine might be chosen as a blue country
|
||||
-- so that the 55G6 EWR radar unit is available to blue.
|
||||
-- Some countries assign different tasking to aircraft, for example Germany assigns the CAP task to F-4E Phantoms but the USA does not.
|
||||
-- Therefore if F4s are wanted as a coalition’s CAP or GCI aircraft Germany will need to be assigned to that coalition.
|
||||
-- Therefore if F4s are wanted as a coalition's CAP or GCI aircraft Germany will need to be assigned to that coalition.
|
||||
--
|
||||
-- ### 11.2. Country, type, load out, skill and skins for CAP and GCI aircraft?
|
||||
-- ### 12.2. Country, type, load out, skill and skins for CAP and GCI aircraft?
|
||||
--
|
||||
-- * Note these can be from any countries within the coalition but must be an aircraft with one of the main tasks being “CAP”.
|
||||
-- * Note these can be from any countries within the coalition but must be an aircraft with one of the main tasks being "CAP".
|
||||
-- * Obviously skins which are selected must be available to all players that join the mission otherwise they will see a default skin.
|
||||
-- * Load outs should be appropriate to a CAP mission eg perhaps drop tanks for CAP flights and extra missiles for GCI flights.
|
||||
-- * These decisions will eventually lead to template aircraft units being placed as late activation units that the script will use as templates for spawning CAP and GCI flights. Up to 4 different aircraft configurations can be chosen for each coalition. The spawned aircraft will inherit the characteristics of the template aircraft.
|
||||
@@ -830,7 +849,7 @@ do -- AI_A2A_DISPATCHER
|
||||
|
||||
--- AI_A2A_DISPATCHER constructor.
|
||||
-- This is defining the A2A DISPATCHER for one coaliton.
|
||||
-- The Dispatcher works with a @{Functional#Detection} object that is taking of the detection of targets using the EWR units.
|
||||
-- The Dispatcher works with a @{Functional.Detection#DETECTION_BASE} object that is taking of the detection of targets using the EWR units.
|
||||
-- The Detection object is polymorphic, depending on the type of detection object choosen, the detection will work differently.
|
||||
-- @param #AI_A2A_DISPATCHER self
|
||||
-- @param Functional.Detection#DETECTION_BASE Detection The DETECTION object that will detects targets using the the Early Warning Radar network.
|
||||
@@ -983,10 +1002,15 @@ do -- AI_A2A_DISPATCHER
|
||||
|
||||
self:HandleEvent( EVENTS.Crash, self.OnEventCrashOrDead )
|
||||
self:HandleEvent( EVENTS.Dead, self.OnEventCrashOrDead )
|
||||
--self:HandleEvent( EVENTS.RemoveUnit, self.OnEventCrashOrDead )
|
||||
|
||||
|
||||
self:HandleEvent( EVENTS.Land )
|
||||
self:HandleEvent( EVENTS.EngineShutdown )
|
||||
|
||||
-- Handle the situation where the airbases are captured.
|
||||
self:HandleEvent( EVENTS.BaseCaptured )
|
||||
|
||||
self:SetTacticalDisplay( false )
|
||||
|
||||
self:__Start( 5 )
|
||||
@@ -994,6 +1018,25 @@ do -- AI_A2A_DISPATCHER
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- @param #AI_A2A_DISPATCHER self
|
||||
-- @param Core.Event#EVENTDATA EventData
|
||||
function AI_A2A_DISPATCHER:OnEventBaseCaptured( EventData )
|
||||
|
||||
local AirbaseName = EventData.PlaceName -- The name of the airbase that was captured.
|
||||
|
||||
self:I( "Captured " .. AirbaseName )
|
||||
|
||||
-- Now search for all squadrons located at the airbase, and sanatize them.
|
||||
for SquadronName, Squadron in pairs( self.DefenderSquadrons ) do
|
||||
if Squadron.AirbaseName == AirbaseName then
|
||||
Squadron.Resources = -999 -- The base has been captured, and the resources are eliminated. No more spawning.
|
||||
Squadron.Captured = true
|
||||
self:I( "Squadron " .. SquadronName .. " captured." )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- @param #AI_A2A_DISPATCHER self
|
||||
-- @param Core.Event#EVENTDATA EventData
|
||||
function AI_A2A_DISPATCHER:OnEventCrashOrDead( EventData )
|
||||
@@ -1023,10 +1066,6 @@ do -- AI_A2A_DISPATCHER
|
||||
DefenderUnit:Destroy()
|
||||
return
|
||||
end
|
||||
if DefenderUnit:GetFuel() <= self.DefenderDefault.FuelThreshold then
|
||||
DefenderUnit:Destroy()
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1039,7 +1078,8 @@ do -- AI_A2A_DISPATCHER
|
||||
if Squadron then
|
||||
self:F( { SquadronName = Squadron.Name } )
|
||||
local LandingMethod = self:GetSquadronLanding( Squadron.Name )
|
||||
if LandingMethod == AI_A2A_DISPATCHER.Landing.AtEngineShutdown then
|
||||
if LandingMethod == AI_A2A_DISPATCHER.Landing.AtEngineShutdown and
|
||||
not DefenderUnit:InAir() then
|
||||
local DefenderSize = Defender:GetSize()
|
||||
if DefenderSize == 1 then
|
||||
self:RemoveDefenderFromSquadron( Squadron, Defender )
|
||||
@@ -1142,7 +1182,7 @@ do -- AI_A2A_DISPATCHER
|
||||
--- Define a border area to simulate a **cold war** scenario.
|
||||
-- A **cold war** is one where CAP aircraft patrol their territory but will not attack enemy aircraft or launch GCI aircraft unless enemy aircraft enter their territory. In other words the EWR may detect an enemy aircraft but will only send aircraft to attack it if it crosses the border.
|
||||
-- A **hot war** is one where CAP aircraft will intercept any detected enemy aircraft and GCI aircraft will launch against detected enemy aircraft without regard for territory. In other words if the ground radar can detect the enemy aircraft then it will send CAP and GCI aircraft to attack it.
|
||||
-- If it’s a cold war then the **borders of red and blue territory** need to be defined using a @{zone} object derived from @{Zone#ZONE_BASE}. This method needs to be used for this.
|
||||
-- If it's a cold war then the **borders of red and blue territory** need to be defined using a @{zone} object derived from @{Core.Zone#ZONE_BASE}. This method needs to be used for this.
|
||||
-- If a hot war is chosen then **no borders** actually need to be defined using the helicopter units other than it makes it easier sometimes for the mission maker to envisage where the red and blue territories roughly are. In a hot war the borders are effectively defined by the ground based radar coverage of a coalition. Set the noborders parameter to 1
|
||||
-- @param #AI_A2A_DISPATCHER self
|
||||
-- @param Core.Zone#ZONE_BASE BorderZone An object derived from ZONE_BASE, or a list of objects derived from ZONE_BASE.
|
||||
@@ -1276,7 +1316,7 @@ do -- AI_A2A_DISPATCHER
|
||||
--- Calculates which AI friendlies are nearby the area
|
||||
-- @param #AI_A2A_DISPATCHER self
|
||||
-- @param DetectedItem
|
||||
-- @return #number, Core.CommandCenter#REPORT
|
||||
-- @return #table A list of the friendlies nearby.
|
||||
function AI_A2A_DISPATCHER:GetAIFriendliesNearBy( DetectedItem )
|
||||
|
||||
local FriendliesNearBy = self.Detection:GetFriendliesDistance( DetectedItem )
|
||||
@@ -1423,11 +1463,11 @@ do -- AI_A2A_DISPATCHER
|
||||
-- You need to specify here EXACTLY the name of the airbase as you see it in the mission editor.
|
||||
-- Examples are `"Batumi"` or `"Tbilisi-Lochini"`.
|
||||
-- EXACTLY the airbase name, between quotes `""`.
|
||||
-- To ease the airbase naming when using the LDT editor and IntelliSense, the @{Airbase#AIRBASE} class contains enumerations of the airbases of each map.
|
||||
-- To ease the airbase naming when using the LDT editor and IntelliSense, the @{Wrapper.Airbase#AIRBASE} class contains enumerations of the airbases of each map.
|
||||
--
|
||||
-- * Caucasus: @{Airbase#AIRBASE.Caucaus}
|
||||
-- * Nevada or NTTR: @{Airbase#AIRBASE.Nevada}
|
||||
-- * Normandy: @{Airbase#AIRBASE.Normandy}
|
||||
-- * Caucasus: @{Wrapper.Airbase#AIRBASE.Caucaus}
|
||||
-- * Nevada or NTTR: @{Wrapper.Airbase#AIRBASE.Nevada}
|
||||
-- * Normandy: @{Wrapper.Airbase#AIRBASE.Normandy}
|
||||
--
|
||||
-- @param #string TemplatePrefixes A string or an array of strings specifying the **prefix names of the templates** (not going to explain what is templates here again).
|
||||
-- Examples are `{ "104th", "105th" }` or `"104th"` or `"Template 1"` or `"BLUE PLANES"`.
|
||||
@@ -1472,6 +1512,7 @@ do -- AI_A2A_DISPATCHER
|
||||
|
||||
DefenderSquadron.Name = SquadronName
|
||||
DefenderSquadron.Airbase = AIRBASE:FindByName( AirbaseName )
|
||||
DefenderSquadron.AirbaseName = DefenderSquadron.Airbase:GetName()
|
||||
if not DefenderSquadron.Airbase then
|
||||
error( "Cannot find airbase with name:" .. AirbaseName )
|
||||
end
|
||||
@@ -1489,6 +1530,7 @@ do -- AI_A2A_DISPATCHER
|
||||
end
|
||||
DefenderSquadron.Resources = Resources
|
||||
DefenderSquadron.TemplatePrefixes = TemplatePrefixes
|
||||
DefenderSquadron.Captured = false -- Not captured. This flag will be set to true, when the airbase where the squadron is located, is captured.
|
||||
|
||||
self:F( { Squadron = {SquadronName, AirbaseName, TemplatePrefixes, Resources } } )
|
||||
|
||||
@@ -1512,7 +1554,7 @@ do -- AI_A2A_DISPATCHER
|
||||
--- Set a CAP for a Squadron.
|
||||
-- @param #AI_A2A_DISPATCHER self
|
||||
-- @param #string SquadronName The squadron name.
|
||||
-- @param Core.Zone#ZONE_BASE Zone The @{Zone} object derived from @{Zone#ZONE_BASE} that defines the zone wherein the CAP will be executed.
|
||||
-- @param Core.Zone#ZONE_BASE Zone The @{Zone} object derived from @{Core.Zone#ZONE_BASE} that defines the zone wherein the CAP will be executed.
|
||||
-- @param #number FloorAltitude The minimum altitude at which the cap can be executed.
|
||||
-- @param #number CeilingAltitude the maximum altitude at which the cap can be executed.
|
||||
-- @param #number PatrolMinSpeed The minimum speed at which the cap can be executed.
|
||||
@@ -1655,16 +1697,19 @@ do -- AI_A2A_DISPATCHER
|
||||
|
||||
local DefenderSquadron = self:GetSquadron( SquadronName )
|
||||
|
||||
if ( not DefenderSquadron.Resources ) or ( DefenderSquadron.Resources and DefenderSquadron.Resources > 0 ) then
|
||||
|
||||
local Cap = DefenderSquadron.Cap
|
||||
if Cap then
|
||||
local CapCount = self:CountCapAirborne( SquadronName )
|
||||
self:F( { CapCount = CapCount } )
|
||||
if CapCount < Cap.CapLimit then
|
||||
local Probability = math.random()
|
||||
if Probability <= Cap.Probability then
|
||||
return DefenderSquadron
|
||||
if DefenderSquadron.Captured == false then -- We can only spawn new CAP if the base has not been captured.
|
||||
|
||||
if ( not DefenderSquadron.Resources ) or ( DefenderSquadron.Resources and DefenderSquadron.Resources > 0 ) then -- And, if there are sufficient resources.
|
||||
|
||||
local Cap = DefenderSquadron.Cap
|
||||
if Cap then
|
||||
local CapCount = self:CountCapAirborne( SquadronName )
|
||||
self:F( { CapCount = CapCount } )
|
||||
if CapCount < Cap.CapLimit then
|
||||
local Probability = math.random()
|
||||
if Probability <= Cap.Probability then
|
||||
return DefenderSquadron
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1685,10 +1730,13 @@ do -- AI_A2A_DISPATCHER
|
||||
|
||||
local DefenderSquadron = self:GetSquadron( SquadronName )
|
||||
|
||||
if ( not DefenderSquadron.Resources ) or ( DefenderSquadron.Resources and DefenderSquadron.Resources > 0 ) then
|
||||
local Gci = DefenderSquadron.Gci
|
||||
if Gci then
|
||||
return DefenderSquadron
|
||||
if DefenderSquadron.Captured == false then -- We can only spawn new CAP if the base has not been captured.
|
||||
|
||||
if ( not DefenderSquadron.Resources ) or ( DefenderSquadron.Resources and DefenderSquadron.Resources > 0 ) then -- And, if there are sufficient resources.
|
||||
local Gci = DefenderSquadron.Gci
|
||||
if Gci then
|
||||
return DefenderSquadron
|
||||
end
|
||||
end
|
||||
end
|
||||
return nil
|
||||
@@ -2357,7 +2405,7 @@ do -- AI_A2A_DISPATCHER
|
||||
-- A2ADispatcher = AI_A2A_DISPATCHER:New( Detection )
|
||||
--
|
||||
-- -- Now Setup the default fuel treshold.
|
||||
-- A2ADispatcher:SetDefaultRefuelThreshold( 0.30 ) -- Go RTB when only 30% of fuel remaining in the tank.
|
||||
-- A2ADispatcher:SetDefaultFuelThreshold( 0.30 ) -- Go RTB when only 30% of fuel remaining in the tank.
|
||||
--
|
||||
function AI_A2A_DISPATCHER:SetDefaultFuelThreshold( FuelThreshold )
|
||||
|
||||
@@ -2391,7 +2439,7 @@ do -- AI_A2A_DISPATCHER
|
||||
|
||||
--- Set the default tanker where defenders will Refuel in the air.
|
||||
-- @param #AI_A2A_DISPATCHER self
|
||||
-- @param #strig TankerName A string defining the group name of the Tanker as defined within the Mission Editor.
|
||||
-- @param #string TankerName A string defining the group name of the Tanker as defined within the Mission Editor.
|
||||
-- @return #AI_A2A_DISPATCHER
|
||||
-- @usage
|
||||
--
|
||||
@@ -2399,7 +2447,7 @@ do -- AI_A2A_DISPATCHER
|
||||
-- A2ADispatcher = AI_A2A_DISPATCHER:New( Detection )
|
||||
--
|
||||
-- -- Now Setup the default fuel treshold.
|
||||
-- A2ADispatcher:SetDefaultRefuelThreshold( 0.30 ) -- Go RTB when only 30% of fuel remaining in the tank.
|
||||
-- A2ADispatcher:SetDefaultFuelThreshold( 0.30 ) -- Go RTB when only 30% of fuel remaining in the tank.
|
||||
--
|
||||
-- -- Now Setup the default tanker.
|
||||
-- A2ADispatcher:SetDefaultTanker( "Tanker" ) -- The group name of the tanker is "Tanker" in the Mission Editor.
|
||||
@@ -2414,7 +2462,7 @@ do -- AI_A2A_DISPATCHER
|
||||
--- Set the squadron tanker where defenders will Refuel in the air.
|
||||
-- @param #AI_A2A_DISPATCHER self
|
||||
-- @param #string SquadronName The name of the squadron.
|
||||
-- @param #strig TankerName A string defining the group name of the Tanker as defined within the Mission Editor.
|
||||
-- @param #string TankerName A string defining the group name of the Tanker as defined within the Mission Editor.
|
||||
-- @return #AI_A2A_DISPATCHER
|
||||
-- @usage
|
||||
--
|
||||
@@ -2470,7 +2518,7 @@ do -- AI_A2A_DISPATCHER
|
||||
--- Creates an SWEEP task when there are targets for it.
|
||||
-- @param #AI_A2A_DISPATCHER self
|
||||
-- @param Functional.Detection#DETECTION_BASE.DetectedItem DetectedItem
|
||||
-- @return Set#SET_UNIT TargetSetUnit: The target set of units.
|
||||
-- @return Core.Set#SET_UNIT TargetSetUnit: The target set of units.
|
||||
-- @return #nil If there are no targets to be set.
|
||||
function AI_A2A_DISPATCHER:EvaluateSWEEP( DetectedItem )
|
||||
self:F( { DetectedItem.ItemID } )
|
||||
@@ -2541,8 +2589,12 @@ do -- AI_A2A_DISPATCHER
|
||||
local SquadronOverhead = Squadron.Overhead or self.DefenderDefault.Overhead
|
||||
|
||||
local DefenderSize = Defender:GetInitialSize()
|
||||
DefenderCount = DefenderCount + DefenderSize / SquadronOverhead
|
||||
self:F( "Defender Group Name: " .. Defender:GetName() .. ", Size: " .. DefenderSize )
|
||||
if DefenderSize then
|
||||
DefenderCount = DefenderCount + DefenderSize / SquadronOverhead
|
||||
self:F( "Defender Group Name: " .. Defender:GetName() .. ", Size: " .. DefenderSize )
|
||||
else
|
||||
DefenderCount = 0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2890,8 +2942,8 @@ do -- AI_A2A_DISPATCHER
|
||||
|
||||
--- Creates an ENGAGE task when there are human friendlies airborne near the targets.
|
||||
-- @param #AI_A2A_DISPATCHER self
|
||||
-- @param Functional.Detection#DETECTION_BASE.DetectedItem DetectedItem
|
||||
-- @return Set#SET_UNIT TargetSetUnit: The target set of units.
|
||||
-- @param Functional.Detection#DETECTION_BASE.DetectedItem DetectedItem The detected item.
|
||||
-- @return Core.Set#SET_UNIT TargetSetUnit: The target set of units.
|
||||
-- @return #nil If there are no targets to be set.
|
||||
function AI_A2A_DISPATCHER:EvaluateENGAGE( DetectedItem )
|
||||
self:F( { DetectedItem.ItemID } )
|
||||
@@ -2917,8 +2969,8 @@ do -- AI_A2A_DISPATCHER
|
||||
|
||||
--- Creates an GCI task when there are targets for it.
|
||||
-- @param #AI_A2A_DISPATCHER self
|
||||
-- @param Functional.Detection#DETECTION_BASE.DetectedItem DetectedItem
|
||||
-- @return Set#SET_UNIT TargetSetUnit: The target set of units.
|
||||
-- @param Functional.Detection#DETECTION_BASE.DetectedItem DetectedItem The detected item.
|
||||
-- @return Core.Set#SET_UNIT TargetSetUnit: The target set of units.
|
||||
-- @return #nil If there are no targets to be set.
|
||||
function AI_A2A_DISPATCHER:EvaluateGCI( DetectedItem )
|
||||
self:F( { DetectedItem.ItemID } )
|
||||
@@ -2944,7 +2996,7 @@ do -- AI_A2A_DISPATCHER
|
||||
|
||||
--- Assigns A2A AI Tasks in relation to the detected items.
|
||||
-- @param #AI_A2A_DISPATCHER self
|
||||
-- @param Functional.Detection#DETECTION_BASE Detection The detection created by the @{Detection#DETECTION_BASE} derived object.
|
||||
-- @param Functional.Detection#DETECTION_BASE Detection The detection created by the @{Functional.Detection#DETECTION_BASE} derived object.
|
||||
-- @return #boolean Return true if you want the task assigning to continue... false will cancel the loop.
|
||||
function AI_A2A_DISPATCHER:ProcessDetected( Detection )
|
||||
|
||||
@@ -2984,6 +3036,8 @@ do -- AI_A2A_DISPATCHER
|
||||
|
||||
local Report = REPORT:New( "\nTactical Overview" )
|
||||
|
||||
local DefenderGroupCount = 0
|
||||
|
||||
-- Now that all obsolete tasks are removed, loop through the detected targets.
|
||||
for DetectedItemID, DetectedItem in pairs( Detection:GetDetectedItems() ) do
|
||||
|
||||
@@ -3021,16 +3075,19 @@ do -- AI_A2A_DISPATCHER
|
||||
for Defender, DefenderTask in pairs( self:GetDefenderTasks() ) do
|
||||
local Defender = Defender -- Wrapper.Group#GROUP
|
||||
if DefenderTask.Target and DefenderTask.Target.Index == DetectedItem.Index then
|
||||
local Fuel = Defender:GetFuel() * 100
|
||||
local Damage = Defender:GetLife() / Defender:GetLife0() * 100
|
||||
Report:Add( string.format( " - %s ( %s - %s ): ( #%d ) F: %3d, D:%3d - %s",
|
||||
Defender:GetName(),
|
||||
DefenderTask.Type,
|
||||
DefenderTask.Fsm:GetState(),
|
||||
Defender:GetSize(),
|
||||
Fuel,
|
||||
Damage,
|
||||
Defender:HasTask() == true and "Executing" or "Idle" ) )
|
||||
if Defender:IsAlive() then
|
||||
DefenderGroupCount = DefenderGroupCount + 1
|
||||
local Fuel = Defender:GetFuelMin() * 100
|
||||
local Damage = Defender:GetLife() / Defender:GetLife0() * 100
|
||||
Report:Add( string.format( " - %s ( %s - %s ): ( #%d ) F: %3d, D:%3d - %s",
|
||||
Defender:GetName(),
|
||||
DefenderTask.Type,
|
||||
DefenderTask.Fsm:GetState(),
|
||||
Defender:GetSize(),
|
||||
Fuel,
|
||||
Damage,
|
||||
Defender:HasTask() == true and "Executing" or "Idle" ) )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -3043,20 +3100,23 @@ do -- AI_A2A_DISPATCHER
|
||||
TaskCount = TaskCount + 1
|
||||
local Defender = Defender -- Wrapper.Group#GROUP
|
||||
if not DefenderTask.Target then
|
||||
local DefenderHasTask = Defender:HasTask()
|
||||
local Fuel = Defender:GetFuel() * 100
|
||||
local Damage = Defender:GetLife() / Defender:GetLife0() * 100
|
||||
Report:Add( string.format( " - %s ( %s - %s ): ( #%d ) F: %3d, D:%3d - %s",
|
||||
Defender:GetName(),
|
||||
DefenderTask.Type,
|
||||
DefenderTask.Fsm:GetState(),
|
||||
Defender:GetSize(),
|
||||
Fuel,
|
||||
Damage,
|
||||
Defender:HasTask() == true and "Executing" or "Idle" ) )
|
||||
if Defender:IsAlive() then
|
||||
local DefenderHasTask = Defender:HasTask()
|
||||
local Fuel = Defender:GetFuelMin() * 100
|
||||
local Damage = Defender:GetLife() / Defender:GetLife0() * 100
|
||||
DefenderGroupCount = DefenderGroupCount + 1
|
||||
Report:Add( string.format( " - %s ( %s - %s ): ( #%d ) F: %3d, D:%3d - %s",
|
||||
Defender:GetName(),
|
||||
DefenderTask.Type,
|
||||
DefenderTask.Fsm:GetState(),
|
||||
Defender:GetSize(),
|
||||
Fuel,
|
||||
Damage,
|
||||
Defender:HasTask() == true and "Executing" or "Idle" ) )
|
||||
end
|
||||
end
|
||||
end
|
||||
Report:Add( string.format( "\n - %d Tasks", TaskCount ) )
|
||||
Report:Add( string.format( "\n - %d Tasks - %d Defender Groups", TaskCount, DefenderGroupCount ) )
|
||||
|
||||
self:F( Report:Text( "\n" ) )
|
||||
trigger.action.outText( Report:Text( "\n" ), 25 )
|
||||
@@ -3069,10 +3129,10 @@ end
|
||||
|
||||
do
|
||||
|
||||
--- Calculates which HUMAN friendlies are nearby the area
|
||||
--- Calculates which HUMAN friendlies are nearby the area.
|
||||
-- @param #AI_A2A_DISPATCHER self
|
||||
-- @param DetectedItem
|
||||
-- @return #number, Core.CommandCenter#REPORT
|
||||
-- @param DetectedItem The detected item.
|
||||
-- @return #number, Core.Report#REPORT The amount of friendlies and a text string explaining which friendlies of which type.
|
||||
function AI_A2A_DISPATCHER:GetPlayerFriendliesNearBy( DetectedItem )
|
||||
|
||||
local DetectedSet = DetectedItem.Set
|
||||
@@ -3115,14 +3175,14 @@ do
|
||||
return PlayersCount, PlayerTypesReport
|
||||
end
|
||||
|
||||
--- Calculates which friendlies are nearby the area
|
||||
--- Calculates which friendlies are nearby the area.
|
||||
-- @param #AI_A2A_DISPATCHER self
|
||||
-- @param DetectedItem
|
||||
-- @return #number, Core.CommandCenter#REPORT
|
||||
function AI_A2A_DISPATCHER:GetFriendliesNearBy( Target )
|
||||
-- @param DetectedItem The detected item.
|
||||
-- @return #number, Core.Report#REPORT The amount of friendlies and a text string explaining which friendlies of which type.
|
||||
function AI_A2A_DISPATCHER:GetFriendliesNearBy( DetectedItem )
|
||||
|
||||
local DetectedSet = Target.Set
|
||||
local FriendlyUnitsNearBy = self.Detection:GetFriendliesNearBy( Target )
|
||||
local DetectedSet = DetectedItem.Set
|
||||
local FriendlyUnitsNearBy = self.Detection:GetFriendliesNearBy( DetectedItem )
|
||||
|
||||
local FriendlyTypes = {}
|
||||
local FriendliesCount = 0
|
||||
@@ -3159,8 +3219,8 @@ do
|
||||
return FriendliesCount, FriendlyTypesReport
|
||||
end
|
||||
|
||||
---
|
||||
-- @param AI_A2A_DISPATCHER
|
||||
--- Schedules a new CAP for the given SquadronName.
|
||||
-- @param #AI_A2A_DISPATCHER self
|
||||
-- @param #string SquadronName The squadron name.
|
||||
function AI_A2A_DISPATCHER:SchedulerCAP( SquadronName )
|
||||
self:CAP( SquadronName )
|
||||
@@ -3173,12 +3233,8 @@ do
|
||||
--- @type AI_A2A_GCICAP
|
||||
-- @extends #AI_A2A_DISPATCHER
|
||||
|
||||
--- # AI\_A2A\_GCICAP class, extends @{AI_A2A_Dispatcher#AI_A2A_DISPATCHER}
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- The AI_A2A_GCICAP class is designed to create an automatic air defence system for a coalition setting up GCI and CAP air defenses.
|
||||
-- The class derives from @{AI#AI_A2A_DISPATCHER} and thus, all the methods that are defined in the @{AI#AI_A2A_DISPATCHER} class, can be used also in AI\_A2A\_GCICAP.
|
||||
--- Create an automatic air defence system for a coalition setting up GCI and CAP air defenses.
|
||||
-- The class derives from @{#AI_A2A_DISPATCHER} and thus, all the methods that are defined in the @{#AI_A2A_DISPATCHER} class, can be used also in AI\_A2A\_GCICAP.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
@@ -3281,7 +3337,7 @@ do
|
||||
--
|
||||
-- **The place of the helicopter is important, as the airbase closest to the helicopter will be the airbase from where the CAP planes will take off for CAP.**
|
||||
--
|
||||
-- ## 2) There are a lot of defaults set, which can be further modified using the methods in @{AI#AI_A2A_DISPATCHER}:
|
||||
-- ## 2) There are a lot of defaults set, which can be further modified using the methods in @{#AI_A2A_DISPATCHER}:
|
||||
--
|
||||
-- ### 2.1) Planes are taking off in the air from the airbases.
|
||||
--
|
||||
@@ -3553,23 +3609,23 @@ do
|
||||
|
||||
-- Setup squadrons
|
||||
|
||||
self:F( { Airbases = AirbaseNames } )
|
||||
self:I( { Airbases = AirbaseNames } )
|
||||
|
||||
self:F( "Defining Templates for Airbases ..." )
|
||||
self:I( "Defining Templates for Airbases ..." )
|
||||
for AirbaseID, AirbaseName in pairs( AirbaseNames ) do
|
||||
local Airbase = _DATABASE:FindAirbase( AirbaseName ) -- Wrapper.Airbase#AIRBASE
|
||||
local AirbaseName = Airbase:GetName()
|
||||
local AirbaseCoord = Airbase:GetCoordinate()
|
||||
local AirbaseZone = ZONE_RADIUS:New( "Airbase", AirbaseCoord:GetVec2(), 3000 )
|
||||
local Templates = nil
|
||||
self:F( { Airbase = AirbaseName } )
|
||||
self:I( { Airbase = AirbaseName } )
|
||||
for TemplateID, Template in pairs( self.Templates:GetSet() ) do
|
||||
local Template = Template -- Wrapper.Group#GROUP
|
||||
local TemplateCoord = Template:GetCoordinate()
|
||||
if AirbaseZone:IsVec2InZone( TemplateCoord:GetVec2() ) then
|
||||
Templates = Templates or {}
|
||||
table.insert( Templates, Template:GetName() )
|
||||
self:F( { Template = Template:GetName() } )
|
||||
self:I( { Template = Template:GetName() } )
|
||||
end
|
||||
end
|
||||
if Templates then
|
||||
@@ -3585,13 +3641,13 @@ do
|
||||
self.CAPTemplates:FilterPrefixes( CapPrefixes )
|
||||
self.CAPTemplates:FilterOnce()
|
||||
|
||||
self:F( "Setting up CAP ..." )
|
||||
self:I( "Setting up CAP ..." )
|
||||
for CAPID, CAPTemplate in pairs( self.CAPTemplates:GetSet() ) do
|
||||
local CAPZone = ZONE_POLYGON:New( CAPTemplate:GetName(), CAPTemplate )
|
||||
-- Now find the closest airbase from the ZONE (start or center)
|
||||
local AirbaseDistance = 99999999
|
||||
local AirbaseClosest = nil -- Wrapper.Airbase#AIRBASE
|
||||
self:F( { CAPZoneGroup = CAPID } )
|
||||
self:I( { CAPZoneGroup = CAPID } )
|
||||
for AirbaseID, AirbaseName in pairs( AirbaseNames ) do
|
||||
local Airbase = _DATABASE:FindAirbase( AirbaseName ) -- Wrapper.Airbase#AIRBASE
|
||||
local AirbaseName = Airbase:GetName()
|
||||
@@ -3599,7 +3655,7 @@ do
|
||||
local Squadron = self.DefenderSquadrons[AirbaseName]
|
||||
if Squadron then
|
||||
local Distance = AirbaseCoord:Get2DDistance( CAPZone:GetCoordinate() )
|
||||
self:F( { AirbaseDistance = Distance } )
|
||||
self:I( { AirbaseDistance = Distance } )
|
||||
if Distance < AirbaseDistance then
|
||||
AirbaseDistance = Distance
|
||||
AirbaseClosest = Airbase
|
||||
@@ -3607,7 +3663,7 @@ do
|
||||
end
|
||||
end
|
||||
if AirbaseClosest then
|
||||
self:F( { CAPAirbase = AirbaseClosest:GetName() } )
|
||||
self:I( { CAPAirbase = AirbaseClosest:GetName() } )
|
||||
self:SetSquadronCap( AirbaseClosest:GetName(), CAPZone, 6000, 10000, 500, 800, 800, 1200, "RADIO" )
|
||||
self:SetSquadronCapInterval( AirbaseClosest:GetName(), CapLimit, 300, 600, 1 )
|
||||
end
|
||||
@@ -3615,14 +3671,14 @@ do
|
||||
|
||||
-- Setup GCI.
|
||||
-- GCI is setup for all Squadrons.
|
||||
self:F( "Setting up GCI ..." )
|
||||
self:I( "Setting up GCI ..." )
|
||||
for AirbaseID, AirbaseName in pairs( AirbaseNames ) do
|
||||
local Airbase = _DATABASE:FindAirbase( AirbaseName ) -- Wrapper.Airbase#AIRBASE
|
||||
local AirbaseName = Airbase:GetName()
|
||||
local Squadron = self.DefenderSquadrons[AirbaseName]
|
||||
self:F( { Airbase = AirbaseName } )
|
||||
if Squadron then
|
||||
self:F( { GCIAirbase = AirbaseName } )
|
||||
self:I( { GCIAirbase = AirbaseName } )
|
||||
self:SetSquadronGci( AirbaseName, 800, 1200 )
|
||||
end
|
||||
end
|
||||
@@ -3631,6 +3687,7 @@ do
|
||||
|
||||
self:HandleEvent( EVENTS.Crash, self.OnEventCrashOrDead )
|
||||
self:HandleEvent( EVENTS.Dead, self.OnEventCrashOrDead )
|
||||
--self:HandleEvent( EVENTS.RemoveUnit, self.OnEventCrashOrDead )
|
||||
|
||||
self:HandleEvent( EVENTS.Land )
|
||||
self:HandleEvent( EVENTS.EngineShutdown )
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module AI_A2A_GCI
|
||||
-- @module AI.AI_A2A_GCI
|
||||
-- @image AI_Ground_Control_Intercept.JPG
|
||||
|
||||
|
||||
|
||||
@@ -16,13 +17,11 @@
|
||||
-- @extends AI.AI_A2A#AI_A2A
|
||||
|
||||
|
||||
--- # AI_A2A_GCI class, extends @{AI_A2A#AI_A2A}
|
||||
--
|
||||
-- The AI_A2A_GCI class implements the core functions to intercept intruders. The Engage function will intercept intruders.
|
||||
--- Implements the core functions to intercept intruders. Use the Engage trigger to intercept intruders.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- The AI_A2A_GCI is assigned a @{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.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
@@ -65,15 +64,15 @@
|
||||
--
|
||||
-- ### 2.2 AI_A2A_GCI Events
|
||||
--
|
||||
-- * **@{AI_Patrol#AI_PATROL_ZONE.Start}**: Start the process.
|
||||
-- * **@{AI_Patrol#AI_PATROL_ZONE.Route}**: Route the AI to a new random 3D point within the Patrol Zone.
|
||||
-- * **@{AI.AI_Patrol#AI_PATROL_ZONE.Start}**: Start the process.
|
||||
-- * **@{AI.AI_Patrol#AI_PATROL_ZONE.Route}**: Route the AI to a new random 3D point within the Patrol Zone.
|
||||
-- * **@{#AI_A2A_GCI.Engage}**: Let the AI engage the bogeys.
|
||||
-- * **@{#AI_A2A_GCI.Abort}**: Aborts the engagement and return patrolling in the patrol zone.
|
||||
-- * **@{AI_Patrol#AI_PATROL_ZONE.RTB}**: Route the AI to the home base.
|
||||
-- * **@{AI_Patrol#AI_PATROL_ZONE.Detect}**: The AI is detecting targets.
|
||||
-- * **@{AI_Patrol#AI_PATROL_ZONE.Detected}**: The AI has detected new targets.
|
||||
-- * **@{#AI_A2A_GCI.Destroy}**: The AI has destroyed a bogey @{Unit}.
|
||||
-- * **@{#AI_A2A_GCI.Destroyed}**: The AI has destroyed all bogeys @{Unit}s assigned in the CAS task.
|
||||
-- * **@{AI.AI_Patrol#AI_PATROL_ZONE.RTB}**: Route the AI to the home base.
|
||||
-- * **@{AI.AI_Patrol#AI_PATROL_ZONE.Detect}**: The AI is detecting targets.
|
||||
-- * **@{AI.AI_Patrol#AI_PATROL_ZONE.Detected}**: The AI has detected new targets.
|
||||
-- * **@{#AI_A2A_GCI.Destroy}**: The AI has destroyed a bogey @{Wrapper.Unit}.
|
||||
-- * **@{#AI_A2A_GCI.Destroyed}**: The AI has destroyed all bogeys @{Wrapper.Unit}s assigned in the CAS task.
|
||||
-- * **Status** ( Group ): The AI is checking status (fuel and damage). When the tresholds have been reached, the AI will RTB.
|
||||
--
|
||||
-- ## 3. Set the Range of Engagement
|
||||
@@ -84,7 +83,7 @@
|
||||
-- that will define when the AI will engage with the detected airborne enemy targets.
|
||||
-- The range can be beyond or smaller than the range of the Patrol Zone.
|
||||
-- The range is applied at the position of the AI.
|
||||
-- Use the method @{AI_GCI#AI_A2A_GCI.SetEngageRange}() to define that range.
|
||||
-- Use the method @{AI.AI_GCI#AI_A2A_GCI.SetEngageRange}() to define that range.
|
||||
--
|
||||
-- ## 4. Set the Zone of Engagement
|
||||
--
|
||||
@@ -92,7 +91,7 @@
|
||||
--
|
||||
-- An optional @{Zone} can be set,
|
||||
-- that will define when the AI will engage with the detected airborne enemy targets.
|
||||
-- Use the method @{AI_Cap#AI_A2A_GCI.SetEngageZone}() to define that Zone.
|
||||
-- Use the method @{AI.AI_Cap#AI_A2A_GCI.SetEngageZone}() to define that Zone.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
@@ -291,6 +290,7 @@ end
|
||||
-- @param #string To The To State string.
|
||||
function AI_A2A_GCI:onafterStart( AIIntercept, From, Event, To )
|
||||
|
||||
self:GetParent( self ).onafterStart( self, AIIntercept, From, Event, To )
|
||||
AIIntercept:HandleEvent( EVENTS.Takeoff, nil, self )
|
||||
|
||||
end
|
||||
|
||||
@@ -1,26 +1,23 @@
|
||||
--- **AI** -- (R2.2) - Models the process of air patrol of airplanes.
|
||||
--
|
||||
-- This is a class used in the @{AI_A2A_Dispatcher}.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **FlightControl**
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module AI_A2A_Patrol
|
||||
-- @module AI.AI_A2A_Patrol
|
||||
-- @image AI_Air_Patrolling.JPG
|
||||
|
||||
|
||||
--- @type AI_A2A_PATROL
|
||||
-- @extends AI.AI_A2A#AI_A2A
|
||||
|
||||
--- # AI_A2A_PATROL class, extends @{Fsm#FSM_CONTROLLABLE}
|
||||
--
|
||||
-- The AI_A2A_PATROL class implements the core functions to patrol a @{Zone} by an AI @{Group} or @{Group}.
|
||||
--- Implements the core functions to patrol a @{Zone} by an AI @{Wrapper.Group} or @{Wrapper.Group}.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- The AI_A2A_PATROL is assigned a @{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.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
@@ -93,7 +90,7 @@
|
||||
-- * @{#AI_A2A_PATROL.SetDetectionOff}(): Set the detection off, the AI will not detect for targets. The existing target list will NOT be erased.
|
||||
--
|
||||
-- The detection frequency can be set with @{#AI_A2A_PATROL.SetRefreshTimeInterval}( seconds ), where the amount of seconds specify how much seconds will be waited before the next detection.
|
||||
-- Use the method @{#AI_A2A_PATROL.GetDetectedUnits}() to obtain a list of the @{Unit}s detected by the AI.
|
||||
-- Use the method @{#AI_A2A_PATROL.GetDetectedUnits}() to obtain a list of the @{Wrapper.Unit}s detected by the AI.
|
||||
--
|
||||
-- The detection can be filtered to potential targets in a specific zone.
|
||||
-- Use the method @{#AI_A2A_PATROL.SetDetectionZone}() to set the zone where targets need to be detected.
|
||||
@@ -126,11 +123,11 @@ AI_A2A_PATROL = {
|
||||
-- @param #AI_A2A_PATROL self
|
||||
-- @param Wrapper.Group#GROUP AIPatrol
|
||||
-- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed.
|
||||
-- @param Dcs.DCSTypes#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
|
||||
-- @param Dcs.DCSTypes#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
|
||||
-- @param Dcs.DCSTypes#Speed PatrolMinSpeed The minimum speed of the @{Group} in km/h.
|
||||
-- @param Dcs.DCSTypes#Speed PatrolMaxSpeed The maximum speed of the @{Group} in km/h.
|
||||
-- @param Dcs.DCSTypes#AltitudeType PatrolAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to RADIO
|
||||
-- @param DCS#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
|
||||
-- @param DCS#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
|
||||
-- @param DCS#Speed PatrolMinSpeed The minimum speed of the @{Wrapper.Group} in km/h.
|
||||
-- @param DCS#Speed PatrolMaxSpeed The maximum speed of the @{Wrapper.Group} in km/h.
|
||||
-- @param DCS#AltitudeType PatrolAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to RADIO
|
||||
-- @return #AI_A2A_PATROL self
|
||||
-- @usage
|
||||
-- -- Define a new AI_A2A_PATROL Object. This PatrolArea will patrol a Group within PatrolZone between 3000 and 6000 meters, with a variying speed between 600 and 900 km/h.
|
||||
@@ -236,8 +233,8 @@ end
|
||||
|
||||
--- Sets (modifies) the minimum and maximum speed of the patrol.
|
||||
-- @param #AI_A2A_PATROL self
|
||||
-- @param Dcs.DCSTypes#Speed PatrolMinSpeed The minimum speed of the @{Group} in km/h.
|
||||
-- @param Dcs.DCSTypes#Speed PatrolMaxSpeed The maximum speed of the @{Group} in km/h.
|
||||
-- @param DCS#Speed PatrolMinSpeed The minimum speed of the @{Wrapper.Group} in km/h.
|
||||
-- @param DCS#Speed PatrolMaxSpeed The maximum speed of the @{Wrapper.Group} in km/h.
|
||||
-- @return #AI_A2A_PATROL self
|
||||
function AI_A2A_PATROL:SetSpeed( PatrolMinSpeed, PatrolMaxSpeed )
|
||||
self:F2( { PatrolMinSpeed, PatrolMaxSpeed } )
|
||||
@@ -250,8 +247,8 @@ end
|
||||
|
||||
--- Sets the floor and ceiling altitude of the patrol.
|
||||
-- @param #AI_A2A_PATROL self
|
||||
-- @param Dcs.DCSTypes#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
|
||||
-- @param Dcs.DCSTypes#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
|
||||
-- @param DCS#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
|
||||
-- @param DCS#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
|
||||
-- @return #AI_A2A_PATROL self
|
||||
function AI_A2A_PATROL:SetAltitude( PatrolFloorAltitude, PatrolCeilingAltitude )
|
||||
self:F2( { PatrolFloorAltitude, PatrolCeilingAltitude } )
|
||||
@@ -358,7 +355,7 @@ function AI_A2A_PATROL.Resume( AIPatrol )
|
||||
|
||||
AIPatrol:F( { "AI_A2A_PATROL.Resume:", AIPatrol:GetName() } )
|
||||
if AIPatrol:IsAlive() then
|
||||
local _AI_A2A = AIPatrol:GetState( AIPatrol, "AI_A2A" ) -- #AI_A2A
|
||||
local _AI_A2A = AIPatrol:GetState( AIPatrol, "AI_A2A" ) -- AI.AI_A2A#AI_A2A
|
||||
_AI_A2A:__Reset( 1 )
|
||||
_AI_A2A:__Route( 5 )
|
||||
end
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
--- **AI** -- (R2.1) - Manages the independent process of Battlefield Air Interdiction (bombing) for airplanes.
|
||||
--- **AI** -- Peform Battlefield Area Interdiction (BAI) within an engagement zone.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- 
|
||||
-- **Features:**
|
||||
--
|
||||
-- * Hold and standby within a patrol zone.
|
||||
-- * Engage upon command the assigned targets within an engagement zone.
|
||||
-- * Loop the zone until all targets are eliminated.
|
||||
-- * Trigger different events upon the results achieved.
|
||||
-- * After combat, return to the patrol zone and hold.
|
||||
-- * RTB when commanded or after out of fuel.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/BAI%20-%20Battlefield%20Air%20Interdiction)
|
||||
@@ -21,25 +26,23 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module AI_Bai
|
||||
-- @module AI.AI_Bai
|
||||
-- @image AI_Battlefield_Air_Interdiction.JPG
|
||||
|
||||
|
||||
--- AI_BAI_ZONE class
|
||||
-- @type AI_BAI_ZONE
|
||||
-- @field Wrapper.Controllable#CONTROLLABLE AIControllable The @{Controllable} patrolling.
|
||||
-- @field Wrapper.Controllable#CONTROLLABLE AIControllable The @{Wrapper.Controllable} patrolling.
|
||||
-- @field Core.Zone#ZONE_BASE TargetZone The @{Zone} where the patrol needs to be executed.
|
||||
-- @extends AI.AI_Patrol#AI_PATROL_ZONE
|
||||
|
||||
--- # AI_BAI_ZONE class, extends @{AI_Patrol#AI_PATROL_ZONE}
|
||||
--- Implements the core functions to provide BattleGround Air Interdiction in an Engage @{Zone} by an AIR @{Wrapper.Controllable} or @{Wrapper.Group}.
|
||||
--
|
||||
-- AI_BAI_ZONE derives from the @{AI_Patrol#AI_PATROL_ZONE}, inheriting its methods and behaviour.
|
||||
--
|
||||
-- The AI_BAI_ZONE class implements the core functions to provide BattleGround Air Interdiction in an Engage @{Zone} by an AIR @{Controllable} or @{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 is assigned a @{Group} and this must be done before the AI_BAI_ZONE process can be started through the **Start** event.
|
||||
-- The AI_BAI_ZONE is assigned a @{Wrapper.Group} and this must be done before the AI_BAI_ZONE process can be started through the **Start** event.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
@@ -105,15 +108,15 @@
|
||||
--
|
||||
-- ### 2.2. AI_BAI_ZONE Events
|
||||
--
|
||||
-- * **@{AI_Patrol#AI_PATROL_ZONE.Start}**: Start the process.
|
||||
-- * **@{AI_Patrol#AI_PATROL_ZONE.Route}**: Route the AI to a new random 3D point within the Patrol Zone.
|
||||
-- * **@{AI.AI_Patrol#AI_PATROL_ZONE.Start}**: Start the process.
|
||||
-- * **@{AI.AI_Patrol#AI_PATROL_ZONE.Route}**: Route the AI to a new random 3D point within the Patrol Zone.
|
||||
-- * **@{#AI_BAI_ZONE.Engage}**: Engage the AI to provide BOMB in the Engage Zone, destroying any target it finds.
|
||||
-- * **@{#AI_BAI_ZONE.Abort}**: Aborts the engagement and return patrolling in the patrol zone.
|
||||
-- * **@{AI_Patrol#AI_PATROL_ZONE.RTB}**: Route the AI to the home base.
|
||||
-- * **@{AI_Patrol#AI_PATROL_ZONE.Detect}**: The AI is detecting targets.
|
||||
-- * **@{AI_Patrol#AI_PATROL_ZONE.Detected}**: The AI has detected new targets.
|
||||
-- * **@{#AI_BAI_ZONE.Destroy}**: The AI has destroyed a target @{Unit}.
|
||||
-- * **@{#AI_BAI_ZONE.Destroyed}**: The AI has destroyed all target @{Unit}s assigned in the BOMB task.
|
||||
-- * **@{AI.AI_Patrol#AI_PATROL_ZONE.RTB}**: Route the AI to the home base.
|
||||
-- * **@{AI.AI_Patrol#AI_PATROL_ZONE.Detect}**: The AI is detecting targets.
|
||||
-- * **@{AI.AI_Patrol#AI_PATROL_ZONE.Detected}**: The AI has detected new targets.
|
||||
-- * **@{#AI_BAI_ZONE.Destroy}**: The AI has destroyed a target @{Wrapper.Unit}.
|
||||
-- * **@{#AI_BAI_ZONE.Destroyed}**: The AI has destroyed all target @{Wrapper.Unit}s assigned in the BOMB task.
|
||||
-- * **Status**: The AI is checking status (fuel and damage). When the tresholds have been reached, the AI will RTB.
|
||||
--
|
||||
-- ## 3. Modify the Engage Zone behaviour to pinpoint a **map object** or **scenery object**
|
||||
@@ -140,12 +143,12 @@ AI_BAI_ZONE = {
|
||||
--- Creates a new AI_BAI_ZONE object
|
||||
-- @param #AI_BAI_ZONE self
|
||||
-- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed.
|
||||
-- @param Dcs.DCSTypes#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
|
||||
-- @param Dcs.DCSTypes#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
|
||||
-- @param Dcs.DCSTypes#Speed PatrolMinSpeed The minimum speed of the @{Controllable} in km/h.
|
||||
-- @param Dcs.DCSTypes#Speed PatrolMaxSpeed The maximum speed of the @{Controllable} in km/h.
|
||||
-- @param DCS#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
|
||||
-- @param DCS#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
|
||||
-- @param DCS#Speed PatrolMinSpeed The minimum speed of the @{Wrapper.Controllable} in km/h.
|
||||
-- @param DCS#Speed PatrolMaxSpeed The maximum speed of the @{Wrapper.Controllable} in km/h.
|
||||
-- @param Core.Zone#ZONE_BASE EngageZone The zone where the engage will happen.
|
||||
-- @param Dcs.DCSTypes#AltitudeType PatrolAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to RADIO
|
||||
-- @param DCS#AltitudeType PatrolAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to RADIO
|
||||
-- @return #AI_BAI_ZONE self
|
||||
function AI_BAI_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, EngageZone, PatrolAltType )
|
||||
|
||||
@@ -182,24 +185,24 @@ function AI_BAI_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude
|
||||
-- @function [parent=#AI_BAI_ZONE] Engage
|
||||
-- @param #AI_BAI_ZONE self
|
||||
-- @param #number EngageSpeed (optional) The speed the Group will hold when engaging to the target zone.
|
||||
-- @param Dcs.DCSTypes#Distance EngageAltitude (optional) Desired altitude to perform the unit engagement.
|
||||
-- @param Dcs.DCSTypes#AI.Task.WeaponExpend EngageWeaponExpend (optional) Determines how much weapon will be released at each attack.
|
||||
-- @param DCS#Distance EngageAltitude (optional) Desired altitude to perform the unit engagement.
|
||||
-- @param DCS#AI.Task.WeaponExpend EngageWeaponExpend (optional) Determines how much weapon will be released at each attack.
|
||||
-- If parameter is not defined the unit / controllable will choose expend on its own discretion.
|
||||
-- Use the structure @{DCSTypes#AI.Task.WeaponExpend} to define the amount of weapons to be release at each attack.
|
||||
-- Use the structure @{DCS#AI.Task.WeaponExpend} to define the amount of weapons to be release at each attack.
|
||||
-- @param #number EngageAttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo.
|
||||
-- @param Dcs.DCSTypes#Azimuth EngageDirection (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
|
||||
-- @param DCS#Azimuth EngageDirection (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
|
||||
|
||||
--- Asynchronous Event Trigger for Event Engage.
|
||||
-- @function [parent=#AI_BAI_ZONE] __Engage
|
||||
-- @param #AI_BAI_ZONE self
|
||||
-- @param #number Delay The delay in seconds.
|
||||
-- @param #number EngageSpeed (optional) The speed the Group will hold when engaging to the target zone.
|
||||
-- @param Dcs.DCSTypes#Distance EngageAltitude (optional) Desired altitude to perform the unit engagement.
|
||||
-- @param Dcs.DCSTypes#AI.Task.WeaponExpend EngageWeaponExpend (optional) Determines how much weapon will be released at each attack.
|
||||
-- @param DCS#Distance EngageAltitude (optional) Desired altitude to perform the unit engagement.
|
||||
-- @param DCS#AI.Task.WeaponExpend EngageWeaponExpend (optional) Determines how much weapon will be released at each attack.
|
||||
-- If parameter is not defined the unit / controllable will choose expend on its own discretion.
|
||||
-- Use the structure @{DCSTypes#AI.Task.WeaponExpend} to define the amount of weapons to be release at each attack.
|
||||
-- Use the structure @{DCS#AI.Task.WeaponExpend} to define the amount of weapons to be release at each attack.
|
||||
-- @param #number EngageAttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo.
|
||||
-- @param Dcs.DCSTypes#Azimuth EngageDirection (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
|
||||
-- @param DCS#Azimuth EngageDirection (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
|
||||
|
||||
--- OnLeave Transition Handler for State Engaging.
|
||||
-- @function [parent=#AI_BAI_ZONE] OnLeaveEngaging
|
||||
@@ -486,10 +489,10 @@ end
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
-- @param #number EngageSpeed (optional) The speed the Group will hold when engaging to the target zone.
|
||||
-- @param Dcs.DCSTypes#Distance EngageAltitude (optional) Desired altitude to perform the unit engagement.
|
||||
-- @param Dcs.DCSTypes#AI.Task.WeaponExpend EngageWeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / controllable will choose expend on its own discretion.
|
||||
-- @param DCS#Distance EngageAltitude (optional) Desired altitude to perform the unit engagement.
|
||||
-- @param DCS#AI.Task.WeaponExpend EngageWeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / controllable will choose expend on its own discretion.
|
||||
-- @param #number EngageAttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo.
|
||||
-- @param Dcs.DCSTypes#Azimuth EngageDirection (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
|
||||
-- @param DCS#Azimuth EngageDirection (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
|
||||
function AI_BAI_ZONE:onafterEngage( Controllable, From, Event, To,
|
||||
EngageSpeed,
|
||||
EngageAltitude,
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
--- **AI** -- (2.1) - Balance player slots with AI to create an engaging simulation environment, independent of the amount of players.
|
||||
--- **AI** -- Balance player slots with AI to create an engaging simulation environment, independent of the amount of players.
|
||||
--
|
||||
-- ===
|
||||
-- **Features:**
|
||||
--
|
||||
-- 
|
||||
-- * Automatically spawn AI as a replacement of free player slots for a coalition.
|
||||
-- * Make the AI to perform tasks.
|
||||
-- * Define a maximum amount of AI to be active at the same time.
|
||||
-- * Configure the behaviour of AI when a human joins a slot for which an AI is active.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
@@ -21,7 +24,8 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module AI_Balancer
|
||||
-- @module AI.AI_Balancer
|
||||
-- @image AI_Balancing.JPG
|
||||
|
||||
--- @type AI_BALANCER
|
||||
-- @field Core.Set#SET_CLIENT SetClient
|
||||
@@ -30,13 +34,11 @@
|
||||
-- @extends Core.Fsm#FSM_SET
|
||||
|
||||
|
||||
--- # AI_BALANCER class, extends @{Fsm#FSM_SET}
|
||||
--
|
||||
-- The AI_BALANCER class monitors and manages as many replacement AI groups as there are
|
||||
-- CLIENTS in a SET_CLIENT collection, which are not occupied by human players.
|
||||
--- Monitors and manages as many replacement AI groups as there are
|
||||
-- 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.
|
||||
--
|
||||
-- The parent class @{Fsm#FSM_SET} manages the functionality to control the Finite State Machine (FSM).
|
||||
-- The parent class @{Core.Fsm#FSM_SET} manages the functionality to control the Finite State Machine (FSM).
|
||||
-- The mission designer can tailor the behaviour of the AI_BALANCER, by defining event and state transition methods.
|
||||
-- An explanation about state and event transition methods can be found in the @{FSM} module documentation.
|
||||
--
|
||||
@@ -78,8 +80,8 @@
|
||||
-- However, there are 2 additional options that you can use to customize the destroy behaviour.
|
||||
-- When a human player joins a slot, you can configure to let the AI return to:
|
||||
--
|
||||
-- * @{#AI_BALANCER.ReturnToHomeAirbase}: Returns the AI to the **home** @{Airbase#AIRBASE}.
|
||||
-- * @{#AI_BALANCER.ReturnToNearestAirbases}: Returns the AI to the **nearest friendly** @{Airbase#AIRBASE}.
|
||||
-- * @{#AI_BALANCER.ReturnToHomeAirbase}: Returns the AI to the **home** @{Wrapper.Airbase#AIRBASE}.
|
||||
-- * @{#AI_BALANCER.ReturnToNearestAirbases}: Returns the AI to the **nearest friendly** @{Wrapper.Airbase#AIRBASE}.
|
||||
--
|
||||
-- Note that when AI returns to an airbase, the AI_BALANCER will trigger the **Return** event and the AI will return,
|
||||
-- otherwise the AI_BALANCER will trigger a **Destroy** event, and the AI will be destroyed.
|
||||
@@ -141,10 +143,10 @@ function AI_BALANCER:InitSpawnInterval( Earliest, Latest )
|
||||
return self
|
||||
end
|
||||
|
||||
--- Returns the AI to the nearest friendly @{Airbase#AIRBASE}.
|
||||
--- Returns the AI to the nearest friendly @{Wrapper.Airbase#AIRBASE}.
|
||||
-- @param #AI_BALANCER self
|
||||
-- @param Dcs.DCSTypes#Distance ReturnThresholdRange If there is an enemy @{Client#CLIENT} within the ReturnThresholdRange given in meters, the AI will not return to the nearest @{Airbase#AIRBASE}.
|
||||
-- @param Core.Set#SET_AIRBASE ReturnAirbaseSet The SET of @{Set#SET_AIRBASE}s to evaluate where to return to.
|
||||
-- @param DCS#Distance ReturnThresholdRange If there is an enemy @{Wrapper.Client#CLIENT} within the ReturnThresholdRange given in meters, the AI will not return to the nearest @{Wrapper.Airbase#AIRBASE}.
|
||||
-- @param Core.Set#SET_AIRBASE ReturnAirbaseSet The SET of @{Core.Set#SET_AIRBASE}s to evaluate where to return to.
|
||||
function AI_BALANCER:ReturnToNearestAirbases( ReturnThresholdRange, ReturnAirbaseSet )
|
||||
|
||||
self.ToNearestAirbase = true
|
||||
@@ -152,9 +154,9 @@ function AI_BALANCER:ReturnToNearestAirbases( ReturnThresholdRange, ReturnAirbas
|
||||
self.ReturnAirbaseSet = ReturnAirbaseSet
|
||||
end
|
||||
|
||||
--- Returns the AI to the home @{Airbase#AIRBASE}.
|
||||
--- Returns the AI to the home @{Wrapper.Airbase#AIRBASE}.
|
||||
-- @param #AI_BALANCER self
|
||||
-- @param Dcs.DCSTypes#Distance ReturnThresholdRange If there is an enemy @{Client#CLIENT} within the ReturnThresholdRange given in meters, the AI will not return to the nearest @{Airbase#AIRBASE}.
|
||||
-- @param DCS#Distance ReturnThresholdRange If there is an enemy @{Wrapper.Client#CLIENT} within the ReturnThresholdRange given in meters, the AI will not return to the nearest @{Wrapper.Airbase#AIRBASE}.
|
||||
function AI_BALANCER:ReturnToHomeAirbase( ReturnThresholdRange )
|
||||
|
||||
self.ToHomeAirbase = true
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
--- **AI** -- (R2.1) - Manages the independent process of Combat Air Patrol (CAP) for airplanes.
|
||||
--- **AI** -- Perform Combat Air Patrolling (CAP) for airplanes.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- 
|
||||
-- **Features:**
|
||||
--
|
||||
-- * Patrol AI airplanes within a given zone.
|
||||
-- * Trigger detected events when enemy airplanes are detected.
|
||||
-- * Manage a fuel treshold to RTB on time.
|
||||
-- * Engage the enemy when detected.
|
||||
--
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master-release/CAP%20-%20Combat%20Air%20Patrol)
|
||||
@@ -25,23 +29,22 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module AI_Cap
|
||||
-- @module AI.AI_Cap
|
||||
-- @image AI_Combat_Air_Patrol.JPG
|
||||
|
||||
|
||||
--- @type AI_CAP_ZONE
|
||||
-- @field Wrapper.Controllable#CONTROLLABLE AIControllable The @{Controllable} patrolling.
|
||||
-- @field Wrapper.Controllable#CONTROLLABLE AIControllable The @{Wrapper.Controllable} patrolling.
|
||||
-- @field Core.Zone#ZONE_BASE TargetZone The @{Zone} where the patrol needs to be executed.
|
||||
-- @extends AI.AI_Patrol#AI_PATROL_ZONE
|
||||
|
||||
|
||||
--- # AI_CAP_ZONE class, extends @{AI_CAP#AI_PATROL_ZONE}
|
||||
--
|
||||
-- The AI_CAP_ZONE class implements the core functions to patrol a @{Zone} by an AI @{Controllable} or @{Group}
|
||||
--- Implements the core functions to patrol a @{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.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- The AI_CAP_ZONE is assigned a @{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.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
@@ -84,15 +87,15 @@
|
||||
--
|
||||
-- ### 2.2 AI_CAP_ZONE Events
|
||||
--
|
||||
-- * **@{AI_Patrol#AI_PATROL_ZONE.Start}**: Start the process.
|
||||
-- * **@{AI_Patrol#AI_PATROL_ZONE.Route}**: Route the AI to a new random 3D point within the Patrol Zone.
|
||||
-- * **@{AI.AI_Patrol#AI_PATROL_ZONE.Start}**: Start the process.
|
||||
-- * **@{AI.AI_Patrol#AI_PATROL_ZONE.Route}**: Route the AI to a new random 3D point within the Patrol Zone.
|
||||
-- * **@{#AI_CAP_ZONE.Engage}**: Let the AI engage the bogeys.
|
||||
-- * **@{#AI_CAP_ZONE.Abort}**: Aborts the engagement and return patrolling in the patrol zone.
|
||||
-- * **@{AI_Patrol#AI_PATROL_ZONE.RTB}**: Route the AI to the home base.
|
||||
-- * **@{AI_Patrol#AI_PATROL_ZONE.Detect}**: The AI is detecting targets.
|
||||
-- * **@{AI_Patrol#AI_PATROL_ZONE.Detected}**: The AI has detected new targets.
|
||||
-- * **@{#AI_CAP_ZONE.Destroy}**: The AI has destroyed a bogey @{Unit}.
|
||||
-- * **@{#AI_CAP_ZONE.Destroyed}**: The AI has destroyed all bogeys @{Unit}s assigned in the CAS task.
|
||||
-- * **@{AI.AI_Patrol#AI_PATROL_ZONE.RTB}**: Route the AI to the home base.
|
||||
-- * **@{AI.AI_Patrol#AI_PATROL_ZONE.Detect}**: The AI is detecting targets.
|
||||
-- * **@{AI.AI_Patrol#AI_PATROL_ZONE.Detected}**: The AI has detected new targets.
|
||||
-- * **@{#AI_CAP_ZONE.Destroy}**: The AI has destroyed a bogey @{Wrapper.Unit}.
|
||||
-- * **@{#AI_CAP_ZONE.Destroyed}**: The AI has destroyed all bogeys @{Wrapper.Unit}s assigned in the CAS task.
|
||||
-- * **Status** ( Group ): The AI is checking status (fuel and damage). When the tresholds have been reached, the AI will RTB.
|
||||
--
|
||||
-- ## 3. Set the Range of Engagement
|
||||
@@ -103,7 +106,7 @@
|
||||
-- that will define when the AI will engage with the detected airborne enemy targets.
|
||||
-- The range can be beyond or smaller than the range of the Patrol Zone.
|
||||
-- The range is applied at the position of the AI.
|
||||
-- Use the method @{AI_CAP#AI_CAP_ZONE.SetEngageRange}() to define that range.
|
||||
-- Use the method @{AI.AI_CAP#AI_CAP_ZONE.SetEngageRange}() to define that range.
|
||||
--
|
||||
-- ## 4. Set the Zone of Engagement
|
||||
--
|
||||
@@ -111,7 +114,7 @@
|
||||
--
|
||||
-- An optional @{Zone} can be set,
|
||||
-- that will define when the AI will engage with the detected airborne enemy targets.
|
||||
-- Use the method @{AI_Cap#AI_CAP_ZONE.SetEngageZone}() to define that Zone.
|
||||
-- Use the method @{AI.AI_Cap#AI_CAP_ZONE.SetEngageZone}() to define that Zone.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
@@ -125,11 +128,11 @@ AI_CAP_ZONE = {
|
||||
--- Creates a new AI_CAP_ZONE object
|
||||
-- @param #AI_CAP_ZONE self
|
||||
-- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed.
|
||||
-- @param Dcs.DCSTypes#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
|
||||
-- @param Dcs.DCSTypes#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
|
||||
-- @param Dcs.DCSTypes#Speed PatrolMinSpeed The minimum speed of the @{Controllable} in km/h.
|
||||
-- @param Dcs.DCSTypes#Speed PatrolMaxSpeed The maximum speed of the @{Controllable} in km/h.
|
||||
-- @param Dcs.DCSTypes#AltitudeType PatrolAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to RADIO
|
||||
-- @param DCS#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
|
||||
-- @param DCS#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
|
||||
-- @param DCS#Speed PatrolMinSpeed The minimum speed of the @{Wrapper.Controllable} in km/h.
|
||||
-- @param DCS#Speed PatrolMaxSpeed The maximum speed of the @{Wrapper.Controllable} in km/h.
|
||||
-- @param DCS#AltitudeType PatrolAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to RADIO
|
||||
-- @return #AI_CAP_ZONE self
|
||||
function AI_CAP_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType )
|
||||
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
--- **AI** -- (R2.1) - Manages the independent process of Close Air Support for airplanes.
|
||||
--- **AI** -- Perform Close Air Support (CAS) near friendlies.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- 
|
||||
-- **Features:**
|
||||
--
|
||||
-- * Hold and standby within a patrol zone.
|
||||
-- * Engage upon command the enemies within an engagement zone.
|
||||
-- * Loop the zone until all enemies are eliminated.
|
||||
-- * Trigger different events upon the results achieved.
|
||||
-- * After combat, return to the patrol zone and hold.
|
||||
-- * RTB when commanded or after fuel.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master-release/CAS%20-%20Close%20Air%20Support)
|
||||
@@ -23,25 +28,21 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module AI_Cas
|
||||
|
||||
-- @module AI.AI_Cas
|
||||
-- @image AI_Close_Air_Support.JPG
|
||||
|
||||
--- AI_CAS_ZONE class
|
||||
-- @type AI_CAS_ZONE
|
||||
-- @field Wrapper.Controllable#CONTROLLABLE AIControllable The @{Controllable} patrolling.
|
||||
-- @field Wrapper.Controllable#CONTROLLABLE AIControllable The @{Wrapper.Controllable} patrolling.
|
||||
-- @field Core.Zone#ZONE_BASE TargetZone The @{Zone} where the patrol needs to be executed.
|
||||
-- @extends AI.AI_Patrol#AI_PATROL_ZONE
|
||||
|
||||
--- # AI_CAS_ZONE class, extends @{AI_Patrol#AI_PATROL_ZONE}
|
||||
--
|
||||
-- AI_CAS_ZONE derives from the @{AI_Patrol#AI_PATROL_ZONE}, inheriting its methods and behaviour.
|
||||
--
|
||||
-- The AI_CAS_ZONE class implements the core functions to provide Close Air Support in an Engage @{Zone} by an AIR @{Controllable} or @{Group}.
|
||||
--- Implements the core functions to provide Close Air Support in an Engage @{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 is assigned a @{Group} and this must be done before the AI_CAS_ZONE process can be started through the **Start** event.
|
||||
-- The AI_CAS_ZONE is assigned a @{Wrapper.Group} and this must be done before the AI_CAS_ZONE process can be started through the **Start** event.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
@@ -107,15 +108,15 @@
|
||||
--
|
||||
-- ### 2.2. AI_CAS_ZONE Events
|
||||
--
|
||||
-- * **@{AI_Patrol#AI_PATROL_ZONE.Start}**: Start the process.
|
||||
-- * **@{AI_Patrol#AI_PATROL_ZONE.Route}**: Route the AI to a new random 3D point within the Patrol Zone.
|
||||
-- * **@{AI.AI_Patrol#AI_PATROL_ZONE.Start}**: Start the process.
|
||||
-- * **@{AI.AI_Patrol#AI_PATROL_ZONE.Route}**: Route the AI to a new random 3D point within the Patrol Zone.
|
||||
-- * **@{#AI_CAS_ZONE.Engage}**: Engage the AI to provide CAS in the Engage Zone, destroying any target it finds.
|
||||
-- * **@{#AI_CAS_ZONE.Abort}**: Aborts the engagement and return patrolling in the patrol zone.
|
||||
-- * **@{AI_Patrol#AI_PATROL_ZONE.RTB}**: Route the AI to the home base.
|
||||
-- * **@{AI_Patrol#AI_PATROL_ZONE.Detect}**: The AI is detecting targets.
|
||||
-- * **@{AI_Patrol#AI_PATROL_ZONE.Detected}**: The AI has detected new targets.
|
||||
-- * **@{#AI_CAS_ZONE.Destroy}**: The AI has destroyed a target @{Unit}.
|
||||
-- * **@{#AI_CAS_ZONE.Destroyed}**: The AI has destroyed all target @{Unit}s assigned in the CAS task.
|
||||
-- * **@{AI.AI_Patrol#AI_PATROL_ZONE.RTB}**: Route the AI to the home base.
|
||||
-- * **@{AI.AI_Patrol#AI_PATROL_ZONE.Detect}**: The AI is detecting targets.
|
||||
-- * **@{AI.AI_Patrol#AI_PATROL_ZONE.Detected}**: The AI has detected new targets.
|
||||
-- * **@{#AI_CAS_ZONE.Destroy}**: The AI has destroyed a target @{Wrapper.Unit}.
|
||||
-- * **@{#AI_CAS_ZONE.Destroyed}**: The AI has destroyed all target @{Wrapper.Unit}s assigned in the CAS task.
|
||||
-- * **Status**: The AI is checking status (fuel and damage). When the tresholds have been reached, the AI will RTB.
|
||||
--
|
||||
-- ===
|
||||
@@ -130,12 +131,12 @@ AI_CAS_ZONE = {
|
||||
--- Creates a new AI_CAS_ZONE object
|
||||
-- @param #AI_CAS_ZONE self
|
||||
-- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed.
|
||||
-- @param Dcs.DCSTypes#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
|
||||
-- @param Dcs.DCSTypes#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
|
||||
-- @param Dcs.DCSTypes#Speed PatrolMinSpeed The minimum speed of the @{Controllable} in km/h.
|
||||
-- @param Dcs.DCSTypes#Speed PatrolMaxSpeed The maximum speed of the @{Controllable} in km/h.
|
||||
-- @param DCS#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
|
||||
-- @param DCS#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
|
||||
-- @param DCS#Speed PatrolMinSpeed The minimum speed of the @{Wrapper.Controllable} in km/h.
|
||||
-- @param DCS#Speed PatrolMaxSpeed The maximum speed of the @{Wrapper.Controllable} in km/h.
|
||||
-- @param Core.Zone#ZONE_BASE EngageZone The zone where the engage will happen.
|
||||
-- @param Dcs.DCSTypes#AltitudeType PatrolAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to RADIO
|
||||
-- @param DCS#AltitudeType PatrolAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to RADIO
|
||||
-- @return #AI_CAS_ZONE self
|
||||
function AI_CAS_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, EngageZone, PatrolAltType )
|
||||
|
||||
@@ -171,24 +172,24 @@ function AI_CAS_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude
|
||||
-- @function [parent=#AI_CAS_ZONE] Engage
|
||||
-- @param #AI_CAS_ZONE self
|
||||
-- @param #number EngageSpeed (optional) The speed the Group will hold when engaging to the target zone.
|
||||
-- @param Dcs.DCSTypes#Distance EngageAltitude (optional) Desired altitude to perform the unit engagement.
|
||||
-- @param Dcs.DCSTypes#AI.Task.WeaponExpend EngageWeaponExpend (optional) Determines how much weapon will be released at each attack.
|
||||
-- @param DCS#Distance EngageAltitude (optional) Desired altitude to perform the unit engagement.
|
||||
-- @param DCS#AI.Task.WeaponExpend EngageWeaponExpend (optional) Determines how much weapon will be released at each attack.
|
||||
-- If parameter is not defined the unit / controllable will choose expend on its own discretion.
|
||||
-- Use the structure @{DCSTypes#AI.Task.WeaponExpend} to define the amount of weapons to be release at each attack.
|
||||
-- Use the structure @{DCS#AI.Task.WeaponExpend} to define the amount of weapons to be release at each attack.
|
||||
-- @param #number EngageAttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo.
|
||||
-- @param Dcs.DCSTypes#Azimuth EngageDirection (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
|
||||
-- @param DCS#Azimuth EngageDirection (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
|
||||
|
||||
--- Asynchronous Event Trigger for Event Engage.
|
||||
-- @function [parent=#AI_CAS_ZONE] __Engage
|
||||
-- @param #AI_CAS_ZONE self
|
||||
-- @param #number Delay The delay in seconds.
|
||||
-- @param #number EngageSpeed (optional) The speed the Group will hold when engaging to the target zone.
|
||||
-- @param Dcs.DCSTypes#Distance EngageAltitude (optional) Desired altitude to perform the unit engagement.
|
||||
-- @param Dcs.DCSTypes#AI.Task.WeaponExpend EngageWeaponExpend (optional) Determines how much weapon will be released at each attack.
|
||||
-- @param DCS#Distance EngageAltitude (optional) Desired altitude to perform the unit engagement.
|
||||
-- @param DCS#AI.Task.WeaponExpend EngageWeaponExpend (optional) Determines how much weapon will be released at each attack.
|
||||
-- If parameter is not defined the unit / controllable will choose expend on its own discretion.
|
||||
-- Use the structure @{DCSTypes#AI.Task.WeaponExpend} to define the amount of weapons to be release at each attack.
|
||||
-- Use the structure @{DCS#AI.Task.WeaponExpend} to define the amount of weapons to be release at each attack.
|
||||
-- @param #number EngageAttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo.
|
||||
-- @param Dcs.DCSTypes#Azimuth EngageDirection (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
|
||||
-- @param DCS#Azimuth EngageDirection (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
|
||||
|
||||
--- OnLeave Transition Handler for State Engaging.
|
||||
-- @function [parent=#AI_CAS_ZONE] OnLeaveEngaging
|
||||
@@ -430,10 +431,10 @@ end
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
-- @param #number EngageSpeed (optional) The speed the Group will hold when engaging to the target zone.
|
||||
-- @param Dcs.DCSTypes#Distance EngageAltitude (optional) Desired altitude to perform the unit engagement.
|
||||
-- @param Dcs.DCSTypes#AI.Task.WeaponExpend EngageWeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / controllable will choose expend on its own discretion.
|
||||
-- @param DCS#Distance EngageAltitude (optional) Desired altitude to perform the unit engagement.
|
||||
-- @param DCS#AI.Task.WeaponExpend EngageWeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / controllable will choose expend on its own discretion.
|
||||
-- @param #number EngageAttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo.
|
||||
-- @param Dcs.DCSTypes#Azimuth EngageDirection (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
|
||||
-- @param DCS#Azimuth EngageDirection (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.
|
||||
function AI_CAS_ZONE:onafterEngage( Controllable, From, Event, To,
|
||||
EngageSpeed,
|
||||
EngageAltitude,
|
||||
|
||||
486
Moose Development/Moose/AI/AI_Cargo.lua
Normal file
486
Moose Development/Moose/AI/AI_Cargo.lua
Normal file
@@ -0,0 +1,486 @@
|
||||
--- **AI** -- (R2.4) - Models the intelligent transportation of infantry and other cargo.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **FlightControl**
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module AI.AI_Cargo
|
||||
-- @image Cargo.JPG
|
||||
|
||||
--- @type AI_CARGO
|
||||
-- @extends Core.Fsm#FSM_CONTROLLABLE
|
||||
|
||||
|
||||
--- 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.
|
||||
-- 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.
|
||||
-- Please consult the @{Cargo.Cargo} module for more information.
|
||||
--
|
||||
-- The derived classes from this module are:
|
||||
--
|
||||
-- * @{AI.AI_Cargo_APC} - Cargo transportation using APCs and other vehicles between zones.
|
||||
-- * @{AI.AI_Cargo_Helicopter} - Cargo transportation using helicopters between zones.
|
||||
-- * @{AI.AI_Cargo_Airplane} - Cargo transportation using airplanes to and from airbases.
|
||||
--
|
||||
-- @field #AI_CARGO
|
||||
AI_CARGO = {
|
||||
ClassName = "AI_CARGO",
|
||||
Coordinate = nil, -- Core.Point#COORDINATE,
|
||||
Carrier_Cargo = {},
|
||||
}
|
||||
|
||||
--- Creates a new AI_CARGO object.
|
||||
-- @param #AI_CARGO self
|
||||
-- @param Wrapper.Group#GROUP Carrier
|
||||
-- @param Core.Set#SET_CARGO CargoSet
|
||||
-- @param #number CombatRadius
|
||||
-- @return #AI_CARGO
|
||||
function AI_CARGO:New( Carrier, CargoSet )
|
||||
|
||||
local self = BASE:Inherit( self, FSM_CONTROLLABLE:New( Carrier ) ) -- #AI_CARGO
|
||||
|
||||
self.CargoSet = CargoSet -- Core.Set#SET_CARGO
|
||||
self.CargoCarrier = Carrier -- Wrapper.Group#GROUP
|
||||
|
||||
self:SetStartState( "Unloaded" )
|
||||
|
||||
self:AddTransition( "Unloaded", "Pickup", "*" )
|
||||
self:AddTransition( "Loaded", "Deploy", "*" )
|
||||
|
||||
self:AddTransition( "*", "Load", "Boarding" )
|
||||
self:AddTransition( { "Boarding", "Loaded" }, "Board", "Boarding" )
|
||||
self:AddTransition( "Boarding", "Loaded", "Boarding" )
|
||||
self:AddTransition( "Boarding", "PickedUp", "Loaded" )
|
||||
|
||||
self:AddTransition( "Loaded", "Unload", "Unboarding" )
|
||||
self:AddTransition( "Unboarding", "Unboard", "Unboarding" )
|
||||
self:AddTransition( "Unboarding", "Unloaded", "Unboarding" )
|
||||
self:AddTransition( "Unboarding", "Deployed", "Unloaded" )
|
||||
|
||||
--- Pickup Handler OnBefore for AI_CARGO
|
||||
-- @function [parent=#AI_CARGO] OnBeforePickup
|
||||
-- @param #AI_CARGO self
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @param Core.Point#COORDINATE Coordinate
|
||||
-- @param #number Speed Speed in km/h. Default is 50% of max possible speed the group can do.
|
||||
-- @return #boolean
|
||||
|
||||
--- Pickup Handler OnAfter for AI_CARGO
|
||||
-- @function [parent=#AI_CARGO] OnAfterPickup
|
||||
-- @param #AI_CARGO self
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @param Core.Point#COORDINATE Coordinate
|
||||
-- @param #number Speed Speed in km/h. Default is 50% of max possible speed the group can do.
|
||||
|
||||
--- Pickup Trigger for AI_CARGO
|
||||
-- @function [parent=#AI_CARGO] Pickup
|
||||
-- @param #AI_CARGO self
|
||||
-- @param Core.Point#COORDINATE Coordinate
|
||||
-- @param #number Speed Speed in km/h. Default is 50% of max possible speed the group can do.
|
||||
|
||||
--- Pickup Asynchronous Trigger for AI_CARGO
|
||||
-- @function [parent=#AI_CARGO] __Pickup
|
||||
-- @param #AI_CARGO self
|
||||
-- @param #number Delay
|
||||
-- @param Core.Point#COORDINATE Coordinate Pickup place. If not given, loading starts at the current location.
|
||||
-- @param #number Speed Speed in km/h. Default is 50% of max possible speed the group can do.
|
||||
|
||||
--- Deploy Handler OnBefore for AI_CARGO
|
||||
-- @function [parent=#AI_CARGO] OnBeforeDeploy
|
||||
-- @param #AI_CARGO self
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @param Core.Point#COORDINATE Coordinate
|
||||
-- @param #number Speed Speed in km/h. Default is 50% of max possible speed the group can do.
|
||||
-- @return #boolean
|
||||
|
||||
--- Deploy Handler OnAfter for AI_CARGO
|
||||
-- @function [parent=#AI_CARGO] OnAfterDeploy
|
||||
-- @param #AI_CARGO self
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @param Core.Point#COORDINATE Coordinate
|
||||
-- @param #number Speed Speed in km/h. Default is 50% of max possible speed the group can do.
|
||||
|
||||
--- Deploy Trigger for AI_CARGO
|
||||
-- @function [parent=#AI_CARGO] Deploy
|
||||
-- @param #AI_CARGO self
|
||||
-- @param Core.Point#COORDINATE Coordinate
|
||||
-- @param #number Speed Speed in km/h. Default is 50% of max possible speed the group can do.
|
||||
|
||||
--- Deploy Asynchronous Trigger for AI_CARGO
|
||||
-- @function [parent=#AI_CARGO] __Deploy
|
||||
-- @param #AI_CARGO self
|
||||
-- @param #number Delay
|
||||
-- @param Core.Point#COORDINATE Coordinate
|
||||
-- @param #number Speed Speed in km/h. Default is 50% of max possible speed the group can do.
|
||||
|
||||
|
||||
--- Loaded Handler OnAfter for AI_CARGO
|
||||
-- @function [parent=#AI_CARGO] OnAfterLoaded
|
||||
-- @param #AI_CARGO self
|
||||
-- @param Wrapper.Group#GROUP Carrier
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
|
||||
--- Unloaded Handler OnAfter for AI_CARGO
|
||||
-- @function [parent=#AI_CARGO] OnAfterUnloaded
|
||||
-- @param #AI_CARGO self
|
||||
-- @param Wrapper.Group#GROUP Carrier
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
|
||||
for _, CarrierUnit in pairs( Carrier:GetUnits() ) do
|
||||
local CarrierUnit = CarrierUnit -- Wrapper.Unit#UNIT
|
||||
CarrierUnit:SetCargoBayWeightLimit()
|
||||
end
|
||||
|
||||
self.Transporting = false
|
||||
self.Relocating = false
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
|
||||
function AI_CARGO:IsTransporting()
|
||||
|
||||
return self.Transporting == true
|
||||
end
|
||||
|
||||
function AI_CARGO:IsRelocating()
|
||||
|
||||
return self.Relocating == true
|
||||
end
|
||||
|
||||
|
||||
--- On after Pickup event.
|
||||
-- @param #AI_CARGO self
|
||||
-- @param Wrapper.Group#GROUP APC
|
||||
-- @param From
|
||||
-- @param Event
|
||||
-- @param To
|
||||
-- @param Core.Point#COORDINATE Coordinate of the pickup point.
|
||||
-- @param #number Speed Speed in km/h to drive to the pickup coordinate. Default is 50% of max possible speed the unit can go.
|
||||
-- @param #number Height Height in meters to move to the home coordinate.
|
||||
-- @param Core.Zone#ZONE PickupZone (optional) The zone where the cargo will be picked up. The PickupZone can be nil, if there wasn't any PickupZoneSet provided.
|
||||
function AI_CARGO:onafterPickup( APC, From, Event, To, Coordinate, Speed, Height, PickupZone )
|
||||
|
||||
self.Transporting = false
|
||||
self.Relocating = true
|
||||
|
||||
end
|
||||
|
||||
|
||||
--- On after Deploy event.
|
||||
-- @param #AI_CARGO self
|
||||
-- @param Wrapper.Group#GROUP APC
|
||||
-- @param From
|
||||
-- @param Event
|
||||
-- @param To
|
||||
-- @param Core.Point#COORDINATE Coordinate Deploy place.
|
||||
-- @param #number Speed Speed in km/h to drive to the depoly coordinate. Default is 50% of max possible speed the unit can go.
|
||||
-- @param #number Height Height in meters to move to the deploy coordinate.
|
||||
-- @param Core.Zone#ZONE DeployZone The zone where the cargo will be deployed.
|
||||
function AI_CARGO:onafterDeploy( APC, From, Event, To, Coordinate, Speed, Height, DeployZone )
|
||||
|
||||
self.Relocating = false
|
||||
self.Transporting = true
|
||||
|
||||
end
|
||||
|
||||
--- On before Load event.
|
||||
-- @param #AI_CARGO self
|
||||
-- @param Wrapper.Group#GROUP Carrier
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Core.Zone#ZONE PickupZone (optional) The zone where the cargo will be picked up. The PickupZone can be nil, if there wasn't any PickupZoneSet provided.
|
||||
function AI_CARGO:onbeforeLoad( Carrier, From, Event, To, PickupZone )
|
||||
self:F( { Carrier, From, Event, To } )
|
||||
|
||||
local Boarding = false
|
||||
|
||||
local LoadInterval = 5
|
||||
local LoadDelay = 0
|
||||
local Carrier_List = {}
|
||||
local Carrier_Weight = {}
|
||||
|
||||
if Carrier and Carrier:IsAlive() then
|
||||
self.Carrier_Cargo = {}
|
||||
for _, CarrierUnit in pairs( Carrier:GetUnits() ) do
|
||||
local CarrierUnit = CarrierUnit -- Wrapper.Unit#UNIT
|
||||
|
||||
local CargoBayFreeWeight = CarrierUnit:GetCargoBayFreeWeight()
|
||||
self:F({CargoBayFreeWeight=CargoBayFreeWeight})
|
||||
|
||||
Carrier_List[#Carrier_List+1] = CarrierUnit
|
||||
Carrier_Weight[CarrierUnit] = CargoBayFreeWeight
|
||||
end
|
||||
|
||||
local Carrier_Count = #Carrier_List
|
||||
local Carrier_Index = 1
|
||||
|
||||
local Loaded = false
|
||||
|
||||
for _, Cargo in UTILS.spairs( self.CargoSet:GetSet(), function( t, a, b ) return t[a]:GetWeight() > t[b]:GetWeight() end ) do
|
||||
local Cargo = Cargo -- Cargo.Cargo#CARGO
|
||||
|
||||
self:F( { IsUnLoaded = Cargo:IsUnLoaded(), IsDeployed = Cargo:IsDeployed(), Cargo:GetName(), Carrier:GetName() } )
|
||||
|
||||
-- Try all Carriers, but start from the one according the Carrier_Index
|
||||
for Carrier_Loop = 1, #Carrier_List do
|
||||
|
||||
local CarrierUnit = Carrier_List[Carrier_Index] -- Wrapper.Unit#UNIT
|
||||
|
||||
-- This counters loop through the available Carriers.
|
||||
Carrier_Index = Carrier_Index + 1
|
||||
if Carrier_Index > Carrier_Count then
|
||||
Carrier_Index = 1
|
||||
end
|
||||
|
||||
if Cargo:IsUnLoaded() and not Cargo:IsDeployed() then
|
||||
if Cargo:IsInLoadRadius( CarrierUnit:GetCoordinate() ) then
|
||||
self:F( { "In radius", CarrierUnit:GetName() } )
|
||||
|
||||
local CargoWeight = Cargo:GetWeight()
|
||||
|
||||
-- Only when there is space within the bay to load the next cargo item!
|
||||
if Carrier_Weight[CarrierUnit] > CargoWeight then --and CargoBayFreeVolume > CargoVolume then
|
||||
Carrier:RouteStop()
|
||||
--Cargo:Ungroup()
|
||||
Cargo:__Board( -LoadDelay, CarrierUnit )
|
||||
LoadDelay = LoadDelay + Cargo:GetCount() * LoadInterval
|
||||
self:__Board( LoadDelay, Cargo, CarrierUnit, PickupZone )
|
||||
|
||||
-- So now this CarrierUnit has Cargo that is being loaded.
|
||||
-- This will be used further in the logic to follow and to check cargo status.
|
||||
self.Carrier_Cargo[Cargo] = CarrierUnit
|
||||
Boarding = true
|
||||
Carrier_Weight[CarrierUnit] = Carrier_Weight[CarrierUnit] - CargoWeight
|
||||
Loaded = true
|
||||
|
||||
-- Ok, we loaded a cargo, now we can stop the loop.
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
if not Loaded == true then
|
||||
-- No loading happened, so we need to pickup something else.
|
||||
self.Relocating = false
|
||||
end
|
||||
end
|
||||
|
||||
return Boarding
|
||||
|
||||
end
|
||||
|
||||
--- On after Board event.
|
||||
-- @param #AI_CARGO self
|
||||
-- @param Wrapper.Group#GROUP Carrier
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Cargo.Cargo#CARGO Cargo Cargo object.
|
||||
-- @param Wrapper.Unit#UNIT CarrierUnit
|
||||
-- @param Core.Zone#ZONE PickupZone (optional) The zone where the cargo will be picked up. The PickupZone can be nil, if there wasn't any PickupZoneSet provided.
|
||||
function AI_CARGO:onafterBoard( Carrier, From, Event, To, Cargo, CarrierUnit, PickupZone )
|
||||
self:F( { Carrier, From, Event, To, Cargo, CarrierUnit:GetName() } )
|
||||
|
||||
if Carrier and Carrier:IsAlive() then
|
||||
self:F({ IsLoaded = Cargo:IsLoaded(), Cargo:GetName(), Carrier:GetName() } )
|
||||
if not Cargo:IsLoaded() then
|
||||
self:__Board( -10, Cargo, CarrierUnit, PickupZone )
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
self:__Loaded( 0.1, Cargo, CarrierUnit, PickupZone )
|
||||
|
||||
end
|
||||
|
||||
--- On after Loaded event.
|
||||
-- @param #AI_CARGO self
|
||||
-- @param Wrapper.Group#GROUP Carrier
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @return #boolean Cargo loaded.
|
||||
-- @param Core.Zone#ZONE PickupZone (optional) The zone where the cargo will be picked up. The PickupZone can be nil, if there wasn't any PickupZoneSet provided.
|
||||
function AI_CARGO:onafterLoaded( Carrier, From, Event, To, Cargo, PickupZone )
|
||||
self:F( { Carrier, From, Event, To } )
|
||||
|
||||
local Loaded = true
|
||||
|
||||
if Carrier and Carrier:IsAlive() then
|
||||
for Cargo, CarrierUnit in pairs( self.Carrier_Cargo ) do
|
||||
local Cargo = Cargo -- Cargo.Cargo#CARGO
|
||||
self:F( { IsLoaded = Cargo:IsLoaded(), IsDestroyed = Cargo:IsDestroyed(), Cargo:GetName(), Carrier:GetName() } )
|
||||
if not Cargo:IsLoaded() and not Cargo:IsDestroyed() then
|
||||
Loaded = false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if Loaded then
|
||||
self:__PickedUp( 0.1, PickupZone )
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- On after PickedUp event.
|
||||
-- @param #AI_CARGO self
|
||||
-- @param Wrapper.Group#GROUP Carrier
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Core.Zone#ZONE PickupZone (optional) The zone where the cargo will be picked up. The PickupZone can be nil, if there wasn't any PickupZoneSet provided.
|
||||
function AI_CARGO:onafterPickedUp( Carrier, From, Event, To, PickupZone )
|
||||
self:F( { Carrier, From, Event, To } )
|
||||
|
||||
Carrier:RouteResume()
|
||||
|
||||
local HasCargo = false
|
||||
if Carrier and Carrier :IsAlive() then
|
||||
for Cargo, CarrierUnit in pairs( self.Carrier_Cargo ) do
|
||||
HasCargo = true
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
self.Relocating = false
|
||||
if HasCargo then
|
||||
self.Transporting = true
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
--- On after Unload event.
|
||||
-- @param #AI_CARGO self
|
||||
-- @param Wrapper.Group#GROUP Carrier
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Core.Zone#ZONE DeployZone The zone wherein the cargo is deployed. This can be any zone type, like a ZONE, ZONE_GROUP, ZONE_AIRBASE.
|
||||
function AI_CARGO:onafterUnload( Carrier, From, Event, To, DeployZone )
|
||||
self:F( { Carrier, From, Event, To, DeployZone } )
|
||||
|
||||
local UnboardInterval = 10
|
||||
local UnboardDelay = 10
|
||||
|
||||
if Carrier and Carrier:IsAlive() then
|
||||
for _, CarrierUnit in pairs( Carrier:GetUnits() ) do
|
||||
local CarrierUnit = CarrierUnit -- Wrapper.Unit#UNIT
|
||||
Carrier:RouteStop()
|
||||
for _, Cargo in pairs( CarrierUnit:GetCargo() ) do
|
||||
self:F( { Cargo = Cargo:GetName(), Isloaded = Cargo:IsLoaded() } )
|
||||
if Cargo:IsLoaded() then
|
||||
Cargo:__UnBoard( UnboardDelay )
|
||||
UnboardDelay = UnboardDelay + Cargo:GetCount() * UnboardInterval
|
||||
Cargo:SetDeployed( true )
|
||||
self:__Unboard( UnboardDelay, Cargo, CarrierUnit, DeployZone )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- On after Unboard event.
|
||||
-- @param #AI_CARGO self
|
||||
-- @param Wrapper.Group#GROUP Carrier
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param #string Cargo.Cargo#CARGO Cargo Cargo object.
|
||||
-- @param Core.Zone#ZONE DeployZone The zone wherein the cargo is deployed. This can be any zone type, like a ZONE, ZONE_GROUP, ZONE_AIRBASE.
|
||||
function AI_CARGO:onafterUnboard( Carrier, From, Event, To, Cargo, CarrierUnit, DeployZone )
|
||||
self:F( { Carrier, From, Event, To, Cargo:GetName() } )
|
||||
|
||||
if Carrier and Carrier:IsAlive() then
|
||||
if not Cargo:IsUnLoaded() then
|
||||
self:__Unboard( 10, Cargo, CarrierUnit, DeployZone )
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
self:Unloaded( Cargo, CarrierUnit, DeployZone )
|
||||
|
||||
end
|
||||
|
||||
--- On after Unloaded event.
|
||||
-- @param #AI_CARGO self
|
||||
-- @param Wrapper.Group#GROUP Carrier
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param #string Cargo.Cargo#CARGO Cargo Cargo object.
|
||||
-- @param #boolean Deployed Cargo is deployed.
|
||||
-- @param Core.Zone#ZONE DeployZone The zone wherein the cargo is deployed. This can be any zone type, like a ZONE, ZONE_GROUP, ZONE_AIRBASE.
|
||||
function AI_CARGO:onafterUnloaded( Carrier, From, Event, To, Cargo, CarrierUnit, DeployZone )
|
||||
self:F( { Carrier, From, Event, To, Cargo:GetName(), DeployZone = DeployZone } )
|
||||
|
||||
local AllUnloaded = true
|
||||
|
||||
--Cargo:Regroup()
|
||||
|
||||
if Carrier and Carrier:IsAlive() then
|
||||
for _, CarrierUnit in pairs( Carrier:GetUnits() ) do
|
||||
local CarrierUnit = CarrierUnit -- Wrapper.Unit#UNIT
|
||||
local IsEmpty = CarrierUnit:IsCargoEmpty()
|
||||
self:I({ IsEmpty = IsEmpty })
|
||||
if not IsEmpty then
|
||||
AllUnloaded = false
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if AllUnloaded == true then
|
||||
if DeployZone == true then
|
||||
self.Carrier_Cargo = {}
|
||||
end
|
||||
self.CargoCarrier = Carrier
|
||||
end
|
||||
end
|
||||
|
||||
if AllUnloaded == true then
|
||||
self:__Deployed( 5, DeployZone )
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- On after Deployed event.
|
||||
-- @param #AI_CARGO self
|
||||
-- @param Wrapper.Group#GROUP Carrier
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Core.Zone#ZONE DeployZone The zone wherein the cargo is deployed. This can be any zone type, like a ZONE, ZONE_GROUP, ZONE_AIRBASE.
|
||||
function AI_CARGO:onafterDeployed( Carrier, From, Event, To, DeployZone )
|
||||
self:F( { Carrier, From, Event, To, DeployZone = DeployZone } )
|
||||
|
||||
self.Transporting = false
|
||||
|
||||
end
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
--- **AI** -- (R2.3) - Models the intelligent transportation of infantry and other cargo.
|
||||
--- **AI** -- (R2.4) - Models the intelligent transportation of infantry and other cargo.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
@@ -6,30 +6,30 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module AI_Cargo_APC
|
||||
-- @module AI.AI_Cargo_APC
|
||||
-- @image AI_Cargo_Dispatching_For_APC.JPG
|
||||
|
||||
--- @type AI_CARGO_APC
|
||||
-- @extends Core.Fsm#FSM_CONTROLLABLE
|
||||
-- @extends AI.AI_Cargo#AI_CARGO
|
||||
|
||||
|
||||
--- # AI\_CARGO\_APC class, extends @{Core.Base#BASE}
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- AI\_CARGO\APC brings a dynamic cargo handling capability for AI groups.
|
||||
--- 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.
|
||||
-- The AI\_CARGO\APC module uses the @{Cargo} capabilities within the MOOSE framework.
|
||||
-- CARGO derived objects must be declared within the mission to make the AI\_CARGO\APC object recognize the cargo.
|
||||
-- Please consult the @{Cargo} module for more information.
|
||||
--
|
||||
-- The AI_CARGO_APC class uses the @{Cargo.Cargo} capabilities within the MOOSE framework.
|
||||
-- @{Cargo.Cargo} must be declared within the mission to make the AI_CARGO_APC object recognize the cargo.
|
||||
-- Please consult the @{Cargo.Cargo} module for more information.
|
||||
--
|
||||
-- ## Cargo loading.
|
||||
--
|
||||
-- The module will load automatically cargo when the APCs are within boarding or loading range.
|
||||
-- The boarding or loading range is specified when the cargo is created in the simulation, and therefore, this range depends on the type of cargo
|
||||
-- and the specified boarding range.
|
||||
-- The module will load automatically cargo when the APCs are within boarding or loading radius.
|
||||
-- The boarding or loading radius is specified when the cargo is created in the simulation, and therefore, this radius depends on the type of cargo
|
||||
-- and the specified boarding radius.
|
||||
--
|
||||
-- ## Enemies nearby.
|
||||
-- ## **Defending** the APCs when enemies nearby.
|
||||
--
|
||||
-- Cargo will defend the carrier with its available arms, and to avoid cargo being lost within the battlefield.
|
||||
--
|
||||
-- When the APCs are approaching enemy units, something special is happening.
|
||||
-- The APCs will stop moving, and the loaded infantry will unboard and follow the APCs and will help to defend the group.
|
||||
@@ -37,13 +37,17 @@
|
||||
-- to ensure that the APCs are not too far away from the following running infantry.
|
||||
-- Once all enemies are cleared, the infantry will board again automatically into the APCs. Once boarded, the APCs will follow its pre-defined route.
|
||||
--
|
||||
-- A combat range needs to be specified in meters at the @{#AI_CARGO_APC.New}() method.
|
||||
-- This combat range will trigger the unboarding of troops when enemies are within the combat range around the APCs.
|
||||
-- During my tests, I've noticed that there is a balance between ensuring that the infantry is within sufficient hit range (effectiveness) versus
|
||||
-- A combat radius needs to be specified in meters at the @{#AI_CARGO_APC.New}() method.
|
||||
-- This combat radius will trigger the unboarding of troops when enemies are within the combat radius around the APCs.
|
||||
-- During my tests, I've noticed that there is a balance between ensuring that the infantry is within sufficient hit radius (effectiveness) versus
|
||||
-- vulnerability of the infantry. It all depends on the kind of enemies that are expected to be encountered.
|
||||
-- A combat range of 350 meters to 500 meters has been proven to be the most effective and efficient.
|
||||
-- A combat radius of 350 meters to 500 meters has been proven to be the most effective and efficient.
|
||||
--
|
||||
-- ## Infantry health.
|
||||
-- However, when the defense of the carrier, is not required, it must be switched off.
|
||||
-- This is done by disabling the defense of the carrier using the method @{#AI_CARGO_APC.SetCombatRadius}(), and providing a combat radius of 0 meters.
|
||||
-- It can be switched on later when required by reenabling the defense using the method and providing a combat radius larger than 0.
|
||||
--
|
||||
-- ## Infantry or cargo **health**.
|
||||
--
|
||||
-- When infantry is unboarded from the APCs, the infantry is actually respawned into the battlefield.
|
||||
-- As a result, the unboarding infantry is very _healthy_ every time it unboards.
|
||||
@@ -77,34 +81,18 @@
|
||||
AI_CARGO_APC = {
|
||||
ClassName = "AI_CARGO_APC",
|
||||
Coordinate = nil, -- Core.Point#COORDINATE,
|
||||
APC_Cargo = {},
|
||||
}
|
||||
|
||||
--- Creates a new AI_CARGO_APC object.
|
||||
-- @param #AI_CARGO_APC self
|
||||
-- @param Wrapper.Group#GROUP CargoCarrier
|
||||
-- @param Core.Set#SET_CARGO CargoSet
|
||||
-- @param #number CombatRadius
|
||||
-- @param Wrapper.Group#GROUP APC The carrier APC group.
|
||||
-- @param Core.Set#SET_CARGO CargoSet The set of cargo to be transported.
|
||||
-- @param #number CombatRadius Provide the combat radius to defend the carrier by unboarding the cargo when enemies are nearby. When the combat radius is 0, no defense will happen of the carrier.
|
||||
-- @return #AI_CARGO_APC
|
||||
function AI_CARGO_APC:New( CargoCarrier, CargoSet, CombatRadius )
|
||||
function AI_CARGO_APC:New( APC, CargoSet, CombatRadius )
|
||||
|
||||
local self = BASE:Inherit( self, FSM_CONTROLLABLE:New() ) -- #AI_CARGO_APC
|
||||
local self = BASE:Inherit( self, AI_CARGO:New( APC, CargoSet ) ) -- #AI_CARGO_APC
|
||||
|
||||
self.CargoSet = CargoSet -- Core.Set#SET_CARGO
|
||||
self.CombatRadius = CombatRadius
|
||||
|
||||
self:SetStartState( "Unloaded" )
|
||||
|
||||
self:AddTransition( "Unloaded", "Pickup", "*" )
|
||||
self:AddTransition( "Loaded", "Deploy", "*" )
|
||||
|
||||
self:AddTransition( "*", "Load", "Boarding" )
|
||||
self:AddTransition( "Boarding", "Board", "Boarding" )
|
||||
self:AddTransition( "Boarding", "Loaded", "Loaded" )
|
||||
self:AddTransition( "Loaded", "Unload", "Unboarding" )
|
||||
self:AddTransition( "Unboarding", "Unboard", "Unboarding" )
|
||||
self:AddTransition( { "Unboarding", "Unloaded" }, "Unloaded", "Unloaded" )
|
||||
|
||||
self:AddTransition( "*", "Monitor", "*" )
|
||||
self:AddTransition( "*", "Follow", "Following" )
|
||||
self:AddTransition( "*", "Guard", "Unloaded" )
|
||||
@@ -112,86 +100,9 @@ function AI_CARGO_APC:New( CargoCarrier, CargoSet, CombatRadius )
|
||||
|
||||
self:AddTransition( "*", "Destroyed", "Destroyed" )
|
||||
|
||||
self:SetCombatRadius( CombatRadius )
|
||||
|
||||
--- Pickup Handler OnBefore for AI_CARGO_APC
|
||||
-- @function [parent=#AI_CARGO_APC] OnBeforePickup
|
||||
-- @param #AI_CARGO_APC self
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @param Core.Point#COORDINATE Coordinate
|
||||
-- @return #boolean
|
||||
|
||||
--- Pickup Handler OnAfter for AI_CARGO_APC
|
||||
-- @function [parent=#AI_CARGO_APC] OnAfterPickup
|
||||
-- @param #AI_CARGO_APC self
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @param Core.Point#COORDINATE Coordinate
|
||||
|
||||
--- Pickup Trigger for AI_CARGO_APC
|
||||
-- @function [parent=#AI_CARGO_APC] Pickup
|
||||
-- @param #AI_CARGO_APC self
|
||||
-- @param Core.Point#COORDINATE Coordinate
|
||||
|
||||
--- Pickup Asynchronous Trigger for AI_CARGO_APC
|
||||
-- @function [parent=#AI_CARGO_APC] __Pickup
|
||||
-- @param #AI_CARGO_APC self
|
||||
-- @param #number Delay
|
||||
-- @param Core.Point#COORDINATE Coordinate
|
||||
|
||||
--- Deploy Handler OnBefore for AI_CARGO_APC
|
||||
-- @function [parent=#AI_CARGO_APC] OnBeforeDeploy
|
||||
-- @param #AI_CARGO_APC self
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @param Core.Point#COORDINATE Coordinate
|
||||
-- @return #boolean
|
||||
|
||||
--- Deploy Handler OnAfter for AI_CARGO_APC
|
||||
-- @function [parent=#AI_CARGO_APC] OnAfterDeploy
|
||||
-- @param #AI_CARGO_APC self
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @param Core.Point#COORDINATE Coordinate
|
||||
|
||||
--- Deploy Trigger for AI_CARGO_APC
|
||||
-- @function [parent=#AI_CARGO_APC] Deploy
|
||||
-- @param #AI_CARGO_APC self
|
||||
-- @param Core.Point#COORDINATE Coordinate
|
||||
|
||||
--- Deploy Asynchronous Trigger for AI_CARGO_APC
|
||||
-- @function [parent=#AI_CARGO_APC] __Deploy
|
||||
-- @param #AI_CARGO_APC self
|
||||
-- @param Core.Point#COORDINATE Coordinate
|
||||
-- @param #number Delay
|
||||
|
||||
|
||||
--- Loaded Handler OnAfter for AI_CARGO_APC
|
||||
-- @function [parent=#AI_CARGO_APC] OnAfterLoaded
|
||||
-- @param #AI_CARGO_APC self
|
||||
-- @param Wrapper.Group#GROUP APC
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
|
||||
--- Unloaded Handler OnAfter for AI_CARGO_APC
|
||||
-- @function [parent=#AI_CARGO_APC] OnAfterUnloaded
|
||||
-- @param #AI_CARGO_APC self
|
||||
-- @param Wrapper.Group#GROUP APC
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
|
||||
|
||||
self:__Monitor( 1 )
|
||||
|
||||
self:SetCarrier( CargoCarrier )
|
||||
self.Transporting = false
|
||||
self.Relocating = false
|
||||
self:SetCarrier( APC )
|
||||
|
||||
return self
|
||||
end
|
||||
@@ -216,7 +127,7 @@ function AI_CARGO_APC:SetCarrier( CargoCarrier )
|
||||
if AICargoTroops then
|
||||
self:F({})
|
||||
if not AICargoTroops:Is( "Loaded" ) then
|
||||
-- There are enemies within combat range. Unload the CargoCarrier.
|
||||
-- There are enemies within combat radius. Unload the CargoCarrier.
|
||||
AICargoTroops:Destroyed()
|
||||
end
|
||||
end
|
||||
@@ -228,7 +139,7 @@ function AI_CARGO_APC:SetCarrier( CargoCarrier )
|
||||
if AICargoTroops then
|
||||
self:F( { OnHitLoaded = AICargoTroops:Is( "Loaded" ) } )
|
||||
if AICargoTroops:Is( "Loaded" ) or AICargoTroops:Is( "Boarding" ) then
|
||||
-- There are enemies within combat range. Unload the CargoCarrier.
|
||||
-- There are enemies within combat radius. Unload the CargoCarrier.
|
||||
AICargoTroops:Unload( false )
|
||||
end
|
||||
end
|
||||
@@ -245,17 +156,7 @@ function AI_CARGO_APC:SetCarrier( CargoCarrier )
|
||||
end
|
||||
|
||||
|
||||
function AI_CARGO_APC:IsTransporting()
|
||||
|
||||
return self.Transporting == true
|
||||
end
|
||||
|
||||
function AI_CARGO_APC:IsRelocating()
|
||||
|
||||
return self.Relocating == true
|
||||
end
|
||||
|
||||
--- Find a free Carrier within a range.
|
||||
--- Find a free Carrier within a radius.
|
||||
-- @param #AI_CARGO_APC self
|
||||
-- @param Core.Point#COORDINATE Coordinate
|
||||
-- @param #number Radius
|
||||
@@ -280,6 +181,30 @@ function AI_CARGO_APC:FindCarrier( Coordinate, Radius )
|
||||
|
||||
end
|
||||
|
||||
--- Enable/Disable unboarding of cargo (infantry) when enemies are nearby (to help defend the carrier).
|
||||
-- This is only valid for APCs and trucks etc, thus ground vehicles.
|
||||
-- @param #AI_CARGO_APC self
|
||||
-- @param #number CombatRadius Provide the combat radius to defend the carrier by unboarding the cargo when enemies are nearby.
|
||||
-- When the combat radius is 0, no defense will happen of the carrier.
|
||||
-- When the combat radius is not provided, no defense will happen!
|
||||
-- @return #AI_CARGO_APC
|
||||
-- @usage
|
||||
--
|
||||
-- -- Disembark the infantry when the carrier is under attack.
|
||||
-- AICargoAPC:SetCombatRadius( true )
|
||||
--
|
||||
-- -- Keep the cargo in the carrier when the carrier is under attack.
|
||||
-- AICargoAPC:SetCombatRadius( false )
|
||||
function AI_CARGO_APC:SetCombatRadius( CombatRadius )
|
||||
|
||||
self.CombatRadius = CombatRadius or 0
|
||||
|
||||
if self.CombatRadius > 0 then
|
||||
self:__Monitor( -5 )
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Follow Infantry to the Carrier.
|
||||
@@ -337,41 +262,49 @@ function AI_CARGO_APC:FollowToCarrier( Me, APCUnit, CargoGroup )
|
||||
end
|
||||
|
||||
|
||||
--- @param #AI_CARGO_APC self
|
||||
--- On after Monitor event.
|
||||
-- @param #AI_CARGO_APC self
|
||||
-- @param Wrapper.Group#GROUP APC
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function AI_CARGO_APC:onafterMonitor( APC, From, Event, To )
|
||||
self:F( { APC, From, Event, To } )
|
||||
self:F( { APC, From, Event, To, IsTransporting = self:IsTransporting() } )
|
||||
|
||||
if APC and APC:IsAlive() then
|
||||
if self.CarrierCoordinate then
|
||||
if self:IsRelocating() == true then
|
||||
local Coordinate = APC:GetCoordinate()
|
||||
self.Zone:Scan( { Object.Category.UNIT } )
|
||||
if self.Zone:IsAllInZoneOfCoalition( self.Coalition ) then
|
||||
if self:Is( "Unloaded" ) or self:Is( "Following" ) then
|
||||
-- There are no enemies within combat range. Load the CargoCarrier.
|
||||
self:Load()
|
||||
end
|
||||
else
|
||||
if self:Is( "Loaded" ) then
|
||||
-- There are enemies within combat range. Unload the CargoCarrier.
|
||||
self:__Unload( 1, false )
|
||||
else
|
||||
if self:Is( "Unloaded" ) then
|
||||
self:Follow()
|
||||
if self.CombatRadius > 0 then
|
||||
if APC and APC:IsAlive() then
|
||||
if self.CarrierCoordinate then
|
||||
if self:IsTransporting() == true then
|
||||
local Coordinate = APC:GetCoordinate()
|
||||
self.Zone:Scan( { Object.Category.UNIT } )
|
||||
if self.Zone:IsAllInZoneOfCoalition( self.Coalition ) then
|
||||
if self:Is( "Unloaded" ) or self:Is( "Following" ) then
|
||||
-- There are no enemies within combat radius. Load the CargoCarrier.
|
||||
self:Load()
|
||||
end
|
||||
if self:Is( "Following" ) then
|
||||
for APCUnit, Cargo in pairs( self.APC_Cargo ) do
|
||||
local Cargo = Cargo -- Cargo.Cargo#CARGO
|
||||
if Cargo:IsAlive() then
|
||||
if not Cargo:IsNear( APCUnit, 40 ) then
|
||||
APCUnit:RouteStop()
|
||||
self.CarrierStopped = true
|
||||
else
|
||||
if self.CarrierStopped then
|
||||
if Cargo:IsNear( APCUnit, 25 ) then
|
||||
APCUnit:RouteResume()
|
||||
self.CarrierStopped = nil
|
||||
else
|
||||
if self:Is( "Loaded" ) then
|
||||
-- There are enemies within combat radius. Unload the CargoCarrier.
|
||||
self:__Unload( 1 )
|
||||
else
|
||||
if self:Is( "Unloaded" ) then
|
||||
self:Follow()
|
||||
end
|
||||
self:F( "I am here" .. self:GetCurrentState() )
|
||||
if self:Is( "Following" ) then
|
||||
for Cargo, APCUnit in pairs( self.Carrier_Cargo ) do
|
||||
local Cargo = Cargo -- Cargo.Cargo#CARGO
|
||||
local APCUnit = APCUnit -- Wrapper.Unit#UNIT
|
||||
if Cargo:IsAlive() then
|
||||
if not Cargo:IsNear( APCUnit, 40 ) then
|
||||
APCUnit:RouteStop()
|
||||
self.CarrierStopped = true
|
||||
else
|
||||
if self.CarrierStopped then
|
||||
if Cargo:IsNear( APCUnit, 25 ) then
|
||||
APCUnit:RouteResume()
|
||||
self.CarrierStopped = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -380,180 +313,29 @@ function AI_CARGO_APC:onafterMonitor( APC, From, Event, To )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
self.CarrierCoordinate = APC:GetCoordinate()
|
||||
end
|
||||
self.CarrierCoordinate = APC:GetCoordinate()
|
||||
end
|
||||
|
||||
self:__Monitor( -5 )
|
||||
|
||||
end
|
||||
|
||||
|
||||
--- @param #AI_CARGO_APC self
|
||||
-- @param Wrapper.Group#GROUP APC
|
||||
function AI_CARGO_APC:onbeforeLoad( APC, From, Event, To )
|
||||
self:F( { APC, From, Event, To } )
|
||||
|
||||
local Boarding = false
|
||||
self.BoardingCount = 0
|
||||
|
||||
if APC and APC:IsAlive() then
|
||||
self.APC_Cargo = {}
|
||||
for _, APCUnit in pairs( APC:GetUnits() ) do
|
||||
local APCUnit = APCUnit -- Wrapper.Unit#UNIT
|
||||
for _, Cargo in pairs( self.CargoSet:GetSet() ) do
|
||||
local Cargo = Cargo -- Cargo.Cargo#CARGO
|
||||
self:F( { IsUnLoaded = Cargo:IsUnLoaded(), IsDeployed = Cargo:IsDeployed(), Cargo:GetName(), APC:GetName() } )
|
||||
if Cargo:IsUnLoaded() and not Cargo:IsDeployed() then
|
||||
if Cargo:IsInLoadRadius( APCUnit:GetCoordinate() ) then
|
||||
self:F( { "In radius", APCUnit:GetName() } )
|
||||
APC:RouteStop()
|
||||
--Cargo:Ungroup()
|
||||
Cargo:Board( APCUnit, 25 )
|
||||
self:__Board( 1, Cargo )
|
||||
Boarding = true
|
||||
|
||||
-- So now this APCUnit has Cargo that is being loaded.
|
||||
-- This will be used further in the logic to follow and to check cargo status.
|
||||
self.APC_Cargo[APCUnit] = Cargo
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return Boarding
|
||||
|
||||
end
|
||||
|
||||
--- @param #AI_CARGO_APC self
|
||||
-- @param Wrapper.Group#GROUP APC
|
||||
function AI_CARGO_APC:onafterBoard( APC, From, Event, To, Cargo )
|
||||
self:F( { APC, From, Event, To, Cargo } )
|
||||
|
||||
if APC and APC:IsAlive() then
|
||||
self:F({ IsLoaded = Cargo:IsLoaded(), Cargo:GetName(), APC:GetName() } )
|
||||
if not Cargo:IsLoaded() then
|
||||
self:__Board( 10, Cargo )
|
||||
else
|
||||
self:__Loaded( 1 )
|
||||
end
|
||||
self:__Monitor( -5 )
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- @param #AI_CARGO_APC self
|
||||
-- @param Wrapper.Group#GROUP APC
|
||||
function AI_CARGO_APC:onbeforeLoaded( APC, From, Event, To )
|
||||
self:F( { APC, From, Event, To } )
|
||||
|
||||
local Loaded = true
|
||||
|
||||
if APC and APC:IsAlive() then
|
||||
for APCUnit, Cargo in pairs( self.APC_Cargo ) do
|
||||
local Cargo = Cargo -- Cargo.Cargo#CARGO
|
||||
self:F( { IsLoaded = Cargo:IsLoaded(), IsDestroyed = Cargo:IsDestroyed(), Cargo:GetName(), APC:GetName() } )
|
||||
if not Cargo:IsLoaded() and not Cargo:IsDestroyed() then
|
||||
Loaded = false
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
if Loaded == true then
|
||||
APC:RouteResume()
|
||||
end
|
||||
|
||||
return Loaded
|
||||
|
||||
end
|
||||
|
||||
|
||||
--- @param #AI_CARGO_APC self
|
||||
-- @param Wrapper.Group#GROUP APC
|
||||
function AI_CARGO_APC:onafterUnload( APC, From, Event, To, Deployed )
|
||||
self:F( { APC, From, Event, To, Deployed } )
|
||||
|
||||
if APC and APC:IsAlive() then
|
||||
for _, APCUnit in pairs( APC:GetUnits() ) do
|
||||
local APCUnit = APCUnit -- Wrapper.Unit#UNIT
|
||||
APC:RouteStop()
|
||||
for _, Cargo in pairs( APCUnit:GetCargo() ) do
|
||||
Cargo:UnBoard()
|
||||
self:__Unboard( 10, Cargo, Deployed )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- @param #AI_CARGO_APC self
|
||||
-- @param Wrapper.Group#GROUP APC
|
||||
function AI_CARGO_APC:onafterUnboard( APC, From, Event, To, Cargo, Deployed )
|
||||
self:F( { APC, From, Event, To, Cargo:GetName() } )
|
||||
|
||||
if APC and APC:IsAlive() then
|
||||
if not Cargo:IsUnLoaded() then
|
||||
self:__Unboard( 10, Cargo, Deployed )
|
||||
else
|
||||
self:__Unloaded( 1, Cargo, Deployed )
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- @param #AI_CARGO_APC self
|
||||
-- @param Wrapper.Group#GROUP APC
|
||||
function AI_CARGO_APC:onbeforeUnloaded( APC, From, Event, To, Cargo, Deployed )
|
||||
self:F( { APC, From, Event, To, Cargo:GetName(), Deployed = Deployed } )
|
||||
|
||||
local AllUnloaded = true
|
||||
|
||||
--Cargo:Regroup()
|
||||
|
||||
if APC and APC:IsAlive() then
|
||||
for _, APCUnit in pairs( APC:GetUnits() ) do
|
||||
local APCUnit = APCUnit -- Wrapper.Unit#UNIT
|
||||
local CargoCheck = self.APC_Cargo[APCUnit]
|
||||
if CargoCheck then
|
||||
self:F( { CargoCheck:GetName(), IsUnLoaded = CargoCheck:IsUnLoaded() } )
|
||||
if CargoCheck:IsUnLoaded() == false then
|
||||
AllUnloaded = false
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if AllUnloaded == true then
|
||||
if Deployed == true then
|
||||
for APCUnit, Cargo in pairs( self.APC_Cargo ) do
|
||||
local Cargo = Cargo -- Cargo.Cargo#CARGO
|
||||
Cargo:SetDeployed( true )
|
||||
end
|
||||
self.APC_Cargo = {}
|
||||
end
|
||||
self:Guard()
|
||||
self.CargoCarrier = APC
|
||||
end
|
||||
end
|
||||
|
||||
self:F( { AllUnloaded = AllUnloaded } )
|
||||
return AllUnloaded
|
||||
|
||||
end
|
||||
|
||||
|
||||
--- @param #AI_CARGO_APC self
|
||||
|
||||
--- On after Follow event.
|
||||
-- @param #AI_CARGO_APC self
|
||||
-- @param Wrapper.Group#GROUP APC
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function AI_CARGO_APC:onafterFollow( APC, From, Event, To )
|
||||
self:F( { APC, From, Event, To } )
|
||||
|
||||
self:F( "Follow" )
|
||||
if APC and APC:IsAlive() then
|
||||
for APCUnit, Cargo in pairs( self.APC_Cargo ) do
|
||||
for Cargo, APCUnit in pairs( self.Carrier_Cargo ) do
|
||||
local Cargo = Cargo -- Cargo.Cargo#CARGO
|
||||
if Cargo:IsUnLoaded() then
|
||||
self:FollowToCarrier( self, APCUnit, Cargo )
|
||||
@@ -567,50 +349,49 @@ end
|
||||
|
||||
--- @param #AI_CARGO_APC
|
||||
-- @param Wrapper.Group#GROUP APC
|
||||
function AI_CARGO_APC._Pickup( APC, self )
|
||||
function AI_CARGO_APC._Pickup( APC, self, Coordinate, Speed, PickupZone )
|
||||
|
||||
APC:F( { "AI_CARGO_APC._Pickup:", APC:GetName() } )
|
||||
|
||||
if APC:IsAlive() then
|
||||
self:Load()
|
||||
self.Relocating = true
|
||||
self:Load( PickupZone )
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--- @param #AI_CARGO_APC
|
||||
-- @param Wrapper.Group#GROUP APC
|
||||
function AI_CARGO_APC._Deploy( APC, self )
|
||||
function AI_CARGO_APC._Deploy( APC, self, Coordinate, DeployZone )
|
||||
|
||||
APC:F( { "AI_CARGO_APC._Deploy:", APC } )
|
||||
|
||||
if APC:IsAlive() then
|
||||
self:Unload( true )
|
||||
self.Transporting = false
|
||||
self.Relocating = false
|
||||
self:Unload( DeployZone )
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
--- @param #AI_CARGO_APC self
|
||||
--- On after Pickup event.
|
||||
-- @param #AI_CARGO_APC self
|
||||
-- @param Wrapper.Group#GROUP APC
|
||||
-- @param From
|
||||
-- @param Event
|
||||
-- @param To
|
||||
-- @param Core.Point#COORDINATE Coordinate
|
||||
-- @param #number Speed
|
||||
-- @param #string EndPointFormation The formation at the end point of the action.
|
||||
function AI_CARGO_APC:onafterPickup( APC, From, Event, To, Coordinate )
|
||||
-- @param Core.Point#COORDINATE Coordinate of the pickup point.
|
||||
-- @param #number Speed Speed in km/h to drive to the pickup coordinate. Default is 50% of max possible speed the unit can go.
|
||||
-- @param #number Height Height in meters to move to the pickup coordinate. This parameter is ignored for APCs.
|
||||
-- @param Core.Zone#ZONE PickupZone (optional) The zone where the cargo will be picked up. The PickupZone can be nil, if there wasn't any PickupZoneSet provided.
|
||||
function AI_CARGO_APC:onafterPickup( APC, From, Event, To, Coordinate, Speed, Height, PickupZone )
|
||||
|
||||
if APC and APC:IsAlive() then
|
||||
|
||||
if Coordinate then
|
||||
self.RoutePickup = true
|
||||
|
||||
local Waypoints = APC:TaskGroundOnRoad( Coordinate, 150, "Line abreast" )
|
||||
local _speed=Speed or APC:GetSpeedMax()*0.5
|
||||
|
||||
local Waypoints = APC:TaskGroundOnRoad( Coordinate, _speed, "Line abreast", true )
|
||||
|
||||
local TaskFunction = APC:TaskFunction( "AI_CARGO_APC._Pickup", self )
|
||||
local TaskFunction = APC:TaskFunction( "AI_CARGO_APC._Pickup", self, Coordinate, Speed, PickupZone )
|
||||
|
||||
self:F({Waypoints = Waypoints})
|
||||
local Waypoint = Waypoints[#Waypoints]
|
||||
@@ -618,57 +399,84 @@ function AI_CARGO_APC:onafterPickup( APC, From, Event, To, Coordinate )
|
||||
|
||||
APC:Route( Waypoints, 1 ) -- Move after a random seconds to the Route. See the Route method for details.
|
||||
else
|
||||
AI_CARGO_APC._Pickup( APC, self )
|
||||
AI_CARGO_APC._Pickup( APC, self, Coordinate, Speed, PickupZone )
|
||||
end
|
||||
|
||||
self.Transporting = true
|
||||
|
||||
self:GetParent( self, AI_CARGO_APC ).onafterPickup( self, APC, From, Event, To, Coordinate, Speed, Height, PickupZone )
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
--- @param #AI_CARGO_APC self
|
||||
--- On after Deploy event.
|
||||
-- @param #AI_CARGO_APC self
|
||||
-- @param Wrapper.Group#GROUP APC
|
||||
-- @param From
|
||||
-- @param Event
|
||||
-- @param To
|
||||
-- @param Core.Point#COORDINATE Coordinate
|
||||
-- @param #number Speed
|
||||
-- @param #string EndPointFormation The formation at the end point of the action.
|
||||
function AI_CARGO_APC:onafterDeploy( APC, From, Event, To, Coordinate )
|
||||
-- @param Core.Point#COORDINATE Coordinate Deploy place.
|
||||
-- @param #number Speed Speed in km/h to drive to the depoly coordinate. Default is 50% of max possible speed the unit can go.
|
||||
-- @param #number Height Height in meters to move to the deploy coordinate. This parameter is ignored for APCs.
|
||||
-- @param Core.Zone#ZONE DeployZone The zone where the cargo will be deployed.
|
||||
function AI_CARGO_APC:onafterDeploy( APC, From, Event, To, Coordinate, Speed, Height, DeployZone )
|
||||
|
||||
if APC and APC:IsAlive() then
|
||||
|
||||
self.RouteDeploy = true
|
||||
|
||||
local _speed=Speed or APC:GetSpeedMax()*0.5
|
||||
|
||||
local Waypoints = APC:TaskGroundOnRoad( Coordinate, 150, "Line abreast" )
|
||||
local Waypoints = APC:TaskGroundOnRoad( Coordinate, _speed, "Line abreast", true )
|
||||
|
||||
local TaskFunction = APC:TaskFunction( "AI_CARGO_APC._Deploy", self )
|
||||
local TaskFunction = APC:TaskFunction( "AI_CARGO_APC._Deploy", self, Coordinate, DeployZone )
|
||||
|
||||
self:F({Waypoints = Waypoints})
|
||||
local Waypoint = Waypoints[#Waypoints]
|
||||
APC:SetTaskWaypoint( Waypoint, TaskFunction ) -- Set for the given Route at Waypoint 2 the TaskRouteToZone.
|
||||
|
||||
APC:Route( Waypoints, 1 ) -- Move after a random seconds to the Route. See the Route method for details.
|
||||
|
||||
self:GetParent( self, AI_CARGO_APC ).onafterDeploy( self, APC, From, Event, To, Coordinate, Speed, Height, DeployZone )
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- On after Deployed event.
|
||||
-- @param #AI_CARGO_APC self
|
||||
-- @param Wrapper.Group#GROUP Carrier
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Core.Zone#ZONE DeployZone The zone wherein the cargo is deployed. This can be any zone type, like a ZONE, ZONE_GROUP, ZONE_AIRBASE.
|
||||
function AI_CARGO_APC:onafterDeployed( APC, From, Event, To, DeployZone )
|
||||
self:F( { APC, From, Event, To, DeployZone = DeployZone } )
|
||||
|
||||
--- @param #AI_CARGO_HELICOPTER self
|
||||
self:__Guard( 0.1 )
|
||||
|
||||
self:GetParent( self, AI_CARGO_APC ).onafterDeployed( self, APC, From, Event, To, DeployZone )
|
||||
|
||||
end
|
||||
|
||||
|
||||
--- On after Home event.
|
||||
-- @param #AI_CARGO_APC self
|
||||
-- @param Wrapper.Group#GROUP APC
|
||||
-- @param From
|
||||
-- @param Event
|
||||
-- @param To
|
||||
-- @param Core.Point#COORDINATE Coordinate
|
||||
-- @param #number Speed
|
||||
function AI_CARGO_APC:onafterHome( APC, From, Event, To, Coordinate )
|
||||
-- @param Core.Point#COORDINATE Coordinate Home place.
|
||||
-- @param #number Speed Speed in km/h to drive to the pickup coordinate. Default is 50% of max possible speed the unit can go.
|
||||
-- @param #number Height Height in meters to move to the home coordinate. This parameter is ignored for APCs.
|
||||
function AI_CARGO_APC:onafterHome( APC, From, Event, To, Coordinate, Speed, Height, HomeZone )
|
||||
|
||||
if APC and APC:IsAlive() ~= nil then
|
||||
|
||||
self.RouteHome = true
|
||||
|
||||
local Waypoints = APC:TaskGroundOnRoad( Coordinate, 120, "Line abreast" )
|
||||
|
||||
Speed = Speed or APC:GetSpeedMax()*0.5
|
||||
|
||||
local Waypoints = APC:TaskGroundOnRoad( Coordinate, Speed, "Line abreast", true )
|
||||
|
||||
self:F({Waypoints = Waypoints})
|
||||
local Waypoint = Waypoints[#Waypoints]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
--- **AI** -- (R2.3) - Models the intelligent transportation of infantry (cargo).
|
||||
--- **AI** -- (R2.4) - Models the intelligent transportation of infantry (cargo).
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
@@ -6,117 +6,149 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module AI_Cargo_Airplane
|
||||
-- @module AI.AI_Cargo_Airplane
|
||||
-- @image AI_Cargo_Dispatching_For_Airplanes.JPG
|
||||
|
||||
--- @type AI_CARGO_AIRPLANE
|
||||
-- @extends Core.Fsm#FSM_CONTROLLABLE
|
||||
|
||||
|
||||
--- # AI\_CARGO\_AIRPLANE class, extends @{Core.Base@BASE}
|
||||
--- 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.
|
||||
--
|
||||
-- The AI_CARGO_AIRPLANE module uses the @{Cargo.Cargo} capabilities within the MOOSE framework.
|
||||
-- @{Cargo.Cargo} must be declared within the mission to make AI_CARGO_AIRPLANE recognize the cargo.
|
||||
-- Please consult the @{Cargo.Cargo} module for more information.
|
||||
--
|
||||
-- ## Cargo pickup.
|
||||
--
|
||||
-- Using the @{#AI_CARGO_AIRPLANE.Pickup}() method, you are able to direct the helicopters towards a point on the battlefield to board/load the cargo at the specific coordinate.
|
||||
-- Ensure that the landing zone is horizontally flat, and that trees cannot be found in the landing vicinity, or the helicopters won't land or will even crash!
|
||||
--
|
||||
-- ## Cargo deployment.
|
||||
--
|
||||
-- Using the @{#AI_CARGO_AIRPLANE.Deploy}() method, you are able to direct the helicopters towards a point on the battlefield to unboard/unload the cargo at the specific coordinate.
|
||||
-- Ensure that the landing zone is horizontally flat, and that trees cannot be found in the landing vicinity, or the helicopters won't land or will even crash!
|
||||
--
|
||||
-- ## Infantry health.
|
||||
--
|
||||
-- When infantry is unboarded from the APCs, the infantry is actually respawned into the battlefield.
|
||||
-- As a result, the unboarding infantry is very _healthy_ every time it unboards.
|
||||
-- This is due to the limitation of the DCS simulator, which is not able to specify the health of new spawned units as a parameter.
|
||||
-- However, infantry that was destroyed when unboarded, won't be respawned again. Destroyed is destroyed.
|
||||
-- As a result, there is some additional strength that is gained when an unboarding action happens, but in terms of simulation balance this has
|
||||
-- marginal impact on the overall battlefield simulation. Fortunately, the firing strength of infantry is limited, and thus, respacing healthy infantry every
|
||||
-- time is not so much of an issue ...
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @field #AI_CARGO_AIRPLANE
|
||||
AI_CARGO_AIRPLANE = {
|
||||
ClassName = "AI_CARGO_AIRPLANE",
|
||||
Coordinate = nil -- Core.Point#COORDINATE,
|
||||
Coordinate = nil, -- Core.Point#COORDINATE
|
||||
}
|
||||
|
||||
--- Creates a new AI_CARGO_AIRPLANE object.
|
||||
-- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Group#GROUP Airplane
|
||||
-- @param Core.Set#SET_CARGO CargoSet
|
||||
-- @param #number CombatRadius
|
||||
-- @param Wrapper.Group#GROUP Airplane Plane used for transportation of cargo.
|
||||
-- @param Core.Set#SET_CARGO CargoSet Cargo set to be transported.
|
||||
-- @return #AI_CARGO_AIRPLANE
|
||||
function AI_CARGO_AIRPLANE:New( Airplane, CargoSet )
|
||||
|
||||
local self = BASE:Inherit( self, FSM_CONTROLLABLE:New() ) -- #AI_CARGO_AIRPLANE
|
||||
|
||||
self.CargoSet = CargoSet -- Cargo.CargoGroup#CARGO_GROUP
|
||||
|
||||
self:SetStartState( "Unloaded" )
|
||||
|
||||
self:AddTransition( "Unloaded", "Pickup", "*" )
|
||||
self:AddTransition( "Loaded", "Deploy", "*" )
|
||||
|
||||
self:AddTransition( "Unloaded", "Load", "Boarding" )
|
||||
self:AddTransition( "Boarding", "Board", "Boarding" )
|
||||
self:AddTransition( "Boarding", "Loaded", "Loaded" )
|
||||
self:AddTransition( "Loaded", "Unload", "Unboarding" )
|
||||
self:AddTransition( "Unboarding", "Unboard", "Unboarding" )
|
||||
self:AddTransition( "Unboarding", "Unloaded", "Unloaded" )
|
||||
local self = BASE:Inherit( self, AI_CARGO:New( Airplane, CargoSet ) ) -- #AI_CARGO_AIRPLANE
|
||||
|
||||
self:AddTransition( "*", "Landed", "*" )
|
||||
self:AddTransition( "*", "Home" , "*" )
|
||||
|
||||
self:AddTransition( "*", "Destroyed", "Destroyed" )
|
||||
|
||||
--- Pickup Handler OnBefore for AI_CARGO_AIRPLANE
|
||||
-- @function [parent=#AI_CARGO_AIRPLANE] OnBeforePickup
|
||||
-- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @param Wrapper.Airbase#AIRBASE Airbase
|
||||
-- @param Wrapper.Group#GROUP Airplane Cargo transport plane.
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Wrapper.Airbase#AIRBASE Airbase Airbase where troops are picked up.
|
||||
-- @param #number Speed in km/h for travelling to pickup base.
|
||||
-- @return #boolean
|
||||
|
||||
--- Pickup Handler OnAfter for AI_CARGO_AIRPLANE
|
||||
-- @function [parent=#AI_CARGO_AIRPLANE] OnAfterPickup
|
||||
-- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Group#GROUP Airplane Cargo plane.
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @param Wrapper.Airbase#AIRBASE Airbase
|
||||
-- @param Wrapper.Airbase#AIRBASE Airbase Airbase where troops are picked up.
|
||||
-- @param #number Speed in km/h for travelling to pickup base.
|
||||
|
||||
--- Pickup Trigger for AI_CARGO_AIRPLANE
|
||||
-- @function [parent=#AI_CARGO_AIRPLANE] Pickup
|
||||
-- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Airbase#AIRBASE Airbase
|
||||
-- @param Wrapper.Airbase#AIRBASE Airbase Airbase where troops are picked up.
|
||||
-- @param #number Speed in km/h for travelling to pickup base.
|
||||
|
||||
--- Pickup Asynchronous Trigger for AI_CARGO_AIRPLANE
|
||||
-- @function [parent=#AI_CARGO_AIRPLANE] __Pickup
|
||||
-- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param #number Delay
|
||||
-- @param Wrapper.Airbase#AIRBASE Airbase
|
||||
-- @param #number Delay Delay in seconds.
|
||||
-- @param Wrapper.Airbase#AIRBASE Airbase Airbase where troops are picked up.
|
||||
-- @param #number Speed in km/h for travelling to pickup base.
|
||||
|
||||
--- Deploy Handler OnBefore for AI_CARGO_AIRPLANE
|
||||
-- @function [parent=#AI_CARGO_AIRPLANE] OnBeforeDeploy
|
||||
-- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Group#GROUP Airplane Cargo plane.
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @param Wrapper.Airbase#AIRBASE Airbase
|
||||
-- @param Wrapper.Airbase#AIRBASE Airbase Destination airbase where troops are deployed.
|
||||
-- @param #number Speed Speed in km/h for travelling to deploy base.
|
||||
-- @return #boolean
|
||||
|
||||
--- Deploy Handler OnAfter for AI_CARGO_AIRPLANE
|
||||
-- @function [parent=#AI_CARGO_AIRPLANE] OnAfterDeploy
|
||||
-- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Group#GROUP Airplane Cargo plane.
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @param Wrapper.Airbase#AIRBASE Airbase
|
||||
-- @param Wrapper.Airbase#AIRBASE Airbase Destination airbase where troops are deployed.
|
||||
-- @param #number Speed Speed in km/h for travelling to deploy base.
|
||||
|
||||
--- Deploy Trigger for AI_CARGO_AIRPLANE
|
||||
-- @function [parent=#AI_CARGO_AIRPLANE] Deploy
|
||||
-- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Airbase#AIRBASE Airbase
|
||||
-- @param Wrapper.Airbase#AIRBASE Airbase Destination airbase where troops are deployed.
|
||||
-- @param #number Speed Speed in km/h for travelling to deploy base.
|
||||
|
||||
--- Deploy Asynchronous Trigger for AI_CARGO_AIRPLANE
|
||||
-- @function [parent=#AI_CARGO_AIRPLANE] __Deploy
|
||||
-- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Airbase#AIRBASE Airbase
|
||||
-- @param #number Delay
|
||||
|
||||
-- @param #number Delay Delay in seconds.
|
||||
-- @param Wrapper.Airbase#AIRBASE Airbase Destination airbase where troops are deployed.
|
||||
-- @param #number Speed Speed in km/h for travelling to deploy base.
|
||||
|
||||
--- On after Loaded event, i.e. triggered when the cargo is inside the carrier.
|
||||
-- @function [parent=#AI_CARGO_AIRPLANE] OnAfterLoaded
|
||||
-- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Group#GROUP Airplane Cargo plane.
|
||||
-- @param From
|
||||
-- @param Event
|
||||
-- @param To
|
||||
|
||||
-- Set carrier.
|
||||
self:SetCarrier( Airplane )
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Set the Carrier.
|
||||
--- Set the Carrier (controllable). Also initializes events for carrier and defines the coalition.
|
||||
-- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Group#GROUP Airplane
|
||||
-- @return #AI_CARGO_AIRPLANE
|
||||
-- @param Wrapper.Group#GROUP Airplane Transport plane.
|
||||
-- @return #AI_CARGO_AIRPLANE self
|
||||
function AI_CARGO_AIRPLANE:SetCarrier( Airplane )
|
||||
|
||||
local AICargo = self
|
||||
@@ -157,7 +189,8 @@ function AI_CARGO_AIRPLANE:SetCarrier( Airplane )
|
||||
|
||||
|
||||
function Airplane:OnEventEngineShutdown( EventData )
|
||||
AICargo:Landed()
|
||||
AICargo.Relocating = false
|
||||
AICargo:Landed( self.Airplane )
|
||||
end
|
||||
|
||||
self.Coalition = self.Airplane:GetCoalition()
|
||||
@@ -170,7 +203,7 @@ end
|
||||
|
||||
--- Find a free Carrier within a range.
|
||||
-- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Airbase#AIRBASE Airbase
|
||||
-- @param Wrapper.Airbase#AIRBASE Airbase
|
||||
-- @param #number Radius
|
||||
-- @return Wrapper.Group#GROUP NewCarrier
|
||||
function AI_CARGO_AIRPLANE:FindCarrier( Coordinate, Radius )
|
||||
@@ -192,22 +225,24 @@ function AI_CARGO_AIRPLANE:FindCarrier( Coordinate, Radius )
|
||||
|
||||
end
|
||||
|
||||
--- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Group#GROUP Airplane
|
||||
--- On after "Landed" event. Called on engine shutdown and initiates the pickup mission or unloading event.
|
||||
-- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Group#GROUP Airplane Cargo transport plane.
|
||||
-- @param From
|
||||
-- @param Event
|
||||
-- @param To
|
||||
-- @param Wrapper.Airbase#AIRBASE Airbase
|
||||
-- @param #number Speed
|
||||
function AI_CARGO_AIRPLANE:onafterLanded( Airplane, From, Event, To )
|
||||
|
||||
if Airplane and Airplane:IsAlive() then
|
||||
self:F({Airplane, From, Event, To})
|
||||
|
||||
if Airplane and Airplane:IsAlive()~=nil then
|
||||
|
||||
-- Aircraft was sent to this airbase to pickup troops. Initiate loadling.
|
||||
if self.RoutePickup == true then
|
||||
self:Load( Airplane:GetPointVec2() )
|
||||
self.RoutePickup = false
|
||||
self:Load( self.PickupZone )
|
||||
end
|
||||
|
||||
-- Aircraft was send to this airbase to deploy troops. Initiate unloading.
|
||||
if self.RouteDeploy == true then
|
||||
self:Unload()
|
||||
self.RouteDeploy = false
|
||||
@@ -218,231 +253,232 @@ function AI_CARGO_AIRPLANE:onafterLanded( Airplane, From, Event, To )
|
||||
end
|
||||
|
||||
|
||||
|
||||
--- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Group#GROUP Airplane
|
||||
-- @param From
|
||||
-- @param Event
|
||||
-- @param To
|
||||
-- @param Wrapper.Airbase#AIRBASE Airbase
|
||||
-- @param #number Speed
|
||||
function AI_CARGO_AIRPLANE:onafterPickup( Airplane, From, Event, To, Airbase, Speed )
|
||||
--- On after "Pickup" event. Routes transport to pickup airbase.
|
||||
-- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Group#GROUP Airplane Cargo transport plane.
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Core.Point#COORDINATE Coordinate
|
||||
-- @param #number Speed in km/h for travelling to pickup base.
|
||||
-- @param #number Height Height in meters to move to the pickup coordinate.
|
||||
-- @param Core.Zone#ZONE_AIRBASE (optional) PickupZone The zone where the cargo will be picked up.
|
||||
function AI_CARGO_AIRPLANE:onafterPickup( Airplane, From, Event, To, Coordinate, Speed, Height, PickupZone )
|
||||
|
||||
if Airplane and Airplane:IsAlive() then
|
||||
self:Route( Airplane, Airbase, Speed )
|
||||
self.RoutePickup = true
|
||||
self.Airbase = Airbase
|
||||
|
||||
self.PickupZone = PickupZone
|
||||
|
||||
-- Get closest airbase of current position.
|
||||
local ClosestAirbase, DistToAirbase=Airplane:GetCoordinate():GetClosestAirbase()
|
||||
|
||||
-- Two cases. Aircraft spawned in air or at an airbase.
|
||||
if Airplane:InAir() then
|
||||
self.Airbase=nil --> route will start in air
|
||||
else
|
||||
self.Airbase=ClosestAirbase
|
||||
end
|
||||
|
||||
-- Set pickup airbase.
|
||||
local Airbase = PickupZone:GetAirbase()
|
||||
|
||||
-- Distance from closest to pickup airbase ==> we need to know if we are already at the pickup airbase.
|
||||
local Dist = Airbase:GetCoordinate():Get2DDistance(ClosestAirbase:GetCoordinate())
|
||||
--env.info("Distance closest to pickup airbase = "..Dist)
|
||||
|
||||
if Airplane:InAir() or Dist>500 then
|
||||
|
||||
-- Route aircraft to pickup airbase.
|
||||
self:Route( Airplane, Airbase, Speed, Height )
|
||||
|
||||
-- Set airbase as starting point in the next Route() call.
|
||||
self.Airbase = Airbase
|
||||
|
||||
-- Aircraft is on a pickup mission.
|
||||
self.RoutePickup = true
|
||||
|
||||
else
|
||||
|
||||
-- We are already at the right airbase ==> Landed ==> triggers loading of troops. Is usually called at engine shutdown event.
|
||||
self.RoutePickup=true
|
||||
self:Landed()
|
||||
|
||||
end
|
||||
|
||||
self:GetParent( self, AI_CARGO_AIRPLANE ).onafterPickup( self, Airplane, From, Event, To, Coordinate, Speed, Height, PickupZone )
|
||||
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
--- On after Depoly event. Routes plane to the airbase where the troops are deployed.
|
||||
-- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Group#GROUP Airplane Cargo transport plane.
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Core.Point#COORDINATE Coordinate
|
||||
-- @param #number Speed in km/h for travelling to pickup base.
|
||||
-- @param #number Height Height in meters to move to the home coordinate.
|
||||
-- @param Core.Zone#ZONE_AIRBASE DeployZone The zone where the cargo will be deployed.
|
||||
function AI_CARGO_AIRPLANE:onafterDeploy( Airplane, From, Event, To, Coordinate, Speed, Height, DeployZone )
|
||||
|
||||
--- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Group#GROUP Airplane
|
||||
-- @param From
|
||||
-- @param Event
|
||||
-- @param To
|
||||
-- @param Wrapper.Airbase#AIRBASE Airbase
|
||||
-- @param #number Speed
|
||||
function AI_CARGO_AIRPLANE:onafterDeploy( Airplane, From, Event, To, Airbase, Speed )
|
||||
|
||||
if Airplane and Airplane:IsAlive() then
|
||||
self:Route( Airplane, Airbase, Speed )
|
||||
if Airplane and Airplane:IsAlive()~=nil then
|
||||
|
||||
local Airbase = DeployZone:GetAirbase()
|
||||
|
||||
-- Activate uncontrolled airplane.
|
||||
if Airplane:IsAlive()==false then
|
||||
Airplane:SetCommand({id = 'Start', params = {}})
|
||||
end
|
||||
|
||||
-- Route to destination airbase.
|
||||
self:Route( Airplane, Airbase, Speed, Height )
|
||||
|
||||
-- Aircraft is on a depoly mission.
|
||||
self.RouteDeploy = true
|
||||
|
||||
-- Set destination airbase for next :Route() command.
|
||||
self.Airbase = Airbase
|
||||
|
||||
self:GetParent( self, AI_CARGO_AIRPLANE ).onafterDeploy( self, Airplane, From, Event, To, Coordinate, Speed, Height, DeployZone )
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
--- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Group#GROUP Airplane
|
||||
function AI_CARGO_AIRPLANE:onafterLoad( Airplane, From, Event, To, Coordinate )
|
||||
--- On after Unload event. Cargo is beeing unloaded, i.e. the unboarding process is started.
|
||||
-- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Group#GROUP Airplane Cargo transport plane.
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
function AI_CARGO_AIRPLANE:onafterUnload( Airplane, From, Event, To, DeployZone )
|
||||
|
||||
local UnboardInterval = 10
|
||||
local UnboardDelay = 10
|
||||
|
||||
if Airplane and Airplane:IsAlive() then
|
||||
|
||||
for _, Cargo in pairs( self.CargoSet:GetSet() ) do
|
||||
if Cargo:IsInLoadRadius( Coordinate ) then
|
||||
self:__Board( 5 )
|
||||
Cargo:Board( Airplane, 25 )
|
||||
self.Cargo = Cargo
|
||||
break
|
||||
for _, AirplaneUnit in pairs( Airplane:GetUnits() ) do
|
||||
local Cargos = AirplaneUnit:GetCargo()
|
||||
for CargoID, Cargo in pairs( Cargos ) do
|
||||
|
||||
local Angle = 180
|
||||
local CargoCarrierHeading = Airplane:GetHeading() -- Get Heading of object in degrees.
|
||||
local CargoDeployHeading = ( ( CargoCarrierHeading + Angle ) >= 360 ) and ( CargoCarrierHeading + Angle - 360 ) or ( CargoCarrierHeading + Angle )
|
||||
self:T( { CargoCarrierHeading, CargoDeployHeading } )
|
||||
local CargoDeployCoordinate = Airplane:GetPointVec2():Translate( 150, CargoDeployHeading )
|
||||
|
||||
Cargo:__UnBoard( UnboardDelay, CargoDeployCoordinate )
|
||||
UnboardDelay = UnboardDelay + UnboardInterval
|
||||
Cargo:SetDeployed( true )
|
||||
self:__Unboard( UnboardDelay, Cargo, AirplaneUnit, DeployZone )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Group#GROUP Airplane
|
||||
function AI_CARGO_AIRPLANE:onafterBoard( Airplane, From, Event, To )
|
||||
|
||||
if Airplane and Airplane:IsAlive() then
|
||||
self:F({ IsLoaded = self.Cargo:IsLoaded() } )
|
||||
if not self.Cargo:IsLoaded() then
|
||||
self:__Board( 10 )
|
||||
else
|
||||
self:__Loaded( 1 )
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Group#GROUP Airplane
|
||||
function AI_CARGO_AIRPLANE:onafterLoaded( Airplane, From, Event, To )
|
||||
|
||||
if Airplane and Airplane:IsAlive() then
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
--- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Group#GROUP Airplane
|
||||
function AI_CARGO_AIRPLANE:onafterUnload( Airplane, From, Event, To )
|
||||
|
||||
if Airplane and Airplane:IsAlive() then
|
||||
self.Cargo:UnBoard()
|
||||
self:__Unboard( 10 )
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Group#GROUP Airplane
|
||||
function AI_CARGO_AIRPLANE:onafterUnboard( Airplane, From, Event, To )
|
||||
|
||||
if Airplane and Airplane:IsAlive() then
|
||||
if not self.Cargo:IsUnLoaded() then
|
||||
self:__Unboard( 10 )
|
||||
else
|
||||
self:__Unloaded( 1 )
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Group#GROUP Airplane
|
||||
function AI_CARGO_AIRPLANE:onafterUnloaded( Airplane, From, Event, To )
|
||||
|
||||
if Airplane and Airplane:IsAlive() then
|
||||
self.Airplane = Airplane
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
--- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Group#GROUP Airplane
|
||||
-- @param Wrapper.Airbase#AIRBASE Airbase
|
||||
-- @param #number Speed
|
||||
function AI_CARGO_AIRPLANE:Route( Airplane, Airbase, Speed )
|
||||
--- Route the airplane from one airport or it's current position to another airbase.
|
||||
-- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Group#GROUP Airplane Airplane group to be routed.
|
||||
-- @param Wrapper.Airbase#AIRBASE Airbase Destination airbase.
|
||||
-- @param #number Speed Speed in km/h. Default is 80% of max possible speed the group can do.
|
||||
-- @param #number Height Height in meters to move to the Airbase.
|
||||
-- @param #boolean Uncontrolled If true, spawn group in uncontrolled state.
|
||||
function AI_CARGO_AIRPLANE:Route( Airplane, Airbase, Speed, Height, Uncontrolled )
|
||||
|
||||
if Airplane and Airplane:IsAlive() then
|
||||
|
||||
local PointVec3 = Airplane:GetPointVec3()
|
||||
|
||||
local Takeoff = SPAWN.Takeoff.Hot
|
||||
-- Set takeoff type.
|
||||
local Takeoff = SPAWN.Takeoff.Cold
|
||||
|
||||
-- Get template of group.
|
||||
local Template = Airplane:GetTemplate()
|
||||
|
||||
if Template then
|
||||
|
||||
-- Nil check
|
||||
if Template==nil then
|
||||
return
|
||||
end
|
||||
|
||||
local Points = {}
|
||||
|
||||
if self.Airbase then
|
||||
|
||||
local FromWaypoint = Template.route.points[1]
|
||||
-- Waypoints of the route.
|
||||
local Points={}
|
||||
|
||||
-- These are only for ships.
|
||||
FromWaypoint.linkUnit = nil
|
||||
FromWaypoint.helipadId = nil
|
||||
FromWaypoint.airdromeId = nil
|
||||
-- To point.
|
||||
local AirbasePointVec2 = Airbase:GetPointVec2()
|
||||
local ToWaypoint = AirbasePointVec2:WaypointAir(
|
||||
POINT_VEC3.RoutePointAltType.BARO,
|
||||
"Land",
|
||||
"Landing",
|
||||
Speed or Airplane:GetSpeedMax()*0.8
|
||||
)
|
||||
ToWaypoint["airdromeId"] = Airbase:GetID()
|
||||
ToWaypoint["speed_locked"] = true
|
||||
|
||||
local AirbaseID = self.Airbase:GetID()
|
||||
local AirbaseCategory = self.Airbase:GetDesc().category
|
||||
|
||||
FromWaypoint.airdromeId = AirbaseID
|
||||
|
||||
FromWaypoint.alt = 0
|
||||
|
||||
FromWaypoint.type = GROUPTEMPLATE.Takeoff[Takeoff][1] -- type
|
||||
FromWaypoint.action = GROUPTEMPLATE.Takeoff[Takeoff][2] -- action
|
||||
|
||||
|
||||
-- Translate the position of the Group Template to the Vec3.
|
||||
for UnitID = 1, #Template.units do
|
||||
self:T( 'Before Translation SpawnTemplate.units['..UnitID..'].x = ' .. Template.units[UnitID].x .. ', SpawnTemplate.units['..UnitID..'].y = ' .. Template.units[UnitID].y )
|
||||
|
||||
-- These cause a lot of confusion.
|
||||
local UnitTemplate = Template.units[UnitID]
|
||||
|
||||
UnitTemplate.parking = 15
|
||||
UnitTemplate.parking_id = "1"
|
||||
UnitTemplate.alt = 0
|
||||
|
||||
local SX = UnitTemplate.x
|
||||
local SY = UnitTemplate.y
|
||||
local BX = FromWaypoint.x
|
||||
local BY = FromWaypoint.y
|
||||
local TX = PointVec3.x + ( SX - BX )
|
||||
local TY = PointVec3.z + ( SY - BY )
|
||||
|
||||
UnitTemplate.x = TX
|
||||
UnitTemplate.y = TY
|
||||
|
||||
self:T( 'After Translation SpawnTemplate.units['..UnitID..'].x = ' .. UnitTemplate.x .. ', SpawnTemplate.units['..UnitID..'].y = ' .. UnitTemplate.y )
|
||||
end
|
||||
|
||||
FromWaypoint.x = PointVec3.x
|
||||
FromWaypoint.y = PointVec3.z
|
||||
|
||||
Points[#Points+1] = FromWaypoint
|
||||
else
|
||||
|
||||
local GroupPoint = Airplane:GetVec2()
|
||||
local GroupVelocity = Airplane:GetUnit(1):GetDesc().speedMax
|
||||
-- If self.Airbase~=nil then group is currently at an airbase, where it should be respawned.
|
||||
if self.Airbase then
|
||||
|
||||
local FromWaypoint = {}
|
||||
FromWaypoint.x = GroupPoint.x
|
||||
FromWaypoint.y = GroupPoint.y
|
||||
FromWaypoint.type = "Turning Point"
|
||||
FromWaypoint.action = "Turning Point"
|
||||
FromWaypoint.speed = GroupVelocity
|
||||
-- Second point of the route. First point is done in RespawnAtCurrentAirbase() routine.
|
||||
Template.route.points[2] = ToWaypoint
|
||||
|
||||
-- Respawn group at the current airbase.
|
||||
Airplane:RespawnAtCurrentAirbase(Template, Takeoff, Uncontrolled)
|
||||
|
||||
else
|
||||
|
||||
-- From point.
|
||||
local GroupPoint = Airplane:GetVec2()
|
||||
local FromWaypoint = {}
|
||||
FromWaypoint.x = GroupPoint.x
|
||||
FromWaypoint.y = GroupPoint.y
|
||||
FromWaypoint.type = "Turning Point"
|
||||
FromWaypoint.action = "Turning Point"
|
||||
FromWaypoint.speed = Airplane:GetSpeedMax()*0.8
|
||||
|
||||
-- The two route points.
|
||||
Points[1] = FromWaypoint
|
||||
Points[2] = ToWaypoint
|
||||
|
||||
Points[#Points+1] = FromWaypoint
|
||||
end
|
||||
|
||||
local AirbasePointVec2 = Airbase:GetPointVec2()
|
||||
local ToWaypoint = AirbasePointVec2:WaypointAir(
|
||||
POINT_VEC3.RoutePointAltType.BARO,
|
||||
"Land",
|
||||
"Landing",
|
||||
Speed or Airplane:GetUnit(1):GetDesc().speedMax
|
||||
)
|
||||
|
||||
ToWaypoint["airdromeId"] = Airbase:GetID()
|
||||
ToWaypoint["speed_locked"] = true,
|
||||
|
||||
self:F( ToWaypoint )
|
||||
|
||||
Points[#Points+1] = ToWaypoint
|
||||
|
||||
local PointVec3 = Airplane:GetPointVec3()
|
||||
Template.x = PointVec3.x
|
||||
Template.y = PointVec3.z
|
||||
|
||||
self:T3( Points )
|
||||
|
||||
Template.route.points = Points
|
||||
|
||||
--self:Respawn( Template )
|
||||
|
||||
local GroupSpawned = Airplane:Respawn( Template )
|
||||
|
||||
return GroupSpawned
|
||||
|
||||
local GroupSpawned = Airplane:Respawn(Template)
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- On after Home event. Aircraft will be routed to their home base.
|
||||
-- @param #AI_CARGO_AIRPLANE self
|
||||
-- @param Wrapper.Group#GROUP Airplane The cargo plane.
|
||||
-- @param From From state.
|
||||
-- @param Event Event.
|
||||
-- @param To To State.
|
||||
-- @param Core.Point#COORDINATE Coordinate Home place (not used).
|
||||
-- @param #number Speed Speed in km/h to fly to the home airbase (zone). Default is 80% of max possible speed the unit can go.
|
||||
-- @param #number Height Height in meters to move to the home coordinate.
|
||||
-- @param Core.Zone#ZONE_AIRBASE HomeZone The home airbase (zone) where the plane should return to.
|
||||
function AI_CARGO_AIRPLANE:onafterHome(Airplane, From, Event, To, Coordinate, Speed, Height, HomeZone )
|
||||
if Airplane and Airplane:IsAlive() then
|
||||
|
||||
-- We are going home!
|
||||
self.RouteHome = true
|
||||
|
||||
-- Home Base.
|
||||
local HomeBase=HomeZone:GetAirbase()
|
||||
self.Airbase=HomeBase
|
||||
|
||||
-- Now route the airplane home
|
||||
self:Route( Airplane, HomeBase, Speed, Height )
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,29 +1,144 @@
|
||||
--- **AI** -- (R2.4) - Models the intelligent transportation of infantry and other cargo using APCs.
|
||||
--- **AI** -- (2.4) - Models the intelligent transportation of infantry and other cargo using APCs.
|
||||
--
|
||||
-- ## Features:
|
||||
--
|
||||
-- * Quickly transport cargo to various deploy zones using ground vehicles (APCs, trucks ...).
|
||||
-- * Various @{Cargo.Cargo#CARGO} types can be transported. These are infantry groups and crates.
|
||||
-- * Define a list of deploy zones of various types to transport the cargo to.
|
||||
-- * The vehicles follow the roads to ensure the fastest possible cargo transportation over the ground.
|
||||
-- * Multiple vehicles can transport multiple cargo as one vehicle group.
|
||||
-- * Multiple vehicle groups can be enabled as one collaborating transportation process.
|
||||
-- * Infantry loaded as cargo, will unboard in case enemies are nearby and will help defending the vehicles.
|
||||
-- * Different ranges can be setup for enemy defenses.
|
||||
-- * Different options can be setup to tweak the cargo transporation behaviour.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ## Test Missions:
|
||||
--
|
||||
-- Test missions can be located on the main GITHUB site.
|
||||
--
|
||||
-- [FlightControl-Master/MOOSE_MISSIONS/AID - AI Dispatching/AID-CGO - AI Cargo Dispatching/]
|
||||
-- (https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/AID%20-%20AI%20Dispatching/AID-CGO%20-%20AI%20Cargo%20Dispatching)
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **FlightControl**
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module AI_Cargo_Dispatcher_APC
|
||||
-- @module AI.AI_Cargo_Dispatcher_APC
|
||||
-- @image AI_Cargo_Dispatching_For_APC.JPG
|
||||
|
||||
--- @type AI_CARGO_DISPATCHER_APC
|
||||
-- @extends AI.AI_Cargo_Dispatcher#AI_CARGO_DISPATCHER
|
||||
|
||||
|
||||
--- # AI\_CARGO\_DISPATCHER\_APC class, extends @{Core.Base#BASE}
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- AI\_CARGO\_DISPATCHER\_APC brings a dynamic cargo handling 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.
|
||||
-- The AI\_CARGO\_DISPATCHER\_APC module uses the @{Cargo} capabilities within the MOOSE framework.
|
||||
-- CARGO derived objects must be declared within the mission to make the AI\_CARGO\_DISPATCHER\_APC object recognize the cargo.
|
||||
-- Please consult the @{Cargo} module for more information.
|
||||
--
|
||||
-- The AI_CARGO_DISPATCHER_APC module is derived from the AI_CARGO_DISPATCHER module.
|
||||
--
|
||||
-- ## Note! In order to fully understand the mechanisms of the AI_CARGO_DISPATCHER_APC class, it is recommended that you first consult and READ the documentation of the @{AI.AI_Cargo_Dispatcher} module!!!
|
||||
--
|
||||
-- Especially to learn how to **Tailor the different cargo handling events**, this will be very useful!
|
||||
--
|
||||
-- On top, the AI_CARGO_DISPATCHER_APC class uses the @{Cargo.Cargo} capabilities within the MOOSE framework.
|
||||
-- Also ensure that you fully understand how to declare and setup Cargo objects within the MOOSE framework before using this class.
|
||||
-- CARGO derived objects must be declared within the mission to make the AI_CARGO_DISPATCHER_HELICOPTER object recognize the cargo.
|
||||
--
|
||||
--
|
||||
-- # 1) AI_CARGO_DISPATCHER_APC constructor.
|
||||
--
|
||||
-- * @{#AI_CARGO_DISPATCHER_APC.New}(): Creates a new AI_CARGO_DISPATCHER_APC object.
|
||||
--
|
||||
-- ---
|
||||
--
|
||||
-- # 2) AI_CARGO_DISPATCHER_APC is a Finite State Machine.
|
||||
--
|
||||
-- This section must be read as follows. Each of the rows indicate a state transition, triggered through an event, and with an ending state of the event was executed.
|
||||
-- The first column is the **From** state, the second column the **Event**, and the third column the **To** state.
|
||||
--
|
||||
-- So, each of the rows have the following structure.
|
||||
--
|
||||
-- * **From** => **Event** => **To**
|
||||
--
|
||||
-- Important to know is that an event can only be executed if the **current state** is the **From** state.
|
||||
-- This, when an **Event** that is being triggered has a **From** state that is equal to the **Current** state of the state machine, the event will be executed,
|
||||
-- and the resulting state will be the **To** state.
|
||||
--
|
||||
-- These are the different possible state transitions of this state machine implementation:
|
||||
--
|
||||
-- * Idle => Start => Monitoring
|
||||
-- * Monitoring => Monitor => Monitoring
|
||||
-- * Monitoring => Stop => Idle
|
||||
--
|
||||
-- * Monitoring => Pickup => Monitoring
|
||||
-- * Monitoring => Load => Monitoring
|
||||
-- * Monitoring => Loading => Monitoring
|
||||
-- * Monitoring => Loaded => Monitoring
|
||||
-- * Monitoring => PickedUp => Monitoring
|
||||
-- * Monitoring => Deploy => Monitoring
|
||||
-- * Monitoring => Unload => Monitoring
|
||||
-- * Monitoring => Unloaded => Monitoring
|
||||
-- * Monitoring => Deployed => Monitoring
|
||||
-- * Monitoring => Home => Monitoring
|
||||
--
|
||||
--
|
||||
-- ## 2.1) AI_CARGO_DISPATCHER States.
|
||||
--
|
||||
-- * **Monitoring**: The process is dispatching.
|
||||
-- * **Idle**: The process is idle.
|
||||
--
|
||||
-- ## 2.2) AI_CARGO_DISPATCHER Events.
|
||||
--
|
||||
-- * **Start**: Start the transport process.
|
||||
-- * **Stop**: Stop the transport process.
|
||||
-- * **Monitor**: Monitor and take action.
|
||||
--
|
||||
-- * **Pickup**: Pickup cargo.
|
||||
-- * **Load**: Load the cargo.
|
||||
-- * **Loading**: The dispatcher is coordinating the loading of a cargo.
|
||||
-- * **Loaded**: Flag that the cargo is loaded.
|
||||
-- * **PickedUp**: The dispatcher has loaded all requested cargo into the CarrierGroup.
|
||||
-- * **Deploy**: Deploy cargo to a location.
|
||||
-- * **Unload**: Unload the cargo.
|
||||
-- * **Unloaded**: Flag that the cargo is unloaded.
|
||||
-- * **Deployed**: All cargo is unloaded from the carriers in the group.
|
||||
-- * **Home**: A Carrier is going home.
|
||||
--
|
||||
-- ## 2.3) Enhance your mission scripts with **Tailored** Event Handling!
|
||||
--
|
||||
-- Within your mission, you can capture these events when triggered, and tailor the events with your own code!
|
||||
-- Check out the @{AI.AI_Cargo_Dispatcher#AI_CARGO_DISPATCHER} class at chapter 3 for details on the different event handlers that are available and how to use them.
|
||||
--
|
||||
-- **There are a lot of templates available that allows you to quickly setup an event handler for a specific event type!**
|
||||
--
|
||||
-- ---
|
||||
--
|
||||
-- # 3) Set the pickup parameters.
|
||||
--
|
||||
-- Several parameters can be set to pickup cargo:
|
||||
--
|
||||
-- * @{#AI_CARGO_DISPATCHER_APC.SetPickupRadius}(): Sets or randomizes the pickup location for the APC around the cargo coordinate in a radius defined an outer and optional inner radius.
|
||||
-- * @{#AI_CARGO_DISPATCHER_APC.SetPickupSpeed}(): Set the speed or randomizes the speed in km/h to pickup the cargo.
|
||||
--
|
||||
-- # 4) Set the deploy parameters.
|
||||
--
|
||||
-- Several parameters can be set to deploy cargo:
|
||||
--
|
||||
-- * @{#AI_CARGO_DISPATCHER_APC.SetDeployRadius}(): Sets or randomizes the deploy location for the APC around the cargo coordinate in a radius defined an outer and an optional inner radius.
|
||||
-- * @{#AI_CARGO_DISPATCHER_APC.SetDeploySpeed}(): Set the speed or randomizes the speed in km/h to deploy the cargo.
|
||||
--
|
||||
-- # 5) Set the home zone when there isn't any more cargo to pickup.
|
||||
--
|
||||
-- A home zone can be specified to where the APCs will move when there isn't any cargo left for pickup.
|
||||
-- Use @{#AI_CARGO_DISPATCHER_APC.SetHomeZone}() to specify the home zone.
|
||||
--
|
||||
-- If no home zone is specified, the APCs will wait near the deploy zone for a new pickup command.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @field #AI_CARGO_DISPATCHER_APC
|
||||
AI_CARGO_DISPATCHER_APC = {
|
||||
@@ -32,36 +147,63 @@ AI_CARGO_DISPATCHER_APC = {
|
||||
|
||||
--- Creates a new AI_CARGO_DISPATCHER_APC object.
|
||||
-- @param #AI_CARGO_DISPATCHER_APC self
|
||||
-- @param Core.Set#SET_GROUP SetAPC
|
||||
-- @param Core.Set#SET_CARGO SetCargo
|
||||
-- @param Core.Set#SET_ZONE SetDeployZone
|
||||
-- @param Core.Set#SET_GROUP APCSet The set of @{Wrapper.Group#GROUP} objects of vehicles, trucks, APCs that will transport the cargo.
|
||||
-- @param Core.Set#SET_CARGO CargoSet The set of @{Cargo.Cargo#CARGO} objects, which can be CARGO_GROUP, CARGO_CRATE, CARGO_SLINGLOAD objects.
|
||||
-- @param Core.Set#SET_ZONE PickupZoneSet (optional) The set of pickup zones, which are used to where the cargo can be picked up by the APCs. If nil, then cargo can be picked up everywhere.
|
||||
-- @param Core.Set#SET_ZONE DeployZoneSet The set of deploy zones, which are used to where the cargo will be deployed by the APCs.
|
||||
-- @param DCS#Distance CombatRadius The cargo will be unloaded from the APC and engage the enemy if the enemy is within CombatRadius range. The radius is in meters, the default value is 500 meters.
|
||||
-- @return #AI_CARGO_DISPATCHER_APC
|
||||
-- @usage
|
||||
--
|
||||
-- -- Create a new cargo dispatcher
|
||||
-- SetAPC = SET_GROUP:New():FilterPrefixes( "APC" ):FilterStart()
|
||||
-- SetCargo = SET_CARGO:New():FilterTypes( "Infantry" ):FilterStart()
|
||||
-- SetDeployZone = SET_ZONE:New():FilterPrefixes( "Deploy" ):FilterStart()
|
||||
-- AICargoDispatcher = AI_CARGO_DISPATCHER_APC:New( SetAPC, SetCargo )
|
||||
-- -- An AI dispatcher object for a vehicle squadron, moving infantry from pickup zones to deploy zones.
|
||||
--
|
||||
function AI_CARGO_DISPATCHER_APC:New( SetAPC, SetCargo, SetDeployZones )
|
||||
-- local SetCargoInfantry = SET_CARGO:New():FilterTypes( "Infantry" ):FilterStart()
|
||||
-- local SetAPC = SET_GROUP:New():FilterPrefixes( "APC" ):FilterStart()
|
||||
-- local SetDeployZones = SET_ZONE:New():FilterPrefixes( "Deploy" ):FilterStart()
|
||||
--
|
||||
-- AICargoDispatcherAPC = AI_CARGO_DISPATCHER_APC:New( SetAPC, SetCargoInfantry, nil, SetDeployZones )
|
||||
-- AICargoDispatcherAPC:Start()
|
||||
--
|
||||
function AI_CARGO_DISPATCHER_APC:New( APCSet, CargoSet, PickupZoneSet, DeployZoneSet, CombatRadius )
|
||||
|
||||
local self = BASE:Inherit( self, AI_CARGO_DISPATCHER:New( SetAPC, SetCargo, SetDeployZones ) ) -- #AI_CARGO_DISPATCHER_APC
|
||||
local self = BASE:Inherit( self, AI_CARGO_DISPATCHER:New( APCSet, CargoSet, PickupZoneSet, DeployZoneSet ) ) -- #AI_CARGO_DISPATCHER_APC
|
||||
|
||||
self.CombatRadius = 500
|
||||
|
||||
self:SetDeploySpeed( 70, 120 )
|
||||
self:SetPickupSpeed( 70, 120 )
|
||||
self:SetDeploySpeed( 120, 70 )
|
||||
self:SetPickupSpeed( 120, 70 )
|
||||
self:SetPickupRadius( 0, 0 )
|
||||
self:SetDeployRadius( 0, 0 )
|
||||
|
||||
self:Monitor( 1 )
|
||||
|
||||
self:SetPickupHeight()
|
||||
self:SetDeployHeight()
|
||||
|
||||
self:SetCombatRadius( CombatRadius )
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function AI_CARGO_DISPATCHER_APC:AICargo( APC, CargoSet )
|
||||
|
||||
function AI_CARGO_DISPATCHER_APC:AICargo( APC, SetCargo )
|
||||
|
||||
return AI_CARGO_APC:New( APC, SetCargo, self.CombatRadius )
|
||||
return AI_CARGO_APC:New( APC, CargoSet, self.CombatRadius )
|
||||
end
|
||||
|
||||
--- Enable/Disable unboarding of cargo (infantry) when enemies are nearby (to help defend the carrier).
|
||||
-- This is only valid for APCs and trucks etc, thus ground vehicles.
|
||||
-- @param #AI_CARGO_DISPATCHER_APC self
|
||||
-- @param #number CombatRadius Provide the combat radius to defend the carrier by unboarding the cargo when enemies are nearby.
|
||||
-- When the combat radius is 0, no defense will happen of the carrier.
|
||||
-- When the combat radius is not provided, no defense will happen!
|
||||
-- @return #AI_CARGO_DISPATCHER_APC
|
||||
-- @usage
|
||||
--
|
||||
-- -- Disembark the infantry when the carrier is under attack.
|
||||
-- AICargoDispatcher:SetCombatRadius( true )
|
||||
--
|
||||
-- -- Keep the cargo in the carrier when the carrier is under attack.
|
||||
-- AICargoDispatcher:SetCombatRadius( false )
|
||||
function AI_CARGO_DISPATCHER_APC:SetCombatRadius( CombatRadius )
|
||||
|
||||
self.CombatRadius = CombatRadius or 0
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
@@ -1,27 +1,112 @@
|
||||
--- **AI** -- (R2.4) - Models the intelligent transportation of infantry and other cargo using Planes.
|
||||
--
|
||||
-- ## Features:
|
||||
--
|
||||
-- * The airplanes will fly towards the pickup airbases to pickup the cargo.
|
||||
-- * The airplanes will fly towards the deploy airbases to deploy the cargo.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ## Test Missions:
|
||||
--
|
||||
-- Test missions can be located on the main GITHUB site.
|
||||
--
|
||||
-- [FlightControl-Master/MOOSE_MISSIONS/AID - AI Dispatching/AID-CGO - AI Cargo Dispatching/]
|
||||
-- (https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/AID%20-%20AI%20Dispatching/AID-CGO%20-%20AI%20Cargo%20Dispatching)
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **FlightControl**
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module AI_Cargo_Dispatcher_Airplane
|
||||
-- @module AI.AI_Cargo_Dispatcher_Airplane
|
||||
-- @image AI_Cargo_Dispatching_For_Airplanes.JPG
|
||||
|
||||
|
||||
--- @type AI_CARGO_DISPATCHER_AIRPLANE
|
||||
-- @extends AI.AI_Cargo_Dispatcher#AI_CARGO_DISPATCHER
|
||||
|
||||
|
||||
--- # AI\_CARGO\_DISPATCHER\_AIRPLANE class, extends @{Core.Base#BASE}
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- AI\_CARGO\_DISPATCHER\_AIRPLANE 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.
|
||||
-- The AI\_CARGO\_DISPATCHER\_AIRPLANE module uses the @{Cargo} capabilities within the MOOSE framework.
|
||||
-- CARGO derived objects must be declared within the mission to make the AI\_CARGO\_DISPATCHER\_AIRPLANE object recognize the cargo.
|
||||
-- Please consult the @{Cargo} module for more information.
|
||||
--
|
||||
-- The AI_CARGO_DISPATCHER_AIRPLANE module is derived from the AI_CARGO_DISPATCHER module.
|
||||
--
|
||||
-- ## Note! In order to fully understand the mechanisms of the AI_CARGO_DISPATCHER_AIRPLANE class, it is recommended that you first consult and READ the documentation of the @{AI.AI_Cargo_Dispatcher} module!!!**
|
||||
--
|
||||
-- Especially to learn how to **Tailor the different cargo handling events**, this will be very useful!
|
||||
--
|
||||
-- On top, the AI_CARGO_DISPATCHER_AIRPLANE class uses the @{Cargo.Cargo} capabilities within the MOOSE framework.
|
||||
-- Also ensure that you fully understand how to declare and setup Cargo objects within the MOOSE framework before using this class.
|
||||
-- CARGO derived objects must be declared within the mission to make the AI_CARGO_DISPATCHER_HELICOPTER object recognize the cargo.
|
||||
--
|
||||
-- # 1) AI_CARGO_DISPATCHER_AIRPLANE constructor.
|
||||
--
|
||||
-- * @{#AI_CARGO_DISPATCHER_AIRPLANE.New}(): Creates a new AI_CARGO_DISPATCHER_AIRPLANE object.
|
||||
--
|
||||
-- ---
|
||||
--
|
||||
-- # 2) AI_CARGO_DISPATCHER_AIRPLANE is a Finite State Machine.
|
||||
--
|
||||
-- This section must be read as follows. Each of the rows indicate a state transition, triggered through an event, and with an ending state of the event was executed.
|
||||
-- The first column is the **From** state, the second column the **Event**, and the third column the **To** state.
|
||||
--
|
||||
-- So, each of the rows have the following structure.
|
||||
--
|
||||
-- * **From** => **Event** => **To**
|
||||
--
|
||||
-- Important to know is that an event can only be executed if the **current state** is the **From** state.
|
||||
-- This, when an **Event** that is being triggered has a **From** state that is equal to the **Current** state of the state machine, the event will be executed,
|
||||
-- and the resulting state will be the **To** state.
|
||||
--
|
||||
-- These are the different possible state transitions of this state machine implementation:
|
||||
--
|
||||
-- * Idle => Start => Monitoring
|
||||
-- * Monitoring => Monitor => Monitoring
|
||||
-- * Monitoring => Stop => Idle
|
||||
--
|
||||
-- * Monitoring => Pickup => Monitoring
|
||||
-- * Monitoring => Load => Monitoring
|
||||
-- * Monitoring => Loading => Monitoring
|
||||
-- * Monitoring => Loaded => Monitoring
|
||||
-- * Monitoring => PickedUp => Monitoring
|
||||
-- * Monitoring => Deploy => Monitoring
|
||||
-- * Monitoring => Unload => Monitoring
|
||||
-- * Monitoring => Unloaded => Monitoring
|
||||
-- * Monitoring => Deployed => Monitoring
|
||||
-- * Monitoring => Home => Monitoring
|
||||
--
|
||||
--
|
||||
-- ## 2.1) AI_CARGO_DISPATCHER States.
|
||||
--
|
||||
-- * **Monitoring**: The process is dispatching.
|
||||
-- * **Idle**: The process is idle.
|
||||
--
|
||||
-- ## 2.2) AI_CARGO_DISPATCHER Events.
|
||||
--
|
||||
-- * **Start**: Start the transport process.
|
||||
-- * **Stop**: Stop the transport process.
|
||||
-- * **Monitor**: Monitor and take action.
|
||||
--
|
||||
-- * **Pickup**: Pickup cargo.
|
||||
-- * **Load**: Load the cargo.
|
||||
-- * **Loading**: The dispatcher is coordinating the loading of a cargo.
|
||||
-- * **Loaded**: Flag that the cargo is loaded.
|
||||
-- * **PickedUp**: The dispatcher has loaded all requested cargo into the CarrierGroup.
|
||||
-- * **Deploy**: Deploy cargo to a location.
|
||||
-- * **Unload**: Unload the cargo.
|
||||
-- * **Unloaded**: Flag that the cargo is unloaded.
|
||||
-- * **Deployed**: All cargo is unloaded from the carriers in the group.
|
||||
-- * **Home**: A Carrier is going home.
|
||||
--
|
||||
-- ## 2.3) Enhance your mission scripts with **Tailored** Event Handling!
|
||||
--
|
||||
-- Within your mission, you can capture these events when triggered, and tailor the events with your own code!
|
||||
-- Check out the @{AI.AI_Cargo_Dispatcher#AI_CARGO_DISPATCHER} class at chapter 3 for details on the different event handlers that are available and how to use them.
|
||||
--
|
||||
-- **There are a lot of templates available that allows you to quickly setup an event handler for a specific event type!**
|
||||
--
|
||||
--
|
||||
--
|
||||
@@ -32,23 +117,48 @@ AI_CARGO_DISPATCHER_AIRPLANE = {
|
||||
|
||||
--- Creates a new AI_CARGO_DISPATCHER_AIRPLANE object.
|
||||
-- @param #AI_CARGO_DISPATCHER_AIRPLANE self
|
||||
-- @param Core.Set#SET_GROUP SetAirplane
|
||||
-- @param Core.Set#SET_CARGO SetCargo
|
||||
-- @param Core.Set#SET_ZONE SetDeployZone
|
||||
-- @return #AI_CARGO_DISPATCHER_AIRPLANE
|
||||
-- @param Core.Set#SET_GROUP AirplaneSet The set of @{Wrapper.Group#GROUP} objects of airplanes that will transport the cargo.
|
||||
-- @param Core.Set#SET_CARGO CargoSet The set of @{Cargo.Cargo#CARGO} objects, which can be CARGO_GROUP, CARGO_CRATE, CARGO_SLINGLOAD objects.
|
||||
-- @param Core.Zone#SET_ZONE PickupZoneSet The set of zone airbases where the cargo has to be picked up.
|
||||
-- @param Core.Zone#SET_ZONE DeployZoneSet The set of zone airbases where the cargo is deployed. Choice for each cargo is random.
|
||||
-- @return #AI_CARGO_DISPATCHER_AIRPLANE self
|
||||
-- @usage
|
||||
--
|
||||
-- -- Create a new cargo dispatcher
|
||||
-- SetAirplane = SET_GROUP:New():FilterPrefixes( "Airplane" ):FilterStart()
|
||||
-- SetCargo = SET_CARGO:New():FilterTypes( "Infantry" ):FilterStart()
|
||||
-- SetDeployZone = SET_ZONE:New():FilterPrefixes( "Deploy" ):FilterStart()
|
||||
-- AICargoDispatcher = AI_CARGO_DISPATCHER_AIRPLANE:New( SetAirplane, SetCargo )
|
||||
-- -- An AI dispatcher object for an airplane squadron, moving infantry and vehicles from pickup airbases to deploy airbases.
|
||||
--
|
||||
-- local CargoInfantrySet = SET_CARGO:New():FilterTypes( "Infantry" ):FilterStart()
|
||||
-- local AirplanesSet = SET_GROUP:New():FilterPrefixes( "Airplane" ):FilterStart()
|
||||
-- local PickupZoneSet = SET_ZONE:New()
|
||||
-- local DeployZoneSet = SET_ZONE:New()
|
||||
--
|
||||
-- PickupZoneSet:AddZone( ZONE_AIRBASE:New( AIRBASE.Caucasus.Gudauta ) )
|
||||
-- DeployZoneSet:AddZone( ZONE_AIRBASE:New( AIRBASE.Caucasus.Sochi_Adler ) )
|
||||
-- DeployZoneSet:AddZone( ZONE_AIRBASE:New( AIRBASE.Caucasus.Maykop_Khanskaya ) )
|
||||
-- DeployZoneSet:AddZone( ZONE_AIRBASE:New( AIRBASE.Caucasus.Mineralnye_Vody ) )
|
||||
-- DeployZoneSet:AddZone( ZONE_AIRBASE:New( AIRBASE.Caucasus.Vaziani ) )
|
||||
--
|
||||
-- AICargoDispatcherAirplanes = AI_CARGO_DISPATCHER_AIRPLANE:New( AirplanesSet, CargoInfantrySet, PickupZoneSet, DeployZoneSet )
|
||||
-- AICargoDispatcherAirplanes:Start()
|
||||
--
|
||||
function AI_CARGO_DISPATCHER_AIRPLANE:New( SetAirplane, SetCargo, SetDeployZones )
|
||||
function AI_CARGO_DISPATCHER_AIRPLANE:New( AirplaneSet, CargoSet, PickupZoneSet, DeployZoneSet )
|
||||
|
||||
local self = BASE:Inherit( self, AI_CARGO_DISPATCHER:New( SetAirplane, SetCargo, SetDeployZones ) ) -- #AI_CARGO_DISPATCHER_AIRPLANE
|
||||
local self = BASE:Inherit( self, AI_CARGO_DISPATCHER:New( AirplaneSet, CargoSet, PickupZoneSet, DeployZoneSet ) ) -- #AI_CARGO_DISPATCHER_AIRPLANE
|
||||
|
||||
self:SetPickupSpeed( 1200, 600 )
|
||||
self:SetDeploySpeed( 1200, 600 )
|
||||
|
||||
self:SetPickupRadius( 0, 0 )
|
||||
self:SetDeployRadius( 0, 0 )
|
||||
|
||||
self:SetPickupHeight( 8000, 6000 )
|
||||
self:SetDeployHeight( 8000, 6000 )
|
||||
|
||||
self:SetMonitorTimeInterval( 600 )
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function AI_CARGO_DISPATCHER_AIRPLANE:AICargo( Airplane, CargoSet )
|
||||
|
||||
return AI_CARGO_AIRPLANE:New( Airplane, CargoSet )
|
||||
end
|
||||
|
||||
@@ -1,29 +1,147 @@
|
||||
--- **AI** -- (R2.4) - Models the intelligent transportation of infantry and other cargo using Helicopters.
|
||||
--- **AI** -- (2.4) - Models the intelligent transportation of infantry and other cargo using Helicopters.
|
||||
--
|
||||
-- ## Features:
|
||||
--
|
||||
-- * The helicopters will fly towards the pickup locations to pickup the cargo.
|
||||
-- * The helicopters will fly towards the deploy zones to deploy the cargo.
|
||||
-- * Precision deployment as well as randomized deployment within the deploy zones are possible.
|
||||
-- * Helicopters will orbit the deploy zones when there is no space for landing until the deploy zone is free.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ## Test Missions:
|
||||
--
|
||||
-- Test missions can be located on the main GITHUB site.
|
||||
--
|
||||
-- [FlightControl-Master/MOOSE_MISSIONS/AID - AI Dispatching/AID-CGO - AI Cargo Dispatching/]
|
||||
-- (https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/AID%20-%20AI%20Dispatching/AID-CGO%20-%20AI%20Cargo%20Dispatching)
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **FlightControl**
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module AI_Cargo_Dispatcher_Helicopter
|
||||
-- @module AI.AI_Cargo_Dispatcher_Helicopter
|
||||
-- @image AI_Cargo_Dispatching_For_Helicopters.JPG
|
||||
|
||||
--- @type AI_CARGO_DISPATCHER_HELICOPTER
|
||||
-- @extends AI.AI_Cargo_Dispatcher#AI_CARGO_DISPATCHER
|
||||
|
||||
|
||||
--- # AI\_CARGO\_DISPATCHER\_HELICOPTER class, extends @{Core.Base#BASE}
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- AI\_CARGO\_DISPATCHER\_HELICOPTER brings a dynamic cargo handling capability for AI groups.
|
||||
--- A dynamic cargo handling capability for AI helicopter groups.
|
||||
--
|
||||
-- Helicopters can be mobilized to intelligently transport infantry and other cargo within the simulation.
|
||||
-- The AI\_CARGO\_DISPATCHER\_HELICOPTER module uses the @{Cargo} capabilities within the MOOSE framework.
|
||||
-- CARGO derived objects must be declared within the mission to make the AI\_CARGO\_DISPATCHER\_HELICOPTER object recognize the cargo.
|
||||
-- Please consult the @{Cargo} module for more information.
|
||||
--
|
||||
--
|
||||
-- The AI_CARGO_DISPATCHER_HELICOPTER module is derived from the AI_CARGO_DISPATCHER module.
|
||||
--
|
||||
-- ## Note! In order to fully understand the mechanisms of the AI_CARGO_DISPATCHER_HELICOPTER class, it is recommended that you first consult and READ the documentation of the @{AI.AI_Cargo_Dispatcher} module!!!**
|
||||
--
|
||||
-- Especially to learn how to **Tailor the different cargo handling events**, this will be very useful!
|
||||
--
|
||||
-- On top, the AI_CARGO_DISPATCHER_HELICOPTER class uses the @{Cargo.Cargo} capabilities within the MOOSE framework.
|
||||
-- Also ensure that you fully understand how to declare and setup Cargo objects within the MOOSE framework before using this class.
|
||||
-- CARGO derived objects must be declared within the mission to make the AI_CARGO_DISPATCHER_HELICOPTER object recognize the cargo.
|
||||
--
|
||||
-- ---
|
||||
--
|
||||
-- # 1. AI\_CARGO\_DISPATCHER\_HELICOPTER constructor.
|
||||
--
|
||||
-- * @{#AI_CARGO_DISPATCHER\_HELICOPTER.New}(): Creates a new AI\_CARGO\_DISPATCHER\_HELICOPTER object.
|
||||
--
|
||||
-- ---
|
||||
--
|
||||
-- # 2. AI\_CARGO\_DISPATCHER\_HELICOPTER is a Finite State Machine.
|
||||
--
|
||||
-- This section must be read as follows. Each of the rows indicate a state transition, triggered through an event, and with an ending state of the event was executed.
|
||||
-- The first column is the **From** state, the second column the **Event**, and the third column the **To** state.
|
||||
--
|
||||
-- So, each of the rows have the following structure.
|
||||
--
|
||||
-- * **From** => **Event** => **To**
|
||||
--
|
||||
-- Important to know is that an event can only be executed if the **current state** is the **From** state.
|
||||
-- This, when an **Event** that is being triggered has a **From** state that is equal to the **Current** state of the state machine, the event will be executed,
|
||||
-- and the resulting state will be the **To** state.
|
||||
--
|
||||
-- These are the different possible state transitions of this state machine implementation:
|
||||
--
|
||||
-- * Idle => Start => Monitoring
|
||||
-- * Monitoring => Monitor => Monitoring
|
||||
-- * Monitoring => Stop => Idle
|
||||
--
|
||||
-- * Monitoring => Pickup => Monitoring
|
||||
-- * Monitoring => Load => Monitoring
|
||||
-- * Monitoring => Loading => Monitoring
|
||||
-- * Monitoring => Loaded => Monitoring
|
||||
-- * Monitoring => PickedUp => Monitoring
|
||||
-- * Monitoring => Deploy => Monitoring
|
||||
-- * Monitoring => Unload => Monitoring
|
||||
-- * Monitoring => Unloaded => Monitoring
|
||||
-- * Monitoring => Deployed => Monitoring
|
||||
-- * Monitoring => Home => Monitoring
|
||||
--
|
||||
--
|
||||
-- ## 2.1) AI_CARGO_DISPATCHER States.
|
||||
--
|
||||
-- * **Monitoring**: The process is dispatching.
|
||||
-- * **Idle**: The process is idle.
|
||||
--
|
||||
-- ## 2.2) AI_CARGO_DISPATCHER Events.
|
||||
--
|
||||
-- * **Start**: Start the transport process.
|
||||
-- * **Stop**: Stop the transport process.
|
||||
-- * **Monitor**: Monitor and take action.
|
||||
--
|
||||
-- * **Pickup**: Pickup cargo.
|
||||
-- * **Load**: Load the cargo.
|
||||
-- * **Loading**: The dispatcher is coordinating the loading of a cargo.
|
||||
-- * **Loaded**: Flag that the cargo is loaded.
|
||||
-- * **PickedUp**: The dispatcher has loaded all requested cargo into the CarrierGroup.
|
||||
-- * **Deploy**: Deploy cargo to a location.
|
||||
-- * **Unload**: Unload the cargo.
|
||||
-- * **Unloaded**: Flag that the cargo is unloaded.
|
||||
-- * **Deployed**: All cargo is unloaded from the carriers in the group.
|
||||
-- * **Home**: A Carrier is going home.
|
||||
--
|
||||
-- ## 2.3) Enhance your mission scripts with **Tailored** Event Handling!
|
||||
--
|
||||
-- Within your mission, you can capture these events when triggered, and tailor the events with your own code!
|
||||
-- Check out the @{AI.AI_Cargo_Dispatcher#AI_CARGO_DISPATCHER} class at chapter 3 for details on the different event handlers that are available and how to use them.
|
||||
--
|
||||
-- **There are a lot of templates available that allows you to quickly setup an event handler for a specific event type!**
|
||||
--
|
||||
-- ---
|
||||
--
|
||||
-- ## 3. Set the pickup parameters.
|
||||
--
|
||||
-- Several parameters can be set to pickup cargo:
|
||||
--
|
||||
-- * @{#AI_CARGO_DISPATCHER_HELICOPTER.SetPickupRadius}(): Sets or randomizes the pickup location for the helicopter around the cargo coordinate in a radius defined an outer and optional inner radius.
|
||||
-- * @{#AI_CARGO_DISPATCHER_HELICOPTER.SetPickupSpeed}(): Set the speed or randomizes the speed in km/h to pickup the cargo.
|
||||
-- * @{#AI_CARGO_DISPATCHER_HELICOPTER.SetPickupHeight}(): Set the height or randomizes the height in meters to pickup the cargo.
|
||||
--
|
||||
-- ---
|
||||
--
|
||||
-- ## 4. Set the deploy parameters.
|
||||
--
|
||||
-- Several parameters can be set to deploy cargo:
|
||||
--
|
||||
-- * @{#AI_CARGO_DISPATCHER_HELICOPTER.SetDeployRadius}(): Sets or randomizes the deploy location for the helicopter around the cargo coordinate in a radius defined an outer and an optional inner radius.
|
||||
-- * @{#AI_CARGO_DISPATCHER_HELICOPTER.SetDeploySpeed}(): Set the speed or randomizes the speed in km/h to deploy the cargo.
|
||||
-- * @{#AI_CARGO_DISPATCHER_HELICOPTER.SetDeployHeight}(): Set the height or randomizes the height in meters to deploy the cargo.
|
||||
--
|
||||
-- ---
|
||||
--
|
||||
-- ## 5. Set the home zone when there isn't any more cargo to pickup.
|
||||
--
|
||||
-- A home zone can be specified to where the Helicopters will move when there isn't any cargo left for pickup.
|
||||
-- Use @{#AI_CARGO_DISPATCHER_HELICOPTER.SetHomeZone}() to specify the home zone.
|
||||
--
|
||||
-- If no home zone is specified, the helicopters will wait near the deploy zone for a new pickup command.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @field #AI_CARGO_DISPATCHER_HELICOPTER
|
||||
AI_CARGO_DISPATCHER_HELICOPTER = {
|
||||
@@ -32,34 +150,42 @@ AI_CARGO_DISPATCHER_HELICOPTER = {
|
||||
|
||||
--- Creates a new AI_CARGO_DISPATCHER_HELICOPTER object.
|
||||
-- @param #AI_CARGO_DISPATCHER_HELICOPTER self
|
||||
-- @param Core.Set#SET_GROUP SetHelicopter
|
||||
-- @param Core.Set#SET_CARGO SetCargo
|
||||
-- @param Core.Set#SET_ZONE SetDeployZone
|
||||
-- @param Core.Set#SET_GROUP HelicopterSet The set of @{Wrapper.Group#GROUP} objects of helicopters that will transport the cargo.
|
||||
-- @param Core.Set#SET_CARGO CargoSet The set of @{Cargo.Cargo#CARGO} objects, which can be CARGO_GROUP, CARGO_CRATE, CARGO_SLINGLOAD objects.
|
||||
-- @param Core.Set#SET_ZONE PickupZoneSet (optional) The set of pickup zones, which are used to where the cargo can be picked up by the APCs. If nil, then cargo can be picked up everywhere.
|
||||
-- @param Core.Set#SET_ZONE DeployZoneSet The set of deploy zones, which are used to where the cargo will be deployed by the Helicopters.
|
||||
-- @return #AI_CARGO_DISPATCHER_HELICOPTER
|
||||
-- @usage
|
||||
--
|
||||
-- -- Create a new cargo dispatcher
|
||||
-- SetHelicopter = SET_GROUP:New():FilterPrefixes( "Helicopter" ):FilterStart()
|
||||
-- SetCargo = SET_CARGO:New():FilterTypes( "Infantry" ):FilterStart()
|
||||
-- SetDeployZone = SET_ZONE:New():FilterPrefixes( "Deploy" ):FilterStart()
|
||||
-- AICargoDispatcher = AI_CARGO_DISPATCHER_HELICOPTER:New( SetHelicopter, SetCargo )
|
||||
-- -- An AI dispatcher object for a helicopter squadron, moving infantry from pickup zones to deploy zones.
|
||||
--
|
||||
function AI_CARGO_DISPATCHER_HELICOPTER:New( SetHelicopter, SetCargo, SetDeployZones )
|
||||
-- local SetCargoInfantry = SET_CARGO:New():FilterTypes( "Infantry" ):FilterStart()
|
||||
-- local SetHelicopter = SET_GROUP:New():FilterPrefixes( "Helicopter" ):FilterStart()
|
||||
-- local SetPickupZones = SET_ZONE:New():FilterPrefixes( "Pickup" ):FilterStart()
|
||||
-- local SetDeployZones = SET_ZONE:New():FilterPrefixes( "Deploy" ):FilterStart()
|
||||
--
|
||||
-- AICargoDispatcherHelicopter = AI_CARGO_DISPATCHER_HELICOPTER:New( SetHelicopter, SetCargoInfantry, SetPickupZones, SetDeployZones )
|
||||
-- AICargoDispatcherHelicopter:Start()
|
||||
--
|
||||
function AI_CARGO_DISPATCHER_HELICOPTER:New( HelicopterSet, CargoSet, PickupZoneSet, DeployZoneSet )
|
||||
|
||||
local self = BASE:Inherit( self, AI_CARGO_DISPATCHER:New( SetHelicopter, SetCargo, SetDeployZones ) ) -- #AI_CARGO_DISPATCHER_HELICOPTER
|
||||
local self = BASE:Inherit( self, AI_CARGO_DISPATCHER:New( HelicopterSet, CargoSet, PickupZoneSet, DeployZoneSet ) ) -- #AI_CARGO_DISPATCHER_HELICOPTER
|
||||
|
||||
self:SetPickupSpeed( 350, 150 )
|
||||
self:SetDeploySpeed( 350, 150 )
|
||||
|
||||
self:SetDeploySpeed( 200, 150 )
|
||||
self:SetPickupSpeed( 200, 150 )
|
||||
self:SetPickupRadius( 0, 0 )
|
||||
self:SetDeployRadius( 0, 0 )
|
||||
|
||||
self:Monitor( 1 )
|
||||
|
||||
|
||||
self:SetPickupHeight( 500, 200 )
|
||||
self:SetDeployHeight( 500, 200 )
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function AI_CARGO_DISPATCHER_HELICOPTER:AICargo( Helicopter, SetCargo )
|
||||
|
||||
return AI_CARGO_HELICOPTER:New( Helicopter, SetCargo )
|
||||
function AI_CARGO_DISPATCHER_HELICOPTER:AICargo( Helicopter, CargoSet )
|
||||
|
||||
return AI_CARGO_HELICOPTER:New( Helicopter, CargoSet )
|
||||
end
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
--- **AI** -- (R2.3) - Models the intelligent transportation of infantry (cargo).
|
||||
--- **AI** -- (R2.4) - Models the intelligent transportation of infantry (cargo).
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
@@ -6,20 +6,48 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module AI_Cargo_Helicopter
|
||||
-- @module AI.AI_Cargo_Helicopter
|
||||
-- @image AI_Cargo_Dispatching_For_Helicopters.JPG
|
||||
|
||||
--- @type AI_CARGO_HELICOPTER
|
||||
-- @extends Core.Fsm#FSM_CONTROLLABLE
|
||||
|
||||
|
||||
--- # AI\_CARGO\_TROOPS class, extends @{Core.Base@BASE}
|
||||
--- 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.
|
||||
--
|
||||
-- The AI_CARGO_HELICOPTER class uses the @{Cargo.Cargo} capabilities within the MOOSE framework.
|
||||
-- @{Cargo.Cargo} must be declared within the mission to make the AI_CARGO_HELICOPTER object recognize the cargo.
|
||||
-- Please consult the @{Cargo.Cargo} module for more information.
|
||||
--
|
||||
-- ## Cargo pickup.
|
||||
--
|
||||
-- Using the @{#AI_CARGO_HELICOPTER.Pickup}() method, you are able to direct the helicopters towards a point on the battlefield to board/load the cargo at the specific coordinate.
|
||||
-- Ensure that the landing zone is horizontally flat, and that trees cannot be found in the landing vicinity, or the helicopters won't land or will even crash!
|
||||
--
|
||||
-- ## Cargo deployment.
|
||||
--
|
||||
-- Using the @{#AI_CARGO_HELICOPTER.Deploy}() method, you are able to direct the helicopters towards a point on the battlefield to unboard/unload the cargo at the specific coordinate.
|
||||
-- Ensure that the landing zone is horizontally flat, and that trees cannot be found in the landing vicinity, or the helicopters won't land or will even crash!
|
||||
--
|
||||
-- ## Infantry health.
|
||||
--
|
||||
-- When infantry is unboarded from the APCs, the infantry is actually respawned into the battlefield.
|
||||
-- As a result, the unboarding infantry is very _healthy_ every time it unboards.
|
||||
-- This is due to the limitation of the DCS simulator, which is not able to specify the health of new spawned units as a parameter.
|
||||
-- However, infantry that was destroyed when unboarded, won't be respawned again. Destroyed is destroyed.
|
||||
-- As a result, there is some additional strength that is gained when an unboarding action happens, but in terms of simulation balance this has
|
||||
-- marginal impact on the overall battlefield simulation. Fortunately, the firing strength of infantry is limited, and thus, respacing healthy infantry every
|
||||
-- time is not so much of an issue ...
|
||||
--
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @field #AI_CARGO_HELICOPTER
|
||||
AI_CARGO_HELICOPTER = {
|
||||
ClassName = "AI_CARGO_HELICOPTER",
|
||||
Coordinate = nil -- Core.Point#COORDINATE,
|
||||
Coordinate = nil, -- Core.Point#COORDINATE,
|
||||
}
|
||||
|
||||
AI_CARGO_QUEUE = {}
|
||||
@@ -28,14 +56,11 @@ AI_CARGO_QUEUE = {}
|
||||
-- @param #AI_CARGO_HELICOPTER self
|
||||
-- @param Wrapper.Group#GROUP Helicopter
|
||||
-- @param Core.Set#SET_CARGO CargoSet
|
||||
-- @param #number CombatRadius
|
||||
-- @return #AI_CARGO_HELICOPTER
|
||||
function AI_CARGO_HELICOPTER:New( Helicopter, CargoSet )
|
||||
|
||||
local self = BASE:Inherit( self, FSM_CONTROLLABLE:New() ) -- #AI_CARGO_HELICOPTER
|
||||
local self = BASE:Inherit( self, AI_CARGO:New( Helicopter, CargoSet ) ) -- #AI_CARGO_HELICOPTER
|
||||
|
||||
self.CargoSet = CargoSet -- Cargo.CargoGroup#CARGO_GROUP
|
||||
|
||||
self.Zone = ZONE_GROUP:New( Helicopter:GetName(), Helicopter, 300 )
|
||||
|
||||
self:SetStartState( "Unloaded" )
|
||||
@@ -43,12 +68,14 @@ function AI_CARGO_HELICOPTER:New( Helicopter, CargoSet )
|
||||
self:AddTransition( "Unloaded", "Pickup", "*" )
|
||||
self:AddTransition( "Loaded", "Deploy", "*" )
|
||||
|
||||
self:AddTransition( "Unloaded", "Load", "Boarding" )
|
||||
self:AddTransition( { "Unloaded", "Loading" }, "Load", "Boarding" )
|
||||
self:AddTransition( "Boarding", "Board", "Boarding" )
|
||||
self:AddTransition( "Boarding", "Loaded", "Loaded" )
|
||||
self:AddTransition( "Boarding", "Loaded", "Boarding" )
|
||||
self:AddTransition( "Boarding", "PickedUp", "Loaded" )
|
||||
self:AddTransition( "Loaded", "Unload", "Unboarding" )
|
||||
self:AddTransition( "Unboarding", "Unboard", "Unboarding" )
|
||||
self:AddTransition( "Unboarding", "Unloaded", "Unloaded" )
|
||||
self:AddTransition( "Unboarding", "Unloaded", "Unboarding" )
|
||||
self:AddTransition( "Unboarding", "Deployed", "Unloaded" )
|
||||
|
||||
self:AddTransition( "*", "Landed", "*" )
|
||||
self:AddTransition( "*", "Queue", "*" )
|
||||
@@ -73,17 +100,20 @@ function AI_CARGO_HELICOPTER:New( Helicopter, CargoSet )
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @param Core.Point#COORDINATE Coordinate
|
||||
-- @param #number Speed Speed in km/h to drive to the pickup coordinate. Default is 50% of max possible speed the unit can go.
|
||||
|
||||
--- Pickup Trigger for AI_CARGO_HELICOPTER
|
||||
-- @function [parent=#AI_CARGO_HELICOPTER] Pickup
|
||||
-- @param #AI_CARGO_HELICOPTER self
|
||||
-- @param Core.Point#COORDINATE Coordinate
|
||||
-- @param #number Speed Speed in km/h to drive to the pickup coordinate. Default is 50% of max possible speed the unit can go.
|
||||
|
||||
--- Pickup Asynchronous Trigger for AI_CARGO_HELICOPTER
|
||||
-- @function [parent=#AI_CARGO_HELICOPTER] __Pickup
|
||||
-- @param #AI_CARGO_HELICOPTER self
|
||||
-- @param #number Delay
|
||||
-- @param #number Delay Delay in seconds.
|
||||
-- @param Core.Point#COORDINATE Coordinate
|
||||
-- @param #number Speed Speed in km/h to go to the pickup coordinate. Default is 50% of max possible speed the unit can go.
|
||||
|
||||
--- Deploy Handler OnBefore for AI_CARGO_HELICOPTER
|
||||
-- @function [parent=#AI_CARGO_HELICOPTER] OnBeforeDeploy
|
||||
@@ -91,7 +121,8 @@ function AI_CARGO_HELICOPTER:New( Helicopter, CargoSet )
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @param Core.Point#COORDINATE Coordinate
|
||||
-- @param Core.Point#COORDINATE Coordinate Place at which cargo is deployed.
|
||||
-- @param #number Speed Speed in km/h to drive to the pickup coordinate. Default is 50% of max possible speed the unit can go.
|
||||
-- @return #boolean
|
||||
|
||||
--- Deploy Handler OnAfter for AI_CARGO_HELICOPTER
|
||||
@@ -101,34 +132,52 @@ function AI_CARGO_HELICOPTER:New( Helicopter, CargoSet )
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @param Core.Point#COORDINATE Coordinate
|
||||
-- @param #number Speed Speed in km/h to drive to the pickup coordinate. Default is 50% of max possible speed the unit can go.
|
||||
|
||||
--- Deploy Trigger for AI_CARGO_HELICOPTER
|
||||
-- @function [parent=#AI_CARGO_HELICOPTER] Deploy
|
||||
-- @param #AI_CARGO_HELICOPTER self
|
||||
-- @param Core.Point#COORDINATE Coordinate
|
||||
-- @param Core.Point#COORDINATE Coordinate Place at which the cargo is deployed.
|
||||
-- @param #number Speed Speed in km/h to drive to the pickup coordinate. Default is 50% of max possible speed the unit can go.
|
||||
|
||||
--- Deploy Asynchronous Trigger for AI_CARGO_HELICOPTER
|
||||
-- @function [parent=#AI_CARGO_HELICOPTER] __Deploy
|
||||
-- @param #number Delay Delay in seconds.
|
||||
-- @param #AI_CARGO_HELICOPTER self
|
||||
-- @param Core.Point#COORDINATE Coordinate
|
||||
-- @param #number Delay
|
||||
-- @param Core.Point#COORDINATE Coordinate Place at which the cargo is deployed.
|
||||
-- @param #number Speed Speed in km/h to drive to the pickup coordinate. Default is 50% of max possible speed the unit can go.
|
||||
|
||||
|
||||
-- We need to capture the Crash events for the helicopters.
|
||||
-- The helicopter reference is used in the semaphore AI_CARGO_QUEUE.
|
||||
-- So, we need to unlock this when the helo is not anymore ...
|
||||
Helicopter:HandleEvent( EVENTS.Crash,
|
||||
function( Helicopter, EventData )
|
||||
AI_CARGO_QUEUE[Helicopter] = nil
|
||||
end
|
||||
)
|
||||
|
||||
-- We need to capture the Land events for the helicopters.
|
||||
-- The helicopter reference is used in the semaphore AI_CARGO_QUEUE.
|
||||
-- So, we need to unlock this when the helo has landed, which can be anywhere ...
|
||||
-- But only free the landing coordinate after 1 minute, to ensure that all helos have left.
|
||||
Helicopter:HandleEvent( EVENTS.Land,
|
||||
function( Helicopter, EventData )
|
||||
self:ScheduleOnce( 60,
|
||||
function( Helicopter )
|
||||
AI_CARGO_QUEUE[Helicopter] = nil
|
||||
end, Helicopter
|
||||
)
|
||||
end
|
||||
)
|
||||
|
||||
self:SetCarrier( Helicopter )
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function AI_CARGO_HELICOPTER:IsTransporting()
|
||||
|
||||
return self.Transporting == true
|
||||
end
|
||||
|
||||
function AI_CARGO_HELICOPTER:IsRelocating()
|
||||
|
||||
return self.Relocating == true
|
||||
end
|
||||
|
||||
|
||||
--- Set the Carrier.
|
||||
@@ -161,19 +210,6 @@ function AI_CARGO_HELICOPTER:SetCarrier( Helicopter )
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function Helicopter:OnEventHit( EventData )
|
||||
local AICargoTroops = self:GetState( self, "AI_CARGO_HELICOPTER" )
|
||||
if AICargoTroops then
|
||||
self:F( { OnHitLoaded = AICargoTroops:Is( "Loaded" ) } )
|
||||
if AICargoTroops:Is( "Loaded" ) or AICargoTroops:Is( "Boarding" ) then
|
||||
-- There are enemies within combat range. Unload the Helicopter.
|
||||
AICargoTroops:Unload()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function Helicopter:OnEventLand( EventData )
|
||||
AICargo:Landed()
|
||||
end
|
||||
@@ -191,23 +227,34 @@ end
|
||||
-- @param From
|
||||
-- @param Event
|
||||
-- @param To
|
||||
-- @param Core.Point#COORDINATE Coordinate
|
||||
-- @param #number Speed
|
||||
function AI_CARGO_HELICOPTER:onafterLanded( Helicopter, From, Event, To )
|
||||
|
||||
Helicopter:F( { Name = Helicopter:GetName() } )
|
||||
|
||||
if Helicopter and Helicopter:IsAlive() then
|
||||
|
||||
-- S_EVENT_LAND is directly called in two situations:
|
||||
-- 1 - When the helo lands normally on the ground.
|
||||
-- 2 - when the helo is hit and goes RTB or even when it is destroyed.
|
||||
-- For point 2, this is an issue, the infantry may not unload in this case!
|
||||
-- So we check if the helo is on the ground, and velocity< 5.
|
||||
-- Only then the infantry can unload (and load too, for consistency)!
|
||||
|
||||
self:F( { Helicopter:GetName(), Height = Helicopter:GetHeight( true ), Velocity = Helicopter:GetVelocityKMH() } )
|
||||
|
||||
if self.RoutePickup == true then
|
||||
self:Load( Helicopter:GetPointVec2() )
|
||||
self.RoutePickup = false
|
||||
self.Relocating = true
|
||||
if Helicopter:GetHeight( true ) <= 5 and Helicopter:GetVelocityKMH() < 10 then
|
||||
--self:Load( Helicopter:GetPointVec2() )
|
||||
self:Load( self.PickupZone )
|
||||
self.RoutePickup = false
|
||||
end
|
||||
end
|
||||
|
||||
if self.RouteDeploy == true then
|
||||
self:Unload( true )
|
||||
self.RouteDeploy = false
|
||||
self.Transporting = false
|
||||
self.Relocating = false
|
||||
if Helicopter:GetHeight( true ) <= 5 and Helicopter:GetVelocityKMH() < 10 then
|
||||
self:Unload( self.DeployZone )
|
||||
self.RouteDeploy = false
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -221,16 +268,16 @@ end
|
||||
-- @param To
|
||||
-- @param Core.Point#COORDINATE Coordinate
|
||||
-- @param #number Speed
|
||||
function AI_CARGO_HELICOPTER:onafterQueue( Helicopter, From, Event, To, Coordinate )
|
||||
function AI_CARGO_HELICOPTER:onafterQueue( Helicopter, From, Event, To, Coordinate, Speed, DeployZone )
|
||||
|
||||
local HelicopterInZone = false
|
||||
|
||||
if Helicopter and Helicopter:IsAlive() then
|
||||
if Helicopter and Helicopter:IsAlive() == true then
|
||||
|
||||
local Distance = Coordinate:DistanceFromPointVec2( Helicopter:GetCoordinate() )
|
||||
|
||||
if Distance > 500 then
|
||||
self:__Queue( -10, Coordinate )
|
||||
if Distance > 2000 then
|
||||
self:__Queue( -10, Coordinate, Speed, DeployZone )
|
||||
else
|
||||
|
||||
local ZoneFree = true
|
||||
@@ -279,10 +326,16 @@ function AI_CARGO_HELICOPTER:onafterQueue( Helicopter, From, Event, To, Coordina
|
||||
|
||||
-- Now route the helicopter
|
||||
Helicopter:Route( Route, 0 )
|
||||
|
||||
-- Keep the DeployZone, because when the helo has landed, we want to provide the DeployZone to the mission designer as part of the Unloaded event.
|
||||
self.DeployZone = DeployZone
|
||||
|
||||
else
|
||||
self:__Queue( -10, Coordinate )
|
||||
self:__Queue( -10, Coordinate, Speed, DeployZone )
|
||||
end
|
||||
end
|
||||
else
|
||||
AI_CARGO_QUEUE[Helicopter] = nil
|
||||
end
|
||||
end
|
||||
|
||||
@@ -298,215 +351,86 @@ function AI_CARGO_HELICOPTER:onafterOrbit( Helicopter, From, Event, To, Coordina
|
||||
|
||||
if Helicopter and Helicopter:IsAlive() then
|
||||
|
||||
if not self:IsTransporting() then
|
||||
local Route = {}
|
||||
|
||||
-- local CoordinateFrom = Helicopter:GetCoordinate()
|
||||
-- local WaypointFrom = CoordinateFrom:WaypointAir(
|
||||
-- "RADIO",
|
||||
-- POINT_VEC3.RoutePointType.TurningPoint,
|
||||
-- POINT_VEC3.RoutePointAction.TurningPoint,
|
||||
-- Speed,
|
||||
-- true
|
||||
-- )
|
||||
-- Route[#Route+1] = WaypointFrom
|
||||
local CoordinateTo = Coordinate
|
||||
local WaypointTo = CoordinateTo:WaypointAir(
|
||||
"RADIO",
|
||||
POINT_VEC3.RoutePointType.TurningPoint,
|
||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
||||
50,
|
||||
true
|
||||
)
|
||||
Route[#Route+1] = WaypointTo
|
||||
|
||||
local Tasks = {}
|
||||
Tasks[#Tasks+1] = Helicopter:TaskOrbitCircle( math.random( 30, 80 ), 0, CoordinateTo:GetRandomCoordinateInRadius( 800, 500 ) )
|
||||
Route[#Route].task = Helicopter:TaskCombo( Tasks )
|
||||
|
||||
Route[#Route+1] = WaypointTo
|
||||
|
||||
-- Now route the helicopter
|
||||
Helicopter:Route( Route, 0 )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
--- @param #AI_CARGO_HELICOPTER self
|
||||
-- @param Wrapper.Group#GROUP Helicopter
|
||||
function AI_CARGO_HELICOPTER:onbeforeLoad( Helicopter, From, Event, To, Coordinate )
|
||||
|
||||
local Boarding = false
|
||||
|
||||
if Helicopter and Helicopter:IsAlive() then
|
||||
|
||||
self.BoardingCount = 0
|
||||
|
||||
if Helicopter and Helicopter:IsAlive() then
|
||||
self.Helicopter_Cargo = {}
|
||||
for _, HelicopterUnit in pairs( Helicopter:GetUnits() ) do
|
||||
local HelicopterUnit = HelicopterUnit -- Wrapper.Unit#UNIT
|
||||
for _, Cargo in pairs( self.CargoSet:GetSet() ) do
|
||||
local Cargo = Cargo -- Cargo.Cargo#CARGO
|
||||
self:F( { IsUnLoaded = Cargo:IsUnLoaded() } )
|
||||
if Cargo:IsUnLoaded() then
|
||||
if Cargo:IsInLoadRadius( HelicopterUnit:GetCoordinate() ) then
|
||||
self:F( { "In radius", HelicopterUnit:GetName() } )
|
||||
--Cargo:Ungroup()
|
||||
Cargo:Board( HelicopterUnit, 25 )
|
||||
self:__Board( 1, Cargo )
|
||||
Boarding = true
|
||||
|
||||
-- So now this APCUnit has Cargo that is being loaded.
|
||||
-- This will be used further in the logic to follow and to check cargo status.
|
||||
self.Helicopter_Cargo[HelicopterUnit] = Cargo
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return Boarding
|
||||
|
||||
end
|
||||
|
||||
--- @param #AI_CARGO_HELICOPTER self
|
||||
-- @param Wrapper.Group#GROUP Helicopter
|
||||
function AI_CARGO_HELICOPTER:onafterBoard( Helicopter, From, Event, To, Cargo )
|
||||
self:F( { APC, From, Event, To, Cargo } )
|
||||
|
||||
if Helicopter and Helicopter:IsAlive() then
|
||||
self:F({ IsLoaded = Cargo:IsLoaded() } )
|
||||
if not Cargo:IsLoaded() then
|
||||
self:__Board( 10, Cargo )
|
||||
else
|
||||
self:__Loaded( 1, Cargo )
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- @param #AI_CARGO_HELICOPTER self
|
||||
-- @param Wrapper.Group#GROUP Helicopter
|
||||
function AI_CARGO_HELICOPTER:onbeforeLoaded( Helicopter, From, Event, To, Cargo )
|
||||
self:F( { APC, From, Event, To } )
|
||||
|
||||
local Loaded = true
|
||||
|
||||
if Helicopter and Helicopter:IsAlive() then
|
||||
for HelicopterUnit, Cargo in pairs( self.Helicopter_Cargo ) do
|
||||
local Cargo = Cargo -- Cargo.Cargo#CARGO
|
||||
self:F( { IsLoaded = Cargo:IsLoaded(), IsDestroyed = Cargo:IsDestroyed() } )
|
||||
if not Cargo:IsLoaded() and not Cargo:IsDestroyed() then
|
||||
Loaded = false
|
||||
end
|
||||
end
|
||||
local Route = {}
|
||||
|
||||
end
|
||||
|
||||
return Loaded
|
||||
|
||||
end
|
||||
|
||||
|
||||
--- @param #AI_CARGO_HELICOPTER self
|
||||
-- @param Wrapper.Group#GROUP Helicopter
|
||||
function AI_CARGO_HELICOPTER:onafterUnload( Helicopter, From, Event, To, Deployed )
|
||||
|
||||
if Helicopter and Helicopter:IsAlive() then
|
||||
for _, HelicopterUnit in pairs( Helicopter:GetUnits() ) do
|
||||
local HelicopterUnit = HelicopterUnit -- Wrapper.Unit#UNIT
|
||||
for _, Cargo in pairs( HelicopterUnit:GetCargo() ) do
|
||||
Cargo:UnBoard()
|
||||
Cargo:SetDeployed( true )
|
||||
self:__Unboard( 10, Cargo, Deployed )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
--- @param #AI_CARGO_HELICOPTER self
|
||||
-- @param Wrapper.Group#GROUP Helicopter
|
||||
function AI_CARGO_HELICOPTER:onafterUnboard( Helicopter, From, Event, To, Cargo, Deployed )
|
||||
|
||||
if Helicopter and Helicopter:IsAlive() then
|
||||
if not Cargo:IsUnLoaded() then
|
||||
self:__Unboard( 10, Cargo, Deployed )
|
||||
else
|
||||
self:__Unloaded( 1, Cargo, Deployed )
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- @param #AI_CARGO_HELICOPTER self
|
||||
-- @param Wrapper.Group#GROUP Helicopter
|
||||
function AI_CARGO_HELICOPTER:onbeforeUnloaded( Helicopter, From, Event, To, Cargo, Deployed )
|
||||
self:F( { APC, From, Event, To, Cargo:GetName(), Deployed = Deployed } )
|
||||
|
||||
local AllUnloaded = true
|
||||
|
||||
--Cargo:Regroup()
|
||||
|
||||
if Helicopter and Helicopter:IsAlive() then
|
||||
for _, HelicopterUnit in pairs( Helicopter:GetUnits() ) do
|
||||
local CargoCheck = self.Helicopter_Cargo[HelicopterUnit] -- Cargo.Cargo#CARGO
|
||||
if CargoCheck then
|
||||
self:F( { CargoCheck:GetName(), IsUnLoaded = CargoCheck:IsUnLoaded() } )
|
||||
if CargoCheck:IsUnLoaded() == false then
|
||||
AllUnloaded = false
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
-- local CoordinateFrom = Helicopter:GetCoordinate()
|
||||
-- local WaypointFrom = CoordinateFrom:WaypointAir(
|
||||
-- "RADIO",
|
||||
-- POINT_VEC3.RoutePointType.TurningPoint,
|
||||
-- POINT_VEC3.RoutePointAction.TurningPoint,
|
||||
-- Speed,
|
||||
-- true
|
||||
-- )
|
||||
-- Route[#Route+1] = WaypointFrom
|
||||
local CoordinateTo = Coordinate
|
||||
local WaypointTo = CoordinateTo:WaypointAir(
|
||||
"RADIO",
|
||||
POINT_VEC3.RoutePointType.TurningPoint,
|
||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
||||
50,
|
||||
true
|
||||
)
|
||||
Route[#Route+1] = WaypointTo
|
||||
|
||||
if AllUnloaded == true then
|
||||
if Deployed == true then
|
||||
for HelicopterUnit, Cargo in pairs( self.Helicopter_Cargo ) do
|
||||
local Cargo = Cargo -- Cargo.Cargo#CARGO
|
||||
end
|
||||
self.Helicopter_Cargo = {}
|
||||
end
|
||||
self.Helicopter = Helicopter
|
||||
end
|
||||
local Tasks = {}
|
||||
Tasks[#Tasks+1] = Helicopter:TaskOrbitCircle( math.random( 30, 80 ), 150, CoordinateTo:GetRandomCoordinateInRadius( 800, 500 ) )
|
||||
Route[#Route].task = Helicopter:TaskCombo( Tasks )
|
||||
|
||||
Route[#Route+1] = WaypointTo
|
||||
|
||||
-- Now route the helicopter
|
||||
Helicopter:Route( Route, 0 )
|
||||
end
|
||||
|
||||
self:F( { AllUnloaded = AllUnloaded } )
|
||||
return AllUnloaded
|
||||
|
||||
end
|
||||
|
||||
--- @param #AI_CARGO_HELICOPTER self
|
||||
|
||||
|
||||
--- On after Deployed event.
|
||||
-- @param #AI_CARGO_HELICOPTER self
|
||||
-- @param Wrapper.Group#GROUP Helicopter
|
||||
function AI_CARGO_HELICOPTER:onafterUnloaded( Helicopter, From, Event, To, Cargo, Deployed )
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Cargo.Cargo#CARGO Cargo Cargo object.
|
||||
-- @param #boolean Deployed Cargo is deployed.
|
||||
-- @return #boolean True if all cargo has been unloaded.
|
||||
function AI_CARGO_HELICOPTER:onafterDeployed( Helicopter, From, Event, To, DeployZone )
|
||||
self:F( { Helicopter, From, Event, To, DeployZone = DeployZone } )
|
||||
|
||||
self:Orbit( Helicopter:GetCoordinate(), 50 )
|
||||
|
||||
AI_CARGO_QUEUE[Helicopter] = nil
|
||||
|
||||
-- Free the coordinate zone after 30 seconds, so that the original helicopter can fly away first.
|
||||
self:ScheduleOnce( 30,
|
||||
function( Helicopter )
|
||||
AI_CARGO_QUEUE[Helicopter] = nil
|
||||
end, Helicopter
|
||||
)
|
||||
|
||||
self:GetParent( self, AI_CARGO_HELICOPTER ).onafterDeployed( self, Helicopter, From, Event, To, DeployZone )
|
||||
|
||||
|
||||
end
|
||||
|
||||
--- @param #AI_CARGO_HELICOPTER self
|
||||
--- On after Pickup event.
|
||||
-- @param #AI_CARGO_HELICOPTER self
|
||||
-- @param Wrapper.Group#GROUP Helicopter
|
||||
-- @param From
|
||||
-- @param Event
|
||||
-- @param To
|
||||
-- @param Core.Point#COORDINATE Coordinate
|
||||
-- @param #number Speed
|
||||
function AI_CARGO_HELICOPTER:onafterPickup( Helicopter, From, Event, To, Coordinate )
|
||||
-- @param Core.Point#COORDINATE Coordinate Pickup place.
|
||||
-- @param #number Speed Speed in km/h to drive to the pickup coordinate. Default is 50% of max possible speed the unit can go.
|
||||
-- @param #number Height Height in meters to move to the pickup coordinate. This parameter is ignored for APCs.
|
||||
-- @param Core.Zone#ZONE PickupZone (optional) The zone where the cargo will be picked up. The PickupZone can be nil, if there wasn't any PickupZoneSet provided.
|
||||
function AI_CARGO_HELICOPTER:onafterPickup( Helicopter, From, Event, To, Coordinate, Speed, Height, PickupZone )
|
||||
|
||||
if Helicopter and Helicopter:IsAlive() ~= nil then
|
||||
|
||||
Helicopter:Activate()
|
||||
|
||||
self.RoutePickup = true
|
||||
Coordinate.y = math.random( 50, 200 )
|
||||
Coordinate.y = Height
|
||||
|
||||
local _speed=Speed or Helicopter:GetSpeedMax()*0.5
|
||||
|
||||
local Route = {}
|
||||
|
||||
@@ -519,7 +443,7 @@ function AI_CARGO_HELICOPTER:onafterPickup( Helicopter, From, Event, To, Coordin
|
||||
"RADIO",
|
||||
POINT_VEC3.RoutePointType.TurningPoint,
|
||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
||||
150,
|
||||
_speed,
|
||||
true
|
||||
)
|
||||
|
||||
@@ -528,7 +452,7 @@ function AI_CARGO_HELICOPTER:onafterPickup( Helicopter, From, Event, To, Coordin
|
||||
"RADIO",
|
||||
POINT_VEC3.RoutePointType.TurningPoint,
|
||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
||||
150,
|
||||
_speed,
|
||||
true
|
||||
)
|
||||
|
||||
@@ -547,25 +471,33 @@ function AI_CARGO_HELICOPTER:onafterPickup( Helicopter, From, Event, To, Coordin
|
||||
|
||||
-- Now route the helicopter
|
||||
Helicopter:Route( Route, 1 )
|
||||
|
||||
self.PickupZone = PickupZone
|
||||
|
||||
self:GetParent( self, AI_CARGO_HELICOPTER ).onafterPickup( self, Helicopter, From, Event, To, Coordinate, Speed, Height, PickupZone )
|
||||
|
||||
self.Transporting = true
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
function AI_CARGO_HELICOPTER:_Deploy( AICargoHelicopter, Coordinate )
|
||||
AICargoHelicopter:__Queue( -10, Coordinate, 100 )
|
||||
--- Depoloy function and queue.
|
||||
-- @param #AI_CARGO_HELICOPTER self
|
||||
-- @param Wrapper.Group#GROUP AICargoHelicopter
|
||||
-- @param Core.Point#COORDINATE Coordinate Coordinate
|
||||
function AI_CARGO_HELICOPTER:_Deploy( AICargoHelicopter, Coordinate, DeployZone )
|
||||
AICargoHelicopter:__Queue( -10, Coordinate, 100, DeployZone )
|
||||
end
|
||||
|
||||
--- @param #AI_CARGO_HELICOPTER self
|
||||
-- @param Wrapper.Group#GROUP Helicopter
|
||||
--- On after Deploy event.
|
||||
-- @param #AI_CARGO_HELICOPTER self
|
||||
-- @param Wrapper.Group#GROUP Helicopter Transport helicopter.
|
||||
-- @param From
|
||||
-- @param Event
|
||||
-- @param To
|
||||
-- @param Core.Point#COORDINATE Coordinate
|
||||
-- @param #number Speed
|
||||
function AI_CARGO_HELICOPTER:onafterDeploy( Helicopter, From, Event, To, Coordinate )
|
||||
-- @param Core.Point#COORDINATE Coordinate Place at which the cargo is deployed.
|
||||
-- @param #number Speed Speed in km/h to drive to the pickup coordinate. Default is 50% of max possible speed the unit can go.
|
||||
-- @param #number Height Height in meters to move to the deploy coordinate.
|
||||
function AI_CARGO_HELICOPTER:onafterDeploy( Helicopter, From, Event, To, Coordinate, Speed, Height, DeployZone )
|
||||
|
||||
if Helicopter and Helicopter:IsAlive() ~= nil then
|
||||
|
||||
@@ -576,7 +508,9 @@ function AI_CARGO_HELICOPTER:onafterDeploy( Helicopter, From, Event, To, Coordin
|
||||
|
||||
--- Calculate the target route point.
|
||||
|
||||
Coordinate.y = math.random( 50, 200 )
|
||||
Coordinate.y = Height
|
||||
|
||||
local _speed=Speed or Helicopter:GetSpeedMax()*0.5
|
||||
|
||||
--- Create a route point of type air.
|
||||
local CoordinateFrom = Helicopter:GetCoordinate()
|
||||
@@ -584,7 +518,7 @@ function AI_CARGO_HELICOPTER:onafterDeploy( Helicopter, From, Event, To, Coordin
|
||||
"RADIO",
|
||||
POINT_VEC3.RoutePointType.TurningPoint,
|
||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
||||
150,
|
||||
_speed,
|
||||
true
|
||||
)
|
||||
Route[#Route+1] = WaypointFrom
|
||||
@@ -596,7 +530,7 @@ function AI_CARGO_HELICOPTER:onafterDeploy( Helicopter, From, Event, To, Coordin
|
||||
"RADIO",
|
||||
POINT_VEC3.RoutePointType.TurningPoint,
|
||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
||||
150,
|
||||
_speed,
|
||||
true
|
||||
)
|
||||
|
||||
@@ -608,8 +542,8 @@ function AI_CARGO_HELICOPTER:onafterDeploy( Helicopter, From, Event, To, Coordin
|
||||
|
||||
local Tasks = {}
|
||||
|
||||
Tasks[#Tasks+1] = Helicopter:TaskFunction( "AI_CARGO_HELICOPTER._Deploy", self, Coordinate )
|
||||
Tasks[#Tasks+1] = Helicopter:TaskOrbitCircle( math.random( 30, 100 ), 0, CoordinateTo:GetRandomCoordinateInRadius( 800, 500 ) )
|
||||
Tasks[#Tasks+1] = Helicopter:TaskFunction( "AI_CARGO_HELICOPTER._Deploy", self, Coordinate, DeployZone )
|
||||
Tasks[#Tasks+1] = Helicopter:TaskOrbitCircle( math.random( 30, 100 ), _speed, CoordinateTo:GetRandomCoordinateInRadius( 800, 500 ) )
|
||||
|
||||
--Tasks[#Tasks+1] = Helicopter:TaskLandAtVec2( CoordinateTo:GetVec2() )
|
||||
Route[#Route].task = Helicopter:TaskCombo( Tasks )
|
||||
@@ -617,21 +551,25 @@ function AI_CARGO_HELICOPTER:onafterDeploy( Helicopter, From, Event, To, Coordin
|
||||
Route[#Route+1] = WaypointTo
|
||||
|
||||
-- Now route the helicopter
|
||||
Helicopter:Route( Route, 1 )
|
||||
|
||||
Helicopter:Route( Route, 0 )
|
||||
|
||||
self:GetParent( self, AI_CARGO_HELICOPTER ).onafterDeploy( self, Helicopter, From, Event, To, Coordinate, Speed, Height, DeployZone )
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
--- @param #AI_CARGO_HELICOPTER self
|
||||
--- On after Home event.
|
||||
-- @param #AI_CARGO_HELICOPTER self
|
||||
-- @param Wrapper.Group#GROUP Helicopter
|
||||
-- @param From
|
||||
-- @param Event
|
||||
-- @param To
|
||||
-- @param Core.Point#COORDINATE Coordinate
|
||||
-- @param #number Speed
|
||||
function AI_CARGO_HELICOPTER:onafterHome( Helicopter, From, Event, To, Coordinate )
|
||||
-- @param Core.Point#COORDINATE Coordinate Home place.
|
||||
-- @param #number Speed Speed in km/h to drive to the pickup coordinate. Default is 50% of max possible speed the unit can go.
|
||||
-- @param #number Height Height in meters to move to the home coordinate.
|
||||
-- @param Core.Zone#ZONE HomeZone The zone wherein the carrier will return when all cargo has been transported. This can be any zone type, like a ZONE, ZONE_GROUP, ZONE_AIRBASE.
|
||||
function AI_CARGO_HELICOPTER:onafterHome( Helicopter, From, Event, To, Coordinate, Speed, Height, HomeZone )
|
||||
|
||||
if Helicopter and Helicopter:IsAlive() ~= nil then
|
||||
|
||||
@@ -641,7 +579,9 @@ function AI_CARGO_HELICOPTER:onafterHome( Helicopter, From, Event, To, Coordinat
|
||||
|
||||
--- Calculate the target route point.
|
||||
|
||||
Coordinate.y = math.random( 50, 200 )
|
||||
Coordinate.y = Height
|
||||
|
||||
Speed = Speed or Helicopter:GetSpeedMax()*0.5
|
||||
|
||||
--- Create a route point of type air.
|
||||
local CoordinateFrom = Helicopter:GetCoordinate()
|
||||
@@ -649,7 +589,7 @@ function AI_CARGO_HELICOPTER:onafterHome( Helicopter, From, Event, To, Coordinat
|
||||
"RADIO",
|
||||
POINT_VEC3.RoutePointType.TurningPoint,
|
||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
||||
150,
|
||||
Speed ,
|
||||
true
|
||||
)
|
||||
Route[#Route+1] = WaypointFrom
|
||||
@@ -660,7 +600,7 @@ function AI_CARGO_HELICOPTER:onafterHome( Helicopter, From, Event, To, Coordinat
|
||||
"RADIO",
|
||||
POINT_VEC3.RoutePointType.TurningPoint,
|
||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
||||
150,
|
||||
Speed ,
|
||||
true
|
||||
)
|
||||
|
||||
|
||||
@@ -1,35 +1,11 @@
|
||||
--- **AI** -- (R2.2) - Build large airborne formations of aircraft.
|
||||
--- **AI** -- Build large airborne formations of aircraft.
|
||||
--
|
||||
-- ===
|
||||
-- **Features:**
|
||||
--
|
||||
-- * Build in-air formations consisting of more than 40 aircraft as one group.
|
||||
-- * Build different formation types.
|
||||
-- * Assign a group leader that will guide the large formation path.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- AI_FORMATION makes AI @{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 purpose of the class is to:
|
||||
--
|
||||
-- * Make formation building a process that can be managed while in flight, rather than a task.
|
||||
-- * Human players can guide formations, consisting of larget planes.
|
||||
-- * Build large formations (like a large bomber field).
|
||||
-- * Form formations that DCS does not support off the shelve.
|
||||
--
|
||||
-- A few remarks:
|
||||
--
|
||||
-- * Depending on the type of plane, the change in direction by the leader may result in the formation getting disentangled while in flight and needs to be rebuild.
|
||||
-- * Formations are vulnerable to collissions, but is depending on the type of plane, the distance between the planes and the speed and angle executed by the leader.
|
||||
-- * Formations may take a while to build up.
|
||||
--
|
||||
-- As a result, the AI_FORMATION is not perfect, but is very useful to:
|
||||
--
|
||||
-- * Model large formations when flying straight line.
|
||||
-- * Make humans guide a large formation, when the planes are wide from each other.
|
||||
--
|
||||
-- There are the following types of classes defined:
|
||||
--
|
||||
-- * @{#AI_FORMATION}: Create a formation from several @{GROUP}s.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/FOR%20-%20Formation)
|
||||
@@ -45,13 +21,14 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module AI_Formation
|
||||
-- @module AI.AI_Formation
|
||||
-- @image AI_Large_Formations.JPG
|
||||
|
||||
--- AI_FORMATION class
|
||||
-- @type AI_FORMATION
|
||||
-- @extends Fsm#FSM_SET
|
||||
-- @field Unit#UNIT FollowUnit
|
||||
-- @field Set#SET_GROUP FollowGroupSet
|
||||
-- @extends Core.Fsm#FSM_SET
|
||||
-- @field Wrapper.Unit#UNIT FollowUnit
|
||||
-- @field Core.Set#SET_GROUP FollowGroupSet
|
||||
-- @field #string FollowName
|
||||
-- @field #AI_FORMATION.MODE FollowMode The mode the escort is in.
|
||||
-- @field Scheduler#SCHEDULER FollowScheduler The instance of the SCHEDULER class.
|
||||
@@ -61,9 +38,7 @@
|
||||
-- @field DCSTypes#AI.Option.Air.val.REACTION_ON_THREAT OptionReactionOnThreat Which REACTION_ON_THREAT is set to the FollowGroup.
|
||||
|
||||
|
||||
--- # AI_FORMATION class, extends @{Fsm#FSM_SET}
|
||||
--
|
||||
-- The #AI_FORMATION class allows you to build large formations, make AI follow a @{Client#CLIENT} (player) leader or a @{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 @{GROUP}s fly in formation of various compositions.
|
||||
-- The AI_FORMATION class models formations in a different manner than the internal DCS formation logic!!!
|
||||
@@ -89,25 +64,25 @@
|
||||
--
|
||||
-- Create a new SPAWN object with the @{#AI_FORMATION.New} method:
|
||||
--
|
||||
-- * @{Follow#AI_FORMATION.New}(): Creates a new AI_FORMATION object from a @{Group#GROUP} for a @{Client#CLIENT} or a @{Unit#UNIT}, with an optional briefing text.
|
||||
-- * @{#AI_FORMATION.New}(): Creates a new AI_FORMATION object from a @{Wrapper.Group#GROUP} for a @{Wrapper.Client#CLIENT} or a @{Wrapper.Unit#UNIT}, with an optional briefing text.
|
||||
--
|
||||
-- ## Formation methods
|
||||
--
|
||||
-- The following methods can be used to set or change the formation:
|
||||
--
|
||||
-- * @{AI_Formation#AI_FORMATION.FormationLine}(): Form a line formation (core formation function).
|
||||
-- * @{AI_Formation#AI_FORMATION.FormationTrail}(): Form a trail formation.
|
||||
-- * @{AI_Formation#AI_FORMATION.FormationLeftLine}(): Form a left line formation.
|
||||
-- * @{AI_Formation#AI_FORMATION.FormationRightLine}(): Form a right line formation.
|
||||
-- * @{AI_Formation#AI_FORMATION.FormationRightWing}(): Form a right wing formation.
|
||||
-- * @{AI_Formation#AI_FORMATION.FormationLeftWing}(): Form a left wing formation.
|
||||
-- * @{AI_Formation#AI_FORMATION.FormationCenterWing}(): Form a center wing formation.
|
||||
-- * @{AI_Formation#AI_FORMATION.FormationCenterVic}(): Form a Vic formation (same as CenterWing.
|
||||
-- * @{AI_Formation#AI_FORMATION.FormationCenterBoxed}(): Form a center boxed formation.
|
||||
-- * @{#AI_FORMATION.FormationLine}(): Form a line formation (core formation function).
|
||||
-- * @{#AI_FORMATION.FormationTrail}(): Form a trail formation.
|
||||
-- * @{#AI_FORMATION.FormationLeftLine}(): Form a left line formation.
|
||||
-- * @{#AI_FORMATION.FormationRightLine}(): Form a right line formation.
|
||||
-- * @{#AI_FORMATION.FormationRightWing}(): Form a right wing formation.
|
||||
-- * @{#AI_FORMATION.FormationLeftWing}(): Form a left wing formation.
|
||||
-- * @{#AI_FORMATION.FormationCenterWing}(): Form a center wing formation.
|
||||
-- * @{#AI_FORMATION.FormationCenterVic}(): Form a Vic formation (same as CenterWing.
|
||||
-- * @{#AI_FORMATION.FormationCenterBoxed}(): Form a center boxed formation.
|
||||
--
|
||||
-- ## Randomization
|
||||
--
|
||||
-- Use the method @{AI_Formation#AI_FORMATION.SetFlightRandomization}() to simulate the formation flying errors that pilots make while in formation. Is a range set in meters.
|
||||
-- Use the method @{AI.AI_Formation#AI_FORMATION.SetFlightRandomization}() to simulate the formation flying errors that pilots make while in formation. Is a range set in meters.
|
||||
--
|
||||
-- @usage
|
||||
-- local FollowGroupSet = SET_GROUP:New():FilterCategories("plane"):FilterCoalitions("blue"):FilterPrefixes("Follow"):FilterStart()
|
||||
@@ -147,7 +122,7 @@ AI_FORMATION = {
|
||||
|
||||
--- AI_FORMATION class constructor for an AI group
|
||||
-- @param #AI_FORMATION self
|
||||
-- @param Unit#UNIT FollowUnit The UNIT leading the FolllowGroupSet.
|
||||
-- @param Wrapper.Unit#UNIT FollowUnit The UNIT leading the FolllowGroupSet.
|
||||
-- @param Core.Set#SET_GROUP FollowGroupSet The group AI escorting the FollowUnit.
|
||||
-- @param #string FollowName Name of the escort.
|
||||
-- @return #AI_FORMATION self
|
||||
@@ -155,8 +130,8 @@ function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefin
|
||||
local self = BASE:Inherit( self, FSM_SET:New( FollowGroupSet ) )
|
||||
self:F( { FollowUnit, FollowGroupSet, FollowName } )
|
||||
|
||||
self.FollowUnit = FollowUnit -- Unit#UNIT
|
||||
self.FollowGroupSet = FollowGroupSet -- Set#SET_GROUP
|
||||
self.FollowUnit = FollowUnit -- Wrapper.Unit#UNIT
|
||||
self.FollowGroupSet = FollowGroupSet -- Core.Set#SET_GROUP
|
||||
|
||||
self:SetFlightRandomization( 2 )
|
||||
|
||||
@@ -675,7 +650,7 @@ function AI_FORMATION:onafterFormationLine( FollowGroupSet, From , Event , To, X
|
||||
|
||||
local FollowSet = FollowGroupSet:GetSet()
|
||||
|
||||
local i = 0
|
||||
local i = 1 --FF i=0 caused first unit to have no XSpace! Probably needs further adjustments. This is just a quick work around.
|
||||
|
||||
for FollowID, FollowGroup in pairs( FollowSet ) do
|
||||
|
||||
@@ -906,7 +881,7 @@ function AI_FORMATION:onafterFormationBox( FollowGroupSet, From , Event , To, XS
|
||||
end
|
||||
|
||||
|
||||
--- Use the method @{AI_Formation#AI_FORMATION.SetFlightRandomization}() to make the air units in your formation randomize their flight a bit while in formation.
|
||||
--- Use the method @{AI.AI_Formation#AI_FORMATION.SetFlightRandomization}() to make the air units in your formation randomize their flight a bit while in formation.
|
||||
-- @param #AI_FORMATION self
|
||||
-- @param #number FlightRandomization The formation flying errors that pilots can make while in formation. Is a range set in meters.
|
||||
-- @return #AI_FORMATION
|
||||
@@ -993,7 +968,7 @@ function AI_FORMATION:onenterFollowing( FollowGroupSet ) --R2.1
|
||||
local Alpha_R = ( Alpha_T < 0 ) and Alpha_T + 2 * math.pi or Alpha_T
|
||||
local Position = math.cos( Alpha_R )
|
||||
local GD = ( ( GDv.x )^2 + ( GDv.z )^2 ) ^ 0.5
|
||||
local Distance = GD * Position + - CS * 0,5
|
||||
local Distance = GD * Position + - CS * 0.5
|
||||
|
||||
-- Calculate the group direction vector
|
||||
local GV = { x = GV2.x - CV2.x, y = GV2.y - CV2.y, z = GV2.z - CV2.z }
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
--- **AI** -- (R2.1) - Manages the independent process of Air Patrol for airplanes.
|
||||
--- **AI** -- Perform Air Patrolling for airplanes.
|
||||
--
|
||||
-- ===
|
||||
-- **Features:**
|
||||
--
|
||||
-- 
|
||||
-- * Patrol AI airplanes within a given zone.
|
||||
-- * Trigger detected events when enemy airplanes are detected.
|
||||
-- * Manage a fuel treshold to RTB on time.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
@@ -30,27 +32,25 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module AI_Patrol
|
||||
|
||||
-- @module AI.AI_Patrol
|
||||
-- @image AI_Air_Patrolling.JPG
|
||||
|
||||
--- AI_PATROL_ZONE class
|
||||
-- @type AI_PATROL_ZONE
|
||||
-- @field Wrapper.Controllable#CONTROLLABLE AIControllable The @{Controllable} patrolling.
|
||||
-- @field Wrapper.Controllable#CONTROLLABLE AIControllable The @{Wrapper.Controllable} patrolling.
|
||||
-- @field Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed.
|
||||
-- @field Dcs.DCSTypes#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
|
||||
-- @field Dcs.DCSTypes#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
|
||||
-- @field Dcs.DCSTypes#Speed PatrolMinSpeed The minimum speed of the @{Controllable} in km/h.
|
||||
-- @field Dcs.DCSTypes#Speed PatrolMaxSpeed The maximum speed of the @{Controllable} in km/h.
|
||||
-- @field DCS#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
|
||||
-- @field DCS#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
|
||||
-- @field DCS#Speed PatrolMinSpeed The minimum speed of the @{Wrapper.Controllable} in km/h.
|
||||
-- @field DCS#Speed PatrolMaxSpeed The maximum speed of the @{Wrapper.Controllable} in km/h.
|
||||
-- @field Core.Spawn#SPAWN CoordTest
|
||||
-- @extends Core.Fsm#FSM_CONTROLLABLE
|
||||
|
||||
--- # AI_PATROL_ZONE class, extends @{Fsm#FSM_CONTROLLABLE}
|
||||
--
|
||||
-- The AI_PATROL_ZONE class implements the core functions to patrol a @{Zone} by an AI @{Controllable} or @{Group}.
|
||||
--- Implements the core functions to patrol a @{Zone} by an AI @{Wrapper.Controllable} or @{Wrapper.Group}.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- The AI_PATROL_ZONE is assigned a @{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.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
@@ -123,7 +123,7 @@
|
||||
-- * @{#AI_PATROL_ZONE.SetDetectionOff}(): Set the detection off, the AI will not detect for targets. The existing target list will NOT be erased.
|
||||
--
|
||||
-- The detection frequency can be set with @{#AI_PATROL_ZONE.SetRefreshTimeInterval}( seconds ), where the amount of seconds specify how much seconds will be waited before the next detection.
|
||||
-- Use the method @{#AI_PATROL_ZONE.GetDetectedUnits}() to obtain a list of the @{Unit}s detected by the AI.
|
||||
-- Use the method @{#AI_PATROL_ZONE.GetDetectedUnits}() to obtain a list of the @{Wrapper.Unit}s detected by the AI.
|
||||
--
|
||||
-- The detection can be filtered to potential targets in a specific zone.
|
||||
-- Use the method @{#AI_PATROL_ZONE.SetDetectionZone}() to set the zone where targets need to be detected.
|
||||
@@ -155,11 +155,11 @@ AI_PATROL_ZONE = {
|
||||
--- Creates a new AI_PATROL_ZONE object
|
||||
-- @param #AI_PATROL_ZONE self
|
||||
-- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed.
|
||||
-- @param Dcs.DCSTypes#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
|
||||
-- @param Dcs.DCSTypes#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
|
||||
-- @param Dcs.DCSTypes#Speed PatrolMinSpeed The minimum speed of the @{Controllable} in km/h.
|
||||
-- @param Dcs.DCSTypes#Speed PatrolMaxSpeed The maximum speed of the @{Controllable} in km/h.
|
||||
-- @param Dcs.DCSTypes#AltitudeType PatrolAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to RADIO
|
||||
-- @param DCS#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
|
||||
-- @param DCS#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
|
||||
-- @param DCS#Speed PatrolMinSpeed The minimum speed of the @{Wrapper.Controllable} in km/h.
|
||||
-- @param DCS#Speed PatrolMaxSpeed The maximum speed of the @{Wrapper.Controllable} in km/h.
|
||||
-- @param DCS#AltitudeType PatrolAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to RADIO
|
||||
-- @return #AI_PATROL_ZONE self
|
||||
-- @usage
|
||||
-- -- Define a new AI_PATROL_ZONE Object. This PatrolArea will patrol an AIControllable within PatrolZone between 3000 and 6000 meters, with a variying speed between 600 and 900 km/h.
|
||||
@@ -454,8 +454,8 @@ end
|
||||
|
||||
--- Sets (modifies) the minimum and maximum speed of the patrol.
|
||||
-- @param #AI_PATROL_ZONE self
|
||||
-- @param Dcs.DCSTypes#Speed PatrolMinSpeed The minimum speed of the @{Controllable} in km/h.
|
||||
-- @param Dcs.DCSTypes#Speed PatrolMaxSpeed The maximum speed of the @{Controllable} in km/h.
|
||||
-- @param DCS#Speed PatrolMinSpeed The minimum speed of the @{Wrapper.Controllable} in km/h.
|
||||
-- @param DCS#Speed PatrolMaxSpeed The maximum speed of the @{Wrapper.Controllable} in km/h.
|
||||
-- @return #AI_PATROL_ZONE self
|
||||
function AI_PATROL_ZONE:SetSpeed( PatrolMinSpeed, PatrolMaxSpeed )
|
||||
self:F2( { PatrolMinSpeed, PatrolMaxSpeed } )
|
||||
@@ -468,8 +468,8 @@ end
|
||||
|
||||
--- Sets the floor and ceiling altitude of the patrol.
|
||||
-- @param #AI_PATROL_ZONE self
|
||||
-- @param Dcs.DCSTypes#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
|
||||
-- @param Dcs.DCSTypes#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
|
||||
-- @param DCS#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
|
||||
-- @param DCS#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
|
||||
-- @return #AI_PATROL_ZONE self
|
||||
function AI_PATROL_ZONE:SetAltitude( PatrolFloorAltitude, PatrolCeilingAltitude )
|
||||
self:F2( { PatrolFloorAltitude, PatrolCeilingAltitude } )
|
||||
@@ -562,18 +562,18 @@ function AI_PATROL_ZONE:SetDetectionZone( DetectionZone )
|
||||
end
|
||||
end
|
||||
|
||||
--- Gets a list of @{Unit#UNIT}s that were detected by the AI.
|
||||
--- Gets a list of @{Wrapper.Unit#UNIT}s that were detected by the AI.
|
||||
-- No filtering is applied, so, ANY detected UNIT can be in this list.
|
||||
-- It is up to the mission designer to use the @{Unit} class and methods to filter the targets.
|
||||
-- It is up to the mission designer to use the @{Wrapper.Unit} class and methods to filter the targets.
|
||||
-- @param #AI_PATROL_ZONE self
|
||||
-- @return #table The list of @{Unit#UNIT}s
|
||||
-- @return #table The list of @{Wrapper.Unit#UNIT}s
|
||||
function AI_PATROL_ZONE:GetDetectedUnits()
|
||||
self:F2()
|
||||
|
||||
return self.DetectedUnits
|
||||
end
|
||||
|
||||
--- Clears the list of @{Unit#UNIT}s that were detected by the AI.
|
||||
--- Clears the list of @{Wrapper.Unit#UNIT}s that were detected by the AI.
|
||||
-- @param #AI_PATROL_ZONE self
|
||||
function AI_PATROL_ZONE:ClearDetectedUnits()
|
||||
self:F2()
|
||||
@@ -590,7 +590,6 @@ end
|
||||
-- @return #AI_PATROL_ZONE self
|
||||
function AI_PATROL_ZONE:ManageFuel( PatrolFuelThresholdPercentage, PatrolOutOfFuelOrbitTime )
|
||||
|
||||
self.PatrolManageFuel = true
|
||||
self.PatrolFuelThresholdPercentage = PatrolFuelThresholdPercentage
|
||||
self.PatrolOutOfFuelOrbitTime = PatrolOutOfFuelOrbitTime
|
||||
|
||||
@@ -824,7 +823,7 @@ function AI_PATROL_ZONE:onafterStatus()
|
||||
|
||||
local RTB = false
|
||||
|
||||
local Fuel = self.Controllable:GetUnit(1):GetFuel()
|
||||
local Fuel = self.Controllable:GetFuelMin()
|
||||
if Fuel < self.PatrolFuelThresholdPercentage then
|
||||
self:E( self.Controllable:GetName() .. " is out of fuel:" .. Fuel .. ", RTB!" )
|
||||
local OldAIControllable = self.Controllable
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
--- **Actions** - ACT_ACCOUNT_ classes **account for** (detect, count & report) various DCS events occuring on @{Unit}s.
|
||||
--- **Actions** - ACT_ACCOUNT_ classes **account for** (detect, count & report) various DCS events occuring on @{Wrapper.Unit}s.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module Account
|
||||
|
||||
-- @module Actions.Account
|
||||
-- @image MOOSE.JPG
|
||||
|
||||
do -- ACT_ACCOUNT
|
||||
|
||||
--- # @{#ACT_ACCOUNT} FSM class, extends @{Fsm#FSM_PROCESS}
|
||||
--- # @{#ACT_ACCOUNT} FSM class, extends @{Core.Fsm#FSM_PROCESS}
|
||||
--
|
||||
-- ## ACT_ACCOUNT state machine:
|
||||
--
|
||||
@@ -55,7 +55,7 @@ do -- ACT_ACCOUNT
|
||||
-- These state transition methods need to provide a return value, which is specified at the function description.
|
||||
--
|
||||
-- @type ACT_ACCOUNT
|
||||
-- @field Set#SET_UNIT TargetSetUnit
|
||||
-- @field Core.Set#SET_UNIT TargetSetUnit
|
||||
-- @extends Core.Fsm#FSM_PROCESS
|
||||
ACT_ACCOUNT = {
|
||||
ClassName = "ACT_ACCOUNT",
|
||||
@@ -138,7 +138,7 @@ end -- ACT_ACCOUNT
|
||||
|
||||
do -- ACT_ACCOUNT_DEADS
|
||||
|
||||
--- # @{#ACT_ACCOUNT_DEADS} FSM class, extends @{Fsm.Account#ACT_ACCOUNT}
|
||||
--- # @{#ACT_ACCOUNT_DEADS} FSM class, extends @{Core.Fsm.Account#ACT_ACCOUNT}
|
||||
--
|
||||
-- The ACT_ACCOUNT_DEADS class accounts (detects, counts and reports) successful kills of DCS units.
|
||||
-- The process is given a @{Set} of units that will be tracked upon successful destruction.
|
||||
@@ -151,7 +151,7 @@ do -- ACT_ACCOUNT_DEADS
|
||||
-- * @{#ACT_ACCOUNT_DEADS.New}(): Creates a new ACT_ACCOUNT_DEADS object.
|
||||
--
|
||||
-- @type ACT_ACCOUNT_DEADS
|
||||
-- @field Set#SET_UNIT TargetSetUnit
|
||||
-- @field Core.Set#SET_UNIT TargetSetUnit
|
||||
-- @extends #ACT_ACCOUNT
|
||||
ACT_ACCOUNT_DEADS = {
|
||||
ClassName = "ACT_ACCOUNT_DEADS",
|
||||
@@ -160,7 +160,7 @@ do -- ACT_ACCOUNT_DEADS
|
||||
|
||||
--- Creates a new DESTROY process.
|
||||
-- @param #ACT_ACCOUNT_DEADS self
|
||||
-- @param Set#SET_UNIT TargetSetUnit
|
||||
-- @param Core.Set#SET_UNIT TargetSetUnit
|
||||
-- @param #string TaskName
|
||||
function ACT_ACCOUNT_DEADS:New()
|
||||
-- Inherits from BASE
|
||||
@@ -285,7 +285,7 @@ do -- ACT_ACCOUNT_DEADS
|
||||
end
|
||||
|
||||
--- @param #ACT_ACCOUNT_DEADS self
|
||||
-- @param Event#EVENTDATA EventData
|
||||
-- @param Core.Event#EVENTDATA EventData
|
||||
function ACT_ACCOUNT_DEADS:onfuncEventDead( EventData )
|
||||
self:T( { "EventDead", EventData } )
|
||||
|
||||
@@ -297,7 +297,7 @@ do -- ACT_ACCOUNT_DEADS
|
||||
--- DCS Events
|
||||
|
||||
--- @param #ACT_ACCOUNT_DEADS self
|
||||
-- @param Event#EVENTDATA EventData
|
||||
-- @param Core.Event#EVENTDATA EventData
|
||||
function ACT_ACCOUNT_DEADS:onfuncEventCrash( EventData )
|
||||
self:T( { "EventDead", EventData } )
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- # @{#ACT_ASSIGN} FSM template class, extends @{Fsm#FSM_PROCESS}
|
||||
-- # @{#ACT_ASSIGN} FSM template class, extends @{Core.Fsm#FSM_PROCESS}
|
||||
--
|
||||
-- ## ACT_ASSIGN state machine:
|
||||
--
|
||||
@@ -54,7 +54,7 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- # 1) @{#ACT_ASSIGN_ACCEPT} class, extends @{Fsm.Assign#ACT_ASSIGN}
|
||||
-- # 1) @{#ACT_ASSIGN_ACCEPT} class, extends @{Core.Fsm.Assign#ACT_ASSIGN}
|
||||
--
|
||||
-- The ACT_ASSIGN_ACCEPT class accepts by default a task for a player. No player intervention is allowed to reject the task.
|
||||
--
|
||||
@@ -64,7 +64,7 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- # 2) @{#ACT_ASSIGN_MENU_ACCEPT} class, extends @{Fsm.Assign#ACT_ASSIGN}
|
||||
-- # 2) @{#ACT_ASSIGN_MENU_ACCEPT} class, extends @{Core.Fsm.Assign#ACT_ASSIGN}
|
||||
--
|
||||
-- The ACT_ASSIGN_MENU_ACCEPT class accepts a task when the player accepts the task through an added menu option.
|
||||
-- This assignment type is useful to conditionally allow the player to choose whether or not he would accept the task.
|
||||
@@ -77,7 +77,8 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module Assign
|
||||
-- @module Actions.Assign
|
||||
-- @image MOOSE.JPG
|
||||
|
||||
|
||||
do -- ACT_ASSIGN
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
--- (SP) (MP) (FSM) Route AI or players through waypoints or to zones.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- # @{#ACT_ASSIST} FSM class, extends @{Fsm#FSM_PROCESS}
|
||||
--
|
||||
-- ## ACT_ASSIST state machine:
|
||||
--
|
||||
-- This class is a state machine: it manages a process that is triggered by events causing state transitions to occur.
|
||||
@@ -52,7 +48,7 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- # 1) @{#ACT_ASSIST_SMOKE_TARGETS_ZONE} class, extends @{Fsm.Route#ACT_ASSIST}
|
||||
-- # 1) @{#ACT_ASSIST_SMOKE_TARGETS_ZONE} class, extends @{Core.Fsm.Route#ACT_ASSIST}
|
||||
--
|
||||
-- The ACT_ASSIST_SMOKE_TARGETS_ZONE class implements the core functions to smoke targets in a @{Zone}.
|
||||
-- The targets are smoked within a certain range around each target, simulating a realistic smoking behaviour.
|
||||
@@ -64,7 +60,9 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module Smoke
|
||||
-- @module Actions.Assist
|
||||
-- @image MOOSE.JPG
|
||||
|
||||
|
||||
do -- ACT_ASSIST
|
||||
|
||||
@@ -142,7 +140,7 @@ do -- ACT_ASSIST_SMOKE_TARGETS_ZONE
|
||||
|
||||
--- ACT_ASSIST_SMOKE_TARGETS_ZONE class
|
||||
-- @type ACT_ASSIST_SMOKE_TARGETS_ZONE
|
||||
-- @field Set#SET_UNIT TargetSetUnit
|
||||
-- @field Core.Set#SET_UNIT TargetSetUnit
|
||||
-- @field Core.Zone#ZONE_BASE TargetZone
|
||||
-- @extends #ACT_ASSIST
|
||||
ACT_ASSIST_SMOKE_TARGETS_ZONE = {
|
||||
@@ -158,7 +156,7 @@ do -- ACT_ASSIST_SMOKE_TARGETS_ZONE
|
||||
|
||||
--- Creates a new target smoking state machine. The process will request from the menu if it accepts the task, if not, the unit is removed from the simulator.
|
||||
-- @param #ACT_ASSIST_SMOKE_TARGETS_ZONE self
|
||||
-- @param Set#SET_UNIT TargetSetUnit
|
||||
-- @param Core.Set#SET_UNIT TargetSetUnit
|
||||
-- @param Core.Zone#ZONE_BASE TargetZone
|
||||
function ACT_ASSIST_SMOKE_TARGETS_ZONE:New( TargetSetUnit, TargetZone )
|
||||
local self = BASE:Inherit( self, ACT_ASSIST:New() ) -- #ACT_ASSIST
|
||||
@@ -177,7 +175,7 @@ do -- ACT_ASSIST_SMOKE_TARGETS_ZONE
|
||||
|
||||
--- Creates a new target smoking state machine. The process will request from the menu if it accepts the task, if not, the unit is removed from the simulator.
|
||||
-- @param #ACT_ASSIST_SMOKE_TARGETS_ZONE self
|
||||
-- @param Set#SET_UNIT TargetSetUnit
|
||||
-- @param Core.Set#SET_UNIT TargetSetUnit
|
||||
-- @param Core.Zone#ZONE_BASE TargetZone
|
||||
-- @return #ACT_ASSIST_SMOKE_TARGETS_ZONE self
|
||||
function ACT_ASSIST_SMOKE_TARGETS_ZONE:Init( TargetSetUnit, TargetZone )
|
||||
|
||||
@@ -1,198 +0,0 @@
|
||||
--- @module Process_JTAC
|
||||
|
||||
--- PROCESS_JTAC class
|
||||
-- @type PROCESS_JTAC
|
||||
-- @field Wrapper.Unit#UNIT ProcessUnit
|
||||
-- @field Core.Set#SET_UNIT TargetSetUnit
|
||||
-- @extends Core.Fsm#FSM_PROCESS
|
||||
PROCESS_JTAC = {
|
||||
ClassName = "PROCESS_JTAC",
|
||||
Fsm = {},
|
||||
TargetSetUnit = nil,
|
||||
}
|
||||
|
||||
|
||||
--- Creates a new DESTROY process.
|
||||
-- @param #PROCESS_JTAC self
|
||||
-- @param Tasking.Task#TASK Task
|
||||
-- @param Wrapper.Unit#UNIT ProcessUnit
|
||||
-- @param Core.Set#SET_UNIT TargetSetUnit
|
||||
-- @param Wrapper.Unit#UNIT FACUnit
|
||||
-- @return #PROCESS_JTAC self
|
||||
function PROCESS_JTAC:New( Task, ProcessUnit, TargetSetUnit, FACUnit )
|
||||
|
||||
-- Inherits from BASE
|
||||
local self = BASE:Inherit( self, PROCESS:New( "JTAC", Task, ProcessUnit ) ) -- #PROCESS_JTAC
|
||||
|
||||
self.TargetSetUnit = TargetSetUnit
|
||||
self.FACUnit = FACUnit
|
||||
|
||||
self.DisplayInterval = 60
|
||||
self.DisplayCount = 30
|
||||
self.DisplayMessage = true
|
||||
self.DisplayTime = 10 -- 10 seconds is the default
|
||||
self.DisplayCategory = "HQ" -- Targets is the default display category
|
||||
|
||||
|
||||
self.Fsm = FSM_PROCESS:New( self, {
|
||||
initial = 'Assigned',
|
||||
events = {
|
||||
{ name = 'Start', from = 'Assigned', to = 'CreatedMenu' },
|
||||
{ name = 'JTACMenuUpdate', from = 'CreatedMenu', to = 'AwaitingMenu' },
|
||||
{ name = 'JTACMenuAwait', from = 'AwaitingMenu', to = 'AwaitingMenu' },
|
||||
{ name = 'JTACMenuSpot', from = 'AwaitingMenu', to = 'AwaitingMenu' },
|
||||
{ name = 'JTACMenuCancel', from = 'AwaitingMenu', to = 'AwaitingMenu' },
|
||||
{ name = 'JTACStatus', from = 'AwaitingMenu', to = 'AwaitingMenu' },
|
||||
{ name = 'Fail', from = 'AwaitingMenu', to = 'Failed' },
|
||||
{ name = 'Fail', from = 'CreatedMenu', to = 'Failed' },
|
||||
},
|
||||
callbacks = {
|
||||
onStart = self.OnStart,
|
||||
onJTACMenuUpdate = self.OnJTACMenuUpdate,
|
||||
onJTACMenuAwait = self.OnJTACMenuAwait,
|
||||
onJTACMenuSpot = self.OnJTACMenuSpot,
|
||||
onJTACMenuCancel = self.OnJTACMenuCancel,
|
||||
},
|
||||
endstates = { 'Failed' }
|
||||
} )
|
||||
|
||||
self:HandleEvent( EVENTS.Dead, self.EventDead )
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Process Events
|
||||
|
||||
--- StateMachine callback function for a PROCESS
|
||||
-- @param #PROCESS_JTAC self
|
||||
-- @param Core.Fsm#FSM_PROCESS Fsm
|
||||
-- @param #string Event
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
function PROCESS_JTAC:OnStart( Fsm, From, Event, To )
|
||||
|
||||
self:NextEvent( Fsm.JTACMenuUpdate )
|
||||
end
|
||||
|
||||
--- StateMachine callback function for a PROCESS
|
||||
-- @param #PROCESS_JTAC self
|
||||
-- @param Core.Fsm#FSM_PROCESS Fsm
|
||||
-- @param #string Event
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
function PROCESS_JTAC:OnJTACMenuUpdate( Fsm, From, Event, To )
|
||||
|
||||
local function JTACMenuSpot( MenuParam )
|
||||
self:F( MenuParam.TargetUnit.UnitName )
|
||||
local self = MenuParam.self
|
||||
local TargetUnit = MenuParam.TargetUnit
|
||||
|
||||
self:NextEvent( self.Fsm.JTACMenuSpot, TargetUnit )
|
||||
end
|
||||
|
||||
local function JTACMenuCancel( MenuParam )
|
||||
self:F( MenuParam )
|
||||
local self = MenuParam.self
|
||||
local TargetUnit = MenuParam.TargetUnit
|
||||
|
||||
self:NextEvent( self.Fsm.JTACMenuCancel, TargetUnit )
|
||||
end
|
||||
|
||||
|
||||
-- Loop each unit in the target set, and determine the threat levels map table.
|
||||
local UnitThreatLevels = self.TargetSetUnit:GetUnitThreatLevels()
|
||||
|
||||
self:F( {"UnitThreadLevels", UnitThreatLevels } )
|
||||
|
||||
local JTACMenu = self.ProcessGroup:GetState( self.ProcessGroup, "JTACMenu" )
|
||||
|
||||
if not JTACMenu then
|
||||
JTACMenu = MENU_GROUP:New( self.ProcessGroup, "JTAC", self.MissionMenu )
|
||||
for ThreatLevel, ThreatLevelTable in pairs( UnitThreatLevels ) do
|
||||
local JTACMenuThreatLevel = MENU_GROUP:New( self.ProcessGroup, ThreatLevelTable.UnitThreatLevelText, JTACMenu )
|
||||
for ThreatUnitName, ThreatUnit in pairs( ThreatLevelTable.Units ) do
|
||||
local JTACMenuUnit = MENU_GROUP:New( self.ProcessGroup, ThreatUnit:GetTypeName(), JTACMenuThreatLevel )
|
||||
MENU_GROUP_COMMAND:New( self.ProcessGroup, "Lase Target", JTACMenuUnit, JTACMenuSpot, { self = self, TargetUnit = ThreatUnit } )
|
||||
MENU_GROUP_COMMAND:New( self.ProcessGroup, "Cancel Target", JTACMenuUnit, JTACMenuCancel, { self = self, TargetUnit = ThreatUnit } )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- StateMachine callback function for a PROCESS
|
||||
-- @param #PROCESS_JTAC self
|
||||
-- @param Core.Fsm#FSM_PROCESS Fsm
|
||||
-- @param #string Event
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
function PROCESS_JTAC:OnJTACMenuAwait( Fsm, From, Event, To )
|
||||
|
||||
if self.DisplayCount >= self.DisplayInterval then
|
||||
|
||||
local TaskJTAC = self.Task -- Tasking.Task#TASK_JTAC
|
||||
TaskJTAC.Spots = TaskJTAC.Spots or {}
|
||||
for TargetUnitName, SpotData in pairs( TaskJTAC.Spots) do
|
||||
local TargetUnit = UNIT:FindByName( TargetUnitName )
|
||||
self.FACUnit:MessageToGroup( "Lasing " .. TargetUnit:GetTypeName() .. " with laser code " .. SpotData:getCode(), 15, self.ProcessGroup )
|
||||
end
|
||||
self.DisplayCount = 1
|
||||
else
|
||||
self.DisplayCount = self.DisplayCount + 1
|
||||
end
|
||||
|
||||
self:NextEvent( Fsm.JTACMenuAwait )
|
||||
end
|
||||
|
||||
--- StateMachine callback function for a PROCESS
|
||||
-- @param #PROCESS_JTAC self
|
||||
-- @param Core.Fsm#FSM_PROCESS Fsm
|
||||
-- @param #string Event
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
-- @param Wrapper.Unit#UNIT TargetUnit
|
||||
function PROCESS_JTAC:OnJTACMenuSpot( Fsm, From, Event, To, TargetUnit )
|
||||
|
||||
local TargetUnitName = TargetUnit:GetName()
|
||||
|
||||
local TaskJTAC = self.Task -- Tasking.Task#TASK_JTAC
|
||||
|
||||
TaskJTAC.Spots = TaskJTAC.Spots or {}
|
||||
TaskJTAC.Spots[TargetUnitName] = TaskJTAC.Spots[TargetUnitName] or {}
|
||||
|
||||
local DCSFACObject = self.FACUnit:GetDCSObject()
|
||||
local TargetVec3 = TargetUnit:GetVec3()
|
||||
|
||||
TaskJTAC.Spots[TargetUnitName] = Spot.createInfraRed( self.FACUnit:GetDCSObject(), { x = 0, y = 1, z = 0 }, TargetUnit:GetVec3(), math.random( 1000, 9999 ) )
|
||||
|
||||
local SpotData = TaskJTAC.Spots[TargetUnitName]
|
||||
self.FACUnit:MessageToGroup( "Lasing " .. TargetUnit:GetTypeName() .. " with laser code " .. SpotData:getCode(), 15, self.ProcessGroup )
|
||||
|
||||
self:NextEvent( Fsm.JTACMenuAwait )
|
||||
end
|
||||
|
||||
--- StateMachine callback function for a PROCESS
|
||||
-- @param #PROCESS_JTAC self
|
||||
-- @param Core.Fsm#FSM_PROCESS Fsm
|
||||
-- @param #string Event
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
-- @param Wrapper.Unit#UNIT TargetUnit
|
||||
function PROCESS_JTAC:OnJTACMenuCancel( Fsm, From, Event, To, TargetUnit )
|
||||
|
||||
local TargetUnitName = TargetUnit:GetName()
|
||||
|
||||
local TaskJTAC = self.Task -- Tasking.Task#TASK_JTAC
|
||||
|
||||
TaskJTAC.Spots = TaskJTAC.Spots or {}
|
||||
if TaskJTAC.Spots[TargetUnitName] then
|
||||
TaskJTAC.Spots[TargetUnitName]:destroy() -- destroys the spot
|
||||
TaskJTAC.Spots[TargetUnitName] = nil
|
||||
end
|
||||
|
||||
self.FACUnit:MessageToGroup( "Stopped lasing " .. TargetUnit:GetTypeName(), 15, self.ProcessGroup )
|
||||
|
||||
self:NextEvent( Fsm.JTACMenuAwait )
|
||||
end
|
||||
|
||||
|
||||
@@ -1,173 +0,0 @@
|
||||
--- @module Process_Pickup
|
||||
|
||||
--- PROCESS_PICKUP class
|
||||
-- @type PROCESS_PICKUP
|
||||
-- @field Wrapper.Unit#UNIT ProcessUnit
|
||||
-- @field Core.Set#SET_UNIT TargetSetUnit
|
||||
-- @extends Core.Fsm#FSM_PROCESS
|
||||
PROCESS_PICKUP = {
|
||||
ClassName = "PROCESS_PICKUP",
|
||||
Fsm = {},
|
||||
TargetSetUnit = nil,
|
||||
}
|
||||
|
||||
|
||||
--- Creates a new DESTROY process.
|
||||
-- @param #PROCESS_PICKUP self
|
||||
-- @param Tasking.Task#TASK Task
|
||||
-- @param Wrapper.Unit#UNIT ProcessUnit
|
||||
-- @param Core.Set#SET_UNIT TargetSetUnit
|
||||
-- @return #PROCESS_PICKUP self
|
||||
function PROCESS_PICKUP:New( Task, ProcessName, ProcessUnit )
|
||||
|
||||
-- Inherits from BASE
|
||||
local self = BASE:Inherit( self, PROCESS:New( ProcessName, Task, ProcessUnit ) ) -- #PROCESS_PICKUP
|
||||
|
||||
self.DisplayInterval = 30
|
||||
self.DisplayCount = 30
|
||||
self.DisplayMessage = true
|
||||
self.DisplayTime = 10 -- 10 seconds is the default
|
||||
self.DisplayCategory = "HQ" -- Targets is the default display category
|
||||
|
||||
self.Fsm = FSM_PROCESS:New( self, {
|
||||
initial = 'Assigned',
|
||||
events = {
|
||||
{ name = 'Start', from = 'Assigned', to = 'Navigating' },
|
||||
{ name = 'Start', from = 'Navigating', to = 'Navigating' },
|
||||
{ name = 'Nearby', from = 'Navigating', to = 'Preparing' },
|
||||
{ name = 'Pickup', from = 'Preparing', to = 'Loading' },
|
||||
{ name = 'Load', from = 'Loading', to = 'Success' },
|
||||
{ name = 'Fail', from = 'Assigned', to = 'Failed' },
|
||||
{ name = 'Fail', from = 'Navigating', to = 'Failed' },
|
||||
{ name = 'Fail', from = 'Preparing', to = 'Failed' },
|
||||
},
|
||||
callbacks = {
|
||||
onStart = self.OnStart,
|
||||
onNearby = self.OnNearby,
|
||||
onPickup = self.OnPickup,
|
||||
onLoad = self.OnLoad,
|
||||
},
|
||||
endstates = { 'Success', 'Failed' }
|
||||
} )
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Process Events
|
||||
|
||||
--- StateMachine callback function for a PROCESS
|
||||
-- @param #PROCESS_PICKUP self
|
||||
-- @param Core.Fsm#FSM_PROCESS Fsm
|
||||
-- @param #string Event
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
function PROCESS_PICKUP:OnStart( Fsm, From, Event, To )
|
||||
|
||||
self:NextEvent( Fsm.Start )
|
||||
end
|
||||
|
||||
--- StateMachine callback function for a PROCESS
|
||||
-- @param #PROCESS_PICKUP self
|
||||
-- @param Core.Fsm#FSM_PROCESS Fsm
|
||||
-- @param #string Event
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
function PROCESS_PICKUP:OnNavigating( Fsm, From, Event, To )
|
||||
|
||||
local TaskGroup = self.ProcessUnit:GetGroup()
|
||||
if self.DisplayCount >= self.DisplayInterval then
|
||||
MESSAGE:New( "Your group with assigned " .. self.Task:GetName() .. " task has " .. self.TargetSetUnit:GetUnitTypesText() .. " targets left to be destroyed.", 5, "HQ" ):ToGroup( TaskGroup )
|
||||
self.DisplayCount = 1
|
||||
else
|
||||
self.DisplayCount = self.DisplayCount + 1
|
||||
end
|
||||
|
||||
return true -- Process always the event.
|
||||
|
||||
end
|
||||
|
||||
|
||||
--- StateMachine callback function for a PROCESS
|
||||
-- @param #PROCESS_PICKUP self
|
||||
-- @param Core.Fsm#FSM_PROCESS Fsm
|
||||
-- @param #string Event
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
-- @param Core.Event#EVENTDATA Event
|
||||
function PROCESS_PICKUP:OnHitTarget( Fsm, From, Event, To, Event )
|
||||
|
||||
|
||||
self.TargetSetUnit:Flush( self )
|
||||
|
||||
if self.TargetSetUnit:FindUnit( Event.IniUnitName ) then
|
||||
self.TargetSetUnit:RemoveUnitsByName( Event.IniUnitName )
|
||||
local TaskGroup = self.ProcessUnit:GetGroup()
|
||||
MESSAGE:New( "You hit a target. Your group with assigned " .. self.Task:GetName() .. " task has " .. self.TargetSetUnit:Count() .. " targets ( " .. self.TargetSetUnit:GetUnitTypesText() .. " ) left to be destroyed.", 15, "HQ" ):ToGroup( TaskGroup )
|
||||
end
|
||||
|
||||
|
||||
if self.TargetSetUnit:Count() > 0 then
|
||||
self:NextEvent( Fsm.MoreTargets )
|
||||
else
|
||||
self:NextEvent( Fsm.Destroyed )
|
||||
end
|
||||
end
|
||||
|
||||
--- StateMachine callback function for a PROCESS
|
||||
-- @param #PROCESS_PICKUP self
|
||||
-- @param Core.Fsm#FSM_PROCESS Fsm
|
||||
-- @param #string Event
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
function PROCESS_PICKUP:OnMoreTargets( Fsm, From, Event, To )
|
||||
|
||||
|
||||
end
|
||||
|
||||
--- StateMachine callback function for a PROCESS
|
||||
-- @param #PROCESS_PICKUP self
|
||||
-- @param Core.Fsm#FSM_PROCESS Fsm
|
||||
-- @param #string Event
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
-- @param Core.Event#EVENTDATA DCSEvent
|
||||
function PROCESS_PICKUP:OnKilled( Fsm, From, Event, To )
|
||||
|
||||
self:NextEvent( Fsm.Restart )
|
||||
|
||||
end
|
||||
|
||||
--- StateMachine callback function for a PROCESS
|
||||
-- @param #PROCESS_PICKUP self
|
||||
-- @param Core.Fsm#FSM_PROCESS Fsm
|
||||
-- @param #string Event
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
function PROCESS_PICKUP:OnRestart( Fsm, From, Event, To )
|
||||
|
||||
self:NextEvent( Fsm.Menu )
|
||||
|
||||
end
|
||||
|
||||
--- StateMachine callback function for a PROCESS
|
||||
-- @param #PROCESS_PICKUP self
|
||||
-- @param Core.Fsm#FSM_PROCESS Fsm
|
||||
-- @param #string Event
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
function PROCESS_PICKUP:OnDestroyed( Fsm, From, Event, To )
|
||||
|
||||
end
|
||||
|
||||
--- DCS Events
|
||||
|
||||
--- @param #PROCESS_PICKUP self
|
||||
-- @param Core.Event#EVENTDATA Event
|
||||
function PROCESS_PICKUP:EventDead( Event )
|
||||
|
||||
if Event.IniDCSUnit then
|
||||
self:NextEvent( self.Fsm.HitTarget, Event )
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- # @{#ACT_ROUTE} FSM class, extends @{Fsm#FSM_PROCESS}
|
||||
-- # @{#ACT_ROUTE} FSM class, extends @{Core.Fsm#FSM_PROCESS}
|
||||
--
|
||||
-- ## ACT_ROUTE state machine:
|
||||
--
|
||||
@@ -60,9 +60,9 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- # 1) @{#ACT_ROUTE_ZONE} class, extends @{Fsm.Route#ACT_ROUTE}
|
||||
-- # 1) @{#ACT_ROUTE_ZONE} class, extends @{Core.Fsm.Route#ACT_ROUTE}
|
||||
--
|
||||
-- The ACT_ROUTE_ZONE class implements the core functions to route an AIR @{Controllable} player @{Unit} to a @{Zone}.
|
||||
-- The ACT_ROUTE_ZONE class implements the core functions to route an AIR @{Wrapper.Controllable} player @{Wrapper.Unit} to a @{Zone}.
|
||||
-- The player receives on perioding times messages with the coordinates of the route to follow.
|
||||
-- Upon arrival at the zone, a confirmation of arrival is sent, and the process will be ended.
|
||||
--
|
||||
@@ -72,7 +72,8 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module Route
|
||||
-- @module Actions.Route
|
||||
-- @image MOOSE.JPG
|
||||
|
||||
|
||||
do -- ACT_ROUTE
|
||||
@@ -361,7 +362,7 @@ do -- ACT_ROUTE_POINT
|
||||
local Distance = self.Coordinate:Get2DDistance( ProcessUnit:GetCoordinate() )
|
||||
|
||||
if Distance <= self.Range then
|
||||
local RouteText = "You have arrived."
|
||||
local RouteText = "Task \"" .. self:GetTask():GetName() .. "\", you have arrived."
|
||||
self:GetCommandCenter():MessageTypeToGroup( RouteText, ProcessUnit:GetGroup(), MESSAGE.Type.Information )
|
||||
return true
|
||||
end
|
||||
@@ -380,7 +381,7 @@ do -- ACT_ROUTE_POINT
|
||||
-- @param #string To
|
||||
function ACT_ROUTE_POINT:onafterReport( ProcessUnit, From, Event, To )
|
||||
|
||||
local RouteText = self:GetRouteText( ProcessUnit )
|
||||
local RouteText = "Task \"" .. self:GetTask():GetName() .. "\", " .. self:GetRouteText( ProcessUnit )
|
||||
|
||||
self:GetCommandCenter():MessageTypeToGroup( RouteText, ProcessUnit:GetGroup(), MESSAGE.Type.Update )
|
||||
end
|
||||
@@ -452,7 +453,7 @@ do -- ACT_ROUTE_ZONE
|
||||
function ACT_ROUTE_ZONE:onfuncHasArrived( ProcessUnit )
|
||||
|
||||
if ProcessUnit:IsInZone( self.Zone ) then
|
||||
local RouteText = "You have arrived within the zone."
|
||||
local RouteText = "Task \"" .. self:GetTask():GetName() .. "\", you have arrived within the zone."
|
||||
self:GetCommandCenter():MessageTypeToGroup( RouteText, ProcessUnit:GetGroup(), MESSAGE.Type.Information )
|
||||
end
|
||||
|
||||
@@ -470,7 +471,7 @@ do -- ACT_ROUTE_ZONE
|
||||
function ACT_ROUTE_ZONE:onafterReport( ProcessUnit, From, Event, To )
|
||||
self:F( { ProcessUnit = ProcessUnit } )
|
||||
|
||||
local RouteText = self:GetRouteText( ProcessUnit )
|
||||
local RouteText = "Task \"" .. self:GetTask():GetName() .. "\", " .. self:GetRouteText( ProcessUnit )
|
||||
self:GetCommandCenter():MessageTypeToGroup( RouteText, ProcessUnit:GetGroup(), MESSAGE.Type.Update )
|
||||
end
|
||||
|
||||
|
||||
@@ -1,13 +1,236 @@
|
||||
--- **Core** -- Management of CARGO logistics, that can be transported from and to transportation carriers.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- # 1) MOOSE Cargo System.
|
||||
--
|
||||
-- #### Those who have used the mission editor, know that the DCS mission editor provides cargo facilities.
|
||||
-- However, these are merely static objects. Wouldn't it be nice if cargo could bring a new dynamism into your
|
||||
-- simulations? Where various objects of various types could be treated also as cargo?
|
||||
--
|
||||
-- This is what MOOSE brings to you, a complete new cargo object model that used the cargo capabilities of
|
||||
-- DCS world, but enhances it.
|
||||
--
|
||||
-- MOOSE Cargo introduces also a new concept, called a "carrier". These can be:
|
||||
--
|
||||
-- - Helicopters
|
||||
-- - Planes
|
||||
-- - Ground Vehicles
|
||||
-- - Ships
|
||||
--
|
||||
-- With the MOOSE Cargo system, you can:
|
||||
--
|
||||
-- - Take full control of the cargo as objects within your script (see below).
|
||||
-- - Board/Unboard infantry into carriers. Also other objects can be boarded, like mortars.
|
||||
-- - Load/Unload dcs world cargo objects into carriers.
|
||||
-- - Load/Unload other static objects into carriers (like tires etc).
|
||||
-- - Slingload cargo objects.
|
||||
-- - Board units one by one...
|
||||
--
|
||||
-- This module is still under construction, but is described above works already, and will keep working ...
|
||||
-- # 2) MOOSE Cargo Objects.
|
||||
--
|
||||
-- In order to make use of the MOOSE cargo system, you need to **declare** the DCS objects as MOOSE cargo objects!
|
||||
--
|
||||
-- This sounds complicated, but it is actually quite simple.
|
||||
--
|
||||
-- See here an example:
|
||||
--
|
||||
-- local EngineerCargoGroup = CARGO_GROUP:New( GROUP:FindByName( "Engineers" ), "Workmaterials", "Engineers", 250 )
|
||||
--
|
||||
-- The above code declares a MOOSE cargo object called `EngineerCargoGroup`.
|
||||
-- It actually just refers to an infantry group created within the sim called `"Engineers"`.
|
||||
-- The infantry group now becomes controlled by the MOOSE cargo object `EngineerCargoGroup`.
|
||||
-- A MOOSE cargo object also has properties, like the type of cargo, the logical name, and the reporting range.
|
||||
--
|
||||
-- There are 4 types of MOOSE cargo objects possible, each represented by its own class:
|
||||
--
|
||||
-- - @{Cargo.CargoGroup#CARGO_GROUP}: A MOOSE cargo that is represented by a DCS world GROUP object.
|
||||
-- - @{Cargo.CargoCrate#CARGO_CRATE}: A MOOSE cargo that is represented by a DCS world cargo object (static object).
|
||||
-- - @{Cargo.CargoUnit#CARGO_UNIT}: A MOOSE cargo that is represented by a DCS world unit object or static object.
|
||||
-- - @{Cargo.CargoSlingload#CARGO_SLINGLOAD}: A MOOSE cargo that is represented by a DCS world cargo object (static object), that can be slingloaded.
|
||||
--
|
||||
-- Note that a CARGO crate is not meant to be slingloaded (it can, but it is not **meant** to be handled like that.
|
||||
-- Instead, a CARGO_CRATE is able to load itself into the bays of a carrier.
|
||||
--
|
||||
-- Each of these MOOSE cargo objects behave in its own way, and have methods to be handled.
|
||||
--
|
||||
-- local InfantryGroup = GROUP:FindByName( "Infantry" )
|
||||
-- local InfantryCargo = CARGO_GROUP:New( InfantryGroup, "Engineers", "Infantry Engineers", 2000 )
|
||||
-- local CargoCarrier = UNIT:FindByName( "Carrier" )
|
||||
-- -- This call will make the Cargo run to the CargoCarrier.
|
||||
-- -- Upon arrival at the CargoCarrier, the Cargo will be Loaded into the Carrier.
|
||||
-- -- This process is now fully automated.
|
||||
-- InfantryCargo:Board( CargoCarrier, 25 )
|
||||
--
|
||||
-- The above would create a MOOSE cargo object called `InfantryCargo`, and using that object,
|
||||
-- you can board the cargo into the carrier `CargoCarrier`.
|
||||
-- Simple, isn't it? Told you, and this is only the beginning.
|
||||
--
|
||||
-- The boarding, unboarding, loading, unloading of cargo is however something that is not meant to be coded manualy by mission designers.
|
||||
-- It would be too low-level and not end-user friendly to deal with cargo handling complexity.
|
||||
-- Things can become really complex if you want to make cargo being handled and behave in multiple scenarios.
|
||||
--
|
||||
-- # 3) Cargo Handling Classes, the main engines for mission designers!
|
||||
--
|
||||
-- For this reason, the MOOSE Cargo System is heavily used by 3 important **cargo handling class hierarchies** within MOOSE,
|
||||
-- that make cargo come "alive" within your mission in a full automatic manner!
|
||||
--
|
||||
-- ## 3.1) AI Cargo handlers.
|
||||
--
|
||||
-- - @{AI.AI_Cargo_APC} will create for you the capatility to make an APC group handle cargo.
|
||||
-- - @{AI.AI_Cargo_Helicopter} will create for you the capatility to make a Helicopter group handle cargo.
|
||||
--
|
||||
--
|
||||
-- ## 3.2) AI Cargo transportation dispatchers.
|
||||
--
|
||||
-- There are also dispatchers that make AI work together to transport cargo automatically!!!
|
||||
--
|
||||
-- - @{AI.AI_Cargo_Dispatcher_APC} derived classes will create for your dynamic cargo handlers controlled by AI ground vehicle groups (APCs) to transport cargo between sites.
|
||||
-- - @{AI.AI_Cargo_Dispatcher_Helicopters} derived classes will create for your dynamic cargo handlers controlled by AI helicpter groups to transport cargo between sites.
|
||||
--
|
||||
-- ## 3.3) Cargo transportation tasking.
|
||||
--
|
||||
-- And there is cargo transportation tasking for human players.
|
||||
--
|
||||
-- - @{Tasking.Task_CARGO} derived classes will create for you cargo transportation tasks, that allow human players to interact with MOOSE cargo objects to complete tasks.
|
||||
--
|
||||
-- Please refer to the documentation reflected within these modules to understand the detailed capabilties.
|
||||
--
|
||||
-- # 4) Cargo SETs.
|
||||
--
|
||||
-- To make life a bit more easy, MOOSE cargo objects can be grouped into a @{Core.Set#SET_CARGO}.
|
||||
-- This is a collection of MOOSE cargo objects.
|
||||
--
|
||||
-- This would work as follows:
|
||||
--
|
||||
-- -- Define the cargo set.
|
||||
-- local CargoSetWorkmaterials = SET_CARGO:New():FilterTypes( "Workmaterials" ):FilterStart()
|
||||
--
|
||||
-- -- Now add cargo the cargo set.
|
||||
-- local EngineerCargoGroup = CARGO_GROUP:New( GROUP:FindByName( "Engineers" ), "Workmaterials", "Engineers", 250 )
|
||||
-- local ConcreteCargo = CARGO_SLINGLOAD:New( STATIC:FindByName( "Concrete" ), "Workmaterials", "Concrete", 150, 50 )
|
||||
-- local CrateCargo = CARGO_CRATE:New( STATIC:FindByName( "Crate" ), "Workmaterials", "Crate", 150, 50 )
|
||||
-- local EnginesCargo = CARGO_CRATE:New( STATIC:FindByName( "Engines" ), "Workmaterials", "Engines", 150, 50 )
|
||||
-- local MetalCargo = CARGO_CRATE:New( STATIC:FindByName( "Metal" ), "Workmaterials", "Metal", 150, 50 )
|
||||
--
|
||||
-- This is a very powerful concept!
|
||||
-- Instead of having to deal with multiple MOOSE cargo objects yourself, the cargo set capability will group cargo objects into one set.
|
||||
-- The key is the **cargo type** name given at each cargo declaration!
|
||||
-- In the above example, the cargo type name is `"Workmaterials"`. Each cargo object declared is given that type name. (the 2nd parameter).
|
||||
-- What happens now is that the cargo set `CargoSetWorkmaterials` will be added with each cargo object **dynamically** when the cargo object is created.
|
||||
-- In other words, the cargo set `CargoSetWorkmaterials` will incorporate any `"Workmaterials"` dynamically into its set.
|
||||
--
|
||||
-- The cargo sets are extremely important for the AI cargo transportation dispatchers and the cargo transporation tasking.
|
||||
--
|
||||
-- # 5) Declare cargo directly in the mission editor!
|
||||
--
|
||||
-- But I am not finished! There is something more, that is even more great!
|
||||
-- Imagine the mission designers having to code all these lines every time it wants to embed cargo within a mission.
|
||||
--
|
||||
-- -- Now add cargo the cargo set.
|
||||
-- local EngineerCargoGroup = CARGO_GROUP:New( GROUP:FindByName( "Engineers" ), "Workmaterials", "Engineers", 250 )
|
||||
-- local ConcreteCargo = CARGO_SLINGLOAD:New( STATIC:FindByName( "Concrete" ), "Workmaterials", "Concrete", 150, 50 )
|
||||
-- local CrateCargo = CARGO_CRATE:New( STATIC:FindByName( "Crate" ), "Workmaterials", "Crate", 150, 50 )
|
||||
-- local EnginesCargo = CARGO_CRATE:New( STATIC:FindByName( "Engines" ), "Workmaterials", "Engines", 150, 50 )
|
||||
-- local MetalCargo = CARGO_CRATE:New( STATIC:FindByName( "Metal" ), "Workmaterials", "Metal", 150, 50 )
|
||||
--
|
||||
-- This would be extremely tiring and a huge overload.
|
||||
-- However, the MOOSE framework allows to declare MOOSE cargo objects within the mission editor!!!
|
||||
--
|
||||
-- So, at mission startup, MOOSE will search for objects following a special naming convention, and will **create** for you **dynamically
|
||||
-- cargo objects** at **mission start**!!! -- These cargo objects can then be automatically incorporated within cargo set(s)!!!
|
||||
-- In other words, your mission will be reduced to about a few lines of code, providing you with a full dynamic cargo handling mission!
|
||||
--
|
||||
-- ## 5.1) Use \#CARGO tags in the mission editor:
|
||||
--
|
||||
-- MOOSE can create automatically cargo objects, if the name of the cargo contains the **\#CARGO** tag.
|
||||
-- When a mission starts, MOOSE will scan all group and static objects it found for the presence of the \#CARGO tag.
|
||||
-- When found, MOOSE will declare the object as cargo (create in the background a CARGO_ object, like CARGO_GROUP, CARGO_CRATE or CARGO_SLINGLOAD.
|
||||
-- The creation of these CARGO_ objects will allow to be filtered and automatically added in SET_CARGO objects.
|
||||
-- In other words, with very minimal code as explained in the above code section, you are able to create vast amounts of cargo objects just from within the editor.
|
||||
--
|
||||
-- What I talk about is this:
|
||||
--
|
||||
-- -- BEFORE THIS SCRIPT STARTS, MOOSE WILL ALREADY HAVE SCANNED FOR OBJECTS WITH THE #CARGO TAG IN THE NAME.
|
||||
-- -- FOR EACH OF THESE OBJECT, MOOSE WILL HAVE CREATED CARGO_ OBJECTS LIKE CARGO_GROUP, CARGO_CRATE AND CARGO_SLINGLOAD.
|
||||
--
|
||||
-- HQ = GROUP:FindByName( "HQ", "Bravo" )
|
||||
--
|
||||
-- CommandCenter = COMMANDCENTER
|
||||
-- :New( HQ, "Lima" )
|
||||
--
|
||||
-- Mission = MISSION
|
||||
-- :New( CommandCenter, "Operation Cargo Fun", "Tactical", "Transport Cargo", coalition.side.RED )
|
||||
--
|
||||
-- TransportGroups = SET_GROUP:New():FilterCoalitions( "blue" ):FilterPrefixes( "Transport" ):FilterStart()
|
||||
--
|
||||
-- TaskDispatcher = TASK_CARGO_DISPATCHER:New( Mission, TransportGroups )
|
||||
--
|
||||
-- -- This is the most important now. You setup a new SET_CARGO filtering the relevant type.
|
||||
-- -- The actual cargo objects are now created by MOOSE in the background.
|
||||
-- -- Each cargo is setup in the Mission Editor using the #CARGO tag in the group name.
|
||||
-- -- This allows a truly dynamic setup.
|
||||
-- local CargoSetWorkmaterials = SET_CARGO:New():FilterTypes( "Workmaterials" ):FilterStart()
|
||||
--
|
||||
-- local WorkplaceTask = TaskDispatcher:AddTransportTask( "Build a Workplace", CargoSetWorkmaterials, "Transport the workers, engineers and the equipment near the Workplace." )
|
||||
-- TaskDispatcher:SetTransportDeployZone( WorkplaceTask, ZONE:New( "Workplace" ) )
|
||||
--
|
||||
-- The above code example has the `CargoSetWorkmaterials`, which is a SET_CARGO collection and will include the CARGO_ objects of the type "Workmaterials".
|
||||
-- And there is NO cargo object actually declared within the script! However, if you would open the mission, there would be hundreds of cargo objects...
|
||||
--
|
||||
-- The \#CARGO tag even allows for several options to be specified, which are important to learn.
|
||||
--
|
||||
-- ## 5.2) The \#CARGO tag to create CARGO_GROUP objects:
|
||||
--
|
||||
-- You can also use the \#CARGO tag on **group** objects of the mission editor.
|
||||
--
|
||||
-- For example, the following #CARGO naming in the **group name** of the object, will create a CARGO_GROUP object when the mission starts.
|
||||
--
|
||||
-- `Infantry #CARGO(T=Workmaterials,RR=500,NR=25)`
|
||||
--
|
||||
-- This will create a CARGO_GROUP object:
|
||||
--
|
||||
-- * with the group name `Infantry #CARGO`
|
||||
-- * is of type `Workmaterials`
|
||||
-- * will report when a carrier is within 500 meters
|
||||
-- * will board to carriers when the carrier is within 500 meters from the cargo object
|
||||
-- * will dissapear when the cargo is within 25 meters from the carrier during boarding
|
||||
--
|
||||
-- So the overall syntax of the #CARGO naming tag and arguments are:
|
||||
--
|
||||
-- `GroupName #CARGO(T=CargoTypeName,RR=Range,NR=Range)`
|
||||
--
|
||||
-- * **T=** Provide a text that contains the type name of the cargo object. This type name can be used to filter cargo within a SET_CARGO object.
|
||||
-- * **RR=** Provide the minimal range in meters when the report to the carrier, and board to the carrier.
|
||||
-- Note that this option is optional, so can be omitted. The default value of the RR is 250 meters.
|
||||
-- * **NR=** Provide the maximum range in meters when the cargo units will be boarded within the carrier during boarding.
|
||||
-- Note that this option is optional, so can be omitted. The default value of the RR is 10 meters.
|
||||
--
|
||||
-- ## 5.2) The \#CARGO tag to create CARGO_CRATE objects:
|
||||
--
|
||||
-- You can also use the \#CARGO tag on **static** objects, including **static cargo** objects of the mission editor.
|
||||
--
|
||||
-- For example, the following #CARGO naming in the **static name** of the object, will create a CARGO_CRATE object when the mission starts.
|
||||
--
|
||||
-- `Static #CARGO(T=Workmaterials,RR=500,NR=25)`
|
||||
--
|
||||
-- This will create a CARGO_CRATE object:
|
||||
--
|
||||
-- * with the group name `Static #CARGO`
|
||||
-- * is of type `Workmaterials`
|
||||
-- * will report when a carrier is within 500 meters
|
||||
-- * will board to carriers when the carrier is within 500 meters from the cargo object
|
||||
-- * will dissapear when the cargo is within 25 meters from the carrier during boarding
|
||||
--
|
||||
-- So the overall syntax of the #CARGO naming tag and arguments are:
|
||||
--
|
||||
-- `StaticName #CARGO(T=CargoTypeName,RR=Range,NR=Range)`
|
||||
--
|
||||
-- * **T=** Provide a text that contains the type name of the cargo object. This type name can be used to filter cargo within a SET_CARGO object.
|
||||
-- * **RR=** Provide the minimal range in meters when the report to the carrier, and board to the carrier.
|
||||
-- Note that this option is optional, so can be omitted. The default value of the RR is 250 meters.
|
||||
-- * **NR=** Provide the maximum range in meters when the cargo units will be boarded within the carrier during boarding.
|
||||
-- Note that this option is optional, so can be omitted. The default value of the RR is 10 meters.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
@@ -16,7 +239,8 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module Cargo
|
||||
-- @module Cargo.Cargo
|
||||
-- @image Cargo.JPG
|
||||
|
||||
-- Events
|
||||
|
||||
@@ -44,14 +268,14 @@
|
||||
-- The cargo must be in the **Loaded** state.
|
||||
-- @function [parent=#CARGO] UnBoard
|
||||
-- @param #CARGO self
|
||||
-- @param Core.Point#POINT_VEC2 ToPointVec2 (optional) @{Point#POINT_VEC2) to where the cargo should run after onboarding. If not provided, the cargo will run to 60 meters behind the Carrier location.
|
||||
-- @param Core.Point#POINT_VEC2 ToPointVec2 (optional) @{Core.Point#POINT_VEC2) to where the cargo should run after onboarding. If not provided, the cargo will run to 60 meters behind the Carrier location.
|
||||
|
||||
--- UnBoards the cargo to a Carrier. The event will create a movement (= running or driving) of the cargo from the Carrier.
|
||||
-- The cargo must be in the **Loaded** state.
|
||||
-- @function [parent=#CARGO] __UnBoard
|
||||
-- @param #CARGO self
|
||||
-- @param #number DelaySeconds The amount of seconds to delay the action.
|
||||
-- @param Core.Point#POINT_VEC2 ToPointVec2 (optional) @{Point#POINT_VEC2) to where the cargo should run after onboarding. If not provided, the cargo will run to 60 meters behind the Carrier location.
|
||||
-- @param Core.Point#POINT_VEC2 ToPointVec2 (optional) @{Core.Point#POINT_VEC2) to where the cargo should run after onboarding. If not provided, the cargo will run to 60 meters behind the Carrier location.
|
||||
|
||||
|
||||
-- Load
|
||||
@@ -76,14 +300,14 @@
|
||||
-- The cargo must be in the **Loaded** state.
|
||||
-- @function [parent=#CARGO] UnLoad
|
||||
-- @param #CARGO self
|
||||
-- @param Core.Point#POINT_VEC2 ToPointVec2 (optional) @{Point#POINT_VEC2) to where the cargo will be placed after unloading. If not provided, the cargo will be placed 60 meters behind the Carrier location.
|
||||
-- @param Core.Point#POINT_VEC2 ToPointVec2 (optional) @{Core.Point#POINT_VEC2) to where the cargo will be placed after unloading. If not provided, the cargo will be placed 60 meters behind the Carrier location.
|
||||
|
||||
--- UnLoads the cargo to a Carrier. The event will unload the cargo from the Carrier. There will be no movement simulated of the cargo loading.
|
||||
-- The cargo must be in the **Loaded** state.
|
||||
-- @function [parent=#CARGO] __UnLoad
|
||||
-- @param #CARGO self
|
||||
-- @param #number DelaySeconds The amount of seconds to delay the action.
|
||||
-- @param Core.Point#POINT_VEC2 ToPointVec2 (optional) @{Point#POINT_VEC2) to where the cargo will be placed after unloading. If not provided, the cargo will be placed 60 meters behind the Carrier location.
|
||||
-- @param Core.Point#POINT_VEC2 ToPointVec2 (optional) @{Core.Point#POINT_VEC2) to where the cargo will be placed after unloading. If not provided, the cargo will be placed 60 meters behind the Carrier location.
|
||||
|
||||
-- State Transition Functions
|
||||
|
||||
@@ -152,9 +376,8 @@ do -- CARGO
|
||||
-- @field #boolean Representable This flag defines if the cargo can be represented by a DCS Unit.
|
||||
-- @field #boolean Containable This flag defines if the cargo can be contained within a DCS Unit.
|
||||
|
||||
--- # (R2.4) CARGO class, extends @{Fsm#FSM_PROCESS}
|
||||
--- Defines the core functions that defines a cargo object within MOOSE.
|
||||
--
|
||||
-- The CARGO class defines the core functions that defines a cargo object within MOOSE.
|
||||
-- A cargo is a **logical object** defined that is available for transport, and has a life status within a simulation.
|
||||
--
|
||||
-- CARGO is not meant to be used directly by mission designers, but provides a base class for **concrete cargo implementation classes** to handle:
|
||||
@@ -248,7 +471,7 @@ do -- CARGO
|
||||
self.CargoLimit = 0
|
||||
|
||||
self.LoadRadius = LoadRadius or 500
|
||||
self.NearRadius = NearRadius or 25
|
||||
--self.NearRadius = NearRadius or 25
|
||||
|
||||
self:SetDeployed( false )
|
||||
|
||||
@@ -340,7 +563,7 @@ do -- CARGO
|
||||
-- @param #CARGO self
|
||||
function CARGO:Destroy()
|
||||
if self.CargoObject then
|
||||
self.CargoObject:Destroy( false )
|
||||
self.CargoObject:Destroy()
|
||||
end
|
||||
self:Destroyed()
|
||||
end
|
||||
@@ -352,6 +575,17 @@ do -- CARGO
|
||||
return self.Name
|
||||
end
|
||||
|
||||
--- Get the current active object representing or being the Cargo.
|
||||
-- @param #CARGO self
|
||||
-- @return Wrapper.Positionable#POSITIONABLE The object representing or being the Cargo.
|
||||
function CARGO:GetObject()
|
||||
if self:IsLoaded() then
|
||||
return self.CargoCarrier
|
||||
else
|
||||
return self.CargoObject
|
||||
end
|
||||
end
|
||||
|
||||
--- Get the object name of the Cargo.
|
||||
-- @param #CARGO self
|
||||
-- @return #string The object name of the Cargo.
|
||||
@@ -592,7 +826,8 @@ do -- CARGO
|
||||
|
||||
local Distance = 0
|
||||
if self:IsUnLoaded() then
|
||||
Distance = Coordinate:Get2DDistance( self.CargoObject:GetCoordinate() )
|
||||
local CargoCoordinate = self.CargoObject:GetCoordinate()
|
||||
Distance = Coordinate:Get2DDistance( CargoCoordinate )
|
||||
self:T( Distance )
|
||||
if Distance <= self.LoadRadius then
|
||||
return true
|
||||
@@ -623,7 +858,7 @@ do -- CARGO
|
||||
end
|
||||
|
||||
|
||||
--- Check if CargoCarrier is near the Cargo to be Loaded.
|
||||
--- Check if CargoCarrier is near the coordinate within NearRadius.
|
||||
-- @param #CARGO self
|
||||
-- @param Core.Point#COORDINATE Coordinate
|
||||
-- @param #number NearRadius The radius when the cargo will board the Carrier (to avoid collision).
|
||||
@@ -637,7 +872,7 @@ do -- CARGO
|
||||
--self:F( { CargoObjectVec2 = self.CargoObject:GetVec2() } )
|
||||
--self:F( { PointVec2 = PointVec2:GetVec2() } )
|
||||
local Distance = Coordinate:Get2DDistance( self.CargoObject:GetCoordinate() )
|
||||
--self:F( Distance )
|
||||
--self:F( { Distance = Distance, NearRadius = NearRadius or "nil" } )
|
||||
|
||||
if Distance <= NearRadius then
|
||||
--self:F( { PointVec2 = PointVec2, NearRadius = NearRadius, IsNear = true } )
|
||||
@@ -688,6 +923,13 @@ do -- CARGO
|
||||
return self.CargoObject:GetCoordinate()
|
||||
end
|
||||
|
||||
--- Get the weight of the cargo.
|
||||
-- @param #CARGO self
|
||||
-- @return #number Weight The weight in kg.
|
||||
function CARGO:GetWeight()
|
||||
return self.Weight
|
||||
end
|
||||
|
||||
--- Set the weight of the cargo.
|
||||
-- @param #CARGO self
|
||||
-- @param #number Weight The weight in kg.
|
||||
@@ -697,11 +939,27 @@ do -- CARGO
|
||||
return self
|
||||
end
|
||||
|
||||
--- Send a CC message to a @{Group}.
|
||||
--- Get the volume of the cargo.
|
||||
-- @param #CARGO self
|
||||
-- @return #number Volume The volume in kg.
|
||||
function CARGO:GetVolume()
|
||||
return self.Volume
|
||||
end
|
||||
|
||||
--- Set the volume of the cargo.
|
||||
-- @param #CARGO self
|
||||
-- @param #number Volume The volume in kg.
|
||||
-- @return #CARGO
|
||||
function CARGO:SetVolume( Volume )
|
||||
self.Volume = Volume
|
||||
return self
|
||||
end
|
||||
|
||||
--- Send a CC message to a @{Wrapper.Group}.
|
||||
-- @param #CARGO self
|
||||
-- @param #string Message
|
||||
-- @param Wrapper.Group#GROUP CarrierGroup The Carrier Group.
|
||||
-- @param #sring Name (optional) The name of the Group used as a prefix for the message to the Group. If not provided, there will be nothing shown.
|
||||
-- @param #string Name (optional) The name of the Group used as a prefix for the message to the Group. If not provided, there will be nothing shown.
|
||||
function CARGO:MessageToGroup( Message, CarrierGroup, Name )
|
||||
|
||||
MESSAGE:New( Message, 20, "Cargo " .. self:GetName() ):ToGroup( CarrierGroup )
|
||||
@@ -810,13 +1068,31 @@ do -- CARGO_REPRESENTABLE
|
||||
-- @param #CARGO_REPRESENTABLE self
|
||||
-- @param #string Type
|
||||
-- @param #string Name
|
||||
-- @param #number Weight
|
||||
-- @param #number LoadRadius (optional)
|
||||
-- @param #number NearRadius (optional)
|
||||
-- @return #CARGO_REPRESENTABLE
|
||||
function CARGO_REPRESENTABLE:New( CargoObject, Type, Name, Weight, LoadRadius, NearRadius )
|
||||
local self = BASE:Inherit( self, CARGO:New( Type, Name, Weight, LoadRadius, NearRadius ) ) -- #CARGO_REPRESENTABLE
|
||||
self:F( { Type, Name, Weight, LoadRadius, NearRadius } )
|
||||
function CARGO_REPRESENTABLE:New( CargoObject, Type, Name, LoadRadius, NearRadius )
|
||||
local self = BASE:Inherit( self, CARGO:New( Type, Name, 0, LoadRadius, NearRadius ) ) -- #CARGO_REPRESENTABLE
|
||||
self:F( { Type, Name, LoadRadius, NearRadius } )
|
||||
|
||||
local Desc = CargoObject:GetDesc()
|
||||
self:I( { Desc = Desc } )
|
||||
local Weight = math.random( 80, 120 )
|
||||
if Desc then
|
||||
if Desc.typeName == "2B11 mortar" then
|
||||
Weight = 210
|
||||
else
|
||||
Weight = Desc.massEmpty
|
||||
end
|
||||
end
|
||||
|
||||
self:SetWeight( Weight )
|
||||
|
||||
-- local Box = CargoUnit:GetBoundingBox()
|
||||
-- local VolumeUnit = ( Box.max.x - Box.min.x ) * ( Box.max.y - Box.min.y ) * ( Box.max.z - Box.min.z )
|
||||
-- self:I( { VolumeUnit = VolumeUnit, WeightUnit = WeightUnit } )
|
||||
--self:SetVolume( VolumeUnit )
|
||||
|
||||
|
||||
return self
|
||||
end
|
||||
@@ -853,11 +1129,11 @@ do -- CARGO_REPRESENTABLE
|
||||
return self
|
||||
end
|
||||
|
||||
--- Send a message to a @{Group} through a communication channel near the cargo.
|
||||
--- Send a message to a @{Wrapper.Group} through a communication channel near the cargo.
|
||||
-- @param #CARGO_REPRESENTABLE self
|
||||
-- @param #string Message
|
||||
-- @param Wrapper.Group#GROUP TaskGroup
|
||||
-- @param #sring Name (optional) The name of the Group used as a prefix for the message to the Group. If not provided, there will be nothing shown.
|
||||
-- @param #string Name (optional) The name of the Group used as a prefix for the message to the Group. If not provided, there will be nothing shown.
|
||||
function CARGO_REPRESENTABLE:MessageToGroup( Message, TaskGroup, Name )
|
||||
|
||||
local CoordinateZone = ZONE_RADIUS:New( "Zone" , self:GetCoordinate():GetVec2(), 500 )
|
||||
@@ -905,11 +1181,11 @@ do -- CARGO_REPORTABLE
|
||||
return self
|
||||
end
|
||||
|
||||
--- Send a CC message to a @{Group}.
|
||||
--- Send a CC message to a @{Wrapper.Group}.
|
||||
-- @param #CARGO_REPORTABLE self
|
||||
-- @param #string Message
|
||||
-- @param Wrapper.Group#GROUP TaskGroup
|
||||
-- @param #sring Name (optional) The name of the Group used as a prefix for the message to the Group. If not provided, there will be nothing shown.
|
||||
-- @param #string Name (optional) The name of the Group used as a prefix for the message to the Group. If not provided, there will be nothing shown.
|
||||
function CARGO_REPORTABLE:MessageToGroup( Message, TaskGroup, Name )
|
||||
|
||||
MESSAGE:New( Message, 20, "Cargo " .. self:GetName() .. " reporting" ):ToGroup( TaskGroup )
|
||||
@@ -1016,6 +1292,10 @@ end
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
-- @param Wrapper.Unit#UNIT CargoCarrier
|
||||
-- @param #number Speed
|
||||
-- @param #number BoardDistance
|
||||
-- @param #number LoadDistance
|
||||
-- @param #number Angle
|
||||
function CARGO_PACKAGE:onafterOnBoarded( From, Event, To, CargoCarrier, Speed, BoardDistance, LoadDistance, Angle )
|
||||
self:F()
|
||||
|
||||
@@ -1031,6 +1311,7 @@ end
|
||||
-- @param #string Event
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
-- @param Wrapper.Unit#UNIT CargoCarrier
|
||||
-- @param #number Speed
|
||||
-- @param #number UnLoadDistance
|
||||
-- @param #number UnBoardDistance
|
||||
@@ -1074,6 +1355,7 @@ end
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
-- @param Wrapper.Unit#UNIT CargoCarrier
|
||||
-- @param #number Speed
|
||||
function CARGO_PACKAGE:onafterUnBoarded( From, Event, To, CargoCarrier, Speed )
|
||||
self:F()
|
||||
|
||||
@@ -1117,6 +1399,8 @@ end
|
||||
-- @param #string Event
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
-- @param Wrapper.Unit#UNIT CargoCarrier
|
||||
-- @param #number Speed
|
||||
-- @param #number Distance
|
||||
-- @param #number Angle
|
||||
function CARGO_PACKAGE:onafterUnLoad( From, Event, To, CargoCarrier, Speed, Distance, Angle )
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
--- **Cargo** -- Management of single cargo crates, which are based on a @{Static} object.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### [Demo Missions]()
|
||||
--
|
||||
@@ -17,7 +13,8 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module CargoCrate
|
||||
-- @module Cargo.CargoCrate
|
||||
-- @image Cargo_Crates.JPG
|
||||
|
||||
do -- CARGO_CRATE
|
||||
|
||||
@@ -25,11 +22,21 @@ do -- CARGO_CRATE
|
||||
-- @type CARGO_CRATE
|
||||
-- @extends Cargo.Cargo#CARGO_REPRESENTABLE
|
||||
|
||||
--- # CARGO\_CRATE class, extends @{#CARGO_REPRESENTABLE}
|
||||
--
|
||||
-- The CARGO\_CRATE class 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.
|
||||
--
|
||||
-- The above cargo classes are used by the following AI_CARGO_ classes to allow AI groups to transport cargo:
|
||||
--
|
||||
-- * AI Armoured Personnel Carriers to transport cargo and engage in battles, using the @{AI.AI_Cargo_APC} module.
|
||||
-- * AI Helicopters to transport cargo, using the @{AI.AI_Cargo_Helicopter} module.
|
||||
-- * AI Planes to transport cargo, using the @{AI.AI_Cargo_Airplane} module.
|
||||
-- * AI Ships is planned.
|
||||
--
|
||||
-- The above cargo classes are also used by the TASK_CARGO_ classes to allow human players to transport cargo as part of a tasking:
|
||||
--
|
||||
-- * @{Tasking.Task_Cargo_Transport#TASK_CARGO_TRANSPORT} to transport cargo by human players.
|
||||
-- * @{Tasking.Task_Cargo_Transport#TASK_CARGO_CSAR} to transport downed pilots by human players.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @field #CARGO_CRATE
|
||||
@@ -56,9 +63,12 @@ do -- CARGO_CRATE
|
||||
|
||||
self:HandleEvent( EVENTS.Dead, self.OnEventCargoDead )
|
||||
self:HandleEvent( EVENTS.Crash, self.OnEventCargoDead )
|
||||
--self:HandleEvent( EVENTS.RemoveUnit, self.OnEventCargoDead )
|
||||
self:HandleEvent( EVENTS.PlayerLeaveUnit, self.OnEventCargoDead )
|
||||
|
||||
self:SetEventPriority( 4 )
|
||||
|
||||
self.NearRadius = NearRadius or 25
|
||||
|
||||
return self
|
||||
end
|
||||
@@ -146,7 +156,7 @@ do -- CARGO_CRATE
|
||||
if self.CargoObject then
|
||||
self:T("Destroying")
|
||||
self.NoDestroy = true
|
||||
self.CargoObject:Destroy()
|
||||
self.CargoObject:Destroy( false ) -- Do not generate a remove unit event, because we want to keep the template for later respawn in the database.
|
||||
--local Coordinate = self.CargoObject:GetCoordinate():GetRandomCoordinateInRadius( 50, 20 )
|
||||
--self.CargoObject:ReSpawnAt( Coordinate, 0 )
|
||||
end
|
||||
@@ -164,8 +174,14 @@ do -- CARGO_CRATE
|
||||
return false
|
||||
end
|
||||
|
||||
--- Check if the cargo can be sling loaded.
|
||||
-- @param #CARGO_CRATE self
|
||||
function CARGO_CRATE:CanSlingload()
|
||||
return false
|
||||
end
|
||||
|
||||
--- Check if Cargo Crate is in the radius for the Cargo to be reported.
|
||||
-- @param #CARGO self
|
||||
-- @param #CARGO_CRATE self
|
||||
-- @param Core.Point#COORDINATE Coordinate
|
||||
-- @return #boolean true if the Cargo Crate is within the report radius.
|
||||
function CARGO_CRATE:IsInReportRadius( Coordinate )
|
||||
@@ -185,7 +201,7 @@ do -- CARGO_CRATE
|
||||
|
||||
|
||||
--- Check if Cargo Crate is in the radius for the Cargo to be Boarded or Loaded.
|
||||
-- @param #CARGO self
|
||||
-- @param #CARGO_CRATE self
|
||||
-- @param Core.Point#Coordinate Coordinate
|
||||
-- @return #boolean true if the Cargo Crate is within the loading radius.
|
||||
function CARGO_CRATE:IsInLoadRadius( Coordinate )
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
--- **Cargo** -- Management of grouped cargo logistics, which are based on a @{Group} object.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- 
|
||||
--- **Cargo** -- Management of grouped cargo logistics, which are based on a @{Wrapper.Group} object.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
@@ -17,7 +13,8 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module CargoGroup
|
||||
-- @module Cargo.CargoGroup
|
||||
-- @image Cargo_Groups.JPG
|
||||
|
||||
|
||||
do -- CARGO_GROUP
|
||||
@@ -27,25 +24,21 @@ do -- CARGO_GROUP
|
||||
-- @field Core.Set#SET_CARGO CargoSet The collection of derived CARGO objects.
|
||||
-- @field #string GroupName The name of the CargoGroup.
|
||||
|
||||
--- # CARGO\_GROUP class
|
||||
--
|
||||
-- The CARGO\_GROUP class defines a cargo that is represented by a @{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 above cargo classes are used by the 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:
|
||||
--
|
||||
-- * AI Armoured Personnel Carriers to transport cargo and engage in battles, using the @{AI.AI_Cargo_APC#AI_CARGO_APC} class.
|
||||
-- * AI Helicopters to transport cargo, using the @{AI.AI_Cargo_Helicopter#AI_CARGO_HELICOPTER} class.
|
||||
-- * AI Planes to transport cargo, using the @{AI.AI_Cargo_Plane#AI_CARGO_PLANE} class.
|
||||
-- * AI Armoured Personnel Carriers to transport cargo and engage in battles, using the @{AI.AI_Cargo_APC} module.
|
||||
-- * AI Helicopters to transport cargo, using the @{AI.AI_Cargo_Helicopter} module.
|
||||
-- * AI Planes to transport cargo, using the @{AI.AI_Cargo_Airplane} module.
|
||||
-- * AI Ships is planned.
|
||||
--
|
||||
-- The above cargo classes are also used by the TASK\_CARGO\_ classes to allow human players to transport cargo as part of a tasking:
|
||||
-- The above cargo classes are also used by the TASK_CARGO_ classes to allow human players to transport cargo as part of a tasking:
|
||||
--
|
||||
-- * @{Tasking.Task_Cargo_Transport#TASK_CARGO_TRANSPORT} to transport cargo by human players.
|
||||
-- * @{Tasking.Task_Cargo_Transport#TASK_CARGO_CSAR} to transport downed pilots by human players.
|
||||
--
|
||||
-- The
|
||||
--
|
||||
-- @field #CARGO_GROUP CARGO_GROUP
|
||||
--
|
||||
CARGO_GROUP = {
|
||||
@@ -53,17 +46,17 @@ do -- CARGO_GROUP
|
||||
}
|
||||
|
||||
--- CARGO_GROUP constructor.
|
||||
-- This make a new CARGO_GROUP from a @{Group} object.
|
||||
-- This make a new CARGO_GROUP from a @{Wrapper.Group} object.
|
||||
-- It will "ungroup" the group object within the sim, and will create a @{Set} of individual Unit objects.
|
||||
-- @param #CARGO_GROUP self
|
||||
-- @param Wrapper.Group#GROUP CargoGroup
|
||||
-- @param #string Type
|
||||
-- @param #string Name
|
||||
-- @param #number LoadRadius (optional)
|
||||
-- @param #number NearRadius (optional)
|
||||
-- @return #CARGO_GROUP
|
||||
function CARGO_GROUP:New( CargoGroup, Type, Name, LoadRadius )
|
||||
local self = BASE:Inherit( self, CARGO_REPORTABLE:New( Type, Name, 0, LoadRadius ) ) -- #CARGO_GROUP
|
||||
-- @param Wrapper.Group#GROUP CargoGroup Group to be transported as cargo.
|
||||
-- @param #string Type Cargo type, e.g. "Infantry". This is the type used in SET_CARGO:New():FilterTypes("Infantry") to define the valid cargo groups of the set.
|
||||
-- @param #string Name A user defined name of the cargo group. This name CAN be the same as the group object but can also have a different name. This name MUST be unique!
|
||||
-- @param #number LoadRadius (optional) Distance in meters until which a cargo is loaded into the carrier. Cargo outside this radius has to be routed by other means to within the radius to be loaded.
|
||||
-- @param #number NearRadius (optional) Once the units are within this radius of the carrier, they are actually loaded, i.e. disappear from the scene.
|
||||
-- @return #CARGO_GROUP Cargo group object.
|
||||
function CARGO_GROUP:New( CargoGroup, Type, Name, LoadRadius, NearRadius )
|
||||
local self = BASE:Inherit( self, CARGO_REPORTABLE:New( Type, Name, 0, LoadRadius, NearRadius ) ) -- #CARGO_GROUP
|
||||
self:F( { Type, Name, LoadRadius } )
|
||||
|
||||
self.CargoSet = SET_CARGO:New()
|
||||
@@ -71,46 +64,57 @@ do -- CARGO_GROUP
|
||||
self.Grouped = true
|
||||
self.CargoUnitTemplate = {}
|
||||
|
||||
self.NearRadius = NearRadius
|
||||
|
||||
self:SetDeployed( false )
|
||||
|
||||
local WeightGroup = 0
|
||||
local VolumeGroup = 0
|
||||
|
||||
self.CargoGroup:Destroy()
|
||||
self.CargoGroup:Destroy() -- destroy and generate a unit removal event, so that the database gets cleaned, and the linked sets get properly cleaned.
|
||||
|
||||
local GroupName = CargoGroup:GetName()
|
||||
self.CargoName = GroupName:match("(.*)~CARGO") or GroupName
|
||||
self.CargoName = Name
|
||||
self.CargoTemplate = UTILS.DeepCopy( _DATABASE:GetGroupTemplate( GroupName ) )
|
||||
|
||||
local GroupTemplate = UTILS.DeepCopy( self.CargoTemplate )
|
||||
GroupTemplate.name = self.CargoName .. "#CARGO"
|
||||
GroupTemplate.groupId = nil
|
||||
self.GroupTemplate = UTILS.DeepCopy( self.CargoTemplate )
|
||||
self.GroupTemplate.name = self.CargoName .. "#CARGO"
|
||||
self.GroupTemplate.groupId = nil
|
||||
|
||||
GroupTemplate.units = {}
|
||||
self.GroupTemplate.units = {}
|
||||
|
||||
for UnitID, UnitTemplate in pairs( self.CargoTemplate.units ) do
|
||||
UnitTemplate.name = UnitTemplate.name .. "#CARGO"
|
||||
local CargoUnitName = UnitTemplate.name
|
||||
local CargoUnitName = UnitTemplate.name
|
||||
self.CargoUnitTemplate[CargoUnitName] = UnitTemplate
|
||||
|
||||
GroupTemplate.units[#GroupTemplate.units+1] = self.CargoUnitTemplate[CargoUnitName]
|
||||
GroupTemplate.units[#GroupTemplate.units].unitId = nil
|
||||
self.GroupTemplate.units[#self.GroupTemplate.units+1] = self.CargoUnitTemplate[CargoUnitName]
|
||||
self.GroupTemplate.units[#self.GroupTemplate.units].unitId = nil
|
||||
|
||||
-- And we register the spawned unit as part of the CargoSet.
|
||||
local Unit = UNIT:Register( CargoUnitName )
|
||||
--local WeightUnit = Unit:GetDesc().massEmpty
|
||||
--WeightGroup = WeightGroup + WeightUnit
|
||||
local CargoUnit = CARGO_UNIT:New( Unit, Type, CargoUnitName, 10 )
|
||||
self.CargoSet:Add( CargoUnitName, CargoUnit )
|
||||
|
||||
end
|
||||
|
||||
-- Then we register the new group in the database
|
||||
self.CargoGroup = GROUP:NewTemplate( GroupTemplate, GroupTemplate.CoalitionID, GroupTemplate.CategoryID, GroupTemplate.CountryID)
|
||||
self.CargoGroup = GROUP:NewTemplate( self.GroupTemplate, self.GroupTemplate.CoalitionID, self.GroupTemplate.CategoryID, self.GroupTemplate.CountryID )
|
||||
|
||||
-- Now we spawn the new group based on the template created.
|
||||
_DATABASE:Spawn( GroupTemplate )
|
||||
self.CargoObject = _DATABASE:Spawn( self.GroupTemplate )
|
||||
|
||||
for CargoUnitID, CargoUnit in pairs( self.CargoObject:GetUnits() ) do
|
||||
|
||||
|
||||
local CargoUnitName = CargoUnit:GetName()
|
||||
|
||||
local Cargo = CARGO_UNIT:New( CargoUnit, Type, CargoUnitName, LoadRadius, NearRadius )
|
||||
self.CargoSet:Add( CargoUnitName, Cargo )
|
||||
|
||||
WeightGroup = WeightGroup + Cargo:GetWeight()
|
||||
|
||||
end
|
||||
|
||||
self:SetWeight( WeightGroup )
|
||||
self.CargoLimit = 10
|
||||
|
||||
self:T( { "Weight Cargo", WeightGroup } )
|
||||
|
||||
@@ -119,6 +123,7 @@ do -- CARGO_GROUP
|
||||
|
||||
self:HandleEvent( EVENTS.Dead, self.OnEventCargoDead )
|
||||
self:HandleEvent( EVENTS.Crash, self.OnEventCargoDead )
|
||||
--self:HandleEvent( EVENTS.RemoveUnit, self.OnEventCargoDead )
|
||||
self:HandleEvent( EVENTS.PlayerLeaveUnit, self.OnEventCargoDead )
|
||||
|
||||
self:SetEventPriority( 4 )
|
||||
@@ -126,6 +131,35 @@ do -- CARGO_GROUP
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Respawn the CargoGroup.
|
||||
-- @param #CARGO_GROUP self
|
||||
function CARGO_GROUP:Respawn()
|
||||
|
||||
self:F( { "Respawning" } )
|
||||
|
||||
for CargoID, CargoData in pairs( self.CargoSet:GetSet() ) do
|
||||
local Cargo = CargoData -- Cargo.Cargo#CARGO
|
||||
Cargo:Destroy() -- Destroy the cargo and generate a remove unit event to update the sets.
|
||||
Cargo:SetStartState( "UnLoaded" )
|
||||
end
|
||||
|
||||
-- Now we spawn the new group based on the template created.
|
||||
_DATABASE:Spawn( self.GroupTemplate )
|
||||
|
||||
for CargoUnitID, CargoUnit in pairs( self.CargoObject:GetUnits() ) do
|
||||
|
||||
local CargoUnitName = CargoUnit:GetName()
|
||||
|
||||
local Cargo = CARGO_UNIT:New( CargoUnit, self.Type, CargoUnitName, self.LoadRadius )
|
||||
self.CargoSet:Add( CargoUnitName, Cargo )
|
||||
|
||||
end
|
||||
|
||||
self:SetDeployed( false )
|
||||
self:SetStartState( "UnLoaded" )
|
||||
|
||||
end
|
||||
|
||||
--- Ungroup the cargo group into individual groups with one unit.
|
||||
-- This is required because by default a group will move in formation and this is really an issue for group control.
|
||||
@@ -169,7 +203,10 @@ do -- CARGO_GROUP
|
||||
_DATABASE:Spawn( GroupTemplate )
|
||||
end
|
||||
end
|
||||
|
||||
self.CargoObject = nil
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
@@ -209,12 +246,12 @@ do -- CARGO_GROUP
|
||||
end
|
||||
|
||||
-- Then we register the new group in the database
|
||||
self.CargoGroup = GROUP:NewTemplate( GroupTemplate, GroupTemplate.CoalitionID, GroupTemplate.CategoryID, GroupTemplate.CountryID)
|
||||
self.CargoGroup = GROUP:NewTemplate( GroupTemplate, GroupTemplate.CoalitionID, GroupTemplate.CategoryID, GroupTemplate.CountryID )
|
||||
|
||||
self:F( { "Regroup", GroupTemplate } )
|
||||
|
||||
-- Now we spawn the new group based on the template created.
|
||||
_DATABASE:Spawn( GroupTemplate )
|
||||
self.CargoObject = _DATABASE:Spawn( GroupTemplate )
|
||||
end
|
||||
|
||||
end
|
||||
@@ -223,14 +260,15 @@ do -- CARGO_GROUP
|
||||
--- @param #CARGO_GROUP self
|
||||
-- @param Core.Event#EVENTDATA EventData
|
||||
function CARGO_GROUP:OnEventCargoDead( EventData )
|
||||
self:I( EventData )
|
||||
|
||||
self:E(EventData)
|
||||
|
||||
local Destroyed = false
|
||||
|
||||
if self:IsDestroyed() or self:IsUnLoaded() or self:IsBoarding() or self:IsUnboarding() then
|
||||
Destroyed = true
|
||||
for CargoID, CargoData in pairs( self.CargoSet:GetSet() ) do
|
||||
local Cargo = CargoData -- #CARGO
|
||||
local Cargo = CargoData -- Cargo.Cargo#CARGO
|
||||
if Cargo:IsAlive() then
|
||||
Destroyed = false
|
||||
else
|
||||
@@ -255,14 +293,15 @@ do -- CARGO_GROUP
|
||||
|
||||
--- Enter Boarding State.
|
||||
-- @param #CARGO_GROUP self
|
||||
-- @param Wrapper.Unit#UNIT CargoCarrier
|
||||
-- @param #string Event
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
-- @param Wrapper.Unit#UNIT CargoCarrier
|
||||
-- @param #number NearRadius If distance is smaller than this number, cargo is loaded into the carrier.
|
||||
function CARGO_GROUP:onenterBoarding( From, Event, To, CargoCarrier, NearRadius, ... )
|
||||
--self:F( { CargoCarrier.UnitName, From, Event, To } )
|
||||
self:F( { CargoCarrier.UnitName, From, Event, To, NearRadius = NearRadius } )
|
||||
|
||||
local NearRadius = NearRadius or 25
|
||||
NearRadius = NearRadius or self.NearRadius
|
||||
|
||||
if From == "UnLoaded" then
|
||||
|
||||
@@ -301,16 +340,15 @@ do -- CARGO_GROUP
|
||||
end
|
||||
|
||||
--- Leave Boarding State.
|
||||
-- @param #CARGO_GROUP self
|
||||
-- @param Wrapper.Unit#UNIT CargoCarrier
|
||||
-- @param #CARGO_GROUP self
|
||||
-- @param #string Event
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
-- @param Wrapper.Unit#UNIT CargoCarrier
|
||||
-- @param #number NearRadius If distance is smaller than this number, cargo is loaded into the carrier.
|
||||
function CARGO_GROUP:onafterBoarding( From, Event, To, CargoCarrier, NearRadius, ... )
|
||||
--self:F( { CargoCarrier.UnitName, From, Event, To } )
|
||||
|
||||
local NearRadius = NearRadius or 100
|
||||
|
||||
local Boarded = true
|
||||
local Cancelled = false
|
||||
local Dead = true
|
||||
@@ -319,7 +357,7 @@ do -- CARGO_GROUP
|
||||
|
||||
-- For each Cargo object within the CARGO_GROUP, route each object to the CargoLoadPointVec2
|
||||
for CargoID, Cargo in pairs( self.CargoSet:GetSet() ) do
|
||||
self:T( { Cargo:GetName(), Cargo.current } )
|
||||
--self:T( { Cargo:GetName(), Cargo.current } )
|
||||
|
||||
|
||||
if not Cargo:is( "Loaded" )
|
||||
@@ -341,7 +379,7 @@ do -- CARGO_GROUP
|
||||
|
||||
if not Cancelled then
|
||||
if not Boarded then
|
||||
self:__Boarding( 1, CargoCarrier, NearRadius, ... )
|
||||
self:__Boarding( -5, CargoCarrier, NearRadius, ... )
|
||||
else
|
||||
self:F("Group Cargo is loaded")
|
||||
self:__Load( 1, CargoCarrier, ... )
|
||||
@@ -357,12 +395,13 @@ do -- CARGO_GROUP
|
||||
|
||||
--- Enter UnBoarding State.
|
||||
-- @param #CARGO_GROUP self
|
||||
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
||||
-- @param #string Event
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
||||
-- @param #number NearRadius If distance is smaller than this number, cargo is loaded into the carrier.
|
||||
function CARGO_GROUP:onenterUnBoarding( From, Event, To, ToPointVec2, NearRadius, ... )
|
||||
--self:F( {From, Event, To, ToPointVec2, NearRadius } )
|
||||
self:F( {From, Event, To, ToPointVec2, NearRadius } )
|
||||
|
||||
NearRadius = NearRadius or 25
|
||||
|
||||
@@ -379,8 +418,14 @@ do -- CARGO_GROUP
|
||||
--- @param Cargo.Cargo#CARGO Cargo
|
||||
function( Cargo, NearRadius )
|
||||
if not Cargo:IsDestroyed() then
|
||||
Cargo:__UnBoard( Timer, ToPointVec2, NearRadius )
|
||||
Timer = Timer + 3
|
||||
local ToVec=nil
|
||||
if ToPointVec2==nil then
|
||||
ToVec=self.CargoCarrier:GetPointVec2():GetRandomPointVec2InRadius(2*NearRadius, NearRadius)
|
||||
else
|
||||
ToVec=ToPointVec2
|
||||
end
|
||||
Cargo:__UnBoard( Timer, ToVec, NearRadius )
|
||||
Timer = Timer + 1
|
||||
end
|
||||
end, { NearRadius }
|
||||
)
|
||||
@@ -393,10 +438,11 @@ do -- CARGO_GROUP
|
||||
|
||||
--- Leave UnBoarding State.
|
||||
-- @param #CARGO_GROUP self
|
||||
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
||||
-- @param #string Event
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
||||
-- @param #number NearRadius If distance is smaller than this number, cargo is loaded into the carrier.
|
||||
function CARGO_GROUP:onleaveUnBoarding( From, Event, To, ToPointVec2, NearRadius, ... )
|
||||
--self:F( { From, Event, To, ToPointVec2, NearRadius } )
|
||||
|
||||
@@ -430,10 +476,11 @@ do -- CARGO_GROUP
|
||||
|
||||
--- UnBoard Event.
|
||||
-- @param #CARGO_GROUP self
|
||||
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
||||
-- @param #string Event
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
||||
-- @param #number NearRadius If distance is smaller than this number, cargo is loaded into the carrier.
|
||||
function CARGO_GROUP:onafterUnBoarding( From, Event, To, ToPointVec2, NearRadius, ... )
|
||||
--self:F( { From, Event, To, ToPointVec2, NearRadius } )
|
||||
|
||||
@@ -446,10 +493,10 @@ do -- CARGO_GROUP
|
||||
|
||||
--- Enter UnLoaded State.
|
||||
-- @param #CARGO_GROUP self
|
||||
-- @param Core.Point#POINT_VEC2
|
||||
-- @param #string Event
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
-- @param Core.Point#POINT_VEC2
|
||||
function CARGO_GROUP:onenterUnLoaded( From, Event, To, ToPointVec2, ... )
|
||||
--self:F( { From, Event, To, ToPointVec2 } )
|
||||
|
||||
@@ -459,7 +506,7 @@ do -- CARGO_GROUP
|
||||
self.CargoSet:ForEach(
|
||||
function( Cargo )
|
||||
--Cargo:UnLoad( ToPointVec2 )
|
||||
local RandomVec2=ToPointVec2:GetRandomPointVec2InRadius(10)
|
||||
local RandomVec2=ToPointVec2:GetRandomPointVec2InRadius(20, 10)
|
||||
Cargo:UnLoad( RandomVec2 )
|
||||
end
|
||||
)
|
||||
@@ -477,8 +524,6 @@ do -- CARGO_GROUP
|
||||
-- @return Core.Point#COORDINATE The current Coordinate of the first Cargo of the CargoGroup.
|
||||
-- @return #nil There is no valid Cargo in the CargoGroup.
|
||||
function CARGO_GROUP:GetCoordinate()
|
||||
self:F()
|
||||
|
||||
local Cargo = self:GetFirstAlive() -- Cargo.Cargo#CARGO
|
||||
|
||||
if Cargo then
|
||||
@@ -584,8 +629,7 @@ do -- CARGO_GROUP
|
||||
-- @param #CARGO_GROUP self
|
||||
-- @param Wrapper.Group#GROUP CargoCarrier
|
||||
-- @param #number NearRadius
|
||||
-- @return #boolean The Cargo is near to the Carrier.
|
||||
-- @return #nil The Cargo is not near to the Carrier.
|
||||
-- @return #boolean The Cargo is near to the Carrier or #nil if the Cargo is not near to the Carrier.
|
||||
function CARGO_GROUP:IsNear( CargoCarrier, NearRadius )
|
||||
self:F( {NearRadius = NearRadius } )
|
||||
|
||||
@@ -613,10 +657,18 @@ do -- CARGO_GROUP
|
||||
|
||||
if Cargo then
|
||||
local Distance = 0
|
||||
local CargoCoordinate
|
||||
if Cargo:IsLoaded() then
|
||||
Distance = Coordinate:Get2DDistance( Cargo.CargoCarrier:GetCoordinate() )
|
||||
CargoCoordinate = Cargo.CargoCarrier:GetCoordinate()
|
||||
else
|
||||
Distance = Coordinate:Get2DDistance( Cargo.CargoObject:GetCoordinate() )
|
||||
CargoCoordinate = Cargo.CargoObject:GetCoordinate()
|
||||
end
|
||||
|
||||
-- FF check if coordinate could be obtained. This was commented out for some (unknown) reason. But the check seems valid!
|
||||
if CargoCoordinate then
|
||||
Distance = Coordinate:Get2DDistance( CargoCoordinate )
|
||||
else
|
||||
return false
|
||||
end
|
||||
|
||||
self:F( { Distance = Distance, LoadRadius = self.LoadRadius } )
|
||||
@@ -657,60 +709,13 @@ do -- CARGO_GROUP
|
||||
|
||||
end
|
||||
|
||||
--- Respawn the CargoGroup.
|
||||
-- @param #CARGO_GROUP self
|
||||
function CARGO_GROUP:Respawn()
|
||||
|
||||
self:F( { "Respawning" } )
|
||||
|
||||
for CargoID, CargoData in pairs( self.CargoSet:GetSet() ) do
|
||||
local Cargo = CargoData -- #CARGO
|
||||
Cargo:Destroy()
|
||||
Cargo:SetStartState( "UnLoaded" )
|
||||
end
|
||||
|
||||
|
||||
-- We iterate through the group template and for each unit in the template, we create a new group with one unit.
|
||||
for UnitID, UnitTemplate in pairs( self.CargoTemplate.units ) do
|
||||
|
||||
local GroupTemplate = UTILS.DeepCopy( self.CargoTemplate )
|
||||
local GroupName = env.getValueDictByKey( GroupTemplate.name )
|
||||
|
||||
-- We create a new group object with one unit...
|
||||
-- First we prepare the template...
|
||||
GroupTemplate.name = GroupName .. "#CARGO#" .. UnitID
|
||||
GroupTemplate.groupId = nil
|
||||
GroupTemplate.units = {}
|
||||
GroupTemplate.units[1] = UnitTemplate
|
||||
local UnitName = UnitTemplate.name .. "#CARGO"
|
||||
GroupTemplate.units[1].name = UnitTemplate.name .. "#CARGO"
|
||||
|
||||
|
||||
-- Then we register the new group in the database
|
||||
local CargoGroup = GROUP:NewTemplate( GroupTemplate, GroupTemplate.CoalitionID, GroupTemplate.CategoryID, GroupTemplate.CountryID)
|
||||
|
||||
-- Now we spawn the new group based on the template created.
|
||||
_DATABASE:Spawn( GroupTemplate )
|
||||
|
||||
-- And we register the spawned unit as part of the CargoSet.
|
||||
local Unit = UNIT:FindByName( UnitName )
|
||||
--local WeightUnit = Unit:GetDesc().massEmpty
|
||||
--WeightGroup = WeightGroup + WeightUnit
|
||||
local CargoUnit = CARGO_UNIT:New( Unit, Type, UnitName, 10 )
|
||||
self.CargoSet:Add( UnitName, CargoUnit )
|
||||
end
|
||||
|
||||
self:SetDeployed( false )
|
||||
self:SetStartState( "UnLoaded" )
|
||||
|
||||
end
|
||||
|
||||
--- Signal a flare at the position of the CargoGroup.
|
||||
-- @param #CARGO_GROUP self
|
||||
-- @param Utilities.Utils#FLARECOLOR FlareColor
|
||||
function CARGO_GROUP:Flare( FlareColor )
|
||||
|
||||
local Cargo = self.CargoSet:GetFirst() -- #CARGO
|
||||
local Cargo = self.CargoSet:GetFirst() -- Cargo.Cargo#CARGO
|
||||
if Cargo then
|
||||
Cargo:Flare( FlareColor )
|
||||
end
|
||||
@@ -722,7 +727,7 @@ do -- CARGO_GROUP
|
||||
-- @param #number Radius The radius of randomization around the center of the first element of the CargoGroup.
|
||||
function CARGO_GROUP:Smoke( SmokeColor, Radius )
|
||||
|
||||
local Cargo = self.CargoSet:GetFirst() -- #CARGO
|
||||
local Cargo = self.CargoSet:GetFirst() -- Cargo.Cargo#CARGO
|
||||
|
||||
if Cargo then
|
||||
Cargo:Smoke( SmokeColor, Radius )
|
||||
@@ -730,14 +735,14 @@ do -- CARGO_GROUP
|
||||
end
|
||||
|
||||
--- Check if the first element of the CargoGroup is the given @{Zone}.
|
||||
-- @param #CARGO self
|
||||
-- @param #CARGO_GROUP self
|
||||
-- @param Core.Zone#ZONE_BASE Zone
|
||||
-- @return #boolean **true** if the first element of the CargoGroup is in the Zone
|
||||
-- @return #boolean **false** if there is no element of the CargoGroup in the Zone.
|
||||
function CARGO_GROUP:IsInZone( Zone )
|
||||
--self:F( { Zone } )
|
||||
|
||||
local Cargo = self.CargoSet:GetFirst() -- #CARGO
|
||||
local Cargo = self.CargoSet:GetFirst() -- Cargo.Cargo#CARGO
|
||||
|
||||
if Cargo then
|
||||
return Cargo:IsInZone( Zone )
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
--- **Cargo** -- Management of single cargo crates, which are based on a @{Static} object. The cargo can only be slingloaded.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### [Demo Missions]()
|
||||
--
|
||||
@@ -17,7 +13,8 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module CargoCrate
|
||||
-- @module Cargo.CargoSlingload
|
||||
-- @image Cargo_Slingload.JPG
|
||||
|
||||
|
||||
do -- CARGO_SLINGLOAD
|
||||
@@ -26,9 +23,12 @@ do -- CARGO_SLINGLOAD
|
||||
-- @type CARGO_SLINGLOAD
|
||||
-- @extends Cargo.Cargo#CARGO_REPRESENTABLE
|
||||
|
||||
--- # CARGO\_CRATE class, extends @{#CARGO_REPRESENTABLE}
|
||||
--- Defines a cargo that is represented by a UNIT object within the simulator, and can be transported by a carrier.
|
||||
--
|
||||
-- The CARGO\_CRATE class defines a cargo that is represented by a UNIT object within the simulator, and can be transported by a carrier.
|
||||
-- The above cargo classes are also used by the TASK_CARGO_ classes to allow human players to transport cargo as part of a tasking:
|
||||
--
|
||||
-- * @{Tasking.Task_Cargo_Transport#TASK_CARGO_TRANSPORT} to transport cargo by human players.
|
||||
-- * @{Tasking.Task_Cargo_Transport#TASK_CARGO_CSAR} to transport downed pilots by human players.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
@@ -56,9 +56,12 @@ do -- CARGO_SLINGLOAD
|
||||
|
||||
self:HandleEvent( EVENTS.Dead, self.OnEventCargoDead )
|
||||
self:HandleEvent( EVENTS.Crash, self.OnEventCargoDead )
|
||||
--self:HandleEvent( EVENTS.RemoveUnit, self.OnEventCargoDead )
|
||||
self:HandleEvent( EVENTS.PlayerLeaveUnit, self.OnEventCargoDead )
|
||||
|
||||
self:SetEventPriority( 4 )
|
||||
|
||||
self.NearRadius = NearRadius or 25
|
||||
|
||||
return self
|
||||
end
|
||||
@@ -87,8 +90,8 @@ do -- CARGO_SLINGLOAD
|
||||
|
||||
|
||||
--- Check if the cargo can be Slingloaded.
|
||||
-- @param #CARGO self
|
||||
function CARGO:CanSlingload()
|
||||
-- @param #CARGO_SLINGLOAD self
|
||||
function CARGO_SLINGLOAD:CanSlingload()
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
--- **Cargo** -- Management of single cargo logistics, which are based on a @{Unit} object.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- 
|
||||
--- **Cargo** -- Management of single cargo logistics, which are based on a @{Wrapper.Unit} object.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
@@ -17,7 +13,8 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module CargoUnit
|
||||
-- @module Cargo.CargoUnit
|
||||
-- @image Cargo_Units.JPG
|
||||
|
||||
do -- CARGO_UNIT
|
||||
|
||||
@@ -25,10 +22,11 @@ do -- CARGO_UNIT
|
||||
-- @type CARGO_UNIT
|
||||
-- @extends Cargo.Cargo#CARGO_REPRESENTABLE
|
||||
|
||||
--- # CARGO\_UNIT class, extends @{#CARGO_REPRESENTABLE}
|
||||
--- 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_UNIT objects to and from carriers.
|
||||
-- Note that ground forces behave in a group, and thus, act in formation, regardless if one unit is commanded to move.
|
||||
--
|
||||
-- The CARGO\_UNIT class 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\_UNIT objects to and from carriers.
|
||||
-- This class is used in CARGO_GROUP, and is not meant to be used by mission designers individually.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
@@ -47,9 +45,9 @@ do -- CARGO_UNIT
|
||||
-- @param #number LoadRadius (optional)
|
||||
-- @param #number NearRadius (optional)
|
||||
-- @return #CARGO_UNIT
|
||||
function CARGO_UNIT:New( CargoUnit, Type, Name, Weight, NearRadius )
|
||||
local self = BASE:Inherit( self, CARGO_REPRESENTABLE:New( CargoUnit, Type, Name, Weight, NearRadius ) ) -- #CARGO_UNIT
|
||||
self:I( { Type, Name, Weight, NearRadius } )
|
||||
function CARGO_UNIT:New( CargoUnit, Type, Name, LoadRadius, NearRadius )
|
||||
local self = BASE:Inherit( self, CARGO_REPRESENTABLE:New( CargoUnit, Type, Name, LoadRadius, NearRadius ) ) -- #CARGO_UNIT
|
||||
self:I( { Type, Name, LoadRadius, NearRadius } )
|
||||
|
||||
self:T( CargoUnit )
|
||||
self.CargoObject = CargoUnit
|
||||
@@ -67,11 +65,10 @@ do -- CARGO_UNIT
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
||||
-- @param #number NearRadius (optional) Defaut 25 m.
|
||||
function CARGO_UNIT:onenterUnBoarding( From, Event, To, ToPointVec2, NearRadius )
|
||||
self:F( { From, Event, To, ToPointVec2, NearRadius } )
|
||||
|
||||
NearRadius = NearRadius or 25
|
||||
|
||||
local Angle = 180
|
||||
local Speed = 60
|
||||
local DeployDistance = 9
|
||||
@@ -136,11 +133,10 @@ do -- CARGO_UNIT
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
||||
-- @param #number NearRadius (optional) Defaut 100 m.
|
||||
function CARGO_UNIT:onleaveUnBoarding( From, Event, To, ToPointVec2, NearRadius )
|
||||
self:F( { From, Event, To, ToPointVec2, NearRadius } )
|
||||
|
||||
NearRadius = NearRadius or 100
|
||||
|
||||
local Angle = 180
|
||||
local Speed = 10
|
||||
local Distance = 5
|
||||
@@ -163,11 +159,10 @@ do -- CARGO_UNIT
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
||||
-- @param #number NearRadius (optional) Defaut 100 m.
|
||||
function CARGO_UNIT:onafterUnBoarding( From, Event, To, ToPointVec2, NearRadius )
|
||||
self:F( { From, Event, To, ToPointVec2, NearRadius } )
|
||||
|
||||
NearRadius = NearRadius or 100
|
||||
|
||||
self.CargoInAir = self.CargoObject:InAir()
|
||||
|
||||
self:T( self.CargoInAir )
|
||||
@@ -225,11 +220,11 @@ do -- CARGO_UNIT
|
||||
-- @param #string Event
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
-- @param Wrapper.Group#GROUP CargoCarrier
|
||||
-- @param #number NearRadius
|
||||
function CARGO_UNIT:onafterBoard( From, Event, To, CargoCarrier, NearRadius, ... )
|
||||
self:F( { From, Event, To, CargoCarrier, NearRadius } )
|
||||
self:F( { From, Event, To, CargoCarrier, NearRadius = NearRadius } )
|
||||
|
||||
local NearRadius = NearRadius or 25
|
||||
|
||||
self.CargoInAir = self.CargoObject:InAir()
|
||||
|
||||
local Desc = self.CargoObject:GetDesc()
|
||||
@@ -241,6 +236,9 @@ do -- CARGO_UNIT
|
||||
-- Only move the group to the carrier when the cargo is not in the air
|
||||
-- (eg. cargo can be on a oil derrick, moving the cargo on the oil derrick will drop the cargo on the sea).
|
||||
if not self.CargoInAir then
|
||||
-- If NearRadius is given, then use the given NearRadius, otherwise calculate the NearRadius
|
||||
-- based upon the Carrier bounding radius, which is calculated from the bounding rectangle on the Y axis.
|
||||
local NearRadius = NearRadius or CargoCarrier:GetBoundingRadius() + 5
|
||||
if self:IsNear( CargoCarrier:GetPointVec2(), NearRadius ) then
|
||||
self:Load( CargoCarrier, NearRadius, ... )
|
||||
else
|
||||
@@ -250,10 +248,8 @@ do -- CARGO_UNIT
|
||||
|
||||
local Speed = 90
|
||||
local Angle = 180
|
||||
local Distance = 5
|
||||
local Distance = 0
|
||||
|
||||
NearRadius = NearRadius or 25
|
||||
|
||||
local CargoCarrierPointVec2 = CargoCarrier:GetPointVec2()
|
||||
local CargoCarrierHeading = CargoCarrier:GetHeading() -- Get Heading of object in degrees.
|
||||
local CargoDeployHeading = ( ( CargoCarrierHeading + Angle ) >= 360 ) and ( CargoCarrierHeading + Angle - 360 ) or ( CargoCarrierHeading + Angle )
|
||||
@@ -271,7 +267,7 @@ do -- CARGO_UNIT
|
||||
|
||||
local TaskRoute = self.CargoObject:TaskRoute( Points )
|
||||
self.CargoObject:SetTask( TaskRoute, 2 )
|
||||
self:__Boarding( -1, CargoCarrier, NearRadius )
|
||||
self:__Boarding( -5, CargoCarrier, NearRadius, ... )
|
||||
self.RunCount = 0
|
||||
end
|
||||
end
|
||||
@@ -286,26 +282,30 @@ do -- CARGO_UNIT
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
-- @param Wrapper.Client#CLIENT CargoCarrier
|
||||
-- @param #number NearRadius
|
||||
-- @param #number NearRadius Default 25 m.
|
||||
function CARGO_UNIT:onafterBoarding( From, Event, To, CargoCarrier, NearRadius, ... )
|
||||
--self:F( { From, Event, To, CargoCarrier.UnitName, NearRadius } )
|
||||
self:F( { From, Event, To, CargoCarrier:GetName(), NearRadius = NearRadius } )
|
||||
|
||||
|
||||
if CargoCarrier and CargoCarrier:IsAlive() and self.CargoObject and self.CargoObject:IsAlive() then
|
||||
if CargoCarrier:InAir() == false then
|
||||
if (CargoCarrier:IsAir() and not CargoCarrier:InAir()) or true then
|
||||
local NearRadius = NearRadius or CargoCarrier:GetBoundingRadius( NearRadius ) + 5
|
||||
if self:IsNear( CargoCarrier:GetPointVec2(), NearRadius ) then
|
||||
self:__Load( 1, CargoCarrier, ... )
|
||||
else
|
||||
self:__Boarding( -1, CargoCarrier, NearRadius, ... )
|
||||
self.RunCount = self.RunCount + 1
|
||||
if self:IsNear( CargoCarrier:GetPointVec2(), 20 ) then
|
||||
self:__Boarding( -1, CargoCarrier, NearRadius, ... )
|
||||
self.RunCount = self.RunCount + 1
|
||||
else
|
||||
self:__Boarding( -2, CargoCarrier, NearRadius, ... )
|
||||
self.RunCount = self.RunCount + 2
|
||||
end
|
||||
if self.RunCount >= 40 then
|
||||
self.RunCount = 0
|
||||
local Speed = 90
|
||||
local Angle = 180
|
||||
local Distance = 5
|
||||
local Distance = 0
|
||||
|
||||
NearRadius = NearRadius or 25
|
||||
|
||||
local CargoCarrierPointVec2 = CargoCarrier:GetPointVec2()
|
||||
local CargoCarrierHeading = CargoCarrier:GetHeading() -- Get Heading of object in degrees.
|
||||
local CargoDeployHeading = ( ( CargoCarrierHeading + Angle ) >= 360 ) and ( CargoCarrierHeading + Angle - 360 ) or ( CargoCarrierHeading + Angle )
|
||||
@@ -343,6 +343,7 @@ do -- CARGO_UNIT
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
-- @param Wrapper.Unit#UNIT CargoCarrier
|
||||
-- @param #number NearRadius Default 25 m.
|
||||
function CARGO_UNIT:onenterBoarding( From, Event, To, CargoCarrier, NearRadius, ... )
|
||||
--self:F( { From, Event, To, CargoCarrier.UnitName, NearRadius } )
|
||||
|
||||
@@ -350,8 +351,6 @@ do -- CARGO_UNIT
|
||||
local Angle = 180
|
||||
local Distance = 5
|
||||
|
||||
local NearRadius = NearRadius or 25
|
||||
|
||||
if From == "UnLoaded" or From == "Boarding" then
|
||||
|
||||
end
|
||||
|
||||
@@ -1,6 +1,20 @@
|
||||
--- **Core** -- BASE forms **the basis of the MOOSE framework**. Each class within the MOOSE framework derives from BASE.
|
||||
--- **Core** - The base class within the framework.
|
||||
--
|
||||
-- 
|
||||
-- ===
|
||||
--
|
||||
-- ## Features:
|
||||
--
|
||||
-- * The construction and inheritance of MOOSE classes.
|
||||
-- * The class naming and numbering system.
|
||||
-- * The class hierarchy search system.
|
||||
-- * The tracing of information or objects during mission execution for debuggin purposes.
|
||||
-- * The subscription to DCS events for event handling in MOOSE objects.
|
||||
-- * Object inspection.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- All classes within the MOOSE framework are derived from the BASE class.
|
||||
-- Note: The BASE class is an abstract class and is not meant to be used directly.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
@@ -9,7 +23,8 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module Base
|
||||
-- @module Core.Base
|
||||
-- @image Core_Base.JPG
|
||||
|
||||
|
||||
|
||||
@@ -26,26 +41,14 @@ local _ClassID = 0
|
||||
-- @field ClassID The ID number of the class.
|
||||
-- @field ClassNameAndID The name of the class concatenated with the ID number of the class.
|
||||
|
||||
--- # 1) #BASE class
|
||||
--- BASE class
|
||||
--
|
||||
-- # 1. BASE constructor.
|
||||
--
|
||||
-- All classes within the MOOSE framework are derived from the BASE class.
|
||||
--
|
||||
-- BASE provides facilities for :
|
||||
-- Any class derived from BASE, will use the @{Core.Base#BASE.New} constructor embedded in the @{Core.Base#BASE.Inherit} method.
|
||||
-- See an example at the @{Core.Base#BASE.New} method how this is done.
|
||||
--
|
||||
-- * The construction and inheritance of MOOSE classes.
|
||||
-- * The class naming and numbering system.
|
||||
-- * The class hierarchy search system.
|
||||
-- * The tracing of information or objects during mission execution for debuggin purposes.
|
||||
-- * The subscription to DCS events for event handling in MOOSE objects.
|
||||
--
|
||||
-- Note: The BASE class is an abstract class and is not meant to be used directly.
|
||||
--
|
||||
-- ## 1.1) BASE constructor
|
||||
--
|
||||
-- Any class derived from BASE, will use the @{Base#BASE.New} constructor embedded in the @{Base#BASE.Inherit} method.
|
||||
-- See an example at the @{Base#BASE.New} method how this is done.
|
||||
--
|
||||
-- ## 1.2) Trace information for debugging
|
||||
-- # 2. Trace information for debugging.
|
||||
--
|
||||
-- The BASE class contains trace methods to trace progress within a mission execution of a certain object.
|
||||
-- These trace methods are inherited by each MOOSE class interiting BASE, soeach object created from derived class from BASE can use the tracing methods to trace its execution.
|
||||
@@ -76,7 +79,7 @@ local _ClassID = 0
|
||||
--
|
||||
-- Below a more detailed explanation of the different method types for tracing.
|
||||
--
|
||||
-- ### 1.2.1) Tracing methods categories
|
||||
-- ## 2.1. Tracing methods categories.
|
||||
--
|
||||
-- There are basically 3 types of tracing methods available:
|
||||
--
|
||||
@@ -84,9 +87,9 @@ local _ClassID = 0
|
||||
-- * @{#BASE.T}: Used to trace further logic within a function giving optional variables or parameters. A T is indicated at column 44 in the DCS.log file.
|
||||
-- * @{#BASE.E}: Used to always trace information giving optional variables or parameters. An E is indicated at column 44 in the DCS.log file.
|
||||
--
|
||||
-- ### 1.2.2) Tracing levels
|
||||
-- ## 2.2 Tracing levels.
|
||||
--
|
||||
-- There are 3 tracing levels within MOOSE.
|
||||
-- There are 3 tracing levels within MOOSE.
|
||||
-- These tracing levels were defined to avoid bulks of tracing to be generated by lots of objects.
|
||||
--
|
||||
-- As such, the F and T methods have additional variants to trace level 2 and 3 respectively:
|
||||
@@ -96,7 +99,7 @@ local _ClassID = 0
|
||||
-- * @{#BASE.T2}: Trace further logic within a function giving optional variables or parameters with tracing level 2.
|
||||
-- * @{#BASE.T3}: Trace further logic within a function giving optional variables or parameters with tracing level 3.
|
||||
--
|
||||
-- ### 1.2.3) Trace activation.
|
||||
-- ## 2.3. Trace activation.
|
||||
--
|
||||
-- Tracing can be activated in several ways:
|
||||
--
|
||||
@@ -106,16 +109,17 @@ local _ClassID = 0
|
||||
-- * Activate only the tracing of a certain method of a certain class through the @{#BASE.TraceClassMethod}() method.
|
||||
-- * Activate only the tracing of a certain level through the @{#BASE.TraceLevel}() method.
|
||||
--
|
||||
-- ### 1.2.4) Check if tracing is on.
|
||||
-- ## 2.4. Check if tracing is on.
|
||||
--
|
||||
-- The method @{#BASE.IsTrace}() will validate if tracing is activated or not.
|
||||
--
|
||||
-- ## 1.3 DCS simulator Event Handling
|
||||
--
|
||||
-- # 3. DCS simulator Event Handling.
|
||||
--
|
||||
-- The BASE class provides methods to catch DCS Events. These are events that are triggered from within the DCS simulator,
|
||||
-- and handled through lua scripting. MOOSE provides an encapsulation to handle these events more efficiently.
|
||||
--
|
||||
-- ### 1.3.1 Subscribe / Unsubscribe to DCS Events
|
||||
-- ## 3.1. Subscribe / Unsubscribe to DCS Events.
|
||||
--
|
||||
-- At first, the mission designer will need to **Subscribe** to a specific DCS event for the class.
|
||||
-- So, when the DCS event occurs, the class will be notified of that event.
|
||||
@@ -124,10 +128,10 @@ local _ClassID = 0
|
||||
-- * @{#BASE.HandleEvent}(): Subscribe to a DCS Event.
|
||||
-- * @{#BASE.UnHandleEvent}(): Unsubscribe from a DCS Event.
|
||||
--
|
||||
-- ### 1.3.2 Event Handling of DCS Events
|
||||
-- ## 3.2. Event Handling of DCS Events.
|
||||
--
|
||||
-- Once the class is subscribed to the event, an **Event Handling** method on the object or class needs to be written that will be called
|
||||
-- when the DCS event occurs. The Event Handling method receives an @{Event#EVENTDATA} structure, which contains a lot of information
|
||||
-- when the DCS event occurs. The Event Handling method receives an @{Core.Event#EVENTDATA} structure, which contains a lot of information
|
||||
-- about the event that occurred.
|
||||
--
|
||||
-- Find below an example of the prototype how to write an event handling function for two units:
|
||||
@@ -159,7 +163,7 @@ local _ClassID = 0
|
||||
--
|
||||
-- See the @{Event} module for more information about event handling.
|
||||
--
|
||||
-- ## 1.4) Class identification methods
|
||||
-- # 4. Class identification methods.
|
||||
--
|
||||
-- BASE provides methods to get more information of each object:
|
||||
--
|
||||
@@ -167,7 +171,7 @@ local _ClassID = 0
|
||||
-- * @{#BASE.GetClassName}(): Gets the name of the object, which is the name of the class the object was instantiated from.
|
||||
-- * @{#BASE.GetClassNameAndID}(): Gets the name and ID of the object.
|
||||
--
|
||||
-- ## 1.5) All objects derived from BASE can have "States"
|
||||
-- # 5. All objects derived from BASE can have "States".
|
||||
--
|
||||
-- A mechanism is in place in MOOSE, that allows to let the objects administer **states**.
|
||||
-- States are essentially properties of objects, which are identified by a **Key** and a **Value**.
|
||||
@@ -182,7 +186,7 @@ local _ClassID = 0
|
||||
-- Thus, if the state is to be set for the same object as the object for which the method is used, then provide the same
|
||||
-- object name to the method.
|
||||
--
|
||||
-- ## 1.10) Inheritance
|
||||
-- # 6. Inheritance.
|
||||
--
|
||||
-- The following methods are available to implement inheritance
|
||||
--
|
||||
@@ -191,8 +195,7 @@ local _ClassID = 0
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @field #BASE BASE
|
||||
--
|
||||
-- @field #BASE
|
||||
BASE = {
|
||||
ClassName = "BASE",
|
||||
ClassID = 0,
|
||||
@@ -609,8 +612,8 @@ end
|
||||
|
||||
--- Creation of a Birth Event.
|
||||
-- @param #BASE self
|
||||
-- @param Dcs.DCSTypes#Time EventTime The time stamp of the event.
|
||||
-- @param Dcs.DCSWrapper.Object#Object Initiator The initiating object of the event.
|
||||
-- @param DCS#Time EventTime The time stamp of the event.
|
||||
-- @param DCS#Object Initiator The initiating object of the event.
|
||||
-- @param #string IniUnitName The initiating unit name.
|
||||
-- @param place
|
||||
-- @param subplace
|
||||
@@ -631,8 +634,8 @@ end
|
||||
|
||||
--- Creation of a Crash Event.
|
||||
-- @param #BASE self
|
||||
-- @param Dcs.DCSTypes#Time EventTime The time stamp of the event.
|
||||
-- @param Dcs.DCSWrapper.Object#Object Initiator The initiating object of the event.
|
||||
-- @param DCS#Time EventTime The time stamp of the event.
|
||||
-- @param DCS#Object Initiator The initiating object of the event.
|
||||
function BASE:CreateEventCrash( EventTime, Initiator )
|
||||
self:F( { EventTime, Initiator } )
|
||||
|
||||
@@ -647,8 +650,8 @@ end
|
||||
|
||||
--- Creation of a Dead Event.
|
||||
-- @param #BASE self
|
||||
-- @param Dcs.DCSTypes#Time EventTime The time stamp of the event.
|
||||
-- @param Dcs.DCSWrapper.Object#Object Initiator The initiating object of the event.
|
||||
-- @param DCS#Time EventTime The time stamp of the event.
|
||||
-- @param DCS#Object Initiator The initiating object of the event.
|
||||
function BASE:CreateEventDead( EventTime, Initiator )
|
||||
self:F( { EventTime, Initiator } )
|
||||
|
||||
@@ -661,10 +664,26 @@ function BASE:CreateEventDead( EventTime, Initiator )
|
||||
world.onEvent( Event )
|
||||
end
|
||||
|
||||
--- Creation of a Remove Unit Event.
|
||||
-- @param #BASE self
|
||||
-- @param DCS#Time EventTime The time stamp of the event.
|
||||
-- @param DCS#Object Initiator The initiating object of the event.
|
||||
function BASE:CreateEventRemoveUnit( EventTime, Initiator )
|
||||
self:F( { EventTime, Initiator } )
|
||||
|
||||
local Event = {
|
||||
id = EVENTS.RemoveUnit,
|
||||
time = EventTime,
|
||||
initiator = Initiator,
|
||||
}
|
||||
|
||||
world.onEvent( Event )
|
||||
end
|
||||
|
||||
--- Creation of a Takeoff Event.
|
||||
-- @param #BASE self
|
||||
-- @param Dcs.DCSTypes#Time EventTime The time stamp of the event.
|
||||
-- @param Dcs.DCSWrapper.Object#Object Initiator The initiating object of the event.
|
||||
-- @param DCS#Time EventTime The time stamp of the event.
|
||||
-- @param DCS#Object Initiator The initiating object of the event.
|
||||
function BASE:CreateEventTakeoff( EventTime, Initiator )
|
||||
self:F( { EventTime, Initiator } )
|
||||
|
||||
@@ -677,10 +696,10 @@ function BASE:CreateEventTakeoff( EventTime, Initiator )
|
||||
world.onEvent( Event )
|
||||
end
|
||||
|
||||
-- TODO: Complete Dcs.DCSTypes#Event structure.
|
||||
-- TODO: Complete DCS#Event structure.
|
||||
--- The main event handling function... This function captures all events generated for the class.
|
||||
-- @param #BASE self
|
||||
-- @param Dcs.DCSTypes#Event event
|
||||
-- @param DCS#Event event
|
||||
function BASE:onEvent(event)
|
||||
--self:F( { BaseEventCodes[event.id], event } )
|
||||
|
||||
@@ -803,8 +822,7 @@ end
|
||||
-- @param Object The object that will hold the Value set by the Key.
|
||||
-- @param Key The key that is used as a reference of the value. Note that the key can be a #string, but it can also be any other type!
|
||||
-- @param Value The value to is stored in the object.
|
||||
-- @return The Value set.
|
||||
-- @return #nil The Key was not found and thus the Value could not be retrieved.
|
||||
-- @return The Value set.
|
||||
function BASE:SetState( Object, Key, Value )
|
||||
|
||||
local ClassNameAndID = Object:GetClassNameAndID()
|
||||
@@ -821,7 +839,7 @@ end
|
||||
-- @param #BASE self
|
||||
-- @param Object The object that holds the Value set by the Key.
|
||||
-- @param Key The key that is used to retrieve the value. Note that the key can be a #string, but it can also be any other type!
|
||||
-- @return The Value retrieved.
|
||||
-- @return The Value retrieved or nil if the Key was not found and thus the Value could not be retrieved.
|
||||
function BASE:GetState( Object, Key )
|
||||
|
||||
local ClassNameAndID = Object:GetClassNameAndID()
|
||||
@@ -834,6 +852,10 @@ function BASE:GetState( Object, Key )
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Clear the state of an object.
|
||||
-- @param #BASE self
|
||||
-- @param Object The object that holds the Value set by the Key.
|
||||
-- @param StateName The key that is should be cleared.
|
||||
function BASE:ClearState( Object, StateName )
|
||||
|
||||
local ClassNameAndID = Object:GetClassNameAndID()
|
||||
|
||||
@@ -1,4 +1,25 @@
|
||||
--- **Core** -- DATABASE manages the database of mission objects.
|
||||
--- **Core** - Manages several databases containing templates, mission objects, and mission information.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ## Features:
|
||||
--
|
||||
-- * During mission startup, scan the mission environment, and create / instantiate intelligently the different objects as defined within the mission.
|
||||
-- * Manage database of DCS Group templates (as modelled using the mission editor).
|
||||
-- - Group templates.
|
||||
-- - Unit templates.
|
||||
-- - Statics templates.
|
||||
-- * Manage database of @{Wrapper.Group#GROUP} objects alive in the mission.
|
||||
-- * Manage database of @{Wrapper.Unit#UNIT} objects alive in the mission.
|
||||
-- * Manage database of @{Wrapper.Static#STATIC} objects alive in the mission.
|
||||
-- * Manage database of players.
|
||||
-- * Manage database of client slots defined using the mission editor.
|
||||
-- * Manage database of airbases on the map, and from FARPs and ships as defined using the mission editor.
|
||||
-- * Manage database of countries.
|
||||
-- * Manage database of zone names.
|
||||
-- * Manage database of hits to units and statics.
|
||||
-- * Manage database of destroys of units and statics.
|
||||
-- * Manage database of @{Core.Zone#ZONE_BASE} objects.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
@@ -7,13 +28,14 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module Database
|
||||
-- @module Core.Database
|
||||
-- @image Core_Database.JPG
|
||||
|
||||
|
||||
--- @type DATABASE
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
--- # DATABASE class, extends @{Base#BASE}
|
||||
--- Contains collections of wrapper objects defined within MOOSE that reflect objects within the simulator.
|
||||
--
|
||||
-- Mission designers can use the DATABASE class to refer to:
|
||||
--
|
||||
@@ -65,6 +87,7 @@ local _DATABASECoalition =
|
||||
{
|
||||
[1] = "Red",
|
||||
[2] = "Blue",
|
||||
[3] = "Neutral",
|
||||
}
|
||||
|
||||
local _DATABASECategory =
|
||||
@@ -93,9 +116,12 @@ function DATABASE:New()
|
||||
self:HandleEvent( EVENTS.Birth, self._EventOnBirth )
|
||||
self:HandleEvent( EVENTS.Dead, self._EventOnDeadOrCrash )
|
||||
self:HandleEvent( EVENTS.Crash, self._EventOnDeadOrCrash )
|
||||
self:HandleEvent( EVENTS.RemoveUnit, self._EventOnDeadOrCrash )
|
||||
self:HandleEvent( EVENTS.Hit, self.AccountHits )
|
||||
self:HandleEvent( EVENTS.NewCargo )
|
||||
self:HandleEvent( EVENTS.DeleteCargo )
|
||||
self:HandleEvent( EVENTS.NewZone )
|
||||
self:HandleEvent( EVENTS.DeleteZone )
|
||||
|
||||
-- Follow alive players and clients
|
||||
--self:HandleEvent( EVENTS.PlayerEnterUnit, self._EventOnPlayerEnterUnit ) -- This is not working anymore!, handling this through the birth event.
|
||||
@@ -113,7 +139,7 @@ function DATABASE:New()
|
||||
--- @param #DATABASE self
|
||||
local function CheckPlayers( self )
|
||||
|
||||
local CoalitionsData = { AlivePlayersRed = coalition.getPlayers( coalition.side.RED ), AlivePlayersBlue = coalition.getPlayers( coalition.side.BLUE ) }
|
||||
local CoalitionsData = { AlivePlayersRed = coalition.getPlayers( coalition.side.RED ), AlivePlayersBlue = coalition.getPlayers( coalition.side.BLUE ), AlivePlayersNeutral = coalition.getPlayers( coalition.side.NEUTRAL )}
|
||||
for CoalitionId, CoalitionData in pairs( CoalitionsData ) do
|
||||
--self:E( { "CoalitionData:", CoalitionData } )
|
||||
for UnitId, UnitData in pairs( CoalitionData ) do
|
||||
@@ -183,7 +209,10 @@ function DATABASE:AddStatic( DCSStaticName )
|
||||
|
||||
if not self.STATICS[DCSStaticName] then
|
||||
self.STATICS[DCSStaticName] = STATIC:Register( DCSStaticName )
|
||||
return self.STATICS[DCSStaticName]
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
@@ -287,8 +316,37 @@ do -- Zones
|
||||
end
|
||||
|
||||
|
||||
--- Private method that registers new ZONE_BASE derived objects within the DATABASE Object.
|
||||
-- @param #DATABASE self
|
||||
-- @return #DATABASE self
|
||||
function DATABASE:_RegisterZones()
|
||||
|
||||
end
|
||||
for ZoneID, ZoneData in pairs( env.mission.triggers.zones ) do
|
||||
local ZoneName = ZoneData.name
|
||||
|
||||
self:I( { "Register ZONE:", Name = ZoneName } )
|
||||
local Zone = ZONE:New( ZoneName )
|
||||
self.ZONENAMES[ZoneName] = ZoneName
|
||||
self:AddZone( ZoneName, Zone )
|
||||
end
|
||||
|
||||
for ZoneGroupName, ZoneGroup in pairs( self.GROUPS ) do
|
||||
if ZoneGroupName:match("#ZONE_POLYGON") then
|
||||
local ZoneName1 = ZoneGroupName:match("(.*)#ZONE_POLYGON")
|
||||
local ZoneName2 = ZoneGroupName:match(".*#ZONE_POLYGON(.*)")
|
||||
local ZoneName = ZoneName1 .. ( ZoneName2 or "" )
|
||||
|
||||
self:I( { "Register ZONE_POLYGON:", Name = ZoneName } )
|
||||
local Zone_Polygon = ZONE_POLYGON:New( ZoneName, ZoneGroup )
|
||||
self.ZONENAMES[ZoneName] = ZoneName
|
||||
self:AddZone( ZoneName, Zone_Polygon )
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
end -- zone
|
||||
|
||||
|
||||
do -- cargo
|
||||
@@ -322,7 +380,7 @@ do -- cargo
|
||||
return CargoFound
|
||||
end
|
||||
|
||||
--- Checks if the Template name has a ~CARGO tag.
|
||||
--- Checks if the Template name has a #CARGO tag.
|
||||
-- If yes, the group is a cargo.
|
||||
-- @param #DATABASE self
|
||||
-- @param #string TemplateName
|
||||
@@ -331,7 +389,7 @@ do -- cargo
|
||||
|
||||
TemplateName = env.getValueDictByKey( TemplateName )
|
||||
|
||||
local Cargo = TemplateName:match( "~(CARGO)" )
|
||||
local Cargo = TemplateName:match( "#(CARGO)" )
|
||||
|
||||
return Cargo and Cargo == "CARGO"
|
||||
end
|
||||
@@ -339,29 +397,33 @@ do -- cargo
|
||||
--- Private method that registers new Static Templates within the DATABASE Object.
|
||||
-- @param #DATABASE self
|
||||
-- @return #DATABASE self
|
||||
function DATABASE:RegisterCargos()
|
||||
function DATABASE:_RegisterCargos()
|
||||
|
||||
local Groups = UTILS.DeepCopy( self.GROUPS ) -- This is a very important statement. CARGO_GROUP:New creates a new _DATABASE.GROUP entry, which will confuse the loop. I searched 4 hours on this to find the bug!
|
||||
|
||||
for CargoGroupName, CargoGroup in pairs( self.GROUPS ) do
|
||||
for CargoGroupName, CargoGroup in pairs( Groups ) do
|
||||
self:I( { Cargo = CargoGroupName } )
|
||||
if self:IsCargo( CargoGroupName ) then
|
||||
local CargoInfo = CargoGroupName:match("~CARGO(.*)")
|
||||
local CargoInfo = CargoGroupName:match("#CARGO(.*)")
|
||||
local CargoParam = CargoInfo and CargoInfo:match( "%((.*)%)")
|
||||
local CargoName = CargoGroupName:match("(.*)~CARGO")
|
||||
local CargoName1 = CargoGroupName:match("(.*)#CARGO%(.*%)")
|
||||
local CargoName2 = CargoGroupName:match(".*#CARGO%(.*%)(.*)")
|
||||
local CargoName = CargoName1 .. ( CargoName2 or "" )
|
||||
local Type = CargoParam and CargoParam:match( "T=([%a%d ]+),?")
|
||||
local Name = CargoParam and CargoParam:match( "N=([%a%d]+),?") or CargoName
|
||||
local LoadRadius = CargoParam and tonumber( CargoParam:match( "RR=([%a%d]+),?") )
|
||||
local NearRadius = CargoParam and tonumber( CargoParam:match( "NR=([%a%d]+),?") )
|
||||
|
||||
self:F({"Register CargoGroup:",Type=Type,Name=Name,LoadRadius=LoadRadius,NearRadius=NearRadius})
|
||||
self:I({"Register CargoGroup:",Type=Type,Name=Name,LoadRadius=LoadRadius,NearRadius=NearRadius})
|
||||
CARGO_GROUP:New( CargoGroup, Type, Name, LoadRadius, NearRadius )
|
||||
end
|
||||
end
|
||||
|
||||
for CargoStaticName, CargoStatic in pairs( self.STATICS ) do
|
||||
if self:IsCargo( CargoStaticName ) then
|
||||
local CargoInfo = CargoStaticName:match("~CARGO(.*)")
|
||||
local CargoInfo = CargoStaticName:match("#CARGO(.*)")
|
||||
local CargoParam = CargoInfo and CargoInfo:match( "%((.*)%)")
|
||||
local CargoName = CargoStaticName:match("(.*)~CARGO")
|
||||
local CargoName = CargoStaticName:match("(.*)#CARGO")
|
||||
local Type = CargoParam and CargoParam:match( "T=([%a%d ]+),?")
|
||||
local Category = CargoParam and CargoParam:match( "C=([%a%d ]+),?")
|
||||
local Name = CargoParam and CargoParam:match( "N=([%a%d]+),?") or CargoName
|
||||
@@ -369,11 +431,11 @@ do -- cargo
|
||||
local NearRadius = CargoParam and tonumber( CargoParam:match( "NR=([%a%d]+),?") )
|
||||
|
||||
if Category == "SLING" then
|
||||
self:F({"Register CargoSlingload:",Type=Type,Name=Name,LoadRadius=LoadRadius,NearRadius=NearRadius})
|
||||
self:I({"Register CargoSlingload:",Type=Type,Name=Name,LoadRadius=LoadRadius,NearRadius=NearRadius})
|
||||
CARGO_SLINGLOAD:New( CargoStatic, Type, Name, LoadRadius, NearRadius )
|
||||
else
|
||||
if Category == "CRATE" then
|
||||
self:F({"Register CargoCrate:",Type=Type,Name=Name,LoadRadius=LoadRadius,NearRadius=NearRadius})
|
||||
self:I({"Register CargoCrate:",Type=Type,Name=Name,LoadRadius=LoadRadius,NearRadius=NearRadius})
|
||||
CARGO_CRATE:New( CargoStatic, Type, Name, LoadRadius, NearRadius )
|
||||
end
|
||||
end
|
||||
@@ -423,7 +485,7 @@ end
|
||||
function DATABASE:AddGroup( GroupName )
|
||||
|
||||
if not self.GROUPS[GroupName] then
|
||||
self:E( { "Add GROUP:", GroupName } )
|
||||
self:I( { "Add GROUP:", GroupName } )
|
||||
self.GROUPS[GroupName] = GROUP:Register( GroupName )
|
||||
end
|
||||
|
||||
@@ -435,7 +497,7 @@ end
|
||||
function DATABASE:AddPlayer( UnitName, PlayerName )
|
||||
|
||||
if PlayerName then
|
||||
self:E( { "Add player for unit:", UnitName, PlayerName } )
|
||||
self:I( { "Add player for unit:", UnitName, PlayerName } )
|
||||
self.PLAYERS[PlayerName] = UnitName
|
||||
self.PLAYERUNITS[PlayerName] = self:FindUnit( UnitName )
|
||||
self.PLAYERSJOINED[PlayerName] = PlayerName
|
||||
@@ -447,7 +509,7 @@ end
|
||||
function DATABASE:DeletePlayer( UnitName, PlayerName )
|
||||
|
||||
if PlayerName then
|
||||
self:E( { "Clean player:", PlayerName } )
|
||||
self:I( { "Clean player:", PlayerName } )
|
||||
self.PLAYERS[PlayerName] = nil
|
||||
self.PLAYERUNITS[PlayerName] = nil
|
||||
end
|
||||
@@ -497,8 +559,8 @@ end
|
||||
-- SpawnCountryID, SpawnCategoryID
|
||||
-- This method is used by the SPAWN class.
|
||||
-- @param #DATABASE self
|
||||
-- @param #table SpawnTemplate
|
||||
-- @return #DATABASE self
|
||||
-- @param #table SpawnTemplate Template of the group to spawn.
|
||||
-- @return Wrapper.Group#GROUP Spawned group.
|
||||
function DATABASE:Spawn( SpawnTemplate )
|
||||
self:F( SpawnTemplate.name )
|
||||
|
||||
@@ -554,9 +616,9 @@ end
|
||||
--- Private method that registers new Group Templates within the DATABASE Object.
|
||||
-- @param #DATABASE self
|
||||
-- @param #table GroupTemplate
|
||||
-- @param Dcs.DCScoalition#coalition.side CoalitionSide The coalition.side of the object.
|
||||
-- @param Dcs.DCSObject#Object.Category CategoryID The Object.category of the object.
|
||||
-- @param Dcs.DCScountry#country.id CountryID the country.id of the object
|
||||
-- @param DCS#coalition.side CoalitionSide The coalition.side of the object.
|
||||
-- @param DCS#Object.Category CategoryID The Object.category of the object.
|
||||
-- @param DCS#country.id CountryID the country.id of the object
|
||||
-- @return #DATABASE self
|
||||
function DATABASE:_RegisterGroupTemplate( GroupTemplate, CoalitionSide, CategoryID, CountryID, GroupName )
|
||||
|
||||
@@ -631,10 +693,12 @@ end
|
||||
|
||||
--- Private method that registers new Static Templates within the DATABASE Object.
|
||||
-- @param #DATABASE self
|
||||
-- @param #table GroupTemplate
|
||||
-- @param #table StaticTemplate
|
||||
-- @return #DATABASE self
|
||||
function DATABASE:_RegisterStaticTemplate( StaticTemplate, CoalitionID, CategoryID, CountryID )
|
||||
|
||||
local StaticTemplate = UTILS.DeepCopy( StaticTemplate )
|
||||
|
||||
local StaticTemplateName = env.getValueDictByKey(StaticTemplate.name)
|
||||
|
||||
self.Templates.Statics[StaticTemplateName] = self.Templates.Statics[StaticTemplateName] or {}
|
||||
@@ -663,11 +727,17 @@ end
|
||||
|
||||
|
||||
--- @param #DATABASE self
|
||||
function DATABASE:GetStaticUnitTemplate( StaticName )
|
||||
local StaticTemplate = self.Templates.Statics[StaticName].UnitTemplate
|
||||
function DATABASE:GetStaticGroupTemplate( StaticName )
|
||||
local StaticTemplate = self.Templates.Statics[StaticName].GroupTemplate
|
||||
return StaticTemplate, self.Templates.Statics[StaticName].CoalitionID, self.Templates.Statics[StaticName].CategoryID, self.Templates.Statics[StaticName].CountryID
|
||||
end
|
||||
|
||||
--- @param #DATABASE self
|
||||
function DATABASE:GetStaticUnitTemplate( StaticName )
|
||||
local UnitTemplate = self.Templates.Statics[StaticName].UnitTemplate
|
||||
return UnitTemplate, self.Templates.Statics[StaticName].CoalitionID, self.Templates.Statics[StaticName].CategoryID, self.Templates.Statics[StaticName].CountryID
|
||||
end
|
||||
|
||||
|
||||
function DATABASE:GetGroupNameFromUnitName( UnitName )
|
||||
return self.Templates.Units[UnitName].GroupName
|
||||
@@ -706,7 +776,7 @@ end
|
||||
-- @return #DATABASE self
|
||||
function DATABASE:_RegisterPlayers()
|
||||
|
||||
local CoalitionsData = { AlivePlayersRed = coalition.getPlayers( coalition.side.RED ), AlivePlayersBlue = coalition.getPlayers( coalition.side.BLUE ) }
|
||||
local CoalitionsData = { AlivePlayersRed = coalition.getPlayers( coalition.side.RED ), AlivePlayersBlue = coalition.getPlayers( coalition.side.BLUE ), AlivePlayersNeutral = coalition.getPlayers( coalition.side.NEUTRAL ) }
|
||||
for CoalitionId, CoalitionData in pairs( CoalitionsData ) do
|
||||
for UnitId, UnitData in pairs( CoalitionData ) do
|
||||
self:T3( { "UnitData:", UnitData } )
|
||||
@@ -714,7 +784,7 @@ function DATABASE:_RegisterPlayers()
|
||||
local UnitName = UnitData:getName()
|
||||
local PlayerName = UnitData:getPlayerName()
|
||||
if not self.PLAYERS[PlayerName] then
|
||||
self:E( { "Add player for unit:", UnitName, PlayerName } )
|
||||
self:I( { "Add player for unit:", UnitName, PlayerName } )
|
||||
self:AddPlayer( UnitName, PlayerName )
|
||||
end
|
||||
end
|
||||
@@ -730,20 +800,20 @@ end
|
||||
-- @return #DATABASE self
|
||||
function DATABASE:_RegisterGroupsAndUnits()
|
||||
|
||||
local CoalitionsData = { GroupsRed = coalition.getGroups( coalition.side.RED ), GroupsBlue = coalition.getGroups( coalition.side.BLUE ) }
|
||||
local CoalitionsData = { GroupsRed = coalition.getGroups( coalition.side.RED ), GroupsBlue = coalition.getGroups( coalition.side.BLUE ), GroupsNeutral = coalition.getGroups( coalition.side.NEUTRAL ) }
|
||||
for CoalitionId, CoalitionData in pairs( CoalitionsData ) do
|
||||
for DCSGroupId, DCSGroup in pairs( CoalitionData ) do
|
||||
|
||||
if DCSGroup:isExist() then
|
||||
local DCSGroupName = DCSGroup:getName()
|
||||
|
||||
self:E( { "Register Group:", DCSGroupName } )
|
||||
self:I( { "Register Group:", DCSGroupName } )
|
||||
self:AddGroup( DCSGroupName )
|
||||
|
||||
for DCSUnitId, DCSUnit in pairs( DCSGroup:getUnits() ) do
|
||||
|
||||
local DCSUnitName = DCSUnit:getName()
|
||||
self:E( { "Register Unit:", DCSUnitName } )
|
||||
self:I( { "Register Unit:", DCSUnitName } )
|
||||
self:AddUnit( DCSUnitName )
|
||||
end
|
||||
else
|
||||
@@ -752,6 +822,11 @@ function DATABASE:_RegisterGroupsAndUnits()
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
self:I("Groups:")
|
||||
for GroupName, Group in pairs( self.GROUPS ) do
|
||||
self:I( { "Group:", GroupName } )
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
@@ -762,7 +837,7 @@ end
|
||||
function DATABASE:_RegisterClients()
|
||||
|
||||
for ClientName, ClientTemplate in pairs( self.Templates.ClientsByName ) do
|
||||
self:E( { "Register Client:", ClientName } )
|
||||
self:I( { "Register Client:", ClientName } )
|
||||
self:AddClient( ClientName )
|
||||
end
|
||||
|
||||
@@ -773,14 +848,14 @@ end
|
||||
function DATABASE:_RegisterStatics()
|
||||
|
||||
local CoalitionsData = { GroupsRed = coalition.getStaticObjects( coalition.side.RED ), GroupsBlue = coalition.getStaticObjects( coalition.side.BLUE ) }
|
||||
self:E( { Statics = CoalitionsData } )
|
||||
self:I( { Statics = CoalitionsData } )
|
||||
for CoalitionId, CoalitionData in pairs( CoalitionsData ) do
|
||||
for DCSStaticId, DCSStatic in pairs( CoalitionData ) do
|
||||
|
||||
if DCSStatic:isExist() then
|
||||
local DCSStaticName = DCSStatic:getName()
|
||||
|
||||
self:E( { "Register Static:", DCSStaticName } )
|
||||
self:I( { "Register Static:", DCSStaticName } )
|
||||
self:AddStatic( DCSStaticName )
|
||||
else
|
||||
self:E( { "Static does not exist: ", DCSStatic } )
|
||||
@@ -800,7 +875,7 @@ function DATABASE:_RegisterAirbases()
|
||||
|
||||
local DCSAirbaseName = DCSAirbase:getName()
|
||||
|
||||
self:E( { "Register Airbase:", DCSAirbaseName, DCSAirbase:getID() } )
|
||||
self:I( { "Register Airbase:", DCSAirbaseName, DCSAirbase:getID() } )
|
||||
self:AddAirbase( DCSAirbaseName )
|
||||
end
|
||||
end
|
||||
@@ -830,9 +905,8 @@ function DATABASE:_EventOnBirth( Event )
|
||||
Event.IniUnit = self:FindUnit( Event.IniDCSUnitName )
|
||||
Event.IniGroup = self:FindGroup( Event.IniDCSGroupName )
|
||||
local PlayerName = Event.IniUnit:GetPlayerName()
|
||||
self:E( { "PlayerName:", PlayerName } )
|
||||
if PlayerName then
|
||||
self:E( { "Player Joined:", PlayerName } )
|
||||
self:I( { "Player Joined:", PlayerName } )
|
||||
if not self.PLAYERS[PlayerName] then
|
||||
self:AddPlayer( Event.IniUnitName, PlayerName )
|
||||
end
|
||||
@@ -901,7 +975,7 @@ function DATABASE:_EventOnPlayerLeaveUnit( Event )
|
||||
if Event.IniObjectCategory == 1 then
|
||||
local PlayerName = Event.IniUnit:GetPlayerName()
|
||||
if PlayerName and self.PLAYERS[PlayerName] then
|
||||
self:E( { "Player Left:", PlayerName } )
|
||||
self:I( { "Player Left:", PlayerName } )
|
||||
local Settings = SETTINGS:Set( PlayerName )
|
||||
Settings:RemovePlayerMenu( Event.IniUnit )
|
||||
self:DeletePlayer( Event.IniUnit, PlayerName )
|
||||
@@ -1085,6 +1159,31 @@ function DATABASE:OnEventDeleteCargo( EventData )
|
||||
end
|
||||
|
||||
|
||||
--- Handles the OnEventNewZone event.
|
||||
-- @param #DATABASE self
|
||||
-- @param Core.Event#EVENTDATA EventData
|
||||
function DATABASE:OnEventNewZone( EventData )
|
||||
self:F2( { EventData } )
|
||||
|
||||
if EventData.Zone then
|
||||
self:AddZone( EventData.Zone )
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--- Handles the OnEventDeleteZone.
|
||||
-- @param #DATABASE self
|
||||
-- @param Core.Event#EVENTDATA EventData
|
||||
function DATABASE:OnEventDeleteZone( EventData )
|
||||
self:F2( { EventData } )
|
||||
|
||||
if EventData.Zone then
|
||||
self:DeleteZone( EventData.Zone.ZoneName )
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
--- Gets the player settings
|
||||
-- @param #DATABASE self
|
||||
-- @param #string PlayerName
|
||||
@@ -1116,11 +1215,19 @@ function DATABASE:_RegisterTemplates()
|
||||
self.UNITS = {}
|
||||
--Build routines.db.units and self.Navpoints
|
||||
for CoalitionName, coa_data in pairs(env.mission.coalition) do
|
||||
self:T({CoalitionName=CoalitionName})
|
||||
|
||||
if (CoalitionName == 'red' or CoalitionName == 'blue') and type(coa_data) == 'table' then
|
||||
if (CoalitionName == 'red' or CoalitionName == 'blue' or CoalitionName == 'neutrals') and type(coa_data) == 'table' then
|
||||
--self.Units[coa_name] = {}
|
||||
|
||||
local CoalitionSide = coalition.side[string.upper(CoalitionName)]
|
||||
if CoalitionName=="red" then
|
||||
CoalitionSide=coalition.side.NEUTRAL
|
||||
elseif CoalitionName=="blue" then
|
||||
CoalitionSide=coalition.side.BLUE
|
||||
else
|
||||
CoalitionSide=coalition.side.NEUTRAL
|
||||
end
|
||||
|
||||
-- build nav points DB
|
||||
self.Navpoints[CoalitionName] = {}
|
||||
@@ -1191,13 +1298,6 @@ function DATABASE:_RegisterTemplates()
|
||||
end --if coa_name == 'red' or coa_name == 'blue' and type(coa_data) == 'table' then
|
||||
end --for coa_name, coa_data in pairs(mission.coalition) do
|
||||
|
||||
for ZoneID, ZoneData in pairs( env.mission.triggers.zones ) do
|
||||
local ZoneName = ZoneData.name
|
||||
self.ZONENAMES[ZoneName] = ZoneName
|
||||
self:AddZone( ZoneName, ZONE:New( ZoneName ) )
|
||||
self:I( "Added ZONE " .. ZoneName )
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -1280,18 +1380,12 @@ end
|
||||
self:T( { TargetUnitName, TargetGroupName, TargetPlayerName, TargetCoalition, TargetCategory, TargetType } )
|
||||
end
|
||||
|
||||
self:T( "Something got destroyed" )
|
||||
|
||||
local Destroyed = false
|
||||
|
||||
-- What is the player destroying?
|
||||
if self.HITS[Event.IniUnitName] then -- Was there a hit for this unit for this player before registered???
|
||||
|
||||
|
||||
self.DESTROYS[Event.IniUnitName] = self.DESTROYS[Event.IniUnitName] or {}
|
||||
|
||||
self.DESTROYS[Event.IniUnitName] = true
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
--- **Core** -- EVENT models DCS **event dispatching** using a **publish-subscribe** model.
|
||||
--
|
||||
-- 
|
||||
--- **Core** - Models DCS event dispatching using a publish-subscribe model.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- # 1) Event Handling Overview
|
||||
-- ## Features:
|
||||
--
|
||||
-- * Capture DCS events and dispatch them to the subscribed objects.
|
||||
-- * Generate DCS events to the subscribed objects from within the code.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- # Event Handling Overview
|
||||
--
|
||||
-- 
|
||||
--
|
||||
@@ -16,7 +21,7 @@
|
||||
-- Objects can subscribe to different events. The Event dispatcher will publish the received DCS events to the subscribed MOOSE objects, in a specified order.
|
||||
-- In this way, the subscribed MOOSE objects are kept in sync with your evolving running mission.
|
||||
--
|
||||
-- ## 1.1) Event Dispatching
|
||||
-- ## 1. Event Dispatching
|
||||
--
|
||||
-- 
|
||||
--
|
||||
@@ -43,7 +48,7 @@
|
||||
--
|
||||
-- But for some DCS events, the publishing order is reversed. This is due to the fact that objects need to be **erased** instead of added.
|
||||
--
|
||||
-- ## 1.2) Event Handling
|
||||
-- # 2. Event Handling
|
||||
--
|
||||
-- 
|
||||
--
|
||||
@@ -55,14 +60,14 @@
|
||||
-- The BASE class provides methods to catch DCS Events. These are events that are triggered from within the DCS simulator,
|
||||
-- and handled through lua scripting. MOOSE provides an encapsulation to handle these events more efficiently.
|
||||
--
|
||||
-- ### 1.2.1 Subscribe / Unsubscribe to DCS Events
|
||||
-- ## 2.1. Subscribe to / Unsubscribe from DCS Events.
|
||||
--
|
||||
-- At first, the mission designer will need to **Subscribe** to a specific DCS event for the class.
|
||||
-- So, when the DCS event occurs, the class will be notified of that event.
|
||||
-- There are two functions which you use to subscribe to or unsubscribe from an event.
|
||||
--
|
||||
-- * @{Base#BASE.HandleEvent}(): Subscribe to a DCS Event.
|
||||
-- * @{Base#BASE.UnHandleEvent}(): Unsubscribe from a DCS Event.
|
||||
-- * @{Core.Base#BASE.HandleEvent}(): Subscribe to a DCS Event.
|
||||
-- * @{Core.Base#BASE.UnHandleEvent}(): Unsubscribe from a DCS Event.
|
||||
--
|
||||
-- Note that for a UNIT, the event will be handled **for that UNIT only**!
|
||||
-- Note that for a GROUP, the event will be handled **for all the UNITs in that GROUP only**!
|
||||
@@ -71,10 +76,10 @@
|
||||
-- So if a UNIT within the mission has the subscribed event for that object,
|
||||
-- then the object event handler will receive the event for that UNIT!
|
||||
--
|
||||
-- ### 1.3.2 Event Handling of DCS Events
|
||||
-- ## 2.2 Event Handling of DCS Events
|
||||
--
|
||||
-- Once the class is subscribed to the event, an **Event Handling** method on the object or class needs to be written that will be called
|
||||
-- when the DCS event occurs. The Event Handling method receives an @{Event#EVENTDATA} structure, which contains a lot of information
|
||||
-- when the DCS event occurs. The Event Handling method receives an @{Core.Event#EVENTDATA} structure, which contains a lot of information
|
||||
-- about the event that occurred.
|
||||
--
|
||||
-- Find below an example of the prototype how to write an event handling function for two units:
|
||||
@@ -102,21 +107,21 @@
|
||||
-- self:SmokeBlue()
|
||||
-- end
|
||||
--
|
||||
-- ### 1.3.3 Event Handling methods that are automatically called upon subscribed DCS events
|
||||
-- ## 2.3 Event Handling methods that are automatically called upon subscribed DCS events.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- The following list outlines which EVENTS item in the structure corresponds to which Event Handling method.
|
||||
-- Always ensure that your event handling methods align with the events being subscribed to, or nothing will be executed.
|
||||
--
|
||||
-- # 2) EVENTS type
|
||||
-- # 3. EVENTS type
|
||||
--
|
||||
-- The EVENTS structure contains names for all the different DCS events that objects can subscribe to using the
|
||||
-- @{Base#BASE.HandleEvent}() method.
|
||||
-- @{Core.Base#BASE.HandleEvent}() method.
|
||||
--
|
||||
-- # 3) EVENTDATA type
|
||||
-- # 4. EVENTDATA type
|
||||
--
|
||||
-- The @{Event#EVENTDATA} structure contains all the fields that are populated with event information before
|
||||
-- The @{Core.Event#EVENTDATA} structure contains all the fields that are populated with event information before
|
||||
-- an Event Handler method is being called by the event dispatcher.
|
||||
-- The Event Handler received the EVENTDATA object as a parameter, and can be used to investigate further the different events.
|
||||
-- There are basically 4 main categories of information stored in the EVENTDATA structure:
|
||||
@@ -164,13 +169,16 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module Event
|
||||
-- @module Core.Event
|
||||
-- @image Core_Event.JPG
|
||||
|
||||
|
||||
--- The EVENT structure
|
||||
-- @type EVENT
|
||||
--- @type EVENT
|
||||
-- @field #EVENT.Events Events
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
--- The EVENT class
|
||||
-- @field #EVENT
|
||||
EVENT = {
|
||||
ClassName = "EVENT",
|
||||
ClassID = 0,
|
||||
@@ -179,9 +187,13 @@ EVENT = {
|
||||
|
||||
world.event.S_EVENT_NEW_CARGO = world.event.S_EVENT_MAX + 1000
|
||||
world.event.S_EVENT_DELETE_CARGO = world.event.S_EVENT_MAX + 1001
|
||||
world.event.S_EVENT_NEW_ZONE = world.event.S_EVENT_MAX + 1002
|
||||
world.event.S_EVENT_DELETE_ZONE = world.event.S_EVENT_MAX + 1003
|
||||
world.event.S_EVENT_REMOVE_UNIT = world.event.S_EVENT_MAX + 1004
|
||||
|
||||
|
||||
--- The different types of events supported by MOOSE.
|
||||
-- Use this structure to subscribe to events using the @{Base#BASE.HandleEvent}() method.
|
||||
-- Use this structure to subscribe to events using the @{Core.Base#BASE.HandleEvent}() method.
|
||||
-- @type EVENTS
|
||||
EVENTS = {
|
||||
Shot = world.event.S_EVENT_SHOT,
|
||||
@@ -207,8 +219,14 @@ EVENTS = {
|
||||
PlayerComment = world.event.S_EVENT_PLAYER_COMMENT,
|
||||
ShootingStart = world.event.S_EVENT_SHOOTING_START,
|
||||
ShootingEnd = world.event.S_EVENT_SHOOTING_END,
|
||||
MarkAdded = world.event.S_EVENT_MARK_ADDED,
|
||||
MarkChange = world.event.S_EVENT_MARK_CHANGE,
|
||||
MarkRemoved = world.event.S_EVENT_MARK_REMOVED,
|
||||
NewCargo = world.event.S_EVENT_NEW_CARGO,
|
||||
DeleteCargo = world.event.S_EVENT_DELETE_CARGO,
|
||||
NewZone = world.event.S_EVENT_NEW_ZONE,
|
||||
DeleteZone = world.event.S_EVENT_DELETE_ZONE,
|
||||
RemoveUnit = world.event.S_EVENT_REMOVE_UNIT,
|
||||
}
|
||||
|
||||
--- The Event structure
|
||||
@@ -220,36 +238,40 @@ EVENTS = {
|
||||
-- @type EVENTDATA
|
||||
-- @field #number id The identifier of the event.
|
||||
--
|
||||
-- @field Dcs.DCSUnit#Unit initiator (UNIT/STATIC/SCENERY) The initiating @{Dcs.DCSUnit#Unit} or @{Dcs.DCSStaticObject#StaticObject}.
|
||||
-- @field Dcs.DCSObject#Object.Category IniObjectCategory (UNIT/STATIC/SCENERY) The initiator object category ( Object.Category.UNIT or Object.Category.STATIC ).
|
||||
-- @field Dcs.DCSUnit#Unit IniDCSUnit (UNIT/STATIC) The initiating @{DCSUnit#Unit} or @{DCSStaticObject#StaticObject}.
|
||||
-- @field DCS#Unit initiator (UNIT/STATIC/SCENERY) The initiating @{DCS#Unit} or @{DCS#StaticObject}.
|
||||
-- @field DCS#Object.Category IniObjectCategory (UNIT/STATIC/SCENERY) The initiator object category ( Object.Category.UNIT or Object.Category.STATIC ).
|
||||
-- @field DCS#Unit IniDCSUnit (UNIT/STATIC) The initiating @{DCS#Unit} or @{DCS#StaticObject}.
|
||||
-- @field #string IniDCSUnitName (UNIT/STATIC) The initiating Unit name.
|
||||
-- @field Wrapper.Unit#UNIT IniUnit (UNIT/STATIC) The initiating MOOSE wrapper @{Unit#UNIT} of the initiator Unit object.
|
||||
-- @field Wrapper.Unit#UNIT IniUnit (UNIT/STATIC) The initiating MOOSE wrapper @{Wrapper.Unit#UNIT} of the initiator Unit object.
|
||||
-- @field #string IniUnitName (UNIT/STATIC) The initiating UNIT name (same as IniDCSUnitName).
|
||||
-- @field Dcs.DCSGroup#Group IniDCSGroup (UNIT) The initiating {DCSGroup#Group}.
|
||||
-- @field DCS#Group IniDCSGroup (UNIT) The initiating {DCSGroup#Group}.
|
||||
-- @field #string IniDCSGroupName (UNIT) The initiating Group name.
|
||||
-- @field Wrapper.Group#GROUP IniGroup (UNIT) The initiating MOOSE wrapper @{Group#GROUP} of the initiator Group object.
|
||||
-- @field Wrapper.Group#GROUP IniGroup (UNIT) The initiating MOOSE wrapper @{Wrapper.Group#GROUP} of the initiator Group object.
|
||||
-- @field #string IniGroupName UNIT) The initiating GROUP name (same as IniDCSGroupName).
|
||||
-- @field #string IniPlayerName (UNIT) The name of the initiating player in case the Unit is a client or player slot.
|
||||
-- @field Dcs.DCScoalition#coalition.side IniCoalition (UNIT) The coalition of the initiator.
|
||||
-- @field Dcs.DCSUnit#Unit.Category IniCategory (UNIT) The category of the initiator.
|
||||
-- @field DCS#coalition.side IniCoalition (UNIT) The coalition of the initiator.
|
||||
-- @field DCS#Unit.Category IniCategory (UNIT) The category of the initiator.
|
||||
-- @field #string IniTypeName (UNIT) The type name of the initiator.
|
||||
--
|
||||
-- @field Dcs.DCSUnit#Unit target (UNIT/STATIC) The target @{Dcs.DCSUnit#Unit} or @{DCSStaticObject#StaticObject}.
|
||||
-- @field Dcs.DCSObject#Object.Category TgtObjectCategory (UNIT/STATIC) The target object category ( Object.Category.UNIT or Object.Category.STATIC ).
|
||||
-- @field Dcs.DCSUnit#Unit TgtDCSUnit (UNIT/STATIC) The target @{DCSUnit#Unit} or @{DCSStaticObject#StaticObject}.
|
||||
-- @field DCS#Unit target (UNIT/STATIC) The target @{DCS#Unit} or @{DCS#StaticObject}.
|
||||
-- @field DCS#Object.Category TgtObjectCategory (UNIT/STATIC) The target object category ( Object.Category.UNIT or Object.Category.STATIC ).
|
||||
-- @field DCS#Unit TgtDCSUnit (UNIT/STATIC) The target @{DCS#Unit} or @{DCS#StaticObject}.
|
||||
-- @field #string TgtDCSUnitName (UNIT/STATIC) The target Unit name.
|
||||
-- @field Wrapper.Unit#UNIT TgtUnit (UNIT/STATIC) The target MOOSE wrapper @{Unit#UNIT} of the target Unit object.
|
||||
-- @field Wrapper.Unit#UNIT TgtUnit (UNIT/STATIC) The target MOOSE wrapper @{Wrapper.Unit#UNIT} of the target Unit object.
|
||||
-- @field #string TgtUnitName (UNIT/STATIC) The target UNIT name (same as TgtDCSUnitName).
|
||||
-- @field Dcs.DCSGroup#Group TgtDCSGroup (UNIT) The target {DCSGroup#Group}.
|
||||
-- @field DCS#Group TgtDCSGroup (UNIT) The target {DCSGroup#Group}.
|
||||
-- @field #string TgtDCSGroupName (UNIT) The target Group name.
|
||||
-- @field Wrapper.Group#GROUP TgtGroup (UNIT) The target MOOSE wrapper @{Group#GROUP} of the target Group object.
|
||||
-- @field Wrapper.Group#GROUP TgtGroup (UNIT) The target MOOSE wrapper @{Wrapper.Group#GROUP} of the target Group object.
|
||||
-- @field #string TgtGroupName (UNIT) The target GROUP name (same as TgtDCSGroupName).
|
||||
-- @field #string TgtPlayerName (UNIT) The name of the target player in case the Unit is a client or player slot.
|
||||
-- @field Dcs.DCScoalition#coalition.side TgtCoalition (UNIT) The coalition of the target.
|
||||
-- @field Dcs.DCSUnit#Unit.Category TgtCategory (UNIT) The category of the target.
|
||||
-- @field DCS#coalition.side TgtCoalition (UNIT) The coalition of the target.
|
||||
-- @field DCS#Unit.Category TgtCategory (UNIT) The category of the target.
|
||||
-- @field #string TgtTypeName (UNIT) The type name of the target.
|
||||
--
|
||||
-- @field DCS#Airbase place The @{DCS#Airbase}
|
||||
-- @field Wrapper.Airbase#AIRBASE Place The MOOSE airbase object.
|
||||
-- @field #string PlaceName The name of the airbase.
|
||||
--
|
||||
-- @field weapon The weapon used during the event.
|
||||
-- @field Weapon
|
||||
-- @field WeaponName
|
||||
@@ -396,6 +418,24 @@ local _EVENTMETA = {
|
||||
Event = "OnEventShootingEnd",
|
||||
Text = "S_EVENT_SHOOTING_END"
|
||||
},
|
||||
[world.event.S_EVENT_MARK_ADDED] = {
|
||||
Order = 1,
|
||||
Side = "I",
|
||||
Event = "OnEventMarkAdded",
|
||||
Text = "S_EVENT_MARK_ADDED"
|
||||
},
|
||||
[world.event.S_EVENT_MARK_CHANGE] = {
|
||||
Order = 1,
|
||||
Side = "I",
|
||||
Event = "OnEventMarkChange",
|
||||
Text = "S_EVENT_MARK_CHANGE"
|
||||
},
|
||||
[world.event.S_EVENT_MARK_REMOVED] = {
|
||||
Order = 1,
|
||||
Side = "I",
|
||||
Event = "OnEventMarkRemoved",
|
||||
Text = "S_EVENT_MARK_REMOVED"
|
||||
},
|
||||
[EVENTS.NewCargo] = {
|
||||
Order = 1,
|
||||
Event = "OnEventNewCargo",
|
||||
@@ -406,6 +446,21 @@ local _EVENTMETA = {
|
||||
Event = "OnEventDeleteCargo",
|
||||
Text = "S_EVENT_DELETE_CARGO"
|
||||
},
|
||||
[EVENTS.NewZone] = {
|
||||
Order = 1,
|
||||
Event = "OnEventNewZone",
|
||||
Text = "S_EVENT_NEW_ZONE"
|
||||
},
|
||||
[EVENTS.DeleteZone] = {
|
||||
Order = 1,
|
||||
Event = "OnEventDeleteZone",
|
||||
Text = "S_EVENT_DELETE_ZONE"
|
||||
},
|
||||
[EVENTS.RemoveUnit] = {
|
||||
Order = -1,
|
||||
Event = "OnEventRemoveUnit",
|
||||
Text = "S_EVENT_REMOVE_UNIT"
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -423,7 +478,7 @@ end
|
||||
|
||||
--- Initializes the Events structure for the event
|
||||
-- @param #EVENT self
|
||||
-- @param Dcs.DCSWorld#world.event EventID
|
||||
-- @param DCS#world.event EventID
|
||||
-- @param Core.Base#BASE EventClass
|
||||
-- @return #EVENT.Events
|
||||
function EVENT:Init( EventID, EventClass )
|
||||
@@ -449,7 +504,7 @@ end
|
||||
--- Removes a subscription
|
||||
-- @param #EVENT self
|
||||
-- @param Core.Base#BASE EventClass The self instance of the class for which the event is.
|
||||
-- @param Dcs.DCSWorld#world.event EventID
|
||||
-- @param DCS#world.event EventID
|
||||
-- @return #EVENT.Events
|
||||
function EVENT:RemoveEvent( EventClass, EventID )
|
||||
|
||||
@@ -460,7 +515,6 @@ function EVENT:RemoveEvent( EventClass, EventID )
|
||||
self.Events = self.Events or {}
|
||||
self.Events[EventID] = self.Events[EventID] or {}
|
||||
self.Events[EventID][EventPriority] = self.Events[EventID][EventPriority] or {}
|
||||
self.Events[EventID][EventPriority][EventClass] = self.Events[EventID][EventPriority][EventClass]
|
||||
|
||||
self.Events[EventID][EventPriority][EventClass] = nil
|
||||
|
||||
@@ -469,7 +523,7 @@ end
|
||||
--- Resets subscriptions
|
||||
-- @param #EVENT self
|
||||
-- @param Core.Base#BASE EventClass The self instance of the class for which the event is.
|
||||
-- @param Dcs.DCSWorld#world.event EventID
|
||||
-- @param DCS#world.event EventID
|
||||
-- @return #EVENT.Events
|
||||
function EVENT:Reset( EventObject ) --R2.1
|
||||
|
||||
@@ -492,7 +546,7 @@ end
|
||||
|
||||
|
||||
|
||||
--- Clears all event subscriptions for a @{Base#BASE} derived object.
|
||||
--- Clears all event subscriptions for a @{Core.Base#BASE} derived object.
|
||||
-- @param #EVENT self
|
||||
-- @param Core.Base#BASE EventObject
|
||||
function EVENT:RemoveAll( EventObject )
|
||||
@@ -684,7 +738,7 @@ do -- Event Creation
|
||||
-- @param #EVENT self
|
||||
-- @param AI.AI_Cargo#AI_CARGO Cargo The Cargo created.
|
||||
function EVENT:CreateEventNewCargo( Cargo )
|
||||
self:F( { Cargo } )
|
||||
self:I( { Cargo } )
|
||||
|
||||
local Event = {
|
||||
id = EVENTS.NewCargo,
|
||||
@@ -710,6 +764,36 @@ do -- Event Creation
|
||||
world.onEvent( Event )
|
||||
end
|
||||
|
||||
--- Creation of a New Zone Event.
|
||||
-- @param #EVENT self
|
||||
-- @param Core.Zone#ZONE_BASE Zone The Zone created.
|
||||
function EVENT:CreateEventNewZone( Zone )
|
||||
self:F( { Zone } )
|
||||
|
||||
local Event = {
|
||||
id = EVENTS.NewZone,
|
||||
time = timer.getTime(),
|
||||
zone = Zone,
|
||||
}
|
||||
|
||||
world.onEvent( Event )
|
||||
end
|
||||
|
||||
--- Creation of a Zone Deletion Event.
|
||||
-- @param #EVENT self
|
||||
-- @param Core.Zone#ZONE_BASE Zone The Zone created.
|
||||
function EVENT:CreateEventDeleteZone( Zone )
|
||||
self:F( { Zone } )
|
||||
|
||||
local Event = {
|
||||
id = EVENTS.DeleteZone,
|
||||
time = timer.getTime(),
|
||||
zone = Zone,
|
||||
}
|
||||
|
||||
world.onEvent( Event )
|
||||
end
|
||||
|
||||
--- Creation of a S_EVENT_PLAYER_ENTER_UNIT Event.
|
||||
-- @param #EVENT self
|
||||
-- @param Wrapper.Unit#UNIT PlayerUnit.
|
||||
@@ -869,17 +953,40 @@ function EVENT:onEvent( Event )
|
||||
--Event.WeaponTgtDCSUnit = Event.Weapon:getTarget()
|
||||
end
|
||||
|
||||
-- Place should be given for takeoff and landing events as well as base captured. It should be a DCS airbase.
|
||||
if Event.place then
|
||||
Event.Place=AIRBASE:Find(Event.place)
|
||||
Event.PlaceName=Event.Place:GetName()
|
||||
end
|
||||
|
||||
-- @FC: something like this should be added.
|
||||
--[[
|
||||
if Event.idx then
|
||||
Event.MarkID=Event.idx
|
||||
Event.MarkVec3=Event.pos
|
||||
Event.MarkCoordinate=COORDINATE:NewFromVec3(Event.pos)
|
||||
Event.MarkText=Event.text
|
||||
Event.MarkCoalition=Event.coalition
|
||||
Event.MarkGroupID = Event.groupID
|
||||
end
|
||||
]]
|
||||
|
||||
if Event.cargo then
|
||||
Event.Cargo = Event.cargo
|
||||
Event.CargoName = Event.cargo.Name
|
||||
end
|
||||
|
||||
if Event.zone then
|
||||
Event.Zone = Event.zone
|
||||
Event.ZoneName = Event.zone.ZoneName
|
||||
end
|
||||
|
||||
local PriorityOrder = EventMeta.Order
|
||||
local PriorityBegin = PriorityOrder == -1 and 5 or 1
|
||||
local PriorityEnd = PriorityOrder == -1 and 1 or 5
|
||||
|
||||
if Event.IniObjectCategory ~= Object.Category.STATIC then
|
||||
self:E( { EventMeta.Text, Event, Event.IniDCSUnitName, Event.TgtDCSUnitName, PriorityOrder } )
|
||||
self:T( { EventMeta.Text, Event, Event.IniDCSUnitName, Event.TgtDCSUnitName, PriorityOrder } )
|
||||
end
|
||||
|
||||
for EventPriority = PriorityBegin, PriorityEnd, PriorityOrder do
|
||||
@@ -903,7 +1010,8 @@ function EVENT:onEvent( Event )
|
||||
if EventClass:IsAlive() or
|
||||
Event.id == EVENTS.PlayerEnterUnit or
|
||||
Event.id == EVENTS.Crash or
|
||||
Event.id == EVENTS.Dead then
|
||||
Event.id == EVENTS.Dead or
|
||||
Event.id == EVENTS.RemoveUnit then
|
||||
|
||||
local UnitName = EventClass:GetName()
|
||||
|
||||
@@ -953,7 +1061,8 @@ function EVENT:onEvent( Event )
|
||||
if EventClass:IsAlive() or
|
||||
Event.id == EVENTS.PlayerEnterUnit or
|
||||
Event.id == EVENTS.Crash or
|
||||
Event.id == EVENTS.Dead then
|
||||
Event.id == EVENTS.Dead or
|
||||
Event.id == EVENTS.RemoveUnit then
|
||||
|
||||
-- We can get the name of the EventClass, which is now always a GROUP object.
|
||||
local GroupName = EventClass:GetName()
|
||||
|
||||
@@ -1,7 +1,18 @@
|
||||
--- **Core** -- The **FSM** (**F**inite **S**tate **M**achine) class and derived **FSM\_** classes
|
||||
-- are design patterns allowing efficient (long-lasting) processes and workflows.
|
||||
--- **Core** - FSM (Finite State Machine) are objects that model and control long lasting business processes and workflow.
|
||||
--
|
||||
-- 
|
||||
-- ===
|
||||
--
|
||||
-- ## Features:
|
||||
--
|
||||
-- * Provide a base class to model your own state machines.
|
||||
-- * Trigger events synchronously.
|
||||
-- * Trigger events asynchronously.
|
||||
-- * Handle events before or after the event was triggered.
|
||||
-- * Handle state transitions as a result of event before and after the state change.
|
||||
-- * For internal moose purposes, further state machines have been designed:
|
||||
-- - to handle controllables (groups and units).
|
||||
-- - to handle tasks.
|
||||
-- - to handle processes.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
@@ -52,7 +63,7 @@
|
||||
--
|
||||
-- * @{#FSM_TASK}: Models Finite State Machines for @{Task}s.
|
||||
-- * @{#FSM_PROCESS}: Models Finite State Machines for @{Task} actions, which control @{Client}s.
|
||||
-- * @{#FSM_CONTROLLABLE}: Models Finite State Machines for @{Controllable}s, which are @{Group}s, @{Unit}s, @{Client}s.
|
||||
-- * @{#FSM_CONTROLLABLE}: Models Finite State Machines for @{Wrapper.Controllable}s, which are @{Wrapper.Group}s, @{Wrapper.Unit}s, @{Client}s.
|
||||
-- * @{#FSM_SET}: Models Finite State Machines for @{Set}s. Note that these FSMs control multiple objects!!! So State concerns here
|
||||
-- for multiple objects or the position of the state machine in the process.
|
||||
--
|
||||
@@ -64,7 +75,8 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module Fsm
|
||||
-- @module Core.Fsm
|
||||
-- @image Core_Finite_State_Machine.JPG
|
||||
|
||||
do -- FSM
|
||||
|
||||
@@ -72,9 +84,7 @@ do -- FSM
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
|
||||
--- # FSM class, extends @{Base#BASE}
|
||||
--
|
||||
-- A Finite State Machine (FSM) models a process flow that transitions between various **States** through triggered **Events**.
|
||||
--- A Finite State Machine (FSM) models a process flow that transitions between various **States** through triggered **Events**.
|
||||
--
|
||||
-- A FSM can only be in one of a finite number of states.
|
||||
-- The machine is in only one state at a time; the state it is in at any given time is called the **current state**.
|
||||
@@ -328,7 +338,7 @@ do -- FSM
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @field #FSM FSM
|
||||
-- @field #FSM
|
||||
--
|
||||
FSM = {
|
||||
ClassName = "FSM",
|
||||
@@ -410,7 +420,7 @@ do -- FSM
|
||||
return self._Transitions or {}
|
||||
end
|
||||
|
||||
--- Set the default @{Process} template with key ProcessName providing the ProcessClass and the process object when it is assigned to a @{Controllable} by the task.
|
||||
--- Set the default @{Process} template with key ProcessName providing the ProcessClass and the process object when it is assigned to a @{Wrapper.Controllable} by the task.
|
||||
-- @param #FSM self
|
||||
-- @param #table From Can contain a string indicating the From state or a table of strings containing multiple From states.
|
||||
-- @param #string Event The Event name.
|
||||
@@ -804,14 +814,11 @@ do -- FSM_CONTROLLABLE
|
||||
-- @field Wrapper.Controllable#CONTROLLABLE Controllable
|
||||
-- @extends Core.Fsm#FSM
|
||||
|
||||
--- # FSM_CONTROLLABLE, extends @{#FSM}
|
||||
--
|
||||
-- FSM_CONTROLLABLE class models Finite State Machines for @{Controllable}s, which are @{Group}s, @{Unit}s, @{Client}s.
|
||||
--- Models Finite State Machines for @{Wrapper.Controllable}s, which are @{Wrapper.Group}s, @{Wrapper.Unit}s, @{Client}s.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @field #FSM_CONTROLLABLE FSM_CONTROLLABLE
|
||||
--
|
||||
-- @field #FSM_CONTROLLABLE
|
||||
FSM_CONTROLLABLE = {
|
||||
ClassName = "FSM_CONTROLLABLE",
|
||||
}
|
||||
@@ -939,9 +946,7 @@ do -- FSM_PROCESS
|
||||
-- @extends Core.Fsm#FSM_CONTROLLABLE
|
||||
|
||||
|
||||
--- # FSM_PROCESS, extends @{#FSM}
|
||||
--
|
||||
-- FSM_PROCESS class models Finite State Machines for @{Task} actions, which control @{Client}s.
|
||||
--- FSM_PROCESS class models Finite State Machines for @{Task} actions, which control @{Client}s.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
@@ -988,8 +993,9 @@ do -- FSM_PROCESS
|
||||
self:T( "*** FSM *** " .. step .. " *** " .. params[1] .. " --> " .. params[2] .. " --> " .. params[3] .. " *** Task: " .. self.Task:GetName() .. ", TaskUnit: " .. self.Controllable:GetName() )
|
||||
end
|
||||
self._EventSchedules[EventName] = nil
|
||||
local Result, Value
|
||||
if self.Controllable and self.Controllable:IsAlive() == true then
|
||||
local Result, Value = xpcall( function() return self[handler]( self, self.Controllable, self.Task, unpack( params ) ) end, ErrorHandler )
|
||||
Result, Value = xpcall( function() return self[handler]( self, self.Controllable, self.Task, unpack( params ) ) end, ErrorHandler )
|
||||
end
|
||||
return Value
|
||||
--return self[handler]( self, self.Controllable, unpack( params ) )
|
||||
@@ -1116,7 +1122,7 @@ do -- FSM_PROCESS
|
||||
|
||||
|
||||
|
||||
--- Assign the process to a @{Unit} and activate the process.
|
||||
--- Assign the process to a @{Wrapper.Unit} and activate the process.
|
||||
-- @param #FSM_PROCESS self
|
||||
-- @param Task.Tasking#TASK Task
|
||||
-- @param Wrapper.Unit#UNIT ProcessUnit
|
||||
@@ -1184,9 +1190,7 @@ do -- FSM_TASK
|
||||
-- @field Tasking.Task#TASK Task
|
||||
-- @extends #FSM
|
||||
|
||||
--- # FSM_TASK, extends @{#FSM}
|
||||
--
|
||||
-- FSM_TASK class models Finite State Machines for @{Task}s.
|
||||
--- Models Finite State Machines for @{Tasking.Task}s.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
@@ -1213,10 +1217,22 @@ do -- FSM_TASK
|
||||
function FSM_TASK:_call_handler( step, trigger, params, EventName )
|
||||
local handler = step .. trigger
|
||||
|
||||
local ErrorHandler = function( errmsg )
|
||||
|
||||
env.info( "Error in SCHEDULER function:" .. errmsg )
|
||||
if BASE.Debug ~= nil then
|
||||
env.info( BASE.Debug.traceback() )
|
||||
end
|
||||
|
||||
return errmsg
|
||||
end
|
||||
|
||||
if self[handler] then
|
||||
self:T( "*** FSM *** " .. step .. " *** " .. params[1] .. " --> " .. params[2] .. " --> " .. params[3] .. " *** Task: " .. self.TaskName )
|
||||
self._EventSchedules[EventName] = nil
|
||||
return self[handler]( self, unpack( params ) )
|
||||
--return self[handler]( self, unpack( params ) )
|
||||
local Result, Value = xpcall( function() return self[handler]( self, unpack( params ) ) end, ErrorHandler )
|
||||
return Value
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1230,9 +1246,7 @@ do -- FSM_SET
|
||||
-- @extends Core.Fsm#FSM
|
||||
|
||||
|
||||
--- # FSM_SET, extends @{#FSM}
|
||||
--
|
||||
-- FSM_SET class models Finite State Machines for @{Set}s. Note that these FSMs control multiple objects!!! So State concerns here
|
||||
--- FSM_SET class models Finite State Machines for @{Set}s. Note that these FSMs control multiple objects!!! So State concerns here
|
||||
-- for multiple objects or the position of the state machine in the process.
|
||||
--
|
||||
-- ===
|
||||
|
||||
@@ -1,8 +1,16 @@
|
||||
--- **Core (WIP)** -- Base class to allow the modeling of processes to achieve Goals.
|
||||
--- **Core** - Models the process to achieve goal(s).
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- GOAL models processes that have an objective with a defined achievement. Derived classes implement the ways how the achievements can be realized.
|
||||
-- ## Features:
|
||||
--
|
||||
-- * Define the goal.
|
||||
-- * Monitor the goal achievement.
|
||||
-- * Manage goal contribution by players.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- Classes that implement a goal achievement, will derive from GOAL to implement the ways how the achievements can be realized.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
@@ -10,7 +18,9 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module Goal
|
||||
-- @module Core.Goal
|
||||
-- @image Core_Goal.JPG
|
||||
|
||||
|
||||
do -- Goal
|
||||
|
||||
@@ -18,25 +28,45 @@ do -- Goal
|
||||
-- @extends Core.Fsm#FSM
|
||||
|
||||
|
||||
--- # GOAL class, extends @{Fsm#FSM}
|
||||
--- Models processes that have an objective with a defined achievement. Derived classes implement the ways how the achievements can be realized.
|
||||
--
|
||||
-- GOAL models processes that have an objective with a defined achievement. Derived classes implement the ways how the achievements can be realized.
|
||||
--
|
||||
-- ## 1. GOAL constructor
|
||||
-- # 1. GOAL constructor
|
||||
--
|
||||
-- * @{#GOAL.New}(): Creates a new GOAL object.
|
||||
--
|
||||
-- ## 2. GOAL is a finite state machine (FSM).
|
||||
-- # 2. GOAL is a finite state machine (FSM).
|
||||
--
|
||||
-- ### 2.1 GOAL States
|
||||
-- ## 2.1. GOAL States
|
||||
--
|
||||
-- * **Pending**: The goal object is in progress.
|
||||
-- * **Achieved**: The goal objective is Achieved.
|
||||
--
|
||||
-- ### 2.2 GOAL Events
|
||||
-- ## 2.2. GOAL Events
|
||||
--
|
||||
-- * **Achieved**: Set the goal objective to Achieved.
|
||||
--
|
||||
-- # 3. Player contributions.
|
||||
--
|
||||
-- Goals are most of the time achieved by players. These player achievements can be registered as part of the goal achievement.
|
||||
-- Use @{#GOAL.AddPlayerContribution}() to add a player contribution to the goal.
|
||||
-- The player contributions are based on a points system, an internal counter per player.
|
||||
-- So once the goal has been achieved, the player contributions can be queried using @{#GOAL.GetPlayerContributions}(),
|
||||
-- that retrieves all contributions done by the players. For one player, the contribution can be queried using @{#GOAL.GetPlayerContribution}().
|
||||
-- The total amount of player contributions can be queried using @{#GOAL.GetTotalContributions}().
|
||||
--
|
||||
-- # 4. Goal achievement.
|
||||
--
|
||||
-- Once the goal is achieved, the mission designer will need to trigger the goal achievement using the **Achieved** event.
|
||||
-- The underlying 2 examples will achieve the goals for the `Goal` object:
|
||||
--
|
||||
-- Goal:Achieved() -- Achieve the goal immediately.
|
||||
-- Goal:__Achieved( 30 ) -- Achieve the goal within 30 seconds.
|
||||
--
|
||||
-- # 5. Check goal achievement.
|
||||
--
|
||||
-- The method @{#GOAL.IsAchieved}() will return true if the goal is achieved (the trigger **Achieved** was executed).
|
||||
-- You can use this method to check asynchronously if a goal has been achieved, for example using a scheduler.
|
||||
--
|
||||
-- @field #GOAL
|
||||
GOAL = {
|
||||
ClassName = "GOAL",
|
||||
@@ -108,8 +138,9 @@ do -- Goal
|
||||
end
|
||||
|
||||
|
||||
--- @param #GOAL self
|
||||
-- @param #string PlayerName
|
||||
--- Add a new contribution by a player.
|
||||
-- @param #GOAL self
|
||||
-- @param #string PlayerName The name of the player.
|
||||
function GOAL:AddPlayerContribution( PlayerName )
|
||||
self.Players[PlayerName] = self.Players[PlayerName] or 0
|
||||
self.Players[PlayerName] = self.Players[PlayerName] + 1
|
||||
@@ -124,21 +155,28 @@ do -- Goal
|
||||
end
|
||||
|
||||
|
||||
--- @param #GOAL self
|
||||
--- Get the players who contributed to achieve the goal.
|
||||
-- The result is a list of players, sorted by the name of the players.
|
||||
-- @param #GOAL self
|
||||
-- @return #list The list of players, indexed by the player name.
|
||||
function GOAL:GetPlayerContributions()
|
||||
return self.Players or {}
|
||||
end
|
||||
|
||||
|
||||
--- @param #GOAL self
|
||||
--- Gets the total contributions that happened to achieve the goal.
|
||||
-- The result is a number.
|
||||
-- @param #GOAL self
|
||||
-- @return #number The total number of contributions. 0 is returned if there were no contributions (yet).
|
||||
function GOAL:GetTotalContributions()
|
||||
return self.TotalContributions or 0
|
||||
end
|
||||
|
||||
|
||||
|
||||
--- @param #GOAL self
|
||||
-- @return #boolean true if the goal is Achieved
|
||||
--- Validates if the goal is achieved.
|
||||
-- @param #GOAL self
|
||||
-- @return #boolean true if the goal is achieved.
|
||||
function GOAL:IsAchieved()
|
||||
return self:Is( "Achieved" )
|
||||
end
|
||||
|
||||
@@ -1,7 +1,27 @@
|
||||
--- **Core** -- MENU_ classes model the definition of **hierarchical menu structures** and **commands for players** within a mission.
|
||||
--- **Core** - Manage hierarchical menu structures and commands for players within a mission.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Features:
|
||||
--
|
||||
-- * Setup mission sub menus.
|
||||
-- * Setup mission command menus.
|
||||
-- * Setup coalition sub menus.
|
||||
-- * Setup coalition command menus.
|
||||
-- * Setup group sub menus.
|
||||
-- * Setup group command menus.
|
||||
-- * Manage menu creation intelligently, avoid double menu creation.
|
||||
-- * Only create or delete menus when required, and keep existing menus persistent.
|
||||
-- * Update menu structures.
|
||||
-- * Refresh menu structures intelligently, based on a time stamp of updates.
|
||||
-- - Delete obscolete menus.
|
||||
-- - Create new one where required.
|
||||
-- - Don't touch the existing ones.
|
||||
-- * Provide a variable amount of parameters to menus.
|
||||
-- * Update the parameters and the receiving methods, without updating the menu within DCS!
|
||||
-- * Provide a great performance boost in menu management.
|
||||
-- * Provide a great tool to manage menus in your code.
|
||||
--
|
||||
-- DCS Menus can be managed using the MENU classes.
|
||||
-- The advantage of using MENU classes is that it hides the complexity of dealing with menu management in more advanced scanerios where you need to
|
||||
-- set menus and later remove them, and later set them again. You'll find while using use normal DCS scripting functions, that setting and removing
|
||||
@@ -13,15 +33,15 @@
|
||||
--
|
||||
-- ### To manage **main menus**, the classes begin with **MENU_**:
|
||||
--
|
||||
-- * @{Menu#MENU_MISSION}: Manages main menus for whole mission file.
|
||||
-- * @{Menu#MENU_COALITION}: Manages main menus for whole coalition.
|
||||
-- * @{Menu#MENU_GROUP}: Manages main menus for GROUPs.
|
||||
-- * @{Core.Menu#MENU_MISSION}: Manages main menus for whole mission file.
|
||||
-- * @{Core.Menu#MENU_COALITION}: Manages main menus for whole coalition.
|
||||
-- * @{Core.Menu#MENU_GROUP}: Manages main menus for GROUPs.
|
||||
--
|
||||
-- ### To manage **command menus**, which are menus that allow the player to issue **functions**, the classes begin with **MENU_COMMAND_**:
|
||||
--
|
||||
-- * @{Menu#MENU_MISSION_COMMAND}: Manages command menus for whole mission file.
|
||||
-- * @{Menu#MENU_COALITION_COMMAND}: Manages command menus for whole coalition.
|
||||
-- * @{Menu#MENU_GROUP_COMMAND}: Manages command menus for GROUPs.
|
||||
-- * @{Core.Menu#MENU_MISSION_COMMAND}: Manages command menus for whole mission file.
|
||||
-- * @{Core.Menu#MENU_COALITION_COMMAND}: Manages command menus for whole coalition.
|
||||
-- * @{Core.Menu#MENU_GROUP_COMMAND}: Manages command menus for GROUPs.
|
||||
--
|
||||
-- ===
|
||||
---
|
||||
@@ -30,7 +50,8 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module Menu
|
||||
-- @module Core.Menu
|
||||
-- @image Core_Menu.JPG
|
||||
|
||||
|
||||
MENU_INDEX = {}
|
||||
@@ -88,11 +109,14 @@ function MENU_INDEX:PrepareCoalition( CoalitionSide )
|
||||
self.Coalition[CoalitionSide].Menus = self.Coalition[CoalitionSide].Menus or {}
|
||||
end
|
||||
|
||||
|
||||
---
|
||||
-- @param Wrapper.Group#GROUP Group
|
||||
function MENU_INDEX:PrepareGroup( Group )
|
||||
if Group and Group:IsAlive() ~= nil then -- something was changed here!
|
||||
local GroupName = Group:GetName()
|
||||
self.Group[GroupName] = self.Group[GroupName] or {}
|
||||
self.Group[GroupName].Menus = self.Group[GroupName].Menus or {}
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -132,14 +156,17 @@ end
|
||||
|
||||
|
||||
function MENU_INDEX:HasGroupMenu( Group, Path )
|
||||
|
||||
local MenuGroupName = Group:GetName()
|
||||
return self.Group[MenuGroupName].Menus[Path]
|
||||
if Group and Group:IsAlive() then
|
||||
local MenuGroupName = Group:GetName()
|
||||
return self.Group[MenuGroupName].Menus[Path]
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function MENU_INDEX:SetGroupMenu( Group, Path, Menu )
|
||||
|
||||
local MenuGroupName = Group:GetName()
|
||||
Group:F({MenuGroupName=MenuGroupName,Path=Path})
|
||||
self.Group[MenuGroupName].Menus[Path] = Menu
|
||||
end
|
||||
|
||||
@@ -182,8 +209,7 @@ do -- MENU_BASE
|
||||
--- @type MENU_BASE
|
||||
-- @extends Base#BASE
|
||||
|
||||
--- # MENU_BASE class, extends @{Base#BASE}
|
||||
-- The MENU_BASE class defines the main MENU class where other MENU classes are derived from.
|
||||
--- Defines the main MENU class where other MENU classes are derived from.
|
||||
-- This is an abstract class, so don't use it.
|
||||
-- @field #MENU_BASE
|
||||
MENU_BASE = {
|
||||
@@ -286,9 +312,7 @@ do -- MENU_COMMAND_BASE
|
||||
-- @field #function MenuCallHandler
|
||||
-- @extends Core.Menu#MENU_BASE
|
||||
|
||||
--- # MENU_COMMAND_BASE class, extends @{Base#BASE}
|
||||
-- ----------------------------------------------------------
|
||||
-- The MENU_COMMAND_BASE class defines the main MENU class where other MENU COMMAND_
|
||||
--- Defines the main MENU class where other MENU COMMAND_
|
||||
-- classes are derived from, in order to set commands.
|
||||
--
|
||||
-- @field #MENU_COMMAND_BASE
|
||||
@@ -358,9 +382,8 @@ do -- MENU_MISSION
|
||||
--- @type MENU_MISSION
|
||||
-- @extends Core.Menu#MENU_BASE
|
||||
|
||||
--- # MENU_MISSION class, extends @{Menu#MENU_BASE}
|
||||
--- Manages the main menus for a complete mission.
|
||||
--
|
||||
-- The MENU_MISSION class manages the main menus for a complete mission.
|
||||
-- You can add menus with the @{#MENU_MISSION.New} method, which constructs a MENU_MISSION object and returns you the object reference.
|
||||
-- Using this object reference, you can then remove ALL the menus and submenus underlying automatically with @{#MENU_MISSION.Remove}.
|
||||
-- @field #MENU_MISSION
|
||||
@@ -455,9 +478,8 @@ do -- MENU_MISSION_COMMAND
|
||||
--- @type MENU_MISSION_COMMAND
|
||||
-- @extends Core.Menu#MENU_COMMAND_BASE
|
||||
|
||||
--- # MENU_MISSION_COMMAND class, extends @{Menu#MENU_COMMAND_BASE}
|
||||
--
|
||||
-- The MENU_MISSION_COMMAND class manages the command menus for a complete mission, which allow players to execute functions during mission execution.
|
||||
--- Manages the command menus for a complete mission, which allow players to execute functions during mission execution.
|
||||
--
|
||||
-- You can add menus with the @{#MENU_MISSION_COMMAND.New} method, which constructs a MENU_MISSION_COMMAND object and returns you the object reference.
|
||||
-- Using this object reference, you can then remove ALL the menus and submenus underlying automatically with @{#MENU_MISSION_COMMAND.Remove}.
|
||||
--
|
||||
@@ -469,7 +491,7 @@ do -- MENU_MISSION_COMMAND
|
||||
--- MENU_MISSION constructor. Creates a new radio command item for a complete mission file, which can invoke a function with parameters.
|
||||
-- @param #MENU_MISSION_COMMAND self
|
||||
-- @param #string MenuText The text for the menu.
|
||||
-- @param Menu#MENU_MISSION ParentMenu The parent menu.
|
||||
-- @param Core.Menu#MENU_MISSION ParentMenu The parent menu.
|
||||
-- @param CommandMenuFunction A function that is called when the menu key is pressed.
|
||||
-- @param CommandMenuArgument An argument for the function. There can only be ONE argument given. So multiple arguments must be wrapped into a table. See the below example how to do this.
|
||||
-- @return #MENU_MISSION_COMMAND self
|
||||
@@ -542,9 +564,8 @@ do -- MENU_COALITION
|
||||
--- @type MENU_COALITION
|
||||
-- @extends Core.Menu#MENU_BASE
|
||||
|
||||
--- # MENU_COALITION class, extends @{Menu#MENU_BASE}
|
||||
--- Manages the main menus for @{DCS.coalition}s.
|
||||
--
|
||||
-- The @{Menu#MENU_COALITION} class manages the main menus for coalitions.
|
||||
-- You can add menus with the @{#MENU_COALITION.New} method, which constructs a MENU_COALITION object and returns you the object reference.
|
||||
-- Using this object reference, you can then remove ALL the menus and submenus underlying automatically with @{#MENU_COALITION.Remove}.
|
||||
--
|
||||
@@ -593,7 +614,7 @@ do -- MENU_COALITION
|
||||
|
||||
--- MENU_COALITION constructor. Creates a new MENU_COALITION object and creates the menu for a complete coalition.
|
||||
-- @param #MENU_COALITION self
|
||||
-- @param Dcs.DCSCoalition#coalition.side Coalition The coalition owning the menu.
|
||||
-- @param DCS#coalition.side Coalition The coalition owning the menu.
|
||||
-- @param #string MenuText The text for the menu.
|
||||
-- @param #table ParentMenu The parent menu. This parameter can be ignored if you want the menu to be located at the perent menu of DCS world (under F10 other).
|
||||
-- @return #MENU_COALITION self
|
||||
@@ -680,9 +701,8 @@ do -- MENU_COALITION_COMMAND
|
||||
--- @type MENU_COALITION_COMMAND
|
||||
-- @extends Core.Menu#MENU_COMMAND_BASE
|
||||
|
||||
--- # MENU_COALITION_COMMAND class, extends @{Menu#MENU_COMMAND_BASE}
|
||||
--- Manages the command menus for coalitions, which allow players to execute functions during mission execution.
|
||||
--
|
||||
-- The MENU_COALITION_COMMAND class manages the command menus for coalitions, which allow players to execute functions during mission execution.
|
||||
-- You can add menus with the @{#MENU_COALITION_COMMAND.New} method, which constructs a MENU_COALITION_COMMAND object and returns you the object reference.
|
||||
-- Using this object reference, you can then remove ALL the menus and submenus underlying automatically with @{#MENU_COALITION_COMMAND.Remove}.
|
||||
--
|
||||
@@ -693,9 +713,9 @@ do -- MENU_COALITION_COMMAND
|
||||
|
||||
--- MENU_COALITION constructor. Creates a new radio command item for a coalition, which can invoke a function with parameters.
|
||||
-- @param #MENU_COALITION_COMMAND self
|
||||
-- @param Dcs.DCSCoalition#coalition.side Coalition The coalition owning the menu.
|
||||
-- @param DCS#coalition.side Coalition The coalition owning the menu.
|
||||
-- @param #string MenuText The text for the menu.
|
||||
-- @param Menu#MENU_COALITION ParentMenu The parent menu.
|
||||
-- @param Core.Menu#MENU_COALITION ParentMenu The parent menu.
|
||||
-- @param CommandMenuFunction A function that is called when the menu key is pressed.
|
||||
-- @param CommandMenuArgument An argument for the function. There can only be ONE argument given. So multiple arguments must be wrapped into a table. See the below example how to do this.
|
||||
-- @return #MENU_COALITION_COMMAND
|
||||
@@ -780,9 +800,8 @@ do
|
||||
-- @extends Core.Menu#MENU_BASE
|
||||
|
||||
|
||||
--- #MENU_GROUP class, extends @{Menu#MENU_BASE}
|
||||
--- Manages the main menus for @{Wrapper.Group}s.
|
||||
--
|
||||
-- The MENU_GROUP class manages the main menus for coalitions.
|
||||
-- You can add menus with the @{#MENU_GROUP.New} method, which constructs a MENU_GROUP object and returns you the object reference.
|
||||
-- Using this object reference, you can then remove ALL the menus and submenus underlying automatically with @{#MENU_GROUP.Remove}.
|
||||
--
|
||||
@@ -938,9 +957,7 @@ do
|
||||
--- @type MENU_GROUP_COMMAND
|
||||
-- @extends Core.Menu#MENU_COMMAND_BASE
|
||||
|
||||
--- # MENU_GROUP_COMMAND class, extends @{Menu#MENU_COMMAND_BASE}
|
||||
--
|
||||
-- The @{Menu#MENU_GROUP_COMMAND} class manages the command menus for coalitions, which allow players to execute functions during mission execution.
|
||||
--- The @{Core.Menu#MENU_GROUP_COMMAND} class manages the command menus for coalitions, which allow players to execute functions during mission execution.
|
||||
-- You can add menus with the @{#MENU_GROUP_COMMAND.New} method, which constructs a MENU_GROUP_COMMAND object and returns you the object reference.
|
||||
-- Using this object reference, you can then remove ALL the menus and submenus underlying automatically with @{#MENU_GROUP_COMMAND.Remove}.
|
||||
--
|
||||
@@ -1035,9 +1052,7 @@ do
|
||||
-- @extends Core.Menu#MENU_BASE
|
||||
|
||||
|
||||
--- #MENU_GROUP_DELAYED class, extends @{Menu#MENU_BASE}
|
||||
--
|
||||
-- The MENU_GROUP_DELAYED class manages the main menus for groups.
|
||||
--- The MENU_GROUP_DELAYED class manages the main menus for groups.
|
||||
-- You can add menus with the @{#MENU_GROUP.New} method, which constructs a MENU_GROUP object and returns you the object reference.
|
||||
-- Using this object reference, you can then remove ALL the menus and submenus underlying automatically with @{#MENU_GROUP.Remove}.
|
||||
-- The creation of the menu item is delayed however, and must be created using the @{#MENU_GROUP.Set} method.
|
||||
@@ -1171,9 +1186,8 @@ do
|
||||
--- @type MENU_GROUP_COMMAND_DELAYED
|
||||
-- @extends Core.Menu#MENU_COMMAND_BASE
|
||||
|
||||
--- # MENU_GROUP_COMMAND_DELAYED class, extends @{Menu#MENU_COMMAND_BASE}
|
||||
--- Manages the command menus for coalitions, which allow players to execute functions during mission execution.
|
||||
--
|
||||
-- The @{Menu#MENU_GROUP_COMMAND_DELAYED} class manages the command menus for coalitions, which allow players to execute functions during mission execution.
|
||||
-- You can add menus with the @{#MENU_GROUP_COMMAND_DELAYED.New} method, which constructs a MENU_GROUP_COMMAND_DELAYED object and returns you the object reference.
|
||||
-- Using this object reference, you can then remove ALL the menus and submenus underlying automatically with @{#MENU_GROUP_COMMAND_DELAYED.Remove}.
|
||||
--
|
||||
|
||||
@@ -1,43 +1,51 @@
|
||||
--- **Core** -- MESSAGE class takes are of the **real-time notifications** and **messages to players** during a simulation.
|
||||
--
|
||||
-- 
|
||||
--- **Core** - Informs the players using messages during a simulation.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module Message
|
||||
-- ## Features:
|
||||
--
|
||||
-- * A more advanced messaging system using the DCS message system.
|
||||
-- * Time messages.
|
||||
-- * Send messages based on a message type, which has a pre-defined duration that can be tweaked in SETTINGS.
|
||||
-- * Send message to all players.
|
||||
-- * Send messages to a coalition.
|
||||
-- * Send messages to a specific group.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module Core.Message
|
||||
-- @image Core_Message.JPG
|
||||
|
||||
--- The MESSAGE class
|
||||
-- @type MESSAGE
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
--- # MESSAGE class, extends @{Base#BASE}
|
||||
--
|
||||
-- Message System to display Messages to Clients, Coalitions or All.
|
||||
--- Message System to display Messages to Clients, Coalitions or All.
|
||||
-- Messages are shown on the display panel for an amount of seconds, and will then disappear.
|
||||
-- Messages can contain a category which is indicating the category of the message.
|
||||
--
|
||||
-- ## MESSAGE construction
|
||||
--
|
||||
-- Messages are created with @{Message#MESSAGE.New}. Note that when the MESSAGE object is created, no message is sent yet.
|
||||
-- Messages are created with @{#MESSAGE.New}. Note that when the MESSAGE object is created, no message is sent yet.
|
||||
-- To send messages, you need to use the To functions.
|
||||
--
|
||||
-- ## Send messages to an audience
|
||||
--
|
||||
-- Messages are sent:
|
||||
--
|
||||
-- * To a @{Client} using @{Message#MESSAGE.ToClient}().
|
||||
-- * To a @{Group} using @{Message#MESSAGE.ToGroup}()
|
||||
-- * To a coalition using @{Message#MESSAGE.ToCoalition}().
|
||||
-- * To the red coalition using @{Message#MESSAGE.ToRed}().
|
||||
-- * To the blue coalition using @{Message#MESSAGE.ToBlue}().
|
||||
-- * To all Players using @{Message#MESSAGE.ToAll}().
|
||||
-- * To a @{Client} using @{#MESSAGE.ToClient}().
|
||||
-- * To a @{Wrapper.Group} using @{#MESSAGE.ToGroup}()
|
||||
-- * To a coalition using @{#MESSAGE.ToCoalition}().
|
||||
-- * To the red coalition using @{#MESSAGE.ToRed}().
|
||||
-- * To the blue coalition using @{#MESSAGE.ToBlue}().
|
||||
-- * To all Players using @{#MESSAGE.ToAll}().
|
||||
--
|
||||
-- ## Send conditionally to an audience
|
||||
--
|
||||
-- Messages can be sent conditionally to an audience (when a condition is true):
|
||||
--
|
||||
-- * To all players using @{Message#MESSAGE.ToAllIf}().
|
||||
-- * To a coalition using @{Message#MESSAGE.ToCoalitionIf}().
|
||||
-- * To all players using @{#MESSAGE.ToAllIf}().
|
||||
-- * To a coalition using @{#MESSAGE.ToCoalitionIf}().
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
@@ -69,6 +77,7 @@ MESSAGE.Type = {
|
||||
-- @param #string MessageText is the text of the Message.
|
||||
-- @param #number MessageDuration is a number in seconds of how long the MESSAGE should be shown on the display panel.
|
||||
-- @param #string MessageCategory (optional) is a string expressing the "category" of the Message. The category will be shown as the first text in the message followed by a ": ".
|
||||
-- @param #boolean ClearScreen (optional) Clear all previous messages if true.
|
||||
-- @return #MESSAGE
|
||||
-- @usage
|
||||
-- -- Create a series of new Messages.
|
||||
@@ -80,7 +89,7 @@ MESSAGE.Type = {
|
||||
-- MessageRED = MESSAGE:New( "To the RED Players: You receive a penalty because you've killed one of your own units", 25, "Penalty" )
|
||||
-- MessageClient1 = MESSAGE:New( "Congratulations, you've just hit a target", 25, "Score" )
|
||||
-- MessageClient2 = MESSAGE:New( "Congratulations, you've just killed a target", 25, "Score")
|
||||
function MESSAGE:New( MessageText, MessageDuration, MessageCategory )
|
||||
function MESSAGE:New( MessageText, MessageDuration, MessageCategory, ClearScreen )
|
||||
local self = BASE:Inherit( self, BASE:New() )
|
||||
self:F( { MessageText, MessageDuration, MessageCategory } )
|
||||
|
||||
@@ -97,6 +106,11 @@ function MESSAGE:New( MessageText, MessageDuration, MessageCategory )
|
||||
else
|
||||
self.MessageCategory = ""
|
||||
end
|
||||
|
||||
self.ClearScreen=false
|
||||
if ClearScreen~=nil then
|
||||
self.ClearScreen=ClearScreen
|
||||
end
|
||||
|
||||
self.MessageDuration = MessageDuration or 5
|
||||
self.MessageTime = timer.getTime()
|
||||
@@ -117,18 +131,24 @@ end
|
||||
-- @param self
|
||||
-- @param #string MessageText is the text of the Message.
|
||||
-- @param #MESSAGE.Type MessageType The type of the message.
|
||||
-- @param #boolean ClearScreen (optional) Clear all previous messages.
|
||||
-- @return #MESSAGE
|
||||
-- @usage
|
||||
-- MessageAll = MESSAGE:NewType( "To all Players: BLUE has won! Each player of BLUE wins 50 points!", MESSAGE.Type.Information )
|
||||
-- MessageRED = MESSAGE:NewType( "To the RED Players: You receive a penalty because you've killed one of your own units", MESSAGE.Type.Information )
|
||||
-- MessageClient1 = MESSAGE:NewType( "Congratulations, you've just hit a target", MESSAGE.Type.Update )
|
||||
-- MessageClient2 = MESSAGE:NewType( "Congratulations, you've just killed a target", MESSAGE.Type.Update )
|
||||
function MESSAGE:NewType( MessageText, MessageType )
|
||||
function MESSAGE:NewType( MessageText, MessageType, ClearScreen )
|
||||
|
||||
local self = BASE:Inherit( self, BASE:New() )
|
||||
self:F( { MessageText } )
|
||||
|
||||
self.MessageType = MessageType
|
||||
|
||||
self.ClearScreen=false
|
||||
if ClearScreen~=nil then
|
||||
self.ClearScreen=ClearScreen
|
||||
end
|
||||
|
||||
self.MessageTime = timer.getTime()
|
||||
self.MessageText = MessageText:gsub("^\n","",1):gsub("\n$","",1)
|
||||
@@ -138,11 +158,21 @@ end
|
||||
|
||||
|
||||
|
||||
--- Clears all previous messages from the screen before the new message is displayed. Not that this must come before all functions starting with ToX(), e.g. ToAll(), ToGroup() etc.
|
||||
-- @param #MESSAGE self
|
||||
-- @return #MESSAGE
|
||||
function MESSAGE:Clear()
|
||||
self:F()
|
||||
self.ClearScreen=true
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
|
||||
--- Sends a MESSAGE to a Client Group. Note that the Group needs to be defined within the ME with the skillset "Client" or "Player".
|
||||
-- @param #MESSAGE self
|
||||
-- @param Wrapper.Client#CLIENT Client is the Group of the Client.
|
||||
-- @param Core.Settings#SETTINGS Settings Settings used to display the message.
|
||||
-- @return #MESSAGE
|
||||
-- @usage
|
||||
-- -- Send the 2 messages created with the @{New} method to the Client Group.
|
||||
@@ -173,7 +203,7 @@ function MESSAGE:ToClient( Client, Settings )
|
||||
if self.MessageDuration ~= 0 then
|
||||
local ClientGroupID = Client:GetClientGroupID()
|
||||
self:T( self.MessageCategory .. self.MessageText:gsub("\n$",""):gsub("\n$","") .. " / " .. self.MessageDuration )
|
||||
trigger.action.outTextForGroup( ClientGroupID, self.MessageCategory .. self.MessageText:gsub("\n$",""):gsub("\n$",""), self.MessageDuration )
|
||||
trigger.action.outTextForGroup( ClientGroupID, self.MessageCategory .. self.MessageText:gsub("\n$",""):gsub("\n$",""), self.MessageDuration , self.ClearScreen)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -182,8 +212,8 @@ end
|
||||
|
||||
--- Sends a MESSAGE to a Group.
|
||||
-- @param #MESSAGE self
|
||||
-- @param Wrapper.Group#GROUP Group is the Group.
|
||||
-- @return #MESSAGE
|
||||
-- @param Wrapper.Group#GROUP Group to which the message is displayed.
|
||||
-- @return #MESSAGE Message object.
|
||||
function MESSAGE:ToGroup( Group, Settings )
|
||||
self:F( Group.GroupName )
|
||||
|
||||
@@ -197,7 +227,7 @@ function MESSAGE:ToGroup( Group, Settings )
|
||||
|
||||
if self.MessageDuration ~= 0 then
|
||||
self:T( self.MessageCategory .. self.MessageText:gsub("\n$",""):gsub("\n$","") .. " / " .. self.MessageDuration )
|
||||
trigger.action.outTextForGroup( Group:GetID(), self.MessageCategory .. self.MessageText:gsub("\n$",""):gsub("\n$",""), self.MessageDuration )
|
||||
trigger.action.outTextForGroup( Group:GetID(), self.MessageCategory .. self.MessageText:gsub("\n$",""):gsub("\n$",""), self.MessageDuration, self.ClearScreen )
|
||||
end
|
||||
end
|
||||
|
||||
@@ -243,8 +273,9 @@ end
|
||||
|
||||
--- Sends a MESSAGE to a Coalition.
|
||||
-- @param #MESSAGE self
|
||||
-- @param CoalitionSide needs to be filled out by the defined structure of the standard scripting engine @{coalition.side}.
|
||||
-- @return #MESSAGE
|
||||
-- @param #DCS.coalition.side CoalitionSide @{#DCS.coalition.side} to which the message is displayed.
|
||||
-- @param Core.Settings#SETTINGS Settings (Optional) Settings for message display.
|
||||
-- @return #MESSAGE Message object.
|
||||
-- @usage
|
||||
-- -- Send a message created with the @{New} method to the RED coalition.
|
||||
-- MessageRED = MESSAGE:New( "To the RED Players: You receive a penalty because you've killed one of your own units", "Penalty", 25, "Score" ):ToCoalition( coalition.side.RED )
|
||||
@@ -265,7 +296,7 @@ function MESSAGE:ToCoalition( CoalitionSide, Settings )
|
||||
if CoalitionSide then
|
||||
if self.MessageDuration ~= 0 then
|
||||
self:T( self.MessageCategory .. self.MessageText:gsub("\n$",""):gsub("\n$","") .. " / " .. self.MessageDuration )
|
||||
trigger.action.outTextForCoalition( CoalitionSide, self.MessageText:gsub("\n$",""):gsub("\n$",""), self.MessageDuration )
|
||||
trigger.action.outTextForCoalition( CoalitionSide, self.MessageText:gsub("\n$",""):gsub("\n$",""), self.MessageDuration, self.ClearScreen )
|
||||
end
|
||||
end
|
||||
|
||||
@@ -274,8 +305,9 @@ end
|
||||
|
||||
--- Sends a MESSAGE to a Coalition if the given Condition is true.
|
||||
-- @param #MESSAGE self
|
||||
-- @param CoalitionSide needs to be filled out by the defined structure of the standard scripting engine @{coalition.side}.
|
||||
-- @return #MESSAGE
|
||||
-- @param CoalitionSide needs to be filled out by the defined structure of the standard scripting engine @{coalition.side}.
|
||||
-- @param #boolean Condition Sends the message only if the condition is true.
|
||||
-- @return #MESSAGE self
|
||||
function MESSAGE:ToCoalitionIf( CoalitionSide, Condition )
|
||||
self:F( CoalitionSide )
|
||||
|
||||
@@ -288,6 +320,7 @@ end
|
||||
|
||||
--- Sends a MESSAGE to all players.
|
||||
-- @param #MESSAGE self
|
||||
-- @param Core.Settings#Settings Settings (Optional) Settings for message display.
|
||||
-- @return #MESSAGE
|
||||
-- @usage
|
||||
-- -- Send a message created to all players.
|
||||
@@ -297,7 +330,7 @@ end
|
||||
-- or
|
||||
-- MessageAll = MESSAGE:New( "To all Players: BLUE has won! Each player of BLUE wins 50 points!", "End of Mission", 25, "Win" )
|
||||
-- MessageAll:ToAll()
|
||||
function MESSAGE:ToAll()
|
||||
function MESSAGE:ToAll(Settings)
|
||||
self:F()
|
||||
|
||||
if self.MessageType then
|
||||
@@ -308,7 +341,7 @@ function MESSAGE:ToAll()
|
||||
|
||||
if self.MessageDuration ~= 0 then
|
||||
self:T( self.MessageCategory .. self.MessageText:gsub("\n$",""):gsub("\n$","") .. " / " .. self.MessageDuration )
|
||||
trigger.action.outText( self.MessageCategory .. self.MessageText:gsub("\n$",""):gsub("\n$",""), self.MessageDuration )
|
||||
trigger.action.outText( self.MessageCategory .. self.MessageText:gsub("\n$",""):gsub("\n$",""), self.MessageDuration, self.ClearScreen )
|
||||
end
|
||||
|
||||
return self
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,11 @@
|
||||
--- **Core** -- The RADIO Module is responsible for everything that is related to radio transmission and you can hear in DCS, be it TACAN beacons, Radio transmissions...
|
||||
--
|
||||
-- 
|
||||
--- **Core** - Is responsible for everything that is related to radio transmission and you can hear in DCS, be it TACAN beacons, Radio transmissions.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ## Features:
|
||||
--
|
||||
-- * Provide radio functionality to broadcast radio transmissions.
|
||||
-- * Provide beacon functionality to assist pilots.
|
||||
--
|
||||
-- The Radio contains 2 classes : RADIO and BEACON
|
||||
--
|
||||
@@ -18,10 +21,10 @@
|
||||
-- * They need to be added in .\l10n\DEFAULT\ in you .miz file (wich can be decompressed like a .zip file),
|
||||
-- * For simplicty sake, you can **let DCS' Mission Editor add the file** itself, by creating a new Trigger with the action "Sound to Country", and choosing your sound file and a country you don't use in your mission.
|
||||
--
|
||||
-- Due to weird DCS quirks, **radio communications behave differently** if sent by a @{Unit#UNIT} or a @{Group#GROUP} or by any other @{Positionable#POSITIONABLE}
|
||||
-- Due to weird DCS quirks, **radio communications behave differently** if sent by a @{Wrapper.Unit#UNIT} or a @{Wrapper.Group#GROUP} or by any other @{Wrapper.Positionable#POSITIONABLE}
|
||||
--
|
||||
-- * If the transmitter is a @{Unit#UNIT} or a @{Group#GROUP}, DCS will set the power of the transmission automatically,
|
||||
-- * If the transmitter is any other @{Positionable#POSITIONABLE}, the transmisison can't be subtitled or looped.
|
||||
-- * If the transmitter is a @{Wrapper.Unit#UNIT} or a @{Wrapper.Group#GROUP}, DCS will set the power of the transmission automatically,
|
||||
-- * If the transmitter is any other @{Wrapper.Positionable#POSITIONABLE}, the transmisison can't be subtitled or looped.
|
||||
--
|
||||
-- Note that obviously, the **frequency** and the **modulation** of the transmission are important only if the players are piloting an **Advanced System Modelling** enabled aircraft,
|
||||
-- like the A10C or the Mirage 2000C. They will **hear the transmission** if they are tuned on the **right frequency and modulation** (and if they are close enough - more on that below).
|
||||
@@ -32,39 +35,40 @@
|
||||
--
|
||||
-- ### Author: Hugues "Grey_Echo" Bousquet
|
||||
--
|
||||
-- @module Radio
|
||||
-- @module Core.Radio
|
||||
-- @image Core_Radio.JPG
|
||||
|
||||
|
||||
--- # RADIO class, extends @{Base#BASE}
|
||||
--- Models the radio capabilty.
|
||||
--
|
||||
-- ## RADIO usage
|
||||
--
|
||||
-- There are 3 steps to a successful radio transmission.
|
||||
--
|
||||
-- * First, you need to **"add a @{#RADIO} object** to your @{Positionable#POSITIONABLE}. This is done using the @{Positionable#POSITIONABLE.GetRadio}() function,
|
||||
-- * First, you need to **"add a @{#RADIO} object** to your @{Wrapper.Positionable#POSITIONABLE}. This is done using the @{Wrapper.Positionable#POSITIONABLE.GetRadio}() function,
|
||||
-- * Then, you will **set the relevant parameters** to the transmission (see below),
|
||||
-- * When done, you can actually **broadcast the transmission** (i.e. play the sound) with the @{RADIO.Broadcast}() function.
|
||||
--
|
||||
-- Methods to set relevant parameters for both a @{Unit#UNIT} or a @{Group#GROUP} or any other @{Positionable#POSITIONABLE}
|
||||
-- Methods to set relevant parameters for both a @{Wrapper.Unit#UNIT} or a @{Wrapper.Group#GROUP} or any other @{Wrapper.Positionable#POSITIONABLE}
|
||||
--
|
||||
-- * @{#RADIO.SetFileName}() : Sets the file name of your sound file (e.g. "Noise.ogg"),
|
||||
-- * @{#RADIO.SetFrequency}() : Sets the frequency of your transmission.
|
||||
-- * @{#RADIO.SetModulation}() : Sets the modulation of your transmission.
|
||||
-- * @{#RADIO.SetLoop}() : Choose if you want the transmission to be looped. If you need your transmission to be looped, you might need a @{#BEACON} instead...
|
||||
--
|
||||
-- Additional Methods to set relevant parameters if the transmiter is a @{Unit#UNIT} or a @{Group#GROUP}
|
||||
-- Additional Methods to set relevant parameters if the transmiter is a @{Wrapper.Unit#UNIT} or a @{Wrapper.Group#GROUP}
|
||||
--
|
||||
-- * @{#RADIO.SetSubtitle}() : Set both the subtitle and its duration,
|
||||
-- * @{#RADIO.NewUnitTransmission}() : Shortcut to set all the relevant parameters in one method call
|
||||
--
|
||||
-- Additional Methods to set relevant parameters if the transmiter is any other @{Positionable#POSITIONABLE}
|
||||
-- Additional Methods to set relevant parameters if the transmiter is any other @{Wrapper.Positionable#POSITIONABLE}
|
||||
--
|
||||
-- * @{#RADIO.SetPower}() : Sets the power of the antenna in Watts
|
||||
-- * @{#RADIO.NewGenericTransmission}() : Shortcut to set all the relevant parameters in one method call
|
||||
--
|
||||
-- What is this power thing ?
|
||||
--
|
||||
-- * If your transmission is sent by a @{Positionable#POSITIONABLE} other than a @{Unit#UNIT} or a @{Group#GROUP}, you can set the power of the antenna,
|
||||
-- * If your transmission is sent by a @{Wrapper.Positionable#POSITIONABLE} other than a @{Wrapper.Unit#UNIT} or a @{Wrapper.Group#GROUP}, you can set the power of the antenna,
|
||||
-- * Otherwise, DCS sets it automatically, depending on what's available on your Unit,
|
||||
-- * If the player gets **too far** from the transmiter, or if the antenna is **too weak**, the transmission will **fade** and **become noisyer**,
|
||||
-- * This an automated DCS calculation you have no say on,
|
||||
@@ -93,7 +97,7 @@ RADIO = {
|
||||
}
|
||||
|
||||
--- Create a new RADIO Object. This doesn't broadcast a transmission, though, use @{#RADIO.Broadcast} to actually broadcast
|
||||
-- If you want to create a RADIO, you probably should use @{Positionable#POSITIONABLE.GetRadio}() instead
|
||||
-- If you want to create a RADIO, you probably should use @{Wrapper.Positionable#POSITIONABLE.GetRadio}() instead
|
||||
-- @param #RADIO self
|
||||
-- @param Wrapper.Positionable#POSITIONABLE Positionable The @{Positionable} that will receive radio capabilities.
|
||||
-- @return #RADIO Radio
|
||||
@@ -262,7 +266,7 @@ end
|
||||
|
||||
--- Create a new transmission, that is to say, populate the RADIO with relevant data
|
||||
-- In this function the data is especially relevant if the broadcaster is a UNIT or a GROUP,
|
||||
-- but it will work for any @{Positionable#POSITIONABLE}.
|
||||
-- but it will work for any @{Wrapper.Positionable#POSITIONABLE}.
|
||||
-- Only the RADIO and the Filename are mandatory.
|
||||
-- @param #RADIO self
|
||||
-- @param #string FileName
|
||||
@@ -276,8 +280,12 @@ function RADIO:NewUnitTransmission(FileName, Subtitle, SubtitleDuration, Frequen
|
||||
self:F({FileName, Subtitle, SubtitleDuration, Frequency, Modulation, Loop})
|
||||
|
||||
self:SetFileName(FileName)
|
||||
if Subtitle then self:SetSubtitle(Subtitle) end
|
||||
if SubtitleDuration then self:SetSubtitleDuration(SubtitleDuration) end
|
||||
local Duration = 5
|
||||
if SubtitleDuration then Duration = SubtitleDuration end
|
||||
-- SubtitleDuration argument was missing, adding it
|
||||
if Subtitle then self:SetSubtitle(Subtitle, Duration) end
|
||||
-- self:SetSubtitleDuration is non existent, removing faulty line
|
||||
-- if SubtitleDuration then self:SetSubtitleDuration(SubtitleDuration) end
|
||||
if Frequency then self:SetFrequency(Frequency) end
|
||||
if Modulation then self:SetModulation(Modulation) end
|
||||
if Loop then self:SetLoop(Loop) end
|
||||
@@ -287,7 +295,7 @@ end
|
||||
|
||||
--- Actually Broadcast the transmission
|
||||
-- * The Radio has to be populated with the new transmission before broadcasting.
|
||||
-- * Please use RADIO setters or either @{Radio#RADIO.NewGenericTransmission} or @{Radio#RADIO.NewUnitTransmission}
|
||||
-- * Please use RADIO setters or either @{#RADIO.NewGenericTransmission} or @{#RADIO.NewUnitTransmission}
|
||||
-- * This class is in fact pretty smart, it determines the right DCS function to use depending on the type of POSITIONABLE
|
||||
-- * If the POSITIONABLE is not a UNIT or a GROUP, we use the generic (but limited) trigger.action.radioTransmission()
|
||||
-- * If the POSITIONABLE is a UNIT or a GROUP, we use the "TransmitMessage" Command
|
||||
@@ -339,22 +347,20 @@ function RADIO:StopBroadcast()
|
||||
end
|
||||
|
||||
|
||||
--- # BEACON class, extends @{Base#BASE}
|
||||
--
|
||||
-- After attaching a @{#BEACON} to your @{Positionable#POSITIONABLE}, you need to select the right function to activate the kind of beacon you want.
|
||||
--- After attaching a @{#BEACON} to your @{Wrapper.Positionable#POSITIONABLE}, you need to select the right function to activate the kind of beacon you want.
|
||||
-- There are two types of BEACONs available : the AA TACAN Beacon and the general purpose Radio Beacon.
|
||||
-- Note that in both case, you can set an optional parameter : the `BeaconDuration`. This can be very usefull to simulate the battery time if your BEACON is
|
||||
-- attach to a cargo crate, for exemple.
|
||||
--
|
||||
-- ## AA TACAN Beacon usage
|
||||
--
|
||||
-- This beacon only works with airborne @{Unit#UNIT} or a @{Group#GROUP}. Use @{#BEACON:AATACAN}() to set the beacon parameters and start the beacon.
|
||||
-- This beacon only works with airborne @{Wrapper.Unit#UNIT} or a @{Wrapper.Group#GROUP}. Use @{#BEACON:AATACAN}() to set the beacon parameters and start the beacon.
|
||||
-- Use @#BEACON:StopAATACAN}() to stop it.
|
||||
--
|
||||
-- ## General Purpose Radio Beacon usage
|
||||
--
|
||||
-- This beacon will work with any @{Positionable#POSITIONABLE}, but **it won't follow the @{Positionable#POSITIONABLE}** ! This means that you should only use it with
|
||||
-- @{Positionable#POSITIONABLE} that don't move, or move very slowly. Use @{#BEACON:RadioBeacon}() to set the beacon parameters and start the beacon.
|
||||
-- This beacon will work with any @{Wrapper.Positionable#POSITIONABLE}, but **it won't follow the @{Wrapper.Positionable#POSITIONABLE}** ! This means that you should only use it with
|
||||
-- @{Wrapper.Positionable#POSITIONABLE} that don't move, or move very slowly. Use @{#BEACON:RadioBeacon}() to set the beacon parameters and start the beacon.
|
||||
-- Use @{#BEACON:StopRadioBeacon}() to stop it.
|
||||
--
|
||||
-- @type BEACON
|
||||
@@ -364,7 +370,7 @@ BEACON = {
|
||||
}
|
||||
|
||||
--- Create a new BEACON Object. This doesn't activate the beacon, though, use @{#BEACON.AATACAN} or @{#BEACON.Generic}
|
||||
-- If you want to create a BEACON, you probably should use @{Positionable#POSITIONABLE.GetBeacon}() instead.
|
||||
-- If you want to create a BEACON, you probably should use @{Wrapper.Positionable#POSITIONABLE.GetBeacon}() instead.
|
||||
-- @param #BEACON self
|
||||
-- @param Wrapper.Positionable#POSITIONABLE Positionable The @{Positionable} that will receive radio capabilities.
|
||||
-- @return #BEACON Beacon
|
||||
|
||||
@@ -1,6 +1,26 @@
|
||||
--- The REPORT class
|
||||
-- @type REPORT
|
||||
--- **Core** - Provides a handy means to create messages and reports.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ## Features:
|
||||
--
|
||||
-- * Create text blocks that are formatted.
|
||||
-- * Create automatic indents.
|
||||
-- * Variate the delimiters between reporting lines.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Authors: FlightControl : Design & Programming
|
||||
--
|
||||
-- @module Core.Report
|
||||
-- @image Core_Report.JPG
|
||||
|
||||
|
||||
--- @type REPORT
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
--- Provides a handy means to create messages and reports.
|
||||
-- @field #REPORT
|
||||
REPORT = {
|
||||
ClassName = "REPORT",
|
||||
Title = "",
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
--
|
||||
-- The SCHEDULEDISPATCHER allows multiple scheduled functions to be planned and executed for one SCHEDULER object.
|
||||
-- The SCHEDULER object therefore keeps a table of "CallID's", which are returned after each planning of a new scheduled function by the SCHEDULEDISPATCHER.
|
||||
-- The SCHEDULER object plans new scheduled functions through the @{Scheduler#SCHEDULER.Schedule}() method.
|
||||
-- The SCHEDULER object plans new scheduled functions through the @{Core.Scheduler#SCHEDULER.Schedule}() method.
|
||||
-- The Schedule() method returns the CallID that is the reference ID for each planned schedule.
|
||||
--
|
||||
-- ===
|
||||
@@ -30,7 +30,8 @@
|
||||
-- ### Contributions: -
|
||||
-- ### Authors: FlightControl : Design & Programming
|
||||
--
|
||||
-- @module ScheduleDispatcher
|
||||
-- @module Core.ScheduleDispatcher
|
||||
-- @image Core_Schedule_Dispatcher.JPG
|
||||
|
||||
--- The SCHEDULEDISPATCHER structure
|
||||
-- @type SCHEDULEDISPATCHER
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
--- **Core** -- SCHEDULER prepares and handles the **execution of functions over scheduled time (intervals)**.
|
||||
--- **Core** - Prepares and handles the execution of functions over scheduled time (intervals).
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- SCHEDULER manages the **scheduling of functions**:
|
||||
-- ## Features:
|
||||
--
|
||||
-- * optionally in an optional specified time interval,
|
||||
-- * optionally **repeating** with a specified time repeat interval,
|
||||
-- * optionally **randomizing** with a specified time interval randomization factor,
|
||||
-- * optionally **stop** the repeating after a specified time interval.
|
||||
-- * Schedule functions over time,
|
||||
-- * optionally in an optional specified time interval,
|
||||
-- * optionally **repeating** with a specified time repeat interval,
|
||||
-- * optionally **randomizing** with a specified time interval randomization factor,
|
||||
-- * optionally **stop** the repeating after a specified time interval.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
@@ -39,8 +38,8 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module Scheduler
|
||||
|
||||
-- @module Core.Scheduler
|
||||
-- @image Core_Scheduler.JPG
|
||||
|
||||
--- The SCHEDULER class
|
||||
-- @type SCHEDULER
|
||||
@@ -48,9 +47,7 @@
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
|
||||
--- # SCHEDULER class, extends @{Base#BASE}
|
||||
--
|
||||
-- The SCHEDULER class creates schedule.
|
||||
--- Creates and handles schedules over time, which allow to execute code at specific time intervals with randomization.
|
||||
--
|
||||
-- A SCHEDULER can manage **multiple** (repeating) schedules. Each planned or executing schedule has a unique **ScheduleID**.
|
||||
-- The ScheduleID is returned when the method @{#SCHEDULER.Schedule}() is called.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,9 +1,19 @@
|
||||
--- **Core** -- Manages various settings for MOOSE classes.
|
||||
--
|
||||
-- 
|
||||
--- **Core** - Manages various settings for running missions, consumed by moose classes and provides a menu system for players to tweak settings in running missions.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ## Features:
|
||||
--
|
||||
-- * Provide a settings menu system to the players.
|
||||
-- * Provide a player settings menu and an overall mission settings menu.
|
||||
-- * Mission settings provide default settings, while player settings override mission settings.
|
||||
-- * Provide a menu to select between different coordinate formats for A2G coordinates.
|
||||
-- * Provide a menu to select between different coordinate formats for A2A coordinates.
|
||||
-- * Provide a menu to select between different message time duration options.
|
||||
-- * Provide a menu to select between different metric systems.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- The documentation of the SETTINGS class can be found further in this document.
|
||||
--
|
||||
-- ===
|
||||
@@ -16,21 +26,17 @@
|
||||
--
|
||||
-- * **FlightControl**: Design & Programming
|
||||
--
|
||||
-- @module Settings
|
||||
-- @module Core.Settings
|
||||
-- @image Core_Settings.JPG
|
||||
|
||||
|
||||
--- @type SETTINGS
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
--- # SETTINGS class, extends @{Base#BASE}
|
||||
-- The SETTINGS class takes care of various settings that influence the behaviour of certain functionalities and classes within the MOOSE framework.
|
||||
--- Takes care of various settings that influence the behaviour of certain functionalities and classes within the MOOSE framework.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- The SETTINGS class takes care of various settings that influence the behaviour of certain functionalities and classes within the MOOSE framework.
|
||||
-- SETTINGS can work on 2 levels:
|
||||
--
|
||||
@@ -39,29 +45,29 @@
|
||||
--
|
||||
-- So, when there isn't any **Player setting** defined for a player for a specific setting, or, the player cannot be identified, the **Default setting** will be used instead.
|
||||
--
|
||||
-- ## 1. \_SETTINGS object
|
||||
-- # 1) \_SETTINGS object
|
||||
--
|
||||
-- MOOSE defines by default a singleton object called **\_SETTINGS**. Use this object to modify all the **Default settings** for a running mission.
|
||||
-- For each player, MOOSE will automatically allocate also a **player settings** object, and will expose a radio menu to allow the player to adapt the settings to his own preferences.
|
||||
--
|
||||
-- ## 2. SETTINGS Menu
|
||||
-- # 2) SETTINGS Menu
|
||||
--
|
||||
-- Settings can be adapted by the Players and by the Mission Administrator through **radio menus, which are automatically available in the mission**.
|
||||
-- These menus can be found **on level F10 under "Settings"**. There are two kinds of menus generated by the system.
|
||||
--
|
||||
-- ### 2.1. Default settings menu
|
||||
-- ## 2.1) Default settings menu
|
||||
--
|
||||
-- A menu is created automatically per Command Center that allows to modify the **Default** settings.
|
||||
-- So, when joining a CC unit, a menu will be available that allows to change the settings parameters **FOR ALL THE PLAYERS**!
|
||||
-- Note that the **Default settings** will only be used when a player has not choosen its own settings.
|
||||
--
|
||||
-- ### 2.2. Player settings menu
|
||||
-- ## 2.2) Player settings menu
|
||||
--
|
||||
-- A menu is created automatically per Player Slot (group) that allows to modify the **Player** settings.
|
||||
-- So, when joining a slot, a menu wil be available that allows to change the settings parameters **FOR THE PLAYER ONLY**!
|
||||
-- Note that when a player has not chosen a specific setting, the **Default settings** will be used.
|
||||
--
|
||||
-- ### 2.3. Show or Hide the Player Setting menus
|
||||
-- ## 2.3) Show or Hide the Player Setting menus
|
||||
--
|
||||
-- Of course, it may be requried not to show any setting menus. In this case, a method is available on the **\_SETTINGS object**.
|
||||
-- Use @{#SETTINGS.SetPlayerMenuOff}() to hide the player menus, and use @{#SETTINGS.SetPlayerMenuOn}() show the player menus.
|
||||
@@ -75,14 +81,14 @@
|
||||
-- -- But only when a player exits and reenters the slot these settings will have effect!
|
||||
--
|
||||
--
|
||||
-- ## 3. Settings
|
||||
-- # 3) Settings
|
||||
--
|
||||
-- There are different settings that are managed and applied within the MOOSE framework.
|
||||
-- See below a comprehensive description of each.
|
||||
--
|
||||
-- ### 3.1. **A2G coordinates** display formatting
|
||||
-- ## 3.1) **A2G coordinates** display formatting
|
||||
--
|
||||
-- #### 3.1.1. A2G coordinates setting **types**
|
||||
-- ### 3.1.1) A2G coordinates setting **types**
|
||||
--
|
||||
-- Will customize which display format is used to indicate A2G coordinates in text as part of the Command Center communications.
|
||||
--
|
||||
@@ -91,11 +97,11 @@
|
||||
-- - A2G LL DMS: Lattitude Longitude [Degrees Minutes Seconds](https://en.wikipedia.org/wiki/Geographic_coordinate_conversion). The accuracy can also be adapted.
|
||||
-- - A2G LL DDM: Lattitude Longitude [Decimal Degrees Minutes](https://en.wikipedia.org/wiki/Decimal_degrees). The accuracy can also be adapted.
|
||||
--
|
||||
-- #### 3.1.2. A2G coordinates setting **menu**
|
||||
-- ### 3.1.2) A2G coordinates setting **menu**
|
||||
--
|
||||
-- The settings can be changed by using the **Default settings menu** on the Command Center or the **Player settings menu** on the Player Slot.
|
||||
--
|
||||
-- #### 3.1.3. A2G coordinates setting **methods**
|
||||
-- ### 3.1.3) A2G coordinates setting **methods**
|
||||
--
|
||||
-- There are different methods that can be used to change the **System settings** using the \_SETTINGS object.
|
||||
--
|
||||
@@ -104,14 +110,14 @@
|
||||
-- - @{#SETTINGS.SetA2G_LL_DMS}(): Enable the LL DMS display formatting by default. Use @{SETTINGS.SetLL_Accuracy}() to adapt the accuracy of the Seconds formatting.
|
||||
-- - @{#SETTINGS.SetA2G_LL_DDM}(): Enable the LL DDM display formatting by default. Use @{SETTINGS.SetLL_Accuracy}() to adapt the accuracy of the Seconds formatting.
|
||||
--
|
||||
-- #### 3.1.4. A2G coordinates setting - additional notes
|
||||
-- ### 3.1.4) A2G coordinates setting - additional notes
|
||||
--
|
||||
-- One additional note on BR. In a situation when a BR coordinate should be given,
|
||||
-- but there isn't any player context (no player unit to reference from), the MGRS formatting will be applied!
|
||||
--
|
||||
-- ### 3.2. **A2A coordinates** formatting
|
||||
-- ## 3.2) **A2A coordinates** formatting
|
||||
--
|
||||
-- #### 3.2.1. A2A coordinates setting **types**
|
||||
-- ### 3.2.1) A2A coordinates setting **types**
|
||||
--
|
||||
-- Will customize which display format is used to indicate A2A coordinates in text as part of the Command Center communications.
|
||||
--
|
||||
@@ -121,11 +127,11 @@
|
||||
-- - A2A LL DDM: Lattitude Longitude [Decimal Degrees and Minutes](https://en.wikipedia.org/wiki/Decimal_degrees). The accuracy can also be adapted.
|
||||
-- - A2A BULLS: [Bullseye](http://falcon4.wikidot.com/concepts:bullseye).
|
||||
--
|
||||
-- #### 3.2.2. A2A coordinates setting **menu**
|
||||
-- ### 3.2.2) A2A coordinates setting **menu**
|
||||
--
|
||||
-- The settings can be changed by using the **Default settings menu** on the Command Center or the **Player settings menu** on the Player Slot.
|
||||
--
|
||||
-- #### 3.2.3. A2A coordinates setting **methods**
|
||||
-- ### 3.2.3) A2A coordinates setting **methods**
|
||||
--
|
||||
-- There are different methods that can be used to change the **System settings** using the \_SETTINGS object.
|
||||
--
|
||||
@@ -135,34 +141,34 @@
|
||||
-- - @{#SETTINGS.SetA2A_LL_DDM}(): Enable the LL DDM display formatting by default. Use @{SETTINGS.SetLL_Accuracy}() to adapt the accuracy of the Seconds formatting.
|
||||
-- - @{#SETTINGS.SetA2A_BULLS}(): Enable the BULLSeye display formatting by default.
|
||||
--
|
||||
-- #### 3.2.4. A2A coordinates settings - additional notes
|
||||
-- ### 3.2.4) A2A coordinates settings - additional notes
|
||||
--
|
||||
-- One additional note on BRAA. In a situation when a BRAA coordinate should be given,
|
||||
-- but there isn't any player context (no player unit to reference from), the MGRS formatting will be applied!
|
||||
--
|
||||
-- ### 3.3. **Measurements** formatting
|
||||
-- ## 3.3) **Measurements** formatting
|
||||
--
|
||||
-- #### 3.3.1. Measurements setting **types**
|
||||
-- ### 3.3.1) Measurements setting **types**
|
||||
--
|
||||
-- Will customize the measurements system being used as part as part of the Command Center communications.
|
||||
--
|
||||
-- - **Metrics** system: Applies the [Metrics system](https://en.wikipedia.org/wiki/Metric_system) ...
|
||||
-- - **Imperial** system: Applies the [Imperial system](https://en.wikipedia.org/wiki/Imperial_units) ...
|
||||
--
|
||||
-- #### 3.3.2. Measurements setting **menu**
|
||||
-- ### 3.3.2) Measurements setting **menu**
|
||||
--
|
||||
-- The settings can be changed by using the **Default settings menu** on the Command Center or the **Player settings menu** on the Player Slot.
|
||||
--
|
||||
-- #### 3.3.3. Measurements setting **methods**
|
||||
-- ### 3.3.3) Measurements setting **methods**
|
||||
--
|
||||
-- There are different methods that can be used to change the **Default settings** using the \_SETTINGS object.
|
||||
--
|
||||
-- - @{#SETTINGS.SetMetric}(): Enable the Metric system.
|
||||
-- - @{#SETTINGS.SetImperial}(): Enable the Imperial system.
|
||||
--
|
||||
-- ### 3.4. **Message** display times
|
||||
-- ## 3.4) **Message** display times
|
||||
--
|
||||
-- #### 3.4.1. Message setting **types**
|
||||
-- ### 3.4.1) Message setting **types**
|
||||
--
|
||||
-- There are various **Message Types** that will influence the duration how long a message will appear as part of the Command Center communications.
|
||||
--
|
||||
@@ -172,7 +178,7 @@
|
||||
-- - **Overview report**: Provides a short report overview, the summary of the report.
|
||||
-- - **Detailed report**: Provides a complete report.
|
||||
--
|
||||
-- #### 3.4.2. Message setting **menu**
|
||||
-- ### 3.4.2) Message setting **menu**
|
||||
--
|
||||
-- The settings can be changed by using the **Default settings menu** on the Command Center or the **Player settings menu** on the Player Slot.
|
||||
--
|
||||
@@ -181,7 +187,7 @@
|
||||
-- So the player can choose its own amount of seconds how long a message should be displayed of a certain type.
|
||||
-- Note that **Update** messages can be chosen not to be displayed at all!
|
||||
--
|
||||
-- #### 3.4.3. Message setting **methods**
|
||||
-- ### 3.4.3) Message setting **methods**
|
||||
--
|
||||
-- There are different methods that can be used to change the **System settings** using the \_SETTINGS object.
|
||||
--
|
||||
@@ -370,7 +376,6 @@ do -- SETTINGS
|
||||
-- @param #SETTINGS self
|
||||
-- @return #boolean true if BRA
|
||||
function SETTINGS:IsA2A_BRAA()
|
||||
self:E( { BRA = ( self.A2ASystem and self.A2ASystem == "BRAA" ) or ( not self.A2ASystem and _SETTINGS:IsA2A_BRAA() ) } )
|
||||
return ( self.A2ASystem and self.A2ASystem == "BRAA" ) or ( not self.A2ASystem and _SETTINGS:IsA2A_BRAA() )
|
||||
end
|
||||
|
||||
@@ -729,7 +734,7 @@ do -- SETTINGS
|
||||
end
|
||||
|
||||
--- Removes the player menu from the PlayerUnit.
|
||||
--- @param #SETTINGS self
|
||||
-- @param #SETTINGS self
|
||||
-- @param Wrapper.Client#CLIENT PlayerUnit
|
||||
-- @return #SETTINGS self
|
||||
function SETTINGS:RemovePlayerMenu( PlayerUnit )
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,14 @@
|
||||
--- **Core** -- Spawn dynamically new STATICs in your missions.
|
||||
--- **Core** - Spawn new statics in your running missions.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- SPAWNSTATIC spawns static structures in your missions dynamically. See below the SPAWNSTATIC class documentation.
|
||||
-- ## Features:
|
||||
--
|
||||
-- * Spawn new statics from a static already defined using the mission editor.
|
||||
-- * Spawn new statics from a given template.
|
||||
-- * Spawn new statics from a given type.
|
||||
-- * Spawn with a custom heading and location.
|
||||
-- * Spawn within a zone.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
@@ -29,7 +33,8 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module SpawnStatic
|
||||
-- @module Core.SpawnStatic
|
||||
-- @image Core_Spawnstatic.JPG
|
||||
|
||||
|
||||
|
||||
@@ -37,9 +42,7 @@
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
|
||||
--- # SPAWNSTATIC class, extends @{Base#BASE}
|
||||
--
|
||||
-- The SPAWNSTATIC class allows to spawn dynamically new @{Static}s.
|
||||
--- Allows to spawn dynamically new @{Static}s.
|
||||
-- Through creating a copy of an existing static object template as defined in the Mission Editor (ME),
|
||||
-- SPAWNSTATIC can retireve the properties of the defined static object template (like type, category etc), and "copy"
|
||||
-- these properties to create a new static object and place it at the desired coordinate.
|
||||
@@ -80,20 +83,22 @@ SPAWNSTATIC = {
|
||||
--- Creates the main object to spawn a @{Static} defined in the ME.
|
||||
-- @param #SPAWNSTATIC self
|
||||
-- @param #string SpawnTemplatePrefix is the name of the Group in the ME that defines the Template. Each new group will have the name starting with SpawnTemplatePrefix.
|
||||
-- @param DCS#country.id SpawnCountryID The ID of the country.
|
||||
-- @param DCS#coalition.side SpawnCoalitionID The ID of the coalition.
|
||||
-- @return #SPAWNSTATIC
|
||||
function SPAWNSTATIC:NewFromStatic( SpawnTemplatePrefix, SpawnCountryID ) --R2.1
|
||||
function SPAWNSTATIC:NewFromStatic( SpawnTemplatePrefix, SpawnCountryID, SpawnCoalitionID )
|
||||
local self = BASE:Inherit( self, BASE:New() ) -- #SPAWNSTATIC
|
||||
self:F( { SpawnTemplatePrefix } )
|
||||
|
||||
local TemplateStatic, CoalitionID, CategoryID, CountryID = _DATABASE:GetStaticUnitTemplate( SpawnTemplatePrefix )
|
||||
local TemplateStatic, CoalitionID, CategoryID, CountryID = _DATABASE:GetStaticGroupTemplate( SpawnTemplatePrefix )
|
||||
if TemplateStatic then
|
||||
self.SpawnTemplatePrefix = SpawnTemplatePrefix
|
||||
self.CountryID = SpawnCountryID or CountryID
|
||||
self.CategoryID = CategoryID
|
||||
self.CoalitionID = CoalitionID
|
||||
self.CoalitionID = SpawnCoalitionID or CoalitionID
|
||||
self.SpawnIndex = 0
|
||||
else
|
||||
error( "SPAWNSTATIC:New: There is no group declared in the mission editor with SpawnTemplatePrefix = '" .. SpawnTemplatePrefix .. "'" )
|
||||
error( "SPAWNSTATIC:New: There is no static declared in the mission editor with SpawnTemplatePrefix = '" .. SpawnTemplatePrefix .. "'" )
|
||||
end
|
||||
|
||||
self:SetEventPriority( 5 )
|
||||
@@ -105,12 +110,13 @@ end
|
||||
-- @param #SPAWNSTATIC self
|
||||
-- @param #string SpawnTypeName is the name of the type.
|
||||
-- @return #SPAWNSTATIC
|
||||
function SPAWNSTATIC:NewFromType( SpawnTypeName, SpawnShapeName, SpawnCategory, CountryID ) --R2.1
|
||||
function SPAWNSTATIC:NewFromType( SpawnTypeName, SpawnShapeName, SpawnCategory, SpawnCountryID, SpawnCoalitionID )
|
||||
local self = BASE:Inherit( self, BASE:New() ) -- #SPAWNSTATIC
|
||||
self:F( { SpawnTypeName } )
|
||||
|
||||
self.SpawnTypeName = SpawnTypeName
|
||||
self.CountryID = CountryID
|
||||
self.CountryID = SpawnCountryID
|
||||
self.CoalitionID = SpawnCoalitionID
|
||||
self.SpawnIndex = 0
|
||||
|
||||
self:SetEventPriority( 5 )
|
||||
@@ -127,32 +133,28 @@ end
|
||||
function SPAWNSTATIC:Spawn( Heading, NewName ) --R2.3
|
||||
self:F( { Heading, NewName } )
|
||||
|
||||
local StaticTemplate = _DATABASE:GetStaticUnitTemplate( self.SpawnTemplatePrefix )
|
||||
local StaticTemplate, CoalitionID, CategoryID, CountryID = _DATABASE:GetStaticGroupTemplate( self.SpawnTemplatePrefix )
|
||||
|
||||
if StaticTemplate then
|
||||
|
||||
local CountryID = self.CountryID
|
||||
local CountryName = _DATABASE.COUNTRY_NAME[CountryID]
|
||||
local StaticUnitTemplate = StaticTemplate.units[1]
|
||||
|
||||
StaticTemplate.name = NewName or string.format("%s#%05d", self.SpawnTemplatePrefix, self.SpawnIndex )
|
||||
StaticTemplate.heading = ( Heading / 180 ) * math.pi
|
||||
|
||||
StaticTemplate.CountryID = nil
|
||||
StaticTemplate.CoalitionID = nil
|
||||
StaticTemplate.CategoryID = nil
|
||||
|
||||
local Static = coalition.addStaticObject( CountryID, StaticTemplate )
|
||||
_DATABASE:_RegisterStaticTemplate( StaticTemplate, CoalitionID, CategoryID, CountryID )
|
||||
|
||||
local Static = coalition.addStaticObject( self.CountryID or CountryID, StaticTemplate.units[1] )
|
||||
|
||||
self.SpawnIndex = self.SpawnIndex + 1
|
||||
|
||||
return Static
|
||||
return _DATABASE:FindStatic(Static:getName())
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
|
||||
--- Creates a new @{Static} from a POINT_VEC2.
|
||||
-- @param #SPAWNSTATIC self
|
||||
-- @param Core.Point#POINT_VEC2 PointVec2 The 2D coordinate where to spawn the static.
|
||||
@@ -162,64 +164,53 @@ end
|
||||
function SPAWNSTATIC:SpawnFromPointVec2( PointVec2, Heading, NewName ) --R2.1
|
||||
self:F( { PointVec2, Heading, NewName } )
|
||||
|
||||
local StaticTemplate = _DATABASE:GetStaticUnitTemplate( self.SpawnTemplatePrefix )
|
||||
local StaticTemplate, CoalitionID, CategoryID, CountryID = _DATABASE:GetStaticGroupTemplate( self.SpawnTemplatePrefix )
|
||||
|
||||
if StaticTemplate then
|
||||
|
||||
local CountryID = self.CountryID
|
||||
local CountryName = _DATABASE.COUNTRY_NAME[CountryID]
|
||||
|
||||
StaticTemplate.x = PointVec2.x
|
||||
StaticTemplate.y = PointVec2.z
|
||||
|
||||
StaticTemplate.units = nil
|
||||
local StaticUnitTemplate = StaticTemplate.units[1]
|
||||
|
||||
StaticUnitTemplate.x = PointVec2.x
|
||||
StaticUnitTemplate.y = PointVec2.z
|
||||
|
||||
StaticTemplate.route = nil
|
||||
StaticTemplate.groupId = nil
|
||||
|
||||
StaticTemplate.name = NewName or string.format("%s#%05d", self.SpawnTemplatePrefix, self.SpawnIndex )
|
||||
StaticTemplate.heading = ( Heading / 180 ) * math.pi
|
||||
StaticUnitTemplate.name = StaticTemplate.name
|
||||
StaticUnitTemplate.heading = ( Heading / 180 ) * math.pi
|
||||
|
||||
StaticTemplate.CountryID = nil
|
||||
StaticTemplate.CoalitionID = nil
|
||||
StaticTemplate.CategoryID = nil
|
||||
_DATABASE:_RegisterStaticTemplate( StaticTemplate, CoalitionID, CategoryID, CountryID)
|
||||
|
||||
local Static = coalition.addStaticObject( CountryID, StaticTemplate )
|
||||
self:F({StaticTemplate = StaticTemplate})
|
||||
|
||||
local Static = coalition.addStaticObject( self.CountryID or CountryID, StaticTemplate.units[1] )
|
||||
|
||||
self.SpawnIndex = self.SpawnIndex + 1
|
||||
|
||||
return Static
|
||||
|
||||
return _DATABASE:FindStatic(Static:getName())
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
--- Creates the original @{Static} at a POINT_VEC2.
|
||||
--- Respawns the original @{Static}.
|
||||
-- @param #SPAWNSTATIC self
|
||||
-- @param Core.Point#POINT_VEC2 PointVec2 The 2D coordinate where to spawn the static.
|
||||
-- @param #number Heading The heading of the static, which is a number in degrees from 0 to 360.
|
||||
-- @param #string (optional) The name of the new static.
|
||||
-- @return #SPAWNSTATIC
|
||||
function SPAWNSTATIC:ReSpawn()
|
||||
|
||||
local StaticTemplate = _DATABASE:GetStaticUnitTemplate( self.SpawnTemplatePrefix )
|
||||
local StaticTemplate, CoalitionID, CategoryID, CountryID = _DATABASE:GetStaticGroupTemplate( self.SpawnTemplatePrefix )
|
||||
|
||||
if StaticTemplate then
|
||||
|
||||
local CountryID = self.CountryID
|
||||
local CountryName = _DATABASE.COUNTRY_NAME[CountryID]
|
||||
|
||||
StaticTemplate.units = nil
|
||||
local StaticUnitTemplate = StaticTemplate.units[1]
|
||||
StaticTemplate.route = nil
|
||||
StaticTemplate.groupId = nil
|
||||
|
||||
StaticTemplate.CountryID = nil
|
||||
StaticTemplate.CoalitionID = nil
|
||||
StaticTemplate.CategoryID = nil
|
||||
local Static = coalition.addStaticObject( self.CountryID or CountryID, StaticTemplate.units[1] )
|
||||
|
||||
local Static = coalition.addStaticObject( CountryID, StaticTemplate )
|
||||
|
||||
return Static
|
||||
return _DATABASE:FindStatic(Static:getName())
|
||||
end
|
||||
|
||||
return nil
|
||||
@@ -233,24 +224,20 @@ end
|
||||
-- @return #SPAWNSTATIC
|
||||
function SPAWNSTATIC:ReSpawnAt( Coordinate, Heading )
|
||||
|
||||
local StaticTemplate = _DATABASE:GetStaticUnitTemplate( self.SpawnTemplatePrefix )
|
||||
local StaticTemplate, CoalitionID, CategoryID, CountryID = _DATABASE:GetStaticGroupTemplate( self.SpawnTemplatePrefix )
|
||||
|
||||
if StaticTemplate then
|
||||
|
||||
local CountryID = self.CountryID
|
||||
|
||||
StaticTemplate.x = Coordinate.x
|
||||
StaticTemplate.y = Coordinate.z
|
||||
local StaticUnitTemplate = StaticTemplate.units[1]
|
||||
|
||||
StaticUnitTemplate.x = Coordinate.x
|
||||
StaticUnitTemplate.y = Coordinate.z
|
||||
|
||||
StaticTemplate.heading = Heading and ( ( Heading / 180 ) * math.pi ) or StaticTemplate.heading
|
||||
|
||||
StaticTemplate.CountryID = nil
|
||||
StaticTemplate.CoalitionID = nil
|
||||
StaticTemplate.CategoryID = nil
|
||||
StaticUnitTemplate.heading = Heading and ( ( Heading / 180 ) * math.pi ) or StaticTemplate.heading
|
||||
|
||||
local Static = coalition.addStaticObject( CountryID, StaticTemplate )
|
||||
local Static = coalition.addStaticObject( self.CountryID or CountryID, StaticTemplate.units[1] )
|
||||
|
||||
return Static
|
||||
return _DATABASE:FindStatic(Static:getName())
|
||||
end
|
||||
|
||||
return nil
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
--- **Core** -- Management of SPOT logistics, that can be transported from and to transportation carriers.
|
||||
--
|
||||
-- 
|
||||
--- **Core** - Management of spotting logistics, that can be activated and deactivated upon command.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- SPOT implements the DCS Spot class functionality, but adds additional luxury to be able to:
|
||||
--
|
||||
-- * Spot for a defined duration.
|
||||
-- * wiggle the spot at the target.
|
||||
-- * Provide a @{Unit} as a target, instead of a point.
|
||||
-- * Updates of laer spot position every 0.2 seconds for moving targets.
|
||||
-- * Wiggle the spot at the target.
|
||||
-- * Provide a @{Wrapper.Unit} as a target, instead of a point.
|
||||
-- * Implement a status machine, LaseOn, LaseOff.
|
||||
--
|
||||
-- ===
|
||||
@@ -38,7 +37,8 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module Spot
|
||||
-- @module Core.Spot
|
||||
-- @image Core_Spot.JPG
|
||||
|
||||
|
||||
do
|
||||
@@ -47,13 +47,12 @@ do
|
||||
-- @extends Core.Fsm#FSM
|
||||
|
||||
|
||||
--- # SPOT class, extends @{Fsm#FSM}
|
||||
--
|
||||
-- SPOT implements the DCS Spot class functionality, but adds additional luxury to be able to:
|
||||
--- Implements the target spotting or marking functionality, but adds additional luxury to be able to:
|
||||
--
|
||||
-- * Mark targets for a defined duration.
|
||||
-- * wiggle the spot at the target.
|
||||
-- * Provide a @{Unit} as a target, instead of a point.
|
||||
-- * Updates of laer spot position every 0.2 seconds for moving targets.
|
||||
-- * Wiggle the spot at the target.
|
||||
-- * Provide a @{Wrapper.Unit} as a target, instead of a point.
|
||||
-- * Implement a status machine, LaseOn, LaseOff.
|
||||
--
|
||||
-- ## 1. SPOT constructor
|
||||
@@ -88,9 +87,7 @@ do
|
||||
|
||||
--- SPOT Constructor.
|
||||
-- @param #SPOT self
|
||||
-- @param Wrapper.Unit#UNIT Recce
|
||||
-- @param #number LaserCode
|
||||
-- @param #number Duration
|
||||
-- @param Wrapper.Unit#UNIT Recce Unit that is lasing
|
||||
-- @return #SPOT
|
||||
function SPOT:New( Recce )
|
||||
|
||||
@@ -118,12 +115,17 @@ do
|
||||
--- LaseOn Trigger for SPOT
|
||||
-- @function [parent=#SPOT] LaseOn
|
||||
-- @param #SPOT self
|
||||
-- @param Wrapper.Positionable#POSITIONABLE Target
|
||||
-- @param #number LaserCode Laser code.
|
||||
-- @param #number Duration Duration of lasing in seconds.
|
||||
|
||||
--- LaseOn Asynchronous Trigger for SPOT
|
||||
-- @function [parent=#SPOT] __LaseOn
|
||||
-- @param #SPOT self
|
||||
-- @param #number Delay
|
||||
|
||||
-- @param Wrapper.Positionable#POSITIONABLE Target
|
||||
-- @param #number LaserCode Laser code.
|
||||
-- @param #number Duration Duration of lasing in seconds.
|
||||
|
||||
|
||||
self:AddTransition( "On", "Lasing", "On" )
|
||||
@@ -196,9 +198,9 @@ do
|
||||
-- @param From
|
||||
-- @param Event
|
||||
-- @param To
|
||||
-- @param Wrapper.Positionable#POSITIONABLE Target
|
||||
-- @param #number LaserCode
|
||||
-- @param #number Duration
|
||||
-- @param Wrapper.Positionable#POSITIONABLE Target Unit that is being lased.
|
||||
-- @param #number LaserCode Laser code.
|
||||
-- @param #number Duration Duration of lasing in seconds.
|
||||
function SPOT:onafterLaseOn( From, Event, To, Target, LaserCode, Duration )
|
||||
self:F( { "LaseOn", Target, LaserCode, Duration } )
|
||||
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
--- **Core (WIP)** -- Manage user flags.
|
||||
--- **Core** - Manage user flags to interact with the mission editor trigger system and server side scripts.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- Management of DCS User Flags.
|
||||
-- ## Features:
|
||||
--
|
||||
-- * Set or get DCS user flags within running missions.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
@@ -10,7 +12,9 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module UserFlag
|
||||
-- @module Core.UserFlag
|
||||
-- @image Core_Userflag.JPG
|
||||
--
|
||||
|
||||
do -- UserFlag
|
||||
|
||||
@@ -18,11 +22,9 @@ do -- UserFlag
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
|
||||
--- # USERFLAG class, extends @{Base#BASE}
|
||||
--- Management of DCS User Flags.
|
||||
--
|
||||
-- Management of DCS User Flags.
|
||||
--
|
||||
-- ## 1. USERFLAG constructor
|
||||
-- # 1. USERFLAG constructor
|
||||
--
|
||||
-- * @{#USERFLAG.New}(): Creates a new USERFLAG object.
|
||||
--
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
--- **Core (WIP)** -- Manage user sound.
|
||||
--- **Core** - Manage user sound.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ## Features:
|
||||
--
|
||||
-- * Play sounds wihtin running missions.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- Management of DCS User Sound.
|
||||
--
|
||||
-- ===
|
||||
@@ -10,7 +16,8 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module UserSound
|
||||
-- @module Core.UserSound
|
||||
-- @image Core_Usersound.JPG
|
||||
|
||||
do -- UserSound
|
||||
|
||||
@@ -18,11 +25,9 @@ do -- UserSound
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
|
||||
--- # USERSOUND class, extends @{Base#BASE}
|
||||
--- Management of DCS User Sound.
|
||||
--
|
||||
-- Management of DCS User Sound.
|
||||
--
|
||||
-- ## 1. USERSOUND constructor
|
||||
-- ## USERSOUND constructor
|
||||
--
|
||||
-- * @{#USERSOUND.New}(): Creates a new USERSOUND object.
|
||||
--
|
||||
@@ -80,7 +85,7 @@ do -- UserSound
|
||||
|
||||
--- Play the usersound to the given coalition.
|
||||
-- @param #USERSOUND self
|
||||
-- @param Dcs.DCScoalition#coalition Coalition The coalition to play the usersound to.
|
||||
-- @param DCS#coalition Coalition The coalition to play the usersound to.
|
||||
-- @return #USERSOUND The usersound instance.
|
||||
-- @usage
|
||||
-- local BlueVictory = USERSOUND:New( "BlueVictory.ogg" )
|
||||
@@ -96,7 +101,7 @@ do -- UserSound
|
||||
|
||||
--- Play the usersound to the given country.
|
||||
-- @param #USERSOUND self
|
||||
-- @param Dcs.DCScountry#country Country The country to play the usersound to.
|
||||
-- @param DCS#country Country The country to play the usersound to.
|
||||
-- @return #USERSOUND The usersound instance.
|
||||
-- @usage
|
||||
-- local BlueVictory = USERSOUND:New( "BlueVictory.ogg" )
|
||||
@@ -110,9 +115,9 @@ do -- UserSound
|
||||
end
|
||||
|
||||
|
||||
--- Play the usersound to the given @{Group}.
|
||||
--- Play the usersound to the given @{Wrapper.Group}.
|
||||
-- @param #USERSOUND self
|
||||
-- @param Wrapper.Group#GROUP Group The @{Group} to play the usersound to.
|
||||
-- @param Wrapper.Group#GROUP Group The @{Wrapper.Group} to play the usersound to.
|
||||
-- @return #USERSOUND The usersound instance.
|
||||
-- @usage
|
||||
-- local BlueVictory = USERSOUND:New( "BlueVictory.ogg" )
|
||||
|
||||
@@ -1,13 +1,22 @@
|
||||
--- **Core** -- VELOCITY models a speed, which can be expressed in various formats according the Settings.
|
||||
--- **Core** - Models a velocity or speed, which can be expressed in various formats according the settings.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ## Features:
|
||||
--
|
||||
-- * Convert velocity in various metric systems.
|
||||
-- * Set the velocity.
|
||||
-- * Create a text in a specific format of a velocity.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **FlightControl**
|
||||
-- ### Contributions:
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module Velocity
|
||||
-- @module Core.Velocity
|
||||
-- @image MOOSE.JPG
|
||||
|
||||
do -- Velocity
|
||||
|
||||
@@ -15,11 +24,9 @@ do -- Velocity
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
|
||||
--- # VELOCITY class, extends @{Base#BASE}
|
||||
--- VELOCITY models a speed, which can be expressed in various formats according the Settings.
|
||||
--
|
||||
-- VELOCITY models a speed, which can be expressed in various formats according the Settings.
|
||||
--
|
||||
-- ## 1. VELOCITY constructor
|
||||
-- ## VELOCITY constructor
|
||||
--
|
||||
-- * @{#VELOCITY.New}(): Creates a new VELOCITY object.
|
||||
--
|
||||
@@ -125,7 +132,7 @@ do -- VELOCITY_POSITIONABLE
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
|
||||
--- # VELOCITY_POSITIONABLE class, extends @{Base#BASE}
|
||||
--- # VELOCITY_POSITIONABLE class, extends @{Core.Base#BASE}
|
||||
--
|
||||
-- VELOCITY_POSITIONABLE monitors the speed of an @{Positionable} in the simulation, which can be expressed in various formats according the Settings.
|
||||
--
|
||||
|
||||
@@ -1,9 +1,24 @@
|
||||
--- **Core** -- ZONE classes define **zones** within your mission of **various forms**, with **various capabilities**.
|
||||
--
|
||||
-- 
|
||||
--- **Core** - Define zones within your mission of various forms, with various capabilities.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ## Features:
|
||||
--
|
||||
-- * Create radius zones.
|
||||
-- * Create trigger zones.
|
||||
-- * Create polygon zones.
|
||||
-- * Create moving zones around a unit.
|
||||
-- * Create moving zones around a group.
|
||||
-- * Provide the zone behaviour. Some zones are static, while others are moveable.
|
||||
-- * Enquiry if a coordinate is within a zone.
|
||||
-- * Smoke zones.
|
||||
-- * Set a zone probability to control zone selection.
|
||||
-- * Get zone coordinates.
|
||||
-- * Get zone properties.
|
||||
-- * Get zone bounding box.
|
||||
-- * Set/get zone name.
|
||||
--
|
||||
--
|
||||
-- There are essentially two core functions that zones accomodate:
|
||||
--
|
||||
-- * Test if an object is within the zone boundaries.
|
||||
@@ -12,7 +27,7 @@
|
||||
-- The object classes are using the zone classes to test the zone boundaries, which can take various forms:
|
||||
--
|
||||
-- * Test if completely within the zone.
|
||||
-- * Test if partly within the zone (for @{Group#GROUP} objects).
|
||||
-- * Test if partly within the zone (for @{Wrapper.Group#GROUP} objects).
|
||||
-- * Test if not in the zone.
|
||||
-- * Distance to the nearest intersecting point of the zone.
|
||||
-- * Distance to the center of the zone.
|
||||
@@ -23,9 +38,9 @@
|
||||
-- * @{#ZONE_BASE}: The ZONE_BASE class defining the base for all other zone classes.
|
||||
-- * @{#ZONE_RADIUS}: The ZONE_RADIUS class defined by a zone name, a location and a radius.
|
||||
-- * @{#ZONE}: The ZONE class, defined by the zone name as defined within the Mission Editor.
|
||||
-- * @{#ZONE_UNIT}: The ZONE_UNIT class defines by a zone around a @{Unit#UNIT} with a radius.
|
||||
-- * @{#ZONE_GROUP}: The ZONE_GROUP class defines by a zone around a @{Group#GROUP} with a radius.
|
||||
-- * @{#ZONE_POLYGON}: The ZONE_POLYGON class defines by a sequence of @{Group#GROUP} waypoints within the Mission Editor, forming a polygon.
|
||||
-- * @{#ZONE_UNIT}: The ZONE_UNIT class defines by a zone around a @{Wrapper.Unit#UNIT} with a radius.
|
||||
-- * @{#ZONE_GROUP}: The ZONE_GROUP class defines by a zone around a @{Wrapper.Group#GROUP} with a radius.
|
||||
-- * @{#ZONE_POLYGON}: The ZONE_POLYGON class defines by a sequence of @{Wrapper.Group#GROUP} waypoints within the Mission Editor, forming a polygon.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
@@ -34,7 +49,8 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module Zone
|
||||
-- @module Core.Zone
|
||||
-- @image Core_Zones.JPG
|
||||
|
||||
|
||||
--- @type ZONE_BASE
|
||||
@@ -43,9 +59,7 @@
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
|
||||
--- # ZONE_BASE class, extends @{Base#BASE}
|
||||
--
|
||||
-- This class is an abstract BASE class for derived classes, and is not meant to be instantiated.
|
||||
--- This class is an abstract BASE class for derived classes, and is not meant to be instantiated.
|
||||
--
|
||||
-- ## Each zone has a name:
|
||||
--
|
||||
@@ -53,7 +67,7 @@
|
||||
-- * @{#ZONE_BASE.SetName}(): Sets the name of the zone.
|
||||
--
|
||||
--
|
||||
-- ## Each zone implements two polymorphic functions defined in @{Zone#ZONE_BASE}:
|
||||
-- ## Each zone implements two polymorphic functions defined in @{Core.Zone#ZONE_BASE}:
|
||||
--
|
||||
-- * @{#ZONE_BASE.IsVec2InZone}(): Returns if a 2D vector is within the zone.
|
||||
-- * @{#ZONE_BASE.IsVec3InZone}(): Returns if a 3D vector is within the zone.
|
||||
@@ -95,10 +109,10 @@ ZONE_BASE = {
|
||||
|
||||
--- The ZONE_BASE.BoundingSquare
|
||||
-- @type ZONE_BASE.BoundingSquare
|
||||
-- @field Dcs.DCSTypes#Distance x1 The lower x coordinate (left down)
|
||||
-- @field Dcs.DCSTypes#Distance y1 The lower y coordinate (left down)
|
||||
-- @field Dcs.DCSTypes#Distance x2 The higher x coordinate (right up)
|
||||
-- @field Dcs.DCSTypes#Distance y2 The higher y coordinate (right up)
|
||||
-- @field DCS#Distance x1 The lower x coordinate (left down)
|
||||
-- @field DCS#Distance y1 The lower y coordinate (left down)
|
||||
-- @field DCS#Distance x2 The higher x coordinate (right up)
|
||||
-- @field DCS#Distance y2 The higher y coordinate (right up)
|
||||
|
||||
|
||||
--- ZONE_BASE constructor
|
||||
@@ -138,7 +152,7 @@ end
|
||||
|
||||
--- Returns if a Vec2 is within the zone.
|
||||
-- @param #ZONE_BASE self
|
||||
-- @param Dcs.DCSTypes#Vec2 Vec2 The Vec2 to test.
|
||||
-- @param DCS#Vec2 Vec2 The Vec2 to test.
|
||||
-- @return #boolean true if the Vec2 is within the zone.
|
||||
function ZONE_BASE:IsVec2InZone( Vec2 )
|
||||
self:F2( Vec2 )
|
||||
@@ -148,7 +162,7 @@ end
|
||||
|
||||
--- Returns if a Vec3 is within the zone.
|
||||
-- @param #ZONE_BASE self
|
||||
-- @param Dcs.DCSTypes#Vec3 Vec3 The point to test.
|
||||
-- @param DCS#Vec3 Vec3 The point to test.
|
||||
-- @return #boolean true if the Vec3 is within the zone.
|
||||
function ZONE_BASE:IsVec3InZone( Vec3 )
|
||||
local InZone = self:IsVec2InZone( { x = Vec3.x, y = Vec3.z } )
|
||||
@@ -183,16 +197,16 @@ function ZONE_BASE:IsPointVec3InZone( PointVec3 )
|
||||
end
|
||||
|
||||
|
||||
--- Returns the @{DCSTypes#Vec2} coordinate of the zone.
|
||||
--- Returns the @{DCS#Vec2} coordinate of the zone.
|
||||
-- @param #ZONE_BASE self
|
||||
-- @return #nil.
|
||||
function ZONE_BASE:GetVec2()
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Returns a @{Point#POINT_VEC2} of the zone.
|
||||
--- Returns a @{Core.Point#POINT_VEC2} of the zone.
|
||||
-- @param #ZONE_BASE self
|
||||
-- @param Dcs.DCSTypes#Distance Height The height to add to the land height where the center of the zone is located.
|
||||
-- @param DCS#Distance Height The height to add to the land height where the center of the zone is located.
|
||||
-- @return Core.Point#POINT_VEC2 The PointVec2 of the zone.
|
||||
function ZONE_BASE:GetPointVec2()
|
||||
self:F2( self.ZoneName )
|
||||
@@ -207,7 +221,7 @@ function ZONE_BASE:GetPointVec2()
|
||||
end
|
||||
|
||||
|
||||
--- Returns a @{Point#COORDINATE} of the zone.
|
||||
--- Returns a @{Core.Point#COORDINATE} of the zone.
|
||||
-- @param #ZONE_BASE self
|
||||
-- @return Core.Point#COORDINATE The Coordinate of the zone.
|
||||
function ZONE_BASE:GetCoordinate()
|
||||
@@ -223,10 +237,10 @@ function ZONE_BASE:GetCoordinate()
|
||||
end
|
||||
|
||||
|
||||
--- Returns the @{DCSTypes#Vec3} of the zone.
|
||||
--- Returns the @{DCS#Vec3} of the zone.
|
||||
-- @param #ZONE_BASE self
|
||||
-- @param Dcs.DCSTypes#Distance Height The height to add to the land height where the center of the zone is located.
|
||||
-- @return Dcs.DCSTypes#Vec3 The Vec3 of the zone.
|
||||
-- @param DCS#Distance Height The height to add to the land height where the center of the zone is located.
|
||||
-- @return DCS#Vec3 The Vec3 of the zone.
|
||||
function ZONE_BASE:GetVec3( Height )
|
||||
self:F2( self.ZoneName )
|
||||
|
||||
@@ -241,9 +255,9 @@ function ZONE_BASE:GetVec3( Height )
|
||||
return Vec3
|
||||
end
|
||||
|
||||
--- Returns a @{Point#POINT_VEC3} of the zone.
|
||||
--- Returns a @{Core.Point#POINT_VEC3} of the zone.
|
||||
-- @param #ZONE_BASE self
|
||||
-- @param Dcs.DCSTypes#Distance Height The height to add to the land height where the center of the zone is located.
|
||||
-- @param DCS#Distance Height The height to add to the land height where the center of the zone is located.
|
||||
-- @return Core.Point#POINT_VEC3 The PointVec3 of the zone.
|
||||
function ZONE_BASE:GetPointVec3( Height )
|
||||
self:F2( self.ZoneName )
|
||||
@@ -257,9 +271,9 @@ function ZONE_BASE:GetPointVec3( Height )
|
||||
return PointVec3
|
||||
end
|
||||
|
||||
--- Returns a @{Point#COORDINATE} of the zone.
|
||||
--- Returns a @{Core.Point#COORDINATE} of the zone.
|
||||
-- @param #ZONE_BASE self
|
||||
-- @param Dcs.DCSTypes#Distance Height The height to add to the land height where the center of the zone is located.
|
||||
-- @param DCS#Distance Height The height to add to the land height where the center of the zone is located.
|
||||
-- @return Core.Point#COORDINATE The Coordinate of the zone.
|
||||
function ZONE_BASE:GetCoordinate( Height ) --R2.1
|
||||
self:F2( self.ZoneName )
|
||||
@@ -274,21 +288,21 @@ function ZONE_BASE:GetCoordinate( Height ) --R2.1
|
||||
end
|
||||
|
||||
|
||||
--- Define a random @{DCSTypes#Vec2} within the zone.
|
||||
--- Define a random @{DCS#Vec2} within the zone.
|
||||
-- @param #ZONE_BASE self
|
||||
-- @return Dcs.DCSTypes#Vec2 The Vec2 coordinates.
|
||||
-- @return DCS#Vec2 The Vec2 coordinates.
|
||||
function ZONE_BASE:GetRandomVec2()
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Define a random @{Point#POINT_VEC2} within the zone.
|
||||
--- Define a random @{Core.Point#POINT_VEC2} within the zone.
|
||||
-- @param #ZONE_BASE self
|
||||
-- @return Core.Point#POINT_VEC2 The PointVec2 coordinates.
|
||||
function ZONE_BASE:GetRandomPointVec2()
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Define a random @{Point#POINT_VEC3} within the zone.
|
||||
--- Define a random @{Core.Point#POINT_VEC3} within the zone.
|
||||
-- @param #ZONE_BASE self
|
||||
-- @return Core.Point#POINT_VEC3 The PointVec3 coordinates.
|
||||
function ZONE_BASE:GetRandomPointVec3()
|
||||
@@ -315,14 +329,15 @@ end
|
||||
-- @param Utilities.Utils#SMOKECOLOR SmokeColor The smoke color.
|
||||
function ZONE_BASE:SmokeZone( SmokeColor )
|
||||
self:F2( SmokeColor )
|
||||
|
||||
|
||||
end
|
||||
|
||||
--- Set the randomization probability of a zone to be selected.
|
||||
-- @param #ZONE_BASE self
|
||||
-- @param ZoneProbability A value between 0 and 1. 0 = 0% and 1 = 100% probability.
|
||||
-- @param #number ZoneProbability A value between 0 and 1. 0 = 0% and 1 = 100% probability.
|
||||
-- @return #ZONE_BASE self
|
||||
function ZONE_BASE:SetZoneProbability( ZoneProbability )
|
||||
self:F2( ZoneProbability )
|
||||
self:F( { self:GetName(), ZoneProbability = ZoneProbability } )
|
||||
|
||||
self.ZoneProbability = ZoneProbability or 1
|
||||
return self
|
||||
@@ -332,7 +347,7 @@ end
|
||||
-- @param #ZONE_BASE self
|
||||
-- @return #number A value between 0 and 1. 0 = 0% and 1 = 100% probability.
|
||||
function ZONE_BASE:GetZoneProbability()
|
||||
self:F2()
|
||||
self:F2()
|
||||
|
||||
return self.ZoneProbability
|
||||
end
|
||||
@@ -341,6 +356,27 @@ end
|
||||
-- @param #ZONE_BASE self
|
||||
-- @return #ZONE_BASE The zone is selected taking into account the randomization probability factor.
|
||||
-- @return #nil The zone is not selected taking into account the randomization probability factor.
|
||||
-- @usage
|
||||
--
|
||||
-- local ZoneArray = { ZONE:New( "Zone1" ), ZONE:New( "Zone2" ) }
|
||||
--
|
||||
-- -- We set a zone probability of 70% to the first zone and 30% to the second zone.
|
||||
-- ZoneArray[1]:SetZoneProbability( 0.5 )
|
||||
-- ZoneArray[2]:SetZoneProbability( 0.5 )
|
||||
--
|
||||
-- local ZoneSelected = nil
|
||||
--
|
||||
-- while ZoneSelected == nil do
|
||||
-- for _, Zone in pairs( ZoneArray ) do
|
||||
-- ZoneSelected = Zone:GetZoneMaybe()
|
||||
-- if ZoneSelected ~= nil then
|
||||
-- break
|
||||
-- end
|
||||
-- end
|
||||
-- end
|
||||
--
|
||||
-- -- The result should be that Zone1 would be more probable selected than Zone2.
|
||||
--
|
||||
function ZONE_BASE:GetZoneMaybe()
|
||||
self:F2()
|
||||
|
||||
@@ -355,13 +391,11 @@ end
|
||||
|
||||
--- The ZONE_RADIUS class, defined by a zone name, a location and a radius.
|
||||
-- @type ZONE_RADIUS
|
||||
-- @field Dcs.DCSTypes#Vec2 Vec2 The current location of the zone.
|
||||
-- @field Dcs.DCSTypes#Distance Radius The radius of the zone.
|
||||
-- @field DCS#Vec2 Vec2 The current location of the zone.
|
||||
-- @field DCS#Distance Radius The radius of the zone.
|
||||
-- @extends #ZONE_BASE
|
||||
|
||||
--- # ZONE_RADIUS class, extends @{Zone#ZONE_BASE}
|
||||
--
|
||||
-- The ZONE_RADIUS class defined by a zone name, a location and a radius.
|
||||
--- The ZONE_RADIUS class defined by a zone name, a location and a radius.
|
||||
-- This class implements the inherited functions from Core.Zone#ZONE_BASE taking into account the own zone format and properties.
|
||||
--
|
||||
-- ## ZONE_RADIUS constructor
|
||||
@@ -375,17 +409,17 @@ end
|
||||
--
|
||||
-- ## Manage the location of the zone
|
||||
--
|
||||
-- * @{#ZONE_RADIUS.SetVec2}(): Sets the @{DCSTypes#Vec2} of the zone.
|
||||
-- * @{#ZONE_RADIUS.GetVec2}(): Returns the @{DCSTypes#Vec2} of the zone.
|
||||
-- * @{#ZONE_RADIUS.GetVec3}(): Returns the @{DCSTypes#Vec3} of the zone, taking an additional height parameter.
|
||||
-- * @{#ZONE_RADIUS.SetVec2}(): Sets the @{DCS#Vec2} of the zone.
|
||||
-- * @{#ZONE_RADIUS.GetVec2}(): Returns the @{DCS#Vec2} of the zone.
|
||||
-- * @{#ZONE_RADIUS.GetVec3}(): Returns the @{DCS#Vec3} of the zone, taking an additional height parameter.
|
||||
--
|
||||
-- ## Zone point randomization
|
||||
--
|
||||
-- Various functions exist to find random points within the zone.
|
||||
--
|
||||
-- * @{#ZONE_RADIUS.GetRandomVec2}(): Gets a random 2D point in the zone.
|
||||
-- * @{#ZONE_RADIUS.GetRandomPointVec2}(): Gets a @{Point#POINT_VEC2} object representing a random 2D point in the zone.
|
||||
-- * @{#ZONE_RADIUS.GetRandomPointVec3}(): Gets a @{Point#POINT_VEC3} object representing a random 3D point in the zone. Note that the height of the point is at landheight.
|
||||
-- * @{#ZONE_RADIUS.GetRandomPointVec2}(): Gets a @{Core.Point#POINT_VEC2} object representing a random 2D point in the zone.
|
||||
-- * @{#ZONE_RADIUS.GetRandomPointVec3}(): Gets a @{Core.Point#POINT_VEC3} object representing a random 3D point in the zone. Note that the height of the point is at landheight.
|
||||
--
|
||||
-- @field #ZONE_RADIUS
|
||||
ZONE_RADIUS = {
|
||||
@@ -395,8 +429,8 @@ ZONE_RADIUS = {
|
||||
--- Constructor of @{#ZONE_RADIUS}, taking the zone name, the zone location and a radius.
|
||||
-- @param #ZONE_RADIUS self
|
||||
-- @param #string ZoneName Name of the zone.
|
||||
-- @param Dcs.DCSTypes#Vec2 Vec2 The location of the zone.
|
||||
-- @param Dcs.DCSTypes#Distance Radius The radius of the zone.
|
||||
-- @param DCS#Vec2 Vec2 The location of the zone.
|
||||
-- @param DCS#Distance Radius The radius of the zone.
|
||||
-- @return #ZONE_RADIUS self
|
||||
function ZONE_RADIUS:New( ZoneName, Vec2, Radius )
|
||||
local self = BASE:Inherit( self, ZONE_BASE:New( ZoneName ) ) -- #ZONE_RADIUS
|
||||
@@ -410,8 +444,9 @@ end
|
||||
|
||||
--- Bounds the zone with tires.
|
||||
-- @param #ZONE_RADIUS self
|
||||
-- @param #number Points (optional) The amount of points in the circle.
|
||||
-- @param #boolean UnBound If true the tyres will be destroyed.
|
||||
-- @param #number Points (optional) The amount of points in the circle. Default 360.
|
||||
-- @param DCS#country.id CountryID The country id of the tire objects, e.g. country.id.USA for blue or country.id.RUSSIA for red.
|
||||
-- @param #boolean UnBound (Optional) If true the tyres will be destroyed.
|
||||
-- @return #ZONE_RADIUS self
|
||||
function ZONE_RADIUS:BoundZone( Points, CountryID, UnBound )
|
||||
|
||||
@@ -490,7 +525,7 @@ end
|
||||
-- @param #ZONE_RADIUS self
|
||||
-- @param Utilities.Utils#FLARECOLOR FlareColor The flare color.
|
||||
-- @param #number Points (optional) The amount of points in the circle.
|
||||
-- @param Dcs.DCSTypes#Azimuth Azimuth (optional) Azimuth The azimuth of the flare.
|
||||
-- @param DCS#Azimuth Azimuth (optional) Azimuth The azimuth of the flare.
|
||||
-- @param #number AddHeight (optional) The height to be added for the smoke.
|
||||
-- @return #ZONE_RADIUS self
|
||||
function ZONE_RADIUS:FlareZone( FlareColor, Points, Azimuth, AddHeight )
|
||||
@@ -518,7 +553,7 @@ end
|
||||
|
||||
--- Returns the radius of the zone.
|
||||
-- @param #ZONE_RADIUS self
|
||||
-- @return Dcs.DCSTypes#Distance The radius of the zone.
|
||||
-- @return DCS#Distance The radius of the zone.
|
||||
function ZONE_RADIUS:GetRadius()
|
||||
self:F2( self.ZoneName )
|
||||
|
||||
@@ -529,8 +564,8 @@ end
|
||||
|
||||
--- Sets the radius of the zone.
|
||||
-- @param #ZONE_RADIUS self
|
||||
-- @param Dcs.DCSTypes#Distance Radius The radius of the zone.
|
||||
-- @return Dcs.DCSTypes#Distance The radius of the zone.
|
||||
-- @param DCS#Distance Radius The radius of the zone.
|
||||
-- @return DCS#Distance The radius of the zone.
|
||||
function ZONE_RADIUS:SetRadius( Radius )
|
||||
self:F2( self.ZoneName )
|
||||
|
||||
@@ -540,9 +575,9 @@ function ZONE_RADIUS:SetRadius( Radius )
|
||||
return self.Radius
|
||||
end
|
||||
|
||||
--- Returns the @{DCSTypes#Vec2} of the zone.
|
||||
--- Returns the @{DCS#Vec2} of the zone.
|
||||
-- @param #ZONE_RADIUS self
|
||||
-- @return Dcs.DCSTypes#Vec2 The location of the zone.
|
||||
-- @return DCS#Vec2 The location of the zone.
|
||||
function ZONE_RADIUS:GetVec2()
|
||||
self:F2( self.ZoneName )
|
||||
|
||||
@@ -551,10 +586,10 @@ function ZONE_RADIUS:GetVec2()
|
||||
return self.Vec2
|
||||
end
|
||||
|
||||
--- Sets the @{DCSTypes#Vec2} of the zone.
|
||||
--- Sets the @{DCS#Vec2} of the zone.
|
||||
-- @param #ZONE_RADIUS self
|
||||
-- @param Dcs.DCSTypes#Vec2 Vec2 The new location of the zone.
|
||||
-- @return Dcs.DCSTypes#Vec2 The new location of the zone.
|
||||
-- @param DCS#Vec2 Vec2 The new location of the zone.
|
||||
-- @return DCS#Vec2 The new location of the zone.
|
||||
function ZONE_RADIUS:SetVec2( Vec2 )
|
||||
self:F2( self.ZoneName )
|
||||
|
||||
@@ -565,10 +600,10 @@ function ZONE_RADIUS:SetVec2( Vec2 )
|
||||
return self.Vec2
|
||||
end
|
||||
|
||||
--- Returns the @{DCSTypes#Vec3} of the ZONE_RADIUS.
|
||||
--- Returns the @{DCS#Vec3} of the ZONE_RADIUS.
|
||||
-- @param #ZONE_RADIUS self
|
||||
-- @param Dcs.DCSTypes#Distance Height The height to add to the land height where the center of the zone is located.
|
||||
-- @return Dcs.DCSTypes#Vec3 The point of the zone.
|
||||
-- @param DCS#Distance Height The height to add to the land height where the center of the zone is located.
|
||||
-- @return DCS#Vec3 The point of the zone.
|
||||
function ZONE_RADIUS:GetVec3( Height )
|
||||
self:F2( { self.ZoneName, Height } )
|
||||
|
||||
@@ -627,14 +662,14 @@ function ZONE_RADIUS:Scan( ObjectCategories )
|
||||
local CoalitionDCSUnit = ZoneObject:getCoalition()
|
||||
self.ScanData.Coalitions[CoalitionDCSUnit] = true
|
||||
self.ScanData.Units[ZoneObject] = ZoneObject
|
||||
self:F( { Name = ZoneObject:getName(), Coalition = CoalitionDCSUnit } )
|
||||
self:F2( { Name = ZoneObject:getName(), Coalition = CoalitionDCSUnit } )
|
||||
end
|
||||
if ObjectCategory == Object.Category.SCENERY then
|
||||
local SceneryType = ZoneObject:getTypeName()
|
||||
local SceneryName = ZoneObject:getName()
|
||||
self.ScanData.Scenery[SceneryType] = self.ScanData.Scenery[SceneryType] or {}
|
||||
self.ScanData.Scenery[SceneryType][SceneryName] = SCENERY:Register( SceneryName, ZoneObject )
|
||||
self:F( { SCENERY = self.ScanData.Scenery[SceneryType][SceneryName] } )
|
||||
self:F2( { SCENERY = self.ScanData.Scenery[SceneryType][SceneryName] } )
|
||||
end
|
||||
end
|
||||
return true
|
||||
@@ -812,7 +847,7 @@ end
|
||||
|
||||
--- Returns if a location is within the zone.
|
||||
-- @param #ZONE_RADIUS self
|
||||
-- @param Dcs.DCSTypes#Vec2 Vec2 The location to test.
|
||||
-- @param DCS#Vec2 Vec2 The location to test.
|
||||
-- @return #boolean true if the location is within the zone.
|
||||
function ZONE_RADIUS:IsVec2InZone( Vec2 )
|
||||
self:F2( Vec2 )
|
||||
@@ -830,7 +865,7 @@ end
|
||||
|
||||
--- Returns if a point is within the zone.
|
||||
-- @param #ZONE_RADIUS self
|
||||
-- @param Dcs.DCSTypes#Vec3 Vec3 The point to test.
|
||||
-- @param DCS#Vec3 Vec3 The point to test.
|
||||
-- @return #boolean true if the point is within the zone.
|
||||
function ZONE_RADIUS:IsVec3InZone( Vec3 )
|
||||
self:F2( Vec3 )
|
||||
@@ -844,7 +879,7 @@ end
|
||||
-- @param #ZONE_RADIUS self
|
||||
-- @param #number inner (optional) Minimal distance from the center of the zone. Default is 0.
|
||||
-- @param #number outer (optional) Maximal distance from the outer edge of the zone. Default is the radius of the zone.
|
||||
-- @return Dcs.DCSTypes#Vec2 The random location within the zone.
|
||||
-- @return DCS#Vec2 The random location within the zone.
|
||||
function ZONE_RADIUS:GetRandomVec2( inner, outer )
|
||||
self:F( self.ZoneName, inner, outer )
|
||||
|
||||
@@ -862,11 +897,11 @@ function ZONE_RADIUS:GetRandomVec2( inner, outer )
|
||||
return Point
|
||||
end
|
||||
|
||||
--- Returns a @{Point#POINT_VEC2} object reflecting a random 2D location within the zone.
|
||||
--- Returns a @{Core.Point#POINT_VEC2} object reflecting a random 2D location within the zone.
|
||||
-- @param #ZONE_RADIUS self
|
||||
-- @param #number inner (optional) Minimal distance from the center of the zone. Default is 0.
|
||||
-- @param #number outer (optional) Maximal distance from the outer edge of the zone. Default is the radius of the zone.
|
||||
-- @return Core.Point#POINT_VEC2 The @{Point#POINT_VEC2} object reflecting the random 3D location within the zone.
|
||||
-- @return Core.Point#POINT_VEC2 The @{Core.Point#POINT_VEC2} object reflecting the random 3D location within the zone.
|
||||
function ZONE_RADIUS:GetRandomPointVec2( inner, outer )
|
||||
self:F( self.ZoneName, inner, outer )
|
||||
|
||||
@@ -881,7 +916,7 @@ end
|
||||
-- @param #ZONE_RADIUS self
|
||||
-- @param #number inner (optional) Minimal distance from the center of the zone. Default is 0.
|
||||
-- @param #number outer (optional) Maximal distance from the outer edge of the zone. Default is the radius of the zone.
|
||||
-- @return Dcs.DCSTypes#Vec3 The random location within the zone.
|
||||
-- @return DCS#Vec3 The random location within the zone.
|
||||
function ZONE_RADIUS:GetRandomVec3( inner, outer )
|
||||
self:F( self.ZoneName, inner, outer )
|
||||
|
||||
@@ -893,11 +928,11 @@ function ZONE_RADIUS:GetRandomVec3( inner, outer )
|
||||
end
|
||||
|
||||
|
||||
--- Returns a @{Point#POINT_VEC3} object reflecting a random 3D location within the zone.
|
||||
--- Returns a @{Core.Point#POINT_VEC3} object reflecting a random 3D location within the zone.
|
||||
-- @param #ZONE_RADIUS self
|
||||
-- @param #number inner (optional) Minimal distance from the center of the zone. Default is 0.
|
||||
-- @param #number outer (optional) Maximal distance from the outer edge of the zone. Default is the radius of the zone.
|
||||
-- @return Core.Point#POINT_VEC3 The @{Point#POINT_VEC3} object reflecting the random 3D location within the zone.
|
||||
-- @return Core.Point#POINT_VEC3 The @{Core.Point#POINT_VEC3} object reflecting the random 3D location within the zone.
|
||||
function ZONE_RADIUS:GetRandomPointVec3( inner, outer )
|
||||
self:F( self.ZoneName, inner, outer )
|
||||
|
||||
@@ -909,7 +944,7 @@ function ZONE_RADIUS:GetRandomPointVec3( inner, outer )
|
||||
end
|
||||
|
||||
|
||||
--- Returns a @{Point#COORDINATE} object reflecting a random 3D location within the zone.
|
||||
--- Returns a @{Core.Point#COORDINATE} object reflecting a random 3D location within the zone.
|
||||
-- @param #ZONE_RADIUS self
|
||||
-- @param #number inner (optional) Minimal distance from the center of the zone. Default is 0.
|
||||
-- @param #number outer (optional) Maximal distance from the outer edge of the zone. Default is the radius of the zone.
|
||||
@@ -917,7 +952,7 @@ end
|
||||
function ZONE_RADIUS:GetRandomCoordinate( inner, outer )
|
||||
self:F( self.ZoneName, inner, outer )
|
||||
|
||||
local Coordinate = COORDINATE:NewFromVec2( self:GetRandomVec2() )
|
||||
local Coordinate = COORDINATE:NewFromVec2( self:GetRandomVec2(inner, outer) )
|
||||
|
||||
self:T3( { Coordinate = Coordinate } )
|
||||
|
||||
@@ -930,11 +965,33 @@ end
|
||||
-- @extends #ZONE_RADIUS
|
||||
|
||||
|
||||
--- # ZONE class, extends @{Zone#ZONE_RADIUS}
|
||||
--
|
||||
-- The ZONE class, defined by the zone name as defined within the Mission Editor.
|
||||
--- The ZONE class, defined by the zone name as defined within the Mission Editor.
|
||||
-- This class implements the inherited functions from @{#ZONE_RADIUS} taking into account the own zone format and properties.
|
||||
--
|
||||
-- ## ZONE constructor
|
||||
--
|
||||
-- * @{#ZONE.New}(): Constructor. This will search for a trigger zone with the name given, and will return for you a ZONE object.
|
||||
--
|
||||
-- ## Declare a ZONE directly in the DCS mission editor!
|
||||
--
|
||||
-- You can declare a ZONE using the DCS mission editor by adding a trigger zone in the mission editor.
|
||||
--
|
||||
-- Then during mission startup, when loading Moose.lua, this trigger zone will be detected as a ZONE declaration.
|
||||
-- Within the background, a ZONE object will be created within the @{Core.Database}.
|
||||
-- The ZONE name will be the trigger zone name.
|
||||
--
|
||||
-- So, you can search yourself for the ZONE object by using the @{#ZONE.FindByName}() method.
|
||||
-- In this example, `local TriggerZone = ZONE:FindByName( "DefenseZone" )` would return the ZONE object
|
||||
-- that was created at mission startup, and reference it into the `TriggerZone` local object.
|
||||
--
|
||||
-- Refer to mission `ZON-110` for a demonstration.
|
||||
--
|
||||
-- This is especially handy if you want to quickly setup a SET_ZONE...
|
||||
-- So when you would declare `local SetZone = SET_ZONE:New():FilterPrefixes( "Defense" ):FilterStart()`,
|
||||
-- then SetZone would contain the ZONE object `DefenseZone` as part of the zone collection,
|
||||
-- without much scripting overhead!!!
|
||||
--
|
||||
--
|
||||
-- @field #ZONE
|
||||
ZONE = {
|
||||
ClassName="ZONE",
|
||||
@@ -978,9 +1035,10 @@ end
|
||||
-- @field Wrapper.Unit#UNIT ZoneUNIT
|
||||
-- @extends Core.Zone#ZONE_RADIUS
|
||||
|
||||
|
||||
--- # ZONE_UNIT class, extends @{Zone#ZONE_RADIUS}
|
||||
--
|
||||
-- The ZONE_UNIT class defined by a zone around a @{Unit#UNIT} with a radius.
|
||||
-- The ZONE_UNIT class defined by a zone attached to a @{Wrapper.Unit#UNIT} with a radius and optional offsets.
|
||||
-- This class implements the inherited functions from @{#ZONE_RADIUS} taking into account the own zone format and properties.
|
||||
--
|
||||
-- @field #ZONE_UNIT
|
||||
@@ -988,31 +1046,79 @@ ZONE_UNIT = {
|
||||
ClassName="ZONE_UNIT",
|
||||
}
|
||||
|
||||
--- Constructor to create a ZONE_UNIT instance, taking the zone name, a zone unit and a radius.
|
||||
--- Constructor to create a ZONE_UNIT instance, taking the zone name, a zone unit and a radius and optional offsets in X and Y directions.
|
||||
-- @param #ZONE_UNIT self
|
||||
-- @param #string ZoneName Name of the zone.
|
||||
-- @param Wrapper.Unit#UNIT ZoneUNIT The unit as the center of the zone.
|
||||
-- @param Dcs.DCSTypes#Distance Radius The radius of the zone.
|
||||
-- @param #table Offset A table specifying the offset. The offset table may have the following elements:
|
||||
-- dx The offset in X direction, +x is north.
|
||||
-- dy The offset in Y direction, +y is east.
|
||||
-- rho The distance of the zone from the unit
|
||||
-- theta The azimuth of the zone relative to unit
|
||||
-- relative_to_unit If true, theta is measured clockwise from unit's direction else clockwise from north. If using dx, dy setting this to true makes +x parallel to unit heading.
|
||||
-- dx, dy OR rho, theta may be used, not both.
|
||||
-- @return #ZONE_UNIT self
|
||||
function ZONE_UNIT:New( ZoneName, ZoneUNIT, Radius )
|
||||
function ZONE_UNIT:New( ZoneName, ZoneUNIT, Radius, Offset)
|
||||
|
||||
if Offset then
|
||||
-- check if the inputs was reasonable, either (dx, dy) or (rho, theta) can be given, else raise an exception.
|
||||
if (Offset.dx or Offset.dy) and (Offset.rho or Offset.theta) then
|
||||
error("Cannot use (dx, dy) with (rho, theta)")
|
||||
end
|
||||
|
||||
self.dy = Offset.dy or 0.0
|
||||
self.dx = Offset.dx or 0.0
|
||||
self.rho = Offset.rho or 0.0
|
||||
self.theta = (Offset.theta or 0.0) * math.pi / 180.0
|
||||
self.relative_to_unit = Offset.relative_to_unit or false
|
||||
end
|
||||
|
||||
local self = BASE:Inherit( self, ZONE_RADIUS:New( ZoneName, ZoneUNIT:GetVec2(), Radius ) )
|
||||
|
||||
self:F( { ZoneName, ZoneUNIT:GetVec2(), Radius } )
|
||||
|
||||
self.ZoneUNIT = ZoneUNIT
|
||||
self.LastVec2 = ZoneUNIT:GetVec2()
|
||||
|
||||
-- Zone objects are added to the _DATABASE and SET_ZONE objects.
|
||||
_EVENTDISPATCHER:CreateEventNewZone( self )
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Returns the current location of the @{Unit#UNIT}.
|
||||
--- Returns the current location of the @{Wrapper.Unit#UNIT}.
|
||||
-- @param #ZONE_UNIT self
|
||||
-- @return Dcs.DCSTypes#Vec2 The location of the zone based on the @{Unit#UNIT}location.
|
||||
-- @return DCS#Vec2 The location of the zone based on the @{Wrapper.Unit#UNIT}location and the offset, if any.
|
||||
function ZONE_UNIT:GetVec2()
|
||||
self:F2( self.ZoneName )
|
||||
|
||||
local ZoneVec2 = self.ZoneUNIT:GetVec2()
|
||||
if ZoneVec2 then
|
||||
|
||||
local heading
|
||||
if self.relative_to_unit then
|
||||
heading = ( self.ZoneUNIT:GetHeading() or 0.0 ) * math.pi / 180.0
|
||||
else
|
||||
heading = 0.0
|
||||
end
|
||||
|
||||
-- update the zone position with the offsets.
|
||||
if (self.dx or self.dy) then
|
||||
|
||||
-- use heading to rotate offset relative to unit using rotation matrix in 2D.
|
||||
-- see: https://en.wikipedia.org/wiki/Rotation_matrix
|
||||
ZoneVec2.x = ZoneVec2.x + self.dx * math.cos( -heading ) + self.dy * math.sin( -heading )
|
||||
ZoneVec2.y = ZoneVec2.y - self.dx * math.sin( -heading ) + self.dy * math.cos( -heading )
|
||||
end
|
||||
|
||||
-- if using the polar coordinates
|
||||
if (self.rho or self.theta) then
|
||||
ZoneVec2.x = ZoneVec2.x + self.rho * math.cos( self.theta + heading )
|
||||
ZoneVec2.y = ZoneVec2.y + self.rho * math.sin( self.theta + heading )
|
||||
end
|
||||
|
||||
self.LastVec2 = ZoneVec2
|
||||
return ZoneVec2
|
||||
else
|
||||
@@ -1026,12 +1132,13 @@ end
|
||||
|
||||
--- Returns a random location within the zone.
|
||||
-- @param #ZONE_UNIT self
|
||||
-- @return Dcs.DCSTypes#Vec2 The random location within the zone.
|
||||
-- @return DCS#Vec2 The random location within the zone.
|
||||
function ZONE_UNIT:GetRandomVec2()
|
||||
self:F( self.ZoneName )
|
||||
|
||||
local RandomVec2 = {}
|
||||
local Vec2 = self.ZoneUNIT:GetVec2()
|
||||
--local Vec2 = self.ZoneUNIT:GetVec2() -- FF: This does not take care of the new offset feature!
|
||||
local Vec2 = self:GetVec2()
|
||||
|
||||
if not Vec2 then
|
||||
Vec2 = self.LastVec2
|
||||
@@ -1046,10 +1153,10 @@ function ZONE_UNIT:GetRandomVec2()
|
||||
return RandomVec2
|
||||
end
|
||||
|
||||
--- Returns the @{DCSTypes#Vec3} of the ZONE_UNIT.
|
||||
--- Returns the @{DCS#Vec3} of the ZONE_UNIT.
|
||||
-- @param #ZONE_UNIT self
|
||||
-- @param Dcs.DCSTypes#Distance Height The height to add to the land height where the center of the zone is located.
|
||||
-- @return Dcs.DCSTypes#Vec3 The point of the zone.
|
||||
-- @param DCS#Distance Height The height to add to the land height where the center of the zone is located.
|
||||
-- @return DCS#Vec3 The point of the zone.
|
||||
function ZONE_UNIT:GetVec3( Height )
|
||||
self:F2( self.ZoneName )
|
||||
|
||||
@@ -1068,48 +1175,57 @@ end
|
||||
-- @extends #ZONE_RADIUS
|
||||
|
||||
|
||||
--- # ZONE_GROUP class, extends @{Zone#ZONE_RADIUS}
|
||||
--
|
||||
-- The ZONE_GROUP class defines by a zone around a @{Group#GROUP} with a radius. The current leader of the group defines the center of the zone.
|
||||
-- This class implements the inherited functions from @{Zone#ZONE_RADIUS} taking into account the own zone format and properties.
|
||||
--- The ZONE_GROUP class defines by a zone around a @{Wrapper.Group#GROUP} with a radius. The current leader of the group defines the center of the zone.
|
||||
-- This class implements the inherited functions from @{Core.Zone#ZONE_RADIUS} taking into account the own zone format and properties.
|
||||
--
|
||||
-- @field #ZONE_GROUP
|
||||
ZONE_GROUP = {
|
||||
ClassName="ZONE_GROUP",
|
||||
}
|
||||
|
||||
--- Constructor to create a ZONE_GROUP instance, taking the zone name, a zone @{Group#GROUP} and a radius.
|
||||
--- Constructor to create a ZONE_GROUP instance, taking the zone name, a zone @{Wrapper.Group#GROUP} and a radius.
|
||||
-- @param #ZONE_GROUP self
|
||||
-- @param #string ZoneName Name of the zone.
|
||||
-- @param Wrapper.Group#GROUP ZoneGROUP The @{Group} as the center of the zone.
|
||||
-- @param Dcs.DCSTypes#Distance Radius The radius of the zone.
|
||||
-- @param Wrapper.Group#GROUP ZoneGROUP The @{Wrapper.Group} as the center of the zone.
|
||||
-- @param DCS#Distance Radius The radius of the zone.
|
||||
-- @return #ZONE_GROUP self
|
||||
function ZONE_GROUP:New( ZoneName, ZoneGROUP, Radius )
|
||||
local self = BASE:Inherit( self, ZONE_RADIUS:New( ZoneName, ZoneGROUP:GetVec2(), Radius ) )
|
||||
self:F( { ZoneName, ZoneGROUP:GetVec2(), Radius } )
|
||||
|
||||
self._.ZoneGROUP = ZoneGROUP
|
||||
self._.ZoneVec2Cache = self._.ZoneGROUP:GetVec2()
|
||||
|
||||
-- Zone objects are added to the _DATABASE and SET_ZONE objects.
|
||||
_EVENTDISPATCHER:CreateEventNewZone( self )
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Returns the current location of the @{Group}.
|
||||
--- Returns the current location of the @{Wrapper.Group}.
|
||||
-- @param #ZONE_GROUP self
|
||||
-- @return Dcs.DCSTypes#Vec2 The location of the zone based on the @{Group} location.
|
||||
-- @return DCS#Vec2 The location of the zone based on the @{Wrapper.Group} location.
|
||||
function ZONE_GROUP:GetVec2()
|
||||
self:F( self.ZoneName )
|
||||
|
||||
local ZoneVec2 = self._.ZoneGROUP:GetVec2()
|
||||
local ZoneVec2 = nil
|
||||
|
||||
if self._.ZoneGROUP:IsAlive() then
|
||||
ZoneVec2 = self._.ZoneGROUP:GetVec2()
|
||||
self._.ZoneVec2Cache = ZoneVec2
|
||||
else
|
||||
ZoneVec2 = self._.ZoneVec2Cache
|
||||
end
|
||||
|
||||
self:T( { ZoneVec2 } )
|
||||
|
||||
return ZoneVec2
|
||||
end
|
||||
|
||||
--- Returns a random location within the zone of the @{Group}.
|
||||
--- Returns a random location within the zone of the @{Wrapper.Group}.
|
||||
-- @param #ZONE_GROUP self
|
||||
-- @return Dcs.DCSTypes#Vec2 The random location of the zone based on the @{Group} location.
|
||||
-- @return DCS#Vec2 The random location of the zone based on the @{Wrapper.Group} location.
|
||||
function ZONE_GROUP:GetRandomVec2()
|
||||
self:F( self.ZoneName )
|
||||
|
||||
@@ -1125,11 +1241,11 @@ function ZONE_GROUP:GetRandomVec2()
|
||||
return Point
|
||||
end
|
||||
|
||||
--- Returns a @{Point#POINT_VEC2} object reflecting a random 2D location within the zone.
|
||||
--- Returns a @{Core.Point#POINT_VEC2} object reflecting a random 2D location within the zone.
|
||||
-- @param #ZONE_GROUP self
|
||||
-- @param #number inner (optional) Minimal distance from the center of the zone. Default is 0.
|
||||
-- @param #number outer (optional) Maximal distance from the outer edge of the zone. Default is the radius of the zone.
|
||||
-- @return Core.Point#POINT_VEC2 The @{Point#POINT_VEC2} object reflecting the random 3D location within the zone.
|
||||
-- @return Core.Point#POINT_VEC2 The @{Core.Point#POINT_VEC2} object reflecting the random 3D location within the zone.
|
||||
function ZONE_GROUP:GetRandomPointVec2( inner, outer )
|
||||
self:F( self.ZoneName, inner, outer )
|
||||
|
||||
@@ -1142,14 +1258,12 @@ end
|
||||
|
||||
|
||||
--- @type ZONE_POLYGON_BASE
|
||||
-- --@field #ZONE_POLYGON_BASE.ListVec2 Polygon The polygon defined by an array of @{DCSTypes#Vec2}.
|
||||
-- --@field #ZONE_POLYGON_BASE.ListVec2 Polygon The polygon defined by an array of @{DCS#Vec2}.
|
||||
-- @extends #ZONE_BASE
|
||||
|
||||
|
||||
--- # ZONE_POLYGON_BASE class, extends @{Zone#ZONE_BASE}
|
||||
--
|
||||
-- The ZONE_POLYGON_BASE class defined by a sequence of @{Group#GROUP} waypoints within the Mission Editor, forming a polygon.
|
||||
-- This class implements the inherited functions from @{Zone#ZONE_RADIUS} taking into account the own zone format and properties.
|
||||
--- The ZONE_POLYGON_BASE class defined by a sequence of @{Wrapper.Group#GROUP} waypoints within the Mission Editor, forming a polygon.
|
||||
-- This class implements the inherited functions from @{Core.Zone#ZONE_RADIUS} taking into account the own zone format and properties.
|
||||
-- This class is an abstract BASE class for derived classes, and is not meant to be instantiated.
|
||||
--
|
||||
-- ## Zone point randomization
|
||||
@@ -1157,8 +1271,8 @@ end
|
||||
-- Various functions exist to find random points within the zone.
|
||||
--
|
||||
-- * @{#ZONE_POLYGON_BASE.GetRandomVec2}(): Gets a random 2D point in the zone.
|
||||
-- * @{#ZONE_POLYGON_BASE.GetRandomPointVec2}(): Return a @{Point#POINT_VEC2} object representing a random 2D point within the zone.
|
||||
-- * @{#ZONE_POLYGON_BASE.GetRandomPointVec3}(): Return a @{Point#POINT_VEC3} object representing a random 3D point at landheight within the zone.
|
||||
-- * @{#ZONE_POLYGON_BASE.GetRandomPointVec2}(): Return a @{Core.Point#POINT_VEC2} object representing a random 2D point within the zone.
|
||||
-- * @{#ZONE_POLYGON_BASE.GetRandomPointVec3}(): Return a @{Core.Point#POINT_VEC3} object representing a random 3D point at landheight within the zone.
|
||||
--
|
||||
-- @field #ZONE_POLYGON_BASE
|
||||
ZONE_POLYGON_BASE = {
|
||||
@@ -1167,13 +1281,13 @@ ZONE_POLYGON_BASE = {
|
||||
|
||||
--- A points array.
|
||||
-- @type ZONE_POLYGON_BASE.ListVec2
|
||||
-- @list <Dcs.DCSTypes#Vec2>
|
||||
-- @list <DCS#Vec2>
|
||||
|
||||
--- Constructor to create a ZONE_POLYGON_BASE instance, taking the zone name and an array of @{DCSTypes#Vec2}, forming a polygon.
|
||||
-- The @{Group#GROUP} waypoints define the polygon corners. The first and the last point are automatically connected.
|
||||
--- Constructor to create a ZONE_POLYGON_BASE instance, taking the zone name and an array of @{DCS#Vec2}, forming a polygon.
|
||||
-- The @{Wrapper.Group#GROUP} waypoints define the polygon corners. The first and the last point are automatically connected.
|
||||
-- @param #ZONE_POLYGON_BASE self
|
||||
-- @param #string ZoneName Name of the zone.
|
||||
-- @param #ZONE_POLYGON_BASE.ListVec2 PointsArray An array of @{DCSTypes#Vec2}, forming a polygon..
|
||||
-- @param #ZONE_POLYGON_BASE.ListVec2 PointsArray An array of @{DCS#Vec2}, forming a polygon..
|
||||
-- @return #ZONE_POLYGON_BASE self
|
||||
function ZONE_POLYGON_BASE:New( ZoneName, PointsArray )
|
||||
local self = BASE:Inherit( self, ZONE_BASE:New( ZoneName ) )
|
||||
@@ -1194,7 +1308,7 @@ end
|
||||
|
||||
--- Returns the center location of the polygon.
|
||||
-- @param #ZONE_GROUP self
|
||||
-- @return Dcs.DCSTypes#Vec2 The location of the zone based on the @{Group} location.
|
||||
-- @return DCS#Vec2 The location of the zone based on the @{Wrapper.Group} location.
|
||||
function ZONE_POLYGON_BASE:GetVec2()
|
||||
self:F( self.ZoneName )
|
||||
|
||||
@@ -1301,7 +1415,7 @@ end
|
||||
--- Returns if a location is within the zone.
|
||||
-- Source learned and taken from: https://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
|
||||
-- @param #ZONE_POLYGON_BASE self
|
||||
-- @param Dcs.DCSTypes#Vec2 Vec2 The location to test.
|
||||
-- @param DCS#Vec2 Vec2 The location to test.
|
||||
-- @return #boolean true if the location is within the zone.
|
||||
function ZONE_POLYGON_BASE:IsVec2InZone( Vec2 )
|
||||
self:F2( Vec2 )
|
||||
@@ -1329,9 +1443,9 @@ function ZONE_POLYGON_BASE:IsVec2InZone( Vec2 )
|
||||
return InPolygon
|
||||
end
|
||||
|
||||
--- Define a random @{DCSTypes#Vec2} within the zone.
|
||||
--- Define a random @{DCS#Vec2} within the zone.
|
||||
-- @param #ZONE_POLYGON_BASE self
|
||||
-- @return Dcs.DCSTypes#Vec2 The Vec2 coordinate.
|
||||
-- @return DCS#Vec2 The Vec2 coordinate.
|
||||
function ZONE_POLYGON_BASE:GetRandomVec2()
|
||||
self:F2()
|
||||
|
||||
@@ -1355,9 +1469,9 @@ function ZONE_POLYGON_BASE:GetRandomVec2()
|
||||
return Vec2
|
||||
end
|
||||
|
||||
--- Return a @{Point#POINT_VEC2} object representing a random 2D point at landheight within the zone.
|
||||
--- Return a @{Core.Point#POINT_VEC2} object representing a random 2D point at landheight within the zone.
|
||||
-- @param #ZONE_POLYGON_BASE self
|
||||
-- @return @{Point#POINT_VEC2}
|
||||
-- @return @{Core.Point#POINT_VEC2}
|
||||
function ZONE_POLYGON_BASE:GetRandomPointVec2()
|
||||
self:F2()
|
||||
|
||||
@@ -1368,9 +1482,9 @@ function ZONE_POLYGON_BASE:GetRandomPointVec2()
|
||||
return PointVec2
|
||||
end
|
||||
|
||||
--- Return a @{Point#POINT_VEC3} object representing a random 3D point at landheight within the zone.
|
||||
--- Return a @{Core.Point#POINT_VEC3} object representing a random 3D point at landheight within the zone.
|
||||
-- @param #ZONE_POLYGON_BASE self
|
||||
-- @return @{Point#POINT_VEC3}
|
||||
-- @return @{Core.Point#POINT_VEC3}
|
||||
function ZONE_POLYGON_BASE:GetRandomPointVec3()
|
||||
self:F2()
|
||||
|
||||
@@ -1382,7 +1496,7 @@ function ZONE_POLYGON_BASE:GetRandomPointVec3()
|
||||
end
|
||||
|
||||
|
||||
--- Return a @{Point#COORDINATE} object representing a random 3D point at landheight within the zone.
|
||||
--- Return a @{Core.Point#COORDINATE} object representing a random 3D point at landheight within the zone.
|
||||
-- @param #ZONE_POLYGON_BASE self
|
||||
-- @return Core.Point#COORDINATE
|
||||
function ZONE_POLYGON_BASE:GetRandomCoordinate()
|
||||
@@ -1423,18 +1537,36 @@ end
|
||||
-- @extends #ZONE_POLYGON_BASE
|
||||
|
||||
|
||||
--- # ZONE_POLYGON class, extends @{Zone#ZONE_POLYGON_BASE}
|
||||
--- The ZONE_POLYGON class defined by a sequence of @{Wrapper.Group#GROUP} waypoints within the Mission Editor, forming a polygon.
|
||||
-- This class implements the inherited functions from @{Core.Zone#ZONE_RADIUS} taking into account the own zone format and properties.
|
||||
--
|
||||
-- The ZONE_POLYGON class defined by a sequence of @{Group#GROUP} waypoints within the Mission Editor, forming a polygon.
|
||||
-- This class implements the inherited functions from @{Zone#ZONE_RADIUS} taking into account the own zone format and properties.
|
||||
-- ## Declare a ZONE_POLYGON directly in the DCS mission editor!
|
||||
--
|
||||
-- You can declare a ZONE_POLYGON using the DCS mission editor by adding the ~ZONE_POLYGON tag in the group name.
|
||||
--
|
||||
-- So, imagine you have a group declared in the mission editor, with group name `DefenseZone~ZONE_POLYGON`.
|
||||
-- Then during mission startup, when loading Moose.lua, this group will be detected as a ZONE_POLYGON declaration.
|
||||
-- Within the background, a ZONE_POLYGON object will be created within the @{Core.Database} using the properties of the group.
|
||||
-- The ZONE_POLYGON name will be the group name without the ~ZONE_POLYGON tag.
|
||||
--
|
||||
-- So, you can search yourself for the ZONE_POLYGON by using the @{#ZONE_POLYGON.FindByName}() method.
|
||||
-- In this example, `local PolygonZone = ZONE_POLYGON:FindByName( "DefenseZone" )` would return the ZONE_POLYGON object
|
||||
-- that was created at mission startup, and reference it into the `PolygonZone` local object.
|
||||
--
|
||||
-- Mission `ZON-510` shows a demonstration of this feature or method.
|
||||
--
|
||||
-- This is especially handy if you want to quickly setup a SET_ZONE...
|
||||
-- So when you would declare `local SetZone = SET_ZONE:New():FilterPrefixes( "Defense" ):FilterStart()`,
|
||||
-- then SetZone would contain the ZONE_POLYGON object `DefenseZone` as part of the zone collection,
|
||||
-- without much scripting overhead!!!
|
||||
--
|
||||
-- @field #ZONE_POLYGON
|
||||
ZONE_POLYGON = {
|
||||
ClassName="ZONE_POLYGON",
|
||||
}
|
||||
|
||||
--- Constructor to create a ZONE_POLYGON instance, taking the zone name and the @{Group#GROUP} defined within the Mission Editor.
|
||||
-- The @{Group#GROUP} waypoints define the polygon corners. The first and the last point are automatically connected by ZONE_POLYGON.
|
||||
--- Constructor to create a ZONE_POLYGON instance, taking the zone name and the @{Wrapper.Group#GROUP} defined within the Mission Editor.
|
||||
-- The @{Wrapper.Group#GROUP} waypoints define the polygon corners. The first and the last point are automatically connected by ZONE_POLYGON.
|
||||
-- @param #ZONE_POLYGON self
|
||||
-- @param #string ZoneName Name of the zone.
|
||||
-- @param Wrapper.Group#GROUP ZoneGroup The GROUP waypoints as defined within the Mission Editor define the polygon shape.
|
||||
@@ -1446,14 +1578,16 @@ function ZONE_POLYGON:New( ZoneName, ZoneGroup )
|
||||
local self = BASE:Inherit( self, ZONE_POLYGON_BASE:New( ZoneName, GroupPoints ) )
|
||||
self:F( { ZoneName, ZoneGroup, self._.Polygon } )
|
||||
|
||||
-- Zone objects are added to the _DATABASE and SET_ZONE objects.
|
||||
_EVENTDISPATCHER:CreateEventNewZone( self )
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Constructor to create a ZONE_POLYGON instance, taking the zone name and the **name** of the @{Group#GROUP} defined within the Mission Editor.
|
||||
-- The @{Group#GROUP} waypoints define the polygon corners. The first and the last point are automatically connected by ZONE_POLYGON.
|
||||
--- Constructor to create a ZONE_POLYGON instance, taking the zone name and the **name** of the @{Wrapper.Group#GROUP} defined within the Mission Editor.
|
||||
-- The @{Wrapper.Group#GROUP} waypoints define the polygon corners. The first and the last point are automatically connected by ZONE_POLYGON.
|
||||
-- @param #ZONE_POLYGON self
|
||||
-- @param #string ZoneName Name of the zone.
|
||||
-- @param #string GroupName The group name of the GROUP defining the waypoints within the Mission Editor to define the polygon shape.
|
||||
-- @return #ZONE_POLYGON self
|
||||
function ZONE_POLYGON:NewFromGroupName( GroupName )
|
||||
@@ -1465,6 +1599,120 @@ function ZONE_POLYGON:NewFromGroupName( GroupName )
|
||||
local self = BASE:Inherit( self, ZONE_POLYGON_BASE:New( GroupName, GroupPoints ) )
|
||||
self:F( { GroupName, ZoneGroup, self._.Polygon } )
|
||||
|
||||
-- Zone objects are added to the _DATABASE and SET_ZONE objects.
|
||||
_EVENTDISPATCHER:CreateEventNewZone( self )
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Find a polygon zone in the _DATABASE using the name of the polygon zone.
|
||||
-- @param #ZONE_POLYGON self
|
||||
-- @param #string ZoneName The name of the polygon zone.
|
||||
-- @return #ZONE_POLYGON self
|
||||
function ZONE_POLYGON:FindByName( ZoneName )
|
||||
|
||||
local ZoneFound = _DATABASE:FindZone( ZoneName )
|
||||
return ZoneFound
|
||||
end
|
||||
|
||||
do -- ZONE_AIRBASE
|
||||
|
||||
--- @type ZONE_AIRBASE
|
||||
-- @extends #ZONE_RADIUS
|
||||
|
||||
|
||||
--- The ZONE_AIRBASE class defines by a zone around a @{Wrapper.Airbase#AIRBASE} with a radius.
|
||||
-- This class implements the inherited functions from @{Core.Zone#ZONE_RADIUS} taking into account the own zone format and properties.
|
||||
--
|
||||
-- @field #ZONE_AIRBASE
|
||||
ZONE_AIRBASE = {
|
||||
ClassName="ZONE_AIRBASE",
|
||||
}
|
||||
|
||||
|
||||
|
||||
--- Constructor to create a ZONE_AIRBASE instance, taking the zone name, a zone @{Wrapper.Airbase#AIRBASE} and a radius.
|
||||
-- @param #ZONE_AIRBASE self
|
||||
-- @param #string AirbaseName Name of the airbase.
|
||||
-- @param DCS#Distance Radius (Optional)The radius of the zone in meters. Default 4000 meters.
|
||||
-- @return #ZONE_AIRBASE self
|
||||
function ZONE_AIRBASE:New( AirbaseName, Radius )
|
||||
|
||||
Radius=Radius or 4000
|
||||
|
||||
local Airbase = AIRBASE:FindByName( AirbaseName )
|
||||
|
||||
local self = BASE:Inherit( self, ZONE_RADIUS:New( AirbaseName, Airbase:GetVec2(), Radius ) )
|
||||
|
||||
self._.ZoneAirbase = Airbase
|
||||
self._.ZoneVec2Cache = self._.ZoneAirbase:GetVec2()
|
||||
|
||||
-- Zone objects are added to the _DATABASE and SET_ZONE objects.
|
||||
_EVENTDISPATCHER:CreateEventNewZone( self )
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Get the airbase as part of the ZONE_AIRBASE object.
|
||||
-- @param #ZONE_AIRBASE self
|
||||
-- @return Wrapper.Airbase#AIRBASE The airbase.
|
||||
function ZONE_AIRBASE:GetAirbase()
|
||||
return self._.ZoneAirbase
|
||||
end
|
||||
|
||||
--- Returns the current location of the @{Wrapper.Group}.
|
||||
-- @param #ZONE_AIRBASE self
|
||||
-- @return DCS#Vec2 The location of the zone based on the @{Wrapper.Group} location.
|
||||
function ZONE_AIRBASE:GetVec2()
|
||||
self:F( self.ZoneName )
|
||||
|
||||
local ZoneVec2 = nil
|
||||
|
||||
if self._.ZoneAirbase:IsAlive() then
|
||||
ZoneVec2 = self._.ZoneAirbase:GetVec2()
|
||||
self._.ZoneVec2Cache = ZoneVec2
|
||||
else
|
||||
ZoneVec2 = self._.ZoneVec2Cache
|
||||
end
|
||||
|
||||
self:T( { ZoneVec2 } )
|
||||
|
||||
return ZoneVec2
|
||||
end
|
||||
|
||||
--- Returns a random location within the zone of the @{Wrapper.Group}.
|
||||
-- @param #ZONE_AIRBASE self
|
||||
-- @return DCS#Vec2 The random location of the zone based on the @{Wrapper.Group} location.
|
||||
function ZONE_AIRBASE:GetRandomVec2()
|
||||
self:F( self.ZoneName )
|
||||
|
||||
local Point = {}
|
||||
local Vec2 = self._.ZoneAirbase:GetVec2()
|
||||
|
||||
local angle = math.random() * math.pi*2;
|
||||
Point.x = Vec2.x + math.cos( angle ) * math.random() * self:GetRadius();
|
||||
Point.y = Vec2.y + math.sin( angle ) * math.random() * self:GetRadius();
|
||||
|
||||
self:T( { Point } )
|
||||
|
||||
return Point
|
||||
end
|
||||
|
||||
--- Returns a @{Core.Point#POINT_VEC2} object reflecting a random 2D location within the zone.
|
||||
-- @param #ZONE_AIRBASE self
|
||||
-- @param #number inner (optional) Minimal distance from the center of the zone. Default is 0.
|
||||
-- @param #number outer (optional) Maximal distance from the outer edge of the zone. Default is the radius of the zone.
|
||||
-- @return Core.Point#POINT_VEC2 The @{Core.Point#POINT_VEC2} object reflecting the random 3D location within the zone.
|
||||
function ZONE_AIRBASE:GetRandomPointVec2( inner, outer )
|
||||
self:F( self.ZoneName, inner, outer )
|
||||
|
||||
local PointVec2 = POINT_VEC2:NewFromVec2( self:GetRandomVec2() )
|
||||
|
||||
self:T3( { PointVec2 } )
|
||||
|
||||
return PointVec2
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
1202
Moose Development/Moose/DCS.lua
Normal file
1202
Moose Development/Moose/DCS.lua
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,54 +0,0 @@
|
||||
-------------------------------------------------------------------------------
|
||||
-- @module DCSAirbase
|
||||
|
||||
|
||||
--- Represents airbases: airdromes, helipads and ships with flying decks or landing pads.
|
||||
-- @type Airbase
|
||||
-- @extends Dcs.DCSCoalitionWrapper.Object#CoalitionObject
|
||||
-- @field #Airbase.ID ID Identifier of an airbase. It assigned to an airbase by the Mission Editor automatically. This identifier is used in AI tasks to refer an airbase that exists (spawned and not dead) or not.
|
||||
-- @field #Airbase.Category Category enum contains identifiers of airbase categories.
|
||||
-- @field #Airbase.Desc Desc Airbase descriptor. Airdromes are unique and their types are unique, but helipads and ships are not always unique and may have the same type.
|
||||
|
||||
--- Enum contains identifiers of airbase categories.
|
||||
-- @type Airbase.Category
|
||||
-- @field AIRDROME
|
||||
-- @field HELIPAD
|
||||
-- @field SHIP
|
||||
|
||||
--- Airbase descriptor. Airdromes are unique and their types are unique, but helipads and ships are not always unique and may have the same type.
|
||||
-- @type Airbase.Desc
|
||||
-- @extends #Desc
|
||||
-- @field #Airbase.Category category Category of the airbase type.
|
||||
|
||||
--- Returns airbase by its name. If no airbase found the function will return nil.
|
||||
-- @function [parent=#Airbase] getByName
|
||||
-- @param #string name
|
||||
-- @return #Airbase
|
||||
|
||||
--- Returns airbase descriptor by type name. If no descriptor is found the function will return nil.
|
||||
-- @function [parent=#Airbase] getDescByName
|
||||
-- @param #TypeName typeName Airbase type name.
|
||||
-- @return #Airbase.Desc
|
||||
|
||||
--- Returns Unit that is corresponded to the airbase. Works only for ships.
|
||||
-- @function [parent=#Airbase] getUnit
|
||||
-- @param self
|
||||
-- @return Wrapper.Unit#Unit
|
||||
|
||||
--- Returns identifier of the airbase.
|
||||
-- @function [parent=#Airbase] getID
|
||||
-- @param self
|
||||
-- @return #Airbase.ID
|
||||
|
||||
--- Returns the airbase's callsign - the localized string.
|
||||
-- @function [parent=#Airbase] getCallsign
|
||||
-- @param self
|
||||
-- @return #string
|
||||
|
||||
--- Returns descriptor of the airbase.
|
||||
-- @function [parent=#Airbase] getDesc
|
||||
-- @param self
|
||||
-- @return #Airbase.Desc
|
||||
|
||||
|
||||
Airbase = {} --#Airbase
|
||||
@@ -1,20 +0,0 @@
|
||||
-------------------------------------------------------------------------------
|
||||
-- @module DCSCoalitionObject
|
||||
|
||||
--- @type CoalitionObject
|
||||
-- @extends Dcs.DCSWrapper.Object#Object
|
||||
|
||||
|
||||
|
||||
--- Returns coalition of the object.
|
||||
-- @function [parent=#CoalitionObject] getCoalition
|
||||
-- @param #CoalitionObject self
|
||||
-- @return Dcs.DCSTypes#coalition.side
|
||||
|
||||
--- Returns object country.
|
||||
-- @function [parent=#CoalitionObject] getCountry
|
||||
-- @param #CoalitionObject self
|
||||
-- @return #country.id
|
||||
|
||||
|
||||
CoalitionObject = {} --#CoalitionObject
|
||||
@@ -1,10 +0,0 @@
|
||||
--- @module DCSCommand
|
||||
|
||||
|
||||
--- @type Command
|
||||
-- @field #string id
|
||||
-- @field #Command.params params
|
||||
|
||||
--- @type Command.params
|
||||
|
||||
env.info( "Command defined" )
|
||||
@@ -1,115 +0,0 @@
|
||||
-------------------------------------------------------------------------------
|
||||
-- @module DCSController
|
||||
|
||||
--- Controller is an object that performs A.I.-routines. Other words controller is an instance of A.I.. Controller stores current main task, active enroute tasks and behavior options. Controller performs commands. Please, read DCS A-10C GUI Manual EN.pdf chapter "Task Planning for Unit Groups", page 91 to understand A.I. system of DCS:A-10C.
|
||||
--
|
||||
-- This class has 2 types of functions:
|
||||
--
|
||||
-- * Tasks
|
||||
-- * Commands: Commands are instant actions those required zero time to perform. Commands may be used both for control unit/group behavior and control game mechanics.
|
||||
-- @type Controller
|
||||
-- @field #Controller.Detection Detection Enum contains identifiers of surface types.
|
||||
|
||||
--- Enables and disables the controller.
|
||||
-- Note: Now it works only for ground / naval groups!
|
||||
-- @function [parent=#Controller] setOnOff
|
||||
-- @param self
|
||||
-- @param #boolean value Enable / Disable.
|
||||
|
||||
-- Tasks
|
||||
|
||||
--- Resets current task and then sets the task to the controller. Task is a table that contains task identifier and task parameters.
|
||||
-- @function [parent=#Controller] setTask
|
||||
-- @param self
|
||||
-- @param #Task task
|
||||
|
||||
--- Resets current task of the controller.
|
||||
-- @function [parent=#Controller] resetTask
|
||||
-- @param self
|
||||
|
||||
--- Pushes the task to the front of the queue and makes the task active. Further call of function Controller.setTask() function will stop current task, clear the queue and set the new task active. If the task queue is empty the function will work like function Controller.setTask() function.
|
||||
-- @function [parent=#Controller] pushTask
|
||||
-- @param self
|
||||
-- @param #Task task
|
||||
|
||||
--- Pops current (front) task from the queue and makes active next task in the queue (if exists). If no more tasks in the queue the function works like function Controller.resetTask() function. Does nothing if the queue is empty.
|
||||
-- @function [parent=#Controller] popTask
|
||||
-- @param self
|
||||
|
||||
--- Returns true if the controller has a task.
|
||||
-- @function [parent=#Controller] hasTask
|
||||
-- @param self
|
||||
-- @return #boolean
|
||||
|
||||
-- Commands
|
||||
|
||||
--TODO: describe #Command structure
|
||||
--- Sets the command to perform by controller.
|
||||
-- @function [parent=#Controller] setCommand
|
||||
-- @param self
|
||||
-- @param #Command command Table that contains command identifier and command parameters.
|
||||
|
||||
|
||||
-- Behaviours
|
||||
|
||||
--- Sets the option to the controller.
|
||||
-- Option is a pair of identifier and value. Behavior options are global parameters those affect controller behavior in all tasks it performs.
|
||||
-- Option identifiers and values are stored in table AI.Option in subtables Air, Ground and Naval.
|
||||
--
|
||||
-- OptionId = @{#AI.Option.Air.id} or @{#AI.Option.Ground.id} or @{#AI.Option.Naval.id}
|
||||
-- OptionValue = AI.Option.Air.val[optionName] or AI.Option.Ground.val[optionName] or AI.Option.Naval.val[optionName]
|
||||
--
|
||||
-- @function [parent=#Controller] setOption
|
||||
-- @param self
|
||||
-- @param #OptionId optionId Option identifier.
|
||||
-- @param #OptionValue optionValue Value of the option.
|
||||
|
||||
|
||||
-- Detection
|
||||
|
||||
--- Enum contains identifiers of surface types.
|
||||
-- @type Controller.Detection
|
||||
-- @field VISUAL
|
||||
-- @field OPTIC
|
||||
-- @field RADAR
|
||||
-- @field IRST
|
||||
-- @field RWR
|
||||
-- @field DLINK
|
||||
|
||||
--- Detected target.
|
||||
-- @type DetectedTarget
|
||||
-- @field Wrapper.Object#Object object The target
|
||||
-- @field #boolean visible The target is visible
|
||||
-- @field #boolean type The target type is known
|
||||
-- @field #boolean distance Distance to the target is known
|
||||
|
||||
|
||||
--- Checks if the target is detected or not. If one or more detection method is specified the function will return true if the target is detected by at least one of these methods. If no detection methods are specified the function will return true if the target is detected by any method.
|
||||
-- @function [parent=#Controller] isTargetDetected
|
||||
-- @param self
|
||||
-- @param Wrapper.Object#Object target Target to check
|
||||
-- @param #Controller.Detection detection Controller.Detection detection1, Controller.Detection detection2, ... Controller.Detection detectionN
|
||||
-- @return #boolean detected True if the target is detected.
|
||||
-- @return #boolean visible Has effect only if detected is true. True if the target is visible now.
|
||||
-- @return #ModelTime lastTime Has effect only if visible is false. Last time when target was seen.
|
||||
-- @return #boolean type Has effect only if detected is true. True if the target type is known.
|
||||
-- @return #boolean distance Has effect only if detected is true. True if the distance to the target is known.
|
||||
-- @return #Vec3 lastPos Has effect only if visible is false. Last position of the target when it was seen.
|
||||
-- @return #Vec3 lastVel Has effect only if visible is false. Last velocity of the target when it was seen.
|
||||
|
||||
|
||||
--- Returns list of detected targets. If one or more detection method is specified the function will return targets which were detected by at least one of these methods. If no detection methods are specified the function will return targets which were detected by any method.
|
||||
-- @function [parent=#Controller] getDetectedTargets
|
||||
-- @param self
|
||||
-- @param #Controller.Detection detection Controller.Detection detection1, Controller.Detection detection2, ... Controller.Detection detectionN
|
||||
-- @return #list<#DetectedTarget> array of DetectedTarget
|
||||
|
||||
--- Know a target.
|
||||
-- @function [parent=#Controller] knowTarget
|
||||
-- @param self
|
||||
-- @param Wrapper.Object#Object object The target.
|
||||
-- @param #boolean type Target type is known.
|
||||
-- @param #boolean distance Distance to target is known.
|
||||
|
||||
|
||||
Controller = {} --#Controller
|
||||
@@ -1,83 +0,0 @@
|
||||
-------------------------------------------------------------------------------
|
||||
-- @module DCSGroup
|
||||
|
||||
--- Represents group of Units.
|
||||
-- @type Group
|
||||
-- @field #ID ID Identifier of a group. It is assigned to a group by Mission Editor automatically.
|
||||
-- @field #Group.Category Category Enum contains identifiers of group types.
|
||||
|
||||
--- Enum contains identifiers of group types.
|
||||
-- @type Group.Category
|
||||
-- @field AIRPLANE
|
||||
-- @field HELICOPTER
|
||||
-- @field GROUND
|
||||
-- @field SHIP
|
||||
|
||||
-- Static Functions
|
||||
|
||||
--- Returns group by the name assigned to the group in Mission Editor.
|
||||
-- @function [parent=#Group] getByName
|
||||
-- @param #string name
|
||||
-- @return #Group
|
||||
|
||||
-- Member Functions
|
||||
|
||||
--- returns true if the group exist or false otherwise.
|
||||
-- @function [parent=#Group] isExist
|
||||
-- @param #Group self
|
||||
-- @return #boolean
|
||||
|
||||
--- Destroys the group and all of its units.
|
||||
-- @function [parent=#Group] destroy
|
||||
-- @param #Group self
|
||||
|
||||
--- Returns category of the group.
|
||||
-- @function [parent=#Group] getCategory
|
||||
-- @param #Group self
|
||||
-- @return #Group.Category
|
||||
|
||||
--TODO check coalition.side
|
||||
|
||||
--- Returns the coalition of the group.
|
||||
-- @function [parent=#Group] getCoalition
|
||||
-- @param #Group self
|
||||
-- @return Dcs.DCSCoalitionWrapper.Object#coalition.side
|
||||
|
||||
--- Returns the group's name. This is the same name assigned to the group in Mission Editor.
|
||||
-- @function [parent=#Group] getName
|
||||
-- @param #Group self
|
||||
-- @return #string
|
||||
|
||||
--- Returns the group identifier.
|
||||
-- @function [parent=#Group] getID
|
||||
-- @param #Group self
|
||||
-- @return #ID
|
||||
|
||||
--- Returns the unit with number unitNumber. If the unit is not exists the function will return nil.
|
||||
-- @function [parent=#Group] getUnit
|
||||
-- @param #Group self
|
||||
-- @param #number unitNumber
|
||||
-- @return Dcs.DCSWrapper.Unit#Unit
|
||||
|
||||
--- Returns current size of the group. If some of the units will be destroyed, As units are destroyed the size of the group will be changed.
|
||||
-- @function [parent=#Group] getSize
|
||||
-- @param #Group self
|
||||
-- @return #number
|
||||
|
||||
--- Returns initial size of the group. If some of the units will be destroyed, initial size of the group will not be changed. Initial size limits the unitNumber parameter for Group.getUnit() function.
|
||||
-- @function [parent=#Group] getInitialSize
|
||||
-- @param #Group self
|
||||
-- @return #number
|
||||
|
||||
--- Returns array of the units present in the group now. Destroyed units will not be enlisted at all.
|
||||
-- @function [parent=#Group] getUnits
|
||||
-- @param #Group self
|
||||
-- @return #list<Dcs.DCSWrapper.Unit#Unit> array of Units
|
||||
|
||||
--- Returns controller of the group.
|
||||
-- @function [parent=#Group] getController
|
||||
-- @param #Group self
|
||||
-- @return Controller#Controller
|
||||
|
||||
Group = {} --#Group
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
-------------------------------------------------------------------------------
|
||||
-- @module DCSObject
|
||||
|
||||
--- @type Object
|
||||
-- @field #Object.Category Category
|
||||
-- @field #Object.Desc Desc
|
||||
|
||||
--- @type Object.Category
|
||||
-- @field UNIT
|
||||
-- @field WEAPON
|
||||
-- @field STATIC
|
||||
-- @field SCENERY
|
||||
-- @field BASE
|
||||
|
||||
--- @type Object.Desc
|
||||
-- @extends #Desc
|
||||
-- @field #number life initial life level
|
||||
-- @field #Box3 box bounding box of collision geometry
|
||||
|
||||
--- @function [parent=#Object] isExist
|
||||
-- @param #Object self
|
||||
-- @return #boolean
|
||||
|
||||
--- @function [parent=#Object] destroy
|
||||
-- @param #Object self
|
||||
|
||||
--- @function [parent=#Object] getCategory
|
||||
-- @param #Object self
|
||||
-- @return #Object.Category
|
||||
|
||||
--- Returns type name of the Object.
|
||||
-- @function [parent=#Object] getTypeName
|
||||
-- @param #Object self
|
||||
-- @return #string
|
||||
|
||||
--- Returns object descriptor.
|
||||
-- @function [parent=#Object] getDesc
|
||||
-- @param #Object self
|
||||
-- @return #Object.Desc
|
||||
|
||||
--- Returns true if the object belongs to the category.
|
||||
-- @function [parent=#Object] hasAttribute
|
||||
-- @param #Object self
|
||||
-- @param #AttributeName attributeName Attribute name to check.
|
||||
-- @return #boolean
|
||||
|
||||
--- Returns name of the object. This is the name that is assigned to the object in the Mission Editor.
|
||||
-- @function [parent=#Object] getName
|
||||
-- @param #Object self
|
||||
-- @return #string
|
||||
|
||||
--- Returns object coordinates for current time.
|
||||
-- @function [parent=#Object] getPoint
|
||||
-- @param #Object self
|
||||
-- @return #Vec3
|
||||
|
||||
--- Returns object position for current time.
|
||||
-- @function [parent=#Object] getPosition
|
||||
-- @param #Object self
|
||||
-- @return #Position3
|
||||
|
||||
--- Returns the unit's velocity vector.
|
||||
-- @function [parent=#Object] getVelocity
|
||||
-- @param #Object self
|
||||
-- @return #Vec3
|
||||
|
||||
--- Returns true if the unit is in air.
|
||||
-- @function [parent=#Object] inAir
|
||||
-- @param #Object self
|
||||
-- @return #boolean
|
||||
|
||||
Object = {} --#Object
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
-------------------------------------------------------------------------------
|
||||
-- @module DCSStaticObject
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- @module StaticObject
|
||||
-- @extends CoalitionWrapper.Object#CoalitionObject
|
||||
|
||||
--- Represents static object added in the Mission Editor.
|
||||
-- @type StaticObject
|
||||
-- @field #StaticObject.ID ID Identifier of a StaticObject. It assigned to an StaticObject by the Mission Editor automatically.
|
||||
-- @field #StaticObject.Desc Desc Descriptor of StaticObject and Unit are equal. StaticObject is just a passive variant of Unit.
|
||||
|
||||
--- StaticObject descriptor. Airdromes are unique and their types are unique, but helipads and ships are not always unique and may have the same type.
|
||||
-- @type StaticObject.Desc
|
||||
-- @extends Wrapper.Unit#Unit.Desc
|
||||
|
||||
--- Returns static object by its name. If no static object found nil will be returned.
|
||||
-- @function [parent=#StaticObject] getByName
|
||||
-- @param #string name Name of static object to find.
|
||||
-- @return #StaticObject
|
||||
|
||||
--- returns identifier of the static object.
|
||||
-- @function [parent=#StaticObject] getID
|
||||
-- @param #StaticObject self
|
||||
-- @return #StaticObject.ID
|
||||
|
||||
--- Returns descriptor of the StaticObject.
|
||||
-- @function [parent=#StaticObject] getDesc
|
||||
-- @param #StaticObject self
|
||||
-- @return #StaticObject.Desc
|
||||
|
||||
|
||||
StaticObject = {} --#StaticObject
|
||||
@@ -1,15 +0,0 @@
|
||||
--- @module DCSTask
|
||||
|
||||
|
||||
--- A task descriptor (internal structure for DCS World)
|
||||
-- @type Task
|
||||
-- @field #string id
|
||||
-- @field #Task.param param
|
||||
|
||||
--- @type Task.param
|
||||
|
||||
--- List of @{#Task}
|
||||
-- @type TaskArray
|
||||
-- @list <#Task>
|
||||
|
||||
env.info( "Task defined" )
|
||||
@@ -1,8 +0,0 @@
|
||||
-------------------------------------------------------------------------------
|
||||
-- @module DCSTime
|
||||
|
||||
--- @type ModelTime
|
||||
-- @extends #number
|
||||
|
||||
--- @type Time
|
||||
-- @extends #number
|
||||
@@ -1,246 +0,0 @@
|
||||
-------------------------------------------------------------------------------
|
||||
-- @module DCSTypes
|
||||
|
||||
|
||||
|
||||
--- Time is given in seconds.
|
||||
-- @type Time
|
||||
-- @extends #number
|
||||
|
||||
--- Model time is the time that drives the simulation. Model time may be stopped, accelerated and decelerated relative real time.
|
||||
-- @type ModelTime
|
||||
-- @extends #number
|
||||
|
||||
--- Mission time is a model time plus time of the mission start.
|
||||
-- @type MissionTime
|
||||
-- @extends #number
|
||||
|
||||
|
||||
--- Distance is given in meters.
|
||||
-- @type Distance
|
||||
-- @extends #number
|
||||
|
||||
--- Angle is given in radians.
|
||||
-- @type Angle
|
||||
-- @extends #number
|
||||
|
||||
--- Azimuth is an angle of rotation around world axis y counter-clockwise.
|
||||
-- @type Azimuth
|
||||
-- @extends #number
|
||||
|
||||
--- Mass is given in kilograms.
|
||||
-- @type Mass
|
||||
-- @extends #number
|
||||
|
||||
--- Vec3 type is a 3D-vector.
|
||||
-- DCS world has 3-dimensional coordinate system. DCS ground is an infinite plain.
|
||||
-- @type Vec3
|
||||
-- @field #Distance x is directed to the north
|
||||
-- @field #Distance z is directed to the east
|
||||
-- @field #Distance y is directed up
|
||||
|
||||
--- Vec2 is a 2D-vector for the ground plane as a reference plane.
|
||||
-- @type Vec2
|
||||
-- @field #Distance x Vec2.x = Vec3.x
|
||||
-- @field #Distance y Vec2.y = Vec3.z
|
||||
|
||||
--- Position is a composite structure. It consists of both coordinate vector and orientation matrix. Position3 (also known as "Pos3" for short) is a table that has following format:
|
||||
-- @type Position3
|
||||
-- @field #Vec3 p
|
||||
-- @field #Vec3 x
|
||||
-- @field #Vec3 y
|
||||
-- @field #Vec3 z
|
||||
|
||||
--- 3-dimensional box.
|
||||
-- @type Box3
|
||||
-- @field #Vec3 min
|
||||
-- @field #Vec3 max
|
||||
|
||||
--- Each object belongs to a type. Object type is a named couple of properties those independent of mission and common for all units of the same type. Name of unit type is a string. Samples of unit type: "Su-27", "KAMAZ" and "M2 Bradley".
|
||||
-- @type TypeName
|
||||
-- @extends #string
|
||||
|
||||
--- AttributeName = string
|
||||
-- Each object type may have attributes.
|
||||
-- Attributes are enlisted in ./Scripts/Database/db_attributes.Lua.
|
||||
-- To know what attributes the object type has, look for the unit type script in sub-directories planes/, helicopter/s, vehicles, navy/ of ./Scripts/Database/ directory.
|
||||
-- @type AttributeName
|
||||
-- @extends #string
|
||||
|
||||
--- List of @{#AttributeName}
|
||||
-- @type AttributeNameArray
|
||||
-- @list <#AttributeName>
|
||||
|
||||
--- @type AI
|
||||
-- @field #AI.Skill Skill
|
||||
-- @field #AI.Task Task
|
||||
-- @field #AI.Option Option
|
||||
|
||||
--- @type AI.Skill
|
||||
-- @field AVERAGE
|
||||
-- @field GOOD
|
||||
-- @field HIGH
|
||||
-- @field EXCELLENT
|
||||
-- @field PLAYER
|
||||
-- @field CLIENT
|
||||
|
||||
--- @type AI.Task
|
||||
-- @field #AI.Task.WeaponExpend WeaponExpend
|
||||
-- @field #AI.Task.OrbitPattern OrbitPattern
|
||||
-- @field #AI.Task.Designation Designation
|
||||
-- @field #AI.Task.WaypointType WaypointType
|
||||
-- @field #AI.Task.TurnMethod TurnMethod
|
||||
-- @field #AI.Task.AltitudeType AltitudeType
|
||||
-- @field #AI.Task.VehicleFormation VehicleFormation
|
||||
|
||||
--- @type AI.Task.WeaponExpend
|
||||
-- @field ONE
|
||||
-- @field TWO
|
||||
-- @field FOUR
|
||||
-- @field QUARTER
|
||||
-- @field HALF
|
||||
-- @field ALL
|
||||
|
||||
--- @type AI.Task.OrbitPattern
|
||||
-- @field CIRCLE
|
||||
-- @field RACE_TRACK
|
||||
|
||||
--- @type AI.Task.Designation
|
||||
-- @field NO
|
||||
-- @field AUTO
|
||||
-- @field WP
|
||||
-- @field IR_POINTER
|
||||
-- @field LASER
|
||||
|
||||
--- @type AI.Task.WaypointType
|
||||
-- @field TAKEOFF
|
||||
-- @field TAKEOFF_PARKING
|
||||
-- @field TURNING_POINT
|
||||
-- @field LAND
|
||||
|
||||
--- @type AI.Task.TurnMethod
|
||||
-- @field FLY_OVER_POINT
|
||||
-- @field FIN_POINT
|
||||
|
||||
--- @type AI.Task.AltitudeType
|
||||
-- @field BARO
|
||||
-- @field RADIO
|
||||
|
||||
--- @type AI.Task.VehicleFormation
|
||||
-- @field OFF_ROAD
|
||||
-- @field ON_ROAD
|
||||
-- @field RANK
|
||||
-- @field CONE
|
||||
-- @field DIAMOND
|
||||
-- @field VEE
|
||||
-- @field ECHELON_LEFT
|
||||
-- @field ECHELON_RIGHT
|
||||
|
||||
--- @type AI.Option
|
||||
-- @field #AI.Option.Air Air
|
||||
-- @field #AI.Option.Ground Ground
|
||||
-- @field #AI.Option.Naval Naval
|
||||
|
||||
--- @type AI.Option.Air
|
||||
-- @field #AI.Option.Air.id id
|
||||
-- @field #AI.Option.Air.val val
|
||||
|
||||
--- @type AI.Option.Ground
|
||||
-- @field #AI.Option.Ground.id id
|
||||
-- @field #AI.Option.Ground.val val
|
||||
|
||||
--- @type AI.Option.Naval
|
||||
-- @field #AI.Option.Naval.id id
|
||||
-- @field #AI.Option.Naval.val val
|
||||
|
||||
--TODO: work on formation
|
||||
--- @type AI.Option.Air.id
|
||||
-- @field NO_OPTION
|
||||
-- @field ROE
|
||||
-- @field REACTION_ON_THREAT
|
||||
-- @field RADAR_USING
|
||||
-- @field FLARE_USING
|
||||
-- @field FORMATION
|
||||
-- @field RTB_ON_BINGO
|
||||
-- @field SILENCE
|
||||
|
||||
--- @type AI.Option.Air.val
|
||||
-- @field #AI.Option.Air.val.ROE ROE
|
||||
-- @field #AI.Option.Air.val.REACTION_ON_THREAT REACTION_ON_THREAT
|
||||
-- @field #AI.Option.Air.val.RADAR_USING RADAR_USING
|
||||
-- @field #AI.Option.Air.val.FLARE_USING FLARE_USING
|
||||
|
||||
--- @type AI.Option.Air.val.ROE
|
||||
-- @field WEAPON_FREE
|
||||
-- @field OPEN_FIRE_WEAPON_FREE
|
||||
-- @field OPEN_FIRE
|
||||
-- @field RETURN_FIRE
|
||||
-- @field WEAPON_HOLD
|
||||
|
||||
--- @type AI.Option.Air.val.REACTION_ON_THREAT
|
||||
-- @field NO_REACTION
|
||||
-- @field PASSIVE_DEFENCE
|
||||
-- @field EVADE_FIRE
|
||||
-- @field BYPASS_AND_ESCAPE
|
||||
-- @field ALLOW_ABORT_MISSION
|
||||
|
||||
--- @type AI.Option.Air.val.RADAR_USING
|
||||
-- @field NEVER
|
||||
-- @field FOR_ATTACK_ONLY
|
||||
-- @field FOR_SEARCH_IF_REQUIRED
|
||||
-- @field FOR_CONTINUOUS_SEARCH
|
||||
|
||||
--- @type AI.Option.Air.val.FLARE_USING
|
||||
-- @field NEVER
|
||||
-- @field AGAINST_FIRED_MISSILE
|
||||
-- @field WHEN_FLYING_IN_SAM_WEZ
|
||||
-- @field WHEN_FLYING_NEAR_ENEMIES
|
||||
|
||||
--- @type AI.Option.Ground.id
|
||||
-- @field NO_OPTION
|
||||
-- @field ROE @{#AI.Option.Ground.val.ROE}
|
||||
-- @field DISPERSE_ON_ATTACK true or false
|
||||
-- @field ALARM_STATE @{#AI.Option.Ground.val.ALARM_STATE}
|
||||
|
||||
--- @type AI.Option.Ground.val
|
||||
-- @field #AI.Option.Ground.val.ROE ROE
|
||||
-- @field #AI.Option.Ground.val.ALARM_STATE ALARM_STATE
|
||||
|
||||
--- @type AI.Option.Ground.val.ROE
|
||||
-- @field OPEN_FIRE
|
||||
-- @field RETURN_FIRE
|
||||
-- @field WEAPON_HOLD
|
||||
|
||||
--- @type AI.Option.Ground.val.ALARM_STATE
|
||||
-- @field AUTO
|
||||
-- @field GREEN
|
||||
-- @field RED
|
||||
|
||||
--- @type AI.Option.Naval.id
|
||||
-- @field NO_OPTION
|
||||
-- @field ROE
|
||||
|
||||
--- @type AI.Option.Naval.val
|
||||
-- @field #AI.Option.Naval.val.ROE ROE
|
||||
|
||||
--- @type AI.Option.Naval.val.ROE
|
||||
-- @field OPEN_FIRE
|
||||
-- @field RETURN_FIRE
|
||||
-- @field WEAPON_HOLD
|
||||
|
||||
AI = {} --#AI
|
||||
|
||||
|
||||
--- @type Desc
|
||||
-- @field #TypeName typeName type name
|
||||
-- @field #string displayName localized display name
|
||||
-- @field #table attributes object type attributes
|
||||
|
||||
--- A distance type
|
||||
-- @type Distance
|
||||
|
||||
--- An angle type
|
||||
-- @type Angle
|
||||
|
||||
env.info( 'AI types created' )
|
||||
|
||||
@@ -1,241 +0,0 @@
|
||||
-------------------------------------------------------------------------------
|
||||
-- @module DCSUnit
|
||||
|
||||
--- @type Unit
|
||||
-- @extends Dcs.DCSCoalitionWrapper.Object#CoalitionObject
|
||||
-- @field ID Identifier of an unit. It assigned to an unit by the Mission Editor automatically.
|
||||
-- @field #Unit.Category Category
|
||||
-- @field #Unit.RefuelingSystem RefuelingSystem
|
||||
-- @field #Unit.SensorType SensorType
|
||||
-- @field #Unit.OpticType OpticType
|
||||
-- @field #Unit.RadarType RadarType
|
||||
-- @field #Unit.Desc Desc
|
||||
-- @field #Unit.DescAircraft DescAircraft
|
||||
-- @field #Unit.DescAirplane DescAirplane
|
||||
-- @field #Unit.DescHelicopter DescHelicopter
|
||||
-- @field #Unit.DescVehicle DescVehicle
|
||||
-- @field #Unit.DescShip DescShip
|
||||
-- @field #Unit.AmmoItem AmmoItem
|
||||
-- @field #list<#Unit.AmmoItem> Ammo
|
||||
-- @field #Unit.Sensor Sensor
|
||||
-- @field #Unit.Optic Optic
|
||||
-- @field #Unit.Radar Radar
|
||||
-- @field #Unit.IRST IRST
|
||||
|
||||
|
||||
--- Enum that stores unit categories.
|
||||
-- @type Unit.Category
|
||||
-- @field AIRPLANE
|
||||
-- @field HELICOPTER
|
||||
-- @field GROUND_UNIT
|
||||
-- @field SHIP
|
||||
-- @field STRUCTURE
|
||||
|
||||
--- Enum that stores aircraft refueling system types.
|
||||
-- @type Unit.RefuelingSystem
|
||||
-- @field BOOM_AND_RECEPTACLE
|
||||
-- @field PROBE_AND_DROGUE
|
||||
|
||||
--- Enum that stores sensor types.
|
||||
-- @type Unit.SensorType
|
||||
-- @field OPTIC
|
||||
-- @field RADAR
|
||||
-- @field IRST
|
||||
-- @field RWR
|
||||
|
||||
--- Enum that stores types of optic sensors.
|
||||
-- @type Unit.OpticType
|
||||
-- @field TV TV-sensor
|
||||
-- @field LLTV Low-level TV-sensor
|
||||
-- @field IR Infra-Red optic sensor
|
||||
|
||||
--- Enum that stores radar types.
|
||||
-- @type Unit.RadarType
|
||||
-- @field AS air search radar
|
||||
-- @field SS surface/land search radar
|
||||
|
||||
|
||||
--- A unit descriptor.
|
||||
-- @type Unit.Desc
|
||||
-- @extends Wrapper.Object#Object.Desc
|
||||
-- @field #Unit.Category category Unit Category
|
||||
-- @field #Mass massEmpty mass of empty unit
|
||||
-- @field #number speedMax istance / Time, --maximal velocity
|
||||
|
||||
--- An aircraft descriptor.
|
||||
-- @type Unit.DescAircraft
|
||||
-- @extends Wrapper.Unit#Unit.Desc
|
||||
-- @field #Mass fuelMassMax maximal inner fuel mass
|
||||
-- @field #Distance range Operational range
|
||||
-- @field #Distance Hmax Ceiling
|
||||
-- @field #number VyMax #Distance / #Time, --maximal climb rate
|
||||
-- @field #number NyMin minimal safe acceleration
|
||||
-- @field #number NyMax maximal safe acceleration
|
||||
-- @field #Unit.RefuelingSystem tankerType refueling system type
|
||||
|
||||
--- An airplane descriptor.
|
||||
-- @type Unit.DescAirplane
|
||||
-- @extends Wrapper.Unit#Unit.DescAircraft
|
||||
-- @field #number speedMax0 Distance / Time maximal TAS at ground level
|
||||
-- @field #number speedMax10K Distance / Time maximal TAS at altitude of 10 km
|
||||
|
||||
--- A helicopter descriptor.
|
||||
-- @type Unit.DescHelicopter
|
||||
-- @extends Wrapper.Unit#Unit.DescAircraft
|
||||
-- @field #Distance HmaxStat static ceiling
|
||||
|
||||
--- A vehicle descriptor.
|
||||
-- @type Unit.DescVehicle
|
||||
-- @extends Wrapper.Unit#Unit.Desc
|
||||
-- @field #Angle maxSlopeAngle maximal slope angle
|
||||
-- @field #boolean riverCrossing can the vehicle cross a rivers
|
||||
|
||||
--- A ship descriptor.
|
||||
-- @type Unit.DescShip
|
||||
-- @extends #Unit.Desc
|
||||
|
||||
--- ammunition item: "type-count" pair.
|
||||
-- @type Unit.AmmoItem
|
||||
-- @field #Weapon.Desc desc ammunition descriptor
|
||||
-- @field #number count ammunition count
|
||||
|
||||
--- A unit sensor.
|
||||
-- @type Unit.Sensor
|
||||
-- @field #TypeName typeName
|
||||
-- @field #Unit.SensorType type
|
||||
|
||||
--- An optic sensor.
|
||||
-- @type Unit.Optic
|
||||
-- @extends Wrapper.Unit#Unit.Sensor
|
||||
-- @field #Unit.OpticType opticType
|
||||
|
||||
--- A radar.
|
||||
-- @type Unit.Radar
|
||||
-- @extends Wrapper.Unit#Unit.Sensor
|
||||
-- @field #Distance detectionDistanceRBM detection distance for RCS=1m^2 in real-beam mapping mode, nil if radar doesn't support surface/land search
|
||||
-- @field #Distance detectionDistanceHRM detection distance for RCS=1m^2 in high-resolution mapping mode, nil if radar has no HRM
|
||||
-- @field #Unit.Radar.detectionDistanceAir detectionDistanceAir detection distance for RCS=1m^2 airborne target, nil if radar doesn't support air search
|
||||
|
||||
--- @type Unit.Radar.detectionDistanceAir
|
||||
-- @field #Unit.Radar.detectionDistanceAir.upperHemisphere upperHemisphere
|
||||
-- @field #Unit.Radar.detectionDistanceAir.lowerHemisphere lowerHemisphere
|
||||
|
||||
--- @type Unit.Radar.detectionDistanceAir.upperHemisphere
|
||||
-- @field #Distance headOn
|
||||
-- @field #Distance tailOn
|
||||
|
||||
--- @type Unit.Radar.detectionDistanceAir.lowerHemisphere
|
||||
-- @field #Distance headOn
|
||||
-- @field #Distance tailOn
|
||||
|
||||
--- An IRST.
|
||||
-- @type Wrapper.Unit#Unit.IRST
|
||||
-- @extends Unit.Sensor
|
||||
-- @field #Distance detectionDistanceIdle detection of tail-on target with heat signature = 1 in upper hemisphere, engines are in idle
|
||||
-- @field #Distance detectionDistanceMaximal ..., engines are in maximal mode
|
||||
-- @field #Distance detectionDistanceAfterburner ..., engines are in afterburner mode
|
||||
|
||||
--- An RWR.
|
||||
-- @type Unit.RWR
|
||||
-- @extends Wrapper.Unit#Unit.Sensor
|
||||
|
||||
--- table that stores all unit sensors.
|
||||
-- TODO @type Sensors
|
||||
--
|
||||
|
||||
|
||||
--- Returns unit object by the name assigned to the unit in Mission Editor. If there is unit with such name or the unit is destroyed the function will return nil. The function provides access to non-activated units too.
|
||||
-- @function [parent=#Unit] getByName
|
||||
-- @param #string name
|
||||
-- @return #Unit
|
||||
|
||||
--- Returns if the unit is activated.
|
||||
-- @function [parent=#Unit] isActive
|
||||
-- @param #Unit self
|
||||
-- @return #boolean
|
||||
|
||||
--- Returns name of the player that control the unit or nil if the unit is controlled by A.I.
|
||||
-- @function [parent=#Unit] getPlayerName
|
||||
-- @param #Unit self
|
||||
-- @return #string
|
||||
|
||||
--- returns the unit's unique identifier.
|
||||
-- @function [parent=#Unit] getID
|
||||
-- @param #Unit self
|
||||
-- @return #Unit.ID
|
||||
|
||||
|
||||
--- Returns the unit's number in the group. The number is the same number the unit has in ME. It may not be changed during the mission. If any unit in the group is destroyed, the numbers of another units will not be changed.
|
||||
-- @function [parent=#Unit] getNumber
|
||||
-- @param #Unit self
|
||||
-- @return #number
|
||||
|
||||
--- Returns controller of the unit if it exist and nil otherwise
|
||||
-- @function [parent=#Unit] getController
|
||||
-- @param #Unit self
|
||||
-- @return #Controller
|
||||
|
||||
--- Returns the unit's group if it exist and nil otherwise
|
||||
-- @function [parent=#Unit] getGroup
|
||||
-- @param #Unit self
|
||||
-- @return Dcs.DCSWrapper.Group#Group
|
||||
|
||||
--- Returns the unit's callsign - the localized string.
|
||||
-- @function [parent=#Unit] getCallsign
|
||||
-- @param #Unit self
|
||||
-- @return #string
|
||||
|
||||
--- Returns the unit's health. Dead units has health <= 1.0
|
||||
-- @function [parent=#Unit] getLife
|
||||
-- @param #Unit self
|
||||
-- @return #number
|
||||
|
||||
--- returns the unit's initial health.
|
||||
-- @function [parent=#Unit] getLife0
|
||||
-- @param #Unit self
|
||||
-- @return #number
|
||||
|
||||
--- Returns relative amount of fuel (from 0.0 to 1.0) the unit has in its internal tanks. If there are additional fuel tanks the value may be greater than 1.0.
|
||||
-- @function [parent=#Unit] getFuel
|
||||
-- @param #Unit self
|
||||
-- @return #number
|
||||
|
||||
--- Returns the unit ammunition.
|
||||
-- @function [parent=#Unit] getAmmo
|
||||
-- @param #Unit self
|
||||
-- @return #Unit.Ammo
|
||||
|
||||
--- Returns the unit sensors.
|
||||
-- @function [parent=#Unit] getSensors
|
||||
-- @param #Unit self
|
||||
-- @return #Unit.Sensors
|
||||
|
||||
--- Returns true if the unit has specified types of sensors. This function is more preferable than Unit.getSensors() if you don't want to get information about all the unit's sensors, and just want to check if the unit has specified types of sensors.
|
||||
-- @function [parent=#Unit] hasSensors
|
||||
-- @param #Unit self
|
||||
-- @param #Unit.SensorType sensorType (= nil) Sensor type.
|
||||
-- @param ... Additional parameters.
|
||||
-- @return #boolean
|
||||
-- @usage
|
||||
-- If sensorType is Unit.SensorType.OPTIC, additional parameters are optic sensor types. Following example checks if the unit has LLTV or IR optics:
|
||||
-- unit:hasSensors(Unit.SensorType.OPTIC, Unit.OpticType.LLTV, Unit.OpticType.IR)
|
||||
-- If sensorType is Unit.SensorType.RADAR, additional parameters are radar types. Following example checks if the unit has air search radars:
|
||||
-- unit:hasSensors(Unit.SensorType.RADAR, Unit.RadarType.AS)
|
||||
-- If no additional parameters are specified the function returns true if the unit has at least one sensor of specified type.
|
||||
-- If sensor type is not specified the function returns true if the unit has at least one sensor of any type.
|
||||
--
|
||||
|
||||
--- returns two values:
|
||||
-- First value indicates if at least one of the unit's radar(s) is on.
|
||||
-- Second value is the object of the radar's interest. Not nil only if at least one radar of the unit is tracking a target.
|
||||
-- @function [parent=#Unit] getRadar
|
||||
-- @param #Unit self
|
||||
-- @return #boolean, Wrapper.Object#Object
|
||||
|
||||
--- Returns unit descriptor. Descriptor type depends on unit category.
|
||||
-- @function [parent=#Unit] getDesc
|
||||
-- @param #Unit self
|
||||
-- @return #Unit.Desc
|
||||
|
||||
|
||||
Unit = {} --#Unit
|
||||
@@ -1,11 +0,0 @@
|
||||
-------------------------------------------------------------------------------
|
||||
-- @module DCSVec3
|
||||
|
||||
|
||||
|
||||
---
|
||||
-- @type Vec3
|
||||
-- @field #number x
|
||||
-- @field #number y
|
||||
-- @field #number z
|
||||
Vec3 = {}
|
||||
@@ -1,10 +0,0 @@
|
||||
-------------------------------------------------------------------------------
|
||||
-- @module DCSZone
|
||||
|
||||
|
||||
|
||||
---
|
||||
-- @type Zone
|
||||
-- @field DCSVec3#Vec3 point
|
||||
-- @field #number radius
|
||||
Zone = {}
|
||||
@@ -1,16 +0,0 @@
|
||||
-------------------------------------------------------------------------------
|
||||
-- @module DCScoalition
|
||||
|
||||
--- @type coalition
|
||||
-- @field #coalition.side side
|
||||
|
||||
--- @type coalition.side
|
||||
-- @field NEUTRAL
|
||||
-- @field RED
|
||||
-- @field BLUE
|
||||
|
||||
--- @function [parent=#coalition] getCountryCoalition
|
||||
-- @param #number countryId
|
||||
-- @return #number coalitionId
|
||||
|
||||
coalition = coalition -- #coalition
|
||||
@@ -1,27 +0,0 @@
|
||||
-------------------------------------------------------------------------------
|
||||
-- @module DCScountry
|
||||
|
||||
--- @type country
|
||||
-- @field #country.id id
|
||||
country = country -- #country
|
||||
|
||||
--- @type country.id
|
||||
-- @field RUSSIA
|
||||
-- @field UKRAINE
|
||||
-- @field USA
|
||||
-- @field TURKEY
|
||||
-- @field UK
|
||||
-- @field FRANCE
|
||||
-- @field GERMANY
|
||||
-- @field CANADA
|
||||
-- @field SPAIN
|
||||
-- @field THE_NETHERLANDS
|
||||
-- @field BELGIUM
|
||||
-- @field NORWAY
|
||||
-- @field DENMARK
|
||||
-- @field ISRAEL
|
||||
-- @field GEORGIA
|
||||
-- @field INSURGENTS
|
||||
-- @field ABKHAZIA
|
||||
-- @field SOUTH_OSETIA
|
||||
-- @field ITALY
|
||||
@@ -1,27 +0,0 @@
|
||||
-------------------------------------------------------------------------------
|
||||
-- @module env
|
||||
|
||||
--- @type env
|
||||
|
||||
--- Add message to simulator log with caption "INFO". Message box is optional.
|
||||
-- @function [parent=#env] info
|
||||
-- @field #string message message string to add to log.
|
||||
-- @field #boolean showMessageBox If the parameter is true Message Box will appear. Optional.
|
||||
|
||||
--- Add message to simulator log with caption "WARNING". Message box is optional.
|
||||
-- @function [parent=#env] warning
|
||||
-- @field #string message message string to add to log.
|
||||
-- @field #boolean showMessageBox If the parameter is true Message Box will appear. Optional.
|
||||
|
||||
--- Add message to simulator log with caption "ERROR". Message box is optional.
|
||||
-- @function [parent=#env] error
|
||||
-- @field #string message message string to add to log.
|
||||
-- @field #boolean showMessageBox If the parameter is true Message Box will appear. Optional.
|
||||
|
||||
--- Enables/disables appearance of message box each time lua error occurs.
|
||||
-- @function [parent=#env] setErrorMessageBoxEnabled
|
||||
-- @field #boolean on if true message box appearance is enabled.
|
||||
|
||||
|
||||
|
||||
env = {} --#env
|
||||
@@ -1,26 +0,0 @@
|
||||
-------------------------------------------------------------------------------
|
||||
-- @module land
|
||||
|
||||
--- @type land
|
||||
-- @field #land.SurfaceType SurfaceType
|
||||
|
||||
|
||||
--- @type land.SurfaceType
|
||||
-- @field LAND
|
||||
-- @field SHALLOW_WATER
|
||||
-- @field WATER
|
||||
-- @field ROAD
|
||||
-- @field RUNWAY
|
||||
|
||||
--- Returns altitude MSL of the point.
|
||||
-- @function [parent=#land] getHeight
|
||||
-- @param #Vec2 point point on the ground.
|
||||
-- @return Dcs.DCSTypes#Distance
|
||||
|
||||
--- returns surface type at the given point.
|
||||
-- @function [parent=#land] getSurfaceType
|
||||
-- @param #Vec2 point Point on the land.
|
||||
-- @return #land.SurfaceType
|
||||
|
||||
|
||||
land = {} --#land
|
||||
@@ -1,45 +0,0 @@
|
||||
-------------------------------------------------------------------------------
|
||||
-- @module DCStimer
|
||||
|
||||
--- @type timer
|
||||
|
||||
|
||||
--- Returns model time in seconds.
|
||||
-- @function [parent=#timer] getTime
|
||||
-- @return #Time
|
||||
|
||||
--- Returns mission time in seconds.
|
||||
-- @function [parent=#timer] getAbsTime
|
||||
-- @return #Time
|
||||
|
||||
--- Returns mission start time in seconds.
|
||||
-- @function [parent=#timer] getTime0
|
||||
-- @return #Time
|
||||
|
||||
--- Schedules function to call at desired model time.
|
||||
-- Time function FunctionToCall(any argument, Time time)
|
||||
--
|
||||
-- ...
|
||||
--
|
||||
-- return ...
|
||||
--
|
||||
-- end
|
||||
--
|
||||
-- Must return model time of next call or nil. Note that the DCS scheduler calls the function in protected mode and any Lua errors in the called function will be trapped and not reported. If the function triggers a Lua error then it will be terminated and not scheduled to run again.
|
||||
-- @function [parent=#timer] scheduleFunction
|
||||
-- @param #FunctionToCall functionToCall Lua-function to call. Must have prototype of FunctionToCall.
|
||||
-- @param functionArgument Function argument of any type to pass to functionToCall.
|
||||
-- @param #Time time Model time of the function call.
|
||||
-- @return functionId
|
||||
|
||||
--- Re-schedules function to call at another model time.
|
||||
-- @function [parent=#timer] setFunctionTime
|
||||
-- @param functionId Lua-function to call. Must have prototype of FunctionToCall.
|
||||
-- @param #Time time Model time of the function call.
|
||||
|
||||
|
||||
--- Removes the function from schedule.
|
||||
-- @function [parent=#timer] removeFunction
|
||||
-- @param functionId Function identifier to remove from schedule
|
||||
|
||||
timer = {} --#timer
|
||||
@@ -1,8 +0,0 @@
|
||||
-------------------------------------------------------------------------------
|
||||
-- @module DCStrigger
|
||||
|
||||
|
||||
trigger = {} --#timer
|
||||
|
||||
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
-------------------------------------------------------------------------------
|
||||
-- @module DCSWorld
|
||||
|
||||
--- @type world
|
||||
-- @field #world.event event
|
||||
|
||||
|
||||
--- @type world.event
|
||||
-- @field S_EVENT_INVALID
|
||||
-- @field S_EVENT_SHOT
|
||||
-- @field S_EVENT_HIT
|
||||
-- @field S_EVENT_TAKEOFF
|
||||
-- @field S_EVENT_LAND
|
||||
-- @field S_EVENT_CRASH
|
||||
-- @field S_EVENT_EJECTION
|
||||
-- @field S_EVENT_REFUELING
|
||||
-- @field S_EVENT_DEAD
|
||||
-- @field S_EVENT_PILOT_DEAD
|
||||
-- @field S_EVENT_BASE_CAPTURED
|
||||
-- @field S_EVENT_MISSION_START
|
||||
-- @field S_EVENT_MISSION_END
|
||||
-- @field S_EVENT_TOOK_CONTROL
|
||||
-- @field S_EVENT_REFUELING_STOP
|
||||
-- @field S_EVENT_BIRTH
|
||||
-- @field S_EVENT_HUMAN_FAILURE
|
||||
-- @field S_EVENT_ENGINE_STARTUP
|
||||
-- @field S_EVENT_ENGINE_SHUTDOWN
|
||||
-- @field S_EVENT_PLAYER_ENTER_UNIT
|
||||
-- @field S_EVENT_PLAYER_LEAVE_UNIT
|
||||
-- @field S_EVENT_PLAYER_COMMENT
|
||||
-- @field S_EVENT_SHOOTING_START
|
||||
-- @field S_EVENT_SHOOTING_END
|
||||
-- @field S_EVENT_MAX
|
||||
|
||||
world = {} --#world
|
||||
@@ -1,18 +1,28 @@
|
||||
--- **Functional** -- The ATC\_GROUND classes monitor airbase traffic and regulate speed while taxiing.
|
||||
--- **Functional** -- Monitor airbase traffic and regulate speed while taxiing.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ## Features:
|
||||
--
|
||||
-- 
|
||||
-- * Monitor speed of the airplanes of players during taxi.
|
||||
-- * Communicate ATC ground operations.
|
||||
-- * Kick speeding players during taxi.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ## Missions:
|
||||
--
|
||||
-- [ABP - Airbase Police](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/ABP%20-%20Airbase%20Police)
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Contributions: Dutch Baron - Concept & Testing
|
||||
-- ### Author: FlightControl - Framework Design & Programming
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module ATC_Ground
|
||||
|
||||
-- @module Functional.ATC_Ground
|
||||
-- @image Air_Traffic_Control_Ground_Operations.JPG
|
||||
|
||||
--- @type ATC_GROUND
|
||||
-- @field Core.Set#SET_CLIENT SetClient
|
||||
@@ -417,7 +427,7 @@ end
|
||||
-- # Airbases monitored
|
||||
--
|
||||
-- The following airbases are monitored at the Caucasus region.
|
||||
-- Use the @{Airbase#AIRBASE.Caucasus} enumeration to select the airbases to be monitored.
|
||||
-- Use the @{Wrapper.Airbase#AIRBASE.Caucasus} enumeration to select the airbases to be monitored.
|
||||
--
|
||||
-- * `AIRBASE.Caucasus.Anapa_Vityazevo`
|
||||
-- * `AIRBASE.Caucasus.Batumi`
|
||||
@@ -1021,7 +1031,7 @@ end
|
||||
-- # Airbases monitored
|
||||
--
|
||||
-- The following airbases are monitored at the Nevada region.
|
||||
-- Use the @{Airbase#AIRBASE.Nevada} enumeration to select the airbases to be monitored.
|
||||
-- Use the @{Wrapper.Airbase#AIRBASE.Nevada} enumeration to select the airbases to be monitored.
|
||||
--
|
||||
-- * `AIRBASE.Nevada.Beatty_Airport`
|
||||
-- * `AIRBASE.Nevada.Boulder_City_Airport`
|
||||
@@ -1561,7 +1571,7 @@ end
|
||||
-- # Airbases monitored
|
||||
--
|
||||
-- The following airbases are monitored at the Normandy region.
|
||||
-- Use the @{Airbase#AIRBASE.Normandy} enumeration to select the airbases to be monitored.
|
||||
-- Use the @{Wrapper.Airbase#AIRBASE.Normandy} enumeration to select the airbases to be monitored.
|
||||
--
|
||||
-- * `AIRBASE.Normandy.Azeville`
|
||||
-- * `AIRBASE.Normandy.Bazenville`
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,26 +1,23 @@
|
||||
--- **Functional** -- The CLEANUP_AIRBASE class keeps an area clean of crashing or colliding airplanes. It also prevents airplanes from firing within this area.
|
||||
--- **Functional** -- Keep airbases clean of crashing or colliding airplanes, and kill missiles when being fired at airbases.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **FlightControl**
|
||||
-- ### Contributions:
|
||||
-- ## Features:
|
||||
--
|
||||
--
|
||||
-- * Try to keep the airbase clean and operational.
|
||||
-- * Prevent airplanes from crashing.
|
||||
-- * Clean up obstructing airplanes from the runway that are standing still for a period of time.
|
||||
-- * Prevent airplanes firing missiles within the airbase zone.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module CleanUp
|
||||
|
||||
--- @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.
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
--- @type CLEANUP_AIRBASE
|
||||
-- @extends #CLEANUP_AIRBASE.__
|
||||
|
||||
--- # CLEANUP_AIRBASE, extends @{Base#BASE}
|
||||
-- ## Missions:
|
||||
--
|
||||
-- 
|
||||
-- [CLA - CleanUp Airbase](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/CLA%20-%20CleanUp%20Airbase)
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- The CLEANUP_AIRBASE class keeps airbases clean, and tries to guarantee continuous airbase operations, even under combat.
|
||||
-- Specific airbases need to be provided that need to be guarded. Each airbase registered, will be guarded within a zone of 8 km around the airbase.
|
||||
-- Any unit that fires a missile, or shoots within the zone of an airbase, will be monitored by CLEANUP_AIRBASE.
|
||||
-- Within the 8km zone, units cannot fire any missile, which prevents the airbase runway to receive missile or bomb hits.
|
||||
@@ -45,7 +42,26 @@
|
||||
--
|
||||
-- By following the above guidelines, you can add airbase cleanup with acceptable CPU overhead.
|
||||
--
|
||||
-- ## 1. CLEANUP_AIRBASE Constructor
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **FlightControl**
|
||||
-- ### Contributions:
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module Functional.CleanUp
|
||||
-- @image CleanUp_Airbases.JPG
|
||||
|
||||
--- @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.
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
--- @type CLEANUP_AIRBASE
|
||||
-- @extends #CLEANUP_AIRBASE.__
|
||||
|
||||
--- Keeps airbases clean, and tries to guarantee continuous airbase operations, even under combat.
|
||||
--
|
||||
-- # 1. CLEANUP_AIRBASE Constructor
|
||||
--
|
||||
-- Creates the main object which is preventing the airbase to get polluted with debris on the runway, which halts the airbase.
|
||||
--
|
||||
@@ -56,12 +72,12 @@
|
||||
-- CleanUpTbilisi = CLEANUP_AIRBASE:New( AIRBASE.Caucasus.Tbilisi )
|
||||
-- CleanUpKutaisi = CLEANUP_AIRBASE:New( AIRBASE.Caucasus.Kutaisi )
|
||||
--
|
||||
-- ## 2. Add or Remove airbases
|
||||
-- # 2. Add or Remove airbases
|
||||
--
|
||||
-- The method @{#CLEANUP_AIRBASE.AddAirbase}() to add an airbase to the cleanup validation process.
|
||||
-- The method @{#CLEANUP_AIRBASE.RemoveAirbase}() removes an airbase from the cleanup validation process.
|
||||
--
|
||||
-- ## 3. Clean missiles and bombs within the airbase zone.
|
||||
-- # 3. Clean missiles and bombs within the airbase zone.
|
||||
--
|
||||
-- When missiles or bombs hit the runway, the airbase operations stop.
|
||||
-- Use the method @{#CLEANUP_AIRBASE.SetCleanMissiles}() to control the cleaning of missiles, which will prevent airbases to stop.
|
||||
@@ -114,6 +130,20 @@ function CLEANUP_AIRBASE:New( AirbaseNames )
|
||||
self:HandleEvent( EVENTS.PilotDead, self.__.OnEventCrash )
|
||||
self:HandleEvent( EVENTS.Dead, self.__.OnEventCrash )
|
||||
self:HandleEvent( EVENTS.Crash, self.__.OnEventCrash )
|
||||
|
||||
for UnitName, Unit in pairs( _DATABASE.UNITS ) do
|
||||
local Unit = Unit -- Wrapper.Unit#UNIT
|
||||
if Unit:IsAlive() ~= nil then
|
||||
if self:IsInAirbase( Unit:GetVec2() ) then
|
||||
self:F( { UnitName = UnitName } )
|
||||
self.CleanUpList[UnitName] = {}
|
||||
self.CleanUpList[UnitName].CleanUpUnit = Unit
|
||||
self.CleanUpList[UnitName].CleanUpGroup = Unit:GetGroup()
|
||||
self.CleanUpList[UnitName].CleanUpGroupName = Unit:GetGroup():GetName()
|
||||
self.CleanUpList[UnitName].CleanUpUnitName = Unit:GetName()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
@@ -173,7 +203,7 @@ end
|
||||
|
||||
|
||||
|
||||
--- Destroys a @{Unit} from the simulator, but checks first if it is still existing!
|
||||
--- Destroys a @{Wrapper.Unit} from the simulator, but checks first if it is still existing!
|
||||
-- @param #CLEANUP_AIRBASE self
|
||||
-- @param Wrapper.Unit#UNIT CleanUpUnit The object to be destroyed.
|
||||
function CLEANUP_AIRBASE.__:DestroyUnit( CleanUpUnit )
|
||||
@@ -182,7 +212,7 @@ function CLEANUP_AIRBASE.__:DestroyUnit( CleanUpUnit )
|
||||
if CleanUpUnit then
|
||||
local CleanUpUnitName = CleanUpUnit:GetName()
|
||||
local CleanUpGroup = CleanUpUnit:GetGroup()
|
||||
-- TODO Client bug in 1.5.3
|
||||
-- TODO DCS BUG - Client bug in 1.5.3
|
||||
if CleanUpGroup:IsAlive() then
|
||||
local CleanUpGroupUnits = CleanUpGroup:GetUnits()
|
||||
if #CleanUpGroupUnits == 1 then
|
||||
@@ -200,7 +230,7 @@ end
|
||||
|
||||
--- Destroys a missile from the simulator, but checks first if it is still existing!
|
||||
-- @param #CLEANUP_AIRBASE self
|
||||
-- @param Dcs.DCSTypes#Weapon MissileObject
|
||||
-- @param DCS#Weapon MissileObject
|
||||
function CLEANUP_AIRBASE.__:DestroyMissile( MissileObject )
|
||||
self:F( { MissileObject } )
|
||||
|
||||
@@ -215,11 +245,15 @@ end
|
||||
function CLEANUP_AIRBASE.__:OnEventBirth( EventData )
|
||||
self:F( { EventData } )
|
||||
|
||||
self.CleanUpList[EventData.IniDCSUnitName] = {}
|
||||
self.CleanUpList[EventData.IniDCSUnitName].CleanUpUnit = EventData.IniUnit
|
||||
self.CleanUpList[EventData.IniDCSUnitName].CleanUpGroup = EventData.IniGroup
|
||||
self.CleanUpList[EventData.IniDCSUnitName].CleanUpGroupName = EventData.IniDCSGroupName
|
||||
self.CleanUpList[EventData.IniDCSUnitName].CleanUpUnitName = EventData.IniDCSUnitName
|
||||
if EventData.IniUnit:IsAlive() ~= nil then
|
||||
if self:IsInAirbase( EventData.IniUnit:GetVec2() ) then
|
||||
self.CleanUpList[EventData.IniDCSUnitName] = {}
|
||||
self.CleanUpList[EventData.IniDCSUnitName].CleanUpUnit = EventData.IniUnit
|
||||
self.CleanUpList[EventData.IniDCSUnitName].CleanUpGroup = EventData.IniGroup
|
||||
self.CleanUpList[EventData.IniDCSUnitName].CleanUpGroupName = EventData.IniDCSGroupName
|
||||
self.CleanUpList[EventData.IniDCSUnitName].CleanUpUnitName = EventData.IniDCSUnitName
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -231,7 +265,7 @@ end
|
||||
function CLEANUP_AIRBASE.__:OnEventCrash( Event )
|
||||
self:F( { Event } )
|
||||
|
||||
--TODO: This stuff is not working due to a DCS bug. Burning units cannot be destroyed.
|
||||
--TODO: DCS BUG - This stuff is not working due to a DCS bug. Burning units cannot be destroyed.
|
||||
-- self:T("before getGroup")
|
||||
-- local _grp = Unit.getGroup(event.initiator)-- Identify the group that fired
|
||||
-- self:T("after getGroup")
|
||||
@@ -290,9 +324,9 @@ function CLEANUP_AIRBASE.__:OnEventHit( Event )
|
||||
end
|
||||
end
|
||||
|
||||
--- Add the @{DCSWrapper.Unit#Unit} to the CleanUpList for CleanUp.
|
||||
--- Add the @{DCS#Unit} to the CleanUpList for CleanUp.
|
||||
-- @param #CLEANUP_AIRBASE self
|
||||
-- @param Wrapper.Unit#UNIT CleanUpUnit
|
||||
-- @param DCS#UNIT CleanUpUnit
|
||||
-- @oaram #string CleanUpUnitName
|
||||
function CLEANUP_AIRBASE.__:AddForCleanUp( CleanUpUnit, CleanUpUnitName )
|
||||
self:F( { CleanUpUnit, CleanUpUnitName } )
|
||||
@@ -351,45 +385,50 @@ function CLEANUP_AIRBASE.__:CleanUpSchedule()
|
||||
local CleanUpGroupName = CleanUpListData.CleanUpGroupName
|
||||
|
||||
if CleanUpUnit:IsAlive() ~= nil then
|
||||
|
||||
if self:IsInAirbase( CleanUpUnit:GetVec2() ) then
|
||||
|
||||
if _DATABASE:GetStatusGroup( CleanUpGroupName ) ~= "ReSpawn" then
|
||||
|
||||
local CleanUpCoordinate = CleanUpUnit:GetCoordinate()
|
||||
|
||||
self:T( { "CleanUp Scheduler", CleanUpUnitName } )
|
||||
if CleanUpUnit:GetLife() <= CleanUpUnit:GetLife0() * 0.95 then
|
||||
if CleanUpUnit:IsAboveRunway() then
|
||||
if CleanUpUnit:InAir() then
|
||||
|
||||
local CleanUpLandHeight = CleanUpCoordinate:GetLandHeight()
|
||||
local CleanUpUnitHeight = CleanUpCoordinate.y - CleanUpLandHeight
|
||||
|
||||
if CleanUpUnitHeight < 100 then
|
||||
self:T( { "CleanUp Scheduler", "Destroy " .. CleanUpUnitName .. " because below safe height and damaged." } )
|
||||
self:DestroyUnit( CleanUpUnit )
|
||||
end
|
||||
else
|
||||
self:T( { "CleanUp Scheduler", "Destroy " .. CleanUpUnitName .. " because on runway and damaged." } )
|
||||
self:DestroyUnit( CleanUpUnit )
|
||||
end
|
||||
end
|
||||
end
|
||||
-- Clean Units which are waiting for a very long time in the CleanUpZone.
|
||||
if CleanUpUnit then
|
||||
local CleanUpUnitVelocity = CleanUpUnit:GetVelocityKMH()
|
||||
if CleanUpUnitVelocity < 1 then
|
||||
if CleanUpListData.CleanUpMoved then
|
||||
if CleanUpListData.CleanUpTime + 180 <= timer.getTime() then
|
||||
self:T( { "CleanUp Scheduler", "Destroy due to not moving anymore " .. CleanUpUnitName } )
|
||||
self:DestroyUnit( CleanUpUnit )
|
||||
end
|
||||
end
|
||||
else
|
||||
CleanUpListData.CleanUpTime = timer.getTime()
|
||||
CleanUpListData.CleanUpMoved = true
|
||||
end
|
||||
end
|
||||
|
||||
if _DATABASE:GetStatusGroup( CleanUpGroupName ) ~= "ReSpawn" then
|
||||
|
||||
local CleanUpCoordinate = CleanUpUnit:GetCoordinate()
|
||||
|
||||
self:T( { "CleanUp Scheduler", CleanUpUnitName } )
|
||||
if CleanUpUnit:GetLife() <= CleanUpUnit:GetLife0() * 0.95 then
|
||||
if CleanUpUnit:IsAboveRunway() then
|
||||
if CleanUpUnit:InAir() then
|
||||
|
||||
local CleanUpLandHeight = CleanUpCoordinate:GetLandHeight()
|
||||
local CleanUpUnitHeight = CleanUpCoordinate.y - CleanUpLandHeight
|
||||
|
||||
if CleanUpUnitHeight < 100 then
|
||||
self:T( { "CleanUp Scheduler", "Destroy " .. CleanUpUnitName .. " because below safe height and damaged." } )
|
||||
self:DestroyUnit( CleanUpUnit )
|
||||
end
|
||||
else
|
||||
self:T( { "CleanUp Scheduler", "Destroy " .. CleanUpUnitName .. " because on runway and damaged." } )
|
||||
self:DestroyUnit( CleanUpUnit )
|
||||
end
|
||||
end
|
||||
end
|
||||
-- Clean Units which are waiting for a very long time in the CleanUpZone.
|
||||
if CleanUpUnit and not CleanUpUnit:GetPlayerName() then
|
||||
local CleanUpUnitVelocity = CleanUpUnit:GetVelocityKMH()
|
||||
if CleanUpUnitVelocity < 1 then
|
||||
if CleanUpListData.CleanUpMoved then
|
||||
if CleanUpListData.CleanUpTime + 180 <= timer.getTime() then
|
||||
self:T( { "CleanUp Scheduler", "Destroy due to not moving anymore " .. CleanUpUnitName } )
|
||||
self:DestroyUnit( CleanUpUnit )
|
||||
end
|
||||
end
|
||||
else
|
||||
CleanUpListData.CleanUpTime = timer.getTime()
|
||||
CleanUpListData.CleanUpMoved = true
|
||||
end
|
||||
end
|
||||
else
|
||||
-- not anymore in an airbase zone, remove from cleanup list.
|
||||
self.CleanUpList[CleanUpUnitName] = nil
|
||||
end
|
||||
else
|
||||
-- Do nothing ...
|
||||
self.CleanUpList[CleanUpUnitName] = nil
|
||||
|
||||
@@ -2,198 +2,205 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- DESIGNATE is orchestrating the designation of potential targets executed by a Recce group,
|
||||
-- and communicates these to a dedicated attacking group of players,
|
||||
-- so that following a dynamically generated menu system,
|
||||
-- each detected set of potential targets can be lased or smoked...
|
||||
-- ## Features:
|
||||
--
|
||||
-- Targets can be:
|
||||
-- * Faciliate the communication of detected targets to players.
|
||||
-- * Designate targets using lasers, through a menu system.
|
||||
-- * Designate targets using smoking, through a menu system.
|
||||
-- * Designate targets using illumination, through a menu system.
|
||||
-- * Auto lase targets.
|
||||
-- * Refresh detection upon specified time intervals.
|
||||
-- * Prioritization on threat levels.
|
||||
-- * Reporting system of threats.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ## Missions:
|
||||
--
|
||||
-- [DES - Designation](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/DES%20-%20Designation)
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- Targets detected by recce will be communicated to a group of attacking players.
|
||||
-- A menu system is made available that allows to:
|
||||
--
|
||||
-- * **Lased** for a period of time.
|
||||
-- * **Smoked**. Artillery or airplanes with Illuminatino ordonance need to be present. (WIP, but early demo ready.)
|
||||
-- * **Illuminated** through an illumination bomb. Artillery or airplanes with Illuminatino ordonance need to be present. (WIP, but early demo ready.
|
||||
--
|
||||
-- ===
|
||||
-- The following terminology is being used throughout this document:
|
||||
--
|
||||
-- # **AUTHORS and CONTRIBUTIONS**
|
||||
-- * The **DesignateObject** is the object of the DESIGNATE class, which is this class explained in the document.
|
||||
-- * The **DetectionObject** is the object of a DETECTION_ class (DETECTION_TYPES, DETECTION_AREAS, DETECTION_UNITS), which is executing the detection and grouping of Targets into _DetectionItems_.
|
||||
-- * **TargetGroups** is the list of detected target groupings by the _DetectionObject_. Each _TargetGroup_ contains a _TargetSet_.
|
||||
-- * **TargetGroup** is one element of the __TargetGroups__ list, and contains a _TargetSet_.
|
||||
-- * The **TargetSet** is a SET_UNITS collection of _Targets_, that have been detected by the _DetectionObject_.
|
||||
-- * A **Target** is a detected UNIT object by the _DetectionObject_.
|
||||
-- * A **Threat Level** is a number from 0 to 10 that is calculated based on the threat of the Target in an Air to Ground battle scenario.
|
||||
-- * The **RecceSet** is a SET_GROUP collection that contains the **RecceGroups**.
|
||||
-- * A **RecceGroup** is a GROUP object containing the **Recces**.
|
||||
-- * A **Recce** is a UNIT object executing the reconnaissance as part the _DetectionObject_. A Recce can be of any UNIT type.
|
||||
-- * An **AttackGroup** is a GROUP object that contain _Players_.
|
||||
-- * A **Player** is an active CLIENT object containing a human player.
|
||||
-- * A **Designate Menu** is the menu that is dynamically created during the designation process for each _AttackGroup_.
|
||||
--
|
||||
-- # Player Manual
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- A typical mission setup would require Recce (a @{Set} of Recce) to be detecting potential targets.
|
||||
-- The DetectionObject will group the detected targets based on the detection method being used.
|
||||
-- Possible detection methods could be by Area, by Type or by Unit.
|
||||
-- Each grouping will result in a **TargetGroup**, for terminology and clarity we will use this term throughout the document.
|
||||
--
|
||||
-- **Recce** require to have Line of Sight (LOS) towards the targets.
|
||||
-- The **Recce** will report any detected targets to the Players (on the picture Observers).
|
||||
-- When targets are detected, a menu will be made available that allows those **TargetGroups** to be designated.
|
||||
-- Designation can be done by Lasing, Smoking and Illumination.
|
||||
-- Smoking is useful during the day, while illumination is recommended to be used during the night.
|
||||
-- Smoking can designate specific targets, but not very precise, while lasing is very accurate and allows to
|
||||
-- players to attack the targets using laser guided bombs or rockets.
|
||||
-- Illumination will lighten up the Target Area.
|
||||
--
|
||||
-- **Recce** can be ground based or airborne. Airborne **Recce** (AFAC) can be really useful to designate a large amount of targets
|
||||
-- in a wide open area, as airborne **Recce** has a large LOS.
|
||||
-- However, ground based **Recce** are very useful to smoke or illuminate targets, as they can be much closer
|
||||
-- to the Target Area.
|
||||
--
|
||||
-- It is recommended to make the **Recce** invisible and immortal using the Mission Editor in DCS World.
|
||||
-- This will ensure that the detection process won't be interrupted and that targets can be designated.
|
||||
-- However, you don't have to, so to simulate a more real-word situation or simulation, **Recce can also be destroyed**!
|
||||
--
|
||||
-- ## 1. Player View (Observer)
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- The RecceSet is continuously detecting for potential Targets,
|
||||
-- executing its task as part of the DetectionObject.
|
||||
-- Once Targets have been detected, the DesignateObject will trigger the **Detect Event**.
|
||||
--
|
||||
-- In order to prevent an overflow in the DesignateObject of detected targets,
|
||||
-- there is a maximum amount of TargetGroups
|
||||
-- that can be put in **scope** of the DesignateObject.
|
||||
-- We call this the **MaximumDesignations** term.
|
||||
--
|
||||
-- ## 2. Designate Menu
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- For each detected TargetGroup, there is:
|
||||
--
|
||||
-- * A **Designate Menu** are created and continuously refreshed, containing the **DesignationID** and the **Designation Status**.
|
||||
-- * The RecceGroups are reporting to each AttackGroup, sending **Messages** containing the Threat Level and the TargetSet composition.
|
||||
--
|
||||
-- A Player can then select an action from the **Designate Menu**.
|
||||
-- The Designation Status is shown between the ( ).
|
||||
--
|
||||
-- It indicates for each TargetGroup the current active designation action applied:
|
||||
--
|
||||
-- * An "I" for Illumnation designation.
|
||||
-- * An "S" for Smoking designation.
|
||||
-- * An "L" for Lasing designation.
|
||||
--
|
||||
-- Note that multiple designation methods can be active at the same time!
|
||||
-- Note the **Auto Lase** option. When switched on, the available **Recce** will lase
|
||||
-- Targets when detected.
|
||||
--
|
||||
-- Targets are designated per **Threat Level**.
|
||||
-- The most threatening targets from an Air to Ground perspective, are designated first!
|
||||
-- This is for all designation methods.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- Each Designate Menu has a sub menu structure, which allows specific actions to be triggered:
|
||||
--
|
||||
-- * Lase Targets using a specific laser code.
|
||||
-- * Smoke Targets using a specific smoke color.
|
||||
-- * Illuminate areas.
|
||||
--
|
||||
-- ## 3. Lasing Targets
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- Lasing targets is done as expected. Each available Recce can lase only ONE target through!
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- Lasing can be done for specific laser codes. The Su-25T requires laser code 1113, while the A-10A requires laser code 1680.
|
||||
-- For those, specific menu options can be made available for players to lase with these codes.
|
||||
-- Auto Lase (as explained above), will ensure continuous lasing of available targets.
|
||||
-- The status report shows which targets are being designated.
|
||||
--
|
||||
-- The following logic is executed when a TargetGroup is selected to be *lased* from the Designation Menu:
|
||||
--
|
||||
-- * The RecceSet is searched for any Recce that is within *designation distance* from a Target in the TargetGroup that is currently not being designated.
|
||||
-- * If there is a Recce found that is currently no designating a target, and is within designation distance from the Target, then that Target will be designated.
|
||||
-- * During designation, any Recce that does not have Line of Sight (LOS) and is not within disignation distance from the Target, will stop designating the Target, and a report is given.
|
||||
-- * When a Recce is designating a Target, and that Target is destroyed, then the Recce will stop designating the Target, and will report the event.
|
||||
-- * When a Recce is designating a Target, and that Recce is destroyed, then the Recce will be removed from the RecceSet and designation will stop without reporting.
|
||||
-- * When all RecceGroups are destroyed from the RecceSet, then the DesignationObject will stop functioning, and nothing will be reported.
|
||||
--
|
||||
-- In this way, DESIGNATE assists players to designate ground targets for a coordinated attack!
|
||||
--
|
||||
-- ## 4. Illuminating Targets
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- Illumination bombs are fired between 500 and 700 meters altitude and will burn about 2 minutes, while slowly decending.
|
||||
-- Each available recce within range will fire an illumination bomb.
|
||||
-- Illumination bombs can be fired in while lasing targets.
|
||||
-- When illumination bombs are fired, it will take about 2 minutes until a sequent bomb run can be requested using the menus.
|
||||
--
|
||||
-- ## 5. Smoking Targets
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- Smoke will fire for 5 minutes.
|
||||
-- Each available recce within range will smoke a target.
|
||||
-- Smoking can be requested while lasing targets.
|
||||
-- Smoke will appear "around" the targets, because of accuracy limitations.
|
||||
--
|
||||
--
|
||||
-- Have FUN!
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Contributions:
|
||||
--
|
||||
-- * [**Ciribob**](https://forums.eagle.ru/member.php?u=112175): Showing the way how to lase targets + how laser codes work!!! Explained the autolase script.
|
||||
-- * [**EasyEB**](https://forums.eagle.ru/member.php?u=112055): Ideas and Beta Testing
|
||||
-- * [**Wingthor**](https://forums.eagle.ru/member.php?u=123698): Beta Testing
|
||||
--
|
||||
--
|
||||
-- ### Authors:
|
||||
--
|
||||
-- * **FlightControl**: Design & Programming
|
||||
--
|
||||
-- @module Designate
|
||||
|
||||
-- ===
|
||||
--
|
||||
-- @module Functional.Designate
|
||||
-- @image Designation.JPG
|
||||
|
||||
do -- DESIGNATE
|
||||
|
||||
--- @type DESIGNATE
|
||||
-- @extends Core.Fsm#FSM_PROCESS
|
||||
|
||||
--- # DESIGNATE class, extends @{Fsm#FSM}
|
||||
--
|
||||
-- DESIGNATE is managing the designation of detected targets.
|
||||
-- Targets detected by recce will be communicated to a group of attacking players.
|
||||
-- A menu system is made available that allows to:
|
||||
--
|
||||
-- * **Lased** for a period of time.
|
||||
-- * **Smoked**. Artillery or airplanes with Illuminatino ordonance need to be present. (WIP, but early demo ready.)
|
||||
-- * **Illuminated** through an illumination bomb. Artillery or airplanes with Illuminatino ordonance need to be present. (WIP, but early demo ready.
|
||||
--
|
||||
-- The following terminology is being used throughout this document:
|
||||
--
|
||||
-- * The **DesignateObject** is the object of the DESIGNATE class, which is this class explained in the document.
|
||||
-- * The **DetectionObject** is the object of a DETECTION_ class (DETECTION_TYPES, DETECTION_AREAS, DETECTION_UNITS), which is executing the detection and grouping of Targets into _DetectionItems_.
|
||||
-- * **TargetGroups** is the list of detected target groupings by the _DetectionObject_. Each _TargetGroup_ contains a _TargetSet_.
|
||||
-- * **TargetGroup** is one element of the __TargetGroups__ list, and contains a _TargetSet_.
|
||||
-- * The **TargetSet** is a SET_UNITS collection of _Targets_, that have been detected by the _DetectionObject_.
|
||||
-- * A **Target** is a detected UNIT object by the _DetectionObject_.
|
||||
-- * A **Threat Level** is a number from 0 to 10 that is calculated based on the threat of the Target in an Air to Ground battle scenario.
|
||||
-- * The **RecceSet** is a SET_GROUP collection that contains the **RecceGroups**.
|
||||
-- * A **RecceGroup** is a GROUP object containing the **Recces**.
|
||||
-- * A **Recce** is a UNIT object executing the reconnaissance as part the _DetectionObject_. A Recce can be of any UNIT type.
|
||||
-- * An **AttackGroup** is a GROUP object that contain _Players_.
|
||||
-- * A **Player** is an active CLIENT object containing a human player.
|
||||
-- * A **Designate Menu** is the menu that is dynamically created during the designation process for each _AttackGroup_.
|
||||
--
|
||||
-- ## 0. Player Manual
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- A typical mission setup would require Recce (a @{Set} of Recce) to be detecting potential targets.
|
||||
-- The DetectionObject will group the detected targets based on the detection method being used.
|
||||
-- Possible detection methods could be by Area, by Type or by Unit.
|
||||
-- Each grouping will result in a **TargetGroup**, for terminology and clarity we will use this term throughout the document.
|
||||
--
|
||||
-- **Recce** require to have Line of Sight (LOS) towards the targets.
|
||||
-- The **Recce** will report any detected targets to the Players (on the picture Observers).
|
||||
-- When targets are detected, a menu will be made available that allows those **TargetGroups** to be designated.
|
||||
-- Designation can be done by Lasing, Smoking and Illumination.
|
||||
-- Smoking is useful during the day, while illumination is recommended to be used during the night.
|
||||
-- Smoking can designate specific targets, but not very precise, while lasing is very accurate and allows to
|
||||
-- players to attack the targets using laser guided bombs or rockets.
|
||||
-- Illumination will lighten up the Target Area.
|
||||
--
|
||||
-- **Recce** can be ground based or airborne. Airborne **Recce** (AFAC) can be really useful to designate a large amount of targets
|
||||
-- in a wide open area, as airborne **Recce** has a large LOS.
|
||||
-- However, ground based **Recce** are very useful to smoke or illuminate targets, as they can be much closer
|
||||
-- to the Target Area.
|
||||
--
|
||||
-- It is recommended to make the **Recce** invisible and immortal using the Mission Editor in DCS World.
|
||||
-- This will ensure that the detection process won't be interrupted and that targets can be designated.
|
||||
-- However, you don't have to, so to simulate a more real-word situation or simulation, **Recce can also be destroyed**!
|
||||
--
|
||||
-- ### 0.1. Player View (Observer)
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- The RecceSet is continuously detecting for potential Targets,
|
||||
-- executing its task as part of the DetectionObject.
|
||||
-- Once Targets have been detected, the DesignateObject will trigger the **Detect Event**.
|
||||
--
|
||||
-- In order to prevent an overflow in the DesignateObject of detected targets,
|
||||
-- there is a maximum amount of TargetGroups
|
||||
-- that can be put in **scope** of the DesignateObject.
|
||||
-- We call this the **MaximumDesignations** term.
|
||||
--
|
||||
-- ### 0.2. Designate Menu
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- For each detected TargetGroup, there is:
|
||||
--
|
||||
-- * A **Designate Menu** are created and continuously refreshed, containing the **DesignationID** and the **Designation Status**.
|
||||
-- * The RecceGroups are reporting to each AttackGroup, sending **Messages** containing the Threat Level and the TargetSet composition.
|
||||
--
|
||||
-- A Player can then select an action from the **Designate Menu**.
|
||||
-- The Designation Status is shown between the ( ).
|
||||
--
|
||||
-- It indicates for each TargetGroup the current active designation action applied:
|
||||
--
|
||||
-- * An "I" for Illumnation designation.
|
||||
-- * An "S" for Smoking designation.
|
||||
-- * An "L" for Lasing designation.
|
||||
--
|
||||
-- Note that multiple designation methods can be active at the same time!
|
||||
-- Note the **Auto Lase** option. When switched on, the available **Recce** will lase
|
||||
-- Targets when detected.
|
||||
--
|
||||
-- Targets are designated per **Threat Level**.
|
||||
-- The most threatening targets from an Air to Ground perspective, are designated first!
|
||||
-- This is for all designation methods.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- Each Designate Menu has a sub menu structure, which allows specific actions to be triggered:
|
||||
--
|
||||
-- * Lase Targets using a specific laser code.
|
||||
-- * Smoke Targets using a specific smoke color.
|
||||
-- * Illuminate areas.
|
||||
--
|
||||
-- ### 0.3. Lasing Targets
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- Lasing targets is done as expected. Each available Recce can lase only ONE target through!
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- Lasing can be done for specific laser codes. The Su-25T requires laser code 1113, while the A-10A requires laser code 1680.
|
||||
-- For those, specific menu options can be made available for players to lase with these codes.
|
||||
-- Auto Lase (as explained above), will ensure continuous lasing of available targets.
|
||||
-- The status report shows which targets are being designated.
|
||||
--
|
||||
-- The following logic is executed when a TargetGroup is selected to be *lased* from the Designation Menu:
|
||||
--
|
||||
-- * The RecceSet is searched for any Recce that is within *designation distance* from a Target in the TargetGroup that is currently not being designated.
|
||||
-- * If there is a Recce found that is currently no designating a target, and is within designation distance from the Target, then that Target will be designated.
|
||||
-- * During designation, any Recce that does not have Line of Sight (LOS) and is not within disignation distance from the Target, will stop designating the Target, and a report is given.
|
||||
-- * When a Recce is designating a Target, and that Target is destroyed, then the Recce will stop designating the Target, and will report the event.
|
||||
-- * When a Recce is designating a Target, and that Recce is destroyed, then the Recce will be removed from the RecceSet and designation will stop without reporting.
|
||||
-- * When all RecceGroups are destroyed from the RecceSet, then the DesignationObject will stop functioning, and nothing will be reported.
|
||||
--
|
||||
-- In this way, DESIGNATE assists players to designate ground targets for a coordinated attack!
|
||||
--
|
||||
-- ### 0.4. Illuminating Targets
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- Illumination bombs are fired between 500 and 700 meters altitude and will burn about 2 minutes, while slowly decending.
|
||||
-- Each available recce within range will fire an illumination bomb.
|
||||
-- Illumination bombs can be fired in while lasing targets.
|
||||
-- When illumination bombs are fired, it will take about 2 minutes until a sequent bomb run can be requested using the menus.
|
||||
--
|
||||
-- ### 0.5. Smoking Targets
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- Smoke will fire for 5 minutes.
|
||||
-- Each available recce within range will smoke a target.
|
||||
-- Smoking can be requested while lasing targets.
|
||||
-- Smoke will appear “around” the targets, because of accuracy limitations.
|
||||
--- Manage the designation of detected targets.
|
||||
--
|
||||
--
|
||||
-- Have FUN!
|
||||
--
|
||||
-- ## 1. DESIGNATE constructor
|
||||
-- # 1. DESIGNATE constructor
|
||||
--
|
||||
-- * @{#DESIGNATE.New}(): Creates a new DESIGNATE object.
|
||||
--
|
||||
-- ## 2. DESIGNATE is a FSM
|
||||
-- # 2. DESIGNATE is a FSM
|
||||
--
|
||||
-- Designate is a finite state machine, which allows for controlled transitions of states.
|
||||
--
|
||||
-- ### 2.1 DESIGNATE States
|
||||
-- ## 2.1 DESIGNATE States
|
||||
--
|
||||
-- * **Designating** ( Group ): The designation process.
|
||||
--
|
||||
-- ### 2.2 DESIGNATE Events
|
||||
-- ## 2.2 DESIGNATE Events
|
||||
--
|
||||
-- * **@{#DESIGNATE.Detect}**: Detect targets.
|
||||
-- * **@{#DESIGNATE.LaseOn}**: Lase the targets with the specified Index.
|
||||
@@ -201,7 +208,7 @@ do -- DESIGNATE
|
||||
-- * **@{#DESIGNATE.Smoke}**: Smoke the targets with the specified Index.
|
||||
-- * **@{#DESIGNATE.Status}**: Report designation status.
|
||||
--
|
||||
-- ## 3. Maximum Designations
|
||||
-- # 3. Maximum Designations
|
||||
--
|
||||
-- In order to prevent an overflow of designations due to many Detected Targets, there is a
|
||||
-- Maximum Designations scope that is set in the DesignationObject.
|
||||
@@ -209,9 +216,9 @@ do -- DESIGNATE
|
||||
-- The method @{#DESIGNATE.SetMaximumDesignations}() will put a limit on the amount of designations put in scope of the DesignationObject.
|
||||
-- Using the menu system, the player can "forget" a designation, so that gradually a new designation can be put in scope when detected.
|
||||
--
|
||||
-- ## 4. Laser codes
|
||||
-- # 4. Laser codes
|
||||
--
|
||||
-- ### 4.1. Set possible laser codes
|
||||
-- ## 4.1. Set possible laser codes
|
||||
--
|
||||
-- An array of laser codes can be provided, that will be used by the DESIGNATE when lasing.
|
||||
-- The laser code is communicated by the Recce when it is lasing a larget.
|
||||
@@ -229,11 +236,11 @@ do -- DESIGNATE
|
||||
--
|
||||
-- The above sets a collection of possible laser codes that can be assigned. **Note the { } notation!**
|
||||
--
|
||||
-- ### 4.2. Auto generate laser codes
|
||||
-- ## 4.2. Auto generate laser codes
|
||||
--
|
||||
-- Use the method @{#DESIGNATE.GenerateLaserCodes}() to generate all possible laser codes. Logic implemented and advised by Ciribob!
|
||||
--
|
||||
-- ### 4.3. Add specific lase codes to the lase menu
|
||||
-- ## 4.3. Add specific lase codes to the lase menu
|
||||
--
|
||||
-- Certain plane types can only drop laser guided ordonnance when targets are lased with specific laser codes.
|
||||
-- The SU-25T needs targets to be lased using laser code 1113.
|
||||
@@ -242,7 +249,7 @@ do -- DESIGNATE
|
||||
-- The method @{#DESIGNATE.AddMenuLaserCode}() to allow a player to lase a target using a specific laser code.
|
||||
-- Remove such a lase menu option using @{#DESIGNATE.RemoveMenuLaserCode}().
|
||||
--
|
||||
-- ## 5. Autolase to automatically lase detected targets.
|
||||
-- # 5. Autolase to automatically lase detected targets.
|
||||
--
|
||||
-- DetectionItems can be auto lased once detected by Recces. As such, there is almost no action required from the Players using the Designate Menu.
|
||||
-- The **auto lase** function can be activated through the Designation Menu.
|
||||
@@ -253,7 +260,7 @@ do -- DESIGNATE
|
||||
--
|
||||
-- Activate the auto lasing.
|
||||
--
|
||||
-- ## 6. Target prioritization on threat level
|
||||
-- # 6. Target prioritization on threat level
|
||||
--
|
||||
-- Targets can be detected of different types in one DetectionItem. Depending on the type of the Target, a different threat level applies in an Air to Ground combat context.
|
||||
-- SAMs are of a higher threat than normal tanks. So, if the Target type was recognized, the Recces will select those targets that form the biggest threat first,
|
||||
@@ -266,12 +273,12 @@ do -- DESIGNATE
|
||||
--
|
||||
-- The example will activate the threat level prioritization for this the Designate object. Threats will be marked based on the threat level of the Target.
|
||||
--
|
||||
-- ## 6. Designate Menu Location for a Mission
|
||||
-- # 7. Designate Menu Location for a Mission
|
||||
--
|
||||
-- You can make DESIGNATE work for a @{Mission#MISSION} object. In this way, the designate menu will not appear in the root of the radio menu, but in the menu of the Mission.
|
||||
-- You can make DESIGNATE work for a @{Tasking.Mission#MISSION} object. In this way, the designate menu will not appear in the root of the radio menu, but in the menu of the Mission.
|
||||
-- Use the method @{#DESIGNATE.SetMission}() to set the @{Mission} object for the designate function.
|
||||
--
|
||||
-- ## 7. Status Report
|
||||
-- # 8. Status Report
|
||||
--
|
||||
-- A status report is available that displays the current Targets detected, grouped per DetectionItem, and a list of which Targets are currently being marked.
|
||||
--
|
||||
@@ -937,89 +944,112 @@ do -- DESIGNATE
|
||||
return self
|
||||
end
|
||||
|
||||
--- Sets the Designate Menu.
|
||||
|
||||
--- Sets the Designate Menu for one attack groups.
|
||||
-- @param #DESIGNATE self
|
||||
-- @return #DESIGNATE
|
||||
function DESIGNATE:SetMenu( AttackGroup )
|
||||
|
||||
self.MenuDesignate = self.MenuDesignate or {}
|
||||
|
||||
local MissionMenu = nil
|
||||
|
||||
if self.Mission then
|
||||
--MissionMenu = self.Mission:GetRootMenu( AttackGroup )
|
||||
MissionMenu = self.Mission:GetMenu( AttackGroup )
|
||||
end
|
||||
|
||||
local MenuTime = timer.getTime()
|
||||
|
||||
self.MenuDesignate[AttackGroup] = MENU_GROUP_DELAYED:New( AttackGroup, self.DesignateName, MissionMenu ):SetTime( MenuTime ):SetTag( self.DesignateName )
|
||||
local MenuDesignate = self.MenuDesignate[AttackGroup] -- Core.Menu#MENU_GROUP_DELAYED
|
||||
|
||||
-- Set Menu option for auto lase
|
||||
|
||||
if self.AutoLase then
|
||||
MENU_GROUP_COMMAND_DELAYED:New( AttackGroup, "Auto Lase Off", MenuDesignate, self.MenuAutoLase, self, false ):SetTime( MenuTime ):SetTag( self.DesignateName )
|
||||
else
|
||||
MENU_GROUP_COMMAND_DELAYED:New( AttackGroup, "Auto Lase On", MenuDesignate, self.MenuAutoLase, self, true ):SetTime( MenuTime ):SetTag( self.DesignateName )
|
||||
end
|
||||
|
||||
local StatusMenu = MENU_GROUP_DELAYED:New( AttackGroup, "Status", MenuDesignate ):SetTime( MenuTime ):SetTag( self.DesignateName )
|
||||
MENU_GROUP_COMMAND_DELAYED:New( AttackGroup, "Report Status", StatusMenu, self.MenuStatus, self, AttackGroup ):SetTime( MenuTime ):SetTag( self.DesignateName )
|
||||
|
||||
if self.FlashStatusMenu[AttackGroup] then
|
||||
MENU_GROUP_COMMAND_DELAYED:New( AttackGroup, "Flash Status Report Off", StatusMenu, self.MenuFlashStatus, self, AttackGroup, false ):SetTime( MenuTime ):SetTag( self.DesignateName )
|
||||
else
|
||||
MENU_GROUP_COMMAND_DELAYED:New( AttackGroup, "Flash Status Report On", StatusMenu, self.MenuFlashStatus, self, AttackGroup, true ):SetTime( MenuTime ):SetTag( self.DesignateName )
|
||||
end
|
||||
|
||||
local DesignateCount = 0
|
||||
|
||||
for DesignateIndex, Designating in pairs( self.Designating ) do
|
||||
|
||||
local DetectedItem = self.Detection:GetDetectedItemByIndex( DesignateIndex )
|
||||
|
||||
if DetectedItem then
|
||||
|
||||
local Coord = self.Detection:GetDetectedItemCoordinate( DetectedItem )
|
||||
local ID = self.Detection:GetDetectedItemID( DetectedItem )
|
||||
local MenuText = ID --.. ", " .. Coord:ToStringA2G( AttackGroup )
|
||||
|
||||
MenuText = string.format( "(%3s) %s", Designating, MenuText )
|
||||
local DetectedMenu = MENU_GROUP_DELAYED:New( AttackGroup, MenuText, MenuDesignate ):SetTime( MenuTime ):SetTag( self.DesignateName )
|
||||
|
||||
-- Build the Lasing menu.
|
||||
if string.find( Designating, "L", 1, true ) == nil then
|
||||
MENU_GROUP_COMMAND_DELAYED:New( AttackGroup, "Search other target", DetectedMenu, self.MenuForget, self, DesignateIndex ):SetTime( MenuTime ):SetTag( self.DesignateName )
|
||||
for LaserCode, MenuText in pairs( self.MenuLaserCodes ) do
|
||||
MENU_GROUP_COMMAND_DELAYED:New( AttackGroup, string.format( MenuText, LaserCode ), DetectedMenu, self.MenuLaseCode, self, DesignateIndex, 60, LaserCode ):SetTime( MenuTime ):SetTag( self.DesignateName )
|
||||
end
|
||||
MENU_GROUP_COMMAND_DELAYED:New( AttackGroup, "Lase with random laser code(s)", DetectedMenu, self.MenuLaseOn, self, DesignateIndex, 60 ):SetTime( MenuTime ):SetTag( self.DesignateName )
|
||||
else
|
||||
MENU_GROUP_COMMAND_DELAYED:New( AttackGroup, "Stop lasing", DetectedMenu, self.MenuLaseOff, self, DesignateIndex ):SetTime( MenuTime ):SetTag( self.DesignateName )
|
||||
end
|
||||
|
||||
-- Build the Smoking menu.
|
||||
if string.find( Designating, "S", 1, true ) == nil then
|
||||
MENU_GROUP_COMMAND_DELAYED:New( AttackGroup, "Smoke red", DetectedMenu, self.MenuSmoke, self, DesignateIndex, SMOKECOLOR.Red ):SetTime( MenuTime ):SetTag( self.DesignateName )
|
||||
MENU_GROUP_COMMAND_DELAYED:New( AttackGroup, "Smoke blue", DetectedMenu, self.MenuSmoke, self, DesignateIndex, SMOKECOLOR.Blue ):SetTime( MenuTime ):SetTag( self.DesignateName )
|
||||
MENU_GROUP_COMMAND_DELAYED:New( AttackGroup, "Smoke green", DetectedMenu, self.MenuSmoke, self, DesignateIndex, SMOKECOLOR.Green ):SetTime( MenuTime ):SetTag( self.DesignateName )
|
||||
MENU_GROUP_COMMAND_DELAYED:New( AttackGroup, "Smoke white", DetectedMenu, self.MenuSmoke, self, DesignateIndex, SMOKECOLOR.White ):SetTime( MenuTime ):SetTag( self.DesignateName )
|
||||
MENU_GROUP_COMMAND_DELAYED:New( AttackGroup, "Smoke orange", DetectedMenu, self.MenuSmoke, self, DesignateIndex, SMOKECOLOR.Orange ):SetTime( MenuTime ):SetTag( self.DesignateName )
|
||||
end
|
||||
|
||||
-- Build the Illuminate menu.
|
||||
if string.find( Designating, "I", 1, true ) == nil then
|
||||
MENU_GROUP_COMMAND_DELAYED:New( AttackGroup, "Illuminate", DetectedMenu, self.MenuIlluminate, self, DesignateIndex ):SetTime( MenuTime ):SetTag( self.DesignateName )
|
||||
end
|
||||
end
|
||||
|
||||
DesignateCount = DesignateCount + 1
|
||||
if DesignateCount > 10 then
|
||||
break
|
||||
end
|
||||
end
|
||||
MenuDesignate:Remove( MenuTime, self.DesignateName )
|
||||
MenuDesignate:Set()
|
||||
end
|
||||
|
||||
|
||||
--- Sets the Designate Menu for all the attack groups.
|
||||
-- @param #DESIGNATE self
|
||||
-- @return #DESIGNATE
|
||||
function DESIGNATE:SetDesignateMenu()
|
||||
|
||||
self.AttackSet:Flush( self )
|
||||
|
||||
local Delay = 1
|
||||
|
||||
self.AttackSet:ForEachGroupAlive(
|
||||
|
||||
--- @param Wrapper.Group#GROUP GroupReport
|
||||
function( AttackGroup )
|
||||
self.MenuDesignate = self.MenuDesignate or {}
|
||||
|
||||
local MissionMenu = nil
|
||||
|
||||
if self.Mission then
|
||||
MissionMenu = self.Mission:GetRootMenu( AttackGroup )
|
||||
end
|
||||
|
||||
local MenuTime = timer.getTime()
|
||||
|
||||
self.MenuDesignate[AttackGroup] = MENU_GROUP_DELAYED:New( AttackGroup, self.DesignateName, MissionMenu ):SetTime( MenuTime ):SetTag( self.DesignateName )
|
||||
local MenuDesignate = self.MenuDesignate[AttackGroup] -- Core.Menu#MENU_GROUP_DELAYED
|
||||
|
||||
-- Set Menu option for auto lase
|
||||
|
||||
if self.AutoLase then
|
||||
MENU_GROUP_COMMAND_DELAYED:New( AttackGroup, "Auto Lase Off", MenuDesignate, self.MenuAutoLase, self, false ):SetTime( MenuTime ):SetTag( self.DesignateName )
|
||||
else
|
||||
MENU_GROUP_COMMAND_DELAYED:New( AttackGroup, "Auto Lase On", MenuDesignate, self.MenuAutoLase, self, true ):SetTime( MenuTime ):SetTag( self.DesignateName )
|
||||
end
|
||||
|
||||
local StatusMenu = MENU_GROUP_DELAYED:New( AttackGroup, "Status", MenuDesignate ):SetTime( MenuTime ):SetTag( self.DesignateName )
|
||||
MENU_GROUP_COMMAND_DELAYED:New( AttackGroup, "Report Status", StatusMenu, self.MenuStatus, self, AttackGroup ):SetTime( MenuTime ):SetTag( self.DesignateName )
|
||||
|
||||
if self.FlashStatusMenu[AttackGroup] then
|
||||
MENU_GROUP_COMMAND_DELAYED:New( AttackGroup, "Flash Status Report Off", StatusMenu, self.MenuFlashStatus, self, AttackGroup, false ):SetTime( MenuTime ):SetTag( self.DesignateName )
|
||||
else
|
||||
MENU_GROUP_COMMAND_DELAYED:New( AttackGroup, "Flash Status Report On", StatusMenu, self.MenuFlashStatus, self, AttackGroup, true ):SetTime( MenuTime ):SetTag( self.DesignateName )
|
||||
end
|
||||
|
||||
for DesignateIndex, Designating in pairs( self.Designating ) do
|
||||
|
||||
local DetectedItem = self.Detection:GetDetectedItemByIndex( DesignateIndex )
|
||||
|
||||
if DetectedItem then
|
||||
|
||||
local Coord = self.Detection:GetDetectedItemCoordinate( DetectedItem )
|
||||
local ID = self.Detection:GetDetectedItemID( DetectedItem )
|
||||
local MenuText = ID --.. ", " .. Coord:ToStringA2G( AttackGroup )
|
||||
|
||||
MenuText = string.format( "(%3s) %s", Designating, MenuText )
|
||||
local DetectedMenu = MENU_GROUP_DELAYED:New( AttackGroup, MenuText, MenuDesignate ):SetTime( MenuTime ):SetTag( self.DesignateName )
|
||||
|
||||
-- Build the Lasing menu.
|
||||
if string.find( Designating, "L", 1, true ) == nil then
|
||||
MENU_GROUP_COMMAND_DELAYED:New( AttackGroup, "Search other target", DetectedMenu, self.MenuForget, self, DesignateIndex ):SetTime( MenuTime ):SetTag( self.DesignateName )
|
||||
for LaserCode, MenuText in pairs( self.MenuLaserCodes ) do
|
||||
MENU_GROUP_COMMAND_DELAYED:New( AttackGroup, string.format( MenuText, LaserCode ), DetectedMenu, self.MenuLaseCode, self, DesignateIndex, 60, LaserCode ):SetTime( MenuTime ):SetTag( self.DesignateName )
|
||||
end
|
||||
MENU_GROUP_COMMAND_DELAYED:New( AttackGroup, "Lase with random laser code(s)", DetectedMenu, self.MenuLaseOn, self, DesignateIndex, 60 ):SetTime( MenuTime ):SetTag( self.DesignateName )
|
||||
else
|
||||
MENU_GROUP_COMMAND_DELAYED:New( AttackGroup, "Stop lasing", DetectedMenu, self.MenuLaseOff, self, DesignateIndex ):SetTime( MenuTime ):SetTag( self.DesignateName )
|
||||
end
|
||||
|
||||
-- Build the Smoking menu.
|
||||
if string.find( Designating, "S", 1, true ) == nil then
|
||||
MENU_GROUP_COMMAND_DELAYED:New( AttackGroup, "Smoke red", DetectedMenu, self.MenuSmoke, self, DesignateIndex, SMOKECOLOR.Red ):SetTime( MenuTime ):SetTag( self.DesignateName )
|
||||
MENU_GROUP_COMMAND_DELAYED:New( AttackGroup, "Smoke blue", DetectedMenu, self.MenuSmoke, self, DesignateIndex, SMOKECOLOR.Blue ):SetTime( MenuTime ):SetTag( self.DesignateName )
|
||||
MENU_GROUP_COMMAND_DELAYED:New( AttackGroup, "Smoke green", DetectedMenu, self.MenuSmoke, self, DesignateIndex, SMOKECOLOR.Green ):SetTime( MenuTime ):SetTag( self.DesignateName )
|
||||
MENU_GROUP_COMMAND_DELAYED:New( AttackGroup, "Smoke white", DetectedMenu, self.MenuSmoke, self, DesignateIndex, SMOKECOLOR.White ):SetTime( MenuTime ):SetTag( self.DesignateName )
|
||||
MENU_GROUP_COMMAND_DELAYED:New( AttackGroup, "Smoke orange", DetectedMenu, self.MenuSmoke, self, DesignateIndex, SMOKECOLOR.Orange ):SetTime( MenuTime ):SetTag( self.DesignateName )
|
||||
end
|
||||
|
||||
-- Build the Illuminate menu.
|
||||
if string.find( Designating, "I", 1, true ) == nil then
|
||||
MENU_GROUP_COMMAND_DELAYED:New( AttackGroup, "Illuminate", DetectedMenu, self.MenuIlluminate, self, DesignateIndex ):SetTime( MenuTime ):SetTag( self.DesignateName )
|
||||
end
|
||||
end
|
||||
end
|
||||
MenuDesignate:Remove( MenuTime, self.DesignateName )
|
||||
MenuDesignate:Set()
|
||||
end
|
||||
self:ScheduleOnce( Delay, self.SetMenu, self, AttackGroup )
|
||||
Delay = Delay + 1
|
||||
end
|
||||
|
||||
)
|
||||
|
||||
return self
|
||||
|
||||
@@ -2,22 +2,25 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- 
|
||||
-- ## Features:
|
||||
--
|
||||
-- * Detection of targets by recce units.
|
||||
-- * Group detected targets per unit, type or area (zone).
|
||||
-- * Keep persistency of detected targets, if when detection is lost.
|
||||
-- * Provide an indication of detected targets.
|
||||
-- * Report detected targets.
|
||||
-- * Refresh detection upon specified time intervals.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- DETECTION classes facilitate the detection of enemy units within the battle zone executed by FACs (Forward Air Controllers) or RECCEs (Reconnassance Units).
|
||||
-- DETECTION uses the in-built detection capabilities of DCS World, but adds new functionalities.
|
||||
-- ## Missions:
|
||||
--
|
||||
-- Find the DETECTION classes documentation further in this document in the globals section.
|
||||
-- [DET - Detection](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/DET%20-%20Detection)
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/DET%20-%20Detection)
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### [YouTube Playlist](https://www.youtube.com/playlist?list=PL7ZUrU4zZUl3Cf5jpI6BS0sBOVWK__tji)
|
||||
-- Facilitate the detection of enemy units within the battle zone executed by FACs (Forward Air Controllers) or RECCEs (Reconnassance Units).
|
||||
-- It uses the in-built detection capabilities of DCS World, but adds new functionalities.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
@@ -29,27 +32,24 @@
|
||||
--
|
||||
-- * FlightControl : Analysis, Design, Programming, Testing
|
||||
--
|
||||
-- @module Detection
|
||||
-- ===
|
||||
--
|
||||
-- @module Functional.Detection
|
||||
-- @image Detection.JPG
|
||||
|
||||
----BASE:TraceClass("DETECTION_BASE")
|
||||
----BASE:TraceClass("DETECTION_AREAS")
|
||||
----BASE:TraceClass("DETECTION_UNITS")
|
||||
----BASE:TraceClass("DETECTION_TYPES")
|
||||
|
||||
do -- DETECTION_BASE
|
||||
|
||||
--- @type DETECTION_BASE
|
||||
-- @field Core.Set#SET_GROUP DetectionSetGroup The @{Set} of GROUPs in the Forward Air Controller role.
|
||||
-- @field Dcs.DCSTypes#Distance DetectionRange The range till which targets are accepted to be detected.
|
||||
-- @field DCS#Distance DetectionRange The range till which targets are accepted to be detected.
|
||||
-- @field #DETECTION_BASE.DetectedObjects DetectedObjects The list of detected objects.
|
||||
-- @field #table DetectedObjectsIdentified Map of the DetectedObjects identified.
|
||||
-- @field #number DetectionRun
|
||||
-- @extends Core.Fsm#FSM
|
||||
|
||||
--- DETECTION_BASE class, extends @{Fsm#FSM}
|
||||
--
|
||||
-- The DETECTION_BASE class defines the core functions to administer detected objects.
|
||||
-- The DETECTION_BASE class will detect objects within the battle zone for a list of @{Group}s detecting targets following (a) detection method(s).
|
||||
--- Defines the core functions to administer detected objects.
|
||||
-- The DETECTION_BASE class will detect objects within the battle zone for a list of @{Wrapper.Group}s detecting targets following (a) detection method(s).
|
||||
--
|
||||
-- ## DETECTION_BASE constructor
|
||||
--
|
||||
@@ -105,11 +105,11 @@ do -- DETECTION_BASE
|
||||
--
|
||||
-- Various methods exist how to retrieve the grouped items from a DETECTION_BASE derived class:
|
||||
--
|
||||
-- * The method @{Detection#DETECTION_BASE.GetDetectedItems}() retrieves the DetectedItems[] list.
|
||||
-- * A DetectedItem from the DetectedItems[] list can be retrieved using the method @{Detection#DETECTION_BASE.GetDetectedItem}( DetectedItemIndex ).
|
||||
-- * The method @{Functional.Detection#DETECTION_BASE.GetDetectedItems}() retrieves the DetectedItems[] list.
|
||||
-- * A DetectedItem from the DetectedItems[] list can be retrieved using the method @{Functional.Detection#DETECTION_BASE.GetDetectedItem}( DetectedItemIndex ).
|
||||
-- Note that this method returns a DetectedItem element from the list, that contains a Set variable and further information
|
||||
-- about the DetectedItem that is set by the DETECTION_BASE derived classes, used to group the DetectedItem.
|
||||
-- * A DetectedSet from the DetectedItems[] list can be retrieved using the method @{Detection#DETECTION_BASE.GetDetectedSet}( DetectedItemIndex ).
|
||||
-- * A DetectedSet from the DetectedItems[] list can be retrieved using the method @{Functional.Detection#DETECTION_BASE.GetDetectedSet}( DetectedItemIndex ).
|
||||
-- This method retrieves the Set from a DetectedItem element from the DetectedItem list (DetectedItems[ DetectedItemIndex ].Set ).
|
||||
--
|
||||
-- ## **Visual filters** to fine-tune the probability of the detected objects
|
||||
@@ -146,7 +146,7 @@ do -- DETECTION_BASE
|
||||
--
|
||||
-- Note that based on this probability factor, not only the detection but also the **type** of the unit will be applied!
|
||||
--
|
||||
-- Use the method @{Detection#DETECTION_BASE.SetDistanceProbability}() to set the probability factor upon a 10 km distance.
|
||||
-- Use the method @{Functional.Detection#DETECTION_BASE.SetDistanceProbability}() to set the probability factor upon a 10 km distance.
|
||||
--
|
||||
-- ### Alpha Angle visual detection probability
|
||||
--
|
||||
@@ -158,7 +158,7 @@ do -- DETECTION_BASE
|
||||
-- For example, if a alpha angle probability factor of 0.7 is given, the extrapolated probabilities of the different angles would look like:
|
||||
-- 0°: 70%, 10°: 75,21%, 20°: 80,26%, 30°: 85%, 40°: 89,28%, 50°: 92,98%, 60°: 95,98%, 70°: 98,19%, 80°: 99,54%, 90°: 100%
|
||||
--
|
||||
-- Use the method @{Detection#DETECTION_BASE.SetAlphaAngleProbability}() to set the probability factor if 0°.
|
||||
-- Use the method @{Functional.Detection#DETECTION_BASE.SetAlphaAngleProbability}() to set the probability factor if 0°.
|
||||
--
|
||||
-- ### Cloudy Zones detection probability
|
||||
--
|
||||
@@ -166,7 +166,7 @@ do -- DETECTION_BASE
|
||||
-- The Cloudy Zones work with the ZONE_BASE derived classes. The mission designer can define within the mission
|
||||
-- zones that reflect cloudy areas where detected units may not be so easily visually detected.
|
||||
--
|
||||
-- Use the method @{Detection#DETECTION_BASE.SetZoneProbability}() to set for a defined number of zones, the probability factors.
|
||||
-- Use the method @{Functional.Detection#DETECTION_BASE.SetZoneProbability}() to set for a defined number of zones, the probability factors.
|
||||
--
|
||||
-- Note however, that the more zones are defined to be "cloudy" within a detection, the more performance it will take
|
||||
-- from the DETECTION_BASE to calculate the presence of the detected unit within each zone.
|
||||
@@ -183,7 +183,7 @@ do -- DETECTION_BASE
|
||||
-- ### Detection acceptance of within range limit
|
||||
--
|
||||
-- A range can be set that will limit a successful detection for a unit.
|
||||
-- Use the method @{Detection#DETECTION_BASE.SetAcceptRange}() to apply a range in meters till where detected units will be accepted.
|
||||
-- Use the method @{Functional.Detection#DETECTION_BASE.SetAcceptRange}() to apply a range in meters till where detected units will be accepted.
|
||||
--
|
||||
-- local SetGroup = SET_GROUP:New():FilterPrefixes( "FAC" ):FilterStart() -- Build a SetGroup of Forward Air Controllers.
|
||||
--
|
||||
@@ -200,7 +200,7 @@ do -- DETECTION_BASE
|
||||
-- ### Detection acceptance if within zone(s).
|
||||
--
|
||||
-- Specific ZONE_BASE object(s) can be given as a parameter, which will only accept a detection if the unit is within the specified ZONE_BASE object(s).
|
||||
-- Use the method @{Detection#DETECTION_BASE.SetAcceptZones}() will accept detected units if they are within the specified zones.
|
||||
-- Use the method @{Functional.Detection#DETECTION_BASE.SetAcceptZones}() will accept detected units if they are within the specified zones.
|
||||
--
|
||||
-- local SetGroup = SET_GROUP:New():FilterPrefixes( "FAC" ):FilterStart() -- Build a SetGroup of Forward Air Controllers.
|
||||
--
|
||||
@@ -220,7 +220,7 @@ do -- DETECTION_BASE
|
||||
-- ### Detection rejectance if within zone(s).
|
||||
--
|
||||
-- Specific ZONE_BASE object(s) can be given as a parameter, which will reject detection if the unit is within the specified ZONE_BASE object(s).
|
||||
-- Use the method @{Detection#DETECTION_BASE.SetRejectZones}() will reject detected units if they are within the specified zones.
|
||||
-- Use the method @{Functional.Detection#DETECTION_BASE.SetRejectZones}() will reject detected units if they are within the specified zones.
|
||||
-- An example of how to use the method is shown below.
|
||||
--
|
||||
-- local SetGroup = SET_GROUP:New():FilterPrefixes( "FAC" ):FilterStart() -- Build a SetGroup of Forward Air Controllers.
|
||||
@@ -240,7 +240,7 @@ do -- DETECTION_BASE
|
||||
--
|
||||
-- ## Detection of Friendlies Nearby
|
||||
--
|
||||
-- Use the method @{Detection#DETECTION_BASE.SetFriendliesRange}() to set the range what will indicate when friendlies are nearby
|
||||
-- Use the method @{Functional.Detection#DETECTION_BASE.SetFriendliesRange}() to set the range what will indicate when friendlies are nearby
|
||||
-- a DetectedItem. The default range is 6000 meters. For air detections, it is advisory to use about 30.000 meters.
|
||||
--
|
||||
-- ## DETECTION_BASE is a Finite State Machine
|
||||
@@ -292,6 +292,7 @@ do -- DETECTION_BASE
|
||||
-- @list <#DETECTION_BASE.DetectedItem>
|
||||
|
||||
--- @type DETECTION_BASE.DetectedItem
|
||||
-- @field #boolean IsDetected Indicates if the DetectedItem has been detected or not.
|
||||
-- @field Core.Set#SET_UNIT Set
|
||||
-- @field Core.Set#SET_UNIT Set -- The Set of Units in the detected area.
|
||||
-- @field Core.Zone#ZONE_UNIT Zone -- The Zone of the detected area.
|
||||
@@ -450,7 +451,16 @@ do -- DETECTION_BASE
|
||||
-- @param #DETECTION_BASE self
|
||||
-- @param #number Delay The delay in seconds.
|
||||
|
||||
self:AddTransition( "Detecting", "DetectedItem", "Detecting" )
|
||||
|
||||
--- OnAfter Transition Handler for Event DetectedItem.
|
||||
-- @function [parent=#DETECTION_BASE] OnAfterDetectedItem
|
||||
-- @param #DETECTION_BASE self
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
-- @param #table DetectedItem The DetectedItem.
|
||||
|
||||
self:AddTransition( "*", "Stop", "Stopped" )
|
||||
|
||||
--- OnBefore Transition Handler for Event Stop.
|
||||
@@ -518,8 +528,21 @@ do -- DETECTION_BASE
|
||||
|
||||
local DetectionTimeStamp = timer.getTime()
|
||||
|
||||
-- Reset detection cache for the next detection run.
|
||||
for DetectionObjectName, DetectedObjectData in pairs( self.DetectedObjects ) do
|
||||
|
||||
self.DetectedObjects[DetectionObjectName].IsDetected = false
|
||||
self.DetectedObjects[DetectionObjectName].IsVisible = false
|
||||
self.DetectedObjects[DetectionObjectName].KnowDistance = nil
|
||||
self.DetectedObjects[DetectionObjectName].LastTime = nil
|
||||
self.DetectedObjects[DetectionObjectName].LastPos = nil
|
||||
self.DetectedObjects[DetectionObjectName].LastVelocity = nil
|
||||
self.DetectedObjects[DetectionObjectName].Distance = 10000000
|
||||
|
||||
end
|
||||
for DetectionGroupID, DetectionGroupData in pairs( self.DetectionSetGroup:GetSet() ) do
|
||||
--self:F( { DetectionGroupData } )
|
||||
self:F( { DetectionGroup = DetectionGroupData:GetName() } )
|
||||
self:__DetectionGroup( DetectDelay, DetectionGroupData, DetectionTimeStamp ) -- Process each detection asynchronously.
|
||||
self.DetectionCount = self.DetectionCount + 1
|
||||
DetectDelay = DetectDelay + 1
|
||||
@@ -531,8 +554,11 @@ do -- DETECTION_BASE
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
-- @param Wrapper.Group#GROUP DetectionGroup The Group detecting.
|
||||
-- @param #number DetectionTimeStamp Time stamp of detection event.
|
||||
function DETECTION_BASE:onafterDetectionGroup( From, Event, To, DetectionGroup, DetectionTimeStamp )
|
||||
|
||||
--self:F( { DetectedObjects = self.DetectedObjects } )
|
||||
|
||||
self.DetectionRun = self.DetectionRun + 1
|
||||
|
||||
local HasDetectedObjects = false
|
||||
@@ -555,13 +581,27 @@ do -- DETECTION_BASE
|
||||
self.DetectDLINK
|
||||
)
|
||||
|
||||
--self:F( DetectedTargets )
|
||||
self:F( { DetectedTargets = DetectedTargets } )
|
||||
|
||||
for DetectionObjectID, Detection in pairs( DetectedTargets ) do
|
||||
local DetectedObject = Detection.object -- Dcs.DCSWrapper.Object#Object
|
||||
local DetectedObject = Detection.object -- DCS#Object
|
||||
|
||||
if DetectedObject and DetectedObject:isExist() and DetectedObject.id_ < 50000000 then -- and ( DetectedObject:getCategory() == Object.Category.UNIT or DetectedObject:getCategory() == Object.Category.STATIC ) then
|
||||
|
||||
local DetectedObjectName = DetectedObject:getName()
|
||||
if not self.DetectedObjects[DetectedObjectName] then
|
||||
self.DetectedObjects[DetectedObjectName] = self.DetectedObjects[DetectedObjectName] or {}
|
||||
self.DetectedObjects[DetectedObjectName].Name = DetectedObjectName
|
||||
self.DetectedObjects[DetectedObjectName].Object = DetectedObject
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
for DetectionObjectName, DetectedObjectData in pairs( self.DetectedObjects ) do
|
||||
|
||||
local DetectedObject = DetectedObjectData.Object
|
||||
|
||||
if DetectedObject:isExist() then
|
||||
|
||||
local TargetIsDetected, TargetIsVisible, TargetLastTime, TargetKnowType, TargetKnowDistance, TargetLastPos, TargetLastVelocity = DetectionUnit:IsTargetDetected(
|
||||
DetectedObject,
|
||||
self.DetectVisual,
|
||||
@@ -573,7 +613,7 @@ do -- DETECTION_BASE
|
||||
)
|
||||
|
||||
--self:T2( { TargetIsDetected = TargetIsDetected, TargetIsVisible = TargetIsVisible, TargetLastTime = TargetLastTime, TargetKnowType = TargetKnowType, TargetKnowDistance = TargetKnowDistance, TargetLastPos = TargetLastPos, TargetLastVelocity = TargetLastVelocity } )
|
||||
|
||||
|
||||
-- Only process if the target is visible. Detection also returns invisible units.
|
||||
--if Detection.visible == true then
|
||||
|
||||
@@ -636,7 +676,7 @@ do -- DETECTION_BASE
|
||||
|
||||
-- Calculate additional probabilities
|
||||
|
||||
if not self.DetectedObjects[DetectedObjectName] and Detection.visible and self.DistanceProbability then
|
||||
if not self.DetectedObjects[DetectedObjectName] and TargetIsVisible and self.DistanceProbability then
|
||||
local DistanceFactor = Distance / 4
|
||||
local DistanceProbabilityReversed = ( 1 - self.DistanceProbability ) * DistanceFactor
|
||||
local DistanceProbability = 1 - DistanceProbabilityReversed
|
||||
@@ -648,7 +688,7 @@ do -- DETECTION_BASE
|
||||
end
|
||||
end
|
||||
|
||||
if not self.DetectedObjects[DetectedObjectName] and Detection.visible and self.AlphaAngleProbability then
|
||||
if not self.DetectedObjects[DetectedObjectName] and TargetIsVisible and self.AlphaAngleProbability then
|
||||
local NormalVec2 = { x = DetectedObjectVec2.x - DetectionGroupVec2.x, y = DetectedObjectVec2.y - DetectionGroupVec2.y }
|
||||
local AlphaAngle = math.atan2( NormalVec2.y, NormalVec2.x )
|
||||
local Sinus = math.sin( AlphaAngle )
|
||||
@@ -665,7 +705,7 @@ do -- DETECTION_BASE
|
||||
|
||||
end
|
||||
|
||||
if not self.DetectedObjects[DetectedObjectName] and Detection.visible and self.ZoneProbability then
|
||||
if not self.DetectedObjects[DetectedObjectName] and TargetIsVisible and self.ZoneProbability then
|
||||
|
||||
for ZoneDataID, ZoneData in pairs( self.ZoneProbability ) do
|
||||
self:F({ZoneData})
|
||||
@@ -688,33 +728,50 @@ do -- DETECTION_BASE
|
||||
|
||||
HasDetectedObjects = true
|
||||
|
||||
self.DetectedObjects[DetectedObjectName] = self.DetectedObjects[DetectedObjectName] or {}
|
||||
self.DetectedObjects[DetectedObjectName] = self.DetectedObjects[DetectedObjectName] or {}
|
||||
self.DetectedObjects[DetectedObjectName].Name = DetectedObjectName
|
||||
self.DetectedObjects[DetectedObjectName].IsDetected = TargetIsDetected
|
||||
self.DetectedObjects[DetectedObjectName].IsVisible = TargetIsVisible
|
||||
self.DetectedObjects[DetectedObjectName].LastTime = TargetLastTime
|
||||
self.DetectedObjects[DetectedObjectName].LastPos = TargetLastPos
|
||||
self.DetectedObjects[DetectedObjectName].LastVelocity = TargetLastVelocity
|
||||
self.DetectedObjects[DetectedObjectName].KnowType = TargetKnowType
|
||||
self.DetectedObjects[DetectedObjectName].KnowDistance = Detection.distance -- TargetKnowDistance
|
||||
self.DetectedObjects[DetectedObjectName].Distance = Distance
|
||||
|
||||
if TargetIsDetected and TargetIsDetected == true then
|
||||
self.DetectedObjects[DetectedObjectName].IsDetected = TargetIsDetected
|
||||
end
|
||||
|
||||
if TargetIsDetected and TargetIsVisible and TargetIsVisible == true then
|
||||
self.DetectedObjects[DetectedObjectName].IsVisible = TargetIsDetected and TargetIsVisible
|
||||
end
|
||||
|
||||
if TargetIsDetected and not self.DetectedObjects[DetectedObjectName].KnowType then
|
||||
self.DetectedObjects[DetectedObjectName].KnowType = TargetIsDetected and TargetKnowType
|
||||
end
|
||||
self.DetectedObjects[DetectedObjectName].KnowDistance = TargetKnowDistance -- Detection.distance -- TargetKnowDistance
|
||||
self.DetectedObjects[DetectedObjectName].LastTime = ( TargetIsDetected and TargetIsVisible == false ) and TargetLastTime
|
||||
self.DetectedObjects[DetectedObjectName].LastPos = ( TargetIsDetected and TargetIsVisible == false ) and TargetLastPos
|
||||
self.DetectedObjects[DetectedObjectName].LastVelocity = ( TargetIsDetected and TargetIsVisible == false ) and TargetLastVelocity
|
||||
|
||||
if not self.DetectedObjects[DetectedObjectName].Distance or ( Distance and self.DetectedObjects[DetectedObjectName].Distance > Distance ) then
|
||||
self.DetectedObjects[DetectedObjectName].Distance = Distance
|
||||
end
|
||||
|
||||
self.DetectedObjects[DetectedObjectName].DetectionTimeStamp = DetectionTimeStamp
|
||||
|
||||
--self:F( { DetectedObject = self.DetectedObjects[DetectedObjectName] } )
|
||||
self:F( { DetectedObject = self.DetectedObjects[DetectedObjectName] } )
|
||||
|
||||
local DetectedUnit = UNIT:FindByName( DetectedObjectName )
|
||||
|
||||
DetectedUnits[DetectedObjectName] = DetectedUnit
|
||||
else
|
||||
-- if beyond the DetectionRange then nullify...
|
||||
self:F( { DetectedObject = "No more detection for " .. DetectedObjectName } )
|
||||
if self.DetectedObjects[DetectedObjectName] then
|
||||
self.DetectedObjects[DetectedObjectName] = nil
|
||||
end
|
||||
end
|
||||
--end
|
||||
|
||||
--self:T2( self.DetectedObjects )
|
||||
else
|
||||
-- The previously detected object does not exist anymore, delete from the cache.
|
||||
self:F( "Removing from DetectedObjects: " .. DetectionObjectName )
|
||||
self.DetectedObjects[DetectionObjectName] = nil
|
||||
end
|
||||
|
||||
--self:T2( self.DetectedObjects )
|
||||
end
|
||||
|
||||
if HasDetectedObjects then
|
||||
@@ -740,6 +797,9 @@ do -- DETECTION_BASE
|
||||
for DetectedItemID, DetectedItem in pairs( self.DetectedItems ) do
|
||||
self:UpdateDetectedItemDetection( DetectedItem )
|
||||
self:CleanDetectionItem( DetectedItem, DetectedItemID ) -- Any DetectionItem that has a Set with zero elements in it, must be removed from the DetectionItems list.
|
||||
if DetectedItem then
|
||||
self:__DetectedItem( 0.1, DetectedItem )
|
||||
end
|
||||
end
|
||||
|
||||
self:__Detect( self.RefreshTimeInterval )
|
||||
@@ -896,7 +956,7 @@ do -- DETECTION_BASE
|
||||
-- DetectionObject:FilterCategories( { Unit.Category.AIRPLANE, Unit.Category.HELICOPTER } )
|
||||
--
|
||||
-- @param #DETECTION_BASE self
|
||||
-- @param #list<Dcs.DCSUnit#Unit> FilterCategories The Categories entries
|
||||
-- @param #list<DCS#Unit> FilterCategories The Categories entries
|
||||
-- @return #DETECTION_BASE self
|
||||
function DETECTION_BASE:FilterCategories( FilterCategories )
|
||||
self:F2()
|
||||
@@ -1170,7 +1230,7 @@ do -- DETECTION_BASE
|
||||
--- Returns if there are friendlies nearby the FAC units ...
|
||||
-- @param #DETECTION_BASE self
|
||||
-- @param DetectedItem
|
||||
-- @param Dcs.DCSUnit#Unit.Category Category The category of the unit.
|
||||
-- @param DCS#Unit.Category Category The category of the unit.
|
||||
-- @return #boolean true if there are friendlies nearby
|
||||
function DETECTION_BASE:IsFriendliesNearBy( DetectedItem, Category )
|
||||
--self:F( { "FriendliesNearBy Test", DetectedItem.FriendliesNearBy } )
|
||||
@@ -1180,7 +1240,7 @@ do -- DETECTION_BASE
|
||||
--- Returns friendly units nearby the FAC units ...
|
||||
-- @param #DETECTION_BASE self
|
||||
-- @param DetectedItem
|
||||
-- @param Dcs.DCSUnit#Unit.Category Category The category of the unit.
|
||||
-- @param DCS#Unit.Category Category The category of the unit.
|
||||
-- @return #map<#string,Wrapper.Unit#UNIT> The map of Friendly UNITs.
|
||||
function DETECTION_BASE:GetFriendliesNearBy( DetectedItem, Category )
|
||||
|
||||
@@ -1253,9 +1313,9 @@ do -- DETECTION_BASE
|
||||
|
||||
}
|
||||
|
||||
--- @param Dcs.DCSWrapper.Unit#Unit FoundDCSUnit
|
||||
--- @param DCS#Unit FoundDCSUnit
|
||||
-- @param Wrapper.Group#GROUP ReportGroup
|
||||
-- @param Set#SET_GROUP ReportSetGroup
|
||||
-- @param Core.Set#SET_GROUP ReportSetGroup
|
||||
local FindNearByFriendlies = function( FoundDCSUnit, ReportGroupData )
|
||||
|
||||
local DetectedItem = ReportGroupData.DetectedItem -- Functional.Detection#DETECTION_BASE.DetectedItem
|
||||
@@ -1401,16 +1461,18 @@ do -- DETECTION_BASE
|
||||
-- @param #string ObjectName
|
||||
-- @return #DETECTION_BASE.DetectedObject
|
||||
function DETECTION_BASE:GetDetectedObject( ObjectName )
|
||||
--self:F2( ObjectName )
|
||||
self:F2( { ObjectName = ObjectName } )
|
||||
|
||||
if ObjectName then
|
||||
local DetectedObject = self.DetectedObjects[ObjectName]
|
||||
|
||||
if DetectedObject then
|
||||
--self:F( { DetectedObjects = self.DetectedObjects } )
|
||||
-- Only return detected objects that are alive!
|
||||
local DetectedUnit = UNIT:FindByName( ObjectName )
|
||||
if DetectedUnit and DetectedUnit:IsAlive() then
|
||||
if self:IsDetectedObjectIdentified( DetectedObject ) == false then
|
||||
--self:F( { DetectedObject = DetectedObject } )
|
||||
return DetectedObject
|
||||
end
|
||||
end
|
||||
@@ -1595,7 +1657,7 @@ do -- DETECTION_BASE
|
||||
return ""
|
||||
end
|
||||
|
||||
--- Get the @{Set#SET_UNIT} of a detecttion area using a given numeric index.
|
||||
--- Get the @{Core.Set#SET_UNIT} of a detecttion area using a given numeric index.
|
||||
-- @param #DETECTION_BASE self
|
||||
-- @param #DETECTION_BASE.DetectedItem DetectedItem
|
||||
-- @return Core.Set#SET_UNIT DetectedSet
|
||||
@@ -1609,7 +1671,7 @@ do -- DETECTION_BASE
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Set IsDetected flag for all DetectedItems.
|
||||
--- Set IsDetected flag for the DetectedItem, which can have more units.
|
||||
-- @param #DETECTION_BASE self
|
||||
-- @return #DETECTION_BASE.DetectedItem DetectedItem
|
||||
-- @return #boolean true if at least one UNIT is detected from the DetectedSet, false if no UNIT was detected from the DetectedSet.
|
||||
@@ -1644,7 +1706,7 @@ do -- DETECTION_BASE
|
||||
|
||||
do -- Zones
|
||||
|
||||
--- Get the @{Zone#ZONE_UNIT} of a detection area using a given numeric index.
|
||||
--- Get the @{Core.Zone#ZONE_UNIT} of a detection area using a given numeric index.
|
||||
-- @param #DETECTION_BASE self
|
||||
-- @param #DETECTION_BASE.DetectedItem DetectedItem The DetectedItem.
|
||||
-- @return Core.Zone#ZONE_UNIT DetectedZone
|
||||
@@ -1807,15 +1869,16 @@ end
|
||||
|
||||
do -- DETECTION_UNITS
|
||||
|
||||
--- # DETECTION_UNITS class, extends @{Detection#DETECTION_BASE}
|
||||
--- @type DETECTION_UNITS
|
||||
-- @field DCS#Distance DetectionRange The range till which targets are detected.
|
||||
-- @extends Functional.Detection#DETECTION_BASE
|
||||
|
||||
--- Will detect units within the battle zone.
|
||||
--
|
||||
-- The DETECTION_UNITS class will detect units within the battle zone.
|
||||
-- It will build a DetectedItems list filled with DetectedItems. Each DetectedItem will contain a field Set, which contains a @{Set#SET_UNIT} containing ONE @{UNIT} object reference.
|
||||
-- It will build a DetectedItems list filled with DetectedItems. Each DetectedItem will contain a field Set, which contains a @{Core.Set#SET_UNIT} containing ONE @{UNIT} object reference.
|
||||
-- Beware that when the amount of units detected is large, the DetectedItems list will be large also.
|
||||
--
|
||||
-- @type DETECTION_UNITS
|
||||
-- @field Dcs.DCSTypes#Distance DetectionRange The range till which targets are detected.
|
||||
-- @extends #DETECTION_BASE
|
||||
-- @field #DETECTION_UNITS
|
||||
DETECTION_UNITS = {
|
||||
ClassName = "DETECTION_UNITS",
|
||||
DetectionRange = nil,
|
||||
@@ -1841,7 +1904,7 @@ do -- DETECTION_UNITS
|
||||
|
||||
--- Make text documenting the changes of the detected zone.
|
||||
-- @param #DETECTION_UNITS self
|
||||
-- @param #DETECTION_UNITS.DetectedItem DetectedItem
|
||||
-- @param #DETECTION_BASE.DetectedItem DetectedItem
|
||||
-- @return #string The Changes text
|
||||
function DETECTION_UNITS:GetChangeText( DetectedItem )
|
||||
self:F( DetectedItem )
|
||||
@@ -1882,7 +1945,6 @@ do -- DETECTION_UNITS
|
||||
-- @param #DETECTION_UNITS self
|
||||
-- @return #DETECTION_UNITS self
|
||||
function DETECTION_UNITS:CreateDetectionItems()
|
||||
|
||||
-- Loop the current detected items, and check if each object still exists and is detected.
|
||||
|
||||
for DetectedItemKey, DetectedItem in pairs( self.DetectedItems ) do
|
||||
@@ -1903,6 +1965,7 @@ do -- DETECTION_UNITS
|
||||
-- Yes, the DetectedUnit is still detected or exists. Flag as identified.
|
||||
self:IdentifyDetectedObject( DetectedObject )
|
||||
|
||||
self:F( { "**DETECTED**", IsVisible = DetectedObject.IsVisible } )
|
||||
-- Update the detection with the new data provided.
|
||||
DetectedItem.TypeName = DetectedUnit:GetTypeName()
|
||||
DetectedItem.CategoryName = DetectedUnit:GetCategoryName()
|
||||
@@ -2027,6 +2090,9 @@ do -- DETECTION_UNITS
|
||||
Report:Add(DetectedItemID .. ", " .. DetectedItemCoordText)
|
||||
Report:Add( string.format( "Threat: [%s]", string.rep( "■", ThreatLevelA2G ), string.rep( "□", 10-ThreatLevelA2G ) ) )
|
||||
Report:Add( string.format("Type: %s%s", UnitCategoryText, UnitDistanceText ) )
|
||||
Report:Add( string.format("Visible: %s", DetectedItem.IsVisible and "yes" or "no" ) )
|
||||
Report:Add( string.format("Detected: %s", DetectedItem.IsDetected and "yes" or "no" ) )
|
||||
Report:Add( string.format("Distance: %s", DetectedItem.KnowDistance and "yes" or "no" ) )
|
||||
return Report
|
||||
end
|
||||
return nil
|
||||
@@ -2057,15 +2123,15 @@ end
|
||||
|
||||
do -- DETECTION_TYPES
|
||||
|
||||
--- # 3) DETECTION_TYPES class, extends @{Detection#DETECTION_BASE}
|
||||
--
|
||||
-- The DETECTION_TYPES class will detect units within the battle zone.
|
||||
--- @type DETECTION_TYPES
|
||||
-- @extends Functional.Detection#DETECTION_BASE
|
||||
|
||||
--- Will detect units within the battle zone.
|
||||
-- It will build a DetectedItems[] list filled with DetectedItems, grouped by the type of units detected.
|
||||
-- Each DetectedItem will contain a field Set, which contains a @{Set#SET_UNIT} containing ONE @{UNIT} object reference.
|
||||
-- Each DetectedItem will contain a field Set, which contains a @{Core.Set#SET_UNIT} containing ONE @{UNIT} object reference.
|
||||
-- Beware that when the amount of different types detected is large, the DetectedItems[] list will be large also.
|
||||
--
|
||||
-- @type DETECTION_TYPES
|
||||
-- @extends #DETECTION_BASE
|
||||
-- @field #DETECTION_TYPES
|
||||
DETECTION_TYPES = {
|
||||
ClassName = "DETECTION_TYPES",
|
||||
DetectionRange = nil,
|
||||
@@ -2091,7 +2157,7 @@ do -- DETECTION_TYPES
|
||||
|
||||
--- Make text documenting the changes of the detected zone.
|
||||
-- @param #DETECTION_TYPES self
|
||||
-- @param #DETECTION_TYPES.DetectedItem DetectedItem
|
||||
-- @param Functional.Detection#DETECTION_BASE.DetectedItem DetectedItem
|
||||
-- @return #string The Changes text
|
||||
function DETECTION_TYPES:GetChangeText( DetectedItem )
|
||||
self:F( DetectedItem )
|
||||
@@ -2266,42 +2332,42 @@ end
|
||||
|
||||
do -- DETECTION_AREAS
|
||||
|
||||
--- # 4) DETECTION_AREAS class, extends @{Detection#DETECTION_BASE}
|
||||
--
|
||||
-- The DETECTION_AREAS class will detect units within the battle zone for a list of @{Group}s detecting targets following (a) detection method(s),
|
||||
-- and will build a list (table) of @{Set#SET_UNIT}s containing the @{Unit#UNIT}s detected.
|
||||
--- @type DETECTION_AREAS
|
||||
-- @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, @{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
|
||||
|
||||
--- Detect units within the battle zone for a list of @{Wrapper.Group}s detecting targets following (a) detection method(s),
|
||||
-- and will build a list (table) of @{Core.Set#SET_UNIT}s containing the @{Wrapper.Unit#UNIT}s detected.
|
||||
-- The class is group the detected units within zones given a DetectedZoneRange parameter.
|
||||
-- A set with multiple detected zones will be created as there are groups of units detected.
|
||||
--
|
||||
-- ## 4.1) Retrieve the Detected Unit Sets and Detected Zones
|
||||
--
|
||||
-- The methods to manage the DetectedItems[].Set(s) are implemented in @{Detection#DECTECTION_BASE} and
|
||||
-- the methods to manage the DetectedItems[].Zone(s) is implemented in @{Detection#DETECTION_AREAS}.
|
||||
-- The methods to manage the DetectedItems[].Set(s) are implemented in @{Functional.Detection#DECTECTION_BASE} and
|
||||
-- the methods to manage the DetectedItems[].Zone(s) is implemented in @{Functional.Detection#DETECTION_AREAS}.
|
||||
--
|
||||
-- Retrieve the DetectedItems[].Set with the method @{Detection#DETECTION_BASE.GetDetectedSet}(). A @{Set#SET_UNIT} object will be returned.
|
||||
-- Retrieve the DetectedItems[].Set with the method @{Functional.Detection#DETECTION_BASE.GetDetectedSet}(). A @{Core.Set#SET_UNIT} object will be returned.
|
||||
--
|
||||
-- Retrieve the formed @{Zone@ZONE_UNIT}s as a result of the grouping the detected units within the DetectionZoneRange, use the method @{Detection#DETECTION_BASE.GetDetectionZones}().
|
||||
-- To understand the amount of zones created, use the method @{Detection#DETECTION_BASE.GetDetectionZoneCount}().
|
||||
-- If you want to obtain a specific zone from the DetectedZones, use the method @{Detection#DETECTION_BASE.GetDetectionZone}() with a given index.
|
||||
-- Retrieve the formed @{Zone@ZONE_UNIT}s as a result of the grouping the detected units within the DetectionZoneRange, use the method @{Functional.Detection#DETECTION_BASE.GetDetectionZones}().
|
||||
-- To understand the amount of zones created, use the method @{Functional.Detection#DETECTION_BASE.GetDetectionZoneCount}().
|
||||
-- If you want to obtain a specific zone from the DetectedZones, use the method @{Functional.Detection#DETECTION_BASE.GetDetectionZone}() with a given index.
|
||||
--
|
||||
-- ## 4.4) Flare or Smoke detected units
|
||||
--
|
||||
-- Use the methods @{Detection#DETECTION_AREAS.FlareDetectedUnits}() or @{Detection#DETECTION_AREAS.SmokeDetectedUnits}() to flare or smoke the detected units when a new detection has taken place.
|
||||
-- Use the methods @{Functional.Detection#DETECTION_AREAS.FlareDetectedUnits}() or @{Functional.Detection#DETECTION_AREAS.SmokeDetectedUnits}() to flare or smoke the detected units when a new detection has taken place.
|
||||
--
|
||||
-- ## 4.5) Flare or Smoke or Bound detected zones
|
||||
--
|
||||
-- Use the methods:
|
||||
--
|
||||
-- * @{Detection#DETECTION_AREAS.FlareDetectedZones}() to flare in a color
|
||||
-- * @{Detection#DETECTION_AREAS.SmokeDetectedZones}() to smoke in a color
|
||||
-- * @{Detection#DETECTION_AREAS.SmokeDetectedZones}() to bound with a tire with a white flag
|
||||
-- * @{Functional.Detection#DETECTION_AREAS.FlareDetectedZones}() to flare in a color
|
||||
-- * @{Functional.Detection#DETECTION_AREAS.SmokeDetectedZones}() to smoke in a color
|
||||
-- * @{Functional.Detection#DETECTION_AREAS.SmokeDetectedZones}() to bound with a tire with a white flag
|
||||
--
|
||||
-- the detected zones when a new detection has taken place.
|
||||
--
|
||||
-- @type DETECTION_AREAS
|
||||
-- @field Dcs.DCSTypes#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 @{Unit}s, @{Zone}s, the center @{Unit} within the zone, and ID of each area that was detected within a DetectionZoneRange.
|
||||
-- @extends #DETECTION_BASE
|
||||
-- @field #DETECTION_AREAS
|
||||
DETECTION_AREAS = {
|
||||
ClassName = "DETECTION_AREAS",
|
||||
DetectionZoneRange = nil,
|
||||
@@ -2311,7 +2377,7 @@ do -- DETECTION_AREAS
|
||||
--- DETECTION_AREAS constructor.
|
||||
-- @param #DETECTION_AREAS self
|
||||
-- @param Core.Set#SET_GROUP DetectionSetGroup The @{Set} of GROUPs in the Forward Air Controller role.
|
||||
-- @param Dcs.DCSTypes#Distance DetectionZoneRange The range till which targets are grouped upon the first detected target.
|
||||
-- @param DCS#Distance DetectionZoneRange The range till which targets are grouped upon the first detected target.
|
||||
-- @return #DETECTION_AREAS
|
||||
function DETECTION_AREAS:New( DetectionSetGroup, DetectionZoneRange )
|
||||
|
||||
@@ -2357,6 +2423,7 @@ do -- DETECTION_AREAS
|
||||
Report:Add(DetectedItemID .. ", " .. DetectedItemCoordText)
|
||||
Report:Add( string.format( "Threat: [%s]", string.rep( "■", ThreatLevelA2G ), string.rep( "□", 10-ThreatLevelA2G ) ) )
|
||||
Report:Add( string.format("Type: %2d of %s", DetectedItemsCount, DetectedItemsTypes ) )
|
||||
Report:Add( string.format("Detected: %s", DetectedItem.IsDetected and "yes" or "no" ) )
|
||||
|
||||
return Report
|
||||
end
|
||||
@@ -2521,7 +2588,9 @@ do -- DETECTION_AREAS
|
||||
function DETECTION_AREAS:CreateDetectionItems()
|
||||
|
||||
|
||||
self:T2( "Checking Detected Items for new Detected Units ..." )
|
||||
self:F( "Checking Detected Items for new Detected Units ..." )
|
||||
--self:F( { DetectedObjects = self.DetectedObjects } )
|
||||
|
||||
-- First go through all detected sets, and check if there are new detected units, match all existing detected units and identify undetected units.
|
||||
-- Regroup when needed, split groups when needed.
|
||||
for DetectedItemID, DetectedItemData in pairs( self.DetectedItems ) do
|
||||
|
||||
@@ -2,61 +2,81 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @{#ESCORT} class
|
||||
-- ## Features:
|
||||
--
|
||||
-- * Escort navigation commands.
|
||||
-- * Escort hold at position commands.
|
||||
-- * Escorts reporting detected targets.
|
||||
-- * Escorts scanning targets in advance.
|
||||
-- * Escorts attacking specific targets.
|
||||
-- * Request assistance from other groups for attack.
|
||||
-- * Manage rule of engagement of escorts.
|
||||
-- * Manage the allowed evasion techniques of escorts.
|
||||
-- * Make escort to execute a defined mission or path.
|
||||
-- * Escort tactical situation reporting.
|
||||
--
|
||||
-- ===
|
||||
-- The @{#ESCORT} class allows you to interact with escorting AI on your flight and take the lead.
|
||||
--
|
||||
-- ## Missions:
|
||||
--
|
||||
-- [ESC - Escorting](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/ESC%20-%20Escorting)
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- Allows you to interact with escorting AI on your flight and take the lead.
|
||||
--
|
||||
-- Each escorting group can be commanded with a whole 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.
|
||||
-- Ships and Ground troops will have a more limited set, but they can provide support through the bombing of targets designated by the other escorts.
|
||||
--
|
||||
-- RADIO MENUs that can be created:
|
||||
-- ===
|
||||
-- # RADIO MENUs that can be created:
|
||||
--
|
||||
-- Find a summary below of the current available commands:
|
||||
--
|
||||
-- Navigation ...:
|
||||
-- ---------------
|
||||
-- ## Navigation ...:
|
||||
--
|
||||
-- Escort group navigation functions:
|
||||
--
|
||||
-- * **"Join-Up and Follow at x meters":** The escort group fill follow you at about x meters, and they will follow you.
|
||||
-- * **"Flare":** Provides menu commands to let the escort group shoot a flare in the air in a color.
|
||||
-- * **"Smoke":** Provides menu commands to let the escort group smoke the air in a color. Note that smoking is only available for ground and naval troops.
|
||||
--
|
||||
-- Hold position ...:
|
||||
-- ------------------
|
||||
-- ## Hold position ...:
|
||||
--
|
||||
-- Escort group navigation functions:
|
||||
--
|
||||
-- * **"At current location":** Stops the escort group and they will hover 30 meters above the ground at the position they stopped.
|
||||
-- * **"At client location":** Stops the escort group and they will hover 30 meters above the ground at the position they stopped.
|
||||
--
|
||||
-- Report targets ...:
|
||||
-- -------------------
|
||||
-- ## Report targets ...:
|
||||
--
|
||||
-- Report targets will make the escort group to report any target that it identifies within a 8km range. Any detected target can be attacked using the 4. Attack nearby targets function. (see below).
|
||||
--
|
||||
-- * **"Report now":** Will report the current detected targets.
|
||||
-- * **"Report targets on":** Will make the escort group to report detected targets and will fill the "Attack nearby targets" menu list.
|
||||
-- * **"Report targets off":** Will stop detecting targets.
|
||||
--
|
||||
-- Scan targets ...:
|
||||
-- -----------------
|
||||
-- ## Scan targets ...:
|
||||
--
|
||||
-- Menu items to pop-up the escort group for target scanning. After scanning, the escort group will resume with the mission or defined task.
|
||||
--
|
||||
-- * **"Scan targets 30 seconds":** Scan 30 seconds for targets.
|
||||
-- * **"Scan targets 60 seconds":** Scan 60 seconds for targets.
|
||||
--
|
||||
-- Attack targets ...:
|
||||
-- -------------------
|
||||
-- ## Attack targets ...:
|
||||
--
|
||||
-- This menu item will list all detected targets within a 15km range. Depending on the level of detection (known/unknown) and visuality, the targets type will also be listed.
|
||||
--
|
||||
-- Request assistance from ...:
|
||||
-- ----------------------------
|
||||
-- ## Request assistance from ...:
|
||||
--
|
||||
-- This menu item will list all detected targets within a 15km range, as with the menu item **Attack Targets**.
|
||||
-- This menu item allows to request attack support from other escorts supporting the current client group.
|
||||
-- eg. the function allows a player to request support from the Ship escort to attack a target identified by the Plane escort with its Tomahawk missiles.
|
||||
-- eg. the function allows a player to request support from other Planes escorting to bomb the unit with illumination missiles or bombs, so that the main plane escort can attack the area.
|
||||
--
|
||||
-- ROE ...:
|
||||
-- --------
|
||||
-- ## ROE ...:
|
||||
--
|
||||
-- Sets the Rules of Engagement (ROE) of the escort group when in flight.
|
||||
--
|
||||
-- * **"Hold Fire":** The escort group will hold fire.
|
||||
@@ -64,8 +84,8 @@
|
||||
-- * **"Open Fire":** The escort group will open fire on designated targets.
|
||||
-- * **"Weapon Free":** The escort group will engage with any target.
|
||||
--
|
||||
-- Evasion ...:
|
||||
-- ------------
|
||||
-- ## Evasion ...:
|
||||
--
|
||||
-- Will define the evasion techniques that the escort group will perform during flight or combat.
|
||||
--
|
||||
-- * **"Fight until death":** The escort group will have no reaction to threats.
|
||||
@@ -73,35 +93,43 @@
|
||||
-- * **"Evade enemy fire":** The rescort group will evade enemy fire before firing.
|
||||
-- * **"Go below radar and evade fire":** The escort group will perform evasive vertical manoeuvres.
|
||||
--
|
||||
-- Resume Mission ...:
|
||||
-- -------------------
|
||||
-- ## Resume Mission ...:
|
||||
--
|
||||
-- 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.
|
||||
--
|
||||
-- ESCORT construction methods.
|
||||
-- ===
|
||||
--
|
||||
-- ### Authors: **FlightControl**
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module Functional.Escort
|
||||
-- @image Escorting.JPG
|
||||
|
||||
|
||||
|
||||
--- @type ESCORT
|
||||
-- @extends Core.Base#BASE
|
||||
-- @field Wrapper.Client#CLIENT EscortClient
|
||||
-- @field Wrapper.Group#GROUP EscortGroup
|
||||
-- @field #string EscortName
|
||||
-- @field #ESCORT.MODE EscortMode The mode the escort is in.
|
||||
-- @field Core.Scheduler#SCHEDULER FollowScheduler The instance of the SCHEDULER class.
|
||||
-- @field #number FollowDistance The current follow distance.
|
||||
-- @field #boolean ReportTargets If true, nearby targets are reported.
|
||||
-- @Field DCS#AI.Option.Air.val.ROE OptionROE Which ROE is set to the EscortGroup.
|
||||
-- @field DCS#AI.Option.Air.val.REACTION_ON_THREAT OptionReactionOnThreat Which REACTION_ON_THREAT is set to the EscortGroup.
|
||||
-- @field FunctionalMENU_GROUPDETECTION_BASE Detection
|
||||
|
||||
--- ESCORT class
|
||||
--
|
||||
-- # ESCORT construction methods.
|
||||
--
|
||||
-- Create a new SPAWN object with the @{#ESCORT.New} method:
|
||||
--
|
||||
-- * @{#ESCORT.New}: Creates a new ESCORT object from a @{Group#GROUP} for a @{Client#CLIENT}, with an optional briefing text.
|
||||
-- * @{#ESCORT.New}: Creates a new ESCORT object from a @{Wrapper.Group#GROUP} for a @{Wrapper.Client#CLIENT}, with an optional briefing text.
|
||||
--
|
||||
-- ESCORT initialization methods.
|
||||
-- ===
|
||||
-- The following menus are created within the RADIO MENU (F10) of an active unit hosted by a player:
|
||||
--
|
||||
-- * @{#ESCORT.MenuFollowAt}: Creates a menu to make the escort follow the client.
|
||||
-- * @{#ESCORT.MenuHoldAtEscortPosition}: Creates a menu to hold the escort at its current position.
|
||||
-- * @{#ESCORT.MenuHoldAtLeaderPosition}: Creates a menu to hold the escort at the client position.
|
||||
-- * @{#ESCORT.MenuScanForTargets}: Creates a menu so that the escort scans targets.
|
||||
-- * @{#ESCORT.MenuFlare}: Creates a menu to disperse flares.
|
||||
-- * @{#ESCORT.MenuSmoke}: Creates a menu to disparse smoke.
|
||||
-- * @{#ESCORT.MenuReportTargets}: Creates a menu so that the escort reports targets.
|
||||
-- * @{#ESCORT.MenuReportPosition}: Creates a menu so that the escort reports its current position from bullseye.
|
||||
-- * @{#ESCORT.MenuAssistedAttack: Creates a menu so that the escort supportes assisted attack from other escorts with the client.
|
||||
-- * @{#ESCORT.MenuROE: Creates a menu structure to set the rules of engagement of the escort.
|
||||
-- * @{#ESCORT.MenuEvasion: Creates a menu structure to set the evasion techniques when the escort is under threat.
|
||||
-- * @{#ESCORT.MenuResumeMission}: Creates a menu structure so that the escort can resume from a waypoint.
|
||||
--
|
||||
--
|
||||
-- @usage
|
||||
-- -- Declare a new EscortPlanes object as follows:
|
||||
--
|
||||
@@ -111,25 +139,8 @@
|
||||
--
|
||||
-- -- Now use these 2 objects to construct the new EscortPlanes object.
|
||||
-- EscortPlanes = ESCORT:New( EscortClient, EscortGroup, "Desert", "Welcome to the mission. You are escorted by a plane with code name 'Desert', which can be instructed through the F10 radio menu." )
|
||||
--
|
||||
--
|
||||
--
|
||||
-- @module Escort
|
||||
-- @author FlightControl
|
||||
|
||||
--- ESCORT class
|
||||
-- @type ESCORT
|
||||
-- @extends Core.Base#BASE
|
||||
-- @field Wrapper.Client#CLIENT EscortClient
|
||||
-- @field Wrapper.Group#GROUP EscortGroup
|
||||
-- @field #string EscortName
|
||||
-- @field #ESCORT.MODE EscortMode The mode the escort is in.
|
||||
-- @field Core.Scheduler#SCHEDULER FollowScheduler The instance of the SCHEDULER class.
|
||||
-- @field #number FollowDistance The current follow distance.
|
||||
-- @field #boolean ReportTargets If true, nearby targets are reported.
|
||||
-- @Field Dcs.DCSTypes#AI.Option.Air.val.ROE OptionROE Which ROE is set to the EscortGroup.
|
||||
-- @field Dcs.DCSTypes#AI.Option.Air.val.REACTION_ON_THREAT OptionReactionOnThreat Which REACTION_ON_THREAT is set to the EscortGroup.
|
||||
-- @field FunctionalMENU_GROUPDETECTION_BASE Detection
|
||||
-- @field #ESCORT
|
||||
ESCORT = {
|
||||
ClassName = "ESCORT",
|
||||
EscortName = nil, -- The Escort Name
|
||||
@@ -295,7 +306,7 @@ end
|
||||
--- Defines a menu slot to let the escort Join and Follow you at a certain distance.
|
||||
-- This menu will appear under **Navigation**.
|
||||
-- @param #ESCORT self
|
||||
-- @param Dcs.DCSTypes#Distance Distance The distance in meters that the escort needs to follow the client.
|
||||
-- @param DCS#Distance Distance The distance in meters that the escort needs to follow the client.
|
||||
-- @return #ESCORT
|
||||
function ESCORT:MenuFollowAt( Distance )
|
||||
self:F(Distance)
|
||||
@@ -320,8 +331,8 @@ end
|
||||
--- Defines a menu slot to let the escort hold at their current position and stay low with a specified height during a specified time in seconds.
|
||||
-- This menu will appear under **Hold position**.
|
||||
-- @param #ESCORT self
|
||||
-- @param Dcs.DCSTypes#Distance Height Optional parameter that sets the height in meters to let the escort orbit at the current location. The default value is 30 meters.
|
||||
-- @param Dcs.DCSTypes#Time Seconds Optional parameter that lets the escort orbit at the current position for a specified time. (not implemented yet). The default value is 0 seconds, meaning, that the escort will orbit forever until a sequent command is given.
|
||||
-- @param DCS#Distance Height Optional parameter that sets the height in meters to let the escort orbit at the current location. The default value is 30 meters.
|
||||
-- @param DCS#Time Seconds Optional parameter that lets the escort orbit at the current position for a specified time. (not implemented yet). The default value is 0 seconds, meaning, that the escort will orbit forever until a sequent command is given.
|
||||
-- @param #string MenuTextFormat Optional parameter that shows the menu option text. The text string is formatted, and should contain two %d tokens in the string. The first for the Height, the second for the Time (if given). If no text is given, the default text will be displayed.
|
||||
-- @return #ESCORT
|
||||
-- TODO: Implement Seconds parameter. Challenge is to first develop the "continue from last activity" function.
|
||||
@@ -381,8 +392,8 @@ end
|
||||
--- Defines a menu slot to let the escort hold at the client position and stay low with a specified height during a specified time in seconds.
|
||||
-- This menu will appear under **Navigation**.
|
||||
-- @param #ESCORT self
|
||||
-- @param Dcs.DCSTypes#Distance Height Optional parameter that sets the height in meters to let the escort orbit at the current location. The default value is 30 meters.
|
||||
-- @param Dcs.DCSTypes#Time Seconds Optional parameter that lets the escort orbit at the current position for a specified time. (not implemented yet). The default value is 0 seconds, meaning, that the escort will orbit forever until a sequent command is given.
|
||||
-- @param DCS#Distance Height Optional parameter that sets the height in meters to let the escort orbit at the current location. The default value is 30 meters.
|
||||
-- @param DCS#Time Seconds Optional parameter that lets the escort orbit at the current position for a specified time. (not implemented yet). The default value is 0 seconds, meaning, that the escort will orbit forever until a sequent command is given.
|
||||
-- @param #string MenuTextFormat Optional parameter that shows the menu option text. The text string is formatted, and should contain one or two %d tokens in the string. The first for the Height, the second for the Time (if given). If no text is given, the default text will be displayed.
|
||||
-- @return #ESCORT
|
||||
-- TODO: Implement Seconds parameter. Challenge is to first develop the "continue from last activity" function.
|
||||
@@ -442,8 +453,8 @@ end
|
||||
--- Defines a menu slot to let the escort scan for targets at a certain height for a certain time in seconds.
|
||||
-- This menu will appear under **Scan targets**.
|
||||
-- @param #ESCORT self
|
||||
-- @param Dcs.DCSTypes#Distance Height Optional parameter that sets the height in meters to let the escort orbit at the current location. The default value is 30 meters.
|
||||
-- @param Dcs.DCSTypes#Time Seconds Optional parameter that lets the escort orbit at the current position for a specified time. (not implemented yet). The default value is 0 seconds, meaning, that the escort will orbit forever until a sequent command is given.
|
||||
-- @param DCS#Distance Height Optional parameter that sets the height in meters to let the escort orbit at the current location. The default value is 30 meters.
|
||||
-- @param DCS#Time Seconds Optional parameter that lets the escort orbit at the current position for a specified time. (not implemented yet). The default value is 0 seconds, meaning, that the escort will orbit forever until a sequent command is given.
|
||||
-- @param #string MenuTextFormat Optional parameter that shows the menu option text. The text string is formatted, and should contain one or two %d tokens in the string. The first for the Height, the second for the Time (if given). If no text is given, the default text will be displayed.
|
||||
-- @return #ESCORT
|
||||
function ESCORT:MenuScanForTargets( Height, Seconds, MenuTextFormat )
|
||||
@@ -567,7 +578,7 @@ end
|
||||
-- This menu will appear under **Report targets**.
|
||||
-- Note that if a report targets menu is not specified, no targets will be detected by the escort, and the attack and assisted attack menus will not be displayed.
|
||||
-- @param #ESCORT self
|
||||
-- @param Dcs.DCSTypes#Time Seconds Optional parameter that lets the escort report their current detected targets after specified time interval in seconds. The default time is 30 seconds.
|
||||
-- @param DCS#Time Seconds Optional parameter that lets the escort report their current detected targets after specified time interval in seconds. The default time is 30 seconds.
|
||||
-- @return #ESCORT
|
||||
function ESCORT:MenuReportTargets( Seconds )
|
||||
self:F( { Seconds } )
|
||||
@@ -737,7 +748,7 @@ end
|
||||
-- @param Functional.Escort#ESCORT self
|
||||
-- @param Wrapper.Group#GROUP EscortGroup
|
||||
-- @param Wrapper.Client#CLIENT EscortClient
|
||||
-- @param Dcs.DCSTypes#Distance Distance
|
||||
-- @param DCS#Distance Distance
|
||||
function ESCORT:JoinUpAndFollow( EscortGroup, EscortClient, Distance )
|
||||
self:F( { EscortGroup, EscortClient, Distance } )
|
||||
|
||||
|
||||
@@ -1,20 +1,27 @@
|
||||
--- **Functional** -- MISSILETRAINER helps you to train missile avoidance.
|
||||
--- **Functional** -- Train missile defence and deflection.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- 1) @{MissileTrainer#MISSILETRAINER} class, extends @{Base#BASE}
|
||||
-- ## Features:
|
||||
--
|
||||
-- * Track the missiles fired at you and other players, providing bearing and range information of the missiles towards the airplanes.
|
||||
-- * Provide alerts of missile launches, including detailed information of the units launching, including bearing, range <20>
|
||||
-- * Provide alerts when a missile would have killed your aircraft.
|
||||
-- * Provide alerts when the missile self destructs.
|
||||
-- * Enable / Disable and Configure the Missile Trainer using the various menu options.
|
||||
--
|
||||
-- ===
|
||||
-- The @{#MISSILETRAINER} class uses the DCS world messaging system to be alerted of any missiles fired, and when a missile would hit your aircraft,
|
||||
--
|
||||
-- ## Missions:
|
||||
--
|
||||
-- [MIT - Missile Trainer](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/MIT%20-%20Missile%20Trainer)
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- Uses the MOOSE messaging system to be alerted of any missiles fired, and when a missile would hit your aircraft,
|
||||
-- the class will destroy the missile within a certain range, to avoid damage to your aircraft.
|
||||
-- It suports the following functionality:
|
||||
--
|
||||
-- * Track the missiles fired at you and other players, providing bearing and range information of the missiles towards the airplanes.
|
||||
-- * Provide alerts of missile launches, including detailed information of the units launching, including bearing, range <20>
|
||||
-- * Provide alerts when a missile would have killed your aircraft.
|
||||
-- * Provide alerts when the missile self destructs.
|
||||
-- * Enable / Disable and Configure the Missile Trainer using the various menu options.
|
||||
--
|
||||
-- When running a mission where MISSILETRAINER is used, the following radio menu structure ( 'Radio Menu' -> 'Other (F10)' -> 'MissileTrainer' ) options are available for the players:
|
||||
-- When running a mission where the missile trainer is used, the following radio menu structure ( 'Radio Menu' -> 'Other (F10)' -> 'MissileTrainer' ) options are available for the players:
|
||||
--
|
||||
-- * **Messages**: Menu to configure all messages.
|
||||
-- * **Messages On**: Show all messages.
|
||||
@@ -44,17 +51,40 @@
|
||||
-- * **150 meter**: Destroys the missile when the distance to the aircraft is below or equal to 150 meter.
|
||||
-- * **200 meter**: Destroys the missile when the distance to the aircraft is below or equal to 200 meter.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Authors: **FlightControl**
|
||||
--
|
||||
-- ### Contributions:
|
||||
--
|
||||
-- * **Stuka (Danny)**: Who you can search on the Eagle Dynamics Forums. Working together with Danny has resulted in the MISSILETRAINER class.
|
||||
-- Danny has shared his ideas and together we made a design.
|
||||
-- Together with the **476 virtual team**, we tested the MISSILETRAINER class, and got much positive feedback!
|
||||
-- * **132nd Squadron**: Testing and optimizing the logic.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- 1.1) MISSILETRAINER construction methods:
|
||||
-- -----------------------------------------
|
||||
-- @module Functional.MissileTrainer
|
||||
-- @image Missile_Trainer.JPG
|
||||
|
||||
|
||||
--- @type MISSILETRAINER
|
||||
-- @field Core.Set#SET_CLIENT DBClients
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
|
||||
---
|
||||
--
|
||||
-- # Constructor:
|
||||
--
|
||||
-- Create a new MISSILETRAINER object with the @{#MISSILETRAINER.New} method:
|
||||
--
|
||||
-- * @{#MISSILETRAINER.New}: Creates a new MISSILETRAINER object taking the maximum distance to your aircraft to evaluate when a missile needs to be destroyed.
|
||||
--
|
||||
-- MISSILETRAINER will collect each unit declared in the mission with a skill level "Client" and "Player", and will monitor the missiles shot at those.
|
||||
--
|
||||
-- 1.2) MISSILETRAINER initialization methods:
|
||||
-- -------------------------------------------
|
||||
-- # Initialization:
|
||||
--
|
||||
-- A MISSILETRAINER object will behave differently based on the usage of initialization methods:
|
||||
--
|
||||
-- * @{#MISSILETRAINER.InitMessagesOnOff}: Sets by default the display of any message to be ON or OFF.
|
||||
@@ -67,24 +97,8 @@
|
||||
-- * @{#MISSILETRAINER.InitRangeOnOff}: Sets by default the display of range information of missiles ON of OFF.
|
||||
-- * @{#MISSILETRAINER.InitBearingOnOff}: Sets by default the display of bearing information of missiles ON of OFF.
|
||||
-- * @{#MISSILETRAINER.InitMenusOnOff}: Allows to configure the options through the radio menu.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- CREDITS
|
||||
-- ===
|
||||
-- **Stuka (Danny)** Who you can search on the Eagle Dynamics Forums.
|
||||
-- Working together with Danny has resulted in the MISSILETRAINER class.
|
||||
-- Danny has shared his ideas and together we made a design.
|
||||
-- Together with the **476 virtual team**, we tested the MISSILETRAINER class, and got much positive feedback!
|
||||
--
|
||||
-- @module MissileTrainer
|
||||
-- @author FlightControl
|
||||
|
||||
|
||||
--- The MISSILETRAINER class
|
||||
-- @type MISSILETRAINER
|
||||
-- @field Core.Set#SET_CLIENT DBClients
|
||||
-- @extends Core.Base#BASE
|
||||
-- @field #MISSILETRAINER
|
||||
MISSILETRAINER = {
|
||||
ClassName = "MISSILETRAINER",
|
||||
TrackingMissiles = {},
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
--- **Functional** -- Limit the MOVEMENT of simulaneous moving ground vehicles.
|
||||
--- **Functional** -- Limit the movement of simulaneous moving ground vehicles.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
@@ -7,11 +7,14 @@
|
||||
-- Performance: If in a DCSRTE there are a lot of moving GROUND units, then in a multi player mission, this WILL create lag if
|
||||
-- the main DCS execution core of your CPU is fully utilized. So, this class will limit the amount of simultaneous moving GROUND units
|
||||
-- on defined intervals (currently every minute).
|
||||
-- @module Movement
|
||||
-- @module Functional.Movement
|
||||
-- @image MOOSE.JPG
|
||||
|
||||
--- the MOVEMENT class
|
||||
-- @type MOVEMENT
|
||||
--- @type MOVEMENT
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
---
|
||||
--@field #MOVEMENT
|
||||
MOVEMENT = {
|
||||
ClassName = "MOVEMENT",
|
||||
}
|
||||
|
||||
@@ -1,305 +0,0 @@
|
||||
--- **Functional** -- The PROTECT class handles the protection of objects, which can be zones, units, scenery.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **FlightControl**
|
||||
-- ### Contributions: **MillerTime**
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module Protect
|
||||
|
||||
--- @type PROTECT.__ Methods which are not intended for mission designers, but which are used interally by the moose designer :-)
|
||||
-- @extends Core.Fsm#FSM
|
||||
|
||||
--- @type PROTECT
|
||||
-- @extends #PROTECT.__
|
||||
|
||||
--- # PROTECT, extends @{Base#BASE}
|
||||
--
|
||||
-- @field #PROTECT
|
||||
PROTECT = {
|
||||
ClassName = "PROTECT",
|
||||
}
|
||||
|
||||
--- Get the ProtectZone
|
||||
-- @param #PROTECT self
|
||||
-- @return Core.Zone#ZONE_BASE
|
||||
function PROTECT:GetProtectZone()
|
||||
return self.ProtectZone
|
||||
end
|
||||
|
||||
|
||||
--- Get the name of the ProtectZone
|
||||
-- @param #PROTECT self
|
||||
-- @return #string
|
||||
function PROTECT:GetProtectZoneName()
|
||||
return self.ProtectZone:GetName()
|
||||
end
|
||||
|
||||
|
||||
--- Set the owning coalition of the zone.
|
||||
-- @param #PROTECT self
|
||||
-- @param DCSCoalition.DCSCoalition#coalition Coalition
|
||||
function PROTECT:SetCoalition( Coalition )
|
||||
self.Coalition = Coalition
|
||||
end
|
||||
|
||||
|
||||
--- Get the owning coalition of the zone.
|
||||
-- @param #PROTECT self
|
||||
-- @return DCSCoalition.DCSCoalition#coalition Coalition.
|
||||
function PROTECT:GetCoalition()
|
||||
return self.Coalition
|
||||
end
|
||||
|
||||
|
||||
--- Get the owning coalition name of the zone.
|
||||
-- @param #PROTECT self
|
||||
-- @return #string Coalition name.
|
||||
function PROTECT:GetCoalitionName()
|
||||
|
||||
if self.Coalition == coalition.side.BLUE then
|
||||
return "Blue"
|
||||
end
|
||||
|
||||
if self.Coalition == coalition.side.RED then
|
||||
return "Red"
|
||||
end
|
||||
|
||||
if self.Coalition == coalition.side.NEUTRAL then
|
||||
return "Neutral"
|
||||
end
|
||||
|
||||
return ""
|
||||
end
|
||||
|
||||
|
||||
function PROTECT:IsGuarded()
|
||||
|
||||
local IsGuarded = self.ProtectZone:IsAllInZoneOfCoalition( self.Coalition )
|
||||
self:F( { IsGuarded = IsGuarded } )
|
||||
return IsGuarded
|
||||
end
|
||||
|
||||
function PROTECT:IsCaptured()
|
||||
|
||||
local IsCaptured = self.ProtectZone:IsAllInZoneOfOtherCoalition( self.Coalition )
|
||||
self:F( { IsCaptured = IsCaptured } )
|
||||
return IsCaptured
|
||||
end
|
||||
|
||||
|
||||
function PROTECT:IsAttacked()
|
||||
|
||||
local IsAttacked = self.ProtectZone:IsSomeInZoneOfCoalition( self.Coalition )
|
||||
self:F( { IsAttacked = IsAttacked } )
|
||||
return IsAttacked
|
||||
end
|
||||
|
||||
|
||||
function PROTECT:IsEmpty()
|
||||
|
||||
local IsEmpty = self.ProtectZone:IsNoneInZone()
|
||||
self:F( { IsEmpty = IsEmpty } )
|
||||
return IsEmpty
|
||||
end
|
||||
|
||||
|
||||
--- Check if the units are still alive.
|
||||
-- @param #PROTECT self
|
||||
function PROTECT:AreProtectUnitsAlive()
|
||||
|
||||
local IsAlive = false
|
||||
|
||||
local UnitSet = self.ProtectUnitSet
|
||||
UnitSet:Flush( self )
|
||||
local UnitList = UnitSet:GetSet()
|
||||
|
||||
for UnitID, ProtectUnit in pairs( UnitList ) do
|
||||
local IsUnitAlive = ProtectUnit:IsAlive()
|
||||
if IsUnitAlive == true then
|
||||
IsAlive = true
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
return IsAlive
|
||||
end
|
||||
|
||||
--- Check if the statics are still alive.
|
||||
-- @param #PROTECT self
|
||||
function PROTECT:AreProtectStaticsAlive()
|
||||
|
||||
local IsAlive = false
|
||||
|
||||
local StaticSet = self.ProtectStaticSet
|
||||
StaticSet:Flush( self )
|
||||
local StaticList = StaticSet:GetSet()
|
||||
|
||||
for UnitID, ProtectStatic in pairs( StaticList ) do
|
||||
local IsStaticAlive = ProtectStatic:IsAlive()
|
||||
if IsStaticAlive == true then
|
||||
IsAlive = true
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
return IsAlive
|
||||
end
|
||||
|
||||
|
||||
--- Check if there is a capture unit in the zone.
|
||||
-- @param #PROTECT self
|
||||
function PROTECT:IsCaptureUnitInZone()
|
||||
|
||||
local CaptureUnitSet = self.CaptureUnitSet
|
||||
CaptureUnitSet:Flush( self )
|
||||
|
||||
local IsInZone = self.CaptureUnitSet:IsPartiallyInZone( self.ProtectZone )
|
||||
|
||||
self:F({IsInZone = IsInZone})
|
||||
|
||||
return IsInZone
|
||||
end
|
||||
|
||||
--- Smoke.
|
||||
-- @param #PROTECT self
|
||||
-- @param #SMOKECOLOR.Color SmokeColor
|
||||
function PROTECT:Smoke( SmokeColor )
|
||||
|
||||
self.SmokeColor = SmokeColor
|
||||
end
|
||||
|
||||
|
||||
--- Flare.
|
||||
-- @param #PROTECT self
|
||||
-- @param #SMOKECOLOR.Color FlareColor
|
||||
function PROTECT:Flare( FlareColor )
|
||||
self.ProtectZone:FlareZone( FlareColor, math.random( 1, 360 ) )
|
||||
end
|
||||
|
||||
|
||||
--- Mark.
|
||||
-- @param #PROTECT self
|
||||
function PROTECT:Mark()
|
||||
|
||||
local Coord = self.ProtectZone:GetCoordinate()
|
||||
local ZoneName = self:GetProtectZoneName()
|
||||
local State = self:GetState()
|
||||
|
||||
if self.MarkRed and self.MarkBlue then
|
||||
self:F( { MarkRed = self.MarkRed, MarkBlue = self.MarkBlue } )
|
||||
Coord:RemoveMark( self.MarkRed )
|
||||
Coord:RemoveMark( self.MarkBlue )
|
||||
end
|
||||
|
||||
if self.Coalition == coalition.side.BLUE then
|
||||
self.MarkBlue = Coord:MarkToCoalitionBlue( "Guard Zone: " .. ZoneName .. "\nStatus: " .. State )
|
||||
self.MarkRed = Coord:MarkToCoalitionRed( "Capture Zone: " .. ZoneName .. "\nStatus: " .. State )
|
||||
else
|
||||
self.MarkRed = Coord:MarkToCoalitionRed( "Guard Zone: " .. ZoneName .. "\nStatus: " .. State )
|
||||
self.MarkBlue = Coord:MarkToCoalitionBlue( "Capture Zone: " .. ZoneName .. "\nStatus: " .. State )
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--- Bound.
|
||||
-- @param #PROTECT self
|
||||
function PROTECT:onafterStart()
|
||||
|
||||
self:ScheduleRepeat( 5, 15, 0.1, nil, self.StatusCoalition, self )
|
||||
self:ScheduleRepeat( 5, 15, 0.1, nil, self.StatusZone, self )
|
||||
self:ScheduleRepeat( 10, 15, 0, nil, self.StatusSmoke, self )
|
||||
end
|
||||
|
||||
--- Bound.
|
||||
-- @param #PROTECT self
|
||||
function PROTECT:onenterGuarded()
|
||||
|
||||
|
||||
if self.Coalition == coalition.side.BLUE then
|
||||
--elf.ProtectZone:BoundZone( 12, country.id.USA )
|
||||
else
|
||||
--self.ProtectZone:BoundZone( 12, country.id.RUSSIA )
|
||||
end
|
||||
|
||||
self:Mark()
|
||||
|
||||
end
|
||||
|
||||
function PROTECT:onenterCaptured()
|
||||
|
||||
local NewCoalition = self.ProtectZone:GetCoalition()
|
||||
self:F( { NewCoalition = NewCoalition } )
|
||||
self:SetCoalition( NewCoalition )
|
||||
|
||||
self:Mark()
|
||||
end
|
||||
|
||||
|
||||
function PROTECT:onenterEmpty()
|
||||
|
||||
self:Mark()
|
||||
end
|
||||
|
||||
|
||||
function PROTECT:onenterAttacked()
|
||||
|
||||
self:Mark()
|
||||
end
|
||||
|
||||
|
||||
--- Check status Coalition ownership.
|
||||
-- @param #PROTECT self
|
||||
function PROTECT:StatusCoalition()
|
||||
|
||||
self:F( { State = self:GetState() } )
|
||||
|
||||
self.ProtectZone:Scan()
|
||||
|
||||
if self:IsGuarded() then
|
||||
self:Guard()
|
||||
else
|
||||
if self:IsCaptured() then
|
||||
self:Capture()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Check status Zone.
|
||||
-- @param #PROTECT self
|
||||
function PROTECT:StatusZone()
|
||||
|
||||
self:F( { State = self:GetState() } )
|
||||
|
||||
self.ProtectZone:Scan()
|
||||
|
||||
if self:IsAttacked() then
|
||||
self:Attack()
|
||||
else
|
||||
if self:IsEmpty() then
|
||||
self:Empty()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Check status Smoke.
|
||||
-- @param #PROTECT self
|
||||
function PROTECT:StatusSmoke()
|
||||
|
||||
local CurrentTime = timer.getTime()
|
||||
|
||||
if self.SmokeTime == nil or self.SmokeTime + 300 <= CurrentTime then
|
||||
if self.SmokeColor then
|
||||
self.ProtectZone:GetCoordinate():Smoke( self.SmokeColor )
|
||||
--self.SmokeColor = nil
|
||||
self.SmokeTime = CurrentTime
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
--- **Functional** - (R2.4) Rudimentary ATC.
|
||||
--- **Functional** - Rudimentary ATC.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
@@ -9,7 +8,7 @@
|
||||
--
|
||||
-- In particular, a menu entry "Pseudo ATC" is created in the "F10 Other..." radiomenu.
|
||||
--
|
||||
-- ## Features
|
||||
-- ## Features:
|
||||
--
|
||||
-- * Weather report at nearby airbases and mission waypoints.
|
||||
-- * Report absolute bearing and range to nearest airports and mission waypoints.
|
||||
@@ -21,12 +20,6 @@
|
||||
--
|
||||
-- ====
|
||||
--
|
||||
-- # Demo Missions
|
||||
--
|
||||
-- ### [MOOSE - ALL Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS)
|
||||
--
|
||||
-- ====
|
||||
--
|
||||
-- # YouTube Channel
|
||||
--
|
||||
-- ### [MOOSE YouTube Channel](https://www.youtube.com/channel/UCjrA9j5LQoWsG4SpS8i79Qg)
|
||||
@@ -38,7 +31,8 @@
|
||||
-- ### Contributions: [FlightControl](https://forums.eagle.ru/member.php?u=89536)
|
||||
--
|
||||
-- ====
|
||||
-- @module PseudoATC
|
||||
-- @module Functional.PseudoATC
|
||||
-- @image Pseudo_ATC.JPG
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
--- PSEUDOATC class
|
||||
@@ -53,8 +47,7 @@
|
||||
-- @field #boolean eventsmoose If true, events are handled by MOOSE. If false, events are handled directly by DCS eventhandler.
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
---# PSEUDOATC class, extends @{Base#BASE}
|
||||
-- The PSEUDOATC class adds some rudimentary ATC functionality via the radio menu.
|
||||
--- Adds some rudimentary ATC functionality via the radio menu.
|
||||
--
|
||||
-- Local weather reports can be requested for nearby airports and player's mission waypoints.
|
||||
-- The weather report includes
|
||||
@@ -987,7 +980,7 @@ function PSEUDOATC:_DisplayMessageToGroup(_unit, _text, _time, _clear)
|
||||
end
|
||||
|
||||
--- Returns a string which consits of this callsign and the player name.
|
||||
-- @param #RANGE self
|
||||
-- @param #PSEUDOATC self
|
||||
-- @param #string unitname Name of the player unit.
|
||||
function PSEUDOATC:_myname(unitname)
|
||||
self:F2(unitname)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,12 +1,7 @@
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
--- **Functional** - (R2.3) - Range Practice.
|
||||
--- **Functional** - Range Practice.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- The RANGE class enables easy set up of bombing and strafing ranges within DCS World.
|
||||
--
|
||||
-- Implementation is based on the [Simple Range Script](https://forums.eagle.ru/showthread.php?t=157991) by [Ciribob](https://forums.eagle.ru/member.php?u=112175), which itself was motivated
|
||||
@@ -14,30 +9,22 @@
|
||||
--
|
||||
-- [476th - Air Weapons Range Objects mod](http://www.476vfightergroup.com/downloads.php?do=file&id=287) is highly recommended for this class.
|
||||
--
|
||||
-- ## Features
|
||||
-- ## Features:
|
||||
--
|
||||
-- * Impact points of bombs, rockets and missils are recorded and distance to closest range target is measured and reported to the player.
|
||||
-- * Number of hits on strafing passes are counted and reported. Also the percentage of hits w.r.t fired shots is evaluated.
|
||||
-- * Results of all bombing and strafing runs are stored and top 10 results can be displayed.
|
||||
-- * Range targets can be marked by smoke.
|
||||
-- * Range can be illuminated by illumination bombs for night practices.
|
||||
-- * Bomb, rocket and missile impact points can be marked by smoke.
|
||||
-- * Direct hits on targets can trigger flares.
|
||||
-- * Smoke and flare colors can be adjusted for each player via radio menu.
|
||||
-- * Range information and weather report at the range can be reported via radio menu.
|
||||
-- * Impact points of bombs, rockets and missils are recorded and distance to closest range target is measured and reported to the player.
|
||||
-- * Number of hits on strafing passes are counted and reported. Also the percentage of hits w.r.t fired shots is evaluated.
|
||||
-- * Results of all bombing and strafing runs are stored and top 10 results can be displayed.
|
||||
-- * Range targets can be marked by smoke.
|
||||
-- * Range can be illuminated by illumination bombs for night practices.
|
||||
-- * Bomb, rocket and missile impact points can be marked by smoke.
|
||||
-- * Direct hits on targets can trigger flares.
|
||||
-- * Smoke and flare colors can be adjusted for each player via radio menu.
|
||||
-- * Range information and weather report at the range can be reported via radio menu.
|
||||
--
|
||||
-- More information and examples can be found below.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- # Demo Missions
|
||||
--
|
||||
-- ### [MOOSE - ALL Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS)
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- # YouTube Channel
|
||||
--
|
||||
-- ### [MOOSE YouTube Channel](https://www.youtube.com/channel/UCjrA9j5LQoWsG4SpS8i79Qg)
|
||||
-- ### [MOOSE - On the Range - Demonstration Video](https://www.youtube.com/watch?v=kIXcxNB9_3M)
|
||||
--
|
||||
@@ -48,7 +35,8 @@
|
||||
-- ### Contributions: [FlightControl](https://forums.eagle.ru/member.php?u=89536), [Ciribob](https://forums.eagle.ru/member.php?u=112175)
|
||||
--
|
||||
-- ===
|
||||
-- @module Range
|
||||
-- @module Functional.Range
|
||||
-- @image Range.JPG
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
--- RANGE class
|
||||
@@ -70,7 +58,10 @@
|
||||
-- @field #table bombPlayerResults Table containing the bombing results of each player.
|
||||
-- @field #table PlayerSettings Indiviual player settings.
|
||||
-- @field #number dtBombtrack Time step [sec] used for tracking released bomb/rocket positions. Default 0.005 seconds.
|
||||
-- @field #number BombtrackThreshold Bombs/rockets/missiles are only tracked if player-range distance is smaller than this threashold [m]. Default 25000 m.
|
||||
-- @field #number Tmsg Time [sec] messages to players are displayed. Default 30 sec.
|
||||
-- @field #string examinergroupname Name of the examiner group which should get all messages.
|
||||
-- @field #boolean examinerexclusive If true, only the examiner gets messages. If false, clients and examiner get messages.
|
||||
-- @field #number strafemaxalt Maximum altitude above ground for registering for a strafe run. Default is 914 m = 3000 ft.
|
||||
-- @field #number ndisplayresult Number of (player) results that a displayed. Default is 10.
|
||||
-- @field Utilities.Utils#SMOKECOLOR BombSmokeColor Color id used for smoking bomb targets.
|
||||
@@ -86,8 +77,7 @@
|
||||
-- @field #boolean trackmissiles If true (default), all missile types are tracked and impact point to closest bombing target is evaluated.
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
---# RANGE class, extends @{Base#BASE}
|
||||
-- The RANGE class enables a mission designer to easily set up practice ranges in DCS. A new RANGE object can be created with the @{#RANGE.New}(rangename) contructor.
|
||||
--- Enables a mission designer to easily set up practice ranges in DCS. A new RANGE object can be created with the @{#RANGE.New}(rangename) contructor.
|
||||
-- The parameter "rangename" defindes the name of the range. It has to be unique since this is also the name displayed in the radio menu.
|
||||
--
|
||||
-- Generally, a range consists of strafe pits and bombing targets. For strafe pits the number of hits for each pass is counted and tabulated.
|
||||
@@ -106,9 +96,9 @@
|
||||
-- ## Strafe Pits
|
||||
-- Each strafe pit can consist of multiple targets. Often one findes two or three strafe targets next to each other.
|
||||
--
|
||||
-- A strafe pit can be added to the range by the @{#RANGE.AddStrafepit}(*targetnames, boxlength, boxwidth, heading, inverseheading, goodpass, foulline*) function.
|
||||
-- A strafe pit can be added to the range by the @{#RANGE.AddStrafePit}(*targetnames, boxlength, boxwidth, heading, inverseheading, goodpass, foulline*) function.
|
||||
--
|
||||
-- * The first parameter *targetnames* defines the target or targets. This has to be given as a lua table which contains the names of @{Unit} or @{Static} objects defined in the mission editor.
|
||||
-- * The first parameter *targetnames* defines the target or targets. This has to be given as a lua table which contains the names of @{Wrapper.Unit} or @{Static} objects defined in the mission editor.
|
||||
-- * In order to perform a valid pass on the strafe pit, the pilot has to begin his run from the correct direction. Therefore, an "approach box" is defined in front
|
||||
-- of the strafe targets. The parameters *boxlength* and *boxwidth* define the size of the box while the parameter *heading* defines its direction.
|
||||
-- If the parameter *heading* is passed as **nil**, the heading is automatically taken from the heading of the first target unit as defined in the ME.
|
||||
@@ -118,7 +108,7 @@
|
||||
-- * The last parameter *foulline* sets the distance from the pit targets to the foul line. Hit from closer than this line are not counted!
|
||||
--
|
||||
-- Another function to add a strafe pit is @{#RANGE.AddStrafePitGroup}(*group, boxlength, boxwidth, heading, inverseheading, goodpass, foulline*). Here,
|
||||
-- the first parameter *group* is a MOOSE @{Group} object and **all** units in this group define **one** strafe pit.
|
||||
-- the first parameter *group* is a MOOSE @{Wrapper.Group} object and **all** units in this group define **one** strafe pit.
|
||||
--
|
||||
-- Finally, a valid approach has to be performed below a certain maximum altitude. The default is 914 meters (3000 ft) AGL. This is a parameter valid for all
|
||||
-- strafing pits of the range and can be adjusted by the @{#RANGE.SetMaxStrafeAlt}(maxalt) function.
|
||||
@@ -126,13 +116,13 @@
|
||||
-- ## Bombing targets
|
||||
-- One ore multiple bombing targets can be added to the range by the @{#RANGE.AddBombingTargets}(targetnames, goodhitrange, randommove) function.
|
||||
--
|
||||
-- * The first parameter *targetnames* has to be a lua table, which contains the names of @{Unit} and/or @{Static} objects defined in the mission editor.
|
||||
-- Note that the @{Range} logic **automatically** determines, if a name belongs to a @{Unit} or @{Static} object now.
|
||||
-- * The first parameter *targetnames* has to be a lua table, which contains the names of @{Wrapper.Unit} and/or @{Static} objects defined in the mission editor.
|
||||
-- Note that the @{Range} logic **automatically** determines, if a name belongs to a @{Wrapper.Unit} or @{Static} object now.
|
||||
-- * The (optional) parameter *goodhitrange* specifies the radius around the target. If a bomb or rocket falls at a distance smaller than this number, the hit is considered to be "good".
|
||||
-- * If final (optional) parameter "*randommove*" can be enabled to create moving targets. If this parameter is set to true, the units of this bombing target will randomly move within the range zone.
|
||||
-- Note that there might be quirks since DCS units can get stuck in buildings etc. So it might be safer to manually define a route for the units in the mission editor if moving targets are desired.
|
||||
--
|
||||
-- Another possibility to add bombing targets is the @{#RANGE.AddBombingTargetGroup}(*group, goodhitrange, randommove*) function. Here the parameter *group* is a MOOSE @{Group} object
|
||||
-- Another possibility to add bombing targets is the @{#RANGE.AddBombingTargetGroup}(*group, goodhitrange, randommove*) function. Here the parameter *group* is a MOOSE @{Wrapper.Group} object
|
||||
-- and **all** units in this group are defined as bombing targets.
|
||||
--
|
||||
-- ## Fine Tuning
|
||||
@@ -236,7 +226,10 @@ RANGE={
|
||||
bombPlayerResults = {},
|
||||
PlayerSettings = {},
|
||||
dtBombtrack=0.005,
|
||||
BombtrackThreshold=25000,
|
||||
Tmsg=30,
|
||||
examinergroupname=nil,
|
||||
examinerexclusive=nil,
|
||||
strafemaxalt=914,
|
||||
ndisplayresult=10,
|
||||
BombSmokeColor=SMOKECOLOR.Red,
|
||||
@@ -282,8 +275,8 @@ RANGE.MenuF10={}
|
||||
RANGE.id="RANGE | "
|
||||
|
||||
--- Range script version.
|
||||
-- @field #number version
|
||||
RANGE.version="1.1.1"
|
||||
-- @field #string version
|
||||
RANGE.version="1.2.1"
|
||||
|
||||
--TODO list:
|
||||
--TODO: Add custom weapons, which can be specified by the user.
|
||||
@@ -314,7 +307,7 @@ function RANGE:New(rangename)
|
||||
self.rangename=rangename or "Practice Range"
|
||||
|
||||
-- Debug info.
|
||||
local text=string.format("RANGE script version %s. Creating new RANGE object. Range name: %s.", RANGE.version, self.rangename)
|
||||
local text=string.format("RANGE script version %s - creating new RANGE object of name: %s.", RANGE.version, self.rangename)
|
||||
self:E(RANGE.id..text)
|
||||
MESSAGE:New(text, 10):ToAllIf(self.Debug)
|
||||
|
||||
@@ -437,6 +430,15 @@ function RANGE:SetMessageTimeDuration(time)
|
||||
self.Tmsg=time or RANGE.Defaults.Tmsg
|
||||
end
|
||||
|
||||
--- Set messages to examiner. The examiner will receive messages from all clients.
|
||||
-- @param #RANGE self
|
||||
-- @param #string examinergroupname Name of the group of the examiner.
|
||||
-- @param #boolean exclusively If true, messages are send exclusively to the examiner, i.e. not to the clients.
|
||||
function RANGE:SetMessageToExaminer(examinergroupname, exclusively)
|
||||
self.examinergroupname=examinergroupname
|
||||
self.examinerexclusive=exclusively
|
||||
end
|
||||
|
||||
--- Set max number of player results that are displayed.
|
||||
-- @param #RANGE self
|
||||
-- @param #number nmax Number of results. Default is 10.
|
||||
@@ -451,6 +453,13 @@ function RANGE:SetRangeRadius(radius)
|
||||
self.rangeradius=radius*1000 or RANGE.Defaults.rangeradius
|
||||
end
|
||||
|
||||
--- Set bomb track threshold distance. Bombs/rockets/missiles are only tracked if player-range distance is less than this distance. Default 25 km.
|
||||
-- @param #RANGE self
|
||||
-- @param #number distance Threshold distance in km. Default 25 km.
|
||||
function RANGE:SetBombtrackThreshold(distance)
|
||||
self.BombtrackThreshold=distance*1000 or 25*1000
|
||||
end
|
||||
|
||||
--- Set range location. If this is not done, one (random) unit position of the range is used to determine the center of the range.
|
||||
-- @param #RANGE self
|
||||
-- @param Core.Point#COORDINATE coordinate Coordinate of the center of the range.
|
||||
@@ -1081,6 +1090,7 @@ function RANGE:OnEventShot(EventData)
|
||||
local _weaponName = _weaponStrArray[#_weaponStrArray]
|
||||
|
||||
-- Debug info.
|
||||
self:T(RANGE.id.."EVENT SHOT: Range "..self.rangename)
|
||||
self:T(RANGE.id.."EVENT SHOT: Ini unit = "..EventData.IniUnitName)
|
||||
self:T(RANGE.id.."EVENT SHOT: Ini group = "..EventData.IniGroupName)
|
||||
self:T(RANGE.id.."EVENT SHOT: Weapon type = ".._weapon)
|
||||
@@ -1097,129 +1107,141 @@ function RANGE:OnEventShot(EventData)
|
||||
-- Check if any condition applies here.
|
||||
local _track = (_bombs and self.trackbombs) or (_rockets and self.trackrockets) or (_missiles and self.trackmissiles)
|
||||
|
||||
if _track then
|
||||
-- Get unit name.
|
||||
local _unitName = EventData.IniUnitName
|
||||
|
||||
-- Get player unit and name.
|
||||
local _unit, _playername = self:_GetPlayerUnitAndName(_unitName)
|
||||
|
||||
-- Weapon
|
||||
local _ordnance = EventData.weapon
|
||||
-- Set this to larger value than the threshold.
|
||||
local dPR=self.BombtrackThreshold*2
|
||||
|
||||
-- Distance player to range.
|
||||
if _unit and _playername then
|
||||
dPR=_unit:GetCoordinate():Get2DDistance(self.location)
|
||||
self:T(RANGE.id..string.format("Range %s, player %s, player-range distance = %d km.", self.rangename, _playername, dPR/1000))
|
||||
end
|
||||
|
||||
-- Only track if distance player to range is < 25 km.
|
||||
if _track and dPR<=self.BombtrackThreshold then
|
||||
|
||||
-- Tracking info and init of last bomb position.
|
||||
self:T(RANGE.id..string.format("Tracking %s - %s.", _weapon, _ordnance:getName()))
|
||||
self:T(RANGE.id..string.format("RANGE %s: Tracking %s - %s.", self.rangename, _weapon, EventData.weapon:getName()))
|
||||
|
||||
-- Init bomb position.
|
||||
local _lastBombPos = {x=0,y=0,z=0}
|
||||
|
||||
-- Get unit name.
|
||||
local _unitName = EventData.IniUnitName
|
||||
|
||||
-- Function monitoring the position of a bomb until impact.
|
||||
local function trackBomb(_previousPos)
|
||||
local function trackBomb(_ordnance)
|
||||
|
||||
-- When the pcall returns a failure the weapon has hit.
|
||||
local _status,_bombPos = pcall(
|
||||
function()
|
||||
return _ordnance:getPoint()
|
||||
end)
|
||||
|
||||
self:T3(RANGE.id..string.format("Range %s: Bomb still in air: %s", self.rangename, tostring(_status)))
|
||||
if _status then
|
||||
|
||||
-- Get player unit and name.
|
||||
local _unit, _playername = self:_GetPlayerUnitAndName(_unitName)
|
||||
local _callsign=self:_myname(_unitName)
|
||||
-- Still in the air. Remember this position.
|
||||
_lastBombPos = {x = _bombPos.x, y = _bombPos.y, z= _bombPos.z }
|
||||
|
||||
if _unit and _playername then
|
||||
|
||||
-- When the pcall returns a failure the weapon has hit.
|
||||
local _status,_bombPos = pcall(
|
||||
function()
|
||||
return _ordnance:getPoint()
|
||||
end)
|
||||
|
||||
if _status then
|
||||
-- Check again in 0.005 seconds.
|
||||
return timer.getTime() + self.dtBombtrack
|
||||
|
||||
-- Still in the air. Remember this position.
|
||||
_lastBombPos = {x = _bombPos.x, y = _bombPos.y, z= _bombPos.z }
|
||||
|
||||
-- Check again in 0.005 seconds.
|
||||
return timer.getTime() + self.dtBombtrack
|
||||
|
||||
else
|
||||
else
|
||||
|
||||
-- Bomb did hit the ground.
|
||||
-- Get closet target to last position.
|
||||
local _closetTarget = nil
|
||||
local _distance = nil
|
||||
local _hitquality = "POOR"
|
||||
|
||||
-- Bomb did hit the ground.
|
||||
-- Get closet target to last position.
|
||||
local _closetTarget = nil
|
||||
local _distance = nil
|
||||
local _hitquality = "POOR"
|
||||
|
||||
-- Coordinate of impact point.
|
||||
local impactcoord=COORDINATE:NewFromVec3(_lastBombPos)
|
||||
|
||||
-- Distance from range. We dont want to smoke targets outside of the range.
|
||||
local impactdist=impactcoord:Get2DDistance(self.location)
|
||||
|
||||
-- Smoke impact point of bomb.
|
||||
if self.PlayerSettings[_playername].smokebombimpact and impactdist<self.rangeradius then
|
||||
if self.PlayerSettings[_playername].delaysmoke then
|
||||
timer.scheduleFunction(self._DelayedSmoke, {coord=impactcoord, color=self.PlayerSettings[_playername].smokecolor}, timer.getTime() + self.TdelaySmoke)
|
||||
else
|
||||
impactcoord:Smoke(self.PlayerSettings[_playername].smokecolor)
|
||||
end
|
||||
-- Get callsign.
|
||||
local _callsign=self:_myname(_unitName)
|
||||
|
||||
-- Coordinate of impact point.
|
||||
local impactcoord=COORDINATE:NewFromVec3(_lastBombPos)
|
||||
|
||||
-- Distance from range. We dont want to smoke targets outside of the range.
|
||||
local impactdist=impactcoord:Get2DDistance(self.location)
|
||||
|
||||
-- Smoke impact point of bomb.
|
||||
if self.PlayerSettings[_playername].smokebombimpact and impactdist<self.rangeradius then
|
||||
if self.PlayerSettings[_playername].delaysmoke then
|
||||
timer.scheduleFunction(self._DelayedSmoke, {coord=impactcoord, color=self.PlayerSettings[_playername].smokecolor}, timer.getTime() + self.TdelaySmoke)
|
||||
else
|
||||
impactcoord:Smoke(self.PlayerSettings[_playername].smokecolor)
|
||||
end
|
||||
|
||||
-- Loop over defined bombing targets.
|
||||
for _,_bombtarget in pairs(self.bombingTargets) do
|
||||
end
|
||||
|
||||
-- Loop over defined bombing targets.
|
||||
for _,_bombtarget in pairs(self.bombingTargets) do
|
||||
|
||||
local _target=_bombtarget.target --Wrapper.Positionable#POSITIONABLE
|
||||
|
||||
if _target and _target:IsAlive() then
|
||||
|
||||
-- Distance between bomb and target.
|
||||
local _temp = impactcoord:Get2DDistance(_target:GetCoordinate())
|
||||
|
||||
local _target=_bombtarget.target --Wrapper.Positionable#POSITIONABLE
|
||||
|
||||
if _target and _target:IsAlive() then
|
||||
|
||||
-- Distance between bomb and target.
|
||||
local _temp = impactcoord:Get2DDistance(_target:GetCoordinate())
|
||||
|
||||
-- Find closest target to last known position of the bomb.
|
||||
if _distance == nil or _temp < _distance then
|
||||
_distance = _temp
|
||||
_closetTarget = _bombtarget
|
||||
if _distance <= 0.5*_bombtarget.goodhitrange then
|
||||
_hitquality = "EXCELLENT"
|
||||
elseif _distance <= _bombtarget.goodhitrange then
|
||||
_hitquality = "GOOD"
|
||||
elseif _distance <= 2*_bombtarget.goodhitrange then
|
||||
_hitquality = "INEFFECTIVE"
|
||||
else
|
||||
_hitquality = "POOR"
|
||||
end
|
||||
|
||||
-- Find closest target to last known position of the bomb.
|
||||
if _distance == nil or _temp < _distance then
|
||||
_distance = _temp
|
||||
_closetTarget = _bombtarget
|
||||
if _distance <= 0.5*_bombtarget.goodhitrange then
|
||||
_hitquality = "EXCELLENT"
|
||||
elseif _distance <= _bombtarget.goodhitrange then
|
||||
_hitquality = "GOOD"
|
||||
elseif _distance <= 2*_bombtarget.goodhitrange then
|
||||
_hitquality = "INEFFECTIVE"
|
||||
else
|
||||
_hitquality = "POOR"
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Count if bomb fell less than 1 km away from the target.
|
||||
if _distance <= self.scorebombdistance then
|
||||
|
||||
-- Init bomb player results.
|
||||
if not self.bombPlayerResults[_playername] then
|
||||
self.bombPlayerResults[_playername] = {}
|
||||
end
|
||||
|
||||
-- Local results.
|
||||
local _results = self.bombPlayerResults[_playername]
|
||||
|
||||
-- Add to table.
|
||||
table.insert(_results, {name=_closetTarget.name, distance =_distance, weapon = _weaponName, quality=_hitquality })
|
||||
-- Count if bomb fell less than 1 km away from the target.
|
||||
if _distance <= self.scorebombdistance then
|
||||
|
||||
-- Send message to player.
|
||||
local _message = string.format("%s, impact %d m from bullseye of target %s. %s hit.", _callsign, _distance, _closetTarget.name, _hitquality)
|
||||
|
||||
-- Send message.
|
||||
self:_DisplayMessageToGroup(_unit, _message, nil, true)
|
||||
elseif _distance <= self.rangeradius then
|
||||
-- Send message
|
||||
local _message=string.format("%s, weapon fell more than %.1f km away from nearest range target. No score!", _callsign, self.scorebombdistance/1000)
|
||||
self:_DisplayMessageToGroup(_unit, _message, nil, true)
|
||||
-- Init bomb player results.
|
||||
if not self.bombPlayerResults[_playername] then
|
||||
self.bombPlayerResults[_playername] = {}
|
||||
end
|
||||
|
||||
end -- _status
|
||||
|
||||
-- Local results.
|
||||
local _results = self.bombPlayerResults[_playername]
|
||||
|
||||
end -- end unit ~= nil
|
||||
|
||||
return nil --Terminate the timer
|
||||
end -- end function bombtrack
|
||||
-- Add to table.
|
||||
table.insert(_results, {name=_closetTarget.name, distance =_distance, weapon = _weaponName, quality=_hitquality })
|
||||
|
||||
timer.scheduleFunction(trackBomb, nil, timer.getTime() + 1)
|
||||
-- Send message to player.
|
||||
local _message = string.format("%s, impact %d m from bullseye of target %s. %s hit.", _callsign, _distance, _closetTarget.name, _hitquality)
|
||||
|
||||
-- Send message.
|
||||
self:_DisplayMessageToGroup(_unit, _message, nil, true)
|
||||
elseif _distance <= self.rangeradius then
|
||||
-- Send message
|
||||
local _message=string.format("%s, weapon fell more than %.1f km away from nearest range target. No score!", _callsign, self.scorebombdistance/1000)
|
||||
self:_DisplayMessageToGroup(_unit, _message, nil, true)
|
||||
end
|
||||
|
||||
--Terminate the timer
|
||||
self:T(RANGE.id..string.format("Range %s, player %s: Terminating bomb track timer.", self.rangename, _playername))
|
||||
return nil
|
||||
|
||||
end -- _status check
|
||||
|
||||
end -- end function trackBomb
|
||||
|
||||
-- Weapon is not yet "alife" just yet. Start timer in one second.
|
||||
self:T(RANGE.id..string.format("Range %s, player %s: Tracking of weapon starts in one second.", self.rangename, _playername))
|
||||
timer.scheduleFunction(trackBomb, EventData.weapon, timer.getTime() + 1.0)
|
||||
|
||||
end --if string.match
|
||||
end --if _track (string.match) and player-range distance < threshold.
|
||||
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -2102,13 +2124,24 @@ function RANGE:_DisplayMessageToGroup(_unit, _text, _time, _clear)
|
||||
-- Group ID.
|
||||
local _gid=_unit:GetGroup():GetID()
|
||||
|
||||
if _gid then
|
||||
if _gid and not self.examinerexclusive then
|
||||
if _clear == true then
|
||||
trigger.action.outTextForGroup(_gid, _text, _time, _clear)
|
||||
else
|
||||
trigger.action.outTextForGroup(_gid, _text, _time)
|
||||
end
|
||||
end
|
||||
|
||||
if self.examinergroupname~=nil then
|
||||
local _examinerid=GROUP:FindByName(self.examinergroupname):GetID()
|
||||
if _examinerid then
|
||||
if _clear == true then
|
||||
trigger.action.outTextForGroup(_examinerid, _text, _time, _clear)
|
||||
else
|
||||
trigger.action.outTextForGroup(_examinerid, _text, _time)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
@@ -1,16 +1,33 @@
|
||||
--- **Functional** -- (R2.0) - Administer the scoring of player achievements, and create a CSV file logging the scoring events for use at team or squadron websites.
|
||||
--- **Functional** - Administer the scoring of player achievements, and create a CSV file logging the scoring events for use at team or squadron websites.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- ## Features:
|
||||
--
|
||||
-- * Set the scoring scales based on threat level.
|
||||
-- * Positive scores and negative scores.
|
||||
-- * A contribution model to score achievements.
|
||||
-- * Score goals.
|
||||
-- * Score specific achievements.
|
||||
-- * Score the hits and destroys of units.
|
||||
-- * Score the hits and destroys of statics.
|
||||
-- * Score the hits and destroys of scenery.
|
||||
-- * Log scores into a CSV file.
|
||||
-- * Connect to a remote server using JSON and IP.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- The @{#SCORING} class administers the scoring of player achievements,
|
||||
-- ## Missions:
|
||||
--
|
||||
-- [SCO - Scoring](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/SCO%20-%20Scoring)
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- Administers the scoring of player achievements,
|
||||
-- and creates a CSV file logging the scoring events and results for use at team or squadron websites.
|
||||
--
|
||||
-- SCORING automatically calculates the threat level of the objects hit and destroyed by players,
|
||||
-- which can be @{Unit}, @{Static) and @{Scenery} objects.
|
||||
-- which can be @{Wrapper.Unit}, @{Static) and @{Scenery} objects.
|
||||
--
|
||||
-- Positive score points are granted when enemy or neutral targets are destroyed.
|
||||
-- Negative score points or penalties are given when a friendly target is hit or destroyed.
|
||||
@@ -56,9 +73,34 @@
|
||||
-- Use the radio menu F10 to consult the scores while running the mission.
|
||||
-- Scores can be reported for your user, or an overall score can be reported of all players currently active in the mission.
|
||||
--
|
||||
-- # 1) @{Scoring#SCORING} class, extends @{Base#BASE}
|
||||
-- ===
|
||||
--
|
||||
-- ## 1.1) Set the destroy score or penalty scale
|
||||
-- ### Authors: **FlightControl**
|
||||
--
|
||||
-- ### Contributions:
|
||||
--
|
||||
-- * **Wingthor (TAW)**: Testing & Advice.
|
||||
-- * **Dutch-Baron (TAW)**: Testing & Advice.
|
||||
-- * **[Whisper](http://forums.eagle.ru/member.php?u=3829): Testing and Advice.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module Functional.Scoring
|
||||
-- @image Scoring.JPG
|
||||
|
||||
|
||||
--- @type SCORING
|
||||
-- @field Players A collection of the current players that have joined the game.
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
--- SCORING class
|
||||
--
|
||||
-- # Constructor:
|
||||
--
|
||||
-- local Scoring = SCORING:New( "Scoring File" )
|
||||
--
|
||||
--
|
||||
-- # Set the destroy score or penalty scale:
|
||||
--
|
||||
-- Score scales can be set for scores granted when enemies or friendlies are destroyed.
|
||||
-- Use the method @{#SCORING.SetScaleDestroyScore}() to set the scale of enemy destroys (positive destroys).
|
||||
@@ -71,12 +113,12 @@
|
||||
-- The above sets the scale for valid scores to 10. So scores will be given in a scale from 0 to 10.
|
||||
-- The penalties will be given in a scale from 0 to 40.
|
||||
--
|
||||
-- ## 1.2) Define special targets that will give extra scores.
|
||||
-- # Define special targets that will give extra scores:
|
||||
--
|
||||
-- Special targets can be set that will give extra scores to the players when these are destroyed.
|
||||
-- Use the methods @{#SCORING.AddUnitScore}() and @{#SCORING.RemoveUnitScore}() to specify a special additional score for a specific @{Unit}s.
|
||||
-- Use the methods @{#SCORING.AddUnitScore}() and @{#SCORING.RemoveUnitScore}() to specify a special additional score for a specific @{Wrapper.Unit}s.
|
||||
-- Use the methods @{#SCORING.AddStaticScore}() and @{#SCORING.RemoveStaticScore}() to specify a special additional score for a specific @{Static}s.
|
||||
-- Use the method @{#SCORING.SetGroupGroup}() to specify a special additional score for a specific @{Group}s.
|
||||
-- Use the method @{#SCORING.SetGroupGroup}() to specify a special additional score for a specific @{Wrapper.Group}s.
|
||||
--
|
||||
-- local Scoring = SCORING:New( "Scoring File" )
|
||||
-- Scoring:AddUnitScore( UNIT:FindByName( "Unit #001" ), 200 )
|
||||
@@ -88,22 +130,22 @@
|
||||
--
|
||||
-- Scoring:RemoveUnitScore( UNIT:FindByName( "Unit #001" ) )
|
||||
--
|
||||
-- ## 1.3) Define destruction zones that will give extra scores.
|
||||
-- # Define destruction zones that will give extra scores:
|
||||
--
|
||||
-- Define zones of destruction. Any object destroyed within the zone of the given category will give extra points.
|
||||
-- Use the method @{#SCORING.AddZoneScore}() to add a @{Zone} for additional scoring.
|
||||
-- Use the method @{#SCORING.RemoveZoneScore}() to remove a @{Zone} for additional scoring.
|
||||
-- There are interesting variations that can be achieved with this functionality. For example, if the @{Zone} is a @{Zone#ZONE_UNIT},
|
||||
-- There are interesting variations that can be achieved with this functionality. For example, if the @{Zone} is a @{Core.Zone#ZONE_UNIT},
|
||||
-- then the zone is a moving zone, and anything destroyed within that @{Zone} will generate points.
|
||||
-- The other implementation could be to designate a scenery target (a building) in the mission editor surrounded by a @{Zone},
|
||||
-- just large enough around that building.
|
||||
--
|
||||
-- ## 1.4) Add extra Goal scores upon an event or a condition.
|
||||
-- # Add extra Goal scores upon an event or a condition:
|
||||
--
|
||||
-- A mission has goals and achievements. The scoring system provides an API to set additional scores when a goal or achievement event happens.
|
||||
-- Use the method @{#SCORING.AddGoalScore}() to add a score for a Player at any time in your mission.
|
||||
--
|
||||
-- ## 1.5) (Decommissioned) Configure fratricide level.
|
||||
-- # (Decommissioned) Configure fratricide level.
|
||||
--
|
||||
-- **This functionality is decomissioned until the DCS bug concerning Unit:destroy() not being functional in multi player for player units has been fixed by ED**.
|
||||
--
|
||||
@@ -111,13 +153,13 @@
|
||||
-- Use the method @{#SCORING.SetFratricide}() to define the level when a player gets kicked.
|
||||
-- By default, the fratricide level is the default penalty mutiplier * 2 for the penalty score.
|
||||
--
|
||||
-- ## 1.6) Penalty score when a player changes the coalition.
|
||||
-- # Penalty score when a player changes the coalition.
|
||||
--
|
||||
-- When a player changes the coalition, he can receive a penalty score.
|
||||
-- Use the method @{#SCORING.SetCoalitionChangePenalty}() to define the penalty when a player changes coalition.
|
||||
-- By default, the penalty for changing coalition is the default penalty scale.
|
||||
--
|
||||
-- ## 1.8) Define output CSV files.
|
||||
-- # Define output CSV files.
|
||||
--
|
||||
-- The CSV file is given the name of the string given in the @{#SCORING.New}{} constructor, followed by the .csv extension.
|
||||
-- The file is incrementally saved in the **<User>\\Saved Games\\DCS\\Logs** folder, and has a time stamp indicating each mission run.
|
||||
@@ -154,7 +196,7 @@
|
||||
-- The MOOSE designer cannot take any responsibility of any damage inflicted as a result of the de-sanitization.
|
||||
-- That being said, I hope that the SCORING class provides you with a great add-on to score your squad mates achievements.
|
||||
--
|
||||
-- ## 1.9) Configure messages.
|
||||
-- # Configure messages.
|
||||
--
|
||||
-- When players hit or destroy targets, messages are sent.
|
||||
-- Various methods exist to configure:
|
||||
@@ -162,7 +204,7 @@
|
||||
-- * Which messages are sent upon the event.
|
||||
-- * Which audience receives the message.
|
||||
--
|
||||
-- ### 1.9.1) Configure the messages sent upon the event.
|
||||
-- ## Configure the messages sent upon the event.
|
||||
--
|
||||
-- Use the following methods to configure when to send messages. By default, all messages are sent.
|
||||
--
|
||||
@@ -171,48 +213,16 @@
|
||||
-- * @{#SCORING.SetMessagesAddon}(): Configure to send messages for additional score, after a target has been destroyed.
|
||||
-- * @{#SCORING.SetMessagesZone}(): Configure to send messages for additional score, after a target has been destroyed within a given zone.
|
||||
--
|
||||
-- ### 1.9.2) Configure the audience of the messages.
|
||||
-- ## Configure the audience of the messages.
|
||||
--
|
||||
-- Use the following methods to configure the audience of the messages. By default, the messages are sent to all players in the mission.
|
||||
--
|
||||
-- * @{#SCORING.SetMessagesToAll}(): Configure to send messages to all players.
|
||||
-- * @{#SCORING.SetMessagesToCoalition}(): Configure to send messages to only those players within the same coalition as the player.
|
||||
--
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- # **API CHANGE HISTORY**
|
||||
--
|
||||
-- The underlying change log documents the API changes. Please read this carefully. The following notation is used:
|
||||
--
|
||||
-- * **Added** parts are expressed in bold type face.
|
||||
-- * _Removed_ parts are expressed in italic type face.
|
||||
--
|
||||
-- Hereby the change log:
|
||||
--
|
||||
-- 2017-02-26: Initial class and API.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- # **AUTHORS and CONTRIBUTIONS**
|
||||
--
|
||||
-- ### Contributions:
|
||||
--
|
||||
-- * **Wingthor (TAW)**: Testing & Advice.
|
||||
-- * **Dutch-Baron (TAW)**: Testing & Advice.
|
||||
-- * **[Whisper](http://forums.eagle.ru/member.php?u=3829): Testing and Advice.
|
||||
--
|
||||
-- ### Authors:
|
||||
--
|
||||
-- * **FlightControl**: Concept, Design & Programming.
|
||||
--
|
||||
-- @module Scoring
|
||||
|
||||
|
||||
--- The Scoring class
|
||||
-- @type SCORING
|
||||
-- @field Players A collection of the current players that have joined the game.
|
||||
-- @extends Core.Base#BASE
|
||||
-- @field #SCORING
|
||||
SCORING = {
|
||||
ClassName = "SCORING",
|
||||
ClassID = 0,
|
||||
@@ -239,8 +249,10 @@ local _SCORINGCategory =
|
||||
-- @param #string GameName The name of the game. This name is also logged in the CSV score file.
|
||||
-- @return #SCORING self
|
||||
-- @usage
|
||||
--
|
||||
-- -- Define a new scoring object for the mission Gori Valley.
|
||||
-- ScoringObject = SCORING:New( "Gori Valley" )
|
||||
--
|
||||
function SCORING:New( GameName )
|
||||
|
||||
-- Inherits from BASE
|
||||
@@ -339,11 +351,11 @@ function SCORING:SetScaleDestroyPenalty( Scale )
|
||||
return self
|
||||
end
|
||||
|
||||
--- Add a @{Unit} for additional scoring when the @{Unit} is destroyed.
|
||||
-- Note that if there was already a @{Unit} declared within the scoring with the same name,
|
||||
-- then the old @{Unit} will be replaced with the new @{Unit}.
|
||||
--- Add a @{Wrapper.Unit} for additional scoring when the @{Wrapper.Unit} is destroyed.
|
||||
-- Note that if there was already a @{Wrapper.Unit} declared within the scoring with the same name,
|
||||
-- then the old @{Wrapper.Unit} will be replaced with the new @{Wrapper.Unit}.
|
||||
-- @param #SCORING self
|
||||
-- @param Wrapper.Unit#UNIT ScoreUnit The @{Unit} for which the Score needs to be given.
|
||||
-- @param Wrapper.Unit#UNIT ScoreUnit The @{Wrapper.Unit} for which the Score needs to be given.
|
||||
-- @param #number Score The Score value.
|
||||
-- @return #SCORING
|
||||
function SCORING:AddUnitScore( ScoreUnit, Score )
|
||||
@@ -355,9 +367,9 @@ function SCORING:AddUnitScore( ScoreUnit, Score )
|
||||
return self
|
||||
end
|
||||
|
||||
--- Removes a @{Unit} for additional scoring when the @{Unit} is destroyed.
|
||||
--- Removes a @{Wrapper.Unit} for additional scoring when the @{Wrapper.Unit} is destroyed.
|
||||
-- @param #SCORING self
|
||||
-- @param Wrapper.Unit#UNIT ScoreUnit The @{Unit} for which the Score needs to be given.
|
||||
-- @param Wrapper.Unit#UNIT ScoreUnit The @{Wrapper.Unit} for which the Score needs to be given.
|
||||
-- @return #SCORING
|
||||
function SCORING:RemoveUnitScore( ScoreUnit )
|
||||
|
||||
@@ -398,9 +410,9 @@ function SCORING:RemoveStaticScore( ScoreStatic )
|
||||
end
|
||||
|
||||
|
||||
--- Specify a special additional score for a @{Group}.
|
||||
--- Specify a special additional score for a @{Wrapper.Group}.
|
||||
-- @param #SCORING self
|
||||
-- @param Wrapper.Group#GROUP ScoreGroup The @{Group} for which each @{Unit} a Score is given.
|
||||
-- @param Wrapper.Group#GROUP ScoreGroup The @{Wrapper.Group} for which each @{Wrapper.Unit} a Score is given.
|
||||
-- @param #number Score The Score value.
|
||||
-- @return #SCORING
|
||||
function SCORING:AddScoreGroup( ScoreGroup, Score )
|
||||
@@ -714,7 +726,7 @@ end
|
||||
-- A free text can be given that is shown to the players.
|
||||
-- The Score can be both positive and negative.
|
||||
-- @param #SCORING self
|
||||
-- @param Wrapper.Unit#UNIT PlayerUnit The @{Unit} of the Player. Other Properties for the scoring are taken from this PlayerUnit, like coalition, type etc.
|
||||
-- @param Wrapper.Unit#UNIT PlayerUnit The @{Wrapper.Unit} of the Player. Other Properties for the scoring are taken from this PlayerUnit, like coalition, type etc.
|
||||
-- @param #string GoalTag The string or identifier that is used in the CSV file to identify the goal (sort or group later in Excel).
|
||||
-- @param #string Text A free text that is shown to the players.
|
||||
-- @param #number Score The score can be both positive or negative ( Penalty ).
|
||||
|
||||
@@ -1,12 +1,41 @@
|
||||
--- **Functional** -- Provides defensive behaviour to a set of SAM sites within a running Mission.
|
||||
--- **Functional** -- Make SAM sites execute evasive and defensive behaviour when being fired upon.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module Sead
|
||||
-- ## Features:
|
||||
--
|
||||
-- * When SAM sites are being fired upon, the SAMs will take evasive action will reposition themselves when possible.
|
||||
-- * When SAM sites are being fired upon, the SAMs will take defensive action by shutting down their radars.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ## Missions:
|
||||
--
|
||||
-- [SEV - SEAD Evasion](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/SEV%20-%20SEAD%20Evasion)
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Authors: **FlightControl**
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module Functional.Sead
|
||||
-- @image SEAD.JPG
|
||||
|
||||
--- The SEAD class
|
||||
-- @type SEAD
|
||||
--- @type SEAD
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
--- Make SAM sites execute evasive and defensive behaviour when being fired upon.
|
||||
--
|
||||
-- This class is very easy to use. Just setup a SEAD object by using @{#SEAD.New}() and SAMs will evade and take defensive action when being fired upon.
|
||||
--
|
||||
-- # Constructor:
|
||||
--
|
||||
-- Use the @{#SEAD.New}() constructor to create a new SEAD object.
|
||||
--
|
||||
-- SEAD_RU_SAM_Defenses = SEAD:New( { 'RU SA-6 Kub', 'RU SA-6 Defenses', 'RU MI-26 Troops', 'RU Attack Gori' } )
|
||||
--
|
||||
-- @field #SEAD
|
||||
SEAD = {
|
||||
ClassName = "SEAD",
|
||||
TargetSkill = {
|
||||
|
||||
@@ -1,9 +1,18 @@
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
--- **Functional** - (R2.4) Suppress fire of ground units when they get hit.
|
||||
--- **Functional** - Suppress fire of ground units when they get hit.
|
||||
--
|
||||
-- 
|
||||
-- ===
|
||||
--
|
||||
-- ====
|
||||
-- ## Features:
|
||||
--
|
||||
-- * Hold fire of attacked units when being fired upon.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ## Missions:
|
||||
--
|
||||
-- ## [MOOSE - ALL Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS)
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- When ground units get hit by (suppressive) enemy fire, they will not be able to shoot back for a certain amount of time.
|
||||
--
|
||||
@@ -14,12 +23,6 @@
|
||||
--
|
||||
-- ====
|
||||
--
|
||||
-- # Demo Missions
|
||||
--
|
||||
-- ### [MOOSE - ALL Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS)
|
||||
--
|
||||
-- ====
|
||||
--
|
||||
-- # YouTube Channel
|
||||
--
|
||||
-- ### [MOOSE YouTube Channel](https://www.youtube.com/channel/UCjrA9j5LQoWsG4SpS8i79Qg)
|
||||
@@ -30,8 +33,10 @@
|
||||
--
|
||||
-- ### Contributions: [FlightControl](https://forums.eagle.ru/member.php?u=89536)
|
||||
--
|
||||
-- ====
|
||||
-- @module Suppression
|
||||
-- ===
|
||||
--
|
||||
-- @module Functional.Suppression
|
||||
-- @image Suppression.JPG
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -76,8 +81,7 @@
|
||||
-- @extends Core.Fsm#FSM_CONTROLLABLE
|
||||
--
|
||||
|
||||
---# SUPPRESSION class, extends @{Core.Fsm#FSM_CONTROLLABLE}
|
||||
-- Mimic suppressive enemy fire and let groups flee or retreat.
|
||||
--- Mimic suppressive enemy fire and let groups flee or retreat.
|
||||
--
|
||||
-- ## Suppression Process
|
||||
--
|
||||
@@ -1727,7 +1731,7 @@ end
|
||||
--@param Core.Point#COORDINATE a Coordinate.
|
||||
--@param Core.Point#COORDINATE b Coordinate.
|
||||
--@return #number angle Angle from a to b in degrees.
|
||||
function SUPPRESSION:_Heading(a, b, distance)
|
||||
function SUPPRESSION:_Heading(a, b)
|
||||
local dx = b.x-a.x
|
||||
local dy = b.z-a.z
|
||||
local angle = math.deg(math.atan2(dy,dx))
|
||||
|
||||
7664
Moose Development/Moose/Functional/Warehouse.lua
Normal file
7664
Moose Development/Moose/Functional/Warehouse.lua
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,18 +1,40 @@
|
||||
--- **Functional** -- (R2.3) Models the process to zone guarding and capturing.
|
||||
--- **Functional** -- Models the process to zone guarding and capturing.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- 
|
||||
-- ## Features:
|
||||
--
|
||||
-- * Models the possible state transitions between the Guarded, Attacked, Empty and Captured states.
|
||||
-- * A zone has an owning coalition, that means that at a specific point in time, a zone can be owned by the red or blue coalition.
|
||||
-- * Provide event handlers to tailor the actions when a zone changes coalition or state.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### [Demo Missions](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/CAZ - Capture Zones)
|
||||
-- ## Missions:
|
||||
--
|
||||
-- - CAZ-000 - Capture Zone: Demonstrates the basic concept of capturing a zone.
|
||||
-- [CAZ - Capture Zones](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/CAZ%20-%20Capture%20Zones)
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### [YouTube Playlist](https://www.youtube.com/watch?v=0m6K6Yxa-os&list=PL7ZUrU4zZUl0qqJsfa8DPvZWDY-OyDumE)
|
||||
-- # Player Experience
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- The above models the possible state transitions between the **Guarded**, **Attacked**, **Empty** and **Captured** states.
|
||||
-- A zone has an __owning coalition__, that means that at a specific point in time, a zone can be owned by the red or blue coalition.
|
||||
--
|
||||
-- The Zone can be in the state **Guarded** by the __owning coalition__, which is the coalition that initially occupies the zone with units of its coalition.
|
||||
-- Once units of an other coalition are entering the Zone, the state will change to **Attacked**. As long as these units remain in the zone, the state keeps set to Attacked.
|
||||
-- When all units are destroyed in the Zone, the state will change to **Empty**, which expresses that the Zone is empty, and can be captured.
|
||||
-- When units of the other coalition are in the Zone, and no other units of the owning coalition is in the Zone, the Zone is captured, and its state will change to **Captured**.
|
||||
--
|
||||
-- The zone needs to be monitored regularly for the presence of units to interprete the correct state transition required.
|
||||
-- This monitoring process MUST be started using the @{#ZONE_CAPTURE_COALITION.Start}() method.
|
||||
-- Otherwise no monitoring will be active and the zone will stay in the current state forever.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ## [YouTube Playlist](https://www.youtube.com/watch?v=0m6K6Yxa-os&list=PL7ZUrU4zZUl0qqJsfa8DPvZWDY-OyDumE)
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
@@ -21,7 +43,8 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module ZoneCaptureCoalition
|
||||
-- @module Functional.ZoneCaptureCoalition
|
||||
-- @image Capture_Zones.JPG
|
||||
|
||||
do -- ZONE_CAPTURE_COALITION
|
||||
|
||||
@@ -29,70 +52,79 @@ do -- ZONE_CAPTURE_COALITION
|
||||
-- @extends Functional.ZoneGoalCoalition#ZONE_GOAL_COALITION
|
||||
|
||||
|
||||
--- # ZONE\_CAPTURE\_COALITION class, extends @{ZoneGoalCoalition#ZONE_GOAL_COALITION}
|
||||
--
|
||||
-- Models the process to capture a Zone for a Coalition, which is guarded by another Coalition.
|
||||
--- Models the process to capture a Zone for a Coalition, which is guarded by another Coalition.
|
||||
-- This is a powerful concept that allows to create very dynamic missions based on the different state transitions of various zones.
|
||||
--
|
||||
-- ---
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- ---
|
||||
-- ===
|
||||
--
|
||||
-- # 0. Player Experience
|
||||
-- In order to use ZONE_CAPTURE_COALITION, you need to:
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- The above models the possible state transitions between the **Guarded**, **Attacked**, **Empty** and **Captured** states.
|
||||
-- A zone has an __owning coalition__, that means that at a specific point in time, a zone can be owned by the red or blue coalition.
|
||||
--
|
||||
-- The Zone can be in the state **Guarded** by the __owning coalition__, which is the coalition that initially occupies the zone with units of its coalition.
|
||||
-- Once units of an other coalition are entering the Zone, the state will change to **Attacked**. As long as these units remain in the zone, the state keeps set to Attacked.
|
||||
-- When all units are destroyed in the Zone, the state will change to **Empty**, which expresses that the Zone is empty, and can be captured.
|
||||
-- When units of the other coalition are in the Zone, and no other units of the owning coalition is in the Zone, the Zone is captured, and its state will change to **Captured**.
|
||||
--
|
||||
-- The zone needs to be monitored regularly for the presence of units to interprete the correct state transition required.
|
||||
-- This monitoring process MUST be started using the @{#ZONE_CAPTURE_COALITION.Start}() method.
|
||||
-- Otherwise no monitoring will be active and the zone will stay in the current state forever.
|
||||
-- See further in chapter 3.3 for more information about this.
|
||||
--
|
||||
-- ## 1. ZONE\_CAPTURE\_COALITION constructor
|
||||
--
|
||||
-- * @{#ZONE_CAPTURE_COALITION.New}(): Creates a new ZONE\_CAPTURE\_COALITION object.
|
||||
--
|
||||
-- In order to use ZONE\_CAPTURE\_COALITION, you need to:
|
||||
--
|
||||
-- - Create a @{Zone} object from one of the ZONE\_ classes. Note that ZONE\_POLYGON\_ classes are not yet functional. The only functional ZONE\_ classses are those derived from a ZONE\_RADIUS.
|
||||
-- * Create a @{Zone} object from one of the ZONE_ classes.
|
||||
-- Note that ZONE_POLYGON_ classes are not yet functional.
|
||||
-- The only functional ZONE_ classses are those derived from a ZONE_RADIUS.
|
||||
-- * Set the state of the zone. Most of the time, Guarded would be the initial state.
|
||||
-- * Start the zone capturing **monitoring process**.
|
||||
-- This will check the presence of friendly and/or enemy units within the zone and will transition the state of the zone when the tactical situation changed.
|
||||
-- The frequency of the monitoring must not be real-time, a 30 second interval to execute the checks is sufficient.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- Ensure that during the life cycle of the ZONE\_CAPTURE\_COALITION object, the object keeps alive.
|
||||
-- It is best to declare the object globally within your script.
|
||||
-- ### Important:
|
||||
--
|
||||
-- ## 2. ZONE\_CAPTURE\_COALITION is a finite state machine (FSM).
|
||||
-- You must start the monitoring process within your code, or there won't be any state transition checks executed.
|
||||
-- See further the start/stop monitoring process.
|
||||
--
|
||||
-- ### Important:
|
||||
--
|
||||
-- Ensure that the object containing the ZONE_CAPTURE_COALITION object is persistent.
|
||||
-- Otherwise the garbage collector of lua will remove the object and the monitoring process will stop.
|
||||
-- This will result in your object to be destroyed (removed) from internal memory and there won't be any zone state transitions anymore detected!
|
||||
-- So use the `local` keyword in lua with thought! Most of the time, you can declare your object gobally.
|
||||
--
|
||||
--
|
||||
--
|
||||
-- # Example:
|
||||
--
|
||||
-- -- Define a new ZONE object, which is based on the trigger zone `CaptureZone`, which is defined within the mission editor.
|
||||
-- CaptureZone = ZONE:New( "CaptureZone" )
|
||||
--
|
||||
-- -- Here we create a new ZONE_CAPTURE_COALITION object, using the :New constructor.
|
||||
-- ZoneCaptureCoalition = ZONE_CAPTURE_COALITION:New( CaptureZone, coalition.side.RED )
|
||||
--
|
||||
-- -- Set the zone to Guarding state.
|
||||
-- ZoneCaptureCoalition:__Guard( 1 )
|
||||
--
|
||||
-- -- Start the zone monitoring process in 30 seconds and check every 30 seconds.
|
||||
-- ZoneCaptureCoalition:Start( 30, 30 )
|
||||
--
|
||||
--
|
||||
-- # Constructor:
|
||||
--
|
||||
-- Use the @{#ZONE_CAPTURE_COALITION.New}() constructor to create a new ZONE_CAPTURE_COALITION object.
|
||||
--
|
||||
-- # ZONE_CAPTURE_COALITION is a finite state machine (FSM).
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- ### 2.1 ZONE\_CAPTURE\_COALITION States
|
||||
-- ## ZONE_CAPTURE_COALITION States
|
||||
--
|
||||
-- * **Captured**: The Zone has been captured by an other coalition.
|
||||
-- * **Attacked**: The Zone is currently intruded by an other coalition. There are units of the owning coalition and an other coalition in the Zone.
|
||||
-- * **Guarded**: The Zone is guarded by the owning coalition. There is no other unit of an other coalition in the Zone.
|
||||
-- * **Empty**: The Zone is empty. There is not valid unit in the Zone.
|
||||
--
|
||||
-- ### 2.2 ZONE\_CAPTURE\_COALITION Events
|
||||
-- ## 2.2 ZONE_CAPTURE_COALITION Events
|
||||
--
|
||||
-- * **Capture**: The Zone has been captured by an other coalition.
|
||||
-- * **Attack**: The Zone is currently intruded by an other coalition. There are units of the owning coalition and an other coalition in the Zone.
|
||||
-- * **Guard**: The Zone is guarded by the owning coalition. There is no other unit of an other coalition in the Zone.
|
||||
-- * **Empty**: The Zone is empty. There is not valid unit in the Zone.
|
||||
--
|
||||
-- ## 3. "Script It"
|
||||
-- # "Script It"
|
||||
--
|
||||
-- ZONE\_CAPTURE\_COALITION allows to take action on the various state transitions and add your custom code and logic.
|
||||
-- ZONE_CAPTURE_COALITION allows to take action on the various state transitions and add your custom code and logic.
|
||||
--
|
||||
-- ### 3.1. Take action using state- and event handlers.
|
||||
-- ## Take action using state- and event handlers.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
@@ -109,8 +141,6 @@ do -- ZONE_CAPTURE_COALITION
|
||||
-- - On Before the event is triggered. Return false to cancel the transition.
|
||||
-- - On After the event is triggered.
|
||||
--
|
||||
--
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- Each handler can receive optionally 3 parameters:
|
||||
@@ -131,7 +161,7 @@ do -- ZONE_CAPTURE_COALITION
|
||||
--
|
||||
-- This code checks that when the __Guarded__ state has been reached, that if the **From** state was __Empty__, then display a message.
|
||||
--
|
||||
-- ### 3.2. Example Event Handler.
|
||||
-- ## Example Event Handler.
|
||||
--
|
||||
-- --- @param Functional.ZoneCaptureCoalition#ZONE_CAPTURE_COALITION self
|
||||
-- function ZoneCaptureCoalition:OnEnterGuarded( From, Event, To )
|
||||
@@ -150,7 +180,7 @@ do -- ZONE_CAPTURE_COALITION
|
||||
-- end
|
||||
-- end
|
||||
--
|
||||
-- ### 3.3. Stop and Start the zone monitoring process.
|
||||
-- ## Stop and Start the zone monitoring process.
|
||||
--
|
||||
-- At regular intervals, the state of the zone needs to be monitored.
|
||||
-- The zone needs to be scanned for the presence of units within the zone boundaries.
|
||||
@@ -162,8 +192,8 @@ do -- ZONE_CAPTURE_COALITION
|
||||
--
|
||||
-- Therefore, the mission designer is given 2 methods that allow to take control of the CPU utilization efficiency:
|
||||
--
|
||||
-- - @{#ZONE_CAPTURE_COALITION.Start()}(): This starts the monitoring process.
|
||||
-- - @{#ZONE_CAPTURE_COALITION.Stop()}(): This stops the monitoring process.
|
||||
-- * @{#ZONE_CAPTURE_COALITION.Start}(): This starts the monitoring process.
|
||||
-- * @{#ZONE_CAPTURE_COALITION.Stop}(): This stops the monitoring process.
|
||||
--
|
||||
-- ### IMPORTANT
|
||||
--
|
||||
@@ -171,9 +201,9 @@ do -- ZONE_CAPTURE_COALITION
|
||||
-- The monitoring process is NOT started by default!!!**
|
||||
--
|
||||
--
|
||||
-- ## 4. Full Example
|
||||
-- # Full Example
|
||||
--
|
||||
-- The following annotated code shows a real example of how ZONE\_CAPTURE\_COALITION can be applied.
|
||||
-- The following annotated code shows a real example of how ZONE_CAPTURE_COALITION can be applied.
|
||||
--
|
||||
-- The concept is simple.
|
||||
--
|
||||
@@ -334,7 +364,7 @@ do -- ZONE_CAPTURE_COALITION
|
||||
|
||||
do
|
||||
|
||||
--- Captured State Handler OnLeave for ZONE\_CAPTURE\_COALITION
|
||||
--- Captured State Handler OnLeave for ZONE_CAPTURE_COALITION
|
||||
-- @function [parent=#ZONE_CAPTURE_COALITION] OnLeaveCaptured
|
||||
-- @param #ZONE_CAPTURE_COALITION self
|
||||
-- @param #string From
|
||||
@@ -342,7 +372,7 @@ do -- ZONE_CAPTURE_COALITION
|
||||
-- @param #string To
|
||||
-- @return #boolean
|
||||
|
||||
--- Captured State Handler OnEnter for ZONE\_CAPTURE\_COALITION
|
||||
--- Captured State Handler OnEnter for ZONE_CAPTURE_COALITION
|
||||
-- @function [parent=#ZONE_CAPTURE_COALITION] OnEnterCaptured
|
||||
-- @param #ZONE_CAPTURE_COALITION self
|
||||
-- @param #string From
|
||||
@@ -354,7 +384,7 @@ do -- ZONE_CAPTURE_COALITION
|
||||
|
||||
do
|
||||
|
||||
--- Attacked State Handler OnLeave for ZONE\_CAPTURE\_COALITION
|
||||
--- Attacked State Handler OnLeave for ZONE_CAPTURE_COALITION
|
||||
-- @function [parent=#ZONE_CAPTURE_COALITION] OnLeaveAttacked
|
||||
-- @param #ZONE_CAPTURE_COALITION self
|
||||
-- @param #string From
|
||||
@@ -362,7 +392,7 @@ do -- ZONE_CAPTURE_COALITION
|
||||
-- @param #string To
|
||||
-- @return #boolean
|
||||
|
||||
--- Attacked State Handler OnEnter for ZONE\_CAPTURE\_COALITION
|
||||
--- Attacked State Handler OnEnter for ZONE_CAPTURE_COALITION
|
||||
-- @function [parent=#ZONE_CAPTURE_COALITION] OnEnterAttacked
|
||||
-- @param #ZONE_CAPTURE_COALITION self
|
||||
-- @param #string From
|
||||
@@ -373,7 +403,7 @@ do -- ZONE_CAPTURE_COALITION
|
||||
|
||||
do
|
||||
|
||||
--- Guarded State Handler OnLeave for ZONE\_CAPTURE\_COALITION
|
||||
--- Guarded State Handler OnLeave for ZONE_CAPTURE_COALITION
|
||||
-- @function [parent=#ZONE_CAPTURE_COALITION] OnLeaveGuarded
|
||||
-- @param #ZONE_CAPTURE_COALITION self
|
||||
-- @param #string From
|
||||
@@ -381,7 +411,7 @@ do -- ZONE_CAPTURE_COALITION
|
||||
-- @param #string To
|
||||
-- @return #boolean
|
||||
|
||||
--- Guarded State Handler OnEnter for ZONE\_CAPTURE\_COALITION
|
||||
--- Guarded State Handler OnEnter for ZONE_CAPTURE_COALITION
|
||||
-- @function [parent=#ZONE_CAPTURE_COALITION] OnEnterGuarded
|
||||
-- @param #ZONE_CAPTURE_COALITION self
|
||||
-- @param #string From
|
||||
@@ -393,7 +423,7 @@ do -- ZONE_CAPTURE_COALITION
|
||||
|
||||
do
|
||||
|
||||
--- Empty State Handler OnLeave for ZONE\_CAPTURE\_COALITION
|
||||
--- Empty State Handler OnLeave for ZONE_CAPTURE_COALITION
|
||||
-- @function [parent=#ZONE_CAPTURE_COALITION] OnLeaveEmpty
|
||||
-- @param #ZONE_CAPTURE_COALITION self
|
||||
-- @param #string From
|
||||
@@ -401,7 +431,7 @@ do -- ZONE_CAPTURE_COALITION
|
||||
-- @param #string To
|
||||
-- @return #boolean
|
||||
|
||||
--- Empty State Handler OnEnter for ZONE\_CAPTURE\_COALITION
|
||||
--- Empty State Handler OnEnter for ZONE_CAPTURE_COALITION
|
||||
-- @function [parent=#ZONE_CAPTURE_COALITION] OnEnterEmpty
|
||||
-- @param #ZONE_CAPTURE_COALITION self
|
||||
-- @param #string From
|
||||
@@ -412,7 +442,7 @@ do -- ZONE_CAPTURE_COALITION
|
||||
|
||||
self:AddTransition( "*", "Guard", "Guarded" )
|
||||
|
||||
--- Guard Handler OnBefore for ZONE\_CAPTURE\_COALITION
|
||||
--- Guard Handler OnBefore for ZONE_CAPTURE_COALITION
|
||||
-- @function [parent=#ZONE_CAPTURE_COALITION] OnBeforeGuard
|
||||
-- @param #ZONE_CAPTURE_COALITION self
|
||||
-- @param #string From
|
||||
@@ -420,25 +450,25 @@ do -- ZONE_CAPTURE_COALITION
|
||||
-- @param #string To
|
||||
-- @return #boolean
|
||||
|
||||
--- Guard Handler OnAfter for ZONE\_CAPTURE\_COALITION
|
||||
--- Guard Handler OnAfter for ZONE_CAPTURE_COALITION
|
||||
-- @function [parent=#ZONE_CAPTURE_COALITION] OnAfterGuard
|
||||
-- @param #ZONE_CAPTURE_COALITION self
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
|
||||
--- Guard Trigger for ZONE\_CAPTURE\_COALITION
|
||||
--- Guard Trigger for ZONE_CAPTURE_COALITION
|
||||
-- @function [parent=#ZONE_CAPTURE_COALITION] Guard
|
||||
-- @param #ZONE_CAPTURE_COALITION self
|
||||
|
||||
--- Guard Asynchronous Trigger for ZONE\_CAPTURE\_COALITION
|
||||
--- Guard Asynchronous Trigger for ZONE_CAPTURE_COALITION
|
||||
-- @function [parent=#ZONE_CAPTURE_COALITION] __Guard
|
||||
-- @param #ZONE_CAPTURE_COALITION self
|
||||
-- @param #number Delay
|
||||
|
||||
self:AddTransition( "*", "Empty", "Empty" )
|
||||
|
||||
--- Empty Handler OnBefore for ZONE\_CAPTURE\_COALITION
|
||||
--- Empty Handler OnBefore for ZONE_CAPTURE_COALITION
|
||||
-- @function [parent=#ZONE_CAPTURE_COALITION] OnBeforeEmpty
|
||||
-- @param #ZONE_CAPTURE_COALITION self
|
||||
-- @param #string From
|
||||
@@ -446,18 +476,18 @@ do -- ZONE_CAPTURE_COALITION
|
||||
-- @param #string To
|
||||
-- @return #boolean
|
||||
|
||||
--- Empty Handler OnAfter for ZONE\_CAPTURE\_COALITION
|
||||
--- Empty Handler OnAfter for ZONE_CAPTURE_COALITION
|
||||
-- @function [parent=#ZONE_CAPTURE_COALITION] OnAfterEmpty
|
||||
-- @param #ZONE_CAPTURE_COALITION self
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
|
||||
--- Empty Trigger for ZONE\_CAPTURE\_COALITION
|
||||
--- Empty Trigger for ZONE_CAPTURE_COALITION
|
||||
-- @function [parent=#ZONE_CAPTURE_COALITION] Empty
|
||||
-- @param #ZONE_CAPTURE_COALITION self
|
||||
|
||||
--- Empty Asynchronous Trigger for ZONE\_CAPTURE\_COALITION
|
||||
--- Empty Asynchronous Trigger for ZONE_CAPTURE_COALITION
|
||||
-- @function [parent=#ZONE_CAPTURE_COALITION] __Empty
|
||||
-- @param #ZONE_CAPTURE_COALITION self
|
||||
-- @param #number Delay
|
||||
@@ -465,7 +495,7 @@ do -- ZONE_CAPTURE_COALITION
|
||||
|
||||
self:AddTransition( { "Guarded", "Empty" }, "Attack", "Attacked" )
|
||||
|
||||
--- Attack Handler OnBefore for ZONE\_CAPTURE\_COALITION
|
||||
--- Attack Handler OnBefore for ZONE_CAPTURE_COALITION
|
||||
-- @function [parent=#ZONE_CAPTURE_COALITION] OnBeforeAttack
|
||||
-- @param #ZONE_CAPTURE_COALITION self
|
||||
-- @param #string From
|
||||
@@ -473,25 +503,25 @@ do -- ZONE_CAPTURE_COALITION
|
||||
-- @param #string To
|
||||
-- @return #boolean
|
||||
|
||||
--- Attack Handler OnAfter for ZONE\_CAPTURE\_COALITION
|
||||
--- Attack Handler OnAfter for ZONE_CAPTURE_COALITION
|
||||
-- @function [parent=#ZONE_CAPTURE_COALITION] OnAfterAttack
|
||||
-- @param #ZONE_CAPTURE_COALITION self
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
|
||||
--- Attack Trigger for ZONE\_CAPTURE\_COALITION
|
||||
--- Attack Trigger for ZONE_CAPTURE_COALITION
|
||||
-- @function [parent=#ZONE_CAPTURE_COALITION] Attack
|
||||
-- @param #ZONE_CAPTURE_COALITION self
|
||||
|
||||
--- Attack Asynchronous Trigger for ZONE\_CAPTURE\_COALITION
|
||||
--- Attack Asynchronous Trigger for ZONE_CAPTURE_COALITION
|
||||
-- @function [parent=#ZONE_CAPTURE_COALITION] __Attack
|
||||
-- @param #ZONE_CAPTURE_COALITION self
|
||||
-- @param #number Delay
|
||||
|
||||
self:AddTransition( { "Guarded", "Attacked", "Empty" }, "Capture", "Captured" )
|
||||
|
||||
--- Capture Handler OnBefore for ZONE\_CAPTURE\_COALITION
|
||||
--- Capture Handler OnBefore for ZONE_CAPTURE_COALITION
|
||||
-- @function [parent=#ZONE_CAPTURE_COALITION] OnBeforeCapture
|
||||
-- @param #ZONE_CAPTURE_COALITION self
|
||||
-- @param #string From
|
||||
@@ -499,18 +529,18 @@ do -- ZONE_CAPTURE_COALITION
|
||||
-- @param #string To
|
||||
-- @return #boolean
|
||||
|
||||
--- Capture Handler OnAfter for ZONE\_CAPTURE\_COALITION
|
||||
--- Capture Handler OnAfter for ZONE_CAPTURE_COALITION
|
||||
-- @function [parent=#ZONE_CAPTURE_COALITION] OnAfterCapture
|
||||
-- @param #ZONE_CAPTURE_COALITION self
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
|
||||
--- Capture Trigger for ZONE\_CAPTURE\_COALITION
|
||||
--- Capture Trigger for ZONE_CAPTURE_COALITION
|
||||
-- @function [parent=#ZONE_CAPTURE_COALITION] Capture
|
||||
-- @param #ZONE_CAPTURE_COALITION self
|
||||
|
||||
--- Capture Asynchronous Trigger for ZONE\_CAPTURE\_COALITION
|
||||
--- Capture Asynchronous Trigger for ZONE_CAPTURE_COALITION
|
||||
-- @function [parent=#ZONE_CAPTURE_COALITION] __Capture
|
||||
-- @param #ZONE_CAPTURE_COALITION self
|
||||
-- @param #number Delay
|
||||
|
||||
@@ -11,7 +11,8 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module ZoneGoal
|
||||
-- @module Functional.ZoneGoal
|
||||
-- @image MOOSE.JPG
|
||||
|
||||
do -- Zone
|
||||
|
||||
@@ -19,9 +20,7 @@ do -- Zone
|
||||
-- @extends Core.Fsm#FSM
|
||||
|
||||
|
||||
--- # ZONE_GOAL class, extends @{Fsm#FSM}
|
||||
--
|
||||
-- ZONE_GOAL models processes that have a Goal with a defined achievement involving a Zone.
|
||||
-- Models processes that have a Goal with a defined achievement involving a Zone.
|
||||
-- Derived classes implement the ways how the achievements can be realized.
|
||||
--
|
||||
-- ## 1. ZONE_GOAL constructor
|
||||
@@ -36,7 +35,7 @@ do -- Zone
|
||||
--
|
||||
-- ### 2.2 ZONE_GOAL Events
|
||||
--
|
||||
-- * DestroyedUnit: A @{Unit} is destroyed in the Zone. The event will only get triggered if the method @{#ZONE_GOAL.MonitorDestroyedUnits}() is used.
|
||||
-- * DestroyedUnit: A @{Wrapper.Unit} is destroyed in the Zone. The event will only get triggered if the method @{#ZONE_GOAL.MonitorDestroyedUnits}() is used.
|
||||
--
|
||||
-- @field #ZONE_GOAL
|
||||
ZONE_GOAL = {
|
||||
|
||||
@@ -11,7 +11,8 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module ZoneGoalCargo
|
||||
-- @module Functional.ZoneGoalCargo
|
||||
-- @image MOOSE.JPG
|
||||
|
||||
do -- ZoneGoal
|
||||
|
||||
@@ -19,9 +20,7 @@ do -- ZoneGoal
|
||||
-- @extends Functional.ZoneGoal#ZONE_GOAL
|
||||
|
||||
|
||||
--- # ZONE_GOAL_CARGO class, extends @{ZoneGoal#ZONE_GOAL}
|
||||
--
|
||||
-- ZONE_GOAL_CARGO models processes that have a Goal with a defined achievement involving a Zone and Cargo.
|
||||
--- Models processes that have a Goal with a defined achievement involving a Zone and Cargo.
|
||||
-- Derived classes implement the ways how the achievements can be realized.
|
||||
--
|
||||
-- ## 1. ZONE_GOAL_CARGO constructor
|
||||
|
||||
@@ -11,7 +11,8 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module ZoneGoalCoalition
|
||||
-- @module Functional.ZoneGoalCoalition
|
||||
-- @image MOOSE.JPG
|
||||
|
||||
do -- ZoneGoal
|
||||
|
||||
@@ -19,9 +20,7 @@ do -- ZoneGoal
|
||||
-- @extends Functional.ZoneGoal#ZONE_GOAL
|
||||
|
||||
|
||||
--- # ZONE_GOAL_COALITION class, extends @{ZoneGoal#ZONE_GOAL}
|
||||
--
|
||||
-- ZONE_GOAL_COALITION models processes that have a Goal with a defined achievement involving a Zone for a Coalition.
|
||||
--- ZONE_GOAL_COALITION models processes that have a Goal with a defined achievement involving a Zone for a Coalition.
|
||||
-- Derived classes implement the ways how the achievements can be realized.
|
||||
--
|
||||
-- ## 1. ZONE_GOAL_COALITION constructor
|
||||
|
||||
@@ -13,5 +13,6 @@ _DATABASE = DATABASE:New() -- Core.Database#DATABASE
|
||||
_SETTINGS = SETTINGS:Set()
|
||||
_SETTINGS:SetPlayerMenuOn()
|
||||
|
||||
_DATABASE:RegisterCargos()
|
||||
_DATABASE:_RegisterCargos()
|
||||
_DATABASE:_RegisterZones()
|
||||
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
--- **Tasking** -- A COMMANDCENTER is the owner of multiple missions within MOOSE.
|
||||
-- A COMMANDCENTER governs multiple missions, the tasking and the reporting.
|
||||
--- **Tasking** -- A command center governs multiple missions, and takes care of the reporting and communications.
|
||||
--
|
||||
-- **Features:**
|
||||
--
|
||||
-- * Govern multiple missions.
|
||||
-- * Communicate to coalitions, groups.
|
||||
-- * Assign tasks.
|
||||
-- * Manage the menus.
|
||||
-- * Manage reference zones.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
@@ -9,37 +16,107 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module CommandCenter
|
||||
|
||||
|
||||
|
||||
-- @module Tasking.CommandCenter
|
||||
-- @image Task_Command_Center.JPG
|
||||
|
||||
|
||||
--- The COMMANDCENTER class
|
||||
-- @type COMMANDCENTER
|
||||
-- @field Wrapper.Group#GROUP HQ
|
||||
-- @field Dcs.DCSCoalitionWrapper.Object#coalition CommandCenterCoalition
|
||||
-- @field DCS#coalition CommandCenterCoalition
|
||||
-- @list<Tasking.Mission#MISSION> Missions
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
|
||||
--- # COMMANDCENTER class, extends @{Base#BASE}
|
||||
--
|
||||
-- The COMMANDCENTER class governs multiple missions, the tasking and the reporting.
|
||||
--- Governs multiple missions, the tasking and the reporting.
|
||||
--
|
||||
-- The commandcenter communicates important messages between the various groups of human players executing tasks in missions.
|
||||
-- Command centers govern missions, communicates the task assignments between human players of the coalition, and manages the menu flow.
|
||||
-- It can assign a random task to a player when requested.
|
||||
-- The commandcenter provides the facilitites to communicate between human players online, executing a task.
|
||||
--
|
||||
-- ## COMMANDCENTER constructor
|
||||
-- ## 1. Create a command center object.
|
||||
--
|
||||
-- * @{#COMMANDCENTER.New}(): Creates a new COMMANDCENTER object.
|
||||
--
|
||||
-- ## Mission Management
|
||||
-- ## 2. Command center mission management.
|
||||
--
|
||||
-- Command centers manage missions. These can be added, removed and provides means to retrieve missions.
|
||||
-- These methods are heavily used by the task dispatcher classes.
|
||||
--
|
||||
-- * @{#COMMANDCENTER.AddMission}(): Adds a mission to the commandcenter control.
|
||||
-- * @{#COMMANDCENTER.RemoveMission}(): Removes a mission to the commandcenter control.
|
||||
-- * @{#COMMANDCENTER.GetMissions}(): Retrieves the missions table controlled by the commandcenter.
|
||||
--
|
||||
-- ## Reference Zones
|
||||
-- ## 3. Communication management between players.
|
||||
--
|
||||
-- Command center provide means of communication between players.
|
||||
-- Because a command center is a central object governing multiple missions,
|
||||
-- there are several levels at which communication needs to be done.
|
||||
-- Within MOOSE, communication is facilitated using the message system within the DCS simulator.
|
||||
--
|
||||
-- Messages can be sent between players at various levels:
|
||||
--
|
||||
-- - On a global level, to all players.
|
||||
-- - On a coalition level, only to the players belonging to the same coalition.
|
||||
-- - On a group level, to the players belonging to the same group.
|
||||
--
|
||||
-- Messages can be sent to **all players** by the command center using the method @{Tasking.CommandCenter#COMMANDCENTER.MessageToAll}().
|
||||
--
|
||||
-- To send messages to **the coalition of the command center**, there are two methods available:
|
||||
--
|
||||
-- - Use the method @{Tasking.CommandCenter#COMMANDCENTER.MessageToCoalition}() to send a specific message to the coalition, with a given message display duration.
|
||||
-- - You can send a specific type of message using the method @{Tasking.CommandCenter#COMMANDCENTER.MessageTypeToCoalition}().
|
||||
-- This will send a message of a specific type to the coalition, and as a result its display duration will be flexible according the message display time selection by the human player.
|
||||
--
|
||||
-- To send messages **to the group** of human players, there are also two methods available:
|
||||
--
|
||||
-- - Use the method @{Tasking.CommandCenter#COMMANDCENTER.MessageToGroup}() to send a specific message to a group, with a given message display duration.
|
||||
-- - You can send a specific type of message using the method @{Tasking.CommandCenter#COMMANDCENTER.MessageTypeToGroup}().
|
||||
-- This will send a message of a specific type to the group, and as a result its display duration will be flexible according the message display time selection by the human player .
|
||||
--
|
||||
-- Messages are considered to be sometimes disturbing for human players, therefore, the settings menu provides the means to activate or deactivate messages.
|
||||
-- For more information on the message types and display timings that can be selected and configured using the menu, refer to the @{Core.Settings} menu description.
|
||||
--
|
||||
-- ## 4. Command center detailed methods.
|
||||
--
|
||||
-- Various methods are added to manage command centers.
|
||||
--
|
||||
-- ### 4.1. Naming and description.
|
||||
--
|
||||
-- There are 3 methods that can be used to retrieve the description of a command center:
|
||||
--
|
||||
-- - Use the method @{Tasking.CommandCenter#COMMANDCENTER.GetName}() to retrieve the name of the command center.
|
||||
-- This is the name given as part of the @{Tasking.CommandCenter#COMMANDCENTER.New}() constructor.
|
||||
-- The returned name using this method, is not to be used for message communication.
|
||||
--
|
||||
-- A textual description can be retrieved that provides the command center name to be used within message communication:
|
||||
--
|
||||
-- - @{Tasking.CommandCenter#COMMANDCENTER.GetShortText}() returns the command center name as `CC [CommandCenterName]`.
|
||||
-- - @{Tasking.CommandCenter#COMMANDCENTER.GetText}() returns the command center name as `Command Center [CommandCenterName]`.
|
||||
--
|
||||
-- ### 4.2. The coalition of the command center.
|
||||
--
|
||||
-- The method @{Tasking.CommandCenter#COMMANDCENTER.GetCoalition}() returns the coalition of the command center.
|
||||
-- The return value is an enumeration of the type @{DCS#coalition.side}, which contains the RED, BLUE and NEUTRAL coalition.
|
||||
--
|
||||
-- ### 4.3. The command center is a real object.
|
||||
--
|
||||
-- The command center must be represented by a live object within the DCS simulator. As a result, the command center
|
||||
-- can be a @{Wrapper.Unit}, a @{Wrapper.Group}, an @{Wrapper.Airbase} or a @{Wrapper.Static} object.
|
||||
--
|
||||
-- Using the method @{Tasking.CommandCenter#COMMANDCENTER.GetPositionable}() you retrieve the polymorphic positionable object representing
|
||||
-- the command center, but just be aware that you should be able to use the representable object derivation methods.
|
||||
--
|
||||
-- ### 5. Command center reports.
|
||||
--
|
||||
-- Because a command center giverns multiple missions, there are several reports available that are generated by command centers.
|
||||
-- These reports are generated using the following methods:
|
||||
--
|
||||
-- - @{Tasking.CommandCenter#COMMANDCENTER.ReportSummary}(): Creates a summary report of all missions governed by the command center.
|
||||
-- - @{Tasking.CommandCenter#COMMANDCENTER.ReportDetails}(): Creates a detailed report of all missions governed by the command center.
|
||||
-- - @{Tasking.CommandCenter#COMMANDCENTER.ReportMissionPlayers}(): Creates a report listing the players active at the missions governed by the command center.
|
||||
--
|
||||
-- ## 6. Reference Zones.
|
||||
--
|
||||
-- Command Centers may be aware of certain Reference Zones within the battleground. These Reference Zones can refer to
|
||||
-- known areas, recognizable buildings or sites, or any other point of interest.
|
||||
@@ -193,6 +270,8 @@ function COMMANDCENTER:New( CommandCenterPositionable, CommandCenterName )
|
||||
self:SetMenu()
|
||||
|
||||
_SETTINGS:SetSystemMenu( CommandCenterPositionable )
|
||||
|
||||
self:SetCommandMenu()
|
||||
|
||||
return self
|
||||
end
|
||||
@@ -349,6 +428,7 @@ end
|
||||
|
||||
--- Gets the commandcenter menu structure governed by the HQ command center.
|
||||
-- @param #COMMANDCENTER self
|
||||
-- @param Wrapper.Group#Group TaskGroup Task Group.
|
||||
-- @return Core.Menu#MENU_COALITION
|
||||
function COMMANDCENTER:GetMenu( TaskGroup )
|
||||
|
||||
@@ -362,10 +442,7 @@ function COMMANDCENTER:GetMenu( TaskGroup )
|
||||
self.CommandCenterMenus[TaskGroup] = CommandCenterMenu
|
||||
|
||||
if self.AutoAssignTasks == false then
|
||||
local AutoAssignTaskMenu = MENU_GROUP_COMMAND:New( TaskGroup, "Assign Task On", CommandCenterMenu, self.SetAutoAssignTasks, self, true ):SetTime(MenuTime):SetTag("AutoTask")
|
||||
local AssignTaskMenu = MENU_GROUP_COMMAND:New( TaskGroup, "Assign Task", CommandCenterMenu, self.AssignRandomTask, self, TaskGroup ):SetTime(MenuTime):SetTag("AutoTask")
|
||||
else
|
||||
local AutoAssignTaskMenu = MENU_GROUP_COMMAND:New( TaskGroup, "Assign Task Off", CommandCenterMenu, self.SetAutoAssignTasks, self, false ):SetTime(MenuTime):SetTag("AutoTask")
|
||||
end
|
||||
CommandCenterMenu:Remove( MenuTime, "AutoTask" )
|
||||
|
||||
@@ -397,10 +474,32 @@ function COMMANDCENTER:AssignRandomTask( TaskGroup )
|
||||
end
|
||||
|
||||
|
||||
--- Sets the menu of the command center.
|
||||
-- This command is called within the :New() method.
|
||||
-- @param #COMMANDCENTER self
|
||||
function COMMANDCENTER:SetCommandMenu()
|
||||
|
||||
local MenuTime = timer.getTime()
|
||||
|
||||
if self.CommandCenterPositionable and self.CommandCenterPositionable:IsInstanceOf(GROUP) then
|
||||
local CommandCenterText = self:GetText()
|
||||
local CommandCenterMenu = MENU_GROUP:New( self.CommandCenterPositionable, CommandCenterText ):SetTime(MenuTime)
|
||||
|
||||
if self.AutoAssignTasks == false then
|
||||
local AutoAssignTaskMenu = MENU_GROUP_COMMAND:New( self.CommandCenterPositionable, "Assign Task On", CommandCenterMenu, self.SetAutoAssignTasks, self, true ):SetTime(MenuTime):SetTag("AutoTask")
|
||||
else
|
||||
local AutoAssignTaskMenu = MENU_GROUP_COMMAND:New( self.CommandCenterPositionable, "Assign Task Off", CommandCenterMenu, self.SetAutoAssignTasks, self, false ):SetTime(MenuTime):SetTag("AutoTask")
|
||||
end
|
||||
CommandCenterMenu:Remove( MenuTime, "AutoTask" )
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
--- Automatically assigns tasks to all TaskGroups.
|
||||
-- @param #COMMANDCENTER self
|
||||
-- @param #boolean AutoAssign true for ON and false or nil for OFF.
|
||||
-- @return #COMMANDCENTER
|
||||
function COMMANDCENTER:SetAutoAssignTasks( AutoAssign )
|
||||
|
||||
self.AutoAssignTasks = AutoAssign or false
|
||||
@@ -417,6 +516,8 @@ function COMMANDCENTER:SetAutoAssignTasks( AutoAssign )
|
||||
else
|
||||
self:ScheduleStop( self.AssignTasks )
|
||||
end
|
||||
|
||||
self:SetCommandCenterMenu()
|
||||
|
||||
end
|
||||
|
||||
@@ -439,12 +540,13 @@ function COMMANDCENTER:AssignTasks()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
--- Get all the Groups active within the command center.
|
||||
-- @param #COMMANDCENTER self
|
||||
-- @return Core.Set#SET_GROUP
|
||||
-- @return Core.Set#SET_GROUP The set of groups active within the command center.
|
||||
function COMMANDCENTER:AddGroups()
|
||||
|
||||
local GroupSet = SET_GROUP:New()
|
||||
@@ -460,7 +562,7 @@ end
|
||||
|
||||
--- Checks of the TaskGroup has a Task.
|
||||
-- @param #COMMANDCENTER self
|
||||
-- @return #boolean
|
||||
-- @return #boolean When true, the TaskGroup has a Task, otherwise the returned value will be false.
|
||||
function COMMANDCENTER:IsGroupAssigned( TaskGroup )
|
||||
|
||||
local Assigned = false
|
||||
@@ -477,9 +579,9 @@ function COMMANDCENTER:IsGroupAssigned( TaskGroup )
|
||||
end
|
||||
|
||||
|
||||
--- Checks of the COMMANDCENTER has a GROUP.
|
||||
--- Checks of the command center has the given MissionGroup.
|
||||
-- @param #COMMANDCENTER self
|
||||
-- @param Wrapper.Group#GROUP
|
||||
-- @param Wrapper.Group#GROUP MissionGroup The group active within one of the missions governed by the command center.
|
||||
-- @return #boolean
|
||||
function COMMANDCENTER:HasGroup( MissionGroup )
|
||||
|
||||
@@ -496,37 +598,39 @@ function COMMANDCENTER:HasGroup( MissionGroup )
|
||||
return Has
|
||||
end
|
||||
|
||||
--- Send a CC message to the coalition of the CC.
|
||||
--- Let the command center send a Message to all players.
|
||||
-- @param #COMMANDCENTER self
|
||||
-- @param #string Message The message text.
|
||||
function COMMANDCENTER:MessageToAll( Message )
|
||||
|
||||
self:GetPositionable():MessageToAll( Message, 20, self:GetName() )
|
||||
|
||||
end
|
||||
|
||||
--- Send a CC message to a GROUP.
|
||||
--- Let the command center send a message to the MessageGroup.
|
||||
-- @param #COMMANDCENTER self
|
||||
-- @param #string Message
|
||||
-- @param Wrapper.Group#GROUP TaskGroup
|
||||
function COMMANDCENTER:MessageToGroup( Message, TaskGroup )
|
||||
-- @param #string Message The message text.
|
||||
-- @param Wrapper.Group#GROUP MessageGroup The group to receive the message.
|
||||
function COMMANDCENTER:MessageToGroup( Message, MessageGroup )
|
||||
|
||||
self:GetPositionable():MessageToGroup( Message, 15, TaskGroup, self:GetShortText() )
|
||||
self:GetPositionable():MessageToGroup( Message, 15, MessageGroup, self:GetShortText() )
|
||||
|
||||
end
|
||||
|
||||
--- Send a CC message of a specified type to a GROUP.
|
||||
--- Let the command center send a message to the MessageGroup.
|
||||
-- @param #COMMANDCENTER self
|
||||
-- @param #string Message
|
||||
-- @param Wrapper.Group#GROUP TaskGroup
|
||||
-- @param #string Message The message text.
|
||||
-- @param Wrapper.Group#GROUP MessageGroup The group to receive the message.
|
||||
-- @param Core.Message#MESSAGE.MessageType MessageType The type of the message, resulting in automatic time duration and prefix of the message.
|
||||
function COMMANDCENTER:MessageTypeToGroup( Message, TaskGroup, MessageType )
|
||||
function COMMANDCENTER:MessageTypeToGroup( Message, MessageGroup, MessageType )
|
||||
|
||||
self:GetPositionable():MessageTypeToGroup( Message, MessageType, TaskGroup, self:GetShortText() )
|
||||
self:GetPositionable():MessageTypeToGroup( Message, MessageType, MessageGroup, self:GetShortText() )
|
||||
|
||||
end
|
||||
|
||||
--- Send a CC message to the coalition of the CC.
|
||||
--- Let the command center send a message to the coalition of the command center.
|
||||
-- @param #COMMANDCENTER self
|
||||
-- @param #string Message The message text.
|
||||
function COMMANDCENTER:MessageToCoalition( Message )
|
||||
|
||||
local CCCoalition = self:GetPositionable():GetCoalition()
|
||||
@@ -537,9 +641,9 @@ function COMMANDCENTER:MessageToCoalition( Message )
|
||||
end
|
||||
|
||||
|
||||
--- Send a CC message of a specified type to the coalition of the CC.
|
||||
--- Let the command center send a message of a specified type to the coalition of the command center.
|
||||
-- @param #COMMANDCENTER self
|
||||
-- @param #string Message The message.
|
||||
-- @param #string Message The message text.
|
||||
-- @param Core.Message#MESSAGE.MessageType MessageType The type of the message, resulting in automatic time duration and prefix of the message.
|
||||
function COMMANDCENTER:MessageTypeToCoalition( Message, MessageType )
|
||||
|
||||
@@ -551,9 +655,10 @@ function COMMANDCENTER:MessageTypeToCoalition( Message, MessageType )
|
||||
end
|
||||
|
||||
|
||||
--- Report the status of all MISSIONs to a GROUP.
|
||||
--- Let the command center send a report of the status of all missions to a group.
|
||||
-- Each Mission is listed, with an indication how many Tasks are still to be completed.
|
||||
-- @param #COMMANDCENTER self
|
||||
-- @param Wrapper.Group#GROUP ReportGroup The group to receive the report.
|
||||
function COMMANDCENTER:ReportSummary( ReportGroup )
|
||||
self:F( ReportGroup )
|
||||
|
||||
@@ -565,15 +670,16 @@ function COMMANDCENTER:ReportSummary( ReportGroup )
|
||||
|
||||
for MissionID, Mission in pairs( self.Missions ) do
|
||||
local Mission = Mission -- Tasking.Mission#MISSION
|
||||
Report:Add( " - " .. Mission:ReportSummary() )
|
||||
Report:Add( " - " .. Mission:ReportSummary( ReportGroup ) )
|
||||
end
|
||||
|
||||
self:MessageToGroup( Report:Text(), ReportGroup )
|
||||
end
|
||||
|
||||
--- Report the players of all MISSIONs to a GROUP.
|
||||
--- Let the command center send a report of the players of all missions to a group.
|
||||
-- Each Mission is listed, with an indication how many Tasks are still to be completed.
|
||||
-- @param #COMMANDCENTER self
|
||||
-- @param Wrapper.Group#GROUP ReportGroup The group to receive the report.
|
||||
function COMMANDCENTER:ReportMissionsPlayers( ReportGroup )
|
||||
self:F( ReportGroup )
|
||||
|
||||
@@ -589,9 +695,11 @@ function COMMANDCENTER:ReportMissionsPlayers( ReportGroup )
|
||||
self:MessageToGroup( Report:Text(), ReportGroup )
|
||||
end
|
||||
|
||||
--- Report the status of a Task to a Group.
|
||||
--- Let the command center send a report of the status of a task to a group.
|
||||
-- Report the details of a Mission, listing the Mission, and all the Task details.
|
||||
-- @param #COMMANDCENTER self
|
||||
-- @param Wrapper.Group#GROUP ReportGroup The group to receive the report.
|
||||
-- @param Tasking.Task#TASK Task The task to be reported.
|
||||
function COMMANDCENTER:ReportDetails( ReportGroup, Task )
|
||||
self:F( ReportGroup )
|
||||
|
||||
|
||||
@@ -1,38 +1,36 @@
|
||||
--- This module contains the DETECTION_MANAGER class and derived classes.
|
||||
--- **Tasking** - This module contains the DETECTION_MANAGER class and derived classes.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- 1) @{DetectionManager#DETECTION_MANAGER} class, extends @{Fsm#FSM}
|
||||
-- ===
|
||||
-- The @{DetectionManager#DETECTION_MANAGER} class defines the core functions to report detected objects to groups.
|
||||
-- The @{#DETECTION_MANAGER} class defines the core functions to report detected objects to groups.
|
||||
-- Reportings can be done in several manners, and it is up to the derived classes if DETECTION_MANAGER to model the reporting behaviour.
|
||||
--
|
||||
-- 1.1) DETECTION_MANAGER constructor:
|
||||
-- -----------------------------------
|
||||
-- * @{DetectionManager#DETECTION_MANAGER.New}(): Create a new DETECTION_MANAGER instance.
|
||||
-- * @{#DETECTION_MANAGER.New}(): Create a new DETECTION_MANAGER instance.
|
||||
--
|
||||
-- 1.2) DETECTION_MANAGER reporting:
|
||||
-- ---------------------------------
|
||||
-- Derived DETECTION_MANAGER classes will reports detected units using the method @{DetectionManager#DETECTION_MANAGER.ReportDetected}(). This method implements polymorphic behaviour.
|
||||
-- Derived DETECTION_MANAGER classes will reports detected units using the method @{#DETECTION_MANAGER.ReportDetected}(). This method implements polymorphic behaviour.
|
||||
--
|
||||
-- The time interval in seconds of the reporting can be changed using the methods @{DetectionManager#DETECTION_MANAGER.SetRefreshTimeInterval}().
|
||||
-- To control how long a reporting message is displayed, use @{DetectionManager#DETECTION_MANAGER.SetReportDisplayTime}().
|
||||
-- Derived classes need to implement the method @{DetectionManager#DETECTION_MANAGER.GetReportDisplayTime}() to use the correct display time for displayed messages during a report.
|
||||
-- The time interval in seconds of the reporting can be changed using the methods @{#DETECTION_MANAGER.SetRefreshTimeInterval}().
|
||||
-- To control how long a reporting message is displayed, use @{#DETECTION_MANAGER.SetReportDisplayTime}().
|
||||
-- Derived classes need to implement the method @{#DETECTION_MANAGER.GetReportDisplayTime}() to use the correct display time for displayed messages during a report.
|
||||
--
|
||||
-- Reporting can be started and stopped using the methods @{DetectionManager#DETECTION_MANAGER.StartReporting}() and @{DetectionManager#DETECTION_MANAGER.StopReporting}() respectively.
|
||||
-- If an ad-hoc report is requested, use the method @{DetectionManager#DETECTION_MANAGER#ReportNow}().
|
||||
-- Reporting can be started and stopped using the methods @{#DETECTION_MANAGER.StartReporting}() and @{#DETECTION_MANAGER.StopReporting}() respectively.
|
||||
-- If an ad-hoc report is requested, use the method @{#DETECTION_MANAGER#ReportNow}().
|
||||
--
|
||||
-- The default reporting interval is every 60 seconds. The reporting messages are displayed 15 seconds.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- 2) @{DetectionManager#DETECTION_REPORTING} class, extends @{DetectionManager#DETECTION_MANAGER}
|
||||
-- 2) @{#DETECTION_REPORTING} class, extends @{#DETECTION_MANAGER}
|
||||
-- ===
|
||||
-- The @{DetectionManager#DETECTION_REPORTING} class implements detected units reporting. Reporting can be controlled using the reporting methods available in the @{DetectionManager#DETECTION_MANAGER} class.
|
||||
-- The @{#DETECTION_REPORTING} class implements detected units reporting. Reporting can be controlled using the reporting methods available in the @{Tasking.DetectionManager#DETECTION_MANAGER} class.
|
||||
--
|
||||
-- 2.1) DETECTION_REPORTING constructor:
|
||||
-- -------------------------------
|
||||
-- The @{DetectionManager#DETECTION_REPORTING.New}() method creates a new DETECTION_REPORTING instance.
|
||||
-- The @{#DETECTION_REPORTING.New}() method creates a new DETECTION_REPORTING instance.
|
||||
--
|
||||
--
|
||||
-- ===
|
||||
@@ -40,15 +38,18 @@
|
||||
-- ### Contributions: Mechanist, Prof_Hilactic, FlightControl - Concept & Testing
|
||||
-- ### Author: FlightControl - Framework Design & Programming
|
||||
--
|
||||
-- @module DetectionManager
|
||||
-- @module Tasking.DetectionManager
|
||||
-- @image Task_Detection_Manager.JPG
|
||||
|
||||
do -- DETECTION MANAGER
|
||||
|
||||
--- DETECTION_MANAGER class.
|
||||
-- @type DETECTION_MANAGER
|
||||
-- @field Set#SET_GROUP SetGroup The groups to which the FAC will report to.
|
||||
--- @type DETECTION_MANAGER
|
||||
-- @field Core.Set#SET_GROUP SetGroup The groups to which the FAC will report to.
|
||||
-- @field Functional.Detection#DETECTION_BASE Detection The DETECTION_BASE object that is used to report the detected objects.
|
||||
-- @extends Core.Fsm#FSM
|
||||
|
||||
--- DETECTION_MANAGER class.
|
||||
-- @field #DETECTION_MANAGER
|
||||
DETECTION_MANAGER = {
|
||||
ClassName = "DETECTION_MANAGER",
|
||||
SetGroup = nil,
|
||||
@@ -57,7 +58,7 @@ do -- DETECTION MANAGER
|
||||
|
||||
--- FAC constructor.
|
||||
-- @param #DETECTION_MANAGER self
|
||||
-- @param Set#SET_GROUP SetGroup
|
||||
-- @param Core.Set#SET_GROUP SetGroup
|
||||
-- @param Functional.Detection#DETECTION_BASE Detection
|
||||
-- @return #DETECTION_MANAGER self
|
||||
function DETECTION_MANAGER:New( SetGroup, Detection )
|
||||
@@ -122,6 +123,48 @@ do -- DETECTION MANAGER
|
||||
-- @function [parent=#DETECTION_MANAGER] __Stop
|
||||
-- @param #DETECTION_MANAGER self
|
||||
-- @param #number Delay
|
||||
|
||||
self:AddTransition( "Started", "Success", "Started" )
|
||||
|
||||
--- Success Handler OnAfter for DETECTION_MANAGER
|
||||
-- @function [parent=#DETECTION_MANAGER] OnAfterSuccess
|
||||
-- @param #DETECTION_MANAGER self
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @param Tasking.Task#TASK Task
|
||||
|
||||
|
||||
self:AddTransition( "Started", "Failed", "Started" )
|
||||
|
||||
--- Failed Handler OnAfter for DETECTION_MANAGER
|
||||
-- @function [parent=#DETECTION_MANAGER] OnAfterFailed
|
||||
-- @param #DETECTION_MANAGER self
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @param Tasking.Task#TASK Task
|
||||
|
||||
|
||||
self:AddTransition( "Started", "Aborted", "Started" )
|
||||
|
||||
--- Aborted Handler OnAfter for DETECTION_MANAGER
|
||||
-- @function [parent=#DETECTION_MANAGER] OnAfterAborted
|
||||
-- @param #DETECTION_MANAGER self
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @param Tasking.Task#TASK Task
|
||||
|
||||
self:AddTransition( "Started", "Cancelled", "Started" )
|
||||
|
||||
--- Cancelled Handler OnAfter for DETECTION_MANAGER
|
||||
-- @function [parent=#DETECTION_MANAGER] OnAfterCancelled
|
||||
-- @param #DETECTION_MANAGER self
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @param Tasking.Task#TASK Task
|
||||
|
||||
|
||||
self:AddTransition( "Started", "Report", "Started" )
|
||||
@@ -175,7 +218,7 @@ do -- DETECTION MANAGER
|
||||
return self._ReportDisplayTime
|
||||
end
|
||||
|
||||
--- Reports the detected items to the @{Set#SET_GROUP}.
|
||||
--- Reports the detected items to the @{Core.Set#SET_GROUP}.
|
||||
-- @param #DETECTION_MANAGER self
|
||||
-- @param Functional.Detection#DETECTION_BASE Detection
|
||||
-- @return #DETECTION_MANAGER self
|
||||
@@ -191,7 +234,7 @@ do -- DETECTION_REPORTING
|
||||
|
||||
--- DETECTION_REPORTING class.
|
||||
-- @type DETECTION_REPORTING
|
||||
-- @field Set#SET_GROUP SetGroup The groups to which the FAC will report to.
|
||||
-- @field Core.Set#SET_GROUP SetGroup The groups to which the FAC will report to.
|
||||
-- @field Functional.Detection#DETECTION_BASE Detection The DETECTION_BASE object that is used to report the detected objects.
|
||||
-- @extends #DETECTION_MANAGER
|
||||
DETECTION_REPORTING = {
|
||||
@@ -201,7 +244,7 @@ do -- DETECTION_REPORTING
|
||||
|
||||
--- DETECTION_REPORTING constructor.
|
||||
-- @param #DETECTION_REPORTING self
|
||||
-- @param Set#SET_GROUP SetGroup
|
||||
-- @param Core.Set#SET_GROUP SetGroup
|
||||
-- @param Functional.Detection#DETECTION_AREAS Detection
|
||||
-- @return #DETECTION_REPORTING self
|
||||
function DETECTION_REPORTING:New( SetGroup, Detection )
|
||||
@@ -215,7 +258,7 @@ do -- DETECTION_REPORTING
|
||||
|
||||
--- Creates a string of the detected items in a @{Detection}.
|
||||
-- @param #DETECTION_MANAGER self
|
||||
-- @param Set#SET_UNIT DetectedSet The detected Set created by the @{Detection#DETECTION_BASE} object.
|
||||
-- @param Core.Set#SET_UNIT DetectedSet The detected Set created by the @{Functional.Detection#DETECTION_BASE} object.
|
||||
-- @return #DETECTION_MANAGER self
|
||||
function DETECTION_REPORTING:GetDetectedItemsText( DetectedSet )
|
||||
self:F2()
|
||||
@@ -245,10 +288,10 @@ do -- DETECTION_REPORTING
|
||||
|
||||
|
||||
|
||||
--- Reports the detected items to the @{Set#SET_GROUP}.
|
||||
--- Reports the detected items to the @{Core.Set#SET_GROUP}.
|
||||
-- @param #DETECTION_REPORTING self
|
||||
-- @param Wrapper.Group#GROUP Group The @{Group} object to where the report needs to go.
|
||||
-- @param Functional.Detection#DETECTION_AREAS Detection The detection created by the @{Detection#DETECTION_BASE} object.
|
||||
-- @param Wrapper.Group#GROUP Group The @{Wrapper.Group} object to where the report needs to go.
|
||||
-- @param Functional.Detection#DETECTION_AREAS Detection The detection created by the @{Functional.Detection#DETECTION_BASE} object.
|
||||
-- @return #boolean Return true if you want the reporting to continue... false will cancel the reporting loop.
|
||||
function DETECTION_REPORTING:ProcessDetected( Group, Detection )
|
||||
self:F2( Group )
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
--- **Tasking** -- A MISSION is the main owner of a Mission orchestration within MOOSE.
|
||||
--- **Tasking** -- A mission models a goal to be achieved through the execution and completion of tasks by human players.
|
||||
--
|
||||
-- **Features:**
|
||||
--
|
||||
-- * A mission has a goal to be achieved, through the execution and completion of tasks of different categories by human players.
|
||||
-- * A mission manages these tasks.
|
||||
-- * A mission has a state, that indicates the fase of the mission.
|
||||
-- * A mission has a menu structure, that facilitates mission reports and tasking menus.
|
||||
-- * A mission can assign a task to a player.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
@@ -8,14 +16,109 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module Mission
|
||||
-- @module Tasking.Mission
|
||||
-- @image Task_Mission.JPG
|
||||
|
||||
--- The MISSION class
|
||||
-- @type MISSION
|
||||
--- @type MISSION
|
||||
-- @field #MISSION.Clients _Clients
|
||||
-- @field Core.Menu#MENU_COALITION MissionMenu
|
||||
-- @field #string MissionBriefing
|
||||
-- @extends Core.Fsm#FSM
|
||||
|
||||
--- Models goals to be achieved and can contain multiple tasks to be executed to achieve the goals.
|
||||
--
|
||||
-- A mission contains multiple tasks and can be of different task types.
|
||||
-- These tasks need to be assigned to human players to be executed.
|
||||
--
|
||||
-- A mission can have multiple states, which will evolve as the mission progresses during the DCS simulation.
|
||||
--
|
||||
-- - **IDLE**: The mission is defined, but not started yet. No task has yet been joined by a human player as part of the mission.
|
||||
-- - **ENGAGED**: The mission is ongoing, players have joined tasks to be executed.
|
||||
-- - **COMPLETED**: The goals of the mission has been successfully reached, and the mission is flagged as completed.
|
||||
-- - **FAILED**: For a certain reason, the goals of the mission has not been reached, and the mission is flagged as failed.
|
||||
-- - **HOLD**: The mission was enaged, but for some reason it has been put on hold.
|
||||
--
|
||||
-- Note that a mission goals need to be checked by a goal check trigger: @{#MISSION.OnBeforeMissionGoals}(), which may return false if the goal has not been reached.
|
||||
-- This goal is checked automatically by the mission object every x seconds.
|
||||
--
|
||||
-- - @{#MISSION.Start}() or @{#MISSION.__Start}() will start the mission, and will bring it from **IDLE** state to **ENGAGED** state.
|
||||
-- - @{#MISSION.Stop}() or @{#MISSION.__Stop}() will stop the mission, and will bring it from **ENGAGED** state to **IDLE** state.
|
||||
-- - @{#MISSION.Complete}() or @{#MISSION.__Complete}() will complete the mission, and will bring the mission state to **COMPLETED**.
|
||||
-- Note that the mission must be in state **ENGAGED** to be able to complete the mission.
|
||||
-- - @{#MISSION.Fail}() or @{#MISSION.__Fail}() will fail the mission, and will bring the mission state to **FAILED**.
|
||||
-- Note that the mission must be in state **ENGAGED** to be able to fail the mission.
|
||||
-- - @{#MISSION.Hold}() or @{#MISSION.__Hold}() will hold the mission, and will bring the mission state to **HOLD**.
|
||||
-- Note that the mission must be in state **ENGAGED** to be able to hold the mission.
|
||||
-- Re-engage the mission using the engage trigger.
|
||||
--
|
||||
-- The following sections provide an overview of the most important methods that can be used as part of a mission object.
|
||||
-- Note that the @{Tasking.CommandCenter} system is using most of these methods to manage the missions in its system.
|
||||
--
|
||||
-- ## 1. Create a mission object.
|
||||
--
|
||||
-- - @{#MISSION.New}(): Creates a new MISSION object.
|
||||
--
|
||||
-- ## 2. Mission task management.
|
||||
--
|
||||
-- Missions maintain tasks, which can be added or removed, or enquired.
|
||||
--
|
||||
-- - @{#MISSION.AddTask}(): Adds a task to the mission.
|
||||
-- - @{#MISSION.RemoveTask}(): Removes a task from the mission.
|
||||
--
|
||||
-- ## 3. Mission detailed methods.
|
||||
--
|
||||
-- Various methods are added to manage missions.
|
||||
--
|
||||
-- ### 3.1. Naming and description.
|
||||
--
|
||||
-- There are several methods that can be used to retrieve the properties of a mission:
|
||||
--
|
||||
-- - Use the method @{#MISSION.GetName}() to retrieve the name of the mission.
|
||||
-- This is the name given as part of the @{#MISSION.New}() constructor.
|
||||
--
|
||||
-- A textual description can be retrieved that provides the mission name to be used within message communication:
|
||||
--
|
||||
-- - @{#MISSION.GetShortText}() returns the mission name as `Mission "MissionName"`.
|
||||
-- - @{#MISSION.GetText}() returns the mission name as `Mission "MissionName (MissionPriority)"`. A longer version including the priority text of the mission.
|
||||
--
|
||||
-- ### 3.2. Get task information.
|
||||
--
|
||||
-- - @{#MISSION.GetTasks}(): Retrieves a list of the tasks controlled by the mission.
|
||||
-- - @{#MISSION.GetTask}(): Retrieves a specific task controlled by the mission.
|
||||
-- - @{#MISSION.GetTasksRemaining}(): Retrieve a list of the tasks that aren't finished or failed, and are governed by the mission.
|
||||
-- - @{#MISSION.GetGroupTasks}(): Retrieve a list of the tasks that can be asigned to a @{Wrapper.Group}.
|
||||
-- - @{#MISSION.GetTaskTypes}(): Retrieve a list of the different task types governed by the mission.
|
||||
--
|
||||
-- ### 3.3. Get the command center.
|
||||
--
|
||||
-- - @{#MISSION.GetCommandCenter}(): Retrieves the @{Tasking.CommandCenter} governing the mission.
|
||||
--
|
||||
-- ### 3.4. Get the groups active in the mission as a @{Core.Set}.
|
||||
--
|
||||
-- - @{#MISSION.GetGroups}(): Retrieves a @{Core.Set#SET_GROUP} of all the groups active in the mission (as part of the tasks).
|
||||
--
|
||||
-- ### 3.5. Get the names of the players.
|
||||
--
|
||||
-- - @{#MISSION.GetPlayerNames}(): Retrieves the list of the players that were active within th mission..
|
||||
--
|
||||
-- ## 4. Menu management.
|
||||
--
|
||||
-- A mission object is able to manage its own menu structure. Use the @{#MISSION.GetMenu}() and @{#MISSION.SetMenu}() to manage the underlying submenu
|
||||
-- structure managing the tasks of the mission.
|
||||
--
|
||||
-- ## 5. Reporting management.
|
||||
--
|
||||
-- Several reports can be generated for a mission, and will return a text string that can be used to display using the @{Core.Message} system.
|
||||
--
|
||||
-- - @{#MISSION.ReportBriefing}(): Generates the briefing for the mission.
|
||||
-- - @{#MISSION.ReportOverview}(): Generates an overview of the tasks and status of the mission.
|
||||
-- - @{#MISSION.ReportDetails}(): Generates a detailed report of the tasks of the mission.
|
||||
-- - @{#MISSION.ReportSummary}(): Generates a summary report of the tasks of the mission.
|
||||
-- - @{#MISSION.ReportPlayersPerTask}(): Generates a report showing the active players per task.
|
||||
-- - @{#MISSION.ReportPlayersProgress}(): Generates a report showing the task progress per player.
|
||||
--
|
||||
--
|
||||
-- @field #MISSION
|
||||
MISSION = {
|
||||
ClassName = "MISSION",
|
||||
Name = "",
|
||||
@@ -26,10 +129,10 @@ MISSION = {
|
||||
--- This is the main MISSION declaration method. Each Mission is like the master or a Mission orchestration between, Clients, Tasks, Stages etc.
|
||||
-- @param #MISSION self
|
||||
-- @param Tasking.CommandCenter#COMMANDCENTER CommandCenter
|
||||
-- @param #string MissionName is the name of the mission. This name will be used to reference the status of each mission by the players.
|
||||
-- @param #string MissionPriority is a string indicating the "priority" of the Mission. f.e. "Primary", "Secondary" or "First", "Second". It is free format and up to the Mission designer to choose. There are no rules behind this field.
|
||||
-- @param #string MissionBriefing is a string indicating the mission briefing to be shown when a player joins a @{CLIENT}.
|
||||
-- @param #string MissionCoalition is a string indicating the coalition or party to which this mission belongs to. It is free format and can be chosen freely by the mission designer. Note that this field is not to be confused with the coalition concept of the ME. Examples of a Mission Coalition could be "NATO", "CCCP", "Intruders", "Terrorists"...
|
||||
-- @param #string MissionName Name of the mission. This name will be used to reference the status of each mission by the players.
|
||||
-- @param #string MissionPriority String indicating the "priority" of the Mission. e.g. "Primary", "Secondary". It is free format and up to the Mission designer to choose. There are no rules behind this field.
|
||||
-- @param #string MissionBriefing String indicating the mission briefing to be shown when a player joins a @{CLIENT}.
|
||||
-- @param DCS#coaliton.side MissionCoalition Side of the coalition, i.e. and enumerator @{#DCS.coalition.side} corresponding to RED, BLUE or NEUTRAL.
|
||||
-- @return #MISSION self
|
||||
function MISSION:New( CommandCenter, MissionName, MissionPriority, MissionBriefing, MissionCoalition )
|
||||
|
||||
@@ -458,7 +561,7 @@ do -- Group Assignment
|
||||
end
|
||||
|
||||
|
||||
--- Set @{Group} assigned to the @{Mission}.
|
||||
--- Set @{Wrapper.Group} assigned to the @{Mission}.
|
||||
-- @param #MISSION self
|
||||
-- @param Wrapper.Group#GROUP MissionGroup
|
||||
-- @return #MISSION
|
||||
@@ -473,7 +576,7 @@ do -- Group Assignment
|
||||
return self
|
||||
end
|
||||
|
||||
--- Clear the @{Group} assignment from the @{Mission}.
|
||||
--- Clear the @{Wrapper.Group} assignment from the @{Mission}.
|
||||
-- @param #MISSION self
|
||||
-- @param Wrapper.Group#GROUP MissionGroup
|
||||
-- @return #MISSION
|
||||
@@ -508,13 +611,14 @@ function MISSION:RemoveTaskMenu( Task )
|
||||
end
|
||||
|
||||
|
||||
--- Gets the root mission menu for the TaskGroup.
|
||||
--- Gets the root mission menu for the TaskGroup. Obsolete?! Originally no reference to TaskGroup parameter!
|
||||
-- @param #MISSION self
|
||||
-- @param Wrapper.Group#GROUP TaskGroup Task group.
|
||||
-- @return Core.Menu#MENU_COALITION self
|
||||
function MISSION:GetRootMenu( TaskGroup ) -- R2.2
|
||||
|
||||
local CommandCenter = self:GetCommandCenter()
|
||||
local CommandCenterMenu = CommandCenter:GetMenu()
|
||||
local CommandCenterMenu = CommandCenter:GetMenu( TaskGroup )
|
||||
|
||||
local MissionName = self:GetText()
|
||||
--local MissionMenu = CommandCenterMenu:GetMenu( MissionName )
|
||||
@@ -526,6 +630,7 @@ end
|
||||
|
||||
--- Gets the mission menu for the TaskGroup.
|
||||
-- @param #MISSION self
|
||||
-- @param Wrapper.Group#GROUP TaskGroup Task group.
|
||||
-- @return Core.Menu#MENU_COALITION self
|
||||
function MISSION:GetMenu( TaskGroup ) -- R2.1 -- Changed Menu Structure
|
||||
|
||||
|
||||
@@ -1,4 +1,208 @@
|
||||
--- **Tasking** -- This module contains the TASK class, the main engine to run human taskings.
|
||||
--- **Tasking** -- A task object governs the main engine to administer human taskings.
|
||||
--
|
||||
-- **Features:**
|
||||
--
|
||||
-- * A base class for other task classes filling in the details and making a concrete task process.
|
||||
-- * Manage the overall task execution, following-up the progression made by the pilots and actors.
|
||||
-- * Provide a mechanism to set a task status, depending on the progress made within the task.
|
||||
-- * Manage a task briefing.
|
||||
-- * Manage the players executing the task.
|
||||
-- * Manage the task menu system.
|
||||
-- * Manage the task goal and scoring.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- # 1) Tasking from a player perspective.
|
||||
--
|
||||
-- Tasking can be controlled by using the "other" menu in the radio menu of the player group.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- ## 1.1) Command Centers govern multiple Missions.
|
||||
--
|
||||
-- Depending on the tactical situation, your coalition may have one (or multiple) command center(s).
|
||||
-- These command centers govern one (or multiple) mission(s).
|
||||
--
|
||||
-- For each command center, there will be a separate **Command Center Menu** that focuses on the missions governed by that command center.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- In the above example menu structure, there is one command center with the name **`[Lima]`**.
|
||||
-- The command center has one @{Tasking.Mission}, named **`"Overlord"`** with **`High`** priority.
|
||||
--
|
||||
-- ## 1.2) Missions govern multiple Tasks.
|
||||
--
|
||||
-- A mission has a mission goal to be achieved by the players within the coalition.
|
||||
-- The mission goal is actually dependent on the tactical situation of the overall battlefield and the conditions set to achieve the goal.
|
||||
-- So a mission can be much more than just shoot stuff ... It can be a combination of different conditions or events to complete a mission goal.
|
||||
--
|
||||
-- A mission can be in a specific state during the simulation run. For more information about these states, please check the @{Tasking.Mission} section.
|
||||
--
|
||||
-- To achieve the mission goal, a mission administers @{Tasking.Task}s that are set to achieve the mission goal by the human players.
|
||||
-- Each of these tasks can be **dynamically created** using a task dispatcher, or **coded** by the mission designer.
|
||||
-- Each mission has a separate **Mission Menu**, that focuses on the administration of these tasks.
|
||||
--
|
||||
-- On top, a mission has a mission briefing, can help to allocate specific points of interest on the map, and provides various reports.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- The above shows a mission menu in detail of **`"Overlord"`**.
|
||||
--
|
||||
-- The two other menus are related to task assignment. Which will be detailed later.
|
||||
--
|
||||
-- ### 1.2.1) Mission briefing.
|
||||
--
|
||||
-- The task briefing will show a message containing a description of the mission goal, and other tactical information.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- ### 1.2.2) Mission Map Locations.
|
||||
--
|
||||
-- Various points of interest as part of the mission can be indicated on the map using the *Mark Task Locations on Map* menu.
|
||||
-- As a result, the map will contain various points of interest for the player (group).
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- ### 1.2.3) Mission Task Reports.
|
||||
--
|
||||
-- Various reports can be generated on the status of each task governed within the mission.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- The Task Overview Report will show each task, with its task status and a short coordinate information.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- The other Task Menus will show for each task more details, for example here the planned tasks report.
|
||||
-- Note that the order of the tasks are shortest distance first to the unit position seated by the player.
|
||||
--
|
||||
-- ### 1.2.4) Mission Statistics.
|
||||
--
|
||||
-- Various statistics can be displayed regarding the mission.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- A statistic report on the progress of the mission. Each task achievement will increase the %-tage to 100% as a goal to complete the task.
|
||||
--
|
||||
-- ## 1.3) Join a Task.
|
||||
--
|
||||
-- The mission menu contains a very important option, that is to join a task governed within the mission.
|
||||
-- In order to join a task, select the **Join Planned Task** menu, and a new menu will be given.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- A mission governs multiple tasks, as explained earlier. Each task is of a certain task type.
|
||||
-- This task type was introduced to have some sort of task classification system in place for the player.
|
||||
-- A short acronym is shown that indicates the task type. The meaning of each acronym can be found in the task types explanation.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- When the player selects a task type, a list of the available tasks of that type are listed...
|
||||
-- In this case the **`SEAD`** task type was selected and a list of available **`SEAD`** tasks can be selected.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- A new list of menu options are now displayed that allow to join the task selected, but also to obtain first some more information on the task.
|
||||
--
|
||||
-- ### 1.3.1) Report Task Details.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- When selected, a message is displayed that shows detailed information on the task, like the coordinate, enemy target information, threat level etc.
|
||||
--
|
||||
-- ### 1.3.2) Mark Task Location on Map.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- When selected, the target location on the map is indicated with specific information on the task.
|
||||
--
|
||||
-- ### 1.3.3) Join Task.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- By joining a task, the player will indicate that the task is assigned to him, and the task is started.
|
||||
-- The Command Center will communicate several task details to the player and the coalition of the player.
|
||||
--
|
||||
-- ## 1.4) Task Control and Actions.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- When a player has joined a task, a **Task Action Menu** is available to be used by the player.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- The task action menu contains now menu items specific to the task, but also one generic menu item, which is to control the task.
|
||||
-- This **Task Control Menu** allows to display again the task details and the task map location information.
|
||||
-- But it also allows to abort a task!
|
||||
--
|
||||
-- Depending on the task type, the task action menu can contain more menu items which are specific to the task.
|
||||
-- For example, cargo transportation tasks will contain various additional menu items to select relevant cargo coordinates,
|
||||
-- or to load/unload cargo.
|
||||
--
|
||||
-- ## 1.5) Automatic task assignment.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- When we take back the command center menu, you see two addtional **Assign Task** menu items.
|
||||
-- The menu **Assign Task On** will automatically allocate a task to the player.
|
||||
-- After the selection of this menu, the menu will change into **Assign Task Off**,
|
||||
-- and will need to be selected again by the player to switch of the automatic task assignment.
|
||||
--
|
||||
-- The other option is to select **Assign Task**, which will assign a new random task to the player.
|
||||
--
|
||||
-- When a task is automatically assigned to a player, the task needs to be confirmed as accepted within 30 seconds.
|
||||
-- If this is not the case, the task will be cancelled automatically, and a new random task will be assigned to the player.
|
||||
-- This will continue to happen until the player accepts the task or switches off the automatic task assignment process.
|
||||
--
|
||||
-- The player can accept the task using the menu **Confirm Task Acceptance** ...
|
||||
--
|
||||
-- ## 1.6) Task states.
|
||||
--
|
||||
-- A task has a state, reflecting the progress or completion status of the task:
|
||||
--
|
||||
-- - **Planned**: Expresses that the task is created, but not yet in execution and is not assigned yet to a pilot.
|
||||
-- - **Assigned**: Expresses that the task is assigned to a group of pilots, and that the task is in execution mode.
|
||||
-- - **Success**: Expresses the successful execution and finalization of the task.
|
||||
-- - **Failed**: Expresses the failure of a task.
|
||||
-- - **Abort**: Expresses that the task is aborted by by the player using the abort menu.
|
||||
-- - **Cancelled**: Expresses that the task is cancelled by HQ or through a logical situation where a cancellation of the task is required.
|
||||
--
|
||||
-- ### 1.6.1) Task progress.
|
||||
--
|
||||
-- The task governor takes care of the **progress** and **completion** of the task **goal(s)**.
|
||||
-- Tasks are executed by **human pilots** and actors within a DCS simulation.
|
||||
-- Pilots can use a **menu system** to engage or abort a task, and provides means to
|
||||
-- understand the **task briefing** and goals, and the relevant **task locations** on the map and
|
||||
-- obtain **various reports** related to the task.
|
||||
--
|
||||
-- ### 1.6.2) Task completion.
|
||||
--
|
||||
-- As the task progresses, the **task status** will change over time, from Planned state to Completed state.
|
||||
-- **Multiple pilots** can execute the same task, as such, the tasking system provides a **co-operative model** for joint task execution.
|
||||
-- Depending on the task progress, a **scoring** can be allocated to award pilots of the achievements made.
|
||||
-- The scoring is fully flexible, and different levels of awarding can be provided depending on the task type and complexity.
|
||||
--
|
||||
-- A normal flow of task status would evolve from the **Planned** state, to the **Assigned** state ending either in a **Success** or a **Failed** state.
|
||||
--
|
||||
-- Planned -> Assigned -> Success
|
||||
-- -> Failed
|
||||
-- -> Cancelled
|
||||
--
|
||||
-- The state completion is by default set to **Success**, if the goals of the task have been reached, but can be overruled by a goal method.
|
||||
--
|
||||
-- Depending on the tactical situation, a task can be **Cancelled** by the mission governer.
|
||||
-- It is actually the mission designer who has the flexibility to decide at which conditions a task would be set to **Success**, **Failed** or **Cancelled**.
|
||||
-- This decision all depends on the task goals, and the phase/evolution of the task conditions that would accomplish the goals.
|
||||
--
|
||||
-- For example, if the task goal is to merely destroy a target, and the target is mid-mission destroyed by another event than the pilot destroying the target,
|
||||
-- the task goal could be set to **Failed**, or .. **Cancelled** ...
|
||||
-- However, it could very well be also acceptable that the task would be flagged as **Success**.
|
||||
--
|
||||
-- The tasking mechanism governs beside the progress also a scoring mechanism, and in case of goal completion without any active pilot involved
|
||||
-- in the execution of the task, could result in a **Success** task completion status, but no score would be awared, as there were no players involved.
|
||||
--
|
||||
-- These different completion states are important for the mission designer to reflect scoring to a player.
|
||||
-- A success could mean a positive score to be given, while a failure could mean a negative score or penalties to be awarded.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
@@ -8,7 +212,8 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module Task
|
||||
-- @module Tasking.Task
|
||||
-- @image MOOSE.JPG
|
||||
|
||||
--- @type TASK
|
||||
-- @field Core.Scheduler#SCHEDULER TaskScheduler
|
||||
@@ -20,50 +225,106 @@
|
||||
-- @field Tasking.TaskInfo#TASKINFO TaskInfo
|
||||
-- @extends Core.Fsm#FSM_TASK
|
||||
|
||||
---
|
||||
-- # TASK class, extends @{Base#BASE}
|
||||
--- Governs the main engine to administer human taskings.
|
||||
--
|
||||
-- ## The TASK class implements the methods for task orchestration within MOOSE.
|
||||
-- A task is governed by a @{Tasking.Mission} object. Tasks are of different types.
|
||||
-- The @{#TASK} object is used or derived by more detailed tasking classes that will implement the task execution mechanisms
|
||||
-- and goals.
|
||||
--
|
||||
-- The class provides a couple of methods to:
|
||||
-- # 1) Derived task classes.
|
||||
--
|
||||
-- * @{#TASK.AssignToGroup}():Assign a task to a group (of players).
|
||||
-- * @{#TASK.AddProcess}():Add a @{Process} to a task.
|
||||
-- * @{#TASK.RemoveProcesses}():Remove a running @{Process} from a running task.
|
||||
-- * @{#TASK.SetStateMachine}():Set a @{Fsm} to a task.
|
||||
-- * @{#TASK.RemoveStateMachine}():Remove @{Fsm} from a task.
|
||||
-- * @{#TASK.HasStateMachine}():Enquire if the task has a @{Fsm}
|
||||
-- * @{#TASK.AssignToUnit}(): Assign a task to a unit. (Needs to be implemented in the derived classes from @{#TASK}.
|
||||
-- * @{#TASK.UnAssignFromUnit}(): Unassign the task from a unit.
|
||||
-- * @{#TASK.SetTimeOut}(): Set timer in seconds before task gets cancelled if not assigned.
|
||||
-- The following TASK_ classes are derived from @{#TASK}.
|
||||
--
|
||||
-- TASK
|
||||
-- TASK_A2A
|
||||
-- TASK_A2A_ENGAGE
|
||||
-- TASK_A2A_INTERCEPT
|
||||
-- TASK_A2A_SWEEP
|
||||
-- TASK_A2G
|
||||
-- TASK_A2G_SEAD
|
||||
-- TASK_A2G_CAS
|
||||
-- TASK_A2G_BAI
|
||||
-- TASK_CARGO
|
||||
-- TASK_CARGO_TRANSPORT
|
||||
-- TASK_CARGO_CSAR
|
||||
--
|
||||
-- ## 1.1) A2A Tasks
|
||||
--
|
||||
-- - @{Tasking.Task_A2A#TASK_A2A_ENGAGE} - Models an A2A engage task of a target group of airborne intruders mid-air.
|
||||
-- - @{Tasking.Task_A2A#TASK_A2A_INTERCEPT} - Models an A2A ground intercept task of a target group of airborne intruders mid-air.
|
||||
-- - @{Tasking.Task_A2A#TASK_A2A_SWEEP} - Models an A2A sweep task to clean an area of previously detected intruders mid-air.
|
||||
--
|
||||
-- ## 1.2) A2G Tasks
|
||||
--
|
||||
-- - @{Tasking.Task_A2G#TASK_A2G_SEAD} - Models an A2G Suppression or Extermination of Air Defenses task to clean an area of air to ground defense threats.
|
||||
-- - @{Tasking.Task_A2G#TASK_A2G_CAS} - Models an A2G Close Air Support task to provide air support to nearby friendlies near the front-line.
|
||||
-- - @{Tasking.Task_A2G#TASK_A2G_BAI} - Models an A2G Battlefield Air Interdiction task to provide air support to nearby friendlies near the front-line.
|
||||
--
|
||||
-- ## 1.3) Cargo Tasks
|
||||
--
|
||||
-- - @{Tasking.Task_Cargo#TASK_CARGO_TRANSPORT} - Models the transportation of cargo to deployment zones.
|
||||
-- - @{Tasking.Task_Cargo#TASK_CARGO_CSAR} - Models the rescue of downed friendly pilots from behind enemy lines.
|
||||
--
|
||||
--
|
||||
-- # 2) Task status events.
|
||||
--
|
||||
-- The task statuses can be set by using the following methods:
|
||||
--
|
||||
-- - @{#TASK.Success}() - Set the task to **Success** state.
|
||||
-- - @{#TASK.Fail}() - Set the task to **Failed** state.
|
||||
-- - @{#TASK.Hold}() - Set the task to **Hold** state.
|
||||
-- - @{#TASK.Abort}() - Set the task to **Aborted** state, aborting the task. The task may be replanned.
|
||||
-- - @{#TASK.Cancel}() - Set the task to **Cancelled** state, cancelling the task.
|
||||
--
|
||||
-- The mentioned derived TASK_ classes are implementing the task status transitions out of the box.
|
||||
-- So no extra logic needs to be written.
|
||||
--
|
||||
-- ## 1.2) Set and enquire task status (beyond the task state machine processing).
|
||||
-- # 3) Goal conditions for a task.
|
||||
--
|
||||
-- A task needs to implement as a minimum the following task states:
|
||||
-- Every 30 seconds, a @{#Task.Goal} trigger method is fired.
|
||||
-- You as a mission designer, can capture the **Goal** event trigger to check your own task goal conditions and take action!
|
||||
--
|
||||
-- * **Success**: Expresses the successful execution and finalization of the task.
|
||||
-- * **Failed**: Expresses the failure of a task.
|
||||
-- * **Planned**: Expresses that the task is created, but not yet in execution and is not assigned yet.
|
||||
-- * **Assigned**: Expresses that the task is assigned to a Group of players, and that the task is in execution mode.
|
||||
-- ## 3.1) Goal event handler `OnAfterGoal()`.
|
||||
--
|
||||
-- A task may also implement the following task states:
|
||||
--
|
||||
-- * **Rejected**: Expresses that the task is rejected by a player, who was requested to accept the task.
|
||||
-- * **Cancelled**: Expresses that the task is cancelled by HQ or through a logical situation where a cancellation of the task is required.
|
||||
--
|
||||
-- A task can implement more statusses than the ones outlined above. Please consult the documentation of the specific tasks to understand the different status modelled.
|
||||
--
|
||||
-- The status of tasks can be set by the methods **State** followed by the task status. An example is `StateAssigned()`.
|
||||
-- The status of tasks can be enquired by the methods **IsState** followed by the task status name. An example is `if IsStateAssigned() then`.
|
||||
-- And this is a really great feature! Imagine a task which has **several conditions to check** before the task can move into **Success** state.
|
||||
-- You can do this with the OnAfterGoal method.
|
||||
--
|
||||
-- ## 1.3) Add scoring when reaching a certain task status:
|
||||
-- The following code provides an example of such a goal condition check implementation.
|
||||
--
|
||||
-- function Task:OnAfterGoal()
|
||||
-- if condition == true then
|
||||
-- self:Success() -- This will flag the task to Succcess when the condition is true.
|
||||
-- else
|
||||
-- if condition2 == true and condition3 == true then
|
||||
-- self:Fail() -- This will flag the task to Failed, when condition2 and condition3 would be true.
|
||||
-- end
|
||||
-- end
|
||||
-- end
|
||||
--
|
||||
-- So the @{#TASK.OnAfterGoal}() event handler would be called every 30 seconds automatically,
|
||||
-- and within this method, you can now check the conditions and take respective action.
|
||||
--
|
||||
-- ## 3.2) Goal event trigger `Goal()`.
|
||||
--
|
||||
-- If you would need to check a goal at your own defined event timing, then just call the @{#TASK.Goal}() method within your logic.
|
||||
-- The @{#TASK.OnAfterGoal}() event handler would then directly be called and would execute the logic.
|
||||
-- Note that you can also delay the goal check by using the delayed event trigger syntax `:__Goal( Delay )`.
|
||||
--
|
||||
--
|
||||
-- # 4) Score task completion.
|
||||
--
|
||||
-- Upon reaching a certain task status in a task, additional scoring can be given. If the Mission has a scoring system attached, the scores will be added to the mission scoring.
|
||||
-- Use the method @{#TASK.AddScore}() to add scores when a status is reached.
|
||||
--
|
||||
-- ## 1.4) Task briefing:
|
||||
-- # 5) Task briefing.
|
||||
--
|
||||
-- A task briefing is a text that is shown to the player when he is assigned to the task.
|
||||
-- The briefing is broadcasted by the command center owning the mission.
|
||||
--
|
||||
-- The briefing is part of the parameters in the @{#TASK.New}() constructor,
|
||||
-- but can separately be modified later in your mission using the
|
||||
-- @{#TASK.SetBriefing}() method.
|
||||
--
|
||||
-- A task briefing can be given that is shown to the player when he is assigned to the task.
|
||||
--
|
||||
-- @field #TASK TASK
|
||||
--
|
||||
@@ -186,7 +447,7 @@ function TASK:New( Mission, SetGroupAssign, TaskName, TaskType, TaskBriefing )
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @param Wrapper.Unit#UNIT PlayerUnit The @{Unit} of the player.
|
||||
-- @param Wrapper.Unit#UNIT PlayerUnit The @{Wrapper.Unit} of the player.
|
||||
-- @param #string PlayerName The name of the player.
|
||||
-- @return #boolean
|
||||
|
||||
@@ -196,20 +457,20 @@ function TASK:New( Mission, SetGroupAssign, TaskName, TaskType, TaskBriefing )
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @param Wrapper.Unit#UNIT PlayerUnit The @{Unit} of the player.
|
||||
-- @param Wrapper.Unit#UNIT PlayerUnit The @{Wrapper.Unit} of the player.
|
||||
-- @param #string PlayerName The name of the player.
|
||||
|
||||
--- Goal Trigger for TASK
|
||||
-- @function [parent=#TASK] Goal
|
||||
-- @param #TASK self
|
||||
-- @param Wrapper.Unit#UNIT PlayerUnit The @{Unit} of the player.
|
||||
-- @param Wrapper.Unit#UNIT PlayerUnit The @{Wrapper.Unit} of the player.
|
||||
-- @param #string PlayerName The name of the player.
|
||||
|
||||
--- Goal Asynchronous Trigger for TASK
|
||||
-- @function [parent=#TASK] __Goal
|
||||
-- @param #TASK self
|
||||
-- @param #number Delay
|
||||
-- @param Wrapper.Unit#UNIT PlayerUnit The @{Unit} of the player.
|
||||
-- @param Wrapper.Unit#UNIT PlayerUnit The @{Wrapper.Unit} of the player.
|
||||
-- @param #string PlayerName The name of the player.
|
||||
|
||||
|
||||
@@ -489,7 +750,7 @@ do -- Group Assignment
|
||||
end
|
||||
|
||||
|
||||
--- Set @{Group} assigned to the @{Task}.
|
||||
--- Set @{Wrapper.Group} assigned to the @{Task}.
|
||||
-- @param #TASK self
|
||||
-- @param Wrapper.Group#GROUP TaskGroup
|
||||
-- @return #TASK
|
||||
@@ -519,7 +780,7 @@ do -- Group Assignment
|
||||
return self
|
||||
end
|
||||
|
||||
--- Clear the @{Group} assignment from the @{Task}.
|
||||
--- Clear the @{Wrapper.Group} assignment from the @{Task}.
|
||||
-- @param #TASK self
|
||||
-- @param Wrapper.Group#GROUP TaskGroup
|
||||
-- @return #TASK
|
||||
@@ -563,7 +824,7 @@ do -- Group Assignment
|
||||
end
|
||||
|
||||
|
||||
--- Assign the @{Task} to a @{Group}.
|
||||
--- Assign the @{Task} to a @{Wrapper.Group}.
|
||||
-- @param #TASK self
|
||||
-- @param Wrapper.Group#GROUP TaskGroup
|
||||
-- @return #TASK
|
||||
@@ -598,7 +859,7 @@ do -- Group Assignment
|
||||
return self
|
||||
end
|
||||
|
||||
--- UnAssign the @{Task} from a @{Group}.
|
||||
--- UnAssign the @{Task} from a @{Wrapper.Group}.
|
||||
-- @param #TASK self
|
||||
-- @param Wrapper.Group#GROUP TaskGroup
|
||||
function TASK:UnAssignFromGroup( TaskGroup )
|
||||
@@ -633,7 +894,7 @@ function TASK:HasGroup( FindGroup )
|
||||
|
||||
end
|
||||
|
||||
--- Assign the @{Task} to an alive @{Unit}.
|
||||
--- Assign the @{Task} to an alive @{Wrapper.Unit}.
|
||||
-- @param #TASK self
|
||||
-- @param Wrapper.Unit#UNIT TaskUnit
|
||||
-- @return #TASK self
|
||||
@@ -652,7 +913,7 @@ function TASK:AssignToUnit( TaskUnit )
|
||||
return self
|
||||
end
|
||||
|
||||
--- UnAssign the @{Task} from an alive @{Unit}.
|
||||
--- UnAssign the @{Task} from an alive @{Wrapper.Unit}.
|
||||
-- @param #TASK self
|
||||
-- @param Wrapper.Unit#UNIT TaskUnit
|
||||
-- @return #TASK self
|
||||
@@ -677,7 +938,7 @@ function TASK:SetTimeOut ( Timer )
|
||||
return self
|
||||
end
|
||||
|
||||
--- Send a message of the @{Task} to the assigned @{Group}s.
|
||||
--- Send a message of the @{Task} to the assigned @{Wrapper.Group}s.
|
||||
-- @param #TASK self
|
||||
function TASK:MessageToGroups( Message )
|
||||
self:F( { Message = Message } )
|
||||
@@ -694,7 +955,7 @@ function TASK:MessageToGroups( Message )
|
||||
end
|
||||
|
||||
|
||||
--- Send the briefng message of the @{Task} to the assigned @{Group}s.
|
||||
--- Send the briefng message of the @{Task} to the assigned @{Wrapper.Group}s.
|
||||
-- @param #TASK self
|
||||
function TASK:SendBriefingToAssignedGroups()
|
||||
self:F2()
|
||||
@@ -709,7 +970,7 @@ function TASK:SendBriefingToAssignedGroups()
|
||||
end
|
||||
|
||||
|
||||
--- UnAssign the @{Task} from the @{Group}s.
|
||||
--- UnAssign the @{Task} from the @{Wrapper.Group}s.
|
||||
-- @param #TASK self
|
||||
function TASK:UnAssignFromGroups()
|
||||
self:F2()
|
||||
@@ -874,7 +1135,7 @@ function TASK:RemoveMenu( MenuTime )
|
||||
end
|
||||
|
||||
|
||||
--- Remove the menu option of the @{Task} for a @{Group}.
|
||||
--- Remove the menu option of the @{Task} for a @{Wrapper.Group}.
|
||||
-- @param #TASK self
|
||||
-- @param Wrapper.Group#GROUP TaskGroup
|
||||
-- @param #number MenuTime
|
||||
@@ -905,7 +1166,7 @@ function TASK:RefreshMenus( TaskGroup, MenuTime )
|
||||
|
||||
end
|
||||
|
||||
--- Remove the assigned menu option of the @{Task} for a @{Group}.
|
||||
--- Remove the assigned menu option of the @{Task} for a @{Wrapper.Group}.
|
||||
-- @param #TASK self
|
||||
-- @param Wrapper.Group#GROUP TaskGroup
|
||||
-- @param #number MenuTime
|
||||
@@ -939,15 +1200,27 @@ function TASK:MenuMarkToGroup( TaskGroup )
|
||||
|
||||
self:UpdateTaskInfo( self.DetectedItem )
|
||||
|
||||
local Report = REPORT:New():SetIndent( 0 )
|
||||
|
||||
self.TaskInfo:Report( Report, "M", TaskGroup )
|
||||
|
||||
local TargetCoordinate = self.TaskInfo:GetData( "Coordinate" ) -- Core.Point#COORDINATE
|
||||
local MarkText = Report:Text( ", " )
|
||||
self:F( { Coordinate = TargetCoordinate, MarkText = MarkText } )
|
||||
TargetCoordinate:MarkToGroup( MarkText, TaskGroup )
|
||||
--Coordinate:MarkToAll( Briefing )
|
||||
local TargetCoordinates = self.TaskInfo:GetData( "Coordinates" ) -- Core.Point#COORDINATE
|
||||
if TargetCoordinates then
|
||||
for TargetCoordinateID, TargetCoordinate in pairs( TargetCoordinates ) do
|
||||
local Report = REPORT:New():SetIndent( 0 )
|
||||
self.TaskInfo:Report( Report, "M", TaskGroup, self )
|
||||
local MarkText = Report:Text( ", " )
|
||||
self:F( { Coordinate = TargetCoordinate, MarkText = MarkText } )
|
||||
TargetCoordinate:MarkToGroup( MarkText, TaskGroup )
|
||||
--Coordinate:MarkToAll( Briefing )
|
||||
end
|
||||
else
|
||||
local TargetCoordinate = self.TaskInfo:GetData( "Coordinate" ) -- Core.Point#COORDINATE
|
||||
if TargetCoordinate then
|
||||
local Report = REPORT:New():SetIndent( 0 )
|
||||
self.TaskInfo:Report( Report, "M", TaskGroup, self )
|
||||
local MarkText = Report:Text( ", " )
|
||||
self:F( { Coordinate = TargetCoordinate, MarkText = MarkText } )
|
||||
TargetCoordinate:MarkToGroup( MarkText, TaskGroup )
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- Report the task status.
|
||||
@@ -1001,7 +1274,7 @@ end
|
||||
|
||||
|
||||
-- TODO: Obscolete?
|
||||
--- Fail processes from @{Task} with key @{Unit}
|
||||
--- Fail processes from @{Task} with key @{Wrapper.Unit}
|
||||
-- @param #TASK self
|
||||
-- @param #string TaskUnitName
|
||||
-- @return #TASK self
|
||||
@@ -1013,7 +1286,7 @@ function TASK:FailProcesses( TaskUnitName )
|
||||
end
|
||||
end
|
||||
|
||||
--- Add a FiniteStateMachine to @{Task} with key Task@{Unit}
|
||||
--- Add a FiniteStateMachine to @{Task} with key Task@{Wrapper.Unit}
|
||||
-- @param #TASK self
|
||||
-- @param Wrapper.Unit#UNIT TaskUnit
|
||||
-- @param Core.Fsm#FSM_PROCESS Fsm
|
||||
@@ -1026,7 +1299,7 @@ function TASK:SetStateMachine( TaskUnit, Fsm )
|
||||
return Fsm
|
||||
end
|
||||
|
||||
--- Gets the FiniteStateMachine of @{Task} with key Task@{Unit}
|
||||
--- Gets the FiniteStateMachine of @{Task} with key Task@{Wrapper.Unit}
|
||||
-- @param #TASK self
|
||||
-- @param Wrapper.Unit#UNIT TaskUnit
|
||||
-- @return Core.Fsm#FSM_PROCESS
|
||||
@@ -1036,7 +1309,7 @@ function TASK:GetStateMachine( TaskUnit )
|
||||
return self.Fsm[TaskUnit]
|
||||
end
|
||||
|
||||
--- Remove FiniteStateMachines from @{Task} with key Task@{Unit}
|
||||
--- Remove FiniteStateMachines from @{Task} with key Task@{Wrapper.Unit}
|
||||
-- @param #TASK self
|
||||
-- @param Wrapper.Unit#UNIT TaskUnit
|
||||
-- @return #TASK self
|
||||
@@ -1060,7 +1333,7 @@ function TASK:RemoveStateMachine( TaskUnit )
|
||||
end
|
||||
|
||||
|
||||
--- Checks if there is a FiniteStateMachine assigned to Task@{Unit} for @{Task}
|
||||
--- Checks if there is a FiniteStateMachine assigned to Task@{Wrapper.Unit} for @{Task}
|
||||
-- @param #TASK self
|
||||
-- @param Wrapper.Unit#UNIT TaskUnit
|
||||
-- @return #TASK self
|
||||
@@ -1478,7 +1751,7 @@ function TASK:ReportSummary( ReportGroup )
|
||||
-- Determine the status of the Task.
|
||||
Report:Add( "State: <" .. self:GetState() .. ">" )
|
||||
|
||||
self.TaskInfo:Report( Report, "S", ReportGroup )
|
||||
self.TaskInfo:Report( Report, "S", ReportGroup, self )
|
||||
|
||||
return Report:Text( ', ' )
|
||||
end
|
||||
@@ -1495,7 +1768,7 @@ function TASK:ReportOverview( ReportGroup )
|
||||
local TaskName = self:GetName()
|
||||
local Report = REPORT:New()
|
||||
|
||||
self.TaskInfo:Report( Report, "O", ReportGroup )
|
||||
self.TaskInfo:Report( Report, "O", ReportGroup, self )
|
||||
|
||||
return Report:Text()
|
||||
end
|
||||
@@ -1579,7 +1852,7 @@ function TASK:ReportDetails( ReportGroup )
|
||||
Report:AddIndent( Players )
|
||||
end
|
||||
|
||||
self.TaskInfo:Report( Report, "D", ReportGroup )
|
||||
self.TaskInfo:Report( Report, "D", ReportGroup, self )
|
||||
|
||||
return Report:Text()
|
||||
end
|
||||
@@ -1675,7 +1948,7 @@ do -- Task Control Menu
|
||||
|
||||
--- Init Task Control Menu
|
||||
-- @param #TASK self
|
||||
-- @param Wrapper.Unit#UNIT TaskUnit The @{Unit} that contains a player.
|
||||
-- @param Wrapper.Unit#UNIT TaskUnit The @{Wrapper.Unit} that contains a player.
|
||||
-- @return Task Control Menu Refresh ID
|
||||
function TASK:InitTaskControlMenu( TaskUnit )
|
||||
|
||||
@@ -1686,7 +1959,7 @@ do -- Task Control Menu
|
||||
|
||||
--- Get Task Control Menu
|
||||
-- @param #TASK self
|
||||
-- @param Wrapper.Unit#UNIT TaskUnit The @{Unit} that contains a player.
|
||||
-- @param Wrapper.Unit#UNIT TaskUnit The @{Wrapper.Unit} that contains a player.
|
||||
-- @return Core.Menu#MENU_GROUP TaskControlMenu The Task Control Menu
|
||||
function TASK:GetTaskControlMenu( TaskUnit, TaskName )
|
||||
|
||||
@@ -1706,7 +1979,7 @@ do -- Task Control Menu
|
||||
|
||||
--- Remove Task Control Menu
|
||||
-- @param #TASK self
|
||||
-- @param Wrapper.Unit#UNIT TaskUnit The @{Unit} that contains a player.
|
||||
-- @param Wrapper.Unit#UNIT TaskUnit The @{Wrapper.Unit} that contains a player.
|
||||
function TASK:RemoveTaskControlMenu( TaskUnit )
|
||||
|
||||
if self.TaskControlMenu then
|
||||
@@ -1717,7 +1990,7 @@ do -- Task Control Menu
|
||||
|
||||
--- Refresh Task Control Menu
|
||||
-- @param #TASK self
|
||||
-- @param Wrapper.Unit#UNIT TaskUnit The @{Unit} that contains a player.
|
||||
-- @param Wrapper.Unit#UNIT TaskUnit The @{Wrapper.Unit} that contains a player.
|
||||
-- @param MenuTime The refresh time that was used to refresh the Task Control Menu items.
|
||||
-- @param MenuTag The tag.
|
||||
function TASK:RefreshTaskControlMenu( TaskUnit, MenuTime, MenuTag )
|
||||
|
||||
@@ -8,13 +8,14 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module TaskInfo
|
||||
-- @module Tasking.TaskInfo
|
||||
-- @image MOOSE.JPG
|
||||
|
||||
--- @type TASKINFO
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
---
|
||||
-- # TASKINFO class, extends @{Base#BASE}
|
||||
-- # TASKINFO class, extends @{Core.Base#BASE}
|
||||
--
|
||||
-- ## The TASKINFO class implements the methods to contain information and display information of a task.
|
||||
--
|
||||
@@ -84,7 +85,7 @@ end
|
||||
-- @return Data The data of the info.
|
||||
function TASKINFO:GetData( Key )
|
||||
local Object = self.Info:Get( Key )
|
||||
return Object.Data
|
||||
return Object and Object.Data
|
||||
end
|
||||
|
||||
|
||||
@@ -129,6 +130,19 @@ function TASKINFO:AddCoordinate( Coordinate, Order, Detail, Keep )
|
||||
end
|
||||
|
||||
|
||||
--- Add Coordinates.
|
||||
-- @param #TASKINFO self
|
||||
-- @param #list<Core.Point#COORDINATE> Coordinates
|
||||
-- @param #number Order The display order, which is a number from 0 to 100.
|
||||
-- @param #TASKINFO.Detail Detail The detail Level.
|
||||
-- @param #boolean Keep (optional) If true, this would indicate that the planned taskinfo would be persistent when the task is completed, so that the original planned task info is used at the completed reports.
|
||||
-- @return #TASKINFO self
|
||||
function TASKINFO:AddCoordinates( Coordinates, Order, Detail, Keep )
|
||||
self:AddInfo( "Coordinates", Coordinates, Order, Detail, Keep )
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
|
||||
--- Add Threat.
|
||||
-- @param #TASKINFO self
|
||||
@@ -258,6 +272,7 @@ function TASKINFO:AddCargoSet( SetCargo, Order, Detail, Keep )
|
||||
)
|
||||
|
||||
self:AddInfo( "Cargo", CargoReport:Text(), Order, Detail, Keep )
|
||||
|
||||
|
||||
return self
|
||||
end
|
||||
@@ -269,8 +284,9 @@ end
|
||||
-- @param Core.Report#REPORT Report
|
||||
-- @param #TASKINFO.Detail Detail The detail Level.
|
||||
-- @param Wrapper.Group#GROUP ReportGroup
|
||||
-- @param Tasking.Task#TASK Task
|
||||
-- @return #TASKINFO self
|
||||
function TASKINFO:Report( Report, Detail, ReportGroup )
|
||||
function TASKINFO:Report( Report, Detail, ReportGroup, Task )
|
||||
|
||||
local Line = 0
|
||||
local LineReport = REPORT:New()
|
||||
@@ -291,7 +307,7 @@ function TASKINFO:Report( Report, Detail, ReportGroup )
|
||||
end
|
||||
if Key == "Coordinate" then
|
||||
local Coordinate = Data.Data -- Core.Point#COORDINATE
|
||||
Text = Coordinate:ToString( ReportGroup:GetUnit(1), nil, self )
|
||||
Text = Coordinate:ToString( ReportGroup:GetUnit(1), nil, Task )
|
||||
end
|
||||
if Key == "Threat" then
|
||||
local DataText = Data.Data -- #string
|
||||
@@ -307,15 +323,15 @@ function TASKINFO:Report( Report, Detail, ReportGroup )
|
||||
end
|
||||
if Key == "QFE" then
|
||||
local Coordinate = Data.Data -- Core.Point#COORDINATE
|
||||
Text = Coordinate:ToStringPressure( ReportGroup:GetUnit(1), nil, self )
|
||||
Text = Coordinate:ToStringPressure( ReportGroup:GetUnit(1), nil, Task )
|
||||
end
|
||||
if Key == "Temperature" then
|
||||
local Coordinate = Data.Data -- Core.Point#COORDINATE
|
||||
Text = Coordinate:ToStringTemperature( ReportGroup:GetUnit(1), nil, self )
|
||||
Text = Coordinate:ToStringTemperature( ReportGroup:GetUnit(1), nil, Task )
|
||||
end
|
||||
if Key == "Wind" then
|
||||
local Coordinate = Data.Data -- Core.Point#COORDINATE
|
||||
Text = Coordinate:ToStringWind( ReportGroup:GetUnit(1), nil, self )
|
||||
Text = Coordinate:ToStringWind( ReportGroup:GetUnit(1), nil, Task )
|
||||
end
|
||||
if Key == "Cargo" then
|
||||
local DataText = Data.Data -- #string
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module TaskZoneCapture
|
||||
-- @module Tasking.TaskZoneCapture
|
||||
-- @image MOOSE.JPG
|
||||
|
||||
do -- TASK_ZONE_GOAL
|
||||
|
||||
@@ -17,14 +18,14 @@ do -- TASK_ZONE_GOAL
|
||||
-- @field Core.ZoneGoal#ZONE_GOAL ZoneGoal
|
||||
-- @extends Tasking.Task#TASK
|
||||
|
||||
--- # TASK_ZONE_GOAL class, extends @{Task#TASK}
|
||||
--- # TASK_ZONE_GOAL class, extends @{Tasking.Task#TASK}
|
||||
--
|
||||
-- The TASK_ZONE_GOAL class defines the task to protect or capture a protection zone.
|
||||
-- The TASK_ZONE_GOAL is implemented using a @{Fsm#FSM_TASK}, and has the following statuses:
|
||||
-- The TASK_ZONE_GOAL is implemented using a @{Core.Fsm#FSM_TASK}, and has the following statuses:
|
||||
--
|
||||
-- * **None**: Start of the process
|
||||
-- * **Planned**: The A2G task is planned.
|
||||
-- * **Assigned**: The A2G task is assigned to a @{Group#GROUP}.
|
||||
-- * **Assigned**: The A2G task is assigned to a @{Wrapper.Group#GROUP}.
|
||||
-- * **Success**: The A2G task is successfully completed.
|
||||
-- * **Failed**: The A2G task has failed. This will happen if the player exists the task early, without communicating a possible cancellation to HQ.
|
||||
--
|
||||
@@ -44,7 +45,7 @@ do -- TASK_ZONE_GOAL
|
||||
--- Instantiates a new TASK_ZONE_GOAL.
|
||||
-- @param #TASK_ZONE_GOAL self
|
||||
-- @param Tasking.Mission#MISSION Mission
|
||||
-- @param Set#SET_GROUP SetGroup The set of groups for which the Task can be assigned.
|
||||
-- @param Core.Set#SET_GROUP SetGroup The set of groups for which the Task can be assigned.
|
||||
-- @param #string TaskName The name of the Task.
|
||||
-- @param Core.ZoneGoal#ZONE_GOAL ZoneGoal
|
||||
-- @return #TASK_ZONE_GOAL self
|
||||
@@ -166,12 +167,12 @@ do -- TASK_ZONE_CAPTURE
|
||||
-- @field Core.ZoneGoalCoalition#ZONE_GOAL_COALITION ZoneGoal
|
||||
-- @extends #TASK_ZONE_GOAL
|
||||
|
||||
--- # TASK_ZONE_CAPTURE class, extends @{TaskZoneGoal#TASK_ZONE_GOAL}
|
||||
--- # TASK_ZONE_CAPTURE class, extends @{Tasking.TaskZoneGoal#TASK_ZONE_GOAL}
|
||||
--
|
||||
-- The TASK_ZONE_CAPTURE class defines an Suppression or Extermination of Air Defenses task for a human player to be executed.
|
||||
-- These tasks are important to be executed as they will help to achieve air superiority at the vicinity.
|
||||
--
|
||||
-- The TASK_ZONE_CAPTURE is used by the @{Task_A2G_Dispatcher#TASK_A2G_DISPATCHER} to automatically create SEAD tasks
|
||||
-- The TASK_ZONE_CAPTURE is used by the @{Tasking.Task_A2G_Dispatcher#TASK_A2G_DISPATCHER} to automatically create SEAD tasks
|
||||
-- based on detected enemy ground targets.
|
||||
--
|
||||
-- @field #TASK_ZONE_CAPTURE
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user