Dcs lua tool (#66)

* custom drawings and animations for video

* wip

* Work in progress refactor for toolkit

* wip

* Refactored everything for Lua Compile Tool

* Trying out the github action

* updated the github action ref

* initial working version

---------

Co-authored-by: ex61wi <tim.rorije@ing.com>
Co-authored-by: dutchie031 <dutchie031>
This commit is contained in:
2026-06-06 19:26:32 +02:00
committed by GitHub
co-authored by ex61wi dutchie031 <dutchie031>
parent c027921527
commit 128aed1d2b
82 changed files with 8963 additions and 4390 deletions
+326
View File
@@ -0,0 +1,326 @@
local Util = require("classes.util.Util")
local RTB = require("classes.capClasses.taskings.RTB")
---@class CAPTasking
local CAP = {}
---@param attackHelos boolean
---@return table
local function GetCAPTargetTypes(attackHelos)
local targetTypes = {
[1] = "Planes",
}
if attackHelos then
targetTypes[2] = "Helicopters"
end
return targetTypes
end
---@class CapTaskingOptions
---@field furthest Vec2
---@field closest Vec2
---@field legLength number
---@field width number
---@field hotLegDir number
---@param capZone SpearheadTriggerZone
---@param airBase Airbase
---@return CapTaskingOptions
local function GetCAPPointFromTriggerZone(airBase, capZone)
local furthestA = nil
local furthestB = nil
local furthestFromBase = nil
local furthestFromBaseDistance = 0
local furthestDistance = 0
for indexA, pointA in ipairs(capZone.verts) do
for indexB, pointB in ipairs(capZone.verts) do
if pointA ~= pointB then
local distance = Util.VectorDistance2d(pointA, pointB)
if distance > furthestDistance then
furthestDistance = distance
furthestA = indexA
furthestB = indexB
end
end
end
end
local baseVec3 = airBase:getPoint()
---@type Vec2
local baseVec2 = { x = baseVec3.x, y = baseVec3.z }
local pointA = capZone.verts[furthestA]
local pointB = capZone.verts[furthestB]
local furthest = pointA
local closest = pointB
local heading = Util.vectorHeadingFromTo(pointA, pointB)
if Util.VectorDistance2d(baseVec2, pointB) > Util.VectorDistance2d(baseVec2, pointA) then
furthest = pointB
closest = pointA
heading = Util.vectorHeadingFromTo(pointB, pointA)
end
local distance = furthestDistance
if distance > 15000 then
distance = distance - 10000
end
return {
width = 10000,
furthest = furthest,
closest = closest,
legLength = distance,
hotLegDir = math.rad(heading),
orbitOriginPoint = closest
}
end
---@param airbase Airbase
---@param capZone SpearheadTriggerZone
---@param capConfig CapConfig
local GetOutboundTask = function(airbase, capZone, capConfig)
local airbaseVec3 = airbase:getPoint()
local airbaseVec2 = { x = airbaseVec3.x, y = airbaseVec3.z }
local heading = Util.vectorHeadingFromTo(airbaseVec2, capZone.location)
local point = Util.vectorMove(airbaseVec2, heading, 18520)
return {
alt = 2000,
action = "Fly Over Point",
type = "Turning Point",
alt_type = "BARO",
speed = capConfig:getMinSpeed(),
ETA = 0,
ETA_locked = false,
x = point.x,
y = point.y,
speed_locked = false,
formation_template = "",
task = {
id = "ComboTask",
params = {
tasks = {
[1] = {
id = 'EngageTargets',
params = {
maxDist = capConfig:getMaxDeviationRange() + 10 * 1852,
maxDistEnabled = capConfig:getMaxDeviationRange() > 0, -- required to check maxDist
targetTypes = GetCAPTargetTypes(false),
priority = 0
}
},
}
}
}
}
end
---@param groupName string
---@param airbase Airbase
---@param capZone SpearheadTriggerZone
---@param capConfig CapConfig
function CAP.getAsMissionFromAirbase(groupName, airbase, capZone, capConfig)
local points = {
[1] = GetOutboundTask(airbase, capZone, capConfig),
[2] = GetOutboundTask(airbase, capZone, capConfig),
[3] = CAP.getAsTasking(groupName, airbase, capZone, capConfig),
[4] = RTB.getApproachPoint(airbase, capZone.location, capConfig),
[5] = RTB.getInitialPoint(airbase),
[6] = RTB.getLandingPoint(airbase)
}
local mission = {
id = 'Mission',
params = {
airborne = true,
route = {
points = points
}
}
}
return mission
end
---@param groupName string
---@param airbase Airbase
---@param capZone SpearheadTriggerZone
---@param capConfig CapConfig
function CAP.getAsMission(groupName, airbase, capZone, capConfig)
local points = {
[1] = CAP.getAsTasking(groupName, airbase, capZone, capConfig),
[2] = RTB.getApproachPoint(airbase, capZone.location, capConfig),
[3] = RTB.getInitialPoint(airbase),
[4] = RTB.getLandingPoint(airbase)
}
local mission = {
id = 'Mission',
params = {
airborne = true,
route = {
points = points
}
}
}
return mission
end
---@private
---@param groupName string
---@param airbase Airbase
---@param capZone SpearheadTriggerZone
---@param capConfig CapConfig
function CAP.getAsTasking(groupName, airbase, capZone, capConfig)
local duration = math.random(capConfig:getMinDurationOnStation(), capConfig:getMaxDurationOnStation()) or 1500
local capTaskingOptions = GetCAPPointFromTriggerZone(airbase, capZone)
local durationBefore10 = duration - 600
if durationBefore10 < 0 then durationBefore10 = 0 end
local durationAfter10 = 600
if duration < 600 then
durationAfter10 = duration
end
local alt = math.random(capConfig:getMinAlt(), capConfig:getMaxAlt())
local speed = math.random(capConfig:getMinSpeed(), capConfig:getMaxSpeed())
return {
alt = alt,
action = "Turning Point",
alt_type = "BARO",
speed = speed,
ETA = 0,
ETA_locked = false,
x = capTaskingOptions.closest.x,
y = capTaskingOptions.closest.y,
speed_locked = true,
formation_template = "",
task = {
id = "ComboTask",
params = {
tasks = {
[1] = {
number = 1,
auto = false,
id = "WrappedAction",
enabled = "true",
params = {
action = {
id = "Script",
params = {
command = "pcall(Spearhead.Events.PublishOnStation, \"" .. groupName .. "\")"
}
}
}
},
[2] = {
id = 'EngageTargets',
params = {
maxDist = capConfig:getMaxDeviationRange(),
maxDistEnabled = capConfig:getMaxDeviationRange() >= 0, -- required to check maxDist
targetTypes = GetCAPTargetTypes(false),
priority = 0
}
},
[3] = {
number = 3,
auto = false,
id = "ControlledTask",
enabled = true,
params = {
task = {
id = "Orbit",
params = {
altitude = alt,
pattern = "Anchored",
speed = speed,
point = {
x = capTaskingOptions.closest.x,
y = capTaskingOptions.closest.y
},
speedEdited = true,
clockWise = false,
hotLegDir = capTaskingOptions.hotLegDir,
legLength = capTaskingOptions.legLength,
width = capTaskingOptions.width,
}
},
stopCondition = {
duration = durationBefore10,
condition = "return Spearhead.DcsUtil.NeedsRTBInTen(\"" .. groupName .. "\", 0.10)",
}
}
},
[4] = {
number = 4,
auto = false,
id = "WrappedAction",
enabled = "true",
params = {
action = {
id = "Script",
params = {
command = "pcall(Spearhead.Events.PublishRTBInTen, \"" .. groupName .. "\")"
}
}
}
},
[5] = {
number = 5,
auto = false,
id = "ControlledTask",
enabled = true,
params = {
task = {
id = "Orbit",
params = {
altitude = alt,
pattern = "Circle",
speed = speed,
-- speedEdited = true,
-- clockWise = false,
-- hotLegDir = capTaskingOptions.hotLegDir,
-- legLength = capTaskingOptions.legLength,
-- width = capTaskingOptions.width,
}
},
stopCondition = {
duration = durationAfter10,
condition = "return Spearhead.DcsUtil.IsBingoFuel(\"" .. groupName .. "\")",
}
}
},
[6] = {
number = 6,
auto = false,
id = "WrappedAction",
enabled = "true",
params = {
action = {
id = "Script",
params = {
command = "pcall(Spearhead.Events.PublishRTB, \"" .. groupName .. "\")"
}
}
}
}
}
}
}
}
end
return CAP
@@ -0,0 +1,396 @@
local Util = require("classes.util.Util")
local RTB = require("classes.capClasses.taskings.RTB")
---@class InterceptTasking
local INTERCEPT = {}
---@param groupName string
---@param interceptPoint Vec2
---@param airbase Airbase
---@param speed number?
---@param alt number?
---@param config CapConfig
function INTERCEPT.getMissionFromAirbase(groupName, interceptPoint, airbase, config, speed, alt)
local airbaseVec3 = airbase:getPoint()
local airbaseVec2 = { x = airbaseVec3.x, y = airbaseVec3.z }
local heading = Util.vectorHeadingFromTo(airbaseVec2, interceptPoint)
env.info("BLAAT: heading from runway to first point: " .. heading)
local point = Util.vectorMove(airbaseVec2, heading, 3*1852)
local pointA, pointB, pointC, pointD = INTERCEPT.getInterceptTaskPoint(groupName, point, interceptPoint, airbaseVec2, config, speed, alt)
local points = {
[1] = pointA,
[2] = pointA,
[3] = pointB,
[4] = pointC,
[5] = pointD,
[6] = RTB.getApproachPoint(airbase, interceptPoint, config),
[7] = RTB.getInitialPoint(airbase),
[8] = RTB.getLandingPoint(airbase)
}
local mission = {
id = 'Mission',
params = {
airborne = true,
route = {
points = points
}
}
}
return mission
end
---comment
---@param groupName string
---@param currentPosition Vec2
---@param interceptPoint Vec2
---@param airbase Airbase
---@param speed number?
---@param alt number?
---@param config CapConfig
---@return table
function INTERCEPT.getMissionFromInAir(groupName, currentPosition, interceptPoint, airbase, config, speed, alt)
local pointAirbasev3 = airbase:getPoint()
local airbase2 = { x = pointAirbasev3.x, y = pointAirbasev3.z }
local pointA, pointB, pointC, pointD = INTERCEPT.getInterceptTaskPoint(groupName, currentPosition, interceptPoint, airbase2, config, speed, alt)
local points = {
[1] = pointA,
[2] = pointA,
[3] = pointB,
[4] = pointC,
[5] = pointD,
[6] = RTB.getApproachPoint(airbase, interceptPoint, config),
[7] = RTB.getInitialPoint(airbase),
[8] = RTB.getLandingPoint(airbase)
}
local mission = {
id = 'Mission',
params = {
airborne = true,
route = {
points = points
}
}
}
return mission
end
---comment
---@param groupName string
---@param currentPoint Vec2
---@param targetPosition Vec2
---@param targetUnit Unit
---@param airbase any
---@param config any
---@param speed number?
---@param alt number?
---@return table
function INTERCEPT.getUnitInterceptMissionFromAir(groupName, currentPoint, targetPosition, targetUnit, airbase, config, speed, alt)
local pointAirbasev3 = airbase:getPoint()
local airbase2 = { x = pointAirbasev3.x, y = pointAirbasev3.z }
local pointA, pointB, pointC, pointD = INTERCEPT.getUnitInterceptTaskPoint(groupName, currentPoint, targetPosition, targetUnit, airbase2, config, speed, alt)
local points = {
[1] = pointA,
[2] = pointA,
[3] = pointB,
[4] = pointC,
[5] = pointD,
[6] = RTB.getApproachPoint(airbase, currentPoint, config),
[7] = RTB.getInitialPoint(airbase),
[8] = RTB.getLandingPoint(airbase)
}
local mission = {
id = 'Mission',
params = {
airborne = true,
route = {
points = points
}
}
}
return mission
end
---@private
---@param groupName string
---@param currentPoint Vec2
---@param targetPoint Vec2
---@param airbasePoint Vec2
---@param config CapConfig
---@param speed number?
---@param alt number?
---@return table pointA @Starts the task right away
---@return table pointB @The actual target point to fly to and search, but searching started at pointA
---@return table pointC A fly over point halfway between the target and the airbase, if nothing it found then the unit will fly it's route till here
---@return table pointD THe point after Point C where the unit will execute the RTB command
function INTERCEPT.getInterceptTaskPoint(groupName, currentPoint, targetPoint, airbasePoint, config, speed, alt)
local pointA = {
alt = alt or config:getMinAlt(),
action = "Turning Point",
alt_type = "BARO",
speed = speed or config:getMaxSpeed(),
ETA = 0,
ETA_locked = false,
x = currentPoint.x,
y = currentPoint.y,
speed_locked = true,
formation_template = "",
task = {
id = "ComboTask",
params = {
tasks = {
id = 'EngageTargetsInZone',
params = {
point = targetPoint,
zoneRadius = 10 * 1852, -- 10 NM, point will be updated, so target should be in this zone.
targetTypes = {
[1] = "Planes",
},
priority = 0
}
}
}
}
}
local pointB = {
alt = alt or config:getMinAlt(),
action = "Turning Point",
alt_type = "BARO",
speed = speed or config:getMaxSpeed(),
ETA = 0,
ETA_locked = false,
x = targetPoint.x,
y = targetPoint.y,
speed_locked = true,
formation_template = "",
task = {
id = "ComboTask",
params = {
tasks = {
id = 'EngageTargetsInZone',
params = {
point = targetPoint,
zoneRadius = 10 * 1852, -- 10 NM, point will be updated, so target should be in this zone.
targetTypes = {
[1] = "Planes",
},
priority = 0
}
}
}
}
}
local midPoint = {
x = (targetPoint.x + airbasePoint.x) / 2,
y = (targetPoint.y + airbasePoint.y) / 2
}
local pointC = {
alt = config:getMinAlt(),
action = "Fly Over Point",
alt_type = "BARO",
speed = config:getMaxSpeed(),
ETA = 0,
ETA_locked = false,
x = midPoint.x,
y = midPoint.y,
speed_locked = true,
formation_template = "",
task = {
id = "ComboTask",
params = {}
}
}
local pointD = {
alt = config:getMinAlt(),
action = "Turning Point",
alt_type = "BARO",
speed = config:getMaxSpeed(),
ETA = 0,
ETA_locked = false,
x = midPoint.x,
y = midPoint.y,
speed_locked = true,
formation_template = "",
task = {
id = "ComboTask",
params = {
tasks = {
[1] = {
number = 1,
auto = false,
id = "WrappedAction",
enabled = "true",
params = {
action = {
id = "Script",
params = {
command = "pcall(Spearhead.Events.PublishRTB, \"" .. groupName .. "\")"
}
}
}
}
}
}
}
}
return pointA, pointB, pointC, pointD
end
---@private
---@param groupName string
---@param currentPoint Vec2
---@param targetPosition Vec2
---@param targetUnit Unit
---@param airbasePoint Vec2
---@param config CapConfig
---@param speed number?
---@param alt number?
---@return table pointA @Starts the task right away
---@return table pointB @The actual target point to fly to and search, but searching started at pointA
---@return table pointC A fly over point halfway between the target and the airbase, if nothing it found then the unit will fly it's route till here
---@return table pointD THe point after Point C where the unit will execute the RTB command
function INTERCEPT.getUnitInterceptTaskPoint(groupName, currentPoint, targetPosition, targetUnit, airbasePoint, config, speed, alt)
local pointA = {
alt = alt or config:getMinAlt(),
action = "Turning Point",
alt_type = "BARO",
speed = speed or config:getMaxSpeed(),
ETA = 0,
ETA_locked = false,
x = currentPoint.x,
y = currentPoint.y,
speed_locked = true,
formation_template = "",
task = {
id = "ComboTask",
params = {
tasks = {
[1] = {
id = 'EngageUnit',
params = {
unitId = targetUnit:getID(),
groupAttack = true,
priority = 0
}
}
}
}
}
}
local pointB = {
alt = alt or config:getMinAlt(),
action = "Turning Point",
alt_type = "BARO",
speed = speed or config:getMaxSpeed(),
ETA = 0,
ETA_locked = false,
x = targetPosition.x,
y = targetPosition.y,
speed_locked = true,
formation_template = "",
task = {
id = "ComboTask",
params = {
tasks = {
[1] = {
id = 'EngageUnit',
params = {
unitId = targetUnit:getID(),
groupAttack = true,
priority = 0
}
}
}
}
}
}
local midPoint = {
x = (targetPosition.x + airbasePoint.x) / 2,
y = (targetPosition.y + airbasePoint.y) / 2
}
local pointC = {
alt = config:getMinAlt(),
action = "Fly Over Point",
alt_type = "BARO",
speed = config:getMaxSpeed(),
ETA = 0,
ETA_locked = false,
x = midPoint.x,
y = midPoint.y,
speed_locked = true,
formation_template = "",
task = {
id = "ComboTask",
params = {}
}
}
local pointD = {
alt = config:getMinAlt(),
action = "Turning Point",
alt_type = "BARO",
speed = config:getMaxSpeed(),
ETA = 0,
ETA_locked = false,
x = midPoint.x,
y = midPoint.y,
speed_locked = true,
formation_template = "",
task = {
id = "ComboTask",
params = {
tasks = {
[1] = {
number = 1,
auto = false,
id = "WrappedAction",
enabled = "true",
params = {
action = {
id = "Script",
params = {
command = "pcall(Spearhead.Events.PublishRTB, \"" .. groupName .. "\")"
}
}
}
}
}
}
}
}
return pointA, pointB, pointC, pointD
end
return INTERCEPT
+198
View File
@@ -0,0 +1,198 @@
local Util = require("classes.util.Util")
---@class RTBTasking
local RTB = {}
---@param airbase Airbase
---@param missionPoint Vec2
---@param capConfig CapConfig
function RTB.getAsMission(airbase, missionPoint, capConfig)
return {
id = "Mission",
params = {
airborne = true,
route = {
points = {
[1] = RTB.getApproachPoint(airbase, missionPoint, capConfig),
[2] = RTB.getInitialPoint(airbase),
[3] = RTB.getLandingPoint(airbase)
}
}
}
}
end
---@param airbase Airbase
---@return number
local getRunwayIntoWindCourseRad = function(airbase)
local activeCourse = nil
local minAlignment = nil
local runways = airbase:getRunways()
local windVec = atmosphere.getWind(airbase:getPoint())
local mPerS = Util.vectorMagnitude(windVec)
if mPerS > 0 then
for i = 1, #runways do
local runway = runways[i]
do --normal
local rad = runway.course
if rad < 0 then
rad = math.abs(rad)
else
rad = 0 - rad
end
local runwayVec = {x = math.cos(rad), z = math.sin(rad), y = 0}
local alignment = Util.vectorAlignment(windVec, runwayVec)
if minAlignment == nil or alignment < minAlignment then
activeCourse = i
minAlignment = alignment
end
end
do --inverse
local degree = math.deg(runway.course)
degree = (degree + 180) % 360
local rad = math.rad(degree)
if rad < 0 then
rad = math.abs(rad)
else
rad = 0 - rad
end
local runwayVec = {x = math.cos(rad), z = math.sin(rad), y = 0}
local alignment = Util.vectorAlignment(windVec, runwayVec)
if minAlignment == nil or alignment < minAlignment then
activeCourse = i
minAlignment = alignment
end
end
end
end
local rad = runways[1].course
if activeCourse ~= nil then
rad = runways[activeCourse].course
end
if rad < 0 then
return math.abs(rad)
else
return 0 - rad
end
end
---comment
---@param airbase Airbase
---@return Vec2
---@return number headingFromRunwayDegrees
local function calcInitialPoint(airbase)
local runwayCourseRad = getRunwayIntoWindCourseRad(airbase)
local heading = math.deg(runwayCourseRad)
local flipped = (heading + 180) % 360
local basePoint = airbase:getPoint()
local basePointVec2 = {x = basePoint.x, y = basePoint.z}
local point = Util.vectorMove(basePointVec2, flipped, 22000)
return point, flipped
end
---comment
---@param airbase Airbase
---@param missionPoint Vec2
---@param capConfig CapConfig
function RTB.getApproachPoint(airbase, missionPoint, capConfig)
local initialPoint, headingFromRunway = calcInitialPoint(airbase)
local pointA = Util.vectorMove(initialPoint, headingFromRunway - 45, 9000)
local pointB = Util.vectorMove(initialPoint, headingFromRunway + 45, 9000)
if Util.VectorDistance2d(missionPoint, pointA) > Util.VectorDistance2d(missionPoint, pointB) then
pointA = pointB
end
return {
alt = 3000,
action = "Turning Point",
alt_type = "BARO",
speed = capConfig:getMinSpeed(),
ETA = 0,
ETA_locked = false,
x = pointA.x,
y = pointA.y,
speed_locked = true,
formation_template = "",
type = "Turning Point",
task = {
id = "ComboTask",
params = {
tasks = {}
}
}
}
end
---@param airbase Airbase
function RTB.getInitialPoint(airbase)
local point = calcInitialPoint(airbase)
return {
alt = 600,
action = "Turning Point",
alt_type = "BARO",
speed = 180,
ETA = 0,
ETA_locked = false,
x = point.x,
y = point.y,
speed_locked = true,
formation_template = "",
type = "Turning Point",
task = {
id = "ComboTask",
params = {
tasks = {}
}
}
}
end
function RTB.getLandingPoint(airbase)
local basePoint = airbase:getPoint()
return {
alt = basePoint.y,
action = "Landing",
alt_type = "BARO",
speed = 70,
ETA = 0,
ETA_locked = false,
x = basePoint.x,
y = basePoint.z,
speed_locked = true,
formation_template = "",
airdromeId = airbase:getID(),
type = "Land",
task = {
id = "ComboTask",
params = {
tasks = {}
}
}
}
end
return RTB
+286
View File
@@ -0,0 +1,286 @@
local Util = require("classes.util.Util")
local RTB = require("classes.capClasses.taskings.RTB")
---@class SWEEPTasking
local SWEEP = {}
---@param attackHelos boolean
---@return table
local function GetCAPTargetTypes(attackHelos)
local targetTypes = {
[1] = "Planes",
}
if attackHelos then
targetTypes[2] = "Helicopters"
end
return targetTypes
end
---@class SWEEPTaskingOptions
---@field furthest Vec2
---@field closest Vec2
---@param capZone SpearheadTriggerZone
---@param airBase Airbase
---@return SWEEPTaskingOptions
local function GetCAPPointFromTriggerZone(airBase, capZone)
local furthestA = nil
local furthestB = nil
local furthestDistance = 0
for indexA, pointA in ipairs(capZone.verts) do
for indexB, pointB in ipairs(capZone.verts) do
if pointA ~= pointB then
local distance = Util.VectorDistance2d(pointA, pointB)
if distance > furthestDistance then
furthestDistance = distance
furthestA = indexA
furthestB = indexB
end
end
end
end
local baseVec3 = airBase:getPoint()
---@type Vec2
local baseVec2 = { x = baseVec3.x, y = baseVec3.z }
local pointA = capZone.verts[furthestA]
local pointB = capZone.verts[furthestB]
local furthest = pointA
local closest = pointB
local heading = Util.vectorHeadingFromTo(pointA, pointB)
if Util.VectorDistance2d(baseVec2, pointB) > Util.VectorDistance2d(baseVec2, pointA) then
furthest = pointB
closest = pointA
heading = Util.vectorHeadingFromTo(pointB, pointA)
end
local distance = furthestDistance
if distance > 15000 then
distance = distance - 10000
end
return {
width = 10000,
furthest = furthest,
closest = closest,
legLength = distance,
hotLegDir = math.rad(heading),
orbitOriginPoint = closest
}
end
---@param airbase Airbase
---@param capZone SpearheadTriggerZone
---@param capConfig CapConfig
local GetOutboundTask = function(airbase, capZone, capConfig)
local airbaseVec3 = airbase:getPoint()
local airbaseVec2 = { x = airbaseVec3.x, y = airbaseVec3.z }
local heading = Util.vectorHeadingFromTo(airbaseVec2, capZone.location)
local point = Util.vectorMove(airbaseVec2, heading, 18520)
return {
alt = 2000,
action = "Fly Over Point",
type = "Turning Point",
alt_type = "BARO",
speed = capConfig:getMinSpeed(),
ETA = 0,
ETA_locked = false,
x = point.x,
y = point.y,
speed_locked = false,
formation_template = "",
task = {
id = "ComboTask",
params = {
tasks = {
[1] = {
id = 'EngageTargets',
params = {
maxDist = capConfig:getMaxDeviationRange(),
maxDistEnabled = capConfig:getMaxDeviationRange() > 0, -- required to check maxDist
targetTypes = GetCAPTargetTypes(false),
priority = 0
}
},
}
}
}
}
end
---@param groupName string
---@param airbase Airbase
---@param capZone SpearheadTriggerZone
---@param capConfig CapConfig
function SWEEP.getAsMissionFromAirbase(groupName, airbase, capZone, capConfig)
local pointA, pointB, pointC = SWEEP.getAsTasking(groupName, airbase, capZone, capConfig)
local points = {
[1] = GetOutboundTask(airbase, capZone, capConfig),
[2] = GetOutboundTask(airbase, capZone, capConfig),
[3] = pointA,
[4] = pointB,
[5] = pointC,
[6] = RTB.getApproachPoint(airbase, capZone.location, capConfig),
[7] = RTB.getInitialPoint(airbase),
[8] = RTB.getLandingPoint(airbase)
}
local mission = {
id = 'Mission',
params = {
airborne = true,
route = {
points = points
}
}
}
return mission
end
---@private
---@param groupName string
---@param airbase Airbase
---@param capZone SpearheadTriggerZone
---@param capConfig CapConfig
---@return table TurningPointA
---@return table TurningPointB
---@return table TurningPointC
function SWEEP.getAsTasking(groupName, airbase, capZone, capConfig)
local capTaskingOptions = GetCAPPointFromTriggerZone(airbase, capZone)
local alt = math.random(capConfig:getMinAlt(), capConfig:getMaxAlt())
local speed = capConfig:getMaxSpeed()
local pointA = {
alt = alt,
action = "Turning Point",
alt_type = "BARO",
speed = speed,
ETA = 0,
ETA_locked = false,
x = capTaskingOptions.closest.x,
y = capTaskingOptions.closest.y,
speed_locked = true,
formation_template = "",
task = {
id = "ComboTask",
params = {
tasks = {
[1] = {
number = 1,
auto = false,
id = "WrappedAction",
enabled = "true",
params = {
action = {
id = "Script",
params = {
command = "pcall(Spearhead.Events.PublishOnStation, \"" .. groupName .. "\")"
}
}
}
},
[2] = {
id = 'EngageTargets',
params = {
maxDist = capConfig:getMaxDeviationRange(),
maxDistEnabled = capConfig:getMaxDeviationRange() >= 0, -- required to check maxDist
targetTypes = GetCAPTargetTypes(false),
priority = 0
}
}
}
}
}
}
local pointB = {
alt = alt,
action = "Turning Point",
alt_type = "BARO",
speed = speed,
ETA = 0,
ETA_locked = false,
x = capTaskingOptions.furthest.x,
y = capTaskingOptions.furthest.y,
speed_locked = true,
formation_template = "",
task = {
id = "ComboTask",
params = {
tasks = {
[1] = {
id = 'EngageTargets',
params = {
maxDist = capConfig:getMaxDeviationRange(),
maxDistEnabled = capConfig:getMaxDeviationRange() >= 0, -- required to check maxDist
targetTypes = GetCAPTargetTypes(false),
priority = 0
}
}
}
}
}
}
local pointC = {
alt = alt,
action = "Turning Point",
alt_type = "BARO",
speed = speed,
ETA = 0,
ETA_locked = false,
x = capTaskingOptions.closest.x,
y = capTaskingOptions.closest.y,
speed_locked = true,
formation_template = "",
task = {
id = "ComboTask",
params = {
tasks = {
[1] = {
id = 'EngageTargets',
params = {
maxDist = capConfig:getMaxDeviationRange(),
maxDistEnabled = capConfig:getMaxDeviationRange() >= 0, -- required to check maxDist
targetTypes = GetCAPTargetTypes(false),
priority = 0
}
},
[2] = {
number = 2,
auto = false,
id = "WrappedAction",
enabled = "true",
params = {
action = {
id = "Script",
params = {
command = "pcall(Spearhead.Events.PublishRTB, \"" .. groupName .. "\")"
}
}
}
}
}
}
}
}
return pointA, pointB, pointC
end
return SWEEP