View difference between Paste ID: Vty3vhnY and MQvSDt1F
SHOW: | | - or go back to the newest paste.
1
local version = "1.0" -- String declaration. We can do this before the GetInfo callin (event).
2
function widget:GetInfo()
3
    return {
4
      name      = "Ez Selector " .. version, -- .. means to combine two strings. The second string, 'version' (see above) is added to the end of this string.
5
      desc      = "Selects units when a user presses a certain key.",
6
      author    = "_Shaman",
7
      date      = "May 19, 2016",
8
      license   = "None",
9
      layer     = 15,
10
      enabled   = true,
11
    }
12
  end -- All widgets/gadgets need this to run. You can declare variables before it though. This tells the engine this is a widget.
13
  
14
  --config--
15
local debug = false
16
local color = {raider = {0.25,0.41,1},
17
                assault = {0.86,0.08,0.24},
18
                skirm = {0.25,0.55,0.13},
19
                arty = {0.8,0.68,0},
20
                riot = {0,0.81,0.82},
21
                none = {1,1,1},
22
                growth = {0.19,0.5,0.08},
23
                shrink = {1,0.08,0.58},} -- OpenGL uses floating points instead of 255 (float = decimal num)
24
local keypresses = {raider = 113,
25
                    assault = 97,
26
                    skirm = 116,
27
                    arty = 120,
28
                    riot = 122,
29
                    plus = 91, -- increased radius.
30
                    minus = 93, -- decrease radius. Change these as desired.
31
                    } -- Table. Format is Key = Value. 113.115.100.102.103
32
33
local triggerkeys = {}
34
triggerkeys[keypresses.raider] = 1
35
triggerkeys[keypresses.assault] = 1
36
triggerkeys[keypresses.skirm] = 1
37
triggerkeys[keypresses.arty] = 1
38
triggerkeys[keypresses.riot] = 1
39
local rad = 150
40
local on = false
41
local ontype = "none" -- we'll use ontype and on to talk to gameframe and drawworld.
42
local unittypes = {raider = {
43
                    armpw = 1,
44
                    corak = 1,
45
                    corgator = 1,
46
                    amphraider3 = 1,
47
                    corpyro = 1,
48
                    corsh = 1,
49
                    subraider = 1,
50
                    armpw = 1,
51
                    },
52
                   assault = {
53
                    armzeus = 1,
54
                    armorco = 1,
55
                    spiderassault = 1,
56
                    corgol = 1,
57
                    correap = 1,
58
                    shipraider = 1,
59
                    amphassault = 1,
60
                    corraid = 1,
61
                    corthud = 1,
62
                    corcan = 1,
63
                    hoverassault = 1,
64
                    funnelweb = 1,
65
                   },
66
                   skirm = {
67
                    armrock = 1,
68
                    armsptk = 1,
69
                    slowmort = 1,
70
                    corstorm = 1,
71
                    shipskirm = 1,
72
                    amphfloater = 1,
73
                    cormist = 1,
74
                   },
75
                   arty = {
76
                    armham = 1,
77
                    armraven = 1,
78
                    armsnipe = 1,
79
                    shieldarty = 1,
80
                    firewalker = 1,
81
                    corgarp = 1,
82
                    armmerl = 1,
83
                    cormart = 1,
84
                    trem = 1,
85
                    armcrabe = 1,
86
                    subarty = 1,
87
                    shiparty = 1,
88
                    corbats = 1,
89
                    reef = 1,
90
                    armmanni = 1,
91
                   },
92
                   riot = {
93
                    armwar = 1,
94
                    cormak = 1,
95
                    spiderriot = 1,
96
                    arm_venom = 1,
97
                    jumpblackhole = 1,
98
                    corsumo = 1,
99
                    corlevlr = 1,
100
                    tawf114 = 1,
101
                    amphriot = 1,
102
                    amphraider2 = 1,
103
                    shiptorp = 1,
104
                    dante = 1,
105
                    hoverriot = 1,
106
                   }
107
                  }
108
109
local selection = {}
110
local selected = {}
111
local checked = {}
112
local radchanged = false
113
local originalrad = rad
114
local radchangeddrawtime = 0
115
local lastrelease = -1
116
117
function widget:KeyPress(key, mods, isRepeat) -- This callin is triggered whenever the user presses a key.
118
  if key == keypresses.plus then
119
    if radchanged == false then
120
      originalrad = rad
121
    end
122
    rad = rad+10
123
    radchanged = true
124
    radchangeddrawtime = 12
125
  end
126
  if key == keypresses.minus and rad > 10 then
127
    rad = rad-10
128
    radchanged = true
129
    radchangeddrawtime = 12
130
  end
131
  if isRepeat == false and debug then
132
    Spring.Echo("game_message: key: " .. key)
133
  end
134
  if key == keypresses.raider and isRepeat and ontype == "none" then --Here keypresses.raider is the same as keypresses["raider"]. This is how you look up values in a table.
135
    on = true -- we're using this variable to talk to KeyRelease and DrawWorld. This way then they know we're working on getting a selection going.
136
    ontype = "raider"
137
  end
138
  if key == keypresses.skirm and isRepeat and ontype == "none" then
139
    on = true
140
    ontype = "skirm"
141
  end
142
  if key == keypresses.assault and isRepeat and ontype == "none" then
143
    on = true
144
    ontype = "assault"
145
  end
146
  if key == keypresses.arty and isRepeat and ontype == "none" then
147
    on = true
148
    ontype = "arty"
149
  end
150
  if key == keypresses.riot and isRepeat and ontype == "none" then
151
    on = true
152
    ontype = "riot"
153
  end
154
end
155
156
function widget:GameFrame(f) -- called once every frame. This is so we don't keep looking for units every keypress.
157
  if radchanged and radchangeddrawtime > 0 then
158
    radchangeddrawtime = radchangeddrawtime - 1
159
    if radchangeddrawtime == 0 then
160
      radchanged = false
161
    end
162
  end
163
  if f%2 == 0 then -- % means the remainers left after divided by the second number. here it's framenum divided by 2. So this happens every 2nd frame.
164
  if on and ontype ~= "none" then
165
    local x,y = Spring.GetMouseState()
166
    local _,pos = Spring.TraceScreenRay(x,y,true)
167
    if type(pos) == "table" then -- prevent crashing from attempting to index a number value. The above seems to give random numbers sometimes.
168
      x = pos[1];y = pos[3];pos = nil -- ; is effectively a new line in LUA. This just makes your code look nicer.
169
    else
170
      if Spring.ValidUnitID(pos) then
171
        x,_,y = Spring.GetUnitPosition(pos)
172
      elseif Spring.ValidFeatureID(pos) then
173
        x,_,y = Spring.GetFeaturePosition(pos)
174
      end
175
    end
176
    if x ~= nil and y ~= nil then
177
      for _,id in pairs(Spring.GetUnitsInCylinder(x,y,rad,Spring.GetMyTeamID())) do -- Here we're skipping the creation of the table altogether in favor of just plugging in the results of 'getunitsincylinder'
178
        if checked[id] == nil and unittypes[ontype][UnitDefs[Spring.GetUnitDefID(id)].name] and not selected[id] then -- Here we're using LUA's if true or exists logic. This says 'if this unit's unitdefid exists as a value in this table AND it's not a key in selected, then do this. This means units must match on the table and be a unique unit
179
          if debug then Spring.Echo("game_message: Selected " .. id) end
180
          selection[#selection+1] = id
181
          selected[id] = id
182
        end
183
        checked[id] = 1
184
      end
185
    end
186
  end
187
end
188
end
189
190
function widget:KeyRelease(key) -- Called whenever user stops pressing a key.
191
  if triggerkeys[key] and on then
192
    on = false
193
    ontype = "none"
194
    Spring.SelectUnitArray(selection,false)
195
    selection = {} -- clear the table.
196
    selected = {}
197
    checked = {}
198
  end
199
end
200
201
function widget:DrawWorld() -- this is used for openGL stuff.
202
  if on or radchanged then
203
    local x,y = Spring.GetMouseState()
204
    local _,pos = Spring.TraceScreenRay(x,y,true)
205
    x,y = nil
206
    if type(pos) == "number" then -- prevent crashing from attempting to index a number value. The above seems to give random numbers sometimes.
207
      if Spring.ValidUnitID(pos) then
208
        local id = pos
209
        pos = {}
210
        pos[1],pos[2],pos[3] = Spring.GetUnitPosition(id)
211
        id = nil
212
      elseif Spring.ValidFeatureID(pos) then
213
        local id = pos
214
        pos = {}
215
        pos[1],pos[2],pos[3] = Spring.GetFeaturePosition(id)
216
      end
217
    end
218
    if on then
219
      if type(pos) == "table" and pos[1] ~= nil and pos[2] ~= nil then
220
        gl.PushMatrix() --This is the start of an openGL function.
221
        gl.LineStipple(true)
222
        gl.LineWidth(3.0)
223
        gl.Color(color[ontype][1],color[ontype][2],color[ontype][3],1)
224
        gl.DrawGroundCircle(pos[1], pos[2], pos[3], rad, 40) -- draws a simple circle.
225
        gl.Translate(pos[1],pos[2],pos[3])
226
        gl.Billboard()
227
        gl.Text("Selecting " .. ontype,-25,-25,12,"v") -- Displays text. First value is the string, second is a modifier for x (in this case it's x-25), third is a modifier for y, fourth is the size, then last is a modifier for the text itself. "v" means vertical align.
228
        gl.Color(1,1,1,1) -- we have to reset what we did here.
229
        gl.LineWidth(1.0)
230
        gl.LineStipple(false)
231
        gl.PopMatrix() -- end of function. Have to use this with after a push!
232
      end
233
    end
234
  if radchanged and not on and type(pos) == "table" and originalrad then
235
    gl.PushMatrix()
236
    gl.LineWidth(3.0)
237
    gl.Color(1,1,1,1)
238
    gl.DrawGroundCircle(pos[1],pos[2],pos[3],originalrad,40)
239
    if rad > originalrad then
240
      gl.Color(color["growth"][1],color["growth"][2],color["growth"][3],1)
241
    else
242
      if rad < originalrad then
243
        gl.Color(color["shrink"][1],color["shrink"][2],color["shrink"][3],1)
244
      else
245
        gl.Color(1,1,1,1)
246
      end
247
    end
248
    gl.LineStipple(true)
249
    gl.DrawGroundCircle(pos[1],pos[2],pos[3],rad,40)
250
    gl.LineStipple(false)
251
    gl.Translate(pos[1],pos[2],pos[3])
252
    gl.Billboard()
253
    gl.Text("New Radius: " .. rad .. "(Was: " .. originalrad .. ", change:" .. rad-originalrad .. ")",-100,-25,12,"v")
254
    gl.LineWidth(1.0)
255
    gl.Color(1,1,1,1)
256
    gl.PopMatrix()
257
  end
258
  pos = nil
259
end
260
if #selection > 0 then -- Draw circles around selected units. #tablename is the length of the ordered table (or last consecutive value)
261
  local pos = {}
262
    for i=1,#selection do -- do this for every entry in the ordered table. i is the incremental value. i=1 means that the first value is 1. i increases by 1 (or a third value if provided eg 1,5,0.25 would do 1 + 0.25 every execution) with every execution and will continue until i == #selection. i=1,#table is very useful for doing things to every entry in an ordered table.
263
      if Spring.ValidUnitID(selection[i]) then
264
        pos[1],pos[2],pos[3] = Spring.GetUnitPosition(selection[i])
265
        gl.PushMatrix()
266
        gl.LineWidth(3.0)
267
        gl.Color(color[ontype][1],color[ontype][2],color[ontype][3],1)
268
        gl.DrawGroundCircle(pos[1],pos[2],pos[3],40,40)
269
        gl.Color(1,1,1,1)
270
        gl.PopMatrix()
271
      end
272
    end
273
  end
274
end