Mercurial > wow > crossrealmassist
view CrossRealmAssist.lua @ 11:421508c17712
Started implementing new interface
| author | ShadowTheAge |
|---|---|
| date | Tue, 10 Mar 2015 00:16:23 +0300 |
| parents | 9fa8442dd547 |
| children | 0deef890ec99 |
line wrap: on
line source
CrossRealmAssist = LibStub("AceAddon-3.0"):NewAddon("CrossRealmAssist", "AceEvent-3.0", "AceConsole-3.0", "AceTimer-3.0") local AceGUI = LibStub("AceGUI-3.0") local addon = CrossRealmAssist; local wholib = LibStub:GetLibrary('LibWho-2.0'):Library() local homeRealm, realmSep, gui, btRefresh, btQuick, btManual, lbRealm, lbStatus, playerName local curRealmStat local scanstate=0 local recentRealms={} local active=false local lfgGroups={ 6, -- Custom 10, -- Ashran 1, -- Quests 3, -- Raids 8 -- BGs } local lfgTabs local curLfgGroup local sheduledScan local wasInGroup local wasInInstance local lfgScanInProgress=false local function setupWidget(widget, parameters, x, y) if parameters then for key,value in pairs(parameters) do widget[key](widget,value) end end if y then widget:SetPoint("TOPLEFT",widget:GetParent(),"TOPLEFT",x,-y) end return widget end local function ShowTooltip(widget) GameTooltip:SetOwner(widget, widget.TooltipAnchor) GameTooltip:ClearLines() widget:TooltipFactory() GameTooltip:Show() end local function HideTooltip(widget) GameTooltip:Hide() end local function setupTooltip(widget, anchor, factory) widget.TooltipAnchor = anchor; widget.TooltipFactory = factory; widget:SetScript("OnEnter", ShowTooltip) widget:SetScript("OnLeave", HideTooltip) end function addon:OnInitialize() end function addon:OnEnable() local tabCount = table.getn(lfgGroups) lfgTabs = {} for i=1,tabCount do local cat = lfgGroups[i] table.insert(lfgTabs,{value=cat,text=(C_LFGList.GetCategoryInfo(cat))}) end realmSep = _G.REALM_SEPARATORS playerName = UnitName("player") homeRealm = GetRealmName() addon:RegisterChatCommand("cra", "Activate") addon:RegisterChatCommand("crossrealmassist", "Activate") addon:ScheduleTimer("Activate", 0.5) end function addon:OnDisable() addon:Deactivate() end function addon:Activate() if active then return end active=true wasInGroup = IsInGroup() if not gui then addon:CreateUI() end addon:updateCurrentRealm(); addon:ForceRefreshZone(); gui:Show() addon:RegisterEvent("ZONE_CHANGED_NEW_AREA", "ForceRefreshZone") addon:RegisterEvent("SCENARIO_UPDATE", "ForceRefreshZone") --addon:RegisterEvent("LFG_LIST_SEARCH_RESULTS_RECEIVED", "LfgResponseData") --addon:RegisterEvent("LFG_LIST_SEARCH_FAILED", "LfgScanFailed") --addon:RegisterEvent("GROUP_ROSTER_UPDATE", "updatePartyInfo") --addon:RegisterEvent("LFG_LIST_APPLICATION_STATUS_UPDATED", "updateAppStatus") end function addon:Deactivate() if not active then return end active = false scanstate = 0 lfgScanInProgress = false addon:UnregisterEvent("ZONE_CHANGED_NEW_AREA") addon:UnregisterEvent("PLAYER_REGEN_ENABLED") addon:UnregisterEvent("LFG_LIST_SEARCH_RESULTS_RECEIVED") addon:UnregisterEvent("LFG_LIST_SEARCH_FAILED") addon:UnregisterEvent("GROUP_ROSTER_UPDATE") addon:UnregisterEvent("LFG_LIST_APPLICATION_STATUS_UPDATED") end function addon:SetStatus(status) if status then lbStatus:SetText(status) else lbStatus:SetText("") -- TODO end end function addon:CreateUI() gui = setupWidget(CreateFrame("Frame",nil,nil,"InsetFrameTemplate3"), {SetFrameStrata="DIALOG",SetWidth=208,SetHeight=60,EnableMouse=true,SetMovable=true}) local title = setupWidget(CreateFrame("Frame",nil,gui), {SetWidth=190,SetHeight=18,EnableMouse=true,RegisterForDrag="LeftButton"}, 0, 6); title:SetScript("OnDragStart", function() gui:StartMoving() end) title:SetScript("OnDragStop", function() gui:StopMovingOrSizing() end) gui:SetScript("OnHide", addon.Deactivate) setupTooltip(title, "ANCHOR_TOP", addon.realmToolip) lbRealm = setupWidget(gui:CreateFontString(nil,"BACKGROUND", "GameFontNormal"), {SetWidth=200,SetHeight=18}, 0, 6) lbStatus = setupWidget(gui:CreateFontString(nil,"BACKGROUND", "GameFontHighlightSmallLeft"), {SetWidth=200,SetHeight=10}, 6, 23) btQuick = setupWidget(CreateFrame("Button",nil,gui,"UIMenuButtonStretchTemplate"),{EnableMouse=true,SetWidth=90,SetHeight=20,SetText="Quick join"},4,36) btManual = setupWidget(CreateFrame("Button",nil,gui,"UIMenuButtonStretchTemplate"),{EnableMouse=true,SetWidth=90,SetHeight=20,SetText="Manual join"},94,36) setupWidget(CreateFrame("Button",nil,gui,"UIPanelCloseButton"),{EnableMouse=true,SetWidth=20,SetHeight=20},188,0) btRefresh = setupWidget(CreateFrame("Button",nil,gui,"UIPanelSquareButton"),{EnableMouse=true,SetWidth=20,SetHeight=20},184,36) btRefresh.icon:SetTexture("Interface/BUTTONS/UI-RefreshButton") btRefresh.icon:SetTexCoord(0,1,0,1); btRefresh:SetScript("OnClick",addon.RefreshZone) gui:SetPoint("CENTER",0,0) --[[gui = addon:AddUI(nil,"Window",{SetTitle="Cross Realm Assist",EnableResize=false,SetLayout="Flow"},true,{OnClose=addon.Deactivate}) local tabgroup = addon:AddUI(gui,"TabGroup",{SetFullHeight=true,SetTabs=lfgTabs,SetLayout="Fill"},true,{OnGroupSelected=addon.LfgScan}) tabgroup:SelectTab(lfgGroups[1]) lfgContainer = addon:AddUI(tabgroup,"ScrollFrame") local hgroupc = addon:AddUI(gui,"InlineGroup",{SetLayout="Fill",SetFullHeight=true,SetTitle="Realm info"},true) hgroup = addon:AddUI(hgroupc,"ScrollFrame") addon:AddUI(hgroup,"Heading",{SetText="Current realm"}) currealm = addon:AddUI(hgroup,"SimpleGroup"); addon:AddUI(hgroup,"Button",{SetText="Refresh",SetRelativeWidth=0.5,SetHeight=20},true,{OnClick=addon.ScanRealm}) addon:AddUI(hgroup,"Heading",{SetText="Party statistics"}) partyrealm = addon:AddUI(hgroup,"SimpleGroup"); leavebtn = addon:AddUI(hgroup,"Button",{SetText="Leave",SetRelativeWidth=0.5,SetHeight=20,SetDisabled=not IsInGroup()},true,{OnClick=LeaveParty}) addon:AddUI(hgroup,"Heading",{SetText="Recent realms"}) recrealm = addon:AddUI(hgroup,"SimpleGroup"); addon:AddUI(hgroup,"Button",{SetText="Clear",SetRelativeWidth=0.5,SetHeight=20},true,{OnClick=addon.ClearRecentRealms}) gui:DoLayout() gui:PauseLayout() tabgroup:SetPoint("BOTTOMRIGHT", gui.content, "BOTTOMRIGHT", -200, 0) hgroupc:SetPoint("TOPLEFT", gui.content, "TOPRIGHT", -200, 0) hgroupc:SetPoint("BOTTOMRIGHT", gui.content, "BOTTOMRIGHT") if curRealmStat then addon:updateCurrentRealm() end addon:updatePartyInfo() addon:updateRecentRealms()]] end -- LFG scanning routine --[[function addon.refreshLfgCurrent() addon.LfgScan(nil,nil,curLfgGroup) end function addon.LfgScan(widget, callback, tab) if not tab then return end lfgScanInProgress = true if lfgContainer then lfgContainer:ReleaseChildren() end curLfgGroup = tab C_LFGList.Search(curLfgGroup,"") end function addon:LfgScanFailed(event, reason) print("scan failed "..reason) if reason == "throttled" then addon:ScheduleTimer(addon.LfgScan, 2, nil, nil, curLfgGroup) end end local function WeightLfgItem(item) local leaderRealm = 3 if (item.realm ~= "???") then leaderRealm = (5 - (recentRealms[item.realm] or 0)) end local weight = (item.autoinv and 5 or 2) * ((item.friends > 0) and 2 or 3) * ((item.ilvl > 0) and 2 or 3) * ((item.voice ~= "") and 2 or 4) local count = item.pcount; local countWeight if count >= 39 or count <= 1 then countWeight = 1 elseif count >= 35 or count <= 4 then countWeight = 2 elseif count >= 30 or count <= 10 then countWeight = 3 else countWeight = 4 end return weight * leaderRealm * countWeight; end function addon:LfgResponseData() lfgScanInProgress = false; addon:UpdateCurrentLfgInfo() end function addon:UpdateCurrentLfgInfo(repeated) if lfgScanInProgress then return end local count, list = C_LFGList.GetSearchResults() local lfgList = {} local lfgEntries = 0 local hasUnknowns = false for i = 1,count do local rid = list[i]; if not rid then break end local _, action, caption, desc, voice, ilvl, time, bnetfr, charfr, guild, delisted, fullname, pcount, autoinv = C_LFGList.GetSearchResultInfo(rid) if not fullname then fullname = "???-???" hasUnknowns = true end if not delisted then local pname, realm = strsplit(realmSep, fullname) realm = realm or homeRealm local item = { rid=rid, action=action, caption=caption, desc=desc, ilvl=ilvl, voice=voice, time=time, friends=bnetfr+charfr+guild, name=pname, realm = realm, pcount=pcount, autoinv=autoinv } item.weight = WeightLfgItem(item) table.insert(lfgList, item) lfgEntries = lfgEntries + 1 end end addon:refreshLFGList(lfgList, lfgEntries); if hasUnknowns and repeated ~= true then addon:ScheduleTimer("UpdateCurrentLfgInfo", 1, true) end end function addon:refreshLFGList(list, count) if not lfgContainer then return end lfgContainer:PauseLayout() lfgContainer:ReleaseChildren() table.sort(list, addon.SortLfgItems) local canJoin = addon.canJoinGroup() for i=1,count do local data = list[i]; local renderer = addon:AddUI(lfgContainer,"SimpleGroup",{SetLayout="Flow",SetHeight=20,SetAutoAdjustHeight=false}); addon:AddUI(renderer,"Label",{SetText=data.caption,SetRelativeWidth=0.4},true) addon:AddUI(renderer,"Label",{SetText=data.pcount,SetRelativeWidth=0.05},true) local realm = addon:AddUI(renderer,"Label",{SetText=data.realm,SetRelativeWidth=0.25},true) if recentRealms[data.realm] then local r,g,b = GetItemQualityColor(recentRealms[data.realm]); realm:SetColor(r,g,b) end local tooltip = {} if data.voice ~= "" then table.insert(tooltip,"Voice: "..data.voice) end if data.friends > 0 then table.insert(tooltip,"Friends: "..data.friends) end if data.ilvl > 0 then table.insert(tooltip,"Min. Ilvl: "..data.ilvl) end addon:AddIcon(renderer, "Interface/GossipFrame/ActiveQuestIcon", 16, tooltip[1] ~= nil, tooltip) addon:AddIcon(renderer, READY_CHECK_READY_TEXTURE, 16, data.autoinv, {"Auto invite!"}) local btn = addon:AddUI(renderer,"Button",{SetText="Join",SetRelativeWidth=0.2,SetHeight=20,SetDisabled=not canJoin},true,{OnClick=addon.joinGroup}) btn:SetUserData('rid',data.rid) end addon:AddUI(lfgContainer,"Button",{SetText="Refresh",SetWidth=100,SetHeight=20},true,{OnClick=addon.refreshLfgCurrent}) lfgContainer:ResumeLayout() lfgContainer:DoLayout() end function addon.SortLfgItems(a,b) return a.weight > b.weight end function addon.canJoinGroup() return (not IsInGroup()) or (UnitIsGroupLeader('player') and not IsInRaid()) end function addon.joinGroup(widget) if not addon.canJoinGroup() then return end local rid = widget:GetUserData('rid'); widget:SetDisabled(true) C_LFGList.ApplyToGroup(rid, "", C_LFGList.GetAvailableRoles()) end function addon:updateAppStatus(event, id, status, oldstatus) if status == "invited" then LFGListInviteDialog_Accept(LFGListInviteDialog) end end]] -- Zone scanning routine function addon:LeaveCombat() addon:UnregisterEvent("PLAYER_REGEN_ENABLED") scanstate = 0 addon:ScanRealm(); end function addon:ForceRefreshZone() addon:RefreshZone(true) end function addon:RefreshZone(shedule) local inst, instType = IsInInstance() if (inst or instType ~= "none") then lbRealm:SetText("Instanced zone") curRealmStat = nil btQuick:Disable() else btQuick:Enable() if scanstate == 0 then addon:ScanRealm() elseif shedule == true and scanstate == 2 then addon:SetStatus("Rescan sheduled...") scanstate = 3 end end end function addon:ScanRealm() if scanstate > 0 then return end if InCombatLockdown() then addon:RegisterEvent("PLAYER_REGEN_ENABLED","LeaveCombat") scanstate = 1 addon:SetStatus("Scan sheduled after combat..."); return end scanstate = 2 addon:SetStatus("Scanning current realm..."); local searchString = _G.WHO_TAG_ZONE .. '"' .. GetZoneText() .. '"'; wholib:Who(searchString, {callback = "ScanResult", handler=addon}) end function addon:ScanResult(query, results, complete) local realms = {} for _, player in ipairs(results) do addon:AddRealmStat(player.Name, realms); end curRealmStat = addon:GetRealmStat(realms); curRealmStat.complete = complete addon:updateCurrentRealm(); local rescan = scanstate == 3 scanstate = 0; if rescan then addon:ScanRealm() end end function addon:AddRealmStat(name, realms) if (name == playerName) then return end local _, realm = strsplit(realmSep, name) realm = realm or homeRealm realms[realm] = (realms[realm] or 0) + 1 end function addon:AddUnitIdStat(unitid, realms) local name, realm = UnitName(unitid); if not name then return end if realm == "" then realm = homeRealm end realm = realm or homeRealm realms[realm] = (realms[realm] or 0) + 1 end function addon:GetRealmStat(realms) local rcount = 0; local stat = {}; local pcount = 0; for realm,count in pairs(realms) do table.insert(stat,{realm=realm,count=count}) rcount = rcount + 1; pcount = pcount + count; end if rcount > 1 then table.sort(stat, function(a,b) return a.count > b.count end) stat.max = stat[1].count else stat.max = 0 end stat.players = pcount; stat.realms = rcount; return stat; end function addon:updateCurrentRealm() addon:SetStatus(); if not curRealmStat or curRealmStat.realms < 1 then lbRealm:SetText("Unknown realm (No players)") return; end local bestRealm = curRealmStat[1] local prevThreshold = math.min(bestRealm.count/3,5) local mixCount = 0 for i=2,curRealmStat.realms do local data = curRealmStat[i] if data.count >= prevThreshold then mixCount = mixCount + 1 prevThreshold = math.min(data.count/3,5) end end curRealmStat.threshold = prevThreshold if (mixCount > 0) then lbRealm:SetText("Mixed "..bestRealm.realm.." +"..mixCount) else lbRealm:SetText(bestRealm.realm) end end function addon:realmToolip() if not curRealmStat then return end local players = curRealmStat.players; local threshold = curRealmStat.threshold GameTooltip:AddLine("Players in zone: "..players) if not curRealmStat.complete then GameTooltip:AppendText("+") end for i=1,curRealmStat.realms do local data = curRealmStat[i] local percent = math.ceil(100 * data.count / players - 0.5) .. "%"; if data.count >= threshold then GameTooltip:AddDoubleLine(data.realm, percent, 0,1,0,0,1,0) else GameTooltip:AddDoubleLine(data.realm, percent, 0.5,0.5,0.5,0.5,0.5,0.5) end end end --[[function addon:addLabels(container, stats, epict, whitet, grayt, emptytext) if stats.realms == 0 then addon:AddLabel(container, emptytext) else local players = stats.players local pleft = players; for i=1,stats.realms do local data = stats[i] local count = data.count; local percent = math.ceil(100 * count / players - 0.5) local label = data.realm .. " (" .. percent .. "%)"; local color if count < grayt then break elseif count < whitet then color = 1 elseif count < epict then color = 2 else color = 4 end pleft = pleft - count addon:AddLabel(container, label, color); end if pleft > 0 then addon:AddLabel(container, "Other" .. " (" .. math.ceil(100 * pleft / players - 0.5) .. "%)", 0); end end end function addon:updateRecentRealms() if not recrealm then return end recrealm:ReleaseChildren() local nothing = true; for realm,color in pairs(recentRealms) do addon:AddLabel(recrealm, realm,color); nothing = false; end if nothing then addon:AddLabel(recrealm, "No recent realms"); end end function addon:ClearRecentRealms() recentRealms = {} addon:UpdateCurrentLfgInfo() addon:updateRecentRealms() end function addon:updatePartyInfo() if not partyrealm then return end partyrealm:ReleaseChildren() local realms = {} local inGroup = IsInGroup() if IsInGroup() then if IsInRaid() then for i=1, MAX_RAID_MEMBERS do addon:AddUnitIdStat("raid"..i, realms) end else for i=1, MAX_PARTY_MEMBERS do addon:AddUnitIdStat("party"..i, realms) end end end if inGroup ~= wasInGroup then addon:SheduleScan() wasInGroup = inGroup addon:UpdateCurrentLfgInfo() leavebtn:SetDisabled(not inGroup) end local partyStat = addon:GetRealmStat(realms); addon:addLabels(partyrealm, partyStat, partyStat.players/2, 2, 0, "Not in party"); end]]
