mirror of
https://github.com/akaAgar/the-universal-mission-for-dcs-world.git
synced 2025-11-25 19:31:01 +00:00
395 lines
14 KiB
Lua
395 lines
14 KiB
Lua
-- ====================================================================================
|
|
-- DCSTOOLS - FUNCTIONS LINKED TO DCS WORLD RULES AND TABLES
|
|
-- ====================================================================================
|
|
-- DCSEx.dcs.getBRAA(point, refPoint, showAltitude, metricSystem, casualFormat)
|
|
-- DCSEx.dcs.getCJTFForCoalition(coalitionID)
|
|
-- DCSEx.dcs.getCoalitionAsString(coalitionID)
|
|
-- DCSEx.dcs.getCoalitionColor(coalitionID, alpha)
|
|
-- DCSEx.dcs.getGroupCenterPoint(group)
|
|
-- DCSEx.dcs.getGroupIDAsNumber(group)
|
|
-- DCSEx.dcs.getNearestObject(refPoint, objectTable)
|
|
-- DCSEx.dcs.getNearestObjects(refPoint, objectTable, maxCount)
|
|
-- DCSEx.dcs.getNearestPoints(refPoint, pointsTable, maxCount)
|
|
-- DCSEx.dcs.getOppositeCoalition(coalitionID)
|
|
-- DCSEx.dcs.getPlayerUnitsInGroup(group)
|
|
-- DCSEx.dcs.getPlayerUnitsInGroupByID(groupID)
|
|
-- DCSEx.dcs.getRadioModulationName(modulationID)
|
|
-- DCSEx.dcs.getObjectIDAsNumber(obj)
|
|
-- DCSEx.dcs.getUnitTypeFromFamily(unitFamily)
|
|
-- DCSEx.dcs.getUnitFamilyForDecade(unitFamily, decade) -- TODO: remove?
|
|
-- ====================================================================================
|
|
|
|
DCSEx.dcs = { }
|
|
|
|
-- TODO: add description and update file header
|
|
function DCSEx.dcs.doNothing()
|
|
end
|
|
|
|
-------------------------------------
|
|
-- Gets a BRAA (bearing, range, altitude, aspect) string about a point
|
|
-- Format is "[bearing to unit] for [distance] at [altitude]"
|
|
-- @param unit A unit
|
|
-- @param refPoint Reference point for the bearing and distance
|
|
-- @param showAltitude Should altitude be displayed?
|
|
-- @param metricSystem Should metric system units be used?
|
|
-- @param casualFormat Should the format be casual ("32nm northeast" instead of "45 for 32")?
|
|
-- @return BRAA, as a string
|
|
-------------------------------------
|
|
function DCSEx.dcs.getBRAA(point, refPoint, showAltitude, metricSystem, casualFormat)
|
|
casualFormat = casualFormat or false
|
|
metricSystem = metricSystem or false
|
|
showAltitude = showAltitude or false
|
|
|
|
if not point.z then point = DCSEx.math.vec2ToVec3(point, "land") end
|
|
if not refPoint.z then refPoint = DCSEx.math.vec2ToVec3(refPoint, "land") end
|
|
|
|
local braa = nil
|
|
|
|
braa = tostring(DCSEx.math.getBearing(point, refPoint, casualFormat))
|
|
|
|
local distance = DCSEx.math.getDistance2D(point, refPoint)
|
|
if metricSystem then
|
|
distance = distance / 1000.0
|
|
else
|
|
distance = DCSEx.converter.metersToNM(distance)
|
|
end
|
|
|
|
if casualFormat then
|
|
if metricSystem then
|
|
braa = math.ceil(distance).."km "..braa
|
|
else
|
|
braa = math.ceil(distance).."nm "..braa
|
|
end
|
|
else
|
|
braa = braa .. " for " .. tostring(math.ceil(distance))
|
|
end
|
|
|
|
if showAltitude then
|
|
local altitude = point.y
|
|
if metricSystem then
|
|
altitude = math.floor(point.y / 100) * 100
|
|
else
|
|
altitude = math.floor(DCSEx.converter.metersToFeet(point.y) / 1000) * 1000
|
|
end
|
|
braa = braa .. " at " .. tostring(altitude)
|
|
if casualFormat then
|
|
if metricSystem then
|
|
braa = braa.."m"
|
|
else
|
|
braa = braa.."ft"
|
|
end
|
|
end
|
|
end
|
|
|
|
return braa
|
|
end
|
|
|
|
-------------------------------------
|
|
-- Returns the CJTF country for a given coalition
|
|
-- @param A coalition ID
|
|
-- @return A country ID (country.id.CJTF_BLUE or country.id.CJTF_RED)
|
|
-------------------------------------
|
|
function DCSEx.dcs.getCJTFForCoalition(coalitionID)
|
|
if coalitionID == coalition.side.RED then return country.id.CJTF_RED end
|
|
|
|
return country.id.CJTF_BLUE
|
|
end
|
|
|
|
-------------------------------------
|
|
-- Returns the name of a coalition, as a string ("blue", "red" or "neutral")
|
|
-- @param A coalition ID
|
|
-- @return A string
|
|
-------------------------------------
|
|
function DCSEx.dcs.getCoalitionAsString(coalitionID)
|
|
if coalitionID == coalition.side.NEUTRAL then return "neutral" end
|
|
if coalitionID == coalition.side.RED then return "red" end
|
|
if coalitionID == coalition.side.BLUE then return "blue" end
|
|
return nil
|
|
end
|
|
|
|
-------------------------------------
|
|
-- Returns the RGBA color table for the given coalition, accoding to NATO symbology colors
|
|
-- @param coalitionID A coalition side
|
|
-- @param alpha (optional) Alpha. Default is 1
|
|
-- @return A RGBA color table
|
|
-------------------------------------
|
|
function DCSEx.dcs.getCoalitionColor(coalitionID, alpha)
|
|
alpha = alpha or 1.0
|
|
|
|
if coalitionID == coalition.side.RED then return {0.97, 0.52, 0.51, alpha}
|
|
elseif coalitionID == coalition.side.BLUE then return {0.52, 0.87, 0.99, alpha}
|
|
else
|
|
return {0.5, 0.5, 0.5, alpha}
|
|
end
|
|
end
|
|
|
|
-- TODO: description
|
|
function DCSEx.dcs.getFirstUnitCallsign(group)
|
|
if not group then return nil end
|
|
|
|
local units = group:getUnits()
|
|
if not units then return nil end
|
|
|
|
local unit0 = units[1]
|
|
if not unit0 then return nil end
|
|
return unit0:getCallsign()
|
|
end
|
|
|
|
-------------------------------------
|
|
-- Returns a vec3 point at the center of all units of a group
|
|
-- @param group A group object
|
|
-- @return A vec3
|
|
-------------------------------------
|
|
function DCSEx.dcs.getGroupCenterPoint(group)
|
|
if not group then return nil end
|
|
local units = group:getUnits()
|
|
if not units or #units == 0 then return nil end
|
|
|
|
local centerPoint = { x = 0, y = 0, z = 0}
|
|
for _,u in pairs(units) do
|
|
local uPoint = u:getPoint()
|
|
centerPoint.x = centerPoint.x + uPoint.x
|
|
centerPoint.y = centerPoint.y + uPoint.y
|
|
centerPoint.z = centerPoint.z + uPoint.z
|
|
end
|
|
|
|
centerPoint.x = centerPoint.x / #units
|
|
centerPoint.y = centerPoint.y / #units
|
|
centerPoint.z = centerPoint.z / #units
|
|
|
|
return centerPoint
|
|
end
|
|
|
|
-------------------------------------
|
|
-- Returns the ID of a group as a number (here to fix a bug where sometimes ID is returned as a string)
|
|
-- @param group A group table
|
|
-- @return An ID (as an number) or nil if group is nil or has no ID
|
|
-------------------------------------
|
|
function DCSEx.dcs.getGroupIDAsNumber(group)
|
|
if not group then
|
|
return nil
|
|
end
|
|
|
|
return tonumber(group:getID())
|
|
end
|
|
|
|
-------------------------------------
|
|
-- Returns the object nearest (in a 2D plane) from a given point
|
|
-- @param refPoint A reference point, as a vec2 or vec3
|
|
-- @param objectTable A table of DCS objects
|
|
-- @return The object nearest from the point, or nil if no object was found
|
|
-------------------------------------
|
|
function DCSEx.dcs.getNearestObject(refPoint, objectTable)
|
|
local nearestObjects = DCSEx.dcs.getNearestObjects(refPoint, objectTable, 1)
|
|
if #nearestObjects == 0 then return nil end
|
|
return nearestObjects[1]
|
|
end
|
|
|
|
-------------------------------------
|
|
-- Returns the nearest objects (in a 2D plane) from a given point
|
|
-- @param refPoint A reference point, as a vec2 or vec3
|
|
-- @param objectTable A table of DCS objects
|
|
-- @param maxCount (optional) Maximum number of objects to return
|
|
-- @return A table of objects, sorted by distance
|
|
-------------------------------------
|
|
function DCSEx.dcs.getNearestObjects(refPoint, objectTable, maxCount)
|
|
if not refPoint then return DCSEx.table.deepCopy(objectTable) end
|
|
|
|
refPoint = DCSEx.math.vec3ToVec2(refPoint)
|
|
local sortedObjects = {}
|
|
local sortedKeys = {}
|
|
|
|
for i,o in pairs(objectTable) do
|
|
local distance = DCSEx.math.getDistance2D(refPoint, o:getPoint())
|
|
sortedObjects[distance] = i
|
|
table.insert(sortedKeys, distance)
|
|
end
|
|
|
|
table.sort(sortedKeys)
|
|
|
|
local sortedList = {}
|
|
for _,v in ipairs(sortedKeys) do
|
|
if maxCount and #sortedList >= maxCount then break end
|
|
table.insert(sortedList, objectTable[sortedObjects[v]])
|
|
end
|
|
|
|
return sortedList
|
|
end
|
|
|
|
-------------------------------------
|
|
-- Returns the nearest points (in a 2D plane) from a given point
|
|
-- @param refPoint A reference point, as a vec2 or vec3
|
|
-- @param objectTable A table of points (vec2 or vec3)
|
|
-- @param maxCount (optional) Maximum number of points to return
|
|
-- @return A table of points, sorted by distance
|
|
-------------------------------------
|
|
function DCSEx.dcs.getNearestPoints(refPoint, pointsTable, maxCount)
|
|
if not refPoint then return DCSEx.table.deepCopy(pointsTable) end
|
|
|
|
refPoint = DCSEx.math.vec3ToVec2(refPoint)
|
|
local sortedPoints = {}
|
|
local sortedKeys = {}
|
|
|
|
for i,pt in pairs(pointsTable) do
|
|
local distance = DCSEx.math.getDistance2D(refPoint, pt)
|
|
sortedPoints[distance] = i
|
|
table.insert(sortedKeys, distance)
|
|
end
|
|
|
|
table.sort(sortedKeys)
|
|
|
|
local sortedList = {}
|
|
for _,v in ipairs(sortedKeys) do
|
|
if maxCount and #sortedList >= maxCount then break end
|
|
table.insert(sortedList, pointsTable[sortedPoints[v]])
|
|
end
|
|
|
|
return sortedList
|
|
end
|
|
|
|
-------------------------------------
|
|
-- Returns the coalition opposed to the provided coalition (coalition.side.NEUTRAL still returns NEUTRAL)
|
|
-- @param group A coalition
|
|
-- @return Another coalition
|
|
-------------------------------------
|
|
function DCSEx.dcs.getOppositeCoalition(coalitionID)
|
|
if coalitionID == coalition.side.RED then return coalition.side.BLUE end
|
|
if coalitionID == coalition.side.BLUE then return coalition.side.RED end
|
|
return coalition.side.NEUTRAL
|
|
end
|
|
|
|
-------------------------------------
|
|
-- Returns all player-controlled units in a group
|
|
-- @param group A group object
|
|
-- @return A table of unit objects
|
|
-------------------------------------
|
|
function DCSEx.dcs.getPlayerUnitsInGroup(group)
|
|
if not group then return nil end
|
|
local units = group:getUnits()
|
|
if not units then return { } end
|
|
|
|
local players = {}
|
|
for _,u in pairs(units) do
|
|
if u:getPlayerName() then
|
|
table.insert(players, u)
|
|
end
|
|
end
|
|
|
|
return players
|
|
end
|
|
|
|
-------------------------------------
|
|
-- Returns all player-controlled units in the group with the given ID
|
|
-- @param groupID A group ID
|
|
-- @return A table of unit objects
|
|
-------------------------------------
|
|
function DCSEx.dcs.getPlayerUnitsInGroupByID(groupID)
|
|
return DCSEx.dcs.getPlayerUnitsInGroup(DCSEx.world.getGroupByID(groupID))
|
|
end
|
|
|
|
-------------------------------------
|
|
-- Returns a radio modulation type as a string
|
|
-- @param modulationID A modulation ID (from radio.modulation enum)
|
|
-- @return A string
|
|
-------------------------------------
|
|
function DCSEx.dcs.getRadioModulationName(modulationID)
|
|
if modulationID == radio.modulation.FM then return "FM" end
|
|
return "AM"
|
|
end
|
|
|
|
-------------------------------------
|
|
-- Returns a remplacement unit family for given family if it's not available in this decade (e.g. SAMs in the 1940s). Else returns the original family.
|
|
-- @param unitFamily An unit family
|
|
-- @param decade (optional) A decade, or the current decade from env.mission.date.Year
|
|
-- @return An unit family
|
|
-------------------------------------
|
|
function DCSEx.dcs.getUnitFamilyForDecade(unitFamily, decade)
|
|
-- TODO
|
|
-- decade = decade or envMission.getDecade()
|
|
|
|
-- if decade < 1990 then
|
|
-- if unitFamily == DCSEx.enums.unitFamily.UAVs then
|
|
-- unitFamily = DCSEx.enums.unitFamily.AttackHelicopters
|
|
-- end
|
|
-- end
|
|
|
|
-- if decade < 1970 then
|
|
-- if unitFamily == DCSEx.enums.unitFamily.AWACS then
|
|
-- unitFamily = DCSEx.enums.unitFamily.Transports
|
|
-- elseif unitFamily == DCSEx.enums.unitFamily.SAMShort then
|
|
-- unitFamily = DCSEx.enums.unitFamily.MobileAAA
|
|
-- elseif unitFamily == DCSEx.enums.unitFamily.SAMShortIR then
|
|
-- unitFamily = DCSEx.enums.unitFamily.MobileAAA
|
|
-- end
|
|
-- end
|
|
|
|
-- if decade < 1960 then
|
|
-- if unitFamily == DCSEx.enums.unitFamily.AttackHelicopters then
|
|
-- unitFamily = DCSEx.enums.unitFamily.Fighters
|
|
-- elseif unitFamily == DCSEx.enums.unitFamily.MANPADS then
|
|
-- unitFamily = DCSEx.enums.unitFamily.Infantry
|
|
-- elseif unitFamily == DCSEx.enums.unitFamily.SAMLong then
|
|
-- unitFamily = DCSEx.enums.unitFamily.StaticAAA
|
|
-- elseif unitFamily == DCSEx.enums.unitFamily.SAMMedium then
|
|
-- unitFamily = DCSEx.enums.unitFamily.StaticAAA
|
|
-- elseif unitFamily == DCSEx.enums.unitFamily.SSMissiles then
|
|
-- unitFamily = DCSEx.enums.unitFamily.Artillery
|
|
-- elseif unitFamily == DCSEx.enums.unitFamily.TransportHelicopters then
|
|
-- unitFamily = DCSEx.enums.unitFamily.Transports
|
|
-- end
|
|
-- end
|
|
|
|
-- if decade < 1950 then
|
|
-- if unitFamily == DCSEx.enums.unitFamily.MobileAAA then
|
|
-- unitFamily = DCSEx.enums.unitFamily.APC
|
|
-- elseif unitFamily == DCSEx.enums.unitFamily.Tankers then
|
|
-- unitFamily = DCSEx.enums.unitFamily.Transports
|
|
-- end
|
|
-- end
|
|
|
|
return unitFamily
|
|
end
|
|
|
|
-- TODO: description
|
|
function DCSEx.dcs.getUnitTypeFromFamily(unitFamily)
|
|
return math.floor(unitFamily / 100)
|
|
end
|
|
|
|
-------------------------------------
|
|
-- Returns the ID of an object as a number (here to fix a bug where sometimes ID is returned as a string)
|
|
-- @param obj An object (unit, static object...)
|
|
-- @return An ID (as an number) or nil if unit is nil or has no ID
|
|
-------------------------------------
|
|
function DCSEx.dcs.getObjectIDAsNumber(obj)
|
|
if not obj then return nil end
|
|
return tonumber(obj:getID())
|
|
end
|
|
|
|
-- TODO: description & file header
|
|
function DCSEx.dcs.loadMission(fileName)
|
|
net.dostring_in("mission", string.format("a_load_mission(\"%s\")", fileName))
|
|
end
|
|
|
|
-- TODO: description & file header
|
|
-- function DCSEx.dcs.isMultiplayer()
|
|
-- if #net.get_player_list() > 0 then return true end
|
|
-- if dcs and dcs.isServer() == true then return true end
|
|
-- return false
|
|
-- end
|
|
|
|
-- TODO: a_end_mission
|
|
|
|
-- TODO: description & file header
|
|
function DCSEx.dcs.outPicture(fileName, durationSeconds, clearView, startDelay, horizontalAlign, verticalAlign, size, sizeUnits)
|
|
clearView = clearView or false
|
|
startDelay = startDelay or 0
|
|
horizontalAlign = horizontalAlign or 1
|
|
verticalAlign = verticalAlign or 1
|
|
size = size or 100
|
|
sizeUnits = sizeUnits or 0
|
|
|
|
if clearView then clearView = "true" else clearView = "false" end
|
|
|
|
net.dostring_in("mission", string.format("a_out_picture(getValueResourceByKey(\"%s\"), %d, %s, %d, \"%d\", \"%d\", %d, \"%d\")", fileName, durationSeconds, clearView, startDelay, horizontalAlign, verticalAlign, size, sizeUnits))
|
|
end
|