Compare commits

...

11 Commits

Author SHA1 Message Date
Ciaran Fisher 644b4dc2fe Added optional despawn timers to JTAC and to Troops 2019-01-12 10:52:25 +00:00
Ciaran Fisher 58731f3d84 Bug Fix 2018-04-16 22:16:27 +01:00
Ciaran Fisher 71b54491fc Release 1.73 2018-04-15 18:28:38 +01:00
Ciaran Fisher 7ca6af38fc Version bump 2018-04-15 18:23:24 +01:00
Ciaran Fisher 844144f695 Added minimum distance from friendly logistics option 2018-04-15 15:51:44 +01:00
Ciaran Fisher f12c67c5e0 Bug Fix
Bug fix for crate timing out
2018-02-18 17:16:40 +00:00
Ciaran Fisher b5436bd6d2 Update 1.71 2018-01-18 21:54:27 +00:00
Ciaran Fisher a10de260c7 Merge pull request #36 from ciribob/crateMove
Merge pull request #35 from ciribob/master
2018-01-18 21:50:48 +00:00
Ciaran Fisher 4d3ae4b5ee Update missions 2018-01-18 21:49:40 +00:00
Ciaran Fisher f6efa0ec58 Merge pull request #34 from ciribob/jtac-optimisation
JTAC Target Optimisation
2018-01-18 21:47:12 +00:00
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
8 changed files with 6127 additions and 6029 deletions
+3
View File
@@ -0,0 +1,3 @@
*.iml
.idea/encodings.xml
*.xml
+228 -133
View File
@@ -16,12 +16,8 @@
- jmontleon - https://github.com/jmontleon - jmontleon - https://github.com/jmontleon
- emilianomolina - https://github.com/emilianomolina - emilianomolina - https://github.com/emilianomolina
Version: 1.70 - 25/06/2017 Version: 1.73 - 15/04/2018
- Added ability to set maximum group size that can be carried - Allow minimum distance from friendly logistics to be set
- 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!
@@ -49,6 +45,10 @@ ctld.maximumDistanceLogistic = 200 -- max distance from vehicle to logistics to
ctld.maximumSearchDistance = 4000 -- max distance for troops to search for enemy 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.minimumDeployDistance = 1000 -- minimum distance from a friendly pickup zone where you can deploy a crate
ctld.despawnTroopsTimer = -1 -- if this value is a positive number, any deployed troops will despawn after that amount of seconds have elapsed
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 -- 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
@@ -132,6 +132,8 @@ ctld.JTAC_location = true -- shows location of target in JTAC message
ctld.JTAC_lock = "all" -- "vehicle" OR "troop" OR "all" forces JTAC to only lock vehicles or troops or all ground units ctld.JTAC_lock = "all" -- "vehicle" OR "troop" OR "all" forces JTAC to only lock vehicles or troops or all ground units
ctld.JTAC_despawnTimer = -1 -- if this value is a positive number, any deployed JTACS will despawn after that amount of seconds have elapsed
-- ***************** Pickup, dropoff and waypoint zones ***************** -- ***************** Pickup, dropoff and waypoint zones *****************
-- Available colors (anything else like "none" disables smoke): "green", "red", "white", "orange", "blue", "none", -- Available colors (anything else like "none" disables smoke): "green", "red", "white", "orange", "blue", "none",
@@ -1581,7 +1583,7 @@ function ctld.spawnCrate(_arguments)
local _position = _heli:getPosition() local _position = _heli:getPosition()
-- check crate spam -- check crate spam
if _heli:getPlayerName() ~= nil and ctld.crateWait[_heli:getPlayerName()] and ctld.crateWait[_heli:getPlayerName()] < timer.getTime() then 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) ctld.displayMessageToGroup(_heli,"Sorry you must wait "..(ctld.crateWait[_heli:getPlayerName()] - timer.getTime()).. " seconds before you can get another crate", 20)
return return
@@ -1657,6 +1659,32 @@ function ctld.troopsOnboard(_heli, _troops)
end end
end end
-- tracks the troops dropped or JTACS
-- stores group name and expiry time -- reset on redrop
ctld.droppedTroopsTracker = {}
function ctld.despawnTimer(groupName,despawnTimer)
if despawnTimer > 0 then
-- resets timer if time reused
ctld.droppedTroopsTracker[groupName] = (timer.getTime() +despawnTimer) - 1
timer.scheduleFunction(function()
-- checks timer hasnt been reset
if ctld.droppedTroopsTracker[groupName] < timer.getTime() then
local group = Group.getByName(groupName)
if group then
group:destroy()
end
end
end, nil, timer.getTime() + ctld.despawnTroopsTimer)
end
end
-- if its dropped by AI then there is no player name so return the type of unit -- if its dropped by AI then there is no player name so return the type of unit
function ctld.getPlayerNameOrType(_heli) function ctld.getPlayerNameOrType(_heli)
@@ -1753,6 +1781,9 @@ function ctld.deployTroops(_heli, _troops)
ctld.processCallback({unit = _heli, unloaded = _droppedTroops, action = "dropped_troops"}) ctld.processCallback({unit = _heli, unloaded = _droppedTroops, action = "dropped_troops"})
-- create timer
ctld.despawnTimer(_droppedTroops:getName(),ctld.despawnTroopsTimer)
else else
--extract zone! --extract zone!
@@ -1794,12 +1825,18 @@ function ctld.deployTroops(_heli, _troops)
ctld.processCallback({unit = _heli, unloaded = _droppedVehicles, action = "dropped_vehicles"}) ctld.processCallback({unit = _heli, unloaded = _droppedVehicles, action = "dropped_vehicles"})
-- create timer
ctld.despawnTimer(_droppedVehicles:getName(),ctld.despawnTroopsTimer)
trigger.action.outTextForCoalition(_heli:getCoalition(), ctld.getPlayerNameOrType(_heli) .. " dropped vehicles from " .. _heli:getTypeName() .. " into combat", 10) trigger.action.outTextForCoalition(_heli:getCoalition(), ctld.getPlayerNameOrType(_heli) .. " dropped vehicles from " .. _heli:getTypeName() .. " into combat", 10)
end end
end end
end end
end end
function ctld.insertIntoTroopsArray(_troopType,_count,_troopArray) function ctld.insertIntoTroopsArray(_troopType,_count,_troopArray)
for _i = 1, _count do for _i = 1, _count do
@@ -2885,6 +2922,16 @@ function ctld.unpackCrates(_arguments)
local _crates = ctld.getCratesAndDistance(_heli) local _crates = ctld.getCratesAndDistance(_heli)
local _crate = ctld.getClosestCrate(_heli, _crates) local _crate = ctld.getClosestCrate(_heli, _crates)
if ctld.inLogisticsZone(_heli) == true or ctld.farEnoughFromLogisticZone(_heli) == false then
ctld.displayMessageToGroup(_heli, "You can't unpack that here! Take it to where it's needed!", 20)
return
end
if _crate ~= nil and _crate.dist < 750 if _crate ~= nil and _crate.dist < 750
and (_crate.details.unit == "FOB" or _crate.details.unit == "FOB-SMALL") then and (_crate.details.unit == "FOB" or _crate.details.unit == "FOB-SMALL") then
@@ -2894,13 +2941,6 @@ function ctld.unpackCrates(_arguments)
elseif _crate ~= nil and _crate.dist < 200 then elseif _crate ~= nil and _crate.dist < 200 then
if ctld.inLogisticsZone(_heli) == true then
ctld.displayMessageToGroup(_heli, "You can't unpack that here! Take it to where it's needed!", 20)
return
end
if ctld.forceCrateToBeMoved and ctld.crateMove[_crate.crateUnit:getName()] then if ctld.forceCrateToBeMoved and ctld.crateMove[_crate.crateUnit:getName()] then
ctld.displayMessageToGroup(_heli,"Sorry you must move this crate before you unpack it!", 20) ctld.displayMessageToGroup(_heli,"Sorry you must move this crate before you unpack it!", 20)
return return
@@ -2963,6 +3003,9 @@ function ctld.unpackCrates(_arguments)
--put to the end --put to the end
table.insert(ctld.jtacGeneratedLaserCodes, _code) table.insert(ctld.jtacGeneratedLaserCodes, _code)
-- create timer
ctld.despawnTimer(_spawnedGroups:getName(),ctld.JTAC_despawnTimer)
ctld.JTACAutoLase(_spawnedGroups:getName(), _code) --(_jtacGroupName, _laserCode, _smoke, _lock, _colour) ctld.JTACAutoLase(_spawnedGroups:getName(), _code) --(_jtacGroupName, _laserCode, _smoke, _lock, _colour)
end end
end end
@@ -4382,6 +4425,37 @@ function ctld.inLogisticsZone(_heli)
return false return false
end end
-- are far enough from a friendly logistics zone
function ctld.farEnoughFromLogisticZone(_heli)
if ctld.inAir(_heli) then
return false
end
local _heliPoint = _heli:getPoint()
local _farEnough = true
for _, _name in pairs(ctld.logisticUnits) do
local _logistic = StaticObject.getByName(_name)
if _logistic ~= nil and _logistic:getCoalition() == _heli:getCoalition() then
--get distance
local _dist = ctld.getDistance(_heliPoint, _logistic:getPoint())
-- env.info("DIST ".._dist)
if _dist <= ctld.minimumDeployDistance then
-- env.info("TOO CLOSE ".._dist)
_farEnough = false
end
end
end
return _farEnough
end
function ctld.refreshSmoke() function ctld.refreshSmoke()
if ctld.disableAllSmoke == true then if ctld.disableAllSmoke == true then
@@ -5213,144 +5287,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()
if _jtacUnit:getCoalition() == 1 then local _offsetJTACPos = { x = _jtacPoint.x, y = _jtacPoint.y + 2.0, z = _jtacPoint.z }
_enemyGroups = coalition.getGroups(2, Group.Category.GROUND)
else local _volume = {
_enemyGroups = coalition.getGroups(1, Group.Category.GROUND) 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})
end
end
end
end)
return true
end 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 _offsetJTACPos = { x = _jtacPoint.x, y = _jtacPoint.y + 2.0, z = _jtacPoint.z }
local _tempPosition = nil
local _tempDist = nil local _volume = {
id = world.VolumeType.SPHERE,
params = {
point = _offsetJTACPos,
radius = _maxDistance
}
}
local _enemies = nil
-- finish this function local _search = function(_unit, _coa)
local _vhpriority = false pcall(function()
local _vpriority = false
local _thpriority = false if _unit ~= nil
local _tpriority = false and _unit:getLife() > 0
for _i = 1, #_enemyGroups do and _unit:isActive()
if _enemyGroups[_i] ~= nil then and _unit:getCoalition() ~= _coa
_groupName = _enemyGroups[_i]:getName() and not _unit:inAir() then
_units = ctld.getGroup(_groupName)
if #_units > 0 then local _tempPoint = _unit:getPoint()
for _y = 1, #_units do local _offsetEnemyPos = { x = _tempPoint.x, y = _tempPoint.y + 2.0, z = _tempPoint.z }
local _targeted = false
if not _distance then if land.isVisible(_offsetJTACPos,_offsetEnemyPos ) then
_targeted = ctld.alreadyTarget(_jtacUnit, _units[_x])
if not _enemies then
_enemies = {}
end end
-- calc distance _enemies[_unit:getTypeName()] = _unit:getTypeName()
_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
end end)
return true
end end
for _i = 1, #_enemyGroups do world.searchObjects(Object.Category.UNIT, _volume, _search, _coa)
if _enemyGroups[_i] ~= nil then
_groupName = _enemyGroups[_i]:getName()
_units = ctld.getGroup(_groupName)
if #_units > 0 then
for _x = 1, #_units do return _enemies
--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 }
-- calc visible
if land.isVisible(_offsetEnemyPos, _offsetJTACPos) then
_nearestDistance = _tempDist
_nearestUnit = _units[_x]
end
end
end
end
end
end
end
if _nearestUnit == nil then
return nil
end
return _nearestUnit
end end
-- tests whether the unit is targeted by another JTAC -- tests whether the unit is targeted by another JTAC
@@ -5439,6 +5522,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
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.