-- Enchanting reagents local VOID = 22450 local NEXUS = 20725 local LPRISMATIC = 22449 local LBRILLIANT = 14344 local LRADIANT = 11178 local LGLOWING = 11139 local LGLIMMERING = 11084 local SPRISMATIC = 22448 local SBRILLIANT = 14343 local SRADIANT = 11177 local SGLOWING = 11138 local SGLIMMERING = 10978 local GPLANAR = 22446 local GETERNAL = 16203 local GNETHER = 11175 local GMYSTIC = 11135 local GASTRAL = 11082 local GMAGIC = 10939 local LPLANAR = 22447 local LETERNAL = 16202 local LNETHER = 11174 local LMYSTIC = 11134 local LASTRAL = 10998 local LMAGIC = 10938 local ARCANE = 22445 local ILLUSION = 16204 local DREAM = 11176 local VISION = 11137 local SOUL = 11083 local STRANGE = 10940 -- These are market norm prices. -- Median prices from Allakhazam.com, Mar 15, 2007 local baselinePrices = { [20725] = 75000, -- Nexus Crystal [14344] = 110000, -- Large Brilliant Shard [11178] = 87710, -- Large Radiant Shard [11139] = 26125, -- Large Glowing Shard [11084] = 10000, -- Large Glimmering Shard [14343] = 22500, -- Small Brilliant Shard [11177] = 70000, -- Small Radiant Shard [11138] = 5349, -- Small Glowing Shard [10978] = 3500, -- Small Glimmering Shard [16203] = 115000, -- Greater Eternal Essence [11175] = 60000, -- Greater Nether Essence [11135] = 10000, -- Greater Mystic Essence [11082] = 9285, -- Greater Astral Essence [10939] = 5998, -- Greater Magic Essence [16202] = 43500, -- Lesser Eternal Essence [11174] = 23333, -- Lesser Nether Essence [11134] = 5000, -- Lesser Mystic Essence [10998] = 4066, -- Lesser Astral Essence [10938] = 3000, -- Lesser Magic Essence [16204] = 21000, -- Illusion Dust [11176] = 8750, -- Dream Dust [11137] = 5500, -- Vision Dust [11083] = 3453, -- Soul Dust [10940] = 1275, -- Strange Dust [22445] = 20000, -- Arcane Dust [22447] = 22325, -- Lesser Planar Essence [22446] = 68000, -- Greater Planar Essence [22448] = 64600, -- Small Prismatic Shard [22449] = 190000, -- Large Prismatic Shard [22450] = 997500, -- Void Crystal } -- A price adjustment to favour/disfavour particular reagents -- depending on the market. local priceAdjustment = { [VOID] = 1, [NEXUS] = 1, [LPRISMATIC] = 1, [LBRILLIANT] = 1, [LRADIANT] = 1, [LGLOWING] = 1, [LGLIMMERING] = 1, [SPRISMATIC] = 1, [SBRILLIANT] = 1, [SRADIANT] = 1, [SGLOWING] = 1, [SGLIMMERING] = 1, [GPLANAR] = 1, [GETERNAL] = 1, [GNETHER] = 1, [GMYSTIC] = 1, [GASTRAL] = 1, [GMAGIC] = 1, [LPLANAR] = 1, [LETERNAL] = 1, [LNETHER] = 1, [LMYSTIC] = 1, [LASTRAL] = 1, [LMAGIC] = 1, [ARCANE] = 1, [ILLUSION] = 1, [DREAM] = 1, [VISION] = 1, [SOUL] = 0.9, [STRANGE] = 1, } -- item types local WEAPON = 0 local ARMOR = 1 -- item qualities local UNCOMMON = 2 local RARE = 3 local EPIC = 4 -- convert an item type string to an integer type local typeStringToType = { ["Weapon"] = WEAPON, ["Armor"] = ARMOR, } -- disenchanting level bracket upper bounds, e.g. an ilevel 52 item -- goes into bracket 55 local levelUpperBounds = { 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 85, 99, 120 } -- bad items that look like they should be disenchantable but aren't local badItem = { [11287] = {}, -- Lesser Magic Wand [11288] = {}, -- Greater Magic Wand [11289] = {}, -- Lesser Mystic Wand [11290] = {}, -- Greater Mystic Wand [20406] = {}, -- Twilight Cultist Mantle [20407] = {}, -- Twilight Cultist Robe [20408] = {}, -- Twilight Cultist Cowl } -- the big disenchant table, indexed by [quality][type][level bracket] -- and yielding { { reagent type, drop probability, average drop quantity }, ... } -- I would use Enchantrix, but it lacks data for new items local disenchantTable = { [UNCOMMON] = { [WEAPON] = { [15] = { { STRANGE , 0.20, 1.5 }, { LMAGIC , 0.80, 1.5 }, }, [20] = { { STRANGE , 0.20, 2.5 }, { GMAGIC , 0.75, 1.5 }, { SGLIMMERING, 0.05, 1.0 }, }, [25] = { { STRANGE , 0.15, 5.0 }, { GMAGIC , 0.75, 1.5 }, { SGLIMMERING, 0.10, 1.0 }, }, [30] = { { SOUL , 0.20, 1.5 }, { GMAGIC , 0.75, 1.5 }, { LGLIMMERING, 0.05, 1.0 }, }, [35] = { { SOUL , 0.20, 3.5 }, { LMYSTIC , 0.75, 1.5 }, { SGLOWING , 0.05, 1.0 }, }, [40] = { { VISION , 0.20, 1.5 }, { GMYSTIC , 0.75, 1.5 }, { LGLOWING , 0.05, 1.0 }, }, [45] = { { VISION , 0.15, 3.5 }, { LNETHER , 0.80, 1.5 }, { SRADIANT , 0.05, 1.0 }, }, [50] = { { DREAM , 0.20, 1.5 }, { GNETHER , 0.75, 1.5 }, { LRADIANT , 0.05, 1.0 }, }, [55] = { { DREAM , 0.20, 3.5 }, { LETERNAL, 0.75, 1.5 }, { SBRILLIANT , 0.05, 1.0 }, }, [60] = { { ILLUSION, 0.20, 1.5 }, { GETERNAL, 0.75, 1.5 }, { LBRILLIANT , 0.05, 1.0 }, }, [65] = { { ILLUSION, 0.20, 3.5 }, { GETERNAL, 0.75, 2.5 }, { LBRILLIANT , 0.05, 1.0 }, }, [85] = { { ARCANE , 0.20, 2.5 }, { LPLANAR , 0.75, 2.5 }, { SPRISMATIC , 0.05, 1.0 }, }, [99] = { { ARCANE , 0.20, 2.5 }, { LPLANAR , 0.75, 2.5 }, { SPRISMATIC , 0.05, 1.0 }, }, [120] = { { ARCANE , 0.20, 3.5 }, { GPLANAR , 0.75, 1.5 }, { LPRISMATIC , 0.05, 1.0 }, }, }, [ARMOR] = { [15] = { { STRANGE , 0.80, 1.5 }, { LMAGIC , 0.20, 1.5 }, }, [20] = { { STRANGE , 0.75, 2.5 }, { GMAGIC , 0.20, 1.5 }, { SGLIMMERING, 0.05, 1.0 }, }, [25] = { { STRANGE , 0.75, 5.0 }, { LASTRAL , 0.15, 1.5 }, { SGLIMMERING, 0.10, 1.0 }, }, [30] = { { SOUL , 0.75, 1.5 }, { GASTRAL , 0.20, 1.5 }, { LGLIMMERING, 0.05, 1.0 }, }, [35] = { { SOUL , 0.75, 3.5 }, { LMYSTIC , 0.20, 1.5 }, { SGLOWING , 0.05, 1.0 }, }, [40] = { { VISION , 0.75, 1.5 }, { GMYSTIC , 0.20, 1.5 }, { LGLOWING , 0.05, 1.0 }, }, [45] = { { VISION , 0.80, 3.5 }, { LNETHER , 0.15, 1.5 }, { SRADIANT , 0.05, 1.0 }, }, [50] = { { DREAM , 0.75, 1.5 }, { GNETHER , 0.20, 1.5 }, { LRADIANT , 0.05, 1.0 }, }, [55] = { { DREAM , 0.75, 3.5 }, { LETERNAL, 0.20, 1.5 }, { SBRILLIANT , 0.05, 1.0 }, }, [60] = { { ILLUSION, 0.75, 1.5 }, { GETERNAL, 0.20, 1.5 }, { LBRILLIANT , 0.05, 1.0 }, }, [65] = { { ILLUSION, 0.75, 3.5 }, { GETERNAL, 0.20, 2.5 }, { LBRILLIANT , 0.05, 1.0 }, }, [85] = { { ARCANE , 0.75, 2.5 }, { LPLANAR , 0.20, 2.5 }, { SPRISMATIC , 0.05, 1.0 }, }, [99] = { { ARCANE , 0.75, 2.5 }, { LPLANAR , 0.20, 2.5 }, { SPRISMATIC , 0.05, 1.0 }, }, [120] = { { ARCANE , 0.75, 3.5 }, { GPLANAR , 0.20, 1.5 }, { LPRISMATIC , 0.05, 1.0 }, }, }, }, [RARE] = { [WEAPON] = { [20] = { { SGLIMMERING, 1.00, 1.0 }, }, [25] = { { SGLIMMERING, 1.00, 1.0 }, }, [30] = { { LGLIMMERING, 1.00, 1.0 }, }, [35] = { { SGLOWING , 1.00, 1.0 }, }, [40] = { { LGLOWING , 1.00, 1.0 }, }, [45] = { { SRADIANT , 1.00, 1.0 }, }, [50] = { { LRADIANT , 1.00, 1.0 }, }, [55] = { { SBRILLIANT , 1.00, 1.0 }, }, [60] = { { LBRILLIANT , 0.99, 1.0 }, { NEXUS, 0.01, 1.0 }, }, [65] = { { LBRILLIANT , 0.99, 1.0 }, { NEXUS, 0.01, 1.0 }, }, [85] = { { SPRISMATIC , 0.99, 1.0 }, { NEXUS, 0.01, 1.0 }, }, [99] = { { SPRISMATIC , 0.99, 1.0 }, { VOID , 0.01, 1.0 }, }, [120] = { { LPRISMATIC , 0.99, 1.0 }, { VOID , 0.01, 1.0 }, }, }, [ARMOR] = { [20] = { { SGLIMMERING, 1.00, 1.0 }, }, [25] = { { SGLIMMERING, 1.00, 1.0 }, }, [30] = { { LGLIMMERING, 1.00, 1.0 }, }, [35] = { { SGLOWING , 1.00, 1.0 }, }, [40] = { { LGLOWING , 1.00, 1.0 }, }, [45] = { { SRADIANT , 1.00, 1.0 }, }, [50] = { { LRADIANT , 1.00, 1.0 }, }, [55] = { { SBRILLIANT , 1.00, 1.0 }, }, [60] = { { LBRILLIANT , 0.99, 1.0 }, { NEXUS, 0.01, 1.0 }, }, [65] = { { LBRILLIANT , 0.99, 1.0 }, { NEXUS, 0.01, 1.0 }, }, [85] = { { SPRISMATIC , 0.99, 1.0 }, { NEXUS, 0.01, 1.0 }, }, [99] = { { SPRISMATIC , 0.99, 1.0 }, { VOID , 0.01, 1.0 }, }, [120] = { { LPRISMATIC , 0.99, 1.0 }, { VOID , 0.01, 1.0 }, }, }, }, [EPIC] = { [WEAPON] = { [45] = { { SRADIANT , 1.00, 3.5 }, }, [50] = { { LRADIANT , 1.00, 3.5 }, }, [55] = { { SBRILLIANT, 1.00, 3.5 }, }, [60] = { { NEXUS , 1.00, 1.0 }, }, [65] = { { NEXUS , 1.00, 1.0 }, }, [85] = { { NEXUS , 1.00, 1.0 }, }, [99] = { { VOID , 1.00, 1.0 }, }, [120] = { { VOID , 1.00, 1.5 }, }, }, [ARMOR] = { [45] = { { SRADIANT , 1.00, 3.5 }, }, [50] = { { LRADIANT , 1.00, 3.5 }, }, [55] = { { SBRILLIANT, 1.00, 3.5 }, }, [60] = { { NEXUS , 1.00, 1.0 }, }, [65] = { { NEXUS , 1.00, 1.0 }, }, [85] = { { NEXUS , 1.00, 1.0 }, }, [99] = { { VOID , 1.00, 1.0 }, }, [120] = { { VOID , 1.00, 1.5 }, }, }, }, } ---------------------------------------- -- calculate value of a stack of reagents based on -- auctioneer data and price tables above local getReagentValue = function(itemID, itemCount) local base = baselinePrices[itemID] local adjust = priceAdjustment[itemID] or 1 if not base then return nil end local median, snapshot, snapshotCount = nil, nil, nil local _, link = GetItemInfo(itemID) if link then local key = Auctioneer.ItemDB.CreateItemKeyFromLink(link) if key then median = Auctioneer.Statistic.GetItemHistoricalMedianBuyout(key) snapshot, snapshotCount = Auctioneer.Statistic.GetItemSnapshotMedianBuyout(key) end end median = median or base snapshot = snapshot or base snapshotCount = snapshotCount or 1 local snapshotWeight = 0 if snapshotCount >= 5 and snapshot < median then snapshotWeight = math.log10(snapshotCount) / math.log10(50) end snapshotWeight = math.min(math.max(snapshotWeight, 0), 1) local medianWeight = 1 - snapshotWeight local combined = median * medianWeight + snapshot * snapshotWeight return combined * adjust * itemCount end -- take an ilevel and round it up to the corresponding bracket local roundupLevel = function(level) for _, bracket in pairs(levelUpperBounds) do if bracket >= level then return bracket end end return nil end -- get entry from disenchant table (or nil if nothing found) local getDisenchants = function(quality, type, level) if disenchantTable[quality] and disenchantTable[quality][type] and disenchantTable[quality][type][level] then return disenchantTable[quality][type][level] end return nil end -- calculate disenchant value of item based on disenchant table and -- calculated reagent values local getDisenchantValue = function(itemID) local result = nil local _, _, quality, level, _, typeString, _, _, _, _ = GetItemInfo(itemID) if quality >= UNCOMMON and quality <= EPIC and not badItem[itemID] then local type = typeStringToType[typeString] if type then level = roundupLevel(level) if level then local disenchants = getDisenchants(quality, type, level) if disenchants then result = 0 for _, stats in pairs(disenchants) do local reagent, chance, count = stats[1], stats[2], stats[3] result = result + getReagentValue(reagent, chance * count) end end end end end return result end -------------------------------------------------------------------------------- -- now decide what to do with the auction -- min profit for bid local bidMinProfitRel = 0.65 local bidMinProfitAbs = 3000 -- min profit for buy local buyMinProfitRel = 0.65 local buyMinProfitAbs = 5000 -- if buyout is close enough to low enough bid, just buy it anyway local buyMaxBidNear = 0.025 -- assume item is worthless until proven otherwise local myBasePrice = 0 -- prevent equipable greens from showing up for resale local _,_, quality, _, _, class, _,_,_ = GetItemInfo(itemID) if (quality==2 and (class =="Weapon" or class == "Armor")) then basePrice = 0 end -- calculate disenchant value or reagent value depending on the type of item local disenchantValue = getDisenchantValue(itemID) if disenchantValue then myBasePrice = disenchantValue reason = "Disenchant" depositCost = 0 depositRate = 0 else local reagentValue = getReagentValue(itemID, itemCount) if reagentValue then myBasePrice = reagentValue reason = "Reagent" depositCost = 0 depositRate = 0 end end -- account for AH cut local resaleValue = myBasePrice * 0.95 -- decide whether or not to buy if buyPrice ~= 0 and buyPrice <= resaleValue * (1 - buyMinProfitRel) and buyPrice <= resaleValue - buyMinProfitAbs then action = "buy" reason = reason .. " (buy)" basePrice = resaleValue elseif bidPrice ~= 0 and bidPrice <= resaleValue * (1 - bidMinProfitRel) and bidPrice <= resaleValue - bidMinProfitAbs then if buyPrice ~= 0 and bidPrice >= buyPrice * (1 - buyMaxBidNear) then action = "buy" reason = reason .. " (buy near bid)" basePrice = resaleValue else action = "bid" reason = reason .. " (bid)" basePrice = resaleValue end end