DCS_MissionDev/fac2_ArtyMarkRecceZone_v2_1_25RugerModifided2.lua

4433 lines
168 KiB
Lua

--[[
DCS FAC v2.1.25
-------
Authors: Pb_Magnet (github.com/jweisner), modified by Shadow
NOTE: Almost all of the hard stuff here is copied/adapted from CTLD: https://github.com/ciribob/DCS-CTLD
This script was originally submitted as a PR to include in CTLD, but there didn't seem to be any interest from CTLD vOv
New features:
Required Scripts for this scrip to function:
Mist
markManager
Reworked Artillery control via F10
Auto Map Marking
RECCE Units --> Cant Lase but will mark all units in an area
Manual Targeting mode
Offset Mortar aimpoint to compensate for rounds falling short
Added arty fire type choice
Added AI Artillery Spotters
Added Air Ops Menu for TALD and Carpet Bomb Map Attack
Integrated Naval Fire Support
Added AI RECCE support
Readded MLRS support
]]
local facPlayerSpawn ={}
fac = {} -- do not modify this line
local CrptBmbDesig = {}
local RECCEDesig = {}
function contains(t, e)
for i = 1,#t do
if t[i] == e then return true end
end
return false
end
function removebyKey(tab, val)
for i, v in ipairs (tab) do
if (v.id == val) then
tab[i] = nil
end
end
end
fac.facACTypes ={
"SA342L",
"UH-1H",
"Mi-8MTV2",
--"TF-51",
--"Hawk",
}
fac.artyDirectorTypes = {
"Soldier M249",
--"Paratrooper AKS-74",
--"Soldier M4",
}
-- ***************** FAC CONFIGURATION *****************
fac.FAC_maxDistance = 18520 -- How far a FAC can "see" in meters (with Line of Sight)
fac.AutoOn = true -- when enabled turns auto on station for AFAC
fac.FAC_smokeOn_RED = true -- enables marking of target with smoke for RED forces
fac.FAC_smokeOn_BLUE = true -- enables marking of target with smoke for BLUE forces
fac.FAC_smokeColour_RED = 0 -- RED side smoke colour -- Green = 0 , Red = 1, White = 2, Orange = 3, Blue = 4 (if using flares limit to green and orange)
fac.FAC_smokeColour_BLUE = 3 -- BLUE side smoke colour -- Green = 0 , Red = 1, White = 2, Orange = 3, Blue = 4 (if using flares limit to green and orange)
fac.FAC_FACStatusF10 = true -- enables F10 FAC Status menu
fac.FAC_location = true -- shows location of target in FAC message
fac.FAC_lock = "all" -- "vehicle" OR "troop" OR "all" forces FAC to only lock vehicles or troops or all ground units
fac.FAC_laser_codes = { '1688', '1677', '1666', '1113','1115' ,'1111'}
fac.fireMissionRounds = 24 -- number of shells per fire mission request
fac.illumHeight = 500 --height for illumination bomb
fac.facOffsetDist = 5000
fac.markID = 1000 --intial MarkerID
fac.recceID = 50000 --Initial recce ID number
-- ******************** FAC names **********************
function fac.isAFAC(acUnit)
local playerGroup = Unit.getGroup(acUnit)
local playerGroupName = playerGroup:getName()
local AFACmatch = 0
if (string.find(playerGroupName, "AFAC") == nil) and (string.find(playerGroupName, "RECON") == nil) then
AFACmatch = 0
else
AFACmatch = 1
end
if contains(fac.facACTypes,acUnit:getTypeName()) then
AFACmatch = 1
end
return AFACmatch
end
function fac.isRECCE(acUnit)
local playerGroup = Unit.getGroup(acUnit)
local playerGroupName = playerGroup:getName()
local RECCEmatch = 0
--trigger.action.outText(acUnit:getTypeName(),5)
if (string.find(playerGroupName, "RECCE") == nil) and (string.find(playerGroupName, "RECON") == nil) then
RECCEmatch = 0
else
RECCEmatch = 1
end
if contains(fac.facACTypes,acUnit:getTypeName()) then
RECCEmatch = 1
end
return RECCEmatch
end
function fac.isArtyD(acUnit)
local adMatch = 0
local playerGroup = Unit.getGroup(acUnit)
if playerGroup then
local playerGroupName = playerGroup:getName()
if playerGroupName then
if contains(fac.artyDirectorTypes,acUnit:getTypeName()) then
adMatch = 1
end
end
end
return adMatch
end
-- Use any of the predefined names or set your own ones
fac.facPilotNames = {
"Chevy 6-1",
"Chevy 6-2",
"Chevy 6-3",
"Chevy 6-4",
"Chevy 5-1",
"Chevy 5-2",
"Chevy 5-3",
"Chevy 5-4",
"Chevy 4-1",
"Chevy 4-2",
"Chevy 4-3",
"Chevy 4-4",
"Chevy 2-1",
"Chevy 2-2",
"Chevy 2-3",
"Chevy 2-4",
"Chevy 1-1",
"Chevy 1-2",
"Chevy 1-3",
"Chevy 1-4",
"837",
"838",
"839",
"840",
"841",
"842",
"843",
"844",
-- "Red AFAC #001",
-- "Red AFAC #002",
-- "Red AFAC #003",
-- "Red AFAC #004",
-- "Red AFAC #005",
-- "Red AFAC #006",
-- "Red AFAC #007",
-- "Red AFAC #008",
-- "Red AFAC #009",
-- "Red AFAC #010",
-- "Blue AFAC #001",
-- "Blue AFAC #002",
-- "Blue AFAC #003",
-- "Blue AFAC #004",
-- "Blue AFAC #005",
-- "Blue AFAC #006",
-- "Blue AFAC #007",
-- "Blue AFAC #008",
-- "Blue AFAC #009",
-- "Blue AFAC #010",
-- "helicargo4",
-- "helicargo8",
-- "FAC #001",
-- "FAC #002",
-- "FAC #003",
-- "FAC #004",
-- "FAC #005",
-- "FAC #006",
-- "FAC #007",
-- "FAC #008",
-- "RED Mobile FOB TRANSPORT #001",
-- "RED Mobile FOB TRANSPORT #002",
-- "BLUE Mobile FOB TRANSPORT #001",
-- "BLUE Mobile FOB TRANSPORT #002",
}
--Define RECCE pilots
fac.reccePilotNames = {
--Enter RECCE pilot names here,
"RECCE1",
"RECCE2",
}
fac.artDirectNames = {
"RECCE1",
"RECCE2",
"RECCE3",
"RECCE4",
}
--init FAC
-- Auto Detects Group names and adds unit to FAC and RECCE list
function facPlayerSpawn:onEvent(e)
if e.id == world.event.S_EVENT_BIRTH then
local objType = e.initiator:getDesc()
if Object.getCategory(e.initiator) == 1 then
if objType.category < 2 then
local AFAC = fac.isAFAC(e.initiator)
local RECCE = fac.isRECCE(e.initiator)
local test2 = Unit.getGroup(e.initiator)
local gid = test2:getID()
local afacUnitName = e.initiator:getName()
local checkAFACName, afacIdx = contains(fac.facPilotNames,afacUnitName)
local checkRECCEName, afacIdx = contains(fac.reccePilotNames,afacUnitName)
--trigger.action.outText(RECCE .. afacUnitName,5)
if AFAC == 1 then
if contains(fac.facPilotNames,afacUnitName) == false then
table.insert(fac.facPilotNames, afacUnitName)
trigger.action.outTextForGroup(gid,"Your A/C is an AFAC and added to AFAC List \nUse your F10 menu to spot targets for your team and call in artillery strikes", 15)
else
trigger.action.outTextForGroup(gid,"Your A/C is an AFAC \nUse your F10 menu to spot targets for your team and call in artillery strikes", 15)
end
if fac.AutoOn == true then
fac.setFacOnStation({afacUnitName,true})
end
--trigger.action.outTextForGroup(gid,"Your A/C is an AFAC "..afacUnitName.." "..#fac.facPilotNames, 15)
--trigger.action.outText(rampcheck,5)
elseif checkAFACName == true then
trigger.action.outTextForGroup(gid,"Your A/C is an AFAC \nUse your F10 menu to spot targets for your team and call in artillery strikes", 15)
end
if RECCE == 1 then
if contains(fac.reccePilotNames,afacUnitName) == false then
table.insert(fac.reccePilotNames, afacUnitName)
trigger.action.outTextForGroup(gid,"Your A/C is an RECCE and added to RECCE List \nUse your F10 menu to spot all targets in an area for your team and mark them on the F10 map", 15)
else
trigger.action.outTextForGroup(gid,"Your A/C is an Recon A/C \nUse your F10 menu to spot all targets in an area for your team and mark them on the F10 map", 15)
end
elseif checkRECCEName == true then
trigger.action.outTextForGroup(gid,"Your A/C is an RECCE \nUse your F10 menu to spot all targets in an area for your team and mark them on the F10 map", 15)
end
elseif objType.category == 2 then
local artDirect = fac.isArtyD(e.initiator)
local afacUnitName = e.initiator:getName()
local test2 = Unit.getGroup(e.initiator)
local gid = test2:getCoalition()
if artDirect == 1 then
if contains(fac.artDirectNames,afacUnitName) == false then
table.insert(fac.artDirectNames, afacUnitName)
--trigger.action.outText("Artillery Spotter has been deployed" .. e.initiator:getTypeName() , 15)
end
end
end
end
end
end
world.addEventHandler(facPlayerSpawn)
--Arty properties from Mbot's AES script
fac.ArtilleryProperties = {
["2B11 mortar"] = {
minrange = 500, --Minimal firing range
maxrange = 7000, --Maximal firing range
FM_rounds = 24, --The total amount of shots of a fire mission for a battery of this unit type
minAmmo = 0, --The amount of rounds left in a individual unit when switching from rapid fire to sustained fire
displacementTime = 0 --Time the battery waits between firing and moving
},
["SAU 2-C9"] = {
minrange = 500, --Minimal firing range
maxrange = 7000, --Maximal firing range
FM_rounds = 24, --The total amount of shots of a fire mission for a battery of this unit type
minAmmo = 0, --The amount of rounds left in a individual unit when switching from rapid fire to sustained fire
displacementTime = 10 --Time the battery waits between firing and moving
},
["M-109"] = {
minrange = 300, --Minimal firing range
maxrange = 22000, --Maximal firing range
FM_rounds = 24, --The total amount of shots of a fire mission for a battery of this unit type
minAmmo = 160, --The amount of rounds left in a individual unit when switching from rapid fire to sustained fire
displacementTime = 10 --Time the battery waits between firing and moving
},
["SAU Gvozdika"] = {
minrange = 300, --Minimal firing range
maxrange = 15000, --Maximal firing range
FM_rounds = 24, --The total amount of shots of a fire mission for a battery of this unit type
minAmmo = 0, --The amount of rounds left in a individual unit when switching from rapid fire to sustained fire
displacementTime = 10 --Time the battery waits between firing and moving
},
["SAU Akatsia"] = {
minrange = 300, --Minimal firing range
maxrange = 17000, --Maximal firing range
FM_rounds = 24, --The total amount of shots of a fire mission for a battery of this unit type
minAmmo = 0, --The amount of rounds left in a individual unit when switching from rapid fire to sustained fire
displacementTime = 10 --Time the battery waits between firing and moving
},
["SAU Msta"] = {
minrange = 300, --Minimal firing range
maxrange = 23500, --Maximal firing range
FM_rounds = 24, --The total amount of shots of a fire mission for a battery of this unit type
minAmmo = 300, --The amount of rounds left in a individual unit when switching from rapid fire to sustained fire
displacementTime = 10 --Time the battery waits between firing and moving
},
["MLRS"] = {
minrange = 10000, --Minimal firing range
maxrange = 32000, --Maximal firing range
FM_rounds = 12, --The total amount of shots of a fire mission for a battery of this unit type
minAmmo = 12, --The amount of rounds left in a individual unit when switching from rapid fire to sustained fire
displacementTime = 10 --Time the battery waits between firing and moving
},
["Grad-URAL"] = {
minrange = 5000, --Minimal firing range
maxrange = 19000, --Maximal firing range
FM_rounds = 120, --The total amount of shots of a fire mission for a battery of this unit type
minAmmo = 40, --The amount of rounds left in a individual unit when switching from rapid fire to sustained fire
displacementTime = 120 --Time the battery waits between firing and moving
},
["Smerch"] = {
minrange = 20000, --Minimal firing range
maxrange = 70000, --Maximal firing range
FM_rounds = 24, --The total amount of shots of a fire mission for a battery of this unit type
minAmmo = 12, --The amount of rounds left in a individual unit when switching from rapid fire to sustained fire
displacementTime = 120 --Time the battery waits between firing and moving
},
["Uragan_BM-27"] = {
minrange = 11500, --Minimal firing range
maxrange = 35800, --Maximal firing range
FM_rounds = 16, --The total amount of shots of a fire mission for a battery of this unit type
minAmmo = 12, --The amount of rounds left in a individual unit when switching from rapid fire to sustained fire
displacementTime = 120 --Time the battery waits between firing and moving
},
["SpGH_Dana"] = {
minrange = 300, --Minimal firing range
maxrange = 18700, --Maximal firing range
FM_rounds = 16, --The total amount of shots of a fire mission for a battery of this unit type
minAmmo = 12, --The amount of rounds left in a individual unit when switching from rapid fire to sustained fire
displacementTime = 120 --Time the battery waits between firing and moving
},
["Smerch_HE"] = {
minrange = 20000, --Minimal firing range
maxrange = 70000, --Maximal firing range
FM_rounds = 16, --The total amount of shots of a fire mission for a battery of this unit type
minAmmo = 12, --The amount of rounds left in a individual unit when switching from rapid fire to sustained fire
displacementTime = 120 --Time the battery waits between firing and moving
},
["T155_Firtina"] = {
minrange = 300, --Minimal firing range
maxrange = 41000, --Maximal firing range
FM_rounds = 16, --The total amount of shots of a fire mission for a battery of this unit type
minAmmo = 12, --The amount of rounds left in a individual unit when switching from rapid fire to sustained fire
displacementTime = 120 --Time the battery waits between firing and moving
},
["PLZ05"] = {
minrange = 300, --Minimal firing range
maxrange = 23500, --Maximal firing range
FM_rounds = 16, --The total amount of shots of a fire mission for a battery of this unit type
minAmmo = 12, --The amount of rounds left in a individual unit when switching from rapid fire to sustained fire
displacementTime = 120 --Time the battery waits between firing and moving
},
-- ["hy_launcher"] = { -- doesn't work do not use
-- minrange = 3000, --Minimal firing range
-- maxrange = 40000, --Maximal firing range
-- FM_rounds = 16, --The total amount of shots of a fire mission for a battery of this unit type
-- minAmmo = 12, --The amount of rounds left in a individual unit when switching from rapid fire to sustained fire
-- displacementTime = 120 --Time the battery waits between firing and moving
-- },
-- ["TomahawkLauncher"] = {
-- minrange = 18520, --Minimal firing range
-- maxrange = 460000, --Maximal firing range
-- FM_rounds = 16, --The total amount of shots of a fire mission for a battery of this unit type
-- minAmmo = 12, --The amount of rounds left in a individual unit when switching from rapid fire to sustained fire
-- displacementTime = 120 --Time the battery waits between firing and moving
-- }
}
------------ FAC -----------
fac.facManTGT = {}
fac.facLaserPoints = {}
fac.facIRPoints = {}
fac.facSmokeMarks = {}
fac.facUnits = {} -- list of FAC units for f10 command
fac.facCurrentTargets = {}
fac.facAddedTo = {} -- keeps track of who's had the fac command menu added
fac.RECCEAddedTo = {} -- keeps track of who's had the RECCE command menu added
fac.facRadioAdded = {} -- keeps track of who's had the radio command added
fac.facLaserPointCodes = {} -- keeps track of what laser code is used by each fac
fac.facOnStation = {} -- keeps track of which facs are on station
fac.markerType = {} -- keeps track of marker type per FAC
fac.markerTypeColor = {} -- keeps track of marker color per FAC
fac.redArty = {} -- keeps track of available arty for Red
fac.bluArty = {} --keeps track of available arty for Blue
fac.ArtyTasked = {} --keeps track of Arty with current fire missions
fac.RECCETasked = {}
fac.AITgted = {}
-- search for activated FAC units and schedule facAutoLase
function fac.checkFacStatus()
--env.info("FAC checkFacStatus")
timer.scheduleFunction(fac.checkFacStatus, nil, timer.getTime() + 1.0)
local _status, _result = pcall(function()
for _, _facUnitName in ipairs(fac.facPilotNames) do
local _facUnit = fac.getFacUnit(_facUnitName)
if _facUnit ~= nil then
--[[
if fac.facOnStation[_facUnitName] == true then
env.info("FAC DEBUG: fac.checkFacStatus() " .. _facUnitName .. " on-station")
end
if fac.facOnStation[_facUnitName] == nil then
env.info("FAC DEBUG: fac.checkFacStatus() " .. _facUnitName .. " off-station")
end
]]
-- if fac is off-station and is AI, set onStation
if fac.facUnits[_facUnitName] == nil and _facUnit:getPlayerName() == nil then
--env.info("FAC: setting onStation for AI fac unit " .. _facUnitName)
fac.setFacOnStation({_facUnitName, true})
end
-- start facAutoLase if the FAC is on station and not already scheduled
if fac.facUnits[_facUnitName] == nil and fac.facOnStation[_facUnitName] == true then
env.info("FAC: found new FAC unit. Starting facAutoLase for " .. _facUnitName)
fac.facAutoLase(_facUnitName) --(_facUnitName, _laserCode, _smoke, _lock, _colour)
end
end
end
end)
if (not _status) then
env.error(string.format("FAC ERROR: %s", _result))
end
end
-- gets the FAC status and displays to coalition units
function fac.getFacStatus(_args)
--returns the status of all FAC units
local _playerUnit = fac.getFacUnit(_args[1])
local colorString = {["0"] = "GREEN" ,["1"] = "RED" ,["2"] = "WHITE", ["3"] = "ORANGE" , ["4"] = "BLUE"}
if _playerUnit == nil then
return
end
local _side = _playerUnit:getCoalition()
local _mkrColor
if _side == 1 then
_mkrColor = fac.FAC_smokeColour_BLUE
elseif _side == 2 then
_mkrColor = fac.FAC_smokeColour_RED
else
_mkrColor = 2
end
local _facUnit = nil
local _message = "FAC STATUS: \n\n"
for _facUnitName, _facDetails in pairs(fac.facUnits) do
--look up units
_facUnit = Unit.getByName(_facDetails.name)
if _facUnit ~= nil and _facUnit:getLife() > 0 and _facUnit:isActive() == true and _facUnit:getCoalition() == _side and fac.facOnStation[_facUnitName] == true then
local _enemyUnit = fac.getCurrentFacUnit(_facUnit, _facUnitName)
local _laserCode = fac.facLaserPointCodes[_facUnitName]
-- get player name if available
local _facName = _facUnitName
if _facUnit:getPlayerName() ~= nil then
_facName = _facUnit:getPlayerName()
end
if fac.markerTypeColor[_facName] ~= nil then
_mkrColor = fac.markerTypeColor[_facName]
end
if _laserCode == nil then
_laserCode = "UNKNOWN"
end
if fac.markerType[_facUnitName] == nil then
fac.markerType[_facUnitName] = "FLARES"
end
if _enemyUnit ~= nil and _enemyUnit:getLife() > 0 and _enemyUnit:isActive() == true then
_message = _message .. "" .. _facName .. " targeting " .. _enemyUnit:getTypeName() .. " CODE: " .. _laserCode .. fac.getFacPositionString(_enemyUnit) .. "\nMarked with " .. colorString[tostring(_mkrColor)] .." ".. fac.markerType[_facUnitName].. "\n"
else
_message = _message .. "" .. _facName .. " on-station and searching for targets" .. " CODE: " .. _laserCode .. "\n"
end
end
end
if _message == "FAC STATUS: \n\n" then
_message = "No Active FACs, Join a slot labeled RECON or AFAC to play as a flying JTAC and Artillery Spotter"
end
fac.notifyCoalition(_message, 60, _side)
end
function fac.getFacPositionString(_unit)
if fac.FAC_location == false then
return ""
end
local _lat, _lon = coord.LOtoLL(_unit:getPosition().p)
local unitPos = _unit:getPoint()
-- local _latDeg,_latMinf = math.modf(_lat)
-- local _longDeg,_longMinf = math.modf(_lat)
-- local _latMin, _latSecf = math.modf(_latMinf*60)
-- local _longMin, _longSecf = math.modf(_longMinf*60)
-- local _latSec = _latSecf*605
-- local _longSec = _longSecf*60
local _latLngStr = mist.tostringLL(_lat, _lon, 3, false)
local _latLngSecStr = mist.tostringLL(_lat, _lon, 3, true)
local _mgrsString = mist.tostringMGRS(coord.LLtoMGRS(coord.LOtoLL(_unit:getPosition().p)), 5)
return " @\n- DD " .. _latLngStr .." \n- DMS: " .. _latLngSecStr .. " \n- MGRS: " .. _mgrsString .."\nAltitude: ".. math.floor(unitPos.y) .."m/" .. math.floor(unitPos.y*3.28084) .."ft"
end
-- get currently selected unit and check if the FAC is still in range
function fac.getCurrentFacUnit(_facUnit, _facUnitName)
local _unit = nil
if fac.facCurrentTargets[_facUnitName] ~= nil then
_unit = Unit.getByName(fac.facCurrentTargets[_facUnitName].name)
end
local _tempPoint = nil
local _tempDist = nil
local _tempPosition = nil
local _facPosition = _facUnit:getPosition()
local _facPoint = _facUnit:getPoint()
if _unit ~= nil and _unit:getLife() > 0 and _unit:isActive() == true then
-- calc distance
_tempPoint = _unit:getPoint()
-- tempPosition = unit:getPosition()
_tempDist = fac.getDistance(_unit:getPoint(), _facUnit:getPoint())
if _tempDist < fac.FAC_maxDistance then
-- calc visible
-- check slightly above the target as rounding errors can cause issues, plus the unit has some height anyways
local _offsetEnemyPos = { x = _tempPoint.x, y = _tempPoint.y + 2.0, z = _tempPoint.z }
local _offsetFacPos = { x = _facPoint.x, y = _facPoint.y + 2.0, z = _facPoint.z }
if land.isVisible(_offsetEnemyPos, _offsetFacPos) then
return _unit
end
end
end
return nil
end
function fac.getFacUnit(_facUnitName)
if _facUnitName == nil then
return nil
end
local _fac = Unit.getByName(_facUnitName)
if _fac ~= nil and _fac:isActive() and _fac:getLife() > 0 then
return _fac
end
return nil
end
-- gets the FAC player name if available
function fac.getFacName(_facUnitName)
local _facUnit = Unit.getByName(_facUnitName)
local _facName = _facUnitName
if _facUnit == nil then
--env.info('FAC: fac.getFacName: unit not found: '.._facUnitName)
return _facUnitName
end
if _facUnit:getPlayerName() ~= nil then
_facName = _facUnit:getPlayerName()
end
return _facName
end
function fac.facAutoLase(_facUnitName, _laserCode, _smoke, _lock, _colour,_knwnTarget)
local colorString = { ["0"] = "GREEN" ,["1"] = "RED" ,["2"] = "WHITE", ["3"] = "ORANGE" ,["4"] = "BLUE"}
--env.info('FAC DEBUG: ' .. _facUnitName .. ' autolase')
if _lock == nil then
_lock = fac.FAC_lock
end
local _mkrColor
local _facUnit = Unit.getByName(_facUnitName)
if _facUnit == nil then
--env.info('FAC: ' .. _facUnitName .. ' dead.')
-- FAC was in the list, now the unit is missing: probably dead
if fac.facUnits[_facUnitName] ~= nil then
fac.notifyCoalition("[Forward Air Controller \"" ..fac.getFacName(_facUnitName).. "\" MIA.]", 10, fac.facUnits[_facUnitName].side)
end
--remove fac
fac.cleanupFac(_facUnitName)
return
end
local side = _facUnit:getCoalition()
if side == 1 then
_mkrColor = fac.FAC_smokeColour_BLUE
elseif side == 2 then
_mkrColor = fac.FAC_smokeColour_RED
else
_mkrColor = 2
end
-- stop fac activity if fac is marked off-station CANCELS AUTO-LASE
if fac.facOnStation[_facUnitName] == nil then
env.info('FAC: ' .. _facUnitName .. ' is marked off-station, stopping autolase')
fac.cancelFacLase(_facUnitName)
fac.facCurrentTargets[_facUnitName] = nil
return
end
if fac.facLaserPointCodes[_facUnitName] == nil then
--env.info('FAC: fac.facAutoLase() ' .. _facUnitName .. ' has no laserCode, setting default')
fac.facLaserPointCodes[_facUnitName] = fac.FAC_laser_codes[1]
end
_laserCode = fac.facLaserPointCodes[_facUnitName]
--env.info('FAC: ' .. _facUnitName .. ' laser code: ' .. _laserCode)
if fac.facUnits[_facUnitName] == nil then
--env.info('FAC: ' .. _facUnitName .. ' not in fac.facUnits list, adding')
--add to list
fac.facUnits[_facUnitName] = { name = _facUnit:getName(), side = _facUnit:getCoalition() }
-- work out smoke colour
if _colour == nil then
if _facUnit:getCoalition() == 1 then
_colour = fac.FAC_smokeColour_RED
else
_colour = fac.FAC_smokeColour_BLUE
end
end
if fac.markerTypeColor[_facUnitName] ~= nil then
_colour = fac.markerTypeColor[_facUnitName]
end
if _smoke == nil then
if _facUnit:getCoalition() == 1 then
_smoke = fac.FAC_smokeOn_RED
else
_smoke = fac.FAC_smokeOn_BLUE
end
end
end
if fac.markerType[_facUnitName] == nil then
fac.markerType[_facUnitName] = "FLARES"
end
-- search for current unit
if _facUnit:isActive() == false then
fac.cleanupFac(_facUnitName)
env.info('FAC: ' .. _facUnitName .. ' Not Active - Waiting 30 seconds')
timer.scheduleFunction(fac.timerFacAutoLase, { _facUnitName, _laserCode, _smoke, _lock, _colour }, timer.getTime() + 30)
return
end
local _enemyUnit = fac.getCurrentFacUnit(_facUnit, _facUnitName)
if _enemyUnit == nil and fac.facCurrentTargets[_facUnitName] ~= nil then
local _tempUnitInfo = fac.facCurrentTargets[_facUnitName]
local _tempUnit = Unit.getByName(_tempUnitInfo.name)
if _tempUnit ~= nil and _tempUnit:getLife() > 0 and _tempUnit:isActive() == true then
fac.notifyCoalition("["..fac.getFacName(_facUnitName) .. " target " .. _tempUnitInfo.unitType .. " lost. Scanning for Targets.]", 10, _facUnit:getCoalition())
else
fac.notifyCoalition("["..fac.getFacName(_facUnitName) .. " target " .. _tempUnitInfo.unitType .. " KIA. Good Job! Scanning for Targets.]", 10, _facUnit:getCoalition())
--trigger.action.removeMark(fac.markID+_tempUnit:getID())
end
--remove from smoke list
fac.facSmokeMarks[_tempUnitInfo.name] = nil
-- remove from target list
fac.facCurrentTargets[_facUnitName] = nil
--stop lasing
fac.cancelFacLase(_facUnitName)
end
if _enemyUnit == nil then
if _knwnTarget == nil then
_enemyUnit = fac.findFacNearestVisibleEnemy(_facUnit, _lock)
else
_enemyUnit = _knwnTarget
end
if _enemyUnit ~= nil then
local tgtMarkID = timer.getTime() * 1000
-- store current target for easy lookup
fac.facCurrentTargets[_facUnitName] = { name = _enemyUnit:getName(), unitType = _enemyUnit:getTypeName(), unitId = _enemyUnit:getID() }
local _vel = _enemyUnit:getVelocity()
local _spd = 0
if _vel ~=nil then
_spd = math.sqrt(_vel.x^2+_vel.z^2)
end
local unitPos = _enemyUnit:getPoint()
local _lat, _lon = coord.LOtoLL(_enemyUnit:getPosition().p)
local _latLngStr = mist.tostringLL(_lat, _lon, 3, false)
local _latLngSecStr = mist.tostringLL(_lat, _lon, 3, true)
local _mgrsString = mist.tostringMGRS(coord.LLtoMGRS(coord.LOtoLL(_enemyUnit:getPosition().p)), 5)
local _eTypeName = _enemyUnit:getTypeName()
trigger.action.markToCoalition(tgtMarkID,_eTypeName.. " - DMS: " .. _latLngSecStr .." Altitude: ".. math.floor(unitPos.y) .."m/" .. math.floor(unitPos.y*3.28084) .."ft".. "\nHeading: ".. math.floor(getHeading(_enemyUnit) * 180/math.pi) .. "\nSpeed: " .. math.floor(_spd*2) .. " MPH" .."\nSpotted by: " .. fac.getFacName(_facUnitName), _enemyUnit:getPoint(), _facUnit:getCoalition(),false,fac.getFacName(_facUnitName).." marked a target")
timer.scheduleFunction(removeSetMark,{tgtMarkID},timer.getTime() + 120)
fac.notifyCoalition("["..fac.getFacName(_facUnitName) .. " lasing new target " .. _eTypeName .. '. CODE: ' .. _laserCode .. fac.getFacPositionString(_enemyUnit).."\nMarked with "..colorString[tostring(_colour)] .." "..fac.markerType[_facUnitName].."]" , 10, _facUnit:getCoalition())
local tgtMark = fac.markID+1
--local tgtMark = curMark
fac.markID = tgtMark
-- create smoke
if _smoke == true then
--trigger.action.removeMark(tgtMark)
--timer.scheduleFunction(trigger.action.removeMark,{tgtMark},timer.getTime() + 30)
--create first smoke
fac.createSmokeMarker(_enemyUnit, _colour,_facUnitName)
end
end
end
if _enemyUnit ~= nil then
fac.facLaseUnit(_enemyUnit, _facUnit, _facUnitName, _laserCode)
-- DEBUG
--env.info('FAC: Timer timerSparkleLase '.._facUnitName.." ".._laserCode.." ".._enemyUnit:getName())
--
local _vel = _enemyUnit:getVelocity()
local _spd = 0
if _vel ~=nil then
_spd = math.sqrt(_vel.x^2+_vel.z^2)
end
local timeNext
if _spd < 1 then
timeNext = 1
else
timeNext = 1/(_spd)
end
--trigger.action.outText(timeNext,10)
timer.scheduleFunction(fac.timerFacAutoLase, { _facUnitName, _laserCode, _smoke, _lock, _colour }, timer.getTime() + timeNext)
if _smoke == true then
local _nextSmokeTime = fac.facSmokeMarks[_enemyUnit:getName()]
--recreate smoke marker after 5 mins
if _nextSmokeTime ~= nil and _nextSmokeTime < timer.getTime() then
fac.createSmokeMarker(_enemyUnit, _colour,_facUnitName)
end
end
else
--env.info('FAC: LASE: No Enemies Nearby')
-- stop lazing the old spot
fac.cancelFacLase(_facUnitName)
timer.scheduleFunction(fac.timerFacAutoLase, { _facUnitName, _laserCode, _smoke, _lock, _colour }, timer.getTime() + 5)
end
end
-- used by the timer function
function fac.timerFacAutoLase(_args)
fac.facAutoLase(_args[1], _args[2], _args[3], _args[4], _args[5])
end
function fac.cleanupFac(_facUnitName)
-- clear laser - just in case
fac.cancelFacLase(_facUnitName)
-- Cleanup
fac.facLaserPoints[_facUnitName] = nil
fac.facIRPoints[_facUnitName] = nil
fac.facSmokeMarks[_facUnitName] = nil
fac.facUnits[_facUnitName] = nil
fac.facCurrentTargets[_facUnitName] = nil
fac.facAddedTo[_facUnitName] = nil
fac.facRadioAdded[_facUnitName] = nil
fac.facLaserPointCodes[_facUnitName] = nil
fac.facOnStation[_facUnitName] = nil
fac.markerType[_facUnitName] = nil
end
function fac.createFacSmokeMarker(_enemyUnit, _colour,_facUnitName)
--recreate in 5 mins
if fac.markerType[_facUnitName] == "SMOKE" then
fac.facSmokeMarks[_enemyUnit:getName()] = timer.getTime() + 300.0
else
fac.facSmokeMarks[_enemyUnit:getName()] = timer.getTime() + 5
end
-- move smoke 2 meters above target for ease
local _enemyPoint = _enemyUnit:getPoint()
if fac.markerType[_facUnitName] =="SMOKE" then
trigger.action.smoke({ x = _enemyPoint.x + 5.0, y = _enemyPoint.y + 5.0, z = _enemyPoint.z }, _colour)
else
trigger.action.signalFlare({ x = _enemyPoint.x + 5.0, y = _enemyPoint.y + 5.0, z = _enemyPoint.z }, _colour,0)
end
end
function fac.cancelFacLase(_facUnitName)
local _tempLase = fac.facLaserPoints[_facUnitName]
if _tempLase ~= nil then
Spot.destroy(_tempLase)
fac.facLaserPoints[_facUnitName] = nil
_tempLase = nil
end
local _tempIR = fac.facIRPoints[_facUnitName]
if _tempIR ~= nil then
Spot.destroy(_tempIR)
fac.facIRPoints[_facUnitName] = nil
_tempIR = nil
end
end
function fac.facLasePoint(_Point, _facUnit, _facUnitName, _laserCode)
--cancelLase(_facUnitName)
local _spots = {}
local _enemyVector = _Point
local _enemyVectorUpdated = { x = _enemyVector.x, y = _enemyVector.y + 2.0, z = _enemyVector.z }
local _oldLase = fac.facLaserPoints[_facUnitName]
local _oldIR = fac.facIRPoints[_facUnitName]
if _oldLase == nil or _oldIR == nil then
-- create lase
local _status, _result = pcall(function()
_spots['irPoint'] = Spot.createInfraRed(_facUnit, { x = 0, y = 2.0, z = 0 }, _enemyVectorUpdated)
_spots['laserPoint'] = Spot.createLaser(_facUnit, { x = 0, y = 2.0, z = 0 }, _enemyVectorUpdated, _laserCode)
return _spots
end)
if not _status then
env.error('FAC: ERROR: ' .. _result, false)
else
if _result.irPoint then
-- DEBUG
--env.info('FAC:' .. _facUnitName .. ' placed IR Pointer on '.._enemyUnit:getName())
fac.facIRPoints[_facUnitName] = _result.irPoint --store so we can remove after
end
if _result.laserPoint then
-- DEBUG
--env.info('FAC:' .. _facUnitName .. ' is Lasing '.._enemyUnit:getName()..'. CODE:'.._laserCode)
fac.facLaserPoints[_facUnitName] = _result.laserPoint
end
end
else
-- update lase
if _oldLase ~= nil then
_oldLase:setPoint(_enemyVectorUpdated)
end
if _oldIR ~= nil then
_oldIR:setPoint(_enemyVectorUpdated)
end
end
end
function fac.facLaseUnit(_enemyUnit, _facUnit, _facUnitName, _laserCode)
--cancelLase(_facUnitName)
local _spots = {}
local _enemyVector = _enemyUnit:getPoint()
local _enemyVectorUpdated = { x = _enemyVector.x, y = _enemyVector.y + 2.0, z = _enemyVector.z }
local _oldLase = fac.facLaserPoints[_facUnitName]
local _oldIR = fac.facIRPoints[_facUnitName]
if _oldLase == nil or _oldIR == nil then
-- create lase
local _status, _result = pcall(function()
_spots['irPoint'] = Spot.createInfraRed(_facUnit, { x = 0, y = 2.0, z = 0 }, _enemyVectorUpdated)
_spots['laserPoint'] = Spot.createLaser(_facUnit, { x = 0, y = 2.0, z = 0 }, _enemyVectorUpdated, _laserCode)
return _spots
end)
if not _status then
env.error('FAC: ERROR: ' .. _result, false)
else
if _result.irPoint then
-- DEBUG
--env.info('FAC:' .. _facUnitName .. ' placed IR Pointer on '.._enemyUnit:getName())
fac.facIRPoints[_facUnitName] = _result.irPoint --store so we can remove after
end
if _result.laserPoint then
-- DEBUG
--env.info('FAC:' .. _facUnitName .. ' is Lasing '.._enemyUnit:getName()..'. CODE:'.._laserCode)
fac.facLaserPoints[_facUnitName] = _result.laserPoint
end
end
else
-- update lase
if _oldLase ~= nil then
_oldLase:setPoint(_enemyVectorUpdated)
end
if _oldIR ~= nil then
_oldIR:setPoint(_enemyVectorUpdated)
end
end
end
-- Find nearest enemy to FAC that isn't blocked by terrain
function fac.findFacNearestVisibleEnemy(_facUnit, _targetType,_distance)
-- DEBUG
--local _facUnitName = _facUnit:getName()
--env.info('FAC:' .. _facUnitName .. ' fac.findFacNearestVisibleEnemy() ')
local _maxDistance = _distance or fac.FAC_maxDistance
local _x = 1
local _i = 1
local _units = nil
local _groupName = nil
local _nearestUnit = nil
local _nearestDistance = _maxDistance
local _enemyGroups
local _enemyStatic
local _facSide = _facUnit:getCoalition()
if _facUnit:getCoalition() == 1 then
_enemyGroups = coalition.getGroups(2, Group.Category.GROUND)
_enemyShips = coalition.getGroups(2, Group.Category.SHIP)
_enemyStatic = coalition.getStaticObjects(2)
else
_enemyGroups = coalition.getGroups(1, Group.Category.GROUND)
_enemyShips = coalition.getGroups(1, Group.Category.SHIP)
_enemyStatic = coalition.getStaticObjects(1)
end
local _facPoint = _facUnit:getPoint()
local _facPosition = _facUnit:getPosition()
local _tempPoint = nil
local _tempPosition = nil
local _tempDist = nil
local dist = {
id = world.VolumeType.SPHERE,
params = {
point = _facPoint,
radius = fac.FAC_maxDistance --max range ARTY
}
}
local findClosest = function(foundItem, val) -- generic search for all scenery
local _unit = foundItem
local foundOutput = nil
local foundObjectPos = nil
local sideCheck = foundItem:getCoalition()
if foundItem:getLife() > 1 and foundItem:inAir() == false then
if sideCheck ~= _facSide then
local samFactor = 1
local _unitPos = _unit:getPoint()
if _unit:hasAttribute("SAM TR") then
samFactor = 0.1
elseif _unit:hasAttribute("IR Guided SAM") then
samFactor = 0.5
elseif _unit:hasAttribute("AA_flak") then
samFactor = 0.7
end
local _tempADist = fac.getDistance(_unitPos,_facPoint)
_tempDist = _tempADist*samFactor
--trigger.action.outText("Found ".._tempDist.." " ..samFactor,10)
local _offsetEnemyPos = { x = _unitPos.x, y = _unitPos.y + 2.0, z = _unitPos.z }
local _offsetFacPos = { x = _facPoint.x, y = _facPoint.y + 2.0, z = _facPoint.z }
if land.isVisible(_offsetEnemyPos, _offsetFacPos) and _unit:isActive() then
local _type = fac.tgtCatType(foundItem)
if _tempADist < fac.FAC_maxDistance then
if _nearestDistance > _tempDist then
_nearestDistance = _tempDist
_nearestUnit = _unit
end
end
end
end
end
end
world.searchObjects(Object.Category.UNIT,dist,findClosest)
-- -- finish this function
-- local _vhpriority = false
-- local _vpriority = false
-- local _thpriority = false
-- local _tpriority = false
-- for _i = 1, #_enemyGroups do
-- if _enemyGroups[_i] ~= nil then
-- _groupName = _enemyGroups[_i]:getName()
-- _units = fac.getGroup(_groupName)
-- if #_units > 0 then
-- for _y = 1, #_units do
-- local _targeted = false
-- local _targetedJTAC = false
-- if not _distance then
-- _targeted = fac.alreadyFacTarget(_facUnit, _units[_x])
-- end
-- -- calc distance
-- _tempPoint = _units[_y]:getPoint()
-- _tempDist = fac.getDistance(_tempPoint, _facPoint)
-- if _tempDist < _maxDistance and _tempDist < _nearestDistance then
-- local _offsetEnemyPos = { x = _tempPoint.x, y = _tempPoint.y + 2.0, z = _tempPoint.z }
-- local _offsetFacPos = { x = _facPoint.x, y = _facPoint.y + 2.0, z = _facPoint.z }
-- -- calc visible
-- if land.isVisible(_offsetEnemyPos, _offsetFacPos) and _targeted == false and _targetedJTAC == false then
-- if (string.match(_units[_y]:getName(), "hpriority") ~= nil) and fac.isVehicle(_units[_y]) then
-- _vhpriority = true
-- elseif (string.match(_units[_y]:getName(), "priority") ~= nil) and fac.isVehicle(_units[_y]) then
-- _vpriority = true
-- elseif (string.match(_units[_y]:getName(), "hpriority") ~= nil) and fac.isInfantry(_units[_y]) then
-- _thpriority = true
-- elseif (string.match(_units[_y]:getName(), "priority") ~= nil) and fac.isInfantry(_units[_y]) then
-- _tpriority = true
-- end
-- end
-- end
-- end
-- end
-- end
-- end
-- for _i = 1, #_enemyGroups do
-- if _enemyGroups[_i] ~= nil then
-- _groupName = _enemyGroups[_i]:getName()
-- _units = fac.getGroup(_groupName)
-- if #_units > 0 then
-- for _x = 1, #_units do
-- --check to see if a FAC has already targeted this unit only if a distance
-- --wasnt passed in
-- local _targeted = false
-- if not _distance then
-- _targeted = fac.alreadyFacTarget(_facUnit, _units[_x])
-- end
-- local _allowedTarget = true
-- if _targetType == "vehicle" and _vhpriority == true then
-- _allowedTarget = (string.match(_units[_x]:getName(), "hpriority") ~= nil) and fac.isVehicle(_units[_x])
-- elseif _targetType == "vehicle" and _vpriority == true then
-- _allowedTarget = (string.match(_units[_x]:getName(), "priority") ~= nil) and fac.isVehicle(_units[_x])
-- elseif _targetType == "vehicle" then
-- _allowedTarget = fac.isVehicle(_units[_x])
-- elseif _targetType == "troop" and _hpriority == true then
-- _allowedTarget = (string.match(_units[_x]:getName(), "hpriority") ~= nil) and fac.isInfantry(_units[_x])
-- elseif _targetType == "troop" and _priority == true then
-- _allowedTarget = (string.match(_units[_x]:getName(), "priority") ~= nil) and fac.isInfantry(_units[_x])
-- elseif _targetType == "troop" then
-- _allowedTarget = fac.isInfantry(_units[_x])
-- elseif _vhpriority == true or _thpriority == true then
-- _allowedTarget = (string.match(_units[_x]:getName(), "hpriority") ~= nil)
-- elseif _vpriority == true or _tpriority == true then
-- _allowedTarget = (string.match(_units[_x]:getName(), "priority") ~= nil)
-- else
-- _allowedTarget = true
-- end
-- if _units[_x]:isActive() == true and _targeted == false and _allowedTarget == true then
-- -- calc distance
-- _tempPoint = _units[_x]:getPoint()
-- _tempDist = fac.getDistance(_tempPoint, _facPoint)
-- if _tempDist < _maxDistance and _tempDist < _nearestDistance then
-- local _offsetEnemyPos = { x = _tempPoint.x, y = _tempPoint.y + 2.0, z = _tempPoint.z }
-- local _offsetFacPos = { x = _facPoint.x, y = _facPoint.y + 2.0, z = _facPoint.z }
-- -- calc visible
-- if land.isVisible(_offsetEnemyPos, _offsetFacPos) then
-- _nearestDistance = _tempDist
-- _nearestUnit = _units[_x]
-- end
-- end
-- end
-- end
-- end
-- end
-- end
if _nearestUnit == nil then
return nil
end
return _nearestUnit
end
-- tests whether the unit is targeted by another FAC
function fac.alreadyFacTarget(_facUnit, _enemyUnit)
for _, _facTarget in pairs(fac.facCurrentTargets) do
if _facTarget.unitId == _enemyUnit:getID() then
-- env.info("FAC: ALREADY TARGET")
return true
end
end
return false
end
function fac.scanForTGToff(_args)
--fac.facManTGT[_args[1]] = {}
local _fac = Unit.getByName(_args[1])
local _side = _fac:getCoalition()
fac.setFacOnStation({_args[1], nil})
--fac.cancelFacLase(_args[1])
--fac.notifyCoalition("Forward Air Controller \"" .. fac.getFacName(_args[1]) .. "\" off-station.", 10, _fac:getCoalition())
end
function fac.scanForTGT (_args)
--trigger.action.outText("scanning ",10)
local _fac = Unit.getByName(_args[1])
local _side = _fac:getCoalition()
local _facPos = _fac:getPoint()
local _facGID = fac.getGroupId(_fac)
local _i
local _j
local _offsetFacPos = { x = _facPos.x, y = _facPos.y + 2.0, z = _facPos.z }
local dist2 = {
id = world.VolumeType.SPHERE,
params = {
point = _fac:getPoint(),
radius = fac.FAC_maxDistance --max range ARTY
}
}
--fac.cancelFacLase(_args[1])
--fac.facCurrentTargets[_args[1]] = nil
--trigger.action.outText("scanning ",10)
fac.facManTGT[_args[1]] = {}
local tempFound = {}
local aaTempFound = {}
local count = 0
local getTGT = function(foundItemM, val) -- generic search for all scenery
--trigger.action.outText("scanning ",10)
--local _checkArty = fac.isArty(foundItem)
--local _tempTGTGroup = foundItem:getGroup()
if _side ~= foundItemM:getCoalition() then -- check for friendly
--if count <6 then
--trigger.action.outText("scanning ",10)
--trigger.action.outText("scanning "..foundItemM:getTypeName(),10)
if foundItemM:inAir() == false and foundItemM:isActive() and foundItemM:getLife() > 1 then
local _tempPoint= foundItemM:getPoint()
local _offsetEnemyPos = { x = _tempPoint.x, y = _tempPoint.y + 2.0, z = _tempPoint.z }
if land.isVisible(_offsetEnemyPos, _offsetFacPos) then
--trigger.action.outText("scanning ",10)
--trigger.action.outText("FOUND "..foundItemM:getTypeName(),10)
if foundItemM:hasAttribute("SAM TR") or foundItemM:hasAttribute("IR Guided SAM") or foundItemM:hasAttribute("AA_flak") then
table.insert(aaTempFound,foundItemM)
else
table.insert(tempFound,foundItemM)
--count = count + 1
end
end
end
--end
--return
end
end
world.searchObjects(Object.Category.UNIT,dist2,getTGT)
for count = 1,10 do
if #aaTempFound >= count then
table.insert(fac.facManTGT[_args[1]],aaTempFound[count])
else
table.insert(fac.facManTGT[_args[1]],tempFound[count])
end
end
local _tgtList = fac.facManTGT[_args[1]]
local count = 0
for _i=1, #_tgtList do
local tgtp = _tgtList[_i]:getPoint()
local _TGTdist = math.sqrt(((tgtp.z-_facPos.z)^2)+((tgtp.x-_facPos.x)^2))
-- local _TGTheading = math.atan((tp.z-_facPos.z)/(tp.x-_facPos.x))
-- if _TGTheading > 0 then
-- _TGTheading= _TGTheading + math.pi
-- end
-- _TGTheadDeg = _TGTheading*180/math.pi
-- if _TGTheadDeg <0 then
-- _TGTheadDeg = _TGTheadDeg +360
-- end
--trigger.action.outText("FOUND "..foundItem:getTypeName(),10)
local dy = tgtp.z-_facPos.z
local dx = tgtp.x-_facPos.x
count = count + 1
local _TGTheading = math.atan(dy/dx)
--correcting for coordinate space
local recceMarkID = timer.getTime()*1000 + count
if dy < 0 then -- dy = -1 90-270
if dx < 0 then --dy/dx = 1 180-270
--trigger.action.outText(_artyInRange:getName().." Firing SW:\n".. (_fireheading/math.pi)*180 .."\n", 300)
_TGTheading= _TGTheading + math.pi
else
--trigger.action.outText(_artyInRange:getName().." Firing SE:\n".. (_fireheading/math.pi)*180 .."\n", 300)
_TGTheading= _TGTheading + math.pi
end
else --dy = 1 270-90
if dx < 0 then --dy/dx = -1 270-0
--trigger.action.outText(_artyInRange:getName().." Firing NW:\n".. (_fireheading/math.pi)*180 .."\n", 300)
_TGTheading= _TGTheading + 2*math.pi
else --dy/dx = 1 0-90
--trigger.action.outText(_artyInRange:getName().." Firing NE:\n".. (_fireheading/math.pi)*180 .."\n", 300)
_TGTheading= _TGTheading
end
end
local _TGTheadDeg =(_TGTheading)/math.pi*180
--math.floor(_TGTdist) .."m/" .. math.floor(_TGTdist*3.28084) .."ft"
trigger.action.outTextForGroup(_facGID,"Target ".._i .. ":" .. _tgtList[_i]:getTypeName() .. " Bearing:" ..math.floor(_TGTheadDeg) .. " Range:"..math.floor(_TGTdist) .."m/" .. math.floor(_TGTdist*3.28084) .."ft",30)
trigger.action.markToGroup(recceMarkID,"Target ".._i ..":".. _tgtList[_i]:getTypeName(), _tgtList[_i]:getPoint(),_facGID,false,"")
timer.scheduleFunction(removeSetMark,{recceMarkID},timer.getTime() + 60)
end
end
function fac.scanForTGTai (_args)
--trigger.action.outText("scanning 1" .. _args[1] ,10)
local _fac = Unit.getByName(_args[1])
local _tgtList = {}
if _fac ~= nil then
local _side = _fac:getCoalition()
local _facPos = _fac:getPoint()
--local _facGID = fac.getGroupId(_fac)
local _i
local _j
local _offsetFacPos = { x = _facPos.x, y = _facPos.y + 2.0, z = _facPos.z }
local dist2 = {
id = world.VolumeType.SPHERE,
params = {
point = _fac:getPoint(),
radius = fac.FAC_maxDistance/10 * 5 + _facPos.y --max range ARTY
}
}
--fac.cancelFacLase(_args[1])
--fac.facCurrentTargets[_args[1]] = nil
--trigger.action.outText("scanning 2",10)
local tempFound = {}
local aaTempFound = {}
local count = 0
local getTGT = function(foundItemM, val) -- generic search for all scenery
--trigger.action.outText("scanning ",10)
--local _checkArty = fac.isArty(foundItem)
--local _tempTGTGroup = foundItem:getGroup()
if _side ~= foundItemM:getCoalition() then -- check for friendly
--if count <6 then
--trigger.action.outText("scanning ",10)
--trigger.action.outText("scanning "..foundItemM:getTypeName(),10)
if foundItemM:inAir() == false and foundItemM:isActive() and foundItemM:getLife() > 1 then
local _tempPoint= foundItemM:getPoint()
local _offsetEnemyPos = { x = _tempPoint.x, y = _tempPoint.y + 2.0, z = _tempPoint.z }
if land.isVisible(_offsetEnemyPos, _offsetFacPos) then
--trigger.action.outText("scanning ",10)
--trigger.action.outText("FOUND "..foundItemM:getTypeName(),10)
local _vel = foundItemM:getVelocity()
local _spd
if _vel ~=nil then
_spd = math.sqrt(_vel.x^2+_vel.z^2)
end
if _spd == 0 then
if foundItemM:hasAttribute("SAM TR") or foundItemM:hasAttribute("IR Guided SAM") or foundItemM:hasAttribute("AA_flak") then
table.insert(aaTempFound,foundItemM)
else
table.insert(tempFound,foundItemM)
--count = count + 1
end
end
end
end
--end
--return
end
end
world.searchObjects(Object.Category.UNIT,dist2,getTGT)
for count = 1,10 do
if #aaTempFound >= count then
table.insert(_tgtList,aaTempFound[count])
else
table.insert(_tgtList,tempFound[count])
end
end
--local _tgtList = fac.facManTGT[_args[1]]
end
return _tgtList
end
function fac.setManualTgt(_args)
fac.cancelFacLase(_args[1])
local _fac = Unit.getByName(_args[1])
local _facGID = fac.getGroupId(_fac)
fac.notifyCoalition("[Forward Air Controller \"" .. fac.getFacName(_args[1]) .. "\" starting manual laze. Reseting to new target]", 10, _fac:getCoalition())
--fac.facCurrentTargets[_args[1]] = nil
fac.setFacOnStation({_args[1],true})
--fac.cancelFacLase(_args[1])
--fac.facCurrentTargets[_facUnitName]
--fac.facCurrentTargets[_args[1]] = nil
--fac.facUnits[_facUnitName] = nil
local _tgtList = fac.facManTGT[_args[1]]
if _tgtList == nil then
trigger.action.outTextForGroup(_facGID,"Error loading tgts, please reset FAC",10)
return
end
local _enemyUnit = _tgtList[_args[2]]
fac.facCurrentTargets[_args[1]] = { name = _enemyUnit:getName(), unitType = _enemyUnit:getTypeName(), unitId = _enemyUnit:getID() }
local _lock = "all"
if _fac:getCoalition() == 1 then
local _colour = fac.FAC_smokeColour_RED
local _smoke = fac.FAC_smokeOn_RED
else
local _colour = fac.FAC_smokeColour_BLUE
local _smoke = fac.FAC_smokeOn_BLUE
end
if fac.markerTypeColor[_args[1]] ~= nil then
_colour = fac.markerTypeColor[_args[1]]
end
local _laserCode = fac.facLaserPointCodes[_args[1]]
if _laserCode == nil then
fac.setFacLaserCode({_args[1], fac.FAC_laser_codes[1]})
_laserCode = fac.facLaserPointCodes[_args[1]]+1
end
--local _facGroup =
trigger.action.outTextForGroup(_facGID,"Designating Target ".._args[2]..": ".._tgtList[_args[2]]:getTypeName(),10)
if _args[2] > #_tgtList then
trigger.action.outTextForGroup(_facGID,"Invalid Target",10)
elseif _tgtList[_args[2]]:getLife() > 0 then
fac.notifyCoalition("[Forward Air Controller \"" .. fac.getFacName(_args[1]) .. "\" starting manual laze.]", 10, _fac:getCoalition())
fac.facAutoLase(_args[1], _laserCode, _smoke, _lock, _colour)
fac.createSmokeMarker(_tgtList[_args[2]], _colour,_args[1])
--fac.facLaseUnit(_tgtList[_args[2]], _fac, _args[1], _laserCode)
-- --fac.notifyCoalition(fac.getFacName(_args[1]) .. " lasing new target " .. _tgtList[_args[2]]:getTypeName() .. '. CODE: ' .. _laserCode .. fac.getFacPositionString(_tgtList[_args[2]]), 10, _fac:getCoalition())
-- --trigger.action.outTextForGroup(_facGID,"Designated Target ".._args[2].. " " .. _tgtList[_args[2]]:getTypeName().." for attack",10)
-- if _smoke == true then
-- local _nextSmokeTime = fac.facSmokeMarks[_tgtList[_args[2]]:getName()]
-- --recreate smoke marker after 5 mins
-- if _nextSmokeTime ~= nil and _nextSmokeTime < timer.getTime() then
-- fac.createSmokeMarker(_tgtList[_args[2]], _colour,_args[1])
-- end
-- end
trigger.action.outTextForGroup(_facGID,"Designated Target ".._args[2].. " " .. _tgtList[_args[2]]:getTypeName().." for attack",10)
elseif _tgtList[_args[2]]:getLife() < 1 then
trigger.action.outTextForGroup(_facGID,"Designated Target ".._args[2].. " " .. _tgtList[_args[2]]:getTypeName().." is already dead",10)
end
end
-- Adds menuitem to all FAC units that are active
function fac.addFacF10MenuOptions()
-- Loop through all FAC units
timer.scheduleFunction(fac.addFacF10MenuOptions, nil, timer.getTime() + 10)
for _, _facUnitName in pairs(fac.facPilotNames) do
local status, error = pcall(function()
local _unit = fac.getFacUnit(_facUnitName)
if _unit ~= nil then
local _groupId = fac.getGroupId(_unit)
if _groupId then
if fac.facAddedTo[tostring(_groupId)] == nil then
local _rootPath = missionCommands.addSubMenuForGroup(_groupId, "FAC")
local _TGTModePath = missionCommands.addSubMenuForGroup(_groupId, "Targeting Mode",_rootPath)
local _AutoTGTModePath = missionCommands.addSubMenuForGroup(_groupId, "Auto Mode",_TGTModePath)
local _ManTGTModePath = missionCommands.addSubMenuForGroup(_groupId, "Manual Mode",_TGTModePath)
missionCommands.addCommandForGroup(_groupId, "Auto Laze On", _AutoTGTModePath, fac.setFacOnStation, { _facUnitName, true})
missionCommands.addCommandForGroup(_groupId, "Auto Laze Off", _AutoTGTModePath, fac.setFacOnStation, { _facUnitName, nil})
missionCommands.addCommandForGroup(_groupId, "Scan for Close Targets", _ManTGTModePath, fac.scanForTGT, { _facUnitName})
missionCommands.addCommandForGroup(_groupId, "Stop Manual Designating", _ManTGTModePath, fac.scanForTGToff, { _facUnitName})
local _TGTSelectPath = missionCommands.addSubMenuForGroup(_groupId, "Select Found Target",_ManTGTModePath)
missionCommands.addCommandForGroup(_groupId, "Target 1", _TGTSelectPath, fac.setManualTgt, { _facUnitName, 1})
missionCommands.addCommandForGroup(_groupId, "Target 2", _TGTSelectPath, fac.setManualTgt, { _facUnitName, 2})
missionCommands.addCommandForGroup(_groupId, "Target 3", _TGTSelectPath, fac.setManualTgt, { _facUnitName, 3})
missionCommands.addCommandForGroup(_groupId, "Target 4", _TGTSelectPath, fac.setManualTgt, { _facUnitName, 4})
missionCommands.addCommandForGroup(_groupId, "Target 5", _TGTSelectPath, fac.setManualTgt, { _facUnitName, 5})
missionCommands.addCommandForGroup(_groupId, "Target 6", _TGTSelectPath, fac.setManualTgt, { _facUnitName, 6})
missionCommands.addCommandForGroup(_groupId, "Target 7", _TGTSelectPath, fac.setManualTgt, { _facUnitName, 7})
missionCommands.addCommandForGroup(_groupId, "Target 8", _TGTSelectPath, fac.setManualTgt, { _facUnitName, 8})
missionCommands.addCommandForGroup(_groupId, "Target 9", _TGTSelectPath, fac.setManualTgt, { _facUnitName, 9})
missionCommands.addCommandForGroup(_groupId, "Target 10", _TGTSelectPath, fac.setManualTgt, { _facUnitName, 10})
missionCommands.addCommandForGroup(_groupId, "Call artillery strikes on all manual targets", _ManTGTModePath, fac.multiStrike, { _facUnitName})
-- add each possible laser code as a menu option
local _lzrpath = missionCommands.addSubMenuForGroup(_groupId, "Avaliable Laser Codes",_rootPath)
for _, _laserCode in pairs(fac.FAC_laser_codes) do
missionCommands.addCommandForGroup(_groupId, string.format("Laser code: %s", _laserCode), _lzrpath, fac.setFacLaserCode, { _facUnitName, _laserCode})
end
local _lzerCustPath = missionCommands.addSubMenuForGroup(_groupId, "Custom Laser Code", _lzrpath)
local _digCount
local _lzerCode1Path = missionCommands.addSubMenuForGroup(_groupId, "Digit 1", _lzerCustPath)
for _digCount = 1 ,1 do
missionCommands.addCommandForGroup(_groupId, _digCount, _lzerCode1Path, fac.setCustCode, { _facUnitName, 1,_digCount})
end
local _lzerCode2Path = missionCommands.addSubMenuForGroup(_groupId, "Digit 2", _lzerCustPath)
for _digCount = 1 ,6 do
missionCommands.addCommandForGroup(_groupId, _digCount, _lzerCode2Path, fac.setCustCode, { _facUnitName, 2,_digCount})
end
local _lzerCode3Path = missionCommands.addSubMenuForGroup(_groupId, "Digit 3", _lzerCustPath)
for _digCount = 1 ,8 do
missionCommands.addCommandForGroup(_groupId, _digCount, _lzerCode3Path, fac.setCustCode, { _facUnitName, 3,_digCount})
end
local _lzerCode4Path = missionCommands.addSubMenuForGroup(_groupId, "Digit 4", _lzerCustPath)
for _digCount = 1 ,8 do
missionCommands.addCommandForGroup(_groupId, _digCount, _lzerCode4Path, fac.setCustCode, { _facUnitName, 4,_digCount})
end
local _artyPath = missionCommands.addSubMenuForGroup(_groupId, "Artillery Control",_rootPath)
missionCommands.addCommandForGroup(_groupId, "Check Avaliable Arty Groups", _artyPath , fac.checkTask, {_facUnitName})
missionCommands.addCommandForGroup(_groupId, "Call Artillery Fire Mission", _artyPath , fac.callFireMission, { _facUnitName,fac.fireMissionRounds,0})
missionCommands.addCommandForGroup(_groupId, "Call Illummination", _artyPath , fac.callFireMission, { _facUnitName,fac.fireMissionRounds,1})
missionCommands.addCommandForGroup(_groupId, "Call Mortar Strike Only(Anti-infantry)", _artyPath , fac.callFireMission, { _facUnitName,fac.fireMissionRounds,2})
missionCommands.addCommandForGroup(_groupId, "Call Heavy Artillery Strike Only <No Smart Munition> (Anti-Material)", _artyPath , fac.callFireMission, { _facUnitName,10,3})
local _cMissilePath = missionCommands.addSubMenuForGroup(_groupId, "Air/Naval THAWK Strike Menu",_artyPath)
missionCommands.addCommandForGroup(_groupId, "Single Target", _cMissilePath , fac.callFireMission, { _facUnitName,1,4})
missionCommands.addCommandForGroup(_groupId, "Multi Target (Manual Targeting Required), GPS weapons only", _cMissilePath , fac.callFireMissionMulti, { _facUnitName,1,4})
--missionCommands.addCommandForGroup(_groupId, "Carpet Bomb (Define on F10 Map with syntax: AttackAz CBRQT), Dumb bombs only", _cMissilePath , world.addEventHandler, CrptBmbDesig)
missionCommands.addCommandForGroup(_groupId, "Carpet Bomb (Turn your aircraft to desired attack azimuth), Dumb bombs only", _cMissilePath , fac.callFireMissionCarpet2, { _facUnitName,1,5})
local _mkrpath = missionCommands.addSubMenuForGroup(_groupId, "Marker Type",_rootPath)
local _colorSmokePath = missionCommands.addSubMenuForGroup(_groupId, "Smoke",_mkrpath)
missionCommands.addCommandForGroup(_groupId, "GREEN", _colorSmokePath, fac.setMarkerColor, { _facUnitName, "SMOKE",0})
missionCommands.addCommandForGroup(_groupId, "RED", _colorSmokePath , fac.setMarkerColor, { _facUnitName, "SMOKE",1})
missionCommands.addCommandForGroup(_groupId, "ORANGE", _colorSmokePath , fac.setMarkerColor, { _facUnitName, "SMOKE",3})
missionCommands.addCommandForGroup(_groupId, "BLUE", _colorSmokePath , fac.setMarkerColor, { _facUnitName, "SMOKE",4})
missionCommands.addCommandForGroup(_groupId, "WHITE", _colorSmokePath , fac.setMarkerColor, { _facUnitName, "SMOKE",2})
local _colorFlarePath = missionCommands.addSubMenuForGroup(_groupId, "FLARES",_mkrpath)
missionCommands.addCommandForGroup(_groupId, "GREEN", _colorFlarePath, fac.setMarkerColor, { _facUnitName, "FLARES",0})
missionCommands.addCommandForGroup(_groupId, "WHITE", _colorFlarePath , fac.setMarkerColor, { _facUnitName, "FLARES",2})
missionCommands.addCommandForGroup(_groupId, "ORANGE", _colorFlarePath , fac.setMarkerColor, { _facUnitName, "FLARES",3})
--missionCommands.addCommandForGroup(_groupId, "Smoke", _mkrpath, fac.setMarkerType, { _facUnitName, "SMOKE"})
--missionCommands.addCommandForGroup(_groupId, "FLARES", _mkrpath , fac.setMarkerType, { _facUnitName, "FLARES"})
missionCommands.addCommandForGroup(_groupId, "Map Marker", _mkrpath , fac.setMapMarker, { _facUnitName})
--missionCommands.addCommandForGroup(_groupId, "RECCE", _mkrpath , fac.recceDetect, { _facUnitName})
fac.facAddedTo[tostring(_groupId)] = true
end
end
--[[else
env.info(string.format("FAC DEBUG: unit nil %s",_facUnitName)) ]]
end
end)
end
for _, _facUnitName in pairs(fac.reccePilotNames) do
local status, error = pcall(function()
local _unitR = fac.getFacUnit(_facUnitName)
if _unitR ~= nil then
local _groupIdR = fac.getGroupId(_unitR)
if _groupIdR then
if fac.RECCEAddedTo[tostring(_groupIdR)] == nil then
local _rootPathR = missionCommands.addSubMenuForGroup(_groupIdR, "RECCE")
missionCommands.addCommandForGroup(_groupIdR, "RECCE", _rootPathR, fac.recceDetect, { _facUnitName})
missionCommands.addCommandForGroup(_groupIdR, "Strategic Strike", _rootPathR, fac.stratStrike, { _facUnitName})
--missionCommands.addCommandForGroup(_groupId, "Go Off-Station", _rootPathR, fac.recceDetect, { _facUnitName, nil})
fac.RECCEAddedTo[tostring(_groupIdR)] = true
end
end
--[[else
env.info(string.format("FAC DEBUG: unit nil %s",_facUnitName)) ]]
end
end)
if (not status) then
env.error(string.format("Error adding f10 to RECCE: %s", error), false)
end
end
local status, error = pcall(function()
-- now do any player controlled aircraft that ARENT FAC units
if fac.FAC_FACStatusF10 then
-- get all BLUE players
fac.addFacRadioCommand(2)
-- get all RED players
fac.addFacRadioCommand(1)
end
end)
if (not status) then
env.error(string.format("Error adding f10 to other players: %s", error), false)
end
end
function fac.setMapMarker(_args)
local _facUnitName = _args[1]
local _unit = nil
local _facUnit = fac.getFacUnit(_facUnitName)
local _groupId = fac.getGroupId(_facUnit)
local tgtMarkID = timer.getTime()*1000
local recceMarkID = timer.getTime()*1000
trigger.action.outTextForGroup(_groupId,"Processing Mark",10)
if fac.facCurrentTargets[_facUnitName] ~= nil then
_unit = Unit.getByName(fac.facCurrentTargets[_facUnitName].name)
tempMarkID = tgtMarkID
--fac.markID = tgtMarkID + 1
elseif _args[2] ~= nil then
_unit = _args[2]
tempMarkID = recceMarkID
--fac.recceID = recceMarkID + 1
else
trigger.action.outTextForGroup(_groupId,"No Target to Mark",10)
end
if _unit ~=nil and _unit:isActive() then
local _vel = _unit:getVelocity()
local _spd = 0
if _vel ~=nil then
_spd = math.sqrt(_vel.x^2+_vel.z^2)
end
local unitPos = _unit:getPoint()
local _lat, _lon = coord.LOtoLL(_unit:getPosition().p)
local _latLngStr = mist.tostringLL(_lat, _lon, 3, false)
local _latLngSecStr = mist.tostringLL(_lat, _lon, 3, true)
local _mgrsString = mist.tostringMGRS(coord.LLtoMGRS(coord.LOtoLL(_unit:getPosition().p)), 5)
trigger.action.markToCoalition(tgtMarkID,_unit:getTypeName().. " - DMS: " .. _latLngSecStr .." Altitude: ".. math.floor(unitPos.y) .."m/" .. math.floor(unitPos.y*3.28084) .."ft".. "\nHeading: ".. math.floor(getHeading(_unit) * 180/math.pi) .. "\nSpeed: " .. math.floor(_spd*2) .. " MPH" .."\nSpotted by: " .. fac.getFacName(_facUnitName), _unit:getPoint(), _facUnit:getCoalition(),false,fac.getFacName(_facUnitName).." marked a target")
timer.scheduleFunction(removeSetMark,{tgtMarkID},timer.getTime() + 300)
end
end
function fac.setMarkerColor(_args)
local _facUnitName = _args[1]
local _mkrType = _args[2]
fac.cancelFacLase(_facUnitName)
fac.setFacOnStation({_args[1],nil})
fac.markerType[_facUnitName] = _mkrType
fac.markerTypeColor[_facUnitName] = _args[3]
fac.setMarkerType(_args)
fac.setFacOnStation({_args[1],true})
end
function fac.setMarkerType(_args)
local _facUnitName = _args[1]
local _mkrType = _args[2]
local _facUnit = fac.getFacUnit(_facUnitName)
local _groupId = fac.getGroupId(_facUnit)
local colorString = { ["0"] = "GREEN" ,["1"] = "RED" ,["2"] = "WHITE", ["3"] = "ORANGE" ,["4"] = "BLUE"}
local _mkrColor
local _facUnit = Unit.getByName(_facUnitName)
local side = _facUnit:getCoalition()
if side == 1 then
_mkrColor = fac.FAC_smokeColour_BLUE
elseif side == 2 then
_mkrColor = fac.FAC_smokeColour_RED
else
_mkrColor = 2
end
if _args[3]~=nil then
_mkrColor = _args[3]
end
if _facUnit == nil then
--env.info('FAC DEBUG: fac.setFacLaserCode() _facUnit is null, aborting.')
return
end
fac.markerTypeColor[_facUnitName] = _args[3]
fac.markerType[_facUnitName] = _mkrType
if fac.facOnStation[_facUnitName] == true then
fac.notifyCoalition("[Forward Air Controller \"" .. fac.getFacName(_facUnitName) .. "\" on-station marking with: "..colorString[tostring(_mkrColor)].." "..fac.markerType[_facUnitName]..".]", 10, _facUnit:getCoalition())
else
trigger.action.outTextForGroup(_groupId,"Marker set to ".. colorString[tostring(_mkrColor)].." "..fac.markerType[_facUnitName],10)
end
--fac.setFacOnStation({ _facUnitName, nil})
--fac.setFacOnStation( {_facUnitName, true})
end
function fac.addFacRadioCommand(_side)
local _players = coalition.getPlayers(_side)
if _players ~= nil then
for _, _playerUnit in pairs(_players) do
local _groupId = fac.getGroupId(_playerUnit)
if _groupId then
-- env.info("adding command for "..index)
if fac.facRadioAdded[tostring(_groupId)] == nil then
-- env.info("about command for "..index)
missionCommands.addCommandForGroup(_groupId, "FAC Status", nil, fac.getFacStatus, { _playerUnit:getName() })
local _airstrikeMenu = missionCommands.addSubMenuForGroup(_groupId, "Air OPS Menu")
missionCommands.addCommandForGroup(_groupId, "Map Attack (Define on F10 Map with syntax: AttackAz CBRQT or TDRQT), CB for Carpet/TD for TALD", _airstrikeMenu , fac.carpetMapDesignate, {nil})
missionCommands.addCommandForGroup(_groupId, "RECCE FLT (Define on F10 Map with syntax: RECCE)", _airstrikeMenu , fac.RECCEDesignate, {nil})
--missionCommands.addCommandForGroup(_groupId, "TALD Strike (Define on F10 Map with syntax: AttackAz TDRQT)", _airstrikeMenu , fac.carpetMapDesignate, {nil})
--local _cMissilePath = missionCommands.addSubMenuForGroup(_groupId, "Air Strike Menu",_airstrikeMenu)
fac.facRadioAdded[tostring(_groupId)] = true
-- env.info("Added command for " .. index)
end
end
end
end
end
function fac.setFacLaserCode(_args)
local _facUnitName = _args[1]
local _laserCode = _args[2]
local _facUnit = fac.getFacUnit(_facUnitName)
--fac.setFacOnStation( {_facUnitName, nil})
--fac.setFacOnStation( {_facUnitName, true})
if _facUnit == nil then
--env.info('FAC DEBUG: fac.setFacLaserCode() _facUnit is null, aborting.')
return
end
fac.facLaserPointCodes[_facUnitName] = _laserCode
if fac.facOnStation[_facUnitName] == true then
fac.notifyCoalition("[Forward Air Controller \"" .. fac.getFacName(_facUnitName) .. "\" on-station using CODE: "..fac.facLaserPointCodes[_facUnitName]..".]", 10, _facUnit:getCoalition())
end
end
function fac.setCustCode(_args)
local _facUnitName = _args[1]
local _facUnit = fac.getFacUnit(_facUnitName)
if fac.facLaserPointCodes[_facUnitName] == nil then
fac.facLaserPointCodes[_facUnitName] = "1688"
end
local tempCode = fac.facLaserPointCodes[_facUnitName]
tempCode = fac.replace_char(_args[2],tempCode,_args[3])
fac.facLaserPointCodes[_facUnitName] = tempCode
fac.notifyCoalition("[Forward Air Controller \"" .. fac.getFacName(_facUnitName) .. "\" on-station using CODE: "..fac.facLaserPointCodes[_facUnitName]..".]", 10, _facUnit:getCoalition())
end
function fac.replace_char(pos, str, r)
return str:sub(1, pos-1) .. r .. str:sub(pos+1)
end
function fac.setFacOnStation(_args)
local _facUnitName = _args[1]
local _onStation = _args[2]
local _facUnit = fac.getFacUnit(_facUnitName)
local colorString = { ["0"] = "GREEN" ,["1"] = "RED" ,["2"] = "WHITE", ["3"] = "ORANGE" ,["4"] = "BLUE"}
local _mkrColor = tostring(fac.markerTypeColor[_facUnitName])
-- going on-station
if _facUnit == nil then
--env.info('FAC DEBUG: fac.setFacOnStation() _facUnit is null, aborting.')
return
end
if fac.facLaserPointCodes[_facUnitName] == nil then
-- set default laser code
--env.info('FAC: ' .. _facUnitName .. ' no laser code, assigning default ' .. fac.FAC_laser_codes[1])
fac.setFacLaserCode( {_facUnitName, fac.FAC_laser_codes[1]} )
end
-- going on-station from off-station
if fac.facOnStation[_facUnitName] == nil and _onStation == true then
env.info('FAC: ' .. _facUnitName .. ' going on-station')
fac.cancelFacLase(_facUnitName)
--fac.scanForTGToff({_facUnitName})
fac.notifyCoalition("[Forward Air Controller \"" .. fac.getFacName(_facUnitName) .. "\" on-station using CODE: "..fac.facLaserPointCodes[_facUnitName]..".]", 10, _facUnit:getCoalition())
fac.setFacLaserCode( {_facUnitName, fac.facLaserPointCodes[_facUnitName]} )
end
-- going off-station from on-station
if fac.facOnStation[_facUnitName] == true and _onStation == nil then
env.info('FAC: ' .. _facUnitName .. ' going off-station')
fac.notifyCoalition("[Forward Air Controller \"" .. fac.getFacName(_facUnitName) .. "\" off-station.]", 10, _facUnit:getCoalition())
fac.cancelFacLase(_facUnitName)
fac.facUnits[_facUnitName] = nil
--fac.scanForTGToff({_facUnitName})
end
fac.facOnStation[_facUnitName] = _onStation
end
--get distance in meters assuming a Flat world
function fac.getDistance(_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
function fac.notifyCoalition(_message, _displayFor, _side)
trigger.action.outTextForCoalition(_side, _message, _displayFor)
trigger.action.outSoundForCoalition(_side, "radiobeep.ogg")
end
-- Returns only alive units from group but the group / unit may not be active
function fac.getGroup(groupName)
local _groupUnits = Group.getByName(groupName)
local _filteredUnits = {} --contains alive units
local _x = 1
if _groupUnits ~= nil and _groupUnits:isExist() then
_groupUnits = _groupUnits:getUnits()
if _groupUnits ~= nil and #_groupUnits > 0 then
for _x = 1, #_groupUnits do
if _groupUnits[_x]:getLife() > 0 then -- removed and _groupUnits[_x]:isExist() as isExist doesnt work on single units!
table.insert(_filteredUnits, _groupUnits[_x])
end
end
end
end
return _filteredUnits
end
function fac.isInfantry(_unit)
local _typeName = _unit:getTypeName()
--type coerce tostring
_typeName = string.lower(_typeName .. "")
local _soldierType = { "infantry", "paratrooper", "stinger", "manpad", "mortar" }
for _key, _value in pairs(_soldierType) do
if string.match(_typeName, _value) then
return true
end
end
return false
end
function fac.isArty(_Aunit)
local _typeName = _Aunit:getTypeName()
-- --type coerce tostring
-- _typeName = string.lower(_typeName .. "")
--trigger.action.outText( _typeName.." found",10)
-- local _artyType = { "mrls", "sph", "mortar" }
-- for _key, _value in pairs(_artyType) do
-- if string.match(_typeName, _value) then
-- return true
-- end
-- end
--trigger.action.outText( _typeName.." found",10)
if _Aunit:hasAttribute('Artillery') or _Aunit:hasAttribute('Strategic bombers') or _Aunit:hasAttribute('Cruisers') or _Aunit:hasAttribute('Frigates') or _Aunit:hasAttribute('Corvettes') or _Aunit:hasAttribute('Landing Ships') then --or _Aunit:hasAttribute('MLRS') or _Aunit:hasAttribute('Bombers') or _Aunit:hasAttribute('Multirole fighters') then
if _typeName == "Silkworm_SR" or _typeName == "hy_launcher" then -- or _Aunit:hasAttribute('MLRS') then
return false
else
--trigger.action.outText( _typeName.." found",10)
return true
end
else
return false
end
end
function fac.isBomber(_Aunit)
local _typeName = _Aunit:getTypeName()
-- --type coerce tostring
-- _typeName = string.lower(_typeName .. "")
--trigger.action.outText( _typeName.." found",10)
-- local _artyType = { "mrls", "sph", "mortar" }
-- for _key, _value in pairs(_artyType) do
-- if string.match(_typeName, _value) then
-- return true
-- end
-- end
if _Aunit:hasAttribute('Strategic bombers') or _Aunit:hasAttribute('Bombers') or _Aunit:hasAttribute('Multirole fighters') then
return true
else
return false
end
end
-- assume anything that isnt soldier is vehicle
function fac.isVehicle(_unit)
if fac.isInfantry(_unit) then
return false
end
return true
end
-- copied from CTLD
function fac.getGroupId(_unit)
local _unitDB = mist.DBs.unitsById[tonumber(_unit:getID())]
local _gID = _unit:getGroup():getID()
if _unitDB ~= nil and _unitDB.groupId then
return _unitDB.groupId
elseif _gID ~= nil then
return _gID
end
return nil
end
function fac.createSmokeMarker(_enemyUnit, _colour,_facUnitName)
--recreate in 5 mins
if fac.markerType[_facUnitName] == "SMOKE" then
fac.facSmokeMarks[_enemyUnit:getName()] = timer.getTime() + 300.0
else
fac.facSmokeMarks[_enemyUnit:getName()] = timer.getTime() + 2
end
-- move smoke 2 meters above target for ease
local _enemyPoint = _enemyUnit:getPoint()
if fac.markerType[_facUnitName] == "SMOKE" then
trigger.action.smoke({ x = _enemyPoint.x, y = _enemyPoint.y + 2.0, z = _enemyPoint.z }, _colour)
else
trigger.action.signalFlare({ x = _enemyPoint.x, y = _enemyPoint.y + 2.0, z = _enemyPoint.z }, _colour,0)
end
end
--fire mission control
-- function fac.checkArty(_side, _artyTable)
-- --trigger.action.outText( "Found " ..#_artyTable.." arty units".._side,10)
-- local _artyIDX = 1
-- local _artyGroups = coalition.getGroups(_side, Group.Category.GROUND)
-- if #_artyGroups == 0 then
-- trigger.action.outText( "ERROR no Units",10)
-- --_artyGroups = coalition.getGroups(_side, Group.Category.GROUND)
-- elseif _artyGroups[1] == nil then
-- trigger.action.outText( "ERROR ground returned Nil",10)
-- end
-- for _artyIDX = 1, #_artyGroups do
-- local _artyunits = _artyGroups[_artyIDX]:getUnits()
-- if _artyunits[1] ~= nil then
-- if fac.isArty(_artyunits[1]) == true then
-- if contains(_artyTable,_artyGroups[_artyIDX]:getName()) == false then
-- table.insert(_artyTable,_artyGroups[_artyIDX]:getName())
-- --trigger.action.outText( "Found " ..#_artyTable.." arty units out of" ..#_artyGroups ,10)
-- end
-- end
-- end
-- end
-- end
function getHeading(unit)
local unitpos = unit:getPosition()
if unitpos then
local Heading = math.atan2(unitpos.x.z, unitpos.x.x)
Heading = Heading + getNorthCorrection(unitpos.p)
if Heading < 0 then
Heading = Heading + 2*math.pi -- put heading in range of 0 to 2*pi
end
return Heading
end
end
getNorthCorrection = function(point) --gets the correction needed for true north
if not point.z then --Vec2; convert to Vec3
point.z = point.y
point.y = 0
end
local lat, lon = coord.LOtoLL(point)
local north_posit = coord.LLtoLO(lat + 1, lon)
return math.atan2(north_posit.z - point.z, north_posit.x - point.x)
end
function fac.facOffsetMaker(_fac)
local _facOffset = {}
local angle = getHeading(_fac)
local xofs = math.cos(angle) * fac.facOffsetDist
local yofs = math.sin(angle) * fac.facOffsetDist
local _facPoint = _fac:getPoint()
_facOffset.x = _facPoint.x + xofs
_facOffset.y = _facPoint.y
_facOffset.z = _facPoint.z +yofs
return _facOffset
end
function fac.getBomber(_mapPt,_col,_artyType)
local _attackPoint = _mapPt
local _i = 1
local _j = 1
local _k = 1
--local _gndGroups = {}
local _tempPoint = nil
local _tempDist = nil
local _tempPosition = nil
local _lastArty = {ammo = 0, group = {}}
local _chosenArty = nil
local _tempArty = {}
local _tempList = {}
local _artyGroups = {}
local side = _col
local lastAmmo = 0
local tempFound = {}
local _foundArty = {}
local dist = {
id = world.VolumeType.SPHERE,
params = {
point = _attackPoint,
radius = 4600000 --max range ARTY
}
}
local getArty = function(foundItem, val) -- generic search for all scenery
local _checkArty = fac.isBomber(foundItem)
local _tempArtyGroup = foundItem:getGroup()
local _tGC = _tempArtyGroup:getController()
if side == foundItem:getCoalition() and foundItem:getPlayerName() == nil then -- check for friendly and not a player
if contains(tempFound,_tempArtyGroup:getName()) == false then --check for redundant groups
if _checkArty == true then
--trigger.action.outText(foundItem:getTypeName(),10)
--if _tGC:hasTask() == false then -- check for tasked arty
--if contains(fac.ArtyTasked,_tempArtyGroup:getName()) == false then -- check for tasked arty
if fac.ArtyTasked[_tempArtyGroup:getName()] == nil then
fac.ArtyTasked[_tempArtyGroup:getName()] = { name = _tempArtyGroup:getName(), tasked = 0, timeTasked = nil,tgt = nil}
end
--trigger.action.outText(_tempArtyGroup:getName() .. " " .. fac.ArtyTasked[_tempArtyGroup:getName()].tasked,10)
if fac.ArtyTasked[_tempArtyGroup:getName()].tasked == 0 then
_tempPoint = foundItem:getPoint()
_tempDist = fac.getDistance(_tempPoint, _attackPoint)
--foundItem
--trigger.action.outText(_tempArtyGroup:getName() .. " " .. fac.ArtyTasked[_tempArtyGroup:getName()].tasked,10)
local _type = Unit.getTypeName(foundItem)
if fac.artyGetAmmo(_tempArtyGroup:getUnits()) > 0 and foundItem:isActive() == true then
--trigger.action.outText(_tempDist.. " "..fac.ArtilleryProperties[_type].minrange .. " " .. fac.ArtilleryProperties[_type].maxrange,10)
if foundItem:hasAttribute('Strategic bombers') or foundItem:hasAttribute('Bombers') or foundItem:hasAttribute('Multirole fighters') then
--trigger.action.outText(foundItem:getTypeName().." "..fac.artyGetAmmo(_tempArtyGroup:getUnits()),10)
table.insert(tempFound,_tempArtyGroup:getName())
end
end
end
elseif foundItem:getTypeName() == "USS_Arleigh_Burke_IIa" or foundItem:getTypeName() == "TICONDEROG" and _artyType == 4 then
table.insert(tempFound,_tempArtyGroup:getName())
end
end
end
end
world.searchObjects(Object.Category.UNIT,dist,getArty)
if _artyType == 5 then
for _i = 1, #tempFound do
if Group.getByName(tempFound[_i]):getUnit(1):hasAttribute('Strategic bombers') or Group.getByName(tempFound[_i]):getUnit(1):hasAttribute('Bombers') then
--trigger.action.outText(Group.getByName(tempFound[_i]):getUnit(1):getTypeName() .." ".._artyFilter,10)
local payloadCheck = Group.getByName(tempFound[_i]):getUnit(1):getAmmo()
if payloadCheck ~= nil then
if payloadCheck[1].desc.guidance == 1 then
--trigger.action.outText(Group.getByName(tempFound[_i]):getUnit(1):getTypeName() .. " " .. payloadCheck[1].desc.guidance,10)
else
--trigger.action.outText(Group.getByName(tempFound[_i]):getUnit(1):getTypeName() .. " unguided bombs",10)
table.insert(_foundArty,tempFound[_i])
end
end
end
end
elseif _artyType == 4 then
for _i = 1, #tempFound do
--trigger.action.outText(Group.getByName(tempFound[_i]):getUnit(1):getTypeName() .." ".._artyFilter,10)
if Group.getByName(tempFound[_i]):getUnit(1):hasAttribute('Strategic bombers') or Group.getByName(tempFound[_i]):getUnit(1):hasAttribute('Bombers') or Group.getByName(tempFound[_i]):getUnit(1):hasAttribute('Multirole fighters') then
local payloadCheck = Group.getByName(tempFound[_i]):getUnit(1):getAmmo()
if payloadCheck ~= nil then
if payloadCheck[1].desc.guidance == 1 then
table.insert(_foundArty,tempFound[_i])
--trigger.action.outText(Group.getByName(tempFound[_i]):getUnit(1):getTypeName() .. " " .. payloadCheck[1].desc.guidance,10)
else
--trigger.action.outText(Group.getByName(tempFound[_i]):getUnit(1):getTypeName() .. " unguided bombs",10)
end
end
elseif Unit.getByName(tempFound[_i]):getTypeName() == "USS_Arleigh_Burke_IIa" or Unit.getByName(tempFound[_i]):getTypeName() == "TICONDEROG" then
--trigger.action.outText( Unit.getByName(tempFound[_i]):getTypeName() .." Found",10)
if fac.artyGetGuidedAmmo(Group.getByName(tempFound[_i]):getUnits()) > 0 then
table.insert(_foundArty,tempFound[_i])
end
end
end
elseif _artyType == 3 then
for _i = 1, #tempFound do
--trigger.action.outText(Group.getByName(tempFound[_i]):getUnit(1):getTypeName() .." ".._artyFilter,10)
if Group.getByName(tempFound[_i]):getUnit(1):hasAttribute('Multirole fighters') then
local payloadCheck = Group.getByName(tempFound[_i]):getUnit(1):getAmmo()
if payloadCheck ~= nil then
for _k = 1,#payloadCheck do
--trigger.action.outText(payloadCheck[_k].desc.typeName,10)
if payloadCheck[_k].desc.typeName == "weapons.missiles.ADM_141A" then
table.insert(_foundArty,tempFound[_i])
--trigger.action.outText(Group.getByName(tempFound[_i]):getUnit(1):getTypeName() .. " " .. payloadCheck[1].desc.guidance,10)
else
--trigger.action.outText(Group.getByName(tempFound[_i]):getUnit(1):getTypeName() .. " unguided bombs",10)
end
end
end
end
end
else
_foundArty = tempFound
end
for _j = 1, #_foundArty do -- find arty with most ammo
--trigger.action.outText(_foundArty[_j] .. " unguided bombs",10)
--trigger.action.outText(#Group.getByName(_foundArty[_j]):getUnits().. " unguided bombs",10)
local curAmmo = fac.artyGetAmmo(Group.getByName(_foundArty[_j]):getUnits())
if curAmmo > lastAmmo then
_chosenArty = _foundArty[_j]
end
end
if _chosenArty ~=nil then
--trigger.action.outText(_chosenArty,10)
return Group.getByName(_chosenArty)
-- if retask == true then
-- trigger.action.outTextForCoalition(side,fac.getFacName(_fac:getName()) .. " is re-tasking ".. _chosenArty .. "(".. Group.getByName(tempFound[_j]):getUnit(1) ..") to a new target",10)
-- end
else
return nil
end
end
function fac.getArty(_enemyUnit,_fac,_artyType)
local _attackPoint = {}
if _enemyUnit == nil then
_attackPoint = fac.facOffsetMaker(_fac)
else
_attackPoint = _enemyUnit:getPoint()
end
local _i = 1
local _j = 1
--local _gndGroups = {}
local _tempPoint = nil
local _tempDist = nil
local _tempPosition = nil
local _lastArty = {ammo = 0, group = {}}
local _chosenArty = nil
local _tempArty = {}
local _tempList = {}
local _artyGroups = {}
local side = _fac:getCoalition()
local lastAmmo = 0
-- if overide == 2 then
-- local retask = true
-- --trigger.action.outText("retask",10)
-- else
-- local retask = false
-- end
-- finds all avaliable arty and chooses any untasked arty for firemission
-- NEW arty check
local dist = {
id = world.VolumeType.SPHERE,
params = {
point = _attackPoint,
radius = 4600000 --max range ARTY
}
}
local tempFound = {}
local _foundArty = {}
local getArty = function(foundItem, val) -- generic search for all scenery
--trigger.action.outTextForCoalition(side,foundItem:getTypeName() .. " found1 ",10)
if side == foundItem:getCoalition() and foundItem:isActive() == true and foundItem:getPlayerName() == nil then -- check for friendly and not a player
local _checkArty = fac.isArty(foundItem)
local _tempArtyGroup = foundItem:getGroup()
local _tGC = _tempArtyGroup:getController()
--trigger.action.outText(_tempArtyGroup:getName() .. " found ",10)
--trigger.action.outTextForCoalition(side,foundItem:getTypeName() .. " found1 ",10)
if contains(tempFound,_tempArtyGroup:getName()) == false then --check for redundant groups
--trigger.action.outTextForCoalition(side,foundItem:getTypeName() .. " found2 ",10)
if _checkArty == true then
--trigger.action.outTextForCoalition(side,foundItem:getTypeName() .. " found3 ",10)
--trigger.action.outText(foundItem:getTypeName(),10)
--if _tGC:hasTask() == false then -- check for tasked arty
--if contains(fac.ArtyTasked,_tempArtyGroup:getName()) == false then -- check for tasked arty
if fac.ArtyTasked[_tempArtyGroup:getName()] == nil then
fac.ArtyTasked[_tempArtyGroup:getName()] = { name = _tempArtyGroup:getName(), tasked = 0, timeTasked = nil,tgt = nil, requestor = nil}
end
--trigger.action.outText(_tempArtyGroup:getName() .. " " .. fac.ArtyTasked[_tempArtyGroup:getName()].tasked,10)
if fac.ArtyTasked[_tempArtyGroup:getName()].tasked == 0 then
_tempPoint = foundItem:getPoint()
_tempDist = fac.getDistance(_tempPoint, _attackPoint)
--foundItem
--trigger.action.outText(_tempArtyGroup:getName() .. " " .. fac.ArtyTasked[_tempArtyGroup:getName()].requestor,10)
local _type = Unit.getTypeName(foundItem)
if fac.artyGetAmmo(_tempArtyGroup:getUnits()) > 0 and foundItem:isActive() == true then
--trigger.action.outText(_tempDist.. " "..fac.ArtilleryProperties[_type].minrange .. " " .. fac.ArtilleryProperties[_type].maxrange,10)
if foundItem:hasAttribute('Strategic bombers') or foundItem:hasAttribute('Bombers') then
--trigger.action.outText(foundItem:getTypeName().." "..fac.artyGetAmmo(_tempArtyGroup:getUnits()),10)
table.insert(tempFound,_tempArtyGroup:getName())
elseif foundItem:hasAttribute('Naval') then
if _artyType == 4 then
if foundItem:getTypeName() == "USS_Arleigh_Burke_IIa" or foundItem:getTypeName() == "TICONDEROG" then
table.insert(tempFound,_tempArtyGroup:getName())
end
else
local gunStats = {}
gunStats = fac.artyGetNavalGunAmmo(_tempArtyGroup:getUnits())
--trigger.action.outText(foundItem:getTypeName().." "..gunStats[2],10)
if gunStats[2] >= _tempDist then
table.insert(tempFound,_tempArtyGroup:getName())
end
end
elseif (_tempDist > fac.ArtilleryProperties[_type].minrange and _tempDist < fac.ArtilleryProperties[_type].maxrange) then --check if in arty params
--trigger.action.outText(foundItem:getTypeName().." "..fac.artyGetAmmo(_tempArtyGroup:getUnits()),10)
-- check for ammo and if arty is active
--if foundItem:getLife() > 1 then
table.insert(tempFound,_tempArtyGroup:getName())
--end
end
end
elseif fac.ArtyTasked[_tempArtyGroup:getName()].requestor == "AI Spotter" and _artyType ~= -1 then
_tempPoint = foundItem:getPoint()
_tempDist = fac.getDistance(_tempPoint, _attackPoint)
--foundItem
--trigger.action.outText(_tempArtyGroup:getName() .. " " .. fac.ArtyTasked[_tempArtyGroup:getName()].requestor,10)
--trigger.action.outText(_tempArtyGroup:getName() .. " " .. fac.ArtyTasked[_tempArtyGroup:getName()].tasked,10)
local _type = Unit.getTypeName(foundItem)
if fac.artyGetAmmo(_tempArtyGroup:getUnits()) > 0 and foundItem:isActive() == true then
trigger.action.outText(_tempDist.. " "..fac.ArtilleryProperties[_type].minrange .. " " .. fac.ArtilleryProperties[_type].maxrange,10)
if foundItem:hasAttribute('Strategic bombers') or foundItem:hasAttribute('Bombers') then
--trigger.action.outText(foundItem:getTypeName().." "..fac.artyGetAmmo(_tempArtyGroup:getUnits()),10)
table.insert(tempFound,_tempArtyGroup:getName())
elseif (_tempDist > fac.ArtilleryProperties[_type].minrange and _tempDist < fac.ArtilleryProperties[_type].maxrange) then --check if in arty params
--trigger.action.outText(foundItem:getTypeName().." "..fac.artyGetAmmo(_tempArtyGroup:getUnits()),10)
-- check for ammo and if arty is active
--if foundItem:getLife() > 1 then
table.insert(tempFound,_tempArtyGroup:getName())
--end
end
end
end
end
end
end
end
world.searchObjects(Object.Category.UNIT,dist,getArty)
--trigger.action.outTextForCoalition(side,#tempFound .. " found ",10)
local _artyFilter = "2B11 mortar"
if _artyType == 2 then
--trigger.action.outText(Group.getByName(tempFound[_i]):getUnit(1):getTypeName().. " ".._artyFilter,10)
for _i = 1, #tempFound do
if Group.getByName(tempFound[_i]):getUnit(1):getTypeName() == _artyFilter then
table.insert(_foundArty,tempFound[_i])
end
end
elseif _artyType == 3 then
for _i = 1, #tempFound do
--trigger.action.outText(Group.getByName(tempFound[_i]):getUnit(1):getTypeName() .." ".._artyFilter,10)
if Group.getByName(tempFound[_i]):getUnit(1):getTypeName() ~= _artyFilter and (not Group.getByName(tempFound[_i]):getUnit(1):hasAttribute('MissilesSS')) then
local payloadCheck = Group.getByName(tempFound[_i]):getUnit(1):getAmmo()
if payloadCheck[1].desc.guidance ~= nil then
--trigger.action.outText(Group.getByName(tempFound[_i]):getUnit(1):getTypeName() .. " " .. payloadCheck[1].desc.guidance,10)
else
--trigger.action.outText(Group.getByName(tempFound[_i]):getUnit(1):getTypeName() .. " unguided bombs",10)
table.insert(_foundArty,tempFound[_i])
end
end
end
elseif _artyType == 5 then
for _i = 1, #tempFound do
if Group.getByName(tempFound[_i]):getUnit(1):hasAttribute('Strategic bombers') or Group.getByName(tempFound[_i]):getUnit(1):hasAttribute('Bombers') then
--trigger.action.outText(Group.getByName(tempFound[_i]):getUnit(1):getTypeName() .." ".._artyFilter,10)
local payloadCheck = Group.getByName(tempFound[_i]):getUnit(1):getAmmo()
if payloadCheck[1].desc.guidance == 1 then
--trigger.action.outText(Group.getByName(tempFound[_i]):getUnit(1):getTypeName() .. " " .. payloadCheck[1].desc.guidance,10)
else
--trigger.action.outText(Group.getByName(tempFound[_i]):getUnit(1):getTypeName() .. " unguided bombs",10)
table.insert(_foundArty,tempFound[_i])
end
end
end
elseif _artyType == 4 then
for _i = 1, #tempFound do
--trigger.action.outText(Group.getByName(tempFound[_i]):getUnit(1):getTypeName() .." ".._artyFilter,10)
if Group.getByName(tempFound[_i]):getUnit(1):hasAttribute('Strategic bombers') or Group.getByName(tempFound[_i]):getUnit(1):hasAttribute('Bombers') then
local payloadCheck = Group.getByName(tempFound[_i]):getUnit(1):getAmmo()
if payloadCheck[1].desc.guidance == 1 then
table.insert(_foundArty,tempFound[_i])
--trigger.action.outText(Group.getByName(tempFound[_i]):getUnit(1):getTypeName() .. " " .. payloadCheck[1].desc.guidance,10)
else
--trigger.action.outText(Group.getByName(tempFound[_i]):getUnit(1):getTypeName() .. " unguided bombs",10)
end
elseif Group.getByName(tempFound[_i]):getUnit(1):hasAttribute('Naval') then
table.insert(_foundArty,tempFound[_i])
end
end
elseif _artyType == -1 then
for _i = 1, #tempFound do
if Group.getByName(tempFound[_i]):getUnit(1):hasAttribute('Strategic bombers') == false or Group.getByName(tempFound[_i]):getUnit(1):hasAttribute('Bombers') == false then
--local payloadCheck = Group.getByName(tempFound[_i]):getUnit(1):getAmmo()
--if payloadCheck[1].desc.guidance == 1 then
table.insert(_foundArty,tempFound[_i])
end
end
else
_foundArty = tempFound
end
for _j = 1, #_foundArty do -- find arty with most ammo
--trigger.action.outText(_foundArty[_j] .. " unguided bombs",10)
--trigger.action.outText(#Group.getByName(_foundArty[_j]):getUnits().. " unguided bombs",10)
local curAmmo = fac.artyGetAmmo(Group.getByName(_foundArty[_j]):getUnits())
if curAmmo > lastAmmo then
_chosenArty = _foundArty[_j]
end
end
if _chosenArty ~=nil then
return Group.getByName(_chosenArty)
-- if retask == true then
-- trigger.action.outTextForCoalition(side,fac.getFacName(_fac:getName()) .. " is re-tasking ".. _chosenArty .. "(".. Group.getByName(tempFound[_j]):getUnit(1) ..") to a new target",10)
-- end
else
return nil
end
end
function fac.artyGetAmmo(_units)
local BatteryAmmo = 0
local n
for n = 1, #_units do --Iterate through all units of the battery
--if _units[n]:getTypeName() == groupType then --Check if a unit is of the same type as the battery
local ammo = _units[n]:getAmmo() --Get ammo for this unit
if ammo ~= nil then
if ammo[1] then --Check if ammo[1] exists. If the ammo is used up, it returns nil...
local UnitAmmo = ammo[1].count --Get the shell count for this unit
--if UnitAmmo > minAmmo then --Check if there is ready ammo left
local UnitReadyAmmo = UnitAmmo
BatteryAmmo = BatteryAmmo + UnitReadyAmmo --Add unit ready ammo to total of group
--end
end
end
--end
end
return BatteryAmmo
end
function fac.artyGetNavalGunAmmo(_units)
local BatteryAmmo = 0
local n
local i
local MaxRange = 0
local tempMaxRange = 0
for n = 1, #_units do --Iterate through all units of the battery
--if _units[n]:getTypeName() == groupType then --Check if a unit is of the same type as the battery
local ammo = _units[n]:getAmmo() --Get ammo for this unit
if ammo ~= nil then
for i = 1, #ammo do
if ammo[i] then --Check if ammo[1] exists. If the ammo is used up, it returns nil...
if ammo[i].desc.warhead.caliber >=75 and ammo[i].desc.category == 0 then
local UnitAmmo = ammo[i].count --Get the shell count for this unit
--if UnitAmmo > minAmmo then --Check if there is ready ammo left
local UnitReadyAmmo = UnitAmmo
BatteryAmmo = BatteryAmmo + UnitReadyAmmo --Add unit ready ammo to total of group
if ammo[i].desc.warhead.caliber >= 120 then
tempMaxRange = 22222
if tempMaxRange > MaxRange then
MaxRange = tempMaxRange
end
else
tempMaxRange = 18000
if tempMaxRange > MaxRange then
MaxRange = tempMaxRange
end
end
end
end
end
end
--end
end
return {BatteryAmmo, MaxRange}
end
function fac.artyGetGuidedAmmo(_units)
local BatteryAmmo = 0
local n
local i
for n = 1, #_units do --Iterate through all units of the battery
--if _units[n]:getTypeName() == groupType then --Check if a unit is of the same type as the battery
local ammo = _units[n]:getAmmo() --Get ammo for this unit
if ammo ~= nil then
for i = 1, #ammo do
if ammo[i].desc.guidance == 1 then --Check if ammo[1] exists. If the ammo is used up, it returns nil...
if ammo[i].desc.category == 1 then
if ammo[i].desc.missileCategory == 5 then
local UnitAmmo = ammo[i].count --Get the shell count for this unit
--if UnitAmmo > minAmmo then --Check if there is ready ammo left
local UnitReadyAmmo = UnitAmmo
BatteryAmmo = BatteryAmmo + UnitReadyAmmo --Add unit ready ammo to total of group
end
else
local UnitAmmo = ammo[i].count --Get the shell count for this unit
--if UnitAmmo > minAmmo then --Check if there is ready ammo left
local UnitReadyAmmo = UnitAmmo
BatteryAmmo = BatteryAmmo + UnitReadyAmmo --Add unit ready ammo to total of group
end
end
end
end
--end
end
return BatteryAmmo
end
function fac.purgeArtList(_args)
-- local element = fac.ArtyTasked[_args[1]]
-- local tempTbl = {}
--local I = 1
-- fac.ArtyTasked[_args[1]] = nil
-- for I = 1, #fac.ArtyTasked do
-- if(fac.ArtyTasked[I] ~= nil) then
-- table.insert(tempTbl, fac.ArtyTasked[I])
-- end
-- end
-- fac.ArtyTasked = {}
-- trigger.action.outText("clear" .. #fac.ArtyTasked,10)
-- fac.ArtyTasked = tempTbl
-- trigger.action.outText(_args[1].."clearing " .. #fac.ArtyTasked,10)
-- local test, outIdx = contains(fac.ArtyTasked,_args[1])
-- trigger.action.outText(_args[1].."clearing " .. fac.ArtyTasked[outIdx],10)
-- if test == true and fac.ArtyTasked[outIdx] == _args[1] then
-- table.remove(fac.ArtyTasked,outIdx)
-- trigger.action.outText(_args[1].." cleared " .. #fac.ArtyTasked,10)
-- elseif test == true and fac.ArtyTasked[outIdx] ~= _args[1] then
-- trigger.action.outText(" error clearing ".._args[1],10)
-- for I = 1, #fac.ArtyTasked do
-- if fac.ArtyTasked[I] ~= nil then
-- trigger.action.outText(I .. " ".. fac.ArtyTasked[I],10)
-- end
-- end
-- fac.purgeArtList(_args[1])
-- end
--table.remove(fac.ArtyTasked)
local curTime = timer.getTime()
--trigger.action.outText(curTime .. " " .. fac.ArtyTasked[_args[1]].timeTasked,5)
if Group.getByName(_args[1]):getCategory() >= 2 then
if fac.ArtyTasked[_args[1]].timeTasked ~= nil then
if fac.ArtyTasked[_args[1]].tasked == _args[2] then
fac.ArtyTasked[_args[1]].tasked = 0
fac.ArtyTasked[_args[1]].tgt = nil
fac.ArtyTasked[_args[1]].timeTasked = nil
local leaderType = Group.getByName(_args[1]):getUnit(1):getDesc()
trigger.action.outTextForCoalition(Group.getByName(_args[1]):getCoalition(),leaderType.displayName .. " time out, canceling tasking ",0.5)
Group.getByName(_args[1]):getController():popTask()
elseif fac.artyGetAmmo(Group.getByName(_args[1]):getUnits()) < fac.ArtyTasked[_args[1]].tasked then
fac.ArtyTasked[_args[1]].tasked = 0
fac.ArtyTasked[_args[1]].tgt = nil
fac.ArtyTasked[_args[1]].timeTasked = nil
local leaderType = Group.getByName(_args[1]):getUnit(1):getDesc()
trigger.action.outTextForCoalition(Group.getByName(_args[1]):getCoalition(),leaderType.displayName .. " insufficent ammo, canceling tasking ",0.5)
Group.getByName(_args[1]):getController():popTask()
end
end
end
end
function fac.tgtCatType(target)
--trigger.action.outText("Assessing Type "..target:getName(), 15)
--local _TGT_Type = Group.getByName(target:getName()):getCategory()
local _TGT_Type = target:getCategory()
--trigger.action.outText(_TGT_Type, 15)
if _TGT_Type == 3 then
--trigger.action.outText("TGT is Static Object", 15)
return "Static"
elseif _TGT_Type == 1 then
--local _leadUnit = Group.getByName(target):getUnit(1)
local _unitType = target:getCategory()
--trigger.action.outText("TGT is Unit Object " .. _unitType, 15)
return "Unit"
end
--end
end
function removeSetMark(_args)
trigger.action.removeMark(_args[1])
end
function fac.recceDetect(_args)
local _facUnitName = _args[1]
local _unit = nil
fac.facManTGT[_args[1]] = {}
local recceUnit = fac.getFacUnit(_facUnitName)
local recceSide = recceUnit:getCoalition()
local reccePos = recceUnit:getPoint()
local _groupId = fac.getGroupId(recceUnit)
local tempFound = {}
local dist = {
id = world.VolumeType.SPHERE,
params = {
point = reccePos,
radius = 40000
}
}
--trigger.action.outText("FINDING STUFF", 15)
--remove old Marks
local _i
--local recceMarkID = timer.getTime() * 1000
--for _i = 5000, fac.recceID do
--trigger.action.removeMark(_i)
--end
local count = 0
local recceMarkTagets = function(foundItem, val) -- generic search for all scenery
local foundOutput = nil
local foundObjectPos = nil
local sideCheck = foundItem:getCoalition()
count = count + 1
if foundItem:getLife() >= 1 then
if sideCheck ~= recceSide then
_unit = foundItem
local _unitPos = _unit:getPoint()
local _offsetEnemyPos = { x = _unitPos.x, y = _unitPos.y + 2.0, z = _unitPos.z }
local _offsetFacPos = { x = reccePos.x, y = reccePos.y + 2.0, z = reccePos.z }
--trigger.action.outText("FOUND STUFF ".. foundItem:getLife(), 15)
local _type = fac.tgtCatType(foundItem)
if land.isVisible(_offsetEnemyPos, _offsetFacPos) then
if _type == "Static" or _unit:isActive() then
local recceMarkID = timer.getTime() * 1000 + count
--trigger.action.outText("FOUND STUFF ".. _unit:getTypeName() .. recceMarkID .." "..fID, 15)
local _vel = _unit:getVelocity()
local _spd = 0
if _vel ~=nil then
_spd = math.sqrt(_vel.x^2+_vel.z^2)
end
local unitPos = _unit:getPosition()
local head = math.atan2(unitPos.x.z, unitPos.x.x)
local _unitPos = _unit:getPosition().p
--trigger.action.outText("FOUND STUFF ".. _unitPos.z, 15)
if _unit:getTypeName() == "outpost_road" then
_unitPos.x = _unitPos.x + math.cos(head+math.pi/2)*18
_unitPos.z = _unitPos.z + math.sin(head+math.pi/2)*18
end
local _lat, _lon = coord.LOtoLL(_unitPos)
local _latLngStr = mist.tostringLL(_lat, _lon, 3, false)
local _latLngSecStr = mist.tostringLL(_lat, _lon, 3, true)
local _mgrsString = mist.tostringMGRS(coord.LLtoMGRS(coord.LOtoLL(_unit:getPosition().p)), 5)
--timer.scheduleFunction(fac.msgDraw, {_unit,recceSide,_facUnitName},timer.getTime() + 0.1)
trigger.action.markToCoalition(recceMarkID,_unit:getTypeName() .." - DMS: " .. _latLngSecStr .." Altitude: ".. math.floor(_unitPos.y) .."m/" .. math.floor(_unitPos.y*3.28084) .."ft" .. "\nHeading: ".. math.floor(getHeading(_unit) * 180/math.pi) .. "\nSpeed: " .. math.floor(_spd*2) .. " MPH" .."\nSpotted by: " .. fac.getFacName(_facUnitName), _unitPos, recceSide, false,"")
timer.scheduleFunction(removeSetMark,{recceMarkID},timer.getTime() + 300)
table.insert(tempFound,_unit)
fac.recceID = recceMarkID +1
end
end
end
end
end
world.searchObjects(1,dist,recceMarkTagets)
--world.searchObjects(Group.Category.GROUND,dist,recceMarkTagets)
count = 0
world.searchObjects(3,dist,recceMarkTagets)
--timer.scheduleFunction(fac.recceDetect, {_args,true}, timer.getTime() + 180)
fac.facManTGT[_args[1]] = tempFound
end
function fac.stratStrike(_args)
local i = 0
local _tgtList = fac.facManTGT[_args[1]]
--local roundsExpended = fac.callFireMissionMulti({_args[1],1,4,_tgtList})
local roundsExpended = 1
--trigger.action.outText("FOUND STUFF "..#_tgtList .. " " .. roundsExpended, 30)
while roundsExpended ~= nil do
local tempList = {}
for i = roundsExpended+1, #_tgtList do
table.insert(tempList,_tgtList[i])
end
_tgtList = {}
_tgtList = tempList
--trigger.action.outText(i .. " Targeting "..#_tgtList .. " " .. roundsExpended , 30)
if #_tgtList >0 then
roundsExpended = fac.callFireMissionMulti({_args[1],1,4,_tgtList})
else
roundsExpended = nil
end
end
end
function fac.multiStrike(_args)
local i = 0
local _tgtList = fac.facManTGT[_args[1]]
--local roundsExpended = fac.callFireMissionMulti({_args[1],1,4,_tgtList})
local roundsExpended = 1
--trigger.action.outText("FOUND STUFF "..#_tgtList .. " " .. roundsExpended, 30)
for i = 1, #_tgtList do
if _tgtList[i]:isExist() then
fac.callFireMission({_args[1],10,0,_tgtList[i]})
end
end
end
function fac.msgDraw(_args)
local _unit = _args[1]
local recceSide = _args[2]
local _facUnitName = _args[3]
local recceMarkID = timer.getTime() * 1000
local _unitPos = _unit:getPoint()
local _vel = _unit:getVelocity()
local _spd = 0
if _vel ~=nil then
_spd = math.sqrt(_vel.x^2+_vel.z^2)
end
--local unitPos = _unit:getPoint()
local _lat, _lon = coord.LOtoLL(_unit:getPosition().p)
local _latLngStr = mist.tostringLL(_lat, _lon, 3, false)
local _latLngSecStr = mist.tostringLL(_lat, _lon, 3, true)
local _mgrsString = mist.tostringMGRS(coord.LLtoMGRS(coord.LOtoLL(_unit:getPosition().p)), 5)
trigger.action.outText("Trying to draw mark ".. curMark, 15)
trigger.action.markToCoalition(recceMarkID,_unit:getTypeName() .." - DMS: " .. _latLngSecStr .." Altitude: ".. math.floor(_unitPos.y) .."m/" .. math.floor(_unitPos.y*3.28084) .."ft" .. "\nHeading: ".. math.floor(getHeading(_unit) * 180/math.pi) .. "\nSpeed: " .. math.floor(_spd*2) .. " MPH" .."\nSpotted by: " .. fac.getFacName(_facUnitName), _unitPos, recceSide, false,"")
timer.scheduleFunction(removeSetMark,{recceMarkID},timer.getTime() + 180)
--timer.scheduleFunction(awacs.removeSetMark,{facMarkID,_args[2]:getUnit(1):getName()},timer.getTime() + awacs.setAWACSscanRate [_args[3]]-.25)
--awacs.trackID = AWACSMarkID +1
return
end
function fac.callFireMissionMulti(_args)
local _facUnitName = _args[1]
local _tgtList
--trigger.action.outText("FOUND STUFF "..#_args[4], 15)
local _facUnit = Unit.getByName(_facUnitName)
if _args[4] == nil then
_tgtList = fac.facManTGT[_args[1]]
else
_tgtList = _args[4]
end
local _artyRounds = _args[2]
local _roundType = _args[3]
local _groupId = fac.getGroupId(_facUnit)
local _artyInRange = nil
local _artyPos = {}
local comboShoot = {}
local comboTasker = {}
local tp
local _i
if _tgtList == nil then
trigger.action.outTextForGroup(_groupId,"Unable to process fire mission",10)
trigger.action.outTextForGroup(_groupId,"No Valid Target, please create target list with manual scan",10)
return nil
end
for _i = 1, #_tgtList do
if _tgtList[_i]:isExist() then
_artyInRange = fac.getArty(_tgtList[_i],_facUnit,_roundType)
--if _artyInRange ~=nil then
--_artyPos = _artyInRange:getUnit(1):getPoint()
--else
--return
--end
else
trigger.action.outTextForGroup(_groupId,"Invalid target detected, please rescan for more current target list with manual scan",10)
return
end
if _tgtList[_i] == nil or _artyInRange == nil then
if _tgtList[_i] == nil and _artyInRange ~= nil then
trigger.action.outTextForGroup(_groupId,"Unable to process fire mission",10)
trigger.action.outTextForGroup(_groupId,"No Valid Target",10)
return nil
elseif _artyInRange == nil then
trigger.action.outTextForGroup(_groupId,"Unable to process fire mission",10)
trigger.action.outTextForGroup(_groupId,"No untasked active artillery/bomber in range of target",10)
return nil
else
_artyPos = _artyInRange:getUnit(1):getPoint()
end
else
tp = _tgtList[_i]:getPoint()
local firepoint = {}
firepoint.x = tp.x --+ _fireOffset.x
firepoint.y = tp.z --+ _fireOffset.z
--firepoint.radius = 10
firepoint.expend = "One"
--firepoint.attackQty = 1
firepoint.attackQty = 1
firepoint.altitude = _artyPos.y
firepoint.altitudeEnabled = true
firepoint.weaponType = 268402702
--firepoint.expendQty = _artyRounds
--firepoint.expendQtyEnabled = true
local firemission = {id = 'Bombing', params = firepoint}
if _artyInRange:getUnit(1):hasAttribute('Naval') then
firepoint.expendQty = 1
firepoint.expendQtyEnabled = true
firemission = {id = 'FireAtPoint', params = firepoint}
end
--_artyInRange:getController():pushTask(firemission)
if (fac.artyGetGuidedAmmo(_artyInRange:getUnits())-_i) >= 0 then
--trigger.action.outTextForGroup(_groupId,"Target processed " .. _tgtList[_i]:getTypeName(),10)
table.insert (comboTasker,firemission)
end
-- timer.scheduleFunction(fac.launchMulti,{_artyInRange:getController(),firemission},timer.getTime()+ 45)
end
--tasks = { _i =
end
comboShoot = {id = 'ComboTask', params = {tasks = comboTasker}}
_artyInRange:getController():setOption(1,1)
_artyInRange:getController():pushTask(comboShoot)
_artyInRange:getController():setOption(10,3221225470)
--if fac.ArtyTasked[_artyInRange:getName()] == nil or fac.ArtyTasked[_artyInRange:getName()].tasked == 0 then
--table.insert (fac.ArtyTasked, _artyInRange:getName())
--fac.ArtyTasked[_artyInRange:getName()]
fac.ArtyTasked[_artyInRange:getName()]= {name = _artyInRange:getName(), tasked = #comboTasker,timeTasked = nil}
--timer.scheduleFunction(fac.purgeArtList,{_artyInRange:getName()},timer.getTime()+ 45*#_tgtList)
--end
--timer.scheduleFunction(fac.clearTask,{_artyInRange:getController(),#_tgtList},timer.getTime()+ 20*#_tgtList)
trigger.action.outTextForCoalition(_facUnit:getCoalition(),"Fire mission order sent, " .._artyInRange:getUnit(1):getTypeName() .. " ("..fac.artyGetGuidedAmmo(_artyInRange:getUnits())-#comboTasker .. " rounds remaining"..") firing ".._artyRounds.." rounds at " .. #comboTasker .. " target(s). Requestor: " .. fac.getFacName(_facUnitName) ,10)
return fac.artyGetGuidedAmmo(_artyInRange:getUnits())
end
function tablelength(T)
local count = 0
for _ in pairs(T) do count = count + 1 end
return count
end
function CrptBmbDesig:onEvent(e)
local t ={}
local pwdCheckList = {}
local tgtHead
local i
local j
--local str
if e.id == 26 then
if string.find(e.text, "CBRQT") or string.find(e.text, "TDRQT") then
--trigger.action.outText(e.initiator:getName() .. " " .. e.groupID, 25)
--local pwdCheckList =world.getMarkPanels()
for i in string.gmatch(e.text, "%S+") do
table.insert(t, i)
end
--trigger.action.outText(pwdCheckList[1].groupID..e.coalition, 25)
if string.find(e.text, "CBRQT") then
fac.carpetMapExecute({e.pos,t[1],e.coalition,"CARPET BOMB"})
world.removeEventHandler(CrptBmbDesig)
trigger.action.removeMark(e.idx)
else
fac.carpetMapExecute({e.pos,t[1],e.coalition,"TALD"})
world.removeEventHandler(CrptBmbDesig)
trigger.action.removeMark(e.idx)
--trigger.action.removeMark(pwdCheckList[j].idx)
-- for j =1, #pwdCheckList do
-- if string.find(pwdCheckList[j].text,t[2]) and pwdCheckList[j].coalition ~=-1 then
-- end
end
end
end
end
function fac.carpetMapDesignate(_args)
--local _unitR = fac.getFacUnit(_args[1])
--local _groupId = fac.getGroupId(_unitR)
world.addEventHandler(CrptBmbDesig)
--local pw = "Password is A"..timer.getTime()
--trigger.action.markToGroup(timer.getTime()+_groupId,pw,_unitR:getPoint(),_groupId)
end
function RECCEDesig:onEvent(e)
local t ={}
local pwdCheckList = {}
local tgtHead
local i
local j
--local str
if e.id == 26 then
if string.find(e.text, "RECCE") then
--trigger.action.outText(e.initiator:getName() .. " " .. e.groupID, 25)
--local pwdCheckList =world.getMarkPanels()
for i in string.gmatch(e.text, "%S+") do
table.insert(t, i)
end
fac.RECCEMapExecute({e.pos,t[1],e.coalition,"TALD"})
world.removeEventHandler(RECCEDesig)
trigger.action.removeMark(e.idx)
end
end
end
function fac.RECCEDesignate(_args)
--local _unitR = fac.getFacUnit(_args[1])
--local _groupId = fac.getGroupId(_unitR)
world.addEventHandler(RECCEDesig)
--local pw = "Password is A"..timer.getTime()
--trigger.action.markToGroup(timer.getTime()+_groupId,pw,_unitR:getPoint(),_groupId)
end
function fac.RECCEMapExecute(_args)
local blueRECCEac = " "
local redRECCEEac = " "
local reccePont = _args[1]
local side = _args[3]
local avaliAB = {}
local dist2RECCE = 1000000000
local RECCEmission = {}
local _facUnitName = nil
local selectRECCE = nil
local selectRECCEgroup
local selectRECCEpos
for _, _facUnitName in pairs(fac.reccePilotNames) do
--trigger.action.outText("Found " .. _facUnitName, 25)
local recceAC = Unit.getByName(_facUnitName)
if recceAC ~= nil then
if recceAC:getPlayerName() == nil and fac.RECCETasked[_facUnitName] ~= 1 then
--trigger.action.outText("Found " .. _facUnitName, 25)
if side == recceAC:getCoalition() and recceAC:isExist() then
local tempSelectRECCE = _facUnitName
local tempSelectRECCEgroup = Unit.getByName(_facUnitName) :getGroup()
local tempSelectRECCEpos = Unit.getByName(_facUnitName):getPoint()
local tempdist = math.sqrt((tempSelectRECCEpos.x-reccePont.x)^2 + (tempSelectRECCEpos.z-reccePont.z)^2)
--trigger.action.outText("Found " .. tempdist, 25)
if dist2RECCE > tempdist then
-- trigger.action.outText("Found " .. _facUnitName .." " ..tempdist.." " .. dist2RECCE, 25)
selectRECCE = tempSelectRECCE
selectRECCEgroup = tempSelectRECCEgroup
selectRECCEpos = tempSelectRECCEpos
dist2RECCE = tempdist
end
end
end
end
end
if selectRECCE ~= nil then
local scriptSTR = "fac.recceDetect({"..'"' .. selectRECCE .. '"'.."})\nfac.RECCETasked["..'"'..selectRECCE..'"'.."] = 0\ntrigger.action.outTextForCoalition(" .. side ..","..'"'.."RECCE Misson Complete, " .. selectRECCE .." returning to holding orbit" .. '"'..",10)"
local scriptSTR2 = "fac.RECCETasked["..'"'..selectRECCE..'"'.."] = 0\ntrigger.action.outTextForCoalition(" .. side ..","..'"'.. selectRECCE .." avaliable for retasking" .. '"'..",10)"
--trigger.action.outText(scriptSTR, 25)
--removebyKey(fac.RECCETasked,selectRECCE)
RECCEmission = {
id = 'Mission',
params = {
airborne = true,
route = {
points = {
[1] = {
["x"] = selectRECCEpos.x, --bombIP.x + math.cos(ipAngle+_FH*math.pi/4)*radTurn,
["y"] = selectRECCEpos.z, --bombIP.y + math.sin(ipAngle+_FH*math.pi/4)*radTurn,
["type"] = "Turning Point",
["action"] = "Turning Point",
["alt"] = selectRECCEpos.y,
["speed"] = 544,
--["task"] = {},
},
[2] = {
["x"] = reccePont.x, --bombIP.x + math.cos(ipAngle+_FH*math.pi/4)*radTurn,
["y"] = reccePont.z, --bombIP.y + math.sin(ipAngle+_FH*math.pi/4)*radTurn,
["type"] = "Turning Point",
["action"] = "Fly Over Point",
["alt"] = 20000,
["speed"] = 544,
--["ETA"] = timer.getTime()+time2IP,
["ETA_locked"] = false,
--["alt_type"] =
["task"] =
{
["id"] = "ComboTask",
["params"] =
{
["tasks"] =
{
--[1] = {},
[1] =
{
["enabled"] = true,
["auto"] = false,
["id"] = "WrappedAction",
["number"] = 2,
["params"] =
{
["action"] =
{
["id"] = "Script",
["params"] =
{
["command"] = scriptSTR,
}, -- end of ["params"]
}, -- end of ["action"]
}, -- end of ["params"]
}, -- end of [1]
}, -- end of ["tasks"]
}, -- end of ["params"]
}, -- end of ["task"]
},
[3] = {
["x"] = selectRECCEpos.x, --bombIP.x + math.cos(ipAngle+_FH*math.pi/4)*radTurn,
["y"] = selectRECCEpos.z, --bombIP.y + math.sin(ipAngle+_FH*math.pi/4)*radTurn,
["type"] = "Turning Point",
["action"] = "Turning Point",
["alt"] = selectRECCEpos.y,
["speed"] = 544,
["task"] = {
["id"] = "ComboTask",
["params"] =
{
["tasks"] =
{
[1] =
{
["enabled"] = true,
["auto"] = false,
["id"] = "Orbit",
["number"] = 1,
["params"] =
{
["altitude"] = selectRECCEpos.y,
["pattern"] = "Circle",
["speed"] = 424.98611111111,
["speedEdited"] = true,
}, -- end of ["params"]
}, -- end of [1]
[2] =
{
["enabled"] = true,
["auto"] = false,
["id"] = "WrappedAction",
["number"] = 2,
["params"] =
{
["action"] =
{
["id"] = "Script",
["params"] =
{
["command"] = scriptSTR,
}, -- end of ["params"]
}, -- end of ["action"]
}, -- end of ["params"]
}, -- end of [2]
}, -- end of ["tasks"]
}, -- end of ["params"]
}, -- end of ["task"]
},
}
}
}
}
local recceController = selectRECCEgroup:getController()
recceController:setTask(RECCEmission)
recceController:setOption(1,1)
trigger.action.outTextForCoalition(_args[3], selectRECCE .. " a " .. Unit.getByName(selectRECCE):getTypeName() .. " has been dispatched to RECCE a Map Mark", 10)
if contains(fac.RECCETasked,selectRECCE) == false then
table.insert(fac.RECCETasked,selectRECCE)
fac.RECCETasked[selectRECCE] = 1
else
fac.RECCETasked[selectRECCE] = 1
end
else
trigger.action.outTextForCoalition(_args[3], "No AI RECCE Assets available", 10)
end
-- --RECCE spawner wip
-- avaliAB = coalition.getAirbases(enum coalitionId )
-- for abCount = 1, #avaliAB do
-- if Airbase.getCategory(avaliAB[abCount]) == 0 then
-- -- --trigger.action.outTextForCoalition(Group.getByName(fireGroup):getCoalition(),Group.getByName(fireGroup):getUnit(1):getTypeName() .. " is winchester and RTB for rearm at " .. Airbase.getCallsign((avaliAB[abCount]),10)
-- avaliAB[abCount].getPoint
-- end
-- end
-- local group = {
-- ["visible"] = false,
-- ["taskSelected"] = true,
-- --["groupId"] = HVA.tempGroupSpawnedcounter,
-- ["hidden"] = false,
-- ["units"] = {},
-- ["frequency"] = "",
-- ["y"] = yofs,
-- ["x"] = xofs,
-- ["name"] = {},
-- ["start_time"] = 0,
-- ["task"] = {},
-- ["route"] = {
-- ["points"] =
-- {
-- [1] =
-- {
-- ["alt"] = rPos.y,
-- ["type"] = "Turning Point",
-- ["ETA"] = 0,
-- ["alt_type"] = "RADIO",
-- ["formation_template"] = "",
-- ["y"] = yofs,
-- ["x"] = xofs,
-- ["ETA_locked"] = true,
-- ["speed"] = _spd,
-- ["action"] = "Cone",
-- ["task"] = {
-- ["id"] = "ComboTask",
-- ["params"] =
-- {
-- ["tasks"] =
-- {
-- [1] ={},
-- [2] =
-- {
-- ["number"] = 2,
-- ["auto"] = true,
-- ["id"] = "Follow",
-- ["enabled"] = true,
-- ["params"] =
-- {
-- ["lastWptIndexFlagChangedManually"] = false,
-- ["groupId"] = rId,
-- ["lastWptIndex"] = 4,
-- ["lastWptIndexFlag"] = false,
-- ["pos"] =
-- {
-- ["y"] = math.random(0,200),
-- ["x"] = 200,
-- ["z"] = 200,
-- }, -- end of ["pos"]
-- },
-- },
-- }, -- end of ["tasks"]
-- }, -- end of ["params"]
-- }, -- end of ["task"],
-- ["speed_locked"] = false,
-- }, -- end of [1]
-- }
-- }
-- }
end
function fac.carpetMapExecute(_args)
local _enemyUnit = nil
local _artyInRange = nil
local _artyPos = {}
local comboShoot = {}
local previousTask = {}
local comboTasker = {}
local firemission = {}
local firePointTask = {}
local firePointWpt = {}
local firepoint = {}
local firepointFormTask ={}
local firepointForm ={}
local tpENV ={}
local _i
local bombIP ={}
local ipTurnPt = {}
local combatClimb = {}
local combatTurn = {}
local tp = {}
local _k
local comboTasker = {}
--local tp = _args[4]
local _i
--trigger.action.outText(_args[1],_args[3], 25)
local attackAz = 0
local directATTACK = true
if _args[2] ~= "CBRQT" and _args[2] ~= "TDRQT" then --and type(_args[2]) ~= "string" and _args[2] > 360
--trigger.action.outText(_args[2], 25)
local inAz = tonumber(_args[2])
if inAz ~= nil and inAz < 360 then
attackAz = math.rad(inAz)
directATTACK = false
end
else
trigger.action.outTextForCoalition(_args[3],"Attack Heading not selected or is invalid, Defaulting to direct attack",10)
end
if _args[4] == "CARPET BOMB" then
_artyInRange = fac.getBomber(_args[1],_args[3],5)
else
_artyInRange = fac.getBomber(_args[1],_args[3],3)
end
--if _enemyUnit == nil or _artyInRange == nil then
-- if _enemyUnit == nil and _artyInRange ~= nil then
-- trigger.action.outTextForGroup(_groupId,"Unable to process fire mission",10)
-- trigger.action.outTextForGroup(_groupId,"No Valid Target",10)
-- return
if _artyInRange == nil then
trigger.action.outTextForCoalition(_args[3],"Unable to process fire mission",10)
trigger.action.outTextForCoalition(_args[3],"No untasked active bomber in range of target",10)
return
--else
else
_artyPos = _artyInRange:getUnit(1):getPoint()
local ammoType = _artyInRange:getUnit(1):getAmmo()
local weapStation = 1
if _args[4] == "TALD" then
for _k = 1,#ammoType do
--trigger.action.outText(payloadCheck[_k].desc.typeName,10)
if ammoType[_k].desc.typeName == "weapons.missiles.ADM_141A" then
weapStation = _k
--table.insert(_foundArty,tempFound[_i])
--trigger.action.outText(Group.getByName(tempFound[_i]):getUnit(1):getTypeName() .. " " .. payloadCheck[1].desc.guidance,10)
--else
--trigger.action.outText(Group.getByName(tempFound[_i]):getUnit(1):getTypeName() .. " unguided bombs",10)
break
end
end
end
tp = _args[1]
-- firePointWpt.x = tp.x + math.cos(getHeading(_facUnit)+math.pi)*5000
-- firePointWpt.y = tp.z + math.sin(getHeading(_facUnit)+math.pi)*5000
-- firePointWpt.type = "Turning Point"
-- firePointWpt.action = "Turning Point"
-- firePointWpt.alt = _artyPos.y
firepoint.x = tp.x --+ _fireOffset.x
firepoint.y = tp.z --+ _fireOffset.z
firepoint.attackType = 'Carpet'
firepoint.carpetLength = ammoType[weapStation].count*10
firepoint.expend = "All"
firepoint.direction = attackAz + math.pi
firepoint.directionEnabled = true
firepoint.attackQty = 1
firepoint.groupAttack = true
--firepoint.weaponType = 2147485694
if _args[4] == "TALD" then
firepoint.weaponType = 8589934592
firepoint.altitude = 10000
firepoint.altitudeEnabled = false
else
firepoint.weaponType = 2147485694
firepoint.altitude = _artyPos.y
firepoint.altitudeEnabled = true
end
--firepoint.expendQty = _artyRounds
--firepoint.expendQtyEnabled = true
--["params"] =
TALDmission2 = {id = 'Bombing', params =
{
["direction"] = firepoint.direction,
["attackQtyLimit"] = false,
["attackQty"] = 1,
["expend"] = "All",
["altitudeEdited"] = true,
["directionEnabled"] = false,
["groupAttack"] = true,
["altitude"] = firepoint.altitude,
["altitudeEnabled"] = true,
["y"] = firepoint.y,
["weaponType"] = firepoint.weaponType,
["x"] = firepoint.x,
}, -- end of ["params"]
}
firePointTask = {id = 'CarpetBombing', params = firepoint}
--TALDmission = {id = 'Bombing', params = firepoint}
-- firePointWpt.task = firepointTask
-- firepointForm.variantIndex = 2
-- firepointForm.formationIndex = 2
-- firepointForm.value = 131074
-- firePointFormTask = {id = 'Formation', params = firepointForm}
-- previousTask = mist.getGroupRoute(_artyInRange:getName())
-- --table.insert (comboTasker,firepointFormTask)
-- table.insert (comboTasker,firepointTask)
-- --trigger.action.outText(mist.utils.tableShow(previousTask), 25)
-- table.insert (comboTasker,previousTask)
local _vel = _artyInRange:getUnit(1):getVelocity()
_spd = math.sqrt(_vel.x^2+_vel.z^2)
local atkSpd = _spd
-- if _args[4] == "TALD" then
-- atkSpd = 500
-- end
local radTurn = (2*atkSpd)^2/(11.8*math.tan(25*math.pi/180))
radTurn = 20000
if _args[4] == "TALD" then
radTurn = 64820
end
local combatClimb =
{
["alt"] = 2000,
["action"] = "Turning Point",
["alt_type"] = "BARO",
["speed"] = 220.97222222222,
["task"] =
{
["id"] = "ComboTask",
["params"] =
{
["tasks"] =
{
[1] =
{
["enabled"] = true,
["auto"] = false,
["id"] = "Aerobatics",
["number"] = 1,
["params"] =
{
["maneuversSequency"] =
{
[1] =
{
["name"] = "CLIMB",
["params"] =
{
["InitSpeed"] =
{
["order"] = 3,
["value"] = 444,
}, -- end of ["InitSpeed"]
["InitAltitude"] =
{
["order"] = 2,
["value"] = 2000,
}, -- end of ["InitAltitude"]
["StartImmediatly"] =
{
["order"] = 5,
["value"] = 1,
}, -- end of ["StartImmediatly"]
["RepeatQty"] =
{
["min_v"] = 1,
["max_v"] = 10,
["value"] = 1,
["order"] = 1,
}, -- end of ["RepeatQty"]
["UseSmoke"] =
{
["order"] = 4,
["value"] = 0,
}, -- end of ["UseSmoke"]
["Angle"] =
{
["min_v"] = 15,
["max_v"] = 90,
["value"] = 45,
["step"] = 5,
["order"] = 6,
}, -- end of ["Angle"]
["FinalAltitude"] =
{
["order"] = 7,
["value"] = 10000,
}, -- end of ["FinalAltitude"]
}, -- end of ["params"]
}, -- end of [1]
}, -- end of ["maneuversSequency"]
}, -- end of ["params"]
}, -- end of [1]
},
},
},
}
local combatTurn = {
["enabled"] = true,
["auto"] = false,
["id"] = "Aerobatics",
["number"] = 2,
["params"] =
{
["maneuversSequency"] =
{
[1] =
{
["name"] = "TURN",
["params"] =
{
["Ny_req"] =
{
["order"] = 6,
["value"] = 2,
}, -- end of ["Ny_req"]
["InitAltitude"] =
{
["order"] = 2,
["value"] = 2000,
}, -- end of ["InitAltitude"]
["StartImmediatly"] =
{
["order"] = 5,
["value"] = 1,
}, -- end of ["StartImmediatly"]
["UseSmoke"] =
{
["order"] = 4,
["value"] = 0,
}, -- end of ["UseSmoke"]
["SIDE"] =
{
["order"] = 9,
["value"] = 0,
}, -- end of ["SIDE"]
["InitSpeed"] =
{
["order"] = 3,
["value"] = 795.49999999999,
}, -- end of ["InitSpeed"]
["ROLL"] =
{
["order"] = 7,
["value"] = 60,
}, -- end of ["ROLL"]
["SECTOR"] =
{
["order"] = 8,
["value"] = 90,
}, -- end of ["SECTOR"]
["RepeatQty"] =
{
["min_v"] = 1,
["max_v"] = 10,
["value"] = 1,
["order"] = 1,
}, -- end of ["RepeatQty"]
}, -- end of ["params"]
}, -- end of [1]
},
},
}
bombIP.x = tp.x + math.cos(attackAz+math.pi)*radTurn*1
bombIP.z = tp.z + math.sin(attackAz+math.pi)*radTurn*1
local dx = -(_artyPos.x-bombIP.x)
local dy = -(_artyPos.z-bombIP.z)
local ipAngle = math.atan(dy/dx)
--trigger.action.outText("IPANGLE = " .. (ipAngle)/math.pi*180 .."\n", 300)
-- if ipAngle < 0 then
-- ipAngle = ipAngle + 2*math.pi
-- end
local d2TGT = math.sqrt((_artyPos.x-tp.x)^2 + (_artyPos.z-tp.z)^2)
local d2TP = math.sqrt((dx)^2 + (dy)^2)
local time2TGT = d2TGT/411.6
local time2IP = d2TP/411.6
-- if d2TGT < d2TP then
-- bombIP.x = tp.x + math.cos(attackAz)*radTurn*1
-- bombIP.z = tp.z + math.sin(attackAz)*radTurn*1
-- end
local _FH = 1
if dy < 0 then -- dy = -1 90-270
if dx < 0 then --dy/dx = 1 180-270
--trigger.action.outText(_artyInRange:getName().." Firing SW:\n".. (ipAngle/math.pi)*180 .."\n", 300)
--ipAngle= ipAngle + 2*math.pi -- math.pi/4
_FH = 0
else
--trigger.action.outText(_artyInRange:getName().." Firing SE:\n".. (ipAngle/math.pi)*180 .."\n", 300)
--ipAngle= ipAngle + math.pi --+ math.pi/4
_FH = -1
end
elseif dy > 0 then --dy = 1 270-90
if dx < 0 then --dy/dx = -1 270-0
--trigger.action.outText(_artyInRange:getName().." Firing NW:\n".. (ipAngle/math.pi)*180 .."\n", 300)
_FH = 0
--ipAngle= ipAngle + 2*math.pi -- math.pi/4
else --dy/dx = 1 0-90
--trigger.action.outText(_artyInRange:getName().." Firing NE:\n".. (ipAngle/math.pi)*180 .."\n", 300)
--ipAngle= ipAngle -- + math.pi/4
_FH = 1
end
end
local taskedMission = {}
if _args[4] == "TALD" then
taskedMission = TALDmission2
else
taskedMission = firePointTask
end
local IPoffset = {}
IPoffset.x = bombIP.x + math.cos(ipAngle+math.pi*_FH)*d2TP/2
IPoffset.z = bombIP.z + math.sin(ipAngle+math.pi*_FH)*d2TP/2
if math.sqrt(dx^2+dy^2) < radTurn then
IPoffset.x = bombIP.x
IPoffset.z = bombIP.z
end
--_artyInRange
local headingDeg = (ipAngle)/math.pi*180
if headingDeg >= 360 then
headingDeg = headingDeg-360
end
local scriptSTR = "trigger.action.outTextForCoalition(" .. _args[3] ..","..'"'.. _artyInRange:getUnit(1):getTypeName() .." is IP Inbound for " .._args[4] .. " attack" .. '"'..",10)"
local ipSTR = {}
ipstr ={
["enabled"] = true,
["auto"] = false,
["id"] = "WrappedAction",
["number"] = 2,
["params"] =
{
["action"] =
{
["id"] = "Script",
["params"] =
{
["command"] = scriptSTR,
}, -- end of ["params"]
}, -- end of ["action"]
}, -- end of ["params"]
} -- end of [1]
table.insert(comboTasker,ipstr)
--table.insert(comboTasker,combatClimb)
table.insert(comboTasker,taskedMission)
comboMission = {id = 'ComboTask', params = {tasks = comboTasker}}
--trigger.action.outText(scriptSTR, 25)
--trigger.action.outText(radTurn.."\n"..IPoffset.x .. " ".. IPoffset.z .."\n" ..bombIP.x .. " ".. bombIP.z .."\n".. headingDeg.."\n", 300)
--trigger.action.markToCoalition(timer.getTime()+100,"TP ".. headingDeg .. "\nETA " .. time2IP, IPoffset,_args[3])
--trigger.action.markToCoalition(timer.getTime()+200,"IP".. headingDeg, bombIP,_args[3])
firemission = {
id = 'Mission',
params = {
airborne = true,
route = {
points = {--firePointWpt--,previousTask
[1] = {
["x"] = _artyPos.x, --bombIP.x + math.cos(ipAngle+_FH*math.pi/4)*radTurn,
["y"] = _artyPos.z, --bombIP.y + math.sin(ipAngle+_FH*math.pi/4)*radTurn,
["type"] = "Turning Point",
["action"] = "Turning Point",
["alt"] = firepoint.altitude,
["speed"] = atkSpd,
--["task"] = {},
},
-- [2] = {
-- ["x"] = IPoffset.x, --bombIP.x + math.cos(ipAngle+_FH*math.pi/4)*radTurn,
-- ["y"] = IPoffset.z, --bombIP.y + math.sin(ipAngle+_FH*math.pi/4)*radTurn,
-- ["type"] = "Turning Point",
-- ["action"] = "Turning Point",
-- ["alt"] = firepoint.altitude,
-- ["speed"] = atkSpd,
-- ["ETA"] = timer.getTime()+time2IP,
-- ["ETA_locked"] = false,
-- --["alt_type"] =
-- ["task"] = {}, -- end of ["task"]
-- },
-- [2] = {
-- ["x"] = tp.x + math.cos(getHeading(_facUnit)+math.pi)*50*_spd*2,
-- ["y"] = tp.z + math.sin(getHeading(_facUnit)+math.pi)*50*_spd*2,
-- ["type"] = "Turning Point",
-- ["action"] = "Turning Point",
-- ["alt"] = _artyPos.y,
-- --["speed"] = _artyInRange:getUnit(1):getVelocity(),
-- --["task"] = {}
-- },
[2] = {
["x"] = bombIP.x ,
["y"] = bombIP.z,
["type"] = "Turning Point",
["action"] = "Fly Over Point",
["alt"] = firepoint.altitude,
--["alt_type"] =
["speed"] = atkSpd,
["task"] = comboMission,
["ETA"] = timer.getTime() + time2IP*2,
["ETA_locked"] = false,
},
[3] = {
["x"] = IPoffset.x,
["y"] = IPoffset.z,
["type"] = "Turning Point",
["action"] = "Turning Point",
["alt"] = firepoint.altitude,
["speed"] = atkSpd,
--["alt_type"] =
--["task"] = {}
},
}
}
}
}
--_artyInRange:getController():pushTask(firemission)
-- timer.scheduleFunction(fac.launchMulti,{_artyInRange:getController(),firemission},timer.getTime()+ 45)
--end
--tasks = { _i =
--end
--comboShoot = {id = 'ComboTask', params = {tasks = comboTasker}}
--_artyInRange:getController():setOption(5,65539)
--_artyInRange:getController():pushTask(firePointTask)
_artyInRange:getController():setOption(1,1)
if _args[4] == "TALD" then
_artyInRange:getController():setOption(5,131074)
if directATTACK == true then
_artyInRange:getController():setTask(comboMission)
else
_artyInRange:getController():setTask(firemission)
end
else
_artyInRange:getController():setOption(5,786435)
if directATTACK == true then
_artyInRange:getController():setTask(comboMission)
else
_artyInRange:getController():setTask(firemission)
end
end
_artyInRange:getController():setOption(10,3221225470)
if fac.ArtyTasked[_artyInRange:getName()] == nil or fac.ArtyTasked[_artyInRange:getName()].tasked == 0 then
if fac.ArtyTasked[_artyInRange:getName()] == nil then
table.insert (fac.ArtyTasked, _artyInRange:getName())
end
--fac.ArtyTasked[_artyInRange:getName()]
--fac.ArtyTasked[_artyInRange:getName()]= {name = _artyInRange:getName(), tasked = 1,timeTasked = nil}
fac.ArtyTasked[_artyInRange:getName()]= {name = _artyInRange:getName(), tasked = ammoType[weapStation].count *#_artyInRange:getUnits() ,timeTasked = timer.getTime() ,tgt = nil}
--timer.scheduleFunction(fac.purgeArtList,{_artyInRange:getName()},timer.getTime()+ 45*1)
end
--timer.scheduleFunction(fac.clearTask,{_artyInRange:getController(),#_tgtList},timer.getTime()+ 20*#_tgtList)
trigger.action.outTextForCoalition(_args[3],"Fire mission order sent, " .._artyInRange:getUnit(1):getTypeName() .. "(".. ammoType[weapStation].count *#_artyInRange:getUnits() .." Rounds)".." will carpet bomb using ATK Az of ".. math.floor(attackAz/math.pi*180) .. " degrees on Map Mark" ,10)
end
end
function fac.callFireMissionCarpet(_args)
--local _facUnitName = _args[1]
local _facUnit =_args[1]
--local _tgtList = fac.facManTGT[_args[1]]
local _artyRounds = _args[2]
local _roundType = _args[3]
local _groupId = _args[6]
local _enemyUnit = nil
local _artyInRange = nil
local _artyPos = {}
local comboShoot = {}
local previousTask = {}
local comboTasker = {}
local firemission = {}
local firePointTask = {}
local firePointWpt = {}
local firepoint = {}
local firepointFormTask ={}
local firepointForm ={}
local tp = _args[4]
local _i
local attackHead = _args[5]
if attackHead == nil or attackHead == "CBRQT" then
trigger.action.outTextForGroup(_groupId,"No Heading defined, defaulting to 0 az",10)
--trigger.action.outTextForGroup(_groupId,"No Valid Target, please create target list with manual scan",10)
--return
attackHead = 0
end
--for _i = 1, #_tgtList do
--if _tgtList[_i]:isExist() then
--_enemyUnit = fac.getCurrentFacUnit(_facUnit, _facUnitName)
_artyInRange = fac.getArty(tp,nil,_roundType,_args[7])
--if _artyInRange ~=nil then
--_artyPos = _artyInRange:getUnit(1):getPoint()
--else
--return
--end
--else
--trigger.action.outTextForGroup(_groupId,"Invalid target detected, please rescan for more current target list with manual scan",10)
--return
--end
if _artyInRange == nil then
trigger.action.outTextForGroup(_groupId,"Unable to process fire mission",10)
trigger.action.outTextForGroup(_groupId,"No untasked active artillery/bomber in range of target",10)
return
--else
else
_artyPos = _artyInRange:getUnit(1):getPoint()
tp = _enemyUnit:getPoint()
firePointWpt.x = tp.x + math.cos(attackHead+math.pi)*5000
firePointWpt.y = tp.z + math.sin(attackHead+math.pi)*5000
firePointWpt.type = "Turning Point"
firePointWpt.action = "Turning Point"
firePointWpt.alt = _artyPos.y
firepoint.x = tp.x --+ _fireOffset.x
firepoint.y = tp.z --+ _fireOffset.z
firepoint.attackType = 'Carpet'
firepoint.carpetLength = 500
firepoint.expend = "All"
--firepoint.direction = getHeading(_facUnit)--+math.pi
firepoint.directionEnabled = true
firepoint.attackQty = 1
firepoint.altitude = _artyPos.y
firepoint.altitudeEnabled = true
--firepoint.expendQty = _artyRounds
--firepoint.expendQtyEnabled = true
firepoint.groupAttack = true
firePointTask = {id = 'CarpetBombing', params = firepoint}
firePointWpt.task = firepointTask
-- firepointForm.variantIndex = 2
-- firepointForm.formationIndex = 2
-- firepointForm.value = 131074
-- firePointFormTask = {id = 'Formation', params = firepointForm}
previousTask = mist.getGroupRoute(_artyInRange:getName())
--table.insert (comboTasker,firepointFormTask)
table.insert (comboTasker,firePointWpt)
--trigger.action.outText(mist.utils.tableShow(previousTask), 25)
table.insert (comboTasker,previousTask)
--_artyInRange
firemission = {
id = 'Mission',
params = {
route = {
points = {--firePointWpt--,previousTask
[1] = {
["x"] = tp.x + math.cos(attackHead+math.pi)*20000,
["y"] = tp.z + math.sin(attackHead+math.pi)*20000,
["type"] = "Turning Point",
["action"] = "Turning Point",
["alt"] = _artyPos.y,
["task"] = firePointTask
},
-- [2] = {
-- ["x"] = tp.x + math.cos(getHeading(_facUnit)+math.pi)*5000,
-- ["y"] = tp.z + math.sin(getHeading(_facUnit)+math.pi)*5000,
-- ["type"] = "Turning Point",
-- ["action"] = "Turning Point",
-- ["alt"] = _artyPos.y,
-- ["task"] = firePointTask
-- }
}
}
}
}
--_artyInRange:getController():pushTask(firemission)
-- timer.scheduleFunction(fac.launchMulti,{_artyInRange:getController(),firemission},timer.getTime()+ 45)
end
--tasks = { _i =
--end
--comboShoot = {id = 'ComboTask', params = {tasks = comboTasker}}
_artyInRange:getController():setOption(1,1)
--_artyInRange:getController():pushTask(firePointTask)
_artyInRange:getController():setOption(5,65539)
_artyInRange:getController():setTask(firemission)
_artyInRange:getController():setOption(10,3221225470)
--if fac.ArtyTasked[_artyInRange:getName()] == nil or fac.ArtyTasked[_artyInRange:getName()].tasked > 0 then
--table.insert (fac.ArtyTasked, _artyInRange:getName())
--fac.ArtyTasked[_artyInRange:getName()]
fac.ArtyTasked[_artyInRange:getName()]= {name = _artyInRange:getName(), tasked = 1,timeTasked = nil}
--timer.scheduleFunction(fac.purgeArtList,{_artyInRange:getName()},timer.getTime()+ 45*1)
--end
local ammoType = _artyInRange:getUnit(1):getAmmo()
--timer.scheduleFunction(fac.clearTask,{_artyInRange:getController(),#_tgtList},timer.getTime()+ 20*#_tgtList)
trigger.action.outTextForCoalition(_facUnit:getCoalition(),"Fire mission order sent, " .._artyInRange:getUnit(1):getTypeName() .. "(".. ammoType[1].count .." Rounds)".." will carpet bomb using ATK Az of ".. math.floor(attackHead/math.pi*180).. " degrees on target:" .. _enemyUnit:getTypeName() ,10)
end
function fac.callFireMissionCarpet2(_args)
local _facUnitName = _args[1]
local _facUnit = Unit.getByName(_facUnitName)
local _tgtList = fac.facManTGT[_args[1]]
local _artyRounds = _args[2]
local _roundType = _args[3]
local _groupId = fac.getGroupId(_facUnit)
local _enemyUnit = nil
local _artyInRange = nil
local _artyPos = {}
local comboShoot = {}
local previousTask = {}
local comboTasker = {}
local firemission = {}
local firePointTask = {}
local firePointWpt = {}
local firepoint = {}
local firepointFormTask ={}
local firepointForm ={}
local tpENV ={}
local _i
local bombIP ={}
local ipTurnPt = {}
--if _tgtList == nil then
--trigger.action.outTextForGroup(_groupId,"Unable to process fire mission",10)
--trigger.action.outTextForGroup(_groupId,"No Valid Target, please create target list with manual scan",10)
--return
--end
--for _i = 1, #_tgtList do
--if _tgtList[_i]:isExist() then
_enemyUnit = fac.getCurrentFacUnit(_facUnit, _facUnitName)
_artyInRange = fac.getArty(_enemyUnit,_facUnit,_roundType)
--if _artyInRange ~=nil then
--_artyPos = _artyInRange:getUnit(1):getPoint()
--else
--return
--end
--else
--trigger.action.outTextForGroup(_groupId,"Invalid target detected, please rescan for more current target list with manual scan",10)
--return
--end
if _enemyUnit == nil or _artyInRange == nil then
if _enemyUnit == nil and _artyInRange ~= nil then
trigger.action.outTextForGroup(_groupId,"Unable to process fire mission",10)
trigger.action.outTextForGroup(_groupId,"No Valid Target",10)
return
elseif _artyInRange == nil then
trigger.action.outTextForGroup(_groupId,"Unable to process fire mission",10)
trigger.action.outTextForGroup(_groupId,"No untasked active artillery/bomber in range of target",10)
return
--else
end
else
_artyPos = _artyInRange:getUnit(1):getPoint()
tp = _enemyUnit:getPoint()
firePointWpt.x = tp.x + math.cos(getHeading(_facUnit)+math.pi)*5000
firePointWpt.y = tp.z + math.sin(getHeading(_facUnit)+math.pi)*5000
firePointWpt.type = "Turning Point"
firePointWpt.action = "Turning Point"
firePointWpt.alt = _artyPos.y
firepoint.x = tp.x --+ _fireOffset.x
firepoint.y = tp.z --+ _fireOffset.z
firepoint.attackType = 'Carpet'
firepoint.carpetLength = 1000
firepoint.expend = "All"
--firepoint.direction = getHeading(_facUnit)--+math.pi
--firepoint.directionEnabled = true
firepoint.attackQty = 1
firepoint.altitude = _artyPos.y
firepoint.altitudeEnabled = true
--firepoint.expendQty = _artyRounds
--firepoint.expendQtyEnabled = true
firepoint.groupAttack = true
firePointTask = {id = 'CarpetBombing', params = firepoint}
firePointWpt.task = firepointTask
-- firepointForm.variantIndex = 2
-- firepointForm.formationIndex = 2
-- firepointForm.value = 131074
-- firePointFormTask = {id = 'Formation', params = firepointForm}
previousTask = mist.getGroupRoute(_artyInRange:getName())
--table.insert (comboTasker,firepointFormTask)
table.insert (comboTasker,firepointTask)
--trigger.action.outText(mist.utils.tableShow(previousTask), 25)
table.insert (comboTasker,previousTask)
local _vel = _artyInRange:getUnit(1):getVelocity()
_spd = math.sqrt(_vel.x^2+_vel.z^2)
local radTurn = (2*_spd)^2/(11.8*math.tan(25*math.pi/180))
bombIP.x = tp.x + math.cos(getHeading(_facUnit)+math.pi)*radTurn*1
bombIP.y = tp.z + math.sin(getHeading(_facUnit)+math.pi)*radTurn*1
local dx = -(_artyPos.x-bombIP.x)
local dy = -(_artyPos.z-bombIP.y)
local ipAngle = math.atan(dy/dx)
local _FH = 1
if dy < 0 then -- dy = -1 90-270
if dx < 0 then --dy/dx = 1 180-270
--trigger.action.outText(_artyInRange:getName().." Firing SW:\n".. (_fireheading/math.pi)*180 .."\n", 300)
ipAngle= ipAngle + 2*math.pi
else
--trigger.action.outText(_artyInRange:getName().." Firing SE:\n".. (_fireheading/math.pi)*180 .."\n", 300)
ipAngle= ipAngle + math.pi
end
elseif dy > 0 then --dy = 1 270-90
if dx < 0 then --dy/dx = -1 270-0
--trigger.action.outText(_artyInRange:getName().." Firing NW:\n".. (_fireheading/math.pi)*180 .."\n", 300)
ipAngle= ipAngle + 2*math.pi
else --dy/dx = 1 0-90
--trigger.action.outText(_artyInRange:getName().." Firing NE:\n".. (_fireheading/math.pi)*180 .."\n", 300)
ipAngle= ipAngle
_FH = -1
end
end
local IPoffset = {}
IPoffset.x = radTurn
IPoffset.y = radTurn
if math.sqrt(dx^2+dy^2) < radTurn then
IPoffset.x = 1
IPoffset.y = 1
end
--_artyInRange
firemission = {
id = 'Mission',
params = {
airborne = true,
route = {
points = {--firePointWpt--,previousTask
[1] = {
["x"] = bombIP.x + math.cos(ipAngle)*radTurn,
["y"] = bombIP.y + math.sin(ipAngle)*radTurn,
["type"] = "Turning Point",
["action"] = "Turning Point",
["alt"] = _artyPos.y,
["speed"] = _artyInRange:getUnit(1):getVelocity(),
--["alt_type"] =
--["task"] = {}
},
-- [2] = {
-- ["x"] = tp.x + math.cos(getHeading(_facUnit)+math.pi)*50*_spd*2,
-- ["y"] = tp.z + math.sin(getHeading(_facUnit)+math.pi)*50*_spd*2,
-- ["type"] = "Turning Point",
-- ["action"] = "Turning Point",
-- ["alt"] = _artyPos.y,
-- --["speed"] = _artyInRange:getUnit(1):getVelocity(),
-- --["task"] = {}
-- },
[2] = {
["x"] = tp.x + math.cos(getHeading(_facUnit)+math.pi)*radTurn*1,
["y"] = tp.z + math.sin(getHeading(_facUnit)+math.pi)*radTurn*1,
["type"] = "Turning Point",
["action"] = "Turning Point",
["alt"] = _artyPos.y,
--["alt_type"] =
["speed"] = _artyInRange:getUnit(1):getVelocity(),
["task"] = firePointTask
}
}
}
}
}
--_artyInRange:getController():pushTask(firemission)
-- timer.scheduleFunction(fac.launchMulti,{_artyInRange:getController(),firemission},timer.getTime()+ 45)
end
--tasks = { _i =
--end
--comboShoot = {id = 'ComboTask', params = {tasks = comboTasker}}
_artyInRange:getController():setOption(1,1)
_artyInRange:getController():setOption(5,65539)
--_artyInRange:getController():pushTask(firePointTask)
_artyInRange:getController():setTask(firemission)
_artyInRange:getController():setOption(10,3221225470)
--if fac.ArtyTasked[_artyInRange:getName()] == nil or fac.ArtyTasked[_artyInRange:getName()].tasked > 0 then
--table.insert (fac.ArtyTasked, _artyInRange:getName())
--fac.ArtyTasked[_artyInRange:getName()]
fac.ArtyTasked[_artyInRange:getName()]= {name = _artyInRange:getName(), tasked = 1,timeTasked = nil}
--timer.scheduleFunction(fac.purgeArtList,{_artyInRange:getName()},timer.getTime()+ 45*1)
--end
local ammoType = _artyInRange:getUnit(1):getAmmo()
--timer.scheduleFunction(fac.clearTask,{_artyInRange:getController(),#_tgtList},timer.getTime()+ 20*#_tgtList)
trigger.action.outTextForCoalition(_facUnit:getCoalition(),"Fire mission order sent, " .._artyInRange:getUnit(1):getTypeName() .. "(".. ammoType[1].count .." Rounds)".." will carpet bomb using ATK Az of ".. math.floor(getHeading(_facUnit)/math.pi*180).. " degrees on target:" .. _enemyUnit:getTypeName() .. ". Requestor: " .. fac.getFacName(_facUnitName) ,10)
end
function fac.launchMulti(_args)
_args[1]:pushTask(_args[2])
end
function fac.taskedArty(_args)
_args[1]:pushTask(_args[2])
end
local facArtyFireDetect ={}
function facArtyFireDetect:onEvent(e)
if e.id == world.event.S_EVENT_SHOT then
local fireGroup = Unit.getGroup(e.initiator):getName()
local displayUnitName = e.initiator:getDesc()
if fac.ArtyTasked[fireGroup] ~= nil and fac.ArtyTasked[fireGroup].tasked > 0 then
fac.ArtyTasked[fireGroup].tasked = fac.ArtyTasked[fireGroup].tasked - 1
trigger.action.outTextForCoalition(Group.getByName(fireGroup):getCoalition(),displayUnitName.displayName .. " has commenced attack at designated target, tasked rounds remaining "..fac.ArtyTasked[fireGroup].tasked,0.5)
if fac.ArtyTasked[fireGroup].tasked == 0 then
--fac.ArtyTasked[fireGroup].tasked = false
local leaderType = Group.getByName(fireGroup):getUnit(1):getDesc()
trigger.action.outTextForCoalition(Group.getByName(fireGroup):getCoalition(), leaderType.displayName .. " Task Group available for re-tasking ",20)
end
if Unit.getGroup(e.initiator):getCategory() > 1 and e.weapon:getCategory() == 0 then
if fac.ArtyTasked[fireGroup].tgt:isExist() then
local tgtPnt = fac.ArtyTasked[fireGroup].tgt:getPoint()
local _tempDist = fac.getDistance(e.initiator:getPoint(), tgtPnt)
timer.scheduleFunction(fac.explosions, {tgtPnt}, timer.getTime() + _tempDist/264)
else
Group.getByName(fireGroup):getController():popTask()
fac.ArtyTasked[fireGroup].tasked = 0
trigger.action.outTextForCoalition(Group.getByName(fireGroup):getCoalition(),Group.getByName(fireGroup):getUnit(1):getTypeName() .. " Task Group tasked target destroyed, available for re-tasking ",20)
end
end
elseif fac.ArtyTasked[fireGroup] ~= nil then
fac.ArtyTasked[fireGroup].tasked = 0
if Unit.getGroup(e.initiator):getCategory() == 0 then
--trigger.action.outTextForCoalition(Group.getByName(fireGroup):getCoalition(),Group.getByName(fireGroup):getUnit(1):getTypeName() .. " BOMBS AWAY!!! ",0.25)
end
end
if fac.ArtyTasked[fireGroup] ~= nil and Unit.getGroup(e.initiator):getCategory() == 0 then
--trigger.action.outTextForCoalition(Group.getByName(fireGroup):getCoalition(),Group.getByName(fireGroup):getUnit(1):getTypeName() .. " has ammo remaining " .. fac.artyGetAmmo(Unit.getGroup(e.initiator):getUnits()),10)
if fac.artyGetAmmo(Unit.getGroup(e.initiator):getUnits()) == 0 then
trigger.action.outTextForCoalition(Group.getByName(fireGroup):getCoalition(),displayUnitName.displayName .. " is winchester and RTB",10)
-- local avaliAB = coalition.getAirbases(Group.getByName(fireGroup):getCoalition())
-- for abCount = 1, #avaliAB do
-- if Airbase.getCategory(avaliAB[abCount]) == 0 then
-- --trigger.action.outTextForCoalition(Group.getByName(fireGroup):getCoalition(),Group.getByName(fireGroup):getUnit(1):getTypeName() .. " is winchester and RTB for rearm at " .. Airbase.getCallsign((avaliAB[abCount]),10)
-- local rearm = {}
-- rearm = {
-- id = 'Mission',
-- params = {
-- airborne = true,
-- route = {
-- points = {--firePointWpt--,previousTask
-- [1] = {
-- ["x"] = 0,
-- ["y"] = 0,
-- ["type"] = "LandingReFuAr",
-- ["action"] = "LandingReFuAr",
-- ["alt"] =0,
-- ["speed"] = e.initiator:getUnit(1):getVelocity(),
-- ["airdromeId"] = Airbase.getID(avaliAB[abCount]),
-- ["timeReFuAr"] = 10,
-- --["alt_type"] =
-- --["task"] = {}
-- },
-- }
-- }
-- },
-- }
-- trigger.action.outTextForCoalition(Group.getByName(fireGroup):getCoalition(),Group.getByName(fireGroup):getUnit(1):getTypeName() .. " is winchester and RTB for rearm at " .. Airbase.getCallsign(avaliAB[abCount]),10)
-- break
-- end
-- end
-- Unit.getGroup(e.initiator):getController():pushTask(rearm)
end
end
end
end
function fac.explosions(args)
local tgtPnt = args[1]
local explodePnt = {}
explodePnt.x = tgtPnt.x + math.random(-15,15)
explodePnt.z = tgtPnt.z + math.random(-15,15)
explodePnt.y = tgtPnt.y
trigger.action.explosion(explodePnt, 10)
end
world.addEventHandler(facArtyFireDetect)
function fac.checkTask(_args)
local _i
local _j
local _facUnitName = _args[1]
local _facUnit = Unit.getByName(_facUnitName)
local _facGroup = _facUnit:getGroup()
local _groupId = fac.getGroupId(_facUnit)
trigger.action.outTextForCoalition(_facGroup:getCoalition(), "Checking artillery/bomber units" ,10)
local _enemyUnit = fac.getCurrentFacUnit(_facUnit, _facUnitName)
local _artyInRange = fac.getArty(_enemyUnit,_facUnit,1)
local artyList = fac.ArtyTasked
local tp
local _TGTdist = -1
--trigger.action.outTextForCoalition(_facGroup:getCoalition(), tablelength(fac.ArtyTasked),10)
for _i, _j in pairs(fac.ArtyTasked) do
if tablelength(fac.ArtyTasked) > 0 then
local fireGroup = _i
if _facGroup:getCoalition() == Group.getByName(fireGroup):getCoalition() and Group.getByName(fireGroup):getUnit(1):isActive() and Group.getByName(fireGroup):isExist() then
local _artyPos = Group.getByName(fireGroup):getUnit(1):getPoint()
if _enemyUnit ~= nil then
tp = _enemyUnit:getPoint()
_TGTdist = math.sqrt(((tp.z-_artyPos.z)^2)+((tp.x-_artyPos.x)^2))
end
local ammoCount = fac.artyGetAmmo(Group.getByName(fireGroup):getUnits())
trigger.action.outTextForCoalition(Group.getByName(fireGroup):getCoalition(),Group.getByName(fireGroup):getUnit(1):getTypeName() .. " Tasked rounds remaining: "..fac.ArtyTasked[fireGroup].tasked .. " Current Ammo: " .. ammoCount .." " .. math.floor(_TGTdist) ,10)
end
else
trigger.action.outTextForCoalition(_facGroup:getCoalition(), "No active artillery detected, build some artillery units with CTLD!!" ,10)
end
end
end
function fac.callFireMission(_args)
local _facUnitName = _args[1]
local _artyRounds = _args[2]
local _roundType = _args[3]
local _enemyUnit = nil
local _artyInRange = nil
local _facUnit = Unit.getByName(_facUnitName)
local _groupId = fac.getGroupId(_facUnit)
local _illumPoint = {}
local tp
local spotterName
local msgTime = 10
if fac.getFacName(_facUnitName) == nil then
spotterName = "AI Spotter"
else
spotterName = fac.getFacName(_facUnitName)
end
if _args[4] == nil then
_enemyUnit = fac.getCurrentFacUnit(_facUnit, _facUnitName)
else
_enemyUnit = _args[4]
end
if _roundType < 4 then
_artyInRange = fac.getArty(_enemyUnit,_facUnit,_roundType)
else
_artyInRange = fac.getBomber(_enemyUnit,_facUnit,_roundType)
end
if _enemyUnit == nil or _artyInRange == nil then
if _enemyUnit == nil and _artyInRange ~= nil then
if _roundType ~= 1 then
if _roundType ~= -1 then
trigger.action.outTextForGroup(_groupId,"Unable to process fire mission",10)
trigger.action.outTextForGroup(_groupId,"No Valid Target",10)
end
else
tp = fac.facOffsetMaker(_facUnit)
_illumPoint.x = tp.x
_illumPoint.y = tp.y + fac.illumHeight
_illumPoint.z = tp.z
trigger.action.illuminationBomb(_illumPoint,500)
trigger.action.outTextForCoalition(_facUnit:getCoalition(),"Fire mission order sent, " .._artyInRange:getUnit(1):getTypeName() .. " Task Group is firing illumination rounds " .. fac.facOffsetDist .. " m from " ..spotterName,10)
end
elseif _artyInRange == nil then
if _roundType ~= -1 then
trigger.action.outTextForGroup(_groupId,"Unable to process fire mission",10)
trigger.action.outTextForGroup(_groupId,"No untasked active artillery/bomber in range of target",10)
end
end
else
--if _enemyUnit:getCoalition() == 1 then
if _roundType ~= 1 then
if fac.ArtyTasked[_artyInRange:getName()] == nil or fac.ArtyTasked[_artyInRange:getName()].tasked == 0 then
--table.insert (fac.ArtyTasked, _artyInRange:getName())
--fac.ArtyTasked[_artyInRange:getName()]
fac.ArtyTasked[_artyInRange:getName()]= {name = _artyInRange:getName(), tasked = 0}
if _artyInRange:getUnit(1):hasAttribute('Strategic bombers') or _artyInRange:getUnit(1):hasAttribute('Bombers') then
--local firemission = {id = 'Bombing', params = firepoint}
--timer.scheduleFunction(fac.purgeArtList,{_artyInRange:getName()},timer.getTime()+ 20)
else
--timer.scheduleFunction(fac.purgeArtList,{_artyInRange:getName()},timer.getTime()+ 600)
end
--timer.scheduleFunction(fac.clearTask,{_artyInRange:getController(),1},timer.getTime()+ 20*_artyRounds+180)
end
end
--trigger.action.outText(table.getn(fac.redArty) .. "insert blu" ,10)
-- else
-- if _roundType ~= 1 then
-- table.insert (fac.ArtyTasked, _artyInRange:getName())
-- timer.scheduleFunction(fac.purgeArtList,{_artyInRange:getName()},timer.getTime()+ 180)
-- end
-- --trigger.action.outText(table.getn(fac.redArty) .. "insert red" ,10)
-- end
local _artyPos = _artyInRange:getUnit(1):getPoint()
local firepoint = {}
tp = _enemyUnit:getPoint()
local _fireOffset = {x = 0,y = 0,z =0}
--local _fireOffset.y = 0
local dx = tp.x-_artyPos.x
local dy = tp.z-_artyPos.z
local fpNorthOffset = getNorthCorrection(tp)
local _fireheading = math.atan(dy/dx)
--correcting for coordinate space
local _FH = 1
if dy < 0 then -- dy = -1 90-270
if dx < 0 then --dy/dx = 1 180-270
--trigger.action.outText(_artyInRange:getName().." Firing SW:\n".. (_fireheading/math.pi)*180 .."\n", 300)
_fireheading= _fireheading + 2*math.pi
else
--trigger.action.outText(_artyInRange:getName().." Firing SE:\n".. (_fireheading/math.pi)*180 .."\n", 300)
_fireheading= _fireheading + math.pi
end
elseif dy > 0 then --dy = 1 270-90
if dx < 0 then --dy/dx = -1 270-0
--trigger.action.outText(_artyInRange:getName().." Firing NW:\n".. (_fireheading/math.pi)*180 .."\n", 300)
_fireheading= _fireheading + 2*math.pi
else --dy/dx = 1 0-90
--trigger.action.outText(_artyInRange:getName().." Firing NE:\n".. (_fireheading/math.pi)*180 .."\n", 300)
_fireheading= _fireheading
_FH = -1
end
end
local headingDeg =(_fireheading)/math.pi*180
if headingDeg >= 360 then
headingDeg = headingDeg-360
end
--trigger.action.outText(_artyInRange:getName().."\ndY ".. dy .."\ndX ".. dx .."\ndy/dx" .. dy/dx .."\nrad ".. _fireheading/math.pi .."\ndeg " .. headingDeg,120)
--_fireheading = _fireheading
local _TGTdist = math.sqrt(((tp.z-_artyPos.z)^2)+((tp.x-_artyPos.x)^2))
local _TGThghtD = math.abs(tp.y-_artyPos.y)
if _artyInRange:getUnit(1):getTypeName() == "2B11 mortar" then
_fireOffset.x = math.cos(_fireheading)*(-(100+_TGThghtD/10))*_FH
_fireOffset.z = math.sin(_fireheading)*(-(100+_TGThghtD/10))*_FH
elseif _artyInRange:getUnit(1):hasAttribute('Strategic bombers') or _artyInRange:getUnit(1):hasAttribute('Bombers') then
_artyRounds = 1
end
firepoint.x = tp.x + _fireOffset.x
firepoint.y = tp.z + _fireOffset.z
--firepoint.radius = 10
local firemission = {}
local ammoRemain = fac.artyGetAmmo(_artyInRange:getUnits())
if _artyInRange:getUnit(1):hasAttribute('Naval') then
local tempAmmoRemain = {}
tempAmmoRemain = fac.artyGetNavalGunAmmo(_artyInRange:getUnits())
ammoRemain = tempAmmoRemain[1]
end
if ammoRemain < _artyRounds then
_artyRounds = ammoRemain
end
if _artyInRange:getUnit(1):hasAttribute('Strategic bombers') or _artyInRange:getUnit(1):hasAttribute('Bombers') then
local bomberTasked = _artyInRange:getUnit(1)
local payloadCheck = {}
payloadCheck = bomberTasked:getAmmo()
if payloadCheck[1].desc.guidance == nil or payloadCheck[1].desc.guidance == 7 then
--trigger.action.outText(bomberTasked:getTypeName(),10)
--trigger.action.outText(#payloadCheck,10)
firepoint.expend = "Quarter"
else
--trigger.action.outText( payloadCheck[1].desc.guidance,120)
firepoint.expend = "One"
end
firepoint.attackQty = 1
firepoint.altitude = _artyPos.y
firepoint.altitudeEnabled = true
firemission = {id = 'Bombing', params = firepoint}
_artyInRange:getController():setOption(1,1)
_artyInRange:getController():setOption(10,3221225470)
elseif _artyInRange:getUnit(1):hasAttribute('MLRS') or (_artyInRange:getUnit(2) ~= nil and _artyInRange:getUnit(2):hasAttribute('MLRS')) then
firepoint.expendQty = _artyRounds
firepoint.expendQtyEnabled = true
firepoint.weaponType = 30720
firemission = {id = 'FireAtPoint', params = firepoint}
else
firepoint.expendQty = _artyRounds
firepoint.expendQtyEnabled = true
firepoint.weaponType = 258503344128
firemission = {id = 'FireAtPoint', params = firepoint}
end
-- local firepoint2 ={}
-- firepoint2.groupId = fac.getGroupId(_enemyUnit)
-- firepoint2.expend = "Quarter"
-- local firemission = {id = 'AttackGroup', params = firepoint2}
if _roundType ~= 1 then
--_artyInRange:getController():setOption(9,2)
local artyController = _artyInRange:getController()
--timer.scheduleFunction(fac.fireArty,{artyController,firemission},timer.getTime() + .5)
artyController:pushTask(firemission)
--_artyInRange:getController():setOption(9,0)
--if _roundType ~= -1 then
fac.ArtyTasked[_artyInRange:getName()]= {name = _artyInRange:getName(), tasked = _artyRounds ,timeTasked = timer.getTime() ,tgt = _enemyUnit, requestor = spotterName}
--end
--Controller.knowTarget(_artyInRange:getUnit(3):getController(),_enemyUnit)
trigger.action.outTextForGroup(_artyInRange:getID(),"Az: "..math.floor(headingDeg).." Range: ".._TGTdist,30)
--trigger.action.outTextForGroup(_groupId,"Az: "..math.floor(headingDeg).." Range: ".._TGTdist,60)
--local ammoRemain = fac.artyGetAmmo(_artyInRange:getUnits())
local displayUnitName = _artyInRange:getUnit(1):getDesc()
if _roundType == -1 then
msgTime = 1
end
trigger.action.outTextForCoalition(_facUnit:getCoalition(),"Fire mission order sent, " .. displayUnitName.displayName .. " Task Group(".. ammoRemain .. " rounds remaining"..") firing ".._artyRounds.." rounds at " .. _enemyUnit:getTypeName() .. ". Requestor: " .. spotterName ,msgTime)
timer.scheduleFunction(fac.purgeArtList,{_artyInRange:getName(),_artyRounds}, timer.getTime() + 200)
else
_illumPoint.x = tp.x
_illumPoint.y = tp.y + fac.illumHeight
_illumPoint.z = tp.z
trigger.action.illuminationBomb(_illumPoint,500)
trigger.action.outTextForCoalition(_facUnit:getCoalition(),"Fire mission order sent, " .. displayUnitName.displayName .. "Task Group is firing illumination rounds at " .. _enemyUnit:getTypeName() .. ". Requestor: " .. spotterName,10)
end
end
end
function fac.fireArty(_args)
_args[1]:pushTask(_args[2])
end
function fac.artyAICall()
--local atyDunitName
--trigger.action.outText("Tasking AI to call ARTY", 10)
fac.AITgted = {}
local aiARTYmultiTgt = {}
for _, atyDunitName in pairs(fac.artDirectNames) do
--trigger.action.outText(atyDunitName.. " found", 10)
local status, error = pcall(function()
local _unitR = fac.getFacUnit(atyDunitName)
if _unitR ~= nil then
--trigger.action.outText(atyDunitName.. " calling ARTY", 10)
local _groupIdR = fac.getGroupId(_unitR)
if _groupIdR then
--trigger.action.outText(atyDunitName.. " calling ARTY2", 10)
aiARTYmultiTgt = fac.scanForTGTai({atyDunitName})
-- local i
for i = 1, #aiARTYmultiTgt do
if contains(fac.AITgted,aiARTYmultiTgt[i]:getName()) == false then
table.insert(fac.AITgted, aiARTYmultiTgt[i]:getName())
if aiARTYmultiTgt[i]:isExist() then
--trigger.action.outText(atyDunitName.. " calling ARTY on " .. aiARTYmultiTgt[i]:getName(), 10)
fac.callFireMission({atyDunitName,10,-1,aiARTYmultiTgt[i]})
end
end
end
end
--[[else
env.info(string.format("FAC DEBUG: unit nil %s",_facUnitName)) ]]
end
end)
if (not status) then
env.error(string.format("Error adding f10 to ARTY Spotter: %s", error), false)
end
end
if ctld then
local troopTypeIDX
local transportIDX
local onboardArtD = false
for _i, transportIDX in pairs(ctld.inTransitTroops) do
--trigger.action.outText(transportIDX.. " found", 10)
--local onboardTroops = ctld.inTransitTroops[_i]
--trigger.action.outText(transportIDX.troops.type .. " found", 10)
if transportIDX.troops ~= nil then
--trigger.action.outText(transportIDX.troops .. " found", 10)
for _j, troopTypeIDX in pairs(transportIDX.troops.units) do
--trigger.action.outText(troopTypeIDX.type .. "on" .. _i .. " found", 10)
if contains(fac.artyDirectorTypes,troopTypeIDX.type) then
onboardArtD = true
break
end
end
if onboardArtD == true then
aiARTYmultiTgt = fac.scanForTGTai({_i})
-- local i
for i = 1, #aiARTYmultiTgt do
if contains(fac.AITgted,aiARTYmultiTgt[i]:getName()) == false then
table.insert(fac.AITgted, aiARTYmultiTgt[i]:getName())
if aiARTYmultiTgt[i]:isExist() then
--trigger.action.outText(atyDunitName.. " calling ARTY on " .. aiARTYmultiTgt[i]:getName(), 10)
fac.callFireMission({_i,10,-1,aiARTYmultiTgt[i]})
end
end
end
end
end
end
end
--fac.AITgted = {}
timer.scheduleFunction(fac.artyAICall, nil, timer.getTime() + 30)
end
-- Scheduled functions (run cyclically)
timer.scheduleFunction(fac.addFacF10MenuOptions, nil, timer.getTime() + 5.5)
timer.scheduleFunction(fac.checkFacStatus, nil, timer.getTime() + 5.4)
timer.scheduleFunction(fac.artyAICall, nil, timer.getTime() + 5)