Quantcast

rename files

Bediko [01-25-15 - 20:02]
rename files
Filename
Looking for Satchels.lua
Looking for Satchels.toc
diff --git a/Looking for Satchels.lua b/Looking for Satchels.lua
new file mode 100644
index 0000000..dc4e0a1
--- /dev/null
+++ b/Looking for Satchels.lua
@@ -0,0 +1,616 @@
+SatchelQueue = LibStub("AceAddon-3.0"):NewAddon("Looking for Satchels", "AceConsole-3.0", "AceEvent-3.0", "AceHook-3.0", "AceTimer-3.0")
+local SatchelQueue = SatchelQueue
+
+local BUTTON_TEXT = "Satchel"
+local BUTTON_QUEUED = "Cancel"
+
+local timer = nil
+
+local sound_all = nil
+local sound_bg = nil
+
+local should_auto_loot = false
+
+StaticPopupDialogs["SATCHEL_QUEUE"] = {
+	text = "",
+    button1 = ACCEPT,
+    button2 = DECLINE,
+	OnAccept = function(self)
+		SetLFGDungeon(LE_LFG_CATEGORY_LFD, self.data)
+		JoinLFG(LE_LFG_CATEGORY_LFD)
+	end,
+	OnShow = function(self)
+		local name = GetLFGDungeonInfo(self.data)
+		self.text:SetFormattedText(LFG_CALL_TO_ARMS .. name, "\n") -- :(
+	end,
+    hideOnEscape = 1,
+    whileDead = 1
+}
+
+function SatchelQueue:OnInitialize()
+    local defaults = {
+        global = {
+            icon = true,
+            tooltip = false,
+            requeue = false,
+            prevent_auto_loot = true,
+            fake_auto_loot = false,
+            prioritise = false,
+            exclusive = false,
+            flash_enable = false,
+            sound_enable = true,
+            sound_force = false,
+            sound_file = "Sound/Spells/Clearcasting_Impact_Chest.wav",
+
+            saved_uids = {},
+            items = {},
+            count = 0,
+            coin_min = -1,
+            coin_max = -1,
+            coin_total = 0
+        }
+    }
+    self.db = LibStub("AceDB-3.0"):New("SatchelQueueDB", defaults, true)
+
+    local option_table = {
+        type = "group",
+        set = function(info, val) self.db.global[info[#info]] = val end,
+        get = function(info) return self.db.global[info[#info]] end,
+        args = {
+            header_queueing = {
+                order = 0,
+                type = "header",
+                name = "Queueing"
+            },
+            prioritise = {
+                order = 1,
+                type = "toggle",
+                width = "double",
+                name = "Prioritise newer dungeons"
+            },
+            exclusive = {
+                order = 2,
+                type = "toggle",
+                name = "Exclusively",
+                desc = "Oueue exclusively for the newer dungeons when prioritised",
+                disabled = function(info) return not self.db.global.prioritise end
+            },
+            requeue = {
+                order = 3,
+                type = "toggle",
+                width = "full",
+                name = "Requeue after leaving"
+            },
+            icon = {
+                order = 4,
+                type = "toggle",
+                width = "full",
+                name = "Enable LFG minimap icon while waiting"
+            },
+            header_satchel = {
+                order = 5,
+                type = "header",
+                name = "Satchels"
+            },
+            prevent_auto_loot = {
+                order = 6,
+                type = "toggle",
+                width = "double",
+                name = "Prevent auto loot"
+            },
+            fake_auto_loot = {
+                order = 7,
+                type = "toggle",
+                name = "Only protect BoP items",
+                desc = "Non-BoP items will still be looted",
+                disabled = function(info) return not self.db.global.prevent_auto_loot end
+            },
+            tooltip = {
+                order = 8,
+                type = "toggle",
+                width = "double",
+                name = "Enable contents in tooltip"
+            },
+            header_notification = {
+                order = 9,
+                type = "header",
+                name = "Notification"
+            },
+            flash_enable = {
+                order = 10,
+                type = "toggle",
+                width = "full",
+                name = "Enable Screen Flash"
+            },
+            sound_enable = {
+                order = 11,
+                type = "toggle",
+                width = "double",
+                name = "Enable Sound"
+            },
+            sound_force = {
+                order = 12,
+                type = "toggle",
+                name = "Force unmute for alert",
+                disabled = function(info) return not self.db.global.sound_enable end
+            },
+            sound_file = {
+                order = 13,
+                type = "input",
+                width = "full",
+                name = "Sound File",
+                disabled = function(info) return not self.db.global.sound_enable end
+            }
+        }
+    }
+    local stats_table = {
+        type = "group",
+        args = {
+            text = {
+                type = "input",
+                name = "Statistics",
+                width = "full",
+                multiline = 24,
+                get = function(info)
+                    local s = "total satchels: " .. self.db.global.count .. "\n"
+                    if self.db.global.coin_min > 0 then
+                        s = s .. "\ntotal gold: " .. GetMoneyString(self.db.global.coin_total)
+                        s = s .. "\nmin: " .. GetMoneyString(self.db.global.coin_min)
+                        s = s .. "\nmax: " .. GetMoneyString(self.db.global.coin_max)
+                        s = s .. "\navg: " .. GetMoneyString(self.db.global.coin_total / self.db.global.count) .. "\n"
+                    end
+                    s = s .. "\nitems:"
+                    local items = {}
+                    for k, v in pairs(self.db.global.items) do
+                        table.insert(items, { id = k, count = v })
+                    end
+                    table.sort(items, function(a, b) return a.count > b.count end)
+                    for i = 1, #items do
+                        s = s .. "\n" .. (GetItemInfo(items[i].id) or "<item not cached>")  .. ": " .. items[i].count
+                    end
+                    return s
+                end,
+                set = nil
+            },
+            reset = {
+                type = "execute",
+                name = "reload",
+                width = "full",
+                func = function(info)
+                    LibStub("AceConfigRegistry-3.0"):NotifyChange("Statistics")
+                end
+            }
+        }
+    }
+
+    LibStub("AceConfig-3.0"):RegisterOptionsTable("Looking for Satchels", option_table)
+
+    local option_frame = LibStub("AceConfigDialog-3.0"):AddToBlizOptions("Looking for Satchels", "Looking for Satchels")
+
+    self:RegisterChatCommand("satchel", function(...) InterfaceOptionsFrame_OpenToCategory(option_frame) end)
+
+end
+
+local function SatchelID(link)
+	if not link then
+		return nil
+	end
+    return select(3, string.find(link, "|Hitem:69903:0:0:0:0:0:0:(%d+):")) or select(3, string.find(link, "|Hitem:90818:0:0:0:0:0:0:(%d+):")) or select(3, string.find(link, "|Hitem:104260:0:0:0:0:0:0:(%d+):")) or nil
+end
+
+local function Satchel_OnLeave(self, motion)
+    SatchelQueue:Unhook(self, "OnLeave")
+    SatchelQueue:Unhook(self, "PreClick")
+    SatchelQueue:Unhook(self, "PostClick")
+end
+
+local toggle_loot, default_loot = nil, nil
+local function Satchel_PreClick(self, button)
+    if button == "RightButton" and GetCVarBool("autoLootDefault") ~= IsModifiedClick("AUTOLOOTTOGGLE") then
+        should_auto_loot = true
+        toggle_loot, default_loot = true, GetCVarBool("autoLootDefault")
+        SetCVar("autoLootDefault", default_loot and 0 or 1)
+    end
+end
+
+local function Satchel_PostClick(self, button)
+    if toggle_loot then
+        toggle_loot = false
+        SetCVar("autoLootDefault", default_loot)
+    end
+end
+
+local function Satchel_OnEnter(self, motion)
+    if SatchelQueue.db.global.prevent_auto_loot and not SatchelQueue:IsHooked(self, "OnLeave") and SatchelID(GetContainerItemLink(self:GetParent():GetID(), self:GetID())) then
+        SatchelQueue:HookScript(self, "OnLeave", Satchel_OnLeave)
+        SatchelQueue:HookScript(self, "PreClick", Satchel_PreClick)
+        SatchelQueue:HookScript(self, "PostClick", Satchel_PostClick)
+    end
+end
+
+local function Satchel_TooltipText(self)
+    local _, link = self:GetItem()
+    local id = link and SatchelID(link) or nil
+    if id and SatchelQueue.db.global.tooltip then
+        if type(SatchelQueue.db.global.saved_uids[id]) == "table" then
+            self:AddLine(" ")
+            for slot = 1, #SatchelQueue.db.global.saved_uids[id] do
+                local content = SatchelQueue.db.global.saved_uids[id][slot]
+                if content < 0 then
+                    self:AddLine("|cffffffff" .. GetCoinTextureString(-content) .. "|r")
+                else
+                    local name, _, quality = GetItemInfo(content)
+                    if name then
+                        local r, g, b = GetItemQualityColor(quality)
+                        self:AddLine(name, r, g, b)
+                    end
+                end
+            end
+        end
+    end
+end
+
+function SatchelQueue:OnEnable()
+    self:Hook("ContainerFrameItemButton_OnEnter", Satchel_OnEnter, true)
+    self:HookScript(GameTooltip, "OnTooltipSetItem", Satchel_TooltipText)
+    self:SecureHook("QueueStatusFrame_Update", "UpdateStatus")
+    self:RegisterEvent("LOOT_OPENED")
+    self:RegisterEvent("LOOT_SLOT_CLEARED")
+    SatchelQueue_Button:Show()
+end
+
+function SatchelQueue:OnDisable()
+    self:UnregisterEvent("LOOT_OPENED")
+    self:UnregisterEvent("LOOT_SLOT_CLEARED")
+    self:TimerStop()
+    SatchelQueue_Button:Hide()
+    self:UnhookAll()
+end
+
+function SatchelQueue:Toggle()
+    if timer then
+        self:TimerStop()
+    else
+        self:TimerStart()
+    end
+    self:UpdateStatus(QueueStatusFrame)
+end
+
+function SatchelQueue:TimerStart()
+    if not timer then
+        self:RegisterEvent("LFG_UPDATE_RANDOM_INFO")
+        timer = self:ScheduleRepeatingTimer(RequestLFDPlayerLockInfo, LFD_STATISTIC_CHANGE_TIME)
+        SatchelQueue_Button:SetText(BUTTON_QUEUED)
+        RequestLFDPlayerLockInfo()
+    end
+end
+
+local function ResetSound()
+    if sound_all then
+        SetCVar("Sound_EnableAllSound", sound_all)
+        SetCVar("Sound_EnableSoundWhenGameIsInBG", sound_bg)
+
+        sound_all = nil
+        sound_bg = nil
+    end
+end
+
+function SatchelQueue:TimerStop()
+    if timer then
+        self:UnregisterEvent("LFG_UPDATE_RANDOM_INFO")
+        self:CancelTimer(timer, true)
+        timer = nil;
+        SatchelQueue_Button:SetText(BUTTON_TEXT)
+        ResetSound()
+    end
+end
+
+-- code copied from Blizzard's QueueStatusFrame_Update, may be it can be hooked somehow instead?
+function SatchelQueue:UpdateStatus(self)
+    local showMinimapButton, animateEye;
+
+    local nextEntry = 1;
+
+    local totalHeight = 4; --Add some buffer height
+
+    --Try each LFG type
+    for i=1, NUM_LE_LFG_CATEGORYS do
+        local mode, submode = GetLFGMode(i);
+        if ( mode ) then
+            local entry = QueueStatusFrame_GetEntry(self, nextEntry);
+            QueueStatusEntry_SetUpLFG(entry, i);
+            entry:Show();
+            totalHeight = totalHeight + entry:GetHeight();
+            nextEntry = nextEntry + 1;
+
+            showMinimapButton = true;
+            if ( mode == "queued" ) then
+                animateEye = true;
+            end
+        end
+    end
+
+    --Try all PvP queues
+    for i=1, GetMaxBattlefieldID() do
+        local status, mapName, instanceID, levelRangeMin, levelRangeMax, teamSize, registeredMatch, eligibleInQueue, waitingOnOtherActivity = GetBattlefieldStatus(i);
+        if ( status and status ~= "none" ) then
+            local entry = QueueStatusFrame_GetEntry(self, nextEntry);
+            QueueStatusEntry_SetUpBattlefield(entry, i);
+            entry:Show();
+            totalHeight = totalHeight + entry:GetHeight();
+            nextEntry = nextEntry + 1;
+
+            showMinimapButton = true;
+            if ( status == "queued" ) then
+                animateEye = true;
+            end
+        end
+    end
+
+    --Try all World PvP queues
+    for i=1, MAX_WORLD_PVP_QUEUES do
+        local status, mapName, queueID = GetWorldPVPQueueStatus(i);
+        if ( status and status ~= "none" ) then
+            local entry = QueueStatusFrame_GetEntry(self, nextEntry);
+            QueueStatusEntry_SetUpWorldPvP(entry, i);
+            entry:Show();
+            totalHeight = totalHeight + entry:GetHeight();
+            nextEntry = nextEntry + 1;
+
+            showMinimapButton = true;
+            if ( status == "queued" ) then
+                animateEye = true;
+            end
+        end
+    end
+
+    --World PvP areas we're currently in
+    if ( CanHearthAndResurrectFromArea() ) then
+        local entry = QueueStatusFrame_GetEntry(self, nextEntry);
+        QueueStatusEntry_SetUpActiveWorldPVP(entry);
+        entry:Show();
+        totalHeight = totalHeight + entry:GetHeight();
+        nextEntry = nextEntry + 1;
+
+        showMinimapButton = true;
+    end
+
+    --Pet Battle PvP Queue
+    local pbStatus = C_PetBattles.GetPVPMatchmakingInfo();
+    if ( pbStatus ) then
+        local entry = QueueStatusFrame_GetEntry(self, nextEntry);
+        QueueStatusEntry_SetUpPetBattlePvP(entry);
+        entry:Show();
+        totalHeight = totalHeight + entry:GetHeight();
+        nextEntry = nextEntry + 1;
+
+        showMinimapButton = true;
+        if ( pbStatus == "queued" ) then
+            animateEye = true;
+        end
+    end
+
+    --Satchel Queue
+    if SatchelQueue.db.global.icon then
+        local mode = GetLFGMode(LE_LFG_CATEGORY_LFD)
+        if not mode and timer then
+            local entry = QueueStatusFrame_GetEntry(self, nextEntry);
+            QueueStatusEntry_SetMinimalDisplay(entry, "Looking for Satchels", QUEUED_STATUS_QUEUED);
+            entry:Show();
+            totalHeight = totalHeight + entry:GetHeight();
+            nextEntry = nextEntry + 1;
+
+            showMinimapButton = true;
+            animateEye = true;
+        end
+    end
+
+    --Hide all remaining entries.
+    for i=nextEntry, #self.StatusEntries do
+        self.StatusEntries[i]:Hide();
+    end
+
+    --Update the size of this frame to fit everything
+    self:SetHeight(totalHeight);
+
+    --Update the minimap icon
+    if ( showMinimapButton ) then
+        QueueStatusMinimapButton:Show();
+    else
+        QueueStatusMinimapButton:Hide();
+    end
+
+    if ( animateEye ) then
+        EyeTemplate_StartAnimating(QueueStatusMinimapButton.Eye);
+    else
+        EyeTemplate_StopAnimating(QueueStatusMinimapButton.Eye);
+    end
+end
+
+local function CheckQueueReward(dungeonID)
+    local leaderChecked, tankChecked, healerChecked, damageChecked = LFDQueueFrame_GetRoles()
+    local eligible, forTank, forHealer, forDamage, itemCount = GetLFGRoleShortageRewards(dungeonID, LFG_ROLE_SHORTAGE_RARE)
+    return eligible and itemCount > 0 and ((tankChecked and forTank) or (healerChecked and forHealer) or (damageChecked and forDamage))
+end
+
+local function CheckQueuePopReward(dungeonID, role)
+    local eligible, forTank, forHealer, forDamage, itemCount = GetLFGRoleShortageRewards(dungeonID, LFG_ROLE_SHORTAGE_RARE)
+    return eligible and itemCount > 0 and ((role == "TANK" and forTank) or (role == "HEALER" and forHealer) or (role == "DAMAGER" and forDamage))
+end
+
+function SatchelQueue:LFG_UPDATE_RANDOM_INFO()
+    if not timer then
+        return
+    end
+
+    ResetSound()
+
+    local mode, submode = GetLFGMode(LE_LFG_CATEGORY_LFD)
+
+    if not mode then
+        local first, last, step = 1, GetNumRandomDungeons(), 1
+        if self.db.global.prioritise then
+            first, last, step = last, first, -1
+
+            if self.db.global.exclusive then
+                last = first
+            end
+        end
+
+        for i = first, last, step do
+            local id = GetLFGRandomDungeonInfo(i)
+            if IsLFGDungeonJoinable(id) and CheckQueueReward(id) then
+                --SetLFGDungeon(LE_LFG_CATEGORY_LFD, id)
+                --JoinLFG(LE_LFG_CATEGORY_LFD)
+				StaticPopup_Show("SATCHEL_QUEUE", nil, nil, id)
+                return
+            end
+        end
+		StaticPopup_Hide("SATCHEL_QUEUE")
+    elseif mode == "proposal" then
+        if submode == "unaccepted" then
+            local _, dungeonID, _, _, _, _, role = GetLFGProposal()
+            if CheckQueuePopReward(dungeonID, role) then
+                if self.db.global.sound_enable then
+                    if self.db.global.sound_force then
+                        if not sound_all then
+                            sound_all = GetCVar("Sound_EnableAllSound")
+                            sound_bg = GetCVar("Sound_EnableSoundWhenGameIsInBG")
+                        end
+
+                        SetCVar("Sound_EnableAllSound", "1")
+                        SetCVar("Sound_EnableSoundWhenGameIsInBG", "1")
+                    end
+                    PlaySoundFile(self.db.global.sound_file, "MASTER")
+                end
+                if self.db.global.flash_enable then
+                    UIFrameFlash(SatchelQueue_Flash, 0.5, 0.5, 10.0, false, 0.0, 0.0)
+                end
+            elseif GetNumSubgroupMembers() == 0 then
+                RejectProposal()
+            end
+        end
+    elseif mode == "lfgparty" then
+        if not self.db.global.requeue then
+            self:TimerStop()
+        end
+    end
+end
+
+--hack: if item is locked, it is being used. only check satchels
+local function GuessOpenSatchel()
+    for bag = 0, NUM_BAG_SLOTS do
+        for slot = 1, GetContainerNumSlots(bag) do
+            local texture, count, locked, quality, readable, lootable, link = GetContainerItemInfo(bag, slot)
+            if locked and lootable then
+                local uid = SatchelID(GetContainerItemLink(bag, slot))
+                if uid then
+                    return uid
+                end
+            end
+        end
+    end
+    return nil
+end
+
+--gold parsing liberated from Wowhead Looter (http://www.wowhead.com/client)
+local WL_CURRENCY = {
+	["1"] = COPPER_AMOUNT:gsub("%%d ", ""),
+	["100"] = SILVER_AMOUNT:gsub("%%d ", ""),
+	["10000"] = GOLD_AMOUNT:gsub("%%d ", ""),
+};
+
+local function wlParseCoin(strCoin)
+	local coin = 0;
+	for k, v in pairs(WL_CURRENCY) do
+		local found, _, a = strCoin:find("(%d+) "..v);
+		if found then
+			coin = coin + a * tonumber(k);
+		end
+	end
+
+	return coin;
+end
+
+local function IsBindOnPickup(link)
+    SatchelQueue_Tooltip:SetOwner(UIParent, "ANCHOR_NONE")
+    SatchelQueue_Tooltip:SetHyperlink(link)
+
+    for _,region in ipairs({SatchelQueue_Tooltip:GetRegions()}) do
+        if region and region:GetObjectType() == "FontString" then
+            if region:GetText() == ITEM_BIND_ON_PICKUP then
+                return 1
+            end
+        end
+    end
+    return nil
+end
+
+function SatchelQueue:LOOT_OPENED()
+    local uid = GuessOpenSatchel()
+    if uid then
+        if not self.db.global.saved_uids[uid] then
+            self.db.global.count = self.db.global.count + 1
+
+            for slot = 1, GetNumLootItems() do
+				local slotType = GetLootSlotType(slot)
+                local texture, item, quantity, quality, locked = GetLootSlotInfo(slot)
+
+                if slotType == LOOT_SLOT_MONEY then
+                    local coin = wlParseCoin(item)
+                    self.db.global.coin_total = self.db.global.coin_total + coin
+
+                    if self.db.global.coin_min == -1 then
+                        self.db.global.coin_min = coin
+                        self.db.global.coin_max = coin
+                    else
+                        self.db.global.coin_min = min(self.db.global.coin_min, coin)
+                        self.db.global.coin_max = max(self.db.global.coin_max, coin)
+                    end
+                elseif slotType == LOOT_SLOT_ITEM then
+                    local _, _, id = string.find(GetLootSlotLink(slot), "|Hitem:(%d+):")
+                    self.db.global.items[id] = (self.db.global.items[id] or 0) + quantity
+                end
+            end
+        end
+
+        local closing = nil
+        if self.db.global.prevent_auto_loot and self.db.global.fake_auto_loot and should_auto_loot then
+            should_auto_loot = false
+            closing = true
+
+            for slot = 1, GetNumLootItems() do
+                if GetLootSlotType(slot) == LOOT_SLOT_MONEY or not IsBindOnPickup(GetLootSlotLink(slot)) then
+                    LootSlot(slot)
+                end
+            end
+            if GetNumLootItems() == 0 then
+                self.db.global.saved_uids[uid] = nil
+            end
+        end
+
+        --rebuild stored items
+        if GetNumLootItems() > 0 then
+            self.db.global.saved_uids[uid] = {}
+            for slot = 1, GetNumLootItems() do
+                local _, item = GetLootSlotInfo(slot)
+                if item then --we havent just looted the slot
+                    self.db.global.saved_uids[uid][slot] = GetLootSlotType(slot) == LOOT_SLOT_MONEY and -wlParseCoin(item) or tonumber(select(3, string.find(GetLootSlotLink(slot), "|Hitem:(%d+):")))
+                end
+            end
+        end
+
+        if closing then
+            CloseLoot()
+        end
+    end
+end
+
+function SatchelQueue:LOOT_SLOT_CLEARED()
+    local uid = GuessOpenSatchel()
+    if uid then
+        if GetNumLootItems() == 1 and not GetLootSlotInfo(1) then
+            self.db.global.saved_uids[uid] = nil
+        end
+    end
+end
diff --git a/Looking for Satchels.toc b/Looking for Satchels.toc
new file mode 100644
index 0000000..67bc326
--- /dev/null
+++ b/Looking for Satchels.toc
@@ -0,0 +1,10 @@
+## Interface: 60100
+## Title: Looking for Satchels
+## Notes: Queues for Satchels!
+## Author: Bediko
+## Version: 0.1.2
+## SavedVariables: SatchelQueueDB
+embeds.xml
+
+Looking for Satchels.lua
+SatchelQueue.xml
\ No newline at end of file