-- ShowTablet line 3: possible source of bugs (glitch) when trying to solve: block/self -> incorrect setpoint |
|
local BUTTON_HEIGHT, ICON_SIZE, GAP, TEXT_OFFSET, TIMEOUT = |
15, 13, 10, 5, .05 |
|
local f = CreateFrame( "Frame", "AraBrokerGuildFriends" ) |
local extraFrame = CreateFrame"Frame" |
local dropdown, dropdown_init = CreateFrame( "Frame", "AraBrokerGuildFriendsDDFrame", nil, "UIDropDownMenuTemplate" ) |
|
local block, isGuild, leaving |
|
local L = setmetatable( {}, { __index = function(t,k) return k end } ) -- GetLocale() |
|
local format, strfind, GetGuildRosterInfo, GetFriendInfo, RAID_CLASS_COLORS, CLASS_BUTTONS = |
format, strfind, GetGuildRosterInfo, GetFriendInfo, RAID_CLASS_COLORS, CLASS_BUTTONS |
|
---------------------------------[[ ]]-------------------------------- |
|
local tables = {} |
|
local new = function( ... ) |
local table = tremove(tables) or {} |
for i=1, select("#",...) do table[i] = select(i,...) end |
return table |
end |
|
local del = function( table ) |
tables[ #tables + 1 ] = wipe(table) |
end |
|
|
local mejoin = format( ERR_GUILD_JOIN_S, UnitName"player" ) |
local friendOnline, friendOffline = gsub(ERR_FRIEND_ONLINE_SS,"\124Hplayer:%%s\124h%[%%s%]\124h",""), gsub(ERR_FRIEND_OFFLINE_S,"%%s","") |
function f:CHAT_MSG_SYSTEM( event, msg ) |
if msg == mejoin then self.updateGuild = true return end |
if strfind( msg, friendOnline ) or strfind( msg, friendOffline ) then self.updateFriends, self.updateGuild = true, true end |
end |
|
local friendEntries = {} |
|
function f:FRIENDLIST_UPDATE() |
for k,v in next,friendEntries do del(v) friendEntries[k]=nil end |
local total, online = GetNumFriends(), 0 |
for i = 1, total do |
local name, level, class, zone, connected, status, note = GetFriendInfo(i) |
if( connected )then |
if( online == 0 )then |
friendEntries[1] = new( nil, "Name", "", "Lv", "Zone", "Notes" ) |
end |
online = online + 1 |
friendEntries[online+1] = new( name, status and format("%s %s", tostring(status), tostring(name)) or name, class:gsub(" ",""):upper(), level, zone or "Unknown", note and format("[%s]",note) or "-" ) |
end |
end |
f.FriendsBlock.text = total > 0 and format("%d/%d", online, total) or L["No friends."] |
if( not isGuild and block )then f:FriendsOnEnter(block) end |
end |
|
function f:GUILD_ROSTER_UPDATE() |
local numOnline = 0 |
for i=1, GetNumGuildMembers() do |
if( select( 9, GetGuildRosterInfo(i) ) )then numOnline = numOnline + 1 end |
end |
f.GuildBlock.text = IsInGuild() and format( "%s - %d/%d", GetGuildInfo"player", numOnline, GetNumGuildMembers(true) ) or L["No Guild"] |
if( isGuild and block )then f:GuildOnEnter(block) end |
end |
|
function f:PLAYER_GUILD_UPDATE(event, unit) |
if( unit and unit ~= "player" )then return end |
return IsInGuild() and GuildRoster() |
end |
|
local horde |
local hordeZones = "Orgrimmar,Undercity,Thunder Bluff,Silvermoon City,Tirisfal Glades,Durotar,The Barrens,Silverpine Forest,Mulgore,The Sepulcher,Eversong Woods,Ghostlands," |
local allianceZones = "Ironforge,Stormwind City,Darnassus,Azuremyst Isle,Bloodmyst Isle,Darkshore,Dun Morogh,Loch Modan,Wetlands,Elwynn Forest,Redridge Mountains,Westfall,Teldrassil,Duskwood,Darshire,Thelsamar,Deeprun Tram,The Exodar,Auberdine,Menethil Harbor,Theramore Isle" |
local function GetZoneColor(zone) |
if( strfind( hordeZones , zone.."," ) )then if( horde )then return 0,1,0 else return 1,0,0 end end |
if( strfind( allianceZones, zone.."," ) )then if( horde )then return 1,0,0 else return 0,1,0 end end |
return 1,1,0 |
end |
|
local function Menu_OnUpdate( frame, elapsed ) |
extraFrame.timer = extraFrame.timer + elapsed |
if( extraFrame.timer <= TIMEOUT )then return end |
extraFrame:SetScript( "OnUpdate", nil ) |
f:Hide() |
block = nil |
end |
|
local highlight = f:CreateTexture(nil,"ARTWORK") |
highlight:SetTexture"Interface\\QuestFrame\\UI-QuestTitleHighlight" |
highlight:SetBlendMode"ADD" |
highlight:SetAlpha(0) |
|
local function Menu_OnEnter(b) |
leaving = false |
extraFrame:SetScript( "OnUpdate", nil ) |
if(b.index)then |
highlight:SetAllPoints(b) |
if( b.index > 1)then highlight:SetAlpha(1) end |
end |
end |
|
local function Menu_OnLeave(b) |
leaving = true |
extraFrame.timer = 0 |
extraFrame:SetScript( "OnUpdate", Menu_OnUpdate ) |
highlight:ClearAllPoints() |
if(b.index and b.index > 1)then highlight:SetAlpha(0) end |
end |
|
local font, _, flags = GameFontNormal:GetFont() |
local function CreateFS( index, parent, justify, anchor ) |
local fs = parent:CreateFontString( nil, "OVERLAY" ) |
fs:SetFont( font, 12, flags ) |
fs:SetJustifyH( justify ) |
fs:SetTextColor( 1, index == 1 and .8 or 1, 0 ) |
fs:SetShadowColor( 0, 0, 0 ) -- ADDED |
fs:SetShadowOffset( 1, -1 ) -- ADDED |
if( anchor )then fs:SetPoint( "LEFT", anchor, "RIGHT", GAP, 0 ) end |
return fs |
end |
|
local buttons = setmetatable( { }, { __index = function( table, key ) |
local button = CreateFrame( "Button", nil, f ) |
rawset( table, key, button ) |
button.index = key |
button:RegisterForClicks"AnyUp" |
button:SetHeight( BUTTON_HEIGHT ) |
button:SetScript( "OnEnter", Menu_OnEnter ) |
button:SetScript( "OnLeave", Menu_OnLeave ) |
|
button.fontName = CreateFS( key, button, "LEFT" ) |
if( key == 0 )then |
button.fontName:SetJustifyV"TOP" |
else |
if( key > 1 )then |
button.icon = button:CreateTexture( nil, "OVERLAY" ) |
button.icon:SetWidth( ICON_SIZE ) button.icon:SetHeight( ICON_SIZE ) |
button.icon:SetPoint( "LEFT", button, "LEFT" ) |
end |
|
button.fontName:SetPoint( "LEFT", button, "LEFT", ICON_SIZE + TEXT_OFFSET, 0 ) |
button.fontLevel = CreateFS( key, button, "CENTER", button.fontName ) |
button.fontZone = CreateFS( key, button, "CENTER", button.fontLevel ) |
button.fontNotes = CreateFS( key, button, "CENTER", button.fontZone ) |
button.fontRank = CreateFS( key, button, "RIGHT", button.fontNotes ) |
end |
return button |
end } ) |
|
|
local function SetButtonData( index, name, class, level, zone, notes, rank ) |
local button = buttons[index] |
button.fontName:SetText( name or "" ) |
button:Show() |
if( class )then |
if( index > 1 )then |
button.icon:SetTexture"Interface\\Glues\\CharacterCreate\\UI-CharacterCreate-Classes" |
local offset, left, right, bottom, top = 0.025, unpack( CLASS_BUTTONS[class] ) |
button.icon:SetTexCoord( left+offset, right-offset, bottom+offset, top-offset ) |
-- button.icon:SetTexCoord( unpack( CLASS_BUTTONS[class] ) ) |
local color = RAID_CLASS_COLORS[class] |
button.fontName:SetTextColor( color.r, color.g, color.b ) |
color = GetDifficultyColor(level) |
button.fontLevel:SetTextColor( color.r, color.g, color.b ) |
button.fontZone:SetTextColor( GetZoneColor(zone or "#") ) |
end |
button.fontLevel:SetText( level or "" ) |
button.fontZone:SetText( zone or "" ) |
button.fontNotes:SetText( notes or "" ) |
button.fontRank:SetText( rank or "" ) |
return button, button.fontName:GetStringWidth(), button.fontLevel:GetStringWidth(), button.fontZone:GetStringWidth(), button.fontNotes:GetStringWidth(), button.fontRank:GetStringWidth() |
end |
return button, button.fontName:GetStringWidth() |
end |
|
|
------------------------------[[ data feed ]]---------------------------- |
local function EditMOTD() |
f:Hide() |
GuildMOTDEditButton:Click() |
end |
|
local colspace = { ICON_SIZE } |
local cols = { "class", "name", "level", "zone", "note", "rank" } |
|
local function OnGuildmateClick( self, button ) |
if( not( self and self.unit ) )then return end |
if( isGuild and button ~= "LeftButton" )then -- sort columns |
local prevDist = GetCursorPosition() / self:GetEffectiveScale() - self:GetLeft() |
local colpos, dist = colspace[1] - prevDist |
for i=2, #colspace do |
colpos = colpos + colspace[i] + (i==2 and TEXT_OFFSET or GAP) |
dist = abs( colpos - colspace[i]*.5 ) |
if( dist > prevDist )then dist, prevDist = i-1, -1 break else prevDist = dist end |
end |
SortGuildRoster( cols[ prevDist < 0 and dist or #colspace ] ) |
elseif( IsAltKeyDown() )then |
InviteUnit( self.unit ) |
elseif( not isGuild and IsControlKeyDown() )then |
FriendsFrame.NotesID = self.index - 1 |
StaticPopup_Show( "SET_FRIENDNOTE", self.unit ) |
else |
SetItemRef("player:"..self.unit, format( "|Hplayer:%s|h[%s]|h", self.unit, self.unit ), "LeftButton") |
end |
end |
|
local function ShowTablet( self, _isGuild, entries, onClickFunc ) |
isGuild = _isGuild |
block = not leaving and block or self -- possible source of bugs when fast switching |
if( InCombatLockdown() )then return end |
if( isGuild and not IsInGuild() or #entries == 0 )then |
GameTooltip:SetOwner(self) |
GameTooltip:AddLine( isGuild and ERR_GUILD_PLAYER_NOT_IN_GUILD or L["No friends online."] ) |
return GameTooltip:Show() |
end |
Menu_OnEnter(self) |
local offsetEntries, button = isGuild and 1 or 0 |
local nameC, levelC, zoneC, notesC, rankC = 0, 0, 0, 0, 0 |
local nameW, levelW, zoneW, notesW, rankW |
|
local extraHeight, motd = 0 |
if( isGuild )then |
motd, extraHeight = SetButtonData( 0, "|cffffffffMOTD:|r " .. GetGuildRosterMOTD() ) |
if( CanEditMOTD() )then motd:SetScript( "OnClick", EditMOTD ) end |
motd.fontName:ClearAllPoints() |
end |
|
for i, entry in ipairs(entries) do |
button, nameW, levelW, zoneW, notesW, rankW = SetButtonData( i, entry[2], entry[3], entry[4], entry[5], entry[6], entry[7] ) |
button:SetScript( "OnClick", onClickFunc ) |
button.unit = entry[1] |
if( nameW > nameC )then nameC = nameW end |
if( levelW > levelC )then levelC = levelW end |
if( zoneW > zoneC )then zoneC = zoneW end |
if( notesW > notesC )then notesC = notesW end |
if( rankW > rankC )then rankC = rankW end |
end |
|
local maxWidth = ICON_SIZE + TEXT_OFFSET + nameC + levelC + zoneC + notesC + rankC + GAP * (isGuild and 4 or 3) |
extraHeight = ceil( extraHeight / maxWidth ) |
|
if( isGuild )then |
motd:SetWidth( maxWidth ) |
motd:SetPoint( "TOPLEFT", f, "TOPLEFT", GAP, -GAP ) |
motd:SetHeight( (extraHeight+1) * BUTTON_HEIGHT ) |
motd.fontName:SetAllPoints(motd) |
buttons[1]:SetPoint( "TOPLEFT", motd, "BOTTOMLEFT" ) |
elseif( rawget( buttons, 0 ) )then |
buttons[0]:Hide() |
end |
|
for i=1, #entries do |
button = buttons[i] |
button.fontName:SetWidth(nameC) |
button.fontLevel:SetWidth(levelC) |
button.fontZone:SetWidth(zoneC) |
button.fontNotes:SetWidth(notesC) |
button.fontRank:SetWidth(rankC) |
button:SetWidth( maxWidth ) |
if( not isGuild or i>1 )then button:SetPoint( "TOPLEFT", f, "TOPLEFT", GAP, (1-i-extraHeight-offsetEntries) * BUTTON_HEIGHT - GAP ) end |
end |
colspace[2], colspace[3], colspace[4], colspace[5], colspace[6] = nameC, levelC, zoneC, notesC, rankC |
|
f:SetWidth( maxWidth + GAP*2 ) |
f:SetHeight( BUTTON_HEIGHT * (#entries+offsetEntries+extraHeight) + GAP*2 ) |
|
local showBelow = select( 2, block:GetCenter() ) > ( UIParent:GetHeight() / 2 ) |
f:ClearAllPoints() |
f:SetPoint( showBelow and "TOP" or "BOTTOM", block, showBelow and "BOTTOM" or "TOP" ) |
f:Show() |
for i=#entries+1, #buttons do buttons[i]:Hide() end |
end |
|
|
function f:FriendsOnEnter() |
if( InCombatLockdown() )then return end |
return ShowTablet( self, false, friendEntries, OnGuildmateClick ) |
end |
|
local guildEntries = {} |
|
function f:GuildOnEnter() |
if( InCombatLockdown() )then return end |
for k, v in next, guildEntries do del(v) guildEntries[k]=nil end |
for i=1, GetNumGuildMembers(true) do |
local name, rank, _, level, _, zone, note, offnote, connected, status, class = GetGuildRosterInfo(i) |
if( connected )then |
if( #guildEntries == 0 )then -- first entry, so add header |
guildEntries[1] = new( nil, "Name", "", "Lv", "Zone", "Notes", "Rank" ) |
end |
local notes = note ~= "" and (offnote ~= "" and |
format( "[%s] - [%s]", note, offnote ) or |
format( "[%s]", note )) or (offnote ~= "" and |
format( "[%s]", offnote ) or "-") |
guildEntries[#guildEntries+1] = new( name, status == "" and name or format( "%s %s", status, name ), class, level, zone, notes, rank ) |
end |
end |
ShowTablet( self, true, guildEntries, OnGuildmateClick ) |
end |
|
|
local ldb = LibStub("LibDataBroker-1.1") |
|
f.GuildBlock = ldb:NewDataObject( "|cFFFFB366Ara|r Guild", { |
text = GUILD, |
icon = "Interface\\AddOns\\Ara_Broker_Guild&Friends\\guild.tga", |
OnEnter = f.GuildOnEnter, |
OnLeave = function(self) return IsInGuild() and Menu_OnLeave(self) or GameTooltip:Hide() end, |
OnClick = function(self) ToggleFriendsFrame(3) end, |
} ) |
|
f.FriendsBlock = ldb:NewDataObject( "|cFFFFB366Ara|r Friends", { |
text = FRIENDS, |
icon = "Interface\\AddOns\\Ara_Broker_Guild&Friends\\friends.tga", |
OnEnter = f.FriendsOnEnter, |
OnLeave = function(self) Menu_OnLeave(self) GameTooltip:Hide() end, |
OnClick = function(self) ToggleFriendsFrame(1) end, |
} ) |
|
local orgShowFriends = ShowFriends |
ShowFriends = function(...) |
f.friendsTimer, f.updateFriends = 0, false |
return orgShowFriends(...) |
end |
|
local orgGuildRoster = GuildRoster |
GuildRoster = function(...) |
f.guildTimer, f.updateGuild = 0, false |
return orgGuildRoster(...) |
end |
|
local function OnUpdate( self, elapsed ) |
self.guildTimer, self.friendsTimer = self.guildTimer + elapsed, self.friendsTimer + elapsed |
if( self.updateGuild and self.guildTimer > 15 or self.guildTimer > 300 )then |
self.guildTimer, self.updateGuild = 0, false |
if IsInGuild() then GuildRoster() end |
end |
if( self.updateFriends and self.friendsTimer > 15 or self.friendsTimer > 300 )then |
ShowFriends() |
end |
end |
|
-------------------------------[[ events ]]------------------------------ |
|
f.PLAYER_LOGIN = function( self, event ) |
horde = UnitFactionGroup"player" == "Horde" |
SortGuildRoster"class" -- "name", "rank", "note", "online", "zone", "level", "class" |
|
self:SetBackdrop( { bgFile="Interface\\Buttons\\WHITE8X8", edgeFile="Interface\\Tooltips\\UI-Tooltip-Border", |
tile=true, tileSize=12, edgeSize=12, insets = { left=2, right=2, top=2, bottom=2 } } ) |
self:SetBackdropColor( 0, 0, 0, .75 ) |
self:SetScale( UIParent:GetScale() ) |
self:SetFrameStrata"DIALOG" |
self:SetClampedToScreen(true) |
self:EnableMouse( true ) |
self:Show() -- possible fix for menu width bug (or TODO: put in PLAYER_ENTERING_WORLD) |
|
self.guildTimer, self.friendsTimer = 0, 0 |
self:SetScript( "OnUpdate", OnUpdate ) |
self:SetScript( "OnEnter", Menu_OnEnter ) |
self:SetScript( "OnLeave", Menu_OnLeave ) |
|
self:RegisterEvent"GUILD_ROSTER_UPDATE" |
self:RegisterEvent"PLAYER_GUILD_UPDATE" |
self:RegisterEvent"FRIENDLIST_UPDATE" |
self:RegisterEvent"CHAT_MSG_SYSTEM" |
|
if IsInGuild() then GuildRoster() end |
ShowFriends() |
|
self:UnregisterEvent"PLAYER_LOGIN" |
self.PLAYER_LOGIN = nil |
end |
|
f:SetScript( "OnEvent", function(self, event, ...) return self[event](self, event, ...) end ) |
return IsLoggedIn() and f:PLAYER_LOGIN() or f:RegisterEvent"PLAYER_LOGIN" |