Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --------------------------------------------------------------------------------
- --------------------------------------------------------------------------------
- function widget:GetInfo()
- return {
- name = "Chili Deluxe Player List - MOD",
- desc = "v0.202 Chili Deluxe Player List, Alpha Release",
- author = "CarRepairer, KingRaptor, CrazyEddie, MoriturusMortus",
- date = "2012-06-30",
- license = "GNU GPL, v2 or later",
- layer = 50,
- enabled = false,
- --detailsDefault = 1
- -- based on v1.31 Chili Crude Player List by CarRepairer, KingRaptor, et al
- }
- end
- --[[
- TODO:
- * Fast-and-Easy switching between large and small views, and between a single view hidden or shown
- * More granular control over which columns are displayed, and how (text vs. icons, etc)
- * More and better tooltips, and options for controlling whether and how they are displayed
- * Scaling x-axis dimensions proportionally with the fontsize
- * Profiling and improving performance
- * Tons of minor bugfixes, cosmetic enhancements, and code cleanup
- --]]
- --------------------------------------------------------------------------------
- --------------------------------------------------------------------------------
- function SetupPlayerNames() end
- function ToggleVisibility() end
- local echo = Spring.Echo
- local spGetUnitIsStunned = Spring.GetUnitIsStunned
- local Chili
- local Image
- local Button
- local Checkbox
- local Window
- local ScrollPanel
- local StackPanel
- local Label
- local screen0
- local color2incolor
- local incolor2color
- --------------------------------------------------------------------------------
- --------------------------------------------------------------------------------
- local window_cpl, scroll_cpl
- options_path = 'Settings/HUD Panels/PlayerList'
- 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',
- options = {
- visible = {
- name = "Visible",
- type = 'bool',
- value = true,
- desc = "Set a hotkey here to toggle the playerlist on and off",
- OnChange = function() ToggleVisibility() end,
- },
- backgroundOpacity = {
- name = "Background Opacity",
- type = "number",
- value = 0.5, min = 0, max = 1, step = 0.01,
- OnChange = function(self)
- scroll_cpl.backgroundColor = {1,1,1,self.value}
- scroll_cpl:Invalidate()
- end,
- },
- text_height = {
- name = 'Font Size (10-14)',
- type = 'number',
- value = 13,
- min=10,max=14,step=1,
- OnChange = function() SetupPanels() end,
- advanced = true
- },
- name_width = {
- name = 'Name Width (50-200)',
- type = 'number',
- value = 120,
- min=50,max=200,step=10,
- OnChange = function() SetupPanels() end,
- advanced = true
- },
- mousewheel = {
- name = "Scroll with mousewheel",
- type = 'bool',
- value = false,
- OnChange = function(self) scroll_cpl.noMouseWheel = not self.value; end,
- },
- alignToTop = {
- name = "Align to top",
- type = 'bool',
- value = true,
- desc = "Align to top and grow downwards (vs. align to bottom and grow upwards)",
- OnChange = function() SetupPlayerNames() end,
- },
- alignToLeft = {
- name = "Align to left",
- type = 'bool',
- value = false,
- desc = "Align to left and grow rightwards (vs. align to right and grow leftwards)",
- OnChange = function() SetupScrollPanel() end,
- },
- showSummaries = {
- name = "Show team summaries",
- type = 'bool',
- value = true,
- desc = "Display summary information for each team (note: even with this checked, summaries won't be displayed if all the teams are very small)",
- OnChange = function() SetupPlayerNames() end,
- },
- --Clan Begin
- showClanSummaries = {
- name = "Show MyClan summaries",
- type = 'bool',
- value = true,
- desc = "Display summary information for your Clan",
- OnChange = function() SetupPlayerNames() end,
- },
- --Clan End
- --Damage Begin
- show_Damage_stats = {
- name = "Show Damage summaries",
- type = 'bool',
- value = true,
- desc = "Display Damage statistics: dealt and taken damage.",
- OnChange = function() SetupPanels() end,
- },
- --Damage End
- show_unit_stats = {
- name = "Show unit stats",
- type = 'bool',
- value = true,
- desc = "Display resource statistics: metal in mobile units and static defenses.",
- OnChange = function() SetupPanels() end,
- },
- show_income_stats = {
- name = "Show income stats",
- type = 'bool',
- value = true,
- desc = "Display resource statistics: metal and energy income.",
- OnChange = function() SetupPanels() end,
- },
- --Support Begin
- --[[
- support_ally_floor = {
- name = 'Support: ally floor (1-500)',
- type = 'number',
- value = 50,
- desc = "Determine ally minimum threshold, cross the threshold = send resource.",
- min=1,max=500,step=10,
- OnChange = function() SetupPanels() end,
- advanced = true
- },
- ]]--
- support_my_Ceiling = {
- name = 'Support: my ceiling (10-5000)',
- type = 'number',
- value = 250,
- desc = "Determine your maximum threshold, cross the threshold = send resource.",
- min=10,max=5000,step=10,
- OnChange = function() SetupPanels() end,
- advanced = true
- },
- --Support End
- --ShareResources Begin
- send_resources_amount = {
- name = 'Resources send on double click (10-500)',
- type = 'number',
- value = 50,
- desc = "Amount of resources to be send on double click",
- min=10,max=500,step=10,
- OnChange = function() SetupPanels() end,
- advanced = true
- },
- --ShareResources END
- colorResourceStats = {
- name = "Show stats in color",
- type = 'bool',
- value = false,
- desc = "Display resource statistics such as unit metal and income in each player's color (vs. white)",
- OnChange = function() SetupPlayerNames() end,
- },
- show_ccr = {
- name = "Show clan/country/rank",
- type = 'bool',
- value = true,
- desc = "Show the clan, country, and rank columns",
- OnChange = function() SetupPanels() end,
- },
- rank_as_text = {
- name = "Show rank as text",
- type = 'bool',
- value = false,
- desc = "Show rank as text (vs. as an icon)",
- OnChange = function() SetupPlayerNames() end,
- },
- --Elo Begin
- round_elo = {
- name = "Round elo",
- type = 'bool',
- value = true,
- desc = "Round elo",
- OnChange = function() SetupPanels() end,
- },
- --Elo End
- cpu_ping_as_text = {
- name = "Show ping/cpu as text",
- type = 'bool',
- value = false,
- desc = "Show ping and cpu stats as text (vs. as an icon)",
- OnChange = function() SetupPanels() end,
- },
- show_tooltips = {
- name = "Show tooltips",
- type = 'bool',
- value = true,
- desc = "Show tooltips where available (vs. hiding all tooltips)",
- OnChange = function() SetupPanels() end,
- },
- list_size = {
- name = 'List Size: Who should be included?',
- type = 'list',
- value = 3,
- items = {
- { key = 0, name = "Nobody" },
- { key = 1, name = "Just you" },
- { key = 2, name = "Just your team" },
- { key = 3, name = "All players" },
- { key = 4, name = "All players and spectators" },
- },
- OnChange = function() SetupPlayerNames() end,
- },
- }
- local name_width
- local green = ''
- local red = ''
- local orange = ''
- local yellow = ''
- local cyan = ''
- local white = ''
- local function IsFFA()
- local allyteams = Spring.GetAllyTeamList()
- local gaiaT = Spring.GetGaiaTeamID()
- local gaiaAT = select(6, Spring.GetTeamInfo(gaiaT))
- local numAllyTeams = 0
- for i=1,#allyteams do
- if allyteams[i] ~= gaiaAT then
- local teams = Spring.GetTeamList()
- if #teams > 0 then
- numAllyTeams = numAllyTeams + 1
- end
- end
- end
- return numAllyTeams > 2
- end
- -- The ceasefire functionality isn't working right now.
- -- I'm leaving all the code in place, but disabling the buttons.
- -- Someone can come back in and fix it later.
- --
- -- local cf = IsFFA()
- local cf = false
- local localTeam = 0
- local localAlliance = 0
- local myID
- local myName
- local amSpec
- local myClan --Clan
- myID = Spring.GetMyPlayerID()
- myName,_,amSpec,_,_,_,_,_,_,CKeys = Spring.GetPlayerInfo(myID)
- --Clan Begin
- if CKeys then
- myClan = CKeys.clan
- end
- myClan = myClan or "<No Clan>"
- --Clan END
- localTeam = Spring.GetMyTeamID()
- localAlliance = Spring.GetMyAllyTeamID()
- -- This is awkward, but it's okay for now.
- -- I'll make it elegant when I implement x-scaling with fontsize
- --
- local x_icon_clan
- local x_icon_country
- local x_icon_rank
- local x_elo
- local x_cf
- local x_status
- local x_name
- local x_share
- local x_m_mobiles
- local x_m_defense
- local x_c_damage
- local x_t_damage
- local x_m_income
- local x_e_income
- local x_m_fill
- local x_e_fill
- local x_cpu
- local x_ping
- local x_postping
- local x_bound
- local x_windowbound
- local function CalculateWidths()
- name_width = options.name_width.value or 120
- x_icon_clan = 10
- x_icon_country = x_icon_clan + 18
- x_icon_rank = x_icon_country + 20
- x_elo = options.show_ccr.value and x_icon_rank + 16 or x_icon_clan
- x_cf = x_elo + 32
- x_status = cf and x_cf + 20 or x_cf
- x_name = x_status + 12
- x_share = x_name + name_width
- --Damage Begin
- x_c_damage = not amSpec and x_share + 12 or x_share
- x_t_damage = x_c_damage + 36
- --Damage End
- x_m_mobiles = options.show_Damage_stats.value and x_t_damage + 40 or x_c_damage
- x_m_defense = x_m_mobiles + 34
- x_m_income = options.show_unit_stats.value and x_m_defense + 40 or x_m_mobiles
- x_e_income = x_m_income + 30
- x_m_fill = options.show_income_stats.value and x_e_income + 26 or x_m_income
- x_e_fill = x_m_fill + 30
- x_cpu = x_e_fill + (options.cpu_ping_as_text.value and 52 or 30)
- x_ping = x_cpu + (options.cpu_ping_as_text.value and 46 or 16)
- x_bound = x_ping + 28
- x_windowbound = x_bound + 0
- end
- CalculateWidths()
- local UPDATE_FREQUENCY = 0.8 -- seconds
- local cfCheckBoxes = {}
- local allyTeams = {} -- [id] = {team1, team2, ...}
- local allyClans = {}
- local teams = {} -- [id] = {leaderName = name, roster = {entity1, entity2, ...}}
- local teamZeroPlayers = {}
- -- entity = player (including specs) or bot
- -- ordered list; contains isAI, isSpec, playerID, teamID, name, namelabel, cpuImg, pingImg
- local entities = {}
- local allyTeamEntities = {}
- local allyTeamOrderRank = {}
- local allyTeamsDead = {}
- local allyTeamsElo = {}
- local playerTeamStatsCache = {}
- local finishedUnits = {}
- local numBigTeams = 0
- local existsVeryBigTeam = nil
- local myTeamIsVeryBig = nil
- local specTeam = {roster = {}}
- local CausedDamageList = {}
- local TakenDamageList = {}
- --Clan Begin
- local allyClanEntities = {}
- local allyClanOrderRank = {}
- local allyClanDead = {}
- local existsVeryBigClan = nil
- local myClanIsVeryBig = nil
- local numBigClan = 0
- --Clan END
- local sharePic = ":n:"..LUAUI_DIRNAME.."Images/playerlist/share.png"
- local cpuPic = ":n:"..LUAUI_DIRNAME.."Images/playerlist/cpu.png"
- local pingPic = ":n:"..LUAUI_DIRNAME.."Images/playerlist/ping.png"
- local row
- local fontsize
- local list_size
- local timer = 0
- local lastSizeX
- local lastSizeY
- local lastChosenSizeX = 0
- include("keysym.h.lua")
- --------------------------------------------------------------------------------
- --------------------------------------------------------------------------------
- local function TableFind(f, l)
- if f == nil or l == nil then
- return false
- else
- local count = 0
- for _, v in ipairs(l) do
- count = count + 1
- if f == v then
- return count
- end
- end
- end
- return false
- end
- --Chat Begin
- local function ChatwithUser(playername)
- Spring.SendCommands("ChatAll","pastetext /w "..playername..' \1')
- end
- local function ChatwithTeam()
- Spring.SendCommands("ChatAlly","pastetext \1")
- end
- --Chat END
- --View Begin
- --Code taken from the Team View lua script created by BoredJoe
- local function ViewTeam(TeamList)
- local averagex = 0
- local averagey = 0
- local averagez = 0
- local count = 0
- for i=1,#TeamList do
- local teamID = TeamList[i]
- for _,unitID in ipairs(Spring.GetAllUnits()) do
- UnitTeamID = Spring.GetUnitTeam(unitID)
- if UnitTeamID == teamID then
- local x, y, z = Spring.GetUnitPosition(unitID)
- averagex = (averagex + x)
- averagey = (averagey + y)
- averagez = (averagez + z)
- count = (count + 1)
- end
- end
- end
- averagex = averagex / count
- averagey = averagey / count
- averagez = averagez / count
- if count ~= 0 then
- Spring.SetCameraTarget(averagex, averagey, averagez)
- end
- end
- --View END
- local function ShareUnits(playername, team)
- local selcnt = Spring.GetSelectedUnitsCount()
- if selcnt > 0 then
- Spring.SendCommands("say a: I gave "..selcnt.." units to "..playername..".")
- Spring.ShareResources(team, "units")
- else
- echo 'Player List: No units selected to share.'
- end
- end
- local function AskForUnits()
- local count = 0
- local Units = Spring.GetTeamUnits(localTeam)
- for i=1,#Units do
- local UN = Units[i]
- local unitDefID = Spring.GetUnitDefID(UN)
- if (UnitDefs[unitDefID]["canReclaim"]) then
- count = count +1
- end
- end
- if count <= 0 then
- Spring.SendCommands("say a: I need a Constructor")
- else
- Spring.SendCommands("say a: I need Unit support.")
- end
- end
- local function AskForResources(resource)
- Spring.SendCommands("say a: I need some "..resource..".")
- end
- --ShareResources Begin
- local function SendResources(playername, teamID, resource)
- local myCur,_,_,_,_,_,_,_ = Spring.GetTeamResources(localTeam, resource)
- local plCur,plMax,_,_,_,_,_,_ = Spring.GetTeamResources(teamID, resource)
- if myCur >= options.send_resources_amount.value and (plCur - 2 <= plMax) then
- Spring.ShareResources(teamID, resource, options.send_resources_amount.value)
- Spring.SendCommands("say a: I gave "..options.send_resources_amount.value.." "..resource.." to "..playername..".")
- else
- echo ("Not enough resources or storage.")
- end
- end
- --ShareResources END
- --Support Begin
- local m_SupportList = {}
- local e_SupportList = {}
- local m_TeamSupport = false
- local e_TeamSupport = false
- local m_ClanSupport = false
- local e_ClanSupport = false
- function Support(teamID)
- if m_SupportList[teamID] then
- SendSupport(teamID, 'metal')
- end
- if e_SupportList[teamID] then
- SendSupport(teamID, 'energy')
- end
- end
- function SendSupport(teamID, resource)
- local Transfer = 0
- local myCeiling = options.support_my_Ceiling.value
- --echo(allyFloor)
- --echo(myCeiling)
- local Cur,Max,_,Income,Expense,_,_,_ = Spring.GetTeamResources(localTeam, resource)
- local Plus = Income-Expense
- --local Seer=Max-Plus
- --echo(Cur)
- local AllyCur,AllyMax,_,AllyIncome,AllyExpense,_,_,_ = Spring.GetTeamResources(teamID, resource)
- local AllyPlus = AllyIncome-AllyExpense
- --local AllySeer = AllyMax-(AllyPlus+Plus)
- --echo(AllyCur)
- local allyFloor = (AllyMax*0.9) -- options.support_ally_floor.value
- if AllyCur < allyFloor and Cur > myCeiling and AllyPlus < 0 then
- if (Cur-(AllyPlus*(-1))) >= myCeiling then
- Transfer = (Cur-myCeiling)
- else
- Transfer = (AllyPlus*-1)
- end
- if (AllyCur+Transfer) > allyFloor then
- Transfer = allyFloor-AllyCur
- end
- Spring.ShareResources(teamID, resource, Transfer)
- --echo(teamID.." "..resource.." "..Transfer)
- end
- end
- local function AddtoSupport(entity, resource)
- if resource == 'metal' then
- if m_SupportList[entity.teamID] then
- m_SupportList[entity.teamID] = false
- echo ("Removed "..entity.name.." to metal support list.")
- if entity.m_SupportButton then entity.m_SupportButton.backgroundColor = {0,0,0,0} end
- else
- m_SupportList = m_SupportList or {}
- m_SupportList[entity.teamID] = true
- echo ("Added "..entity.name.." to metal support list.")
- if entity.m_SupportButton then entity.m_SupportButton.backgroundColor = {0,1,0,1} end
- end
- elseif resource == 'energy' then
- if e_SupportList[entity.teamID] then
- e_SupportList[entity.teamID] = false
- echo ("Removed "..entity.name.." to energy support list.")
- if entity.e_SupportButton then entity.e_SupportButton.backgroundColor = {0,0,0,0} end
- else
- e_SupportList = e_SupportList or {}
- e_SupportList[entity.teamID] = true
- echo ("Added "..entity.name.." to energy support list.")
- if entity.e_SupportButton then entity.e_SupportButton.backgroundColor = {0,1,0,1} end
- end
- end
- end
- local ListSupportButton = {}
- local function AddTeamtoSupport(mainentity,resource)
- if resource == 'metal' then
- if m_TeamSupport then
- if ListSupportButton.teammetal then ListSupportButton.teammetal.backgroundColor = {0,0,0,0} end
- m_TeamSupport = false
- if ListSupportButton.clanmetal then ListSupportButton.clanmetal.backgroundColor = {0,0,0,0}; ListSupportButton.clanmetal:Invalidate() end
- m_ClanSupport = false
- for i=1,#allyTeams[localAlliance] do
- local teamID = allyTeams[localAlliance][i]
- if teamID ~= localTeam and teams[teamID].roster then
- for j=1,#teams[teamID].roster do
- local entity = teams[teamID].roster[j]
- m_SupportList[teamID] = false
- echo ("Removed "..entity.name.." to metal support list.")
- if entity.m_SupportButton then entity.m_SupportButton.backgroundColor = {0,0,0,0}; entity.m_SupportButton:Invalidate() end
- end
- end
- end
- elseif not m_TeamSupport then
- if ListSupportButton.teammetal then ListSupportButton.teammetal.backgroundColor = {0,1,0,1} end
- m_TeamSupport = true
- for i=1,#allyTeams[localAlliance] do
- local teamID = allyTeams[localAlliance][i]
- if teamID ~= localTeam and teams[teamID].roster then
- for j=1,#teams[teamID].roster do
- local entity = teams[teamID].roster[j]
- m_SupportList[teamID] = true
- echo ("Added "..entity.name.." to metal support list.")
- if entity.m_SupportButton then entity.m_SupportButton.backgroundColor = {0,1,0,1}; entity.m_SupportButton:Invalidate() end
- end
- end
- end
- end
- elseif resource == 'energy' then
- if e_TeamSupport then
- if ListSupportButton.teamenergy then ListSupportButton.teamenergy.backgroundColor = {0,0,0,0} end
- e_TeamSupport = false
- if ListSupportButton.clanenergy then ListSupportButton.clanenergy.backgroundColor = {0,0,0,0}; ListSupportButton.clanenergy:Invalidate() end
- e_ClanSupport = false
- for i=1,#allyTeams[localAlliance] do
- teamID = allyTeams[localAlliance][i]
- if teamID ~= localTeam and teams[teamID].roster then
- for j=1,#teams[teamID].roster do
- entity = teams[teamID].roster[j]
- e_SupportList[teamID] = false
- echo ("Removed "..entity.name.." to energy support list.")
- if entity.e_SupportButton then entity.e_SupportButton.backgroundColor = {0,0,0,0}; entity.e_SupportButton:Invalidate() end
- end
- end
- end
- elseif not e_TeamSupport then
- if ListSupportButton.teamenergy then ListSupportButton.teamenergy.backgroundColor = {0,1,0,1} end
- e_TeamSupport = true
- for i=1,#allyTeams[localAlliance] do
- teamID = allyTeams[localAlliance][i]
- if teamID ~= localTeam and teams[teamID].roster then
- for j=1,#teams[teamID].roster do
- entity = teams[teamID].roster[j]
- e_SupportList[teamID] = true
- echo ("Added "..entity.name.." to energy support list.")
- if entity.e_SupportButton then entity.e_SupportButton.backgroundColor = {0,1,0,1}; entity.e_SupportButton:Invalidate() end
- end
- end
- end
- end
- end
- end
- local function AddClantoSupport(mainentity,resource)
- --clanentity = mainentity
- if resource == 'metal' then
- if m_ClanSupport then
- if ListSupportButton.clanmetal then ListSupportButton.clanmetal.backgroundColor = {0,0,0,0} end
- m_ClanSupport = false
- for i=1,#allyClans[localAlliance] do
- local teamID = allyClans[localAlliance][i]
- if teamID ~= localTeam and teams[teamID].roster then
- for j=1,#teams[teamID].roster do
- local entity = teams[teamID].roster[j]
- m_SupportList[teamID] = false
- echo ("Removed "..entity.name.." to metal support list.")
- if entity.m_SupportButton then entity.m_SupportButton.backgroundColor = {0,0,0,0}; entity.m_SupportButton:Invalidate() end
- end
- end
- end
- elseif not m_ClanSupport then
- if ListSupportButton.clanmetal then ListSupportButton.clanmetal.backgroundColor = {0,1,0,1} end
- m_ClanSupport = true
- for i=1,#allyClans[localAlliance] do
- local teamID = allyClans[localAlliance][i]
- if teamID ~= localTeam and teams[teamID].roster then
- for j=1,#teams[teamID].roster do
- local entity = teams[teamID].roster[j]
- m_SupportList[teamID] = true
- echo ("Added "..entity.name.." to metal support list.")
- if entity.m_SupportButton then entity.m_SupportButton.backgroundColor = {0,1,0,1}; entity.m_SupportButton:Invalidate() end
- end
- end
- end
- end
- elseif resource == 'energy' then
- if e_ClanSupport then
- if ListSupportButton.clanenergy then ListSupportButton.clanenergy.backgroundColor = {0,0,0,0} end
- e_ClanSupport = false
- for i=1,#allyClans[localAlliance] do
- teamID = allyClans[localAlliance][i]
- if teamID ~= localTeam and teams[teamID].roster then
- for j=1,#teams[teamID].roster do
- entity = teams[teamID].roster[j]
- e_SupportList[teamID] = false
- echo ("Removed "..entity.name.." to energy support list.")
- if entity.e_SupportButton then entity.e_SupportButton.backgroundColor = {0,0,0,0}; entity.e_SupportButton:Invalidate() end
- end
- end
- end
- elseif not e_ClanSupport then
- if ListSupportButton.clanenergy then ListSupportButton.clanenergy.backgroundColor = {0,1,0,1} end
- e_ClanSupport = true
- for i=1,#allyClans[localAlliance] do
- teamID = allyClans[localAlliance][i]
- if teamID ~= localTeam and teams[teamID].roster then
- for j=1,#teams[teamID].roster do
- entity = teams[teamID].roster[j]
- e_SupportList[teamID] = true
- echo ("Added "..entity.name.." to energy support list.")
- if entity.e_SupportButton then entity.e_SupportButton.backgroundColor = {0,1,0,1}; entity.e_SupportButton:Invalidate() end
- end
- end
- end
- end
- end
- end
- --Support END
- -- makes a color char from a color table
- -- explanation for string.char: http://springrts.com/phpbb/viewtopic.php?f=23&t=24952
- local function GetColorChar(colorTable)
- if colorTable == nil then return string.char(255,255,255,255) end
- local col = {}
- for i=1,4 do
- col[i] = math.ceil(colorTable[i]*255)
- end
- return string.char(col[4],col[1],col[2],col[3])
- end
- local function FormatPingCpu(ping,cpu)
- -- guard against being called with nils
- ping = ping or 0
- cpu = cpu or 0
- -- guard against silly values
- ping = math.max(math.min(ping,999),0)
- cpu = math.max(math.min(cpu,9.99),0)
- local pingMult = 2/3 -- lower = higher ping needed to be red
- local pingCpuColors = {
- {0, 1, 0, 1},
- {0.7, 1, 0, 1},
- {1, 1, 0, 1},
- {1, 0.6, 0, 1},
- {1, 0, 0, 1}
- }
- local pingCol = pingCpuColors[ math.ceil( math.min(ping * pingMult, 1) * 5) ] or {.85,.85,.85,1}
- local cpuCol = pingCpuColors[ math.ceil( math.min(cpu, 1) * 5 ) ] or {.85,.85,.85,1}
- local pingText
- if ping < 1 then
- pingText = (math.floor(ping*1000) ..'ms')
- else
- pingText = ('' .. (math.floor(ping*100)/100)):sub(1,4) .. 's'
- end
- local cpuText = math.round(cpu*100) .. '%'
- return pingCol,cpuCol,pingText,cpuText
- end
- local function FormatMetalStats(stat,k)
- -- if k then
- -- stat = 1000 * math.floor((stat/1000) + .5)
- -- return string.format("%.0f", stat/1000) .. "k"
- -- else
- -- stat = 50 * math.floor((stat/50) + .5)
- return stat < 1000
- and string.format("%.0f", stat)
- or string.format("%.1f", stat/1000) .. "k"
- -- end
- end
- --Damage Begin
- local function FormatDamageStats(damage)
- if (damage>=1000 and damage<100000) then
- return string.format("%.1f", damage/1000) .. "k"
- elseif (damage>=100000 and damage<100000000) then
- return string.format("%.1f", damage/1000000) .. "M"
- elseif (damage>=100000000 and damage<100000000000) then
- return string.format("%.1f", damage/1000000000) .. "G"
- elseif (damage>=100000000000) then
- return string.format("%.1f", damage/1000000000000) .. "T"
- else
- return string.format("%.0f", damage)
- end
- end
- --Damage END
- local function FormatElo(elo,full)
- local mult = full and 1 or 50
- local elo_out
- if options.round_elo.value then
- elo_out = mult * math.floor((elo/mult) + .5)
- else
- elo_out = math.floor(elo)
- end
- local eloCol = {}
- local top = 1800
- local mid = 1600
- local bot = 1400
- local tc = {1,1,1,1}
- local mc = {1,1,0,1}
- local bc = {1,.2,.2,1}
- if elo_out >= top then eloCol = tc
- elseif elo_out >= mid then
- local r = (elo_out-mid)/(top-mid)
- for i = 1,4 do
- eloCol[i] = (r * tc[i]) + ((1-r) * mc[i])
- end
- elseif elo_out >= bot then
- local r = (elo_out-bot)/(mid-bot)
- for i = 1,4 do
- eloCol[i] = (r * mc[i]) + ((1-r) * bc[i])
- end
- else eloCol = bc
- end
- return elo_out, eloCol
- end
- local function ProcessUnit(unitID, unitDefID, unitTeam, remove)
- local stats = playerTeamStatsCache[unitTeam]
- if UnitDefs[unitDefID] and stats then -- shouldn't need to guard against nil here, but I've had it happen
- local metal = UnitDefs[unitDefID].metalCost
- local speed = UnitDefs[unitDefID].speed
- local unarmed = UnitDefs[unitDefID].springCategories.unarmed
- local isbuilt = not select(3, spGetUnitIsStunned(unitID))
- if metal and metal < 1000000 then -- tforms show up as 1million cost, so ignore them
- if remove then
- metal = -metal
- end
- -- for mobiles, count only completed units
- if speed and speed ~= 0 then
- if remove then
- finishedUnits[unitID] = nil
- stats.mMobs = stats.mMobs + metal
- elseif isbuilt then
- finishedUnits[unitID] = true
- stats.mMobs = stats.mMobs + metal
- end
- -- for static defense, include full cost of unfinished units so you can see when your teammates are trying to build too much
- elseif not unarmed then
- stats.mDefs = stats.mDefs + metal
- end
- end
- end
- end
- local function GetPlayerTeamStats(teamID)
- if not playerTeamStatsCache[teamID] then
- playerTeamStatsCache[teamID] = {mMobs = 0, mDefs = 0}
- local units = Spring.GetTeamUnits(teamID)
- for i=1,#units do
- local unitID = units[i]
- local unitDefID = Spring.GetUnitDefID(unitID)
- ProcessUnit(unitID, unitDefID, teamID)
- end
- end
- local stats = playerTeamStatsCache[teamID]
- local eCurr, eStor, ePull, eInco, eExpe, eShar, eSent, eReci = Spring.GetTeamResources(teamID, "energy")
- local mCurr, mStor, mPull, mInco, mExpe, mShar, mSent, mReci = Spring.GetTeamResources(teamID, "metal")
- if eStor then
- eStor = eStor - 10000 -- eStor has a "hidden 10k" to account for
- if eStor > 50000 then eStor = 1000 end -- fix for weirdness where sometimes storage is reported as huge, assume it should be 1000
- end
- -- guard against dividing by zero later, when the fill bar percentage is calculated
- -- these probably aren't ever going to be zero, but better safe than sorry
- if mStore and mStore == 0 then mStore = 1000 end
- if eStore and eStore == 0 then eStore = 1000 end
- -- Default these to 1 if the value is nil for some reason.
- -- These should never be 1 in normal play, so if you see
- -- them showing up as 1 then that means that something got nil,
- -- which should perhaps then be looked into further.
- -- Whereas it's quite reasonable for them to sometimes be zero.
- stats.mInco = mInco or 1
- stats.eInco = eInco or 1
- stats.mCurr = mCurr or 1
- stats.mStor = mStor or 1
- stats.eCurr = eCurr or 1
- stats.eStor = eStor or 1
- return playerTeamStatsCache[teamID]
- end
- --Damage Begin
- local function GetTeamStatsHistory(teamID)
- if amSpec or Spring.AreTeamsAllied(localTeam,teamID) then
- local idx = Spring.GetTeamStatsHistory(localTeam)
- return Spring.GetTeamStatsHistory(teamID,idx)[1]
- else
- local d = { damageDealt = 0, damageReceived = 0 }
- return d
- end
- end
- --Damage END
- -- ceasefire button tooltip
- local function CfTooltip(allyTeam)
- local tooltip = ''
- tooltip = tooltip .. 'Check this box to vote for a ceasefire with '.. yellow ..'<Team ' .. (allyTeam+1) .. '>'..white..'. '
- ..'If everyone votes Yes, an offer will be made. If there is a ceasefire, '
- ..'unchecking the box will break it.\n\n'
- tooltip = tooltip .. 'Your team\'s votes: \n'
- local teamList = Spring.GetTeamList(localAlliance)
- for _,teamID in ipairs(teamList) do
- local _,playerID = Spring.GetTeamInfo(teamID)
- local name = Spring.GetPlayerInfo(playerID) or '-'
- local vote = Spring.GetTeamRulesParam(teamID, 'cf_vote_' ..allyTeam)==1 and green..'Y'..white or red..'N'..white
- local teamColor = color2incolor(Spring.GetTeamColor(teamID))
- tooltip = tooltip .. teamColor .. ' <' .. name .. '> ' .. white.. vote .. '\n'
- end
- if Spring.GetGameRulesParam('cf_' .. localAlliance .. '_' .. allyTeam) == 1 then
- tooltip = tooltip .. '\n\n' .. green .. 'Ceasefire in effect.' .. white
- else
- local theyOffer = Spring.GetGameRulesParam('cf_offer_' .. localAlliance .. '_' .. allyTeam) == 1
- local youOffer = Spring.GetGameRulesParam('cf_offer_' .. allyTeam.. '_' .. localAlliance) == 1
- if theyOffer then
- tooltip = tooltip .. '\n\n' .. yellow .. 'They have offered a ceasefire.' .. white
- end
- if youOffer then
- tooltip = tooltip .. '\n\n' .. cyan .. 'Your team has offered a ceasefire.' .. white
- end
- tooltip = tooltip .. '\n\n' .. red .. 'No ceasefire in effect.' .. white
- end
- return tooltip
- end
- local function MakeSpecTooltip()
- if (not options.show_tooltips.value) or list_size == 4 or (list_size == 3 and #specTeam.roster == 0) then
- scroll_cpl.tooltip = nil
- return
- end
- local windowTooltip
- local players = {}
- local spectators = {}
- local playerlist = Spring.GetPlayerList()
- for i=1, #playerlist do
- local playerID = playerlist[i]
- local name,active,spectator,teamID,allyTeamID,pingTime,cpuUsage,country,rank,customKeys = Spring.GetPlayerInfo(playerID)
- local pingCol, cpuCol, pingText, cpuText = FormatPingCpu(pingTime,cpuUsage)
- local cpuColChar = GetColorChar(cpuCol)
- local pingColChar = GetColorChar(pingCol)
- if active and not spectator then
- players[#players+1] = { name = name, pingText = pingText, cpuText = cpuText, pingColChar = pingColChar, cpuColChar = cpuColChar }
- elseif spectator then
- spectators[#spectators+1] = { name = name, pingText = pingText, cpuText = cpuText, pingColChar = pingColChar, cpuColChar = cpuColChar }
- end
- end
- table.sort (players, function(a,b)
- return a.name:lower() < b.name:lower()
- end
- )
- table.sort (spectators, function(a,b)
- return a.name:lower() < b.name:lower()
- end
- )
- if list_size <= 2 then
- windowTooltip = windowTooltip or "PLAYERS"
- for i=1, #players do
- windowTooltip = windowTooltip .. "\n\t"..players[i].name.."\t"..players[i].cpuColChar..(players[i].cpuText)..'\008' .. "\t"..players[i].pingColChar..(players[i].pingText).."\008"
- end
- end
- if #spectators ~= 0 then
- windowTooltip = windowTooltip and (windowTooltip .. "\n\n") or ""
- windowTooltip = windowTooltip .. "SPECTATORS"
- for i=1, #spectators do
- windowTooltip = windowTooltip .. "\n\t"..spectators[i].name.."\t"..spectators[i].cpuColChar..(spectators[i].cpuText)..'\008' .. "\t"..spectators[i].pingColChar..(spectators[i].pingText).."\008"
- end
- end
- scroll_cpl.tooltip = windowTooltip
- end
- --------------------------------------------------------------------------------
- --------------------------------------------------------------------------------
- local function MakeNewLabel(entity,name,o) -- "o" is for options
- -- pass in x, width, caption, textColor
- -- pass in any optional params like align
- -- pass in anything to override these defaults:
- o.y = o.y or (fontsize+1) * row
- o.fontsize = o.fontsize or fontsize
- o.fontShadow = o.fontShadow or true
- o.autosize = o.autosize or false
- local newLabel = Label:New(o)
- entity[name] = newLabel
- scroll_cpl:AddChild(newLabel)
- end
- local function MakeNewBar(entity,name,o)
- -- pass in x, width, color, value
- -- pass in anything to override these defaults:
- o.y = o.y or ((fontsize+1) * row) + 6
- o.height = o.height or 5
- o.min = o.min or 0
- o.max = o.max or 1
- o.autosize = o.autosize or false
- local newBar = Chili.Progressbar:New(o)
- entity[name] = newBar
- scroll_cpl:AddChild(newBar)
- end
- local function MakeNewIcon(entity,name,o)
- -- pass in x, file
- -- pass in anything to override these defaults:
- o.y = o.y or ((fontsize+1) * row) + 2
- o.width = o.width or fontsize + 3
- o.height = o.height or fontsize + 3
- o.tooltip = options.show_tooltips.value and o.tooltip or nil
- local newIcon = Chili.Image:New(o)
- entity[name] = newIcon
- scroll_cpl:AddChild(newIcon)
- end
- --TeamworkButtons Begin
- local function MakeNewButton(entity,name,o)
- -- pass in x, width, color, value
- -- pass in anything to override these defaults:
- o.y = o.y or ((fontsize+1) * row) + 6
- o.height = o.height or 5
- o.width = o.width or 24
- o.caption = o.caption or ''
- o.fontsize = o.fontsize or fontsize
- o.fontShadow = o.fontShadow or true
- o.autosize = o.autosize or false
- o.backgroundColor = o.backgroundColor or {0,0,0,0}
- local newButton = Button:New(o)
- entity[name] = newButton
- scroll_cpl:AddChild(newButton)
- end
- --TeamworkButtons End
- local function AccumulatePlayerTeamStats(r,s)
- r.eCurr = r.eCurr + s.eCurr
- r.eStor = r.eStor + s.eStor
- r.eInco = r.eInco + s.eInco
- r.mCurr = r.mCurr + s.mCurr
- r.mStor = r.mStor + s.mStor
- r.mInco = r.mInco + s.mInco
- r.mMobs = r.mMobs + s.mMobs
- r.mDefs = r.mDefs + s.mDefs
- end
- --Damage Begin
- local function AccumulatePlayerTeamDamage(rd,sd)
- rd.damageDealt = rd.damageDealt + sd.damageDealt
- rd.damageReceived = rd.damageReceived + sd.damageReceived
- end
- --Damage END
- local function DrawPlayerTeamStats(entity,teamcolor,s,d) --Damage
- if not options.colorResourceStats.value then teamcolor = {.85,.85,.85,1} end
- --Damage Begin
- if options.show_Damage_stats.value then
- MakeNewLabel(entity,"m_cdamageLabel",{x=x_c_damage,width=36,caption = FormatDamageStats(d.damageDealt),textColor = teamcolor,align = 'right',})
- MakeNewLabel(entity,"m_tdamageLabel",{x=x_t_damage,width=36,caption = FormatDamageStats(d.damageReceived),textColor = teamcolor,align = 'right',})
- end
- --Damage END
- if options.show_unit_stats.value then
- MakeNewLabel(entity,"m_mobilesLabel",{x=x_m_mobiles,width=36,caption = FormatMetalStats(s.mMobs,true),textColor = teamcolor,align = 'right',})
- MakeNewLabel(entity,"m_defenseLabel",{x=x_m_defense,width=36,caption = FormatMetalStats(s.mDefs),textColor = teamcolor,align = 'right',})
- end
- if options.show_income_stats.value then
- MakeNewLabel(entity,"m_incomeLabel",{x=x_m_income,width=24,caption = string.format("%." .. (0) .. "f", s.mInco),textColor = teamcolor,align = 'right',})
- MakeNewLabel(entity,"e_incomeLabel",{x=x_e_income,width=24,caption = string.format("%." .. (0) .. "f", s.eInco),textColor = teamcolor,align = 'right',})
- end
- MakeNewBar(entity,"m_fillBar",{x=x_m_fill + 6,width=24,color = {.7,.75,.9,1},value = s.mCurr/s.mStor,})
- MakeNewBar(entity,"e_fillBar",{x=x_e_fill + 2,width=24,color = {1,1,0,1}, value = s.eCurr/s.eStor,})
- end
- --TeamworkButtons Begin
- local function MakePlayerTeamworkButtons(entity,teamcolor)
- local u_SendButtonFunc
- local m_SupportButtonFunc
- local e_SupportButtonFunc
- local m_SendButtonFunc
- local e_SendButtonFunc
- local u_SendButtonCol
- local u_SendButtonTip
- local m_SupportButtonTip
- local e_SupportButtonTip
- local m_SendButtonTip
- local e_SendButtonTip
- if entity.teamID ~= localTeam then
- u_SendButtonFunc = { function(self) ShareUnits(entity.name, entity.teamID) end, }
- m_SupportButtonFunc = { function(self) AddtoSupport(entity, "metal") end, }
- e_SupportButtonFunc = { function(self) AddtoSupport(entity, "energy") end, }
- m_SendButtonFunc = { function(self) SendResources(entity.name, entity.teamID, "metal") end, }
- e_SendButtonFunc = { function(self) SendResources(entity.name, entity.teamID, "energy") end, }
- u_SendButtonCol = {1, 1, 1, 1}
- u_SendButtonTip = 'Double click to share selected units to ' .. entity.name .. '.'
- m_SupportButtonTip = 'Click to Support ' .. entity.name .. '.'
- e_SupportButtonTip = 'Click to Support ' .. entity.name .. '.'
- m_SendButtonTip = 'Double click to share '.. options.send_resources_amount.value ..' metal to ' .. entity.name .. '.'
- e_SendButtonTip = 'Double click to share '.. options.send_resources_amount.value ..' energy to ' .. entity.name .. '.'
- elseif entity.teamID == localTeam then
- u_SendButtonFunc = { function(self) AskForUnits() end, }
- m_SupportButtonFunc = { function(self) end, }
- e_SupportButtonFunc = { function(self) end, }
- m_SendButtonFunc = { function(self) AskForResources("metal") end, }
- e_SendButtonFunc = { function(self) AskForResources("energy") end, }
- u_SendButtonCol = {1, .3, .3, 1}
- u_SendButtonTip = 'Double click to ask for Units.'
- m_SupportButtonTip = ''
- e_SupportButtonTip = ''
- m_SendButtonTip = 'Double click to ask for metal.'
- e_SendButtonTip = 'Double click to ask for energy.'
- end
- MakeNewButton(entity,"u_SendButton",{x = x_share,
- y = (fontsize+1)*(row+0.5)-2.5,
- height = fontsize,
- width = fontsize,
- tooltip = options.show_tooltips.value and u_SendButtonTip,
- padding = {0,0,0,0},
- OnDblClick = u_SendButtonFunc,
- children = {
- Image:New{
- x=0,y=0,
- height='100%',
- width='100%',
- color = u_SendButtonCol,
- file = sharePic,
- },
- },
- })
- if options.show_income_stats.value and entity.teamID ~= localTeam then
- MakeNewButton(entity,"m_SupportButton",{x = x_m_income+5,
- align = 'right',
- tooltip = options.show_tooltips.value and m_SupportButtonTip,
- OnClick = m_SupportButtonFunc,
- })
- MakeNewButton(entity,"e_SupportButton",{x = x_e_income+5,
- align = 'right',
- tooltip = options.show_tooltips.value and e_SupportButtonTip,
- OnClick = e_SupportButtonFunc,
- })
- end
- MakeNewButton(entity,"m_SendButton",{x = x_m_fill + 6,
- tooltip = options.show_tooltips.value and m_SendButtonTip,
- OnDblClick = m_SendButtonFunc,
- })
- MakeNewButton(entity,"e_SendButton",{x = x_e_fill + 2,
- tooltip = options.show_tooltips.value and e_SendButtonTip,
- OnDblClick = e_SendButtonFunc,
- })
- end
- local function MakeListTeamworkButtons(entity,entitygroup,TeamList)
- local ClickFunc
- if amSpec then
- MakeNewButton(entity,"WatchButton",{x = x_name,
- width = name_width,
- tooltip = options.show_tooltips.value and 'View ' .. entitygroup .. '.',
- OnClick = { function(self) ViewTeam(TeamList) end, }
- })
- else
- if entitygroup == "team" then
- ClickFunc = AddTeamtoSupport
- elseif entitygroup == "clan" then
- ClickFunc = AddClantoSupport
- end
- MakeNewButton(entity,entitygroup.."ChatButton",{x = x_name,
- width = name_width,
- tooltip = options.show_tooltips.value and 'Chat with your Team.',
- OnClick = { function(self) ChatwithTeam() end, }
- })
- if options.show_income_stats.value then
- MakeNewButton(ListSupportButton,entitygroup.."metal",{x = x_m_income+5,
- align = 'right',
- tooltip = options.show_tooltips.value and 'Click to Support '..entitygroup..' Members with metal',
- OnClick = { function(self) ClickFunc(entity, "metal") end, },
- })
- MakeNewButton(ListSupportButton,entitygroup.."energy",{x = x_e_income+5,
- align = 'right',
- tooltip = options.show_tooltips.value and 'Click to Support '..entitygroup..' Members with energy',
- OnClick = { function(self) ClickFunc(entity, "energy") end, },
- })
- end
- end
- end
- --TeamworkButtons END
- local function UpdatePlayerTeamStats(entity,s,d) --Damage
- if entity.m_mobilesLabel then entity.m_mobilesLabel:SetCaption(FormatMetalStats(s.mMobs,true)) end
- if entity.m_defenseLabel then entity.m_defenseLabel:SetCaption(FormatMetalStats(s.mDefs)) end
- --Damage Begin
- if entity.m_cdamageLabel then entity.m_cdamageLabel:SetCaption(FormatDamageStats(d.damageDealt)) end
- if entity.m_tdamageLabel then entity.m_tdamageLabel:SetCaption(FormatDamageStats(d.damageReceived)) end
- --Damage END
- if entity.m_incomeLabel then entity.m_incomeLabel:SetCaption(string.format("%." .. (0) .. "f", s.mInco)) end
- if entity.e_incomeLabel then entity.e_incomeLabel:SetCaption(string.format("%." .. (0) .. "f", s.eInco)) end
- if entity.m_fillBar then entity.m_fillBar:SetValue(s.mCurr/s.mStor) end
- if entity.e_fillBar then entity.e_fillBar:SetValue(s.eCurr/s.eStor) end
- end
- --------------------------------------------------------------------------------
- --------------------------------------------------------------------------------
- local function UpdatePingCpu(entity,pingTime,cpuUsage,pstatus)
- pingTime = pingTime or 0
- cpuUsage = cpuUsage or 0
- if pstatus == 'gone' then
- pingTime = 0
- cpuUsage = 0
- end
- local pingCol, cpuCol, pingText, cpuText = FormatPingCpu(pingTime,cpuUsage)
- if options.cpu_ping_as_text.value then
- if entity.cpuLabel then entity.cpuLabel.font:SetColor(cpuCol) ; entity.cpuLabel:SetCaption(cpuText) end
- if entity.pingLabel then entity.pingLabel.font:SetColor(pingCol) ; entity.pingLabel:SetCaption(pingText) end
- else
- if entity.cpuImg then
- entity.cpuImg.color = cpuCol
- if options.show_tooltips.value then entity.cpuImg.tooltip = ('CPU: ' .. cpuText) end
- entity.cpuImg:Invalidate()
- end
- if entity.pingImg then
- entity.pingImg.color = pingCol
- if options.show_tooltips.value then entity.pingImg.tooltip = ('Ping: ' .. pingText) end
- entity.pingImg:Invalidate()
- end
- end
- end
- --Clan Begin
- local function updateresourcetotals(allyListEntities, allyEntities)
- if allyListEntities then
- for k,v in pairs(allyListEntities) do
- local r = { eCurr = 0, eStor = 0, eInco = 0, mCurr = 0, mStor = 0, mInco = 0, mMobs = 0, mDefs = 0 }
- local rd = { damageDealt = 0, damageReceived = 0} --Damage
- if allyEntities[k] then
- for j=1,#allyEntities[k] do
- local teamID = allyEntities[k][j]
- if teamID then
- local s = GetPlayerTeamStats(teamID)
- AccumulatePlayerTeamStats(r,s)
- --Damage Begin
- local d = GetTeamStatsHistory(teamID)
- AccumulatePlayerTeamDamage(rd,d)
- --Damage END
- end
- end
- end
- UpdatePlayerTeamStats(v,r,rd)
- end
- end
- end
- --Clan END
- -- updates as needed: status, name, ping, cpu, resource stats, etc.
- local function UpdatePlayerInfo()
- for i=1,#entities do
- local teamID
- if entities[i].isAI then
- teamID = entities[i].teamID
- Support(teamID) --Support
- else
- local playerID = entities[i].playerID
- local name,active,spectator,localteamID,allyTeamID,pingTime,cpuUsage = Spring.GetPlayerInfo(playerID)
- teamID = localteamID
- local teamcolor = teamID and {Spring.GetTeamColor(teamID)} or {1,1,1,1}
- -- status (player status and team status)
- local pstatus = nil
- local tstatus = ''
- local tstatuscolor = {1,1,1,1}
- if not active then
- if Spring.GetGameSeconds() < 0.1 or cpuUsage > 1 then tstatus = '?' ; tstatuscolor = teamcolor
- else pstatus = 'gone'
- end
- elseif spectator and (teamID ~= 0 or teamZeroPlayers[playerID]) then
- pstatus = 'spec'
- end
- if pstatus == 'spec' or pstatus == 'gone' then
- if Spring.GetTeamUnitCount(teamID) > 0 then
- tstatus = '!!'
- tstatuscolor = {1,1,0,1}
- else
- tstatus = 'X'
- tstatuscolor = {1,0,0,1}
- end
- end
- local displayname
- local whitestring = GetColorChar({1,1,1,1})
- local greystring = GetColorChar({.5,.5,.5,1})
- local teamcolorstring = GetColorChar(teamcolor)
- -- these were part of a failed experiment that I might try to fix later
- if pstatus == 'spec' then displayname = (" ss: " .. name)
- elseif pstatus == 'gone' then displayname = (" xx: " .. name)
- else displayname = (name)
- end
- if entities[i].nameLabel then entities[i].nameLabel:SetCaption(displayname) end
- if entities[i].statusLabel then entities[i].statusLabel:SetCaption(tstatus) ; entities[i].statusLabel.font:SetColor(tstatuscolor) end
- UpdatePingCpu(entities[i],pingTime,cpuUsage,pstatus)
- if pstatus ~= 'spec' and pstatus ~= 'gone' then Support(teamID) end --Support
- end -- if not isAI
- -- update the resource stats for all entities, including AIs
- local s = GetPlayerTeamStats(teamID)
- local d = GetTeamStatsHistory(teamID)
- UpdatePlayerTeamStats(entities[i],s,d)
- end -- for entities
- -- update ping and cpu for the spectators
- if #specTeam.roster ~= 0 then
- for i = 1,#specTeam.roster do
- local playerID = specTeam.roster[i].playerID
- local name,active,spectator,localteamID,allyTeamID,pingTime,cpuUsage = Spring.GetPlayerInfo(playerID)
- specTeam.roster[i].pingTime = pingTime
- specTeam.roster[i].cpuUsage = cpuUsage
- if list_size == 4 then
- UpdatePingCpu(specTeam.roster[i],pingTime,cpuUsage)
- end
- end
- end
- MakeSpecTooltip()
- for allyTeam, cb in pairs(cfCheckBoxes) do
- cb.tooltip = CfTooltip(allyTeam)
- end
- --Clan Begin
- -- update resource totals for allyTeams and allyClans
- updateresourcetotals(allyTeamEntities, allyTeams)
- updateresourcetotals(allyClanEntities, allyClans)
- --Clan ENd
- end
- --------------------------------------------------------------------------------
- --------------------------------------------------------------------------------
- local function AddTableHeaders()
- if cf then
- scroll_cpl:AddChild( Label:New{ x=x_cf, y=(fontsize+1) * row, caption = 'CF', fontShadow = true, fontsize = fontsize, } )
- end
- --Damage Begin
- if options.show_Damage_stats.value then
- 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',} )
- 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',} )
- end
- --Damage END
- if options.show_unit_stats.value then
- 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',} )
- 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',} )
- end
- if options.show_income_stats.value then
- scroll_cpl:AddChild( Image:New{ x=x_e_income - 15, y=((fontsize+1) * row) + 3, height = (fontsize)+1, file = 'LuaUI/Images/energy.png',} )
- scroll_cpl:AddChild( Image:New{ x=x_m_income - 15, y=((fontsize+1) * row) + 3, height = (fontsize)+1, file = 'LuaUI/Images/ibeam.png',} )
- end
- scroll_cpl:AddChild( Label:New{ x=x_cpu, y=(fontsize+1) * row, caption = 'C', fontShadow = true, fontsize = fontsize,} )
- scroll_cpl:AddChild( Label:New{ x=x_ping, y=(fontsize+1) * row, caption = 'P', fontShadow = true, fontsize = fontsize,} )
- end
- local function AddCfCheckbox(allyTeam)
- if cf and allyTeam ~= -1 and allyTeam ~= localAlliance then
- local cfCheck = Checkbox:New{
- x=x_cf,y=(fontsize+1) * row + 3,width=20,
- caption='',
- checked = Spring.GetTeamRulesParam(localTeam, 'cf_vote_' ..allyTeam)==1,
- tooltip = CfTooltip(allyTeam),
- OnChange = { function(self)
- Spring.SendLuaRulesMsg('ceasefire:'.. (self.checked and 'n' or 'y') .. allyTeam)
- self.tooltip = CfTooltip(allyTeam)
- end },
- }
- scroll_cpl:AddChild(cfCheck)
- cfCheckBoxes[allyTeam] = cfCheck
- end
- end
- -- adds all the entity information
- local function AddEntity(entity, teamID, allyTeamID)
- local teamcolor = (teamID and teamID ~= -1) and {Spring.GetTeamColor(teamID)} or {1,1,1,1}
- if entity.isAI then
- MakeNewLabel(entity,"nameLabel",{x=x_name,width=name_width,caption = entity.name,textColor = teamcolor,})
- else
- -- clan/faction emblems, level, country, elo
- local icon = nil
- local icRank = nil
- local elo = nil
- local eloCol = nil
- local icCountry = entity.country and entity.country ~= '' and entity.country ~= '??' and "LuaUI/Images/flags/" .. (entity.country) .. ".png" or nil
- if options.show_ccr.value then
- if entity.clan and entity.clan ~= "" then
- icon = "LuaUI/Configs/Clans/" .. entity.clan ..".png"
- elseif entity.faction and entity.faction ~= "" then
- icon = "LuaUI/Configs/Factions/" .. entity.faction ..".png"
- end
- if entity.level and entity.level ~= "" then
- icRank = "LuaUI/Images/Ranks/" .. math.min((1+math.floor((entity.level or 0)/10)),9) .. ".png"
- end
- if icCountry then MakeNewIcon(entity,"countryIcon",{x=x_icon_country,file=icCountry,}) end
- if options.rank_as_text.value then
- 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
- else
- if icRank then MakeNewIcon(entity,"rankIcon",{x=x_icon_rank,file=icRank,}) end
- end
- if icon then MakeNewIcon(entity,"clanIcon",{x=x_icon_clan,file=icon,y=((fontsize+1)*row)+5,width=fontsize-1,height=fontsize-1}) end
- end
- if entity.elo and entity.elo ~= "" then
- elo, eloCol = FormatElo(entity.elo)
- end
- if elo then MakeNewLabel(entity,"eloLabel",{x=x_elo,caption = elo,textColor = eloCol,}) end
- -- status (player status and team status)
- local pstatus = nil
- local tstatus = ''
- local tstatuscolor = {1,1,1,1}
- if teamID ~= -1 then
- if not entity.isActive then
- if Spring.GetGameSeconds() < 0.1 or entity.cpuUsage > 1 then tstatus = '?' ; tstatuscolor = teamcolor
- else pstatus = 'gone'
- end
- elseif entity.isSpec and (teamID ~= 0 or teamZeroPlayers[entity.playerID]) then
- pstatus = 'spec'
- end
- end
- if pstatus == 'spec' or pstatus == 'gone' then
- if Spring.GetTeamUnitCount(teamID) > 0 then
- tstatus = '!!'
- tstatuscolor = {1,1,0,1}
- else
- tstatus = 'X'
- tstatuscolor = {1,0,0,1}
- end
- end
- MakeNewLabel(entity,"statusLabel",{x=x_status,width=16,caption = tstatus,textColor = tstatuscolor,})
- -- name, including player status designators
- local displayname
- local whitestring = GetColorChar({1,1,1,1})
- local greystring = GetColorChar({.5,.5,.5,1})
- local teamcolorstring = GetColorChar(teamcolor)
- -- these were part of a failed experiment that I might try to fix later
- if pstatus == 'spec' then displayname = (" ss: " .. entity.name)
- elseif pstatus == 'gone' then displayname = (" xx: " .. entity.name)
- else displayname = (entity.name)
- end
- MakeNewLabel(entity,"nameLabel",{x=x_name,width=name_width,caption = displayname,textColor = teamcolor,})
- --View Begin
- if teamID ~= -1 and amSpec and(teams[teamID] and (teams[teamID].isPlaying and not teams[teamID].isDead)) then
- MakeNewButton(entity,"WatchButton",{x = x_name,
- width = name_width,
- tooltip = options.show_tooltips.value and 'View ' .. entity.name ..'.',
- textColor = teamcolor,
- OnClick = { function(self) ViewTeam({ entity.teamID }) end, }
- })
- end
- --View END
- --Chat Begin
- 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
- MakeNewButton(entity,"ChatButton",{x = x_name,
- width = name_width,
- tooltip = options.show_tooltips.value and "Chat with " .. entity.name,
- textColor = teamcolor,
- OnClick = { function(self) ChatwithUser(entity.name) end, }
- })
- end
- --Chat END
- if teamID == localTeam then end
- -- ping and cpu icons / labels
- local pingCol, cpuCol, pingText, cpuText = FormatPingCpu(pstatus == 'gone' and 0 or entity.pingTime,pstatus == 'gone' and 0 or entity.cpuUsage)
- if options.cpu_ping_as_text.value then
- MakeNewLabel(entity,"cpuLabel",{x=x_cpu,width = (fontsize+3)*10/16,caption = cpuText,textColor = cpuCol,align = 'right',})
- MakeNewLabel(entity,"pingLabel",{x=x_ping,width = (fontsize+3)*10/16,caption = pingText,textColor = pingCol,align = 'right',})
- else
- MakeNewIcon(entity,"cpuImg",{x=x_cpu,file=cpuPic,width = (fontsize+3)*10/16,keepAspect = false,tooltip = 'CPU: ' .. cpuText,})
- MakeNewIcon(entity,"pingImg",{x=x_ping,file=pingPic,width = (fontsize+3)*10/16,keepAspect = false,tooltip = 'Ping: ' .. pingText,})
- entity.cpuImg.color = cpuCol
- entity.pingImg.color = pingCol
- function entity.cpuImg:HitTest(x,y) return self end
- function entity.pingImg:HitTest(x,y) return self end
- end
- end -- if not isAI
- -- mobile and defense metal, metal and energy income, resource bars
- if teamID ~= -1 and (allyTeamID == localAlliance or amSpec) then
- local s = GetPlayerTeamStats(teamID)
- local d = GetTeamStatsHistory(teamID)
- DrawPlayerTeamStats(entity,teamcolor,s,d)
- end
- --TeamworkButtons Begin
- if teamID ~= -1 and not amSpec and (teams[teamID] and (teams[teamID].isPlaying and not teams[teamID].isDead)) and allyTeamID == localAlliance then
- MakePlayerTeamworkButtons(entity,teamcolor)
- end
- --TeamworkButtons END
- row = row + 1
- end
- local function AddTeamSummarie(allyTeamID)
- local allyTeamResources
- local allyTeamDamage
- if allyTeams[allyTeamID] then
- for j=1,#allyTeams[allyTeamID] do
- local teamID = allyTeams[allyTeamID][j]
- if teamID then
- local s = GetPlayerTeamStats(teamID)
- allyTeamResources = allyTeamResources or {}
- allyTeamResources[allyTeamID] = allyTeamResources[allyTeamID] or { eCurr = 0, eStor = 0, eInco = 0, mCurr = 0, mStor = 0, mInco = 0, mMobs = 0, mDefs = 0 }
- AccumulatePlayerTeamStats(allyTeamResources[allyTeamID],s)
- --Damage BEGIN
- local d = GetTeamStatsHistory(teamID)
- allyTeamDamage = allyTeamDamage or {}
- allyTeamDamage[allyTeamID] = allyTeamDamage[allyTeamID] or { damageDealt = 0, damageReceived = 0 }
- AccumulatePlayerTeamDamage(allyTeamDamage[allyTeamID],d)
- --Damage END
- end
- end
- end
- if allyTeamResources and allyTeamDamage then --Damage
- if allyTeamResources[allyTeamID] and allyTeamDamage[allyTeamID] and allyTeams[allyTeamID] then --Damage
- allyTeamEntities[allyTeamID] = allyTeamEntities[allyTeamID] or {}
- local allyTeamColor
- local elo
- local eloCol
- if allyTeamsElo[allyTeamID] then
- elo, eloCol = FormatElo(allyTeamsElo[allyTeamID].total / allyTeamsElo[allyTeamID].count, true)
- end
- if (localTeam ~= 0 or teamZeroPlayers[myID]) and allyTeamID == localAlliance then
- allyTeamColor = {Spring.GetTeamColor(localTeam)}
- else
- allyTeamColor = {Spring.GetTeamColor(allyTeams[allyTeamID][1])}
- end
- if options.show_ccr.value then
- MakeNewLabel(allyTeamEntities[allyTeamID],"nameLabel",{x=x_icon_clan,width=150,caption = ("TEAM " .. allyTeamID+1 .. "."),textColor = allyTeamColor,})
- LabelCaption = "Overall:"
- else
- LabelCaption = "Team " .. allyTeamID+1 .. ". Overall:"
- end
- MakeNewLabel(allyTeamEntities[allyTeamID],"nameLabel",{x=x_name,width=150,caption = LabelCaption,textColor = allyTeamColor,})
- DrawPlayerTeamStats(allyTeamEntities[allyTeamID],allyTeamColor,allyTeamResources[allyTeamID],allyTeamDamage[allyTeamID]) --Damage
- MakeListTeamworkButtons(allyTeamEntities[allyTeamID],"team",allyTeams[allyTeamID])
- if elo then MakeNewLabel(allyTeamEntities[allyTeamID],"eloLabel",{x=x_elo,caption = elo,textColor = eloCol,}) end
- if allyTeamsDead[allyTeamID] then MakeNewLabel(allyTeamEntities[allyTeamID],"statusLabel",{x=x_status,width=16,caption = "X",textColor = {1,0,0,1},}) end
- row = row + 1
- end
- end
- end
- local function AddTeamSummarieNonSpec(allyTeamID)
- if allyTeams[allyTeamID] then
- allyTeamEntities[allyTeamID] = allyTeamEntities[allyTeamID] or {}
- local allyTeamColor
- local elo
- local eloCol
- local LabelX
- if allyTeamsElo[allyTeamID] then
- elo, eloCol = FormatElo(allyTeamsElo[allyTeamID].total / allyTeamsElo[allyTeamID].count, true)
- end
- if (localTeam ~= 0 or teamZeroPlayers[myID]) and allyTeamID == localAlliance then
- allyTeamColor = {Spring.GetTeamColor(localTeam)}
- else
- allyTeamColor = {Spring.GetTeamColor(allyTeams[allyTeamID][1])}
- end
- if options.show_ccr.value then LabelX = x_icon_clan else LabelX = x_name end
- MakeNewLabel(allyTeamEntities[allyTeamID],"nameLabel",{x=LabelX,width=150,caption = ("TEAM " .. allyTeamID+1 .. ":"),textColor = allyTeamColor,})
- if elo then MakeNewLabel(allyTeamEntities[allyTeamID],"eloLabel",{x=x_elo,caption = elo,textColor = eloCol,}) end
- if allyTeamsDead[allyTeamID] then MakeNewLabel(allyTeamEntities[allyTeamID],"statusLabel",{x=x_status,width=16,caption = "X",textColor = {1,0,0,1},}) end
- row = row + 1
- end
- end
- local function AddClanSummarie(allyTeamID)
- local allyClanResources
- local allyClanDamage
- if allyClans[allyTeamID] then
- for j=1,#allyClans[allyTeamID] do
- local teamID = allyClans[allyTeamID][j]
- if teamID then
- local s = GetPlayerTeamStats(teamID)
- allyClanResources = allyClanResources or {}
- allyClanResources[allyTeamID] = allyClanResources[allyTeamID] or { eCurr = 0, eStor = 0, eInco = 0, mCurr = 0, mStor = 0, mInco = 0, mMobs = 0, mDefs = 0 }
- AccumulatePlayerTeamStats(allyClanResources[allyTeamID],s)
- --Damage BEGIN
- local d = GetTeamStatsHistory(teamID)
- allyClanDamage = allyClanDamage or {}
- allyClanDamage[allyTeamID] = allyClanDamage[allyTeamID] or { damageDealt = 0, damageReceived = 0 }
- AccumulatePlayerTeamDamage(allyClanDamage[allyTeamID],d)
- --Damage END
- end
- end
- end
- if allyClanResources and allyClanDamage then --Damage
- if allyClanResources[allyTeamID] and allyClanDamage[allyTeamID] and allyClans[allyTeamID] then --Damage
- allyClanEntities[allyTeamID] = allyClanEntities[allyTeamID] or {}
- local allyTeamColor
- local elo
- local eloCol
- local LabelCaption
- if allyClansElo[allyTeamID] then
- elo, eloCol = FormatElo(allyClansElo[allyTeamID].total / allyClansElo[allyTeamID].count, true)
- end
- if (localTeam ~= 0 or teamZeroPlayers[myID]) and allyTeamID == localAlliance then
- allyTeamColor = {Spring.GetTeamColor(localTeam)}
- else
- allyTeamColor = {Spring.GetTeamColor(allyClans[allyTeamID][1])}
- end
- if options.show_ccr.value then
- MakeNewLabel(allyClanEntities[allyTeamID],"nameLabel",{x=x_icon_clan,width=150,caption = ("CLAN " .. allyTeamID+1 .. "."),textColor = allyTeamColor,})
- LabelCaption = "Overall:"
- else
- LabelCaption = "CLAN " .. allyTeamID+1 .. ". Overall:"
- end
- MakeNewLabel(allyClanEntities[allyTeamID],"nameLabel",{x=x_name,width=150,caption = LabelCaption,textColor = allyTeamColor,})
- DrawPlayerTeamStats(allyClanEntities[allyTeamID],allyTeamColor,allyClanResources[allyTeamID],allyClanDamage[allyTeamID]) --Damage
- MakeListTeamworkButtons(allyClanEntities[allyTeamID],"clan",allyClans[allyTeamID])
- if elo then MakeNewLabel(allyClanEntities[allyTeamID],"eloLabel",{x=x_elo,caption = elo,textColor = eloCol,}) end
- if allyTeamsDead[allyTeamID] then MakeNewLabel(allyClanEntities[allyTeamID],"statusLabel",{x=x_status,width=16,caption = "X",textColor = {1,0,0,1},}) end
- row = row + 1
- end
- end
- end
- local function AddClanSummarieNonSpec(allyTeamID)
- if allyClans[allyTeamID] then
- allyClanEntities[allyTeamID] = allyClanEntities[allyTeamID] or {}
- local allyTeamColor
- local elo
- local eloCol
- local LabelX
- if allyClansElo[allyTeamID] then
- elo, eloCol = FormatElo(allyClansElo[allyTeamID].total / allyClansElo[allyTeamID].count, true)
- end
- if (localTeam ~= 0 or teamZeroPlayers[myID]) and allyTeamID == localAlliance then
- allyTeamColor = {Spring.GetTeamColor(localTeam)}
- else
- allyTeamColor = {Spring.GetTeamColor(allyClans[allyTeamID][1])}
- end
- if options.show_ccr.value then LabelX = x_icon_clan else LabelX = x_name end
- MakeNewLabel(allyClanEntities[allyTeamID],"nameLabel",{x=LabelX,width=150,caption = ("CLAN " .. allyTeamID+1 .. "."),textColor = allyTeamColor,})
- if elo then MakeNewLabel(allyClanEntities[allyTeamID],"eloLabel",{x=x_elo,caption = elo,textColor = eloCol,}) end
- if allyTeamsDead[allyTeamID] then MakeNewLabel(allyClanEntities[allyTeamID],"statusLabel",{x=x_status,width=16,caption = "X",textColor = {1,0,0,1},}) end
- row = row + 1
- end
- end
- local function AlignScrollPanel()
- local height = math.ceil(row * (fontsize+1.5) + 8)
- scroll_cpl.height = math.min(height, window_cpl.height)
- if not (options.alignToTop.value) then
- scroll_cpl.y = (window_cpl.height) - scroll_cpl.height
- else
- scroll_cpl.y = 0
- end
- end
- -- sort each allyteam's list of playerteams:
- -- own pteam first, then by elo of the first player on the pteam, and alphabetically otherwise
- -- dead pteams (even your own) come after alive pteams
- -- dead pteams whose first player is speccing come before dead pteams whose first player is gone
- local function sorteachteamlist(allyEntitiesSorted, allyEntities)
- for i=1,#allyEntitiesSorted do -- for every ally team
- local allyTeamID = allyEntitiesSorted[i]
- if allyEntities[allyTeamID] then
- table.sort (allyEntities[allyTeamID], function(a,b)
- if (teams[a].isDead or not teams[a].isPlaying) and not (teams[b].isDead or not teams[b].isPlaying) then return false end
- if (teams[b].isDead or not teams[b].isPlaying) and not (teams[a].isDead or not teams[a].isPlaying) then return true end
- if (teams[a].isDead or not teams[a].isPlaying) and (teams[b].isDead or not teams[b].isPlaying) then
- if teams[a].roster[1].isActive and not teams[b].roster[1].isActive then return true end
- if teams[b].roster[1].isActive and not teams[a].roster[1].isActive then return false end
- end
- if localTeam ~= 0 or teamZeroPlayers[myID] then
- if a == localTeam then return true end
- if b == localTeam then return false end
- end
- if teams[a].roster[1].elo and teams[b].roster[1].elo then
- return teams[a].roster[1].elo > teams[b].roster[1].elo
- end
- return a > b
- end
- )
- end
- end
- end
- -- add the player entities
- local function addplayerentities(allyEntities, allyTeamID, alreadyadded)
- if allyEntities[allyTeamID] and (list_size >= 3 or allyTeamID == localAlliance) then
- AddCfCheckbox(allyTeamID)
- for i=1,#allyEntities[allyTeamID] do -- for every player team on the ally team
- local teamID = allyEntities[allyTeamID][i]
- if alreadyadded then
- if not TableFind(teamID, allyClans[allyTeamID]) then
- if teams[teamID] and teams[teamID].roster and (list_size >= 2 or teamID == localTeam) then
- for k=1,#teams[teamID].roster do -- for every player on the player team
- AddEntity(teams[teamID].roster[k], teamID, allyTeamID)
- end
- end
- end
- else
- if teams[teamID] and teams[teamID].roster and (list_size >= 2 or teamID == localTeam) then
- for k=1,#teams[teamID].roster do -- for every player on the player team
- AddEntity(teams[teamID].roster[k], teamID, allyTeamID)
- end
- end
- end
- end
- end
- end
- SetupPlayerNames = function()
- entities = {}
- teams = {}
- allyTeams = {}
- allyTeamsElo = {}
- --Clan Begin
- allyClans = {}
- allyClansElo = {}
- --Clan END
- specTeam = {roster = {}}
- playerTeamStatsCache = {}
- fontsize = options.text_height.value
- scroll_cpl:ClearChildren()
- local playerlist = Spring.GetPlayerList()
- local teamsSorted = Spring.GetTeamList()
- local allyTeamsSorted = Spring.GetAllyTeamList()
- local allyClanSorted = {}
- list_size = options.list_size.value or 3
- if not (localTeam ~= 0 or teamZeroPlayers[myID]) then
- if list_size == 1 then list_size = 0 end
- if list_size == 2 then list_size = 3 end
- end
- -- register any AIs as entities, assign teams to allyTeams
- for i=1,#teamsSorted do
- local teamID = teamsSorted[i]
- if teamID ~= Spring.GetGaiaTeamID() then
- teams[teamID] = teams[teamID] or {roster = {}}
- local _,leader,isDead,isAI,_,allyTeamID = Spring.GetTeamInfo(teamID)
- if isAI then
- local skirmishAIID, name, hostingPlayerID, shortName, version, options = Spring.GetAIInfo(teamID)
- name = '<'.. name ..'> '.. shortName
- local entityID = #entities + 1
- entities[entityID] = {name = name, teamID = teamID, isAI = true}
- local index = #teams[teamID].roster + 1
- teams[teamID].roster[index] = entities[entityID]
- teams[teamID].isPlaying = true
- end
- teams[teamID].leader = leader
- allyTeams[allyTeamID] = allyTeams[allyTeamID] or {}
- allyTeams[allyTeamID][#allyTeams[allyTeamID]+1] = teamID
- if isDead then
- teams[teamID].isDead = true
- end
- end --if teamID ~= Spring.GetGaiaTeamID()
- end --for each team
- -- go through all players, register as entities, assign to teams
- -- also store the data needed later to calculate the team average elo
- for i=1, #playerlist do
- local playerID = playerlist[i]
- local name,active,spectator,teamID,allyTeamID,pingTime,cpuUsage,country,rank,customKeys = Spring.GetPlayerInfo(playerID)
- local clan, faction, level, elo
- if customKeys then
- clan = customKeys.clan
- faction = customKeys.faction
- level = customKeys.level
- elo = customKeys.elo
- end
- if teamID == 0 and not spectator then
- teamZeroPlayers[playerID] = true
- end
- if teamID ~= 0 or teamZeroPlayers[playerID] then
- local entityID = #entities + 1
- entities[entityID] = {
- playerID = playerID,
- name = name,
- isActive = active,
- isSpec = spectator,
- teamID = teamID,
- pingTime = pingTime,
- cpuUsage = cpuUsage,
- country = country,
- rank = rank,
- clan = clan,
- faction = faction,
- level = level,
- elo = elo,
- }
- local index = #teams[teamID].roster + 1
- teams[teamID].roster[index] = entities[entityID]
- if not (spectator or (not active and Spring.GetGameSeconds() > 0.1 and cpuUsage < 1)) then
- teams[teamID].isPlaying = true
- if allyTeamID and elo then
- if allyTeamsElo[allyTeamID] then
- allyTeamsElo[allyTeamID].total = allyTeamsElo[allyTeamID].total + elo
- allyTeamsElo[allyTeamID].count = allyTeamsElo[allyTeamID].count + 1
- else
- allyTeamsElo[allyTeamID] = { ["total"] = elo, ["count"] = 1}
- end
- end
- --Clan Begin
- if allyTeamID and clan == myClan then
- if not TableFind(allyTeamID, allyClanSorted) then
- allyClanSorted[#allyClanSorted+1] = allyTeamID
- end
- allyClans[allyTeamID] = allyClans[allyTeamID] or {}
- allyClans[allyTeamID][#allyClans[allyTeamID]+1] = teamID
- if allyClansElo[allyTeamID] then
- allyClansElo[allyTeamID].total = allyClansElo[allyTeamID].total + elo
- allyClansElo[allyTeamID].count = allyClansElo[allyTeamID].count + 1
- else
- allyClansElo[allyTeamID] = { ["total"] = elo, ["count"] = 1}
- end
- end
- --Clan End
- end
- end
- if spectator and active then
- specTeam.roster[#(specTeam.roster) + 1] = {
- playerID = playerID,
- name = name,
- isActive = active,
- isSpec = spectator,
- teamID = teamID,
- pingTime = pingTime,
- cpuUsage = cpuUsage,
- country = country,
- rank = rank,
- clan = clan,
- faction = faction,
- level = level,
- elo = elo,
- }
- end
- end
- -- sort each playerteam's roster: self first, then by elo, and alphabetically otherwise
- for i=1,#teams do
- if teams[i].roster then
- table.sort (teams[i].roster, function(a,b)
- if localTeam ~= 0 or teamZeroPlayers[myID] then
- if a.playerID == myID then return true end
- if b.playerID == myID then return false end
- end
- return a.elo > b.elo
- end
- )
- end
- end
- --Clan Begin
- sorteachteamlist(allyTeamsSorted, allyTeams)
- sorteachteamlist(allyClanSorted, allyClans)
- --Caln End
- -- if we haven't ever done so before, build the ally team sort order
- -- ally teams are sorted by total elo, so larger teams will be above smaller teams
- -- ally team sort order is determined at the very start, and doesn't change even if
- -- the team composition changes (except that dead teams will fall to the bottom)
- --
- -- while we're at it, determine whether or not to show the ally team summary lines
- --
- if #allyTeamOrderRank == 0 then
- if #allyTeams[localAlliance] > 2 then myTeamIsVeryBig = true end
- for i=1,#allyTeamsSorted do -- for every ally team
- local allyTeamID = allyTeamsSorted[i]
- allyTeamOrderRank[allyTeamID] = 0
- if allyTeams[allyTeamID] then
- if #allyTeams[allyTeamID] > 2 then existsVeryBigTeam = true end
- if #allyTeams[allyTeamID] > 1 then numBigTeams = numBigTeams + 1 end
- for j=1,#allyTeams[allyTeamID] do -- for every player team on the ally team
- local teamID = allyTeams[allyTeamID][j]
- if teams[teamID] and teams[teamID].roster then
- for k=1,#teams[teamID].roster do -- for every player on the player team
- if teams[teamID].roster[k].elo then allyTeamOrderRank[allyTeamID] = allyTeamOrderRank[allyTeamID] + teams[teamID].roster[k].elo end
- end
- end
- end
- end
- end
- end
- --Clan Begin
- if #allyClanOrderRank == 0 then
- if allyClans[localAlliance] then
- if #allyClans[localAlliance] > 1 then myClanIsVeryBig = true end
- for i=1,#allyClanSorted do -- for every ally team
- local allyTeamID = allyClanSorted[i]
- allyClanOrderRank[allyTeamID] = 0
- if allyClans[allyTeamID] then
- if #allyClans[allyTeamID] > 1 then existsVeryBigClan = true end --Have to be diffrent extra var
- if #allyClans[allyTeamID] > 1 then numBigClan = numBigClan + 1 end --here too
- for j=1,#allyClans[allyTeamID] do -- for every player team on the ally team
- local teamID = allyClans[allyTeamID][j]
- if teams[teamID] and teams[teamID].roster then
- for k=1,#teams[teamID].roster do -- for every player on the player team
- if teams[teamID].roster[k].elo then allyClanOrderRank[allyTeamID] = allyClanOrderRank[allyTeamID] + teams[teamID].roster[k].elo end
- end
- end
- end
- end
- end
- end
- end
- --Clan End
- -- find out which ally teams are dead
- allyTeamsDead = {}
- for i=1,#allyTeamsSorted do -- for every ally team
- local allyTeamID = allyTeamsSorted[i]
- allyTeamsDead[allyTeamID] = true
- if allyTeams[allyTeamID] then
- for j=1,#allyTeams[allyTeamID] do -- for every player team on the ally team
- local teamID = allyTeams[allyTeamID][j]
- if teams[teamID] and not (teams[teamID].isDead or not teams[teamID].isPlaying) then
- allyTeamsDead[allyTeamID] = nil
- end
- end
- end
- end
- --Clan Begin
- allyClanDead = {}
- for i=1,#allyClanSorted do
- local allyTeamID = allyClanSorted[i]
- allyClanDead[allyTeamID] = true
- if allyClans[allyTeamID] then
- for j=1,#allyClans[allyTeamID] do -- for every player team on the ally team
- local teamID = allyTeams[allyTeamID][j]
- if teams[teamID] and not (teams[teamID].isDead or not teams[teamID].isPlaying) then
- allyClanDead[allyTeamID] = nil
- end
- end
- end
- end
- --Clan END
- -- sort allyteams: own at top, others in order by total elo, dead teams at bottom
- table.sort(allyTeamsSorted, function(a,b)
- if allyTeamsDead[a] and not allyTeamsDead[b] then return false end
- if allyTeamsDead[b] and not allyTeamsDead[a] then return true end
- if allyTeamsDead[b] and allyTeamsDead[a] and allyTeams[a] and allyTeams[b] then
- local teamIDa = allyTeams[a][1]
- local teamIDb = allyTeams[b][1]
- if teamIDa and teamIDb and teams[teamIDa].roster and teams[teamIDb].roster then
- if teams[teamIDa].roster[1].isActive and not teams[teamIDb].roster[1].isActive then return true end
- if teams[teamIDb].roster[1].isActive and not teams[teamIDa].roster[1].isActive then return false end
- end
- end
- if localTeam ~= 0 or teamZeroPlayers[myID] then
- if a == localAlliance then return true end
- if b == localAlliance then return false end
- end
- return allyTeamOrderRank[a] > allyTeamOrderRank[b]
- end
- )
- -- Clan Begin
- table.sort(allyClanSorted, function(a,b)
- if allyClanDead[a] and not allyClanDead[b] then return false end
- if allyClanDead[b] and not allyClanDead[a] then return true end
- if allyClanDead[b] and allyClanDead[a] and allyClans[a] and allyClans[b] then
- local teamIDa = allyClans[a][1]
- local teamIDb = allyClans[b][1]
- if teamIDa and teamIDb and teams[teamIDa].roster and teams[teamIDb].roster then
- if teams[teamIDa].roster[1].isActive and not teams[teamIDb].roster[1].isActive then return true end
- if teams[teamIDb].roster[1].isActive and not teams[teamIDa].roster[1].isActive then return false end
- end
- end
- if localTeam ~= 0 or teamZeroPlayers[myID] then
- if a == localAlliance then return true end
- if b == localAlliance then return false end
- end
- return allyClanOrderRank[a] > allyClanOrderRank[b]
- end
- )
- --Clan END
- -- sort the specteam
- table.sort(specTeam.roster, function(a,b)
- return a.name:lower() < b.name:lower()
- end)
- row = 0
- AddTableHeaders()
- row = row + 1
- -- Clan Begin
- local clanmebers = false
- if list_size ~= 0 then
- if amSpec then
- if options.showSummaries.value and (existsVeryBigTeam or numBigTeams > 2) then
- for i=1,#allyTeamsSorted do
- local allyTeamID = allyTeamsSorted[i]
- AddTeamSummarie(allyTeamID)
- row = row + 0.2
- if options.showClanSummaries.value and allyClans[allyTeamID] and #allyClans[allyTeamID] > 1 then
- AddClanSummarie(allyTeamID)
- row = row + 0.2
- clanmebers = true
- addplayerentities(allyClans, allyTeamID, false)
- row = row + 0.4
- end
- if allyTeams[allyTeamID] then
- addplayerentities(allyTeams, allyTeamID, clanmebers)
- end
- if i ~= (#allyTeamsSorted-1) then
- row = row + 0.5
- end
- end
- else
- for i=1,#allyTeamsSorted do -- for every ally team
- local allyTeamID = allyTeamsSorted[i]
- if allyTeams[allyTeamID] then
- addplayerentities(allyTeams, allyTeamID, clanmebers)
- if numBigTeams > 2 then row = row + 0.6 end
- end
- end
- end
- else
- if options.showSummaries.value and myTeamIsVeryBig then
- --AddTeamSummarie({localTeam})
- AddTeamSummarie(localAlliance)
- row = row + 0.2
- if options.showClanSummaries.value and allyClans[localAlliance] and #allyClans[localAlliance] > 1 then
- AddClanSummarie(localAlliance)
- row = row + 0.2
- clanmebers = true
- addplayerentities(allyClans, localAlliance, false)
- row = row + 0.4
- end
- if allyTeams[localAlliance] then
- addplayerentities(allyTeams, localAlliance, clanmebers)
- end
- clanmebers = false
- row = row + 0.5
- for i=1,#allyTeamsSorted do
- if localAlliance ~= allyTeamsSorted[i] then
- local allyTeamID = allyTeamsSorted[i]
- AddTeamSummarieNonSpec(allyTeamID)
- row = row + 0.2
- if options.showClanSummaries.value and allyClans[allyTeamID] and #allyClans[allyTeamID] > 1 then
- AddClanSummarieNonSpec(allyTeamID)
- row = row + 0.2
- clanmebers = true
- addplayerentities(allyClans, allyTeamID, false)
- row = row + 0.4
- end
- if allyTeams[allyTeamID] then
- addplayerentities(allyTeams, allyTeamID, clanmebers)
- end
- clanmebers = false
- if i ~= (#allyTeamsSorted-1) then
- row = row + 0.5
- end
- end
- end
- else
- for i=1,#allyTeamsSorted do -- for every ally team
- local allyTeamID = allyTeamsSorted[i]
- if allyTeams[allyTeamID] then
- addplayerentities(allyTeams, allyTeamID, clanmebers)
- if numBigTeams > 2 then row = row + 0.6 end
- end
- end
- end
- end
- end
- -- Clan END
- -- add the spectator entities
- if list_size == 4 and #specTeam.roster ~= 0 then
- teams[-1] = specTeam
- allyTeams[-1] = {-1}
- for k=1,#specTeam.roster do
- AddEntity(specTeam.roster[k], -1, -1)
- end
- end
- MakeSpecTooltip()
- -- ceasefire: restricted zones button
- if cf then
- scroll_cpl:AddChild( Checkbox:New{
- x=5, y=(fontsize+1) * (row + 0.5),
- height=fontsize * 1.5, width=160,
- caption = 'Place Restricted Zones',
- checked = WG.rzones.rZonePlaceMode,
- OnChange = { function(self) WG.rzones.rZonePlaceMode = not WG.rzones.rZonePlaceMode; end },
- } )
- row = row + 1.5
- end
- AlignScrollPanel()
- end
- SetupScrollPanel = function ()
- if scroll_cpl then scroll_cpl:Dispose() end
- local scpl = {
- parent = window_cpl,
- --width = "100%",
- --height = "100%",
- backgroundColor = {1,1,1,options.backgroundOpacity.value},
- borderColor = {1,1,1,options.backgroundOpacity.value},
- padding = {0, 5, 0, 5},
- --autosize = true,
- --right = 0,
- scrollbarSize = 6,
- width = x_bound,
- horizontalScrollbar = false,
- hitTestAllowEmpty = true,
- noMouseWheel = not options.mousewheel.value,
- }
- if options.alignToLeft.value then
- scpl.left = 0
- else
- scpl.right = 0
- end
- scroll_cpl = ScrollPanel:New(scpl)
- SetupPlayerNames()
- end
- SetupPanels = function ()
- CalculateWidths()
- local x,y,height,width
- if window_cpl then
- y = window_cpl.y
- height = window_cpl.height
- width = math.max(x_windowbound, lastChosenSizeX)
- x = options.alignToLeft.value and window_cpl.x or (window_cpl.x + window_cpl.width - width)
- window_cpl:Dispose()
- else
- x = screen0.width - x_windowbound
- y = screen0.height - 150
- width = x_windowbound
- height = 150
- end
- lastSizeX = width
- window_cpl = Window:New{
- dockable = true,
- name = "Player List",
- color = {0,0,0,0},
- x = x,
- y = y,
- width = width,
- height = height,
- padding = {0, 0, 0, 0};
- parent = screen0,
- draggable = false,
- resizable = false,
- tweakDraggable = true,
- tweakResizable = true,
- minimizable = false,
- minWidth = x_windowbound,
- OnMouseDown={ function(self)
- local alt, ctrl, meta, shift = Spring.GetModKeyState()
- if not meta then return false end
- WG.crude.OpenPath(options_path)
- WG.crude.ShowMenu()
- return true
- end },
- }
- SetupScrollPanel()
- end
- function ToggleVisibility()
- if window_cpl and scroll_cpl then
- if options.visible.value then
- window_cpl:AddChild(scroll_cpl)
- else
- window_cpl:RemoveChild(scroll_cpl)
- end
- end
- end
- function PlayersChanged()
- if amSpec then
- SetupPlayerNames()
- else
- local _,_,amNowSpec = Spring.GetPlayerInfo(myID)
- if amNowSpec then
- amSpec = amNowSpec
- SetupPanels()
- else
- SetupPlayerNames()
- end
- end
- end
- --------------------------------------------------------------------------------
- --------------------------------------------------------------------------------
- function widget:Shutdown()
- Spring.SendCommands({"info 1"})
- end
- -- Part of an experiment to try to improve performance, will come back to it later
- -- local updateModulus = 8
- -- local updateCount = 0
- function widget:Update(s)
- timer = timer + s
- if timer > UPDATE_FREQUENCY then
- timer = 0
- if (lastSizeX ~= window_cpl.width or lastSizeY ~= window_cpl.height) then --//if user resize the player-list
- AlignScrollPanel()
- lastChosenSizeX = window_cpl.width
- lastSizeX = window_cpl.width
- lastSizeY = window_cpl.height
- else
- -- for i=updateCount+1,#playerTeamStatsCache,updateModulus do
- -- playerTeamStatsCache[i] = nil
- -- end
- -- updateCount = (updateCount + 1) % updateModulus
- if (not scroll_cpl.parent) then return end --//don't update when window is hidden
- UpdatePlayerInfo()
- end
- end
- end
- function widget:PlayerChanged(playerID)
- PlayersChanged()
- end
- function widget:PlayerAdded(playerID)
- PlayersChanged()
- end
- function widget:PlayerRemoved(playerID)
- PlayersChanged()
- end
- function widget:TeamDied(teamID)
- PlayersChanged()
- end
- function widget:TeamChanged(teamID)
- PlayersChanged()
- end
- -- workaround for stupidity
- function widget:GameStart()
- SetupPanels()
- end
- -----------------------------------------------------------------------
- -- we need both UnitCreated and UnitFinished because mobiles and static defense aren't treated the same >:<
- function widget:UnitCreated(unitID, unitDefID, unitTeam)
- local speed = UnitDefs[unitDefID].speed
- local unarmed = UnitDefs[unitDefID].springCategories.unarmed
- if (speed == nil or speed == 0) and not unarmed then -- is static-d
- ProcessUnit(unitID, unitDefID, unitTeam)
- end
- end
- function widget:UnitFinished(unitID, unitDefID, unitTeam)
- local speed = UnitDefs[unitDefID].speed
- local unarmed = UnitDefs[unitDefID].springCategories.unarmed
- if speed and speed ~= 0 and (not finishedUnits[unitID]) then -- mobile unit
- ProcessUnit(unitID, unitDefID, unitTeam)
- end
- end
- function widget:UnitDestroyed(unitID, unitDefID, unitTeam)
- local speed = UnitDefs[unitDefID].speed
- local unarmed = UnitDefs[unitDefID].springCategories.unarmed
- if speed and speed ~= 0 then -- mobile unit
- if finishedUnits[unitID] then
- ProcessUnit(unitID, unitDefID, unitTeam, true)
- end
- elseif not unarmed then -- static defense
- ProcessUnit(unitID, unitDefID, unitTeam, true)
- end
- end
- function widget:UnitGiven(unitID, unitDefID, newTeamID, teamID)
- -- doing this twice is a bit inefficient but bah
- ProcessUnit(unitID, unitDefID, teamID, true)
- ProcessUnit(unitID, unitDefID, newTeamID)
- end
- -----------------------------------------------------------------------
- function widget:Initialize()
- if (not WG.Chili) then
- widgetHandler:RemoveWidget()
- return
- end
- Chili = WG.Chili
- Image = Chili.Image
- Button = Chili.Button
- Checkbox = Chili.Checkbox
- Window = Chili.Window
- ScrollPanel = Chili.ScrollPanel
- StackPanel = Chili.StackPanel
- Label = Chili.Label
- screen0 = Chili.Screen0
- color2incolor = Chili.color2incolor
- incolor2color = Chili.incolor2color
- green = color2incolor(0,1,0,1)
- red = color2incolor(1,0,0,1)
- orange = color2incolor(1,0.4,0,1)
- yellow = color2incolor(1,1,0,1)
- cyan = color2incolor(0,1,1,1)
- white = color2incolor(1,1,1,1)
- SetupPanels()
- Spring.SendCommands({"info 0"})
- lastSizeX = window_cpl.width
- lastSizeY = window_cpl.height
- self:LocalColorRegister()
- end
- function widget:Shutdown()
- self:LocalColorUnregister()
- end
- function widget:LocalColorRegister()
- if WG.LocalColor and WG.LocalColor.RegisterListener then
- WG.LocalColor.RegisterListener(widget:GetInfo().name, SetupPlayerNames)
- end
- end
- function widget:LocalColorUnregister()
- if WG.LocalColor and WG.LocalColor.UnregisterListener then
- WG.LocalColor.UnregisterListener(widget:GetInfo().name)
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement