Files
2026-08-15 16:01:02 -05:00

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")