Files
spearhead/classes/capClasses/taskings/CAP.lua
T
dutchie031andGitHub 0233b9e2d7 Cap rework (#48)
- Refactored all CAP classes.
- Improved timing
- Zones are now not tied to MissionStages
  - CAPROUTE_<routeID>_<free>
  - routeID is now what is used in the naming convention.
- Units taxi back to their spawn parking space and rearm there.
  (Units destroyed while in the Rearming or Repairing state are not taken into account)
2025-06-01 18:58:35 +02:00

328 lines
11 KiB
Lua

---@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 = Spearhead.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 = Spearhead.Util.vectorHeadingFromTo(pointA, pointB)
if Spearhead.Util.VectorDistance2d(baseVec2, pointB) > Spearhead.Util.VectorDistance2d(baseVec2, pointA) then
furthest = pointB
closest = pointA
heading = Spearhead.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 = Spearhead.Util.vectorHeadingFromTo(airbaseVec2, capZone.location)
local point = Spearhead.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] = Spearhead.classes.capClasses.taskings.RTB.getApproachPoint(airbase, capZone.location, capConfig),
[5] = Spearhead.classes.capClasses.taskings.RTB.getInitialPoint(airbase),
[6] = Spearhead.classes.capClasses.taskings.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] = Spearhead.classes.capClasses.taskings.RTB.getApproachPoint(airbase, capZone.location, capConfig),
[3] = Spearhead.classes.capClasses.taskings.RTB.getInitialPoint(airbase),
[4] = Spearhead.classes.capClasses.taskings.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
if not Spearhead then Spearhead = {} end
if not Spearhead.classes then Spearhead.classes = {} end
if not Spearhead.classes.capClasses then Spearhead.classes.capClasses = {} end
if not Spearhead.classes.capClasses.taskings then Spearhead.classes.capClasses.taskings = {} end
Spearhead.classes.capClasses.taskings.CAP = CAP