233 lines
9.1 KiB
Lua
Executable File
233 lines
9.1 KiB
Lua
Executable File
-- ============================================================================
|
|
-- Addon Name: TargetScanner
|
|
-- Description: Item scanner tailored for the
|
|
-- Anniversary Edition Auction House API.
|
|
-- API Version: Compatible with Anniversary Realms (1.15.x)
|
|
-- ============================================================================
|
|
|
|
local addonName, addonTable = ...
|
|
|
|
-- 1. CONFIGURATION: Define target item names and your maximum unit buyout threshold.
|
|
-- Server-side queries accept item names as search filters rather than raw IDs.
|
|
-- WoW Anniversary Edition Alchemy Consumables Configuration (Max Price in Copper)
|
|
local TargetItems = {
|
|
-- Restoration Potions (Health)
|
|
["Minor Healing Potion"] = { maxPrice = 500 },
|
|
["Lesser Healing Potion"] = { maxPrice = 1500 },
|
|
["Healing Potion"] = { maxPrice = 5000 },
|
|
["Greater Healing Potion"] = { maxPrice = 20000 },
|
|
["Superior Healing Potion"] = { maxPrice = 50000 },
|
|
["Major Healing Potion"] = { maxPrice = 150000 },
|
|
|
|
-- Restoration Potions (Mana)
|
|
["Lesser Mana Potion"] = { maxPrice = 2000 },
|
|
["Mana Potion"] = { maxPrice = 6000 },
|
|
["Greater Mana Potion"] = { maxPrice = 25000 },
|
|
["Superior Mana Potion"] = { maxPrice = 75000 },
|
|
["Major Mana Potion"] = { maxPrice = 200000 },
|
|
["Combat Mana Potion"] = { maxPrice = 100000 },
|
|
|
|
-- Utility & Defensive Potions
|
|
["Swiftness Potion"] = { maxPrice = 80000 },
|
|
["Swim Speed Potion"] = { maxPrice = 15000 },
|
|
["Free Action Potion"] = { maxPrice = 150000 },
|
|
["Living Action Potion"] = { maxPrice = 250000 },
|
|
["Limited Invulnerability Potion"] = { maxPrice = 180000 },
|
|
["Restorative Potion"] = { maxPrice = 120000 },
|
|
["Invisibility Potion"] = { maxPrice = 100000 },
|
|
["Lesser Invisibility Potion"] = { maxPrice = 40000 },
|
|
["Potion of Dreamless Sleep"] = { maxPrice = 60000 },
|
|
["Purification Potion"] = { maxPrice = 50000 },
|
|
["Wildvine Potion"] = { maxPrice = 90000 },
|
|
|
|
-- Elemental Protection Potions
|
|
["Fire Protection Potion"] = { maxPrice = 30000 },
|
|
["Greater Fire Protection Potion"] = { maxPrice = 250000 },
|
|
["Mighty Fire Protection Potion"] = { maxPrice = 400000 },
|
|
["Frost Protection Potion"] = { maxPrice = 20000 },
|
|
["Greater Frost Protection Potion"] = { maxPrice = 150000 },
|
|
["Mighty Frost Protection Potion"] = { maxPrice = 300000 },
|
|
["Nature Protection Potion"] = { maxPrice = 25000 },
|
|
["Greater Nature Protection Potion"] = { maxPrice = 200000 },
|
|
["Mighty Nature Protection Potion"] = { maxPrice = 350000 },
|
|
["Shadow Protection Potion"] = { maxPrice = 30000 },
|
|
["Greater Shadow Protection Potion"] = { maxPrice = 220000 },
|
|
["Mighty Shadow Protection Potion"] = { maxPrice = 380000 },
|
|
["Arcane Protection Potion"] = { maxPrice = 15000 },
|
|
["Greater Arcane Protection Potion"] = { maxPrice = 100000 },
|
|
|
|
-- Combat Stats & Class Potions
|
|
["Rage Potion"] = { maxPrice = 10000 },
|
|
["Great Rage Potion"] = { maxPrice = 40000 },
|
|
["Mighty Rage Potion"] = { maxPrice = 180000 },
|
|
["Greater Stoneshield Potion"] = { maxPrice = 120000 },
|
|
["Mageblood Potion"] = { maxPrice = 90000 },
|
|
["Major Troll's Blood Potion"] = { maxPrice = 40000 },
|
|
|
|
-- Physical/Combat Elixirs
|
|
["Elixir of Lion's Strength"] = { maxPrice = 800 },
|
|
["Elixir of Lesser Agility"] = { maxPrice = 3000 },
|
|
["Elixir of Agility"] = { maxPrice = 25000 },
|
|
["Elixir of Giants"] = { maxPrice = 45000 },
|
|
["Elixir of Brute Force"] = { maxPrice = 60000 },
|
|
["Elixir of the Mongoose"] = { maxPrice = 180000 },
|
|
|
|
-- Caster Elixirs
|
|
["Elixir of Firepower"] = { maxPrice = 15000 },
|
|
["Elixir of Greater Firepower"] = { maxPrice = 70000 },
|
|
["Elixir of Shadow Power"] = { maxPrice = 55000 },
|
|
["Elixir of Greater Intellect"] = { maxPrice = 35000 },
|
|
["Elixir of the Sages"] = { maxPrice = 40000 },
|
|
["Arcane Elixir"] = { maxPrice = 45000 },
|
|
["Greater Arcane Elixir"] = { maxPrice = 160000 },
|
|
|
|
-- Defensive & Utility Elixirs
|
|
["Elixir of Defense"] = { maxPrice = 8000 },
|
|
["Elixir of Fortitude"] = { maxPrice = 35000 },
|
|
["Elixir of Superior Defense"] = { maxPrice = 150000 },
|
|
["Elixir of Poison Resistance"] = { maxPrice = 25000 },
|
|
["Gift of Arthas"] = { maxPrice = 30000 },
|
|
["Elixir of Dream Vision"] = { maxPrice = 40000 },
|
|
|
|
-- Raid Flasks (Persistent through death)
|
|
["Flask of the Titans"] = { maxPrice = 600000 },
|
|
["Flask of Supreme Power"] = { maxPrice = 600000 },
|
|
["Flask of Distilled Wisdom"] = { maxPrice = 600000 },
|
|
["Flask of Chromatic Resistance"] = { maxPrice = 400000 },
|
|
["Flask of Petrification"] = { maxPrice = 500000 },
|
|
|
|
-- Alchemy Oils
|
|
["Shadow Oil"] = { maxPrice = 80000 },
|
|
["Frost Oil"] = { maxPrice = 50000 }
|
|
}
|
|
|
|
-- Addon state properties
|
|
local currentItemIndex = 1
|
|
local itemOrder = {}
|
|
local isScanning = false
|
|
|
|
-- Chronologically map out the sequence keys
|
|
for name, _ in pairs(TargetItems) do
|
|
table.insert(itemOrder, name)
|
|
end
|
|
|
|
-- 2. FRAME & EVENT DISPATCHER
|
|
local ScannerFrame = CreateFrame("Frame")
|
|
ScannerFrame:RegisterEvent("AUCTION_HOUSE_SHOW")
|
|
ScannerFrame:RegisterEvent("AUCTION_HOUSE_CLOSED")
|
|
ScannerFrame:RegisterEvent("AUCTION_ITEM_LIST_UPDATE")
|
|
|
|
-- 3. CORE PRINT UTILITY
|
|
local function PrintMessage(msg)
|
|
print("|cFF00FFCC[TargetScanner]|r: " .. msg)
|
|
end
|
|
|
|
-- Converts flat copper currencies into beautifully color-coded Gold/Silver/Copper strings
|
|
local function FormatMoney(copper)
|
|
if not copper or copper == 0 then return "0g" end
|
|
local gold = math.floor(copper / 10000)
|
|
local silver = math.floor((copper % 10000) / 100)
|
|
local cop = copper % 100
|
|
return string.format("|cFFFFD700%dg|r |cFFC7C7C7%ds|r |cFFB87333%dc|r", gold, silver, cop)
|
|
end
|
|
|
|
-- 4. SEQUENCE STEP MANAGER
|
|
local function ScanNextItem()
|
|
if not isScanning then return end
|
|
|
|
-- Check if we finished checking our tailored list
|
|
if currentItemIndex > #itemOrder then
|
|
PrintMessage("Scan process complete!")
|
|
isScanning = false
|
|
currentItemIndex = 1
|
|
return
|
|
end
|
|
|
|
local targetName = itemOrder[currentItemIndex]
|
|
PrintMessage("Querying server for: " .. targetName .. "...")
|
|
|
|
-- Auction Query API Structure:
|
|
-- QueryAuctionItems("name", minLevel, maxLevel, page, isUsable, rarityFilter, getAll, exactMatch)
|
|
-- We set exactMatch (parameter 8) to true to cut out extraneous suffix permutations
|
|
QueryAuctionItems(targetName, nil, nil, 0, nil, nil, false, true)
|
|
end
|
|
|
|
-- Main interface execution call
|
|
function TargetScanner_StartScan()
|
|
if isScanning then
|
|
PrintMessage("A scan sequence is already actively running.")
|
|
return
|
|
end
|
|
|
|
isScanning = true
|
|
currentItemIndex = 1
|
|
PrintMessage("Kicking off sequential tracking for " .. #itemOrder .. " Classic items...")
|
|
ScanNextItem()
|
|
end
|
|
|
|
-- 5. EVENT SYSTEM INTERACTION
|
|
ScannerFrame:SetScript("OnEvent", function(self, event, ...)
|
|
if event == "AUCTION_HOUSE_SHOW" then
|
|
PrintMessage("Anniversary Auction House ready. Type /tscan to check values.")
|
|
|
|
elseif event == "AUCTION_HOUSE_CLOSED" then
|
|
isScanning = false
|
|
currentItemIndex = 1
|
|
|
|
elseif event == "AUCTION_ITEM_LIST_UPDATE" then
|
|
-- This event fires when server database page details load into local client visibility
|
|
if not isScanning then return end
|
|
|
|
local batchCount, totalCount = GetNumAuctionItems("list")
|
|
local targetName = itemOrder[currentItemIndex]
|
|
local config = TargetItems[targetName]
|
|
local foundDeals = false
|
|
|
|
-- Scan through all listings currently sent to the client list buffer
|
|
for i = 1, batchCount do
|
|
-- Data fetch return structure map
|
|
local name, _, count, _, _, _, _, _, _, buyoutPrice = GetAuctionItemInfo("list", i)
|
|
|
|
if name == targetName and buyoutPrice and buyoutPrice > 0 then
|
|
-- Divide by stack count size to extract true single unit prices
|
|
local unitPrice = buyoutPrice / count
|
|
|
|
if unitPrice <= config.maxPrice then
|
|
PrintMessage(string.format("PROFITABLE LISTING: %s x%d - Unit Cost: %s (Total Buyout: %s)",
|
|
name,
|
|
count,
|
|
FormatMoney(unitPrice),
|
|
FormatMoney(buyoutPrice)
|
|
))
|
|
foundDeals = true
|
|
end
|
|
end
|
|
end
|
|
|
|
if not foundDeals then
|
|
PrintMessage("No listings found below price caps for: " .. targetName)
|
|
end
|
|
|
|
-- Increment queue index to prepare the next item
|
|
currentItemIndex = currentItemIndex + 1
|
|
|
|
-- CRITICAL: Servers implement severe request limits.
|
|
-- An explicit 2.0-second delay protects the client connection from disconnects.
|
|
C_Timer.After(2.0, function()
|
|
ScanNextItem()
|
|
end)
|
|
end
|
|
end)
|
|
|
|
-- 6. INTERFACE INTERACTION COMMAND
|
|
SLASH_TARSCAN1 = "/tscan"
|
|
SlashCmdList["TARSCAN"] = function(msg)
|
|
-- WoW utilizes 'AuctionFrame'
|
|
if not AuctionFrame or not AuctionFrame:IsShown() then
|
|
PrintMessage("Aborted: You must have an interaction window open with an Auctioneer NPC.")
|
|
return
|
|
end
|
|
TargetScanner_StartScan()
|
|
end
|
|
|
|
PrintMessage("Targeted script loaded. Macro command: /tscan") |