12 Commits

Author SHA1 Message Date
Ciaran Fisher
58acfbc152 JTAC Target Optimisation
Possible Fixes for JTAC priority
JTAC search optimised for high unit missions
Added JTAC "visual on" report
2018-01-18 21:45:13 +00:00
Ciaran Fisher
2a4c9ed91a Merge pull request #33 from ciribob/crateMove
Added force crate to be moved
2018-01-18 20:42:16 +00:00
Ciaran Fisher
a78dd40688 Added force crate to be moved
Added Wait time for requesting crates

Added per unit type optional group limits

Added per unit type allowable actions
2017-07-24 21:06:53 +01:00
Ciaran Fisher
44ff4d61da Version 2017-06-25 21:06:51 +01:00
Ciaran Fisher
196efb7bcb Added ability to set maximum group size
You can now set the maximum group size that'll fit in a helicopter.
Larger groups cant be picked up
2017-06-25 21:03:33 +01:00
Ciaran Fisher
38128b65c0 Release 1.64
Fixed bug where count in zone wouldn't work for Mission editor added
crates
Delayed config by a second so you can easily override options without
editing the file
2016-12-11 09:09:20 +00:00
Ciaran Fisher
ee6977aa96 Version bump 2016-12-07 22:26:01 +00:00
Ciaran Fisher
dc214da0d6 Added New Cargos
Added new cargos
Fixed bug where units / groups would disappear
Updating MIST
Updated all missions
2016-12-07 22:20:41 +00:00
Ciaran Fisher
ee41e86628 Merge pull request #24 from emilianomolina/master
List radio beacons when enabledRadioBeaconDrop is false.
2016-12-03 10:57:25 +00:00
Ciaran Fisher
fdc24a32c5 Merge pull request #25 from mvee/patch-1
Cargo objects were updated
2016-12-03 10:56:18 +00:00
mvee
cb63b37494 Cargo objects were updated
Quickfix for the cargo container hence the catergory and type was changed after Mi8 release
2016-12-02 18:58:49 +02:00
Emiliano Molina
cefd92f720 List radio beacons when enabledRadioBeaconDrop is false.
When radio beacons are programmatically generated, if option to allow
the player to create beacons is not set then there was no way for the
player to get the operating frequency of the programmatically generated
beacons.

This patch modifies addF10MenuOptions to give the user to list radio
beacons when enabledRadioBaconDrop is false.  If enabledRadioBeaconDrop
is true then there is no change to the behaviour of the program.

However if it is false then a check is made to see if
deployedRadioBeacons is empty.  If it is not the the user is given the
option to list radio beacons but not modify them.
2016-12-03 00:16:32 +11:00
8 changed files with 5935 additions and 4986 deletions

577
CTLD.lua
View File

@@ -12,11 +12,16 @@
Contributors: Contributors:
- Steggles - https://github.com/Bob7heBuilder - Steggles - https://github.com/Bob7heBuilder
- mvee - https://github.com/mvee
- jmontleon - https://github.com/jmontleon
- emilianomolina - https://github.com/emilianomolina
Version: 1.62 - 01/08/2016 Version: 1.70 - 25/06/2017
- Changed staticBugWorkaround to false as the bug is fixed - Added ability to set maximum group size that can be carried
- Sling load crates will now be destroyed when deployed - THIS IS GREAT! :D - Added new sling load crates
- Fixed bug where crates and / or groups would disappear
- Fixed bug where count in zone wouldn't work for mission crates
- Delayed config of F10 menu and other scheduled functions so they can be overwritten by mission if a user wants
]] ]]
ctld = {} -- DONT REMOVE! ctld = {} -- DONT REMOVE!
@@ -45,6 +50,7 @@ ctld.maximumSearchDistance = 4000 -- max distance for troops to search for enemy
ctld.maximumMoveDistance = 2000 -- max distance for troops to move from drop point if no enemy is nearby ctld.maximumMoveDistance = 2000 -- max distance for troops to move from drop point if no enemy is nearby
ctld.numberOfTroops = 10 -- default number of troops to load on a transport heli or C-130 ctld.numberOfTroops = 10 -- default number of troops to load on a transport heli or C-130
-- also works as maximum size of group that'll fit into a helicopter unless overridden
ctld.enableFastRopeInsertion = true -- allows you to drop troops by fast rope ctld.enableFastRopeInsertion = true -- allows you to drop troops by fast rope
ctld.fastRopeMaximumHeight = 18.28 -- in meters which is 60 ft max fast rope (not rappell) safe height ctld.fastRopeMaximumHeight = 18.28 -- in meters which is 60 ft max fast rope (not rappell) safe height
@@ -70,6 +76,10 @@ ctld.troopPickupAtFOB = true -- if true, troops can also be picked up at a creat
ctld.buildTimeFOB = 120 --time in seconds for the FOB to be built ctld.buildTimeFOB = 120 --time in seconds for the FOB to be built
ctld.crateWaitTime = 120 -- time in seconds to wait before you can spawn another crate
ctld.forceCrateToBeMoved = true -- a crate must be picked up at least once and moved before it can be unpacked. Helps to reduce crate spam
ctld.radioSound = "beacon.ogg" -- the name of the sound file to use for the FOB radio beacons. If this isnt added to the mission BEACONS WONT WORK! ctld.radioSound = "beacon.ogg" -- the name of the sound file to use for the FOB radio beacons. If this isnt added to the mission BEACONS WONT WORK!
ctld.radioSoundFC3 = "beaconsilent.ogg" -- name of the second silent radio file, used so FC3 aircraft dont hear ALL the beacon noises... :) ctld.radioSoundFC3 = "beaconsilent.ogg" -- name of the second silent radio file, used so FC3 aircraft dont hear ALL the beacon noises... :)
@@ -385,6 +395,49 @@ ctld.vehicleTransportEnabled = {
"C-130", "C-130",
} }
-- ************** Maximum Units SETUP for UNITS ******************
-- Put the name of the Unit you want to limit group sizes too
-- i.e
-- ["UH-1H"] = 10,
--
-- Will limit UH1 to only transport groups with a size 10 or less
-- Make sure the unit name is exactly right or it wont work
ctld.unitLoadLimits = {
-- Remove the -- below to turn on options
-- ["SA342Mistral"] = 4,
-- ["SA342L"] = 4,
-- ["SA342M"] = 4,
}
-- ************** Allowable actions for UNIT TYPES ******************
-- Put the name of the Unit you want to limit actions for
-- NOTE - the unit must've been listed in the transportPilotNames list above
-- This can be used in conjunction with the options above for group sizes
-- By default you can load both crates and troops unless overriden below
-- i.e
-- ["UH-1H"] = {crates=true, troops=false},
--
-- Will limit UH1 to only transport CRATES but NOT TROOPS
--
-- ["SA342Mistral"] = {crates=fales, troops=true},
-- Will allow Mistral Gazelle to only transport crates, not troops
ctld.unitActions = {
-- Remove the -- below to turn on options
-- ["SA342Mistral"] = {crates=true, troops=true},
-- ["SA342L"] = {crates=false, troops=true},
-- ["SA342M"] = {crates=false, troops=true},
}
-- ************** INFANTRY GROUPS FOR PICKUP ****************** -- ************** INFANTRY GROUPS FOR PICKUP ******************
-- Unit Types -- Unit Types
-- inf is normal infantry -- inf is normal infantry
@@ -474,6 +527,22 @@ ctld.jtacUnitTypes = {
"SKP", "Hummer" -- there are some wierd encoding issues so if you write SKP-11 it wont match as the - sign is encoded differently... "SKP", "Hummer" -- there are some wierd encoding issues so if you write SKP-11 it wont match as the - sign is encoded differently...
} }
ctld.nextUnitId = 1;
ctld.getNextUnitId = function()
ctld.nextUnitId = ctld.nextUnitId + 1
return ctld.nextUnitId
end
ctld.nextGroupId = 1;
ctld.getNextGroupId = function()
ctld.nextGroupId = ctld.nextGroupId + 1
return ctld.nextGroupId
end
-- *************************************************************** -- ***************************************************************
-- **************** Mission Editor Functions ********************* -- **************** Mission Editor Functions *********************
-- *************************************************************** -- ***************************************************************
@@ -1171,7 +1240,7 @@ function ctld.spawnCrateAtZone(_side, _weight,_zone)
local _alt = land.getHeight(_pos2) local _alt = land.getHeight(_pos2)
local _point = { x = _pos2.x, y = _alt, z = _pos2.y } local _point = { x = _pos2.x, y = _alt, z = _pos2.y }
local _unitId = mist.getNextUnitId() local _unitId = ctld.getNextUnitId()
local _name = string.format("%s #%i", _crateType.desc, _unitId) local _name = string.format("%s #%i", _crateType.desc, _unitId)
@@ -1206,7 +1275,7 @@ function ctld.spawnCrateAtPoint(_side, _weight,_point)
_country = 2 _country = 2
end end
local _unitId = mist.getNextUnitId() local _unitId = ctld.getNextUnitId()
local _name = string.format("%s #%i", _crateType.desc, _unitId) local _name = string.format("%s #%i", _crateType.desc, _unitId)
@@ -1255,6 +1324,9 @@ ctld.AASystemTemplate = {
} }
ctld.crateWait = {}
ctld.crateMove = {}
---------------- INTERNAL FUNCTIONS ---------------- ---------------- INTERNAL FUNCTIONS ----------------
function ctld.getTransportUnit(_unitName) function ctld.getTransportUnit(_unitName)
@@ -1278,12 +1350,12 @@ function ctld.spawnCrateStatic(_country, _unitId, _point, _name, _weight,_side)
local _spawnedCrate local _spawnedCrate
if ctld.staticBugWorkaround and ctld.slingLoad == false then if ctld.staticBugWorkaround and ctld.slingLoad == false then
local _groupId = mist.getNextGroupId() local _groupId = ctld.getNextGroupId()
local _groupName = "Crate Group #".._groupId local _groupName = "Crate Group #".._groupId
local _group = { local _group = {
["visible"] = false, ["visible"] = false,
["groupId"] = _groupId, -- ["groupId"] = _groupId,
["hidden"] = false, ["hidden"] = false,
["units"] = {}, ["units"] = {},
-- ["y"] = _positions[1].z, -- ["y"] = _positions[1].z,
@@ -1308,10 +1380,10 @@ function ctld.spawnCrateStatic(_country, _unitId, _point, _name, _weight,_side)
if ctld.slingLoad then if ctld.slingLoad then
_crate = { _crate = {
["category"] = "Cargo", ["category"] = "Cargos", --now plurar
["shape_name"] = "ab-212_cargo", ["shape_name"] = "bw_container_cargo", --new slingloadable container
["type"] = "Cargo1", ["type"] = "container_cargo", --new type
["unitId"] = _unitId, -- ["unitId"] = _unitId,
["y"] = _point.z, ["y"] = _point.z,
["x"] = _point.x, ["x"] = _point.x,
["mass"] = _weight, ["mass"] = _weight,
@@ -1323,11 +1395,55 @@ function ctld.spawnCrateStatic(_country, _unitId, _point, _name, _weight,_side)
-- ["cargoDisplayName"] = "cargo123", -- ["cargoDisplayName"] = "cargo123",
-- ["CargoDisplayName"] = "cargo123", -- ["CargoDisplayName"] = "cargo123",
} }
--[[ Placeholder for different type of cargo containers. Let's say pipes and trunks, fuel for FOB building
["shape_name"] = "ab-212_cargo",
["type"] = "uh1h_cargo" --new type for the container previously used
["shape_name"] = "ammo_box_cargo",
["type"] = "ammo_cargo",
["shape_name"] = "barrels_cargo",
["type"] = "barrels_cargo",
["shape_name"] = "bw_container_cargo",
["type"] = "container_cargo",
["shape_name"] = "f_bar_cargo",
["type"] = "f_bar_cargo",
["shape_name"] = "fueltank_cargo",
["type"] = "fueltank_cargo",
["shape_name"] = "iso_container_cargo",
["type"] = "iso_container",
["shape_name"] = "iso_container_small_cargo",
["type"] = "iso_container_small",
["shape_name"] = "oiltank_cargo",
["type"] = "oiltank_cargo",
["shape_name"] = "pipes_big_cargo",
["type"] = "pipes_big_cargo",
["shape_name"] = "pipes_small_cargo",
["type"] = "pipes_small_cargo",
["shape_name"] = "tetrapod_cargo",
["type"] = "tetrapod_cargo",
["shape_name"] = "trunks_long_cargo",
["type"] = "trunks_long_cargo",
["shape_name"] = "trunks_small_cargo",
["type"] = "trunks_small_cargo",
]]--
else else
_crate = { _crate = {
["shape_name"] = "GeneratorF", ["shape_name"] = "GeneratorF",
["type"] = "GeneratorF", ["type"] = "GeneratorF",
["unitId"] = _unitId, -- ["unitId"] = _unitId,
["y"] = _point.z, ["y"] = _point.z,
["x"] = _point.x, ["x"] = _point.x,
["name"] = _name, ["name"] = _name,
@@ -1361,7 +1477,7 @@ function ctld.spawnFOBCrateStatic(_country, _unitId, _point, _name)
["category"] = "Fortifications", ["category"] = "Fortifications",
["shape_name"] = "konteiner_red1", ["shape_name"] = "konteiner_red1",
["type"] = "Container red 1", ["type"] = "Container red 1",
["unitId"] = _unitId, -- ["unitId"] = _unitId,
["y"] = _point.z, ["y"] = _point.z,
["x"] = _point.x, ["x"] = _point.x,
["name"] = _name, ["name"] = _name,
@@ -1385,7 +1501,7 @@ function ctld.spawnFOB(_country, _unitId, _point, _name)
local _crate = { local _crate = {
["category"] = "Fortifications", ["category"] = "Fortifications",
["type"] = "outpost", ["type"] = "outpost",
["unitId"] = _unitId, -- ["unitId"] = _unitId,
["y"] = _point.z, ["y"] = _point.z,
["x"] = _point.x, ["x"] = _point.x,
["name"] = _name, ["name"] = _name,
@@ -1398,10 +1514,10 @@ function ctld.spawnFOB(_country, _unitId, _point, _name)
local _spawnedCrate = StaticObject.getByName(_crate["name"]) local _spawnedCrate = StaticObject.getByName(_crate["name"])
--local _spawnedCrate = coalition.addStaticObject(_country, _crate) --local _spawnedCrate = coalition.addStaticObject(_country, _crate)
local _id = mist.getNextUnitId() local _id = ctld.getNextUnitId()
local _tower = { local _tower = {
["type"] = "house2arm", ["type"] = "house2arm",
["unitId"] = _id, -- ["unitId"] = _id,
["rate"] = 100, ["rate"] = 100,
["y"] = _point.z + -36.57142857, ["y"] = _point.z + -36.57142857,
["x"] = _point.x + 14.85714286, ["x"] = _point.x + 14.85714286,
@@ -1464,14 +1580,23 @@ function ctld.spawnCrate(_arguments)
local _position = _heli:getPosition() local _position = _heli:getPosition()
-- check crate spam
if _heli:getPlayerName() ~= nil and ctld.crateWait[_heli:getPlayerName()] and ctld.crateWait[_heli:getPlayerName()] < timer.getTime() then
ctld.displayMessageToGroup(_heli,"Sorry you must wait "..(ctld.crateWait[_heli:getPlayerName()] - timer.getTime()).. " seconds before you can get another crate", 20)
return
end
if _heli:getPlayerName() ~= nil then
ctld.crateWait[_heli:getPlayerName()] = timer.getTime() + ctld.crateWaitTime
end
-- trigger.action.outText("Spawn Crate".._args[1].." ".._args[2],10) -- trigger.action.outText("Spawn Crate".._args[1].." ".._args[2],10)
local _heli = ctld.getTransportUnit(_args[1]) local _heli = ctld.getTransportUnit(_args[1])
local _point = ctld.getPointAt12Oclock(_heli, 30) local _point = ctld.getPointAt12Oclock(_heli, 30)
local _unitId = mist.getNextUnitId() local _unitId = ctld.getNextUnitId()
local _side = _heli:getCoalition() local _side = _heli:getCoalition()
@@ -1479,6 +1604,9 @@ function ctld.spawnCrate(_arguments)
local _spawnedCrate = ctld.spawnCrateStatic(_heli:getCountry(), _unitId, _point, _name, _crateType.weight,_side) local _spawnedCrate = ctld.spawnCrateStatic(_heli:getCountry(), _unitId, _point, _name, _crateType.weight,_side)
-- add to move table
ctld.crateMove[_name] = _name
ctld.displayMessageToGroup(_heli, string.format("A %s crate weighing %s kg has been brought out and is at your 12 o'clock ", _crateType.desc, _crateType.weight), 20) ctld.displayMessageToGroup(_heli, string.format("A %s crate weighing %s kg has been brought out and is at your 12 o'clock ", _crateType.desc, _crateType.weight), 20)
else else
@@ -1675,7 +1803,7 @@ end
function ctld.insertIntoTroopsArray(_troopType,_count,_troopArray) function ctld.insertIntoTroopsArray(_troopType,_count,_troopArray)
for _i = 1, _count do for _i = 1, _count do
local _unitId = mist.getNextUnitId() local _unitId = ctld.getNextUnitId()
table.insert(_troopArray, { type = _troopType, unitId = _unitId, name = string.format("Dropped %s #%i", _troopType, _unitId) }) table.insert(_troopArray, { type = _troopType, unitId = _unitId, name = string.format("Dropped %s #%i", _troopType, _unitId) })
end end
@@ -1748,13 +1876,13 @@ function ctld.generateTroopTypes(_side, _countOrTemplate, _country)
end end
end end
local _unitId = mist.getNextUnitId() local _unitId = ctld.getNextUnitId()
_troops[_i] = { type = _unitType, unitId = _unitId, name = string.format("Dropped %s #%i", _unitType, _unitId) } _troops[_i] = { type = _unitType, unitId = _unitId, name = string.format("Dropped %s #%i", _unitType, _unitId) }
end end
end end
local _groupId = mist.getNextGroupId() local _groupId = ctld.getNextGroupId()
local _details = { units = _troops, groupId = _groupId, groupName = string.format("Dropped Group %i", _groupId), side = _side, country = _country } local _details = { units = _troops, groupId = _groupId, groupName = string.format("Dropped Group %i", _groupId), side = _side, country = _country }
return _details return _details
@@ -1848,13 +1976,13 @@ function ctld.generateVehiclesForTransport(_side, _country)
for _i, _type in ipairs(_list) do for _i, _type in ipairs(_list) do
local _unitId = mist.getNextUnitId() local _unitId = ctld.getNextUnitId()
_vehicles[_i] = { type = _type, unitId = _unitId, name = string.format("Dropped %s #%i", _type, _unitId) } _vehicles[_i] = { type = _type, unitId = _unitId, name = string.format("Dropped %s #%i", _type, _unitId) }
end end
local _groupId = mist.getNextGroupId() local _groupId = ctld.getNextGroupId()
local _details = { units = _vehicles, groupId = _groupId, groupName = string.format("Dropped Group %i", _groupId), side = _side, country = _country } local _details = { units = _vehicles, groupId = _groupId, groupName = string.format("Dropped Group %i", _groupId), side = _side, country = _country }
return _details return _details
@@ -1894,11 +2022,11 @@ function ctld.loadUnloadFOBCrate(_args)
local _side = _heli:getCoalition() local _side = _heli:getCoalition()
local _unitId = mist.getNextUnitId() local _unitId = ctld.getNextUnitId()
local _name = string.format("FOB Crate #%i", _unitId) local _name = string.format("FOB Crate #%i", _unitId)
local _spawnedCrate = ctld.spawnFOBCrateStatic(_heli:getCountry(), mist.getNextUnitId(), { x = _point.x + _xOffset, z = _point.z + _yOffset }, _name) local _spawnedCrate = ctld.spawnFOBCrateStatic(_heli:getCountry(), ctld.getNextUnitId(), { x = _point.x + _xOffset, z = _point.z + _yOffset }, _name)
if _side == 1 then if _side == 1 then
ctld.droppedFOBCratesRED[_name] = _name ctld.droppedFOBCratesRED[_name] = _name
@@ -2115,8 +2243,21 @@ function ctld.extractTroops(_args)
_extractTroops = ctld.findNearestGroup(_heli, ctld.droppedTroopsBLUE) _extractTroops = ctld.findNearestGroup(_heli, ctld.droppedTroopsBLUE)
end end
if _extractTroops ~= nil then if _extractTroops ~= nil then
local _limit = ctld.getTransportLimit(_heli:getTypeName())
local _size = #_extractTroops.group:getUnits()
if _limit < #_extractTroops.group:getUnits() then
ctld.displayMessageToGroup(_heli, "Sorry - The group of ".._size.." is too large to fit. \n\nLimit is ".._limit.." for ".._heli:getTypeName(), 20)
return
end
_onboard.troops = _extractTroops.details _onboard.troops = _extractTroops.details
trigger.action.outTextForCoalition(_heli:getCoalition(), ctld.getPlayerNameOrType(_heli) .. " extracted troops in " .. _heli:getTypeName() .. " from combat", 10) trigger.action.outTextForCoalition(_heli:getCoalition(), ctld.getPlayerNameOrType(_heli) .. " extracted troops in " .. _heli:getTypeName() .. " from combat", 10)
@@ -2293,6 +2434,9 @@ function ctld.checkHoverStatus()
ctld.hoverStatus[_transUnit:getName()] = nil ctld.hoverStatus[_transUnit:getName()] = nil
ctld.displayMessageToGroup(_transUnit, "Loaded " .. _crate.details.desc .. " crate!", 10,true) ctld.displayMessageToGroup(_transUnit, "Loaded " .. _crate.details.desc .. " crate!", 10,true)
--crates been moved once!
ctld.crateMove[_crate.crateUnit:getName()] = nil
if _transUnit:getCoalition() == 1 then if _transUnit:getCoalition() == 1 then
ctld.spawnedCratesRED[_crate.crateUnit:getName()] = nil ctld.spawnedCratesRED[_crate.crateUnit:getName()] = nil
else else
@@ -2353,6 +2497,8 @@ function ctld.loadNearbyCrate(_name)
ctld.spawnedCratesBLUE[_crate.crateUnit:getName()] = nil ctld.spawnedCratesBLUE[_crate.crateUnit:getName()] = nil
end end
ctld.crateMove[_crate.crateUnit:getName()] = nil
_crate.crateUnit:destroy() _crate.crateUnit:destroy()
local _copiedCrate = mist.utils.deepCopy(_crate.details) local _copiedCrate = mist.utils.deepCopy(_crate.details)
@@ -2755,6 +2901,12 @@ function ctld.unpackCrates(_arguments)
return return
end end
if ctld.forceCrateToBeMoved and ctld.crateMove[_crate.crateUnit:getName()] then
ctld.displayMessageToGroup(_heli,"Sorry you must move this crate before you unpack it!", 20)
return
end
local _aaTemplate = ctld.getAATemplate(_crate.details.unit) local _aaTemplate = ctld.getAATemplate(_crate.details.unit)
if _aaTemplate then if _aaTemplate then
@@ -2779,7 +2931,7 @@ function ctld.unpackCrates(_arguments)
local _cratePoint = _crate.crateUnit:getPoint() local _cratePoint = _crate.crateUnit:getPoint()
local _crateName = _crate.crateUnit:getName() local _crateName = _crate.crateUnit:getName()
-- ctld.spawnCrateStatic( _heli:getCoalition(),mist.getNextUnitId(),{x=100,z=100},_crateName,100) -- ctld.spawnCrateStatic( _heli:getCoalition(),ctld.getNextUnitId(),{x=100,z=100},_crateName,100)
--remove crate --remove crate
-- if ctld.slingLoad == false then -- if ctld.slingLoad == false then
@@ -2897,7 +3049,7 @@ function ctld.unpackFOBCrates(_crates, _heli)
timer.scheduleFunction(function(_args) timer.scheduleFunction(function(_args)
local _unitId = mist.getNextUnitId() local _unitId = ctld.getNextUnitId()
local _name = "Deployed FOB #" .. _unitId local _name = "Deployed FOB #" .. _unitId
local _fob = ctld.spawnFOB(_args[2], _unitId, _args[1], _name) local _fob = ctld.spawnFOB(_args[2], _unitId, _args[1], _name)
@@ -2957,7 +3109,7 @@ function ctld.dropSlingCrate(_args)
local _point = _heli:getPoint() local _point = _heli:getPoint()
local _unitId = mist.getNextUnitId() local _unitId = ctld.getNextUnitId()
local _side = _heli:getCoalition() local _side = _heli:getCoalition()
@@ -3106,20 +3258,20 @@ end
function ctld.spawnRadioBeaconUnit(_point, _country, _type) function ctld.spawnRadioBeaconUnit(_point, _country, _type)
local _groupId = mist.getNextGroupId() local _groupId = ctld.getNextGroupId()
local _unitId = mist.getNextUnitId() local _unitId = ctld.getNextUnitId()
local _radioGroup = { local _radioGroup = {
["visible"] = false, ["visible"] = false,
["groupId"] = _groupId, -- ["groupId"] = _groupId,
["hidden"] = false, ["hidden"] = false,
["units"] = { ["units"] = {
[1] = { [1] = {
["y"] = _point.z, ["y"] = _point.z,
["type"] = "2B11 mortar", ["type"] = "2B11 mortar",
["name"] = _type .. " Radio Beacon Unit #" .. _unitId, ["name"] = _type .. " Radio Beacon Unit #" .. _unitId,
["unitId"] = _unitId, -- ["unitId"] = _unitId,
["heading"] = 0, ["heading"] = 0,
["playerCanDrive"] = true, ["playerCanDrive"] = true,
["skill"] = "Excellent", ["skill"] = "Excellent",
@@ -3753,7 +3905,7 @@ end
function ctld.spawnCrateGroup(_heli, _positions, _types) function ctld.spawnCrateGroup(_heli, _positions, _types)
local _id = mist.getNextGroupId() local _id = ctld.getNextGroupId()
local _groupName = _types[1] .. " #" .. _id local _groupName = _types[1] .. " #" .. _id
@@ -3761,7 +3913,7 @@ function ctld.spawnCrateGroup(_heli, _positions, _types)
local _group = { local _group = {
["visible"] = false, ["visible"] = false,
["groupId"] = _id, -- ["groupId"] = _id,
["hidden"] = false, ["hidden"] = false,
["units"] = {}, ["units"] = {},
-- ["y"] = _positions[1].z, -- ["y"] = _positions[1].z,
@@ -3772,7 +3924,7 @@ function ctld.spawnCrateGroup(_heli, _positions, _types)
if #_positions == 1 then if #_positions == 1 then
local _unitId = mist.getNextUnitId() local _unitId = ctld.getNextUnitId()
local _details = { type = _types[1], unitId = _unitId, name = string.format("Unpacked %s #%i", _types[1], _unitId) } local _details = { type = _types[1], unitId = _unitId, name = string.format("Unpacked %s #%i", _types[1], _unitId) }
_group.units[1] = ctld.createUnit(_positions[1].x + 5, _positions[1].z + 5, 120, _details) _group.units[1] = ctld.createUnit(_positions[1].x + 5, _positions[1].z + 5, 120, _details)
@@ -3781,7 +3933,7 @@ function ctld.spawnCrateGroup(_heli, _positions, _types)
for _i, _pos in ipairs(_positions) do for _i, _pos in ipairs(_positions) do
local _unitId = mist.getNextUnitId() local _unitId = ctld.getNextUnitId()
local _details = { type = _types[_i], unitId = _unitId, name = string.format("Unpacked %s #%i", _types[_i], _unitId) } local _details = { type = _types[_i], unitId = _unitId, name = string.format("Unpacked %s #%i", _types[_i], _unitId) }
_group.units[_i] = ctld.createUnit(_pos.x + 5, _pos.z + 5, 120, _details) _group.units[_i] = ctld.createUnit(_pos.x + 5, _pos.z + 5, 120, _details)
@@ -3815,7 +3967,7 @@ function ctld.spawnDroppedGroup(_point, _details, _spawnBehind, _maxSearch)
local _group = { local _group = {
["visible"] = false, ["visible"] = false,
["groupId"] = _details.groupId, -- ["groupId"] = _details.groupId,
["hidden"] = false, ["hidden"] = false,
["units"] = {}, ["units"] = {},
-- ["y"] = _positions[1].z, -- ["y"] = _positions[1].z,
@@ -4012,7 +4164,7 @@ function ctld.createUnit(_x, _y, _angle, _details)
["y"] = _y, ["y"] = _y,
["type"] = _details.type, ["type"] = _details.type,
["name"] = _details.name, ["name"] = _details.name,
["unitId"] = _details.unitId, -- ["unitId"] = _details.unitId,
["heading"] = _angle, ["heading"] = _angle,
["playerCanDrive"] = true, ["playerCanDrive"] = true,
["skill"] = "Excellent", ["skill"] = "Excellent",
@@ -4447,6 +4599,26 @@ function ctld.checkAIStatus()
end end
function ctld.getTransportLimit(_unitType)
if ctld.unitLoadLimits[_unitType] then
return ctld.unitLoadLimits[_unitType]
end
return ctld.numberOfTroops
end
function ctld.getUnitActions(_unitType)
if ctld.unitActions[_unitType] then
return ctld.unitActions[_unitType]
end
return {crates=true,troops=true}
end
-- Adds menuitem to all heli units that are active -- Adds menuitem to all heli units that are active
function ctld.addF10MenuOptions() function ctld.addF10MenuOptions()
@@ -4470,6 +4642,11 @@ function ctld.addF10MenuOptions()
local _rootPath = missionCommands.addSubMenuForGroup(_groupId, "CTLD") local _rootPath = missionCommands.addSubMenuForGroup(_groupId, "CTLD")
local _unitActions = ctld.getUnitActions(_unit:getTypeName())
if _unitActions.troops then
local _troopCommandsPath = missionCommands.addSubMenuForGroup(_groupId, "Troop Transport", _rootPath) local _troopCommandsPath = missionCommands.addSubMenuForGroup(_groupId, "Troop Transport", _rootPath)
missionCommands.addCommandForGroup(_groupId, "Unload / Extract Troops", _troopCommandsPath, ctld.unloadExtractTroops, { _unitName }) missionCommands.addCommandForGroup(_groupId, "Unload / Extract Troops", _troopCommandsPath, ctld.unloadExtractTroops, { _unitName })
@@ -4479,9 +4656,13 @@ function ctld.addF10MenuOptions()
-- local _loadPath = missionCommands.addSubMenuForGroup(_groupId, "Load From Zone", _troopCommandsPath) -- local _loadPath = missionCommands.addSubMenuForGroup(_groupId, "Load From Zone", _troopCommandsPath)
for _,_loadGroup in pairs(ctld.loadableGroups) do for _,_loadGroup in pairs(ctld.loadableGroups) do
if not _loadGroup.side or _loadGroup.side == _unit:getCoalition() then if not _loadGroup.side or _loadGroup.side == _unit:getCoalition() then
-- check size & unit
if ctld.getTransportLimit(_unit:getTypeName()) >= _loadGroup.total then
missionCommands.addCommandForGroup(_groupId, "Load ".._loadGroup.name, _troopCommandsPath, ctld.loadTroopsFromZone, { _unitName, true,_loadGroup,false }) missionCommands.addCommandForGroup(_groupId, "Load ".._loadGroup.name, _troopCommandsPath, ctld.loadTroopsFromZone, { _unitName, true,_loadGroup,false })
end end
end end
end
if ctld.unitCanCarryVehicles(_unit) then if ctld.unitCanCarryVehicles(_unit) then
@@ -4497,8 +4678,10 @@ function ctld.addF10MenuOptions()
missionCommands.addCommandForGroup(_groupId, "Check Cargo", _vehicleCommandsPath, ctld.checkTroopStatus, { _unitName }) missionCommands.addCommandForGroup(_groupId, "Check Cargo", _vehicleCommandsPath, ctld.checkTroopStatus, { _unitName })
end end
end
if ctld.enableCrates then
if ctld.enableCrates and _unitActions.crates then
if ctld.unitCanCarryVehicles(_unit) == false then if ctld.unitCanCarryVehicles(_unit) == false then
@@ -4528,11 +4711,14 @@ function ctld.addF10MenuOptions()
end end
end end
if ctld.enabledFOBBuilding or ctld.enableCrates then if (ctld.enabledFOBBuilding or ctld.enableCrates) and _unitActions.crates then
local _crateCommands = missionCommands.addSubMenuForGroup(_groupId, "CTLD Commands", _rootPath) local _crateCommands = missionCommands.addSubMenuForGroup(_groupId, "CTLD Commands", _rootPath)
if ctld.hoverPickup == false or ctld.slingLoad == true then if ctld.hoverPickup == false then
if ctld.slingLoad == false then
missionCommands.addCommandForGroup(_groupId, "Load Nearby Crate", _crateCommands, ctld.loadNearbyCrate, _unitName ) missionCommands.addCommandForGroup(_groupId, "Load Nearby Crate", _crateCommands, ctld.loadNearbyCrate, _unitName )
end end
end
missionCommands.addCommandForGroup(_groupId, "Unpack Any Crate", _crateCommands, ctld.unpackCrates, { _unitName }) missionCommands.addCommandForGroup(_groupId, "Unpack Any Crate", _crateCommands, ctld.unpackCrates, { _unitName })
@@ -4562,6 +4748,9 @@ function ctld.addF10MenuOptions()
missionCommands.addCommandForGroup(_groupId, "List Beacons", _radioCommands, ctld.listRadioBeacons, { _unitName }) missionCommands.addCommandForGroup(_groupId, "List Beacons", _radioCommands, ctld.listRadioBeacons, { _unitName })
missionCommands.addCommandForGroup(_groupId, "Drop Beacon", _radioCommands, ctld.dropRadioBeacon, { _unitName }) missionCommands.addCommandForGroup(_groupId, "Drop Beacon", _radioCommands, ctld.dropRadioBeacon, { _unitName })
missionCommands.addCommandForGroup(_groupId, "Remove Closet Beacon", _radioCommands, ctld.removeRadioBeacon, { _unitName }) missionCommands.addCommandForGroup(_groupId, "Remove Closet Beacon", _radioCommands, ctld.removeRadioBeacon, { _unitName })
elseif ctld.deployedRadioBeacons ~= {} then
local _radioCommands = missionCommands.addSubMenuForGroup(_groupId, "Radio Beacons", _rootPath)
missionCommands.addCommandForGroup(_groupId, "List Beacons", _radioCommands, ctld.listRadioBeacons, { _unitName })
end end
ctld.addedTo[tostring(_groupId)] = true ctld.addedTo[tostring(_groupId)] = true
@@ -5024,144 +5213,153 @@ end
-- Find nearest enemy to JTAC that isn't blocked by terrain -- Find nearest enemy to JTAC that isn't blocked by terrain
function ctld.findNearestVisibleEnemy(_jtacUnit, _targetType,_distance) function ctld.findNearestVisibleEnemy(_jtacUnit, _targetType,_distance)
--local startTime = os.clock()
local _maxDistance = _distance or ctld.JTAC_maxDistance local _maxDistance = _distance or ctld.JTAC_maxDistance
local _x = 1
local _i = 1
local _units = nil
local _groupName = nil
local _nearestUnit = nil
local _nearestDistance = _maxDistance local _nearestDistance = _maxDistance
local _enemyGroups local _jtacPoint = _jtacUnit:getPoint()
local _coa = _jtacUnit:getCoalition()
local _offsetJTACPos = { x = _jtacPoint.x, y = _jtacPoint.y + 2.0, z = _jtacPoint.z }
local _volume = {
id = world.VolumeType.SPHERE,
params = {
point = _offsetJTACPos,
radius = _maxDistance
}
}
local _unitList = {}
local _search = function(_unit, _coa)
pcall(function()
if _unit ~= nil
and _unit:getLife() > 0
and _unit:isActive()
and _unit:getCoalition() ~= _coa
and not _unit:inAir()
and not ctld.alreadyTarget(_jtacUnit,_unit) then
local _tempPoint = _unit:getPoint()
local _offsetEnemyPos = { x = _tempPoint.x, y = _tempPoint.y + 2.0, z = _tempPoint.z }
if land.isVisible(_offsetJTACPos,_offsetEnemyPos ) then
local _dist = ctld.getDistance(_offsetJTACPos, _offsetEnemyPos)
if _dist < _maxDistance then
table.insert(_unitList,{unit=_unit, dist=_dist})
if _jtacUnit:getCoalition() == 1 then
_enemyGroups = coalition.getGroups(2, Group.Category.GROUND)
else
_enemyGroups = coalition.getGroups(1, Group.Category.GROUND)
end end
end
end
end)
return true
end
world.searchObjects(Object.Category.UNIT, _volume, _search, _coa)
--log.info(string.format("JTAC Search elapsed time: %.4f\n", os.clock() - startTime))
-- generate list order by distance & visible
-- first check
-- hpriority
-- priority
-- vehicle
-- unit
local _sort = function( a,b ) return a.dist < b.dist end
table.sort(_unitList,_sort)
-- sort list
-- check for hpriority
for _, _enemyUnit in ipairs(_unitList) do
local _enemyName = _enemyUnit.unit:getName()
if string.match(_enemyName, "hpriority") then
return _enemyUnit.unit
end
end
for _, _enemyUnit in ipairs(_unitList) do
local _enemyName = _enemyUnit.unit:getName()
if string.match(_enemyName, "priority") then
return _enemyUnit.unit
end
end
for _, _enemyUnit in ipairs(_unitList) do
local _enemyName = _enemyUnit.unit:getName()
if (_targetType == "vehicle" and ctld.isVehicle(_enemyUnit.unit)) or _targetType == "all" then
return _enemyUnit.unit
elseif (_targetType == "troop" and ctld.isInfantry(_enemyUnit.unit)) or _targetType == "all" then
return _enemyUnit.unit
end
end
return nil
end
function ctld.listNearbyEnemies(_jtacUnit)
local _maxDistance = ctld.JTAC_maxDistance
local _jtacPoint = _jtacUnit:getPoint() local _jtacPoint = _jtacUnit:getPoint()
local _jtacPosition = _jtacUnit:getPosition() local _coa = _jtacUnit:getCoalition()
local _tempPoint = nil
local _tempPosition = nil
local _tempDist = nil
-- 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 = ctld.getGroup(_groupName)
if #_units > 0 then
for _y = 1, #_units do
local _targeted = false
if not _distance then
_targeted = ctld.alreadyTarget(_jtacUnit, _units[_x])
end
-- calc distance
_tempPoint = _units[_y]:getPoint()
_tempDist = ctld.getDistance(_tempPoint, _jtacPoint)
if _tempDist < _maxDistance and _tempDist < _nearestDistance then
local _offsetEnemyPos = { x = _tempPoint.x, y = _tempPoint.y + 2.0, z = _tempPoint.z }
local _offsetJTACPos = { x = _jtacPoint.x, y = _jtacPoint.y + 2.0, z = _jtacPoint.z }
-- calc visible
if land.isVisible(_offsetEnemyPos, _offsetJTACPos) and _targeted == false then
if (string.match(_units[_y]:getName(), "hpriority") ~= nil) and ctld.isVehicle(_units[_y]) then
_vhpriority = true
elseif (string.match(_units[_y]:getName(), "priority") ~= nil) and ctld.isVehicle(_units[_y]) then
_vpriority = true
elseif (string.match(_units[_y]:getName(), "hpriority") ~= nil) and ctld.isInfantry(_units[_y]) then
_thpriority = true
elseif (string.match(_units[_y]:getName(), "priority") ~= nil) and ctld.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 = ctld.getGroup(_groupName)
if #_units > 0 then
for _x = 1, #_units do
--check to see if a JTAC has already targeted this unit only if a distance
--wasnt passed in
local _targeted = false
if not _distance then
_targeted = ctld.alreadyTarget(_jtacUnit, _units[_x])
end
local _allowedTarget = true
if _targetType == "vehicle" and _vhpriority == true then
_allowedTarget = (string.match(_units[_x]:getName(), "hpriority") ~= nil) and ctld.isVehicle(_units[_x])
elseif _targetType == "vehicle" and _vpriority == true then
_allowedTarget = (string.match(_units[_x]:getName(), "priority") ~= nil) and ctld.isVehicle(_units[_x])
elseif _targetType == "vehicle" then
_allowedTarget = ctld.isVehicle(_units[_x])
elseif _targetType == "troop" and _thpriority == true then
_allowedTarget = (string.match(_units[_x]:getName(), "hpriority") ~= nil) and ctld.isInfantry(_units[_x])
elseif _targetType == "troop" and _tpriority == true then
_allowedTarget = (string.match(_units[_x]:getName(), "priority") ~= nil) and ctld.isInfantry(_units[_x])
elseif _targetType == "troop" then
_allowedTarget = ctld.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 = ctld.getDistance(_tempPoint, _jtacPoint)
if _tempDist < _maxDistance and _tempDist < _nearestDistance then
local _offsetEnemyPos = { x = _tempPoint.x, y = _tempPoint.y + 2.0, z = _tempPoint.z }
local _offsetJTACPos = { x = _jtacPoint.x, y = _jtacPoint.y + 2.0, z = _jtacPoint.z } local _offsetJTACPos = { x = _jtacPoint.x, y = _jtacPoint.y + 2.0, z = _jtacPoint.z }
local _volume = {
id = world.VolumeType.SPHERE,
params = {
point = _offsetJTACPos,
radius = _maxDistance
}
}
local _enemies = nil
-- calc visible local _search = function(_unit, _coa)
if land.isVisible(_offsetEnemyPos, _offsetJTACPos) then pcall(function()
_nearestDistance = _tempDist if _unit ~= nil
_nearestUnit = _units[_x] and _unit:getLife() > 0
end and _unit:isActive()
end and _unit:getCoalition() ~= _coa
end and not _unit:inAir() then
end
end local _tempPoint = _unit:getPoint()
end local _offsetEnemyPos = { x = _tempPoint.x, y = _tempPoint.y + 2.0, z = _tempPoint.z }
if land.isVisible(_offsetJTACPos,_offsetEnemyPos ) then
if not _enemies then
_enemies = {}
end end
if _nearestUnit == nil then _enemies[_unit:getTypeName()] = _unit:getTypeName()
return nil
end
end
end)
return true
end end
world.searchObjects(Object.Category.UNIT, _volume, _search, _coa)
return _nearestUnit return _enemies
end end
-- tests whether the unit is targeted by another JTAC -- tests whether the unit is targeted by another JTAC
@@ -5250,6 +5448,18 @@ function ctld.getJTACStatus(_args)
if _enemyUnit ~= nil and _enemyUnit:getLife() > 0 and _enemyUnit:isActive() == true then if _enemyUnit ~= nil and _enemyUnit:getLife() > 0 and _enemyUnit:isActive() == true then
_message = _message .. "" .. _jtacGroupName .. " targeting " .. _enemyUnit:getTypeName() .. " CODE: " .. _laserCode .. ctld.getPositionString(_enemyUnit) .. "\n" _message = _message .. "" .. _jtacGroupName .. " targeting " .. _enemyUnit:getTypeName() .. " CODE: " .. _laserCode .. ctld.getPositionString(_enemyUnit) .. "\n"
local _list = ctld.listNearbyEnemies(_jtacUnit)
if _list then
_message = _message.."Visual On: "
for _,_type in pairs(_list) do
_message = _message.._type.." "
end
_message = _message.."\n"
end
else else
_message = _message .. "" .. _jtacGroupName .. " searching for targets" .. ctld.getPositionString(_jtacUnit) .. "\n" _message = _message .. "" .. _jtacGroupName .. " searching for targets" .. ctld.getPositionString(_jtacUnit) .. "\n"
end end
@@ -5719,19 +5929,51 @@ if ctld.allowRandomAiTeamPickups == true then
end end
end end
-- add total count
-- Scheduled functions (run cyclically) for _,_loadGroup in pairs(ctld.loadableGroups) do
_loadGroup.total = 0
if _loadGroup.aa then
_loadGroup.total = _loadGroup.aa + _loadGroup.total
end
if _loadGroup.inf then
_loadGroup.total = _loadGroup.inf + _loadGroup.total
end
if _loadGroup.mg then
_loadGroup.total = _loadGroup.mg + _loadGroup.total
end
if _loadGroup.at then
_loadGroup.total = _loadGroup.at + _loadGroup.total
end
if _loadGroup.mortar then
_loadGroup.total = _loadGroup.mortar + _loadGroup.total
end
end
-- Scheduled functions (run cyclically) -- but hold execution for a second so we can override parts
timer.scheduleFunction(ctld.refreshSmoke, nil, timer.getTime() + 5)
timer.scheduleFunction(ctld.addF10MenuOptions, nil, timer.getTime() + 5)
timer.scheduleFunction(ctld.checkAIStatus, nil, timer.getTime() + 1) timer.scheduleFunction(ctld.checkAIStatus, nil, timer.getTime() + 1)
timer.scheduleFunction(ctld.checkTransportStatus, nil, timer.getTime() + 5) timer.scheduleFunction(ctld.checkTransportStatus, nil, timer.getTime() + 5)
timer.scheduleFunction(function()
timer.scheduleFunction(ctld.refreshRadioBeacons, nil, timer.getTime() + 5) timer.scheduleFunction(ctld.refreshRadioBeacons, nil, timer.getTime() + 5)
timer.scheduleFunction(ctld.refreshSmoke, nil, timer.getTime() + 5)
timer.scheduleFunction(ctld.addF10MenuOptions, nil, timer.getTime() + 5)
if ctld.enableCrates == true and ctld.slingLoad == false and ctld.hoverPickup == true then if ctld.enableCrates == true and ctld.slingLoad == false and ctld.hoverPickup == true then
timer.scheduleFunction(ctld.checkHoverStatus, nil, timer.getTime() + 1) timer.scheduleFunction(ctld.checkHoverStatus, nil, timer.getTime() + 1)
end end
end,nil, timer.getTime()+1 )
--event handler for deaths --event handler for deaths
--world.addEventHandler(ctld.eventHandler) --world.addEventHandler(ctld.eventHandler)
@@ -5780,9 +6022,10 @@ for _coalitionName, _coalitionData in pairs(env.mission.coalition) do
for _groupId, _group in pairs(_objectTypeData.group) do for _groupId, _group in pairs(_objectTypeData.group) do
if _group and _group.units and type(_group.units) == 'table' then if _group and _group.units and type(_group.units) == 'table' then
for _unitNum, _unit in pairs(_group.units) do for _unitNum, _unit in pairs(_group.units) do
if _unit.type == "Cargo1" and _unit.canCargo == true then if _unit.canCargo == true then
ctld.missionEditorCargoCrates[_unit.name] = _unit.name local _cargoName = env.getValueDictByKey(_unit.name)
env.info("Crate Found: " .. _unit.name) ctld.missionEditorCargoCrates[_cargoName] = _cargoName
env.info("Crate Found: " .. _unit.name.." - Unit: ".._cargoName)
end end
end end
end end

Binary file not shown.

Binary file not shown.

7750
mist.lua

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.