Loading...
  OR  Zero-K Name:    Password:   

Post edit history

New U.I. Suggestion: Hot Select for units

To display differences between versions, select one or more edits in the list using checkboxes and click "diff selected"
Post edit history
Date Editor Before After
6/3/2025 6:32:06 PMUSrankFrequentPilgrim before revert after revert
6/3/2025 6:22:22 PMUSrankFrequentPilgrim before revert after revert
6/3/2025 6:17:38 PMUSrankFrequentPilgrim before revert after revert
6/3/2025 6:07:05 PMUSrankFrequentPilgrim before revert after revert
6/3/2025 6:04:33 PMUSrankFrequentPilgrim before revert after revert
6/3/2025 5:46:28 PMUSrankFrequentPilgrim before revert after revert
Before After
1 Download this file and place it within your LuaUI/Widgets folder: 1 Download this file and place it within your LuaUI/Widgets folder:
2 https://github.com/FrequentPilgrim/FrequentPilgrim-Files/blob/main/gui_letter_auto_groups.lua 2 https://github.com/FrequentPilgrim/FrequentPilgrim-Files/blob/main/gui_letter_auto_groups.lua
3 \n 3 \n
4 Great News! 4 Great News!
5 \n 5 \n
6 I was able to put together a fully functional widget that has all of the features I was trying to implement. 6 I was able to put together a fully functional widget that has all of the features I was trying to implement.
7 \n 7 \n
8 This is working much better than the previous attempt in that it's now trivially easy to adjust your groupings exactly how you want. The groups get saved to your LUAui configuration files and persist until you decide to clear the group. There is no limitation on how many groups a unit can be added to. 8 This is working much better than the previous attempt in that it's now trivially easy to adjust your groupings exactly how you want. The groups get saved to your LUAui configuration files and persist until you decide to clear the group. There is no limitation on how many groups a unit can be added to. It's a good idea to save your configurations as backup before diving into this widget, just in case.
9 \n 9 \n
10 It feels great to combine groupings now with the shift key: combining your minotaurs and cyclops groups with the press of a button; Quickly pairing your Grizzly and Scallops to a lobster within a control group without lassoing with a mouse. 10 It feels great to combine groupings now with the shift key: combining your minotaurs and cyclops groups with the press of a button; Quickly pairing your Grizzly and Scallops to a lobster within a control group without lassoing with a mouse.
11 \n 11 \n
12 The filtering is also great. If you've ever been frustrated about trying to pull your artillery out of a unit blob, ctrl + space + T after I've selected the blob now filters my selection to artillery. 12 The filtering is also great. If you've ever been frustrated about trying to pull your artillery out of a unit blob, ctrl + space + T after I've selected the blob now filters my selection to artillery.
13 \n 13 \n
14 Having a factory selected no longer preventes spacebar + letter from selecting units. 14 Having a factory selected no longer preventes spacebar + letter from selecting units.
15 \n 15 \n
16 [img]https://i.imgur.com/pMphL2C.png[/img] 16 [img]https://i.imgur.com/pMphL2C.png[/img]
17 \n 17 \n
18 I have not been able to figure out how to implement controls for this widget into the menu system, despite spending many hours attempting to get it working. I would appreciate any assistance on menu integration. 18 I have not been able to figure out how to implement controls for this widget into the menu system, despite spending many hours attempting to get it working. I would appreciate any assistance on menu integration.
19 \n 19 \n
20 Instead, the widget uses the debug text box that appears by default when you press (f8). This will inform you of all of the notifications happening with your groupings.[img]https://i.imgur.com/xiy5BNh.png[/img] 20 Instead, the widget uses the debug text box that appears by default when you press (f8). This will inform you of all of the notifications happening with your groupings.[img]https://i.imgur.com/xiy5BNh.png[/img]
21 \n 21 \n
22 The controls also exists as part of the widget description, so if you forget in game you can simply hover over your widget in the alt+f11 window to get refreshed. 22 The controls also exists as part of the widget description, so if you forget in game you can simply hover over your widget in the alt+f11 window to get refreshed.
23 [img]https://i.imgur.com/6zvFeO7.png[/img] 23 [img]https://i.imgur.com/6zvFeO7.png[/img]
24 \n 24 \n
25 My recommendation is to set up all of the groups you want first in a singleplayer match against Inactive AI. Use either cheats or income multipliers to quickly produce 1 of every factory and 1 of every unit. Then save this match so that you can quickly make adjustments to your groupings by loading it. 25 My recommendation is to set up all of the groups you want first in a singleplayer match against Inactive AI. Use either cheats or income multipliers to quickly produce 1 of every factory and 1 of every unit. Then save this match so that you can quickly make adjustments to your groupings by loading it.
26 \n 26 \n
27 I've been using the previous widget to make to make this grouping process streamlined by clicking my premade group buttons in the menu system and then assigning them to a letter. My groupings and letters are mostly unchanged from my most recent posting about groupings. You'll want to clear all of the spacebar selections being used for the Global Selection Hotkeys widget. I'm still using global selections for air units, but these can also be assigned to 'Spacebar + Letter' groupings as you desire. 27 I've been using the previous widget to make to make this grouping process streamlined by clicking my premade group buttons in the menu system and then assigning them to a letter. My groupings and letters are mostly unchanged from my most recent posting about groupings. You'll want to clear all of the spacebar selections being used for the Global Selection Hotkeys widget. I'm still using global selections for air units, but these can also be assigned to 'Spacebar + Letter' groupings as you desire.
28 \n 28 \n
29 If you're not sure how to group things, I feel like this is a really solid start that you can tweak as desired instead of having to make everything from scratch: 29 If you're not sure how to group things, I feel like this is a really solid start that you can tweak as desired instead of having to make everything from scratch:
30 \n 30 \n
31 [img]https://i.imgur.com/0vDzBe7.png[/img] 31 [img]https://i.imgur.com/0vDzBe7.png[/img]
32 \n 32 \n
33 \n 33 \n
34 [img]https://i.imgur.com/CkcfxuF.png[/img] 34 [img]https://i.imgur.com/CkcfxuF.png[/img]
35 \n 35 \n
36 \n 36 \n
37 [img]https://i.imgur.com/pcLjalp.png[/img] 37 [img]https://i.imgur.com/pcLjalp.png[/img]
38 \n 38 \n
39 \n 39 \n
40 [img]https://i.imgur.com/f9jjHGR.png[/img] 40 [img]https://i.imgur.com/f9jjHGR.png[/img]
41 \n 41 \n
42 \n 42 \n
43 [img]https://i.imgur.com/E6qvKcQ.png[/img] 43 [img]https://i.imgur.com/E6qvKcQ.png[/img]
44 \n 44 \n
45 \n 45 \n
46 [img]https://i.imgur.com/lsbRQNY.png[/img] 46 [img]https://i.imgur.com/lsbRQNY.png[/img]
47 \n 47 \n
48 \n 48 \n
49 [img]https://i.imgur.com/STS6SsF.png[/img] 49 [img]https://i.imgur.com/STS6SsF.png[/img]
50 \n 50 \n
51 \n 51 \n
52 [img]https://i.imgur.com/rx8ccCe.png[/img] 52 [img]https://i.imgur.com/rx8ccCe.png[/img]
53 \n 53 \n
54 \n 54 \n
55 [img]https://i.imgur.com/w7Mg7Ca.png[/img] 55 [img]https://i.imgur.com/w7Mg7Ca.png[/img]
56 \n 56 \n
57 \n 57 \n
58 [img]https://i.imgur.com/5LdhPg3.png[/img] 58 [img]https://i.imgur.com/5LdhPg3.png[/img]
59 \n 59 \n
60 \n 60 \n
61 [img]https://i.imgur.com/fTtTRlu.png[/img] 61 [img]https://i.imgur.com/fTtTRlu.png[/img]
62 \n 62 \n
63 \n 63 \n
64 [img]https://i.imgur.com/xZpr9w9.png[/img] 64 [img]https://i.imgur.com/xZpr9w9.png[/img]
65 \n 65 \n
66 \n 66 \n
67 [img]https://i.imgur.com/4CYuhYq.png[/img] 67 [img]https://i.imgur.com/4CYuhYq.png[/img]
68 \n 68 \n
69 \n 69 \n
70 [img]https://i.imgur.com/RMdipho.png[/img] 70 [img]https://i.imgur.com/RMdipho.png[/img]
71 \n 71 \n
72 \n 72 \n
73 [img]https://i.imgur.com/bOtmPR2.png[/img] 73 [img]https://i.imgur.com/bOtmPR2.png[/img]
74 \n 74 \n
75 Just for reference these are my Air Hotkeys that Im still using the older widget to control. 75 Just for reference these are my Air Hotkeys that Im still using the older widget to control.
76 [img]https://i.imgur.com/AQJsryg.png[/img] 76 [img]https://i.imgur.com/AQJsryg.png[/img]
77 \n 77 \n
78 \n 78 \n
79 Click this spoiler to see the categories I'm currently using and how they are saved within Zero-K\LuaUI\Config ZK_data.lua 79 Click this spoiler to see the categories I'm currently using and how they are saved within Zero-K\LuaUI\Config ZK_data.lua
80 [spoiler] 80 [spoiler]
81 \n 81 \n
82 ["Letter UnitType Multi Auto Groups"] = { 82 ["Letter UnitType Multi Auto Groups"] = {
83 A = { 83 A = {
84 [1] = "hoverassault", 84 [1] = "hoverassault",
85 [2] = "cloakassault", 85 [2] = "cloakassault",
86 [3] = "jumpassault", 86 [3] = "jumpassault",
87 [4] = "spiderassault", 87 [4] = "spiderassault",
88 [5] = "tankassault", 88 [5] = "tankassault",
89 [6] = "shieldassault", 89 [6] = "shieldassault",
90 [7] = "vehassault", 90 [7] = "vehassault",
91 }, 91 },
92 B = { 92 B = {
93 [1] = "tankaa", 93 [1] = "tankaa",
94 [2] = "shieldbomb", 94 [2] = "shieldbomb",
95 [3] = "hoverassault", 95 [3] = "hoverassault",
96 [4] = "vehaa", 96 [4] = "vehaa",
97 [5] = "hoverdepthcharge", 97 [5] = "hoverdepthcharge",
98 [6] = "jumpscout", 98 [6] = "jumpscout",
99 [7] = "hoverraid", 99 [7] = "hoverraid",
100 [8] = "jumpbomb", 100 [8] = "jumpbomb",
101 [9] = "shieldscout", 101 [9] = "shieldscout",
102 [10] = "amphtele", 102 [10] = "amphtele",
103 [11] = "spideremp", 103 [11] = "spideremp",
104 [12] = "shieldassault", 104 [12] = "shieldassault",
105 [13] = "cloakbomb", 105 [13] = "cloakbomb",
106 [14] = "spiderscout", 106 [14] = "spiderscout",
107 [15] = "jumpaa", 107 [15] = "jumpaa",
108 [16] = "shieldraid", 108 [16] = "shieldraid",
109 [17] = "tankheavyassault", 109 [17] = "tankheavyassault",
110 [18] = "vehscout", 110 [18] = "vehscout",
111 [19] = "tankarty", 111 [19] = "tankarty",
112 [20] = "amphfloater", 112 [20] = "amphfloater",
113 [21] = "cloakheavyraid", 113 [21] = "cloakheavyraid",
114 [22] = "shieldshield", 114 [22] = "shieldshield",
115 [23] = "shieldriot", 115 [23] = "shieldriot",
116 [24] = "veharty", 116 [24] = "veharty",
117 [25] = "shieldarty", 117 [25] = "shieldarty",
118 [26] = "cloakaa", 118 [26] = "cloakaa",
119 [27] = "vehassault", 119 [27] = "vehassault",
120 [28] = "spiderriot", 120 [28] = "spiderriot",
121 [29] = "jumpsumo", 121 [29] = "jumpsumo",
122 [30] = "hoverarty", 122 [30] = "hoverarty",
123 [31] = "shieldfelon", 123 [31] = "shieldfelon",
124 [32] = "jumpblackhole", 124 [32] = "jumpblackhole",
125 [33] = "tankheavyarty", 125 [33] = "tankheavyarty",
126 [34] = "tankheavyraid", 126 [34] = "tankheavyraid",
127 [35] = "vehsupport", 127 [35] = "vehsupport",
128 [36] = "jumpassault", 128 [36] = "jumpassault",
129 [37] = "amphbomb", 129 [37] = "amphbomb",
130 [38] = "shieldaa", 130 [38] = "shieldaa",
131 [39] = "spiderassault", 131 [39] = "spiderassault",
132 [40] = "vehriot", 132 [40] = "vehriot",
133 [41] = "amphlaunch", 133 [41] = "amphlaunch",
134 [42] = "spideraa", 134 [42] = "spideraa",
135 [43] = "jumpskirm", 135 [43] = "jumpskirm",
136 [44] = "vehcapture", 136 [44] = "vehcapture",
137 [45] = "cloakraid", 137 [45] = "cloakraid",
138 [46] = "amphraid", 138 [46] = "amphraid",
139 [47] = "tankassault", 139 [47] = "tankassault",
140 [48] = "cloaksnipe", 140 [48] = "cloaksnipe",
141 [49] = "shieldskirm", 141 [49] = "shieldskirm",
142 [50] = "spiderskirm", 142 [50] = "spiderskirm",
143 [51] = "spidercrabe", 143 [51] = "spidercrabe",
144 [52] = "amphassault", 144 [52] = "amphassault",
145 [53] = "cloakarty", 145 [53] = "cloakarty",
146 [54] = "hoverriot", 146 [54] = "hoverriot",
147 [55] = "jumparty", 147 [55] = "jumparty",
148 [56] = "cloakjammer", 148 [56] = "cloakjammer",
149 [57] = "amphsupport", 149 [57] = "amphsupport",
150 [58] = "cloakskirm", 150 [58] = "cloakskirm",
151 [59] = "striderarty", 151 [59] = "striderarty",
152 [60] = "hoverheavyraid", 152 [60] = "hoverheavyraid",
153 [61] = "jumpraid", 153 [61] = "jumpraid",
154 [62] = "amphriot", 154 [62] = "amphriot",
155 [63] = "amphaa", 155 [63] = "amphaa",
156 [64] = "cloakassault", 156 [64] = "cloakassault",
157 [65] = "vehheavyarty", 157 [65] = "vehheavyarty",
158 [66] = "spiderantiheavy", 158 [66] = "spiderantiheavy",
159 [67] = "tankraid", 159 [67] = "tankraid",
160 [68] = "vehraid", 160 [68] = "vehraid",
161 [69] = "cloakriot", 161 [69] = "cloakriot",
162 [70] = "amphimpulse", 162 [70] = "amphimpulse",
163 [71] = "tankriot", 163 [71] = "tankriot",
164 [72] = "hoverskirm", 164 [72] = "hoverskirm",
165 [73] = "hoveraa", 165 [73] = "hoveraa",
166 }, 166 },
167 C = { 167 C = {
168 [1] = "vehsupport", 168 [1] = "vehsupport",
169 [2] = "amphsupport", 169 [2] = "amphsupport",
170 }, 170 },
171 D = { 171 D = {
172 [1] = "tankaa", 172 [1] = "tankaa",
173 [2] = "jumpaa", 173 [2] = "jumpaa",
174 [3] = "spideraa", 174 [3] = "spideraa",
175 [4] = "hoveraa", 175 [4] = "hoveraa",
176 [5] = "shieldaa", 176 [5] = "shieldaa",
177 [6] = "amphaa", 177 [6] = "amphaa",
178 [7] = "cloakaa", 178 [7] = "cloakaa",
179 [8] = "vehaa", 179 [8] = "vehaa",
180 }, 180 },
181 E = { 181 E = {
182 [1] = "cloakskirm", 182 [1] = "cloakskirm",
183 [2] = "amphfloater", 183 [2] = "amphfloater",
184 [3] = "spiderskirm", 184 [3] = "spiderskirm",
185 [4] = "jumpskirm", 185 [4] = "jumpskirm",
186 [5] = "hoverskirm", 186 [5] = "hoverskirm",
187 [6] = "shieldskirm", 187 [6] = "shieldskirm",
188 }, 188 },
189 F = { 189 F = {
190 [1] = "tankheavyassault", 190 [1] = "tankheavyassault",
191 [2] = "amphassault", 191 [2] = "amphassault",
192 [3] = "jumpsumo", 192 [3] = "jumpsumo",
193 [4] = "cloaksnipe", 193 [4] = "cloaksnipe",
194 [5] = "shieldfelon", 194 [5] = "shieldfelon",
195 [6] = "spidercrabe", 195 [6] = "spidercrabe",
196 }, 196 },
197 G = { 197 G = {
198 [1] = "spiderantiheavy", 198 [1] = "spiderantiheavy",
199 [2] = "hoverdepthcharge", 199 [2] = "hoverdepthcharge",
200 [3] = "amphbomb", 200 [3] = "amphbomb",
201 [4] = "shieldbomb", 201 [4] = "shieldbomb",
202 [5] = "jumpbomb", 202 [5] = "jumpbomb",
203 [6] = "cloakbomb", 203 [6] = "cloakbomb",
204 }, 204 },
205 H = { 205 H = {
206 [1] = "amphtele", 206 [1] = "amphtele",
207 [2] = "shieldshield", 207 [2] = "shieldshield",
208 [3] = "cloakjammer", 208 [3] = "cloakjammer",
209 }, 209 },
210 M = { 210 M = {
211 [1] = "athena", 211 [1] = "athena",
212 [2] = "shipcon", 212 [2] = "shipcon",
213 [3] = "shieldcon", 213 [3] = "shieldcon",
214 [4] = "jumpcon", 214 [4] = "jumpcon",
215 [5] = "gunshipcon", 215 [5] = "gunshipcon",
216 [6] = "planecon", 216 [6] = "planecon",
217 [7] = "hovercon", 217 [7] = "hovercon",
218 [8] = "amphcon", 218 [8] = "amphcon",
219 [9] = "tankcon", 219 [9] = "tankcon",
220 [10] = "cloakcon", 220 [10] = "cloakcon",
221 [11] = "vehcon", 221 [11] = "vehcon",
222 [12] = "spidercon", 222 [12] = "spidercon",
223 }, 223 },
224 N = { 224 N = {
225 [1] = "shiptorpraider", 225 [1] = "shiptorpraider",
226 [2] = "shipassault", 226 [2] = "shipassault",
227 [3] = "shipriot", 227 [3] = "shipriot",
228 [4] = "shipheavyarty", 228 [4] = "shipheavyarty",
229 [5] = "shipaa", 229 [5] = "shipaa",
230 [6] = "shipcarrier", 230 [6] = "shipcarrier",
231 [7] = "shiparty", 231 [7] = "shiparty",
232 [8] = "subraider", 232 [8] = "subraider",
233 [9] = "subtacmissile", 233 [9] = "subtacmissile",
234 [10] = "shipscout", 234 [10] = "shipscout",
235 [11] = "shipskirm", 235 [11] = "shipskirm",
236 }, 236 },
237 Q = { 237 Q = {
238 [1] = "spideremp", 238 [1] = "spideremp",
239 [2] = "hoverheavyraid", 239 [2] = "hoverheavyraid",
240 [3] = "tankheavyraid", 240 [3] = "tankheavyraid",
241 [4] = "amphimpulse", 241 [4] = "amphimpulse",
242 }, 242 },
243 R = { 243 R = {
244 [1] = "cloakriot", 244 [1] = "cloakriot",
245 [2] = "tankriot", 245 [2] = "tankriot",
246 [3] = "vehriot", 246 [3] = "vehriot",
247 [4] = "spiderriot", 247 [4] = "spiderriot",
248 [5] = "amphriot", 248 [5] = "amphriot",
249 [6] = "hoverriot", 249 [6] = "hoverriot",
250 [7] = "jumpblackhole", 250 [7] = "jumpblackhole",
251 [8] = "shieldriot", 251 [8] = "shieldriot",
252 }, 252 },
253 S = { 253 S = {
254 [1] = "jumpscout", 254 [1] = "jumpscout",
255 [2] = "vehscout", 255 [2] = "vehscout",
256 [3] = "spiderscout", 256 [3] = "spiderscout",
257 [4] = "shieldscout", 257 [4] = "shieldscout",
258 }, 258 },
259 T = { 259 T = {
260 [1] = "veharty", 260 [1] = "veharty",
261 [2] = "cloakarty", 261 [2] = "cloakarty",
262 [3] = "hoverarty", 262 [3] = "hoverarty",
263 [4] = "jumparty", 263 [4] = "jumparty",
264 [5] = "shieldarty", 264 [5] = "shieldarty",
265 [6] = "tankarty", 265 [6] = "tankarty",
266 }, 266 },
267 V = { 267 V = {
268 [1] = "bomberriot", 268 [1] = "bomberriot",
269 [2] = "planeheavyfighter", 269 [2] = "planeheavyfighter",
270 [3] = "gunshipheavyskirm", 270 [3] = "gunshipheavyskirm",
271 [4] = "dronecarry", 271 [4] = "dronecarry",
272 [5] = "gunshipemp", 272 [5] = "gunshipemp",
273 [6] = "planelightscout", 273 [6] = "planelightscout",
274 [7] = "bomberprec", 274 [7] = "bomberprec",
275 [8] = "gunshipskirm", 275 [8] = "gunshipskirm",
276 [9] = "planescout", 276 [9] = "planescout",
277 [10] = "bomberstrike", 277 [10] = "bomberstrike",
278 [11] = "bomberheavy", 278 [11] = "bomberheavy",
279 [12] = "bomberassault", 279 [12] = "bomberassault",
280 [13] = "gunshipraid", 280 [13] = "gunshipraid",
281 [14] = "gunshipassault", 281 [14] = "gunshipassault",
282 [15] = "gunshipkrow", 282 [15] = "gunshipkrow",
283 [16] = "gunshipbomb", 283 [16] = "gunshipbomb",
284 [17] = "gunshipaa", 284 [17] = "gunshipaa",
285 [18] = "bomberdisarm", 285 [18] = "bomberdisarm",
286 [19] = "planefighter", 286 [19] = "planefighter",
287 }, 287 },
288 W = { 288 W = {
289 [1] = "tankraid", 289 [1] = "tankraid",
290 [2] = "shieldraid", 290 [2] = "shieldraid",
291 [3] = "jumpraid", 291 [3] = "jumpraid",
292 [4] = "amphraid", 292 [4] = "amphraid",
293 [5] = "hoverraid", 293 [5] = "hoverraid",
294 [6] = "cloakraid", 294 [6] = "cloakraid",
295 [7] = "vehraid", 295 [7] = "vehraid",
296 }, 296 },
297 X = { 297 X = {
298 [1] = "cloakheavyraid", 298 [1] = "cloakheavyraid",
299 [2] = "amphlaunch", 299 [2] = "amphlaunch",
300 [3] = "vehcapture", 300 [3] = "vehcapture",
301 }, 301 },
302 Y = { 302 Y = {
303 [1] = "striderarty", 303 [1] = "striderarty",
304 [2] = "vehheavyarty", 304 [2] = "vehheavyarty",
305 [3] = "tankheavyarty", 305 [3] = "tankheavyarty",
306 }, 306 },
307 Z = { 307 Z = {
308 [1] = "striderbantha", 308 [1] = "striderbantha",
309 [2] = "striderdetriment", 309 [2] = "striderdetriment",
310 [3] = "striderdante", 310 [3] = "striderdante",
311 [4] = "striderscorpion", 311 [4] = "striderscorpion",
312 [5] = "striderantiheavy", 312 [5] = "striderantiheavy",
313 }, 313 },
314 }, 314 },
315 \n 315 \n
316 [/spoiler] 316 [/spoiler]
317 \n 317 \n
318 Full Widget Code: [spoiler] 318 Full Widget Code: [spoiler]
319 function widget:GetInfo() 319 function widget:GetInfo()
320 return { 320 return {
321 name = "Letter UnitType Multi Auto Groups", 321 name = "Letter UnitType Multi Auto Groups",
322 desc = "Assign multiple unit types to letter groups, select/add/filter units with modifiers, persistent across matches. Open Debug Panel to see results (f8). alt + Space + Letter - assign units. space + letter - select units. backspace + space + letter - clear group. shift + space + letter - add group to selection. Ctrl + space + letter - filter from current selection instead of globally.", 322 desc = "Assign multiple unit types to letter groups, select/add/filter units with modifiers, persistent across matches. Open Debug Panel to see results (f8). alt + Space + Letter - assign units. space + letter - select units. backspace + space + letter - clear group. shift + space + letter - add group to selection. Ctrl + space + letter - filter from current selection instead of globally.",
323 author = "FrequentPilgrim", 323 author = "FrequentPilgrim",
324 date = "2025-06-01", 324 date = "2025-06-01",
325 license = "GNU GPL v2", 325 license = "GNU GPL v2",
326 layer = 0, 326 layer = 0,
327 enabled = true 327 enabled = true
328 } 328 }
329 end 329 end
330 \n 330 \n
331 local assignedGroups = {} -- letter -> set of unitDefNames { [unitDefName] = true, ... } 331 local assignedGroups = {} -- letter -> set of unitDefNames { [unitDefName] = true, ... }
332 local keycodeToLetter = {} 332 local keycodeToLetter = {}
333 local backspaceKey = Spring.GetKeyCode("backspace") 333 local backspaceKey = Spring.GetKeyCode("backspace")
334 local backspaceDown = false 334 local backspaceDown = false
335 \n 335 \n
336 -- Fill keycodeToLetter for letters A-Z 336 -- Fill keycodeToLetter for letters A-Z
337 for i = 65, 90 do -- ASCII A-Z 337 for i = 65, 90 do -- ASCII A-Z
338 local ch = string.char(i) 338 local ch = string.char(i)
339 keycodeToLetter[Spring.GetKeyCode(ch:lower())] = ch 339 keycodeToLetter[Spring.GetKeyCode(ch:lower())] = ch
340 end 340 end
341 \n 341 \n
342 local function ShowMessage(msg) 342 local function ShowMessage(msg)
343 Spring.Echo("[LetterUnitTypeGroups] " .. msg) 343 Spring.Echo("[LetterUnitTypeGroups] " .. msg)
344 end 344 end
345 \n 345 \n
346 local function AssignLetterGroup(letter) 346 local function AssignLetterGroup(letter)
347 local selUnits = Spring.GetSelectedUnits() 347 local selUnits = Spring.GetSelectedUnits()
348 if #selUnits == 0 then 348 if #selUnits == 0 then
349 ShowMessage("No units selected to assign group " .. letter) 349 ShowMessage("No units selected to assign group " .. letter)
350 return 350 return
351 end 351 end
352 \n 352 \n
353 assignedGroups[letter] = assignedGroups[letter] or {} 353 assignedGroups[letter] = assignedGroups[letter] or {}
354 local addedCount = 0 354 local addedCount = 0
355 for _, unitID in ipairs(selUnits) do 355 for _, unitID in ipairs(selUnits) do
356 local udid = Spring.GetUnitDefID(unitID) 356 local udid = Spring.GetUnitDefID(unitID)
357 if udid then 357 if udid then
358 local defName = UnitDefs[udid].name 358 local defName = UnitDefs[udid].name
359 if defName and not assignedGroups[letter][defName] then 359 if defName and not assignedGroups[letter][defName] then
360 assignedGroups[letter][defName] = true 360 assignedGroups[letter][defName] = true
361 addedCount = addedCount + 1 361 addedCount = addedCount + 1
362 end 362 end
363 end 363 end
364 end 364 end
365 \n 365 \n
366 if addedCount > 0 then 366 if addedCount > 0 then
367 ShowMessage("Added " .. addedCount .. " unit types to group " .. letter) 367 ShowMessage("Added " .. addedCount .. " unit types to group " .. letter)
368 else 368 else
369 ShowMessage("No new unit types added to group " .. letter) 369 ShowMessage("No new unit types added to group " .. letter)
370 end 370 end
371 end 371 end
372 \n 372 \n
373 local function ClearLetterGroup(letter) 373 local function ClearLetterGroup(letter)
374 if assignedGroups[letter] then 374 if assignedGroups[letter] then
375 assignedGroups[letter] = nil 375 assignedGroups[letter] = nil
376 ShowMessage("Cleared group " .. letter) 376 ShowMessage("Cleared group " .. letter)
377 else 377 else
378 ShowMessage("Group " .. letter .. " is not assigned") 378 ShowMessage("Group " .. letter .. " is not assigned")
379 end 379 end
380 end 380 end
381 \n 381 \n
382 local function GetUnitsInGroup(letter) 382 local function GetUnitsInGroup(letter)
383 local defNameSet = assignedGroups[letter] 383 local defNameSet = assignedGroups[letter]
384 if not defNameSet then return {} end 384 if not defNameSet then return {} end
385 \n 385 \n
386 local myTeam = Spring.GetMyTeamID() 386 local myTeam = Spring.GetMyTeamID()
387 local units = Spring.GetTeamUnits(myTeam) 387 local units = Spring.GetTeamUnits(myTeam)
388 local toSelect = {} 388 local toSelect = {}
389 for _, unitID in ipairs(units) do 389 for _, unitID in ipairs(units) do
390 local udid = Spring.GetUnitDefID(unitID) 390 local udid = Spring.GetUnitDefID(unitID)
391 if udid then 391 if udid then
392 local defName = UnitDefs[udid].name 392 local defName = UnitDefs[udid].name
393 if defNameSet[defName] then 393 if defNameSet[defName] then
394 table.insert(toSelect, unitID) 394 table.insert(toSelect, unitID)
395 end 395 end
396 end 396 end
397 end 397 end
398 return toSelect 398 return toSelect
399 end 399 end
400 \n 400 \n
401 local function SelectLetterGroup(letter) 401 local function SelectLetterGroup(letter)
402 local toSelect = GetUnitsInGroup(letter) 402 local toSelect = GetUnitsInGroup(letter)
403 if #toSelect == 0 then 403 if #toSelect == 0 then
404 ShowMessage("No alive units of group " .. letter) 404 ShowMessage("No alive units of group " .. letter)
405 return 405 return
406 end 406 end
407 Spring.SelectUnitArray(toSelect, false) 407 Spring.SelectUnitArray(toSelect, false)
408 ShowMessage("Selected " .. #toSelect .. " units from group " .. letter) 408 ShowMessage("Selected " .. #toSelect .. " units from group " .. letter)
409 end 409 end
410 \n 410 \n
411 local function AddToSelection(letter) 411 local function AddToSelection(letter)
412 local toSelect = GetUnitsInGroup(letter) 412 local toSelect = GetUnitsInGroup(letter)
413 if #toSelect == 0 then 413 if #toSelect == 0 then
414 ShowMessage("No units to add from group " .. letter) 414 ShowMessage("No units to add from group " .. letter)
415 return 415 return
416 end 416 end
417 Spring.SelectUnitArray(toSelect, true) 417 Spring.SelectUnitArray(toSelect, true)
418 ShowMessage("Added " .. #toSelect .. " units from group " .. letter) 418 ShowMessage("Added " .. #toSelect .. " units from group " .. letter)
419 end 419 end
420 \n 420 \n
421 local function FilterSelection(letter) 421 local function FilterSelection(letter)
422 local current = Spring.GetSelectedUnits() 422 local current = Spring.GetSelectedUnits()
423 if #current == 0 then return end 423 if #current == 0 then return end
424 \n 424 \n
425 local defNameSet = assignedGroups[letter] 425 local defNameSet = assignedGroups[letter]
426 if not defNameSet then 426 if not defNameSet then
427 ShowMessage("Group " .. letter .. " not assigned") 427 ShowMessage("Group " .. letter .. " not assigned")
428 return 428 return
429 end 429 end
430 \n 430 \n
431 local filtered = {} 431 local filtered = {}
432 for _, unitID in ipairs(current) do 432 for _, unitID in ipairs(current) do
433 local udid = Spring.GetUnitDefID(unitID) 433 local udid = Spring.GetUnitDefID(unitID)
434 if udid then 434 if udid then
435 local defName = UnitDefs[udid].name 435 local defName = UnitDefs[udid].name
436 if defNameSet[defName] then 436 if defNameSet[defName] then
437 table.insert(filtered, unitID) 437 table.insert(filtered, unitID)
438 end 438 end
439 end 439 end
440 end 440 end
441 \n 441 \n
442 Spring.SelectUnitArray(filtered, false) 442 Spring.SelectUnitArray(filtered, false)
443 ShowMessage("Filtered selection to " .. #filtered .. " units in group " .. letter) 443 ShowMessage("Filtered selection to " .. #filtered .. " units in group " .. letter)
444 end 444 end
445 \n 445 \n
446 function widget:KeyPress(key, mods, isRepeat) 446 function widget:KeyPress(key, mods, isRepeat)
447 if key == backspaceKey then 447 if key == backspaceKey then
448 backspaceDown = true 448 backspaceDown = true
449 return false 449 return false
450 end 450 end
451 \n 451 \n
452 local letter = keycodeToLetter[key] 452 local letter = keycodeToLetter[key]
453 if not letter or not mods.meta then return false end 453 if not letter or not mods.meta then return false end
454 \n 454 \n
455 if backspaceDown then 455 if backspaceDown then
456 ClearLetterGroup(letter) 456 ClearLetterGroup(letter)
457 return true 457 return true
458 elseif mods.alt then 458 elseif mods.alt then
459 AssignLetterGroup(letter) 459 AssignLetterGroup(letter)
460 return true 460 return true
461 elseif mods.shift then 461 elseif mods.shift then
462 AddToSelection(letter) 462 AddToSelection(letter)
463 return true 463 return true
464 elseif mods.ctrl then 464 elseif mods.ctrl then
465 FilterSelection(letter) 465 FilterSelection(letter)
466 return true 466 return true
467 else 467 else
468 SelectLetterGroup(letter) 468 SelectLetterGroup(letter)
469 return true 469 return true
470 end 470 end
471 end 471 end
472 \n 472 \n
473 function widget:KeyRelease(key) 473 function widget:KeyRelease(key)
474 if key == backspaceKey then 474 if key == backspaceKey then
475 backspaceDown = false 475 backspaceDown = false
476 end 476 end
477 end 477 end
478 \n 478 \n
479 function widget:GetConfigData() 479 function widget:GetConfigData()
480 local saved = {} 480 local saved = {}
481 for letter, defSet in pairs(assignedGroups) do 481 for letter, defSet in pairs(assignedGroups) do
482 saved[letter] = {} 482 saved[letter] = {}
483 for defName in pairs(defSet) do 483 for defName in pairs(defSet) do
484 table.insert(saved[letter], defName) 484 table.insert(saved[letter], defName)
485 end 485 end
486 end 486 end
487 return saved 487 return saved
488 end 488 end
489 \n 489 \n
490 function widget:SetConfigData(data) 490 function widget:SetConfigData(data)
491 if type(data) == "table" then 491 if type(data) == "table" then
492 assignedGroups = {} 492 assignedGroups = {}
493 for letter, defList in pairs(data) do 493 for letter, defList in pairs(data) do
494 assignedGroups[letter] = {} 494 assignedGroups[letter] = {}
495 for _, defName in ipairs(defList) do 495 for _, defName in ipairs(defList) do
496 assignedGroups[letter][defName] = true 496 assignedGroups[letter][defName] = true
497 end 497 end
498 end 498 end
499 Spring.Echo("[LetterUnitTypeGroups] Loaded saved groups") 499 Spring.Echo("[LetterUnitTypeGroups] Loaded saved groups")
500 end 500 end
501 end 501 end
502 [/spoiler] 502 [/spoiler]