-- ==================================================================================== -- TUM.WINGMEN - HANDLES THE WINGMEN'S CONTACTS -- ==================================================================================== -- ==================================================================================== TUM.wingmenContacts = {} do local CONTACT_REPORT_INTERVAL = 8 -- Called AT MOST every 15 seconds, so 6 means "AT MOST every two minutes" local knownGroupsID = {} local newGroupsID = {} local ticksLeftBeforeContactReport = CONTACT_REPORT_INTERVAL local function getGroupDetectionRange(grp) if not grp then return 0.0 end local gCateg = Group.getCategory(grp) -- Take into account better sensors (radars, TGPs...) in later periods local detectionRangeMultiplier = 1.0 if TUM.settings.getValue(TUM.settings.id.TIME_PERIOD) == DCSEx.enums.timePeriod.MODERN then detectionRangeMultiplier = 2.0 elseif TUM.settings.getValue(TUM.settings.id.TIME_PERIOD) == DCSEx.enums.timePeriod.COLD_WAR then detectionRangeMultiplier = 1.5 elseif TUM.settings.getValue(TUM.settings.id.TIME_PERIOD) == DCSEx.enums.timePeriod.VIETNAM_WAR then detectionRangeMultiplier = 1.25 end local detectionRange = DCSEx.converter.nmToMeters(15 * detectionRangeMultiplier) if gCateg == Group.Category.AIRPLANE then detectionRange = DCSEx.converter.nmToMeters(35 * detectionRangeMultiplier) elseif gCateg == Group.Category.SHIP then detectionRange = DCSEx.converter.nmToMeters(25 * detectionRangeMultiplier) local onlySpeedboats = true for _,u in ipairs(grp:getUnits()) do if u:getTypeName() ~= "speedboat" then onlySpeedboats = false end end if onlySpeedboats then detectionRange = detectionRange / 8 end -- Speedboats are HARD to spot elseif gCateg == Group.Category.GROUND then local onlyInfantry = true for _,u in ipairs(grp:getUnits()) do if not u:hasAttribute("Infantry") then onlyInfantry = false end end if onlyInfantry then detectionRange = detectionRange / 8 end -- Infantry is HARD to spot end return detectionRange end function TUM.wingmenContacts.clearKnownContacts() knownGroupsID = {} newGroupsID = {} ticksLeftBeforeContactReport = CONTACT_REPORT_INTERVAL end function TUM.wingmenContacts.getContacts(groupCategory) if TUM.settings.getValue(TUM.settings.id.MULTIPLAYER) then return {} end -- No wingmen in multiplayer if TUM.mission.getStatus() == TUM.mission.status.NONE then return {} end local wingmenGroup = TUM.wingmen.getGroup() if not wingmenGroup then return {} end local searchPoint = DCSEx.world.getGroupCenter(wingmenGroup) local detectedTargets = {} local allGroups = coalition.getGroups(TUM.settings.getEnemyCoalition(), groupCategory) for _,g in ipairs(allGroups) do local gID = g:getID() if g:isExist() and g:getSize() > 0 then local gPos = DCSEx.world.getGroupCenter(g) local gCateg = Group.getCategory(g) local detectionRange = getGroupDetectionRange(g) local distanceToGroup = DCSEx.math.getDistance2D(gPos, searchPoint) if distanceToGroup <= detectionRange then -- Check if wingman group is in detection range if not DCSEx.table.contains(knownGroupsID, gID) then table.insert(knownGroupsID, gID) table.insert(newGroupsID, gID) end local groupInfo = { id = gID, point2 = gPos, size = g:getSize(), type = "contact" } if gCateg == Group.Category.AIRPLANE or gCateg == Group.Category.HELICOPTER then -- if distanceToGroup < detectionRange / 2 then groupInfo.type = Library.objectNames.get(g:getUnit(1)) -- else -- groupInfo.type = Library.objectNames.getGenericGroup(g) -- end else groupInfo.type = Library.objectNames.getGenericGroup(g) end table.insert(detectedTargets, groupInfo) end end end return detectedTargets end function TUM.wingmenContacts.getContactsAsReportString(groupCategory, giveRelativePosition, newContactsOnly) giveRelativePosition = giveRelativePosition or false newContactsOnly = newContactsOnly or false if TUM.settings.getValue(TUM.settings.id.MULTIPLAYER) then return nil end -- No wingmen in multiplayer local contacts = TUM.wingmenContacts.getContacts(groupCategory) if not contacts or #contacts == 0 then return nil end local refPoint = DCSEx.world.getGroupCenter(TUM.wingmen.getGroup()) local reportText = "" for _,t in ipairs(contacts) do if not newContactsOnly or DCSEx.table.contains(newGroupsID, t.id) then reportText = reportText.."\n - "..tostring(t.size).."x "..t.type if refPoint and giveRelativePosition then reportText = reportText..", "..DCSEx.dcs.getBRAA(t.point2, refPoint, false, false, false) end end end return reportText end ---------------------------------------------------------- -- Called on every mission update tick (every 10-20 seconds) -- @return True if something was done this tick, false otherwise ---------------------------------------------------------- function TUM.wingmenContacts.onClockTick() if TUM.settings.getValue(TUM.settings.id.MULTIPLAYER) then return false end -- No wingmen in multiplayer if TUM.mission.getStatus() == TUM.mission.status.NONE then return false end TUM.wingmenContacts.getContacts() -- Check for new contacts, just in case if #newGroupsID > 0 then -- New contacts found, alert the player! local newContactsReportString = TUM.wingmenContacts.getContactsAsReportString(nil, true, true) TUM.radio.playForAll("pilotWingmanReportContactsNew", { TUM.wingmen.getFirstWingmanNumber(), newContactsReportString }, TUM.wingmen.getFirstWingmanCallsign(), false) newGroupsID = {} if ticksLeftBeforeContactReport < math.floor(CONTACT_REPORT_INTERVAL / 2) then ticksLeftBeforeContactReport = math.floor(CONTACT_REPORT_INTERVAL / 2) end return true end ticksLeftBeforeContactReport = ticksLeftBeforeContactReport - 1 if ticksLeftBeforeContactReport > 0 then return false end ticksLeftBeforeContactReport = CONTACT_REPORT_INTERVAL return TUM.wingmenTasking.commandReportContacts(nil, true, false) end end