Skip to content

Instantly share code, notes, and snippets.

@L-e-x-o-n
Last active May 4, 2025 09:23
Show Gist options
  • Save L-e-x-o-n/fca8795fac2ae34b9fa75756bc1417d2 to your computer and use it in GitHub Desktop.
Save L-e-x-o-n/fca8795fac2ae34b9fa75756bc1417d2 to your computer and use it in GitHub Desktop.
Easier and smarter area unit reclaim orders, priority system by team and unitdef
function widget:GetInfo()
return {
name = "Improved unit area reclaim",
desc = "Easier and smarter area unit reclaim orders, priority system by team and unitdef",
author = "Lexon",
date = "17.07.2022",
version = 1.1,
license = "GNU GPL, v2 or later",
layer = 10,
enabled = true -- loaded by default?
}
end
local spGetUnitsInCylinder = Spring.GetUnitsInCylinder
local spGetFeaturesInCylinder = Spring.GetFeaturesInCylinder
local spGiveOrderToUnit = Spring.GiveOrderToUnit
local spGetSelectedUnits = Spring.GetSelectedUnits
local spGetUnitDefID = Spring.GetUnitDefID
local spGetUnitSeparation = Spring.GetUnitSeparation
local spGetUnitCommands = Spring.GetUnitCommands
local isImmobileBuilder = {}
for unitDefID, unitDef in pairs(UnitDefs) do
if unitDef.isBuilder and not unitDef.canMove and not unitDef.isFactory then
isImmobileBuilder[unitDefID] = true
end
end
local function ContainsFightCMD(commands)
for _, value in pairs(commands) do
if value.id == CMD.FIGHT then
return true
end
end
return false
end
local function FilterByUnitDefID(list, id)
for index, value in pairs(list) do
if spGetUnitDefID(value) ~= id then
list[index] = nil
end
end
return list
end
function widget:CommandNotify(cmdID, cmdParams, _)
-- Check if the command is a reclaim order
if cmdID == CMD.RECLAIM then
-- Check if the reclaim command is an area command (x, z, radius)
if cmdParams[1] and cmdParams[3] and cmdParams[4] then
local x, z, radius = cmdParams[1], cmdParams[3], cmdParams[4]
--Skip if features/reclaim is present
local features = spGetFeaturesInCylinder(x, z, radius)
if features and #features > 1 then
return false
end
local reclaimers = {}
local unitDefIDTemp
for _, reclaimerID in pairs(spGetSelectedUnits()) do
unitDefIDTemp = spGetUnitDefID(reclaimerID)
if UnitDefs[unitDefIDTemp].canReclaim then
reclaimers[reclaimerID] = unitDefIDTemp
end
end
-- Get unit under mouse
local targetDef = spGetUnitsInCylinder(x, z, 15)
if targetDef[1] then
targetDef = spGetUnitDefID(targetDef[1])
else
targetDef = nil
end
--Get enemy units first
local units = spGetUnitsInCylinder(x, z, radius, Spring.ENEMY_UNITS)
if targetDef then
units = FilterByUnitDefID(units, targetDef)
end
--Get allied units if there are no enemy units
if #units < 1 then
units = spGetUnitsInCylinder(x, z, radius, Spring.MY_UNITS)
if targetDef then
units = FilterByUnitDefID(units, targetDef)
end
end
for reclaimerID, unitDefID in pairs(reclaimers) do
for _, unitID in pairs(units) do
if isImmobileBuilder[unitDefID] and spGetUnitSeparation(reclaimerID, unitID, true) < UnitDefs[unitDefID].buildDistance then
-- Construction turrets are on fight command when idle
-- Inserting reclaim command, tried other nicer solutions but could not get them to work...
if ContainsFightCMD(spGetUnitCommands(reclaimerID, 2)) then
spGiveOrderToUnit(reclaimerID, CMD.INSERT, {0, CMD.RECLAIM, CMD.OPT_SHIFT, unitID}, {"alt"} )
else
spGiveOrderToUnit(reclaimerID, CMD.RECLAIM, {unitID}, {"shift"})
end
end
if not isImmobileBuilder[unitDefID] then
spGiveOrderToUnit(reclaimerID, CMD.RECLAIM, {unitID}, {"shift"})
end
end
end
-- Block the original order, it does nothing and triggers UnitIdle for con turrets that replaces our given order with a fight command
return true
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment