Advertisement
Guest User

Untitled

a guest
Mar 30th, 2014
151
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 18.28 KB | None | 0 0
  1.  
  2. function widget:GetInfo()
  3. return {
  4. name = "Initial Queue - XTA",
  5. desc = "Allows you to queue buildings before game start",
  6. author = "Niobium", -- Modified for XTA by Deadnight Warrior. Made compatible with side changes by Jools. new animdef for zk by knorke
  7. version = "1.4 zk v1",
  8. date = "2 June 2012, zk Feb 2014",
  9. license = "GNU GPL, v2 or later",
  10. layer = -1, -- Puts it above minimap_startboxes with layer 0
  11. enabled = true,
  12. handler = true
  13. }
  14. end
  15.  
  16. ------------------------------------------------------------
  17. -- Config
  18. ------------------------------------------------------------
  19. -- Panel
  20. local iconSize = 40
  21. local borderSize = 1
  22. local maxCols = 5
  23. local fontSize = 16
  24.  
  25. -- Colors
  26. local buildDistanceColor = {0.3, 1.0, 0.3, 0.7}
  27. local buildLinesColor = {0.3, 1.0, 0.3, 0.7}
  28. local borderNormalColor = {0.3, 1.0, 0.3, 0.5}
  29. local borderClashColor = {0.7, 0.3, 0.3, 1.0}
  30. local borderValidColor = {0.0, 1.0, 0.0, 1.0}
  31. local borderInvalidColor = {1.0, 0.0, 0.0, 1.0}
  32. local buildingQueuedAlpha = 0.5
  33.  
  34. local metalColor = '\255\196\196\255' -- Light blue
  35. local energyColor = '\255\255\255\128' -- Light yellow
  36. local buildColor = '\255\128\255\128' -- Light green
  37. local whiteColor = '\255\255\255\255' -- White
  38.  
  39. ------------------------------------------------------------
  40. -- Globals
  41. ------------------------------------------------------------
  42. local sDefID = UnitDefNames["corned"].id -- Starting unit def ID
  43. local sDef -- UnitDefs[sDefID]
  44. local myTeamID = Spring.GetMyTeamID()
  45.  
  46. local selDefID = nil -- Currently selected def ID
  47. local buildQueue = {}
  48. local buildNameToID = {}
  49.  
  50. local wl, wt = 500, 500
  51. local cellRows = {} -- {{bDefID, bDefID, ...}, ...}
  52. local panelList = nil -- Display list for panel
  53. local areDragging = false
  54.  
  55. local isMex = {} -- isMex[uDefID] = true / nil
  56. local weaponRange = {} -- weaponRange[uDefID] = # / nil
  57. local spGetTeamRulesParam = Spring.GetTeamRulesParam
  58.  
  59. -- Maps units that could get disabled because of map conditions
  60. local disablable = {}
  61.  
  62. local modOptions = Spring.GetModOptions()
  63.  
  64.  
  65. ------------------------------------------------------------
  66. -- Local functions
  67. ------------------------------------------------------------
  68. local function TraceDefID(mx, my)
  69. local overRow = cellRows[1 + math.floor((wt - my) / (iconSize + borderSize))]
  70. if not overRow then return nil end
  71. return overRow[1 + math.floor((mx - wl) / (iconSize + borderSize))]
  72. end
  73. local function GetBuildingDimensions(uDefID, facing)
  74. local bDef = UnitDefs[uDefID]
  75. if (facing % 2 == 1) then
  76. return 4 * bDef.zsize, 4 * bDef.xsize
  77. else
  78. return 4 * bDef.xsize, 4 * bDef.zsize
  79. end
  80. end
  81. local function DrawBuilding(buildData, borderColor, buildingAlpha, drawRanges)
  82.  
  83. local bDefID, bx, by, bz, facing = buildData[1], buildData[2], buildData[3], buildData[4], buildData[5]
  84. local bw, bh = GetBuildingDimensions(bDefID, facing)
  85.  
  86. gl.DepthTest(false)
  87. gl.Color(borderColor)
  88.  
  89. gl.Shape(GL.LINE_LOOP, {{v={bx - bw, by, bz - bh}},
  90. {v={bx + bw, by, bz - bh}},
  91. {v={bx + bw, by, bz + bh}},
  92. {v={bx - bw, by, bz + bh}}})
  93.  
  94. if drawRanges then
  95.  
  96. if isMex[bDefID] then
  97. gl.Color(1.0, 0.3, 0.3, 0.7)
  98. gl.DrawGroundCircle(bx, by, bz, Game.extractorRadius, 40)
  99. end
  100.  
  101. local wRange = weaponRange[bDefID]
  102. if wRange then
  103. gl.Color(1.0, 0.3, 0.3, 0.7)
  104. gl.DrawGroundCircle(bx, by, bz, wRange, 40)
  105. end
  106. end
  107.  
  108. gl.DepthTest(GL.LEQUAL)
  109. gl.DepthMask(true)
  110. if buildingAlpha == 1 then gl.Lighting(true) end
  111. gl.Color(1.0, 1.0, 1.0, buildingAlpha)
  112.  
  113. gl.PushMatrix()
  114. gl.Translate(bx, by, bz)
  115. gl.Rotate(90 * facing, 0, 1, 0)
  116. gl.UnitShape(bDefID, Spring.GetMyTeamID())
  117. gl.PopMatrix()
  118.  
  119. gl.Lighting(false)
  120. gl.DepthTest(false)
  121. gl.DepthMask(false)
  122. end
  123. local function DrawUnitDef(uDefID, uTeam, ux, uy, uz)
  124.  
  125. gl.Color(1.0, 1.0, 1.0, 1.0)
  126. gl.DepthTest(GL.LEQUAL)
  127. gl.DepthMask(true)
  128. gl.Lighting(true)
  129.  
  130. gl.PushMatrix()
  131. gl.Translate(ux, uy, uz)
  132. gl.UnitShape(uDefID, uTeam)
  133. gl.PopMatrix()
  134.  
  135. gl.Lighting(false)
  136. gl.DepthTest(false)
  137. gl.DepthMask(false)
  138. end
  139. local function DoBuildingsClash(buildData1, buildData2)
  140.  
  141. local w1, h1 = GetBuildingDimensions(buildData1[1], buildData1[5])
  142. local w2, h2 = GetBuildingDimensions(buildData2[1], buildData2[5])
  143.  
  144. return math.abs(buildData1[2] - buildData2[2]) < w1 + w2 and
  145. math.abs(buildData1[4] - buildData2[4]) < h1 + h2
  146. end
  147. local function SetSelDefID(defID)
  148.  
  149. selDefID = defID
  150.  
  151. if (isMex[selDefID] ~= nil) ~= (Spring.GetMapDrawMode() == "metal") then
  152. Spring.SendCommands("ShowMetalMap")
  153. end
  154. end
  155. local function GetUnitCanCompleteQueue(uID)
  156.  
  157. local uDefID = Spring.GetUnitDefID(uID)
  158. if uDefID == sDefID then
  159. return true
  160. end
  161.  
  162. -- What can this unit build ?
  163. local uCanBuild = {}
  164. local uBuilds = UnitDefs[uDefID].buildOptions
  165. for i = 1, #uBuilds do
  166. uCanBuild[uBuilds[i]] = true
  167. end
  168.  
  169. -- Can it build everything that was queued ?
  170. for i = 1, #buildQueue do
  171. if not uCanBuild[buildQueue[i][1]] then
  172. return false
  173. end
  174. end
  175.  
  176. return true
  177. end
  178. local function GetQueueBuildTime()
  179. local t = 0
  180. for i = 1, #buildQueue do
  181. t = t + UnitDefs[buildQueue[i][1]].buildTime
  182. end
  183. return t / sDef.buildSpeed
  184. end
  185. local function GetQueueCosts()
  186. local mCost = 0
  187. local eCost = 0
  188. local bCost = 0
  189. for i = 1, #buildQueue do
  190. local uDef = UnitDefs[buildQueue[i][1]]
  191. mCost = mCost + uDef.metalCost
  192. eCost = eCost + uDef.energyCost
  193. bCost = bCost + uDef.buildTime
  194. end
  195. return mCost, eCost, bCost
  196. end
  197.  
  198. ------------------------------------------------------------
  199. -- Initialize/shutdown
  200. ------------------------------------------------------------
  201. function widget:Initialize()
  202.  
  203. if (Game.startPosType == 1) or -- Don't run if start positions are random
  204. (Game.startPosType == 0) or -- Don't run if start positions are fixed or n/a
  205. (Spring.GetGameFrame() > 0) or -- Don't run if game has already started
  206. (Spring.GetSpectatingState()) then -- Don't run if we are a spec
  207. Spring.Echo ("i should be turned off")
  208. -- widgetHandler:RemoveWidget(self)
  209. --return
  210. end
  211.  
  212. local modOptions = Spring.GetModOptions()
  213. if modOptions.mission then -- Don't run on missions; screen will be in the way.
  214. Spring.Echo ("i should be turned off")
  215.  
  216. --widgetHandler:RemoveWidget(self)
  217. --return
  218. end
  219.  
  220. --Determine if certain units got disabled
  221. local disableWind = Game.windMax < 9.1
  222. if disableWind then
  223. disablable["arm_wind_generator"] = true
  224. disablable["core_wind_generator"] = true
  225. end
  226. if not modOptions.space_mode or (modOptions.space_mode and modOptions.space_mode=="0") then
  227. local map = Game.mapHumanName:lower()
  228. local disableAir = Game.windMin <= 1 and Game.windMax <= 4 or map:find("comet") or map:find("moon")
  229. local disableHovers = disableAir
  230. disableAir = disableAir or Game.windMin >= 30 or Game.windMax >= 35
  231. if disableAir then
  232. disablable["arm_aircraft_plant"] = true
  233. disablable["arm_adv_aircraft_plant"] = true
  234. disablable["arm_seaplane_platform"] = true
  235. disablable["core_aircraft_plant"] = true
  236. disablable["core_adv_aircraft_plant"] = true
  237. disablable["core_seaplane_platform"] = true
  238. end
  239. if disableHovers then
  240. disablable["arm_hovercraft_platform"] = true
  241. disablable["core_hovercraft_platform"] = true
  242. end
  243. end
  244. -- Get our starting unit
  245. -- Sometimes the information is not available, so the widget will error and exit :)
  246. local _, _, _, _, mySide = Spring.GetTeamInfo(myTeamID)
  247. local startUnitName = "corned" --Spring.GetSideData(mySide)
  248. sDefID = UnitDefNames[startUnitName].id
  249. local startID = UnitDefNames[startUnitName].id --spGetTeamRulesParam(myTeamID, 'startUnit')
  250. if startID and startID ~= "" then sDefID = startID end
  251. InitializeFaction(sDefID)
  252.  
  253. end
  254.  
  255. function widget:Shutdown()
  256. if panelList then
  257. gl.DeleteList(panelList)
  258. end
  259. end
  260.  
  261. function InitializeFaction(sDefID)
  262. Spring.Echo ("InitializeFaction(sDefID)")
  263. sDef = UnitDefs[sDefID]
  264. -- Don't run if theres nothing to show
  265. local sBuilds = sDef.buildOptions
  266. Spring.Echo ("#sBuilds=", #sBuilds)
  267. if not sBuilds or (#sBuilds == 0) then
  268. Spring.Echo ("sBuilds or (#sBuilds == 0)")
  269. --widgetHandler:RemoveWidget(self)
  270. return
  271. end
  272. -- Retain the build list order, but move all sea units to the end
  273. local waterBuilds = {}
  274. local newBuilds = {}
  275. for i = 1, #sBuilds do
  276. --Spring.Echo (sBuilds[i])
  277. local uDefID = sBuilds[i]
  278. local uDef = UnitDefs[uDefID]
  279. if not disablable[uDef.name] then
  280. buildNameToID[uDef.name] = uDefID
  281. if uDef.minWaterDepth <= 0 then
  282. newBuilds[#newBuilds + 1] = uDefID
  283. else
  284. waterBuilds[#waterBuilds + 1] = uDefID
  285. end
  286. end
  287. end
  288. for i = 1, #waterBuilds do
  289. newBuilds[#newBuilds + 1] = waterBuilds[i]
  290. end
  291. sBuilds = newBuilds
  292.  
  293.  
  294. -- Set up cells
  295. local numCols = math.min(#sBuilds, maxCols)
  296. local numRows = math.ceil(#sBuilds / numCols)
  297. for r = 1, numRows do
  298. cellRows[r] = {}
  299. end
  300. for b = 0, #sBuilds - 1 do
  301. cellRows[1 + math.floor(b / numCols)][1 + b % numCols] = sBuilds[b + 1]
  302. end
  303.  
  304. -- Set up drawing function
  305. local drawFunc = function()
  306.  
  307. gl.PushMatrix()
  308. gl.Translate(0, borderSize, 0)
  309.  
  310. for r = 1, #cellRows do
  311. local cellRow = cellRows[r]
  312.  
  313. gl.Translate(0, -iconSize - borderSize, 0)
  314. gl.PushMatrix()
  315.  
  316. for c = 1, #cellRow do
  317.  
  318. gl.Color(0, 0, 0, 1)
  319. gl.Rect(-borderSize, -borderSize, iconSize + borderSize, iconSize + borderSize)
  320.  
  321. gl.Color(1, 1, 1, 1)
  322. gl.Texture("#" .. cellRow[c])
  323. gl.TexRect(0, 0, iconSize, iconSize)
  324. gl.Texture(false)
  325.  
  326. gl.Translate(iconSize + borderSize, 0, 0)
  327. end
  328. gl.PopMatrix()
  329. end
  330.  
  331. gl.PopMatrix()
  332. end
  333.  
  334. -- delete any pre-existing displaylist
  335. if panelList then
  336. gl.DeleteList(panelList)
  337. end
  338.  
  339. panelList = gl.CreateList(drawFunc)
  340.  
  341. for uDefID, uDef in pairs(UnitDefs) do
  342.  
  343. if uDef.extractsMetal > 0 then
  344. isMex[uDefID] = true
  345. end
  346.  
  347. if uDef.maxWeaponRange > 16 then
  348. weaponRange[uDefID] = uDef.maxWeaponRange
  349. end
  350. end
  351. end
  352.  
  353.  
  354.  
  355. ------------------------------------------------------------
  356. -- Config
  357. ------------------------------------------------------------
  358. --FIXME: fuck configs
  359. --[[
  360. function widget:GetConfigData()
  361. local wWidth, wHeight = Spring.GetWindowGeometry()
  362. return {wl / wWidth, wt / wHeight}
  363. end
  364. function widget:SetConfigData(data)
  365. local wWidth, wHeight = Spring.GetWindowGeometry()
  366. wl = math.floor(wWidth * (data[1] or 0.25))
  367. wt = math.floor(wHeight * (data[2] or 0.50))
  368. end
  369. --]]
  370. ------------------------------------------------------------
  371. -- Drawing
  372. ------------------------------------------------------------
  373. --local queueTimeFormat = whiteColor .. 'Queued: ' .. buildColor .. '%.1f sec ' .. whiteColor .. '[' .. metalColor .. '%d m' .. whiteColor .. ', ' .. energyColor .. '%d e' .. whiteColor .. ']'
  374. local queueTimeFormat = whiteColor .. 'Queued ' .. metalColor .. '%dm ' .. energyColor .. '%de ' .. buildColor .. '%.1f sec'
  375. --local queueTimeFormat = metalColor .. '%dm ' .. whiteColor .. '/ ' .. energyColor .. '%de ' .. whiteColor .. '/ ' .. buildColor .. '%.1f sec'
  376.  
  377.  
  378. -- "Queued 23.9 seconds (820m / 2012e)" (I think this one is the best. Time first emphasises point and goodness of widget)
  379. -- Also, it is written like english and reads well, none of this colon stuff or figures stacked together
  380.  
  381.  
  382.  
  383. function widget:DrawScreen()
  384. gl.PushMatrix()
  385. gl.Translate(wl, wt, 0)
  386. gl.CallList(panelList)
  387. if #buildQueue > 0 then
  388. local mCost, eCost, bCost = GetQueueCosts()
  389. gl.Text(string.format(queueTimeFormat, mCost, eCost, bCost / sDef.buildSpeed), 0, 0, fontSize, 'do')
  390. end
  391. gl.PopMatrix()
  392. end
  393. function widget:DrawWorld()
  394.  
  395. -- Set up gl
  396. gl.LineWidth(1.49)
  397.  
  398. -- We need data about currently selected building, for drawing clashes etc
  399. local selBuildData
  400. if selDefID then
  401. local mx, my = Spring.GetMouseState()
  402. local _, pos = Spring.TraceScreenRay(mx, my, true)
  403. if pos then
  404. local bx, by, bz = Spring.Pos2BuildPos(selDefID, pos[1], pos[2], pos[3])
  405. local buildFacing = Spring.GetBuildFacing()
  406. selBuildData = {selDefID, bx, by, bz, buildFacing}
  407. end
  408. end
  409.  
  410. local sx, sy, sz = Spring.GetTeamStartPosition(myTeamID) -- Returns -100, -100, -100 when none chosen
  411. local startChosen = (sx ~= -100)
  412. if startChosen then
  413.  
  414. -- Correction for start positions in the air
  415. sy = Spring.GetGroundHeight(sx, sz)
  416.  
  417. -- Draw the starting unit at start position
  418. DrawUnitDef(sDefID, myTeamID, sx, sy, sz)
  419.  
  420. -- Draw start units build radius
  421. gl.Color(buildDistanceColor)
  422. gl.DrawGroundCircle(sx, sy, sz, 400, 40) --FIXME: use real build radius
  423. end
  424.  
  425. -- Draw all the buildings
  426. local queueLineVerts = startChosen and {{v={sx, sy, sz}}} or {}
  427. for b = 1, #buildQueue do
  428. local buildData = buildQueue[b]
  429.  
  430. if selBuildData and DoBuildingsClash(selBuildData, buildData) then
  431. DrawBuilding(buildData, borderClashColor, buildingQueuedAlpha)
  432. else
  433. DrawBuilding(buildData, borderNormalColor, buildingQueuedAlpha)
  434. end
  435.  
  436. queueLineVerts[#queueLineVerts + 1] = {v={buildData[2], buildData[3], buildData[4]}}
  437. end
  438.  
  439. -- Draw queue lines
  440. gl.Color(buildLinesColor)
  441. gl.LineStipple("springdefault")
  442. gl.Shape(GL.LINE_STRIP, queueLineVerts)
  443. gl.LineStipple(false)
  444.  
  445. -- Draw selected building
  446. if selBuildData then
  447. if Spring.TestBuildOrder(selDefID, selBuildData[2], selBuildData[3], selBuildData[4], selBuildData[5]) ~= 0 then
  448. DrawBuilding(selBuildData, borderValidColor, 1.0, true)
  449. else
  450. DrawBuilding(selBuildData, borderInvalidColor, 1.0, true)
  451. end
  452. end
  453.  
  454. -- Reset gl
  455. gl.Color(1.0, 1.0, 1.0, 1.0)
  456. gl.LineWidth(1.0)
  457. end
  458.  
  459. ------------------------------------------------------------
  460. -- Game start
  461. ------------------------------------------------------------
  462. function widget:GameFrame(n)
  463. --[[
  464. -- Don't run if we are a spec
  465. local areSpec = Spring.GetSpectatingState()
  466. if areSpec then
  467. --widgetHandler:RemoveWidget(self)
  468. Spring.Echo ("nonono")
  469. return
  470. end
  471.  
  472. -- Don't run if we didn't queue anything
  473. if (#buildQueue == 0) then
  474. Spring.Echo ("nonono")
  475. --widgetHandler:RemoveWidget(self)
  476. return
  477. end
  478. --]]
  479. if (n < 2) then return end -- Give the unit frames 0 and 1 to spawn
  480. if (n > 10) then
  481. --Spring.Echo("> Starting unit never spawned !")
  482. widgetHandler:RemoveWidget(self)
  483. Spring.Echo ("game has started, byebye")
  484. return
  485. end
  486.  
  487. -- Search for our starting unit
  488. local units = Spring.GetTeamUnits(Spring.GetMyTeamID())
  489. for u = 1, #units do
  490. local uID = units[u]
  491. if GetUnitCanCompleteQueue(uID) then --Spring.GetUnitDefID(uID) == sDefID then
  492.  
  493. for b = 1, #buildQueue do
  494. local buildData = buildQueue[b]
  495. Spring.GiveOrderToUnit(uID, -buildData[1], {buildData[2], buildData[3], buildData[4], buildData[5]}, {"shift"})
  496. end
  497.  
  498. --widgetHandler:RemoveWidget(self)
  499. --Spring.Echo ("nonono")
  500. return
  501. end
  502. end
  503. end
  504.  
  505. ------------------------------------------------------------
  506. -- Mouse
  507. ------------------------------------------------------------
  508. function widget:IsAbove(mx, my)
  509. return TraceDefID(mx, my)
  510. end
  511. local tooltipFormat = 'Build %s\n%s\n' .. metalColor .. '%d m ' .. whiteColor .. '/ ' .. energyColor .. '%d e ' .. whiteColor .. '/ ' .. buildColor .. '%.1f sec'
  512. function widget:GetTooltip(mx, my)
  513. local bDefID = TraceDefID(mx, my)
  514. local bDef = UnitDefs[bDefID]
  515. return string.format(tooltipFormat, bDef.humanName, bDef.tooltip, bDef.metalCost, bDef.energyCost, bDef.buildTime / sDef.buildSpeed)
  516. end
  517. function widget:MousePress(mx, my, mButton)
  518.  
  519. local tracedDefID = TraceDefID(mx, my)
  520. if tracedDefID then
  521. if mButton == 1 then
  522. SetSelDefID(tracedDefID)
  523. return true
  524. elseif mButton == 3 then
  525. areDragging = true
  526. return true
  527. end
  528. else
  529. if selDefID then
  530. if mButton == 1 then
  531.  
  532. local mx, my = Spring.GetMouseState()
  533. local _, pos = Spring.TraceScreenRay(mx, my, true)
  534. if not pos then return end
  535. local bx, by, bz = Spring.Pos2BuildPos(selDefID, pos[1], pos[2], pos[3])
  536. local buildFacing = Spring.GetBuildFacing()
  537.  
  538. if Spring.TestBuildOrder(selDefID, bx, by, bz, buildFacing) ~= 0 then
  539.  
  540. local buildData = {selDefID, bx, by, bz, buildFacing}
  541. local _, _, meta, shift = Spring.GetModKeyState()
  542. if meta then
  543. table.insert(buildQueue, 1, buildData)
  544.  
  545. elseif shift then
  546.  
  547. local anyClashes = false
  548. for i = #buildQueue, 1, -1 do
  549. if DoBuildingsClash(buildData, buildQueue[i]) then
  550. anyClashes = true
  551. table.remove(buildQueue, i)
  552. end
  553. end
  554.  
  555. if not anyClashes then
  556. buildQueue[#buildQueue + 1] = buildData
  557. end
  558. else
  559. buildQueue = {buildData}
  560. end
  561.  
  562. if not shift then
  563. SetSelDefID(nil)
  564. end
  565. end
  566.  
  567. return true
  568.  
  569. elseif mButton == 3 then
  570.  
  571. SetSelDefID(nil)
  572. return true
  573. end
  574. end
  575. end
  576. end
  577. function widget:MouseMove(mx, my, dx, dy, mButton)
  578. if areDragging then
  579. wl = wl + dx
  580. wt = wt + dy
  581. end
  582. end
  583. function widget:MouseRelease(mx, my, mButton)
  584. areDragging = false
  585. end
  586.  
  587. ------------------------------------------------------------
  588. -- Misc
  589. ------------------------------------------------------------
  590. function widget:RecvLuaMsg(msg, playerID)
  591. -- we just use this function to trigger side change update.
  592.  
  593. local sidePrefix = '195' -- set by widget gui_commchange.lua
  594.  
  595. if string.find(msg,sidePrefix) then
  596. local myTeamID = Spring.GetMyTeamID()
  597. local startID = spGetTeamRulesParam(myTeamID, 'startUnit')
  598. --if startID and startID ~= "" then sDefID = startID end
  599. InitializeFaction(sDefID)
  600. end
  601. end
  602.  
  603.  
  604.  
  605. function widget:TextCommand(cmd)
  606.  
  607. -- Facing commands are only handled by spring if we have a building selected, which isn't possible pre-game
  608. local m = cmd:match("^buildfacing (.+)$")
  609. if m then
  610.  
  611. local oldFacing = Spring.GetBuildFacing()
  612. local newFacing
  613. if (m == "inc") then
  614. newFacing = (oldFacing + 1) % 4
  615. elseif (m == "dec") then
  616. newFacing = (oldFacing + 3) % 4
  617. else
  618. return false
  619. end
  620.  
  621. Spring.SetBuildFacing(newFacing)
  622. Spring.Echo("Buildings set to face " .. ({"South", "East", "North", "West"})[1 + newFacing])
  623. return true
  624. end
  625.  
  626. local buildName = cmd:match("^buildunit_([^%s]+)$")
  627. if buildName then
  628. local bDefID = buildNameToID[buildName]
  629. if bDefID then
  630. SetSelDefID(bDefID)
  631. return true
  632. end
  633. end
  634. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement