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]
|