Advertisement
Guest User

Chili Deluxe Player List - MOD

a guest
Mar 20th, 2013
145
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 81.97 KB | None | 0 0
  1. --------------------------------------------------------------------------------
  2. --------------------------------------------------------------------------------
  3.  
  4. function widget:GetInfo()
  5. return {
  6. name = "Chili Deluxe Player List - MOD",
  7. desc = "v0.202 Chili Deluxe Player List, Alpha Release",
  8. author = "CarRepairer, KingRaptor, CrazyEddie, MoriturusMortus",
  9. date = "2012-06-30",
  10. license = "GNU GPL, v2 or later",
  11. layer = 50,
  12. enabled = false,
  13. --detailsDefault = 1
  14. -- based on v1.31 Chili Crude Player List by CarRepairer, KingRaptor, et al
  15. }
  16. end
  17.  
  18. --[[
  19. TODO:
  20. * Fast-and-Easy switching between large and small views, and between a single view hidden or shown
  21. * More granular control over which columns are displayed, and how (text vs. icons, etc)
  22. * More and better tooltips, and options for controlling whether and how they are displayed
  23. * Scaling x-axis dimensions proportionally with the fontsize
  24. * Profiling and improving performance
  25. * Tons of minor bugfixes, cosmetic enhancements, and code cleanup
  26. --]]
  27.  
  28. --------------------------------------------------------------------------------
  29. --------------------------------------------------------------------------------
  30.  
  31. function SetupPlayerNames() end
  32. function ToggleVisibility() end
  33.  
  34. local echo = Spring.Echo
  35. local spGetUnitIsStunned = Spring.GetUnitIsStunned
  36.  
  37. local Chili
  38. local Image
  39. local Button
  40. local Checkbox
  41. local Window
  42. local ScrollPanel
  43. local StackPanel
  44. local Label
  45. local screen0
  46. local color2incolor
  47. local incolor2color
  48.  
  49. --------------------------------------------------------------------------------
  50. --------------------------------------------------------------------------------
  51.  
  52. local window_cpl, scroll_cpl
  53.  
  54. options_path = 'Settings/HUD Panels/PlayerList'
  55. options_order = { 'visible', 'backgroundOpacity', 'text_height', 'name_width', 'mousewheel', 'alignToTop', 'alignToLeft', 'showSummaries', 'showClanSummaries', 'show_Damage_stats', 'show_unit_stats', 'show_income_stats', 'support_my_Ceiling', 'send_resources_amount', 'colorResourceStats', 'show_ccr', 'rank_as_text', 'round_elo', 'cpu_ping_as_text', 'show_tooltips', 'list_size'} --'support_ally_floor',
  56. options = {
  57. visible = {
  58. name = "Visible",
  59. type = 'bool',
  60. value = true,
  61. desc = "Set a hotkey here to toggle the playerlist on and off",
  62. OnChange = function() ToggleVisibility() end,
  63. },
  64. backgroundOpacity = {
  65. name = "Background Opacity",
  66. type = "number",
  67. value = 0.5, min = 0, max = 1, step = 0.01,
  68. OnChange = function(self)
  69. scroll_cpl.backgroundColor = {1,1,1,self.value}
  70. scroll_cpl:Invalidate()
  71. end,
  72. },
  73. text_height = {
  74. name = 'Font Size (10-14)',
  75. type = 'number',
  76. value = 13,
  77. min=10,max=14,step=1,
  78. OnChange = function() SetupPanels() end,
  79. advanced = true
  80. },
  81. name_width = {
  82. name = 'Name Width (50-200)',
  83. type = 'number',
  84. value = 120,
  85. min=50,max=200,step=10,
  86. OnChange = function() SetupPanels() end,
  87. advanced = true
  88. },
  89. mousewheel = {
  90. name = "Scroll with mousewheel",
  91. type = 'bool',
  92. value = false,
  93. OnChange = function(self) scroll_cpl.noMouseWheel = not self.value; end,
  94. },
  95. alignToTop = {
  96. name = "Align to top",
  97. type = 'bool',
  98. value = true,
  99. desc = "Align to top and grow downwards (vs. align to bottom and grow upwards)",
  100. OnChange = function() SetupPlayerNames() end,
  101. },
  102. alignToLeft = {
  103. name = "Align to left",
  104. type = 'bool',
  105. value = false,
  106. desc = "Align to left and grow rightwards (vs. align to right and grow leftwards)",
  107. OnChange = function() SetupScrollPanel() end,
  108. },
  109. showSummaries = {
  110. name = "Show team summaries",
  111. type = 'bool',
  112. value = true,
  113. desc = "Display summary information for each team (note: even with this checked, summaries won't be displayed if all the teams are very small)",
  114. OnChange = function() SetupPlayerNames() end,
  115. },
  116. --Clan Begin
  117. showClanSummaries = {
  118. name = "Show MyClan summaries",
  119. type = 'bool',
  120. value = true,
  121. desc = "Display summary information for your Clan",
  122. OnChange = function() SetupPlayerNames() end,
  123. },
  124. --Clan End
  125. --Damage Begin
  126. show_Damage_stats = {
  127. name = "Show Damage summaries",
  128. type = 'bool',
  129. value = true,
  130. desc = "Display Damage statistics: dealt and taken damage.",
  131. OnChange = function() SetupPanels() end,
  132. },
  133. --Damage End
  134. show_unit_stats = {
  135. name = "Show unit stats",
  136. type = 'bool',
  137. value = true,
  138. desc = "Display resource statistics: metal in mobile units and static defenses.",
  139. OnChange = function() SetupPanels() end,
  140. },
  141. show_income_stats = {
  142. name = "Show income stats",
  143. type = 'bool',
  144. value = true,
  145. desc = "Display resource statistics: metal and energy income.",
  146. OnChange = function() SetupPanels() end,
  147. },
  148. --Support Begin
  149. --[[
  150. support_ally_floor = {
  151. name = 'Support: ally floor (1-500)',
  152. type = 'number',
  153. value = 50,
  154. desc = "Determine ally minimum threshold, cross the threshold = send resource.",
  155. min=1,max=500,step=10,
  156. OnChange = function() SetupPanels() end,
  157. advanced = true
  158. },
  159. ]]--
  160. support_my_Ceiling = {
  161. name = 'Support: my ceiling (10-5000)',
  162. type = 'number',
  163. value = 250,
  164. desc = "Determine your maximum threshold, cross the threshold = send resource.",
  165. min=10,max=5000,step=10,
  166. OnChange = function() SetupPanels() end,
  167. advanced = true
  168. },
  169. --Support End
  170. --ShareResources Begin
  171. send_resources_amount = {
  172. name = 'Resources send on double click (10-500)',
  173. type = 'number',
  174. value = 50,
  175. desc = "Amount of resources to be send on double click",
  176. min=10,max=500,step=10,
  177. OnChange = function() SetupPanels() end,
  178. advanced = true
  179. },
  180. --ShareResources END
  181. colorResourceStats = {
  182. name = "Show stats in color",
  183. type = 'bool',
  184. value = false,
  185. desc = "Display resource statistics such as unit metal and income in each player's color (vs. white)",
  186. OnChange = function() SetupPlayerNames() end,
  187. },
  188. show_ccr = {
  189. name = "Show clan/country/rank",
  190. type = 'bool',
  191. value = true,
  192. desc = "Show the clan, country, and rank columns",
  193. OnChange = function() SetupPanels() end,
  194. },
  195. rank_as_text = {
  196. name = "Show rank as text",
  197. type = 'bool',
  198. value = false,
  199. desc = "Show rank as text (vs. as an icon)",
  200. OnChange = function() SetupPlayerNames() end,
  201. },
  202. --Elo Begin
  203. round_elo = {
  204. name = "Round elo",
  205. type = 'bool',
  206. value = true,
  207. desc = "Round elo",
  208. OnChange = function() SetupPanels() end,
  209. },
  210. --Elo End
  211. cpu_ping_as_text = {
  212. name = "Show ping/cpu as text",
  213. type = 'bool',
  214. value = false,
  215. desc = "Show ping and cpu stats as text (vs. as an icon)",
  216. OnChange = function() SetupPanels() end,
  217. },
  218. show_tooltips = {
  219. name = "Show tooltips",
  220. type = 'bool',
  221. value = true,
  222. desc = "Show tooltips where available (vs. hiding all tooltips)",
  223. OnChange = function() SetupPanels() end,
  224. },
  225. list_size = {
  226. name = 'List Size: Who should be included?',
  227. type = 'list',
  228. value = 3,
  229. items = {
  230. { key = 0, name = "Nobody" },
  231. { key = 1, name = "Just you" },
  232. { key = 2, name = "Just your team" },
  233. { key = 3, name = "All players" },
  234. { key = 4, name = "All players and spectators" },
  235. },
  236. OnChange = function() SetupPlayerNames() end,
  237. },
  238. }
  239.  
  240. local name_width
  241.  
  242. local green = ''
  243. local red = ''
  244. local orange = ''
  245. local yellow = ''
  246. local cyan = ''
  247. local white = ''
  248.  
  249. local function IsFFA()
  250. local allyteams = Spring.GetAllyTeamList()
  251. local gaiaT = Spring.GetGaiaTeamID()
  252. local gaiaAT = select(6, Spring.GetTeamInfo(gaiaT))
  253. local numAllyTeams = 0
  254. for i=1,#allyteams do
  255. if allyteams[i] ~= gaiaAT then
  256. local teams = Spring.GetTeamList()
  257. if #teams > 0 then
  258. numAllyTeams = numAllyTeams + 1
  259. end
  260. end
  261. end
  262. return numAllyTeams > 2
  263. end
  264.  
  265. -- The ceasefire functionality isn't working right now.
  266. -- I'm leaving all the code in place, but disabling the buttons.
  267. -- Someone can come back in and fix it later.
  268. --
  269. -- local cf = IsFFA()
  270. local cf = false
  271.  
  272. local localTeam = 0
  273. local localAlliance = 0
  274. local myID
  275. local myName
  276. local amSpec
  277. local myClan --Clan
  278.  
  279. myID = Spring.GetMyPlayerID()
  280. myName,_,amSpec,_,_,_,_,_,_,CKeys = Spring.GetPlayerInfo(myID)
  281.  
  282. --Clan Begin
  283. if CKeys then
  284. myClan = CKeys.clan
  285. end
  286. myClan = myClan or "<No Clan>"
  287. --Clan END
  288.  
  289. localTeam = Spring.GetMyTeamID()
  290. localAlliance = Spring.GetMyAllyTeamID()
  291.  
  292. -- This is awkward, but it's okay for now.
  293. -- I'll make it elegant when I implement x-scaling with fontsize
  294. --
  295. local x_icon_clan
  296. local x_icon_country
  297. local x_icon_rank
  298. local x_elo
  299. local x_cf
  300. local x_status
  301. local x_name
  302. local x_share
  303. local x_m_mobiles
  304. local x_m_defense
  305. local x_c_damage
  306. local x_t_damage
  307. local x_m_income
  308. local x_e_income
  309. local x_m_fill
  310. local x_e_fill
  311. local x_cpu
  312. local x_ping
  313. local x_postping
  314. local x_bound
  315. local x_windowbound
  316.  
  317. local function CalculateWidths()
  318. name_width = options.name_width.value or 120
  319. x_icon_clan = 10
  320. x_icon_country = x_icon_clan + 18
  321. x_icon_rank = x_icon_country + 20
  322. x_elo = options.show_ccr.value and x_icon_rank + 16 or x_icon_clan
  323. x_cf = x_elo + 32
  324. x_status = cf and x_cf + 20 or x_cf
  325. x_name = x_status + 12
  326. x_share = x_name + name_width
  327. --Damage Begin
  328. x_c_damage = not amSpec and x_share + 12 or x_share
  329. x_t_damage = x_c_damage + 36
  330. --Damage End
  331. x_m_mobiles = options.show_Damage_stats.value and x_t_damage + 40 or x_c_damage
  332. x_m_defense = x_m_mobiles + 34
  333. x_m_income = options.show_unit_stats.value and x_m_defense + 40 or x_m_mobiles
  334. x_e_income = x_m_income + 30
  335. x_m_fill = options.show_income_stats.value and x_e_income + 26 or x_m_income
  336. x_e_fill = x_m_fill + 30
  337. x_cpu = x_e_fill + (options.cpu_ping_as_text.value and 52 or 30)
  338. x_ping = x_cpu + (options.cpu_ping_as_text.value and 46 or 16)
  339. x_bound = x_ping + 28
  340. x_windowbound = x_bound + 0
  341. end
  342. CalculateWidths()
  343.  
  344. local UPDATE_FREQUENCY = 0.8 -- seconds
  345.  
  346. local cfCheckBoxes = {}
  347.  
  348. local allyTeams = {} -- [id] = {team1, team2, ...}
  349. local allyClans = {}
  350. local teams = {} -- [id] = {leaderName = name, roster = {entity1, entity2, ...}}
  351. local teamZeroPlayers = {}
  352.  
  353. -- entity = player (including specs) or bot
  354. -- ordered list; contains isAI, isSpec, playerID, teamID, name, namelabel, cpuImg, pingImg
  355. local entities = {}
  356. local allyTeamEntities = {}
  357. local allyTeamOrderRank = {}
  358. local allyTeamsDead = {}
  359. local allyTeamsElo = {}
  360. local playerTeamStatsCache = {}
  361. local finishedUnits = {}
  362. local numBigTeams = 0
  363. local existsVeryBigTeam = nil
  364. local myTeamIsVeryBig = nil
  365. local specTeam = {roster = {}}
  366. local CausedDamageList = {}
  367. local TakenDamageList = {}
  368.  
  369. --Clan Begin
  370. local allyClanEntities = {}
  371. local allyClanOrderRank = {}
  372. local allyClanDead = {}
  373. local existsVeryBigClan = nil
  374. local myClanIsVeryBig = nil
  375. local numBigClan = 0
  376. --Clan END
  377.  
  378. local sharePic = ":n:"..LUAUI_DIRNAME.."Images/playerlist/share.png"
  379. local cpuPic = ":n:"..LUAUI_DIRNAME.."Images/playerlist/cpu.png"
  380. local pingPic = ":n:"..LUAUI_DIRNAME.."Images/playerlist/ping.png"
  381.  
  382. local row
  383. local fontsize
  384. local list_size
  385. local timer = 0
  386. local lastSizeX
  387. local lastSizeY
  388. local lastChosenSizeX = 0
  389. include("keysym.h.lua")
  390.  
  391. --------------------------------------------------------------------------------
  392. --------------------------------------------------------------------------------
  393. local function TableFind(f, l)
  394. if f == nil or l == nil then
  395. return false
  396. else
  397. local count = 0
  398. for _, v in ipairs(l) do
  399. count = count + 1
  400. if f == v then
  401. return count
  402. end
  403. end
  404. end
  405. return false
  406. end
  407.  
  408.  
  409. --Chat Begin
  410. local function ChatwithUser(playername)
  411. Spring.SendCommands("ChatAll","pastetext /w "..playername..' \1')
  412. end
  413.  
  414. local function ChatwithTeam()
  415. Spring.SendCommands("ChatAlly","pastetext \1")
  416. end
  417. --Chat END
  418.  
  419. --View Begin
  420. --Code taken from the Team View lua script created by BoredJoe
  421. local function ViewTeam(TeamList)
  422. local averagex = 0
  423. local averagey = 0
  424. local averagez = 0
  425. local count = 0
  426. for i=1,#TeamList do
  427. local teamID = TeamList[i]
  428. for _,unitID in ipairs(Spring.GetAllUnits()) do
  429. UnitTeamID = Spring.GetUnitTeam(unitID)
  430. if UnitTeamID == teamID then
  431. local x, y, z = Spring.GetUnitPosition(unitID)
  432. averagex = (averagex + x)
  433. averagey = (averagey + y)
  434. averagez = (averagez + z)
  435. count = (count + 1)
  436. end
  437. end
  438. end
  439. averagex = averagex / count
  440. averagey = averagey / count
  441. averagez = averagez / count
  442. if count ~= 0 then
  443. Spring.SetCameraTarget(averagex, averagey, averagez)
  444. end
  445. end
  446. --View END
  447.  
  448. local function ShareUnits(playername, team)
  449. local selcnt = Spring.GetSelectedUnitsCount()
  450. if selcnt > 0 then
  451. Spring.SendCommands("say a: I gave "..selcnt.." units to "..playername..".")
  452. Spring.ShareResources(team, "units")
  453. else
  454. echo 'Player List: No units selected to share.'
  455. end
  456. end
  457.  
  458. local function AskForUnits()
  459. local count = 0
  460. local Units = Spring.GetTeamUnits(localTeam)
  461. for i=1,#Units do
  462. local UN = Units[i]
  463. local unitDefID = Spring.GetUnitDefID(UN)
  464. if (UnitDefs[unitDefID]["canReclaim"]) then
  465. count = count +1
  466. end
  467. end
  468. if count <= 0 then
  469. Spring.SendCommands("say a: I need a Constructor")
  470. else
  471. Spring.SendCommands("say a: I need Unit support.")
  472. end
  473. end
  474.  
  475. local function AskForResources(resource)
  476. Spring.SendCommands("say a: I need some "..resource..".")
  477. end
  478.  
  479. --ShareResources Begin
  480. local function SendResources(playername, teamID, resource)
  481. local myCur,_,_,_,_,_,_,_ = Spring.GetTeamResources(localTeam, resource)
  482. local plCur,plMax,_,_,_,_,_,_ = Spring.GetTeamResources(teamID, resource)
  483. if myCur >= options.send_resources_amount.value and (plCur - 2 <= plMax) then
  484. Spring.ShareResources(teamID, resource, options.send_resources_amount.value)
  485. Spring.SendCommands("say a: I gave "..options.send_resources_amount.value.." "..resource.." to "..playername..".")
  486. else
  487. echo ("Not enough resources or storage.")
  488. end
  489. end
  490. --ShareResources END
  491.  
  492. --Support Begin
  493.  
  494. local m_SupportList = {}
  495. local e_SupportList = {}
  496. local m_TeamSupport = false
  497. local e_TeamSupport = false
  498. local m_ClanSupport = false
  499. local e_ClanSupport = false
  500.  
  501. function Support(teamID)
  502. if m_SupportList[teamID] then
  503. SendSupport(teamID, 'metal')
  504. end
  505. if e_SupportList[teamID] then
  506. SendSupport(teamID, 'energy')
  507. end
  508. end
  509.  
  510. function SendSupport(teamID, resource)
  511.  
  512. local Transfer = 0
  513.  
  514. local myCeiling = options.support_my_Ceiling.value
  515.  
  516. --echo(allyFloor)
  517. --echo(myCeiling)
  518.  
  519. local Cur,Max,_,Income,Expense,_,_,_ = Spring.GetTeamResources(localTeam, resource)
  520. local Plus = Income-Expense
  521. --local Seer=Max-Plus
  522. --echo(Cur)
  523.  
  524. local AllyCur,AllyMax,_,AllyIncome,AllyExpense,_,_,_ = Spring.GetTeamResources(teamID, resource)
  525. local AllyPlus = AllyIncome-AllyExpense
  526. --local AllySeer = AllyMax-(AllyPlus+Plus)
  527. --echo(AllyCur)
  528.  
  529. local allyFloor = (AllyMax*0.9) -- options.support_ally_floor.value
  530.  
  531. if AllyCur < allyFloor and Cur > myCeiling and AllyPlus < 0 then
  532. if (Cur-(AllyPlus*(-1))) >= myCeiling then
  533. Transfer = (Cur-myCeiling)
  534. else
  535. Transfer = (AllyPlus*-1)
  536. end
  537. if (AllyCur+Transfer) > allyFloor then
  538. Transfer = allyFloor-AllyCur
  539. end
  540. Spring.ShareResources(teamID, resource, Transfer)
  541. --echo(teamID.." "..resource.." "..Transfer)
  542. end
  543. end
  544.  
  545. local function AddtoSupport(entity, resource)
  546. if resource == 'metal' then
  547. if m_SupportList[entity.teamID] then
  548. m_SupportList[entity.teamID] = false
  549. echo ("Removed "..entity.name.." to metal support list.")
  550. if entity.m_SupportButton then entity.m_SupportButton.backgroundColor = {0,0,0,0} end
  551. else
  552. m_SupportList = m_SupportList or {}
  553. m_SupportList[entity.teamID] = true
  554. echo ("Added "..entity.name.." to metal support list.")
  555. if entity.m_SupportButton then entity.m_SupportButton.backgroundColor = {0,1,0,1} end
  556. end
  557. elseif resource == 'energy' then
  558. if e_SupportList[entity.teamID] then
  559. e_SupportList[entity.teamID] = false
  560. echo ("Removed "..entity.name.." to energy support list.")
  561. if entity.e_SupportButton then entity.e_SupportButton.backgroundColor = {0,0,0,0} end
  562. else
  563. e_SupportList = e_SupportList or {}
  564. e_SupportList[entity.teamID] = true
  565. echo ("Added "..entity.name.." to energy support list.")
  566. if entity.e_SupportButton then entity.e_SupportButton.backgroundColor = {0,1,0,1} end
  567. end
  568. end
  569. end
  570.  
  571. local ListSupportButton = {}
  572.  
  573. local function AddTeamtoSupport(mainentity,resource)
  574. if resource == 'metal' then
  575. if m_TeamSupport then
  576. if ListSupportButton.teammetal then ListSupportButton.teammetal.backgroundColor = {0,0,0,0} end
  577. m_TeamSupport = false
  578. if ListSupportButton.clanmetal then ListSupportButton.clanmetal.backgroundColor = {0,0,0,0}; ListSupportButton.clanmetal:Invalidate() end
  579. m_ClanSupport = false
  580. for i=1,#allyTeams[localAlliance] do
  581. local teamID = allyTeams[localAlliance][i]
  582. if teamID ~= localTeam and teams[teamID].roster then
  583. for j=1,#teams[teamID].roster do
  584. local entity = teams[teamID].roster[j]
  585. m_SupportList[teamID] = false
  586. echo ("Removed "..entity.name.." to metal support list.")
  587. if entity.m_SupportButton then entity.m_SupportButton.backgroundColor = {0,0,0,0}; entity.m_SupportButton:Invalidate() end
  588. end
  589. end
  590. end
  591. elseif not m_TeamSupport then
  592. if ListSupportButton.teammetal then ListSupportButton.teammetal.backgroundColor = {0,1,0,1} end
  593. m_TeamSupport = true
  594. for i=1,#allyTeams[localAlliance] do
  595. local teamID = allyTeams[localAlliance][i]
  596. if teamID ~= localTeam and teams[teamID].roster then
  597. for j=1,#teams[teamID].roster do
  598. local entity = teams[teamID].roster[j]
  599. m_SupportList[teamID] = true
  600. echo ("Added "..entity.name.." to metal support list.")
  601. if entity.m_SupportButton then entity.m_SupportButton.backgroundColor = {0,1,0,1}; entity.m_SupportButton:Invalidate() end
  602. end
  603. end
  604. end
  605. end
  606. elseif resource == 'energy' then
  607. if e_TeamSupport then
  608. if ListSupportButton.teamenergy then ListSupportButton.teamenergy.backgroundColor = {0,0,0,0} end
  609. e_TeamSupport = false
  610. if ListSupportButton.clanenergy then ListSupportButton.clanenergy.backgroundColor = {0,0,0,0}; ListSupportButton.clanenergy:Invalidate() end
  611. e_ClanSupport = false
  612. for i=1,#allyTeams[localAlliance] do
  613. teamID = allyTeams[localAlliance][i]
  614. if teamID ~= localTeam and teams[teamID].roster then
  615. for j=1,#teams[teamID].roster do
  616. entity = teams[teamID].roster[j]
  617. e_SupportList[teamID] = false
  618. echo ("Removed "..entity.name.." to energy support list.")
  619. if entity.e_SupportButton then entity.e_SupportButton.backgroundColor = {0,0,0,0}; entity.e_SupportButton:Invalidate() end
  620. end
  621. end
  622. end
  623. elseif not e_TeamSupport then
  624. if ListSupportButton.teamenergy then ListSupportButton.teamenergy.backgroundColor = {0,1,0,1} end
  625. e_TeamSupport = true
  626. for i=1,#allyTeams[localAlliance] do
  627. teamID = allyTeams[localAlliance][i]
  628. if teamID ~= localTeam and teams[teamID].roster then
  629. for j=1,#teams[teamID].roster do
  630. entity = teams[teamID].roster[j]
  631. e_SupportList[teamID] = true
  632. echo ("Added "..entity.name.." to energy support list.")
  633. if entity.e_SupportButton then entity.e_SupportButton.backgroundColor = {0,1,0,1}; entity.e_SupportButton:Invalidate() end
  634. end
  635. end
  636. end
  637. end
  638. end
  639. end
  640.  
  641. local function AddClantoSupport(mainentity,resource)
  642. --clanentity = mainentity
  643. if resource == 'metal' then
  644. if m_ClanSupport then
  645. if ListSupportButton.clanmetal then ListSupportButton.clanmetal.backgroundColor = {0,0,0,0} end
  646. m_ClanSupport = false
  647. for i=1,#allyClans[localAlliance] do
  648. local teamID = allyClans[localAlliance][i]
  649. if teamID ~= localTeam and teams[teamID].roster then
  650. for j=1,#teams[teamID].roster do
  651. local entity = teams[teamID].roster[j]
  652. m_SupportList[teamID] = false
  653. echo ("Removed "..entity.name.." to metal support list.")
  654. if entity.m_SupportButton then entity.m_SupportButton.backgroundColor = {0,0,0,0}; entity.m_SupportButton:Invalidate() end
  655. end
  656. end
  657. end
  658. elseif not m_ClanSupport then
  659. if ListSupportButton.clanmetal then ListSupportButton.clanmetal.backgroundColor = {0,1,0,1} end
  660. m_ClanSupport = true
  661. for i=1,#allyClans[localAlliance] do
  662. local teamID = allyClans[localAlliance][i]
  663. if teamID ~= localTeam and teams[teamID].roster then
  664. for j=1,#teams[teamID].roster do
  665. local entity = teams[teamID].roster[j]
  666. m_SupportList[teamID] = true
  667. echo ("Added "..entity.name.." to metal support list.")
  668. if entity.m_SupportButton then entity.m_SupportButton.backgroundColor = {0,1,0,1}; entity.m_SupportButton:Invalidate() end
  669. end
  670. end
  671. end
  672. end
  673. elseif resource == 'energy' then
  674. if e_ClanSupport then
  675. if ListSupportButton.clanenergy then ListSupportButton.clanenergy.backgroundColor = {0,0,0,0} end
  676. e_ClanSupport = false
  677. for i=1,#allyClans[localAlliance] do
  678. teamID = allyClans[localAlliance][i]
  679. if teamID ~= localTeam and teams[teamID].roster then
  680. for j=1,#teams[teamID].roster do
  681. entity = teams[teamID].roster[j]
  682. e_SupportList[teamID] = false
  683. echo ("Removed "..entity.name.." to energy support list.")
  684. if entity.e_SupportButton then entity.e_SupportButton.backgroundColor = {0,0,0,0}; entity.e_SupportButton:Invalidate() end
  685. end
  686. end
  687. end
  688. elseif not e_ClanSupport then
  689. if ListSupportButton.clanenergy then ListSupportButton.clanenergy.backgroundColor = {0,1,0,1} end
  690. e_ClanSupport = true
  691. for i=1,#allyClans[localAlliance] do
  692. teamID = allyClans[localAlliance][i]
  693. if teamID ~= localTeam and teams[teamID].roster then
  694. for j=1,#teams[teamID].roster do
  695. entity = teams[teamID].roster[j]
  696. e_SupportList[teamID] = true
  697. echo ("Added "..entity.name.." to energy support list.")
  698. if entity.e_SupportButton then entity.e_SupportButton.backgroundColor = {0,1,0,1}; entity.e_SupportButton:Invalidate() end
  699. end
  700. end
  701. end
  702. end
  703. end
  704. end
  705. --Support END
  706.  
  707. -- makes a color char from a color table
  708. -- explanation for string.char: http://springrts.com/phpbb/viewtopic.php?f=23&t=24952
  709. local function GetColorChar(colorTable)
  710. if colorTable == nil then return string.char(255,255,255,255) end
  711. local col = {}
  712. for i=1,4 do
  713. col[i] = math.ceil(colorTable[i]*255)
  714. end
  715. return string.char(col[4],col[1],col[2],col[3])
  716. end
  717.  
  718. local function FormatPingCpu(ping,cpu)
  719. -- guard against being called with nils
  720. ping = ping or 0
  721. cpu = cpu or 0
  722. -- guard against silly values
  723. ping = math.max(math.min(ping,999),0)
  724. cpu = math.max(math.min(cpu,9.99),0)
  725.  
  726. local pingMult = 2/3 -- lower = higher ping needed to be red
  727. local pingCpuColors = {
  728. {0, 1, 0, 1},
  729. {0.7, 1, 0, 1},
  730. {1, 1, 0, 1},
  731. {1, 0.6, 0, 1},
  732. {1, 0, 0, 1}
  733. }
  734.  
  735. local pingCol = pingCpuColors[ math.ceil( math.min(ping * pingMult, 1) * 5) ] or {.85,.85,.85,1}
  736. local cpuCol = pingCpuColors[ math.ceil( math.min(cpu, 1) * 5 ) ] or {.85,.85,.85,1}
  737.  
  738. local pingText
  739. if ping < 1 then
  740. pingText = (math.floor(ping*1000) ..'ms')
  741. else
  742. pingText = ('' .. (math.floor(ping*100)/100)):sub(1,4) .. 's'
  743. end
  744.  
  745. local cpuText = math.round(cpu*100) .. '%'
  746.  
  747. return pingCol,cpuCol,pingText,cpuText
  748. end
  749.  
  750. local function FormatMetalStats(stat,k)
  751. -- if k then
  752. -- stat = 1000 * math.floor((stat/1000) + .5)
  753. -- return string.format("%.0f", stat/1000) .. "k"
  754. -- else
  755. -- stat = 50 * math.floor((stat/50) + .5)
  756. return stat < 1000
  757. and string.format("%.0f", stat)
  758. or string.format("%.1f", stat/1000) .. "k"
  759. -- end
  760. end
  761.  
  762. --Damage Begin
  763. local function FormatDamageStats(damage)
  764. if (damage>=1000 and damage<100000) then
  765. return string.format("%.1f", damage/1000) .. "k"
  766. elseif (damage>=100000 and damage<100000000) then
  767. return string.format("%.1f", damage/1000000) .. "M"
  768. elseif (damage>=100000000 and damage<100000000000) then
  769. return string.format("%.1f", damage/1000000000) .. "G"
  770. elseif (damage>=100000000000) then
  771. return string.format("%.1f", damage/1000000000000) .. "T"
  772. else
  773. return string.format("%.0f", damage)
  774. end
  775. end
  776. --Damage END
  777.  
  778. local function FormatElo(elo,full)
  779. local mult = full and 1 or 50
  780.  
  781. local elo_out
  782.  
  783. if options.round_elo.value then
  784. elo_out = mult * math.floor((elo/mult) + .5)
  785. else
  786. elo_out = math.floor(elo)
  787. end
  788.  
  789. local eloCol = {}
  790.  
  791. local top = 1800
  792. local mid = 1600
  793. local bot = 1400
  794. local tc = {1,1,1,1}
  795. local mc = {1,1,0,1}
  796. local bc = {1,.2,.2,1}
  797.  
  798. if elo_out >= top then eloCol = tc
  799. elseif elo_out >= mid then
  800. local r = (elo_out-mid)/(top-mid)
  801. for i = 1,4 do
  802. eloCol[i] = (r * tc[i]) + ((1-r) * mc[i])
  803. end
  804. elseif elo_out >= bot then
  805. local r = (elo_out-bot)/(mid-bot)
  806. for i = 1,4 do
  807. eloCol[i] = (r * mc[i]) + ((1-r) * bc[i])
  808. end
  809. else eloCol = bc
  810. end
  811.  
  812. return elo_out, eloCol
  813. end
  814.  
  815. local function ProcessUnit(unitID, unitDefID, unitTeam, remove)
  816. local stats = playerTeamStatsCache[unitTeam]
  817. if UnitDefs[unitDefID] and stats then -- shouldn't need to guard against nil here, but I've had it happen
  818. local metal = UnitDefs[unitDefID].metalCost
  819. local speed = UnitDefs[unitDefID].speed
  820. local unarmed = UnitDefs[unitDefID].springCategories.unarmed
  821. local isbuilt = not select(3, spGetUnitIsStunned(unitID))
  822. if metal and metal < 1000000 then -- tforms show up as 1million cost, so ignore them
  823. if remove then
  824. metal = -metal
  825. end
  826. -- for mobiles, count only completed units
  827. if speed and speed ~= 0 then
  828. if remove then
  829. finishedUnits[unitID] = nil
  830. stats.mMobs = stats.mMobs + metal
  831. elseif isbuilt then
  832. finishedUnits[unitID] = true
  833. stats.mMobs = stats.mMobs + metal
  834. end
  835. -- for static defense, include full cost of unfinished units so you can see when your teammates are trying to build too much
  836. elseif not unarmed then
  837. stats.mDefs = stats.mDefs + metal
  838. end
  839. end
  840. end
  841. end
  842.  
  843. local function GetPlayerTeamStats(teamID)
  844. if not playerTeamStatsCache[teamID] then
  845. playerTeamStatsCache[teamID] = {mMobs = 0, mDefs = 0}
  846. local units = Spring.GetTeamUnits(teamID)
  847. for i=1,#units do
  848. local unitID = units[i]
  849. local unitDefID = Spring.GetUnitDefID(unitID)
  850. ProcessUnit(unitID, unitDefID, teamID)
  851. end
  852. end
  853.  
  854. local stats = playerTeamStatsCache[teamID]
  855.  
  856. local eCurr, eStor, ePull, eInco, eExpe, eShar, eSent, eReci = Spring.GetTeamResources(teamID, "energy")
  857. local mCurr, mStor, mPull, mInco, mExpe, mShar, mSent, mReci = Spring.GetTeamResources(teamID, "metal")
  858. if eStor then
  859. eStor = eStor - 10000 -- eStor has a "hidden 10k" to account for
  860. if eStor > 50000 then eStor = 1000 end -- fix for weirdness where sometimes storage is reported as huge, assume it should be 1000
  861. end
  862. -- guard against dividing by zero later, when the fill bar percentage is calculated
  863. -- these probably aren't ever going to be zero, but better safe than sorry
  864. if mStore and mStore == 0 then mStore = 1000 end
  865. if eStore and eStore == 0 then eStore = 1000 end
  866.  
  867. -- Default these to 1 if the value is nil for some reason.
  868. -- These should never be 1 in normal play, so if you see
  869. -- them showing up as 1 then that means that something got nil,
  870. -- which should perhaps then be looked into further.
  871. -- Whereas it's quite reasonable for them to sometimes be zero.
  872. stats.mInco = mInco or 1
  873. stats.eInco = eInco or 1
  874. stats.mCurr = mCurr or 1
  875. stats.mStor = mStor or 1
  876. stats.eCurr = eCurr or 1
  877. stats.eStor = eStor or 1
  878.  
  879. return playerTeamStatsCache[teamID]
  880. end
  881.  
  882. --Damage Begin
  883. local function GetTeamStatsHistory(teamID)
  884. if amSpec or Spring.AreTeamsAllied(localTeam,teamID) then
  885. local idx = Spring.GetTeamStatsHistory(localTeam)
  886. return Spring.GetTeamStatsHistory(teamID,idx)[1]
  887. else
  888. local d = { damageDealt = 0, damageReceived = 0 }
  889. return d
  890. end
  891. end
  892. --Damage END
  893.  
  894. -- ceasefire button tooltip
  895. local function CfTooltip(allyTeam)
  896. local tooltip = ''
  897.  
  898. tooltip = tooltip .. 'Check this box to vote for a ceasefire with '.. yellow ..'<Team ' .. (allyTeam+1) .. '>'..white..'. '
  899. ..'If everyone votes Yes, an offer will be made. If there is a ceasefire, '
  900. ..'unchecking the box will break it.\n\n'
  901.  
  902. tooltip = tooltip .. 'Your team\'s votes: \n'
  903. local teamList = Spring.GetTeamList(localAlliance)
  904. for _,teamID in ipairs(teamList) do
  905. local _,playerID = Spring.GetTeamInfo(teamID)
  906. local name = Spring.GetPlayerInfo(playerID) or '-'
  907. local vote = Spring.GetTeamRulesParam(teamID, 'cf_vote_' ..allyTeam)==1 and green..'Y'..white or red..'N'..white
  908. local teamColor = color2incolor(Spring.GetTeamColor(teamID))
  909. tooltip = tooltip .. teamColor .. ' <' .. name .. '> ' .. white.. vote .. '\n'
  910. end
  911.  
  912. if Spring.GetGameRulesParam('cf_' .. localAlliance .. '_' .. allyTeam) == 1 then
  913. tooltip = tooltip .. '\n\n' .. green .. 'Ceasefire in effect.' .. white
  914. else
  915. local theyOffer = Spring.GetGameRulesParam('cf_offer_' .. localAlliance .. '_' .. allyTeam) == 1
  916. local youOffer = Spring.GetGameRulesParam('cf_offer_' .. allyTeam.. '_' .. localAlliance) == 1
  917. if theyOffer then
  918. tooltip = tooltip .. '\n\n' .. yellow .. 'They have offered a ceasefire.' .. white
  919. end
  920. if youOffer then
  921. tooltip = tooltip .. '\n\n' .. cyan .. 'Your team has offered a ceasefire.' .. white
  922. end
  923.  
  924. tooltip = tooltip .. '\n\n' .. red .. 'No ceasefire in effect.' .. white
  925. end
  926.  
  927. return tooltip
  928. end
  929.  
  930.  
  931. local function MakeSpecTooltip()
  932.  
  933. if (not options.show_tooltips.value) or list_size == 4 or (list_size == 3 and #specTeam.roster == 0) then
  934. scroll_cpl.tooltip = nil
  935. return
  936. end
  937.  
  938. local windowTooltip
  939. local players = {}
  940. local spectators = {}
  941.  
  942. local playerlist = Spring.GetPlayerList()
  943. for i=1, #playerlist do
  944. local playerID = playerlist[i]
  945. local name,active,spectator,teamID,allyTeamID,pingTime,cpuUsage,country,rank,customKeys = Spring.GetPlayerInfo(playerID)
  946. local pingCol, cpuCol, pingText, cpuText = FormatPingCpu(pingTime,cpuUsage)
  947. local cpuColChar = GetColorChar(cpuCol)
  948. local pingColChar = GetColorChar(pingCol)
  949. if active and not spectator then
  950. players[#players+1] = { name = name, pingText = pingText, cpuText = cpuText, pingColChar = pingColChar, cpuColChar = cpuColChar }
  951. elseif spectator then
  952. spectators[#spectators+1] = { name = name, pingText = pingText, cpuText = cpuText, pingColChar = pingColChar, cpuColChar = cpuColChar }
  953. end
  954. end
  955.  
  956. table.sort (players, function(a,b)
  957. return a.name:lower() < b.name:lower()
  958. end
  959. )
  960.  
  961. table.sort (spectators, function(a,b)
  962. return a.name:lower() < b.name:lower()
  963. end
  964. )
  965.  
  966. if list_size <= 2 then
  967. windowTooltip = windowTooltip or "PLAYERS"
  968. for i=1, #players do
  969. windowTooltip = windowTooltip .. "\n\t"..players[i].name.."\t"..players[i].cpuColChar..(players[i].cpuText)..'\008' .. "\t"..players[i].pingColChar..(players[i].pingText).."\008"
  970. end
  971. end
  972.  
  973. if #spectators ~= 0 then
  974. windowTooltip = windowTooltip and (windowTooltip .. "\n\n") or ""
  975. windowTooltip = windowTooltip .. "SPECTATORS"
  976. for i=1, #spectators do
  977. windowTooltip = windowTooltip .. "\n\t"..spectators[i].name.."\t"..spectators[i].cpuColChar..(spectators[i].cpuText)..'\008' .. "\t"..spectators[i].pingColChar..(spectators[i].pingText).."\008"
  978. end
  979. end
  980.  
  981. scroll_cpl.tooltip = windowTooltip
  982. end
  983.  
  984. --------------------------------------------------------------------------------
  985. --------------------------------------------------------------------------------
  986.  
  987. local function MakeNewLabel(entity,name,o) -- "o" is for options
  988. -- pass in x, width, caption, textColor
  989. -- pass in any optional params like align
  990. -- pass in anything to override these defaults:
  991. o.y = o.y or (fontsize+1) * row
  992. o.fontsize = o.fontsize or fontsize
  993. o.fontShadow = o.fontShadow or true
  994. o.autosize = o.autosize or false
  995.  
  996. local newLabel = Label:New(o)
  997. entity[name] = newLabel
  998. scroll_cpl:AddChild(newLabel)
  999. end
  1000.  
  1001. local function MakeNewBar(entity,name,o)
  1002. -- pass in x, width, color, value
  1003. -- pass in anything to override these defaults:
  1004. o.y = o.y or ((fontsize+1) * row) + 6
  1005. o.height = o.height or 5
  1006. o.min = o.min or 0
  1007. o.max = o.max or 1
  1008. o.autosize = o.autosize or false
  1009.  
  1010. local newBar = Chili.Progressbar:New(o)
  1011. entity[name] = newBar
  1012. scroll_cpl:AddChild(newBar)
  1013. end
  1014.  
  1015. local function MakeNewIcon(entity,name,o)
  1016. -- pass in x, file
  1017. -- pass in anything to override these defaults:
  1018. o.y = o.y or ((fontsize+1) * row) + 2
  1019. o.width = o.width or fontsize + 3
  1020. o.height = o.height or fontsize + 3
  1021.  
  1022. o.tooltip = options.show_tooltips.value and o.tooltip or nil
  1023.  
  1024. local newIcon = Chili.Image:New(o)
  1025. entity[name] = newIcon
  1026. scroll_cpl:AddChild(newIcon)
  1027. end
  1028.  
  1029. --TeamworkButtons Begin
  1030. local function MakeNewButton(entity,name,o)
  1031. -- pass in x, width, color, value
  1032. -- pass in anything to override these defaults:
  1033. o.y = o.y or ((fontsize+1) * row) + 6
  1034. o.height = o.height or 5
  1035. o.width = o.width or 24
  1036. o.caption = o.caption or ''
  1037. o.fontsize = o.fontsize or fontsize
  1038. o.fontShadow = o.fontShadow or true
  1039. o.autosize = o.autosize or false
  1040. o.backgroundColor = o.backgroundColor or {0,0,0,0}
  1041.  
  1042. local newButton = Button:New(o)
  1043. entity[name] = newButton
  1044. scroll_cpl:AddChild(newButton)
  1045. end
  1046. --TeamworkButtons End
  1047.  
  1048. local function AccumulatePlayerTeamStats(r,s)
  1049. r.eCurr = r.eCurr + s.eCurr
  1050. r.eStor = r.eStor + s.eStor
  1051. r.eInco = r.eInco + s.eInco
  1052. r.mCurr = r.mCurr + s.mCurr
  1053. r.mStor = r.mStor + s.mStor
  1054. r.mInco = r.mInco + s.mInco
  1055. r.mMobs = r.mMobs + s.mMobs
  1056. r.mDefs = r.mDefs + s.mDefs
  1057. end
  1058.  
  1059. --Damage Begin
  1060. local function AccumulatePlayerTeamDamage(rd,sd)
  1061. rd.damageDealt = rd.damageDealt + sd.damageDealt
  1062. rd.damageReceived = rd.damageReceived + sd.damageReceived
  1063. end
  1064. --Damage END
  1065.  
  1066. local function DrawPlayerTeamStats(entity,teamcolor,s,d) --Damage
  1067. if not options.colorResourceStats.value then teamcolor = {.85,.85,.85,1} end
  1068. --Damage Begin
  1069. if options.show_Damage_stats.value then
  1070. MakeNewLabel(entity,"m_cdamageLabel",{x=x_c_damage,width=36,caption = FormatDamageStats(d.damageDealt),textColor = teamcolor,align = 'right',})
  1071. MakeNewLabel(entity,"m_tdamageLabel",{x=x_t_damage,width=36,caption = FormatDamageStats(d.damageReceived),textColor = teamcolor,align = 'right',})
  1072. end
  1073. --Damage END
  1074. if options.show_unit_stats.value then
  1075. MakeNewLabel(entity,"m_mobilesLabel",{x=x_m_mobiles,width=36,caption = FormatMetalStats(s.mMobs,true),textColor = teamcolor,align = 'right',})
  1076. MakeNewLabel(entity,"m_defenseLabel",{x=x_m_defense,width=36,caption = FormatMetalStats(s.mDefs),textColor = teamcolor,align = 'right',})
  1077. end
  1078. if options.show_income_stats.value then
  1079. MakeNewLabel(entity,"m_incomeLabel",{x=x_m_income,width=24,caption = string.format("%." .. (0) .. "f", s.mInco),textColor = teamcolor,align = 'right',})
  1080. MakeNewLabel(entity,"e_incomeLabel",{x=x_e_income,width=24,caption = string.format("%." .. (0) .. "f", s.eInco),textColor = teamcolor,align = 'right',})
  1081. end
  1082. MakeNewBar(entity,"m_fillBar",{x=x_m_fill + 6,width=24,color = {.7,.75,.9,1},value = s.mCurr/s.mStor,})
  1083. MakeNewBar(entity,"e_fillBar",{x=x_e_fill + 2,width=24,color = {1,1,0,1}, value = s.eCurr/s.eStor,})
  1084. end
  1085.  
  1086. --TeamworkButtons Begin
  1087.  
  1088. local function MakePlayerTeamworkButtons(entity,teamcolor)
  1089.  
  1090. local u_SendButtonFunc
  1091. local m_SupportButtonFunc
  1092. local e_SupportButtonFunc
  1093. local m_SendButtonFunc
  1094. local e_SendButtonFunc
  1095.  
  1096. local u_SendButtonCol
  1097.  
  1098. local u_SendButtonTip
  1099. local m_SupportButtonTip
  1100. local e_SupportButtonTip
  1101. local m_SendButtonTip
  1102. local e_SendButtonTip
  1103.  
  1104. if entity.teamID ~= localTeam then
  1105.  
  1106. u_SendButtonFunc = { function(self) ShareUnits(entity.name, entity.teamID) end, }
  1107. m_SupportButtonFunc = { function(self) AddtoSupport(entity, "metal") end, }
  1108. e_SupportButtonFunc = { function(self) AddtoSupport(entity, "energy") end, }
  1109. m_SendButtonFunc = { function(self) SendResources(entity.name, entity.teamID, "metal") end, }
  1110. e_SendButtonFunc = { function(self) SendResources(entity.name, entity.teamID, "energy") end, }
  1111.  
  1112. u_SendButtonCol = {1, 1, 1, 1}
  1113.  
  1114. u_SendButtonTip = 'Double click to share selected units to ' .. entity.name .. '.'
  1115. m_SupportButtonTip = 'Click to Support ' .. entity.name .. '.'
  1116. e_SupportButtonTip = 'Click to Support ' .. entity.name .. '.'
  1117. m_SendButtonTip = 'Double click to share '.. options.send_resources_amount.value ..' metal to ' .. entity.name .. '.'
  1118. e_SendButtonTip = 'Double click to share '.. options.send_resources_amount.value ..' energy to ' .. entity.name .. '.'
  1119.  
  1120. elseif entity.teamID == localTeam then
  1121.  
  1122. u_SendButtonFunc = { function(self) AskForUnits() end, }
  1123. m_SupportButtonFunc = { function(self) end, }
  1124. e_SupportButtonFunc = { function(self) end, }
  1125. m_SendButtonFunc = { function(self) AskForResources("metal") end, }
  1126. e_SendButtonFunc = { function(self) AskForResources("energy") end, }
  1127.  
  1128. u_SendButtonCol = {1, .3, .3, 1}
  1129.  
  1130. u_SendButtonTip = 'Double click to ask for Units.'
  1131. m_SupportButtonTip = ''
  1132. e_SupportButtonTip = ''
  1133. m_SendButtonTip = 'Double click to ask for metal.'
  1134. e_SendButtonTip = 'Double click to ask for energy.'
  1135.  
  1136. end
  1137. MakeNewButton(entity,"u_SendButton",{x = x_share,
  1138. y = (fontsize+1)*(row+0.5)-2.5,
  1139. height = fontsize,
  1140. width = fontsize,
  1141. tooltip = options.show_tooltips.value and u_SendButtonTip,
  1142. padding = {0,0,0,0},
  1143. OnDblClick = u_SendButtonFunc,
  1144. children = {
  1145. Image:New{
  1146. x=0,y=0,
  1147. height='100%',
  1148. width='100%',
  1149. color = u_SendButtonCol,
  1150. file = sharePic,
  1151. },
  1152. },
  1153. })
  1154. if options.show_income_stats.value and entity.teamID ~= localTeam then
  1155. MakeNewButton(entity,"m_SupportButton",{x = x_m_income+5,
  1156. align = 'right',
  1157. tooltip = options.show_tooltips.value and m_SupportButtonTip,
  1158. OnClick = m_SupportButtonFunc,
  1159. })
  1160. MakeNewButton(entity,"e_SupportButton",{x = x_e_income+5,
  1161. align = 'right',
  1162. tooltip = options.show_tooltips.value and e_SupportButtonTip,
  1163. OnClick = e_SupportButtonFunc,
  1164. })
  1165. end
  1166. MakeNewButton(entity,"m_SendButton",{x = x_m_fill + 6,
  1167. tooltip = options.show_tooltips.value and m_SendButtonTip,
  1168. OnDblClick = m_SendButtonFunc,
  1169. })
  1170. MakeNewButton(entity,"e_SendButton",{x = x_e_fill + 2,
  1171. tooltip = options.show_tooltips.value and e_SendButtonTip,
  1172. OnDblClick = e_SendButtonFunc,
  1173. })
  1174. end
  1175.  
  1176. local function MakeListTeamworkButtons(entity,entitygroup,TeamList)
  1177. local ClickFunc
  1178. if amSpec then
  1179. MakeNewButton(entity,"WatchButton",{x = x_name,
  1180. width = name_width,
  1181. tooltip = options.show_tooltips.value and 'View ' .. entitygroup .. '.',
  1182. OnClick = { function(self) ViewTeam(TeamList) end, }
  1183. })
  1184. else
  1185. if entitygroup == "team" then
  1186. ClickFunc = AddTeamtoSupport
  1187. elseif entitygroup == "clan" then
  1188. ClickFunc = AddClantoSupport
  1189. end
  1190. MakeNewButton(entity,entitygroup.."ChatButton",{x = x_name,
  1191. width = name_width,
  1192. tooltip = options.show_tooltips.value and 'Chat with your Team.',
  1193. OnClick = { function(self) ChatwithTeam() end, }
  1194. })
  1195. if options.show_income_stats.value then
  1196. MakeNewButton(ListSupportButton,entitygroup.."metal",{x = x_m_income+5,
  1197. align = 'right',
  1198. tooltip = options.show_tooltips.value and 'Click to Support '..entitygroup..' Members with metal',
  1199. OnClick = { function(self) ClickFunc(entity, "metal") end, },
  1200. })
  1201. MakeNewButton(ListSupportButton,entitygroup.."energy",{x = x_e_income+5,
  1202. align = 'right',
  1203. tooltip = options.show_tooltips.value and 'Click to Support '..entitygroup..' Members with energy',
  1204. OnClick = { function(self) ClickFunc(entity, "energy") end, },
  1205. })
  1206. end
  1207. end
  1208. end
  1209. --TeamworkButtons END
  1210.  
  1211. local function UpdatePlayerTeamStats(entity,s,d) --Damage
  1212. if entity.m_mobilesLabel then entity.m_mobilesLabel:SetCaption(FormatMetalStats(s.mMobs,true)) end
  1213. if entity.m_defenseLabel then entity.m_defenseLabel:SetCaption(FormatMetalStats(s.mDefs)) end
  1214. --Damage Begin
  1215. if entity.m_cdamageLabel then entity.m_cdamageLabel:SetCaption(FormatDamageStats(d.damageDealt)) end
  1216. if entity.m_tdamageLabel then entity.m_tdamageLabel:SetCaption(FormatDamageStats(d.damageReceived)) end
  1217. --Damage END
  1218. if entity.m_incomeLabel then entity.m_incomeLabel:SetCaption(string.format("%." .. (0) .. "f", s.mInco)) end
  1219. if entity.e_incomeLabel then entity.e_incomeLabel:SetCaption(string.format("%." .. (0) .. "f", s.eInco)) end
  1220. if entity.m_fillBar then entity.m_fillBar:SetValue(s.mCurr/s.mStor) end
  1221. if entity.e_fillBar then entity.e_fillBar:SetValue(s.eCurr/s.eStor) end
  1222. end
  1223.  
  1224. --------------------------------------------------------------------------------
  1225. --------------------------------------------------------------------------------
  1226.  
  1227. local function UpdatePingCpu(entity,pingTime,cpuUsage,pstatus)
  1228. pingTime = pingTime or 0
  1229. cpuUsage = cpuUsage or 0
  1230. if pstatus == 'gone' then
  1231. pingTime = 0
  1232. cpuUsage = 0
  1233. end
  1234. local pingCol, cpuCol, pingText, cpuText = FormatPingCpu(pingTime,cpuUsage)
  1235. if options.cpu_ping_as_text.value then
  1236. if entity.cpuLabel then entity.cpuLabel.font:SetColor(cpuCol) ; entity.cpuLabel:SetCaption(cpuText) end
  1237. if entity.pingLabel then entity.pingLabel.font:SetColor(pingCol) ; entity.pingLabel:SetCaption(pingText) end
  1238. else
  1239. if entity.cpuImg then
  1240. entity.cpuImg.color = cpuCol
  1241. if options.show_tooltips.value then entity.cpuImg.tooltip = ('CPU: ' .. cpuText) end
  1242. entity.cpuImg:Invalidate()
  1243. end
  1244. if entity.pingImg then
  1245. entity.pingImg.color = pingCol
  1246. if options.show_tooltips.value then entity.pingImg.tooltip = ('Ping: ' .. pingText) end
  1247. entity.pingImg:Invalidate()
  1248. end
  1249. end
  1250. end
  1251.  
  1252. --Clan Begin
  1253. local function updateresourcetotals(allyListEntities, allyEntities)
  1254. if allyListEntities then
  1255. for k,v in pairs(allyListEntities) do
  1256. local r = { eCurr = 0, eStor = 0, eInco = 0, mCurr = 0, mStor = 0, mInco = 0, mMobs = 0, mDefs = 0 }
  1257. local rd = { damageDealt = 0, damageReceived = 0} --Damage
  1258. if allyEntities[k] then
  1259. for j=1,#allyEntities[k] do
  1260. local teamID = allyEntities[k][j]
  1261. if teamID then
  1262. local s = GetPlayerTeamStats(teamID)
  1263. AccumulatePlayerTeamStats(r,s)
  1264. --Damage Begin
  1265. local d = GetTeamStatsHistory(teamID)
  1266. AccumulatePlayerTeamDamage(rd,d)
  1267. --Damage END
  1268. end
  1269. end
  1270. end
  1271. UpdatePlayerTeamStats(v,r,rd)
  1272. end
  1273. end
  1274. end
  1275. --Clan END
  1276.  
  1277. -- updates as needed: status, name, ping, cpu, resource stats, etc.
  1278. local function UpdatePlayerInfo()
  1279. for i=1,#entities do
  1280. local teamID
  1281. if entities[i].isAI then
  1282. teamID = entities[i].teamID
  1283. Support(teamID) --Support
  1284. else
  1285. local playerID = entities[i].playerID
  1286. local name,active,spectator,localteamID,allyTeamID,pingTime,cpuUsage = Spring.GetPlayerInfo(playerID)
  1287. teamID = localteamID
  1288. local teamcolor = teamID and {Spring.GetTeamColor(teamID)} or {1,1,1,1}
  1289.  
  1290. -- status (player status and team status)
  1291. local pstatus = nil
  1292. local tstatus = ''
  1293. local tstatuscolor = {1,1,1,1}
  1294.  
  1295. if not active then
  1296. if Spring.GetGameSeconds() < 0.1 or cpuUsage > 1 then tstatus = '?' ; tstatuscolor = teamcolor
  1297. else pstatus = 'gone'
  1298. end
  1299. elseif spectator and (teamID ~= 0 or teamZeroPlayers[playerID]) then
  1300. pstatus = 'spec'
  1301. end
  1302.  
  1303. if pstatus == 'spec' or pstatus == 'gone' then
  1304. if Spring.GetTeamUnitCount(teamID) > 0 then
  1305. tstatus = '!!'
  1306. tstatuscolor = {1,1,0,1}
  1307. else
  1308. tstatus = 'X'
  1309. tstatuscolor = {1,0,0,1}
  1310. end
  1311. end
  1312.  
  1313. local displayname
  1314. local whitestring = GetColorChar({1,1,1,1})
  1315. local greystring = GetColorChar({.5,.5,.5,1})
  1316. local teamcolorstring = GetColorChar(teamcolor)
  1317. -- these were part of a failed experiment that I might try to fix later
  1318.  
  1319. if pstatus == 'spec' then displayname = (" ss: " .. name)
  1320. elseif pstatus == 'gone' then displayname = (" xx: " .. name)
  1321. else displayname = (name)
  1322. end
  1323.  
  1324. if entities[i].nameLabel then entities[i].nameLabel:SetCaption(displayname) end
  1325. if entities[i].statusLabel then entities[i].statusLabel:SetCaption(tstatus) ; entities[i].statusLabel.font:SetColor(tstatuscolor) end
  1326.  
  1327. UpdatePingCpu(entities[i],pingTime,cpuUsage,pstatus)
  1328.  
  1329. if pstatus ~= 'spec' and pstatus ~= 'gone' then Support(teamID) end --Support
  1330.  
  1331. end -- if not isAI
  1332. -- update the resource stats for all entities, including AIs
  1333. local s = GetPlayerTeamStats(teamID)
  1334. local d = GetTeamStatsHistory(teamID)
  1335. UpdatePlayerTeamStats(entities[i],s,d)
  1336. end -- for entities
  1337.  
  1338. -- update ping and cpu for the spectators
  1339. if #specTeam.roster ~= 0 then
  1340. for i = 1,#specTeam.roster do
  1341. local playerID = specTeam.roster[i].playerID
  1342. local name,active,spectator,localteamID,allyTeamID,pingTime,cpuUsage = Spring.GetPlayerInfo(playerID)
  1343. specTeam.roster[i].pingTime = pingTime
  1344. specTeam.roster[i].cpuUsage = cpuUsage
  1345. if list_size == 4 then
  1346. UpdatePingCpu(specTeam.roster[i],pingTime,cpuUsage)
  1347. end
  1348. end
  1349. end
  1350. MakeSpecTooltip()
  1351.  
  1352. for allyTeam, cb in pairs(cfCheckBoxes) do
  1353. cb.tooltip = CfTooltip(allyTeam)
  1354. end
  1355.  
  1356. --Clan Begin
  1357. -- update resource totals for allyTeams and allyClans
  1358. updateresourcetotals(allyTeamEntities, allyTeams)
  1359. updateresourcetotals(allyClanEntities, allyClans)
  1360. --Clan ENd
  1361. end
  1362.  
  1363. --------------------------------------------------------------------------------
  1364. --------------------------------------------------------------------------------
  1365.  
  1366. local function AddTableHeaders()
  1367. if cf then
  1368. scroll_cpl:AddChild( Label:New{ x=x_cf, y=(fontsize+1) * row, caption = 'CF', fontShadow = true, fontsize = fontsize, } )
  1369. end
  1370. --Damage Begin
  1371. if options.show_Damage_stats.value then
  1372. scroll_cpl:AddChild( Image:New{ x=x_c_damage - 10, y=((fontsize+1) * row) + 3, height = (fontsize)+1, file = 'LuaUI/Images/commands/Bold/settarget.png',} )
  1373. scroll_cpl:AddChild( Image:New{ x=x_t_damage - 7, y=((fontsize+1) * row) + 3, height = (fontsize)+1, file = 'LuaUI/Images/commands/Bold/health.png',} )
  1374. end
  1375. --Damage END
  1376. if options.show_unit_stats.value then
  1377. scroll_cpl:AddChild( Image:New{ x=x_m_mobiles - 10, y=((fontsize+1) * row) + 3, height = (fontsize)+1, color = {1, .3, .3, 1}, file = 'LuaUI/Images/commands/Bold/attack.png',} )
  1378. scroll_cpl:AddChild( Image:New{ x=x_m_defense - 7, y=((fontsize+1) * row) + 3, height = (fontsize)+1, color = {.3, .3, 1, 1}, file = 'LuaUI/Images/commands/Bold/guard.png',} )
  1379. end
  1380. if options.show_income_stats.value then
  1381. scroll_cpl:AddChild( Image:New{ x=x_e_income - 15, y=((fontsize+1) * row) + 3, height = (fontsize)+1, file = 'LuaUI/Images/energy.png',} )
  1382. scroll_cpl:AddChild( Image:New{ x=x_m_income - 15, y=((fontsize+1) * row) + 3, height = (fontsize)+1, file = 'LuaUI/Images/ibeam.png',} )
  1383. end
  1384. scroll_cpl:AddChild( Label:New{ x=x_cpu, y=(fontsize+1) * row, caption = 'C', fontShadow = true, fontsize = fontsize,} )
  1385. scroll_cpl:AddChild( Label:New{ x=x_ping, y=(fontsize+1) * row, caption = 'P', fontShadow = true, fontsize = fontsize,} )
  1386. end
  1387.  
  1388. local function AddCfCheckbox(allyTeam)
  1389. if cf and allyTeam ~= -1 and allyTeam ~= localAlliance then
  1390. local cfCheck = Checkbox:New{
  1391. x=x_cf,y=(fontsize+1) * row + 3,width=20,
  1392. caption='',
  1393. checked = Spring.GetTeamRulesParam(localTeam, 'cf_vote_' ..allyTeam)==1,
  1394. tooltip = CfTooltip(allyTeam),
  1395. OnChange = { function(self)
  1396. Spring.SendLuaRulesMsg('ceasefire:'.. (self.checked and 'n' or 'y') .. allyTeam)
  1397. self.tooltip = CfTooltip(allyTeam)
  1398. end },
  1399. }
  1400. scroll_cpl:AddChild(cfCheck)
  1401. cfCheckBoxes[allyTeam] = cfCheck
  1402. end
  1403. end
  1404.  
  1405. -- adds all the entity information
  1406. local function AddEntity(entity, teamID, allyTeamID)
  1407. local teamcolor = (teamID and teamID ~= -1) and {Spring.GetTeamColor(teamID)} or {1,1,1,1}
  1408.  
  1409. if entity.isAI then
  1410. MakeNewLabel(entity,"nameLabel",{x=x_name,width=name_width,caption = entity.name,textColor = teamcolor,})
  1411.  
  1412. else
  1413.  
  1414. -- clan/faction emblems, level, country, elo
  1415. local icon = nil
  1416. local icRank = nil
  1417. local elo = nil
  1418. local eloCol = nil
  1419. local icCountry = entity.country and entity.country ~= '' and entity.country ~= '??' and "LuaUI/Images/flags/" .. (entity.country) .. ".png" or nil
  1420. if options.show_ccr.value then
  1421. if entity.clan and entity.clan ~= "" then
  1422. icon = "LuaUI/Configs/Clans/" .. entity.clan ..".png"
  1423. elseif entity.faction and entity.faction ~= "" then
  1424. icon = "LuaUI/Configs/Factions/" .. entity.faction ..".png"
  1425. end
  1426. if entity.level and entity.level ~= "" then
  1427. icRank = "LuaUI/Images/Ranks/" .. math.min((1+math.floor((entity.level or 0)/10)),9) .. ".png"
  1428. end
  1429. if icCountry then MakeNewIcon(entity,"countryIcon",{x=x_icon_country,file=icCountry,}) end
  1430. if options.rank_as_text.value then
  1431. if entity.level then MakeNewLabel(entity,"rankLabel",{x=x_icon_rank,width=14,caption = math.min(entity.level,99),textColor = {0.85,0.85,0.85,1},align = 'right',}) end
  1432. else
  1433. if icRank then MakeNewIcon(entity,"rankIcon",{x=x_icon_rank,file=icRank,}) end
  1434. end
  1435. if icon then MakeNewIcon(entity,"clanIcon",{x=x_icon_clan,file=icon,y=((fontsize+1)*row)+5,width=fontsize-1,height=fontsize-1}) end
  1436. end
  1437. if entity.elo and entity.elo ~= "" then
  1438. elo, eloCol = FormatElo(entity.elo)
  1439. end
  1440. if elo then MakeNewLabel(entity,"eloLabel",{x=x_elo,caption = elo,textColor = eloCol,}) end
  1441.  
  1442. -- status (player status and team status)
  1443. local pstatus = nil
  1444. local tstatus = ''
  1445. local tstatuscolor = {1,1,1,1}
  1446.  
  1447. if teamID ~= -1 then
  1448. if not entity.isActive then
  1449. if Spring.GetGameSeconds() < 0.1 or entity.cpuUsage > 1 then tstatus = '?' ; tstatuscolor = teamcolor
  1450. else pstatus = 'gone'
  1451. end
  1452. elseif entity.isSpec and (teamID ~= 0 or teamZeroPlayers[entity.playerID]) then
  1453. pstatus = 'spec'
  1454. end
  1455. end
  1456.  
  1457. if pstatus == 'spec' or pstatus == 'gone' then
  1458. if Spring.GetTeamUnitCount(teamID) > 0 then
  1459. tstatus = '!!'
  1460. tstatuscolor = {1,1,0,1}
  1461. else
  1462. tstatus = 'X'
  1463. tstatuscolor = {1,0,0,1}
  1464. end
  1465. end
  1466.  
  1467. MakeNewLabel(entity,"statusLabel",{x=x_status,width=16,caption = tstatus,textColor = tstatuscolor,})
  1468.  
  1469. -- name, including player status designators
  1470. local displayname
  1471. local whitestring = GetColorChar({1,1,1,1})
  1472. local greystring = GetColorChar({.5,.5,.5,1})
  1473. local teamcolorstring = GetColorChar(teamcolor)
  1474. -- these were part of a failed experiment that I might try to fix later
  1475.  
  1476. if pstatus == 'spec' then displayname = (" ss: " .. entity.name)
  1477. elseif pstatus == 'gone' then displayname = (" xx: " .. entity.name)
  1478. else displayname = (entity.name)
  1479. end
  1480.  
  1481.  
  1482. MakeNewLabel(entity,"nameLabel",{x=x_name,width=name_width,caption = displayname,textColor = teamcolor,})
  1483.  
  1484. --View Begin
  1485. if teamID ~= -1 and amSpec and(teams[teamID] and (teams[teamID].isPlaying and not teams[teamID].isDead)) then
  1486. MakeNewButton(entity,"WatchButton",{x = x_name,
  1487. width = name_width,
  1488. tooltip = options.show_tooltips.value and 'View ' .. entity.name ..'.',
  1489. textColor = teamcolor,
  1490. OnClick = { function(self) ViewTeam({ entity.teamID }) end, }
  1491. })
  1492. end
  1493. --View END
  1494. --Chat Begin
  1495. if teamID ~= -1 and not amSpec and (teams[teamID] and (teams[teamID].isPlaying and not teams[teamID].isDead)) and allyTeamID == localAlliance and teamID ~= localTeam then
  1496. MakeNewButton(entity,"ChatButton",{x = x_name,
  1497. width = name_width,
  1498. tooltip = options.show_tooltips.value and "Chat with " .. entity.name,
  1499. textColor = teamcolor,
  1500. OnClick = { function(self) ChatwithUser(entity.name) end, }
  1501. })
  1502. end
  1503. --Chat END
  1504.  
  1505. if teamID == localTeam then end
  1506.  
  1507. -- ping and cpu icons / labels
  1508. local pingCol, cpuCol, pingText, cpuText = FormatPingCpu(pstatus == 'gone' and 0 or entity.pingTime,pstatus == 'gone' and 0 or entity.cpuUsage)
  1509. if options.cpu_ping_as_text.value then
  1510. MakeNewLabel(entity,"cpuLabel",{x=x_cpu,width = (fontsize+3)*10/16,caption = cpuText,textColor = cpuCol,align = 'right',})
  1511. MakeNewLabel(entity,"pingLabel",{x=x_ping,width = (fontsize+3)*10/16,caption = pingText,textColor = pingCol,align = 'right',})
  1512. else
  1513. MakeNewIcon(entity,"cpuImg",{x=x_cpu,file=cpuPic,width = (fontsize+3)*10/16,keepAspect = false,tooltip = 'CPU: ' .. cpuText,})
  1514. MakeNewIcon(entity,"pingImg",{x=x_ping,file=pingPic,width = (fontsize+3)*10/16,keepAspect = false,tooltip = 'Ping: ' .. pingText,})
  1515. entity.cpuImg.color = cpuCol
  1516. entity.pingImg.color = pingCol
  1517. function entity.cpuImg:HitTest(x,y) return self end
  1518. function entity.pingImg:HitTest(x,y) return self end
  1519. end
  1520.  
  1521. end -- if not isAI
  1522.  
  1523. -- mobile and defense metal, metal and energy income, resource bars
  1524. if teamID ~= -1 and (allyTeamID == localAlliance or amSpec) then
  1525. local s = GetPlayerTeamStats(teamID)
  1526. local d = GetTeamStatsHistory(teamID)
  1527. DrawPlayerTeamStats(entity,teamcolor,s,d)
  1528. end
  1529.  
  1530. --TeamworkButtons Begin
  1531. if teamID ~= -1 and not amSpec and (teams[teamID] and (teams[teamID].isPlaying and not teams[teamID].isDead)) and allyTeamID == localAlliance then
  1532. MakePlayerTeamworkButtons(entity,teamcolor)
  1533. end
  1534. --TeamworkButtons END
  1535.  
  1536. row = row + 1
  1537. end
  1538.  
  1539. local function AddTeamSummarie(allyTeamID)
  1540. local allyTeamResources
  1541. local allyTeamDamage
  1542. if allyTeams[allyTeamID] then
  1543. for j=1,#allyTeams[allyTeamID] do
  1544. local teamID = allyTeams[allyTeamID][j]
  1545. if teamID then
  1546. local s = GetPlayerTeamStats(teamID)
  1547. allyTeamResources = allyTeamResources or {}
  1548. allyTeamResources[allyTeamID] = allyTeamResources[allyTeamID] or { eCurr = 0, eStor = 0, eInco = 0, mCurr = 0, mStor = 0, mInco = 0, mMobs = 0, mDefs = 0 }
  1549. AccumulatePlayerTeamStats(allyTeamResources[allyTeamID],s)
  1550. --Damage BEGIN
  1551. local d = GetTeamStatsHistory(teamID)
  1552. allyTeamDamage = allyTeamDamage or {}
  1553. allyTeamDamage[allyTeamID] = allyTeamDamage[allyTeamID] or { damageDealt = 0, damageReceived = 0 }
  1554. AccumulatePlayerTeamDamage(allyTeamDamage[allyTeamID],d)
  1555. --Damage END
  1556. end
  1557. end
  1558. end
  1559. if allyTeamResources and allyTeamDamage then --Damage
  1560. if allyTeamResources[allyTeamID] and allyTeamDamage[allyTeamID] and allyTeams[allyTeamID] then --Damage
  1561. allyTeamEntities[allyTeamID] = allyTeamEntities[allyTeamID] or {}
  1562. local allyTeamColor
  1563. local elo
  1564. local eloCol
  1565. if allyTeamsElo[allyTeamID] then
  1566. elo, eloCol = FormatElo(allyTeamsElo[allyTeamID].total / allyTeamsElo[allyTeamID].count, true)
  1567. end
  1568. if (localTeam ~= 0 or teamZeroPlayers[myID]) and allyTeamID == localAlliance then
  1569. allyTeamColor = {Spring.GetTeamColor(localTeam)}
  1570. else
  1571. allyTeamColor = {Spring.GetTeamColor(allyTeams[allyTeamID][1])}
  1572. end
  1573. if options.show_ccr.value then
  1574. MakeNewLabel(allyTeamEntities[allyTeamID],"nameLabel",{x=x_icon_clan,width=150,caption = ("TEAM " .. allyTeamID+1 .. "."),textColor = allyTeamColor,})
  1575. LabelCaption = "Overall:"
  1576. else
  1577. LabelCaption = "Team " .. allyTeamID+1 .. ". Overall:"
  1578. end
  1579. MakeNewLabel(allyTeamEntities[allyTeamID],"nameLabel",{x=x_name,width=150,caption = LabelCaption,textColor = allyTeamColor,})
  1580. DrawPlayerTeamStats(allyTeamEntities[allyTeamID],allyTeamColor,allyTeamResources[allyTeamID],allyTeamDamage[allyTeamID]) --Damage
  1581. MakeListTeamworkButtons(allyTeamEntities[allyTeamID],"team",allyTeams[allyTeamID])
  1582. if elo then MakeNewLabel(allyTeamEntities[allyTeamID],"eloLabel",{x=x_elo,caption = elo,textColor = eloCol,}) end
  1583. if allyTeamsDead[allyTeamID] then MakeNewLabel(allyTeamEntities[allyTeamID],"statusLabel",{x=x_status,width=16,caption = "X",textColor = {1,0,0,1},}) end
  1584. row = row + 1
  1585. end
  1586. end
  1587. end
  1588.  
  1589. local function AddTeamSummarieNonSpec(allyTeamID)
  1590. if allyTeams[allyTeamID] then
  1591. allyTeamEntities[allyTeamID] = allyTeamEntities[allyTeamID] or {}
  1592. local allyTeamColor
  1593. local elo
  1594. local eloCol
  1595. local LabelX
  1596. if allyTeamsElo[allyTeamID] then
  1597. elo, eloCol = FormatElo(allyTeamsElo[allyTeamID].total / allyTeamsElo[allyTeamID].count, true)
  1598. end
  1599. if (localTeam ~= 0 or teamZeroPlayers[myID]) and allyTeamID == localAlliance then
  1600. allyTeamColor = {Spring.GetTeamColor(localTeam)}
  1601. else
  1602. allyTeamColor = {Spring.GetTeamColor(allyTeams[allyTeamID][1])}
  1603. end
  1604. if options.show_ccr.value then LabelX = x_icon_clan else LabelX = x_name end
  1605. MakeNewLabel(allyTeamEntities[allyTeamID],"nameLabel",{x=LabelX,width=150,caption = ("TEAM " .. allyTeamID+1 .. ":"),textColor = allyTeamColor,})
  1606. if elo then MakeNewLabel(allyTeamEntities[allyTeamID],"eloLabel",{x=x_elo,caption = elo,textColor = eloCol,}) end
  1607. if allyTeamsDead[allyTeamID] then MakeNewLabel(allyTeamEntities[allyTeamID],"statusLabel",{x=x_status,width=16,caption = "X",textColor = {1,0,0,1},}) end
  1608. row = row + 1
  1609. end
  1610. end
  1611.  
  1612. local function AddClanSummarie(allyTeamID)
  1613. local allyClanResources
  1614. local allyClanDamage
  1615. if allyClans[allyTeamID] then
  1616. for j=1,#allyClans[allyTeamID] do
  1617. local teamID = allyClans[allyTeamID][j]
  1618. if teamID then
  1619. local s = GetPlayerTeamStats(teamID)
  1620. allyClanResources = allyClanResources or {}
  1621. allyClanResources[allyTeamID] = allyClanResources[allyTeamID] or { eCurr = 0, eStor = 0, eInco = 0, mCurr = 0, mStor = 0, mInco = 0, mMobs = 0, mDefs = 0 }
  1622. AccumulatePlayerTeamStats(allyClanResources[allyTeamID],s)
  1623. --Damage BEGIN
  1624. local d = GetTeamStatsHistory(teamID)
  1625. allyClanDamage = allyClanDamage or {}
  1626. allyClanDamage[allyTeamID] = allyClanDamage[allyTeamID] or { damageDealt = 0, damageReceived = 0 }
  1627. AccumulatePlayerTeamDamage(allyClanDamage[allyTeamID],d)
  1628. --Damage END
  1629. end
  1630. end
  1631. end
  1632. if allyClanResources and allyClanDamage then --Damage
  1633. if allyClanResources[allyTeamID] and allyClanDamage[allyTeamID] and allyClans[allyTeamID] then --Damage
  1634. allyClanEntities[allyTeamID] = allyClanEntities[allyTeamID] or {}
  1635. local allyTeamColor
  1636. local elo
  1637. local eloCol
  1638. local LabelCaption
  1639. if allyClansElo[allyTeamID] then
  1640. elo, eloCol = FormatElo(allyClansElo[allyTeamID].total / allyClansElo[allyTeamID].count, true)
  1641. end
  1642. if (localTeam ~= 0 or teamZeroPlayers[myID]) and allyTeamID == localAlliance then
  1643. allyTeamColor = {Spring.GetTeamColor(localTeam)}
  1644. else
  1645. allyTeamColor = {Spring.GetTeamColor(allyClans[allyTeamID][1])}
  1646. end
  1647. if options.show_ccr.value then
  1648. MakeNewLabel(allyClanEntities[allyTeamID],"nameLabel",{x=x_icon_clan,width=150,caption = ("CLAN " .. allyTeamID+1 .. "."),textColor = allyTeamColor,})
  1649. LabelCaption = "Overall:"
  1650. else
  1651. LabelCaption = "CLAN " .. allyTeamID+1 .. ". Overall:"
  1652. end
  1653. MakeNewLabel(allyClanEntities[allyTeamID],"nameLabel",{x=x_name,width=150,caption = LabelCaption,textColor = allyTeamColor,})
  1654. DrawPlayerTeamStats(allyClanEntities[allyTeamID],allyTeamColor,allyClanResources[allyTeamID],allyClanDamage[allyTeamID]) --Damage
  1655. MakeListTeamworkButtons(allyClanEntities[allyTeamID],"clan",allyClans[allyTeamID])
  1656. if elo then MakeNewLabel(allyClanEntities[allyTeamID],"eloLabel",{x=x_elo,caption = elo,textColor = eloCol,}) end
  1657. if allyTeamsDead[allyTeamID] then MakeNewLabel(allyClanEntities[allyTeamID],"statusLabel",{x=x_status,width=16,caption = "X",textColor = {1,0,0,1},}) end
  1658. row = row + 1
  1659. end
  1660. end
  1661. end
  1662.  
  1663. local function AddClanSummarieNonSpec(allyTeamID)
  1664. if allyClans[allyTeamID] then
  1665. allyClanEntities[allyTeamID] = allyClanEntities[allyTeamID] or {}
  1666. local allyTeamColor
  1667. local elo
  1668. local eloCol
  1669. local LabelX
  1670. if allyClansElo[allyTeamID] then
  1671. elo, eloCol = FormatElo(allyClansElo[allyTeamID].total / allyClansElo[allyTeamID].count, true)
  1672. end
  1673. if (localTeam ~= 0 or teamZeroPlayers[myID]) and allyTeamID == localAlliance then
  1674. allyTeamColor = {Spring.GetTeamColor(localTeam)}
  1675. else
  1676. allyTeamColor = {Spring.GetTeamColor(allyClans[allyTeamID][1])}
  1677. end
  1678. if options.show_ccr.value then LabelX = x_icon_clan else LabelX = x_name end
  1679. MakeNewLabel(allyClanEntities[allyTeamID],"nameLabel",{x=LabelX,width=150,caption = ("CLAN " .. allyTeamID+1 .. "."),textColor = allyTeamColor,})
  1680. if elo then MakeNewLabel(allyClanEntities[allyTeamID],"eloLabel",{x=x_elo,caption = elo,textColor = eloCol,}) end
  1681. if allyTeamsDead[allyTeamID] then MakeNewLabel(allyClanEntities[allyTeamID],"statusLabel",{x=x_status,width=16,caption = "X",textColor = {1,0,0,1},}) end
  1682. row = row + 1
  1683. end
  1684. end
  1685.  
  1686. local function AlignScrollPanel()
  1687. local height = math.ceil(row * (fontsize+1.5) + 8)
  1688. scroll_cpl.height = math.min(height, window_cpl.height)
  1689. if not (options.alignToTop.value) then
  1690. scroll_cpl.y = (window_cpl.height) - scroll_cpl.height
  1691. else
  1692. scroll_cpl.y = 0
  1693. end
  1694. end
  1695.  
  1696. -- sort each allyteam's list of playerteams:
  1697. -- own pteam first, then by elo of the first player on the pteam, and alphabetically otherwise
  1698. -- dead pteams (even your own) come after alive pteams
  1699. -- dead pteams whose first player is speccing come before dead pteams whose first player is gone
  1700. local function sorteachteamlist(allyEntitiesSorted, allyEntities)
  1701. for i=1,#allyEntitiesSorted do -- for every ally team
  1702. local allyTeamID = allyEntitiesSorted[i]
  1703. if allyEntities[allyTeamID] then
  1704. table.sort (allyEntities[allyTeamID], function(a,b)
  1705. if (teams[a].isDead or not teams[a].isPlaying) and not (teams[b].isDead or not teams[b].isPlaying) then return false end
  1706. if (teams[b].isDead or not teams[b].isPlaying) and not (teams[a].isDead or not teams[a].isPlaying) then return true end
  1707. if (teams[a].isDead or not teams[a].isPlaying) and (teams[b].isDead or not teams[b].isPlaying) then
  1708. if teams[a].roster[1].isActive and not teams[b].roster[1].isActive then return true end
  1709. if teams[b].roster[1].isActive and not teams[a].roster[1].isActive then return false end
  1710. end
  1711. if localTeam ~= 0 or teamZeroPlayers[myID] then
  1712. if a == localTeam then return true end
  1713. if b == localTeam then return false end
  1714. end
  1715. if teams[a].roster[1].elo and teams[b].roster[1].elo then
  1716. return teams[a].roster[1].elo > teams[b].roster[1].elo
  1717. end
  1718. return a > b
  1719. end
  1720. )
  1721. end
  1722. end
  1723. end
  1724.  
  1725. -- add the player entities
  1726. local function addplayerentities(allyEntities, allyTeamID, alreadyadded)
  1727. if allyEntities[allyTeamID] and (list_size >= 3 or allyTeamID == localAlliance) then
  1728. AddCfCheckbox(allyTeamID)
  1729. for i=1,#allyEntities[allyTeamID] do -- for every player team on the ally team
  1730. local teamID = allyEntities[allyTeamID][i]
  1731. if alreadyadded then
  1732. if not TableFind(teamID, allyClans[allyTeamID]) then
  1733. if teams[teamID] and teams[teamID].roster and (list_size >= 2 or teamID == localTeam) then
  1734. for k=1,#teams[teamID].roster do -- for every player on the player team
  1735. AddEntity(teams[teamID].roster[k], teamID, allyTeamID)
  1736. end
  1737. end
  1738. end
  1739. else
  1740. if teams[teamID] and teams[teamID].roster and (list_size >= 2 or teamID == localTeam) then
  1741. for k=1,#teams[teamID].roster do -- for every player on the player team
  1742. AddEntity(teams[teamID].roster[k], teamID, allyTeamID)
  1743. end
  1744. end
  1745. end
  1746. end
  1747. end
  1748. end
  1749.  
  1750. SetupPlayerNames = function()
  1751. entities = {}
  1752. teams = {}
  1753. allyTeams = {}
  1754. allyTeamsElo = {}
  1755. --Clan Begin
  1756. allyClans = {}
  1757. allyClansElo = {}
  1758. --Clan END
  1759. specTeam = {roster = {}}
  1760. playerTeamStatsCache = {}
  1761.  
  1762. fontsize = options.text_height.value
  1763. scroll_cpl:ClearChildren()
  1764.  
  1765. local playerlist = Spring.GetPlayerList()
  1766. local teamsSorted = Spring.GetTeamList()
  1767. local allyTeamsSorted = Spring.GetAllyTeamList()
  1768. local allyClanSorted = {}
  1769.  
  1770.  
  1771. list_size = options.list_size.value or 3
  1772. if not (localTeam ~= 0 or teamZeroPlayers[myID]) then
  1773. if list_size == 1 then list_size = 0 end
  1774. if list_size == 2 then list_size = 3 end
  1775. end
  1776.  
  1777. -- register any AIs as entities, assign teams to allyTeams
  1778. for i=1,#teamsSorted do
  1779. local teamID = teamsSorted[i]
  1780. if teamID ~= Spring.GetGaiaTeamID() then
  1781. teams[teamID] = teams[teamID] or {roster = {}}
  1782. local _,leader,isDead,isAI,_,allyTeamID = Spring.GetTeamInfo(teamID)
  1783. if isAI then
  1784. local skirmishAIID, name, hostingPlayerID, shortName, version, options = Spring.GetAIInfo(teamID)
  1785. name = '<'.. name ..'> '.. shortName
  1786. local entityID = #entities + 1
  1787. entities[entityID] = {name = name, teamID = teamID, isAI = true}
  1788. local index = #teams[teamID].roster + 1
  1789. teams[teamID].roster[index] = entities[entityID]
  1790. teams[teamID].isPlaying = true
  1791. end
  1792. teams[teamID].leader = leader
  1793. allyTeams[allyTeamID] = allyTeams[allyTeamID] or {}
  1794. allyTeams[allyTeamID][#allyTeams[allyTeamID]+1] = teamID
  1795. if isDead then
  1796. teams[teamID].isDead = true
  1797. end
  1798. end --if teamID ~= Spring.GetGaiaTeamID()
  1799. end --for each team
  1800.  
  1801.  
  1802. -- go through all players, register as entities, assign to teams
  1803. -- also store the data needed later to calculate the team average elo
  1804. for i=1, #playerlist do
  1805. local playerID = playerlist[i]
  1806. local name,active,spectator,teamID,allyTeamID,pingTime,cpuUsage,country,rank,customKeys = Spring.GetPlayerInfo(playerID)
  1807. local clan, faction, level, elo
  1808. if customKeys then
  1809. clan = customKeys.clan
  1810. faction = customKeys.faction
  1811. level = customKeys.level
  1812. elo = customKeys.elo
  1813. end
  1814. if teamID == 0 and not spectator then
  1815. teamZeroPlayers[playerID] = true
  1816. end
  1817. if teamID ~= 0 or teamZeroPlayers[playerID] then
  1818. local entityID = #entities + 1
  1819. entities[entityID] = {
  1820. playerID = playerID,
  1821. name = name,
  1822. isActive = active,
  1823. isSpec = spectator,
  1824. teamID = teamID,
  1825. pingTime = pingTime,
  1826. cpuUsage = cpuUsage,
  1827. country = country,
  1828. rank = rank,
  1829. clan = clan,
  1830. faction = faction,
  1831. level = level,
  1832. elo = elo,
  1833. }
  1834. local index = #teams[teamID].roster + 1
  1835. teams[teamID].roster[index] = entities[entityID]
  1836. if not (spectator or (not active and Spring.GetGameSeconds() > 0.1 and cpuUsage < 1)) then
  1837. teams[teamID].isPlaying = true
  1838. if allyTeamID and elo then
  1839. if allyTeamsElo[allyTeamID] then
  1840. allyTeamsElo[allyTeamID].total = allyTeamsElo[allyTeamID].total + elo
  1841. allyTeamsElo[allyTeamID].count = allyTeamsElo[allyTeamID].count + 1
  1842. else
  1843. allyTeamsElo[allyTeamID] = { ["total"] = elo, ["count"] = 1}
  1844. end
  1845. end
  1846. --Clan Begin
  1847. if allyTeamID and clan == myClan then
  1848. if not TableFind(allyTeamID, allyClanSorted) then
  1849. allyClanSorted[#allyClanSorted+1] = allyTeamID
  1850. end
  1851. allyClans[allyTeamID] = allyClans[allyTeamID] or {}
  1852. allyClans[allyTeamID][#allyClans[allyTeamID]+1] = teamID
  1853. if allyClansElo[allyTeamID] then
  1854. allyClansElo[allyTeamID].total = allyClansElo[allyTeamID].total + elo
  1855. allyClansElo[allyTeamID].count = allyClansElo[allyTeamID].count + 1
  1856. else
  1857. allyClansElo[allyTeamID] = { ["total"] = elo, ["count"] = 1}
  1858. end
  1859. end
  1860. --Clan End
  1861. end
  1862. end
  1863.  
  1864. if spectator and active then
  1865. specTeam.roster[#(specTeam.roster) + 1] = {
  1866. playerID = playerID,
  1867. name = name,
  1868. isActive = active,
  1869. isSpec = spectator,
  1870. teamID = teamID,
  1871. pingTime = pingTime,
  1872. cpuUsage = cpuUsage,
  1873. country = country,
  1874. rank = rank,
  1875. clan = clan,
  1876. faction = faction,
  1877. level = level,
  1878. elo = elo,
  1879. }
  1880. end
  1881.  
  1882. end
  1883.  
  1884. -- sort each playerteam's roster: self first, then by elo, and alphabetically otherwise
  1885. for i=1,#teams do
  1886. if teams[i].roster then
  1887. table.sort (teams[i].roster, function(a,b)
  1888. if localTeam ~= 0 or teamZeroPlayers[myID] then
  1889. if a.playerID == myID then return true end
  1890. if b.playerID == myID then return false end
  1891. end
  1892. return a.elo > b.elo
  1893. end
  1894. )
  1895. end
  1896. end
  1897.  
  1898. --Clan Begin
  1899. sorteachteamlist(allyTeamsSorted, allyTeams)
  1900. sorteachteamlist(allyClanSorted, allyClans)
  1901. --Caln End
  1902.  
  1903. -- if we haven't ever done so before, build the ally team sort order
  1904. -- ally teams are sorted by total elo, so larger teams will be above smaller teams
  1905. -- ally team sort order is determined at the very start, and doesn't change even if
  1906. -- the team composition changes (except that dead teams will fall to the bottom)
  1907. --
  1908. -- while we're at it, determine whether or not to show the ally team summary lines
  1909. --
  1910. if #allyTeamOrderRank == 0 then
  1911. if #allyTeams[localAlliance] > 2 then myTeamIsVeryBig = true end
  1912. for i=1,#allyTeamsSorted do -- for every ally team
  1913. local allyTeamID = allyTeamsSorted[i]
  1914. allyTeamOrderRank[allyTeamID] = 0
  1915. if allyTeams[allyTeamID] then
  1916. if #allyTeams[allyTeamID] > 2 then existsVeryBigTeam = true end
  1917. if #allyTeams[allyTeamID] > 1 then numBigTeams = numBigTeams + 1 end
  1918. for j=1,#allyTeams[allyTeamID] do -- for every player team on the ally team
  1919. local teamID = allyTeams[allyTeamID][j]
  1920. if teams[teamID] and teams[teamID].roster then
  1921. for k=1,#teams[teamID].roster do -- for every player on the player team
  1922. if teams[teamID].roster[k].elo then allyTeamOrderRank[allyTeamID] = allyTeamOrderRank[allyTeamID] + teams[teamID].roster[k].elo end
  1923. end
  1924. end
  1925. end
  1926. end
  1927. end
  1928. end
  1929. --Clan Begin
  1930. if #allyClanOrderRank == 0 then
  1931. if allyClans[localAlliance] then
  1932. if #allyClans[localAlliance] > 1 then myClanIsVeryBig = true end
  1933. for i=1,#allyClanSorted do -- for every ally team
  1934. local allyTeamID = allyClanSorted[i]
  1935. allyClanOrderRank[allyTeamID] = 0
  1936. if allyClans[allyTeamID] then
  1937. if #allyClans[allyTeamID] > 1 then existsVeryBigClan = true end --Have to be diffrent extra var
  1938. if #allyClans[allyTeamID] > 1 then numBigClan = numBigClan + 1 end --here too
  1939. for j=1,#allyClans[allyTeamID] do -- for every player team on the ally team
  1940. local teamID = allyClans[allyTeamID][j]
  1941. if teams[teamID] and teams[teamID].roster then
  1942. for k=1,#teams[teamID].roster do -- for every player on the player team
  1943. if teams[teamID].roster[k].elo then allyClanOrderRank[allyTeamID] = allyClanOrderRank[allyTeamID] + teams[teamID].roster[k].elo end
  1944. end
  1945. end
  1946. end
  1947. end
  1948. end
  1949. end
  1950. end
  1951. --Clan End
  1952.  
  1953. -- find out which ally teams are dead
  1954. allyTeamsDead = {}
  1955. for i=1,#allyTeamsSorted do -- for every ally team
  1956. local allyTeamID = allyTeamsSorted[i]
  1957. allyTeamsDead[allyTeamID] = true
  1958. if allyTeams[allyTeamID] then
  1959. for j=1,#allyTeams[allyTeamID] do -- for every player team on the ally team
  1960. local teamID = allyTeams[allyTeamID][j]
  1961. if teams[teamID] and not (teams[teamID].isDead or not teams[teamID].isPlaying) then
  1962. allyTeamsDead[allyTeamID] = nil
  1963. end
  1964. end
  1965. end
  1966. end
  1967.  
  1968. --Clan Begin
  1969. allyClanDead = {}
  1970. for i=1,#allyClanSorted do
  1971. local allyTeamID = allyClanSorted[i]
  1972. allyClanDead[allyTeamID] = true
  1973. if allyClans[allyTeamID] then
  1974. for j=1,#allyClans[allyTeamID] do -- for every player team on the ally team
  1975. local teamID = allyTeams[allyTeamID][j]
  1976. if teams[teamID] and not (teams[teamID].isDead or not teams[teamID].isPlaying) then
  1977. allyClanDead[allyTeamID] = nil
  1978. end
  1979. end
  1980. end
  1981. end
  1982. --Clan END
  1983.  
  1984. -- sort allyteams: own at top, others in order by total elo, dead teams at bottom
  1985. table.sort(allyTeamsSorted, function(a,b)
  1986. if allyTeamsDead[a] and not allyTeamsDead[b] then return false end
  1987. if allyTeamsDead[b] and not allyTeamsDead[a] then return true end
  1988. if allyTeamsDead[b] and allyTeamsDead[a] and allyTeams[a] and allyTeams[b] then
  1989. local teamIDa = allyTeams[a][1]
  1990. local teamIDb = allyTeams[b][1]
  1991. if teamIDa and teamIDb and teams[teamIDa].roster and teams[teamIDb].roster then
  1992. if teams[teamIDa].roster[1].isActive and not teams[teamIDb].roster[1].isActive then return true end
  1993. if teams[teamIDb].roster[1].isActive and not teams[teamIDa].roster[1].isActive then return false end
  1994. end
  1995. end
  1996. if localTeam ~= 0 or teamZeroPlayers[myID] then
  1997. if a == localAlliance then return true end
  1998. if b == localAlliance then return false end
  1999. end
  2000. return allyTeamOrderRank[a] > allyTeamOrderRank[b]
  2001. end
  2002. )
  2003.  
  2004. -- Clan Begin
  2005. table.sort(allyClanSorted, function(a,b)
  2006. if allyClanDead[a] and not allyClanDead[b] then return false end
  2007. if allyClanDead[b] and not allyClanDead[a] then return true end
  2008. if allyClanDead[b] and allyClanDead[a] and allyClans[a] and allyClans[b] then
  2009. local teamIDa = allyClans[a][1]
  2010. local teamIDb = allyClans[b][1]
  2011. if teamIDa and teamIDb and teams[teamIDa].roster and teams[teamIDb].roster then
  2012. if teams[teamIDa].roster[1].isActive and not teams[teamIDb].roster[1].isActive then return true end
  2013. if teams[teamIDb].roster[1].isActive and not teams[teamIDa].roster[1].isActive then return false end
  2014. end
  2015. end
  2016. if localTeam ~= 0 or teamZeroPlayers[myID] then
  2017. if a == localAlliance then return true end
  2018. if b == localAlliance then return false end
  2019. end
  2020. return allyClanOrderRank[a] > allyClanOrderRank[b]
  2021. end
  2022. )
  2023. --Clan END
  2024.  
  2025. -- sort the specteam
  2026. table.sort(specTeam.roster, function(a,b)
  2027. return a.name:lower() < b.name:lower()
  2028. end)
  2029.  
  2030. row = 0
  2031. AddTableHeaders()
  2032. row = row + 1
  2033.  
  2034. -- Clan Begin
  2035. local clanmebers = false
  2036. if list_size ~= 0 then
  2037. if amSpec then
  2038. if options.showSummaries.value and (existsVeryBigTeam or numBigTeams > 2) then
  2039. for i=1,#allyTeamsSorted do
  2040. local allyTeamID = allyTeamsSorted[i]
  2041. AddTeamSummarie(allyTeamID)
  2042. row = row + 0.2
  2043. if options.showClanSummaries.value and allyClans[allyTeamID] and #allyClans[allyTeamID] > 1 then
  2044. AddClanSummarie(allyTeamID)
  2045. row = row + 0.2
  2046. clanmebers = true
  2047. addplayerentities(allyClans, allyTeamID, false)
  2048. row = row + 0.4
  2049. end
  2050. if allyTeams[allyTeamID] then
  2051. addplayerentities(allyTeams, allyTeamID, clanmebers)
  2052. end
  2053. if i ~= (#allyTeamsSorted-1) then
  2054. row = row + 0.5
  2055. end
  2056. end
  2057. else
  2058. for i=1,#allyTeamsSorted do -- for every ally team
  2059. local allyTeamID = allyTeamsSorted[i]
  2060. if allyTeams[allyTeamID] then
  2061. addplayerentities(allyTeams, allyTeamID, clanmebers)
  2062. if numBigTeams > 2 then row = row + 0.6 end
  2063. end
  2064. end
  2065. end
  2066. else
  2067. if options.showSummaries.value and myTeamIsVeryBig then
  2068. --AddTeamSummarie({localTeam})
  2069. AddTeamSummarie(localAlliance)
  2070. row = row + 0.2
  2071. if options.showClanSummaries.value and allyClans[localAlliance] and #allyClans[localAlliance] > 1 then
  2072. AddClanSummarie(localAlliance)
  2073. row = row + 0.2
  2074. clanmebers = true
  2075. addplayerentities(allyClans, localAlliance, false)
  2076. row = row + 0.4
  2077. end
  2078. if allyTeams[localAlliance] then
  2079. addplayerentities(allyTeams, localAlliance, clanmebers)
  2080. end
  2081. clanmebers = false
  2082. row = row + 0.5
  2083. for i=1,#allyTeamsSorted do
  2084. if localAlliance ~= allyTeamsSorted[i] then
  2085. local allyTeamID = allyTeamsSorted[i]
  2086. AddTeamSummarieNonSpec(allyTeamID)
  2087. row = row + 0.2
  2088. if options.showClanSummaries.value and allyClans[allyTeamID] and #allyClans[allyTeamID] > 1 then
  2089. AddClanSummarieNonSpec(allyTeamID)
  2090. row = row + 0.2
  2091. clanmebers = true
  2092. addplayerentities(allyClans, allyTeamID, false)
  2093. row = row + 0.4
  2094. end
  2095. if allyTeams[allyTeamID] then
  2096. addplayerentities(allyTeams, allyTeamID, clanmebers)
  2097. end
  2098. clanmebers = false
  2099. if i ~= (#allyTeamsSorted-1) then
  2100. row = row + 0.5
  2101. end
  2102. end
  2103. end
  2104. else
  2105. for i=1,#allyTeamsSorted do -- for every ally team
  2106. local allyTeamID = allyTeamsSorted[i]
  2107. if allyTeams[allyTeamID] then
  2108. addplayerentities(allyTeams, allyTeamID, clanmebers)
  2109. if numBigTeams > 2 then row = row + 0.6 end
  2110. end
  2111. end
  2112. end
  2113. end
  2114. end
  2115. -- Clan END
  2116.  
  2117. -- add the spectator entities
  2118. if list_size == 4 and #specTeam.roster ~= 0 then
  2119. teams[-1] = specTeam
  2120. allyTeams[-1] = {-1}
  2121. for k=1,#specTeam.roster do
  2122. AddEntity(specTeam.roster[k], -1, -1)
  2123. end
  2124. end
  2125. MakeSpecTooltip()
  2126.  
  2127. -- ceasefire: restricted zones button
  2128. if cf then
  2129. scroll_cpl:AddChild( Checkbox:New{
  2130. x=5, y=(fontsize+1) * (row + 0.5),
  2131. height=fontsize * 1.5, width=160,
  2132. caption = 'Place Restricted Zones',
  2133. checked = WG.rzones.rZonePlaceMode,
  2134. OnChange = { function(self) WG.rzones.rZonePlaceMode = not WG.rzones.rZonePlaceMode; end },
  2135. } )
  2136. row = row + 1.5
  2137. end
  2138. AlignScrollPanel()
  2139. end
  2140.  
  2141. SetupScrollPanel = function ()
  2142. if scroll_cpl then scroll_cpl:Dispose() end
  2143. local scpl = {
  2144. parent = window_cpl,
  2145. --width = "100%",
  2146. --height = "100%",
  2147. backgroundColor = {1,1,1,options.backgroundOpacity.value},
  2148. borderColor = {1,1,1,options.backgroundOpacity.value},
  2149. padding = {0, 5, 0, 5},
  2150. --autosize = true,
  2151. --right = 0,
  2152. scrollbarSize = 6,
  2153. width = x_bound,
  2154. horizontalScrollbar = false,
  2155. hitTestAllowEmpty = true,
  2156. noMouseWheel = not options.mousewheel.value,
  2157. }
  2158. if options.alignToLeft.value then
  2159. scpl.left = 0
  2160. else
  2161. scpl.right = 0
  2162. end
  2163. scroll_cpl = ScrollPanel:New(scpl)
  2164. SetupPlayerNames()
  2165. end
  2166.  
  2167. SetupPanels = function ()
  2168.  
  2169. CalculateWidths()
  2170. local x,y,height,width
  2171. if window_cpl then
  2172. y = window_cpl.y
  2173. height = window_cpl.height
  2174. width = math.max(x_windowbound, lastChosenSizeX)
  2175. x = options.alignToLeft.value and window_cpl.x or (window_cpl.x + window_cpl.width - width)
  2176. window_cpl:Dispose()
  2177. else
  2178. x = screen0.width - x_windowbound
  2179. y = screen0.height - 150
  2180. width = x_windowbound
  2181. height = 150
  2182. end
  2183. lastSizeX = width
  2184.  
  2185. window_cpl = Window:New{
  2186. dockable = true,
  2187. name = "Player List",
  2188. color = {0,0,0,0},
  2189. x = x,
  2190. y = y,
  2191. width = width,
  2192. height = height,
  2193. padding = {0, 0, 0, 0};
  2194. parent = screen0,
  2195. draggable = false,
  2196. resizable = false,
  2197. tweakDraggable = true,
  2198. tweakResizable = true,
  2199. minimizable = false,
  2200. minWidth = x_windowbound,
  2201. OnMouseDown={ function(self)
  2202. local alt, ctrl, meta, shift = Spring.GetModKeyState()
  2203. if not meta then return false end
  2204. WG.crude.OpenPath(options_path)
  2205. WG.crude.ShowMenu()
  2206. return true
  2207. end },
  2208. }
  2209.  
  2210. SetupScrollPanel()
  2211.  
  2212. end
  2213.  
  2214. function ToggleVisibility()
  2215. if window_cpl and scroll_cpl then
  2216. if options.visible.value then
  2217. window_cpl:AddChild(scroll_cpl)
  2218. else
  2219. window_cpl:RemoveChild(scroll_cpl)
  2220. end
  2221. end
  2222. end
  2223.  
  2224. function PlayersChanged()
  2225. if amSpec then
  2226. SetupPlayerNames()
  2227. else
  2228. local _,_,amNowSpec = Spring.GetPlayerInfo(myID)
  2229. if amNowSpec then
  2230. amSpec = amNowSpec
  2231. SetupPanels()
  2232. else
  2233. SetupPlayerNames()
  2234. end
  2235. end
  2236. end
  2237.  
  2238. --------------------------------------------------------------------------------
  2239. --------------------------------------------------------------------------------
  2240.  
  2241. function widget:Shutdown()
  2242. Spring.SendCommands({"info 1"})
  2243. end
  2244.  
  2245. -- Part of an experiment to try to improve performance, will come back to it later
  2246. -- local updateModulus = 8
  2247. -- local updateCount = 0
  2248.  
  2249. function widget:Update(s)
  2250. timer = timer + s
  2251. if timer > UPDATE_FREQUENCY then
  2252. timer = 0
  2253. if (lastSizeX ~= window_cpl.width or lastSizeY ~= window_cpl.height) then --//if user resize the player-list
  2254. AlignScrollPanel()
  2255. lastChosenSizeX = window_cpl.width
  2256. lastSizeX = window_cpl.width
  2257. lastSizeY = window_cpl.height
  2258. else
  2259. -- for i=updateCount+1,#playerTeamStatsCache,updateModulus do
  2260. -- playerTeamStatsCache[i] = nil
  2261. -- end
  2262. -- updateCount = (updateCount + 1) % updateModulus
  2263. if (not scroll_cpl.parent) then return end --//don't update when window is hidden
  2264. UpdatePlayerInfo()
  2265. end
  2266. end
  2267. end
  2268.  
  2269. function widget:PlayerChanged(playerID)
  2270. PlayersChanged()
  2271. end
  2272.  
  2273. function widget:PlayerAdded(playerID)
  2274. PlayersChanged()
  2275. end
  2276.  
  2277. function widget:PlayerRemoved(playerID)
  2278. PlayersChanged()
  2279. end
  2280.  
  2281. function widget:TeamDied(teamID)
  2282. PlayersChanged()
  2283. end
  2284.  
  2285. function widget:TeamChanged(teamID)
  2286. PlayersChanged()
  2287. end
  2288.  
  2289. -- workaround for stupidity
  2290. function widget:GameStart()
  2291. SetupPanels()
  2292. end
  2293.  
  2294. -----------------------------------------------------------------------
  2295. -- we need both UnitCreated and UnitFinished because mobiles and static defense aren't treated the same >:<
  2296. function widget:UnitCreated(unitID, unitDefID, unitTeam)
  2297. local speed = UnitDefs[unitDefID].speed
  2298. local unarmed = UnitDefs[unitDefID].springCategories.unarmed
  2299. if (speed == nil or speed == 0) and not unarmed then -- is static-d
  2300. ProcessUnit(unitID, unitDefID, unitTeam)
  2301. end
  2302. end
  2303.  
  2304. function widget:UnitFinished(unitID, unitDefID, unitTeam)
  2305. local speed = UnitDefs[unitDefID].speed
  2306. local unarmed = UnitDefs[unitDefID].springCategories.unarmed
  2307. if speed and speed ~= 0 and (not finishedUnits[unitID]) then -- mobile unit
  2308. ProcessUnit(unitID, unitDefID, unitTeam)
  2309. end
  2310. end
  2311.  
  2312. function widget:UnitDestroyed(unitID, unitDefID, unitTeam)
  2313. local speed = UnitDefs[unitDefID].speed
  2314. local unarmed = UnitDefs[unitDefID].springCategories.unarmed
  2315. if speed and speed ~= 0 then -- mobile unit
  2316. if finishedUnits[unitID] then
  2317. ProcessUnit(unitID, unitDefID, unitTeam, true)
  2318. end
  2319. elseif not unarmed then -- static defense
  2320. ProcessUnit(unitID, unitDefID, unitTeam, true)
  2321. end
  2322. end
  2323.  
  2324. function widget:UnitGiven(unitID, unitDefID, newTeamID, teamID)
  2325. -- doing this twice is a bit inefficient but bah
  2326. ProcessUnit(unitID, unitDefID, teamID, true)
  2327. ProcessUnit(unitID, unitDefID, newTeamID)
  2328. end
  2329.  
  2330. -----------------------------------------------------------------------
  2331.  
  2332. function widget:Initialize()
  2333. if (not WG.Chili) then
  2334. widgetHandler:RemoveWidget()
  2335. return
  2336. end
  2337.  
  2338. Chili = WG.Chili
  2339. Image = Chili.Image
  2340. Button = Chili.Button
  2341. Checkbox = Chili.Checkbox
  2342. Window = Chili.Window
  2343. ScrollPanel = Chili.ScrollPanel
  2344. StackPanel = Chili.StackPanel
  2345. Label = Chili.Label
  2346. screen0 = Chili.Screen0
  2347. color2incolor = Chili.color2incolor
  2348. incolor2color = Chili.incolor2color
  2349.  
  2350. green = color2incolor(0,1,0,1)
  2351. red = color2incolor(1,0,0,1)
  2352. orange = color2incolor(1,0.4,0,1)
  2353. yellow = color2incolor(1,1,0,1)
  2354. cyan = color2incolor(0,1,1,1)
  2355. white = color2incolor(1,1,1,1)
  2356.  
  2357. SetupPanels()
  2358.  
  2359. Spring.SendCommands({"info 0"})
  2360. lastSizeX = window_cpl.width
  2361. lastSizeY = window_cpl.height
  2362.  
  2363. self:LocalColorRegister()
  2364. end
  2365.  
  2366. function widget:Shutdown()
  2367. self:LocalColorUnregister()
  2368. end
  2369.  
  2370. function widget:LocalColorRegister()
  2371. if WG.LocalColor and WG.LocalColor.RegisterListener then
  2372. WG.LocalColor.RegisterListener(widget:GetInfo().name, SetupPlayerNames)
  2373. end
  2374. end
  2375.  
  2376. function widget:LocalColorUnregister()
  2377. if WG.LocalColor and WG.LocalColor.UnregisterListener then
  2378. WG.LocalColor.UnregisterListener(widget:GetInfo().name)
  2379. end
  2380. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement