Added "change altitude" wingman command

This commit is contained in:
Ambroise Garel
2025-07-27 19:47:31 +02:00
parent 34d54e8f76
commit ef66016f9f
2 changed files with 73 additions and 17 deletions

View File

@@ -6,6 +6,15 @@
TUM.wingmenMenu = {} TUM.wingmenMenu = {}
do do
local function radioCommandChangeAltitude(args)
local player = world:getPlayer()
if not player then return end
TUM.radio.playForAll("playerWingmanChangeAltitude", { args.altitudeText }, player:getCallsign(), false)
TUM.wingmenTasking.commandChangeAltitude(args.altitudeFraction, true)
end
local function radioCommandCoverMe(args) local function radioCommandCoverMe(args)
local player = world:getPlayer() local player = world:getPlayer()
if not player then return end if not player then return end
@@ -92,6 +101,8 @@ do
engageSubPath = missionCommands.addSubMenu("Ground", engagePath) engageSubPath = missionCommands.addSubMenu("Ground", engagePath)
missionCommands.addCommand("Any ground vehicles", engageSubPath, radioCommandEngage, { attributes = {"Tanks", "Trucks", "Artillery", "IFV", "APC"}, category = Group.Category.GROUND, radioMessageSuffix = "Ground", radioTargetName = "ground" }) missionCommands.addCommand("Any ground vehicles", engageSubPath, radioCommandEngage, { attributes = {"Tanks", "Trucks", "Artillery", "IFV", "APC"}, category = Group.Category.GROUND, radioMessageSuffix = "Ground", radioTargetName = "ground" })
missionCommands.addCommand("Armor", engageSubPath, radioCommandEngage, { attributes = {"Tanks", "IFV", "APC"}, category = Group.Category.GROUND, radioMessageSuffix = "Ground", radioTargetName = "armor" }) missionCommands.addCommand("Armor", engageSubPath, radioCommandEngage, { attributes = {"Tanks", "IFV", "APC"}, category = Group.Category.GROUND, radioMessageSuffix = "Ground", radioTargetName = "armor" })
missionCommands.addCommand("Armor (APCs only)", engageSubPath, radioCommandEngage, { attributes = {"IFV", "APC"}, category = Group.Category.GROUND, radioMessageSuffix = "Ground", radioTargetName = "armor" })
missionCommands.addCommand("Armor (tanks only)", engageSubPath, radioCommandEngage, { attributes = {"Tanks"}, category = Group.Category.GROUND, radioMessageSuffix = "Ground", radioTargetName = "armor" })
missionCommands.addCommand("Artillery", engageSubPath, radioCommandEngage, { attributes = {"Artillery"}, category = Group.Category.GROUND, radioMessageSuffix = "Ground", radioTargetName = "artillery" }) missionCommands.addCommand("Artillery", engageSubPath, radioCommandEngage, { attributes = {"Artillery"}, category = Group.Category.GROUND, radioMessageSuffix = "Ground", radioTargetName = "artillery" })
missionCommands.addCommand("Infantry", engageSubPath, radioCommandEngage, { attributes = {"Infantry"}, category = Group.Category.GROUND, radioMessageSuffix = "Ground", radioTargetName = "infantry" }) missionCommands.addCommand("Infantry", engageSubPath, radioCommandEngage, { attributes = {"Infantry"}, category = Group.Category.GROUND, radioMessageSuffix = "Ground", radioTargetName = "infantry" })
missionCommands.addCommand("Trucks", engageSubPath, radioCommandEngage, { attributes = {"Trucks"}, category = Group.Category.GROUND, radioMessageSuffix = "Ground", radioTargetName = "truck" }) missionCommands.addCommand("Trucks", engageSubPath, radioCommandEngage, { attributes = {"Trucks"}, category = Group.Category.GROUND, radioMessageSuffix = "Ground", radioTargetName = "truck" })
@@ -121,6 +132,19 @@ do
-- missionCommands.addCommand("Go to map marker "..TUM.wingmenTasking.DEFAULT_MARKER_TEXT:upper(), rootPath, radioCommandGoToMapMarker, nil) -- missionCommands.addCommand("Go to map marker "..TUM.wingmenTasking.DEFAULT_MARKER_TEXT:upper(), rootPath, radioCommandGoToMapMarker, nil)
missionCommands.addCommand("Report contacts", rootPath, radioCommandReportContacts, nil) missionCommands.addCommand("Report contacts", rootPath, radioCommandReportContacts, nil)
missionCommands.addCommand("Hold position", rootPath, radioCommandOrbit, nil) missionCommands.addCommand("Hold position", rootPath, radioCommandOrbit, nil)
------------------------------------------------------
-- "Change altitude" submenu
------------------------------------------------------
local altitudePath = missionCommands.addSubMenu("Change altitude", rootPath)
local baseAltitude = DCSEx.converter.metersToFeet(Library.aircraft[world.getPlayer():getTypeName()].altitude)
local altitudeFactions = { 0, 0.25, 0.5, 0.75, 1.0, 1.25, 1.5 }
for _,f in ipairs(altitudeFactions) do
local altText = DCSEx.string.toStringThousandsSeparator(math.floor((baseAltitude * f) / 100) * 100).."ft"
if f == 0 then altText = "nap-of-the-earth" end
missionCommands.addCommand(DCSEx.string.firstToUpper(altText), altitudePath, radioCommandChangeAltitude, { altitudeFraction = f, altitudeText = altText })
end
missionCommands.addCommand("Status report", rootPath, radioCommandReportStatus, nil) missionCommands.addCommand("Status report", rootPath, radioCommandReportStatus, nil)
missionCommands.addCommand("Rejoin", rootPath, radioCommandRejoin, nil) missionCommands.addCommand("Rejoin", rootPath, radioCommandRejoin, nil)
end end

View File

@@ -16,6 +16,8 @@ do
local currentTargetIDorPoint = nil -- ID for groups/statics, point2 for scenery objects local currentTargetIDorPoint = nil -- ID for groups/statics, point2 for scenery objects
local currentTargetType = nil local currentTargetType = nil
local cruiseAltitudeFraction = 1.0 -- Fraction of the default aircraft cruise altitude
local function allowWeaponUse(wingmenCtrl, allowAA, allowAG) local function allowWeaponUse(wingmenCtrl, allowAA, allowAG)
allowAA = allowAA or false allowAA = allowAA or false
allowAG = allowAG or false allowAG = allowAG or false
@@ -24,6 +26,25 @@ do
wingmenCtrl:setOption(AI.Option.Air.id.PROHIBIT_AG, not allowAG) wingmenCtrl:setOption(AI.Option.Air.id.PROHIBIT_AG, not allowAG)
end end
local function getAltitude()
local player = world.getPlayer()
if not player then return 600 end -- Don't care about altitude if player's dead anyway
local altitude = Library.aircraft[player:getTypeName()].altitude * cruiseAltitudeFraction
return altitude
end
local function setWingmenAltitude(altitude)
local wingmenCtrl = TUM.wingmen.getController()
if not wingmenCtrl then return nil end
altitude = altitude or getAltitude()
altitude = math.max(50, altitude)
altitude = altitude * DCSEx.math.randomFloat(0.98, 1.02) -- add a slight variation
wingmenCtrl:setAltitude(altitude, true, AI.Task.AltitudeType.BARO)
end
local function doCommandEngageStrikeTargets() local function doCommandEngageStrikeTargets()
-- Not a strike mission, so no strike targets -- Not a strike mission, so no strike targets
if TUM.settings.getValue(TUM.settings.id.TASKING) ~= DCSEx.enums.taskFamily.STRIKE then return nil end if TUM.settings.getValue(TUM.settings.id.TASKING) ~= DCSEx.enums.taskFamily.STRIKE then return nil end
@@ -73,6 +94,7 @@ do
} }
} }
allowWeaponUse(wingmenCtrl, false, true) allowWeaponUse(wingmenCtrl, false, true)
setWingmenAltitude()
wingmenCtrl:setTask(taskTable) wingmenCtrl:setTask(taskTable)
return DCSEx.world.getStaticObjectByID(nearestTarget):getPoint() return DCSEx.world.getStaticObjectByID(nearestTarget):getPoint()
elseif nearestTargetType == "scenery" then elseif nearestTargetType == "scenery" then
@@ -86,6 +108,7 @@ do
} }
} }
allowWeaponUse(wingmenCtrl, false, true) allowWeaponUse(wingmenCtrl, false, true)
setWingmenAltitude()
wingmenCtrl:setTask(taskTable) wingmenCtrl:setTask(taskTable)
return DCSEx.math.vec2ToVec3(nearestTarget, "land") return DCSEx.math.vec2ToVec3(nearestTarget, "land")
end end
@@ -93,25 +116,11 @@ do
return nil return nil
end end
local function getOrbitAltitude()
local player = world.getPlayer()
if not player then return 600 end
local altitude = world.getPlayer():getPoint().y
local aircraftType = player:getTypeName()
if Library.aircraft[aircraftType] and Library.aircraft[aircraftType].altitude then
altitude = math.max(altitude, Library.aircraft[aircraftType].altitude * 0.8)
end
return altitude
end
local function getOrbitTaskTable(point2) local function getOrbitTaskTable(point2)
return { return {
id = "Orbit", id = "Orbit",
params = { params = {
altitude = getOrbitAltitude(), altitude = getAltitude(),
pattern = "Circle", pattern = "Circle",
point = point2, point = point2,
width = DCSEx.converter.nmToMeters(1.0) width = DCSEx.converter.nmToMeters(1.0)
@@ -133,6 +142,20 @@ do
} }
end end
function TUM.wingmenTasking.commandChangeAltitude(altFraction, delayRadioAnswer)
cruiseAltitudeFraction = DCSEx.math.clamp(altFraction or 1.0, 0.0, 2.0)
local newAlt = getAltitude()
local newAltStr = "nap-of-the-earth"
if altFraction > 0 then
newAltStr = DCSEx.string.toStringThousandsSeparator(math.floor(DCSEx.converter.metersToFeet(newAlt) / 100) * 100).."ft"
end
setWingmenAltitude()
TUM.radio.playForAll("pilotWingmanChangeAltitude", { TUM.wingmen.getFirstWingmanNumber(), newAltStr }, TUM.wingmen.getFirstWingmanCallsign(), delayRadioAnswer)
return true
end
function TUM.wingmenTasking.commandEngage(groupCategory, targetAttributes, delayRadioAnswer) function TUM.wingmenTasking.commandEngage(groupCategory, targetAttributes, delayRadioAnswer)
delayRadioAnswer = delayRadioAnswer or false delayRadioAnswer = delayRadioAnswer or false
if TUM.settings.getValue(TUM.settings.id.MULTIPLAYER) then return false end -- No wingmen in multiplayer if TUM.settings.getValue(TUM.settings.id.MULTIPLAYER) then return false end -- No wingmen in multiplayer
@@ -207,6 +230,7 @@ do
local targetInAir = target:inAir() local targetInAir = target:inAir()
allowWeaponUse(wingmenCtrl, targetInAir, not targetInAir) allowWeaponUse(wingmenCtrl, targetInAir, not targetInAir)
setWingmenAltitude()
wingmenCtrl:setTask(taskTable) wingmenCtrl:setTask(taskTable)
local targetBRAA = "distance unknown" local targetBRAA = "distance unknown"
@@ -214,11 +238,11 @@ do
local messageSuffix = nil local messageSuffix = nil
if targetInAir then if targetInAir then
messageSuffix = "Air" messageSuffix = "Air"
targetInfo = Library.objectNames.get(target) -- Library.objectNames.getGeneric(target) targetInfo = Library.objectNames.get(target)
targetBRAA = DCSEx.dcs.getBRAA(target:getPoint(), wingmenPosition, true) targetBRAA = DCSEx.dcs.getBRAA(target:getPoint(), wingmenPosition, true)
else else
messageSuffix = "Surface" messageSuffix = "Surface"
targetInfo = Library.objectNames.get(target) -- Library.objectNames.getGeneric(target) targetInfo = Library.objectNames.getGeneric(target)
targetBRAA = DCSEx.dcs.getBRAA(target:getPoint(), wingmenPosition, false) targetBRAA = DCSEx.dcs.getBRAA(target:getPoint(), wingmenPosition, false)
end end
@@ -257,6 +281,7 @@ do
currentTargetIDorPoint = nil currentTargetIDorPoint = nil
allowWeaponUse(wingmenCtrl, false, false) allowWeaponUse(wingmenCtrl, false, false)
setWingmenAltitude()
wingmenCtrl:setTask(getOrbitTaskTable(DCSEx.math.vec3ToVec2(mapMarker.pos))) wingmenCtrl:setTask(getOrbitTaskTable(DCSEx.math.vec3ToVec2(mapMarker.pos)))
-- TUM.radio.playForAll("pilotWingmanGoToMarker", { TUM.wingmen.getFirstWingmanNumber() }, TUM.wingmen.getFirstWingmanCallsign(), delayRadioAnswer) -- TUM.radio.playForAll("pilotWingmanGoToMarker", { TUM.wingmen.getFirstWingmanNumber() }, TUM.wingmen.getFirstWingmanCallsign(), delayRadioAnswer)
@@ -272,6 +297,7 @@ do
allowWeaponUse(wingmenCtrl, false, false) allowWeaponUse(wingmenCtrl, false, false)
currentTargetIDorPoint = nil currentTargetIDorPoint = nil
setWingmenAltitude()
wingmenCtrl:setTask(getOrbitTaskTable(DCSEx.world.getGroupCenter(TUM.wingmen.getGroup()))) wingmenCtrl:setTask(getOrbitTaskTable(DCSEx.world.getGroupCenter(TUM.wingmen.getGroup())))
TUM.radio.playForAll("pilotWingmanOrbit", { TUM.wingmen.getFirstWingmanNumber() }, TUM.wingmen.getFirstWingmanCallsign(), delayRadioAnswer) TUM.radio.playForAll("pilotWingmanOrbit", { TUM.wingmen.getFirstWingmanNumber() }, TUM.wingmen.getFirstWingmanCallsign(), delayRadioAnswer)
@@ -292,6 +318,8 @@ do
currentTargetIDorPoint = nil currentTargetIDorPoint = nil
allowWeaponUse(wingmenCtrl, false, false) allowWeaponUse(wingmenCtrl, false, false)
-- setWingmenAltitude(player:getPoint().y)
setWingmenAltitude()
wingmenCtrl:setTask(getRejoinTaskTable(formationDistance)) wingmenCtrl:setTask(getRejoinTaskTable(formationDistance))
if not silent then if not silent then
local msgID = "pilotWingmanRejoin" local msgID = "pilotWingmanRejoin"
@@ -389,4 +417,8 @@ do
end end
end end
end end
function TUM.wingmenTasking.resetTaskingParameters()
cruiseAltitudeFraction = 1.0
end
end end