mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2026-08-17 12:50:22 +00:00
Merge branch 'develop' into FF/OpsDev
This commit is contained in:
@@ -5,6 +5,8 @@ on:
|
|||||||
branches:
|
branches:
|
||||||
- master
|
- master
|
||||||
- develop
|
- develop
|
||||||
|
- Apple/Develop
|
||||||
|
|
||||||
paths:
|
paths:
|
||||||
- 'Moose Setup/**/*.lua'
|
- 'Moose Setup/**/*.lua'
|
||||||
- 'Moose Development/**/*.lua'
|
- 'Moose Development/**/*.lua'
|
||||||
|
|||||||
+12
-2
@@ -1,7 +1,17 @@
|
|||||||
{
|
{
|
||||||
"Lua.workspace.preloadFileSize": 1000,
|
"Lua.workspace.preloadFileSize": 10000,
|
||||||
"Lua.diagnostics.disable": [
|
"Lua.diagnostics.disable": [
|
||||||
"undefined-doc-name"
|
"undefined-doc-name",
|
||||||
|
"duplicate-set-field",
|
||||||
|
"trailing-space",
|
||||||
|
"need-check-nil",
|
||||||
|
"ambiguity-1",
|
||||||
|
"undefined-doc-param",
|
||||||
|
"redundant-parameter",
|
||||||
|
"param-type-mismatch",
|
||||||
|
"deprecated",
|
||||||
|
"undefined-global",
|
||||||
|
"lowercase-global"
|
||||||
],
|
],
|
||||||
"Lua.diagnostics.globals": [
|
"Lua.diagnostics.globals": [
|
||||||
"BASE",
|
"BASE",
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
-- @module AI.AI_A2A_Cap
|
-- @module AI.AI_A2A_Cap
|
||||||
-- @image AI_Combat_Air_Patrol.JPG
|
-- @image AI_Combat_Air_Patrol.JPG
|
||||||
|
|
||||||
--- @type AI_A2A_CAP
|
-- @type AI_A2A_CAP
|
||||||
-- @extends AI.AI_Air_Patrol#AI_AIR_PATROL
|
-- @extends AI.AI_Air_Patrol#AI_AIR_PATROL
|
||||||
-- @extends AI.AI_Air_Engage#AI_AIR_ENGAGE
|
-- @extends AI.AI_Air_Engage#AI_AIR_ENGAGE
|
||||||
|
|
||||||
|
|||||||
@@ -13,8 +13,8 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
--- @type AI_A2A_GCI
|
-- @type AI_A2A_GCI
|
||||||
-- @extends AI.AI_Air_Engage#AI_AIR_ENGAGE
|
-- @extends AI.AI_A2A#AI_A2A
|
||||||
|
|
||||||
|
|
||||||
--- Implements the core functions to intercept intruders. Use the Engage trigger to intercept intruders.
|
--- Implements the core functions to intercept intruders. Use the Engage trigger to intercept intruders.
|
||||||
@@ -39,6 +39,8 @@
|
|||||||
--
|
--
|
||||||
-- ## 2. AI_A2A_GCI is a FSM
|
-- ## 2. AI_A2A_GCI is a FSM
|
||||||
--
|
--
|
||||||
|
-- 
|
||||||
|
--
|
||||||
-- ### 2.1 AI_A2A_GCI States
|
-- ### 2.1 AI_A2A_GCI States
|
||||||
--
|
--
|
||||||
-- * **None** ( Group ): The process is not started yet.
|
-- * **None** ( Group ): The process is not started yet.
|
||||||
|
|||||||
@@ -10,8 +10,8 @@
|
|||||||
-- @image AI_Air_Patrolling.JPG
|
-- @image AI_Air_Patrolling.JPG
|
||||||
|
|
||||||
|
|
||||||
--- @type AI_A2A_PATROL
|
-- @type AI_A2A_PATROL
|
||||||
-- @extends AI.AI_Air_Patrol#AI_AIR_PATROL
|
-- @extends AI.AI_A2A#AI_A2A
|
||||||
|
|
||||||
--- Implements the core functions to patrol a @{Core.Zone} by an AI @{Wrapper.Group} or @{Wrapper.Group}.
|
--- Implements the core functions to patrol a @{Core.Zone} by an AI @{Wrapper.Group} or @{Wrapper.Group}.
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -11,9 +11,8 @@
|
|||||||
-- @module AI.AI_A2G_BAI
|
-- @module AI.AI_A2G_BAI
|
||||||
-- @image AI_Air_To_Ground_Engage.JPG
|
-- @image AI_Air_To_Ground_Engage.JPG
|
||||||
|
|
||||||
--- @type AI_A2G_BAI
|
-- @type AI_A2G_BAI
|
||||||
-- @extends AI.AI_Air_Patrol#AI_AIR_PATROL
|
-- @extends AI.AI_A2A_Engage#AI_A2A_Engage -- TODO: Documentation. This class does not exist, unable to determine what it extends.
|
||||||
-- @extends AI.AI_Air_Engage#AI_AIR_ENGAGE
|
|
||||||
|
|
||||||
--- Implements the core functions to intercept intruders. Use the Engage trigger to intercept intruders.
|
--- Implements the core functions to intercept intruders. Use the Engage trigger to intercept intruders.
|
||||||
--
|
--
|
||||||
@@ -47,7 +46,7 @@ AI_A2G_BAI = {
|
|||||||
function AI_A2G_BAI:New2( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType )
|
function AI_A2G_BAI:New2( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType )
|
||||||
|
|
||||||
local AI_Air = AI_AIR:New( AIGroup )
|
local AI_Air = AI_AIR:New( AIGroup )
|
||||||
local AI_Air_Patrol = AI_AIR_PATROL:New( AI_Air, AIGroup, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType )
|
local AI_Air_Patrol = AI_AIR_PATROL:New( AI_Air, AIGroup, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType ) -- #AI_AIR_PATROL
|
||||||
local AI_Air_Engage = AI_AIR_ENGAGE:New( AI_Air_Patrol, AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType )
|
local AI_Air_Engage = AI_AIR_ENGAGE:New( AI_Air_Patrol, AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType )
|
||||||
local self = BASE:Inherit( self, AI_Air_Engage )
|
local self = BASE:Inherit( self, AI_Air_Engage )
|
||||||
|
|
||||||
|
|||||||
@@ -11,9 +11,8 @@
|
|||||||
-- @module AI.AI_A2G_CAS
|
-- @module AI.AI_A2G_CAS
|
||||||
-- @image AI_Air_To_Ground_Engage.JPG
|
-- @image AI_Air_To_Ground_Engage.JPG
|
||||||
|
|
||||||
--- @type AI_A2G_CAS
|
-- @type AI_A2G_CAS
|
||||||
-- @extends AI.AI_Air_Patrol#AI_AIR_PATROL
|
-- @extends AI.AI_A2G_Patrol#AI_AIR_PATROL TODO: Documentation. This class does not exist, unable to determine what it extends.
|
||||||
-- @extends AI.AI_Air_Engage#AI_AIR_ENGAGE
|
|
||||||
|
|
||||||
--- Implements the core functions to intercept intruders. Use the Engage trigger to intercept intruders.
|
--- Implements the core functions to intercept intruders. Use the Engage trigger to intercept intruders.
|
||||||
--
|
--
|
||||||
@@ -47,7 +46,7 @@ AI_A2G_CAS = {
|
|||||||
function AI_A2G_CAS:New2( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType )
|
function AI_A2G_CAS:New2( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType )
|
||||||
|
|
||||||
local AI_Air = AI_AIR:New( AIGroup )
|
local AI_Air = AI_AIR:New( AIGroup )
|
||||||
local AI_Air_Patrol = AI_AIR_PATROL:New( AI_Air, AIGroup, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType )
|
local AI_Air_Patrol = AI_AIR_PATROL:New( AI_Air, AIGroup, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType ) -- #AI_AIR_PATROL
|
||||||
local AI_Air_Engage = AI_AIR_ENGAGE:New( AI_Air_Patrol, AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType )
|
local AI_Air_Engage = AI_AIR_ENGAGE:New( AI_Air_Patrol, AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType )
|
||||||
local self = BASE:Inherit( self, AI_Air_Engage )
|
local self = BASE:Inherit( self, AI_Air_Engage )
|
||||||
|
|
||||||
|
|||||||
@@ -3895,10 +3895,14 @@ do -- AI_A2G_DISPATCHER
|
|||||||
|
|
||||||
if Squadron then
|
if Squadron then
|
||||||
local FirstUnit = AttackSetUnit:GetRandomSurely()
|
local FirstUnit = AttackSetUnit:GetRandomSurely()
|
||||||
|
if FirstUnit then
|
||||||
local Coordinate = FirstUnit:GetCoordinate() -- Core.Point#COORDINATE
|
local Coordinate = FirstUnit:GetCoordinate() -- Core.Point#COORDINATE
|
||||||
if self.SetSendPlayerMessages then
|
if self.SetSendPlayerMessages then
|
||||||
Dispatcher:MessageToPlayers( Squadron, DefenderName .. ", on route to ground target at " .. Coordinate:ToStringA2G( DefenderGroup ), DefenderGroup )
|
Dispatcher:MessageToPlayers( Squadron, DefenderName .. ", on route to ground target at " .. Coordinate:ToStringA2G( DefenderGroup ), DefenderGroup )
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
return
|
||||||
|
end
|
||||||
end
|
end
|
||||||
self:GetParent(self).onafterEngageRoute( self, DefenderGroup, From, Event, To, AttackSetUnit )
|
self:GetParent(self).onafterEngageRoute( self, DefenderGroup, From, Event, To, AttackSetUnit )
|
||||||
end
|
end
|
||||||
@@ -4784,4 +4788,5 @@ end
|
|||||||
Squadron.ResourceCount = Squadron.ResourceCount - Amount
|
Squadron.ResourceCount = Squadron.ResourceCount - Amount
|
||||||
end
|
end
|
||||||
self:T({Squadron = Squadron.Name,SquadronResourceCount = Squadron.ResourceCount})
|
self:T({Squadron = Squadron.Name,SquadronResourceCount = Squadron.ResourceCount})
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -13,9 +13,8 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
--- @type AI_A2G_SEAD
|
-- @type AI_A2G_SEAD
|
||||||
-- @extends AI.AI_Air_Patrol#AI_AIR_PATROL
|
-- @extends AI.AI_A2G_Patrol#AI_AIR_PATROL
|
||||||
-- @extends AI.AI_Air_Engage#AI_AIR_ENGAGE
|
|
||||||
|
|
||||||
|
|
||||||
--- Implements the core functions to SEAD intruders. Use the Engage trigger to intercept intruders.
|
--- Implements the core functions to SEAD intruders. Use the Engage trigger to intercept intruders.
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
-- @module AI.AI_Air
|
-- @module AI.AI_Air
|
||||||
-- @image MOOSE.JPG
|
-- @image MOOSE.JPG
|
||||||
|
|
||||||
|
---
|
||||||
-- @type AI_AIR
|
-- @type AI_AIR
|
||||||
-- @extends Core.Fsm#FSM_CONTROLLABLE
|
-- @extends Core.Fsm#FSM_CONTROLLABLE
|
||||||
|
|
||||||
@@ -656,8 +657,8 @@ function AI_AIR:onafterRTB( AIGroup, From, Event, To )
|
|||||||
--- Create a route point of type air.
|
--- Create a route point of type air.
|
||||||
local FromRTBRoutePoint = FromCoord:WaypointAir(
|
local FromRTBRoutePoint = FromCoord:WaypointAir(
|
||||||
self.PatrolAltType,
|
self.PatrolAltType,
|
||||||
POINT_VEC3.RoutePointType.TurningPoint,
|
COORDINATE.WaypointType.TurningPoint,
|
||||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
COORDINATE.WaypointAction.TurningPoint,
|
||||||
RTBSpeed,
|
RTBSpeed,
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
@@ -665,8 +666,8 @@ function AI_AIR:onafterRTB( AIGroup, From, Event, To )
|
|||||||
--- Create a route point of type air.
|
--- Create a route point of type air.
|
||||||
local ToRTBRoutePoint = ToAirbaseCoord:WaypointAir(
|
local ToRTBRoutePoint = ToAirbaseCoord:WaypointAir(
|
||||||
self.PatrolAltType,
|
self.PatrolAltType,
|
||||||
POINT_VEC3.RoutePointType.TurningPoint,
|
COORDINATE.WaypointType.TurningPoint,
|
||||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
COORDINATE.WaypointAction.TurningPoint,
|
||||||
RTBSpeed,
|
RTBSpeed,
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
@@ -760,10 +761,10 @@ function AI_AIR:onafterRefuel( AIGroup, From, Event, To )
|
|||||||
local ToRefuelSpeed = math.random( self.PatrolMinSpeed, self.PatrolMaxSpeed )
|
local ToRefuelSpeed = math.random( self.PatrolMinSpeed, self.PatrolMaxSpeed )
|
||||||
|
|
||||||
--- Create a route point of type air.
|
--- 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!
|
--- 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 } )
|
self:F( { ToRefuelSpeed = ToRefuelSpeed } )
|
||||||
|
|
||||||
|
|||||||
@@ -453,7 +453,7 @@ function AI_AIR_ENGAGE:onafterEngageRoute( DefenderGroup, From, Event, To, Attac
|
|||||||
|
|
||||||
--- Calculate the target route point.
|
--- 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
|
EngageRoute[#EngageRoute+1] = FromWP
|
||||||
|
|
||||||
@@ -462,7 +462,7 @@ function AI_AIR_ENGAGE:onafterEngageRoute( DefenderGroup, From, Event, To, Attac
|
|||||||
local FromEngageAngle = DefenderCoord:GetAngleDegrees( DefenderCoord:GetDirectionVec3( TargetCoord ) )
|
local FromEngageAngle = DefenderCoord:GetAngleDegrees( DefenderCoord:GetDirectionVec3( TargetCoord ) )
|
||||||
local ToCoord=DefenderCoord:Translate( EngageDistance, FromEngageAngle, true )
|
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
|
EngageRoute[#EngageRoute+1] = ToWP
|
||||||
|
|
||||||
@@ -536,7 +536,7 @@ function AI_AIR_ENGAGE:onafterEngage( DefenderGroup, From, Event, To, AttackSetU
|
|||||||
local EngageRoute = {}
|
local EngageRoute = {}
|
||||||
local AttackTasks = {}
|
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
|
EngageRoute[#EngageRoute+1] = FromWP
|
||||||
|
|
||||||
self:SetTargetDistance( TargetCoord ) -- For RTB status check
|
self:SetTargetDistance( TargetCoord ) -- For RTB status check
|
||||||
@@ -544,7 +544,7 @@ function AI_AIR_ENGAGE:onafterEngage( DefenderGroup, From, Event, To, AttackSetU
|
|||||||
local FromEngageAngle = DefenderCoord:GetAngleDegrees( DefenderCoord:GetDirectionVec3( TargetCoord ) )
|
local FromEngageAngle = DefenderCoord:GetAngleDegrees( DefenderCoord:GetDirectionVec3( TargetCoord ) )
|
||||||
local ToCoord=DefenderCoord:Translate( EngageDistance, FromEngageAngle, true )
|
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
|
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!
|
-- 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,7 +9,7 @@
|
|||||||
-- @module AI.AI_Air_Patrol
|
-- @module AI.AI_Air_Patrol
|
||||||
-- @image AI_Air_To_Ground_Patrol.JPG
|
-- @image AI_Air_To_Ground_Patrol.JPG
|
||||||
|
|
||||||
--- @type AI_AIR_PATROL
|
-- @type AI_AIR_PATROL
|
||||||
-- @extends AI.AI_Air#AI_AIR
|
-- @extends AI.AI_Air#AI_AIR
|
||||||
|
|
||||||
--- The AI_AIR_PATROL class implements the core functions to patrol a @{Core.Zone} by an AI @{Wrapper.Group}
|
--- The AI_AIR_PATROL class implements the core functions to patrol a @{Core.Zone} by an AI @{Wrapper.Group}
|
||||||
@@ -309,7 +309,7 @@ function AI_AIR_PATROL:onafterPatrolRoute( AIPatrol, From, Event, To )
|
|||||||
local ToTargetSpeed = math.random( self.PatrolMinSpeed, self.PatrolMaxSpeed )
|
local ToTargetSpeed = math.random( self.PatrolMinSpeed, self.PatrolMaxSpeed )
|
||||||
local speedkmh=ToTargetSpeed
|
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
|
PatrolRoute[#PatrolRoute+1] = FromWP
|
||||||
|
|
||||||
if self.racetrack then
|
if self.racetrack then
|
||||||
@@ -359,9 +359,9 @@ function AI_AIR_PATROL:onafterPatrolRoute( AIPatrol, From, Event, To )
|
|||||||
else
|
else
|
||||||
|
|
||||||
--- Create a route point of type air.
|
--- 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
|
PatrolRoute[#PatrolRoute+1] = ToWP
|
||||||
|
|
||||||
local Tasks = {}
|
local Tasks = {}
|
||||||
Tasks[#Tasks+1] = AIPatrol:TaskFunction("AI_AIR_PATROL.___PatrolRoute", self)
|
Tasks[#Tasks+1] = AIPatrol:TaskFunction("AI_AIR_PATROL.___PatrolRoute", self)
|
||||||
PatrolRoute[#PatrolRoute].task = AIPatrol:TaskCombo( Tasks )
|
PatrolRoute[#PatrolRoute].task = AIPatrol:TaskCombo( Tasks )
|
||||||
|
|||||||
@@ -174,8 +174,7 @@ function AI_BAI_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude
|
|||||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||||
-- @param #string From The From State string.
|
-- @param #string From The From State string.
|
||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
-- @param #string To The To State string.
|
-- @param #string To The To State string.
|
||||||
|
|
||||||
-- @return #boolean Return false to cancel Transition.
|
-- @return #boolean Return false to cancel Transition.
|
||||||
|
|
||||||
--- OnAfter Transition Handler for Event Engage.
|
--- OnAfter Transition Handler for Event Engage.
|
||||||
@@ -408,7 +407,7 @@ function AI_BAI_ZONE:onafterStart( Controllable, From, Event, To )
|
|||||||
self:SetDetectionDeactivated() -- When not engaging, set the detection off.
|
self:SetDetectionDeactivated() -- When not engaging, set the detection off.
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param Wrapper.Controllable#CONTROLLABLE AIControllable
|
-- @param Wrapper.Controllable#CONTROLLABLE AIControllable
|
||||||
function _NewEngageRoute( AIControllable )
|
function _NewEngageRoute( AIControllable )
|
||||||
|
|
||||||
AIControllable:T( "NewEngageRoute" )
|
AIControllable:T( "NewEngageRoute" )
|
||||||
@@ -417,7 +416,7 @@ function _NewEngageRoute( AIControllable )
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- @param #AI_BAI_ZONE self
|
-- @param #AI_BAI_ZONE self
|
||||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||||
-- @param #string From The From State string.
|
-- @param #string From The From State string.
|
||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
@@ -429,7 +428,7 @@ function AI_BAI_ZONE:onbeforeEngage( Controllable, From, Event, To )
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #AI_BAI_ZONE self
|
-- @param #AI_BAI_ZONE self
|
||||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||||
-- @param #string From The From State string.
|
-- @param #string From The From State string.
|
||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
@@ -478,7 +477,7 @@ function AI_BAI_ZONE:onafterTarget( Controllable, From, Event, To )
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- @param #AI_BAI_ZONE self
|
-- @param #AI_BAI_ZONE self
|
||||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||||
-- @param #string From The From State string.
|
-- @param #string From The From State string.
|
||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
@@ -488,7 +487,7 @@ function AI_BAI_ZONE:onafterAbort( Controllable, From, Event, To )
|
|||||||
self:__Route( 1 )
|
self:__Route( 1 )
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #AI_BAI_ZONE self
|
-- @param #AI_BAI_ZONE self
|
||||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||||
-- @param #string From The From State string.
|
-- @param #string From The From State string.
|
||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
@@ -522,12 +521,12 @@ function AI_BAI_ZONE:onafterEngage( Controllable, From, Event, To,
|
|||||||
|
|
||||||
--DONE: Create GetAltitude function for GROUP, and delete GetUnit(1).
|
--DONE: Create GetAltitude function for GROUP, and delete GetUnit(1).
|
||||||
local CurrentAltitude = self.Controllable: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 ToEngageZoneSpeed = self.PatrolMaxSpeed
|
local ToEngageZoneSpeed = self.PatrolMaxSpeed
|
||||||
local CurrentRoutePoint = CurrentPointVec3:WaypointAir(
|
local CurrentRoutePoint = CurrentPointVec3:WaypointAir(
|
||||||
self.PatrolAltType,
|
self.PatrolAltType,
|
||||||
POINT_VEC3.RoutePointType.TurningPoint,
|
COORDINATE.WaypointType.TurningPoint,
|
||||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
COORDINATE.WaypointAction.TurningPoint,
|
||||||
self.EngageSpeed,
|
self.EngageSpeed,
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
@@ -578,13 +577,13 @@ function AI_BAI_ZONE:onafterEngage( Controllable, From, Event, To,
|
|||||||
self:T2( ToTargetVec2 )
|
self:T2( ToTargetVec2 )
|
||||||
|
|
||||||
--- Obtain a 3D @{Point} from the 2D point + altitude.
|
--- 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.
|
--- Create a route point of type air.
|
||||||
local ToTargetRoutePoint = ToTargetPointVec3:WaypointAir(
|
local ToTargetRoutePoint = ToTargetPointVec3:WaypointAir(
|
||||||
self.PatrolAltType,
|
self.PatrolAltType,
|
||||||
POINT_VEC3.RoutePointType.TurningPoint,
|
COORDINATE.WaypointType.TurningPoint,
|
||||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
COORDINATE.WaypointAction.TurningPoint,
|
||||||
self.EngageSpeed,
|
self.EngageSpeed,
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
@@ -612,7 +611,7 @@ function AI_BAI_ZONE:onafterEngage( Controllable, From, Event, To,
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- @param #AI_BAI_ZONE self
|
-- @param #AI_BAI_ZONE self
|
||||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||||
-- @param #string From The From State string.
|
-- @param #string From The From State string.
|
||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
@@ -623,7 +622,7 @@ function AI_BAI_ZONE:onafterAccomplish( Controllable, From, Event, To )
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- @param #AI_BAI_ZONE self
|
-- @param #AI_BAI_ZONE self
|
||||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||||
-- @param #string From The From State string.
|
-- @param #string From The From State string.
|
||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
@@ -637,7 +636,7 @@ function AI_BAI_ZONE:onafterDestroy( Controllable, From, Event, To, EventData )
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- @param #AI_BAI_ZONE self
|
-- @param #AI_BAI_ZONE self
|
||||||
-- @param Core.Event#EVENTDATA EventData
|
-- @param Core.Event#EVENTDATA EventData
|
||||||
function AI_BAI_ZONE:OnEventDead( EventData )
|
function AI_BAI_ZONE:OnEventDead( EventData )
|
||||||
self:F( { "EventDead", EventData } )
|
self:F( { "EventDead", EventData } )
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
-- @module AI.AI_Balancer
|
-- @module AI.AI_Balancer
|
||||||
-- @image AI_Balancing.JPG
|
-- @image AI_Balancing.JPG
|
||||||
|
|
||||||
--- @type AI_BALANCER
|
-- @type AI_BALANCER
|
||||||
-- @field Core.Set#SET_CLIENT SetClient
|
-- @field Core.Set#SET_CLIENT SetClient
|
||||||
-- @field Core.Spawn#SPAWN SpawnAI
|
-- @field Core.Spawn#SPAWN SpawnAI
|
||||||
-- @field Wrapper.Group#GROUP Test
|
-- @field Wrapper.Group#GROUP Test
|
||||||
@@ -220,16 +220,9 @@ function AI_BALANCER:onenterReturning( SetGroup, From, Event, To, AIGroup )
|
|||||||
AIGroup:MessageToRed( "Returning to home base ...", 30 )
|
AIGroup:MessageToRed( "Returning to home base ...", 30 )
|
||||||
else
|
else
|
||||||
-- Okay, we need to send this Group back to the nearest base of the Coalition of the AI.
|
-- 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 = COORDINATE:New(AIGroup:GetVec2().x, 0, AIGroup:GetVec2().y)
|
||||||
local PointVec2 = POINT_VEC2:New( AIGroup:GetVec2().x, AIGroup:GetVec2().y )
|
|
||||||
local ClosestAirbase = self.ReturnAirbaseSet:FindNearestAirbaseFromPointVec2( PointVec2 )
|
local ClosestAirbase = self.ReturnAirbaseSet:FindNearestAirbaseFromPointVec2( PointVec2 )
|
||||||
self:T( ClosestAirbase.AirbaseName )
|
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)
|
AIGroup:RouteRTB(ClosestAirbase)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
-- @module AI.AI_CAP
|
-- @module AI.AI_CAP
|
||||||
-- @image AI_Combat_Air_Patrol.JPG
|
-- @image AI_Combat_Air_Patrol.JPG
|
||||||
|
|
||||||
--- @type AI_CAP_ZONE
|
-- @type AI_CAP_ZONE
|
||||||
-- @field Wrapper.Controllable#CONTROLLABLE AIControllable The @{Wrapper.Controllable} patrolling.
|
-- @field Wrapper.Controllable#CONTROLLABLE AIControllable The @{Wrapper.Controllable} patrolling.
|
||||||
-- @field Core.Zone#ZONE_BASE TargetZone The @{Core.Zone} where the patrol needs to be executed.
|
-- @field Core.Zone#ZONE_BASE TargetZone The @{Core.Zone} where the patrol needs to be executed.
|
||||||
-- @extends AI.AI_Patrol#AI_PATROL_ZONE
|
-- @extends AI.AI_Patrol#AI_PATROL_ZONE
|
||||||
@@ -344,7 +344,7 @@ function AI_CAP_ZONE:onafterStart( Controllable, From, Event, To )
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param AI.AI_CAP#AI_CAP_ZONE
|
-- @param AI.AI_CAP#AI_CAP_ZONE
|
||||||
-- @param Wrapper.Group#GROUP EngageGroup
|
-- @param Wrapper.Group#GROUP EngageGroup
|
||||||
function AI_CAP_ZONE.EngageRoute( EngageGroup, Fsm )
|
function AI_CAP_ZONE.EngageRoute( EngageGroup, Fsm )
|
||||||
|
|
||||||
@@ -355,7 +355,7 @@ function AI_CAP_ZONE.EngageRoute( EngageGroup, Fsm )
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #AI_CAP_ZONE self
|
-- @param #AI_CAP_ZONE self
|
||||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||||
-- @param #string From The From State string.
|
-- @param #string From The From State string.
|
||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
@@ -367,7 +367,7 @@ function AI_CAP_ZONE:onbeforeEngage( Controllable, From, Event, To )
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #AI_CAP_ZONE self
|
-- @param #AI_CAP_ZONE self
|
||||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||||
-- @param #string From The From State string.
|
-- @param #string From The From State string.
|
||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
@@ -395,7 +395,7 @@ function AI_CAP_ZONE:onafterDetected( Controllable, From, Event, To )
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #AI_CAP_ZONE self
|
-- @param #AI_CAP_ZONE self
|
||||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||||
-- @param #string From The From State string.
|
-- @param #string From The From State string.
|
||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
@@ -405,7 +405,7 @@ function AI_CAP_ZONE:onafterAbort( Controllable, From, Event, To )
|
|||||||
self:__Route( 1 )
|
self:__Route( 1 )
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #AI_CAP_ZONE self
|
-- @param #AI_CAP_ZONE self
|
||||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||||
-- @param #string From The From State string.
|
-- @param #string From The From State string.
|
||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
@@ -423,12 +423,12 @@ function AI_CAP_ZONE:onafterEngage( Controllable, From, Event, To )
|
|||||||
|
|
||||||
--DONE: Create GetAltitude function for GROUP, and delete GetUnit(1).
|
--DONE: Create GetAltitude function for GROUP, and delete GetUnit(1).
|
||||||
local CurrentAltitude = self.Controllable: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 ToEngageZoneSpeed = self.PatrolMaxSpeed
|
local ToEngageZoneSpeed = self.PatrolMaxSpeed
|
||||||
local CurrentRoutePoint = CurrentPointVec3:WaypointAir(
|
local CurrentRoutePoint = CurrentPointVec3:WaypointAir(
|
||||||
self.PatrolAltType,
|
self.PatrolAltType,
|
||||||
POINT_VEC3.RoutePointType.TurningPoint,
|
COORDINATE.WaypointType.TurningPoint,
|
||||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
COORDINATE.WaypointAction.TurningPoint,
|
||||||
ToEngageZoneSpeed,
|
ToEngageZoneSpeed,
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
@@ -445,13 +445,13 @@ function AI_CAP_ZONE:onafterEngage( Controllable, From, Event, To )
|
|||||||
self:T2( { self.PatrolMinSpeed, self.PatrolMaxSpeed, ToTargetSpeed } )
|
self:T2( { self.PatrolMinSpeed, self.PatrolMaxSpeed, ToTargetSpeed } )
|
||||||
|
|
||||||
--- Obtain a 3D @{Point} from the 2D point + altitude.
|
--- 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.
|
--- Create a route point of type air.
|
||||||
local ToPatrolRoutePoint = ToTargetPointVec3:WaypointAir(
|
local ToPatrolRoutePoint = ToTargetPointVec3:WaypointAir(
|
||||||
self.PatrolAltType,
|
self.PatrolAltType,
|
||||||
POINT_VEC3.RoutePointType.TurningPoint,
|
COORDINATE.WaypointType.TurningPoint,
|
||||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
COORDINATE.WaypointAction.TurningPoint,
|
||||||
ToTargetSpeed,
|
ToTargetSpeed,
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
@@ -505,7 +505,7 @@ function AI_CAP_ZONE:onafterEngage( Controllable, From, Event, To )
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #AI_CAP_ZONE self
|
-- @param #AI_CAP_ZONE self
|
||||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||||
-- @param #string From The From State string.
|
-- @param #string From The From State string.
|
||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
@@ -515,7 +515,7 @@ function AI_CAP_ZONE:onafterAccomplish( Controllable, From, Event, To )
|
|||||||
self:SetDetectionOff()
|
self:SetDetectionOff()
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #AI_CAP_ZONE self
|
-- @param #AI_CAP_ZONE self
|
||||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||||
-- @param #string From The From State string.
|
-- @param #string From The From State string.
|
||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
@@ -528,7 +528,7 @@ function AI_CAP_ZONE:onafterDestroy( Controllable, From, Event, To, EventData )
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #AI_CAP_ZONE self
|
-- @param #AI_CAP_ZONE self
|
||||||
-- @param Core.Event#EVENTDATA EventData
|
-- @param Core.Event#EVENTDATA EventData
|
||||||
function AI_CAP_ZONE:OnEventDead( EventData )
|
function AI_CAP_ZONE:OnEventDead( EventData )
|
||||||
self:F( { "EventDead", EventData } )
|
self:F( { "EventDead", EventData } )
|
||||||
|
|||||||
@@ -162,7 +162,6 @@ function AI_CAS_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude
|
|||||||
-- @param #string From The From State string.
|
-- @param #string From The From State string.
|
||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
-- @param #string To The To State string.
|
-- @param #string To The To State string.
|
||||||
|
|
||||||
-- @return #boolean Return false to cancel Transition.
|
-- @return #boolean Return false to cancel Transition.
|
||||||
|
|
||||||
--- OnAfter Transition Handler for Event Engage.
|
--- OnAfter Transition Handler for Event Engage.
|
||||||
@@ -363,7 +362,7 @@ function AI_CAS_ZONE:onafterStart( Controllable, From, Event, To )
|
|||||||
self:SetDetectionDeactivated() -- When not engaging, set the detection off.
|
self:SetDetectionDeactivated() -- When not engaging, set the detection off.
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param AI.AI_CAS#AI_CAS_ZONE
|
-- @param AI.AI_CAS#AI_CAS_ZONE
|
||||||
-- @param Wrapper.Group#GROUP EngageGroup
|
-- @param Wrapper.Group#GROUP EngageGroup
|
||||||
function AI_CAS_ZONE.EngageRoute( EngageGroup, Fsm )
|
function AI_CAS_ZONE.EngageRoute( EngageGroup, Fsm )
|
||||||
|
|
||||||
@@ -375,7 +374,7 @@ function AI_CAS_ZONE.EngageRoute( EngageGroup, Fsm )
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- @param #AI_CAS_ZONE self
|
-- @param #AI_CAS_ZONE self
|
||||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||||
-- @param #string From The From State string.
|
-- @param #string From The From State string.
|
||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
@@ -387,7 +386,7 @@ function AI_CAS_ZONE:onbeforeEngage( Controllable, From, Event, To )
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #AI_CAS_ZONE self
|
-- @param #AI_CAS_ZONE self
|
||||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||||
-- @param #string From The From State string.
|
-- @param #string From The From State string.
|
||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
@@ -420,7 +419,7 @@ function AI_CAS_ZONE:onafterTarget( Controllable, From, Event, To )
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- @param #AI_CAS_ZONE self
|
-- @param #AI_CAS_ZONE self
|
||||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||||
-- @param #string From The From State string.
|
-- @param #string From The From State string.
|
||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
@@ -430,7 +429,7 @@ function AI_CAS_ZONE:onafterAbort( Controllable, From, Event, To )
|
|||||||
self:__Route( 1 )
|
self:__Route( 1 )
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #AI_CAS_ZONE self
|
-- @param #AI_CAS_ZONE self
|
||||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||||
-- @param #string From The From State string.
|
-- @param #string From The From State string.
|
||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
@@ -466,12 +465,12 @@ function AI_CAS_ZONE:onafterEngage( Controllable, From, Event, To,
|
|||||||
|
|
||||||
--DONE: Create GetAltitude function for GROUP, and delete GetUnit(1).
|
--DONE: Create GetAltitude function for GROUP, and delete GetUnit(1).
|
||||||
local CurrentAltitude = self.Controllable: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 ToEngageZoneSpeed = self.PatrolMaxSpeed
|
local ToEngageZoneSpeed = self.PatrolMaxSpeed
|
||||||
local CurrentRoutePoint = CurrentPointVec3:WaypointAir(
|
local CurrentRoutePoint = CurrentPointVec3:WaypointAir(
|
||||||
self.PatrolAltType,
|
self.PatrolAltType,
|
||||||
POINT_VEC3.RoutePointType.TurningPoint,
|
COORDINATE.WaypointType.TurningPoint,
|
||||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
COORDINATE.WaypointAction.TurningPoint,
|
||||||
self.EngageSpeed,
|
self.EngageSpeed,
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
@@ -508,13 +507,13 @@ function AI_CAS_ZONE:onafterEngage( Controllable, From, Event, To,
|
|||||||
self:T2( ToTargetVec2 )
|
self:T2( ToTargetVec2 )
|
||||||
|
|
||||||
--- Obtain a 3D @{Point} from the 2D point + altitude.
|
--- 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.
|
--- Create a route point of type air.
|
||||||
local ToTargetRoutePoint = ToTargetPointVec3:WaypointAir(
|
local ToTargetRoutePoint = ToTargetPointVec3:WaypointAir(
|
||||||
self.PatrolAltType,
|
self.PatrolAltType,
|
||||||
POINT_VEC3.RoutePointType.TurningPoint,
|
COORDINATE.WaypointType.TurningPoint,
|
||||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
COORDINATE.WaypointAction.TurningPoint,
|
||||||
self.EngageSpeed,
|
self.EngageSpeed,
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
@@ -530,7 +529,7 @@ function AI_CAS_ZONE:onafterEngage( Controllable, From, Event, To,
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- @param #AI_CAS_ZONE self
|
-- @param #AI_CAS_ZONE self
|
||||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||||
-- @param #string From The From State string.
|
-- @param #string From The From State string.
|
||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
@@ -541,7 +540,7 @@ function AI_CAS_ZONE:onafterAccomplish( Controllable, From, Event, To )
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- @param #AI_CAS_ZONE self
|
-- @param #AI_CAS_ZONE self
|
||||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||||
-- @param #string From The From State string.
|
-- @param #string From The From State string.
|
||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
@@ -555,7 +554,7 @@ function AI_CAS_ZONE:onafterDestroy( Controllable, From, Event, To, EventData )
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- @param #AI_CAS_ZONE self
|
-- @param #AI_CAS_ZONE self
|
||||||
-- @param Core.Event#EVENTDATA EventData
|
-- @param Core.Event#EVENTDATA EventData
|
||||||
function AI_CAS_ZONE:OnEventDead( EventData )
|
function AI_CAS_ZONE:OnEventDead( EventData )
|
||||||
self:F( { "EventDead", EventData } )
|
self:F( { "EventDead", EventData } )
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
-- @module AI.AI_Cargo_APC
|
-- @module AI.AI_Cargo_APC
|
||||||
-- @image AI_Cargo_Dispatching_For_APC.JPG
|
-- @image AI_Cargo_Dispatching_For_APC.JPG
|
||||||
|
|
||||||
--- @type AI_CARGO_APC
|
-- @type AI_CARGO_APC
|
||||||
-- @extends AI.AI_Cargo#AI_CARGO
|
-- @extends AI.AI_Cargo#AI_CARGO
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
-- @module AI.AI_Cargo_Airplane
|
-- @module AI.AI_Cargo_Airplane
|
||||||
-- @image AI_Cargo_Dispatching_For_Airplanes.JPG
|
-- @image AI_Cargo_Dispatching_For_Airplanes.JPG
|
||||||
|
|
||||||
--- @type AI_CARGO_AIRPLANE
|
-- @type AI_CARGO_AIRPLANE
|
||||||
-- @extends Core.Fsm#FSM_CONTROLLABLE
|
-- @extends Core.Fsm#FSM_CONTROLLABLE
|
||||||
|
|
||||||
|
|
||||||
@@ -440,7 +440,7 @@ function AI_CARGO_AIRPLANE:Route( Airplane, Airbase, Speed, Height, Uncontrolled
|
|||||||
|
|
||||||
-- To point.
|
-- To point.
|
||||||
local AirbasePointVec2 = Airbase:GetPointVec2()
|
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["airdromeId"] = Airbase:GetID()
|
||||||
--ToWaypoint["speed_locked"] = true
|
--ToWaypoint["speed_locked"] = true
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
-- @module AI.AI_Cargo_Dispatcher_APC
|
-- @module AI.AI_Cargo_Dispatcher_APC
|
||||||
-- @image AI_Cargo_Dispatching_For_APC.JPG
|
-- @image AI_Cargo_Dispatching_For_APC.JPG
|
||||||
|
|
||||||
--- @type AI_CARGO_DISPATCHER_APC
|
-- @type AI_CARGO_DISPATCHER_APC
|
||||||
-- @extends AI.AI_Cargo_Dispatcher#AI_CARGO_DISPATCHER
|
-- @extends AI.AI_Cargo_Dispatcher#AI_CARGO_DISPATCHER
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
-- @image AI_Cargo_Dispatching_For_Airplanes.JPG
|
-- @image AI_Cargo_Dispatching_For_Airplanes.JPG
|
||||||
|
|
||||||
|
|
||||||
--- @type AI_CARGO_DISPATCHER_AIRPLANE
|
-- @type AI_CARGO_DISPATCHER_AIRPLANE
|
||||||
-- @extends AI.AI_Cargo_Dispatcher#AI_CARGO_DISPATCHER
|
-- @extends AI.AI_Cargo_Dispatcher#AI_CARGO_DISPATCHER
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
-- @module AI.AI_Cargo_Dispatcher_Helicopter
|
-- @module AI.AI_Cargo_Dispatcher_Helicopter
|
||||||
-- @image AI_Cargo_Dispatching_For_Helicopters.JPG
|
-- @image AI_Cargo_Dispatching_For_Helicopters.JPG
|
||||||
|
|
||||||
--- @type AI_CARGO_DISPATCHER_HELICOPTER
|
-- @type AI_CARGO_DISPATCHER_HELICOPTER
|
||||||
-- @extends AI.AI_Cargo_Dispatcher#AI_CARGO_DISPATCHER
|
-- @extends AI.AI_Cargo_Dispatcher#AI_CARGO_DISPATCHER
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
-- @module AI.AI_Cargo_Dispatcher_Ship
|
-- @module AI.AI_Cargo_Dispatcher_Ship
|
||||||
-- @image AI_Cargo_Dispatcher.JPG
|
-- @image AI_Cargo_Dispatcher.JPG
|
||||||
|
|
||||||
--- @type AI_CARGO_DISPATCHER_SHIP
|
-- @type AI_CARGO_DISPATCHER_SHIP
|
||||||
-- @extends AI.AI_Cargo_Dispatcher#AI_CARGO_DISPATCHER
|
-- @extends AI.AI_Cargo_Dispatcher#AI_CARGO_DISPATCHER
|
||||||
|
|
||||||
|
|
||||||
@@ -160,7 +160,7 @@ AI_CARGO_DISPATCHER_SHIP = {
|
|||||||
-- local SetPickupZones = SET_ZONE:New():FilterPrefixes( "Pickup" ):FilterStart()
|
-- local SetPickupZones = SET_ZONE:New():FilterPrefixes( "Pickup" ):FilterStart()
|
||||||
-- local SetDeployZones = SET_ZONE:New():FilterPrefixes( "Deploy" ):FilterStart()
|
-- local SetDeployZones = SET_ZONE:New():FilterPrefixes( "Deploy" ):FilterStart()
|
||||||
-- NEED MORE THOUGHT - ShippingLane is part of Warehouse.......
|
-- NEED MORE THOUGHT - ShippingLane is part of Warehouse.......
|
||||||
-- local ShippingLane = GROUP:New():FilterPrefixes( "ShippingLane" ):FilterStart()
|
-- local ShippingLane = SET_GROUP:New():FilterPrefixes( "ShippingLane" ):FilterOnce():GetSetObjects()
|
||||||
--
|
--
|
||||||
-- AICargoDispatcherShip = AI_CARGO_DISPATCHER_SHIP:New( SetShip, SetCargoInfantry, SetPickupZones, SetDeployZones, ShippingLane )
|
-- AICargoDispatcherShip = AI_CARGO_DISPATCHER_SHIP:New( SetShip, SetCargoInfantry, SetPickupZones, SetDeployZones, ShippingLane )
|
||||||
-- AICargoDispatcherShip:Start()
|
-- AICargoDispatcherShip:Start()
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
-- @module AI.AI_Cargo_Helicopter
|
-- @module AI.AI_Cargo_Helicopter
|
||||||
-- @image AI_Cargo_Dispatching_For_Helicopters.JPG
|
-- @image AI_Cargo_Dispatching_For_Helicopters.JPG
|
||||||
|
|
||||||
--- @type AI_CARGO_HELICOPTER
|
-- @type AI_CARGO_HELICOPTER
|
||||||
-- @extends Core.Fsm#FSM_CONTROLLABLE
|
-- @extends Core.Fsm#FSM_CONTROLLABLE
|
||||||
|
|
||||||
|
|
||||||
@@ -287,7 +287,7 @@ function AI_CARGO_HELICOPTER:SetLandingSpeedAndHeight(speed, height)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #AI_CARGO_HELICOPTER self
|
-- @param #AI_CARGO_HELICOPTER self
|
||||||
-- @param Wrapper.Group#GROUP Helicopter
|
-- @param Wrapper.Group#GROUP Helicopter
|
||||||
-- @param From
|
-- @param From
|
||||||
-- @param Event
|
-- @param Event
|
||||||
@@ -326,7 +326,7 @@ function AI_CARGO_HELICOPTER:onafterLanded( Helicopter, From, Event, To )
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #AI_CARGO_HELICOPTER self
|
-- @param #AI_CARGO_HELICOPTER self
|
||||||
-- @param Wrapper.Group#GROUP Helicopter
|
-- @param Wrapper.Group#GROUP Helicopter
|
||||||
-- @param From
|
-- @param From
|
||||||
-- @param Event
|
-- @param Event
|
||||||
@@ -367,8 +367,8 @@ function AI_CARGO_HELICOPTER:onafterQueue( Helicopter, From, Event, To, Coordina
|
|||||||
-- local CoordinateFrom = Helicopter:GetCoordinate()
|
-- local CoordinateFrom = Helicopter:GetCoordinate()
|
||||||
-- local WaypointFrom = CoordinateFrom:WaypointAir(
|
-- local WaypointFrom = CoordinateFrom:WaypointAir(
|
||||||
-- "RADIO",
|
-- "RADIO",
|
||||||
-- POINT_VEC3.RoutePointType.TurningPoint,
|
-- COORDINATE.WaypointType.TurningPoint,
|
||||||
-- POINT_VEC3.RoutePointAction.TurningPoint,
|
-- COORDINATE.WaypointAction.TurningPoint,
|
||||||
-- Speed,
|
-- Speed,
|
||||||
-- true
|
-- true
|
||||||
-- )
|
-- )
|
||||||
@@ -380,8 +380,8 @@ function AI_CARGO_HELICOPTER:onafterQueue( Helicopter, From, Event, To, Coordina
|
|||||||
|
|
||||||
local WaypointTo = CoordinateTo:WaypointAir(
|
local WaypointTo = CoordinateTo:WaypointAir(
|
||||||
"RADIO",
|
"RADIO",
|
||||||
POINT_VEC3.RoutePointType.TurningPoint,
|
COORDINATE.WaypointType.TurningPoint,
|
||||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
COORDINATE.WaypointAction.TurningPoint,
|
||||||
50,
|
50,
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
@@ -409,7 +409,7 @@ function AI_CARGO_HELICOPTER:onafterQueue( Helicopter, From, Event, To, Coordina
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- @param #AI_CARGO_HELICOPTER self
|
-- @param #AI_CARGO_HELICOPTER self
|
||||||
-- @param Wrapper.Group#GROUP Helicopter
|
-- @param Wrapper.Group#GROUP Helicopter
|
||||||
-- @param From
|
-- @param From
|
||||||
-- @param Event
|
-- @param Event
|
||||||
@@ -427,7 +427,7 @@ function AI_CARGO_HELICOPTER:onafterOrbit( Helicopter, From, Event, To, Coordina
|
|||||||
local landheight = CoordinateTo:GetLandHeight() -- get target height
|
local landheight = CoordinateTo:GetLandHeight() -- get target height
|
||||||
CoordinateTo.y = landheight + 50 -- flight height should be 50m above ground
|
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
|
Route[#Route+1] = WaypointTo
|
||||||
|
|
||||||
local Tasks = {}
|
local Tasks = {}
|
||||||
@@ -496,14 +496,14 @@ function AI_CARGO_HELICOPTER:onafterPickup( Helicopter, From, Event, To, Coordin
|
|||||||
local CoordinateFrom = Helicopter:GetCoordinate()
|
local CoordinateFrom = Helicopter:GetCoordinate()
|
||||||
|
|
||||||
--- Create a route point of type air.
|
--- 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.
|
--- Create a route point of type air.
|
||||||
local CoordinateTo = Coordinate
|
local CoordinateTo = Coordinate
|
||||||
local landheight = CoordinateTo:GetLandHeight() -- get target height
|
local landheight = CoordinateTo:GetLandHeight() -- get target height
|
||||||
CoordinateTo.y = landheight + 50 -- flight height should be 50m above ground
|
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] = WaypointFrom
|
||||||
Route[#Route+1] = WaypointTo
|
Route[#Route+1] = WaypointTo
|
||||||
@@ -563,7 +563,7 @@ function AI_CARGO_HELICOPTER:onafterDeploy( Helicopter, From, Event, To, Coordin
|
|||||||
|
|
||||||
--- Create a route point of type air.
|
--- Create a route point of type air.
|
||||||
local CoordinateFrom = Helicopter:GetCoordinate()
|
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
|
||||||
Route[#Route+1] = WaypointFrom
|
Route[#Route+1] = WaypointFrom
|
||||||
|
|
||||||
@@ -573,7 +573,7 @@ function AI_CARGO_HELICOPTER:onafterDeploy( Helicopter, From, Event, To, Coordin
|
|||||||
local landheight = CoordinateTo:GetLandHeight() -- get target height
|
local landheight = CoordinateTo:GetLandHeight() -- get target height
|
||||||
CoordinateTo.y = landheight + 50 -- flight height should be 50m above ground
|
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
|
||||||
Route[#Route+1] = WaypointTo
|
Route[#Route+1] = WaypointTo
|
||||||
@@ -631,7 +631,7 @@ function AI_CARGO_HELICOPTER:onafterHome( Helicopter, From, Event, To, Coordinat
|
|||||||
--- Create a route point of type air.
|
--- Create a route point of type air.
|
||||||
local CoordinateFrom = Helicopter:GetCoordinate()
|
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
|
||||||
|
|
||||||
--- Create a route point of type air.
|
--- Create a route point of type air.
|
||||||
@@ -639,7 +639,7 @@ function AI_CARGO_HELICOPTER:onafterHome( Helicopter, From, Event, To, Coordinat
|
|||||||
local landheight = CoordinateTo:GetLandHeight() -- get target height
|
local landheight = CoordinateTo:GetLandHeight() -- get target height
|
||||||
CoordinateTo.y = landheight + Height -- flight height should be 50m above ground
|
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
|
Route[#Route+1] = WaypointTo
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
-- @module AI.AI_Cargo_Ship
|
-- @module AI.AI_Cargo_Ship
|
||||||
-- @image AI_Cargo_Dispatcher.JPG
|
-- @image AI_Cargo_Dispatcher.JPG
|
||||||
|
|
||||||
--- @type AI_CARGO_SHIP
|
-- @type AI_CARGO_SHIP
|
||||||
-- @extends AI.AI_Cargo#AI_CARGO
|
-- @extends AI.AI_Cargo#AI_CARGO
|
||||||
|
|
||||||
--- Brings a dynamic cargo handling capability for an AI naval group.
|
--- Brings a dynamic cargo handling capability for an AI naval group.
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
-- @image MOOSE.JPG
|
-- @image MOOSE.JPG
|
||||||
|
|
||||||
|
|
||||||
--- @type AI_ESCORT_DISPATCHER_REQUEST
|
-- @type AI_ESCORT_DISPATCHER_REQUEST
|
||||||
-- @extends Core.Fsm#FSM
|
-- @extends Core.Fsm#FSM
|
||||||
|
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ AI_ESCORT_DISPATCHER_REQUEST = {
|
|||||||
ClassName = "AI_ESCORT_DISPATCHER_REQUEST",
|
ClassName = "AI_ESCORT_DISPATCHER_REQUEST",
|
||||||
}
|
}
|
||||||
|
|
||||||
--- @field #list
|
-- @field #list
|
||||||
AI_ESCORT_DISPATCHER_REQUEST.AI_Escorts = {}
|
AI_ESCORT_DISPATCHER_REQUEST.AI_Escorts = {}
|
||||||
|
|
||||||
|
|
||||||
@@ -80,7 +80,7 @@ function AI_ESCORT_DISPATCHER_REQUEST:onafterStart( From, Event, To )
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #AI_ESCORT_DISPATCHER_REQUEST self
|
-- @param #AI_ESCORT_DISPATCHER_REQUEST self
|
||||||
-- @param Core.Event#EVENTDATA EventData
|
-- @param Core.Event#EVENTDATA EventData
|
||||||
function AI_ESCORT_DISPATCHER_REQUEST:OnEventExit( EventData )
|
function AI_ESCORT_DISPATCHER_REQUEST:OnEventExit( EventData )
|
||||||
|
|
||||||
@@ -97,7 +97,7 @@ function AI_ESCORT_DISPATCHER_REQUEST:OnEventExit( EventData )
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #AI_ESCORT_DISPATCHER_REQUEST self
|
-- @param #AI_ESCORT_DISPATCHER_REQUEST self
|
||||||
-- @param Core.Event#EVENTDATA EventData
|
-- @param Core.Event#EVENTDATA EventData
|
||||||
function AI_ESCORT_DISPATCHER_REQUEST:OnEventBirth( EventData )
|
function AI_ESCORT_DISPATCHER_REQUEST:OnEventBirth( EventData )
|
||||||
|
|
||||||
|
|||||||
@@ -136,12 +136,12 @@
|
|||||||
--
|
--
|
||||||
-- Escort groups can have their own mission. This menu item will allow the escort group to resume their Mission from a given waypoint.
|
-- Escort groups can have their own mission. This menu item will allow the escort group to resume their Mission from a given waypoint.
|
||||||
-- Note that this is really fantastic, as you now have the dynamic of taking control of the escort groups, and allowing them to resume their path or mission.
|
-- Note that this is really fantastic, as you now have the dynamic of taking control of the escort groups, and allowing them to resume their path or mission.
|
||||||
--
|
--
|
||||||
-- # Developer Note
|
-- # Developer Note
|
||||||
--
|
--
|
||||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||||
-- Therefore, this class is considered to be deprecated
|
-- Therefore, this class is considered to be deprecated
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ### Authors: **FlightControl**
|
-- ### Authors: **FlightControl**
|
||||||
@@ -153,7 +153,7 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
--- @type AI_ESCORT_REQUEST
|
-- @type AI_ESCORT_REQUEST
|
||||||
-- @extends AI.AI_Escort#AI_ESCORT
|
-- @extends AI.AI_Escort#AI_ESCORT
|
||||||
|
|
||||||
--- AI_ESCORT_REQUEST class
|
--- AI_ESCORT_REQUEST class
|
||||||
@@ -228,7 +228,7 @@ function AI_ESCORT_REQUEST:New( EscortUnit, EscortSpawn, EscortAirbase, EscortNa
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #AI_ESCORT_REQUEST self
|
-- @param #AI_ESCORT_REQUEST self
|
||||||
function AI_ESCORT_REQUEST:SpawnEscort()
|
function AI_ESCORT_REQUEST:SpawnEscort()
|
||||||
|
|
||||||
local EscortGroup = self.EscortSpawn:SpawnAtAirbase( self.EscortAirbase, SPAWN.Takeoff.Hot )
|
local EscortGroup = self.EscortSpawn:SpawnAtAirbase( self.EscortAirbase, SPAWN.Takeoff.Hot )
|
||||||
@@ -253,7 +253,7 @@ function AI_ESCORT_REQUEST:SpawnEscort()
|
|||||||
self:_InitEscortMenus( EscortGroup )
|
self:_InitEscortMenus( EscortGroup )
|
||||||
self:_InitEscortRoute( EscortGroup )
|
self:_InitEscortRoute( EscortGroup )
|
||||||
|
|
||||||
--- @param #AI_ESCORT self
|
-- @param #AI_ESCORT self
|
||||||
-- @param Core.Event#EVENTDATA EventData
|
-- @param Core.Event#EVENTDATA EventData
|
||||||
function EscortGroup:OnEventDeadOrCrash( EventData )
|
function EscortGroup:OnEventDeadOrCrash( EventData )
|
||||||
self:F( { "EventDead", EventData } )
|
self:F( { "EventDead", EventData } )
|
||||||
@@ -268,7 +268,7 @@ function AI_ESCORT_REQUEST:SpawnEscort()
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #AI_ESCORT_REQUEST self
|
-- @param #AI_ESCORT_REQUEST self
|
||||||
-- @param Core.Set#SET_GROUP EscortGroupSet
|
-- @param Core.Set#SET_GROUP EscortGroupSet
|
||||||
function AI_ESCORT_REQUEST:onafterStart( EscortGroupSet )
|
function AI_ESCORT_REQUEST:onafterStart( EscortGroupSet )
|
||||||
|
|
||||||
@@ -290,14 +290,14 @@ function AI_ESCORT_REQUEST:onafterStart( EscortGroupSet )
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #AI_ESCORT_REQUEST self
|
-- @param #AI_ESCORT_REQUEST self
|
||||||
-- @param Core.Set#SET_GROUP EscortGroupSet
|
-- @param Core.Set#SET_GROUP EscortGroupSet
|
||||||
function AI_ESCORT_REQUEST:onafterStop( EscortGroupSet )
|
function AI_ESCORT_REQUEST:onafterStop( EscortGroupSet )
|
||||||
|
|
||||||
self:F()
|
self:F()
|
||||||
|
|
||||||
EscortGroupSet:ForEachGroup(
|
EscortGroupSet:ForEachGroup(
|
||||||
--- @param Wrapper.Group#GROUP EscortGroup
|
-- @param Core.Group#GROUP EscortGroup
|
||||||
function( EscortGroup )
|
function( EscortGroup )
|
||||||
EscortGroup:WayPointInitialize()
|
EscortGroup:WayPointInitialize()
|
||||||
|
|
||||||
|
|||||||
@@ -34,8 +34,8 @@
|
|||||||
-- @field Core.Scheduler#SCHEDULER FollowScheduler The instance of the SCHEDULER class.
|
-- @field Core.Scheduler#SCHEDULER FollowScheduler The instance of the SCHEDULER class.
|
||||||
-- @field #number FollowDistance The current follow distance.
|
-- @field #number FollowDistance The current follow distance.
|
||||||
-- @field #boolean ReportTargets If true, nearby targets are reported.
|
-- @field #boolean ReportTargets If true, nearby targets are reported.
|
||||||
-- @field DCS#AI.Option.Air.val.ROE OptionROE Which ROE is set to the FollowGroup.
|
-- @Field DCSTypes#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 DCSTypes#AI.Option.Air.val.REACTION_ON_THREAT OptionReactionOnThreat Which REACTION_ON_THREAT is set to the FollowGroup.
|
||||||
-- @field #number dtFollow Time step between position updates.
|
-- @field #number dtFollow Time step between position updates.
|
||||||
|
|
||||||
|
|
||||||
@@ -92,12 +92,12 @@
|
|||||||
-- local LargeFormation = AI_FORMATION:New( LeaderUnit, FollowGroupSet, "Center Wing Formation", "Briefing" )
|
-- local LargeFormation = AI_FORMATION:New( LeaderUnit, FollowGroupSet, "Center Wing Formation", "Briefing" )
|
||||||
-- LargeFormation:FormationCenterWing( 500, 50, 0, 250, 250 )
|
-- LargeFormation:FormationCenterWing( 500, 50, 0, 250, 250 )
|
||||||
-- LargeFormation:__Start( 1 )
|
-- LargeFormation:__Start( 1 )
|
||||||
--
|
--
|
||||||
-- # Developer Note
|
-- # Developer Note
|
||||||
--
|
--
|
||||||
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE
|
||||||
-- Therefore, this class is considered to be deprecated
|
-- Therefore, this class is considered to be deprecated
|
||||||
--
|
--
|
||||||
-- @field #AI_FORMATION
|
-- @field #AI_FORMATION
|
||||||
AI_FORMATION = {
|
AI_FORMATION = {
|
||||||
ClassName = "AI_FORMATION",
|
ClassName = "AI_FORMATION",
|
||||||
@@ -117,7 +117,7 @@ AI_FORMATION = {
|
|||||||
|
|
||||||
AI_FORMATION.__Enum = {}
|
AI_FORMATION.__Enum = {}
|
||||||
|
|
||||||
--- @type AI_FORMATION.__Enum.Formation
|
-- @type AI_FORMATION.__Enum.Formation
|
||||||
-- @field #number None
|
-- @field #number None
|
||||||
-- @field #number Line
|
-- @field #number Line
|
||||||
-- @field #number Trail
|
-- @field #number Trail
|
||||||
@@ -142,7 +142,7 @@ AI_FORMATION.__Enum.Formation = {
|
|||||||
Box = 10,
|
Box = 10,
|
||||||
}
|
}
|
||||||
|
|
||||||
--- @type AI_FORMATION.__Enum.Mode
|
-- @type AI_FORMATION.__Enum.Mode
|
||||||
-- @field #number Mission
|
-- @field #number Mission
|
||||||
-- @field #number Formation
|
-- @field #number Formation
|
||||||
AI_FORMATION.__Enum.Mode = {
|
AI_FORMATION.__Enum.Mode = {
|
||||||
@@ -152,13 +152,13 @@ AI_FORMATION.__Enum.Mode = {
|
|||||||
Reconnaissance = "R",
|
Reconnaissance = "R",
|
||||||
}
|
}
|
||||||
|
|
||||||
--- @type AI_FORMATION.__Enum.ReportType
|
-- @type AI_FORMATION.__Enum.ReportType
|
||||||
-- @field #number All
|
-- @field #number All
|
||||||
-- @field #number Airborne
|
-- @field #number Airborne
|
||||||
-- @field #number GroundRadar
|
-- @field #number GroundRadar
|
||||||
-- @field #number Ground
|
-- @field #number Ground
|
||||||
AI_FORMATION.__Enum.ReportType = {
|
AI_FORMATION.__Enum.ReportType = {
|
||||||
Airborne = "*",
|
All = "*",
|
||||||
Airborne = "A",
|
Airborne = "A",
|
||||||
GroundRadar = "R",
|
GroundRadar = "R",
|
||||||
Ground = "G",
|
Ground = "G",
|
||||||
@@ -725,7 +725,7 @@ function AI_FORMATION:onafterFormationLine( FollowGroupSet, From , Event , To, X
|
|||||||
|
|
||||||
for FollowID, FollowGroup in pairs( FollowSet ) do
|
for FollowID, FollowGroup in pairs( FollowSet ) do
|
||||||
|
|
||||||
local PointVec3 = POINT_VEC3:New()
|
local PointVec3 = COORDINATE:New()
|
||||||
PointVec3:SetX( XStart + i * XSpace )
|
PointVec3:SetX( XStart + i * XSpace )
|
||||||
PointVec3:SetY( YStart + i * YSpace )
|
PointVec3:SetY( YStart + i * YSpace )
|
||||||
PointVec3:SetZ( ZStart + i * ZSpace )
|
PointVec3:SetZ( ZStart + i * ZSpace )
|
||||||
@@ -877,7 +877,7 @@ function AI_FORMATION:onafterFormationCenterWing( FollowGroupSet, From , Event ,
|
|||||||
|
|
||||||
for FollowID, FollowGroup in pairs( FollowSet ) do
|
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 Side = ( i % 2 == 0 ) and 1 or -1
|
||||||
local Row = i / 2 + 1
|
local Row = i / 2 + 1
|
||||||
@@ -936,7 +936,7 @@ function AI_FORMATION:onafterFormationBox( FollowGroupSet, From , Event , To, XS
|
|||||||
|
|
||||||
for FollowID, FollowGroup in pairs( FollowSet ) do
|
for FollowID, FollowGroup in pairs( FollowSet ) do
|
||||||
|
|
||||||
local PointVec3 = POINT_VEC3:New()
|
local PointVec3 = COORDINATE:New()
|
||||||
|
|
||||||
local ZIndex = i % ZLevels
|
local ZIndex = i % ZLevels
|
||||||
local XIndex = math.floor( i / ZLevels )
|
local XIndex = math.floor( i / ZLevels )
|
||||||
@@ -996,7 +996,7 @@ function AI_FORMATION:SetFlightModeMission( FollowGroup )
|
|||||||
FollowGroup:SetState( FollowGroup, "Mode", self.__Enum.Mode.Mission )
|
FollowGroup:SetState( FollowGroup, "Mode", self.__Enum.Mode.Mission )
|
||||||
else
|
else
|
||||||
self.FollowGroupSet:ForSomeGroupAlive(
|
self.FollowGroupSet:ForSomeGroupAlive(
|
||||||
--- @param Wrapper.Group#GROUP EscortGroup
|
-- @param Core.Group#GROUP EscortGroup
|
||||||
function( FollowGroup )
|
function( FollowGroup )
|
||||||
FollowGroup:SetState( FollowGroup, "PreviousMode", FollowGroup:GetState( FollowGroup, "Mode" ) )
|
FollowGroup:SetState( FollowGroup, "PreviousMode", FollowGroup:GetState( FollowGroup, "Mode" ) )
|
||||||
FollowGroup:SetState( FollowGroup, "Mode", self.__Enum.Mode.Mission )
|
FollowGroup:SetState( FollowGroup, "Mode", self.__Enum.Mode.Mission )
|
||||||
@@ -1020,7 +1020,7 @@ function AI_FORMATION:SetFlightModeAttack( FollowGroup )
|
|||||||
FollowGroup:SetState( FollowGroup, "Mode", self.__Enum.Mode.Attack )
|
FollowGroup:SetState( FollowGroup, "Mode", self.__Enum.Mode.Attack )
|
||||||
else
|
else
|
||||||
self.FollowGroupSet:ForSomeGroupAlive(
|
self.FollowGroupSet:ForSomeGroupAlive(
|
||||||
--- @param Wrapper.Group#GROUP EscortGroup
|
-- @param Core.Group#GROUP EscortGroup
|
||||||
function( FollowGroup )
|
function( FollowGroup )
|
||||||
FollowGroup:SetState( FollowGroup, "PreviousMode", FollowGroup:GetState( FollowGroup, "Mode" ) )
|
FollowGroup:SetState( FollowGroup, "PreviousMode", FollowGroup:GetState( FollowGroup, "Mode" ) )
|
||||||
FollowGroup:SetState( FollowGroup, "Mode", self.__Enum.Mode.Attack )
|
FollowGroup:SetState( FollowGroup, "Mode", self.__Enum.Mode.Attack )
|
||||||
@@ -1044,7 +1044,7 @@ function AI_FORMATION:SetFlightModeFormation( FollowGroup )
|
|||||||
FollowGroup:SetState( FollowGroup, "Mode", self.__Enum.Mode.Formation )
|
FollowGroup:SetState( FollowGroup, "Mode", self.__Enum.Mode.Formation )
|
||||||
else
|
else
|
||||||
self.FollowGroupSet:ForSomeGroupAlive(
|
self.FollowGroupSet:ForSomeGroupAlive(
|
||||||
--- @param Wrapper.Group#GROUP EscortGroup
|
-- @param Core.Group#GROUP EscortGroup
|
||||||
function( FollowGroup )
|
function( FollowGroup )
|
||||||
FollowGroup:SetState( FollowGroup, "PreviousMode", FollowGroup:GetState( FollowGroup, "Mode" ) )
|
FollowGroup:SetState( FollowGroup, "PreviousMode", FollowGroup:GetState( FollowGroup, "Mode" ) )
|
||||||
FollowGroup:SetState( FollowGroup, "Mode", self.__Enum.Mode.Formation )
|
FollowGroup:SetState( FollowGroup, "Mode", self.__Enum.Mode.Formation )
|
||||||
@@ -1222,7 +1222,7 @@ function AI_FORMATION:FollowMe(FollowGroup, ClientUnit, CT1, CV1, CT2, CV2)
|
|||||||
local CVI = {
|
local CVI = {
|
||||||
x = CV2.x + CS * 10 * math.sin(Ca),
|
x = CV2.x + CS * 10 * math.sin(Ca),
|
||||||
y = GH2.y + Inclination, -- + FollowFormation.y,
|
y = GH2.y + Inclination, -- + FollowFormation.y,
|
||||||
y = GH2.y,
|
--y = GH2.y,
|
||||||
z = CV2.z + CS * 10 * math.cos(Ca),
|
z = CV2.z + CS * 10 * math.cos(Ca),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -751,12 +751,12 @@ function AI_PATROL_ZONE:onafterRoute( Controllable, From, Event, To )
|
|||||||
if not CurrentVec2 then return end
|
if not CurrentVec2 then return end
|
||||||
--Done: Create GetAltitude function for GROUP, and delete GetUnit(1).
|
--Done: Create GetAltitude function for GROUP, and delete GetUnit(1).
|
||||||
local CurrentAltitude = self.Controllable: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 ToPatrolZoneSpeed = self.PatrolMaxSpeed
|
||||||
local CurrentRoutePoint = CurrentPointVec3:WaypointAir(
|
local CurrentRoutePoint = CurrentPointVec3:WaypointAir(
|
||||||
self.PatrolAltType,
|
self.PatrolAltType,
|
||||||
POINT_VEC3.RoutePointType.TakeOffParking,
|
COORDINATE.WaypointType.TakeOffParking,
|
||||||
POINT_VEC3.RoutePointAction.FromParkingArea,
|
COORDINATE.WaypointAction.FromParkingArea,
|
||||||
ToPatrolZoneSpeed,
|
ToPatrolZoneSpeed,
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
@@ -767,12 +767,12 @@ function AI_PATROL_ZONE:onafterRoute( Controllable, From, Event, To )
|
|||||||
if not CurrentVec2 then return end
|
if not CurrentVec2 then return end
|
||||||
--DONE: Create GetAltitude function for GROUP, and delete GetUnit(1).
|
--DONE: Create GetAltitude function for GROUP, and delete GetUnit(1).
|
||||||
local CurrentAltitude = self.Controllable: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 ToPatrolZoneSpeed = self.PatrolMaxSpeed
|
||||||
local CurrentRoutePoint = CurrentPointVec3:WaypointAir(
|
local CurrentRoutePoint = CurrentPointVec3:WaypointAir(
|
||||||
self.PatrolAltType,
|
self.PatrolAltType,
|
||||||
POINT_VEC3.RoutePointType.TurningPoint,
|
COORDINATE.WaypointType.TurningPoint,
|
||||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
COORDINATE.WaypointAction.TurningPoint,
|
||||||
ToPatrolZoneSpeed,
|
ToPatrolZoneSpeed,
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
@@ -792,13 +792,13 @@ function AI_PATROL_ZONE:onafterRoute( Controllable, From, Event, To )
|
|||||||
self:T2( { self.PatrolMinSpeed, self.PatrolMaxSpeed, ToTargetSpeed } )
|
self:T2( { self.PatrolMinSpeed, self.PatrolMaxSpeed, ToTargetSpeed } )
|
||||||
|
|
||||||
--- Obtain a 3D @{Point} from the 2D point + altitude.
|
--- 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.
|
--- Create a route point of type air.
|
||||||
local ToTargetRoutePoint = ToTargetPointVec3:WaypointAir(
|
local ToTargetRoutePoint = ToTargetPointVec3:WaypointAir(
|
||||||
self.PatrolAltType,
|
self.PatrolAltType,
|
||||||
POINT_VEC3.RoutePointType.TurningPoint,
|
COORDINATE.WaypointType.TurningPoint,
|
||||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
COORDINATE.WaypointAction.TurningPoint,
|
||||||
ToTargetSpeed,
|
ToTargetSpeed,
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
@@ -846,7 +846,6 @@ function AI_PATROL_ZONE:onafterStatus()
|
|||||||
OldAIControllable:SetTask( TimedOrbitTask, 10 )
|
OldAIControllable:SetTask( TimedOrbitTask, 10 )
|
||||||
|
|
||||||
RTB = true
|
RTB = true
|
||||||
else
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- TODO: Check GROUP damage function.
|
-- TODO: Check GROUP damage function.
|
||||||
@@ -856,6 +855,16 @@ function AI_PATROL_ZONE:onafterStatus()
|
|||||||
RTB = true
|
RTB = true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if self:IsInstanceOf("AI_CAS") or self:IsInstanceOf("AI_BAI") then
|
||||||
|
local atotal,shells,rockets,bombs,missiles = self.Controllable:GetAmmunition()
|
||||||
|
local arelevant = rockets+bombs
|
||||||
|
if arelevant == 0 or missiles == 0 then
|
||||||
|
RTB = true
|
||||||
|
self:T({total=atotal,shells=shells,rockets=rockets,bombs=bombs,missiles=missiles})
|
||||||
|
self:T( self.Controllable:GetName() .. " is out of ammo, RTB!" )
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
if RTB == true then
|
if RTB == true then
|
||||||
self:RTB()
|
self:RTB()
|
||||||
else
|
else
|
||||||
@@ -881,12 +890,12 @@ function AI_PATROL_ZONE:onafterRTB()
|
|||||||
--DONE: Create GetAltitude function for GROUP, and delete GetUnit(1).
|
--DONE: Create GetAltitude function for GROUP, and delete GetUnit(1).
|
||||||
--local CurrentAltitude = self.Controllable:GetUnit(1):GetAltitude()
|
--local CurrentAltitude = self.Controllable:GetUnit(1):GetAltitude()
|
||||||
local CurrentAltitude = self.Controllable: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 ToPatrolZoneSpeed = self.PatrolMaxSpeed
|
||||||
local CurrentRoutePoint = CurrentPointVec3:WaypointAir(
|
local CurrentRoutePoint = CurrentPointVec3:WaypointAir(
|
||||||
self.PatrolAltType,
|
self.PatrolAltType,
|
||||||
POINT_VEC3.RoutePointType.TurningPoint,
|
COORDINATE.WaypointType.TurningPoint,
|
||||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
COORDINATE.WaypointAction.TurningPoint,
|
||||||
ToPatrolZoneSpeed,
|
ToPatrolZoneSpeed,
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -274,7 +274,7 @@ do -- ACT_ACCOUNT_DEADS
|
|||||||
|
|
||||||
--- DCS Events
|
--- DCS Events
|
||||||
|
|
||||||
--- @param #ACT_ACCOUNT_DEADS self
|
-- @param #ACT_ACCOUNT_DEADS self
|
||||||
-- @param Core.Event#EVENTDATA EventData
|
-- @param Core.Event#EVENTDATA EventData
|
||||||
function ACT_ACCOUNT_DEADS:OnEventHit( EventData )
|
function ACT_ACCOUNT_DEADS:OnEventHit( EventData )
|
||||||
self:T( { "EventDead", EventData } )
|
self:T( { "EventDead", EventData } )
|
||||||
@@ -285,7 +285,7 @@ do -- ACT_ACCOUNT_DEADS
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #ACT_ACCOUNT_DEADS self
|
-- @param #ACT_ACCOUNT_DEADS self
|
||||||
-- @param Core.Event#EVENTDATA EventData
|
-- @param Core.Event#EVENTDATA EventData
|
||||||
function ACT_ACCOUNT_DEADS:onfuncEventDead( EventData )
|
function ACT_ACCOUNT_DEADS:onfuncEventDead( EventData )
|
||||||
self:T( { "EventDead", EventData } )
|
self:T( { "EventDead", EventData } )
|
||||||
@@ -297,7 +297,7 @@ do -- ACT_ACCOUNT_DEADS
|
|||||||
|
|
||||||
--- DCS Events
|
--- DCS Events
|
||||||
|
|
||||||
--- @param #ACT_ACCOUNT_DEADS self
|
-- @param #ACT_ACCOUNT_DEADS self
|
||||||
-- @param Core.Event#EVENTDATA EventData
|
-- @param Core.Event#EVENTDATA EventData
|
||||||
function ACT_ACCOUNT_DEADS:onfuncEventCrash( EventData )
|
function ACT_ACCOUNT_DEADS:onfuncEventCrash( EventData )
|
||||||
self:T( { "EventDead", EventData } )
|
self:T( { "EventDead", EventData } )
|
||||||
|
|||||||
@@ -200,7 +200,7 @@ do -- ACT_ASSIST_SMOKE_TARGETS_ZONE
|
|||||||
function ACT_ASSIST_SMOKE_TARGETS_ZONE:onenterSmoking( ProcessUnit, From, Event, To )
|
function ACT_ASSIST_SMOKE_TARGETS_ZONE:onenterSmoking( ProcessUnit, From, Event, To )
|
||||||
|
|
||||||
self.TargetSetUnit:ForEachUnit(
|
self.TargetSetUnit:ForEachUnit(
|
||||||
--- @param Wrapper.Unit#UNIT SmokeUnit
|
-- @param Wrapper.Unit#UNIT SmokeUnit
|
||||||
function( SmokeUnit )
|
function( SmokeUnit )
|
||||||
if math.random( 1, ( 100 * self.TargetSetUnit:Count() ) / 4 ) <= 100 then
|
if math.random( 1, ( 100 * self.TargetSetUnit:Count() ) / 4 ) <= 100 then
|
||||||
SCHEDULER:New( self,
|
SCHEDULER:New( self,
|
||||||
|
|||||||
@@ -275,14 +275,14 @@
|
|||||||
-- The cargo must be in the **Loaded** state.
|
-- The cargo must be in the **Loaded** state.
|
||||||
-- @function [parent=#CARGO] UnBoard
|
-- @function [parent=#CARGO] UnBoard
|
||||||
-- @param #CARGO self
|
-- @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.
|
--- 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.
|
-- The cargo must be in the **Loaded** state.
|
||||||
-- @function [parent=#CARGO] __UnBoard
|
-- @function [parent=#CARGO] __UnBoard
|
||||||
-- @param #CARGO self
|
-- @param #CARGO self
|
||||||
-- @param #number DelaySeconds The amount of seconds to delay the action.
|
-- @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
|
-- Load
|
||||||
@@ -307,14 +307,14 @@
|
|||||||
-- The cargo must be in the **Loaded** state.
|
-- The cargo must be in the **Loaded** state.
|
||||||
-- @function [parent=#CARGO] UnLoad
|
-- @function [parent=#CARGO] UnLoad
|
||||||
-- @param #CARGO self
|
-- @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.
|
--- 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.
|
-- The cargo must be in the **Loaded** state.
|
||||||
-- @function [parent=#CARGO] __UnLoad
|
-- @function [parent=#CARGO] __UnLoad
|
||||||
-- @param #CARGO self
|
-- @param #CARGO self
|
||||||
-- @param #number DelaySeconds The amount of seconds to delay the action.
|
-- @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
|
-- State Transition Functions
|
||||||
|
|
||||||
@@ -467,7 +467,7 @@ do -- CARGO
|
|||||||
self.Type = Type
|
self.Type = Type
|
||||||
self.Name = Name
|
self.Name = Name
|
||||||
self.Weight = Weight or 0
|
self.Weight = Weight or 0
|
||||||
self.CargoObject = nil
|
self.CargoObject = nil -- Wrapper.Group#GROUP
|
||||||
self.CargoCarrier = nil -- Wrapper.Client#CLIENT
|
self.CargoCarrier = nil -- Wrapper.Client#CLIENT
|
||||||
self.Representable = false
|
self.Representable = false
|
||||||
self.Slingloadable = false
|
self.Slingloadable = false
|
||||||
@@ -897,7 +897,7 @@ do -- CARGO
|
|||||||
|
|
||||||
--- Get the current PointVec2 of the cargo.
|
--- Get the current PointVec2 of the cargo.
|
||||||
-- @param #CARGO self
|
-- @param #CARGO self
|
||||||
-- @return Core.Point#POINT_VEC2
|
-- @return Core.Point#COORDINATE
|
||||||
function CARGO:GetPointVec2()
|
function CARGO:GetPointVec2()
|
||||||
return self.CargoObject:GetPointVec2()
|
return self.CargoObject:GetPointVec2()
|
||||||
end
|
end
|
||||||
@@ -1094,7 +1094,7 @@ do -- CARGO_REPRESENTABLE
|
|||||||
|
|
||||||
--- Route a cargo unit to a PointVec2.
|
--- Route a cargo unit to a PointVec2.
|
||||||
-- @param #CARGO_REPRESENTABLE self
|
-- @param #CARGO_REPRESENTABLE self
|
||||||
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
-- @param Core.Point#COORDINATE ToPointVec2
|
||||||
-- @param #number Speed
|
-- @param #number Speed
|
||||||
-- @return #CARGO_REPRESENTABLE
|
-- @return #CARGO_REPRESENTABLE
|
||||||
function CARGO_REPRESENTABLE:RouteTo( ToPointVec2, Speed )
|
function CARGO_REPRESENTABLE:RouteTo( ToPointVec2, Speed )
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ do -- CARGO_CRATE
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #CARGO_CRATE self
|
-- @param #CARGO_CRATE self
|
||||||
-- @param Core.Event#EVENTDATA EventData
|
-- @param Core.Event#EVENTDATA EventData
|
||||||
function CARGO_CRATE:OnEventCargoDead( EventData )
|
function CARGO_CRATE:OnEventCargoDead( EventData )
|
||||||
|
|
||||||
@@ -114,7 +114,7 @@ do -- CARGO_CRATE
|
|||||||
-- @param #string Event
|
-- @param #string Event
|
||||||
-- @param #string From
|
-- @param #string From
|
||||||
-- @param #string To
|
-- @param #string To
|
||||||
-- @param Core.Point#POINT_VEC2
|
-- @param Core.Point#COORDINATE
|
||||||
function CARGO_CRATE:onenterUnLoaded( From, Event, To, ToPointVec2 )
|
function CARGO_CRATE:onenterUnLoaded( From, Event, To, ToPointVec2 )
|
||||||
--self:T( { ToPointVec2, From, Event, To } )
|
--self:T( { ToPointVec2, From, Event, To } )
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ do -- CARGO_GROUP
|
|||||||
--- @type CARGO_GROUP
|
--- @type CARGO_GROUP
|
||||||
-- @field Core.Set#SET_CARGO CargoSet The collection of derived CARGO objects.
|
-- @field Core.Set#SET_CARGO CargoSet The collection of derived CARGO objects.
|
||||||
-- @field #string GroupName The name of the CargoGroup.
|
-- @field #string GroupName The name of the CargoGroup.
|
||||||
|
-- @field Wrapper.Group#GROUÜ CargoCarrier The carrier group.
|
||||||
-- @extends Cargo.Cargo#CARGO_REPORTABLE
|
-- @extends Cargo.Cargo#CARGO_REPORTABLE
|
||||||
|
|
||||||
--- Defines a cargo that is represented by a @{Wrapper.Group} object within the simulator.
|
--- Defines a cargo that is represented by a @{Wrapper.Group} object within the simulator.
|
||||||
@@ -410,7 +411,7 @@ do -- CARGO_GROUP
|
|||||||
-- @param #string Event
|
-- @param #string Event
|
||||||
-- @param #string From
|
-- @param #string From
|
||||||
-- @param #string To
|
-- @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.
|
-- @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, ... )
|
function CARGO_GROUP:onafterUnBoard( From, Event, To, ToPointVec2, NearRadius, ... )
|
||||||
self:T( {From, Event, To, ToPointVec2, NearRadius } )
|
self:T( {From, Event, To, ToPointVec2, NearRadius } )
|
||||||
@@ -453,7 +454,7 @@ do -- CARGO_GROUP
|
|||||||
-- @param #string Event
|
-- @param #string Event
|
||||||
-- @param #string From
|
-- @param #string From
|
||||||
-- @param #string To
|
-- @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.
|
-- @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, ... )
|
function CARGO_GROUP:onafterUnBoarding( From, Event, To, ToPointVec2, NearRadius, ... )
|
||||||
--self:T( { From, Event, To, ToPointVec2, NearRadius } )
|
--self:T( { From, Event, To, ToPointVec2, NearRadius } )
|
||||||
@@ -491,7 +492,7 @@ do -- CARGO_GROUP
|
|||||||
-- @param #string Event
|
-- @param #string Event
|
||||||
-- @param #string From
|
-- @param #string From
|
||||||
-- @param #string To
|
-- @param #string To
|
||||||
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
-- @param Core.Point#COORDINATE ToPointVec2
|
||||||
function CARGO_GROUP:onafterUnLoad( From, Event, To, ToPointVec2, ... )
|
function CARGO_GROUP:onafterUnLoad( From, Event, To, ToPointVec2, ... )
|
||||||
--self:T( { From, Event, To, ToPointVec2 } )
|
--self:T( { From, Event, To, ToPointVec2 } )
|
||||||
|
|
||||||
@@ -598,7 +599,7 @@ do -- CARGO_GROUP
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Get the amount of cargo units in the group.
|
--- Get the underlying GROUP object from the CARGO_GROUP.
|
||||||
-- @param #CARGO_GROUP self
|
-- @param #CARGO_GROUP self
|
||||||
-- @return #CARGO_GROUP
|
-- @return #CARGO_GROUP
|
||||||
function CARGO_GROUP:GetGroup( Cargo )
|
function CARGO_GROUP:GetGroup( Cargo )
|
||||||
@@ -771,3 +772,4 @@ do -- CARGO_GROUP
|
|||||||
|
|
||||||
|
|
||||||
end -- CARGO_GROUP
|
end -- CARGO_GROUP
|
||||||
|
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ do -- CARGO_SLINGLOAD
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- @param #CARGO_SLINGLOAD self
|
-- @param #CARGO_SLINGLOAD self
|
||||||
-- @param Core.Event#EVENTDATA EventData
|
-- @param Core.Event#EVENTDATA EventData
|
||||||
function CARGO_SLINGLOAD:OnEventCargoDead( EventData )
|
function CARGO_SLINGLOAD:OnEventCargoDead( EventData )
|
||||||
|
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ do -- CARGO_UNIT
|
|||||||
-- @param #string Event
|
-- @param #string Event
|
||||||
-- @param #string From
|
-- @param #string From
|
||||||
-- @param #string To
|
-- @param #string To
|
||||||
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
-- @param Core.Point#COORDINATE ToPointVec2
|
||||||
-- @param #number NearRadius (optional) Defaut 25 m.
|
-- @param #number NearRadius (optional) Defaut 25 m.
|
||||||
function CARGO_UNIT:onenterUnBoarding( From, Event, To, ToPointVec2, NearRadius )
|
function CARGO_UNIT:onenterUnBoarding( From, Event, To, ToPointVec2, NearRadius )
|
||||||
self:T( { From, Event, To, ToPointVec2, NearRadius } )
|
self:T( { From, Event, To, ToPointVec2, NearRadius } )
|
||||||
@@ -145,7 +145,7 @@ do -- CARGO_UNIT
|
|||||||
-- @param #string Event
|
-- @param #string Event
|
||||||
-- @param #string From
|
-- @param #string From
|
||||||
-- @param #string To
|
-- @param #string To
|
||||||
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
-- @param Core.Point#COORDINATE ToPointVec2
|
||||||
-- @param #number NearRadius (optional) Defaut 100 m.
|
-- @param #number NearRadius (optional) Defaut 100 m.
|
||||||
function CARGO_UNIT:onleaveUnBoarding( From, Event, To, ToPointVec2, NearRadius )
|
function CARGO_UNIT:onleaveUnBoarding( From, Event, To, ToPointVec2, NearRadius )
|
||||||
self:T( { From, Event, To, ToPointVec2, NearRadius } )
|
self:T( { From, Event, To, ToPointVec2, NearRadius } )
|
||||||
@@ -171,7 +171,7 @@ do -- CARGO_UNIT
|
|||||||
-- @param #string Event
|
-- @param #string Event
|
||||||
-- @param #string From
|
-- @param #string From
|
||||||
-- @param #string To
|
-- @param #string To
|
||||||
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
-- @param Core.Point#COORDINATE ToPointVec2
|
||||||
-- @param #number NearRadius (optional) Defaut 100 m.
|
-- @param #number NearRadius (optional) Defaut 100 m.
|
||||||
function CARGO_UNIT:onafterUnBoarding( From, Event, To, ToPointVec2, NearRadius )
|
function CARGO_UNIT:onafterUnBoarding( From, Event, To, ToPointVec2, NearRadius )
|
||||||
self:T( { From, Event, To, ToPointVec2, NearRadius } )
|
self:T( { From, Event, To, ToPointVec2, NearRadius } )
|
||||||
@@ -197,7 +197,7 @@ do -- CARGO_UNIT
|
|||||||
-- @param #string Event
|
-- @param #string Event
|
||||||
-- @param #string From
|
-- @param #string From
|
||||||
-- @param #string To
|
-- @param #string To
|
||||||
-- @param Core.Point#POINT_VEC2
|
-- @param Core.Point#COORDINATE
|
||||||
function CARGO_UNIT:onenterUnLoaded( From, Event, To, ToPointVec2 )
|
function CARGO_UNIT:onenterUnLoaded( From, Event, To, ToPointVec2 )
|
||||||
self:T( { ToPointVec2, From, Event, To } )
|
self:T( { ToPointVec2, From, Event, To } )
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
-- @module Core.Base
|
-- @module Core.Base
|
||||||
-- @image Core_Base.JPG
|
-- @image Core_Base.JPG
|
||||||
|
|
||||||
local _TraceOnOff = true
|
local _TraceOnOff = false -- default to no tracing
|
||||||
local _TraceLevel = 1
|
local _TraceLevel = 1
|
||||||
local _TraceAll = false
|
local _TraceAll = false
|
||||||
local _TraceClass = {}
|
local _TraceClass = {}
|
||||||
@@ -34,11 +34,12 @@ local _TraceClassMethod = {}
|
|||||||
|
|
||||||
local _ClassID = 0
|
local _ClassID = 0
|
||||||
|
|
||||||
---
|
--- Base class of everything
|
||||||
-- @type BASE
|
-- @type BASE
|
||||||
-- @field ClassName The name of the class.
|
-- @field #string ClassName The name of the class.
|
||||||
-- @field ClassID The ID number of the class.
|
-- @field #number ClassID The ID number of the class.
|
||||||
-- @field ClassNameAndID The name of the class concatenated with the ID number of the class.
|
-- @field #string ClassNameAndID The name of the class concatenated with the ID number of the class.
|
||||||
|
-- @field Core.Scheduler#SCHEDULER Scheduler The scheduler object.
|
||||||
|
|
||||||
--- BASE class
|
--- BASE class
|
||||||
--
|
--
|
||||||
@@ -200,6 +201,7 @@ BASE = {
|
|||||||
States = {},
|
States = {},
|
||||||
Debug = debug,
|
Debug = debug,
|
||||||
Scheduler = nil,
|
Scheduler = nil,
|
||||||
|
Properties = {},
|
||||||
}
|
}
|
||||||
|
|
||||||
-- @field #BASE.__
|
-- @field #BASE.__
|
||||||
@@ -210,14 +212,6 @@ BASE._ = {
|
|||||||
Schedules = {}, --- Contains the Schedulers Active
|
Schedules = {}, --- Contains the Schedulers Active
|
||||||
}
|
}
|
||||||
|
|
||||||
--- The Formation Class
|
|
||||||
-- @type FORMATION
|
|
||||||
-- @field Cone A cone formation.
|
|
||||||
FORMATION = {
|
|
||||||
Cone = "Cone",
|
|
||||||
Vee = "Vee",
|
|
||||||
}
|
|
||||||
|
|
||||||
--- BASE constructor.
|
--- BASE constructor.
|
||||||
--
|
--
|
||||||
-- This is an example how to use the BASE:New() constructor in a new class definition when inheriting from BASE.
|
-- This is an example how to use the BASE:New() constructor in a new class definition when inheriting from BASE.
|
||||||
@@ -741,7 +735,31 @@ do -- Event Handling
|
|||||||
-- @function [parent=#BASE] OnEventPlayerEnterAircraft
|
-- @function [parent=#BASE] OnEventPlayerEnterAircraft
|
||||||
-- @param #BASE self
|
-- @param #BASE self
|
||||||
-- @param Core.Event#EVENTDATA EventData The EventData structure.
|
-- @param Core.Event#EVENTDATA EventData The EventData structure.
|
||||||
|
|
||||||
|
--- Occurs when a player creates a dynamic cargo object from the F8 ground crew menu.
|
||||||
|
-- *** NOTE *** this is a workarounf for DCS not creating these events as of Aug 2024.
|
||||||
|
-- @function [parent=#BASE] OnEventNewDynamicCargo
|
||||||
|
-- @param #BASE self
|
||||||
|
-- @param Core.Event#EVENTDATA EventData The EventData structure.
|
||||||
|
|
||||||
|
--- Occurs when a player loads a dynamic cargo object with the F8 ground crew menu into a helo.
|
||||||
|
-- *** NOTE *** this is a workarounf for DCS not creating these events as of Aug 2024.
|
||||||
|
-- @function [parent=#BASE] OnEventDynamicCargoLoaded
|
||||||
|
-- @param #BASE self
|
||||||
|
-- @param Core.Event#EVENTDATA EventData The EventData structure.
|
||||||
|
|
||||||
|
--- Occurs when a player unloads a dynamic cargo object with the F8 ground crew menu from a helo.
|
||||||
|
-- *** NOTE *** this is a workarounf for DCS not creating these events as of Aug 2024.
|
||||||
|
-- @function [parent=#BASE] OnEventDynamicCargoUnloaded
|
||||||
|
-- @param #BASE self
|
||||||
|
-- @param Core.Event#EVENTDATA EventData The EventData structure.
|
||||||
|
|
||||||
|
--- Occurs when a dynamic cargo crate is removed.
|
||||||
|
-- *** NOTE *** this is a workarounf for DCS not creating these events as of Aug 2024.
|
||||||
|
-- @function [parent=#BASE] OnEventDynamicCargoRemoved
|
||||||
|
-- @param #BASE self
|
||||||
|
-- @param Core.Event#EVENTDATA EventData The EventData structure.
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Creation of a Birth Event.
|
--- Creation of a Birth Event.
|
||||||
@@ -862,6 +880,62 @@ end
|
|||||||
|
|
||||||
world.onEvent(Event)
|
world.onEvent(Event)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Creation of a S_EVENT_NEW_DYNAMIC_CARGO event.
|
||||||
|
-- @param #BASE self
|
||||||
|
-- @param Wrapper.DynamicCargo#DYNAMICCARGO DynamicCargo the dynamic cargo object
|
||||||
|
function BASE:CreateEventNewDynamicCargo(DynamicCargo)
|
||||||
|
self:F({DynamicCargo})
|
||||||
|
local Event = {
|
||||||
|
id = EVENTS.NewDynamicCargo,
|
||||||
|
time = timer.getTime(),
|
||||||
|
dynamiccargo = DynamicCargo,
|
||||||
|
initiator = DynamicCargo:GetDCSObject(),
|
||||||
|
}
|
||||||
|
world.onEvent( Event )
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Creation of a S_EVENT_DYNAMIC_CARGO_LOADED event.
|
||||||
|
-- @param #BASE self
|
||||||
|
-- @param Wrapper.DynamicCargo#DYNAMICCARGO DynamicCargo the dynamic cargo object
|
||||||
|
function BASE:CreateEventDynamicCargoLoaded(DynamicCargo)
|
||||||
|
self:F({DynamicCargo})
|
||||||
|
local Event = {
|
||||||
|
id = EVENTS.DynamicCargoLoaded,
|
||||||
|
time = timer.getTime(),
|
||||||
|
dynamiccargo = DynamicCargo,
|
||||||
|
initiator = DynamicCargo:GetDCSObject(),
|
||||||
|
}
|
||||||
|
world.onEvent( Event )
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Creation of a S_EVENT_DYNAMIC_CARGO_UNLOADED event.
|
||||||
|
-- @param #BASE self
|
||||||
|
-- @param Wrapper.DynamicCargo#DYNAMICCARGO DynamicCargo the dynamic cargo object
|
||||||
|
function BASE:CreateEventDynamicCargoUnloaded(DynamicCargo)
|
||||||
|
self:F({DynamicCargo})
|
||||||
|
local Event = {
|
||||||
|
id = EVENTS.DynamicCargoUnloaded,
|
||||||
|
time = timer.getTime(),
|
||||||
|
dynamiccargo = DynamicCargo,
|
||||||
|
initiator = DynamicCargo:GetDCSObject(),
|
||||||
|
}
|
||||||
|
world.onEvent( Event )
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Creation of a S_EVENT_DYNAMIC_CARGO_REMOVED event.
|
||||||
|
-- @param #BASE self
|
||||||
|
-- @param Wrapper.DynamicCargo#DYNAMICCARGO DynamicCargo the dynamic cargo object
|
||||||
|
function BASE:CreateEventDynamicCargoRemoved(DynamicCargo)
|
||||||
|
self:F({DynamicCargo})
|
||||||
|
local Event = {
|
||||||
|
id = EVENTS.DynamicCargoRemoved,
|
||||||
|
time = timer.getTime(),
|
||||||
|
dynamiccargo = DynamicCargo,
|
||||||
|
initiator = DynamicCargo:GetDCSObject(),
|
||||||
|
}
|
||||||
|
world.onEvent( Event )
|
||||||
|
end
|
||||||
|
|
||||||
--- The main event handling function... This function captures all events generated for the class.
|
--- The main event handling function... This function captures all events generated for the class.
|
||||||
-- @param #BASE self
|
-- @param #BASE self
|
||||||
@@ -1036,6 +1110,31 @@ function BASE:ClearState( Object, StateName )
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Set one property of an object.
|
||||||
|
-- @param #BASE self
|
||||||
|
-- @param Key The key that is used as a reference of the value. Note that the key can be a #string, but it can also be any other type!
|
||||||
|
-- @param Value The value that is stored. Note that the value can be a #string, but it can also be any other type!
|
||||||
|
function BASE:SetProperty(Key,Value)
|
||||||
|
self.Properties = self.Properties or {}
|
||||||
|
self.Properties[Key] = Value
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get one property of an object by the key.
|
||||||
|
-- @param #BASE self
|
||||||
|
-- @param Key The key that is used as a reference of the value. Note that the key can be a #string, but it can also be any other type!
|
||||||
|
-- @return Value The value that is stored. Note that the value can be a #string, but it can also be any other type! Nil if not found.
|
||||||
|
function BASE:GetProperty(Key)
|
||||||
|
self.Properties = self.Properties or {}
|
||||||
|
return self.Properties[Key]
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get all of the properties of an object in a table.
|
||||||
|
-- @param #BASE self
|
||||||
|
-- @return #table of values, indexed by keys.
|
||||||
|
function BASE:GetProperties()
|
||||||
|
return self.Properties
|
||||||
|
end
|
||||||
|
|
||||||
-- Trace section
|
-- Trace section
|
||||||
|
|
||||||
-- Log a trace (only shown when trace is on)
|
-- Log a trace (only shown when trace is on)
|
||||||
@@ -1200,7 +1299,7 @@ end
|
|||||||
-- @param Arguments A #table or any field.
|
-- @param Arguments A #table or any field.
|
||||||
function BASE:F( Arguments )
|
function BASE:F( Arguments )
|
||||||
|
|
||||||
if BASE.Debug and _TraceOnOff then
|
if BASE.Debug and _TraceOnOff == true then
|
||||||
local DebugInfoCurrent = BASE.Debug.getinfo( 2, "nl" )
|
local DebugInfoCurrent = BASE.Debug.getinfo( 2, "nl" )
|
||||||
local DebugInfoFrom = BASE.Debug.getinfo( 3, "l" )
|
local DebugInfoFrom = BASE.Debug.getinfo( 3, "l" )
|
||||||
|
|
||||||
@@ -1215,7 +1314,7 @@ end
|
|||||||
-- @param Arguments A #table or any field.
|
-- @param Arguments A #table or any field.
|
||||||
function BASE:F2( Arguments )
|
function BASE:F2( Arguments )
|
||||||
|
|
||||||
if BASE.Debug and _TraceOnOff then
|
if BASE.Debug and _TraceOnOff == true and _TraceLevel >= 2 then
|
||||||
local DebugInfoCurrent = BASE.Debug.getinfo( 2, "nl" )
|
local DebugInfoCurrent = BASE.Debug.getinfo( 2, "nl" )
|
||||||
local DebugInfoFrom = BASE.Debug.getinfo( 3, "l" )
|
local DebugInfoFrom = BASE.Debug.getinfo( 3, "l" )
|
||||||
|
|
||||||
@@ -1230,7 +1329,7 @@ end
|
|||||||
-- @param Arguments A #table or any field.
|
-- @param Arguments A #table or any field.
|
||||||
function BASE:F3( Arguments )
|
function BASE:F3( Arguments )
|
||||||
|
|
||||||
if BASE.Debug and _TraceOnOff then
|
if BASE.Debug and _TraceOnOff == true and _TraceLevel >= 3 then
|
||||||
local DebugInfoCurrent = BASE.Debug.getinfo( 2, "nl" )
|
local DebugInfoCurrent = BASE.Debug.getinfo( 2, "nl" )
|
||||||
local DebugInfoFrom = BASE.Debug.getinfo( 3, "l" )
|
local DebugInfoFrom = BASE.Debug.getinfo( 3, "l" )
|
||||||
|
|
||||||
@@ -1274,7 +1373,7 @@ end
|
|||||||
-- @param Arguments A #table or any field.
|
-- @param Arguments A #table or any field.
|
||||||
function BASE:T( Arguments )
|
function BASE:T( Arguments )
|
||||||
|
|
||||||
if BASE.Debug and _TraceOnOff then
|
if BASE.Debug and _TraceOnOff == true then
|
||||||
local DebugInfoCurrent = BASE.Debug.getinfo( 2, "nl" )
|
local DebugInfoCurrent = BASE.Debug.getinfo( 2, "nl" )
|
||||||
local DebugInfoFrom = BASE.Debug.getinfo( 3, "l" )
|
local DebugInfoFrom = BASE.Debug.getinfo( 3, "l" )
|
||||||
|
|
||||||
@@ -1289,7 +1388,7 @@ end
|
|||||||
-- @param Arguments A #table or any field.
|
-- @param Arguments A #table or any field.
|
||||||
function BASE:T2( Arguments )
|
function BASE:T2( Arguments )
|
||||||
|
|
||||||
if BASE.Debug and _TraceOnOff then
|
if BASE.Debug and _TraceOnOff == true and _TraceLevel >= 2 then
|
||||||
local DebugInfoCurrent = BASE.Debug.getinfo( 2, "nl" )
|
local DebugInfoCurrent = BASE.Debug.getinfo( 2, "nl" )
|
||||||
local DebugInfoFrom = BASE.Debug.getinfo( 3, "l" )
|
local DebugInfoFrom = BASE.Debug.getinfo( 3, "l" )
|
||||||
|
|
||||||
@@ -1304,7 +1403,7 @@ end
|
|||||||
-- @param Arguments A #table or any field.
|
-- @param Arguments A #table or any field.
|
||||||
function BASE:T3( Arguments )
|
function BASE:T3( Arguments )
|
||||||
|
|
||||||
if BASE.Debug and _TraceOnOff then
|
if BASE.Debug and _TraceOnOff == true and _TraceLevel >= 3 then
|
||||||
local DebugInfoCurrent = BASE.Debug.getinfo( 2, "nl" )
|
local DebugInfoCurrent = BASE.Debug.getinfo( 2, "nl" )
|
||||||
local DebugInfoFrom = BASE.Debug.getinfo( 3, "l" )
|
local DebugInfoFrom = BASE.Debug.getinfo( 3, "l" )
|
||||||
|
|
||||||
@@ -1336,7 +1435,7 @@ function BASE:E( Arguments )
|
|||||||
|
|
||||||
env.info( string.format( "%6d(%6d)/%1s:%30s%05d.%s(%s)", LineCurrent, LineFrom, "E", self.ClassName, self.ClassID, Function, UTILS.BasicSerialize( Arguments ) ) )
|
env.info( string.format( "%6d(%6d)/%1s:%30s%05d.%s(%s)", LineCurrent, LineFrom, "E", self.ClassName, self.ClassID, Function, UTILS.BasicSerialize( Arguments ) ) )
|
||||||
else
|
else
|
||||||
env.info( string.format( "%1s:%30s%05d(%s)", "E", self.ClassName, self.ClassID, BASE:_Serialize(Arguments) ) )
|
env.info( string.format( "%1s:%30s%05d(%s)", "E", self.ClassName, self.ClassID, UTILS.BasicSerialize(Arguments) ) )
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
@@ -1363,8 +1462,7 @@ function BASE:I( Arguments )
|
|||||||
|
|
||||||
env.info( string.format( "%6d(%6d)/%1s:%30s%05d.%s(%s)", LineCurrent, LineFrom, "I", self.ClassName, self.ClassID, Function, UTILS.BasicSerialize( Arguments ) ) )
|
env.info( string.format( "%6d(%6d)/%1s:%30s%05d.%s(%s)", LineCurrent, LineFrom, "I", self.ClassName, self.ClassID, Function, UTILS.BasicSerialize( Arguments ) ) )
|
||||||
else
|
else
|
||||||
env.info( string.format( "%1s:%30s%05d(%s)", "I", self.ClassName, self.ClassID, BASE:_Serialize(Arguments)) )
|
env.info( string.format( "%1s:%30s%05d(%s)", "I", self.ClassName, self.ClassID, UTILS.BasicSerialize(Arguments)) )
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
--
|
--
|
||||||
-- @module Core.ClientMenu
|
-- @module Core.ClientMenu
|
||||||
-- @image Core_Menu.JPG
|
-- @image Core_Menu.JPG
|
||||||
-- last change: May 2024
|
-- last change: Jan 2025
|
||||||
|
|
||||||
-- TODO
|
-- TODO
|
||||||
----------------------------------------------------------------------------------------------------------------
|
----------------------------------------------------------------------------------------------------------------
|
||||||
@@ -57,9 +57,9 @@
|
|||||||
---
|
---
|
||||||
-- @field #CLIENTMENU
|
-- @field #CLIENTMENU
|
||||||
CLIENTMENU = {
|
CLIENTMENU = {
|
||||||
ClassName = "CLIENTMENUE",
|
ClassName = "CLIENTMENU",
|
||||||
lid = "",
|
lid = "",
|
||||||
version = "0.1.2",
|
version = "0.1.3",
|
||||||
name = nil,
|
name = nil,
|
||||||
path = nil,
|
path = nil,
|
||||||
group = nil,
|
group = nil,
|
||||||
@@ -417,7 +417,7 @@ end
|
|||||||
CLIENTMENUMANAGER = {
|
CLIENTMENUMANAGER = {
|
||||||
ClassName = "CLIENTMENUMANAGER",
|
ClassName = "CLIENTMENUMANAGER",
|
||||||
lid = "",
|
lid = "",
|
||||||
version = "0.1.5a",
|
version = "0.1.6",
|
||||||
name = nil,
|
name = nil,
|
||||||
clientset = nil,
|
clientset = nil,
|
||||||
menutree = {},
|
menutree = {},
|
||||||
@@ -455,7 +455,7 @@ end
|
|||||||
-- @param #CLIENTMENUMANAGER self
|
-- @param #CLIENTMENUMANAGER self
|
||||||
-- @param Core.Event#EVENTDATA EventData
|
-- @param Core.Event#EVENTDATA EventData
|
||||||
-- @return #CLIENTMENUMANAGER self
|
-- @return #CLIENTMENUMANAGER self
|
||||||
function CLIENTMENUMANAGER:_EventHandler(EventData)
|
function CLIENTMENUMANAGER:_EventHandler(EventData,Retry)
|
||||||
self:T(self.lid.."_EventHandler: "..EventData.id)
|
self:T(self.lid.."_EventHandler: "..EventData.id)
|
||||||
--self:I(self.lid.."_EventHandler: "..tostring(EventData.IniPlayerName))
|
--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
|
if EventData.id == EVENTS.PlayerLeaveUnit or EventData.id == EVENTS.Ejection or EventData.id == EVENTS.Crash or EventData.id == EVENTS.PilotDead then
|
||||||
@@ -468,6 +468,10 @@ function CLIENTMENUMANAGER:_EventHandler(EventData)
|
|||||||
if EventData.IniPlayerName and EventData.IniGroup then
|
if EventData.IniPlayerName and EventData.IniGroup then
|
||||||
if (not self.clientset:IsIncludeObject(_DATABASE:FindClient( EventData.IniUnitName ))) then
|
if (not self.clientset:IsIncludeObject(_DATABASE:FindClient( EventData.IniUnitName ))) then
|
||||||
self:T(self.lid.."Client not in SET: "..EventData.IniPlayerName)
|
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
|
return self
|
||||||
end
|
end
|
||||||
--self:I(self.lid.."Join event for player: "..EventData.IniPlayerName)
|
--self:I(self.lid.."Join event for player: "..EventData.IniPlayerName)
|
||||||
@@ -524,7 +528,7 @@ function CLIENTMENUMANAGER:InitAutoPropagation()
|
|||||||
self:HandleEvent(EVENTS.PilotDead, self._EventHandler)
|
self:HandleEvent(EVENTS.PilotDead, self._EventHandler)
|
||||||
self:HandleEvent(EVENTS.PlayerEnterAircraft, self._EventHandler)
|
self:HandleEvent(EVENTS.PlayerEnterAircraft, self._EventHandler)
|
||||||
self:HandleEvent(EVENTS.PlayerEnterUnit, self._EventHandler)
|
self:HandleEvent(EVENTS.PlayerEnterUnit, self._EventHandler)
|
||||||
self:SetEventPriority(5)
|
self:SetEventPriority(6)
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -740,7 +744,7 @@ function CLIENTMENUMANAGER:AddEntry(Entry,Client)
|
|||||||
for _,_client in pairs(Set) do
|
for _,_client in pairs(Set) do
|
||||||
local client = _client -- Wrapper.Client#CLIENT
|
local client = _client -- Wrapper.Client#CLIENT
|
||||||
if client and client:IsAlive() then
|
if client and client:IsAlive() then
|
||||||
local playername = client:GetPlayerName()
|
local playername = client:GetPlayerName() or "None"
|
||||||
local unitname = client:GetName()
|
local unitname = client:GetName()
|
||||||
if not knownunits[unitname] then
|
if not knownunits[unitname] then
|
||||||
knownunits[unitname] = true
|
knownunits[unitname] = true
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
-- * Manage database of hits to units and statics.
|
-- * Manage database of hits to units and statics.
|
||||||
-- * Manage database of destroys of units and statics.
|
-- * Manage database of destroys of units and statics.
|
||||||
-- * Manage database of @{Core.Zone#ZONE_BASE} objects.
|
-- * Manage database of @{Core.Zone#ZONE_BASE} objects.
|
||||||
|
-- * Manage database of @{Wrapper.DynamicCargo#DYNAMICCARGO} objects alive in the mission.
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
@@ -39,6 +40,7 @@
|
|||||||
-- @field #table STORAGES DCS warehouse storages.
|
-- @field #table STORAGES DCS warehouse storages.
|
||||||
-- @field #table STNS Used Link16 octal numbers for F16/15/18/AWACS planes.
|
-- @field #table STNS Used Link16 octal numbers for F16/15/18/AWACS planes.
|
||||||
-- @field #table SADL Used Link16 octal numbers for A10/C-II planes.
|
-- @field #table SADL Used Link16 octal numbers for A10/C-II planes.
|
||||||
|
-- @field #table DYNAMICCARGO Dynamic Cargo objects.
|
||||||
-- @extends Core.Base#BASE
|
-- @extends Core.Base#BASE
|
||||||
|
|
||||||
--- Contains collections of wrapper objects defined within MOOSE that reflect objects within the simulator.
|
--- Contains collections of wrapper objects defined within MOOSE that reflect objects within the simulator.
|
||||||
@@ -54,6 +56,7 @@
|
|||||||
-- * PLAYERS
|
-- * PLAYERS
|
||||||
-- * CARGOS
|
-- * CARGOS
|
||||||
-- * STORAGES (DCS warehouses)
|
-- * STORAGES (DCS warehouses)
|
||||||
|
-- * DYNAMICCARGO
|
||||||
--
|
--
|
||||||
-- On top, for internal MOOSE administration purposes, the DATABASE administers the Unit and Group TEMPLATES as defined within the Mission Editor.
|
-- On top, for internal MOOSE administration purposes, the DATABASE administers the Unit and Group TEMPLATES as defined within the Mission Editor.
|
||||||
--
|
--
|
||||||
@@ -97,6 +100,7 @@ DATABASE = {
|
|||||||
STORAGES = {},
|
STORAGES = {},
|
||||||
STNS={},
|
STNS={},
|
||||||
SADL={},
|
SADL={},
|
||||||
|
DYNAMICCARGO={},
|
||||||
}
|
}
|
||||||
|
|
||||||
local _DATABASECoalition =
|
local _DATABASECoalition =
|
||||||
@@ -135,7 +139,7 @@ function DATABASE:New()
|
|||||||
self:HandleEvent( EVENTS.Dead, self._EventOnDeadOrCrash )
|
self:HandleEvent( EVENTS.Dead, self._EventOnDeadOrCrash )
|
||||||
self:HandleEvent( EVENTS.Crash, self._EventOnDeadOrCrash )
|
self:HandleEvent( EVENTS.Crash, self._EventOnDeadOrCrash )
|
||||||
self:HandleEvent( EVENTS.RemoveUnit, self._EventOnDeadOrCrash )
|
self:HandleEvent( EVENTS.RemoveUnit, self._EventOnDeadOrCrash )
|
||||||
--self:HandleEvent( EVENTS.UnitLost, self._EventOnDeadOrCrash ) -- DCS 2.7.1 for Aerial units no dead event ATM
|
self:HandleEvent( EVENTS.UnitLost, self._EventOnDeadOrCrash ) -- DCS 2.7.1 for Aerial units no dead event ATM
|
||||||
self:HandleEvent( EVENTS.Hit, self.AccountHits )
|
self:HandleEvent( EVENTS.Hit, self.AccountHits )
|
||||||
self:HandleEvent( EVENTS.NewCargo )
|
self:HandleEvent( EVENTS.NewCargo )
|
||||||
self:HandleEvent( EVENTS.DeleteCargo )
|
self:HandleEvent( EVENTS.DeleteCargo )
|
||||||
@@ -143,6 +147,8 @@ function DATABASE:New()
|
|||||||
self:HandleEvent( EVENTS.DeleteZone )
|
self:HandleEvent( EVENTS.DeleteZone )
|
||||||
--self:HandleEvent( EVENTS.PlayerEnterUnit, self._EventOnPlayerEnterUnit ) -- This is not working anymore!, handling this through the birth event.
|
--self:HandleEvent( EVENTS.PlayerEnterUnit, self._EventOnPlayerEnterUnit ) -- This is not working anymore!, handling this through the birth event.
|
||||||
self:HandleEvent( EVENTS.PlayerLeaveUnit, self._EventOnPlayerLeaveUnit )
|
self:HandleEvent( EVENTS.PlayerLeaveUnit, self._EventOnPlayerLeaveUnit )
|
||||||
|
-- DCS 2.9.7 Moose own dynamic cargo events
|
||||||
|
self:HandleEvent( EVENTS.DynamicCargoRemoved, self._EventOnDynamicCargoRemoved)
|
||||||
|
|
||||||
self:_RegisterTemplates()
|
self:_RegisterTemplates()
|
||||||
self:_RegisterGroupsAndUnits()
|
self:_RegisterGroupsAndUnits()
|
||||||
@@ -170,24 +176,30 @@ end
|
|||||||
--- Adds a Unit based on the Unit Name in the DATABASE.
|
--- Adds a Unit based on the Unit Name in the DATABASE.
|
||||||
-- @param #DATABASE self
|
-- @param #DATABASE self
|
||||||
-- @param #string DCSUnitName Unit name.
|
-- @param #string DCSUnitName Unit name.
|
||||||
|
-- @param #boolean force
|
||||||
-- @return Wrapper.Unit#UNIT The added unit.
|
-- @return Wrapper.Unit#UNIT The added unit.
|
||||||
function DATABASE:AddUnit( DCSUnitName )
|
function DATABASE:AddUnit( DCSUnitName, force )
|
||||||
|
|
||||||
if not self.UNITS[DCSUnitName] then
|
local DCSunitName = DCSUnitName
|
||||||
|
|
||||||
|
if type(DCSunitName) == "number" then DCSunitName = string.format("%d",DCSUnitName) end
|
||||||
|
|
||||||
|
if not self.UNITS[DCSunitName] or force == true then
|
||||||
-- Debug info.
|
-- Debug info.
|
||||||
self:T( { "Add UNIT:", DCSUnitName } )
|
self:T( { "Add UNIT:", DCSunitName } )
|
||||||
|
|
||||||
-- Register unit
|
-- Register unit
|
||||||
self.UNITS[DCSUnitName]=UNIT:Register(DCSUnitName)
|
self.UNITS[DCSunitName]=UNIT:Register(DCSunitName)
|
||||||
end
|
end
|
||||||
|
|
||||||
return self.UNITS[DCSUnitName]
|
return self.UNITS[DCSunitName]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Deletes a Unit from the DATABASE based on the Unit Name.
|
--- Deletes a Unit from the DATABASE based on the Unit Name.
|
||||||
-- @param #DATABASE self
|
-- @param #DATABASE self
|
||||||
function DATABASE:DeleteUnit( DCSUnitName )
|
function DATABASE:DeleteUnit( DCSUnitName )
|
||||||
|
self:T("DeleteUnit "..tostring(DCSUnitName))
|
||||||
self.UNITS[DCSUnitName] = nil
|
self.UNITS[DCSUnitName] = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -199,10 +211,9 @@ function DATABASE:AddStatic( DCSStaticName )
|
|||||||
|
|
||||||
if not self.STATICS[DCSStaticName] then
|
if not self.STATICS[DCSStaticName] then
|
||||||
self.STATICS[DCSStaticName] = STATIC:Register( DCSStaticName )
|
self.STATICS[DCSStaticName] = STATIC:Register( DCSStaticName )
|
||||||
return self.STATICS[DCSStaticName]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return nil
|
return self.STATICS[DCSStaticName]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -212,16 +223,42 @@ function DATABASE:DeleteStatic( DCSStaticName )
|
|||||||
self.STATICS[DCSStaticName] = nil
|
self.STATICS[DCSStaticName] = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Finds a STATIC based on the StaticName.
|
--- Finds a STATIC based on the Static Name.
|
||||||
-- @param #DATABASE self
|
-- @param #DATABASE self
|
||||||
-- @param #string StaticName
|
-- @param #string StaticName Name of the static object.
|
||||||
-- @return Wrapper.Static#STATIC The found STATIC.
|
-- @return Wrapper.Static#STATIC The found STATIC.
|
||||||
function DATABASE:FindStatic( StaticName )
|
function DATABASE:FindStatic( StaticName )
|
||||||
|
|
||||||
local StaticFound = self.STATICS[StaticName]
|
local StaticFound = self.STATICS[StaticName]
|
||||||
return StaticFound
|
return StaticFound
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Add a DynamicCargo to the database.
|
||||||
|
-- @param #DATABASE self
|
||||||
|
-- @param #string Name Name of the dynamic cargo.
|
||||||
|
-- @return Wrapper.DynamicCargo#DYNAMICCARGO The dynamic cargo object.
|
||||||
|
function DATABASE:AddDynamicCargo( Name )
|
||||||
|
if not self.DYNAMICCARGO[Name] then
|
||||||
|
self.DYNAMICCARGO[Name] = DYNAMICCARGO:Register(Name)
|
||||||
|
end
|
||||||
|
return self.DYNAMICCARGO[Name]
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Finds a DYNAMICCARGO based on the Dynamic Cargo Name.
|
||||||
|
-- @param #DATABASE self
|
||||||
|
-- @param #string DynamicCargoName
|
||||||
|
-- @return Wrapper.DynamicCargo#DYNAMICCARGO The found DYNAMICCARGO.
|
||||||
|
function DATABASE:FindDynamicCargo( DynamicCargoName )
|
||||||
|
local StaticFound = self.DYNAMICCARGO[DynamicCargoName]
|
||||||
|
return StaticFound
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Deletes a DYNAMICCARGO from the DATABASE based on the Dynamic Cargo Name.
|
||||||
|
-- @param #DATABASE self
|
||||||
|
function DATABASE:DeleteDynamicCargo( DynamicCargoName )
|
||||||
|
self.DYNAMICCARGO[DynamicCargoName] = nil
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- Adds a Airbase based on the Airbase Name in the DATABASE.
|
--- Adds a Airbase based on the Airbase Name in the DATABASE.
|
||||||
-- @param #DATABASE self
|
-- @param #DATABASE self
|
||||||
-- @param #string AirbaseName The name of the airbase.
|
-- @param #string AirbaseName The name of the airbase.
|
||||||
@@ -813,14 +850,19 @@ end
|
|||||||
--- Adds a CLIENT based on the ClientName in the DATABASE.
|
--- Adds a CLIENT based on the ClientName in the DATABASE.
|
||||||
-- @param #DATABASE self
|
-- @param #DATABASE self
|
||||||
-- @param #string ClientName Name of the Client unit.
|
-- @param #string ClientName Name of the Client unit.
|
||||||
|
-- @param #boolean Force (optional) Force registration of client.
|
||||||
-- @return Wrapper.Client#CLIENT The client object.
|
-- @return Wrapper.Client#CLIENT The client object.
|
||||||
function DATABASE:AddClient( ClientName )
|
function DATABASE:AddClient( ClientName, Force )
|
||||||
|
|
||||||
if not self.CLIENTS[ClientName] then
|
local DCSUnitName = ClientName
|
||||||
self.CLIENTS[ClientName] = CLIENT:Register( ClientName )
|
|
||||||
|
if type(DCSUnitName) == "number" then DCSUnitName = string.format("%d",ClientName) end
|
||||||
|
|
||||||
|
if not self.CLIENTS[DCSUnitName] or Force == true then
|
||||||
|
self.CLIENTS[DCSUnitName] = CLIENT:Register( DCSUnitName )
|
||||||
end
|
end
|
||||||
|
|
||||||
return self.CLIENTS[ClientName]
|
return self.CLIENTS[DCSUnitName]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -831,15 +873,25 @@ end
|
|||||||
function DATABASE:FindGroup( GroupName )
|
function DATABASE:FindGroup( GroupName )
|
||||||
|
|
||||||
local GroupFound = self.GROUPS[GroupName]
|
local GroupFound = self.GROUPS[GroupName]
|
||||||
|
|
||||||
|
if GroupFound == nil and GroupName ~= nil and self.Templates.Groups[GroupName] == nil then
|
||||||
|
-- see if the group exists in the API, maybe a dynamic slot
|
||||||
|
self:_RegisterDynamicGroup(GroupName)
|
||||||
|
return self.GROUPS[GroupName]
|
||||||
|
end
|
||||||
|
|
||||||
return GroupFound
|
return GroupFound
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Adds a GROUP based on the GroupName in the DATABASE.
|
--- Adds a GROUP based on the GroupName in the DATABASE.
|
||||||
-- @param #DATABASE self
|
-- @param #DATABASE self
|
||||||
function DATABASE:AddGroup( GroupName )
|
-- @param #string GroupName
|
||||||
|
-- @param #boolean force
|
||||||
|
-- @return Wrapper.Group#GROUP The Group
|
||||||
|
function DATABASE:AddGroup( GroupName, force )
|
||||||
|
|
||||||
if not self.GROUPS[GroupName] then
|
if not self.GROUPS[GroupName] or force == true then
|
||||||
self:T( { "Add GROUP:", GroupName } )
|
self:T( { "Add GROUP:", GroupName } )
|
||||||
self.GROUPS[GroupName] = GROUP:Register( GroupName )
|
self.GROUPS[GroupName] = GROUP:Register( GroupName )
|
||||||
end
|
end
|
||||||
@@ -850,9 +902,11 @@ end
|
|||||||
--- Adds a player based on the Player Name in the DATABASE.
|
--- Adds a player based on the Player Name in the DATABASE.
|
||||||
-- @param #DATABASE self
|
-- @param #DATABASE self
|
||||||
function DATABASE:AddPlayer( UnitName, PlayerName )
|
function DATABASE:AddPlayer( UnitName, PlayerName )
|
||||||
|
|
||||||
|
if type(UnitName) == "number" then UnitName = string.format("%d",UnitName) end
|
||||||
|
|
||||||
if PlayerName then
|
if PlayerName then
|
||||||
self:T( { "Add player for unit:", UnitName, PlayerName } )
|
self:I( { "Add player for unit:", UnitName, PlayerName } )
|
||||||
self.PLAYERS[PlayerName] = UnitName
|
self.PLAYERS[PlayerName] = UnitName
|
||||||
self.PLAYERUNITS[PlayerName] = self:FindUnit( UnitName )
|
self.PLAYERUNITS[PlayerName] = self:FindUnit( UnitName )
|
||||||
self.PLAYERSJOINED[PlayerName] = PlayerName
|
self.PLAYERSJOINED[PlayerName] = PlayerName
|
||||||
@@ -860,6 +914,21 @@ function DATABASE:AddPlayer( UnitName, PlayerName )
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Get a PlayerName by UnitName from PLAYERS in DATABASE.
|
||||||
|
-- @param #DATABASE self
|
||||||
|
-- @return #string PlayerName
|
||||||
|
-- @return Wrapper.Unit#UNIT PlayerUnit
|
||||||
|
function DATABASE:_FindPlayerNameByUnitName(UnitName)
|
||||||
|
if UnitName then
|
||||||
|
for playername,unitname in pairs(self.PLAYERS) do
|
||||||
|
if unitname == UnitName and self.PLAYERUNITS[playername] and self.PLAYERUNITS[playername]:IsAlive() then
|
||||||
|
return playername, self.PLAYERUNITS[playername]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
--- Deletes a player from the DATABASE based on the Player Name.
|
--- Deletes a player from the DATABASE based on the Player Name.
|
||||||
-- @param #DATABASE self
|
-- @param #DATABASE self
|
||||||
function DATABASE:DeletePlayer( UnitName, PlayerName )
|
function DATABASE:DeletePlayer( UnitName, PlayerName )
|
||||||
@@ -1198,6 +1267,43 @@ function DATABASE:_RegisterStaticTemplate( StaticTemplate, CoalitionID, Category
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Get a generic static cargo group template from scratch for dynamic cargo spawns register. Does not register the template!
|
||||||
|
-- @param #DATABASE self
|
||||||
|
-- @param #string Name Name of the static.
|
||||||
|
-- @param #string Typename Typename of the static. Defaults to "container_cargo".
|
||||||
|
-- @param #number Mass Mass of the static. Defaults to 0.
|
||||||
|
-- @param #number Coalition Coalition of the static. Defaults to coalition.side.BLUE.
|
||||||
|
-- @param #number Country Country of the static. Defaults to country.id.GERMANY.
|
||||||
|
-- @return #table Static template table.
|
||||||
|
function DATABASE:_GetGenericStaticCargoGroupTemplate(Name,Typename,Mass,Coalition,Country)
|
||||||
|
local StaticTemplate = {}
|
||||||
|
StaticTemplate.name = Name or "None"
|
||||||
|
StaticTemplate.units = { [1] = {
|
||||||
|
name = Name,
|
||||||
|
resourcePayload = {
|
||||||
|
["weapons"] = {},
|
||||||
|
["aircrafts"] = {},
|
||||||
|
["gasoline"] = 0,
|
||||||
|
["diesel"] = 0,
|
||||||
|
["methanol_mixture"] = 0,
|
||||||
|
["jet_fuel"] = 0,
|
||||||
|
},
|
||||||
|
["mass"] = Mass or 0,
|
||||||
|
["category"] = "Cargos",
|
||||||
|
["canCargo"] = true,
|
||||||
|
["type"] = Typename or "container_cargo",
|
||||||
|
["rate"] = 100,
|
||||||
|
["y"] = 0,
|
||||||
|
["x"] = 0,
|
||||||
|
["heading"] = 0,
|
||||||
|
}}
|
||||||
|
StaticTemplate.CategoryID = "static"
|
||||||
|
StaticTemplate.CoalitionID = Coalition or coalition.side.BLUE
|
||||||
|
StaticTemplate.CountryID = Country or country.id.GERMANY
|
||||||
|
--UTILS.PrintTableToLog(StaticTemplate)
|
||||||
|
return StaticTemplate
|
||||||
|
end
|
||||||
|
|
||||||
--- Get static group template.
|
--- Get static group template.
|
||||||
-- @param #DATABASE self
|
-- @param #DATABASE self
|
||||||
-- @param #string StaticName Name of the static.
|
-- @param #string StaticName Name of the static.
|
||||||
@@ -1274,7 +1380,7 @@ function DATABASE:GetCoalitionFromClientTemplate( ClientName )
|
|||||||
if self.Templates.ClientsByName[ClientName] then
|
if self.Templates.ClientsByName[ClientName] then
|
||||||
return self.Templates.ClientsByName[ClientName].CoalitionID
|
return self.Templates.ClientsByName[ClientName].CoalitionID
|
||||||
end
|
end
|
||||||
self:E("ERROR: Template does not exist for client "..tostring(ClientName))
|
self:E("WARNING: Template does not exist for client "..tostring(ClientName))
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1286,7 +1392,7 @@ function DATABASE:GetCategoryFromClientTemplate( ClientName )
|
|||||||
if self.Templates.ClientsByName[ClientName] then
|
if self.Templates.ClientsByName[ClientName] then
|
||||||
return self.Templates.ClientsByName[ClientName].CategoryID
|
return self.Templates.ClientsByName[ClientName].CategoryID
|
||||||
end
|
end
|
||||||
self:E("ERROR: Template does not exist for client "..tostring(ClientName))
|
self:E("WARNING: Template does not exist for client "..tostring(ClientName))
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1298,7 +1404,7 @@ function DATABASE:GetCountryFromClientTemplate( ClientName )
|
|||||||
if self.Templates.ClientsByName[ClientName] then
|
if self.Templates.ClientsByName[ClientName] then
|
||||||
return self.Templates.ClientsByName[ClientName].CountryID
|
return self.Templates.ClientsByName[ClientName].CountryID
|
||||||
end
|
end
|
||||||
self:E("ERROR: Template does not exist for client "..tostring(ClientName))
|
self:E("WARNING: Template does not exist for client "..tostring(ClientName))
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1345,6 +1451,36 @@ function DATABASE:_RegisterPlayers()
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Private method that registers a single dynamic slot Group and Units within in the mission.
|
||||||
|
-- @param #DATABASE self
|
||||||
|
-- @return #DATABASE self
|
||||||
|
function DATABASE:_RegisterDynamicGroup(Groupname)
|
||||||
|
local DCSGroup = Group.getByName(Groupname)
|
||||||
|
if DCSGroup and DCSGroup:isExist() then
|
||||||
|
|
||||||
|
-- Group name.
|
||||||
|
local DCSGroupName = DCSGroup:getName()
|
||||||
|
|
||||||
|
-- Add group.
|
||||||
|
self:I(string.format("Register Group: %s", tostring(DCSGroupName)))
|
||||||
|
self:AddGroup( DCSGroupName, true )
|
||||||
|
|
||||||
|
-- Loop over units in group.
|
||||||
|
for DCSUnitId, DCSUnit in pairs( DCSGroup:getUnits() ) do
|
||||||
|
|
||||||
|
-- Get unit name.
|
||||||
|
local DCSUnitName = DCSUnit:getName()
|
||||||
|
|
||||||
|
-- Add unit.
|
||||||
|
self:I(string.format("Register Unit: %s", tostring(DCSUnitName)))
|
||||||
|
self:AddUnit( tostring(DCSUnitName), true )
|
||||||
|
|
||||||
|
end
|
||||||
|
else
|
||||||
|
self:E({"Group does not exist: ", DCSGroup})
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- Private method that registers all Groups and Units within in the mission.
|
--- Private method that registers all Groups and Units within in the mission.
|
||||||
-- @param #DATABASE self
|
-- @param #DATABASE self
|
||||||
@@ -1443,12 +1579,29 @@ end
|
|||||||
-- @param DCS#Airbase airbase Airbase.
|
-- @param DCS#Airbase airbase Airbase.
|
||||||
-- @return #DATABASE self
|
-- @return #DATABASE self
|
||||||
function DATABASE:_RegisterAirbase(airbase)
|
function DATABASE:_RegisterAirbase(airbase)
|
||||||
|
|
||||||
|
local IsSyria = UTILS.GetDCSMap() == "Syria" and true or false
|
||||||
|
local countHSyria = 0
|
||||||
|
|
||||||
if airbase then
|
if airbase then
|
||||||
|
|
||||||
-- Get the airbase name.
|
-- Get the airbase name.
|
||||||
local DCSAirbaseName = airbase:getName()
|
local DCSAirbaseName = airbase:getName()
|
||||||
|
|
||||||
|
-- DCS 2.9.8.1107 added 143 helipads all named H with the same object ID ..
|
||||||
|
if IsSyria and DCSAirbaseName == "H" and countHSyria > 0 then
|
||||||
|
--[[
|
||||||
|
local p = airbase:getPosition().p
|
||||||
|
local mgrs = COORDINATE:New(p.x,p.z,p.y):ToStringMGRS()
|
||||||
|
self:I("Airbase on Syria map named H @ "..mgrs)
|
||||||
|
countHSyria = countHSyria + 1
|
||||||
|
if countHSyria > 1 then return self end
|
||||||
|
--]]
|
||||||
|
return self
|
||||||
|
elseif IsSyria and DCSAirbaseName == "H" and countHSyria == 0 then
|
||||||
|
countHSyria = countHSyria + 1
|
||||||
|
end
|
||||||
|
|
||||||
-- This gave the incorrect value to be inserted into the airdromeID for DCS 2.5.6. Is fixed now.
|
-- This gave the incorrect value to be inserted into the airdromeID for DCS 2.5.6. Is fixed now.
|
||||||
local airbaseID=airbase:getID()
|
local airbaseID=airbase:getID()
|
||||||
|
|
||||||
@@ -1488,7 +1641,7 @@ end
|
|||||||
-- @param #DATABASE self
|
-- @param #DATABASE self
|
||||||
-- @param Core.Event#EVENTDATA Event
|
-- @param Core.Event#EVENTDATA Event
|
||||||
function DATABASE:_EventOnBirth( Event )
|
function DATABASE:_EventOnBirth( Event )
|
||||||
self:F( { Event } )
|
self:T( { Event } )
|
||||||
|
|
||||||
if Event.IniDCSUnit then
|
if Event.IniDCSUnit then
|
||||||
|
|
||||||
@@ -1496,7 +1649,17 @@ function DATABASE:_EventOnBirth( Event )
|
|||||||
|
|
||||||
-- Add static object to DB.
|
-- Add static object to DB.
|
||||||
self:AddStatic( Event.IniDCSUnitName )
|
self:AddStatic( Event.IniDCSUnitName )
|
||||||
|
|
||||||
|
elseif Event.IniObjectCategory == Object.Category.CARGO and string.match(Event.IniUnitName,".+|%d%d:%d%d|PKG%d+") then
|
||||||
|
|
||||||
|
-- Add dynamic cargo object to DB
|
||||||
|
|
||||||
|
local cargo = self:AddDynamicCargo(Event.IniDCSUnitName)
|
||||||
|
|
||||||
|
self:I(string.format("Adding dynamic cargo %s", tostring(Event.IniDCSUnitName)))
|
||||||
|
|
||||||
|
self:CreateEventNewDynamicCargo( cargo )
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
if Event.IniObjectCategory == Object.Category.UNIT then
|
if Event.IniObjectCategory == Object.Category.UNIT then
|
||||||
@@ -1517,9 +1680,9 @@ function DATABASE:_EventOnBirth( Event )
|
|||||||
end
|
end
|
||||||
|
|
||||||
if Event.IniObjectCategory == Object.Category.UNIT then
|
if Event.IniObjectCategory == Object.Category.UNIT then
|
||||||
|
|
||||||
Event.IniUnit = self:FindUnit( Event.IniDCSUnitName )
|
|
||||||
Event.IniGroup = self:FindGroup( Event.IniDCSGroupName )
|
Event.IniGroup = self:FindGroup( Event.IniDCSGroupName )
|
||||||
|
Event.IniUnit = self:FindUnit( Event.IniDCSUnitName )
|
||||||
|
|
||||||
-- Client
|
-- Client
|
||||||
local client=self.CLIENTS[Event.IniDCSUnitName] --Wrapper.Client#CLIENT
|
local client=self.CLIENTS[Event.IniDCSUnitName] --Wrapper.Client#CLIENT
|
||||||
@@ -1535,10 +1698,10 @@ function DATABASE:_EventOnBirth( Event )
|
|||||||
|
|
||||||
-- Debug info.
|
-- Debug info.
|
||||||
self:I(string.format("Player '%s' joined unit '%s' of group '%s'", tostring(PlayerName), tostring(Event.IniDCSUnitName), tostring(Event.IniDCSGroupName)))
|
self:I(string.format("Player '%s' joined unit '%s' of group '%s'", tostring(PlayerName), tostring(Event.IniDCSUnitName), tostring(Event.IniDCSGroupName)))
|
||||||
|
|
||||||
-- Add client in case it does not exist already.
|
-- Add client in case it does not exist already.
|
||||||
if not client then
|
if client == nil or (client and client:CountPlayers() == 0) then
|
||||||
client=self:AddClient(Event.IniDCSUnitName)
|
client=self:AddClient(Event.IniDCSUnitName, true)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Add player.
|
-- Add player.
|
||||||
@@ -1548,14 +1711,19 @@ function DATABASE:_EventOnBirth( Event )
|
|||||||
if not self.PLAYERS[PlayerName] then
|
if not self.PLAYERS[PlayerName] then
|
||||||
self:AddPlayer( Event.IniUnitName, PlayerName )
|
self:AddPlayer( Event.IniUnitName, PlayerName )
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Player settings.
|
local function SetPlayerSettings(self,PlayerName,IniUnit)
|
||||||
local Settings = SETTINGS:Set( PlayerName )
|
-- Player settings.
|
||||||
Settings:SetPlayerMenu(Event.IniUnit)
|
local Settings = SETTINGS:Set( PlayerName )
|
||||||
|
--Settings:SetPlayerMenu(Event.IniUnit)
|
||||||
-- Create an event.
|
Settings:SetPlayerMenu(IniUnit)
|
||||||
self:CreateEventPlayerEnterAircraft(Event.IniUnit)
|
-- Create an event.
|
||||||
|
self:CreateEventPlayerEnterAircraft(IniUnit)
|
||||||
|
--self:CreateEventPlayerEnterAircraft(Event.IniUnit)
|
||||||
|
end
|
||||||
|
|
||||||
|
self:ScheduleOnce(1,SetPlayerSettings,self,PlayerName,Event.IniUnit)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
@@ -1569,7 +1737,6 @@ end
|
|||||||
-- @param #DATABASE self
|
-- @param #DATABASE self
|
||||||
-- @param Core.Event#EVENTDATA Event
|
-- @param Core.Event#EVENTDATA Event
|
||||||
function DATABASE:_EventOnDeadOrCrash( Event )
|
function DATABASE:_EventOnDeadOrCrash( Event )
|
||||||
|
|
||||||
if Event.IniDCSUnit then
|
if Event.IniDCSUnit then
|
||||||
|
|
||||||
local name=Event.IniDCSUnitName
|
local name=Event.IniDCSUnitName
|
||||||
@@ -1577,7 +1744,7 @@ function DATABASE:_EventOnDeadOrCrash( Event )
|
|||||||
if Event.IniObjectCategory == 3 then
|
if Event.IniObjectCategory == 3 then
|
||||||
|
|
||||||
---
|
---
|
||||||
-- STATICS
|
-- STATICS
|
||||||
---
|
---
|
||||||
|
|
||||||
if self.STATICS[Event.IniDCSUnitName] then
|
if self.STATICS[Event.IniDCSUnitName] then
|
||||||
@@ -1587,7 +1754,7 @@ function DATABASE:_EventOnDeadOrCrash( Event )
|
|||||||
---
|
---
|
||||||
-- Maybe a UNIT?
|
-- Maybe a UNIT?
|
||||||
---
|
---
|
||||||
|
|
||||||
-- Delete unit.
|
-- Delete unit.
|
||||||
if self.UNITS[Event.IniDCSUnitName] then
|
if self.UNITS[Event.IniDCSUnitName] then
|
||||||
self:T("STATIC Event for UNIT "..tostring(Event.IniDCSUnitName))
|
self:T("STATIC Event for UNIT "..tostring(Event.IniDCSUnitName))
|
||||||
@@ -1610,7 +1777,8 @@ function DATABASE:_EventOnDeadOrCrash( Event )
|
|||||||
|
|
||||||
-- Delete unit.
|
-- Delete unit.
|
||||||
if self.UNITS[Event.IniDCSUnitName] then
|
if self.UNITS[Event.IniDCSUnitName] then
|
||||||
self:DeleteUnit(Event.IniDCSUnitName)
|
self:ScheduleOnce(1,self.DeleteUnit,self,Event.IniDCSUnitName)
|
||||||
|
--self:DeleteUnit(Event.IniDCSUnitName)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Remove client players.
|
-- Remove client players.
|
||||||
@@ -1677,6 +1845,15 @@ function DATABASE:_EventOnPlayerEnterUnit( Event )
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Handles the OnDynamicCargoRemoved event to clean the active dynamic cargo table.
|
||||||
|
-- @param #DATABASE self
|
||||||
|
-- @param Core.Event#EVENTDATA Event
|
||||||
|
function DATABASE:_EventOnDynamicCargoRemoved( Event )
|
||||||
|
self:T( { Event } )
|
||||||
|
if Event.IniDynamicCargoName then
|
||||||
|
self:DeleteDynamicCargo(Event.IniDynamicCargoName)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
--- Handles the OnPlayerLeaveUnit event to clean the active players table.
|
--- Handles the OnPlayerLeaveUnit event to clean the active players table.
|
||||||
-- @param #DATABASE self
|
-- @param #DATABASE self
|
||||||
@@ -1718,6 +1895,7 @@ function DATABASE:_EventOnPlayerLeaveUnit( Event )
|
|||||||
local client=self.CLIENTS[Event.IniDCSUnitName] --Wrapper.Client#CLIENT
|
local client=self.CLIENTS[Event.IniDCSUnitName] --Wrapper.Client#CLIENT
|
||||||
if client then
|
if client then
|
||||||
client:RemovePlayer(PlayerName)
|
client:RemovePlayer(PlayerName)
|
||||||
|
--self.PLAYERSETTINGS[PlayerName] = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -194,6 +194,11 @@ world.event.S_EVENT_NEW_ZONE_GOAL = world.event.S_EVENT_MAX + 1004
|
|||||||
world.event.S_EVENT_DELETE_ZONE_GOAL = world.event.S_EVENT_MAX + 1005
|
world.event.S_EVENT_DELETE_ZONE_GOAL = world.event.S_EVENT_MAX + 1005
|
||||||
world.event.S_EVENT_REMOVE_UNIT = world.event.S_EVENT_MAX + 1006
|
world.event.S_EVENT_REMOVE_UNIT = world.event.S_EVENT_MAX + 1006
|
||||||
world.event.S_EVENT_PLAYER_ENTER_AIRCRAFT = world.event.S_EVENT_MAX + 1007
|
world.event.S_EVENT_PLAYER_ENTER_AIRCRAFT = world.event.S_EVENT_MAX + 1007
|
||||||
|
-- dynamic cargo
|
||||||
|
world.event.S_EVENT_NEW_DYNAMIC_CARGO = world.event.S_EVENT_MAX + 1008
|
||||||
|
world.event.S_EVENT_DYNAMIC_CARGO_LOADED = world.event.S_EVENT_MAX + 1009
|
||||||
|
world.event.S_EVENT_DYNAMIC_CARGO_UNLOADED = world.event.S_EVENT_MAX + 1010
|
||||||
|
world.event.S_EVENT_DYNAMIC_CARGO_REMOVED = world.event.S_EVENT_MAX + 1011
|
||||||
|
|
||||||
|
|
||||||
--- The different types of events supported by MOOSE.
|
--- The different types of events supported by MOOSE.
|
||||||
@@ -261,17 +266,29 @@ EVENTS = {
|
|||||||
SimulationStart = world.event.S_EVENT_SIMULATION_START or -1,
|
SimulationStart = world.event.S_EVENT_SIMULATION_START or -1,
|
||||||
WeaponRearm = world.event.S_EVENT_WEAPON_REARM or -1,
|
WeaponRearm = world.event.S_EVENT_WEAPON_REARM or -1,
|
||||||
WeaponDrop = world.event.S_EVENT_WEAPON_DROP or -1,
|
WeaponDrop = world.event.S_EVENT_WEAPON_DROP or -1,
|
||||||
-- Added with DCS 2.9.0
|
-- Added with DCS 2.9.x
|
||||||
UnitTaskTimeout = world.event.S_EVENT_UNIT_TASK_TIMEOUT or -1,
|
--UnitTaskTimeout = world.event.S_EVENT_UNIT_TASK_TIMEOUT or -1,
|
||||||
|
UnitTaskComplete = world.event.S_EVENT_UNIT_TASK_COMPLETE or -1,
|
||||||
UnitTaskStage = world.event.S_EVENT_UNIT_TASK_STAGE or -1,
|
UnitTaskStage = world.event.S_EVENT_UNIT_TASK_STAGE or -1,
|
||||||
MacSubtaskScore = world.event.S_EVENT_MAC_SUBTASK_SCORE or -1,
|
--MacSubtaskScore = world.event.S_EVENT_MAC_SUBTASK_SCORE or -1,
|
||||||
MacExtraScore = world.event.S_EVENT_MAC_EXTRA_SCORE or -1,
|
MacExtraScore = world.event.S_EVENT_MAC_EXTRA_SCORE or -1,
|
||||||
MissionRestart = world.event.S_EVENT_MISSION_RESTART or -1,
|
MissionRestart = world.event.S_EVENT_MISSION_RESTART or -1,
|
||||||
MissionWinner = world.event.S_EVENT_MISSION_WINNER or -1,
|
MissionWinner = world.event.S_EVENT_MISSION_WINNER or -1,
|
||||||
PostponedTakeoff = world.event.S_EVENT_POSTPONED_TAKEOFF or -1,
|
RunwayTakeoff = world.event.S_EVENT_RUNWAY_TAKEOFF or -1,
|
||||||
PostponedLand = world.event.S_EVENT_POSTPONED_LAND or -1,
|
RunwayTouch = world.event.S_EVENT_RUNWAY_TOUCH or -1,
|
||||||
|
MacLMSRestart = world.event.S_EVENT_MAC_LMS_RESTART or -1,
|
||||||
|
SimulationFreeze = world.event.S_EVENT_SIMULATION_FREEZE or -1,
|
||||||
|
SimulationUnfreeze = world.event.S_EVENT_SIMULATION_UNFREEZE or -1,
|
||||||
|
HumanAircraftRepairStart = world.event.S_EVENT_HUMAN_AIRCRAFT_REPAIR_START or -1,
|
||||||
|
HumanAircraftRepairFinish = world.event.S_EVENT_HUMAN_AIRCRAFT_REPAIR_FINISH or -1,
|
||||||
|
-- dynamic cargo
|
||||||
|
NewDynamicCargo = world.event.S_EVENT_NEW_DYNAMIC_CARGO or -1,
|
||||||
|
DynamicCargoLoaded = world.event.S_EVENT_DYNAMIC_CARGO_LOADED or -1,
|
||||||
|
DynamicCargoUnloaded = world.event.S_EVENT_DYNAMIC_CARGO_UNLOADED or -1,
|
||||||
|
DynamicCargoRemoved = world.event.S_EVENT_DYNAMIC_CARGO_REMOVED or -1,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
--- The Event structure
|
--- The Event structure
|
||||||
-- Note that at the beginning of each field description, there is an indication which field will be populated depending on the object type involved in the Event:
|
-- Note that at the beginning of each field description, there is an indication which field will be populated depending on the object type involved in the Event:
|
||||||
--
|
--
|
||||||
@@ -327,6 +344,9 @@ EVENTS = {
|
|||||||
--
|
--
|
||||||
-- @field Core.Zone#ZONE Zone The zone object.
|
-- @field Core.Zone#ZONE Zone The zone object.
|
||||||
-- @field #string ZoneName The name of the zone.
|
-- @field #string ZoneName The name of the zone.
|
||||||
|
--
|
||||||
|
-- @field Wrapper.DynamicCargo#DYNAMICCARGO IniDynamicCargo The dynamic cargo object.
|
||||||
|
-- @field #string IniDynamicCargoName The dynamic cargo unit name.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -646,24 +666,24 @@ local _EVENTMETA = {
|
|||||||
Text = "S_EVENT_WEAPON_DROP"
|
Text = "S_EVENT_WEAPON_DROP"
|
||||||
},
|
},
|
||||||
-- DCS 2.9
|
-- DCS 2.9
|
||||||
[EVENTS.UnitTaskTimeout] = {
|
--[EVENTS.UnitTaskTimeout] = {
|
||||||
Order = 1,
|
-- Order = 1,
|
||||||
Side = "I",
|
-- Side = "I",
|
||||||
Event = "OnEventUnitTaskTimeout",
|
-- Event = "OnEventUnitTaskTimeout",
|
||||||
Text = "S_EVENT_UNIT_TASK_TIMEOUT "
|
-- Text = "S_EVENT_UNIT_TASK_TIMEOUT "
|
||||||
},
|
--},
|
||||||
[EVENTS.UnitTaskStage] = {
|
[EVENTS.UnitTaskStage] = {
|
||||||
Order = 1,
|
Order = 1,
|
||||||
Side = "I",
|
Side = "I",
|
||||||
Event = "OnEventUnitTaskStage",
|
Event = "OnEventUnitTaskStage",
|
||||||
Text = "S_EVENT_UNIT_TASK_STAGE "
|
Text = "S_EVENT_UNIT_TASK_STAGE "
|
||||||
},
|
},
|
||||||
[EVENTS.MacSubtaskScore] = {
|
--[EVENTS.MacSubtaskScore] = {
|
||||||
Order = 1,
|
-- Order = 1,
|
||||||
Side = "I",
|
--Side = "I",
|
||||||
Event = "OnEventMacSubtaskScore",
|
--Event = "OnEventMacSubtaskScore",
|
||||||
Text = "S_EVENT_MAC_SUBTASK_SCORE"
|
--Text = "S_EVENT_MAC_SUBTASK_SCORE"
|
||||||
},
|
--},
|
||||||
[EVENTS.MacExtraScore] = {
|
[EVENTS.MacExtraScore] = {
|
||||||
Order = 1,
|
Order = 1,
|
||||||
Side = "I",
|
Side = "I",
|
||||||
@@ -682,20 +702,76 @@ local _EVENTMETA = {
|
|||||||
Event = "OnEventMissionWinner",
|
Event = "OnEventMissionWinner",
|
||||||
Text = "S_EVENT_MISSION_WINNER"
|
Text = "S_EVENT_MISSION_WINNER"
|
||||||
},
|
},
|
||||||
[EVENTS.PostponedTakeoff] = {
|
[EVENTS.RunwayTakeoff] = {
|
||||||
Order = 1,
|
Order = 1,
|
||||||
Side = "I",
|
Side = "I",
|
||||||
Event = "OnEventPostponedTakeoff",
|
Event = "OnEventRunwayTakeoff",
|
||||||
Text = "S_EVENT_POSTPONED_TAKEOFF"
|
Text = "S_EVENT_RUNWAY_TAKEOFF"
|
||||||
},
|
},
|
||||||
[EVENTS.PostponedLand] = {
|
[EVENTS.RunwayTouch] = {
|
||||||
Order = 1,
|
Order = 1,
|
||||||
Side = "I",
|
Side = "I",
|
||||||
Event = "OnEventPostponedLand",
|
Event = "OnEventRunwayTouch",
|
||||||
Text = "S_EVENT_POSTPONED_LAND"
|
Text = "S_EVENT_RUNWAY_TOUCH"
|
||||||
|
},
|
||||||
|
[EVENTS.MacLMSRestart] = {
|
||||||
|
Order = 1,
|
||||||
|
Side = "I",
|
||||||
|
Event = "OnEventMacLMSRestart",
|
||||||
|
Text = "S_EVENT_MAC_LMS_RESTART"
|
||||||
|
},
|
||||||
|
[EVENTS.SimulationFreeze] = {
|
||||||
|
Order = 1,
|
||||||
|
Side = "I",
|
||||||
|
Event = "OnEventSimulationFreeze",
|
||||||
|
Text = "S_EVENT_SIMULATION_FREEZE"
|
||||||
|
},
|
||||||
|
[EVENTS.SimulationUnfreeze] = {
|
||||||
|
Order = 1,
|
||||||
|
Side = "I",
|
||||||
|
Event = "OnEventSimulationUnfreeze",
|
||||||
|
Text = "S_EVENT_SIMULATION_UNFREEZE"
|
||||||
|
},
|
||||||
|
[EVENTS.HumanAircraftRepairStart] = {
|
||||||
|
Order = 1,
|
||||||
|
Side = "I",
|
||||||
|
Event = "OnEventHumanAircraftRepairStart",
|
||||||
|
Text = "S_EVENT_HUMAN_AIRCRAFT_REPAIR_START"
|
||||||
|
},
|
||||||
|
[EVENTS.HumanAircraftRepairFinish] = {
|
||||||
|
Order = 1,
|
||||||
|
Side = "I",
|
||||||
|
Event = "OnEventHumanAircraftRepairFinish",
|
||||||
|
Text = "S_EVENT_HUMAN_AIRCRAFT_REPAIR_FINISH"
|
||||||
|
},
|
||||||
|
-- dynamic cargo
|
||||||
|
[EVENTS.NewDynamicCargo] = {
|
||||||
|
Order = 1,
|
||||||
|
Side = "I",
|
||||||
|
Event = "OnEventNewDynamicCargo",
|
||||||
|
Text = "S_EVENT_NEW_DYNAMIC_CARGO"
|
||||||
|
},
|
||||||
|
[EVENTS.DynamicCargoLoaded] = {
|
||||||
|
Order = 1,
|
||||||
|
Side = "I",
|
||||||
|
Event = "OnEventDynamicCargoLoaded",
|
||||||
|
Text = "S_EVENT_DYNAMIC_CARGO_LOADED"
|
||||||
|
},
|
||||||
|
[EVENTS.DynamicCargoUnloaded] = {
|
||||||
|
Order = 1,
|
||||||
|
Side = "I",
|
||||||
|
Event = "OnEventDynamicCargoUnloaded",
|
||||||
|
Text = "S_EVENT_DYNAMIC_CARGO_UNLOADED"
|
||||||
|
},
|
||||||
|
[EVENTS.DynamicCargoRemoved] = {
|
||||||
|
Order = 1,
|
||||||
|
Side = "I",
|
||||||
|
Event = "OnEventDynamicCargoRemoved",
|
||||||
|
Text = "S_EVENT_DYNAMIC_CARGO_REMOVED"
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
--- The Events structure
|
--- The Events structure
|
||||||
-- @type EVENT.Events
|
-- @type EVENT.Events
|
||||||
-- @field #number IniUnit
|
-- @field #number IniUnit
|
||||||
@@ -1108,7 +1184,63 @@ do -- Event Creation
|
|||||||
|
|
||||||
world.onEvent( Event )
|
world.onEvent( Event )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Creation of a S_EVENT_NEW_DYNAMIC_CARGO event.
|
||||||
|
-- @param #EVENT self
|
||||||
|
-- @param Wrapper.DynamicCargo#DYNAMICCARGO DynamicCargo the dynamic cargo object
|
||||||
|
function EVENT:CreateEventNewDynamicCargo(DynamicCargo)
|
||||||
|
self:F({DynamicCargo})
|
||||||
|
local Event = {
|
||||||
|
id = EVENTS.NewDynamicCargo,
|
||||||
|
time = timer.getTime(),
|
||||||
|
dynamiccargo = DynamicCargo,
|
||||||
|
initiator = DynamicCargo:GetDCSObject(),
|
||||||
|
}
|
||||||
|
world.onEvent( Event )
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Creation of a S_EVENT_DYNAMIC_CARGO_LOADED event.
|
||||||
|
-- @param #EVENT self
|
||||||
|
-- @param Wrapper.DynamicCargo#DYNAMICCARGO DynamicCargo the dynamic cargo object
|
||||||
|
function EVENT:CreateEventDynamicCargoLoaded(DynamicCargo)
|
||||||
|
self:F({DynamicCargo})
|
||||||
|
local Event = {
|
||||||
|
id = EVENTS.DynamicCargoLoaded,
|
||||||
|
time = timer.getTime(),
|
||||||
|
dynamiccargo = DynamicCargo,
|
||||||
|
initiator = DynamicCargo:GetDCSObject(),
|
||||||
|
}
|
||||||
|
world.onEvent( Event )
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Creation of a S_EVENT_DYNAMIC_CARGO_UNLOADED event.
|
||||||
|
-- @param #EVENT self
|
||||||
|
-- @param Wrapper.DynamicCargo#DYNAMICCARGO DynamicCargo the dynamic cargo object
|
||||||
|
function EVENT:CreateEventDynamicCargoUnloaded(DynamicCargo)
|
||||||
|
self:F({DynamicCargo})
|
||||||
|
local Event = {
|
||||||
|
id = EVENTS.DynamicCargoUnloaded,
|
||||||
|
time = timer.getTime(),
|
||||||
|
dynamiccargo = DynamicCargo,
|
||||||
|
initiator = DynamicCargo:GetDCSObject(),
|
||||||
|
}
|
||||||
|
world.onEvent( Event )
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Creation of a S_EVENT_DYNAMIC_CARGO_REMOVED event.
|
||||||
|
-- @param #EVENT self
|
||||||
|
-- @param Wrapper.DynamicCargo#DYNAMICCARGO DynamicCargo the dynamic cargo object
|
||||||
|
function EVENT:CreateEventDynamicCargoRemoved(DynamicCargo)
|
||||||
|
self:F({DynamicCargo})
|
||||||
|
local Event = {
|
||||||
|
id = EVENTS.DynamicCargoRemoved,
|
||||||
|
time = timer.getTime(),
|
||||||
|
dynamiccargo = DynamicCargo,
|
||||||
|
initiator = DynamicCargo:GetDCSObject(),
|
||||||
|
}
|
||||||
|
world.onEvent( Event )
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Main event function.
|
--- Main event function.
|
||||||
@@ -1197,6 +1329,7 @@ function EVENT:onEvent( Event )
|
|||||||
end
|
end
|
||||||
|
|
||||||
Event.IniDCSGroupName = Event.IniUnit and Event.IniUnit.GroupName or ""
|
Event.IniDCSGroupName = Event.IniUnit and Event.IniUnit.GroupName or ""
|
||||||
|
Event.IniGroupName=Event.IniDCSGroupName --At least set the group name because group might not exist any more
|
||||||
if Event.IniDCSGroup and Event.IniDCSGroup:isExist() then
|
if Event.IniDCSGroup and Event.IniDCSGroup:isExist() then
|
||||||
Event.IniDCSGroupName = Event.IniDCSGroup:getName()
|
Event.IniDCSGroupName = Event.IniDCSGroup:getName()
|
||||||
Event.IniGroup = GROUP:FindByName( Event.IniDCSGroupName )
|
Event.IniGroup = GROUP:FindByName( Event.IniDCSGroupName )
|
||||||
@@ -1223,7 +1356,13 @@ function EVENT:onEvent( Event )
|
|||||||
Event.IniDCSUnit = Event.initiator
|
Event.IniDCSUnit = Event.initiator
|
||||||
Event.IniDCSUnitName = Event.IniDCSUnit:getName()
|
Event.IniDCSUnitName = Event.IniDCSUnit:getName()
|
||||||
Event.IniUnitName = Event.IniDCSUnitName
|
Event.IniUnitName = Event.IniDCSUnitName
|
||||||
Event.IniUnit = CARGO:FindByName( Event.IniDCSUnitName )
|
if string.match(Event.IniUnitName,".+|%d%d:%d%d|PKG%d+") then
|
||||||
|
Event.IniDynamicCargo = DYNAMICCARGO:FindByName(Event.IniUnitName)
|
||||||
|
Event.IniDynamicCargoName = Event.IniUnitName
|
||||||
|
Event.IniPlayerName = string.match(Event.IniUnitName,"^(.+)|%d%d:%d%d|PKG%d+")
|
||||||
|
else
|
||||||
|
Event.IniUnit = CARGO:FindByName( Event.IniDCSUnitName )
|
||||||
|
end
|
||||||
Event.IniCoalition = Event.IniDCSUnit:getCoalition()
|
Event.IniCoalition = Event.IniDCSUnit:getCoalition()
|
||||||
Event.IniCategory = Event.IniDCSUnit:getDesc().category
|
Event.IniCategory = Event.IniDCSUnit:getDesc().category
|
||||||
Event.IniTypeName = Event.IniDCSUnit:getTypeName()
|
Event.IniTypeName = Event.IniDCSUnit:getTypeName()
|
||||||
@@ -1233,10 +1372,10 @@ function EVENT:onEvent( Event )
|
|||||||
-- Scenery
|
-- Scenery
|
||||||
---
|
---
|
||||||
Event.IniDCSUnit = Event.initiator
|
Event.IniDCSUnit = Event.initiator
|
||||||
Event.IniDCSUnitName = Event.IniDCSUnit:getName()
|
Event.IniDCSUnitName = Event.IniDCSUnit.getName and Event.IniDCSUnit:getName() or "Scenery no name "..math.random(1,20000)
|
||||||
Event.IniUnitName = Event.IniDCSUnitName
|
Event.IniUnitName = Event.IniDCSUnitName
|
||||||
Event.IniUnit = SCENERY:Register( Event.IniDCSUnitName, Event.initiator )
|
Event.IniUnit = SCENERY:Register( Event.IniDCSUnitName, Event.initiator )
|
||||||
Event.IniCategory = Event.IniDCSUnit:getDesc().category
|
Event.IniCategory = Event.IniDCSUnit.getDesc and Event.IniDCSUnit:getDesc().category
|
||||||
Event.IniTypeName = Event.initiator:isExist() and Event.IniDCSUnit:getTypeName() or "SCENERY"
|
Event.IniTypeName = Event.initiator:isExist() and Event.IniDCSUnit:getTypeName() or "SCENERY"
|
||||||
|
|
||||||
elseif Event.IniObjectCategory == Object.Category.BASE then
|
elseif Event.IniObjectCategory == Object.Category.BASE then
|
||||||
@@ -1335,24 +1474,26 @@ function EVENT:onEvent( Event )
|
|||||||
-- SCENERY
|
-- SCENERY
|
||||||
---
|
---
|
||||||
Event.TgtDCSUnit = Event.target
|
Event.TgtDCSUnit = Event.target
|
||||||
Event.TgtDCSUnitName = Event.TgtDCSUnit:getName()
|
Event.TgtDCSUnitName = Event.TgtDCSUnit.getName and Event.TgtDCSUnit.getName() or nil
|
||||||
Event.TgtUnitName = Event.TgtDCSUnitName
|
if Event.TgtDCSUnitName~=nil then
|
||||||
Event.TgtUnit = SCENERY:Register( Event.TgtDCSUnitName, Event.target )
|
Event.TgtUnitName = Event.TgtDCSUnitName
|
||||||
Event.TgtCategory = Event.TgtDCSUnit:getDesc().category
|
Event.TgtUnit = SCENERY:Register( Event.TgtDCSUnitName, Event.target )
|
||||||
Event.TgtTypeName = Event.TgtDCSUnit:getTypeName()
|
Event.TgtCategory = Event.TgtDCSUnit:getDesc().category
|
||||||
|
Event.TgtTypeName = Event.TgtDCSUnit:getTypeName()
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Weapon.
|
-- Weapon.
|
||||||
if Event.weapon then
|
if Event.weapon and type(Event.weapon) == "table" and Event.weapon.isExist and Event.weapon:isExist() then
|
||||||
Event.Weapon = Event.weapon
|
Event.Weapon = Event.weapon
|
||||||
Event.WeaponName = Event.weapon:isExist() and Event.weapon:getTypeName() or "Unknown Weapon"
|
Event.WeaponName = Event.weapon:isExist() and Event.weapon:getTypeName() or "Unknown Weapon"
|
||||||
Event.WeaponUNIT = CLIENT:Find( Event.Weapon, '', true ) -- Sometimes, the weapon is a player unit!
|
Event.WeaponUNIT = CLIENT:Find( Event.Weapon, '', true ) -- Sometimes, the weapon is a player unit!
|
||||||
Event.WeaponPlayerName = Event.WeaponUNIT and Event.Weapon.getPlayerName and Event.Weapon:getPlayerName()
|
Event.WeaponPlayerName = Event.WeaponUNIT and Event.Weapon.getPlayerName and Event.Weapon:getPlayerName()
|
||||||
--Event.WeaponPlayerName = Event.WeaponUNIT and Event.Weapon:getPlayerName()
|
--Event.WeaponPlayerName = Event.WeaponUNIT and Event.Weapon:getPlayerName()
|
||||||
Event.WeaponCoalition = Event.WeaponUNIT and Event.Weapon:getCoalition()
|
Event.WeaponCoalition = Event.WeaponUNIT and Event.Weapon.getCoalition and Event.Weapon:getCoalition()
|
||||||
Event.WeaponCategory = Event.WeaponUNIT and Event.Weapon:getDesc().category
|
Event.WeaponCategory = Event.WeaponUNIT and Event.Weapon.getDesc and Event.Weapon:getDesc().category
|
||||||
Event.WeaponTypeName = Event.WeaponUNIT and Event.Weapon:getTypeName()
|
Event.WeaponTypeName = Event.WeaponUNIT and Event.Weapon.getTypeName and Event.Weapon:getTypeName()
|
||||||
--Event.WeaponTgtDCSUnit = Event.Weapon:getTarget()
|
--Event.WeaponTgtDCSUnit = Event.Weapon:getTarget()
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1387,6 +1528,15 @@ function EVENT:onEvent( Event )
|
|||||||
Event.Cargo = Event.cargo
|
Event.Cargo = Event.cargo
|
||||||
Event.CargoName = Event.cargo.Name
|
Event.CargoName = Event.cargo.Name
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Dynamic cargo Object
|
||||||
|
if Event.dynamiccargo then
|
||||||
|
Event.IniDynamicCargo = Event.dynamiccargo
|
||||||
|
Event.IniDynamicCargoName = Event.IniDynamicCargo.StaticName
|
||||||
|
if Event.IniDynamicCargo.Owner or Event.IniUnitName then
|
||||||
|
Event.IniPlayerName = Event.IniDynamicCargo.Owner or string.match(Event.IniUnitName or "None|00:00|PKG00","^(.+)|%d%d:%d%d|PKG%d+")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- Zone object.
|
-- Zone object.
|
||||||
if Event.zone then
|
if Event.zone then
|
||||||
|
|||||||
@@ -79,7 +79,7 @@
|
|||||||
|
|
||||||
do -- FSM
|
do -- FSM
|
||||||
|
|
||||||
--- @type FSM
|
-- @type FSM
|
||||||
-- @field #string ClassName Name of the class.
|
-- @field #string ClassName Name of the class.
|
||||||
-- @field Core.Scheduler#SCHEDULER CallScheduler Call scheduler.
|
-- @field Core.Scheduler#SCHEDULER CallScheduler Call scheduler.
|
||||||
-- @field #table options Options.
|
-- @field #table options Options.
|
||||||
@@ -948,8 +948,9 @@ do -- FSM
|
|||||||
end
|
end
|
||||||
|
|
||||||
do -- FSM_CONTROLLABLE
|
do -- FSM_CONTROLLABLE
|
||||||
|
|
||||||
--- @type FSM_CONTROLLABLE
|
---
|
||||||
|
-- @type FSM_CONTROLLABLE
|
||||||
-- @field Wrapper.Controllable#CONTROLLABLE Controllable
|
-- @field Wrapper.Controllable#CONTROLLABLE Controllable
|
||||||
-- @extends Core.Fsm#FSM
|
-- @extends Core.Fsm#FSM
|
||||||
|
|
||||||
@@ -1081,8 +1082,9 @@ do -- FSM_CONTROLLABLE
|
|||||||
end
|
end
|
||||||
|
|
||||||
do -- FSM_PROCESS
|
do -- FSM_PROCESS
|
||||||
|
|
||||||
--- @type FSM_PROCESS
|
---
|
||||||
|
-- @type FSM_PROCESS
|
||||||
-- @field Tasking.Task#TASK Task
|
-- @field Tasking.Task#TASK Task
|
||||||
-- @extends Core.Fsm#FSM_CONTROLLABLE
|
-- @extends Core.Fsm#FSM_CONTROLLABLE
|
||||||
|
|
||||||
|
|||||||
@@ -24,7 +24,7 @@
|
|||||||
|
|
||||||
do -- Goal
|
do -- Goal
|
||||||
|
|
||||||
--- @type GOAL
|
-- @type GOAL
|
||||||
-- @extends Core.Fsm#FSM
|
-- @extends Core.Fsm#FSM
|
||||||
|
|
||||||
--- Models processes that have an objective with a defined achievement. Derived classes implement the ways how the achievements can be realized.
|
--- Models processes that have an objective with a defined achievement. Derived classes implement the ways how the achievements can be realized.
|
||||||
@@ -71,10 +71,10 @@ do -- Goal
|
|||||||
ClassName = "GOAL",
|
ClassName = "GOAL",
|
||||||
}
|
}
|
||||||
|
|
||||||
--- @field #table GOAL.Players
|
-- @field #table GOAL.Players
|
||||||
GOAL.Players = {}
|
GOAL.Players = {}
|
||||||
|
|
||||||
--- @field #number GOAL.TotalContributions
|
-- @field #number GOAL.TotalContributions
|
||||||
GOAL.TotalContributions = 0
|
GOAL.TotalContributions = 0
|
||||||
|
|
||||||
--- GOAL Constructor.
|
--- GOAL Constructor.
|
||||||
@@ -145,7 +145,7 @@ do -- Goal
|
|||||||
self.TotalContributions = self.TotalContributions + 1
|
self.TotalContributions = self.TotalContributions + 1
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #GOAL self
|
-- @param #GOAL self
|
||||||
-- @param #number Player contribution.
|
-- @param #number Player contribution.
|
||||||
function GOAL:GetPlayerContribution( PlayerName )
|
function GOAL:GetPlayerContribution( PlayerName )
|
||||||
return self.Players[PlayerName] or 0
|
return self.Players[PlayerName] or 0
|
||||||
|
|||||||
@@ -108,26 +108,30 @@ function MARKEROPS_BASE:New(Tagname,Keywords,Casesensitive)
|
|||||||
--- On after "MarkAdded" event. Triggered when a Marker is added to the F10 map.
|
--- On after "MarkAdded" event. Triggered when a Marker is added to the F10 map.
|
||||||
-- @function [parent=#MARKEROPS_BASE] OnAfterMarkAdded
|
-- @function [parent=#MARKEROPS_BASE] OnAfterMarkAdded
|
||||||
-- @param #MARKEROPS_BASE self
|
-- @param #MARKEROPS_BASE self
|
||||||
-- @param #string From The From state
|
-- @param #string From The From state.
|
||||||
-- @param #string Event The Event called
|
-- @param #string Event The Event called.
|
||||||
-- @param #string To The To state
|
-- @param #string To The To state.
|
||||||
-- @param #string Text The text on the marker
|
-- @param #string Text The text on the marker.
|
||||||
-- @param #table Keywords Table of matching keywords found in the Event text
|
-- @param #table Keywords Table of matching keywords found in the Event text.
|
||||||
-- @param Core.Point#COORDINATE Coord Coordinate of the marker.
|
-- @param Core.Point#COORDINATE Coord Coordinate of the marker.
|
||||||
-- @param #number MarkerID Id of this marker
|
-- @param #number MarkerID Id of this marker.
|
||||||
-- @param #number CoalitionNumber Coalition of the marker creator
|
-- @param #number CoalitionNumber Coalition of the marker creator.
|
||||||
|
-- @param #string PlayerName Name of the player creating/changing the mark. nil if it cannot be obtained.
|
||||||
|
-- @param Core.Event#EVENTDATA EventData the event data table.
|
||||||
|
|
||||||
--- On after "MarkChanged" event. Triggered when a Marker is changed on the F10 map.
|
--- On after "MarkChanged" event. Triggered when a Marker is changed on the F10 map.
|
||||||
-- @function [parent=#MARKEROPS_BASE] OnAfterMarkChanged
|
-- @function [parent=#MARKEROPS_BASE] OnAfterMarkChanged
|
||||||
-- @param #MARKEROPS_BASE self
|
-- @param #MARKEROPS_BASE self
|
||||||
-- @param #string From The From state
|
-- @param #string From The From state.
|
||||||
-- @param #string Event The Event called
|
-- @param #string Event The Event called.
|
||||||
-- @param #string To The To state
|
-- @param #string To The To state.
|
||||||
-- @param #string Text The text on the marker
|
-- @param #string Text The text on the marker.
|
||||||
-- @param #table Keywords Table of matching keywords found in the Event text
|
-- @param #table Keywords Table of matching keywords found in the Event text.
|
||||||
-- @param Core.Point#COORDINATE Coord Coordinate of the marker.
|
-- @param Core.Point#COORDINATE Coord Coordinate of the marker.
|
||||||
-- @param #number MarkerID Id of this marker
|
-- @param #number MarkerID Id of this marker.
|
||||||
-- @param #number CoalitionNumber Coalition of the marker creator
|
-- @param #number CoalitionNumber Coalition of the marker creator.
|
||||||
|
-- @param #string PlayerName Name of the player creating/changing the mark. nil if it cannot be obtained.
|
||||||
|
-- @param Core.Event#EVENTDATA EventData the event data table
|
||||||
|
|
||||||
--- On after "MarkDeleted" event. Triggered when a Marker is deleted from the F10 map.
|
--- On after "MarkDeleted" event. Triggered when a Marker is deleted from the F10 map.
|
||||||
-- @function [parent=#MARKEROPS_BASE] OnAfterMarkDeleted
|
-- @function [parent=#MARKEROPS_BASE] OnAfterMarkDeleted
|
||||||
@@ -167,7 +171,7 @@ function MARKEROPS_BASE:OnEventMark(Event)
|
|||||||
if Eventtext~=nil then
|
if Eventtext~=nil then
|
||||||
if self:_MatchTag(Eventtext) then
|
if self:_MatchTag(Eventtext) then
|
||||||
local matchtable = self:_MatchKeywords(Eventtext)
|
local matchtable = self:_MatchKeywords(Eventtext)
|
||||||
self:MarkAdded(Eventtext,matchtable,coord,Event.idx,coalition)
|
self:MarkAdded(Eventtext,matchtable,coord,Event.idx,coalition,Event.PlayerName,Event)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
elseif Event.id==world.event.S_EVENT_MARK_CHANGE then
|
elseif Event.id==world.event.S_EVENT_MARK_CHANGE then
|
||||||
@@ -177,7 +181,7 @@ function MARKEROPS_BASE:OnEventMark(Event)
|
|||||||
if Eventtext~=nil then
|
if Eventtext~=nil then
|
||||||
if self:_MatchTag(Eventtext) then
|
if self:_MatchTag(Eventtext) then
|
||||||
local matchtable = self:_MatchKeywords(Eventtext)
|
local matchtable = self:_MatchKeywords(Eventtext)
|
||||||
self:MarkChanged(Eventtext,matchtable,coord,Event.idx,coalition)
|
self:MarkChanged(Eventtext,matchtable,coord,Event.idx,coalition,Event.PlayerName,Event)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
elseif Event.id==world.event.S_EVENT_MARK_REMOVED then
|
elseif Event.id==world.event.S_EVENT_MARK_REMOVED then
|
||||||
|
|||||||
@@ -105,6 +105,7 @@ function MENU_INDEX:PrepareCoalition( CoalitionSide )
|
|||||||
self.Coalition[CoalitionSide] = self.Coalition[CoalitionSide] or {}
|
self.Coalition[CoalitionSide] = self.Coalition[CoalitionSide] or {}
|
||||||
self.Coalition[CoalitionSide].Menus = self.Coalition[CoalitionSide].Menus or {}
|
self.Coalition[CoalitionSide].Menus = self.Coalition[CoalitionSide].Menus or {}
|
||||||
end
|
end
|
||||||
|
|
||||||
---
|
---
|
||||||
-- @param Wrapper.Group#GROUP Group
|
-- @param Wrapper.Group#GROUP Group
|
||||||
function MENU_INDEX:PrepareGroup( Group )
|
function MENU_INDEX:PrepareGroup( Group )
|
||||||
@@ -118,9 +119,11 @@ end
|
|||||||
function MENU_INDEX:HasMissionMenu( Path )
|
function MENU_INDEX:HasMissionMenu( Path )
|
||||||
return self.MenuMission.Menus[Path]
|
return self.MenuMission.Menus[Path]
|
||||||
end
|
end
|
||||||
|
|
||||||
function MENU_INDEX:SetMissionMenu( Path, Menu )
|
function MENU_INDEX:SetMissionMenu( Path, Menu )
|
||||||
self.MenuMission.Menus[Path] = Menu
|
self.MenuMission.Menus[Path] = Menu
|
||||||
end
|
end
|
||||||
|
|
||||||
function MENU_INDEX:ClearMissionMenu( Path )
|
function MENU_INDEX:ClearMissionMenu( Path )
|
||||||
self.MenuMission.Menus[Path] = nil
|
self.MenuMission.Menus[Path] = nil
|
||||||
end
|
end
|
||||||
@@ -128,9 +131,11 @@ end
|
|||||||
function MENU_INDEX:HasCoalitionMenu( Coalition, Path )
|
function MENU_INDEX:HasCoalitionMenu( Coalition, Path )
|
||||||
return self.Coalition[Coalition].Menus[Path]
|
return self.Coalition[Coalition].Menus[Path]
|
||||||
end
|
end
|
||||||
|
|
||||||
function MENU_INDEX:SetCoalitionMenu( Coalition, Path, Menu )
|
function MENU_INDEX:SetCoalitionMenu( Coalition, Path, Menu )
|
||||||
self.Coalition[Coalition].Menus[Path] = Menu
|
self.Coalition[Coalition].Menus[Path] = Menu
|
||||||
end
|
end
|
||||||
|
|
||||||
function MENU_INDEX:ClearCoalitionMenu( Coalition, Path )
|
function MENU_INDEX:ClearCoalitionMenu( Coalition, Path )
|
||||||
self.Coalition[Coalition].Menus[Path] = nil
|
self.Coalition[Coalition].Menus[Path] = nil
|
||||||
end
|
end
|
||||||
@@ -138,19 +143,24 @@ end
|
|||||||
function MENU_INDEX:HasGroupMenu( Group, Path )
|
function MENU_INDEX:HasGroupMenu( Group, Path )
|
||||||
if Group and Group:IsAlive() then
|
if Group and Group:IsAlive() then
|
||||||
local MenuGroupName = Group:GetName()
|
local MenuGroupName = Group:GetName()
|
||||||
return self.Group[MenuGroupName].Menus[Path]
|
if self.Group[MenuGroupName] and self.Group[MenuGroupName].Menus and self.Group[MenuGroupName].Menus[Path] then
|
||||||
|
return self.Group[MenuGroupName].Menus[Path]
|
||||||
|
end
|
||||||
end
|
end
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
function MENU_INDEX:SetGroupMenu( Group, Path, Menu )
|
function MENU_INDEX:SetGroupMenu( Group, Path, Menu )
|
||||||
local MenuGroupName = Group:GetName()
|
local MenuGroupName = Group:GetName()
|
||||||
Group:F({MenuGroupName=MenuGroupName,Path=Path})
|
--Group:F({MenuGroupName=MenuGroupName,Path=Path})
|
||||||
self.Group[MenuGroupName].Menus[Path] = Menu
|
self.Group[MenuGroupName].Menus[Path] = Menu
|
||||||
end
|
end
|
||||||
|
|
||||||
function MENU_INDEX:ClearGroupMenu( Group, Path )
|
function MENU_INDEX:ClearGroupMenu( Group, Path )
|
||||||
local MenuGroupName = Group:GetName()
|
local MenuGroupName = Group:GetName()
|
||||||
self.Group[MenuGroupName].Menus[Path] = nil
|
self.Group[MenuGroupName].Menus[Path] = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
function MENU_INDEX:Refresh( Group )
|
function MENU_INDEX:Refresh( Group )
|
||||||
for MenuID, Menu in pairs( self.MenuMission.Menus ) do
|
for MenuID, Menu in pairs( self.MenuMission.Menus ) do
|
||||||
Menu:Refresh()
|
Menu:Refresh()
|
||||||
|
|||||||
@@ -75,35 +75,37 @@ MESSAGE.Type = {
|
|||||||
|
|
||||||
--- Creates a new MESSAGE object. Note that these MESSAGE objects are not yet displayed on the display panel. You must use the functions @{#MESSAGE.ToClient} or @{#MESSAGE.ToCoalition} or @{#MESSAGE.ToAll} to send these Messages to the respective recipients.
|
--- Creates a new MESSAGE object. Note that these MESSAGE objects are not yet displayed on the display panel. You must use the functions @{#MESSAGE.ToClient} or @{#MESSAGE.ToCoalition} or @{#MESSAGE.ToAll} to send these Messages to the respective recipients.
|
||||||
-- @param self
|
-- @param self
|
||||||
-- @param #string MessageText is the text of the Message.
|
-- @param #string Text is the text of the Message.
|
||||||
-- @param #number MessageDuration is a number in seconds of how long the MESSAGE should be shown on the display panel.
|
-- @param #number Duration Duration in seconds how long the message text is shown.
|
||||||
-- @param #string MessageCategory (optional) is a string expressing the "category" of the Message. The category will be shown as the first text in the message followed by a ": ".
|
-- @param #string Category (Optional) String expressing the "category" of the Message. The category will be shown as the first text in the message followed by a ": ".
|
||||||
-- @param #boolean ClearScreen (optional) Clear all previous messages if true.
|
-- @param #boolean ClearScreen (optional) Clear all previous messages if true.
|
||||||
-- @return #MESSAGE
|
-- @return #MESSAGE self
|
||||||
-- @usage
|
-- @usage
|
||||||
--
|
--
|
||||||
-- -- Create a series of new Messages.
|
-- -- Create a series of new Messages.
|
||||||
-- -- MessageAll is meant to be sent to all players, for 25 seconds, and is classified as "Score".
|
-- -- MessageAll is meant to be sent to all players, for 25 seconds, and is classified as "Score".
|
||||||
-- -- MessageRED is meant to be sent to the RED players only, for 10 seconds, and is classified as "End of Mission", with ID "Win".
|
-- -- MessageRED is meant to be sent to the RED players only, for 10 seconds, and is classified as "End of Mission", with ID "Win".
|
||||||
-- -- MessageClient1 is meant to be sent to a Client, for 25 seconds, and is classified as "Score", with ID "Score".
|
-- -- MessageClient1 is meant to be sent to a Client, for 25 seconds, and is classified as "Score", with ID "Score".
|
||||||
-- -- MessageClient1 is meant to be sent to a Client, for 25 seconds, and is classified as "Score", with ID "Score".
|
-- -- MessageClient1 is meant to be sent to a Client, for 25 seconds, and is classified as "Score", with ID "Score".
|
||||||
-- MessageAll = MESSAGE:New( "To all Players: BLUE has won! Each player of BLUE wins 50 points!", 25, "End of Mission" )
|
-- MessageAll = MESSAGE:New( "To all Players: BLUE has won! Each player of BLUE wins 50 points!", 25, "End of Mission" )
|
||||||
-- MessageRED = MESSAGE:New( "To the RED Players: You receive a penalty because you've killed one of your own units", 25, "Penalty" )
|
-- MessageRED = MESSAGE:New( "To the RED Players: You receive a penalty because you've killed one of your own units", 25, "Penalty" )
|
||||||
-- MessageClient1 = MESSAGE:New( "Congratulations, you've just hit a target", 25, "Score" )
|
-- MessageClient1 = MESSAGE:New( "Congratulations, you've just hit a target", 25, "Score" )
|
||||||
-- MessageClient2 = MESSAGE:New( "Congratulations, you've just killed a target", 25, "Score")
|
-- MessageClient2 = MESSAGE:New( "Congratulations, you've just killed a target", 25, "Score")
|
||||||
--
|
--
|
||||||
function MESSAGE:New( MessageText, MessageDuration, MessageCategory, ClearScreen )
|
function MESSAGE:New( Text, Duration, Category, ClearScreen )
|
||||||
|
|
||||||
local self = BASE:Inherit( self, BASE:New() )
|
local self = BASE:Inherit( self, BASE:New() )
|
||||||
self:F( { MessageText, MessageDuration, MessageCategory } )
|
|
||||||
|
self:F( { Text, Duration, Category } )
|
||||||
|
|
||||||
self.MessageType = nil
|
self.MessageType = nil
|
||||||
|
|
||||||
-- When no MessageCategory is given, we don't show it as a title...
|
-- When no MessageCategory is given, we don't show it as a title...
|
||||||
if MessageCategory and MessageCategory ~= "" then
|
if Category and Category ~= "" then
|
||||||
if MessageCategory:sub( -1 ) ~= "\n" then
|
if Category:sub( -1 ) ~= "\n" then
|
||||||
self.MessageCategory = MessageCategory .. ": "
|
self.MessageCategory = Category .. ": "
|
||||||
else
|
else
|
||||||
self.MessageCategory = MessageCategory:sub( 1, -2 ) .. ":\n"
|
self.MessageCategory = Category:sub( 1, -2 ) .. ":\n"
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
self.MessageCategory = ""
|
self.MessageCategory = ""
|
||||||
@@ -114,9 +116,9 @@ function MESSAGE:New( MessageText, MessageDuration, MessageCategory, ClearScreen
|
|||||||
self.ClearScreen = ClearScreen
|
self.ClearScreen = ClearScreen
|
||||||
end
|
end
|
||||||
|
|
||||||
self.MessageDuration = MessageDuration or 5
|
self.MessageDuration = Duration or 5
|
||||||
self.MessageTime = timer.getTime()
|
self.MessageTime = timer.getTime()
|
||||||
self.MessageText = MessageText:gsub( "^\n", "", 1 ):gsub( "\n$", "", 1 )
|
self.MessageText = Text:gsub( "^\n", "", 1 ):gsub( "\n$", "", 1 )
|
||||||
|
|
||||||
self.MessageSent = false
|
self.MessageSent = false
|
||||||
self.MessageGroup = false
|
self.MessageGroup = false
|
||||||
@@ -177,22 +179,22 @@ end
|
|||||||
--
|
--
|
||||||
-- -- Send the 2 messages created with the @{New} method to the Client Group.
|
-- -- Send the 2 messages created with the @{New} method to the Client Group.
|
||||||
-- -- Note that the Message of MessageClient2 is overwriting the Message of MessageClient1.
|
-- -- Note that the Message of MessageClient2 is overwriting the Message of MessageClient1.
|
||||||
-- Client = CLIENT:FindByName("UnitNameOfMyClient")
|
-- Client = CLIENT:FindByName("NameOfClientUnit")
|
||||||
--
|
--
|
||||||
-- MessageClient1 = MESSAGE:New( "Congratulations, you've just hit a target", "Score", 25, "Score" ):ToClient( Client )
|
-- MessageClient1 = MESSAGE:New( "Congratulations, you've just hit a target", 25, "Score" ):ToClient( Client )
|
||||||
-- MessageClient2 = MESSAGE:New( "Congratulations, you've just killed a target", "Score", 25, "Score" ):ToClient( Client )
|
-- MessageClient2 = MESSAGE:New( "Congratulations, you've just killed a target", 25, "Score" ):ToClient( Client )
|
||||||
-- or
|
-- or
|
||||||
-- MESSAGE:New( "Congratulations, you've just hit a target", "Score", 25 ):ToClient( Client )
|
-- MESSAGE:New( "Congratulations, you've just hit a target", 25, "Score"):ToClient( Client )
|
||||||
-- MESSAGE:New( "Congratulations, you've just killed a target", "Score", 25 ):ToClient( Client )
|
-- MESSAGE:New( "Congratulations, you've just killed a target", 25, "Score"):ToClient( Client )
|
||||||
-- or
|
-- or
|
||||||
-- MessageClient1 = MESSAGE:New( "Congratulations, you've just hit a target", "Score", 25 )
|
-- MessageClient1 = MESSAGE:New( "Congratulations, you've just hit a target", 25, "Score")
|
||||||
-- MessageClient2 = MESSAGE:New( "Congratulations, you've just killed a target", "Score", 25 )
|
-- MessageClient2 = MESSAGE:New( "Congratulations, you've just killed a target", 25, "Score")
|
||||||
-- MessageClient1:ToClient( Client )
|
-- MessageClient1:ToClient( Client )
|
||||||
-- MessageClient2:ToClient( Client )
|
-- MessageClient2:ToClient( Client )
|
||||||
--
|
--
|
||||||
function MESSAGE:ToClient( Client, Settings )
|
function MESSAGE:ToClient( Client, Settings )
|
||||||
self:F( Client )
|
self:F( Client )
|
||||||
self:ToUnit(Client, Settings)
|
self:ToUnit(Client,Settings)
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -239,6 +241,7 @@ function MESSAGE:ToUnit( Unit, Settings )
|
|||||||
|
|
||||||
if self.MessageDuration ~= 0 then
|
if self.MessageDuration ~= 0 then
|
||||||
self:T( self.MessageCategory .. self.MessageText:gsub("\n$",""):gsub("\n$","") .. " / " .. self.MessageDuration )
|
self:T( self.MessageCategory .. self.MessageText:gsub("\n$",""):gsub("\n$","") .. " / " .. self.MessageDuration )
|
||||||
|
local ID = Unit:GetID()
|
||||||
trigger.action.outTextForUnit( Unit:GetID(), self.MessageCategory .. self.MessageText:gsub("\n$",""):gsub("\n$",""), self.MessageDuration, self.ClearScreen )
|
trigger.action.outTextForUnit( Unit:GetID(), self.MessageCategory .. self.MessageText:gsub("\n$",""):gsub("\n$",""), self.MessageDuration, self.ClearScreen )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -287,11 +290,11 @@ end
|
|||||||
-- @usage
|
-- @usage
|
||||||
--
|
--
|
||||||
-- -- Send a message created with the @{New} method to the BLUE coalition.
|
-- -- Send a message created with the @{New} method to the BLUE coalition.
|
||||||
-- MessageBLUE = MESSAGE:New( "To the BLUE Players: You receive a penalty because you've killed one of your own units", "Penalty", 25):ToBlue()
|
-- MessageBLUE = MESSAGE:New( "To the BLUE Players: You receive a penalty because you've killed one of your own units", 25, "Penalty"):ToBlue()
|
||||||
-- or
|
-- or
|
||||||
-- MESSAGE:New( "To the BLUE Players: You receive a penalty because you've killed one of your own units", "Penalty", 25 ):ToBlue()
|
-- MESSAGE:New( "To the BLUE Players: You receive a penalty because you've killed one of your own units", 25, "Penalty"):ToBlue()
|
||||||
-- or
|
-- or
|
||||||
-- MessageBLUE = MESSAGE:New( "To the BLUE Players: You receive a penalty because you've killed one of your own units", "Penalty", 25 )
|
-- MessageBLUE = MESSAGE:New( "To the BLUE Players: You receive a penalty because you've killed one of your own units", 25, "Penalty")
|
||||||
-- MessageBLUE:ToBlue()
|
-- MessageBLUE:ToBlue()
|
||||||
--
|
--
|
||||||
function MESSAGE:ToBlue()
|
function MESSAGE:ToBlue()
|
||||||
@@ -308,11 +311,11 @@ end
|
|||||||
-- @usage
|
-- @usage
|
||||||
--
|
--
|
||||||
-- -- Send a message created with the @{New} method to the RED coalition.
|
-- -- Send a message created with the @{New} method to the RED coalition.
|
||||||
-- MessageRED = MESSAGE:New( "To the RED Players: You receive a penalty because you've killed one of your own units", "Penalty", 25 ):ToRed()
|
-- MessageRED = MESSAGE:New( "To the RED Players: You receive a penalty because you've killed one of your own units", 25, "Penalty"):ToRed()
|
||||||
-- or
|
-- or
|
||||||
-- MESSAGE:New( "To the RED Players: You receive a penalty because you've killed one of your own units", "Penalty", 25 ):ToRed()
|
-- MESSAGE:New( "To the RED Players: You receive a penalty because you've killed one of your own units", 25, "Penalty"):ToRed()
|
||||||
-- or
|
-- or
|
||||||
-- MessageRED = MESSAGE:New( "To the RED Players: You receive a penalty because you've killed one of your own units", "Penalty", 25 )
|
-- MessageRED = MESSAGE:New( "To the RED Players: You receive a penalty because you've killed one of your own units", 25, "Penalty")
|
||||||
-- MessageRED:ToRed()
|
-- MessageRED:ToRed()
|
||||||
--
|
--
|
||||||
function MESSAGE:ToRed()
|
function MESSAGE:ToRed()
|
||||||
@@ -331,11 +334,11 @@ end
|
|||||||
-- @usage
|
-- @usage
|
||||||
--
|
--
|
||||||
-- -- Send a message created with the @{New} method to the RED coalition.
|
-- -- Send a message created with the @{New} method to the RED coalition.
|
||||||
-- MessageRED = MESSAGE:New( "To the RED Players: You receive a penalty because you've killed one of your own units", "Penalty", 25 ):ToCoalition( coalition.side.RED )
|
-- MessageRED = MESSAGE:New( "To the RED Players: You receive a penalty because you've killed one of your own units", 25, "Penalty"):ToCoalition( coalition.side.RED )
|
||||||
-- or
|
-- or
|
||||||
-- MESSAGE:New( "To the RED Players: You receive a penalty because you've killed one of your own units", "Penalty", 25 ):ToCoalition( coalition.side.RED )
|
-- MESSAGE:New( "To the RED Players: You receive a penalty because you've killed one of your own units", 25, "Penalty"):ToCoalition( coalition.side.RED )
|
||||||
-- or
|
-- or
|
||||||
-- MessageRED = MESSAGE:New( "To the RED Players: You receive a penalty because you've killed one of your own units", "Penalty", 25 )
|
-- MessageRED = MESSAGE:New( "To the RED Players: You receive a penalty because you've killed one of your own units", 25, "Penalty")
|
||||||
-- MessageRED:ToCoalition( coalition.side.RED )
|
-- MessageRED:ToCoalition( coalition.side.RED )
|
||||||
--
|
--
|
||||||
function MESSAGE:ToCoalition( CoalitionSide, Settings )
|
function MESSAGE:ToCoalition( CoalitionSide, Settings )
|
||||||
@@ -381,13 +384,13 @@ end
|
|||||||
-- @return #MESSAGE self
|
-- @return #MESSAGE self
|
||||||
-- @usage
|
-- @usage
|
||||||
--
|
--
|
||||||
-- -- Send a message created to all players.
|
-- -- Send a message created to all players.
|
||||||
-- MessageAll = MESSAGE:New( "To all Players: BLUE has won! Each player of BLUE wins 50 points!", "End of Mission", 25 ):ToAll()
|
-- MessageAll = MESSAGE:New( "To all Players: BLUE has won! Each player of BLUE wins 50 points!", 25, "End of Mission"):ToAll()
|
||||||
-- or
|
-- or
|
||||||
-- MESSAGE:New( "To all Players: BLUE has won! Each player of BLUE wins 50 points!", "End of Mission", 25 ):ToAll()
|
-- MESSAGE:New( "To all Players: BLUE has won! Each player of BLUE wins 50 points!", 25, "End of Mission"):ToAll()
|
||||||
-- or
|
-- or
|
||||||
-- MessageAll = MESSAGE:New( "To all Players: BLUE has won! Each player of BLUE wins 50 points!", "End of Mission", 25 )
|
-- MessageAll = MESSAGE:New( "To all Players: BLUE has won! Each player of BLUE wins 50 points!", 25, "End of Mission")
|
||||||
-- MessageAll:ToAll()
|
-- MessageAll:ToAll()
|
||||||
--
|
--
|
||||||
function MESSAGE:ToAll( Settings, Delay )
|
function MESSAGE:ToAll( Settings, Delay )
|
||||||
self:F()
|
self:F()
|
||||||
@@ -461,6 +464,7 @@ _MESSAGESRS = {}
|
|||||||
-- @param #number Volume (optional) Volume, can be between 0.0 and 1.0 (loudest).
|
-- @param #number Volume (optional) Volume, can be between 0.0 and 1.0 (loudest).
|
||||||
-- @param #string Label (optional) Label, defaults to "MESSAGE" or the Message Category set.
|
-- @param #string Label (optional) Label, defaults to "MESSAGE" or the Message Category set.
|
||||||
-- @param Core.Point#COORDINATE Coordinate (optional) Coordinate this messages originates from.
|
-- @param Core.Point#COORDINATE Coordinate (optional) Coordinate this messages originates from.
|
||||||
|
-- @param #string Backend (optional) Backend to be used, can be MSRS.Backend.SRSEXE or MSRS.Backend.GRPC
|
||||||
-- @usage
|
-- @usage
|
||||||
-- -- Mind the dot here, not using the colon this time around!
|
-- -- Mind the dot here, not using the colon this time around!
|
||||||
-- -- Needed once only
|
-- -- Needed once only
|
||||||
@@ -468,7 +472,7 @@ _MESSAGESRS = {}
|
|||||||
-- -- later on in your code
|
-- -- later on in your code
|
||||||
-- MESSAGE:New("Test message!",15,"SPAWN"):ToSRS()
|
-- MESSAGE:New("Test message!",15,"SPAWN"):ToSRS()
|
||||||
--
|
--
|
||||||
function MESSAGE.SetMSRS(PathToSRS,Port,PathToCredentials,Frequency,Modulation,Gender,Culture,Voice,Coalition,Volume,Label,Coordinate)
|
function MESSAGE.SetMSRS(PathToSRS,Port,PathToCredentials,Frequency,Modulation,Gender,Culture,Voice,Coalition,Volume,Label,Coordinate,Backend)
|
||||||
|
|
||||||
_MESSAGESRS.PathToSRS = PathToSRS or MSRS.path or "C:\\Program Files\\DCS-SimpleRadio-Standalone"
|
_MESSAGESRS.PathToSRS = PathToSRS or MSRS.path or "C:\\Program Files\\DCS-SimpleRadio-Standalone"
|
||||||
|
|
||||||
@@ -486,6 +490,10 @@ function MESSAGE.SetMSRS(PathToSRS,Port,PathToCredentials,Frequency,Modulation,G
|
|||||||
_MESSAGESRS.MSRS:SetCoordinate(Coordinate)
|
_MESSAGESRS.MSRS:SetCoordinate(Coordinate)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if Backend then
|
||||||
|
_MESSAGESRS.MSRS:SetBackend(Backend)
|
||||||
|
end
|
||||||
|
|
||||||
_MESSAGESRS.Culture = Culture or MSRS.culture or "en-GB"
|
_MESSAGESRS.Culture = Culture or MSRS.culture or "en-GB"
|
||||||
_MESSAGESRS.MSRS:SetCulture(Culture)
|
_MESSAGESRS.MSRS:SetCulture(Culture)
|
||||||
|
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ do -- COORDINATE
|
|||||||
--
|
--
|
||||||
-- ## 4.4) Get the North correction of the current location.
|
-- ## 4.4) Get the North correction of the current location.
|
||||||
--
|
--
|
||||||
-- * @{#COORDINATE.GetNorthCorrection}(): Obtains the north correction at the current 3D point.
|
-- * @{#COORDINATE.GetNorthCorrectionRadians}(): Obtains the north correction at the current 3D point.
|
||||||
--
|
--
|
||||||
-- ## 4.5) Point Randomization
|
-- ## 4.5) Point Randomization
|
||||||
--
|
--
|
||||||
@@ -985,8 +985,13 @@ do -- COORDINATE
|
|||||||
-- @return DCS#Distance Distance The distance in meters.
|
-- @return DCS#Distance Distance The distance in meters.
|
||||||
function COORDINATE:Get2DDistance(TargetCoordinate)
|
function COORDINATE:Get2DDistance(TargetCoordinate)
|
||||||
if not TargetCoordinate then return 1000000 end
|
if not TargetCoordinate then return 1000000 end
|
||||||
local a={x=TargetCoordinate.x-self.x, y=0, z=TargetCoordinate.z-self.z}
|
--local a={x=TargetCoordinate.x-self.x, y=0, z=TargetCoordinate.z-self.z}
|
||||||
local norm=UTILS.VecNorm(a)
|
local a = self:GetVec2()
|
||||||
|
if not TargetCoordinate.ClassName then
|
||||||
|
TargetCoordinate=COORDINATE:NewFromVec3(TargetCoordinate)
|
||||||
|
end
|
||||||
|
local b = TargetCoordinate:GetVec2()
|
||||||
|
local norm=UTILS.VecDist2D(a,b)
|
||||||
return norm
|
return norm
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1169,6 +1174,162 @@ do -- COORDINATE
|
|||||||
return vec3
|
return vec3
|
||||||
end
|
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}.
|
--- Returns a text documenting the wind direction (from) and strength according the measurement system @{Core.Settings}.
|
||||||
-- The text will reflect the wind like this:
|
-- The text will reflect the wind like this:
|
||||||
@@ -1233,7 +1394,7 @@ do -- COORDINATE
|
|||||||
local s = string.format( '%03d°', AngleDegrees )
|
local s = string.format( '%03d°', AngleDegrees )
|
||||||
|
|
||||||
if MagVar then
|
if MagVar then
|
||||||
local variation = UTILS.GetMagneticDeclination() or 0
|
local variation = self:GetMagneticDeclination() or 0
|
||||||
local AngleMagnetic = AngleDegrees - variation
|
local AngleMagnetic = AngleDegrees - variation
|
||||||
|
|
||||||
if AngleMagnetic < 0 then AngleMagnetic = 360-AngleMagnetic end
|
if AngleMagnetic < 0 then AngleMagnetic = 360-AngleMagnetic end
|
||||||
@@ -1346,13 +1507,16 @@ do -- COORDINATE
|
|||||||
-- @param Core.Settings#SETTINGS Settings
|
-- @param Core.Settings#SETTINGS Settings
|
||||||
-- @param #string Language (Optional) Language "en" or "ru"
|
-- @param #string Language (Optional) Language "en" or "ru"
|
||||||
-- @param #boolean MagVar If true, also state angle in magnetic
|
-- @param #boolean MagVar If true, also state angle in magnetic
|
||||||
|
-- @param #number Precision Rounding precision, defaults to 0
|
||||||
-- @return #string The BR Text
|
-- @return #string The BR Text
|
||||||
function COORDINATE:GetBRText( AngleRadians, Distance, Settings, Language, MagVar )
|
function COORDINATE:GetBRText( AngleRadians, Distance, Settings, Language, MagVar, Precision )
|
||||||
|
|
||||||
local Settings = Settings or _SETTINGS -- Core.Settings#SETTINGS
|
local Settings = Settings or _SETTINGS -- Core.Settings#SETTINGS
|
||||||
|
|
||||||
|
Precision = Precision or 0
|
||||||
|
|
||||||
local BearingText = self:GetBearingText( AngleRadians, 0, Settings, MagVar )
|
local BearingText = self:GetBearingText( AngleRadians, 0, Settings, MagVar )
|
||||||
local DistanceText = self:GetDistanceText( Distance, Settings, Language, 0 )
|
local DistanceText = self:GetDistanceText( Distance, Settings, Language, Precision )
|
||||||
|
|
||||||
local BRText = BearingText .. DistanceText
|
local BRText = BearingText .. DistanceText
|
||||||
|
|
||||||
@@ -1974,9 +2138,18 @@ do -- COORDINATE
|
|||||||
--- Smokes the point in a color.
|
--- Smokes the point in a color.
|
||||||
-- @param #COORDINATE self
|
-- @param #COORDINATE self
|
||||||
-- @param Utilities.Utils#SMOKECOLOR SmokeColor
|
-- @param Utilities.Utils#SMOKECOLOR SmokeColor
|
||||||
function COORDINATE:Smoke( 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:F2( { SmokeColor } )
|
||||||
trigger.action.smoke( self:GetVec3(), SmokeColor )
|
self.firename = name or "Smoke-"..math.random(1,100000)
|
||||||
|
trigger.action.smoke( self:GetVec3(), SmokeColor, self.firename )
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Stops smoking the point in a color.
|
||||||
|
-- @param #COORDINATE self
|
||||||
|
-- @param #string name (Optional) Name if you want to stop the smoke early (normal duration: 5mins)
|
||||||
|
function COORDINATE:StopSmoke( name )
|
||||||
|
self:StopBigSmokeAndFire( name )
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Smoke the COORDINATE Green.
|
--- Smoke the COORDINATE Green.
|
||||||
@@ -2427,7 +2600,7 @@ do -- COORDINATE
|
|||||||
for i,coord in ipairs(Coordinates) do
|
for i,coord in ipairs(Coordinates) do
|
||||||
vecs[i+1]=coord:GetVec3()
|
vecs[i+1]=coord:GetVec3()
|
||||||
end
|
end
|
||||||
|
|
||||||
if #vecs<3 then
|
if #vecs<3 then
|
||||||
self:E("ERROR: A free form polygon needs at least three points!")
|
self:E("ERROR: A free form polygon needs at least three points!")
|
||||||
elseif #vecs==3 then
|
elseif #vecs==3 then
|
||||||
@@ -2686,9 +2859,9 @@ do -- COORDINATE
|
|||||||
local date=UTILS.GetDCSMissionDate()
|
local date=UTILS.GetDCSMissionDate()
|
||||||
|
|
||||||
-- Debug output.
|
-- Debug output.
|
||||||
--self:I(string.format("Sun rise at lat=%.3f long=%.3f on %s (DayOfYear=%d): %s (%d sec of the day) (GMT %d)", Latitude, Longitude, date, DayOfYear, tostring(UTILS.SecondsToClock(sunrise)), sunrise, Tdiff))
|
--self:I(string.format("Sun rise at lat=%.3f long=%.3f on %s (DayOfYear=%d): %s (%s sec of the day) (GMT %d)", Latitude, Longitude, date, DayOfYear, tostring(UTILS.SecondsToClock(sunrise)), tonumber(sunrise) or "0", Tdiff))
|
||||||
|
|
||||||
if InSeconds then
|
if InSeconds or type(sunrise) == "string" then
|
||||||
return sunrise
|
return sunrise
|
||||||
else
|
else
|
||||||
return UTILS.SecondsToClock(sunrise, true)
|
return UTILS.SecondsToClock(sunrise, true)
|
||||||
@@ -2854,9 +3027,9 @@ do -- COORDINATE
|
|||||||
local date=UTILS.GetDCSMissionDate()
|
local date=UTILS.GetDCSMissionDate()
|
||||||
|
|
||||||
-- Debug output.
|
-- Debug output.
|
||||||
--self:I(string.format("Sun set at lat=%.3f long=%.3f on %s (DayOfYear=%d): %s (%d sec of the day) (GMT %d)", Latitude, Longitude, date, DayOfYear, tostring(UTILS.SecondsToClock(sunrise)), sunrise, Tdiff))
|
--self:I(string.format("Sun set at lat=%.3f long=%.3f on %s (DayOfYear=%d): %s (%s sec of the day) (GMT %d)", Latitude, Longitude, date, DayOfYear, tostring(UTILS.SecondsToClock(sunrise)), tostring(sunrise) or "0", Tdiff))
|
||||||
|
|
||||||
if InSeconds then
|
if InSeconds or type(sunrise) == "string" then
|
||||||
return sunrise
|
return sunrise
|
||||||
else
|
else
|
||||||
return UTILS.SecondsToClock(sunrise, true)
|
return UTILS.SecondsToClock(sunrise, true)
|
||||||
@@ -2917,12 +3090,13 @@ do -- COORDINATE
|
|||||||
-- @param #COORDINATE FromCoordinate The coordinate to measure the distance and the bearing from.
|
-- @param #COORDINATE FromCoordinate The coordinate to measure the distance and the bearing from.
|
||||||
-- @param Core.Settings#SETTINGS Settings (optional) The settings. Can be nil, and in this case the default settings are used. If you want to specify your own settings, use the _SETTINGS object.
|
-- @param Core.Settings#SETTINGS Settings (optional) The settings. Can be nil, and in this case the default settings are used. If you want to specify your own settings, use the _SETTINGS object.
|
||||||
-- @param #boolean MagVar If true, also get angle in MagVar for BR/BRA
|
-- @param #boolean MagVar If true, also get angle in MagVar for BR/BRA
|
||||||
|
-- @param #number Precision Rounding precision, currently full km as default (=0)
|
||||||
-- @return #string The BR text.
|
-- @return #string The BR text.
|
||||||
function COORDINATE:ToStringBR( FromCoordinate, Settings, MagVar )
|
function COORDINATE:ToStringBR( FromCoordinate, Settings, MagVar, Precision )
|
||||||
local DirectionVec3 = FromCoordinate:GetDirectionVec3( self )
|
local DirectionVec3 = FromCoordinate:GetDirectionVec3( self )
|
||||||
local AngleRadians = self:GetAngleRadians( DirectionVec3 )
|
local AngleRadians = self:GetAngleRadians( DirectionVec3 )
|
||||||
local Distance = self:Get2DDistance( FromCoordinate )
|
local Distance = self:Get2DDistance( FromCoordinate )
|
||||||
return "BR, " .. self:GetBRText( AngleRadians, Distance, Settings, nil, MagVar )
|
return "BR, " .. self:GetBRText( AngleRadians, Distance, Settings, nil, MagVar, Precision )
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Return a BRA string from a COORDINATE to the COORDINATE.
|
--- Return a BRA string from a COORDINATE to the COORDINATE.
|
||||||
@@ -2958,6 +3132,8 @@ do -- COORDINATE
|
|||||||
local AngleRadians = self:GetAngleRadians( DirectionVec3 )
|
local AngleRadians = self:GetAngleRadians( DirectionVec3 )
|
||||||
|
|
||||||
local bearing = UTILS.Round( UTILS.ToDegree( AngleRadians ),0 )
|
local bearing = UTILS.Round( UTILS.ToDegree( AngleRadians ),0 )
|
||||||
|
local magnetic = self:GetMagneticDeclination() or 0
|
||||||
|
bearing = bearing - magnetic
|
||||||
|
|
||||||
local rangeMetres = self:Get2DDistance(currentCoord)
|
local rangeMetres = self:Get2DDistance(currentCoord)
|
||||||
local rangeNM = UTILS.Round( UTILS.MetersToNM(rangeMetres), 0)
|
local rangeNM = UTILS.Round( UTILS.MetersToNM(rangeMetres), 0)
|
||||||
@@ -3330,16 +3506,16 @@ do -- COORDINATE
|
|||||||
-- @param #COORDINATE self
|
-- @param #COORDINATE self
|
||||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The controllable to retrieve the settings from, otherwise the default settings will be chosen.
|
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The controllable to retrieve the settings from, otherwise the default settings will be chosen.
|
||||||
-- @param Core.Settings#SETTINGS Settings (optional) The settings. Can be nil, and in this case the default settings are used. If you want to specify your own settings, use the _SETTINGS object.
|
-- @param Core.Settings#SETTINGS Settings (optional) The settings. Can be nil, and in this case the default settings are used. If you want to specify your own settings, use the _SETTINGS object.
|
||||||
-- @param Tasking.Task#TASK Task The task for which coordinates need to be calculated.
|
|
||||||
-- @return #string The coordinate Text in the configured coordinate system.
|
-- @return #string The coordinate Text in the configured coordinate system.
|
||||||
function COORDINATE:ToString( Controllable, Settings, Task )
|
function COORDINATE:ToString( Controllable, Settings )
|
||||||
|
|
||||||
-- self:E( { Controllable = Controllable and Controllable:GetName() } )
|
-- self:E( { Controllable = Controllable and Controllable:GetName() } )
|
||||||
|
|
||||||
local Settings = Settings or ( Controllable and _DATABASE:GetPlayerSettings( Controllable:GetPlayerName() ) ) or _SETTINGS
|
local Settings = Settings or ( Controllable and _DATABASE:GetPlayerSettings( Controllable:GetPlayerName() ) ) or _SETTINGS
|
||||||
|
|
||||||
local ModeA2A = nil
|
local ModeA2A = nil
|
||||||
|
|
||||||
|
--[[
|
||||||
if Task then
|
if Task then
|
||||||
if Task:IsInstanceOf( TASK_A2A ) then
|
if Task:IsInstanceOf( TASK_A2A ) then
|
||||||
ModeA2A = true
|
ModeA2A = true
|
||||||
@@ -3356,7 +3532,7 @@ do -- COORDINATE
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
--]]
|
||||||
|
|
||||||
if ModeA2A == nil then
|
if ModeA2A == nil then
|
||||||
local IsAir = Controllable and ( Controllable:IsAirPlane() or Controllable:IsHelicopter() ) or false
|
local IsAir = Controllable and ( Controllable:IsAirPlane() or Controllable:IsHelicopter() ) or false
|
||||||
@@ -3431,7 +3607,7 @@ do -- COORDINATE
|
|||||||
-- @param #COORDINATE self
|
-- @param #COORDINATE self
|
||||||
-- @param #number Radius (Optional) Radius to check around the coordinate, defaults to 50m (100m diameter)
|
-- @param #number Radius (Optional) Radius to check around the coordinate, defaults to 50m (100m diameter)
|
||||||
-- @param #number Minelevation (Optional) Elevation from which on a area is defined as steep, defaults to 8% (8m height gain across 100 meters)
|
-- @param #number Minelevation (Optional) Elevation from which on a area is defined as steep, defaults to 8% (8m height gain across 100 meters)
|
||||||
-- @return #boolen IsSteep If true, area is steep
|
-- @return #boolean IsSteep If true, area is steep
|
||||||
-- @return #number MaxElevation Elevation in meters measured over 100m
|
-- @return #number MaxElevation Elevation in meters measured over 100m
|
||||||
function COORDINATE:IsInSteepArea(Radius,Minelevation)
|
function COORDINATE:IsInSteepArea(Radius,Minelevation)
|
||||||
local steep = false
|
local steep = false
|
||||||
@@ -3463,7 +3639,7 @@ do -- COORDINATE
|
|||||||
-- @param #COORDINATE self
|
-- @param #COORDINATE self
|
||||||
-- @param #number Radius (Optional) Radius to check around the coordinate, defaults to 50m (100m diameter)
|
-- @param #number Radius (Optional) Radius to check around the coordinate, defaults to 50m (100m diameter)
|
||||||
-- @param #number Minelevation (Optional) Elevation from which on a area is defined as steep, defaults to 8% (8m height gain across 100 meters)
|
-- @param #number Minelevation (Optional) Elevation from which on a area is defined as steep, defaults to 8% (8m height gain across 100 meters)
|
||||||
-- @return #boolen IsFlat If true, area is flat
|
-- @return #boolean IsFlat If true, area is flat
|
||||||
-- @return #number MaxElevation Elevation in meters measured over 100m
|
-- @return #number MaxElevation Elevation in meters measured over 100m
|
||||||
function COORDINATE:IsInFlatArea(Radius,Minelevation)
|
function COORDINATE:IsInFlatArea(Radius,Minelevation)
|
||||||
local steep, elev = self:IsInSteepArea(Radius,Minelevation)
|
local steep, elev = self:IsInSteepArea(Radius,Minelevation)
|
||||||
@@ -3471,9 +3647,18 @@ do -- COORDINATE
|
|||||||
return flat, elev
|
return flat, elev
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
do -- POINT_VEC3
|
do
|
||||||
|
|
||||||
--- The POINT_VEC3 class
|
--- The POINT_VEC3 class
|
||||||
-- @type POINT_VEC3
|
-- @type POINT_VEC3
|
||||||
@@ -3490,6 +3675,8 @@ do -- POINT_VEC3
|
|||||||
|
|
||||||
--- Defines a 3D point in the simulator and with its methods, you can use or manipulate the point in 3D space.
|
--- 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.
|
-- **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,
|
-- 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,
|
-- I want to emphasize that the formulas embedded in the MIST framework were created by Grimes or previous authors,
|
||||||
@@ -3577,130 +3764,19 @@ do -- POINT_VEC3
|
|||||||
return self
|
return self
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
do -- POINT_VEC2
|
do
|
||||||
|
|
||||||
-- @type POINT_VEC2
|
--- @type POINT_VEC2
|
||||||
-- @field DCS#Distance x The x coordinate in meters.
|
-- @field DCS#Distance x The x coordinate in meters.
|
||||||
-- @field DCS#Distance y the y coordinate in meters.
|
-- @field DCS#Distance y the y coordinate in meters.
|
||||||
-- @extends Core.Point#COORDINATE
|
-- @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.
|
--- 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
|
-- ## POINT_VEC2 constructor
|
||||||
--
|
--
|
||||||
-- A new POINT_VEC2 instance can be created with:
|
-- A new POINT_VEC2 instance can be created with:
|
||||||
@@ -3748,166 +3824,4 @@ do -- POINT_VEC2
|
|||||||
return self
|
return self
|
||||||
end
|
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
|
end
|
||||||
|
|||||||
@@ -15,7 +15,8 @@
|
|||||||
-- @module Core.Report
|
-- @module Core.Report
|
||||||
-- @image Core_Report.JPG
|
-- @image Core_Report.JPG
|
||||||
|
|
||||||
--- @type REPORT
|
---
|
||||||
|
-- @type REPORT
|
||||||
-- @extends Core.Base#BASE
|
-- @extends Core.Base#BASE
|
||||||
|
|
||||||
--- Provides a handy means to create messages and reports.
|
--- Provides a handy means to create messages and reports.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
--- **Core** - SCHEDULEDISPATCHER dispatches the different schedules.
|
---- **Core** - SCHEDULEDISPATCHER dispatches the different schedules.
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
|
|||||||
+1140
-364
File diff suppressed because it is too large
Load Diff
@@ -29,7 +29,9 @@
|
|||||||
-- @module Core.Settings
|
-- @module Core.Settings
|
||||||
-- @image Core_Settings.JPG
|
-- @image Core_Settings.JPG
|
||||||
|
|
||||||
--- @type SETTINGS
|
|
||||||
|
---
|
||||||
|
-- @type SETTINGS
|
||||||
-- @extends Core.Base#BASE
|
-- @extends Core.Base#BASE
|
||||||
|
|
||||||
--- Takes care of various settings that influence the behavior of certain functionalities and classes within the MOOSE framework.
|
--- Takes care of various settings that influence the behavior of certain functionalities and classes within the MOOSE framework.
|
||||||
@@ -218,7 +220,8 @@ SETTINGS = {
|
|||||||
|
|
||||||
SETTINGS.__Enum = {}
|
SETTINGS.__Enum = {}
|
||||||
|
|
||||||
--- @type SETTINGS.__Enum.Era
|
---
|
||||||
|
-- @type SETTINGS.__Enum.Era
|
||||||
-- @field #number WWII
|
-- @field #number WWII
|
||||||
-- @field #number Korea
|
-- @field #number Korea
|
||||||
-- @field #number Cold
|
-- @field #number Cold
|
||||||
@@ -737,8 +740,8 @@ do -- SETTINGS
|
|||||||
if _SETTINGS.ShowPlayerMenu == true then
|
if _SETTINGS.ShowPlayerMenu == true then
|
||||||
|
|
||||||
local PlayerGroup = PlayerUnit:GetGroup()
|
local PlayerGroup = PlayerUnit:GetGroup()
|
||||||
local PlayerName = PlayerUnit:GetPlayerName()
|
local PlayerName = PlayerUnit:GetPlayerName() or "None"
|
||||||
local PlayerNames = PlayerGroup:GetPlayerNames()
|
--local PlayerNames = PlayerGroup:GetPlayerNames()
|
||||||
|
|
||||||
local PlayerMenu = MENU_GROUP:New( PlayerGroup, 'Settings "' .. PlayerName .. '"' )
|
local PlayerMenu = MENU_GROUP:New( PlayerGroup, 'Settings "' .. PlayerName .. '"' )
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -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.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.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**!
|
-- * @{#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
|
-- @field #SPAWNSTATIC SPAWNSTATIC
|
||||||
@@ -189,6 +189,7 @@ function SPAWNSTATIC:NewFromType(StaticType, StaticCategory, CountryID)
|
|||||||
self.InitStaticCategory=StaticCategory
|
self.InitStaticCategory=StaticCategory
|
||||||
self.CountryID=CountryID or country.id.USA
|
self.CountryID=CountryID or country.id.USA
|
||||||
self.SpawnTemplatePrefix=self.InitStaticType
|
self.SpawnTemplatePrefix=self.InitStaticType
|
||||||
|
self.TemplateStaticUnit = {}
|
||||||
|
|
||||||
self.InitStaticCoordinate=COORDINATE:New(0, 0, 0)
|
self.InitStaticCoordinate=COORDINATE:New(0, 0, 0)
|
||||||
self.InitStaticHeading=0
|
self.InitStaticHeading=0
|
||||||
@@ -196,6 +197,61 @@ function SPAWNSTATIC:NewFromType(StaticType, StaticCategory, CountryID)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- (Internal/Cargo) Init the resource table for STATIC object that should be spawned containing storage objects.
|
||||||
|
-- NOTE that you have to init many other parameters as the resources.
|
||||||
|
-- @param #SPAWNSTATIC self
|
||||||
|
-- @param #number CombinedWeight The weight this cargo object should have (some have fixed weights!), defaults to 1kg.
|
||||||
|
-- @return #SPAWNSTATIC self
|
||||||
|
function SPAWNSTATIC:_InitResourceTable(CombinedWeight)
|
||||||
|
if not self.TemplateStaticUnit.resourcePayload then
|
||||||
|
self.TemplateStaticUnit.resourcePayload = {
|
||||||
|
["weapons"] = {},
|
||||||
|
["aircrafts"] = {},
|
||||||
|
["gasoline"] = 0,
|
||||||
|
["diesel"] = 0,
|
||||||
|
["methanol_mixture"] = 0,
|
||||||
|
["jet_fuel"] = 0,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
self:InitCargo(true)
|
||||||
|
self:InitCargoMass(CombinedWeight or 1)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- (User/Cargo) Add to resource table for STATIC object that should be spawned containing storage objects. Inits the object table if necessary and sets it to be cargo for helicopters.
|
||||||
|
-- @param #SPAWNSTATIC self
|
||||||
|
-- @param #string Type Type of cargo. Known types are: STORAGE.Type.WEAPONS, STORAGE.Type.LIQUIDS, STORAGE.Type.AIRCRAFT. Liquids are fuel.
|
||||||
|
-- @param #string Name Name of the cargo type. Liquids can be STORAGE.LiquidName.JETFUEL, STORAGE.LiquidName.GASOLINE, STORAGE.LiquidName.MW50 and STORAGE.LiquidName.DIESEL. The currently available weapon items are available in the `ENUMS.Storage.weapons`, e.g. `ENUMS.Storage.weapons.bombs.Mk_82Y`. Aircraft go by their typename.
|
||||||
|
-- @param #number Amount of tons (liquids) or number (everything else) to add.
|
||||||
|
-- @param #number CombinedWeight Combined weight to be set to this static cargo object. NOTE - some static cargo objects have fixed weights!
|
||||||
|
-- @return #SPAWNSTATIC self
|
||||||
|
function SPAWNSTATIC:AddCargoResource(Type,Name,Amount,CombinedWeight)
|
||||||
|
if not self.TemplateStaticUnit.resourcePayload then
|
||||||
|
self:_InitResourceTable(CombinedWeight)
|
||||||
|
end
|
||||||
|
if Type == STORAGE.Type.LIQUIDS and type(Name) == "string" then
|
||||||
|
self.TemplateStaticUnit.resourcePayload[Name] = Amount
|
||||||
|
else
|
||||||
|
self.TemplateStaticUnit.resourcePayload[Type] = {
|
||||||
|
[Name] = {
|
||||||
|
["amount"] = Amount,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
UTILS.PrintTableToLog(self.TemplateStaticUnit)
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- (User/Cargo) Resets resource table to zero for STATIC object that should be spawned containing storage objects. Inits the object table if necessary and sets it to be cargo for helicopters.
|
||||||
|
-- Handy if you spawn from cargo statics which have resources already set.
|
||||||
|
-- @param #SPAWNSTATIC self
|
||||||
|
-- @return #SPAWNSTATIC self
|
||||||
|
function SPAWNSTATIC:ResetCargoResources()
|
||||||
|
self.TemplateStaticUnit.resourcePayload = nil
|
||||||
|
self:_InitResourceTable()
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- Initialize heading of the spawned static.
|
--- Initialize heading of the spawned static.
|
||||||
-- @param #SPAWNSTATIC self
|
-- @param #SPAWNSTATIC self
|
||||||
-- @param Core.Point#COORDINATE Coordinate Position where the static is spawned.
|
-- @param Core.Point#COORDINATE Coordinate Position where the static is spawned.
|
||||||
@@ -317,6 +373,25 @@ function SPAWNSTATIC:InitLinkToUnit(Unit, OffsetX, OffsetY, OffsetAngle)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Allows to place a CallFunction hook when a new static spawns.
|
||||||
|
-- The provided method will be called when a new group is spawned, including its given parameters.
|
||||||
|
-- The first parameter of the SpawnFunction is the @{Wrapper.Static#STATIC} that was spawned.
|
||||||
|
-- @param #SPAWNSTATIC self
|
||||||
|
-- @param #function SpawnCallBackFunction The function to be called when a group spawns.
|
||||||
|
-- @param SpawnFunctionArguments A random amount of arguments to be provided to the function when the group spawns.
|
||||||
|
-- @return #SPAWNSTATIC self
|
||||||
|
function SPAWNSTATIC:OnSpawnStatic( SpawnCallBackFunction, ... )
|
||||||
|
self:F( "OnSpawnStatic" )
|
||||||
|
|
||||||
|
self.SpawnFunctionHook = SpawnCallBackFunction
|
||||||
|
self.SpawnFunctionArguments = {}
|
||||||
|
if arg then
|
||||||
|
self.SpawnFunctionArguments = arg
|
||||||
|
end
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- Spawn a new STATIC object.
|
--- Spawn a new STATIC object.
|
||||||
-- @param #SPAWNSTATIC self
|
-- @param #SPAWNSTATIC self
|
||||||
-- @param #number Heading (Optional) The heading of the static, which is a number in degrees from 0 to 360. Default is the heading of the template.
|
-- @param #number Heading (Optional) The heading of the static, which is a number in degrees from 0 to 360. Default is the heading of the template.
|
||||||
@@ -336,9 +411,9 @@ function SPAWNSTATIC:Spawn(Heading, NewName)
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Creates a new @{Wrapper.Static} from a POINT_VEC2.
|
--- Creates a new @{Wrapper.Static} from a COORDINATE.
|
||||||
-- @param #SPAWNSTATIC self
|
-- @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 #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.
|
-- @param #string NewName (Optional) The name of the new static.
|
||||||
-- @return Wrapper.Static#STATIC The static spawned.
|
-- @return Wrapper.Static#STATIC The static spawned.
|
||||||
@@ -460,12 +535,6 @@ function SPAWNSTATIC:_SpawnStatic(Template, CountryID)
|
|||||||
-- Name of the spawned static.
|
-- Name of the spawned static.
|
||||||
Template.name = self.InitStaticName or string.format("%s#%05d", self.SpawnTemplatePrefix, self.SpawnIndex)
|
Template.name = self.InitStaticName or string.format("%s#%05d", self.SpawnTemplatePrefix, self.SpawnIndex)
|
||||||
|
|
||||||
-- Add and register the new static.
|
|
||||||
local mystatic=_DATABASE:AddStatic(Template.name)
|
|
||||||
|
|
||||||
-- Debug output.
|
|
||||||
self:T(Template)
|
|
||||||
|
|
||||||
-- Add static to the game.
|
-- Add static to the game.
|
||||||
local Static=nil --DCS#StaticObject
|
local Static=nil --DCS#StaticObject
|
||||||
|
|
||||||
@@ -488,7 +557,7 @@ function SPAWNSTATIC:_SpawnStatic(Template, CountryID)
|
|||||||
-- ED's dirty way to spawn FARPS.
|
-- ED's dirty way to spawn FARPS.
|
||||||
Static=coalition.addGroup(CountryID, -1, TemplateGroup)
|
Static=coalition.addGroup(CountryID, -1, TemplateGroup)
|
||||||
|
|
||||||
-- Currently DCS 2.8 does not trigger birth events if FAPRS are spawned!
|
-- Currently DCS 2.8 does not trigger birth events if FARPS are spawned!
|
||||||
-- We create such an event. The airbase is registered in Core.Event
|
-- We create such an event. The airbase is registered in Core.Event
|
||||||
local Event = {
|
local Event = {
|
||||||
id = EVENTS.Birth,
|
id = EVENTS.Birth,
|
||||||
@@ -502,6 +571,28 @@ function SPAWNSTATIC:_SpawnStatic(Template, CountryID)
|
|||||||
self:T("Spawning Static")
|
self:T("Spawning Static")
|
||||||
self:T2({Template=Template})
|
self:T2({Template=Template})
|
||||||
Static=coalition.addStaticObject(CountryID, Template)
|
Static=coalition.addStaticObject(CountryID, Template)
|
||||||
|
|
||||||
|
if Static then
|
||||||
|
self:T(string.format("Succesfully spawned static object \"%s\" ID=%d", Static:getName(), Static:getID()))
|
||||||
|
--[[
|
||||||
|
local static=StaticObject.getByName(Static:getName())
|
||||||
|
if static then
|
||||||
|
env.info(string.format("FF got static from StaticObject.getByName"))
|
||||||
|
else
|
||||||
|
env.error(string.format("FF error did NOT get static from StaticObject.getByName"))
|
||||||
|
end ]]
|
||||||
|
else
|
||||||
|
self:E(string.format("ERROR: DCS static object \"%s\" is nil!", tostring(Template.name)))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Add and register the new static.
|
||||||
|
local mystatic=_DATABASE:AddStatic(Template.name)
|
||||||
|
|
||||||
|
-- If there is a SpawnFunction hook defined, call it.
|
||||||
|
if self.SpawnFunctionHook then
|
||||||
|
-- delay calling this for .3 seconds so that it hopefully comes after the BIRTH event of the group.
|
||||||
|
self:ScheduleOnce(0.3, self.SpawnFunctionHook, mystatic, unpack(self.SpawnFunctionArguments))
|
||||||
end
|
end
|
||||||
|
|
||||||
return mystatic
|
return mystatic
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
do -- UserFlag
|
do -- UserFlag
|
||||||
|
|
||||||
--- @type USERFLAG
|
-- @type USERFLAG
|
||||||
-- @field #string ClassName Name of the class
|
-- @field #string ClassName Name of the class
|
||||||
-- @field #string UserFlagName Name of the flag.
|
-- @field #string UserFlagName Name of the flag.
|
||||||
-- @extends Core.Base#BASE
|
-- @extends Core.Base#BASE
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
do -- Velocity
|
do -- Velocity
|
||||||
|
|
||||||
--- @type VELOCITY
|
-- @type VELOCITY
|
||||||
-- @extends Core.Base#BASE
|
-- @extends Core.Base#BASE
|
||||||
|
|
||||||
|
|
||||||
@@ -127,7 +127,7 @@ end
|
|||||||
|
|
||||||
do -- VELOCITY_POSITIONABLE
|
do -- VELOCITY_POSITIONABLE
|
||||||
|
|
||||||
--- @type VELOCITY_POSITIONABLE
|
-- @type VELOCITY_POSITIONABLE
|
||||||
-- @extends Core.Base#BASE
|
-- @extends Core.Base#BASE
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,8 @@
|
|||||||
-- @module Core.Zone_Detection
|
-- @module Core.Zone_Detection
|
||||||
-- @image MOOSE.JPG
|
-- @image MOOSE.JPG
|
||||||
|
|
||||||
--- @type ZONE_DETECTION
|
---
|
||||||
|
-- @type ZONE_DETECTION
|
||||||
-- @field DCS#Vec2 Vec2 The current location of the zone.
|
-- @field DCS#Vec2 Vec2 The current location of the zone.
|
||||||
-- @field DCS#Distance Radius The radius of the zone.
|
-- @field DCS#Distance Radius The radius of the zone.
|
||||||
-- @extends #ZONE_BASE
|
-- @extends #ZONE_BASE
|
||||||
@@ -106,7 +107,7 @@ function ZONE_DETECTION:SmokeZone( SmokeColor, Points, AddHeight, AngleOffset )
|
|||||||
local Radial = ( Angle + AngleOffset ) * RadialBase / 360
|
local Radial = ( Angle + AngleOffset ) * RadialBase / 360
|
||||||
Point.x = Vec2.x + math.cos( Radial ) * self:GetRadius()
|
Point.x = Vec2.x + math.cos( Radial ) * self:GetRadius()
|
||||||
Point.y = Vec2.y + math.sin( 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
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
@@ -137,7 +138,7 @@ function ZONE_DETECTION:FlareZone( FlareColor, Points, Azimuth, AddHeight )
|
|||||||
local Radial = Angle * RadialBase / 360
|
local Radial = Angle * RadialBase / 360
|
||||||
Point.x = Vec2.x + math.cos( Radial ) * self:GetRadius()
|
Point.x = Vec2.x + math.cos( Radial ) * self:GetRadius()
|
||||||
Point.y = Vec2.y + math.sin( 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
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
@@ -201,4 +202,3 @@ function ZONE_DETECTION:IsVec3InZone( Vec3 )
|
|||||||
|
|
||||||
return InZone
|
return InZone
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
+432
-378
File diff suppressed because it is too large
Load Diff
@@ -18,7 +18,7 @@
|
|||||||
-- ### Author: FlightControl - Framework Design & Programming
|
-- ### Author: FlightControl - Framework Design & Programming
|
||||||
-- ### Refactoring to use the Runway auto-detection: Applevangelist
|
-- ### Refactoring to use the Runway auto-detection: Applevangelist
|
||||||
-- @date August 2022
|
-- @date August 2022
|
||||||
-- Last Update Nov 2023
|
-- Last Update Feb 2025
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
@@ -416,7 +416,7 @@ end
|
|||||||
-- @field #ATC_GROUND_UNIVERSAL
|
-- @field #ATC_GROUND_UNIVERSAL
|
||||||
ATC_GROUND_UNIVERSAL = {
|
ATC_GROUND_UNIVERSAL = {
|
||||||
ClassName = "ATC_GROUND_UNIVERSAL",
|
ClassName = "ATC_GROUND_UNIVERSAL",
|
||||||
Version = "0.0.1",
|
Version = "0.0.2",
|
||||||
SetClient = nil,
|
SetClient = nil,
|
||||||
Airbases = nil,
|
Airbases = nil,
|
||||||
AirbaseList = nil,
|
AirbaseList = nil,
|
||||||
@@ -441,17 +441,25 @@ function ATC_GROUND_UNIVERSAL:New(AirbaseList)
|
|||||||
self:T( { self.ClassName } )
|
self:T( { self.ClassName } )
|
||||||
|
|
||||||
self.Airbases = {}
|
self.Airbases = {}
|
||||||
|
|
||||||
for _name,_ in pairs(_DATABASE.AIRBASES) do
|
|
||||||
self.Airbases[_name]={}
|
|
||||||
end
|
|
||||||
|
|
||||||
self.AirbaseList = AirbaseList
|
self.AirbaseList = AirbaseList
|
||||||
|
|
||||||
if not self.AirbaseList then
|
if not self.AirbaseList then
|
||||||
self.AirbaseList = {}
|
self.AirbaseList = {}
|
||||||
for _name,_ in pairs(_DATABASE.AIRBASES) do
|
for _name,_base in pairs(_DATABASE.AIRBASES) do
|
||||||
self.AirbaseList[_name]=_name
|
-- DONE exclude FARPS and Ships
|
||||||
|
if _base and _base.isAirdrome == true then
|
||||||
|
self.AirbaseList[_name]=_name
|
||||||
|
self.Airbases[_name]={}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
for _,_name in pairs(AirbaseList) do
|
||||||
|
-- DONE exclude FARPS and Ships
|
||||||
|
local airbase = _DATABASE:FindAirbase(_name)
|
||||||
|
if airbase and (airbase.isAirdrome == true) then
|
||||||
|
self.Airbases[_name]={}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -721,14 +729,18 @@ function ATC_GROUND_UNIVERSAL:_AirbaseMonitor()
|
|||||||
|
|
||||||
if NotInRunwayZone then
|
if NotInRunwayZone then
|
||||||
|
|
||||||
|
local Taxi = Client:GetState( self, "Taxi" )
|
||||||
|
|
||||||
if IsOnGround then
|
if IsOnGround then
|
||||||
local Taxi = Client:GetState( self, "Taxi" )
|
|
||||||
self:T( Taxi )
|
self:T( Taxi )
|
||||||
if Taxi == false then
|
if Taxi == false then
|
||||||
local Velocity = VELOCITY:New( AirbaseMeta.KickSpeed or self.KickSpeed )
|
local Velocity = VELOCITY:New( AirbaseMeta.KickSpeed or self.KickSpeed )
|
||||||
Client:Message( "Welcome to " .. AirbaseID .. ". The maximum taxiing speed is " ..
|
Client:Message( "Welcome to " .. AirbaseID .. ". The maximum taxiing speed is " ..
|
||||||
Velocity:ToString() , 20, "ATC" )
|
Velocity:ToString() , 20, "ATC" )
|
||||||
Client:SetState( self, "Taxi", true )
|
Client:SetState( self, "Taxi", true )
|
||||||
|
Client:SetState( self, "Speeding", false )
|
||||||
|
Client:SetState( self, "Warnings", 0 )
|
||||||
end
|
end
|
||||||
|
|
||||||
-- TODO: GetVelocityKMH function usage
|
-- TODO: GetVelocityKMH function usage
|
||||||
@@ -737,7 +749,7 @@ function ATC_GROUND_UNIVERSAL:_AirbaseMonitor()
|
|||||||
local IsAboveRunway = Client:IsAboveRunway()
|
local IsAboveRunway = Client:IsAboveRunway()
|
||||||
self:T( {IsAboveRunway, IsOnGround, Velocity:Get() })
|
self:T( {IsAboveRunway, IsOnGround, Velocity:Get() })
|
||||||
|
|
||||||
if IsOnGround then
|
if IsOnGround and not Taxi then
|
||||||
local Speeding = false
|
local Speeding = false
|
||||||
if AirbaseMeta.MaximumKickSpeed then
|
if AirbaseMeta.MaximumKickSpeed then
|
||||||
if Velocity:Get() > AirbaseMeta.MaximumKickSpeed then
|
if Velocity:Get() > AirbaseMeta.MaximumKickSpeed then
|
||||||
@@ -749,15 +761,17 @@ function ATC_GROUND_UNIVERSAL:_AirbaseMonitor()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
if Speeding == true then
|
if Speeding == true then
|
||||||
MESSAGE:New( "Penalty! Player " .. Client:GetPlayerName() ..
|
--MESSAGE:New( "Penalty! Player " .. Client:GetPlayerName() ..
|
||||||
" has been kicked, due to a severe airbase traffic rule violation ...", 10, "ATC" ):ToAll()
|
-- " has been kicked, due to a severe airbase traffic rule violation ...", 10, "ATC" ):ToAll()
|
||||||
Client:Destroy()
|
--Client:Destroy()
|
||||||
Client:SetState( self, "Speeding", false )
|
Client:SetState( self, "Speeding", true )
|
||||||
Client:SetState( self, "Warnings", 0 )
|
local SpeedingWarnings = Client:GetState( self, "Warnings" )
|
||||||
|
Client:SetState( self, "Warnings", SpeedingWarnings + 1 )
|
||||||
|
Client:Message( "Warning " .. SpeedingWarnings .. "/3! Airbase traffic rule violation! Slow down now! Your speed is " ..
|
||||||
|
Velocity:ToString(), 5, "ATC" )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
if IsOnGround then
|
if IsOnGround then
|
||||||
|
|
||||||
local Speeding = false
|
local Speeding = false
|
||||||
@@ -1035,23 +1049,23 @@ end
|
|||||||
-- The following airbases are monitored at the Nevada region.
|
-- The following airbases are monitored at the Nevada region.
|
||||||
-- Use the @{Wrapper.Airbase#AIRBASE.Nevada} enumeration to select the airbases to be monitored.
|
-- Use the @{Wrapper.Airbase#AIRBASE.Nevada} enumeration to select the airbases to be monitored.
|
||||||
--
|
--
|
||||||
-- * `AIRBASE.Nevada.Beatty_Airport`
|
-- * `AIRBASE.Nevada.Beatty`
|
||||||
-- * `AIRBASE.Nevada.Boulder_City_Airport`
|
-- * `AIRBASE.Nevada.Boulder_City`
|
||||||
-- * `AIRBASE.Nevada.Creech_AFB`
|
-- * `AIRBASE.Nevada.Creech`
|
||||||
-- * `AIRBASE.Nevada.Echo_Bay`
|
-- * `AIRBASE.Nevada.Echo_Bay`
|
||||||
-- * `AIRBASE.Nevada.Groom_Lake_AFB`
|
-- * `AIRBASE.Nevada.Groom_Lake`
|
||||||
-- * `AIRBASE.Nevada.Henderson_Executive_Airport`
|
-- * `AIRBASE.Nevada.Henderson_Executive`
|
||||||
-- * `AIRBASE.Nevada.Jean_Airport`
|
-- * `AIRBASE.Nevada.Jean`
|
||||||
-- * `AIRBASE.Nevada.Laughlin_Airport`
|
-- * `AIRBASE.Nevada.Laughlin`
|
||||||
-- * `AIRBASE.Nevada.Lincoln_County`
|
-- * `AIRBASE.Nevada.Lincoln_County`
|
||||||
-- * `AIRBASE.Nevada.McCarran_International_Airport`
|
-- * `AIRBASE.Nevada.McCarran_International`
|
||||||
-- * `AIRBASE.Nevada.Mesquite`
|
-- * `AIRBASE.Nevada.Mesquite`
|
||||||
-- * `AIRBASE.Nevada.Mina_Airport`
|
-- * `AIRBASE.Nevada.Mina`
|
||||||
-- * `AIRBASE.Nevada.Nellis_AFB`
|
-- * `AIRBASE.Nevada.Nellis`
|
||||||
-- * `AIRBASE.Nevada.North_Las_Vegas`
|
-- * `AIRBASE.Nevada.North_Las_Vegas`
|
||||||
-- * `AIRBASE.Nevada.Pahute_Mesa_Airstrip`
|
-- * `AIRBASE.Nevada.Pahute_Mesa`
|
||||||
-- * `AIRBASE.Nevada.Tonopah_Airport`
|
-- * `AIRBASE.Nevada.Tonopah`
|
||||||
-- * `AIRBASE.Nevada.Tonopah_Test_Range_Airfield`
|
-- * `AIRBASE.Nevada.Tonopah_Test_Range`
|
||||||
--
|
--
|
||||||
-- # Installation
|
-- # Installation
|
||||||
--
|
--
|
||||||
@@ -1088,10 +1102,10 @@ end
|
|||||||
--
|
--
|
||||||
-- -- Monitor specific airbases.
|
-- -- Monitor specific airbases.
|
||||||
-- ATC_Ground = ATC_GROUND_NEVADA:New(
|
-- ATC_Ground = ATC_GROUND_NEVADA:New(
|
||||||
-- { AIRBASE.Nevada.Laughlin_Airport,
|
-- { AIRBASE.Nevada.Laughlin,
|
||||||
-- AIRBASE.Nevada.Lincoln_County,
|
-- AIRBASE.Nevada.Lincoln_County,
|
||||||
-- AIRBASE.Nevada.North_Las_Vegas,
|
-- AIRBASE.Nevada.North_Las_Vegas,
|
||||||
-- AIRBASE.Nevada.McCarran_International_Airport
|
-- AIRBASE.Nevada.McCarran_International
|
||||||
-- }
|
-- }
|
||||||
-- )
|
-- )
|
||||||
--
|
--
|
||||||
@@ -1330,33 +1344,33 @@ end
|
|||||||
-- The following airbases are monitored at the PersianGulf region.
|
-- The following airbases are monitored at the PersianGulf region.
|
||||||
-- Use the @{Wrapper.Airbase#AIRBASE.PersianGulf} enumeration to select the airbases to be monitored.
|
-- Use the @{Wrapper.Airbase#AIRBASE.PersianGulf} enumeration to select the airbases to be monitored.
|
||||||
--
|
--
|
||||||
-- * `AIRBASE.PersianGulf.Abu_Musa_Island_Airport`
|
-- * `AIRBASE.PersianGulf.Abu_Musa_Island`
|
||||||
-- * `AIRBASE.PersianGulf.Al_Dhafra_AB`
|
-- * `AIRBASE.PersianGulf.Al_Dhafra_AFB`
|
||||||
-- * `AIRBASE.PersianGulf.Al_Maktoum_Intl`
|
-- * `AIRBASE.PersianGulf.Al_Maktoum_Intl`
|
||||||
-- * `AIRBASE.PersianGulf.Al_Minhad_AB`
|
-- * `AIRBASE.PersianGulf.Al_Minhad_AFB`
|
||||||
-- * `AIRBASE.PersianGulf.Bandar_Abbas_Intl`
|
-- * `AIRBASE.PersianGulf.Bandar_Abbas_Intl`
|
||||||
-- * `AIRBASE.PersianGulf.Bandar_Lengeh`
|
-- * `AIRBASE.PersianGulf.Bandar_Lengeh`
|
||||||
-- * `AIRBASE.PersianGulf.Dubai_Intl`
|
-- * `AIRBASE.PersianGulf.Dubai_Intl`
|
||||||
-- * `AIRBASE.PersianGulf.Fujairah_Intl`
|
-- * `AIRBASE.PersianGulf.Fujairah_Intl`
|
||||||
-- * `AIRBASE.PersianGulf.Havadarya`
|
-- * `AIRBASE.PersianGulf.Havadarya`
|
||||||
-- * `AIRBASE.PersianGulf.Kerman_Airport`
|
-- * `AIRBASE.PersianGulf.Kerman`
|
||||||
-- * `AIRBASE.PersianGulf.Khasab`
|
-- * `AIRBASE.PersianGulf.Khasab`
|
||||||
-- * `AIRBASE.PersianGulf.Lar_Airbase`
|
-- * `AIRBASE.PersianGulf.Lar`
|
||||||
-- * `AIRBASE.PersianGulf.Qeshm_Island`
|
-- * `AIRBASE.PersianGulf.Qeshm_Island`
|
||||||
-- * `AIRBASE.PersianGulf.Sharjah_Intl`
|
-- * `AIRBASE.PersianGulf.Sharjah_Intl`
|
||||||
-- * `AIRBASE.PersianGulf.Shiraz_International_Airport`
|
-- * `AIRBASE.PersianGulf.Shiraz_Intl`
|
||||||
-- * `AIRBASE.PersianGulf.Sir_Abu_Nuayr`
|
-- * `AIRBASE.PersianGulf.Sir_Abu_Nuayr`
|
||||||
-- * `AIRBASE.PersianGulf.Sirri_Island`
|
-- * `AIRBASE.PersianGulf.Sirri_Island`
|
||||||
-- * `AIRBASE.PersianGulf.Tunb_Island_AFB`
|
-- * `AIRBASE.PersianGulf.Tunb_Island_AFB`
|
||||||
-- * `AIRBASE.PersianGulf.Tunb_Kochak`
|
-- * `AIRBASE.PersianGulf.Tunb_Kochak`
|
||||||
-- * `AIRBASE.PersianGulf.Sas_Al_Nakheel_Airport`
|
-- * `AIRBASE.PersianGulf.Sas_Al_Nakheel`
|
||||||
-- * `AIRBASE.PersianGulf.Bandar_e_Jask_airfield`
|
-- * `AIRBASE.PersianGulf.Bandar_e_Jask`
|
||||||
-- * `AIRBASE.PersianGulf.Abu_Dhabi_International_Airport`
|
-- * `AIRBASE.PersianGulf.Abu_Dhabi_Intl`
|
||||||
-- * `AIRBASE.PersianGulf.Al_Bateen_Airport`
|
-- * `AIRBASE.PersianGulf.Al_Bateen`
|
||||||
-- * `AIRBASE.PersianGulf.Kish_International_Airport`
|
-- * `AIRBASE.PersianGulf.Kish_Intl`
|
||||||
-- * `AIRBASE.PersianGulf.Al_Ain_International_Airport`
|
-- * `AIRBASE.PersianGulf.Al_Ain_Intl`
|
||||||
-- * `AIRBASE.PersianGulf.Lavan_Island_Airport`
|
-- * `AIRBASE.PersianGulf.Lavan_Island`
|
||||||
-- * `AIRBASE.PersianGulf.Jiroft_Airport`
|
-- * `AIRBASE.PersianGulf.Jiroft`
|
||||||
--
|
--
|
||||||
-- # Installation
|
-- # Installation
|
||||||
--
|
--
|
||||||
@@ -1391,8 +1405,8 @@ end
|
|||||||
-- AirbasePoliceCaucasus = ATC_GROUND_PERSIANGULF:New()
|
-- AirbasePoliceCaucasus = ATC_GROUND_PERSIANGULF:New()
|
||||||
--
|
--
|
||||||
-- ATC_Ground = ATC_GROUND_PERSIANGULF:New(
|
-- ATC_Ground = ATC_GROUND_PERSIANGULF:New(
|
||||||
-- { AIRBASE.PersianGulf.Kerman_Airport,
|
-- { AIRBASE.PersianGulf.Kerman,
|
||||||
-- AIRBASE.PersianGulf.Al_Minhad_AB
|
-- AIRBASE.PersianGulf.Al_Minhad_AFB
|
||||||
-- }
|
-- }
|
||||||
-- )
|
-- )
|
||||||
--
|
--
|
||||||
@@ -1441,11 +1455,10 @@ function ATC_GROUND_PERSIANGULF:Start( RepeatScanSeconds )
|
|||||||
self.AirbaseMonitor = SCHEDULER:New( self, self._AirbaseMonitor, { self }, 0, RepeatScanSeconds )
|
self.AirbaseMonitor = SCHEDULER:New( self, self._AirbaseMonitor, { self }, 0, RepeatScanSeconds )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---
|
||||||
-- @type ATC_GROUND_MARIANAISLANDS
|
-- @type ATC_GROUND_MARIANAISLANDS
|
||||||
-- @extends #ATC_GROUND
|
-- @extends #ATC_GROUND
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--- # ATC\_GROUND\_MARIANA, extends @{#ATC_GROUND}
|
--- # ATC\_GROUND\_MARIANA, extends @{#ATC_GROUND}
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -77,7 +77,7 @@
|
|||||||
-- ammotruck.monitor = -60 -- 1 minute - AMMOTRUCK checks run every one minute
|
-- ammotruck.monitor = -60 -- 1 minute - AMMOTRUCK checks run every one minute
|
||||||
-- ammotruck.routeonroad = true -- Trucks will **try** to drive on roads
|
-- 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.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
|
-- 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
|
-- ## 3 FSM Events to shape mission
|
||||||
--
|
--
|
||||||
|
|||||||
@@ -619,63 +619,148 @@ ARTY.WeaponType={
|
|||||||
}
|
}
|
||||||
|
|
||||||
--- Database of common artillery unit properties.
|
--- Database of common artillery unit properties.
|
||||||
|
-- @type ARTY.dbitem
|
||||||
|
-- @field #string displayname Name displayed in ME.
|
||||||
|
-- @field #number minrange Minimum firing range in meters.
|
||||||
|
-- @field #number maxrange Maximum firing range in meters.
|
||||||
|
-- @field #number reloadtime Reload time in seconds.
|
||||||
|
|
||||||
|
--- Database of common artillery unit properties.
|
||||||
|
-- Table key is the "type name" and table value is and `ARTY.dbitem`.
|
||||||
-- @type ARTY.db
|
-- @type ARTY.db
|
||||||
ARTY.db={
|
ARTY.db={
|
||||||
["2B11 mortar"] = { -- type "2B11 mortar"
|
["LeFH_18-40-105"] = {
|
||||||
minrange = 500, -- correct?
|
displayname = "FH LeFH-18 105mm", -- name displayed in the ME
|
||||||
maxrange = 7000, -- 7 km
|
minrange = 500, -- min range (green circle) in meters
|
||||||
reloadtime = 30, -- 30 sec
|
maxrange = 10500, -- max range (red circle) in meters
|
||||||
|
reloadtime = nil, -- reload time in seconds
|
||||||
},
|
},
|
||||||
["SPH 2S1 Gvozdika"] = { -- type "SAU Gvozdika"
|
["M2A1-105"] = {
|
||||||
minrange = 300, -- correct?
|
displayname = "FH M2A1 105mm",
|
||||||
maxrange = 15000, -- 15 km
|
minrange = 500,
|
||||||
reloadtime = nil, -- unknown
|
maxrange = 11500,
|
||||||
|
reloadtime = nil,
|
||||||
},
|
},
|
||||||
["SPH 2S19 Msta"] = { --type "SAU Msta", alias "2S19 Msta"
|
["Pak40"] = {
|
||||||
minrange = 300, -- correct?
|
displayname = "FH Pak 40 75mm",
|
||||||
maxrange = 23500, -- 23.5 km
|
minrange = 500,
|
||||||
reloadtime = nil, -- unknown
|
maxrange = 3000,
|
||||||
|
reloadtime = nil,
|
||||||
|
},
|
||||||
|
["L118_Unit"] = {
|
||||||
|
displayname = "L118 Light Artillery Gun",
|
||||||
|
minrange = 500,
|
||||||
|
maxrange = 17500,
|
||||||
|
reloadtime = nil,
|
||||||
},
|
},
|
||||||
["SPH 2S3 Akatsia"] = { -- type "SAU Akatsia", alias "2S3 Akatsia"
|
["Smerch"] = {
|
||||||
minrange = 300, -- correct?
|
displayname = "MLRS 9A52 Smerch CM 300mm",
|
||||||
maxrange = 17000, -- 17 km
|
minrange = 20000,
|
||||||
reloadtime = nil, -- unknown
|
maxrange = 70000,
|
||||||
|
reloadtime = 2160,
|
||||||
},
|
},
|
||||||
["SPH 2S9 Nona"] = { --type "SAU 2-C9"
|
["Smerch_HE"] = {
|
||||||
minrange = 500, -- correct?
|
displayname = "MLRS 9A52 Smerch HE 300mm",
|
||||||
maxrange = 7000, -- 7 km
|
minrange = 20000,
|
||||||
reloadtime = nil, -- unknown
|
maxrange = 70000,
|
||||||
|
reloadtime = 2160,
|
||||||
},
|
},
|
||||||
["SPH M109 Paladin"] = { -- type "M-109", alias "M109"
|
["Uragan_BM-27"] = {
|
||||||
minrange = 300, -- correct?
|
displayname = "MLRS 9K57 Uragan BM-27 220mm",
|
||||||
maxrange = 22000, -- 22 km
|
minrange = 11500,
|
||||||
reloadtime = nil, -- unknown
|
maxrange = 35800,
|
||||||
|
reloadtime = 840,
|
||||||
},
|
},
|
||||||
["SpGH Dana"] = { -- type "SpGH_Dana"
|
["Grad-URAL"] = {
|
||||||
minrange = 300, -- correct?
|
displayname = "MLRS BM-21 Grad 122mm",
|
||||||
maxrange = 18700, -- 18.7 km
|
minrange = 5000,
|
||||||
reloadtime = nil, -- unknown
|
maxrange = 19000,
|
||||||
|
reloadtime = 420,
|
||||||
},
|
},
|
||||||
["MLRS BM-21 Grad"] = { --type "Grad-URAL", alias "MLRS BM-21 Grad"
|
["HL_B8M1"] = {
|
||||||
minrange = 5000, -- 5 km
|
displayname = "MLRS HL with B8M1 80mm",
|
||||||
maxrange = 19000, -- 19 km
|
minrange = 500,
|
||||||
reloadtime = 420, -- 7 min
|
maxrange = 5000,
|
||||||
|
reloadtime = nil,
|
||||||
},
|
},
|
||||||
["MLRS 9K57 Uragan BM-27"] = { -- type "Uragan_BM-27"
|
["tt_B8M1"] = {
|
||||||
minrange = 11500, -- 11.5 km
|
displayname = "MLRS LC with B8M1 80mm",
|
||||||
maxrange = 35800, -- 35.8 km
|
minrange = 500,
|
||||||
reloadtime = 840, -- 14 min
|
maxrange = 5000,
|
||||||
|
reloadtime = nil,
|
||||||
},
|
},
|
||||||
["MLRS 9A52 Smerch"] = { -- type "Smerch"
|
["MLRS"] = {
|
||||||
minrange = 20000, -- 20 km
|
displayname = "MLRS M270 227mm",
|
||||||
maxrange = 70000, -- 70 km
|
minrange = 10000,
|
||||||
reloadtime = 2160, -- 36 min
|
maxrange = 32000,
|
||||||
|
reloadtime = 540,
|
||||||
},
|
},
|
||||||
["MLRS M270"] = { --type "MRLS", alias "M270 MRLS"
|
["2B11 mortar"] = {
|
||||||
minrange = 10000, -- 10 km
|
displayname = "Mortar 2B11 120mm",
|
||||||
maxrange = 32000, -- 32 km
|
minrange = 500,
|
||||||
reloadtime = 540, -- 9 min
|
maxrange = 7000,
|
||||||
|
reloadtime = 30,
|
||||||
},
|
},
|
||||||
|
["PLZ05"] = {
|
||||||
|
displayname = "PLZ-05",
|
||||||
|
minrange = 500,
|
||||||
|
maxrange = 23500,
|
||||||
|
reloadtime = nil,
|
||||||
|
},
|
||||||
|
["SAU Gvozdika"] = {
|
||||||
|
displayname = "SPH 2S1 Gvozdika 122mm",
|
||||||
|
minrange = 300,
|
||||||
|
maxrange = 15000,
|
||||||
|
reloadtime = nil,
|
||||||
|
},
|
||||||
|
["SAU Msta"] = {
|
||||||
|
displayname = "SPH 2S19 Msta 152mm",
|
||||||
|
minrange = 300,
|
||||||
|
maxrange = 23500,
|
||||||
|
reloadtime = nil,
|
||||||
|
},
|
||||||
|
["SAU Akatsia"] = {
|
||||||
|
displayname = "SPH 2S3 Akatsia 152mm",
|
||||||
|
minrange = 300,
|
||||||
|
maxrange = 17000,
|
||||||
|
reloadtime = nil,
|
||||||
|
},
|
||||||
|
["SpGH_Dana"] = {
|
||||||
|
displayname = "SPH Dana vz77 152mm",
|
||||||
|
minrange = 300,
|
||||||
|
maxrange = 18700,
|
||||||
|
reloadtime = nil,
|
||||||
|
},
|
||||||
|
["M-109"] = {
|
||||||
|
displayname = "SPH M109 Paladin 155mm",
|
||||||
|
minrange = 300,
|
||||||
|
maxrange = 22000,
|
||||||
|
reloadtime = nil,
|
||||||
|
},
|
||||||
|
["M12_GMC"] = {
|
||||||
|
displayname = "SPH M12 GMC 155mm",
|
||||||
|
minrange = 300,
|
||||||
|
maxrange = 18200,
|
||||||
|
reloadtime = nil,
|
||||||
|
},
|
||||||
|
["Wespe124"] = {
|
||||||
|
displayname = "SPH Sd.Kfz.124 Wespe 105mm",
|
||||||
|
minrange = 300,
|
||||||
|
maxrange = 7000,
|
||||||
|
reloadtime = nil,
|
||||||
|
},
|
||||||
|
["T155_Firtina"] = {
|
||||||
|
displayname = "SPH T155 Firtina 155mm",
|
||||||
|
minrange = 300,
|
||||||
|
maxrange = 41000,
|
||||||
|
reloadtime = nil,
|
||||||
|
},
|
||||||
|
["SAU 2-C9"] = {
|
||||||
|
displayname = "SPM 2S9 Nona 120mm M",
|
||||||
|
minrange = 500,
|
||||||
|
maxrange = 7000,
|
||||||
|
reloadtime = nil,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Target.
|
--- Target.
|
||||||
@@ -695,7 +780,7 @@ ARTY.db={
|
|||||||
|
|
||||||
--- Arty script version.
|
--- Arty script version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
ARTY.version="1.3.1"
|
ARTY.version="1.3.3"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -797,8 +882,8 @@ function ARTY:New(group, alias)
|
|||||||
-- Maximum speed in km/h.
|
-- Maximum speed in km/h.
|
||||||
self.SpeedMax=group:GetSpeedMax()
|
self.SpeedMax=group:GetSpeedMax()
|
||||||
|
|
||||||
-- Group is mobile or not (e.g. mortars).
|
-- Group is mobile or not (e.g. mortars). Some immobile units have a speed of 1 m/s = 3.6 km/h. So we check this number.
|
||||||
if self.SpeedMax>1 then
|
if self.SpeedMax>3.6 then
|
||||||
self.ismobile=true
|
self.ismobile=true
|
||||||
else
|
else
|
||||||
self.ismobile=false
|
self.ismobile=false
|
||||||
@@ -1923,7 +2008,7 @@ function ARTY:onafterStart(Controllable, From, Event, To)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Check if we have and arty type that is in the DB.
|
-- Check if we have and arty type that is in the DB.
|
||||||
local _dbproperties=self:_CheckDB(self.DisplayName)
|
local _dbproperties=self:_CheckDB(self.Type)
|
||||||
self:T({dbproperties=_dbproperties})
|
self:T({dbproperties=_dbproperties})
|
||||||
if _dbproperties~=nil then
|
if _dbproperties~=nil then
|
||||||
for property,value in pairs(_dbproperties) do
|
for property,value in pairs(_dbproperties) do
|
||||||
@@ -1969,8 +2054,8 @@ function ARTY:onafterStart(Controllable, From, Event, To)
|
|||||||
text=text..string.format("Type = %s\n", self.Type)
|
text=text..string.format("Type = %s\n", self.Type)
|
||||||
text=text..string.format("Display Name = %s\n", self.DisplayName)
|
text=text..string.format("Display Name = %s\n", self.DisplayName)
|
||||||
text=text..string.format("Number of units = %d\n", self.IniGroupStrength)
|
text=text..string.format("Number of units = %d\n", self.IniGroupStrength)
|
||||||
text=text..string.format("Speed max = %d km/h\n", self.SpeedMax)
|
text=text..string.format("Speed max = %.1f km/h\n", self.SpeedMax)
|
||||||
text=text..string.format("Speed default = %d km/h\n", self.Speed)
|
text=text..string.format("Speed default = %.1f km/h\n", self.Speed)
|
||||||
text=text..string.format("Is mobile = %s\n", tostring(self.ismobile))
|
text=text..string.format("Is mobile = %s\n", tostring(self.ismobile))
|
||||||
text=text..string.format("Is cargo = %s\n", tostring(self.iscargo))
|
text=text..string.format("Is cargo = %s\n", tostring(self.iscargo))
|
||||||
text=text..string.format("Min range = %.1f km\n", self.minrange/1000)
|
text=text..string.format("Min range = %.1f km\n", self.minrange/1000)
|
||||||
@@ -2301,12 +2386,12 @@ function ARTY:OnEventShot(EventData)
|
|||||||
self.Nukes=self.Nukes-1
|
self.Nukes=self.Nukes-1
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Decrease available illuminatin shells because we just fired one.
|
-- Decrease available illumination shells because we just fired one.
|
||||||
if self.currentTarget.weapontype==ARTY.WeaponType.IlluminationShells then
|
if self.currentTarget.weapontype==ARTY.WeaponType.IlluminationShells then
|
||||||
self.Nillu=self.Nillu-1
|
self.Nillu=self.Nillu-1
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Decrease available illuminatin shells because we just fired one.
|
-- Decrease available smoke shells because we just fired one.
|
||||||
if self.currentTarget.weapontype==ARTY.WeaponType.SmokeShells then
|
if self.currentTarget.weapontype==ARTY.WeaponType.SmokeShells then
|
||||||
self.Nsmoke=self.Nsmoke-1
|
self.Nsmoke=self.Nsmoke-1
|
||||||
end
|
end
|
||||||
@@ -3049,7 +3134,7 @@ function ARTY:onafterOpenFire(Controllable, From, Event, To, target)
|
|||||||
local nfire=Narty
|
local nfire=Narty
|
||||||
local _type="shots"
|
local _type="shots"
|
||||||
if target.weapontype==ARTY.WeaponType.Auto then
|
if target.weapontype==ARTY.WeaponType.Auto then
|
||||||
nfire=Narty
|
nfire=Nammo -- We take everything that is available
|
||||||
_type="shots"
|
_type="shots"
|
||||||
elseif target.weapontype==ARTY.WeaponType.Cannon then
|
elseif target.weapontype==ARTY.WeaponType.Cannon then
|
||||||
nfire=Narty
|
nfire=Narty
|
||||||
@@ -3070,6 +3155,8 @@ function ARTY:onafterOpenFire(Controllable, From, Event, To, target)
|
|||||||
nfire=Nmissiles
|
nfire=Nmissiles
|
||||||
_type="cruise missiles"
|
_type="cruise missiles"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--env.info(string.format("FF type=%s, Nrockets=%d, Nfire=%d target.nshells=%d", _type, Nrockets, nfire, target.nshells))
|
||||||
|
|
||||||
-- Adjust if less than requested ammo is left.
|
-- Adjust if less than requested ammo is left.
|
||||||
target.nshells=math.min(target.nshells, nfire)
|
target.nshells=math.min(target.nshells, nfire)
|
||||||
@@ -3717,51 +3804,6 @@ function ARTY:_NuclearBlast(_coord)
|
|||||||
ignite(_fires)
|
ignite(_fires)
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
|
||||||
local ZoneNuke=ZONE_RADIUS:New("Nukezone", _coord:GetVec2(), 2000)
|
|
||||||
|
|
||||||
-- Scan for Scenery objects.
|
|
||||||
ZoneNuke:Scan(Object.Category.SCENERY)
|
|
||||||
|
|
||||||
-- Array with all possible hideouts, i.e. scenery objects in the vicinity of the group.
|
|
||||||
local scenery={}
|
|
||||||
|
|
||||||
for SceneryTypeName, SceneryData in pairs(ZoneNuke:GetScannedScenery()) do
|
|
||||||
for SceneryName, SceneryObject in pairs(SceneryData) do
|
|
||||||
|
|
||||||
local SceneryObject = SceneryObject -- Wrapper.Scenery#SCENERY
|
|
||||||
|
|
||||||
-- Position of the scenery object.
|
|
||||||
local spos=SceneryObject:GetCoordinate()
|
|
||||||
|
|
||||||
-- Distance from group to impact point.
|
|
||||||
local distance= spos:Get2DDistance(_coord)
|
|
||||||
|
|
||||||
-- Place markers on every possible scenery object.
|
|
||||||
if self.Debug then
|
|
||||||
local MarkerID=spos:MarkToAll(string.format("%s scenery object %s", self.Controllable:GetName(), SceneryObject:GetTypeName()))
|
|
||||||
local text=string.format("%s scenery: %s, Coord %s", self.Controllable:GetName(), SceneryObject:GetTypeName(), SceneryObject:GetCoordinate():ToStringLLDMS())
|
|
||||||
self:T2(SUPPRESSION.id..text)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Add to table.
|
|
||||||
table.insert(scenery, {object=SceneryObject, distance=distance})
|
|
||||||
|
|
||||||
--SceneryObject:Destroy()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Sort scenery wrt to distance from impact point.
|
|
||||||
-- local _sort = function(a,b) return a.distance < b.distance end
|
|
||||||
-- table.sort(scenery,_sort)
|
|
||||||
|
|
||||||
-- for _,object in pairs(scenery) do
|
|
||||||
-- local sobject=object -- Wrapper.Scenery#SCENERY
|
|
||||||
-- sobject:Destroy()
|
|
||||||
-- end
|
|
||||||
|
|
||||||
]]
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Route group to a certain point.
|
--- Route group to a certain point.
|
||||||
|
|||||||
@@ -74,7 +74,7 @@
|
|||||||
-- @image Designation.JPG
|
-- @image Designation.JPG
|
||||||
--
|
--
|
||||||
-- Date: 24 Oct 2021
|
-- Date: 24 Oct 2021
|
||||||
-- Last Update: May 2024
|
-- Last Update: Mar 2025
|
||||||
--
|
--
|
||||||
--- Class AUTOLASE
|
--- Class AUTOLASE
|
||||||
-- @type AUTOLASE
|
-- @type AUTOLASE
|
||||||
@@ -89,6 +89,10 @@
|
|||||||
-- @field #table playermenus
|
-- @field #table playermenus
|
||||||
-- @field #boolean smokemenu
|
-- @field #boolean smokemenu
|
||||||
-- @field #boolean threatmenu
|
-- @field #boolean threatmenu
|
||||||
|
-- @field #number RoundingPrecision
|
||||||
|
-- @field #table smokeoffset
|
||||||
|
-- @field #boolean increasegroundawareness
|
||||||
|
-- @field #number MonitorFrequency
|
||||||
-- @extends Ops.Intel#INTEL
|
-- @extends Ops.Intel#INTEL
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -100,6 +104,9 @@ AUTOLASE = {
|
|||||||
alias = "",
|
alias = "",
|
||||||
debug = false,
|
debug = false,
|
||||||
smokemenu = true,
|
smokemenu = true,
|
||||||
|
RoundingPrecision = 0,
|
||||||
|
increasegroundawareness = true,
|
||||||
|
MonitorFrequency = 30,
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Laser spot info
|
--- Laser spot info
|
||||||
@@ -118,7 +125,7 @@ AUTOLASE = {
|
|||||||
|
|
||||||
--- AUTOLASE class version.
|
--- AUTOLASE class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
AUTOLASE.version = "0.1.25"
|
AUTOLASE.version = "0.1.31"
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
-- Begin Functional.Autolase.lua
|
-- Begin Functional.Autolase.lua
|
||||||
@@ -191,6 +198,7 @@ function AUTOLASE:New(RecceSet, Coalition, Alias, PilotSet)
|
|||||||
self.reporttimelong = 30
|
self.reporttimelong = 30
|
||||||
self.smoketargets = false
|
self.smoketargets = false
|
||||||
self.smokecolor = SMOKECOLOR.Red
|
self.smokecolor = SMOKECOLOR.Red
|
||||||
|
self.smokeoffset = nil
|
||||||
self.notifypilots = true
|
self.notifypilots = true
|
||||||
self.targetsperrecce = {}
|
self.targetsperrecce = {}
|
||||||
self.RecceUnits = {}
|
self.RecceUnits = {}
|
||||||
@@ -207,6 +215,11 @@ function AUTOLASE:New(RecceSet, Coalition, Alias, PilotSet)
|
|||||||
self.playermenus = {}
|
self.playermenus = {}
|
||||||
self.smokemenu = true
|
self.smokemenu = true
|
||||||
self.threatmenu = true
|
self.threatmenu = true
|
||||||
|
self.RoundingPrecision = 0
|
||||||
|
self.increasegroundawareness = true
|
||||||
|
self.MonitorFrequency = 30
|
||||||
|
|
||||||
|
self:EnableSmokeMenu({Angle=math.random(0,359),Distance=math.random(10,20)})
|
||||||
|
|
||||||
-- Set some string id for output to DCS.log file.
|
-- Set some string id for output to DCS.log file.
|
||||||
self.lid=string.format("AUTOLASE %s (%s) | ", self.alias, self.coalition and UTILS.GetCoalitionName(self.coalition) or "unknown")
|
self.lid=string.format("AUTOLASE %s (%s) | ", self.alias, self.coalition and UTILS.GetCoalitionName(self.coalition) or "unknown")
|
||||||
@@ -309,16 +322,41 @@ end
|
|||||||
-- Helper Functions
|
-- Helper Functions
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- [User] When using Monitor, set the frequency here in which the report will appear
|
||||||
|
-- @param #AUTOLASE self
|
||||||
|
-- @param #number Seconds Run the report loop every number of seconds defined here.
|
||||||
|
-- @return #AUTOLASE self
|
||||||
|
function AUTOLASE:SetMonitorFrequency(Seconds)
|
||||||
|
self.MonitorFrequency = Seconds or 30
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- [User] Set a table of possible laser codes.
|
--- [User] Set a table of possible laser codes.
|
||||||
-- Each new RECCE can select a code from this table, default is { 1688, 1130, 4785, 6547, 1465, 4578 } .
|
-- Each new RECCE can select a code from this table, default is { 1688, 1130, 4785, 6547, 1465, 4578 }.
|
||||||
-- @param #AUTOLASE self
|
-- @param #AUTOLASE self
|
||||||
-- @param #list<#number> LaserCodes
|
-- @param #list<#number> LaserCodes
|
||||||
-- @return #AUTOLASE
|
-- @return #AUTOLASE self
|
||||||
function AUTOLASE:SetLaserCodes( LaserCodes )
|
function AUTOLASE:SetLaserCodes( LaserCodes )
|
||||||
self.LaserCodes = ( type( LaserCodes ) == "table" ) and LaserCodes or { LaserCodes }
|
self.LaserCodes = ( type( LaserCodes ) == "table" ) and LaserCodes or { LaserCodes }
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- [User] Improve ground unit detection by using a zone scan and LOS check.
|
||||||
|
-- @param #AUTOLASE self
|
||||||
|
-- @return #AUTOLASE self
|
||||||
|
function AUTOLASE:EnableImproveGroundUnitsDetection()
|
||||||
|
self.increasegroundawareness = true
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [User] Do not improve ground unit detection by using a zone scan and LOS check.
|
||||||
|
-- @param #AUTOLASE self
|
||||||
|
-- @return #AUTOLASE self
|
||||||
|
function AUTOLASE:DisableImproveGroundUnitsDetection()
|
||||||
|
self.increasegroundawareness = false
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- (Internal) Function to set pilot menu.
|
--- (Internal) Function to set pilot menu.
|
||||||
-- @param #AUTOLASE self
|
-- @param #AUTOLASE self
|
||||||
-- @return #AUTOLASE self
|
-- @return #AUTOLASE self
|
||||||
@@ -600,11 +638,26 @@ function AUTOLASE:SetSmokeTargets(OnOff,Color)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- (User) Function to set rounding precision for BR distance output.
|
||||||
|
-- @param #AUTOLASE self
|
||||||
|
-- @param #number IDP Rounding precision before/after the decimal sign. Defaults to zero. Positive values round right of the decimal sign, negative ones left of the decimal sign.
|
||||||
|
-- @return #AUTOLASE self
|
||||||
|
function AUTOLASE:SetRoundingPrecsion(IDP)
|
||||||
|
self.RoundingPrecision = IDP or 0
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- (User) Show the "Switch smoke target..." menu entry for pilots. On by default.
|
--- (User) Show the "Switch smoke target..." menu entry for pilots. On by default.
|
||||||
-- @param #AUTOLASE self
|
-- @param #AUTOLASE self
|
||||||
|
-- @param #table Offset (Optional) Define an offset for the smoke, i.e. not directly on the unit itself, angle is degrees and distance is meters. E.g. `autolase:EnableSmokeMenu({Angle=30,Distance=20})`
|
||||||
-- @return #AUTOLASE self
|
-- @return #AUTOLASE self
|
||||||
function AUTOLASE:EnableSmokeMenu()
|
function AUTOLASE:EnableSmokeMenu(Offset)
|
||||||
self.smokemenu = true
|
self.smokemenu = true
|
||||||
|
if Offset then
|
||||||
|
self.smokeoffset = {}
|
||||||
|
self.smokeoffset.Distance = Offset.Distance or math.random(10,20)
|
||||||
|
self.smokeoffset.Angle = Offset.Angle or math.random(0,359)
|
||||||
|
end
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -613,6 +666,7 @@ end
|
|||||||
-- @return #AUTOLASE self
|
-- @return #AUTOLASE self
|
||||||
function AUTOLASE:DisableSmokeMenu()
|
function AUTOLASE:DisableSmokeMenu()
|
||||||
self.smokemenu = false
|
self.smokemenu = false
|
||||||
|
self.smokeoffset = nil
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -671,7 +725,8 @@ function AUTOLASE:CleanCurrentLasing()
|
|||||||
local unit = recce:GetUnit(1)
|
local unit = recce:GetUnit(1)
|
||||||
local name = unit:GetName()
|
local name = unit:GetName()
|
||||||
if not self.RecceUnits[name] then
|
if not self.RecceUnits[name] then
|
||||||
self.RecceUnits[name] = { name=name, unit=unit, cooldown = false, timestamp = timer.getAbsTime() }
|
local isground = (unit and unit.IsGround) and unit:IsGround() or false
|
||||||
|
self.RecceUnits[name] = { name=name, unit=unit, cooldown = false, timestamp = timer.getAbsTime(), isground=isground }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -757,9 +812,11 @@ function AUTOLASE:ShowStatus(Group,Unit)
|
|||||||
end
|
end
|
||||||
local code = self:GetLaserCode(unit:GetName())
|
local code = self:GetLaserCode(unit:GetName())
|
||||||
report:Add(string.format("Recce %s has code %d",name,code))
|
report:Add(string.format("Recce %s has code %d",name,code))
|
||||||
|
report:Add("---------------")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
report:Add(string.format("Lasing min threat level %d",self.minthreatlevel))
|
report:Add(string.format("Lasing min threat level %d",self.minthreatlevel))
|
||||||
|
report:Add("---------------")
|
||||||
local lines = 0
|
local lines = 0
|
||||||
for _ind,_entry in pairs(self.CurrentLasing) do
|
for _ind,_entry in pairs(self.CurrentLasing) do
|
||||||
local entry = _entry -- #AUTOLASE.LaserSpot
|
local entry = _entry -- #AUTOLASE.LaserSpot
|
||||||
@@ -779,22 +836,28 @@ function AUTOLASE:ShowStatus(Group,Unit)
|
|||||||
if playername then
|
if playername then
|
||||||
local settings = _DATABASE:GetPlayerSettings(playername)
|
local settings = _DATABASE:GetPlayerSettings(playername)
|
||||||
if settings then
|
if settings then
|
||||||
self:I("Get Settings ok!")
|
self:T("Get Settings ok!")
|
||||||
if settings:IsA2G_MGRS() then
|
if settings:IsA2G_MGRS() then
|
||||||
locationstring = entry.coordinate:ToStringMGRS(settings)
|
locationstring = entry.coordinate:ToStringMGRS(settings)
|
||||||
elseif settings:IsA2G_LL_DMS() then
|
elseif settings:IsA2G_LL_DMS() then
|
||||||
locationstring = entry.coordinate:ToStringLLDMS(settings)
|
locationstring = entry.coordinate:ToStringLLDMS(settings)
|
||||||
|
elseif settings:IsA2G_LL_DDM() then
|
||||||
|
locationstring = entry.coordinate:ToStringLLDDM(settings)
|
||||||
elseif settings:IsA2G_BR() then
|
elseif settings:IsA2G_BR() then
|
||||||
locationstring = entry.coordinate:ToStringBR(Group:GetCoordinate() or Unit:GetCoordinate(),settings)
|
-- attention this is the distance from the ASKING unit to target, not from RECCE to target!
|
||||||
|
local startcoordinate = Unit:GetCoordinate() or Group:GetCoordinate()
|
||||||
|
locationstring = entry.coordinate:ToStringBR(startcoordinate,settings,false,self.RoundingPrecision)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local text = string.format("%s lasing %s code %d\nat %s",reccename,typename,code,locationstring)
|
local text = string.format("+ %s lasing %s code %d\nat %s",reccename,typename,code,locationstring)
|
||||||
report:Add(text)
|
report:Add(text)
|
||||||
|
report:Add("---------------")
|
||||||
lines = lines + 1
|
lines = lines + 1
|
||||||
end
|
end
|
||||||
if lines == 0 then
|
if lines == 0 then
|
||||||
report:Add("No targets!")
|
report:Add("No targets!")
|
||||||
|
report:Add("---------------")
|
||||||
end
|
end
|
||||||
local reporttime = self.reporttimelong
|
local reporttime = self.reporttimelong
|
||||||
if lines == 0 then reporttime = self.reporttimeshort end
|
if lines == 0 then reporttime = self.reporttimeshort end
|
||||||
@@ -913,6 +976,65 @@ function AUTOLASE:CanLase(Recce,Unit)
|
|||||||
return canlase
|
return canlase
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- (Internal) Function to do a zone check per ground Recce and make found units and statics "known".
|
||||||
|
-- @param #AUTOLASE self
|
||||||
|
-- @return #AUTOLASE self
|
||||||
|
function AUTOLASE:_Prescient()
|
||||||
|
-- self.RecceUnits[name] = { name=name, unit=unit, cooldown = false, timestamp = timer.getAbsTime(), isground=isground }
|
||||||
|
for _,_data in pairs(self.RecceUnits) do
|
||||||
|
-- ground units only
|
||||||
|
if _data.isground and _data.unit and _data.unit:IsAlive() then
|
||||||
|
local unit = _data.unit -- Wrapper.Unit#UNIT
|
||||||
|
local position = unit:GetCoordinate() -- Core.Point#COORDINATE
|
||||||
|
local needsinit = false
|
||||||
|
if position then
|
||||||
|
local lastposition = unit:GetProperty("lastposition")
|
||||||
|
-- property initiated?
|
||||||
|
if not lastposition then
|
||||||
|
unit:SetProperty("lastposition",position)
|
||||||
|
lastposition = position
|
||||||
|
needsinit = true
|
||||||
|
end
|
||||||
|
-- has moved?
|
||||||
|
local dist = position:Get2DDistance(lastposition)
|
||||||
|
-- refresh?
|
||||||
|
local TNow = timer.getAbsTime()
|
||||||
|
-- check
|
||||||
|
if dist > 10 or needsinit==true or TNow - _data.timestamp > 29 then
|
||||||
|
-- init scan objects
|
||||||
|
local hasunits,hasstatics,_,Units,Statics = position:ScanObjects(self.LaseDistance,true,true,false)
|
||||||
|
-- loop found units
|
||||||
|
if hasunits then
|
||||||
|
self:T(self.lid.."Checking possibly visible UNITs for Recce "..unit:GetName())
|
||||||
|
for _,_target in pairs(Units) do -- Wrapper.Unit#UNIT object here
|
||||||
|
local target = _target -- Wrapper.Unit#UNIT
|
||||||
|
if target and target:GetCoalition() ~= self.coalition then
|
||||||
|
if unit:IsLOS(target) and (not target:IsUnitDetected(unit))then
|
||||||
|
unit:KnowUnit(target,true,true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- loop found statics
|
||||||
|
if hasstatics then
|
||||||
|
self:T(self.lid.."Checking possibly visible STATICs for Recce "..unit:GetName())
|
||||||
|
for _,_static in pairs(Statics) do -- DCS static object here
|
||||||
|
local static = STATIC:Find(_static)
|
||||||
|
if static and static:GetCoalition() ~= self.coalition then
|
||||||
|
local IsLOS = position:IsLOS(static:GetCoordinate())
|
||||||
|
if IsLOS then
|
||||||
|
unit:KnowUnit(static,true,true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
-- FSM Functions
|
-- FSM Functions
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
@@ -925,6 +1047,9 @@ end
|
|||||||
-- @return #AUTOLASE self
|
-- @return #AUTOLASE self
|
||||||
function AUTOLASE:onbeforeMonitor(From, Event, To)
|
function AUTOLASE:onbeforeMonitor(From, Event, To)
|
||||||
self:T({From, Event, To})
|
self:T({From, Event, To})
|
||||||
|
if self.increasegroundawareness then
|
||||||
|
self:_Prescient()
|
||||||
|
end
|
||||||
-- Check if group has detected any units.
|
-- Check if group has detected any units.
|
||||||
self:UpdateIntel()
|
self:UpdateIntel()
|
||||||
return self
|
return self
|
||||||
@@ -953,7 +1078,7 @@ function AUTOLASE:onafterMonitor(From, Event, To)
|
|||||||
local grp = contact.group
|
local grp = contact.group
|
||||||
local coord = contact.position
|
local coord = contact.position
|
||||||
local reccename = contact.recce or "none"
|
local reccename = contact.recce or "none"
|
||||||
local threat = contact.threatlevel or 0
|
local threat = contact.threatlevel or 0
|
||||||
local reccegrp = UNIT:FindByName(reccename)
|
local reccegrp = UNIT:FindByName(reccename)
|
||||||
if reccegrp then
|
if reccegrp then
|
||||||
local reccecoord = reccegrp:GetCoordinate()
|
local reccecoord = reccegrp:GetCoordinate()
|
||||||
@@ -1077,6 +1202,9 @@ function AUTOLASE:onafterMonitor(From, Event, To)
|
|||||||
}
|
}
|
||||||
if self.smoketargets then
|
if self.smoketargets then
|
||||||
local coord = unit:GetCoordinate()
|
local coord = unit:GetCoordinate()
|
||||||
|
if self.smokeoffset then
|
||||||
|
coord:Translate(self.smokeoffset.Distance,self.smokeoffset.Angle,true,true)
|
||||||
|
end
|
||||||
local color = self:GetSmokeColor(reccename)
|
local color = self:GetSmokeColor(reccename)
|
||||||
coord:Smoke(color)
|
coord:Smoke(color)
|
||||||
end
|
end
|
||||||
@@ -1087,7 +1215,8 @@ function AUTOLASE:onafterMonitor(From, Event, To)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
self:__Monitor(-30)
|
local nextloop = -self.MonitorFrequency or -30
|
||||||
|
self:__Monitor(nextloop)
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -52,11 +52,13 @@
|
|||||||
-- @module Functional.CleanUp
|
-- @module Functional.CleanUp
|
||||||
-- @image CleanUp_Airbases.JPG
|
-- @image CleanUp_Airbases.JPG
|
||||||
|
|
||||||
--- @type CLEANUP_AIRBASE.__ Methods which are not intended for mission designers, but which are used interally by the moose designer :-)
|
---
|
||||||
|
-- @type CLEANUP_AIRBASE.__ Methods which are not intended for mission designers, but which are used interally by the moose designer :-)
|
||||||
-- @field #map<#string,Wrapper.Airbase#AIRBASE> Airbases Map of Airbases.
|
-- @field #map<#string,Wrapper.Airbase#AIRBASE> Airbases Map of Airbases.
|
||||||
-- @extends Core.Base#BASE
|
-- @extends Core.Base#BASE
|
||||||
|
|
||||||
--- @type CLEANUP_AIRBASE
|
---
|
||||||
|
-- @type CLEANUP_AIRBASE
|
||||||
-- @extends #CLEANUP_AIRBASE.__
|
-- @extends #CLEANUP_AIRBASE.__
|
||||||
|
|
||||||
--- Keeps airbases clean, and tries to guarantee continuous airbase operations, even under combat.
|
--- Keeps airbases clean, and tries to guarantee continuous airbase operations, even under combat.
|
||||||
@@ -93,7 +95,7 @@ CLEANUP_AIRBASE = {
|
|||||||
-- @field #CLEANUP_AIRBASE.__
|
-- @field #CLEANUP_AIRBASE.__
|
||||||
CLEANUP_AIRBASE.__ = {}
|
CLEANUP_AIRBASE.__ = {}
|
||||||
|
|
||||||
--- @field #CLEANUP_AIRBASE.__.Airbases
|
-- @field #CLEANUP_AIRBASE.__.Airbases
|
||||||
CLEANUP_AIRBASE.__.Airbases = {}
|
CLEANUP_AIRBASE.__.Airbases = {}
|
||||||
|
|
||||||
--- Creates the main object which is handling the cleaning of the debris within the given Zone Names.
|
--- Creates the main object which is handling the cleaning of the debris within the given Zone Names.
|
||||||
@@ -240,7 +242,8 @@ function CLEANUP_AIRBASE.__:DestroyMissile( MissileObject )
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #CLEANUP_AIRBASE self
|
---
|
||||||
|
-- @param #CLEANUP_AIRBASE self
|
||||||
-- @param Core.Event#EVENTDATA EventData
|
-- @param Core.Event#EVENTDATA EventData
|
||||||
function CLEANUP_AIRBASE.__:OnEventBirth( EventData )
|
function CLEANUP_AIRBASE.__:OnEventBirth( EventData )
|
||||||
self:F( { EventData } )
|
self:F( { EventData } )
|
||||||
@@ -354,7 +357,7 @@ function CLEANUP_AIRBASE.__:EventAddForCleanUp( Event )
|
|||||||
self:F({Event})
|
self:F({Event})
|
||||||
|
|
||||||
|
|
||||||
if Event.IniDCSUnit and Event.IniCategory == Object.Category.UNIT then
|
if Event.IniDCSUnit and Event.IniUnit and Event.IniCategory == Object.Category.UNIT then
|
||||||
if self.CleanUpList[Event.IniDCSUnitName] == nil then
|
if self.CleanUpList[Event.IniDCSUnitName] == nil then
|
||||||
if self:IsInAirbase( Event.IniUnit:GetVec2() ) then
|
if self:IsInAirbase( Event.IniUnit:GetVec2() ) then
|
||||||
self:AddForCleanUp( Event.IniUnit, Event.IniDCSUnitName )
|
self:AddForCleanUp( Event.IniUnit, Event.IniDCSUnitName )
|
||||||
@@ -362,7 +365,7 @@ function CLEANUP_AIRBASE.__:EventAddForCleanUp( Event )
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if Event.TgtDCSUnit and Event.TgtCategory == Object.Category.UNIT then
|
if Event.TgtDCSUnit and Event.TgtUnit and Event.TgtCategory == Object.Category.UNIT then
|
||||||
if self.CleanUpList[Event.TgtDCSUnitName] == nil then
|
if self.CleanUpList[Event.TgtDCSUnitName] == nil then
|
||||||
if self:IsInAirbase( Event.TgtUnit:GetVec2() ) then
|
if self:IsInAirbase( Event.TgtUnit:GetVec2() ) then
|
||||||
self:AddForCleanUp( Event.TgtUnit, Event.TgtDCSUnitName )
|
self:AddForCleanUp( Event.TgtUnit, Event.TgtDCSUnitName )
|
||||||
@@ -384,7 +387,7 @@ function CLEANUP_AIRBASE.__:CleanUpSchedule()
|
|||||||
local CleanUpUnit = CleanUpListData.CleanUpUnit -- Wrapper.Unit#UNIT
|
local CleanUpUnit = CleanUpListData.CleanUpUnit -- Wrapper.Unit#UNIT
|
||||||
local CleanUpGroupName = CleanUpListData.CleanUpGroupName
|
local CleanUpGroupName = CleanUpListData.CleanUpGroupName
|
||||||
|
|
||||||
if CleanUpUnit:IsAlive() ~= nil then
|
if CleanUpUnit and CleanUpUnit:IsAlive() ~= nil then
|
||||||
|
|
||||||
if self:IsInAirbase( CleanUpUnit:GetVec2() ) then
|
if self:IsInAirbase( CleanUpUnit:GetVec2() ) then
|
||||||
|
|
||||||
@@ -411,7 +414,7 @@ function CLEANUP_AIRBASE.__:CleanUpSchedule()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
-- Clean Units which are waiting for a very long time in the CleanUpZone.
|
-- Clean Units which are waiting for a very long time in the CleanUpZone.
|
||||||
if CleanUpUnit and not CleanUpUnit:GetPlayerName() then
|
if CleanUpUnit and (CleanUpUnit.GetPlayerName == nil or not CleanUpUnit:GetPlayerName()) then
|
||||||
local CleanUpUnitVelocity = CleanUpUnit:GetVelocityKMH()
|
local CleanUpUnitVelocity = CleanUpUnit:GetVelocityKMH()
|
||||||
if CleanUpUnitVelocity < 1 then
|
if CleanUpUnitVelocity < 1 then
|
||||||
if CleanUpListData.CleanUpMoved then
|
if CleanUpListData.CleanUpMoved then
|
||||||
|
|||||||
@@ -0,0 +1,687 @@
|
|||||||
|
--- **Functional** - Manage and track client slots easily to add your own client-based menus and modules to.
|
||||||
|
--
|
||||||
|
-- The @{#CLIENTWATCH} class adds a simplified way to create scripts and menus for individual clients. Instead of creating large algorithms and juggling multiple event handlers, you can simply provide one or more prefixes to the class and use the callback functions on spawn, despawn, and any aircraft related events to script to your hearts content.
|
||||||
|
--
|
||||||
|
-- ===
|
||||||
|
--
|
||||||
|
-- ## Features:
|
||||||
|
--
|
||||||
|
-- * Find clients by prefixes or by providing a Wrapper.CLIENT object
|
||||||
|
-- * Trigger functions when the client spawns and despawns
|
||||||
|
-- * Create multiple client instances without overwriting event handlers between instances
|
||||||
|
-- * More reliable aircraft lost events for when DCS thinks the aircraft id dead but a dead event fails to trigger
|
||||||
|
-- * Easily manage clients spawned in dynamic slots
|
||||||
|
--
|
||||||
|
-- ====
|
||||||
|
--
|
||||||
|
-- ### Author: **Statua**
|
||||||
|
--
|
||||||
|
-- ### Contributions: **FlightControl**: Wrapper.CLIENT
|
||||||
|
--
|
||||||
|
-- ====
|
||||||
|
-- @module Functional.ClientWatch
|
||||||
|
-- @image clientwatch.jpg
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
--- CLIENTWATCH class
|
||||||
|
-- @type CLIENTWATCH
|
||||||
|
-- @field #string ClassName Name of the class.
|
||||||
|
-- @field #boolean Debug Write Debug messages to DCS log file and send Debug messages to all players.
|
||||||
|
-- @field #string lid String for DCS log file.
|
||||||
|
-- @field #number FilterCoalition If not nil, will only activate for aircraft of the given coalition value.
|
||||||
|
-- @field #number FilterCategory If not nil, will only activate for aircraft of the given category value.
|
||||||
|
-- @extends Core.Fsm#FSM_CONTROLLABLE
|
||||||
|
|
||||||
|
--- Manage and track client slots easily to add your own client-based menus and modules to.
|
||||||
|
--
|
||||||
|
-- ## Creating a new instance
|
||||||
|
--
|
||||||
|
-- To start, you must first create a new instance of the client manager and provide it with either a Wrapper.Client#CLIENT object, a string prefix of the unit name, or a table of string prefixes for unit names. These are used to capture the client unit when it spawns and apply your scripted functions to it. Only fixed wing and rotary wing aircraft controlled by players can be used by this class.
|
||||||
|
-- **This will not work if the client aircraft is alive!**
|
||||||
|
--
|
||||||
|
-- ### Examples
|
||||||
|
--
|
||||||
|
-- -- Create an instance with a Wrapper.Client#CLIENT object
|
||||||
|
-- local heliClient = CLIENT:FindByName('Rotary1-1')
|
||||||
|
-- local clientInstance = CLIENTWATCH:New(heliClient)
|
||||||
|
--
|
||||||
|
-- -- Create an instance with part of the unit name in the Mission Editor
|
||||||
|
-- local clientInstance = CLIENTWATCH:New("Rotary")
|
||||||
|
--
|
||||||
|
-- -- Create an instance using prefixes for a few units as well as a FARP name for any dynamic spawns coming out of it
|
||||||
|
-- local clientInstance = CLIENTWATCH:New({"Rescue","UH-1H","FARP ALPHA"})
|
||||||
|
--
|
||||||
|
-- ## Applying functions and methods to client aircraft when they spawn
|
||||||
|
--
|
||||||
|
-- Once the instance is created, it will watch for birth events. If the unit name of the client aircraft matches the one provided in the instance, the callback method @{#CLIENTWATCH:OnAfterSpawn}() can be used to apply functions and methods to the client object.
|
||||||
|
--
|
||||||
|
-- In the OnAfterSpawn() callback method are four values. From, Event, To, and ClientObject. From,Event,To are standard FSM strings for the state changes. ClientObject is where the magic happens. This is a special object which you can use to access all the data of the client aircraft. The following entries in ClientObject are available for you to use:
|
||||||
|
--
|
||||||
|
-- * **ClientObject.Unit**: The Moose @{Wrapper.Unit#UNIT} of the client aircraft
|
||||||
|
-- * **ClientObject.Group**: The Moose @{Wrapper.Group#GRUP} of the client aircraft
|
||||||
|
-- * **ClientObject.Client**: The Moose @{Wrapper.Client#CLIENT} of the client aircraft
|
||||||
|
-- * **ClientObject.PlayerName**: A #string of the player controlling the aircraft
|
||||||
|
-- * **ClientObject.UnitName**: A #string of the client aircraft unit.
|
||||||
|
-- * **ClientObject.GroupName**: A #string of the client aircraft group.
|
||||||
|
--
|
||||||
|
-- ### Examples
|
||||||
|
--
|
||||||
|
-- -- Create an instance with a client unit prefix and send them a message when they spawn
|
||||||
|
-- local clientInstance = CLIENTWATCH:New("Rotary")
|
||||||
|
-- function clientInstance:OnAfterSpawn(From,Event,To,ClientObject,EventData)
|
||||||
|
-- MESSAGE:New("Welcome to your aircraft!",10):ToUnit(ClientObject.Unit)
|
||||||
|
-- end
|
||||||
|
--
|
||||||
|
-- ## Using event callbacks
|
||||||
|
--
|
||||||
|
-- In a normal setting, you can only use a callback function for a specific option in one location. If you have multiple scripts that rely on the same callback from the same object, this can get quite messy. With the ClientWatch module, these callbacks are isolated t the instances and therefore open the possibility to use many instances with the same callback doing different things. ClientWatch instances subscribe to all events that are applicable to player controlled aircraft and provides callbacks for each, forwarding the EventData in the callback function.
|
||||||
|
--
|
||||||
|
-- The following event callbacks can be used inside the OnAfterSpawn() callback:
|
||||||
|
--
|
||||||
|
-- * **:OnAfterDespawn(From,Event,To)**: Triggers whenever DCS no longer sees the aircraft as 'alive'. No event data is given in this callback as it is derived from other events
|
||||||
|
-- * **:OnAfterHit(From,Event,To,EventData)**: Triggers every time the aircraft takes damage or is struck by a weapon/explosion
|
||||||
|
-- * **:OnAfterKill(From,Event,To,EventData)**: Triggers after the aircraft kills something with its weapons
|
||||||
|
-- * **:OnAfterScore(From,Event,To,EventData)**: Triggers after accumulating score
|
||||||
|
-- * **:OnAfterShot(From,Event,To,EventData)**: Triggers after a single-shot weapon is released
|
||||||
|
-- * **:OnAfterShootingStart(From,Event,To,EventData)**: Triggers when an automatic weapon begins firing
|
||||||
|
-- * **:OnAfterShootingEnd(From,Event,To,EventData)**: Triggers when an automatic weapon stops firing
|
||||||
|
-- * **:OnAfterLand(From,Event,To,EventData)**: Triggers when an aircraft transitions from being airborne to on the ground
|
||||||
|
-- * **:OnAfterTakeoff(From,Event,To,EventData)**: Triggers when an aircraft transitions from being on the ground to airborne
|
||||||
|
-- * **:OnAfterRunwayTakeoff(From,Event,To,EventData)**: Triggers after lifting off from a runway
|
||||||
|
-- * **:OnAfterRunwayTouch(From,Event,To,EventData)**: Triggers when an aircraft's gear makes contact with a runway
|
||||||
|
-- * **:OnAfterRefueling(From,Event,To,EventData)**: Triggers when an aircraft begins taking on fuel
|
||||||
|
-- * **:OnAfterRefuelingStop(From,Event,To,EventData)**: Triggers when an aircraft stops taking on fuel
|
||||||
|
-- * **:OnAfterPlayerLeaveUnit(From,Event,To,EventData)**: Triggers when a player leaves an operational aircraft
|
||||||
|
-- * **:OnAfterCrash(From,Event,To,EventData)**: Triggers when an aircraft is destroyed (may fail to trigger if the aircraft is only partially destroyed)
|
||||||
|
-- * **:OnAfterDead(From,Event,To,EventData)**: Triggers when an aircraft is considered dead (may fail to trigger if the aircraft was partially destroyed first)
|
||||||
|
-- * **:OnAfterPilotDead(From,Event,To,EventData)**: Triggers when the pilot is killed (may fail to trigger if the aircraft was partially destroyed first)
|
||||||
|
-- * **:OnAfterUnitLost(From,Event,To,EventData)**: Triggers when an aircraft is lost for any reason (may fail to trigger if the aircraft was partially destroyed first)
|
||||||
|
-- * **:OnAfterEjection(From,Event,To,EventData)**: Triggers when a pilot ejects from an aircraft
|
||||||
|
-- * **:OnAfterHumanFailure(From,Event,To,EventData)**: Triggers when an aircraft or system is damaged from any source or action by the player
|
||||||
|
-- * **:OnAfterHumanAircraftRepairStart(From,Event,To,EventData)**: Triggers when an aircraft repair is started
|
||||||
|
-- * **:OnAfterHumanAircraftRepairFinish(From,Event,To,EventData)**: Triggers when an aircraft repair is completed
|
||||||
|
-- * **:OnAfterEngineStartup(From,Event,To,EventData)**: Triggers when the engine enters what DCS considers to be a started state. Parameters vary by aircraft
|
||||||
|
-- * **:OnAfterEngineShutdown(From,Event,To,EventData)**: Triggers when the engine enters what DCS considers to be a stopped state. Parameters vary by aircraft
|
||||||
|
-- * **:OnAfterWeaponAdd(From,Event,To,EventData)**: Triggers when an item is added to an aircraft's payload
|
||||||
|
-- * **:OnAfterWeaponDrop(From,Event,To,EventData)**: Triggers when an item is jettisoned or dropped from an aircraft (unconfirmed)
|
||||||
|
-- * **:OnAfterWeaponRearm(From,Event,To,EventData)**: Triggers when an item with internal supply is restored (unconfirmed)
|
||||||
|
--
|
||||||
|
-- ### Examples
|
||||||
|
--
|
||||||
|
-- -- Show a message to player when they take damage from a weapon
|
||||||
|
-- local clientInstance = CLIENTWATCH:New("Rotary")
|
||||||
|
-- function clientInstance:OnAfterSpawn(From,Event,To,ClientObject,EventData)
|
||||||
|
-- function ClientObject:OnAfterHit(From,Event,To,EventData)
|
||||||
|
-- local typeShooter = EventData.IniTypeName
|
||||||
|
-- local nameWeapon = EventData.weapon_name
|
||||||
|
-- MESSAGE:New("A "..typeShooter.." hit you with a "..nameWeapon,20):ToUnit(ClientObject.Unit)
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
|
--
|
||||||
|
-- @field #CLIENTWATCH
|
||||||
|
CLIENTWATCH = {}
|
||||||
|
CLIENTWATCH.ClassName = "CLIENTWATCH"
|
||||||
|
CLIENTWATCH.Debug = false
|
||||||
|
CLIENTWATCH.DebugEventData = false
|
||||||
|
CLIENTWATCH.lid = nil
|
||||||
|
|
||||||
|
-- @type CLIENTWATCHTools
|
||||||
|
-- @field #table Unit Wrapper.UNIT of the cient object
|
||||||
|
-- @field #table Group Wrapper.GROUP of the cient object
|
||||||
|
-- @field #table Client Wrapper.CLIENT of the cient object
|
||||||
|
-- @field #string PlayerName Name of the player controlling the client object
|
||||||
|
-- @field #string UnitName Name of the unit that is the client object
|
||||||
|
-- @field #string GroupName Name of the group the client object belongs to
|
||||||
|
CLIENTWATCHTools = {}
|
||||||
|
|
||||||
|
--- CLIENTWATCH version
|
||||||
|
-- @field #string version
|
||||||
|
CLIENTWATCH.version="1.0.1"
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- Creates a new instance of CLIENTWATCH to add scripts to. Can be used multiple times with the same client/prefixes if you need it for multiple scripts.
|
||||||
|
-- @param #CLIENTWATCH self
|
||||||
|
-- @param #string Will watch for clients whos UNIT NAME or GROUP NAME matches part of the #string as a prefix.
|
||||||
|
-- @param #table Put strings in a table to use multiple prefixes for the above method.
|
||||||
|
-- @param Wrapper.Client#CLIENT Provide a Moose CLIENT object to apply to that specific aircraft slot (static slots only!)
|
||||||
|
-- @param #nil Leave blank to activate for ALL CLIENTS
|
||||||
|
-- @return #CLIENTWATCH self
|
||||||
|
function CLIENTWATCH:New(client)
|
||||||
|
--Init FSM
|
||||||
|
local self=BASE:Inherit(self, FSM:New())
|
||||||
|
self:SetStartState( "Idle" )
|
||||||
|
self:AddTransition( "*", "Spawn", "*" )
|
||||||
|
|
||||||
|
self.FilterCoalition = nil
|
||||||
|
self.FilterCategory = nil
|
||||||
|
|
||||||
|
--- User function for OnAfter "Spawn" event.
|
||||||
|
-- @function [parent=#CLIENTWATCH] OnAfterSpawn
|
||||||
|
-- @param #CLIENTWATCH self
|
||||||
|
-- @param Wrapper.Controllable#CONTROLLABLE Controllable Controllable of the group.
|
||||||
|
-- @param #string From From state.
|
||||||
|
-- @param #string Event Event.
|
||||||
|
-- @param #string To To state.
|
||||||
|
-- @param #table clientObject Custom object that handles events and stores Moose object data. See top documentation for more details.
|
||||||
|
-- @param #table eventdata Data from EVENTS.Birth.
|
||||||
|
|
||||||
|
--Set up spawn tracking
|
||||||
|
if not client then
|
||||||
|
if self.Debug then self:I({"New client instance created. ClientType = All clients"}) end
|
||||||
|
self:HandleEvent(EVENTS.Birth)
|
||||||
|
function self:OnEventBirth(eventdata)
|
||||||
|
if (eventdata.IniCategory == 0 or eventdata.IniCategory == 1) and eventdata.IniPlayerName
|
||||||
|
and (not self.FilterCoalition or self.FilterCoalition == eventdata.IniCoalition)
|
||||||
|
and (not self.FilterCategory or self.FilterCategory == eventdata.IniCategory) then
|
||||||
|
if self.Debug then
|
||||||
|
self:I({"Client spawned in.",IniCategory = eventdata.IniCategory})
|
||||||
|
end
|
||||||
|
local clientWatchDebug = self.Debug
|
||||||
|
local clientObject = CLIENTWATCHTools:_newClient(clientWatchDebug,eventdata)
|
||||||
|
self:Spawn(clientObject,eventdata)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif type(client) == "table" or type(client) == "string" then
|
||||||
|
if type(client) == "table" then
|
||||||
|
|
||||||
|
--CLIENT TABLE
|
||||||
|
if client.ClassName == "CLIENT" then
|
||||||
|
if self.Debug then self:I({"New client instance created. ClientType = Wrapper.CLIENT",client}) end
|
||||||
|
self.ClientName = client:GetName()
|
||||||
|
self:HandleEvent(EVENTS.Birth)
|
||||||
|
function self:OnEventBirth(eventdata)
|
||||||
|
if (eventdata.IniCategory == 0 or eventdata.IniCategory == 1) and eventdata.IniPlayerName
|
||||||
|
and (not self.FilterCoalition or self.FilterCoalition == eventdata.IniCoalition)
|
||||||
|
and (not self.FilterCategory or self.FilterCategory == eventdata.IniCategory) then
|
||||||
|
if self.ClientName == eventdata.IniUnitName then
|
||||||
|
if self.Debug then
|
||||||
|
self:I({"Client spawned in.",IniCategory = eventdata.IniCategory})
|
||||||
|
end
|
||||||
|
local clientWatchDebug = self.Debug
|
||||||
|
local clientObject = CLIENTWATCHTools:_newClient(clientWatchDebug,eventdata)
|
||||||
|
self:Spawn(clientObject,eventdata)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--STRING TABLE
|
||||||
|
else
|
||||||
|
if self.Debug then self:I({"New client instance created. ClientType = Multiple Prefixes",client}) end
|
||||||
|
local tableValid = true
|
||||||
|
for _,entry in pairs(client) do
|
||||||
|
if type(entry) ~= "string" then
|
||||||
|
tableValid = false
|
||||||
|
self:E({"The base handler failed to start because at least one entry in param1's table is not a string!",InvalidEntry = entry})
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if tableValid then
|
||||||
|
self:HandleEvent(EVENTS.Birth)
|
||||||
|
function self:OnEventBirth(eventdata)
|
||||||
|
for _,entry in pairs(client) do
|
||||||
|
if (eventdata.IniCategory == 0 or eventdata.IniCategory == 1) and eventdata.IniPlayerName
|
||||||
|
and (not self.FilterCoalition or self.FilterCoalition == eventdata.IniCoalition)
|
||||||
|
and (not self.FilterCategory or self.FilterCategory == eventdata.IniCategory) then
|
||||||
|
if string.match(eventdata.IniUnitName,entry) or string.match(eventdata.IniGroupName,entry) then
|
||||||
|
if self.Debug then
|
||||||
|
self:I({"Client spawned in.",IniCategory = eventdata.IniCategory})
|
||||||
|
end
|
||||||
|
local clientWatchDebug = self.Debug
|
||||||
|
local clientObject = CLIENTWATCHTools:_newClient(clientWatchDebug,eventdata)
|
||||||
|
self:Spawn(clientObject,eventdata)
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if self.Debug then self:I({"New client instance created. ClientType = Single Prefix",client}) end
|
||||||
|
|
||||||
|
--SOLO STRING
|
||||||
|
self:HandleEvent(EVENTS.Birth)
|
||||||
|
function self:OnEventBirth(eventdata)
|
||||||
|
if (eventdata.IniCategory == 0 or eventdata.IniCategory == 1) and eventdata.IniPlayerName
|
||||||
|
and (not self.FilterCoalition or self.FilterCoalition == eventdata.IniCoalition)
|
||||||
|
and (not self.FilterCategory or self.FilterCategory == eventdata.IniCategory) then
|
||||||
|
if string.match(eventdata.IniUnitName,client) or string.match(eventdata.IniGroupName,client) then
|
||||||
|
if self.Debug then
|
||||||
|
self:I({"Client spawned in.",IniCategory = eventdata.IniCategory})
|
||||||
|
end
|
||||||
|
local clientWatchDebug = self.Debug
|
||||||
|
local clientObject = CLIENTWATCHTools:_newClient(clientWatchDebug,eventdata)
|
||||||
|
self:Spawn(clientObject,eventdata)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
self:E({"The base handler failed to start because param1 is not a CLIENT object or a prefix string!",param1 = client})
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Filter out all clients not belonging to the provided coalition
|
||||||
|
-- @param #CLIENTWATCH self
|
||||||
|
-- @param #number Coalition number (1 = red, 2 = blue)
|
||||||
|
-- @param #string Coalition string ('red' or 'blue')
|
||||||
|
function CLIENTWATCH:FilterByCoalition(value)
|
||||||
|
if value == 1 or value == "red" then
|
||||||
|
self.FilterCoalition = 1
|
||||||
|
else
|
||||||
|
self.FilterCoalition = 2
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--- Filter out all clients that are not of the given category
|
||||||
|
-- @param #CLIENTWATCH self
|
||||||
|
-- @param #number Category number (0 = airplane, 1 = helicopter)
|
||||||
|
-- @param #string Category string ('airplane' or 'helicopter')
|
||||||
|
function CLIENTWATCH:FilterByCategory(value)
|
||||||
|
if value == 1 or value == "helicopter" then
|
||||||
|
self.FilterCategory = 1
|
||||||
|
else
|
||||||
|
self.FilterCategory = 0
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- Internal function for creating a new client on birth. Do not use!!!.
|
||||||
|
-- @param #CLIENTWATCHTools self
|
||||||
|
-- @param #EVENTS.Birth EventData
|
||||||
|
-- @return #CLIENTWATCHTools self
|
||||||
|
function CLIENTWATCHTools:_newClient(clientWatchDebug,eventdata)
|
||||||
|
--Init FSM
|
||||||
|
local self=BASE:Inherit(self, FSM:New())
|
||||||
|
self:SetStartState( "Alive" )
|
||||||
|
self:AddTransition( "Alive", "Despawn", "Dead" )
|
||||||
|
|
||||||
|
self.Unit = eventdata.IniUnit
|
||||||
|
self.Group = self.Unit:GetGroup()
|
||||||
|
self.Client = self.Unit:GetClient()
|
||||||
|
self.PlayerName = self.Unit:GetPlayerName()
|
||||||
|
self.UnitName = self.Unit:GetName()
|
||||||
|
self.GroupName = self.Group:GetName()
|
||||||
|
|
||||||
|
--Event events
|
||||||
|
self:AddTransition( "*", "Hit", "*" )
|
||||||
|
self:AddTransition( "*", "Kill", "*" )
|
||||||
|
self:AddTransition( "*", "Score", "*" )
|
||||||
|
self:AddTransition( "*", "Shot", "*" )
|
||||||
|
self:AddTransition( "*", "ShootingStart", "*" )
|
||||||
|
self:AddTransition( "*", "ShootingEnd", "*" )
|
||||||
|
self:AddTransition( "*", "Land", "*" )
|
||||||
|
self:AddTransition( "*", "Takeoff", "*" )
|
||||||
|
self:AddTransition( "*", "RunwayTakeoff", "*" )
|
||||||
|
self:AddTransition( "*", "RunwayTouch", "*" )
|
||||||
|
self:AddTransition( "*", "Refueling", "*" )
|
||||||
|
self:AddTransition( "*", "RefuelingStop", "*" )
|
||||||
|
self:AddTransition( "*", "PlayerLeaveUnit", "*" )
|
||||||
|
self:AddTransition( "*", "Crash", "*" )
|
||||||
|
self:AddTransition( "*", "Dead", "*" )
|
||||||
|
self:AddTransition( "*", "PilotDead", "*" )
|
||||||
|
self:AddTransition( "*", "UnitLost", "*" )
|
||||||
|
self:AddTransition( "*", "Ejection", "*" )
|
||||||
|
self:AddTransition( "*", "HumanFailure", "*" )
|
||||||
|
self:AddTransition( "*", "HumanAircraftRepairFinish", "*" )
|
||||||
|
self:AddTransition( "*", "HumanAircraftRepairStart", "*" )
|
||||||
|
self:AddTransition( "*", "EngineShutdown", "*" )
|
||||||
|
self:AddTransition( "*", "EngineStartup", "*" )
|
||||||
|
self:AddTransition( "*", "WeaponAdd", "*" )
|
||||||
|
self:AddTransition( "*", "WeaponDrop", "*" )
|
||||||
|
self:AddTransition( "*", "WeaponRearm", "*" )
|
||||||
|
|
||||||
|
--Event Handlers
|
||||||
|
self:HandleEvent( EVENTS.Hit )
|
||||||
|
self:HandleEvent( EVENTS.Kill )
|
||||||
|
self:HandleEvent( EVENTS.Score )
|
||||||
|
self:HandleEvent( EVENTS.Shot )
|
||||||
|
self:HandleEvent( EVENTS.ShootingStart )
|
||||||
|
self:HandleEvent( EVENTS.ShootingEnd )
|
||||||
|
self:HandleEvent( EVENTS.Land )
|
||||||
|
self:HandleEvent( EVENTS.Takeoff )
|
||||||
|
self:HandleEvent( EVENTS.RunwayTakeoff )
|
||||||
|
self:HandleEvent( EVENTS.RunwayTouch )
|
||||||
|
self:HandleEvent( EVENTS.Refueling )
|
||||||
|
self:HandleEvent( EVENTS.RefuelingStop )
|
||||||
|
self:HandleEvent( EVENTS.PlayerLeaveUnit )
|
||||||
|
self:HandleEvent( EVENTS.Crash )
|
||||||
|
self:HandleEvent( EVENTS.Dead )
|
||||||
|
self:HandleEvent( EVENTS.PilotDead )
|
||||||
|
self:HandleEvent( EVENTS.UnitLost )
|
||||||
|
self:HandleEvent( EVENTS.Ejection )
|
||||||
|
self:HandleEvent( EVENTS.HumanFailure )
|
||||||
|
self:HandleEvent( EVENTS.HumanAircraftRepairFinish )
|
||||||
|
self:HandleEvent( EVENTS.HumanAircraftRepairStart )
|
||||||
|
self:HandleEvent( EVENTS.EngineShutdown )
|
||||||
|
self:HandleEvent( EVENTS.EngineStartup )
|
||||||
|
self:HandleEvent( EVENTS.WeaponAdd )
|
||||||
|
self:HandleEvent( EVENTS.WeaponDrop )
|
||||||
|
self:HandleEvent( EVENTS.WeaponRearm )
|
||||||
|
|
||||||
|
function self:OnEventHit(EventData)
|
||||||
|
if EventData.TgtUnitName == self.UnitName then
|
||||||
|
if clientWatchDebug then
|
||||||
|
self:I({"Client triggered hit event.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
|
||||||
|
|
||||||
|
end
|
||||||
|
self:Hit(EventData)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function self:OnEventKill(EventData)
|
||||||
|
if EventData.IniUnitName == self.UnitName then
|
||||||
|
if clientWatchDebug then
|
||||||
|
self:I({"Client triggered kill event.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
|
||||||
|
|
||||||
|
end
|
||||||
|
self:Kill(EventData)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function self:OnEventScore(EventData)
|
||||||
|
if EventData.IniUnitName == self.UnitName then
|
||||||
|
if clientWatchDebug then
|
||||||
|
self:I({"Client triggered score event.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
|
||||||
|
|
||||||
|
end
|
||||||
|
self:Score(EventData)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function self:OnEventShot(EventData)
|
||||||
|
if EventData.IniUnitName == self.UnitName then
|
||||||
|
if clientWatchDebug then
|
||||||
|
self:I({"Client triggered shot event.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
|
||||||
|
|
||||||
|
end
|
||||||
|
self:Shot(EventData)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function self:OnEventShootingStart(EventData)
|
||||||
|
if EventData.IniUnitName == self.UnitName then
|
||||||
|
if clientWatchDebug then
|
||||||
|
self:I({"Client triggered shooting start event.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
|
||||||
|
|
||||||
|
end
|
||||||
|
self:ShootingStart(EventData)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function self:OnEventShootingEnd(EventData)
|
||||||
|
if EventData.IniUnitName == self.UnitName then
|
||||||
|
if clientWatchDebug then
|
||||||
|
self:I({"Client triggered shooting end event.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
|
||||||
|
|
||||||
|
end
|
||||||
|
self:ShootingEnd(EventData)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function self:OnEventLand(EventData)
|
||||||
|
if EventData.IniUnitName == self.UnitName then
|
||||||
|
if clientWatchDebug then
|
||||||
|
self:I({"Client triggered land event.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
|
||||||
|
|
||||||
|
end
|
||||||
|
self:Land(EventData)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function self:OnEventTakeoff(EventData)
|
||||||
|
if EventData.IniUnitName == self.UnitName then
|
||||||
|
if clientWatchDebug then
|
||||||
|
self:I({"Client triggered takeoff event.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
|
||||||
|
|
||||||
|
end
|
||||||
|
self:Takeoff(EventData)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function self:OnEventRunwayTakeoff(EventData)
|
||||||
|
if EventData.IniUnitName == self.UnitName then
|
||||||
|
if clientWatchDebug then
|
||||||
|
self:I({"Client triggered runway takeoff event.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
|
||||||
|
|
||||||
|
end
|
||||||
|
self:RunwayTakeoff(EventData)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function self:OnEventRunwayTouch(EventData)
|
||||||
|
if EventData.IniUnitName == self.UnitName then
|
||||||
|
if clientWatchDebug then
|
||||||
|
self:I({"Client triggered runway touch event.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
|
||||||
|
|
||||||
|
end
|
||||||
|
self:RunwayTouch(EventData)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function self:OnEventRefueling(EventData)
|
||||||
|
if EventData.IniUnitName == self.UnitName then
|
||||||
|
if clientWatchDebug then
|
||||||
|
self:I({"Client triggered refueling event.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
|
||||||
|
|
||||||
|
end
|
||||||
|
self:Refueling(EventData)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function self:OnEventRefuelingStop(EventData)
|
||||||
|
if EventData.IniUnitName == self.UnitName then
|
||||||
|
if clientWatchDebug then
|
||||||
|
self:I({"Client triggered refueling event.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
|
||||||
|
|
||||||
|
end
|
||||||
|
self:RefuelingStop(EventData)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function self:OnEventPlayerLeaveUnit(EventData)
|
||||||
|
if EventData.IniUnitName == self.UnitName then
|
||||||
|
if clientWatchDebug then
|
||||||
|
self:I({"Client triggered leave unit event.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
|
||||||
|
|
||||||
|
end
|
||||||
|
self:PlayerLeaveUnit(EventData)
|
||||||
|
self._deadRoutine()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function self:OnEventCrash(EventData)
|
||||||
|
if EventData.IniUnitName == self.UnitName then
|
||||||
|
if clientWatchDebug then
|
||||||
|
self:I({"Client triggered crash event.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
|
||||||
|
|
||||||
|
end
|
||||||
|
self:Crash(EventData)
|
||||||
|
self._deadRoutine()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function self:OnEventDead(EventData)
|
||||||
|
if EventData.IniUnitName == self.UnitName then
|
||||||
|
if clientWatchDebug then
|
||||||
|
self:I({"Client triggered dead event.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
|
||||||
|
|
||||||
|
end
|
||||||
|
self:Dead(EventData)
|
||||||
|
self._deadRoutine()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function self:OnEventPilotDead(EventData)
|
||||||
|
if EventData.IniUnitName == self.UnitName then
|
||||||
|
if clientWatchDebug then
|
||||||
|
self:I({"Client triggered pilot dead event.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
|
||||||
|
|
||||||
|
end
|
||||||
|
self:PilotDead(EventData)
|
||||||
|
self._deadRoutine()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function self:OnEventUnitLost(EventData)
|
||||||
|
if EventData.IniUnitName == self.UnitName then
|
||||||
|
if clientWatchDebug then
|
||||||
|
self:I({"Client triggered unit lost event.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
|
||||||
|
|
||||||
|
end
|
||||||
|
self:UnitLost(EventData)
|
||||||
|
self._deadRoutine()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function self:OnEventEjection(EventData)
|
||||||
|
if EventData.IniUnitName == self.UnitName then
|
||||||
|
if clientWatchDebug then
|
||||||
|
self:I({"Client triggered ejection event.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
|
||||||
|
|
||||||
|
end
|
||||||
|
self:Ejection(EventData)
|
||||||
|
self._deadRoutine()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function self:OnEventHumanFailure(EventData)
|
||||||
|
if EventData.IniUnitName == self.UnitName then
|
||||||
|
if clientWatchDebug then
|
||||||
|
self:I({"Client triggered human failure event.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
|
||||||
|
|
||||||
|
end
|
||||||
|
self:HumanFailure(EventData)
|
||||||
|
if not self.Unit:IsAlive() then
|
||||||
|
self._deadRoutine()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function self:OnEventHumanAircraftRepairFinish(EventData)
|
||||||
|
if EventData.IniUnitName == self.UnitName then
|
||||||
|
if clientWatchDebug then
|
||||||
|
self:I({"Client triggered repair finished event.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
|
||||||
|
|
||||||
|
end
|
||||||
|
self:HumanAircraftRepairFinish(EventData)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function self:OnEventHumanAircraftRepairStart(EventData)
|
||||||
|
if EventData.IniUnitName == self.UnitName then
|
||||||
|
if clientWatchDebug then
|
||||||
|
self:I({"Client triggered repair start event.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
|
||||||
|
|
||||||
|
end
|
||||||
|
self:HumanAircraftRepairStart(EventData)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function self:OnEventEngineShutdown(EventData)
|
||||||
|
if EventData.IniUnitName == self.UnitName then
|
||||||
|
if clientWatchDebug then
|
||||||
|
self:I({"Client triggered engine shutdown event.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
|
||||||
|
|
||||||
|
end
|
||||||
|
self:EngineShutdown(EventData)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function self:OnEventEngineStartup(EventData)
|
||||||
|
if EventData.IniUnitName == self.UnitName then
|
||||||
|
if clientWatchDebug then
|
||||||
|
self:I({"Client triggered engine startup event.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
|
||||||
|
|
||||||
|
end
|
||||||
|
self:EngineStartup(EventData)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function self:OnEventWeaponAdd(EventData)
|
||||||
|
if EventData.IniUnitName == self.UnitName then
|
||||||
|
if clientWatchDebug then
|
||||||
|
self:I({"Client triggered weapon add event.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
|
||||||
|
|
||||||
|
end
|
||||||
|
self:WeaponAdd(EventData)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function self:OnEventWeaponDrop(EventData)
|
||||||
|
if EventData.IniUnitName == self.UnitName then
|
||||||
|
if clientWatchDebug then
|
||||||
|
self:I({"Client triggered weapon drop event.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
|
||||||
|
|
||||||
|
end
|
||||||
|
self:WeaponDrop(EventData)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function self:OnEventWeaponRearm(EventData)
|
||||||
|
if EventData.IniUnitName == self.UnitName then
|
||||||
|
if clientWatchDebug then
|
||||||
|
self:I({"Client triggered weapon rearm event.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
|
||||||
|
|
||||||
|
end
|
||||||
|
self:WeaponRearm(EventData)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
--Fallback timer
|
||||||
|
self.FallbackTimer = TIMER:New(function()
|
||||||
|
if not self.Unit:IsAlive() then
|
||||||
|
if clientWatchDebug then
|
||||||
|
self:I({"Client is registered as dead without an event trigger. Running fallback dead routine.",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName})
|
||||||
|
end
|
||||||
|
self._deadRoutine()
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
self.FallbackTimer:Start(5,5)
|
||||||
|
|
||||||
|
--Stop event handlers and trigger Despawn
|
||||||
|
function self._deadRoutine()
|
||||||
|
if clientWatchDebug then self:I({"Client dead routine triggered. Shutting down tracking...",Player = self.PlayerName,Group = self.GroupName,Unit = self.UnitName}) end
|
||||||
|
self:UnHandleEvent( EVENTS.Hit )
|
||||||
|
self:UnHandleEvent( EVENTS.Kill )
|
||||||
|
self:UnHandleEvent( EVENTS.Score )
|
||||||
|
self:UnHandleEvent( EVENTS.Shot )
|
||||||
|
self:UnHandleEvent( EVENTS.ShootingStart )
|
||||||
|
self:UnHandleEvent( EVENTS.ShootingEnd )
|
||||||
|
self:UnHandleEvent( EVENTS.Land )
|
||||||
|
self:UnHandleEvent( EVENTS.Takeoff )
|
||||||
|
self:UnHandleEvent( EVENTS.RunwayTakeoff )
|
||||||
|
self:UnHandleEvent( EVENTS.RunwayTouch )
|
||||||
|
self:UnHandleEvent( EVENTS.Refueling )
|
||||||
|
self:UnHandleEvent( EVENTS.RefuelingStop )
|
||||||
|
self:UnHandleEvent( EVENTS.PlayerLeaveUnit )
|
||||||
|
self:UnHandleEvent( EVENTS.Crash )
|
||||||
|
self:UnHandleEvent( EVENTS.Dead )
|
||||||
|
self:UnHandleEvent( EVENTS.PilotDead )
|
||||||
|
self:UnHandleEvent( EVENTS.UnitLost )
|
||||||
|
self:UnHandleEvent( EVENTS.Ejection )
|
||||||
|
self:UnHandleEvent( EVENTS.HumanFailure )
|
||||||
|
self:UnHandleEvent( EVENTS.HumanAircraftRepairFinish )
|
||||||
|
self:UnHandleEvent( EVENTS.HumanAircraftRepairStart )
|
||||||
|
self:UnHandleEvent( EVENTS.EngineShutdown )
|
||||||
|
self:UnHandleEvent( EVENTS.EngineStartup )
|
||||||
|
self:UnHandleEvent( EVENTS.WeaponAdd )
|
||||||
|
self:UnHandleEvent( EVENTS.WeaponDrop )
|
||||||
|
self:UnHandleEvent( EVENTS.WeaponRearm )
|
||||||
|
self.FallbackTimer:Stop()
|
||||||
|
self:Despawn()
|
||||||
|
end
|
||||||
|
|
||||||
|
self:I({"Detected client spawn and applied internal functions and events.", PlayerName = self.PlayerName, UnitName = self.UnitName, GroupName = self.GroupName})
|
||||||
|
return self
|
||||||
|
end
|
||||||
@@ -595,7 +595,8 @@ do -- DETECTION_BASE
|
|||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---
|
||||||
-- @param #DETECTION_BASE self
|
-- @param #DETECTION_BASE self
|
||||||
-- @param #string From The From State string.
|
-- @param #string From The From State string.
|
||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
@@ -604,7 +605,7 @@ do -- DETECTION_BASE
|
|||||||
-- @param #number DetectionTimeStamp Time stamp of detection event.
|
-- @param #number DetectionTimeStamp Time stamp of detection event.
|
||||||
function DETECTION_BASE:onafterDetection( From, Event, To, Detection, DetectionTimeStamp )
|
function DETECTION_BASE:onafterDetection( From, Event, To, Detection, DetectionTimeStamp )
|
||||||
|
|
||||||
self:I( { DetectedObjects = self.DetectedObjects } )
|
self:T( { DetectedObjects = self.DetectedObjects } )
|
||||||
|
|
||||||
self.DetectionRun = self.DetectionRun + 1
|
self.DetectionRun = self.DetectionRun + 1
|
||||||
|
|
||||||
@@ -612,10 +613,10 @@ do -- DETECTION_BASE
|
|||||||
|
|
||||||
if Detection and Detection:IsAlive() then
|
if Detection and Detection:IsAlive() then
|
||||||
|
|
||||||
self:I( { "DetectionGroup is Alive", Detection:GetName() } )
|
self:T( { "DetectionGroup is Alive", Detection:GetName() } )
|
||||||
|
|
||||||
local DetectionGroupName = Detection:GetName()
|
local DetectionGroupName = Detection:GetName()
|
||||||
local DetectionUnit = Detection:GetUnit( 1 )
|
local DetectionUnit = Detection:GetFirstUnitAlive()
|
||||||
|
|
||||||
local DetectedUnits = {}
|
local DetectedUnits = {}
|
||||||
|
|
||||||
@@ -628,30 +629,30 @@ do -- DETECTION_BASE
|
|||||||
self.DetectDLINK
|
self.DetectDLINK
|
||||||
)
|
)
|
||||||
|
|
||||||
--self:I( { DetectedTargets = DetectedTargets } )
|
--self:T( { DetectedTargets = DetectedTargets } )
|
||||||
--self:I(UTILS.PrintTableToLog(DetectedTargets))
|
--self:T(UTILS.PrintTableToLog(DetectedTargets))
|
||||||
|
|
||||||
|
|
||||||
for DetectionObjectID, Detection in pairs( DetectedTargets ) do
|
for DetectionObjectID, Detection in pairs( DetectedTargets or {}) do
|
||||||
local DetectedObject = Detection.object -- DCS#Object
|
local DetectedObject = Detection.object -- DCS#Object
|
||||||
|
|
||||||
if DetectedObject and DetectedObject:isExist() and DetectedObject.id_ < 50000000 then -- and ( DetectedObject:getCategory() == Object.Category.UNIT or DetectedObject:getCategory() == Object.Category.STATIC ) then
|
if DetectedObject and DetectedObject:isExist() and DetectedObject.id_ < 50000000 then -- and ( DetectedObject:getCategory() == Object.Category.UNIT or DetectedObject:getCategory() == Object.Category.STATIC ) then
|
||||||
local DetectedObjectName = DetectedObject:getName()
|
local DetectedObjectName = DetectedObject:getName()
|
||||||
if not self.DetectedObjects[DetectedObjectName] then
|
if not self.DetectedObjects[DetectedObjectName] then
|
||||||
self.DetectedObjects[DetectedObjectName] = self.DetectedObjects[DetectedObjectName] or {}
|
self.DetectedObjects[DetectedObjectName] = self.DetectedObjects[DetectedObjectName] or {}
|
||||||
self.DetectedObjects[DetectedObjectName].Name = DetectedObjectName
|
self.DetectedObjects[DetectedObjectName].Name = DetectedObjectName
|
||||||
self.DetectedObjects[DetectedObjectName].Object = DetectedObject
|
self.DetectedObjects[DetectedObjectName].Object = DetectedObject
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
for DetectionObjectName, DetectedObjectData in pairs( self.DetectedObjects ) do
|
for DetectionObjectName, DetectedObjectData in pairs( self.DetectedObjects or {}) do
|
||||||
|
|
||||||
local DetectedObject = DetectedObjectData.Object
|
local DetectedObject = DetectedObjectData.Object
|
||||||
|
|
||||||
if DetectedObject:isExist() then
|
if DetectedObject:isExist() then
|
||||||
|
|
||||||
local TargetIsDetected, TargetIsVisible, TargetLastTime, TargetKnowType, TargetKnowDistance, TargetLastPos, TargetLastVelocity = DetectionUnit:IsTargetDetected(
|
local TargetIsDetected, TargetIsVisible, TargetKnowType, TargetKnowDistance, TargetLastTime, TargetLastPos, TargetLastVelocity = DetectionUnit:IsTargetDetected(
|
||||||
DetectedObject,
|
DetectedObject,
|
||||||
self.DetectVisual,
|
self.DetectVisual,
|
||||||
self.DetectOptical,
|
self.DetectOptical,
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
do -- DETECTION_ZONES
|
do -- DETECTION_ZONES
|
||||||
|
|
||||||
--- @type DETECTION_ZONES
|
-- @type DETECTION_ZONES
|
||||||
-- @field DCS#Distance DetectionZoneRange The range till which targets are grouped upon the first detected target.
|
-- @field DCS#Distance DetectionZoneRange The range till which targets are grouped upon the first detected target.
|
||||||
-- @field #DETECTION_BASE.DetectedItems DetectedItems A list of areas containing the set of @{Wrapper.Unit}s, @{Core.Zone}s, the center @{Wrapper.Unit} within the zone, and ID of each area that was detected within a DetectionZoneRange.
|
-- @field #DETECTION_BASE.DetectedItems DetectedItems A list of areas containing the set of @{Wrapper.Unit}s, @{Core.Zone}s, the center @{Wrapper.Unit} within the zone, and ID of each area that was detected within a DetectionZoneRange.
|
||||||
-- @extends Functional.Detection#DETECTION_BASE
|
-- @extends Functional.Detection#DETECTION_BASE
|
||||||
@@ -68,7 +68,7 @@ do -- DETECTION_ZONES
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #DETECTION_ZONES self
|
-- @param #DETECTION_ZONES self
|
||||||
-- @param #number The amount of alive recce.
|
-- @param #number The amount of alive recce.
|
||||||
function DETECTION_ZONES:CountAliveRecce()
|
function DETECTION_ZONES:CountAliveRecce()
|
||||||
|
|
||||||
@@ -76,7 +76,7 @@ do -- DETECTION_ZONES
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #DETECTION_ZONES self
|
-- @param #DETECTION_ZONES self
|
||||||
function DETECTION_ZONES:ForEachAliveRecce( IteratorFunction, ... )
|
function DETECTION_ZONES:ForEachAliveRecce( IteratorFunction, ... )
|
||||||
self:F2( arg )
|
self:F2( arg )
|
||||||
|
|
||||||
@@ -352,7 +352,7 @@ do -- DETECTION_ZONES
|
|||||||
--DetectedSet:Flush( self )
|
--DetectedSet:Flush( self )
|
||||||
|
|
||||||
DetectedSet:ForEachUnit(
|
DetectedSet:ForEachUnit(
|
||||||
--- @param Wrapper.Unit#UNIT DetectedUnit
|
-- @param Wrapper.Unit#UNIT DetectedUnit
|
||||||
function( DetectedUnit )
|
function( DetectedUnit )
|
||||||
if DetectedUnit:IsAlive() then
|
if DetectedUnit:IsAlive() then
|
||||||
--self:T( "Detected Set #" .. DetectedItem.ID .. ":" .. DetectedUnit:GetName() )
|
--self:T( "Detected Set #" .. DetectedItem.ID .. ":" .. DetectedUnit:GetName() )
|
||||||
@@ -380,7 +380,7 @@ do -- DETECTION_ZONES
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #DETECTION_ZONES self
|
-- @param #DETECTION_ZONES self
|
||||||
-- @param #string From The From State string.
|
-- @param #string From The From State string.
|
||||||
-- @param #string Event The Event string.
|
-- @param #string Event The Event string.
|
||||||
-- @param #string To The To State string.
|
-- @param #string To The To State string.
|
||||||
|
|||||||
@@ -1154,8 +1154,6 @@ function ESCORT:_ReportTargetsScheduler()
|
|||||||
|
|
||||||
if self.EscortGroup:IsAlive() and self.EscortClient:IsAlive() then
|
if self.EscortGroup:IsAlive() and self.EscortClient:IsAlive() then
|
||||||
|
|
||||||
if true then
|
|
||||||
|
|
||||||
local EscortGroupName = self.EscortGroup:GetName()
|
local EscortGroupName = self.EscortGroup:GetName()
|
||||||
|
|
||||||
self.EscortMenuAttackNearbyTargets:RemoveSubMenus()
|
self.EscortMenuAttackNearbyTargets:RemoveSubMenus()
|
||||||
@@ -1226,177 +1224,6 @@ function ESCORT:_ReportTargetsScheduler()
|
|||||||
end
|
end
|
||||||
|
|
||||||
return true
|
return true
|
||||||
else
|
|
||||||
-- local EscortGroupName = self.EscortGroup:GetName()
|
|
||||||
-- local EscortTargets = self.EscortGroup:GetDetectedTargets()
|
|
||||||
--
|
|
||||||
-- local ClientEscortTargets = self.EscortClient._EscortGroups[EscortGroupName].Targets
|
|
||||||
--
|
|
||||||
-- local EscortTargetMessages = ""
|
|
||||||
-- for EscortTargetID, EscortTarget in pairs( EscortTargets ) do
|
|
||||||
-- local EscortObject = EscortTarget.object
|
|
||||||
-- self:T( EscortObject )
|
|
||||||
-- if EscortObject and EscortObject:isExist() and EscortObject.id_ < 50000000 then
|
|
||||||
--
|
|
||||||
-- local EscortTargetUnit = UNIT:Find( EscortObject )
|
|
||||||
-- local EscortTargetUnitName = EscortTargetUnit:GetName()
|
|
||||||
--
|
|
||||||
--
|
|
||||||
--
|
|
||||||
-- -- local EscortTargetIsDetected,
|
|
||||||
-- -- EscortTargetIsVisible,
|
|
||||||
-- -- EscortTargetLastTime,
|
|
||||||
-- -- EscortTargetKnowType,
|
|
||||||
-- -- EscortTargetKnowDistance,
|
|
||||||
-- -- EscortTargetLastPos,
|
|
||||||
-- -- EscortTargetLastVelocity
|
|
||||||
-- -- = self.EscortGroup:IsTargetDetected( EscortObject )
|
|
||||||
-- --
|
|
||||||
-- -- self:T( { EscortTargetIsDetected,
|
|
||||||
-- -- EscortTargetIsVisible,
|
|
||||||
-- -- EscortTargetLastTime,
|
|
||||||
-- -- EscortTargetKnowType,
|
|
||||||
-- -- EscortTargetKnowDistance,
|
|
||||||
-- -- EscortTargetLastPos,
|
|
||||||
-- -- EscortTargetLastVelocity } )
|
|
||||||
--
|
|
||||||
--
|
|
||||||
-- local EscortTargetUnitVec3 = EscortTargetUnit:GetVec3()
|
|
||||||
-- local EscortVec3 = self.EscortGroup:GetVec3()
|
|
||||||
-- local Distance = ( ( EscortTargetUnitVec3.x - EscortVec3.x )^2 +
|
|
||||||
-- ( EscortTargetUnitVec3.y - EscortVec3.y )^2 +
|
|
||||||
-- ( EscortTargetUnitVec3.z - EscortVec3.z )^2
|
|
||||||
-- ) ^ 0.5 / 1000
|
|
||||||
--
|
|
||||||
-- self:T( { self.EscortGroup:GetName(), EscortTargetUnit:GetName(), Distance, EscortTarget } )
|
|
||||||
--
|
|
||||||
-- if Distance <= 15 then
|
|
||||||
--
|
|
||||||
-- if not ClientEscortTargets[EscortTargetUnitName] then
|
|
||||||
-- ClientEscortTargets[EscortTargetUnitName] = {}
|
|
||||||
-- end
|
|
||||||
-- ClientEscortTargets[EscortTargetUnitName].AttackUnit = EscortTargetUnit
|
|
||||||
-- ClientEscortTargets[EscortTargetUnitName].visible = EscortTarget.visible
|
|
||||||
-- ClientEscortTargets[EscortTargetUnitName].type = EscortTarget.type
|
|
||||||
-- ClientEscortTargets[EscortTargetUnitName].distance = EscortTarget.distance
|
|
||||||
-- else
|
|
||||||
-- if ClientEscortTargets[EscortTargetUnitName] then
|
|
||||||
-- ClientEscortTargets[EscortTargetUnitName] = nil
|
|
||||||
-- end
|
|
||||||
-- end
|
|
||||||
-- end
|
|
||||||
-- end
|
|
||||||
--
|
|
||||||
-- self:T( { "Sorting Targets Table:", ClientEscortTargets } )
|
|
||||||
-- table.sort( ClientEscortTargets, function( a, b ) return a.Distance < b.Distance end )
|
|
||||||
-- self:T( { "Sorted Targets Table:", ClientEscortTargets } )
|
|
||||||
--
|
|
||||||
-- -- Remove the sub menus of the Attack menu of the Escort for the EscortGroup.
|
|
||||||
-- self.EscortMenuAttackNearbyTargets:RemoveSubMenus()
|
|
||||||
--
|
|
||||||
-- if self.EscortMenuTargetAssistance then
|
|
||||||
-- self.EscortMenuTargetAssistance:RemoveSubMenus()
|
|
||||||
-- end
|
|
||||||
--
|
|
||||||
-- --for MenuIndex = 1, #self.EscortMenuAttackTargets do
|
|
||||||
-- -- self:T( { "Remove Menu:", self.EscortMenuAttackTargets[MenuIndex] } )
|
|
||||||
-- -- self.EscortMenuAttackTargets[MenuIndex] = self.EscortMenuAttackTargets[MenuIndex]:Remove()
|
|
||||||
-- --end
|
|
||||||
--
|
|
||||||
--
|
|
||||||
-- if ClientEscortTargets then
|
|
||||||
-- for ClientEscortTargetUnitName, ClientEscortTargetData in pairs( ClientEscortTargets ) do
|
|
||||||
--
|
|
||||||
-- for ClientEscortGroupName, EscortGroupData in pairs( self.EscortClient._EscortGroups ) do
|
|
||||||
--
|
|
||||||
-- if ClientEscortTargetData and ClientEscortTargetData.AttackUnit:IsAlive() then
|
|
||||||
--
|
|
||||||
-- local EscortTargetMessage = ""
|
|
||||||
-- local EscortTargetCategoryName = ClientEscortTargetData.AttackUnit:GetCategoryName()
|
|
||||||
-- local EscortTargetCategoryType = ClientEscortTargetData.AttackUnit:GetTypeName()
|
|
||||||
-- if ClientEscortTargetData.type then
|
|
||||||
-- EscortTargetMessage = EscortTargetMessage .. EscortTargetCategoryName .. " (" .. EscortTargetCategoryType .. ") at "
|
|
||||||
-- else
|
|
||||||
-- EscortTargetMessage = EscortTargetMessage .. "Unknown target at "
|
|
||||||
-- end
|
|
||||||
--
|
|
||||||
-- local EscortTargetUnitVec3 = ClientEscortTargetData.AttackUnit:GetVec3()
|
|
||||||
-- local EscortVec3 = self.EscortGroup:GetVec3()
|
|
||||||
-- local Distance = ( ( EscortTargetUnitVec3.x - EscortVec3.x )^2 +
|
|
||||||
-- ( EscortTargetUnitVec3.y - EscortVec3.y )^2 +
|
|
||||||
-- ( EscortTargetUnitVec3.z - EscortVec3.z )^2
|
|
||||||
-- ) ^ 0.5 / 1000
|
|
||||||
--
|
|
||||||
-- self:T( { self.EscortGroup:GetName(), ClientEscortTargetData.AttackUnit:GetName(), Distance, ClientEscortTargetData.AttackUnit } )
|
|
||||||
-- if ClientEscortTargetData.visible == false then
|
|
||||||
-- EscortTargetMessage = EscortTargetMessage .. string.format( "%.2f", Distance ) .. " estimated km"
|
|
||||||
-- else
|
|
||||||
-- EscortTargetMessage = EscortTargetMessage .. string.format( "%.2f", Distance ) .. " km"
|
|
||||||
-- end
|
|
||||||
--
|
|
||||||
-- if ClientEscortTargetData.visible then
|
|
||||||
-- EscortTargetMessage = EscortTargetMessage .. ", visual"
|
|
||||||
-- end
|
|
||||||
--
|
|
||||||
-- if ClientEscortGroupName == EscortGroupName then
|
|
||||||
--
|
|
||||||
-- MENU_GROUP_COMMAND:New( self.EscortClient,
|
|
||||||
-- EscortTargetMessage,
|
|
||||||
-- self.EscortMenuAttackNearbyTargets,
|
|
||||||
-- ESCORT._AttackTarget,
|
|
||||||
-- { ParamSelf = self,
|
|
||||||
-- ParamUnit = ClientEscortTargetData.AttackUnit
|
|
||||||
-- }
|
|
||||||
-- )
|
|
||||||
-- EscortTargetMessages = EscortTargetMessages .. "\n - " .. EscortTargetMessage
|
|
||||||
-- else
|
|
||||||
-- if self.EscortMenuTargetAssistance then
|
|
||||||
-- local MenuTargetAssistance = MENU_GROUP:New( self.EscortClient, EscortGroupData.EscortName, self.EscortMenuTargetAssistance )
|
|
||||||
-- MENU_GROUP_COMMAND:New( self.EscortClient,
|
|
||||||
-- EscortTargetMessage,
|
|
||||||
-- MenuTargetAssistance,
|
|
||||||
-- ESCORT._AssistTarget,
|
|
||||||
-- self,
|
|
||||||
-- EscortGroupData.EscortGroup,
|
|
||||||
-- ClientEscortTargetData.AttackUnit
|
|
||||||
-- )
|
|
||||||
-- end
|
|
||||||
-- end
|
|
||||||
-- else
|
|
||||||
-- ClientEscortTargetData = nil
|
|
||||||
-- end
|
|
||||||
-- end
|
|
||||||
-- end
|
|
||||||
--
|
|
||||||
-- if EscortTargetMessages ~= "" and self.ReportTargets == true then
|
|
||||||
-- self.EscortGroup:MessageToClient( "Detected targets within 15 km range:" .. EscortTargetMessages:gsub("\n$",""), 20, self.EscortClient )
|
|
||||||
-- else
|
|
||||||
-- self.EscortGroup:MessageToClient( "No targets detected!", 20, self.EscortClient )
|
|
||||||
-- end
|
|
||||||
-- end
|
|
||||||
--
|
|
||||||
-- if self.EscortMenuResumeMission then
|
|
||||||
-- self.EscortMenuResumeMission:RemoveSubMenus()
|
|
||||||
--
|
|
||||||
-- -- if self.EscortMenuResumeWayPoints then
|
|
||||||
-- -- for MenuIndex = 1, #self.EscortMenuResumeWayPoints do
|
|
||||||
-- -- self:T( { "Remove Menu:", self.EscortMenuResumeWayPoints[MenuIndex] } )
|
|
||||||
-- -- self.EscortMenuResumeWayPoints[MenuIndex] = self.EscortMenuResumeWayPoints[MenuIndex]:Remove()
|
|
||||||
-- -- end
|
|
||||||
-- -- end
|
|
||||||
--
|
|
||||||
-- local TaskPoints = self:RegisterRoute()
|
|
||||||
-- for WayPointID, WayPoint in pairs( TaskPoints ) do
|
|
||||||
-- local EscortVec3 = self.EscortGroup:GetVec3()
|
|
||||||
-- local Distance = ( ( WayPoint.x - EscortVec3.x )^2 +
|
|
||||||
-- ( WayPoint.y - EscortVec3.z )^2
|
|
||||||
-- ) ^ 0.5 / 1000
|
|
||||||
-- MENU_GROUP_COMMAND:New( self.EscortClient, "Waypoint " .. WayPointID .. " at " .. string.format( "%.2f", Distance ).. "km", self.EscortMenuResumeMission, ESCORT._ResumeMission, { ParamSelf = self, ParamWayPoint = WayPointID } )
|
|
||||||
-- end
|
|
||||||
-- end
|
|
||||||
--
|
|
||||||
-- return true
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return false
|
return false
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ FOX = {
|
|||||||
explosiondist = 200,
|
explosiondist = 200,
|
||||||
explosiondist2 = 500,
|
explosiondist2 = 500,
|
||||||
bigmissilemass = 50,
|
bigmissilemass = 50,
|
||||||
destroy = nil,
|
--destroy = nil,
|
||||||
dt50 = 5,
|
dt50 = 5,
|
||||||
dt10 = 1,
|
dt10 = 1,
|
||||||
dt05 = 0.5,
|
dt05 = 0.5,
|
||||||
@@ -1060,7 +1060,7 @@ function FOX:onafterMissileLaunch(From, Event, To, missile)
|
|||||||
|
|
||||||
-- Tracking info and init of last bomb position.
|
-- Tracking info and init of last bomb position.
|
||||||
local text=string.format("FOX: Tracking missile %s(%s) - target %s - shooter %s", missile.missileType, missile.missileName, tostring(missile.targetName), missile.shooterName)
|
local text=string.format("FOX: Tracking missile %s(%s) - target %s - shooter %s", missile.missileType, missile.missileName, tostring(missile.targetName), missile.shooterName)
|
||||||
self:I(FOX.lid..text)
|
self:T(FOX.lid..text)
|
||||||
MESSAGE:New(text, 10):ToAllIf(self.Debug)
|
MESSAGE:New(text, 10):ToAllIf(self.Debug)
|
||||||
|
|
||||||
-- Loop over players.
|
-- Loop over players.
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
-- @module Functional.Mantis
|
-- @module Functional.Mantis
|
||||||
-- @image Functional.Mantis.jpg
|
-- @image Functional.Mantis.jpg
|
||||||
--
|
--
|
||||||
-- Last Update: May 2024
|
-- Last Update: Mar 2025
|
||||||
|
|
||||||
-------------------------------------------------------------------------
|
-------------------------------------------------------------------------
|
||||||
--- **MANTIS** class, extends Core.Base#BASE
|
--- **MANTIS** class, extends Core.Base#BASE
|
||||||
@@ -59,6 +59,10 @@
|
|||||||
-- @field #number ShoradTime Timer in seconds, how long #SHORAD will be active after a detection inside of the defense range
|
-- @field #number ShoradTime Timer in seconds, how long #SHORAD will be active after a detection inside of the defense range
|
||||||
-- @field #number ShoradActDistance Distance of an attacker in meters from a Mantis SAM site, on which Shorad will be switched on. Useful to not give away Shorad sites too early. Default 15km. Should be smaller than checkradius.
|
-- @field #number ShoradActDistance Distance of an attacker in meters from a Mantis SAM site, on which Shorad will be switched on. Useful to not give away Shorad sites too early. Default 15km. Should be smaller than checkradius.
|
||||||
-- @field #boolean checkforfriendlies If true, do not activate a SAM installation if a friendly aircraft is in firing range.
|
-- @field #boolean checkforfriendlies If true, do not activate a SAM installation if a friendly aircraft is in firing range.
|
||||||
|
-- @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
|
||||||
-- @extends Core.Base#BASE
|
-- @extends Core.Base#BASE
|
||||||
|
|
||||||
|
|
||||||
@@ -70,7 +74,7 @@
|
|||||||
--
|
--
|
||||||
-- * Moose derived Modular, Automatic and Network capable Targeting and Interception System.
|
-- * Moose derived Modular, Automatic and Network capable Targeting and Interception System.
|
||||||
-- * Controls a network of SAM sites. Uses detection to switch on the SAM site closest to the enemy.
|
-- * Controls a network of SAM sites. Uses detection to switch on the SAM site closest to the enemy.
|
||||||
-- * **Automatic mode** (default since 0.8) can set-up your SAM site network automatically for you
|
-- * **Automatic mode** (default since 0.8) will set-up your SAM site network automatically for you
|
||||||
-- * **Classic mode** behaves like before
|
-- * **Classic mode** behaves like before
|
||||||
-- * Leverage evasiveness from SEAD, leverage attack range setting
|
-- * Leverage evasiveness from SEAD, leverage attack range setting
|
||||||
-- * Automatic setup of SHORAD based on groups of the class "short-range"
|
-- * Automatic setup of SHORAD based on groups of the class "short-range"
|
||||||
@@ -85,6 +89,7 @@
|
|||||||
-- * SAM sites, e.g. each **group name** begins with "Red SAM"
|
-- * SAM sites, e.g. each **group name** begins with "Red SAM"
|
||||||
-- * EWR network and AWACS, e.g. each **group name** begins with "Red EWR" and *not* e.g. "Red SAM EWR" (overlap with "Red SAM"), "Red EWR Awacs" will be found by "Red EWR"
|
-- * EWR network and AWACS, e.g. each **group name** begins with "Red EWR" and *not* e.g. "Red SAM EWR" (overlap with "Red SAM"), "Red EWR Awacs" will be found by "Red EWR"
|
||||||
-- * SHORAD, e.g. each **group name** begins with "Red SHORAD" and *not" e.g. just "SHORAD" because you might also have "Blue SHORAD"
|
-- * SHORAD, e.g. each **group name** begins with "Red SHORAD" and *not" e.g. just "SHORAD" because you might also have "Blue SHORAD"
|
||||||
|
-- * Point Defense, e.g. each **group name** begins with "Red AAA" and *not" e.g. just "AAA" because you might also have "Blue AAA"
|
||||||
--
|
--
|
||||||
-- It's important to get this right because of the nature of the filter-system in @{Core.Set#SET_GROUP}. Filters are "greedy", that is they
|
-- It's important to get this right because of the nature of the filter-system in @{Core.Set#SET_GROUP}. Filters are "greedy", that is they
|
||||||
-- will match *any* string that contains the search string - hence we need to avoid that SAMs, EWR and SHORAD step on each other\'s toes.
|
-- will match *any* string that contains the search string - hence we need to avoid that SAMs, EWR and SHORAD step on each other\'s toes.
|
||||||
@@ -143,6 +148,7 @@
|
|||||||
-- **Location** is of highest importance here. Whilst AWACS in DCS has almost the "all seeing eye", EWR don't have that. Choose your location wisely, against a mountain backdrop or inside a valley even the best EWR system
|
-- **Location** is of highest importance here. Whilst AWACS in DCS has almost the "all seeing eye", EWR don't have that. Choose your location wisely, against a mountain backdrop or inside a valley even the best EWR system
|
||||||
-- doesn't work well. Prefer higher-up locations with a good view; use F7 in-game to check where you actually placed your EWR and have a look around. Apart from the obvious choice, do also consider other radar units
|
-- doesn't work well. Prefer higher-up locations with a good view; use F7 in-game to check where you actually placed your EWR and have a look around. Apart from the obvious choice, do also consider other radar units
|
||||||
-- for this role, most have "SR" (search radar) or "STR" (search and track radar) in their names, use the encyclopedia to see what they actually do.
|
-- for this role, most have "SR" (search radar) or "STR" (search and track radar) in their names, use the encyclopedia to see what they actually do.
|
||||||
|
-- **HINT** Set at least one EWR on invisible and immortal so MANTIS doesn't stop working.
|
||||||
--
|
--
|
||||||
-- ## 1.2 SAM sites
|
-- ## 1.2 SAM sites
|
||||||
--
|
--
|
||||||
@@ -191,26 +197,24 @@
|
|||||||
-- mybluemantis:AddZones(AcceptZones,RejectZones,ConflictZones)
|
-- mybluemantis:AddZones(AcceptZones,RejectZones,ConflictZones)
|
||||||
--
|
--
|
||||||
--
|
--
|
||||||
-- ### 2.1.2 Change the number of long-, mid- and short-range systems going live on a detected target:
|
-- ### 2.1.2 Change the number of long-, mid- and short-range, point defense systems going live on a detected target:
|
||||||
--
|
--
|
||||||
-- -- parameters are numbers. Defaults are 1,2,2,6 respectively
|
-- -- parameters are numbers. Defaults are 1,2,2,6,6 respectively
|
||||||
-- mybluemantis:SetMaxActiveSAMs(Short,Mid,Long,Classic)
|
-- mybluemantis:SetMaxActiveSAMs(Short,Mid,Long,Classic,Point)
|
||||||
--
|
--
|
||||||
-- ### 2.1.3 SHORAD will automatically be added from SAM sites of type "short-range"
|
-- ### 2.1.3 SHORAD/Point defense will automatically be added from SAM sites of type "point" or if the range is less than 5km or if the type is AAA.
|
||||||
--
|
--
|
||||||
-- ### 2.1.4 Advanced features
|
-- ### 2.1.4 Advanced features
|
||||||
--
|
--
|
||||||
-- -- switch off auto mode **before** you start MANTIS.
|
-- -- Option to switch off auto mode **before** you start MANTIS (not recommended)
|
||||||
-- mybluemantis.automode = false
|
-- mybluemantis.automode = false
|
||||||
--
|
--
|
||||||
-- -- switch off auto shorad **before** you start MANTIS.
|
-- -- Option to set the scale of the activation range, i.e. don't activate at the fringes of max range, defaults below.
|
||||||
-- mybluemantis.autoshorad = false
|
|
||||||
--
|
|
||||||
-- -- scale of the activation range, i.e. don't activate at the fringes of max range, defaults below.
|
|
||||||
-- -- also see engagerange below.
|
-- -- also see engagerange below.
|
||||||
-- self.radiusscale[MANTIS.SamType.LONG] = 1.1
|
-- self.radiusscale[MANTIS.SamType.LONG] = 1.1
|
||||||
-- self.radiusscale[MANTIS.SamType.MEDIUM] = 1.2
|
-- self.radiusscale[MANTIS.SamType.MEDIUM] = 1.2
|
||||||
-- self.radiusscale[MANTIS.SamType.SHORT] = 1.3
|
-- self.radiusscale[MANTIS.SamType.SHORT] = 1.3
|
||||||
|
-- self.radiusscale[MANTIS.SamType.POINT] = 1.4
|
||||||
--
|
--
|
||||||
-- ### 2.1.5 Friendlies check in firing range
|
-- ### 2.1.5 Friendlies check in firing range
|
||||||
--
|
--
|
||||||
@@ -239,9 +243,9 @@
|
|||||||
--
|
--
|
||||||
-- Use this option if you want to make use of or allow advanced SEAD tactics.
|
-- Use this option if you want to make use of or allow advanced SEAD tactics.
|
||||||
--
|
--
|
||||||
-- # 5. Integrate SHORAD [classic mode]
|
-- # 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. When SHORAD detects a missile fired at one of MANTIS' SAM sites, it will activate SHORAD systems in
|
-- 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:
|
-- 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()
|
-- local SamSet = SET_GROUP:New():FilterPrefixes("Blue SAM"):FilterCoalitions("blue"):FilterStart()
|
||||||
@@ -295,6 +299,7 @@ MANTIS = {
|
|||||||
SAM_Table_Long = {},
|
SAM_Table_Long = {},
|
||||||
SAM_Table_Medium = {},
|
SAM_Table_Medium = {},
|
||||||
SAM_Table_Short = {},
|
SAM_Table_Short = {},
|
||||||
|
SAM_Table_PointDef = {},
|
||||||
lid = "",
|
lid = "",
|
||||||
Detection = nil,
|
Detection = nil,
|
||||||
AWACS_Detection = nil,
|
AWACS_Detection = nil,
|
||||||
@@ -328,6 +333,9 @@ MANTIS = {
|
|||||||
autoshorad = true,
|
autoshorad = true,
|
||||||
ShoradGroupSet = nil,
|
ShoradGroupSet = nil,
|
||||||
checkforfriendlies = false,
|
checkforfriendlies = false,
|
||||||
|
SmokeDecoy = false,
|
||||||
|
SmokeDecoyColor = SMOKECOLOR.White,
|
||||||
|
checkcounter = 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Advanced state enumerator
|
--- Advanced state enumerator
|
||||||
@@ -344,8 +352,17 @@ MANTIS.SamType = {
|
|||||||
SHORT = "Short",
|
SHORT = "Short",
|
||||||
MEDIUM = "Medium",
|
MEDIUM = "Medium",
|
||||||
LONG = "Long",
|
LONG = "Long",
|
||||||
|
POINT = "Point",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
--- SAM Radiusscale
|
||||||
|
-- @type MANTIS.radiusscale
|
||||||
|
MANTIS.radiusscale = {}
|
||||||
|
MANTIS.radiusscale[MANTIS.SamType.LONG] = 1.1
|
||||||
|
MANTIS.radiusscale[MANTIS.SamType.MEDIUM] = 1.2
|
||||||
|
MANTIS.radiusscale[MANTIS.SamType.SHORT] = 1.75
|
||||||
|
MANTIS.radiusscale[MANTIS.SamType.POINT] = 3
|
||||||
|
|
||||||
--- SAM data
|
--- SAM data
|
||||||
-- @type MANTIS.SamData
|
-- @type MANTIS.SamData
|
||||||
-- @field #number Range Max firing range in km
|
-- @field #number Range Max firing range in km
|
||||||
@@ -353,6 +370,7 @@ MANTIS.SamType = {
|
|||||||
-- @field #number Height Max firing height in km
|
-- @field #number Height Max firing height in km
|
||||||
-- @field #string Type #MANTIS.SamType of SAM, i.e. SHORT, MEDIUM or LONG (range)
|
-- @field #string Type #MANTIS.SamType of SAM, i.e. SHORT, MEDIUM or LONG (range)
|
||||||
-- @field #string Radar Radar typename on unit level (used as key)
|
-- @field #string Radar Radar typename on unit level (used as key)
|
||||||
|
-- @field #string Point Point defense capable
|
||||||
MANTIS.SamData = {
|
MANTIS.SamData = {
|
||||||
["Hawk"] = { Range=35, Blindspot=0, Height=12, Type="Medium", Radar="Hawk" }, -- measures in km
|
["Hawk"] = { Range=35, Blindspot=0, Height=12, Type="Medium", Radar="Hawk" }, -- measures in km
|
||||||
["NASAMS"] = { Range=14, Blindspot=0, Height=7, Type="Short", Radar="NSAMS" }, -- AIM 120B
|
["NASAMS"] = { Range=14, Blindspot=0, Height=7, Type="Short", Radar="NSAMS" }, -- AIM 120B
|
||||||
@@ -364,16 +382,16 @@ MANTIS.SamData = {
|
|||||||
["SA-6"] = { Range=25, Blindspot=0, Height=8, Type="Medium", Radar="1S91" },
|
["SA-6"] = { Range=25, Blindspot=0, Height=8, Type="Medium", Radar="1S91" },
|
||||||
["SA-10"] = { Range=119, Blindspot=0, Height=18, Type="Long" , Radar="S-300PS 4"},
|
["SA-10"] = { Range=119, Blindspot=0, Height=18, Type="Long" , Radar="S-300PS 4"},
|
||||||
["SA-11"] = { Range=35, Blindspot=0, Height=20, Type="Medium", Radar="SA-11" },
|
["SA-11"] = { Range=35, Blindspot=0, Height=20, Type="Medium", Radar="SA-11" },
|
||||||
["Roland"] = { Range=5, Blindspot=0, Height=5, Type="Short", Radar="Roland" },
|
["Roland"] = { Range=5, Blindspot=0, Height=5, Type="Point", Radar="Roland" },
|
||||||
["HQ-7"] = { Range=12, Blindspot=0, Height=3, Type="Short", Radar="HQ-7" },
|
["HQ-7"] = { Range=12, Blindspot=0, Height=3, Type="Short", Radar="HQ-7" },
|
||||||
["SA-9"] = { Range=4, Blindspot=0, Height=3, Type="Short", Radar="Strela" },
|
["SA-9"] = { Range=4, Blindspot=0, Height=3, Type="Point", Radar="Strela", Point="true" },
|
||||||
["SA-8"] = { Range=10, Blindspot=0, Height=5, Type="Short", Radar="Osa 9A33" },
|
["SA-8"] = { Range=10, Blindspot=0, Height=5, Type="Short", Radar="Osa 9A33" },
|
||||||
["SA-19"] = { Range=8, Blindspot=0, Height=3, Type="Short", Radar="Tunguska" },
|
["SA-19"] = { Range=8, Blindspot=0, Height=3, Type="Short", Radar="Tunguska" },
|
||||||
["SA-15"] = { Range=11, Blindspot=0, Height=6, Type="Short", Radar="Tor 9A331" },
|
["SA-15"] = { Range=11, Blindspot=0, Height=6, Type="Point", Radar="Tor 9A331", Point="true" },
|
||||||
["SA-13"] = { Range=5, Blindspot=0, Height=3, Type="Short", Radar="Strela" },
|
["SA-13"] = { Range=5, Blindspot=0, Height=3, Type="Point", Radar="Strela", Point="true" },
|
||||||
["Avenger"] = { Range=4, Blindspot=0, Height=3, Type="Short", Radar="Avenger" },
|
["Avenger"] = { Range=4, Blindspot=0, Height=3, Type="Short", Radar="Avenger" },
|
||||||
["Chaparral"] = { Range=8, Blindspot=0, Height=3, Type="Short", Radar="Chaparral" },
|
["Chaparral"] = { Range=8, Blindspot=0, Height=3, Type="Short", Radar="Chaparral" },
|
||||||
["Linebacker"] = { Range=4, Blindspot=0, Height=3, Type="Short", Radar="Linebacker" },
|
["Linebacker"] = { Range=4, Blindspot=0, Height=3, Type="Point", Radar="Linebacker", Point="true" },
|
||||||
["Silkworm"] = { Range=90, Blindspot=1, Height=0.2, Type="Long", Radar="Silkworm" },
|
["Silkworm"] = { Range=90, Blindspot=1, Height=0.2, Type="Long", Radar="Silkworm" },
|
||||||
-- units from HDS Mod, multi launcher options is tricky
|
-- units from HDS Mod, multi launcher options is tricky
|
||||||
["SA-10B"] = { Range=75, Blindspot=0, Height=18, Type="Medium" , Radar="SA-10B"},
|
["SA-10B"] = { Range=75, Blindspot=0, Height=18, Type="Medium" , Radar="SA-10B"},
|
||||||
@@ -381,7 +399,6 @@ MANTIS.SamData = {
|
|||||||
["SA-20A"] = { Range=150, Blindspot=5, Height=27, Type="Long" , Radar="S-300PMU1"},
|
["SA-20A"] = { Range=150, Blindspot=5, Height=27, Type="Long" , Radar="S-300PMU1"},
|
||||||
["SA-20B"] = { Range=200, Blindspot=4, Height=27, Type="Long" , Radar="S-300PMU2"},
|
["SA-20B"] = { Range=200, Blindspot=4, Height=27, Type="Long" , Radar="S-300PMU2"},
|
||||||
["HQ-2"] = { Range=50, Blindspot=6, Height=35, Type="Medium", Radar="HQ_2_Guideline_LN" },
|
["HQ-2"] = { Range=50, Blindspot=6, Height=35, Type="Medium", Radar="HQ_2_Guideline_LN" },
|
||||||
["SHORAD"] = { Range=3, Blindspot=0, Height=3, Type="Short", Radar="Igla" },
|
|
||||||
["TAMIR IDFA"] = { Range=20, Blindspot=0.6, Height=12.3, Type="Short", Radar="IRON_DOME_LN" },
|
["TAMIR IDFA"] = { Range=20, Blindspot=0.6, Height=12.3, Type="Short", Radar="IRON_DOME_LN" },
|
||||||
["STUNNER IDFA"] = { Range=250, Blindspot=1, Height=45, Type="Long", Radar="DAVID_SLING_LN" },
|
["STUNNER IDFA"] = { Range=250, Blindspot=1, Height=45, Type="Long", Radar="DAVID_SLING_LN" },
|
||||||
}
|
}
|
||||||
@@ -393,6 +410,7 @@ MANTIS.SamData = {
|
|||||||
-- @field #number Height Max firing height in km
|
-- @field #number Height Max firing height in km
|
||||||
-- @field #string Type #MANTIS.SamType of SAM, i.e. SHORT, MEDIUM or LONG (range)
|
-- @field #string Type #MANTIS.SamType of SAM, i.e. SHORT, MEDIUM or LONG (range)
|
||||||
-- @field #string Radar Radar typename on unit level (used as key)
|
-- @field #string Radar Radar typename on unit level (used as key)
|
||||||
|
-- @field #string Point Point defense capable
|
||||||
MANTIS.SamDataHDS = {
|
MANTIS.SamDataHDS = {
|
||||||
-- units from HDS Mod, multi launcher options is tricky
|
-- units from HDS Mod, multi launcher options is tricky
|
||||||
-- group name MUST contain HDS to ID launcher type correctly!
|
-- group name MUST contain HDS to ID launcher type correctly!
|
||||||
@@ -414,20 +432,21 @@ MANTIS.SamDataHDS = {
|
|||||||
-- @field #number Height Max firing height in km
|
-- @field #number Height Max firing height in km
|
||||||
-- @field #string Type #MANTIS.SamType of SAM, i.e. SHORT, MEDIUM or LONG (range)
|
-- @field #string Type #MANTIS.SamType of SAM, i.e. SHORT, MEDIUM or LONG (range)
|
||||||
-- @field #string Radar Radar typename on unit level (used as key)
|
-- @field #string Radar Radar typename on unit level (used as key)
|
||||||
|
-- @field #string Point Point defense capable
|
||||||
MANTIS.SamDataSMA = {
|
MANTIS.SamDataSMA = {
|
||||||
-- units from SMA Mod (Sweedish Military Assets)
|
-- units from SMA Mod (Sweedish Military Assets)
|
||||||
-- https://forum.dcs.world/topic/295202-swedish-military-assets-for-dcs-by-currenthill/
|
-- https://forum.dcs.world/topic/295202-swedish-military-assets-for-dcs-by-currenthill/
|
||||||
-- group name MUST contain SMA to ID launcher type correctly!
|
-- group name MUST contain SMA to ID launcher type correctly!
|
||||||
["RBS98M SMA"] = { Range=20, Blindspot=0, Height=8, Type="Short", Radar="RBS-98" },
|
["RBS98M SMA"] = { Range=20, Blindspot=0.2, Height=8, Type="Short", Radar="RBS-98" },
|
||||||
["RBS70 SMA"] = { Range=8, Blindspot=0, Height=5.5, Type="Short", Radar="RBS-70" },
|
["RBS70 SMA"] = { Range=8, Blindspot=0.25, Height=6, Type="Short", Radar="RBS-70" },
|
||||||
["RBS70M SMA"] = { Range=8, Blindspot=0, Height=5.5, Type="Short", Radar="BV410_RBS70" },
|
["RBS70M SMA"] = { Range=8, Blindspot=0.25, Height=6, Type="Short", Radar="BV410_RBS70" },
|
||||||
["RBS90 SMA"] = { Range=8, Blindspot=0, Height=5.5, Type="Short", Radar="RBS-90" },
|
["RBS90 SMA"] = { Range=8, Blindspot=0.25, Height=6, Type="Short", Radar="RBS-90" },
|
||||||
["RBS90M SMA"] = { Range=8, Blindspot=0, Height=5.5, Type="Short", Radar="BV410_RBS90" },
|
["RBS90M SMA"] = { Range=8, Blindspot=0.25, Height=6, Type="Short", Radar="BV410_RBS90" },
|
||||||
["RBS103A SMA"] = { Range=150, Blindspot=3, Height=24.5, Type="Long", Radar="LvS-103_Lavett103_Rb103A" },
|
["RBS103A SMA"] = { Range=160, Blindspot=1, Height=36, Type="Long", Radar="LvS-103_Lavett103_Rb103A" },
|
||||||
["RBS103B SMA"] = { Range=35, Blindspot=0, Height=36, Type="Medium", Radar="LvS-103_Lavett103_Rb103B" },
|
["RBS103B SMA"] = { Range=120, Blindspot=3, Height=24.5, Type="Long", Radar="LvS-103_Lavett103_Rb103B" },
|
||||||
["RBS103AM SMA"] = { Range=150, Blindspot=3, Height=24.5, Type="Long", Radar="LvS-103_Lavett103_HX_Rb103A" },
|
["RBS103AM SMA"] = { Range=160, Blindspot=1, Height=36, Type="Long", Radar="LvS-103_Lavett103_HX_Rb103A" },
|
||||||
["RBS103BM SMA"] = { Range=35, Blindspot=0, Height=36, Type="Medium", Radar="LvS-103_Lavett103_HX_Rb103B" },
|
["RBS103BM SMA"] = { Range=120, Blindspot=3, Height=24.5, Type="Long", Radar="LvS-103_Lavett103_HX_Rb103B" },
|
||||||
["Lvkv9040M SMA"] = { Range=4, Blindspot=0, Height=2.5, Type="Short", Radar="LvKv9040" },
|
["Lvkv9040M SMA"] = { Range=2, Blindspot=0.1, Height=1.2, Type="Point", Radar="LvKv9040",Point="true" },
|
||||||
}
|
}
|
||||||
|
|
||||||
--- SAM data CH
|
--- SAM data CH
|
||||||
@@ -437,28 +456,54 @@ MANTIS.SamDataSMA = {
|
|||||||
-- @field #number Height Max firing height in km
|
-- @field #number Height Max firing height in km
|
||||||
-- @field #string Type #MANTIS.SamType of SAM, i.e. SHORT, MEDIUM or LONG (range)
|
-- @field #string Type #MANTIS.SamType of SAM, i.e. SHORT, MEDIUM or LONG (range)
|
||||||
-- @field #string Radar Radar typename on unit level (used as key)
|
-- @field #string Radar Radar typename on unit level (used as key)
|
||||||
|
-- @field #string Point Point defense capable
|
||||||
MANTIS.SamDataCH = {
|
MANTIS.SamDataCH = {
|
||||||
-- units from CH (Military Assets by Currenthill)
|
-- units from CH (Military Assets by Currenthill)
|
||||||
-- https://www.currenthill.com/
|
-- https://www.currenthill.com/
|
||||||
-- group name MUST contain CHM to ID launcher type correctly!
|
-- group name MUST contain CHM to ID launcher type correctly!
|
||||||
["2S38 CH"] = { 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 CH"] = { Range=20, Blindspot=1.2, Height=15, Type="Short", Radar="PantsirS1" },
|
["PantsirS1 CHM"] = { Range=20, Blindspot=1.2, Height=15, Type="Short", Radar="PantsirS1" },
|
||||||
["PantsirS2 CH"] = { Range=30, Blindspot=1.2, Height=18, Type="Medium", Radar="PantsirS2" },
|
["PantsirS2 CHM"] = { Range=30, Blindspot=1.2, Height=18, Type="Medium", Radar="PantsirS2" },
|
||||||
["PGL-625 CH"] = { Range=10, Blindspot=0.5, Height=5, Type="Short", Radar="PGL_625" },
|
["PGL-625 CHM"] = { Range=10, Blindspot=1, Height=5, Type="Short", Radar="PGL_625" },
|
||||||
["HQ-17A CH"] = { Range=20, Blindspot=1.5, Height=10, Type="Short", Radar="HQ17A" },
|
["HQ-17A CHM"] = { Range=15, Blindspot=1.5, Height=10, Type="Short", Radar="HQ17A" },
|
||||||
["M903PAC2 CH"] = { Range=160, Blindspot=3, Height=24.5, Type="Long", Radar="MIM104_M903_PAC2" },
|
["M903PAC2 CHM"] = { Range=120, Blindspot=3, Height=24.5, Type="Long", Radar="MIM104_M903_PAC2" },
|
||||||
["M903PAC3 CH"] = { Range=120, Blindspot=1, Height=40, Type="Long", Radar="MIM104_M903_PAC3" },
|
["M903PAC3 CHM"] = { Range=160, Blindspot=1, Height=40, Type="Long", Radar="MIM104_M903_PAC3" },
|
||||||
["TorM2 CH"] = { Range=12, Blindspot=1, Height=10, Type="Short", Radar="TorM2" },
|
["TorM2 CHM"] = { Range=12, Blindspot=1, Height=10, Type="Short", Radar="TorM2" },
|
||||||
["TorM2K CH"] = { Range=12, Blindspot=1, Height=10, Type="Short", Radar="TorM2K" },
|
["TorM2K CHM"] = { Range=12, Blindspot=1, Height=10, Type="Short", Radar="TorM2K" },
|
||||||
["TorM2M CH"] = { Range=16, Blindspot=1, Height=10, Type="Short", Radar="TorM2M" },
|
["TorM2M CHM"] = { Range=16, Blindspot=1, Height=10, Type="Short", Radar="TorM2M" },
|
||||||
["NASAMS3-AMRAAMER CH"] = { Range=50, Blindspot=2, Height=35.7, Type="Medium", Radar="CH_NASAMS3_LN_AMRAAM_ER" },
|
["NASAMS3-AMRAAMER CHM"] = { Range=50, Blindspot=2, Height=35.7, Type="Medium", Radar="CH_NASAMS3_LN_AMRAAM_ER" },
|
||||||
["NASAMS3-AIM9X2 CH"] = { Range=20, Blindspot=0.2, Height=18, Type="Short", Radar="CH_NASAMS3_LN_AIM9X2" },
|
["NASAMS3-AIM9X2 CHM"] = { Range=20, Blindspot=0.2, Height=18, Type="Short", Radar="CH_NASAMS3_LN_AIM9X2" },
|
||||||
["C-RAM CH"] = { Range=2, Blindspot=0, Height=2, Type="Short", Radar="CH_Centurion_C_RAM" },
|
["C-RAM CHM"] = { Range=2, Blindspot=0, Height=2, Type="Point", Radar="CH_Centurion_C_RAM", Point="true" },
|
||||||
["PGZ-09 CH"] = { Range=4, Blindspot=0, Height=3, Type="Short", Radar="CH_PGZ09" },
|
["PGZ-09 CHM"] = { Range=4, Blindspot=0.5, Height=3, Type="Point", Radar="CH_PGZ09", Point="true" },
|
||||||
["S350-9M100 CH"] = { Range=15, Blindspot=1.5, Height=8, Type="Short", Radar="CH_S350_50P6_9M100" },
|
["S350-9M100 CHM"] = { Range=15, Blindspot=1, Height=8, Type="Short", Radar="CH_S350_50P6_9M100" },
|
||||||
["S350-9M96D CH"] = { Range=150, Blindspot=2.5, Height=30, Type="Long", Radar="CH_S350_50P6_9M96D" },
|
["S350-9M96D CHM"] = { Range=150, Blindspot=2.5, Height=30, Type="Long", Radar="CH_S350_50P6_9M96D" },
|
||||||
["LAV-AD CH"] = { 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 CH"] = { Range=170, Blindspot=5, Height=27, Type="Long", Radar="CH_HQ22_LN" },
|
["HQ-22 CHM"] = { Range=170, Blindspot=5, Height=27, Type="Long", Radar="CH_HQ22_LN" },
|
||||||
|
["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=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.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" },
|
||||||
}
|
}
|
||||||
|
|
||||||
-----------------------------------------------------------------------
|
-----------------------------------------------------------------------
|
||||||
@@ -519,6 +564,7 @@ do
|
|||||||
self.SAM_Table_Long = {}
|
self.SAM_Table_Long = {}
|
||||||
self.SAM_Table_Medium = {}
|
self.SAM_Table_Medium = {}
|
||||||
self.SAM_Table_Short = {}
|
self.SAM_Table_Short = {}
|
||||||
|
self.SAM_Table_PointDef = {}
|
||||||
self.dynamic = dynamic or false
|
self.dynamic = dynamic or false
|
||||||
self.checkradius = 25000
|
self.checkradius = 25000
|
||||||
self.grouping = 5000
|
self.grouping = 5000
|
||||||
@@ -547,10 +593,6 @@ do
|
|||||||
self.SuppressedGroups = {}
|
self.SuppressedGroups = {}
|
||||||
-- 0.8 additions
|
-- 0.8 additions
|
||||||
self.automode = true
|
self.automode = true
|
||||||
self.radiusscale = {}
|
|
||||||
self.radiusscale[MANTIS.SamType.LONG] = 1.1
|
|
||||||
self.radiusscale[MANTIS.SamType.MEDIUM] = 1.2
|
|
||||||
self.radiusscale[MANTIS.SamType.SHORT] = 1.3
|
|
||||||
--self.SAMCheckRanges = {}
|
--self.SAMCheckRanges = {}
|
||||||
self.usezones = false
|
self.usezones = false
|
||||||
self.AcceptZones = {}
|
self.AcceptZones = {}
|
||||||
@@ -559,6 +601,7 @@ do
|
|||||||
self.maxlongrange = 1
|
self.maxlongrange = 1
|
||||||
self.maxmidrange = 2
|
self.maxmidrange = 2
|
||||||
self.maxshortrange = 2
|
self.maxshortrange = 2
|
||||||
|
self.maxpointdefrange = 6
|
||||||
self.maxclassic = 6
|
self.maxclassic = 6
|
||||||
self.autoshorad = true
|
self.autoshorad = true
|
||||||
self.ShoradGroupSet = SET_GROUP:New() -- Core.Set#SET_GROUP
|
self.ShoradGroupSet = SET_GROUP:New() -- Core.Set#SET_GROUP
|
||||||
@@ -566,7 +609,10 @@ do
|
|||||||
|
|
||||||
self.SkateZones = nil
|
self.SkateZones = nil
|
||||||
self.SkateNumber = 3
|
self.SkateNumber = 3
|
||||||
self.shootandscoot = false
|
self.shootandscoot = false
|
||||||
|
|
||||||
|
self.SmokeDecoy = false
|
||||||
|
self.SmokeDecoyColor = SMOKECOLOR.White
|
||||||
|
|
||||||
self.UseEmOnOff = true
|
self.UseEmOnOff = true
|
||||||
if EmOnOff == false then
|
if EmOnOff == false then
|
||||||
@@ -578,6 +624,7 @@ do
|
|||||||
else
|
else
|
||||||
self.advAwacs = false
|
self.advAwacs = false
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Set the string id for output to DCS.log file.
|
-- Set the string id for output to DCS.log file.
|
||||||
self.lid=string.format("MANTIS %s | ", self.name)
|
self.lid=string.format("MANTIS %s | ", self.name)
|
||||||
@@ -637,9 +684,12 @@ do
|
|||||||
self.HQ_CC = GROUP:FindByName(self.HQ_Template_CC)
|
self.HQ_CC = GROUP:FindByName(self.HQ_Template_CC)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- counter for SAM table updates
|
||||||
|
self.checkcounter = 1
|
||||||
|
|
||||||
-- TODO Version
|
-- TODO Version
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
self.version="0.8.18"
|
self.version="0.9.27"
|
||||||
self:I(string.format("***** Starting MANTIS Version %s *****", self.version))
|
self:I(string.format("***** Starting MANTIS Version %s *****", self.version))
|
||||||
|
|
||||||
--- FSM Functions ---
|
--- FSM Functions ---
|
||||||
@@ -836,7 +886,7 @@ do
|
|||||||
self.AcceptZones = AcceptZones or {}
|
self.AcceptZones = AcceptZones or {}
|
||||||
self.RejectZones = RejectZones or {}
|
self.RejectZones = RejectZones or {}
|
||||||
self.ConflictZones = ConflictZones or {}
|
self.ConflictZones = ConflictZones or {}
|
||||||
if #AcceptZones > 0 or #RejectZones > 0 or #ConflictZones > 0 then
|
if #self.AcceptZones > 0 or #self.RejectZones > 0 or #self.ConflictZones > 0 then
|
||||||
self.usezones = true
|
self.usezones = true
|
||||||
end
|
end
|
||||||
return self
|
return self
|
||||||
@@ -875,19 +925,31 @@ do
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Function to set Short Range SAMs to spit out smoke as decoy, if an enemy plane is in range.
|
||||||
|
-- @param #MANTIS self
|
||||||
|
-- @param #boolean Onoff Set to true for on and nil/false for off.
|
||||||
|
-- @param #number Color (Optional) Color to use, defaults to `SMOKECOLOR.White`
|
||||||
|
function MANTIS:SetSmokeDecoy(Onoff,Color)
|
||||||
|
self.SmokeDecoy = Onoff
|
||||||
|
self.SmokeDecoyColor = Color or SMOKECOLOR.White
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- Function to set number of SAMs going active on a valid, detected thread
|
--- Function to set number of SAMs going active on a valid, detected thread
|
||||||
-- @param #MANTIS self
|
-- @param #MANTIS self
|
||||||
-- @param #number Short Number of short-range systems activated, defaults to 1.
|
-- @param #number Short Number of short-range systems activated, defaults to 1.
|
||||||
-- @param #number Mid Number of mid-range systems activated, defaults to 2.
|
-- @param #number Mid Number of mid-range systems activated, defaults to 2.
|
||||||
-- @param #number Long Number of long-range systems activated, defaults to 2.
|
-- @param #number Long Number of long-range systems activated, defaults to 2.
|
||||||
-- @param #number Classic (non-automode) Number of overall systems activated, defaults to 6.
|
-- @param #number Classic (non-automode) Number of overall systems activated, defaults to 6.
|
||||||
|
-- @param #number Point Number of point defense and AAA systems activated, defaults to 6.
|
||||||
-- @return #MANTIS self
|
-- @return #MANTIS self
|
||||||
function MANTIS:SetMaxActiveSAMs(Short,Mid,Long,Classic)
|
function MANTIS:SetMaxActiveSAMs(Short,Mid,Long,Classic,Point)
|
||||||
self:T(self.lid .. "SetMaxActiveSAMs")
|
self:T(self.lid .. "SetMaxActiveSAMs")
|
||||||
self.maxclassic = Classic or 6
|
self.maxclassic = Classic or 6
|
||||||
self.maxlongrange = Long or 1
|
self.maxlongrange = Long or 1
|
||||||
self.maxmidrange = Mid or 2
|
self.maxmidrange = Mid or 2
|
||||||
self.maxshortrange = Short or 2
|
self.maxshortrange = Short or 2
|
||||||
|
self.maxpointdefrange= Point or 6
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1089,6 +1151,24 @@ do
|
|||||||
end
|
end
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- [Internal] Check if any EWR or AWACS is still alive
|
||||||
|
-- @param #MANTIS self
|
||||||
|
-- @return #boolean outcome
|
||||||
|
function MANTIS:_CheckAnyEWRAlive()
|
||||||
|
self:T(self.lid .. "_CheckAnyEWRAlive")
|
||||||
|
local alive = false
|
||||||
|
if self.EWR_Group:CountAlive() > 0 then
|
||||||
|
alive = true
|
||||||
|
end
|
||||||
|
if not alive and self.AWACS_Prefix then
|
||||||
|
local awacs = GROUP:FindByName(self.AWACS_Prefix)
|
||||||
|
if awacs and awacs:IsAlive() then
|
||||||
|
alive = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return alive
|
||||||
|
end
|
||||||
|
|
||||||
--- [Internal] Function to determine state of the advanced mode
|
--- [Internal] Function to determine state of the advanced mode
|
||||||
-- @param #MANTIS self
|
-- @param #MANTIS self
|
||||||
@@ -1263,9 +1343,9 @@ do
|
|||||||
-- DEBUG
|
-- DEBUG
|
||||||
set = self:_PreFilterHeight(height)
|
set = self:_PreFilterHeight(height)
|
||||||
end
|
end
|
||||||
local friendlyset -- Core.Set#SET_GROUP
|
--self.friendlyset -- Core.Set#SET_GROUP
|
||||||
if self.checkforfriendlies == true then
|
if self.checkforfriendlies == true and self.friendlyset == nil then
|
||||||
friendlyset = SET_GROUP:New():FilterCoalitions(self.Coalition):FilterCategories({"plane","helicopter"}):FilterFunction(function(grp) if grp and grp:InAir() then return true else return false end end):FilterOnce()
|
self.friendlyset = SET_GROUP:New():FilterCoalitions(self.Coalition):FilterCategories({"plane","helicopter"}):FilterFunction(function(grp) if grp and grp:InAir() then return true else return false end end):FilterStart()
|
||||||
end
|
end
|
||||||
for _,_coord in pairs (set) do
|
for _,_coord in pairs (set) do
|
||||||
local coord = _coord -- get current coord to check
|
local coord = _coord -- get current coord to check
|
||||||
@@ -1281,20 +1361,21 @@ do
|
|||||||
zonecheck = self:_CheckCoordinateInZones(coord)
|
zonecheck = self:_CheckCoordinateInZones(coord)
|
||||||
end
|
end
|
||||||
if self.verbose and self.debug then
|
if self.verbose and self.debug then
|
||||||
local dectstring = coord:ToStringLLDMS()
|
--local dectstring = coord:ToStringLLDMS()
|
||||||
local samstring = samcoordinate:ToStringLLDMS()
|
local samstring = samcoordinate:ToStringMGRS({MGRS_Accuracy=0})
|
||||||
|
samstring = string.gsub(samstring,"%s","")
|
||||||
local inrange = "false"
|
local inrange = "false"
|
||||||
if targetdistance <= rad then
|
if targetdistance <= rad then
|
||||||
inrange = "true"
|
inrange = "true"
|
||||||
end
|
end
|
||||||
local text = string.format("Checking SAM at %s | Targetdist %d | Rad %d | Inrange %s", samstring, targetdistance, rad, inrange)
|
local text = string.format("Checking SAM at %s | Tgtdist %.1fkm | Rad %.1fkm | Inrange %s", samstring, targetdistance/1000, rad/1000, inrange)
|
||||||
local m = MESSAGE:New(text,10,"Check"):ToAllIf(self.debug)
|
local m = MESSAGE:New(text,10,"Check"):ToAllIf(self.debug)
|
||||||
self:T(self.lid..text)
|
self:T(self.lid..text)
|
||||||
end
|
end
|
||||||
-- friendlies around?
|
-- friendlies around?
|
||||||
local nofriendlies = true
|
local nofriendlies = true
|
||||||
if self.checkforfriendlies == true then
|
if self.checkforfriendlies == true then
|
||||||
local closestfriend, distance = friendlyset:GetClosestGroup(samcoordinate)
|
local closestfriend, distance = self.friendlyset:GetClosestGroup(samcoordinate)
|
||||||
if closestfriend and distance and distance < rad then
|
if closestfriend and distance and distance < rad then
|
||||||
nofriendlies = false
|
nofriendlies = false
|
||||||
end
|
end
|
||||||
@@ -1395,7 +1476,7 @@ do
|
|||||||
-- @return #string type Long, medium or short range
|
-- @return #string type Long, medium or short range
|
||||||
-- @return #number blind "blind" spot
|
-- @return #number blind "blind" spot
|
||||||
function MANTIS:_GetSAMDataFromUnits(grpname,mod,sma,chm)
|
function MANTIS:_GetSAMDataFromUnits(grpname,mod,sma,chm)
|
||||||
self:T(self.lid.."_GetSAMRangeFromUnits")
|
self:T(self.lid.."_GetSAMDataFromUnits")
|
||||||
local found = false
|
local found = false
|
||||||
local range = self.checkradius
|
local range = self.checkradius
|
||||||
local height = 3000
|
local height = 3000
|
||||||
@@ -1434,6 +1515,17 @@ do
|
|||||||
end
|
end
|
||||||
if found then break end
|
if found then break end
|
||||||
end
|
end
|
||||||
|
--- AAA or Point Defense
|
||||||
|
if not found then
|
||||||
|
local grp = GROUP:FindByName(grpname)
|
||||||
|
if (grp and grp:IsAlive() and grp:IsAAA()) or string.find(grpname,"AAA",1,true) then
|
||||||
|
range = 2000
|
||||||
|
height = 2000
|
||||||
|
blind = 50
|
||||||
|
type = MANTIS.SamType.POINT
|
||||||
|
found = true
|
||||||
|
end
|
||||||
|
end
|
||||||
if not found then
|
if not found then
|
||||||
self:E(self.lid .. string.format("*****Could not match radar data for %s! Will default to midrange values!",grpname))
|
self:E(self.lid .. string.format("*****Could not match radar data for %s! Will default to midrange values!",grpname))
|
||||||
end
|
end
|
||||||
@@ -1448,7 +1540,7 @@ do
|
|||||||
-- @return #string type Long, medium or short range
|
-- @return #string type Long, medium or short range
|
||||||
-- @return #number blind "blind" spot
|
-- @return #number blind "blind" spot
|
||||||
function MANTIS:_GetSAMRange(grpname)
|
function MANTIS:_GetSAMRange(grpname)
|
||||||
self:T(self.lid.."_GetSAMRange")
|
self:T(self.lid.."_GetSAMRange for "..tostring(grpname))
|
||||||
local range = self.checkradius
|
local range = self.checkradius
|
||||||
local height = 3000
|
local height = 3000
|
||||||
local type = MANTIS.SamType.MEDIUM
|
local type = MANTIS.SamType.MEDIUM
|
||||||
@@ -1465,9 +1557,9 @@ do
|
|||||||
elseif string.find(grpname,"CHM",1,true) then
|
elseif string.find(grpname,"CHM",1,true) then
|
||||||
CHMod = true
|
CHMod = true
|
||||||
end
|
end
|
||||||
if self.automode then
|
--if self.automode then
|
||||||
for idx,entry in pairs(self.SamData) do
|
for idx,entry in pairs(self.SamData) do
|
||||||
--self:I("ID = " .. idx)
|
self:T2("ID = " .. idx)
|
||||||
if string.find(grpname,idx,1,true) then
|
if string.find(grpname,idx,1,true) then
|
||||||
local _entry = entry -- #MANTIS.SamData
|
local _entry = entry -- #MANTIS.SamData
|
||||||
type = _entry.Type
|
type = _entry.Type
|
||||||
@@ -1475,18 +1567,32 @@ do
|
|||||||
range = _entry.Range * 1000 * radiusscale -- max firing range
|
range = _entry.Range * 1000 * radiusscale -- max firing range
|
||||||
height = _entry.Height * 1000 -- max firing height
|
height = _entry.Height * 1000 -- max firing height
|
||||||
blind = _entry.Blindspot
|
blind = _entry.Blindspot
|
||||||
--self:I("Matching Groupname = " .. grpname .. " Range= " .. range)
|
self:T("Matching Groupname = " .. grpname .. " Range= " .. range)
|
||||||
found = true
|
found = true
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
--end
|
||||||
|
--- Secondary - AAA or Point Defense
|
||||||
|
if not found then
|
||||||
|
local grp = GROUP:FindByName(grpname)
|
||||||
|
if (grp and grp:IsAlive() and grp:IsAAA()) or string.find(grpname,"AAA",1,true) then
|
||||||
|
range = 2000
|
||||||
|
height = 2000
|
||||||
|
blind = 50
|
||||||
|
type = MANTIS.SamType.POINT
|
||||||
|
found = true
|
||||||
|
end
|
||||||
end
|
end
|
||||||
-- secondary filter if not found
|
--- Tertiary filter if not found
|
||||||
if (not found and self.automode) or HDSmod or SMAMod or CHMod then
|
if (not found) or HDSmod or SMAMod or CHMod then
|
||||||
range, height, type = self:_GetSAMDataFromUnits(grpname,HDSmod,SMAMod,CHMod)
|
range, height, type = self:_GetSAMDataFromUnits(grpname,HDSmod,SMAMod,CHMod)
|
||||||
elseif not found then
|
elseif not found then
|
||||||
self:E(self.lid .. string.format("*****Could not match radar data for %s! Will default to midrange values!",grpname))
|
self:E(self.lid .. string.format("*****Could not match radar data for %s! Will default to midrange values!",grpname))
|
||||||
end
|
end
|
||||||
|
if found and string.find(grpname,"SHORAD",1,true) then
|
||||||
|
type = MANTIS.SamType.POINT -- force short on match
|
||||||
|
end
|
||||||
return range, height, type, blind
|
return range, height, type, blind
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1504,6 +1610,7 @@ do
|
|||||||
local SAM_Tbl_lg = {} -- table of long range SAM defense zones
|
local SAM_Tbl_lg = {} -- table of long range SAM defense zones
|
||||||
local SAM_Tbl_md = {} -- table of mid range SAM defense zones
|
local SAM_Tbl_md = {} -- table of mid range SAM defense zones
|
||||||
local SAM_Tbl_sh = {} -- table of short range SAM defense zones
|
local SAM_Tbl_sh = {} -- table of short range SAM defense zones
|
||||||
|
local SAM_Tbl_pt = {} -- table of point defense/AAA
|
||||||
local SEAD_Grps = {} -- table of SAM names to make evasive
|
local SEAD_Grps = {} -- table of SAM names to make evasive
|
||||||
local engagerange = self.engagerange -- firing range in % of max
|
local engagerange = self.engagerange -- firing range in % of max
|
||||||
--cycle through groups and set alarm state etc
|
--cycle through groups and set alarm state etc
|
||||||
@@ -1522,23 +1629,27 @@ do
|
|||||||
local grpname = group:GetName()
|
local grpname = group:GetName()
|
||||||
local grpcoord = group:GetCoordinate()
|
local grpcoord = group:GetCoordinate()
|
||||||
local grprange,grpheight,type,blind = self:_GetSAMRange(grpname)
|
local grprange,grpheight,type,blind = self:_GetSAMRange(grpname)
|
||||||
table.insert( SAM_Tbl, {grpname, grpcoord, grprange, grpheight, blind})
|
table.insert( SAM_Tbl, {grpname, grpcoord, grprange, grpheight, blind, type})
|
||||||
--table.insert( SEAD_Grps, grpname )
|
--table.insert( SEAD_Grps, grpname )
|
||||||
if type == MANTIS.SamType.LONG then
|
if type == MANTIS.SamType.LONG then
|
||||||
table.insert( SAM_Tbl_lg, {grpname, grpcoord, grprange, grpheight, blind})
|
table.insert( SAM_Tbl_lg, {grpname, grpcoord, grprange, grpheight, blind, type})
|
||||||
table.insert( SEAD_Grps, grpname )
|
table.insert( SEAD_Grps, grpname )
|
||||||
--self:T("SAM "..grpname.." is type LONG")
|
self:T("SAM "..grpname.." is type LONG")
|
||||||
elseif type == MANTIS.SamType.MEDIUM then
|
elseif type == MANTIS.SamType.MEDIUM then
|
||||||
table.insert( SAM_Tbl_md, {grpname, grpcoord, grprange, grpheight, blind})
|
table.insert( SAM_Tbl_md, {grpname, grpcoord, grprange, grpheight, blind, type})
|
||||||
table.insert( SEAD_Grps, grpname )
|
table.insert( SEAD_Grps, grpname )
|
||||||
--self:T("SAM "..grpname.." is type MEDIUM")
|
self:T("SAM "..grpname.." is type MEDIUM")
|
||||||
elseif type == MANTIS.SamType.SHORT then
|
elseif type == MANTIS.SamType.SHORT then
|
||||||
table.insert( SAM_Tbl_sh, {grpname, grpcoord, grprange, grpheight, blind})
|
table.insert( SAM_Tbl_sh, {grpname, grpcoord, grprange, grpheight, blind, type})
|
||||||
--self:T("SAM "..grpname.." is type SHORT")
|
table.insert( SEAD_Grps, grpname )
|
||||||
|
self:T("SAM "..grpname.." is type SHORT")
|
||||||
|
elseif type == MANTIS.SamType.POINT then
|
||||||
|
table.insert( SAM_Tbl_pt, {grpname, grpcoord, grprange, grpheight, blind, type})
|
||||||
|
self:T("SAM "..grpname.." is type POINT")
|
||||||
self.ShoradGroupSet:Add(grpname,group)
|
self.ShoradGroupSet:Add(grpname,group)
|
||||||
if not self.autoshorad then
|
if not self.autoshorad then
|
||||||
table.insert( SEAD_Grps, grpname )
|
table.insert( SEAD_Grps, grpname )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
self.SamStateTracker[grpname] = "GREEN"
|
self.SamStateTracker[grpname] = "GREEN"
|
||||||
end
|
end
|
||||||
@@ -1547,6 +1658,7 @@ do
|
|||||||
self.SAM_Table_Long = SAM_Tbl_lg
|
self.SAM_Table_Long = SAM_Tbl_lg
|
||||||
self.SAM_Table_Medium = SAM_Tbl_md
|
self.SAM_Table_Medium = SAM_Tbl_md
|
||||||
self.SAM_Table_Short = SAM_Tbl_sh
|
self.SAM_Table_Short = SAM_Tbl_sh
|
||||||
|
self.SAM_Table_PointDef = SAM_Tbl_pt
|
||||||
-- make SAMs evasive
|
-- make SAMs evasive
|
||||||
local mysead = SEAD:New( SEAD_Grps, self.Padding ) -- Functional.Sead#SEAD
|
local mysead = SEAD:New( SEAD_Grps, self.Padding ) -- Functional.Sead#SEAD
|
||||||
mysead:SetEngagementRange(engagerange)
|
mysead:SetEngagementRange(engagerange)
|
||||||
@@ -1570,7 +1682,8 @@ do
|
|||||||
local SAM_Tbl = {} -- table of SAM defense zones
|
local SAM_Tbl = {} -- table of SAM defense zones
|
||||||
local SAM_Tbl_lg = {} -- table of long range SAM defense zones
|
local SAM_Tbl_lg = {} -- table of long range SAM defense zones
|
||||||
local SAM_Tbl_md = {} -- table of mid range SAM defense zones
|
local SAM_Tbl_md = {} -- table of mid range SAM defense zones
|
||||||
local SAM_Tbl_sh = {} -- table of short range SAM defense zon
|
local SAM_Tbl_sh = {} -- table of short range SAM defense zones
|
||||||
|
local SAM_Tbl_pt = {} -- table of point defense/AAA
|
||||||
local SEAD_Grps = {} -- table of SAM names to make evasive
|
local SEAD_Grps = {} -- table of SAM names to make evasive
|
||||||
local engagerange = self.engagerange -- firing range in % of max
|
local engagerange = self.engagerange -- firing range in % of max
|
||||||
--cycle through groups and set alarm state etc
|
--cycle through groups and set alarm state etc
|
||||||
@@ -1581,17 +1694,21 @@ do
|
|||||||
local grpname = group:GetName()
|
local grpname = group:GetName()
|
||||||
local grpcoord = group:GetCoordinate()
|
local grpcoord = group:GetCoordinate()
|
||||||
local grprange, grpheight,type,blind = self:_GetSAMRange(grpname)
|
local grprange, grpheight,type,blind = self:_GetSAMRange(grpname)
|
||||||
table.insert( SAM_Tbl, {grpname, grpcoord, grprange, grpheight, blind}) -- make the table lighter, as I don't really use the zone here
|
local radaralive = group:IsSAM()
|
||||||
|
table.insert( SAM_Tbl, {grpname, grpcoord, grprange, grpheight, blind, type}) -- make the table lighter, as I don't really use the zone here
|
||||||
table.insert( SEAD_Grps, grpname )
|
table.insert( SEAD_Grps, grpname )
|
||||||
if type == MANTIS.SamType.LONG then
|
if type == MANTIS.SamType.LONG and radaralive then
|
||||||
table.insert( SAM_Tbl_lg, {grpname, grpcoord, grprange, grpheight, blind})
|
table.insert( SAM_Tbl_lg, {grpname, grpcoord, grprange, grpheight, blind, type})
|
||||||
--self:I({grpname,grprange, grpheight})
|
self:T({grpname,grprange, grpheight})
|
||||||
elseif type == MANTIS.SamType.MEDIUM then
|
elseif type == MANTIS.SamType.MEDIUM and radaralive then
|
||||||
table.insert( SAM_Tbl_md, {grpname, grpcoord, grprange, grpheight, blind})
|
table.insert( SAM_Tbl_md, {grpname, grpcoord, grprange, grpheight, blind, type})
|
||||||
--self:I({grpname,grprange, grpheight})
|
self:T({grpname,grprange, grpheight})
|
||||||
elseif type == MANTIS.SamType.SHORT then
|
elseif type == MANTIS.SamType.SHORT and radaralive then
|
||||||
table.insert( SAM_Tbl_sh, {grpname, grpcoord, grprange, grpheight, blind})
|
table.insert( SAM_Tbl_sh, {grpname, grpcoord, grprange, grpheight, blind, type})
|
||||||
-- self:I({grpname,grprange, grpheight})
|
self:T({grpname,grprange, grpheight})
|
||||||
|
elseif type == MANTIS.SamType.POINT or (not radaralive) then
|
||||||
|
table.insert( SAM_Tbl_pt, {grpname, grpcoord, grprange, grpheight, blind, type})
|
||||||
|
self:T({grpname,grprange, grpheight})
|
||||||
self.ShoradGroupSet:Add(grpname,group)
|
self.ShoradGroupSet:Add(grpname,group)
|
||||||
if self.autoshorad then
|
if self.autoshorad then
|
||||||
self.Shorad.Groupset = self.ShoradGroupSet
|
self.Shorad.Groupset = self.ShoradGroupSet
|
||||||
@@ -1603,6 +1720,7 @@ do
|
|||||||
self.SAM_Table_Long = SAM_Tbl_lg
|
self.SAM_Table_Long = SAM_Tbl_lg
|
||||||
self.SAM_Table_Medium = SAM_Tbl_md
|
self.SAM_Table_Medium = SAM_Tbl_md
|
||||||
self.SAM_Table_Short = SAM_Tbl_sh
|
self.SAM_Table_Short = SAM_Tbl_sh
|
||||||
|
self.SAM_Table_PointDef = SAM_Tbl_pt
|
||||||
-- make SAMs evasive
|
-- make SAMs evasive
|
||||||
if self.mysead ~= nil then
|
if self.mysead ~= nil then
|
||||||
local mysead = self.mysead
|
local mysead = self.mysead
|
||||||
@@ -1646,20 +1764,33 @@ do
|
|||||||
-- @param #table detset Table of COORDINATES
|
-- @param #table detset Table of COORDINATES
|
||||||
-- @param #boolean dlink Using DLINK
|
-- @param #boolean dlink Using DLINK
|
||||||
-- @param #number limit of SAM sites to go active on a contact
|
-- @param #number limit of SAM sites to go active on a contact
|
||||||
-- @return #MANTIS self
|
-- @return #number instatusred
|
||||||
|
-- @return #number instatusgreen
|
||||||
|
-- @return #number activeshorads
|
||||||
function MANTIS:_CheckLoop(samset,detset,dlink,limit)
|
function MANTIS:_CheckLoop(samset,detset,dlink,limit)
|
||||||
self:T(self.lid .. "CheckLoop " .. #detset .. " Coordinates")
|
self:T(self.lid .. "CheckLoop " .. #detset .. " Coordinates")
|
||||||
local switchedon = 0
|
local switchedon = 0
|
||||||
|
local instatusred = 0
|
||||||
|
local instatusgreen = 0
|
||||||
|
local activeshorads = 0
|
||||||
|
local SEADactive = 0
|
||||||
for _,_data in pairs (samset) do
|
for _,_data in pairs (samset) do
|
||||||
local samcoordinate = _data[2]
|
local samcoordinate = _data[2]
|
||||||
local name = _data[1]
|
local name = _data[1]
|
||||||
local radius = _data[3]
|
local radius = _data[3]
|
||||||
local height = _data[4]
|
local height = _data[4]
|
||||||
local blind = _data[5] * 1.25 + 1
|
local blind = _data[5] * 1.25 + 1
|
||||||
|
local shortsam = (_data[6] == MANTIS.SamType.SHORT) and true or false
|
||||||
|
if not shortsam then
|
||||||
|
shortsam = (_data[6] == MANTIS.SamType.POINT) and true or false
|
||||||
|
end
|
||||||
local samgroup = GROUP:FindByName(name)
|
local samgroup = GROUP:FindByName(name)
|
||||||
local IsInZone, Distance = self:_CheckObjectInZone(detset, samcoordinate, radius, height, dlink)
|
local IsInZone, Distance = self:_CheckObjectInZone(detset, samcoordinate, radius, height, dlink)
|
||||||
local suppressed = self.SuppressedGroups[name] or false
|
local suppressed = self.SuppressedGroups[name] or false
|
||||||
local activeshorad = self.Shorad.ActiveGroups[name] or false
|
local activeshorad = false
|
||||||
|
if self.Shorad and self.Shorad.ActiveGroups and self.Shorad.ActiveGroups[name] then
|
||||||
|
activeshorad = true
|
||||||
|
end
|
||||||
if IsInZone and not suppressed and not activeshorad then --check any target in zone and not currently managed by SEAD
|
if IsInZone and not suppressed and not activeshorad then --check any target in zone and not currently managed by SEAD
|
||||||
if samgroup:IsAlive() then
|
if samgroup:IsAlive() then
|
||||||
-- switch on SAM
|
-- switch on SAM
|
||||||
@@ -1672,12 +1803,23 @@ do
|
|||||||
elseif (not self.UseEmOnOff) and switchedon < limit then
|
elseif (not self.UseEmOnOff) and switchedon < limit then
|
||||||
samgroup:OptionAlarmStateRed()
|
samgroup:OptionAlarmStateRed()
|
||||||
switchedon = switchedon + 1
|
switchedon = switchedon + 1
|
||||||
switch = true
|
switch = true
|
||||||
end
|
end
|
||||||
if self.SamStateTracker[name] ~= "RED" and switch then
|
if self.SamStateTracker[name] ~= "RED" and switch then
|
||||||
self:__RedState(1,samgroup)
|
self:__RedState(1,samgroup)
|
||||||
self.SamStateTracker[name] = "RED"
|
self.SamStateTracker[name] = "RED"
|
||||||
end
|
end
|
||||||
|
-- TODO doesn't work
|
||||||
|
if shortsam == true and self.SmokeDecoy == true then
|
||||||
|
self:T("Smoking")
|
||||||
|
local units = samgroup:GetUnits() or {}
|
||||||
|
local smoke = self.SmokeDecoyColor or SMOKECOLOR.White
|
||||||
|
for _,unit in pairs(units) do
|
||||||
|
if unit and unit:IsAlive() then
|
||||||
|
unit:GetCoordinate():Smoke(smoke)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
-- link in to SHORAD if available
|
-- link in to SHORAD if available
|
||||||
-- DONE: Test integration fully
|
-- DONE: Test integration fully
|
||||||
if self.ShoradLink and (Distance < self.ShoradActDistance or Distance < blind ) then -- don't give SHORAD position away too early
|
if self.ShoradLink and (Distance < self.ShoradActDistance or Distance < blind ) then -- don't give SHORAD position away too early
|
||||||
@@ -1690,7 +1832,7 @@ do
|
|||||||
-- debug output
|
-- debug output
|
||||||
if (self.debug or self.verbose) and switch then
|
if (self.debug or self.verbose) and switch then
|
||||||
local text = string.format("SAM %s in alarm state RED!", name)
|
local text = string.format("SAM %s in alarm state RED!", name)
|
||||||
local m=MESSAGE:New(text,10,"MANTIS"):ToAllIf(self.debug)
|
--local m=MESSAGE:New(text,10,"MANTIS"):ToAllIf(self.debug
|
||||||
if self.verbose then self:I(self.lid..text) end
|
if self.verbose then self:I(self.lid..text) end
|
||||||
end
|
end
|
||||||
end --end alive
|
end --end alive
|
||||||
@@ -1708,13 +1850,27 @@ do
|
|||||||
end
|
end
|
||||||
if self.debug or self.verbose then
|
if self.debug or self.verbose then
|
||||||
local text = string.format("SAM %s in alarm state GREEN!", name)
|
local text = string.format("SAM %s in alarm state GREEN!", name)
|
||||||
local m=MESSAGE:New(text,10,"MANTIS"):ToAllIf(self.debug)
|
--local m=MESSAGE:New(text,10,"MANTIS"):ToAllIf(self.debug)
|
||||||
if self.verbose then self:I(self.lid..text) end
|
if self.verbose then self:I(self.lid..text) end
|
||||||
end
|
end
|
||||||
end --end alive
|
end --end alive
|
||||||
end --end check
|
end --end check
|
||||||
end --for for loop
|
end --for loop
|
||||||
return self
|
if self.debug or self.verbose then
|
||||||
|
for _,_status in pairs(self.SamStateTracker) do
|
||||||
|
if _status == "GREEN" then
|
||||||
|
instatusgreen=instatusgreen+1
|
||||||
|
elseif _status == "RED" then
|
||||||
|
instatusred=instatusred+1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if self.Shorad then
|
||||||
|
for _,_name in pairs(self.Shorad.ActiveGroups or {}) do
|
||||||
|
activeshorads=activeshorads+1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return instatusred, instatusgreen, activeshorads
|
||||||
end
|
end
|
||||||
|
|
||||||
--- [Internal] Check detection function
|
--- [Internal] Check detection function
|
||||||
@@ -1727,22 +1883,38 @@ do
|
|||||||
--get detected set
|
--get detected set
|
||||||
local detset = detection:GetDetectedItemCoordinates()
|
local detset = detection:GetDetectedItemCoordinates()
|
||||||
--self:T("Check:", {detset})
|
--self:T("Check:", {detset})
|
||||||
-- randomly update SAM Table
|
-- update SAM Table evey 3 runs
|
||||||
local rand = math.random(1,100)
|
if self.checkcounter%3 == 0 then
|
||||||
if rand > 65 then -- 1/3 of cases
|
|
||||||
self:_RefreshSAMTable()
|
self:_RefreshSAMTable()
|
||||||
end
|
end
|
||||||
|
self.checkcounter = self.checkcounter + 1
|
||||||
|
local instatusred = 0
|
||||||
|
local instatusgreen = 0
|
||||||
|
local activeshorads = 0
|
||||||
-- switch SAMs on/off if (n)one of the detected groups is inside their reach
|
-- switch SAMs on/off if (n)one of the detected groups is inside their reach
|
||||||
if self.automode then
|
if self.automode then
|
||||||
local samset = self.SAM_Table_Long -- table of i.1=names, i.2=coordinates, i.3=firing range, i.4=firing height
|
local samset = self.SAM_Table_Long -- table of i.1=names, i.2=coordinates, i.3=firing range, i.4=firing height
|
||||||
self:_CheckLoop(samset,detset,dlink,self.maxlongrange)
|
local instatusredl, instatusgreenl, activeshoradsl = self:_CheckLoop(samset,detset,dlink,self.maxlongrange)
|
||||||
local samset = self.SAM_Table_Medium -- table of i.1=names, i.2=coordinates, i.3=firing range, i.4=firing height
|
local samset = self.SAM_Table_Medium -- table of i.1=names, i.2=coordinates, i.3=firing range, i.4=firing height
|
||||||
self:_CheckLoop(samset,detset,dlink,self.maxmidrange)
|
local instatusredm, instatusgreenm, activeshoradsm = self:_CheckLoop(samset,detset,dlink,self.maxmidrange)
|
||||||
local samset = self.SAM_Table_Short -- table of i.1=names, i.2=coordinates, i.3=firing range, i.4=firing height
|
local samset = self.SAM_Table_Short -- table of i.1=names, i.2=coordinates, i.3=firing range, i.4=firing height
|
||||||
self:_CheckLoop(samset,detset,dlink,self.maxshortrange)
|
local instatusreds, instatusgreens, activeshoradss = self:_CheckLoop(samset,detset,dlink,self.maxshortrange)
|
||||||
|
local samset = self.SAM_Table_PointDef -- 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.maxpointdefrange)
|
||||||
else
|
else
|
||||||
local samset = self:_GetSAMTable() -- table of i.1=names, i.2=coordinates, i.3=firing range, i.4=firing height
|
local samset = self:_GetSAMTable() -- table of i.1=names, i.2=coordinates, i.3=firing range, i.4=firing height
|
||||||
self:_CheckLoop(samset,detset,dlink,self.maxclassic)
|
instatusred, instatusgreen, activeshorads = self:_CheckLoop(samset,detset,dlink,self.maxclassic)
|
||||||
|
end
|
||||||
|
if self.debug or self.verbose then
|
||||||
|
local statusreport = REPORT:New("\nMANTIS Status "..self.name)
|
||||||
|
statusreport:Add("+-----------------------------+")
|
||||||
|
statusreport:Add(string.format("+ SAM in RED State: %2d",instatusred))
|
||||||
|
statusreport:Add(string.format("+ SAM in GREEN State: %2d",instatusgreen))
|
||||||
|
if self.Shorad then
|
||||||
|
statusreport:Add(string.format("+ SHORAD active: %2d",activeshorads))
|
||||||
|
end
|
||||||
|
statusreport:Add("+-----------------------------+")
|
||||||
|
MESSAGE:New(statusreport:Text(),10):ToAll():ToLog()
|
||||||
end
|
end
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
@@ -1827,7 +1999,7 @@ do
|
|||||||
end
|
end
|
||||||
--]]
|
--]]
|
||||||
if self.autoshorad then
|
if self.autoshorad then
|
||||||
self.Shorad = SHORAD:New(self.name.."-SHORAD",self.name.."-SHORAD",self.SAM_Group,self.ShoradActDistance,self.ShoradTime,self.coalition,self.UseEmOnOff)
|
self.Shorad = SHORAD:New(self.name.."-SHORAD","SHORAD",self.SAM_Group,self.ShoradActDistance,self.ShoradTime,self.coalition,self.UseEmOnOff)
|
||||||
self.Shorad:SetDefenseLimits(80,95)
|
self.Shorad:SetDefenseLimits(80,95)
|
||||||
self.ShoradLink = true
|
self.ShoradLink = true
|
||||||
self.Shorad.Groupset=self.ShoradGroupSet
|
self.Shorad.Groupset=self.ShoradGroupSet
|
||||||
@@ -1852,12 +2024,34 @@ do
|
|||||||
if not self.state2flag then
|
if not self.state2flag then
|
||||||
self:_Check(self.Detection,self.DLink)
|
self:_Check(self.Detection,self.DLink)
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[ check Awacs
|
local EWRAlive = self:_CheckAnyEWRAlive()
|
||||||
if self.advAwacs and not self.state2flag then
|
|
||||||
self:_Check(self.AWACS_Detection,false)
|
local function FindSAMSRTR()
|
||||||
|
for i=1,1000 do
|
||||||
|
local randomsam = self.SAM_Group:GetRandom()
|
||||||
|
if randomsam and randomsam:IsAlive() then
|
||||||
|
if randomsam:IsSAM() then return randomsam end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Switch on a random SR/TR if no EWR left over
|
||||||
|
if not EWRAlive then
|
||||||
|
local randomsam = FindSAMSRTR() -- Wrapper.Group#GROUP
|
||||||
|
if randomsam and randomsam:IsAlive() then
|
||||||
|
if self.UseEmOnOff then
|
||||||
|
randomsam:EnableEmission(true)
|
||||||
|
else
|
||||||
|
randomsam:OptionAlarmStateRed()
|
||||||
|
end
|
||||||
|
local name = randomsam:GetName()
|
||||||
|
if self.SamStateTracker[name] ~= "RED" then
|
||||||
|
self:__RedState(1,randomsam)
|
||||||
|
self.SamStateTracker[name] = "RED"
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
--]]
|
|
||||||
|
|
||||||
-- relocate HQ and EWR
|
-- relocate HQ and EWR
|
||||||
if self.autorelocate then
|
if self.autorelocate then
|
||||||
@@ -1867,8 +2061,6 @@ do
|
|||||||
|
|
||||||
local halfintv = math.floor(timepassed / relointerval)
|
local halfintv = math.floor(timepassed / relointerval)
|
||||||
|
|
||||||
--self:T({timepassed=timepassed, halfintv=halfintv})
|
|
||||||
|
|
||||||
if halfintv >= 1 then
|
if halfintv >= 1 then
|
||||||
self.TimeStamp = timer.getAbsTime()
|
self.TimeStamp = timer.getAbsTime()
|
||||||
self:_Relocate()
|
self:_Relocate()
|
||||||
@@ -1997,7 +2189,7 @@ do
|
|||||||
local Shorad = self.Shorad
|
local Shorad = self.Shorad
|
||||||
local radius = self.checkradius
|
local radius = self.checkradius
|
||||||
local ontime = self.ShoradTime
|
local ontime = self.ShoradTime
|
||||||
Shorad:WakeUpShorad(Name, radius, ontime)
|
Shorad:WakeUpShorad(Name, radius, ontime, nil, true)
|
||||||
self:__ShoradActivated(1,Name, radius, ontime)
|
self:__ShoradActivated(1,Name, radius, ontime)
|
||||||
end
|
end
|
||||||
return self
|
return self
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
--- **Functional** - Create random airtraffic in your missions.
|
--- **Functional** - Create random air traffic in your missions.
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
@@ -179,8 +179,8 @@
|
|||||||
-- * Climb rate is set to a moderate value of ~1500 ft/min.
|
-- * Climb rate is set to a moderate value of ~1500 ft/min.
|
||||||
-- * The standard descent rate follows the 3:1 rule, i.e. 1000 ft decent per 3 miles of travel. Hence, angle of descent is ~3.6 degrees.
|
-- * The standard descent rate follows the 3:1 rule, i.e. 1000 ft decent per 3 miles of travel. Hence, angle of descent is ~3.6 degrees.
|
||||||
-- * A holding point is randomly selected at a distance between 5 and 10 km away from destination airport.
|
-- * A holding point is randomly selected at a distance between 5 and 10 km away from destination airport.
|
||||||
-- * The altitude of theholding point is ~1200 m AGL. Holding patterns might or might not happen with variable duration.
|
-- * The altitude of the holding point is ~1200 m AGL. Holding patterns might or might not happen with variable duration.
|
||||||
-- * If an aircraft is spawned in air, the procedure omitts taxi and take-off and starts with the climb/cruising part.
|
-- * If an aircraft is spawned in air, the procedure omits taxi and take-off and starts with the climb/cruising part.
|
||||||
-- * All values are randomized for each spawned aircraft.
|
-- * All values are randomized for each spawned aircraft.
|
||||||
--
|
--
|
||||||
-- ## Mission Editor Setup
|
-- ## Mission Editor Setup
|
||||||
@@ -196,13 +196,13 @@
|
|||||||
-- Voilà, your already done!
|
-- Voilà, your already done!
|
||||||
--
|
--
|
||||||
-- Optionally, you can set a specific livery for the aircraft or give it some weapons.
|
-- Optionally, you can set a specific livery for the aircraft or give it some weapons.
|
||||||
-- However, the aircraft will by default not engage any enemies. Think of them as beeing on a peaceful or ferry mission.
|
-- However, the aircraft will by default not engage any enemies. Think of them as being on a peaceful or ferry mission.
|
||||||
--
|
--
|
||||||
-- ## Basic Lua Script
|
-- ## Basic Lua Script
|
||||||
--
|
--
|
||||||
-- 
|
-- 
|
||||||
--
|
--
|
||||||
-- The basic Lua script for one template group consits of two simple lines as shown in the picture above.
|
-- The basic Lua script for one template group consists of two simple lines as shown in the picture above.
|
||||||
--
|
--
|
||||||
-- * **Line 2** creates a new RAT object "yak". The only required parameter for the constructor @{#RAT.New}() is the name of the group as defined in the mission editor. In this example it is "RAT_YAK".
|
-- * **Line 2** creates a new RAT object "yak". The only required parameter for the constructor @{#RAT.New}() is the name of the group as defined in the mission editor. In this example it is "RAT_YAK".
|
||||||
-- * **Line 5** trigger the command to spawn the aircraft. The (optional) parameter for the @{#RAT.Spawn}() function is the number of aircraft to be spawned of this object.
|
-- * **Line 5** trigger the command to spawn the aircraft. The (optional) parameter for the @{#RAT.Spawn}() function is the number of aircraft to be spawned of this object.
|
||||||
@@ -216,9 +216,9 @@
|
|||||||
-- ## Parking Problems
|
-- ## Parking Problems
|
||||||
--
|
--
|
||||||
-- One big issue in DCS is that not all aircraft can be spawned on every airport or airbase. In particular, bigger aircraft might not have a valid parking spot at smaller airports and
|
-- One big issue in DCS is that not all aircraft can be spawned on every airport or airbase. In particular, bigger aircraft might not have a valid parking spot at smaller airports and
|
||||||
-- airstripes. This can lead to multiple problems in DCS.
|
-- airstrips. This can lead to multiple problems in DCS.
|
||||||
--
|
--
|
||||||
-- * Landing: When an aircraft tries to land at an airport where it does not have a valid parking spot, it is immidiately despawned the moment its wheels touch the runway, i.e.
|
-- * Landing: When an aircraft tries to land at an airport where it does not have a valid parking spot, it is immediately despawned the moment its wheels touch the runway, i.e.
|
||||||
-- when a landing event is triggered. This leads to the loss of the RAT aircraft. On possible way to circumvent the this problem is to let another RAT aircraft spawn at landing
|
-- when a landing event is triggered. This leads to the loss of the RAT aircraft. On possible way to circumvent the this problem is to let another RAT aircraft spawn at landing
|
||||||
-- and not when it shuts down its engines. See the @{#RAT.RespawnAfterLanding}() function.
|
-- and not when it shuts down its engines. See the @{#RAT.RespawnAfterLanding}() function.
|
||||||
-- * Spawning: When a big aircraft is dynamically spawned on a small airbase a few things can go wrong. For example, it could be spawned at a parking spot with a shelter.
|
-- * Spawning: When a big aircraft is dynamically spawned on a small airbase a few things can go wrong. For example, it could be spawned at a parking spot with a shelter.
|
||||||
@@ -246,9 +246,9 @@
|
|||||||
-- c17:Spawn(5)
|
-- c17:Spawn(5)
|
||||||
--
|
--
|
||||||
-- This would randomly spawn five C-17s but only on airports which have big open air parking spots. Note that also only destination airports are allowed
|
-- This would randomly spawn five C-17s but only on airports which have big open air parking spots. Note that also only destination airports are allowed
|
||||||
-- which do have this type of parking spot. This should ensure that the aircraft is able to land at the destination without beeing despawned immidiately.
|
-- which do have this type of parking spot. This should ensure that the aircraft is able to land at the destination without being despawned immediately.
|
||||||
--
|
--
|
||||||
-- Also, the aircraft are spawned only on the requested parking spot types and not on any other type. If no parking spot of this type is availabe at the
|
-- Also, the aircraft are spawned only on the requested parking spot types and not on any other type. If no parking spot of this type is available at the
|
||||||
-- moment of spawning, the group is automatically spawned in air above the selected airport.
|
-- moment of spawning, the group is automatically spawned in air above the selected airport.
|
||||||
--
|
--
|
||||||
-- ## Examples
|
-- ## Examples
|
||||||
@@ -274,7 +274,7 @@
|
|||||||
--
|
--
|
||||||
-- It is also possible to make aircraft "commute" between two airports, i.e. flying from airport A to B and then back from B to A, etc.
|
-- It is also possible to make aircraft "commute" between two airports, i.e. flying from airport A to B and then back from B to A, etc.
|
||||||
-- This can be done by the @{#RAT.Commute}() function. Note that if no departure or destination airports are specified, the first departure and destination are chosen randomly.
|
-- This can be done by the @{#RAT.Commute}() function. Note that if no departure or destination airports are specified, the first departure and destination are chosen randomly.
|
||||||
-- Then the aircraft will fly back and forth between those two airports indefinetly.
|
-- Then the aircraft will fly back and forth between those two airports indefinitely.
|
||||||
--
|
--
|
||||||
--
|
--
|
||||||
-- ### Spawn in Air
|
-- ### Spawn in Air
|
||||||
@@ -302,7 +302,7 @@
|
|||||||
-- * @{#RAT.SetTakeoff}("cold"), which means that all aircraft are spawned with their engines off,
|
-- * @{#RAT.SetTakeoff}("cold"), which means that all aircraft are spawned with their engines off,
|
||||||
-- * @{#RAT.SetTakeoff}("hot"), which means that all aircraft are spawned with their engines on,
|
-- * @{#RAT.SetTakeoff}("hot"), which means that all aircraft are spawned with their engines on,
|
||||||
-- * @{#RAT.SetTakeoff}("runway"), which means that all aircraft are spawned already at the runway ready to takeoff.
|
-- * @{#RAT.SetTakeoff}("runway"), which means that all aircraft are spawned already at the runway ready to takeoff.
|
||||||
-- Note that in this case the default spawn intervall is set to 180 seconds in order to avoid aircraft jamms on the runway. Generally, this takeoff at runways should be used with care and problems are to be expected.
|
-- Note that in this case the default spawn intervall is set to 180 seconds in order to avoid aircraft jams on the runway. Generally, this takeoff at runways should be used with care and problems are to be expected.
|
||||||
--
|
--
|
||||||
--
|
--
|
||||||
-- The options @{#RAT.SetMinDistance}() and @{#RAT.SetMaxDistance}() can be used to restrict the range from departure to destination. For example
|
-- The options @{#RAT.SetMinDistance}() and @{#RAT.SetMaxDistance}() can be used to restrict the range from departure to destination. For example
|
||||||
@@ -325,7 +325,7 @@
|
|||||||
--
|
--
|
||||||
-- * @{#RAT.SetFLcruise}(300) will cause most planes fly around FL300.
|
-- * @{#RAT.SetFLcruise}(300) will cause most planes fly around FL300.
|
||||||
-- * @{#RAT.SetFLmin}(100) restricts the cruising alt such that no plane will fly below FL100. Note that this automatically changes the minimum distance from departure to destination.
|
-- * @{#RAT.SetFLmin}(100) restricts the cruising alt such that no plane will fly below FL100. Note that this automatically changes the minimum distance from departure to destination.
|
||||||
-- That means that only destinations are possible for which the aircraft has had enought time to reach that flight level and descent again.
|
-- That means that only destinations are possible for which the aircraft has had enough time to reach that flight level and descent again.
|
||||||
-- * @{#RAT.SetFLmax}(200) will restrict the cruise alt to maximum FL200, i.e. no aircraft will travel above this height.
|
-- * @{#RAT.SetFLmax}(200) will restrict the cruise alt to maximum FL200, i.e. no aircraft will travel above this height.
|
||||||
--
|
--
|
||||||
--
|
--
|
||||||
@@ -762,10 +762,10 @@ function RAT:Spawn(naircraft)
|
|||||||
-- Set the coalition table based on choice of self.coalition and self.friendly.
|
-- Set the coalition table based on choice of self.coalition and self.friendly.
|
||||||
self:_SetCoalitionTable()
|
self:_SetCoalitionTable()
|
||||||
|
|
||||||
-- Get all airports of this map beloning to friendly coalition(s).
|
-- Get all airports of this map belonging to friendly coalition(s).
|
||||||
self:_GetAirportsOfCoalition()
|
self:_GetAirportsOfCoalition()
|
||||||
|
|
||||||
-- Set submenuname if it has not been set by user.
|
-- Set sub-menu name if it has not been set by user.
|
||||||
if not self.SubMenuName then
|
if not self.SubMenuName then
|
||||||
self.SubMenuName=self.alias
|
self.SubMenuName=self.alias
|
||||||
end
|
end
|
||||||
@@ -1302,9 +1302,9 @@ end
|
|||||||
|
|
||||||
--- Set name of destination airports or zones for the AI aircraft.
|
--- Set name of destination airports or zones for the AI aircraft.
|
||||||
-- @param #RAT self
|
-- @param #RAT self
|
||||||
-- @param #string destinationnames Name of the destination airport or table of destination airports.
|
-- @param #string destinationnames Name of the destination airport or #table of destination airports.
|
||||||
-- @return #RAT RAT self object.
|
-- @return #RAT RAT self object.
|
||||||
-- @usage RAT:SetDestination("Krymsk") makes all aircraft of this RAT oject fly to Krymsk airport.
|
-- @usage RAT:SetDestination("Krymsk") makes all aircraft of this RAT object fly to Krymsk airport.
|
||||||
function RAT:SetDestination(destinationnames)
|
function RAT:SetDestination(destinationnames)
|
||||||
self:F2(destinationnames)
|
self:F2(destinationnames)
|
||||||
|
|
||||||
@@ -1564,7 +1564,7 @@ function RAT:NoRespawn()
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Number of tries to respawn an aircraft in case it has accitentally been spawned on runway.
|
--- Number of tries to respawn an aircraft in case it has accidentally been spawned on runway.
|
||||||
-- @param #RAT self
|
-- @param #RAT self
|
||||||
-- @param #number n Number of retries. Default is 3.
|
-- @param #number n Number of retries. Default is 3.
|
||||||
-- @return #RAT RAT self object.
|
-- @return #RAT RAT self object.
|
||||||
@@ -1621,7 +1621,7 @@ function RAT:RespawnInAirNotAllowed()
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Check if aircraft have accidentally been spawned on the runway. If so they will be removed immediatly.
|
--- Check if aircraft have accidentally been spawned on the runway. If so they will be removed immediately.
|
||||||
-- @param #RAT self
|
-- @param #RAT self
|
||||||
-- @param #boolean switch If true, check is performed. If false, this check is omitted.
|
-- @param #boolean switch If true, check is performed. If false, this check is omitted.
|
||||||
-- @param #number radius Distance in meters until a unit is considered to have spawned accidentally on the runway. Default is 75 m.
|
-- @param #number radius Distance in meters until a unit is considered to have spawned accidentally on the runway. Default is 75 m.
|
||||||
@@ -2135,7 +2135,12 @@ function RAT:_InitAircraft(DCSgroup)
|
|||||||
self.aircraft.length=16
|
self.aircraft.length=16
|
||||||
self.aircraft.height=5
|
self.aircraft.height=5
|
||||||
self.aircraft.width=9
|
self.aircraft.width=9
|
||||||
|
elseif DCStype == "Saab340" then -- <- These lines added
|
||||||
|
self.aircraft.length=19.73 -- <- These lines added
|
||||||
|
self.aircraft.height=6.97 -- <- These lines added
|
||||||
|
self.aircraft.width=21.44 -- <- These lines added
|
||||||
end
|
end
|
||||||
|
|
||||||
self.aircraft.box=math.max(self.aircraft.length,self.aircraft.width)
|
self.aircraft.box=math.max(self.aircraft.length,self.aircraft.width)
|
||||||
|
|
||||||
-- info message
|
-- info message
|
||||||
@@ -3809,15 +3814,20 @@ function RAT:Status(message, forID)
|
|||||||
local N0units=group:GetInitialSize()
|
local N0units=group:GetInitialSize()
|
||||||
|
|
||||||
-- Monitor travelled distance since last check.
|
-- Monitor travelled distance since last check.
|
||||||
local Pnow=coords
|
local Dtravel=0
|
||||||
local Dtravel=Pnow:Get2DDistance(ratcraft.Pnow)
|
if coords and ratcraft.Pnow then
|
||||||
ratcraft.Pnow=Pnow
|
local Dtravel=coords:Get2DDistance(ratcraft.Pnow)
|
||||||
|
ratcraft.Pnow=coords
|
||||||
|
end
|
||||||
|
|
||||||
-- Add up the travelled distance.
|
-- Add up the travelled distance.
|
||||||
ratcraft.Distance=ratcraft.Distance+Dtravel
|
ratcraft.Distance=ratcraft.Distance+Dtravel
|
||||||
|
|
||||||
-- Distance remaining to destination.
|
-- Distance remaining to destination.
|
||||||
local Ddestination=Pnow:Get2DDistance(ratcraft.destination:GetCoordinate())
|
local Ddestination=-1
|
||||||
|
if ratcraft.Pnow then
|
||||||
|
Ddestination=ratcraft.Pnow:Get2DDistance(ratcraft.destination:GetCoordinate())
|
||||||
|
end
|
||||||
|
|
||||||
-- Status report.
|
-- Status report.
|
||||||
if (forID and spawnindex==forID) or (not forID) then
|
if (forID and spawnindex==forID) or (not forID) then
|
||||||
|
|||||||
@@ -107,6 +107,9 @@
|
|||||||
-- @field Sound.SRS#MSRSQUEUE instructsrsQ SRS queue for range instructor.
|
-- @field Sound.SRS#MSRSQUEUE instructsrsQ SRS queue for range instructor.
|
||||||
-- @field #number Coalition Coalition side for the menu, if any.
|
-- @field #number Coalition Coalition side for the menu, if any.
|
||||||
-- @field Core.Menu#MENU_MISSION menuF10root Specific user defined root F10 menu.
|
-- @field Core.Menu#MENU_MISSION menuF10root Specific user defined root F10 menu.
|
||||||
|
-- @field #number ceilingaltitude Range ceiling altitude in ft MSL. Aircraft above this altitude are not considered to be in the range. Default is 20000 ft.
|
||||||
|
-- @field #boolean ceilingenabled Range has a ceiling and is not unlimited. Default is false.
|
||||||
|
|
||||||
-- @extends Core.Fsm#FSM
|
-- @extends Core.Fsm#FSM
|
||||||
|
|
||||||
--- *Don't only practice your art, but force your way into its secrets; art deserves that, for it and knowledge can raise man to the Divine.* - Ludwig van Beethoven
|
--- *Don't only practice your art, but force your way into its secrets; art deserves that, for it and knowledge can raise man to the Divine.* - Ludwig van Beethoven
|
||||||
@@ -273,6 +276,10 @@
|
|||||||
-- -- Create a range object.
|
-- -- Create a range object.
|
||||||
-- GoldwaterRange=RANGE:New("Goldwater Range")
|
-- GoldwaterRange=RANGE:New("Goldwater Range")
|
||||||
--
|
--
|
||||||
|
-- -- Set and enable the range ceiling altitude in feet MSL. If aircraft are above this altitude they are not considered to be in the range.
|
||||||
|
-- GoldwaterRange:SetRangeCeiling(20000)
|
||||||
|
-- GoldwaterRange:EnableRangeCeiling(true)
|
||||||
|
--
|
||||||
-- -- Distance between strafe target and foul line. You have to specify the names of the unit or static objects.
|
-- -- Distance between strafe target and foul line. You have to specify the names of the unit or static objects.
|
||||||
-- -- Note that this could also be done manually by simply measuring the distance between the target and the foul line in the ME.
|
-- -- Note that this could also be done manually by simply measuring the distance between the target and the foul line in the ME.
|
||||||
-- GoldwaterRange:GetFoullineDistance("GWR Strafe Pit Left 1", "GWR Foul Line Left")
|
-- GoldwaterRange:GetFoullineDistance("GWR Strafe Pit Left 1", "GWR Foul Line Left")
|
||||||
@@ -358,6 +365,8 @@ RANGE = {
|
|||||||
targetpath = nil,
|
targetpath = nil,
|
||||||
targetprefix = nil,
|
targetprefix = nil,
|
||||||
Coalition = nil,
|
Coalition = nil,
|
||||||
|
ceilingaltitude = 20000,
|
||||||
|
ceilingenabled = false,
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Default range parameters.
|
--- Default range parameters.
|
||||||
@@ -1085,6 +1094,37 @@ function RANGE:SetRangeZone( zone )
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Set range ceiling altitude in feet MSL.
|
||||||
|
-- @param #RANGE self
|
||||||
|
-- @param #number altitude (optional) Ceiling altitude of the range in ft MSL. Default 20000ft MSL
|
||||||
|
-- @return #RANGE self
|
||||||
|
function RANGE:SetRangeCeiling( altitude )
|
||||||
|
self:T(self.lid.."SetRangeCeiling")
|
||||||
|
if altitude and type(altitude) == "number" then
|
||||||
|
self.ceilingaltitude=altitude
|
||||||
|
else
|
||||||
|
self:E(self.lid.."Altitude either not provided or is not a number, using default setting (20000).")
|
||||||
|
self.ceilingaltitude=20000
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Enable range ceiling. Aircraft must be below the ceiling altitude to be considered in the range zone.
|
||||||
|
-- @param #RANGE self
|
||||||
|
-- @param #boolean enabled True if you would like to enable the ceiling check. If no value give, will Default to false.
|
||||||
|
-- @return #RANGE self
|
||||||
|
function RANGE:EnableRangeCeiling( enabled )
|
||||||
|
self:T(self.lid.."EnableRangeCeiling")
|
||||||
|
if enabled and type(enabled) == "boolean" then
|
||||||
|
self.ceilingenabled=enabled
|
||||||
|
else
|
||||||
|
self:E(self.lid.."Enabled either not provide or is not a boolean, using default setting (false).")
|
||||||
|
self.ceilingenabled=false
|
||||||
|
end
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- Set smoke color for marking bomb targets. By default bomb targets are marked by red smoke.
|
--- Set smoke color for marking bomb targets. By default bomb targets are marked by red smoke.
|
||||||
-- @param #RANGE self
|
-- @param #RANGE self
|
||||||
-- @param Utilities.Utils#SMOKECOLOR colorid Color id. Default `SMOKECOLOR.Red`.
|
-- @param Utilities.Utils#SMOKECOLOR colorid Color id. Default `SMOKECOLOR.Red`.
|
||||||
@@ -1239,10 +1279,12 @@ function RANGE:SetSRS(PathToSRS, Port, Coalition, Frequency, Modulation, Volume,
|
|||||||
self.instructmsrs:SetLabel("RANGEI")
|
self.instructmsrs:SetLabel("RANGEI")
|
||||||
self.instructmsrs:SetVolume(Volume or 1.0)
|
self.instructmsrs:SetVolume(Volume or 1.0)
|
||||||
self.instructsrsQ = MSRSQUEUE:New("INSTRUCT")
|
self.instructsrsQ = MSRSQUEUE:New("INSTRUCT")
|
||||||
|
|
||||||
if PathToGoogleKey then
|
if PathToGoogleKey then
|
||||||
self.controlmsrs:SetGoogle(PathToGoogleKey)
|
self.controlmsrs:SetProviderOptionsGoogle(PathToGoogleKey,PathToGoogleKey)
|
||||||
self.instructmsrs:SetGoogle(PathToGoogleKey)
|
self.controlmsrs:SetProvider(MSRS.Provider.GOOGLE)
|
||||||
|
self.instructmsrs:SetProviderOptionsGoogle(PathToGoogleKey,PathToGoogleKey)
|
||||||
|
self.instructmsrs:SetProvider(MSRS.Provider.GOOGLE)
|
||||||
end
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
@@ -1338,7 +1380,7 @@ end
|
|||||||
-- @return #RANGE self
|
-- @return #RANGE self
|
||||||
function RANGE:SetSoundfilesPath( path )
|
function RANGE:SetSoundfilesPath( path )
|
||||||
self.soundpath = tostring( path or "Range Soundfiles/" )
|
self.soundpath = tostring( path or "Range Soundfiles/" )
|
||||||
self:I( self.lid .. string.format( "Setting sound files path to %s", self.soundpath ) )
|
self:T2( self.lid .. string.format( "Setting sound files path to %s", self.soundpath ) )
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1634,9 +1676,9 @@ function RANGE:AddBombingTargetUnit( unit, goodhitrange, randommove )
|
|||||||
|
|
||||||
-- Debug or error output.
|
-- Debug or error output.
|
||||||
if _isstatic == true then
|
if _isstatic == true then
|
||||||
self:I( self.lid .. string.format( "Adding STATIC bombing target %s with good hit range %d. Random move = %s.", name, goodhitrange, tostring( randommove ) ) )
|
self:T( self.lid .. string.format( "Adding STATIC bombing target %s with good hit range %d. Random move = %s.", name, goodhitrange, tostring( randommove ) ) )
|
||||||
elseif _isstatic == false then
|
elseif _isstatic == false then
|
||||||
self:I( self.lid .. string.format( "Adding UNIT bombing target %s with good hit range %d. Random move = %s.", name, goodhitrange, tostring( randommove ) ) )
|
self:T( self.lid .. string.format( "Adding UNIT bombing target %s with good hit range %d. Random move = %s.", name, goodhitrange, tostring( randommove ) ) )
|
||||||
else
|
else
|
||||||
self:E( self.lid .. string.format( "ERROR! No bombing target with name %s could be found. Carefully check all UNIT and STATIC names defined in the mission editor!", name ) )
|
self:E( self.lid .. string.format( "ERROR! No bombing target with name %s could be found. Carefully check all UNIT and STATIC names defined in the mission editor!", name ) )
|
||||||
end
|
end
|
||||||
@@ -1704,7 +1746,7 @@ function RANGE:AddBombingTargetScenery( scenery, goodhitrange)
|
|||||||
|
|
||||||
-- Debug or error output.
|
-- Debug or error output.
|
||||||
if name then
|
if name then
|
||||||
self:I( self.lid .. string.format( "Adding SCENERY bombing target %s with good hit range %d", name, goodhitrange) )
|
self:T( self.lid .. string.format( "Adding SCENERY bombing target %s with good hit range %d", name, goodhitrange) )
|
||||||
else
|
else
|
||||||
self:E( self.lid .. string.format( "ERROR! No bombing target with name %s could be found!", name ) )
|
self:E( self.lid .. string.format( "ERROR! No bombing target with name %s could be found!", name ) )
|
||||||
end
|
end
|
||||||
@@ -1809,7 +1851,7 @@ function RANGE:OnEventBirth( EventData )
|
|||||||
if not EventData.IniPlayerName then return end
|
if not EventData.IniPlayerName then return end
|
||||||
|
|
||||||
local _unitName = EventData.IniUnitName
|
local _unitName = EventData.IniUnitName
|
||||||
local _unit, _playername = self:_GetPlayerUnitAndName( _unitName )
|
local _unit, _playername = self:_GetPlayerUnitAndName( _unitName, EventData.IniPlayerName )
|
||||||
|
|
||||||
self:T3( self.lid .. "BIRTH: unit = " .. tostring( EventData.IniUnitName ) )
|
self:T3( self.lid .. "BIRTH: unit = " .. tostring( EventData.IniUnitName ) )
|
||||||
self:T3( self.lid .. "BIRTH: group = " .. tostring( EventData.IniGroupName ) )
|
self:T3( self.lid .. "BIRTH: group = " .. tostring( EventData.IniGroupName ) )
|
||||||
@@ -1891,7 +1933,7 @@ function RANGE:OnEventHit( EventData )
|
|||||||
local _currentTarget = self.strafeStatus[_unitID] --#RANGE.StrafeStatus
|
local _currentTarget = self.strafeStatus[_unitID] --#RANGE.StrafeStatus
|
||||||
|
|
||||||
-- Player has rolled in on a strafing target.
|
-- Player has rolled in on a strafing target.
|
||||||
if _currentTarget and target:IsAlive() then
|
if _currentTarget and target and target:IsAlive() then
|
||||||
|
|
||||||
local playerPos = _unit:GetCoordinate()
|
local playerPos = _unit:GetCoordinate()
|
||||||
local targetPos = target:GetCoordinate()
|
local targetPos = target:GetCoordinate()
|
||||||
@@ -1965,7 +2007,9 @@ end
|
|||||||
-- @param #number attackAlt Attack altitude.
|
-- @param #number attackAlt Attack altitude.
|
||||||
-- @param #number attackVel Attack velocity.
|
-- @param #number attackVel Attack velocity.
|
||||||
function RANGE._OnImpact(weapon, self, playerData, attackHdg, attackAlt, attackVel)
|
function RANGE._OnImpact(weapon, self, playerData, attackHdg, attackAlt, attackVel)
|
||||||
|
|
||||||
|
if not playerData then return end
|
||||||
|
|
||||||
-- Get closet target to last position.
|
-- Get closet target to last position.
|
||||||
local _closetTarget = nil -- #RANGE.BombTarget
|
local _closetTarget = nil -- #RANGE.BombTarget
|
||||||
local _distance = nil
|
local _distance = nil
|
||||||
@@ -1982,13 +2026,13 @@ function RANGE._OnImpact(weapon, self, playerData, attackHdg, attackAlt, attackV
|
|||||||
-- Coordinate of impact point.
|
-- Coordinate of impact point.
|
||||||
local impactcoord = weapon:GetImpactCoordinate()
|
local impactcoord = weapon:GetImpactCoordinate()
|
||||||
|
|
||||||
-- Check if impact happened in range zone.
|
-- Check if impact happened in range zone.+
|
||||||
local insidezone = self.rangezone:IsCoordinateInZone( impactcoord )
|
local insidezone = self.rangezone:IsCoordinateInZone( impactcoord )
|
||||||
|
|
||||||
|
|
||||||
-- Smoke impact point of bomb.
|
-- Smoke impact point of bomb.
|
||||||
if playerData.smokebombimpact and insidezone then
|
if playerData and playerData.smokebombimpact and insidezone then
|
||||||
if playerData.delaysmoke then
|
if playerData and playerData.delaysmoke then
|
||||||
timer.scheduleFunction( self._DelayedSmoke, { coord = impactcoord, color = playerData.smokecolor }, timer.getTime() + self.TdelaySmoke )
|
timer.scheduleFunction( self._DelayedSmoke, { coord = impactcoord, color = playerData.smokecolor }, timer.getTime() + self.TdelaySmoke )
|
||||||
else
|
else
|
||||||
impactcoord:Smoke( playerData.smokecolor )
|
impactcoord:Smoke( playerData.smokecolor )
|
||||||
@@ -2113,7 +2157,7 @@ function RANGE:OnEventShot( EventData )
|
|||||||
local _unitName = EventData.IniUnitName
|
local _unitName = EventData.IniUnitName
|
||||||
|
|
||||||
-- Get player unit and name.
|
-- Get player unit and name.
|
||||||
local _unit, _playername = self:_GetPlayerUnitAndName( _unitName )
|
local _unit, _playername = self:_GetPlayerUnitAndName( _unitName, EventData.IniPlayerName )
|
||||||
|
|
||||||
-- Distance Player-to-Range. Set this to larger value than the threshold.
|
-- Distance Player-to-Range. Set this to larger value than the threshold.
|
||||||
local dPR = self.BombtrackThreshold * 2
|
local dPR = self.BombtrackThreshold * 2
|
||||||
@@ -2125,11 +2169,13 @@ function RANGE:OnEventShot( EventData )
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Only track if distance player to range is < 25 km. Also check that a player shot. No need to track AI weapons.
|
-- Only track if distance player to range is < 25 km. Also check that a player shot. No need to track AI weapons.
|
||||||
if _track and dPR <= self.BombtrackThreshold and _unit and _playername then
|
if _track and dPR <= self.BombtrackThreshold and _unit and _playername and self.PlayerSettings[_playername] then
|
||||||
|
|
||||||
-- Player data.
|
-- Player data.
|
||||||
local playerData = self.PlayerSettings[_playername] -- #RANGE.PlayerData
|
local playerData = self.PlayerSettings[_playername] -- #RANGE.PlayerData
|
||||||
|
|
||||||
|
if not playerData then return end
|
||||||
|
|
||||||
-- Attack parameters.
|
-- Attack parameters.
|
||||||
local attackHdg=_unit:GetHeading()
|
local attackHdg=_unit:GetHeading()
|
||||||
local attackAlt=_unit:GetHeight()
|
local attackAlt=_unit:GetHeight()
|
||||||
@@ -2190,7 +2236,7 @@ function RANGE:onafterStatus( From, Event, To )
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Check range status.
|
-- Check range status.
|
||||||
self:I( self.lid .. text )
|
self:T( self.lid .. text )
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -2391,14 +2437,14 @@ function RANGE:onafterSave( From, Event, To )
|
|||||||
if f then
|
if f then
|
||||||
f:write( data )
|
f:write( data )
|
||||||
f:close()
|
f:close()
|
||||||
self:I( self.lid .. string.format( "Saving player results to file %s", tostring( filename ) ) )
|
self:T( self.lid .. string.format( "Saving player results to file %s", tostring( filename ) ) )
|
||||||
else
|
else
|
||||||
self:E( self.lid .. string.format( "ERROR: Could not save results to file %s", tostring( filename ) ) )
|
self:E( self.lid .. string.format( "ERROR: Could not save results to file %s", tostring( filename ) ) )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Path.
|
-- Path.
|
||||||
local path = lfs.writedir() .. [[Logs\]]
|
local path = self.targetpath or lfs.writedir() .. [[Logs\]]
|
||||||
|
|
||||||
-- Set file name.
|
-- Set file name.
|
||||||
local filename = path .. string.format( "RANGE-%s_BombingResults.csv", self.rangename )
|
local filename = path .. string.format( "RANGE-%s_BombingResults.csv", self.rangename )
|
||||||
@@ -2463,14 +2509,14 @@ function RANGE:onafterLoad( From, Event, To )
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Path in DCS log file.
|
-- Path in DCS log file.
|
||||||
local path = lfs.writedir() .. [[Logs\]]
|
local path = self.targetpath or lfs.writedir() .. [[Logs\]]
|
||||||
|
|
||||||
-- Set file name.
|
-- Set file name.
|
||||||
local filename = path .. string.format( "RANGE-%s_BombingResults.csv", self.rangename )
|
local filename = path .. string.format( "RANGE-%s_BombingResults.csv", self.rangename )
|
||||||
|
|
||||||
-- Info message.
|
-- Info message.
|
||||||
local text = string.format( "Loading player bomb results from file %s", filename )
|
local text = string.format( "Loading player bomb results from file %s", filename )
|
||||||
self:I( self.lid .. text )
|
self:T( self.lid .. text )
|
||||||
|
|
||||||
-- Load asset data from file.
|
-- Load asset data from file.
|
||||||
local data = _loadfile( filename )
|
local data = _loadfile( filename )
|
||||||
@@ -2843,7 +2889,7 @@ function RANGE:_DisplayRangeInfo( _unitname )
|
|||||||
|
|
||||||
-- Check if we have a player.
|
-- Check if we have a player.
|
||||||
if unit and playername then
|
if unit and playername then
|
||||||
self:I(playername)
|
--self:I(playername)
|
||||||
-- Message text.
|
-- Message text.
|
||||||
local text = ""
|
local text = ""
|
||||||
|
|
||||||
@@ -2981,7 +3027,7 @@ function RANGE:_DisplayBombTargets( _unitname )
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
self:_DisplayMessageToGroup( _unit, _text, 120, true, true, _multiplayer )
|
self:_DisplayMessageToGroup( _unit, _text, 150, true, true, _multiplayer )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -3106,7 +3152,10 @@ function RANGE:_CheckPlayers()
|
|||||||
|
|
||||||
if unit and unit:IsAlive() then
|
if unit and unit:IsAlive() then
|
||||||
|
|
||||||
if unit:IsInZone( self.rangezone ) then
|
local unitalt = unit:GetAltitude(false)
|
||||||
|
local unitaltinfeet = UTILS.MetersToFeet(unitalt)
|
||||||
|
|
||||||
|
if unit:IsInZone(self.rangezone) and (not self.ceilingenabled or unitaltinfeet < self.ceilingaltitude) then
|
||||||
|
|
||||||
------------------------------
|
------------------------------
|
||||||
-- Player INSIDE Range Zone --
|
-- Player INSIDE Range Zone --
|
||||||
@@ -3447,10 +3496,10 @@ function RANGE:_AddF10Commands( _unitName )
|
|||||||
-- Range menu
|
-- Range menu
|
||||||
local _rangePath = MENU_GROUP:New( group, self.rangename, _rootMenu )
|
local _rangePath = MENU_GROUP:New( group, self.rangename, _rootMenu )
|
||||||
|
|
||||||
local _statsPath = MENU_GROUP:New( group, "Statistics", _rangePath )
|
|
||||||
local _markPath = MENU_GROUP:New( group, "Mark Targets", _rangePath )
|
|
||||||
local _settingsPath = MENU_GROUP:New( group, "My Settings", _rangePath )
|
|
||||||
local _infoPath = MENU_GROUP:New( group, "Range Info", _rangePath )
|
local _infoPath = MENU_GROUP:New( group, "Range Info", _rangePath )
|
||||||
|
local _markPath = MENU_GROUP:New( group, "Mark Targets", _rangePath )
|
||||||
|
local _statsPath = MENU_GROUP:New( group, "Statistics", _rangePath )
|
||||||
|
local _settingsPath = MENU_GROUP:New( group, "My Settings", _rangePath )
|
||||||
|
|
||||||
-- F10/On the Range/<Range Name>/My Settings/
|
-- F10/On the Range/<Range Name>/My Settings/
|
||||||
local _mysmokePath = MENU_GROUP:New( group, "Smoke Color", _settingsPath )
|
local _mysmokePath = MENU_GROUP:New( group, "Smoke Color", _settingsPath )
|
||||||
@@ -3854,13 +3903,13 @@ function RANGE:_TargetsheetOnOff( _unitname )
|
|||||||
|
|
||||||
-- Inform player.
|
-- Inform player.
|
||||||
if playerData and playerData.targeton == true then
|
if playerData and playerData.targeton == true then
|
||||||
text = string.format( "roger, your targetsheets are now SAVED." )
|
text = string.format( "Roger, your targetsheets are now SAVED." )
|
||||||
else
|
else
|
||||||
text = string.format( "affirm, your targetsheets are NOT SAVED." )
|
text = string.format( "Affirm, your targetsheets are NOT SAVED." )
|
||||||
end
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
text = "negative, target sheet data recorder is broken on this range."
|
text = "Negative, target sheet data recorder is broken on this range."
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Message to player.
|
-- Message to player.
|
||||||
@@ -4097,8 +4146,8 @@ end
|
|||||||
-- @return Wrapper.Unit#UNIT Unit of player.
|
-- @return Wrapper.Unit#UNIT Unit of player.
|
||||||
-- @return #string Name of the player.
|
-- @return #string Name of the player.
|
||||||
-- @return #boolean If true, group has > 1 player in it
|
-- @return #boolean If true, group has > 1 player in it
|
||||||
function RANGE:_GetPlayerUnitAndName( _unitName )
|
function RANGE:_GetPlayerUnitAndName( _unitName, PlayerName )
|
||||||
self:F2( _unitName )
|
--self:I( _unitName )
|
||||||
|
|
||||||
if _unitName ~= nil then
|
if _unitName ~= nil then
|
||||||
|
|
||||||
@@ -4107,9 +4156,9 @@ function RANGE:_GetPlayerUnitAndName( _unitName )
|
|||||||
-- Get DCS unit from its name.
|
-- Get DCS unit from its name.
|
||||||
local DCSunit = Unit.getByName( _unitName )
|
local DCSunit = Unit.getByName( _unitName )
|
||||||
|
|
||||||
if DCSunit then
|
if DCSunit and DCSunit.getPlayerName then
|
||||||
|
|
||||||
local playername = DCSunit:getPlayerName()
|
local playername = DCSunit:getPlayerName() or PlayerName or "None"
|
||||||
local unit = UNIT:Find( DCSunit )
|
local unit = UNIT:Find( DCSunit )
|
||||||
|
|
||||||
self:T2( { DCSunit = DCSunit, unit = unit, playername = playername } )
|
self:T2( { DCSunit = DCSunit, unit = unit, playername = playername } )
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
--
|
--
|
||||||
-- ### Authors: **applevangelist**, **FlightControl**
|
-- ### Authors: **applevangelist**, **FlightControl**
|
||||||
--
|
--
|
||||||
-- Last Update: Dec 2023
|
-- Last Update: Dec 2024
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
@@ -28,6 +28,16 @@
|
|||||||
|
|
||||||
---
|
---
|
||||||
-- @type SEAD
|
-- @type SEAD
|
||||||
|
-- @field #string ClassName The Class Name.
|
||||||
|
-- @field #table TargetSkill Table of target skills.
|
||||||
|
-- @field #table SEADGroupPrefixes Table of SEAD prefixes.
|
||||||
|
-- @field #table SuppressedGroups Table of currently suppressed groups.
|
||||||
|
-- @field #number EngagementRange Engagement Range.
|
||||||
|
-- @field #number Padding Padding in seconds.
|
||||||
|
-- @field #function CallBack Callback function for suppression plans.
|
||||||
|
-- @field #boolean UseCallBack Switch for callback function to be used.
|
||||||
|
-- @field #boolean debug Debug switch.
|
||||||
|
-- @field #boolen WeaponTrack Track switch, if true track weapon speed for 30 secs.
|
||||||
-- @extends Core.Base#BASE
|
-- @extends Core.Base#BASE
|
||||||
|
|
||||||
--- Make SAM sites execute evasive and defensive behaviour when being fired upon.
|
--- Make SAM sites execute evasive and defensive behaviour when being fired upon.
|
||||||
@@ -56,10 +66,11 @@ SEAD = {
|
|||||||
SEADGroupPrefixes = {},
|
SEADGroupPrefixes = {},
|
||||||
SuppressedGroups = {},
|
SuppressedGroups = {},
|
||||||
EngagementRange = 75, -- default 75% engagement range Feature Request #1355
|
EngagementRange = 75, -- default 75% engagement range Feature Request #1355
|
||||||
Padding = 10,
|
Padding = 15,
|
||||||
CallBack = nil,
|
CallBack = nil,
|
||||||
UseCallBack = false,
|
UseCallBack = false,
|
||||||
debug = false,
|
debug = false,
|
||||||
|
WeaponTrack = false,
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Missile enumerators
|
--- Missile enumerators
|
||||||
@@ -69,6 +80,7 @@ SEAD = {
|
|||||||
["AGM_122"] = "AGM_122",
|
["AGM_122"] = "AGM_122",
|
||||||
["AGM_84"] = "AGM_84",
|
["AGM_84"] = "AGM_84",
|
||||||
["AGM_45"] = "AGM_45",
|
["AGM_45"] = "AGM_45",
|
||||||
|
["AGM_65"] = "AGM_65",
|
||||||
["ALARM"] = "ALARM",
|
["ALARM"] = "ALARM",
|
||||||
["LD-10"] = "LD-10",
|
["LD-10"] = "LD-10",
|
||||||
["X_58"] = "X_58",
|
["X_58"] = "X_58",
|
||||||
@@ -88,6 +100,7 @@ SEAD = {
|
|||||||
-- km and mach
|
-- km and mach
|
||||||
["AGM_88"] = { 150, 3},
|
["AGM_88"] = { 150, 3},
|
||||||
["AGM_45"] = { 12, 2},
|
["AGM_45"] = { 12, 2},
|
||||||
|
["AGM_65"] = { 16, 0.9},
|
||||||
["AGM_122"] = { 16.5, 2.3},
|
["AGM_122"] = { 16.5, 2.3},
|
||||||
["AGM_84"] = { 280, 0.8},
|
["AGM_84"] = { 280, 0.8},
|
||||||
["ALARM"] = { 45, 2},
|
["ALARM"] = { 45, 2},
|
||||||
@@ -144,7 +157,7 @@ function SEAD:New( SEADGroupPrefixes, Padding )
|
|||||||
self:AddTransition("*", "ManageEvasion", "*")
|
self:AddTransition("*", "ManageEvasion", "*")
|
||||||
self:AddTransition("*", "CalculateHitZone", "*")
|
self:AddTransition("*", "CalculateHitZone", "*")
|
||||||
|
|
||||||
self:I("*** SEAD - Started Version 0.4.6")
|
self:I("*** SEAD - Started Version 0.4.9")
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -371,7 +384,7 @@ function SEAD:onafterManageEvasion(From,Event,To,_targetskill,_targetgroup,SEADP
|
|||||||
reach = wpndata[1] * 1.1
|
reach = wpndata[1] * 1.1
|
||||||
local mach = wpndata[2]
|
local mach = wpndata[2]
|
||||||
wpnspeed = math.floor(mach * 340.29)
|
wpnspeed = math.floor(mach * 340.29)
|
||||||
if Weapon then
|
if Weapon and Weapon:GetSpeed() > 0 then
|
||||||
wpnspeed = Weapon:GetSpeed()
|
wpnspeed = Weapon:GetSpeed()
|
||||||
self:T(string.format("*** SEAD - Weapon Speed from WEAPON: %f m/s",wpnspeed))
|
self:T(string.format("*** SEAD - Weapon Speed from WEAPON: %f m/s",wpnspeed))
|
||||||
end
|
end
|
||||||
@@ -452,29 +465,38 @@ end
|
|||||||
-- @return #SEAD self
|
-- @return #SEAD self
|
||||||
function SEAD:HandleEventShot( EventData )
|
function SEAD:HandleEventShot( EventData )
|
||||||
self:T( { EventData.id } )
|
self:T( { EventData.id } )
|
||||||
local SEADPlane = EventData.IniUnit -- Wrapper.Unit#UNIT
|
|
||||||
local SEADGroup = EventData.IniGroup -- Wrapper.Group#GROUP
|
|
||||||
local SEADPlanePos = SEADPlane:GetCoordinate() -- Core.Point#COORDINATE
|
|
||||||
local SEADUnit = EventData.IniDCSUnit
|
|
||||||
local SEADUnitName = EventData.IniDCSUnitName
|
|
||||||
local SEADWeapon = EventData.Weapon -- Identify the weapon fired
|
|
||||||
local SEADWeaponName = EventData.WeaponName -- return weapon type
|
|
||||||
|
|
||||||
local WeaponWrapper = WEAPON:New(EventData.Weapon)
|
|
||||||
--local SEADWeaponSpeed = WeaponWrapper:GetSpeed() -- mps
|
|
||||||
|
|
||||||
self:T( "*** SEAD - Missile Launched = " .. SEADWeaponName)
|
local SEADWeapon = EventData.Weapon -- Identify the weapon fired
|
||||||
--self:T({ SEADWeapon })
|
local SEADWeaponName = EventData.WeaponName or "None" -- return weapon type
|
||||||
|
|
||||||
if self:_CheckHarms(SEADWeaponName) then
|
if self:_CheckHarms(SEADWeaponName) then
|
||||||
|
--UTILS.PrintTableToLog(EventData)
|
||||||
|
local SEADPlane = EventData.IniUnit -- Wrapper.Unit#UNIT
|
||||||
|
|
||||||
|
if not SEADPlane then return self end -- case IniUnit is empty
|
||||||
|
|
||||||
|
local SEADGroup = EventData.IniGroup -- Wrapper.Group#GROUP
|
||||||
|
local SEADPlanePos = SEADPlane:GetCoordinate() -- Core.Point#COORDINATE
|
||||||
|
local SEADUnit = EventData.IniDCSUnit
|
||||||
|
local SEADUnitName = EventData.IniDCSUnitName
|
||||||
|
|
||||||
|
local WeaponWrapper = WEAPON:New(EventData.Weapon) -- Wrapper.Weapon#WEAPON
|
||||||
|
|
||||||
|
self:T( "*** SEAD - Missile Launched = " .. SEADWeaponName)
|
||||||
|
|
||||||
self:T( '*** SEAD - Weapon Match' )
|
self:T( '*** SEAD - Weapon Match' )
|
||||||
|
if self.WeaponTrack == true then
|
||||||
|
WeaponWrapper:SetFuncTrack(function(weapon) env.info(string.format("*** Weapon Speed: %d m/s",weapon:GetSpeed() or -1)) end)
|
||||||
|
WeaponWrapper:StartTrack(0.1)
|
||||||
|
WeaponWrapper:StopTrack(30)
|
||||||
|
end
|
||||||
local _targetskill = "Random"
|
local _targetskill = "Random"
|
||||||
local _targetgroupname = "none"
|
local _targetgroupname = "none"
|
||||||
local _target = EventData.Weapon:getTarget() -- Identify target
|
local _target = EventData.Weapon:getTarget() -- Identify target
|
||||||
if not _target or self.debug then -- AGM-88 or 154 w/o target data
|
if not _target or self.debug then -- AGM-88 or 154 w/o target data
|
||||||
self:E("***** SEAD - No target data for " .. (SEADWeaponName or "None"))
|
self:E("***** SEAD - No target data for " .. (SEADWeaponName or "None"))
|
||||||
if string.find(SEADWeaponName,"AGM_88",1,true) or string.find(SEADWeaponName,"AGM_154",1,true) then
|
if string.find(SEADWeaponName,"AGM_88",1,true) or string.find(SEADWeaponName,"AGM_154",1,true) then
|
||||||
self:I("**** Tracking AGM-88/154 with no target data.")
|
self:T("**** Tracking AGM-88/154 with no target data.")
|
||||||
local pos0 = SEADPlane:GetCoordinate()
|
local pos0 = SEADPlane:GetCoordinate()
|
||||||
local fheight = SEADPlane:GetHeight()
|
local fheight = SEADPlane:GetHeight()
|
||||||
self:__CalculateHitZone(20,SEADWeapon,pos0,fheight,SEADGroup,SEADWeaponName)
|
self:__CalculateHitZone(20,SEADWeapon,pos0,fheight,SEADGroup,SEADWeaponName)
|
||||||
@@ -520,7 +542,7 @@ function SEAD:HandleEventShot( EventData )
|
|||||||
end
|
end
|
||||||
if SEADGroupFound == true then -- yes we are being attacked
|
if SEADGroupFound == true then -- yes we are being attacked
|
||||||
if string.find(SEADWeaponName,"ADM_141",1,true) then
|
if string.find(SEADWeaponName,"ADM_141",1,true) then
|
||||||
self:__ManageEvasion(2,_targetskill,_targetgroup,SEADPlanePos,SEADWeaponName,SEADGroup,0,WeaponWrapper)
|
self:__ManageEvasion(2,_targetskill,_targetgroup,SEADPlanePos,SEADWeaponName,SEADGroup,2,WeaponWrapper)
|
||||||
else
|
else
|
||||||
self:ManageEvasion(_targetskill,_targetgroup,SEADPlanePos,SEADWeaponName,SEADGroup,0,WeaponWrapper)
|
self:ManageEvasion(_targetskill,_targetgroup,SEADPlanePos,SEADWeaponName,SEADGroup,0,WeaponWrapper)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
-- @image Functional.Shorad.jpg
|
-- @image Functional.Shorad.jpg
|
||||||
--
|
--
|
||||||
-- Date: Nov 2021
|
-- Date: Nov 2021
|
||||||
-- Last Update: Nov 2023
|
-- Last Update: Jan 2025
|
||||||
|
|
||||||
-------------------------------------------------------------------------
|
-------------------------------------------------------------------------
|
||||||
--- **SHORAD** class, extends Core.Base#BASE
|
--- **SHORAD** class, extends Core.Base#BASE
|
||||||
@@ -113,7 +113,7 @@ SHORAD = {
|
|||||||
SkateNumber = 3,
|
SkateNumber = 3,
|
||||||
SkateZones = nil,
|
SkateZones = nil,
|
||||||
minscootdist = 100,
|
minscootdist = 100,
|
||||||
minscootdist = 3000,
|
maxscootdist = 3000,
|
||||||
scootrandomcoord = false,
|
scootrandomcoord = false,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -443,7 +443,9 @@ do
|
|||||||
for _,_groups in pairs (shoradset) do
|
for _,_groups in pairs (shoradset) do
|
||||||
local groupname = _groups:GetName()
|
local groupname = _groups:GetName()
|
||||||
if string.find(groupname, tgtgrp, 1, true) then
|
if string.find(groupname, tgtgrp, 1, true) then
|
||||||
returnname = true
|
if _groups:IsSAM() then
|
||||||
|
returnname = true
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return returnname
|
return returnname
|
||||||
@@ -470,6 +472,7 @@ do
|
|||||||
-- @param #number Radius Radius of the #ZONE
|
-- @param #number Radius Radius of the #ZONE
|
||||||
-- @param #number ActiveTimer Number of seconds to stay active
|
-- @param #number ActiveTimer Number of seconds to stay active
|
||||||
-- @param #number TargetCat (optional) Category, i.e. Object.Category.UNIT or Object.Category.STATIC
|
-- @param #number TargetCat (optional) Category, i.e. Object.Category.UNIT or Object.Category.STATIC
|
||||||
|
-- @param #boolean ShotAt If true, function is called after a shot
|
||||||
-- @return #SHORAD self
|
-- @return #SHORAD self
|
||||||
-- @usage Use this function to integrate with other systems, example
|
-- @usage Use this function to integrate with other systems, example
|
||||||
--
|
--
|
||||||
@@ -479,7 +482,7 @@ do
|
|||||||
-- mymantis = MANTIS:New("BlueMantis","Blue SAM","Blue EWR",nil,"blue",false,"Blue Awacs")
|
-- mymantis = MANTIS:New("BlueMantis","Blue SAM","Blue EWR",nil,"blue",false,"Blue Awacs")
|
||||||
-- mymantis:AddShorad(myshorad,720)
|
-- mymantis:AddShorad(myshorad,720)
|
||||||
-- mymantis:Start()
|
-- mymantis:Start()
|
||||||
function SHORAD:onafterWakeUpShorad(From, Event, To, TargetGroup, Radius, ActiveTimer, TargetCat)
|
function SHORAD:onafterWakeUpShorad(From, Event, To, TargetGroup, Radius, ActiveTimer, TargetCat, ShotAt)
|
||||||
self:T(self.lid .. " WakeUpShorad")
|
self:T(self.lid .. " WakeUpShorad")
|
||||||
self:T({TargetGroup, Radius, ActiveTimer, TargetCat})
|
self:T({TargetGroup, Radius, ActiveTimer, TargetCat})
|
||||||
local targetcat = TargetCat or Object.Category.UNIT
|
local targetcat = TargetCat or Object.Category.UNIT
|
||||||
@@ -521,7 +524,27 @@ do
|
|||||||
-- go through set and find the one(s) to activate
|
-- go through set and find the one(s) to activate
|
||||||
local TDiff = 4
|
local TDiff = 4
|
||||||
for _,_group in pairs (shoradset) do
|
for _,_group in pairs (shoradset) do
|
||||||
if _group:IsAnyInZone(targetzone) then
|
|
||||||
|
local groupname = _group:GetName()
|
||||||
|
|
||||||
|
if groupname == TargetGroup and ShotAt==true then
|
||||||
|
-- Shot at a SHORAD group
|
||||||
|
if self.UseEmOnOff then
|
||||||
|
_group:EnableEmission(false)
|
||||||
|
end
|
||||||
|
_group:OptionAlarmStateGreen()
|
||||||
|
self.ActiveGroups[groupname] = nil
|
||||||
|
local text = string.format("Shot at SHORAD %s! Evading!", _group:GetName())
|
||||||
|
self:T(text)
|
||||||
|
local m = MESSAGE:New(text,10,"SHORAD"):ToAllIf(self.debug)
|
||||||
|
|
||||||
|
--Shoot and Scoot
|
||||||
|
if self.shootandscoot then
|
||||||
|
self:__ShootAndScoot(1,_group)
|
||||||
|
end
|
||||||
|
|
||||||
|
elseif _group:IsAnyInZone(targetzone) or groupname == TargetGroup then
|
||||||
|
-- shot at a group we protect
|
||||||
local text = string.format("Waking up SHORAD %s", _group:GetName())
|
local text = string.format("Waking up SHORAD %s", _group:GetName())
|
||||||
self:T(text)
|
self:T(text)
|
||||||
local m = MESSAGE:New(text,10,"SHORAD"):ToAllIf(self.debug)
|
local m = MESSAGE:New(text,10,"SHORAD"):ToAllIf(self.debug)
|
||||||
@@ -529,7 +552,6 @@ do
|
|||||||
_group:EnableEmission(true)
|
_group:EnableEmission(true)
|
||||||
end
|
end
|
||||||
_group:OptionAlarmStateRed()
|
_group:OptionAlarmStateRed()
|
||||||
local groupname = _group:GetName()
|
|
||||||
if self.ActiveGroups[groupname] == nil then -- no timer yet for this group
|
if self.ActiveGroups[groupname] == nil then -- no timer yet for this group
|
||||||
self.ActiveGroups[groupname] = { Timing = ActiveTimer }
|
self.ActiveGroups[groupname] = { Timing = ActiveTimer }
|
||||||
local endtime = timer.getTime() + (ActiveTimer * math.random(75,100) / 100 ) -- randomize wakeup a bit
|
local endtime = timer.getTime() + (ActiveTimer * math.random(75,100) / 100 ) -- randomize wakeup a bit
|
||||||
@@ -607,7 +629,7 @@ do
|
|||||||
_targetgroupname = tgtgrp:GetName() -- group name
|
_targetgroupname = tgtgrp:GetName() -- group name
|
||||||
_targetskill = tgtgrp:GetUnit(1):GetSkill()
|
_targetskill = tgtgrp:GetUnit(1):GetSkill()
|
||||||
self:T("*** Found Target = ".. _targetgroupname)
|
self:T("*** Found Target = ".. _targetgroupname)
|
||||||
self:WakeUpShorad(_targetgroupname, self.Radius, self.ActiveTimer, Object.Category.UNIT)
|
self:WakeUpShorad(_targetgroupname, self.Radius, self.ActiveTimer, Object.Category.UNIT,true)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -736,7 +758,7 @@ do
|
|||||||
-- if being shot at, find closest SHORADs to activate
|
-- if being shot at, find closest SHORADs to activate
|
||||||
if shotatsams or shotatus then
|
if shotatsams or shotatus then
|
||||||
self:T({shotatsams=shotatsams,shotatus=shotatus})
|
self:T({shotatsams=shotatsams,shotatus=shotatus})
|
||||||
self:WakeUpShorad(targetgroupname, self.Radius, self.ActiveTimer, targetcat)
|
self:WakeUpShorad(targetgroupname, self.Radius, self.ActiveTimer, targetcat, true)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -97,7 +97,7 @@
|
|||||||
TIRESIAS = {
|
TIRESIAS = {
|
||||||
ClassName = "TIRESIAS",
|
ClassName = "TIRESIAS",
|
||||||
debug = false,
|
debug = false,
|
||||||
version = "0.0.4",
|
version = "0.0.5",
|
||||||
Interval = 20,
|
Interval = 20,
|
||||||
GroundSet = nil,
|
GroundSet = nil,
|
||||||
VehicleSet = nil,
|
VehicleSet = nil,
|
||||||
@@ -187,7 +187,7 @@ function TIRESIAS:SetAAARanges(FiringRange,SwitchAAA)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- [USER] Add a SET_GROUP of GROUP objects as exceptions. Can be done multiple times.
|
--- [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 #TIRESIAS self
|
||||||
-- @param Core.Set#SET_GROUP Set to add to the exception list.
|
-- @param Core.Set#SET_GROUP Set to add to the exception list.
|
||||||
-- @return #TIRESIAS self
|
-- @return #TIRESIAS self
|
||||||
@@ -203,7 +203,7 @@ function TIRESIAS:AddExceptionSet(Set)
|
|||||||
}
|
}
|
||||||
exceptions:AddGroup(grp,true)
|
exceptions:AddGroup(grp,true)
|
||||||
end
|
end
|
||||||
BASE:I("TIRESIAS: Added exception group: "..grp:GetName())
|
BASE:T("TIRESIAS: Added exception group: "..grp:GetName())
|
||||||
end
|
end
|
||||||
)
|
)
|
||||||
return self
|
return self
|
||||||
@@ -288,7 +288,7 @@ function TIRESIAS:_InitGroups()
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
if grp.Tiresias and (not grp.Tiresias.exception == true) then
|
if grp.Tiresias and (not grp.Tiresias.exception == true) then
|
||||||
if grp.Tiresias.invisible and grp.Tiresias.invisible == false then
|
if grp.Tiresias.invisible == false then
|
||||||
grp:SetCommandInvisible(true)
|
grp:SetCommandInvisible(true)
|
||||||
grp.Tiresias.invisible = true
|
grp.Tiresias.invisible = true
|
||||||
if SwitchAAA then
|
if SwitchAAA then
|
||||||
@@ -315,10 +315,11 @@ function TIRESIAS:_InitGroups()
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
if grp.Tiresias and (not grp.Tiresias.exception == true) then
|
if grp.Tiresias and (not grp.Tiresias.exception == true) then
|
||||||
if grp.Tiresias and grp.Tiresias.invisible and grp.Tiresias.invisible == false then
|
if grp.Tiresias and grp.Tiresias.invisible == false then
|
||||||
grp:SetCommandInvisible(true)
|
grp:SetCommandInvisible(true)
|
||||||
grp:SetAIOff()
|
grp:SetAIOff()
|
||||||
grp.Tiresias.invisible = true
|
grp.Tiresias.invisible = true
|
||||||
|
grp.Tiresias.AIOff = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
--BASE:I(string.format("Init/Switch off Vehicle %s (Exception %s)",grp:GetName(),tostring(grp.Tiresias.exception)))
|
--BASE:I(string.format("Init/Switch off Vehicle %s (Exception %s)",grp:GetName(),tostring(grp.Tiresias.exception)))
|
||||||
@@ -336,7 +337,7 @@ function TIRESIAS:_InitGroups()
|
|||||||
}
|
}
|
||||||
end
|
end
|
||||||
if grp.Tiresias and (not grp.Tiresias.exception == true) then
|
if grp.Tiresias and (not grp.Tiresias.exception == true) then
|
||||||
if grp.Tiresias and grp.Tiresias.invisible and grp.Tiresias.invisible == false then
|
if grp.Tiresias and grp.Tiresias.invisible == false then
|
||||||
grp:SetCommandInvisible(true)
|
grp:SetCommandInvisible(true)
|
||||||
grp.Tiresias.invisible = true
|
grp.Tiresias.invisible = true
|
||||||
end
|
end
|
||||||
@@ -391,7 +392,9 @@ function TIRESIAS:_SwitchOnGroups(group,radius)
|
|||||||
if ground:CountAlive() > 0 then
|
if ground:CountAlive() > 0 then
|
||||||
ground:ForEachGroupAlive(
|
ground:ForEachGroupAlive(
|
||||||
function(grp)
|
function(grp)
|
||||||
if grp.Tiresias and grp.Tiresias.type and (not grp.Tiresias.exception == true ) then
|
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
|
if grp.Tiresias.invisible == true then
|
||||||
grp:SetCommandInvisible(false)
|
grp:SetCommandInvisible(false)
|
||||||
grp.Tiresias.invisible = false
|
grp.Tiresias.invisible = false
|
||||||
@@ -407,7 +410,7 @@ function TIRESIAS:_SwitchOnGroups(group,radius)
|
|||||||
end
|
end
|
||||||
--BASE:I(string.format("TIRESIAS - Switch on %s %s (Exception %s)",tostring(grp.Tiresias.type),grp:GetName(),tostring(grp.Tiresias.exception)))
|
--BASE:I(string.format("TIRESIAS - Switch on %s %s (Exception %s)",tostring(grp.Tiresias.type),grp:GetName(),tostring(grp.Tiresias.exception)))
|
||||||
else
|
else
|
||||||
BASE:E("TIRESIAS - This group has not been initialized or is an exception!")
|
BASE:T("TIRESIAS - This group "..tostring(name).. " has not been initialized or is an exception!")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -6047,7 +6047,7 @@ function WAREHOUSE:_SpawnAssetAircraft(alias, asset, request, parking, uncontrol
|
|||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
if #parking<#template.units and not airstart then
|
if parking and #parking<#template.units and not airstart then
|
||||||
local text=string.format("ERROR: Not enough parking! Free parking = %d < %d aircraft to be spawned.", #parking, #template.units)
|
local text=string.format("ERROR: Not enough parking! Free parking = %d < %d aircraft to be spawned.", #parking, #template.units)
|
||||||
self:_DebugMessage(text)
|
self:_DebugMessage(text)
|
||||||
return nil
|
return nil
|
||||||
@@ -6089,7 +6089,7 @@ function WAREHOUSE:_SpawnAssetAircraft(alias, asset, request, parking, uncontrol
|
|||||||
terminal=parking[i].TerminalID
|
terminal=parking[i].TerminalID
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.Debug then
|
if self.Debug and terminal then
|
||||||
local text=string.format("Spawnplace unit %s terminal %d.", unit.name, terminal)
|
local text=string.format("Spawnplace unit %s terminal %d.", unit.name, terminal)
|
||||||
coord:MarkToAll(text)
|
coord:MarkToAll(text)
|
||||||
env.info(text)
|
env.info(text)
|
||||||
@@ -6732,7 +6732,7 @@ end
|
|||||||
-- @param Wrapper.Group#GROUP deadgroup Group of unit that died.
|
-- @param Wrapper.Group#GROUP deadgroup Group of unit that died.
|
||||||
-- @param #WAREHOUSE.Pendingitem request Request that needs to be updated.
|
-- @param #WAREHOUSE.Pendingitem request Request that needs to be updated.
|
||||||
function WAREHOUSE:_UnitDead(deadunit, deadgroup, request)
|
function WAREHOUSE:_UnitDead(deadunit, deadgroup, request)
|
||||||
self:F(self.lid.."FF unit dead "..deadunit:GetName())
|
--self:F(self.lid.."FF unit dead "..deadunit:GetName())
|
||||||
|
|
||||||
-- Find opsgroup.
|
-- Find opsgroup.
|
||||||
local opsgroup=_DATABASE:FindOpsGroup(deadgroup)
|
local opsgroup=_DATABASE:FindOpsGroup(deadgroup)
|
||||||
@@ -8122,9 +8122,11 @@ function WAREHOUSE:_FindParkingForAssets(airbase, assets)
|
|||||||
-- Debug output for occupied spots.
|
-- Debug output for occupied spots.
|
||||||
if self.Debug then
|
if self.Debug then
|
||||||
local coord=problem.coord --Core.Point#COORDINATE
|
local coord=problem.coord --Core.Point#COORDINATE
|
||||||
local text=string.format("Obstacle %s [type=%s] blocking spot=%d! Size=%.1f m and distance=%.1f m.", problem.name, problem.type, _termid, problem.size, problem.dist)
|
if coord then
|
||||||
self:I(self.lid..text)
|
local text=string.format("Obstacle %s [type=%s] blocking spot=%d! Size=%.1f m and distance=%.1f m.", problem.name, problem.type, _termid, problem.size, problem.dist)
|
||||||
coord:MarkToAll(string.format(text))
|
self:I(self.lid..text)
|
||||||
|
coord:MarkToAll(text)
|
||||||
|
end
|
||||||
else
|
else
|
||||||
self:T(self.lid..string.format("Parking spot %d is occupied or not big enough!", _termid))
|
self:T(self.lid..string.format("Parking spot %d is occupied or not big enough!", _termid))
|
||||||
end
|
end
|
||||||
@@ -8433,12 +8435,14 @@ function WAREHOUSE:_GetAttribute(group)
|
|||||||
local attribute=WAREHOUSE.Attribute.OTHER_UNKNOWN --#WAREHOUSE.Attribute
|
local attribute=WAREHOUSE.Attribute.OTHER_UNKNOWN --#WAREHOUSE.Attribute
|
||||||
|
|
||||||
if group then
|
if group then
|
||||||
|
|
||||||
|
local groupCat=group:GetCategory()
|
||||||
|
|
||||||
-----------
|
-----------
|
||||||
--- Air ---
|
--- Air ---
|
||||||
-----------
|
-----------
|
||||||
-- Planes
|
-- Planes
|
||||||
local transportplane=group:HasAttribute("Transports") and group:HasAttribute("Planes")
|
local transportplane=group:HasAttribute("Transports") and group:HasAttribute("Planes") and groupCat==Group.Category.AIRPLANE
|
||||||
local awacs=group:HasAttribute("AWACS")
|
local awacs=group:HasAttribute("AWACS")
|
||||||
local fighter=group:HasAttribute("Fighters") or group:HasAttribute("Interceptors") or group:HasAttribute("Multirole fighters") or (group:HasAttribute("Bombers") and not group:HasAttribute("Strategic bombers"))
|
local fighter=group:HasAttribute("Fighters") or group:HasAttribute("Interceptors") or group:HasAttribute("Multirole fighters") or (group:HasAttribute("Bombers") and not group:HasAttribute("Strategic bombers"))
|
||||||
local bomber=group:HasAttribute("Strategic bombers")
|
local bomber=group:HasAttribute("Strategic bombers")
|
||||||
@@ -8593,7 +8597,6 @@ end
|
|||||||
-- @param #WAREHOUSE.Queueitem qitem Item of queue to be removed.
|
-- @param #WAREHOUSE.Queueitem qitem Item of queue to be removed.
|
||||||
-- @param #table queue The queue from which the item should be deleted.
|
-- @param #table queue The queue from which the item should be deleted.
|
||||||
function WAREHOUSE:_DeleteQueueItem(qitem, queue)
|
function WAREHOUSE:_DeleteQueueItem(qitem, queue)
|
||||||
self:F({qitem=qitem, queue=queue})
|
|
||||||
|
|
||||||
for i=1,#queue do
|
for i=1,#queue do
|
||||||
local _item=queue[i] --#WAREHOUSE.Queueitem
|
local _item=queue[i] --#WAREHOUSE.Queueitem
|
||||||
|
|||||||
@@ -48,7 +48,7 @@
|
|||||||
|
|
||||||
do -- ZONE_CAPTURE_COALITION
|
do -- ZONE_CAPTURE_COALITION
|
||||||
|
|
||||||
--- @type ZONE_CAPTURE_COALITION
|
-- @type ZONE_CAPTURE_COALITION
|
||||||
-- @field #string ClassName Name of the class.
|
-- @field #string ClassName Name of the class.
|
||||||
-- @field #number MarkBlue ID of blue F10 mark.
|
-- @field #number MarkBlue ID of blue F10 mark.
|
||||||
-- @field #number MarkRed ID of red F10 mark.
|
-- @field #number MarkRed ID of red F10 mark.
|
||||||
@@ -161,7 +161,7 @@ do -- ZONE_CAPTURE_COALITION
|
|||||||
-- The mission designer can use these values to alter the logic.
|
-- The mission designer can use these values to alter the logic.
|
||||||
-- For example:
|
-- For example:
|
||||||
--
|
--
|
||||||
-- --- @param Functional.ZoneCaptureCoalition#ZONE_CAPTURE_COALITION self
|
-- -- @param Functional.ZoneCaptureCoalition#ZONE_CAPTURE_COALITION self
|
||||||
-- function ZoneCaptureCoalition:OnEnterGuarded( From, Event, To )
|
-- function ZoneCaptureCoalition:OnEnterGuarded( From, Event, To )
|
||||||
-- if From ~= "Empty" then
|
-- if From ~= "Empty" then
|
||||||
-- -- Display a message
|
-- -- Display a message
|
||||||
@@ -172,7 +172,7 @@ do -- ZONE_CAPTURE_COALITION
|
|||||||
--
|
--
|
||||||
-- ## Example Event Handler.
|
-- ## Example Event Handler.
|
||||||
--
|
--
|
||||||
-- --- @param Functional.ZoneCaptureCoalition#ZONE_CAPTURE_COALITION self
|
-- -- @param Functional.ZoneCaptureCoalition#ZONE_CAPTURE_COALITION self
|
||||||
-- function ZoneCaptureCoalition:OnEnterGuarded( From, Event, To )
|
-- function ZoneCaptureCoalition:OnEnterGuarded( From, Event, To )
|
||||||
-- if From ~= To then
|
-- if From ~= To then
|
||||||
-- local Coalition = self:GetCoalition()
|
-- local Coalition = self:GetCoalition()
|
||||||
@@ -273,7 +273,7 @@ do -- ZONE_CAPTURE_COALITION
|
|||||||
-- Depending on the zone ownership, different messages are sent.
|
-- Depending on the zone ownership, different messages are sent.
|
||||||
-- Note the methods `ZoneCaptureCoalition:GetZoneName()`.
|
-- Note the methods `ZoneCaptureCoalition:GetZoneName()`.
|
||||||
--
|
--
|
||||||
-- --- @param Functional.ZoneCaptureCoalition#ZONE_CAPTURE_COALITION self
|
-- -- @param Functional.ZoneCaptureCoalition#ZONE_CAPTURE_COALITION self
|
||||||
-- function ZoneCaptureCoalition:OnEnterGuarded( From, Event, To )
|
-- function ZoneCaptureCoalition:OnEnterGuarded( From, Event, To )
|
||||||
-- if From ~= To then
|
-- if From ~= To then
|
||||||
-- local Coalition = self:GetCoalition()
|
-- local Coalition = self:GetCoalition()
|
||||||
@@ -294,7 +294,7 @@ do -- ZONE_CAPTURE_COALITION
|
|||||||
-- Next is the Event Handler when the **Empty** state transition is triggered.
|
-- Next is the Event Handler when the **Empty** state transition is triggered.
|
||||||
-- Now we smoke the ZoneCaptureCoalition with a green color, using `self:Smoke( SMOKECOLOR.Green )`.
|
-- Now we smoke the ZoneCaptureCoalition with a green color, using `self:Smoke( SMOKECOLOR.Green )`.
|
||||||
--
|
--
|
||||||
-- --- @param Functional.Protect#ZONE_CAPTURE_COALITION self
|
-- -- @param Functional.Protect#ZONE_CAPTURE_COALITION self
|
||||||
-- function ZoneCaptureCoalition:OnEnterEmpty()
|
-- function ZoneCaptureCoalition:OnEnterEmpty()
|
||||||
-- self:Smoke( SMOKECOLOR.Green )
|
-- self:Smoke( SMOKECOLOR.Green )
|
||||||
-- US_CC:MessageTypeToCoalition( string.format( "%s is unprotected, and can be captured!", ZoneCaptureCoalition:GetZoneName() ), MESSAGE.Type.Information )
|
-- US_CC:MessageTypeToCoalition( string.format( "%s is unprotected, and can be captured!", ZoneCaptureCoalition:GetZoneName() ), MESSAGE.Type.Information )
|
||||||
@@ -304,7 +304,7 @@ do -- ZONE_CAPTURE_COALITION
|
|||||||
-- The next Event Handlers speak for itself.
|
-- The next Event Handlers speak for itself.
|
||||||
-- When the zone is Attacked, we smoke the zone white and send some messages to each coalition.
|
-- When the zone is Attacked, we smoke the zone white and send some messages to each coalition.
|
||||||
--
|
--
|
||||||
-- --- @param Functional.Protect#ZONE_CAPTURE_COALITION self
|
-- -- @param Functional.Protect#ZONE_CAPTURE_COALITION self
|
||||||
-- function ZoneCaptureCoalition:OnEnterAttacked()
|
-- function ZoneCaptureCoalition:OnEnterAttacked()
|
||||||
-- ZoneCaptureCoalition:Smoke( SMOKECOLOR.White )
|
-- ZoneCaptureCoalition:Smoke( SMOKECOLOR.White )
|
||||||
-- local Coalition = self:GetCoalition()
|
-- local Coalition = self:GetCoalition()
|
||||||
@@ -321,7 +321,7 @@ do -- ZONE_CAPTURE_COALITION
|
|||||||
-- When the zone is Captured, we send some victory or loss messages to the correct coalition.
|
-- When the zone is Captured, we send some victory or loss messages to the correct coalition.
|
||||||
-- And we add some score.
|
-- And we add some score.
|
||||||
--
|
--
|
||||||
-- --- @param Functional.Protect#ZONE_CAPTURE_COALITION self
|
-- -- @param Functional.Protect#ZONE_CAPTURE_COALITION self
|
||||||
-- function ZoneCaptureCoalition:OnEnterCaptured()
|
-- function ZoneCaptureCoalition:OnEnterCaptured()
|
||||||
-- local Coalition = self:GetCoalition()
|
-- local Coalition = self:GetCoalition()
|
||||||
-- self:E({Coalition = Coalition})
|
-- self:E({Coalition = Coalition})
|
||||||
@@ -641,7 +641,7 @@ do -- ZONE_CAPTURE_COALITION
|
|||||||
--
|
--
|
||||||
-- @usage
|
-- @usage
|
||||||
-- -- For example, one could stop the monitoring when the zone was captured!
|
-- -- For example, one could stop the monitoring when the zone was captured!
|
||||||
-- --- @param Functional.Protect#ZONE_CAPTURE_COALITION self
|
-- -- @param Functional.Protect#ZONE_CAPTURE_COALITION self
|
||||||
-- function ZoneCaptureCoalition:OnEnterCaptured()
|
-- function ZoneCaptureCoalition:OnEnterCaptured()
|
||||||
-- local Coalition = self:GetCoalition()
|
-- local Coalition = self:GetCoalition()
|
||||||
-- self:E({Coalition = Coalition})
|
-- self:E({Coalition = Coalition})
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
do -- Zone
|
do -- Zone
|
||||||
|
|
||||||
--- @type ZONE_GOAL
|
-- @type ZONE_GOAL
|
||||||
-- @field #string ClassName Name of the class.
|
-- @field #string ClassName Name of the class.
|
||||||
-- @field Core.Goal#GOAL Goal The goal object.
|
-- @field Core.Goal#GOAL Goal The goal object.
|
||||||
-- @field #number SmokeTime Time stamp in seconds when the last smoke of the zone was triggered.
|
-- @field #number SmokeTime Time stamp in seconds when the last smoke of the zone was triggered.
|
||||||
@@ -178,7 +178,7 @@ do -- Zone
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #ZONE_GOAL self
|
-- @param #ZONE_GOAL self
|
||||||
-- @param Core.Event#EVENTDATA EventData Event data table.
|
-- @param Core.Event#EVENTDATA EventData Event data table.
|
||||||
function ZONE_GOAL:__Destroyed( EventData )
|
function ZONE_GOAL:__Destroyed( EventData )
|
||||||
self:F( { "EventDead", EventData } )
|
self:F( { "EventDead", EventData } )
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
do -- ZoneGoal
|
do -- ZoneGoal
|
||||||
|
|
||||||
--- @type ZONE_GOAL_CARGO
|
-- @type ZONE_GOAL_CARGO
|
||||||
-- @extends Functional.ZoneGoal#ZONE_GOAL
|
-- @extends Functional.ZoneGoal#ZONE_GOAL
|
||||||
|
|
||||||
|
|
||||||
@@ -55,7 +55,7 @@ do -- ZoneGoal
|
|||||||
ClassName = "ZONE_GOAL_CARGO",
|
ClassName = "ZONE_GOAL_CARGO",
|
||||||
}
|
}
|
||||||
|
|
||||||
--- @field #table ZONE_GOAL_CARGO.States
|
-- @field #table ZONE_GOAL_CARGO.States
|
||||||
ZONE_GOAL_CARGO.States = {}
|
ZONE_GOAL_CARGO.States = {}
|
||||||
|
|
||||||
--- ZONE_GOAL_CARGO Constructor.
|
--- ZONE_GOAL_CARGO Constructor.
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
do -- ZoneGoal
|
do -- ZoneGoal
|
||||||
|
|
||||||
--- @type ZONE_GOAL_COALITION
|
-- @type ZONE_GOAL_COALITION
|
||||||
-- @field #string ClassName Name of the Class.
|
-- @field #string ClassName Name of the Class.
|
||||||
-- @field #number Coalition The current coalition ID of the zone owner.
|
-- @field #number Coalition The current coalition ID of the zone owner.
|
||||||
-- @field #number PreviousCoalition The previous owner of the zone.
|
-- @field #number PreviousCoalition The previous owner of the zone.
|
||||||
@@ -48,7 +48,7 @@ do -- ZoneGoal
|
|||||||
ObjectCategories = nil,
|
ObjectCategories = nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
--- @field #table ZONE_GOAL_COALITION.States
|
-- @field #table ZONE_GOAL_COALITION.States
|
||||||
ZONE_GOAL_COALITION.States = {}
|
ZONE_GOAL_COALITION.States = {}
|
||||||
|
|
||||||
--- ZONE_GOAL_COALITION Constructor.
|
--- ZONE_GOAL_COALITION Constructor.
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ _SCHEDULEDISPATCHER = SCHEDULEDISPATCHER:New() -- Core.ScheduleDispatcher#SCHEDU
|
|||||||
_DATABASE = DATABASE:New() -- Core.Database#DATABASE
|
_DATABASE = DATABASE:New() -- Core.Database#DATABASE
|
||||||
|
|
||||||
--- Settings
|
--- Settings
|
||||||
_SETTINGS = SETTINGS:Set()
|
_SETTINGS = SETTINGS:Set() -- Core.Settings#SETTINGS
|
||||||
_SETTINGS:SetPlayerMenuOn()
|
_SETTINGS:SetPlayerMenuOn()
|
||||||
|
|
||||||
--- Register cargos.
|
--- Register cargos.
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Utilities/Enums.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Utilities/Enums.lua' )
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Utilities/Utils.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Utilities/Utils.lua' )
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Utilities/Profiler.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Utilities/Profiler.lua' )
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Utilities/Templates.lua' )
|
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Utilities/STTS.lua' )
|
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Utilities/FiFo.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Utilities/FiFo.lua' )
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Utilities/Socket.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Utilities/Socket.lua' )
|
||||||
|
|
||||||
@@ -49,6 +47,7 @@ __Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Wrapper/Marker.lua' )
|
|||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Wrapper/Weapon.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Wrapper/Weapon.lua' )
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Wrapper/Net.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Wrapper/Net.lua' )
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Wrapper/Storage.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Wrapper/Storage.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Wrapper/DynamicCargo.lua' )
|
||||||
|
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Cargo/Cargo.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Cargo/Cargo.lua' )
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Cargo/CargoUnit.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Cargo/CargoUnit.lua' )
|
||||||
@@ -84,6 +83,7 @@ __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/ZoneGoalCargo.lua' )
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/Tiresias.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/Stratego.lua' )
|
||||||
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Functional/ClientWatch.lua')
|
||||||
|
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/Airboss.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/Airboss.lua' )
|
||||||
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/RecoveryTanker.lua' )
|
__Moose.Include( MOOSE_DEVELOPMENT_FOLDER..'/Moose/Ops/RecoveryTanker.lua' )
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
__Moose.Include( 'Utilities\\Enums.lua' )
|
__Moose.Include( 'Utilities\\Enums.lua' )
|
||||||
__Moose.Include( 'Utilities\\Routines.lua' )
|
|
||||||
__Moose.Include( 'Utilities\\Utils.lua' )
|
__Moose.Include( 'Utilities\\Utils.lua' )
|
||||||
__Moose.Include( 'Utilities\\Profiler.lua' )
|
__Moose.Include( 'Utilities\\Profiler.lua' )
|
||||||
__Moose.Include( 'Utilities\\Templates.lua' )
|
--__Moose.Include( 'Utilities\\STTS.lua' )
|
||||||
__Moose.Include( 'Utilities\\STTS.lua' )
|
|
||||||
__Moose.Include( 'Utilities\\FiFo.lua' )
|
__Moose.Include( 'Utilities\\FiFo.lua' )
|
||||||
__Moose.Include( 'Utilities\\Socket.lua' )
|
__Moose.Include( 'Utilities\\Socket.lua' )
|
||||||
|
|
||||||
@@ -17,11 +15,11 @@ __Moose.Include( 'Core\\Event.lua' )
|
|||||||
__Moose.Include( 'Core\\Settings.lua' )
|
__Moose.Include( 'Core\\Settings.lua' )
|
||||||
__Moose.Include( 'Core\\Menu.lua' )
|
__Moose.Include( 'Core\\Menu.lua' )
|
||||||
__Moose.Include( 'Core\\Zone.lua' )
|
__Moose.Include( 'Core\\Zone.lua' )
|
||||||
__Moose.Include( 'Core\\Zone_Detection.lua' )
|
__Moose.Include( 'Core\\Velocity.lua' )
|
||||||
__Moose.Include( 'Core\\Database.lua' )
|
__Moose.Include( 'Core\\Database.lua' )
|
||||||
__Moose.Include( 'Core\\Set.lua' )
|
__Moose.Include( 'Core\\Set.lua' )
|
||||||
__Moose.Include( 'Core\\Point.lua' )
|
__Moose.Include( 'Core\\Point.lua' )
|
||||||
__Moose.Include( 'Core\\Velocity.lua' )
|
__Moose.Include( 'Core\\Pathline.lua' )
|
||||||
__Moose.Include( 'Core\\Message.lua' )
|
__Moose.Include( 'Core\\Message.lua' )
|
||||||
__Moose.Include( 'Core\\Fsm.lua' )
|
__Moose.Include( 'Core\\Fsm.lua' )
|
||||||
__Moose.Include( 'Core\\Spawn.lua' )
|
__Moose.Include( 'Core\\Spawn.lua' )
|
||||||
@@ -46,6 +44,10 @@ __Moose.Include( 'Wrapper\\Static.lua' )
|
|||||||
__Moose.Include( 'Wrapper\\Airbase.lua' )
|
__Moose.Include( 'Wrapper\\Airbase.lua' )
|
||||||
__Moose.Include( 'Wrapper\\Scenery.lua' )
|
__Moose.Include( 'Wrapper\\Scenery.lua' )
|
||||||
__Moose.Include( 'Wrapper\\Marker.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\\Cargo.lua' )
|
||||||
__Moose.Include( 'Cargo\\CargoUnit.lua' )
|
__Moose.Include( 'Cargo\\CargoUnit.lua' )
|
||||||
@@ -77,6 +79,10 @@ __Moose.Include( 'Functional\\Mantis.lua' )
|
|||||||
__Moose.Include( 'Functional\\Shorad.lua' )
|
__Moose.Include( 'Functional\\Shorad.lua' )
|
||||||
__Moose.Include( 'Functional\\Autolase.lua' )
|
__Moose.Include( 'Functional\\Autolase.lua' )
|
||||||
__Moose.Include( 'Functional\\AICSAR.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\\Airboss.lua' )
|
||||||
__Moose.Include( 'Ops\\RecoveryTanker.lua' )
|
__Moose.Include( 'Ops\\RecoveryTanker.lua' )
|
||||||
@@ -107,6 +113,9 @@ __Moose.Include( 'Ops\\Awacs.lua' )
|
|||||||
__Moose.Include( 'Ops\\PlayerTask.lua' )
|
__Moose.Include( 'Ops\\PlayerTask.lua' )
|
||||||
__Moose.Include( 'Ops\\Operation.lua' )
|
__Moose.Include( 'Ops\\Operation.lua' )
|
||||||
__Moose.Include( 'Ops\\FlightControl.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_Balancer.lua' )
|
||||||
__Moose.Include( 'AI\\AI_Air.lua' )
|
__Moose.Include( 'AI\\AI_Air.lua' )
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
-- * Option to present information in imperial or metric units
|
-- * Option to present information in imperial or metric units
|
||||||
-- * Runway length and airfield elevation (optional)
|
-- * Runway length and airfield elevation (optional)
|
||||||
-- * Frequencies/channels of nav aids (ILS, VOR, NDB, TACAN, PRMG, RSBN) (optional)
|
-- * Frequencies/channels of nav aids (ILS, VOR, NDB, TACAN, PRMG, RSBN) (optional)
|
||||||
-- * SRS Simple-Text-To-Speech (STTS) integration (no sound files necessary)
|
-- * SRS Simple-Text-To-Speech (MSRS) integration (no sound files necessary)
|
||||||
--
|
--
|
||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
@@ -291,7 +291,7 @@
|
|||||||
-- ## Nevada: Nellis AFB
|
-- ## Nevada: Nellis AFB
|
||||||
--
|
--
|
||||||
-- -- ATIS Nellis AFB on 270.10 MHz AM.
|
-- -- ATIS Nellis AFB on 270.10 MHz AM.
|
||||||
-- atisNellis=ATIS:New(AIRBASE.Nevada.Nellis_AFB, 270.1)
|
-- atisNellis=ATIS:New(AIRBASE.Nevada.Nellis, 270.1)
|
||||||
-- atisNellis:SetRadioRelayUnitName("Radio Relay Nellis")
|
-- atisNellis:SetRadioRelayUnitName("Radio Relay Nellis")
|
||||||
-- atisNellis:SetActiveRunway("21L")
|
-- atisNellis:SetActiveRunway("21L")
|
||||||
-- atisNellis:SetTowerFrequencies({327.000, 132.550})
|
-- atisNellis:SetTowerFrequencies({327.000, 132.550})
|
||||||
@@ -302,7 +302,7 @@
|
|||||||
-- ## Persian Gulf: Abu Dhabi International Airport
|
-- ## Persian Gulf: Abu Dhabi International Airport
|
||||||
--
|
--
|
||||||
-- -- ATIS Abu Dhabi International on 125.1 MHz AM.
|
-- -- ATIS Abu Dhabi International on 125.1 MHz AM.
|
||||||
-- atisAbuDhabi=ATIS:New(AIRBASE.PersianGulf.Abu_Dhabi_International_Airport, 125.1)
|
-- atisAbuDhabi=ATIS:New(AIRBASE.PersianGulf.Abu_Dhabi_Intl, 125.1)
|
||||||
-- atisAbuDhabi:SetRadioRelayUnitName("Radio Relay Abu Dhabi International Airport")
|
-- atisAbuDhabi:SetRadioRelayUnitName("Radio Relay Abu Dhabi International Airport")
|
||||||
-- atisAbuDhabi:SetMetricUnits()
|
-- atisAbuDhabi:SetMetricUnits()
|
||||||
-- atisAbuDhabi:SetActiveRunway("L")
|
-- atisAbuDhabi:SetActiveRunway("L")
|
||||||
@@ -498,6 +498,9 @@ ATIS.Alphabet = {
|
|||||||
-- @field #number Syria +5° (East).
|
-- @field #number Syria +5° (East).
|
||||||
-- @field #number MarianaIslands +2° (East).
|
-- @field #number MarianaIslands +2° (East).
|
||||||
-- @field #number SinaiMap +5° (East).
|
-- @field #number SinaiMap +5° (East).
|
||||||
|
-- @field #number Kola +15° (East).
|
||||||
|
-- @field #number Afghanistan +3° (East).
|
||||||
|
-- @field #number Iraq +4.4° (East).
|
||||||
ATIS.RunwayM2T = {
|
ATIS.RunwayM2T = {
|
||||||
Caucasus = 0,
|
Caucasus = 0,
|
||||||
Nevada = 12,
|
Nevada = 12,
|
||||||
@@ -508,6 +511,9 @@ ATIS.RunwayM2T = {
|
|||||||
MarianaIslands = 2,
|
MarianaIslands = 2,
|
||||||
Falklands = 12,
|
Falklands = 12,
|
||||||
SinaiMap = 5,
|
SinaiMap = 5,
|
||||||
|
Kola = 15,
|
||||||
|
Afghanistan = 3,
|
||||||
|
Iraq=4.4
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Whether ICAO phraseology is used for ATIS broadcasts.
|
--- Whether ICAO phraseology is used for ATIS broadcasts.
|
||||||
@@ -521,6 +527,9 @@ ATIS.RunwayM2T = {
|
|||||||
-- @field #boolean MarianaIslands true.
|
-- @field #boolean MarianaIslands true.
|
||||||
-- @field #boolean Falklands true.
|
-- @field #boolean Falklands true.
|
||||||
-- @field #boolean SinaiMap true.
|
-- @field #boolean SinaiMap true.
|
||||||
|
-- @field #boolean Kola true.
|
||||||
|
-- @field #boolean Afghanistan true.
|
||||||
|
-- @field #boolean Iraq true.
|
||||||
ATIS.ICAOPhraseology = {
|
ATIS.ICAOPhraseology = {
|
||||||
Caucasus = true,
|
Caucasus = true,
|
||||||
Nevada = false,
|
Nevada = false,
|
||||||
@@ -531,6 +540,9 @@ ATIS.ICAOPhraseology = {
|
|||||||
MarianaIslands = true,
|
MarianaIslands = true,
|
||||||
Falklands = true,
|
Falklands = true,
|
||||||
SinaiMap = true,
|
SinaiMap = true,
|
||||||
|
Kola = true,
|
||||||
|
Afghanistan = true,
|
||||||
|
Iraq = true,
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Nav point data.
|
--- Nav point data.
|
||||||
@@ -619,83 +631,83 @@ ATIS.ICAOPhraseology = {
|
|||||||
-- @field #ATIS.Soundfile TACANChannel
|
-- @field #ATIS.Soundfile TACANChannel
|
||||||
-- @field #ATIS.Soundfile VORFrequency
|
-- @field #ATIS.Soundfile VORFrequency
|
||||||
ATIS.Sound = {
|
ATIS.Sound = {
|
||||||
ActiveRunway = { filename = "ActiveRunway.ogg", duration = 0.99 },
|
ActiveRunway = { filename = "ActiveRunway.ogg", duration = 0.85 },
|
||||||
ActiveRunwayDeparture = { filename = "ActiveRunwayDeparture.ogg", duration = 0.99 },
|
ActiveRunwayDeparture = { filename = "ActiveRunwayDeparture.ogg", duration = 1.50 },
|
||||||
ActiveRunwayArrival = { filename = "ActiveRunwayArrival.ogg", duration = 0.99 },
|
ActiveRunwayArrival = { filename = "ActiveRunwayArrival.ogg", duration = 1.38 },
|
||||||
AdviceOnInitial = { filename = "AdviceOnInitial.ogg", duration = 3.00 },
|
AdviceOnInitial = { filename = "AdviceOnInitial.ogg", duration = 2.98 },
|
||||||
Airport = { filename = "Airport.ogg", duration = 0.66 },
|
Airport = { filename = "Airport.ogg", duration = 0.55 },
|
||||||
Altimeter = { filename = "Altimeter.ogg", duration = 0.68 },
|
Altimeter = { filename = "Altimeter.ogg", duration = 0.91 },
|
||||||
At = { filename = "At.ogg", duration = 0.41 },
|
At = { filename = "At.ogg", duration = 0.32 },
|
||||||
CloudBase = { filename = "CloudBase.ogg", duration = 0.82 },
|
CloudBase = { filename = "CloudBase.ogg", duration = 0.69 },
|
||||||
CloudCeiling = { filename = "CloudCeiling.ogg", duration = 0.61 },
|
CloudCeiling = { filename = "CloudCeiling.ogg", duration = 0.53 },
|
||||||
CloudsBroken = { filename = "CloudsBroken.ogg", duration = 1.07 },
|
CloudsBroken = { filename = "CloudsBroken.ogg", duration = 0.81 },
|
||||||
CloudsFew = { filename = "CloudsFew.ogg", duration = 0.99 },
|
CloudsFew = { filename = "CloudsFew.ogg", duration = 0.74 },
|
||||||
CloudsNo = { filename = "CloudsNo.ogg", duration = 1.01 },
|
CloudsNo = { filename = "CloudsNo.ogg", duration = 0.69},
|
||||||
CloudsNotAvailable = { filename = "CloudsNotAvailable.ogg", duration = 2.35 },
|
CloudsNotAvailable = { filename = "CloudsNotAvailable.ogg", duration = 2.64 },
|
||||||
CloudsOvercast = { filename = "CloudsOvercast.ogg", duration = 0.83 },
|
CloudsOvercast = { filename = "CloudsOvercast.ogg", duration = 0.82 },
|
||||||
CloudsScattered = { filename = "CloudsScattered.ogg", duration = 1.18 },
|
CloudsScattered = { filename = "CloudsScattered.ogg", duration = 0.89 },
|
||||||
Decimal = { filename = "Decimal.ogg", duration = 0.54 },
|
Decimal = { filename = "Decimal.ogg", duration = 0.71 },
|
||||||
DegreesCelsius = { filename = "DegreesCelsius.ogg", duration = 1.27 },
|
DegreesCelsius = { filename = "DegreesCelsius.ogg", duration = 1.08 },
|
||||||
DegreesFahrenheit = { filename = "DegreesFahrenheit.ogg", duration = 1.23 },
|
DegreesFahrenheit = { filename = "DegreesFahrenheit.ogg", duration = 1.07 },
|
||||||
DewPoint = { filename = "DewPoint.ogg", duration = 0.65 },
|
DewPoint = { filename = "DewPoint.ogg", duration = 0.59 },
|
||||||
Dust = { filename = "Dust.ogg", duration = 0.54 },
|
Dust = { filename = "Dust.ogg", duration = 0.37 },
|
||||||
Elevation = { filename = "Elevation.ogg", duration = 0.78 },
|
Elevation = { filename = "Elevation.ogg", duration = 0.92 },
|
||||||
EndOfInformation = { filename = "EndOfInformation.ogg", duration = 1.15 },
|
EndOfInformation = { filename = "EndOfInformation.ogg", duration = 1.24 },
|
||||||
Feet = { filename = "Feet.ogg", duration = 0.45 },
|
Feet = { filename = "Feet.ogg", duration = 0.34 },
|
||||||
Fog = { filename = "Fog.ogg", duration = 0.47 },
|
Fog = { filename = "Fog.ogg", duration = 0.41 },
|
||||||
Gusting = { filename = "Gusting.ogg", duration = 0.55 },
|
Gusting = { filename = "Gusting.ogg", duration = 0.58 },
|
||||||
HectoPascal = { filename = "HectoPascal.ogg", duration = 1.15 },
|
HectoPascal = { filename = "HectoPascal.ogg", duration = 0.92 },
|
||||||
Hundred = { filename = "Hundred.ogg", duration = 0.47 },
|
Hundred = { filename = "Hundred.ogg", duration = 0.53 },
|
||||||
InchesOfMercury = { filename = "InchesOfMercury.ogg", duration = 1.16 },
|
|
||||||
Information = { filename = "Information.ogg", duration = 0.85 },
|
|
||||||
Kilometers = { filename = "Kilometers.ogg", duration = 0.78 },
|
|
||||||
Knots = { filename = "Knots.ogg", duration = 0.59 },
|
|
||||||
Left = { filename = "Left.ogg", duration = 0.54 },
|
|
||||||
MegaHertz = { filename = "MegaHertz.ogg", duration = 0.87 },
|
|
||||||
Meters = { filename = "Meters.ogg", duration = 0.59 },
|
|
||||||
MetersPerSecond = { filename = "MetersPerSecond.ogg", duration = 1.14 },
|
|
||||||
Miles = { filename = "Miles.ogg", duration = 0.60 },
|
|
||||||
MillimetersOfMercury = { filename = "MillimetersOfMercury.ogg", duration = 1.53 },
|
|
||||||
Minus = { filename = "Minus.ogg", duration = 0.64 },
|
|
||||||
N0 = { filename = "N-0.ogg", duration = 0.55 },
|
|
||||||
N1 = { filename = "N-1.ogg", duration = 0.41 },
|
|
||||||
N2 = { filename = "N-2.ogg", duration = 0.37 },
|
|
||||||
N3 = { filename = "N-3.ogg", duration = 0.41 },
|
|
||||||
N4 = { filename = "N-4.ogg", duration = 0.37 },
|
|
||||||
N5 = { filename = "N-5.ogg", duration = 0.43 },
|
|
||||||
N6 = { filename = "N-6.ogg", duration = 0.55 },
|
|
||||||
N7 = { filename = "N-7.ogg", duration = 0.43 },
|
|
||||||
N8 = { filename = "N-8.ogg", duration = 0.38 },
|
|
||||||
N9 = { filename = "N-9.ogg", duration = 0.55 },
|
|
||||||
NauticalMiles = { filename = "NauticalMiles.ogg", duration = 1.04 },
|
|
||||||
None = { filename = "None.ogg", duration = 0.43 },
|
|
||||||
QFE = { filename = "QFE.ogg", duration = 0.63 },
|
|
||||||
QNH = { filename = "QNH.ogg", duration = 0.71 },
|
|
||||||
Rain = { filename = "Rain.ogg", duration = 0.41 },
|
|
||||||
Right = { filename = "Right.ogg", duration = 0.44 },
|
|
||||||
Snow = { filename = "Snow.ogg", duration = 0.48 },
|
|
||||||
SnowStorm = { filename = "SnowStorm.ogg", duration = 0.82 },
|
|
||||||
StatuteMiles = { filename = "StatuteMiles.ogg", duration = 1.15 },
|
|
||||||
SunriseAt = { filename = "SunriseAt.ogg", duration = 0.92 },
|
|
||||||
SunsetAt = { filename = "SunsetAt.ogg", duration = 0.95 },
|
|
||||||
Temperature = { filename = "Temperature.ogg", duration = 0.64 },
|
|
||||||
Thousand = { filename = "Thousand.ogg", duration = 0.55 },
|
|
||||||
ThunderStorm = { filename = "ThunderStorm.ogg", duration = 0.81 },
|
|
||||||
TimeLocal = { filename = "TimeLocal.ogg", duration = 0.90 },
|
|
||||||
TimeZulu = { filename = "TimeZulu.ogg", duration = 0.86 },
|
|
||||||
TowerFrequency = { filename = "TowerFrequency.ogg", duration = 1.19 },
|
|
||||||
Visibilty = { filename = "Visibility.ogg", duration = 0.79 },
|
|
||||||
WeatherPhenomena = { filename = "WeatherPhenomena.ogg", duration = 1.07 },
|
|
||||||
WindFrom = { filename = "WindFrom.ogg", duration = 0.60 },
|
|
||||||
ILSFrequency = { filename = "ILSFrequency.ogg", duration = 1.30 },
|
ILSFrequency = { filename = "ILSFrequency.ogg", duration = 1.30 },
|
||||||
InnerNDBFrequency = { filename = "InnerNDBFrequency.ogg", duration = 1.56 },
|
InchesOfMercury = { filename = "InchesOfMercury.ogg", duration = 1.26 },
|
||||||
OuterNDBFrequency = { filename = "OuterNDBFrequency.ogg", duration = 1.59 },
|
Information = { filename = "Information.ogg", duration = 0.99 },
|
||||||
RunwayLength = { filename = "RunwayLength.ogg", duration = 0.91 },
|
InnerNDBFrequency = { filename = "InnerNDBFrequency.ogg", duration = 1.69 },
|
||||||
VORFrequency = { filename = "VORFrequency.ogg", duration = 1.38 },
|
Kilometers = { filename = "Kilometers.ogg", duration = 0.93 },
|
||||||
TACANChannel = { filename = "TACANChannel.ogg", duration = 0.88 },
|
Knots = { filename = "Knots.ogg", duration = 0.46 },
|
||||||
PRMGChannel = { filename = "PRMGChannel.ogg", duration = 1.18 },
|
Left = { filename = "Left.ogg", duration = 0.41 },
|
||||||
RSBNChannel = { filename = "RSBNChannel.ogg", duration = 1.14 },
|
MegaHertz = { filename = "MegaHertz.ogg", duration = 0.83 },
|
||||||
Zulu = { filename = "Zulu.ogg", duration = 0.62 },
|
Meters = { filename = "Meters.ogg", duration = 0.55 },
|
||||||
|
MetersPerSecond = { filename = "MetersPerSecond.ogg", duration = 1.03 },
|
||||||
|
Miles = { filename = "Miles.ogg", duration = 0.44 },
|
||||||
|
MillimetersOfMercury = { filename = "MillimetersOfMercury.ogg", duration = 1.59 },
|
||||||
|
Minus = { filename = "Minus.ogg", duration = 0.55 },
|
||||||
|
N0 = { filename = "N-0.ogg", duration = 0.52 },
|
||||||
|
N1 = { filename = "N-1.ogg", duration = 0.35 },
|
||||||
|
N2 = { filename = "N-2.ogg", duration = 0.41 },
|
||||||
|
N3 = { filename = "N-3.ogg", duration = 0.34 },
|
||||||
|
N4 = { filename = "N-4.ogg", duration = 0.37 },
|
||||||
|
N5 = { filename = "N-5.ogg", duration = 0.40 },
|
||||||
|
N6 = { filename = "N-6.ogg", duration = 0.46 },
|
||||||
|
N7 = { filename = "N-7.ogg", duration = 0.52 },
|
||||||
|
N8 = { filename = "N-8.ogg", duration = 0.36 },
|
||||||
|
N9 = { filename = "N-9.ogg", duration = 0.51 },
|
||||||
|
NauticalMiles = { filename = "NauticalMiles.ogg", duration = 0.93 },
|
||||||
|
None = { filename = "None.ogg", duration = 0.33 },
|
||||||
|
OuterNDBFrequency = { filename = "OuterNDBFrequency.ogg", duration = 1.70 },
|
||||||
|
PRMGChannel = { filename = "PRMGChannel.ogg", duration = 1.27 },
|
||||||
|
QFE = { filename = "QFE.ogg", duration = 0.90 },
|
||||||
|
QNH = { filename = "QNH.ogg", duration = 0.94 },
|
||||||
|
Rain = { filename = "Rain.ogg", duration = 0.35 },
|
||||||
|
Right = { filename = "Right.ogg", duration = 0.31 },
|
||||||
|
RSBNChannel = { filename = "RSBNChannel.ogg", duration = 1.26 },
|
||||||
|
RunwayLength = { filename = "RunwayLength.ogg", duration = 0.81 },
|
||||||
|
Snow = { filename = "Snow.ogg", duration = 0.40 },
|
||||||
|
SnowStorm = { filename = "SnowStorm.ogg", duration = 0.73 },
|
||||||
|
StatuteMiles = { filename = "StatuteMiles.ogg", duration = 0.90 },
|
||||||
|
SunriseAt = { filename = "SunriseAt.ogg", duration = 0.82 },
|
||||||
|
SunsetAt = { filename = "SunsetAt.ogg", duration = 0.87 },
|
||||||
|
TACANChannel = { filename = "TACANChannel.ogg", duration = 0.81 },
|
||||||
|
Temperature = { filename = "Temperature.ogg", duration = 0.70 },
|
||||||
|
Thousand = { filename = "Thousand.ogg", duration = 0.58 },
|
||||||
|
ThunderStorm = { filename = "ThunderStorm.ogg", duration = 0.79 },
|
||||||
|
TimeLocal = { filename = "TimeLocal.ogg", duration = 0.83 },
|
||||||
|
TimeZulu = { filename = "TimeZulu.ogg", duration = 0.83 },
|
||||||
|
TowerFrequency = { filename = "TowerFrequency.ogg", duration = 1.05 },
|
||||||
|
Visibilty = { filename = "Visibility.ogg", duration = 1.16 },
|
||||||
|
VORFrequency = { filename = "VORFrequency.ogg", duration = 1.28 },
|
||||||
|
WeatherPhenomena = { filename = "WeatherPhenomena.ogg", duration = 1.09 },
|
||||||
|
WindFrom = { filename = "WindFrom.ogg", duration = 0.63 },
|
||||||
|
Zulu = { filename = "Zulu.ogg", duration = 0.51 },
|
||||||
}
|
}
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -882,6 +894,66 @@ ATIS.Messages = {
|
|||||||
FARP = "Farp",
|
FARP = "Farp",
|
||||||
DELIMITER = "Punto", -- decimal delimiter
|
DELIMITER = "Punto", -- decimal delimiter
|
||||||
},
|
},
|
||||||
|
-- French messages thanks to @Wojtech and Bing
|
||||||
|
FR = {
|
||||||
|
HOURS = "Heures",
|
||||||
|
TIME = "Temps",
|
||||||
|
NOCLOUDINFO = "Informations sur la couverture nuageuse non disponibles",
|
||||||
|
OVERCAST = "Ciel couvert",
|
||||||
|
BROKEN = "Nuages fragmentés",
|
||||||
|
SCATTERED = "Nuages épars",
|
||||||
|
FEWCLOUDS = "Nuages rares",
|
||||||
|
NOCLOUDS = "Clair",
|
||||||
|
AIRPORT = "Aéroport",
|
||||||
|
INFORMATION ="Information",
|
||||||
|
SUNRISEAT = "Levé du soleil à %s heure locale",
|
||||||
|
SUNSETAT = "Couché du soleil à %s heure locale",
|
||||||
|
WINDFROMMS = "Vent du %s pour %s mètres par seconde",
|
||||||
|
WINDFROMKNOTS = "Vent du %s pour %s noeuds",
|
||||||
|
GUSTING = "Rafale de vent",
|
||||||
|
VISIKM = "Visibilité %s kilomètres",
|
||||||
|
VISISM = "Visibilité %s Miles",
|
||||||
|
RAIN = "Pluie",
|
||||||
|
TSTORM = "Orage",
|
||||||
|
SNOW = "Neige",
|
||||||
|
SSTROM = "Tempête de neige",
|
||||||
|
FOG = "Brouillard",
|
||||||
|
DUST = "Poussière",
|
||||||
|
PHENOMENA = "Phénomène météorologique",
|
||||||
|
CLOUDBASEM = "Couverture nuageuse de %s à %s mètres",
|
||||||
|
CLOUDBASEFT = "Couverture nuageuse de %s à %s pieds",
|
||||||
|
TEMPERATURE = "Température",
|
||||||
|
DEWPOINT = "Point de rosée",
|
||||||
|
ALTIMETER = "Altimètre",
|
||||||
|
ACTIVERUN = "Décollages piste",
|
||||||
|
ACTIVELANDING = "Atterrissages piste",
|
||||||
|
LEFT = "Gauche",
|
||||||
|
RIGHT = "Droite",
|
||||||
|
RWYLENGTH = "Longueur de piste",
|
||||||
|
METERS = "Mètre",
|
||||||
|
FEET = "Pieds",
|
||||||
|
ELEVATION = "Hauteur",
|
||||||
|
TOWERFREQ = "Fréquences de la tour",
|
||||||
|
ILSFREQ = "Fréquences ILS",
|
||||||
|
OUTERNDB = "Fréquences Outer NDB",
|
||||||
|
INNERNDB = "Fréquences Inner NDB",
|
||||||
|
VORFREQ = "Fréquences VOR",
|
||||||
|
VORFREQTTS = "Fréquences V O R",
|
||||||
|
TACANCH = "Canal TACAN %d",
|
||||||
|
RSBNCH = "Canal RSBN",
|
||||||
|
PRMGCH = "Canal PRMG",
|
||||||
|
ADVISE = "Informez le contrôle que vous avez copié l'information",
|
||||||
|
STATUTE = "Statute Miles",
|
||||||
|
DEGREES = "Degré celcius",
|
||||||
|
FAHRENHEIT = "Degré Fahrenheit",
|
||||||
|
INCHHG = "Pouces de mercure",
|
||||||
|
MMHG = "Millimètres de mercure",
|
||||||
|
HECTO = "Hectopascals",
|
||||||
|
METERSPER = "Mètres par seconde",
|
||||||
|
TACAN = "TAKAN",
|
||||||
|
FARP = "FARPE",
|
||||||
|
DELIMITER = "Décimal", -- decimal delimiter
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -894,7 +966,7 @@ _ATIS = {}
|
|||||||
|
|
||||||
--- ATIS class version.
|
--- ATIS class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
ATIS.version = "1.0.0"
|
ATIS.version = "1.0.1"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- TODO list
|
-- TODO list
|
||||||
@@ -1061,7 +1133,7 @@ end
|
|||||||
-- @return #ATIS self
|
-- @return #ATIS self
|
||||||
function ATIS:_InitLocalization()
|
function ATIS:_InitLocalization()
|
||||||
self:T(self.lid.."_InitLocalization")
|
self:T(self.lid.."_InitLocalization")
|
||||||
self.gettext = TEXTANDSOUND:New("AWACS","en") -- Core.TextAndSound#TEXTANDSOUND
|
self.gettext = TEXTANDSOUND:New("ATIS","en") -- Core.TextAndSound#TEXTANDSOUND
|
||||||
self.locale = "en"
|
self.locale = "en"
|
||||||
for locale,table in pairs(self.Messages) do
|
for locale,table in pairs(self.Messages) do
|
||||||
local Locale = string.lower(tostring(locale))
|
local Locale = string.lower(tostring(locale))
|
||||||
@@ -1975,17 +2047,28 @@ function ATIS:onafterBroadcast( From, Event, To )
|
|||||||
|
|
||||||
local hours = self.gettext:GetEntry("HOURS",self.locale)
|
local hours = self.gettext:GetEntry("HOURS",self.locale)
|
||||||
local sunrise = coord:GetSunrise()
|
local sunrise = coord:GetSunrise()
|
||||||
sunrise = UTILS.Split( sunrise, ":" )
|
--self:I(sunrise)
|
||||||
local SUNRISE = string.format( "%s%s", sunrise[1], sunrise[2] )
|
local SUNRISE = "no time"
|
||||||
if self.useSRS then
|
local NorthPolar = true
|
||||||
SUNRISE = string.format( "%s %s %s", sunrise[1], sunrise[2], hours )
|
if tostring(sunrise) ~= "N/S" and tostring(sunrise) ~= "N/R" then
|
||||||
|
sunrise = UTILS.Split( sunrise, ":" )
|
||||||
|
SUNRISE = string.format( "%s%s", sunrise[1], sunrise[2] )
|
||||||
|
if self.useSRS then
|
||||||
|
SUNRISE = string.format( "%s %s %s", sunrise[1], sunrise[2], hours )
|
||||||
|
end
|
||||||
|
NorthPolar = false
|
||||||
end
|
end
|
||||||
|
|
||||||
local sunset = coord:GetSunset()
|
local sunset = coord:GetSunset()
|
||||||
sunset = UTILS.Split( sunset, ":" )
|
--self:I(sunset)
|
||||||
local SUNSET = string.format( "%s%s", sunset[1], sunset[2] )
|
local SUNSET = "no time"
|
||||||
if self.useSRS then
|
if tostring(sunset) ~= "N/S" and tostring(sunset) ~= "N/R" then
|
||||||
SUNSET = string.format( "%s %s %s", sunset[1], sunset[2], hours )
|
sunset = UTILS.Split( sunset, ":" )
|
||||||
|
SUNSET = string.format( "%s%s", sunset[1], sunset[2] )
|
||||||
|
if self.useSRS then
|
||||||
|
SUNSET = string.format( "%s %s %s", sunset[1], sunset[2], hours )
|
||||||
|
end
|
||||||
|
NorthPolar = false
|
||||||
end
|
end
|
||||||
|
|
||||||
---------------------------------
|
---------------------------------
|
||||||
@@ -2012,34 +2095,32 @@ function ATIS:onafterBroadcast( From, Event, To )
|
|||||||
---------------
|
---------------
|
||||||
|
|
||||||
-- Get mission weather info. Most of this is static.
|
-- Get mission weather info. Most of this is static.
|
||||||
local clouds, visibility, turbulence, fog, dust, static = self:GetMissionWeather()
|
local clouds, visibility, turbulence, dustdens, static = self:GetMissionWeather()
|
||||||
|
|
||||||
-- Check that fog is actually "thick" enough to reach the airport. If an airport is in the mountains, fog might not affect it as it is measured from sea level.
|
local dust=false
|
||||||
if fog and fog.thickness < height + 25 then
|
local fog=false
|
||||||
fog = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Dust only up to 1500 ft = 457 m ASL.
|
|
||||||
if dust and height + 25 > UTILS.FeetToMeters( 1500 ) then
|
|
||||||
dust = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
------------------
|
------------------
|
||||||
--- Visibility ---
|
--- Visibility ---
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
-- Get min visibility.
|
if dustdens then
|
||||||
local visibilitymin = visibility
|
|
||||||
|
-- Dust only up to 1500 ft = 457 m ASL.
|
||||||
if fog then
|
if UTILS.FeetToMeters( 1500 )> height+25 then
|
||||||
if fog.visibility < visibilitymin then
|
dust=true
|
||||||
visibilitymin = fog.visibility
|
visibility=math.min(visibility, dustdens)
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
else -- As of DCS 2.9.10.3948 (December 2024), fog and dust are mutually exclusive!
|
||||||
if dust then
|
|
||||||
if dust < visibilitymin then
|
-- Get current fog visibility and thickness
|
||||||
visibilitymin = dust
|
local fvis=world.weather.getFogVisibilityDistance()
|
||||||
|
local fheight=world.weather.getFogThickness()
|
||||||
|
|
||||||
|
if fvis>0 and fheight>height+25 then
|
||||||
|
fog=true
|
||||||
|
visibility=math.min(visibility, fvis)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -2047,7 +2128,7 @@ function ATIS:onafterBroadcast( From, Event, To )
|
|||||||
|
|
||||||
if self.metric then
|
if self.metric then
|
||||||
-- Visibility in km.
|
-- Visibility in km.
|
||||||
local reportedviz = UTILS.Round( visibilitymin / 1000 )
|
local reportedviz = UTILS.Round( visibility / 1000 )
|
||||||
-- max reported visibility 9999 m
|
-- max reported visibility 9999 m
|
||||||
if reportedviz > 10 then
|
if reportedviz > 10 then
|
||||||
reportedviz = 10
|
reportedviz = 10
|
||||||
@@ -2055,7 +2136,7 @@ function ATIS:onafterBroadcast( From, Event, To )
|
|||||||
VISIBILITY = string.format( "%d", reportedviz )
|
VISIBILITY = string.format( "%d", reportedviz )
|
||||||
else
|
else
|
||||||
-- max reported visibility 10 NM
|
-- max reported visibility 10 NM
|
||||||
local reportedviz = UTILS.Round( UTILS.MetersToSM( visibilitymin ) )
|
local reportedviz = UTILS.Round( UTILS.MetersToSM( visibility ) )
|
||||||
if reportedviz > 10 then
|
if reportedviz > 10 then
|
||||||
reportedviz = 10
|
reportedviz = 10
|
||||||
end
|
end
|
||||||
@@ -2069,7 +2150,7 @@ function ATIS:onafterBroadcast( From, Event, To )
|
|||||||
local cloudbase = clouds.base
|
local cloudbase = clouds.base
|
||||||
local cloudceil = clouds.base + clouds.thickness
|
local cloudceil = clouds.base + clouds.thickness
|
||||||
local clouddens = clouds.density
|
local clouddens = clouds.density
|
||||||
|
|
||||||
-- Cloud preset (DCS 2.7)
|
-- Cloud preset (DCS 2.7)
|
||||||
local cloudspreset = clouds.preset or "Nothing"
|
local cloudspreset = clouds.preset or "Nothing"
|
||||||
|
|
||||||
@@ -2100,6 +2181,39 @@ function ATIS:onafterBroadcast( From, Event, To )
|
|||||||
else
|
else
|
||||||
precepitation = 3 -- snow
|
precepitation = 3 -- snow
|
||||||
end
|
end
|
||||||
|
elseif cloudspreset:find( "RainyPreset4" ) then
|
||||||
|
-- Overcast + Rain
|
||||||
|
clouddens = 5
|
||||||
|
if temperature > 5 then
|
||||||
|
precepitation = 1 -- rain
|
||||||
|
else
|
||||||
|
precepitation = 3 -- snow
|
||||||
|
end
|
||||||
|
elseif cloudspreset:find( "RainyPreset5" ) then
|
||||||
|
-- Overcast + Rain
|
||||||
|
clouddens = 5
|
||||||
|
if temperature > 5 then
|
||||||
|
precepitation = 1 -- rain
|
||||||
|
else
|
||||||
|
precepitation = 3 -- snow
|
||||||
|
end
|
||||||
|
elseif cloudspreset:find( "RainyPreset6" ) then
|
||||||
|
-- Overcast + Rain
|
||||||
|
clouddens = 5
|
||||||
|
if temperature > 5 then
|
||||||
|
precepitation = 1 -- rain
|
||||||
|
else
|
||||||
|
precepitation = 3 -- snow
|
||||||
|
end
|
||||||
|
-- NEWRAINPRESET4
|
||||||
|
elseif cloudspreset:find( "NEWRAINPRESET4" ) then
|
||||||
|
-- Overcast + Rain
|
||||||
|
clouddens = 5
|
||||||
|
if temperature > 5 then
|
||||||
|
precepitation = 1 -- rain
|
||||||
|
else
|
||||||
|
precepitation = 3 -- snow
|
||||||
|
end
|
||||||
elseif cloudspreset:find( "RainyPreset" ) then
|
elseif cloudspreset:find( "RainyPreset" ) then
|
||||||
-- Overcast + Rain
|
-- Overcast + Rain
|
||||||
clouddens = 9
|
clouddens = 9
|
||||||
@@ -2294,7 +2408,7 @@ function ATIS:onafterBroadcast( From, Event, To )
|
|||||||
local sunrise = self.gettext:GetEntry("SUNRISEAT",self.locale)
|
local sunrise = self.gettext:GetEntry("SUNRISEAT",self.locale)
|
||||||
--subtitle = string.format( "Sunrise at %s local time", SUNRISE )
|
--subtitle = string.format( "Sunrise at %s local time", SUNRISE )
|
||||||
subtitle = string.format( sunrise, SUNRISE )
|
subtitle = string.format( sunrise, SUNRISE )
|
||||||
if not self.useSRS then
|
if not self.useSRS and NorthPolar == false then
|
||||||
self:Transmission( self.Sound.SunriseAt, 0.5, subtitle )
|
self:Transmission( self.Sound.SunriseAt, 0.5, subtitle )
|
||||||
self.radioqueue:Number2Transmission( SUNRISE, nil, 0.2 )
|
self.radioqueue:Number2Transmission( SUNRISE, nil, 0.2 )
|
||||||
self:Transmission( self.Sound.TimeLocal, 0.2 )
|
self:Transmission( self.Sound.TimeLocal, 0.2 )
|
||||||
@@ -2305,7 +2419,7 @@ function ATIS:onafterBroadcast( From, Event, To )
|
|||||||
local sunset = self.gettext:GetEntry("SUNSETAT",self.locale)
|
local sunset = self.gettext:GetEntry("SUNSETAT",self.locale)
|
||||||
--subtitle = string.format( "Sunset at %s local time", SUNSET )
|
--subtitle = string.format( "Sunset at %s local time", SUNSET )
|
||||||
subtitle = string.format( sunset, SUNSET )
|
subtitle = string.format( sunset, SUNSET )
|
||||||
if not self.useSRS then
|
if not self.useSRS and NorthPolar == false then
|
||||||
self:Transmission( self.Sound.SunsetAt, 0.5, subtitle )
|
self:Transmission( self.Sound.SunsetAt, 0.5, subtitle )
|
||||||
self.radioqueue:Number2Transmission( SUNSET, nil, 0.5 )
|
self.radioqueue:Number2Transmission( SUNSET, nil, 0.5 )
|
||||||
self:Transmission( self.Sound.TimeLocal, 0.2 )
|
self:Transmission( self.Sound.TimeLocal, 0.2 )
|
||||||
@@ -2631,7 +2745,7 @@ function ATIS:onafterBroadcast( From, Event, To )
|
|||||||
if not self.ATISforFARPs then
|
if not self.ATISforFARPs then
|
||||||
-- Active runway.
|
-- Active runway.
|
||||||
local subtitle = ""
|
local subtitle = ""
|
||||||
if runwayLanding then
|
if runwayLanding and runwayLanding ~= runwayTakeoff then
|
||||||
|
|
||||||
local actrun = self.gettext:GetEntry("ACTIVELANDING",self.locale)
|
local actrun = self.gettext:GetEntry("ACTIVELANDING",self.locale)
|
||||||
|
|
||||||
@@ -3249,28 +3363,13 @@ function ATIS:GetMissionWeather()
|
|||||||
dust = weather.dust_density
|
dust = weather.dust_density
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Fog
|
|
||||||
--[[
|
|
||||||
["enable_fog"] = false,
|
|
||||||
["fog"] =
|
|
||||||
{
|
|
||||||
["thickness"] = 0,
|
|
||||||
["visibility"] = 25,
|
|
||||||
}, -- end of ["fog"]
|
|
||||||
]]
|
|
||||||
local fog = nil
|
|
||||||
if weather.enable_fog == true then
|
|
||||||
fog = weather.fog
|
|
||||||
end
|
|
||||||
|
|
||||||
self:T( "FF weather:" )
|
self:T( "FF weather:" )
|
||||||
self:T( { clouds = clouds } )
|
self:T( { clouds = clouds } )
|
||||||
self:T( { visibility = visibility } )
|
self:T( { visibility = visibility } )
|
||||||
self:T( { turbulence = turbulence } )
|
self:T( { turbulence = turbulence } )
|
||||||
self:T( { fog = fog } )
|
|
||||||
self:T( { dust = dust } )
|
self:T( { dust = dust } )
|
||||||
self:T( { static = static } )
|
self:T( { static = static } )
|
||||||
return clouds, visibility, turbulence, fog, dust, static
|
return clouds, visibility, turbulence, dust, static
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Get thousands of a number.
|
--- Get thousands of a number.
|
||||||
|
|||||||
@@ -187,7 +187,7 @@ AIRWING = {
|
|||||||
|
|
||||||
--- AIRWING class version.
|
--- AIRWING class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
AIRWING.version="0.9.5"
|
AIRWING.version="0.9.6"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- ToDo list
|
-- ToDo list
|
||||||
@@ -1041,6 +1041,9 @@ function AIRWING:onafterStatus(From, Event, To)
|
|||||||
|
|
||||||
-- Check Recon missions.
|
-- Check Recon missions.
|
||||||
self:CheckRECON()
|
self:CheckRECON()
|
||||||
|
|
||||||
|
-- Display tactival overview.
|
||||||
|
self:_TacticalOverview()
|
||||||
|
|
||||||
----------------
|
----------------
|
||||||
-- Transport ---
|
-- Transport ---
|
||||||
@@ -1362,16 +1365,20 @@ function AIRWING:CheckRescuhelo()
|
|||||||
|
|
||||||
local N=self:CountMissionsInQueue({AUFTRAG.Type.RESCUEHELO})
|
local N=self:CountMissionsInQueue({AUFTRAG.Type.RESCUEHELO})
|
||||||
|
|
||||||
local name=self.airbase:GetName()
|
if self.airbase then
|
||||||
|
|
||||||
local carrier=UNIT:FindByName(name)
|
local name=self.airbase:GetName()
|
||||||
|
|
||||||
for i=1,self.nflightsRescueHelo-N do
|
local carrier=UNIT:FindByName(name)
|
||||||
|
|
||||||
local mission=AUFTRAG:NewRESCUEHELO(carrier)
|
for i=1,self.nflightsRescueHelo-N do
|
||||||
|
|
||||||
self:AddMission(mission)
|
local mission=AUFTRAG:NewRESCUEHELO(carrier)
|
||||||
|
|
||||||
|
self:AddMission(mission)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
|
|||||||
@@ -3615,7 +3615,7 @@ function AIRBOSS:onafterStart( From, Event, To )
|
|||||||
|
|
||||||
-- Handle events.
|
-- Handle events.
|
||||||
self:HandleEvent( EVENTS.Birth )
|
self:HandleEvent( EVENTS.Birth )
|
||||||
self:HandleEvent( EVENTS.Land )
|
self:HandleEvent( EVENTS.RunwayTouch )
|
||||||
self:HandleEvent( EVENTS.EngineShutdown )
|
self:HandleEvent( EVENTS.EngineShutdown )
|
||||||
self:HandleEvent( EVENTS.Takeoff )
|
self:HandleEvent( EVENTS.Takeoff )
|
||||||
self:HandleEvent( EVENTS.Crash )
|
self:HandleEvent( EVENTS.Crash )
|
||||||
@@ -3623,6 +3623,7 @@ function AIRBOSS:onafterStart( From, Event, To )
|
|||||||
self:HandleEvent( EVENTS.PlayerLeaveUnit, self._PlayerLeft )
|
self:HandleEvent( EVENTS.PlayerLeaveUnit, self._PlayerLeft )
|
||||||
self:HandleEvent( EVENTS.MissionEnd )
|
self:HandleEvent( EVENTS.MissionEnd )
|
||||||
self:HandleEvent( EVENTS.RemoveUnit )
|
self:HandleEvent( EVENTS.RemoveUnit )
|
||||||
|
self:HandleEvent( EVENTS.UnitLost, self.OnEventRemoveUnit )
|
||||||
|
|
||||||
-- self.StatusScheduler=SCHEDULER:New(self)
|
-- self.StatusScheduler=SCHEDULER:New(self)
|
||||||
-- self.StatusScheduler:Schedule(self, self._Status, {}, 1, 0.5)
|
-- self.StatusScheduler:Schedule(self, self._Status, {}, 1, 0.5)
|
||||||
@@ -4380,7 +4381,7 @@ function AIRBOSS:onafterStop( From, Event, To )
|
|||||||
|
|
||||||
-- Unhandle events.
|
-- Unhandle events.
|
||||||
self:UnHandleEvent( EVENTS.Birth )
|
self:UnHandleEvent( EVENTS.Birth )
|
||||||
self:UnHandleEvent( EVENTS.Land )
|
self:UnHandleEvent( EVENTS.RunwayTouch )
|
||||||
self:UnHandleEvent( EVENTS.EngineShutdown )
|
self:UnHandleEvent( EVENTS.EngineShutdown )
|
||||||
self:UnHandleEvent( EVENTS.Takeoff )
|
self:UnHandleEvent( EVENTS.Takeoff )
|
||||||
self:UnHandleEvent( EVENTS.Crash )
|
self:UnHandleEvent( EVENTS.Crash )
|
||||||
@@ -8290,7 +8291,7 @@ end
|
|||||||
--- Airboss event handler for event land.
|
--- Airboss event handler for event land.
|
||||||
-- @param #AIRBOSS self
|
-- @param #AIRBOSS self
|
||||||
-- @param Core.Event#EVENTDATA EventData
|
-- @param Core.Event#EVENTDATA EventData
|
||||||
function AIRBOSS:OnEventLand( EventData )
|
function AIRBOSS:OnEventRunwayTouch( EventData )
|
||||||
self:F3( { eventland = EventData } )
|
self:F3( { eventland = EventData } )
|
||||||
|
|
||||||
-- Nil checks.
|
-- Nil checks.
|
||||||
@@ -14679,7 +14680,7 @@ function AIRBOSS:_GetPlayerUnitAndName( _unitName )
|
|||||||
-- Get DCS unit from its name.
|
-- Get DCS unit from its name.
|
||||||
local DCSunit = Unit.getByName( _unitName )
|
local DCSunit = Unit.getByName( _unitName )
|
||||||
|
|
||||||
if DCSunit then
|
if DCSunit and DCSunit.getPlayerName then
|
||||||
|
|
||||||
-- Get player name if any.
|
-- Get player name if any.
|
||||||
local playername = DCSunit:getPlayerName()
|
local playername = DCSunit:getPlayerName()
|
||||||
@@ -15650,7 +15651,7 @@ function AIRBOSS:_Number2Sound( playerData, sender, number, delay )
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Split string into characters.
|
-- Split string into characters.
|
||||||
local numbers = _split( number )
|
local numbers = _split( tostring(number) )
|
||||||
|
|
||||||
local wait = 0
|
local wait = 0
|
||||||
for i = 1, #numbers do
|
for i = 1, #numbers do
|
||||||
@@ -15718,7 +15719,7 @@ function AIRBOSS:_Number2Radio( radio, number, delay, interval, pilotcall )
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Split string into characters.
|
-- Split string into characters.
|
||||||
local numbers = _split( number )
|
local numbers = _split( tostring(number) )
|
||||||
|
|
||||||
local wait = 0
|
local wait = 0
|
||||||
for i = 1, #numbers do
|
for i = 1, #numbers do
|
||||||
@@ -18086,7 +18087,7 @@ function AIRBOSS:_MarkCaseZones( _unitName, flare )
|
|||||||
self:_GetZoneArcIn( case ):FlareZone( FLARECOLOR.White, 45 )
|
self:_GetZoneArcIn( case ):FlareZone( FLARECOLOR.White, 45 )
|
||||||
text = text .. "\n* arc turn in with WHITE flares"
|
text = text .. "\n* arc turn in with WHITE flares"
|
||||||
self:_GetZoneArcOut( case ):FlareZone( FLARECOLOR.White, 45 )
|
self:_GetZoneArcOut( case ):FlareZone( FLARECOLOR.White, 45 )
|
||||||
text = text .. "\n* arc trun out with WHITE flares"
|
text = text .. "\n* arc turn out with WHITE flares"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -18138,7 +18139,7 @@ function AIRBOSS:_MarkCaseZones( _unitName, flare )
|
|||||||
self:_GetZoneArcIn( case ):SmokeZone( SMOKECOLOR.Blue, 45 )
|
self:_GetZoneArcIn( case ):SmokeZone( SMOKECOLOR.Blue, 45 )
|
||||||
text = text .. "\n* arc turn in with BLUE smoke"
|
text = text .. "\n* arc turn in with BLUE smoke"
|
||||||
self:_GetZoneArcOut( case ):SmokeZone( SMOKECOLOR.Blue, 45 )
|
self:_GetZoneArcOut( case ):SmokeZone( SMOKECOLOR.Blue, 45 )
|
||||||
text = text .. "\n* arc trun out with BLUE smoke"
|
text = text .. "\n* arc turn out with BLUE smoke"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ ARMYGROUP = {
|
|||||||
|
|
||||||
--- Army Group version.
|
--- Army Group version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
ARMYGROUP.version="1.0.1"
|
ARMYGROUP.version="1.0.3"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- TODO list
|
-- TODO list
|
||||||
@@ -403,6 +403,7 @@ function ARMYGROUP:New(group)
|
|||||||
self:HandleEvent(EVENTS.Birth, self.OnEventBirth)
|
self:HandleEvent(EVENTS.Birth, self.OnEventBirth)
|
||||||
self:HandleEvent(EVENTS.Dead, self.OnEventDead)
|
self:HandleEvent(EVENTS.Dead, self.OnEventDead)
|
||||||
self:HandleEvent(EVENTS.RemoveUnit, self.OnEventRemoveUnit)
|
self:HandleEvent(EVENTS.RemoveUnit, self.OnEventRemoveUnit)
|
||||||
|
self:HandleEvent(EVENTS.UnitLost, self.OnEventRemoveUnit)
|
||||||
self:HandleEvent(EVENTS.Hit, self.OnEventHit)
|
self:HandleEvent(EVENTS.Hit, self.OnEventHit)
|
||||||
|
|
||||||
-- Start the status monitoring.
|
-- Start the status monitoring.
|
||||||
@@ -2048,114 +2049,70 @@ end
|
|||||||
--- Initialize group parameters. Also initializes waypoints if self.waypoints is nil.
|
--- Initialize group parameters. Also initializes waypoints if self.waypoints is nil.
|
||||||
-- @param #ARMYGROUP self
|
-- @param #ARMYGROUP self
|
||||||
-- @param #table Template Template used to init the group. Default is `self.template`.
|
-- @param #table Template Template used to init the group. Default is `self.template`.
|
||||||
|
-- @param #number Delay Delay in seconds before group is initialized. Default `nil`, *i.e.* instantaneous.
|
||||||
-- @return #ARMYGROUP self
|
-- @return #ARMYGROUP self
|
||||||
function ARMYGROUP:_InitGroup(Template, Delay)
|
function ARMYGROUP:_InitGroup(Template, Delay)
|
||||||
|
|
||||||
if Delay and Delay>0 then
|
if Delay and Delay>0 then
|
||||||
self:ScheduleOnce(Delay, ARMYGROUP._InitGroup, self, Template, 0)
|
self:ScheduleOnce(Delay, ARMYGROUP._InitGroup, self, Template, 0)
|
||||||
else
|
else
|
||||||
-- First check if group was already initialized.
|
|
||||||
if self.groupinitialized then
|
|
||||||
self:T(self.lid.."WARNING: Group was already initialized! Will NOT do it again!")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Get template of group.
|
|
||||||
local template=Template or self:_GetTemplate()
|
|
||||||
|
|
||||||
-- Ground are always AI.
|
|
||||||
self.isAI=true
|
|
||||||
|
|
||||||
-- Is (template) group late activated.
|
|
||||||
self.isLateActivated=template.lateActivation
|
|
||||||
|
|
||||||
-- Ground groups cannot be uncontrolled.
|
|
||||||
self.isUncontrolled=false
|
|
||||||
|
|
||||||
-- Max speed in km/h.
|
|
||||||
self.speedMax=self.group:GetSpeedMax()
|
|
||||||
|
|
||||||
-- Is group mobile?
|
|
||||||
if self.speedMax and self.speedMax>3.6 then
|
|
||||||
self.isMobile=true
|
|
||||||
else
|
|
||||||
self.isMobile=false
|
|
||||||
self.speedMax = 0
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Cruise speed in km/h
|
|
||||||
self.speedCruise=self.speedMax*0.7
|
|
||||||
|
|
||||||
-- Group ammo.
|
|
||||||
self.ammo=self:GetAmmoTot()
|
|
||||||
|
|
||||||
-- Radio parameters from template.
|
|
||||||
self.radio.On=false -- Radio is always OFF for ground.
|
|
||||||
self.radio.Freq=133
|
|
||||||
self.radio.Modu=radio.modulation.AM
|
|
||||||
|
|
||||||
-- Set default radio.
|
|
||||||
self:SetDefaultRadio(self.radio.Freq, self.radio.Modu, self.radio.On)
|
|
||||||
|
|
||||||
-- Get current formation from first waypoint.
|
|
||||||
self.option.Formation=template.route.points[1].action
|
|
||||||
|
|
||||||
-- Set default formation to "on road".
|
|
||||||
self.optionDefault.Formation=ENUMS.Formation.Vehicle.OnRoad
|
|
||||||
|
|
||||||
-- First check if group was already initialized.
|
-- First check if group was already initialized.
|
||||||
if self.groupinitialized then
|
if self.groupinitialized then
|
||||||
self:T(self.lid.."WARNING: Group was already initialized! Will NOT do it again!")
|
self:T(self.lid.."WARNING: Group was already initialized! Will NOT do it again!")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
self:T(self.lid.."FF Initializing Group")
|
|
||||||
|
|
||||||
-- Get template of group.
|
-- Get template of group.
|
||||||
local template=Template or self:_GetTemplate()
|
local template=Template or self:_GetTemplate()
|
||||||
|
|
||||||
-- Ground are always AI.
|
-- Ground are always AI.
|
||||||
self.isAI=true
|
self.isAI=true
|
||||||
|
|
||||||
-- Is (template) group late activated.
|
-- Is (template) group late activated.
|
||||||
self.isLateActivated=template.lateActivation
|
self.isLateActivated=template.lateActivation
|
||||||
|
|
||||||
-- Ground groups cannot be uncontrolled.
|
-- Ground groups cannot be uncontrolled.
|
||||||
self.isUncontrolled=false
|
self.isUncontrolled=false
|
||||||
|
|
||||||
-- Max speed in km/h.
|
-- Max speed in km/h.
|
||||||
self.speedMax=self.group:GetSpeedMax()
|
self.speedMax=self.group:GetSpeedMax()
|
||||||
|
|
||||||
-- Is group mobile?
|
-- Is group mobile?
|
||||||
if self.speedMax>3.6 then
|
if self.speedMax and self.speedMax>3.6 then
|
||||||
self.isMobile=true
|
self.isMobile=true
|
||||||
else
|
else
|
||||||
self.isMobile=false
|
self.isMobile=false
|
||||||
|
self.speedMax = 0
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Cruise speed in km/h
|
-- Cruise speed in km/h
|
||||||
self.speedCruise=self.speedMax*0.7
|
self.speedCruise=self.speedMax*0.7
|
||||||
|
|
||||||
-- Group ammo.
|
-- Group ammo.
|
||||||
self.ammo=self:GetAmmoTot()
|
self.ammo=self:GetAmmoTot()
|
||||||
|
|
||||||
-- Radio parameters from template.
|
-- Radio parameters from template.
|
||||||
self.radio.On=false -- Radio is always OFF for ground.
|
self.radio.On=false -- Radio is always OFF for ground.
|
||||||
self.radio.Freq=133
|
self.radio.Freq=133
|
||||||
self.radio.Modu=radio.modulation.AM
|
self.radio.Modu=radio.modulation.AM
|
||||||
|
|
||||||
-- Set default radio.
|
-- Set default radio.
|
||||||
self:SetDefaultRadio(self.radio.Freq, self.radio.Modu, self.radio.On)
|
self:SetDefaultRadio(self.radio.Freq, self.radio.Modu, self.radio.On)
|
||||||
|
|
||||||
-- Get current formation from first waypoint.
|
-- Get current formation from first waypoint.
|
||||||
self.option.Formation=template.route.points[1].action
|
self.option.Formation=template.route.points[1].action
|
||||||
|
|
||||||
-- Set default formation to "on road".
|
-- Set default formation to "on road".
|
||||||
self.optionDefault.Formation=ENUMS.Formation.Vehicle.OnRoad
|
self.optionDefault.Formation=ENUMS.Formation.Vehicle.OnRoad
|
||||||
|
|
||||||
-- Default TACAN off.
|
-- Default TACAN off.
|
||||||
self:SetDefaultTACAN(nil, nil, nil, nil, true)
|
if not self.tacanDefault then
|
||||||
self.tacan=UTILS.DeepCopy(self.tacanDefault)
|
self:SetDefaultTACAN(nil, nil, nil, nil, true)
|
||||||
|
end
|
||||||
|
if not self.tacan then
|
||||||
|
self.tacan=UTILS.DeepCopy(self.tacanDefault)
|
||||||
|
end
|
||||||
|
|
||||||
-- Units of the group.
|
-- Units of the group.
|
||||||
local units=self.group:GetUnits()
|
local units=self.group:GetUnits()
|
||||||
@@ -2176,7 +2133,6 @@ function ARMYGROUP:_InitGroup(Template, Delay)
|
|||||||
self:_AddElementByName(unitname)
|
self:_AddElementByName(unitname)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Init done.
|
-- Init done.
|
||||||
self.groupinitialized=true
|
self.groupinitialized=true
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -93,6 +93,7 @@
|
|||||||
-- @field #number engageWeaponType Weapon type used.
|
-- @field #number engageWeaponType Weapon type used.
|
||||||
-- @field #number engageWeaponExpend How many weapons are used.
|
-- @field #number engageWeaponExpend How many weapons are used.
|
||||||
-- @field #boolean engageAsGroup Group attack.
|
-- @field #boolean engageAsGroup Group attack.
|
||||||
|
-- @field #number engageLength Length of engage (carpet or strafing) in meters.
|
||||||
-- @field #number engageMaxDistance Max engage distance.
|
-- @field #number engageMaxDistance Max engage distance.
|
||||||
-- @field #number refuelSystem Refuel type (boom or probe) for TANKER missions.
|
-- @field #number refuelSystem Refuel type (boom or probe) for TANKER missions.
|
||||||
--
|
--
|
||||||
@@ -161,6 +162,7 @@
|
|||||||
-- @field #number missionRange Mission range in meters. Used by LEGION classes (AIRWING, BRIGADE, ...).
|
-- @field #number missionRange Mission range in meters. Used by LEGION classes (AIRWING, BRIGADE, ...).
|
||||||
-- @field Core.Point#COORDINATE missionWaypointCoord Mission waypoint coordinate.
|
-- @field Core.Point#COORDINATE missionWaypointCoord Mission waypoint coordinate.
|
||||||
-- @field Core.Point#COORDINATE missionEgressCoord Mission egress waypoint coordinate.
|
-- @field Core.Point#COORDINATE missionEgressCoord Mission egress waypoint coordinate.
|
||||||
|
-- @field Core.Point#COORDINATE missionIngressCoord Mission Ingress waypoint coordinate.
|
||||||
-- @field #number missionWaypointRadius Random radius in meters.
|
-- @field #number missionWaypointRadius Random radius in meters.
|
||||||
-- @field #boolean legionReturn If `true`, assets return to their legion (default). If `false`, they will stay alive.
|
-- @field #boolean legionReturn If `true`, assets return to their legion (default). If `false`, they will stay alive.
|
||||||
--
|
--
|
||||||
@@ -239,6 +241,10 @@
|
|||||||
-- ## Bombing Carpet
|
-- ## Bombing Carpet
|
||||||
--
|
--
|
||||||
-- A carpet bombing mission can be created with the @{#AUFTRAG.NewBOMBCARPET}() function.
|
-- A carpet bombing mission can be created with the @{#AUFTRAG.NewBOMBCARPET}() function.
|
||||||
|
--
|
||||||
|
-- ## Strafing
|
||||||
|
--
|
||||||
|
-- A strafing mission can be created with the @{#AUFTRAG.NewSTRAFING}() function.
|
||||||
--
|
--
|
||||||
-- ## CAP
|
-- ## CAP
|
||||||
--
|
--
|
||||||
@@ -445,6 +451,7 @@ _AUFTRAGSNR=0
|
|||||||
-- @field #string CAPTUREZONE Capture zone mission.
|
-- @field #string CAPTUREZONE Capture zone mission.
|
||||||
-- @field #string NOTHING Nothing.
|
-- @field #string NOTHING Nothing.
|
||||||
-- @field #string PATROLRACETRACK Patrol Racetrack.
|
-- @field #string PATROLRACETRACK Patrol Racetrack.
|
||||||
|
-- @field #string STRAFING Strafing run.
|
||||||
AUFTRAG.Type={
|
AUFTRAG.Type={
|
||||||
ANTISHIP="Anti Ship",
|
ANTISHIP="Anti Ship",
|
||||||
AWACS="AWACS",
|
AWACS="AWACS",
|
||||||
@@ -491,6 +498,7 @@ AUFTRAG.Type={
|
|||||||
CAPTUREZONE="Capture Zone",
|
CAPTUREZONE="Capture Zone",
|
||||||
NOTHING="Nothing",
|
NOTHING="Nothing",
|
||||||
PATROLRACETRACK="Patrol Racetrack",
|
PATROLRACETRACK="Patrol Racetrack",
|
||||||
|
STRAFING="Strafing",
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Special task description.
|
--- Special task description.
|
||||||
@@ -1062,8 +1070,10 @@ end
|
|||||||
-- @param #number Time Time in seconds to stay. Default 300 seconds.
|
-- @param #number Time Time in seconds to stay. Default 300 seconds.
|
||||||
-- @param #number Speed Speed in knots to fly to the target coordinate. Default 150kn.
|
-- @param #number Speed Speed in knots to fly to the target coordinate. Default 150kn.
|
||||||
-- @param #number MissionAlt Altitude to fly towards the mission in feet AGL. Default 1000ft.
|
-- @param #number MissionAlt Altitude to fly towards the mission in feet AGL. Default 1000ft.
|
||||||
|
-- @param #boolean CombatLanding (Optional) If true, set the Combat Landing option.
|
||||||
|
-- @param #number DirectionAfterLand (Optional) Heading after landing in degrees.
|
||||||
-- @return #AUFTRAG self
|
-- @return #AUFTRAG self
|
||||||
function AUFTRAG:NewLANDATCOORDINATE(Coordinate, OuterRadius, InnerRadius, Time, Speed, MissionAlt)
|
function AUFTRAG:NewLANDATCOORDINATE(Coordinate, OuterRadius, InnerRadius, Time, Speed, MissionAlt, CombatLanding, DirectionAfterLand)
|
||||||
|
|
||||||
local mission=AUFTRAG:New(AUFTRAG.Type.LANDATCOORDINATE)
|
local mission=AUFTRAG:New(AUFTRAG.Type.LANDATCOORDINATE)
|
||||||
|
|
||||||
@@ -1071,6 +1081,8 @@ function AUFTRAG:NewLANDATCOORDINATE(Coordinate, OuterRadius, InnerRadius, Time,
|
|||||||
|
|
||||||
mission.stayTime = Time or 300
|
mission.stayTime = Time or 300
|
||||||
mission.stayAt = Coordinate
|
mission.stayAt = Coordinate
|
||||||
|
mission.combatLand = CombatLanding
|
||||||
|
mission.directionAfter = DirectionAfterLand
|
||||||
self:SetMissionSpeed(Speed or 150)
|
self:SetMissionSpeed(Speed or 150)
|
||||||
self:SetMissionAltitude(MissionAlt or 1000)
|
self:SetMissionAltitude(MissionAlt or 1000)
|
||||||
|
|
||||||
@@ -1707,15 +1719,16 @@ end
|
|||||||
-- @param #AUFTRAG self
|
-- @param #AUFTRAG self
|
||||||
-- @param Core.Point#COORDINATE Target The target coordinate. Can also be given as a GROUP, UNIT, STATIC or TARGET object.
|
-- @param Core.Point#COORDINATE Target The target coordinate. Can also be given as a GROUP, UNIT, STATIC or TARGET object.
|
||||||
-- @param #number Altitude Engage altitude in feet. Default 2000 ft.
|
-- @param #number Altitude Engage altitude in feet. Default 2000 ft.
|
||||||
|
-- @param #number EngageWeaponType Which weapon to use. Defaults to auto, ie ENUMS.WeaponFlag.Auto. See ENUMS.WeaponFlag for options.
|
||||||
-- @return #AUFTRAG self
|
-- @return #AUFTRAG self
|
||||||
function AUFTRAG:NewSTRIKE(Target, Altitude)
|
function AUFTRAG:NewSTRIKE(Target, Altitude, EngageWeaponType)
|
||||||
|
|
||||||
local mission=AUFTRAG:New(AUFTRAG.Type.STRIKE)
|
local mission=AUFTRAG:New(AUFTRAG.Type.STRIKE)
|
||||||
|
|
||||||
mission:_TargetFromObject(Target)
|
mission:_TargetFromObject(Target)
|
||||||
|
|
||||||
-- DCS Task options:
|
-- DCS Task options:
|
||||||
mission.engageWeaponType=ENUMS.WeaponFlag.Auto
|
mission.engageWeaponType=EngageWeaponType or ENUMS.WeaponFlag.Auto
|
||||||
mission.engageWeaponExpend=AI.Task.WeaponExpend.ALL
|
mission.engageWeaponExpend=AI.Task.WeaponExpend.ALL
|
||||||
mission.engageAltitude=UTILS.FeetToMeters(Altitude or 2000)
|
mission.engageAltitude=UTILS.FeetToMeters(Altitude or 2000)
|
||||||
|
|
||||||
@@ -1734,18 +1747,20 @@ function AUFTRAG:NewSTRIKE(Target, Altitude)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--- **[AIR]** Create a BOMBING mission. Flight will drop bombs a specified coordinate.
|
--- **[AIR]** Create a BOMBING mission. Flight will drop bombs a specified coordinate.
|
||||||
|
-- See [DCS task bombing](https://wiki.hoggitworld.com/view/DCS_task_bombing).
|
||||||
-- @param #AUFTRAG self
|
-- @param #AUFTRAG self
|
||||||
-- @param Core.Point#COORDINATE Target Target coordinate. Can also be specified as a GROUP, UNIT, STATIC or TARGET object.
|
-- @param Core.Point#COORDINATE Target Target coordinate. Can also be specified as a GROUP, UNIT, STATIC or TARGET object.
|
||||||
-- @param #number Altitude Engage altitude in feet. Default 25000 ft.
|
-- @param #number Altitude Engage altitude in feet. Default 25000 ft.
|
||||||
|
-- @param #number EngageWeaponType Which weapon to use. Defaults to auto, ie ENUMS.WeaponFlag.Auto. See ENUMS.WeaponFlag for options.
|
||||||
-- @return #AUFTRAG self
|
-- @return #AUFTRAG self
|
||||||
function AUFTRAG:NewBOMBING(Target, Altitude)
|
function AUFTRAG:NewBOMBING(Target, Altitude, EngageWeaponType)
|
||||||
|
|
||||||
local mission=AUFTRAG:New(AUFTRAG.Type.BOMBING)
|
local mission=AUFTRAG:New(AUFTRAG.Type.BOMBING)
|
||||||
|
|
||||||
mission:_TargetFromObject(Target)
|
mission:_TargetFromObject(Target)
|
||||||
|
|
||||||
-- DCS task options:
|
-- DCS task options:
|
||||||
mission.engageWeaponType=ENUMS.WeaponFlag.Auto
|
mission.engageWeaponType=EngageWeaponType or ENUMS.WeaponFlag.Auto
|
||||||
mission.engageWeaponExpend=AI.Task.WeaponExpend.ALL
|
mission.engageWeaponExpend=AI.Task.WeaponExpend.ALL
|
||||||
mission.engageAltitude=UTILS.FeetToMeters(Altitude or 25000)
|
mission.engageAltitude=UTILS.FeetToMeters(Altitude or 25000)
|
||||||
|
|
||||||
@@ -1767,9 +1782,47 @@ function AUFTRAG:NewBOMBING(Target, Altitude)
|
|||||||
return mission
|
return mission
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- **[AIR]** Create a STRAFING mission. Assigns a point on the ground for which the AI will do a strafing run with guns or rockets.
|
||||||
|
-- See [DCS task strafing](https://wiki.hoggitworld.com/view/DCS_task_strafing).
|
||||||
|
-- @param #AUFTRAG self
|
||||||
|
-- @param Core.Point#COORDINATE Target Target coordinate. Can also be specified as a GROUP, UNIT, STATIC or TARGET object.
|
||||||
|
-- @param #number Altitude Engage altitude in feet. Default 1000 ft.
|
||||||
|
-- @param #number Length The total length of the strafing target in meters. Default `nil`.
|
||||||
|
-- @return #AUFTRAG self
|
||||||
|
function AUFTRAG:NewSTRAFING(Target, Altitude, Length)
|
||||||
|
|
||||||
|
local mission=AUFTRAG:New(AUFTRAG.Type.STRAFING)
|
||||||
|
|
||||||
|
mission:_TargetFromObject(Target)
|
||||||
|
|
||||||
|
-- DCS task options:
|
||||||
|
mission.engageWeaponType=805337088 -- Corresponds to guns/cannons (805306368) + any rocket (30720). This is the default when selecting this task in the ME.
|
||||||
|
mission.engageWeaponExpend=AI.Task.WeaponExpend.ALL
|
||||||
|
mission.engageAltitude=UTILS.FeetToMeters(Altitude or 1000)
|
||||||
|
mission.engageLength=Length
|
||||||
|
|
||||||
|
-- Mission options:
|
||||||
|
mission.missionTask=ENUMS.MissionTask.GROUNDATTACK
|
||||||
|
mission.missionAltitude=mission.engageAltitude*0.8
|
||||||
|
mission.missionFraction=0.5
|
||||||
|
mission.optionROE=ENUMS.ROE.OpenFire
|
||||||
|
mission.optionROT=ENUMS.ROT.NoReaction -- No reaction is better.
|
||||||
|
|
||||||
|
-- Evaluate result after 5 min. We might need time until the bombs have dropped and targets have been detroyed.
|
||||||
|
mission.dTevaluate=5*60
|
||||||
|
|
||||||
|
mission.categories={AUFTRAG.Category.AIRCRAFT}
|
||||||
|
|
||||||
|
-- Get DCS task.
|
||||||
|
mission.DCStask=mission:GetDCSMissionTask()
|
||||||
|
|
||||||
|
return mission
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
--- **[AIR]** Create a BOMBRUNWAY mission.
|
--- **[AIR]** Create a BOMBRUNWAY mission.
|
||||||
-- @param #AUFTRAG self
|
-- @param #AUFTRAG self
|
||||||
-- @param Wrapper.Airbase#AIRBASE Airdrome The airbase to bomb. This must be an airdrome (not a FARP or ship) as these to not have a runway.
|
-- @param Wrapper.Airbase#AIRBASE Airdrome The airbase to bomb. This must be an airdrome (not a FARP or ship) as these do not have a runway.
|
||||||
-- @param #number Altitude Engage altitude in feet. Default 25000 ft.
|
-- @param #number Altitude Engage altitude in feet. Default 25000 ft.
|
||||||
-- @return #AUFTRAG self
|
-- @return #AUFTRAG self
|
||||||
function AUFTRAG:NewBOMBRUNWAY(Airdrome, Altitude)
|
function AUFTRAG:NewBOMBRUNWAY(Airdrome, Altitude)
|
||||||
@@ -1821,7 +1874,7 @@ function AUFTRAG:NewBOMBCARPET(Target, Altitude, CarpetLength)
|
|||||||
mission.engageWeaponType=ENUMS.WeaponFlag.Auto
|
mission.engageWeaponType=ENUMS.WeaponFlag.Auto
|
||||||
mission.engageWeaponExpend=AI.Task.WeaponExpend.ALL
|
mission.engageWeaponExpend=AI.Task.WeaponExpend.ALL
|
||||||
mission.engageAltitude=UTILS.FeetToMeters(Altitude or 25000)
|
mission.engageAltitude=UTILS.FeetToMeters(Altitude or 25000)
|
||||||
mission.engageCarpetLength=CarpetLength or 500
|
mission.engageLength=CarpetLength or 500
|
||||||
mission.engageAsGroup=false -- Looks like this must be false or the task is not executed. It is not available in the ME anyway but in the task of the mission file.
|
mission.engageAsGroup=false -- Looks like this must be false or the task is not executed. It is not available in the ME anyway but in the task of the mission file.
|
||||||
mission.engageDirection=nil -- This is also not available in the ME.
|
mission.engageDirection=nil -- This is also not available in the ME.
|
||||||
|
|
||||||
@@ -2105,7 +2158,11 @@ end
|
|||||||
|
|
||||||
]]
|
]]
|
||||||
|
|
||||||
--- **[GROUND, NAVAL]** Create an ARTY mission.
|
--- **[GROUND, NAVAL]** Create an ARTY mission ("Fire at point" task).
|
||||||
|
--
|
||||||
|
-- If the group has more than one weapon type supporting the "Fire at point" task, the employed weapon type can be set via the `AUFTRAG:SetWeaponType()` function.
|
||||||
|
--
|
||||||
|
-- **Note** that it is recommended to set the weapon range via the `OPSGROUP:AddWeaponRange()` function as this cannot be retrieved from the DCS API.
|
||||||
-- @param #AUFTRAG self
|
-- @param #AUFTRAG self
|
||||||
-- @param Core.Point#COORDINATE Target Center of the firing solution.
|
-- @param Core.Point#COORDINATE Target Center of the firing solution.
|
||||||
-- @param #number Nshots Number of shots to be fired. Default `#nil`.
|
-- @param #number Nshots Number of shots to be fired. Default `#nil`.
|
||||||
@@ -2128,6 +2185,7 @@ function AUFTRAG:NewARTY(Target, Nshots, Radius, Altitude)
|
|||||||
mission.optionAlarm=0
|
mission.optionAlarm=0
|
||||||
|
|
||||||
mission.missionFraction=0.0
|
mission.missionFraction=0.0
|
||||||
|
mission.missionWaypointRadius=0.0
|
||||||
|
|
||||||
-- Evaluate after 8 min.
|
-- Evaluate after 8 min.
|
||||||
mission.dTevaluate=8*60
|
mission.dTevaluate=8*60
|
||||||
@@ -2252,7 +2310,7 @@ function AUFTRAG:NewCAPTUREZONE(OpsZone, Coalition, Speed, Altitude, Formation)
|
|||||||
params.formation=Formation or "Off Road"
|
params.formation=Formation or "Off Road"
|
||||||
params.zone=mission:GetObjective()
|
params.zone=mission:GetObjective()
|
||||||
params.altitude=mission.missionAltitude
|
params.altitude=mission.missionAltitude
|
||||||
params.speed=mission.missionSpeed
|
params.speed=mission.missionSpeed and UTILS.KmphToMps(mission.missionSpeed) or nil
|
||||||
|
|
||||||
mission.DCStask.params=params
|
mission.DCStask.params=params
|
||||||
|
|
||||||
@@ -2302,7 +2360,7 @@ function AUFTRAG:NewGROUNDATTACK(Target, Speed, Formation)
|
|||||||
|
|
||||||
mission.DCStask=mission:GetDCSMissionTask()
|
mission.DCStask=mission:GetDCSMissionTask()
|
||||||
|
|
||||||
mission.DCStask.params.speed=Speed
|
mission.DCStask.params.speed=mission.missionSpeed and UTILS.KmphToMps(mission.missionSpeed) or nil
|
||||||
mission.DCStask.params.formation=Formation or ENUMS.Formation.Vehicle.Vee
|
mission.DCStask.params.formation=Formation or ENUMS.Formation.Vehicle.Vee
|
||||||
|
|
||||||
return mission
|
return mission
|
||||||
@@ -2611,6 +2669,8 @@ function AUFTRAG:NewFromTarget(Target, MissionType)
|
|||||||
mission=self:NewBOMBING(Target, Altitude)
|
mission=self:NewBOMBING(Target, Altitude)
|
||||||
elseif MissionType==AUFTRAG.Type.BOMBRUNWAY then
|
elseif MissionType==AUFTRAG.Type.BOMBRUNWAY then
|
||||||
mission=self:NewBOMBRUNWAY(Target, Altitude)
|
mission=self:NewBOMBRUNWAY(Target, Altitude)
|
||||||
|
elseif MissionType==AUFTRAG.Type.STRAFING then
|
||||||
|
mission=self:NewSTRAFING(Target, Altitude)
|
||||||
elseif MissionType==AUFTRAG.Type.CAS then
|
elseif MissionType==AUFTRAG.Type.CAS then
|
||||||
mission=self:NewCAS(ZONE_RADIUS:New(Target:GetName(),Target:GetVec2(),1000), Altitude, Speed, Target:GetAverageCoordinate(), Heading, Leg, TargetTypes)
|
mission=self:NewCAS(ZONE_RADIUS:New(Target:GetName(),Target:GetVec2(),1000), Altitude, Speed, Target:GetAverageCoordinate(), Heading, Leg, TargetTypes)
|
||||||
elseif MissionType==AUFTRAG.Type.CASENHANCED then
|
elseif MissionType==AUFTRAG.Type.CASENHANCED then
|
||||||
@@ -3429,7 +3489,7 @@ end
|
|||||||
|
|
||||||
--- Set Rules of Engagement (ROE) for this mission.
|
--- Set Rules of Engagement (ROE) for this mission.
|
||||||
-- @param #AUFTRAG self
|
-- @param #AUFTRAG self
|
||||||
-- @param #string roe Mission ROE.
|
-- @param #number roe Mission ROE, e.g. `ENUMS.ROE.ReturnFire` (whiche equals 3)
|
||||||
-- @return #AUFTRAG self
|
-- @return #AUFTRAG self
|
||||||
function AUFTRAG:SetROE(roe)
|
function AUFTRAG:SetROE(roe)
|
||||||
|
|
||||||
@@ -3441,7 +3501,7 @@ end
|
|||||||
|
|
||||||
--- Set Reaction on Threat (ROT) for this mission.
|
--- Set Reaction on Threat (ROT) for this mission.
|
||||||
-- @param #AUFTRAG self
|
-- @param #AUFTRAG self
|
||||||
-- @param #string rot Mission ROT.
|
-- @param #number rot Mission ROT, e.g. `ENUMS.ROT.NoReaction` (whiche equals 0)
|
||||||
-- @return #AUFTRAG self
|
-- @return #AUFTRAG self
|
||||||
function AUFTRAG:SetROT(rot)
|
function AUFTRAG:SetROT(rot)
|
||||||
|
|
||||||
@@ -4605,6 +4665,16 @@ function AUFTRAG:SetGroupWaypointCoordinate(opsgroup, coordinate)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- [Air] Set mission (ingress) waypoint coordinate for FLIGHT group.
|
||||||
|
-- @param #AUFTRAG self
|
||||||
|
-- @param Core.Point#COORDINATE coordinate Waypoint Coordinate.
|
||||||
|
-- @return #AUFTRAG self
|
||||||
|
function AUFTRAG:SetIngressCoordinate(coordinate)
|
||||||
|
self.missionIngressCoord = coordinate
|
||||||
|
self.missionIngressCoordAlt = UTILS.MetersToFeet(coordinate.y) or 10000
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- Get mission (ingress) waypoint coordinate of OPS group
|
--- Get mission (ingress) waypoint coordinate of OPS group
|
||||||
-- @param #AUFTRAG self
|
-- @param #AUFTRAG self
|
||||||
-- @param Ops.OpsGroup#OPSGROUP opsgroup The OPS group.
|
-- @param Ops.OpsGroup#OPSGROUP opsgroup The OPS group.
|
||||||
@@ -5660,7 +5730,7 @@ function AUFTRAG:GetMissionTypesText(MissionTypes)
|
|||||||
return text
|
return text
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Set the mission waypoint coordinate where the mission is executed. Note that altitude is set via `:SetMissionAltitude`.
|
--- [NON-AIR] Set the mission waypoint coordinate from where the mission is executed. Note that altitude is set via `:SetMissionAltitude`.
|
||||||
-- @param #AUFTRAG self
|
-- @param #AUFTRAG self
|
||||||
-- @param Core.Point#COORDINATE Coordinate Coordinate where the mission is executed.
|
-- @param Core.Point#COORDINATE Coordinate Coordinate where the mission is executed.
|
||||||
-- @return #AUFTRAG self
|
-- @return #AUFTRAG self
|
||||||
@@ -5688,8 +5758,9 @@ end
|
|||||||
-- @param #AUFTRAG self
|
-- @param #AUFTRAG self
|
||||||
-- @param Core.Point#COORDINATE Coordinate Egrees coordinate.
|
-- @param Core.Point#COORDINATE Coordinate Egrees coordinate.
|
||||||
-- @param #number Altitude (Optional) Altitude in feet. Default is y component of coordinate.
|
-- @param #number Altitude (Optional) Altitude in feet. Default is y component of coordinate.
|
||||||
|
-- @param #number Speed (Optional) Speed in knots to reach this waypoint. Defaults to mission speed.
|
||||||
-- @return #AUFTRAG self
|
-- @return #AUFTRAG self
|
||||||
function AUFTRAG:SetMissionEgressCoord(Coordinate, Altitude)
|
function AUFTRAG:SetMissionEgressCoord(Coordinate, Altitude, Speed)
|
||||||
|
|
||||||
-- Obviously a zone was passed. We get the coordinate.
|
-- Obviously a zone was passed. We get the coordinate.
|
||||||
if Coordinate:IsInstanceOf("ZONE_BASE") then
|
if Coordinate:IsInstanceOf("ZONE_BASE") then
|
||||||
@@ -5700,7 +5771,64 @@ function AUFTRAG:SetMissionEgressCoord(Coordinate, Altitude)
|
|||||||
|
|
||||||
if Altitude then
|
if Altitude then
|
||||||
self.missionEgressCoord.y=UTILS.FeetToMeters(Altitude)
|
self.missionEgressCoord.y=UTILS.FeetToMeters(Altitude)
|
||||||
|
self.missionEgressCoordAlt = UTILS.FeetToMeters(Altitude)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
self.missionEgressCoordSpeed=Speed and Speed or nil
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [Air] Set the mission ingress coordinate. This is the coordinate where the assigned group will fly before the actual mission coordinate.
|
||||||
|
-- @param #AUFTRAG self
|
||||||
|
-- @param Core.Point#COORDINATE Coordinate Ingrees coordinate.
|
||||||
|
-- @param #number Altitude (Optional) Altitude in feet. Default is y component of coordinate.
|
||||||
|
-- @param #number Speed (Optional) Speed in knots to reach this waypoint. Defaults to mission speed.
|
||||||
|
-- @return #AUFTRAG self
|
||||||
|
function AUFTRAG:SetMissionIngressCoord(Coordinate, Altitude, Speed)
|
||||||
|
|
||||||
|
-- Obviously a zone was passed. We get the coordinate.
|
||||||
|
if Coordinate:IsInstanceOf("ZONE_BASE") then
|
||||||
|
Coordinate=Coordinate:GetCoordinate()
|
||||||
|
end
|
||||||
|
|
||||||
|
self.missionIngressCoord=Coordinate
|
||||||
|
|
||||||
|
if Altitude then
|
||||||
|
self.missionIngressCoord.y=UTILS.FeetToMeters(Altitude)
|
||||||
|
self.missionIngressCoordAlt = UTILS.FeetToMeters(Altitude or 10000)
|
||||||
|
end
|
||||||
|
|
||||||
|
self.missionIngressCoordSpeed=Speed and Speed or nil
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- [Air] Set the mission holding coordinate. This is the coordinate where the assigned group will fly before the actual mission execution starts. Do not forget to add a push condition, too!
|
||||||
|
-- @param #AUFTRAG self
|
||||||
|
-- @param Core.Point#COORDINATE Coordinate Holding coordinate.
|
||||||
|
-- @param #number Altitude (Optional) Altitude in feet. Default is y component of coordinate.
|
||||||
|
-- @param #number Speed (Optional) Speed in knots to reach this waypoint and hold there. Defaults to mission speed.
|
||||||
|
-- @param #number Duration (Optional) Duration in seconds on how long to hold, defaults to 15 minutes. Mission continues if either a push condition is met or the time is up.
|
||||||
|
-- @return #AUFTRAG self
|
||||||
|
function AUFTRAG:SetMissionHoldingCoord(Coordinate, Altitude, Speed, Duration)
|
||||||
|
|
||||||
|
-- Obviously a zone was passed. We get the coordinate.
|
||||||
|
if Coordinate:IsInstanceOf("ZONE_BASE") then
|
||||||
|
Coordinate=Coordinate:GetCoordinate()
|
||||||
|
end
|
||||||
|
|
||||||
|
self.missionHoldingCoord=Coordinate
|
||||||
|
self.missionHoldingDuration=Duration or 900
|
||||||
|
|
||||||
|
if Altitude then
|
||||||
|
self.missionHoldingCoord.y=UTILS.FeetToMeters(Altitude)
|
||||||
|
self.missionHoldingCoordAlt = UTILS.FeetToMeters(Altitude or 10000)
|
||||||
|
end
|
||||||
|
|
||||||
|
self.missionHoldingCoordSpeed=Speed and Speed or nil
|
||||||
|
|
||||||
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Get the mission egress coordinate if this was defined.
|
--- Get the mission egress coordinate if this was defined.
|
||||||
@@ -5710,6 +5838,20 @@ function AUFTRAG:GetMissionEgressCoord()
|
|||||||
return self.missionEgressCoord
|
return self.missionEgressCoord
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Get the mission ingress coordinate if this was defined.
|
||||||
|
-- @param #AUFTRAG self
|
||||||
|
-- @return Core.Point#COORDINATE Coordinate Coordinate or nil.
|
||||||
|
function AUFTRAG:GetMissionIngressCoord()
|
||||||
|
return self.missionIngressCoord
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Get the mission holding coordinate if this was defined.
|
||||||
|
-- @param #AUFTRAG self
|
||||||
|
-- @return Core.Point#COORDINATE Coordinate Coordinate or nil.
|
||||||
|
function AUFTRAG:GetMissionHoldingCoord()
|
||||||
|
return self.missionHoldingCoord
|
||||||
|
end
|
||||||
|
|
||||||
--- Get coordinate which was set as mission waypoint coordinate.
|
--- Get coordinate which was set as mission waypoint coordinate.
|
||||||
-- @param #AUFTRAG self
|
-- @param #AUFTRAG self
|
||||||
-- @return Core.Point#COORDINATE Coordinate where the mission is executed or `#nil`.
|
-- @return Core.Point#COORDINATE Coordinate where the mission is executed or `#nil`.
|
||||||
@@ -5744,10 +5886,27 @@ function AUFTRAG:GetMissionWaypointCoord(group, randomradius, surfacetypes)
|
|||||||
end
|
end
|
||||||
return coord
|
return coord
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local coord=group:GetCoordinate()
|
||||||
|
|
||||||
|
-- Check if an ingress or holding coord has been explicitly set.
|
||||||
|
if self.missionHoldingCoord then
|
||||||
|
coord=self.missionHoldingCoord
|
||||||
|
if self.missionHoldingCoorddAlt then
|
||||||
|
coord:SetAltitude(self.missionHoldingCoordAlt, true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if self.missionIngressCoord then
|
||||||
|
coord=self.missionIngressCoord
|
||||||
|
if self.missionIngressCoordAlt then
|
||||||
|
coord:SetAltitude(self.missionIngressCoordAlt, true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- Create waypoint coordinate half way between us and the target.
|
-- Create waypoint coordinate half way between us and the target.
|
||||||
local waypointcoord=COORDINATE:New(0,0,0)
|
local waypointcoord=COORDINATE:New(0,0,0)
|
||||||
local coord=group:GetCoordinate()
|
|
||||||
if coord then
|
if coord then
|
||||||
waypointcoord=coord:GetIntermediateCoordinate(self:GetTargetCoordinate(), self.missionFraction)
|
waypointcoord=coord:GetIntermediateCoordinate(self:GetTargetCoordinate(), self.missionFraction)
|
||||||
else
|
else
|
||||||
@@ -5952,6 +6111,16 @@ function AUFTRAG:GetDCSMissionTask()
|
|||||||
local DCStask=CONTROLLABLE.TaskBombing(nil, self:GetTargetVec2(), self.engageAsGroup, self.engageWeaponExpend, self.engageQuantity, self.engageDirection, self.engageAltitude, self.engageWeaponType, Divebomb)
|
local DCStask=CONTROLLABLE.TaskBombing(nil, self:GetTargetVec2(), self.engageAsGroup, self.engageWeaponExpend, self.engageQuantity, self.engageDirection, self.engageAltitude, self.engageWeaponType, Divebomb)
|
||||||
|
|
||||||
table.insert(DCStasks, DCStask)
|
table.insert(DCStasks, DCStask)
|
||||||
|
|
||||||
|
elseif self.type==AUFTRAG.Type.STRAFING then
|
||||||
|
|
||||||
|
----------------------
|
||||||
|
-- STRAFING Mission --
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
local DCStask=CONTROLLABLE.TaskStrafing(nil,self:GetTargetVec2(), self.engageQuantity, self.engageLength,self.engageWeaponType,self.engageWeaponExpend,self.engageDirection,self.engageAsGroup)
|
||||||
|
|
||||||
|
table.insert(DCStasks, DCStask)
|
||||||
|
|
||||||
elseif self.type==AUFTRAG.Type.BOMBRUNWAY then
|
elseif self.type==AUFTRAG.Type.BOMBRUNWAY then
|
||||||
|
|
||||||
@@ -5969,7 +6138,7 @@ function AUFTRAG:GetDCSMissionTask()
|
|||||||
-- BOMBCARPET Mission --
|
-- BOMBCARPET Mission --
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
local DCStask=CONTROLLABLE.TaskCarpetBombing(nil, self:GetTargetVec2(), self.engageAsGroup, self.engageWeaponExpend, self.engageQuantity, self.engageDirection, self.engageAltitude, self.engageWeaponType, self.engageCarpetLength)
|
local DCStask=CONTROLLABLE.TaskCarpetBombing(nil, self:GetTargetVec2(), self.engageAsGroup, self.engageWeaponExpend, self.engageQuantity, self.engageDirection, self.engageAltitude, self.engageWeaponType, self.engageLength)
|
||||||
|
|
||||||
table.insert(DCStasks, DCStask)
|
table.insert(DCStasks, DCStask)
|
||||||
|
|
||||||
@@ -6037,7 +6206,7 @@ function AUFTRAG:GetDCSMissionTask()
|
|||||||
local param={}
|
local param={}
|
||||||
param.zone=self:GetObjective()
|
param.zone=self:GetObjective()
|
||||||
param.altitude=self.missionAltitude
|
param.altitude=self.missionAltitude
|
||||||
param.speed=self.missionSpeed
|
param.speed=self.missionSpeed and UTILS.KmphToMps(self.missionSpeed) or nil
|
||||||
|
|
||||||
DCStask.params=param
|
DCStask.params=param
|
||||||
|
|
||||||
@@ -6117,7 +6286,7 @@ function AUFTRAG:GetDCSMissionTask()
|
|||||||
local param={}
|
local param={}
|
||||||
param.target=self.engageTarget
|
param.target=self.engageTarget
|
||||||
param.altitude=self.missionAltitude
|
param.altitude=self.missionAltitude
|
||||||
param.speed=self.missionSpeed
|
param.speed=self.missionSpeed and UTILS.KmphToMps(self.missionSpeed) or nil
|
||||||
param.lastindex=nil
|
param.lastindex=nil
|
||||||
|
|
||||||
DCStask.params=param
|
DCStask.params=param
|
||||||
@@ -6290,7 +6459,7 @@ function AUFTRAG:GetDCSMissionTask()
|
|||||||
local param={}
|
local param={}
|
||||||
param.zone=self:GetObjective()
|
param.zone=self:GetObjective()
|
||||||
param.altitude=self.missionAltitude
|
param.altitude=self.missionAltitude
|
||||||
param.speed=self.missionSpeed
|
param.speed=self.missionSpeed and UTILS.KmphToMps(self.missionSpeed) or nil
|
||||||
|
|
||||||
DCStask.params=param
|
DCStask.params=param
|
||||||
|
|
||||||
@@ -6326,7 +6495,7 @@ function AUFTRAG:GetDCSMissionTask()
|
|||||||
local param={}
|
local param={}
|
||||||
param.zone=self:GetObjective()
|
param.zone=self:GetObjective()
|
||||||
param.altitude=self.missionAltitude
|
param.altitude=self.missionAltitude
|
||||||
param.speed=self.missionSpeed
|
param.speed=self.missionSpeed and UTILS.KmphToMps(self.missionSpeed) or nil
|
||||||
|
|
||||||
DCStask.params=param
|
DCStask.params=param
|
||||||
|
|
||||||
@@ -6346,7 +6515,7 @@ function AUFTRAG:GetDCSMissionTask()
|
|||||||
local param={}
|
local param={}
|
||||||
param.target=self:GetTargetData()
|
param.target=self:GetTargetData()
|
||||||
param.action="Wedge"
|
param.action="Wedge"
|
||||||
param.speed=self.missionSpeed
|
param.speed=self.missionSpeed and UTILS.KmphToMps(self.missionSpeed) or nil
|
||||||
|
|
||||||
DCStask.params=param
|
DCStask.params=param
|
||||||
|
|
||||||
@@ -6492,8 +6661,7 @@ function AUFTRAG:GetDCSMissionTask()
|
|||||||
|
|
||||||
local DCStask={}
|
local DCStask={}
|
||||||
local Vec2 = self.stayAt:GetVec2()
|
local Vec2 = self.stayAt:GetVec2()
|
||||||
local DCStask = CONTROLLABLE.TaskLandAtVec2(nil,Vec2,self.stayTime)
|
local DCStask = CONTROLLABLE.TaskLandAtVec2(nil,Vec2,self.stayTime, self.combatLand, self.directionAfter)
|
||||||
|
|
||||||
table.insert(DCStasks, DCStask)
|
table.insert(DCStasks, DCStask)
|
||||||
|
|
||||||
elseif self.type==AUFTRAG.Type.ONGUARD or self.type==AUFTRAG.Type.ARMOREDGUARD then
|
elseif self.type==AUFTRAG.Type.ONGUARD or self.type==AUFTRAG.Type.ARMOREDGUARD then
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
-- ===
|
-- ===
|
||||||
--
|
--
|
||||||
-- ### Author: **applevangelist**
|
-- ### Author: **applevangelist**
|
||||||
-- @date Last Update Jan 2024
|
-- @date Last Update Jan 2025
|
||||||
-- @module Ops.AWACS
|
-- @module Ops.AWACS
|
||||||
-- @image OPS_AWACS.jpg
|
-- @image OPS_AWACS.jpg
|
||||||
|
|
||||||
@@ -122,6 +122,7 @@ do
|
|||||||
-- @field #number TacticalModulation
|
-- @field #number TacticalModulation
|
||||||
-- @field #number TacticalInterval
|
-- @field #number TacticalInterval
|
||||||
-- @field Core.Set#SET_GROUP DetectionSet
|
-- @field Core.Set#SET_GROUP DetectionSet
|
||||||
|
-- @field #number MaxMissionRange
|
||||||
-- @extends Core.Fsm#FSM
|
-- @extends Core.Fsm#FSM
|
||||||
|
|
||||||
|
|
||||||
@@ -183,7 +184,7 @@ do
|
|||||||
--
|
--
|
||||||
-- Add Escorts Squad (recommended, optional)
|
-- Add Escorts Squad (recommended, optional)
|
||||||
--
|
--
|
||||||
-- local Squad_Two = SQUADRON:New("Escorts",4,"Escorts North")
|
-- local Squad_Two = SQUADRON:New("Escorts",4,"Escorts North") -- taking a template with 2 planes here, will result in a group of 2 escorts which can fly in formation escorting the AWACS.
|
||||||
-- Squad_Two:AddMissionCapability({AUFTRAG.Type.ESCORT})
|
-- Squad_Two:AddMissionCapability({AUFTRAG.Type.ESCORT})
|
||||||
-- Squad_Two:SetFuelLowRefuel(true)
|
-- Squad_Two:SetFuelLowRefuel(true)
|
||||||
-- Squad_Two:SetFuelLowThreshold(0.3)
|
-- Squad_Two:SetFuelLowThreshold(0.3)
|
||||||
@@ -231,8 +232,8 @@ do
|
|||||||
-- -- set up in the mission editor with a late activated helo named "Rock#ZONE_POLYGON". Note this also sets the BullsEye to be referenced as "Rock".
|
-- -- set up in the mission editor with a late activated helo named "Rock#ZONE_POLYGON". Note this also sets the BullsEye to be referenced as "Rock".
|
||||||
-- -- The CAP station zone is called "Fremont". We will be on 255 AM.
|
-- -- The CAP station zone is called "Fremont". We will be on 255 AM.
|
||||||
-- local testawacs = AWACS:New("AWACS North",AwacsAW,"blue",AIRBASE.Caucasus.Kutaisi,"Awacs Orbit",ZONE:FindByName("Rock"),"Fremont",255,radio.modulation.AM )
|
-- local testawacs = AWACS:New("AWACS North",AwacsAW,"blue",AIRBASE.Caucasus.Kutaisi,"Awacs Orbit",ZONE:FindByName("Rock"),"Fremont",255,radio.modulation.AM )
|
||||||
-- -- set two escorts
|
-- -- set one escort group; this example has two units in the template group, so they can fly a nice formation.
|
||||||
-- testawacs:SetEscort(2)
|
-- testawacs:SetEscort(1,ENUMS.Formation.FixedWing.FingerFour.Group,{x=-500,y=50,z=500},45)
|
||||||
-- -- Callsign will be "Focus". We'll be a Angels 30, doing 300 knots, orbit leg to 88deg with a length of 25nm.
|
-- -- Callsign will be "Focus". We'll be a Angels 30, doing 300 knots, orbit leg to 88deg with a length of 25nm.
|
||||||
-- testawacs:SetAwacsDetails(CALLSIGN.AWACS.Focus,1,30,300,88,25)
|
-- testawacs:SetAwacsDetails(CALLSIGN.AWACS.Focus,1,30,300,88,25)
|
||||||
-- -- Set up SRS on port 5010 - change the below to your path and port
|
-- -- Set up SRS on port 5010 - change the below to your path and port
|
||||||
@@ -508,7 +509,7 @@ do
|
|||||||
-- @field #AWACS
|
-- @field #AWACS
|
||||||
AWACS = {
|
AWACS = {
|
||||||
ClassName = "AWACS", -- #string
|
ClassName = "AWACS", -- #string
|
||||||
version = "0.2.64", -- #string
|
version = "0.2.71", -- #string
|
||||||
lid = "", -- #string
|
lid = "", -- #string
|
||||||
coalition = coalition.side.BLUE, -- #number
|
coalition = coalition.side.BLUE, -- #number
|
||||||
coalitiontxt = "blue", -- #string
|
coalitiontxt = "blue", -- #string
|
||||||
@@ -605,6 +606,7 @@ AWACS = {
|
|||||||
TacticalModulation = radio.modulation.AM,
|
TacticalModulation = radio.modulation.AM,
|
||||||
TacticalInterval = 120,
|
TacticalInterval = 120,
|
||||||
DetectionSet = nil,
|
DetectionSet = nil,
|
||||||
|
MaxMissionRange = 125,
|
||||||
}
|
}
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -935,7 +937,7 @@ AWACS.TaskStatus = {
|
|||||||
--@field #boolean FromAI
|
--@field #boolean FromAI
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- TODO-List 0.2.53
|
-- TODO-List 0.2.54
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
--
|
--
|
||||||
-- DONE - WIP - Player tasking, VID
|
-- DONE - WIP - Player tasking, VID
|
||||||
@@ -1572,6 +1574,15 @@ function AWACS:SetLocale(Locale)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- [User] Set the max mission range flights can be away from their home base.
|
||||||
|
-- @param #AWACS self
|
||||||
|
-- @param #number NM Distance in nautical miles
|
||||||
|
-- @return #AWACS self
|
||||||
|
function AWACS:SetMaxMissionRange(NM)
|
||||||
|
self.MaxMissionRange = NM or 125
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- [User] Add additional frequency and modulation for AWACS SRS output.
|
--- [User] Add additional frequency and modulation for AWACS SRS output.
|
||||||
-- @param #AWACS self
|
-- @param #AWACS self
|
||||||
-- @param #number Frequency The frequency to add, e.g. 132.5
|
-- @param #number Frequency The frequency to add, e.g. 132.5
|
||||||
@@ -1762,7 +1773,7 @@ function AWACS:_EventHandler(EventData)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if Event.id == EVENTS.PlayerLeaveUnit then --player left unit
|
if Event.id == EVENTS.PlayerLeaveUnit and Event.IniGroupName then --player left unit
|
||||||
-- check known player?
|
-- check known player?
|
||||||
self:T("Player group left unit: " .. Event.IniGroupName)
|
self:T("Player group left unit: " .. Event.IniGroupName)
|
||||||
self:T("Player name left: " .. Event.IniPlayerName)
|
self:T("Player name left: " .. Event.IniPlayerName)
|
||||||
@@ -2158,9 +2169,12 @@ end
|
|||||||
|
|
||||||
--- [User] Set AWACS Escorts Template
|
--- [User] Set AWACS Escorts Template
|
||||||
-- @param #AWACS self
|
-- @param #AWACS self
|
||||||
-- @param #number EscortNumber Number of fighther planes to accompany this AWACS. 0 or nil means no escorts.
|
-- @param #number EscortNumber Number of fighther plane GROUPs to accompany this AWACS. 0 or nil means no escorts. If you want >1 plane in an escort group, you can either set the respective squadron grouping to the desired number, or use a template for escorts with >1 unit.
|
||||||
|
-- @param #number Formation Formation the escort should take (if more than one plane), e.g. `ENUMS.Formation.FixedWing.FingerFour.Group`. Formation is used on GROUP level, multiple groups of one unit will NOT conform to this formation.
|
||||||
|
-- @param #table OffsetVector Offset the escorts should fly behind the AWACS, given as table, distance in meters, e.g. `{x=-500,y=0,z=500}` - 500m behind (negative value) and to the right (negative for left), no vertical separation (positive over, negative under the AWACS flight). For multiple groups, the vectors will be slightly changed to avoid collisions.
|
||||||
|
-- @param #number EscortEngageMaxDistance Escorts engage air targets max this NM away, defaults to 45NM.
|
||||||
-- @return #AWACS self
|
-- @return #AWACS self
|
||||||
function AWACS:SetEscort(EscortNumber)
|
function AWACS:SetEscort(EscortNumber,Formation,OffsetVector,EscortEngageMaxDistance)
|
||||||
self:T(self.lid.."SetEscort")
|
self:T(self.lid.."SetEscort")
|
||||||
if EscortNumber and EscortNumber > 0 then
|
if EscortNumber and EscortNumber > 0 then
|
||||||
self.HasEscorts = true
|
self.HasEscorts = true
|
||||||
@@ -2169,6 +2183,9 @@ function AWACS:SetEscort(EscortNumber)
|
|||||||
self.HasEscorts = false
|
self.HasEscorts = false
|
||||||
self.EscortNumber = 0
|
self.EscortNumber = 0
|
||||||
end
|
end
|
||||||
|
self.EscortFormation = Formation
|
||||||
|
self.OffsetVec = OffsetVector or {x=500,y=100,z=500}
|
||||||
|
self.EscortEngageMaxDistance = EscortEngageMaxDistance or 45
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -2223,11 +2240,26 @@ function AWACS:_StartEscorts(Shiftchange)
|
|||||||
local group = AwacsFG:GetGroup()
|
local group = AwacsFG:GetGroup()
|
||||||
|
|
||||||
local timeonstation = (self.EscortsTimeOnStation + self.ShiftChangeTime) * 3600 -- hours to seconds
|
local timeonstation = (self.EscortsTimeOnStation + self.ShiftChangeTime) * 3600 -- hours to seconds
|
||||||
|
local OffsetX = 500
|
||||||
|
local OffsetY = 500
|
||||||
|
local OffsetZ = 500
|
||||||
|
if self.OffsetVec then
|
||||||
|
OffsetX = self.OffsetVec.x or 500
|
||||||
|
OffsetY = self.OffsetVec.y or 500
|
||||||
|
OffsetZ = self.OffsetVec.z or 500
|
||||||
|
end
|
||||||
|
|
||||||
for i=1,self.EscortNumber do
|
for i=1,self.EscortNumber do
|
||||||
-- every
|
-- every
|
||||||
local escort = AUFTRAG:NewESCORT(group, {x= -100*((i + (i%2))/2), y=0, z=(100 + 100*((i + (i%2))/2))*(-1)^i},45,{"Air"})
|
local escort = AUFTRAG:NewESCORT(group, {x= OffsetX*((i + (i%2))/2), y=OffsetY*((i + (i%2))/2), z=(OffsetZ + OffsetZ*((i + (i%2))/2))*(-1)^i},self.EscortEngageMaxDistance,{"Air"})
|
||||||
escort:SetRequiredAssets(1)
|
--local escort = AUFTRAG:NewESCORT(group,self.OffsetVec,self.EscortEngageMaxDistance,{"Air"})
|
||||||
|
--escort:SetRequiredAssets(self.EscortNumber)
|
||||||
escort:SetTime(nil,timeonstation)
|
escort:SetTime(nil,timeonstation)
|
||||||
|
if self.Escortformation then
|
||||||
|
escort:SetFormation(self.Escortformation)
|
||||||
|
end
|
||||||
|
escort:SetMissionRange(self.MaxMissionRange)
|
||||||
|
|
||||||
self.AirWing:AddMission(escort)
|
self.AirWing:AddMission(escort)
|
||||||
self.CatchAllMissions[#self.CatchAllMissions+1] = escort
|
self.CatchAllMissions[#self.CatchAllMissions+1] = escort
|
||||||
|
|
||||||
@@ -2434,7 +2466,7 @@ function AWACS:_GetCallSign(Group,GID, IsPlayer)
|
|||||||
|
|
||||||
local callsign = "Ghost 1"
|
local callsign = "Ghost 1"
|
||||||
if Group and Group:IsAlive() then
|
if Group and Group:IsAlive() then
|
||||||
callsign = Group:GetCustomCallSign(self.callsignshort,self.keepnumber,self.callsignTranslations)
|
callsign = Group:GetCustomCallSign(self.callsignshort,self.keepnumber,self.callsignTranslations,self.callsignCustomFunc,self.callsignCustomArgs)
|
||||||
end
|
end
|
||||||
return callsign
|
return callsign
|
||||||
end
|
end
|
||||||
@@ -2443,10 +2475,12 @@ end
|
|||||||
-- @param #AWACS self
|
-- @param #AWACS self
|
||||||
-- @param #boolean ShortCallsign If true, only call out the major flight number
|
-- @param #boolean ShortCallsign If true, only call out the major flight number
|
||||||
-- @param #boolean Keepnumber If true, keep the **customized callsign** in the #GROUP name as-is, no amendments or numbers.
|
-- @param #boolean Keepnumber If true, keep the **customized callsign** in the #GROUP name as-is, no amendments or numbers.
|
||||||
-- @param #table CallsignTranslations (optional) Table to translate between DCS standard callsigns and bespoke ones. Does not apply if using customized
|
-- @param #table CallsignTranslations (Optional) Table to translate between DCS standard callsigns and bespoke ones. Does not apply if using customized.
|
||||||
-- callsigns from playername or group name.
|
-- callsigns from playername or group name.
|
||||||
|
-- @param #func CallsignCustomFunc (Optional) For player names only(!). If given, this function will return the callsign. Needs to take the groupname and the playername as first two arguments.
|
||||||
|
-- @param #arg ... (Optional) Comma separated arguments to add to the custom function call after groupname and playername.
|
||||||
-- @return #AWACS self
|
-- @return #AWACS self
|
||||||
function AWACS:SetCallSignOptions(ShortCallsign,Keepnumber,CallsignTranslations)
|
function AWACS:SetCallSignOptions(ShortCallsign,Keepnumber,CallsignTranslations,CallsignCustomFunc,...)
|
||||||
if not ShortCallsign or ShortCallsign == false then
|
if not ShortCallsign or ShortCallsign == false then
|
||||||
self.callsignshort = false
|
self.callsignshort = false
|
||||||
else
|
else
|
||||||
@@ -2454,6 +2488,8 @@ function AWACS:SetCallSignOptions(ShortCallsign,Keepnumber,CallsignTranslations)
|
|||||||
end
|
end
|
||||||
self.keepnumber = Keepnumber or false
|
self.keepnumber = Keepnumber or false
|
||||||
self.callsignTranslations = CallsignTranslations
|
self.callsignTranslations = CallsignTranslations
|
||||||
|
self.callsignCustomFunc = CallsignCustomFunc
|
||||||
|
self.callsignCustomArgs = arg or {}
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -3626,7 +3662,7 @@ function AWACS:_CheckIn(Group)
|
|||||||
managedgroup.LastTasking = timer.getTime()
|
managedgroup.LastTasking = timer.getTime()
|
||||||
|
|
||||||
GID = managedgroup.GID
|
GID = managedgroup.GID
|
||||||
self.ManagedGrps[self.ManagedGrpID]=managedgroup
|
self.ManagedGrps[self.ManagedGrpID]=managedgroup
|
||||||
|
|
||||||
local alphacheckbulls = self:_ToStringBULLS(Group:GetCoordinate())
|
local alphacheckbulls = self:_ToStringBULLS(Group:GetCoordinate())
|
||||||
local alphacheckbullstts = self:_ToStringBULLS(Group:GetCoordinate(),false,true)
|
local alphacheckbullstts = self:_ToStringBULLS(Group:GetCoordinate(),false,true)
|
||||||
@@ -3893,6 +3929,12 @@ function AWACS:_SetClientMenus()
|
|||||||
checkin = checkin,
|
checkin = checkin,
|
||||||
}
|
}
|
||||||
self.clientmenus:Push(menus,cgrpname)
|
self.clientmenus:Push(menus,cgrpname)
|
||||||
|
-- catch errors - when this entry is built we should NOT have a managed entry
|
||||||
|
local GID,hasentry = self:_GetManagedGrpID(cgrp)
|
||||||
|
if hasentry then
|
||||||
|
-- this user is checked in but has the check in entry ... not good.
|
||||||
|
self:_CheckOut(cgrp,GID,true)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
@@ -5585,6 +5627,12 @@ function AWACS:_ThreatRangeCall(GID,Contact)
|
|||||||
local grptxt = self.gettext:GetEntry("GROUP",self.locale)
|
local grptxt = self.gettext:GetEntry("GROUP",self.locale)
|
||||||
local thrt = self.gettext:GetEntry("THREAT",self.locale)
|
local thrt = self.gettext:GetEntry("THREAT",self.locale)
|
||||||
local text = string.format("%s. %s. %s %s, %s. %s",self.callsigntxt,pilotcallsign,contacttag,grptxt, thrt, BRATExt)
|
local text = string.format("%s. %s. %s %s, %s. %s",self.callsigntxt,pilotcallsign,contacttag,grptxt, thrt, BRATExt)
|
||||||
|
-- DONE MS TTS - fix spelling out B-R-A in this case
|
||||||
|
if string.find(text,"BRAA",1,true) then
|
||||||
|
text = string.gsub(text,"BRAA","brah")
|
||||||
|
elseif string.find(text,"BRA",1,true) then
|
||||||
|
text = string.gsub(text,"BRA","brah")
|
||||||
|
end
|
||||||
if IsSub == false then
|
if IsSub == false then
|
||||||
self:_NewRadioEntry(text,text,GID,true,self.debug,true,false,true)
|
self:_NewRadioEntry(text,text,GID,true,self.debug,true,false,true)
|
||||||
end
|
end
|
||||||
@@ -5733,7 +5781,7 @@ function AWACS:_AssignPilotToTarget(Pilots,Targets)
|
|||||||
local intercept = AUFTRAG:NewINTERCEPT(Target.Target)
|
local intercept = AUFTRAG:NewINTERCEPT(Target.Target)
|
||||||
intercept:SetWeaponExpend(AI.Task.WeaponExpend.ALL)
|
intercept:SetWeaponExpend(AI.Task.WeaponExpend.ALL)
|
||||||
intercept:SetWeaponType(ENUMS.WeaponFlag.Auto)
|
intercept:SetWeaponType(ENUMS.WeaponFlag.Auto)
|
||||||
|
intercept:SetMissionRange(self.MaxMissionRange)
|
||||||
-- TODO
|
-- TODO
|
||||||
-- now this is going to be interesting...
|
-- now this is going to be interesting...
|
||||||
-- Check if the target left the "hot" area or is dead already
|
-- Check if the target left the "hot" area or is dead already
|
||||||
@@ -5781,6 +5829,7 @@ function AWACS:_AssignPilotToTarget(Pilots,Targets)
|
|||||||
AnchorSpeed = UTILS.KnotsToAltKIAS(AnchorSpeed,Angels)
|
AnchorSpeed = UTILS.KnotsToAltKIAS(AnchorSpeed,Angels)
|
||||||
local Anchor = self.AnchorStacks:ReadByPointer(Pilot.AnchorStackNo) -- #AWACS.AnchorData
|
local Anchor = self.AnchorStacks:ReadByPointer(Pilot.AnchorStackNo) -- #AWACS.AnchorData
|
||||||
local capauftrag = AUFTRAG:NewCAP(Anchor.StationZone,Angels,AnchorSpeed,Anchor.StationZoneCoordinate,0,15,{})
|
local capauftrag = AUFTRAG:NewCAP(Anchor.StationZone,Angels,AnchorSpeed,Anchor.StationZoneCoordinate,0,15,{})
|
||||||
|
capauftrag:SetMissionRange(self.MaxMissionRange)
|
||||||
capauftrag:SetTime(nil,((self.CAPTimeOnStation*3600)+(15*60)))
|
capauftrag:SetTime(nil,((self.CAPTimeOnStation*3600)+(15*60)))
|
||||||
Pilot.FlightGroup:AddMission(capauftrag)
|
Pilot.FlightGroup:AddMission(capauftrag)
|
||||||
|
|
||||||
@@ -5898,6 +5947,8 @@ function AWACS:onafterStart(From, Event, To)
|
|||||||
-- set up the AWACS and let it orbit
|
-- set up the AWACS and let it orbit
|
||||||
local AwacsAW = self.AirWing -- Ops.Airwing#AIRWING
|
local AwacsAW = self.AirWing -- Ops.Airwing#AIRWING
|
||||||
local mission = AUFTRAG:NewORBIT_RACETRACK(self.OrbitZone:GetCoordinate(),self.AwacsAngels*1000,self.Speed,self.Heading,self.Leg)
|
local mission = AUFTRAG:NewORBIT_RACETRACK(self.OrbitZone:GetCoordinate(),self.AwacsAngels*1000,self.Speed,self.Heading,self.Leg)
|
||||||
|
mission:SetMissionRange(self.MaxMissionRange)
|
||||||
|
mission:SetRequiredAttribute({ GROUP.Attribute.AIR_AWACS }) -- prefered plane type, thanks to Heart8reaker
|
||||||
local timeonstation = (self.AwacsTimeOnStation + self.ShiftChangeTime) * 3600
|
local timeonstation = (self.AwacsTimeOnStation + self.ShiftChangeTime) * 3600
|
||||||
mission:SetTime(nil,timeonstation)
|
mission:SetTime(nil,timeonstation)
|
||||||
self.CatchAllMissions[#self.CatchAllMissions+1] = mission
|
self.CatchAllMissions[#self.CatchAllMissions+1] = mission
|
||||||
@@ -6040,6 +6091,7 @@ function AWACS:_CheckAwacsStatus()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
--------------------------------
|
--------------------------------
|
||||||
-- AWACS
|
-- AWACS
|
||||||
--------------------------------
|
--------------------------------
|
||||||
@@ -6188,12 +6240,13 @@ function AWACS:_CheckAwacsStatus()
|
|||||||
|
|
||||||
report:Add("====================")
|
report:Add("====================")
|
||||||
|
|
||||||
|
local RESMission
|
||||||
-- Check for replacement mission - if any
|
-- Check for replacement mission - if any
|
||||||
if self.ShiftChangeEscortsFlag and self.ShiftChangeEscortsRequested then -- Ops.Auftrag#AUFTRAG
|
if self.ShiftChangeEscortsFlag and self.ShiftChangeEscortsRequested then -- Ops.Auftrag#AUFTRAG
|
||||||
ESmission = self.EscortMissionReplacement[i]
|
RESMission = self.EscortMissionReplacement[i]
|
||||||
local esstatus = ESmission:GetState()
|
local esstatus = RESMission:GetState()
|
||||||
local ESmissiontime = (timer.getTime() - self.EscortsTimeStamp)
|
local RESMissiontime = (timer.getTime() - self.EscortsTimeStamp)
|
||||||
local ESTOSLeft = UTILS.Round((((self.EscortsTimeOnStation+self.ShiftChangeTime)*3600) - ESmissiontime),0) -- seconds
|
local ESTOSLeft = UTILS.Round((((self.EscortsTimeOnStation+self.ShiftChangeTime)*3600) - RESMissiontime),0) -- seconds
|
||||||
ESTOSLeft = UTILS.Round(ESTOSLeft/60,0) -- minutes
|
ESTOSLeft = UTILS.Round(ESTOSLeft/60,0) -- minutes
|
||||||
local ChangeTime = UTILS.Round(((self.ShiftChangeTime * 3600)/60),0)
|
local ChangeTime = UTILS.Round(((self.ShiftChangeTime * 3600)/60),0)
|
||||||
|
|
||||||
@@ -6201,7 +6254,7 @@ function AWACS:_CheckAwacsStatus()
|
|||||||
report:Add(string.format("Auftrag Status: %s",esstatus))
|
report:Add(string.format("Auftrag Status: %s",esstatus))
|
||||||
report:Add(string.format("TOS Left: %d min",ESTOSLeft))
|
report:Add(string.format("TOS Left: %d min",ESTOSLeft))
|
||||||
|
|
||||||
local OpsGroups = ESmission:GetOpsGroups()
|
local OpsGroups = RESMission:GetOpsGroups()
|
||||||
local OpsGroup = self:_GetAliveOpsGroupFromTable(OpsGroups) -- Ops.OpsGroup#OPSGROUP
|
local OpsGroup = self:_GetAliveOpsGroupFromTable(OpsGroups) -- Ops.OpsGroup#OPSGROUP
|
||||||
if OpsGroup then
|
if OpsGroup then
|
||||||
local OpsName = OpsGroup:GetName() or "Unknown"
|
local OpsName = OpsGroup:GetName() or "Unknown"
|
||||||
@@ -6213,13 +6266,13 @@ function AWACS:_CheckAwacsStatus()
|
|||||||
report:Add("***** Cannot obtain (yet) this missions OpsGroup!")
|
report:Add("***** Cannot obtain (yet) this missions OpsGroup!")
|
||||||
end
|
end
|
||||||
|
|
||||||
if ESmission:IsExecuting() then
|
if RESMission and RESMission:IsExecuting() then
|
||||||
-- make the actual change in the queue
|
-- make the actual change in the queue
|
||||||
self.ShiftChangeEscortsFlag = false
|
self.ShiftChangeEscortsFlag = false
|
||||||
self.ShiftChangeEscortsRequested = false
|
self.ShiftChangeEscortsRequested = false
|
||||||
-- cancel old mission
|
-- cancel old mission
|
||||||
if ESmission and ESmission:IsNotOver() then
|
if ESmission and ESmission:IsNotOver() then
|
||||||
ESmission:Cancel()
|
ESmission:__Cancel(1)
|
||||||
end
|
end
|
||||||
self.EscortMission[i] = self.EscortMissionReplacement[i]
|
self.EscortMission[i] = self.EscortMissionReplacement[i]
|
||||||
self.EscortMissionReplacement[i] = nil
|
self.EscortMissionReplacement[i] = nil
|
||||||
@@ -6471,6 +6524,7 @@ function AWACS:onafterAssignedAnchor(From, Event, To, GID, Anchor, AnchorStackNo
|
|||||||
if auftragtype == AUFTRAG.Type.ALERT5 then
|
if auftragtype == AUFTRAG.Type.ALERT5 then
|
||||||
-- all correct
|
-- all correct
|
||||||
local capauftrag = AUFTRAG:NewCAP(Anchor.StationZone,Angels*1000,AnchorSpeed,Anchor.StationZone:GetCoordinate(),0,15,{})
|
local capauftrag = AUFTRAG:NewCAP(Anchor.StationZone,Angels*1000,AnchorSpeed,Anchor.StationZone:GetCoordinate(),0,15,{})
|
||||||
|
capauftrag:SetMissionRange(self.MaxMissionRange)
|
||||||
capauftrag:SetTime(nil,((self.CAPTimeOnStation*3600)+(15*60)))
|
capauftrag:SetTime(nil,((self.CAPTimeOnStation*3600)+(15*60)))
|
||||||
capauftrag:AddAsset(managedgroup.FlightGroup)
|
capauftrag:AddAsset(managedgroup.FlightGroup)
|
||||||
self.CatchAllMissions[#self.CatchAllMissions+1] = capauftrag
|
self.CatchAllMissions[#self.CatchAllMissions+1] = capauftrag
|
||||||
@@ -6834,7 +6888,8 @@ function AWACS:onafterAwacsShiftChange(From,Event,To)
|
|||||||
self.CatchAllMissions[#self.CatchAllMissions+1] = mission
|
self.CatchAllMissions[#self.CatchAllMissions+1] = mission
|
||||||
local timeonstation = (self.AwacsTimeOnStation + self.ShiftChangeTime) * 3600
|
local timeonstation = (self.AwacsTimeOnStation + self.ShiftChangeTime) * 3600
|
||||||
mission:SetTime(nil,timeonstation)
|
mission:SetTime(nil,timeonstation)
|
||||||
|
mission:SetMissionRange(self.MaxMissionRange)
|
||||||
|
|
||||||
AwacsAW:AddMission(mission)
|
AwacsAW:AddMission(mission)
|
||||||
|
|
||||||
self.AwacsMissionReplacement = mission
|
self.AwacsMissionReplacement = mission
|
||||||
|
|||||||
@@ -491,6 +491,9 @@ function BRIGADE:onafterStatus(From, Event, To)
|
|||||||
-- Info ---
|
-- Info ---
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
|
-- Display tactival overview.
|
||||||
|
self:_TacticalOverview()
|
||||||
|
|
||||||
-- General info:
|
-- General info:
|
||||||
if self.verbose>=1 then
|
if self.verbose>=1 then
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
-- @image OPS_CSAR.jpg
|
-- @image OPS_CSAR.jpg
|
||||||
|
|
||||||
---
|
---
|
||||||
-- Last Update April 2024
|
-- Last Update Jan 2025
|
||||||
|
|
||||||
-------------------------------------------------------------------------
|
-------------------------------------------------------------------------
|
||||||
--- **CSAR** class, extends Core.Base#BASE, Core.Fsm#FSM
|
--- **CSAR** class, extends Core.Base#BASE, Core.Fsm#FSM
|
||||||
@@ -41,6 +41,7 @@
|
|||||||
-- @field #string lid Class id string for output to DCS log file.
|
-- @field #string lid Class id string for output to DCS log file.
|
||||||
-- @field #number coalition Coalition side number, e.g. `coalition.side.RED`.
|
-- @field #number coalition Coalition side number, e.g. `coalition.side.RED`.
|
||||||
-- @field Core.Set#SET_GROUP allheligroupset Set of CSAR heli groups.
|
-- @field Core.Set#SET_GROUP allheligroupset Set of CSAR heli groups.
|
||||||
|
-- @field Core.Set#SET_GROUP UserSetGroup Set of CSAR heli groups as designed by the mission designer (if any set).
|
||||||
-- @extends Core.Fsm#FSM
|
-- @extends Core.Fsm#FSM
|
||||||
|
|
||||||
--- *Combat search and rescue (CSAR) are search and rescue operations that are carried out during war that are within or near combat zones.* (Wikipedia)
|
--- *Combat search and rescue (CSAR) are search and rescue operations that are carried out during war that are within or near combat zones.* (Wikipedia)
|
||||||
@@ -91,7 +92,7 @@
|
|||||||
-- mycsar.immortalcrew = true -- Set to true to make wounded crew immortal.
|
-- mycsar.immortalcrew = true -- Set to true to make wounded crew immortal.
|
||||||
-- mycsar.invisiblecrew = false -- Set to true to make wounded crew insvisible.
|
-- mycsar.invisiblecrew = false -- Set to true to make wounded crew insvisible.
|
||||||
-- mycsar.loadDistance = 75 -- configure distance for pilots to get into helicopter in meters.
|
-- mycsar.loadDistance = 75 -- configure distance for pilots to get into helicopter in meters.
|
||||||
-- mycsar.mashprefix = {"MASH"} -- prefixes of #GROUP objects used as MASHes.
|
-- mycsar.mashprefix = {"MASH"} -- prefixes of #GROUP objects used as MASHes. Will also try to add ZONE and STATIC objects with this prefix once at startup.
|
||||||
-- mycsar.max_units = 6 -- max number of pilots that can be carried if #CSAR.AircraftType is undefined.
|
-- mycsar.max_units = 6 -- max number of pilots that can be carried if #CSAR.AircraftType is undefined.
|
||||||
-- mycsar.messageTime = 15 -- Time to show messages for in seconds. Doubled for long messages.
|
-- mycsar.messageTime = 15 -- Time to show messages for in seconds. Doubled for long messages.
|
||||||
-- mycsar.radioSound = "beacon.ogg" -- the name of the sound file to use for the pilots\' radio beacons.
|
-- mycsar.radioSound = "beacon.ogg" -- the name of the sound file to use for the pilots\' radio beacons.
|
||||||
@@ -116,8 +117,17 @@
|
|||||||
-- mycsar.topmenuname = "CSAR" -- set the menu entry name
|
-- mycsar.topmenuname = "CSAR" -- set the menu entry name
|
||||||
-- mycsar.ADFRadioPwr = 1000 -- ADF Beacons sending with 1KW as default
|
-- mycsar.ADFRadioPwr = 1000 -- ADF Beacons sending with 1KW as default
|
||||||
-- mycsar.PilotWeight = 80 -- Loaded pilots weigh 80kgs each
|
-- mycsar.PilotWeight = 80 -- Loaded pilots weigh 80kgs each
|
||||||
|
-- mycsar.AllowIRStrobe = false -- Allow a menu item to request an IR strobe to find a downed pilot at night (requires NVGs to see it).
|
||||||
|
-- mycsar.IRStrobeRuntime = 300 -- If an IR Strobe is activated, it runs for 300 seconds (5 mins).
|
||||||
|
--
|
||||||
|
-- ## 2.1 Create own SET_GROUP to manage CTLD Pilot groups
|
||||||
|
--
|
||||||
|
-- -- Parameter: Set The SET_GROUP object created by the mission designer/user to represent the CSAR pilot groups.
|
||||||
|
-- -- Needs to be set before starting the CSAR instance.
|
||||||
|
-- local myset = SET_GROUP:New():FilterPrefixes("Helikopter"):FilterCoalitions("red"):FilterStart()
|
||||||
|
-- mycsar:SetOwnSetPilotGroups(myset)
|
||||||
--
|
--
|
||||||
-- ## 2.1 SRS Features and Other Features
|
-- ## 2.2 SRS Features and Other Features
|
||||||
--
|
--
|
||||||
-- mycsar.useSRS = false -- Set true to use FF\'s SRS integration
|
-- mycsar.useSRS = false -- Set true to use FF\'s SRS integration
|
||||||
-- mycsar.SRSPath = "C:\\Progra~1\\DCS-SimpleRadio-Standalone\\" -- adjust your own path in your SRS installation -- server(!)
|
-- mycsar.SRSPath = "C:\\Progra~1\\DCS-SimpleRadio-Standalone\\" -- adjust your own path in your SRS installation -- server(!)
|
||||||
@@ -136,6 +146,7 @@
|
|||||||
-- mycsar.csarUsePara = false -- If set to true, will use the LandingAfterEjection Event instead of Ejection. Requires mycsar.enableForAI to be set to true. --shagrat
|
-- mycsar.csarUsePara = false -- If set to true, will use the LandingAfterEjection Event instead of Ejection. Requires mycsar.enableForAI to be set to true. --shagrat
|
||||||
-- mycsar.wetfeettemplate = "man in floating thingy" -- if you use a mod to have a pilot in a rescue float, put the template name in here for wet feet spawns. Note: in conjunction with csarUsePara this might create dual ejected pilots in edge cases.
|
-- mycsar.wetfeettemplate = "man in floating thingy" -- if you use a mod to have a pilot in a rescue float, put the template name in here for wet feet spawns. Note: in conjunction with csarUsePara this might create dual ejected pilots in edge cases.
|
||||||
-- mycsar.allowbronco = false -- set to true to use the Bronco mod as a CSAR plane
|
-- mycsar.allowbronco = false -- set to true to use the Bronco mod as a CSAR plane
|
||||||
|
-- mycsar.CreateRadioBeacons = true -- set to false to disallow creating ADF radio beacons.
|
||||||
--
|
--
|
||||||
-- ## 3. Results
|
-- ## 3. Results
|
||||||
--
|
--
|
||||||
@@ -256,6 +267,10 @@ CSAR = {
|
|||||||
topmenuname = "CSAR",
|
topmenuname = "CSAR",
|
||||||
ADFRadioPwr = 1000,
|
ADFRadioPwr = 1000,
|
||||||
PilotWeight = 80,
|
PilotWeight = 80,
|
||||||
|
CreateRadioBeacons = true,
|
||||||
|
UserSetGroup = nil,
|
||||||
|
AllowIRStrobe = false,
|
||||||
|
IRStrobeRuntime = 300,
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Downed pilots info.
|
--- Downed pilots info.
|
||||||
@@ -272,6 +287,7 @@ CSAR = {
|
|||||||
-- @field #number timestamp Timestamp for approach process.
|
-- @field #number timestamp Timestamp for approach process.
|
||||||
-- @field #boolean alive Group is alive or dead/rescued.
|
-- @field #boolean alive Group is alive or dead/rescued.
|
||||||
-- @field #boolean wetfeet Group is spawned over (deep) water.
|
-- @field #boolean wetfeet Group is spawned over (deep) water.
|
||||||
|
-- @field #string BeaconName Name of radio beacon - if any.
|
||||||
|
|
||||||
--- All slot / Limit settings
|
--- All slot / Limit settings
|
||||||
-- @type CSAR.AircraftType
|
-- @type CSAR.AircraftType
|
||||||
@@ -293,10 +309,11 @@ CSAR.AircraftType["Bronco-OV-10A"] = 2
|
|||||||
CSAR.AircraftType["MH-60R"] = 10
|
CSAR.AircraftType["MH-60R"] = 10
|
||||||
CSAR.AircraftType["OH-6A"] = 2
|
CSAR.AircraftType["OH-6A"] = 2
|
||||||
CSAR.AircraftType["OH58D"] = 2
|
CSAR.AircraftType["OH58D"] = 2
|
||||||
|
CSAR.AircraftType["CH-47Fbl1"] = 31
|
||||||
|
|
||||||
--- CSAR class version.
|
--- CSAR class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
CSAR.version="1.0.24"
|
CSAR.version="1.0.30"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- ToDo list
|
-- ToDo list
|
||||||
@@ -455,6 +472,9 @@ function CSAR:New(Coalition, Template, Alias)
|
|||||||
|
|
||||||
-- added 1.0.16
|
-- added 1.0.16
|
||||||
self.PilotWeight = 80
|
self.PilotWeight = 80
|
||||||
|
|
||||||
|
-- Own SET_GROUP if any
|
||||||
|
self.UserSetGroup = nil
|
||||||
|
|
||||||
-- WARNING - here\'ll be dragons
|
-- WARNING - here\'ll be dragons
|
||||||
-- for this to work you need to de-sanitize your mission environment in <DCS root>\Scripts\MissionScripting.lua
|
-- for this to work you need to de-sanitize your mission environment in <DCS root>\Scripts\MissionScripting.lua
|
||||||
@@ -633,7 +653,7 @@ end
|
|||||||
-- @param #string Playername Name of Player (if applicable)
|
-- @param #string Playername Name of Player (if applicable)
|
||||||
-- @param #boolean Wetfeet Ejected over water
|
-- @param #boolean Wetfeet Ejected over water
|
||||||
-- @return #CSAR self.
|
-- @return #CSAR self.
|
||||||
function CSAR:_CreateDownedPilotTrack(Group,Groupname,Side,OriginalUnit,Description,Typename,Frequency,Playername,Wetfeet)
|
function CSAR:_CreateDownedPilotTrack(Group,Groupname,Side,OriginalUnit,Description,Typename,Frequency,Playername,Wetfeet,BeaconName)
|
||||||
self:T({"_CreateDownedPilotTrack",Groupname,Side,OriginalUnit,Description,Typename,Frequency,Playername})
|
self:T({"_CreateDownedPilotTrack",Groupname,Side,OriginalUnit,Description,Typename,Frequency,Playername})
|
||||||
|
|
||||||
-- create new entry
|
-- create new entry
|
||||||
@@ -641,7 +661,7 @@ function CSAR:_CreateDownedPilotTrack(Group,Groupname,Side,OriginalUnit,Descript
|
|||||||
DownedPilot.desc = Description or ""
|
DownedPilot.desc = Description or ""
|
||||||
DownedPilot.frequency = Frequency or 0
|
DownedPilot.frequency = Frequency or 0
|
||||||
DownedPilot.index = self.downedpilotcounter
|
DownedPilot.index = self.downedpilotcounter
|
||||||
DownedPilot.name = Groupname or ""
|
DownedPilot.name = Groupname or Playername or ""
|
||||||
DownedPilot.originalUnit = OriginalUnit or ""
|
DownedPilot.originalUnit = OriginalUnit or ""
|
||||||
DownedPilot.player = Playername or ""
|
DownedPilot.player = Playername or ""
|
||||||
DownedPilot.side = Side or 0
|
DownedPilot.side = Side or 0
|
||||||
@@ -650,6 +670,7 @@ function CSAR:_CreateDownedPilotTrack(Group,Groupname,Side,OriginalUnit,Descript
|
|||||||
DownedPilot.timestamp = 0
|
DownedPilot.timestamp = 0
|
||||||
DownedPilot.alive = true
|
DownedPilot.alive = true
|
||||||
DownedPilot.wetfeet = Wetfeet or false
|
DownedPilot.wetfeet = Wetfeet or false
|
||||||
|
DownedPilot.BeaconName = BeaconName
|
||||||
|
|
||||||
-- Add Pilot
|
-- Add Pilot
|
||||||
local PilotTable = self.downedPilots
|
local PilotTable = self.downedPilots
|
||||||
@@ -736,7 +757,6 @@ function CSAR:_SpawnPilotInField(country,point,frequency,wetfeet)
|
|||||||
:NewWithAlias(template,alias)
|
:NewWithAlias(template,alias)
|
||||||
:InitCoalition(coalition)
|
:InitCoalition(coalition)
|
||||||
:InitCountry(country)
|
:InitCountry(country)
|
||||||
--:InitAIOnOff(pilotcacontrol)
|
|
||||||
:InitDelayOff()
|
:InitDelayOff()
|
||||||
:SpawnFromCoordinate(point)
|
:SpawnFromCoordinate(point)
|
||||||
|
|
||||||
@@ -789,6 +809,8 @@ end
|
|||||||
-- @param #boolean noMessage
|
-- @param #boolean noMessage
|
||||||
-- @param #string _description Description
|
-- @param #string _description Description
|
||||||
-- @param #boolean forcedesc Use the description only for the pilot track entry
|
-- @param #boolean forcedesc Use the description only for the pilot track entry
|
||||||
|
-- @return Wrapper.Group#GROUP PilotInField Pilot GROUP object
|
||||||
|
-- @return #string AliasName Alias display name
|
||||||
function CSAR:_AddCsar(_coalition , _country, _point, _typeName, _unitName, _playerName, _freq, noMessage, _description, forcedesc )
|
function CSAR:_AddCsar(_coalition , _country, _point, _typeName, _unitName, _playerName, _freq, noMessage, _description, forcedesc )
|
||||||
self:T(self.lid .. " _AddCsar")
|
self:T(self.lid .. " _AddCsar")
|
||||||
self:T({_coalition , _country, _point, _typeName, _unitName, _playerName, _freq, noMessage, _description})
|
self:T({_coalition , _country, _point, _typeName, _unitName, _playerName, _freq, noMessage, _description})
|
||||||
@@ -818,8 +840,18 @@ function CSAR:_AddCsar(_coalition , _country, _point, _typeName, _unitName, _pla
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local BeaconName
|
||||||
|
|
||||||
|
if _playerName then
|
||||||
|
BeaconName = _playerName..math.random(1,10000)
|
||||||
|
elseif _unitName then
|
||||||
|
BeaconName = _unitName..math.random(1,10000)
|
||||||
|
else
|
||||||
|
BeaconName = "Ghost-1-1"..math.random(1,10000)
|
||||||
|
end
|
||||||
|
|
||||||
if (_freq and _freq ~= 0) then --shagrat only add beacon if _freq is NOT 0
|
if (_freq and _freq ~= 0) then --shagrat only add beacon if _freq is NOT 0
|
||||||
self:_AddBeaconToGroup(_spawnedGroup, _freq)
|
self:_AddBeaconToGroup(_spawnedGroup, _freq, BeaconName)
|
||||||
end
|
end
|
||||||
|
|
||||||
self:_AddSpecialOptions(_spawnedGroup)
|
self:_AddSpecialOptions(_spawnedGroup)
|
||||||
@@ -844,11 +876,11 @@ function CSAR:_AddCsar(_coalition , _country, _point, _typeName, _unitName, _pla
|
|||||||
|
|
||||||
local _GroupName = _spawnedGroup:GetName() or _alias
|
local _GroupName = _spawnedGroup:GetName() or _alias
|
||||||
|
|
||||||
self:_CreateDownedPilotTrack(_spawnedGroup,_GroupName,_coalition,_unitName,_text,_typeName,_freq,_playerName,wetfeet)
|
self:_CreateDownedPilotTrack(_spawnedGroup,_GroupName,_coalition,_unitName,_text,_typeName,_freq,_playerName,wetfeet,BeaconName)
|
||||||
|
|
||||||
self:_InitSARForPilot(_spawnedGroup, _unitName, _freq, noMessage, _playerName) --shagrat use unitName to have the aircraft callsign / descriptive "name" etc.
|
self:_InitSARForPilot(_spawnedGroup, _unitName, _freq, noMessage, _playerName) --shagrat use unitName to have the aircraft callsign / descriptive "name" etc.
|
||||||
|
|
||||||
return self
|
return _spawnedGroup, _alias
|
||||||
end
|
end
|
||||||
|
|
||||||
--- (Internal) Function to add a CSAR object into the scene at a zone coordinate. For mission designers wanting to add e.g. PoWs to the scene.
|
--- (Internal) Function to add a CSAR object into the scene at a zone coordinate. For mission designers wanting to add e.g. PoWs to the scene.
|
||||||
@@ -962,7 +994,6 @@ end
|
|||||||
-- @param Core.Point#COORDINATE Point
|
-- @param Core.Point#COORDINATE Point
|
||||||
-- @param #number Coalition Coalition.
|
-- @param #number Coalition Coalition.
|
||||||
-- @param #string Description (optional) Description.
|
-- @param #string Description (optional) Description.
|
||||||
-- @param #boolean addBeacon (optional) yes or no.
|
|
||||||
-- @param #boolean Nomessage (optional) If true, don\'t send a message to SAR.
|
-- @param #boolean Nomessage (optional) If true, don\'t send a message to SAR.
|
||||||
-- @param #string Unitname (optional) Name of the lost unit.
|
-- @param #string Unitname (optional) Name of the lost unit.
|
||||||
-- @param #string Typename (optional) Type of plane.
|
-- @param #string Typename (optional) Type of plane.
|
||||||
@@ -1792,9 +1823,6 @@ function CSAR:_DisplayMessageToSAR(_unit, _text, _time, _clear, _speak, _overrid
|
|||||||
end
|
end
|
||||||
_text = string.gsub(_text,"km"," kilometer")
|
_text = string.gsub(_text,"km"," kilometer")
|
||||||
_text = string.gsub(_text,"nm"," nautical miles")
|
_text = string.gsub(_text,"nm"," nautical miles")
|
||||||
--self.msrs:SetVoice(self.SRSVoice)
|
|
||||||
--self.SRSQueue:NewTransmission(_text,nil,self.msrs,nil,1)
|
|
||||||
--self:I("Voice = "..self.SRSVoice)
|
|
||||||
self.SRSQueue:NewTransmission(_text,duration,self.msrs,tstart,2,subgroups,subtitle,subduration,self.SRSchannel,self.SRSModulation,gender,culture,self.SRSVoice,volume,label,coord)
|
self.SRSQueue:NewTransmission(_text,duration,self.msrs,tstart,2,subgroups,subtitle,subduration,self.SRSchannel,self.SRSModulation,gender,culture,self.SRSVoice,volume,label,coord)
|
||||||
end
|
end
|
||||||
return self
|
return self
|
||||||
@@ -1803,8 +1831,9 @@ end
|
|||||||
--- (Internal) Function to get string of a group\'s position.
|
--- (Internal) Function to get string of a group\'s position.
|
||||||
-- @param #CSAR self
|
-- @param #CSAR self
|
||||||
-- @param Wrapper.Controllable#CONTROLLABLE _woundedGroup Group or Unit object.
|
-- @param Wrapper.Controllable#CONTROLLABLE _woundedGroup Group or Unit object.
|
||||||
|
-- @param Wrapper.Unit#UNIT _Unit Requesting helo pilot unit
|
||||||
-- @return #string Coordinates as Text
|
-- @return #string Coordinates as Text
|
||||||
function CSAR:_GetPositionOfWounded(_woundedGroup)
|
function CSAR:_GetPositionOfWounded(_woundedGroup,_Unit)
|
||||||
self:T(self.lid .. " _GetPositionOfWounded")
|
self:T(self.lid .. " _GetPositionOfWounded")
|
||||||
local _coordinate = _woundedGroup:GetCoordinate()
|
local _coordinate = _woundedGroup:GetCoordinate()
|
||||||
local _coordinatesText = "None"
|
local _coordinatesText = "None"
|
||||||
@@ -1819,6 +1848,26 @@ function CSAR:_GetPositionOfWounded(_woundedGroup)
|
|||||||
_coordinatesText = _coordinate:ToStringBULLS(self.coalition)
|
_coordinatesText = _coordinate:ToStringBULLS(self.coalition)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
if _Unit and _Unit:GetPlayerName() then
|
||||||
|
local playername = _Unit:GetPlayerName()
|
||||||
|
if playername then
|
||||||
|
local settings = _DATABASE:GetPlayerSettings(playername) or _SETTINGS
|
||||||
|
if settings then
|
||||||
|
self:T("Get Settings ok!")
|
||||||
|
if settings:IsA2G_MGRS() then
|
||||||
|
_coordinatesText = _coordinate:ToStringMGRS(settings)
|
||||||
|
elseif settings:IsA2G_LL_DMS() then
|
||||||
|
_coordinatesText = _coordinate:ToStringLLDMS(settings)
|
||||||
|
elseif settings:IsA2G_LL_DDM() then
|
||||||
|
_coordinatesText = _coordinate:ToStringLLDDM(settings)
|
||||||
|
elseif settings:IsA2G_BR() then
|
||||||
|
-- attention this is the distance from the ASKING unit to target, not from RECCE to target!
|
||||||
|
local startcoordinate = _Unit:GetCoordinate()
|
||||||
|
_coordinatesText = _coordinate:ToStringBR(startcoordinate,settings)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
return _coordinatesText
|
return _coordinatesText
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1844,22 +1893,26 @@ function CSAR:_DisplayActiveSAR(_unitName)
|
|||||||
self:T({Table=_value})
|
self:T({Table=_value})
|
||||||
local _woundedGroup = _value.group
|
local _woundedGroup = _value.group
|
||||||
if _woundedGroup and _value.alive then
|
if _woundedGroup and _value.alive then
|
||||||
local _coordinatesText = self:_GetPositionOfWounded(_woundedGroup)
|
local _coordinatesText = self:_GetPositionOfWounded(_woundedGroup,_heli)
|
||||||
local _helicoord = _heli:GetCoordinate()
|
local _helicoord = _heli:GetCoordinate()
|
||||||
local _woundcoord = _woundedGroup:GetCoordinate()
|
local _woundcoord = _woundedGroup:GetCoordinate()
|
||||||
local _distance = self:_GetDistance(_helicoord, _woundcoord)
|
local _distance = self:_GetDistance(_helicoord, _woundcoord)
|
||||||
self:T({_distance = _distance})
|
self:T({_distance = _distance})
|
||||||
local distancetext = ""
|
local distancetext = ""
|
||||||
if _SETTINGS:IsImperial() then
|
local settings = _SETTINGS
|
||||||
|
if _heli:GetPlayerName() then
|
||||||
|
settings = _DATABASE:GetPlayerSettings(_heli:GetPlayerName()) or _SETTINGS
|
||||||
|
end
|
||||||
|
if settings:IsImperial() then
|
||||||
distancetext = string.format("%.1fnm",UTILS.MetersToNM(_distance))
|
distancetext = string.format("%.1fnm",UTILS.MetersToNM(_distance))
|
||||||
else
|
else
|
||||||
distancetext = string.format("%.1fkm", _distance/1000.0)
|
distancetext = string.format("%.1fkm", _distance/1000.0)
|
||||||
end
|
end
|
||||||
if _value.frequency == 0 then--shagrat insert CASEVAC without Frequency
|
if _value.frequency == 0 or self.CreateRadioBeacons == false then--shagrat insert CASEVAC without Frequency
|
||||||
table.insert(_csarList, { dist = _distance, msg = string.format("%s at %s - %s ", _value.desc, _coordinatesText, distancetext) })
|
table.insert(_csarList, { dist = _distance, msg = string.format("%s at %s - %s ", _value.desc, _coordinatesText, distancetext) })
|
||||||
else
|
else
|
||||||
table.insert(_csarList, { dist = _distance, msg = string.format("%s at %s - %.2f KHz ADF - %s ", _value.desc, _coordinatesText, _value.frequency / 1000, distancetext) })
|
table.insert(_csarList, { dist = _distance, msg = string.format("%s at %s - %.2f KHz ADF - %s ", _value.desc, _coordinatesText, _value.frequency / 1000, distancetext) })
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1940,7 +1993,7 @@ function CSAR:_SignalFlare(_unitName)
|
|||||||
else
|
else
|
||||||
_distance = string.format("%.1fkm",_closest.distance/1000)
|
_distance = string.format("%.1fkm",_closest.distance/1000)
|
||||||
end
|
end
|
||||||
local _msg = string.format("%s - Popping signal flare at your %s o\'clock. Distance %s", self:_GetCustomCallSign(_unitName), _clockDir, _distance)
|
local _msg = string.format("%s - Firing signal flare at your %s o\'clock. Distance %s", self:_GetCustomCallSign(_unitName), _clockDir, _distance)
|
||||||
self:_DisplayMessageToSAR(_heli, _msg, self.messageTime, false, true, true)
|
self:_DisplayMessageToSAR(_heli, _msg, self.messageTime, false, true, true)
|
||||||
|
|
||||||
local _coord = _closest.pilot:GetCoordinate()
|
local _coord = _closest.pilot:GetCoordinate()
|
||||||
@@ -1974,7 +2027,7 @@ function CSAR:_DisplayToAllSAR(_message, _side, _messagetime,ToSRS,ToScreen)
|
|||||||
if self.msrs:GetProvider() == MSRS.Provider.WINDOWS then
|
if self.msrs:GetProvider() == MSRS.Provider.WINDOWS then
|
||||||
voice = self.CSARVoiceMS or MSRS.Voices.Microsoft.Hedda
|
voice = self.CSARVoiceMS or MSRS.Voices.Microsoft.Hedda
|
||||||
end
|
end
|
||||||
self:F("Voice = "..voice)
|
--self:F("Voice = "..voice)
|
||||||
self.SRSQueue:NewTransmission(_message,duration,self.msrs,tstart,2,subgroups,subtitle,subduration,self.SRSchannel,self.SRSModulation,gender,culture,voice,volume,label,self.coordinate)
|
self.SRSQueue:NewTransmission(_message,duration,self.msrs,tstart,2,subgroups,subtitle,subduration,self.SRSchannel,self.SRSModulation,gender,culture,voice,volume,label,self.coordinate)
|
||||||
end
|
end
|
||||||
if ToScreen == true or ToScreen == nil then
|
if ToScreen == true or ToScreen == nil then
|
||||||
@@ -1988,6 +2041,41 @@ function CSAR:_DisplayToAllSAR(_message, _side, _messagetime,ToSRS,ToScreen)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---(Internal) Request IR Strobe at closest downed pilot.
|
||||||
|
--@param #CSAR self
|
||||||
|
--@param #string _unitName Name of the helicopter
|
||||||
|
function CSAR:_ReqIRStrobe( _unitName )
|
||||||
|
self:T(self.lid .. " _ReqIRStrobe")
|
||||||
|
local _heli = self:_GetSARHeli(_unitName)
|
||||||
|
if _heli == nil then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local smokedist = 8000
|
||||||
|
if smokedist < self.approachdist_far then smokedist = self.approachdist_far end
|
||||||
|
local _closest = self:_GetClosestDownedPilot(_heli)
|
||||||
|
if _closest ~= nil and _closest.pilot ~= nil and _closest.distance > 0 and _closest.distance < smokedist then
|
||||||
|
local _clockDir = self:_GetClockDirection(_heli, _closest.pilot)
|
||||||
|
local _distance = string.format("%.1fkm",_closest.distance/1000)
|
||||||
|
if _SETTINGS:IsImperial() then
|
||||||
|
_distance = string.format("%.1fnm",UTILS.MetersToNM(_closest.distance))
|
||||||
|
else
|
||||||
|
_distance = string.format("%.1fkm",_closest.distance/1000)
|
||||||
|
end
|
||||||
|
local _msg = string.format("%s - IR Strobe active at your %s o\'clock. Distance %s", self:_GetCustomCallSign(_unitName), _clockDir, _distance)
|
||||||
|
self:_DisplayMessageToSAR(_heli, _msg, self.messageTime, false, true, true)
|
||||||
|
_closest.pilot:NewIRMarker(true,self.IRStrobeRuntime or 300)
|
||||||
|
else
|
||||||
|
local _distance = string.format("%.1fkm",smokedist/1000)
|
||||||
|
if _SETTINGS:IsImperial() then
|
||||||
|
_distance = string.format("%.1fnm",UTILS.MetersToNM(smokedist))
|
||||||
|
else
|
||||||
|
_distance = string.format("%.1fkm",smokedist/1000)
|
||||||
|
end
|
||||||
|
self:_DisplayMessageToSAR(_heli, string.format("No Pilots within %s",_distance), self.messageTime, false, false, true)
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
---(Internal) Request smoke at closest downed pilot.
|
---(Internal) Request smoke at closest downed pilot.
|
||||||
--@param #CSAR self
|
--@param #CSAR self
|
||||||
--@param #string _unitName Name of the helicopter
|
--@param #string _unitName Name of the helicopter
|
||||||
@@ -2111,12 +2199,12 @@ function CSAR:_AddMedevacMenuItem()
|
|||||||
local coalition = self.coalition
|
local coalition = self.coalition
|
||||||
local allheligroupset = self.allheligroupset -- Core.Set#SET_GROUP
|
local allheligroupset = self.allheligroupset -- Core.Set#SET_GROUP
|
||||||
local _allHeliGroups = allheligroupset:GetSetObjects()
|
local _allHeliGroups = allheligroupset:GetSetObjects()
|
||||||
|
|
||||||
-- rebuild units table
|
-- rebuild units table
|
||||||
local _UnitList = {}
|
local _UnitList = {}
|
||||||
for _key, _group in pairs (_allHeliGroups) do
|
for _key, _group in pairs (_allHeliGroups) do
|
||||||
local _unit = _group:GetUnit(1) -- Asume that there is only one unit in the flight for players
|
local _unit = _group:GetFirstUnitAlive() -- Asume that there is only one unit in the flight for players
|
||||||
if _unit then
|
if _unit then
|
||||||
|
--self:T("Unitname ".._unit:GetName().." IsAlive "..tostring(_unit:IsAlive()).." IsPlayer "..tostring(_unit:IsPlayer()))
|
||||||
if _unit:IsAlive() and _unit:IsPlayer() then
|
if _unit:IsAlive() and _unit:IsPlayer() then
|
||||||
local unitName = _unit:GetName()
|
local unitName = _unit:GetName()
|
||||||
_UnitList[unitName] = unitName
|
_UnitList[unitName] = unitName
|
||||||
@@ -2139,7 +2227,12 @@ function CSAR:_AddMedevacMenuItem()
|
|||||||
local _rootMenu1 = MENU_GROUP_COMMAND:New(_group,"List Active CSAR",_rootPath, self._DisplayActiveSAR,self,_unitName)
|
local _rootMenu1 = MENU_GROUP_COMMAND:New(_group,"List Active CSAR",_rootPath, self._DisplayActiveSAR,self,_unitName)
|
||||||
local _rootMenu2 = MENU_GROUP_COMMAND:New(_group,"Check Onboard",_rootPath, self._CheckOnboard,self,_unitName)
|
local _rootMenu2 = MENU_GROUP_COMMAND:New(_group,"Check Onboard",_rootPath, self._CheckOnboard,self,_unitName)
|
||||||
local _rootMenu3 = MENU_GROUP_COMMAND:New(_group,"Request Signal Flare",_rootPath, self._SignalFlare,self,_unitName)
|
local _rootMenu3 = MENU_GROUP_COMMAND:New(_group,"Request Signal Flare",_rootPath, self._SignalFlare,self,_unitName)
|
||||||
local _rootMenu4 = MENU_GROUP_COMMAND:New(_group,"Request Smoke",_rootPath, self._Reqsmoke,self,_unitName):Refresh()
|
local _rootMenu4 = MENU_GROUP_COMMAND:New(_group,"Request Smoke",_rootPath, self._Reqsmoke,self,_unitName)
|
||||||
|
if self.AllowIRStrobe then
|
||||||
|
local _rootMenu5 = MENU_GROUP_COMMAND:New(_group,"Request IR Strobe",_rootPath, self._ReqIRStrobe,self,_unitName):Refresh()
|
||||||
|
else
|
||||||
|
_rootMenu4:Refresh()
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -2230,9 +2323,13 @@ end
|
|||||||
-- @param #CSAR self
|
-- @param #CSAR self
|
||||||
-- @param Wrapper.Group#GROUP _group Group #GROUP object.
|
-- @param Wrapper.Group#GROUP _group Group #GROUP object.
|
||||||
-- @param #number _freq Frequency to use
|
-- @param #number _freq Frequency to use
|
||||||
function CSAR:_AddBeaconToGroup(_group, _freq)
|
-- @param #string _name Beacon Name to use
|
||||||
|
-- @return #CSAR self
|
||||||
|
function CSAR:_AddBeaconToGroup(_group, _freq, _name)
|
||||||
self:T(self.lid .. " _AddBeaconToGroup")
|
self:T(self.lid .. " _AddBeaconToGroup")
|
||||||
|
if self.CreateRadioBeacons == false then return end
|
||||||
local _group = _group
|
local _group = _group
|
||||||
|
|
||||||
if _group == nil then
|
if _group == nil then
|
||||||
--return frequency to pool of available
|
--return frequency to pool of available
|
||||||
for _i, _current in ipairs(self.UsedVHFFrequencies) do
|
for _i, _current in ipairs(self.UsedVHFFrequencies) do
|
||||||
@@ -2247,22 +2344,24 @@ function CSAR:_AddBeaconToGroup(_group, _freq)
|
|||||||
if _group:IsAlive() then
|
if _group:IsAlive() then
|
||||||
local _radioUnit = _group:GetUnit(1)
|
local _radioUnit = _group:GetUnit(1)
|
||||||
if _radioUnit then
|
if _radioUnit then
|
||||||
local name = _radioUnit:GetName()
|
local name = _radioUnit:GetName()
|
||||||
local Frequency = _freq -- Freq in Hertz
|
local Frequency = _freq -- Freq in Hertz
|
||||||
local name = _radioUnit:GetName()
|
local name = _radioUnit:GetName()
|
||||||
local Sound = "l10n/DEFAULT/"..self.radioSound
|
local Sound = "l10n/DEFAULT/"..self.radioSound
|
||||||
local vec3 = _radioUnit:GetVec3() or _radioUnit:GetPositionVec3() or {x=0,y=0,z=0}
|
local vec3 = _radioUnit:GetVec3() or _radioUnit:GetPositionVec3() or {x=0,y=0,z=0}
|
||||||
trigger.action.radioTransmission(Sound, vec3, 0, false, Frequency, self.ADFRadioPwr or 1000,name..math.random(1,10000)) -- Beacon in MP only runs for exactly 30secs straight
|
trigger.action.radioTransmission(Sound, vec3, 0, false, Frequency, self.ADFRadioPwr or 1000,_name) -- Beacon in MP only runs for exactly 30secs straight
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- (Internal) Helper function to (re-)add beacon to downed pilot.
|
--- (Internal) Helper function to (re-)add beacon to downed pilot.
|
||||||
-- @param #CSAR self
|
-- @param #CSAR self
|
||||||
-- @param #table _args Arguments
|
-- @return #CSAR self
|
||||||
function CSAR:_RefreshRadioBeacons()
|
function CSAR:_RefreshRadioBeacons()
|
||||||
self:T(self.lid .. " _RefreshRadioBeacons")
|
self:T(self.lid .. " _RefreshRadioBeacons")
|
||||||
|
if self.CreateRadioBeacons == false then return end
|
||||||
if self:_CountActiveDownedPilots() > 0 then
|
if self:_CountActiveDownedPilots() > 0 then
|
||||||
local PilotTable = self.downedPilots
|
local PilotTable = self.downedPilots
|
||||||
for _,_pilot in pairs (PilotTable) do
|
for _,_pilot in pairs (PilotTable) do
|
||||||
@@ -2270,8 +2369,10 @@ function CSAR:_RefreshRadioBeacons()
|
|||||||
local pilot = _pilot -- #CSAR.DownedPilot
|
local pilot = _pilot -- #CSAR.DownedPilot
|
||||||
local group = pilot.group
|
local group = pilot.group
|
||||||
local frequency = pilot.frequency or 0 -- thanks to @Thrud
|
local frequency = pilot.frequency or 0 -- thanks to @Thrud
|
||||||
|
local bname = pilot.BeaconName or pilot.name..math.random(1,100000)
|
||||||
|
trigger.action.stopRadioTransmission(bname)
|
||||||
if group and group:IsAlive() and frequency > 0 then
|
if group and group:IsAlive() and frequency > 0 then
|
||||||
self:_AddBeaconToGroup(group,frequency)
|
self:_AddBeaconToGroup(group,frequency,bname)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -2308,6 +2409,16 @@ function CSAR:_ReachedPilotLimit()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- User - Function to add onw SET_GROUP Set-up for pilot filtering and assignment.
|
||||||
|
-- Needs to be set before starting the CSAR instance.
|
||||||
|
-- @param #CSAR self
|
||||||
|
-- @param Core.Set#SET_GROUP Set The SET_GROUP object created by the mission designer/user to represent the CSAR pilot groups.
|
||||||
|
-- @return #CSAR self
|
||||||
|
function CSAR:SetOwnSetPilotGroups(Set)
|
||||||
|
self.UserSetGroup = Set
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
------------------------------
|
------------------------------
|
||||||
--- FSM internal Functions ---
|
--- FSM internal Functions ---
|
||||||
------------------------------
|
------------------------------
|
||||||
@@ -2329,7 +2440,9 @@ function CSAR:onafterStart(From, Event, To)
|
|||||||
self:HandleEvent(EVENTS.PlayerEnterUnit, self._EventHandler)
|
self:HandleEvent(EVENTS.PlayerEnterUnit, self._EventHandler)
|
||||||
self:HandleEvent(EVENTS.PilotDead, self._EventHandler)
|
self:HandleEvent(EVENTS.PilotDead, self._EventHandler)
|
||||||
|
|
||||||
if self.allowbronco then
|
if self.UserSetGroup then
|
||||||
|
self.allheligroupset = self.UserSetGroup
|
||||||
|
elseif self.allowbronco then
|
||||||
local prefixes = self.csarPrefix or {}
|
local prefixes = self.csarPrefix or {}
|
||||||
self.allheligroupset = SET_GROUP:New():FilterCoalitions(self.coalitiontxt):FilterPrefixes(prefixes):FilterStart()
|
self.allheligroupset = SET_GROUP:New():FilterCoalitions(self.coalitiontxt):FilterPrefixes(prefixes):FilterStart()
|
||||||
elseif self.useprefix then
|
elseif self.useprefix then
|
||||||
@@ -2338,7 +2451,24 @@ function CSAR:onafterStart(From, Event, To)
|
|||||||
else
|
else
|
||||||
self.allheligroupset = SET_GROUP:New():FilterCoalitions(self.coalitiontxt):FilterCategoryHelicopter():FilterStart()
|
self.allheligroupset = SET_GROUP:New():FilterCoalitions(self.coalitiontxt):FilterCategoryHelicopter():FilterStart()
|
||||||
end
|
end
|
||||||
self.mash = SET_GROUP:New():FilterCoalitions(self.coalitiontxt):FilterPrefixes(self.mashprefix):FilterStart() -- currently only GROUP objects, maybe support STATICs also?
|
|
||||||
|
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()
|
||||||
|
|
||||||
|
if staticmashes:Count() > 0 then
|
||||||
|
for _,_mash in pairs(staticmashes.Set) do
|
||||||
|
self.mash:AddObject(_mash)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if zonemashes:Count() > 0 then
|
||||||
|
for _,_mash in pairs(zonemashes.Set) do
|
||||||
|
self.mash:AddObject(_mash)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
if not self.coordinate then
|
if not self.coordinate then
|
||||||
local csarhq = self.mash:GetRandom()
|
local csarhq = self.mash:GetRandom()
|
||||||
if csarhq then
|
if csarhq then
|
||||||
|
|||||||
+2091
-542
File diff suppressed because it is too large
Load Diff
@@ -34,6 +34,7 @@
|
|||||||
-- @field Ops.Commander#COMMANDER commander Commander of assigned legions.
|
-- @field Ops.Commander#COMMANDER commander Commander of assigned legions.
|
||||||
-- @field #number Nsuccess Number of successful missions.
|
-- @field #number Nsuccess Number of successful missions.
|
||||||
-- @field #number Nfailure Number of failed mission.
|
-- @field #number Nfailure Number of failed mission.
|
||||||
|
-- @field #table assetNumbers Asset numbers. Each entry is a table of data type `#CHIEF.AssetNumber`.
|
||||||
-- @extends Ops.Intel#INTEL
|
-- @extends Ops.Intel#INTEL
|
||||||
|
|
||||||
--- *In preparing for battle I have always found that plans are useless, but planning is indispensable* -- Dwight D Eisenhower
|
--- *In preparing for battle I have always found that plans are useless, but planning is indispensable* -- Dwight D Eisenhower
|
||||||
@@ -163,7 +164,7 @@
|
|||||||
--
|
--
|
||||||
-- Will at a strategic zone with importance 2.
|
-- Will at a strategic zone with importance 2.
|
||||||
--
|
--
|
||||||
-- If the zone is currently owned by another coalition and enemy ground troops are present in the zone, a CAS and an ARTY mission are lauchned:
|
-- If the zone is currently owned by another coalition and enemy ground troops are present in the zone, a CAS and an ARTY mission are launched:
|
||||||
--
|
--
|
||||||
-- * A mission of type `AUFTRAG.Type.CASENHANCED` is started if assets are available that can carry out this mission type.
|
-- * A mission of type `AUFTRAG.Type.CASENHANCED` is started if assets are available that can carry out this mission type.
|
||||||
-- * A mission of type `AUFTRAG.Type.ARTY` is started provided assets are available.
|
-- * A mission of type `AUFTRAG.Type.ARTY` is started provided assets are available.
|
||||||
@@ -331,7 +332,7 @@ CHIEF.Strategy = {
|
|||||||
|
|
||||||
--- CHIEF class version.
|
--- CHIEF class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
CHIEF.version="0.6.0"
|
CHIEF.version="0.6.1"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- TODO list
|
-- TODO list
|
||||||
@@ -1284,8 +1285,10 @@ end
|
|||||||
--
|
--
|
||||||
-- Empty:
|
-- Empty:
|
||||||
--
|
--
|
||||||
-- * `AUFTRAG.Type.ONGURAD` with Nmin=1 and Nmax=1 assets, Attribute=`GROUP.Attribute.GROUND_TANK`.
|
-- * `AUFTRAG.Type.ONGURAD` with Nmin=0 and Nmax=1 assets, Attribute=`GROUP.Attribute.GROUND_TANK`.
|
||||||
|
-- * `AUFTRAG.Type.ONGURAD` with Nmin=0 and Nmax=1 assets, Attribute=`GROUP.Attribute.GROUND_IFV`.
|
||||||
-- * `AUFTRAG.Type.ONGUARD` with Nmin=1 and Nmax=3 assets, Attribute=`GROUP.Attribute.GROUND_INFANTRY`.
|
-- * `AUFTRAG.Type.ONGUARD` with Nmin=1 and Nmax=3 assets, Attribute=`GROUP.Attribute.GROUND_INFANTRY`.
|
||||||
|
-- * `AUFTRAG.Type.OPSTRANSPORT` with Nmin=0 and Nmax=1 assets, Attribute=`GROUP.Attribute.AIR_TRANSPORTHELO` or `GROUP.Attribute.GROUND_APC`. This asset is used to transport the infantry groups.
|
||||||
--
|
--
|
||||||
-- Resources can be created with the @{#CHIEF.CreateResource} and @{#CHIEF.AddToResource} functions.
|
-- Resources can be created with the @{#CHIEF.CreateResource} and @{#CHIEF.AddToResource} functions.
|
||||||
--
|
--
|
||||||
@@ -3033,10 +3036,13 @@ function CHIEF:RecruitAssetsForZone(StratZone, Resource)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Recruite infantry assets.
|
-- Recruite infantry assets.
|
||||||
|
self:T(self.lid..string.format("Recruiting assets for zone %s", StratZone.opszone:GetName()))
|
||||||
self:T(self.lid.."Missiontype="..MissionType)
|
self:T(self.lid.."Missiontype="..MissionType)
|
||||||
self:T({categories=Categories})
|
self:T({categories=Categories})
|
||||||
self:T({attributes=Attributes})
|
self:T({attributes=Attributes})
|
||||||
self:T({properties=Properties})
|
self:T({properties=Properties})
|
||||||
|
|
||||||
|
|
||||||
local recruited, assets, legions=LEGION.RecruitCohortAssets(Cohorts, MissionType, nil, NassetsMin, NassetsMax, TargetVec2, nil, RangeMax, nil, nil, nil, nil, Categories, Attributes, Properties)
|
local recruited, assets, legions=LEGION.RecruitCohortAssets(Cohorts, MissionType, nil, NassetsMin, NassetsMax, TargetVec2, nil, RangeMax, nil, nil, nil, nil, Categories, Attributes, Properties)
|
||||||
|
|
||||||
if recruited then
|
if recruited then
|
||||||
@@ -3052,9 +3058,12 @@ function CHIEF:RecruitAssetsForZone(StratZone, Resource)
|
|||||||
local TargetCoord = TargetZone:GetCoordinate()
|
local TargetCoord = TargetZone:GetCoordinate()
|
||||||
|
|
||||||
-- First check if we need a transportation.
|
-- First check if we need a transportation.
|
||||||
local transport=nil
|
local transport=nil --Ops.OpsTransport#OPSTRANSPORT
|
||||||
|
local Ntransports=0
|
||||||
if Resource.carrierNmin and Resource.carrierNmax and Resource.carrierNmax>0 then
|
if Resource.carrierNmin and Resource.carrierNmax and Resource.carrierNmax>0 then
|
||||||
|
|
||||||
|
self:T(self.lid..string.format("Recruiting carrier assets: Nmin=%s, Nmax=%s", tostring(Resource.carrierNmin), tostring(Resource.carrierNmax)))
|
||||||
|
|
||||||
-- Filter only those assets that shall be transported.
|
-- Filter only those assets that shall be transported.
|
||||||
local cargoassets=CHIEF._FilterAssets(assets, Resource.Categories, Resource.Attributes, Resource.Properties)
|
local cargoassets=CHIEF._FilterAssets(assets, Resource.Categories, Resource.Attributes, Resource.Properties)
|
||||||
|
|
||||||
@@ -3064,6 +3073,10 @@ function CHIEF:RecruitAssetsForZone(StratZone, Resource)
|
|||||||
recruited, transport=LEGION.AssignAssetsForTransport(self.commander, self.commander.legions, cargoassets,
|
recruited, transport=LEGION.AssignAssetsForTransport(self.commander, self.commander.legions, cargoassets,
|
||||||
Resource.carrierNmin, Resource.carrierNmax, TargetZone, nil, Resource.carrierCategories, Resource.carrierAttributes, Resource.carrierProperties)
|
Resource.carrierNmin, Resource.carrierNmax, TargetZone, nil, Resource.carrierCategories, Resource.carrierAttributes, Resource.carrierProperties)
|
||||||
|
|
||||||
|
Ntransports=transport~=nil and #transport.assets or 0
|
||||||
|
|
||||||
|
self:T(self.lid..string.format("Recruited %d transport carrier assets success=%s", Ntransports, tostring(recruited)))
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
@@ -3076,7 +3089,7 @@ function CHIEF:RecruitAssetsForZone(StratZone, Resource)
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Debug messgage.
|
-- Debug message
|
||||||
self:T2(self.lid..string.format("Recruited %d assets for mission %s", #assets, MissionType))
|
self:T2(self.lid..string.format("Recruited %d assets for mission %s", #assets, MissionType))
|
||||||
|
|
||||||
|
|
||||||
@@ -3224,10 +3237,13 @@ function CHIEF:RecruitAssetsForZone(StratZone, Resource)
|
|||||||
-- Attach mission to ops zone.
|
-- Attach mission to ops zone.
|
||||||
StratZone.opszone:_AddMission(self.coalition, MissionType, mission)
|
StratZone.opszone:_AddMission(self.coalition, MissionType, mission)
|
||||||
|
|
||||||
|
mission:SetName(string.format("Stratzone %s-%d", StratZone.opszone:GetName(), mission.auftragsnummer))
|
||||||
|
|
||||||
-- Attach mission to resource.
|
-- Attach mission to resource.
|
||||||
Resource.mission=mission
|
Resource.mission=mission
|
||||||
|
|
||||||
if transport then
|
-- Check if transport assets could be allocated. If carrier Nmin=0 and 0 assets could be allocated, transport would still be created but not usefull obviously
|
||||||
|
if transport and Ntransports>0 then
|
||||||
-- Attach OPS transport to mission.
|
-- Attach OPS transport to mission.
|
||||||
mission.opstransport=transport
|
mission.opstransport=transport
|
||||||
-- Set ops zone to transport.
|
-- Set ops zone to transport.
|
||||||
|
|||||||
@@ -88,7 +88,10 @@ COHORT = {
|
|||||||
|
|
||||||
--- COHORT class version.
|
--- COHORT class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
COHORT.version="0.3.5"
|
COHORT.version="0.3.6"
|
||||||
|
|
||||||
|
--- Global variable to store the unique(!) cohort names
|
||||||
|
_COHORTNAMES={}
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- TODO list
|
-- TODO list
|
||||||
@@ -110,6 +113,17 @@ COHORT.version="0.3.5"
|
|||||||
-- @return #COHORT self
|
-- @return #COHORT self
|
||||||
function COHORT:New(TemplateGroupName, Ngroups, CohortName)
|
function COHORT:New(TemplateGroupName, Ngroups, CohortName)
|
||||||
|
|
||||||
|
-- Name of the cohort.
|
||||||
|
local name=tostring(CohortName or TemplateGroupName)
|
||||||
|
|
||||||
|
-- Cohort name has to be unique or we will get serious problems!
|
||||||
|
if UTILS.IsAnyInTable(_COHORTNAMES, name) then
|
||||||
|
env.error(string.format('ERROR: cannot create cohort "%s" because another cohort with that name already exists. Names must be unique!', name))
|
||||||
|
return nil
|
||||||
|
else
|
||||||
|
table.insert(_COHORTNAMES, name)
|
||||||
|
end
|
||||||
|
|
||||||
-- Inherit everything from FSM class.
|
-- Inherit everything from FSM class.
|
||||||
local self=BASE:Inherit(self, FSM:New()) -- #COHORT
|
local self=BASE:Inherit(self, FSM:New()) -- #COHORT
|
||||||
|
|
||||||
@@ -117,7 +131,7 @@ function COHORT:New(TemplateGroupName, Ngroups, CohortName)
|
|||||||
self.templatename=TemplateGroupName
|
self.templatename=TemplateGroupName
|
||||||
|
|
||||||
-- Cohort name.
|
-- Cohort name.
|
||||||
self.name=tostring(CohortName or TemplateGroupName)
|
self.name=name
|
||||||
|
|
||||||
-- Set some string id for output to DCS.log file.
|
-- Set some string id for output to DCS.log file.
|
||||||
self.lid=string.format("COHORT %s | ", self.name)
|
self.lid=string.format("COHORT %s | ", self.name)
|
||||||
@@ -577,7 +591,7 @@ function COHORT:AddAsset(Asset)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Remove asset from chort.
|
--- Remove specific asset from chort.
|
||||||
-- @param #COHORT self
|
-- @param #COHORT self
|
||||||
-- @param Functional.Warehouse#WAREHOUSE.Assetitem Asset The asset.
|
-- @param Functional.Warehouse#WAREHOUSE.Assetitem Asset The asset.
|
||||||
-- @return #COHORT self
|
-- @return #COHORT self
|
||||||
@@ -609,6 +623,40 @@ function COHORT:DelGroup(GroupName)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Remove assets from pool. Not that assets must not be spawned or already reserved or requested.
|
||||||
|
-- @param #COHORT self
|
||||||
|
-- @param #number N Number of assets to be removed. Default 1.
|
||||||
|
-- @return #COHORT self
|
||||||
|
function COHORT:RemoveAssets(N)
|
||||||
|
self:T2(self.lid..string.format("Remove %d assets of Cohort", N))
|
||||||
|
|
||||||
|
N=N or 1
|
||||||
|
|
||||||
|
local n=0
|
||||||
|
for i=#self.assets,1,-1 do
|
||||||
|
local asset=self.assets[i] --Functional.Warehouse#WAREHOUSE.Assetitem
|
||||||
|
|
||||||
|
self:T2(self.lid..string.format("Checking removing asset %s", asset.spawngroupname))
|
||||||
|
if not (asset.requested or asset.spawned or asset.isReserved) then
|
||||||
|
self:T2(self.lid..string.format("Removing asset %s", asset.spawngroupname))
|
||||||
|
table.remove(self.assets, i)
|
||||||
|
n=n+1
|
||||||
|
else
|
||||||
|
self:T2(self.lid..string.format("Could NOT Remove asset %s", asset.spawngroupname))
|
||||||
|
end
|
||||||
|
|
||||||
|
if n>=N then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
self:T(self.lid..string.format("Removed %d/%d assets. New asset count=%d", n, N, #self.assets))
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Get name of the cohort.
|
--- Get name of the cohort.
|
||||||
-- @param #COHORT self
|
-- @param #COHORT self
|
||||||
-- @return #string Name of the cohort.
|
-- @return #string Name of the cohort.
|
||||||
@@ -975,6 +1023,7 @@ function COHORT:CanMission(Mission)
|
|||||||
|
|
||||||
if Mission.refuelSystem and Mission.refuelSystem==self.tankerSystem then
|
if Mission.refuelSystem and Mission.refuelSystem==self.tankerSystem then
|
||||||
-- Correct refueling system.
|
-- Correct refueling system.
|
||||||
|
self:T(self.lid..string.format("INFO: Correct refueling system requested=%s != %s=available", tostring(Mission.refuelSystem), tostring(self.tankerSystem)))
|
||||||
else
|
else
|
||||||
self:T(self.lid..string.format("INFO: Wrong refueling system requested=%s != %s=available", tostring(Mission.refuelSystem), tostring(self.tankerSystem)))
|
self:T(self.lid..string.format("INFO: Wrong refueling system requested=%s != %s=available", tostring(Mission.refuelSystem), tostring(self.tankerSystem)))
|
||||||
return false
|
return false
|
||||||
|
|||||||
@@ -1774,8 +1774,10 @@ function COMMANDER:RecruitAssetsForMission(Mission)
|
|||||||
MaxWeight=cohort.cargobayLimit
|
MaxWeight=cohort.cargobayLimit
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
self:T(self.lid..string.format("Largest cargo bay available=%.1f", MaxWeight))
|
if MaxWeight then
|
||||||
|
self:T(self.lid..string.format("Largest cargo bay available=%.1f", MaxWeight))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local legions=self.legions
|
local legions=self.legions
|
||||||
@@ -2165,4 +2167,4 @@ end
|
|||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
--
|
--
|
||||||
-------------------------------------------------------------------------
|
-------------------------------------------------------------------------
|
||||||
-- Date: September 2023
|
-- Date: September 2023
|
||||||
|
-- Last Update: July 2024
|
||||||
-------------------------------------------------------------------------
|
-------------------------------------------------------------------------
|
||||||
--
|
--
|
||||||
--- **Ops** - Easy GCI & CAP Manager
|
--- **Ops** - Easy GCI & CAP Manager
|
||||||
@@ -49,7 +50,7 @@
|
|||||||
-- @field #number capleg
|
-- @field #number capleg
|
||||||
-- @field #number maxinterceptsize
|
-- @field #number maxinterceptsize
|
||||||
-- @field #number missionrange
|
-- @field #number missionrange
|
||||||
-- @field #number noaltert5
|
-- @field #number noalert5
|
||||||
-- @field #table ManagedAW
|
-- @field #table ManagedAW
|
||||||
-- @field #table ManagedSQ
|
-- @field #table ManagedSQ
|
||||||
-- @field #table ManagedCP
|
-- @field #table ManagedCP
|
||||||
@@ -67,6 +68,7 @@
|
|||||||
-- @field #table ReadyFlightGroups
|
-- @field #table ReadyFlightGroups
|
||||||
-- @field #boolean DespawnAfterLanding
|
-- @field #boolean DespawnAfterLanding
|
||||||
-- @field #boolean DespawnAfterHolding
|
-- @field #boolean DespawnAfterHolding
|
||||||
|
-- @field #list<Ops.Auftrag#AUFTRAG> ListOfAuftrag
|
||||||
-- @extends Core.Fsm#FSM
|
-- @extends Core.Fsm#FSM
|
||||||
|
|
||||||
--- *“Airspeed, altitude, and brains. Two are always needed to successfully complete the flight.”* -- Unknown.
|
--- *“Airspeed, altitude, and brains. Two are always needed to successfully complete the flight.”* -- Unknown.
|
||||||
@@ -95,7 +97,8 @@
|
|||||||
--
|
--
|
||||||
-- ### Prerequisites
|
-- ### Prerequisites
|
||||||
--
|
--
|
||||||
-- You have to put a STATIC object on the airbase with the UNIT name according to the name of the airbase. E.g. for Kuitaisi this has to have the name Kutaisi. This object symbolizes the AirWing HQ.
|
-- You have to put a **STATIC WAREHOUSE** object on the airbase with the UNIT name according to the name of the airbase. **Do not put any other static type or it creates a conflict with the airbase name!**
|
||||||
|
-- E.g. for Kuitaisi this has to have the unit name Kutaisi. This object symbolizes the AirWing HQ.
|
||||||
-- Next put a late activated template group for your CAP/GCI Squadron on the map. Last, put a zone on the map for the CAP operations, let's name it "Blue Zone 1". Size of the zone plays no role.
|
-- Next put a late activated template group for your CAP/GCI Squadron on the map. Last, put a zone on the map for the CAP operations, let's name it "Blue Zone 1". Size of the zone plays no role.
|
||||||
-- Put an EW radar system on the map and name it aptly, like "Blue EWR".
|
-- Put an EW radar system on the map and name it aptly, like "Blue EWR".
|
||||||
--
|
--
|
||||||
@@ -164,7 +167,7 @@
|
|||||||
-- * @{#EASYGCICAP.SetDefaultCAPLeg}: Set the length of the CAP leg, default is 15 NM.
|
-- * @{#EASYGCICAP.SetDefaultCAPLeg}: Set the length of the CAP leg, default is 15 NM.
|
||||||
-- * @{#EASYGCICAP.SetDefaultCAPGrouping}: Set how many planes will be spawned per mission (CVAP/GCI), defaults to 2.
|
-- * @{#EASYGCICAP.SetDefaultCAPGrouping}: Set how many planes will be spawned per mission (CVAP/GCI), defaults to 2.
|
||||||
-- * @{#EASYGCICAP.SetDefaultMissionRange}: Set how many NM the planes can go from the home base, defaults to 100.
|
-- * @{#EASYGCICAP.SetDefaultMissionRange}: Set how many NM the planes can go from the home base, defaults to 100.
|
||||||
-- * @{#EASYGCICAP.SetDefaultNumberAlter5Standby}: Set how many planes will be spawned on cold standby (Alert5), default 2.
|
-- * @{#EASYGCICAP.SetDefaultNumberAlert5Standby}: Set how many planes will be spawned on cold standby (Alert5), default 2.
|
||||||
-- * @{#EASYGCICAP.SetDefaultEngageRange}: Set max engage range for CAP flights if they detect intruders, defaults to 50.
|
-- * @{#EASYGCICAP.SetDefaultEngageRange}: Set max engage range for CAP flights if they detect intruders, defaults to 50.
|
||||||
-- * @{#EASYGCICAP.SetMaxAliveMissions}: Set max parallel missions can be done (CAP+GCI+Alert5+Tanker+AWACS), defaults to 8.
|
-- * @{#EASYGCICAP.SetMaxAliveMissions}: Set max parallel missions can be done (CAP+GCI+Alert5+Tanker+AWACS), defaults to 8.
|
||||||
-- * @{#EASYGCICAP.SetDefaultRepeatOnFailure}: Set max repeats on failure for intercepting/killing intruders, defaults to 3.
|
-- * @{#EASYGCICAP.SetDefaultRepeatOnFailure}: Set max repeats on failure for intercepting/killing intruders, defaults to 3.
|
||||||
@@ -194,7 +197,7 @@ EASYGCICAP = {
|
|||||||
capleg = 15,
|
capleg = 15,
|
||||||
maxinterceptsize = 2,
|
maxinterceptsize = 2,
|
||||||
missionrange = 100,
|
missionrange = 100,
|
||||||
noaltert5 = 4,
|
noalert5 = 4,
|
||||||
ManagedAW = {},
|
ManagedAW = {},
|
||||||
ManagedSQ = {},
|
ManagedSQ = {},
|
||||||
ManagedCP = {},
|
ManagedCP = {},
|
||||||
@@ -213,6 +216,7 @@ EASYGCICAP = {
|
|||||||
ReadyFlightGroups = {},
|
ReadyFlightGroups = {},
|
||||||
DespawnAfterLanding = false,
|
DespawnAfterLanding = false,
|
||||||
DespawnAfterHolding = true,
|
DespawnAfterHolding = true,
|
||||||
|
ListOfAuftrag = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Internal Squadron data type
|
--- Internal Squadron data type
|
||||||
@@ -248,7 +252,7 @@ EASYGCICAP = {
|
|||||||
|
|
||||||
--- EASYGCICAP class version.
|
--- EASYGCICAP class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
EASYGCICAP.version="0.1.11"
|
EASYGCICAP.version="0.1.17"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- TODO list
|
-- TODO list
|
||||||
@@ -265,7 +269,7 @@ EASYGCICAP.version="0.1.11"
|
|||||||
-- @param #string Alias A Name for this GCICAP
|
-- @param #string Alias A Name for this GCICAP
|
||||||
-- @param #string AirbaseName Name of the Home Airbase
|
-- @param #string AirbaseName Name of the Home Airbase
|
||||||
-- @param #string Coalition Coalition, e.g. "blue" or "red"
|
-- @param #string Coalition Coalition, e.g. "blue" or "red"
|
||||||
-- @param #string EWRName (Partial) group name of the EWR system of the coalition, e.g. "Red EWR"
|
-- @param #string EWRName (Partial) group name of the EWR system of the coalition, e.g. "Red EWR", can be handed in as table of names, e.g.{"EWR","Radar","SAM"}
|
||||||
-- @return #EASYGCICAP self
|
-- @return #EASYGCICAP self
|
||||||
function EASYGCICAP:New(Alias, AirbaseName, Coalition, EWRName)
|
function EASYGCICAP:New(Alias, AirbaseName, Coalition, EWRName)
|
||||||
-- Inherit everything from FSM class.
|
-- Inherit everything from FSM class.
|
||||||
@@ -274,9 +278,10 @@ function EASYGCICAP:New(Alias, AirbaseName, Coalition, EWRName)
|
|||||||
-- defaults
|
-- defaults
|
||||||
self.alias = Alias or AirbaseName.." CAP Wing"
|
self.alias = Alias or AirbaseName.." CAP Wing"
|
||||||
self.coalitionname = string.lower(Coalition) or "blue"
|
self.coalitionname = string.lower(Coalition) or "blue"
|
||||||
self.coalition = self.coaltitionname == "blue" and coalition.side.BLUE or coalition.side.RED
|
self.coalition = self.coalitionname == "blue" and coalition.side.BLUE or coalition.side.RED
|
||||||
self.wings = {}
|
self.wings = {}
|
||||||
self.EWRName = EWRName or self.coalitionname.." EWR"
|
if type(EWRName) == "string" then EWRName = {EWRName} end
|
||||||
|
self.EWRName = EWRName --or self.coalitionname.." EWR"
|
||||||
--self.CapZoneName = CapZoneName
|
--self.CapZoneName = CapZoneName
|
||||||
self.airbasename = AirbaseName
|
self.airbasename = AirbaseName
|
||||||
self.airbase = AIRBASE:FindByName(self.airbasename)
|
self.airbase = AIRBASE:FindByName(self.airbasename)
|
||||||
@@ -289,7 +294,7 @@ function EASYGCICAP:New(Alias, AirbaseName, Coalition, EWRName)
|
|||||||
self.capleg = 15
|
self.capleg = 15
|
||||||
self.capgrouping = 2
|
self.capgrouping = 2
|
||||||
self.missionrange = 100
|
self.missionrange = 100
|
||||||
self.noaltert5 = 2
|
self.noalert5 = 2
|
||||||
self.MaxAliveMissions = 8
|
self.MaxAliveMissions = 8
|
||||||
self.engagerange = 50
|
self.engagerange = 50
|
||||||
self.repeatsonfailure = 3
|
self.repeatsonfailure = 3
|
||||||
@@ -298,6 +303,7 @@ function EASYGCICAP:New(Alias, AirbaseName, Coalition, EWRName)
|
|||||||
self.CapFormation = ENUMS.Formation.FixedWing.FingerFour.Group
|
self.CapFormation = ENUMS.Formation.FixedWing.FingerFour.Group
|
||||||
self.DespawnAfterLanding = false
|
self.DespawnAfterLanding = false
|
||||||
self.DespawnAfterHolding = true
|
self.DespawnAfterHolding = true
|
||||||
|
self.ListOfAuftrag = {}
|
||||||
|
|
||||||
-- Set some string id for output to DCS.log file.
|
-- Set some string id for output to DCS.log file.
|
||||||
self.lid=string.format("EASYGCICAP %s | ", self.alias)
|
self.lid=string.format("EASYGCICAP %s | ", self.alias)
|
||||||
@@ -342,9 +348,23 @@ function EASYGCICAP:SetTankerAndAWACSInvisible(Switch)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Set Maximum of alive missions to stop airplanes spamming the map
|
--- Count alive missions in our internal stack.
|
||||||
-- @param #EASYGCICAP self
|
-- @param #EASYGCICAP self
|
||||||
-- @param #number Maxiumum Maxmimum number of parallel missions allowed. Count is Cap-Missions + Intercept-Missions + Alert5-Missionsm default is 6
|
-- @return #number count
|
||||||
|
function EASYGCICAP:_CountAliveAuftrags()
|
||||||
|
local alive = 0
|
||||||
|
for _,_auftrag in pairs(self.ListOfAuftrag) do
|
||||||
|
local auftrag = _auftrag -- Ops.Auftrag#AUFTRAG
|
||||||
|
if auftrag and (not (auftrag:IsCancelled() or auftrag:IsDone() or auftrag:IsOver())) then
|
||||||
|
alive = alive + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return alive
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Set Maximum of alive missions created by this instance to stop airplanes spamming the map
|
||||||
|
-- @param #EASYGCICAP self
|
||||||
|
-- @param #number Maxiumum Maxmimum number of parallel missions allowed. Count is Intercept-Missions + Alert5-Missions, default is 8
|
||||||
-- @return #EASYGCICAP self
|
-- @return #EASYGCICAP self
|
||||||
function EASYGCICAP:SetMaxAliveMissions(Maxiumum)
|
function EASYGCICAP:SetMaxAliveMissions(Maxiumum)
|
||||||
self:T(self.lid.."SetMaxAliveMissions")
|
self:T(self.lid.."SetMaxAliveMissions")
|
||||||
@@ -436,9 +456,9 @@ end
|
|||||||
-- @param #EASYGCICAP self
|
-- @param #EASYGCICAP self
|
||||||
-- @param #number Airframes defaults to 2
|
-- @param #number Airframes defaults to 2
|
||||||
-- @return #EASYGCICAP self
|
-- @return #EASYGCICAP self
|
||||||
function EASYGCICAP:SetDefaultNumberAlter5Standby(Airframes)
|
function EASYGCICAP:SetDefaultNumberAlert5Standby(Airframes)
|
||||||
self:T(self.lid.."SetDefaultNumberAlter5Standby")
|
self:T(self.lid.."SetDefaultNumberAlert5Standby")
|
||||||
self.noaltert5 = math.abs(Airframes) or 2
|
self.noalert5 = math.abs(Airframes) or 2
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -447,7 +467,7 @@ end
|
|||||||
-- @param #number Range defaults to 50NM
|
-- @param #number Range defaults to 50NM
|
||||||
-- @return #EASYGCICAP self
|
-- @return #EASYGCICAP self
|
||||||
function EASYGCICAP:SetDefaultEngageRange(Range)
|
function EASYGCICAP:SetDefaultEngageRange(Range)
|
||||||
self:T(self.lid.."SetDefaultNumberAlter5Standby")
|
self:T(self.lid.."SetDefaultEngageRange")
|
||||||
self.engagerange = Range or 50
|
self.engagerange = Range or 50
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
@@ -579,7 +599,7 @@ function EASYGCICAP:_AddAirwing(Airbasename, Alias)
|
|||||||
|
|
||||||
local TankerInvisible = self.TankerInvisible
|
local TankerInvisible = self.TankerInvisible
|
||||||
|
|
||||||
function CAP_Wing:OnAfterFlightOnMission(From, Event, To, Flightgroup, Mission)
|
function CAP_Wing:onbeforeFlightOnMission(From, Event, To, Flightgroup, Mission)
|
||||||
local flightgroup = Flightgroup -- Ops.FlightGroup#FLIGHTGROUP
|
local flightgroup = Flightgroup -- Ops.FlightGroup#FLIGHTGROUP
|
||||||
if DespawnAfterLanding then
|
if DespawnAfterLanding then
|
||||||
flightgroup:SetDespawnAfterLanding()
|
flightgroup:SetDespawnAfterLanding()
|
||||||
@@ -609,17 +629,18 @@ function EASYGCICAP:_AddAirwing(Airbasename, Alias)
|
|||||||
flightgroup:SetFuelLowRTB(true)
|
flightgroup:SetFuelLowRTB(true)
|
||||||
Intel:AddAgent(flightgroup)
|
Intel:AddAgent(flightgroup)
|
||||||
if DespawnAfterHolding then
|
if DespawnAfterHolding then
|
||||||
function flightgroup:OnAfterHolding(From,Event,To)
|
function flightgroup:onbeforeHolding(From,Event,To)
|
||||||
self:Despawn(1,true)
|
self:Despawn(1,true)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.noaltert5 > 0 then
|
if self.noalert5 > 0 then
|
||||||
local alert = AUFTRAG:NewALERT5(AUFTRAG.Type.INTERCEPT)
|
local alert = AUFTRAG:NewALERT5(AUFTRAG.Type.INTERCEPT)
|
||||||
alert:SetRequiredAssets(self.noaltert5)
|
alert:SetRequiredAssets(self.noalert5)
|
||||||
alert:SetRepeat(99)
|
alert:SetRepeat(99)
|
||||||
CAP_Wing:AddMission(alert)
|
CAP_Wing:AddMission(alert)
|
||||||
|
table.insert(self.ListOfAuftrag,alert)
|
||||||
end
|
end
|
||||||
|
|
||||||
self.wings[Airbasename] = { CAP_Wing, AIRBASE:FindByName(Airbasename):GetZone(), Airbasename }
|
self.wings[Airbasename] = { CAP_Wing, AIRBASE:FindByName(Airbasename):GetZone(), Airbasename }
|
||||||
@@ -1156,7 +1177,7 @@ function EASYGCICAP:_TryAssignIntercept(ReadyFlightGroups,InterceptAuftrag,Group
|
|||||||
return assigned, wingsize
|
return assigned, wingsize
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Add a zone to the rejected zones set.
|
--- Here, we'll decide if we need to launch an intercepting flight, and from where
|
||||||
-- @param #EASYGCICAP self
|
-- @param #EASYGCICAP self
|
||||||
-- @param Ops.Intel#INTEL.Cluster Cluster
|
-- @param Ops.Intel#INTEL.Cluster Cluster
|
||||||
-- @return #EASYGCICAP self
|
-- @return #EASYGCICAP self
|
||||||
@@ -1170,7 +1191,7 @@ function EASYGCICAP:_AssignIntercept(Cluster)
|
|||||||
|
|
||||||
local wings = self.wings
|
local wings = self.wings
|
||||||
local ctlpts = self.ManagedCP
|
local ctlpts = self.ManagedCP
|
||||||
local MaxAliveMissions = self.MaxAliveMissions * self.capgrouping
|
local MaxAliveMissions = self.MaxAliveMissions --* self.capgrouping
|
||||||
local nogozoneset = self.NoGoZoneSet
|
local nogozoneset = self.NoGoZoneSet
|
||||||
local ReadyFlightGroups = self.ReadyFlightGroups
|
local ReadyFlightGroups = self.ReadyFlightGroups
|
||||||
|
|
||||||
@@ -1200,9 +1221,11 @@ function EASYGCICAP:_AssignIntercept(Cluster)
|
|||||||
local zone = _data[2] -- Core.Zone#ZONE
|
local zone = _data[2] -- Core.Zone#ZONE
|
||||||
local zonecoord = zone:GetCoordinate()
|
local zonecoord = zone:GetCoordinate()
|
||||||
local name = _data[3] -- #string
|
local name = _data[3] -- #string
|
||||||
|
local coa = AIRBASE:FindByName(name):GetCoalition()
|
||||||
local distance = position:DistanceFromPointVec2(zonecoord)
|
local distance = position:DistanceFromPointVec2(zonecoord)
|
||||||
local airframes = airwing:CountAssets(true)
|
local airframes = airwing:CountAssets(true)
|
||||||
if distance < bestdistance and airframes >= wingsize then
|
local samecoalitionab = coa == self.coalition and true or false
|
||||||
|
if distance < bestdistance and airframes >= wingsize and samecoalitionab == true then
|
||||||
bestdistance = distance
|
bestdistance = distance
|
||||||
targetairwing = airwing
|
targetairwing = airwing
|
||||||
targetawname = name
|
targetawname = name
|
||||||
@@ -1218,10 +1241,11 @@ function EASYGCICAP:_AssignIntercept(Cluster)
|
|||||||
local name = data.AirbaseName
|
local name = data.AirbaseName
|
||||||
local zonecoord = data.Coordinate
|
local zonecoord = data.Coordinate
|
||||||
local airwing = wings[name][1]
|
local airwing = wings[name][1]
|
||||||
|
local coa = AIRBASE:FindByName(name):GetCoalition()
|
||||||
|
local samecoalitionab = coa == self.coalition and true or false
|
||||||
local distance = position:DistanceFromPointVec2(zonecoord)
|
local distance = position:DistanceFromPointVec2(zonecoord)
|
||||||
local airframes = airwing:CountAssets(true)
|
local airframes = airwing:CountAssets(true)
|
||||||
if distance < bestdistance and airframes >= wingsize then
|
if distance < bestdistance and airframes >= wingsize and samecoalitionab == true then
|
||||||
bestdistance = distance
|
bestdistance = distance
|
||||||
targetairwing = airwing -- Ops.Airwing#AIRWING
|
targetairwing = airwing -- Ops.Airwing#AIRWING
|
||||||
targetawname = name
|
targetawname = name
|
||||||
@@ -1232,9 +1256,10 @@ function EASYGCICAP:_AssignIntercept(Cluster)
|
|||||||
-- Do we have a matching airwing?
|
-- Do we have a matching airwing?
|
||||||
if targetairwing then
|
if targetairwing then
|
||||||
local AssetCount = targetairwing:CountAssetsOnMission(MissionTypes,Cohort)
|
local AssetCount = targetairwing:CountAssetsOnMission(MissionTypes,Cohort)
|
||||||
|
local missioncount = self:_CountAliveAuftrags()
|
||||||
-- Enough airframes on mission already?
|
-- Enough airframes on mission already?
|
||||||
self:T(self.lid.." Assets on Mission "..AssetCount)
|
self:T(self.lid.." Assets on Mission "..AssetCount)
|
||||||
if AssetCount <= MaxAliveMissions then
|
if missioncount < MaxAliveMissions then
|
||||||
local repeats = repeatsonfailure
|
local repeats = repeatsonfailure
|
||||||
local InterceptAuftrag = AUFTRAG:NewINTERCEPT(contact.group)
|
local InterceptAuftrag = AUFTRAG:NewINTERCEPT(contact.group)
|
||||||
:SetMissionRange(150)
|
:SetMissionRange(150)
|
||||||
@@ -1260,6 +1285,8 @@ function EASYGCICAP:_AssignIntercept(Cluster)
|
|||||||
nogozoneset
|
nogozoneset
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
table.insert(self.ListOfAuftrag,InterceptAuftrag)
|
||||||
local assigned, rest = self:_TryAssignIntercept(ReadyFlightGroups,InterceptAuftrag,contact.group,wingsize)
|
local assigned, rest = self:_TryAssignIntercept(ReadyFlightGroups,InterceptAuftrag,contact.group,wingsize)
|
||||||
if not assigned then
|
if not assigned then
|
||||||
InterceptAuftrag:SetRequiredAssets(rest)
|
InterceptAuftrag:SetRequiredAssets(rest)
|
||||||
@@ -1280,11 +1307,11 @@ function EASYGCICAP:_StartIntel()
|
|||||||
self:T(self.lid.."_StartIntel")
|
self:T(self.lid.."_StartIntel")
|
||||||
-- Border GCI Detection
|
-- Border GCI Detection
|
||||||
local BlueAir_DetectionSetGroup = SET_GROUP:New()
|
local BlueAir_DetectionSetGroup = SET_GROUP:New()
|
||||||
BlueAir_DetectionSetGroup:FilterPrefixes( { self.EWRName } )
|
BlueAir_DetectionSetGroup:FilterPrefixes( self.EWRName )
|
||||||
BlueAir_DetectionSetGroup:FilterStart()
|
BlueAir_DetectionSetGroup:FilterStart()
|
||||||
|
|
||||||
-- Intel type detection
|
-- Intel type detection
|
||||||
local BlueIntel = INTEL:New(BlueAir_DetectionSetGroup,self.coalitionname, self.EWRName)
|
local BlueIntel = INTEL:New(BlueAir_DetectionSetGroup,self.coalitionname, self.alias)
|
||||||
BlueIntel:SetClusterAnalysis(true,false,false)
|
BlueIntel:SetClusterAnalysis(true,false,false)
|
||||||
BlueIntel:SetForgetTime(300)
|
BlueIntel:SetForgetTime(300)
|
||||||
BlueIntel:SetAcceptZones(self.GoZoneSet)
|
BlueIntel:SetAcceptZones(self.GoZoneSet)
|
||||||
@@ -1300,7 +1327,7 @@ function EASYGCICAP:_StartIntel()
|
|||||||
self:_AssignIntercept(Cluster)
|
self:_AssignIntercept(Cluster)
|
||||||
end
|
end
|
||||||
|
|
||||||
function BlueIntel:OnAfterNewCluster(From,Event,To,Cluster)
|
function BlueIntel:onbeforeNewCluster(From,Event,To,Cluster)
|
||||||
AssignCluster(Cluster)
|
AssignCluster(Cluster)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1351,6 +1378,20 @@ end
|
|||||||
-- @return #EASYGCICAP self
|
-- @return #EASYGCICAP self
|
||||||
function EASYGCICAP:onafterStatus(From,Event,To)
|
function EASYGCICAP:onafterStatus(From,Event,To)
|
||||||
self:T({From,Event,To})
|
self:T({From,Event,To})
|
||||||
|
-- cleanup
|
||||||
|
local cleaned = false
|
||||||
|
local cleanlist = {}
|
||||||
|
for _,_auftrag in pairs(self.ListOfAuftrag) do
|
||||||
|
local auftrag = _auftrag -- Ops.Auftrag#AUFTRAG
|
||||||
|
if auftrag and (not (auftrag:IsCancelled() or auftrag:IsDone() or auftrag:IsOver())) then
|
||||||
|
table.insert(cleanlist,auftrag)
|
||||||
|
cleaned = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if cleaned == true then
|
||||||
|
self.ListOfAuftrag = nil
|
||||||
|
self.ListOfAuftrag = cleanlist
|
||||||
|
end
|
||||||
-- Gather Some Stats
|
-- Gather Some Stats
|
||||||
local function counttable(tbl)
|
local function counttable(tbl)
|
||||||
local count = 0
|
local count = 0
|
||||||
@@ -1403,12 +1444,14 @@ function EASYGCICAP:onafterStatus(From,Event,To)
|
|||||||
local text = "GCICAP "..self.alias
|
local text = "GCICAP "..self.alias
|
||||||
text = text.."\nWings: "..wings.."\nSquads: "..squads.."\nCapPoints: "..caps.."\nAssets on Mission: "..assets.."\nAssets in Stock: "..instock
|
text = text.."\nWings: "..wings.."\nSquads: "..squads.."\nCapPoints: "..caps.."\nAssets on Mission: "..assets.."\nAssets in Stock: "..instock
|
||||||
text = text.."\nThreats: "..threatcount
|
text = text.."\nThreats: "..threatcount
|
||||||
text = text.."\nMissions: "..capmission+interceptmission
|
text = text.."\nAirWing managed Missions: "..capmission+awacsmission+tankermission+reconmission
|
||||||
text = text.."\n - CAP: "..capmission
|
text = text.."\n - CAP: "..capmission
|
||||||
text = text.."\n - Intercept: "..interceptmission
|
|
||||||
text = text.."\n - AWACS: "..awacsmission
|
text = text.."\n - AWACS: "..awacsmission
|
||||||
text = text.."\n - TANKER: "..tankermission
|
text = text.."\n - TANKER: "..tankermission
|
||||||
text = text.."\n - Recon: "..reconmission
|
text = text.."\n - Recon: "..reconmission
|
||||||
|
text = text.."\nSelf managed Missions:"
|
||||||
|
text = text.."\n - Mission Limit: "..self.MaxAliveMissions
|
||||||
|
text = text.."\n - Alert5+Intercept "..self:_CountAliveAuftrags()
|
||||||
MESSAGE:New(text,15,"GCICAP"):ToAll():ToLogIf(self.debug)
|
MESSAGE:New(text,15,"GCICAP"):ToAll():ToLogIf(self.debug)
|
||||||
end
|
end
|
||||||
self:__Status(30)
|
self:__Status(30)
|
||||||
|
|||||||
@@ -334,6 +334,9 @@ function FLEET:onafterStatus(From, Event, To)
|
|||||||
-- Info ---
|
-- Info ---
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
|
-- Display tactival overview.
|
||||||
|
self:_TacticalOverview()
|
||||||
|
|
||||||
-- General info:
|
-- General info:
|
||||||
if self.verbose>=1 then
|
if self.verbose>=1 then
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -21,6 +21,7 @@
|
|||||||
-- @field #table cohorts Cohorts of this legion.
|
-- @field #table cohorts Cohorts of this legion.
|
||||||
-- @field Ops.Commander#COMMANDER commander Commander of this legion.
|
-- @field Ops.Commander#COMMANDER commander Commander of this legion.
|
||||||
-- @field Ops.Chief#CHIEF chief Chief of this legion.
|
-- @field Ops.Chief#CHIEF chief Chief of this legion.
|
||||||
|
-- @field #boolean tacview If `true`, show tactical overview on status update.
|
||||||
-- @extends Functional.Warehouse#WAREHOUSE
|
-- @extends Functional.Warehouse#WAREHOUSE
|
||||||
|
|
||||||
--- *Per aspera ad astra.*
|
--- *Per aspera ad astra.*
|
||||||
@@ -52,7 +53,7 @@ LEGION.RandomAssetScore=1
|
|||||||
|
|
||||||
--- LEGION class version.
|
--- LEGION class version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
LEGION.version="0.5.0"
|
LEGION.version="0.5.1"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- ToDo list
|
-- ToDo list
|
||||||
@@ -322,6 +323,14 @@ function LEGION:SetVerbosity(VerbosityLevel)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Set tactical overview on.
|
||||||
|
-- @param #LEGION self
|
||||||
|
-- @return #LEGION self
|
||||||
|
function LEGION:SetTacticalOverviewOn()
|
||||||
|
self.tacview=true
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- Add a mission for the legion. It will pick the best available assets for the mission and lauch it when ready.
|
--- Add a mission for the legion. It will pick the best available assets for the mission and lauch it when ready.
|
||||||
-- @param #LEGION self
|
-- @param #LEGION self
|
||||||
-- @param Ops.Auftrag#AUFTRAG Mission Mission for this legion.
|
-- @param Ops.Auftrag#AUFTRAG Mission Mission for this legion.
|
||||||
@@ -436,6 +445,21 @@ function LEGION:DelCohort(Cohort)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Remove specific asset from legion.
|
||||||
|
-- @param #LEGION self
|
||||||
|
-- @param Functional.Warehouse#WAREHOUSE.Assetitem Asset The asset.
|
||||||
|
-- @return #LEGION self
|
||||||
|
function LEGION:DelAsset(Asset)
|
||||||
|
|
||||||
|
if Asset.cohort then
|
||||||
|
Asset.cohort:DelAsset(Asset)
|
||||||
|
else
|
||||||
|
self:E(self.lid..string.format("ERROR: Asset has not cohort attached. Cannot remove it from legion!"))
|
||||||
|
end
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Relocate a cohort to another legion.
|
--- Relocate a cohort to another legion.
|
||||||
-- Assets in stock are spawned and routed to the new legion.
|
-- Assets in stock are spawned and routed to the new legion.
|
||||||
@@ -1634,6 +1658,9 @@ function LEGION:onafterAssetDead(From, Event, To, asset, request)
|
|||||||
if self.commander and self.commander.chief then
|
if self.commander and self.commander.chief then
|
||||||
self.commander.chief.detectionset:RemoveGroupsByName({asset.spawngroupname})
|
self.commander.chief.detectionset:RemoveGroupsByName({asset.spawngroupname})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Remove asset from cohort and legion.
|
||||||
|
self:DelAsset(asset)
|
||||||
|
|
||||||
-- Remove asset from mission is done via Mission:AssetDead() call from flightgroup onafterFlightDead function
|
-- Remove asset from mission is done via Mission:AssetDead() call from flightgroup onafterFlightDead function
|
||||||
-- Remove asset from squadron same
|
-- Remove asset from squadron same
|
||||||
@@ -1772,7 +1799,7 @@ end
|
|||||||
-- Mission Functions
|
-- Mission Functions
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
--- Create a new flight group after an asset was spawned.
|
--- Create a new OPS group after an asset was spawned.
|
||||||
-- @param #LEGION self
|
-- @param #LEGION self
|
||||||
-- @param Functional.Warehouse#WAREHOUSE.Assetitem asset The asset.
|
-- @param Functional.Warehouse#WAREHOUSE.Assetitem asset The asset.
|
||||||
-- @return Ops.FlightGroup#FLIGHTGROUP The created flightgroup object.
|
-- @return Ops.FlightGroup#FLIGHTGROUP The created flightgroup object.
|
||||||
@@ -1818,6 +1845,9 @@ function LEGION:_CreateFlightGroup(asset)
|
|||||||
-- Set home base.
|
-- Set home base.
|
||||||
opsgroup.homebase=self.airbase
|
opsgroup.homebase=self.airbase
|
||||||
|
|
||||||
|
-- Set destination base
|
||||||
|
opsgroup.destbase=self.airbase
|
||||||
|
|
||||||
-- Set home zone.
|
-- Set home zone.
|
||||||
opsgroup.homezone=self.spawnzone
|
opsgroup.homezone=self.spawnzone
|
||||||
|
|
||||||
@@ -1836,6 +1866,53 @@ function LEGION:_CreateFlightGroup(asset)
|
|||||||
return opsgroup
|
return opsgroup
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Display tactical overview.
|
||||||
|
-- @param #LEGION self
|
||||||
|
function LEGION:_TacticalOverview()
|
||||||
|
|
||||||
|
if self.tacview then
|
||||||
|
|
||||||
|
local NassetsTotal=self:CountAssets(nil)
|
||||||
|
local NassetsStock=self:CountAssets(true)
|
||||||
|
local NassetsActiv=self:CountAssets(false)
|
||||||
|
|
||||||
|
local NmissionsTotal=#self.missionqueue
|
||||||
|
local NmissionsRunni=self:CountMissionsInQueue()
|
||||||
|
|
||||||
|
-- Info message
|
||||||
|
local text=string.format("Tactical Overview %s\n", self.alias)
|
||||||
|
text=text..string.format("===================================\n")
|
||||||
|
|
||||||
|
-- Asset info.
|
||||||
|
text=text..string.format("Assets: %d [Active=%d, Stock=%d]\n", NassetsTotal, NassetsActiv, NassetsStock)
|
||||||
|
|
||||||
|
-- Mission info.
|
||||||
|
text=text..string.format("Missions: %d [Running=%d]\n", NmissionsTotal, NmissionsRunni)
|
||||||
|
for _,mtype in pairs(AUFTRAG.Type) do
|
||||||
|
local n=self:CountMissionsInQueue(mtype)
|
||||||
|
if n>0 then
|
||||||
|
local N=self:CountMissionsInQueue(mtype)
|
||||||
|
text=text..string.format(" - %s: %d [Running=%d]\n", mtype, n, N)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local Ntransports=#self.transportqueue
|
||||||
|
if Ntransports>0 then
|
||||||
|
text=text..string.format("Transports: %d\n", Ntransports)
|
||||||
|
for _,_transport in pairs(self.transportqueue) do
|
||||||
|
local transport=_transport --Ops.OpsTransport#OPSTRANSPORT
|
||||||
|
text=text..string.format(" - %s", transport:GetState())
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Message to coalition.
|
||||||
|
MESSAGE:New(text, 60, nil, true):ToCoalition(self:GetCoalition())
|
||||||
|
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
--- Check if an asset is currently on a mission (STARTED or EXECUTING).
|
--- Check if an asset is currently on a mission (STARTED or EXECUTING).
|
||||||
-- @param #LEGION self
|
-- @param #LEGION self
|
||||||
@@ -2563,6 +2640,8 @@ function LEGION._CohortCan(Cohort, MissionType, Categories, Attributes, Properti
|
|||||||
local RangeMax = RangeMax or 0
|
local RangeMax = RangeMax or 0
|
||||||
local InRange=(RangeMax and math.max(RangeMax, Rmax) or Rmax) >= TargetDistance
|
local InRange=(RangeMax and math.max(RangeMax, Rmax) or Rmax) >= TargetDistance
|
||||||
|
|
||||||
|
--env.info(string.format("Range TargetDist=%.1f Rmax=%.1f RangeMax=%.1f InRange=%s", TargetDistance, Rmax, RangeMax, tostring(InRange)))
|
||||||
|
|
||||||
return InRange
|
return InRange
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -2628,7 +2707,7 @@ function LEGION._CohortCan(Cohort, MissionType, Categories, Attributes, Properti
|
|||||||
else
|
else
|
||||||
Cohort:T(Cohort.lid..string.format("Cohort %s cannot because of category", Cohort.name))
|
Cohort:T(Cohort.lid..string.format("Cohort %s cannot because of category", Cohort.name))
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
if can then
|
if can then
|
||||||
can=CheckAttribute(Cohort)
|
can=CheckAttribute(Cohort)
|
||||||
@@ -2684,7 +2763,7 @@ function LEGION._CohortCan(Cohort, MissionType, Categories, Attributes, Properti
|
|||||||
else
|
else
|
||||||
Cohort:T(Cohort.lid..string.format("Cohort %s cannot because of max weight", Cohort.name))
|
Cohort:T(Cohort.lid..string.format("Cohort %s cannot because of max weight", Cohort.name))
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
@@ -2728,6 +2807,8 @@ function LEGION.RecruitCohortAssets(Cohorts, MissionTypeRecruit, MissionTypeOpt,
|
|||||||
|
|
||||||
-- Check if cohort can do the mission.
|
-- Check if cohort can do the mission.
|
||||||
local can=LEGION._CohortCan(cohort, MissionTypeRecruit, Categories, Attributes, Properties, WeaponTypes, TargetVec2, RangeMax, RefuelSystem, CargoWeight, MaxWeight)
|
local can=LEGION._CohortCan(cohort, MissionTypeRecruit, Categories, Attributes, Properties, WeaponTypes, TargetVec2, RangeMax, RefuelSystem, CargoWeight, MaxWeight)
|
||||||
|
|
||||||
|
--env.info(string.format("RecruitCohortAssets %s Cohort=%s can=%s", MissionTypeRecruit, cohort:GetName(), tostring(can)))
|
||||||
|
|
||||||
-- Check OnDuty, capable, in range and refueling type (if TANKER).
|
-- Check OnDuty, capable, in range and refueling type (if TANKER).
|
||||||
if can then
|
if can then
|
||||||
@@ -2744,6 +2825,12 @@ function LEGION.RecruitCohortAssets(Cohorts, MissionTypeRecruit, MissionTypeOpt,
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Break if no assets could be found
|
||||||
|
if #Assets==0 then
|
||||||
|
--env.info(string.format("LEGION.RecruitCohortAssets: No assets could be recruited for mission type %s [Nmin=%s, Nmax=%s]", MissionTypeRecruit, tostring(NreqMin), tostring(NreqMax)))
|
||||||
|
return false, {}, {}
|
||||||
|
end
|
||||||
|
|
||||||
-- Now we have a long list with assets.
|
-- Now we have a long list with assets.
|
||||||
LEGION._OptimizeAssetSelection(Assets, MissionTypeOpt, TargetVec2, false, TotalWeight)
|
LEGION._OptimizeAssetSelection(Assets, MissionTypeOpt, TargetVec2, false, TotalWeight)
|
||||||
|
|
||||||
|
|||||||
@@ -44,6 +44,7 @@
|
|||||||
-- @field #number pathCorridor Path corrdidor width in meters.
|
-- @field #number pathCorridor Path corrdidor width in meters.
|
||||||
-- @field #boolean ispathfinding If true, group is currently path finding.
|
-- @field #boolean ispathfinding If true, group is currently path finding.
|
||||||
-- @field #NAVYGROUP.Target engage Engage target.
|
-- @field #NAVYGROUP.Target engage Engage target.
|
||||||
|
-- @field #boolean intowindold Use old calculation to determine heading into wind.
|
||||||
-- @extends Ops.OpsGroup#OPSGROUP
|
-- @extends Ops.OpsGroup#OPSGROUP
|
||||||
|
|
||||||
--- *Something must be left to chance; nothing is sure in a sea fight above all.* -- Horatio Nelson
|
--- *Something must be left to chance; nothing is sure in a sea fight above all.* -- Horatio Nelson
|
||||||
@@ -90,7 +91,7 @@ NAVYGROUP = {
|
|||||||
|
|
||||||
--- NavyGroup version.
|
--- NavyGroup version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
NAVYGROUP.version="1.0.2"
|
NAVYGROUP.version="1.0.3"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- TODO list
|
-- TODO list
|
||||||
@@ -393,7 +394,8 @@ function NAVYGROUP:New(group)
|
|||||||
-- Handle events:
|
-- Handle events:
|
||||||
self:HandleEvent(EVENTS.Birth, self.OnEventBirth)
|
self:HandleEvent(EVENTS.Birth, self.OnEventBirth)
|
||||||
self:HandleEvent(EVENTS.Dead, self.OnEventDead)
|
self:HandleEvent(EVENTS.Dead, self.OnEventDead)
|
||||||
self:HandleEvent(EVENTS.RemoveUnit, self.OnEventRemoveUnit)
|
self:HandleEvent(EVENTS.RemoveUnit, self.OnEventRemoveUnit)
|
||||||
|
self:HandleEvent(EVENTS.UnitLost, self.OnEventRemoveUnit)
|
||||||
|
|
||||||
-- Start the status monitoring.
|
-- Start the status monitoring.
|
||||||
self.timerStatus=TIMER:New(self.Status, self):Start(1, 30)
|
self.timerStatus=TIMER:New(self.Status, self):Start(1, 30)
|
||||||
@@ -455,6 +457,18 @@ function NAVYGROUP:SetPathfindingOff()
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Set if old into wind calculation is used when carrier turns into the wind for a recovery.
|
||||||
|
-- @param #NAVYGROUP self
|
||||||
|
-- @param #boolean SwitchOn If `true` or `nil`, use old into wind calculation.
|
||||||
|
-- @return #NAVYGROUP self
|
||||||
|
function NAVYGROUP:SetIntoWindLegacy( SwitchOn )
|
||||||
|
if SwitchOn==nil then
|
||||||
|
SwitchOn=true
|
||||||
|
end
|
||||||
|
self.intowindold=SwitchOn
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Add a *scheduled* task.
|
--- Add a *scheduled* task.
|
||||||
-- @param #NAVYGROUP self
|
-- @param #NAVYGROUP self
|
||||||
@@ -600,6 +614,58 @@ function NAVYGROUP:AddTurnIntoWind(starttime, stoptime, speed, uturn, offset)
|
|||||||
return recovery
|
return recovery
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Get "Turn Into Wind" data. You can specify a certain ID.
|
||||||
|
-- @param #NAVYGROUP self
|
||||||
|
-- @param #number TID (Optional) Turn Into wind ID. If not given, the currently open "Turn into Wind" data is return (if there is any).
|
||||||
|
-- @return #NAVYGROUP.IntoWind Turn into window data table.
|
||||||
|
function NAVYGROUP:GetTurnIntoWind(TID)
|
||||||
|
|
||||||
|
if TID then
|
||||||
|
|
||||||
|
-- Look for a specific ID.
|
||||||
|
for _,_turn in pairs(self.Qintowind) do
|
||||||
|
local turn=_turn --#NAVYGROUP.IntoWind
|
||||||
|
if turn.Id==TID then
|
||||||
|
return turn
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
-- Return currently open window.
|
||||||
|
return self.intowind
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Extend duration of turn into wind.
|
||||||
|
-- @param #NAVYGROUP self
|
||||||
|
-- @param #number Duration Duration in seconds. Default 300 sec.
|
||||||
|
-- @param #NAVYGROUP.IntoWind TurnIntoWind (Optional) Turn into window data table. If not given, the currently open one is used (if there is any).
|
||||||
|
-- @return #NAVYGROUP self
|
||||||
|
function NAVYGROUP:ExtendTurnIntoWind(Duration, TurnIntoWind)
|
||||||
|
|
||||||
|
Duration=Duration or 300
|
||||||
|
|
||||||
|
-- ID of turn or nil
|
||||||
|
local TID=TurnIntoWind and TurnIntoWind.Id or nil
|
||||||
|
|
||||||
|
-- Get turn data.
|
||||||
|
local turn=self:GetTurnIntoWind(TID)
|
||||||
|
|
||||||
|
if turn then
|
||||||
|
turn.Tstop=turn.Tstop+Duration
|
||||||
|
self:T(self.lid..string.format("Extending turn into wind by %d seconds. New stop time is %s", Duration, UTILS.SecondsToClock(turn.Tstop)))
|
||||||
|
else
|
||||||
|
self:E(self.lid.."Could not get turn into wind to extend!")
|
||||||
|
end
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Remove steam into wind window from queue. If the window is currently active, it is stopped first.
|
--- Remove steam into wind window from queue. If the window is currently active, it is stopped first.
|
||||||
-- @param #NAVYGROUP self
|
-- @param #NAVYGROUP self
|
||||||
-- @param #NAVYGROUP.IntoWind IntoWindData Turn into window data table.
|
-- @param #NAVYGROUP.IntoWind IntoWindData Turn into window data table.
|
||||||
@@ -709,7 +775,7 @@ end
|
|||||||
|
|
||||||
--- Update status.
|
--- Update status.
|
||||||
-- @param #NAVYGROUP self
|
-- @param #NAVYGROUP self
|
||||||
function NAVYGROUP:Status(From, Event, To)
|
function NAVYGROUP:Status()
|
||||||
|
|
||||||
-- FSM state.
|
-- FSM state.
|
||||||
local fsmstate=self:GetState()
|
local fsmstate=self:GetState()
|
||||||
@@ -912,6 +978,35 @@ function NAVYGROUP:Status(From, Event, To)
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
---
|
||||||
|
-- Elements
|
||||||
|
---
|
||||||
|
|
||||||
|
if self.verbose>=2 then
|
||||||
|
local text="Elements:"
|
||||||
|
for i,_element in pairs(self.elements) do
|
||||||
|
local element=_element --Ops.OpsGroup#OPSGROUP.Element
|
||||||
|
|
||||||
|
local name=element.name
|
||||||
|
local status=element.status
|
||||||
|
local unit=element.unit
|
||||||
|
local life,life0=self:GetLifePoints(element)
|
||||||
|
|
||||||
|
local life0=element.life0
|
||||||
|
|
||||||
|
-- Get ammo.
|
||||||
|
local ammo=self:GetAmmoElement(element)
|
||||||
|
|
||||||
|
-- Output text for element.
|
||||||
|
text=text..string.format("\n[%d] %s: status=%s, life=%.1f/%.1f, guns=%d, rockets=%d, bombs=%d, missiles=%d, cargo=%d/%d kg",
|
||||||
|
i, name, status, life, life0, ammo.Guns, ammo.Rockets, ammo.Bombs, ammo.Missiles, element.weightCargo, element.weightMaxCargo)
|
||||||
|
end
|
||||||
|
if #self.elements==0 then
|
||||||
|
text=text.." none!"
|
||||||
|
end
|
||||||
|
self:I(self.lid..text)
|
||||||
|
end
|
||||||
|
|
||||||
---
|
---
|
||||||
-- Engage Detected Targets
|
-- Engage Detected Targets
|
||||||
---
|
---
|
||||||
@@ -975,7 +1070,7 @@ function NAVYGROUP:onafterSpawned(From, Event, To)
|
|||||||
|
|
||||||
-- Debug info.
|
-- Debug info.
|
||||||
if self.verbose>=1 then
|
if self.verbose>=1 then
|
||||||
local text=string.format("Initialized Navy Group %s:\n", self.groupname)
|
local text=string.format("Initialized Navy Group %s [GID=%d]:\n", self.groupname, self.group:GetID())
|
||||||
text=text..string.format("Unit type = %s\n", self.actype)
|
text=text..string.format("Unit type = %s\n", self.actype)
|
||||||
text=text..string.format("Speed max = %.1f Knots\n", UTILS.KmphToKnots(self.speedMax))
|
text=text..string.format("Speed max = %.1f Knots\n", UTILS.KmphToKnots(self.speedMax))
|
||||||
text=text..string.format("Speed cruise = %.1f Knots\n", UTILS.KmphToKnots(self.speedCruise))
|
text=text..string.format("Speed cruise = %.1f Knots\n", UTILS.KmphToKnots(self.speedCruise))
|
||||||
@@ -1203,7 +1298,7 @@ function NAVYGROUP:onafterUpdateRoute(From, Event, To, n, N, Speed, Depth)
|
|||||||
if self.verbose>=10 then
|
if self.verbose>=10 then
|
||||||
for i=1,#waypoints do
|
for i=1,#waypoints do
|
||||||
local wp=waypoints[i] --Ops.OpsGroup#OPSGROUP.Waypoint
|
local wp=waypoints[i] --Ops.OpsGroup#OPSGROUP.Waypoint
|
||||||
local text=string.format("%s Waypoint [%d] UID=%d speed=%d", self.groupname, i-1, wp.uid or -1, wp.speed)
|
local text=string.format("%s Waypoint [%d] UID=%d speed=%d m/s", self.groupname, i-1, wp.uid or -1, wp.speed)
|
||||||
self:I(self.lid..text)
|
self:I(self.lid..text)
|
||||||
COORDINATE:NewFromWaypoint(wp):MarkToAll(text)
|
COORDINATE:NewFromWaypoint(wp):MarkToAll(text)
|
||||||
end
|
end
|
||||||
@@ -1775,81 +1870,96 @@ end
|
|||||||
--- Initialize group parameters. Also initializes waypoints if self.waypoints is nil.
|
--- Initialize group parameters. Also initializes waypoints if self.waypoints is nil.
|
||||||
-- @param #NAVYGROUP self
|
-- @param #NAVYGROUP self
|
||||||
-- @param #table Template Template used to init the group. Default is `self.template`.
|
-- @param #table Template Template used to init the group. Default is `self.template`.
|
||||||
|
-- @param #number Delay Delay in seconds before group is initialized. Default `nil`, *i.e.* instantaneous.
|
||||||
-- @return #NAVYGROUP self
|
-- @return #NAVYGROUP self
|
||||||
function NAVYGROUP:_InitGroup(Template)
|
function NAVYGROUP:_InitGroup(Template, Delay)
|
||||||
|
|
||||||
-- First check if group was already initialized.
|
if Delay and Delay>0 then
|
||||||
if self.groupinitialized then
|
-- Delayed call
|
||||||
self:T(self.lid.."WARNING: Group was already initialized! Will NOT do it again!")
|
self:ScheduleOnce(Delay, NAVYGROUP._InitGroup, self, Template, 0)
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Get template of group.
|
|
||||||
local template=Template or self:_GetTemplate()
|
|
||||||
|
|
||||||
-- Ships are always AI.
|
|
||||||
self.isAI=true
|
|
||||||
|
|
||||||
-- Is (template) group late activated.
|
|
||||||
self.isLateActivated=template.lateActivation
|
|
||||||
|
|
||||||
-- Naval groups cannot be uncontrolled.
|
|
||||||
self.isUncontrolled=false
|
|
||||||
|
|
||||||
-- Max speed in km/h.
|
|
||||||
self.speedMax=self.group:GetSpeedMax()
|
|
||||||
|
|
||||||
-- Is group mobile?
|
|
||||||
if self.speedMax and self.speedMax>3.6 then
|
|
||||||
self.isMobile=true
|
|
||||||
else
|
else
|
||||||
self.isMobile=false
|
|
||||||
self.speedMax = 0
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Cruise speed: 70% of max speed.
|
-- First check if group was already initialized.
|
||||||
self.speedCruise=self.speedMax*0.7
|
if self.groupinitialized then
|
||||||
|
self:T(self.lid.."WARNING: Group was already initialized! Will NOT do it again!")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
-- Group ammo.
|
-- Get template of group.
|
||||||
self.ammo=self:GetAmmoTot()
|
local template=Template or self:_GetTemplate()
|
||||||
|
|
||||||
-- Radio parameters from template. Default is set on spawn if not modified by the user.
|
-- Ships are always AI.
|
||||||
self.radio.On=true -- Radio is always on for ships.
|
self.isAI=true
|
||||||
self.radio.Freq=tonumber(template.units[1].frequency)/1000000
|
|
||||||
self.radio.Modu=tonumber(template.units[1].modulation)
|
-- Is (template) group late activated.
|
||||||
|
self.isLateActivated=template.lateActivation
|
||||||
|
|
||||||
|
-- Naval groups cannot be uncontrolled.
|
||||||
|
self.isUncontrolled=false
|
||||||
|
|
||||||
|
-- Max speed in km/h.
|
||||||
|
self.speedMax=self.group:GetSpeedMax()
|
||||||
|
|
||||||
|
-- Is group mobile?
|
||||||
|
if self.speedMax and self.speedMax>3.6 then
|
||||||
|
self.isMobile=true
|
||||||
|
else
|
||||||
|
self.isMobile=false
|
||||||
|
self.speedMax = 0
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Cruise speed: 70% of max speed.
|
||||||
|
self.speedCruise=self.speedMax*0.7
|
||||||
|
|
||||||
|
-- Group ammo.
|
||||||
|
self.ammo=self:GetAmmoTot()
|
||||||
|
|
||||||
|
-- Radio parameters from template. Default is set on spawn if not modified by the user.
|
||||||
|
self.radio.On=true -- Radio is always on for ships.
|
||||||
|
self.radio.Freq=tonumber(template.units[1].frequency)/1000000
|
||||||
|
self.radio.Modu=tonumber(template.units[1].modulation)
|
||||||
|
|
||||||
|
-- Set default formation. No really applicable for ships.
|
||||||
|
self.optionDefault.Formation="Off Road"
|
||||||
|
self.option.Formation=self.optionDefault.Formation
|
||||||
|
|
||||||
-- Set default formation. No really applicable for ships.
|
-- Default TACAN off (we check if something is set already to keep those values in case of respawn)
|
||||||
self.optionDefault.Formation="Off Road"
|
if not self.tacanDefault then
|
||||||
self.option.Formation=self.optionDefault.Formation
|
self:SetDefaultTACAN(nil, nil, nil, nil, true)
|
||||||
|
end
|
||||||
-- Default TACAN off.
|
if not self.tacan then
|
||||||
self:SetDefaultTACAN(nil, nil, nil, nil, true)
|
self.tacan=UTILS.DeepCopy(self.tacanDefault)
|
||||||
self.tacan=UTILS.DeepCopy(self.tacanDefault)
|
end
|
||||||
|
|
||||||
|
-- Default ICLS off.
|
||||||
|
if not self.iclsDefault then
|
||||||
|
self:SetDefaultICLS(nil, nil, nil, true)
|
||||||
|
end
|
||||||
|
if not self.icls then
|
||||||
|
self.icls=UTILS.DeepCopy(self.iclsDefault)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Get all units of the group.
|
||||||
|
local units=self.group:GetUnits()
|
||||||
|
|
||||||
-- Default ICLS off.
|
-- DCS group.
|
||||||
self:SetDefaultICLS(nil, nil, nil, true)
|
local dcsgroup=Group.getByName(self.groupname)
|
||||||
self.icls=UTILS.DeepCopy(self.iclsDefault)
|
local size0=dcsgroup:getInitialSize()
|
||||||
|
|
||||||
-- Get all units of the group.
|
-- Quick check.
|
||||||
local units=self.group:GetUnits()
|
if #units~=size0 then
|
||||||
|
self:E(self.lid..string.format("ERROR: Got #units=%d but group consists of %d units!", #units, size0))
|
||||||
-- DCS group.
|
end
|
||||||
local dcsgroup=Group.getByName(self.groupname)
|
|
||||||
local size0=dcsgroup:getInitialSize()
|
-- Add elemets.
|
||||||
|
for _,unit in pairs(units) do
|
||||||
-- Quick check.
|
self:_AddElementByName(unit:GetName())
|
||||||
if #units~=size0 then
|
end
|
||||||
self:E(self.lid..string.format("ERROR: Got #units=%d but group consists of %d units!", #units, size0))
|
|
||||||
|
-- Init done.
|
||||||
|
self.groupinitialized=true
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Add elemets.
|
|
||||||
for _,unit in pairs(units) do
|
|
||||||
self:_AddElementByName(unit:GetName())
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Init done.
|
|
||||||
self.groupinitialized=true
|
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -2068,8 +2178,43 @@ end
|
|||||||
--- Get heading of group into the wind.
|
--- Get heading of group into the wind.
|
||||||
-- @param #NAVYGROUP self
|
-- @param #NAVYGROUP self
|
||||||
-- @param #number Offset Offset angle in degrees, e.g. to account for an angled runway.
|
-- @param #number Offset Offset angle in degrees, e.g. to account for an angled runway.
|
||||||
|
-- @param #number vdeck Desired wind speed on deck in Knots.
|
||||||
-- @return #number Carrier heading in degrees.
|
-- @return #number Carrier heading in degrees.
|
||||||
function NAVYGROUP:GetHeadingIntoWind_old(Offset)
|
-- @return #number Carrier speed in knots.
|
||||||
|
function NAVYGROUP:GetHeadingIntoWind_old(Offset, vdeck)
|
||||||
|
|
||||||
|
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
|
||||||
|
-- +4 degrees at 12m/s = 31kts
|
||||||
|
-- +4 degrees at 11m/s = 29kts
|
||||||
|
-- +4 degrees at 10m/s = 27kts
|
||||||
|
-- +4 degrees at 9m/s = 27kts
|
||||||
|
-- +4 degrees at 8m/s = 27kts
|
||||||
|
-- +8 degrees at 7m/s = 27kts
|
||||||
|
-- +8 degrees at 6m/s = 27kts
|
||||||
|
-- +8 degrees at 5m/s = 26kts
|
||||||
|
-- +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
|
||||||
|
degreesAdjustment = 20
|
||||||
|
elseif windSpeed >= 5 and windSpeed < 8 then
|
||||||
|
degreesAdjustment = 8
|
||||||
|
elseif windSpeed >= 8 and windSpeed < 13 then
|
||||||
|
degreesAdjustment = 4
|
||||||
|
elseif windSpeed >= 13 then
|
||||||
|
degreesAdjustment = 0
|
||||||
|
end
|
||||||
|
|
||||||
|
return degreesAdjustment
|
||||||
|
end
|
||||||
|
|
||||||
Offset=Offset or 0
|
Offset=Offset or 0
|
||||||
|
|
||||||
@@ -2077,7 +2222,7 @@ function NAVYGROUP:GetHeadingIntoWind_old(Offset)
|
|||||||
local windfrom, vwind=self:GetWind()
|
local windfrom, vwind=self:GetWind()
|
||||||
|
|
||||||
-- Actually, we want the runway in the wind.
|
-- Actually, we want the runway in the wind.
|
||||||
local intowind=windfrom-Offset
|
local intowind = windfrom - Offset + adjustDegreesForWindSpeed(vwind)
|
||||||
|
|
||||||
-- If no wind, take current heading.
|
-- If no wind, take current heading.
|
||||||
if vwind<0.1 then
|
if vwind<0.1 then
|
||||||
@@ -2088,8 +2233,11 @@ function NAVYGROUP:GetHeadingIntoWind_old(Offset)
|
|||||||
if intowind<0 then
|
if intowind<0 then
|
||||||
intowind=intowind+360
|
intowind=intowind+360
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Speed of carrier in m/s but at least 4 knots.
|
||||||
|
local vtot = math.max(vdeck-UTILS.MpsToKnots(vwind), 4)
|
||||||
|
|
||||||
return intowind
|
return intowind, vtot
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
@@ -2099,7 +2247,8 @@ end
|
|||||||
-- @param #number Offset Offset angle in degrees, e.g. to account for an angled runway.
|
-- @param #number Offset Offset angle in degrees, e.g. to account for an angled runway.
|
||||||
-- @param #number vdeck Desired wind speed on deck in Knots.
|
-- @param #number vdeck Desired wind speed on deck in Knots.
|
||||||
-- @return #number Carrier heading in degrees.
|
-- @return #number Carrier heading in degrees.
|
||||||
function NAVYGROUP:GetHeadingIntoWind(Offset, vdeck)
|
-- @return #number Carrier speed in knots.
|
||||||
|
function NAVYGROUP:GetHeadingIntoWind_new(Offset, vdeck)
|
||||||
|
|
||||||
-- Default offset angle.
|
-- Default offset angle.
|
||||||
Offset=Offset or 0
|
Offset=Offset or 0
|
||||||
@@ -2180,6 +2329,25 @@ function NAVYGROUP:GetHeadingIntoWind(Offset, vdeck)
|
|||||||
return intowind, v
|
return intowind, v
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Get heading of group into the wind. This minimizes the cross wind for an angled runway.
|
||||||
|
-- Implementation based on [Mags & Bami](https://magwo.github.io/carrier-cruise/) work.
|
||||||
|
-- @param #NAVYGROUP self
|
||||||
|
-- @param #number Offset Offset angle in degrees, e.g. to account for an angled runway.
|
||||||
|
-- @param #number vdeck Desired wind speed on deck in Knots.
|
||||||
|
-- @return #number Carrier heading in degrees.
|
||||||
|
-- @return #number Carrier speed in knots.
|
||||||
|
function NAVYGROUP:GetHeadingIntoWind(Offset, vdeck)
|
||||||
|
|
||||||
|
if self.intowindold then
|
||||||
|
--env.info("FF use OLD into wind")
|
||||||
|
return self:GetHeadingIntoWind_old(Offset, vdeck)
|
||||||
|
else
|
||||||
|
--env.info("FF use NEW into wind")
|
||||||
|
return self:GetHeadingIntoWind_new(Offset, vdeck)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
--- Find free path to next waypoint.
|
--- Find free path to next waypoint.
|
||||||
-- @param #NAVYGROUP self
|
-- @param #NAVYGROUP self
|
||||||
|
|||||||
@@ -513,7 +513,7 @@ OPSGROUP.CargoStatus={
|
|||||||
|
|
||||||
--- OpsGroup version.
|
--- OpsGroup version.
|
||||||
-- @field #string version
|
-- @field #string version
|
||||||
OPSGROUP.version="1.0.1"
|
OPSGROUP.version="1.0.4"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
-- TODO list
|
-- TODO list
|
||||||
@@ -1047,7 +1047,7 @@ function OPSGROUP:SetReturnToLegion(Switch)
|
|||||||
else
|
else
|
||||||
self.legionReturn=true
|
self.legionReturn=true
|
||||||
end
|
end
|
||||||
self:T(self.lid..string.format("Setting ReturnToLetion=%s", tostring(self.legionReturn)))
|
self:T(self.lid..string.format("Setting ReturnToLegion=%s", tostring(self.legionReturn)))
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1339,8 +1339,9 @@ end
|
|||||||
-- @param Core.Point#COORDINATE TargetCoord Coordinate of the target.
|
-- @param Core.Point#COORDINATE TargetCoord Coordinate of the target.
|
||||||
-- @param #number WeaponBitType Weapon type.
|
-- @param #number WeaponBitType Weapon type.
|
||||||
-- @param Core.Point#COORDINATE RefCoord Reference coordinate.
|
-- @param Core.Point#COORDINATE RefCoord Reference coordinate.
|
||||||
|
-- @param #table SurfaceTypes Valid surfaces types of the coordinate. Default any (nil).
|
||||||
-- @return Core.Point#COORDINATE Coordinate in weapon range
|
-- @return Core.Point#COORDINATE Coordinate in weapon range
|
||||||
function OPSGROUP:GetCoordinateInRange(TargetCoord, WeaponBitType, RefCoord)
|
function OPSGROUP:GetCoordinateInRange(TargetCoord, WeaponBitType, RefCoord, SurfaceTypes)
|
||||||
|
|
||||||
local coordInRange=nil --Core.Point#COORDINATE
|
local coordInRange=nil --Core.Point#COORDINATE
|
||||||
|
|
||||||
@@ -1349,35 +1350,58 @@ function OPSGROUP:GetCoordinateInRange(TargetCoord, WeaponBitType, RefCoord)
|
|||||||
-- Get weapon range.
|
-- Get weapon range.
|
||||||
local weapondata=self:GetWeaponData(WeaponBitType)
|
local weapondata=self:GetWeaponData(WeaponBitType)
|
||||||
|
|
||||||
|
-- Heading intervals to search for a possible new coordinate in range.
|
||||||
|
local dh={0, -5, 5, -10, 10, -15, 15, -20, 20, -25, 25, -30, 30, -35, 35, -40, 40, -45, 45, -50, 50, -55, 55, -60, 60, -65, 65, -70, 70, -75, 75, -80, 80}
|
||||||
|
|
||||||
|
-- Function that checks if the given surface type is valid
|
||||||
|
local function _checkSurface(point)
|
||||||
|
if SurfaceTypes then
|
||||||
|
local stype=point:GetSurfaceType()
|
||||||
|
for _,sf in pairs(SurfaceTypes) do
|
||||||
|
if sf==stype then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
else
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
if weapondata then
|
if weapondata then
|
||||||
|
|
||||||
-- Heading to target.
|
-- Heading to target.
|
||||||
local heading=RefCoord:HeadingTo(TargetCoord)
|
local heading=TargetCoord:HeadingTo(RefCoord)
|
||||||
|
|
||||||
-- Distance to target.
|
-- Distance to target.
|
||||||
local dist=RefCoord:Get2DDistance(TargetCoord)
|
local dist=RefCoord:Get2DDistance(TargetCoord)
|
||||||
|
|
||||||
|
local range=nil
|
||||||
|
if dist>weapondata.RangeMax then
|
||||||
|
range=weapondata.RangeMax
|
||||||
|
self:T(self.lid..string.format("Out of max range = %.1f km by %.1f km for weapon %s", weapondata.RangeMax/1000, (weapondata.RangeMax-dist)/1000, tostring(WeaponBitType)))
|
||||||
|
elseif dist<weapondata.RangeMin then
|
||||||
|
range=weapondata.RangeMin
|
||||||
|
self:T(self.lid..string.format("Out of min range = %.1f km by %.1f km for weapon %s", weapondata.RangeMin/1000, (weapondata.RangeMin-dist)/1000, tostring(WeaponBitType)))
|
||||||
|
end
|
||||||
|
|
||||||
-- Check if we are within range.
|
-- Check if we are within range.
|
||||||
if dist>weapondata.RangeMax then
|
if range then
|
||||||
|
|
||||||
local d=(dist-weapondata.RangeMax)*1.05
|
for _,delta in pairs(dh) do
|
||||||
|
|
||||||
-- New waypoint coord.
|
local h=heading+delta
|
||||||
coordInRange=RefCoord:Translate(d, heading)
|
|
||||||
|
|
||||||
-- Debug info.
|
|
||||||
self:T(self.lid..string.format("Out of max range = %.1f km for weapon %s", weapondata.RangeMax/1000, tostring(WeaponBitType)))
|
|
||||||
elseif dist<weapondata.RangeMin then
|
|
||||||
|
|
||||||
local d=(dist-weapondata.RangeMin)*1.05
|
|
||||||
|
|
||||||
-- New waypoint coord.
|
|
||||||
coordInRange=RefCoord:Translate(d, heading)
|
|
||||||
|
|
||||||
-- Debug info.
|
|
||||||
self:T(self.lid..string.format("Out of min range = %.1f km for weapon %s", weapondata.RangeMax/1000, tostring(WeaponBitType)))
|
|
||||||
else
|
|
||||||
|
|
||||||
|
-- New waypoint coord.
|
||||||
|
coordInRange=TargetCoord:Translate(range, h)
|
||||||
|
|
||||||
|
if _checkSurface(coordInRange) then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
else
|
||||||
-- Debug info.
|
-- Debug info.
|
||||||
self:T(self.lid..string.format("Already in range for weapon %s", tostring(WeaponBitType)))
|
self:T(self.lid..string.format("Already in range for weapon %s", tostring(WeaponBitType)))
|
||||||
end
|
end
|
||||||
@@ -1456,11 +1480,14 @@ end
|
|||||||
-- @param #number RangeMin Minimum range in nautical miles. Default 0 NM.
|
-- @param #number RangeMin Minimum range in nautical miles. Default 0 NM.
|
||||||
-- @param #number RangeMax Maximum range in nautical miles. Default 10 NM.
|
-- @param #number RangeMax Maximum range in nautical miles. Default 10 NM.
|
||||||
-- @param #number BitType Bit mask of weapon type for which the given min/max ranges apply. Default is `ENUMS.WeaponFlag.Auto`, i.e. for all weapon types.
|
-- @param #number BitType Bit mask of weapon type for which the given min/max ranges apply. Default is `ENUMS.WeaponFlag.Auto`, i.e. for all weapon types.
|
||||||
|
-- @param #function ConversionToMeters Function that converts input units of ranges to meters. Defaul `UTILS.NMToMeters`.
|
||||||
-- @return #OPSGROUP self
|
-- @return #OPSGROUP self
|
||||||
function OPSGROUP:AddWeaponRange(RangeMin, RangeMax, BitType)
|
function OPSGROUP:AddWeaponRange(RangeMin, RangeMax, BitType, ConversionToMeters)
|
||||||
|
|
||||||
RangeMin=UTILS.NMToMeters(RangeMin or 0)
|
ConversionToMeters=ConversionToMeters or UTILS.NMToMeters
|
||||||
RangeMax=UTILS.NMToMeters(RangeMax or 10)
|
|
||||||
|
RangeMin=ConversionToMeters(RangeMin or 0)
|
||||||
|
RangeMax=ConversionToMeters(RangeMax or 10)
|
||||||
|
|
||||||
local weapon={} --#OPSGROUP.WeaponData
|
local weapon={} --#OPSGROUP.WeaponData
|
||||||
|
|
||||||
@@ -4175,7 +4202,7 @@ function OPSGROUP:onbeforeTaskExecute(From, Event, To, Task)
|
|||||||
if self:IsWaiting() then
|
if self:IsWaiting() then
|
||||||
-- Group is already waiting
|
-- Group is already waiting
|
||||||
else
|
else
|
||||||
-- Wait indefinately.
|
-- Wait indefinitely.
|
||||||
local alt=Mission.missionAltitude and UTILS.MetersToFeet(Mission.missionAltitude) or nil
|
local alt=Mission.missionAltitude and UTILS.MetersToFeet(Mission.missionAltitude) or nil
|
||||||
self:Wait(nil, alt)
|
self:Wait(nil, alt)
|
||||||
end
|
end
|
||||||
@@ -4486,7 +4513,7 @@ function OPSGROUP:_UpdateTask(Task, Mission)
|
|||||||
-- Set speed. Default max.
|
-- Set speed. Default max.
|
||||||
local speed=self.speedMax and UTILS.KmphToKnots(self.speedMax) or nil
|
local speed=self.speedMax and UTILS.KmphToKnots(self.speedMax) or nil
|
||||||
if Task.dcstask.params.speed then
|
if Task.dcstask.params.speed then
|
||||||
speed=Task.dcstask.params.speed
|
speed=UTILS.MpsToKnots(Task.dcstask.params.speed)
|
||||||
end
|
end
|
||||||
|
|
||||||
if target then
|
if target then
|
||||||
@@ -6079,17 +6106,16 @@ function OPSGROUP:RouteToMission(mission, delay)
|
|||||||
-- Target Coord.
|
-- Target Coord.
|
||||||
local targetcoord=mission:GetTargetCoordinate()
|
local targetcoord=mission:GetTargetCoordinate()
|
||||||
|
|
||||||
|
|
||||||
-- In range already?
|
-- In range already?
|
||||||
local inRange=self:InWeaponRange(targetcoord, mission.engageWeaponType)
|
local inRange=self:InWeaponRange(targetcoord, mission.engageWeaponType, waypointcoord)
|
||||||
|
|
||||||
if inRange then
|
if inRange then
|
||||||
|
|
||||||
waypointcoord=self:GetCoordinate(true)
|
--waypointcoord=self:GetCoordinate(true)
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|
||||||
local coordInRange=self:GetCoordinateInRange(targetcoord, mission.engageWeaponType, waypointcoord)
|
local coordInRange=self:GetCoordinateInRange(targetcoord, mission.engageWeaponType, waypointcoord, surfacetypes)
|
||||||
|
|
||||||
if coordInRange then
|
if coordInRange then
|
||||||
|
|
||||||
@@ -6124,7 +6150,32 @@ function OPSGROUP:RouteToMission(mission, delay)
|
|||||||
-- Add mission execution (ingress) waypoint.
|
-- Add mission execution (ingress) waypoint.
|
||||||
local waypoint=nil --#OPSGROUP.Waypoint
|
local waypoint=nil --#OPSGROUP.Waypoint
|
||||||
if self:IsFlightgroup() then
|
if self:IsFlightgroup() then
|
||||||
|
|
||||||
|
|
||||||
|
local ingresscoord = mission:GetMissionIngressCoord()
|
||||||
|
local holdingcoord = mission:GetMissionHoldingCoord()
|
||||||
|
|
||||||
|
if holdingcoord then
|
||||||
|
waypoint=FLIGHTGROUP.AddWaypoint(self, holdingcoord, mission.missionHoldingCoordSpeed or SpeedToMission, uid, UTILS.MetersToFeet(mission.missionHoldingCoordAlt or self.altitudeCruise), false)
|
||||||
|
uid=waypoint.uid
|
||||||
|
-- Orbit until flaghold=1 (true) but max 5 min
|
||||||
|
self.flaghold:Set(0)
|
||||||
|
local TaskOrbit = self.group:TaskOrbit(holdingcoord, mission.missionHoldingCoordAlt, UTILS.KnotsToMps(mission.missionHoldingCoordSpeed or SpeedToMission))
|
||||||
|
local TaskStop = self.group:TaskCondition(nil, self.flaghold.UserFlagName, 1, nil, mission.missionHoldingDuration or 900)
|
||||||
|
local TaskCntr = self.group:TaskControlled(TaskOrbit, TaskStop)
|
||||||
|
local TaskOver = self.group:TaskFunction("FLIGHTGROUP._FinishedWaiting", self)
|
||||||
|
local DCSTasks=self.group:TaskCombo({TaskCntr, TaskOver})
|
||||||
|
-- Add waypoint task. UpdateRoute is called inside.
|
||||||
|
local waypointtask=self:AddTaskWaypoint(DCSTasks, waypoint, "Holding")
|
||||||
|
waypointtask.ismission=false
|
||||||
|
self.isHoldingAtHoldingPoint = true
|
||||||
|
end
|
||||||
|
|
||||||
|
if ingresscoord then
|
||||||
|
waypoint=FLIGHTGROUP.AddWaypoint(self, ingresscoord, mission.missionIngressCoordSpeed or SpeedToMission, uid, UTILS.MetersToFeet(mission.missionIngressCoordAlt or self.altitudeCruise), false)
|
||||||
|
uid=waypoint.uid
|
||||||
|
end
|
||||||
|
|
||||||
waypoint=FLIGHTGROUP.AddWaypoint(self, waypointcoord, SpeedToMission, uid, UTILS.MetersToFeet(mission.missionAltitude or self.altitudeCruise), false)
|
waypoint=FLIGHTGROUP.AddWaypoint(self, waypointcoord, SpeedToMission, uid, UTILS.MetersToFeet(mission.missionAltitude or self.altitudeCruise), false)
|
||||||
|
|
||||||
elseif self:IsArmygroup() then
|
elseif self:IsArmygroup() then
|
||||||
@@ -6163,7 +6214,7 @@ function OPSGROUP:RouteToMission(mission, delay)
|
|||||||
if egresscoord then
|
if egresscoord then
|
||||||
local Ewaypoint=nil --#OPSGROUP.Waypoint
|
local Ewaypoint=nil --#OPSGROUP.Waypoint
|
||||||
if self:IsFlightgroup() then
|
if self:IsFlightgroup() then
|
||||||
Ewaypoint=FLIGHTGROUP.AddWaypoint(self, egresscoord, SpeedToMission, waypoint.uid, UTILS.MetersToFeet(mission.missionAltitude or self.altitudeCruise), false)
|
Ewaypoint=FLIGHTGROUP.AddWaypoint(self, egresscoord, mission.missionEgressCoordSpeed or SpeedToMission, waypoint.uid, UTILS.MetersToFeet(mission.missionEgressCoordAlt or self.altitudeCruise), false)
|
||||||
elseif self:IsArmygroup() then
|
elseif self:IsArmygroup() then
|
||||||
Ewaypoint=ARMYGROUP.AddWaypoint(self, egresscoord, SpeedToMission, waypoint.uid, mission.optionFormation, false)
|
Ewaypoint=ARMYGROUP.AddWaypoint(self, egresscoord, SpeedToMission, waypoint.uid, mission.optionFormation, false)
|
||||||
elseif self:IsNavygroup() then
|
elseif self:IsNavygroup() then
|
||||||
@@ -7681,6 +7732,7 @@ function OPSGROUP:Teleport(Coordinate, Delay, NoPauseMission)
|
|||||||
unit.heading=math.rad(heading)
|
unit.heading=math.rad(heading)
|
||||||
unit.psi=-unit.heading
|
unit.psi=-unit.heading
|
||||||
else
|
else
|
||||||
|
-- Remove unit from spawn template because it is already dead
|
||||||
table.remove(units, i)
|
table.remove(units, i)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -7768,25 +7820,41 @@ function OPSGROUP:_Respawn(Delay, Template, Reset)
|
|||||||
-- Despawn old group. Dont trigger any remove unit event since this is a respawn.
|
-- Despawn old group. Dont trigger any remove unit event since this is a respawn.
|
||||||
self:Despawn(0, true)
|
self:Despawn(0, true)
|
||||||
|
|
||||||
else
|
|
||||||
|
|
||||||
---
|
|
||||||
-- Group is NOT ALIVE
|
|
||||||
---
|
|
||||||
|
|
||||||
-- Ensure elements in utero.
|
|
||||||
for _,_element in pairs(self.elements) do
|
|
||||||
local element=_element --#OPSGROUP.Element
|
|
||||||
self:ElementInUtero(element)
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Ensure elements in utero.
|
||||||
|
for _,_element in pairs(self.elements) do
|
||||||
|
local element=_element --#OPSGROUP.Element
|
||||||
|
if element and element.status~=OPSGROUP.ElementStatus.DEAD then
|
||||||
|
self:ElementInUtero(element)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Spawn with a little delay (especially Navy groups caused problems if they were instantly respawned)
|
||||||
|
self:_Spawn(0.01, Template)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Spawn group from a given template.
|
||||||
|
-- @param #OPSGROUP self
|
||||||
|
-- @param #number Delay Delay in seconds before respawn happens. Default 0.
|
||||||
|
-- @param DCS#Template Template (optional) The template of the Group retrieved with GROUP:GetTemplate(). If the template is not provided, the template will be retrieved of the group itself.
|
||||||
|
-- @return #OPSGROUP self
|
||||||
|
function OPSGROUP:_Spawn(Delay, Template)
|
||||||
|
if Delay and Delay>0 then
|
||||||
|
self:ScheduleOnce(Delay, OPSGROUP._Spawn, self, 0, Template)
|
||||||
|
else
|
||||||
-- Debug output.
|
-- Debug output.
|
||||||
self:T({Template=Template})
|
self:T2({Template=Template})
|
||||||
|
|
||||||
-- Spawn new group.
|
-- Spawn new group.
|
||||||
self.group=_DATABASE:Spawn(Template)
|
self.group=_DATABASE:Spawn(Template)
|
||||||
|
--local countryID=self.group:GetCountry()
|
||||||
|
--local categoryID=self.group:GetCategory()
|
||||||
|
--local dcsgroup=coalition.addGroup(countryID, categoryID, Template)
|
||||||
|
|
||||||
-- Set DCS group and controller.
|
-- Set DCS group and controller.
|
||||||
self.dcsgroup=self:GetDCSGroup()
|
self.dcsgroup=self:GetDCSGroup()
|
||||||
@@ -7800,7 +7868,6 @@ function OPSGROUP:_Respawn(Delay, Template, Reset)
|
|||||||
self.isDead=false
|
self.isDead=false
|
||||||
self.isDestroyed=false
|
self.isDestroyed=false
|
||||||
|
|
||||||
|
|
||||||
self.groupinitialized=false
|
self.groupinitialized=false
|
||||||
self.wpcounter=1
|
self.wpcounter=1
|
||||||
self.currentwp=1
|
self.currentwp=1
|
||||||
@@ -7808,15 +7875,12 @@ function OPSGROUP:_Respawn(Delay, Template, Reset)
|
|||||||
-- Init waypoints.
|
-- Init waypoints.
|
||||||
self:_InitWaypoints()
|
self:_InitWaypoints()
|
||||||
|
|
||||||
-- Init Group.
|
-- Init Group. This call is delayed because NAVY groups did not like to be initialized just yet (group did not contain any units).
|
||||||
self:_InitGroup(Template)
|
self:_InitGroup(Template, 0.001)
|
||||||
|
|
||||||
-- Reset events.
|
-- Reset events.
|
||||||
--self:ResetEvents()
|
--self:ResetEvents()
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- On after "InUtero" event.
|
--- On after "InUtero" event.
|
||||||
@@ -7836,24 +7900,6 @@ end
|
|||||||
-- @param #string To To state.
|
-- @param #string To To state.
|
||||||
function OPSGROUP:onafterDamaged(From, Event, To)
|
function OPSGROUP:onafterDamaged(From, Event, To)
|
||||||
self:T(self.lid..string.format("Group damaged at t=%.3f", timer.getTime()))
|
self:T(self.lid..string.format("Group damaged at t=%.3f", timer.getTime()))
|
||||||
|
|
||||||
--[[
|
|
||||||
local lifemin=nil
|
|
||||||
for _,_element in pairs(self.elements) do
|
|
||||||
local element=_element --#OPSGROUP.Element
|
|
||||||
if element.status~=OPSGROUP.ElementStatus.DEAD and element.status~=OPSGROUP.ElementStatus.INUTERO then
|
|
||||||
local life, life0=self:GetLifePoints(element)
|
|
||||||
if lifemin==nil or life<lifemin then
|
|
||||||
lifemin=life
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if lifemin and lifemin/self.life<0.5 then
|
|
||||||
self:RTB()
|
|
||||||
end
|
|
||||||
]]
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- On after "Destroyed" event.
|
--- On after "Destroyed" event.
|
||||||
@@ -9005,7 +9051,7 @@ function OPSGROUP:AddWeightCargo(UnitName, Weight)
|
|||||||
self:T(self.lid..string.format("%s: Adding %.1f kg cargo weight. New cargo weight=%.1f kg", UnitName, Weight, element.weightCargo))
|
self:T(self.lid..string.format("%s: Adding %.1f kg cargo weight. New cargo weight=%.1f kg", UnitName, Weight, element.weightCargo))
|
||||||
|
|
||||||
-- For airborne units, we set the weight in game.
|
-- For airborne units, we set the weight in game.
|
||||||
if self.isFlightgroup then
|
if self.isFlightgroup and element.unit and element.unit:IsAlive() then -- #2272 trying to deduct cargo weight from possibly dead units
|
||||||
trigger.action.setUnitInternalCargo(element.name, element.weightCargo) --https://wiki.hoggitworld.com/view/DCS_func_setUnitInternalCargo
|
trigger.action.setUnitInternalCargo(element.name, element.weightCargo) --https://wiki.hoggitworld.com/view/DCS_func_setUnitInternalCargo
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -11450,10 +11496,10 @@ function OPSGROUP:_InitWaypoints(WpIndexMin, WpIndexMax)
|
|||||||
if self:IsFlightgroup() then
|
if self:IsFlightgroup() then
|
||||||
|
|
||||||
-- Get home and destination airbases from waypoints.
|
-- Get home and destination airbases from waypoints.
|
||||||
self.homebase=self.homebase or self:GetHomebaseFromWaypoints()
|
self.homebase=self.homebase or self:GetHomebaseFromWaypoints() -- GetHomebaseFromWaypoints() returns carriers or destroyers if no airbase is found.
|
||||||
local destbase=self:GetDestinationFromWaypoints()
|
local destbase=self:GetDestinationFromWaypoints()
|
||||||
self.destbase=self.destbase or destbase
|
self.destbase=self.destbase or destbase
|
||||||
self.currbase=self:GetHomebaseFromWaypoints()
|
self.currbase=self:GetHomebaseFromWaypoints() -- Skipped To fix RTB issue
|
||||||
|
|
||||||
--env.info("FF home base "..(self.homebase and self.homebase:GetName() or "unknown"))
|
--env.info("FF home base "..(self.homebase and self.homebase:GetName() or "unknown"))
|
||||||
--env.info("FF dest base "..(self.destbase and self.destbase:GetName() or "unknown"))
|
--env.info("FF dest base "..(self.destbase and self.destbase:GetName() or "unknown"))
|
||||||
@@ -11464,7 +11510,7 @@ function OPSGROUP:_InitWaypoints(WpIndexMin, WpIndexMax)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Set destination to homebase.
|
-- Set destination to homebase.
|
||||||
if self.destbase==nil then
|
if self.destbase==nil then -- Skipped To fix RTB issue
|
||||||
self.destbase=self.homebase
|
self.destbase=self.homebase
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -490,6 +490,19 @@ function OPSZONE:SetDrawZone(Switch)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Set if zone is drawn on the F10 map for the owner coalition only.
|
||||||
|
-- @param #OPSZONE self
|
||||||
|
-- @param #boolean Switch If `false` or `nil`, draw zone for all coalitions. If `true`, zone is drawn for the owning coalition only if drawZone is true.
|
||||||
|
-- @return #OPSZONE self
|
||||||
|
function OPSZONE:SetDrawZoneForCoalition(Switch)
|
||||||
|
if Switch==true then
|
||||||
|
self.drawZoneForCoalition=true
|
||||||
|
else
|
||||||
|
self.drawZoneForCoalition=false
|
||||||
|
end
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- Set if a marker on the F10 map shows the current zone status.
|
--- Set if a marker on the F10 map shows the current zone status.
|
||||||
-- @param #OPSZONE self
|
-- @param #OPSZONE self
|
||||||
-- @param #boolean Switch If `true`, zone is marked. If `false` or `nil`, zone is not marked.
|
-- @param #boolean Switch If `true`, zone is marked. If `false` or `nil`, zone is not marked.
|
||||||
@@ -710,6 +723,7 @@ end
|
|||||||
-- @param #string From From state.
|
-- @param #string From From state.
|
||||||
-- @param #string Event Event.
|
-- @param #string Event Event.
|
||||||
-- @param #string To To state.
|
-- @param #string To To state.
|
||||||
|
-- @return #OPSZONE self
|
||||||
function OPSZONE:onafterStart(From, Event, To)
|
function OPSZONE:onafterStart(From, Event, To)
|
||||||
|
|
||||||
-- Info.
|
-- Info.
|
||||||
@@ -726,6 +740,7 @@ function OPSZONE:onafterStart(From, Event, To)
|
|||||||
self:HandleEvent(EVENTS.BaseCaptured)
|
self:HandleEvent(EVENTS.BaseCaptured)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Stop OPSZONE FSM.
|
--- Stop OPSZONE FSM.
|
||||||
@@ -837,8 +852,12 @@ function OPSZONE:onafterCaptured(From, Event, To, NewOwnerCoalition)
|
|||||||
self.zone:UndrawZone()
|
self.zone:UndrawZone()
|
||||||
|
|
||||||
local color=self:_GetZoneColor()
|
local color=self:_GetZoneColor()
|
||||||
|
|
||||||
self.zone:DrawZone(nil, color, 1.0, color, 0.5)
|
local coalition = nil
|
||||||
|
if self.drawZoneForCoalition then
|
||||||
|
coalition = self.ownerCurrent
|
||||||
|
end
|
||||||
|
self.zone:DrawZone(coalition, color, 1.0, color, 0.5)
|
||||||
end
|
end
|
||||||
|
|
||||||
for _,_chief in pairs(self.chiefs) do
|
for _,_chief in pairs(self.chiefs) do
|
||||||
@@ -913,8 +932,12 @@ function OPSZONE:onenterGuarded(From, Event, To)
|
|||||||
self.zone:UndrawZone()
|
self.zone:UndrawZone()
|
||||||
|
|
||||||
local color=self:_GetZoneColor()
|
local color=self:_GetZoneColor()
|
||||||
|
|
||||||
self.zone:DrawZone(nil, color, 1.0, color, 0.5)
|
local coalition = nil
|
||||||
|
if self.drawZoneForCoalition then
|
||||||
|
coalition = self.ownerCurrent
|
||||||
|
end
|
||||||
|
self.zone:DrawZone(coalition, color, 1.0, color, 0.5)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
@@ -954,9 +977,13 @@ function OPSZONE:onenterAttacked(From, Event, To, AttackerCoalition)
|
|||||||
|
|
||||||
-- Color.
|
-- Color.
|
||||||
local color={1, 204/255, 204/255}
|
local color={1, 204/255, 204/255}
|
||||||
|
|
||||||
|
local coalition = nil
|
||||||
|
if self.drawZoneForCoalition then
|
||||||
|
coalition = self.ownerCurrent
|
||||||
|
end
|
||||||
-- Draw zone.
|
-- Draw zone.
|
||||||
self.zone:DrawZone(nil, color, 1.0, color, 0.5)
|
self.zone:DrawZone(coalition, color, 1.0, color, 0.5)
|
||||||
end
|
end
|
||||||
|
|
||||||
self:_CleanMissionTable()
|
self:_CleanMissionTable()
|
||||||
@@ -987,8 +1014,12 @@ function OPSZONE:onenterEmpty(From, Event, To)
|
|||||||
self.zone:UndrawZone()
|
self.zone:UndrawZone()
|
||||||
|
|
||||||
local color=self:_GetZoneColor()
|
local color=self:_GetZoneColor()
|
||||||
|
|
||||||
self.zone:DrawZone(nil, color, 1.0, color, 0.2)
|
local coalition = nil
|
||||||
|
if self.drawZoneForCoalition then
|
||||||
|
coalition = self.ownerCurrent
|
||||||
|
end
|
||||||
|
self.zone:DrawZone(coalition, color, 1.0, color, 0.2)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
@@ -1285,7 +1316,7 @@ function OPSZONE:EvaluateZone()
|
|||||||
|
|
||||||
if Nblu>0 then
|
if Nblu>0 then
|
||||||
|
|
||||||
if not self:IsAttacked() and self.Tnut>=self.threatlevelCapture then
|
if not self:IsAttacked() and self.Tblu>=self.threatlevelCapture then
|
||||||
self:Attacked(coalition.side.BLUE)
|
self:Attacked(coalition.side.BLUE)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -1337,7 +1368,7 @@ function OPSZONE:EvaluateZone()
|
|||||||
|
|
||||||
if Nred>0 then
|
if Nred>0 then
|
||||||
|
|
||||||
if not self:IsAttacked() and self.Tnut>=self.threatlevelCapture then
|
if not self:IsAttacked() and self.Tred>=self.threatlevelCapture then
|
||||||
-- Red is attacking blue zone.
|
-- Red is attacking blue zone.
|
||||||
self:Attacked(coalition.side.RED)
|
self:Attacked(coalition.side.RED)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -80,6 +80,7 @@
|
|||||||
-- @field #boolean smokeownposition
|
-- @field #boolean smokeownposition
|
||||||
-- @field #table SmokeOwn
|
-- @field #table SmokeOwn
|
||||||
-- @field #boolean smokeaveragetargetpos
|
-- @field #boolean smokeaveragetargetpos
|
||||||
|
-- @field #boolean reporttostringbullsonly
|
||||||
-- @extends Core.Fsm#FSM
|
-- @extends Core.Fsm#FSM
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -105,7 +106,7 @@ PLAYERRECCE = {
|
|||||||
ClassName = "PLAYERRECCE",
|
ClassName = "PLAYERRECCE",
|
||||||
verbose = true,
|
verbose = true,
|
||||||
lid = nil,
|
lid = nil,
|
||||||
version = "0.1.23",
|
version = "0.1.26",
|
||||||
ViewZone = {},
|
ViewZone = {},
|
||||||
ViewZoneVisual = {},
|
ViewZoneVisual = {},
|
||||||
ViewZoneLaser = {},
|
ViewZoneLaser = {},
|
||||||
@@ -133,7 +134,8 @@ PLAYERRECCE = {
|
|||||||
TargetCache = nil,
|
TargetCache = nil,
|
||||||
smokeownposition = false,
|
smokeownposition = false,
|
||||||
SmokeOwn = {},
|
SmokeOwn = {},
|
||||||
smokeaveragetargetpos = false,
|
smokeaveragetargetpos = true,
|
||||||
|
reporttostringbullsonly = true,
|
||||||
}
|
}
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -152,7 +154,8 @@ PLAYERRECCE.LaserRelativePos = {
|
|||||||
["SA342Minigun"] = { x = 1.7, y = 1.2, z = 0 },
|
["SA342Minigun"] = { x = 1.7, y = 1.2, z = 0 },
|
||||||
["SA342L"] = { x = 1.7, y = 1.2, z = 0 },
|
["SA342L"] = { x = 1.7, y = 1.2, z = 0 },
|
||||||
["Ka-50"] = { x = 6.1, y = -0.85 , z = 0 },
|
["Ka-50"] = { x = 6.1, y = -0.85 , z = 0 },
|
||||||
["Ka-50_3"] = { x = 6.1, y = -0.85 , z = 0 }
|
["Ka-50_3"] = { x = 6.1, y = -0.85 , z = 0 },
|
||||||
|
["OH58D"] = {x = 0, y = 2.8, z = 0},
|
||||||
}
|
}
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -164,7 +167,8 @@ PLAYERRECCE.MaxViewDistance = {
|
|||||||
["SA342Minigun"] = 8000,
|
["SA342Minigun"] = 8000,
|
||||||
["SA342L"] = 8000,
|
["SA342L"] = 8000,
|
||||||
["Ka-50"] = 8000,
|
["Ka-50"] = 8000,
|
||||||
["Ka-50_3"] = 8000,
|
["Ka-50_3"] = 8000,
|
||||||
|
["OH58D"] = 8000,
|
||||||
}
|
}
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -176,7 +180,8 @@ PLAYERRECCE.Cameraheight = {
|
|||||||
["SA342Minigun"] = 2.85,
|
["SA342Minigun"] = 2.85,
|
||||||
["SA342L"] = 2.85,
|
["SA342L"] = 2.85,
|
||||||
["Ka-50"] = 0.5,
|
["Ka-50"] = 0.5,
|
||||||
["Ka-50_3"] = 0.5,
|
["Ka-50_3"] = 0.5,
|
||||||
|
["OH58D"] = 4.25,
|
||||||
}
|
}
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -188,7 +193,8 @@ PLAYERRECCE.CanLase = {
|
|||||||
["SA342Minigun"] = false, -- no optics
|
["SA342Minigun"] = false, -- no optics
|
||||||
["SA342L"] = true,
|
["SA342L"] = true,
|
||||||
["Ka-50"] = true,
|
["Ka-50"] = true,
|
||||||
["Ka-50_3"] = true,
|
["Ka-50_3"] = true,
|
||||||
|
["OH58D"] = false, -- has onboard and useable laser
|
||||||
}
|
}
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -236,6 +242,8 @@ function PLAYERRECCE:New(Name, Coalition, PlayerSet)
|
|||||||
|
|
||||||
self.minthreatlevel = 0
|
self.minthreatlevel = 0
|
||||||
|
|
||||||
|
self.reporttostringbullsonly = true
|
||||||
|
|
||||||
self.TForget = 600
|
self.TForget = 600
|
||||||
self.TargetCache = FIFO:New()
|
self.TargetCache = FIFO:New()
|
||||||
|
|
||||||
@@ -542,7 +550,7 @@ function PLAYERRECCE:SetAttackSet(AttackSet)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
---[Internal] Check Gazelle camera in on
|
---[Internal] Check Helicopter camera in on
|
||||||
-- @param #PLAYERRECCE self
|
-- @param #PLAYERRECCE self
|
||||||
-- @param Wrapper.Client#CLIENT client
|
-- @param Wrapper.Client#CLIENT client
|
||||||
-- @param #string playername
|
-- @param #string playername
|
||||||
@@ -558,6 +566,12 @@ function PLAYERRECCE:_CameraOn(client,playername)
|
|||||||
if vivihorizontal < -0.7 or vivihorizontal > 0.7 then
|
if vivihorizontal < -0.7 or vivihorizontal > 0.7 then
|
||||||
camera = false
|
camera = false
|
||||||
end
|
end
|
||||||
|
elseif string.find(typename,"OH58") then
|
||||||
|
local dcsunit = Unit.getByName(client:GetName())
|
||||||
|
local vivihorizontal = dcsunit:getDrawArgumentValue(528) or 0 -- Kiow
|
||||||
|
if vivihorizontal < -0.527 or vivihorizontal > 0.527 then
|
||||||
|
camera = false
|
||||||
|
end
|
||||||
elseif string.find(typename,"Ka-50") then
|
elseif string.find(typename,"Ka-50") then
|
||||||
camera = true
|
camera = true
|
||||||
end
|
end
|
||||||
@@ -565,6 +579,52 @@ function PLAYERRECCE:_CameraOn(client,playername)
|
|||||||
return camera
|
return camera
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- [Internal] Get the view parameters from a Kiowa MMS camera
|
||||||
|
-- @param #PLAYERRECCE self
|
||||||
|
-- @param Wrapper.Unit#UNIT Kiowa
|
||||||
|
-- @return #number cameraheading in degrees.
|
||||||
|
-- @return #number cameranodding in degrees.
|
||||||
|
-- @return #number maxview in meters.
|
||||||
|
-- @return #boolean cameraison If true, camera is on, else off.
|
||||||
|
function PLAYERRECCE:_GetKiowaMMSSight(Kiowa)
|
||||||
|
self:T(self.lid.."_GetKiowaMMSSight")
|
||||||
|
local unit = Kiowa -- Wrapper.Unit#UNIT
|
||||||
|
if unit and unit:IsAlive() then
|
||||||
|
local dcsunit = Unit.getByName(Kiowa:GetName())
|
||||||
|
--[[
|
||||||
|
shagrat — 01/01/2025 23:13
|
||||||
|
Found the necessary ARGS for the Kiowa MMS angle and rotation:
|
||||||
|
Arg 527 vertical movement
|
||||||
|
0 = neutral
|
||||||
|
-1.0 = max depression (30° max depression angle)
|
||||||
|
+1.0 = max elevation angle (30° max elevation angle)
|
||||||
|
|
||||||
|
Arg 528 horizontal movement
|
||||||
|
0 = forward (0 degr)
|
||||||
|
-0.25 = 90° left
|
||||||
|
-0.5 = rear (180°) left (max 190° = -0.527
|
||||||
|
+0.25 = 90° right
|
||||||
|
+0.5 = 180° right (max 190° = 0.527)
|
||||||
|
--]]
|
||||||
|
local mmshorizontal = dcsunit:getDrawArgumentValue(528) or 0
|
||||||
|
local mmsvertical = dcsunit:getDrawArgumentValue(527) or 0
|
||||||
|
self:T(string.format("Kiowa MMS Arguments Read: H %.3f V %.3f",mmshorizontal,mmsvertical))
|
||||||
|
local mmson = true
|
||||||
|
if mmshorizontal < -0.527 or mmshorizontal > 0.527 then mmson = false end
|
||||||
|
local horizontalview = mmshorizontal / 0.527 * 190
|
||||||
|
local heading = unit:GetHeading()
|
||||||
|
local mmsheading = (heading+horizontalview)%360
|
||||||
|
--local mmsyaw = mmsvertical * 30
|
||||||
|
local mmsyaw = math.atan(mmsvertical)*40
|
||||||
|
local maxview = self:_GetActualMaxLOSight(unit,mmsheading, mmsyaw,not mmson)
|
||||||
|
if maxview > 8000 then maxview = 8000 end
|
||||||
|
self:T(string.format("Kiowa MMS Heading %d, Yaw %d, MaxView %dm MMS On %s",mmsheading,mmsyaw,maxview,tostring(mmson)))
|
||||||
|
return mmsheading,mmsyaw,maxview,mmson
|
||||||
|
end
|
||||||
|
return 0,0,0,false
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
--- [Internal] Get the view parameters from a Gazelle camera
|
--- [Internal] Get the view parameters from a Gazelle camera
|
||||||
-- @param #PLAYERRECCE self
|
-- @param #PLAYERRECCE self
|
||||||
-- @param Wrapper.Unit#UNIT Gazelle
|
-- @param Wrapper.Unit#UNIT Gazelle
|
||||||
@@ -593,40 +653,15 @@ function PLAYERRECCE:_GetGazelleVivianneSight(Gazelle)
|
|||||||
vivioff = true
|
vivioff = true
|
||||||
return 0,0,0,false
|
return 0,0,0,false
|
||||||
end
|
end
|
||||||
vivivertical = vivivertical / 1.10731 -- normalize
|
|
||||||
local horizontalview = vivihorizontal * -180
|
local horizontalview = vivihorizontal * -180
|
||||||
local verticalview = vivivertical * 30 -- ca +/- 30°
|
--local verticalview = vivivertical * 30 -- ca +/- 30°
|
||||||
--self:I(string.format("vivihorizontal=%.5f | vivivertical=%.5f",vivihorizontal,vivivertical))
|
local verticalview = math.atan(vivivertical)
|
||||||
--self:I(string.format("horizontal=%.5f | vertical=%.5f",horizontalview,verticalview))
|
|
||||||
local heading = unit:GetHeading()
|
local heading = unit:GetHeading()
|
||||||
local viviheading = (heading+horizontalview)%360
|
local viviheading = (heading+horizontalview)%360
|
||||||
local maxview = self:_GetActualMaxLOSight(unit,viviheading, verticalview,vivioff)
|
local maxview = self:_GetActualMaxLOSight(unit,viviheading, verticalview,vivioff)
|
||||||
--self:I(string.format("maxview=%.5f",maxview))
|
|
||||||
-- visual skew
|
|
||||||
local factor = 3.15
|
|
||||||
self.GazelleViewFactors = {
|
|
||||||
[1]=1.18,
|
|
||||||
[2]=1.32,
|
|
||||||
[3]=1.46,
|
|
||||||
[4]=1.62,
|
|
||||||
[5]=1.77,
|
|
||||||
[6]=1.85,
|
|
||||||
[7]=2.05,
|
|
||||||
[8]=2.05,
|
|
||||||
[9]=2.3,
|
|
||||||
[10]=2.3,
|
|
||||||
[11]=2.27,
|
|
||||||
[12]=2.27,
|
|
||||||
[13]=2.43,
|
|
||||||
}
|
|
||||||
local lfac = UTILS.Round(maxview,-2)
|
|
||||||
if lfac <= 1300 then
|
|
||||||
--factor = self.GazelleViewFactors[lfac/100]
|
|
||||||
factor = 3.15
|
|
||||||
maxview = math.ceil((maxview*factor)/100)*100
|
|
||||||
end
|
|
||||||
if maxview > 8000 then maxview = 8000 end
|
if maxview > 8000 then maxview = 8000 end
|
||||||
--self:I(string.format("corrected maxview=%.5f",maxview))
|
|
||||||
return viviheading, verticalview,maxview, not vivioff
|
return viviheading, verticalview,maxview, not vivioff
|
||||||
end
|
end
|
||||||
return 0,0,0,false
|
return 0,0,0,false
|
||||||
@@ -647,20 +682,20 @@ function PLAYERRECCE:_GetActualMaxLOSight(unit,vheading, vnod, vivoff)
|
|||||||
if unit and unit:IsAlive() then
|
if unit and unit:IsAlive() then
|
||||||
local typename = unit:GetTypeName()
|
local typename = unit:GetTypeName()
|
||||||
maxview = self.MaxViewDistance[typename] or 8000
|
maxview = self.MaxViewDistance[typename] or 8000
|
||||||
local CamHeight = self.Cameraheight[typename] or 0
|
local CamHeight = self.Cameraheight[typename] or 1
|
||||||
if vnod < 0 then
|
if vnod < -2 then
|
||||||
-- Looking down
|
-- Looking down
|
||||||
-- determine max distance we're looking at
|
-- determine max distance we're looking at
|
||||||
local beta = 90
|
local beta = 90
|
||||||
local gamma = math.floor(90-vnod)
|
local gamma = 90-math.abs(vnod)
|
||||||
local alpha = math.floor(180-beta-gamma)
|
local alpha = 90-gamma
|
||||||
local a = unit:GetHeight()-unit:GetCoordinate():GetLandHeight()+CamHeight
|
local a = unit:GetHeight()-unit:GetCoordinate():GetLandHeight()+CamHeight
|
||||||
local b = a / math.sin(math.rad(alpha))
|
local b = a / math.sin(math.rad(alpha))
|
||||||
local c = b * math.sin(math.rad(gamma))
|
local c = b * math.sin(math.rad(gamma))
|
||||||
maxview = c*1.2 -- +20%
|
maxview = c*1.2 -- +20%
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return math.abs(maxview)
|
return math.ceil(math.abs(maxview))
|
||||||
end
|
end
|
||||||
|
|
||||||
--- [User] Set callsign options for TTS output. See @{Wrapper.Group#GROUP.GetCustomCallSign}() on how to set customized callsigns.
|
--- [User] Set callsign options for TTS output. See @{Wrapper.Group#GROUP.GetCustomCallSign}() on how to set customized callsigns.
|
||||||
@@ -669,8 +704,10 @@ end
|
|||||||
-- @param #boolean Keepnumber If true, keep the **customized callsign** in the #GROUP name for players as-is, no amendments or numbers.
|
-- @param #boolean Keepnumber If true, keep the **customized callsign** in the #GROUP name for players as-is, no amendments or numbers.
|
||||||
-- @param #table CallsignTranslations (optional) Table to translate between DCS standard callsigns and bespoke ones. Does not apply if using customized
|
-- @param #table CallsignTranslations (optional) Table to translate between DCS standard callsigns and bespoke ones. Does not apply if using customized
|
||||||
-- callsigns from playername or group name.
|
-- callsigns from playername or group name.
|
||||||
|
-- @param #func CallsignCustomFunc (Optional) For player names only(!). If given, this function will return the callsign. Needs to take the groupname and the playername as first two arguments.
|
||||||
|
-- @param #arg ... (Optional) Comma separated arguments to add to the custom function call after groupname and playername.
|
||||||
-- @return #PLAYERRECCE self
|
-- @return #PLAYERRECCE self
|
||||||
function PLAYERRECCE:SetCallSignOptions(ShortCallsign,Keepnumber,CallsignTranslations)
|
function PLAYERRECCE:SetCallSignOptions(ShortCallsign,Keepnumber,CallsignTranslations,CallsignCustomFunc,...)
|
||||||
if not ShortCallsign or ShortCallsign == false then
|
if not ShortCallsign or ShortCallsign == false then
|
||||||
self.ShortCallsign = false
|
self.ShortCallsign = false
|
||||||
else
|
else
|
||||||
@@ -678,6 +715,8 @@ function PLAYERRECCE:SetCallSignOptions(ShortCallsign,Keepnumber,CallsignTransla
|
|||||||
end
|
end
|
||||||
self.Keepnumber = Keepnumber or false
|
self.Keepnumber = Keepnumber or false
|
||||||
self.CallsignTranslations = CallsignTranslations
|
self.CallsignTranslations = CallsignTranslations
|
||||||
|
self.CallsignCustomFunc = CallsignCustomFunc
|
||||||
|
self.CallsignCustomArgs = arg or {}
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -799,7 +838,7 @@ function PLAYERRECCE:_GetTargetSet(unit,camera,laser)
|
|||||||
local minview = 0
|
local minview = 0
|
||||||
local typename = unit:GetTypeName()
|
local typename = unit:GetTypeName()
|
||||||
local playername = unit:GetPlayerName()
|
local playername = unit:GetPlayerName()
|
||||||
local maxview = self.MaxViewDistance[typename] or 5000
|
local maxview = self.MaxViewDistance[typename] or 8000
|
||||||
local heading,nod,maxview,angle = 0,30,8000,10
|
local heading,nod,maxview,angle = 0,30,8000,10
|
||||||
local camon = false
|
local camon = false
|
||||||
local name = unit:GetName()
|
local name = unit:GetName()
|
||||||
@@ -807,16 +846,25 @@ function PLAYERRECCE:_GetTargetSet(unit,camera,laser)
|
|||||||
heading,nod,maxview,camon = self:_GetGazelleVivianneSight(unit)
|
heading,nod,maxview,camon = self:_GetGazelleVivianneSight(unit)
|
||||||
angle=10
|
angle=10
|
||||||
-- Model nod and actual TV view don't compute
|
-- Model nod and actual TV view don't compute
|
||||||
maxview = self.MaxViewDistance[typename] or 5000
|
maxview = self.MaxViewDistance[typename] or 8000
|
||||||
elseif string.find(typename,"Ka-50") and camera then
|
elseif string.find(typename,"Ka-50") and camera then
|
||||||
heading = unit:GetHeading()
|
heading = unit:GetHeading()
|
||||||
nod,maxview,camon = 10,1000,true
|
nod,maxview,camon = 10,1000,true
|
||||||
angle = 10
|
angle = 10
|
||||||
maxview = self.MaxViewDistance[typename] or 5000
|
maxview = self.MaxViewDistance[typename] or 8000
|
||||||
|
elseif string.find(typename,"OH58") and camera then
|
||||||
|
--heading = unit:GetHeading()
|
||||||
|
nod,maxview,camon = 0,8000,true
|
||||||
|
heading,nod,maxview,camon = self:_GetKiowaMMSSight(unit)
|
||||||
|
angle = 8
|
||||||
|
if maxview == 0 then
|
||||||
|
maxview = self.MaxViewDistance[typename] or 8000
|
||||||
|
end
|
||||||
else
|
else
|
||||||
-- visual
|
-- visual
|
||||||
heading = unit:GetHeading()
|
heading = unit:GetHeading()
|
||||||
nod,maxview,camon = 10,1000,true
|
nod,maxview,camon = 10,3000,true
|
||||||
|
maxview = self.MaxViewDistance[typename] or 3000
|
||||||
angle = 45
|
angle = 45
|
||||||
end
|
end
|
||||||
if laser then
|
if laser then
|
||||||
@@ -929,7 +977,8 @@ function PLAYERRECCE:_LaseTarget(client,targetset)
|
|||||||
if (not oldtarget) or targetset:IsNotInSet(oldtarget) or target:IsDead() or target:IsDestroyed() then
|
if (not oldtarget) or targetset:IsNotInSet(oldtarget) or target:IsDead() or target:IsDestroyed() then
|
||||||
-- lost LOS or dead
|
-- lost LOS or dead
|
||||||
laser:LaseOff()
|
laser:LaseOff()
|
||||||
if target:IsDead() or target:IsDestroyed() or target:GetLife() < 2 then
|
self:T(self.lid.."Target Life Points: "..target:GetLife() or "none")
|
||||||
|
if target:IsDead() or target:IsDestroyed() or target:GetDamage() > 79 or target:GetLife() <= 1 then
|
||||||
self:__Shack(-1,client,oldtarget)
|
self:__Shack(-1,client,oldtarget)
|
||||||
--self.LaserTarget[playername] = nil
|
--self.LaserTarget[playername] = nil
|
||||||
else
|
else
|
||||||
@@ -1274,6 +1323,9 @@ self:T(self.lid.."_ReportLaserTargets")
|
|||||||
report:Add("Threat Level: "..ThreatGraph.." ("..ThreatLevelText..")")
|
report:Add("Threat Level: "..ThreatGraph.." ("..ThreatLevelText..")")
|
||||||
if not self.ReferencePoint then
|
if not self.ReferencePoint then
|
||||||
report:Add("Location: "..client:GetCoordinate():ToStringBULLS(self.Coalition,Settings))
|
report:Add("Location: "..client:GetCoordinate():ToStringBULLS(self.Coalition,Settings))
|
||||||
|
if self.reporttostringbullsonly ~= true then
|
||||||
|
report:Add("Location: "..client:GetCoordinate():ToStringA2G(nil,Settings))
|
||||||
|
end
|
||||||
else
|
else
|
||||||
report:Add("Location: "..client:GetCoordinate():ToStringFromRPShort(self.ReferencePoint,self.RPName,client,Settings))
|
report:Add("Location: "..client:GetCoordinate():ToStringFromRPShort(self.ReferencePoint,self.RPName,client,Settings))
|
||||||
end
|
end
|
||||||
@@ -1317,8 +1369,14 @@ function PLAYERRECCE:_ReportVisualTargets(client,group,playername)
|
|||||||
report:Add("Threat Level: "..ThreatGraph.." ("..ThreatLevelText..")")
|
report:Add("Threat Level: "..ThreatGraph.." ("..ThreatLevelText..")")
|
||||||
if not self.ReferencePoint then
|
if not self.ReferencePoint then
|
||||||
report:Add("Location: "..client:GetCoordinate():ToStringBULLS(self.Coalition,Settings))
|
report:Add("Location: "..client:GetCoordinate():ToStringBULLS(self.Coalition,Settings))
|
||||||
|
if self.reporttostringbullsonly ~= true then
|
||||||
|
report:Add("Location: "..client:GetCoordinate():ToStringA2G(nil,Settings))
|
||||||
|
end
|
||||||
else
|
else
|
||||||
report:Add("Location: "..client:GetCoordinate():ToStringFromRPShort(self.ReferencePoint,self.RPName,client,Settings))
|
report:Add("Location: "..client:GetCoordinate():ToStringFromRPShort(self.ReferencePoint,self.RPName,client,Settings))
|
||||||
|
if self.reporttostringbullsonly ~= true then
|
||||||
|
report:Add("Location: "..client:GetCoordinate():ToStringA2G(nil,Settings))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
report:Add(string.rep("-",15))
|
report:Add(string.rep("-",15))
|
||||||
local text = report:Text()
|
local text = report:Text()
|
||||||
@@ -1347,6 +1405,7 @@ function PLAYERRECCE:_BuildMenus(Client)
|
|||||||
local client = _client -- Wrapper.Client#CLIENT
|
local client = _client -- Wrapper.Client#CLIENT
|
||||||
if client and client:IsAlive() then
|
if client and client:IsAlive() then
|
||||||
local playername = client:GetPlayerName()
|
local playername = client:GetPlayerName()
|
||||||
|
self:T("Menu for "..playername)
|
||||||
if not self.UnitLaserCodes[playername] then
|
if not self.UnitLaserCodes[playername] then
|
||||||
self:_SetClientLaserCode(nil,nil,playername,1688)
|
self:_SetClientLaserCode(nil,nil,playername,1688)
|
||||||
end
|
end
|
||||||
@@ -1355,6 +1414,7 @@ function PLAYERRECCE:_BuildMenus(Client)
|
|||||||
end
|
end
|
||||||
local group = client:GetGroup()
|
local group = client:GetGroup()
|
||||||
if not self.ClientMenus[playername] then
|
if not self.ClientMenus[playername] then
|
||||||
|
self:T("Start Menubuild for "..playername)
|
||||||
local canlase = self.CanLase[client:GetTypeName()]
|
local canlase = self.CanLase[client:GetTypeName()]
|
||||||
self.ClientMenus[playername] = MENU_GROUP:New(group,self.MenuName or self.Name or "RECCE")
|
self.ClientMenus[playername] = MENU_GROUP:New(group,self.MenuName or self.Name or "RECCE")
|
||||||
local txtonstation = self.OnStation[playername] and "ON" or "OFF"
|
local txtonstation = self.OnStation[playername] and "ON" or "OFF"
|
||||||
@@ -1492,8 +1552,9 @@ end
|
|||||||
-- Note that this must be installed on your windows system. Can also be Google voice types, if you are using Google TTS.
|
-- Note that this must be installed on your windows system. Can also be Google voice types, if you are using Google TTS.
|
||||||
-- @param #number Volume (Optional) Volume - between 0.0 (silent) and 1.0 (loudest)
|
-- @param #number Volume (Optional) Volume - between 0.0 (silent) and 1.0 (loudest)
|
||||||
-- @param #string PathToGoogleKey (Optional) Path to your google key if you want to use google TTS
|
-- @param #string PathToGoogleKey (Optional) Path to your google key if you want to use google TTS
|
||||||
|
-- @param #string Backend (optional) Backend to be used, can be MSRS.Backend.SRSEXE or MSRS.Backend.GRPC
|
||||||
-- @return #PLAYERRECCE self
|
-- @return #PLAYERRECCE self
|
||||||
function PLAYERRECCE:SetSRS(Frequency,Modulation,PathToSRS,Gender,Culture,Port,Voice,Volume,PathToGoogleKey)
|
function PLAYERRECCE:SetSRS(Frequency,Modulation,PathToSRS,Gender,Culture,Port,Voice,Volume,PathToGoogleKey,Backend)
|
||||||
self:T(self.lid.."SetSRS")
|
self:T(self.lid.."SetSRS")
|
||||||
self.PathToSRS = PathToSRS or MSRS.path or "C:\\Program Files\\DCS-SimpleRadio-Standalone" --
|
self.PathToSRS = PathToSRS or MSRS.path or "C:\\Program Files\\DCS-SimpleRadio-Standalone" --
|
||||||
self.Gender = Gender or MSRS.gender or "male" --
|
self.Gender = Gender or MSRS.gender or "male" --
|
||||||
@@ -1515,6 +1576,9 @@ function PLAYERRECCE:SetSRS(Frequency,Modulation,PathToSRS,Gender,Culture,Port,V
|
|||||||
self.SRS:SetCulture(self.Culture)
|
self.SRS:SetCulture(self.Culture)
|
||||||
self.SRS:SetPort(self.Port)
|
self.SRS:SetPort(self.Port)
|
||||||
self.SRS:SetVolume(self.Volume)
|
self.SRS:SetVolume(self.Volume)
|
||||||
|
if Backend then
|
||||||
|
self.SRS:SetBackend(Backend)
|
||||||
|
end
|
||||||
if self.PathToGoogleKey then
|
if self.PathToGoogleKey then
|
||||||
self.SRS:SetProviderOptionsGoogle(self.PathToGoogleKey,self.PathToGoogleKey)
|
self.SRS:SetProviderOptionsGoogle(self.PathToGoogleKey,self.PathToGoogleKey)
|
||||||
self.SRS:SetProvider(MSRS.Provider.GOOGLE)
|
self.SRS:SetProvider(MSRS.Provider.GOOGLE)
|
||||||
@@ -1552,6 +1616,16 @@ function PLAYERRECCE:SetMenuName(Name)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- [User] Set reporting to be BULLS only or BULLS plus playersettings based coordinate.
|
||||||
|
-- @param #PLAYERRECCE self
|
||||||
|
-- @param #boolean OnOff
|
||||||
|
-- @return #PLAYERRECCE self
|
||||||
|
function PLAYERRECCE:SetReportBullsOnly(OnOff)
|
||||||
|
self:T(self.lid.."SetReportBullsOnly: "..tostring(OnOff))
|
||||||
|
self.reporttostringbullsonly = OnOff
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- [User] Enable smoking of own position
|
--- [User] Enable smoking of own position
|
||||||
-- @param #PLAYERRECCE self
|
-- @param #PLAYERRECCE self
|
||||||
-- @return #PLAYERRECCE self
|
-- @return #PLAYERRECCE self
|
||||||
@@ -1561,6 +1635,15 @@ function PLAYERRECCE:EnableSmokeOwnPosition()
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- [User] Enable auto lasing for the Kiowa OH-58D.
|
||||||
|
-- @param #PLAYERRECCE self
|
||||||
|
-- @return #PLAYERRECCE self
|
||||||
|
function PLAYERRECCE:EnableKiowaAutolase()
|
||||||
|
self:T(self.lid.."EnableKiowaAutolase")
|
||||||
|
self.CanLase.OH58D = true
|
||||||
|
return self
|
||||||
|
end
|
||||||
|
|
||||||
--- [User] Disable smoking of own position
|
--- [User] Disable smoking of own position
|
||||||
-- @param #PLAYERRECCE self
|
-- @param #PLAYERRECCE self
|
||||||
-- @return #PLAYERRECCE
|
-- @return #PLAYERRECCE
|
||||||
@@ -1718,7 +1801,7 @@ end
|
|||||||
-- @return #PLAYERRECCE self
|
-- @return #PLAYERRECCE self
|
||||||
function PLAYERRECCE:onafterRecceOnStation(From, Event, To, Client, Playername)
|
function PLAYERRECCE:onafterRecceOnStation(From, Event, To, Client, Playername)
|
||||||
self:T({From, Event, To})
|
self:T({From, Event, To})
|
||||||
local callsign = Client:GetGroup():GetCustomCallSign(self.ShortCallsign,self.Keepnumber,self.CallsignTranslations)
|
local callsign = Client:GetGroup():GetCustomCallSign(self.ShortCallsign,self.Keepnumber,self.CallsignTranslations,self.CallsignCustomFunc,self.CallsignCustomArgs)
|
||||||
local coord = Client:GetCoordinate()
|
local coord = Client:GetCoordinate()
|
||||||
local coordtext = coord:ToStringBULLS(self.Coalition)
|
local coordtext = coord:ToStringBULLS(self.Coalition)
|
||||||
if self.ReferencePoint then
|
if self.ReferencePoint then
|
||||||
@@ -1727,7 +1810,7 @@ function PLAYERRECCE:onafterRecceOnStation(From, Event, To, Client, Playername)
|
|||||||
end
|
end
|
||||||
local text1 = "Party time!"
|
local text1 = "Party time!"
|
||||||
local text2 = string.format("All stations, FACA %s on station\nat %s!",callsign, coordtext)
|
local text2 = string.format("All stations, FACA %s on station\nat %s!",callsign, coordtext)
|
||||||
local text2tts = string.format("All stations, FACA %s on station at %s!",callsign, coordtext)
|
local text2tts = string.format(" All stations, FACA %s on station at %s!",callsign, coordtext)
|
||||||
text2tts = self:_GetTextForSpeech(text2tts)
|
text2tts = self:_GetTextForSpeech(text2tts)
|
||||||
if self.debug then
|
if self.debug then
|
||||||
self:T(text2.."\n"..text2tts)
|
self:T(text2.."\n"..text2tts)
|
||||||
@@ -1758,7 +1841,7 @@ end
|
|||||||
-- @return #PLAYERRECCE self
|
-- @return #PLAYERRECCE self
|
||||||
function PLAYERRECCE:onafterRecceOffStation(From, Event, To, Client, Playername)
|
function PLAYERRECCE:onafterRecceOffStation(From, Event, To, Client, Playername)
|
||||||
self:T({From, Event, To})
|
self:T({From, Event, To})
|
||||||
local callsign = Client:GetGroup():GetCustomCallSign(self.ShortCallsign,self.Keepnumber,self.CallsignTranslations)
|
local callsign = Client:GetGroup():GetCustomCallSign(self.ShortCallsign,self.Keepnumber,self.CallsignTranslations,self.CallsignCustomFunc,self.CallsignCustomArgs)
|
||||||
local coord = Client:GetCoordinate()
|
local coord = Client:GetCoordinate()
|
||||||
local coordtext = coord:ToStringBULLS(self.Coalition)
|
local coordtext = coord:ToStringBULLS(self.Coalition)
|
||||||
if self.ReferencePoint then
|
if self.ReferencePoint then
|
||||||
@@ -1898,7 +1981,7 @@ end
|
|||||||
-- @return #PLAYERRECCE self
|
-- @return #PLAYERRECCE self
|
||||||
function PLAYERRECCE:onafterIllumination(From, Event, To, Client, Playername, TargetSet)
|
function PLAYERRECCE:onafterIllumination(From, Event, To, Client, Playername, TargetSet)
|
||||||
self:T({From, Event, To})
|
self:T({From, Event, To})
|
||||||
local callsign = Client:GetGroup():GetCustomCallSign(self.ShortCallsign,self.Keepnumber,self.CallsignTranslations)
|
local callsign = Client:GetGroup():GetCustomCallSign(self.ShortCallsign,self.Keepnumber,self.CallsignTranslations,self.CallsignCustomFunc,self.CallsignCustomArgs)
|
||||||
local coord = Client:GetCoordinate()
|
local coord = Client:GetCoordinate()
|
||||||
local coordtext = coord:ToStringBULLS(self.Coalition)
|
local coordtext = coord:ToStringBULLS(self.Coalition)
|
||||||
if self.AttackSet then
|
if self.AttackSet then
|
||||||
@@ -1941,7 +2024,7 @@ end
|
|||||||
-- @return #PLAYERRECCE self
|
-- @return #PLAYERRECCE self
|
||||||
function PLAYERRECCE:onafterTargetsSmoked(From, Event, To, Client, Playername, TargetSet)
|
function PLAYERRECCE:onafterTargetsSmoked(From, Event, To, Client, Playername, TargetSet)
|
||||||
self:T({From, Event, To})
|
self:T({From, Event, To})
|
||||||
local callsign = Client:GetGroup():GetCustomCallSign(self.ShortCallsign,self.Keepnumber,self.CallsignTranslations)
|
local callsign = Client:GetGroup():GetCustomCallSign(self.ShortCallsign,self.Keepnumber,self.CallsignTranslations,self.CallsignCustomFunc,self.CallsignCustomArgs)
|
||||||
local coord = Client:GetCoordinate()
|
local coord = Client:GetCoordinate()
|
||||||
local coordtext = coord:ToStringBULLS(self.Coalition)
|
local coordtext = coord:ToStringBULLS(self.Coalition)
|
||||||
if self.AttackSet then
|
if self.AttackSet then
|
||||||
@@ -1984,7 +2067,7 @@ end
|
|||||||
-- @return #PLAYERRECCE self
|
-- @return #PLAYERRECCE self
|
||||||
function PLAYERRECCE:onafterTargetsFlared(From, Event, To, Client, Playername, TargetSet)
|
function PLAYERRECCE:onafterTargetsFlared(From, Event, To, Client, Playername, TargetSet)
|
||||||
self:T({From, Event, To})
|
self:T({From, Event, To})
|
||||||
local callsign = Client:GetGroup():GetCustomCallSign(self.ShortCallsign,self.Keepnumber,self.CallsignTranslations)
|
local callsign = Client:GetGroup():GetCustomCallSign(self.ShortCallsign,self.Keepnumber,self.CallsignTranslations,self.CallsignCustomFunc,self.CallsignCustomArgs)
|
||||||
local coord = Client:GetCoordinate()
|
local coord = Client:GetCoordinate()
|
||||||
local coordtext = coord:ToStringBULLS(self.Coalition)
|
local coordtext = coord:ToStringBULLS(self.Coalition)
|
||||||
if self.AttackSet then
|
if self.AttackSet then
|
||||||
@@ -2028,7 +2111,7 @@ end
|
|||||||
-- @return #PLAYERRECCE self
|
-- @return #PLAYERRECCE self
|
||||||
function PLAYERRECCE:onafterTargetLasing(From, Event, To, Client, Target, Lasercode, Lasingtime)
|
function PLAYERRECCE:onafterTargetLasing(From, Event, To, Client, Target, Lasercode, Lasingtime)
|
||||||
self:T({From, Event, To})
|
self:T({From, Event, To})
|
||||||
local callsign = Client:GetGroup():GetCustomCallSign(self.ShortCallsign,self.Keepnumber,self.CallsignTranslations)
|
local callsign = Client:GetGroup():GetCustomCallSign(self.ShortCallsign,self.Keepnumber,self.CallsignTranslations,self.CallsignCustomFunc,self.CallsignCustomArgs)
|
||||||
local Settings = ( Client and _DATABASE:GetPlayerSettings( Client:GetPlayerName() ) ) or _SETTINGS
|
local Settings = ( Client and _DATABASE:GetPlayerSettings( Client:GetPlayerName() ) ) or _SETTINGS
|
||||||
local coord = Client:GetCoordinate()
|
local coord = Client:GetCoordinate()
|
||||||
local coordtext = coord:ToStringBULLS(self.Coalition,Settings)
|
local coordtext = coord:ToStringBULLS(self.Coalition,Settings)
|
||||||
@@ -2075,7 +2158,7 @@ end
|
|||||||
-- @return #PLAYERRECCE self
|
-- @return #PLAYERRECCE self
|
||||||
function PLAYERRECCE:onafterShack(From, Event, To, Client, Target)
|
function PLAYERRECCE:onafterShack(From, Event, To, Client, Target)
|
||||||
self:T({From, Event, To})
|
self:T({From, Event, To})
|
||||||
local callsign = Client:GetGroup():GetCustomCallSign(self.ShortCallsign,self.Keepnumber,self.CallsignTranslations)
|
local callsign = Client:GetGroup():GetCustomCallSign(self.ShortCallsign,self.Keepnumber,self.CallsignTranslations,self.CallsignCustomFunc,self.CallsignCustomArgs)
|
||||||
local Settings = ( Client and _DATABASE:GetPlayerSettings( Client:GetPlayerName() ) ) or _SETTINGS
|
local Settings = ( Client and _DATABASE:GetPlayerSettings( Client:GetPlayerName() ) ) or _SETTINGS
|
||||||
local coord = Client:GetCoordinate()
|
local coord = Client:GetCoordinate()
|
||||||
local coordtext = coord:ToStringBULLS(self.Coalition,Settings)
|
local coordtext = coord:ToStringBULLS(self.Coalition,Settings)
|
||||||
@@ -2122,7 +2205,7 @@ end
|
|||||||
-- @return #PLAYERRECCE self
|
-- @return #PLAYERRECCE self
|
||||||
function PLAYERRECCE:onafterTargetLOSLost(From, Event, To, Client, Target)
|
function PLAYERRECCE:onafterTargetLOSLost(From, Event, To, Client, Target)
|
||||||
self:T({From, Event, To})
|
self:T({From, Event, To})
|
||||||
local callsign = Client:GetGroup():GetCustomCallSign(self.ShortCallsign,self.Keepnumber,self.CallsignTranslations)
|
local callsign = Client:GetGroup():GetCustomCallSign(self.ShortCallsign,self.Keepnumber,self.CallsignTranslations,self.CallsignCustomFunc,self.CallsignCustomArgs)
|
||||||
local Settings = ( Client and _DATABASE:GetPlayerSettings( Client:GetPlayerName() ) ) or _SETTINGS
|
local Settings = ( Client and _DATABASE:GetPlayerSettings( Client:GetPlayerName() ) ) or _SETTINGS
|
||||||
local coord = Client:GetCoordinate()
|
local coord = Client:GetCoordinate()
|
||||||
local coordtext = coord:ToStringBULLS(self.Coalition,Settings)
|
local coordtext = coord:ToStringBULLS(self.Coalition,Settings)
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user