Advertisement
Guest User

Unit Stats v1.4

a guest
Aug 16th, 2015
278
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.62 KB | None | 0 0
  1.  
  2. function widget:GetInfo()
  3. return {
  4. name = "Unit Stats",
  5. desc = "Shows detailed unit stats",
  6. author = "Niobium",
  7. date = "Jan 11, 2009",
  8. version = 1.4,
  9. license = "GNU GPL, v2 or later",
  10. layer = 6,
  11. enabled = true, -- loaded by default?
  12. handler = true
  13. }
  14. end
  15.  
  16. ---- v1.4 changes
  17. --[teh]decay - dont trigger widget in "chat" mode
  18.  
  19. ---- v1.3 changes
  20. -- Fix for 87.0
  21. -- Added display of experience effect (when experience >25%)
  22.  
  23. ---- v1.2 changes
  24. -- Fixed drains for burst weapons (Removed 0.125 minimum)
  25. -- Show remaining costs for units under construction
  26.  
  27. ---- v1.1 changes
  28. -- Added extra text to help explain numbers
  29. -- Added grouping of duplicate weapons
  30. -- Added sonar radius
  31. -- Fixed radar/jammer detection
  32. -- Fixed stockpiling unit drains
  33. -- Fixed turnrate/acceleration scale
  34. -- Fixed very low reload times
  35.  
  36. ------------------------------------------------------------------------------------
  37. -- Globals
  38. ------------------------------------------------------------------------------------
  39. local fontSize = 14
  40. local xOffset = 25
  41. local yOffset = 25
  42. local useExp = false
  43.  
  44. local cX, cY
  45.  
  46. ------------------------------------------------------------------------------------
  47. -- Speedups
  48. ------------------------------------------------------------------------------------
  49. local white = '\255\255\255\255'
  50. local green = '\255\1\255\1'
  51. local yellow = '\255\255\255\1'
  52. local orange = '\255\255\128\1'
  53. local blue = '\255\128\128\255'
  54.  
  55. local metalColor = '\255\196\196\255' -- Light blue
  56. local energyColor = '\255\255\255\128' -- Light yellow
  57. local buildColor = '\255\128\255\128' -- Light green
  58.  
  59. local max = math.max
  60. local floor = math.floor
  61. local format = string.format
  62. local char = string.char
  63.  
  64. local glColor = gl.Color
  65. local glText = gl.Text
  66.  
  67. local spGetMyTeamID = Spring.GetMyTeamID
  68. local spGetTeamResources = Spring.GetTeamResources
  69. local spGetTeamInfo = Spring.GetTeamInfo
  70. local spGetPlayerInfo = Spring.GetPlayerInfo
  71. local spGetTeamColor = Spring.GetTeamColor
  72.  
  73. local spGetModKeyState = Spring.GetModKeyState
  74. local spGetMouseState = Spring.GetMouseState
  75. local spTraceScreenRay = Spring.TraceScreenRay
  76.  
  77. local spGetUnitDefID = Spring.GetUnitDefID
  78. local spGetUnitExp = Spring.GetUnitExperience
  79. local spGetUnitHealth = Spring.GetUnitHealth
  80. local spGetUnitTeam = Spring.GetUnitTeam
  81. local spGetUnitExperience = Spring.GetUnitExperience
  82. local spGetUnitSensorRadius = Spring.GetUnitSensorRadius
  83.  
  84. local uDefs = UnitDefs
  85. local wDefs = WeaponDefs
  86.  
  87. local show = false
  88. ------------------------------------------------------------------------------------
  89. -- Functions
  90. ------------------------------------------------------------------------------------
  91. local function DrawText(t1, t2)
  92. glText(t1, cX, cY, fontSize, "o")
  93. glText(t2, cX + 60, cY, fontSize, "o")
  94. cY = cY - fontSize
  95. end
  96.  
  97. local function GetTeamColorCode(teamID)
  98.  
  99. if not teamID then return "\255\255\255\255" end
  100.  
  101. local R, G, B = spGetTeamColor(teamID)
  102.  
  103. if not R then return "\255\255\255\255" end
  104.  
  105. R = floor(R * 255)
  106. G = floor(G * 255)
  107. B = floor(B * 255)
  108.  
  109. if (R < 11) then R = 11 end -- Note: char(10) terminates string
  110. if (G < 11) then G = 11 end
  111. if (B < 11) then B = 11 end
  112.  
  113. return "\255" .. char(R) .. char(G) .. char(B)
  114. end
  115.  
  116. local function GetTeamName(teamID)
  117.  
  118. if not teamID then return 'Error:NoTeamID' end
  119.  
  120. local _, teamLeader = spGetTeamInfo(teamID)
  121. if not teamLeader then return 'Error:NoLeader' end
  122.  
  123. local leaderName = spGetPlayerInfo(teamLeader)
  124. return leaderName or 'Error:NoName'
  125. end
  126.  
  127. ------------------------------------------------------------------------------------
  128. -- Code
  129. ------------------------------------------------------------------------------------
  130. function widget:Initialize()
  131. local highlightWidget = widgetHandler:FindWidget("HighlightUnit")
  132. if highlightWidget then
  133. widgetHandler:RemoveWidgetCallIn("DrawScreen", highlightWidget)
  134. end
  135. end
  136.  
  137. function widget:Shutdown()
  138. local highlightWidget = widgetHandler:FindWidget("HighlightUnit")
  139. if highlightWidget then
  140. widgetHandler:UpdateWidgetCallIn("DrawScreen", highlightWidget)
  141. end
  142. end
  143.  
  144. function widget:KeyPress(key, mods, isRepeat)
  145. -- Spring.Echo(key)
  146. if key == 32 then
  147. show = true
  148. end
  149. end
  150.  
  151. function widget:KeyRelease(key, mods, isRepeat)
  152. if key == 32 then
  153. show = false
  154. end
  155. end
  156.  
  157. function widget:DrawScreen()
  158.  
  159. -- local alt, ctrl, meta, shift = spGetModKeyState()
  160. --- if not meta then return end
  161. if not show then return end
  162. useExp = ctrl
  163.  
  164. local mx, my = spGetMouseState()
  165. local rType, uID = spTraceScreenRay(mx, my)
  166. if rType ~= 'unit' or not uID then return end
  167.  
  168. local uDefID = spGetUnitDefID(uID)
  169. if not uDefID then return end
  170.  
  171. local uDef = uDefs[uDefID]
  172. local _, _, _, _, buildProg = spGetUnitHealth(uID)
  173. local uTeam = spGetUnitTeam(uID)
  174.  
  175. cX = mx + xOffset
  176. cY = my + yOffset
  177. glColor(1.0, 1.0, 1.0, 1.0)
  178.  
  179. ------------------------------------------------------------------------------------
  180. -- Owner, unit name, unit ID
  181. ------------------------------------------------------------------------------------
  182. glText(GetTeamColorCode(uTeam) .. GetTeamName(uTeam) .. "'s " .. yellow .. uDef.humanName .. white .. " (" .. uDef.name .. ", #" .. uID .. ")", cX, cY, fontSize, "o")
  183. cY = cY - 2 * fontSize
  184.  
  185. ------------------------------------------------------------------------------------
  186. -- Units under construction
  187. ------------------------------------------------------------------------------------
  188. if buildProg and buildProg < 1 then
  189.  
  190. local myTeamID = spGetMyTeamID()
  191. local mCur, mStor, mPull, mInc, mExp, mShare, mSent, mRec = spGetTeamResources(myTeamID, 'metal')
  192. local eCur, eStor, ePull, eInc, eExp, eShare, eSent, eRec = spGetTeamResources(myTeamID, 'energy')
  193.  
  194. local mTotal = uDef.metalCost
  195. local eTotal = uDef.energyCost
  196. local buildRem = 1 - buildProg
  197. local mRem = mTotal * buildRem
  198. local eRem = eTotal * buildRem
  199. local mEta = (mRem - mCur) / (mInc + mRec)
  200. local eEta = (eRem - eCur) / (eInc + eRec)
  201.  
  202. DrawText("Prog:", format("%d%%", 100 * buildProg))
  203. DrawText("M:", format("%d / %d (" .. yellow .. "%d" .. white .. ", %ds)", mTotal * buildProg, mTotal, mRem, mEta))
  204. DrawText("E:", format("%d / %d (" .. yellow .. "%d" .. white .. ", %ds)", eTotal * buildProg, eTotal, eRem, eEta))
  205. --DrawText("MaxBP:", format(white .. '%d', buildRem * uDef.buildTime / math.max(mEta, eEta)))
  206. cY = cY - fontSize
  207. end
  208.  
  209. ------------------------------------------------------------------------------------
  210. -- Generic information, cost, move, class
  211. ------------------------------------------------------------------------------------
  212. DrawText("Cost:", format(metalColor .. '%d' .. white .. ' / ' ..
  213. energyColor .. '%d' .. white .. ' / ' ..
  214. buildColor .. '%d', uDef.metalCost, uDef.energyCost, uDef.buildTime)
  215. )
  216.  
  217. if not (uDef.isBuilding or uDef.isFactory) then
  218. DrawText("Move:", format("%.1f / %.1f / %.0f (Speed / Accel / Turn)", uDef.speed, 900 * uDef.maxAcc, 30 * uDef.turnRate * (180 / 32767)))
  219. end
  220.  
  221. DrawText("Class:", Game.armorTypes[uDef.armorType or 0] or '???')
  222.  
  223. if uDef.buildSpeed > 0 then DrawText('Build:', yellow .. uDef.buildSpeed) end
  224.  
  225. cY = cY - fontSize
  226.  
  227. ------------------------------------------------------------------------------------
  228. -- Sensors and Jamming
  229. ------------------------------------------------------------------------------------
  230. local losRadius = spGetUnitSensorRadius(uID, 'los') or 0
  231. local airLosRadius = spGetUnitSensorRadius(uID, 'airLos') or 0
  232. local radarRadius = spGetUnitSensorRadius(uID, 'radar') or 0
  233. local sonarRadius = spGetUnitSensorRadius(uID, 'sonar') or 0
  234. local jammingRadius = spGetUnitSensorRadius(uID, 'radarJammer') or 0
  235. -- local sonarJammingRadius = spGetUnitSensorRadius(uID, 'sonarJammer')
  236. local seismicRadius = spGetUnitSensorRadius(uID, 'seismic') or 0
  237.  
  238. DrawText('Los:', losRadius .. (airLosRadius > losRadius and format(' (AirLos: %d)', airLosRadius) or ''))
  239.  
  240. if radarRadius > 0 then DrawText('Radar:', '\255\77\255\77' .. radarRadius) end
  241. if sonarRadius > 0 then DrawText('Sonar:', '\255\128\128\255' .. sonarRadius) end
  242. if jammingRadius > 0 then DrawText('Jam:' , '\255\255\77\77' .. jammingRadius) end
  243. if seismicRadius > 0 then DrawText('Seis:' , '\255\255\26\255' .. seismicRadius) end
  244.  
  245. if uDef.stealth then DrawText("Other:", "Stealth") end
  246.  
  247. cY = cY - fontSize
  248.  
  249. ------------------------------------------------------------------------------------
  250. -- Weapons
  251. ------------------------------------------------------------------------------------
  252. local uExp = spGetUnitExperience(uID) or 0
  253. uExp = uExp / (1 + uExp)
  254. local uExpDmg = uExp * 1
  255. local uExpRld = 1 / (1 - uExp * 0.4) - 1
  256. local uExpHp = uExp * 0.7
  257. if uExp > 0 then
  258. DrawText("Exp:", format("+%d%% damage, +%d%% firerate, +%d%% health", uExpDmg*100, uExpRld*100, uExpHp*100))
  259. cY = cY - fontSize
  260. end
  261.  
  262. local wepCounts = {} -- wepCounts[wepDefID] = #
  263. local wepsCompact = {} -- uWepsCompact[1..n] = wepDefID
  264.  
  265. local uWeps = uDef.weapons
  266. for i = 1, #uWeps do
  267. local wDefID = uWeps[i].weaponDef
  268. local wCount = wepCounts[wDefID]
  269. if wCount then
  270. wepCounts[wDefID] = wCount + 1
  271. else
  272. wepCounts[wDefID] = 1
  273. wepsCompact[#wepsCompact + 1] = wDefID
  274. end
  275. end
  276.  
  277. for i = 1, #wepsCompact do
  278.  
  279. local wDefId = wepsCompact[i]
  280. local uWep = wDefs[wDefId]
  281.  
  282. if uWep.range > 16 then
  283. local oBurst = uWep.salvoSize * uWep.projectiles
  284. local oRld = uWep.stockpile and uWep.stockpileTime or uWep.reload
  285. local wepCount = wepCounts[wDefId]
  286.  
  287. if wepCount > 1 then
  288. DrawText("Weap:", format(yellow .. "%dx" .. white .. " %s", wepCount, uWep.type))
  289. else
  290. DrawText("Weap:", uWep.type)
  291. end
  292.  
  293. DrawText("Info:", format("%d range, %d aoe, %d%% edge", uWep.range, uWep.damageAreaOfEffect, 100 * uWep.edgeEffectiveness))
  294.  
  295. if useExp then
  296. oRld = oRld*(1-uExpRld)
  297. end
  298. local defaultDamage = uWep.damages[0]
  299. for cat=0, #uWep.damages do
  300. local oDmg = uWep.damages[cat]
  301. local catName = Game.armorTypes[cat]
  302. if catName and oDmg and (oDmg ~= defaultDamage or cat == 0) then
  303. local dmgString
  304. if useExp then
  305. oDmg = oDmg*(1+uExpDmg)
  306. end
  307. if oBurst > 1 then
  308. dmgString = format(yellow .. "%d (x%d)" .. white .. " / " .. yellow .. "%.2f" .. white .. " = " .. yellow .. "%.2f", oDmg, oBurst, oRld, oBurst * oDmg / oRld)
  309. else
  310. dmgString = format(yellow .. "%d" .. white .. " / " .. yellow .. "%.2f" .. white .. " = " .. yellow .. "%.2f", oDmg, oRld, oDmg / oRld)
  311. end
  312.  
  313. if wepCount > 1 then
  314. dmgString = dmgString .. white .. " (Each)"
  315. end
  316.  
  317. dmgString = dmgString .. white .. " (" .. catName .. ")"
  318.  
  319. DrawText("Dmg:", dmgString)
  320. end
  321. end
  322.  
  323. if uWep.metalCost > 0 or uWep.energyCost > 0 then
  324.  
  325. -- Stockpiling weapons are weird
  326. -- They take the correct amount of resources overall
  327. -- They take the correct amount of time
  328. -- They drain (32/30) times more resources than they should (And the listed drain is real, having lower income than listed drain WILL stall you)
  329. local drainAdjust = uWep.stockpile and 32/30 or 1
  330.  
  331. DrawText('Cost:', format(metalColor .. '%d' .. white .. ', ' ..
  332. energyColor .. '%d' .. white .. ' = ' ..
  333. metalColor .. '-%d' .. white .. ', ' ..
  334. energyColor .. '-%d' .. white .. ' per second',
  335. uWep.metalCost,
  336. uWep.energyCost,
  337. drainAdjust * uWep.metalCost / oRld,
  338. drainAdjust * uWep.energyCost / oRld))
  339. end
  340.  
  341. cY = cY - fontSize
  342. end
  343. end
  344. end
  345.  
  346. ------------------------------------------------------------------------------------
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement