ShadowTheAge@42: local version = "v0.81"; ShadowTheAge@32: local about = [[About: ShadowTheAge@32: I have started to make this addon as a tool for myself. Few people started to use it when I pushed it to Curse. Then updated it once with 6.2 release. ShadowTheAge@32: After some time I have catched a dialog on my own realm discussing it. I went to check curse page and I was shocked - it was in top-60 monthly downloaded addons with lots of suggestions and few bug reports. ShadowTheAge@32: I wasn't going to support it - because it was working - but now it looks like I have to spend at least some time to make it better. ShadowTheAge@32: ShadowTheAge@32: Realm hopping has become a thing. The idea was rather obvious, but less people were using it at the start of WOD. Now every raid group with autoaccept are going to have some quiet people joining and leaving it. But since we became a huge community, it is up to us to control this. ShadowTheAge@32: The idea is to create groups from realmhoppers to realmhoppers. Taking small steps to not flood LFG too much. There are some ideas how to make realmhopping more comfortably while reducing annoyance to others. ShadowTheAge@32: ShadowTheAge@32: FAQ: ShadowTheAge@32: Q: I cannot loot timeless coins / some other loot ShadowTheAge@32: A: Some items cannot be looted while in a raid group. However, rare timeless items can be.". ShadowTheAge@32: ShadowTheAge@32: Q: I'm on the oceanic region and I can't hop to another realm ShadowTheAge@32: A: Unfortunately, oceanic realms are separated by Blizzard. There is little I can do :( ShadowTheAge@32: ShadowTheAge@32: Changelog: ShadowTheAge@32: ShadowTheAge@40: v0.7 - 0.76 ShadowTheAge@32: - New options panel (Groundwork for future customization) ShadowTheAge@32: - Some UI customizations are now possible ShadowTheAge@32: - "Join to a friend" feature ShadowTheAge@32: - "Keywords" feature - blacklist, whitelist and highlight list ShadowTheAge@32: - You can add more info to "Manual Join" list ShadowTheAge@32: - Clicking to join group when you are already in a group causes you to leave it. ShadowTheAge@32: - You can now create a group for other people to use for realm hopping purpose ShadowTheAge@32: - You can now automatically create such group when AFK at garrison ShadowTheAge@32: - Added advanced filters ShadowTheAge@32: - Last column ("Misc") is now a sortable column - it uses base sort (by weight) ShadowTheAge@32: ShadowTheAge@40: v0.8 ShadowTheAge@40: - WoW Legion update ShadowTheAge@40: - Minor fixes ShadowTheAge@40: ShadowTheAge@32: http://www.curse.com/addons/wow/crossrealmassist ShadowTheAge@32: https://www.reddit.com/r/crossrealmassist ShadowTheAge@32: ]] ShadowTheAge@32: ShadowTheAge@32: local AceConfig = LibStub("AceConfig-3.0") ShadowTheAge@32: local addon = CrossRealmAssist; ShadowTheAge@32: ShadowTheAge@32: local db ShadowTheAge@32: local orderId = 0 ShadowTheAge@32: local registered = false; ShadowTheAge@32: local needReloadUI = false; ShadowTheAge@32: ShadowTheAge@32: local function haveToReloadUI() ShadowTheAge@32: return not needReloadUI; ShadowTheAge@32: end ShadowTheAge@32: ShadowTheAge@32: local function order() ShadowTheAge@32: orderId = orderId + 1 ShadowTheAge@32: return orderId; ShadowTheAge@32: end ShadowTheAge@32: ShadowTheAge@32: local function traverse(info, value) ShadowTheAge@32: local node = db.global ShadowTheAge@32: local last ShadowTheAge@32: if info.arg then ShadowTheAge@32: for k,v in ipairs(info.arg) do ShadowTheAge@32: if last then node = node[last] end ShadowTheAge@32: last = v; ShadowTheAge@32: end ShadowTheAge@32: if value ~= nil then ShadowTheAge@32: local callback = info.arg.callback ShadowTheAge@32: if callback then ShadowTheAge@32: if (type(callback) == "string") then ShadowTheAge@32: addon[callback](value); ShadowTheAge@32: elseif type(callback) == "function" then ShadowTheAge@32: callback(value) ShadowTheAge@32: end ShadowTheAge@32: end ShadowTheAge@32: if info.arg.needReloadUI then ShadowTheAge@32: needReloadUI = true ShadowTheAge@32: end ShadowTheAge@32: end ShadowTheAge@32: else last = info[#info] end ShadowTheAge@32: return node, last ShadowTheAge@32: end ShadowTheAge@32: ShadowTheAge@32: local function getter(info) ShadowTheAge@32: local node, last = traverse(info); ShadowTheAge@32: return node[last] ShadowTheAge@32: end ShadowTheAge@32: ShadowTheAge@32: local function setter(info, value) ShadowTheAge@32: local node, last = traverse(info, value); ShadowTheAge@32: node[last] = value; ShadowTheAge@32: end ShadowTheAge@32: ShadowTheAge@32: local function multiGetter(info, key) ShadowTheAge@32: local node, last = traverse(info); ShadowTheAge@32: return node[last][key]; ShadowTheAge@32: end ShadowTheAge@32: ShadowTheAge@32: local function multiSetter(info, key, value) ShadowTheAge@32: local node, last = traverse(info, value); ShadowTheAge@32: node[last][key] = value; ShadowTheAge@32: end ShadowTheAge@32: ShadowTheAge@32: local function setMinimapIcon(hidden) ShadowTheAge@32: if hidden then ShadowTheAge@32: DEFAULT_CHAT_FRAME:AddMessage("|cffff0000Type |cffffffff/cra |cffff0000in chat to open Cross Realm Assist without minimap button"); ShadowTheAge@32: minimapIcon:Hide("CrossRealmAssistMinimapIcon") ShadowTheAge@32: else ShadowTheAge@32: minimapIcon:Show("CrossRealmAssistMinimapIcon") ShadowTheAge@32: end ShadowTheAge@32: end ShadowTheAge@32: ShadowTheAge@32: local function createKeywordTable(name, desc, listValue) ShadowTheAge@32: local list = db.global[listValue]; ShadowTheAge@32: if not list then ShadowTheAge@32: list = {} ShadowTheAge@32: db.global[listValue] = list; ShadowTheAge@32: end ShadowTheAge@32: local selected = 0; ShadowTheAge@32: ShadowTheAge@32: local function setSelection(info, value) ShadowTheAge@32: selected = value ShadowTheAge@32: end ShadowTheAge@32: ShadowTheAge@32: local function getSelection() ShadowTheAge@32: return selected ShadowTheAge@32: end ShadowTheAge@32: ShadowTheAge@32: local function deleteSelected() ShadowTheAge@32: if selected == 0 then return end; ShadowTheAge@32: table.remove(list, selected); ShadowTheAge@32: selected = 0; ShadowTheAge@32: end ShadowTheAge@32: ShadowTheAge@32: local function addItem(info, value) ShadowTheAge@32: if string.len(value) >= 3 then ShadowTheAge@32: value = string.lower(value); ShadowTheAge@32: for k,v in pairs(list) do ShadowTheAge@32: if v == value then return end ShadowTheAge@32: end ShadowTheAge@32: table.insert(list, value); ShadowTheAge@32: end ShadowTheAge@32: end ShadowTheAge@32: ShadowTheAge@32: return { ShadowTheAge@32: name = name, ShadowTheAge@32: type = "group", ShadowTheAge@32: order=order(), ShadowTheAge@32: args = { ShadowTheAge@32: desc = { ShadowTheAge@32: type = "description", ShadowTheAge@32: order=order(), ShadowTheAge@32: name = desc ShadowTheAge@32: }, ShadowTheAge@32: input = { ShadowTheAge@32: type = "input", ShadowTheAge@32: name = "Add new", ShadowTheAge@32: order=order(), ShadowTheAge@32: set = addItem ShadowTheAge@32: }, ShadowTheAge@32: list = { ShadowTheAge@32: name = "Current list", ShadowTheAge@32: type = "select", ShadowTheAge@32: values=list, ShadowTheAge@32: style="radio", ShadowTheAge@32: order=order(), ShadowTheAge@32: set = setSelection, ShadowTheAge@32: get = getSelection, ShadowTheAge@32: }, ShadowTheAge@32: delete = { ShadowTheAge@32: type = "execute", ShadowTheAge@32: name = "Delete selected", ShadowTheAge@32: order=order(), ShadowTheAge@32: func = deleteSelected ShadowTheAge@32: }, ShadowTheAge@32: }, ShadowTheAge@32: } ShadowTheAge@32: end ShadowTheAge@32: ShadowTheAge@32: local function getLFGGroups() ShadowTheAge@32: local table = {} ShadowTheAge@32: for i=1,#addon.lfgGroups do ShadowTheAge@32: local groupId = addon.lfgGroups[i] ShadowTheAge@32: table[groupId] = (C_LFGList.GetCategoryInfo(groupId)) ShadowTheAge@32: end ShadowTheAge@32: return table; ShadowTheAge@32: end ShadowTheAge@32: ShadowTheAge@32: local function register() ShadowTheAge@32: local CRAOptions = { ShadowTheAge@32: type = "group", ShadowTheAge@32: get = getter, ShadowTheAge@32: set = setter, ShadowTheAge@32: args = { ShadowTheAge@32: reload = { ShadowTheAge@32: type = "execute", ShadowTheAge@32: name = "Reload UI", ShadowTheAge@32: order=order(), ShadowTheAge@32: func = ReloadUI, ShadowTheAge@32: hidden = haveToReloadUI ShadowTheAge@32: }, ShadowTheAge@32: reloadDesc = { ShadowTheAge@32: name = "UI reload is required for some settings to take effect", ShadowTheAge@32: type = "description", ShadowTheAge@32: order=order(), ShadowTheAge@32: width="double", ShadowTheAge@32: hidden = haveToReloadUI ShadowTheAge@32: }, ShadowTheAge@32: general={ ShadowTheAge@32: name = "General options", ShadowTheAge@32: type = "group", ShadowTheAge@32: order=order(), ShadowTheAge@32: args = { ShadowTheAge@32: quickJoinHint = { ShadowTheAge@32: name = "Show Quick Join Hint", ShadowTheAge@32: type = "toggle", ShadowTheAge@32: order=order(), ShadowTheAge@32: }, ShadowTheAge@32: minimap = { ShadowTheAge@32: name = "Hide minimap button", ShadowTheAge@32: type = "toggle", ShadowTheAge@32: arg = {"minimap","hide",callback="toggleMinimapIcon"}, ShadowTheAge@32: order=order(), ShadowTheAge@32: }, ShadowTheAge@32: allLanguages = { ShadowTheAge@32: name = "All language groups", ShadowTheAge@32: type = "toggle", ShadowTheAge@32: order=order(), ShadowTheAge@32: }, ShadowTheAge@32: applyAsDD = { ShadowTheAge@32: name = "Apply to groups as DD only", ShadowTheAge@32: type = "toggle", ShadowTheAge@32: width = "double", ShadowTheAge@32: order=order(), ShadowTheAge@32: }, ShadowTheAge@32: quickJoin = { ShadowTheAge@32: name = "Quick Join Categories", ShadowTheAge@32: type = "multiselect", ShadowTheAge@32: values = getLFGGroups(), ShadowTheAge@32: get = multiGetter, ShadowTheAge@32: set = multiSetter, ShadowTheAge@32: order=order() ShadowTheAge@32: }, ShadowTheAge@32: hopGroupHeader = { ShadowTheAge@32: name = "Realm Hoppers Union", ShadowTheAge@32: type = "header", ShadowTheAge@32: order=order(), ShadowTheAge@32: }, ShadowTheAge@32: hopGroupDesc = { ShadowTheAge@32: name = "Help other CrossRealmAssist users (and other people) and they will help you someday! Open a group for others when you are away. CRA can automatically open such group when following conditions are met:", ShadowTheAge@32: type = "description", ShadowTheAge@32: order=order(), ShadowTheAge@32: }, ShadowTheAge@32: autoCreateHopGroup = { ShadowTheAge@32: name = "You are AFK at garrison", ShadowTheAge@32: type = "toggle", ShadowTheAge@32: order=order(), ShadowTheAge@32: } ShadowTheAge@32: } ShadowTheAge@32: }, ShadowTheAge@32: keywords={ ShadowTheAge@32: name = "Keywords", ShadowTheAge@32: type = "group", ShadowTheAge@32: order=order(), ShadowTheAge@32: args={ ShadowTheAge@32: blacklist = createKeywordTable("Blacklisted keywords","Groups with these keywords will be ignored when quick joining. Don't be evil","stoplist"), ShadowTheAge@32: whitelist = createKeywordTable("Priority keywords","Groups with these keywords are high-priority groups and are first to join regardless of group size","priorityList"), ShadowTheAge@32: highlight = createKeywordTable("Highlight keywords","Groups with these keywords will be highlighted in green in the Manual Join panel","highlightList") ShadowTheAge@32: } ShadowTheAge@32: }, ShadowTheAge@32: appearance={ ShadowTheAge@32: name = "Appearance", ShadowTheAge@32: type = "group", ShadowTheAge@32: order=order(), ShadowTheAge@32: args={ ShadowTheAge@32: uiScale = { ShadowTheAge@32: name = "Mini panel size", ShadowTheAge@32: type = "range", ShadowTheAge@32: min=0.5, max=1.5,isPercent=true,bigStep=0.05, ShadowTheAge@32: order=order(), ShadowTheAge@32: arg={"uiScale",callback="updateUIScale"} ShadowTheAge@32: }, ShadowTheAge@32: lfgPanelScale = { ShadowTheAge@32: name = "Manual Join panel size", ShadowTheAge@32: type = "range", ShadowTheAge@32: min=0.5, max=1.5,isPercent=true,bigStep=0.05, ShadowTheAge@32: order=order(), ShadowTheAge@32: arg={"lfgPanelScale",callback="updateLfgScale"} ShadowTheAge@32: }, ShadowTheAge@32: listItemCount = { ShadowTheAge@32: name = "Manual Join list size", ShadowTheAge@32: type = "range", ShadowTheAge@32: min=5, max=30,step=1, ShadowTheAge@32: order=order(), ShadowTheAge@32: arg={"listItemCount",needReloadUI=1} ShadowTheAge@32: }, ShadowTheAge@32: extraColumns = { ShadowTheAge@32: name = "Show extra info in group table", ShadowTheAge@32: type = "multiselect", ShadowTheAge@32: values = {rtype="Realm type (PVE/PVP/etc)",groupAge="Group age",joinTime="Time since joining"}, ShadowTheAge@32: arg={"extraColumns",needReloadUI=1}, ShadowTheAge@32: get = multiGetter, ShadowTheAge@32: set = multiSetter, ShadowTheAge@32: order=order() ShadowTheAge@32: }, ShadowTheAge@32: } ShadowTheAge@32: }, ShadowTheAge@32: about={ ShadowTheAge@32: name = "About", ShadowTheAge@32: type = "group", ShadowTheAge@32: order=order(), ShadowTheAge@32: args={ ShadowTheAge@32: aboutHeader = { ShadowTheAge@32: name = "CrossRealmAssist "..version.." by ShadowTheAge", ShadowTheAge@32: type = "header", ShadowTheAge@32: order=order(), ShadowTheAge@32: }, ShadowTheAge@32: aboutDesc = { ShadowTheAge@32: name = about, ShadowTheAge@32: type = "description", ShadowTheAge@32: width = "full", ShadowTheAge@32: order=order(), ShadowTheAge@32: } ShadowTheAge@32: } ShadowTheAge@32: } ShadowTheAge@32: } ShadowTheAge@32: } ShadowTheAge@32: AceConfig:RegisterOptionsTable("CrossRealmAssist", CRAOptions) ShadowTheAge@32: registered = true; ShadowTheAge@32: end ShadowTheAge@32: ShadowTheAge@32: addon.showSettings = function() ShadowTheAge@32: db = addon.db; ShadowTheAge@32: if not registered then register() end ShadowTheAge@32: LibStub("AceConfigDialog-3.0"):Open("CrossRealmAssist") ShadowTheAge@32: end