Can now individually control wingmen

This commit is contained in:
Ambroise Garel
2025-07-25 09:33:26 +02:00
parent be154c3540
commit 07cfaf527c
+111 -59
View File
@@ -13,6 +13,8 @@ do
} }
local wingmenGroupID = nil local wingmenGroupID = nil
local wingmenUnitID = {}
local WINGMEN_COUNT = 2 -- TODO: load from setting
local function getWingmenGroup() local function getWingmenGroup()
if TUM.settings.getValue(TUM.settings.id.MULTIPLAYER) then return nil end -- No wingmen in multiplayer if TUM.settings.getValue(TUM.settings.id.MULTIPLAYER) then return nil end -- No wingmen in multiplayer
@@ -45,29 +47,40 @@ do
return false return false
end end
local function getDetectedTargets(attributes) local function getDetectedTargets(wingmanIndex, attributes, maxRangeInNM)
local wingmenGroup = getWingmenGroup() local maxRange = DCSEx.converter.nmToMeters(maxRangeInNM or 1000)
trigger.action.outText("A", 1)
if not wingmenGroup then return {} end
trigger.action.outText("B", 1) local wingmenIndices = {}
local detectedTargets = {} if wingmanIndex then
for _,u in ipairs(wingmenGroup:getUnits()) do wingmenIndices = { wingmanIndex }
trigger.action.outText("C", 1) else
local ctrl = u:getController() for i=1,wingmanIndex do
if ctrl then table.insert(wingmenIndices, i)
trigger.action.outText("D", 1)
local targets = ctrl:getDetectedTargets() -- Controller.Detection.VISUAL, Controller.Detection.OPTIC, Controller.Detection.RADAR, Controller.Detection.RWR, Controller.Detection.IRST)
for _,t in ipairs(targets) do
trigger.action.outText("E", 1)
if isValidTarget(t, attributes) then
trigger.action.outText("F", 1)
table.insert(detectedTargets, t.object)
end
end
end end
end end
-- local wingmenGroup = getWingmenGroup()
-- trigger.action.outText("A", 1)
-- if not wingmenGroup then return {} end
-- trigger.action.outText("B", 1)
-- local detectedTargets = {}
-- for _,u in ipairs(wingmenGroup:getUnits()) do
-- trigger.action.outText("C", 1)
-- local ctrl = u:getController()
-- if ctrl then
-- trigger.action.outText("D", 1)
-- local targets = ctrl:getDetectedTargets() -- Controller.Detection.VISUAL, Controller.Detection.OPTIC, Controller.Detection.RADAR, Controller.Detection.RWR, Controller.Detection.IRST)
-- for _,t in ipairs(targets) do
-- trigger.action.outText("E", 1)
-- if isValidTarget(t, attributes) then
-- trigger.action.outText("F", 1)
-- table.insert(detectedTargets, t.object)
-- end
-- end
-- end
-- end
return detectedTargets return detectedTargets
end end
@@ -138,15 +151,27 @@ do
wingmenCtrl:setTask(taskTable) wingmenCtrl:setTask(taskTable)
end end
local function doWingmenCommandOrbit() local function getWingmanController(wingmanIndex)
if not wingmanIndex then
local wingmenGroup = getWingmenGroup()
if not wingmenGroup then return nil end
return wingmenGroup:getController()
end
if wingmanIndex < 1 or wingmanIndex > #wingmenUnitID then return nil end
local wingmanUnit = DCSEx.world.getUnitByID(wingmenUnitID[wingmanIndex])
if not wingmanUnit then return nil end
return wingmanUnit:getController()
end
local function doWingmenCommandOrbit(args)
local player = world:getPlayer() local player = world:getPlayer()
if not player then return end if not player then return end
TUM.radio.playForAll("playerFlightOrbit", nil, player:getCallsign(), false) TUM.radio.playForAll("playerFlightOrbit", nil, player:getCallsign(), false)
local wingmenGroup = getWingmenGroup() local wingmenCtrl = getWingmanController(args.index)
if not wingmenGroup then return end
local wingmenCtrl = wingmenGroup:getController()
if not wingmenCtrl then return end if not wingmenCtrl then return end
local taskTable = { local taskTable = {
@@ -161,15 +186,13 @@ do
TUM.radio.playForAll("pilotWingmanOrbit", nil, getWingmenCallsign(), true) TUM.radio.playForAll("pilotWingmanOrbit", nil, getWingmenCallsign(), true)
end end
local function doWingmenCommandRejoin() local function doWingmenCommandRejoin(args)
local player = world:getPlayer() local player = world:getPlayer()
if not player then return end if not player then return end
TUM.radio.playForAll("playerFlightRejoin", nil, player:getCallsign(), false) TUM.radio.playForAll("playerFlightRejoin", nil, player:getCallsign(), false)
local wingmenGroup = getWingmenGroup() local wingmenCtrl = getWingmanController(args.index)
if not wingmenGroup then return end
local wingmenCtrl = wingmenGroup:getController()
if not wingmenCtrl then return end if not wingmenCtrl then return end
local taskTable = { local taskTable = {
@@ -185,7 +208,8 @@ do
TUM.radio.playForAll("pilotWingmanRejoin", nil, getWingmenCallsign(), true) TUM.radio.playForAll("pilotWingmanRejoin", nil, getWingmenCallsign(), true)
end end
local function doWingmenOrderEngage(orderID) local function doWingmenCommandEngage(args)
-- , { index = wingmanIndex, attributes = { "Battle airplanes" }, range = 60 }
end end
local function doWingmenCommandReportTargets(attributes) local function doWingmenCommandReportTargets(attributes)
@@ -202,44 +226,54 @@ do
trigger.action.outText(reportText, 5) trigger.action.outText(reportText, 5)
end end
local function doWingmenCommandReportStatus(sponatenousReport) local function doWingmenCommandReportStatus(args)
sponatenousReport = sponatenousReport or false args.noPlayerMessage = args.noPlayerMessage or false
local player = world:getPlayer() local player = world:getPlayer()
if not player then return end if not player then return end
if not sponatenousReport then if not args.noPlayerMessage then
TUM.radio.playForAll("playerFlightReportStatus", nil, player:getCallsign(), false) TUM.radio.playForAll("playerFlightReportStatus", nil, player:getCallsign(), false)
end end
local wingmenGroup = getWingmenGroup() local wingmenGroup = getWingmenGroup()
if not wingmenGroup then return end if not wingmenGroup then return end
local statusMsg = "" local statusMsg = ""
local atLeastOneUnit = false
for i,u in ipairs(wingmenGroup:getUnits()) do for i,u in ipairs(wingmenGroup:getUnits()) do
statusMsg = statusMsg..u:getCallsign():upper() if not args.index or args.index == i then
if u:getLife() >= u:getLife0() then atLeastOneUnit = true
statusMsg = statusMsg.."\n- No damage sustained" statusMsg = statusMsg..u:getCallsign():upper()
else if u:getLife() >= u:getLife0() then
statusMsg = statusMsg.."\n- Aircraft suffered damage" statusMsg = statusMsg.."\n- No damage sustained"
end else
statusMsg = statusMsg.."\n- BRAA from you: "..DCSEx.dcs.getBRAA(u:getPoint(), DCSEx.math.vec3ToVec2(player:getPoint()), true) statusMsg = statusMsg.."\n- Aircraft suffered damage"
statusMsg = statusMsg.."\n- Armament: " end
local ammo = u:getAmmo() statusMsg = statusMsg.."\n- BRAA from you: "..DCSEx.dcs.getBRAA(u:getPoint(), DCSEx.math.vec3ToVec2(player:getPoint()), true)
if #ammo == 0 then statusMsg = statusMsg.."\n- Armament: "
statusMsg = statusMsg.."None" local ammo = u:getAmmo()
else if #ammo == 0 then
for j,a in ipairs(ammo) do statusMsg = statusMsg.."None"
if a.count and a.desc and (a.desc.displayName or a.desc.typeName) then else
local ammoName = a.desc.displayName or a.desc.typeName for j,a in ipairs(ammo) do
if j > 1 then statusMsg = statusMsg..", " end if a.count and a.desc and (a.desc.displayName or a.desc.typeName) then
statusMsg = statusMsg..tostring(a.count).."x "..ammoName local ammoName = a.desc.displayName or a.desc.typeName
if j > 1 then statusMsg = statusMsg..", " end
statusMsg = statusMsg..tostring(a.count).."x "..ammoName
end
end end
end end
end
if i < wingmenGroup:getSize() then statusMsg = statusMsg.."\n\n" end statusMsg = statusMsg.."\n\n"
end
end end
TUM.radio.playForAll("pilotWingmanReportStatus", { statusMsg }, getWingmenCallsign(), not sponatenousReport) if not atLeastOneUnit then return end
if #statusMsg >= 2 then -- Remove trailing "\n\n"
statusMsg = statusMsg:sub(1, #statusMsg - 2)
end
TUM.radio.playForAll("pilotWingmanReportStatus", { statusMsg }, getWingmenCallsign(), not args.noPlayerMessage)
end end
local function createWingmen() local function createWingmen()
@@ -288,6 +322,7 @@ do
return return
end end
wingmenGroupID = groupInfo.groupID wingmenGroupID = groupInfo.groupID
wingmenUnitID = DCSEx.table.deepCopy(groupInfo.unitsID)
TUM.log("Spawned AI wingmen") TUM.log("Spawned AI wingmen")
TUM.radio.playForAll("pilotWingmanRejoin", nil, getWingmenCallsign(), true) TUM.radio.playForAll("pilotWingmanRejoin", nil, getWingmenCallsign(), true)
@@ -302,20 +337,37 @@ do
-- TODO: delayed "returned to base" message from wingmen? -- TODO: delayed "returned to base" message from wingmen?
wingmenGroupID = nil wingmenGroupID = nil
wingmenUnitID = {}
end
local function createWingmanSubMenu(rootPath, wingmanIndex)
local wingmanName = "Flight"
if wingmanIndex then
wingmanName = DCSEx.string.toStringNumber(wingmanIndex + 1, true)
end
local wingmanPath = missionCommands.addSubMenu(wingmanName, rootPath)
-- missionCommands.addCommand("Engage bandits", wingmanPath, doWingmenOrder, TUM.supportWingmen.orderID.ENGAGE_BANDITS)
-- missionCommands.addCommand("Engage air defense", wingmanPath, doWingmenOrder, TUM.supportWingmen.orderID.ENGAGE_BANDITS)
-- missionCommands.addCommand("Engage ground targets", wingmanPath, doWingmenOrder, TUM.supportWingmen.orderID.ENGAGE_BANDITS)
missionCommands.addCommand("Engage bandits", wingmanPath, doWingmenCommandEngage, { index = wingmanIndex, attributes = { "Battle airplanes" }, range = 60 })
missionCommands.addCommand("Report targets", wingmanPath, doWingmenCommandReportTargets, { index = wingmanIndex })
missionCommands.addCommand("Report status", wingmanPath, doWingmenCommandReportStatus, { index = wingmanIndex, noPlayerMessage = false } )
missionCommands.addCommand("Orbit", wingmanPath, doWingmenCommandOrbit, { index = wingmanIndex })
missionCommands.addCommand("Rejoin", wingmanPath, doWingmenCommandRejoin, { index = wingmanIndex })
end end
function TUM.supportWingmen.createMenu() function TUM.supportWingmen.createMenu()
if TUM.settings.getValue(TUM.settings.id.MULTIPLAYER) then return end -- No wingmen in multiplayer if TUM.settings.getValue(TUM.settings.id.MULTIPLAYER) then return end -- No wingmen in multiplayer
if WINGMEN_COUNT == 0 then return end
local rootPath = missionCommands.addSubMenu("Flight") local rootPath = missionCommands.addSubMenu("Wingmen")
missionCommands.addCommand("Engage bandits", rootPath, doWingmenOrder, TUM.supportWingmen.orderID.ENGAGE_BANDITS) createWingmanSubMenu(rootPath, nil)
missionCommands.addCommand("Engage air defense", rootPath, doWingmenOrder, TUM.supportWingmen.orderID.ENGAGE_BANDITS) for i=1,WINGMEN_COUNT do
missionCommands.addCommand("Engage ground targets", rootPath, doWingmenOrder, TUM.supportWingmen.orderID.ENGAGE_BANDITS) createWingmanSubMenu(rootPath, i)
missionCommands.addCommand("Report targets", rootPath, doWingmenCommandReportTargets, nil) end
missionCommands.addCommand("Report status", rootPath, doWingmenCommandReportStatus, false)
missionCommands.addCommand("Orbit", rootPath, doWingmenCommandOrbit, nil)
missionCommands.addCommand("Rejoin", rootPath, doWingmenCommandRejoin, nil)
end end
------------------------------------- -------------------------------------