This commit is contained in:
Frank 2023-10-31 10:45:58 +01:00
commit 059d8ccfc0
21 changed files with 694 additions and 126 deletions

View File

@ -67,3 +67,12 @@ jobs:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v1
check:
runs-on: ubuntu-latest
needs: deploy
steps:
- name: Setup Node
uses: actions/setup-node@v3
- run: npm install linkinator
- run: npx linkinator https://flightcontrol-master.github.io/MOOSE/ --recurse

2
.gitignore vendored
View File

@ -234,3 +234,5 @@ MooseCodeWS.code-workspace
# Excludes for act (https://github.com/nektos/act)
.secrets
.env
.actrc
.vars

View File

@ -135,6 +135,22 @@ do -- env
end -- env
do -- radio
---@type radio
-- @field #radio.modulation modulation
---
-- @type radio.modulation
-- @field AM
-- @field FM
radio = {}
radio.modulation = {}
radio.modulation.AM = 0
radio.modulation.FM = 1
end
do -- timer
@ -329,11 +345,11 @@ end -- country
do -- Command
--- @type Command
-- @type Command
-- @field #string id
-- @field #Command.params params
--- @type Command.params
-- @type Command.params
end -- Command
@ -374,7 +390,7 @@ end -- coalition
do -- Types
--- @type Desc
-- @type Desc
-- @field #number speedMax0 Max speed in meters/second at zero altitude.
-- @field #number massEmpty Empty mass in kg.
-- @field #number tankerType Type of refueling system: 0=boom, 1=probe.
@ -471,16 +487,16 @@ do -- Types
-- @type AttributeNameArray
-- @list <#AttributeName>
--- @type Zone
-- @type Zone
-- @field DCSVec3#Vec3 point
-- @field #number radius
Zone = {}
--- @type ModelTime
-- @type ModelTime
-- @extends #number
--- @type Time
-- @type Time
-- @extends #number
--- A task descriptor (internal structure for DCS World). See [https://wiki.hoggitworld.com/view/Category:Tasks](https://wiki.hoggitworld.com/view/Category:Tasks).
@ -489,7 +505,7 @@ do -- Types
-- @field #string id
-- @field #Task.param param
--- @type Task.param
-- @type Task.param
--- List of @{#Task}
-- @type TaskArray
@ -536,7 +552,7 @@ do -- Object
-- @field SCENERY
-- @field CARGO
--- @type Object.Desc
-- @type Object.Desc
-- @extends #Desc
-- @field #number life initial life level
-- @field #Box3 box bounding box of collision geometry
@ -1085,7 +1101,7 @@ end -- Controller
do -- Unit
--- @type Unit
-- @type Unit
-- @extends #CoalitionObject
-- @field ID Identifier of an unit. It assigned to an unit by the Mission Editor automatically.
-- @field #Unit.Category Category
@ -1200,15 +1216,18 @@ do -- Unit
-- @field #Distance detectionDistanceHRM detection distance for RCS=1m^2 in high-resolution mapping mode, nil if radar has no HRM
-- @field #Unit.Radar.detectionDistanceAir detectionDistanceAir detection distance for RCS=1m^2 airborne target, nil if radar doesn't support air search
--- @type Unit.Radar.detectionDistanceAir
--- A radar.
-- @type Unit.Radar.detectionDistanceAir
-- @field #Unit.Radar.detectionDistanceAir.upperHemisphere upperHemisphere
-- @field #Unit.Radar.detectionDistanceAir.lowerHemisphere lowerHemisphere
--- @type Unit.Radar.detectionDistanceAir.upperHemisphere
--- A radar.
-- @type Unit.Radar.detectionDistanceAir.upperHemisphere
-- @field #Distance headOn
-- @field #Distance tailOn
--- @type Unit.Radar.detectionDistanceAir.lowerHemisphere
--- A radar.
-- @type Unit.Radar.detectionDistanceAir.lowerHemisphere
-- @field #Distance headOn
-- @field #Distance tailOn
@ -1510,22 +1529,26 @@ do -- AI
-- @field IR_POINTER
-- @field LASER
--- @type AI.Task.WaypointType
---
-- @type AI.Task.WaypointType
-- @field TAKEOFF
-- @field TAKEOFF_PARKING
-- @field TURNING_POINT
-- @field TAKEOFF_PARKING_HOT
-- @field LAND
--- @type AI.Task.TurnMethod
---
-- @type AI.Task.TurnMethod
-- @field FLY_OVER_POINT
-- @field FIN_POINT
--- @type AI.Task.AltitudeType
---
-- @type AI.Task.AltitudeType
-- @field BARO
-- @field RADIO
--- @type AI.Task.VehicleFormation
---
-- @type AI.Task.VehicleFormation
-- @field OFF_ROAD
-- @field ON_ROAD
-- @field RANK
@ -1535,27 +1558,30 @@ do -- AI
-- @field ECHELON_LEFT
-- @field ECHELON_RIGHT
--- @type AI.Option
---
-- @type AI.Option
-- @field #AI.Option.Air Air
-- @field #AI.Option.Ground Ground
-- @field #AI.Option.Naval Naval
--- @type AI.Option.Air
---
-- @type AI.Option.Air
-- @field #AI.Option.Air.id id
-- @field #AI.Option.Air.val val
--- @type AI.Option.Ground
---
-- @type AI.Option.Ground
-- @field #AI.Option.Ground.id id
-- @field #AI.Option.Ground.val val
-- @field #AI.Option.Ground.mid mid
-- @field #AI.Option.Ground.mval mval
--
--- @type AI.Option.Naval
-- @type AI.Option.Naval
-- @field #AI.Option.Naval.id id
-- @field #AI.Option.Naval.val val
--- @type AI.Option.Air.id
---
-- @type AI.Option.Air.id
-- @field NO_OPTION
-- @field ROE
-- @field REACTION_ON_THREAT
@ -1578,72 +1604,60 @@ do -- AI
-- @field JETT_TANKS_IF_EMPTY
-- @field FORCED_ATTACK
--- @type AI.Option.Air.id.FORMATION
-- @field LINE_ABREAST
-- @field TRAIL
-- @field WEDGE
-- @field ECHELON_RIGHT
-- @field ECHELON_LEFT
-- @field FINGER_FOUR
-- @field SPREAD_FOUR
-- @field WW2_BOMBER_ELEMENT
-- @field WW2_BOMBER_ELEMENT_HEIGHT
-- @field WW2_FIGHTER_VIC
-- @field HEL_WEDGE
-- @field HEL_ECHELON
-- @field HEL_FRONT
-- @field HEL_COLUMN
-- @field COMBAT_BOX
-- @field JAVELIN_DOWN
--- @type AI.Option.Air.val
---
-- @type AI.Option.Air.val
-- @field #AI.Option.Air.val.ROE ROE
-- @field #AI.Option.Air.val.REACTION_ON_THREAT REACTION_ON_THREAT
-- @field #AI.Option.Air.val.RADAR_USING RADAR_USING
-- @field #AI.Option.Air.val.FLARE_USING FLARE_USING
--- @type AI.Option.Air.val.ROE
---
-- @type AI.Option.Air.val.ROE
-- @field WEAPON_FREE
-- @field OPEN_FIRE_WEAPON_FREE
-- @field OPEN_FIRE
-- @field RETURN_FIRE
-- @field WEAPON_HOLD
--- @type AI.Option.Air.val.REACTION_ON_THREAT
---
-- @type AI.Option.Air.val.REACTION_ON_THREAT
-- @field NO_REACTION
-- @field PASSIVE_DEFENCE
-- @field EVADE_FIRE
-- @field BYPASS_AND_ESCAPE
-- @field ALLOW_ABORT_MISSION
--- @type AI.Option.Air.val.RADAR_USING
---
-- @type AI.Option.Air.val.RADAR_USING
-- @field NEVER
-- @field FOR_ATTACK_ONLY
-- @field FOR_SEARCH_IF_REQUIRED
-- @field FOR_CONTINUOUS_SEARCH
--- @type AI.Option.Air.val.FLARE_USING
---
-- @type AI.Option.Air.val.FLARE_USING
-- @field NEVER
-- @field AGAINST_FIRED_MISSILE
-- @field WHEN_FLYING_IN_SAM_WEZ
-- @field WHEN_FLYING_NEAR_ENEMIES
--- @type AI.Option.Air.val.ECM_USING
---
-- @type AI.Option.Air.val.ECM_USING
-- @field NEVER_USE
-- @field USE_IF_ONLY_LOCK_BY_RADAR
-- @field USE_IF_DETECTED_LOCK_BY_RADAR
-- @field ALWAYS_USE
--- @type AI.Option.Air.val.MISSILE_ATTACK
---
-- @type AI.Option.Air.val.MISSILE_ATTACK
-- @field MAX_RANGE
-- @field NEZ_RANGE
-- @field HALF_WAY_RMAX_NEZ
-- @field TARGET_THREAT_EST
-- @field RANDOM_RANGE
--- @type AI.Option.Ground.id
---
-- @type AI.Option.Ground.id
-- @field NO_OPTION
-- @field ROE @{#AI.Option.Ground.val.ROE}
-- @field FORMATION
@ -1652,42 +1666,51 @@ do -- AI
-- @field ENGAGE_AIR_WEAPONS
-- @field AC_ENGAGEMENT_RANGE_RESTRICTION
--- @type AI.Option.Ground.mid -- Moose added
---
-- @type AI.Option.Ground.mid -- Moose added
-- @field RESTRICT_AAA_MIN 27
-- @field RESTRICT_AAA_MAX 29
-- @field RESTRICT_TARGETS @{#AI.Option.Ground.mval.ENGAGE_TARGETS} 28
--- @type AI.Option.Ground.val
---
-- @type AI.Option.Ground.val
-- @field #AI.Option.Ground.val.ROE ROE
-- @field #AI.Option.Ground.val.ALARM_STATE ALARM_STATE
-- @field #AI.Option.Ground.val.ENGAGE_TARGETS RESTRICT_TARGETS
--- @type AI.Option.Ground.val.ROE
---
-- @type AI.Option.Ground.val.ROE
-- @field OPEN_FIRE
-- @field RETURN_FIRE
-- @field WEAPON_HOLD
--- @type AI.Option.Ground.mval -- Moose added
---
-- @type AI.Option.Ground.mval -- Moose added
-- @field #AI.Option.Ground.mval.ENGAGE_TARGETS ENGAGE_TARGETS
--- @type AI.Option.Ground.mval.ENGAGE_TARGETS -- Moose added
---
-- @type AI.Option.Ground.mval.ENGAGE_TARGETS -- Moose added
-- @field ANY_TARGET -- 0
-- @field AIR_UNITS_ONLY -- 1
-- @field GROUND_UNITS_ONLY -- 2
--- @type AI.Option.Ground.val.ALARM_STATE
---
-- @type AI.Option.Ground.val.ALARM_STATE
-- @field AUTO
-- @field GREEN
-- @field RED
--- @type AI.Option.Naval.id
---
-- @type AI.Option.Naval.id
-- @field NO_OPTION
-- @field ROE
--- @type AI.Option.Naval.val
---
-- @type AI.Option.Naval.val
-- @field #AI.Option.Naval.val.ROE ROE
--- @type AI.Option.Naval.val.ROE
---
-- @type AI.Option.Naval.val.ROE
-- @field OPEN_FIRE
-- @field RETURN_FIRE
-- @field WEAPON_HOLD

View File

@ -3616,9 +3616,10 @@ function WAREHOUSE:onafterStatus(From, Event, To)
end
-- Print queue after processing requests.
if self.verbosity > 2 then
self:_PrintQueue(self.queue, "Queue waiting")
self:_PrintQueue(self.pending, "Queue pending")
end
-- Check fuel for all assets.
--self:_CheckFuel()
@ -8234,7 +8235,7 @@ end
-- @return #number Request ID.
function WAREHOUSE:_GetIDsFromGroupName(groupname)
---@param #string text The text to analyse.
-- @param #string text The text to analyse.
local function analyse(text)
-- Get rid of #0001 tail from spawn.

View File

@ -54,6 +54,8 @@
-- @field #string takeoffType Take of type.
-- @field #boolean despawnAfterLanding Aircraft are despawned after landing.
-- @field #boolean despawnAfterHolding Aircraft are despawned after holding.
-- @field #boolean capOptionPatrolRaceTrack Use closer patrol race track or standard orbit auftrag.
-- @field #number capFormation If capOptionPatrolRaceTrack is true, set the formation, also.
--
-- @extends Ops.Legion#LEGION
@ -128,6 +130,8 @@ AIRWING = {
pointsAWACS = {},
pointsRecon = {},
markpoints = false,
capOptionPatrolRaceTrack = false,
capFormation = nil,
}
--- Payload data.
@ -179,7 +183,7 @@ AIRWING = {
--- AIRWING class version.
-- @field #string version
AIRWING.version="0.9.3"
AIRWING.version="0.9.4"
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- ToDo list
@ -699,6 +703,24 @@ function AIRWING:SetNumberCAP(n)
return self
end
--- Set CAP flight formation.
-- @param #AIRWING self
-- @param #number Formation Formation to take, e.g. ENUMS.Formation.FixedWing.Trail.Close, also see [Hoggit Wiki](https://wiki.hoggitworld.com/view/DCS_option_formation).
-- @return #AIRWING self
function AIRWING:SetCAPFormation(Formation)
self.capFormation = Formation
return self
end
--- Set CAP close race track.We'll utilize the AUFTRAG PatrolRaceTrack instead of a standard race track orbit task.
-- @param #AIRWING self
-- @param #boolean OnOff If true, switch this on, else switch off. Off by default.
-- @return #AIRWING self
function AIRWING:SetCapCloseRaceTrack(OnOff)
self.capOptionPatrolRaceTrack = OnOff
return self
end
--- Set number of TANKER flights with Boom constantly in the air.
-- @param #AIRWING self
-- @param #number Nboom Number of flights. Default 1.
@ -1112,13 +1134,14 @@ end
-- @return #AIRWING self
function AIRWING:CheckCAP()
local Ncap=0 --self:CountMissionsInQueue({AUFTRAG.Type.GCICAP, AUFTRAG.Type.INTERCEPT})
local Ncap=0
-- Count CAP missions.
for _,_mission in pairs(self.missionqueue) do
local mission=_mission --Ops.Auftrag#AUFTRAG
if mission:IsNotOver() and mission.type==AUFTRAG.Type.GCICAP and mission.patroldata then
if mission:IsNotOver() and (mission.type==AUFTRAG.Type.GCICAP or mission.type == AUFTRAG.Type.PATROLRACETRACK) and mission.patroldata then
Ncap=Ncap+1
end
@ -1130,7 +1153,17 @@ function AIRWING:CheckCAP()
local altitude=patrol.altitude+1000*patrol.noccupied
local missionCAP=AUFTRAG:NewGCICAP(patrol.coord, altitude, patrol.speed, patrol.heading, patrol.leg)
local missionCAP = nil -- Ops.Auftrag#AUFTRAG
if self.capOptionPatrolRaceTrack then
missionCAP=AUFTRAG:NewPATROL_RACETRACK(patrol.coord,altitude,patrol.speed,patrol.heading,patrol.leg, self.capFormation)
else
missionCAP=AUFTRAG:NewGCICAP(patrol.coord, altitude, patrol.speed, patrol.heading, patrol.leg)
end
missionCAP.patroldata=patrol
@ -1150,7 +1183,7 @@ end
-- @return #AIRWING self
function AIRWING:CheckRECON()
local Ncap=0 --self:CountMissionsInQueue({AUFTRAG.Type.GCICAP, AUFTRAG.Type.INTERCEPT})
local Ncap=0
-- Count CAP missions.
for _,_mission in pairs(self.missionqueue) do
@ -1278,7 +1311,6 @@ function AIRWING:CheckAWACS()
end
for i=1,self.nflightsAWACS-N do
local patrol=self:_GetPatrolData(self.pointsAWACS)

View File

@ -443,6 +443,7 @@ _AUFTRAGSNR=0
-- @field #string REARMING Rearming mission.
-- @field #string CAPTUREZONE Capture zone mission.
-- @field #string NOTHING Nothing.
-- @field #string PATROLRACETRACK Patrol Racetrack.
AUFTRAG.Type={
ANTISHIP="Anti Ship",
AWACS="AWACS",
@ -484,10 +485,10 @@ AUFTRAG.Type={
RELOCATECOHORT="Relocate Cohort",
AIRDEFENSE="Air Defence",
EWR="Early Warning Radar",
--RECOVERYTANKER="Recovery Tanker",
REARMING="Rearming",
CAPTUREZONE="Capture Zone",
NOTHING="Nothing",
PATROLRACETRACK="Patrol Racetrack",
}
--- Special task description.
@ -511,6 +512,7 @@ AUFTRAG.Type={
-- @field #string REARMING Rearming.
-- @field #string CAPTUREZONE Capture OPS zone.
-- @field #string NOTHING Nothing.
-- @field #string PATROLRACETRACK Patrol Racetrack.
AUFTRAG.SpecialTask={
FORMATION="Formation",
PATROLZONE="PatrolZone",
@ -532,6 +534,7 @@ AUFTRAG.SpecialTask={
REARMING="Rearming",
CAPTUREZONE="Capture Zone",
NOTHING="Nothing",
PATROLRACETRACK="Patrol Racetrack",
}
--- Mission status.
@ -652,7 +655,7 @@ AUFTRAG.Category={
--- AUFTRAG class version.
-- @field #string version
AUFTRAG.version="1.2.0"
AUFTRAG.version="1.2.1"
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO list
@ -1017,7 +1020,7 @@ end
-- @param #number Altitude Hover altitude in feet AGL. Default is 50 feet above ground.
-- @param #number Time Time in seconds to hold the hover. Default 300 seconds.
-- @param #number Speed Speed in knots to fly to the target coordinate. Default 150kn.
-- @param #number MissionAlt Altitide to fly towards the mission in feet AGL. Default 1000ft.
-- @param #number MissionAlt Altitude to fly towards the mission in feet AGL. Default 1000ft.
-- @return #AUFTRAG self
function AUFTRAG:NewHOVER(Coordinate, Altitude, Time, Speed, MissionAlt)
@ -1049,6 +1052,58 @@ function AUFTRAG:NewHOVER(Coordinate, Altitude, Time, Speed, MissionAlt)
return mission
end
--- **[AIR]** Create an enhanced orbit race track mission. Planes will keep closer to the track.
-- @param #AUFTRAG self
-- @param Core.Point#COORDINATE Coordinate Where to start the race track.
-- @param #number Altitude (Optional) Altitude in feet. Defaults to 20,000ft ASL.
-- @param #number Speed (Optional) Speed in knots. Defaults to 300kn TAS.
-- @param #number Heading (Optional) Heading in degrees, 0 to 360. Defaults to 90 degree (East).
-- @param #number Leg (Optional) Leg of the race track in NM. Defaults to 10nm.
-- @param #number Formation (Optional) Formation to take, e.g. ENUMS.Formation.FixedWing.Trail.Close, also see [Hoggit Wiki](https://wiki.hoggitworld.com/view/DCS_option_formation).
-- @return #AUFTRAG self
function AUFTRAG:NewPATROL_RACETRACK(Coordinate,Altitude,Speed,Heading,Leg,Formation)
local mission = AUFTRAG:New(AUFTRAG.Type.PATROLRACETRACK)
-- Target.
mission:_TargetFromObject(Coordinate)
-- Set Altitude.
if Altitude then
mission.TrackAltitude=UTILS.FeetToMeters(Altitude)
else
mission.TrackAltitude=UTILS.FeetToMeters(20000)
end
-- Points
mission.TrackPoint1 = Coordinate
local leg = UTILS.NMToMeters(Leg) or UTILS.NMToMeters(10)
local heading = Heading or 90
if heading < 0 or heading > 360 then heading = 90 end
mission.TrackPoint2 = Coordinate:Translate(leg,heading,true)
-- Orbit speed in m/s TAS.
mission.TrackSpeed = UTILS.IasToTas(UTILS.KnotsToKmph(Speed or 300), mission.TrackAltitude)
-- Mission speed in km/h and altitude
mission.missionSpeed = UTILS.KnotsToKmph(Speed or 300)
mission.missionAltitude = mission.TrackAltitude * 0.9
mission.missionTask=ENUMS.MissionTask.CAP
mission.optionROE=ENUMS.ROE.ReturnFire
mission.optionROT=ENUMS.ROT.PassiveDefense
mission.categories={AUFTRAG.Category.AIRCRAFT}
mission.DCStask=mission:GetDCSMissionTask()
return mission
end
--- **[AIR]** Create an ORBIT mission, which can be either a circular orbit or a race-track pattern.
-- @param #AUFTRAG self
-- @param Core.Point#COORDINATE Coordinate Where to orbit.
@ -1181,7 +1236,7 @@ function AUFTRAG:NewORBIT_GROUP(Group, Altitude, Speed, Leg, Heading, OffsetVec2
end
--- **[AIR]** Create a Ground Controlled CAP (GCICAP) mission. Flights with this task are considered for A2A INTERCEPT missions by the CHIEF class. They will perform a compat air patrol but not engage by
--- **[AIR]** Create a Ground Controlled CAP (GCICAP) mission. Flights with this task are considered for A2A INTERCEPT missions by the CHIEF class. They will perform a combat air patrol but not engage by
-- themselfs. They wait for the CHIEF to tell them whom to engage.
-- @param #AUFTRAG self
-- @param Core.Point#COORDINATE Coordinate Where to orbit.
@ -2688,6 +2743,8 @@ function AUFTRAG:NewAUTO(EngageGroup)
mission=AUFTRAG:NewTANKER(Coordinate,Altitude,Speed,Heading,Leg,RefuelSystem)
elseif auftrag==AUFTRAG.Type.TROOPTRANSPORT then
mission=AUFTRAG:NewTROOPTRANSPORT(TransportGroupSet,DropoffCoordinate,PickupCoordinate)
elseif auftrag==AUFTRAG.Type.PATROLRACETRACK then
mission=AUFTRAG:NewPATROL_RACETRACK(Coordinate,Altitude,Speed,Heading,Leg,Formation)
else
end
@ -6345,6 +6402,30 @@ function AUFTRAG:GetDCSMissionTask()
table.insert(DCStasks, DCStask)
elseif self.type==AUFTRAG.Type.PATROLRACETRACK then
---------------------
-- Enhanced Orbit Racetrack --
---------------------
local DCStask={}
DCStask.id=AUFTRAG.SpecialTask.PATROLRACETRACK
local param={}
-- ONTROLLABLE:PatrolRaceTrack(Point1, Point2, Altitude, Speed, Formation, Delay)
param.TrackAltitude = self.TrackAltitude
param.TrackSpeed = self.TrackSpeed
param.TrackPoint1 = self.TrackPoint1
param.TrackPoint2 = self.TrackPoint2
param.missionSpeed = self.missionSpeed
param.missionAltitude = self.missionAltitude
param.TrackFormation = self.TrackFormation
DCStask.params=param
table.insert(DCStasks, DCStask)
elseif self.type==AUFTRAG.Type.HOVER then
---------------------
@ -6619,6 +6700,8 @@ function AUFTRAG:GetMissionTaskforMissionType(MissionType)
mtask=ENUMS.MissionTask.NOTHING
elseif MissionType==AUFTRAG.Type.HOVER then
mtask=ENUMS.MissionTask.NOTHING
elseif MissionType==AUFTRAG.Type.PATROLRACETRACK then
mtask=ENUMS.MissionTask.CAP
end
return mtask

View File

@ -75,7 +75,7 @@ COHORT = {
livery = nil,
skill = nil,
legion = nil,
Ngroups = nil,
--Ngroups = nil,
Ngroups = 0,
engageRange = nil,
tacanChannel = {},
@ -1098,7 +1098,7 @@ function COHORT:RecruitAssets(MissionType, Npayloads)
-- Assets on mission NOTHING are considered.
table.insert(assets, asset)
elseif self.legion:IsAssetOnMission(asset, AUFTRAG.Type.GCICAP) and MissionType==AUFTRAG.Type.INTERCEPT then
elseif self.legion:IsAssetOnMission(asset, {AUFTRAG.Type.GCICAP, AUFTRAG.Type.PATROLRACETRACK}) and MissionType==AUFTRAG.Type.INTERCEPT then
-- Check if the payload of this asset is compatible with the mission.
-- Note: we do not check the payload as an asset that is on a GCICAP mission should be able to do an INTERCEPT as well!
@ -1595,4 +1595,3 @@ end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

View File

@ -64,6 +64,7 @@
-- @field Core.Set#SET_ZONE NoGoZoneSet
-- @field #boolean Monitor
-- @field #boolean TankerInvisible
-- @field #number CapFormation
-- @extends Core.Fsm#FSM
--- *“Airspeed, altitude, and brains. Two are always needed to successfully complete the flight.”* -- Unknown.
@ -207,6 +208,7 @@ EASYGCICAP = {
NoGoZoneSet = nil,
Monitor = false,
TankerInvisible = true,
CapFormation = nil,
}
--- Internal Squadron data type
@ -242,7 +244,7 @@ EASYGCICAP = {
--- EASYGCICAP class version.
-- @field #string version
EASYGCICAP.version="0.0.8"
EASYGCICAP.version="0.0.9"
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO list
@ -289,6 +291,7 @@ function EASYGCICAP:New(Alias, AirbaseName, Coalition, EWRName)
self.repeatsonfailure = 3
self.Monitor = false
self.TankerInvisible = true
self.CapFormation = ENUMS.Formation.FixedWing.FingerFour.Group
-- Set some string id for output to DCS.log file.
self.lid=string.format("EASYGCICAP %s | ", self.alias)
@ -313,6 +316,14 @@ end
-- Functions
-------------------------------------------------------------------------
--- Set CAP formation.
-- @param #EASYGCICAP self
-- @param #number Formation Formation to fly, defaults to ENUMS.Formation.FixedWing.FingerFour.Group
-- @return #EASYGCICAP self
function EASYGCICAP:SetCAPFormation(Formation)
self.CapFormation = Formation
return self
end
--- Set Tanker and AWACS to be invisible to enemy AI eyes
-- @param #EASYGCICAP self
@ -476,6 +487,8 @@ end
function EASYGCICAP:_AddAirwing(Airbasename, Alias)
self:T(self.lid.."_AddAirwing "..Airbasename)
local CapFormation = self.CapFormation
-- Create Airwing
local CAP_Wing = AIRWING:New(Airbasename,Alias)
CAP_Wing:SetVerbosityLevel(3)
@ -484,11 +497,15 @@ function EASYGCICAP:_AddAirwing(Airbasename, Alias)
CAP_Wing:SetAirbase(AIRBASE:FindByName(Airbasename))
CAP_Wing:SetRespawnAfterDestroyed()
CAP_Wing:SetNumberCAP(self.capgrouping)
CAP_Wing:SetCapCloseRaceTrack(true)
if CapFormation then
CAP_Wing:SetCAPFormation(CapFormation)
end
if #self.ManagedTK > 0 then
CAP_Wing:SetNumberTankerBoom(1)
CAP_Wing:SetNumberTankerProbe(1)
end
if #self.ManagedAW > 0 then
if #self.ManagedEWR > 0 then
CAP_Wing:SetNumberAWACS(1)
end
if #self.ManagedREC > 0 then
@ -515,6 +532,9 @@ function EASYGCICAP:_AddAirwing(Airbasename, Alias)
flightgroup:SetDetection(true)
flightgroup:SetEngageDetectedOn(self.engagerange,{"Air"},self.GoZoneSet,self.NoGoZoneSet)
flightgroup:SetOutOfAAMRTB()
if CapFormation then
flightgroup:GetGroup():SetOption(AI.Option.Air.id.FORMATION,CapFormation)
end
end
if Mission.type == AUFTRAG.Type.TANKER or Mission.type == AUFTRAG.Type.AWACS or Mission.type == AUFTRAG.Type.RECON then
if TankerInvisible then
@ -549,8 +569,8 @@ end
-- @param #EASYGCICAP self
-- @param #string AirbaseName Name of the Wing's airbase
-- @param Core.Point#COORDINATE Coordinate.
-- @param #number Altitude Defaults to 25000 feet.
-- @param #number Speed Defaults to 300 knots.
-- @param #number Altitude Defaults to 25000 feet ASL.
-- @param #number Speed Defaults to 300 knots TAS.
-- @param #number Heading Defaults to 90 degrees (East).
-- @param #number LegLength Defaults to 15 NM.
-- @return #EASYGCICAP self
@ -888,7 +908,7 @@ function EASYGCICAP:_AddSquadron(TemplateName, SquadName, AirbaseName, AirFrames
self:T(self.lid.."_AddSquadron "..SquadName)
-- Add Squadrons
local Squadron_One = SQUADRON:New(TemplateName,AirFrames,SquadName)
Squadron_One:AddMissionCapability({AUFTRAG.Type.CAP, AUFTRAG.Type.GCICAP, AUFTRAG.Type.INTERCEPT, AUFTRAG.Type.ALERT5})
Squadron_One:AddMissionCapability({AUFTRAG.Type.CAP, AUFTRAG.Type.GCICAP, AUFTRAG.Type.INTERCEPT, AUFTRAG.Type.PATROLRACETRACK, AUFTRAG.Type.ALERT5})
--Squadron_One:SetFuelLowRefuel(true)
Squadron_One:SetFuelLowThreshold(0.3)
Squadron_One:SetTurnoverTime(10,20)
@ -900,7 +920,7 @@ function EASYGCICAP:_AddSquadron(TemplateName, SquadName, AirbaseName, AirFrames
local wing = self.wings[AirbaseName][1] -- Ops.AirWing#AIRWING
wing:AddSquadron(Squadron_One)
wing:NewPayload(TemplateName,-1,{AUFTRAG.Type.CAP, AUFTRAG.Type.GCICAP, AUFTRAG.Type.INTERCEPT, AUFTRAG.Type.ALERT5},75)
wing:NewPayload(TemplateName,-1,{AUFTRAG.Type.CAP, AUFTRAG.Type.GCICAP, AUFTRAG.Type.INTERCEPT, AUFTRAG.Type.PATROLRACETRACK, AUFTRAG.Type.ALERT5},75)
return self
end
@ -1234,12 +1254,16 @@ function EASYGCICAP:onafterStatus(From,Event,To)
local capmission = 0
local interceptmission = 0
local reconmission = 0
local awacsmission = 0
local tankermission = 0
for _,_wing in pairs(self.wings) do
local count = _wing[1]:CountAssetsOnMission(MissionTypes,Cohort)
local count2 = _wing[1]:CountAssets(true,MissionTypes,Attributes)
capmission = capmission + _wing[1]:CountMissionsInQueue({AUFTRAG.Type.GCICAP})
capmission = capmission + _wing[1]:CountMissionsInQueue({AUFTRAG.Type.GCICAP,AUFTRAG.Type.PATROLRACETRACK})
interceptmission = interceptmission + _wing[1]:CountMissionsInQueue({AUFTRAG.Type.INTERCEPT})
reconmission = reconmission + _wing[1]:CountMissionsInQueue({AUFTRAG.Type.RECON})
awacsmission = awacsmission + _wing[1]:CountMissionsInQueue({AUFTRAG.Type.AWACS})
tankermission = tankermission + _wing[1]:CountMissionsInQueue({AUFTRAG.Type.TANKER})
assets = assets + count
instock = instock + count2
end
@ -1251,6 +1275,8 @@ function EASYGCICAP:onafterStatus(From,Event,To)
text = text.."\nMissions: "..capmission+interceptmission
text = text.."\n - CAP: "..capmission
text = text.."\n - Intercept: "..interceptmission
text = text.."\n - AWACS: "..awacsmission
text = text.."\n - TANKER: "..tankermission
text = text.."\n - Recon: "..reconmission
MESSAGE:New(text,15,"GCICAP"):ToAll():ToLogIf(self.debug)
end

View File

@ -4,7 +4,7 @@
--
-- * Manage aircraft departure and arrival
-- * Handles AI and human players
-- * Limit number of AI groups taxiing, taking off and landing simultaniously
-- * Limit number of AI groups taxiing, taking off and landing simultaneously
-- * Immersive voice overs via SRS text-to-speech
-- * Define holding patterns for airdromes
--
@ -61,6 +61,7 @@
-- @field #number runwaydestroyed Time stamp (abs), when runway was destroyed. If `nil`, runway is operational.
-- @field #number runwayrepairtime Time in seconds until runway will be repaired after it was destroyed. Default is 3600 sec (one hour).
-- @field #boolean markerParking If `true`, occupied parking spots are marked.
-- @field #boolean nosubs If `true`, SRS TTS is without subtitles.
-- @extends Core.Fsm#FSM
--- **Ground Control**: Airliner X, Good news, you are clear to taxi to the active.
@ -122,7 +123,7 @@
-- * `Length` is the length of the pattern.
-- * `FlightLevelMin` is the lowest altitude at which aircraft can hold.
-- * `FlightLevelMax` is the highest altitude at which aircraft can hold.
-- * `Prio` is the priority of this holdig stacks. If multiple patterns are defined, patterns with higher prio will be filled first.
-- * `Prio` is the priority of this holding stacks. If multiple patterns are defined, patterns with higher prio will be filled first.
--
-- # Parking Guard
--
@ -137,13 +138,13 @@
--
-- # Limits for Inbound and Outbound Flights
--
-- You can define limits on how many aircraft are simultaniously landing and taking off. This avoids (DCS) problems where taxiing aircraft cause a "traffic jam" on the taxi way(s)
-- You can define limits on how many aircraft are simultaneously landing and taking off. This avoids (DCS) problems where taxiing aircraft cause a "traffic jam" on the taxi way(s)
-- and bring the whole airbase effectively to a stand still.
--
-- ## Landing Limits
--
-- The number of groups getting landing clearance can be set with the @{#FLIGHTCONTROL.SetLimitLanding}(*Nlanding, Ntakeoff*) function.
-- The first parameter, `Nlanding`, defines how many groups get clearance simultaniously.
-- The first parameter, `Nlanding`, defines how many groups get clearance simultaneously.
--
-- The second parameter, `Ntakeoff`, sets a limit on how many flights can take off whilst inbound flights still get clearance. By default, this is set to zero because the runway can only be used for takeoff *or*
-- landing. So if you have a flight taking off, inbound fights will have to wait until the runway is clear.
@ -155,7 +156,7 @@
-- ## Taxiing/Takeoff Limits
--
-- The number of AI flight groups getting clearance to taxi to the runway can be set with the @{#FLIGHTCONTROL.SetLimitTaxi}(*Nlanding, Ntakeoff*) function.
-- The first parameter, `Ntaxi`, defines how many groups are allowed to taxi to the runway simultaniously. Note that once the AI starts to taxi, we loose complete control over it.
-- The first parameter, `Ntaxi`, defines how many groups are allowed to taxi to the runway simultaneously. Note that once the AI starts to taxi, we loose complete control over it.
-- They will follow their internal logic to get the the runway and take off. Therefore, giving clearance to taxi is equivalent to giving them clearance for takeoff.
--
-- By default, the parameter only counts the number of flights taxiing *to* the runway. If you set the second parameter, `IncludeInbound`, to `true`, this will also count the flights
@ -237,9 +238,9 @@
-- atcNellis:SetParkingGuardStatic("Static Generator F Template")
-- -- Set taxi speed limit to 25 knots.
-- atcNellis:SetSpeedLimitTaxi(25)
-- -- Set that max 3 groups are allowed to taxi simultaniously.
-- -- Set that max 3 groups are allowed to taxi simultaneously.
-- atcNellis:SetLimitTaxi(3, false, 1)
-- -- Set that max 2 groups are allowd to land simultaniously and unlimited number (99) groups can land, while other groups are taking off.
-- -- Set that max 2 groups are allowd to land simultaneously and unlimited number (99) groups can land, while other groups are taking off.
-- atcNellis:SetLimitLanding(2, 99)
-- -- Use Google for text-to-speech.
-- atcNellis:SetSRSTower(nil, nil, "en-AU-Standard-A", nil, nil, "D:\\Path To Google\\GoogleCredentials.json")
@ -270,6 +271,7 @@ FLIGHTCONTROL = {
Nparkingspots = nil,
holdingpatterns = {},
hpcounter = 0,
nosubs = false,
}
--- Holding point. Contains holding stacks.
@ -327,7 +329,7 @@ FLIGHTCONTROL.FlightStatus={
--- FlightControl class version.
-- @field #string version
FLIGHTCONTROL.version="0.7.3"
FLIGHTCONTROL.version="0.7.4"
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO list
@ -407,6 +409,7 @@ function FLIGHTCONTROL:New(AirbaseName, Frequency, Modulation, PathToSRS, Port,
self:SetFrequency(Frequency, Modulation)
self:SetMarkHoldingPattern(true)
self:SetRunwayRepairtime()
self.nosubs = false
-- Set SRS Port
self:SetSRSPort(Port or 5002)
@ -556,6 +559,22 @@ function FLIGHTCONTROL:SetVerbosity(VerbosityLevel)
return self
end
--- Set subtitles to appear on SRS TTS messages.
-- @param #FLIGHTCONTROL self
-- @return #FLIGHTCONTROL self
function FLIGHTCONTROL:SwitchSubtitlesOn()
self.nosubs = false
return self
end
--- Set subtitles to appear on SRS TTS messages.
-- @param #FLIGHTCONTROL self
-- @return #FLIGHTCONTROL self
function FLIGHTCONTROL:SwitchSubtitlesOff()
self.nosubs = true
return self
end
--- Set the tower frequency.
-- @param #FLIGHTCONTROL self
-- @param #number Frequency Frequency in MHz. Default 305 MHz.
@ -595,7 +614,7 @@ end
-- @param #string Culture Culture, e.g. "en-GB" (default).
-- @param #string Voice Specific voice. Overrides `Gender` and `Culture`.
-- @param #number Volume Volume. Default 1.0.
-- @param #string Label Name under which SRS transmitts.
-- @param #string Label Name under which SRS transmits.
-- @param #string PathToGoogleCredentials Path to google credentials json file.
-- @param #number Port Server port for SRS
-- @return #FLIGHTCONTROL self
@ -626,7 +645,7 @@ end
-- @param #string Culture Culture, e.g. "en-GB" (default).
-- @param #string Voice Specific voice. Overrides `Gender` and `Culture`. See [Google Voices](https://cloud.google.com/text-to-speech/docs/voices).
-- @param #number Volume Volume. Default 1.0.
-- @param #string Label Name under which SRS transmitts. Default `self.alias`.
-- @param #string Label Name under which SRS transmits. Default `self.alias`.
-- @param #string PathToGoogleCredentials Path to google credentials json file.
-- @return #FLIGHTCONTROL self
function FLIGHTCONTROL:SetSRSTower(Gender, Culture, Voice, Volume, Label, PathToGoogleCredentials)
@ -644,7 +663,7 @@ end
-- @param #string Culture Culture, e.g. "en-US" (default).
-- @param #string Voice Specific voice. Overrides `Gender` and `Culture`.
-- @param #number Volume Volume. Default 1.0.
-- @param #string Label Name under which SRS transmitts. Default "Pilot".
-- @param #string Label Name under which SRS transmits. Default "Pilot".
-- @param #string PathToGoogleCredentials Path to google credentials json file.
-- @return #FLIGHTCONTROL self
function FLIGHTCONTROL:SetSRSPilot(Gender, Culture, Voice, Volume, Label, PathToGoogleCredentials)
@ -657,17 +676,17 @@ function FLIGHTCONTROL:SetSRSPilot(Gender, Culture, Voice, Volume, Label, PathTo
end
--- Set the number of aircraft groups, that are allowed to land simultaniously.
--- Set the number of aircraft groups, that are allowed to land simultaneously.
-- Note that this restricts AI and human players.
--
-- By default, up to two groups get landing clearance. They are spaced out in time, i.e. after the first one got cleared, the second has to wait a bit.
-- This
--
-- By default, landing clearance is only given when **no** other flight is taking off. You can adjust this for airports with more than one runway or
-- in cases where simulatious takeoffs and landings are unproblematic. Note that only because there are multiple runways, it does not mean the AI uses them.
-- in cases where simultaneous takeoffs and landings are unproblematic. Note that only because there are multiple runways, it does not mean the AI uses them.
--
-- @param #FLIGHTCONTROL self
-- @param #number Nlanding Max number of aircraft landing simultaniously. Default 2.
-- @param #number Nlanding Max number of aircraft landing simultaneously. Default 2.
-- @param #number Ntakeoff Allowed number of aircraft taking off for groups to get landing clearance. Default 0.
-- @return #FLIGHTCONTROL self
function FLIGHTCONTROL:SetLimitLanding(Nlanding, Ntakeoff)
@ -691,7 +710,7 @@ function FLIGHTCONTROL:SetLandingInterval(dt)
end
--- Set the number of **AI** aircraft groups, that are allowed to taxi simultaniously.
--- Set the number of **AI** aircraft groups, that are allowed to taxi simultaneously.
-- If the limit is reached, other AI groups not get taxi clearance to taxi to the runway.
--
-- By default, this only counts the number of AI that taxi from their parking position to the runway.
@ -887,7 +906,7 @@ end
-- Note that this is the time, the DCS engine uses not something we can control on a user level or we could get via scripting.
-- You need to input the value. On the DCS forum it was stated that this is currently one hour. Hence this is the default value.
-- @param #FLIGHTCONTROL self
-- @param #number RepairTime Time in seconds until the runway is repaired. Default 3600 sec (one hour).
-- @param #number RepairTime Time in seconds until the runway is repaired. Default 3600sec (one hour).
-- @return #FLIGHTCONTROL self
function FLIGHTCONTROL:SetRunwayRepairtime(RepairTime)
self.runwayrepairtime=RepairTime or 3600
@ -1010,7 +1029,7 @@ function FLIGHTCONTROL:onbeforeStatusUpdate()
if Tqueue>0 then
-- Debug info.
local text=string.format("Still got %d messages in the radio queue. Will call status again in %.1f sec", #self.msrsqueue, Tqueue)
self:I(self.lid..text)
self:T(self.lid..text)
-- Call status again in dt seconds.
self:__StatusUpdate(-Tqueue)
@ -2753,9 +2772,10 @@ function FLIGHTCONTROL:_PlayerInfoATIS(groupname)
if flight then
local text=string.format("Airbase %s ATIS:", self.airbasename)
local srstxt = string.format("Airbase %s ", self.airbasename)
if self.atis then
text=text..string.format("\nATIS %.3f MHz %s", self.atis.frequency, UTILS.GetModulationName(self.atis.modulation))
srstxt=srstxt..string.format("ATIS %.3f Megahertz %s", self.atis.frequency, UTILS.GetModulationName(self.atis.modulation))
if self.atis.towerfrequency then
local tower=""
for _,freq in pairs(self.atis.towerfrequency) do
@ -2779,7 +2799,17 @@ function FLIGHTCONTROL:_PlayerInfoATIS(groupname)
end
-- Message to flight
self:TextMessageToFlight(text, flight, 10, true)
--self:TextMessageToFlight(text, flight, 10, true)
-- Call sign.
local callsign=self:_GetCallsignName(flight)
-- Pilot calls inbound for landing.
local rtext=string.format("%s, %s, request ATIS frequency.", self.alias, callsign)
-- Radio message.
self:TransmissionPilot(rtext, flight)
self:TransmissionTower(srstxt,flight,10)
else
self:E(self.lid..string.format("Cannot find flight group %s.", tostring(groupname)))
@ -3390,7 +3420,7 @@ function FLIGHTCONTROL:_PlayerRequestDirectLanding(groupname)
if nTakeoff>self.NlandingTakeoff then
-- Message text.
local text=string.format("%s, negative! We have currently traffic taking off", callsign)
local text=string.format("%s, negative! We have currently traffic taking off!", callsign)
-- Send message.
self:TransmissionTower(text, flight, 10)
@ -3854,7 +3884,7 @@ function FLIGHTCONTROL:_PlayerArrived(groupname)
else
-- Message text.
local text=string.format("%s, %s, arrived at parking position", self.alias, callsign)
local text=string.format("%s, %s, arrived at parking position.", self.alias, callsign)
-- Transmit message.
self:TransmissionPilot(text, flight)
@ -4277,7 +4307,7 @@ function FLIGHTCONTROL:TransmissionTower(Text, Flight, Delay)
local subgroups=nil
if Flight and not Flight.isAI then
local playerData=Flight:_GetPlayerData()
if playerData.subtitles then
if playerData.subtitles and (not self.nosubs) then
subgroups=subgroups or {}
table.insert(subgroups, Flight.group)
end
@ -4324,7 +4354,7 @@ function FLIGHTCONTROL:TransmissionPilot(Text, Flight, Delay)
local subgroups=nil
if Flight and not Flight.isAI then
local playerData=Flight:_GetPlayerData()
if playerData.subtitles then
if playerData.subtitles and (not self.nosubs) then
subgroups=subgroups or {}
table.insert(subgroups, Flight.group)
end

View File

@ -2605,6 +2605,9 @@ function FLIGHTGROUP:onbeforeUpdateRoute(From, Event, To, n, N)
elseif task.dcstask.id==AUFTRAG.SpecialTask.RECON then
-- For recon missions, we need to allow the update as we insert new waypoints.
self:T2(self.lid.."Allowing update route for Task: ReconMission")
elseif task.dcstask.id==AUFTRAG.SpecialTask.PATROLRACETRACK then
-- For recon missions, we need to allow the update as we insert new waypoints.
self:T2(self.lid.."Allowing update route for Task: Patrol Race Track")
elseif task.dcstask.id==AUFTRAG.SpecialTask.HOVER then
-- For recon missions, we need to allow the update as we insert new waypoints.
self:T2(self.lid.."Allowing update route for Task: Hover")

View File

@ -965,7 +965,7 @@ function LEGION:onafterMissionRequest(From, Event, To, Mission, Assets)
local pause=false
-- Check if mission is INTERCEPT and asset is currently on GCI mission. If so, GCI is paused.
if currM.type==AUFTRAG.Type.GCICAP and Mission.type==AUFTRAG.Type.INTERCEPT then
if (currM.type==AUFTRAG.Type.GCICAP or currM.type==AUFTRAG.Type.PATROLRACETRACK) and Mission.type==AUFTRAG.Type.INTERCEPT then
pause=true
elseif (currM.type==AUFTRAG.Type.ONGUARD or currM.type==AUFTRAG.Type.PATROLZONE) and (Mission.type==AUFTRAG.Type.ARTY or Mission.type==AUFTRAG.Type.GROUNDATTACK) then
pause=true
@ -1445,7 +1445,7 @@ end
-- @param Functional.Warehouse#WAREHOUSE.Assetitem Asset The asset that returned.
function LEGION:onafterLegionAssetReturned(From, Event, To, Cohort, Asset)
-- Debug message.
self:I(self.lid..string.format("Asset %s from Cohort %s returned! asset.assignment=\"%s\"", Asset.spawngroupname, Cohort.name, tostring(Asset.assignment)))
self:T(self.lid..string.format("Asset %s from Cohort %s returned! asset.assignment=\"%s\"", Asset.spawngroupname, Cohort.name, tostring(Asset.assignment)))
-- Stop flightgroup.
if Asset.flightgroup and not Asset.flightgroup:IsStopped() then
@ -2560,6 +2560,7 @@ function LEGION._CohortCan(Cohort, MissionType, Categories, Attributes, Properti
-- Is in range?
local Rmax=cohort:GetMissionRange(WeaponTypes)
local RangeMax = RangeMax or 0
local InRange=(RangeMax and math.max(RangeMax, Rmax) or Rmax) >= TargetDistance
return InRange
@ -2610,6 +2611,7 @@ function LEGION._CohortCan(Cohort, MissionType, Categories, Attributes, Properti
-- Is capable of the mission type?
local can=AUFTRAG.CheckMissionCapability(MissionType, Cohort.missiontypes)
if can then
can=CheckCategory(Cohort)
else
@ -2687,7 +2689,7 @@ function LEGION._CohortCan(Cohort, MissionType, Categories, Attributes, Properti
return nil
end
--- Recruit assets from Cohorts for the given parameters. **NOTE** that we set the `asset.isReserved=true` flag so it cant be recruited by anyone else.
--- Recruit assets from Cohorts for the given parameters. **NOTE** that we set the `asset.isReserved=true` flag so it cannot be recruited by anyone else.
-- @param #table Cohorts Cohorts included.
-- @param #string MissionTypeRecruit Mission type for recruiting the cohort assets.
-- @param #string MissionTypeOpt Mission type for which the assets are optimized. Default is the same as `MissionTypeRecruit`.
@ -3181,7 +3183,7 @@ function LEGION.CalculateAssetMissionScore(asset, MissionType, TargetVec2, Inclu
if currmission.type==AUFTRAG.Type.ALERT5 and currmission.alert5MissionType==MissionType then
-- Prefer assets that are on ALERT5 for this mission type.
score=score+25
elseif currmission.type==AUFTRAG.Type.GCICAP and MissionType==AUFTRAG.Type.INTERCEPT then
elseif (currmission.type==AUFTRAG.Type.GCICAP or currmission.type==AUFTRAG.Type.PATROLRACETRACK) and MissionType==AUFTRAG.Type.INTERCEPT then
-- Prefer assets that are on GCICAP to perform INTERCEPTS. We set this even higher than alert5 because they are already in the air.
score=score+35
elseif (currmission.type==AUFTRAG.Type.ONGUARD or currmission.type==AUFTRAG.Type.PATROLZONE) and (MissionType==AUFTRAG.Type.ARTY or MissionType==AUFTRAG.Type.GROUNDATTACK) then

View File

@ -4468,6 +4468,26 @@ function OPSGROUP:_UpdateTask(Task, Mission)
self:EngageTarget(target, speed, Task.dcstask.params.formation)
end
elseif Task.dcstask.id==AUFTRAG.SpecialTask.PATROLRACETRACK then
---
-- Task "Patrol Race Track" Mission.
---
if self.isFlightgroup then
self:T("We are Special Auftrag Patrol Race Track, starting now ...")
--self:I({Task.dcstask.params})
--[[
Task.dcstask.params.TrackAltitude = self.TrackAltitude
Task.dcstask.params.TrackSpeed = self.TrackSpeed
Task.dcstask.params.TrackPoint1 = self.TrackPoint1
Task.dcstask.params.TrackPoint2 = self.TrackPoint2
Task.dcstask.params.TrackFormation = self.TrackFormation
--]]
local aircraft = self:GetGroup()
aircraft:PatrolRaceTrack(Task.dcstask.params.TrackPoint1,Task.dcstask.params.TrackPoint2,Task.dcstask.params.TrackAltitude,Task.dcstask.params.TrackSpeed,Task.dcstask.params.TrackFormation,false,1)
end
elseif Task.dcstask.id==AUFTRAG.SpecialTask.HOVER then
---

View File

@ -21,7 +21,7 @@
-- ===
-- @module Ops.PlayerTask
-- @image OPS_PlayerTask.jpg
-- @date Last Update Sept 2023
-- @date Last Update Oct 2023
do
@ -98,7 +98,7 @@ PLAYERTASK = {
--- PLAYERTASK class version.
-- @field #string version
PLAYERTASK.version="0.1.20"
PLAYERTASK.version="0.1.21"
--- Generic task condition.
-- @type PLAYERTASK.Condition
@ -470,10 +470,11 @@ end
--- [User] Remove a client from this task
-- @param #PLAYERTASK self
-- @param Wrapper.Client#CLIENT Client
-- @param #string Name Name of the client
-- @return #PLAYERTASK self
function PLAYERTASK:RemoveClient(Client)
function PLAYERTASK:RemoveClient(Client,Name)
self:T(self.lid.."RemoveClient")
local name = Client:GetPlayerName()
local name = Name or Client:GetPlayerName()
if self.Clients:HasUniqueID(name) then
self.Clients:PullByID(name)
if self.verbose then
@ -1551,7 +1552,7 @@ PLAYERTASKCONTROLLER.Messages = {
--- PLAYERTASK class version.
-- @field #string version
PLAYERTASKCONTROLLER.version="0.1.61"
PLAYERTASKCONTROLLER.version="0.1.62"
--- Create and run a new TASKCONTROLLER instance.
-- @param #PLAYERTASKCONTROLLER self
@ -2186,6 +2187,10 @@ function PLAYERTASKCONTROLLER:_EventHandler(EventData)
task:RemoveClient(Client)
--text = "Task aborted!"
text = self.gettext:GetEntry("TASKABORT",self.locale)
else
task:RemoveClient(nil,EventData.IniPlayerName)
--text = "Task aborted!"
text = self.gettext:GetEntry("TASKABORT",self.locale)
end
else
--text = "No active task!"

View File

@ -5329,3 +5329,54 @@ function CONTROLLABLE:TaskAerobaticsBarrelRoll(TaskAerobatics,Repeats,InitAltitu
return TaskAerobatics
end
--- [Air] Make an airplane or helicopter patrol between two points in a racetrack - resulting in a much tighter track around the start and end points.
-- @param #CONTROLLABLE self
-- @param Core.Point#COORDINATE Point1 Start point.
-- @param Core.Point#COORDINATE Point2 End point.
-- @param #number Altitude (Optional) Altitude in meters. Defaults to the altitude of the coordinate.
-- @param #number Speed (Optional) Speed in kph. Defaults to 500 kph.
-- @param #number Formation (Optional) Formation to take, e.g. ENUMS.Formation.FixedWing.Trail.Close, also see [Hoggit Wiki](https://wiki.hoggitworld.com/view/DCS_option_formation).
-- @param #boolean AGL (Optional) If true, set altitude to above ground level (AGL), not above sea level (ASL).
-- @param #number Delay (Optional) Set the task after delay seconds only.
-- @return #CONTROLLABLE self
function CONTROLLABLE:PatrolRaceTrack(Point1, Point2, Altitude, Speed, Formation, AGL, Delay)
local PatrolGroup = self -- Wrapper.Group#GROUP
if not self:IsInstanceOf( "GROUP" ) then
PatrolGroup = self:GetGroup() -- Wrapper.Group#GROUP
end
local delay = Delay or 1
self:F( { PatrolGroup = PatrolGroup:GetName() } )
if PatrolGroup:IsAir() then
if Formation then
PatrolGroup:SetOption(AI.Option.Air.id.FORMATION,Formation) -- https://wiki.hoggitworld.com/view/DCS_option_formation
end
local FromCoord = PatrolGroup:GetCoordinate()
local ToCoord = Point1:GetCoordinate()
-- Calculate the new Route
if Altitude then
local asl = true
if AGL then asl = false end
FromCoord:SetAltitude(Altitude, asl)
ToCoord:SetAltitude(Altitude, asl)
end
-- Create a "air waypoint", which is a "point" structure that can be given as a parameter to a Task
local Route = {}
Route[#Route + 1] = FromCoord:WaypointAir( AltType, COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, Speed, true, nil, DCSTasks, description, timeReFuAr )
Route[#Route + 1] = ToCoord:WaypointAir( AltType, COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, Speed, true, nil, DCSTasks, description, timeReFuAr )
local TaskRouteToZone = PatrolGroup:TaskFunction( "CONTROLLABLE.PatrolRaceTrack", Point2, Point1, Altitude, Speed, Formation, Delay )
PatrolGroup:SetTaskWaypoint( Route[#Route], TaskRouteToZone ) -- Set for the given Route at Waypoint 2 the TaskRouteToZone.
PatrolGroup:Route( Route, Delay ) -- Move after delay seconds to the Route. See the Route method for details.
end
return self
end

View File

@ -20,8 +20,8 @@
-- @module Wrapper.Unit
-- @image Wrapper_Unit.JPG
--- @type UNIT
---
-- @type UNIT
-- @field #string ClassName Name of the class.
-- @field #string UnitName Name of the unit.
-- @field #string GroupName Name of the group the unit belongs to.
@ -561,7 +561,7 @@ end
--- Check if the unit is a tanker. Also retrieves the refuelling system (boom or probe) if applicable.
-- @param #UNIT self
-- @return #boolean If true, unit is refuelable (checks for the attribute "Refuelable").
-- @return #boolean If true, unit is a tanker (checks for the attribute "Tankers").
-- @return #number Refueling system (if any): 0=boom, 1=probe.
function UNIT:IsTanker()
self:F2( self.UnitName )
@ -582,7 +582,7 @@ function UNIT:IsTanker()
-- Some hard coded data as this is not in the descriptors...
if typename=="IL-78M" then
system=1 --probe
elseif typename=="KC130" then
elseif typename=="KC130" or typename=="KC130J" then
system=1 --probe
elseif typename=="KC135BDA" then
system=1 --probe
@ -590,6 +590,10 @@ function UNIT:IsTanker()
system=1 --probe
elseif typename=="S-3B Tanker" then
system=1 --probe
elseif typename=="KC_10_Extender" then
system=1 --probe
elseif typename=="KC_10_Extender_D" then
system=0 --boom
end
end

View File

@ -1,3 +1,5 @@
baseurl: ""
url: "https://flightcontrol-master.github.io"
repository: FlightControl-Master/MOOSE
title: MOOSE
description: MOOSE is a Mission Object Oriented Scripting Environment for mission designers in DCS World

View File

@ -0,0 +1,73 @@
---
parent: Build system
nav_order: 2
---
# Build class documentation
The documentation of all classes are included in the code as comments.
This kind of documentation process is called [LuaDoc]. But we build the
html files for the documentation with [LuaDocumentor]. It is a tool
similar to [LuaDoc], but with some additional features the Moose team
decided to use.
{: .important }
> The team created also some modifications, which are not part of the
> official [LuaDocumentor] tool. So we use the code in the git repository
> [Applevangelist/luadocumentor] in the branch `patch-1`.
There are two git repositories which are used to save the generated
documentation:
- [MOOSE_DOCS] is the repository for the `master` branch of [MOOSE]
- A configured GitHub Pages job will deploy the result to:<br/>
<https://flightcontrol-master.github.io/MOOSE_DOCS/>
- [MOOSE_DOCS_DEVELOP] is the repository for the `develop` branch of [MOOSE]
- A configured GitHub Pages job will deploy the result to:<br/>
<https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/>
Main build steps to create the class documentation are defined in [.github/workflows/build-docs.yml]:
- Checkout of the git repository [MOOSE].
- Create output folders.
- Checkout of the git repository [Applevangelist/luadocumentor] with
branch `patch-1` into a subdirectory.
- Update the Linux system software.
- Install needed tools:
- [tree] - A tool to output a tree view of a folder structure.
- [lua] - Package to run [Lua] scripts. This time [Lua] 5.1,
because it matches the DCS environment.
- [LuaRocks] - This is the package manager for Lua modules.
- [markdown] - Dependency for [LuaDocumentor]
- [penlight] - Dependency for [LuaDocumentor]
- [metalua-compiler] - Dependency for [LuaDocumentor]
- [metalua-parser] - Dependency for [metalua-compiler]
- [checks] - Dependency for [metalua-parser]
- Run the build steps:
- Run `luadocumentor.lua` to create the html files.
- Deploy build results:
- Checkout [MOOSE_DOCS] or [MOOSE_DOCS_DEVELOP] git repository in a subdirectory.
- Use the matching git repository for the branch of [MOOSE].
- `master` -> [MOOSE_DOCS].
- `develop` -> [MOOSE_DOCS_DEVELOP].
- Use a `TOKEN` for checkout, so a `push` is possible later on.
- Copy build result to `MOOSE_DOCS` folder.
- Push results to the target repository.
[tree]: https://wiki.ubuntuusers.de/tree/
[LuaDoc]: https://keplerproject.github.io/luadoc/
[LuaDocumentor]: https://luarocks.org/modules/luarocks/luadocumentor
[Applevangelist/luadocumentor]: https://github.com/Applevangelist/luadocumentor/tree/patch-1
[markdown]: https://luarocks.org/modules/mpeterv/markdown
[penlight]: https://luarocks.org/modules/tieske/penlight
[metalua-compiler]: https://luarocks.org/modules/luarocks/metalua-compiler
[metalua-parser]: https://luarocks.org/modules/luarocks/metalua-parser
[checks]: https://luarocks.org/modules/fab13n/checks
[MOOSE]: https://github.com/FlightControl-Master/MOOSE
[MOOSE_DOCS]: https://github.com/FlightControl-Master/MOOSE_DOCS
[MOOSE_DOCS_DEVELOP]: https://github.com/FlightControl-Master/MOOSE_DOCS_DEVELOP
[Lua]: https://www.lua.org/
[LuaRocks]: https://luarocks.org/
[.github/workflows/build-docs.yml]: https://github.com/FlightControl-Master/MOOSE/blob/master/.github/workflows/build-docs.yml

View File

@ -0,0 +1,45 @@
---
parent: Build system
nav_order: 1
---
# Build include files
Main build steps to create the include files are defined in [.github/workflows/build-includes.yml]:
- Checkout of the git repository [MOOSE].
- Create output folders.
- Update the Linux system software.
- Install needed tools:
- [tree] - A tool to output a tree view of a folder structure.
- [lua5.3] - Package to run [Lua] scripts. Version 5.3 is needed, because we
need liblua5.3-dev for [LuaSrcDiet].
- [LuaRocks] - LuaRocks is the package manager for Lua modules.
- liblua5.3-dev - Header file of [Lua] needed for [LuaSrcDiet] to work.
- [LuaSrcDiet] - To compress the [Lua] code and create `Moose_.lua`.
- [LuaCheck] - This is a static code analyzer and a linter for [Lua].
- Run the build steps:
- Run `./Moose Setup/Moose_Create.lua` to create `Moose.lua`.
- Run `./Moose Setup/Moose_Create.lua` to create dynamic `Moose.lua` to
load individual Lua class files used by Moose developers.
- Run [LuaSrcDiet] to compress the [Lua] code and create `Moose_.lua`
- Run [LuaCheck] to find errors in the code. Warnings are ignored, because
there are a lot of warnings, which cannot be resolved by the Moose team.
- Deploy build results:
- Checkout [MOOSE_INCLUDE] git repository in a subdirectory.
- Use the same branch used to checkout [MOOSE] git repository.
- Use a `TOKEN` for checkout, so a `push` is possible later on.
- Copy build result to `MOOSE_INCLUDE` folder
- Push results to [MOOSE_INCLUDE] repository
[.github/workflows/build-includes.yml]: https://github.com/FlightControl-Master/MOOSE/blob/master/.github/workflows/build-includes.yml
[tree]: https://wiki.ubuntuusers.de/tree/
[lua5.3]: https://www.lua.org/manual/5.3/
[LuaRocks]: https://luarocks.org/
[LuaCheck]: https://github.com/mpeterv/luacheck
[MOOSE]: https://github.com/FlightControl-Master/MOOSE
[MOOSE_INCLUDE]: https://github.com/FlightControl-Master/MOOSE_INCLUDE
[LuaSrcDiet]: https://github.com/jirutka/luasrcdiet
[Lua]: https://www.lua.org/

View File

@ -0,0 +1,51 @@
---
parent: Build system
nav_order: 3
---
# Build GitHub Pages
This documentation is created by [GitHub Pages]. The source files are
stored in the repository [MOOSE] in the subfolder `docs`.
We use [Just the Docs], which is a modern, highly customizable, and responsive
[Jekyll] theme for documentation.
{: .note }
> The class documentation is created by its own [build] and is not the scope for this page!
The build steps to create this documentation are defined in [.github/workflows/gh-pages.yml].
It is divided into two jobs:
- build:
- Only changes to in the subfolder `docs` or `gh-pages.yml` will trigger a build.
- Checkout of the git repository [MOOSE].
- Setup [Ruby] version 3.1, which is needed by [Jekyll].
- Run action [configure-pages].
- Build with [Jekyll].
- Run action [upload-pages-artifact].
- deploy:
- Run action [deploy-pages].
# Preview of this documentation
When enhancing this documentation it is very useful to see a 1on1 preview of the pages.
This can be displayed as follows:
- You need a working installation of [Docker].
- Go to the `docs` subfolder.
- Run `docker compose up`.
- Open a browser with the following URL: `http://127.0.0.1:4000/`.
- After a change of the [Markdown] files, wait some seconds and press F5 in the browser.
[GitHub Pages]: https://pages.github.com/
[MOOSE]: https://github.com/FlightControl-Master/MOOSE
[Just the Docs]: https://github.com/just-the-docs/just-the-docs
[Jekyll]: https://jekyllrb.com/
[Ruby]: https://www.ruby-lang.org/en/
[build]: build-docs.md
[.github/workflows/gh-pages.yml]: https://github.com/FlightControl-Master/MOOSE/blob/master/.github/workflows/gh-pages.yml
[configure-pages]: https://github.com/actions/configure-pages/
[upload-pages-artifact]: https://github.com/actions/upload-pages-artifact
[deploy-pages]: https://github.com/actions/deploy-pages/
[Docker]: https://www.docker.com/
[Markdown]: https://www.markdownguide.org/

58
docs/buildsystem/index.md Normal file
View File

@ -0,0 +1,58 @@
---
has_children: true
nav_order: 3
---
# Build system
{: .note }
> This documentation is not needed for end users. Only the people of the
> development team, who must maintain the build system need to read this.
In this document we want to describe our build system for MOOSE.
MOOSE consists of multiple [Lua] files. Each class is stored in its own file.
This is needed for MOOSE developers to maintain clarity.
For users this is not practical, because they want to include the whole framework
as a single file into their missions.
Because of this the build will collect all needed files and merge them together
in one file with the name `Moose.lua`. It includes also all comments and the
class documentation. Because of this its size is about 6-7 MB.
To reduce the size of the file and make mission files smaller, the Moose team
decided to create a version without all comments and documentation. This file
is named `Moose_.lua`. It is created by a tool with the name [LuaSrcDiet].
Both files will be called static includes. In other programming languages includes
are dependencies. For Moose it is easier to memorize, that these files must be
included in your mission to use Moose. It is an static approach because you need
to add it once and it is only read from inside of the mission file after that.
A dynamic approach is to load all the single class files on each mission start
from the hard disk. But this is more for advanced Moose users and Moose developers.
## Details
In the past [AppVeyor] was used to run the build on a Windows system.
We decided to migrate this build to [GitHub Actions]. Installation of
dependencies was not stable on Windows with [GitHub Actions]. So we switched
to Ubuntu Linux.
### GitHub Actions yml files
The build configuration is stored in the folder `.github/workflows`. You will find
multiple files in this directory:
- [build-docs.yml] - Job definition to generate the class documentation
- [build-includes.yml] - Job definition to build the static includes
- [gh-pages.yml] - Job to build this documentation page
We decided to use different files for each job for separation of duties and easier
maintenance.
[Lua]: https://www.lua.org/
[LuaSrcDiet]: https://github.com/jirutka/luasrcdiet
[AppVeyor]: https://www.appveyor.com/
[GitHub Actions]: https://docs.github.com/en/actions
[build-docs.yml]: build-docs.md
[build-includes.yml]: build-includes.md
[gh-pages.yml]: gh-pages.md

View File

@ -0,0 +1,49 @@
---
parent: Build system
nav_order: 4
---
# Run builds locally
When creating or enhancing [GitHub Actions] builds it is a problem to test the
build. After each change you need to commit and check the build result. This
leads to a lot of unnecessary commits.
Therefor it is needed to run the build locally on the developer PC. The tool
which enabled this is [act]. It uses [Docker] to create a build runner and
executes the [GitHub Actions] build with it.
[act] can by installed by [Chocolatey] by this single command: `choco install act-cli`.
We use the `Medium Docker Image` for our MOOSE builds to work properly.
Unfortunately the docker images used by [act] are not as up to date as the
images used by [GitHub Actions]. So we needed to add a build step with
`sudo apt-get -qq update`.
The build jobs needs `TOKENS` to run properly. So you have to create a PAT
([Personal Access Token]). A classic Token with read rights is enough to run
the build, as long as don't want to push the results.
{: .important }
> The push step is only executed if the variable `FORCE_PUSH` with value `true` is set.
> - This is only needed if the push step itself must be change and tested!
> - Add parameter `--var FORCE_PUSH=true` to your [act] commando.
> - You and your PAT needs write access to the target repos, too.
Save your PAT in the file `.secrets` in the main folder
of the MOOSE repository. This file is added to `.gitignore`, so it is not
recognized by git for commits. Add the following line to `.secrets`:
```
BOT_TOKEN=<your PAT>
```
To run the builds use these commands:
- `act push -W .github/workflows/build-includes.yml`
- `act push -W .github/workflows/build-docs.yml`
[GitHub Actions]: https://docs.github.com/en/actions
[act]: https://github.com/nektos/act
[Docker]: https://www.docker.com/
[Chocolatey]: https://community.chocolatey.org/
[Personal Access Token]: https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens