vanilla-wow-addons – Rev 1

Subversion Repositories:
Rev:
--[[--------------------------------------------------------------------------------
  ItemSync Framework

  Author:  Derkyle
  Website: http://www.manaflux.com
-----------------------------------------------------------------------------------]]

ISYNC_VERSION = 12.4; --version

--EMBED
ISync =  {};

--REALM_NUM
ISYNC_REALM_NUM = 0;

--GLOBALS
ISYNC_LOADYES = 0;
ISYNC_VARLOAD = 0;
ISYNC_LOADONCE  = 0;
ISYNC_DB_MAX = 12;


--HOOKS
local ISync_HookedMoney;
local ISync_HookedOnShow;

local ISChatRepChk = "";
local SetDB_RepeatChk = "";
local ItemSync_MouseArray = { };


---------------------------------------------------
-- ISync:PrimaryLoad()
---------------------------------------------------
function ISync:PrimaryLoad()

        --display loaded
        if( DEFAULT_CHAT_FRAME ) then
                DEFAULT_CHAT_FRAME:AddMessage("|c00A2D96FDerkyle's ItemSync Ver. ["..ISYNC_VERSION.."]|r  |cffffffffType: /itemsync  /isync  /ims  /is");
        end

        -- Register our slash command
        ---------------------------------------------------
        SLASH_ITEMSYNC1 = "/itemsync";
        SLASH_ITEMSYNC2 = "/isync";
        SLASH_ITEMSYNC3 = "/ims";
        SLASH_ITEMSYNC4 = "/is";
        SlashCmdList["ITEMSYNC"] = ISync_SlashCommand;

        
        --this is for AxuItemMenus :) Thanks Axu!
        if (AxuItemMenus_AddConfigToggle) then

                AxuItemMenus_AddConfigToggle({
                id = "isync", -- this appears in my previous snippet
                default = true, -- feature enabled by default
                -- consider localizing the following:
                text = "ItemSync",
                helptext = "Enable pop-up menus in ItemSync"
                });
        end
        
        tinsert(UISpecialFrames, "ISync_MainFrame");
        
end


---------------------------------------------------
-- ISync:OnPrimaryEvent()
---------------------------------------------------
function ISync:OnPrimaryEvent(event,arg1,arg2,arg3,arg4,arg5)


        if( event == "VARIABLES_LOADED" ) then
        
                --enable primary data structure
                if( not ISyncDB ) then ISyncDB = { }; end
                if( not ISyncDB_Names ) then ISyncDB_Names = { }; end
                
                --check favorites
                if( not ISyncFav ) then ISyncFav = { }; end
                if( not ISyncFav[UnitName("player")] ) then ISyncFav[UnitName("player")] = { }; end
                
                        --check for old version, if we are starting fresh add it as current
                        if(ISyncOpt and ISyncOpt.Version) then
                                ISync:SetVar({"ISYNC_VER","OLDVERSION"}, ISyncOpt.Version);
                                ISyncOpt = nil;
                                ISyncOpt = { }; --delete it so we can recreate
                                
--                              ISync_DBPopUp:Show();
                                
                        elseif(not ISync:SetVar({"ISYNC_VER","OLDVERSION"}, ISYNC_VERSION, "CHK")) then
                                ISync:SetVar({"ISYNC_VER","OLDVERSION"}, ISYNC_VERSION);
                                
--                              ISync_DBPopUp:Show();
                        end
                        
                --reset
                GameTooltip.isDisplayDone = nil;
                GameTooltip.SendtoMods = nil;
                
                --options check and set
                ISync:SetVar({"OPT","PRICE"}, 1);
                ISync:SetVar({"OPT","VENDOR"}, 1);
                ISync:SetVar({"OPT","MONEYSET"}, 1);
                ISync:SetVar({"OPT","ITEMCOUNTDISPLAY"}, 0);
                ISync:SetVar({"OPT","RARITY_DD"}, "name");
                ISync:SetVar({"OPT","SHOWMONEYICONS"}, 0);
                ISync:SetVar({"OPT","ITEMCOUNT_VALID"}, 0);
                ISync:SetVar({"OPT","ITEMCOUNT_INVALID"}, 0);
                ISync:SetVar({"OPT","MINIMAP_SHOW"}, 0);
                ISync:SetVar({"OPT","MINIMAP_LOC"}, 305);
                ISync:SetVar({"OPT","TOOLTIPITEMICONS"}, 1);
                ISync:SetVar({"OPT","LINKFETCH"}, 0);
                ISync:SetVar({"OPT","MOUSEOVERINSPECT"}, 1);
                --layout
                ISync:SetVar({"LAYOUT","GOLD"}, "|c00FFFFFF%s|r|c00E2CD54"..ISYNC_OPTGOLD1.."|r ");
                ISync:SetVar({"LAYOUT","SILVER"}, "|c00FFFFFF%s|r|c00AEAEAE"..ISYNC_OPTSILVER1.."|r ");
                ISync:SetVar({"LAYOUT","COPPER"}, "|c00FFFFFF%s|r|c00D7844D"..ISYNC_OPTCOPPER1.."|r");
                --alerts
                ISync:SetVar({"ALERT","QUALITY"}, 0);
                ISync:SetVar({"ALERT","INVALID"}, 0);
                --mods
                ISync:SetVar({"MOD","AMAS"}, 0);
                ISync:SetVar({"MOD","AUCTIONEER"}, 0);
                ISync:SetVar({"MOD","REAGENTINFO"}, 0);
                --filters
                ISync:SetVar({"FILTERS",0}, 1);
                ISync:SetVar({"FILTERS",1}, 1);
                ISync:SetVar({"FILTERS",2}, 1);
                ISync:SetVar({"FILTERS",3}, 1);
                ISync:SetVar({"FILTERS",4}, 1);
                ISync:SetVar({"FILTERS",5}, 1);
                --bagview
                ISync:SetVar({"BAGVIEW","SHOWSTACKED"}, 1);
                ISync:SetVar({"BAGVIEW","SHOWNIL"}, 0);
                ISync:SetVar({"BAGVIEW","SORT_VALUE"}, 1);
                ISync:SetVar({"BAGVIEW","SORT_RARITY"}, 0);
                --required refresh for new items
                ISync:SetVar({"REQUIRED","REFRESH"}, 0);
                

                --check for data
                if (not ISync:GrabDataProfile() ) then
                        ISYNC_LOADYES = 0;
                        DEFAULT_CHAT_FRAME:AddMessage("|c00A2D96FItemSync:|r |cffffffffNo profile could be generated.  ItemSync has been halted.|r");
                else
                        ISYNC_LOADYES = 1;
                        ISYNC_REALM_NUM = ISync:GrabDataProfile();
                end--if (not ISync:GrabDataProfile() ) then
                
                
                ISync:Fav_DD_Load();
                ISync:MiniMapButton_Init();
                
                        

        elseif( event == "PLAYER_TARGET_CHANGED" ) then

                --check first
                if(ISYNC_LOADYES == 1) then
                        if(not UnitIsUnit("target", "player") and UnitIsPlayer("target") ) then 
                                ISync:InspectTarget("target"); 
                        end
                end
                
        --mouseover
        elseif( event == "UPDATE_MOUSEOVER_UNIT" ) then

                --check first
                if(ISYNC_LOADYES == 1) then
                        --check to see if the user allowed it
                        if(ISync:SetVar({"OPT","MOUSEOVERINSPECT"}, 1, "COMPARE")) then
                                if(not UnitIsUnit("mouseover", "player") and UnitIsPlayer("mouseover") ) then 
                                        ISync:InspectTarget("mouseover"); 
                                end
                        end
                end
                
        --the inventory has been updated so lets check it again
        elseif( event == "UNIT_INVENTORY_CHANGED" ) then

                if(ISYNC_LOADYES == 1 and arg1 == "player" ) then  ISync_CoreFrame.unitinvchanged = .2; end
                
        --bank frame opened so lets scan that too
        elseif( event == "BANKFRAME_OPENED" ) then

                if(ISYNC_LOADYES == 1) then ISync:ScanBank(); end
                
        --scan auction window
        elseif( event == "AUCTION_ITEM_LIST_UPDATE" ) then

                if(ISYNC_LOADYES == 1) then ISync:ScanAuction(); end

        --scan merchant window
        elseif( event == "MERCHANT_SHOW" ) then
                
                if(ISYNC_LOADYES == 1) then ISync:MerchantMoneyScan(this); end
                if(ISYNC_LOADYES == 1) then ISync:VendorScan(); end
                if(ISYNC_LOADYES == 1) then ISync:BV_Refresh(); end
                
        --scan tooltip money
        elseif( event == "BAG_UPDATE" ) then
        
                if(ISYNC_LOADYES == 1) then ISync_CoreFrame.bagupdate = .2; end
                
        elseif ( event == "PLAYER_ENTERING_WORLD" ) then
        
                if(ISYNC_LOADYES == 1 and ISYNC_LOADONCE == 0) then
                
                
                        ---VERSION CHECKS
                        ----------------------------------------------------------
                
                        ISync:SetVar({"ISYNC_VER","VERSION"}, ISYNC_VERSION); --create if it doesn't exist

                        --check update
                        if(tonumber(ISync:SetVar({"ISYNC_VER","VERSION"}, ISYNC_VERSION)) < ISYNC_VERSION) then

                                ISync:CleanupDB(nil, nil); --force it

                                ISync:SetVar({"ISYNC_VER","VERSION"}, ISYNC_VERSION, "TRUE");

                        end
                        ----------------------------------------------------------
                        
                
                        ISync:InspectTarget("player");
                        ISync:ScanInv();
                        ISync:ItemDisplay_Update();
                        ISYNC_LOADONCE = 1;
                        
                end

        --rest
        else
                
                --send to parse, it's chat information to be parsed
                --since sometimes chat informations loves to send doubles lets check for that
                if(ISYNC_LOADYES == 1 and arg1) then
                
                        --check for repeats
                        if(ISChatRepChk ~= event..arg1) then
                                ISChatRepChk =  event..arg1;
                                ISync:ProcessLinks(arg1, "CHAT", nil, nil);
                        end
                        
                end

        end--end event checks


end



---------------------------------------------------
-- ISync:OnUpdateTriggered()
---------------------------------------------------
function ISync:OnUpdateTriggered(elapsed)

        --BAG_UPDATE
        if(ISync_CoreFrame.bagupdate) then
        
                --update the laspe
                ISync_CoreFrame.bagupdate = ISync_CoreFrame.bagupdate - elapsed;
                
                --check if the timer ran out
                if ( ISync_CoreFrame.bagupdate <= 0 ) then
                        
                        ISync:BV_Refresh();
                        ISync_CoreFrame.bagupdate = nil;

                end

        end
        
        
        --UNIT_INVENTORY_CHANGED
        if(ISync_CoreFrame.unitinvchanged) then
        
                --update the laspe
                ISync_CoreFrame.unitinvchanged = ISync_CoreFrame.unitinvchanged - elapsed;
                
                --check if the timer ran out
                if ( ISync_CoreFrame.unitinvchanged <= 0 ) then
                        
                        --inspect user and inventory
                        ISync:InspectTarget("player");
                        ISync:ScanInv();
                        ISync:BV_Refresh();
                        ISync_CoreFrame.unitinvchanged = nil;
                        
                end

        end

end



-----------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------


---------------------------------------------------
-- ISync:ProcessLinks()
---------------------------------------------------
function ISync:ProcessLinks(sText, sEvent, sVendorPrice, sVendorQty)
        
        if(ISYNC_LOADYES == 0) then return nil; end --don't run if the profile didn't load
        if(not sText) then return nil; end --no data no parsing
        if(not ISyncDB) then return nil; end --the database should have been created
        if(not ISyncDB[ISYNC_REALM_NUM]) then return nil; end --don't even bother

        --locals
        local item, name, color, sPL, xPL1, xPL2;

        --do the loop
        for color, item, name in string.gfind(sText, "|c(%x+)|Hitem:(%d+:%d+:%d+:%d+)|h%[(.-)%]|h|r") do
                        
                --make sure we have data to process
                if( color and item and name ) then
                
                        sPL  = string.gsub(item, "^(%d+):(%d+):(%d+):(%d+)$", "%1:0:%3:0");
                        xPL1 = string.gsub(item, "^(%d+):(%d+):(%d+):(%d+)$", "%1");
                        xPL2 = string.gsub(item, "^(%d+):(%d+):(%d+):(%d+)$", "%3");
                        
                        if(not sPL or not xPL1 or not xPL2) then return nil; end --don't bother
                        
                        xPL1 = tonumber(xPL1);
                        xPL2 = tonumber(xPL2);
                        
                        --sometimes in chat the information isnt grabbed because not been clicked on
                        --but we can get around this by setting it to the tooltip
                        -----------------------------------------------------------------------
                        if(sEvent and sEvent == "CHAT") then

                                local name_X, link_X, quality_X, minLevel_X, class_X, subclass_X, maxStack_X, equipType_X, iconTexture_X  = GetItemInfo("item:"..sPL);
                                
                                if(not name_X) then
                                        ISync_MainFrame.TooltipButton = this:GetID();
                                        GameTooltip:SetOwner(this, "ANCHOR_RIGHT");
                                        GameTooltip:SetHyperlink("item:"..sPL);
                                        GameTooltip:Hide();
                                end
                                
                        end
                        -----------------------------------------------------------------------
                        
                        --grab the info
                        local name_X, link_X, quality_X, minLevel_X, class_X, subclass_X, maxStack_X, equipType_X, iconTexture_X  = GetItemInfo("item:"..sPL);
                        
                        
                        --check
                        if(name_X and link_X and quality_X and ISync:SetVar({"FILTERS",quality_X}, 1, "COMPARE")) then
                                
                                
                                --if we don't have it then add it
                                if(not ISync:FetchDB(xPL1, "chk")) then
                                        
                                        
                                        --check for SPOOFS
                                        if(not ISync:CheckSpoof(item, equipType_X, quality_X)) then return nil; end

                                        --add the item
                                        ISync:SetDB(xPL1, "subitem", xPL2);
                                        ISync:SetDB(xPL1, "quality", quality_X);

                                        --parse it
                                        ISync:Do_Parse(UIParent, ISyncTooltip, xPL1, link_X);
                                
                                --check if we have it as a subitem, if not add it
                                elseif(xPL2 ~= 0 and not ISync:FetchDB(xPL1, "subitem", xPL2)) then
                                
                                        ISync:SetDB(xPL1, "subitem", xPL2);
        
                                end--if(not ISync:FetchDB(name_X, "item")) then
                                
                                
                                -------------------------------------------------
                                --VENDOR INFORMATION
                                if(sVendorPrice or sVendorQty) then

                                        --check vendor stuff
                                        if(sVendorPrice) then
                                                ISync:SetDB(xPL1, "vendor", sVendorPrice);
                                        end
                                        if(sVendorQty) then
                                                ISync:SetDB(xPL1, "vendorqty", sVendorQty);
                                        end

                                end
                                -------------------------------------------------
                                
                                
                        end--if(name_X) then
                        
                end--if( color and item and name ) then
                
        end--for color, item, name 

end


---------------------------------------------------
-- ISync:CheckSpoof()
-- This code is inspired by Brodrick
---------------------------------------------------
--sLink cannot have itemid: in the front
function ISync:CheckSpoof(sLink, sEquipT, sQuality)

        --check
        if(not sLink or not sEquipT or not sQuality) then return nil; end
        
        --folks were starting to use empty values to create spoofs.
        if(sLink == "0:0:0:0") then return nil; end
        

        --grab the item information based on it's string id
        local _, _, sItemID, sEnchant, sItemStat, sSetBonus = string.find( sLink, "(%d+):(%d+):(%d+):(%d+)" );

        
        --make sure
        if(not sEnchant or not sItemID or not sItemStat) then return nil; end
        
        
        --grab array of items that can't have items stats
        local ChkItem = {
                [""] = 2,
                ["INVTYPE_TRINKET"] = 2,
                ["INVTYPE_AMMO"] = 2,
                ["INVTYPE_THROWN"] = 2,
                ["INVTYPE_BAG"] = 2,
                ["INVTYPE_TABARD"] = 2,
                ["INVTYPE_BODY"] = 2, --INVTYPE_BODY is not INVTYPE_CHEST or INVTYPE_ROBE
                ["INVTYPE_HOLDABLE"] = 1,
                ["INVTYPE_FINGER"] = 1,
                ["INVTYPE_WAIST"] = 1,
        }


        --first check the stats
        if ( sItemStat and tonumber(sItemStat) > 0 ) then

                --check quality, greens, blues and one epic are allowed to have 'of the' only
                if ( sQuality ~= 2 and sQuality ~= 3 and sItemID ~= "20039" ) then
                        --20039: is dark iron boots which is an exception

                        --error this item is invalid return nil
                        return nil;

                --only certain items can have bonues 'of the'
                elseif( ChkItem[sEquipT] == 2 ) then

                        --error this item is invalid return nil
                        return nil;
                end


        end


        --check for enchants
        if ( sEnchant and tonumber(sEnchant) > 0 ) then

                --only armor and weapons can have enchants
                if ( ChkItem[sEquipT] ) then

                        return nil;

                end
        end


        --everything checks out so return true
        return 1;       
        
        
end


-----------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------

---------------------------------------------------
-- ISync:InspectTarget()
---------------------------------------------------
function ISync:InspectTarget(sTarget)
        
        if(sTarget == "mouseover") then
                --we don't want to check the user over and over and over again
                
                local sName = UnitName(sTarget); --get their name
                local sGetTime = GetTime(); --get current time
                local sLastScan = ItemSync_MouseArray[sName]; --get last time scanned if any
                
                if ( sLastScan and sGetTime - sLastScan < 120 ) then --check if we have scanned them anytime soon
                        return nil; --we did so return nil
                end
                
                --initiate if not there
                ItemSync_MouseArray.iCount = (ItemSync_MouseArray.iCount or 0);
                if(ItemSync_MouseArray.iCount and ItemSync_MouseArray.iCount < 0) then ItemSync_MouseArray.iCount = 0; end
                
                
                --we didn't so lets add them to the array
                --first fix the array if we have exceeded our limit
                if( ItemSync_MouseArray.iCount > 100 ) then
                        
                        --clean array
                        for xKey, xVar in ItemSync_MouseArray do
                                
                                if(xKey ~= "iCount") then
                                
                                        if(xVar and (GetTime() - xVar) > 120) then --time expired so lets remove
                                                ItemSync_MouseArray[xKey] = nil;
                                                ItemSync_MouseArray.iCount = ItemSync_MouseArray.iCount - 1; --decrease
                                        end
                                
                                end
                        end

                end
                
                --if for some reason it's still bigger then limit, then reset it.  We don't want a memory leak.
                if(ItemSync_MouseArray.iCount > 100) then
                        ItemSync_MouseArray = nil;
                        ItemSync_MouseArray = { };
                end
                
                ItemSync_MouseArray[sName] = GetTime();
                ItemSync_MouseArray.iCount = (ItemSync_MouseArray.iCount or 0) + 1;
        
        end--if(sTarget == "mouseover") then


        for i = 1, 19, 1 do
                local link = GetInventoryItemLink(sTarget, i);
                if( link ) then
                        ISync:ProcessLinks(link, nil, nil, nil)
                end
        end--for i = 1, 19, 1 do
        
end



---------------------------------------------------
-- ISync:ScanInv()
---------------------------------------------------
function ISync:ScanInv()

        local bagid, size, slotid, link;
        
        for bagid=0,NUM_BAG_FRAMES,1 do
        
                size = GetContainerNumSlots(bagid);
                
                if( size ) then
                        for slotid = size, 1, -1 do
                                link = GetContainerItemLink(bagid, slotid);
                                if( link ) then ISync:ProcessLinks(link, nil, nil, nil); end
                        end
                end
        end
        
end


---------------------------------------------------
-- ISync:ScanBank()
---------------------------------------------------
function ISync:ScanBank()

        local bagid, size, slotid, link;
        
        --Bank Container
        size = GetContainerNumSlots(BANK_CONTAINER);
        for slotid = size, 1, -1 do
                link = GetContainerItemLink(BANK_CONTAINER, slotid);
                if( link ) then ISync:ProcessLinks(link, nil, nil, nil); end
        end
        
        --Bank Bag Containers
        for bagid= NUM_BAG_SLOTS + 1, (NUM_BAG_SLOTS + NUM_BANKBAGSLOTS), 1 do
        
                size = GetContainerNumSlots(bagid);
                if( size ) then
                        for slotid = size, 1, -1 do
                                link = GetContainerItemLink(bagid, slotid);
                                if( link ) then ISync:ProcessLinks(link, nil, nil, nil); end
                        end
                end
        end
        
end


---------------------------------------------------
-- ISync:ScanAuction()
---------------------------------------------------
function ISync:ScanAuction()
        local numBatchAuctions, totalAuctions = GetNumAuctionItems("list");
        local auctionid;
        local link;

        if( numBatchAuctions > 0 ) then
                for auctionid = 1, numBatchAuctions do
                        link = GetAuctionItemLink("list", auctionid);
                        if( link ) then ISync:ProcessLinks(link, nil, nil, nil); end
                end
        end
        
end




---------------------------------------------------
-- ISync:VendorScan()
---------------------------------------------------
function ISync:VendorScan()

        --only do if merchant window is opened
        if(not MerchantFrame:IsVisible()) then return nil; end
        
        local numMerchantItems = GetMerchantNumItems();
        local name, texture, price, quantity, numAvailable, isUsable;
        
        for i=1, MERCHANT_ITEMS_PER_PAGE, 1 do
                local index = (((MerchantFrame.page - 1) * MERCHANT_ITEMS_PER_PAGE) + i);

                if ( index <= numMerchantItems ) then
                        name, texture, price, quantity, numAvailable, isUsable = GetMerchantItemInfo(index);
                
                        --get the link for the item
                        local link = GetMerchantItemLink(index)
                        
                        --if there is a link, quantity, and a price then set it to be stored with
                        --vendor price and information
                        if (link and quantity and price) then
                                
                                ISync:ProcessLinks(link, nil , price, quantity);
                                
                        --for some reason there isn't any so lets just add it anyways
                        elseif (link) then
                        
                                ISync:ProcessLinks(link, nil, nil, nil);
                        end
                
                end--if ( index <= numMerchantItems ) then
                
        end--for i=1, MERCHANT_ITEMS_PER_PAGE, 1 do
        
end





---------------------------------------------------
-- ISync:MerchantMoneyScan()
---------------------------------------------------
function ISync:MerchantMoneyScan(frame)

        local costOfItem;

        GameTooltip:Hide();

        for bag=0,NUM_BAG_FRAMES do
                for slot=1,GetContainerNumSlots(bag) do

                    local link = GetContainerItemLink(bag, slot);

                        if (link and link ~= "") then

                                --get the name of the link
                                local sID = ISync:GetCoreID(link);

                                if(sID) then

                                        --reset
                                        ISYNC_ITEMCOST = 0;
                                        costOfItem = 0;

                                        --we had to change it to gametooltip because that is what is processing the money
                                        GameTooltip:SetBagItem(bag, slot); --set the bag slot to grab tooltip

                                        --hide again
                                        GameTooltip:Hide();

                                        local texture, itemCount, locked, quality, readable = GetContainerItemInfo(bag, slot);
                                        
                                        if( itemCount and itemCount > 0 and tonumber(ISYNC_ITEMCOST)) then --anything divided by 1 is itself
                                                costOfItem = floor(ISYNC_ITEMCOST / itemCount);
                                        end


                                        if(costOfItem and costOfItem ~= 0 and tonumber(costOfItem)) then

                                                ISync:SetDB(sID, "price", costOfItem);

                                        elseif(tonumber(costOfItem) and costOfItem < 1) then

                                                --it equals zero so lets put n for the nosellprice to show
                                                ISync:SetDB(sID, "price", -1);
                                        end

                                end--if(sName) then

                        end--if (link and link ~= "") then

                end--for slot=1,GetContainerNumSlots(bag) do
                
        end--for bag=0,NUM_BAG_FRAMES do
        
end


-----------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------


---------------------------------------------------
-- ISync:FetchDB()
---------------------------------------------------
function ISync:FetchDB(sID, SDelimiter, sCompare)

        if(not sID or not SDelimiter) then return nil; end
        if(not ISyncDB) then return nil; end
        if(not ISyncDB[ISYNC_REALM_NUM]) then return nil; end
        if(not ISyncDB[ISYNC_REALM_NUM][sID]) then return nil; end
        if(ISYNC_LOADYES == 0) then return nil; end
        if(not tonumber(sID)) then return nil; end --only allow numbers to store

        sID = tonumber(sID); --convert to number
        
        if(SDelimiter == "chk") then return 1; end
        
        --set the delimiters
        if(SDelimiter == "quality") then SDelimiter = 1;
        elseif(SDelimiter == "price") then SDelimiter = 2;
        elseif(SDelimiter == "wl") then SDelimiter = 3;
        elseif(SDelimiter == "wt") then SDelimiter = 4;
        elseif(SDelimiter == "ts") then SDelimiter = 5;
        elseif(SDelimiter == "at") then SDelimiter = 6;
        elseif(SDelimiter == "st") then SDelimiter = 7;
        elseif(SDelimiter == "level") then SDelimiter = 8;
        elseif(SDelimiter == "vendor") then SDelimiter = 9;
        elseif(SDelimiter == "vendorqty") then SDelimiter = 10;
        elseif(SDelimiter == "idchk") then SDelimiter = 11;
        elseif(SDelimiter == "subitem") then SDelimiter = 12;
        else return nil; end
        
        local sArray = ISync:SplitData(ISyncDB[ISYNC_REALM_NUM][sID], "°");
        
        --convert to strings
        if(sCompare and type(sCompare) ~= "string") then sCompare = tostring(sCompare); end

        --do loop
        for i = 1, ISYNC_DB_MAX do
        
                --check
                if(i == SDelimiter) then
                
                        --make sure we have something to return and that its
                        --not the subitems array
                        if(sArray and sArray[i] and i ~= 12) then --12 = subitems
                        
                                --we have something now check to see if we want to compare
                                if(sCompare) then
                                        
                                        --check compare
                                        if(sArray[i] == sCompare) then 
                                                return sArray[i];
                                        else
                                                return nil;
                                        end
                                
                                --we don't want to compare so just send regular
                                else
                                        return sArray[i];
                                end
                        
                                --there was an error
                                return nil;
                        
                        --it is the subitems they want
                        elseif(sArray and sArray[i] and i == 12) then --12 = subitems
                        
                                --check if we have an empty
                                if(sArray[i] == "0" or tonumber(sArray[i]) and tonumber(sArray[i]) == 0) then
                                        return nil;
                                end
                                
                                local yArray = ISync:SplitData(sArray[12], "º"); --12 = subitems
                                
                                --check if we are comparing
                                if(sCompare) then
                                
                                        --loop
                                        for sKey, sVar in yArray do
                                                if(sVar == sCompare) then return sVar; end
                                        end
                                        
                                        --there was an error
                                        return nil;
                
                                else
                                        if(not yArray) then return nil; else return yArray; end
                                end
                        
                                --there was an error
                                return nil;
                                
                        --something went wrong
                        else
                                return nil;
                                
                        end--if(sArray and sArray[i] and i ~= 12)
                        

                        break; --break out of for loop
                        
                
                end--if(i == SDelimiter) then

        end--for i = 1, ISYNC_DB_MAX do
        

        --return empty space
        return nil;
end


---------------------------------------------------
-- ISync:SetDB()
---------------------------------------------------
function ISync:SetDB(sID, SDelimiter, sValue, sOpt)

        if(not sID or not SDelimiter or not sValue) then return nil; end
        if(not ISyncDB) then return nil; end
        if(not ISyncDB[ISYNC_REALM_NUM]) then return nil; end
        if(ISYNC_LOADYES == 0) then return nil; end
        if(not tonumber(sID)) then return nil; end --only allow numbers to store

        sID = tonumber(sID); --convert to number
        
        
        --check for repeating to add to db, this causes lag
        ---------------------------------------------
        local sSdx = "";
        
                if(sID) then
                        sSdx = sSdx..tostring(sID);
                end
                if(SDelimiter) then
                        sSdx = sSdx..tostring(SDelimiter);
                end
                if(sValue) then
                        sSdx = sSdx..tostring(sValue);
                end
                if(sOpt) then
                        sSdx = sSdx..tostring(sOpt);
                end     
        
                if(sSdx == SetDB_RepeatChk) then return nil; end
                
                SetDB_RepeatChk = sSdx; --set it
        
        ---------------------------------------------
        
        --check the filter
        if(SDelimiter and SDelimiter == "quality" and tonumber(sValue)) then
                if(not ISync:SetVar({"FILTERS",tonumber(sValue)}, 1, "COMPARE")) then return nil; end
        end
        

        --set the delimiters
        if(SDelimiter == "quality") then SDelimiter = 1;
        elseif(SDelimiter == "price") then SDelimiter = 2;
        elseif(SDelimiter == "wl") then SDelimiter = 3;
        elseif(SDelimiter == "wt") then SDelimiter = 4;
        elseif(SDelimiter == "ts") then SDelimiter = 5;
        elseif(SDelimiter == "at") then SDelimiter = 6;
        elseif(SDelimiter == "st") then SDelimiter = 7;
        elseif(SDelimiter == "level") then SDelimiter = 8;
        elseif(SDelimiter == "vendor") then SDelimiter = 9;
        elseif(SDelimiter == "vendorqty") then SDelimiter = 10;
        elseif(SDelimiter == "idchk") then SDelimiter = 11;
        elseif(SDelimiter == "subitem") then SDelimiter = 12;
        else return nil; end
        
        --since we use a string we must convert numerics to strings as well
        if(type(sValue) == "number") then sValue = tostring(sValue); end
        
        --create if doesn't exist
        if(not ISyncDB[ISYNC_REALM_NUM][sID]) then
                ISyncDB[ISYNC_REALM_NUM][sID] = 0;
                
                --increment
                ISync:SetVar({"OPT","ITEMCOUNT_VALID"},(tonumber(ISync:SetVar({"OPT","ITEMCOUNT_VALID"},0))+1), "TRUE");
                ISync:ItemDisplay_Update();
                --set that we require a refresh if we have a new item
                if(ISync_SortIndex) then ISync:SetVar({"REQUIRED","REFRESH"}, 1, "TRUE"); end

        end
        
        local sArray = ISync:SplitData(ISyncDB[ISYNC_REALM_NUM][sID], "°");
        local finalStr = "";
        local subItemStr;
        
        ----------------------------------------------
        --before we continue lets fix the subitems if we have too
        --basically this is to remove a value from the array ;)
        if(sArray and sArray[12] and SDelimiter == 12 and sOpt and string.upper(sOpt) == "TRUE") then
        
                local yArray = ISync:SplitData(sArray[12], "º");
                
                --loop
                for sKey, sVar in yArray do
                        if(not subItemStr and  sVar ~= sValue) then 
                                subItemStr = sVar;
                        elseif(subItemStr and  sVar ~= sValue) then 
                                subItemStr = subItemStr.."º"..sVar;
                        end
                end
                
                --if nothing then default
                if(not subItemStr) then subItemStr = 0; end
                
                --change the value to store it below and store back into array
                sArray[12] = subItemStr;
                sValue = subItemStr;
                

        elseif(sArray and sArray[12] and SDelimiter == 12 and sOpt and string.upper(sOpt) == "REPLACE") then
        
                --they want to replace the entire subitem string
                sArray[12] = sValue;
                
        --else just add to end
        elseif(sArray and sArray[12] and SDelimiter == 12 and not sOpt) then
                
                
                --check if we have this already in the array
                local yArray = ISync:SplitData(sArray[12], "º");
                
                --loop
                for sKey, sVar in yArray do
                        if(sVar == sValue) then 
                                return nil; --don't do it cause we have this # already
                        end
                end
                

                --save the array for processing
                local sOld = sArray[12];
                
                --check for empty (in case were starting off)
                if(sOld == "0" or tonumber(sOld) and tonumber(sOld) == 0) then
                        sValue = sValue; --update value to be stored below
                        sArray[12] = sValue; --update array
                else
                        sValue = sOld.."º"..sValue; --update value to be stored below
                        sArray[12] = sOld.."º"..sValue; --update array
                end
                
                
                sOld = nil; --reset
                
        end
        ----------------------------------------------
        
        
        --do loop
        for i = 1, ISYNC_DB_MAX do
                
                --do not add the delimiter to the end duh
                if(i ~= ISYNC_DB_MAX) then
                        
                        --if the delimiter matches then replace
                        if(i == SDelimiter) then 
                                finalStr = finalStr..sValue.."°";
                        else
                                --if it doesn't then check for old and add, if not then add zero
                                if(sArray and sArray[i]) then
                                        finalStr = finalStr..sArray[i].."°";
                                else
                                        finalStr = finalStr.."0°";
                                end
                        end
                        
                --it does equal the last
                --don't add a delimiter at end
                else
                
                        --if the delimiter matches then replace
                        if(i == SDelimiter) then 
                                finalStr = finalStr..sValue;
                        else
                                --if it doesn't then check for old and add, if not then add zero
                                if(sArray and sArray[i]) then
                                        finalStr = finalStr..sArray[i];
                                else
                                        finalStr = finalStr.."0";
                                end
                        end
                        
                
                end--if(i ~= ISYNC_DB_MAX) then
                
        
        end--for i = 1, ISYNC_DB_MAX do
        
        
        --store it
        ISyncDB[ISYNC_REALM_NUM][sID] = finalStr;
        
        
        --reset
        sArray = nil;
        if(yArray) then yArray = nil; end
        
        --return value and delimiter num
        return SDelimiter, sValue;
        
end



---------------------------------------------------
-- ISync:SplitData()
---------------------------------------------------
function ISync:SplitData(sData, sDelimiter)

        --first check for data
        if(not sData) then return nil; end
        
        --now check for a delimiter
        if(not sDelimiter) then return nil; end
        
        --make sure the data is a string
        if (type(sData) ~= "string") then return nil; end
        
        
          local list = {}
          local pos = 1
          if strfind("", sDelimiter, 1) then -- this would result in endless loops
          end
          while 1 do
            local first, last = strfind(sData, sDelimiter, pos)
            if first then -- found?

                --do not insert empty values
                if(strsub(sData, pos, first-1) ~= "") then

                        tinsert(list, strsub(sData, pos, first-1))

                end
              pos = last+1
            else

                --do not insert empty values
                if(strsub(sData, pos) ~= "") then

                        tinsert(list, strsub(sData, pos))

                end

              break
            end
          end
          return list
          
end


-----------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------

---------------------------------------------------
-- ISync:SlashCommand
---------------------------------------------------
function ISync_SlashCommand(msg)


        if (msg == nil) then 
        
                if(ISYNC_LOADYES == 1) then
                
                        ISync:MainFrame_Binding();
                end
                
                return nil;
        end
        
        
        local num, offset, command, args = string.find (msg, "^(%w+)%s*(.*)$");
        

        if (command == nil) then 

                if(ISYNC_LOADYES == 1) then
                
                        ISync:MainFrame_Binding();
                end
                
                return nil;

        --the user is preforming a search
        elseif (string.lower(command) == "search" and args ~= nil or args ~= "") then

                
                if(ISync.SF_Reset and ISync_TextEditBox and ISYNC_LOADYES == 1 ) then
                        
                        --reset first
                        ISync:SF_Reset();
                        
                                ISync_TextEditBox:SetText(args);
                                
                                ISYNC_SHOWSEARCH_CHK = 1;
                                
                                --only show if it's hidden
                                if ( not ISync_MainFrame:IsVisible() ) then 
                                        ISync_MainFrame:Show();
                                end
                                
                                ISync:Main_Refresh();
                                

                end
                

        --the user is preforming a search (with just s instead of search)
        elseif (string.lower(command) == "s" and args ~= nil or args ~= "") then

                
                if(ISync.SF_Reset and ISync_TextEditBox and ISYNC_LOADYES == 1 ) then
                        
                        --reset first
                        ISync:SF_Reset();
                        
                                ISync_TextEditBox:SetText(args);
                                
                                ISYNC_SHOWSEARCH_CHK = 1;
                                
                                --only show if it's hidden
                                if ( not ISync_MainFrame:IsVisible() ) then 
                                        ISync_MainFrame:Show();
                                end
                                
                                ISync:Main_Refresh();
                                
                end
                
        --the user is preforming a search
        elseif (string.lower(command) == "itemid") then

                ISync:ItemIDSearch_Binding();
                
        --the user is preforming a search
        elseif (string.lower(command) == "fav" or string.lower(command) == "favorites") then
        
                if(ISYNC_LOADYES == 1) then
                
                        ISync:FavFrame_Binding();
                end
                
                
                
        --the user is reseting the windows
        elseif (string.lower(command) == "resetwindow") then    
                
                getglobal("ISync_MainFrame"):ClearAllPoints(); getglobal("ISync_MainFrame"):SetPoint("CENTER", UIParent, "CENTER", 0, 0);
                getglobal("ISync_BV_Frame"):ClearAllPoints(); getglobal("ISync_BV_Frame"):SetPoint("CENTER", UIParent, "CENTER", 0, 0); 
                getglobal("ISync_ItemIDFrame"):ClearAllPoints(); getglobal("ISync_ItemIDFrame"):SetPoint("CENTER", UIParent, "CENTER", 0, 0);
                getglobal("ISync_ID_Frame"):ClearAllPoints(); getglobal("ISync_ID_Frame"):SetPoint("CENTER", UIParent, "CENTER", 0, 0); 

                getglobal("ISync_FavFrame"):ClearAllPoints(); getglobal("ISync_FavFrame"):SetPoint("CENTER", UIParent, "CENTER", 400, 0);
                getglobal("ISync_OptionsFrame"):ClearAllPoints(); getglobal("ISync_OptionsFrame"):SetPoint("CENTER", UIParent, "CENTER", 400, 0);
                getglobal("ISync_FiltersFrame"):ClearAllPoints(); getglobal("ISync_FiltersFrame"):SetPoint("CENTER", UIParent, "CENTER", 400, 0);
                getglobal("ISync_SearchFrame"):ClearAllPoints(); getglobal("ISync_SearchFrame"):SetPoint("CENTER", UIParent, "CENTER", 400, 0);
                getglobal("ISync_HelpFrame"):ClearAllPoints(); getglobal("ISync_HelpFrame"):SetPoint("CENTER", UIParent, "CENTER", 400, 0);


        --the user is preforming a search
        elseif (string.lower(command) == "help") then
        
                if( DEFAULT_CHAT_FRAME ) then
                        DEFAULT_CHAT_FRAME:AddMessage("|c00FFFF00ItemSync Ver. ["..ISYNC_VERSION.."]|r");
                        DEFAULT_CHAT_FRAME:AddMessage("|c00FFFF00/itemsync, /isync, /ims, /is, /bagview, /bv, /bagv|r");
                        DEFAULT_CHAT_FRAME:AddMessage("|c00FFFF00 |r");
                        DEFAULT_CHAT_FRAME:AddMessage("|c00FFFF00ItemSync "..ISYNC_BT_SEARCH..":   /is search itemname, /is s itemname|r");
                        DEFAULT_CHAT_FRAME:AddMessage("|c00FFFF00ItemSync "..ISYNC_BT_ITEMID..":   /is itemid|r");
                        DEFAULT_CHAT_FRAME:AddMessage("|c00FFFF00ItemSync "..ISYNC_BT_FAVORITES..":   /is fav, /is favorites|r");
                        DEFAULT_CHAT_FRAME:AddMessage("|c00FFFF00ItemSync "..ISYNC_SLASHRESETWINDOWS..":   /is resetwindow|r");
                end
            
                
        else
        
                if(ISYNC_LOADYES == 1) then
                
                        ISync:MainFrame_Binding();
                end
                
        end
        

end


-----------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------

--MODDERS NEED TO UPDATE!  THESE FUNCTIONS WILL BE REMOVED IN FUTURE UPDATES OF ITEMSYNC!


--hookback functions (THESE ARE OLD AND SHOULD BE REMOVED BY MODDERS)
--ISync:SetData()
function ISync:SetData(sID, SDelimiter, sValue, sOpt)

        --users the numbered system
        if(tonumber(sID)) then
                
                return ISync:SetDB(sID, SDelimiter, sValue, sOpt);
                
        --uses old names
        else
                for index, value in ISyncDB_Names do

                        if(string.lower(sID) == string.lower(sID)) then

                                return ISync:SetDB(sID, SDelimiter, sValue, sOpt);
                                
                        end--if(string.lower(value) == string.lower(text)) then

                end
                
                
        end
        
        return nil;
end
--ISync:GetData()
function ISync:GetData(sID, SDelimiter, sOpt)


        --users the numbered system
        if(tonumber(sID)) then
                
                 return ISync:FetchDB(sID, SDelimiter, sOpt);
                
        --uses old names
        else
                for index, value in ISyncDB_Names do

                        if(string.lower(sID) == string.lower(sID)) then

                                return ISync:FetchDB(sID, SDelimiter, sOpt);
                                
                        end--if(string.lower(value) == string.lower(text)) then

                end
                
                
        end
        
        return nil;
        
end