mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-08-15 10:47:21 +00:00
Compare commits
96 Commits
2.9.11
...
FF/MasterD
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
28ae63bd8d | ||
|
|
42e7e3f94f | ||
|
|
24b47b02e0 | ||
|
|
cbcc893ce5 | ||
|
|
382b049c5f | ||
|
|
a53763221c | ||
|
|
b7bac28113 | ||
|
|
a9edb16554 | ||
|
|
0aeb1fc6af | ||
|
|
eeeeda4e5e | ||
|
|
f5881eda53 | ||
|
|
c1997d9f70 | ||
|
|
bb1caa6642 | ||
|
|
dd5ca93f26 | ||
|
|
1889df4952 | ||
|
|
7ca219748d | ||
|
|
2fc16ba694 | ||
|
|
a4feafab8e | ||
|
|
997baf21a0 | ||
|
|
b126cc00d0 | ||
|
|
09b7922b84 | ||
|
|
7a5b9a75f3 | ||
|
|
4bab2ee1de | ||
|
|
d7defe6f7f | ||
|
|
db869bcb6d | ||
|
|
ea4a1f9ff9 | ||
|
|
20406e40ca | ||
|
|
3b50fee5a0 | ||
|
|
804004198b | ||
|
|
5b8b8a5566 | ||
|
|
0468bacc0b | ||
|
|
7eba1349ae | ||
|
|
b6074a4795 | ||
|
|
36c9f551d9 | ||
|
|
89c3f7310b | ||
|
|
a6b622ed31 | ||
|
|
f1af3a50b8 | ||
|
|
0c90e90c18 | ||
|
|
f97ef25104 | ||
|
|
069c0aa03f | ||
|
|
b145588ed5 | ||
|
|
3ad60a95ce | ||
|
|
ac4b620f16 | ||
|
|
ccada18a6a | ||
|
|
1547d66327 | ||
|
|
8042e8bfaf | ||
|
|
dd7b87e9cd | ||
|
|
460d2768ff | ||
|
|
3c74272749 | ||
|
|
82c409d77a | ||
|
|
195aac4504 | ||
|
|
08d8f3e25f | ||
|
|
6f72697e26 | ||
|
|
0f6439cf9f | ||
|
|
2c10943cb1 | ||
|
|
544db963ea | ||
|
|
207698a2dd | ||
|
|
d1ae2c0f5e | ||
|
|
0392417189 | ||
|
|
be4beea9d0 | ||
|
|
5da899138b | ||
|
|
1ec1e00bde | ||
|
|
5d93b33d42 | ||
|
|
b2077bfc74 | ||
|
|
6fdf9a649f | ||
|
|
d013bbc751 | ||
|
|
e0092fdba0 | ||
|
|
fbeada439f | ||
|
|
6c8858d2f5 | ||
|
|
e2b77878df | ||
|
|
53d7972858 | ||
|
|
04a55e4104 | ||
|
|
d11acecdac | ||
|
|
49c11073e6 | ||
|
|
1a156e7e12 | ||
|
|
1856754614 | ||
|
|
6ac452ff15 | ||
|
|
d707a4775c | ||
|
|
ffccc31e38 | ||
|
|
0405af2bde | ||
|
|
e50e572c78 | ||
|
|
3083599158 | ||
|
|
b7b6c1ea19 | ||
|
|
5b107ce2da | ||
|
|
5c1e342a79 | ||
|
|
ddf33da787 | ||
|
|
b0a192a767 | ||
|
|
986c340211 | ||
|
|
2109537f86 | ||
|
|
690db7f12f | ||
|
|
4f3fd06cc9 | ||
|
|
4074023ed3 | ||
|
|
6c00b0c7eb | ||
|
|
76dc0d690a | ||
|
|
d783f7be99 | ||
|
|
b66e91b11f |
1
.github/workflows/build-docs.yml
vendored
1
.github/workflows/build-docs.yml
vendored
@@ -57,7 +57,6 @@ jobs:
|
||||
|
||||
- name: Update apt-get (needed for act docker image)
|
||||
run: |
|
||||
sudo rm /etc/apt/sources.list.d/microsoft-prod.list
|
||||
sudo apt-get -qq update
|
||||
|
||||
- name: Install tree
|
||||
|
||||
2
.github/workflows/build-includes.yml
vendored
2
.github/workflows/build-includes.yml
vendored
@@ -110,7 +110,7 @@ jobs:
|
||||
- name: Run LuaSrcDiet
|
||||
run: |
|
||||
luasrcdiet --basic --opt-emptylines ./build/result/Moose_Include_Static/Moose.lua -o ./build/result/Moose_Include_Static/Moose_.lua
|
||||
|
||||
|
||||
#########################################################################
|
||||
# Push to MOOSE_INCLUDE
|
||||
#########################################################################
|
||||
|
||||
7
.gitignore
vendored
7
.gitignore
vendored
@@ -28,13 +28,6 @@ local.properties
|
||||
.buildpath
|
||||
|
||||
|
||||
#####################
|
||||
## Visual Studio Code
|
||||
#####################
|
||||
*.code-workspace
|
||||
.vscode/
|
||||
|
||||
|
||||
#################
|
||||
## Visual Studio
|
||||
#################
|
||||
|
||||
@@ -1953,7 +1953,7 @@ local function refct_from_id(id) -- refct = refct_from_id(CTypeID)
|
||||
unsigned = refct.unsigned,
|
||||
size = bit.band(bit.rshift(ctype.info, 16), 127),
|
||||
}
|
||||
refct.bool, refct.const, refct.volatile, refct.unsigned = nil
|
||||
refct.bool, refct.const, refct.volatile, refct.unsigned = nil, nil, nil, nil
|
||||
end
|
||||
|
||||
if CT[4] then -- Merge sibling attributes onto this type.
|
||||
|
||||
14
Moose Development/Moose/.vscode/settings.json
vendored
14
Moose Development/Moose/.vscode/settings.json
vendored
@@ -1,17 +1,7 @@
|
||||
{
|
||||
"Lua.workspace.preloadFileSize": 10000,
|
||||
"Lua.workspace.preloadFileSize": 1000,
|
||||
"Lua.diagnostics.disable": [
|
||||
"undefined-doc-name",
|
||||
"duplicate-set-field",
|
||||
"trailing-space",
|
||||
"need-check-nil",
|
||||
"ambiguity-1",
|
||||
"undefined-doc-param",
|
||||
"redundant-parameter",
|
||||
"param-type-mismatch",
|
||||
"deprecated",
|
||||
"undefined-global",
|
||||
"lowercase-global"
|
||||
"undefined-doc-name"
|
||||
],
|
||||
"Lua.diagnostics.globals": [
|
||||
"BASE",
|
||||
|
||||
@@ -11,13 +11,15 @@
|
||||
-- @module AI.AI_A2A_Cap
|
||||
-- @image AI_Combat_Air_Patrol.JPG
|
||||
|
||||
-- @type AI_A2A_CAP
|
||||
--- @type AI_A2A_CAP
|
||||
-- @extends AI.AI_Air_Patrol#AI_AIR_PATROL
|
||||
-- @extends AI.AI_Air_Engage#AI_AIR_ENGAGE
|
||||
|
||||
--- The AI_A2A_CAP class implements the core functions to patrol a @{Core.Zone} by an AI @{Wrapper.Group} or @{Wrapper.Group}
|
||||
-- and automatically engage any airborne enemies that are within a certain range or within a certain zone.
|
||||
--
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- The AI_A2A_CAP is assigned a @{Wrapper.Group} and this must be done before the AI_A2A_CAP process can be started using the **Start** event.
|
||||
|
||||
@@ -32,7 +32,9 @@
|
||||
-- [DCS WORLD - MOOSE - A2A GCICAP - Build an automatic A2A Defense System](https://www.youtube.com/playlist?list=PL7ZUrU4zZUl0S4KMNUUJpaUs6zZHjLKNx)
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- # QUICK START GUIDE
|
||||
--
|
||||
-- There are basically two classes available to model an A2A defense system.
|
||||
|
||||
@@ -13,12 +13,14 @@
|
||||
|
||||
|
||||
|
||||
-- @type AI_A2A_GCI
|
||||
-- @extends AI.AI_A2A#AI_A2A
|
||||
--- @type AI_A2A_GCI
|
||||
-- @extends AI.AI_Air_Engage#AI_AIR_ENGAGE
|
||||
|
||||
|
||||
--- Implements the core functions to intercept intruders. Use the Engage trigger to intercept intruders.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- The AI_A2A_GCI is assigned a @{Wrapper.Group} and this must be done before the AI_A2A_GCI process can be started using the **Start** event.
|
||||
--
|
||||
-- The AI will fly towards the random 3D point within the patrol zone, using a random speed within the given altitude and speed limits.
|
||||
@@ -39,8 +41,6 @@
|
||||
--
|
||||
-- ## 2. AI_A2A_GCI is a FSM
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- ### 2.1 AI_A2A_GCI States
|
||||
--
|
||||
-- * **None** ( Group ): The process is not started yet.
|
||||
|
||||
@@ -10,11 +10,13 @@
|
||||
-- @image AI_Air_Patrolling.JPG
|
||||
|
||||
|
||||
-- @type AI_A2A_PATROL
|
||||
-- @extends AI.AI_A2A#AI_A2A
|
||||
--- @type AI_A2A_PATROL
|
||||
-- @extends AI.AI_Air_Patrol#AI_AIR_PATROL
|
||||
|
||||
--- Implements the core functions to patrol a @{Core.Zone} by an AI @{Wrapper.Group} or @{Wrapper.Group}.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- The AI_A2A_PATROL is assigned a @{Wrapper.Group} and this must be done before the AI_A2A_PATROL process can be started using the **Start** event.
|
||||
|
||||
@@ -11,11 +11,14 @@
|
||||
-- @module AI.AI_A2G_BAI
|
||||
-- @image AI_Air_To_Ground_Engage.JPG
|
||||
|
||||
-- @type AI_A2G_BAI
|
||||
-- @extends AI.AI_A2A_Engage#AI_A2A_Engage -- TODO: Documentation. This class does not exist, unable to determine what it extends.
|
||||
--- @type AI_A2G_BAI
|
||||
-- @extends AI.AI_Air_Patrol#AI_AIR_PATROL
|
||||
-- @extends AI.AI_Air_Engage#AI_AIR_ENGAGE
|
||||
|
||||
--- Implements the core functions to intercept intruders. Use the Engage trigger to intercept intruders.
|
||||
--
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
@@ -46,7 +49,7 @@ AI_A2G_BAI = {
|
||||
function AI_A2G_BAI:New2( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType )
|
||||
|
||||
local AI_Air = AI_AIR:New( AIGroup )
|
||||
local AI_Air_Patrol = AI_AIR_PATROL:New( AI_Air, AIGroup, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType ) -- #AI_AIR_PATROL
|
||||
local AI_Air_Patrol = AI_AIR_PATROL:New( AI_Air, AIGroup, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType )
|
||||
local AI_Air_Engage = AI_AIR_ENGAGE:New( AI_Air_Patrol, AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType )
|
||||
local self = BASE:Inherit( self, AI_Air_Engage )
|
||||
|
||||
|
||||
@@ -11,13 +11,16 @@
|
||||
-- @module AI.AI_A2G_CAS
|
||||
-- @image AI_Air_To_Ground_Engage.JPG
|
||||
|
||||
-- @type AI_A2G_CAS
|
||||
-- @extends AI.AI_A2G_Patrol#AI_AIR_PATROL TODO: Documentation. This class does not exist, unable to determine what it extends.
|
||||
--- @type AI_A2G_CAS
|
||||
-- @extends AI.AI_Air_Patrol#AI_AIR_PATROL
|
||||
-- @extends AI.AI_Air_Engage#AI_AIR_ENGAGE
|
||||
|
||||
--- Implements the core functions to intercept intruders. Use the Engage trigger to intercept intruders.
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
@@ -46,7 +49,7 @@ AI_A2G_CAS = {
|
||||
function AI_A2G_CAS:New2( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType )
|
||||
|
||||
local AI_Air = AI_AIR:New( AIGroup )
|
||||
local AI_Air_Patrol = AI_AIR_PATROL:New( AI_Air, AIGroup, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType ) -- #AI_AIR_PATROL
|
||||
local AI_Air_Patrol = AI_AIR_PATROL:New( AI_Air, AIGroup, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType )
|
||||
local AI_Air_Engage = AI_AIR_ENGAGE:New( AI_Air_Patrol, AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType )
|
||||
local self = BASE:Inherit( self, AI_Air_Engage )
|
||||
|
||||
|
||||
@@ -36,6 +36,8 @@
|
||||
--
|
||||
-- # QUICK START GUIDE
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- The following class is available to model an A2G defense system.
|
||||
--
|
||||
-- AI_A2G_DISPATCHER is the main A2G defense class that models the A2G defense system.
|
||||
|
||||
@@ -13,12 +13,15 @@
|
||||
|
||||
|
||||
|
||||
-- @type AI_A2G_SEAD
|
||||
-- @extends AI.AI_A2G_Patrol#AI_AIR_PATROL
|
||||
--- @type AI_A2G_SEAD
|
||||
-- @extends AI.AI_Air_Patrol#AI_AIR_PATROL
|
||||
-- @extends AI.AI_Air_Engage#AI_AIR_ENGAGE
|
||||
|
||||
|
||||
--- Implements the core functions to SEAD intruders. Use the Engage trigger to intercept intruders.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- The AI_A2G_SEAD is assigned a @{Wrapper.Group} and this must be done before the AI_A2G_SEAD process can be started using the **Start** event.
|
||||
--
|
||||
-- The AI will fly towards the random 3D point within the patrol zone, using a random speed within the given altitude and speed limits.
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
--- The AI_AIR class implements the core functions to operate an AI @{Wrapper.Group}.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- # 1) AI_AIR constructor
|
||||
--
|
||||
@@ -657,8 +658,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 +667,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 +762,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 } )
|
||||
|
||||
|
||||
@@ -36,6 +36,8 @@
|
||||
--
|
||||
-- # QUICK START GUIDE
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- The following class is available to model an AIR defense system.
|
||||
--
|
||||
-- AI_AIR_DISPATCHER is the main AIR defense class that models the AIR defense system.
|
||||
|
||||
@@ -13,12 +13,14 @@
|
||||
|
||||
|
||||
|
||||
-- @type AI_AIR_ENGAGE
|
||||
--- @type AI_AIR_ENGAGE
|
||||
-- @extends AI.AI_AIR#AI_AIR
|
||||
|
||||
|
||||
--- Implements the core functions to intercept intruders. Use the Engage trigger to intercept intruders.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- The AI_AIR_ENGAGE is assigned a @{Wrapper.Group} and this must be done before the AI_AIR_ENGAGE process can be started using the **Start** event.
|
||||
--
|
||||
-- The AI will fly towards the random 3D point within the patrol zone, using a random speed within the given altitude and speed limits.
|
||||
@@ -453,7 +455,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 +464,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 +538,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 +546,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!
|
||||
|
||||
@@ -9,12 +9,14 @@
|
||||
-- @module AI.AI_Air_Patrol
|
||||
-- @image AI_Air_To_Ground_Patrol.JPG
|
||||
|
||||
-- @type AI_AIR_PATROL
|
||||
--- @type AI_AIR_PATROL
|
||||
-- @extends AI.AI_Air#AI_AIR
|
||||
|
||||
--- The AI_AIR_PATROL class implements the core functions to patrol a @{Core.Zone} by an AI @{Wrapper.Group}
|
||||
-- and automatically engage any airborne enemies that are within a certain range or within a certain zone.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- The AI_AIR_PATROL is assigned a @{Wrapper.Group} and this must be done before the AI_AIR_PATROL process can be started using the **Start** event.
|
||||
@@ -309,7 +311,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 +361,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 )
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
|
||||
|
||||
-- @type AI_AIR_SQUADRON
|
||||
--- @type AI_AIR_SQUADRON
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
|
||||
@@ -38,6 +38,8 @@
|
||||
|
||||
--- Implements the core functions to provide BattleGround Air Interdiction in an Engage @{Core.Zone} by an AIR @{Wrapper.Controllable} or @{Wrapper.Group}.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- The AI_BAI_ZONE runs a process. It holds an AI in a Patrol Zone and when the AI is commanded to engage, it will fly to an Engage Zone.
|
||||
--
|
||||
-- 
|
||||
@@ -407,7 +409,7 @@ function AI_BAI_ZONE:onafterStart( Controllable, From, Event, To )
|
||||
self:SetDetectionDeactivated() -- When not engaging, set the detection off.
|
||||
end
|
||||
|
||||
-- @param Wrapper.Controllable#CONTROLLABLE AIControllable
|
||||
--- @param Wrapper.Controllable#CONTROLLABLE AIControllable
|
||||
function _NewEngageRoute( AIControllable )
|
||||
|
||||
AIControllable:T( "NewEngageRoute" )
|
||||
@@ -416,7 +418,7 @@ function _NewEngageRoute( AIControllable )
|
||||
end
|
||||
|
||||
|
||||
-- @param #AI_BAI_ZONE self
|
||||
--- @param #AI_BAI_ZONE self
|
||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
@@ -428,7 +430,7 @@ function AI_BAI_ZONE:onbeforeEngage( Controllable, From, Event, To )
|
||||
end
|
||||
end
|
||||
|
||||
-- @param #AI_BAI_ZONE self
|
||||
--- @param #AI_BAI_ZONE self
|
||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
@@ -477,7 +479,7 @@ function AI_BAI_ZONE:onafterTarget( Controllable, From, Event, To )
|
||||
end
|
||||
|
||||
|
||||
-- @param #AI_BAI_ZONE self
|
||||
--- @param #AI_BAI_ZONE self
|
||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
@@ -487,7 +489,7 @@ function AI_BAI_ZONE:onafterAbort( Controllable, From, Event, To )
|
||||
self:__Route( 1 )
|
||||
end
|
||||
|
||||
-- @param #AI_BAI_ZONE self
|
||||
--- @param #AI_BAI_ZONE self
|
||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
@@ -521,12 +523,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 +579,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
|
||||
)
|
||||
@@ -611,7 +613,7 @@ function AI_BAI_ZONE:onafterEngage( Controllable, From, Event, To,
|
||||
end
|
||||
|
||||
|
||||
-- @param #AI_BAI_ZONE self
|
||||
--- @param #AI_BAI_ZONE self
|
||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
@@ -622,7 +624,7 @@ function AI_BAI_ZONE:onafterAccomplish( Controllable, From, Event, To )
|
||||
end
|
||||
|
||||
|
||||
-- @param #AI_BAI_ZONE self
|
||||
--- @param #AI_BAI_ZONE self
|
||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
@@ -636,7 +638,7 @@ function AI_BAI_ZONE:onafterDestroy( Controllable, From, Event, To, EventData )
|
||||
end
|
||||
|
||||
|
||||
-- @param #AI_BAI_ZONE self
|
||||
--- @param #AI_BAI_ZONE self
|
||||
-- @param Core.Event#EVENTDATA EventData
|
||||
function AI_BAI_ZONE:OnEventDead( EventData )
|
||||
self:F( { "EventDead", EventData } )
|
||||
|
||||
@@ -27,14 +27,15 @@
|
||||
-- @module AI.AI_Balancer
|
||||
-- @image AI_Balancing.JPG
|
||||
|
||||
-- @type AI_BALANCER
|
||||
--- @type AI_BALANCER
|
||||
-- @field Core.Set#SET_CLIENT SetClient
|
||||
-- @field Core.Spawn#SPAWN SpawnAI
|
||||
-- @field Wrapper.Group#GROUP Test
|
||||
-- @extends Core.Fsm#FSM_SET
|
||||
|
||||
|
||||
--- Monitors and manages as many replacement AI groups as there are
|
||||
--- 
|
||||
--
|
||||
-- Monitors and manages as many replacement AI groups as there are
|
||||
-- CLIENTS in a SET\_CLIENT collection, which are not occupied by human players.
|
||||
-- In other words, use AI_BALANCER to simulate human behaviour by spawning in replacement AI in multi player missions.
|
||||
--
|
||||
@@ -220,16 +221,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
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
-- @module AI.AI_CAP
|
||||
-- @image AI_Combat_Air_Patrol.JPG
|
||||
|
||||
-- @type AI_CAP_ZONE
|
||||
--- @type AI_CAP_ZONE
|
||||
-- @field Wrapper.Controllable#CONTROLLABLE AIControllable The @{Wrapper.Controllable} patrolling.
|
||||
-- @field Core.Zone#ZONE_BASE TargetZone The @{Core.Zone} where the patrol needs to be executed.
|
||||
-- @extends AI.AI_Patrol#AI_PATROL_ZONE
|
||||
@@ -39,6 +39,8 @@
|
||||
--- Implements the core functions to patrol a @{Core.Zone} by an AI @{Wrapper.Controllable} or @{Wrapper.Group}
|
||||
-- and automatically engage any airborne enemies that are within a certain range or within a certain zone.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- The AI_CAP_ZONE is assigned a @{Wrapper.Group} and this must be done before the AI_CAP_ZONE process can be started using the **Start** event.
|
||||
@@ -344,7 +346,7 @@ function AI_CAP_ZONE:onafterStart( Controllable, From, Event, To )
|
||||
|
||||
end
|
||||
|
||||
-- @param AI.AI_CAP#AI_CAP_ZONE
|
||||
--- @param AI.AI_CAP#AI_CAP_ZONE
|
||||
-- @param Wrapper.Group#GROUP EngageGroup
|
||||
function AI_CAP_ZONE.EngageRoute( EngageGroup, Fsm )
|
||||
|
||||
@@ -355,7 +357,7 @@ function AI_CAP_ZONE.EngageRoute( EngageGroup, Fsm )
|
||||
end
|
||||
end
|
||||
|
||||
-- @param #AI_CAP_ZONE self
|
||||
--- @param #AI_CAP_ZONE self
|
||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
@@ -367,7 +369,7 @@ function AI_CAP_ZONE:onbeforeEngage( Controllable, From, Event, To )
|
||||
end
|
||||
end
|
||||
|
||||
-- @param #AI_CAP_ZONE self
|
||||
--- @param #AI_CAP_ZONE self
|
||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
@@ -395,7 +397,7 @@ function AI_CAP_ZONE:onafterDetected( Controllable, From, Event, To )
|
||||
end
|
||||
end
|
||||
|
||||
-- @param #AI_CAP_ZONE self
|
||||
--- @param #AI_CAP_ZONE self
|
||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
@@ -405,7 +407,7 @@ function AI_CAP_ZONE:onafterAbort( Controllable, From, Event, To )
|
||||
self:__Route( 1 )
|
||||
end
|
||||
|
||||
-- @param #AI_CAP_ZONE self
|
||||
--- @param #AI_CAP_ZONE self
|
||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
@@ -423,12 +425,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 +447,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
|
||||
)
|
||||
@@ -505,7 +507,7 @@ function AI_CAP_ZONE:onafterEngage( Controllable, From, Event, To )
|
||||
end
|
||||
end
|
||||
|
||||
-- @param #AI_CAP_ZONE self
|
||||
--- @param #AI_CAP_ZONE self
|
||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
@@ -515,7 +517,7 @@ function AI_CAP_ZONE:onafterAccomplish( Controllable, From, Event, To )
|
||||
self:SetDetectionOff()
|
||||
end
|
||||
|
||||
-- @param #AI_CAP_ZONE self
|
||||
--- @param #AI_CAP_ZONE self
|
||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
@@ -528,7 +530,7 @@ function AI_CAP_ZONE:onafterDestroy( Controllable, From, Event, To, EventData )
|
||||
end
|
||||
end
|
||||
|
||||
-- @param #AI_CAP_ZONE self
|
||||
--- @param #AI_CAP_ZONE self
|
||||
-- @param Core.Event#EVENTDATA EventData
|
||||
function AI_CAP_ZONE:OnEventDead( EventData )
|
||||
self:F( { "EventDead", EventData } )
|
||||
|
||||
@@ -38,6 +38,9 @@
|
||||
-- @extends AI.AI_Patrol#AI_PATROL_ZONE
|
||||
|
||||
--- Implements the core functions to provide Close Air Support in an Engage @{Core.Zone} by an AIR @{Wrapper.Controllable} or @{Wrapper.Group}.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- The AI_CAS_ZONE runs a process. It holds an AI in a Patrol Zone and when the AI is commanded to engage, it will fly to an Engage Zone.
|
||||
--
|
||||
-- 
|
||||
@@ -162,6 +165,7 @@ function AI_CAS_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
|
||||
-- @return #boolean Return false to cancel Transition.
|
||||
|
||||
--- OnAfter Transition Handler for Event Engage.
|
||||
@@ -362,7 +366,7 @@ function AI_CAS_ZONE:onafterStart( Controllable, From, Event, To )
|
||||
self:SetDetectionDeactivated() -- When not engaging, set the detection off.
|
||||
end
|
||||
|
||||
-- @param AI.AI_CAS#AI_CAS_ZONE
|
||||
--- @param AI.AI_CAS#AI_CAS_ZONE
|
||||
-- @param Wrapper.Group#GROUP EngageGroup
|
||||
function AI_CAS_ZONE.EngageRoute( EngageGroup, Fsm )
|
||||
|
||||
@@ -374,7 +378,7 @@ function AI_CAS_ZONE.EngageRoute( EngageGroup, Fsm )
|
||||
end
|
||||
|
||||
|
||||
-- @param #AI_CAS_ZONE self
|
||||
--- @param #AI_CAS_ZONE self
|
||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
@@ -386,7 +390,7 @@ function AI_CAS_ZONE:onbeforeEngage( Controllable, From, Event, To )
|
||||
end
|
||||
end
|
||||
|
||||
-- @param #AI_CAS_ZONE self
|
||||
--- @param #AI_CAS_ZONE self
|
||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
@@ -419,7 +423,7 @@ function AI_CAS_ZONE:onafterTarget( Controllable, From, Event, To )
|
||||
end
|
||||
|
||||
|
||||
-- @param #AI_CAS_ZONE self
|
||||
--- @param #AI_CAS_ZONE self
|
||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
@@ -429,7 +433,7 @@ function AI_CAS_ZONE:onafterAbort( Controllable, From, Event, To )
|
||||
self:__Route( 1 )
|
||||
end
|
||||
|
||||
-- @param #AI_CAS_ZONE self
|
||||
--- @param #AI_CAS_ZONE self
|
||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
@@ -465,12 +469,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 +511,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
|
||||
)
|
||||
@@ -529,7 +533,7 @@ function AI_CAS_ZONE:onafterEngage( Controllable, From, Event, To,
|
||||
end
|
||||
|
||||
|
||||
-- @param #AI_CAS_ZONE self
|
||||
--- @param #AI_CAS_ZONE self
|
||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
@@ -540,7 +544,7 @@ function AI_CAS_ZONE:onafterAccomplish( Controllable, From, Event, To )
|
||||
end
|
||||
|
||||
|
||||
-- @param #AI_CAS_ZONE self
|
||||
--- @param #AI_CAS_ZONE self
|
||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
@@ -554,7 +558,7 @@ function AI_CAS_ZONE:onafterDestroy( Controllable, From, Event, To, EventData )
|
||||
end
|
||||
|
||||
|
||||
-- @param #AI_CAS_ZONE self
|
||||
--- @param #AI_CAS_ZONE self
|
||||
-- @param Core.Event#EVENTDATA EventData
|
||||
function AI_CAS_ZONE:OnEventDead( EventData )
|
||||
self:F( { "EventDead", EventData } )
|
||||
|
||||
@@ -9,12 +9,14 @@
|
||||
-- @module AI.AI_Cargo
|
||||
-- @image Cargo.JPG
|
||||
|
||||
-- @type AI_CARGO
|
||||
--- @type AI_CARGO
|
||||
-- @extends Core.Fsm#FSM_CONTROLLABLE
|
||||
|
||||
|
||||
--- Base class for the dynamic cargo handling capability for AI groups.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- Carriers can be mobilized to intelligently transport infantry and other cargo within the simulation.
|
||||
-- The AI_CARGO module uses the @{Cargo.Cargo} capabilities within the MOOSE framework.
|
||||
-- CARGO derived objects must be declared within the mission to make the AI_CARGO object recognize the cargo.
|
||||
|
||||
@@ -9,12 +9,14 @@
|
||||
-- @module AI.AI_Cargo_APC
|
||||
-- @image AI_Cargo_Dispatching_For_APC.JPG
|
||||
|
||||
-- @type AI_CARGO_APC
|
||||
--- @type AI_CARGO_APC
|
||||
-- @extends AI.AI_Cargo#AI_CARGO
|
||||
|
||||
|
||||
--- Brings a dynamic cargo handling capability for an AI vehicle group.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- Armoured Personnel Carriers (APC), Trucks, Jeeps and other ground based carrier equipment can be mobilized to intelligently transport infantry and other cargo within the simulation.
|
||||
--
|
||||
-- The AI_CARGO_APC class uses the @{Cargo.Cargo} capabilities within the MOOSE framework.
|
||||
|
||||
@@ -9,11 +9,13 @@
|
||||
-- @module AI.AI_Cargo_Airplane
|
||||
-- @image AI_Cargo_Dispatching_For_Airplanes.JPG
|
||||
|
||||
-- @type AI_CARGO_AIRPLANE
|
||||
--- @type AI_CARGO_AIRPLANE
|
||||
-- @extends Core.Fsm#FSM_CONTROLLABLE
|
||||
|
||||
|
||||
--- Brings a dynamic cargo handling capability for an AI airplane group.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- Airplane carrier equipment can be mobilized to intelligently transport infantry and other cargo within the simulation between airbases.
|
||||
--
|
||||
@@ -440,7 +442,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
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- # The dispatcher concept.
|
||||
--
|
||||
-- Carrier equipment can be mobilized to intelligently transport infantry and other cargo within the simulation.
|
||||
|
||||
@@ -30,12 +30,14 @@
|
||||
-- @module AI.AI_Cargo_Dispatcher_APC
|
||||
-- @image AI_Cargo_Dispatching_For_APC.JPG
|
||||
|
||||
-- @type AI_CARGO_DISPATCHER_APC
|
||||
--- @type AI_CARGO_DISPATCHER_APC
|
||||
-- @extends AI.AI_Cargo_Dispatcher#AI_CARGO_DISPATCHER
|
||||
|
||||
|
||||
--- A dynamic cargo transportation capability for AI groups.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- Armoured Personnel APCs (APC), Trucks, Jeeps and other carrier equipment can be mobilized to intelligently transport infantry and other cargo within the simulation.
|
||||
--
|
||||
-- The AI_CARGO_DISPATCHER_APC module is derived from the AI_CARGO_DISPATCHER module.
|
||||
|
||||
@@ -24,12 +24,14 @@
|
||||
-- @image AI_Cargo_Dispatching_For_Airplanes.JPG
|
||||
|
||||
|
||||
-- @type AI_CARGO_DISPATCHER_AIRPLANE
|
||||
--- @type AI_CARGO_DISPATCHER_AIRPLANE
|
||||
-- @extends AI.AI_Cargo_Dispatcher#AI_CARGO_DISPATCHER
|
||||
|
||||
|
||||
--- Brings a dynamic cargo handling capability for AI groups.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- Airplanes can be mobilized to intelligently transport infantry and other cargo within the simulation.
|
||||
--
|
||||
-- The AI_CARGO_DISPATCHER_AIRPLANE module is derived from the AI_CARGO_DISPATCHER module.
|
||||
|
||||
@@ -25,12 +25,14 @@
|
||||
-- @module AI.AI_Cargo_Dispatcher_Helicopter
|
||||
-- @image AI_Cargo_Dispatching_For_Helicopters.JPG
|
||||
|
||||
-- @type AI_CARGO_DISPATCHER_HELICOPTER
|
||||
--- @type AI_CARGO_DISPATCHER_HELICOPTER
|
||||
-- @extends AI.AI_Cargo_Dispatcher#AI_CARGO_DISPATCHER
|
||||
|
||||
|
||||
--- A dynamic cargo handling capability for AI helicopter groups.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- Helicopters can be mobilized to intelligently transport infantry and other cargo within the simulation.
|
||||
--
|
||||
--
|
||||
|
||||
@@ -23,12 +23,14 @@
|
||||
-- @module AI.AI_Cargo_Dispatcher_Ship
|
||||
-- @image AI_Cargo_Dispatcher.JPG
|
||||
|
||||
-- @type AI_CARGO_DISPATCHER_SHIP
|
||||
--- @type AI_CARGO_DISPATCHER_SHIP
|
||||
-- @extends AI.AI_Cargo_Dispatcher#AI_CARGO_DISPATCHER
|
||||
|
||||
|
||||
--- A dynamic cargo transportation capability for AI groups.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- Naval vessels can be mobilized to semi-intelligently transport cargo within the simulation.
|
||||
--
|
||||
-- The AI_CARGO_DISPATCHER_SHIP module is derived from the AI_CARGO_DISPATCHER module.
|
||||
@@ -160,7 +162,7 @@ AI_CARGO_DISPATCHER_SHIP = {
|
||||
-- local SetPickupZones = SET_ZONE:New():FilterPrefixes( "Pickup" ):FilterStart()
|
||||
-- local SetDeployZones = SET_ZONE:New():FilterPrefixes( "Deploy" ):FilterStart()
|
||||
-- NEED MORE THOUGHT - ShippingLane is part of Warehouse.......
|
||||
-- local ShippingLane = SET_GROUP:New():FilterPrefixes( "ShippingLane" ):FilterOnce():GetSetObjects()
|
||||
-- local ShippingLane = GROUP:New():FilterPrefixes( "ShippingLane" ):FilterStart()
|
||||
--
|
||||
-- AICargoDispatcherShip = AI_CARGO_DISPATCHER_SHIP:New( SetShip, SetCargoInfantry, SetPickupZones, SetDeployZones, ShippingLane )
|
||||
-- AICargoDispatcherShip:Start()
|
||||
|
||||
@@ -9,12 +9,14 @@
|
||||
-- @module AI.AI_Cargo_Helicopter
|
||||
-- @image AI_Cargo_Dispatching_For_Helicopters.JPG
|
||||
|
||||
-- @type AI_CARGO_HELICOPTER
|
||||
--- @type AI_CARGO_HELICOPTER
|
||||
-- @extends Core.Fsm#FSM_CONTROLLABLE
|
||||
|
||||
|
||||
--- Brings a dynamic cargo handling capability for an AI helicopter group.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- Helicopter carriers can be mobilized to intelligently transport infantry and other cargo within the simulation.
|
||||
--
|
||||
-- The AI_CARGO_HELICOPTER class uses the @{Cargo.Cargo} capabilities within the MOOSE framework.
|
||||
@@ -287,7 +289,7 @@ function AI_CARGO_HELICOPTER:SetLandingSpeedAndHeight(speed, height)
|
||||
return self
|
||||
end
|
||||
|
||||
-- @param #AI_CARGO_HELICOPTER self
|
||||
--- @param #AI_CARGO_HELICOPTER self
|
||||
-- @param Wrapper.Group#GROUP Helicopter
|
||||
-- @param From
|
||||
-- @param Event
|
||||
@@ -326,7 +328,7 @@ function AI_CARGO_HELICOPTER:onafterLanded( Helicopter, From, Event, To )
|
||||
|
||||
end
|
||||
|
||||
-- @param #AI_CARGO_HELICOPTER self
|
||||
--- @param #AI_CARGO_HELICOPTER self
|
||||
-- @param Wrapper.Group#GROUP Helicopter
|
||||
-- @param From
|
||||
-- @param Event
|
||||
@@ -367,8 +369,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 +382,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
|
||||
)
|
||||
@@ -409,7 +411,7 @@ function AI_CARGO_HELICOPTER:onafterQueue( Helicopter, From, Event, To, Coordina
|
||||
end
|
||||
|
||||
|
||||
-- @param #AI_CARGO_HELICOPTER self
|
||||
--- @param #AI_CARGO_HELICOPTER self
|
||||
-- @param Wrapper.Group#GROUP Helicopter
|
||||
-- @param From
|
||||
-- @param Event
|
||||
@@ -427,7 +429,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 +498,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 +565,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 +575,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 +633,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 +641,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
|
||||
|
||||
|
||||
@@ -9,11 +9,13 @@
|
||||
-- @module AI.AI_Cargo_Ship
|
||||
-- @image AI_Cargo_Dispatcher.JPG
|
||||
|
||||
-- @type AI_CARGO_SHIP
|
||||
--- @type AI_CARGO_SHIP
|
||||
-- @extends AI.AI_Cargo#AI_CARGO
|
||||
|
||||
--- Brings a dynamic cargo handling capability for an AI naval group.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- Naval ships can be utilized to transport cargo around the map following naval shipping lanes.
|
||||
-- The AI_CARGO_SHIP class uses the @{Cargo.Cargo} capabilities within the MOOSE framework.
|
||||
-- @{Cargo.Cargo} must be declared within the mission or warehouse to make the AI_CARGO_SHIP recognize the cargo.
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
--
|
||||
-- Allows you to interact with escorting AI on your flight and take the lead.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- Each escorting group can be commanded with a complete set of radio commands (radio menu in your flight, and then F10).
|
||||
--
|
||||
-- The radio commands will vary according the category of the group. The richest set of commands are with helicopters and airPlanes.
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
|
||||
@@ -15,12 +15,14 @@
|
||||
-- @image MOOSE.JPG
|
||||
|
||||
|
||||
-- @type AI_ESCORT_DISPATCHER_REQUEST
|
||||
--- @type AI_ESCORT_DISPATCHER_REQUEST
|
||||
-- @extends Core.Fsm#FSM
|
||||
|
||||
|
||||
--- Models the assignment of AI escorts to player flights upon request using the radio menu.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
@@ -33,7 +35,7 @@ AI_ESCORT_DISPATCHER_REQUEST = {
|
||||
ClassName = "AI_ESCORT_DISPATCHER_REQUEST",
|
||||
}
|
||||
|
||||
-- @field #list
|
||||
--- @field #list
|
||||
AI_ESCORT_DISPATCHER_REQUEST.AI_Escorts = {}
|
||||
|
||||
|
||||
@@ -80,7 +82,7 @@ function AI_ESCORT_DISPATCHER_REQUEST:onafterStart( From, Event, To )
|
||||
|
||||
end
|
||||
|
||||
-- @param #AI_ESCORT_DISPATCHER_REQUEST self
|
||||
--- @param #AI_ESCORT_DISPATCHER_REQUEST self
|
||||
-- @param Core.Event#EVENTDATA EventData
|
||||
function AI_ESCORT_DISPATCHER_REQUEST:OnEventExit( EventData )
|
||||
|
||||
@@ -97,7 +99,7 @@ function AI_ESCORT_DISPATCHER_REQUEST:OnEventExit( EventData )
|
||||
|
||||
end
|
||||
|
||||
-- @param #AI_ESCORT_DISPATCHER_REQUEST self
|
||||
--- @param #AI_ESCORT_DISPATCHER_REQUEST self
|
||||
-- @param Core.Event#EVENTDATA EventData
|
||||
function AI_ESCORT_DISPATCHER_REQUEST:OnEventBirth( EventData )
|
||||
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
--
|
||||
-- Allows you to interact with escorting AI on your flight and take the lead.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- Each escorting group can be commanded with a complete set of radio commands (radio menu in your flight, and then F10).
|
||||
--
|
||||
-- The radio commands will vary according the category of the group. The richest set of commands are with helicopters and airPlanes.
|
||||
@@ -136,12 +138,12 @@
|
||||
--
|
||||
-- Escort groups can have their own mission. This menu item will allow the escort group to resume their Mission from a given waypoint.
|
||||
-- Note that this is really fantastic, as you now have the dynamic of taking control of the escort groups, and allowing them to resume their path or mission.
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Authors: **FlightControl**
|
||||
@@ -153,7 +155,7 @@
|
||||
|
||||
|
||||
|
||||
-- @type AI_ESCORT_REQUEST
|
||||
--- @type AI_ESCORT_REQUEST
|
||||
-- @extends AI.AI_Escort#AI_ESCORT
|
||||
|
||||
--- AI_ESCORT_REQUEST class
|
||||
@@ -228,7 +230,7 @@ function AI_ESCORT_REQUEST:New( EscortUnit, EscortSpawn, EscortAirbase, EscortNa
|
||||
return self
|
||||
end
|
||||
|
||||
-- @param #AI_ESCORT_REQUEST self
|
||||
--- @param #AI_ESCORT_REQUEST self
|
||||
function AI_ESCORT_REQUEST:SpawnEscort()
|
||||
|
||||
local EscortGroup = self.EscortSpawn:SpawnAtAirbase( self.EscortAirbase, SPAWN.Takeoff.Hot )
|
||||
@@ -253,7 +255,7 @@ function AI_ESCORT_REQUEST:SpawnEscort()
|
||||
self:_InitEscortMenus( EscortGroup )
|
||||
self:_InitEscortRoute( EscortGroup )
|
||||
|
||||
-- @param #AI_ESCORT self
|
||||
--- @param #AI_ESCORT self
|
||||
-- @param Core.Event#EVENTDATA EventData
|
||||
function EscortGroup:OnEventDeadOrCrash( EventData )
|
||||
self:F( { "EventDead", EventData } )
|
||||
@@ -268,7 +270,7 @@ function AI_ESCORT_REQUEST:SpawnEscort()
|
||||
|
||||
end
|
||||
|
||||
-- @param #AI_ESCORT_REQUEST self
|
||||
--- @param #AI_ESCORT_REQUEST self
|
||||
-- @param Core.Set#SET_GROUP EscortGroupSet
|
||||
function AI_ESCORT_REQUEST:onafterStart( EscortGroupSet )
|
||||
|
||||
@@ -290,14 +292,14 @@ function AI_ESCORT_REQUEST:onafterStart( EscortGroupSet )
|
||||
|
||||
end
|
||||
|
||||
-- @param #AI_ESCORT_REQUEST self
|
||||
--- @param #AI_ESCORT_REQUEST self
|
||||
-- @param Core.Set#SET_GROUP EscortGroupSet
|
||||
function AI_ESCORT_REQUEST:onafterStop( EscortGroupSet )
|
||||
|
||||
self:F()
|
||||
|
||||
EscortGroupSet:ForEachGroup(
|
||||
-- @param Core.Group#GROUP EscortGroup
|
||||
--- @param Wrapper.Group#GROUP EscortGroup
|
||||
function( EscortGroup )
|
||||
EscortGroup:WayPointInitialize()
|
||||
|
||||
|
||||
@@ -34,12 +34,14 @@
|
||||
-- @field Core.Scheduler#SCHEDULER FollowScheduler The instance of the SCHEDULER class.
|
||||
-- @field #number FollowDistance The current follow distance.
|
||||
-- @field #boolean ReportTargets If true, nearby targets are reported.
|
||||
-- @Field DCSTypes#AI.Option.Air.val.ROE OptionROE Which ROE is set to the FollowGroup.
|
||||
-- @field DCSTypes#AI.Option.Air.val.REACTION_ON_THREAT OptionReactionOnThreat Which REACTION_ON_THREAT is set to the FollowGroup.
|
||||
-- @field DCS#AI.Option.Air.val.ROE OptionROE Which ROE is set to the FollowGroup.
|
||||
-- @field DCS#AI.Option.Air.val.REACTION_ON_THREAT OptionReactionOnThreat Which REACTION_ON_THREAT is set to the FollowGroup.
|
||||
-- @field #number dtFollow Time step between position updates.
|
||||
|
||||
|
||||
--- Build large formations, make AI follow a @{Wrapper.Client#CLIENT} (player) leader or a @{Wrapper.Unit#UNIT} (AI) leader.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- AI_FORMATION makes AI @{Wrapper.Group#GROUP}s fly in formation of various compositions.
|
||||
-- The AI_FORMATION class models formations in a different manner than the internal DCS formation logic!!!
|
||||
@@ -92,12 +94,12 @@
|
||||
-- local LargeFormation = AI_FORMATION:New( LeaderUnit, FollowGroupSet, "Center Wing Formation", "Briefing" )
|
||||
-- LargeFormation:FormationCenterWing( 500, 50, 0, 250, 250 )
|
||||
-- LargeFormation:__Start( 1 )
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
-- @field #AI_FORMATION
|
||||
AI_FORMATION = {
|
||||
ClassName = "AI_FORMATION",
|
||||
@@ -117,7 +119,7 @@ AI_FORMATION = {
|
||||
|
||||
AI_FORMATION.__Enum = {}
|
||||
|
||||
-- @type AI_FORMATION.__Enum.Formation
|
||||
--- @type AI_FORMATION.__Enum.Formation
|
||||
-- @field #number None
|
||||
-- @field #number Line
|
||||
-- @field #number Trail
|
||||
@@ -142,7 +144,7 @@ AI_FORMATION.__Enum.Formation = {
|
||||
Box = 10,
|
||||
}
|
||||
|
||||
-- @type AI_FORMATION.__Enum.Mode
|
||||
--- @type AI_FORMATION.__Enum.Mode
|
||||
-- @field #number Mission
|
||||
-- @field #number Formation
|
||||
AI_FORMATION.__Enum.Mode = {
|
||||
@@ -152,13 +154,12 @@ AI_FORMATION.__Enum.Mode = {
|
||||
Reconnaissance = "R",
|
||||
}
|
||||
|
||||
-- @type AI_FORMATION.__Enum.ReportType
|
||||
--- @type AI_FORMATION.__Enum.ReportType
|
||||
-- @field #number All
|
||||
-- @field #number Airborne
|
||||
-- @field #number GroundRadar
|
||||
-- @field #number Ground
|
||||
AI_FORMATION.__Enum.ReportType = {
|
||||
All = "*",
|
||||
Airborne = "A",
|
||||
GroundRadar = "R",
|
||||
Ground = "G",
|
||||
@@ -725,7 +726,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 +878,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 +937,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 )
|
||||
@@ -996,7 +997,7 @@ function AI_FORMATION:SetFlightModeMission( FollowGroup )
|
||||
FollowGroup:SetState( FollowGroup, "Mode", self.__Enum.Mode.Mission )
|
||||
else
|
||||
self.FollowGroupSet:ForSomeGroupAlive(
|
||||
-- @param Core.Group#GROUP EscortGroup
|
||||
--- @param Wrapper.Group#GROUP EscortGroup
|
||||
function( FollowGroup )
|
||||
FollowGroup:SetState( FollowGroup, "PreviousMode", FollowGroup:GetState( FollowGroup, "Mode" ) )
|
||||
FollowGroup:SetState( FollowGroup, "Mode", self.__Enum.Mode.Mission )
|
||||
@@ -1020,7 +1021,7 @@ function AI_FORMATION:SetFlightModeAttack( FollowGroup )
|
||||
FollowGroup:SetState( FollowGroup, "Mode", self.__Enum.Mode.Attack )
|
||||
else
|
||||
self.FollowGroupSet:ForSomeGroupAlive(
|
||||
-- @param Core.Group#GROUP EscortGroup
|
||||
--- @param Wrapper.Group#GROUP EscortGroup
|
||||
function( FollowGroup )
|
||||
FollowGroup:SetState( FollowGroup, "PreviousMode", FollowGroup:GetState( FollowGroup, "Mode" ) )
|
||||
FollowGroup:SetState( FollowGroup, "Mode", self.__Enum.Mode.Attack )
|
||||
@@ -1044,7 +1045,7 @@ function AI_FORMATION:SetFlightModeFormation( FollowGroup )
|
||||
FollowGroup:SetState( FollowGroup, "Mode", self.__Enum.Mode.Formation )
|
||||
else
|
||||
self.FollowGroupSet:ForSomeGroupAlive(
|
||||
-- @param Core.Group#GROUP EscortGroup
|
||||
--- @param Wrapper.Group#GROUP EscortGroup
|
||||
function( FollowGroup )
|
||||
FollowGroup:SetState( FollowGroup, "PreviousMode", FollowGroup:GetState( FollowGroup, "Mode" ) )
|
||||
FollowGroup:SetState( FollowGroup, "Mode", self.__Enum.Mode.Formation )
|
||||
@@ -1222,7 +1223,6 @@ function AI_FORMATION:FollowMe(FollowGroup, ClientUnit, CT1, CV1, CT2, CV2)
|
||||
local CVI = {
|
||||
x = CV2.x + CS * 10 * math.sin(Ca),
|
||||
y = GH2.y + Inclination, -- + FollowFormation.y,
|
||||
--y = GH2.y,
|
||||
z = CV2.z + CS * 10 * math.cos(Ca),
|
||||
}
|
||||
|
||||
|
||||
@@ -48,6 +48,8 @@
|
||||
|
||||
--- Implements the core functions to patrol a @{Core.Zone} by an AI @{Wrapper.Controllable} or @{Wrapper.Group}.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- The AI_PATROL_ZONE is assigned a @{Wrapper.Group} and this must be done before the AI_PATROL_ZONE process can be started using the **Start** event.
|
||||
@@ -751,12 +753,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 +769,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 +794,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 +892,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
|
||||
)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
--- **Actions** - ACT_ACCOUNT_ classes **account for** (detect, count & report) various DCS events occurring on UNITs.
|
||||
--
|
||||
-- 
|
||||
-- 
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
@@ -8,9 +8,11 @@
|
||||
-- @image MOOSE.JPG
|
||||
|
||||
do -- ACT_ACCOUNT
|
||||
|
||||
|
||||
--- # @{#ACT_ACCOUNT} FSM class, extends @{Core.Fsm#FSM_PROCESS}
|
||||
--
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- ## ACT_ACCOUNT state machine:
|
||||
--
|
||||
-- This class is a state machine: it manages a process that is triggered by events causing state transitions to occur.
|
||||
@@ -133,7 +135,7 @@ do -- ACT_ACCOUNT
|
||||
-- @param #string Event
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
function ACT_ACCOUNT:onafterEvent( ProcessUnit, From, Event, To, Event )
|
||||
function ACT_ACCOUNT:onafterEvent( ProcessUnit, From, Event, To )
|
||||
|
||||
self:__NoMore( 1 )
|
||||
end
|
||||
@@ -274,7 +276,7 @@ do -- ACT_ACCOUNT_DEADS
|
||||
|
||||
--- DCS Events
|
||||
|
||||
-- @param #ACT_ACCOUNT_DEADS self
|
||||
--- @param #ACT_ACCOUNT_DEADS self
|
||||
-- @param Core.Event#EVENTDATA EventData
|
||||
function ACT_ACCOUNT_DEADS:OnEventHit( EventData )
|
||||
self:T( { "EventDead", EventData } )
|
||||
@@ -285,7 +287,7 @@ do -- ACT_ACCOUNT_DEADS
|
||||
end
|
||||
end
|
||||
|
||||
-- @param #ACT_ACCOUNT_DEADS self
|
||||
--- @param #ACT_ACCOUNT_DEADS self
|
||||
-- @param Core.Event#EVENTDATA EventData
|
||||
function ACT_ACCOUNT_DEADS:onfuncEventDead( EventData )
|
||||
self:T( { "EventDead", EventData } )
|
||||
@@ -297,7 +299,7 @@ do -- ACT_ACCOUNT_DEADS
|
||||
|
||||
--- DCS Events
|
||||
|
||||
-- @param #ACT_ACCOUNT_DEADS self
|
||||
--- @param #ACT_ACCOUNT_DEADS self
|
||||
-- @param Core.Event#EVENTDATA EventData
|
||||
function ACT_ACCOUNT_DEADS:onfuncEventCrash( EventData )
|
||||
self:T( { "EventDead", EventData } )
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
--- (SP) (MP) (FSM) Accept or reject process for player (task) assignments.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- # @{#ACT_ASSIGN} FSM template class, extends @{Core.Fsm#FSM_PROCESS}
|
||||
--
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
--- (SP) (MP) (FSM) Route AI or players through waypoints or to zones.
|
||||
--
|
||||
-- 
|
||||
-- ## ACT_ASSIST state machine:
|
||||
--
|
||||
-- This class is a state machine: it manages a process that is triggered by events causing state transitions to occur.
|
||||
@@ -200,7 +201,7 @@ do -- ACT_ASSIST_SMOKE_TARGETS_ZONE
|
||||
function ACT_ASSIST_SMOKE_TARGETS_ZONE:onenterSmoking( ProcessUnit, From, Event, To )
|
||||
|
||||
self.TargetSetUnit:ForEachUnit(
|
||||
-- @param Wrapper.Unit#UNIT SmokeUnit
|
||||
--- @param Wrapper.Unit#UNIT SmokeUnit
|
||||
function( SmokeUnit )
|
||||
if math.random( 1, ( 100 * self.TargetSetUnit:Count() ) / 4 ) <= 100 then
|
||||
SCHEDULER:New( self,
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- # @{#ACT_ROUTE} FSM class, extends @{Core.Fsm#FSM_PROCESS}
|
||||
--
|
||||
-- ## ACT_ROUTE state machine:
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- # 1) MOOSE Cargo System.
|
||||
--
|
||||
-- #### Those who have used the mission editor, know that the DCS mission editor provides cargo facilities.
|
||||
@@ -275,14 +277,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 +309,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 +469,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 +899,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 +1096,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 )
|
||||
|
||||
@@ -22,6 +22,9 @@ do -- CARGO_CRATE
|
||||
-- @type CARGO_CRATE
|
||||
-- @extends Cargo.Cargo#CARGO_REPRESENTABLE
|
||||
|
||||
---
|
||||
-- 
|
||||
--
|
||||
--- Defines a cargo that is represented by a UNIT object within the simulator, and can be transported by a carrier.
|
||||
-- Use the event functions as described above to Load, UnLoad, Board, UnBoard the CARGO\_CRATE objects to and from carriers.
|
||||
--
|
||||
@@ -78,7 +81,7 @@ do -- CARGO_CRATE
|
||||
return self
|
||||
end
|
||||
|
||||
-- @param #CARGO_CRATE self
|
||||
--- @param #CARGO_CRATE self
|
||||
-- @param Core.Event#EVENTDATA EventData
|
||||
function CARGO_CRATE:OnEventCargoDead( EventData )
|
||||
|
||||
@@ -114,7 +117,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 } )
|
||||
|
||||
|
||||
@@ -22,9 +22,12 @@ 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.
|
||||
--
|
||||
-- 
|
||||
-- The cargo can be Loaded, UnLoaded, Boarded, UnBoarded to and from Carriers.
|
||||
--
|
||||
-- The above cargo classes are used by the following AI_CARGO_ classes to allow AI groups to transport cargo:
|
||||
@@ -410,7 +413,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 +456,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 +494,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 } )
|
||||
|
||||
@@ -598,7 +601,7 @@ do -- CARGO_GROUP
|
||||
end
|
||||
|
||||
|
||||
--- Get the underlying GROUP object from the CARGO_GROUP.
|
||||
--- Get the amount of cargo units in the group.
|
||||
-- @param #CARGO_GROUP self
|
||||
-- @return #CARGO_GROUP
|
||||
function CARGO_GROUP:GetGroup( Cargo )
|
||||
@@ -771,3 +774,4 @@ do -- CARGO_GROUP
|
||||
|
||||
|
||||
end -- CARGO_GROUP
|
||||
|
||||
|
||||
@@ -32,6 +32,8 @@ do -- CARGO_SLINGLOAD
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
@@ -72,7 +74,7 @@ do -- CARGO_SLINGLOAD
|
||||
end
|
||||
|
||||
|
||||
-- @param #CARGO_SLINGLOAD self
|
||||
--- @param #CARGO_SLINGLOAD self
|
||||
-- @param Core.Event#EVENTDATA EventData
|
||||
function CARGO_SLINGLOAD:OnEventCargoDead( EventData )
|
||||
|
||||
|
||||
@@ -30,6 +30,8 @@ do -- CARGO_UNIT
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
@@ -72,7 +74,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 +147,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 +173,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 +199,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 } )
|
||||
|
||||
|
||||
@@ -974,7 +974,7 @@ do -- Scheduling
|
||||
-- @param #BASE self
|
||||
-- @param #number Start Specifies the amount of seconds that will be waited before the scheduling is started, and the event function is called.
|
||||
-- @param #function SchedulerFunction The event function to be called when a timer event occurs. The event function needs to accept the parameters specified in SchedulerArguments.
|
||||
-- @param #table ... Optional arguments that can be given as part of scheduler. The arguments need to be given as a table { param1, param 2, ... }.
|
||||
-- @param ... Optional arguments that can be given as part of scheduler. The arguments need to be given as a table { param1, param 2, ... }.
|
||||
-- @return #string The Schedule ID of the planned schedule.
|
||||
function BASE:ScheduleOnce( Start, SchedulerFunction, ... )
|
||||
|
||||
|
||||
@@ -1,924 +0,0 @@
|
||||
--- **Core** - Client Menu Management.
|
||||
--
|
||||
-- **Main Features:**
|
||||
--
|
||||
-- * For complex, non-static menu structures
|
||||
-- * Lightweigt implementation as alternative to MENU
|
||||
-- * Separation of menu tree creation from menu on the clients's side
|
||||
-- * Works with a SET_CLIENT set of clients
|
||||
-- * Allow manipulation of the shadow tree in various ways
|
||||
-- * Push to all or only one client
|
||||
-- * Change entries' menu text
|
||||
-- * Option to make an entry usable once only across all clients
|
||||
-- * Auto appends GROUP and CLIENT objects to menu calls
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **applevangelist**
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module Core.ClientMenu
|
||||
-- @image Core_Menu.JPG
|
||||
-- last change: Jan 2025
|
||||
|
||||
-- TODO
|
||||
----------------------------------------------------------------------------------------------------------------
|
||||
--
|
||||
-- CLIENTMENU
|
||||
--
|
||||
----------------------------------------------------------------------------------------------------------------
|
||||
|
||||
---
|
||||
-- @type CLIENTMENU
|
||||
-- @field #string ClassName Class Name
|
||||
-- @field #string lid Lid for log entries
|
||||
-- @field #string version Version string
|
||||
-- @field #string name Name
|
||||
-- @field #string groupname Group name
|
||||
-- @field #table path
|
||||
-- @field #table parentpath
|
||||
-- @field #CLIENTMENU Parent
|
||||
-- @field Wrapper.Client#CLIENT client
|
||||
-- @field #number GroupID Group ID
|
||||
-- @field #number ID Entry ID
|
||||
-- @field Wrapper.Group#GROUP group
|
||||
-- @field #string UUID Unique ID based on path+name
|
||||
-- @field #string Function
|
||||
-- @field #table Functionargs
|
||||
-- @field #table Children
|
||||
-- @field #boolean Once
|
||||
-- @field #boolean Generic
|
||||
-- @field #boolean debug
|
||||
-- @field #CLIENTMENUMANAGER Controller
|
||||
-- @field #active boolean
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
---
|
||||
-- @field #CLIENTMENU
|
||||
CLIENTMENU = {
|
||||
ClassName = "CLIENTMENU",
|
||||
lid = "",
|
||||
version = "0.1.3",
|
||||
name = nil,
|
||||
path = nil,
|
||||
group = nil,
|
||||
client = nil,
|
||||
GroupID = nil,
|
||||
Children = {},
|
||||
Once = false,
|
||||
Generic = false,
|
||||
debug = false,
|
||||
Controller = nil,
|
||||
groupname = nil,
|
||||
active = false,
|
||||
}
|
||||
|
||||
---
|
||||
-- @field #CLIENTMENU_ID
|
||||
CLIENTMENU_ID = 0
|
||||
|
||||
--- Create an new CLIENTMENU object.
|
||||
-- @param #CLIENTMENU self
|
||||
-- @param Wrapper.Client#CLIENT Client The client for whom this entry is. Leave as nil for a generic entry.
|
||||
-- @param #string Text Text of the F10 menu entry.
|
||||
-- @param #CLIENTMENU Parent The parent menu entry.
|
||||
-- @param #string Function (optional) Function to call when the entry is used.
|
||||
-- @param ... (optional) Arguments for the Function, comma separated
|
||||
-- @return #CLIENTMENU self
|
||||
function CLIENTMENU:NewEntry(Client,Text,Parent,Function,...)
|
||||
-- Inherit everything from BASE class.
|
||||
local self=BASE:Inherit(self, BASE:New()) -- #CLIENTMENU
|
||||
CLIENTMENU_ID = CLIENTMENU_ID + 1
|
||||
self.ID = CLIENTMENU_ID
|
||||
if Client then
|
||||
self.group = Client:GetGroup()
|
||||
self.client = Client
|
||||
self.GroupID = self.group:GetID()
|
||||
self.groupname = self.group:GetName() or "Unknown Groupname"
|
||||
else
|
||||
self.Generic = true
|
||||
end
|
||||
self.name = Text or "unknown entry"
|
||||
if Parent then
|
||||
if Parent:IsInstanceOf("MENU_BASE") then
|
||||
self.parentpath = Parent.MenuPath
|
||||
else
|
||||
self.parentpath = Parent:GetPath()
|
||||
Parent:AddChild(self)
|
||||
end
|
||||
end
|
||||
self.Parent = Parent
|
||||
self.Function = Function
|
||||
self.Functionargs = arg or {}
|
||||
table.insert(self.Functionargs,self.group)
|
||||
table.insert(self.Functionargs,self.client)
|
||||
if self.Functionargs and self.debug then
|
||||
self:T({"Functionargs",self.Functionargs})
|
||||
end
|
||||
if not self.Generic and self.active == false then
|
||||
if Function ~= nil then
|
||||
local ErrorHandler = function( errmsg )
|
||||
env.info( "MOOSE Error in CLIENTMENU COMMAND function: " .. errmsg )
|
||||
if BASE.Debug ~= nil then
|
||||
env.info( BASE.Debug.traceback() )
|
||||
end
|
||||
return errmsg
|
||||
end
|
||||
self.CallHandler = function()
|
||||
local function MenuFunction()
|
||||
return self.Function( unpack( self.Functionargs ) )
|
||||
end
|
||||
local Status, Result = xpcall( MenuFunction, ErrorHandler)
|
||||
if self.Once == true then
|
||||
self:Clear()
|
||||
end
|
||||
end
|
||||
self.path = missionCommands.addCommandForGroup(self.GroupID,Text,self.parentpath, self.CallHandler)
|
||||
self.active = true
|
||||
else
|
||||
self.path = missionCommands.addSubMenuForGroup(self.GroupID,Text,self.parentpath)
|
||||
self.active = true
|
||||
end
|
||||
else
|
||||
if self.parentpath then
|
||||
self.path = UTILS.DeepCopy(self.parentpath)
|
||||
else
|
||||
self.path = {}
|
||||
end
|
||||
self.path[#self.path+1] = Text
|
||||
end
|
||||
self.UUID = table.concat(self.path,";")
|
||||
self:T({self.UUID})
|
||||
self.Once = false
|
||||
-- Log id.
|
||||
self.lid=string.format("CLIENTMENU %s | %s | ", self.ID, self.name)
|
||||
self:T(self.lid.."Created")
|
||||
return self
|
||||
end
|
||||
|
||||
--- Create a UUID
|
||||
-- @param #CLIENTMENU self
|
||||
-- @param #CLIENTMENU Parent The parent object if any
|
||||
-- @param #string Text The menu entry text
|
||||
-- @return #string UUID
|
||||
function CLIENTMENU:CreateUUID(Parent,Text)
|
||||
local path = {}
|
||||
if Parent and Parent.path then
|
||||
path = Parent.path
|
||||
end
|
||||
path[#path+1] = Text
|
||||
local UUID = table.concat(path,";")
|
||||
return UUID
|
||||
end
|
||||
|
||||
--- Set the CLIENTMENUMANAGER for this entry.
|
||||
-- @param #CLIENTMENU self
|
||||
-- @param #CLIENTMENUMANAGER Controller The controlling object.
|
||||
-- @return #CLIENTMENU self
|
||||
function CLIENTMENU:SetController(Controller)
|
||||
self.Controller = Controller
|
||||
return self
|
||||
end
|
||||
|
||||
--- The entry will be deleted after being used used - for menu entries with functions only.
|
||||
-- @param #CLIENTMENU self
|
||||
-- @return #CLIENTMENU self
|
||||
function CLIENTMENU:SetOnce()
|
||||
self:T(self.lid.."SetOnce")
|
||||
self.Once = true
|
||||
return self
|
||||
end
|
||||
|
||||
--- Remove the entry from the F10 menu.
|
||||
-- @param #CLIENTMENU self
|
||||
-- @return #CLIENTMENU self
|
||||
function CLIENTMENU:RemoveF10()
|
||||
self:T(self.lid.."RemoveF10")
|
||||
if self.GroupID then
|
||||
--self:I(self.lid.."Removing "..table.concat(self.path,";"))
|
||||
local function RemoveFunction()
|
||||
return missionCommands.removeItemForGroup(self.GroupID , self.path )
|
||||
end
|
||||
local status, err = pcall(RemoveFunction)
|
||||
if not status then
|
||||
self:I(string.format("**** Error Removing Menu Entry %s for %s!",tostring(self.name),self.groupname))
|
||||
end
|
||||
self.active = false
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- Get the menu path table.
|
||||
-- @param #CLIENTMENU self
|
||||
-- @return #table Path
|
||||
function CLIENTMENU:GetPath()
|
||||
self:T(self.lid.."GetPath")
|
||||
return self.path
|
||||
end
|
||||
|
||||
--- Get the UUID.
|
||||
-- @param #CLIENTMENU self
|
||||
-- @return #string UUID
|
||||
function CLIENTMENU:GetUUID()
|
||||
self:T(self.lid.."GetUUID")
|
||||
return self.UUID
|
||||
end
|
||||
|
||||
--- Link a child entry.
|
||||
-- @param #CLIENTMENU self
|
||||
-- @param #CLIENTMENU Child The entry to link as a child.
|
||||
-- @return #CLIENTMENU self
|
||||
function CLIENTMENU:AddChild(Child)
|
||||
self:T(self.lid.."AddChild "..Child.ID)
|
||||
table.insert(self.Children,Child.ID,Child)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Remove a child entry.
|
||||
-- @param #CLIENTMENU self
|
||||
-- @param #CLIENTMENU Child The entry to remove from the children.
|
||||
-- @return #CLIENTMENU self
|
||||
function CLIENTMENU:RemoveChild(Child)
|
||||
self:T(self.lid.."RemoveChild "..Child.ID)
|
||||
table.remove(self.Children,Child.ID)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Remove all subentries (children) from this entry.
|
||||
-- @param #CLIENTMENU self
|
||||
-- @return #CLIENTMENU self
|
||||
function CLIENTMENU:RemoveSubEntries()
|
||||
self:T(self.lid.."RemoveSubEntries")
|
||||
self:T({self.Children})
|
||||
for _id,_entry in pairs(self.Children) do
|
||||
self:T("Removing ".._id)
|
||||
if _entry then
|
||||
_entry:RemoveSubEntries()
|
||||
_entry:RemoveF10()
|
||||
if _entry.Parent then
|
||||
_entry.Parent:RemoveChild(self)
|
||||
end
|
||||
--if self.Controller then
|
||||
--self.Controller:_RemoveByID(_entry.ID)
|
||||
--end
|
||||
--_entry = nil
|
||||
end
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- Remove this entry and all subentries (children) from this entry.
|
||||
-- @param #CLIENTMENU self
|
||||
-- @return #CLIENTMENU self
|
||||
function CLIENTMENU:Clear()
|
||||
self:T(self.lid.."Clear")
|
||||
for _id,_entry in pairs(self.Children) do
|
||||
if _entry then
|
||||
_entry:RemoveSubEntries()
|
||||
_entry = nil
|
||||
end
|
||||
end
|
||||
self:RemoveF10()
|
||||
if self.Parent then
|
||||
self.Parent:RemoveChild(self)
|
||||
end
|
||||
--if self.Controller then
|
||||
--self.Controller:_RemoveByID(self.ID)
|
||||
--end
|
||||
return self
|
||||
end
|
||||
|
||||
-- TODO
|
||||
----------------------------------------------------------------------------------------------------------------
|
||||
--
|
||||
-- CLIENTMENUMANAGER
|
||||
--
|
||||
----------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
--- Class CLIENTMENUMANAGER
|
||||
-- @type CLIENTMENUMANAGER
|
||||
-- @field #string ClassName Class Name
|
||||
-- @field #string lid Lid for log entries
|
||||
-- @field #string version Version string
|
||||
-- @field #string name Name
|
||||
-- @field Core.Set#SET_CLIENT clientset The set of clients this menu manager is for
|
||||
-- @field #table flattree
|
||||
-- @field #table rootentries
|
||||
-- @field #table menutree
|
||||
-- @field #number entrycount
|
||||
-- @field #boolean debug
|
||||
-- @field #table PlayerMenu
|
||||
-- @field #number Coalition
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
--- *As a child my family's menu consisted of two choices: take it, or leave it.*
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ## CLIENTMENU and CLIENTMENUMANAGER
|
||||
--
|
||||
-- Manage menu structures for a SET_CLIENT of clients.
|
||||
--
|
||||
-- ## Concept
|
||||
--
|
||||
-- Separate creation of a menu tree structure from pushing it to each client. Create a shadow "reference" menu structure tree for your client pilot's in a mission.
|
||||
-- This can then be propagated to all clients. Manipulate the entries in the structure with removing, clearing or changing single entries, create replacement sub-structures
|
||||
-- for entries etc, push to one or all clients.
|
||||
--
|
||||
-- Many functions can either change the tree for one client or for all clients.
|
||||
--
|
||||
-- ## Conceptual remarks
|
||||
--
|
||||
-- There's a couple of things to fully understand:
|
||||
--
|
||||
-- 1) **CLIENTMENUMANAGER** manages a set of entries from **CLIENTMENU**, it's main purpose is to administer the *shadow menu tree*, ie. a menu structure which is not
|
||||
-- (yet) visible to any client
|
||||
-- 2) The entries are **CLIENTMENU** objects, which are linked in a tree form. There's two ways to create them:
|
||||
-- A) in the manager with ":NewEntry()" which initially
|
||||
-- adds it to the shadow menu **only**
|
||||
-- B) stand-alone directly as `CLIENTMENU:NewEntry()` - here it depends on whether or not you gave a CLIENT object if the entry is created as generic entry or pushed
|
||||
-- a **specific** client. **Be aware** though that the entries are not managed by the CLIENTMANAGER before the next step!
|
||||
-- A generic entry can be added to the manager (and the shadow tree) with `:AddEntry()` - this will also push it to all clients(!) if no client is given, or a specific client only.
|
||||
-- 3) Pushing only works for alive clients.
|
||||
-- 4) Live and shadow tree entries are managed via the CLIENTMENUMANAGER object.
|
||||
-- 5) `Propagate()`refreshes the menu tree for all, or a single client.
|
||||
--
|
||||
-- ## Create a base reference tree and send to all clients
|
||||
--
|
||||
-- local clientset = SET_CLIENT:New():FilterStart()
|
||||
--
|
||||
-- local menumgr = CLIENTMENUMANAGER:New(clientset,"Dayshift")
|
||||
-- local mymenu = menumgr:NewEntry("Top")
|
||||
-- local mymenu_lv1a = menumgr:NewEntry("Level 1 a",mymenu)
|
||||
-- local mymenu_lv1b = menumgr:NewEntry("Level 1 b",mymenu)
|
||||
-- -- next one is a command menu entry, which can only be used once
|
||||
-- local mymenu_lv1c = menumgr:NewEntry("Action Level 1 c",mymenu, testfunction, "testtext"):SetOnce()
|
||||
--
|
||||
-- local mymenu_lv2a = menumgr:NewEntry("Go here",mymenu_lv1a)
|
||||
-- local mymenu_lv2b = menumgr:NewEntry("Level 2 ab",mymenu_lv1a)
|
||||
-- local mymenu_lv2c = menumgr:NewEntry("Level 2 ac",mymenu_lv1a)
|
||||
--
|
||||
-- local mymenu_lv2ba = menumgr:NewEntry("Level 2 ba",mymenu_lv1b)
|
||||
-- local mymenu_lv2bb = menumgr:NewEntry("Level 2 bb",mymenu_lv1b)
|
||||
-- local mymenu_lv2bc = menumgr:NewEntry("Level 2 bc",mymenu_lv1b)
|
||||
--
|
||||
-- local mymenu_lv3a = menumgr:NewEntry("Level 3 aaa",mymenu_lv2a)
|
||||
-- local mymenu_lv3b = menumgr:NewEntry("Level 3 aab",mymenu_lv2a)
|
||||
-- local mymenu_lv3c = menumgr:NewEntry("Level 3 aac",mymenu_lv2a)
|
||||
--
|
||||
-- menumgr:Propagate() -- propagate **once** to all clients in the SET_CLIENT
|
||||
--
|
||||
-- ## Remove a single entry's subtree
|
||||
--
|
||||
-- menumgr:RemoveSubEntries(mymenu_lv3a)
|
||||
--
|
||||
-- ## Remove a single entry and also it's subtree
|
||||
--
|
||||
-- menumgr:DeleteEntry(mymenu_lv3a)
|
||||
--
|
||||
-- ## Add a single entry
|
||||
--
|
||||
-- local baimenu = menumgr:NewEntry("BAI",mymenu_lv1b)
|
||||
--
|
||||
-- menumgr:AddEntry(baimenu)
|
||||
--
|
||||
-- ## Add an entry with a function
|
||||
--
|
||||
-- local baimenu = menumgr:NewEntry("Task Action", mymenu_lv1b, TestFunction, Argument1, Argument1)
|
||||
--
|
||||
-- Now, the class will **automatically append the call with GROUP and CLIENT objects**, as this is can only be done when pushing the entry to the clients. So, the actual function implementation needs to look like this:
|
||||
--
|
||||
-- function TestFunction( Argument1, Argument2, Group, Client)
|
||||
--
|
||||
-- **Caveat is**, that you need to ensure your arguments are not **nil** or **false**, as LUA will optimize those away. You would end up having Group and Client in wrong places in the function call. Hence,
|
||||
-- if you need/ want to send **nil** or **false**, send a place holder instead and ensure your function can handle this, e.g.
|
||||
--
|
||||
-- local baimenu = menumgr:NewEntry("Task Action", mymenu_lv1b, TestFunction, "nil", Argument1)
|
||||
--
|
||||
-- ## Change the text of a leaf entry in the menu tree
|
||||
--
|
||||
-- menumgr:ChangeEntryTextForAll(mymenu_lv1b,"Attack")
|
||||
--
|
||||
-- ## Reset a single clients menu tree
|
||||
--
|
||||
-- menumgr:ResetMenu(client)
|
||||
--
|
||||
-- ## Reset all and clear the reference tree
|
||||
--
|
||||
-- menumgr:ResetMenuComplete()
|
||||
--
|
||||
-- ## Set to auto-propagate for CLIENTs joining the SET_CLIENT **after** the script is loaded - handy if you have a single menu tree.
|
||||
--
|
||||
-- menumgr:InitAutoPropagation()
|
||||
--
|
||||
-- @field #CLIENTMENUMANAGER
|
||||
CLIENTMENUMANAGER = {
|
||||
ClassName = "CLIENTMENUMANAGER",
|
||||
lid = "",
|
||||
version = "0.1.6",
|
||||
name = nil,
|
||||
clientset = nil,
|
||||
menutree = {},
|
||||
flattree = {},
|
||||
playertree = {},
|
||||
entrycount = 0,
|
||||
rootentries = {},
|
||||
debug = true,
|
||||
PlayerMenu = {},
|
||||
Coalition = nil,
|
||||
}
|
||||
|
||||
--- Create a new ClientManager instance.
|
||||
-- @param #CLIENTMENUMANAGER self
|
||||
-- @param Core.Set#SET_CLIENT ClientSet The set of clients to manage.
|
||||
-- @param #string Alias The name of this manager.
|
||||
-- @param #number Coalition (Optional) Coalition of this Manager, defaults to coalition.side.BLUE
|
||||
-- @return #CLIENTMENUMANAGER self
|
||||
function CLIENTMENUMANAGER:New(ClientSet, Alias, Coalition)
|
||||
-- Inherit everything from FSM class.
|
||||
local self=BASE:Inherit(self, BASE:New()) -- #CLIENTMENUMANAGER
|
||||
self.clientset = ClientSet
|
||||
self.PlayerMenu = {}
|
||||
self.name = Alias or "Nightshift"
|
||||
self.Coalition = Coalition or coalition.side.BLUE
|
||||
-- Log id.
|
||||
self.lid=string.format("CLIENTMENUMANAGER %s | %s | ", self.version, self.name)
|
||||
if self.debug then
|
||||
self:I(self.lid.."Created")
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- [Internal] Event handling
|
||||
-- @param #CLIENTMENUMANAGER self
|
||||
-- @param Core.Event#EVENTDATA EventData
|
||||
-- @return #CLIENTMENUMANAGER self
|
||||
function CLIENTMENUMANAGER:_EventHandler(EventData,Retry)
|
||||
self:T(self.lid.."_EventHandler: "..EventData.id)
|
||||
--self:I(self.lid.."_EventHandler: "..tostring(EventData.IniPlayerName))
|
||||
if EventData.id == EVENTS.PlayerLeaveUnit or EventData.id == EVENTS.Ejection or EventData.id == EVENTS.Crash or EventData.id == EVENTS.PilotDead then
|
||||
self:T(self.lid.."Leave event for player: "..tostring(EventData.IniPlayerName))
|
||||
local Client = _DATABASE:FindClient( EventData.IniUnitName )
|
||||
if Client then
|
||||
self:ResetMenu(Client)
|
||||
end
|
||||
elseif (EventData.id == EVENTS.PlayerEnterAircraft) and EventData.IniCoalition == self.Coalition then
|
||||
if EventData.IniPlayerName and EventData.IniGroup then
|
||||
if (not self.clientset:IsIncludeObject(_DATABASE:FindClient( EventData.IniUnitName ))) then
|
||||
self:T(self.lid.."Client not in SET: "..EventData.IniPlayerName)
|
||||
if not Retry then
|
||||
-- try again in 2 secs
|
||||
self:ScheduleOnce(2,CLIENTMENUMANAGER._EventHandler,self,EventData,true)
|
||||
end
|
||||
return self
|
||||
end
|
||||
--self:I(self.lid.."Join event for player: "..EventData.IniPlayerName)
|
||||
local player = _DATABASE:FindClient( EventData.IniUnitName )
|
||||
self:Propagate(player)
|
||||
end
|
||||
elseif EventData.id == EVENTS.PlayerEnterUnit then
|
||||
-- special for CA slots
|
||||
local grp = GROUP:FindByName(EventData.IniGroupName)
|
||||
if grp:IsGround() then
|
||||
self:T(string.format("Player %s entered GROUND unit %s!",EventData.IniPlayerName,EventData.IniUnitName))
|
||||
local IsPlayer = EventData.IniDCSUnit:getPlayerName()
|
||||
if IsPlayer then
|
||||
|
||||
local client=_DATABASE.CLIENTS[EventData.IniDCSUnitName] --Wrapper.Client#CLIENT
|
||||
|
||||
-- Add client in case it does not exist already.
|
||||
if not client then
|
||||
|
||||
-- Debug info.
|
||||
self:I(string.format("Player '%s' joined ground unit '%s' of group '%s'", tostring(EventData.IniPlayerName), tostring(EventData.IniDCSUnitName), tostring(EventData.IniDCSGroupName)))
|
||||
|
||||
client=_DATABASE:AddClient(EventData.IniDCSUnitName)
|
||||
|
||||
-- Add player.
|
||||
client:AddPlayer(EventData.IniPlayerName)
|
||||
|
||||
-- Add player.
|
||||
if not _DATABASE.PLAYERS[EventData.IniPlayerName] then
|
||||
_DATABASE:AddPlayer( EventData.IniUnitName, EventData.IniPlayerName )
|
||||
end
|
||||
|
||||
-- Player settings.
|
||||
local Settings = SETTINGS:Set( EventData.IniPlayerName )
|
||||
Settings:SetPlayerMenu(EventData.IniUnit)
|
||||
end
|
||||
--local player = _DATABASE:FindClient( EventData.IniPlayerName )
|
||||
self:Propagate(client)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set this Client Manager to auto-propagate menus **once** to newly joined players. Useful if you have **one** menu structure only. Does not automatically push follow-up changes to the client(s).
|
||||
-- @param #CLIENTMENUMANAGER self
|
||||
-- @return #CLIENTMENUMANAGER self
|
||||
function CLIENTMENUMANAGER:InitAutoPropagation()
|
||||
-- Player Events
|
||||
self:HandleEvent(EVENTS.PlayerLeaveUnit, self._EventHandler)
|
||||
self:HandleEvent(EVENTS.Ejection, self._EventHandler)
|
||||
self:HandleEvent(EVENTS.Crash, self._EventHandler)
|
||||
self:HandleEvent(EVENTS.PilotDead, self._EventHandler)
|
||||
self:HandleEvent(EVENTS.PlayerEnterAircraft, self._EventHandler)
|
||||
self:HandleEvent(EVENTS.PlayerEnterUnit, self._EventHandler)
|
||||
self:SetEventPriority(6)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Create a new entry in the **generic** structure.
|
||||
-- @param #CLIENTMENUMANAGER self
|
||||
-- @param #string Text Text of the F10 menu entry.
|
||||
-- @param #CLIENTMENU Parent The parent menu entry.
|
||||
-- @param #string Function (optional) Function to call when the entry is used.
|
||||
-- @param ... (optional) Arguments for the Function, comma separated.
|
||||
-- @return #CLIENTMENU Entry
|
||||
function CLIENTMENUMANAGER:NewEntry(Text,Parent,Function,...)
|
||||
self:T(self.lid.."NewEntry "..Text or "None")
|
||||
self.entrycount = self.entrycount + 1
|
||||
local entry = CLIENTMENU:NewEntry(nil,Text,Parent,Function,unpack(arg))
|
||||
if not Parent then
|
||||
self.rootentries[self.entrycount] = entry
|
||||
end
|
||||
local depth = #entry.path
|
||||
if not self.menutree[depth] then self.menutree[depth] = {} end
|
||||
table.insert(self.menutree[depth],entry.UUID)
|
||||
self.flattree[entry.UUID] = entry
|
||||
return entry
|
||||
end
|
||||
|
||||
--- Check matching entry in the generic structure by UUID.
|
||||
-- @param #CLIENTMENUMANAGER self
|
||||
-- @param #string UUID UUID of the menu entry.
|
||||
-- @return #boolean Exists
|
||||
function CLIENTMENUMANAGER:EntryUUIDExists(UUID)
|
||||
local exists = self.flattree[UUID] and true or false
|
||||
return exists
|
||||
end
|
||||
|
||||
--- Find matching entry in the generic structure by UUID.
|
||||
-- @param #CLIENTMENUMANAGER self
|
||||
-- @param #string UUID UUID of the menu entry.
|
||||
-- @return #CLIENTMENU Entry The #CLIENTMENU object found or nil.
|
||||
function CLIENTMENUMANAGER:FindEntryByUUID(UUID)
|
||||
self:T(self.lid.."FindEntryByUUID "..UUID or "None")
|
||||
local entry = nil
|
||||
for _gid,_entry in pairs(self.flattree) do
|
||||
local Entry = _entry -- #CLIENTMENU
|
||||
if Entry and Entry.UUID == UUID then
|
||||
entry = Entry
|
||||
end
|
||||
end
|
||||
return entry
|
||||
end
|
||||
|
||||
--- Find matching entries by text in the generic structure by UUID.
|
||||
-- @param #CLIENTMENUMANAGER self
|
||||
-- @param #string Text Text or partial text of the menu entry to find.
|
||||
-- @param #CLIENTMENU Parent (Optional) Only find entries under this parent entry.
|
||||
-- @return #table Table of matching UUIDs of #CLIENTMENU objects
|
||||
-- @return #table Table of matching #CLIENTMENU objects
|
||||
-- @return #number Number of matches
|
||||
function CLIENTMENUMANAGER:FindUUIDsByText(Text,Parent)
|
||||
self:T(self.lid.."FindUUIDsByText "..Text or "None")
|
||||
local matches = {}
|
||||
local entries = {}
|
||||
local n = 0
|
||||
for _uuid,_entry in pairs(self.flattree) do
|
||||
local Entry = _entry -- #CLIENTMENU
|
||||
if Parent then
|
||||
if Entry and string.find(Entry.name,Text,1,true) and string.find(Entry.UUID,Parent.UUID,1,true) then
|
||||
table.insert(matches,_uuid)
|
||||
table.insert(entries,Entry )
|
||||
n=n+1
|
||||
end
|
||||
else
|
||||
if Entry and string.find(Entry.name,Text,1,true) then
|
||||
table.insert(matches,_uuid)
|
||||
table.insert(entries,Entry )
|
||||
n=n+1
|
||||
end
|
||||
end
|
||||
end
|
||||
return matches, entries, n
|
||||
end
|
||||
|
||||
--- Find matching entries in the generic structure by the menu text.
|
||||
-- @param #CLIENTMENUMANAGER self
|
||||
-- @param #string Text Text or partial text of the F10 menu entry.
|
||||
-- @param #CLIENTMENU Parent (Optional) Only find entries under this parent entry.
|
||||
-- @return #table Table of matching #CLIENTMENU objects.
|
||||
-- @return #number Number of matches
|
||||
function CLIENTMENUMANAGER:FindEntriesByText(Text,Parent)
|
||||
self:T(self.lid.."FindEntriesByText "..Text or "None")
|
||||
local matches, objects, number = self:FindUUIDsByText(Text, Parent)
|
||||
return objects, number
|
||||
end
|
||||
|
||||
--- Find matching entries under a parent in the generic structure by UUID.
|
||||
-- @param #CLIENTMENUMANAGER self
|
||||
-- @param #CLIENTMENU Parent Find entries under this parent entry.
|
||||
-- @return #table Table of matching UUIDs of #CLIENTMENU objects
|
||||
-- @return #table Table of matching #CLIENTMENU objects
|
||||
-- @return #number Number of matches
|
||||
function CLIENTMENUMANAGER:FindUUIDsByParent(Parent)
|
||||
self:T(self.lid.."FindUUIDsByParent")
|
||||
local matches = {}
|
||||
local entries = {}
|
||||
local n = 0
|
||||
for _uuid,_entry in pairs(self.flattree) do
|
||||
local Entry = _entry -- #CLIENTMENU
|
||||
if Parent then
|
||||
if Entry and string.find(Entry.UUID,Parent.UUID,1,true) then
|
||||
table.insert(matches,_uuid)
|
||||
table.insert(entries,Entry )
|
||||
n=n+1
|
||||
end
|
||||
end
|
||||
end
|
||||
return matches, entries, n
|
||||
end
|
||||
|
||||
--- Find matching entries in the generic structure under a parent.
|
||||
-- @param #CLIENTMENUMANAGER self
|
||||
-- @param #CLIENTMENU Parent Find entries under this parent entry.
|
||||
-- @return #table Table of matching #CLIENTMENU objects.
|
||||
-- @return #number Number of matches
|
||||
function CLIENTMENUMANAGER:FindEntriesByParent(Parent)
|
||||
self:T(self.lid.."FindEntriesByParent")
|
||||
local matches, objects, number = self:FindUUIDsByParent(Parent)
|
||||
return objects, number
|
||||
end
|
||||
|
||||
--- Alter the text of a leaf entry in the generic structure and push to one specific client's F10 menu.
|
||||
-- @param #CLIENTMENUMANAGER self
|
||||
-- @param #CLIENTMENU Entry The menu entry.
|
||||
-- @param #string Text New Text of the F10 menu entry.
|
||||
-- @param Wrapper.Client#CLIENT Client (optional) The client for whom to alter the entry, if nil done for all clients.
|
||||
-- @return #CLIENTMENUMANAGER self
|
||||
function CLIENTMENUMANAGER:ChangeEntryText(Entry, Text, Client)
|
||||
self:T(self.lid.."ChangeEntryText "..Text or "None")
|
||||
local newentry = CLIENTMENU:NewEntry(nil,Text,Entry.Parent,Entry.Function,unpack(Entry.Functionargs))
|
||||
self:DeleteF10Entry(Entry,Client)
|
||||
self:DeleteGenericEntry(Entry)
|
||||
if not Entry.Parent then
|
||||
self.rootentries[self.entrycount] = newentry
|
||||
end
|
||||
local depth = #newentry.path
|
||||
if not self.menutree[depth] then self.menutree[depth] = {} end
|
||||
table.insert(self.menutree[depth],newentry.UUID)
|
||||
self.flattree[newentry.UUID] = newentry
|
||||
self:AddEntry(newentry,Client)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Push the complete menu structure to each of the clients in the set - refresh the menu tree of the clients.
|
||||
-- @param #CLIENTMENUMANAGER self
|
||||
-- @param Wrapper.Client#CLIENT Client (optional) If given, propagate only for this client.
|
||||
-- @return #CLIENTMENU Entry
|
||||
function CLIENTMENUMANAGER:Propagate(Client)
|
||||
self:T(self.lid.."Propagate")
|
||||
--self:I(UTILS.PrintTableToLog(Client,1))
|
||||
local knownunits = {} -- track so we can ID multi seated
|
||||
local Set = self.clientset.Set
|
||||
if Client then
|
||||
Set = {Client}
|
||||
end
|
||||
self:ResetMenu(Client)
|
||||
for _,_client in pairs(Set) do
|
||||
local client = _client -- Wrapper.Client#CLIENT
|
||||
if client and client:IsAlive() then
|
||||
local playerunit = client:GetName()
|
||||
--local playergroup = client:GetGroup()
|
||||
local playername = client:GetPlayerName() or "none"
|
||||
if not knownunits[playerunit] then
|
||||
knownunits[playerunit] = true
|
||||
else
|
||||
self:I("Player in multi seat unit: "..playername)
|
||||
break -- multi seat already build
|
||||
end
|
||||
if not self.playertree[playername] then
|
||||
self.playertree[playername] = {}
|
||||
end
|
||||
for level,branch in pairs (self.menutree) do
|
||||
self:T("Building branch:" .. level)
|
||||
for _,leaf in pairs(branch) do
|
||||
self:T("Building leaf:" .. leaf)
|
||||
local entry = self:FindEntryByUUID(leaf)
|
||||
if entry then
|
||||
self:T("Found generic entry:" .. entry.UUID)
|
||||
local parent = nil
|
||||
if entry.Parent and entry.Parent.UUID then
|
||||
parent = self.playertree[playername][entry.Parent.UUID] or self:FindEntryByUUID(entry.Parent.UUID)
|
||||
end
|
||||
self.playertree[playername][entry.UUID] = CLIENTMENU:NewEntry(client,entry.name,parent,entry.Function,unpack(entry.Functionargs))
|
||||
self.playertree[playername][entry.UUID].Once = entry.Once
|
||||
else
|
||||
self:T("NO generic entry for:" .. leaf)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- Push a single previously created entry into the F10 menu structure of all clients.
|
||||
-- @param #CLIENTMENUMANAGER self
|
||||
-- @param #CLIENTMENU Entry The entry to add.
|
||||
-- @param Wrapper.Client#CLIENT Client (optional) If given, make this change only for this client.
|
||||
-- @return #CLIENTMENUMANAGER self
|
||||
function CLIENTMENUMANAGER:AddEntry(Entry,Client)
|
||||
self:T(self.lid.."AddEntry")
|
||||
local Set = self.clientset.Set
|
||||
local knownunits = {}
|
||||
if Client then
|
||||
Set = {Client}
|
||||
end
|
||||
for _,_client in pairs(Set) do
|
||||
local client = _client -- Wrapper.Client#CLIENT
|
||||
if client and client:IsAlive() then
|
||||
local playername = client:GetPlayerName() or "None"
|
||||
local unitname = client:GetName()
|
||||
if not knownunits[unitname] then
|
||||
knownunits[unitname] = true
|
||||
else
|
||||
self:I("Player in multi seat unit: "..playername)
|
||||
break
|
||||
end
|
||||
if Entry then
|
||||
self:T("Adding generic entry:" .. Entry.UUID)
|
||||
local parent = nil
|
||||
if not self.playertree[playername] then
|
||||
self.playertree[playername] = {}
|
||||
end
|
||||
if Entry.Parent and Entry.Parent.UUID then
|
||||
parent = self.playertree[playername][Entry.Parent.UUID] or self:FindEntryByUUID(Entry.Parent.UUID)
|
||||
end
|
||||
self.playertree[playername][Entry.UUID] = CLIENTMENU:NewEntry(client,Entry.name,parent,Entry.Function,unpack(Entry.Functionargs))
|
||||
self.playertree[playername][Entry.UUID].Once = Entry.Once
|
||||
else
|
||||
self:T("NO generic entry given")
|
||||
end
|
||||
end
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- Blank out the menu - remove **all root entries** and all entries below from the client's F10 menus, leaving the generic structure untouched.
|
||||
-- @param #CLIENTMENUMANAGER self
|
||||
-- @param Wrapper.Client#CLIENT Client (optional) If given, remove only for this client.
|
||||
-- @return #CLIENTMENUMANAGER self
|
||||
function CLIENTMENUMANAGER:ResetMenu(Client)
|
||||
self:T(self.lid.."ResetMenu")
|
||||
for _,_entry in pairs(self.rootentries) do
|
||||
--local RootEntry = self.structure.generic[_entry]
|
||||
if _entry then
|
||||
self:DeleteF10Entry(_entry,Client)
|
||||
end
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- Blank out the menu - remove **all root entries** and all entries below from all clients' F10 menus, and **delete** the generic structure.
|
||||
-- @param #CLIENTMENUMANAGER self
|
||||
-- @return #CLIENTMENUMANAGER self
|
||||
function CLIENTMENUMANAGER:ResetMenuComplete()
|
||||
self:T(self.lid.."ResetMenuComplete")
|
||||
for _,_entry in pairs(self.rootentries) do
|
||||
--local RootEntry = self.structure.generic[_entry]
|
||||
if _entry then
|
||||
self:DeleteF10Entry(_entry)
|
||||
end
|
||||
end
|
||||
self.playertree = nil
|
||||
self.playertree = {}
|
||||
self.rootentries = nil
|
||||
self.rootentries = {}
|
||||
self.menutree = nil
|
||||
self.menutree = {}
|
||||
return self
|
||||
end
|
||||
|
||||
--- Remove the entry and all entries below the given entry from the client's F10 menus.
|
||||
-- @param #CLIENTMENUMANAGER self
|
||||
-- @param #CLIENTMENU Entry The entry to remove
|
||||
-- @param Wrapper.Client#CLIENT Client (optional) If given, make this change only for this client.
|
||||
-- @return #CLIENTMENUMANAGER self
|
||||
function CLIENTMENUMANAGER:DeleteF10Entry(Entry,Client)
|
||||
self:T(self.lid.."DeleteF10Entry")
|
||||
local Set = self.clientset.Set
|
||||
if Client then
|
||||
Set = {Client}
|
||||
end
|
||||
for _,_client in pairs(Set) do
|
||||
if _client and _client:IsAlive() then
|
||||
local playername = _client:GetPlayerName()
|
||||
if self.playertree[playername] then
|
||||
local centry = self.playertree[playername][Entry.UUID] -- #CLIENTMENU
|
||||
if centry then
|
||||
--self:I("Match for "..Entry.UUID)
|
||||
centry:Clear()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- Remove the entry and all entries below the given entry from the generic tree.
|
||||
-- @param #CLIENTMENUMANAGER self
|
||||
-- @param #CLIENTMENU Entry The entry to remove
|
||||
-- @return #CLIENTMENUMANAGER self
|
||||
function CLIENTMENUMANAGER:DeleteGenericEntry(Entry)
|
||||
self:T(self.lid.."DeleteGenericEntry")
|
||||
|
||||
if Entry.Children and #Entry.Children > 0 then
|
||||
self:RemoveGenericSubEntries(Entry)
|
||||
end
|
||||
|
||||
local depth = #Entry.path
|
||||
local uuid = Entry.UUID
|
||||
|
||||
local tbl = UTILS.DeepCopy(self.menutree)
|
||||
|
||||
if tbl[depth] then
|
||||
for i=depth,#tbl do
|
||||
--self:I("Level = "..i)
|
||||
for _id,_uuid in pairs(tbl[i]) do
|
||||
self:T(_uuid)
|
||||
if string.find(_uuid,uuid,1,true) or _uuid == uuid then
|
||||
--self:I("Match for ".._uuid)
|
||||
self.menutree[i][_id] = nil
|
||||
self.flattree[_uuid] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Remove all entries below the given entry from the generic tree.
|
||||
-- @param #CLIENTMENUMANAGER self
|
||||
-- @param #CLIENTMENU Entry The entry where to start. This entry stays.
|
||||
-- @return #CLIENTMENUMANAGER self
|
||||
function CLIENTMENUMANAGER:RemoveGenericSubEntries(Entry)
|
||||
self:T(self.lid.."RemoveGenericSubEntries")
|
||||
|
||||
local depth = #Entry.path + 1
|
||||
local uuid = Entry.UUID
|
||||
|
||||
local tbl = UTILS.DeepCopy(self.menutree)
|
||||
|
||||
if tbl[depth] then
|
||||
for i=depth,#tbl do
|
||||
self:T("Level = "..i)
|
||||
for _id,_uuid in pairs(tbl[i]) do
|
||||
self:T(_uuid)
|
||||
if string.find(_uuid,uuid,1,true) then
|
||||
self:T("Match for ".._uuid)
|
||||
self.menutree[i][_id] = nil
|
||||
self.flattree[_uuid] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Remove all entries below the given entry from the client's F10 menus.
|
||||
-- @param #CLIENTMENUMANAGER self
|
||||
-- @param #CLIENTMENU Entry The entry where to start. This entry stays.
|
||||
-- @param Wrapper.Client#CLIENT Client (optional) If given, make this change only for this client. In this case the generic structure will not be touched.
|
||||
-- @return #CLIENTMENUMANAGER self
|
||||
function CLIENTMENUMANAGER:RemoveF10SubEntries(Entry,Client)
|
||||
self:T(self.lid.."RemoveSubEntries")
|
||||
local Set = self.clientset.Set
|
||||
if Client then
|
||||
Set = {Client}
|
||||
end
|
||||
for _,_client in pairs(Set) do
|
||||
if _client and _client:IsAlive() then
|
||||
local playername = _client:GetPlayerName()
|
||||
if self.playertree[playername] then
|
||||
local centry = self.playertree[playername][Entry.UUID] -- #CLIENTMENU
|
||||
centry:RemoveSubEntries()
|
||||
end
|
||||
end
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------------------------------------------------
|
||||
--
|
||||
-- End ClientMenu
|
||||
--
|
||||
----------------------------------------------------------------------------------------------------------------
|
||||
@@ -872,6 +872,8 @@ end
|
||||
-- @return Wrapper.Group#GROUP The found GROUP.
|
||||
function DATABASE:FindGroup( GroupName )
|
||||
|
||||
if type(GroupName) ~= "string" or GroupName == "" then return end
|
||||
|
||||
local GroupFound = self.GROUPS[GroupName]
|
||||
|
||||
if GroupFound == nil and GroupName ~= nil and self.Templates.Groups[GroupName] == nil then
|
||||
@@ -1697,7 +1699,7 @@ function DATABASE:_EventOnBirth( Event )
|
||||
if PlayerName then
|
||||
|
||||
-- Debug info.
|
||||
self:I(string.format("Player '%s' joined unit '%s' of group '%s'", tostring(PlayerName), tostring(Event.IniDCSUnitName), tostring(Event.IniDCSGroupName)))
|
||||
self:I(string.format("Player '%s' joined unit '%s' (%s) of group '%s'", tostring(PlayerName), tostring(Event.IniDCSUnitName), tostring(Event.IniTypeName), tostring(Event.IniDCSGroupName)))
|
||||
|
||||
-- Add client in case it does not exist already.
|
||||
if client == nil or (client and client:CountPlayers() == 0) then
|
||||
|
||||
@@ -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
|
||||
---
|
||||
|
||||
@@ -79,7 +79,7 @@
|
||||
|
||||
do -- FSM
|
||||
|
||||
-- @type FSM
|
||||
--- @type FSM
|
||||
-- @field #string ClassName Name of the class.
|
||||
-- @field Core.Scheduler#SCHEDULER CallScheduler Call scheduler.
|
||||
-- @field #table options Options.
|
||||
@@ -948,9 +948,8 @@ do -- FSM
|
||||
end
|
||||
|
||||
do -- FSM_CONTROLLABLE
|
||||
|
||||
---
|
||||
-- @type FSM_CONTROLLABLE
|
||||
|
||||
--- @type FSM_CONTROLLABLE
|
||||
-- @field Wrapper.Controllable#CONTROLLABLE Controllable
|
||||
-- @extends Core.Fsm#FSM
|
||||
|
||||
@@ -1082,9 +1081,8 @@ do -- FSM_CONTROLLABLE
|
||||
end
|
||||
|
||||
do -- FSM_PROCESS
|
||||
|
||||
---
|
||||
-- @type FSM_PROCESS
|
||||
|
||||
--- @type FSM_PROCESS
|
||||
-- @field Tasking.Task#TASK Task
|
||||
-- @extends Core.Fsm#FSM_CONTROLLABLE
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
do -- Goal
|
||||
|
||||
-- @type GOAL
|
||||
--- @type GOAL
|
||||
-- @extends Core.Fsm#FSM
|
||||
|
||||
--- Models processes that have an objective with a defined achievement. Derived classes implement the ways how the achievements can be realized.
|
||||
@@ -71,10 +71,10 @@ do -- Goal
|
||||
ClassName = "GOAL",
|
||||
}
|
||||
|
||||
-- @field #table GOAL.Players
|
||||
--- @field #table GOAL.Players
|
||||
GOAL.Players = {}
|
||||
|
||||
-- @field #number GOAL.TotalContributions
|
||||
--- @field #number GOAL.TotalContributions
|
||||
GOAL.TotalContributions = 0
|
||||
|
||||
--- GOAL Constructor.
|
||||
@@ -145,7 +145,7 @@ do -- Goal
|
||||
self.TotalContributions = self.TotalContributions + 1
|
||||
end
|
||||
|
||||
-- @param #GOAL self
|
||||
--- @param #GOAL self
|
||||
-- @param #number Player contribution.
|
||||
function GOAL:GetPlayerContribution( PlayerName )
|
||||
return self.Players[PlayerName] or 0
|
||||
|
||||
@@ -206,7 +206,7 @@ end
|
||||
function MESSAGE:ToGroup( Group, Settings )
|
||||
self:F( Group.GroupName )
|
||||
|
||||
if Group then
|
||||
if Group and Group:IsAlive() then
|
||||
|
||||
if self.MessageType then
|
||||
local Settings = Settings or (Group and _DATABASE:GetPlayerSettings( Group:GetPlayerName() )) or _SETTINGS -- Core.Settings#SETTINGS
|
||||
@@ -231,7 +231,7 @@ end
|
||||
function MESSAGE:ToUnit( Unit, Settings )
|
||||
self:F( Unit.IdentifiableName )
|
||||
|
||||
if Unit then
|
||||
if Unit and Unit:IsAlive() then
|
||||
|
||||
if self.MessageType then
|
||||
local Settings = Settings or ( Unit and _DATABASE:GetPlayerSettings( Unit:GetPlayerName() ) ) or _SETTINGS -- Core.Settings#SETTINGS
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
do -- COORDINATE
|
||||
|
||||
---
|
||||
--- Coordinate class
|
||||
-- @type COORDINATE
|
||||
-- @field #string ClassName Name of the class
|
||||
-- @field #number x Component of the 3D vector.
|
||||
@@ -59,6 +59,10 @@ do -- COORDINATE
|
||||
-- * @{#COORDINATE.SmokeOrange}(): To smoke the point in orange.
|
||||
-- * @{#COORDINATE.SmokeWhite}(): To smoke the point in white.
|
||||
-- * @{#COORDINATE.SmokeGreen}(): To smoke the point in green.
|
||||
-- * @{#COORDINATE.SetSmokeOffsetDirection}(): To set an offset point direction for smoke.
|
||||
-- * @{#COORDINATE.SetSmokeOffsetDistance}(): To set an offset point distance for smoke.
|
||||
-- * @{#COORDINATE.SwitchSmokeOffsetOn}(): To set an offset point for smoke to on.
|
||||
-- * @{#COORDINATE.SwitchSmokeOffsetOff}(): To set an offset point for smoke to off.
|
||||
--
|
||||
-- ## 2.2) Flare
|
||||
--
|
||||
@@ -1157,6 +1161,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:
|
||||
@@ -1962,14 +2122,112 @@ do -- COORDINATE
|
||||
end
|
||||
|
||||
|
||||
--- Smokes the point in a color.
|
||||
--- Create colored smoke the point. The smoke we last up to 5 min (DCS limitation) but you can optionally specify a shorter duration or stop it manually.
|
||||
-- @param #COORDINATE self
|
||||
-- @param Utilities.Utils#SMOKECOLOR SmokeColor
|
||||
-- @param #string name (Optional) Name if you want to stop the smoke early (normal duration: 5mins)
|
||||
function COORDINATE:Smoke( SmokeColor, name )
|
||||
self:F2( { SmokeColor } )
|
||||
self.firename = name or "Smoke-"..math.random(1,100000)
|
||||
trigger.action.smoke( self:GetVec3(), SmokeColor, self.firename )
|
||||
-- @param #number SmokeColor Color of smoke, e.g. `SMOKECOLOR.Green` for green smoke.
|
||||
-- @param #number Duration (Optional) Duration of the smoke in seconds. DCS stopps the smoke automatically after 5 min.
|
||||
-- @param #number Delay (Optional) Delay before the smoke is started in seconds.
|
||||
-- @param #string Name (Optional) Name if you want to stop the smoke early (normal duration: 5mins)
|
||||
-- @param #boolean Offset (Optional) If true, offset the smokle a bit.
|
||||
-- @param #number Direction (Optional) If Offset is true this is the direction of the offset, 1-359 (degrees). Default random.
|
||||
-- @param #number Distance (Optional) If Offset is true this is the distance of the offset in meters. Default random 10-20.
|
||||
-- @return #COORDINATE self
|
||||
function COORDINATE:Smoke( SmokeColor, Duration, Delay, Name, Offset,Direction,Distance)
|
||||
self:F2( { SmokeColor, Name, Duration, Delay, Offset } )
|
||||
|
||||
SmokeColor=SmokeColor or SMOKECOLOR.Green
|
||||
|
||||
if Delay and Delay>0 then
|
||||
self:ScheduleOnce(Delay, COORDINATE.Smoke, self, SmokeColor, Duration, 0, Name, Direction,Distance)
|
||||
else
|
||||
|
||||
-- Create a name which is used to stop the smoke manually
|
||||
self.firename = Name or "Smoke-"..math.random(1,100000)
|
||||
|
||||
-- Create smoke
|
||||
if Offset or self.SmokeOffset then
|
||||
local Angle = Direction or self:GetSmokeOffsetDirection()
|
||||
local Distance = Distance or self:GetSmokeOffsetDistance()
|
||||
local newpos = self:Translate(Distance,Angle,true,false)
|
||||
local newvec3 = newpos:GetVec3()
|
||||
trigger.action.smoke( newvec3, SmokeColor, self.firename )
|
||||
else
|
||||
trigger.action.smoke( self:GetVec3(), SmokeColor, self.firename )
|
||||
end
|
||||
|
||||
-- Stop smoke
|
||||
if Duration and Duration>0 then
|
||||
self:ScheduleOnce(Duration, COORDINATE.StopSmoke, self, self.firename )
|
||||
end
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Get the offset direction when using `COORDINATE:Smoke()`.
|
||||
-- @param #COORDINATE self
|
||||
-- @return #number Direction in degrees.
|
||||
function COORDINATE:GetSmokeOffsetDirection()
|
||||
local direction = self.SmokeOffsetDirection or math.random(1,359)
|
||||
return direction
|
||||
end
|
||||
|
||||
--- Set the offset direction when using `COORDINATE:Smoke()`.
|
||||
-- @param #COORDINATE self
|
||||
-- @param #number Direction (Optional) This is the direction of the offset, 1-359 (degrees). Default random.
|
||||
-- @return #COORDINATE self
|
||||
function COORDINATE:SetSmokeOffsetDirection(Direction)
|
||||
if self then
|
||||
self.SmokeOffsetDirection = Direction or math.random(1,359)
|
||||
return self
|
||||
else
|
||||
COORDINATE.SmokeOffsetDirection = Direction or math.random(1,359)
|
||||
end
|
||||
end
|
||||
|
||||
--- Get the offset distance when using `COORDINATE:Smoke()`.
|
||||
-- @param #COORDINATE self
|
||||
-- @return #number Distance Distance in meters.
|
||||
function COORDINATE:GetSmokeOffsetDistance()
|
||||
local distance = self.SmokeOffsetDistance or math.random(10,20)
|
||||
return distance
|
||||
end
|
||||
|
||||
--- Set the offset distance when using `COORDINATE:Smoke()`.
|
||||
-- @param #COORDINATE self
|
||||
-- @param #number Distance (Optional) This is the distance of the offset in meters. Default random 10-20.
|
||||
-- @return #COORDINATE self
|
||||
function COORDINATE:SetSmokeOffsetDistance(Distance)
|
||||
if self then
|
||||
self.SmokeOffsetDistance = Distance or math.random(10,20)
|
||||
return self
|
||||
else
|
||||
COORDINATE.SmokeOffsetDistance = Distance or math.random(10,20)
|
||||
end
|
||||
end
|
||||
|
||||
--- Set the offset on when using `COORDINATE:Smoke()`.
|
||||
-- @param #COORDINATE self
|
||||
-- @return #COORDINATE self
|
||||
function COORDINATE:SwitchSmokeOffsetOn()
|
||||
if self then
|
||||
self.SmokeOffset = true
|
||||
return self
|
||||
else
|
||||
COORDINATE.SmokeOffset = true
|
||||
end
|
||||
end
|
||||
|
||||
--- Set the offset off when using `COORDINATE:Smoke()`.
|
||||
-- @param #COORDINATE self
|
||||
-- @return #COORDINATE self
|
||||
function COORDINATE:SwitchSmokeOffsetOff()
|
||||
if self then
|
||||
self.SmokeOffset = false
|
||||
return self
|
||||
else
|
||||
COORDINATE.SmokeOffset = false
|
||||
end
|
||||
end
|
||||
|
||||
--- Stops smoking the point in a color.
|
||||
@@ -1981,49 +2239,83 @@ do -- COORDINATE
|
||||
|
||||
--- Smoke the COORDINATE Green.
|
||||
-- @param #COORDINATE self
|
||||
function COORDINATE:SmokeGreen()
|
||||
self:F2()
|
||||
self:Smoke( SMOKECOLOR.Green )
|
||||
-- @param #number Duration (Optional) Duration of the smoke in seconds. DCS stopps the smoke automatically after 5 min.
|
||||
-- @param #number Delay (Optional) Delay before the smoke is started in seconds.
|
||||
-- @return #COORDINATE self
|
||||
function COORDINATE:SmokeGreen(Duration, Delay)
|
||||
self:Smoke( SMOKECOLOR.Green, Duration, Delay )
|
||||
return self
|
||||
end
|
||||
|
||||
--- Smoke the COORDINATE Red.
|
||||
-- @param #COORDINATE self
|
||||
function COORDINATE:SmokeRed()
|
||||
self:F2()
|
||||
self:Smoke( SMOKECOLOR.Red )
|
||||
-- @param #number Duration (Optional) Duration of the smoke in seconds. DCS stopps the smoke automatically after 5 min.
|
||||
-- @param #number Delay (Optional) Delay before the smoke is started in seconds.
|
||||
-- @return #COORDINATE self
|
||||
function COORDINATE:SmokeRed(Duration, Delay)
|
||||
self:Smoke( SMOKECOLOR.Red, Duration, Delay )
|
||||
return self
|
||||
end
|
||||
|
||||
--- Smoke the COORDINATE White.
|
||||
-- @param #COORDINATE self
|
||||
function COORDINATE:SmokeWhite()
|
||||
self:F2()
|
||||
self:Smoke( SMOKECOLOR.White )
|
||||
-- @param #number Duration (Optional) Duration of the smoke in seconds. DCS stopps the smoke automatically after 5 min.
|
||||
-- @param #number Delay (Optional) Delay before the smoke is started in seconds.
|
||||
-- @return #COORDINATE self
|
||||
function COORDINATE:SmokeWhite(Duration, Delay)
|
||||
self:Smoke( SMOKECOLOR.White, Duration, Delay )
|
||||
return self
|
||||
end
|
||||
|
||||
--- Smoke the COORDINATE Orange.
|
||||
-- @param #COORDINATE self
|
||||
function COORDINATE:SmokeOrange()
|
||||
self:F2()
|
||||
self:Smoke( SMOKECOLOR.Orange )
|
||||
-- @param #number Duration (Optional) Duration of the smoke in seconds. DCS stopps the smoke automatically after 5 min.
|
||||
-- @param #number Delay (Optional) Delay before the smoke is started in seconds.
|
||||
-- @return #COORDINATE self
|
||||
function COORDINATE:SmokeOrange(Duration, Delay)
|
||||
self:Smoke( SMOKECOLOR.Orange, Duration, Delay )
|
||||
return self
|
||||
end
|
||||
|
||||
--- Smoke the COORDINATE Blue.
|
||||
-- @param #COORDINATE self
|
||||
function COORDINATE:SmokeBlue()
|
||||
self:F2()
|
||||
self:Smoke( SMOKECOLOR.Blue )
|
||||
-- @param #number Duration (Optional) Duration of the smoke in seconds. DCS stopps the smoke automatically after 5 min.
|
||||
-- @param #number Delay (Optional) Delay before the smoke is started in seconds.
|
||||
-- @return #COORDINATE self
|
||||
function COORDINATE:SmokeBlue(Duration, Delay)
|
||||
self:Smoke( SMOKECOLOR.Blue, Duration, Delay )
|
||||
return self
|
||||
end
|
||||
|
||||
--- Big smoke and fire at the coordinate.
|
||||
-- @param #COORDINATE self
|
||||
-- @param Utilities.Utils#BIGSMOKEPRESET preset Smoke preset (1=small smoke and fire, 2=medium smoke and fire, 3=large smoke and fire, 4=huge smoke and fire, 5=small smoke, 6=medium smoke, 7=large smoke, 8=huge smoke).
|
||||
-- @param #number density (Optional) Smoke density. Number in [0,...,1]. Default 0.5.
|
||||
-- @param #string name (Optional) Name of the fire to stop it later again if not using the same COORDINATE object. Defaults to "Fire-" plus a random 5-digit-number.
|
||||
function COORDINATE:BigSmokeAndFire( preset, density, name )
|
||||
self:F2( { preset=preset, density=density } )
|
||||
density=density or 0.5
|
||||
self.firename = name or "Fire-"..math.random(1,10000)
|
||||
trigger.action.effectSmokeBig( self:GetVec3(), preset, density, self.firename )
|
||||
-- @param #number Preset Smoke preset (1=small smoke and fire, 2=medium smoke and fire, 3=large smoke and fire, 4=huge smoke and fire, 5=small smoke, 6=medium smoke, 7=large smoke, 8=huge smoke).
|
||||
-- @param #number Density (Optional) Smoke density. Number in [0,...,1]. Default 0.5.
|
||||
-- @param #number Duration (Optional) Duration of the smoke and fire in seconds.
|
||||
-- @param #number Delay (Optional) Delay before the smoke and fire is started in seconds.
|
||||
-- @param #string Name (Optional) Name of the fire to stop it later again if not using the same COORDINATE object. Defaults to "Fire-" plus a random 5-digit-number.
|
||||
-- @return #COORDINATE self
|
||||
function COORDINATE:BigSmokeAndFire( Preset, Density, Duration, Delay, Name )
|
||||
self:F2( { preset=Preset, density=Density } )
|
||||
|
||||
Preset=Preset or BIGSMOKEPRESET.SmallSmokeAndFire
|
||||
Density=Density or 0.5
|
||||
|
||||
if Delay and Delay>0 then
|
||||
self:ScheduleOnce(Delay, COORDINATE.BigSmokeAndFire, self, Preset, Density, Duration, 0, Name)
|
||||
else
|
||||
|
||||
self.firename = Name or "Fire-"..math.random(1,10000)
|
||||
|
||||
trigger.action.effectSmokeBig( self:GetVec3(), Preset, Density, self.firename )
|
||||
|
||||
-- Stop smoke
|
||||
if Duration and Duration>0 then
|
||||
self:ScheduleOnce(Duration, COORDINATE.StopBigSmokeAndFire, self, self.firename )
|
||||
end
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Stop big smoke and fire at the coordinate.
|
||||
@@ -2036,82 +2328,98 @@ do -- COORDINATE
|
||||
|
||||
--- Small smoke and fire at the coordinate.
|
||||
-- @param #COORDINATE self
|
||||
-- @param #number density (Optional) Smoke density. Number between 0 and 1. Default 0.5.
|
||||
-- @param #string name (Optional) Name of the fire to stop it later again if not using the same COORDINATE object. Defaults to "Fire-" plus a random 5-digit-number.
|
||||
function COORDINATE:BigSmokeAndFireSmall( density, name )
|
||||
self:F2( { density=density } )
|
||||
density=density or 0.5
|
||||
self:BigSmokeAndFire(BIGSMOKEPRESET.SmallSmokeAndFire, density, name)
|
||||
-- @param #number Density (Optional) Smoke density. Number between 0 and 1. Default 0.5.
|
||||
-- @param #number Duration (Optional) Duration of the smoke and fire in seconds.
|
||||
-- @param #number Delay (Optional) Delay before the smoke and fire is started in seconds.
|
||||
-- @param #string Name (Optional) Name of the fire to stop it later again if not using the same COORDINATE object. Defaults to "Fire-" plus a random 5-digit-number.
|
||||
-- @return #COORDINATE self
|
||||
function COORDINATE:BigSmokeAndFireSmall( Density, Duration, Delay, Name )
|
||||
self:BigSmokeAndFire(BIGSMOKEPRESET.SmallSmokeAndFire, Density, Duration, Delay, Name)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Medium smoke and fire at the coordinate.
|
||||
-- @param #COORDINATE self
|
||||
-- @param #number density (Optional) Smoke density. Number between 0 and 1. Default 0.5.
|
||||
-- @param #number Duration (Optional) Duration of the smoke and fire in seconds.
|
||||
-- @param #number Delay (Optional) Delay before the smoke and fire is started in seconds.
|
||||
-- @param #string name (Optional) Name of the fire to stop it later again if not using the same COORDINATE object. Defaults to "Fire-" plus a random 5-digit-number.
|
||||
function COORDINATE:BigSmokeAndFireMedium( density, name )
|
||||
self:F2( { density=density } )
|
||||
density=density or 0.5
|
||||
self:BigSmokeAndFire(BIGSMOKEPRESET.MediumSmokeAndFire, density, name)
|
||||
-- @return #COORDINATE self
|
||||
function COORDINATE:BigSmokeAndFireMedium( Density, Duration, Delay, Name )
|
||||
self:BigSmokeAndFire(BIGSMOKEPRESET.MediumSmokeAndFire, Density, Duration, Delay, Name)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Large smoke and fire at the coordinate.
|
||||
-- @param #COORDINATE self
|
||||
-- @param #number density (Optional) Smoke density. Number between 0 and 1. Default 0.5.
|
||||
-- @param #number Duration (Optional) Duration of the smoke and fire in seconds.
|
||||
-- @param #number Delay (Optional) Delay before the smoke and fire is started in seconds.
|
||||
-- @param #string name (Optional) Name of the fire to stop it later again if not using the same COORDINATE object. Defaults to "Fire-" plus a random 5-digit-number.
|
||||
function COORDINATE:BigSmokeAndFireLarge( density, name )
|
||||
self:F2( { density=density } )
|
||||
density=density or 0.5
|
||||
self:BigSmokeAndFire(BIGSMOKEPRESET.LargeSmokeAndFire, density, name)
|
||||
-- @return #COORDINATE self
|
||||
function COORDINATE:BigSmokeAndFireLarge( Density, Duration, Delay, Name )
|
||||
self:BigSmokeAndFire(BIGSMOKEPRESET.LargeSmokeAndFire, Density, Duration, Delay, Name)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Huge smoke and fire at the coordinate.
|
||||
-- @param #COORDINATE self
|
||||
-- @param #number density (Optional) Smoke density. Number between 0 and 1. Default 0.5.
|
||||
-- @param #number Duration (Optional) Duration of the smoke and fire in seconds.
|
||||
-- @param #number Delay (Optional) Delay before the smoke and fire is started in seconds.
|
||||
-- @param #string name (Optional) Name of the fire to stop it later again if not using the same COORDINATE object. Defaults to "Fire-" plus a random 5-digit-number.
|
||||
function COORDINATE:BigSmokeAndFireHuge( density, name )
|
||||
self:F2( { density=density } )
|
||||
density=density or 0.5
|
||||
self:BigSmokeAndFire(BIGSMOKEPRESET.HugeSmokeAndFire, density, name)
|
||||
-- @return #COORDINATE self
|
||||
function COORDINATE:BigSmokeAndFireHuge( Density, Duration, Delay, Name )
|
||||
self:BigSmokeAndFire(BIGSMOKEPRESET.HugeSmokeAndFire, Density, Duration, Delay, Name)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Small smoke at the coordinate.
|
||||
-- @param #COORDINATE self
|
||||
-- @param #number density (Optional) Smoke density. Number between 0 and 1. Default 0.5.
|
||||
-- @param #number Duration (Optional) Duration of the smoke and fire in seconds.
|
||||
-- @param #number Delay (Optional) Delay before the smoke and fire is started in seconds.
|
||||
-- @param #string name (Optional) Name of the fire to stop it later again if not using the same COORDINATE object. Defaults to "Fire-" plus a random 5-digit-number.
|
||||
function COORDINATE:BigSmokeSmall( density, name )
|
||||
self:F2( { density=density } )
|
||||
density=density or 0.5
|
||||
self:BigSmokeAndFire(BIGSMOKEPRESET.SmallSmoke, density, name)
|
||||
-- @return #COORDINATE self
|
||||
function COORDINATE:BigSmokeSmall( Density, Duration, Delay, Name )
|
||||
self:BigSmokeAndFire(BIGSMOKEPRESET.SmallSmoke, Density, Duration, Delay, Name)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Medium smoke at the coordinate.
|
||||
-- @param #COORDINATE self
|
||||
-- @param number density (Optional) Smoke density. Number between 0 and 1. Default 0.5.
|
||||
-- @param #number Duration (Optional) Duration of the smoke and fire in seconds.
|
||||
-- @param #number Delay (Optional) Delay before the smoke and fire is started in seconds.
|
||||
-- @param #string name (Optional) Name of the fire to stop it later again if not using the same COORDINATE object. Defaults to "Fire-" plus a random 5-digit-number.
|
||||
function COORDINATE:BigSmokeMedium( density, name )
|
||||
self:F2( { density=density } )
|
||||
density=density or 0.5
|
||||
self:BigSmokeAndFire(BIGSMOKEPRESET.MediumSmoke, density, name)
|
||||
-- @return #COORDINATE self
|
||||
function COORDINATE:BigSmokeMedium( Density, Duration, Delay, Name )
|
||||
self:BigSmokeAndFire(BIGSMOKEPRESET.MediumSmoke, Density, Duration, Delay, Name)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Large smoke at the coordinate.
|
||||
-- @param #COORDINATE self
|
||||
-- @param #number density (Optional) Smoke density. Number between 0 and 1. Default 0.5.
|
||||
-- @param #number Duration (Optional) Duration of the smoke and fire in seconds.
|
||||
-- @param #number Delay (Optional) Delay before the smoke and fire is started in seconds.
|
||||
-- @param #string name (Optional) Name of the fire to stop it later again if not using the same COORDINATE object. Defaults to "Fire-" plus a random 5-digit-number.
|
||||
function COORDINATE:BigSmokeLarge( density, name )
|
||||
self:F2( { density=density } )
|
||||
density=density or 0.5
|
||||
self:BigSmokeAndFire(BIGSMOKEPRESET.LargeSmoke, density,name)
|
||||
-- @return #COORDINATE self
|
||||
function COORDINATE:BigSmokeLarge( Density, Duration, Delay, Name )
|
||||
self:BigSmokeAndFire(BIGSMOKEPRESET.LargeSmoke, Density, Duration, Delay, Name)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Huge smoke at the coordinate.
|
||||
-- @param #COORDINATE self
|
||||
-- @param #number density (Optional) Smoke density. Number between 0 and 1. Default 0.5.
|
||||
-- @param #number Duration (Optional) Duration of the smoke and fire in seconds.
|
||||
-- @param #number Delay (Optional) Delay before the smoke and fire is started in seconds.
|
||||
-- @param #string name (Optional) Name of the fire to stop it later again if not using the same COORDINATE object. Defaults to "Fire-" plus a random 5-digit-number.
|
||||
function COORDINATE:BigSmokeHuge( density, name )
|
||||
self:F2( { density=density } )
|
||||
density=density or 0.5
|
||||
self:BigSmokeAndFire(BIGSMOKEPRESET.HugeSmoke, density,name)
|
||||
-- @return #COORDINATE self
|
||||
function COORDINATE:BigSmokeHuge( Density, Duration, Delay, Name )
|
||||
self:BigSmokeAndFire(BIGSMOKEPRESET.HugeSmoke, Density, Duration, Delay, Name)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Flares the point in a color.
|
||||
@@ -2765,8 +3073,10 @@ do -- COORDINATE
|
||||
local sunrise=UTILS.GetSunRiseAndSet(DayOfYear, Latitude, Longitude, true, Tdiff)
|
||||
local sunset=UTILS.GetSunRiseAndSet(DayOfYear, Latitude, Longitude, false, Tdiff)
|
||||
|
||||
if sunrise == "N/R" then return false end
|
||||
if sunrise == "N/S" then return true end
|
||||
if type(sunrise) == "string" or type(sunset) == "string" then
|
||||
if sunrise == "N/R" then return false end
|
||||
if sunset == "N/S" then return true end
|
||||
end
|
||||
|
||||
local time=UTILS.ClockToSeconds(clock)
|
||||
|
||||
@@ -2784,6 +3094,11 @@ do -- COORDINATE
|
||||
|
||||
-- Todays sun set in sec.
|
||||
local sunset=self:GetSunset(true)
|
||||
|
||||
if type(sunrise) == "string" or type(sunset) == "string" then
|
||||
if sunrise == "N/R" then return false end
|
||||
if sunset == "N/S" then return true end
|
||||
end
|
||||
|
||||
-- Seconds passed since midnight.
|
||||
local time=UTILS.SecondsOfToday()
|
||||
@@ -3474,9 +3789,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 +3817,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 +3906,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 +3966,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
|
||||
|
||||
@@ -15,8 +15,7 @@
|
||||
-- @module Core.Report
|
||||
-- @image Core_Report.JPG
|
||||
|
||||
---
|
||||
-- @type REPORT
|
||||
--- @type REPORT
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
--- Provides a handy means to create messages and reports.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
---- **Core** - SCHEDULEDISPATCHER dispatches the different schedules.
|
||||
--- **Core** - SCHEDULEDISPATCHER dispatches the different schedules.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
|
||||
@@ -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 = {},
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
do -- UserFlag
|
||||
|
||||
-- @type USERFLAG
|
||||
--- @type USERFLAG
|
||||
-- @field #string ClassName Name of the class
|
||||
-- @field #string UserFlagName Name of the flag.
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
do -- Velocity
|
||||
|
||||
-- @type VELOCITY
|
||||
--- @type VELOCITY
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
|
||||
@@ -127,7 +127,7 @@ end
|
||||
|
||||
do -- VELOCITY_POSITIONABLE
|
||||
|
||||
-- @type VELOCITY_POSITIONABLE
|
||||
--- @type VELOCITY_POSITIONABLE
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
|
||||
|
||||
@@ -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 } )
|
||||
|
||||
@@ -330,16 +330,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 +814,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 +1010,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 +1040,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 +1561,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 +1592,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 +2036,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 +2192,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 +2769,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 +2804,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 +2880,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 +3931,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 +4082,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 } )
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -198,7 +198,7 @@ end -- env
|
||||
|
||||
do -- radio
|
||||
|
||||
---@type radio
|
||||
--@type radio
|
||||
-- @field #radio.modulation modulation
|
||||
|
||||
---
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,806 +0,0 @@
|
||||
--- **Functional** -- Send a truck to supply artillery groups.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- **AMMOTRUCK** - Send a truck to supply artillery groups.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ## Missions:
|
||||
--
|
||||
-- Demo missions can be found on [GitHub](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/Functional/AmmoTruck)
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author : **applevangelist**
|
||||
--
|
||||
-- @module Functional.AmmoTruck
|
||||
-- @image Artillery.JPG
|
||||
--
|
||||
-- Last update: July 2023
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
--- **AMMOTRUCK** class, extends Core.Fsm#FSM
|
||||
-- @type AMMOTRUCK
|
||||
-- @field #string ClassName Class Name
|
||||
-- @field #string lid Lid for log entries
|
||||
-- @field #string version Version string
|
||||
-- @field #string alias Alias name
|
||||
-- @field #boolean debug Debug flag
|
||||
-- @field #table trucklist List of (alive) #AMMOTRUCK.data trucks
|
||||
-- @field #table targetlist List of (alive) #AMMOTRUCK.data artillery
|
||||
-- @field #number coalition Coalition this is for
|
||||
-- @field Core.Set#SET_GROUP truckset SET of trucks
|
||||
-- @field Core.Set#SET_GROUP targetset SET of artillery
|
||||
-- @field #table remunitionqueue List of (alive) #AMMOTRUCK.data artillery to be reloaded
|
||||
-- @field #table waitingtargets List of (alive) #AMMOTRUCK.data artillery waiting
|
||||
-- @field #number ammothreshold Threshold (min) ammo before sending a truck
|
||||
-- @field #number remunidist Max distance trucks will go
|
||||
-- @field #number monitor Monitor interval in seconds
|
||||
-- @field #number unloadtime Unload time in seconds
|
||||
-- @field #number waitingtime Max waiting time in seconds
|
||||
-- @field #boolean routeonroad Route truck on road if true (default)
|
||||
-- @field #number reloads Number of reloads a single truck can do before he must return home
|
||||
-- @extends Core.Fsm#FSM
|
||||
|
||||
--- *Amateurs talk about tactics, but professionals study logistics.* - General Robert H Barrow, USMC
|
||||
--
|
||||
-- Simple Class to re-arm your artillery with trucks.
|
||||
--
|
||||
-- #AMMOTRUCK
|
||||
--
|
||||
-- * Controls a SET\_GROUP of trucks which will re-arm a SET\_GROUP of artillery groups when they run out of ammunition.
|
||||
--
|
||||
-- ## 1 The AMMOTRUCK concept
|
||||
--
|
||||
-- A SET\_GROUP of trucks which will re-arm a SET\_GROUP of artillery groups when they run out of ammunition. They will be based on a
|
||||
-- homebase and drive from there to the artillery groups and then back home.
|
||||
-- Trucks are the **only known in-game mechanic** to re-arm artillery and other units in DCS. Working units are e.g.: M-939 (blue), Ural-375 and ZIL-135 (both red).
|
||||
--
|
||||
-- ## 2 Set-up
|
||||
--
|
||||
-- Define a set of trucks and a set of artillery:
|
||||
--
|
||||
-- local truckset = SET_GROUP:New():FilterCoalitions("blue"):FilterActive(true):FilterCategoryGround():FilterPrefixes("Ammo Truck"):FilterStart()
|
||||
-- local ariset = SET_GROUP:New():FilterCoalitions("blue"):FilterActive(true):FilterCategoryGround():FilterPrefixes("Artillery"):FilterStart()
|
||||
--
|
||||
-- Create an AMMOTRUCK object to take care of the artillery using the trucks, with a homezone:
|
||||
--
|
||||
-- local ammotruck = AMMOTRUCK:New(truckset,ariset,coalition.side.BLUE,"Logistics",ZONE:FindByName("HomeZone")
|
||||
--
|
||||
-- ## 2 Options and their default values
|
||||
--
|
||||
-- ammotruck.ammothreshold = 5 -- send a truck when down to this many rounds
|
||||
-- ammotruck.remunidist = 20000 -- 20km - send trucks max this far from home
|
||||
-- ammotruck.unloadtime = 600 -- 10 minutes - min time to unload ammunition
|
||||
-- ammotruck.waitingtime = 1800 -- 30 mintes - wait max this long until remunition is done
|
||||
-- ammotruck.monitor = -60 -- 1 minute - AMMOTRUCK checks run every one minute
|
||||
-- ammotruck.routeonroad = true -- Trucks will **try** to drive on roads
|
||||
-- ammotruck.usearmygroup = false -- If true, will make use of ARMYGROUP in the background (if used in DEV branch)
|
||||
-- ammotruck.reloads = 5 -- Maxn re-arms a truck can do before he needs to go home and restock. Set to -1 for unlimited
|
||||
--
|
||||
-- ## 3 FSM Events to shape mission
|
||||
--
|
||||
-- Truck has been sent off:
|
||||
--
|
||||
-- function ammotruck:OnAfterRouteTruck(From, Event, To, Truckdata, Aridata)
|
||||
-- ...
|
||||
-- end
|
||||
--
|
||||
-- Truck has arrived:
|
||||
--
|
||||
-- function ammotruck:OnAfterTruckArrived(From, Event, To, Truckdata)
|
||||
-- ...
|
||||
-- end
|
||||
--
|
||||
-- Truck is unloading:
|
||||
--
|
||||
-- function ammotruck:OnAfterTruckUnloading(From, Event, To, Truckdata)
|
||||
-- ...
|
||||
-- end
|
||||
--
|
||||
-- Truck is returning home:
|
||||
--
|
||||
-- function ammotruck:OnAfterTruckReturning(From, Event, To, Truckdata)
|
||||
-- ...
|
||||
-- end
|
||||
--
|
||||
-- Truck is arrived at home:
|
||||
--
|
||||
-- function ammotruck:OnAfterTruckHome(From, Event, To, Truckdata)
|
||||
-- ...
|
||||
-- end
|
||||
--
|
||||
-- @field #AMMOTRUCK
|
||||
AMMOTRUCK = {
|
||||
ClassName = "AMMOTRUCK",
|
||||
lid = "",
|
||||
version = "0.0.12",
|
||||
alias = "",
|
||||
debug = false,
|
||||
trucklist = {},
|
||||
targetlist = {},
|
||||
coalition = nil,
|
||||
truckset = nil,
|
||||
targetset = nil,
|
||||
remunitionqueue = {},
|
||||
waitingtargets = {},
|
||||
ammothreshold = 5,
|
||||
remunidist = 20000,
|
||||
monitor = -60,
|
||||
unloadtime = 600,
|
||||
waitingtime = 1800,
|
||||
routeonroad = true,
|
||||
reloads = 5,
|
||||
}
|
||||
|
||||
---
|
||||
-- @type AMMOTRUCK.State
|
||||
AMMOTRUCK.State = {
|
||||
IDLE = "idle",
|
||||
DRIVING = "driving",
|
||||
ARRIVED = "arrived",
|
||||
UNLOADING = "unloading",
|
||||
RETURNING = "returning",
|
||||
WAITING = "waiting",
|
||||
RELOADING = "reloading",
|
||||
OUTOFAMMO = "outofammo",
|
||||
REQUESTED = "requested",
|
||||
}
|
||||
|
||||
---
|
||||
--@type AMMOTRUCK.data
|
||||
--@field Wrapper.Group#GROUP group
|
||||
--@field #string name
|
||||
--@field #AMMOTRUCK.State statusquo
|
||||
--@field #number timestamp
|
||||
--@field #number ammo
|
||||
--@field Core.Point#COORDINATE coordinate
|
||||
--@field #string targetname
|
||||
--@field Wrapper.Group#GROUP targetgroup
|
||||
--@field Core.Point#COORDINATE targetcoordinate
|
||||
--@field #number reloads
|
||||
|
||||
---
|
||||
-- @param #AMMOTRUCK self
|
||||
-- @param Core.Set#SET_GROUP Truckset Set of truck groups
|
||||
-- @param Core.Set#SET_GROUP Targetset Set of artillery groups
|
||||
-- @param #number Coalition Coalition
|
||||
-- @param #string Alias Alias Name
|
||||
-- @param Core.Zone#ZONE Homezone Home, return zone for trucks
|
||||
-- @return #AMMOTRUCK self
|
||||
-- @usage
|
||||
-- Define a set of trucks and a set of artillery:
|
||||
-- local truckset = SET_GROUP:New():FilterCoalitions("blue"):FilterActive(true):FilterCategoryGround():FilterPrefixes("Ammo Truck"):FilterStart()
|
||||
-- local ariset = SET_GROUP:New():FilterCoalitions("blue"):FilterActive(true):FilterCategoryGround():FilterPrefixes("Artillery"):FilterStart()
|
||||
--
|
||||
-- Create an AMMOTRUCK object to take care of the artillery using the trucks, with a homezone:
|
||||
-- local ammotruck = AMMOTRUCK:New(truckset,ariset,coalition.side.BLUE,"Logistics",ZONE:FindByName("HomeZone")
|
||||
function AMMOTRUCK:New(Truckset,Targetset,Coalition,Alias,Homezone)
|
||||
|
||||
-- Inherit everything from BASE class.
|
||||
local self=BASE:Inherit(self, FSM:New()) -- #AMMOTRUCK
|
||||
|
||||
self.truckset = Truckset -- Core.Set#SET_GROUP
|
||||
self.targetset = Targetset -- Core.Set#SET_GROUP
|
||||
self.coalition = Coalition -- #number
|
||||
self.alias = Alias -- #string
|
||||
self.debug = false
|
||||
self.remunitionqueue = {}
|
||||
self.trucklist = {}
|
||||
self.targetlist = {}
|
||||
self.ammothreshold = 5
|
||||
self.remunidist = 20000
|
||||
self.homezone = Homezone -- Core.Zone#ZONE
|
||||
self.waitingtime = 1800
|
||||
self.usearmygroup = false
|
||||
self.hasarmygroup = false
|
||||
|
||||
-- Log id.
|
||||
self.lid=string.format("AMMOTRUCK %s | %s | ", self.version, self.alias)
|
||||
|
||||
self:SetStartState("Stopped")
|
||||
self:AddTransition("Stopped", "Start", "Running")
|
||||
self:AddTransition("*", "Monitor", "*")
|
||||
self:AddTransition("*", "RouteTruck", "*")
|
||||
self:AddTransition("*", "TruckArrived", "*")
|
||||
self:AddTransition("*", "TruckUnloading", "*")
|
||||
self:AddTransition("*", "TruckReturning", "*")
|
||||
self:AddTransition("*", "TruckHome", "*")
|
||||
self:AddTransition("*", "Stop", "Stopped")
|
||||
|
||||
self:__Start(math.random(5,10))
|
||||
|
||||
self:I(self.lid .. "Started")
|
||||
|
||||
------------------------
|
||||
--- Pseudo Functions ---
|
||||
------------------------
|
||||
|
||||
--- Triggers the FSM event "Stop". Stops the AMMOTRUCK and all its event handlers.
|
||||
-- @function [parent=#AMMOTRUCK] Stop
|
||||
-- @param #AMMOTRUCK self
|
||||
|
||||
--- Triggers the FSM event "Stop" after a delay. Stops the AMMOTRUCK and all its event handlers.
|
||||
-- @function [parent=#AMMOTRUCK] __Stop
|
||||
-- @param #AMMOTRUCK self
|
||||
-- @param #number delay Delay in seconds.
|
||||
|
||||
--- On after "RouteTruck" event.
|
||||
-- @function [parent=#AMMOTRUCK] OnAfterRouteTruck
|
||||
-- @param #AMMOTRUCK self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param #AMMOTRUCK.data Truck
|
||||
-- @param #AMMOTRUCK.data Artillery
|
||||
|
||||
--- On after "TruckUnloading" event.
|
||||
-- @function [parent=#AMMOTRUCK] OnAfterTruckUnloading
|
||||
-- @param #AMMOTRUCK self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param #AMMOTRUCK.data Truck
|
||||
|
||||
--- On after "TruckReturning" event.
|
||||
-- @function [parent=#AMMOTRUCK] OnAfterTruckReturning
|
||||
-- @param #AMMOTRUCK self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param #AMMOTRUCK.data Truck
|
||||
|
||||
--- On after "RouteTruck" event.
|
||||
-- @function [parent=#AMMOTRUCK] OnAfterRouteTruck
|
||||
-- @param #AMMOTRUCK self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param #AMMOTRUCK.data Truck
|
||||
|
||||
--- On after "TruckHome" event.
|
||||
-- @function [parent=#AMMOTRUCK] OnAfterTruckHome
|
||||
-- @param #AMMOTRUCK self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param #AMMOTRUCK.data Truck
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
---
|
||||
-- @param #AMMOTRUCK self
|
||||
-- @param #table dataset table of #AMMOTRUCK.data entries
|
||||
-- @return #AMMOTRUCK self
|
||||
function AMMOTRUCK:CheckDrivingTrucks(dataset)
|
||||
self:T(self.lid .. " CheckDrivingTrucks")
|
||||
local data = dataset
|
||||
for _,_data in pairs (data) do
|
||||
local truck = _data -- #AMMOTRUCK.data
|
||||
-- see if we arrived at destination
|
||||
local coord = truck.group:GetCoordinate()
|
||||
local tgtcoord = truck.targetcoordinate
|
||||
local dist = coord:Get2DDistance(tgtcoord)
|
||||
if dist <= 150 then
|
||||
-- arrived
|
||||
truck.statusquo = AMMOTRUCK.State.ARRIVED
|
||||
truck.timestamp = timer.getAbsTime()
|
||||
truck.coordinate = coord
|
||||
self:__TruckArrived(1,truck)
|
||||
end
|
||||
-- still driving?
|
||||
local Tnow = timer.getAbsTime()
|
||||
if Tnow - truck.timestamp > 30 then
|
||||
local group = truck.group
|
||||
if self.usearmygroup then
|
||||
group = truck.group:GetGroup()
|
||||
end
|
||||
local currspeed = group:GetVelocityKMH()
|
||||
if truck.lastspeed then
|
||||
if truck.lastspeed == 0 and currspeed == 0 then
|
||||
self:T(truck.group:GetName().." Is not moving!")
|
||||
-- try and move it
|
||||
truck.timestamp = timer.getAbsTime()
|
||||
if self.routeonroad then
|
||||
group:RouteGroundOnRoad(truck.targetcoordinate,30,2,"Vee")
|
||||
else
|
||||
group:RouteGroundTo(truck.targetcoordinate,30,"Vee",2)
|
||||
end
|
||||
end
|
||||
truck.lastspeed = currspeed
|
||||
else
|
||||
truck.lastspeed = currspeed
|
||||
truck.timestamp = timer.getAbsTime()
|
||||
end
|
||||
self:I({truck=truck.group:GetName(),currspeed=currspeed,lastspeed=truck.lastspeed})
|
||||
end
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
---
|
||||
-- @param #AMMOTRUCK self
|
||||
-- @param Wrapper.Group#GROUP Group
|
||||
-- @return #AMMOTRUCK self
|
||||
function AMMOTRUCK:GetAmmoStatus(Group)
|
||||
local ammotot, shells, rockets, bombs, missiles, narti = Group:GetAmmunition()
|
||||
return rockets+missiles+narti
|
||||
end
|
||||
|
||||
---
|
||||
-- @param #AMMOTRUCK self
|
||||
-- @param #table dataset table of #AMMOTRUCK.data entries
|
||||
-- @return #AMMOTRUCK self
|
||||
function AMMOTRUCK:CheckWaitingTargets(dataset)
|
||||
self:T(self.lid .. " CheckWaitingTargets")
|
||||
local data = dataset
|
||||
for _,_data in pairs (data) do
|
||||
local truck = _data -- #AMMOTRUCK.data
|
||||
-- see how long we're waiting - maybe ammo truck is dead?
|
||||
local Tnow = timer.getAbsTime()
|
||||
local Tdiff = Tnow - truck.timestamp
|
||||
if Tdiff > self.waitingtime then
|
||||
local hasammo = self:GetAmmoStatus(truck.group)
|
||||
if hasammo <= self.ammothreshold then
|
||||
truck.statusquo = AMMOTRUCK.State.OUTOFAMMO
|
||||
else
|
||||
truck.statusquo = AMMOTRUCK.State.IDLE
|
||||
end
|
||||
end
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
---
|
||||
-- @param #AMMOTRUCK self
|
||||
-- @param #table dataset table of #AMMOTRUCK.data entries
|
||||
-- @return #AMMOTRUCK self
|
||||
function AMMOTRUCK:CheckReturningTrucks(dataset)
|
||||
self:T(self.lid .. " CheckReturningTrucks")
|
||||
local data = dataset
|
||||
local tgtcoord = self.homezone:GetCoordinate()
|
||||
local radius = self.homezone:GetRadius()
|
||||
for _,_data in pairs (data) do
|
||||
local truck = _data -- #AMMOTRUCK.data
|
||||
-- see if we arrived at destination
|
||||
local coord = truck.group:GetCoordinate()
|
||||
local dist = coord:Get2DDistance(tgtcoord)
|
||||
self:T({name=truck.name,radius=radius,distance=dist})
|
||||
if dist <= radius then
|
||||
-- arrived
|
||||
truck.statusquo = AMMOTRUCK.State.IDLE
|
||||
truck.timestamp = timer.getAbsTime()
|
||||
truck.coordinate = coord
|
||||
truck.reloads = self.reloads or 5
|
||||
self:__TruckHome(1,truck)
|
||||
end
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
---
|
||||
-- @param #AMMOTRUCK self
|
||||
-- @param #string name Artillery group name to find
|
||||
-- @return #AMMOTRUCK.data Data
|
||||
function AMMOTRUCK:FindTarget(name)
|
||||
self:T(self.lid .. " FindTarget")
|
||||
local data = nil
|
||||
local dataset = self.targetlist
|
||||
for _,_entry in pairs(dataset) do
|
||||
local entry = _entry -- #AMMOTRUCK.data
|
||||
if entry.name == name then
|
||||
data = entry
|
||||
break
|
||||
end
|
||||
end
|
||||
return data
|
||||
end
|
||||
|
||||
---
|
||||
-- @param #AMMOTRUCK self
|
||||
-- @param #string name Truck group name to find
|
||||
-- @return #AMMOTRUCK.data Data
|
||||
function AMMOTRUCK:FindTruck(name)
|
||||
self:T(self.lid .. " FindTruck")
|
||||
local data = nil
|
||||
local dataset = self.trucklist
|
||||
for _,_entry in pairs(dataset) do
|
||||
local entry = _entry -- #AMMOTRUCK.data
|
||||
if entry.name == name then
|
||||
data = entry
|
||||
break
|
||||
end
|
||||
end
|
||||
return data
|
||||
end
|
||||
|
||||
---
|
||||
-- @param #AMMOTRUCK self
|
||||
-- @param #table dataset table of #AMMOTRUCK.data entries
|
||||
-- @return #AMMOTRUCK self
|
||||
function AMMOTRUCK:CheckArrivedTrucks(dataset)
|
||||
self:T(self.lid .. " CheckArrivedTrucks")
|
||||
local data = dataset
|
||||
for _,_data in pairs (data) do
|
||||
-- set to unloading
|
||||
local truck = _data -- #AMMOTRUCK.data
|
||||
truck.statusquo = AMMOTRUCK.State.UNLOADING
|
||||
truck.timestamp = timer.getAbsTime()
|
||||
self:__TruckUnloading(2,truck)
|
||||
-- set target to reloading
|
||||
local aridata = self:FindTarget(truck.targetname) -- #AMMOTRUCK.data
|
||||
if aridata then
|
||||
aridata.statusquo = AMMOTRUCK.State.RELOADING
|
||||
aridata.timestamp = timer.getAbsTime()
|
||||
end
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
---
|
||||
-- @param #AMMOTRUCK self
|
||||
-- @param #table dataset table of #AMMOTRUCK.data entries
|
||||
-- @return #AMMOTRUCK self
|
||||
function AMMOTRUCK:CheckUnloadingTrucks(dataset)
|
||||
self:T(self.lid .. " CheckUnloadingTrucks")
|
||||
local data = dataset
|
||||
for _,_data in pairs (data) do
|
||||
-- check timestamp
|
||||
local truck = _data -- #AMMOTRUCK.data
|
||||
local Tnow = timer.getAbsTime()
|
||||
local Tpassed = Tnow - truck.timestamp
|
||||
local hasammo = self:GetAmmoStatus(truck.targetgroup)
|
||||
if Tpassed > self.unloadtime and hasammo > self.ammothreshold then
|
||||
truck.statusquo = AMMOTRUCK.State.RETURNING
|
||||
truck.timestamp = timer.getAbsTime()
|
||||
self:__TruckReturning(2,truck)
|
||||
-- set target to reloaded
|
||||
local aridata = self:FindTarget(truck.targetname) -- #AMMOTRUCK.data
|
||||
if aridata then
|
||||
aridata.statusquo = AMMOTRUCK.State.IDLE
|
||||
aridata.timestamp = timer.getAbsTime()
|
||||
end
|
||||
end
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
---
|
||||
-- @param #AMMOTRUCK self
|
||||
-- @return #AMMOTRUCK self
|
||||
function AMMOTRUCK:CheckTargetsAlive()
|
||||
self:T(self.lid .. " CheckTargetsAlive")
|
||||
local arilist = self.targetlist
|
||||
for _,_ari in pairs(arilist) do
|
||||
local ari = _ari -- #AMMOTRUCK.data
|
||||
if ari.group and ari.group:IsAlive() then
|
||||
-- everything fine
|
||||
else
|
||||
-- ari dead
|
||||
self.targetlist[ari.name] = nil
|
||||
end
|
||||
end
|
||||
-- new arrivals?
|
||||
local aritable = self.targetset:GetSetObjects() --#table
|
||||
for _,_ari in pairs(aritable) do
|
||||
local ari = _ari -- Wrapper.Group#GROUP
|
||||
if ari and ari:IsAlive() and not self.targetlist[ari:GetName()] then
|
||||
local name = ari:GetName()
|
||||
local newari = {} -- #AMMOTRUCK.data
|
||||
newari.name = name
|
||||
newari.group = ari
|
||||
newari.statusquo = AMMOTRUCK.State.IDLE
|
||||
newari.timestamp = timer.getAbsTime()
|
||||
newari.coordinate = ari:GetCoordinate()
|
||||
local hasammo = self:GetAmmoStatus(ari)
|
||||
--newari.ammo = ari:GetAmmunition()
|
||||
newari.ammo = hasammo
|
||||
self.targetlist[name] = newari
|
||||
end
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
---
|
||||
-- @param #AMMOTRUCK self
|
||||
-- @return #AMMOTRUCK self
|
||||
function AMMOTRUCK:CheckTrucksAlive()
|
||||
self:T(self.lid .. " CheckTrucksAlive")
|
||||
local trucklist = self.trucklist
|
||||
for _,_truck in pairs(trucklist) do
|
||||
local truck = _truck -- #AMMOTRUCK.data
|
||||
if truck.group and truck.group:IsAlive() then
|
||||
-- everything fine
|
||||
else
|
||||
-- truck dead
|
||||
local tgtname = truck.targetname
|
||||
local targetdata = self:FindTarget(tgtname) -- #AMMOTRUCK.data
|
||||
if targetdata then
|
||||
if targetdata.statusquo ~= AMMOTRUCK.State.IDLE then
|
||||
targetdata.statusquo = AMMOTRUCK.State.IDLE
|
||||
end
|
||||
end
|
||||
self.trucklist[truck.name] = nil
|
||||
end
|
||||
end
|
||||
-- new arrivals?
|
||||
local trucktable = self.truckset:GetSetObjects() --#table
|
||||
for _,_truck in pairs(trucktable) do
|
||||
local truck = _truck -- Wrapper.Group#GROUP
|
||||
if truck and truck:IsAlive() and not self.trucklist[truck:GetName()] then
|
||||
local name = truck:GetName()
|
||||
local newtruck = {} -- #AMMOTRUCK.data
|
||||
newtruck.name = name
|
||||
newtruck.group = truck
|
||||
if self.hasarmygroup then
|
||||
-- is (not) already ARMYGROUP?
|
||||
if truck.ClassName and truck.ClassName == "GROUP" then
|
||||
local trucker = ARMYGROUP:New(truck)
|
||||
trucker:Activate()
|
||||
newtruck.group = trucker
|
||||
end
|
||||
end
|
||||
newtruck.statusquo = AMMOTRUCK.State.IDLE
|
||||
newtruck.timestamp = timer.getAbsTime()
|
||||
newtruck.coordinate = truck:GetCoordinate()
|
||||
newtruck.reloads = self.reloads or 5
|
||||
self.trucklist[name] = newtruck
|
||||
end
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
---
|
||||
-- @param #AMMOTRUCK self
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @return #AMMOTRUCK self
|
||||
function AMMOTRUCK:onafterStart(From, Event, To)
|
||||
self:T({From, Event, To})
|
||||
if ARMYGROUP and self.usearmygroup then
|
||||
self.hasarmygroup = true
|
||||
else
|
||||
self.hasarmygroup = false
|
||||
end
|
||||
if self.debug then
|
||||
BASE:TraceOn()
|
||||
BASE:TraceClass("AMMOTRUCK")
|
||||
end
|
||||
self:CheckTargetsAlive()
|
||||
self:CheckTrucksAlive()
|
||||
self:__Monitor(-30)
|
||||
return self
|
||||
end
|
||||
|
||||
---
|
||||
-- @param #AMMOTRUCK self
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @return #AMMOTRUCK self
|
||||
function AMMOTRUCK:onafterMonitor(From, Event, To)
|
||||
self:T({From, Event, To})
|
||||
self:CheckTargetsAlive()
|
||||
self:CheckTrucksAlive()
|
||||
-- update ammo state
|
||||
local remunition = false
|
||||
local remunitionqueue = {}
|
||||
local waitingtargets = {}
|
||||
for _,_ari in pairs(self.targetlist) do
|
||||
local data = _ari -- #AMMOTRUCK.data
|
||||
if data.group and data.group:IsAlive() then
|
||||
data.ammo = self:GetAmmoStatus(data.group)
|
||||
data.timestamp = timer.getAbsTime()
|
||||
local text = string.format("Ari %s | Ammo %d | State %s",data.name,data.ammo,data.statusquo)
|
||||
self:T(text)
|
||||
if data.ammo <= self.ammothreshold and (data.statusquo == AMMOTRUCK.State.IDLE or data.statusquo == AMMOTRUCK.State.OUTOFAMMO) then
|
||||
-- add to remu queue
|
||||
data.statusquo = AMMOTRUCK.State.OUTOFAMMO
|
||||
remunitionqueue[#remunitionqueue+1] = data
|
||||
remunition = true
|
||||
elseif data.statusquo == AMMOTRUCK.State.WAITING then
|
||||
waitingtargets[#waitingtargets+1] = data
|
||||
end
|
||||
else
|
||||
self.targetlist[data.name] = nil
|
||||
end
|
||||
end
|
||||
-- sort trucks in buckets
|
||||
local idletrucks = {}
|
||||
local drivingtrucks = {}
|
||||
local unloadingtrucks = {}
|
||||
local arrivedtrucks = {}
|
||||
local returningtrucks = {}
|
||||
local found = false
|
||||
for _,_truckdata in pairs(self.trucklist) do
|
||||
local data = _truckdata -- #AMMOTRUCK.data
|
||||
if data.group and data.group:IsAlive() then
|
||||
-- check state
|
||||
local text = string.format("Truck %s | State %s",data.name,data.statusquo)
|
||||
self:T(text)
|
||||
if data.statusquo == AMMOTRUCK.State.IDLE then
|
||||
idletrucks[#idletrucks+1] = data
|
||||
found = true
|
||||
elseif data.statusquo == AMMOTRUCK.State.DRIVING then
|
||||
drivingtrucks[#drivingtrucks+1] = data
|
||||
elseif data.statusquo == AMMOTRUCK.State.ARRIVED then
|
||||
arrivedtrucks[#arrivedtrucks+1] = data
|
||||
elseif data.statusquo == AMMOTRUCK.State.UNLOADING then
|
||||
unloadingtrucks[#unloadingtrucks+1] = data
|
||||
elseif data.statusquo == AMMOTRUCK.State.RETURNING then
|
||||
returningtrucks[#returningtrucks+1] = data
|
||||
if data.reloads > 0 or data.reloads == -1 then
|
||||
idletrucks[#idletrucks+1] = data
|
||||
found = true
|
||||
end
|
||||
end
|
||||
else
|
||||
self.truckset[data.name] = nil
|
||||
end
|
||||
end
|
||||
-- see if we can/need route one
|
||||
local n=0
|
||||
if found and remunition then
|
||||
-- match
|
||||
--local match = false
|
||||
for _,_truckdata in pairs(idletrucks) do
|
||||
local truckdata = _truckdata -- #AMMOTRUCK.data
|
||||
local truckcoord = truckdata.group:GetCoordinate() -- Core.Point#COORDINATE
|
||||
for _,_aridata in pairs(remunitionqueue) do
|
||||
local aridata = _aridata -- #AMMOTRUCK.data
|
||||
local aricoord = aridata.coordinate
|
||||
local distance = truckcoord:Get2DDistance(aricoord)
|
||||
if distance <= self.remunidist and aridata.statusquo == AMMOTRUCK.State.OUTOFAMMO and n <= #idletrucks then
|
||||
n = n + 1
|
||||
aridata.statusquo = AMMOTRUCK.State.REQUESTED
|
||||
self:__RouteTruck(n*5,truckdata,aridata)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- check driving trucks
|
||||
if #drivingtrucks > 0 then
|
||||
self:CheckDrivingTrucks(drivingtrucks)
|
||||
end
|
||||
|
||||
-- check arrived trucks
|
||||
if #arrivedtrucks > 0 then
|
||||
self:CheckArrivedTrucks(arrivedtrucks)
|
||||
end
|
||||
|
||||
-- check unloading trucks
|
||||
if #unloadingtrucks > 0 then
|
||||
self:CheckUnloadingTrucks(unloadingtrucks)
|
||||
end
|
||||
|
||||
-- check returningtrucks trucks
|
||||
if #returningtrucks > 0 then
|
||||
self:CheckReturningTrucks(returningtrucks)
|
||||
end
|
||||
|
||||
-- check waiting targets
|
||||
if #waitingtargets > 0 then
|
||||
self:CheckWaitingTargets(waitingtargets)
|
||||
end
|
||||
|
||||
self:__Monitor(self.monitor)
|
||||
return self
|
||||
end
|
||||
|
||||
---
|
||||
-- @param #AMMOTRUCK self
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @param #AMMOTRUCK.data Truckdata
|
||||
-- @param #AMMOTRUCK.data Aridata
|
||||
-- @return #AMMOTRUCK self
|
||||
function AMMOTRUCK:onafterRouteTruck(From, Event, To, Truckdata, Aridata)
|
||||
self:T({From, Event, To, Truckdata.name, Aridata.name})
|
||||
local truckdata = Truckdata -- #AMMOTRUCK.data
|
||||
local aridata = Aridata -- #AMMOTRUCK.data
|
||||
local tgtgrp = aridata.group
|
||||
local tgtzone = ZONE_GROUP:New(aridata.name,tgtgrp,30)
|
||||
local tgtcoord = tgtzone:GetRandomCoordinate(15)
|
||||
if self.hasarmygroup then
|
||||
local mission = AUFTRAG:NewONGUARD(tgtcoord)
|
||||
local oldmission = truckdata.group:GetMissionCurrent()
|
||||
if oldmission then oldmission:Cancel() end
|
||||
mission:SetTime(5)
|
||||
mission:SetTeleport(false)
|
||||
truckdata.group:AddMission(mission)
|
||||
elseif self.routeonroad then
|
||||
truckdata.group:RouteGroundOnRoad(tgtcoord,30)
|
||||
else
|
||||
truckdata.group:RouteGroundTo(tgtcoord,30)
|
||||
end
|
||||
truckdata.statusquo = AMMOTRUCK.State.DRIVING
|
||||
truckdata.targetgroup = tgtgrp
|
||||
truckdata.targetname = aridata.name
|
||||
truckdata.targetcoordinate = tgtcoord
|
||||
aridata.statusquo = AMMOTRUCK.State.WAITING
|
||||
aridata.timestamp = timer.getAbsTime()
|
||||
return self
|
||||
end
|
||||
|
||||
---
|
||||
-- @param #AMMOTRUCK self
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @param #AMMOTRUCK.data Truckdata
|
||||
-- @return #AMMOTRUCK self
|
||||
function AMMOTRUCK:onafterTruckUnloading(From, Event, To, Truckdata)
|
||||
local m = MESSAGE:New("Truck "..Truckdata.name.." unloading!",15,"AmmoTruck"):ToCoalitionIf(self.coalition,self.debug)
|
||||
local truck = Truckdata -- Functional.AmmoTruck#AMMOTRUCK.data
|
||||
local coord = truck.group:GetCoordinate()
|
||||
local heading = truck.group:GetHeading()
|
||||
heading = heading < 180 and (360-heading) or (heading - 180)
|
||||
local cid = self.coalition == coalition.side.BLUE and country.id.USA or country.id.RUSSIA
|
||||
cid = self.coalition == coalition.side.NEUTRAL and country.id.UN_PEACEKEEPERS or cid
|
||||
|
||||
local ammo = {}
|
||||
for i=1,5 do
|
||||
ammo[i] = SPAWNSTATIC:NewFromType("ammo_cargo","Cargos",cid)
|
||||
:InitCoordinate(coord:Translate((15+((i-1)*4)),heading))
|
||||
:Spawn(0,"AmmoCrate-"..math.random(1,10000))
|
||||
end
|
||||
|
||||
local function destroyammo(ammo)
|
||||
for _,_crate in pairs(ammo) do
|
||||
_crate:Destroy(false)
|
||||
end
|
||||
end
|
||||
|
||||
local scheduler = SCHEDULER:New(nil,destroyammo,{ammo},self.waitingtime)
|
||||
|
||||
-- one reload less
|
||||
if truck.reloads ~= -1 then
|
||||
truck.reloads = truck.reloads - 1
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
---
|
||||
-- @param #AMMOTRUCK self
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @param #AMMOTRUCK.data Truck
|
||||
-- @return #AMMOTRUCK self
|
||||
function AMMOTRUCK:onafterTruckReturning(From, Event, To, Truck)
|
||||
self:T({From, Event, To, Truck.name})
|
||||
-- route home
|
||||
local truckdata = Truck -- #AMMOTRUCK.data
|
||||
local tgtzone = self.homezone
|
||||
local tgtcoord = tgtzone:GetRandomCoordinate()
|
||||
if self.hasarmygroup then
|
||||
local mission = AUFTRAG:NewONGUARD(tgtcoord)
|
||||
local oldmission = truckdata.group:GetMissionCurrent()
|
||||
if oldmission then oldmission:Cancel() end
|
||||
mission:SetTime(5)
|
||||
mission:SetTeleport(false)
|
||||
truckdata.group:AddMission(mission)
|
||||
elseif self.routeonroad then
|
||||
truckdata.group:RouteGroundOnRoad(tgtcoord,30,1,"Cone")
|
||||
else
|
||||
truckdata.group:RouteGroundTo(tgtcoord,30,"Cone",1)
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
---
|
||||
-- @param #AMMOTRUCK self
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @return #AMMOTRUCK self
|
||||
function AMMOTRUCK:onafterStop(From, Event, To)
|
||||
self:T({From, Event, To})
|
||||
return self
|
||||
end
|
||||
@@ -2386,12 +2386,12 @@ function ARTY:OnEventShot(EventData)
|
||||
self.Nukes=self.Nukes-1
|
||||
end
|
||||
|
||||
-- Decrease available illumination shells because we just fired one.
|
||||
-- Decrease available illuminatin shells because we just fired one.
|
||||
if self.currentTarget.weapontype==ARTY.WeaponType.IlluminationShells then
|
||||
self.Nillu=self.Nillu-1
|
||||
end
|
||||
|
||||
-- Decrease available smoke shells because we just fired one.
|
||||
-- Decrease available illuminatin shells because we just fired one.
|
||||
if self.currentTarget.weapontype==ARTY.WeaponType.SmokeShells then
|
||||
self.Nsmoke=self.Nsmoke-1
|
||||
end
|
||||
@@ -3804,6 +3804,51 @@ function ARTY:_NuclearBlast(_coord)
|
||||
ignite(_fires)
|
||||
end
|
||||
|
||||
--[[
|
||||
local ZoneNuke=ZONE_RADIUS:New("Nukezone", _coord:GetVec2(), 2000)
|
||||
|
||||
-- Scan for Scenery objects.
|
||||
ZoneNuke:Scan(Object.Category.SCENERY)
|
||||
|
||||
-- Array with all possible hideouts, i.e. scenery objects in the vicinity of the group.
|
||||
local scenery={}
|
||||
|
||||
for SceneryTypeName, SceneryData in pairs(ZoneNuke:GetScannedScenery()) do
|
||||
for SceneryName, SceneryObject in pairs(SceneryData) do
|
||||
|
||||
local SceneryObject = SceneryObject -- Wrapper.Scenery#SCENERY
|
||||
|
||||
-- Position of the scenery object.
|
||||
local spos=SceneryObject:GetCoordinate()
|
||||
|
||||
-- Distance from group to impact point.
|
||||
local distance= spos:Get2DDistance(_coord)
|
||||
|
||||
-- Place markers on every possible scenery object.
|
||||
if self.Debug then
|
||||
local MarkerID=spos:MarkToAll(string.format("%s scenery object %s", self.Controllable:GetName(), SceneryObject:GetTypeName()))
|
||||
local text=string.format("%s scenery: %s, Coord %s", self.Controllable:GetName(), SceneryObject:GetTypeName(), SceneryObject:GetCoordinate():ToStringLLDMS())
|
||||
self:T2(SUPPRESSION.id..text)
|
||||
end
|
||||
|
||||
-- Add to table.
|
||||
table.insert(scenery, {object=SceneryObject, distance=distance})
|
||||
|
||||
--SceneryObject:Destroy()
|
||||
end
|
||||
end
|
||||
|
||||
-- Sort scenery wrt to distance from impact point.
|
||||
-- local _sort = function(a,b) return a.distance < b.distance end
|
||||
-- table.sort(scenery,_sort)
|
||||
|
||||
-- for _,object in pairs(scenery) do
|
||||
-- local sobject=object -- Wrapper.Scenery#SCENERY
|
||||
-- sobject:Destroy()
|
||||
-- end
|
||||
|
||||
]]
|
||||
|
||||
end
|
||||
|
||||
--- Route group to a certain point.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -52,13 +52,11 @@
|
||||
-- @module Functional.CleanUp
|
||||
-- @image CleanUp_Airbases.JPG
|
||||
|
||||
---
|
||||
-- @type CLEANUP_AIRBASE.__ Methods which are not intended for mission designers, but which are used interally by the moose designer :-)
|
||||
--- @type CLEANUP_AIRBASE.__ Methods which are not intended for mission designers, but which are used interally by the moose designer :-)
|
||||
-- @field #map<#string,Wrapper.Airbase#AIRBASE> Airbases Map of Airbases.
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
---
|
||||
-- @type CLEANUP_AIRBASE
|
||||
--- @type CLEANUP_AIRBASE
|
||||
-- @extends #CLEANUP_AIRBASE.__
|
||||
|
||||
--- Keeps airbases clean, and tries to guarantee continuous airbase operations, even under combat.
|
||||
@@ -95,7 +93,7 @@ CLEANUP_AIRBASE = {
|
||||
-- @field #CLEANUP_AIRBASE.__
|
||||
CLEANUP_AIRBASE.__ = {}
|
||||
|
||||
-- @field #CLEANUP_AIRBASE.__.Airbases
|
||||
--- @field #CLEANUP_AIRBASE.__.Airbases
|
||||
CLEANUP_AIRBASE.__.Airbases = {}
|
||||
|
||||
--- Creates the main object which is handling the cleaning of the debris within the given Zone Names.
|
||||
@@ -242,8 +240,7 @@ function CLEANUP_AIRBASE.__:DestroyMissile( MissileObject )
|
||||
end
|
||||
end
|
||||
|
||||
---
|
||||
-- @param #CLEANUP_AIRBASE self
|
||||
--- @param #CLEANUP_AIRBASE self
|
||||
-- @param Core.Event#EVENTDATA EventData
|
||||
function CLEANUP_AIRBASE.__:OnEventBirth( EventData )
|
||||
self:F( { EventData } )
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
do -- DETECTION_ZONES
|
||||
|
||||
-- @type DETECTION_ZONES
|
||||
--- @type DETECTION_ZONES
|
||||
-- @field DCS#Distance DetectionZoneRange The range till which targets are grouped upon the first detected target.
|
||||
-- @field #DETECTION_BASE.DetectedItems DetectedItems A list of areas containing the set of @{Wrapper.Unit}s, @{Core.Zone}s, the center @{Wrapper.Unit} within the zone, and ID of each area that was detected within a DetectionZoneRange.
|
||||
-- @extends Functional.Detection#DETECTION_BASE
|
||||
@@ -68,7 +68,7 @@ do -- DETECTION_ZONES
|
||||
return self
|
||||
end
|
||||
|
||||
-- @param #DETECTION_ZONES self
|
||||
--- @param #DETECTION_ZONES self
|
||||
-- @param #number The amount of alive recce.
|
||||
function DETECTION_ZONES:CountAliveRecce()
|
||||
|
||||
@@ -76,7 +76,7 @@ do -- DETECTION_ZONES
|
||||
|
||||
end
|
||||
|
||||
-- @param #DETECTION_ZONES self
|
||||
--- @param #DETECTION_ZONES self
|
||||
function DETECTION_ZONES:ForEachAliveRecce( IteratorFunction, ... )
|
||||
self:F2( arg )
|
||||
|
||||
@@ -352,7 +352,7 @@ do -- DETECTION_ZONES
|
||||
--DetectedSet:Flush( self )
|
||||
|
||||
DetectedSet:ForEachUnit(
|
||||
-- @param Wrapper.Unit#UNIT DetectedUnit
|
||||
--- @param Wrapper.Unit#UNIT DetectedUnit
|
||||
function( DetectedUnit )
|
||||
if DetectedUnit:IsAlive() then
|
||||
--self:T( "Detected Set #" .. DetectedItem.ID .. ":" .. DetectedUnit:GetName() )
|
||||
@@ -380,7 +380,7 @@ do -- DETECTION_ZONES
|
||||
|
||||
end
|
||||
|
||||
-- @param #DETECTION_ZONES self
|
||||
--- @param #DETECTION_ZONES self
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
|
||||
@@ -141,7 +141,6 @@ FOX = {
|
||||
explosiondist = 200,
|
||||
explosiondist2 = 500,
|
||||
bigmissilemass = 50,
|
||||
--destroy = nil,
|
||||
dt50 = 5,
|
||||
dt10 = 1,
|
||||
dt05 = 0.5,
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
-- @module Functional.Mantis
|
||||
-- @image Functional.Mantis.jpg
|
||||
--
|
||||
-- Last Update: Mar 2025
|
||||
-- Last Update: May 2025
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
--- **MANTIS** class, extends Core.Base#BASE
|
||||
@@ -62,7 +62,9 @@
|
||||
-- @field #table FilterZones Table of Core.Zone#ZONE Zones Consider SAM groups in this zone(s) only for this MANTIS instance, must be handed as #table of Zone objects.
|
||||
-- @field #boolean SmokeDecoy If true, smoke short range SAM units as decoy if a plane is in firing range.
|
||||
-- @field #number SmokeDecoyColor Color to use, defaults to SMOKECOLOR.White
|
||||
-- @field #number checkcounter Counter for SAM Table refreshes
|
||||
-- @field #number checkcounter Counter for SAM Table refreshes.
|
||||
-- @field #number DLinkCacheTime Seconds after which cached contacts in DLink will decay.
|
||||
-- @field #boolean logsamstatus Log SAM status in dcs.log every cycle if true
|
||||
-- @extends Core.Base#BASE
|
||||
|
||||
|
||||
@@ -74,10 +76,9 @@
|
||||
--
|
||||
-- * Moose derived Modular, Automatic and Network capable Targeting and Interception System.
|
||||
-- * Controls a network of SAM sites. Uses detection to switch on the SAM site closest to the enemy.
|
||||
-- * **Automatic mode** (default since 0.8) will set-up your SAM site network automatically for you
|
||||
-- * **Classic mode** behaves like before
|
||||
-- * Leverage evasiveness from SEAD, leverage attack range setting
|
||||
-- * Automatic setup of SHORAD based on groups of the class "short-range"
|
||||
-- * **Automatic mode** (default) will set-up your SAM site network automatically for you.
|
||||
-- * Leverage evasiveness from SEAD, leverage attack range setting.
|
||||
-- * Automatic setup of SHORAD based on groups of the class "short-range".
|
||||
--
|
||||
-- # 0. Base considerations and naming conventions
|
||||
--
|
||||
@@ -133,10 +134,10 @@
|
||||
--
|
||||
-- # 0.1 Set-up in the mission editor
|
||||
--
|
||||
-- Set up your SAM sites in the mission editor. Name the groups using a systematic approach like above.
|
||||
-- Set up your EWR system in the mission editor. Name the groups using a systematic approach like above. Can be e.g. AWACS or a combination of AWACS and Search Radars like e.g. EWR 1L13 etc.
|
||||
-- Set up your SAM sites in the mission editor. Name the groups using a systematic approach like above.Can be e.g. AWACS or a combination of AWACS and Search Radars like e.g. EWR 1L13 etc.
|
||||
-- Search Radars usually have "SR" or "STR" in their names. Use the encyclopedia in the mission editor to inform yourself.
|
||||
-- Set up your SHORAD systems. They need to be **close** to (i.e. around) the SAM sites to be effective. Use **one** group per SAM location. SA-15 TOR systems offer a good missile defense.
|
||||
-- Set up your SHORAD systems. They need to be **close** to (i.e. around) the SAM sites to be effective. Use **one unit ** per group (multiple groups) for the SAM location.
|
||||
-- Else, evasive manoevers might club up all defenders in one place. Red SA-15 TOR systems offer a good missile defense.
|
||||
--
|
||||
-- [optional] Set up your HQ. Can be any group, e.g. a command vehicle.
|
||||
--
|
||||
@@ -188,7 +189,7 @@
|
||||
--
|
||||
-- ## 2.1 Auto mode features
|
||||
--
|
||||
-- ### 2.1.1 You can now add Accept-, Reject- and Conflict-Zones to your setup, e.g. to consider borders or de-militarized zones:
|
||||
-- ### 2.1.1 You can add Accept-, Reject- and Conflict-Zones to your setup, e.g. to consider borders or de-militarized zones:
|
||||
--
|
||||
-- -- Parameters are tables of Core.Zone#ZONE objects!
|
||||
-- -- This is effectively a 3-stage filter allowing for zone overlap. A coordinate is accepted first when
|
||||
@@ -205,9 +206,6 @@
|
||||
-- ### 2.1.3 SHORAD/Point defense will automatically be added from SAM sites of type "point" or if the range is less than 5km or if the type is AAA.
|
||||
--
|
||||
-- ### 2.1.4 Advanced features
|
||||
--
|
||||
-- -- Option to switch off auto mode **before** you start MANTIS (not recommended)
|
||||
-- mybluemantis.automode = false
|
||||
--
|
||||
-- -- Option to set the scale of the activation range, i.e. don't activate at the fringes of max range, defaults below.
|
||||
-- -- also see engagerange below.
|
||||
@@ -220,6 +218,12 @@
|
||||
--
|
||||
-- -- For some scenarios, like Cold War, it might be useful not to activate SAMs if friendly aircraft are around to avoid death by friendly fire.
|
||||
-- mybluemantis.checkforfriendlies = true
|
||||
--
|
||||
-- ### 2.1.6 Shoot & Scoot
|
||||
--
|
||||
-- -- Option to make the (driveable) SHORAD units drive around and shuffle positions
|
||||
-- -- We use a SET_ZONE for that, number of zones to consider defaults to three, Random is true for random coordinates and Formation is e.g. "Vee".
|
||||
-- mybluemantis:AddScootZones(ZoneSet, Number, Random, Formation)
|
||||
--
|
||||
-- # 3. Default settings [both modes unless stated otherwise]
|
||||
--
|
||||
@@ -242,26 +246,8 @@
|
||||
-- E.g. mymantis:SetAdvancedMode( true, 90 )
|
||||
--
|
||||
-- Use this option if you want to make use of or allow advanced SEAD tactics.
|
||||
--
|
||||
-- # 5. Integrate SHORAD [classic mode, not necessary in automode, not recommended for manual setup]
|
||||
--
|
||||
-- You can also choose to integrate Mantis with @{Functional.Shorad#SHORAD} for protection against HARMs and AGMs manually. When SHORAD detects a missile fired at one of MANTIS' SAM sites, it will activate SHORAD systems in
|
||||
-- the given defense checkradius around that SAM site. Create a SHORAD object first, then integrate with MANTIS like so:
|
||||
--
|
||||
-- local SamSet = SET_GROUP:New():FilterPrefixes("Blue SAM"):FilterCoalitions("blue"):FilterStart()
|
||||
-- myshorad = SHORAD:New("BlueShorad", "Blue SHORAD", SamSet, 22000, 600, "blue")
|
||||
-- -- now set up MANTIS
|
||||
-- mymantis = MANTIS:New("BlueMantis","Blue SAM","Blue EWR",nil,"blue",false,"Blue Awacs")
|
||||
-- mymantis:AddShorad(myshorad,720)
|
||||
-- mymantis:Start()
|
||||
--
|
||||
-- If you systematically name your SHORAD groups starting with "Blue SHORAD" you'll need exactly **one** SHORAD instance to manage all SHORAD groups.
|
||||
--
|
||||
-- (Optionally) you can remove the link later on with
|
||||
--
|
||||
-- mymantis:RemoveShorad()
|
||||
--
|
||||
-- # 6. Integrated SEAD
|
||||
-- # 5. Integrated SEAD
|
||||
--
|
||||
-- MANTIS is using @{Functional.Sead#SEAD} internally to both detect and evade HARM attacks. No extra efforts needed to set this up!
|
||||
-- Once a HARM attack is detected, MANTIS (via SEAD) will shut down the radars of the attacked SAM site and take evasive action by moving the SAM
|
||||
@@ -336,6 +322,8 @@ MANTIS = {
|
||||
SmokeDecoy = false,
|
||||
SmokeDecoyColor = SMOKECOLOR.White,
|
||||
checkcounter = 1,
|
||||
DLinkCacheTime = 120,
|
||||
logsamstatus = false,
|
||||
}
|
||||
|
||||
--- Advanced state enumerator
|
||||
@@ -374,7 +362,7 @@ MANTIS.radiusscale[MANTIS.SamType.POINT] = 3
|
||||
MANTIS.SamData = {
|
||||
["Hawk"] = { Range=35, Blindspot=0, Height=12, Type="Medium", Radar="Hawk" }, -- measures in km
|
||||
["NASAMS"] = { Range=14, Blindspot=0, Height=7, Type="Short", Radar="NSAMS" }, -- AIM 120B
|
||||
["Patriot"] = { Range=99, Blindspot=0, Height=25, Type="Long", Radar="Patriot" },
|
||||
["Patriot"] = { Range=99, Blindspot=0, Height=25, Type="Long", Radar="Patriot str" },
|
||||
["Rapier"] = { Range=10, Blindspot=0, Height=3, Type="Short", Radar="rapier" },
|
||||
["SA-2"] = { Range=40, Blindspot=7, Height=25, Type="Medium", Radar="S_75M_Volhov" },
|
||||
["SA-3"] = { Range=18, Blindspot=6, Height=18, Type="Short", Radar="5p73 s-125 ln" },
|
||||
@@ -382,7 +370,8 @@ MANTIS.SamData = {
|
||||
["SA-6"] = { Range=25, Blindspot=0, Height=8, Type="Medium", Radar="1S91" },
|
||||
["SA-10"] = { Range=119, Blindspot=0, Height=18, Type="Long" , Radar="S-300PS 4"},
|
||||
["SA-11"] = { Range=35, Blindspot=0, Height=20, Type="Medium", Radar="SA-11" },
|
||||
["Roland"] = { Range=5, Blindspot=0, Height=5, Type="Point", Radar="Roland" },
|
||||
["Roland"] = { Range=6, Blindspot=0, Height=5, Type="Short", Radar="Roland" },
|
||||
["Gepard"] = { Range=5, Blindspot=0, Height=4, Type="Point", Radar="Gepard" },
|
||||
["HQ-7"] = { Range=12, Blindspot=0, Height=3, Type="Short", Radar="HQ-7" },
|
||||
["SA-9"] = { Range=4, Blindspot=0, Height=3, Type="Point", Radar="Strela", Point="true" },
|
||||
["SA-8"] = { Range=10, Blindspot=0, Height=5, Type="Short", Radar="Osa 9A33" },
|
||||
@@ -393,6 +382,7 @@ MANTIS.SamData = {
|
||||
["Chaparral"] = { Range=8, Blindspot=0, Height=3, Type="Short", Radar="Chaparral" },
|
||||
["Linebacker"] = { Range=4, Blindspot=0, Height=3, Type="Point", Radar="Linebacker", Point="true" },
|
||||
["Silkworm"] = { Range=90, Blindspot=1, Height=0.2, Type="Long", Radar="Silkworm" },
|
||||
["HEMTT_C-RAM_Phalanx"] = { Range=2, Blindspot=0, Height=2, Type="Point", Radar="HEMTT_C-RAM_Phalanx", Point="true" },
|
||||
-- units from HDS Mod, multi launcher options is tricky
|
||||
["SA-10B"] = { Range=75, Blindspot=0, Height=18, Type="Medium" , Radar="SA-10B"},
|
||||
["SA-17"] = { Range=50, Blindspot=3, Height=30, Type="Medium", Radar="SA-17" },
|
||||
@@ -437,16 +427,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 +451,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" },
|
||||
}
|
||||
|
||||
-----------------------------------------------------------------------
|
||||
@@ -623,7 +615,8 @@ do
|
||||
self.advAwacs = false
|
||||
end
|
||||
|
||||
|
||||
self:SetDLinkCacheTime()
|
||||
|
||||
-- Set the string id for output to DCS.log file.
|
||||
self.lid=string.format("MANTIS %s | ", self.name)
|
||||
|
||||
@@ -656,6 +649,8 @@ do
|
||||
table.insert(self.ewr_templates,awacs)
|
||||
end
|
||||
|
||||
self.logsamstatus = false
|
||||
|
||||
self:T({self.ewr_templates})
|
||||
|
||||
self.SAM_Group = SET_GROUP:New():FilterPrefixes(self.SAM_Templates_Prefix):FilterCoalitions(self.Coalition)
|
||||
@@ -687,7 +682,7 @@ do
|
||||
|
||||
-- TODO Version
|
||||
-- @field #string version
|
||||
self.version="0.9.27"
|
||||
self.version="0.9.30"
|
||||
self:I(string.format("***** Starting MANTIS Version %s *****", self.version))
|
||||
|
||||
--- FSM Functions ---
|
||||
@@ -1037,6 +1032,16 @@ do
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- Function to set how long INTEL DLINK remembers contacts.
|
||||
-- @param #MANTIS self
|
||||
-- @param #number seconds Remember this many seconds, at least 5 seconds.
|
||||
-- @return #MANTIS self
|
||||
function MANTIS:SetDLinkCacheTime(seconds)
|
||||
self.DLinkCacheTime = math.abs(seconds or 120)
|
||||
if self.DLinkCacheTime < 5 then self.DLinkCacheTime = 5 end
|
||||
return self
|
||||
end
|
||||
|
||||
--- Function to set the detection interval
|
||||
-- @param #MANTIS self
|
||||
@@ -1429,7 +1434,9 @@ do
|
||||
--IntelTwo:SetClusterRadius(5000)
|
||||
IntelTwo:Start()
|
||||
|
||||
local IntelDlink = INTEL_DLINK:New({IntelOne,IntelTwo},self.name.." DLINK",22,300)
|
||||
local CacheTime = self.DLinkCacheTime or 120
|
||||
local IntelDlink = INTEL_DLINK:New({IntelOne,IntelTwo},self.name.." DLINK",22,CacheTime)
|
||||
|
||||
IntelDlink:__Start(1)
|
||||
|
||||
self:SetUsingDLink(IntelDlink)
|
||||
@@ -1491,7 +1498,7 @@ do
|
||||
elseif chm then
|
||||
SAMData = self.SamDataCH
|
||||
end
|
||||
--self:T("Looking to auto-match for "..grpname)
|
||||
--self:I("Looking to auto-match for "..grpname)
|
||||
for _,_unit in pairs(units) do
|
||||
local unit = _unit -- Wrapper.Unit#UNIT
|
||||
local type = string.lower(unit:GetTypeName())
|
||||
@@ -1692,7 +1699,9 @@ do
|
||||
local grpname = group:GetName()
|
||||
local grpcoord = group:GetCoordinate()
|
||||
local grprange, grpheight,type,blind = self:_GetSAMRange(grpname)
|
||||
local radaralive = group:IsSAM()
|
||||
-- TODO the below might stop working at some point after some hours, needs testing
|
||||
--local radaralive = group:IsSAM()
|
||||
local radaralive = true
|
||||
table.insert( SAM_Tbl, {grpname, grpcoord, grprange, grpheight, blind, type}) -- make the table lighter, as I don't really use the zone here
|
||||
table.insert( SEAD_Grps, grpname )
|
||||
if type == MANTIS.SamType.LONG and radaralive then
|
||||
@@ -1854,7 +1863,7 @@ do
|
||||
end --end alive
|
||||
end --end check
|
||||
end --for loop
|
||||
if self.debug or self.verbose then
|
||||
if self.debug or self.verbose or self.logsamstatus then
|
||||
for _,_status in pairs(self.SamStateTracker) do
|
||||
if _status == "GREEN" then
|
||||
instatusgreen=instatusgreen+1
|
||||
@@ -1875,8 +1884,9 @@ do
|
||||
-- @param #MANTIS self
|
||||
-- @param Functional.Detection#DETECTION_AREAS detection Detection object
|
||||
-- @param #boolean dlink
|
||||
-- @param #boolean reporttolog
|
||||
-- @return #MANTIS self
|
||||
function MANTIS:_Check(detection,dlink)
|
||||
function MANTIS:_Check(detection,dlink,reporttolog)
|
||||
self:T(self.lid .. "Check")
|
||||
--get detected set
|
||||
local detset = detection:GetDetectedItemCoordinates()
|
||||
@@ -1903,7 +1913,8 @@ do
|
||||
local samset = self:_GetSAMTable() -- table of i.1=names, i.2=coordinates, i.3=firing range, i.4=firing height
|
||||
instatusred, instatusgreen, activeshorads = self:_CheckLoop(samset,detset,dlink,self.maxclassic)
|
||||
end
|
||||
if self.debug or self.verbose then
|
||||
|
||||
local function GetReport()
|
||||
local statusreport = REPORT:New("\nMANTIS Status "..self.name)
|
||||
statusreport:Add("+-----------------------------+")
|
||||
statusreport:Add(string.format("+ SAM in RED State: %2d",instatusred))
|
||||
@@ -1912,7 +1923,15 @@ do
|
||||
statusreport:Add(string.format("+ SHORAD active: %2d",activeshorads))
|
||||
end
|
||||
statusreport:Add("+-----------------------------+")
|
||||
return statusreport
|
||||
end
|
||||
|
||||
if self.debug or self.verbose then
|
||||
local statusreport = GetReport()
|
||||
MESSAGE:New(statusreport:Text(),10):ToAll():ToLog()
|
||||
elseif reporttolog == true then
|
||||
local statusreport = GetReport()
|
||||
MESSAGE:New(statusreport:Text(),10):ToLog()
|
||||
end
|
||||
return self
|
||||
end
|
||||
@@ -2020,7 +2039,7 @@ do
|
||||
self:T({From, Event, To})
|
||||
-- check detection
|
||||
if not self.state2flag then
|
||||
self:_Check(self.Detection,self.DLink)
|
||||
self:_Check(self.Detection,self.DLink,self.logsamstatus)
|
||||
end
|
||||
|
||||
local EWRAlive = self:_CheckAnyEWRAlive()
|
||||
|
||||
@@ -53,6 +53,8 @@
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE.
|
||||
-- Therefore, this class is considered to be deprecated and superseded by the [Functional.Fox](https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Functional.Fox.html) class, which provides the same functionality.
|
||||
--
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -2102,7 +2102,12 @@ function RANGE._OnImpact(weapon, self, playerData, attackHdg, attackAlt, attackV
|
||||
result.attackHdg = attackHdg
|
||||
result.attackVel = attackVel
|
||||
result.attackAlt = attackAlt
|
||||
result.date=os and os.date() or "n/a"
|
||||
if os and os.date then
|
||||
result.date=os.date()
|
||||
else
|
||||
self:E(self.lid.."os or os.date() not available")
|
||||
result.date = "n/a"
|
||||
end
|
||||
|
||||
-- Add to table.
|
||||
table.insert( _results, result )
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,593 +0,0 @@
|
||||
--- **Functional** - TIRESIAS - manages AI behaviour.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- The @{#TIRESIAS} class is working in the back to keep your large-scale ground units in check.
|
||||
--
|
||||
-- ## Features:
|
||||
--
|
||||
-- * Designed to keep CPU and Network usage lower on missions with a lot of ground units.
|
||||
-- * Does not affect ships to keep the Navy guys happy.
|
||||
-- * Does not affect OpsGroup type groups.
|
||||
-- * Distinguishes between SAM groups, AAA groups and other ground groups.
|
||||
-- * Exceptions can be defined to keep certain actions going.
|
||||
-- * Works coalition-independent in the back
|
||||
-- * Easy setup.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ## Missions:
|
||||
--
|
||||
-- ### [TIRESIAS](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master)
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author : **applevangelist **
|
||||
--
|
||||
-- @module Functional.Tiresias
|
||||
-- @image Functional.Tiresias.jpg
|
||||
--
|
||||
-- Last Update: Dec 2023
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
--- **TIRESIAS** class, extends Core.Base#BASE
|
||||
-- @type TIRESIAS
|
||||
-- @field #string ClassName
|
||||
-- @field #booelan debug
|
||||
-- @field #string version
|
||||
-- @field #number Interval
|
||||
-- @field Core.Set#SET_GROUP GroundSet
|
||||
-- @field #number Coalition
|
||||
-- @field Core.Set#SET_GROUP VehicleSet
|
||||
-- @field Core.Set#SET_GROUP AAASet
|
||||
-- @field Core.Set#SET_GROUP SAMSet
|
||||
-- @field Core.Set#SET_GROUP ExceptionSet
|
||||
-- @field Core.Set#SET_OPSGROUP OpsGroupSet
|
||||
-- @field #number AAARange
|
||||
-- @field #number HeloSwitchRange
|
||||
-- @field #number PlaneSwitchRange
|
||||
-- @field Core.Set#SET_GROUP FlightSet
|
||||
-- @field #boolean SwitchAAA
|
||||
-- @extends Core.Fsm#FSM
|
||||
|
||||
---
|
||||
-- @type TIRESIAS.Data
|
||||
-- @field #string type
|
||||
-- @field #number range
|
||||
-- @field #boolean invisible
|
||||
-- @field #boolean AIOff
|
||||
-- @field #boolean exception
|
||||
|
||||
|
||||
--- *Tiresias, Greek demi-god and shapeshifter, blinded by the Gods, works as oracle for you.* (Wiki)
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ## TIRESIAS Concept
|
||||
--
|
||||
-- * Designed to keep CPU and Network usage lower on missions with a lot of ground units.
|
||||
-- * Does not affect ships to keep the Navy guys happy.
|
||||
-- * Does not affect OpsGroup type groups.
|
||||
-- * Distinguishes between SAM groups, AAA groups and other ground groups.
|
||||
-- * Exceptions can be defined in SET_GROUP objects to keep certain actions going.
|
||||
-- * Works coalition-independent in the back
|
||||
-- * Easy setup.
|
||||
--
|
||||
-- ## Setup
|
||||
--
|
||||
-- Setup is a one-liner:
|
||||
--
|
||||
-- local blinder = TIRESIAS:New()
|
||||
--
|
||||
-- Optionally you can set up exceptions, e.g. for convoys driving around
|
||||
--
|
||||
-- local exceptionset = SET_GROUP:New():FilterCoalitions("red"):FilterPrefixes("Convoy"):FilterStart()
|
||||
-- local blinder = TIRESIAS:New()
|
||||
-- blinder:AddExceptionSet(exceptionset)
|
||||
--
|
||||
-- Options
|
||||
--
|
||||
-- -- Setup different radius for activation around helo and airplane groups (applies to AI and humans)
|
||||
-- blinder:SetActivationRanges(10,25) -- defaults are 10, and 25
|
||||
--
|
||||
-- -- Setup engagement ranges for AAA (non-advanced SAM units like Flaks etc) and if you want them to be AIOff
|
||||
-- blinder:SetAAARanges(60,true) -- defaults are 60, and true
|
||||
--
|
||||
-- @field #TIRESIAS
|
||||
TIRESIAS = {
|
||||
ClassName = "TIRESIAS",
|
||||
debug = false,
|
||||
version = "0.0.5",
|
||||
Interval = 20,
|
||||
GroundSet = nil,
|
||||
VehicleSet = nil,
|
||||
AAASet = nil,
|
||||
SAMSet = nil,
|
||||
ExceptionSet = nil,
|
||||
AAARange = 60, -- 60%
|
||||
HeloSwitchRange = 10, -- NM
|
||||
PlaneSwitchRange = 25, -- NM
|
||||
SwitchAAA = true,
|
||||
}
|
||||
|
||||
--- [USER] Create a new Tiresias object and start it up.
|
||||
-- @param #TIRESIAS self
|
||||
-- @return #TIRESIAS self
|
||||
function TIRESIAS:New()
|
||||
|
||||
-- Inherit everything from FSM class.
|
||||
local self = BASE:Inherit(self, FSM:New()) -- #TIRESIAS
|
||||
|
||||
--- FSM Functions ---
|
||||
|
||||
-- Start State.
|
||||
self:SetStartState("Stopped")
|
||||
|
||||
-- Add FSM transitions.
|
||||
-- From State --> Event --> To State
|
||||
self:AddTransition("Stopped", "Start", "Running") -- Start FSM.
|
||||
self:AddTransition("*", "Status", "*") -- TIRESIAS status update.
|
||||
self:AddTransition("*", "Stop", "Stopped") -- Stop FSM.
|
||||
|
||||
self.ExceptionSet = SET_GROUP:New():Clear(false)
|
||||
|
||||
self:HandleEvent(EVENTS.PlayerEnterAircraft,self._EventHandler)
|
||||
|
||||
self.lid = string.format("TIRESIAS %s | ",self.version)
|
||||
|
||||
self:I(self.lid.."Managing ground groups!")
|
||||
|
||||
--- Triggers the FSM event "Stop". Stops TIRESIAS and all its event handlers.
|
||||
-- @function [parent=#TIRESIAS] Stop
|
||||
-- @param #TIRESIAS self
|
||||
|
||||
--- Triggers the FSM event "Stop" after a delay. Stops TIRESIAS and all its event handlers.
|
||||
-- @function [parent=#TIRESIAS] __Stop
|
||||
-- @param #TIRESIAS self
|
||||
-- @param #number delay Delay in seconds.
|
||||
|
||||
--- Triggers the FSM event "Start". Starts TIRESIAS and all its event handlers. Note - `:New()` already starts the instance.
|
||||
-- @function [parent=#TIRESIAS] Start
|
||||
-- @param #TIRESIAS self
|
||||
|
||||
--- Triggers the FSM event "Start" after a delay. Starts TIRESIAS and all its event handlers. Note - `:New()` already starts the instance.
|
||||
-- @function [parent=#TIRESIAS] __Start
|
||||
-- @param #TIRESIAS self
|
||||
-- @param #number delay Delay in seconds.
|
||||
|
||||
self:__Start(1)
|
||||
return self
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
--
|
||||
-- Helper Functions
|
||||
--
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
---[USER] Set activation radius for Helos and Planes in Nautical Miles.
|
||||
-- @param #TIRESIAS self
|
||||
-- @param #number HeloMiles Radius around a Helicopter in which AI ground units will be activated. Defaults to 10NM.
|
||||
-- @param #number PlaneMiles Radius around an Airplane in which AI ground units will be activated. Defaults to 25NM.
|
||||
-- @return #TIRESIAS self
|
||||
function TIRESIAS:SetActivationRanges(HeloMiles,PlaneMiles)
|
||||
self.HeloSwitchRange = HeloMiles or 10
|
||||
self.PlaneSwitchRange = PlaneMiles or 25
|
||||
return self
|
||||
end
|
||||
|
||||
---[USER] Set AAA Ranges - AAA equals non-SAM systems which qualify as AAA in DCS world.
|
||||
-- @param #TIRESIAS self
|
||||
-- @param #number FiringRange The engagement range that AAA units will be set to. Can be 0 to 100 (percent). Defaults to 60.
|
||||
-- @param #boolean SwitchAAA Decide if these system will have their AI switched off, too. Defaults to true.
|
||||
-- @return #TIRESIAS self
|
||||
function TIRESIAS:SetAAARanges(FiringRange,SwitchAAA)
|
||||
self.AAARange = FiringRange or 60
|
||||
self.SwitchAAA = (SwitchAAA == false) and false or true
|
||||
return self
|
||||
end
|
||||
|
||||
--- [USER] Add a SET_GROUP of GROUP objects as exceptions. Can be done multiple times. Does **not** work work for GROUP objects spawned into the SET after start, i.e. the groups need to exist in the game already.
|
||||
-- @param #TIRESIAS self
|
||||
-- @param Core.Set#SET_GROUP Set to add to the exception list.
|
||||
-- @return #TIRESIAS self
|
||||
function TIRESIAS:AddExceptionSet(Set)
|
||||
self:T(self.lid.."AddExceptionSet")
|
||||
local exceptions = self.ExceptionSet
|
||||
Set:ForEachGroupAlive(
|
||||
function(grp)
|
||||
if not grp.Tiresias then
|
||||
grp.Tiresias = { -- #TIRESIAS.Data
|
||||
type = "Exception",
|
||||
exception = true,
|
||||
}
|
||||
exceptions:AddGroup(grp,true)
|
||||
end
|
||||
BASE:T("TIRESIAS: Added exception group: "..grp:GetName())
|
||||
end
|
||||
)
|
||||
return self
|
||||
end
|
||||
|
||||
--- [INTERNAL] Filter Function
|
||||
-- @param Wrapper.Group#GROUP Group
|
||||
-- @return #boolean isin
|
||||
function TIRESIAS._FilterNotAAA(Group)
|
||||
local grp = Group -- Wrapper.Group#GROUP
|
||||
local isaaa = grp:IsAAA()
|
||||
if isaaa == true and grp:IsGround() and not grp:IsShip() then
|
||||
return false -- remove from SET
|
||||
else
|
||||
return true -- keep in SET
|
||||
end
|
||||
end
|
||||
|
||||
--- [INTERNAL] Filter Function
|
||||
-- @param Wrapper.Group#GROUP Group
|
||||
-- @return #boolean isin
|
||||
function TIRESIAS._FilterNotSAM(Group)
|
||||
local grp = Group -- Wrapper.Group#GROUP
|
||||
local issam = grp:IsSAM()
|
||||
if issam == true and grp:IsGround() and not grp:IsShip() then
|
||||
return false -- remove from SET
|
||||
else
|
||||
return true -- keep in SET
|
||||
end
|
||||
end
|
||||
|
||||
--- [INTERNAL] Filter Function
|
||||
-- @param Wrapper.Group#GROUP Group
|
||||
-- @return #boolean isin
|
||||
function TIRESIAS._FilterAAA(Group)
|
||||
local grp = Group -- Wrapper.Group#GROUP
|
||||
local isaaa = grp:IsAAA()
|
||||
if isaaa == true and grp:IsGround() and not grp:IsShip() then
|
||||
return true -- remove from SET
|
||||
else
|
||||
return false -- keep in SET
|
||||
end
|
||||
end
|
||||
|
||||
--- [INTERNAL] Filter Function
|
||||
-- @param Wrapper.Group#GROUP Group
|
||||
-- @return #boolean isin
|
||||
function TIRESIAS._FilterSAM(Group)
|
||||
local grp = Group -- Wrapper.Group#GROUP
|
||||
local issam = grp:IsSAM()
|
||||
if issam == true and grp:IsGround() and not grp:IsShip() then
|
||||
return true -- remove from SET
|
||||
else
|
||||
return false -- keep in SET
|
||||
end
|
||||
end
|
||||
|
||||
--- [INTERNAL] Init Groups
|
||||
-- @param #TIRESIAS self
|
||||
-- @return #TIRESIAS self
|
||||
function TIRESIAS:_InitGroups()
|
||||
self:T(self.lid.."_InitGroups")
|
||||
-- Set all groups invisible/motionless
|
||||
local EngageRange = self.AAARange
|
||||
local SwitchAAA = self.SwitchAAA
|
||||
--- AAA
|
||||
self.AAASet:ForEachGroupAlive(
|
||||
function(grp)
|
||||
if not grp.Tiresias then
|
||||
grp:OptionEngageRange(EngageRange)
|
||||
grp:SetCommandInvisible(true)
|
||||
if SwitchAAA then
|
||||
grp:SetAIOff()
|
||||
grp:EnableEmission(false)
|
||||
end
|
||||
grp.Tiresias = { -- #TIRESIAS.Data
|
||||
type = "AAA",
|
||||
invisible = true,
|
||||
range = EngageRange,
|
||||
exception = false,
|
||||
AIOff = SwitchAAA,
|
||||
}
|
||||
end
|
||||
if grp.Tiresias and (not grp.Tiresias.exception == true) then
|
||||
if grp.Tiresias.invisible == false then
|
||||
grp:SetCommandInvisible(true)
|
||||
grp.Tiresias.invisible = true
|
||||
if SwitchAAA then
|
||||
grp:SetAIOff()
|
||||
grp:EnableEmission(false)
|
||||
grp.Tiresias.AIOff = true
|
||||
end
|
||||
end
|
||||
end
|
||||
--BASE:I(string.format("Init/Switch off AAA %s (Exception %s)",grp:GetName(),tostring(grp.Tiresias.exception)))
|
||||
end
|
||||
)
|
||||
--- Vehicles
|
||||
self.VehicleSet:ForEachGroupAlive(
|
||||
function(grp)
|
||||
if not grp.Tiresias then
|
||||
grp:SetAIOff()
|
||||
grp:SetCommandInvisible(true)
|
||||
grp.Tiresias = { -- #TIRESIAS.Data
|
||||
type = "Vehicle",
|
||||
invisible = true,
|
||||
AIOff = true,
|
||||
exception = false,
|
||||
}
|
||||
end
|
||||
if grp.Tiresias and (not grp.Tiresias.exception == true) then
|
||||
if grp.Tiresias and grp.Tiresias.invisible == false then
|
||||
grp:SetCommandInvisible(true)
|
||||
grp:SetAIOff()
|
||||
grp.Tiresias.invisible = true
|
||||
grp.Tiresias.AIOff = true
|
||||
end
|
||||
end
|
||||
--BASE:I(string.format("Init/Switch off Vehicle %s (Exception %s)",grp:GetName(),tostring(grp.Tiresias.exception)))
|
||||
end
|
||||
)
|
||||
--- SAM
|
||||
self.SAMSet:ForEachGroupAlive(
|
||||
function(grp)
|
||||
if not grp.Tiresias then
|
||||
grp:SetCommandInvisible(true)
|
||||
grp.Tiresias = { -- #TIRESIAS.Data
|
||||
type = "SAM",
|
||||
invisible = true,
|
||||
exception = false,
|
||||
}
|
||||
end
|
||||
if grp.Tiresias and (not grp.Tiresias.exception == true) then
|
||||
if grp.Tiresias and grp.Tiresias.invisible == false then
|
||||
grp:SetCommandInvisible(true)
|
||||
grp.Tiresias.invisible = true
|
||||
end
|
||||
end
|
||||
--BASE:I(string.format("Init/Switch off SAM %s (Exception %s)",grp:GetName(),tostring(grp.Tiresias.exception)))
|
||||
end
|
||||
)
|
||||
return self
|
||||
end
|
||||
|
||||
--- [INTERNAL] Event handler function
|
||||
-- @param #TIRESIAS self
|
||||
-- @param Core.Event#EVENTDATA EventData
|
||||
-- @return #TIRESIAS self
|
||||
function TIRESIAS:_EventHandler(EventData)
|
||||
self:T(string.format("%s Event = %d",self.lid, EventData.id))
|
||||
local event = EventData -- Core.Event#EVENTDATA
|
||||
if event.id == EVENTS.PlayerEnterAircraft or event.id == EVENTS.PlayerEnterUnit then
|
||||
--local _coalition = event.IniCoalition
|
||||
--if _coalition ~= self.Coalition then
|
||||
-- return --ignore!
|
||||
--end
|
||||
local unitname = event.IniUnitName or "none"
|
||||
local _unit = event.IniUnit
|
||||
local _group = event.IniGroup
|
||||
if _group and _group:IsAlive() then
|
||||
local radius = self.PlaneSwitchRange
|
||||
if _group:IsHelicopter() then
|
||||
radius = self.HeloSwitchRange
|
||||
end
|
||||
self:_SwitchOnGroups(_group,radius)
|
||||
end
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- [INTERNAL] Switch Groups Behaviour
|
||||
-- @param #TIRESIAS self
|
||||
-- @param Wrapper.Group#GROUP group
|
||||
-- @param #number radius Radius in NM
|
||||
-- @return #TIRESIAS self
|
||||
function TIRESIAS:_SwitchOnGroups(group,radius)
|
||||
self:T(self.lid.."_SwitchOnGroups "..group:GetName().." Radius "..radius.." NM")
|
||||
local zone = ZONE_GROUP:New("Zone-"..group:GetName(),group,UTILS.NMToMeters(radius))
|
||||
local ground = SET_GROUP:New():FilterCategoryGround():FilterZones({zone}):FilterOnce()
|
||||
local count = ground:CountAlive()
|
||||
if self.debug then
|
||||
local text = string.format("There are %d groups around this plane or helo!",count)
|
||||
self:I(text)
|
||||
end
|
||||
local SwitchAAA = self.SwitchAAA
|
||||
if ground:CountAlive() > 0 then
|
||||
ground:ForEachGroupAlive(
|
||||
function(grp)
|
||||
local name = grp:GetName()
|
||||
if grp:GetCoalition() ~= group:GetCoalition()
|
||||
and grp.Tiresias and grp.Tiresias.type and (not grp.Tiresias.exception == true ) then
|
||||
if grp.Tiresias.invisible == true then
|
||||
grp:SetCommandInvisible(false)
|
||||
grp.Tiresias.invisible = false
|
||||
end
|
||||
if grp.Tiresias.type == "Vehicle" and grp.Tiresias.AIOff and grp.Tiresias.AIOff == true then
|
||||
grp:SetAIOn()
|
||||
grp.Tiresias.AIOff = false
|
||||
end
|
||||
if SwitchAAA and grp.Tiresias.type == "AAA" and grp.Tiresias.AIOff and grp.Tiresias.AIOff == true then
|
||||
grp:SetAIOn()
|
||||
grp:EnableEmission(true)
|
||||
grp.Tiresias.AIOff = false
|
||||
end
|
||||
--BASE:I(string.format("TIRESIAS - Switch on %s %s (Exception %s)",tostring(grp.Tiresias.type),grp:GetName(),tostring(grp.Tiresias.exception)))
|
||||
else
|
||||
BASE:T("TIRESIAS - This group "..tostring(name).. " has not been initialized or is an exception!")
|
||||
end
|
||||
end
|
||||
)
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
--
|
||||
-- FSM Functions
|
||||
--
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- [INTERNAL] FSM Function
|
||||
-- @param #TIRESIAS self
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @return #TIRESIAS self
|
||||
function TIRESIAS:onafterStart(From, Event, To)
|
||||
self:T({From, Event, To})
|
||||
|
||||
local VehicleSet = SET_GROUP:New():FilterCategoryGround():FilterFunction(TIRESIAS._FilterNotAAA):FilterFunction(TIRESIAS._FilterNotSAM):FilterStart()
|
||||
local AAASet = SET_GROUP:New():FilterCategoryGround():FilterFunction(TIRESIAS._FilterAAA):FilterStart()
|
||||
local SAMSet = SET_GROUP:New():FilterCategoryGround():FilterFunction(TIRESIAS._FilterSAM):FilterStart()
|
||||
local OpsGroupSet = SET_OPSGROUP:New():FilterActive(true):FilterStart()
|
||||
self.FlightSet = SET_GROUP:New():FilterCategories({"plane","helicopter"}):FilterStart()
|
||||
|
||||
local EngageRange = self.AAARange
|
||||
|
||||
local ExceptionSet = self.ExceptionSet
|
||||
if self.ExceptionSet then
|
||||
function ExceptionSet:OnAfterAdded(From,Event,To,ObjectName,Object)
|
||||
BASE:I("TIRESIAS: EXCEPTION Object Added: "..Object:GetName())
|
||||
if Object and Object:IsAlive() then
|
||||
Object.Tiresias = { -- #TIRESIAS.Data
|
||||
type = "Exception",
|
||||
exception = true,
|
||||
}
|
||||
Object:SetAIOn()
|
||||
Object:SetCommandInvisible(false)
|
||||
Object:EnableEmission(true)
|
||||
end
|
||||
end
|
||||
|
||||
local OGS = OpsGroupSet:GetAliveSet()
|
||||
for _,_OG in pairs(OGS or {}) do
|
||||
local OG = _OG -- Ops.OpsGroup#OPSGROUP
|
||||
local grp = OG:GetGroup()
|
||||
ExceptionSet:AddGroup(grp,true)
|
||||
end
|
||||
|
||||
function OpsGroupSet:OnAfterAdded(From,Event,To,ObjectName,Object)
|
||||
local grp = Object:GetGroup()
|
||||
ExceptionSet:AddGroup(grp,true)
|
||||
end
|
||||
end
|
||||
|
||||
function VehicleSet:OnAfterAdded(From,Event,To,ObjectName,Object)
|
||||
BASE:I("TIRESIAS: VEHCILE Object Added: "..Object:GetName())
|
||||
if Object and Object:IsAlive() then
|
||||
Object:SetAIOff()
|
||||
Object:SetCommandInvisible(true)
|
||||
Object.Tiresias = { -- #TIRESIAS.Data
|
||||
type = "Vehicle",
|
||||
invisible = true,
|
||||
AIOff = true,
|
||||
exception = false,
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
local SwitchAAA = self.SwitchAAA
|
||||
|
||||
function AAASet:OnAfterAdded(From,Event,To,ObjectName,Object)
|
||||
if Object and Object:IsAlive() then
|
||||
BASE:I("TIRESIAS: AAA Object Added: "..Object:GetName())
|
||||
Object:OptionEngageRange(EngageRange)
|
||||
Object:SetCommandInvisible(true)
|
||||
if SwitchAAA then
|
||||
Object:SetAIOff()
|
||||
Object:EnableEmission(false)
|
||||
end
|
||||
Object.Tiresias = { -- #TIRESIAS.Data
|
||||
type = "AAA",
|
||||
invisible = true,
|
||||
range = EngageRange,
|
||||
exception = false,
|
||||
AIOff = SwitchAAA,
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
function SAMSet:OnAfterAdded(From,Event,To,ObjectName,Object)
|
||||
if Object and Object:IsAlive() then
|
||||
BASE:I("TIRESIAS: SAM Object Added: "..Object:GetName())
|
||||
Object:SetCommandInvisible(true)
|
||||
Object.Tiresias = { -- #TIRESIAS.Data
|
||||
type = "SAM",
|
||||
invisible = true,
|
||||
exception = false,
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
self.VehicleSet = VehicleSet
|
||||
self.AAASet = AAASet
|
||||
self.SAMSet = SAMSet
|
||||
self.OpsGroupSet = OpsGroupSet
|
||||
|
||||
self:_InitGroups()
|
||||
|
||||
self:__Status(1)
|
||||
return self
|
||||
end
|
||||
|
||||
--- [INTERNAL] FSM Function
|
||||
-- @param #TIRESIAS self
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @return #TIRESIAS self
|
||||
function TIRESIAS:onbeforeStatus(From, Event, To)
|
||||
self:T({From, Event, To})
|
||||
if self:GetState() == "Stopped" then
|
||||
return false
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- [INTERNAL] FSM Function
|
||||
-- @param #TIRESIAS self
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @return #TIRESIAS self
|
||||
function TIRESIAS:onafterStatus(From, Event, To)
|
||||
self:T({From, Event, To})
|
||||
if self.debug then
|
||||
local count = self.VehicleSet:CountAlive()
|
||||
local AAAcount = self.AAASet:CountAlive()
|
||||
local SAMcount = self.SAMSet:CountAlive()
|
||||
local text = string.format("Overall: %d | Vehicles: %d | AAA: %d | SAM: %d",count+AAAcount+SAMcount,count,AAAcount,SAMcount)
|
||||
self:I(text)
|
||||
end
|
||||
self:_InitGroups()
|
||||
if self.FlightSet:CountAlive() > 0 then
|
||||
local Set = self.FlightSet:GetAliveSet()
|
||||
for _,_plane in pairs(Set) do
|
||||
local plane = _plane -- Wrapper.Group#GROUP
|
||||
local radius = self.PlaneSwitchRange
|
||||
if plane:IsHelicopter() then
|
||||
radius = self.HeloSwitchRange
|
||||
end
|
||||
self:_SwitchOnGroups(_plane,radius)
|
||||
end
|
||||
end
|
||||
if self:GetState() ~= "Stopped" then
|
||||
self:__Status(self.Interval)
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--- [INTERNAL] FSM Function
|
||||
-- @param #TIRESIAS self
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @return #TIRESIAS self
|
||||
function TIRESIAS:onafterStop(From, Event, To)
|
||||
self:T({From, Event, To})
|
||||
self:UnHandleEvent(EVENTS.PlayerEnterAircraft)
|
||||
return self
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
--
|
||||
-- End
|
||||
--
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
@@ -48,7 +48,7 @@
|
||||
|
||||
do -- ZONE_CAPTURE_COALITION
|
||||
|
||||
-- @type ZONE_CAPTURE_COALITION
|
||||
--- @type ZONE_CAPTURE_COALITION
|
||||
-- @field #string ClassName Name of the class.
|
||||
-- @field #number MarkBlue ID of blue F10 mark.
|
||||
-- @field #number MarkRed ID of red F10 mark.
|
||||
@@ -161,7 +161,7 @@ do -- ZONE_CAPTURE_COALITION
|
||||
-- The mission designer can use these values to alter the logic.
|
||||
-- For example:
|
||||
--
|
||||
-- -- @param Functional.ZoneCaptureCoalition#ZONE_CAPTURE_COALITION self
|
||||
-- --- @param Functional.ZoneCaptureCoalition#ZONE_CAPTURE_COALITION self
|
||||
-- function ZoneCaptureCoalition:OnEnterGuarded( From, Event, To )
|
||||
-- if From ~= "Empty" then
|
||||
-- -- Display a message
|
||||
@@ -172,7 +172,7 @@ do -- ZONE_CAPTURE_COALITION
|
||||
--
|
||||
-- ## Example Event Handler.
|
||||
--
|
||||
-- -- @param Functional.ZoneCaptureCoalition#ZONE_CAPTURE_COALITION self
|
||||
-- --- @param Functional.ZoneCaptureCoalition#ZONE_CAPTURE_COALITION self
|
||||
-- function ZoneCaptureCoalition:OnEnterGuarded( From, Event, To )
|
||||
-- if From ~= To then
|
||||
-- local Coalition = self:GetCoalition()
|
||||
@@ -273,7 +273,7 @@ do -- ZONE_CAPTURE_COALITION
|
||||
-- Depending on the zone ownership, different messages are sent.
|
||||
-- Note the methods `ZoneCaptureCoalition:GetZoneName()`.
|
||||
--
|
||||
-- -- @param Functional.ZoneCaptureCoalition#ZONE_CAPTURE_COALITION self
|
||||
-- --- @param Functional.ZoneCaptureCoalition#ZONE_CAPTURE_COALITION self
|
||||
-- function ZoneCaptureCoalition:OnEnterGuarded( From, Event, To )
|
||||
-- if From ~= To then
|
||||
-- local Coalition = self:GetCoalition()
|
||||
@@ -294,7 +294,7 @@ do -- ZONE_CAPTURE_COALITION
|
||||
-- Next is the Event Handler when the **Empty** state transition is triggered.
|
||||
-- Now we smoke the ZoneCaptureCoalition with a green color, using `self:Smoke( SMOKECOLOR.Green )`.
|
||||
--
|
||||
-- -- @param Functional.Protect#ZONE_CAPTURE_COALITION self
|
||||
-- --- @param Functional.Protect#ZONE_CAPTURE_COALITION self
|
||||
-- function ZoneCaptureCoalition:OnEnterEmpty()
|
||||
-- self:Smoke( SMOKECOLOR.Green )
|
||||
-- US_CC:MessageTypeToCoalition( string.format( "%s is unprotected, and can be captured!", ZoneCaptureCoalition:GetZoneName() ), MESSAGE.Type.Information )
|
||||
@@ -304,7 +304,7 @@ do -- ZONE_CAPTURE_COALITION
|
||||
-- The next Event Handlers speak for itself.
|
||||
-- When the zone is Attacked, we smoke the zone white and send some messages to each coalition.
|
||||
--
|
||||
-- -- @param Functional.Protect#ZONE_CAPTURE_COALITION self
|
||||
-- --- @param Functional.Protect#ZONE_CAPTURE_COALITION self
|
||||
-- function ZoneCaptureCoalition:OnEnterAttacked()
|
||||
-- ZoneCaptureCoalition:Smoke( SMOKECOLOR.White )
|
||||
-- local Coalition = self:GetCoalition()
|
||||
@@ -321,7 +321,7 @@ do -- ZONE_CAPTURE_COALITION
|
||||
-- When the zone is Captured, we send some victory or loss messages to the correct coalition.
|
||||
-- And we add some score.
|
||||
--
|
||||
-- -- @param Functional.Protect#ZONE_CAPTURE_COALITION self
|
||||
-- --- @param Functional.Protect#ZONE_CAPTURE_COALITION self
|
||||
-- function ZoneCaptureCoalition:OnEnterCaptured()
|
||||
-- local Coalition = self:GetCoalition()
|
||||
-- self:E({Coalition = Coalition})
|
||||
@@ -641,7 +641,7 @@ do -- ZONE_CAPTURE_COALITION
|
||||
--
|
||||
-- @usage
|
||||
-- -- For example, one could stop the monitoring when the zone was captured!
|
||||
-- -- @param Functional.Protect#ZONE_CAPTURE_COALITION self
|
||||
-- --- @param Functional.Protect#ZONE_CAPTURE_COALITION self
|
||||
-- function ZoneCaptureCoalition:OnEnterCaptured()
|
||||
-- local Coalition = self:GetCoalition()
|
||||
-- self:E({Coalition = Coalition})
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
do -- Zone
|
||||
|
||||
-- @type ZONE_GOAL
|
||||
--- @type ZONE_GOAL
|
||||
-- @field #string ClassName Name of the class.
|
||||
-- @field Core.Goal#GOAL Goal The goal object.
|
||||
-- @field #number SmokeTime Time stamp in seconds when the last smoke of the zone was triggered.
|
||||
@@ -178,7 +178,7 @@ do -- Zone
|
||||
|
||||
end
|
||||
|
||||
-- @param #ZONE_GOAL self
|
||||
--- @param #ZONE_GOAL self
|
||||
-- @param Core.Event#EVENTDATA EventData Event data table.
|
||||
function ZONE_GOAL:__Destroyed( EventData )
|
||||
self:F( { "EventDead", EventData } )
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
--
|
||||
-- # Developer Note
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||
-- Therefore, this class is considered to be deprecated
|
||||
--
|
||||
@@ -21,7 +23,7 @@
|
||||
|
||||
do -- ZoneGoal
|
||||
|
||||
-- @type ZONE_GOAL_CARGO
|
||||
--- @type ZONE_GOAL_CARGO
|
||||
-- @extends Functional.ZoneGoal#ZONE_GOAL
|
||||
|
||||
|
||||
@@ -55,7 +57,7 @@ do -- ZoneGoal
|
||||
ClassName = "ZONE_GOAL_CARGO",
|
||||
}
|
||||
|
||||
-- @field #table ZONE_GOAL_CARGO.States
|
||||
--- @field #table ZONE_GOAL_CARGO.States
|
||||
ZONE_GOAL_CARGO.States = {}
|
||||
|
||||
--- ZONE_GOAL_CARGO Constructor.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
--- **Functional (WIP)** - Base class modeling processes to achieve goals involving coalition zones.
|
||||
--- **Functional** - Base class that models processes to achieve goals involving a Zone for a Coalition.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
do -- ZoneGoal
|
||||
|
||||
-- @type ZONE_GOAL_COALITION
|
||||
--- @type ZONE_GOAL_COALITION
|
||||
-- @field #string ClassName Name of the Class.
|
||||
-- @field #number Coalition The current coalition ID of the zone owner.
|
||||
-- @field #number PreviousCoalition The previous owner of the zone.
|
||||
@@ -48,7 +48,7 @@ do -- ZoneGoal
|
||||
ObjectCategories = nil,
|
||||
}
|
||||
|
||||
-- @field #table ZONE_GOAL_COALITION.States
|
||||
--- @field #table ZONE_GOAL_COALITION.States
|
||||
ZONE_GOAL_COALITION.States = {}
|
||||
|
||||
--- ZONE_GOAL_COALITION Constructor.
|
||||
|
||||
@@ -31,7 +31,6 @@ __Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Core/Spot.lua' )
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Core/MarkerOps_Base.lua' )
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Core/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/Wrapper/Object.lua' )
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Wrapper/Identifiable.lua' )
|
||||
@@ -77,13 +76,7 @@ __Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/Warehouse.lua' )
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/Fox.lua' )
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/Mantis.lua' )
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/Shorad.lua' )
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/AICSAR.lua' )
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/AmmoTruck.lua' )
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/Autolase.lua' )
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/ZoneGoalCargo.lua' )
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/Tiresias.lua' )
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/Stratego.lua' )
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/ClientWatch.lua')
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/ClientWatch.lua' )
|
||||
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/Airboss.lua' )
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/RecoveryTanker.lua' )
|
||||
@@ -91,31 +84,6 @@ __Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/RescueHelo.lua' )
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/ATIS.lua' )
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/CTLD.lua' )
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/CSAR.lua' )
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/AirWing.lua' )
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/ArmyGroup.lua' )
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/Auftrag.lua' )
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/Awacs.lua' )
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/Brigade.lua' )
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/Chief.lua' )
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/Cohort.lua' )
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/Commander.lua' )
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/Fleet.lua' )
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/FlightControl.lua' )
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/FlightGroup.lua' )
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/Flotilla.lua' )
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/Intelligence.lua' )
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/Legion.lua' )
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/NavyGroup.lua' )
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/Operation.lua' )
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/OpsGroup.lua' )
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/OpsTransport.lua' )
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/OpsZone.lua' )
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/Platoon.lua' )
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/PlayerTask.lua' )
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/PlayerRecce.lua' )
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/Squadron.lua' )
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/Target.lua' )
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/EasyGCICAP.lua' )
|
||||
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/AI/AI_Balancer.lua' )
|
||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/AI/AI_Air.lua' )
|
||||
|
||||
@@ -1,181 +0,0 @@
|
||||
__Moose.Include( 'Utilities\\Enums.lua' )
|
||||
__Moose.Include( 'Utilities\\Utils.lua' )
|
||||
__Moose.Include( 'Utilities\\Profiler.lua' )
|
||||
--__Moose.Include( 'Utilities\\STTS.lua' )
|
||||
__Moose.Include( 'Utilities\\FiFo.lua' )
|
||||
__Moose.Include( 'Utilities\\Socket.lua' )
|
||||
|
||||
__Moose.Include( 'Core\\Base.lua' )
|
||||
__Moose.Include( 'Core\\Beacon.lua' )
|
||||
__Moose.Include( 'Core\\UserFlag.lua' )
|
||||
__Moose.Include( 'Core\\Report.lua' )
|
||||
__Moose.Include( 'Core\\Scheduler.lua' )
|
||||
__Moose.Include( 'Core\\ScheduleDispatcher.lua' )
|
||||
__Moose.Include( 'Core\\Event.lua' )
|
||||
__Moose.Include( 'Core\\Settings.lua' )
|
||||
__Moose.Include( 'Core\\Menu.lua' )
|
||||
__Moose.Include( 'Core\\Zone.lua' )
|
||||
__Moose.Include( 'Core\\Velocity.lua' )
|
||||
__Moose.Include( 'Core\\Database.lua' )
|
||||
__Moose.Include( 'Core\\Set.lua' )
|
||||
__Moose.Include( 'Core\\Point.lua' )
|
||||
__Moose.Include( 'Core\\Pathline.lua' )
|
||||
__Moose.Include( 'Core\\Message.lua' )
|
||||
__Moose.Include( 'Core\\Fsm.lua' )
|
||||
__Moose.Include( 'Core\\Spawn.lua' )
|
||||
__Moose.Include( 'Core\\SpawnStatic.lua' )
|
||||
__Moose.Include( 'Core\\Timer.lua' )
|
||||
__Moose.Include( 'Core\\Goal.lua' )
|
||||
__Moose.Include( 'Core\\Spot.lua' )
|
||||
__Moose.Include( 'Core\\Astar.lua' )
|
||||
__Moose.Include( 'Core\\MarkerOps_Base.lua' )
|
||||
__Moose.Include( 'Core\\TextAndSound.lua' )
|
||||
__Moose.Include( 'Core\\Condition.lua' )
|
||||
__Moose.Include( 'Core\\ClientMenu.lua' )
|
||||
|
||||
__Moose.Include( 'Wrapper\\Object.lua' )
|
||||
__Moose.Include( 'Wrapper\\Identifiable.lua' )
|
||||
__Moose.Include( 'Wrapper\\Positionable.lua' )
|
||||
__Moose.Include( 'Wrapper\\Controllable.lua' )
|
||||
__Moose.Include( 'Wrapper\\Group.lua' )
|
||||
__Moose.Include( 'Wrapper\\Unit.lua' )
|
||||
__Moose.Include( 'Wrapper\\Client.lua' )
|
||||
__Moose.Include( 'Wrapper\\Static.lua' )
|
||||
__Moose.Include( 'Wrapper\\Airbase.lua' )
|
||||
__Moose.Include( 'Wrapper\\Scenery.lua' )
|
||||
__Moose.Include( 'Wrapper\\Marker.lua' )
|
||||
__Moose.Include( 'Wrapper\\Net.lua' )
|
||||
__Moose.Include( 'Wrapper\\Weapon.lua' )
|
||||
__Moose.Include( 'Wrapper\\Storage.lua' )
|
||||
__Moose.Include( 'Wrapper\\DynamicCargo.lua' )
|
||||
|
||||
__Moose.Include( 'Cargo\\Cargo.lua' )
|
||||
__Moose.Include( 'Cargo\\CargoUnit.lua' )
|
||||
__Moose.Include( 'Cargo\\CargoSlingload.lua' )
|
||||
__Moose.Include( 'Cargo\\CargoCrate.lua' )
|
||||
__Moose.Include( 'Cargo\\CargoGroup.lua' )
|
||||
|
||||
__Moose.Include( 'Functional\\Scoring.lua' )
|
||||
__Moose.Include( 'Functional\\CleanUp.lua' )
|
||||
__Moose.Include( 'Functional\\Movement.lua' )
|
||||
__Moose.Include( 'Functional\\Sead.lua' )
|
||||
__Moose.Include( 'Functional\\Escort.lua' )
|
||||
__Moose.Include( 'Functional\\MissileTrainer.lua' )
|
||||
__Moose.Include( 'Functional\\ATC_Ground.lua' )
|
||||
__Moose.Include( 'Functional\\Detection.lua' )
|
||||
__Moose.Include( 'Functional\\DetectionZones.lua' )
|
||||
__Moose.Include( 'Functional\\Designate.lua' )
|
||||
__Moose.Include( 'Functional\\RAT.lua' )
|
||||
__Moose.Include( 'Functional\\Range.lua' )
|
||||
__Moose.Include( 'Functional\\ZoneGoal.lua' )
|
||||
__Moose.Include( 'Functional\\ZoneGoalCoalition.lua' )
|
||||
__Moose.Include( 'Functional\\ZoneCaptureCoalition.lua' )
|
||||
__Moose.Include( 'Functional\\Artillery.lua' )
|
||||
__Moose.Include( 'Functional\\Suppression.lua' )
|
||||
__Moose.Include( 'Functional\\PseudoATC.lua' )
|
||||
__Moose.Include( 'Functional\\Warehouse.lua' )
|
||||
__Moose.Include( 'Functional\\Fox.lua' )
|
||||
__Moose.Include( 'Functional\\Mantis.lua' )
|
||||
__Moose.Include( 'Functional\\Shorad.lua' )
|
||||
__Moose.Include( 'Functional\\Autolase.lua' )
|
||||
__Moose.Include( 'Functional\\AICSAR.lua' )
|
||||
__Moose.Include( 'Functional\\AmmoTruck.lua' )
|
||||
__Moose.Include( 'Functional\\Tiresias.lua' )
|
||||
__Moose.Include( 'Functional\\Stratego.lua' )
|
||||
__Moose.Include( 'Functional\\ClientWatch.lua' )
|
||||
|
||||
__Moose.Include( 'Ops\\Airboss.lua' )
|
||||
__Moose.Include( 'Ops\\RecoveryTanker.lua' )
|
||||
__Moose.Include( 'Ops\\RescueHelo.lua' )
|
||||
__Moose.Include( 'Ops\\ATIS.lua' )
|
||||
__Moose.Include( 'Ops\\Auftrag.lua' )
|
||||
__Moose.Include( 'Ops\\Target.lua' )
|
||||
__Moose.Include( 'Ops\\OpsGroup.lua' )
|
||||
__Moose.Include( 'Ops\\FlightGroup.lua' )
|
||||
__Moose.Include( 'Ops\\NavyGroup.lua' )
|
||||
__Moose.Include( 'Ops\\ArmyGroup.lua' )
|
||||
__Moose.Include( 'Ops\\Cohort.lua' )
|
||||
__Moose.Include( 'Ops\\Squadron.lua' )
|
||||
__Moose.Include( 'Ops\\Platoon.lua' )
|
||||
__Moose.Include( 'Ops\\Legion.lua' )
|
||||
__Moose.Include( 'Ops\\AirWing.lua' )
|
||||
__Moose.Include( 'Ops\\Brigade.lua' )
|
||||
__Moose.Include( 'Ops\\Intelligence.lua' )
|
||||
__Moose.Include( 'Ops\\Commander.lua' )
|
||||
__Moose.Include( 'Ops\\OpsTransport.lua' )
|
||||
__Moose.Include( 'Ops\\CSAR.lua' )
|
||||
__Moose.Include( 'Ops\\CTLD.lua' )
|
||||
__Moose.Include( 'Ops\\OpsZone.lua' )
|
||||
__Moose.Include( 'Ops\\Chief.lua' )
|
||||
__Moose.Include( 'Ops\\Flotilla.lua' )
|
||||
__Moose.Include( 'Ops\\Fleet.lua' )
|
||||
__Moose.Include( 'Ops\\Awacs.lua' )
|
||||
__Moose.Include( 'Ops\\PlayerTask.lua' )
|
||||
__Moose.Include( 'Ops\\Operation.lua' )
|
||||
__Moose.Include( 'Ops\\FlightControl.lua' )
|
||||
__Moose.Include( 'Ops\\PlayerRecce.lua' )
|
||||
__Moose.Include( 'Ops\\EasyGCICAP.lua' )
|
||||
__Moose.Include( 'Ops\\EasyA2G.lua' )
|
||||
|
||||
__Moose.Include( 'AI\\AI_Balancer.lua' )
|
||||
__Moose.Include( 'AI\\AI_Air.lua' )
|
||||
__Moose.Include( 'AI\\AI_Air_Patrol.lua' )
|
||||
__Moose.Include( 'AI\\AI_Air_Engage.lua' )
|
||||
__Moose.Include( 'AI\\AI_A2A_Patrol.lua' )
|
||||
__Moose.Include( 'AI\\AI_A2A_Cap.lua' )
|
||||
__Moose.Include( 'AI\\AI_A2A_Gci.lua' )
|
||||
__Moose.Include( 'AI\\AI_A2A_Dispatcher.lua' )
|
||||
__Moose.Include( 'AI\\AI_A2G_BAI.lua' )
|
||||
__Moose.Include( 'AI\\AI_A2G_CAS.lua' )
|
||||
__Moose.Include( 'AI\\AI_A2G_SEAD.lua' )
|
||||
__Moose.Include( 'AI\\AI_A2G_Dispatcher.lua' )
|
||||
__Moose.Include( 'AI\\AI_Patrol.lua' )
|
||||
__Moose.Include( 'AI\\AI_Cap.lua' )
|
||||
__Moose.Include( 'AI\\AI_Cas.lua' )
|
||||
__Moose.Include( 'AI\\AI_Bai.lua' )
|
||||
__Moose.Include( 'AI\\AI_Formation.lua' )
|
||||
__Moose.Include( 'AI\\AI_Escort.lua' )
|
||||
__Moose.Include( 'AI\\AI_Escort_Request.lua' )
|
||||
__Moose.Include( 'AI\\AI_Escort_Dispatcher.lua' )
|
||||
__Moose.Include( 'AI\\AI_Escort_Dispatcher_Request.lua' )
|
||||
__Moose.Include( 'AI\\AI_Cargo.lua' )
|
||||
__Moose.Include( 'AI\\AI_Cargo_APC.lua' )
|
||||
__Moose.Include( 'AI\\AI_Cargo_Helicopter.lua' )
|
||||
__Moose.Include( 'AI\\AI_Cargo_Airplane.lua' )
|
||||
__Moose.Include( 'AI\\AI_Cargo_Ship.lua' )
|
||||
__Moose.Include( 'AI\\AI_Cargo_Dispatcher.lua' )
|
||||
__Moose.Include( 'AI\\AI_Cargo_Dispatcher_APC.lua' )
|
||||
__Moose.Include( 'AI\\AI_Cargo_Dispatcher_Helicopter.lua' )
|
||||
__Moose.Include( 'AI\\AI_Cargo_Dispatcher_Airplane.lua' )
|
||||
__Moose.Include( 'AI\\AI_Cargo_Dispatcher_Ship.lua' )
|
||||
|
||||
__Moose.Include( 'Actions\\Act_Assign.lua' )
|
||||
__Moose.Include( 'Actions\\Act_Route.lua' )
|
||||
__Moose.Include( 'Actions\\Act_Account.lua' )
|
||||
__Moose.Include( 'Actions\\Act_Assist.lua' )
|
||||
|
||||
__Moose.Include( 'Sound\\UserSound.lua' )
|
||||
__Moose.Include( 'Sound\\SoundOutput.lua' )
|
||||
__Moose.Include( 'Sound\\Radio.lua' )
|
||||
__Moose.Include( 'Sound\\RadioQueue.lua' )
|
||||
__Moose.Include( 'Sound\\RadioSpeech.lua' )
|
||||
__Moose.Include( 'Sound\\SRS.lua' )
|
||||
|
||||
__Moose.Include( 'Tasking\\CommandCenter.lua' )
|
||||
__Moose.Include( 'Tasking\\Mission.lua' )
|
||||
__Moose.Include( 'Tasking\\Task.lua' )
|
||||
__Moose.Include( 'Tasking\\TaskInfo.lua' )
|
||||
__Moose.Include( 'Tasking\\Task_Manager.lua' )
|
||||
__Moose.Include( 'Tasking\\DetectionManager.lua' )
|
||||
__Moose.Include( 'Tasking\\Task_A2G_Dispatcher.lua' )
|
||||
__Moose.Include( 'Tasking\\Task_A2G.lua' )
|
||||
__Moose.Include( 'Tasking\\Task_A2A_Dispatcher.lua' )
|
||||
__Moose.Include( 'Tasking\\Task_A2A.lua' )
|
||||
__Moose.Include( 'Tasking\\Task_Cargo.lua' )
|
||||
__Moose.Include( 'Tasking\\Task_Cargo_Transport.lua' )
|
||||
__Moose.Include( 'Tasking\\Task_Cargo_CSAR.lua' )
|
||||
__Moose.Include( 'Tasking\\Task_Cargo_Dispatcher.lua' )
|
||||
__Moose.Include( 'Tasking\\Task_Capture_Zone.lua' )
|
||||
__Moose.Include( 'Tasking\\Task_Capture_Dispatcher.lua' )
|
||||
|
||||
__Moose.Include( 'Globals.lua' )
|
||||
@@ -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.
|
||||
@@ -2794,7 +2798,7 @@ function ATIS:onafterBroadcast( From, Event, To )
|
||||
|
||||
end
|
||||
_RUNACT = subtitle
|
||||
alltext = alltext .. ";\n" .. subtitle
|
||||
--alltext = alltext .. ";\n" .. subtitle
|
||||
|
||||
-- Runway length.
|
||||
if self.rwylength then
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -32,6 +32,7 @@
|
||||
-- * [USS George Washington](https://en.wikipedia.org/wiki/USS_George_Washington_\(CVN-73\)) (CVN-73) [Super Carrier Module]
|
||||
-- * [USS Harry S. Truman](https://en.wikipedia.org/wiki/USS_Harry_S._Truman) (CVN-75) [Super Carrier Module]
|
||||
-- * [USS Forrestal](https://en.wikipedia.org/wiki/USS_Forrestal_\(CV-59\)) (CV-59) [Heatblur Carrier Module]
|
||||
-- * [Essex Class](https://en.wikipedia.org/wiki/Essex-class_aircraft_carrier) (CV-11) [Magnitude 3 Carrier Module]
|
||||
-- * [HMS Hermes](https://en.wikipedia.org/wiki/HMS_Hermes_\(R12\)) (R12)
|
||||
-- * [HMS Invincible](https://en.wikipedia.org/wiki/HMS_Invincible_\(R05\)) (R05)
|
||||
-- * [USS Tarawa](https://en.wikipedia.org/wiki/USS_Tarawa_\(LHA-1\)) (LHA-1)
|
||||
@@ -47,6 +48,7 @@
|
||||
-- * [AV-8B N/A Harrier](https://forums.eagle.ru/forumdisplay.php?f=555) (Player & AI)
|
||||
-- * [T-45C Goshawk](https://forum.dcs.world/topic/203816-vnao-t-45-goshawk/) (VNAO mod) (Player & AI)
|
||||
-- * [FE/A-18E/F/G Superhornet](https://forum.dcs.world/topic/316971-cjs-super-hornet-community-mod-v20-official-thread/) (CJS mod) (Player & AI)
|
||||
-- * [F4U-1D Corsair](https://forum.dcs.world/forum/781-f4u-1d/) (Player & AI)
|
||||
-- * F/A-18C Hornet (AI)
|
||||
-- * F-14A Tomcat (AI)
|
||||
-- * E-2D Hawkeye (AI)
|
||||
@@ -1283,6 +1285,8 @@ AIRBOSS = {
|
||||
-- @field #string RHINOE F/A-18E Superhornet (mod).
|
||||
-- @field #string RHINOF F/A-18F Superhornet (mod).
|
||||
-- @field #string GROWLER FEA-18G Superhornet (mod).
|
||||
-- @field #string CORSAIR F4U-1D Corsair.
|
||||
-- @field #string CORSAIR_CW F4U-1D Corsair Mk.4 (clipped wing).
|
||||
AIRBOSS.AircraftCarrier={
|
||||
AV8B="AV8BNA",
|
||||
HORNET="FA-18C_hornet",
|
||||
@@ -1299,6 +1303,8 @@ AIRBOSS.AircraftCarrier={
|
||||
RHINOE="FA-18E",
|
||||
RHINOF="FA-18F",
|
||||
GROWLER="EA-18G",
|
||||
CORSAIR="F4U-1D",
|
||||
CORSAIR_CW="F4U-1D CW",
|
||||
}
|
||||
|
||||
--- Carrier types.
|
||||
@@ -1310,6 +1316,7 @@ AIRBOSS.AircraftCarrier={
|
||||
-- @field #string TRUMAN USS Harry S. Truman (CVN-75) [Super Carrier Module]
|
||||
-- @field #string FORRESTAL USS Forrestal (CV-59) [Heatblur Carrier Module]
|
||||
-- @field #string VINSON USS Carl Vinson (CVN-70) [Deprecated!]
|
||||
-- @field #string ESSEX Essex class carrier (e.g. USS Yorktown (CV-10)) [Magnitude 3 Carrier Module]
|
||||
-- @field #string HERMES HMS Hermes (R12) [V/STOL Carrier]
|
||||
-- @field #string INVINCIBLE HMS Invincible (R05) [V/STOL Carrier]
|
||||
-- @field #string TARAWA USS Tarawa (LHA-1) [V/STOL Carrier]
|
||||
@@ -1325,6 +1332,7 @@ AIRBOSS.CarrierType = {
|
||||
STENNIS = "Stennis",
|
||||
FORRESTAL = "Forrestal",
|
||||
VINSON = "VINSON",
|
||||
ESSEX = "Essex",
|
||||
HERMES = "HERMES81",
|
||||
INVINCIBLE = "hms_invincible",
|
||||
TARAWA = "LHA_Tarawa",
|
||||
@@ -1731,10 +1739,10 @@ AIRBOSS.Difficulty = {
|
||||
-- @field #table trapsheet Groove data table recorded every 0.5 seconds.
|
||||
-- @field #boolean trapon If true, save trap sheets.
|
||||
-- @field #string debriefschedulerID Debrief scheduler ID.
|
||||
--
|
||||
--
|
||||
-- @field Sound.SRS#MSRS SRS
|
||||
-- @field Sound.SRS#MSRSQUEUE SRSQ
|
||||
--
|
||||
--
|
||||
-- @extends #AIRBOSS.FlightGroup
|
||||
|
||||
--- Main group level radio menu: F10 Other/Airboss.
|
||||
@@ -1747,7 +1755,7 @@ AIRBOSS.MenuF10Root = nil
|
||||
|
||||
--- Airboss class version.
|
||||
-- @field #string version
|
||||
AIRBOSS.version = "1.3.3"
|
||||
AIRBOSS.version = "1.4.0"
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- TODO list
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -1912,6 +1920,9 @@ function AIRBOSS:New( carriername, alias )
|
||||
-- Set max section members. Default 2.
|
||||
self:SetMaxSectionSize()
|
||||
|
||||
-- Set max section distance. Default 100 meters.
|
||||
self:SetMaxSectionDistance()
|
||||
|
||||
-- Set max flights per stack. Default is 2.
|
||||
self:SetMaxFlightsPerStack()
|
||||
|
||||
@@ -2010,6 +2021,8 @@ function AIRBOSS:New( carriername, alias )
|
||||
elseif self.carriertype == AIRBOSS.CarrierType.VINSON then
|
||||
-- Carl Vinson is legacy now.
|
||||
self:_InitStennis()
|
||||
elseif self.carriertype == AIRBOSS.CarrierType.ESSEX then
|
||||
self:_InitEssex()
|
||||
elseif self.carriertype == AIRBOSS.CarrierType.HERMES then
|
||||
-- Hermes parameters.
|
||||
self:_InitHermes()
|
||||
@@ -2539,7 +2552,7 @@ function AIRBOSS:AddRecoveryWindow( starttime, stoptime, case, holdingoffset, tu
|
||||
return self
|
||||
end
|
||||
if Tstop <= Tnow then
|
||||
string.format( "WARNING: Recovery stop time %s already over. Tnow=%s! Recovery window rejected.", UTILS.SecondsToClock( Tstop ), UTILS.SecondsToClock( Tnow ) )
|
||||
string.format( "WARNING: Recovery stop time %s already over. Tnow=%s! Recovery window rejected.", UTILS.SecondsToClock( Tstop ), UTILS.SecondsToClock( Tnow ) )
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -2863,23 +2876,28 @@ end
|
||||
function AIRBOSS:SetGlideslopeErrorThresholds(_max,_min, High, HIGH, Low, LOW)
|
||||
|
||||
--Check if V/STOL Carrier
|
||||
if self.carriertype == AIRBOSS.CarrierType.INVINCIBLE or self.carriertype == AIRBOSS.CarrierType.HERMES or self.carriertype == AIRBOSS.CarrierType.TARAWA or self.carriertype == AIRBOSS.CarrierType.AMERICA or self.carriertype == AIRBOSS.CarrierType.JCARLOS or self.carriertype == AIRBOSS.CarrierType.CANBERRA then
|
||||
if self.carriertype == AIRBOSS.CarrierType.INVINCIBLE or
|
||||
self.carriertype == AIRBOSS.CarrierType.HERMES or
|
||||
self.carriertype == AIRBOSS.CarrierType.TARAWA or
|
||||
self.carriertype == AIRBOSS.CarrierType.AMERICA or
|
||||
self.carriertype == AIRBOSS.CarrierType.JCARLOS or
|
||||
self.carriertype == AIRBOSS.CarrierType.CANBERRA then
|
||||
|
||||
-- allow a larger GSE for V/STOL operations --Pene Testing
|
||||
self.gle._max=_max or 0.7
|
||||
self.gle.High=High or 1.4
|
||||
self.gle.HIGH=HIGH or 1.9
|
||||
self.gle._min=_min or -0.5
|
||||
self.gle.Low=Low or -1.2
|
||||
self.gle.LOW=LOW or -1.5
|
||||
-- CVN values
|
||||
-- allow a larger GSE for V/STOL operations --Pene Testing
|
||||
self.gle._max=_max or 0.7
|
||||
self.gle.High=High or 1.4
|
||||
self.gle.HIGH=HIGH or 1.9
|
||||
self.gle._min=_min or -0.5
|
||||
self.gle.Low=Low or -1.2
|
||||
self.gle.LOW=LOW or -1.5
|
||||
else
|
||||
self.gle._max=_max or 0.4
|
||||
self.gle.High=High or 0.8
|
||||
self.gle.HIGH=HIGH or 1.5
|
||||
self.gle._min=_min or -0.3
|
||||
self.gle.Low=Low or -0.6
|
||||
self.gle.LOW=LOW or -0.9
|
||||
-- CVN values
|
||||
self.gle._max=_max or 0.4
|
||||
self.gle.High=High or 0.8
|
||||
self.gle.HIGH=HIGH or 1.5
|
||||
self.gle._min=_min or -0.3
|
||||
self.gle.Low=Low or -0.6
|
||||
self.gle.LOW=LOW or -0.9
|
||||
end
|
||||
|
||||
return self
|
||||
@@ -3066,7 +3084,7 @@ end
|
||||
-- @param #number Port Port of the SRS server, defaults to 5002.
|
||||
-- @param #string Culture (Optional, Airboss Culture) Culture, defaults to "en-US".
|
||||
-- @param #string Gender (Optional, Airboss Gender) Gender, e.g. "male" or "female". Defaults to "male".
|
||||
-- @param #string Voice (Optional, Airboss Voice) Set to use a specific voice. Will **override gender and culture** settings.
|
||||
-- @param #string Voice (Optional, Airboss Voice) Set to use a specific voice. Will **override gender and culture** settings.
|
||||
-- @param #string GoogleCreds (Optional) Path to Google credentials, e.g. "C:\\Program Files\\DCS-SimpleRadio-Standalone\\yourgooglekey.json".
|
||||
-- @param #number Volume (Optional) E.g. 0.75. Defaults to 1.0 (loudest).
|
||||
-- @param #table AltBackend (Optional) See MSRS for details.
|
||||
@@ -3088,8 +3106,7 @@ function AIRBOSS:EnableSRS(PathToSRS,Port,Culture,Gender,Voice,GoogleCreds,Volum
|
||||
self.SRS:SetVolume(Volume or 1)
|
||||
--self.SRS:SetModulations(Modulations)
|
||||
if GoogleCreds then
|
||||
self.SRS:SetProviderOptionsGoogle(GoogleCreds,GoogleCreds)
|
||||
self.SRS:SetProvider(MSRS.Provider.GOOGLE)
|
||||
self.SRS:SetGoogle(GoogleCreds)
|
||||
end
|
||||
if Voice then
|
||||
self.SRS:SetVoice(Voice)
|
||||
@@ -3098,10 +3115,10 @@ function AIRBOSS:EnableSRS(PathToSRS,Port,Culture,Gender,Voice,GoogleCreds,Volum
|
||||
-- SRSQUEUE
|
||||
self.SRSQ = MSRSQUEUE:New("AIRBOSS")
|
||||
self.SRSQ:SetTransmitOnlyWithPlayers(true)
|
||||
if not self.PilotRadio then
|
||||
if not self.PilotRadio then
|
||||
self:SetSRSPilotVoice()
|
||||
end
|
||||
return self
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set LSO radio frequency and modulation. Default frequency is 264 MHz AM.
|
||||
@@ -3344,6 +3361,22 @@ function AIRBOSS:SetMaxSectionSize( nmax )
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set maximum distance up to which section members are allowed (default: 100 meters).
|
||||
-- @param #AIRBOSS self
|
||||
-- @param #number dmax Max distance in meters (default 100 m). Minimum is 10 m, maximum is 5000 m.
|
||||
-- @return #AIRBOSS self
|
||||
function AIRBOSS:SetMaxSectionDistance( dmax )
|
||||
if dmax then
|
||||
if dmax < 10 then
|
||||
dmax = 10
|
||||
elseif dmax > 5000 then
|
||||
dmax = 5000
|
||||
end
|
||||
end
|
||||
self.maxsectiondistance = dmax or 100
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set max number of flights per stack. All members of a section count as one "flight".
|
||||
-- @param #AIRBOSS self
|
||||
-- @param #number nmax Number of max allowed flights per stack. Default is two. Minimum is one, maximum is 4.
|
||||
@@ -3623,7 +3656,6 @@ function AIRBOSS:onafterStart( From, Event, To )
|
||||
self:HandleEvent( EVENTS.PlayerLeaveUnit, self._PlayerLeft )
|
||||
self:HandleEvent( EVENTS.MissionEnd )
|
||||
self:HandleEvent( EVENTS.RemoveUnit )
|
||||
self:HandleEvent( EVENTS.UnitLost, self.OnEventRemoveUnit )
|
||||
|
||||
-- self.StatusScheduler=SCHEDULER:New(self)
|
||||
-- self.StatusScheduler:Schedule(self, self._Status, {}, 1, 0.5)
|
||||
@@ -4610,6 +4642,51 @@ function AIRBOSS:_InitForrestal()
|
||||
|
||||
end
|
||||
|
||||
--- Init parameters for Essec class carriers.
|
||||
-- @param #AIRBOSS self
|
||||
function AIRBOSS:_InitEssex()
|
||||
|
||||
-- Init Nimitz as default.
|
||||
self:_InitNimitz()
|
||||
|
||||
-- Carrier Parameters.
|
||||
self.carrierparam.sterndist = -126
|
||||
self.carrierparam.deckheight = 19.27 --DCS World\CoreMods\tech\M3 WWII PTO units\Database\Essex_Class_Carrier_1944.lua
|
||||
|
||||
-- Total size of the carrier (approx as rectangle).
|
||||
self.carrierparam.totlength = 268
|
||||
self.carrierparam.totwidthport = 23
|
||||
self.carrierparam.totwidthstarboard = 23
|
||||
|
||||
-- Landing runway.
|
||||
self.carrierparam.rwyangle = 0.0
|
||||
self.carrierparam.rwylength = 265
|
||||
self.carrierparam.rwywidth = 20
|
||||
|
||||
-- Wires.
|
||||
self.carrierparam.wire1 = 21.9
|
||||
self.carrierparam.wire2 = 28.3
|
||||
self.carrierparam.wire3 = 34.7
|
||||
self.carrierparam.wire4 = 41.1
|
||||
self.carrierparam.wire5 = 47.4
|
||||
self.carrierparam.wire6 = 53.7
|
||||
self.carrierparam.wire7 = 59.0
|
||||
|
||||
self.carrierparam.wire8 = 64.1
|
||||
self.carrierparam.wire9 = 72.7
|
||||
self.carrierparam.wire10 = 78.0
|
||||
self.carrierparam.wire11 = 85.5
|
||||
|
||||
self.carrierparam.wire12 = 105.9
|
||||
self.carrierparam.wire13 = 113.3
|
||||
self.carrierparam.wire14 = 121.0
|
||||
self.carrierparam.wire15 = 128.5
|
||||
|
||||
-- Landing distance.
|
||||
self.carrierparam.landingdist = self.carrierparam.sterndist+self.carrierparam.wire3
|
||||
|
||||
end
|
||||
|
||||
--- Init parameters for R12 HMS Hermes carrier.
|
||||
-- @param #AIRBOSS self
|
||||
function AIRBOSS:_InitHermes()
|
||||
@@ -5312,7 +5389,8 @@ function AIRBOSS:_GetAircraftAoA( playerData )
|
||||
local goshawk = playerData.actype == AIRBOSS.AircraftCarrier.T45C
|
||||
local skyhawk = playerData.actype == AIRBOSS.AircraftCarrier.A4EC
|
||||
local harrier = playerData.actype == AIRBOSS.AircraftCarrier.AV8B
|
||||
local tomcat = playerData.actype == AIRBOSS.AircraftCarrier.F14A or playerData.actype == AIRBOSS.AircraftCarrier.F14B
|
||||
local tomcat = playerData.actype == AIRBOSS.AircraftCarrier.F14A or playerData.actype == AIRBOSS.AircraftCarrier.F14B
|
||||
local corsair = playerData.actype == AIRBOSS.AircraftCarrier.CORSAIR or playerData.actype == AIRBOSS.AircraftCarrier.CORSAIR_CW
|
||||
|
||||
-- Table with AoA values.
|
||||
local aoa = {} -- #AIRBOSS.AircraftAoA
|
||||
@@ -5357,7 +5435,6 @@ function AIRBOSS:_GetAircraftAoA( playerData )
|
||||
aoa.Fast = 8.25 -- =17.5/2
|
||||
aoa.FAST = 8.00 -- =16.5/2
|
||||
elseif harrier then
|
||||
|
||||
-- AV-8B Harrier parameters. Tuning done on the Fast AoA to allow for abeam and ninety at Nozzles 55. Pene testing
|
||||
aoa.SLOW = 16.0
|
||||
aoa.Slow = 13.5
|
||||
@@ -5366,7 +5443,15 @@ function AIRBOSS:_GetAircraftAoA( playerData )
|
||||
aoa.OnSpeedMin = 9.5
|
||||
aoa.Fast = 8.0
|
||||
aoa.FAST = 7.5
|
||||
|
||||
elseif corsair then
|
||||
-- F4U-1D Corsair parameters.
|
||||
aoa.SLOW = 16.0
|
||||
aoa.Slow = 13.5
|
||||
aoa.OnSpeedMax = 12.5
|
||||
aoa.OnSpeed = 10.0
|
||||
aoa.OnSpeedMin = 9.5
|
||||
aoa.Fast = 8.0
|
||||
aoa.FAST = 7.5
|
||||
end
|
||||
|
||||
return aoa
|
||||
@@ -5479,6 +5564,7 @@ function AIRBOSS:_GetAircraftParameters( playerData, step )
|
||||
local tomcat = playerData.actype == AIRBOSS.AircraftCarrier.F14A or playerData.actype == AIRBOSS.AircraftCarrier.F14B
|
||||
local harrier = playerData.actype == AIRBOSS.AircraftCarrier.AV8B
|
||||
local goshawk = playerData.actype == AIRBOSS.AircraftCarrier.T45C
|
||||
local corsair = playerData.actype == AIRBOSS.AircraftCarrier.CORSAIR or playerData.actype == AIRBOSS.AircraftCarrier.CORSAIR_CW
|
||||
|
||||
-- Return values.
|
||||
local alt
|
||||
@@ -5538,6 +5624,9 @@ function AIRBOSS:_GetAircraftParameters( playerData, step )
|
||||
elseif goshawk then
|
||||
alt = UTILS.FeetToMeters( 800 )
|
||||
speed = UTILS.KnotsToMps( 300 )
|
||||
elseif corsair then
|
||||
alt = UTILS.FeetToMeters( 300 )
|
||||
speed = UTILS.KnotsToMps( 120 )
|
||||
end
|
||||
|
||||
elseif step == AIRBOSS.PatternStep.BREAKENTRY then
|
||||
@@ -5551,6 +5640,9 @@ function AIRBOSS:_GetAircraftParameters( playerData, step )
|
||||
elseif goshawk then
|
||||
alt = UTILS.FeetToMeters( 800 )
|
||||
speed = UTILS.KnotsToMps( 300 )
|
||||
elseif corsair then
|
||||
alt = UTILS.FeetToMeters( 200 )
|
||||
speed = UTILS.KnotsToMps( 110 )
|
||||
end
|
||||
|
||||
elseif step == AIRBOSS.PatternStep.EARLYBREAK then
|
||||
@@ -5559,6 +5651,9 @@ function AIRBOSS:_GetAircraftParameters( playerData, step )
|
||||
alt = UTILS.FeetToMeters( 800 )
|
||||
elseif skyhawk then
|
||||
alt = UTILS.FeetToMeters( 600 )
|
||||
elseif corsair then
|
||||
alt = UTILS.FeetToMeters( 200 )
|
||||
speed = UTILS.KnotsToMps( 100 )
|
||||
end
|
||||
|
||||
elseif step == AIRBOSS.PatternStep.LATEBREAK then
|
||||
@@ -5567,6 +5662,9 @@ function AIRBOSS:_GetAircraftParameters( playerData, step )
|
||||
alt = UTILS.FeetToMeters( 800 )
|
||||
elseif skyhawk then
|
||||
alt = UTILS.FeetToMeters( 600 )
|
||||
elseif corsair then
|
||||
alt = UTILS.FeetToMeters( 150 )
|
||||
speed = UTILS.KnotsToMps( 100 )
|
||||
end
|
||||
|
||||
elseif step == AIRBOSS.PatternStep.ABEAM then
|
||||
@@ -5575,6 +5673,9 @@ function AIRBOSS:_GetAircraftParameters( playerData, step )
|
||||
alt = UTILS.FeetToMeters( 600 )
|
||||
elseif skyhawk then
|
||||
alt = UTILS.FeetToMeters( 500 )
|
||||
elseif corsair then
|
||||
alt = UTILS.FeetToMeters( 150 )
|
||||
speed = UTILS.KnotsToMps( 90 )
|
||||
end
|
||||
|
||||
aoa = aoaac.OnSpeed
|
||||
@@ -5599,6 +5700,9 @@ function AIRBOSS:_GetAircraftParameters( playerData, step )
|
||||
alt = UTILS.FeetToMeters( 500 )
|
||||
elseif harrier then
|
||||
alt = UTILS.FeetToMeters( 425 )
|
||||
elseif corsair then
|
||||
alt = UTILS.FeetToMeters( 90 )
|
||||
speed = UTILS.KnotsToMps( 90 )
|
||||
end
|
||||
|
||||
aoa = aoaac.OnSpeed
|
||||
@@ -5611,6 +5715,8 @@ function AIRBOSS:_GetAircraftParameters( playerData, step )
|
||||
alt = UTILS.FeetToMeters( 430 ) -- Tomcat should be a bit higher as it intercepts the GS a bit higher.
|
||||
elseif skyhawk then
|
||||
alt = UTILS.FeetToMeters( 370 ) -- ?
|
||||
elseif corsair then
|
||||
alt = UTILS.FeetToMeters( 80 )
|
||||
end
|
||||
-- Harrier wont get into wake pos. Runway is not angled and it stays port.
|
||||
|
||||
@@ -5626,6 +5732,8 @@ function AIRBOSS:_GetAircraftParameters( playerData, step )
|
||||
alt = UTILS.FeetToMeters( 300 ) -- ?
|
||||
elseif harrier then
|
||||
alt=UTILS.FeetToMeters(312)-- 300-325 ft
|
||||
elseif corsair then
|
||||
alt = UTILS.FeetToMeters( 80 )
|
||||
end
|
||||
|
||||
aoa = aoaac.OnSpeed
|
||||
@@ -6502,6 +6610,8 @@ function AIRBOSS:_LandAI( flight )
|
||||
Speed = UTILS.KnotsToKmph( 175 )
|
||||
elseif flight.actype == AIRBOSS.AircraftCarrier.S3B or flight.actype == AIRBOSS.AircraftCarrier.S3BTANKER then
|
||||
Speed = UTILS.KnotsToKmph( 140 )
|
||||
elseif flight.actype == AIRBOSS.AircraftCarrier.CORSAIR or flight.actype == AIRBOSS.AircraftCarrier.CORSAIR_CW then
|
||||
Speed = UTILS.KnotsToKmph( 100 )
|
||||
end
|
||||
|
||||
-- Carrier position.
|
||||
@@ -8724,13 +8834,13 @@ function AIRBOSS:OnEventRemoveUnit( EventData )
|
||||
|
||||
-- Nil checks.
|
||||
if EventData == nil then
|
||||
self:E( self.lid .. "ERROR: EventData=nil in event REMOVEUNIT!" )
|
||||
self:E( EventData )
|
||||
self:T( self.lid .. "ERROR: EventData=nil in event REMOVEUNIT!" )
|
||||
self:T( EventData )
|
||||
return
|
||||
end
|
||||
if EventData.IniUnit == nil then
|
||||
self:E( self.lid .. "ERROR: EventData.IniUnit=nil in event REMOVEUNIT!" )
|
||||
self:E( EventData )
|
||||
self:T( self.lid .. "ERROR: EventData.IniUnit=nil in event REMOVEUNIT!" )
|
||||
self:T( EventData )
|
||||
return
|
||||
end
|
||||
|
||||
@@ -10297,6 +10407,9 @@ function AIRBOSS:_GetSternCoord()
|
||||
elseif self.carriertype == AIRBOSS.CarrierType.FORRESTAL then
|
||||
-- Forrestal
|
||||
self.sterncoord:Translate( self.carrierparam.sterndist, hdg, true, true ):Translate( 7.5, FB + 90, true, true )
|
||||
elseif self.carriertype == AIRBOSS.CarrierType.ESSEX then
|
||||
-- Forrestal
|
||||
self.sterncoord:Translate( self.carrierparam.sterndist, hdg, true, true ):Translate( -1, FB + 90, true, true )
|
||||
else
|
||||
-- Nimitz SC: translate 8 meters starboard wrt Final bearing.
|
||||
self.sterncoord:Translate( self.carrierparam.sterndist, hdg, true, true ):Translate( 9.5, FB + 90, true, true )
|
||||
@@ -11598,7 +11711,7 @@ function AIRBOSS:GetHeadingIntoWind_old( vdeck, magnetic, coord )
|
||||
local function adjustDegreesForWindSpeed(windSpeed)
|
||||
local degreesAdjustment = 0
|
||||
-- the windspeeds are in m/s
|
||||
|
||||
|
||||
-- +0 degrees at 15m/s = 37kts
|
||||
-- +0 degrees at 14m/s = 35kts
|
||||
-- +0 degrees at 13m/s = 33kts
|
||||
@@ -11613,7 +11726,7 @@ function AIRBOSS:GetHeadingIntoWind_old( vdeck, magnetic, coord )
|
||||
-- +20 degrees at 4m/s = 26kts
|
||||
-- +20 degrees at 3m/s = 26kts
|
||||
-- +30 degrees at 2m/s = 26kts 1s
|
||||
|
||||
|
||||
if windSpeed > 0 and windSpeed < 3 then
|
||||
degreesAdjustment = 30
|
||||
elseif windSpeed >= 3 and windSpeed < 5 then
|
||||
@@ -11625,7 +11738,7 @@ function AIRBOSS:GetHeadingIntoWind_old( vdeck, magnetic, coord )
|
||||
elseif windSpeed >= 13 then
|
||||
degreesAdjustment = 0
|
||||
end
|
||||
|
||||
|
||||
return degreesAdjustment
|
||||
end
|
||||
|
||||
@@ -11684,60 +11797,60 @@ function AIRBOSS:GetHeadingIntoWind_new( vdeck, magnetic, coord )
|
||||
local h=self:GetHeading(magnetic)
|
||||
return h, math.min(vdeck, Vmax)
|
||||
end
|
||||
|
||||
|
||||
-- Convert wind speed to knots.
|
||||
vwind=UTILS.MpsToKnots(vwind)
|
||||
|
||||
|
||||
-- Wind to in knots.
|
||||
local windto=(windfrom+180)%360
|
||||
|
||||
|
||||
-- Offset angle in rad. We also define the rotation to be clock-wise, which requires a minus sign.
|
||||
local alpha=math.rad(-Offset)
|
||||
|
||||
|
||||
-- Constant.
|
||||
local C = math.sqrt(math.cos(alpha)^2 / math.sin(alpha)^2 + 1)
|
||||
|
||||
|
||||
|
||||
-- Upper limit of desired speed due to max boat speed.
|
||||
local vdeckMax=vwind + math.cos(alpha) * Vmax
|
||||
|
||||
|
||||
-- Lower limit of desired speed due to min boat speed.
|
||||
local vdeckMin=vwind + math.cos(alpha) * Vmin
|
||||
|
||||
|
||||
|
||||
|
||||
-- Speed of ship so it matches the desired speed.
|
||||
local v=0
|
||||
|
||||
-- Angle wrt. to wind TO-direction
|
||||
|
||||
-- Angle wrt. to wind TO-direction
|
||||
local theta=0
|
||||
|
||||
if vdeck>vdeckMax then
|
||||
-- Boat cannot go fast enough
|
||||
|
||||
|
||||
-- Set max speed.
|
||||
v=Vmax
|
||||
|
||||
|
||||
-- Calculate theta.
|
||||
theta = math.asin(v/(vwind*C)) - math.asin(-1/C)
|
||||
|
||||
|
||||
elseif vdeck<vdeckMin then
|
||||
-- Boat cannot go slow enought
|
||||
|
||||
|
||||
-- Set min speed.
|
||||
v=Vmin
|
||||
|
||||
|
||||
-- Calculatge theta.
|
||||
theta = math.asin(v/(vwind*C)) - math.asin(-1/C)
|
||||
|
||||
|
||||
elseif vdeck*math.sin(alpha)>vwind then
|
||||
-- Too little wind
|
||||
|
||||
|
||||
-- Set theta to 90°
|
||||
theta=math.pi/2
|
||||
|
||||
|
||||
-- Set speed.
|
||||
v = math.sqrt(vdeck^2 - vwind^2)
|
||||
|
||||
|
||||
else
|
||||
-- Normal case
|
||||
theta = math.asin(vdeck * math.sin(alpha) / vwind)
|
||||
@@ -11746,9 +11859,9 @@ function AIRBOSS:GetHeadingIntoWind_new( vdeck, magnetic, coord )
|
||||
|
||||
-- Magnetic heading.
|
||||
local magvar= magnetic and self.magvar or 0
|
||||
|
||||
|
||||
-- Ship heading so cross wind is min for the given wind.
|
||||
local intowind = (540 + (windto - magvar + math.deg(theta) )) % 360
|
||||
local intowind = (540 + (windto - magvar + math.deg(theta) )) % 360
|
||||
|
||||
return intowind, v
|
||||
end
|
||||
@@ -12206,7 +12319,7 @@ function AIRBOSS:_LSOgrade( playerData )
|
||||
-- Normal laning part at the beginning
|
||||
local Gb = GXX .. " " .. GIM
|
||||
|
||||
-- Number of deviations that occurred at the the beginning of the landing (XX or IM). These are graded like in non-VTOL landings, i.e. on deviations is
|
||||
-- Number of deviations that occurred at the the beginning of the landing (XX or IM). These are graded like in non-VTOL landings, i.e. on deviations is
|
||||
local N=nXX+nIM
|
||||
local nL=count(Gb, '_')/2
|
||||
local nS=count(Gb, '%(')
|
||||
@@ -12224,7 +12337,7 @@ function AIRBOSS:_LSOgrade( playerData )
|
||||
|
||||
if nL>0 or nLv>1 then
|
||||
-- Larger deviations at XX or IM or at least one larger deviation IC or AR==> "No grade" 2.0 points.
|
||||
-- In other words, we allow one larger deviation at IC+AR
|
||||
-- In other words, we allow one larger deviation at IC+AR
|
||||
grade="--"
|
||||
points=2.0
|
||||
elseif nN>0 or nNv>1 or nLv==1 then
|
||||
@@ -13720,7 +13833,7 @@ function AIRBOSS:CarrierTurnIntoWind( time, vdeck, uturn )
|
||||
local deltaH = self:_GetDeltaHeading( hdg, hiw )
|
||||
|
||||
-- Debug output
|
||||
self:I( self.lid .. string.format( "Carrier steaming into the wind (%.1f kts). Heading=%03d-->%03d (Delta=%.1f), Speed=%.1f knots, Distance=%.1f NM, Time=%d sec",
|
||||
self:I( self.lid .. string.format( "Carrier steaming into the wind (%.1f kts). Heading=%03d-->%03d (Delta=%.1f), Speed=%.1f knots, Distance=%.1f NM, Time=%d sec",
|
||||
UTILS.MpsToKnots( vwind ), hdg, hiw, deltaH, speedknots, distNM, speedknots, time ) )
|
||||
|
||||
-- Current coordinate.
|
||||
@@ -14932,12 +15045,12 @@ function AIRBOSS:RadioTransmission( radio, call, loud, delay, interval, click, p
|
||||
if radio == nil or call == nil then
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
if not self.SRS then
|
||||
|
||||
|
||||
-- Create a new radio transmission item.
|
||||
local transmission = {} -- #AIRBOSS.Radioitem
|
||||
|
||||
|
||||
transmission.radio = radio
|
||||
transmission.call = call
|
||||
transmission.Tplay = timer.getAbsTime() + (delay or 0)
|
||||
@@ -14945,49 +15058,49 @@ function AIRBOSS:RadioTransmission( radio, call, loud, delay, interval, click, p
|
||||
transmission.isplaying = false
|
||||
transmission.Tstarted = nil
|
||||
transmission.loud = loud and call.loud
|
||||
|
||||
|
||||
-- Player onboard number if sender has one.
|
||||
if self:_IsOnboard( call.modexsender ) then
|
||||
self:_Number2Radio( radio, call.modexsender, delay, 0.3, pilotcall )
|
||||
end
|
||||
|
||||
|
||||
-- Play onboard number if receiver has one.
|
||||
if self:_IsOnboard( call.modexreceiver ) then
|
||||
self:_Number2Radio( radio, call.modexreceiver, delay, 0.3, pilotcall )
|
||||
end
|
||||
|
||||
|
||||
-- Add transmission to the right queue.
|
||||
local caller = ""
|
||||
if radio.alias == "LSO" then
|
||||
|
||||
|
||||
table.insert( self.RQLSO, transmission )
|
||||
|
||||
|
||||
caller = "LSOCall"
|
||||
|
||||
|
||||
-- Schedule radio queue checks.
|
||||
if not self.RQLid then
|
||||
self:T( self.lid .. string.format( "Starting LSO radio queue." ) )
|
||||
self.RQLid = self.radiotimer:Schedule( nil, AIRBOSS._CheckRadioQueue, { self, self.RQLSO, "LSO" }, 0.02, 0.05 )
|
||||
end
|
||||
|
||||
|
||||
elseif radio.alias == "MARSHAL" then
|
||||
|
||||
|
||||
table.insert( self.RQMarshal, transmission )
|
||||
|
||||
|
||||
caller = "MarshalCall"
|
||||
|
||||
|
||||
if not self.RQMid then
|
||||
self:T( self.lid .. string.format( "Starting Marhal radio queue." ) )
|
||||
self.RQMid = self.radiotimer:Schedule( nil, AIRBOSS._CheckRadioQueue, { self, self.RQMarshal, "MARSHAL" }, 0.02, 0.05 )
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
-- Append radio click sound at the end of the transmission.
|
||||
if click then
|
||||
self:RadioTransmission( radio, self[caller].CLICK, false, delay )
|
||||
end
|
||||
|
||||
|
||||
else
|
||||
|
||||
-- SRS transmission
|
||||
@@ -14998,7 +15111,7 @@ function AIRBOSS:RadioTransmission( radio, call, loud, delay, interval, click, p
|
||||
local voice = nil
|
||||
local gender = nil
|
||||
local culture = nil
|
||||
|
||||
|
||||
if radio.alias == "AIRBOSS" then
|
||||
frequency = self.AirbossRadio.frequency
|
||||
modulation = self.AirbossRadio.modulation
|
||||
@@ -15006,13 +15119,13 @@ function AIRBOSS:RadioTransmission( radio, call, loud, delay, interval, click, p
|
||||
gender = self.AirbossRadio.gender
|
||||
culture = self.AirbossRadio.culture
|
||||
end
|
||||
|
||||
|
||||
if radio.alias == "MARSHAL" then
|
||||
voice = self.MarshalRadio.voice
|
||||
gender = self.MarshalRadio.gender
|
||||
culture = self.MarshalRadio.culture
|
||||
end
|
||||
|
||||
|
||||
if radio.alias == "LSO" then
|
||||
frequency = self.LSORadio.frequency
|
||||
modulation = self.LSORadio.modulation
|
||||
@@ -15020,7 +15133,7 @@ function AIRBOSS:RadioTransmission( radio, call, loud, delay, interval, click, p
|
||||
gender = self.LSORadio.gender
|
||||
culture = self.LSORadio.culture
|
||||
end
|
||||
|
||||
|
||||
if pilotcall then
|
||||
voice = self.PilotRadio.voice
|
||||
gender = self.PilotRadio.gender
|
||||
@@ -15034,16 +15147,16 @@ function AIRBOSS:RadioTransmission( radio, call, loud, delay, interval, click, p
|
||||
modulation = self.AirbossRadio.modulation
|
||||
radio.alias = "AIRBOSS"
|
||||
end
|
||||
|
||||
|
||||
local volume = nil
|
||||
|
||||
|
||||
if loud then
|
||||
volume = 1.0
|
||||
end
|
||||
|
||||
|
||||
--local text = tostring(call.modexreceiver).."; "..radio.alias.."; "..call.subtitle
|
||||
local text = call.subtitle
|
||||
self:T(self.lid..text)
|
||||
self:T(self.lid..text)
|
||||
local srstext = self:_GetNiceSRSText(text)
|
||||
self.SRSQ:NewTransmission(srstext, call.duration, self.SRS, nil, 0.1, nil, call.subtitle, call.subduration, frequency, modulation, gender, culture, voice, volume, radio.alias)
|
||||
end
|
||||
@@ -15063,11 +15176,11 @@ function AIRBOSS:SetSRSPilotVoice( Voice, Gender, Culture )
|
||||
self.PilotRadio.voice = Voice or MSRS.Voices.Microsoft.David
|
||||
self.PilotRadio.gender = Gender or "male"
|
||||
self.PilotRadio.culture = Culture or "en-US"
|
||||
|
||||
|
||||
if (not Voice) and self.SRS and self.SRS:GetProvider() == MSRS.Provider.GOOGLE then
|
||||
self.PilotRadio.voice = MSRS.Voices.Google.Standard.en_US_Standard_J
|
||||
end
|
||||
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
@@ -15381,44 +15494,44 @@ function AIRBOSS:MessageToPlayer( playerData, message, sender, receiver, duratio
|
||||
-- SCHEDULER:New(nil, self.MessageToPlayer, {self, playerData, message, sender, receiver, duration, clear}, delay)
|
||||
self:ScheduleOnce( delay, self.MessageToPlayer, self, playerData, message, sender, receiver, duration, clear )
|
||||
else
|
||||
|
||||
|
||||
if not self.SRS then
|
||||
-- Wait until previous sound finished.
|
||||
local wait = 0
|
||||
|
||||
|
||||
-- Onboard number to get the attention.
|
||||
if receiver == playerData.onboard then
|
||||
|
||||
|
||||
-- Which voice over number to use.
|
||||
if sender and (sender == "LSO" or sender == "MARSHAL" or sender == "AIRBOSS") then
|
||||
|
||||
|
||||
-- User sound of board number.
|
||||
wait = wait + self:_Number2Sound( playerData, sender, receiver )
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- Negative.
|
||||
if string.find( text:lower(), "negative" ) then
|
||||
local filename = self:_RadioFilename( self.MarshalCall.NEGATIVE, false, "MARSHAL" )
|
||||
USERSOUND:New( filename ):ToGroup( playerData.group, wait )
|
||||
wait = wait + self.MarshalCall.NEGATIVE.duration
|
||||
end
|
||||
|
||||
|
||||
-- Affirm.
|
||||
if string.find( text:lower(), "affirm" ) then
|
||||
local filename = self:_RadioFilename( self.MarshalCall.AFFIRMATIVE, false, "MARSHAL" )
|
||||
USERSOUND:New( filename ):ToGroup( playerData.group, wait )
|
||||
wait = wait + self.MarshalCall.AFFIRMATIVE.duration
|
||||
end
|
||||
|
||||
|
||||
-- Roger.
|
||||
if string.find( text:lower(), "roger" ) then
|
||||
local filename = self:_RadioFilename( self.MarshalCall.ROGER, false, "MARSHAL" )
|
||||
USERSOUND:New( filename ):ToGroup( playerData.group, wait )
|
||||
wait = wait + self.MarshalCall.ROGER.duration
|
||||
end
|
||||
|
||||
|
||||
-- Play click sound to end message.
|
||||
if wait > 0 then
|
||||
local filename = self:_RadioFilename( self.MarshalCall.CLICK )
|
||||
@@ -15431,7 +15544,7 @@ function AIRBOSS:MessageToPlayer( playerData, message, sender, receiver, duratio
|
||||
local voice = self.MarshalRadio.voice
|
||||
local gender = self.MarshalRadio.gender
|
||||
local culture = self.MarshalRadio.culture
|
||||
|
||||
|
||||
if not sender then sender = "AIRBOSS" end
|
||||
|
||||
if string.find(sender,"AIRBOSS" ) then
|
||||
@@ -17049,7 +17162,7 @@ function AIRBOSS:_RemoveSectionMember( playerData, sectionmember )
|
||||
return false
|
||||
end
|
||||
|
||||
--- Set all flights within 100 meters to be part of my section.
|
||||
--- Set all flights within maxsectiondistance meters to be part of my section (default: 100 meters).
|
||||
-- @param #AIRBOSS self
|
||||
-- @param #string _unitName Name of the player unit.
|
||||
function AIRBOSS:_SetSection( _unitName )
|
||||
@@ -17067,7 +17180,7 @@ function AIRBOSS:_SetSection( _unitName )
|
||||
local mycoord = _unit:GetCoordinate()
|
||||
|
||||
-- Max distance up to which section members are allowed.
|
||||
local dmax = 100
|
||||
local dmax = self.maxsectiondistance
|
||||
|
||||
-- Check if player is in Marshal or pattern queue already.
|
||||
local text
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,624 +0,0 @@
|
||||
--- **Ops** - Brigade Warehouse.
|
||||
--
|
||||
-- **Main Features:**
|
||||
--
|
||||
-- * Manage platoons
|
||||
-- * Carry out ARTY and PATROLZONE missions (AUFTRAG)
|
||||
-- * Define rearming zones
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ## Example Missions:
|
||||
--
|
||||
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/Ops/Brigade).
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **funkyfranky**
|
||||
--
|
||||
-- ===
|
||||
-- @module Ops.Brigade
|
||||
-- @image OPS_Brigade_.png
|
||||
|
||||
|
||||
--- BRIGADE class.
|
||||
-- @type BRIGADE
|
||||
-- @field #string ClassName Name of the class.
|
||||
-- @field #number verbose Verbosity of output.
|
||||
-- @field #table rearmingZones Rearming zones. Each element is of type `#BRIGADE.SupplyZone`.
|
||||
-- @field #table refuellingZones Refuelling zones. Each element is of type `#BRIGADE.SupplyZone`.
|
||||
-- @field Core.Set#SET_ZONE retreatZones Retreat zone set.
|
||||
-- @extends Ops.Legion#LEGION
|
||||
|
||||
--- *I am not afraid of an Army of lions lead by a sheep; I am afraid of sheep lead by a lion* -- Alexander the Great
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- # The BRIGADE Concept
|
||||
--
|
||||
-- A BRIGADE consists of one or multiple PLATOONs. These platoons "live" in a WAREHOUSE that has a phyiscal struction (STATIC or UNIT) and can be captured or destroyed.
|
||||
--
|
||||
--
|
||||
-- @field #BRIGADE
|
||||
BRIGADE = {
|
||||
ClassName = "BRIGADE",
|
||||
verbose = 0,
|
||||
rearmingZones = {},
|
||||
refuellingZones = {},
|
||||
}
|
||||
|
||||
--- Supply Zone.
|
||||
-- @type BRIGADE.SupplyZone
|
||||
-- @field Core.Zone#ZONE zone The zone.
|
||||
-- @field Ops.Auftrag#AUFTRAG mission Mission assigned to supply ammo or fuel.
|
||||
-- @field #boolean markerOn If `true`, marker is on.
|
||||
-- @field Wrapper.Marker#MARKER marker F10 marker.
|
||||
|
||||
--- BRIGADE class version.
|
||||
-- @field #string version
|
||||
BRIGADE.version="0.1.1"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- ToDo list
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- TODO: Spawn when hosting warehouse is a ship or oil rig or gas platform.
|
||||
-- TODO: Rearming zones.
|
||||
-- TODO: Retreat zones.
|
||||
-- DONE: Add weapon range.
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Constructor
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Create a new BRIGADE class object.
|
||||
-- @param #BRIGADE self
|
||||
-- @param #string WarehouseName Name of the warehouse STATIC or UNIT object representing the warehouse.
|
||||
-- @param #string BrigadeName Name of the brigade.
|
||||
-- @return #BRIGADE self
|
||||
function BRIGADE:New(WarehouseName, BrigadeName)
|
||||
|
||||
-- Inherit everything from LEGION class.
|
||||
local self=BASE:Inherit(self, LEGION:New(WarehouseName, BrigadeName)) -- #BRIGADE
|
||||
|
||||
-- Nil check.
|
||||
if not self then
|
||||
BASE:E(string.format("ERROR: Could not find warehouse %s!", WarehouseName))
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Set some string id for output to DCS.log file.
|
||||
self.lid=string.format("BRIGADE %s | ", self.alias)
|
||||
|
||||
-- Defaults
|
||||
self:SetRetreatZones()
|
||||
|
||||
-- Turn ship into NAVYGROUP.
|
||||
if self:IsShip() then
|
||||
local wh=self.warehouse --Wrapper.Unit#UNIT
|
||||
local group=wh:GetGroup()
|
||||
self.warehouseOpsGroup=NAVYGROUP:New(group) --Ops.NavyGroup#NAVYGROUP
|
||||
self.warehouseOpsElement=self.warehouseOpsGroup:GetElementByName(wh:GetName())
|
||||
end
|
||||
|
||||
-- Add FSM transitions.
|
||||
-- From State --> Event --> To State
|
||||
self:AddTransition("*", "ArmyOnMission", "*") -- An ARMYGROUP was send on a Mission (AUFTRAG).
|
||||
|
||||
------------------------
|
||||
--- Pseudo Functions ---
|
||||
------------------------
|
||||
|
||||
--- Triggers the FSM event "Start". Starts the BRIGADE. Initializes parameters and starts event handlers.
|
||||
-- @function [parent=#BRIGADE] Start
|
||||
-- @param #BRIGADE self
|
||||
|
||||
--- Triggers the FSM event "Start" after a delay. Starts the BRIGADE. Initializes parameters and starts event handlers.
|
||||
-- @function [parent=#BRIGADE] __Start
|
||||
-- @param #BRIGADE self
|
||||
-- @param #number delay Delay in seconds.
|
||||
|
||||
|
||||
--- Triggers the FSM event "Stop". Stops the BRIGADE and all its event handlers.
|
||||
-- @param #BRIGADE self
|
||||
|
||||
--- Triggers the FSM event "Stop" after a delay. Stops the BRIGADE and all its event handlers.
|
||||
-- @function [parent=#BRIGADE] __Stop
|
||||
-- @param #BRIGADE self
|
||||
-- @param #number delay Delay in seconds.
|
||||
|
||||
|
||||
--- Triggers the FSM event "ArmyOnMission".
|
||||
-- @function [parent=#BRIGADE] ArmyOnMission
|
||||
-- @param #BRIGADE self
|
||||
-- @param Ops.ArmyGroup#ARMYGROUP ArmyGroup The ARMYGROUP on mission.
|
||||
-- @param Ops.Auftrag#AUFTRAG Mission The mission.
|
||||
|
||||
--- Triggers the FSM event "ArmyOnMission" after a delay.
|
||||
-- @function [parent=#BRIGADE] __ArmyOnMission
|
||||
-- @param #BRIGADE self
|
||||
-- @param #number delay Delay in seconds.
|
||||
-- @param Ops.ArmyGroup#ARMYGROUP ArmyGroup The ARMYGROUP on mission.
|
||||
-- @param Ops.Auftrag#AUFTRAG Mission The mission.
|
||||
|
||||
--- On after "ArmyOnMission" event.
|
||||
-- @function [parent=#BRIGADE] OnAfterArmyOnMission
|
||||
-- @param #BRIGADE self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Ops.ArmyGroup#ARMYGROUP ArmyGroup The ARMYGROUP on mission.
|
||||
-- @param Ops.Auftrag#AUFTRAG Mission The mission.
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- User Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Add a platoon to the brigade.
|
||||
-- @param #BRIGADE self
|
||||
-- @param Ops.Platoon#PLATOON Platoon The platoon object.
|
||||
-- @return #BRIGADE self
|
||||
function BRIGADE:AddPlatoon(Platoon)
|
||||
|
||||
-- Add platoon to brigade.
|
||||
table.insert(self.cohorts, Platoon)
|
||||
|
||||
-- Add assets to platoon.
|
||||
self:AddAssetToPlatoon(Platoon, Platoon.Ngroups)
|
||||
|
||||
-- Set brigade of platoon.
|
||||
Platoon:SetBrigade(self)
|
||||
|
||||
-- Start platoon.
|
||||
if Platoon:IsStopped() then
|
||||
Platoon:Start()
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Add asset group(s) to platoon.
|
||||
-- @param #BRIGADE self
|
||||
-- @param Ops.Platoon#PLATOON Platoon The platoon object.
|
||||
-- @param #number Nassets Number of asset groups to add.
|
||||
-- @return #BRIGADE self
|
||||
function BRIGADE:AddAssetToPlatoon(Platoon, Nassets)
|
||||
|
||||
if Platoon then
|
||||
|
||||
-- Get the template group of the platoon.
|
||||
local Group=GROUP:FindByName(Platoon.templatename)
|
||||
|
||||
if Group then
|
||||
|
||||
-- Debug text.
|
||||
local text=string.format("Adding asset %s to platoon %s", Group:GetName(), Platoon.name)
|
||||
self:T(self.lid..text)
|
||||
|
||||
-- Add assets to airwing warehouse.
|
||||
self:AddAsset(Group, Nassets, nil, nil, nil, nil, Platoon.skill, Platoon.livery, Platoon.name)
|
||||
|
||||
else
|
||||
self:E(self.lid.."ERROR: Group does not exist!")
|
||||
end
|
||||
|
||||
else
|
||||
self:E(self.lid.."ERROR: Platoon does not exit!")
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Define a set of retreat zones.
|
||||
-- @param #BRIGADE self
|
||||
-- @param Core.Set#SET_ZONE RetreatZoneSet Set of retreat zones.
|
||||
-- @return #BRIGADE self
|
||||
function BRIGADE:SetRetreatZones(RetreatZoneSet)
|
||||
self.retreatZones=RetreatZoneSet or SET_ZONE:New()
|
||||
return self
|
||||
end
|
||||
|
||||
--- Add a retreat zone.
|
||||
-- @param #BRIGADE self
|
||||
-- @param Core.Zone#ZONE RetreatZone Retreat zone.
|
||||
-- @return #BRIGADE self
|
||||
function BRIGADE:AddRetreatZone(RetreatZone)
|
||||
self.retreatZones:AddZone(RetreatZone)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Get retreat zones.
|
||||
-- @param #BRIGADE self
|
||||
-- @return Core.Set#SET_ZONE Set of retreat zones.
|
||||
function BRIGADE:GetRetreatZones()
|
||||
return self.retreatZones
|
||||
end
|
||||
|
||||
--- Add a rearming zone.
|
||||
-- @param #BRIGADE self
|
||||
-- @param Core.Zone#ZONE RearmingZone Rearming zone.
|
||||
-- @return #BRIGADE.SupplyZone The rearming zone data.
|
||||
function BRIGADE:AddRearmingZone(RearmingZone)
|
||||
|
||||
local rearmingzone={} --#BRIGADE.SupplyZone
|
||||
|
||||
rearmingzone.zone=RearmingZone
|
||||
rearmingzone.mission=nil
|
||||
rearmingzone.marker=MARKER:New(rearmingzone.zone:GetCoordinate(), "Rearming Zone"):ToCoalition(self:GetCoalition())
|
||||
|
||||
table.insert(self.rearmingZones, rearmingzone)
|
||||
|
||||
return rearmingzone
|
||||
end
|
||||
|
||||
|
||||
--- Add a refuelling zone.
|
||||
-- @param #BRIGADE self
|
||||
-- @param Core.Zone#ZONE RefuellingZone Refuelling zone.
|
||||
-- @return #BRIGADE.SupplyZone The refuelling zone data.
|
||||
function BRIGADE:AddRefuellingZone(RefuellingZone)
|
||||
|
||||
local supplyzone={} --#BRIGADE.SupplyZone
|
||||
|
||||
supplyzone.zone=RefuellingZone
|
||||
supplyzone.mission=nil
|
||||
supplyzone.marker=MARKER:New(supplyzone.zone:GetCoordinate(), "Refuelling Zone"):ToCoalition(self:GetCoalition())
|
||||
|
||||
table.insert(self.refuellingZones, supplyzone)
|
||||
|
||||
return supplyzone
|
||||
end
|
||||
|
||||
|
||||
--- Get platoon by name.
|
||||
-- @param #BRIGADE self
|
||||
-- @param #string PlatoonName Name of the platoon.
|
||||
-- @return Ops.Platoon#PLATOON The Platoon object.
|
||||
function BRIGADE:GetPlatoon(PlatoonName)
|
||||
local platoon=self:_GetCohort(PlatoonName)
|
||||
return platoon
|
||||
end
|
||||
|
||||
--- Get platoon of an asset.
|
||||
-- @param #BRIGADE self
|
||||
-- @param Functional.Warehouse#WAREHOUSE.Assetitem Asset The platoon asset.
|
||||
-- @return Ops.Platoon#PLATOON The platoon object.
|
||||
function BRIGADE:GetPlatoonOfAsset(Asset)
|
||||
local platoon=self:GetPlatoon(Asset.squadname)
|
||||
return platoon
|
||||
end
|
||||
|
||||
--- Remove asset from platoon.
|
||||
-- @param #BRIGADE self
|
||||
-- @param Functional.Warehouse#WAREHOUSE.Assetitem Asset The platoon asset.
|
||||
function BRIGADE:RemoveAssetFromPlatoon(Asset)
|
||||
local platoon=self:GetPlatoonOfAsset(Asset)
|
||||
if platoon then
|
||||
platoon:DelAsset(Asset)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--- [ GROUND ] Function to load back an asset in the field that has been filed before.
|
||||
-- @param #BRIGADE self
|
||||
-- @param #string Templatename e.g."1 PzDv LogRg I\_AID-976" - that's the alias (name) of an platoon spawned as `"platoon - alias"_AID-"asset-ID"`
|
||||
-- @param Core.Point#COORDINATE Position where to spawn the platoon
|
||||
-- @return #BRIGADE self
|
||||
-- @usage
|
||||
-- Prerequisites:
|
||||
-- Save the assets spawned by BRIGADE/CHIEF regularly (~every 5 mins) into a file, e.g. like this:
|
||||
--
|
||||
-- local Path = FilePath or "C:\\Users\\<yourname>\\Saved Games\\DCS\\Missions\\" -- example path
|
||||
-- local BlueOpsFilename = BlueFileName or "ExamplePlatoonSave.csv" -- example filename
|
||||
-- local BlueSaveOps = SET_OPSGROUP:New():FilterCoalitions("blue"):FilterCategoryGround():FilterOnce()
|
||||
-- UTILS.SaveSetOfOpsGroups(BlueSaveOps,Path,BlueOpsFilename)
|
||||
--
|
||||
-- where Path and Filename are strings, as chosen by you.
|
||||
-- You can then load back the assets at the start of your next mission run. Be aware that it takes a couple of seconds for the
|
||||
-- platoon data to arrive in brigade, so make this an action after ~20 seconds, e.g. like so:
|
||||
--
|
||||
-- function LoadBackAssets()
|
||||
-- local Path = FilePath or "C:\\Users\\<yourname>\\Saved Games\\DCS\\Missions\\" -- example path
|
||||
-- local BlueOpsFilename = BlueFileName or "ExamplePlatoonSave.csv" -- example filename
|
||||
-- if UTILS.CheckFileExists(Path,BlueOpsFilename) then
|
||||
-- local loadback = UTILS.LoadSetOfOpsGroups(Path,BlueOpsFilename,false)
|
||||
-- for _,_platoondata in pairs (loadback) do
|
||||
-- local groupname = _platoondata.groupname -- #string
|
||||
-- local coordinate = _platoondata.coordinate -- Core.Point#COORDINATE
|
||||
-- Your_Brigade:LoadBackAssetInPosition(groupname,coordinate)
|
||||
-- end
|
||||
-- end
|
||||
-- end
|
||||
--
|
||||
-- local AssetLoader = TIMER:New(LoadBackAssets)
|
||||
-- AssetLoader:Start(20)
|
||||
--
|
||||
-- The assets loaded back into the mission will be considered for AUFTRAG type missions from CHIEF and BRIGADE.
|
||||
function BRIGADE:LoadBackAssetInPosition(Templatename,Position)
|
||||
self:T(self.lid .. "LoadBackAssetInPosition: " .. tostring(Templatename))
|
||||
|
||||
-- get Platoon alias from Templatename
|
||||
local nametbl = UTILS.Split(Templatename,"_")
|
||||
|
||||
local name = nametbl[1]
|
||||
|
||||
self:T(string.format("*** Target Platoon = %s ***",name))
|
||||
|
||||
-- find a matching asset table from BRIGADE
|
||||
local cohorts = self.cohorts or {}
|
||||
local thisasset = nil --Functional.Warehouse#WAREHOUSE.Assetitem
|
||||
local found = false
|
||||
|
||||
for _,_cohort in pairs(cohorts) do
|
||||
local asset = _cohort:GetName()
|
||||
self:T(string.format("*** Looking at Platoon = %s ***",asset))
|
||||
if asset == name then
|
||||
self:T("**** Found Platoon ****")
|
||||
local cohassets = _cohort.assets or {}
|
||||
for _,_zug in pairs (cohassets) do
|
||||
local zug = _zug -- Functional.Warehouse#WAREHOUSE.Assetitem
|
||||
if zug.assignment == name and zug.requested == false then
|
||||
self:T("**** Found Asset ****")
|
||||
found = true
|
||||
thisasset = zug --Functional.Warehouse#WAREHOUSE.Assetitem
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if found then
|
||||
|
||||
-- prep asset
|
||||
thisasset.rid = thisasset.uid
|
||||
thisasset.requested = false
|
||||
thisasset.score=100
|
||||
thisasset.missionTask="CAS"
|
||||
thisasset.spawned = true
|
||||
local template = thisasset.templatename
|
||||
local alias = thisasset.spawngroupname
|
||||
|
||||
-- Spawn group
|
||||
local spawnasset = SPAWN:NewWithAlias(template,alias)
|
||||
:InitDelayOff()
|
||||
:SpawnFromCoordinate(Position)
|
||||
|
||||
-- build a new self request
|
||||
local request = {} --Functional.Warehouse#WAREHOUSE.Pendingitem
|
||||
request.assignment = name
|
||||
request.warehouse = self
|
||||
request.assets = {thisasset}
|
||||
request.ntransporthome = 0
|
||||
request.ndelivered = 0
|
||||
request.ntransport = 0
|
||||
request.cargoattribute = thisasset.attribute
|
||||
request.category = thisasset.category
|
||||
request.cargoassets = {thisasset}
|
||||
request.assetdesc = WAREHOUSE.Descriptor.ASSETLIST
|
||||
request.cargocategory = thisasset.category
|
||||
request.toself = true
|
||||
request.transporttype = WAREHOUSE.TransportType.SELFPROPELLED
|
||||
request.assetproblem = {}
|
||||
request.born = true
|
||||
request.prio = 50
|
||||
request.uid = thisasset.uid
|
||||
request.airbase = nil
|
||||
request.timestamp = timer.getAbsTime()
|
||||
request.assetdescval = {thisasset}
|
||||
request.nasset = 1
|
||||
request.cargogroupset = SET_GROUP:New()
|
||||
request.cargogroupset:AddGroup(spawnasset)
|
||||
request.iscargo = true
|
||||
|
||||
-- Call Brigade self
|
||||
self:__AssetSpawned(2, spawnasset, thisasset, request)
|
||||
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- FSM Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Start BRIGADE FSM.
|
||||
-- @param #BRIGADE self
|
||||
function BRIGADE:onafterStart(From, Event, To)
|
||||
|
||||
-- Start parent Warehouse.
|
||||
self:GetParent(self, BRIGADE).onafterStart(self, From, Event, To)
|
||||
|
||||
-- Info.
|
||||
self:I(self.lid..string.format("Starting BRIGADE v%s", BRIGADE.version))
|
||||
|
||||
end
|
||||
|
||||
--- Update status.
|
||||
-- @param #BRIGADE self
|
||||
function BRIGADE:onafterStatus(From, Event, To)
|
||||
|
||||
-- Status of parent Warehouse.
|
||||
self:GetParent(self).onafterStatus(self, From, Event, To)
|
||||
|
||||
-- FSM state.
|
||||
local fsmstate=self:GetState()
|
||||
|
||||
----------------
|
||||
-- Transport ---
|
||||
----------------
|
||||
|
||||
self:CheckTransportQueue()
|
||||
|
||||
--------------
|
||||
-- Mission ---
|
||||
--------------
|
||||
|
||||
-- Check if any missions should be cancelled.
|
||||
self:CheckMissionQueue()
|
||||
|
||||
---------------------
|
||||
-- Rearming Zones ---
|
||||
---------------------
|
||||
|
||||
for _,_rearmingzone in pairs(self.rearmingZones) do
|
||||
local rearmingzone=_rearmingzone --#BRIGADE.SupplyZone
|
||||
if (not rearmingzone.mission) or rearmingzone.mission:IsOver() then
|
||||
rearmingzone.mission=AUFTRAG:NewAMMOSUPPLY(rearmingzone.zone)
|
||||
self:AddMission(rearmingzone.mission)
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------
|
||||
-- Refuelling Zones ---
|
||||
-----------------------
|
||||
|
||||
-- Check refuelling zones.
|
||||
for _,_supplyzone in pairs(self.refuellingZones) do
|
||||
local supplyzone=_supplyzone --#BRIGADE.SupplyZone
|
||||
-- Check if mission is nil or over.
|
||||
if (not supplyzone.mission) or supplyzone.mission:IsOver() then
|
||||
supplyzone.mission=AUFTRAG:NewFUELSUPPLY(supplyzone.zone)
|
||||
self:AddMission(supplyzone.mission)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-----------
|
||||
-- Info ---
|
||||
-----------
|
||||
|
||||
-- Display tactival overview.
|
||||
self:_TacticalOverview()
|
||||
|
||||
-- General info:
|
||||
if self.verbose>=1 then
|
||||
|
||||
-- Count missions not over yet.
|
||||
local Nmissions=self:CountMissionsInQueue()
|
||||
|
||||
-- Asset count.
|
||||
local Npq, Np, Nq=self:CountAssetsOnMission()
|
||||
|
||||
-- Asset string.
|
||||
local assets=string.format("%d [OnMission: Total=%d, Active=%d, Queued=%d]", self:CountAssets(), Npq, Np, Nq)
|
||||
|
||||
-- Output.
|
||||
local text=string.format("%s: Missions=%d, Platoons=%d, Assets=%s", fsmstate, Nmissions, #self.cohorts, assets)
|
||||
self:I(self.lid..text)
|
||||
end
|
||||
|
||||
------------------
|
||||
-- Mission Info --
|
||||
------------------
|
||||
if self.verbose>=2 then
|
||||
local text=string.format("Missions Total=%d:", #self.missionqueue)
|
||||
for i,_mission in pairs(self.missionqueue) do
|
||||
local mission=_mission --Ops.Auftrag#AUFTRAG
|
||||
|
||||
local prio=string.format("%d/%s", mission.prio, tostring(mission.importance)) ; if mission.urgent then prio=prio.." (!)" end
|
||||
local assets=string.format("%d/%d", mission:CountOpsGroups(), mission.Nassets or 0)
|
||||
local target=string.format("%d/%d Damage=%.1f", mission:CountMissionTargets(), mission:GetTargetInitialNumber(), mission:GetTargetDamage())
|
||||
|
||||
text=text..string.format("\n[%d] %s %s: Status=%s, Prio=%s, Assets=%s, Targets=%s", i, mission.name, mission.type, mission.status, prio, assets, target)
|
||||
end
|
||||
self:I(self.lid..text)
|
||||
end
|
||||
|
||||
--------------------
|
||||
-- Transport Info --
|
||||
--------------------
|
||||
if self.verbose>=2 then
|
||||
local text=string.format("Transports Total=%d:", #self.transportqueue)
|
||||
for i,_transport in pairs(self.transportqueue) do
|
||||
local transport=_transport --Ops.OpsTransport#OPSTRANSPORT
|
||||
|
||||
local prio=string.format("%d/%s", transport.prio, tostring(transport.importance)) ; if transport.urgent then prio=prio.." (!)" end
|
||||
local carriers=string.format("Ncargo=%d/%d, Ncarriers=%d", transport.Ncargo, transport.Ndelivered, transport.Ncarrier)
|
||||
|
||||
text=text..string.format("\n[%d] UID=%d: Status=%s, Prio=%s, Cargo: %s", i, transport.uid, transport:GetState(), prio, carriers)
|
||||
end
|
||||
self:I(self.lid..text)
|
||||
end
|
||||
|
||||
-------------------
|
||||
-- Platoon Info --
|
||||
-------------------
|
||||
if self.verbose>=3 then
|
||||
local text="Platoons:"
|
||||
for i,_platoon in pairs(self.cohorts) do
|
||||
local platoon=_platoon --Ops.Platoon#PLATOON
|
||||
|
||||
local callsign=platoon.callsignName and UTILS.GetCallsignName(platoon.callsignName) or "N/A"
|
||||
local modex=platoon.modex and platoon.modex or -1
|
||||
local skill=platoon.skill and tostring(platoon.skill) or "N/A"
|
||||
|
||||
-- Platoon text.
|
||||
text=text..string.format("\n* %s %s: %s*%d/%d, Callsign=%s, Modex=%d, Skill=%s", platoon.name, platoon:GetState(), platoon.aircrafttype, platoon:CountAssets(true), #platoon.assets, callsign, modex, skill)
|
||||
end
|
||||
self:I(self.lid..text)
|
||||
end
|
||||
|
||||
-------------------
|
||||
-- Rearming Info --
|
||||
-------------------
|
||||
if self.verbose>=4 then
|
||||
local text="Rearming Zones:"
|
||||
for i,_rearmingzone in pairs(self.rearmingZones) do
|
||||
local rearmingzone=_rearmingzone --#BRIGADE.SupplyZone
|
||||
-- Info text.
|
||||
text=text..string.format("\n* %s: Mission status=%s, suppliers=%d", rearmingzone.zone:GetName(), rearmingzone.mission:GetState(), rearmingzone.mission:CountOpsGroups())
|
||||
end
|
||||
self:I(self.lid..text)
|
||||
end
|
||||
|
||||
---------------------
|
||||
-- Refuelling Info --
|
||||
---------------------
|
||||
if self.verbose>=4 then
|
||||
local text="Refuelling Zones:"
|
||||
for i,_refuellingzone in pairs(self.refuellingZones) do
|
||||
local refuellingzone=_refuellingzone --#BRIGADE.SupplyZone
|
||||
-- Info text.
|
||||
text=text..string.format("\n* %s: Mission status=%s, suppliers=%d", refuellingzone.zone:GetName(), refuellingzone.mission:GetState(), refuellingzone.mission:CountOpsGroups())
|
||||
end
|
||||
self:I(self.lid..text)
|
||||
end
|
||||
|
||||
----------------
|
||||
-- Asset Info --
|
||||
----------------
|
||||
if self.verbose>=5 then
|
||||
local text="Assets in stock:"
|
||||
for i,_asset in pairs(self.stock) do
|
||||
local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem
|
||||
-- Info text.
|
||||
text=text..string.format("\n* %s: spawned=%s", asset.spawngroupname, tostring(asset.spawned))
|
||||
end
|
||||
self:I(self.lid..text)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- FSM Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- On after "ArmyOnMission".
|
||||
-- @param #BRIGADE self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Ops.ArmyGroup#ARMYGROUP ArmyGroup Ops army group on mission.
|
||||
-- @param Ops.Auftrag#AUFTRAG Mission The requested mission.
|
||||
function BRIGADE:onafterArmyOnMission(From, Event, To, ArmyGroup, Mission)
|
||||
-- Debug info.
|
||||
self:T(self.lid..string.format("Group %s on %s mission %s", ArmyGroup:GetName(), Mission:GetType(), Mission:GetName()))
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
@@ -31,7 +31,7 @@
|
||||
-- @image OPS_CSAR.jpg
|
||||
|
||||
---
|
||||
-- Last Update Jan 2025
|
||||
-- Last Update May 2025
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
--- **CSAR** class, extends Core.Base#BASE, Core.Fsm#FSM
|
||||
@@ -263,6 +263,7 @@ CSAR = {
|
||||
rescuedpilots = 0,
|
||||
limitmaxdownedpilots = true,
|
||||
maxdownedpilots = 10,
|
||||
useFIFOLimitReplacement = false, -- If true, it will remove the oldest downed pilot when a new one is added, if the limit is reached.
|
||||
allheligroupset = nil,
|
||||
topmenuname = "CSAR",
|
||||
ADFRadioPwr = 1000,
|
||||
@@ -313,7 +314,7 @@ CSAR.AircraftType["CH-47Fbl1"] = 31
|
||||
|
||||
--- CSAR class version.
|
||||
-- @field #string version
|
||||
CSAR.version="1.0.30"
|
||||
CSAR.version="1.0.33"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- ToDo list
|
||||
@@ -468,7 +469,7 @@ function CSAR:New(Coalition, Template, Alias)
|
||||
-- added 1.0.15
|
||||
self.allowbronco = false -- set to true to use the Bronco mod as a CSAR plane
|
||||
|
||||
self.ADFRadioPwr = 1000
|
||||
self.ADFRadioPwr = 500
|
||||
|
||||
-- added 1.0.16
|
||||
self.PilotWeight = 80
|
||||
@@ -1144,19 +1145,8 @@ function CSAR:_EventHandler(EventData)
|
||||
self:T("Double Ejection!")
|
||||
return self
|
||||
end
|
||||
|
||||
-- limit no of pilots in the field.
|
||||
if self.limitmaxdownedpilots and self:_ReachedPilotLimit() then
|
||||
self:T("Maxed Downed Pilot!")
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
-- TODO: Over water check --- EVENTS.LandingAfterEjection NOT triggered by DCS, so handle csarUsePara = true case
|
||||
-- might create dual pilots in edge cases
|
||||
|
||||
local wetfeet = false
|
||||
|
||||
|
||||
|
||||
local initdcscoord = nil
|
||||
local initcoord = nil
|
||||
if _event.id == EVENTS.Ejection then
|
||||
@@ -1168,6 +1158,36 @@ function CSAR:_EventHandler(EventData)
|
||||
initcoord = COORDINATE:NewFromVec3(initdcscoord)
|
||||
self:T({initdcscoord})
|
||||
end
|
||||
|
||||
-- Remove downed pilot if already exists to replace with new one.
|
||||
if _event.IniPlayerName then
|
||||
local PilotTable = self.downedPilots --#CSAR.DownedPilot
|
||||
local _foundPilot = nil
|
||||
for _,_pilot in pairs(PilotTable) do
|
||||
if _pilot.player == _event.IniPlayerName and _pilot.alive == true then
|
||||
_foundPilot = _pilot
|
||||
break
|
||||
end
|
||||
end
|
||||
if _foundPilot then
|
||||
self:T("Downed pilot already exists!")
|
||||
_foundPilot.group:Destroy(false)
|
||||
self:_RemoveNameFromDownedPilots(_foundPilot.name)
|
||||
self:_CheckDownedPilotTable()
|
||||
end
|
||||
end
|
||||
|
||||
-- limit no of pilots in the field.
|
||||
if self.limitmaxdownedpilots and self:_ReachedPilotLimit() then
|
||||
self:T("Maxed Downed Pilot!")
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
-- TODO: Over water check --- EVENTS.LandingAfterEjection NOT triggered by DCS, so handle csarUsePara = true case
|
||||
-- might create dual pilots in edge cases
|
||||
|
||||
local wetfeet = false
|
||||
|
||||
--local surface = _unit:GetCoordinate():GetSurfaceType()
|
||||
local surface = initcoord:GetSurfaceType()
|
||||
@@ -2116,56 +2136,50 @@ end
|
||||
--- (Internal) Determine distance to closest MASH.
|
||||
-- @param #CSAR self
|
||||
-- @param Wrapper.Unit#UNIT _heli Helicopter #UNIT
|
||||
-- @return #CSAR self
|
||||
-- @return #number Distance in meters
|
||||
-- @return #string MASH Name as string
|
||||
function CSAR:_GetClosestMASH(_heli)
|
||||
self:T(self.lid .. " _GetClosestMASH")
|
||||
local _mashset = self.mash -- Core.Set#SET_GROUP
|
||||
local _mashes = _mashset:GetSetObjects() -- #table
|
||||
local MashSets = {}
|
||||
--local _mashes = _mashset.Set-- #table
|
||||
table.insert(MashSets,_mashset.Set)
|
||||
table.insert(MashSets,self.zonemashes.Set)
|
||||
table.insert(MashSets,self.staticmashes.Set)
|
||||
local _shortestDistance = -1
|
||||
local _distance = 0
|
||||
local _helicoord = _heli:GetCoordinate()
|
||||
|
||||
local function GetCloseAirbase(coordinate,Coalition,Category)
|
||||
|
||||
local a=coordinate:GetVec3()
|
||||
local distmin=math.huge
|
||||
local airbase=nil
|
||||
for DCSairbaseID, DCSairbase in pairs(world.getAirbases(Coalition)) do
|
||||
local b=DCSairbase:getPoint()
|
||||
|
||||
local c=UTILS.VecSubstract(a,b)
|
||||
local dist=UTILS.VecNorm(c)
|
||||
|
||||
if dist<distmin and (Category==nil or Category==DCSairbase:getDesc().category) then
|
||||
distmin=dist
|
||||
airbase=DCSairbase
|
||||
end
|
||||
|
||||
end
|
||||
return distmin
|
||||
end
|
||||
local MashName = nil
|
||||
|
||||
if self.allowFARPRescue then
|
||||
local position = _heli:GetCoordinate()
|
||||
local afb,distance = position:GetClosestAirbase(nil,self.coalition)
|
||||
_shortestDistance = distance
|
||||
MashName = (afb ~= nil) and afb:GetName() or "Unknown"
|
||||
end
|
||||
|
||||
for _, _mashUnit in pairs(_mashes) do
|
||||
if _mashUnit and _mashUnit:IsAlive() then
|
||||
local _mashcoord = _mashUnit:GetCoordinate()
|
||||
_distance = self:_GetDistance(_helicoord, _mashcoord)
|
||||
if _distance ~= nil and (_shortestDistance == -1 or _distance < _shortestDistance) then
|
||||
_shortestDistance = _distance
|
||||
end
|
||||
end
|
||||
for _,_mashes in pairs(MashSets) do
|
||||
for _, _mashUnit in pairs(_mashes or {}) do
|
||||
local _mashcoord
|
||||
if _mashUnit and (not _mashUnit:IsInstanceOf("ZONE_BASE")) and _mashUnit:IsAlive() then
|
||||
_mashcoord = _mashUnit:GetCoordinate()
|
||||
elseif _mashUnit and _mashUnit:IsInstanceOf("ZONE_BASE") then
|
||||
_mashcoord = _mashUnit:GetCoordinate()
|
||||
end
|
||||
_distance = self:_GetDistance(_helicoord, _mashcoord)
|
||||
if _distance ~= nil and (_shortestDistance == -1 or _distance < _shortestDistance) then
|
||||
_shortestDistance = _distance
|
||||
MashName = _mashUnit:GetName() or "Unknown"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if _shortestDistance ~= -1 then
|
||||
return _shortestDistance
|
||||
return _shortestDistance, MashName
|
||||
else
|
||||
return -1
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- (Internal) Display onboarded rescued pilots.
|
||||
@@ -2323,9 +2337,9 @@ end
|
||||
-- @param #CSAR self
|
||||
-- @param Wrapper.Group#GROUP _group Group #GROUP object.
|
||||
-- @param #number _freq Frequency to use
|
||||
-- @param #string _name Beacon Name to use
|
||||
-- @param #string BeaconName Beacon Name to use
|
||||
-- @return #CSAR self
|
||||
function CSAR:_AddBeaconToGroup(_group, _freq, _name)
|
||||
function CSAR:_AddBeaconToGroup(_group, _freq, BeaconName)
|
||||
self:T(self.lid .. " _AddBeaconToGroup")
|
||||
if self.CreateRadioBeacons == false then return end
|
||||
local _group = _group
|
||||
@@ -2346,10 +2360,11 @@ function CSAR:_AddBeaconToGroup(_group, _freq, _name)
|
||||
if _radioUnit then
|
||||
local name = _radioUnit:GetName()
|
||||
local Frequency = _freq -- Freq in Hertz
|
||||
local name = _radioUnit:GetName()
|
||||
--local name = _radioUnit:GetName()
|
||||
local Sound = "l10n/DEFAULT/"..self.radioSound
|
||||
local vec3 = _radioUnit:GetVec3() or _radioUnit:GetPositionVec3() or {x=0,y=0,z=0}
|
||||
trigger.action.radioTransmission(Sound, vec3, 0, false, Frequency, self.ADFRadioPwr or 1000,_name) -- Beacon in MP only runs for exactly 30secs straight
|
||||
self:I(self.lid..string.format("Added Radio Beacon %d Hertz | Name %s | Position {%d,%d,%d}",Frequency,BeaconName,vec3.x,vec3.y,vec3.z))
|
||||
trigger.action.radioTransmission(Sound, vec3, 0, true, Frequency, self.ADFRadioPwr or 500,BeaconName) -- Beacon in MP only runs for exactly 30secs straight
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2370,9 +2385,13 @@ function CSAR:_RefreshRadioBeacons()
|
||||
local group = pilot.group
|
||||
local frequency = pilot.frequency or 0 -- thanks to @Thrud
|
||||
local bname = pilot.BeaconName or pilot.name..math.random(1,100000)
|
||||
trigger.action.stopRadioTransmission(bname)
|
||||
--trigger.action.stopRadioTransmission(bname)
|
||||
if group and group:IsAlive() and frequency > 0 then
|
||||
self:_AddBeaconToGroup(group,frequency,bname)
|
||||
--self:_AddBeaconToGroup(group,frequency,bname)
|
||||
else
|
||||
if frequency > 0 then
|
||||
trigger.action.stopRadioTransmission(bname)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -2402,11 +2421,26 @@ function CSAR:_ReachedPilotLimit()
|
||||
local limit = self.maxdownedpilots
|
||||
local islimited = self.limitmaxdownedpilots
|
||||
local count = self:_CountActiveDownedPilots()
|
||||
if islimited and (count >= limit) then
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
if islimited and (count >= limit) then
|
||||
if self.useFIFOLimitReplacement then
|
||||
local oldIndex = -1
|
||||
local oldDownedPilot = nil
|
||||
for _index, _downedpilot in pairs(self.downedPilots) do
|
||||
oldIndex = _index
|
||||
oldDownedPilot = _downedpilot
|
||||
break
|
||||
end
|
||||
if oldDownedPilot then
|
||||
oldDownedPilot.group:Destroy(false)
|
||||
oldDownedPilot.alive = false
|
||||
self:_CheckDownedPilotTable()
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
--- User - Function to add onw SET_GROUP Set-up for pilot filtering and assignment.
|
||||
@@ -2454,9 +2488,10 @@ function CSAR:onafterStart(From, Event, To)
|
||||
|
||||
self.mash = SET_GROUP:New():FilterCoalitions(self.coalitiontxt):FilterPrefixes(self.mashprefix):FilterStart()
|
||||
|
||||
local staticmashes = SET_STATIC:New():FilterCoalitions(self.coalitiontxt):FilterPrefixes(self.mashprefix):FilterOnce()
|
||||
local zonemashes = SET_ZONE:New():FilterPrefixes(self.mashprefix):FilterOnce()
|
||||
self.staticmashes = SET_STATIC:New():FilterCoalitions(self.coalitiontxt):FilterPrefixes(self.mashprefix):FilterStart()
|
||||
self.zonemashes = SET_ZONE:New():FilterPrefixes(self.mashprefix):FilterStart()
|
||||
|
||||
--[[
|
||||
if staticmashes:Count() > 0 then
|
||||
for _,_mash in pairs(staticmashes.Set) do
|
||||
self.mash:AddObject(_mash)
|
||||
@@ -2464,10 +2499,13 @@ function CSAR:onafterStart(From, Event, To)
|
||||
end
|
||||
|
||||
if zonemashes:Count() > 0 then
|
||||
self:T("Adding zones to self.mash SET")
|
||||
for _,_mash in pairs(zonemashes.Set) do
|
||||
self.mash:AddObject(_mash)
|
||||
end
|
||||
self:T("Objects in SET: "..self.mash:Count())
|
||||
end
|
||||
--]]
|
||||
|
||||
if not self.coordinate then
|
||||
local csarhq = self.mash:GetRandom()
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,428 +0,0 @@
|
||||
--- **Ops** - Fleet Warehouse.
|
||||
--
|
||||
-- **Main Features:**
|
||||
--
|
||||
-- * Manage flotillas
|
||||
-- * Carry out ARTY and PATROLZONE missions (AUFTRAG)
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ## Example Missions:
|
||||
--
|
||||
-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/Ops/Fleet).
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **funkyfranky**
|
||||
--
|
||||
-- ===
|
||||
-- @module Ops.Fleet
|
||||
-- @image OPS_Fleet.png
|
||||
|
||||
|
||||
--- FLEET class.
|
||||
-- @type FLEET
|
||||
-- @field #string ClassName Name of the class.
|
||||
-- @field #number verbose Verbosity of output.
|
||||
-- @field Core.Set#SET_ZONE retreatZones Retreat zone set.
|
||||
-- @field #boolean pathfinding Set pathfinding on for all spawned navy groups.
|
||||
-- @extends Ops.Legion#LEGION
|
||||
|
||||
--- *A fleet of British ships at war are the best negotiators.* -- Horatio Nelson
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- # The FLEET Concept
|
||||
--
|
||||
-- A FLEET 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 `FLEET` object can be created with the @{#FLEET.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=FLEET:New("myWarehouseName", "1st Fleet")
|
||||
-- myFleet:SetPortZone(ZonePort1stFleet)
|
||||
-- myFleet:Start()
|
||||
--
|
||||
-- A fleet needs a *port zone*, which is set via the @{#FLEET.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 @{#FLEET.Start}() function. If the fleet is not started, it will not process any requests.
|
||||
--
|
||||
-- ## Adding Flotillas
|
||||
--
|
||||
-- Flotillas can be added via the @{#FLEET.AddFlotilla}(`Flotilla`) function. See @{Ops.Flotilla#FLOTILLA} for how to create a flotilla.
|
||||
--
|
||||
-- myFleet:AddFlotilla(FlotillaTiconderoga)
|
||||
-- myFleet:AddFlotilla(FlotillaPerry)
|
||||
--
|
||||
--
|
||||
--
|
||||
-- @field #FLEET
|
||||
FLEET = {
|
||||
ClassName = "FLEET",
|
||||
verbose = 0,
|
||||
pathfinding = false,
|
||||
}
|
||||
|
||||
--- Supply Zone.
|
||||
-- @type FLEET.SupplyZone
|
||||
-- @field Core.Zone#ZONE zone The zone.
|
||||
-- @field Ops.Auftrag#AUFTRAG mission Mission assigned to supply ammo or fuel.
|
||||
-- @field #boolean markerOn If `true`, marker is on.
|
||||
-- @field Wrapper.Marker#MARKER marker F10 marker.
|
||||
|
||||
--- FLEET class version.
|
||||
-- @field #string version
|
||||
FLEET.version="0.0.1"
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- ToDo list
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- TODO: Add routes?
|
||||
-- DONE: Add weapon range.
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- Constructor
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Create a new FLEET class object.
|
||||
-- @param #FLEET self
|
||||
-- @param #string WarehouseName Name of the warehouse STATIC or UNIT object representing the warehouse.
|
||||
-- @param #string FleetName Name of the fleet.
|
||||
-- @return #FLEET self
|
||||
function FLEET:New(WarehouseName, FleetName)
|
||||
|
||||
-- Inherit everything from LEGION class.
|
||||
local self=BASE:Inherit(self, LEGION:New(WarehouseName, FleetName)) -- #FLEET
|
||||
|
||||
-- Nil check.
|
||||
if not self then
|
||||
BASE:E(string.format("ERROR: Could not find warehouse %s!", WarehouseName))
|
||||
return nil
|
||||
end
|
||||
|
||||
-- Set some string id for output to DCS.log file.
|
||||
self.lid=string.format("FLEET %s | ", self.alias)
|
||||
|
||||
-- Defaults
|
||||
self:SetRetreatZones()
|
||||
|
||||
-- Turn ship into NAVYGROUP.
|
||||
if self:IsShip() then
|
||||
local wh=self.warehouse --Wrapper.Unit#UNIT
|
||||
local group=wh:GetGroup()
|
||||
self.warehouseOpsGroup=NAVYGROUP:New(group) --Ops.NavyGroup#NAVYGROUP
|
||||
self.warehouseOpsElement=self.warehouseOpsGroup:GetElementByName(wh:GetName())
|
||||
end
|
||||
|
||||
|
||||
-- Add FSM transitions.
|
||||
-- From State --> Event --> To State
|
||||
self:AddTransition("*", "NavyOnMission", "*") -- An NAVYGROUP was send on a Mission (AUFTRAG).
|
||||
|
||||
------------------------
|
||||
--- Pseudo Functions ---
|
||||
------------------------
|
||||
|
||||
--- Triggers the FSM event "Start". Starts the FLEET. Initializes parameters and starts event handlers.
|
||||
-- @function [parent=#FLEET] Start
|
||||
-- @param #FLEET self
|
||||
|
||||
--- Triggers the FSM event "Start" after a delay. Starts the FLEET. Initializes parameters and starts event handlers.
|
||||
-- @function [parent=#FLEET] __Start
|
||||
-- @param #FLEET self
|
||||
-- @param #number delay Delay in seconds.
|
||||
|
||||
|
||||
--- Triggers the FSM event "Stop". Stops the FLEET and all its event handlers.
|
||||
-- @param #FLEET self
|
||||
|
||||
--- Triggers the FSM event "Stop" after a delay. Stops the FLEET and all its event handlers.
|
||||
-- @function [parent=#FLEET] __Stop
|
||||
-- @param #FLEET self
|
||||
-- @param #number delay Delay in seconds.
|
||||
|
||||
|
||||
--- Triggers the FSM event "NavyOnMission".
|
||||
-- @function [parent=#FLEET] NavyOnMission
|
||||
-- @param #FLEET self
|
||||
-- @param Ops.NavyGroup#NAVYGROUP ArmyGroup The NAVYGROUP on mission.
|
||||
-- @param Ops.Auftrag#AUFTRAG Mission The mission.
|
||||
|
||||
--- Triggers the FSM event "NavyOnMission" after a delay.
|
||||
-- @function [parent=#FLEET] __NavyOnMission
|
||||
-- @param #FLEET self
|
||||
-- @param #number delay Delay in seconds.
|
||||
-- @param Ops.NavyGroup#NAVYGROUP ArmyGroup The NAVYGROUP on mission.
|
||||
-- @param Ops.Auftrag#AUFTRAG Mission The mission.
|
||||
|
||||
--- On after "NavyOnMission" event.
|
||||
-- @function [parent=#FLEET] OnAfterNavyOnMission
|
||||
-- @param #FLEET self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Ops.NavyGroup#NAVYGROUP NavyGroup The NAVYGROUP on mission.
|
||||
-- @param Ops.Auftrag#AUFTRAG Mission The mission.
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- User Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Add a flotilla to the fleet.
|
||||
-- @param #FLEET self
|
||||
-- @param Ops.Flotilla#FLOTILLA Flotilla The flotilla object.
|
||||
-- @return #FLEET self
|
||||
function FLEET:AddFlotilla(Flotilla)
|
||||
|
||||
-- Add flotilla to fleet.
|
||||
table.insert(self.cohorts, Flotilla)
|
||||
|
||||
-- Add assets to flotilla.
|
||||
self:AddAssetToFlotilla(Flotilla, Flotilla.Ngroups)
|
||||
|
||||
-- Set fleet of flotilla.
|
||||
Flotilla:SetFleet(self)
|
||||
|
||||
-- Start flotilla.
|
||||
if Flotilla:IsStopped() then
|
||||
Flotilla:Start()
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Add asset group(s) to flotilla.
|
||||
-- @param #FLEET self
|
||||
-- @param Ops.Flotilla#FLOTILLA Flotilla The flotilla object.
|
||||
-- @param #number Nassets Number of asset groups to add.
|
||||
-- @return #FLEET self
|
||||
function FLEET:AddAssetToFlotilla(Flotilla, Nassets)
|
||||
|
||||
if Flotilla then
|
||||
|
||||
-- Get the template group of the flotilla.
|
||||
local Group=GROUP:FindByName(Flotilla.templatename)
|
||||
|
||||
if Group then
|
||||
|
||||
-- Debug text.
|
||||
local text=string.format("Adding asset %s to flotilla %s", Group:GetName(), Flotilla.name)
|
||||
self:T(self.lid..text)
|
||||
|
||||
-- Add assets to airwing warehouse.
|
||||
self:AddAsset(Group, Nassets, nil, nil, nil, nil, Flotilla.skill, Flotilla.livery, Flotilla.name)
|
||||
|
||||
else
|
||||
self:E(self.lid.."ERROR: Group does not exist!")
|
||||
end
|
||||
|
||||
else
|
||||
self:E(self.lid.."ERROR: Flotilla does not exit!")
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set pathfinding for all spawned naval groups.
|
||||
-- @param #FLEET self
|
||||
-- @param #boolean Switch If `true`, pathfinding is used.
|
||||
-- @return #FLEET self
|
||||
function FLEET:SetPathfinding(Switch)
|
||||
self.pathfinding=Switch
|
||||
return self
|
||||
end
|
||||
|
||||
--- Define a set of retreat zones.
|
||||
-- @param #FLEET self
|
||||
-- @param Core.Set#SET_ZONE RetreatZoneSet Set of retreat zones.
|
||||
-- @return #FLEET self
|
||||
function FLEET:SetRetreatZones(RetreatZoneSet)
|
||||
self.retreatZones=RetreatZoneSet or SET_ZONE:New()
|
||||
return self
|
||||
end
|
||||
|
||||
--- Add a retreat zone.
|
||||
-- @param #FLEET self
|
||||
-- @param Core.Zone#ZONE RetreatZone Retreat zone.
|
||||
-- @return #FLEET self
|
||||
function FLEET:AddRetreatZone(RetreatZone)
|
||||
self.retreatZones:AddZone(RetreatZone)
|
||||
return self
|
||||
end
|
||||
|
||||
--- Get retreat zones.
|
||||
-- @param #FLEET self
|
||||
-- @return Core.Set#SET_ZONE Set of retreat zones.
|
||||
function FLEET:GetRetreatZones()
|
||||
return self.retreatZones
|
||||
end
|
||||
|
||||
--- Get flotilla by name.
|
||||
-- @param #FLEET self
|
||||
-- @param #string FlotillaName Name of the flotilla.
|
||||
-- @return Ops.Flotilla#FLOTILLA The Flotilla object.
|
||||
function FLEET:GetFlotilla(FlotillaName)
|
||||
local flotilla=self:_GetCohort(FlotillaName)
|
||||
return flotilla
|
||||
end
|
||||
|
||||
--- Get flotilla of an asset.
|
||||
-- @param #FLEET self
|
||||
-- @param Functional.Warehouse#WAREHOUSE.Assetitem Asset The flotilla asset.
|
||||
-- @return Ops.Flotilla#FLOTILLA The flotilla object.
|
||||
function FLEET:GetFlotillaOfAsset(Asset)
|
||||
local flotilla=self:GetFlotilla(Asset.squadname)
|
||||
return flotilla
|
||||
end
|
||||
|
||||
--- Remove asset from flotilla.
|
||||
-- @param #FLEET self
|
||||
-- @param Functional.Warehouse#WAREHOUSE.Assetitem Asset The flotilla asset.
|
||||
function FLEET:RemoveAssetFromFlotilla(Asset)
|
||||
local flotilla=self:GetFlotillaOfAsset(Asset)
|
||||
if flotilla then
|
||||
flotilla:DelAsset(Asset)
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- FSM Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- Start FLEET FSM.
|
||||
-- @param #FLEET self
|
||||
function FLEET:onafterStart(From, Event, To)
|
||||
|
||||
-- Start parent Warehouse.
|
||||
self:GetParent(self, FLEET).onafterStart(self, From, Event, To)
|
||||
|
||||
-- Info.
|
||||
self:I(self.lid..string.format("Starting FLEET v%s", FLEET.version))
|
||||
|
||||
end
|
||||
|
||||
--- Update status.
|
||||
-- @param #FLEET self
|
||||
function FLEET:onafterStatus(From, Event, To)
|
||||
|
||||
-- Status of parent Warehouse.
|
||||
self:GetParent(self).onafterStatus(self, From, Event, To)
|
||||
|
||||
-- FSM state.
|
||||
local fsmstate=self:GetState()
|
||||
|
||||
----------------
|
||||
-- Transport ---
|
||||
----------------
|
||||
|
||||
self:CheckTransportQueue()
|
||||
|
||||
--------------
|
||||
-- Mission ---
|
||||
--------------
|
||||
|
||||
-- Check if any missions should be cancelled.
|
||||
self:CheckMissionQueue()
|
||||
|
||||
-----------
|
||||
-- Info ---
|
||||
-----------
|
||||
|
||||
-- Display tactival overview.
|
||||
self:_TacticalOverview()
|
||||
|
||||
-- General info:
|
||||
if self.verbose>=1 then
|
||||
|
||||
-- Count missions not over yet.
|
||||
local Nmissions=self:CountMissionsInQueue()
|
||||
|
||||
-- Asset count.
|
||||
local Npq, Np, Nq=self:CountAssetsOnMission()
|
||||
|
||||
-- Asset string.
|
||||
local assets=string.format("%d [OnMission: Total=%d, Active=%d, Queued=%d]", self:CountAssets(), Npq, Np, Nq)
|
||||
|
||||
-- Output.
|
||||
local text=string.format("%s: Missions=%d, Flotillas=%d, Assets=%s", fsmstate, Nmissions, #self.cohorts, assets)
|
||||
self:I(self.lid..text)
|
||||
end
|
||||
|
||||
------------------
|
||||
-- Mission Info --
|
||||
------------------
|
||||
if self.verbose>=2 then
|
||||
local text=string.format("Missions Total=%d:", #self.missionqueue)
|
||||
for i,_mission in pairs(self.missionqueue) do
|
||||
local mission=_mission --Ops.Auftrag#AUFTRAG
|
||||
|
||||
local prio=string.format("%d/%s", mission.prio, tostring(mission.importance)) ; if mission.urgent then prio=prio.." (!)" end
|
||||
local assets=string.format("%d/%d", mission:CountOpsGroups(), mission.Nassets or 0)
|
||||
local target=string.format("%d/%d Damage=%.1f", mission:CountMissionTargets(), mission:GetTargetInitialNumber(), mission:GetTargetDamage())
|
||||
|
||||
text=text..string.format("\n[%d] %s %s: Status=%s, Prio=%s, Assets=%s, Targets=%s", i, mission.name, mission.type, mission.status, prio, assets, target)
|
||||
end
|
||||
self:I(self.lid..text)
|
||||
end
|
||||
|
||||
--------------------
|
||||
-- Transport Info --
|
||||
--------------------
|
||||
if self.verbose>=2 then
|
||||
local text=string.format("Transports Total=%d:", #self.transportqueue)
|
||||
for i,_transport in pairs(self.transportqueue) do
|
||||
local transport=_transport --Ops.OpsTransport#OPSTRANSPORT
|
||||
|
||||
local prio=string.format("%d/%s", transport.prio, tostring(transport.importance)) ; if transport.urgent then prio=prio.." (!)" end
|
||||
local carriers=string.format("Ncargo=%d/%d, Ncarriers=%d", transport.Ncargo, transport.Ndelivered, transport.Ncarrier)
|
||||
|
||||
text=text..string.format("\n[%d] UID=%d: Status=%s, Prio=%s, Cargo: %s", i, transport.uid, transport:GetState(), prio, carriers)
|
||||
end
|
||||
self:I(self.lid..text)
|
||||
end
|
||||
|
||||
-------------------
|
||||
-- Flotilla Info --
|
||||
-------------------
|
||||
if self.verbose>=3 then
|
||||
local text="Flotillas:"
|
||||
for i,_flotilla in pairs(self.cohorts) do
|
||||
local flotilla=_flotilla --Ops.Flotilla#FLOTILLA
|
||||
|
||||
local callsign=flotilla.callsignName and UTILS.GetCallsignName(flotilla.callsignName) or "N/A"
|
||||
local modex=flotilla.modex and flotilla.modex or -1
|
||||
local skill=flotilla.skill and tostring(flotilla.skill) or "N/A"
|
||||
|
||||
-- Flotilla text.
|
||||
text=text..string.format("\n* %s %s: %s*%d/%d, Callsign=%s, Modex=%d, Skill=%s", flotilla.name, flotilla:GetState(), flotilla.aircrafttype, flotilla:CountAssets(true), #flotilla.assets, callsign, modex, skill)
|
||||
end
|
||||
self:I(self.lid..text)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- FSM Functions
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
--- On after "NavyOnMission".
|
||||
-- @param #FLEET self
|
||||
-- @param #string From From state.
|
||||
-- @param #string Event Event.
|
||||
-- @param #string To To state.
|
||||
-- @param Ops.ArmyGroup#ARMYGROUP ArmyGroup Ops army group on mission.
|
||||
-- @param Ops.Auftrag#AUFTRAG Mission The requested mission.
|
||||
function FLEET:onafterNavyOnMission(From, Event, To, NavyGroup, Mission)
|
||||
-- Debug info.
|
||||
self:T(self.lid..string.format("Group %s on %s mission %s", NavyGroup:GetName(), Mission:GetType(), Mission:GetName()))
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user