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 |