-- BuyEmAll - By Cogwheel v1.12 - See readme.txt --[[Hook BuyMerchantItem for debugging purposes function BuyMerchantItem(button, amount) if not amount then amount = 1 end print("Buying "..amount.." items.") end --]] -- Herb & Enchanting item lists courtesy of Periodic Table by Tekkub BuyEmAll_SpecialItems = { Herb = "3358 8839 13466 4625 13467 3821 785 13465 13468 2450 2452 3818 3355 3357 8838 3369 3820 8153 8836 13463 8845 8846 13464 2447 2449 765 2453 3819 3356 8831", Enchant = "11083 16204 11137 11176 10940 11174 10938 11135 11175 16202 11134 16203 10998 11082 10939 11084 14343 11139 10978 11177 14344 11138 11178", } function BuyEmAllFrame_OnLoad() -- Set up confirmation dialog StaticPopupDialogs["BUYEMALL_CONFIRM"] = { text = BUYEMALL_CONFIRMATION, button1 = TEXT(YES), button2 = TEXT(NO), OnAccept = BuyEmAll_OnAccept, timeout = 0, hideOnEscape = true, } BuyEmAllStackButton.defaultText = BUYEMALL_STACK BuyEmAllMaxButton.defaultText = BUYEMALL_MAX -- Replace the SplitStack callback and for each merchant item button for i=1,12 do local button=getglobal("MerchantItem"..i.."ItemButton") button.SplitStack = BuyEmAll_SplitStack button:SetScript("OnHide", function() if ( this.hasBuyEmAll == 1 ) then BuyEmAllFrame:Hide(); end end) end end function BuyEmAllCostMoney_OnLoad() MoneyTypeInfo["BUYEMALL"] = { UpdateFunc = function() return this.staticMoney end, showSmallerCoins = "Backpack", fixedWidth = 1, collapse = 0, truncateSmallCoins = nil } this.small = 1 this.staticMoney = 0 MoneyFrame_SetType("BUYEMALL") end --[[ Since I have to control two different paths through this function, I just recreated it here to make life a bit easier. ]] function MerchantItemButton_OnClick(button, ignoreModifiers) if ( MerchantFrame.selectedTab == 1 ) then -- Is merchant frame if ( button == "LeftButton" ) then if ( IsControlKeyDown() and not ignoreModifiers ) then DressUpItemLink(GetMerchantItemLink(this:GetID())); elseif ( IsShiftKeyDown() and not ignoreModifiers ) then if ( ChatFrameEditBox:IsVisible() ) then ChatFrameEditBox:Insert(GetMerchantItemLink(this:GetID())); else BuyEmAll_ChooseAmount() end else PickupMerchantItem(this:GetID()); end else if ( IsControlKeyDown() and not ignoreModifiers ) then return; elseif ( IsShiftKeyDown() and not ignoreModifiers ) then BuyEmAll_ChooseAmount() else BuyMerchantItem(this:GetID()); end end else -- Is buyback item BuybackItem(this:GetID()); end end -- Courtesy of wowwiki.com function GetItemInfoFromItemLink(link) local itemId = nil; if ( type(link) == "string" ) then _,_, itemId = string.find(link, "item:(%d+):"); end if ( itemId ) then return itemId, GetItemInfo(itemId); end end -- Figures out maximum purchase amount and shows the BuyEmAllFrame function BuyEmAll_ChooseAmount() local name, _, price, quantity, numAvailable = GetMerchantItemInfo(this:GetID()); this.presetStack = quantity this.price = price this.itemName = name this.itemID, _,_,_,_,_, this.itemSubType, this.stackSize = GetItemInfoFromItemLink(GetMerchantItemLink(this:GetID())) local bagSpace, specialSpace = BuyEmAll_FreeSpace(name, itemID) local specialMax = floor(specialSpace / quantity) * quantity this.bagMax = floor(bagSpace / quantity) * quantity + specialMax this.moneyMax = floor(GetMoney() / price) * quantity this.available = numAvailable local maxPurchase = min(this.bagMax, this.moneyMax) if numAvailable ~= -1 then maxPurchase = min(maxPurchase, numAvailable * quantity) end this.defaultStack = specialMax > 0 and specialMax <= maxPurchase and specialMax or quantity if not name or maxPurchase == 0 then return elseif maxPurchase == 1 then MerchantItemButton_OnClick("LeftButton", 1) return end OpenBuyEmAllFrame(maxPurchase, "BOTTOMLEFT", "TOPLEFT") end -- Determines free bag space. function BuyEmAll_FreeSpace(name, itemID) local returns = { freeSpace = 0, specialSpace = 0} for theBag = 0,4 do local which = "freeSpace" local doBag = true if theBag > 0 then local _,_,_,_,_,_,bagSubType = GetItemInfoFromItemLink(GetInventoryItemLink("player", theBag + 19)) -- Bag #1 is in inventory slot 20 if bagSubType == "Ammo Pouch" and this.itemSubType == "Bullet" or bagSubType == "Quiver" and this.itemSubType == "Arrow" then which = "specialSpace" elseif bagSubType == "Ammo Pouch" and this.itemSubType ~= "Bullet" or bagSubType == "Quiver" and this.itemSubType ~= "Arrow" or bagSubType == "Herb Bag" and not BuyEmAll_IsSpecial("Herb") or bagSubType == "Enchanting Bag" and not BuyEmAll_IsSpecial("Enchant") then doBag = false end end if doBag then local numSlot = GetContainerNumSlots(theBag); for theSlot = 1, numSlot do local itemLink = GetContainerItemLink(theBag, theSlot); if not itemLink then returns[which] = returns[which] + this.stackSize; elseif string.find(itemLink, "%["..name.."%]") then local _,itemCount = GetContainerItemInfo(theBag, theSlot) returns[which] = returns[which] + this.stackSize - itemCount end end end end return returns.freeSpace, returns.specialSpace end -- Determine whether an item is an herb or enchanting material function BuyEmAll_IsSpecial(which) for itemID in gfind(BuyEmAll_SpecialItems[which], "%d+") do if tonumber(this.itemID) == tonumber(itemID) then return true end end return false end function BuyEmAll_SplitStack(amount) local button = BuyEmAllFrame.owner if (amount > 0) then amount = ceil(amount/button.presetStack) * button.presetStack if amount > button.stackSize and amount > button.defaultStack then local dialog = StaticPopup_Show("BUYEMALL_CONFIRM", amount, button.itemName) dialog.data = amount elseif button.presetStack > 1 then BuyEmAll_OnAccept(amount) else BuyMerchantItem(button:GetID(), amount); BuyEmAllFrame:Hide() end end end function BuyEmAll_OnAccept(amount) BuyEmAllFrame:Hide() local button = BuyEmAllFrame.owner local numLoops, purchAmount, leftover if button.presetStack > 1 then numLoops = amount/button.presetStack purchAmount = 1 leftover = 0 else numLoops = floor(amount/button.stackSize) purchAmount = button.stackSize leftover = mod(amount, button.stackSize) end for i = 1, numLoops do BuyMerchantItem(button:GetID(), purchAmount) end if leftover > 0 then BuyMerchantItem(button:GetID(), leftover) end end local OldMerchantFrame_OnHide = MerchantFrame_OnHide function MerchantFrame_OnHide(...) StaticPopup_Hide("BUYEMALL_CONFIRM") return OldMerchantFrame_OnHide(unpack(arg)) end function BuyEmAll_UpdateCost(amount) local button = BuyEmAllFrame.owner local purchase = ceil((amount and amount or BuyEmAllFrame.split) / button.presetStack) local cost = purchase * button.price MoneyFrame_Update("BuyEmAllCostMoney", cost) end function BuyEmAllStack_Click() BuyEmAll_ConfirmPurchase(BuyEmAllFrame.owner.stackSize) end function BuyEmAllMax_Click() BuyEmAll_ConfirmPurchase(BuyEmAllFrame.maxStack) end function BuyEmAll_ConfirmPurchase(amount) local dialog = StaticPopup_Show("BUYEMALL_CONFIRM", amount, BuyEmAllFrame.owner.itemName) dialog.data = amount end function BuyEmAllStackButton_Enter() local amount = BuyEmAllFrame.owner.stackSize BuyEmAll_UpdateCost(amount) GameTooltip:SetOwner(this, "ANCHOR_BOTTOMRIGHT") GameTooltip:SetText(BUYEMALL_STACK_SIZE.." - |cFFFFFFFF"..amount.."|r") end function BuyEmAllMaxButton_Enter() local amount = BuyEmAllFrame.maxStack BuyEmAll_UpdateCost(amount) GameTooltip:SetOwner(this, "ANCHOR_BOTTOMRIGHT") GameTooltip:SetText(BUYEMALL_CAN_BUY.." - |cFFFFFFFF"..amount.."|r") GameTooltip:AddDoubleLine(BUYEMALL_CAN_FIT, BuyEmAllFrame.owner.bagMax,1,1,1,1,1,1) GameTooltip:AddDoubleLine(BUYEMALL_CAN_AFFORD, BuyEmAllFrame.owner.moneyMax,1,1,1,1,1,1) local available = BuyEmAllFrame.owner.available if available == -1 then available = "∞" end GameTooltip:AddDoubleLine(BUYEMALL_AVAILABLE, available,1,1,1,1,1,1) GameTooltip:Show() end function BuyEmAllMSButton_Leave() BuyEmAll_UpdateCost() GameTooltip:Hide() end --[[ Below is the modified code from the built-in StackSplitFrame ]] function OpenBuyEmAllFrame(maxStack, anchor, anchorTo) if ( BuyEmAllFrame.owner ) then BuyEmAllFrame.owner.hasBuyEmAll = 0; end BuyEmAllFrame.maxStack = maxStack; if ( BuyEmAllFrame.maxStack < 2 ) then BuyEmAllFrame:Hide(); return; end BuyEmAllFrame.owner = this; this.hasBuyEmAll = 1; BuyEmAllFrame.split = this.defaultStack; BuyEmAllFrame.typing = 0; BuyEmAllText:SetText(BuyEmAllFrame.split); BuyEmAllLeftButton:Disable(); BuyEmAllRightButton:Enable(); BuyEmAllStackButton:SetText(BuyEmAllStackButton.defaultText) BuyEmAllMaxButton:SetText(BuyEmAllMaxButton.defaultText) BuyEmAll_UpdateCost() BuyEmAllStackButton:Enable() if BuyEmAllFrame.maxStack < this.stackSize then BuyEmAllStackButton:Disable() end BuyEmAllFrame:ClearAllPoints(); BuyEmAllFrame:SetPoint(anchor, this, anchorTo, 0, 0); BuyEmAllFrame:Show(); end function BuyEmAllFrame_OnChar() if ( arg1 < "0" or arg1 > "9" ) then return; end if ( this.typing == 0 ) then this.typing = 1; this.split = 0; end local split = (this.split * 10) + arg1; if ( split == this.split ) then if( this.split == 0 ) then this.split = 1; end BuyEmAll_UpdateCost() return; end if ( split <= this.maxStack ) then this.split = split; BuyEmAllText:SetText(split); if ( split == this.maxStack ) then BuyEmAllRightButton:Disable(); else BuyEmAllRightButton:Enable(); end if ( split <= this.owner.presetStack ) then BuyEmAllLeftButton:Disable(); else BuyEmAllLeftButton:Enable(); end elseif ( split == 0 ) then this.split = 1; end BuyEmAll_UpdateCost() end function BuyEmAllFrame_OnKeyDown() if ( arg1 == "BACKSPACE" or arg1 == "DELETE" ) then if ( this.typing == 0 or this.split == 1 ) then return; end this.split = floor(this.split / 10); if ( this.split <= 1 ) then this.split = 1; this.typing = 0; end if ( this.split <= this.owner.presetStack ) then BuyEmAllLeftButton:Disable(); else BuyEmAllLeftButton:Enable(); end BuyEmAllText:SetText(this.split); if ( this.money == this.maxStack ) then BuyEmAllRightButton:Disable(); else BuyEmAllRightButton:Enable(); end BuyEmAll_UpdateCost() elseif ( arg1 == "ENTER" ) then BuyEmAllOkay_Click(); elseif ( arg1 == "ESCAPE" ) then BuyEmAllCancel_Click(); elseif ( arg1 == "LEFT" or arg1 == "DOWN" ) then BuyEmAllLeft_Click(); elseif ( arg1 == "RIGHT" or arg1 == "UP" ) then BuyEmAllRight_Click(); end end function BuyEmAllLeft_Click() local preset = BuyEmAllFrame.owner.presetStack if ( BuyEmAllFrame.split <= preset ) then return; end local decrease = mod(BuyEmAllFrame.split, preset) decrease = decrease == 0 and preset or decrease BuyEmAllFrame.split = BuyEmAllFrame.split - decrease BuyEmAllText:SetText(BuyEmAllFrame.split) if ( BuyEmAllFrame.split <= preset ) then BuyEmAllLeftButton:Disable() end BuyEmAllRightButton:Enable() BuyEmAll_UpdateCost() end function BuyEmAllRight_Click() local preset = BuyEmAllFrame.owner.presetStack local increase = preset - mod(BuyEmAllFrame.split, preset) if ( BuyEmAllFrame.split + increase > BuyEmAllFrame.maxStack ) then return; end BuyEmAllFrame.split = BuyEmAllFrame.split + increase; BuyEmAllText:SetText(BuyEmAllFrame.split); if ( BuyEmAllFrame.split == BuyEmAllFrame.maxStack ) then BuyEmAllRightButton:Disable(); end BuyEmAllLeftButton:Enable(); BuyEmAll_UpdateCost() end function BuyEmAllOkay_Click() if ( BuyEmAllFrame.owner ) then BuyEmAllFrame.owner.SplitStack(BuyEmAllFrame.split); end end function BuyEmAllCancel_Click() BuyEmAllFrame:Hide() StaticPopup_Hide("BUYEMALL_CONFIRM") end function BuyEmAllFrame_OnHide() if ( this.owner ) then BuyEmAllFrame.owner.hasBuyEmAll = 0; end StaticPopup_Hide("BUYEMALL_CONFIRM") end