mirror of
https://github.com/dcs-retribution/dcs-retribution.git
synced 2025-11-10 15:41:24 +00:00
Support for Carsten's Arty Spotter script (#357)
* Added Cartsens Arty Script * Added Options to Arty script Added all options and for configuration. * Carstens Arty Spotter with options * Finishing touch --------- Co-authored-by: Raffson <Raffson@users.noreply.github.com>
This commit is contained in:
parent
d0a1a01b12
commit
d84a0ebc78
@ -90,5 +90,6 @@ Excellent lua scripts DCS Liberation/Retribution uses as plugins:
|
||||
|
||||
* For the JTAC feature, DCS Retribution embeds Ciribob's JTAC Autolase [script](https://github.com/ciribob/DCS-JTACAutoLaze).
|
||||
* Walder's [Skynet-IADS](https://github.com/walder/Skynet-IADS) is used for Integrated Air Defense System.
|
||||
* Carstens Arty Spotter https://www.digitalcombatsimulator.com/en/files/3339128/ is an amazing force multiplyer to drop the hammer on enemies.
|
||||
|
||||
Please also show some support to these projects !
|
||||
|
||||
@ -20,7 +20,8 @@
|
||||
* **[UX]** Allow changing squadrons in flight's edit dialog
|
||||
* **[Cheats]** Sink/Resurrect carriers instead of showing an error during cheat-capture (use AWCD-cheat to add squadrons upon resurrection)
|
||||
* **[UI/UX]** Allow changing conditions such as Time, Date & Weather
|
||||
* * **[Modding]** Added support for Su-15 Flagon mod (v1.0)
|
||||
* **[Modding]** Added support for Su-15 Flagon mod (v1.0)
|
||||
* **[Plugins]** Support for Carsten's Arty Spotter script
|
||||
|
||||
## Fixes
|
||||
* **[UI/UX]** A-10A flights can be edited again
|
||||
|
||||
723
resources/plugins/arty/CG_ArtySpotter_V1_2a_MP.lua
Normal file
723
resources/plugins/arty/CG_ArtySpotter_V1_2a_MP.lua
Normal file
@ -0,0 +1,723 @@
|
||||
-- Artillery Spotter script - Multiplayer version
|
||||
-- by Carsten Gurk aka Don Rudi
|
||||
|
||||
-- Map for passing settings from Retribution
|
||||
cg_arty_options = {
|
||||
["user_fireDelay"] = 10,
|
||||
["user_quantity"] = 20,
|
||||
["user_spread"] = 50,
|
||||
["user_spottingDistance"] = 15,
|
||||
}
|
||||
|
||||
local version = "MP 1.2"
|
||||
|
||||
-- User configurable variables
|
||||
|
||||
local user_fireDelay = cg_arty_options.user_fireDelay -- time to impcat of the rounds
|
||||
local user_quantity = cg_arty_options.user_quantity -- how many rounds will be fired in a fire for effect task
|
||||
local user_spread = cg_arty_options.user_spread -- impact radius of the rounds during fire for effect
|
||||
local user_spottingDistance = cg_arty_options.user_spottingDistance -- max allowable distance from player to target to prevent cheating. In kilometers.
|
||||
local user_restrictByType = "" -- Restriction by type ("", "helo", etc.)
|
||||
local user_restrictByUnitName = "" -- Restriction by unit name ("", "spotter", etc.), not case sensitive
|
||||
local user_markerPrefix = "" -- Prefix for marker text, for instance "#arty"
|
||||
|
||||
-- end of user block
|
||||
|
||||
-- Script variables
|
||||
|
||||
local SINGLE_ROUND = false -- pilot called single round on marker (from F10 menu)
|
||||
|
||||
local artyCall = 0 -- pilot called arty (from F10 menu)
|
||||
local artyRadius = user_spread -- Artillery Radius
|
||||
local adjustRadius = 20 -- fire adjustment
|
||||
local quantity = 1 -- Rounds expanded
|
||||
local quantity_effect = user_quantity -- Rounds expanded during fire for effect
|
||||
local tntEquivalent = 12 -- TNT equivalent for explosion
|
||||
local fireDelay = user_fireDelay -- delay til artillery fires in seconds
|
||||
|
||||
local firstShotFired = true
|
||||
|
||||
local markerSet = false
|
||||
|
||||
local pos = { x = 0, y = 0, z = 0 }
|
||||
local playerPos = { x = 0, y = 0, z = 0 }
|
||||
|
||||
local target = {}
|
||||
|
||||
local adjustX = 0
|
||||
local adjustZ = 0
|
||||
|
||||
local adjustDistance = 0 -- Adjust fire (from F10 menu)
|
||||
local adjustDirection = 0 -- Adjust fire (from F10 menu)
|
||||
|
||||
local position = ""
|
||||
|
||||
local markerText = ""
|
||||
|
||||
local artyTasks = {}
|
||||
|
||||
local menuItems = false
|
||||
|
||||
-- optional arty enabled user flag, for use in triggers, if the player wants to
|
||||
|
||||
trigger.action.setUserFlag( "artyEnabled", 1 )
|
||||
|
||||
|
||||
-- select format of target coordinates MGRS or LAT/LONG
|
||||
|
||||
local outputFormat = "MGRS"
|
||||
--local outputFormat = "LL"
|
||||
|
||||
|
||||
-- set values selected by player through F10 menu
|
||||
|
||||
local function setValue( _valueType, _value, _initiatorName )
|
||||
|
||||
if _valueType == "arty" then
|
||||
|
||||
artyCall = _value
|
||||
|
||||
end
|
||||
|
||||
if _valueType == "dist" then
|
||||
|
||||
adjustDistance = _value
|
||||
|
||||
trigger.action.outText("Fire adjusted by "..adjustDistance.." meters", 10)
|
||||
|
||||
end
|
||||
|
||||
if _valueType == "dir" then
|
||||
|
||||
adjustDirection = _value
|
||||
|
||||
end
|
||||
|
||||
artyAction( _initiatorName )
|
||||
|
||||
end
|
||||
|
||||
|
||||
-- Function to add F10 menu items for a specific group and store references
|
||||
|
||||
local function addMenuItems(groupId, initiatorName)
|
||||
|
||||
menuItems = true
|
||||
|
||||
local artyTask = artyTasks[initiatorName]
|
||||
|
||||
artyTask.ArtyMenu = missionCommands.addSubMenuForGroup(groupId, 'Artillery Commands')
|
||||
artyTask.AdjustDistance = missionCommands.addSubMenuForGroup(groupId, 'Adjust distance', artyTask.ArtyMenu)
|
||||
artyTask.AdjustDirection = missionCommands.addSubMenuForGroup(groupId, 'Adjust direction', artyTask.ArtyMenu)
|
||||
|
||||
artyTask.commands = {}
|
||||
artyTask.commands[#artyTask.commands + 1] = missionCommands.addCommandForGroup(groupId, 'request single round', artyTask.ArtyMenu, function() setValue("arty", 1, initiatorName) end)
|
||||
artyTask.commands[#artyTask.commands + 1] = missionCommands.addCommandForGroup(groupId, 'request fire for effect', artyTask.ArtyMenu, function() setValue("arty", 2, initiatorName) end)
|
||||
artyTask.commands[#artyTask.commands + 1] = missionCommands.addCommandForGroup(groupId, 'adjust fire by 20m', artyTask.AdjustDistance, function() setValue("dist", 20, initiatorName) end)
|
||||
artyTask.commands[#artyTask.commands + 1] = missionCommands.addCommandForGroup(groupId, 'adjust fire by 50m', artyTask.AdjustDistance, function() setValue("dist", 50, initiatorName) end)
|
||||
artyTask.commands[#artyTask.commands + 1] = missionCommands.addCommandForGroup(groupId, 'adjust fire by 100m', artyTask.AdjustDistance, function() setValue("dist", 100, initiatorName) end)
|
||||
artyTask.commands[#artyTask.commands + 1] = missionCommands.addCommandForGroup(groupId, 'adjust fire by 200m', artyTask.AdjustDistance, function() setValue("dist", 200, initiatorName) end)
|
||||
artyTask.commands[#artyTask.commands + 1] = missionCommands.addCommandForGroup(groupId, 'adjust fire by 500m', artyTask.AdjustDistance, function() setValue("dist", 500, initiatorName) end)
|
||||
|
||||
artyTask.commands[#artyTask.commands + 1] = missionCommands.addCommandForGroup(groupId, 'adjust fire North', artyTask.AdjustDirection, function() setValue("dir", 360, initiatorName) end)
|
||||
artyTask.commands[#artyTask.commands + 1] = missionCommands.addCommandForGroup(groupId, 'adjust fire North-East', artyTask.AdjustDirection, function() setValue("dir", 45, initiatorName) end)
|
||||
artyTask.commands[#artyTask.commands + 1] = missionCommands.addCommandForGroup(groupId, 'adjust fire East', artyTask.AdjustDirection, function() setValue("dir", 90, initiatorName) end)
|
||||
artyTask.commands[#artyTask.commands + 1] = missionCommands.addCommandForGroup(groupId, 'adjust fire South-East', artyTask.AdjustDirection, function() setValue("dir", 135, initiatorName) end)
|
||||
artyTask.commands[#artyTask.commands + 1] = missionCommands.addCommandForGroup(groupId, 'adjust fire South', artyTask.AdjustDirection, function() setValue("dir", 180, initiatorName) end)
|
||||
artyTask.commands[#artyTask.commands + 1] = missionCommands.addCommandForGroup(groupId, 'adjust fire South-West', artyTask.AdjustDirection, function() setValue("dir", 225, initiatorName) end)
|
||||
artyTask.commands[#artyTask.commands + 1] = missionCommands.addCommandForGroup(groupId, 'adjust fire West', artyTask.AdjustDirection, function() setValue("dir", 270, initiatorName) end)
|
||||
artyTask.commands[#artyTask.commands + 1] = missionCommands.addCommandForGroup(groupId, 'adjust fire North-West', artyTask.AdjustDirection, function() setValue("dir", 315, initiatorName) end)
|
||||
end
|
||||
|
||||
-- Function to remove F10 menu items for a specific group
|
||||
|
||||
local function removeMenuItems(initiatorName)
|
||||
|
||||
local artyTask = artyTasks[initiatorName]
|
||||
|
||||
if artyTask then
|
||||
|
||||
for _, command in ipairs(artyTask.commands) do
|
||||
missionCommands.removeItemForGroup(artyTasks[initiatorName].groupID, command)
|
||||
end
|
||||
missionCommands.removeItemForGroup(artyTasks[initiatorName].groupID, artyTask.AdjustDistance)
|
||||
missionCommands.removeItemForGroup(artyTasks[initiatorName].groupID, artyTask.AdjustDirection)
|
||||
missionCommands.removeItemForGroup(artyTasks[initiatorName].groupID, artyTask.ArtyMenu)
|
||||
end
|
||||
|
||||
menuItems = false
|
||||
|
||||
end
|
||||
|
||||
-- Calculate distance
|
||||
|
||||
local function getDist(_point1, _point2)
|
||||
|
||||
local xUnit = _point1.x
|
||||
local yUnit = _point1.z
|
||||
local xZone = _point2.x
|
||||
local yZone = _point2.z
|
||||
|
||||
local xDiff = xUnit - xZone
|
||||
local yDiff = yUnit - yZone
|
||||
|
||||
return math.sqrt(xDiff * xDiff + yDiff * yDiff)
|
||||
|
||||
end
|
||||
|
||||
-- Shelling Zone
|
||||
|
||||
local function shellZone ( _initiatorName )
|
||||
|
||||
trigger.action.outTextForUnit( artyTasks[_initiatorName].unitID, "Arty Task Created - fire incoming "..quantity.." rounds", 10)
|
||||
|
||||
if artyCall == 1 then
|
||||
artyRadius = 5
|
||||
else
|
||||
artyRadius = 50
|
||||
end
|
||||
|
||||
local _shellPos = artyTasks[_initiatorName].pos
|
||||
|
||||
if firstShotFired == true then
|
||||
_shellPos.x = _shellPos.x + adjustX
|
||||
_shellPos.y = _shellPos.y
|
||||
_shellPos.z = _shellPos.z + adjustZ
|
||||
end
|
||||
|
||||
for i = 1, quantity do
|
||||
|
||||
-- Create a random offset within the given radius
|
||||
|
||||
local randomX = math.random(-artyRadius, artyRadius)
|
||||
local randomZ = math.random(-artyRadius, artyRadius)
|
||||
|
||||
local strikePos = {
|
||||
x = _shellPos.x + randomX,
|
||||
y = _shellPos.y,
|
||||
z = _shellPos.z + randomZ
|
||||
}
|
||||
|
||||
-- Delay the shelling by 1 second for each shell
|
||||
|
||||
timer.scheduleFunction(function()
|
||||
trigger.action.explosion(strikePos, tntEquivalent) -- Create an explosion at the target position with a predefined power
|
||||
end, {}, timer.getTime() + i)
|
||||
end
|
||||
|
||||
--[[
|
||||
if firstShotFired == false then
|
||||
addMenuItems ()
|
||||
firstShotFired = true
|
||||
end
|
||||
]]--
|
||||
|
||||
end
|
||||
|
||||
-- MGRS conversion to LL to x,z
|
||||
|
||||
local function convertMGRStoPos ( _mrgs )
|
||||
|
||||
local lat, lon = coord.MGRStoLL( _mgrs )
|
||||
local markerPos = coord.LLtoLO( lat, lon, 0 )
|
||||
return markerPos
|
||||
|
||||
end
|
||||
|
||||
-- x,z coordinates conversion to LAT/LONG and MGRS
|
||||
|
||||
local function convertPos2Coord ( _pos, _reply )
|
||||
|
||||
local lat, lon, alt = coord.LOtoLL (_pos)
|
||||
local lat_degrees = math.floor (lat)
|
||||
local lat_minutes = (60 * (lat - lat_degrees))
|
||||
local lat_seconds = math.floor(60 * (lat_minutes - math.floor(lat_minutes)))
|
||||
lat_minutes = math.floor(lat_minutes)
|
||||
|
||||
local lon_degrees = math.floor (lon)
|
||||
local lon_minutes = (60 * (lon - lon_degrees))
|
||||
local lon_seconds = math.floor (60 * (lon_minutes - math.floor(lon_minutes)))
|
||||
lon_minutes = math.floor(lon_minutes)
|
||||
|
||||
local coordStringLL = "N" .. lat_degrees .. " " .. lat_minutes .. " " ..lat_seconds.. " E".. lon_degrees .. " " .. lon_minutes .. " ".. lon_seconds
|
||||
|
||||
local targetMGRS = coord.LLtoMGRS(lat, lon)
|
||||
targetMGRS.Easting = math.floor (( targetMGRS.Easting /10 ) + 0.5 )
|
||||
targetMGRS.Northing = math.floor (( targetMGRS.Northing / 10 ) + 0.5 )
|
||||
--local coordStringMGRS = targetMGRS.UTMZone.." "..targetMGRS.MGRSDigraph.." "..string.sub(targetMGRS.Easting, 1, -2).." "..string.sub(targetMGRS.Northing, 1, -2)
|
||||
local coordStringMGRS = targetMGRS.UTMZone.." "..targetMGRS.MGRSDigraph.." "..targetMGRS.Easting.." "..targetMGRS.Northing
|
||||
|
||||
if outputFormat == "MGRS" then
|
||||
coordString = coordStringMGRS
|
||||
else
|
||||
coordString = coordStringLL
|
||||
end
|
||||
|
||||
-- return either formated string or MGRS coordinate
|
||||
|
||||
if _reply == "string" then
|
||||
return coordString
|
||||
elseif _reply == "pos" then
|
||||
return targetMGRS
|
||||
end
|
||||
end
|
||||
|
||||
-- Who is the player
|
||||
|
||||
-- Function to determine which unit is controlled by the player
|
||||
--[[
|
||||
local function getPlayerControlledUnit()
|
||||
|
||||
local playerUnit = nil
|
||||
|
||||
-- Iterate through all coalitions and their respective player units
|
||||
|
||||
for coalitionID = 1, 2 do -- 1 = Red, 2 = Blue
|
||||
local playerUnits = coalition.getPlayers(coalitionID)
|
||||
for _, unit in ipairs(playerUnits) do
|
||||
if unit and unit:getPlayerName() then
|
||||
playerUnit = unit
|
||||
break
|
||||
end
|
||||
end
|
||||
if playerUnit then
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
return playerUnit
|
||||
end
|
||||
]]--
|
||||
|
||||
-- Check if user has created F10 map marker
|
||||
|
||||
artyAction = function ( _initiatorName )
|
||||
|
||||
-- Check Call for arty - 1 = single round, 2 = fire for effect
|
||||
|
||||
if artyCall == 1 or artyCall == 2 then
|
||||
|
||||
if MARKER_FOUND == true and artyTasks[_initiatorName] then
|
||||
|
||||
-- check if target is within 15km from player
|
||||
|
||||
--trigger.action.outTextForUnit( artyTasks[_initiatorName].unitID, "Arty action marker found.", 10)
|
||||
|
||||
--local _player = _initiator
|
||||
local _playerPos = artyTasks[_initiatorName].playerPos
|
||||
local _targetPos = artyTasks[_initiatorName].pos
|
||||
|
||||
local _dist = math.floor( getDist ( _targetPos, _playerPos ) / 10 ) / 100
|
||||
|
||||
if trigger.misc.getUserFlag( "artyEnabled" ) == 1 and _dist <= user_spottingDistance then
|
||||
|
||||
position = convertPos2Coord ( _targetPos, "string" )
|
||||
|
||||
if artyCall == 1 then
|
||||
trigger.action.outTextForUnit( artyTasks[_initiatorName].unitID, "Arty single round requested on "..position, 10)
|
||||
quantity = 1
|
||||
|
||||
elseif artyCall == 2 then
|
||||
trigger.action.outTextForUnit( artyTasks[_initiatorName].unitID, "Arty fire for effect requested on "..position, 10)
|
||||
quantity = quantity_effect
|
||||
end
|
||||
|
||||
timer.scheduleFunction(shellZone, _initiatorName, timer.getTime() + fireDelay)
|
||||
trigger.action.setUserFlag( "artyFired", 1 )
|
||||
|
||||
else
|
||||
trigger.action.outTextForUnit( artyTasks[_initiatorName].unitID, "Artillery not available", 10)
|
||||
end
|
||||
|
||||
else
|
||||
trigger.action.outTextForUnit( artyTasks[_initiatorName].unitID, "Arty Requested Without Marker", 10)
|
||||
end
|
||||
|
||||
artyCall = 0
|
||||
|
||||
end
|
||||
|
||||
-- Check Call for arty direction correction
|
||||
|
||||
if adjustDirection == 360 then
|
||||
|
||||
adjustX = adjustDistance
|
||||
adjustZ = 0
|
||||
artyRadius = 5
|
||||
|
||||
trigger.action.outTextForUnit( artyTasks[_initiatorName].unitID, "Fire adjusted to the North", 10)
|
||||
|
||||
adjustDirection = 0
|
||||
end
|
||||
|
||||
if adjustDirection == 45 then
|
||||
|
||||
adjustX = adjustDistance
|
||||
adjustZ = adjustDistance
|
||||
artyRadius = 5
|
||||
|
||||
adjustDirection = 0
|
||||
end
|
||||
|
||||
if adjustDirection == 90 then
|
||||
|
||||
adjustX = 0
|
||||
adjustZ = adjustDistance
|
||||
artyRadius = 5
|
||||
|
||||
trigger.action.outTextForUnit( artyTasks[_initiatorName].unitID, "Fire adjusted to the East", 10)
|
||||
|
||||
adjustDirection = 0
|
||||
end
|
||||
|
||||
if adjustDirection == 135 then
|
||||
|
||||
adjustX = -adjustDistance
|
||||
adjustZ = adjustDistance
|
||||
artyRadius = 5
|
||||
|
||||
trigger.action.outTextForUnit( artyTasks[_initiatorName].unitID, "Fire adjusted to the South-East", 10)
|
||||
|
||||
adjustDirection = 0
|
||||
end
|
||||
|
||||
if adjustDirection == 180 then
|
||||
|
||||
adjustX = -adjustDistance
|
||||
adjustZ = 0
|
||||
artyRadius = 5
|
||||
|
||||
trigger.action.outTextForUnit( artyTasks[_initiatorName].unitID, "Fire adjusted to the South", 10)
|
||||
|
||||
adjustDirection = 0
|
||||
end
|
||||
|
||||
if adjustDirection == 225 then
|
||||
|
||||
adjustX = -adjustDistance
|
||||
adjustZ = -adjustDistance
|
||||
artyRadius = 5
|
||||
|
||||
trigger.action.outTextForUnit( artyTasks[_initiatorName].unitID, "Fire adjusted to the South-West", 10)
|
||||
|
||||
adjustDirection = 0
|
||||
end
|
||||
|
||||
if adjustDirection == 270 then
|
||||
|
||||
adjustX = 0
|
||||
adjustZ = -adjustDistance
|
||||
artyRadius = 5
|
||||
|
||||
trigger.action.outTextForUnit( artyTasks[_initiatorName].unitID, "Fire adjusted meters to the West", 10)
|
||||
|
||||
adjustDirection = 0
|
||||
end
|
||||
|
||||
if adjustDirection == 315 then
|
||||
|
||||
adjustX = adjustDistance
|
||||
adjustZ = -adjustDistance
|
||||
artyRadius = 5
|
||||
|
||||
trigger.action.outTextForUnit( artyTasks[_initiatorName].unitID, "Fire adjusted meters to the North-West", 10)
|
||||
|
||||
adjustDirection = 0
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- Main
|
||||
|
||||
trigger.action.outText("Arty spotter script "..version.." loaded", 10)
|
||||
|
||||
|
||||
-- Map Marker Text - read and process
|
||||
|
||||
-- Function to remove spaces from a string
|
||||
|
||||
local function removeSpaces( _text )
|
||||
|
||||
_text = _text:gsub( " ", "" )
|
||||
_text = _text:gsub( "-", "" )
|
||||
return _text
|
||||
|
||||
end
|
||||
|
||||
-- Function to validate the structure of the MGRS coordinate
|
||||
|
||||
local function checkValidMGRS( _mgrs, len)
|
||||
|
||||
if len == 13 then
|
||||
|
||||
-- Pattern: 2 digits 1 letter UTM Zone, 2 letters MGRS Digraph, 4 digits Easting, 4 digits Northing
|
||||
return _mgrs:match("^%d%d%u%u%u%d%d%d%d%d%d%d%d$")
|
||||
|
||||
elseif len == 10 then
|
||||
|
||||
-- Pattern: 2 letters MGRS Digraph, 4 digits Easting, 4 digits Northing
|
||||
return _mgrs:match("^%u%u%d%d%d%d%d%d%d%d$")
|
||||
|
||||
elseif len == 8 then
|
||||
|
||||
-- Pattern: 4 digits Easting, 4 digits Northing
|
||||
return _mgrs:match("^%d%d%d%d%d%d%d%d$")
|
||||
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
-- Function to validate and complete MGRS coordinates
|
||||
|
||||
local function processMGRS( _text, _playerPos, initiatorName )
|
||||
local _cleanedText = string.upper( removeSpaces( _text ) )
|
||||
local len = #_cleanedText
|
||||
|
||||
local _isValidMGRS = checkValidMGRS( _cleanedText, len)
|
||||
|
||||
if _isValidMGRS then
|
||||
|
||||
trigger.action.outTextForUnit( artyTasks[initiatorName].unitID, "Processing MGRS: " .. _cleanedText, 10)
|
||||
|
||||
if len == 13 then
|
||||
|
||||
-- Complete MGRS coordinate
|
||||
return _cleanedText
|
||||
|
||||
elseif len == 10 then
|
||||
|
||||
-- Add UTM Zone based on player position
|
||||
local _utmZone = coord.LLtoMGRS(_playerPos.Lat, _playerPos.Lon).UTMZone
|
||||
return _utmZone .. _cleanedText
|
||||
|
||||
elseif len == 8 then
|
||||
|
||||
-- Add UTM Zone and MGRS Digraph based on player position
|
||||
local _mgrs = coord.LLtoMGRS( _playerPos.Lat, _playerPos.Lon )
|
||||
return _mgrs.UTMZone .. _mgrs.MGRSDigraph .. _cleanedText
|
||||
|
||||
else
|
||||
|
||||
-- Invalid MGRS coordinate
|
||||
return nil
|
||||
end
|
||||
|
||||
else
|
||||
|
||||
trigger.action.outTextForUnit( artyTasks[initiatorName].unitID, "Invalid text input: " .. _cleanedText, 10)
|
||||
return nil
|
||||
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
-- Function to convert a valid MGRS to vec3
|
||||
local function MGRStoVec3( _mgrs )
|
||||
|
||||
local lat, lon = coord.MGRStoLL( _mgrs )
|
||||
local vec3 = coord.LLtoLO( lat, lon, 0 )
|
||||
return vec3
|
||||
end
|
||||
|
||||
-- Function to check if the initiator is valid based on restrictions
|
||||
|
||||
local function isValidInitiator(initiator)
|
||||
if not initiator then return false end
|
||||
|
||||
-- Check type restriction
|
||||
|
||||
if user_restrictByType == "helo" then
|
||||
|
||||
if not initiator:getDesc().category == Unit.Category.Helicopter then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
-- Check name restriction
|
||||
|
||||
if user_restrictByUnitName ~= "" then
|
||||
|
||||
local name = initiator:getName():lower()
|
||||
|
||||
if not name:find(user_restrictByUnitName:lower()) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
-- Function to check if the marker text has the required prefix and remove it
|
||||
|
||||
local function checkAndRemovePrefix(text)
|
||||
|
||||
if user_markerPrefix ~= "" and text:sub(1, #user_markerPrefix) == user_markerPrefix then
|
||||
|
||||
return true, text:sub(#user_markerPrefix + 1)
|
||||
|
||||
elseif user_markerPrefix == "" then
|
||||
|
||||
return true, text
|
||||
|
||||
else
|
||||
|
||||
return false, text
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
-- Event handler for map marker creation
|
||||
local function onPlayerAddMarker(event)
|
||||
|
||||
|
||||
if event.id == world.event.S_EVENT_MARK_ADDED and user_markerPrefix == "" then
|
||||
|
||||
if isValidInitiator(event.initiator) then
|
||||
|
||||
--local hasPrefix, cleanedText = checkAndRemovePrefix(event.text)
|
||||
hasPrefix = true
|
||||
|
||||
if hasPrefix then
|
||||
|
||||
MARKER_FOUND = true
|
||||
pos = event.pos
|
||||
|
||||
if event.initiator then
|
||||
|
||||
local initiatorName = event.initiator:getName()
|
||||
|
||||
local playerUnit = event.initiator
|
||||
local playerPos = playerUnit:getPoint()
|
||||
|
||||
-- Store position
|
||||
|
||||
if not artyTasks[initiatorName] then
|
||||
artyTasks[initiatorName] = {}
|
||||
end
|
||||
|
||||
trigger.action.outTextForUnit( event.initiator:getID(), "Marker added", 5)
|
||||
|
||||
artyTasks[initiatorName].playerPos = playerPos
|
||||
artyTasks[initiatorName].pos = pos
|
||||
artyTasks[initiatorName].unitID = event.initiator:getID()
|
||||
|
||||
-- Add menu items for the initiator's group
|
||||
local groupId = event.initiator:getGroup():getID()
|
||||
artyTasks[initiatorName].groupID = groupId
|
||||
|
||||
if menuItems == false then
|
||||
addMenuItems(groupId, initiatorName)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
else
|
||||
--trigger.action.outText("You do not have permission to add a marker.", 5)
|
||||
end
|
||||
|
||||
elseif event.id == world.event.S_EVENT_MARK_CHANGE then
|
||||
|
||||
if isValidInitiator(event.initiator) then
|
||||
|
||||
local hasPrefix, cleanedText = checkAndRemovePrefix(event.text)
|
||||
|
||||
if hasPrefix then
|
||||
|
||||
MARKER_FOUND = true
|
||||
|
||||
local markText = cleanedText
|
||||
|
||||
trigger.action.outText("Text: "..markText, 10)
|
||||
|
||||
if markText and event.initiator then
|
||||
|
||||
local initiatorName = event.initiator:getName()
|
||||
local playerUnit = event.initiator
|
||||
|
||||
if not artyTasks[initiatorName] then
|
||||
artyTasks[initiatorName] = {}
|
||||
end
|
||||
|
||||
artyTasks[initiatorName].initiator = event.initiator
|
||||
artyTasks[initiatorName].unitID = event.initiator:getID()
|
||||
|
||||
trigger.action.outTextForUnit( event.initiator:getID(), "Marker changed", 5)
|
||||
|
||||
if playerUnit then
|
||||
|
||||
local playerPos = playerUnit:getPoint()
|
||||
local lat, lon = coord.LOtoLL(playerPos)
|
||||
local playerPosition = { Lat = lat, Lon = lon }
|
||||
local validMGRS = processMGRS(markText, playerPosition, initiatorName)
|
||||
|
||||
if validMGRS then
|
||||
|
||||
trigger.action.outTextForUnit( artyTasks[initiatorName].unitID, "Valid MGRS: " .. validMGRS, 10)
|
||||
|
||||
local tmpMGRS = {
|
||||
UTMZone = string.sub(validMGRS, 1, 3),
|
||||
MGRSDigraph = string.sub(validMGRS, 4, 5),
|
||||
Easting = tonumber(string.sub(validMGRS, 6, 9)) * 10,
|
||||
Northing = tonumber(string.sub(validMGRS, 10, 13)) * 10
|
||||
}
|
||||
|
||||
local targetPoint = MGRStoVec3(tmpMGRS)
|
||||
targetPoint.y = land.getHeight({ x = targetPoint.x, y = targetPoint.z })
|
||||
|
||||
|
||||
artyTasks[initiatorName].pos = targetPoint
|
||||
artyTasks[initiatorName].playerPos = playerPos
|
||||
|
||||
|
||||
else
|
||||
trigger.action.outTextForUnit( artyTasks[initiatorName].unitID, "Invalid MGRS coordinate entered.", 10)
|
||||
end
|
||||
|
||||
local groupId = event.initiator:getGroup():getID()
|
||||
artyTasks[initiatorName].groupID = groupId
|
||||
|
||||
if menuItems == false then
|
||||
addMenuItems(groupId, initiatorName)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
--trigger.action.outText("You do not have permission to change this marker.", 5)
|
||||
end
|
||||
|
||||
elseif event.id == world.event.S_EVENT_MARK_REMOVED then
|
||||
|
||||
trigger.action.outText("Marker removed", 5)
|
||||
|
||||
if event.initiator then
|
||||
|
||||
local initiatorName = event.initiator:getName()
|
||||
|
||||
if artyTasks[initiatorName] then
|
||||
|
||||
removeMenuItems(initiatorName)
|
||||
artyTasks[initiatorName] = nil
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Register the event handler
|
||||
local eventHandler = { f = onPlayerAddMarker }
|
||||
function eventHandler:onEvent(e)
|
||||
self.f(e)
|
||||
end
|
||||
world.addEventHandler(eventHandler)
|
||||
|
||||
|
||||
|
||||
|
||||
22
resources/plugins/arty/arty-config.lua
Normal file
22
resources/plugins/arty/arty-config.lua
Normal file
@ -0,0 +1,22 @@
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- configuration file for Carsten's Arty Spotter Plugin
|
||||
--
|
||||
-- This configuration is tailored for a mission generated by DCS Retribution
|
||||
-- see https://github.com/dcs-retribution/dcs-retribution
|
||||
-------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
-- arty plugin - configuration
|
||||
if dcsRetribution then
|
||||
-- retrieve specific options values
|
||||
if dcsRetribution.plugins then
|
||||
if dcsRetribution.plugins.arty then
|
||||
env.info("DCSRetribution|Carsten's Arty Spotter plugin - Setting Up")
|
||||
|
||||
cg_arty_options.user_fireDelay = dcsRetribution.plugins.arty.user_fireDelay
|
||||
cg_arty_options.user_quantity = dcsRetribution.plugins.arty.user_quantity
|
||||
cg_arty_options.user_spread = dcsRetribution.plugins.arty.user_spread
|
||||
cg_arty_options.user_spottingDistance = dcsRetribution.plugins.arty.user_spottingDistance
|
||||
end
|
||||
end
|
||||
end
|
||||
38
resources/plugins/arty/plugin.json
Normal file
38
resources/plugins/arty/plugin.json
Normal file
@ -0,0 +1,38 @@
|
||||
{
|
||||
"nameInUI": "Carsten's Arty Spotter",
|
||||
"defaultValue": false,
|
||||
"specificOptions": [
|
||||
{
|
||||
"nameInUI": "Time to impcat of the rounds",
|
||||
"mnemonic": "user_fireDelay",
|
||||
"defaultValue": 15
|
||||
},
|
||||
{
|
||||
"nameInUI": "Salvo quantity",
|
||||
"mnemonic": "user_quantity",
|
||||
"defaultValue": 5
|
||||
},
|
||||
{
|
||||
"nameInUI": "Impact radius",
|
||||
"mnemonic": "user_spread",
|
||||
"defaultValue": 150
|
||||
},
|
||||
{
|
||||
"nameInUI": "Max spotting distance. In kilometers.",
|
||||
"mnemonic": "user_spottingDistance",
|
||||
"defaultValue": 15
|
||||
}
|
||||
],
|
||||
"scriptsWorkOrders": [
|
||||
{
|
||||
"file": "CG_ArtySpotter_V1_2a_MP.lua",
|
||||
"mnemonic": "arty"
|
||||
}
|
||||
],
|
||||
"configurationWorkOrders": [
|
||||
{
|
||||
"file": "arty-config.lua",
|
||||
"mnemonic": "arty-config"
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
[
|
||||
"base",
|
||||
"ctld",
|
||||
"arty",
|
||||
"dismounts",
|
||||
"ewrj",
|
||||
"ewrs",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user