AuctioneerSuite/Enchantrix/EnxMain.lua

417 lines
15 KiB
Lua
Raw Permalink Normal View History

2026-04-13 17:48:13 -04:00
--[[
Enchantrix Addon for World of Warcraft(tm).
Version: 5.9.4961 (WhackyWallaby)
Revision: $Id: EnxMain.lua 4933 2010-10-13 17:16:14Z Nechckn $
URL: http://enchantrix.org/
This is an addon for World of Warcraft that add a list of what an item
disenchants into to the items that you mouse-over in the game.
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.
Note:
This AddOn's source code is specifically designed to work with
World of Warcraft's interpreted AddOn system.
You have an implicit license to use this AddOn with these facilities
since that is its designated purpose as per:
http://www.fsf.org/licensing/licenses/gpl-faq.html#InterpreterIncompat
]]
Enchantrix_RegisterRevision("$URL: http://svn.norganna.org/auctioneer/branches/5.9/Enchantrix/EnxMain.lua $", "$Rev: 4933 $")
-- Local functions
local addonLoaded
local onLoad
local pickupInventoryItemHook
local useContainerItemHook
local spellTargetItemHook
local useItemByNameHook
local onEvent
Enchantrix.Version = "5.9.4961"
if (Enchantrix.Version == "<".."%version%>") then
Enchantrix.Version = "4.0.DEV"
end
local DisenchantEvent = {}
-- Secondary hook for Enchantrix to update itself if Auctioneer is loaded later
function addonLoadedPost(hookArgs, event, addOnName)
if event ~= "ADDON_LOADED" then
return
end
if addOnName:lower() ~= "auctioneer" and addOnName:lower() ~= "auc-advanced" then
return
end
Stubby.UnregisterEventHook("ADDON_LOADED", "Enchantrix")
-- check for auctioneer and version
Enchantrix.Command.AuctioneerLoaded()
-- update gui to match
Enchantrix.Settings.UpdateGuiConfig()
end
-- This function differs from onLoad in that it is executed
-- after variables have been loaded.
function addonLoaded(hookArgs, event, addOnName)
-- this cruft is only needed when using Stubby.RegisterEventHook("ADDON_LOADED", "Enchantrix", addonLoaded)
if (event ~= "ADDON_LOADED") or (addOnName:lower() ~= "enchantrix") then
return
end
Stubby.UnregisterEventHook("ADDON_LOADED", "Enchantrix")
Stubby.RegisterEventHook("ADDON_LOADED", "Enchantrix", addonLoadedPost)
-- Call AddonLoaded for other objects
Enchantrix.Storage.AddonLoaded() -- Sets up saved variables so should be called first
Enchantrix.Command.AddonLoaded()
Enchantrix.Config.AddonLoaded()
Enchantrix.Locale.AddonLoaded()
Enchantrix.Tooltip.AddonLoaded()
Enchantrix.AutoDisenchant.AddonLoaded()
Enchantrix.MiniIcon.Reposition()
Enchantrix.SideIcon.Update()
Enchantrix.Revision = Enchantrix.Util.GetRevision("$Revision: 4933 $")
for name, obj in pairs(Enchantrix) do
if type(obj) == "table" then
Enchantrix.Revision = math.max(Enchantrix.Revision, Enchantrix.Util.GetRevision(obj.Revision))
end
end
-- Register disenchant detection hooks (using secure post hooks)
hooksecurefunc("UseContainerItem", useContainerItemHook)
hooksecurefunc("PickupInventoryItem", pickupInventoryItemHook)
hooksecurefunc("SpellTargetItem", spellTargetItemHook)
hooksecurefunc("UseItemByName", useItemByNameHook); -- added in 2.0, used by macro /use
-- events that we need to catch
Stubby.RegisterEventHook("UNIT_SPELLCAST_SUCCEEDED", "Enchantrix", onEvent)
Stubby.RegisterEventHook("UNIT_SPELLCAST_SENT", "Enchantrix", onEvent)
-- Stubby.RegisterEventHook("UNIT_SPELLCAST_START", "Enchantrix", onEvent) -- not used right now
-- Stubby.RegisterEventHook("UNIT_SPELLCAST_STOP", "Enchantrix", onEvent) -- not used right now
Stubby.RegisterEventHook("UNIT_SPELLCAST_FAILED", "Enchantrix", onEvent)
Stubby.RegisterEventHook("UNIT_SPELLCAST_INTERRUPTED", "Enchantrix", onEvent)
Stubby.RegisterEventHook("LOOT_OPENED", "Enchantrix", onEvent)
-- Stubby.RegisterEventHook("ZONE_CHANGED", "Enchantrix", onEvent) -- not used right now
-- and hook into tooltips for more info
hooksecurefunc("GameTooltip_OnHide", ENX_GameTooltip_OnHide);
hooksecurefunc("GameTooltip_SetDefaultAnchor", ENX_GameTooltip_SetDefaultAnchor);
ENX_SetTooltipHooks("GameTooltip");
ENX_SetTooltipHooks("ItemRefTooltip");
ENX_SetTooltipHooks("ShoppingTooltip1");
ENX_SetTooltipHooks("ShoppingTooltip2");
-- now print our version and credits
local vstr = ("%s-%d"):format(Enchantrix.Version, Enchantrix.Revision)
Enchantrix.Util.ChatPrint(_ENCH('FrmtWelcome'):format(vstr), 0.8, 0.8, 0.2)
-- check for auctioneer and version
Enchantrix.Command.AuctioneerLoaded();
end
-- Register our temporary command hook with stubby
function onLoad()
Stubby.RegisterBootCode("Enchantrix", "CommandHandler", [[
local function cmdHandler(msg)
local i,j, cmd, param = msg:lower():find("^([^ ]+) (.+)$")
if (not cmd) then cmd = msg:lower() end
if (not cmd) then cmd = "" end
if (not param) then param = "" end
if (cmd == "load") then
if (param == "") then
Stubby.Print("Manually loading Enchantrix...")
LoadAddOn("Enchantrix")
elseif (param == "always") then
Stubby.Print("Setting Enchantrix to always load for this character")
Stubby.SetConfig("Enchantrix", "LoadType", param)
LoadAddOn("Enchantrix")
elseif (param == "never") then
Stubby.Print("Setting Enchantrix to never load automatically for this character (you may still load manually)")
Stubby.SetConfig("Enchantrix", "LoadType", param)
else
Stubby.Print("Your command was not understood")
end
else
Stubby.Print("Enchantrix is currently not loaded.")
Stubby.Print(" You may load it now by typing |cffffffff/enchantrix load|r")
Stubby.Print(" You may also set your loading preferences for this character by using the following commands:")
Stubby.Print(" |cffffffff/enchantrix load always|r - Enchantrix will always load for this character")
Stubby.Print(" |cffffffff/enchantrix load never|r - Enchantrix will never load automatically for this character (you may still load it manually)")
end
end
SLASH_ENCHANTRIX1 = "/enchantrix"
SLASH_ENCHANTRIX2 = "/enchant"
SLASH_ENCHANTRIX3 = "/enx"
SlashCmdList["ENCHANTRIX"] = cmdHandler
]]);
Stubby.RegisterBootCode("Enchantrix", "Triggers", [[
if Stubby.GetConfig("Enchantrix", "LoadType") == "always" then
LoadAddOn("Enchantrix")
else
Stubby.Print("]].._ENCH('MesgNotloaded')..[[")
end
]]);
SLASH_ENCHANTRIX1 = "/enchantrix";
SLASH_ENCHANTRIX2 = "/enchant";
SLASH_ENCHANTRIX3 = "/enx";
SlashCmdList["ENCHANTRIX"] = function(msg) Enchantrix.Command.HandleCommand(msg) end
-- this version gets addonLoaded called AFTER SavedVariables have been loaded
Stubby.RegisterEventHook("ADDON_LOADED", "Enchantrix", addonLoaded)
-- this version gets addonLoaded called BEFORE SavedVariables have been loaded
-- so all settings then end up with default values during the addonLoaded call
-- this ends up showing the minimap icon in the wrong location
--Stubby.RegisterAddOnHook("Enchantrix", "Enchantrix", addonLoaded)
end
-- Big thanks to FizzWidget for figuring out how to get the tooltips hooked
-- names have been changed to prevent conflicts
ENX_TooltipHooks = {};
function ENX_GameTooltip_OnHide(this)
local tooltipName = this:GetName();
ENX_SetTooltipHooks(tooltipName);
end
function ENX_GameTooltip_SetDefaultAnchor(tooltip, parent)
local tooltipName = tooltip:GetName();
ENX_SetTooltipHooks(tooltipName);
end
function ENX_SetTooltipHooks(tooltipName)
if (not tooltipName or tooltipName == "") then return; end
local tooltip = _G[tooltipName];
if (tooltip and tooltip:HasScript("OnTooltipSetItem") and not ENX_TooltipHooks[tooltipName]) then
ENX_TooltipHooks[tooltipName] = {};
ENX_TooltipHooks[tooltipName].OnTooltipSetItem = tooltip:GetScript("OnTooltipSetItem");
tooltip:SetScript("OnTooltipSetItem", ENX_OnTooltipSetItem);
end
end
function ENX_OnTooltipSetItem(this)
local tooltipName = this:GetName();
local tooltip = _G[tooltipName];
if (ENX_TooltipHooks[tooltipName] and ENX_TooltipHooks[tooltipName].OnTooltipSetItem) then
ENX_TooltipHooks[tooltipName].OnTooltipSetItem(tooltip);
end
local name, link = this:GetItem();
if (link) then
-- first, make sure that we think this item is disenchantable to start with (reduce false positives)
if (Enchantrix.Util.GetIType(link)) then
-- Ok, we think the item is disenchantable
-- search the tooltip text for the non-disenchantable string
for lineNum = 1, this:NumLines() do
local leftText = _G[this:GetName().."TextLeft"..lineNum]:GetText();
if (leftText == ITEM_DISENCHANT_NOT_DISENCHANTABLE) then
-- found the string, this item really isn't disenchantable
Enchantrix.Storage.SaveNonDisenchantable(link)
-- no need to continue
return false;
end
end
end
end
return false;
end
function pickupInventoryItemHook(slot)
--Enchantrix.Util.DebugPrintQuick("pickupInventoryItemHook", slot);
-- Remember last activated item
if (not UnitCastingInfo("player")) then
if slot then
DisenchantEvent.spellTarget = GetInventoryItemLink("player", slot)
DisenchantEvent.targetted = GetTime()
end
end
end
function useContainerItemHook(bag, slot)
-- Remember last activated item
--Enchantrix.Util.DebugPrintQuick("usecontaineritemhook", bag, slot);
if (not UnitCastingInfo("player")) then
if bag and slot then
DisenchantEvent.spellTarget = GetContainerItemLink(bag, slot)
DisenchantEvent.targetted = GetTime()
end
end
end
function spellTargetItemHook(itemString)
-- Remember targeted item
--Enchantrix.Util.DebugPrintQuick("targetitemhook", itemString);
if (not UnitCastingInfo("player")) then
if itemString then
local _, itemLink = GetItemInfo(itemString)
if itemLink then
DisenchantEvent.spellTarget = itemLink
DisenchantEvent.targetted = GetTime()
end
end
end
end
function useItemByNameHook(itemString)
-- Remember targeted item
--Enchantrix.Util.DebugPrintQuick("useItemByNameHook", itemString);
if (not UnitCastingInfo("player")) then
if itemString then
local _, itemLink = GetItemInfo(itemString)
if itemLink then
DisenchantEvent.spellTarget = itemLink
DisenchantEvent.targetted = GetTime()
end
end
end
end
function onEvent(funcVars, event, player, spell, rank, target)
if event == "UNIT_SPELLCAST_SUCCEEDED" then
-- NOTE: we do get the spell name here
DisenchantEvent.finished = nil
if (spell == _ENCH('ArgSpellname')) or (spell == _ENCH('ArgSpellProspectingName') or (spell == _ENCH('ArgSpellMillingName'))) then
if (DisenchantEvent.spellTarget and GetTime() - DisenchantEvent.targetted < 10) then
DisenchantEvent.finished = DisenchantEvent.spellTarget
DisenchantEvent.spellname = spell;
end
end
DisenchantEvent.sent = nil
elseif event == "UNIT_SPELLCAST_FAILED" then
-- NOTE: we don't get the spell name here
-- Successful disenchant: SENT, START, STOP, SUCCEEDED
-- Events for failed disenchant are: SENT, (sometimes START), FAILED
-- For an item above our level, the events are: SENT, FAILED
if (DisenchantEvent.sent
and DisenchantEvent.spellTarget
and GetTime() - DisenchantEvent.targetted < 5) then
-- first, make sure that we think this item is disenchantable to start with (reduce false positives)
if ( (DisenchantEvent.spellname == _ENCH('ArgSpellname'))
and Enchantrix.Util.GetIType(DisenchantEvent.spellTarget) ) then
-- this means that the item is not disenchantable, but we think it is!
-- now make sure the user had enough skill to disenchant it
-- make sure skill level is up to date
local skill = Enchantrix.Util.GetUserEnchantingSkill();
local name, link, quality, itemLevel = GetItemInfo( DisenchantEvent.spellTarget );
local skillNeeded = Enchantrix.Util.DisenchantSkillRequiredForItemLevel(itemLevel, quality);
if (skill >= skillNeeded) then
Enchantrix.Storage.SaveNonDisenchantable(DisenchantEvent.spellTarget)
end
end
end
DisenchantEvent.finished = nil
DisenchantEvent.sent = nil
elseif event == "UNIT_SPELLCAST_INTERRUPTED" then
-- disenchant interrupted
DisenchantEvent.finished = nil
DisenchantEvent.sent = nil
DisenchantEvent.spellTarget = nil
DisenchantEvent.targetted = nil
--[[
-- left here for debugging purposes
elseif event == "UNIT_SPELLCAST_START" then
-- NOTE: we don't get the spell name here
Enchantrix.Util.DebugPrint("Spellcast", ENX_INFO, "cast start", "info:", funcVars, event, spell, rank, target )
elseif event == "UNIT_SPELLCAST_STOP" then
Enchantrix.Util.DebugPrint("Spellcast", ENX_INFO, "cast stop", "info:", funcVars, event, spell, rank, target )
]]
elseif event == "UNIT_SPELLCAST_SENT" then
-- NOTE: we do get the spell name here
if (spell == _ENCH('ArgSpellname')) or (spell == _ENCH('ArgSpellProspectingName') or (spell == _ENCH('ArgSpellMillingName'))) then
if (DisenchantEvent.spellTarget and GetTime() - DisenchantEvent.targetted < 10) then
DisenchantEvent.sent = true;
end
else
DisenchantEvent.sent = nil;
DisenchantEvent.spellTarget = nil;
end
elseif event == "LOOT_OPENED" then
if DisenchantEvent.finished then
local isDisenchant = nil
local isProspect = nil
local isMilling = nil
local chatPrintYield = Enchantrix.Settings.GetSetting('chatShowFindings')
if (DisenchantEvent.spellname == _ENCH('ArgSpellname')) then
if (chatPrintYield) then
Enchantrix.Util.ChatPrint(_ENCH("FrmtFound"):format(DisenchantEvent.finished))
end
isDisenchant = true;
elseif (DisenchantEvent.spellname == _ENCH('ArgSpellProspectingName')) then
if (chatPrintYield) then
Enchantrix.Util.ChatPrint( _ENCH("FrmtProspectFound"):format(DisenchantEvent.finished))
end
isProspect = true;
elseif (DisenchantEvent.spellname == _ENCH('ArgSpellMillingName')) then
if (chatPrintYield) then
Enchantrix.Util.ChatPrint( _ENCH("FrmtMillingFound"):format(DisenchantEvent.finished))
end
isMilling = true;
end
local sig = Enchantrix.Util.GetSigFromLink(DisenchantEvent.finished)
local reagentList = {}
for i = 1, GetNumLootItems(), 1 do
if LootSlotIsItem(i) then
local icon, name, quantity, rarity = GetLootSlotInfo(i)
local link = GetLootSlotLink(i)
if (chatPrintYield) then
Enchantrix.Util.ChatPrint((" %s x%d"):format(link, quantity))
end
-- Save result
local reagentID = Enchantrix.Util.GetItemIdFromLink(link)
if reagentID then
-- for prospecting, we need to save the whole list
reagentList[ reagentID ] = (reagentList[ reagentID ] or 0) + quantity
if (isDisenchant) then
-- disenchant only yields one item, so we can pass it in one at a time
Enchantrix.Storage.SaveDisenchant(sig, reagentID, quantity)
end
end
end
end
if (isProspect) then
Enchantrix.Storage.SaveProspect(sig, reagentList)
end
if (isMilling) then
Enchantrix.Storage.SaveMilling(sig, reagentList)
end
end
DisenchantEvent.spellTarget = nil
DisenchantEvent.targetted = nil
DisenchantEvent.finished = nil
DisenchantEvent.sent = nil
end
end
-- Execute on load
onLoad()