--[[ Addon: Taos Group Tools Author: TProg Taonnor Created by @Taonnor ]]-- --[[ Local variables ]]-- local LOG_ACTIVE = false local SWIMLANES = 6 local ROWS = 6 local REFRESHRATE = 1000 -- ms; RegisterForUpdate is in miliseconds local TIMEOUT = 4 -- s; GetTimeStamp() is in seconds local _logger = nil local _control = nil local _isActive = false --[[ Table CompactSwimlaneList ]]-- TGT_CompactSwimlaneList = {} TGT_CompactSwimlaneList.__index = TGT_CompactSwimlaneList --[[ Table Members ]]-- TGT_CompactSwimlaneList.Name = "TGT-CompactSwimlaneList" TGT_CompactSwimlaneList.Swimlanes = {} --[[ Sets visibility of labels ]]-- function TGT_CompactSwimlaneList.RefreshList() --if (LOG_ACTIVE) then _logger:logTrace("TGT_CompactSwimlaneList.RefreshList") end -- Check all swimlanes for i,swimlane in ipairs(TGT_CompactSwimlaneList.Swimlanes) do TGT_CompactSwimlaneList.ClearPlayersFromSwimlane(swimlane) end end --[[ Sorts swimlane ]]-- function TGT_CompactSwimlaneList.SortSwimlane(swimlane) if (LOG_ACTIVE) then _logger:logTrace("TGT_CompactSwimlaneList.SortSwimlane") end -- Comparer function compare(playerLeft, playerRight) if (playerLeft.RelativeUltimate == playerRight.RelativeUltimate) then return playerLeft.PingTag < playerRight.PingTag else return playerLeft.RelativeUltimate > playerRight.RelativeUltimate end end table.sort(swimlane.Players, compare) -- Sort by name -- Update sorted swimlane list for i,swimlanePlayer in ipairs(swimlane.Players) do TGT_CompactSwimlaneList.UpdateListRow(swimlane.SwimlaneControl:GetNamedChild("Row" .. i), swimlanePlayer) end end --[[ Updates list row ]]-- function TGT_CompactSwimlaneList.UpdateListRow(row, player) if (LOG_ACTIVE) then --_logger:logTrace("TGT_CompactSwimlaneList.UpdateListRow") end local playerName = player.PlayerName local nameLength = string.len(playerName) if (nameLength > 6) then playerName = string.sub(playerName, 0, 5) .. ".." end row:GetNamedChild("SenderNameValueLabel"):SetText(playerName) row:GetNamedChild("RelativeUltimateStatusBar"):SetValue(player.RelativeUltimate) if (player.IsPlayerDead) then -- Dead Color row:GetNamedChild("SenderNameValueLabel"):SetColor(0.5, 0.5, 0.5, 0.8) row:GetNamedChild("RelativeUltimateStatusBar"):SetColor(0.8, 0.03, 0.03, 0.7) elseif (player.RelativeUltimate == 100) then -- Ready Color row:GetNamedChild("SenderNameValueLabel"):SetColor(1, 1, 1, 1) row:GetNamedChild("RelativeUltimateStatusBar"):SetColor(0.03, 0.7, 0.03, 0.7) else -- Inprogress Color row:GetNamedChild("SenderNameValueLabel"):SetColor(1, 1, 1, 0.8) row:GetNamedChild("RelativeUltimateStatusBar"):SetColor(0.03, 0.03, 0.7, 0.7) end row:SetHidden(false) end --[[ Updates list row ]]-- function TGT_CompactSwimlaneList.UpdatePlayer(player) if (LOG_ACTIVE) then --_logger:logTrace("TGT_CompactSwimlaneList.UpdatePlayer") end if (player) then local swimLane = TGT_CompactSwimlaneList.GetSwimLane(player.UltimateGroup.GroupAbilityId) if (swimLane) then local row = TGT_CompactSwimlaneList.GetSwimLaneRow(swimLane, player.PlayerName) local updateNeeded = true -- Update timestamp if (row ~= nil) then for i,swimlanePlayer in ipairs(swimLane.Players) do if (swimlanePlayer.PlayerName == player.PlayerName) then swimlanePlayer.LastMapPingTimestamp = GetTimeStamp() updateNeeded = swimlanePlayer.IsPlayerDead ~= player.IsPlayerDead or swimlanePlayer.RelativeUltimate ~= player.RelativeUltimate if (swimlanePlayer.RelativeUltimate > player.RelativeUltimate) then local sound = TGT_SettingsHandler.SavedVariables.Sound if (sound[1] > 1) then PlaySound(SOUNDS[sound[2]]) end end swimlanePlayer.IsPlayerDead = player.IsPlayerDead swimlanePlayer.RelativeUltimate = player.RelativeUltimate break end end else -- Add new player local nextFreeRow = 1 for i,player in ipairs(swimLane.Players) do nextFreeRow = nextFreeRow + 1 end if (nextFreeRow <= ROWS) then if (LOG_ACTIVE) then --_logger:logDebug("TGT_CompactSwimlaneList.UpdatePlayer, add player " .. tostring(player.PlayerName) .. " to row " .. tostring(nextFreeRow)) end player.LastMapPingTimestamp = GetTimeStamp() swimLane.Players[nextFreeRow] = player row = swimLane.SwimlaneControl:GetNamedChild("Row" .. nextFreeRow) else if (LOG_ACTIVE) then _logger:logDebug("TGT_CompactSwimlaneList.UpdatePlayer, too much players for one swimlane " .. tostring(nextFreeRow)) end end end -- Only update if player in a row if (row ~= nil and updateNeeded) then if (TGT_SettingsHandler.SavedVariables.IsSortingActive) then -- Sort swimlane with all players TGT_CompactSwimlaneList.SortSwimlane(swimLane) else -- Directly update row with player TGT_CompactSwimlaneList.UpdateListRow(row, player) end end else if (LOG_ACTIVE) then _logger:logDebug("TGT_CompactSwimlaneList.UpdatePlayer, swimlane not found for ultimategroup " .. tostring(ultimateGroup.GroupName)) end end end end --[[ Get swimlane from current SwimLanes ]]-- function TGT_CompactSwimlaneList.GetSwimLane(ultimateGroupId) if (LOG_ACTIVE) then --_logger:logTrace("TGT_CompactSwimlaneList.GetSwimLane") --_logger:logDebug("ultimateGroupId", ultimateGroupId) end if (ultimateGroupId ~= 0) then for i,swimLane in ipairs(TGT_CompactSwimlaneList.Swimlanes) do if (swimLane.UltimateGroupId == ultimateGroupId) then return swimLane end end --if (LOG_ACTIVE) then _logger:logDebug("TGT_CompactSwimlaneList.GetSwimLane, swimLane not found " .. tostring(ultimateGroupId)) end return nil else _logger:logError("TGT_CompactSwimlaneList.GetSwimLane, ultimateGroupId is 0") return nil end end --[[ Get Player Row from current players in swimlane ]]-- function TGT_CompactSwimlaneList.GetSwimLaneRow(swimLane, playerName) if (LOG_ACTIVE) then --_logger:logTrace("TGT_CompactSwimlaneList.GetSwimLaneRow") --_logger:logDebug("swimLane ID", swimLane.Id) end if (swimLane) then for i,player in ipairs(swimLane.Players) do --if (LOG_ACTIVE) then _logger:logDebug(player.PlayerName .. " == " .. playerName) end if (player.PlayerName == playerName) then return swimLane.SwimlaneControl:GetNamedChild("Row" .. i) end end --if (LOG_ACTIVE) then _logger:logDebug("TGT_CompactSwimlaneList.GetSwimLane, player not found " .. tostring(playerName)) end return nil else _logger:logError("TGT_CompactSwimlaneList.GetSwimLane, swimLane is nil") return nil end end --[[ Clears all players in swimlane ]]-- function TGT_CompactSwimlaneList.ClearPlayersFromSwimlane(swimlane) if (LOG_ACTIVE) then --_logger:logTrace("TGT_CompactSwimlaneList.ClearPlayersFromSwimlane") --_logger:logDebug("swimlane ID", swimlane.Id) end if (swimlane) then for i=1, ROWS, 1 do local row = swimlane.SwimlaneControl:GetNamedChild("Row" .. i) local swimlanePlayer = swimlane.Players[i] if (swimlanePlayer ~= nil) then local isPlayerNotGrouped = IsUnitGrouped(swimlanePlayer.PingTag) == false local isPlayerTimedOut = (GetTimeStamp() - swimlanePlayer.LastMapPingTimestamp) > TIMEOUT local isPlayerUltimateNotCorrect = swimlane.UltimateGroupId ~= swimlanePlayer.UltimateGroup.GroupAbilityId if (isPlayerNotGrouped or isPlayerTimedOut or isPlayerUltimateNotCorrect) then --if (LOG_ACTIVE) then _logger:logDebug("Player invalid, hide row: " .. tostring(i)) end row:SetHidden(true) table.remove(swimlane.Players, i) end else --if (LOG_ACTIVE) then _logger:logDebug("Row empty, hide: " .. tostring(i)) end row:SetHidden(true) end end end end --[[ SetControlScale sets the Scale in UI elements ]]-- function TGT_CompactSwimlaneList.SetControlScale(scale) if (LOG_ACTIVE) then _logger:logTrace("TGT_CompactSwimlaneList.SetControlScale") _logger:logDebug("scale", scale) end _control:SetScale(scale) end --[[ SetControlMovable sets the Movable and MouseEnabled flag in UI elements ]]-- function TGT_CompactSwimlaneList.SetControlMovable(isMovable) if (LOG_ACTIVE) then _logger:logTrace("TGT_CompactSwimlaneList.SetControlMovable") _logger:logDebug("isMovable", isMovable) end _control:GetNamedChild("MovableControl"):SetHidden(isMovable == false) _control:SetMovable(isMovable) _control:SetMouseEnabled(isMovable) end --[[ RestorePosition sets TGT_CompactSwimlaneList on settings position ]]-- function TGT_CompactSwimlaneList.RestorePosition(posX, posY) if (LOG_ACTIVE) then _logger:logTrace("TGT_CompactSwimlaneList.RestorePosition") _logger:logDebug("posX, posY", posX, posY) end _control:ClearAnchors() _control:SetAnchor(TOPLEFT, GuiRoot, TOPLEFT, posX, posY) end --[[ OnTGT_CompactSwimlaneListMoveStop saves current TGT_CompactSwimlaneList position to settings ]]-- function TGT_CompactSwimlaneList.OnCompactSwimlaneListMoveStop() if (LOG_ACTIVE) then _logger:logTrace("TGT_CompactSwimlaneList.OnCompactSwimlaneListMoveStop") end local left = _control:GetLeft() local top = _control:GetTop() TGT_SettingsHandler.SavedVariables.PosX = left TGT_SettingsHandler.SavedVariables.PosY = top if (LOG_ACTIVE) then _logger:logDebug("PosX, PosY", TGT_SettingsHandler.SavedVariables.PosX, TGT_SettingsHandler.SavedVariables.PosY) end end --[[ SetControlHidden sets hidden on control ]]-- function TGT_CompactSwimlaneList.SetControlHidden() if (LOG_ACTIVE) then _logger:logTrace("TGT_CompactSwimlaneList.SetControlHidden") end -- Get isActive from settings local isActive = TGT_SettingsHandler.IsCompactSwimlaneListVisible() if (LOG_ACTIVE) then _logger:logDebug("isActive", isActive) end if (isActive) then if (GetIsUnitGrouped() and GetGroupSize() >= TGT_SettingsHandler.SavedVariables.VisibleOffset) then _control:SetHidden(CurrentHudHiddenState()) else _control:SetHidden(true) end else _control:SetHidden(true) end end --[[ SetSwimlanesVisible sets swimlanes visibility on base of settings ]]-- function TGT_CompactSwimlaneList.SetSwimlanesVisible(visibleSwimlanes) if (LOG_ACTIVE) then _logger:logTrace("TGT_CompactSwimlaneList.SetSwimlanesVisible") _logger:logDebug("visibleSwimlanes", visibleSwimlanes) end for i=1, SWIMLANES, 1 do if (i > visibleSwimlanes) then TGT_CompactSwimlaneList.Swimlanes[i].SwimlaneControl:SetHidden(true) else TGT_CompactSwimlaneList.Swimlanes[i].SwimlaneControl:SetHidden(false) end end end --[[ SetControlActive sets hidden on control ]]-- function TGT_CompactSwimlaneList.SetControlActive() if (LOG_ACTIVE) then _logger:logTrace("TGT_CompactSwimlaneList.SetControlActive") end TGT_CompactSwimlaneList.SetControlHidden() -- Get isActive from settings local isActive = TGT_SettingsHandler.IsCompactSwimlaneListVisible() if (LOG_ACTIVE) then _logger:logDebug("isActive", isActive) end if (_isActive ~= isActive) then _isActive = isActive if (isActive) then if (LOG_ACTIVE) then _logger:logDebug("TGT_CompactSwimlaneList.SetControlActive RegisterCallbacks") end TGT_CompactSwimlaneList.SetControlMovable(TGT_SettingsHandler.SavedVariables.Movable) TGT_CompactSwimlaneList.RestorePosition(TGT_SettingsHandler.SavedVariables.PosX, TGT_SettingsHandler.SavedVariables.PosY) TGT_CompactSwimlaneList.SetSwimlanesVisible(TGT_SettingsHandler.SavedVariables.Swimlanes) TGT_CompactSwimlaneList.SetControlScale(TGT_SettingsHandler.SavedVariables.SwimlaneScaling) -- Start timeout timer EVENT_MANAGER:RegisterForUpdate(TGT_CompactSwimlaneList.Name, REFRESHRATE, TGT_CompactSwimlaneList.RefreshList) CALLBACK_MANAGER:RegisterCallback(TAO_GROUP_CHANGED, TGT_CompactSwimlaneList.RefreshList) CALLBACK_MANAGER:RegisterCallback(TGT_PLAYER_DATA_CHANGED, TGT_CompactSwimlaneList.UpdatePlayer) CALLBACK_MANAGER:RegisterCallback(TGT_MOVABLE_CHANGED, TGT_CompactSwimlaneList.SetControlMovable) CALLBACK_MANAGER:RegisterCallback(TGT_SWIMLANE_ULTIMATE_GROUP_ID_CHANGED, TGT_CompactSwimlaneList.SetSwimlaneUltimate) CALLBACK_MANAGER:RegisterCallback(TAO_HUD_HIDDEN_STATE_CHANGED, TGT_CompactSwimlaneList.SetControlHidden) CALLBACK_MANAGER:RegisterCallback(TGT_VISIBLE_OFFSET_CHANGED, TGT_CompactSwimlaneList.SetControlHidden) CALLBACK_MANAGER:RegisterCallback(TGT_SWIMLANES_CHANGED, TGT_CompactSwimlaneList.SetSwimlanesVisible) CALLBACK_MANAGER:RegisterCallback(TGT_SWIMLANE_SCALING_CHANGED, TGT_CompactSwimlaneList.SetControlScale) else if (LOG_ACTIVE) then _logger:logDebug("TGT_CompactSwimlaneList.SetControlActive UnregisterCallbacks") end -- Start timeout timer EVENT_MANAGER:UnregisterForUpdate(TGT_CompactSwimlaneList.Name) CALLBACK_MANAGER:UnregisterCallback(TAO_GROUP_CHANGED, TGT_CompactSwimlaneList.RefreshList) CALLBACK_MANAGER:UnregisterCallback(TGT_PLAYER_DATA_CHANGED, TGT_CompactSwimlaneList.UpdatePlayer) CALLBACK_MANAGER:UnregisterCallback(TGT_MOVABLE_CHANGED, TGT_CompactSwimlaneList.SetControlMovable) CALLBACK_MANAGER:UnregisterCallback(TGT_SWIMLANE_ULTIMATE_GROUP_ID_CHANGED, TGT_CompactSwimlaneList.SetSwimlaneUltimate) CALLBACK_MANAGER:UnregisterCallback(TAO_HUD_HIDDEN_STATE_CHANGED, TGT_CompactSwimlaneList.SetControlHidden) CALLBACK_MANAGER:UnregisterCallback(TGT_VISIBLE_OFFSET_CHANGED, TGT_CompactSwimlaneList.SetControlHidden) CALLBACK_MANAGER:UnregisterCallback(TGT_SWIMLANES_CHANGED, TGT_CompactSwimlaneList.SetSwimlanesVisible) CALLBACK_MANAGER:UnregisterCallback(TGT_SWIMLANE_SCALING_CHANGED, TGT_CompactSwimlaneList.SetControlScale) end else if (LOG_ACTIVE) then _logger:logDebug("_isActive == isActive; State not changed, do not update") end end end --[[ OnSwimlaneHeaderClicked called on header clicked ]]-- function TGT_CompactSwimlaneList.OnSwimlaneHeaderClicked(button, swimlaneId) if (LOG_ACTIVE) then _logger:logTrace("TGT_CompactSwimlaneList.OnSwimlaneHeaderClicked") _logger:logDebug("swimlaneId", swimlaneId) end if (button ~= nil) then CALLBACK_MANAGER:RegisterCallback(TGT_SET_ULTIMATE_GROUP, TGT_CompactSwimlaneList.OnSetUltimateGroup) CALLBACK_MANAGER:FireCallbacks(TGT_SHOW_ULTIMATE_GROUP_MENU, button, swimlaneId) else _logger:logError("TGT_CompactSwimlaneList.OnSwimlaneHeaderClicked, button nil") end end --[[ OnSetUltimateGroup called on header clicked ]]-- function TGT_CompactSwimlaneList.OnSetUltimateGroup(group, swimlaneId) if (LOG_ACTIVE) then _logger:logTrace("TGT_CompactSwimlaneList.OnSetUltimateGroup") _logger:logDebug("group.GroupName, swimlaneId", group.GroupName, swimlaneId) end CALLBACK_MANAGER:UnregisterCallback(TGT_SET_ULTIMATE_GROUP, TGT_CompactSwimlaneList.OnSetUltimateGroup) if (group ~= nil and swimlaneId ~= nil and swimlaneId >= 1 and swimlaneId <= 6) then TGT_SettingsHandler.SetSwimlaneUltimateGroupIdSettings(swimlaneId, group) else _logger:logError("TGT_UltimateGroupMenu.ShowUltimateGroupMenu, group nil or swimlaneId invalid") end end --[[ SetSwimlaneUltimate sets the swimlane header icon in base of ultimateGroupId ]]-- function TGT_CompactSwimlaneList.SetSwimlaneUltimate(swimlaneId, ultimateGroup) if (LOG_ACTIVE) then _logger:logTrace("TGT_CompactSwimlaneList.SetSwimlaneUltimate") _logger:logDebug("ultimateGroup.GroupName, swimlaneId", ultimateGroup.GroupName, swimlaneId) end local swimlaneObject = TGT_CompactSwimlaneList.Swimlanes[swimlaneId] local iconControl = swimlaneObject.SwimlaneControl:GetNamedChild("Header"):GetNamedChild("SelectorButtonControl"):GetNamedChild("Icon") if (ultimateGroup ~= nil and iconControl ~= nil) then iconControl:SetTexture(GetAbilityIcon(ultimateGroup.GroupAbilityId)) swimlaneObject.UltimateGroupId = ultimateGroup.GroupAbilityId TGT_CompactSwimlaneList.ClearPlayersFromSwimlane(swimlaneObject) else _logger:logError("TGT_CompactSwimlaneList.SetSwimlaneUltimateIcon, icon is " .. tostring(icon) .. ";" .. tostring(iconControl) .. ";" .. tostring(ultimateGroup)) end end --[[ CreateCompactSwimlaneListHeaders creates swimlane list headers ]]-- function TGT_CompactSwimlaneList.CreateCompactSwimlaneListHeaders() if (LOG_ACTIVE) then _logger:logTrace("TGT_CompactSwimlaneList.CreateCompactSwimlaneListHeaders") end for i=1, SWIMLANES, 1 do local ultimateGroupId = TGT_SettingsHandler.SavedVariables.SwimlaneUltimateGroupIds[i] local ultimateGroup = TGT_UltimateGroupHandler.GetUltimateGroupByAbilityId(ultimateGroupId) local swimlaneControlName = "Swimlane" .. tostring(i) local swimlaneControl = _control:GetNamedChild(swimlaneControlName) -- Add button local button = swimlaneControl:GetNamedChild("Header"):GetNamedChild("SelectorButtonControl"):GetNamedChild("Button") button:SetHandler("OnClicked", function() TGT_CompactSwimlaneList.OnSwimlaneHeaderClicked(button, i) end) local swimLane = {} swimLane.Id = i swimLane.SwimlaneControl = swimlaneControl swimLane.Players = {} if (ultimateGroup ~= nil) then if (LOG_ACTIVE) then _logger:logDebug("Create Swimlane", i) _logger:logDebug("ultimateGroup.GroupName", ultimateGroup.GroupName) _logger:logDebug("swimlaneControlName", swimlaneControlName) end local icon = swimlaneControl:GetNamedChild("Header"):GetNamedChild("SelectorButtonControl"):GetNamedChild("Icon") icon:SetTexture(GetAbilityIcon(ultimateGroup.GroupAbilityId)) swimLane.UltimateGroupId = ultimateGroup.GroupAbilityId else _logger:logError("TGT_CompactSwimlaneList.CreateCompactSwimlaneListHeaders, ultimateGroup nil.") end TGT_CompactSwimlaneList.CreateCompactSwimlaneListRows(swimlaneControl) TGT_CompactSwimlaneList.Swimlanes[i] = swimLane end end --[[ CreateCompactSwimlaneListRows creates swimlane lsit rows ]]-- function TGT_CompactSwimlaneList.CreateCompactSwimlaneListRows(swimlaneControl) if (LOG_ACTIVE) then _logger:logTrace("TGT_CompactSwimlaneList.CreateCompactSwimlaneListRows") end if (swimlaneControl ~= nil) then for i=1, ROWS, 1 do local row = CreateControlFromVirtual("$(parent)Row", swimlaneControl, "CompactGroupUltimateSwimlaneRow", i) if (LOG_ACTIVE) then _logger:logDebug("Row created " .. row:GetName()) end row:SetHidden(true) -- initial not visible if (i == 1) then row:SetAnchor(TOPLEFT, swimlaneControl, BOTTOMLEFT, 0, 1) else row:SetAnchor(TOPLEFT, lastRow, BOTTOMLEFT, 0, 1) end lastRow = row end else _logger:logError("TGT_CompactSwimlaneList.CreateCompactSwimlaneListRows, swimlaneControl nil.") end end --[[ Initialize initializes TGT_CompactSwimlaneList ]]-- function TGT_CompactSwimlaneList.Initialize(logger) if (LOG_ACTIVE) then logger:logTrace("TGT_CompactSwimlaneList.Initialize") end _logger = logger _control = TGT_CompactSwimlaneListControl TGT_CompactSwimlaneList.CreateCompactSwimlaneListHeaders() TGT_CompactSwimlaneList.SetControlActive() CALLBACK_MANAGER:RegisterCallback(TGT_STYLE_CHANGED, TGT_CompactSwimlaneList.SetControlActive) CALLBACK_MANAGER:RegisterCallback(TGT_IS_ZONE_CHANGED, TGT_CompactSwimlaneList.SetControlActive) CALLBACK_MANAGER:RegisterCallback(TAO_UNIT_GROUPED_CHANGED, TGT_CompactSwimlaneList.SetControlActive) end