mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
Add EWRS plugin.
Fixes https://github.com/Khopa/dcs_liberation/issues/323
This commit is contained in:
parent
2d7fc33726
commit
a2f218d56d
@ -4,6 +4,8 @@ Saves from 2.3 are not compatible with 2.4.
|
||||
|
||||
## Features/Improvements
|
||||
|
||||
* **[Plugins]** [The EWRS plugin](https://github.com/Bob7heBuilder/EWRS) is now included.
|
||||
|
||||
## Fixes
|
||||
|
||||
# 2.3.2
|
||||
|
||||
21
resources/plugins/ewrs/LICENSE
Normal file
21
resources/plugins/ewrs/LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Bob7heBuilder
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
830
resources/plugins/ewrs/ewrs.lua
Normal file
830
resources/plugins/ewrs/ewrs.lua
Normal file
@ -0,0 +1,830 @@
|
||||
--[[
|
||||
Early Warning Radar Script - 1.5.3 - 07/11/2016
|
||||
|
||||
Allows use of units with radars to provide Bearing Range and Altitude information via text display to player aircraft
|
||||
|
||||
Features:
|
||||
- Uses in-game radar information to detect targets so terrain masking, beaming, low altitude flying, etc is effective for avoiding detection
|
||||
- Dynamic. If valid units with radar are created during a mission (eg. via chopper with CTLD), they will be added to the EWRS radar network
|
||||
- Can allow / disable BRA messages to fighters or sides
|
||||
- Uses player aircraft or mission bullseye for BRA reference, can be changed via F10 radio menu or restricted to one reference in the script settings
|
||||
- Can switch between imperial (feet, knots, NM) or metric (meters, km/h, km) measurements using F10 radio menu
|
||||
- Ability to change the message display time and automated update interval
|
||||
- Can choose to disable automated messages and allow players to request BRA from F10 menu
|
||||
- Can allow players to request Bogey Dope at any time through F10 radio menu
|
||||
|
||||
Built and Tested in DCS 1.5 - See https://github.com/Bob7heBuilder/EWRS for the latest version
|
||||
|
||||
This script uses MIST 4.0.57 or later - https://github.com/mrSkortch/MissionScriptingTools
|
||||
|
||||
At the moment, because of limitations within DCS to not show messages to individual units, the reference, measurements, and messages
|
||||
are done per group. So a group of 4 fighters will each receive 4 BRA messages. Each message however, will have the player's name
|
||||
in it, that its refering to. Its unfortunate, but nothing I can do about it.
|
||||
|
||||
Changes:
|
||||
- 1.3 - Added Option to allow picture report to be requested thru F10 menu instead of an automated display
|
||||
- Fixed bug where a known unit type would sometimes still display as ???
|
||||
- 1.4 - Added setting to be able to limit the amount of threats displayed in a picture report
|
||||
- Added option to enable Bogey Dopes
|
||||
* Mission designer can turn on / off in script settings
|
||||
* Pilots can request thru the F10 menu and it will show the BRA to the nearest hostile aircraft that has
|
||||
been detected. It will always reference the requesting pilot's own aircraft.
|
||||
- Finally implemented a cleaner workaround for some ground units being detected and listed in picture report
|
||||
- 1.4.1 - Added some ships to search radar list, you will need to remove the comment markers (--) at the start of the line to activate
|
||||
- 1.5 - Added ability to request picture of friendly aircraft positions referencing your own aircraft - Mission designer chooses if this feature is active or not
|
||||
- 1.5.1 - Added Gazelle to acCategories
|
||||
- 1.5.2 - Added F5E to acCategories
|
||||
- 1.5.3 - Fixed bug with maxThreatDisplay set at 0 not displaying any threats
|
||||
- Added Mistral Gazelle
|
||||
- Added C-101CC
|
||||
]]
|
||||
|
||||
ewrs = {} --DO NOT REMOVE
|
||||
ewrs.HELO = 1
|
||||
ewrs.ATTACK = 2
|
||||
ewrs.FIGHTER = 3
|
||||
|
||||
----SCRIPT OPTIONS----
|
||||
|
||||
ewrs.messageUpdateInterval = 30 --How often EWRS will update automated BRA messages (seconds)
|
||||
ewrs.messageDisplayTime = 25 --How long EWRS BRA messages will show for (seconds)
|
||||
ewrs.restrictToOneReference = false -- Disables the ability to change the BRA calls from pilot's own aircraft or bullseye. If this is true, set ewrs.defaultReference to the option you want to restrict to.
|
||||
ewrs.defaultReference = "self" --The default reference for BRA calls - can be changed via f10 radio menu if ewrs.restrictToOneReference is false (self or bulls)
|
||||
ewrs.defaultMeasurements = "imperial" --Default measurement units - can be changed via f10 radio menu (imperial or metric)
|
||||
ewrs.disableFightersBRA = false -- disables BRA messages to fighters when true
|
||||
ewrs.enableRedTeam = true -- enables / disables EWRS for the red team
|
||||
ewrs.enableBlueTeam = true -- enables / disables EWRS for the blue team
|
||||
ewrs.disableMessageWhenNoThreats = true -- disables message when no threats are detected - Thanks Rivvern - NOTE: If using ewrs.onDemand = true, this has no effect
|
||||
ewrs.useImprovedDetectionLogic = true --this makes the messages more realistic. If the radar doesn't know the type or distance to the detected threat, it will be reflected in the picture report / BRA message
|
||||
ewrs.onDemand = false --Setting to true will disable the automated messages to everyone and will add an F10 menu to get picture / BRA message.
|
||||
ewrs.maxThreatDisplay = 5 -- Max amounts of threats to display on picture report (0 will display all)
|
||||
ewrs.allowBogeyDope = true -- Allows pilots to request a bogey dope even with the automated messages running. It will display only the cloest threat, and will always reference the players own aircraft.
|
||||
ewrs.allowFriendlyPicture = true -- Allows pilots to request picture of friendly aircraft
|
||||
ewrs.maxFriendlyDisplay = 5 -- Limits the amount of friendly aircraft shown on friendly picture
|
||||
|
||||
--[[
|
||||
Units with radar to use as part of the EWRS radar network
|
||||
If you want to shorten the range of SAM radar detection, use their track radars instead of their search radars
|
||||
NOTE that track radars require a search radar to detect targets (but the search radars do not need to be included in the list)
|
||||
I haven't tested detection with ships (that have radar), but should work.
|
||||
]]
|
||||
ewrs.validSearchRadars = {
|
||||
"p-10 s125 sr", --SA-3 Search Radar
|
||||
"Kub 1S91 str", --SA-6 Search and Track Radar
|
||||
"S-300PS 64H6E sr", --SA-10 Search Radar
|
||||
"S-300 PS 40B6MD sr", --SA-10 Search Radar
|
||||
"SA-11 Buk SR 9518M1", --SA-11 Search Radar
|
||||
"55G6 EWR", --Early Warning Radar
|
||||
"1L13 EWR", --Early Warning Radar
|
||||
"A-50", --AWACS
|
||||
"E-2D", --AWACS
|
||||
"E-3A", --AWACS
|
||||
"Roland Radar", --Roland Search Radar
|
||||
"Hawk sr", --Hawk SAM Search Radar
|
||||
"Patriot str", --Patriot SAM Search and Track Radar
|
||||
|
||||
--Ships - I've left these commented out because I don't know which ones have radar
|
||||
--and which ones don't. Just remove the comment to activate them (the '--' at the start of the line)
|
||||
|
||||
--"MOSCOW", -- CG 1164 Moskva
|
||||
--"TICONDEROG", -- CG-60 Normandy
|
||||
--"PIOTR", -- CGN 1144.2 Pyotr Velikiy
|
||||
--"KUZNECOW", -- CV 1143.5 Admiral Kuzentsov
|
||||
--"VINSON", -- CVN-70 Carl Vinson
|
||||
--"REZKY", -- FF 1135M Rezky
|
||||
--"NEUSTRASH", -- FFG 11540 Neustrashimy
|
||||
--"PERRY", -- FFG-7CL Oliver Hazzard Perry
|
||||
--"ALBATROS", -- FFL 1124.4 Grisha
|
||||
--"MOLNIYA", -- FSG 1241.1MP Molniya
|
||||
}
|
||||
|
||||
--[[
|
||||
Aircraft Type ENUMs
|
||||
This is used to restrict BRA messages to fighters
|
||||
Change the ewrs.TYPE for each aircraft (in ewrs.acCategories) to suit your needs
|
||||
For now, BRA will be displayed to everyone unless ewrs.disableFightersBRA is true.
|
||||
When this is true, anything in the list below that == ewrs.FIGHTER will NOT receive BRA messages
|
||||
]]
|
||||
ewrs.acCategories = { --Have I left anything out? Please let me know if I have
|
||||
[ "A-10A" ] = ewrs.ATTACK ,
|
||||
[ "A-10C" ] = ewrs.ATTACK ,
|
||||
[ "Bf-109K-4" ] = ewrs.ATTACK ,
|
||||
[ "C-101EB" ] = ewrs.ATTACK ,
|
||||
[ "C-101CC" ] = ewrs.ATTACK ,
|
||||
[ "F-15C" ] = ewrs.FIGHTER ,
|
||||
[ "F-5E-3" ] = ewrs.ATTACK ,
|
||||
[ "FW-190D9" ] = ewrs.ATTACK ,
|
||||
[ "F-86F Sabre" ] = ewrs.FIGHTER ,
|
||||
[ "Hawk" ] = ewrs.ATTACK ,
|
||||
[ "Ka-50" ] = ewrs.HELO ,
|
||||
[ "L-39C" ] = ewrs.ATTACK ,
|
||||
[ "L-39ZA" ] = ewrs.ATTACK ,
|
||||
[ "Mi-8MT" ] = ewrs.HELO ,
|
||||
[ "MiG-15bis" ] = ewrs.ATTACK ,
|
||||
[ "MiG-21Bis" ] = ewrs.ATTACK ,
|
||||
[ "MiG-29A" ] = ewrs.FIGHTER ,
|
||||
[ "MiG-29S" ] = ewrs.FIGHTER ,
|
||||
[ "M-2000C" ] = ewrs.FIGHTER ,
|
||||
[ "P-51D" ] = ewrs.ATTACK ,
|
||||
[ "SA342M" ] = ewrs.HELO ,
|
||||
[ "SA342L" ] = ewrs.HELO ,
|
||||
[ "SA342Mistral" ] = ewrs.HELO ,
|
||||
[ "Su-25" ] = ewrs.ATTACK ,
|
||||
[ "Su-25T" ] = ewrs.ATTACK ,
|
||||
[ "Su-27" ] = ewrs.FIGHTER ,
|
||||
[ "Su-33" ] = ewrs.FIGHTER ,
|
||||
[ "TF-51D" ] = ewrs.ATTACK ,
|
||||
[ "UH-1H" ] = ewrs.HELO ,
|
||||
}
|
||||
|
||||
----END OF SCRIPT OPTIONS----
|
||||
|
||||
|
||||
----INTERNAL FUNCTIONS ***** Be Careful changing things below here ***** ----
|
||||
|
||||
|
||||
function ewrs.getDistance(obj1PosX, obj1PosZ, obj2PosX, obj2PosZ)
|
||||
local xDiff = obj1PosX - obj2PosX
|
||||
local yDiff = obj1PosZ - obj2PosZ
|
||||
return math.sqrt(xDiff * xDiff + yDiff * yDiff) -- meters
|
||||
end
|
||||
|
||||
function ewrs.getBearing(obj1PosX, obj1PosZ, obj2PosX, obj2PosZ)
|
||||
local bearing = math.atan2(obj2PosZ - obj1PosZ, obj2PosX - obj1PosX)
|
||||
if bearing < 0 then
|
||||
bearing = bearing + 2 * math.pi
|
||||
end
|
||||
bearing = bearing * 180 / math.pi
|
||||
return bearing -- degrees
|
||||
end
|
||||
|
||||
function ewrs.getHeading(vec)
|
||||
local heading = math.atan2(vec.z,vec.x)
|
||||
if heading < 0 then
|
||||
heading = heading + 2 * math.pi
|
||||
end
|
||||
heading = heading * 180 / math.pi
|
||||
return heading -- degrees
|
||||
end
|
||||
|
||||
function ewrs.getSpeed(velocity)
|
||||
local speed = math.sqrt(velocity.x^2 + velocity.y^2 + velocity.z^2) --m/s
|
||||
return speed -- m/s
|
||||
end
|
||||
|
||||
function ewrs.update()
|
||||
timer.scheduleFunction(ewrs.update, nil, timer.getTime() + 5)
|
||||
ewrs.buildActivePlayers()
|
||||
ewrs.buildF10Menu()
|
||||
end
|
||||
|
||||
function ewrs.buildThreatTable(activePlayer, bogeyDope)
|
||||
local function sortRanges(v1,v2)
|
||||
return v1.range < v2.range
|
||||
end
|
||||
|
||||
local targets = {}
|
||||
if activePlayer.side == 2 then
|
||||
targets = ewrs.currentlyDetectedRedUnits
|
||||
else
|
||||
targets = ewrs.currentlyDetectedBlueUnits
|
||||
end
|
||||
|
||||
local bogeyDope = bogeyDope or false
|
||||
local referenceX
|
||||
local referenceZ
|
||||
if ewrs.groupSettings[tostring(activePlayer.groupID)].reference == "self" or bogeyDope then
|
||||
local _self = Unit.getByName(activePlayer.unitname)
|
||||
local selfpos = _self:getPosition()
|
||||
referenceX = selfpos.p.x
|
||||
referenceZ = selfpos.p.z
|
||||
else
|
||||
local bullseye = coalition.getMainRefPoint(activePlayer.side)
|
||||
referenceX = bullseye.x
|
||||
referenceZ = bullseye.z
|
||||
end
|
||||
|
||||
local threatTable = {}
|
||||
|
||||
for k,v in pairs(targets) do
|
||||
local velocity = v["object"]:getVelocity()
|
||||
local bogeypos = v["object"]:getPosition()
|
||||
local bogeyType = nil
|
||||
if ewrs.useImprovedDetectionLogic then
|
||||
if v["type"] then
|
||||
bogeyType = v["object"]:getTypeName()
|
||||
else
|
||||
bogeyType = " ??? "
|
||||
end
|
||||
else
|
||||
bogeyType = v["object"]:getTypeName()
|
||||
end
|
||||
|
||||
local bearing = ewrs.getBearing(referenceX,referenceZ,bogeypos.p.x,bogeypos.p.z)
|
||||
local heading = ewrs.getHeading(velocity)
|
||||
local range = ewrs.getDistance(referenceX,referenceZ,bogeypos.p.x,bogeypos.p.z) -- meters
|
||||
local altitude = bogeypos.p.y --meters
|
||||
local speed = ewrs.getSpeed(velocity) --m/s
|
||||
|
||||
if ewrs.groupSettings[tostring(activePlayer.groupID)].measurements == "metric" then
|
||||
range = range / 1000 --change to KM
|
||||
speed = mist.utils.mpsToKmph(speed)
|
||||
--altitude already in meters
|
||||
else
|
||||
range = mist.utils.metersToNM(range)
|
||||
speed = mist.utils.mpsToKnots(speed)
|
||||
altitude = mist.utils.metersToFeet(altitude)
|
||||
end
|
||||
|
||||
if ewrs.useImprovedDetectionLogic then
|
||||
if not v["distance"] then
|
||||
range = ewrs.notAvailable
|
||||
end
|
||||
end
|
||||
|
||||
local j = #threatTable + 1
|
||||
threatTable[j] = {}
|
||||
threatTable[j].unitType = bogeyType
|
||||
threatTable[j].bearing = bearing
|
||||
threatTable[j].range = range
|
||||
threatTable[j].altitude = altitude
|
||||
threatTable[j].speed = speed
|
||||
threatTable[j].heading = heading
|
||||
end
|
||||
|
||||
table.sort(threatTable,sortRanges)
|
||||
|
||||
return threatTable
|
||||
end
|
||||
|
||||
function ewrs.outText(activePlayer, threatTable, bogeyDope, greeting)
|
||||
local status, result = pcall(function()
|
||||
|
||||
local message = {}
|
||||
local altUnits
|
||||
local speedUnits
|
||||
local rangeUnits
|
||||
local bogeyDope = bogeyDope or false
|
||||
if ewrs.groupSettings[tostring(activePlayer.groupID)].measurements == "metric" then
|
||||
altUnits = "m"
|
||||
speedUnits = "Km/h"
|
||||
rangeUnits = "Km"
|
||||
else
|
||||
altUnits = "ft"
|
||||
speedUnits = "Knts"
|
||||
rangeUnits = "NM"
|
||||
end
|
||||
|
||||
if #threatTable >= 1 then
|
||||
local maxThreats = nil
|
||||
local messageGreeting = nil
|
||||
if greeting == nil then
|
||||
if bogeyDope then
|
||||
maxThreats = 1
|
||||
messageGreeting = "EWRS Bogey Dope for: " .. activePlayer.player
|
||||
else
|
||||
if ewrs.maxThreatDisplay == 0 then
|
||||
maxThreats = 999
|
||||
else
|
||||
maxThreats = ewrs.maxThreatDisplay
|
||||
end
|
||||
messageGreeting = "EWRS Picture Report for: " .. activePlayer.player .. " -- Reference: " .. ewrs.groupSettings[tostring(activePlayer.groupID)].reference
|
||||
end
|
||||
else
|
||||
messageGreeting = greeting
|
||||
maxThreats = ewrs.maxFriendlyDisplay
|
||||
end
|
||||
|
||||
--Display table
|
||||
table.insert(message, "\n")
|
||||
table.insert(message, messageGreeting)
|
||||
table.insert(message, "\n\n")
|
||||
table.insert(message, string.format( "%-16s", "TYPE"))
|
||||
table.insert(message, string.format( "%-12s", "BRG"))
|
||||
table.insert(message, string.format( "%-12s", "RNG"))
|
||||
table.insert(message, string.format( "%-21s", "ALT"))
|
||||
table.insert(message, string.format( "%-15s", "SPD"))
|
||||
table.insert(message, string.format( "%-3s", "HDG"))
|
||||
table.insert(message, "\n")
|
||||
|
||||
for k = 1, maxThreats do
|
||||
if threatTable[k] == nil then break end
|
||||
table.insert(message, "\n")
|
||||
table.insert(message, string.format( "%-16s", threatTable[k].unitType))
|
||||
if threatTable[k].range == ewrs.notAvailable then
|
||||
table.insert(message, string.format( "%-12s", " "))
|
||||
table.insert(message, string.format( "%-12s", "POSITION"))
|
||||
table.insert(message, string.format( "%-21s", " "))
|
||||
table.insert(message, string.format( "%-15s", "UNKNOWN"))
|
||||
table.insert(message, string.format( "%-3s", " "))
|
||||
else
|
||||
table.insert(message, string.format( "%03d", threatTable[k].bearing))
|
||||
table.insert(message, string.format( "%8.1f %s", threatTable[k].range, rangeUnits))
|
||||
table.insert(message, string.format( "%9d %s", threatTable[k].altitude, altUnits))
|
||||
table.insert(message, string.format( "%9d %s", threatTable[k].speed, speedUnits))
|
||||
table.insert(message, string.format( " %03d", threatTable[k].heading))
|
||||
end
|
||||
table.insert(message, "\n")
|
||||
end
|
||||
trigger.action.outTextForGroup(activePlayer.groupID, table.concat(message), ewrs.messageDisplayTime)
|
||||
else
|
||||
if (not ewrs.disableMessageWhenNoThreats) or (ewrs.onDemand) and greeting == nil then
|
||||
trigger.action.outTextForGroup(activePlayer.groupID, "\nEWRS Picture Report for: " .. activePlayer.player .. "\n\nNo targets detected", ewrs.messageDisplayTime)
|
||||
end
|
||||
if greeting ~= nil then
|
||||
trigger.action.outTextForGroup(activePlayer.groupID, "\nEWRS Friendly Picture for: " .. activePlayer.player .. "\n\nNo friendlies detected", ewrs.messageDisplayTime)
|
||||
end
|
||||
end
|
||||
end)
|
||||
if not status then
|
||||
env.error(string.format("EWRS outText Error: %s", result))
|
||||
end
|
||||
end
|
||||
|
||||
function ewrs.displayMessageToAll()
|
||||
local status, result = pcall(function()
|
||||
timer.scheduleFunction(ewrs.displayMessageToAll, nil, timer.getTime() + ewrs.messageUpdateInterval)
|
||||
ewrs.findRadarUnits()
|
||||
ewrs.getDetectedTargets()
|
||||
for i = 1, #ewrs.activePlayers do
|
||||
if ewrs.groupSettings[tostring(ewrs.activePlayers[i].groupID)].messages then
|
||||
if ewrs.activePlayers[i].side == 1 and #ewrs.redEwrUnits > 0 or ewrs.activePlayers[i].side == 2 and #ewrs.blueEwrUnits > 0 then
|
||||
ewrs.outText(ewrs.activePlayers[i], ewrs.buildThreatTable(ewrs.activePlayers[i]))
|
||||
end -- if ewrs.activePlayers[i].side == 1 and #ewrs.redEwrUnits > 0 or ewrs.activePlayers[i].side == 2 and #ewrs.blueEwrUnits > 0 then
|
||||
end -- if ewrs.groupSettings[tostring(ewrs.activePlayers[i].groupID)].messages then
|
||||
end -- for i = 1, #ewrs.activePlayers do
|
||||
end)
|
||||
if not status then
|
||||
env.error(string.format("EWRS displayMessageToAll Error: %s", result))
|
||||
end
|
||||
end
|
||||
|
||||
function ewrs.onDemandMessage(args)
|
||||
local status, result = pcall(function()
|
||||
ewrs.findRadarUnits()
|
||||
ewrs.getDetectedTargets()
|
||||
for i = 1, #ewrs.activePlayers do
|
||||
if ewrs.activePlayers[i].groupID == args[1] then
|
||||
ewrs.outText(ewrs.activePlayers[i], ewrs.buildThreatTable(ewrs.activePlayers[i],args[2]),args[2])
|
||||
end
|
||||
end
|
||||
end)
|
||||
if not status then
|
||||
env.error(string.format("EWRS onDemandMessage Error: %s", result))
|
||||
end
|
||||
end
|
||||
|
||||
function ewrs.buildFriendlyTable(friendlyNames,activePlayer)
|
||||
local function sortRanges(v1,v2)
|
||||
return v1.range < v2.range
|
||||
end
|
||||
|
||||
local units = {}
|
||||
for i =1, #friendlyNames do
|
||||
local unit = Unit.getByName(friendlyNames[i])
|
||||
if unit ~= nil and unit:isActive() then
|
||||
|
||||
table.insert(units,unit)
|
||||
else
|
||||
--env.error("Friendly Picture - Unit not found: "..friendlyNames[i]) -- Client Planes that are not active will fall into here.
|
||||
end
|
||||
end
|
||||
|
||||
local _self = Unit.getByName(activePlayer.unitname)
|
||||
local selfpos = _self:getPosition()
|
||||
local referenceX = selfpos.p.x
|
||||
local referenceZ = selfpos.p.z
|
||||
|
||||
local friendlyTable = {}
|
||||
|
||||
for k,v in pairs(units) do
|
||||
local velocity = v:getVelocity()
|
||||
local pos = v:getPosition()
|
||||
local bogeyType = v:getTypeName()
|
||||
if pos.p.x ~= selfpos.p.x and pos.p.z ~= selfpos.p.z then --same position as self, means its you!
|
||||
|
||||
local bearing = ewrs.getBearing(referenceX,referenceZ,pos.p.x,pos.p.z)
|
||||
local heading = ewrs.getHeading(velocity)
|
||||
local range = ewrs.getDistance(referenceX,referenceZ,pos.p.x,pos.p.z) -- meters
|
||||
local altitude = pos.p.y --meters
|
||||
local speed = ewrs.getSpeed(velocity) --m/s
|
||||
|
||||
if ewrs.groupSettings[tostring(activePlayer.groupID)].measurements == "metric" then
|
||||
range = range / 1000 --change to KM
|
||||
speed = mist.utils.mpsToKmph(speed)
|
||||
--altitude already in meters
|
||||
else
|
||||
range = mist.utils.metersToNM(range)
|
||||
speed = mist.utils.mpsToKnots(speed)
|
||||
altitude = mist.utils.metersToFeet(altitude)
|
||||
end
|
||||
|
||||
local j = #friendlyTable + 1
|
||||
friendlyTable[j] = {}
|
||||
friendlyTable[j].unitType = bogeyType
|
||||
friendlyTable[j].bearing = bearing
|
||||
friendlyTable[j].range = range
|
||||
friendlyTable[j].altitude = altitude
|
||||
friendlyTable[j].speed = speed
|
||||
friendlyTable[j].heading = heading
|
||||
else
|
||||
--env.info("Friendly Picture - Found Self")
|
||||
end
|
||||
end
|
||||
|
||||
table.sort(friendlyTable,sortRanges)
|
||||
|
||||
return friendlyTable
|
||||
end
|
||||
|
||||
function ewrs.friendlyPicture(args)
|
||||
local status, result = pcall(function()
|
||||
for i = 1, #ewrs.activePlayers do
|
||||
if ewrs.activePlayers[i].groupID == args[1] then
|
||||
local sideString = nil
|
||||
if ewrs.activePlayers[i].side == 1 then
|
||||
sideString = "[red]"
|
||||
else
|
||||
sideString = "[blue]"
|
||||
end
|
||||
local filter = {sideString.."[helicopter]", sideString.."[plane]"}
|
||||
local friendlies = mist.makeUnitTable(filter) --find a way to do this only once if there is more then 1 person in a group
|
||||
local friendlyTable = ewrs.buildFriendlyTable(friendlies,ewrs.activePlayers[i])
|
||||
local greeting = "EWRS Friendly Picture for: " .. ewrs.activePlayers[i].player
|
||||
ewrs.outText(ewrs.activePlayers[i],friendlyTable,false,greeting)
|
||||
end
|
||||
end
|
||||
end)
|
||||
if not status then
|
||||
env.error(string.format("EWRS friendlyPicture Error: %s", result))
|
||||
end
|
||||
end
|
||||
|
||||
function ewrs.buildActivePlayers()
|
||||
local status, result = pcall(function()
|
||||
local filter = { "[all][plane]","[all][helicopter]"}
|
||||
local all_vecs = mist.makeUnitTable(filter)
|
||||
ewrs.activePlayers = {}
|
||||
for i = 1, #all_vecs do
|
||||
local vec = Unit.getByName(all_vecs[i])
|
||||
if vec ~= nil and Unit.isActive(vec) then
|
||||
playerName = Unit.getPlayerName(vec)
|
||||
local groupID = ewrs.getGroupId(vec)
|
||||
if playerName ~= nil then
|
||||
unitCategory = ewrs.acCategories[Unit.getTypeName(vec)]
|
||||
if ewrs.disableFightersBRA and unitCategory == ewrs.FIGHTER then
|
||||
--DONT DO ANYTHING
|
||||
else
|
||||
local group = Unit.getGroup(vec)
|
||||
if ewrs.enableBlueTeam and Unit.getCoalition(vec) == 2 then
|
||||
ewrs.addPlayer(playerName, groupID, vec)
|
||||
elseif ewrs.enableRedTeam and Unit.getCoalition(vec) == 1 then
|
||||
ewrs.addPlayer(playerName, groupID, vec)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end) -- pcall
|
||||
|
||||
if not status then
|
||||
env.error(string.format("EWRS buildActivePlayers Error: %s", result))
|
||||
end
|
||||
end
|
||||
|
||||
--THANK YOU ciribob http://forums.eagle.ru/showpost.php?p=2499638&postcount=5
|
||||
--And Stonehouse for pointing me there
|
||||
function ewrs.getGroupId(_unit) --Temp fix for client groups not being accessable
|
||||
|
||||
local _unitDB = mist.DBs.unitsById[tonumber(_unit:getID())]
|
||||
if _unitDB ~= nil and _unitDB.groupId then
|
||||
return _unitDB.groupId
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
function ewrs.getGroupCategory(unit)
|
||||
local unitDB = mist.DBs.unitsById[tonumber(unit:getID())]
|
||||
if unitDB ~= nil and unitDB.category then
|
||||
return unitDB.category
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
function ewrs.addPlayer(playerName, groupID, unit )
|
||||
local status, result = pcall(function()
|
||||
local i = #ewrs.activePlayers + 1
|
||||
ewrs.activePlayers[i] = {}
|
||||
ewrs.activePlayers[i].player = playerName
|
||||
ewrs.activePlayers[i].groupID = groupID
|
||||
ewrs.activePlayers[i].unitname = unit:getName()
|
||||
ewrs.activePlayers[i].side = unit:getCoalition()
|
||||
|
||||
-- add default settings to settings table if it hasn't been done yet
|
||||
if ewrs.groupSettings[tostring(groupID)] == nil then
|
||||
ewrs.addGroupSettings(tostring(groupID))
|
||||
end
|
||||
end)
|
||||
if not status then
|
||||
env.error(string.format("EWRS addPlayer Error: %s", result))
|
||||
end
|
||||
end
|
||||
|
||||
-- filters units so ones detected by multiple radar sites still only get listed once
|
||||
-- Filters out anything that isn't a plane or helicopter
|
||||
function ewrs.filterUnits(units)
|
||||
local newUnits = {}
|
||||
for k,v in pairs(units) do
|
||||
local valid = true
|
||||
if v["object"]:getCategory() ~= Object.Category.UNIT then --rare but i've had it detect missiles
|
||||
valid = false
|
||||
end
|
||||
if valid then --another check cause it seems AI radar can detected some ground units
|
||||
local category = ewrs.getGroupCategory(v["object"])
|
||||
if category ~= "plane" and category ~= "helicopter" then valid = false end
|
||||
end
|
||||
|
||||
if valid then
|
||||
for nk,nv in pairs (newUnits) do --recursive loop, can't see a way around this
|
||||
if v["object"]:getName() == nv["object"]:getName() then
|
||||
valid = false
|
||||
--update already found unit incase the first detection(s) didn't know type or distance
|
||||
if v["type"] then
|
||||
nv["type"] = true
|
||||
end
|
||||
if v["distance"] then
|
||||
nv["distance"] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if valid then
|
||||
table.insert(newUnits, v)
|
||||
end
|
||||
end
|
||||
return newUnits
|
||||
end
|
||||
|
||||
function ewrs.getDetectedTargets()
|
||||
if #ewrs.blueEwrUnits > 0 then
|
||||
ewrs.currentlyDetectedRedUnits = ewrs.findDetectedTargets("red")
|
||||
end
|
||||
if #ewrs.redEwrUnits > 0 then
|
||||
ewrs.currentlyDetectedBlueUnits = ewrs.findDetectedTargets("blue")
|
||||
end
|
||||
end
|
||||
|
||||
function ewrs.findDetectedTargets(side)
|
||||
local units = {}
|
||||
local ewrUnits = {}
|
||||
|
||||
if side == "red" then
|
||||
ewrUnits = ewrs.blueEwrUnits
|
||||
elseif side == "blue" then
|
||||
ewrUnits = ewrs.redEwrUnits
|
||||
end
|
||||
|
||||
for n = 1, #ewrUnits do
|
||||
local ewrUnit = Unit.getByName(ewrUnits[n])
|
||||
if ewrUnit ~= nil then
|
||||
local ewrControl = ewrUnit:getGroup():getController()
|
||||
local detectedTargets = ewrControl:getDetectedTargets(Controller.Detection.RADAR)
|
||||
for k,v in pairs (detectedTargets) do
|
||||
table.insert(units, v)
|
||||
end
|
||||
end
|
||||
end
|
||||
return ewrs.filterUnits(units)
|
||||
end
|
||||
|
||||
function ewrs.findRadarUnits()
|
||||
local filter = {}
|
||||
if ewrs.enableBlueTeam and ewrs.enableRedTeam then
|
||||
filter = { "[all][plane]", "[all][vehicle]", "[all][ship]"}
|
||||
elseif ewrs.enableBlueTeam then
|
||||
filter = { "[blue][plane]", "[blue][vehicle]", "[blue][ship]"}
|
||||
elseif ewrs.enableRedTeam then
|
||||
filter = { "[red][plane]", "[red][vehicle]", "[red][ship]"}
|
||||
end
|
||||
local all_vecs = mist.makeUnitTable(filter)
|
||||
local redUnits = {}
|
||||
local blueUnits = {}
|
||||
|
||||
for i = 1, #all_vecs do
|
||||
local vec = Unit.getByName(all_vecs[i])
|
||||
|
||||
if vec ~= nil then
|
||||
if Unit.isActive(vec) then
|
||||
local vec_type = Unit.getTypeName(vec)
|
||||
for n = 1, #ewrs.validSearchRadars do
|
||||
if ewrs.validSearchRadars[n] == vec_type and Unit.getCoalition(vec) == 2 then
|
||||
table.insert(blueUnits, Unit.getName(vec))
|
||||
break
|
||||
end
|
||||
if ewrs.validSearchRadars[n] == vec_type and Unit.getCoalition(vec) == 1 then
|
||||
table.insert(redUnits, Unit.getName(vec))
|
||||
break
|
||||
end
|
||||
end --for n = 1, #ewrs.validSearchRadars do
|
||||
end --if Unit.isActive(vec) then
|
||||
end --if vec ~= nil then
|
||||
end --for i = 1, #all_vecs do
|
||||
ewrs.blueEwrUnits = blueUnits
|
||||
ewrs.redEwrUnits = redUnits
|
||||
end
|
||||
|
||||
function ewrs.addGroupSettings(groupID)
|
||||
ewrs.groupSettings[groupID] = {}
|
||||
ewrs.groupSettings[groupID].reference = ewrs.defaultReference
|
||||
ewrs.groupSettings[groupID].measurements = ewrs.defaultMeasurements
|
||||
ewrs.groupSettings[groupID].messages = true
|
||||
end
|
||||
|
||||
function ewrs.setGroupReference(args)
|
||||
local groupID = args[1]
|
||||
ewrs.groupSettings[tostring(groupID)].reference = args[2]
|
||||
trigger.action.outTextForGroup(groupID,"Reference changed to "..args[2],ewrs.messageDisplayTime)
|
||||
end
|
||||
|
||||
function ewrs.setGroupMeasurements(args)
|
||||
local groupID = args[1]
|
||||
ewrs.groupSettings[tostring(groupID)].measurements = args[2]
|
||||
trigger.action.outTextForGroup(groupID,"Measurement units changed to "..args[2],ewrs.messageDisplayTime)
|
||||
end
|
||||
|
||||
function ewrs.setGroupMessages(args)
|
||||
local groupID = args[1]
|
||||
local onOff
|
||||
if args[2] then onOff = "on" else onOff = "off" end
|
||||
ewrs.groupSettings[tostring(groupID)].messages = args[2]
|
||||
trigger.action.outTextForGroup(groupID,"Picture reports for group turned "..onOff,ewrs.messageDisplayTime)
|
||||
end
|
||||
|
||||
function ewrs.buildF10Menu()
|
||||
local status, result = pcall(function()
|
||||
for i = 1, #ewrs.activePlayers do
|
||||
local groupID = ewrs.activePlayers[i].groupID
|
||||
local stringGroupID = tostring(groupID)
|
||||
if ewrs.builtF10Menus[stringGroupID] == nil then
|
||||
local rootPath = missionCommands.addSubMenuForGroup(groupID, "EWRS")
|
||||
|
||||
if ewrs.allowBogeyDope then
|
||||
missionCommands.addCommandForGroup(groupID, "Request Bogey Dope",rootPath,ewrs.onDemandMessage,{groupID,true})
|
||||
end
|
||||
|
||||
if ewrs.onDemand then
|
||||
missionCommands.addCommandForGroup(groupID, "Request Picture",rootPath,ewrs.onDemandMessage,{groupID})
|
||||
end
|
||||
|
||||
if ewrs.allowFriendlyPicture then
|
||||
missionCommands.addCommandForGroup(groupID, "Request Friendly Picture",rootPath,ewrs.friendlyPicture,{groupID})
|
||||
end
|
||||
|
||||
if not ewrs.restrictToOneReference then
|
||||
local referenceSetPath = missionCommands.addSubMenuForGroup(groupID,"Set GROUP's reference point", rootPath)
|
||||
missionCommands.addCommandForGroup(groupID, "Set to Bullseye",referenceSetPath,ewrs.setGroupReference,{groupID, "bulls"})
|
||||
missionCommands.addCommandForGroup(groupID, "Set to Self",referenceSetPath,ewrs.setGroupReference,{groupID, "self"})
|
||||
end
|
||||
|
||||
local measurementsSetPath = missionCommands.addSubMenuForGroup(groupID,"Set GROUP's measurement units",rootPath)
|
||||
missionCommands.addCommandForGroup(groupID, "Set to Imperial (feet, knts)",measurementsSetPath,ewrs.setGroupMeasurements,{groupID, "imperial"})
|
||||
missionCommands.addCommandForGroup(groupID, "Set to Metric (meters, km/h)",measurementsSetPath,ewrs.setGroupMeasurements,{groupID, "metric"})
|
||||
|
||||
if not ewrs.onDemand then
|
||||
local messageOnOffPath = missionCommands.addSubMenuForGroup(groupID, "Turn Picture Report On/Off",rootPath)
|
||||
missionCommands.addCommandForGroup(groupID, "Message ON", messageOnOffPath, ewrs.setGroupMessages, {groupID, true})
|
||||
missionCommands.addCommandForGroup(groupID, "Message OFF", messageOnOffPath, ewrs.setGroupMessages, {groupID, false})
|
||||
end
|
||||
|
||||
ewrs.builtF10Menus[stringGroupID] = true
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
if not status then
|
||||
env.error(string.format("EWRS buildF10Menu Error: %s", result))
|
||||
end
|
||||
end
|
||||
|
||||
--temp fix for ground units being detected by radar - FIXED
|
||||
--[[ Leaving this here just in case I introduce threat based filtering, saves me writing it again
|
||||
ewrs.validThreats = {
|
||||
["A-10A"] = true,
|
||||
["A-10C"] = true,
|
||||
["A-50"] = true,
|
||||
["AH-1W"] = true,
|
||||
["AH-64A"] = true,
|
||||
["AH-64D"] = true,
|
||||
["An-26B"] = true,
|
||||
["An-30M"] = true,
|
||||
["B-1B"] = true,
|
||||
["B-52H"] = true,
|
||||
["Bf-109K-4"] = true,
|
||||
["C-101CC"] = true,
|
||||
["C-101EB"] = true,
|
||||
["C-130"] = true,
|
||||
["C-17A"] = true,
|
||||
["CH-47D"] = true,
|
||||
["CH-53E"] = true,
|
||||
["E-2D"] = true,
|
||||
["E-2C"] = true,
|
||||
["E-3A"] = true,
|
||||
["F-111F"] = true,
|
||||
["F-117A"] = true,
|
||||
["F-14A"] = true,
|
||||
["F-15C"] = true,
|
||||
["F-15E"] = true,
|
||||
["F-16A"] = true,
|
||||
["F-16A MLU"] = true,
|
||||
["F-16C bl.50"] = true,
|
||||
["F-16C bl.52d"] = true,
|
||||
["F-4E"] = true,
|
||||
["F-5E"] = true,
|
||||
["F-5E-3"] = true,
|
||||
["F-86F Sabre"] = true,
|
||||
["F/A-18A"] = true,
|
||||
["F/A-18C"] = true,
|
||||
["FW-190D9"] = true,
|
||||
["Hawk"] = true,
|
||||
["IL-76MD"] = true,
|
||||
["IL-78M"] = true,
|
||||
["KC-135"] = true,
|
||||
["Ka-27"] = true,
|
||||
["Ka-50"] = true,
|
||||
["Ka-52"] = true,
|
||||
["L-39C"] = true,
|
||||
["L-39ZA"] = true,
|
||||
["M-2000C"] = true,
|
||||
["MQ-9 Reaper"] = true,
|
||||
["Mi-24V"] = true,
|
||||
["Mi-26"] = true,
|
||||
["Mi-28N"] = true,
|
||||
["Mi-8MT"] = true,
|
||||
["MiG-15bis"] = true,
|
||||
["MiG-21Bis"] = true,
|
||||
["MiG-23MLD"] = true,
|
||||
["MiG-25PD"] = true,
|
||||
["MiG-25RBT"] = true,
|
||||
["MiG-27K"] = true,
|
||||
["MiG-29A"] = true,
|
||||
["MiG-29G"] = true,
|
||||
["MiG-29K"] = true,
|
||||
["MiG-29S"] = true,
|
||||
["MiG-31"] = true,
|
||||
["Mirage 2000-5"] = true,
|
||||
["OH-58D"] = true,
|
||||
["P-51D"] = true,
|
||||
["RQ-1A Predator"] = true,
|
||||
["S-3B"] = true,
|
||||
["S-3B Tanker"] = true,
|
||||
["SH-3W"] = true,
|
||||
["SH-60B"] = true,
|
||||
["Su-17M4"] = true,
|
||||
["Su-24M"] = true,
|
||||
["Su-24MR"] = true,
|
||||
["Su-25"] = true,
|
||||
["Su-25T"] = true,
|
||||
["Su-25TM"] = true,
|
||||
["Su-27"] = true,
|
||||
["Su-30"] = true,
|
||||
["Su-33"] = true,
|
||||
["Su-34"] = true,
|
||||
["TF-51D"] = true,
|
||||
["Tornado GR4"] = true,
|
||||
["Tornado IDS"] = true,
|
||||
["Tu-142"] = true,
|
||||
["Tu-160"] = true,
|
||||
["Tu-22M3"] = true,
|
||||
["Tu-95MS"] = true,
|
||||
["UH-1H"] = true,
|
||||
["UH-60A"] = true,
|
||||
["Yak-40"] = true,
|
||||
}
|
||||
]]
|
||||
|
||||
--SCRIPT INIT
|
||||
ewrs.currentlyDetectedRedUnits = {}
|
||||
ewrs.currentlyDetectedBlueUnits = {}
|
||||
ewrs.redEwrUnits = {}
|
||||
ewrs.blueEwrUnits = {}
|
||||
ewrs.activePlayers = {}
|
||||
ewrs.groupSettings = {}
|
||||
ewrs.builtF10Menus = {}
|
||||
ewrs.notAvailable = 999999
|
||||
|
||||
ewrs.update()
|
||||
if not ewrs.onDemand then
|
||||
timer.scheduleFunction(ewrs.displayMessageToAll, nil, timer.getTime() + ewrs.messageUpdateInterval)
|
||||
end
|
||||
trigger.action.outText("EWRS by Steggles is now running",15)
|
||||
env.info("EWRS Running")
|
||||
|
||||
--[[
|
||||
TODO:
|
||||
- Add check on friendly picture to not give one if no AWACS / EWR units are active. Doesn't use radar info anyway. Maybe just leave it to help out people with SA? Feedback Please!!
|
||||
- Clean up functions and arguments from bogeyDope and friendly picture additions
|
||||
- Threat based filtering if theres interest.
|
||||
]]
|
||||
12
resources/plugins/ewrs/plugin.json
Normal file
12
resources/plugins/ewrs/plugin.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"nameInUI": "EWRS",
|
||||
"defaultValue": false,
|
||||
"specificOptions": [],
|
||||
"scriptsWorkOrders": [
|
||||
{
|
||||
"file": "ewrs.lua",
|
||||
"mnemonic": "ewrs"
|
||||
}
|
||||
],
|
||||
"configurationWorkOrders": []
|
||||
}
|
||||
@ -2,5 +2,6 @@
|
||||
"base",
|
||||
"jtacautolase",
|
||||
"skynetiads",
|
||||
"ewrs",
|
||||
"herculescargo"
|
||||
]
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user