vanilla-wow-addons – Rev 1

Subversion Repositories:
Rev:
--[[
        Auctioneer Addon for World of Warcraft(tm).
        Version: 3.9.0.1000 (Kangaroo)
        Revision: $Id: AucUtil.lua 980 2006-08-31 05:29:48Z mentalpower $

        Auctioneer utility functions.
        Functions to maniuplate items keys, signatures etc

        License:
                This program is free software; you can redistribute it and/or
                modify it under the terms of the GNU General Public License
                as published by the Free Software Foundation; either version 2
                of the License, or (at your option) any later version.

                This program is distributed in the hope that it will be useful,
                but WITHOUT ANY WARRANTY; without even the implied warranty of
                MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                GNU General Public License for more details.

                You should have received a copy of the GNU General Public License
                along with this program(see GPL.txt); if not, write to the Free Software
                Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
]]

--Local function prototypes
local getTimeLeftString, getSecondsLeftString, unpackSeconds, getGSC, getTextGSC, nilSafeString, colorTextWhite, getWarnColor, nullSafe, sanifyAHSnapshot, getAuctionKey, getOppositeKey, getNeutralKey, getHomeKey, isValidAlso, breakItemKey, split, findClass, getCatName, getCatNumberByName, getCatForKey, getKeyFromSig, getCatForSig, getItemLinks, getItems, getItemHyperlinks, loadCategories, loadCategoryClasses, loadCategorySubClasses, chatPrint, setFilterDefaults, protectAuctionFrame, priceForOne, round, delocalizeFilterVal, localizeFilterVal, getLocalizedFilterVal, delocalizeCommand, localizeCommand, findEmptySlot, containerFrameItemButtonOnClick

-- return the string representation of the given timeLeft constant
function getTimeLeftString(timeLeft)
        local timeLeftString = "";

        if timeLeft == Auctioneer.Core.Constants.TimeLeft.Short then
                timeLeftString = _AUCT('TimeShort');

        elseif timeLeft == Auctioneer.Core.Constants.TimeLeft.Medium then
                timeLeftString = _AUCT('TimeMed');

        elseif timeLeft == Auctioneer.Core.Constants.TimeLeft.Long then
                timeLeftString = _AUCT('TimeLong');

        elseif timeLeft == Auctioneer.Core.Constants.TimeLeft.VeryLong then
                timeLeftString = _AUCT('TimeVlong');
        end

        return timeLeftString;
end

function getSecondsLeftString(secondsLeft)
        local timeLeft = nil;

        for i = table.getn(Auctioneer.Core.Constants.TimeLeft.Seconds), 1, -1 do

                if (secondsLeft >= Auctioneer.Core.Constants.TimeLeft.Seconds[i]) then
                        timeLeft = i;
                        break
                end
        end

        return getTimeLeftString(timeLeft);
end

function unpackSeconds(seconds)
        seconds = tonumber(seconds)
        if (not seconds) then
                return
        end

        local weeks
        local days
        local hours
        local minutes

        seconds = math.floor(seconds)

        if (seconds > 604800) then
                weeks = math.floor(seconds / 604800)
                seconds = math.floor(seconds - (weeks * 604800))
        end
        if (seconds > 86400) then
                days = math.floor(seconds / 86400)
                seconds = math.floor(seconds - (days * 86400))
        end
        if (seconds > 3600) then
                hours = math.floor(seconds / 3600)
                seconds = math.floor(seconds - (hours * 3600))
        end
        if (seconds >= 60) then
                minutes = math.floor(seconds / 60)
                seconds = math.floor(seconds - (minutes * 60))
        end

        return (weeks or 0), (days or 0), (hours or 0), (minutes or 0), (seconds or 0)
end

function getGSC(money)
        local g,s,c = EnhTooltip.GetGSC(money);
        return g,s,c;
end

function getTextGSC(money)
        return EnhTooltip.GetGSC(money);
end

-- return an empty string if str is nil
function nilSafeString(str)
        return str or "";
end

function colorTextWhite(text)
        if (not text) then text = ""; end

        local COLORING_START = "|cff%s%s|r";
        local WHITE_COLOR = "e6e6e6";

        return string.format(COLORING_START, WHITE_COLOR, ""..text);
end

function getWarnColor(warn)
        --Make "warn" a required parameter and verify that its a string
        if (not (type(warn) == "string")) then
                return nil
        end

        local cHex, cRed, cGreen, cBlue;

        if (Auctioneer.Command.GetFilter('warn-color')) then
                local FrmtWarnAbovemkt, FrmtWarnUndercut, FrmtWarnNocomp, FrmtWarnAbovemkt, FrmtWarnMarkup, FrmtWarnUser, FrmtWarnNodata, FrmtWarnMyprice

                FrmtWarnToolow = _AUCT('FrmtWarnToolow');
                FrmtWarnNocomp = _AUCT('FrmtWarnNocomp');
                FrmtWarnAbovemkt = _AUCT('FrmtWarnAbovemkt');
                FrmtWarnUser = _AUCT('FrmtWarnUser');
                FrmtWarnNodata = _AUCT('FrmtWarnNodata');
                FrmtWarnMyprice = _AUCT('FrmtWarnMyprice');

                FrmtWarnUndercut = string.format(_AUCT('FrmtWarnUndercut'), tonumber(Auctioneer.Command.GetFilterVal('pct-underlow')));
                FrmtWarnMarkup = string.format(_AUCT('FrmtWarnMarkup'), tonumber(Auctioneer.Command.GetFilterVal('pct-markup')));

                if (warn == FrmtWarnToolow) then
                        --Color Red
                        cHex = "ffff0000";
                        cRed = 1.0;
                        cGreen = 0.0;
                        cBlue = 0.0;

                elseif (warn == FrmtWarnUndercut) then
                        --Color Yellow
                        cHex = "ffffff00";
                        cRed = 1.0;
                        cGreen = 1.0;
                        cBlue = 0.0;

                elseif ((warn == FrmtWarnNocomp) or (warn == FrmtWarnAbovemkt)) then
                        --Color Green
                        cHex = "ff00ff00";
                        cRed = 0.0;
                        cGreen = 1.0;
                        cBlue = 0.0;

                elseif ((warn == FrmtWarnMarkup) or (warn == FrmtWarnUser) or (warn == FrmtWarnNodata) or (warn == FrmtWarnMyprice)) then
                        --Color Gray
                        cHex = "ff999999";
                        cRed = 0.6;
                        cGreen = 0.6;
                        cBlue = 0.6;
                end

        else
                --Color Orange
                cHex = "ffe66600";
                cRed = 0.9;
                cGreen = 0.4;
                cBlue = 0.0;
        end

        return cHex, cRed, cGreen, cBlue
end

-- Used to convert variables that should be numbers but are nil to 0
function nullSafe(val)
        return tonumber(val) or 0;
end

-- Returns the current faction's auction signature, depending on location
function getAuctionKey()
        local serverName = GetCVar("realmName");
        local currentZone = GetMinimapZoneText();
        local factionGroup;

        --Added the ability to record Neutral AH auctions in its own tables.
        if ((currentZone == "Gadgetzan") or (currentZone == "Everlook") or (currentZone == "Booty Bay")) then
                factionGroup = "Neutral"

        else
                factionGroup = UnitFactionGroup("player");
        end
        return serverName.."-"..factionGroup;
end

-- Returns the current faction's opposing faction's auction signature
function getOppositeKey()
        local serverName = GetCVar("realmName");
        local factionGroup = UnitFactionGroup("player");

        if (factionGroup == "Alliance") then factionGroup="Horde"; else factionGroup="Alliance"; end
        return serverName.."-"..factionGroup;
end

-- Returns the current server's neutral auction signature
function getNeutralKey()
        local serverName = GetCVar("realmName");

        return serverName.."-Neutral";
end

-- Returns the current faction's auction signature
function getHomeKey()
        local serverName = GetCVar("realmName");
        local factionGroup = UnitFactionGroup("player");

        return serverName.."-"..factionGroup;
end

-- function returns true, if the given parameter is a valid option for the also command, false otherwise
function isValidAlso(also)
        if (type(also) ~= "string") then
                return false
        end

        if ((also == 'opposite') or (also == 'off') or (also == 'neutral') or (also == 'home')) then
                return true             -- allow special keywords
        end

        -- check if string matches: "[realm]-[faction]"
        local s, e, r, f = string.find(also, "^(.+)-(.+)$")
        if (s == nil) then
                return false    -- invalid string
        end

        -- check if faction = "Horde" or "Alliance"
        if (f == 'Horde') or (f == 'Alliance')or (f == 'Neutral') then
                return true
        end

        return true
end

-- Given an item key, breaks it into its itemID, randomProperty and enchantProperty
function breakItemKey(itemKey)
        local i,j, itemID, randomProp, enchant = string.find(itemKey, "(%d+):(%d+):(%d+)");
        return tonumber(itemID or 0), tonumber(randomProp or 0), tonumber(enchant or 0);
end

function split(str, at)
        local splut = {};

        if (type(str) ~= "string") then return nil end
        if (not str) then str = "" end

        if (not at)
                then table.insert(splut, str)

        else
                for n, c in string.gfind(str, '([^%'..at..']*)(%'..at..'?)') do
                        table.insert(splut, n);

                        if (c == '') then break end
                end
        end
        return splut;
end

function findClass(cName, sName)

        if (AuctionConfig and AuctionConfig.classes) then

                for class, cData in pairs(AuctionConfig.classes) do

                        if (cData.name == cName) then
                                if (sName == nil) then return class, 0; end

                                for sClass, sData in pairs(cData) do
                                        if (sClass ~= "name") and (sData == sName) then
                                                return class, sClass;
                                        end
                                end
                                return class, 0;
                        end
                end
        end
        return 0,0;
end

function getCatName(number)
        if (number == 0) then return "" end;

        if (AuctionConfig.classes[number]) then
                return AuctionConfig.classes[number].name;
        end
        return nil;
end

function getCatNumberByName(name)
        if (not name) then return 0 end
        if (AuctionConfig and AuctionConfig.classes) then

                for cat, class in pairs(AuctionConfig.classes) do
                        if (name == class.name) then
                                return cat;
                        end
                end
        end
        return 0;
end

function getCatForKey(itemKey)
        local info = Auctioneer.Core.GetInfo(itemKey);
        return info.category;
end

function getKeyFromSig(auctSig)
        local id, rprop, enchant = Auctioneer.Core.GetItemSignature(auctSig);
        return id..":"..rprop..":"..enchant;
end

function getCatForSig(auctSig)
        local itemKey = getKeyFromSig(auctSig);
        return getCatForKey(itemKey);
end


function getItemLinks(str)
        if (not (type(str) == "string")) then
                return
        end
        local itemList = {};

        for link, item in string.gfind(str, "|Hitem:([^|]+)|h[[]([^]]+)[]]|h") do
                table.insert(itemList, item.." = "..link)
        end
        return itemList;
end

function getItems(str)
        if (not (type(str) == "string")) then
                return
        end
        local itemList = {};
        local itemKey;

        for itemID, randomProp, enchant, uniqID in string.gfind(str, "|Hitem:(%d+):(%d+):(%d+):(%d+)|h") do
                itemKey = itemID..":"..randomProp..":"..enchant;
                table.insert(itemList, itemKey)
        end
        return itemList;
end

--Many thanks to the guys at irc://irc.datavertex.com/cosmostesters for their help in creating this function
function getItemHyperlinks(str)
        if (not (type(str) == "string")) then
                return
        end
        local itemList = {};

        for color, item, name in string.gfind(str, "|c(%x+)|Hitem:(%d+:%d+:%d+:%d+)|h%[(.-)%]|h|r") do
                table.insert(itemList, "|c"..color.."|Hitem:"..item.."|h["..name.."]|h|r")
        end
        return itemList;
end

function loadCategories()
        if (not AuctionConfig.classes) then AuctionConfig.classes = {} end
        loadCategoryClasses(GetAuctionItemClasses());
end

function loadCategoryClasses(...)
        for c=1, arg.n, 1 do
                AuctionConfig.classes[c] = {};
                AuctionConfig.classes[c].name = arg[c];
                loadCategorySubClasses(c, GetAuctionItemSubClasses(c));
        end
end

function loadCategorySubClasses(c, ...)
        for s=1, arg.n, 1 do
                AuctionConfig.classes[c][s] = arg[s];
        end
end

function chatPrint(text, cRed, cGreen, cBlue, cAlpha, holdTime)
        local frameIndex = Auctioneer.Command.GetFrameIndex();

        if (cRed and cGreen and cBlue) then
                if getglobal("ChatFrame"..frameIndex) then
                        getglobal("ChatFrame"..frameIndex):AddMessage(text, cRed, cGreen, cBlue, cAlpha, holdTime);

                elseif (DEFAULT_CHAT_FRAME) then
                        DEFAULT_CHAT_FRAME:AddMessage(text, cRed, cGreen, cBlue, cAlpha, holdTime);
                end

        else
                if getglobal("ChatFrame"..frameIndex) then
                        getglobal("ChatFrame"..frameIndex):AddMessage(text, 0.0, 1.0, 0.25);

                elseif (DEFAULT_CHAT_FRAME) then
                        DEFAULT_CHAT_FRAME:AddMessage(text, 0.0, 1.0, 0.25);
                end
        end
end

function setFilterDefaults()
        if (not AuctionConfig.filters) then
                AuctionConfig.filters = {};
        end

        for k,v in ipairs(Auctioneer.Core.Constants.FilterDefaults) do
                if (AuctionConfig.filters[k] == nil) then
                        AuctionConfig.filters[k] = v;
                end
        end
end

-- Pass true to protect the Auction Frame from being undesireably closed, not true to disable this
function protectAuctionFrame(enable)
        --Make sure we have an AuctionFrame before doing anything
        if (AuctionFrame) then
                --Handle enabling of protection

                if (enable and not Auctioneer_ProtectionEnabled and AuctionFrame:IsShown()) then
                        --Remember that we are now protecting the frame
                        Auctioneer_ProtectionEnabled = true;
                        --If the frame is the current doublewide frame, then clear the doublewide

                        if ( GetDoublewideFrame() == AuctionFrame ) then
                                SetDoublewideFrame(nil)
                        end
                        --Remove the frame from the UI frame handling system
                        UIPanelWindows["AuctionFrame"] = nil
                        --If mobile frames is around, then remove AuctionFrame from Mobile Frames handling system

                        if (MobileFrames_UIPanelWindowBackup) then
                                MobileFrames_UIPanelWindowBackup.AuctionFrame = nil;
                        end

                        if (MobileFrames_UIPanelsVisible) then
                                MobileFrames_UIPanelsVisible.AuctionFrame = nil;
                        end
                        --Hook the function to show the WorldMap, WorldMap has internal code that forces all these frames to close
                        --so for it, we have to prevent it from showing at all

                        if (not Auctioneer_ToggleWorldMap) then
                                Auctioneer_ToggleWorldMap = ToggleWorldMap;
                        end
                        ToggleWorldMap = function ()

                                if ( ( not Auctioneer_ProtectionEnabled ) or ( not ( AuctionFrame and AuctionFrame:IsVisible() ) ) ) then
                                        Auctioneer_ToggleWorldMap();

                                else
                                        UIErrorsFrame:AddMessage(_AUCT('GuiNoWorldMap'), 0, 1, 0, 1.0, UIERRORS_HOLD_TIME)
                                end
                        end

                elseif (Auctioneer_ProtectionEnabled) then
                        --Handle disabling of protection
                        Auctioneer_ProtectionEnabled = nil;
                        --If Mobile Frames is around, then put the frame back under its control if it is proper to do so

                        if ( MobileFrames_UIPanelWindowBackup and MobileFrames_MasterEnableList and MobileFrames_MasterEnableList["AuctionFrame"] ) then
                                MobileFrames_UIPanelWindowBackup.AuctionFrame = { area = "doublewide", pushable = 0 };

                                if ( MobileFrames_UIPanelsVisible and AuctionFrame:IsVisible() ) then
                                        MobileFrames_UIPanelsVisible.AuctionFrame = 0;
                                end

                        else
                                --Put the frame back into the UI frame handling system
                                UIPanelWindows["AuctionFrame"] = { area = "doublewide", pushable = 0 };

                                if ( AuctionFrame:IsVisible() ) then
                                        SetDoublewideFrame(AuctionFrame)
                                end
                        end
                end
        end
end

function priceForOne(price, count)
        price = nullSafe(price)
        count = math.max(nullSafe(count), 1)
        return math.ceil(price / count)
end

function round(x)
        local y = math.floor(x);

        if (x - y >= 0.5) then
                return y + 1;
        end
        return y;
end

-------------------------------------------------------------------------------
-- Localization functions
-------------------------------------------------------------------------------

Auctioneer.Command.CommandMap = nil;
Auctioneer.Command.CommandMapRev = nil;

function delocalizeFilterVal(value)
        if (value == _AUCT('CmdOn')) then
                return 'on';

        elseif (value == _AUCT('CmdOff')) then
                return 'off';

        elseif (value == _AUCT('CmdDefault')) then
                return 'default';

        elseif (value == _AUCT('CmdToggle')) then
                return 'toggle';

        else
                return value;
        end
end

function localizeFilterVal(value)
        local result

        if (value == 'on') then
                result = _AUCT('CmdOn');

        elseif (value == 'off') then
                result = _AUCT('CmdOff');

        elseif (value == 'default') then
                result = _AUCT('CmdDefault');

        elseif (value == 'toggle') then
                result = _AUCT('CmdToggle');
        end

        if (result) then return result; else return value; end
end

function getLocalizedFilterVal(key)
        return localizeFilterVal(Auctioneer.Command.GetFilterVal(key))
end

-- Turns a localized slash command into the generic English version of the command
function delocalizeCommand(cmd)
        if (not Auctioneer.Command.CommandMap) then Auctioneer.Command.BuildCommandMap();end
        local result = Auctioneer.Command.CommandMap[cmd];

        if (result) then return result; else return cmd; end
end

-- Translate a generic English slash command to the localized version, if available
function localizeCommand(cmd)
        if (not Auctioneer.Command.CommandMapRev) then Auctioneer.Command.BuildCommandMap(); end
        local result = Auctioneer.Command.CommandMapRev[cmd];

        if (result) then return result; else return cmd; end
end

-------------------------------------------------------------------------------
-- Inventory modifying functions
-------------------------------------------------------------------------------

function findEmptySlot()
        local name, i
        for bag = 0, 4 do
                name = GetBagName(bag)
                i = string.find(name, '(Quiver|Ammo|Bandolier)')
                if not i then
                        for slot = 1, GetContainerNumSlots(bag),1 do
                                if not (GetContainerItemInfo(bag,slot)) then
                                        return bag, slot;
                                end
                        end
                end
        end
end


function containerFrameItemButtonOnClick(hookParams, returnValue, button, ignoreShift) --Auctioneer_ContainerFrameItemButton_OnClick
        local bag = this:GetParent():GetID()
        local slot = this:GetID()

        local texture, count, noSplit = GetContainerItemInfo(bag, slot)
        local link = GetContainerItemLink(bag, slot)
        if (count and count > 1 and not noSplit) then
                if (button == "RightButton") and (IsControlKeyDown()) then
                        local splitCount = math.floor(count / 2)
                        local emptyBag, emptySlot = findEmptySlot()
                        if (emptyBag) then
                                SplitContainerItem(bag, slot, splitCount)
                                PickupContainerItem(emptyBag, emptySlot)
                        else
                                chatPrint("Can't split, all bags are full")
                        end
                        return "abort";
                end
        end

        if (AuctionFrame and AuctionFrame:IsVisible()) then
                if (link) then
                        if (button == "RightButton") and (IsAltKeyDown()) then
                                AuctionFrameTab_OnClick(1)
                                local itemID = EnhTooltip.BreakLink(link)
                                if (itemID) then
                                        local itemName = GetItemInfo(tostring(itemID))
                                        if (itemName) then
                                                BrowseName:SetText(itemName)
                                                BrowseMinLevel:SetText("")
                                                BrowseMaxLevel:SetText("")
                                                AuctionFrameBrowse.selectedInvtype = nil
                                                AuctionFrameBrowse.selectedInvtypeIndex = nil
                                                AuctionFrameBrowse.selectedClass = nil
                                                AuctionFrameBrowse.selectedClassIndex = nil
                                                AuctionFrameBrowse.selectedSubclass = nil
                                                AuctionFrameBrowse.selectedSubclassIndex = nil
                                                AuctionFrameFilters_Update()
                                                IsUsableCheckButton:SetChecked(0)
                                                UIDropDownMenu_SetSelectedValue(BrowseDropDown, -1)
                                                AuctionFrameBrowse_Search()
                                                BrowseNoResultsText:SetText(BROWSE_NO_RESULTS)
                                        end
                                end
                                return "abort";
                        end
                end
        end

        if (not CursorHasItem() and AuctionFrameAuctions and AuctionFrameAuctions:IsVisible() and IsAltKeyDown()) then
                PickupContainerItem(bag, slot)
                if (CursorHasItem() and Auctioneer.Command.GetFilter('auction-click')) then
                        ClickAuctionSellItemButton()
                        AuctionsFrameAuctions_ValidateAuction()
                        local start = MoneyInputFrame_GetCopper(StartPrice)
                        local buy = MoneyInputFrame_GetCopper(BuyoutPrice)
                        local duration = AuctionFrameAuctions.duration
                        local warn = AuctionInfoWarnText:GetText()
                        if (AuctionsCreateAuctionButton:IsEnabled() and IsShiftKeyDown()) then
                                local cHex, cRed, cGreen, cBlue = getWarnColor(warn)
                                warn = ("|c"..cHex..warn.."|r")
                                StartAuction(start, buy, duration);
                                chatPrint(string.format(_AUCT('FrmtAutostart'), link, EnhTooltip.GetTextGSC(start), EnhTooltip.GetTextGSC(buy), duration/60, warn));
                        end
                        return "abort";
                end
        end

        if (not CursorHasItem() and AuctionFramePost and AuctionFramePost:IsVisible() and button == "LeftButton" and IsAltKeyDown()) then
                local _, count = GetContainerItemInfo(bag, slot);
                if (count) then
                        if (count > 1 and IsShiftKeyDown()) then
                                this.SplitStack = function(button, split)
                                        local _, _, _, _, name = EnhTooltip.BreakLink(link);
                                        AuctionFramePost:SetAuctionItem(bag, slot, split);
                                end
                                OpenStackSplitFrame(count, this, "BOTTOMRIGHT", "TOPRIGHT");
                        else
                                local _, _, _, _, name = EnhTooltip.BreakLink(link);
                                AuctionFramePost:SetAuctionItem(bag, slot, 1);
                        end
                        return "abort";
                end
        end
end

Auctioneer.Util = {
        GetTimeLeftString = getTimeLeftString,
        GetSecondsLeftString = getSecondsLeftString,
        UnpackSeconds = unpackSeconds,
        GetGSC = getGSC,
        GetTextGSC = getTextGSC,
        NilSafeString = nilSafeString,
        ColorTextWhite = colorTextWhite,
        GetWarnColor = getWarnColor,
        NullSafe = nullSafe,
        SanifyAHSnapshot = sanifyAHSnapshot,
        GetAuctionKey = getAuctionKey,
        GetOppositeKey = getOppositeKey,
        GetNeutralKey = getNeutralKey,
        GetHomeKey = getHomeKey,
        IsValidAlso = isValidAlso,
        BreakItemKey = breakItemKey,
        Split = split,
        FindClass = findClass,
        GetCatName = getCatName,
        GetCatNumberByName = getCatNumberByName,
        GetCatForKey = getCatForKey,
        GetKeyFromSig = getKeyFromSig,
        GetCatForSig = getCatForSig,
        GetItemLinks = getItemLinks,
        GetItems = getItems,
        GetItemHyperlinks = getItemHyperlinks,
        LoadCategories = loadCategories,
        LoadCategoryClasses = loadCategoryClasses,
        LoadCategorySubClasses = loadCategorySubClasses,
        ChatPrint = chatPrint,
        SetFilterDefaults = setFilterDefaults,
        ProtectAuctionFrame = protectAuctionFrame,
        PriceForOne = priceForOne,
        Round = round,
        DelocalizeFilterVal = delocalizeFilterVal,
        LocalizeFilterVal = localizeFilterVal,
        GetLocalizedFilterVal = getLocalizedFilterVal,
        DelocalizeCommand = delocalizeCommand,
        LocalizeCommand = localizeCommand,
        FindEmptySlot = findEmptySlot,
        ContainerFrameItemButtonOnClick = containerFrameItemButtonOnClick,
}