Compare commits

...

161 Commits

Author SHA1 Message Date
Frank
1f20b830b7 Merge branch 'develop' into FF/OpsDev 2025-04-17 21:40:41 +02:00
Frank
0678ad17f8 Merge branch 'master' into develop 2025-04-17 21:34:17 +02:00
Frank
be4beea9d0 Update Airbase.lua
- Removed umlauts and ß in airbase names
2025-04-17 21:34:01 +02:00
Frank
5da899138b Merge pull request #2284 from FlightControl-Master/FF/MasterDevel
Germany CW map
2025-04-17 21:19:48 +02:00
Frank
1ec1e00bde Germany CW map
- ATIS Germany map
- UTILS magnetic declination
2025-04-17 21:19:01 +02:00
Thomas
d7d46d4f1b Merge pull request #2283 from FlightControl-Master/master
Merge from master
2025-04-17 08:45:51 +02:00
Thomas
5d93b33d42 Merge pull request #2282 from shaji-Dev/master
[FIXED] Returns nil for late activated templates we use to mark paths to use in our scripts
2025-04-17 08:44:38 +02:00
shaji
b2077bfc74 [FIXED] Returns nil for late activated templates we use to mark waypoint paths to use in the scripts. 2025-04-16 19:59:13 +02:00
Applevangelist
e958ca103a #EASYGCICAP - make conflict zones setup a bit more explic 2025-04-15 11:45:49 +02:00
Applevangelist
1d9ef869a7 Merge remote-tracking branch 'origin/master' into develop 2025-04-14 12:23:37 +02:00
Applevangelist
6fdf9a649f #AIRBASE rescribe umlauts 2025-04-14 12:23:12 +02:00
Applevangelist
90c6c57449 Merge remote-tracking branch 'origin/master' into develop 2025-04-14 12:11:56 +02:00
Applevangelist
d013bbc751 #STORAGE Enum, some additions 2025-04-14 12:11:27 +02:00
Applevangelist
e0092fdba0 #AIRBASE GermanCW Map airbases 2025-04-14 11:37:45 +02:00
Thomas
ecce2eff9b Merge pull request #2281 from FlightControl-Master/master
Merge
2025-04-12 10:52:39 +02:00
Thomas
fbeada439f Merge pull request #2278 from leka1986/patch-5
Update Group.lua
2025-04-12 10:51:42 +02:00
Thomas
6c8858d2f5 Merge pull request #2280 from leka1986/patch-7
Update Set.lua
2025-04-12 10:51:00 +02:00
Thomas
e2b77878df Merge pull request #2279 from leka1986/patch-6
Update Event.lua
2025-04-12 10:50:39 +02:00
leka1986
53d7972858 Update Set.lua
Removed the Filter={},
2025-04-12 10:48:22 +02:00
leka1986
04a55e4104 Update Event.lua
Added nil checks which was causing nil. had this for a few weeks with no errors.
2025-04-12 10:44:29 +02:00
leka1986
d11acecdac Update Group.lua
Fix for the error attempt to index a nil value called from suppression
2025-04-12 10:26:34 +02:00
Frank
0531b8f57e Merge branch 'FF/Ops' into FF/OpsDev 2025-04-09 22:47:34 +02:00
Frank
98e2997e26 Merge branch 'develop' into FF/OpsDev 2025-04-09 22:43:24 +02:00
Frank
7d3bffcfef Naviation
- Added beacons class
- Added navpoints class
- Added vector class
2025-04-09 22:36:26 +02:00
Frank
5b76ec6b99 Merge branch 'develop' into FF/Ops 2025-04-09 21:17:49 +02:00
Applevangelist
4b23c86daa Merge remote-tracking branch 'origin/master' into develop 2025-04-09 08:16:20 +02:00
Applevangelist
49c11073e6 #MANTIS Mod data updates 2025-04-09 08:15:50 +02:00
Applevangelist
daa5caa125 Merge remote-tracking branch 'origin/master' into develop 2025-04-07 11:57:39 +02:00
Applevangelist
1a156e7e12 #CTLD - make menu build for CA a bit faster 2025-04-07 11:57:15 +02:00
Applevangelist
6fe88a6319 Merge remote-tracking branch 'origin/master' into develop 2025-04-07 10:40:58 +02:00
Applevangelist
1856754614 #Smaller Changes 2025-04-07 10:40:30 +02:00
Thomas
b9f6c1b9c7 Merge pull request #2277 from FlightControl-Master/master
Update docs-header.py
2025-04-06 16:33:05 +02:00
Thomas
6ac452ff15 Update docs-header.py 2025-04-06 16:28:19 +02:00
Applevangelist
b52176a0ff Merge remote-tracking branch 'origin/master' into develop 2025-04-06 16:19:43 +02:00
Applevangelist
d707a4775c xx 2025-04-06 16:19:12 +02:00
Thomas
ffccc31e38 Update CargoGroup.lua 2025-04-06 16:12:13 +02:00
Thomas
0405af2bde Update docs-header.py 2025-04-06 16:04:07 +02:00
Thomas
d09f0b1f6f Update classes-core.md 2025-04-06 15:47:52 +02:00
Thomas
e50e572c78 Update classes-core.md 2025-04-06 15:43:09 +02:00
Applevangelist
2e688e7da1 Merge remote-tracking branch 'origin/master' into develop 2025-04-06 15:38:55 +02:00
Applevangelist
3083599158 #CTLD - Allow CA Ground Transport 2025-04-06 15:38:26 +02:00
Applevangelist
2921f7a76b Merge remote-tracking branch 'origin/master' into develop 2025-04-03 14:22:25 +02:00
Applevangelist
b7b6c1ea19 #RADIOQUEUE - small tweak for a group when a unit dies. 2025-04-03 14:21:58 +02:00
Applevangelist
8a185c352e Merge remote-tracking branch 'origin/master' into develop 2025-04-03 11:49:30 +02:00
Applevangelist
5b107ce2da #CONTROLLABLE:CommandSmokeOnOff(OnOff, Delay) added 2025-04-03 11:48:53 +02:00
Thomas
5c1e342a79 Update classes-core.md 2025-04-03 09:33:49 +02:00
Applevangelist
3fc8f52796 Merge remote-tracking branch 'origin/master' into develop 2025-04-03 09:29:57 +02:00
Applevangelist
ddf33da787 #DYNAMICCARGO - Hover / Sling checks 2025-04-03 09:29:19 +02:00
Thomas
e7cee4d97b Merge pull request #2276 from FlightControl-Master/master
Small fixes
2025-04-02 16:13:50 +02:00
Thomas
b0a192a767 Update DynamicCargo.lua
small fix
2025-04-02 16:12:06 +02:00
Thomas
986c340211 Merge pull request #2275 from FlightControl-Master/Applevangelist-patch-1
Update classes-core.md
2025-04-02 09:54:54 +02:00
Thomas
2109537f86 Update classes-core.md
fix
2025-04-02 09:54:20 +02:00
Thomas
bad9d1ea92 Merge pull request #2274 from FlightControl-Master/master
Fix SpawnStatic
2025-04-02 09:45:44 +02:00
Thomas
690db7f12f Merge pull request #2273 from FlightControl-Master/Applevangelist-SpawnStatic-1
Update SpawnStatic.lua
2025-04-02 09:43:04 +02:00
Thomas
4f3fd06cc9 Update SpawnStatic.lua
Restored previous version as overwritten
2025-04-02 09:42:02 +02:00
Applevangelist
f5b1050086 Merge remote-tracking branch 'origin/master' into develop 2025-04-01 15:27:55 +02:00
Applevangelist
4074023ed3 #DYNAMICCARGO - enhance checks for unloading cargo from hovering Hooks 2025-04-01 15:27:23 +02:00
Applevangelist
f729b1d358 Merge remote-tracking branch 'origin/master' into develop 2025-04-01 14:13:42 +02:00
Applevangelist
6c00b0c7eb #POINT - some catches for POINT_VEC2 behaviour 2025-04-01 14:13:14 +02:00
Applevangelist
5adefe6f7b Merge remote-tracking branch 'origin/master' into develop 2025-04-01 13:18:55 +02:00
Applevangelist
76dc0d690a #POINT - Removal of References to legacy POINT_VEC2/3 classes 2025-04-01 13:17:48 +02:00
Thomas
13c16b8674 Merge pull request #2272 from shaji-Dev/develop
[Fixed] Parameter #1 (unit name) is incorrect
2025-03-31 14:05:41 +02:00
Thomas
222722225e Update OpsGroup.lua
Better make this a unit and alive check
2025-03-31 14:04:07 +02:00
shaji
82e1dcfc04 [Fixed] Parameter #1 (unit name) is incorrect 2025-03-31 13:11:56 +02:00
Thomas
c26220d1fd Merge pull request #2271 from FlightControl-Master/master
DynamicCargo small fixes
2025-03-31 12:32:55 +02:00
Thomas
d783f7be99 Merge pull request #2270 from FlightControl-Master/Applevangelist-patch-1
Update DynamicCargo.lua
2025-03-31 12:31:52 +02:00
Thomas
b66e91b11f Update DynamicCargo.lua
#DYNAMICCARGO small fixes
2025-03-31 12:31:23 +02:00
Frank
eeca95c77f Merge branch 'develop' into FF/Ops 2025-01-02 20:49:06 +01:00
Frank
e406fb0c88 Update Brigade.lua 2024-12-29 21:02:56 +01:00
Frank
bdec6eb82d Merge branch 'FF/Ops' into FF/OpsDev 2024-07-07 11:33:44 +02:00
Frank
9bdacfbcf7 Merge branch 'develop' into FF/OpsDev 2024-07-01 16:46:22 +02:00
Frank
be2eda25df Merge branch 'develop' into FF/OpsDev 2024-06-27 21:31:24 +02:00
Frank
fa8e1d2a56 Merge branch 'FF/Ops' into FF/OpsDev 2024-06-19 07:53:54 +02:00
Frank
5242754c60 Merge branch 'FF/Ops' into FF/OpsDev 2024-04-26 14:33:05 +02:00
Frank
3dbafd7a19 Update Astar.lua 2024-04-20 14:34:15 +02:00
Frank
56e751193a Merge branch 'FF/Ops' into FF/OpsDev 2024-04-04 09:35:53 +02:00
Frank
b2b258cff0 Merge branch 'FF/Ops' into FF/OpsDev 2024-03-30 22:32:42 +01:00
Frank
75068a2a26 Merge branch 'FF/Ops' into FF/OpsDev 2024-03-24 17:25:02 +01:00
Frank
d82df93eff Merge branch 'FF/Ops' into FF/OpsDev 2024-01-23 11:05:50 +01:00
Frank
5168380eac Update Modules.lua 2024-01-21 16:41:09 +01:00
Frank
a7ffbab850 Update Modules.lua 2024-01-16 19:44:08 +01:00
Frank
a238294079 Merge branch 'FF/Ops' into FF/OpsDev 2024-01-16 17:37:41 +01:00
Frank
accb4b45fb Merge branch 'FF/Ops' into FF/OpsDev 2024-01-07 21:17:17 +01:00
Frank
ba4ff5c9e9 Update Procedure.lua 2024-01-07 10:29:31 +01:00
Frank
171c450576 Merge branch 'FF/Ops' into FF/OpsDev 2024-01-04 15:14:25 +01:00
Frank
f35078b426 Merge branch 'FF/Ops' into FF/OpsDev 2024-01-02 17:07:15 +01:00
Frank
8921007805 Update Point.lua 2024-01-02 17:04:04 +01:00
Frank
8fd3034503 Merge branch 'FF/Ops' into FF/OpsDev 2024-01-01 21:55:52 +01:00
Frank
a20b6e8a62 Merge branch 'FF/Ops' into FF/OpsDev 2023-12-03 21:10:24 +01:00
Frank
4ce6cc7776 Merge branch 'FF/Ops' into FF/OpsDev 2023-11-17 18:06:17 +01:00
Frank
434296ab11 Merge branch 'FF/Ops' into FF/OpsDev 2023-11-07 00:06:35 +01:00
Frank
a5232f49c0 Navigation 2023-11-06 21:35:20 +01:00
Frank
befc8207f5 Update Nav 2023-11-02 23:42:59 +01:00
Frank
23947b7c30 Merge branch 'FF/Ops' into FF/OpsDev 2023-11-02 20:33:53 +01:00
Frank
da91b710a9 Merge branch 'FF/Ops' into FF/OpsDev 2023-10-31 20:17:10 +01:00
Frank
d656bbc014 Update Vector.lua 2023-10-19 21:49:45 +02:00
Frank
ed23f11e4a Merge branch 'FF/Ops' into FF/OpsDev 2023-10-13 22:00:57 +02:00
Frank
068465a8f2 Merge branch 'FF/Ops' into FF/OpsDev 2023-10-13 21:33:33 +02:00
Frank
4e24a7bf80 Navigation 2023-10-08 21:49:15 +02:00
Frank
1ece7238dc NAv 2023-10-05 16:52:41 +02:00
Frank
db53f427e3 Update Point.lua 2023-10-02 17:02:21 +02:00
Frank
d2e2c51275 Update FlightPlan.lua 2023-09-29 13:27:59 +02:00
Frank
691748082b Merge branch 'FF/Ops' into FF/OpsDev 2023-09-27 22:29:38 +02:00
Frank
b294ef10c8 Update NavyGroup.lua 2023-09-27 10:54:37 +02:00
Frank
5d40091947 NAVYGROUP
- Improved heading into wind
2023-09-27 10:53:19 +02:00
Frank
7453a6c55d navygroup
- into wind
2023-09-26 17:02:13 +02:00
Frank
153ef7cd08 utils 2023-09-26 01:44:30 +02:00
Frank
b6a550a247 Update Vector.lua 2023-09-25 16:59:41 +02:00
Frank
3568f27150 Vector 2023-09-24 22:46:50 +02:00
Frank
c46061466c VECTOR
- Added functions
2023-09-24 22:09:49 +02:00
Frank
9c7b5e8506 VECTOR
**VECTOR**
- New core class for vector algebra
2023-09-23 01:15:08 +02:00
Frank
b11df6b523 Navigation
Refactored names etc.
2023-09-21 23:37:25 +02:00
Frank
66dcd44fb8 Merge branch 'FF/OpsDev' of https://github.com/FlightControl-Master/MOOSE into FF/OpsDev 2023-09-21 17:48:12 +02:00
Frank
f35237f86f Update FlightControl.lua 2023-09-21 17:48:04 +02:00
Frank
f19c877a11 Navigation 2023-09-21 17:01:32 +02:00
Frank
792a487eeb Merge branch 'FF/Ops' into FF/OpsDev 2023-09-20 22:32:16 +02:00
Frank
f5e8bd0ffc Merge branch 'FF/Ops' into FF/OpsDev 2023-09-20 14:39:41 +02:00
Frank
cbdbf36f32 FC
- Improved taxi phrases
2023-09-20 11:52:14 +02:00
Frank
1116b19b00 FC 2023-09-19 17:04:37 +02:00
Frank
edb490fa97 Update Pathline.lua
- json
2023-09-19 03:01:47 +02:00
Frank
9fa16c6385 Update FlightControl.lua 2023-09-18 16:52:13 +02:00
Frank
a0ee957493 Update FlightControl.lua 2023-09-17 23:07:59 +02:00
Frank
f32c303c0a pathline 2023-09-17 22:58:53 +02:00
Frank
6febbbc8e6 FC 2023-09-17 21:55:29 +02:00
Frank
d5aa9eaf0f Merge branch 'FF/Ops' into FF/OpsDev 2023-09-17 16:26:23 +02:00
Frank
321b2d761d FLIGHTCONTROL
- Improved Taxi comms
2023-09-17 16:10:59 +02:00
Frank
18581e4a78 Merge branch 'FF/OpsDev' of https://github.com/FlightControl-Master/MOOSE into FF/OpsDev 2023-09-14 17:40:11 +02:00
Frank
b03905154d ASTAR Pathlines 2023-09-14 17:40:02 +02:00
Frank
2fda1709bc Update FlightControl.lua 2023-09-14 16:46:08 +02:00
Frank
39f626390a Merge branch 'FF/Ops' into FF/OpsDev 2023-09-13 11:14:55 +02:00
Frank
aa1e12163d ASTAR/PATHLINE 2023-09-12 23:57:50 +02:00
Frank
abb7f860ae Update Astar.lua 2023-09-12 03:21:23 +02:00
Frank
cffada1a1e AIRBASE
- Taxiways
2023-09-11 16:54:10 +02:00
Frank
f8d91798e3 Update FlightControl.lua 2023-09-10 23:55:40 +02:00
Frank
548aa8d5a9 Merge branch 'FF/Ops' into FF/OpsDev 2023-09-10 22:43:13 +02:00
Frank
1e929d1d19 ASTAR Taxi 2023-09-10 22:38:00 +02:00
Frank
d5f215505e Merge branch 'FF/Ops' into FF/OpsDev 2023-09-09 00:32:29 +02:00
Frank
851660c793 NAV 2023-09-08 16:11:11 +02:00
Frank
ee57b46c14 Update Astar.lua 2023-09-07 23:32:07 +02:00
Frank
36eac9fccc PATH 2023-09-06 22:50:24 +02:00
Frank
1f630ab490 Astar Pathline 2023-09-05 23:29:27 +02:00
Frank
8f0c6948ac Merge branch 'FF/Ops' into FF/OpsDev 2023-09-05 20:53:45 +02:00
Frank
eb2380c3f6 Merge branch 'FF/Ops' into FF/OpsDev 2023-09-04 23:35:05 +02:00
Frank
df3e182de4 Merge branch 'FF/OpsDev' of https://github.com/FlightControl-Master/MOOSE into FF/OpsDev 2023-09-04 23:34:26 +02:00
Frank
bda7988118 Astar 2023-09-04 23:34:23 +02:00
Frank
72deb9ee17 Merge branch 'FF/OpsDev' of https://github.com/FlightControl-Master/MOOSE into FF/OpsDev 2023-08-30 15:53:49 +02:00
Frank
ced1f30f3f Update DCS.lua 2023-08-30 15:53:35 +02:00
Frank
47c0006537 ASTAR & PATHLINE 2023-08-29 22:43:36 +02:00
Frank
21e5c124c0 Astar 2023-08-28 22:38:37 +02:00
Frank
3ff374e1b9 Merge branch 'FF/Ops' into FF/OpsDev 2023-08-27 20:39:51 +02:00
Frank
02000be9af Merge branch 'FF/Ops' into FF/OpsDev 2023-08-17 19:15:12 +02:00
Frank
663c6cead0 Update FlightControl.lua 2023-08-16 20:46:53 +02:00
Frank
6867df58c4 Merge branch 'FF/Ops' into FF/OpsDev 2023-08-13 18:22:12 +02:00
Frank
639625d3d5 Update FlightControl.lua 2023-08-13 14:16:40 +02:00
Frank
0ace200e5a Nav
- Small stuff
2023-08-04 00:08:16 +02:00
Frank
e76c26ff59 FLIGHTPLAN 2023-08-03 00:41:34 +02:00
Frank
cb11de6f9c Navigation
- Added NavFix
2023-08-02 10:53:28 +02:00
Frank
cdd78e5163 Update FlightPlan.lua 2023-08-01 00:25:08 +02:00
Frank
a8da02774a Update FlightPlan.lua 2023-08-01 00:24:49 +02:00
Frank
04258a69c4 Navigation
- Init stuff
2023-07-31 21:58:01 +02:00
Frank
49882f03d9 Update FlightControl.lua 2023-07-26 16:05:15 +02:00
49 changed files with 6855 additions and 1696 deletions

View File

@@ -657,8 +657,8 @@ function AI_AIR:onafterRTB( AIGroup, From, Event, To )
--- Create a route point of type air.
local FromRTBRoutePoint = FromCoord:WaypointAir(
self.PatrolAltType,
POINT_VEC3.RoutePointType.TurningPoint,
POINT_VEC3.RoutePointAction.TurningPoint,
COORDINATE.WaypointType.TurningPoint,
COORDINATE.WaypointAction.TurningPoint,
RTBSpeed,
true
)
@@ -666,8 +666,8 @@ function AI_AIR:onafterRTB( AIGroup, From, Event, To )
--- Create a route point of type air.
local ToRTBRoutePoint = ToAirbaseCoord:WaypointAir(
self.PatrolAltType,
POINT_VEC3.RoutePointType.TurningPoint,
POINT_VEC3.RoutePointAction.TurningPoint,
COORDINATE.WaypointType.TurningPoint,
COORDINATE.WaypointAction.TurningPoint,
RTBSpeed,
true
)
@@ -761,10 +761,10 @@ function AI_AIR:onafterRefuel( AIGroup, From, Event, To )
local ToRefuelSpeed = math.random( self.PatrolMinSpeed, self.PatrolMaxSpeed )
--- Create a route point of type air.
local FromRefuelRoutePoint = FromRefuelCoord:WaypointAir(self.PatrolAltType, POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, ToRefuelSpeed, true)
local FromRefuelRoutePoint = FromRefuelCoord:WaypointAir(self.PatrolAltType, COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, ToRefuelSpeed, true)
--- Create a route point of type air. NOT used!
local ToRefuelRoutePoint = Tanker:GetCoordinate():WaypointAir(self.PatrolAltType, POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, ToRefuelSpeed, true)
local ToRefuelRoutePoint = Tanker:GetCoordinate():WaypointAir(self.PatrolAltType, COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, ToRefuelSpeed, true)
self:F( { ToRefuelSpeed = ToRefuelSpeed } )

View File

@@ -453,7 +453,7 @@ function AI_AIR_ENGAGE:onafterEngageRoute( DefenderGroup, From, Event, To, Attac
--- Calculate the target route point.
local FromWP = DefenderCoord:WaypointAir(self.PatrolAltType or "RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, EngageSpeed, true)
local FromWP = DefenderCoord:WaypointAir(self.PatrolAltType or "RADIO", COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, EngageSpeed, true)
EngageRoute[#EngageRoute+1] = FromWP
@@ -462,7 +462,7 @@ function AI_AIR_ENGAGE:onafterEngageRoute( DefenderGroup, From, Event, To, Attac
local FromEngageAngle = DefenderCoord:GetAngleDegrees( DefenderCoord:GetDirectionVec3( TargetCoord ) )
local ToCoord=DefenderCoord:Translate( EngageDistance, FromEngageAngle, true )
local ToWP = ToCoord:WaypointAir(self.PatrolAltType or "RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, EngageSpeed, true)
local ToWP = ToCoord:WaypointAir(self.PatrolAltType or "RADIO", COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, EngageSpeed, true)
EngageRoute[#EngageRoute+1] = ToWP
@@ -536,7 +536,7 @@ function AI_AIR_ENGAGE:onafterEngage( DefenderGroup, From, Event, To, AttackSetU
local EngageRoute = {}
local AttackTasks = {}
local FromWP = DefenderCoord:WaypointAir(self.EngageAltType or "RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, EngageSpeed, true)
local FromWP = DefenderCoord:WaypointAir(self.EngageAltType or "RADIO", COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, EngageSpeed, true)
EngageRoute[#EngageRoute+1] = FromWP
self:SetTargetDistance( TargetCoord ) -- For RTB status check
@@ -544,7 +544,7 @@ function AI_AIR_ENGAGE:onafterEngage( DefenderGroup, From, Event, To, AttackSetU
local FromEngageAngle = DefenderCoord:GetAngleDegrees( DefenderCoord:GetDirectionVec3( TargetCoord ) )
local ToCoord=DefenderCoord:Translate( EngageDistance, FromEngageAngle, true )
local ToWP = ToCoord:WaypointAir(self.EngageAltType or "RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, EngageSpeed, true)
local ToWP = ToCoord:WaypointAir(self.EngageAltType or "RADIO", COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, EngageSpeed, true)
EngageRoute[#EngageRoute+1] = ToWP
-- TODO: A factor of * 3 this way too low. This causes the AI NOT to engage until very close or even merged sometimes. Some A2A missiles have a much longer range! Needs more frequent updates of the task!

View File

@@ -309,7 +309,7 @@ function AI_AIR_PATROL:onafterPatrolRoute( AIPatrol, From, Event, To )
local ToTargetSpeed = math.random( self.PatrolMinSpeed, self.PatrolMaxSpeed )
local speedkmh=ToTargetSpeed
local FromWP = CurrentCoord:WaypointAir(self.PatrolAltType or "RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, ToTargetSpeed, true)
local FromWP = CurrentCoord:WaypointAir(self.PatrolAltType or "RADIO", COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, ToTargetSpeed, true)
PatrolRoute[#PatrolRoute+1] = FromWP
if self.racetrack then
@@ -359,9 +359,9 @@ function AI_AIR_PATROL:onafterPatrolRoute( AIPatrol, From, Event, To )
else
--- Create a route point of type air.
local ToWP = ToTargetCoord:WaypointAir(self.PatrolAltType, POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, ToTargetSpeed, true)
local ToWP = ToTargetCoord:WaypointAir(self.PatrolAltType, COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, ToTargetSpeed, true)
PatrolRoute[#PatrolRoute+1] = ToWP
local Tasks = {}
Tasks[#Tasks+1] = AIPatrol:TaskFunction("AI_AIR_PATROL.___PatrolRoute", self)
PatrolRoute[#PatrolRoute].task = AIPatrol:TaskCombo( Tasks )

View File

@@ -521,12 +521,12 @@ function AI_BAI_ZONE:onafterEngage( Controllable, From, Event, To,
--DONE: Create GetAltitude function for GROUP, and delete GetUnit(1).
local CurrentAltitude = self.Controllable:GetAltitude()
local CurrentPointVec3 = POINT_VEC3:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y )
local CurrentPointVec3 = COORDINATE:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y )
local ToEngageZoneSpeed = self.PatrolMaxSpeed
local CurrentRoutePoint = CurrentPointVec3:WaypointAir(
self.PatrolAltType,
POINT_VEC3.RoutePointType.TurningPoint,
POINT_VEC3.RoutePointAction.TurningPoint,
COORDINATE.WaypointType.TurningPoint,
COORDINATE.WaypointAction.TurningPoint,
self.EngageSpeed,
true
)
@@ -577,13 +577,13 @@ function AI_BAI_ZONE:onafterEngage( Controllable, From, Event, To,
self:T2( ToTargetVec2 )
--- Obtain a 3D @{Point} from the 2D point + altitude.
local ToTargetPointVec3 = POINT_VEC3:New( ToTargetVec2.x, self.EngageAltitude, ToTargetVec2.y )
local ToTargetPointVec3 = COORDINATE:New( ToTargetVec2.x, self.EngageAltitude, ToTargetVec2.y )
--- Create a route point of type air.
local ToTargetRoutePoint = ToTargetPointVec3:WaypointAir(
self.PatrolAltType,
POINT_VEC3.RoutePointType.TurningPoint,
POINT_VEC3.RoutePointAction.TurningPoint,
COORDINATE.WaypointType.TurningPoint,
COORDINATE.WaypointAction.TurningPoint,
self.EngageSpeed,
true
)

View File

@@ -220,16 +220,9 @@ function AI_BALANCER:onenterReturning( SetGroup, From, Event, To, AIGroup )
AIGroup:MessageToRed( "Returning to home base ...", 30 )
else
-- Okay, we need to send this Group back to the nearest base of the Coalition of the AI.
--TODO: i need to rework the POINT_VEC2 thing.
local PointVec2 = POINT_VEC2:New( AIGroup:GetVec2().x, AIGroup:GetVec2().y )
local PointVec2 = COORDINATE:New(AIGroup:GetVec2().x, 0, AIGroup:GetVec2().y)
local ClosestAirbase = self.ReturnAirbaseSet:FindNearestAirbaseFromPointVec2( PointVec2 )
self:T( ClosestAirbase.AirbaseName )
--[[
AIGroup:MessageToRed( "Returning to " .. ClosestAirbase:GetName().. " ...", 30 )
local RTBRoute = AIGroup:RouteReturnToAirbase( ClosestAirbase )
AIGroupTemplate.route = RTBRoute
AIGroup:Respawn( AIGroupTemplate )
]]
AIGroup:RouteRTB(ClosestAirbase)
end

View File

@@ -423,12 +423,12 @@ function AI_CAP_ZONE:onafterEngage( Controllable, From, Event, To )
--DONE: Create GetAltitude function for GROUP, and delete GetUnit(1).
local CurrentAltitude = self.Controllable:GetAltitude()
local CurrentPointVec3 = POINT_VEC3:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y )
local CurrentPointVec3 = COORDINATE:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y )
local ToEngageZoneSpeed = self.PatrolMaxSpeed
local CurrentRoutePoint = CurrentPointVec3:WaypointAir(
self.PatrolAltType,
POINT_VEC3.RoutePointType.TurningPoint,
POINT_VEC3.RoutePointAction.TurningPoint,
COORDINATE.WaypointType.TurningPoint,
COORDINATE.WaypointAction.TurningPoint,
ToEngageZoneSpeed,
true
)
@@ -445,13 +445,13 @@ function AI_CAP_ZONE:onafterEngage( Controllable, From, Event, To )
self:T2( { self.PatrolMinSpeed, self.PatrolMaxSpeed, ToTargetSpeed } )
--- Obtain a 3D @{Point} from the 2D point + altitude.
local ToTargetPointVec3 = POINT_VEC3:New( ToTargetVec2.x, ToTargetAltitude, ToTargetVec2.y )
local ToTargetPointVec3 = COORDINATE:New( ToTargetVec2.x, ToTargetAltitude, ToTargetVec2.y )
--- Create a route point of type air.
local ToPatrolRoutePoint = ToTargetPointVec3:WaypointAir(
self.PatrolAltType,
POINT_VEC3.RoutePointType.TurningPoint,
POINT_VEC3.RoutePointAction.TurningPoint,
COORDINATE.WaypointType.TurningPoint,
COORDINATE.WaypointAction.TurningPoint,
ToTargetSpeed,
true
)

View File

@@ -465,12 +465,12 @@ function AI_CAS_ZONE:onafterEngage( Controllable, From, Event, To,
--DONE: Create GetAltitude function for GROUP, and delete GetUnit(1).
local CurrentAltitude = self.Controllable:GetAltitude()
local CurrentPointVec3 = POINT_VEC3:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y )
local CurrentPointVec3 = COORDINATE:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y )
local ToEngageZoneSpeed = self.PatrolMaxSpeed
local CurrentRoutePoint = CurrentPointVec3:WaypointAir(
self.PatrolAltType,
POINT_VEC3.RoutePointType.TurningPoint,
POINT_VEC3.RoutePointAction.TurningPoint,
COORDINATE.WaypointType.TurningPoint,
COORDINATE.WaypointAction.TurningPoint,
self.EngageSpeed,
true
)
@@ -507,13 +507,13 @@ function AI_CAS_ZONE:onafterEngage( Controllable, From, Event, To,
self:T2( ToTargetVec2 )
--- Obtain a 3D @{Point} from the 2D point + altitude.
local ToTargetPointVec3 = POINT_VEC3:New( ToTargetVec2.x, self.EngageAltitude, ToTargetVec2.y )
local ToTargetPointVec3 = COORDINATE:New( ToTargetVec2.x, self.EngageAltitude, ToTargetVec2.y )
--- Create a route point of type air.
local ToTargetRoutePoint = ToTargetPointVec3:WaypointAir(
self.PatrolAltType,
POINT_VEC3.RoutePointType.TurningPoint,
POINT_VEC3.RoutePointAction.TurningPoint,
COORDINATE.WaypointType.TurningPoint,
COORDINATE.WaypointAction.TurningPoint,
self.EngageSpeed,
true
)

View File

@@ -440,7 +440,7 @@ function AI_CARGO_AIRPLANE:Route( Airplane, Airbase, Speed, Height, Uncontrolled
-- To point.
local AirbasePointVec2 = Airbase:GetPointVec2()
local ToWaypoint = AirbasePointVec2:WaypointAir(POINT_VEC3.RoutePointAltType.BARO, "Land", "Landing", Speed or Airplane:GetSpeedMax()*0.8, true, Airbase)
local ToWaypoint = AirbasePointVec2:WaypointAir(COORDINATE.WaypointAltType.BARO, "Land", "Landing", Speed or Airplane:GetSpeedMax()*0.8, true, Airbase)
--ToWaypoint["airdromeId"] = Airbase:GetID()
--ToWaypoint["speed_locked"] = true

View File

@@ -367,8 +367,8 @@ function AI_CARGO_HELICOPTER:onafterQueue( Helicopter, From, Event, To, Coordina
-- local CoordinateFrom = Helicopter:GetCoordinate()
-- local WaypointFrom = CoordinateFrom:WaypointAir(
-- "RADIO",
-- POINT_VEC3.RoutePointType.TurningPoint,
-- POINT_VEC3.RoutePointAction.TurningPoint,
-- COORDINATE.WaypointType.TurningPoint,
-- COORDINATE.WaypointAction.TurningPoint,
-- Speed,
-- true
-- )
@@ -380,8 +380,8 @@ function AI_CARGO_HELICOPTER:onafterQueue( Helicopter, From, Event, To, Coordina
local WaypointTo = CoordinateTo:WaypointAir(
"RADIO",
POINT_VEC3.RoutePointType.TurningPoint,
POINT_VEC3.RoutePointAction.TurningPoint,
COORDINATE.WaypointType.TurningPoint,
COORDINATE.WaypointAction.TurningPoint,
50,
true
)
@@ -427,7 +427,7 @@ function AI_CARGO_HELICOPTER:onafterOrbit( Helicopter, From, Event, To, Coordina
local landheight = CoordinateTo:GetLandHeight() -- get target height
CoordinateTo.y = landheight + 50 -- flight height should be 50m above ground
local WaypointTo = CoordinateTo:WaypointAir("RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, 50, true)
local WaypointTo = CoordinateTo:WaypointAir("RADIO", COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, 50, true)
Route[#Route+1] = WaypointTo
local Tasks = {}
@@ -496,14 +496,14 @@ function AI_CARGO_HELICOPTER:onafterPickup( Helicopter, From, Event, To, Coordin
local CoordinateFrom = Helicopter:GetCoordinate()
--- Create a route point of type air.
local WaypointFrom = CoordinateFrom:WaypointAir("RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, _speed, true)
local WaypointFrom = CoordinateFrom:WaypointAir("RADIO", COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, _speed, true)
--- Create a route point of type air.
local CoordinateTo = Coordinate
local landheight = CoordinateTo:GetLandHeight() -- get target height
CoordinateTo.y = landheight + 50 -- flight height should be 50m above ground
local WaypointTo = CoordinateTo:WaypointAir("RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint,_speed, true)
local WaypointTo = CoordinateTo:WaypointAir("RADIO", COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint,_speed, true)
Route[#Route+1] = WaypointFrom
Route[#Route+1] = WaypointTo
@@ -563,7 +563,7 @@ function AI_CARGO_HELICOPTER:onafterDeploy( Helicopter, From, Event, To, Coordin
--- Create a route point of type air.
local CoordinateFrom = Helicopter:GetCoordinate()
local WaypointFrom = CoordinateFrom:WaypointAir("RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, _speed, true)
local WaypointFrom = CoordinateFrom:WaypointAir("RADIO", COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, _speed, true)
Route[#Route+1] = WaypointFrom
Route[#Route+1] = WaypointFrom
@@ -573,7 +573,7 @@ function AI_CARGO_HELICOPTER:onafterDeploy( Helicopter, From, Event, To, Coordin
local landheight = CoordinateTo:GetLandHeight() -- get target height
CoordinateTo.y = landheight + 50 -- flight height should be 50m above ground
local WaypointTo = CoordinateTo:WaypointAir("RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, _speed, true)
local WaypointTo = CoordinateTo:WaypointAir("RADIO", COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, _speed, true)
Route[#Route+1] = WaypointTo
Route[#Route+1] = WaypointTo
@@ -631,7 +631,7 @@ function AI_CARGO_HELICOPTER:onafterHome( Helicopter, From, Event, To, Coordinat
--- Create a route point of type air.
local CoordinateFrom = Helicopter:GetCoordinate()
local WaypointFrom = CoordinateFrom:WaypointAir("RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, Speed, true)
local WaypointFrom = CoordinateFrom:WaypointAir("RADIO", COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, Speed, true)
Route[#Route+1] = WaypointFrom
--- Create a route point of type air.
@@ -639,7 +639,7 @@ function AI_CARGO_HELICOPTER:onafterHome( Helicopter, From, Event, To, Coordinat
local landheight = CoordinateTo:GetLandHeight() -- get target height
CoordinateTo.y = landheight + Height -- flight height should be 50m above ground
local WaypointTo = CoordinateTo:WaypointAir("RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, Speed, true)
local WaypointTo = CoordinateTo:WaypointAir("RADIO", COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, Speed, true)
Route[#Route+1] = WaypointTo

View File

@@ -725,7 +725,7 @@ function AI_FORMATION:onafterFormationLine( FollowGroupSet, From , Event , To, X
for FollowID, FollowGroup in pairs( FollowSet ) do
local PointVec3 = POINT_VEC3:New()
local PointVec3 = COORDINATE:New()
PointVec3:SetX( XStart + i * XSpace )
PointVec3:SetY( YStart + i * YSpace )
PointVec3:SetZ( ZStart + i * ZSpace )
@@ -877,7 +877,7 @@ function AI_FORMATION:onafterFormationCenterWing( FollowGroupSet, From , Event ,
for FollowID, FollowGroup in pairs( FollowSet ) do
local PointVec3 = POINT_VEC3:New()
local PointVec3 = COORDINATE:New()
local Side = ( i % 2 == 0 ) and 1 or -1
local Row = i / 2 + 1
@@ -936,7 +936,7 @@ function AI_FORMATION:onafterFormationBox( FollowGroupSet, From , Event , To, XS
for FollowID, FollowGroup in pairs( FollowSet ) do
local PointVec3 = POINT_VEC3:New()
local PointVec3 = COORDINATE:New()
local ZIndex = i % ZLevels
local XIndex = math.floor( i / ZLevels )

View File

@@ -751,12 +751,12 @@ function AI_PATROL_ZONE:onafterRoute( Controllable, From, Event, To )
if not CurrentVec2 then return end
--Done: Create GetAltitude function for GROUP, and delete GetUnit(1).
local CurrentAltitude = self.Controllable:GetAltitude()
local CurrentPointVec3 = POINT_VEC3:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y )
local CurrentPointVec3 = COORDINATE:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y )
local ToPatrolZoneSpeed = self.PatrolMaxSpeed
local CurrentRoutePoint = CurrentPointVec3:WaypointAir(
self.PatrolAltType,
POINT_VEC3.RoutePointType.TakeOffParking,
POINT_VEC3.RoutePointAction.FromParkingArea,
COORDINATE.WaypointType.TakeOffParking,
COORDINATE.WaypointAction.FromParkingArea,
ToPatrolZoneSpeed,
true
)
@@ -767,12 +767,12 @@ function AI_PATROL_ZONE:onafterRoute( Controllable, From, Event, To )
if not CurrentVec2 then return end
--DONE: Create GetAltitude function for GROUP, and delete GetUnit(1).
local CurrentAltitude = self.Controllable:GetAltitude()
local CurrentPointVec3 = POINT_VEC3:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y )
local CurrentPointVec3 = COORDINATE:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y )
local ToPatrolZoneSpeed = self.PatrolMaxSpeed
local CurrentRoutePoint = CurrentPointVec3:WaypointAir(
self.PatrolAltType,
POINT_VEC3.RoutePointType.TurningPoint,
POINT_VEC3.RoutePointAction.TurningPoint,
COORDINATE.WaypointType.TurningPoint,
COORDINATE.WaypointAction.TurningPoint,
ToPatrolZoneSpeed,
true
)
@@ -792,13 +792,13 @@ function AI_PATROL_ZONE:onafterRoute( Controllable, From, Event, To )
self:T2( { self.PatrolMinSpeed, self.PatrolMaxSpeed, ToTargetSpeed } )
--- Obtain a 3D @{Point} from the 2D point + altitude.
local ToTargetPointVec3 = POINT_VEC3:New( ToTargetVec2.x, ToTargetAltitude, ToTargetVec2.y )
local ToTargetPointVec3 = COORDINATE:New( ToTargetVec2.x, ToTargetAltitude, ToTargetVec2.y )
--- Create a route point of type air.
local ToTargetRoutePoint = ToTargetPointVec3:WaypointAir(
self.PatrolAltType,
POINT_VEC3.RoutePointType.TurningPoint,
POINT_VEC3.RoutePointAction.TurningPoint,
COORDINATE.WaypointType.TurningPoint,
COORDINATE.WaypointAction.TurningPoint,
ToTargetSpeed,
true
)
@@ -890,12 +890,12 @@ function AI_PATROL_ZONE:onafterRTB()
--DONE: Create GetAltitude function for GROUP, and delete GetUnit(1).
--local CurrentAltitude = self.Controllable:GetUnit(1):GetAltitude()
local CurrentAltitude = self.Controllable:GetAltitude()
local CurrentPointVec3 = POINT_VEC3:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y )
local CurrentPointVec3 = COORDINATE:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y )
local ToPatrolZoneSpeed = self.PatrolMaxSpeed
local CurrentRoutePoint = CurrentPointVec3:WaypointAir(
self.PatrolAltType,
POINT_VEC3.RoutePointType.TurningPoint,
POINT_VEC3.RoutePointAction.TurningPoint,
COORDINATE.WaypointType.TurningPoint,
COORDINATE.WaypointAction.TurningPoint,
ToPatrolZoneSpeed,
true
)

View File

@@ -275,14 +275,14 @@
-- The cargo must be in the **Loaded** state.
-- @function [parent=#CARGO] UnBoard
-- @param #CARGO self
-- @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.
-- @param Core.Point#COORDINATE ToPointVec2 (optional) @{Core.Point#COORDINATE) 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) @{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.
-- @param Core.Point#COORDINATE ToPointVec2 (optional) @{Core.Point#COORDINATE) to where the cargo should run after onboarding. If not provided, the cargo will run to 60 meters behind the Carrier location.
-- Load
@@ -307,14 +307,14 @@
-- The cargo must be in the **Loaded** state.
-- @function [parent=#CARGO] UnLoad
-- @param #CARGO self
-- @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.
-- @param Core.Point#COORDINATE ToPointVec2 (optional) @{Core.Point#COORDINATE) 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) @{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.
-- @param Core.Point#COORDINATE ToPointVec2 (optional) @{Core.Point#COORDINATE) 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
@@ -467,7 +467,7 @@ do -- CARGO
self.Type = Type
self.Name = Name
self.Weight = Weight or 0
self.CargoObject = nil
self.CargoObject = nil -- Wrapper.Group#GROUP
self.CargoCarrier = nil -- Wrapper.Client#CLIENT
self.Representable = false
self.Slingloadable = false
@@ -897,7 +897,7 @@ do -- CARGO
--- Get the current PointVec2 of the cargo.
-- @param #CARGO self
-- @return Core.Point#POINT_VEC2
-- @return Core.Point#COORDINATE
function CARGO:GetPointVec2()
return self.CargoObject:GetPointVec2()
end
@@ -1094,7 +1094,7 @@ do -- CARGO_REPRESENTABLE
--- Route a cargo unit to a PointVec2.
-- @param #CARGO_REPRESENTABLE self
-- @param Core.Point#POINT_VEC2 ToPointVec2
-- @param Core.Point#COORDINATE ToPointVec2
-- @param #number Speed
-- @return #CARGO_REPRESENTABLE
function CARGO_REPRESENTABLE:RouteTo( ToPointVec2, Speed )

View File

@@ -114,7 +114,7 @@ do -- CARGO_CRATE
-- @param #string Event
-- @param #string From
-- @param #string To
-- @param Core.Point#POINT_VEC2
-- @param Core.Point#COORDINATE
function CARGO_CRATE:onenterUnLoaded( From, Event, To, ToPointVec2 )
--self:T( { ToPointVec2, From, Event, To } )

View File

@@ -22,6 +22,7 @@ do -- CARGO_GROUP
--- @type CARGO_GROUP
-- @field Core.Set#SET_CARGO CargoSet The collection of derived CARGO objects.
-- @field #string GroupName The name of the CargoGroup.
-- @field Wrapper.Group#GROUÜ CargoCarrier The carrier group.
-- @extends Cargo.Cargo#CARGO_REPORTABLE
--- Defines a cargo that is represented by a @{Wrapper.Group} object within the simulator.
@@ -410,7 +411,7 @@ do -- CARGO_GROUP
-- @param #string Event
-- @param #string From
-- @param #string To
-- @param Core.Point#POINT_VEC2 ToPointVec2
-- @param Core.Point#COORDINATE ToPointVec2
-- @param #number NearRadius If distance is smaller than this number, cargo is loaded into the carrier.
function CARGO_GROUP:onafterUnBoard( From, Event, To, ToPointVec2, NearRadius, ... )
self:T( {From, Event, To, ToPointVec2, NearRadius } )
@@ -453,7 +454,7 @@ do -- CARGO_GROUP
-- @param #string Event
-- @param #string From
-- @param #string To
-- @param Core.Point#POINT_VEC2 ToPointVec2
-- @param Core.Point#COORDINATE 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:T( { From, Event, To, ToPointVec2, NearRadius } )
@@ -491,7 +492,7 @@ do -- CARGO_GROUP
-- @param #string Event
-- @param #string From
-- @param #string To
-- @param Core.Point#POINT_VEC2 ToPointVec2
-- @param Core.Point#COORDINATE ToPointVec2
function CARGO_GROUP:onafterUnLoad( From, Event, To, ToPointVec2, ... )
--self:T( { From, Event, To, ToPointVec2 } )
@@ -771,3 +772,4 @@ do -- CARGO_GROUP
end -- CARGO_GROUP

View File

@@ -72,7 +72,7 @@ do -- CARGO_UNIT
-- @param #string Event
-- @param #string From
-- @param #string To
-- @param Core.Point#POINT_VEC2 ToPointVec2
-- @param Core.Point#COORDINATE ToPointVec2
-- @param #number NearRadius (optional) Defaut 25 m.
function CARGO_UNIT:onenterUnBoarding( From, Event, To, ToPointVec2, NearRadius )
self:T( { From, Event, To, ToPointVec2, NearRadius } )
@@ -145,7 +145,7 @@ do -- CARGO_UNIT
-- @param #string Event
-- @param #string From
-- @param #string To
-- @param Core.Point#POINT_VEC2 ToPointVec2
-- @param Core.Point#COORDINATE ToPointVec2
-- @param #number NearRadius (optional) Defaut 100 m.
function CARGO_UNIT:onleaveUnBoarding( From, Event, To, ToPointVec2, NearRadius )
self:T( { From, Event, To, ToPointVec2, NearRadius } )
@@ -171,7 +171,7 @@ do -- CARGO_UNIT
-- @param #string Event
-- @param #string From
-- @param #string To
-- @param Core.Point#POINT_VEC2 ToPointVec2
-- @param Core.Point#COORDINATE ToPointVec2
-- @param #number NearRadius (optional) Defaut 100 m.
function CARGO_UNIT:onafterUnBoarding( From, Event, To, ToPointVec2, NearRadius )
self:T( { From, Event, To, ToPointVec2, NearRadius } )
@@ -197,7 +197,7 @@ do -- CARGO_UNIT
-- @param #string Event
-- @param #string From
-- @param #string To
-- @param Core.Point#POINT_VEC2
-- @param Core.Point#COORDINATE
function CARGO_UNIT:onenterUnLoaded( From, Event, To, ToPointVec2 )
self:T( { ToPointVec2, From, Event, To } )

View File

@@ -157,6 +157,8 @@ ASTAR = {
-- @field #number surfacetype Surface type.
-- @field #table valid Cached valid/invalid nodes.
-- @field #table cost Cached cost.
-- @field Core.Pathline#PATHLINE pathline Pathline that node is part of.
-- @field Core.Pathline#PATHLINE.Point pathpoint Pathline point.
--- ASTAR infinity.
-- @field #number INF
@@ -164,7 +166,7 @@ ASTAR.INF=1/0
--- ASTAR class version.
-- @field #string version
ASTAR.version="0.4.0"
ASTAR.version="0.5.0"
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO list
@@ -172,6 +174,7 @@ ASTAR.version="0.4.0"
-- TODO: Add more valid neighbour functions.
-- TODO: Write docs.
-- DONE: Add pathlines for seach/valid neighbours.
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Constructor
@@ -244,7 +247,10 @@ end
function ASTAR:AddNode(Node)
self.nodes[Node.id]=Node
self.Nnodes=self.Nnodes+1
self.Nnodes=self.Nnodes+1
self:T3(self.lid..string.format("Adding node UID=%d", Node.id))
--Node.coordinate:MarkToAll(string.format("Node ID=%d", Node.id))
return self
end
@@ -262,6 +268,47 @@ function ASTAR:AddNodeFromCoordinate(Coordinate)
return node
end
--- Adds nodes to the table of grid nodes from a PATHLINE.
-- @param #ASTAR self
-- @param Core.Pathline#PATHLINE Pathline Pathline or name of pathline. Has to exist.
-- @return #ASTAR self
function ASTAR:AddNodeFromPathlineName(Pathline)
if type(Pathline)=="string" then
Pathline=PATHLINE:FindByName(Pathline)
end
if Pathline then
for i,_point in pairs(Pathline.points) do
local point=_point --Core.Pathline#PATHLINE.Point
-- Create node from point coordinate.
local node=self:AddNodeFromCoordinate(COORDINATE:NewFromVec3(point.vec3))
-- Add pathline parameters.
node.pathline=Pathline
node.pathpoint=point
-- Debug.
local name=node.pathline and node.pathline.name or "N/A"
local idx=node.pathline and node.pathline:_GetPointIndex(node.pathpoint) or "N/A"
-- Debug message.
self:T(self.lid..string.format("Adding node UID=%d pathline=%s [%s]", node.id, name, tostring(idx)))
-- Debug mark
--node.coordinate:MarkToAll(string.format("Node ID=%d\npathline=%s [%s]", node.id, name, tostring(idx)))
end
else
env.error("FF error pathline")
end
return self
end
--- Check if the coordinate of a node has is at a valid surface type.
-- @param #ASTAR self
-- @param #ASTAR.Node Node The node to be added.
@@ -340,6 +387,18 @@ function ASTAR:SetValidNeighbourRoad(MaxDistance)
return self
end
--- Set valid neighbours to be on the same pathline or not further apart than 10 meters to jump from one pathline to another.
-- @param #ASTAR self
-- @param #number MaxDistance Max allowed distance between nodes of different pathlines in meters. Default is 10 m.
-- @return #ASTAR self
function ASTAR:SetValidNeighbourPathline(MaxDistance)
self:SetValidNeighbourFunction(ASTAR.Pathline, MaxDistance)
return self
end
--- Set the function which calculates the "cost" to go from one to another node.
-- The first to arguments of this function are always the two nodes under consideration. But you can add optional arguments.
-- Very often the distance between nodes is a good measure for the cost.
@@ -384,7 +443,7 @@ end
-- @return #ASTAR self
function ASTAR:SetCostRoad()
self:SetCostFunction(ASTAR)
self:SetCostFunction(ASTAR.Road)
return self
end
@@ -544,6 +603,55 @@ function ASTAR.Road(nodeA, nodeB)
end
--- Function to check if two nodes are on the same pathline or if nodes are less than 10 meters apart.
-- @param #ASTAR.Node nodeA First node.
-- @param #ASTAR.Node nodeB Other node.
-- @param #number distmax Max distance in meters. Default is 10 m.
-- @return #boolean If true, two nodes are connected.
function ASTAR.Pathline(nodeA, nodeB, distmax)
distmax=distmax or 10
if nodeA.pathline.name==nodeB.pathline.name then
-- Nodes are on the same pathline. We use the index to check if they are neighbours.
local pathline=nodeA.pathline
local idxA=pathline:_GetPointIndex(nodeA.pathpoint)
local idxB=pathline:_GetPointIndex(nodeB.pathpoint)
if math.abs(idxA-idxB)<=1 then
return true
end
else
-- Check if nodeB is close to pathline of nodeA.
local c, dist, segA=nodeA.pathline:GetClosestPoint3D(nodeB.coordinate)
local seg=segA --Core.Pathline#PATHLINE.Segment
if dist<distmax and (nodeA.pathpoint.uid==seg.p1.uid or nodeA.pathpoint.uid==seg.p2.uid) then
--env.info(string.format("FF NodeB=%d [pathline=%s] is close to NodeA=%d [pathline=%s] ==> valid neighbour", nodeB.id, nodeB.pathline.name, nodeA.id, nodeA.pathline.name))
return true
end
-- Check if nodeA is close to pathline of nodeB.
local c, dist, segB=nodeB.pathline:GetClosestPoint3D(nodeA.coordinate)
local seg=segB --Core.Pathline#PATHLINE.Segment
if dist<distmax and (nodeB.pathpoint.uid==seg.p1.uid or nodeB.pathpoint.uid==seg.p2.uid) then
--env.info(string.format("FF NodeA=%d [pathline=%s] is close to NodeB=%d [pathline=%s] ==> valid neighbour", nodeA.id, nodeA.pathline.name, nodeB.id, nodeB.pathline.name))
return true
end
end
return false
end
--- Function to check if distance between two nodes is less than a threshold distance.
-- @param #ASTAR.Node nodeA First node.
-- @param #ASTAR.Node nodeB Other node.
@@ -567,7 +675,9 @@ end
-- @param #ASTAR.Node nodeB Other node.
-- @return #number Distance between the two nodes.
function ASTAR.Dist2D(nodeA, nodeB)
local dist=nodeA.coordinate:Get2DDistance(nodeB)
local dist=nodeA.coordinate:Get2DDistance(nodeB.coordinate)
--local text=string.format("FF Cost Dist2D NodeA=%d-->NodeB=%d = %.1f", nodeA.id, nodeB.id, dist)
--env.info(text)
return dist
end
@@ -594,7 +704,7 @@ function ASTAR.DistRoad(nodeA, nodeB)
local dist=0
for i=2,#path do
local b=path[i] --DCS#Vec2
local b=path[i] --DCS#Vec2
local a=path[i-1] --DCS#Vec2
dist=dist+UTILS.VecDist2D(a,b)
@@ -604,7 +714,6 @@ function ASTAR.DistRoad(nodeA, nodeB)
return dist
end
return math.huge
end
@@ -614,10 +723,11 @@ end
--- Find the closest node from a given coordinate.
-- @param #ASTAR self
-- @param Core.Point#COORDINATE Coordinate.
-- @return #ASTAR.Node Cloest node to the coordinate.
-- @param Core.Point#COORDINATE Coordinate Reference coordinate.
-- @param #table ExcludeNodes Table of nodes that are excluded.
-- @return #ASTAR.Node Closest node to the coordinate.
-- @return #number Distance to closest node in meters.
function ASTAR:FindClosestNode(Coordinate)
function ASTAR:FindClosestNode(Coordinate, ExcludeNodes)
local distMin=math.huge
local closeNode=nil
@@ -625,11 +735,15 @@ function ASTAR:FindClosestNode(Coordinate)
for _,_node in pairs(self.nodes) do
local node=_node --#ASTAR.Node
local dist=node.coordinate:Get2DDistance(Coordinate)
if ExcludeNodes==nil or self:_IsNodeNotInTable(ExcludeNodes, node) then
if dist<distMin then
distMin=dist
closeNode=node
local dist=node.coordinate:Get2DDistance(Coordinate)
if dist<distMin then
distMin=dist
closeNode=node
end
end
end
@@ -637,38 +751,162 @@ function ASTAR:FindClosestNode(Coordinate)
return closeNode, distMin
end
--- Find the closest pathline to a given reference coordinate.
-- @param #ASTAR self
-- @param Core.Point#COORDINATE Coordinate Reference coordinate.
-- @return Core.Pathline#PATHLINE Closest pathline
-- @return #number Distance in meters.
-- @return DCS#Vec3 Closest point on pathline to the ref coordinate.
-- @return Core.Pathline#PATHLINE.Segment Segment.
function ASTAR:FindClosestPathline(Coordinate)
local pathline=nil --Core.Pathline#PATHLINE
local dist=math.huge
local vec3=nil
local S=nil
for _,_node in pairs(self.nodes) do
local node=_node --#ASTAR.Node
if node.pathline then
local vec, d, s=node.pathline:GetClosestPoint3D(Coordinate)
if d<dist then
pathline=node.pathline
dist=d
vec3=vec
S=s
end
end
end
if pathline then
-- Debug info.
self:T(self.lid..string.format("Closest pathline %s: dist=%.1f", pathline.name, dist))
end
return pathline, dist, vec3, S
end
--- Find the closest node to the given coordinate.
-- @param #ASTAR self
-- @param Core.Point#COORDINATE Coord Reference coordinate.
-- @param #table ExcludeNodes Nodes that are excluded.
-- @return #ASTAR.Node The node that was fround
function ASTAR:_FindClosestTerminalNode(Coord, ExcludeNodes)
-- Find the closest pathline to the ref coordinate.
local pathline, dist, vec3, s=self:FindClosestPathline(Coord)
-- Find the closest node to the given start coordinate.
local node, dist2=self:FindClosestNode(Coord)
if pathline and vec3 and dist and dist2>dist then
-- Create a node on the closest pathline so we first go straight there and then along the pathline.
local node=self:AddNodeFromCoordinate(COORDINATE:NewFromVec3(vec3))
-- We also need the pathline point.
local point=pathline:AddPointFromVec3(vec3, nil, s.p1)
node.pathline=pathline
node.pathpoint=point
self:T2(self.lid..string.format("Added new node=%d, which is closest to start coord. dist=%.1f m", node.id, dist))
end
-- Find the closest node to the given start coordinate.
local Node, dist3=self:FindClosestNode(Coord, ExcludeNodes)
-- Debug info.
self:T(self.lid..string.format("CLOSEST node ID=%d, distance=%.1f", Node.id, dist3))
return Node, dist3
end
--- Find the start node.
-- @param #ASTAR self
-- @param #ASTAR.Node Node The node to be added to the nodes table.
-- @return #ASTAR self
function ASTAR:FindStartNode()
-- Find the closest pathline to the
local pathline, dist, vec3, s=self:FindClosestPathline(self.startCoord)
local node, dist=self:FindClosestNode(self.startCoord)
-- Find the closest node to the given start coordinate.
local node, dist2=self:FindClosestNode(self.startCoord)
self.startNode=node
if dist>1000 then
self:T(self.lid.."Adding start node to node grid!")
self:AddNode(node)
if pathline and vec3 and dist and dist2>dist then
-- Create a node on the closest pathline so we first go straight there and then along the pathline.
local node=self:AddNodeFromCoordinate(COORDINATE:NewFromVec3(vec3))
-- We also need the pathline point.
local point=pathline:AddPointFromVec3(vec3, nil, s.p1)
node.pathline=pathline
node.pathpoint=point
self:T2(self.lid..string.format("Added new node=%d, which is closest to start coord. dist=%.1f m", node.id, dist))
end
-- Find the closest node to the given start coordinate.
self.startNode, dist2=self:FindClosestNode(self.startCoord)
--self.startNode.coordinate:MarkToAll("Start Node")
-- Debug info.
self:T(self.lid..string.format("START node ID=%d", self.startNode.id))
-- Not sure why I did this. The node does not need to be added again as it is already contained in self.nodes!
-- if dist>1000 then
-- self:T(self.lid.."Adding start node to node grid!")
-- self:AddNode(node)
-- end
return self
end
--- Add a node.
--- Find the end node.
-- @param #ASTAR self
-- @param #ASTAR.Node Node The node to be added to the nodes table.
-- @return #ASTAR self
function ASTAR:FindEndNode()
local node, dist=self:FindClosestNode(self.endCoord)
self.endNode=node
if dist>1000 then
self:T(self.lid.."Adding end node to node grid!")
self:AddNode(node)
local pathline, dist, vec3, s=self:FindClosestPathline(self.endCoord)
-- Find the closest node to the given start coordinate.
local node, dist2=self:FindClosestNode(self.endCoord)
if pathline and vec3 and dist and dist2>dist then
-- Create a node on the closest pathline so we first go straight there and then along the pathline.
local node=self:AddNodeFromCoordinate(COORDINATE:NewFromVec3(vec3))
-- We also need the point.
local point=pathline:AddPointFromVec3(vec3, nil, s.p1)
-- Add pathline parameters to node.
node.pathline=pathline
node.pathpoint=point
self:T2(self.lid..string.format("Added new node=%d, which is closest to END coord: dist=%.1f m", node.id, dist))
end
-- Find closest node to the end coordinate (exclude the start coordinate.
self.endNode, dist=self:FindClosestNode(self.endCoord, {self.startNode})
--self.endNode.coordinate:MarkToAll("End Node")
-- Debug info.
self:T(self.lid..string.format("END node ID=%d", self.endNode.id))
-- Not sure why I did this. The node does not need to be added again as it is already contained in self.nodes!
-- if dist>1000 then
-- self:T(self.lid.."Adding end node to node grid!")
-- self:AddNode(node)
-- end
return self
end
@@ -684,12 +922,21 @@ end
-- @return #table Table of nodes from start to finish.
function ASTAR:GetPath(ExcludeStartNode, ExcludeEndNode)
self:FindStartNode()
self:FindEndNode()
-- self:FindStartNode()
-- self:FindEndNode()
-- Find start Node (closest node to start coordinate).
self.startNode=self:_FindClosestTerminalNode(self.startCoord)
-- Find end node, which is not the start node (excluded).
self.endNode=self:_FindClosestTerminalNode(self.endCoord, {self.startNode})
local nodes=self.nodes
local start=self.startNode
local goal=self.endNode
-- Debug info.
self:T(self.lid..string.format("GetPath Start Node=%d, End Node=%d", start.id, goal.id))
-- Sets.
local openset = {}
@@ -746,7 +993,12 @@ function ASTAR:GetPath(ExcludeStartNode, ExcludeEndNode)
text=text..string.format(", OS Time %.6f sec", dT)
end
text=text..string.format(", Nvalid=%d [%d cached]", self.nvalid, self.nvalidcache)
text=text..string.format(", Ncost=%d [%d cached]", self.ncost, self.ncostcache)
text=text..string.format(", Ncost=%d [%d cached]", self.ncost, self.ncostcache)
text=text..string.format("\nNodes:")
for i,_node in ipairs(path) do
local node=_node --#ASTAR.Node
text=text..string.format("\n[%d] Node ID=%d", i, node.id)
end
self:T(self.lid..text)
return path
@@ -759,13 +1011,16 @@ function ASTAR:GetPath(ExcludeStartNode, ExcludeEndNode)
-- Get neighbour nodes.
local neighbors=self:_NeighbourNodes(current, nodes)
-- Loop over neighbours.
for _,neighbor in pairs(neighbors) do
-- Node is not in closed set.
if self:_NotIn(closedset, neighbor.id) then
local tentative_g_score=g_score[current.id]+self:_DistNodes(current, neighbor)
-- Calculate tentative_g_score.
--local tentative_g_score=g_score[current.id] + self:_DistNodes(current, neighbor)
local tentative_g_score=g_score[current.id] + self:_HeuristicCost(current, neighbor)
if self:_NotIn(openset, neighbor.id) or tentative_g_score < g_score[neighbor.id] then
@@ -793,6 +1048,73 @@ function ASTAR:GetPath(ExcludeStartNode, ExcludeEndNode)
return nil -- no valid path
end
--- A* pathfinding function. This seaches the path along nodes between start and end nodes/coordinates.
-- It automatically creates a PATHLINE object that is returned in combination with the nodes of the optimal path.
-- @param #ASTAR self
-- @param #boolean ExcludeStartNode If *true*, do not include start node in found path. Default is to include it.
-- @param #boolean ExcludeEndNode If *true*, do not include end node in found path. Default is to include it.
-- @return Core.Pathline#PATHLINE Pathline.
-- @return #table Nodes of path.
function ASTAR:GetPathline(ExcludeStartNode, ExcludeEndNode)
local nodes=self:GetPath(ExcludeStartNode, ExcludeEndNode)
local pathline=nil --Core.Pathline#PATHLINE
if nodes then
pathline=PATHLINE:New("Astar")
for _,_node in pairs(nodes) do
local node=_node --#ASTAR.Node
local point=pathline:AddPointFromVec3(node.coordinate)
point.name=node.pathline.name
end
end
return pathline, nodes
end
--- Get pathlines from nodes.
-- @param #ASTAR self
-- @param #table Nodes Given nodes.
-- @return #table Table of PATHLINES used in the path.
function ASTAR:GetPathlinesFromNodes(Nodes)
local pathlines={}
--for _,_node in pairs(Nodes or {}) do
for i=1,#Nodes do
local node=Nodes[i] --#ASTAR.Node
-- Pathline.
local pathline=node.pathline
if pathline and i>1 and i<#Nodes then
-- Previous and next nodes.
local n=Nodes[i-1] --#ASTAR.Node
local N=Nodes[i+1] --#ASTAR.Node
-- Check if previous and next nodes are on the same pathline.
-- If only one point in beteen is of another pathline, this is a junction and we dont actually switch to the other pathline.
if n.pathline and N.pathline and n.pathline.name==N.pathline.name and n.pathline.name~=pathline.name then
pathline=n.pathline
end
end
-- We do not want to add the same pathline two times in a row.
if #pathlines==0 or (#pathlines>0 and pathlines[#pathlines].name~=pathline.name) then
table.insert(pathlines, pathline)
end
end
return pathlines
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- A* pathfinding helper functions
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
@@ -811,16 +1133,18 @@ function ASTAR:_HeuristicCost(nodeA, nodeB)
local cost=nodeA.cost[nodeB.id]
if cost~=nil then
self.ncostcache=self.ncostcache+1
self:T(self.lid..string.format("Cost nodeA=%d --> nodeB=%d = %.1f (Cashed!)", nodeA.id, nodeB.id, cost))
return cost
end
local cost=nil
if self.CostFunc then
cost=self.CostFunc(nodeA, nodeB, unpack(self.CostArg))
else
cost=self:_DistNodes(nodeA, nodeB)
end
self:T(self.lid..string.format("Cost nodeA=%d --> nodeB=%d = %.1f", nodeA.id, nodeB.id, cost))
nodeA.cost[nodeB.id]=cost
nodeB.cost[nodeA.id]=cost -- Symmetric problem.
@@ -834,9 +1158,10 @@ end
-- @return #boolean If true, transition between nodes is possible.
function ASTAR:_IsValidNeighbour(node, neighbor)
-- Counter.
-- Counter of function calls.
self.nvalid=self.nvalid+1
-- Check if neighbour is in cached set.
local valid=node.valid[neighbor.id]
if valid~=nil then
--env.info(string.format("Node %d has valid=%s neighbour %d", node.id, tostring(valid), neighbor.id))
@@ -844,13 +1169,16 @@ function ASTAR:_IsValidNeighbour(node, neighbor)
return valid
end
-- Check if this is a valid neighbour.
local valid=nil
if self.ValidNeighbourFunc then
valid=self.ValidNeighbourFunc(node, neighbor, unpack(self.ValidNeighbourArg))
else
-- If no valid neighbour function is defined, we assume all nodes are valid neighbours.
valid=true
end
-- Cache valid neighbour.
node.valid[neighbor.id]=valid
neighbor.valid[node.id]=valid -- Symmetric problem.
@@ -884,6 +1212,9 @@ function ASTAR:_LowestFscore(set, f_score)
end
end
-- Debug info.
self:T(self.lid..string.format("Lowest Fscore=%.1f, Node=%s", lowest, tostring(bestNode)))
return self.nodes[bestNode]
end
@@ -928,16 +1259,46 @@ end
-- @param #table map Map.
-- @param #ASTAR.Node current_node The current node.
-- @return #table Unwinded path.
function ASTAR:_UnwindPath( flat_path, map, current_node )
function ASTAR:_UnwindPath(flat_path, map, current_node)
if map [current_node] then
table.insert (flat_path, 1, map[current_node])
return self:_UnwindPath(flat_path, map, map[current_node])
local previous_node=map[current_node]
if previous_node then
table.insert(flat_path, 1, previous_node)
return self:_UnwindPath(flat_path, map, previous_node)
else
-- No previous node ==> return path.
return flat_path
end
end
--- Function to check if a certain node is in a given table.
-- @param #ASTAR self
-- @param #table Nodes Nodes table.
-- @param #ASTAR.Node Node The node to check.
-- @return #boolean If true, the node is not in the set.
function ASTAR:_IsNodeInTable(Nodes, Node)
for _,_node in pairs(Nodes) do
local node=_node --#ASTAR.Node
if node.id==Node.id then
return true
end
end
return false
end
--- Function to check if a certain node is **not** in a given table.
-- @param #ASTAR self
-- @param #table Nodes Nodes table.
-- @param #ASTAR.Node Node The node to check.
-- @return #boolean If true, the node is not in the set.
function ASTAR:_IsNodeNotInTable(Nodes, Node)
local is=self:_IsNodeInTable(Nodes, Node)
return not is
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

View File

@@ -1372,11 +1372,12 @@ function EVENT:onEvent( Event )
-- Scenery
---
Event.IniDCSUnit = Event.initiator
Event.IniDCSUnitName = Event.IniDCSUnit.getName and Event.IniDCSUnit:getName() or "Scenery no name "..math.random(1,20000)
Event.IniDCSUnitName = ( Event.IniDCSUnit and Event.IniDCSUnit.getName ) and Event.IniDCSUnit:getName() or "Scenery no name "..math.random(1,20000)
Event.IniUnitName = Event.IniDCSUnitName
Event.IniUnit = SCENERY:Register( Event.IniDCSUnitName, Event.initiator )
Event.IniCategory = Event.IniDCSUnit.getDesc and Event.IniDCSUnit:getDesc().category
Event.IniTypeName = Event.initiator:isExist() and Event.IniDCSUnit:getTypeName() or "SCENERY"
Event.IniCategory = (Event.IniDCSUnit and Event.IniDCSUnit.getDesc ) and Event.IniDCSUnit:getDesc().category
Event.IniTypeName = (Event.initiator and Event.initiator.isExist
and Event.initiator:isExist() and Event.IniDCSUnit and Event.IniDCSUnit.getTypeName) and Event.IniDCSUnit:getTypeName() or "SCENERY"
elseif Event.IniObjectCategory == Object.Category.BASE then
---

View File

@@ -5,11 +5,13 @@
-- * Path from A to B
-- * Arbitrary number of points
-- * Automatically from lines drawtool
-- * Draw line or mark points on F10 map
-- * Find closest points to path
--
-- ===
--
-- ### Author: **funkyfranky**
--
--
-- ===
-- @module Core.Pathline
-- @image CORE_Pathline.png
@@ -21,6 +23,7 @@
-- @field #string lid Class id string for output to DCS log file.
-- @field #string name Name of the path line.
-- @field #table points List of 3D points defining the path.
-- @field #number counter Running number counting the point IDs.
-- @extends Core.Base#BASE
--- *The shortest distance between two points is a straight line.* -- Archimedes
@@ -28,30 +31,30 @@
-- ===
--
-- # The PATHLINE Concept
--
--
-- List of points defining a path from A to B. The pathline can consist of multiple points. Each point holds the information of its position, the surface type, the land height
-- and the water depth (if over sea).
--
--
-- Line drawings created in the mission editor are automatically registered as pathlines and stored in the MOOSE database.
-- They can be accessed with the @{#PATHLINE.FindByName) function.
--
--
-- # Constructor
--
--
-- The @{PATHLINE.New) function creates a new PATHLINE object. This does not hold any points. Points can be added with the @{#PATHLINE.AddPointFromVec2} and @{#PATHLINE.AddPointFromVec3}
--
--
-- For a given table of 2D or 3D positions, a new PATHLINE object can be created with the @{#PATHLINE.NewFromVec2Array} or @{#PATHLINE.NewFromVec3Array}, respectively.
--
--
-- # Line Drawings
--
--
-- The most convenient way to create a pathline is the draw panel feature in the DCS mission editor. You can select "Line" and then "Segments", "Segment" or "Free" to draw your lines.
-- These line drawings are then automatically added to the MOOSE database as PATHLINE objects and can be retrieved with the @{#PATHLINE.FindByName) function, where the name is the one
-- you specify in the draw panel.
--
--
-- # Mark on F10 map
--
-- The ponints of the PATHLINE can be marked on the F10 map with the @{#PATHLINE.MarkPoints}(`true`) function. The mark points contain information of the surface type, land height and
--
-- The ponints of the PATHLINE can be marked on the F10 map with the @{#PATHLINE.MarkPoints}(`true`) function. The mark points contain information of the surface type, land height and
-- water depth.
--
--
-- To remove the marks, use @{#PATHLINE.MarkPoints}(`false`).
--
-- @field #PATHLINE
@@ -59,27 +62,39 @@ PATHLINE = {
ClassName = "PATHLINE",
lid = nil,
points = {},
counter = 0,
}
--- Point of line.
-- @type PATHLINE.Point
-- @field #number uid Unique ID of this point.
-- @field #string mother Name of the pathline this point belongs to.
-- @field #string name Name of this point.
-- @field DCS#Vec3 vec3 3D position.
-- @field DCS#Vec2 vec2 2D position.
-- @field #number surfaceType Surface type.
-- @field #number landHeight Land height in meters.
-- @field #number depth Water depth in meters.
-- @field #number markerID Marker ID.
-- @field #number lineID Marker of pathline ID.
--- Segment of line.
-- @type PATHLINE.Segment
-- @field #PATHLINE.Point p1 First point.
-- @field #PATHLINE.Point p2 Second point.
--- PATHLINE class version.
-- @field #string version
PATHLINE.version="0.1.1"
PATHLINE.version="0.3.0"
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO list
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO: A lot...
-- TODO: Read/write to JSON file
-- TODO: Translate/rotate pathline
-- TODO: Add color.
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Constructor
@@ -93,10 +108,10 @@ function PATHLINE:New(Name)
-- Inherit everything from INTEL class.
local self=BASE:Inherit(self, BASE:New()) --#PATHLINE
self.name=Name or "Unknown Path"
self.lid=string.format("PATHLINE %s | ", Name)
self.lid=string.format("PATHLINE %s | ", self.name)
return self
end
@@ -151,41 +166,70 @@ end
--- Add a point to the path from a given 2D position. The third dimension is determined from the land height.
-- @param #PATHLINE self
-- @param DCS#Vec2 Vec2 The 2D vector (x,y) to add.
-- @param #number Index Index to add this point, *e.g.* 1 for first point or 2 for second point. Default is at the end.
-- @param #PATHLINE.Point Point Add point after given point. Default is at the end or at given index.
-- @return #PATHLINE self
function PATHLINE:AddPointFromVec2(Vec2)
function PATHLINE:AddPointFromVec2(Vec2, Index, Point)
if Vec2 then
-- Create a new point.
local point=self:_CreatePoint(Vec2)
table.insert(self.points, point)
if Index then
-- Add at given index.
table.insert(self.points, Index, point)
else
if Point then
-- Get index of given point.
local i=self:_GetPointIndex(Point)
-- Add new point after given point.
table.insert(self.points, i+1, point)
else
-- Add add the end.
table.insert(self.points, point)
end
end
end
return self
end
--- Add a point to the path from a given 3D position.
-- @param #PATHLINE self
-- @param DCS#Vec3 Vec3 The 3D vector (x,y) to add.
-- @return #PATHLINE self
function PATHLINE:AddPointFromVec3(Vec3)
-- @param #number Index Index to add this point, *e.g.* 1 for first point or 2 for second point. Default is at the end.
-- @param #PATHLINE.Point Point Add point after given point. Default is at the end or at given index.
-- @return #PATHLINE.Point Point that was added.
function PATHLINE:AddPointFromVec3(Vec3, Index, Point)
if Vec3 then
local point=self:_CreatePoint(Vec3)
table.insert(self.points, point)
if Index then
-- Add add given index.
table.insert(self.points, Index, point)
else
if Point then
local i=self:_GetPointIndex(Point)
table.insert(self.points, i+1, point)
else
-- Add add the end.
table.insert(self.points, point)
end
end
return point
end
return self
return nil
end
--- Get name of pathline.
-- @param #PATHLINE self
-- @return #string Name of the pathline.
function PATHLINE:GetName()
function PATHLINE:GetName()
return self.name
end
@@ -199,18 +243,35 @@ end
--- Get points of pathline. Not that points are tables, that contain more information as just the 2D or 3D position but also the surface type etc.
-- @param #PATHLINE self
-- @return #list <#PATHLINE.Point> List of points.
function PATHLINE:GetPoints()
-- @return #list <Core.Pathline#PATHLINE.Point> List of points.
function PATHLINE:GetPoints()
return self.points
end
--- Get segments of pathline.
-- @param #PATHLINE self
-- @return #list <Core.Pathline#PATHLINE.Segment> List of points.
function PATHLINE:GetSetments()
local segments={}
for i=1,#self.points-1 do
local segment={} --#PATHLINE.Segment
segment.p1=self.points[i]
segment.p2=self.points[i+1]
table.insert(segments, segment)
end
return segments
end
--- Get 3D points of pathline.
-- @param #PATHLINE self
-- @return <DCS#Vec3> List of DCS#Vec3 points.
-- @return #list <DCS#Vec3> List of DCS#Vec3 points.
function PATHLINE:GetPoints3D()
local vecs={}
for _,_point in pairs(self.points) do
local point=_point --#PATHLINE.Point
table.insert(vecs, point.vec3)
@@ -221,11 +282,11 @@ end
--- Get 2D points of pathline.
-- @param #PATHLINE self
-- @return <DCS#Vec2> List of DCS#Vec2 points.
-- @return #list <DCS#Vec2> List of DCS#Vec2 points.
function PATHLINE:GetPoints2D()
local vecs={}
for _,_point in pairs(self.points) do
local point=_point --#PATHLINE.Point
table.insert(vecs, point.vec2)
@@ -240,11 +301,11 @@ end
function PATHLINE:GetCoordinates()
local vecs={}
for _,_point in pairs(self.points) do
local point=_point --#PATHLINE.Point
local coord=COORDINATE:NewFromVec3(point.vec3)
table.insert(vecs,coord)
table.insert(vecs, coord)
end
return vecs
@@ -257,11 +318,11 @@ end
function PATHLINE:GetPointFromIndex(n)
local N=self:GetNumberOfPoints()
n=n or 1
local point=nil --#PATHLINE.Point
if n>=1 and n<=N then
point=self.points[n]
else
@@ -278,11 +339,11 @@ end
function PATHLINE:GetPoint3DFromIndex(n)
local point=self:GetPointFromIndex(n)
if point then
return point.vec3
end
return nil
end
@@ -293,11 +354,11 @@ end
function PATHLINE:GetPoint2DFromIndex(n)
local point=self:GetPointFromIndex(n)
if point then
return point.vec2
end
return nil
end
@@ -305,33 +366,314 @@ end
--- Mark points on F10 map.
-- @param #PATHLINE self
-- @param #boolean Switch If `true` or nil, set marks. If `false`, remove marks.
-- @return <DCS#Vec3> List of DCS#Vec3 points.
-- @return #PATHLINE self
function PATHLINE:MarkPoints(Switch)
for i,_point in pairs(self.points) do
local point=_point --#PATHLINE.Point
if Switch==false then
if point.markerID then
UTILS.RemoveMark(point.markerID, Delay)
end
else
if point.markerID then
UTILS.RemoveMark(point.markerID)
end
else
if point.markerID then
UTILS.RemoveMark(point.markerID)
end
point.markerID=UTILS.GetMarkID()
local text=string.format("Pathline %s: Point #%d\nSurface Type=%d\nHeight=%.1f m\nDepth=%.1f m", self.name, i, point.surfaceType, point.landHeight, point.depth)
local text=string.format("Pathline %s: Point #%d [UID=%d]\nSurface Type=%d\nHeight=%.1f m\nDepth=%.1f m", self.name, i, point.uid, point.surfaceType, point.landHeight, point.depth)
trigger.action.markToAll(point.markerID, text, point.vec3, "")
end
end
return self
end
--- Draw line on F10 map.
-- @param #PATHLINE self
-- @param #boolean Switch If `true` or nil, draw pathline. If `false`, remove drawing.
-- @param #number Coalition Coalition side. Default -1 for all.
-- @param #table Color RGB color and alpha `{r, g, b, a}`. Default {0, 1, 0, 0.5}.
-- @param #number LineType Line type. Default 1=solid.
-- @return #PATHLINE self
function PATHLINE:Draw(Switch, Coalition, Color, LineType)
Coalition=Coalition or -1
Color=Color or {0, 1, 0, 0.5}
LineType=LineType or 1
if Switch==false then
for i,_point in pairs(self.points) do
local point=_point --#PATHLINE.Point
if point.lineID then
UTILS.RemoveMark(point.lineID)
end
end
else
for i=2,#self.points do
local p1=self.points[i-1] --#PATHLINE.Point
local p2=self.points[i] --#PATHLINE.Point
if p2.lineID then
UTILS.RemoveMark(p2.lineID)
end
p2.lineID=UTILS.GetMarkID()
trigger.action.lineToAll(Coalition, p2.lineID, p1.vec3, p2.vec3, Color, LineType)
end
end
return self
end
--- Get the closest point on the pathline for a given reference point.
-- @param #PATHLINE self
-- @param DCS#Vec2 Vec2 Reference Point in 2D.
-- @return DCS#Vec2 Cloest point on pathline.
-- @return #number Distance from closest point to ref point in meters.
-- @return #PATHLINE.Segment Closest segment of ref point.
function PATHLINE:GetClosestPoint2D(Vec2)
local P=nil --DCS#Vec2
local D=math.huge
local S={} --#PATHLINE.Segment
for i=2,#self.points do
local A=self.points[i-1] --#PATHLINE.Point
local B=self.points[i] --#PATHLINE.Point
local a=A.vec2
local b=B.vec2
local ab=UTILS.Vec2Substract(b, a)
local ap=UTILS.Vec2Substract(Vec2, a)
local proj=UTILS.Vec2Dot(ap, ab)
local lab=UTILS.Vec2Norm(ab)
local f=proj/lab/lab
-- Debug info.
local text=string.format("FF Proj=%.1f, |ab|=%.1f, f=%.1f", proj, lab, f)
self:T(self.lid..text)
-- Cases for finite segment.
local p=nil --DCS#Vec2
if f<0 then
p=a
elseif f>1 then
p=b
else
local r=UTILS.Vec2Mult(ab, f)
p=UTILS.Vec2Add(a, r)
end
-- Distance.
local d=UTILS.VecDist2D(p, Vec2)
if d<=D then
D=d
P=p
S.p1=A
S.p2=B
end
end
return P, D, S
end
--- Get the closest point on the pathline for a given reference point.
-- This point does not necessarily is a node of the pathline. In general it will be somewhere in between the nodes defining the pathline.
-- @param #PATHLINE self
-- @param DCS#Vec3 Vec3 Reference Point in 3D. Can also be a `COORDINATE`.
-- @return DCS#Vec3 Closest point on pathline.
-- @return #number Distance from closest point to ref point in meters.
-- @return #PATHLINE.Segment Closest segment of ref point.
function PATHLINE:GetClosestPoint3D(Vec3)
local P=nil --DCS#Vec3
local D=math.huge
local S={} --#PATHLINE.Segment
if not Vec3 then
self:E(self.lid.."ERROR: input Vec3 is nil!")
return nil, nil, nil
end
for i=2,#self.points do
local A=self.points[i-1] --#PATHLINE.Point
local B=self.points[i] --#PATHLINE.Point
local a=A.vec3
local b=B.vec3
local ab=UTILS.VecSubstract(b, a)
local ap=UTILS.VecSubstract(Vec3, a)
local proj=UTILS.VecDot(ap, ab)
local lab=UTILS.VecNorm(ab)
local f=proj/lab/lab
-- Debug info.
self:T(self.lid..string.format("Proj=%.1f, |ab|=%.1f, f=%.1f", proj, lab, f))
-- Cases for finite segment.
local p=nil --DCS#Vec2
if f<0 then
p=a
elseif f>1 then
p=b
else
local r=UTILS.VecMult(ab, f)
p=UTILS.VecAdd(a, r)
end
-- Distance.
local d=UTILS.VecDist3D(p, Vec3)
if d<=D then
D=d
P=p
S.p1=A
S.p2=B
end
end
return P, D, S
end
--- Write PATHLINE to JSON file.
-- **NOTE**: Requires `io` and `lfs` to be de-sanitized!
-- @param #PATHLINE self
-- @param #string FileName Name of the file. Default is the name of the pathline.
-- @return #PATHLINE self
function PATHLINE:WriteJSON(FileName)
if io and lfs then
-- JSON script.
local json=loadfile("Scripts\\JSON.lua")()
local data={}
-- We store the name and the points.
data.name=self.name
data.points=self.points
for i,_point in pairs(self.points) do
local point=_point --#PATHLINE.Point
--point.markerID=nil
end
-- Encode data to raw JSON. Encode converts a lua table into JSON string that can be written to file.
local raw_json=json:encode(data)
-- Debug data.
self:T(data)
-- Write in "User/Saved Games/" Folder.
local filepath=lfs.writedir() .. FileName
-- Open file for writing.
local f = io.open(filepath, "wb")
if f then
f:write(raw_json)
f:close()
self:T(self.lid .. string.format("Saving PATHLINE %s file %s", self.name, tostring(filepath)))
else
self:E(self.lid .. string.format( "ERROR: Could not save PATHLINE to file %s", tostring(filepath)))
end
else
self:E(self.lid .. string.format( "ERROR: Could not save results because IO and/or LFS are not de-sanitized!"))
end
end
--- Read PATHLINE from JSON file.
-- **NOTE**: Requires `io` and `lfs` to be de-sanitized!
-- @param #PATHLINE self
-- @param #string FileName Name of the file.
-- @return #PATHLINE self
function PATHLINE:NewFromJSON(FileName)
if io and lfs then
-- JSON script.
local json=loadfile("Scripts\\JSON.lua")()
local data={}
-- Write in "User/Saved Games/" Folder.
local filepath=lfs.writedir() .. FileName
--env.info(filepath)
-- Open file in binary mode for reading.
local f = io.open(filepath, "rb")
if f then
data = f:read("*all")
f:close()
else
env.info(string.format("WARNING: Could not load PATHLINE from file %s!", tostring(filepath)))
return nil
end
-- Decode JSON data to get a lua table.
local data=json:decode(data)
if data and data.name then
-- Create a new pathline instance.
local self=PATHLINE:New(data.name)
for i=1,#data.points do
local point=data.points[i] --#PATHLINE.Point
-- Create new point from data.
local p=self:AddPointFromVec3(point.vec3)
-- Set name.
p.name=point.name
-- Remove marker ID.
p.markerID=nil
end
return self
else
BASE:E("ERROR: Cannot find pathline name in data from JSON file. File may be corrupted!")
end
else
BASE:E("ERROR: IO and/or LFS not de-sanitized! Cannot read file.")
end
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Private functions
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
@@ -339,32 +681,56 @@ end
--- Get 3D points of pathline.
-- @param #PATHLINE self
-- @param DCS#Vec3 Vec Position vector. Can also be a DCS#Vec2 in which case the altitude at landheight is taken.
-- @return #PATHLINE.Point
-- @return #PATHLINE.Point Pathline Point.
function PATHLINE:_CreatePoint(Vec)
local point={} --#PATHLINE.Point
self.counter=self.counter+1
point.uid=self.counter
point.mother=self.name
point.name=string.format("%s #%d", self.name, point.uid)
if Vec.z then
-- Given vec is 3D
point.vec3=UTILS.DeepCopy(Vec)
point.vec2={x=Vec.x, y=Vec.z}
else
-- Given vec is 2D
-- Given vec is 2D
point.vec2=UTILS.DeepCopy(Vec)
point.vec3={x=Vec.x, y=land.getHeight(Vec), z=Vec.y}
end
-- Get surface type.
point.surfaceType=land.getSurfaceType(point.vec2)
-- Get land height and depth.
point.landHeight, point.depth=land.getSurfaceHeightWithSeabed(point.vec2)
point.markerID=nil
return point
end
--- Get index of point in the lua table.
-- @param #PATHLINE self
-- @param #PATHLINE.Point Point Given point.
-- @return #number index
function PATHLINE:_GetPointIndex(Point)
for i,_point in pairs(self.points) do
local point=_point --#PATHLINE.Point
if point.uid==Point.uid then
return i
end
end
return nil
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

View File

@@ -453,6 +453,23 @@ do -- COORDINATE
end
--- Returns the coordinate from the latitude and longitude given in degrees, minutes and seconds (DMS).
-- @param #COORDINATE self
-- @param #string Latitude Latitude in DMS as string, e.g. "`42° 24' 14.3"`". Not that the characters `°`, `'` and `"` are important.
-- @param #string Longitude Longitude in DMS as string, e.g. "`42° 24' 14.3"`". Not that the characters `°`, `'` and `"` are important.
-- @param #number Altitude (Optional) Altitude in meters. Default is the land height at the coordinate.
-- @return #COORDINATE
function COORDINATE:NewFromLLDMS(Latitude, Longitude, Altitude)
local lat=UTILS.LLDMSstringToDD(Latitude)
local lon=UTILS.LLDMSstringToDD(Longitude)
self=COORDINATE:NewFromLLDD(lat, lon, Altitude)
return self
end
--- Returns if the 2 coordinates are at the same 2D position.
-- @param #COORDINATE self
-- @param #COORDINATE Coordinate
@@ -661,7 +678,7 @@ do -- COORDINATE
local _,_,_,_,_,scenerys=self:ScanObjects(radius, false, false, true)
local set={}
for _,_scenery in pairs(scenerys) do
local scenery=_scenery --DCS#Object
@@ -1157,6 +1174,162 @@ do -- COORDINATE
return vec3
end
--- Return the x coordinate of the COORDINATE.
-- @param #COORDINATE self
-- @return #number The x coordinate.
function COORDINATE:GetX()
return self.x
end
--- Return the y coordinate of the COORDINATE.
-- @param #COORDINATE self
-- @return #number The y coordinate.
function COORDINATE:GetY()
if self:IsInstanceOf("POINT_VEC2") then
return self.z
end
return self.y
end
--- Return the z coordinate of the COORDINATE.
-- @param #COORDINATE self
-- @return #number The z coordinate.
function COORDINATE:GetZ()
return self.z
end
--- Set the x coordinate of the COORDINATE.
-- @param #COORDINATE self
-- @param #number x The x coordinate.
-- @return #COORDINATE
function COORDINATE:SetX( x )
self.x = x
return self
end
--- Set the y coordinate of the COORDINATE.
-- @param #COORDINATE self
-- @param #number y The y coordinate.
-- @return #COORDINATE
function COORDINATE:SetY( y )
if self:IsInstanceOf("POINT_VEC2") then
self.z = y
else
self.y = y
end
return self
end
--- Set the z coordinate of the COORDINATE.
-- @param #COORDINATE self
-- @param #number z The z coordinate.
-- @return #COORDINATE
function COORDINATE:SetZ( z )
self.z = z
return self
end
--- Add to the x coordinate of the COORDINATE.
-- @param #COORDINATE self
-- @param #number x The x coordinate value to add to the current x coordinate.
-- @return #COORDINATE
function COORDINATE:AddX( x )
self.x = self.x + x
return self
end
--- Return Return the Lat(itude) coordinate of the COORDINATE (ie: (parent)COORDINATE.x).
-- @param #COORDINATE self
-- @return #number The x coordinate.
function COORDINATE:GetLat()
return self.x
end
--- Set the Lat(itude) coordinate of the COORDINATE (ie: COORDINATE.x).
-- @param #COORDINATE self
-- @param #number x The x coordinate.
-- @return #COORDINATE
function COORDINATE:SetLat( x )
self.x = x
return self
end
--- Return the Lon(gitude) coordinate of the COORDINATE (ie: (parent)COORDINATE.z).
-- @param #COORDINATE self
-- @return #number The y coordinate.
function COORDINATE:GetLon()
return self.z
end
--- Set the Lon(gitude) coordinate of the COORDINATE (ie: COORDINATE.z).
-- @param #COORDINATE self
-- @param #number y The y coordinate.
-- @return #COORDINATE
function COORDINATE:SetLon( z )
self.z = z
return self
end
--- Return the altitude (height) of the land at the COORDINATE.
-- @param #COORDINATE self
-- @return #number The land altitude.
function COORDINATE:GetAlt()
return self.y ~= 0 or land.getHeight( { x = self.x, y = self.z } )
end
--- Set the altitude of the COORDINATE.
-- @param #COORDINATE self
-- @param #number Altitude The land altitude. If nothing (nil) is given, then the current land altitude is set.
-- @return #COORDINATE
function COORDINATE:SetAlt( Altitude )
self.y = Altitude or land.getHeight( { x = self.x, y = self.z } )
return self
end
--- Add to the current land height an altitude.
-- @param #COORDINATE self
-- @param #number Altitude The Altitude to add. If nothing (nil) is given, then the current land altitude is set.
-- @return #COORDINATE
function COORDINATE:AddAlt( Altitude )
self.y = land.getHeight( { x = self.x, y = self.z } ) + Altitude or 0
return self
end
--- Return a random COORDINATE within an Outer Radius and optionally NOT within an Inner Radius of the COORDINATE.
-- @param #COORDINATE self
-- @param DCS#Distance OuterRadius
-- @param DCS#Distance InnerRadius
-- @return #COORDINATE
function COORDINATE:GetRandomPointVec2InRadius( OuterRadius, InnerRadius )
self:F2( { OuterRadius, InnerRadius } )
return COORDINATE:NewFromVec2( self:GetRandomVec2InRadius( OuterRadius, InnerRadius ) )
end
--- Add to the y coordinate of the COORDINATE.
-- @param #COORDINATE self
-- @param #number y The y coordinate value to add to the current y coordinate.
-- @return #COORDINATE
function COORDINATE:AddY( y )
if self:IsInstanceOf("POINT_VEC2") then
return self:AddZ(y)
else
self.y = self.y + y
end
return self
end
--- Add to the z coordinate of the COORDINATE.
-- @param #COORDINATE self
-- @param #number z The z coordinate value to add to the current z coordinate.
-- @return #COORDINATE
function COORDINATE:AddZ( z )
self.z = self.z +z
return self
end
--- Returns a text documenting the wind direction (from) and strength according the measurement system @{Core.Settings}.
-- The text will reflect the wind like this:
@@ -3474,9 +3647,18 @@ do -- COORDINATE
return flat, elev
end
--- Return a random COORDINATE within an Outer Radius and optionally NOT within an Inner Radius of the COORDINATE.
-- @param #COORDINATE self
-- @param DCS#Distance OuterRadius
-- @param DCS#Distance InnerRadius
-- @return #COORDINATE
function COORDINATE:GetRandomPointVec3InRadius( OuterRadius, InnerRadius )
return COORDINATE:NewFromVec3( self:GetRandomVec3InRadius( OuterRadius, InnerRadius ) )
end
end
do -- POINT_VEC3
do
--- The POINT_VEC3 class
-- @type POINT_VEC3
@@ -3493,6 +3675,8 @@ do -- POINT_VEC3
--- Defines a 3D point in the simulator and with its methods, you can use or manipulate the point in 3D space.
--
-- **DEPRECATED - PLEASE USE COORDINATE!**
--
-- **Important Note:** Most of the functions in this section were taken from MIST, and reworked to OO concepts.
-- In order to keep the credibility of the the author,
-- I want to emphasize that the formulas embedded in the MIST framework were created by Grimes or previous authors,
@@ -3580,130 +3764,19 @@ do -- POINT_VEC3
return self
end
--- Create a new POINT_VEC3 object from Vec2 coordinates.
-- @param #POINT_VEC3 self
-- @param DCS#Vec2 Vec2 The Vec2 point.
-- @param DCS#Distance LandHeightAdd (optional) Add a landheight.
-- @return Core.Point#POINT_VEC3 self
function POINT_VEC3:NewFromVec2( Vec2, LandHeightAdd )
local self = BASE:Inherit( self, COORDINATE:NewFromVec2( Vec2, LandHeightAdd ) ) -- Core.Point#POINT_VEC3
self:F2( self )
return self
end
--- Create a new POINT_VEC3 object from Vec3 coordinates.
-- @param #POINT_VEC3 self
-- @param DCS#Vec3 Vec3 The Vec3 point.
-- @return Core.Point#POINT_VEC3 self
function POINT_VEC3:NewFromVec3( Vec3 )
local self = BASE:Inherit( self, COORDINATE:NewFromVec3( Vec3 ) ) -- Core.Point#POINT_VEC3
self:F2( self )
return self
end
--- Return the x coordinate of the POINT_VEC3.
-- @param #POINT_VEC3 self
-- @return #number The x coordinate.
function POINT_VEC3:GetX()
return self.x
end
--- Return the y coordinate of the POINT_VEC3.
-- @param #POINT_VEC3 self
-- @return #number The y coordinate.
function POINT_VEC3:GetY()
return self.y
end
--- Return the z coordinate of the POINT_VEC3.
-- @param #POINT_VEC3 self
-- @return #number The z coordinate.
function POINT_VEC3:GetZ()
return self.z
end
--- Set the x coordinate of the POINT_VEC3.
-- @param #POINT_VEC3 self
-- @param #number x The x coordinate.
-- @return #POINT_VEC3
function POINT_VEC3:SetX( x )
self.x = x
return self
end
--- Set the y coordinate of the POINT_VEC3.
-- @param #POINT_VEC3 self
-- @param #number y The y coordinate.
-- @return #POINT_VEC3
function POINT_VEC3:SetY( y )
self.y = y
return self
end
--- Set the z coordinate of the POINT_VEC3.
-- @param #POINT_VEC3 self
-- @param #number z The z coordinate.
-- @return #POINT_VEC3
function POINT_VEC3:SetZ( z )
self.z = z
return self
end
--- Add to the x coordinate of the POINT_VEC3.
-- @param #POINT_VEC3 self
-- @param #number x The x coordinate value to add to the current x coordinate.
-- @return #POINT_VEC3
function POINT_VEC3:AddX( x )
self.x = self.x + x
return self
end
--- Add to the y coordinate of the POINT_VEC3.
-- @param #POINT_VEC3 self
-- @param #number y The y coordinate value to add to the current y coordinate.
-- @return #POINT_VEC3
function POINT_VEC3:AddY( y )
self.y = self.y + y
return self
end
--- Add to the z coordinate of the POINT_VEC3.
-- @param #POINT_VEC3 self
-- @param #number z The z coordinate value to add to the current z coordinate.
-- @return #POINT_VEC3
function POINT_VEC3:AddZ( z )
self.z = self.z +z
return self
end
--- Return a random POINT_VEC3 within an Outer Radius and optionally NOT within an Inner Radius of the POINT_VEC3.
-- @param #POINT_VEC3 self
-- @param DCS#Distance OuterRadius
-- @param DCS#Distance InnerRadius
-- @return #POINT_VEC3
function POINT_VEC3:GetRandomPointVec3InRadius( OuterRadius, InnerRadius )
return POINT_VEC3:NewFromVec3( self:GetRandomVec3InRadius( OuterRadius, InnerRadius ) )
end
end
do -- POINT_VEC2
do
-- @type POINT_VEC2
--- @type POINT_VEC2
-- @field DCS#Distance x The x coordinate in meters.
-- @field DCS#Distance y the y coordinate in meters.
-- @extends Core.Point#COORDINATE
--- Defines a 2D point in the simulator. The height coordinate (if needed) will be the land height + an optional added height specified.
--
-- **DEPRECATED - PLEASE USE COORDINATE!**
--
-- ## POINT_VEC2 constructor
--
-- A new POINT_VEC2 instance can be created with:
@@ -3751,166 +3824,4 @@ do -- POINT_VEC2
return self
end
--- Create a new POINT_VEC2 object from Vec2 coordinates.
-- @param #POINT_VEC2 self
-- @param DCS#Vec2 Vec2 The Vec2 point.
-- @return Core.Point#POINT_VEC2 self
function POINT_VEC2:NewFromVec2( Vec2, LandHeightAdd )
local LandHeight = land.getHeight( Vec2 )
LandHeightAdd = LandHeightAdd or 0
LandHeight = LandHeight + LandHeightAdd
local self = BASE:Inherit( self, COORDINATE:NewFromVec2( Vec2, LandHeightAdd ) ) -- #POINT_VEC2
self:F2( self )
return self
end
--- Create a new POINT_VEC2 object from Vec3 coordinates.
-- @param #POINT_VEC2 self
-- @param DCS#Vec3 Vec3 The Vec3 point.
-- @return Core.Point#POINT_VEC2 self
function POINT_VEC2:NewFromVec3( Vec3 )
local self = BASE:Inherit( self, COORDINATE:NewFromVec3( Vec3 ) ) -- #POINT_VEC2
self:F2( self )
return self
end
--- Return the x coordinate of the POINT_VEC2.
-- @param #POINT_VEC2 self
-- @return #number The x coordinate.
function POINT_VEC2:GetX()
return self.x
end
--- Return the y coordinate of the POINT_VEC2.
-- @param #POINT_VEC2 self
-- @return #number The y coordinate.
function POINT_VEC2:GetY()
return self.z
end
--- Set the x coordinate of the POINT_VEC2.
-- @param #POINT_VEC2 self
-- @param #number x The x coordinate.
-- @return #POINT_VEC2
function POINT_VEC2:SetX( x )
self.x = x
return self
end
--- Set the y coordinate of the POINT_VEC2.
-- @param #POINT_VEC2 self
-- @param #number y The y coordinate.
-- @return #POINT_VEC2
function POINT_VEC2:SetY( y )
self.z = y
return self
end
--- Return Return the Lat(itude) coordinate of the POINT_VEC2 (ie: (parent)POINT_VEC3.x).
-- @param #POINT_VEC2 self
-- @return #number The x coordinate.
function POINT_VEC2:GetLat()
return self.x
end
--- Set the Lat(itude) coordinate of the POINT_VEC2 (ie: POINT_VEC3.x).
-- @param #POINT_VEC2 self
-- @param #number x The x coordinate.
-- @return #POINT_VEC2
function POINT_VEC2:SetLat( x )
self.x = x
return self
end
--- Return the Lon(gitude) coordinate of the POINT_VEC2 (ie: (parent)POINT_VEC3.z).
-- @param #POINT_VEC2 self
-- @return #number The y coordinate.
function POINT_VEC2:GetLon()
return self.z
end
--- Set the Lon(gitude) coordinate of the POINT_VEC2 (ie: POINT_VEC3.z).
-- @param #POINT_VEC2 self
-- @param #number y The y coordinate.
-- @return #POINT_VEC2
function POINT_VEC2:SetLon( z )
self.z = z
return self
end
--- Return the altitude (height) of the land at the POINT_VEC2.
-- @param #POINT_VEC2 self
-- @return #number The land altitude.
function POINT_VEC2:GetAlt()
return self.y ~= 0 or land.getHeight( { x = self.x, y = self.z } )
end
--- Set the altitude of the POINT_VEC2.
-- @param #POINT_VEC2 self
-- @param #number Altitude The land altitude. If nothing (nil) is given, then the current land altitude is set.
-- @return #POINT_VEC2
function POINT_VEC2:SetAlt( Altitude )
self.y = Altitude or land.getHeight( { x = self.x, y = self.z } )
return self
end
--- Add to the x coordinate of the POINT_VEC2.
-- @param #POINT_VEC2 self
-- @param #number x The x coordinate.
-- @return #POINT_VEC2
function POINT_VEC2:AddX( x )
self.x = self.x + x
return self
end
--- Add to the y coordinate of the POINT_VEC2.
-- @param #POINT_VEC2 self
-- @param #number y The y coordinate.
-- @return #POINT_VEC2
function POINT_VEC2:AddY( y )
self.z = self.z + y
return self
end
--- Add to the current land height an altitude.
-- @param #POINT_VEC2 self
-- @param #number Altitude The Altitude to add. If nothing (nil) is given, then the current land altitude is set.
-- @return #POINT_VEC2
function POINT_VEC2:AddAlt( Altitude )
self.y = land.getHeight( { x = self.x, y = self.z } ) + Altitude or 0
return self
end
--- Return a random POINT_VEC2 within an Outer Radius and optionally NOT within an Inner Radius of the POINT_VEC2.
-- @param #POINT_VEC2 self
-- @param DCS#Distance OuterRadius
-- @param DCS#Distance InnerRadius
-- @return #POINT_VEC2
function POINT_VEC2:GetRandomPointVec2InRadius( OuterRadius, InnerRadius )
self:F2( { OuterRadius, InnerRadius } )
return POINT_VEC2:NewFromVec2( self:GetRandomVec2InRadius( OuterRadius, InnerRadius ) )
end
-- TODO: Check this to replace
--- Calculate the distance from a reference @{#POINT_VEC2}.
-- @param #POINT_VEC2 self
-- @param #POINT_VEC2 PointVec2Reference The reference @{#POINT_VEC2}.
-- @return DCS#Distance The distance from the reference @{#POINT_VEC2} in meters.
function POINT_VEC2:DistanceFromPointVec2( PointVec2Reference )
self:F2( PointVec2Reference )
local Distance = ( ( PointVec2Reference.x - self.x ) ^ 2 + ( PointVec2Reference.z - self.z ) ^2 ) ^ 0.5
self:T2( Distance )
return Distance
end
end

View File

@@ -629,14 +629,14 @@ do -- SET_BASE
return self
end
--- Iterate the SET_BASE while identifying the nearest object in the set from a @{Core.Point#POINT_VEC2}.
--- Iterate the SET_BASE while identifying the nearest object in the set from a @{Core.Point#COORDINATE}.
-- @param #SET_BASE self
-- @param Core.Point#POINT_VEC2 PointVec2 A @{Core.Point#COORDINATE} or @{Core.Point#POINT_VEC2} object (but **not** a simple DCS#Vec2!) from where to evaluate the closest object in the set.
-- @param Core.Point#COORDINATE Coordinate A @{Core.Point#COORDINATE} object (but **not** a simple DCS#Vec2!) from where to evaluate the closest object in the set.
-- @return Core.Base#BASE The closest object.
-- @usage
-- myset:FindNearestObjectFromPointVec2( ZONE:New("Test Zone"):GetCoordinate() )
function SET_BASE:FindNearestObjectFromPointVec2( PointVec2 )
--self:F2( PointVec2 )
function SET_BASE:FindNearestObjectFromPointVec2( Coordinate )
--self:F2( Coordinate )
local NearestObject = nil
local ClosestDistance = nil
@@ -644,9 +644,9 @@ do -- SET_BASE
for ObjectID, ObjectData in pairs( self.Set ) do
if NearestObject == nil then
NearestObject = ObjectData
ClosestDistance = PointVec2:DistanceFromPointVec2( ObjectData:GetCoordinate() )
ClosestDistance = Coordinate:DistanceFromPointVec2( ObjectData:GetCoordinate() )
else
local Distance = PointVec2:DistanceFromPointVec2( ObjectData:GetCoordinate() )
local Distance = Coordinate:DistanceFromPointVec2( ObjectData:GetCoordinate() )
if Distance < ClosestDistance then
NearestObject = ObjectData
ClosestDistance = Distance
@@ -1242,12 +1242,12 @@ do
return GroupFound
end
--- Iterate the SET_GROUP while identifying the nearest object from a @{Core.Point#POINT_VEC2}.
--- Iterate the SET_GROUP while identifying the nearest object from a @{Core.Point#COORDINATE}.
-- @param #SET_GROUP self
-- @param Core.Point#POINT_VEC2 PointVec2 A @{Core.Point#POINT_VEC2} object from where to evaluate the closest object in the set.
-- @param Core.Point#COORDINATE Coordinate A @{Core.Point#COORDINATE} object from where to evaluate the closest object in the set.
-- @return Wrapper.Group#GROUP The closest group.
function SET_GROUP:FindNearestGroupFromPointVec2( PointVec2 )
--self:F2( PointVec2 )
function SET_GROUP:FindNearestGroupFromPointVec2( Coordinate )
--self:F2( Coordinate )
local NearestGroup = nil -- Wrapper.Group#GROUP
local ClosestDistance = nil
@@ -1257,9 +1257,9 @@ do
for ObjectID, ObjectData in pairs( Set ) do
if NearestGroup == nil then
NearestGroup = ObjectData
ClosestDistance = PointVec2:DistanceFromPointVec2( ObjectData:GetCoordinate() )
ClosestDistance = Coordinate:DistanceFromPointVec2( ObjectData:GetCoordinate() )
else
local Distance = PointVec2:DistanceFromPointVec2( ObjectData:GetCoordinate() )
local Distance = Coordinate:DistanceFromPointVec2( ObjectData:GetCoordinate() )
if Distance < ClosestDistance then
NearestGroup = ObjectData
ClosestDistance = Distance
@@ -2519,6 +2519,35 @@ do -- SET_UNIT
)
return self
end
--- Builds a set of units which belong to groups with certain **group names**.
-- @param #SET_UNIT self
-- @param #string Prefixes The (partial) group names to look for. Can be a single string or a table of strings.
-- @return #SET_UNIT self
function SET_UNIT:FilterGroupPrefixes(Prefixes)
if type(Prefixes) == "string" then
Prefixes = {Prefixes}
end
self:FilterFunction(
function(unit,prefixes)
local outcome = false
if unit then
local grp = unit:GetGroup()
local gname = grp ~= nil and grp:GetName() or "none"
for _,_fix in pairs(prefixes or {}) do
if string.find(gname,_fix) then
outcome = true
break
end
end
else
return false
end
return outcome
end, Prefixes
)
return self
end
--- Builds a set of units having a radar of give types.
-- All the units having a radar of a given type will be included within the set.
@@ -4434,6 +4463,35 @@ do -- SET_CLIENT
end
return self
end
--- Builds a set of clients which belong to groups with certain **group names**.
-- @param #SET_CLIENT self
-- @param #string Prefixes The (partial) group names to look for. Can be anywhere in the group name. Can be a single string or a table of strings.
-- @return #SET_CLIENT self
function SET_CLIENT:FilterGroupPrefixes(Prefixes)
if type(Prefixes) == "string" then
Prefixes = {Prefixes}
end
self:FilterFunction(
function(unit,prefixes)
local outcome = false
if unit then
local grp = unit:GetGroup()
local gname = grp ~= nil and grp:GetName() or "none"
for _,_fix in pairs(prefixes or {}) do
if string.find(gname,_fix) then
outcome = true
break
end
end
else
return false
end
return outcome
end, Prefixes
)
return self
end
--- Builds a set of clients that are only active.
-- Only the clients that are active will be included within the set.
@@ -5670,14 +5728,14 @@ do -- SET_AIRBASE
return self
end
--- Iterate the SET_AIRBASE while identifying the nearest @{Wrapper.Airbase#AIRBASE} from a @{Core.Point#POINT_VEC2}.
--- Iterate the SET_AIRBASE while identifying the nearest @{Wrapper.Airbase#AIRBASE} from a @{Core.Point#COORDINATE}.
-- @param #SET_AIRBASE self
-- @param Core.Point#POINT_VEC2 PointVec2 A @{Core.Point#POINT_VEC2} object from where to evaluate the closest @{Wrapper.Airbase#AIRBASE}.
-- @param Core.Point#COORDINATE Coordinate A @{Core.Point#COORDINATE} object from where to evaluate the closest @{Wrapper.Airbase#AIRBASE}.
-- @return Wrapper.Airbase#AIRBASE The closest @{Wrapper.Airbase#AIRBASE}.
function SET_AIRBASE:FindNearestAirbaseFromPointVec2( PointVec2 )
--self:F2( PointVec2 )
function SET_AIRBASE:FindNearestAirbaseFromPointVec2( Coordinate )
--self:F2( Coordinate )
local NearestAirbase = self:FindNearestObjectFromPointVec2( PointVec2 )
local NearestAirbase = self:FindNearestObjectFromPointVec2( Coordinate )
return NearestAirbase
end
@@ -6007,17 +6065,19 @@ do -- SET_CARGO
return self
end
--- (R2.1) Iterate the SET_CARGO while identifying the nearest @{Cargo.Cargo#CARGO} from a @{Core.Point#POINT_VEC2}.
--- (R2.1) Iterate the SET_CARGO while identifying the nearest @{Cargo.Cargo#CARGO} from a @{Core.Point#COORDINATE}.
-- @param #SET_CARGO self
-- @param Core.Point#POINT_VEC2 PointVec2 A @{Core.Point#POINT_VEC2} object from where to evaluate the closest @{Cargo.Cargo#CARGO}.
-- @param Core.Point#COORDINATE Coordinate A @{Core.Point#COORDINATE} object from where to evaluate the closest @{Cargo.Cargo#CARGO}.
-- @return Cargo.Cargo#CARGO The closest @{Cargo.Cargo#CARGO}.
function SET_CARGO:FindNearestCargoFromPointVec2( PointVec2 ) -- R2.1
--self:F2( PointVec2 )
function SET_CARGO:FindNearestCargoFromPointVec2( Coordinate ) -- R2.1
--self:F2( Coordinate )
local NearestCargo = self:FindNearestObjectFromPointVec2( PointVec2 )
local NearestCargo = self:FindNearestObjectFromPointVec2( Coordinate )
return NearestCargo
end
---
-- @param #SET_CARGO self
function SET_CARGO:FirstCargoWithState( State )
local FirstCargo = nil
@@ -6032,6 +6092,8 @@ do -- SET_CARGO
return FirstCargo
end
---
-- @param #SET_CARGO self
function SET_CARGO:FirstCargoWithStateAndNotDeployed( State )
local FirstCargo = nil
@@ -8693,7 +8755,6 @@ do -- SET_DYNAMICCARGO
-- @field #SET_DYNAMICCARGO SET_DYNAMICCARGO
SET_DYNAMICCARGO = {
ClassName = "SET_DYNAMICCARGO",
Filter = {},
Set = {},
List = {},
Index = {},

View File

@@ -1631,7 +1631,7 @@ function SPAWN:SpawnWithIndex( SpawnIndex, NoBirth )
if SpawnTemplate then
local PointVec3 = POINT_VEC3:New( SpawnTemplate.route.points[1].x, SpawnTemplate.route.points[1].alt, SpawnTemplate.route.points[1].y )
local PointVec3 = COORDINATE:New( SpawnTemplate.route.points[1].x, SpawnTemplate.route.points[1].alt, SpawnTemplate.route.points[1].y )
--self:T2( { "Current point of ", self.SpawnTemplatePrefix, PointVec3 } )
-- If RandomizePosition, then Randomize the formation in the zone band, keeping the template.
@@ -2830,7 +2830,7 @@ end
function SPAWN:SpawnFromVec3( Vec3, SpawnIndex )
--self:F( { self.SpawnTemplatePrefix, Vec3, SpawnIndex } )
local PointVec3 = POINT_VEC3:NewFromVec3( Vec3 )
local PointVec3 = COORDINATE:NewFromVec3( Vec3 )
--self:T2( PointVec3 )
if SpawnIndex then
@@ -2906,7 +2906,7 @@ end
-- Note that each point in the route assigned to the spawning group is reset to the point of the spawn.
-- You can use the returned group to further define the route to be followed.
-- @param #SPAWN self
-- @param Core.Point#POINT_VEC3 PointVec3 The PointVec3 coordinates where to spawn the group.
-- @param Core.Point#COORDINATE PointVec3 The COORDINATE coordinates where to spawn the group.
-- @param #number SpawnIndex (optional) The index which group to spawn within the given zone.
-- @return Wrapper.Group#GROUP that was spawned or #nil if nothing was spawned.
-- @usage
@@ -2954,12 +2954,12 @@ function SPAWN:SpawnFromVec2( Vec2, MinHeight, MaxHeight, SpawnIndex )
return self:SpawnFromVec3( { x = Vec2.x, y = Height, z = Vec2.y }, SpawnIndex ) -- y can be nil. In this case, spawn on the ground for vehicles, and in the template altitude for air.
end
--- Will spawn a group from a POINT_VEC2 in 3D space.
--- Will spawn a group from a COORDINATE in 3D space.
-- This method is mostly advisable to be used if you want to simulate spawning groups on the ground from air units, like vehicles.
-- Note that each point in the route assigned to the spawning group is reset to the point of the spawn.
-- You can use the returned group to further define the route to be followed.
-- @param #SPAWN self
-- @param Core.Point#POINT_VEC2 PointVec2 The PointVec2 coordinates where to spawn the group.
-- @param Core.Point#COORDINATE PointVec2 The coordinates where to spawn the group.
-- @param #number MinHeight (optional) The minimum height to spawn an airborne group into the zone.
-- @param #number MaxHeight (optional) The maximum height to spawn an airborne group into the zone.
-- @param #number SpawnIndex (optional) The index which group to spawn within the given zone.

View File

@@ -105,7 +105,7 @@
--
-- * @{#SPAWNSTATIC.Spawn}(Heading, NewName) spawns the static with the set parameters. Optionally, heading and name can be given. The name **must be unique**!
-- * @{#SPAWNSTATIC.SpawnFromCoordinate}(Coordinate, Heading, NewName) spawn the static at the given coordinate. Optionally, heading and name can be given. The name **must be unique**!
-- * @{#SPAWNSTATIC.SpawnFromPointVec2}(PointVec2, Heading, NewName) spawns the static at a POINT_VEC2 coordinate. Optionally, heading and name can be given. The name **must be unique**!
-- * @{#SPAWNSTATIC.SpawnFromPointVec2}(PointVec2, Heading, NewName) spawns the static at a COORDINATE coordinate. Optionally, heading and name can be given. The name **must be unique**!
-- * @{#SPAWNSTATIC.SpawnFromZone}(Zone, Heading, NewName) spawns the static at the center of a @{Core.Zone}. Optionally, heading and name can be given. The name **must be unique**!
--
-- @field #SPAWNSTATIC SPAWNSTATIC
@@ -411,9 +411,9 @@ function SPAWNSTATIC:Spawn(Heading, NewName)
end
--- Creates a new @{Wrapper.Static} from a POINT_VEC2.
--- Creates a new @{Wrapper.Static} from a COORDINATE.
-- @param #SPAWNSTATIC self
-- @param Core.Point#POINT_VEC2 PointVec2 The 2D coordinate where to spawn the static.
-- @param Core.Point#COORDINATE 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 NewName (Optional) The name of the new static.
-- @return Wrapper.Static#STATIC The static spawned.

File diff suppressed because it is too large Load Diff

View File

@@ -213,7 +213,7 @@ end
--- Returns if a PointVec3 is within the zone.
-- @param #ZONE_BASE self
-- @param Core.Point#POINT_VEC3 PointVec3 The PointVec3 to test.
-- @param Core.Point#COORDINATE PointVec3 The PointVec3 to test.
-- @return #boolean true if the PointVec3 is within the zone.
function ZONE_BASE:IsPointVec3InZone( PointVec3 )
local InZone = self:IsPointVec2InZone( PointVec3 )
@@ -227,16 +227,16 @@ function ZONE_BASE:GetVec2()
return nil
end
--- Returns a @{Core.Point#POINT_VEC2} of the zone.
--- Returns a @{Core.Point#COORDINATE} of the zone.
-- @param #ZONE_BASE self
-- @param DCS#Distance Height The height to add to the land height where the center of the zone is located.
-- @return Core.Point#POINT_VEC2 The PointVec2 of the zone.
-- @return Core.Point#COORDINATE The COORDINATE of the zone.
function ZONE_BASE:GetPointVec2()
--self:F2( self.ZoneName )
local Vec2 = self:GetVec2()
local PointVec2 = POINT_VEC2:NewFromVec2( Vec2 )
local PointVec2 = COORDINATE:NewFromVec2( Vec2 )
--self:T2( { PointVec2 } )
@@ -261,16 +261,16 @@ function ZONE_BASE:GetVec3( Height )
return Vec3
end
--- Returns a @{Core.Point#POINT_VEC3} of the zone.
--- Returns a @{Core.Point#COORDINATE} of the zone.
-- @param #ZONE_BASE self
-- @param DCS#Distance Height The height to add to the land height where the center of the zone is located.
-- @return Core.Point#POINT_VEC3 The PointVec3 of the zone.
-- @return Core.Point#COORDINATE The PointVec3 of the zone.
function ZONE_BASE:GetPointVec3( Height )
--self:F2( self.ZoneName )
local Vec3 = self:GetVec3( Height )
local PointVec3 = POINT_VEC3:NewFromVec3( Vec3 )
local PointVec3 = COORDINATE:NewFromVec3( Vec3 )
--self:T2( { PointVec3 } )
@@ -305,6 +305,20 @@ function ZONE_BASE:GetCoordinate( Height ) --R2.1
return self.Coordinate
end
--- Returns the @{Core.Vector#VECTOR} of the zone.
-- @param #ZONE_BASE self
-- @param DCS#Distance Height The height in meters to add to the land height where the center of the zone is located.
-- @return Core.Vector#VECTOR The vector of the zone.
function ZONE_BASE:GetVector( Height )
self:F2(self.ZoneName)
local Vec3 = self:GetVec3( Height )
local vector=VECTOR:NewFromVec(Vec3)
return vector
end
--- Get 2D distance to a coordinate.
-- @param #ZONE_BASE self
-- @param Core.Point#COORDINATE Coordinate Reference coordinate. Can also be a DCS#Vec2 or DCS#Vec3 object.
@@ -330,16 +344,16 @@ function ZONE_BASE:GetRandomVec2()
return nil
end
--- Define a random @{Core.Point#POINT_VEC2} within the zone. Note that this is actually a @{Core.Point#COORDINATE} type object, and not a simple Vec2 table.
--- Define a random @{Core.Point#COORDINATE} within the zone. Note that this is actually a @{Core.Point#COORDINATE} type object, and not a simple Vec2 table.
-- @param #ZONE_BASE self
-- @return Core.Point#POINT_VEC2 The PointVec2 coordinates.
-- @return Core.Point#COORDINATE The COORDINATE coordinates.
function ZONE_BASE:GetRandomPointVec2()
return nil
end
--- Define a random @{Core.Point#POINT_VEC3} within the zone. Note that this is actually a @{Core.Point#COORDINATE} type object, and not a simple Vec3 table.
--- Define a random @{Core.Point#COORDINATE} within the zone. Note that this is actually a @{Core.Point#COORDINATE} type object, and not a simple Vec3 table.
-- @param #ZONE_BASE self
-- @return Core.Point#POINT_VEC3 The PointVec3 coordinates.
-- @return Core.Point#COORDINATE The COORDINATE coordinates.
function ZONE_BASE:GetRandomPointVec3()
return nil
end
@@ -814,8 +828,8 @@ end
-- 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 @{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.
-- * @{#ZONE_RADIUS.GetRandomPointVec2}(): Gets a @{Core.Point#COORDINATE} object representing a random 2D point in the zone.
-- * @{#ZONE_RADIUS.GetRandomPointVec3}(): Gets a @{Core.Point#COORDINATE} object representing a random 3D point in the zone. Note that the height of the point is at landheight.
--
-- ## Draw zone
--
@@ -1010,7 +1024,7 @@ function ZONE_RADIUS:SmokeZone( SmokeColor, Points, AddHeight, AngleOffset )
local Radial = ( Angle + AngleOffset ) * RadialBase / 360
Point.x = Vec2.x + math.cos( Radial ) * self:GetRadius()
Point.y = Vec2.y + math.sin( Radial ) * self:GetRadius()
POINT_VEC2:New( Point.x, Point.y, AddHeight ):Smoke( SmokeColor )
COORDINATE:New( Point.x, AddHeight, Point.y ):Smoke( SmokeColor )
end
return self
@@ -1040,7 +1054,7 @@ function ZONE_RADIUS:FlareZone( FlareColor, Points, Azimuth, AddHeight )
local Radial = Angle * RadialBase / 360
Point.x = Vec2.x + math.cos( Radial ) * self:GetRadius()
Point.y = Vec2.y + math.sin( Radial ) * self:GetRadius()
POINT_VEC2:New( Point.x, Point.y, AddHeight ):Flare( FlareColor, Azimuth )
COORDINATE:New( Point.x, AddHeight, Point.y ):Flare( FlareColor, Azimuth )
end
return self
@@ -1561,15 +1575,15 @@ function ZONE_RADIUS:GetRandomVec2(inner, outer, surfacetypes)
return point
end
--- Returns a @{Core.Point#POINT_VEC2} object reflecting a random 2D location within the zone. Note that this is actually a @{Core.Point#COORDINATE} type object, and not a simple Vec2 table.
--- Returns a @{Core.Point#COORDINATE} object reflecting a random 2D location within the zone. Note that this is actually a @{Core.Point#COORDINATE} type object, and not a simple Vec2 table.
-- @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 @{Core.Point#POINT_VEC2} object reflecting the random 3D location within the zone.
-- @return Core.Point#COORDINATE The @{Core.Point#COORDINATE} object reflecting the random 3D location within the zone.
function ZONE_RADIUS:GetRandomPointVec2( inner, outer )
--self:F( self.ZoneName, inner, outer )
local PointVec2 = POINT_VEC2:NewFromVec2( self:GetRandomVec2( inner, outer ) )
local PointVec2 = COORDINATE:NewFromVec2( self:GetRandomVec2( inner, outer ) )
--self:T3( { PointVec2 } )
@@ -1592,15 +1606,15 @@ function ZONE_RADIUS:GetRandomVec3( inner, outer )
end
--- Returns a @{Core.Point#POINT_VEC3} object reflecting a random 3D location within the zone. Note that this is actually a @{Core.Point#COORDINATE} type object, and not a simple Vec3 table.
--- Returns a @{Core.Point#COORDINATE} object reflecting a random 3D location within the zone. Note that this is actually a @{Core.Point#COORDINATE} type object, and not a simple Vec3 table.
-- @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 @{Core.Point#POINT_VEC3} object reflecting the random 3D location within the zone.
-- @return Core.Point#COORDINATE The @{Core.Point#COORDINATE} object reflecting the random 3D location within the zone.
function ZONE_RADIUS:GetRandomPointVec3( inner, outer )
--self:F( self.ZoneName, inner, outer )
local PointVec3 = POINT_VEC3:NewFromVec2( self:GetRandomVec2( inner, outer ) )
local PointVec3 = COORDINATE:NewFromVec2( self:GetRandomVec2( inner, outer ) )
--self:T3( { PointVec3 } )
@@ -2036,15 +2050,15 @@ function ZONE_GROUP:GetRandomVec2()
return Point
end
--- Returns a @{Core.Point#POINT_VEC2} object reflecting a random 2D location within the zone. Note that this is actually a @{Core.Point#COORDINATE} type object, and not a simple Vec2 table.
--- Returns a @{Core.Point#COORDINATE} object reflecting a random 2D location within the zone. Note that this is actually a @{Core.Point#COORDINATE} type object, and not a simple Vec2 table.
-- @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 @{Core.Point#POINT_VEC2} object reflecting the random 3D location within the zone.
-- @return Core.Point#COORDINATE The @{Core.Point#COORDINATE} object reflecting the random 3D location within the zone.
function ZONE_GROUP:GetRandomPointVec2( inner, outer )
--self:F( self.ZoneName, inner, outer )
local PointVec2 = POINT_VEC2:NewFromVec2( self:GetRandomVec2() )
local PointVec2 = COORDINATE:NewFromVec2( self:GetRandomVec2() )
--self:T3( { PointVec2 } )
@@ -2192,8 +2206,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 @{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.
-- * @{#ZONE_POLYGON_BASE.GetRandomPointVec2}(): Return a @{Core.Point#COORDINATE} object representing a random 2D point within the zone.
-- * @{#ZONE_POLYGON_BASE.GetRandomPointVec3}(): Return a @{Core.Point#COORDINATE} object representing a random 3D point at landheight within the zone.
--
-- ## Draw zone
--
@@ -2769,7 +2783,7 @@ function ZONE_POLYGON_BASE:SmokeZone( SmokeColor, Segments )
for Segment = 0, Segments do -- We divide each line in 5 segments and smoke a point on the line.
local PointX = self._.Polygon[i].x + ( Segment * DeltaX / Segments )
local PointY = self._.Polygon[i].y + ( Segment * DeltaY / Segments )
POINT_VEC2:New( PointX, PointY ):Smoke( SmokeColor )
COORDINATE:New( PointX, 0, PointY ):Smoke( SmokeColor )
end
j = i
i = i + 1
@@ -2804,7 +2818,7 @@ function ZONE_POLYGON_BASE:FlareZone( FlareColor, Segments, Azimuth, AddHeight )
for Segment = 0, Segments do -- We divide each line in 5 segments and smoke a point on the line.
local PointX = self._.Polygon[i].x + ( Segment * DeltaX / Segments )
local PointY = self._.Polygon[i].y + ( Segment * DeltaY / Segments )
POINT_VEC2:New( PointX, PointY, AddHeight ):Flare(FlareColor, Azimuth)
COORDINATE:New( PointX, AddHeight, PointY ):Flare(FlareColor, Azimuth)
end
j = i
i = i + 1
@@ -2880,26 +2894,26 @@ function ZONE_POLYGON_BASE:GetRandomVec2()
end
end
--- Return a @{Core.Point#POINT_VEC2} object representing a random 2D point at landheight within the zone. Note that this is actually a @{Core.Point#COORDINATE} type object, and not a simple Vec2 table.
--- Return a @{Core.Point#COORDINATE} object representing a random 2D point at landheight within the zone. Note that this is actually a @{Core.Point#COORDINATE} type object, and not a simple Vec2 table.
-- @param #ZONE_POLYGON_BASE self
-- @return @{Core.Point#POINT_VEC2}
-- @return @{Core.Point#COORDINATE}
function ZONE_POLYGON_BASE:GetRandomPointVec2()
--self:F2()
local PointVec2 = POINT_VEC2:NewFromVec2( self:GetRandomVec2() )
local PointVec2 = COORDINATE:NewFromVec2( self:GetRandomVec2() )
--self:T2( PointVec2 )
return PointVec2
end
--- Return a @{Core.Point#POINT_VEC3} object representing a random 3D point at landheight within the zone. Note that this is actually a @{Core.Point#COORDINATE} type object, and not a simple Vec3 table.
--- Return a @{Core.Point#COORDINATE} object representing a random 3D point at landheight within the zone. Note that this is actually a @{Core.Point#COORDINATE} type object, and not a simple Vec3 table.
-- @param #ZONE_POLYGON_BASE self
-- @return @{Core.Point#POINT_VEC3}
-- @return @{Core.Point#COORDINATE}
function ZONE_POLYGON_BASE:GetRandomPointVec3()
--self:F2()
local PointVec3 = POINT_VEC3:NewFromVec2( self:GetRandomVec2() )
local PointVec3 = COORDINATE:NewFromVec2( self:GetRandomVec2() )
--self:T2( PointVec3 )
@@ -3931,18 +3945,18 @@ function ZONE_OVAL:GetRandomVec2()
return {x=rx, y=ry}
end
--- Define a random @{Core.Point#POINT_VEC2} within the zone. Note that this is actually a @{Core.Point#COORDINATE} type object, and not a simple Vec2 table.
--- Define a random @{Core.Point#COORDINATE} within the zone. Note that this is actually a @{Core.Point#COORDINATE} type object, and not a simple Vec2 table.
-- @param #ZONE_OVAL self
-- @return Core.Point#POINT_VEC2 The PointVec2 coordinates.
-- @return Core.Point#COORDINATE The COORDINATE coordinates.
function ZONE_OVAL:GetRandomPointVec2()
return POINT_VEC2:NewFromVec2(self:GetRandomVec2())
return COORDINATE:NewFromVec2(self:GetRandomVec2())
end
--- Define a random @{Core.Point#POINT_VEC2} within the zone. Note that this is actually a @{Core.Point#COORDINATE} type object, and not a simple Vec3 table.
--- Define a random @{Core.Point#COORDINATE} within the zone. Note that this is actually a @{Core.Point#COORDINATE} type object, and not a simple Vec3 table.
-- @param #ZONE_OVAL self
-- @return Core.Point#POINT_VEC2 The PointVec2 coordinates.
-- @return Core.Point#COORDINATE The COORDINATE coordinates.
function ZONE_OVAL:GetRandomPointVec3()
return POINT_VEC3:NewFromVec3(self:GetRandomVec2())
return COORDINATE:NewFromVec3(self:GetRandomVec2())
end
--- Draw the zone on the F10 map.
@@ -4082,15 +4096,15 @@ do -- ZONE_AIRBASE
return ZoneVec2
end
--- Returns a @{Core.Point#POINT_VEC2} object reflecting a random 2D location within the zone. Note that this is actually a @{Core.Point#COORDINATE} type object, and not a simple Vec2 table.
--- Returns a @{Core.Point#COORDINATE} object reflecting a random 2D location within the zone. Note that this is actually a @{Core.Point#COORDINATE} type object, and not a simple Vec2 table.
-- @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.
-- @return Core.Point#COORDINATE The @{Core.Point#COORDINATE} 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() )
local PointVec2 = COORDINATE:NewFromVec2( self:GetRandomVec2() )
--self:T3( { PointVec2 } )

View File

@@ -107,7 +107,7 @@ function ZONE_DETECTION:SmokeZone( SmokeColor, Points, AddHeight, AngleOffset )
local Radial = ( Angle + AngleOffset ) * RadialBase / 360
Point.x = Vec2.x + math.cos( Radial ) * self:GetRadius()
Point.y = Vec2.y + math.sin( Radial ) * self:GetRadius()
POINT_VEC2:New( Point.x, Point.y, AddHeight ):Smoke( SmokeColor )
COORDINATE:New( Point.x, AddHeight, Point.y):Smoke( SmokeColor )
end
return self
@@ -138,7 +138,7 @@ function ZONE_DETECTION:FlareZone( FlareColor, Points, Azimuth, AddHeight )
local Radial = Angle * RadialBase / 360
Point.x = Vec2.x + math.cos( Radial ) * self:GetRadius()
Point.y = Vec2.y + math.sin( Radial ) * self:GetRadius()
POINT_VEC2:New( Point.x, Point.y, AddHeight ):Flare( FlareColor, Azimuth )
COORDINATE:New( Point.x, AddHeight, Point.y ):Flare( FlareColor, Azimuth )
end
return self
@@ -202,4 +202,3 @@ function ZONE_DETECTION:IsVec3InZone( Vec3 )
return InZone
end

View File

@@ -437,16 +437,16 @@ MANTIS.SamDataSMA = {
-- units from SMA Mod (Sweedish Military Assets)
-- https://forum.dcs.world/topic/295202-swedish-military-assets-for-dcs-by-currenthill/
-- group name MUST contain SMA to ID launcher type correctly!
["RBS98M SMA"] = { Range=20, Blindspot=0, Height=8, Type="Short", Radar="RBS-98" },
["RBS70 SMA"] = { Range=8, Blindspot=0, Height=5.5, Type="Short", Radar="RBS-70" },
["RBS70M SMA"] = { Range=8, Blindspot=0, Height=5.5, Type="Short", Radar="BV410_RBS70" },
["RBS90 SMA"] = { Range=8, Blindspot=0, Height=5.5, Type="Short", Radar="RBS-90" },
["RBS90M SMA"] = { Range=8, Blindspot=0, Height=5.5, Type="Short", Radar="BV410_RBS90" },
["RBS103A SMA"] = { Range=150, Blindspot=3, Height=24.5, Type="Long", Radar="LvS-103_Lavett103_Rb103A" },
["RBS103B SMA"] = { Range=35, Blindspot=0, Height=36, Type="Medium", Radar="LvS-103_Lavett103_Rb103B" },
["RBS103AM SMA"] = { Range=150, Blindspot=3, Height=24.5, Type="Long", Radar="LvS-103_Lavett103_HX_Rb103A" },
["RBS103BM SMA"] = { Range=35, Blindspot=0, Height=36, Type="Medium", Radar="LvS-103_Lavett103_HX_Rb103B" },
["Lvkv9040M SMA"] = { Range=4, Blindspot=0, Height=2.5, Type="Point", Radar="LvKv9040",Point="true" },
["RBS98M SMA"] = { Range=20, Blindspot=0.2, Height=8, Type="Short", Radar="RBS-98" },
["RBS70 SMA"] = { Range=8, Blindspot=0.25, Height=6, Type="Short", Radar="RBS-70" },
["RBS70M SMA"] = { Range=8, Blindspot=0.25, Height=6, Type="Short", Radar="BV410_RBS70" },
["RBS90 SMA"] = { Range=8, Blindspot=0.25, Height=6, Type="Short", Radar="RBS-90" },
["RBS90M SMA"] = { Range=8, Blindspot=0.25, Height=6, Type="Short", Radar="BV410_RBS90" },
["RBS103A SMA"] = { Range=160, Blindspot=1, Height=36, Type="Long", Radar="LvS-103_Lavett103_Rb103A" },
["RBS103B SMA"] = { Range=120, Blindspot=3, Height=24.5, Type="Long", Radar="LvS-103_Lavett103_Rb103B" },
["RBS103AM SMA"] = { Range=160, Blindspot=1, Height=36, Type="Long", Radar="LvS-103_Lavett103_HX_Rb103A" },
["RBS103BM SMA"] = { Range=120, Blindspot=3, Height=24.5, Type="Long", Radar="LvS-103_Lavett103_HX_Rb103B" },
["Lvkv9040M SMA"] = { Range=2, Blindspot=0.1, Height=1.2, Type="Point", Radar="LvKv9040",Point="true" },
}
--- SAM data CH
@@ -461,47 +461,49 @@ MANTIS.SamDataCH = {
-- units from CH (Military Assets by Currenthill)
-- https://www.currenthill.com/
-- group name MUST contain CHM to ID launcher type correctly!
["2S38 CHM"] = { Range=8, Blindspot=0.5, Height=6, Type="Short", Radar="2S38" },
["2S38 CHM"] = { Range=6, Blindspot=0.1, Height=4.5, Type="Short", Radar="2S38" },
["PantsirS1 CHM"] = { Range=20, Blindspot=1.2, Height=15, Type="Short", Radar="PantsirS1" },
["PantsirS2 CHM"] = { Range=30, Blindspot=1.2, Height=18, Type="Medium", Radar="PantsirS2" },
["PGL-625 CHM"] = { Range=10, Blindspot=0.5, Height=5, Type="Short", Radar="PGL_625" },
["HQ-17A CHM"] = { Range=20, Blindspot=1.5, Height=10, Type="Short", Radar="HQ17A" },
["M903PAC2 CHM"] = { Range=160, Blindspot=3, Height=24.5, Type="Long", Radar="MIM104_M903_PAC2" },
["M903PAC3 CHM"] = { Range=120, Blindspot=1, Height=40, Type="Long", Radar="MIM104_M903_PAC3" },
["PGL-625 CHM"] = { Range=10, Blindspot=1, Height=5, Type="Short", Radar="PGL_625" },
["HQ-17A CHM"] = { Range=15, Blindspot=1.5, Height=10, Type="Short", Radar="HQ17A" },
["M903PAC2 CHM"] = { Range=120, Blindspot=3, Height=24.5, Type="Long", Radar="MIM104_M903_PAC2" },
["M903PAC3 CHM"] = { Range=160, Blindspot=1, Height=40, Type="Long", Radar="MIM104_M903_PAC3" },
["TorM2 CHM"] = { Range=12, Blindspot=1, Height=10, Type="Short", Radar="TorM2" },
["TorM2K CHM"] = { Range=12, Blindspot=1, Height=10, Type="Short", Radar="TorM2K" },
["TorM2M CHM"] = { Range=16, Blindspot=1, Height=10, Type="Short", Radar="TorM2M" },
["NASAMS3-AMRAAMER CHM"] = { Range=50, Blindspot=2, Height=35.7, Type="Medium", Radar="CH_NASAMS3_LN_AMRAAM_ER" },
["NASAMS3-AIM9X2 CHM"] = { Range=20, Blindspot=0.2, Height=18, Type="Short", Radar="CH_NASAMS3_LN_AIM9X2" },
["C-RAM CHM"] = { Range=2, Blindspot=0, Height=2, Type="Point", Radar="CH_Centurion_C_RAM", Point="true" },
["PGZ-09 CHM"] = { Range=4, Blindspot=0, Height=3, Type="Point", Radar="CH_PGZ09", Point="true" },
["S350-9M100 CHM"] = { Range=15, Blindspot=1.5, Height=8, Type="Short", Radar="CH_S350_50P6_9M100" },
["PGZ-09 CHM"] = { Range=4, Blindspot=0.5, Height=3, Type="Point", Radar="CH_PGZ09", Point="true" },
["S350-9M100 CHM"] = { Range=15, Blindspot=1, Height=8, Type="Short", Radar="CH_S350_50P6_9M100" },
["S350-9M96D CHM"] = { Range=150, Blindspot=2.5, Height=30, Type="Long", Radar="CH_S350_50P6_9M96D" },
["LAV-AD CHM"] = { Range=8, Blindspot=0.2, Height=4.8, Type="Short", Radar="CH_LAVAD" },
["LAV-AD CHM"] = { Range=8, Blindspot=0.16, Height=4.8, Type="Short", Radar="CH_LAVAD" },
["HQ-22 CHM"] = { Range=170, Blindspot=5, Height=27, Type="Long", Radar="CH_HQ22_LN" },
["PGZ-95 CHM"] = { Range=2, Blindspot=0, Height=2, Type="Point", Radar="CH_PGZ95",Point="true" },
["LD-3000 CHM"] = { Range=3, Blindspot=0, Height=3, Type="Point", Radar="CH_LD3000_stationary", Point="true" },
["LD-3000M CHM"] = { Range=3, Blindspot=0, Height=3, Type="Point", Radar="CH_LD3000", Point="true" },
["FlaRakRad CHM"] = { Range=8, Blindspot=1.5, Height=6, Type="Short", Radar="HQ17A" },
["PGZ-95 CHM"] = { Range=2.5, Blindspot=0.5, Height=2, Type="Point", Radar="CH_PGZ95",Point="true" },
["LD-3000 CHM"] = { Range=2.5, Blindspot=0.1, Height=3, Type="Point", Radar="CH_LD3000_stationary", Point="true" },
["LD-3000M CHM"] = { Range=2.5, Blindspot=0.1, Height=3, Type="Point", Radar="CH_LD3000", Point="true" },
["FlaRakRad CHM"] = { Range=8, Blindspot=1.5, Height=6, Type="Short", Radar="CH_FlaRakRad" },
["IRIS-T SLM CHM"] = { Range=40, Blindspot=0.5, Height=20, Type="Medium", Radar="CH_IRIST_SLM" },
["M903PAC2KAT1 CHM"] = { Range=160, Blindspot=3, Height=24.5, Type="Long", Radar="CH_MIM104_M903_PAC2_KAT1" },
["Skynex CHM"] = { Range=3.5, Blindspot=0, Height=3.5, Type="Point", Radar="CH_SkynexHX", Point="true" },
["Skyshield CHM"] = { Range=3.5, Blindspot=0, Height=3.5, Type="Point", Radar="CH_Skyshield_Gun", Point="true" },
["WieselOzelot CHM"] = { Range=8, Blindspot=0.2, Height=4.8, Type="Short", Radar="CH_Wiesel2Ozelot" },
["M903PAC2KAT1 CHM"] = { Range=120, Blindspot=3, Height=24.5, Type="Long", Radar="CH_MIM104_M903_PAC2_KAT1" },
["Skynex CHM"] = { Range=3.5, Blindspot=0.1, Height=3.5, Type="Point", Radar="CH_SkynexHX", Point="true" },
["Skyshield CHM"] = { Range=3.5, Blindspot=0.1, Height=3.5, Type="Point", Radar="CH_Skyshield_Gun", Point="true" },
["WieselOzelot CHM"] = { Range=8, Blindspot=0.16, Height=4.8, Type="Short", Radar="CH_Wiesel2Ozelot" },
["BukM3-9M317M CHM"] = { Range=70, Blindspot=0.25, Height=35, Type="Medium", Radar="CH_BukM3_9A317M" },
["BukM3-9M317MA CHM"] = { Range=70, Blindspot=0.25, Height=35, Type="Medium", Radar="CH_BukM3_9A317MA" },
["SkySabre CHM"] = { Range=30, Blindspot=0.5, Height=10, Type="Medium", Radar="CH_SkySabreLN" },
["Stormer CHM"] = { Range=7.5, Blindspot=0.3, Height=7, Type="Short", Radar="CH_StormerHVM" },
["THAAD CHM"] = { Range=200, Blindspot=40, Height=150, Type="Long", Radar="CH_THAAD_M1120" },
["USInfantryFIM92K CHM"] = { Range=8, Blindspot=0.2, Height=4.8, Type="Short", Radar="CH_USInfantry_FIM92" },
["RBS98M CHM"] = { Range=20, Blindspot=0, Height=8, Type="Short", Radar="RBS-98" },
["RBS70 CHM"] = { Range=8, Blindspot=0, Height=5.5, Type="Short", Radar="RBS-70" },
["RBS90 CHM"] = { Range=8, Blindspot=0, Height=5.5, Type="Short", Radar="RBS-90" },
["RBS103A CHM"] = { Range=150, Blindspot=3, Height=24.5, Type="Long", Radar="LvS-103_Lavett103_Rb103A" },
["RBS103B CHM"] = { Range=35, Blindspot=0, Height=36, Type="Medium", Radar="LvS-103_Lavett103_Rb103B" },
["RBS103AM CHM"] = { Range=150, Blindspot=3, Height=24.5, Type="Long", Radar="LvS-103_Lavett103_HX_Rb103A" },
["RBS103BM CHM"] = { Range=35, Blindspot=0, Height=36, Type="Medium", Radar="LvS-103_Lavett103_HX_Rb103B" },
["Lvkv9040M CHM"] = { Range=4, Blindspot=0, Height=2.5, Type="Point", Radar="LvKv9040", Point="true" },
["USInfantryFIM92K CHM"] = { Range=8, Blindspot=0.16, Height=4.8, Type="Short", Radar="CH_USInfantry_FIM92" },
["RBS98M CHM"] = { Range=20, Blindspot=0.2, Height=8, Type="Short", Radar="RBS-98" },
["RBS70 CHM"] = { Range=8, Blindspot=0.25, Height=6, Type="Short", Radar="RBS-70" },
["RBS70M CHM"] = { Range=8, Blindspot=0.25, Height=6, Type="Short", Radar="BV410_RBS70" },
["RBS90 CHM"] = { Range=8, Blindspot=0.25, Height=6, Type="Short", Radar="RBS-90" },
["RBS90M CHM"] = { Range=8, Blindspot=0.25, Height=6, Type="Short", Radar="BV410_RBS90" },
["RBS103A CHM"] = { Range=160, Blindspot=1, Height=36, Type="Long", Radar="LvS-103_Lavett103_Rb103A" },
["RBS103B CHM"] = { Range=120, Blindspot=3, Height=24.5, Type="Long", Radar="LvS-103_Lavett103_Rb103B" },
["RBS103AM CHM"] = { Range=160, Blindspot=1, Height=36, Type="Long", Radar="LvS-103_Lavett103_HX_Rb103A" },
["RBS103BM CHM"] = { Range=120, Blindspot=3, Height=24.5, Type="Long", Radar="LvS-103_Lavett103_HX_Rb103B" },
["Lvkv9040M CHM"] = { Range=2, Blindspot=0.1, Height=1.2, Type="Point", Radar="LvKv9040",Point="true" },
}
-----------------------------------------------------------------------

View File

@@ -32,6 +32,7 @@ __Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Core/MarkerOps_Base.lua' )
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Core/TextAndSound.lua' )
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Core/Pathline.lua' )
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Core/ClientMenu.lua')
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Core/Vector.lua')
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Wrapper/Object.lua' )
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Wrapper/Identifiable.lua' )
@@ -186,4 +187,9 @@ __Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Tasking/Task_Cargo_Dispatcher
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Tasking/Task_Capture_Zone.lua' )
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Tasking/Task_Capture_Dispatcher.lua' )
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Navigation/Beacons.lua' )
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Navigation/Point.lua' )
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Navigation/Procedure.lua' )
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Navigation/FlightPlan.lua' )
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Globals.lua' )

View File

@@ -32,6 +32,7 @@ __Moose.Include( 'Core\\MarkerOps_Base.lua' )
__Moose.Include( 'Core\\TextAndSound.lua' )
__Moose.Include( 'Core\\Condition.lua' )
__Moose.Include( 'Core\\ClientMenu.lua' )
__Moose.Include( 'Core\\Vector.lua' )
__Moose.Include( 'Wrapper\\Object.lua' )
__Moose.Include( 'Wrapper\\Identifiable.lua' )
@@ -178,4 +179,7 @@ __Moose.Include( 'Tasking\\Task_Cargo_Dispatcher.lua' )
__Moose.Include( 'Tasking\\Task_Capture_Zone.lua' )
__Moose.Include( 'Tasking\\Task_Capture_Dispatcher.lua' )
__Moose.Include( 'Navigation\\Point.lua' )
__Moose.Include( 'Navigation\\Beacons.lua' )
__Moose.Include( 'Globals.lua' )

View File

@@ -0,0 +1,139 @@
--- **NAVIGATION** - Beacons of the map/theatre.
--
-- **Main Features:**
--
-- * Beacons of the map
--
-- ===
--
-- ## Example Missions:
--
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/Navigation%20-%20Beacons).
--
-- ===
--
-- ### Author: **funkyfranky**
--
-- ===
-- @module Navigation.Beacons
-- @image NAVIGATION_Beacons.png
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- BEACONS class.
-- @type BEACONS
--
-- @field #string ClassName Name of the class.
-- @field #number verbose Verbosity of output.
-- @field #table beacons Beacons.
--
-- @extends Core.Base#BASE
--- *A fleet of British ships at war are the best negotiators.* -- Horatio Nelson
--
-- ===
--
-- # The BEACONS Concept
--
-- The NAVFIX class has a great concept!
--
-- Bla, bla...
--
-- # Basic Setup
--
-- A new `BEACONS` object can be created with the @{#BEACONS.New}() function.
--
-- local beacons=BEACONS:New("G:\Games\DCS World Testing\Mods\terrains\GermanyColdWar\beacons.lua")
--
-- This is how it works.
--
-- @field #BEACONS
BEACONS = {
ClassName = "BEACONS",
verbose = 0,
beacons = {},
}
--- BEACONS class version.
-- @field #string version
BEACONS.version="0.0.0"
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- ToDo list
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO: A lot...
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Constructor(s)
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Create a new BECAONS class instance from a given file.
-- @param #BEACONS self
-- @param #string FileName Full path to the file containing the map beacons.
-- @return #BEACONS self
function BEACONS:NewFromFile(FileName)
-- Inherit everything from BASE class.
self=BASE:Inherit(self, BASE:New()) -- #BEACONS
return self
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- User Functions
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Add marker all beacons on the F10 map.
-- @param #BEACONS self
-- @return #BEACONS self
function BEACONS:MarkerShow()
return self
end
--- Remove markers of all beacons from the F10 map.
-- @param #BEACONS self
-- @return #BEACONS self
function BEACONS:MarkerRemove()
return self
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Private Functions
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Get text displayed in the F10 marker.
-- @param #BEACONS self
-- @return #string Marker text.
function BEACONS:_GetMarkerText(beacon)
local altmin=self.altMin and tostring(self.altMin) or ""
local altmax=self.altMax and tostring(self.altMax) or ""
local speedmin=self.speedMin and tostring(self.speedMin) or ""
local speedmax=self.speedMax and tostring(self.speedMax) or ""
local text=string.format("NAVFIX %s", self.name)
if self.isIAF then
text=text..string.format(" (IAF)")
end
if self.isIF then
text=text..string.format(" (IF)")
end
text=text..string.format("\nAltitude [ft]: %s - %s", altmin, altmax)
text=text..string.format("\nSpeed [knots]: %s - %s", speedmin, speedmax)
text=text..string.format("\nCompulsory: %s", tostring(self.isCompulsory))
text=text..string.format("\nFly Over: %s", tostring(self.isFlyover))
return text
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

View File

@@ -0,0 +1,481 @@
--- **NAVIGATION** - Flight Plan.
--
-- **Main Features:**
--
-- * Manage navigation aids
-- * VOR, NDB
--
-- ===
--
-- ## Example Missions:
--
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/Ops%20-%20FlightPlan).
--
-- ===
--
-- ### Author: **funkyfranky**
--
-- ===
-- @module Navigation.FlightPlan
-- @image NAVIGATION_FlightPlan.png
--- FLIGHTPLAN class.
-- @type FLIGHTPLAN
-- @field #string ClassName Name of the class.
-- @field #number verbose Verbosity of output.
-- @field #table fixes Navigation fixes.
-- @field Core.Pathline#PATHLINE pathline Pathline of the plan.
-- @field Wrapper.Airbase#AIRBASE departureAirbase Departure airbase.
-- @field Wrapper.Airbase#AIRBASE destinationAirbase Destination airbase.
-- @field #number altitudeCruiseMin Minimum cruise altitude in feet MSL.
-- @field #number altitudeCruiseMax Maximum cruise altitude in feet MSL.
-- @extends Core.Pathline#PATHLINE
--- *Life is what happens to us while we are making other plans.* -- Allen Saunders
--
-- ===
--
-- # The FLIGHTPLAN Concept
--
-- This class has a great concept!
--
-- # Basic Setup
--
-- A new `FLIGHTPLAN` object can be created with the @{#FLIGHTPLAN.New}() function.
--
-- myFlightplan=FLIGHTPLAN:New("Plan A")
-- myFleet:SetPortZone(ZonePort1stFleet)
-- myFleet:Start()
--
-- A fleet needs a *port zone*, which is set via the @{#FLIGHTPLAN.SetPortZone}(`PortZone`) function. This is the zone where the naval assets are spawned and return to.
--
-- Finally, the fleet needs to be started using the @{#FLIGHTPLAN.Start}() function. If the fleet is not started, it will not process any requests.
--
-- @field #FLIGHTPLAN
FLIGHTPLAN = {
ClassName = "FLIGHTPLAN",
verbose = 0,
fixes = {}
}
--- Type of flightplan.
-- @type FLIGHTPLAN.Type
-- @field #string IFRH Instrument Flying Rules High Altitude.
-- @field #string IFRL Instrument Flying Rules Low Altitude.
-- @field #string VFR Visual Flight Rules.
FLIGHTPLAN.Type={
IFRH = "IFR High",
IFRL = "IFR Low",
VFR = "VFR",
}
--- FLIGHTPLAN class version.
-- @field #string version
FLIGHTPLAN.version="0.0.1"
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- ToDo list
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO: How to connect SID, STAR, ENROUTE, TRANSITION, APPROACH. Typical flightplan SID --> ENROUTE --> STAR --> APPROACH
-- TODO: Add approach.
-- DONE: How to handle the FLIGHTGROUP:_LandAtAirBase
-- TODO: Do we always need a holding pattern? https://www.faa.gov/air_traffic/publications/atpubs/aip_html/part2_enr_section_1.5.html#:~:text=If%20no%20holding%20pattern%20is,than%20that%20desired%20by%20ATC.
-- DOEN: Read from MSFS file.
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Constructor
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Create a new FLIGHTPLAN instance.
-- @param #FLIGHTPLAN self
-- @param #string Name Name of this flight plan.
-- @return #FLIGHTPLAN self
function FLIGHTPLAN:New(Name)
-- Inherit everything from BASE class.
self=BASE:Inherit(self, PATHLINE:New(Name)) -- #FLIGHTPLAN
-- Set alias.
self.alias=tostring(Name)
-- Set some string id for output to DCS.log file.
self.lid=string.format("FLIGHTPLAN %s | ", self.alias)
--self.pathline=PATHLINE:New(Name)
-- Debug info.
self:I(self.lid..string.format("Created FLIGHTPLAN!"))
return self
end
--- Create a new FLIGHTPLAN instance from another FLIGHTPLAN acting as blue print.
-- The newly created flight plan is deep copied from the given one.
-- @param #FLIGHTPLAN self
-- @param #FLIGHTPLAN FlightPlan Blue print of the flight plan to copy.
-- @return #FLIGHTPLAN self
function FLIGHTPLAN:NewFromFlightPlan(FlightPlan)
self=UTILS.DeepCopy(FlightPlan)
return self
end
--- Create a new FLIGHTPLAN instance from a given file.
-- Currently, the file has to be an MSFS 2020 .pln file as, *e.g.*, exported from [Navigraph](https://navigraph.com/).
--
-- **Note** that the flight plan does only cover the departure, enroute and arrival portions but **not the approach** part!
-- @param #FLIGHTPLAN self
-- @param #string FileName Full path to file.
-- @return #FLIGHTPLAN self
function FLIGHTPLAN:NewFromFile(FileName)
if UTILS.FileExists(FileName) then
self=FLIGHTPLAN._ReadFileMSFS(FileName)
else
error(string.format("ERROR: File not found! File name=%s", tostring(FileName)))
end
return self
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- User Functions
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Add navigation fix to the flight plan.
-- @param #FLIGHTPLAN self
-- @param Navigation.Point#NAVPOINT NavFix The nav fix.
-- @return #FLIGHTPLAN self
function FLIGHTPLAN:AddNavFix(NavFix)
table.insert(self.fixes, NavFix)
local point=self:AddPointFromVec3(NavFix.vector:GetVec3(true))
point.navpoint=NavFix
return self
end
--- Set departure airbase.
-- @param #FLIGHTPLAN self
-- @param #string AirbaseName Name of the airbase or AIRBASE object.
-- @return #FLIGHTPLAN self
function FLIGHTPLAN:SetDepartureAirbase(AirbaseName)
self.departureAirbase=AIRBASE:FindByName(AirbaseName)
return self
end
--- Set destination airbase.
-- @param #FLIGHTPLAN self
-- @param #string AirbaseName Name of the airbase or AIRBASE object.
-- @return #FLIGHTPLAN self
function FLIGHTPLAN:SetDestinationAirbase(AirbaseName)
self.destinationAirbase=AIRBASE:FindByName(AirbaseName)
return self
end
--- Set cruise altitude.
-- @param #FLIGHTPLAN self
-- @param #number AltMin Minimum altitude in feet MSL.
-- @param #number AltMax Maximum altitude in feet MSL. Default is `AltMin`.
-- @return #FLIGHTPLAN self
function FLIGHTPLAN:SetCruiseAltitude(AltMin, AltMax)
self.altitudeCruiseMin=AltMin
self.altitudeCruiseMax=AltMax or self.altitudeCruiseMin
return self
end
--- Set cruise speed.
-- @param #FLIGHTPLAN self
-- @param #number SpeedMin Minimum speed in knots.
-- @param #number SpeedMax Maximum speed in knots. Default is `SpeedMin`.
-- @return #FLIGHTPLAN self
function FLIGHTPLAN:SetCruiseSpeed(SpeedMin, SpeedMax)
self.speedCruiseMin=SpeedMin
self.speedCruiseMax=SpeedMax or self.speedCruiseMin
return self
end
--- Get the name of this flight plan.
-- @param #FLIGHTPLAN self
-- @return #string The name.
function FLIGHTPLAN:GetName()
return self.alias
end
--- Get cruise altitude. This returns a random altitude between the set min/max cruise altitudes.
-- @param #FLIGHTPLAN self
-- @return #number Cruise altitude in feet MSL.
function FLIGHTPLAN:GetCruiseAltitude()
local alt=10000
if self.altitudeCruiseMin and self.altitudeCruiseMax then
alt=math.random(self.altitudeCruiseMin, self.altitudeCruiseMax)
elseif self.altitudeCruiseMin then
alt=self.altitudeCruiseMin
elseif self.altitudeCruiseMax then
alt=self.altitudeCruiseMax
end
return alt
end
--- Get cruise speed. This returns a random speed between the set min/max cruise speeds.
-- @param #FLIGHTPLAN self
-- @return #number Cruise speed in knots.
function FLIGHTPLAN:GetCruiseSpeed()
local speed=250
if self.speedCruiseMin and self.speedCruiseMax then
speed=math.random(self.speedCruiseMin, self.speedCruiseMax)
elseif self.speedCruiseMin then
speed=self.speedCruiseMin
elseif self.altitudeCruiseMax then
speed=self.speedCruiseMax
end
return speed
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Private Functions
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Read flight plan from a given MSFS 2020 .plt file.
-- @param #string FileName Name of the file.
-- @return #FLIGHTPLAN The flight plan.
function FLIGHTPLAN._ReadFileMSFS(FileName)
local function readfile(filename)
local lines = {}
-- Open file in read binary mode.
local file=assert(io.open(filename, "rb"), string.format("File not found! File name = %s", tostring(filename)))
for line in file:lines() do
lines[#lines+1] = line
end
-- Close file.
file:close()
-- Return data
return lines
end
--- This function returns an XML element, i.e. the string between <...> and </...>.
local function getXMLelement(line)
local element=string.match(line, ">(.+)<")
return element
end
--- This function returns Latitude and Longitude
local function getLatLong(line)
local latlong=getXMLelement(line)
-- The format is "N41° 38' 20.00",E41° 33' 19.00",+000000.00" so we still need to process that.
local lat,long=string.match(latlong, "(.+),(.+),")
return lat,long
end
-- Read data from file.
local data=readfile(FileName)
local flightplan={}
local waypoints={}
local wp=nil
local gotwaypoint=false
for i,line in pairs(data) do
--print(line)
-- Title
if string.find(line, "<Title>") then
flightplan.title=getXMLelement(line)
end
-- Departure ICAO
if string.find(line, "<DepartureID>") then
flightplan.departureICAO=getXMLelement(line)
end
-- Destination ICAO
if string.find(line, "<DestinationID>") then
flightplan.destinationICAO=getXMLelement(line)
end
-- FPType
if string.find(line, "<FPType>") then
flightplan.plantype=getXMLelement(line)
end
-- Route type
if string.find(line, "<RouteType>") then
flightplan.routetype=getXMLelement(line)
end
-- Cruise alt in feet
if string.find(line, "<CruisingAlt>") then
flightplan.altCruise=getXMLelement(line)
end
-- Departure LLA
if string.find(line, "<DepartureLLA>") then
local lat,long=getLatLong(line)
end
-- Destination LLA
if string.find(line, "<DestinationLLA>") then
local lat,long=getLatLong(line)
end
-- Departure Name
if string.find(line, "<DepartureName>") then
local DepartureName=getXMLelement(line)
end
-- DestinationName
if string.find(line, "<DestinationName>") then
local DestinationName=getXMLelement(line)
end
---
-- Waypoint stuff
---
-- New waypoint starts.
if string.find(line, "ATCWaypoint id") then
--Get string inside quotes " and ".
local wpid=string.match(line, [["(.+)"]])
-- Create a new wp table.
wp={}
-- Set waypoint name.
wp.name=wpid
end
-- Waypoint info ends.
if string.find(line, "</ATCWaypoint>") then
-- This is the end of the waypoint.
-- Add info to waypoints table.
table.insert(waypoints, wp)
-- Set waypoint to nil. We create an empty table if the next wp starts.
wp=nil
end
-- Waypoint type (Airport, Intersection, NDB, VORTAC)
if string.find(line, "<ATCWaypointType>") then
local wptype=getXMLelement(line)
wp.type=wptype
end
-- Waypoint position.
if string.find(line, "<WorldPosition>") then
wp.lat, wp.long=getLatLong(line)
end
-- Runway should exist for initial and final WP if it is an airport.
if string.find(line, "RunwayNumberFP") then
wp.runway=getXMLelement(line)
end
-- Runway designator: LEFT, RIGHT, CENTER
if string.find(line, "RunwayDesignatorFP") then
wp.runwayDesignator=getXMLelement(line)
end
-- Segment is Departure
if string.find(line, "<DepartureFP>") then
wp.segment="Departure"
end
-- Segment is Arrival
if string.find(line, "<ArrivalFP>") then
wp.segment="Arrival"
end
-- Segment is Enroute
if string.find(line, "<ATCAirway>") then
wp.segment="Enroute"
end
-- Approach type: VORDME, LOCALIZER
if string.find(line, "ApproachTypeFP") then
flightplan.approachtype=getXMLelement(line)
end
-- Approach type suffic: Z
if string.find(line, "SuffixFP") then
local SuffixFP=getXMLelement(line)
end
end
for key, value in pairs(flightplan) do
env.info(string.format("Flightplan %s=%s", key, tostring(value)))
end
env.info(string.format("Number of waypoints=%d", #waypoints))
for i,wp in pairs(waypoints) do
env.info(string.format("Waypoint name=%s type=%s segment=%s runway=%s lat=%s long=%s", wp.name, wp.type, tostring(wp.segment), tostring(wp.runway)..tostring(wp.runwayDesignator or ""), wp.lat, wp.long))
end
-- Create a new flightplan.
local fp=FLIGHTPLAN:New(flightplan.title)
-- Set cruise altitude.
fp:SetCruiseAltitude(flightplan.altCruise)
-- Set departure and destination airports.
fp:SetDepartureAirbase(flightplan.departureICAO)
fp:SetDestinationAirbase(flightplan.destinationICAO)
--TODO: Remove first and last waypoint if they are identical to the departure/destination airport!
for i,wp in pairs(waypoints) do
-- Create a navpoint.
local navpoint=NAVPOINT:NewFromLLDMS(wp.name, wp.type, wp.lat, wp.long)
navpoint:SetAltMin(flightplan.altCruise)
-- Add point to flightplan.
-- TODO: section departure, enroute, arrival.
fp:AddNavFix(navpoint)
end
return fp
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

View File

@@ -0,0 +1,587 @@
--- **NAVIGATION** - Navigation Airspace Points, Fixes and Aids.
--
-- **Main Features:**
--
-- * Stuff
-- * More Stuff
--
-- ===
--
-- ## Example Missions:
--
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/Navigation%20-%20NavFix).
--
-- ===
--
-- ### Author: **funkyfranky**
--
-- ===
-- @module Navigation.Point
-- @image NAVIGATION_Point.png
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- NAVFIX class.
-- @type NAVFIX
--
-- @field #string ClassName Name of the class.
-- @field #number verbose Verbosity of output.
-- @field #string name Name of the point.
-- @field #string typePoint Type of the point, *e.g. "Intersection", "VOR", "Airport".
-- @field Core.Vector#VECTOR vector Position vector of the fix.
-- @field Wrapper.Marker#MARKER marker Marker on F10 map.
-- @field #number altMin Minimum altitude in meters.
-- @field #number altMax Maximum altitude in meters.
-- @field #number speedMin Minimum speed in knots.
-- @field #number speedMax Maximum speed in knots.
--
-- @field #boolean isCompulsory Is this a compulsory fix.
-- @field #boolean isFlyover Is this a flyover fix (`true`) or turning point otherwise.
-- @field #boolean isFAF Is this a final approach fix.
-- @field #boolean isIAF Is this an initial approach fix.
-- @field #boolean isIF Is this an initial fix.
-- @field #boolean isMAF Is this an initial fix.
--
-- @extends Core.Base#BASE
--- *A fleet of British ships at war are the best negotiators.* -- Horatio Nelson
--
-- ===
--
-- # The NAVFIX Concept
--
-- The NAVFIX class has a great concept!
--
-- A NAVFIX describes a geo position and can, *e.g.*, be part of a FLIGHTPLAN. It has a unique name and is of a certain type, *e.g.* "Intersection", "VOR", "Airbase" etc.
-- It can also have further properties as min/max altitudes and speeds that aircraft need to obey when they pass the point.
--
-- # Basic Setup
--
-- A new `NAVFIX` object can be created with the @{#NAVFIX.New}() function.
--
-- myNavPoint=NAVFIX:New()
-- myTemplate:SetXYZ(X, Y, Z)
--
-- This is how it works.
--
-- @field #NAVFIX
NAVFIX = {
ClassName = "NAVFIX",
verbose = 0,
}
--- Type of point.
-- @type NAVFIX.Type
-- @field #string POINT Waypoint.
-- @field #string INTERSECTION Intersection of airway.
-- @field #string AIRPORT Airport.
-- @field #string VOR Very High Frequency Omnidirectional Range Station.
-- @field #string DME Distance Measuring Equipment.
-- @field #string NDB Non-Directional Beacon.
-- @field #string VORDME Combined VHF omnidirectional range (VOR) with a distance-measuring equipment (DME).
-- @field #string LOC Localizer.
-- @field #string ILS Instrument Landing System.
-- @field #string TACAN TACtical Air Navigation System (TACAN).
NAVFIX.Type={
POINT="Point",
INTERSECTION="Intersection",
AIRPORT="Airport",
NDB="NDB",
VOR="VOR",
DME="DME",
VORDME="VOR/DME",
LOC="Localizer",
ILS="ILS",
TACAN="TACAN"
}
--- NAVFIX class version.
-- @field #string version
NAVFIX.version="0.0.1"
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- ToDo list
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO: A lot...
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Constructor(s)
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Create a new NAVFIX class instance from a given VECTOR.
-- @param #NAVFIX self
-- @param #string Name Name/ident of the point. Should be unique!
-- @param #string Type Type of the point. Default `NAVFIX.Type.POINT`.
-- @param Core.Vector#VECTOR Vector Position vector of the navpoint.
-- @return #NAVFIX self
function NAVFIX:NewFromVector(Name, Type, Vector)
-- Inherit everything from BASE class.
self=BASE:Inherit(self, BASE:New()) -- #NAVFIX
-- Vector of point.
self.vector=Vector
-- Name of point.
self.name=Name
-- Type of the point.
self.typePoint=Type or NAVFIX.Type.POINT
local coord=COORDINATE:NewFromVec3(self.vector)
-- Marker on F10.
self.marker=MARKER:New(coord, self:_GetMarkerText())
-- Log ID string.
self.lid=string.format("NAVFIX %s [%s] | ", tostring(self.name), tostring(self.typePoint))
-- Debug info.
self:I(self.lid..string.format("Created NAVFIX"))
return self
end
--- Create a new NAVFIX class instance from a given COORDINATE.
-- @param #NAVFIX self
-- @param #string Name Name of the fix. Should be unique!
-- @param #string Type Type of the point. Default `NAVFIX.Type.POINT`.
-- @param Core.Point#COORDINATE Coordinate Coordinate of the point.
-- @return #NAVFIX self
function NAVFIX:NewFromCoordinate(Name, Type, Coordinate)
-- Create a VECTOR from the coordinate.
local Vector=VECTOR:NewFromVec(Coordinate)
-- Create NAVFIX.
self=NAVFIX:NewFromVector(Name, Type, Vector)
return self
end
--- Create a new NAVFIX instance from given latitude and longitude in degrees, minutes and seconds (DMS).
-- @param #NAVFIX self
-- @param #string Name Name of the fix. Should be unique!
-- @param #string Type Type of the point. Default `NAVFIX.Type.POINT`.
-- @param #string Latitude Latitude in DMS as string.
-- @param #string Longitude Longitude in DMS as string.
-- @return #NAVFIX self
function NAVFIX:NewFromLLDMS(Name, Type, Latitude, Longitude)
-- Create a VECTOR from the coordinate.
local Vector=VECTOR:NewFromLLDMS(Latitude, Longitude)
-- Create NAVFIX.
self=NAVFIX:NewFromVector(Name, Type, Vector)
return self
end
--- Create a new NAVFIX instance from given latitude and longitude in decimal degrees (DD).
-- @param #NAVFIX self
-- @param #string Name Name of the fix. Should be unique!
-- @param #string Type Type of the point. Default `NAVFIX.Type.POINT`.
-- @param #number Latitude Latitude in DD.
-- @param #number Longitude Longitude in DD.
-- @return #NAVFIX self
function NAVFIX:NewFromLLDD(Name, Type, Latitude, Longitude)
-- Create a VECTOR from the coordinate.
local Vector=VECTOR:NewFromLLDD(Latitude, Longitude)
-- Create NAVFIX.
self=NAVFIX:NewFromVector(Name, Type, Vector)
return self
end
--- Create a new NAVFIX class instance relative to a given other NAVFIX.
-- You have to specify the distance and bearing from the new point to the given point. *E.g.*, for a distance of 5 NM and a bearing of 090° (West), the
-- new nav point is created 5 NM East of the given nav point. The reason is that this corresponts to convention used in most maps.
-- You can, however, use the `Reciprocal` switch to create the new point in the direction you specify.
-- @param #NAVFIX self
-- @param #string Name Name of the fix. Should be unique!
-- @param #string Type Type of navfix.
-- @param #NAVFIX NavFix The given/existing navigation fix relative to which the new fix is created.
-- @param #number Distance Distance from the given to the new point in nautical miles.
-- @param #number Bearing Bearing [Deg] from the new point to the given one.
-- @param #boolean Reciprocal If `true` the reciprocal `Bearing` is taken so it specifies the direction from the given point to the new one.
-- @return #NAVFIX self
function NAVFIX:NewFromNavFix(Name, Type, NavFix, Distance, Bearing, Reciprocal)
-- Convert magnetic to true bearing by adding magnetic declination, e.g. mag. bearing 10°M ==> true bearing 16°M (for 6° variation on Caucasus map)
Bearing=Bearing+UTILS.GetMagneticDeclination()
if Reciprocal then
Bearing=Bearing-180
end
-- Translate.
local Vector=NavFix.vector:Translate(UTILS.NMToMeters(Distance), Bearing, true)
self=NAVFIX:NewFromVector(Name, Type, Vector)
return self
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- User Functions
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Set whether this is the intermediate fix (IF).
-- @param #NAVFIX self
-- @return #NAVFIX self
function NAVFIX:SetIntermediateFix(IntermediateFix)
self.isIF=IntermediateFix
return self
end
--- Set whether this is an initial approach fix (IAF).
-- The IAF is the point where the initial approach segment of an instrument approach begins.
-- It is usually a designated intersection, VHF omidirectional range (VOR) non-directional beacon (NDB)
-- or distance measuring equipment (DME) fix.
-- The IAF may be collocated with the intermediate fix (IF) of the instrument apprach an in such case they designate the
-- beginning of the intermediate segment of the approach. When the IAF and the IF are combined, there is no inital approach segment.
-- @param #NAVFIX self
-- @param #boolean IntermediateFix If `true`, this is an intermediate fix.
-- @return #NAVFIX self
function NAVFIX:SetInitialApproachFix(IntermediateFix)
self.isIAF=IntermediateFix
return self
end
--- Set whether this is the final approach fix (FAF).
-- @param #NAVFIX self
-- @param #boolean FinalApproachFix If `true`, this is a final approach fix.
-- @return #NAVFIX self
function NAVFIX:SetFinalApproachFix(FinalApproachFix)
self.isFAF=FinalApproachFix
return self
end
--- Set whether this is the final approach fix (FAF).
-- @param #NAVFIX self
-- @param #boolean FinalApproachFix If `true`, this is a final approach fix.
-- @return #NAVFIX self
function NAVFIX:SetMissedApproachFix(MissedApproachFix)
self.isMAF=MissedApproachFix
return self
end
--- Set minimum altitude.
-- @param #NAVFIX self
-- @param #number Altitude Min altitude in feet.
-- @return #NAVFIX self
function NAVFIX:SetAltMin(Altitude)
self.altMin=Altitude
return self
end
--- Set maximum altitude.
-- @param #NAVFIX self
-- @param #number Altitude Max altitude in feet.
-- @return #NAVFIX self
function NAVFIX:SetAltMax(Altitude)
self.altMax=Altitude
return self
end
--- Set mandatory altitude (min alt = max alt).
-- @param #NAVFIX self
-- @param #number Altitude Altitude in feet.
-- @return #NAVFIX self
function NAVFIX:SetAltMandatory(Altitude)
self.altMin=Altitude
self.altMax=Altitude
return self
end
--- Set minimum allowed speed at this fix.
-- @param #NAVFIX self
-- @param #number Speed Min speed in knots.
-- @return #NAVFIX self
function NAVFIX:SetSpeedMin(Speed)
self.speedMin=Speed
return self
end
--- Set maximum allowed speed at this fix.
-- @param #NAVFIX self
-- @param #number Speed Max speed in knots.
-- @return #NAVFIX self
function NAVFIX:SetSpeedMax(Speed)
self.speedMax=Speed
return self
end
--- Set mandatory speed (min speed = max speed) at this fix.
-- @param #NAVFIX self
-- @param #number Speed Mandatory speed in knots.
-- @return #NAVFIX self
function NAVFIX:SetSpeedMandatory(Speed)
self.speedMin=Speed
self.speedMax=Speed
return self
end
--- Set whether this fix is compulsory.
-- @param #NAVFIX self
-- @param #boolean Compulsory If `true`, this is a compusory fix. If `false` or nil, it is non-compulsory.
-- @return #NAVFIX self
function NAVFIX:SetCompulsory(Compulsory)
self.isCompulsory=Compulsory
return self
end
--- Set whether this is a fly-over fix fix.
-- @param #NAVFIX self
-- @param #boolean FlyOver If `true`, this is a fly over fix. If `false` or nil, it is not.
-- @return #NAVFIX self
function NAVFIX:SetFlyOver(FlyOver)
self.isFlyover=FlyOver
return self
end
--- Get the altitude in feet MSL. If min and max altitudes are set, it will return a random altitude between min and max.
-- @param #NAVFIX self
-- @return #number Altitude in feet MSL. Can be `nil`, if neither min nor max altitudes have beeen set.
function NAVFIX:GetAltitude()
local alt=nil
if self.altMin and self.altMax and self.altMin~=self.altMax then
alt=math.random(self.altMin, self.altMax)
elseif self.altMin then
alt=self.altMin
elseif self.altMax then
alt=self.altMax
end
return alt
end
--- Get the speed. If min and max speeds are set, it will return a random speed between min and max.
-- @param #NAVFIX self
-- @return #number Speed in knots. Can be `nil`, if neither min nor max speeds have beeen set.
function NAVFIX:GetSpeed()
local speed=nil
if self.speedMin and self.speedMax and self.speedMin~=self.speedMax then
speed=math.random(self.speedMin, self.speedMax)
elseif self.speedMin then
speed=self.speedMin
elseif self.speedMax then
speed=self.speedMax
end
return speed
end
--- Add marker the NAVFIX on the F10 map.
-- @param #NAVFIX self
-- @return #NAVFIX self
function NAVFIX:MarkerShow()
self.marker:ToAll()
return self
end
--- Remove marker of the NAVFIX from the F10 map.
-- @param #NAVFIX self
-- @return #NAVFIX self
function NAVFIX:MarkerRemove()
self.marker:Remove()
return self
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Private Functions
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Get text displayed in the F10 marker.
-- @param #NAVFIX self
-- @return #string Marker text.
function NAVFIX:_GetMarkerText()
local altmin=self.altMin and tostring(self.altMin) or ""
local altmax=self.altMax and tostring(self.altMax) or ""
local speedmin=self.speedMin and tostring(self.speedMin) or ""
local speedmax=self.speedMax and tostring(self.speedMax) or ""
local text=string.format("NAVFIX %s", self.name)
if self.isIAF then
text=text..string.format(" (IAF)")
end
if self.isIF then
text=text..string.format(" (IF)")
end
text=text..string.format("\nAltitude [ft]: %s - %s", altmin, altmax)
text=text..string.format("\nSpeed [knots]: %s - %s", speedmin, speedmax)
text=text..string.format("\nCompulsory: %s", tostring(self.isCompulsory))
text=text..string.format("\nFly Over: %s", tostring(self.isFlyover))
return text
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- NAVAID class.
-- @type NAVAID
-- @field #string ClassName Name of the class.
-- @field #number verbose Verbosity of output.
-- @extends Navigation.Point#NAVFIX
--- *A fleet of British ships at war are the best negotiators.* -- Horatio Nelson
--
-- ===
--
-- # The NAVAID Concept
--
-- A NAVAID consists of one or multiple FLOTILLAs. These flotillas "live" in a WAREHOUSE that has a phyiscal struction (STATIC or UNIT) and can be captured or destroyed.
--
-- # Basic Setup
--
-- A new `NAVAID` object can be created with the @{#NAVAID.New}(`WarehouseName`, `FleetName`) function, where `WarehouseName` is the name of the static or unit object hosting the fleet
-- and `FleetName` is the name you want to give the fleet. This must be *unique*!
--
-- myFleet=NAVAID:New("myWarehouseName", "1st Fleet")
-- myFleet:SetPortZone(ZonePort1stFleet)
-- myFleet:Start()
--
-- A fleet needs a *port zone*, which is set via the @{#NAVAID.SetPortZone}(`PortZone`) function. This is the zone where the naval assets are spawned and return to.
--
-- Finally, the fleet needs to be started using the @{#NAVAID.Start}() function. If the fleet is not started, it will not process any requests.
--
-- @field #NAVAID
NAVAID = {
ClassName = "NAVAID",
verbose = 0,
}
--- NAVAID class version.
-- @field #string version
NAVAID.version="0.0.1"
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- ToDo list
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO: Add frequencies. Which unit MHz, kHz, Hz?
-- TODO: Add radial function
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Constructor
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Create a new NAVAID class instance.
-- @param #NAVAID self
-- @param #string Name Name/ident of this navaid.
-- @param #string Type Type of the point. Default `NAVFIX.Type.POINT`.
-- @param #string ZoneName Name of the zone to scan the scenery.
-- @param #string SceneryName Name of the scenery object.
-- @return #NAVAID self
function NAVAID:NewFromScenery(Name, Type, ZoneName, SceneryName)
-- Get the zone.
local zone=ZONE:FindByName(ZoneName)
-- Get coordinate.
local Coordinate=zone:GetCoordinate()
-- Inherit everything from NAVFIX class.
self=BASE:Inherit(self, NAVFIX:NewFromCoordinate(Name, Type, Coordinate)) -- #NAVAID
-- Set zone.
self.zone=ZONE:FindByName(ZoneName)
-- Try to get the scenery object. Note not all can be found unfortunately.
if SceneryName then
self.scenery=SCENERY:FindByNameInZone(SceneryName, ZoneName)
if not self.scenery then
self:E(string.format("ERROR: Could not find scenery object %s in zone %s", SceneryName, ZoneName))
end
end
-- Alias.
self.alias=string.format("%s %s %s", tostring(ZoneName), tostring(SceneryName), tostring(Type))
-- Set some string id for output to DCS.log file.
self.lid=string.format("NAVAID %s | ", self.alias)
-- Debug info.
self:I(self.lid..string.format("Created NAVAID!"))
return self
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- User Functions
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Set frequency the beacon transmits on.
-- @param #NAVAID self
-- @param #number Frequency Frequency in Hz.
-- @return #NAVAID self
function NAVAID:SetFrequency(Frequency)
self.frequency=Frequency
return self
end
--- Set channel of, *e.g.*, TACAN beacons.
-- @param #NAVAID self
-- @param #number Channel The channel.
-- @param #string Band The band either `"X"` (default) or `"Y"`.
-- @return #NAVAID self
function NAVAID:SetChannel(Channel, Band)
self.channel=Channel
self.band=Band or "X"
return self
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Private Functions
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Add private CLASS functions here.
-- No private NAVAID functions yet.
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

View File

@@ -0,0 +1,333 @@
--- **NAVIGATION** - Prodedures for Departure (*e.g.* SID), Enroute, Arrival (*e.g.* STAR) and Approach.
--
-- **Main Features:**
--
-- * Stuff
-- * More Stuff
--
-- ===
--
-- ## Example Missions:
--
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/Navigation%20-%20Template).
--
-- ===
--
-- ### Author: **funkyfranky**
--
-- ===
-- @module Navigation.Procedure
-- @image NAVIGATION_Procedure.png
--- APPROACH class.
-- @type APPROACH
-- @field #string ClassName Name of the class.
-- @field #number verbose Verbosity of output.
-- @field #string apptype Approach type (ILS, VOR, LOC).
-- @field Wrapper.Airbase#AIRBASE airbase Airbase of this approach.
-- @field Wrapper.Airbase#AIRBASE.Runway runway Runway of this approach.
-- @field Navigation.Point#NAVAID navaid Primary navigation aid.
-- @field #number wpcounter Running number counting the waypoints to generate its UID.
-- @list <#APPROACH.Waypoint> path Path of approach consisting of waypoints.
-- @extends Core.Base#BASE
--- *A fleet of British ships at war are the best negotiators.* -- Horatio Nelson
--
-- ===
--
-- # The APPROACH Concept
--
-- A typical approach has (up to) four segments. It starts with the initial approach segment, followed by the intermediate approach segment, followed
-- by the final approach segment. In case something goes wrong during the final approach, the missed approach segment kicks in.
--
-- The initial approach segment starts at the initial approach fix (IAF). The segment can contain multiple other fixes, that need to be passed.
-- Note, that an approach procedure can have more than one intitial approach segment and IAF.
--
-- The intermediate approach segment starts at the intermediate fix (IF). The intermediate approach segment blends the initial approach segment into the final approach segment.
-- It is the segment in which aircraft configuration, speed, and positioning adjustments are made for entry into the final approach segment.
--
--
-- https://en.wikipedia.org/wiki/Visual_approach
-- https://en.wikipedia.org/wiki/Instrument_approach
--
-- # Basic Setup
--
-- A new `APPROACH` object can be created with the @{#APPROACH.New}() function.
--
-- myTemplate=APPROACH:New()
-- myTemplate:SetXYZ(X, Y, Z)
--
-- This is how it works.
--
-- @field #APPROACH
APPROACH = {
ClassName = "APPROACH",
verbose = 0,
wpcounter = 0,
}
--- Type of approach.
-- @type APPROACH.Type
-- @field #string VFR Visual Flight Rules.
-- @field #string VOR VOR
-- @field #string NDB NDB
APPROACH.Type={
VFR="VFR",
VOR="VOR",
ILS="ILS",
}
--- Setments of approach.
-- @type APPROACH.Segment
-- @field #string INITIAL Initial approach segment.
-- @field #string INTERMEDIATE Intermediate approach segment.
-- @field #string FINAL Final approach segment.
-- @field #string MISSED Missed approach segment.
APPROACH.Segment={
INITIAL="Initial",
INTERMEDIATE="Intermediate",
FINAL="Final",
MISSED="Missed",
}
--- Waypoint of the approach.
-- @type APPROACH.Waypoint
-- @field #number uid Unique ID of the point.
-- @field #string segment The segment this point belongs to.
-- @field Navigation.Point#NAVFIX navfix The navigation fix that determines the coordinates of this point.
--- APPROACH class version.
-- @field #string version
APPROACH.version="0.0.1"
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- ToDo list
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO: A lot...
-- Initial approach segment --> Intermediate approach segment: starts at IF --> Final approach segment
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Constructor
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Create a new APPROACH class instance.
-- @param #APPROACH self
-- @param #string Type Type of approach (ILS, VOR, LOC).
-- @param Wrapper.Airbase#AIRBASE Airbase The airbase or name of the airbase.
-- @param Wrapper.Airbase#AIRBASE.Runway Runway The runway or name of the runway.
-- @return #APPROACH self
function APPROACH:New(Type, Airbase, Runway)
-- Inherit everything from BASE class.
self=BASE:Inherit(self, BASE:New()) -- #APPROACH
-- Set approach type.
-- TODO: Check if this is a valid/known approach type.
self.apptype=Type
if type(Airbase)=="string" then
self.airbase=AIRBASE:FindByName(Airbase)
else
self.airbase=Airbase
end
if type(Runway)=="string" then
self.runway=self.airbase:GetRunwayByName(Runway)
else
self.runway=Runway
end
-- Debug info.
self:I("Created new approach for airbase %s: type=%s, runway=%s", self.airbase:GetName(), self.apptype, self.runway.name)
return self
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- User Functions
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Set the primary navigation aid used in the approach.
-- @param #APPROACH self
-- @param Navigation.Point#NAVAID NavAid The NAVAID.
-- @return #APPROACH self
function APPROACH:SetNavAid(NavAid)
self.navaid=NavAid
return self
end
--- Add a waypoint to the path of the approach.
-- @param #APPROACH self
-- @param Navigation.Point#NAVFIX NavFix The navigation fix.
-- @param #string Segment The approach segment this fix belongs to.
-- @return #APPROACH.Waypoint The waypoint data table.
function APPROACH:AddNavFix(NavFix, Segment)
self.wpcounter=self.wpcounter+1
local point={} --#APPROACH.Waypoint
point.uid=self.wpcounter
point.segment=Segment
point.navfix=NavFix
table.insert(self.path, point)
return point
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Private Functions
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Add private functions here.
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- DEPARTURE class.
-- @type DEPARTURE
-- @field #string ClassName Name of the class.
-- @field #number verbose Verbosity of output.
-- @field #string apptype DEPARTURE type (ILS, VOR, LOC).
-- @field Wrapper.Airbase#AIRBASE airbase Airbase of this DEPARTURE.
-- @field Wrapper.Airbase#AIRBASE.Runway runway Runway of this DEPARTURE.
-- @field Navigation.Point#NAVAID navaid Primary navigation aid.
-- @field #number wpcounter Running number counting the waypoints to generate its UID.
-- @list <#DEPARTURE.Waypoint> path Path of DEPARTURE consisting of waypoints.
-- @extends Core.Base#BASE
--- *A fleet of British ships at war are the best negotiators.* -- Horatio Nelson
--
-- ===
--
-- # The DEPARTURE Concept
--
-- Bla.
--
-- @field #DEPARTURE
DEPARTURE = {
ClassName = "DEPARTURE",
verbose = 0,
wpcounter = 0,
}
--- Type of DEPARTURE.
-- @type DEPARTURE.Type
-- @field #string VOR VOR
-- @field #string NDB NDB
DEPARTURE.Type={
VOR="VOR",
ILS="ILS",
}
--- Setments of DEPARTURE.
-- @type DEPARTURE.Segment
-- @field #string INITIAL Initial DEPARTURE segment.
-- @field #string INTERMEDIATE Intermediate DEPARTURE segment.
-- @field #string FINAL Final DEPARTURE segment.
-- @field #string MISSED Missed DEPARTURE segment.
DEPARTURE.Segment={
INITIAL="Initial",
INTERMEDIATE="Intermediate",
FINAL="Final",
MISSED="Missed",
}
--- Waypoint of the DEPARTURE.
-- @type DEPARTURE.Waypoint
-- @field #number uid Unique ID of the point.
-- @field #string segment The segment this point belongs to.
-- @field Navigation.Point#NAVFIX navfix The navigation fix that determines the coordinates of this point.
--- DEPARTURE class version.
-- @field #string version
DEPARTURE.version="0.0.1"
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- ToDo list
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO: A lot...
-- Initial DEPARTURE segment --> Intermediate DEPARTURE segment: starts at IF --> Final DEPARTURE segment
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Constructor
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Create a new DEPARTURE class instance.
-- @param #DEPARTURE self
-- @param Wrapper.Airbase#AIRBASE Airbase The airbase or name of the airbase.
-- @param Wrapper.Airbase#AIRBASE.Runway Runway The runway or name of the runway.
-- @param #string Type Type of DEPARTURE (ILS, VOR, LOC).
-- @return #DEPARTURE self
function DEPARTURE:New(Airbase, Runway)
-- Inherit everything from BASE class.
self=BASE:Inherit(self, BASE:New()) -- #DEPARTURE
if type(Airbase)=="string" then
self.airbase=AIRBASE:FindByName(Airbase)
else
self.airbase=Airbase
end
if type(Runway)=="string" then
self.runway=self.airbase:GetRunwayByName(Runway)
else
self.runway=Runway
end
return self
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- User Functions
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Set the primary navigation aid used in the DEPARTURE.
-- @param #DEPARTURE self
-- @param Navigation.Point#NAVAID NavAid The NAVAID.
-- @return #DEPARTURE self
function DEPARTURE:SetNavAid(NavAid)
self.navaid=NavAid
return self
end
--- Add a waypoint to the path of the DEPARTURE.
-- @param #DEPARTURE self
-- @param Navigation.Point#NAVFIX NavFix The navigation fix.
-- @param #string Segment The DEPARTURE segment this fix belongs to.
-- @return #DEPARTURE.Waypoint The waypoint data.
function DEPARTURE:AddWaypoint(NavFix, Segment)
self.wpcounter=self.wpcounter+1
local point={} --#DEPARTURE.Waypoint
point.uid=self.wpcounter
point.segment=Segment
point.navfix=NavFix
table.insert(self.path, point)
return point
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Private Functions
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Add DEPARTURE private functions here.
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

View File

@@ -0,0 +1,108 @@
--- **NAVIGATION** - Template.
--
-- **Main Features:**
--
-- * Stuff
-- * More Stuff
--
-- ===
--
-- ## Example Missions:
--
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/Navigation%20-%20Template).
--
-- ===
--
-- ### Author: **funkyfranky**
--
-- ===
-- @module Navigation.Template
-- @image NAVIGATION_Template.png
--- TEMPLATE class.
-- @type TEMPLATE
-- @field #string ClassName Name of the class.
-- @field #number verbose Verbosity of output.
-- @extends Core.Base#BASE
--- *A fleet of British ships at war are the best negotiators.* -- Horatio Nelson
--
-- ===
--
-- # The TEMPLATE Concept
--
-- The TEMPLATE class has a great concept!
--
-- # Basic Setup
--
-- A new `TEMPLATE` object can be created with the @{#TEMPLATE.New}() function.
--
-- myTemplate=TEMPLATE:New()
-- myTemplate:SetXYZ(X, Y, Z)
--
-- This is how it works.
--
-- @field #TEMPLATE
TEMPLATE = {
ClassName = "TEMPLATE",
verbose = 0,
}
--- Type of navaid
-- @type TEMPLATE.Type
-- @field #string VOR VOR
-- @field #string NDB NDB
TEMPLATE.TYPE={
VOR="VOR",
NDB="NDB",
}
--- TEMPLATE class version.
-- @field #string version
TEMPLATE.version="0.0.1"
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- ToDo list
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO: A lot...
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Constructor
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Create a new TEMPLATE class instance.
-- @param #TEMPLATE self
-- @return #TEMPLATE self
function TEMPLATE:New()
-- Inherit everything from SCENERY class.
self=BASE:Inherit(self, BASE:New()) -- #TEMPLATE
return self
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- User Functions
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Set frequency.
-- @param #TEMPLATE self
-- @param #number Frequency Frequency in Hz.
-- @return #TEMPLATE self
function TEMPLATE:SetFrequency(Frequency)
self.frequency=Frequency
return self
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Private Functions
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

View File

@@ -501,6 +501,7 @@ ATIS.Alphabet = {
-- @field #number Kola +15° (East).
-- @field #number Afghanistan +3° (East).
-- @field #number Iraq +4.4° (East).
-- @field #number GermanyCW +0.1° (East).
ATIS.RunwayM2T = {
Caucasus = 0,
Nevada = 12,
@@ -513,7 +514,8 @@ ATIS.RunwayM2T = {
SinaiMap = 5,
Kola = 15,
Afghanistan = 3,
Iraq=4.4
Iraq=4.4,
GermanyCW=0.1,
}
--- Whether ICAO phraseology is used for ATIS broadcasts.
@@ -530,6 +532,7 @@ ATIS.RunwayM2T = {
-- @field #boolean Kola true.
-- @field #boolean Afghanistan true.
-- @field #boolean Iraq true.
-- @field #boolean GermanyCW true.
ATIS.ICAOPhraseology = {
Caucasus = true,
Nevada = false,
@@ -543,6 +546,7 @@ ATIS.ICAOPhraseology = {
Kola = true,
Afghanistan = true,
Iraq = true,
GermanyCW = true,
}
--- Nav point data.

View File

@@ -599,7 +599,80 @@ function BRIGADE:onafterStatus(From, Event, To)
text=text..string.format("\n* %s: spawned=%s", asset.spawngroupname, tostring(asset.spawned))
end
self:I(self.lid..text)
end
end
if self.verbose>=3 then
-- Count numbers
local Ntotal=0
local Nspawned=0
local Nrequested=0
local Nreserved=0
local Nstock=0
local text="\n===========================================\n"
text=text.."Assets:"
local legion=self --Ops.Legion#LEGION
for _,_cohort in pairs(legion.cohorts) do
local cohort=_cohort --Ops.Cohort#COHORT
for _,_asset in pairs(cohort.assets) do
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
local state="In Stock"
if asset.flightgroup then
state=asset.flightgroup:GetState()
local mission=legion:GetAssetCurrentMission(asset)
if mission then
state=state..string.format(", Mission \"%s\" [%s]", mission:GetName(), mission:GetType())
end
else
if asset.spawned then
env.info("FF ERROR: asset has opsgroup but is NOT spawned!")
end
if asset.requested and asset.isReserved then
env.info("FF ERROR: asset is requested and reserved. Should not be both!")
state="Reserved+Requested!"
elseif asset.isReserved then
state="Reserved"
elseif asset.requested then
state="Requested"
end
end
-- Text.
text=text..string.format("\n[UID=%03d] %s Legion=%s [%s]: State=%s [RID=%s]",
asset.uid, asset.spawngroupname, legion.alias, cohort.name, state, tostring(asset.rid))
if asset.spawned then
Nspawned=Nspawned+1
end
if asset.requested then
Nrequested=Nrequested+1
end
if asset.isReserved then
Nreserved=Nreserved+1
end
if not (asset.spawned or asset.requested or asset.isReserved) then
Nstock=Nstock+1
end
Ntotal=Ntotal+1
end
end
text=text.."\n-------------------------------------------"
text=text..string.format("\nNstock = %d", Nstock)
text=text..string.format("\nNreserved = %d", Nreserved)
text=text..string.format("\nNrequested = %d", Nrequested)
text=text..string.format("\nNspawned = %d", Nspawned)
text=text..string.format("\nNtotal = %d (=%d)", Ntotal, Nstock+Nspawned+Nrequested+Nreserved)
text=text.."\n==========================================="
self:I(self.lid..text)
end
end

View File

@@ -1242,7 +1242,21 @@ do
-- end
-- end
--
-- ## 8. Transport crates and troops with CA (Combined Arms) trucks
--
-- You can optionally also allow to CTLD with CA trucks and other vehicles:
--
-- -- Create a SET_CLIENT to capture CA vehicles steered by players
-- local truckers = SET_CLIENT:New():HandleCASlots():FilterCoalitions("blue"):FilterPrefixes("Truck"):FilterStart()
-- -- Allow CA transport
-- my_ctld:AllowCATransport(true,truckers)
-- -- Set truck capability by typename
-- my_ctld:SetUnitCapabilities("M 818", true, true, 2, 12, 9, 4500)
-- -- Alternatively set truck capability with a UNIT object
-- local GazTruck = UNIT:FindByName("GazTruck-1-1")
-- my_ctld:SetUnitCapabilities(GazTruck, true, true, 2, 12, 9, 4500)
--
--
-- @field #CTLD
CTLD = {
ClassName = "CTLD",
@@ -1277,6 +1291,7 @@ CTLD = {
UserSetGroup = nil,
LoadedGroupsTable = {},
keeploadtable = true,
allowCATransport = false,
}
------------------------------
@@ -1384,6 +1399,7 @@ CTLD.UnitTypeCapabilities = {
["OH58D"] = {type="OH58D", crates=false, troops=false, cratelimit = 0, trooplimit = 0, length = 14, cargoweightlimit = 400},
["CH-47Fbl1"] = {type="CH-47Fbl1", crates=true, troops=true, cratelimit = 4, trooplimit = 31, length = 20, cargoweightlimit = 10800},
["MosquitoFBMkVI"] = {type="MosquitoFBMkVI", crates= true, troops=false, cratelimit = 2, trooplimit = 0, length = 13, cargoweightlimit = 1800},
["M 818"] = {type="M 818", crates= true, troops=true, cratelimit = 4, trooplimit = 12, length = 9, cargoweightlimit = 4500},
}
--- Allowed Fixed Wing Types
@@ -1396,7 +1412,7 @@ CTLD.FixedWingTypes = {
--- CTLD class version.
-- @field #string version
CTLD.version="1.1.31"
CTLD.version="1.2.33"
--- Instantiate a new CTLD.
-- @param #CTLD self
@@ -1606,6 +1622,10 @@ function CTLD:New(Coalition, Prefixes, Alias)
math.random()
end
-- CA Transport
self.allowCATransport = false -- #boolean
self.CATransportSet = nil -- Core.Set#SET_CLIENT
self:_GenerateVHFrequencies()
self:_GenerateUHFrequencies()
self:_GenerateFMFrequencies()
@@ -1949,6 +1969,16 @@ function CTLD:_GetUnitCapabilities(Unit)
return capabilities
end
--- (User) Function to allow transport via Combined Arms Trucks.
-- @param #CTLD self
-- @param #boolean OnOff Switch on (true) or off (false).
-- @param Core.Set#SET_CLIENT ClientSet The CA handling client set for ground transport.
-- @return #CTLD self
function CTLD:AllowCATransport(OnOff,ClientSet)
self.allowCATransport = OnOff -- #boolean
self.CATransportSet = ClientSet -- Core.Set#SET_CLIENT
return self
end
--- (Internal) Function to generate valid UHF Frequencies
-- @param #CTLD self
@@ -2029,6 +2059,12 @@ function CTLD:_EventHandler(EventData)
self.Loaded_Cargo[unitname] = nil
self:_RefreshF10Menus()
end
-- CA support
if _unit:IsGround() and self.allowCATransport then
local unitname = event.IniUnitName or "none"
self.Loaded_Cargo[unitname] = nil
self:_RefreshF10Menus()
end
return
elseif event.id == EVENTS.Land or event.id == EVENTS.Takeoff then
local unitname = event.IniUnitName
@@ -2742,6 +2778,7 @@ function CTLD:_GetCrates(Group, Unit, Cargo, number, drop, pack)
-- spawn crates in front of helicopter
local IsHerc = self:IsFixedWing(Unit) -- Herc, Bronco and Hook load from behind
local IsHook = self:IsHook(Unit) -- Herc, Bronco and Hook load from behind
local IsTruck = Unit:IsGround()
local cargotype = Cargo -- Ops.CTLD#CTLD_CARGO
local number = number or cargotype:GetCratesNeeded() --#number
local cratesneeded = cargotype:GetCratesNeeded() --#number
@@ -2763,7 +2800,7 @@ function CTLD:_GetCrates(Group, Unit, Cargo, number, drop, pack)
local rheading = 0
local angleOffNose = 0
local addon = 0
if IsHerc or IsHook then
if IsHerc or IsHook or IsTruck then
-- spawn behind the Herc
addon = 180
end
@@ -3093,24 +3130,24 @@ function CTLD:_FindCratesNearby( _group, _unit, _dist, _ignoreweight, ignoretype
if not _ignoreweight then
maxloadable = self:_GetMaxLoadableMass(_unit)
end
self:T2(self.lid .. " Max loadable mass: " .. maxloadable)
self:T(self.lid .. " Max loadable mass: " .. maxloadable)
for _,_cargoobject in pairs (existingcrates) do
local cargo = _cargoobject -- #CTLD_CARGO
local static = cargo:GetPositionable() -- Wrapper.Static#STATIC -- crates
local weight = cargo:GetMass() -- weight in kgs of this cargo
local staticid = cargo:GetID()
self:T2(self.lid .. " Found cargo mass: " .. weight)
self:T(self.lid .. " Found cargo mass: " .. weight)
if static and static:IsAlive() then --or cargoalive) then
local restricthooktononstatics = self.enableChinookGCLoading and IsHook
--self:I(self.lid .. " restricthooktononstatics: " .. tostring(restricthooktononstatics))
self:T(self.lid .. " restricthooktononstatics: " .. tostring(restricthooktononstatics))
local cargoisstatic = cargo:GetType() == CTLD_CARGO.Enum.STATIC and true or false
--self:I(self.lid .. " Cargo is static: " .. tostring(cargoisstatic))
self:T(self.lid .. " Cargo is static: " .. tostring(cargoisstatic))
local restricted = cargoisstatic and restricthooktononstatics
--self:I(self.lid .. " Loading restricted: " .. tostring(restricted))
self:T(self.lid .. " Loading restricted: " .. tostring(restricted))
local staticpos = static:GetCoordinate() --or dcsunitpos
local cando = cargo:UnitCanCarry(_unit)
if ignoretype == true then cando = true end
--self:I(self.lid .. " Unit can carry: " .. tostring(cando))
self:T(self.lid .. " Unit can carry: " .. tostring(cando))
--- Testing
local distance = self:_GetDistance(location,staticpos)
self:T(self.lid .. string.format("Dist %dm/%dm | weight %dkg | maxloadable %dkg",distance,finddist,weight,maxloadable))
@@ -4110,6 +4147,7 @@ function CTLD:_MoveGroupToZone(Group)
local groupcoord = Group:GetCoordinate()
-- Get closest zone of type
local outcome, name, zone, distance = self:IsUnitInZone(Group,CTLD.CargoZoneType.MOVE)
self:T({canmove=outcome, name=name, zone=zone, dist=distance,max=self.movetroopsdistance})
if (distance <= self.movetroopsdistance) and outcome == true and zone~= nil then
-- yes, we can ;)
local groupname = Group:GetName()
@@ -4184,6 +4222,19 @@ function CTLD:_RefreshF10Menus()
end
end
end
-- 3) CA Units
if self.allowCATransport and self.CATransportSet then
for _,_clientobj in pairs(self.CATransportSet.Set) do
local client = _clientobj -- Wrapper.Client#CLIENT
if client:IsGround() then
local cname = client:GetName()
self:T(self.lid.."Adding: "..cname)
_UnitList[cname] = cname
end
end
end
self.CtldUnits = _UnitList
-- subcats?
@@ -4212,10 +4263,15 @@ function CTLD:_RefreshF10Menus()
local menus = {}
for _, _unitName in pairs(self.CtldUnits) do
if (not self.MenusDone[_unitName]) or (self.showstockinmenuitems == true) then
self:T(self.lid.."Menu not done yet for ".._unitName)
local _unit = UNIT:FindByName(_unitName)
if not _unit and self.allowCATransport then
_unit = CLIENT:FindByName(_unitName)
end
if _unit and _unit:IsAlive() then
local _group = _unit:GetGroup()
if _group then
self:T(self.lid.."Unit and Group exist")
local capabilities = self:_GetUnitCapabilities(_unit)
local cantroops = capabilities.troops
local cancrates = capabilities.crates
@@ -5191,6 +5247,8 @@ function CTLD:ActivateZone(Name,ZoneType,NewState)
table = self.dropOffZones
elseif ZoneType == CTLD.CargoZoneType.SHIP then
table = self.shipZones
elseif ZoneType == CTLD.CargoZoneType.BEACON then
table = self.droppedBeacons
else
table = self.wpZones
end
@@ -5623,7 +5681,8 @@ function CTLD:IsUnitInZone(Unit,Zonetype)
end
local distance = self:_GetDistance(zonecoord,unitcoord)
self:T("Distance Zone: "..distance)
if (zone:IsVec2InZone(unitVec2) or Zonetype == CTLD.CargoZoneType.MOVE) and active == true and maxdist > distance then
self:T("Zone Active: "..tostring(active))
if (zone:IsVec2InZone(unitVec2) or Zonetype == CTLD.CargoZoneType.MOVE) and active == true and distance < maxdist then
outcome = true
maxdist = distance
zoneret = zone
@@ -5730,9 +5789,8 @@ end
local unit = nil
if type(Unittype) == "string" then
unittype = Unittype
elseif type(Unittype) == "table" then
unit = UNIT:FindByName(Unittype) -- Wrapper.Unit#UNIT
unittype = unit:GetTypeName()
elseif type(Unittype) == "table" and Unittype.ClassName and Unittype:IsInstanceOf("UNIT") then
unittype = Unittype:GetTypeName()
else
return self
end
@@ -7699,7 +7757,7 @@ end
--- [Internal] Function to spawn a soldier group of 10 units
-- @param #CTLD_HERCULES self
-- @param Wrapper.Group#GROUP Cargo_Drop_initiator
-- @param Core.Point#POINT_VEC3 Cargo_Drop_Position
-- @param Core.Point#COORDINATE Cargo_Drop_Position
-- @param #string Cargo_Type_name
-- @param #number CargoHeading
-- @param #number Cargo_Country
@@ -7722,7 +7780,7 @@ end
--- [Internal] Function to spawn a group
-- @param #CTLD_HERCULES self
-- @param Wrapper.Group#GROUP Cargo_Drop_initiator
-- @param Core.Point#POINT_VEC3 Cargo_Drop_Position
-- @param Core.Point#COORDINATE Cargo_Drop_Position
-- @param #string Cargo_Type_name
-- @param #number CargoHeading
-- @param #number Cargo_Country
@@ -7746,7 +7804,7 @@ end
--- [Internal] Function to spawn static cargo
-- @param #CTLD_HERCULES self
-- @param Wrapper.Group#GROUP Cargo_Drop_initiator
-- @param Core.Point#POINT_VEC3 Cargo_Drop_Position
-- @param Core.Point#COORDINATE Cargo_Drop_Position
-- @param #string Cargo_Type_name
-- @param #number CargoHeading
-- @param #boolean dead
@@ -7768,7 +7826,7 @@ end
--- [Internal] Function to spawn cargo by type at position
-- @param #CTLD_HERCULES self
-- @param #string Cargo_Type_name
-- @param Core.Point#POINT_VEC3 Cargo_Drop_Position
-- @param Core.Point#COORDINATE Cargo_Drop_Position
-- @return #CTLD_HERCULES self
function CTLD_HERCULES:Cargo_SpawnDroppedAsCargo(_name, _pos)
local theCargo = self.CTLD:_FindCratesCargoObject(_name) -- #CTLD_CARGO

View File

@@ -62,6 +62,7 @@
-- @field #number repeatsonfailure
-- @field Core.Set#SET_ZONE GoZoneSet
-- @field Core.Set#SET_ZONE NoGoZoneSet
-- @field Core.Set#SET_ZONE ConflictZoneSet
-- @field #boolean Monitor
-- @field #boolean TankerInvisible
-- @field #number CapFormation
@@ -102,6 +103,11 @@
-- Next put a late activated template group for your CAP/GCI Squadron on the map. Last, put a zone on the map for the CAP operations, let's name it "Blue Zone 1". Size of the zone plays no role.
-- Put an EW radar system on the map and name it aptly, like "Blue EWR".
--
-- ### Zones
--
-- For our example, you create a RED and a BLUE border, as a closed polygonal zone representing the borderlines. You can also have conflict zone, where - for our example - BLUE will attack
-- RED planes, despite being on RED territory. Think of a no-fly zone or an limited area of engagement. Conflict zones take precedence over borders, i.e. they can overlap all borders.
--
-- ### Code it
--
-- -- Set up a basic system for the blue side, we'll reside on Kutaisi, and use GROUP objects with "Blue EWR" in the name as EW Radar Systems.
@@ -114,10 +120,10 @@
-- mywing:AddSquadron("Blue Sq1 M2000c","CAP Kutaisi",AIRBASE.Caucasus.Kutaisi,20,AI.Skill.GOOD,102,"ec1.5_Vendee_Jeanne_clean")
--
-- -- Add a couple of zones
-- -- We'll defend our border
-- -- We'll defend our own border
-- mywing:AddAcceptZone(ZONE_POLYGON:New( "Blue Border", GROUP:FindByName( "Blue Border" ) ))
-- -- We'll attack intruders also here
-- mywing:AddAcceptZone(ZONE_POLYGON:New("Red Defense Zone", GROUP:FindByName( "Red Defense Zone" )))
-- -- We'll attack intruders also here - conflictzones can overlap borders(!) - limited zone of engagement
-- mywing:AddConflictZone(ZONE_POLYGON:New("Red Defense Zone", GROUP:FindByName( "Red Defense Zone" )))
-- -- We'll leave the reds alone on their turf
-- mywing:AddRejectZone(ZONE_POLYGON:New( "Red Border", GROUP:FindByName( "Red Border" ) ))
--
@@ -125,10 +131,10 @@
-- -- Set up borders on map
-- local BlueBorder = ZONE_POLYGON:New( "Blue Border", GROUP:FindByName( "Blue Border" ) )
-- BlueBorder:DrawZone(-1,{0,0,1},1,FillColor,FillAlpha,1,true)
-- local BlueNoGoZone = ZONE_POLYGON:New("Red Defense Zone", GROUP:FindByName( "Red Defense Zone" ))
-- BlueNoGoZone:DrawZone(-1,{1,1,0},1,FillColor,FillAlpha,2,true)
-- local BlueNoGoZone2 = ZONE_POLYGON:New( "Red Border", GROUP:FindByName( "Red Border" ) )
-- BlueNoGoZone2:DrawZone(-1,{1,0,0},1,FillColor,FillAlpha,4,true)
-- local ConflictZone = ZONE_POLYGON:New("Red Defense Zone", GROUP:FindByName( "Red Defense Zone" ))
-- ConflictZone:DrawZone(-1,{1,1,0},1,FillColor,FillAlpha,2,true)
-- local BlueNoGoZone = ZONE_POLYGON:New( "Red Border", GROUP:FindByName( "Red Border" ) )
-- BlueNoGoZone:DrawZone(-1,{1,0,0},1,FillColor,FillAlpha,4,true)
--
-- ### Add a second airwing with squads and own CAP point (optional)
--
@@ -210,6 +216,7 @@ EASYGCICAP = {
repeatsonfailure = 3,
GoZoneSet = nil,
NoGoZoneSet = nil,
ConflictZoneSet = nil,
Monitor = false,
TankerInvisible = true,
CapFormation = nil,
@@ -252,7 +259,7 @@ EASYGCICAP = {
--- EASYGCICAP class version.
-- @field #string version
EASYGCICAP.version="0.1.17"
EASYGCICAP.version="0.1.18"
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO list
@@ -287,6 +294,7 @@ function EASYGCICAP:New(Alias, AirbaseName, Coalition, EWRName)
self.airbase = AIRBASE:FindByName(self.airbasename)
self.GoZoneSet = SET_ZONE:New()
self.NoGoZoneSet = SET_ZONE:New()
self.ConflictZoneSet = SET_ZONE:New()
self.resurrection = 900
self.capspeed = 300
self.capalt = 25000
@@ -1113,7 +1121,7 @@ end
-- @param Core.Zone#ZONE_BASE Zone
-- @return #EASYGCICAP self
function EASYGCICAP:AddAcceptZone(Zone)
self:T(self.lid.."AddAcceptZone0")
self:T(self.lid.."AddAcceptZone")
self.GoZoneSet:AddZone(Zone)
return self
end
@@ -1128,6 +1136,18 @@ function EASYGCICAP:AddRejectZone(Zone)
return self
end
--- Add a zone to the conflict zones set.
-- @param #EASYGCICAP self
-- @param Core.Zone#ZONE_BASE Zone
-- @return #EASYGCICAP self
function EASYGCICAP:AddConflictZone(Zone)
self:T(self.lid.."AddConflictZone")
self.ConflictZoneSet:AddZone(Zone)
self.GoZoneSet:AddZone(Zone)
return self
end
--- (Internal) Try to assign the intercept to a FlightGroup already in air and ready.
-- @param #EASYGCICAP self
-- @param #table ReadyFlightGroups ReadyFlightGroups
@@ -1193,6 +1213,7 @@ function EASYGCICAP:_AssignIntercept(Cluster)
local ctlpts = self.ManagedCP
local MaxAliveMissions = self.MaxAliveMissions --* self.capgrouping
local nogozoneset = self.NoGoZoneSet
local conflictzoneset = self.ConflictZoneSet
local ReadyFlightGroups = self.ReadyFlightGroups
-- Aircraft?
@@ -1271,18 +1292,22 @@ function EASYGCICAP:_AssignIntercept(Cluster)
if nogozoneset:Count() > 0 then
InterceptAuftrag:AddConditionSuccess(
function(group,zoneset)
function(group,zoneset,conflictset)
local success = false
if group and group:IsAlive() then
local coord = group:GetCoordinate()
if coord and zoneset:IsCoordinateInZone(coord) then
if coord and zoneset:Count() > 0 and zoneset:IsCoordinateInZone(coord) then
success = true
end
if coord and conflictset:Count() > 0 and conflictset:IsCoordinateInZone(coord) then
success = false
end
end
return success
end,
contact.group,
nogozoneset
nogozoneset,
conflictzoneset
)
end
@@ -1316,6 +1341,7 @@ function EASYGCICAP:_StartIntel()
BlueIntel:SetForgetTime(300)
BlueIntel:SetAcceptZones(self.GoZoneSet)
BlueIntel:SetRejectZones(self.NoGoZoneSet)
BlueIntel:SetConflictZones(self.ConflictZoneSet)
BlueIntel:SetVerbosity(0)
BlueIntel:Start()

File diff suppressed because it is too large Load Diff

View File

@@ -445,6 +445,7 @@ OPSGROUP.TaskType={
-- @field Wrapper.Marker#MARKER marker Marker on the F10 map.
-- @field #string formation Ground formation. Similar to action but on/off road.
-- @field #number missionUID Mission UID (Auftragsnr) this waypoint belongs to.
-- @field Navigation.FlightPlan#FLIGHTPLAN flightplan Flightplan this waypoint belongs to.
--- Cargo Carrier status.
-- @type OPSGROUP.CarrierStatus
@@ -573,6 +574,11 @@ function OPSGROUP:New(group)
-- Set DCS group and controller.
self.dcsgroup=self:GetDCSGroup()
if not self.dcsgroup then
return
end
self.controller=self.dcsgroup:getController()
-- Category.
@@ -9045,7 +9051,7 @@ function OPSGROUP:AddWeightCargo(UnitName, Weight)
self:T(self.lid..string.format("%s: Adding %.1f kg cargo weight. New cargo weight=%.1f kg", UnitName, Weight, element.weightCargo))
-- For airborne units, we set the weight in game.
if self.isFlightgroup then
if self.isFlightgroup and element.unit and element.unit:IsAlive() then -- #2272 trying to deduct cargo weight from possibly dead units
trigger.action.setUnitInternalCargo(element.name, element.weightCargo) --https://wiki.hoggitworld.com/view/DCS_func_setUnitInternalCargo
end
@@ -11349,9 +11355,9 @@ function OPSGROUP:_SimpleTaskFunction(Function, uid)
return DCSTask
end
--- Enhance waypoint table.
--- Enhanced waypoint table.
-- @param #OPSGROUP self
-- @param #OPSGROUP.Waypoint Waypoint data.
-- @param #OPSGROUP.Waypoint waypoint Waypoint data.
-- @return #OPSGROUP.Waypoint Modified waypoint data.
function OPSGROUP:_CreateWaypoint(waypoint)
@@ -12779,7 +12785,7 @@ function OPSGROUP:_UpdatePosition()
self.positionLast=self.position or self:GetVec3()
self.headingLast=self.heading or self:GetHeading()
self.orientXLast=self.orientX or self:GetOrientationX()
self.velocityLast=self.velocity or self.group:GetVelocityMPS()
self.velocityLast=self.velocity or self.group:GetVelocityMPS()
-- Current state.
self.position=self:GetVec3()
@@ -13607,20 +13613,24 @@ end
-- @return Core.Point#COORDINATE The coordinate of the object.
function OPSGROUP:_CoordinateFromObject(Object)
env.info("FF coordfrom object")
if Object then
if Object:IsInstanceOf("COORDINATE") then
if VECTOR._IsVector(Object) then
env.info("FF VECTOR")
return Object:GetCoordinate()
elseif Object:IsInstanceOf("COORDINATE") then
return Object
else
if Object:IsInstanceOf("POSITIONABLE") or Object:IsInstanceOf("ZONE_BASE") then
self:T(self.lid.."WARNING: Coordinate is not a COORDINATE but a POSITIONABLE or ZONE. Trying to get coordinate")
self:E(self.lid.."WARNING: Coordinate is not a COORDINATE but a POSITIONABLE or ZONE. Trying to get coordinate")
local coord=Object:GetCoordinate()
return coord
else
self:T(self.lid.."ERROR: Coordinate is neither a COORDINATE nor any POSITIONABLE or ZONE!")
self:E(self.lid.."ERROR: Coordinate is neither a COORDINATE nor any POSITIONABLE or ZONE!")
end
end
else
self:T(self.lid.."ERROR: Object passed is nil!")
self:E(self.lid.."ERROR: Object passed is nil!")
end
return nil

View File

@@ -380,7 +380,8 @@ function RADIOQUEUE:Broadcast(transmission)
self:T(self.lid..string.format("Broadcasting from aircraft %s", sender:GetName()))
if not self.senderinit then
--if not self.senderinit then
-- TODO Seems to be a DCS bug - if I explode ANY unit in a group the BC assignment gets lost
-- Command to set the Frequency for the transmission.
local commandFrequency={
@@ -394,7 +395,7 @@ function RADIOQUEUE:Broadcast(transmission)
sender:SetCommand(commandFrequency)
self.senderinit=true
end
--end
-- Set subtitle only if duration>0 sec.
local subtitle=nil

View File

@@ -1331,6 +1331,12 @@ ENUMS.Storage.weapons.OH58.Smk_Grenade_Yellow = {4,5,9,491}
-- Apache
ENUMS.Storage.weapons.AH64D.AN_APG78 = {4,15,44,2114}
ENUMS.Storage.weapons.AH64D.Internal_Aux_FuelTank = {1,3,43,1700}
-- Other - but cannot set or track those. Harrier stuff?
ENUMS.Storage.weapons.droptanks.FuelTank_610gal = {1,3,43,10}
ENUMS.Storage.weapons.droptanks.FuelTank_370gal = {1,3,43,11}
ENUMS.Storage.weapons.containers.AV8BNA_GAU_12_AP_M79 = {4,15,46,824}
ENUMS.Storage.weapons.containers.AV8BNA_GAU_12_HE_M792 = {4,15,46,825}
ENUMS.Storage.weapons.containers.AV8BNA_GAU_12_SAPHEI_T = {4,15,46,300}
---
-- @type ENUMS.FARPType

View File

@@ -58,6 +58,7 @@ BIGSMOKEPRESET = {
-- @field #string Kola Kola map.
-- @field #string Afghanistan Afghanistan map
-- @field #string Iraq Iraq map
-- @field #string GermanyCW Germany Cold War map
DCSMAP = {
Caucasus="Caucasus",
NTTR="Nevada",
@@ -70,7 +71,8 @@ DCSMAP = {
Sinai="SinaiMap",
Kola="Kola",
Afghanistan="Afghanistan",
Iraq="Iraq"
Iraq="Iraq",
GermanyCW="GermanyCW",
}
@@ -349,7 +351,7 @@ end
-- @return #string Table as a string.
UTILS.OneLineSerialize = function( tbl ) -- serialization of a table all on a single line, no comments, made to replace old get_table_string function
lookup_table = {}
local lookup_table = {}
local function _Serialize( tbl )
@@ -795,6 +797,33 @@ UTILS.kg2lbs = function( kg )
return kg * 2.20462
end
--- Convert latitude or longitude from degrees, minutes, seconds (DMS) to decimal degrees (DD).
-- @param #number Degrees Degrees in grad.
-- @param #number Minutes Minutes.
-- @param #number Seconds Seconds.
-- @return #number Latitude or Longitude in decimal degrees.
UTILS.LLDMSToDD = function(Degrees, Minutes, Seconds)
local dd=tonumber(Degrees or 0) + tonumber(Minutes or 0)/60 + tonumber(Seconds or 0)/3600
return dd
end
--- Convert latitude or longitude from degrees, minutes, seconds (DMS) given in text form to decimal degrees (DD).
-- @param #string LatOrLongString Latitude or longitude passed as ttring in format `DD°MM'SS.SS"`.
-- @return #number Latitude or Longitude in decimal degrees.
UTILS.LLDMSstringToDD = function(LatOrLongString)
local hem=string.match(LatOrLongString, "(%a)")
local Degrees=string.match(LatOrLongString, "(%d+)°")
local Minutes=string.match(LatOrLongString, "(%d+)'")
local Seconds=string.match(LatOrLongString, "([%d\.]+)\"")
local dd=UTILS.LLDMSToDD(Degrees, Minutes, Seconds)
return dd
end
--[[acc:
in DM: decimal point of minutes.
In DMS: decimal point of seconds.
@@ -1515,6 +1544,22 @@ function UTILS.Vec2Add(a, b)
return {x=a.x+b.x, y=a.y+b.y}
end
--- Multiply 2D vector by a scalar value.
-- @param DCS#Vec2 a Vector in 2D with x, y components.
-- @param #number c Scalar value.
-- @return DCS#Vec2 Vector
function UTILS.Vec2Mult(a, c)
return {x=c*a.x, y=c*a.y}
end
--- Multiply 3D vector by a scalar value.
-- @param DCS#Vec3 a Vector in 3D with x, y, z components.
-- @param #number c Scalar value.
-- @return DCS#Vec3 Vector
function UTILS.VecMult(a, c)
return {x=c*a.x, y=c*a.y, z=c*a.z}
end
--- Calculate the angle between two 3D vectors.
-- @param DCS#Vec3 a Vector in 3D with x, y, z components.
-- @param DCS#Vec3 b Vector in 3D with x, y, z components.
@@ -1535,6 +1580,24 @@ function UTILS.VecAngle(a, b)
return math.deg(alpha)
end
--- Calculate the angle between two 3D vectors.
-- @param DCS#Vec3 a Vector in 3D with x, y, z components.
-- @param DCS#Vec3 b Vector in 3D with x, y, z components.
-- @return #number Angle alpha between and b in degrees.
function UTILS.VecAngleSigned(a, b)
local a=UTILS.VecSubstract(s1.p2.vec3, s1.p1.vec3)
local b=UTILS.VecSubstract(s2.p2.vec3, s2.p1.vec3)
local h1=UTILS.VecHdg(a)
local h2=UTILS.VecHdg(b)
local angle=h1-h2 --UTILS.VecAngle(a, b)
end
--- Calculate "heading" of a 3D vector in the X-Z plane.
-- @param DCS#Vec3 a Vector in 3D with x, y, z components.
-- @return #number Heading in degrees in [0,360).
@@ -1557,6 +1620,20 @@ function UTILS.Vec2Hdg(a)
return h
end
--- Calculate the difference between two "heading", i.e. angles in [0,360) deg.
-- @param DCS#Vec3 a Vector a.
-- @param DCS#Vec3 a Vector b.
-- @return #number Heading difference in degrees.
function UTILS.VecHdgDiff(a, b)
local ha=math.deg(math.atan2(a.z, a.x))
local hb=math.deg(math.atan2(b.z, b.x))
local angle=ha-hb
return angle
end
--- Calculate the difference between two "heading", i.e. angles in [0,360) deg.
-- @param #number h1 Heading one.
-- @param #number h2 Heading two.
@@ -1759,7 +1836,9 @@ end
-- * Sinai +4.8 (East)
-- * Kola +15 (East) - note there is a lot of deviation across the map (-1° to +24°), as we are close to the North pole
-- * Afghanistan +3 (East) - actually +3.6 (NW) to +2.3 (SE)
-- @param #string map (Optional) Map for which the declination is returned. Default is from env.mission.theatre
-- * Iraq +4.4 (East)
-- * Germany Cold War +0.1 (East) - near Fulda
-- @param #string map (Optional) Map for which the declination is returned. Default is from `env.mission.theatre`.
-- @return #number Declination in degrees.
function UTILS.GetMagneticDeclination(map)
@@ -1791,6 +1870,8 @@ function UTILS.GetMagneticDeclination(map)
declination=3
elseif map==DCSMAP.Iraq then
declination=4.4
elseif map==DCSMAP.GermanyCW then
declination=0.1
else
declination=0
end
@@ -2024,6 +2105,10 @@ function UTILS.GMTToLocalTimeDifference()
return 3 -- Currently map is +2 but should be +3 (DCS bug?)
elseif theatre==DCSMAP.Afghanistan then
return 4.5 -- UTC +4:30
elseif theatre==DCSMAP.Iraq then
return 3.0 -- UTC +3
elseif theatre==DCSMAP.GermanyCW then
return 1.0 -- UTC +1 Central European Time (not summer time)
else
BASE:E(string.format("ERROR: Unknown Map %s in UTILS.GMTToLocal function. Returning 0", tostring(theatre)))
return 0
@@ -2329,8 +2414,12 @@ function UTILS.IsLoadingDoorOpen( unit_name )
BASE:T(unit_name .. " rear cargo door is open")
return true
end
return false
-- ground
local UnitDescriptor = unit:getDesc()
local IsGroundResult = (UnitDescriptor.category == Unit.Category.GROUND_UNIT)
return IsGroundResult
end -- nil
@@ -3188,6 +3277,62 @@ function UTILS.BearingToCardinal(Heading)
end
end
--- Adjust given heading so that is is in [0, 360).
-- @param #number Heading The heading in degrees.
-- @return #number Adjust heading in [0,360).
function UTILS.AdjustHeading360(Heading)
if Heading>=360 then
Heading=Heading-360
elseif Heading<0 then
Heading=Heading+360
end
return Heading
end
--- Transfroms a given 2D vector 3D.
-- This takes care of ED's different conventions for 2D and 3D coordinate systems.
-- @param DCS#Vec2 Vec Vector to be transformed. Can be any table/object that has at least x and y and optionally a z component.
-- @param #boolean OnSurface If `true`, new vector's y-component (alt) is at surface height. Otherwise, it is set to 0.
-- @return DCS#Vec3 Vector in 3D with x-, y- and z-components.
function UTILS.VecTo3D(Vec, OnSurface)
local vec={x=0, y=0, z=0} --DCS#Vec3
if Vec.z then
-- Vector is 3D already ==> Nothing to do.
vec.x=Vec.x
vec.y=Vec.y
vec.z=Vec.z
else
-- Vector is 2D
vec.x=Vec.x
vec.y=OnSurface and land.getHeight({x=Vec.x, y=Vec.y}) or 0
vec.z=Vec.y
end
return vec
end
--- Transfroms a given 3D (or 2D) vector to 2D.
-- This takes care of ED's different conventions for 2D and 3D coordinate systems.
-- @param DCS#Vec3 Vec Vector to be transformed. Can be any table/object that has at least x and y and optionally a z component.
-- @return DCS#Vec2 Vector in 2D with x- and y-components.
function UTILS.VecTo2D(Vec)
local vec={x=0, y=0} --DCS#Vec2
if Vec.z then
vec.x=Vec.x
vec.y=Vec.z
else
vec.x=Vec.x
vec.y=Vec.y
end
return vec
end
--- Create a BRAA NATO call string BRAA between two GROUP objects
-- @param Wrapper.Group#GROUP FromGrp GROUP object
-- @param Wrapper.Group#GROUP ToGrp GROUP object

View File

@@ -31,6 +31,7 @@
-- @field #AIRBASE.Runway runwayLanding Runway used for landing.
-- @field #AIRBASE.Runway runwayTakeoff Runway used for takeoff.
-- @field Wrapper.Storage#STORAGE storage The DCS warehouse storage.
-- @field #table taxiways Taxiways stored as PATHLINEs.
-- @extends Wrapper.Positionable#POSITIONABLE
--- Wrapper class to handle the DCS Airbase objects:
@@ -78,6 +79,7 @@ AIRBASE = {
[Airbase.Category.SHIP] = "Ship",
},
activerwyno = nil,
taxiways = {},
}
--- Enumeration to identify the airbases in the Caucasus region.
@@ -909,6 +911,413 @@ AIRBASE.Iraq = {
["K1_Base"] = "K1 Base",
}
--- Airbases of the Germany Cold War map
-- * AIRBASE.GermanyCW.Airracing_Frankfurt
-- * AIRBASE.GermanyCW.Airracing_Koblenz
-- * AIRBASE.GermanyCW.Airracing_Luebeck
-- * AIRBASE.GermanyCW.Allstedt
-- * AIRBASE.GermanyCW.Alt_Daber
-- * AIRBASE.GermanyCW.Altes_Lager
-- * AIRBASE.GermanyCW.Bad_Duerkheim
-- * AIRBASE.GermanyCW.Barth
-- * AIRBASE.GermanyCW.Bienenfarm
-- * AIRBASE.GermanyCW.Bindersleben
-- * AIRBASE.GermanyCW.Bitburg
-- * AIRBASE.GermanyCW.Braunschweig
-- * AIRBASE.GermanyCW.Bremen
-- * AIRBASE.GermanyCW.Briest
-- * AIRBASE.GermanyCW.Buechel
-- * AIRBASE.GermanyCW.Bueckeburg
-- * AIRBASE.GermanyCW.Celle
-- * AIRBASE.GermanyCW.Cochstedt
-- * AIRBASE.GermanyCW.Damgarten
-- * AIRBASE.GermanyCW.Dedelow
-- * AIRBASE.GermanyCW.Dessau
-- * AIRBASE.GermanyCW.Fassberg
-- * AIRBASE.GermanyCW.Finow
-- * AIRBASE.GermanyCW.Frankfurt
-- * AIRBASE.GermanyCW.Fritzlar
-- * AIRBASE.GermanyCW.Fulda
-- * AIRBASE.GermanyCW.Gardelegen
-- * AIRBASE.GermanyCW.Gatow
-- * AIRBASE.GermanyCW.Gelnhausen
-- * AIRBASE.GermanyCW.Giebelstadt
-- * AIRBASE.GermanyCW.Glindbruchkippe
-- * AIRBASE.GermanyCW.Gross_Doelln
-- * AIRBASE.GermanyCW.Gross_Mohrdorf
-- * AIRBASE.GermanyCW.Grosse_Wiese
-- * AIRBASE.GermanyCW.Gaerz
-- * AIRBASE.GermanyCW.Guetersloh
-- * AIRBASE.GermanyCW.H_FRG_01
-- * AIRBASE.GermanyCW.H_FRG_02
-- * AIRBASE.GermanyCW.H_FRG_03
-- * AIRBASE.GermanyCW.H_FRG_04
-- * AIRBASE.GermanyCW.H_FRG_05
-- * AIRBASE.GermanyCW.H_FRG_06
-- * AIRBASE.GermanyCW.H_FRG_07
-- * AIRBASE.GermanyCW.H_FRG_08
-- * AIRBASE.GermanyCW.H_FRG_09
-- * AIRBASE.GermanyCW.H_FRG_10
-- * AIRBASE.GermanyCW.H_FRG_11
-- * AIRBASE.GermanyCW.H_FRG_12
-- * AIRBASE.GermanyCW.H_FRG_13
-- * AIRBASE.GermanyCW.H_FRG_14
-- * AIRBASE.GermanyCW.H_FRG_15
-- * AIRBASE.GermanyCW.H_FRG_16
-- * AIRBASE.GermanyCW.H_FRG_17
-- * AIRBASE.GermanyCW.H_FRG_18
-- * AIRBASE.GermanyCW.H_FRG_19
-- * AIRBASE.GermanyCW.H_FRG_20
-- * AIRBASE.GermanyCW.H_FRG_21
-- * AIRBASE.GermanyCW.H_FRG_23
-- * AIRBASE.GermanyCW.H_FRG_25
-- * AIRBASE.GermanyCW.H_FRG_27
-- * AIRBASE.GermanyCW.H_FRG_30
-- * AIRBASE.GermanyCW.H_FRG_31
-- * AIRBASE.GermanyCW.H_FRG_32
-- * AIRBASE.GermanyCW.H_FRG_34
-- * AIRBASE.GermanyCW.H_FRG_38
-- * AIRBASE.GermanyCW.H_FRG_39
-- * AIRBASE.GermanyCW.H_FRG_40
-- * AIRBASE.GermanyCW.H_FRG_41
-- * AIRBASE.GermanyCW.H_FRG_42
-- * AIRBASE.GermanyCW.H_FRG_43
-- * AIRBASE.GermanyCW.H_FRG_44
-- * AIRBASE.GermanyCW.H_FRG_45
-- * AIRBASE.GermanyCW.H_FRG_46
-- * AIRBASE.GermanyCW.H_FRG_47
-- * AIRBASE.GermanyCW.H_FRG_48
-- * AIRBASE.GermanyCW.H_FRG_49
-- * AIRBASE.GermanyCW.H_FRG_50
-- * AIRBASE.GermanyCW.H_FRG_51
-- * AIRBASE.GermanyCW.H_GDR_01
-- * AIRBASE.GermanyCW.H_GDR_02
-- * AIRBASE.GermanyCW.H_GDR_03
-- * AIRBASE.GermanyCW.H_GDR_04
-- * AIRBASE.GermanyCW.H_GDR_05
-- * AIRBASE.GermanyCW.H_GDR_06
-- * AIRBASE.GermanyCW.H_GDR_07
-- * AIRBASE.GermanyCW.H_GDR_08
-- * AIRBASE.GermanyCW.H_GDR_09
-- * AIRBASE.GermanyCW.H_GDR_10
-- * AIRBASE.GermanyCW.H_GDR_11
-- * AIRBASE.GermanyCW.H_GDR_12
-- * AIRBASE.GermanyCW.H_GDR_13
-- * AIRBASE.GermanyCW.H_GDR_14
-- * AIRBASE.GermanyCW.H_GDR_15
-- * AIRBASE.GermanyCW.H_GDR_16
-- * AIRBASE.GermanyCW.H_GDR_17
-- * AIRBASE.GermanyCW.H_GDR_18
-- * AIRBASE.GermanyCW.H_GDR_19
-- * AIRBASE.GermanyCW.H_GDR_21
-- * AIRBASE.GermanyCW.H_GDR_22
-- * AIRBASE.GermanyCW.H_GDR_24
-- * AIRBASE.GermanyCW.H_GDR_25
-- * AIRBASE.GermanyCW.H_GDR_26
-- * AIRBASE.GermanyCW.H_GDR_30
-- * AIRBASE.GermanyCW.H_GDR_31
-- * AIRBASE.GermanyCW.H_GDR_32
-- * AIRBASE.GermanyCW.H_GDR_33
-- * AIRBASE.GermanyCW.H_Med_FRG_02
-- * AIRBASE.GermanyCW.H_Med_FRG_04
-- * AIRBASE.GermanyCW.H_Med_FRG_06
-- * AIRBASE.GermanyCW.H_Med_FRG_09
-- * AIRBASE.GermanyCW.H_Med_FRG_11
-- * AIRBASE.GermanyCW.H_Med_FRG_12
-- * AIRBASE.GermanyCW.H_Med_FRG_13
-- * AIRBASE.GermanyCW.H_Med_FRG_14
-- * AIRBASE.GermanyCW.H_Med_FRG_15
-- * AIRBASE.GermanyCW.H_Med_FRG_16
-- * AIRBASE.GermanyCW.H_Med_FRG_17
-- * AIRBASE.GermanyCW.H_Med_FRG_21
-- * AIRBASE.GermanyCW.H_Med_FRG_24
-- * AIRBASE.GermanyCW.H_Med_FRG_26
-- * AIRBASE.GermanyCW.H_Med_FRG_27
-- * AIRBASE.GermanyCW.H_Med_FRG_29
-- * AIRBASE.GermanyCW.H_Med_GDR_01
-- * AIRBASE.GermanyCW.H_Med_GDR_02
-- * AIRBASE.GermanyCW.H_Med_GDR_03
-- * AIRBASE.GermanyCW.H_Med_GDR_08
-- * AIRBASE.GermanyCW.H_Med_GDR_09
-- * AIRBASE.GermanyCW.H_Med_GDR_10
-- * AIRBASE.GermanyCW.H_Med_GDR_11
-- * AIRBASE.GermanyCW.H_Med_GDR_12
-- * AIRBASE.GermanyCW.H_Med_GDR_13
-- * AIRBASE.GermanyCW.H_Med_GDR_14
-- * AIRBASE.GermanyCW.H_Med_GDR_16
-- * AIRBASE.GermanyCW.H_Radar_FRG_02
-- * AIRBASE.GermanyCW.H_Radar_GDR_01
-- * AIRBASE.GermanyCW.H_Radar_GDR_02
-- * AIRBASE.GermanyCW.H_Radar_GDR_03
-- * AIRBASE.GermanyCW.H_Radar_GDR_04
-- * AIRBASE.GermanyCW.H_Radar_GDR_05
-- * AIRBASE.GermanyCW.H_Radar_GDR_06
-- * AIRBASE.GermanyCW.H_Radar_GDR_07
-- * AIRBASE.GermanyCW.H_Radar_GDR_08
-- * AIRBASE.GermanyCW.H_Radar_GDR_09
-- * AIRBASE.GermanyCW.Hahn
-- * AIRBASE.GermanyCW.Haina
-- * AIRBASE.GermanyCW.Hamburg
-- * AIRBASE.GermanyCW.Hamburg_Finkenwerder
-- * AIRBASE.GermanyCW.Hannover
-- * AIRBASE.GermanyCW.Hasselfelde
-- * AIRBASE.GermanyCW.Herrenteich
-- * AIRBASE.GermanyCW.Hildesheim
-- * AIRBASE.GermanyCW.Hockenheim
-- * AIRBASE.GermanyCW.Holzdorf
-- * AIRBASE.GermanyCW.Kammermark
-- * AIRBASE.GermanyCW.Koethen
-- * AIRBASE.GermanyCW.Laage
-- * AIRBASE.GermanyCW.Langenselbold
-- * AIRBASE.GermanyCW.Leipzig_Halle
-- * AIRBASE.GermanyCW.Leipzig_Mockau
-- * AIRBASE.GermanyCW.Laerz
-- * AIRBASE.GermanyCW.Luebeck
-- * AIRBASE.GermanyCW.Lueneburg
-- * AIRBASE.GermanyCW.Mahlwinkel
-- * AIRBASE.GermanyCW.Mendig
-- * AIRBASE.GermanyCW.Merseburg
-- * AIRBASE.GermanyCW.Neubrandenburg
-- * AIRBASE.GermanyCW.Neuruppin
-- * AIRBASE.GermanyCW.Northeim
-- * AIRBASE.GermanyCW.Ober_Moerlen
-- * AIRBASE.GermanyCW.Obermehler_Schlotheim
-- * AIRBASE.GermanyCW.Parchim
-- * AIRBASE.GermanyCW.Peenemuende
-- * AIRBASE.GermanyCW.Pferdsfeld
-- * AIRBASE.GermanyCW.Pinnow
-- * AIRBASE.GermanyCW.Pottschutthoehe
-- * AIRBASE.GermanyCW.Ramstein
-- * AIRBASE.GermanyCW.Rinteln
-- * AIRBASE.GermanyCW.Schweinfurt
-- * AIRBASE.GermanyCW.Schoenefeld
-- * AIRBASE.GermanyCW.Sembach
-- * AIRBASE.GermanyCW.Spangdahlem
-- * AIRBASE.GermanyCW.Sperenberg
-- * AIRBASE.GermanyCW.Stendal
-- * AIRBASE.GermanyCW.Tegel
-- * AIRBASE.GermanyCW.Tempelhof
-- * AIRBASE.GermanyCW.Tutow
-- * AIRBASE.GermanyCW.Uelzen
-- * AIRBASE.GermanyCW.Uetersen
-- * AIRBASE.GermanyCW.Ummern
-- * AIRBASE.GermanyCW.Verden_Scharnhorst
-- * AIRBASE.GermanyCW.Walldorf
-- * AIRBASE.GermanyCW.Waren_Vielist
-- * AIRBASE.GermanyCW.Werneuchen
-- * AIRBASE.GermanyCW.Weser_Wuemme
-- * AIRBASE.GermanyCW.Wiesbaden
-- * AIRBASE.GermanyCW.Wismar
-- * AIRBASE.GermanyCW.Worms
-- * AIRBASE.GermanyCW.Wunstorf
-- * AIRBASE.GermanyCW.Zerbst
-- * AIRBASE.GermanyCW.Zweibruecken
--
-- @field GermanyCW
AIRBASE.GermanyCW = {
["Airracing_Frankfurt"] = "Airracing Frankfurt",
["Airracing_Koblenz"] = "Airracing Koblenz",
["Airracing_Luebeck"] = "Airracing Lubeck",
["Allstedt"] = "Allstedt",
["Alt_Daber"] = "Alt Daber",
["Altes_Lager"] = "Altes Lager",
["Bad_Duerkheim"] = "Bad Durkheim",
["Barth"] = "Barth",
["Bienenfarm"] = "Bienenfarm",
["Bindersleben"] = "Bindersleben",
["Bitburg"] = "Bitburg",
["Braunschweig"] = "Braunschweig",
["Bremen"] = "Bremen",
["Briest"] = "Briest",
["Buechel"] = "Buchel",
["Bueckeburg"] = "Buckeburg",
["Celle"] = "Celle",
["Cochstedt"] = "Cochstedt",
["Damgarten"] = "Damgarten",
["Dedelow"] = "Dedelow",
["Dessau"] = "Dessau",
["Fassberg"] = "Fassberg",
["Finow"] = "Finow",
["Frankfurt"] = "Frankfurt",
["Fritzlar"] = "Fritzlar",
["Fulda"] = "Fulda",
["Gardelegen"] = "Gardelegen",
["Gatow"] = "Gatow",
["Gelnhausen"] = "Gelnhausen",
["Giebelstadt"] = "Giebelstadt",
["Glindbruchkippe_"] = "Glindbruchkippe ",
["Gross_Doelln"] = "Gross Dolln",
["Gross_Mohrdorf"] = "Gross Mohrdorf",
["Grosse_Wiese"] = "Grosse Wiese",
["Gaerz"] = "Garz",
["Guetersloh"] = "Gutersloh",
["H_FRG_01"] = "H FRG 01",
["H_FRG_02"] = "H FRG 02",
["H_FRG_03"] = "H FRG 03",
["H_FRG_04"] = "H FRG 04",
["H_FRG_05"] = "H FRG 05",
["H_FRG_06"] = "H FRG 06",
["H_FRG_07"] = "H FRG 07",
["H_FRG_08"] = "H FRG 08",
["H_FRG_09"] = "H FRG 09",
["H_FRG_10"] = "H FRG 10",
["H_FRG_11"] = "H FRG 11",
["H_FRG_12"] = "H FRG 12",
["H_FRG_13"] = "H FRG 13",
["H_FRG_14"] = "H FRG 14",
["H_FRG_15"] = "H FRG 15",
["H_FRG_16"] = "H FRG 16",
["H_FRG_17"] = "H FRG 17",
["H_FRG_18"] = "H FRG 18",
["H_FRG_19"] = "H FRG 19",
["H_FRG_20"] = "H FRG 20",
["H_FRG_21"] = "H FRG 21",
["H_FRG_23"] = "H FRG 23",
["H_FRG_25"] = "H FRG 25",
["H_FRG_27"] = "H FRG 27",
["H_FRG_30"] = "H FRG 30",
["H_FRG_31"] = "H FRG 31",
["H_FRG_32"] = "H FRG 32",
["H_FRG_34"] = "H FRG 34",
["H_FRG_38"] = "H FRG 38",
["H_FRG_39"] = "H FRG 39",
["H_FRG_40"] = "H FRG 40",
["H_FRG_41"] = "H FRG 41",
["H_FRG_42"] = "H FRG 42",
["H_FRG_43"] = "H FRG 43",
["H_FRG_44"] = "H FRG 44",
["H_FRG_45"] = "H FRG 45",
["H_FRG_46"] = "H FRG 46",
["H_FRG_47"] = "H FRG 47",
["H_FRG_48"] = "H FRG 48",
["H_FRG_49"] = "H FRG 49",
["H_FRG_50"] = "H FRG 50",
["H_FRG_51"] = "H FRG 51",
["H_GDR_01"] = "H GDR 01",
["H_GDR_02"] = "H GDR 02",
["H_GDR_03"] = "H GDR 03",
["H_GDR_04"] = "H GDR 04",
["H_GDR_05"] = "H GDR 05",
["H_GDR_06"] = "H GDR 06",
["H_GDR_07"] = "H GDR 07",
["H_GDR_08"] = "H GDR 08",
["H_GDR_09"] = "H GDR 09",
["H_GDR_10"] = "H GDR 10",
["H_GDR_11"] = "H GDR 11",
["H_GDR_12"] = "H GDR 12",
["H_GDR_13"] = "H GDR 13",
["H_GDR_14"] = "H GDR 14",
["H_GDR_15"] = "H GDR 15",
["H_GDR_16"] = "H GDR 16",
["H_GDR_17"] = "H GDR 17",
["H_GDR_18"] = "H GDR 18",
["H_GDR_19"] = "H GDR 19",
["H_GDR_21"] = "H GDR 21",
["H_GDR_22"] = "H GDR 22",
["H_GDR_24"] = "H GDR 24",
["H_GDR_25"] = "H GDR 25",
["H_GDR_26"] = "H GDR 26",
["H_GDR_30"] = "H GDR 30",
["H_GDR_31"] = "H GDR 31",
["H_GDR_32"] = "H GDR 32",
["H_GDR_33"] = "H GDR 33",
["H_Med_FRG_02"] = "H Med FRG 02",
["H_Med_FRG_04"] = "H Med FRG 04",
["H_Med_FRG_06"] = "H Med FRG 06",
["H_Med_FRG_09"] = "H Med FRG 09",
["H_Med_FRG_11"] = "H Med FRG 11",
["H_Med_FRG_12"] = "H Med FRG 12",
["H_Med_FRG_13"] = "H Med FRG 13",
["H_Med_FRG_14"] = "H Med FRG 14",
["H_Med_FRG_15"] = "H Med FRG 15",
["H_Med_FRG_16"] = "H Med FRG 16",
["H_Med_FRG_17"] = "H Med FRG 17",
["H_Med_FRG_21"] = "H Med FRG 21",
["H_Med_FRG_24"] = "H Med FRG 24",
["H_Med_FRG_26"] = "H Med FRG 26",
["H_Med_FRG_27"] = "H Med FRG 27",
["H_Med_FRG_29"] = "H Med FRG 29",
["H_Med_GDR_01"] = "H Med GDR 01",
["H_Med_GDR_02"] = "H Med GDR 02",
["H_Med_GDR_03"] = "H Med GDR 03",
["H_Med_GDR_08"] = "H Med GDR 08",
["H_Med_GDR_09"] = "H Med GDR 09",
["H_Med_GDR_10"] = "H Med GDR 10",
["H_Med_GDR_11"] = "H Med GDR 11",
["H_Med_GDR_12"] = "H Med GDR 12",
["H_Med_GDR_13"] = "H Med GDR 13",
["H_Med_GDR_14"] = "H Med GDR 14",
["H_Med_GDR_16"] = "H Med GDR 16",
["H_Radar_FRG_02"] = "H Radar FRG 02",
["H_Radar_GDR_01"] = "H Radar GDR 01",
["H_Radar_GDR_02"] = "H Radar GDR 02",
["H_Radar_GDR_03"] = "H Radar GDR 03",
["H_Radar_GDR_04"] = "H Radar GDR 04",
["H_Radar_GDR_05"] = "H Radar GDR 05",
["H_Radar_GDR_06"] = "H Radar GDR 06",
["H_Radar_GDR_07"] = "H Radar GDR 07",
["H_Radar_GDR_08"] = "H Radar GDR 08",
["H_Radar_GDR_09"] = "H Radar GDR 09",
["Hahn"] = "Hahn",
["Haina"] = "Haina",
["Hamburg"] = "Hamburg",
["Hamburg_Finkenwerder"] = "Hamburg Finkenwerder",
["Hannover"] = "Hannover",
["Hasselfelde"] = "Hasselfelde",
["Herrenteich"] = "Herrenteich",
["Hildesheim"] = "Hildesheim",
["Hockenheim"] = "Hockenheim",
["Holzdorf"] = "Holzdorf",
["Kammermark"] = "Kammermark",
["Koethen"] = "Kothen",
["Laage"] = "Laage",
["Langenselbold"] = "Langenselbold",
["Leipzig_Halle"] = "Leipzig Halle",
["Leipzig_Mockau"] = "Leipzig Mockau",
["Laerz"] = "Larz",
["Luebeck"] = "Lubeck",
["Lueneburg"] = "Luneburg",
["Mahlwinkel"] = "Mahlwinkel",
["Mendig"] = "Mendig",
["Merseburg"] = "Merseburg",
["Neubrandenburg"] = "Neubrandenburg",
["Neuruppin"] = "Neuruppin",
["Northeim"] = "Northeim",
["Ober_Moerlen"] = "Ober-Morlen",
["Obermehler_Schlotheim"] = "Obermehler Schlotheim",
["Parchim"] = "Parchim",
["Peenemuende"] = "Peenemunde",
["Pferdsfeld"] = "Pferdsfeld",
["Pinnow"] = "Pinnow",
["Pottschutthoehe"] = "Pottschutthohe",
["Ramstein"] = "Ramstein",
["Rinteln"] = "Rinteln",
["Schweinfurt"] = "Schweinfurt",
["Schoenefeld"] = "Schonefeld",
["Sembach"] = "Sembach",
["Spangdahlem"] = "Spangdahlem",
["Sperenberg"] = "Sperenberg",
["Stendal"] = "Stendal",
["Tegel"] = "Tegel",
["Tempelhof"] = "Tempelhof",
["Tutow"] = "Tutow",
["Uelzen"] = "Uelzen",
["Uetersen"] = "Uetersen",
["Ummern"] = "Ummern",
["Verden_Scharnhorst"] = "Verden-Scharnhorst",
["Walldorf"] = "Walldorf",
["Waren_Vielist"] = "Waren Vielist",
["Werneuchen"] = "Werneuchen",
["Weser_Wuemme"] = "Weser Wumme",
["Wiesbaden"] = "Wiesbaden",
["Wismar"] = "Wismar",
["Worms"] = "Worms",
["Wunstorf"] = "Wunstorf",
["Zerbst"] = "Zerbst",
["Zweibruecken"] = "Zweibrucken",
}
--- AIRBASE.ParkingSpot ".Coordinate, ".TerminalID", ".TerminalType", ".TOAC", ".Free", ".TerminalID0", ".DistToRwy".
-- @type AIRBASE.ParkingSpot
-- @field Core.Point#COORDINATE Coordinate Coordinate of the parking spot.
@@ -975,6 +1384,32 @@ AIRBASE.SpotStatus = {
RESERVED="Reserved",
}
--- ICAO Codes.
-- @type AIRBASE.ICAO
AIRBASE.ICAO = {
UGTB=AIRBASE.Caucasus.Tbilisi_Lochini,
UGKO=AIRBASE.Caucasus.Kutaisi,
UG5X=AIRBASE.Caucasus.Kobuleti,
UG24=AIRBASE.Caucasus.Soganlug,
UG27=AIRBASE.Caucasus.Vaziani,
UGSS=AIRBASE.Caucasus.Sukhumi_Babushara,
UG23=AIRBASE.Caucasus.Gudauta,
URSS=AIRBASE.Caucasus.Sochi_Adler,
URMO=AIRBASE.Caucasus.Beslan,
URMN=AIRBASE.Caucasus.Nalchik,
XRMF=AIRBASE.Caucasus.Mozdok,
URMM=AIRBASE.Caucasus.Mineralnye_Vody,
URKH=AIRBASE.Caucasus.Maykop_Khanskaya,
URKK=AIRBASE.Caucasus.Krasnodar_Pashkovsky,
URKL=AIRBASE.Caucasus.Krasnodar_Center,
URKG=AIRBASE.Caucasus.Gelendzhik,
URKN=AIRBASE.Caucasus.Novorossiysk,
URKW=AIRBASE.Caucasus.Krymsk,
URKA=AIRBASE.Caucasus.Anapa_Vityazevo,
}
--- Runway data.
-- @type AIRBASE.Runway
-- @field #string name Runway name.
@@ -1152,14 +1587,47 @@ end
--- Find a AIRBASE in the _DATABASE using the name of an existing DCS Airbase.
-- @param #AIRBASE self
-- @param #string AirbaseName The Airbase Name.
-- @param #string AirbaseName The name of the airbase. Can also be the ICAO code or the airbase ID.
-- @return #AIRBASE self
function AIRBASE:FindByName( AirbaseName )
local AirbaseFound = _DATABASE:FindAirbase( AirbaseName )
if not AirbaseFound then
AirbaseFound=self:FindByICAO(AirbaseName)
end
if not AirbaseFound then
AirbaseFound=self:FindByID(AirbaseName)
end
return AirbaseFound
end
--- Find an AIRBASE in the _DATABASE using the [International Civil Aviation Organization](https://en.wikipedia.org/wiki/ICAO_airport_code) (ICAO) airport code.
-- The code consists of four characters. Typically, the first one or two letters of the ICAO code indicate the country and the remaining letters identify the airport.
--
-- **NOTE** that the ICAO code cannot be retrieved via the DCS API and has to be hard coded into the MOOSE code. Therefore, it is a rare occasion where
-- @param #AIRBASE self
-- @param #string AirbaseICAO The Airbase ICAO code.
-- @return #AIRBASE self
function AIRBASE:FindByICAO( AirbaseICAO )
if AirbaseICAO then
local name=AIRBASE.ICAO[AirbaseICAO]
env.info(string.format("FF ICAO=%s, Name=%s", tostring(AirbaseICAO), tostring(name)))
local Airbase=self:FindByName(name)
return Airbase
end
return nil
end
--- Find a AIRBASE in the _DATABASE by its ID.
-- @param #AIRBASE self
-- @param #number id Airbase ID.
@@ -1472,6 +1940,129 @@ function AIRBASE:IsShip()
return self.isShip
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Taxi ways
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- Add a taxiway from a given PATHLINE.
-- @param #AIRBASE self
-- @param Core.Pathline#PATHLINE TaxiPathline Pathline of the taxi way or name of pathline as #string.
-- @param #string Name Name of the taxi way, *e.g.* "Alpha", or "Alpha-Kilo". Default is name of pathline.
-- @return #AIRBASE self
function AIRBASE:AddTaxiway(TaxiPathline, Name)
-- If passed as string, get pathline.
if type(TaxiPathline)=="string" then
TaxiPathline=PATHLINE:FindByName(TaxiPathline)
end
-- Set name.
Name=Name or TaxiPathline:GetName()
-- Create a deep copy.
local taxiway=UTILS.DeepCopy(TaxiPathline) --Core.Pathline#PATHLINE
-- Set name.
taxiway.name=Name
-- Add to taxiways.
self.taxiways[Name]=taxiway
--self:I(self.taxiways)
return self
end
--- Find the shortest path using taxiways to get from given coodinates A to B on the airbase.
-- Note that the taxi ways have to be manually added with the `AIRBASE:AddTaxiway()` function.
-- @param #AIRBASE self
-- @param Core.Point#COORDINATE StartCoord Start coordinate.
-- @param Core.Point#COORDINATE EndCoord End coordinate.
-- @return Core.Pathline#PATHLINE Shortest path on taxiways from `StartCoord` to `EndCoord`.
-- @return #table Table of used taxi way pathlines.
function AIRBASE:FindTaxiwaysFromAtoB(StartCoord, EndCoord)
-- Create A* pathfinding.
local astar=ASTAR:New()
-- Add pathlines of taxiways of airport.
for _,_taxiway in pairs(self.taxiways) do
local taxiway=_taxiway --Core.Pathline#PATHLINE
astar:AddNodeFromPathlineName(taxiway)
end
-- Set cost function.
astar:SetCostDist2D()
-- Set valid neighbours to be on the same pathline or at most 10 meters between nodes to jump from one pathline/taxiway to another.
astar:SetValidNeighbourPathline(10)
-- Set start and end coordinates.
astar:SetStartCoordinate(StartCoord)
astar:SetEndCoordinate(EndCoord)
-- Get pathline.
local taxipath, nodes=astar:GetPathline()
local taxiways=astar:GetPathlinesFromNodes(nodes)
return taxipath, taxiways
end
--- Get closest taxiway from a given reference coordinate.
-- @param #AIRBASE self
-- @param Core.Point#COORDINATE Coord Reference coordinate.
-- @return Core.Pathline#PATHLINE Taxiway.
-- @return #number Distance to taxiway in meters.
-- @return Core.Point#COORDINATE Coordinate on taxiway closest to reference coordinate.
-- @return Core.Pathline#PATHLINE.Segment Segment of the taxiway closest to the reference coordinate.
function AIRBASE:GetClosestTaxiway(Coord)
local taxipath=nil
local distmin=math.huge
local coordmin=nil
local segmin=nil
for name,_pathline in pairs(self.taxiways) do
local pathline=_pathline --Core.Pathline#PATHLINE
local coord, dist, segment=pathline:GetClosestPoint3D(Coord)
if dist<distmin then
taxipath=pathline
coordmin=coord
distmin=dist
segmin=segment
end
end
return taxipath, distmin, coordmin, segmin
end
--- Find the shortest path using taxiways to get from given parking spot to the starting point of a runway.
-- Note that the taxi ways have to be manually added with the `AIRBASE:AddTaxiway()` function.
-- @param #AIRBASE self
-- @param #AIRBASE.ParkingSpot ParkingSpot Parking spot.
-- @param #AIRBASE.Runway Runway The runway. If none is given, we take the active runway for takeoff.
-- @return Core.Pathline#PATHLINE Shortest path on taxiways from `StartCoord` to `EndCoord`.
-- @return #table Table of used taxi way pathlines.
function AIRBASE:FindTaxiwaysParkingToRunway(ParkingSpot, Runway)
Runway=Runway or self:GetActiveRunwayTakeoff()
local StartCoord=ParkingSpot.Coordinate
local EndCoord=Runway.position
local taxipath, taxiways=self:FindTaxiwaysFromAtoB(StartCoord,EndCoord)
return taxipath, taxiways
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Parking
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
@@ -2131,7 +2722,7 @@ function AIRBASE:GetRunwayByName(Name)
-- Name including L or R, e.g. "31L".
local name=self:GetRunwayName(runway)
self:T("Check Runway Name: "..name)
if name==Name:upper() then
return runway
end
@@ -2158,7 +2749,7 @@ function AIRBASE:_InitRunways(IncludeInverse)
--- Function to create a runway data table.
local function _createRunway(name, course, width, length, center)
self:T("Create Runway: name = "..name)
-- Bearing in rad.
local bearing=-1*course
@@ -2174,6 +2765,7 @@ function AIRBASE:_InitRunways(IncludeInverse)
runway.name=string.format("%02d", tonumber(namefromheading))
else
runway.name=string.format("%02d", tonumber(name))
self:I("RunwayName: "..runway.name)
end
--runway.name=string.format("%02d", tonumber(name))
@@ -2495,7 +3087,7 @@ function AIRBASE:GetRunwayData(magvar, mark)
runway.endpoint=c2
-- Debug info.
--self:I(string.format("Airbase %s: Adding runway id=%s, heading=%03d, length=%d m i=%d j=%d", self:GetName(), runway.idx, runway.heading, runway.length, i, j))
self:T(string.format("Airbase %s: Adding runway id=%s, heading=%03d, length=%d m i=%d j=%d", self:GetName(), runway.idx, runway.heading, runway.length, i, j))
-- Debug mark
if mark then
@@ -2622,8 +3214,8 @@ function AIRBASE:GetRunwayIntoWind(PreferLeft)
-- Loop over runways.
local dotmin=nil
for i,_runway in pairs(runways) do
local runway=_runway --#AIRBASE.Runway
for i ,_runway in pairs(runways) do
local runway=_runway --#AIRBASE.Runway
if PreferLeft==nil or PreferLeft==runway.isLeft then

View File

@@ -994,6 +994,65 @@ function CONTROLLABLE:CommandSetFrequencyForUnit(Frequency,Modulation,Power,Unit
return self
end
--- [AIR] Set smoke on or off. See [DCS command smoke on off](https://wiki.hoggitworld.com/view/DCS_command_smoke_on_off)
-- @param #CONTROLLABLE self
-- @param #boolean OnOff Set to true for on and false for off. Defaults to true.
-- @param #number Delay (Optional) Delay the command by this many seconds.
-- @return #CONTROLLABLE self
function CONTROLLABLE:CommandSmokeOnOff(OnOff, Delay)
local switch = (OnOff == nil) and true or OnOff
local command = {
id = 'SMOKE_ON_OFF',
params = {
value = switch
}
}
if Delay and Delay>0 then
SCHEDULER:New(nil,self.CommandSmokeOnOff,{self,switch},Delay)
else
self:SetCommand(command)
end
return self
end
--- [AIR] Set smoke on. See [DCS command smoke on off](https://wiki.hoggitworld.com/view/DCS_command_smoke_on_off)
-- @param #CONTROLLABLE self
-- @param #number Delay (Optional) Delay the command by this many seconds.
-- @return #CONTROLLABLE self
function CONTROLLABLE:CommandSmokeON(Delay)
local command = {
id = 'SMOKE_ON_OFF',
params = {
value = true
}
}
if Delay and Delay>0 then
SCHEDULER:New(nil,self.CommandSmokeON,{self},Delay)
else
self:SetCommand(command)
end
return self
end
--- [AIR] Set smoke off. See [DCS command smoke on off](https://wiki.hoggitworld.com/view/DCS_command_smoke_on_off)
-- @param #CONTROLLABLE self
-- @param #number Delay (Optional) Delay the command by this many seconds.
-- @return #CONTROLLABLE self
function CONTROLLABLE:CommandSmokeOFF(Delay)
local command = {
id = 'SMOKE_ON_OFF',
params = {
value = false
}
}
if Delay and Delay>0 then
SCHEDULER:New(nil,self.CommandSmokeOFF,{self},Delay)
else
self:SetCommand(command)
end
return self
end
--- Set EPLRS data link on/off.
-- @param #CONTROLLABLE self
-- @param #boolean SwitchOnOff If true (or nil) switch EPLRS on. If false switch off.

View File

@@ -2,17 +2,17 @@
--
-- ## Main Features:
--
-- * Convenient access to DCS API functions
-- * Convenient access to Ground Crew created cargo items.
--
-- ===
--
-- ## Example Missions:
--
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_Demos/tree/master/Wrapper/Storage).
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_Demos/tree/master/).
--
-- ===
--
-- ### Author: **Applevangelist**
-- ### Author: **Applevangelist**; additional checks **Chesster**
--
-- ===
-- @module Wrapper.DynamicCargo
@@ -124,7 +124,7 @@ DYNAMICCARGO.AircraftDimensions = {
--- DYNAMICCARGO class version.
-- @field #string version
DYNAMICCARGO.version="0.0.5"
DYNAMICCARGO.version="0.0.7"
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO list
@@ -183,7 +183,7 @@ end
-- @param #DYNAMICCARGO self
-- @return DCS static object
function DYNAMICCARGO:GetDCSObject()
local DCSStatic = Unit.getByName( self.StaticName )
local DCSStatic = StaticObject.getByName( self.StaticName ) or Unit.getByName( self.StaticName )
if DCSStatic then
return DCSStatic
end
@@ -227,7 +227,7 @@ end
-- @param #DYNAMICCARGO self
-- @return #boolean Outcome
function DYNAMICCARGO:IsUnloaded()
if self.CargoState and self.CargoState == DYNAMICCARGO.State.REMOVED then
if self.CargoState and self.CargoState == DYNAMICCARGO.State.UNLOADED then
return true
else
return false
@@ -238,7 +238,7 @@ end
-- @param #DYNAMICCARGO self
-- @return #boolean Outcome
function DYNAMICCARGO:IsRemoved()
if self.CargoState and self.CargoState == DYNAMICCARGO.State.UNLOADED then
if self.CargoState and self.CargoState == DYNAMICCARGO.State.REMOVED then
return true
else
return false
@@ -376,6 +376,33 @@ end
-- Private Functions
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--- [Internal] _Get helo hovering intel
-- @param #DYNAMICCARGO self
-- @param Wrapper.Unit#UNIT Unit The Unit to test
-- @param #number ropelength Ropelength to test
-- @return #boolean Outcome
function DYNAMICCARGO:_HeloHovering(Unit,ropelength)
local DCSUnit = Unit:GetDCSObject() --DCS#Unit
local hovering = false
local Height = 0
if DCSUnit then
local UnitInAir = DCSUnit:inAir()
local UnitCategory = DCSUnit:getDesc().category
if UnitInAir == true and UnitCategory == 1 then
local VelocityVec3 = DCSUnit:getVelocity()
local Velocity = UTILS.VecNorm(VelocityVec3)
local Coordinate = DCSUnit:getPoint()
local LandHeight = land.getHeight({ x = Coordinate.x, y = Coordinate.z })
Height = Coordinate.y - LandHeight
if Velocity < 1 and Height <= ropelength and Height > 6 then -- hover lower than ropelength but higher than the normal FARP height.
hovering = true
end
end
return hovering, Height
end
return false
end
--- [Internal] _Get Possible Player Helo Nearby
-- @param #DYNAMICCARGO self
-- @param Core.Point#COORDINATE pos
@@ -393,30 +420,37 @@ function DYNAMICCARGO:_GetPossibleHeloNearby(pos,loading)
local name = helo:GetPlayerName() or _DATABASE:_FindPlayerNameByUnitName(helo:GetName()) or "None"
self:T(self.lid.." Checking: "..name)
local hpos = helo:GetCoordinate()
-- TODO Unloading via sling load?
--local inair = hpos.y-hpos:GetLandHeight() > 4.5 and true or false -- Standard FARP is 4.5m
local inair = helo:InAir()
self:T(self.lid.." InAir: AGL/InAir: "..hpos.y-hpos:GetLandHeight().."/"..tostring(inair))
-- TODO Check unloading via sling load?
local typename = helo:GetTypeName()
if hpos and typename and inair == false then
local dimensions = DYNAMICCARGO.AircraftDimensions[typename]
if dimensions then
local delta2D = hpos:Get2DDistance(pos)
local delta3D = hpos:Get3DDistance(pos)
if self.testing then
self:T(string.format("Cargo relative position: 2D %dm | 3D %dm",delta2D,delta3D))
self:T(string.format("Helo dimension: length %dm | width %dm | rope %dm",dimensions.length,dimensions.width,dimensions.ropelength))
end
if loading~=true and delta2D > dimensions.length or delta2D > dimensions.width or delta3D > dimensions.ropelength then
success = true
Helo = helo
Playername = name
end
if loading == true and delta2D < dimensions.length or delta2D < dimensions.width or delta3D < dimensions.ropelength then
success = true
Helo = helo
Playername = name
end
local dimensions = DYNAMICCARGO.AircraftDimensions[typename]
local hovering, height = self:_HeloHovering(helo,dimensions.ropelength)
local helolanded = not helo:InAir()
self:T(self.lid.." InAir: AGL/Hovering: "..hpos.y-hpos:GetLandHeight().."/"..tostring(hovering))
if hpos and typename and dimensions then
local delta2D = hpos:Get2DDistance(pos)
local delta3D = hpos:Get3DDistance(pos)
if self.testing then
self:T(string.format("Cargo relative position: 2D %dm | 3D %dm",delta2D,delta3D))
self:T(string.format("Helo dimension: length %dm | width %dm | rope %dm",dimensions.length,dimensions.width,dimensions.ropelength))
self:T(string.format("Helo hovering: %s at %dm",tostring(hovering),height))
end
-- unloading from ground
if loading~=true and (delta2D > dimensions.length or delta2D > dimensions.width) and helolanded then -- Theoretically the cargo could still be attached to the sling if landed next to the cargo. But once moved again it would go back into loaded state once lifted again.
success = true
Helo = helo
Playername = name
end
-- unloading from hover/rope
if loading~=true and delta3D > dimensions.ropelength then
success = true
Helo = helo
Playername = name
end
-- loading
if loading == true and ((delta2D < dimensions.length and delta2D < dimensions.width and helolanded) or (delta3D == dimensions.ropelength and helo:InAir())) then -- Loaded via ground or sling
success = true
Helo = helo
Playername = name
end
end
end
@@ -434,20 +468,22 @@ function DYNAMICCARGO:_UpdatePosition()
self:T(string.format("Cargo position: x=%d, y=%d, z=%d",pos.x,pos.y,pos.z))
self:T(string.format("Last position: x=%d, y=%d, z=%d",self.LastPosition.x,self.LastPosition.y,self.LastPosition.z))
end
if UTILS.Round(UTILS.VecDist3D(pos,self.LastPosition),2) > 0.5 then
if UTILS.Round(UTILS.VecDist3D(pos,self.LastPosition),2) > 0.5 then -- This checks if the cargo has moved more than 0.5m since last check. If so then the cargo is loaded
---------------
-- LOAD Cargo
---------------
if self.CargoState == DYNAMICCARGO.State.NEW then
local isloaded, client, playername = self:_GetPossibleHeloNearby(pos,true)
if self.CargoState == DYNAMICCARGO.State.NEW or self.CargoState == DYNAMICCARGO.State.UNLOADED then
local isloaded, client, playername = self:_GetPossibleHeloNearby(pos,true)
self:T(self.lid.." moved! NEW -> LOADED by "..tostring(playername))
self.CargoState = DYNAMICCARGO.State.LOADED
self.Owner = playername
_DATABASE:CreateEventDynamicCargoLoaded(self)
_DATABASE:CreateEventDynamicCargoLoaded(self)
end
---------------
-- UNLOAD Cargo
---------------
elseif self.CargoState == DYNAMICCARGO.State.LOADED then
---------------
-- If the cargo is stationary then we need to end this condition here to check whether it is unloaded or still onboard or still hooked if anyone can hover that precisly
elseif self.CargoState == DYNAMICCARGO.State.LOADED then
-- TODO add checker if we are in flight somehow
-- ensure not just the helo is moving
local count = _DYNAMICCARGO_HELOS:CountAlive()
@@ -459,26 +495,19 @@ function DYNAMICCARGO:_UpdatePosition()
local isunloaded = true
local client
local playername = self.Owner
if count > 0 and (agl > 0 or self.testing) then
self:T(self.lid.." Possible alive helos: "..count or -1)
if agl ~= 0 or self.testing then
isunloaded, client, playername = self:_GetPossibleHeloNearby(pos,false)
end
if count > 0 then
self:T(self.lid.." Possible alive helos: "..count or -1)
isunloaded, client, playername = self:_GetPossibleHeloNearby(pos,false)
if isunloaded then
self:T(self.lid.." moved! LOADED -> UNLOADED by "..tostring(playername))
self.CargoState = DYNAMICCARGO.State.UNLOADED
self.Owner = playername
_DATABASE:CreateEventDynamicCargoUnloaded(self)
end
elseif count > 0 and agl == 0 then
self:T(self.lid.." moved! LOADED -> UNLOADED by "..tostring(playername))
self.CargoState = DYNAMICCARGO.State.UNLOADED
self.Owner = playername
_DATABASE:CreateEventDynamicCargoUnloaded(self)
end
end
end
self.LastPosition = pos
end
--end
else
---------------
-- REMOVED Cargo

View File

@@ -1179,9 +1179,9 @@ function GROUP:GetAverageVec3()
end
end
--- Returns a POINT_VEC2 object indicating the point in 2D of the first UNIT of the GROUP within the mission.
--- Returns a COORDINATE object indicating the point in 2D of the first UNIT of the GROUP within the mission.
-- @param #GROUP self
-- @return Core.Point#POINT_VEC2 The 2D point vector of the first DCS Unit of the GROUP.
-- @return Core.Point#COORDINATE The 3D point vector of the first DCS Unit of the GROUP.
-- @return #nil The first UNIT is not existing or alive.
function GROUP:GetPointVec2()
--self:F2(self.GroupName)
@@ -1194,7 +1194,7 @@ function GROUP:GetPointVec2()
return FirstUnitPointVec2
end
BASE:E( { "Cannot GetPointVec2", Group = self, Alive = self:IsAlive() } )
BASE:E( { "Cannot get COORDINATE", Group = self, Alive = self:IsAlive() } )
return nil
end
@@ -1843,7 +1843,10 @@ end
-- @return #table
function GROUP:GetTemplateRoutePoints()
local GroupName = self:GetName()
return UTILS.DeepCopy( _DATABASE:GetGroupTemplate( GroupName ).route.points )
local template = _DATABASE:GetGroupTemplate(GroupName)
if template and template.route and template.route.points then
return UTILS.DeepCopy(template.route.points)
end
end
@@ -2093,7 +2096,7 @@ function GROUP:Respawn( Template, Reset )
GroupUnitVec3 = Zone:GetRandomVec3()
else
if self.InitRespawnRandomizePositionInner and self.InitRespawnRandomizePositionOuter then
GroupUnitVec3 = POINT_VEC3:NewFromVec2( From ):GetRandomPointVec3InRadius( self.InitRespawnRandomizePositionsOuter, self.InitRespawnRandomizePositionsInner )
GroupUnitVec3 = COORDINATE:NewFromVec3(From):GetRandomVec3InRadius(self.InitRespawnRandomizePositionsOuter, self.InitRespawnRandomizePositionsInner)
else
GroupUnitVec3 = Zone:GetVec3()
end
@@ -2144,7 +2147,7 @@ function GROUP:Respawn( Template, Reset )
GroupUnitVec3 = Zone:GetRandomVec3()
else
if self.InitRespawnRandomizePositionInner and self.InitRespawnRandomizePositionOuter then
GroupUnitVec3 = POINT_VEC3:NewFromVec2( From ):GetRandomPointVec3InRadius( self.InitRespawnRandomizePositionsOuter, self.InitRespawnRandomizePositionsInner )
GroupUnitVec3 = COORDINATE:NewFromVec2( From ):GetRandomPointVec3InRadius( self.InitRespawnRandomizePositionsOuter, self.InitRespawnRandomizePositionsInner )
else
GroupUnitVec3 = Zone:GetVec3()
end

View File

@@ -16,7 +16,7 @@
--- @type POSITIONABLE
-- @field Core.Point#COORDINATE coordinate Coordinate object.
-- @field Core.Point#POINT_VEC3 pointvec3 Point Vec3 object.
-- @field Core.Point#COORDINATE pointvec3 Point Vec3 object.
-- @extends Wrapper.Identifiable#IDENTIFIABLE
@@ -284,9 +284,9 @@ function POSITIONABLE:GetVec2()
return nil
end
--- Returns a POINT_VEC2 object indicating the point in 2D of the POSITIONABLE within the mission.
--- Returns a COORDINATE object indicating the point in 2D of the POSITIONABLE within the mission.
-- @param #POSITIONABLE self
-- @return Core.Point#POINT_VEC2 The 2D point vector of the POSITIONABLE.
-- @return Core.Point#COORDINATE The 3D point vector of the POSITIONABLE.
-- @return #nil The POSITIONABLE is not existing or alive.
function POSITIONABLE:GetPointVec2()
self:F2( self.PositionableName )
@@ -296,20 +296,20 @@ function POSITIONABLE:GetPointVec2()
if DCSPositionable then
local PositionableVec3 = DCSPositionable:getPosition().p
local PositionablePointVec2 = POINT_VEC2:NewFromVec3( PositionableVec3 )
local PositionablePointVec2 = COORDINATE:NewFromVec3( PositionableVec3 )
-- self:F( PositionablePointVec2 )
return PositionablePointVec2
end
self:E( { "Cannot GetPointVec2", Positionable = self, Alive = self:IsAlive() } )
self:E( { "Cannot Coordinate", Positionable = self, Alive = self:IsAlive() } )
return nil
end
--- Returns a POINT_VEC3 object indicating the point in 3D of the POSITIONABLE within the mission.
--- Returns a COORDINATE object indicating the point in 3D of the POSITIONABLE within the mission.
-- @param #POSITIONABLE self
-- @return Core.Point#POINT_VEC3 The 3D point vector of the POSITIONABLE.
-- @return Core.Point#COORDINATE The 3D point vector of the POSITIONABLE.
-- @return #nil The POSITIONABLE is not existing or alive.
function POSITIONABLE:GetPointVec3()
@@ -329,8 +329,8 @@ function POSITIONABLE:GetPointVec3()
else
-- Create a new POINT_VEC3 object.
self.pointvec3 = POINT_VEC3:NewFromVec3( PositionableVec3 )
-- Create a new COORDINATE object.
self.pointvec3 = COORDINATE:NewFromVec3( PositionableVec3 )
end

View File

@@ -1,6 +1,7 @@
# import required module
from pathlib import Path
import os
import codecs
# assign directory
directory = '.'
@@ -15,8 +16,9 @@ with open( os.path.dirname(__file__) + '/docs-header.html', 'r') as file:
# that directory
files = Path(directory).glob('*.html')
for file in files:
# print(file)
with open(file, 'r') as fileread:
#print(file)
#with open(file, 'r') as fileread:
with codecs.open(file, 'r', encoding='utf-8', errors='ignore') as fileread:
filedata = fileread.read()
# Replace the target string
filedata = filedata.replace( '<head>', newhead )

View File

@@ -169,10 +169,6 @@ Defines an extensive API to manage 3D points in the DCS World 3D simulation spac
**Features:**
* Provides a COORDINATE class, which allows to manage points in 3D space and perform various operations on it.
* Provides a POINT_VEC2 class, which is derived from COORDINATE, and allows to manage points in 3D space, but from a
Lat/Lon and Altitude perspective.
* Provides a POINT_VEC3 class, which is derived from COORDINATE, and allows to manage points in 3D space, but from a
X, Z and Y vector perspective.
**The coordinate system classes are essential to understand. Learn this!**