forked from manshanko/bar-widgets
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcmd_reclaim_selected.lua
More file actions
184 lines (157 loc) · 5.38 KB
/
Copy pathcmd_reclaim_selected.lua
File metadata and controls
184 lines (157 loc) · 5.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
function widget:GetInfo()
return {
name = "Reclaim Selected",
desc = "Reclaim selected units with nearby nano turrets",
author = "manshanko",
date = "2025-04-01",
layer = 2,
enabled = false,
handler = true,
}
end
local CONFIG = {
-- change default action on button press to shuffle
shuffle = true,
}
local echo = Spring.Echo
local i18n = Spring.I18N
local GetSelectedUnits = Spring.GetSelectedUnits
local GetUnitDefID = Spring.GetUnitDefID
local GetUnitPosition = Spring.GetUnitPosition
local GetUnitSeparation = Spring.GetUnitSeparation
local GetUnitsInCylinder = Spring.GetUnitsInCylinder
local GiveOrderToUnit = Spring.GiveOrderToUnit
local GiveOrderToUnitArray = Spring.GiveOrderToUnitArray
local UnitDefs = UnitDefs
local CMD_RECLAIM = CMD.RECLAIM
local CMD_INSERT = CMD.INSERT
local CMD_OPT_SHIFT = CMD.OPT_SHIFT
local CMD_RECLAIM_SELECTED = 28329
local CMD_RECLAIM_SELECTED_DESCRIPTION = {
id = CMD_RECLAIM_SELECTED,
type = CMDTYPE.ICON,
name = "Reclaim Units",
cursor = nil,
action = "reclaim_selected",
}
i18n.set("en.ui.orderMenu." .. CMD_RECLAIM_SELECTED_DESCRIPTION.action, "Reclaim Selected")
i18n.set("en.ui.orderMenu." .. CMD_RECLAIM_SELECTED_DESCRIPTION.action .. "_tooltip", "Reclaim selected units")
local NANO_DEFS = {}
local MAX_DISTANCE = 0
for unit_def_id, unit_def in pairs(UnitDefs) do
if unit_def.isBuilder and not unit_def.canMove and not unit_def.isFactory then
NANO_DEFS[unit_def_id] = unit_def.buildDistance
if unit_def.buildDistance > MAX_DISTANCE then
MAX_DISTANCE = unit_def.buildDistance
end
end
end
local ALT = {"alt"}
local CMD_CACHE = { 0, CMD_RECLAIM, CMD_OPT_SHIFT, 0 }
local function ntNearUnit(target_unit_id)
local pos = {GetUnitPosition(target_unit_id)}
local units_near = GetUnitsInCylinder(pos[1], pos[3], MAX_DISTANCE, -2)
local unit_ids = {}
for _, id in ipairs(units_near) do
local dist = NANO_DEFS[GetUnitDefID(id)]
if dist ~= nil and target_unit_id ~= id then
if dist > GetUnitSeparation(target_unit_id, id, true) then
unit_ids[#unit_ids + 1] = id
end
end
end
return unit_ids
end
local function signalReclaim(target_unit_id)
local unit_ids = ntNearUnit(target_unit_id)
CMD_CACHE[4] = target_unit_id
GiveOrderToUnitArray(unit_ids, CMD_INSERT, CMD_CACHE, ALT)
end
local TASKS = nil
local function signalReclaimShuffle(target_unit_ids)
local executed = 0
TASKS = coroutine.wrap(function()
local tasks = {}
for i=1, #target_unit_ids do
local unit_ids = ntNearUnit(target_unit_ids[i])
table.shuffle(unit_ids)
tasks[i] = {
num_units = #unit_ids,
unit_ids = unit_ids,
target_unit_id = target_unit_ids[i],
}
end
local work = 0
local num_tasks = #tasks
local split = num_tasks
while num_tasks > 0 do
for i, group in pairs(tasks) do
local grp_unit_ids = group.unit_ids
local num_units = group.num_units
local take = math.ceil(math.min(math.max(4, num_units / split), num_units))
group.num_units = group.num_units - take
local unit_ids = {}
for i=1, take do
unit_ids[i] = grp_unit_ids[num_units - i + 1]
end
if group.num_units == 0 then
tasks[i] = nil
num_tasks = num_tasks - 1
end
CMD_CACHE[4] = group.target_unit_id
GiveOrderToUnitArray(unit_ids, CMD_INSERT, CMD_CACHE, ALT)
work = work + take
if work > 30 then
executed = executed + work
work = 0
if executed >= 1000 then
num_tasks = 0
break
else
coroutine.yield()
end
end
end
end
TASKS = nil
end)
TASKS()
end
local function handleReclaimSelected()
local unit_ids = GetSelectedUnits()
for _, unit_id in ipairs(unit_ids) do
signalReclaim(unit_id)
end
end
local function handleReclaimSelectedShuffle()
signalReclaimShuffle(GetSelectedUnits())
end
function widget:CommandsChanged()
local unit_ids = GetSelectedUnits()
if #unit_ids > 0 then
local cmds = widgetHandler.customCommands
cmds[#cmds + 1] = CMD_RECLAIM_SELECTED_DESCRIPTION
end
end
function widget:CommandNotify(cmd_id, cmd_params, cmd_options)
if cmd_id == CMD_RECLAIM_SELECTED then
if CONFIG.shuffle then
handleReclaimSelectedShuffle()
else
handleReclaimSelected()
end
end
end
function widget:GameFrame(n)
if TASKS and n % 3 == 0 then
TASKS()
end
end
function widget:Initialize()
widgetHandler.actionHandler:AddAction(self, "reclaim_selected", handleReclaimSelected, nil, "p")
widgetHandler.actionHandler:AddAction(self, "reclaim_selected_shuffle", handleReclaimSelectedShuffle, nil, "p")
end
function widget:Shutdown()
widgetHandler.actionHandler:RemoveAction(self, "reclaim_selected", "p")
widgetHandler.actionHandler:RemoveAction(self, "reclaim_selected_shuffle", "p")
end