Clean up: removed deprecated libraries
This commit is contained in:
@@ -33,3 +33,4 @@ functions/pack2.lua
|
||||
*.afphoto
|
||||
wowapi.lua
|
||||
plugins/Details_TinyThreat/Details_TinyThreat_original.lua
|
||||
*.png
|
||||
|
||||
@@ -1,996 +0,0 @@
|
||||
-- vim: ts=2 sw=2 ai et fenc=utf8
|
||||
|
||||
--[[
|
||||
-- These events can be registered for using the regular CallbackHandler ways.
|
||||
--
|
||||
-- "GroupInSpecT_Update", guid, unit, info
|
||||
-- "GroupInSpecT_Remove, guid
|
||||
-- "GroupInSpecT_InspectReady", guid, unit
|
||||
--
|
||||
-- Where <info> is a table containing some or all of the following:
|
||||
-- .guid
|
||||
-- .name
|
||||
-- .realm
|
||||
-- .race
|
||||
-- .race_localized
|
||||
-- .class
|
||||
-- .class_localized
|
||||
-- .class_id
|
||||
-- .gender -- 2 = male, 3 = female
|
||||
-- .global_spec_id
|
||||
-- .spec_index
|
||||
-- .spec_name_localized
|
||||
-- .spec_description
|
||||
-- .spec_icon
|
||||
-- .spec_background
|
||||
-- .spec_role
|
||||
-- .spec_role_detailed
|
||||
-- .spec_group -- active spec group (1/2/nil)
|
||||
-- .talents = {
|
||||
-- [<talent_id>] = {
|
||||
-- .tier
|
||||
-- .column
|
||||
-- .name_localized
|
||||
-- .icon
|
||||
-- .talent_id
|
||||
-- .spell_id
|
||||
-- }
|
||||
-- ...
|
||||
-- }
|
||||
-- .pvp_talents = {
|
||||
-- [<talent_id>] = {
|
||||
-- .name_localized
|
||||
-- .icon
|
||||
-- .talent_id
|
||||
-- .spell_id
|
||||
-- }
|
||||
-- ...
|
||||
-- }
|
||||
-- .lku -- last known unit id
|
||||
-- .not_visible
|
||||
--
|
||||
-- Functions for external use:
|
||||
--
|
||||
-- lib:Rescan (guid or nil)
|
||||
-- Force a rescan of the given group member GUID, or of all current group members if nil.
|
||||
--
|
||||
-- lib:QueuedInspections ()
|
||||
-- Returns an array of GUIDs of outstanding inspects.
|
||||
--
|
||||
-- lib:StaleInspections ()
|
||||
-- Returns an array of GUIDs for which the data has become stale and is
|
||||
-- awaiting an update (no action required, the refresh happens internally).
|
||||
-- Due to Blizzard exposing no events on (re/un)talent, there will be
|
||||
-- frequent marking of inspect data as being stale.
|
||||
--
|
||||
-- lib:GetCachedInfo (guid)
|
||||
-- Returns the cached info for the given GUID, if available, nil otherwise.
|
||||
-- Information is cached for current group members only.
|
||||
--
|
||||
-- lib:GroupUnits ()
|
||||
-- Returns an array with the set of unit ids for the current group.
|
||||
--]]
|
||||
|
||||
local MAJOR, MINOR = "LibGroupInSpecT-1.1", 91
|
||||
|
||||
if not LibStub then error(MAJOR.." requires LibStub") end
|
||||
local lib = LibStub:NewLibrary (MAJOR, MINOR)
|
||||
if not lib then return end
|
||||
|
||||
lib.events = lib.events or LibStub ("CallbackHandler-1.0"):New (lib)
|
||||
if not lib.events then error(MAJOR.." requires CallbackHandler") end
|
||||
|
||||
|
||||
local UPDATE_EVENT = "GroupInSpecT_Update"
|
||||
local REMOVE_EVENT = "GroupInSpecT_Remove"
|
||||
local INSPECT_READY_EVENT = "GroupInSpecT_InspectReady"
|
||||
local QUEUE_EVENT = "GroupInSpecT_QueueChanged"
|
||||
|
||||
local COMMS_PREFIX = "LGIST11"
|
||||
local COMMS_FMT = "1"
|
||||
local COMMS_DELIM = "\a"
|
||||
|
||||
local INSPECT_DELAY = 1.5
|
||||
local INSPECT_TIMEOUT = 10 -- If we get no notification within 10s, give up on unit
|
||||
|
||||
local MAX_ATTEMPTS = 2
|
||||
|
||||
--[===[@debug@
|
||||
lib.debug = false
|
||||
local function debug (...)
|
||||
if lib.debug then -- allow programmatic override of debug output by client addons
|
||||
print (...)
|
||||
end
|
||||
end
|
||||
--@end-debug@]===]
|
||||
|
||||
function lib.events:OnUsed(target, eventname)
|
||||
if eventname == INSPECT_READY_EVENT then
|
||||
target.inspect_ready_used = true
|
||||
end
|
||||
end
|
||||
|
||||
function lib.events:OnUnused(target, eventname)
|
||||
if eventname == INSPECT_READY_EVENT then
|
||||
target.inspect_ready_used = nil
|
||||
end
|
||||
end
|
||||
|
||||
-- Frame for events
|
||||
local frame = _G[MAJOR .. "_Frame"] or CreateFrame ("Frame", MAJOR .. "_Frame")
|
||||
lib.frame = frame
|
||||
frame:Hide()
|
||||
frame:UnregisterAllEvents ()
|
||||
frame:RegisterEvent ("PLAYER_LOGIN")
|
||||
frame:RegisterEvent ("PLAYER_LOGOUT")
|
||||
if not frame.OnEvent then
|
||||
frame.OnEvent = function(this, event, ...)
|
||||
local eventhandler = lib[event]
|
||||
return eventhandler and eventhandler (lib, ...)
|
||||
end
|
||||
frame:SetScript ("OnEvent", frame.OnEvent)
|
||||
end
|
||||
|
||||
|
||||
-- Hide our run-state in an easy-to-dump object
|
||||
lib.state = {
|
||||
mainq = {}, staleq = {}, -- inspect queues
|
||||
t = 0,
|
||||
last_inspect = 0,
|
||||
current_guid = nil,
|
||||
throttle = 0,
|
||||
tt = 0,
|
||||
debounce_send_update = 0,
|
||||
}
|
||||
lib.cache = {}
|
||||
lib.static_cache = {}
|
||||
|
||||
|
||||
-- Note: if we cache NotifyInspect, we have to hook before we cache it!
|
||||
if not lib.hooked then
|
||||
hooksecurefunc("NotifyInspect", function (...) return lib:NotifyInspect (...) end)
|
||||
lib.hooked = true
|
||||
end
|
||||
function lib:NotifyInspect(unit)
|
||||
self.state.last_inspect = GetTime()
|
||||
end
|
||||
|
||||
|
||||
-- Get local handles on the key API functions
|
||||
local CanInspect = _G.CanInspect
|
||||
local ClearInspectPlayer = _G.ClearInspectPlayer
|
||||
local GetClassInfo = _G.GetClassInfo
|
||||
local GetNumSubgroupMembers = _G.GetNumSubgroupMembers
|
||||
local GetNumSpecializationsForClassID = _G.GetNumSpecializationsForClassID
|
||||
local GetPlayerInfoByGUID = _G.GetPlayerInfoByGUID
|
||||
local GetInspectSelectedPvpTalent = _G.C_SpecializationInfo.GetInspectSelectedPvpTalent
|
||||
local GetInspectSpecialization = _G.GetInspectSpecialization
|
||||
local GetSpecialization = _G.GetSpecialization
|
||||
local GetSpecializationInfo = _G.GetSpecializationInfo
|
||||
local GetSpecializationInfoForClassID = _G.GetSpecializationInfoForClassID
|
||||
local GetSpecializationRoleByID = _G.GetSpecializationRoleByID
|
||||
local GetSpellInfo = _G.GetSpellInfo
|
||||
local GetPvpTalentInfoByID = _G.GetPvpTalentInfoByID
|
||||
local GetPvpTalentSlotInfo = _G.C_SpecializationInfo.GetPvpTalentSlotInfo
|
||||
local GetTalentInfo = _G.GetTalentInfo
|
||||
local GetTalentInfoByID = _G.GetTalentInfoByID
|
||||
local IsInRaid = _G.IsInRaid
|
||||
--local NotifyInspect = _G.NotifyInspect -- Don't cache, as to avoid missing future hooks
|
||||
local GetNumClasses = _G.GetNumClasses
|
||||
local UnitExists = _G.UnitExists
|
||||
local UnitGUID = _G.UnitGUID
|
||||
local UnitInParty = _G.UnitInParty
|
||||
local UnitInRaid = _G.UnitInRaid
|
||||
local UnitIsConnected = _G.UnitIsConnected
|
||||
local UnitIsPlayer = _G.UnitIsPlayer
|
||||
local UnitIsUnit = _G.UnitIsUnit
|
||||
local UnitName = _G.UnitName
|
||||
local SendAddonMessage = _G.C_ChatInfo.SendAddonMessage
|
||||
local RegisterAddonMessagePrefix = _G.C_ChatInfo.RegisterAddonMessagePrefix
|
||||
|
||||
local MAX_TALENT_TIERS = _G.MAX_TALENT_TIERS
|
||||
local NUM_TALENT_COLUMNS = _G.NUM_TALENT_COLUMNS
|
||||
local NUM_PVP_TALENT_SLOTS = 4
|
||||
|
||||
|
||||
local global_spec_id_roles_detailed = {
|
||||
-- Death Knight
|
||||
[250] = "tank", -- Blood
|
||||
[251] = "melee", -- Frost
|
||||
[252] = "melee", -- Unholy
|
||||
-- Demon Hunter
|
||||
[577] = "melee", -- Havoc
|
||||
[581] = "tank", -- Vengeance
|
||||
-- Druid
|
||||
[102] = "ranged", -- Balance
|
||||
[103] = "melee", -- Feral
|
||||
[104] = "tank", -- Guardian
|
||||
[105] = "healer", -- Restoration
|
||||
-- Hunter
|
||||
[253] = "ranged", -- Beast Mastery
|
||||
[254] = "ranged", -- Marksmanship
|
||||
[255] = "melee", -- Survival
|
||||
-- Mage
|
||||
[62] = "ranged", -- Arcane
|
||||
[63] = "ranged", -- Fire
|
||||
[64] = "ranged", -- Frost
|
||||
-- Monk
|
||||
[268] = "tank", -- Brewmaster
|
||||
[269] = "melee", -- Windwalker
|
||||
[270] = "healer", -- Mistweaver
|
||||
-- Paladin
|
||||
[65] = "healer", -- Holy
|
||||
[66] = "tank", -- Protection
|
||||
[70] = "melee", -- Retribution
|
||||
-- Priest
|
||||
[256] = "healer", -- Discipline
|
||||
[257] = "healer", -- Holy
|
||||
[258] = "ranged", -- Shadow
|
||||
-- Rogue
|
||||
[259] = "melee", -- Assassination
|
||||
[260] = "melee", -- Combat
|
||||
[261] = "melee", -- Subtlety
|
||||
-- Shaman
|
||||
[262] = "ranged", -- Elemental
|
||||
[263] = "melee", -- Enhancement
|
||||
[264] = "healer", -- Restoration
|
||||
-- Warlock
|
||||
[265] = "ranged", -- Affliction
|
||||
[266] = "ranged", -- Demonology
|
||||
[267] = "ranged", -- Destruction
|
||||
-- Warrior
|
||||
[71] = "melee", -- Arms
|
||||
[72] = "melee", -- Fury
|
||||
[73] = "tank", -- Protection
|
||||
}
|
||||
|
||||
local class_fixed_roles = {
|
||||
HUNTER = "DAMAGER",
|
||||
MAGE = "DAMAGER",
|
||||
ROGUE = "DAMAGER",
|
||||
WARLOCK = "DAMAGER",
|
||||
}
|
||||
|
||||
local class_fixed_roles_detailed = {
|
||||
MAGE = "ranged",
|
||||
ROGUE = "melee",
|
||||
WARLOCK = "ranged",
|
||||
}
|
||||
|
||||
-- Inspects only work after being fully logged in, so track that
|
||||
function lib:PLAYER_LOGIN ()
|
||||
self.state.logged_in = true
|
||||
|
||||
self:CacheGameData ()
|
||||
|
||||
frame:RegisterEvent ("INSPECT_READY")
|
||||
frame:RegisterEvent ("GROUP_ROSTER_UPDATE")
|
||||
frame:RegisterEvent ("PLAYER_ENTERING_WORLD")
|
||||
frame:RegisterEvent ("UNIT_LEVEL")
|
||||
frame:RegisterEvent ("PLAYER_TALENT_UPDATE")
|
||||
frame:RegisterEvent ("PLAYER_SPECIALIZATION_CHANGED")
|
||||
frame:RegisterEvent ("UNIT_SPELLCAST_SUCCEEDED")
|
||||
frame:RegisterEvent ("UNIT_NAME_UPDATE")
|
||||
frame:RegisterEvent ("UNIT_AURA")
|
||||
frame:RegisterEvent ("CHAT_MSG_ADDON")
|
||||
RegisterAddonMessagePrefix (COMMS_PREFIX)
|
||||
|
||||
local guid = UnitGUID ("player")
|
||||
local info = self:BuildInfo ("player")
|
||||
self.events:Fire (UPDATE_EVENT, guid, "player", info)
|
||||
end
|
||||
|
||||
function lib:PLAYER_LOGOUT ()
|
||||
self.state.logged_in = false
|
||||
end
|
||||
|
||||
|
||||
-- Simple timer
|
||||
do
|
||||
lib.state.t = 0
|
||||
if not frame.OnUpdate then -- ticket #4 if the OnUpdate code every changes we should stop borrowing the existing handler
|
||||
frame.OnUpdate = function(this, elapsed)
|
||||
lib.state.t = lib.state.t + elapsed
|
||||
lib.state.tt = lib.state.tt + elapsed
|
||||
if lib.state.t > INSPECT_DELAY then
|
||||
lib:ProcessQueues ()
|
||||
lib.state.t = 0
|
||||
end
|
||||
-- Unthrottle, essentially allowing 1 msg every 3 seconds, but with substantial burst capacity
|
||||
if lib.state.tt > 3 and lib.state.throttle > 0 then
|
||||
lib.state.throttle = lib.state.throttle - 1
|
||||
lib.state.tt = 0
|
||||
end
|
||||
if lib.state.debounce_send_update > 0 then
|
||||
local debounce = lib.state.debounce_send_update - elapsed
|
||||
lib.state.debounce_send_update = debounce
|
||||
if debounce <= 0 then lib:SendLatestSpecData () end
|
||||
end
|
||||
end
|
||||
frame:SetScript("OnUpdate", frame.OnUpdate) -- this is good regardless of the handler check above because otherwise a new anonymous function is created every time the OnUpdate code runs
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- Internal library functions
|
||||
|
||||
-- Caches to deal with API shortcomings as well as performance
|
||||
lib.static_cache.global_specs = {} -- [gspec] -> { .idx, .name_localized, .description, .icon, .background, .role }
|
||||
lib.static_cache.class_to_class_id = {} -- [CLASS] -> class_id
|
||||
|
||||
-- The talents cache can no longer be pre-fetched on login, but is now constructed class-by-class as we inspect people.
|
||||
-- This probably means we want to only ever access it through the GetCachedTalentInfo() helper function below.
|
||||
lib.static_cache.talents = {} -- [talent_id] -> { .spell_id, .talent_id, .name_localized, .icon, .tier, .column }
|
||||
lib.static_cache.pvp_talents = {} -- [talent_id] -> { .spell_id, .talent_id, .name_localized, .icon }
|
||||
|
||||
function lib:GetCachedTalentInfo (class_id, tier, col, group, is_inspect, unit)
|
||||
local talent_id, name, icon, sel, _, spell_id = GetTalentInfo (tier, col, group, is_inspect, unit)
|
||||
if not talent_id then
|
||||
--[===[@debug@
|
||||
debug ("GetCachedTalentInfo("..tostring(class_id)..","..tier..","..col..","..group..","..tostring(is_inspect)..","..tostring(unit)..") returned nil") --@end-debug@]===]
|
||||
return {}
|
||||
end
|
||||
local class_talents = self.static_cache.talents
|
||||
if not class_talents[talent_id] then
|
||||
class_talents[talent_id] = {
|
||||
spell_id = spell_id,
|
||||
talent_id = talent_id,
|
||||
name_localized = name,
|
||||
icon = icon,
|
||||
tier = tier,
|
||||
column = col,
|
||||
}
|
||||
end
|
||||
return class_talents[talent_id], sel
|
||||
end
|
||||
|
||||
function lib:GetCachedTalentInfoByID (talent_id)
|
||||
local class_talents = self.static_cache.talents
|
||||
if talent_id and not class_talents[talent_id] then
|
||||
local _, name, icon, _, _, spell_id, _, row, col = GetTalentInfoByID (talent_id)
|
||||
if not name then
|
||||
--[===[@debug@
|
||||
debug ("GetCachedTalentInfoByID("..tostring(talent_id)..") returned nil") --@end-debug@]===]
|
||||
return nil
|
||||
end
|
||||
class_talents[talent_id] = {
|
||||
spell_id = spell_id,
|
||||
talent_id = talent_id,
|
||||
name_localized = name,
|
||||
icon = icon,
|
||||
tier = row,
|
||||
column = col,
|
||||
}
|
||||
end
|
||||
return class_talents[talent_id]
|
||||
end
|
||||
|
||||
function lib:GetCachedPvpTalentInfoByID (talent_id)
|
||||
local pvp_talents = self.static_cache.pvp_talents
|
||||
if talent_id and not pvp_talents[talent_id] then
|
||||
local _, name, icon, _, _, spell_id = GetPvpTalentInfoByID (talent_id)
|
||||
if not name then
|
||||
--[===[@debug@
|
||||
debug ("GetCachedPvpTalentInfo("..tostring(talent_id)..") returned nil") --@end-debug@]===]
|
||||
return nil
|
||||
end
|
||||
pvp_talents[talent_id] = {
|
||||
spell_id = spell_id,
|
||||
talent_id = talent_id,
|
||||
name_localized = name,
|
||||
icon = icon,
|
||||
}
|
||||
end
|
||||
return pvp_talents[talent_id]
|
||||
end
|
||||
|
||||
function lib:CacheGameData ()
|
||||
local gspecs = self.static_cache.global_specs
|
||||
gspecs[0] = {} -- Handle no-specialization case
|
||||
for class_id = 1, GetNumClasses () do
|
||||
for idx = 1, GetNumSpecializationsForClassID (class_id) do
|
||||
local gspec_id, name, description, icon, background = GetSpecializationInfoForClassID (class_id, idx)
|
||||
gspecs[gspec_id] = {}
|
||||
local gspec = gspecs[gspec_id]
|
||||
gspec.idx = idx
|
||||
gspec.name_localized = name
|
||||
gspec.description = description
|
||||
gspec.icon = icon
|
||||
gspec.background = background
|
||||
gspec.role = GetSpecializationRoleByID (gspec_id)
|
||||
end
|
||||
|
||||
local _, class = GetClassInfo (class_id)
|
||||
self.static_cache.class_to_class_id[class] = class_id
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function lib:GuidToUnit (guid)
|
||||
local info = self.cache[guid]
|
||||
if info and info.lku and UnitGUID (info.lku) == guid then return info.lku end
|
||||
|
||||
for i,unit in ipairs (self:GroupUnits ()) do
|
||||
if UnitExists (unit) and UnitGUID (unit) == guid then
|
||||
if info then info.lku = unit end
|
||||
return unit
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function lib:Query (unit)
|
||||
if not UnitIsPlayer (unit) then return end -- NPC
|
||||
|
||||
if UnitIsUnit (unit, "player") then
|
||||
self.events:Fire (UPDATE_EVENT, UnitGUID("player"), "player", self:BuildInfo ("player"))
|
||||
return
|
||||
end
|
||||
|
||||
local mainq, staleq = self.state.mainq, self.state.staleq
|
||||
|
||||
local guid = UnitGUID (unit)
|
||||
if not mainq[guid] then
|
||||
mainq[guid] = 1
|
||||
staleq[guid] = nil
|
||||
self.frame:Show () -- Start timer if not already running
|
||||
self.events:Fire (QUEUE_EVENT)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function lib:Refresh (unit)
|
||||
local guid = UnitGUID (unit)
|
||||
if not guid then return end
|
||||
--[===[@debug@
|
||||
debug ("Refreshing "..unit) --@end-debug@]===]
|
||||
if not self.state.mainq[guid] then
|
||||
self.state.staleq[guid] = 1
|
||||
self.frame:Show ()
|
||||
self.events:Fire (QUEUE_EVENT)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function lib:ProcessQueues ()
|
||||
if not self.state.logged_in then return end
|
||||
if InCombatLockdown () then return end -- Never inspect while in combat
|
||||
if UnitIsDead ("player") then return end -- You can't inspect while dead, so don't even try
|
||||
if InspectFrame and InspectFrame:IsShown () then return end -- Don't mess with the UI's inspections
|
||||
|
||||
local mainq = self.state.mainq
|
||||
local staleq = self.state.staleq
|
||||
|
||||
if not next (mainq) and next(staleq) then
|
||||
--[===[@debug@
|
||||
debug ("Main queue empty, swapping main and stale queues") --@end-debug@]===]
|
||||
self.state.mainq, self.state.staleq = self.state.staleq, self.state.mainq
|
||||
mainq, staleq = staleq, mainq
|
||||
end
|
||||
|
||||
if (self.state.last_inspect + INSPECT_TIMEOUT) < GetTime () then
|
||||
-- If there was an inspect going, it's timed out, so either retry or move it to stale queue
|
||||
local guid = self.state.current_guid
|
||||
if guid then
|
||||
--[===[@debug@
|
||||
debug ("Inspect timed out for "..guid) --@end-debug@]===]
|
||||
|
||||
local count = mainq and mainq[guid] or (MAX_ATTEMPTS + 1)
|
||||
if not self:GuidToUnit (guid) then
|
||||
--[===[@debug@
|
||||
debug ("No longer applicable, removing from queues") --@end-debug@]===]
|
||||
mainq[guid], staleq[guid] = nil, nil
|
||||
elseif count > MAX_ATTEMPTS then
|
||||
--[===[@debug@
|
||||
debug ("Excessive retries, moving to stale queue") --@end-debug@]===]
|
||||
mainq[guid], staleq[guid] = nil, 1
|
||||
else
|
||||
mainq[guid] = count + 1
|
||||
end
|
||||
self.state.current_guid = nil
|
||||
end
|
||||
end
|
||||
|
||||
if self.state.current_guid then return end -- Still waiting on our inspect data
|
||||
|
||||
for guid,count in pairs (mainq) do
|
||||
local unit = self:GuidToUnit (guid)
|
||||
if not unit then
|
||||
--[===[@debug@
|
||||
debug ("No longer applicable, removing from queues") --@end-debug@]===]
|
||||
mainq[guid], staleq[guid] = nil, nil
|
||||
elseif not CanInspect (unit) or not UnitIsConnected (unit) then
|
||||
--[===[@debug@
|
||||
debug ("Cannot inspect "..unit..", aka "..(UnitName(unit) or "nil")..", moving to stale queue") --@end-debug@]===]
|
||||
mainq[guid], staleq[guid] = nil, 1
|
||||
else
|
||||
--[===[@debug@
|
||||
debug ("Inspecting "..unit..", aka "..(UnitName(unit) or "nil")) --@end-debug@]===]
|
||||
mainq[guid] = count + 1
|
||||
self.state.current_guid = guid
|
||||
NotifyInspect (unit)
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if not next (mainq) and not next (staleq) and self.state.throttle == 0 and self.state.debounce_send_update <= 0 then
|
||||
frame:Hide() -- Cancel timer, nothing queued and no unthrottling to be done
|
||||
end
|
||||
self.events:Fire (QUEUE_EVENT)
|
||||
end
|
||||
|
||||
|
||||
function lib:UpdatePlayerInfo (guid, unit, info)
|
||||
info.class_localized, info.class, info.race_localized, info.race, info.gender, info.name, info.realm = GetPlayerInfoByGUID (guid)
|
||||
local class = info.class
|
||||
if info.realm and info.realm == "" then info.realm = nil end
|
||||
info.class_id = class and self.static_cache.class_to_class_id[class]
|
||||
if not info.spec_role then info.spec_role = class and class_fixed_roles[class] end
|
||||
if not info.spec_role_detailed then info.spec_role_detailed = class and class_fixed_roles_detailed[class] end
|
||||
info.lku = unit
|
||||
end
|
||||
|
||||
|
||||
function lib:BuildInfo (unit)
|
||||
local guid = UnitGUID (unit)
|
||||
if not guid then return end
|
||||
|
||||
local cache = self.cache
|
||||
local info = cache[guid] or {}
|
||||
cache[guid] = info
|
||||
info.guid = guid
|
||||
|
||||
self:UpdatePlayerInfo (guid, unit, info)
|
||||
-- On a cold login, GetPlayerInfoByGUID() doesn't seem to be usable, so mark as stale
|
||||
local class = info.class
|
||||
if not class and not self.state.mainq[guid] then
|
||||
self.state.staleq[guid] = 1
|
||||
self.frame:Show ()
|
||||
self.events:Fire (QUEUE_EVENT)
|
||||
end
|
||||
|
||||
local is_inspect = not UnitIsUnit (unit, "player")
|
||||
local spec = GetSpecialization ()
|
||||
local gspec_id = is_inspect and GetInspectSpecialization (unit) or spec and GetSpecializationInfo (spec)
|
||||
|
||||
local gspecs = self.static_cache.global_specs
|
||||
if not gspec_id or not gspecs[gspec_id] then -- not a valid spec_id
|
||||
info.global_spec_id = nil
|
||||
else
|
||||
info.global_spec_id = gspec_id
|
||||
local spec_info = gspecs[gspec_id]
|
||||
info.spec_index = spec_info.idx
|
||||
info.spec_name_localized = spec_info.name_localized
|
||||
info.spec_description = spec_info.description
|
||||
info.spec_icon = spec_info.icon
|
||||
info.spec_background = spec_info.background
|
||||
info.spec_role = spec_info.role
|
||||
info.spec_role_detailed = global_spec_id_roles_detailed[gspec_id]
|
||||
end
|
||||
|
||||
if not info.spec_role then info.spec_role = class and class_fixed_roles[class] end
|
||||
if not info.spec_role_detailed then info.spec_role_detailed = class and class_fixed_roles_detailed[class] end
|
||||
|
||||
info.talents = info.talents or {}
|
||||
info.pvp_talents = info.pvp_talents or {}
|
||||
|
||||
-- Only scan talents when we have player data
|
||||
if info.spec_index then
|
||||
info.spec_group = GetActiveSpecGroup (is_inspect)
|
||||
wipe (info.talents)
|
||||
for tier = 1, MAX_TALENT_TIERS do
|
||||
for col = 1, NUM_TALENT_COLUMNS do
|
||||
local talent, sel = self:GetCachedTalentInfo (info.class_id, tier, col, info.spec_group, is_inspect, unit)
|
||||
if sel then
|
||||
info.talents[talent.talent_id] = talent
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
wipe (info.pvp_talents)
|
||||
if is_inspect then
|
||||
for index = 1, NUM_PVP_TALENT_SLOTS do
|
||||
local talent_id = GetInspectSelectedPvpTalent (unit, index)
|
||||
if talent_id then
|
||||
info.pvp_talents[talent_id] = self:GetCachedPvpTalentInfoByID (talent_id)
|
||||
end
|
||||
end
|
||||
else
|
||||
-- C_SpecializationInfo.GetAllSelectedPvpTalentIDs will sometimes return a lot of extra talents
|
||||
for index = 1, NUM_PVP_TALENT_SLOTS do
|
||||
local slot_info = GetPvpTalentSlotInfo (index)
|
||||
local talent_id = slot_info and slot_info.selectedTalentID
|
||||
if talent_id then
|
||||
info.pvp_talents[talent_id] = self:GetCachedPvpTalentInfoByID (talent_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
info.glyphs = info.glyphs or {} -- kept for addons that still refer to this
|
||||
|
||||
if is_inspect and not UnitIsVisible (unit) and UnitIsConnected (unit) then info.not_visible = true end
|
||||
|
||||
return info
|
||||
end
|
||||
|
||||
|
||||
function lib:INSPECT_READY (guid)
|
||||
local unit = self:GuidToUnit (guid)
|
||||
local finalize = false
|
||||
if unit then
|
||||
if guid == self.state.current_guid then
|
||||
self.state.current_guid = nil -- Got what we asked for
|
||||
finalize = true
|
||||
--[===[@debug@
|
||||
debug ("Got inspection data for requested guid "..guid) --@end-debug@]===]
|
||||
end
|
||||
|
||||
local mainq, staleq = self.state.mainq, self.state.staleq
|
||||
mainq[guid], staleq[guid] = nil, nil
|
||||
|
||||
local gspec_id = GetInspectSpecialization (unit)
|
||||
if not self.static_cache.global_specs[gspec_id] then -- Bah, got garbage, flag as stale and try again
|
||||
staleq[guid] = 1
|
||||
return
|
||||
end
|
||||
|
||||
self.events:Fire (UPDATE_EVENT, guid, unit, self:BuildInfo (unit))
|
||||
self.events:Fire (INSPECT_READY_EVENT, guid, unit)
|
||||
end
|
||||
if finalize then
|
||||
ClearInspectPlayer ()
|
||||
end
|
||||
self.events:Fire (QUEUE_EVENT)
|
||||
end
|
||||
|
||||
|
||||
function lib:PLAYER_ENTERING_WORLD ()
|
||||
if self.commScope == "INSTANCE_CHAT" then
|
||||
-- Handle moving directly from one LFG to another
|
||||
self.commScope = nil
|
||||
self:UpdateCommScope ()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- Group handling parts
|
||||
|
||||
local members = {}
|
||||
function lib:GROUP_ROSTER_UPDATE ()
|
||||
local group = self.cache
|
||||
local units = self:GroupUnits ()
|
||||
-- Find new members
|
||||
for i,unit in ipairs (self:GroupUnits ()) do
|
||||
local guid = UnitGUID (unit)
|
||||
if guid then
|
||||
members[guid] = true
|
||||
if not group[guid] then
|
||||
self:Query (unit)
|
||||
-- Update with what we have so far (guid, unit, name/class/race?)
|
||||
self.events:Fire (UPDATE_EVENT, guid, unit, self:BuildInfo (unit))
|
||||
end
|
||||
end
|
||||
end
|
||||
-- Find removed members
|
||||
for guid in pairs (group) do
|
||||
if not members[guid] then
|
||||
group[guid] = nil
|
||||
self.events:Fire (REMOVE_EVENT, guid, nil)
|
||||
end
|
||||
end
|
||||
wipe (members)
|
||||
self:UpdateCommScope ()
|
||||
end
|
||||
|
||||
|
||||
function lib:DoPlayerUpdate ()
|
||||
self:Query ("player")
|
||||
self.state.debounce_send_update = 2.5 -- Hold off 2.5sec before sending update
|
||||
self.frame:Show ()
|
||||
end
|
||||
|
||||
|
||||
function lib:SendLatestSpecData ()
|
||||
local scope = self.commScope
|
||||
if not scope then return end
|
||||
|
||||
local guid = UnitGUID ("player")
|
||||
local info = self.cache[guid]
|
||||
if not info then return end
|
||||
|
||||
-- fmt, guid, global_spec_id, talent1 -> MAX_TALENT_TIERS, pvptalent1 -> NUM_PVP_TALENT_SLOTS
|
||||
-- sequentially, allow no gaps for missing talents we decode by index on the receiving end.
|
||||
local datastr = COMMS_FMT..COMMS_DELIM..guid..COMMS_DELIM..(info.global_spec_id or 0)
|
||||
local talentCount = 1
|
||||
for k in pairs(info.talents) do
|
||||
datastr = datastr..COMMS_DELIM..k
|
||||
talentCount = talentCount + 1
|
||||
end
|
||||
for i=talentCount,MAX_TALENT_TIERS do
|
||||
datastr = datastr..COMMS_DELIM..0
|
||||
end
|
||||
talentCount = 1
|
||||
for k in pairs(info.pvp_talents) do
|
||||
datastr = datastr..COMMS_DELIM..k
|
||||
talentCount = talentCount + 1
|
||||
end
|
||||
for i=talentCount,NUM_PVP_TALENT_SLOTS do
|
||||
datastr = datastr..COMMS_DELIM..0
|
||||
end
|
||||
|
||||
--[===[@debug@
|
||||
debug ("Sending LGIST update to "..scope) --@end-debug@]===]
|
||||
SendAddonMessage(COMMS_PREFIX, datastr, scope)
|
||||
end
|
||||
|
||||
|
||||
function lib:UpdateCommScope ()
|
||||
local scope = (IsInGroup (LE_PARTY_CATEGORY_INSTANCE) and "INSTANCE_CHAT") or (IsInRaid () and "RAID") or (IsInGroup (LE_PARTY_CATEGORY_HOME) and "PARTY")
|
||||
if self.commScope ~= scope then
|
||||
self.commScope = scope
|
||||
self:DoPlayerUpdate ()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- Indicies for various parts of the split data msg
|
||||
local msg_idx = {}
|
||||
msg_idx.fmt = 1
|
||||
msg_idx.guid = msg_idx.fmt + 1
|
||||
msg_idx.global_spec_id = msg_idx.guid + 1
|
||||
msg_idx.talents = msg_idx.global_spec_id + 1
|
||||
msg_idx.end_talents = msg_idx.talents + MAX_TALENT_TIERS
|
||||
msg_idx.pvp_talents = msg_idx.end_talents + 1
|
||||
msg_idx.end_pvp_talents = msg_idx.pvp_talents + NUM_PVP_TALENT_SLOTS - 1
|
||||
|
||||
function lib:CHAT_MSG_ADDON (prefix, datastr, scope, sender)
|
||||
if prefix ~= COMMS_PREFIX or scope ~= self.commScope then return end
|
||||
--[===[@debug@
|
||||
debug ("Incoming LGIST update from "..(scope or "nil").."/"..(sender or "nil")..": "..(datastr:gsub(COMMS_DELIM,";") or "nil")) --@end-debug@]===]
|
||||
|
||||
local data = { strsplit (COMMS_DELIM,datastr) }
|
||||
local fmt = data[msg_idx.fmt]
|
||||
if fmt ~= COMMS_FMT then return end -- Unknown format, ignore
|
||||
|
||||
local guid = data[msg_idx.guid]
|
||||
|
||||
local senderguid = UnitGUID(sender)
|
||||
if senderguid and senderguid ~= guid then return end
|
||||
|
||||
local info = guid and self.cache[guid]
|
||||
if not info then return end -- Never allow random message to create new group member entries!
|
||||
|
||||
local unit = self:GuidToUnit (guid)
|
||||
if not unit then return end
|
||||
if UnitIsUnit (unit, "player") then return end -- we're already up-to-date, comment out for solo debugging
|
||||
|
||||
self.state.throttle = self.state.throttle + 1
|
||||
self.frame:Show () -- Ensure we're unthrottling
|
||||
if self.state.throttle > 40 then return end -- If we ever hit this, someone's being "funny"
|
||||
|
||||
info.class_localized, info.class, info.race_localized, info.race, info.gender, info.name, info.realm = GetPlayerInfoByGUID (guid)
|
||||
if info.realm and info.realm == "" then info.realm = nil end
|
||||
info.class_id = self.static_cache.class_to_class_id[info.class]
|
||||
|
||||
local gspecs = self.static_cache.global_specs
|
||||
|
||||
local gspec_id = data[msg_idx.global_spec_id] and tonumber (data[msg_idx.global_spec_id])
|
||||
if not gspec_id or not gspecs[gspec_id] then return end -- Malformed message, avoid throwing errors by using this nil
|
||||
|
||||
info.global_spec_id = gspec_id
|
||||
info.spec_index = gspecs[gspec_id].idx
|
||||
info.spec_name_localized = gspecs[gspec_id].name_localized
|
||||
info.spec_description = gspecs[gspec_id].description
|
||||
info.spec_icon = gspecs[gspec_id].icon
|
||||
info.spec_background = gspecs[gspec_id].background
|
||||
info.spec_role = gspecs[gspec_id].role
|
||||
info.spec_role_detailed = global_spec_id_roles_detailed[gspec_id]
|
||||
|
||||
local need_inspect = nil -- shouldn't be needed, but just in case
|
||||
info.talents = wipe (info.talents or {})
|
||||
for i = msg_idx.talents, msg_idx.end_talents do
|
||||
local talent_id = tonumber (data[i]) or 0
|
||||
if talent_id > 0 then
|
||||
local talent = self:GetCachedTalentInfoByID (talent_id)
|
||||
if talent then
|
||||
info.talents[talent_id] = talent
|
||||
else
|
||||
need_inspect = 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
info.pvp_talents = wipe (info.pvp_talents or {})
|
||||
for i = msg_idx.pvp_talents, msg_idx.end_pvp_talents do
|
||||
local talent_id = tonumber (data[i]) or 0
|
||||
if talent_id > 0 then
|
||||
local talent = self:GetCachedPvpTalentInfoByID (talent_id)
|
||||
if talent then
|
||||
info.pvp_talents[talent_id] = talent
|
||||
else
|
||||
need_inspect = 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
info.glyphs = info.glyphs or {} -- kept for addons that still refer to this
|
||||
|
||||
local mainq, staleq = self.state.mainq, self.state.staleq
|
||||
local want_inspect = not need_inspect and self.inspect_ready_used and (mainq[guid] or staleq[guid]) and 1 or nil
|
||||
mainq[guid], staleq[guid] = need_inspect, want_inspect
|
||||
if need_inspect or want_inspect then self.frame:Show () end
|
||||
|
||||
--[===[@debug@
|
||||
debug ("Firing LGIST update event for unit "..unit..", GUID "..guid..", inspect "..tostring(not not need_inspect)) --@end-debug@]===]
|
||||
self.events:Fire (UPDATE_EVENT, guid, unit, info)
|
||||
self.events:Fire (QUEUE_EVENT)
|
||||
end
|
||||
|
||||
|
||||
function lib:UNIT_LEVEL (unit)
|
||||
if UnitInRaid (unit) or UnitInParty (unit) then
|
||||
self:Refresh (unit)
|
||||
end
|
||||
if UnitIsUnit (unit, "player") then
|
||||
self:DoPlayerUpdate ()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function lib:PLAYER_TALENT_UPDATE ()
|
||||
self:DoPlayerUpdate ()
|
||||
end
|
||||
|
||||
|
||||
function lib:PLAYER_SPECIALIZATION_CHANGED (unit)
|
||||
-- This event seems to fire a lot, and for no particular reason *sigh*
|
||||
-- if UnitInRaid (unit) or UnitInParty (unit) then
|
||||
-- self:Refresh (unit)
|
||||
-- end
|
||||
if unit and UnitIsUnit (unit, "player") then
|
||||
self:DoPlayerUpdate ()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function lib:UNIT_NAME_UPDATE (unit)
|
||||
local group = self.cache
|
||||
local guid = UnitGUID (unit)
|
||||
local info = guid and group[guid]
|
||||
if info then
|
||||
self:UpdatePlayerInfo (guid, unit, info)
|
||||
if info.name ~= UNKNOWN then
|
||||
self.events:Fire (UPDATE_EVENT, guid, unit, info)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- Always get a UNIT_AURA when a unit's UnitIsVisible() changes
|
||||
function lib:UNIT_AURA (unit)
|
||||
local group = self.cache
|
||||
local guid = UnitGUID (unit)
|
||||
local info = guid and group[guid]
|
||||
if info then
|
||||
if not UnitIsUnit (unit, "player") then
|
||||
if UnitIsVisible (unit) then
|
||||
if info.not_visible then
|
||||
info.not_visible = nil
|
||||
--[===[@debug@
|
||||
debug (unit..", aka "..(UnitName(unit) or "nil")..", is now visible") --@end-debug@]===]
|
||||
if not self.state.mainq[guid] then
|
||||
self.state.staleq[guid] = 1
|
||||
self.frame:Show ()
|
||||
self.events:Fire (QUEUE_EVENT)
|
||||
end
|
||||
end
|
||||
elseif UnitIsConnected (unit) then
|
||||
--[===[@debug@
|
||||
if not info.not_visible then
|
||||
debug (unit..", aka "..(UnitName(unit) or "nil")..", is no longer visible")
|
||||
end
|
||||
--@end-debug@]===]
|
||||
info.not_visible = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function lib:UNIT_SPELLCAST_SUCCEEDED (unit, _, spell_id)
|
||||
if spell_id == 200749 then -- Activating Specialization
|
||||
self:Query (unit) -- Definitely changed, so high prio refresh
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- External library functions
|
||||
|
||||
function lib:QueuedInspections ()
|
||||
local q = {}
|
||||
for guid in pairs (self.state.mainq) do
|
||||
table.insert (q, guid)
|
||||
end
|
||||
return q
|
||||
end
|
||||
|
||||
|
||||
function lib:StaleInspections ()
|
||||
local q = {}
|
||||
for guid in pairs (self.state.staleq) do
|
||||
table.insert (q, guid)
|
||||
end
|
||||
return q
|
||||
end
|
||||
|
||||
|
||||
function lib:IsInspectQueued (guid)
|
||||
return guid and ((self.state.mainq[guid] or self.state.staleq[guid]) and true)
|
||||
end
|
||||
|
||||
|
||||
function lib:GetCachedInfo (guid)
|
||||
local group = self.cache
|
||||
return guid and group[guid]
|
||||
end
|
||||
|
||||
|
||||
function lib:Rescan (guid)
|
||||
local mainq, staleq = self.state.mainq, self.state.staleq
|
||||
if guid then
|
||||
local unit = self:GuidToUnit (guid)
|
||||
if unit then
|
||||
if UnitIsUnit (unit, "player") then
|
||||
self.events:Fire (UPDATE_EVENT, guid, "player", self:BuildInfo ("player"))
|
||||
elseif not mainq[guid] then
|
||||
staleq[guid] = 1
|
||||
end
|
||||
end
|
||||
else
|
||||
for i,unit in ipairs (self:GroupUnits ()) do
|
||||
if UnitExists (unit) then
|
||||
if UnitIsUnit (unit, "player") then
|
||||
self.events:Fire (UPDATE_EVENT, UnitGUID("player"), "player", self:BuildInfo ("player"))
|
||||
else
|
||||
local guid = UnitGUID (unit)
|
||||
if guid and not mainq[guid] then
|
||||
staleq[guid] = 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
self.frame:Show () -- Start timer if not already running
|
||||
|
||||
-- Evict any stale entries
|
||||
self:GROUP_ROSTER_UPDATE ()
|
||||
self.events:Fire (QUEUE_EVENT)
|
||||
end
|
||||
|
||||
|
||||
local unitstrings = {
|
||||
raid = { "player" }, -- This seems to be needed under certain circumstances. Odd.
|
||||
party = { "player" }, -- Player not part of partyN
|
||||
player = { "player" }
|
||||
}
|
||||
for i = 1,40 do table.insert (unitstrings.raid, "raid"..i) end
|
||||
for i = 1,4 do table.insert (unitstrings.party, "party"..i) end
|
||||
|
||||
|
||||
-- Returns an array with the set of unit ids for the current group
|
||||
function lib:GroupUnits ()
|
||||
local units
|
||||
if IsInRaid () then
|
||||
units = unitstrings.raid
|
||||
elseif GetNumSubgroupMembers () > 0 then
|
||||
units = unitstrings.party
|
||||
else
|
||||
units = unitstrings.player
|
||||
end
|
||||
return units
|
||||
end
|
||||
|
||||
|
||||
-- If demand-loaded, we need to synthesize a login event
|
||||
if IsLoggedIn () then lib:PLAYER_LOGIN () end
|
||||
@@ -1,9 +0,0 @@
|
||||
## Interface: 80300
|
||||
## Title: Lib: GroupInSpecT-1.1
|
||||
## Notes: Keeps track of group members and keeps an up-to-date cache of their specialization and talents.
|
||||
## Version: 1.4.0
|
||||
## Author: Anyia of HordeYakka (Jubei'Thos)
|
||||
## X-Category: Library
|
||||
|
||||
embeds.xml
|
||||
lib.xml
|
||||
@@ -1,5 +0,0 @@
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/..\FrameXML\UI.xsd">
|
||||
|
||||
<Script file="LibGroupInSpecT-1.1.lua"/>
|
||||
|
||||
</Ui>
|
||||
@@ -1,12 +0,0 @@
|
||||
tag 74a4893b4dd1008c1702a98bebcf0080dd1231b3 Release-80000-30
|
||||
Author: Alar of Runetotem <alar@aspide.it>
|
||||
Date: Thu Jul 19 22:46:27 2018 +0200
|
||||
|
||||
BFA
|
||||
|
||||
commit bb6dcff130a8f4298c177ef5eb5c055c905eca34
|
||||
Author: Alar of Runetotem <alar@aspide.it>
|
||||
Date: Thu Jul 19 22:39:53 2018 +0200
|
||||
|
||||
TOC bump
|
||||
|
||||
@@ -1,725 +0,0 @@
|
||||
local MAJOR, MINOR = "LibItemUpgradeInfo-1.0", 30
|
||||
local type,tonumber,select,strsplit,GetItemInfoFromHyperlink=type,tonumber,select,strsplit,GetItemInfoFromHyperlink
|
||||
local unpack,GetDetailedItemLevelInfo=unpack,GetDetailedItemLevelInfo
|
||||
local library,previous = _G.LibStub:NewLibrary(MAJOR, MINOR)
|
||||
local lib=library --#lib Needed to keep Eclipse LDT happy
|
||||
if not lib then return end
|
||||
local pp=print
|
||||
--[===[@debug@
|
||||
LoadAddOn("Blizzard_DebugTools")
|
||||
LoadAddOn("LibDebug")
|
||||
if LibDebug then LibDebug() end
|
||||
--@end-debug@]===]
|
||||
--@non-debug@
|
||||
local print=function() end
|
||||
--@end-non-debug@
|
||||
--[[
|
||||
Caching system
|
||||
1 itemName String The name of the item.
|
||||
2 itemLink String The item link of the item.
|
||||
3 itemRarity Number The quality of the item. The value is 0 to 7, which represents Poor to Heirloom. This appears to include gains from upgrades/bonuses.
|
||||
4 itemLevel Number The item level of this item, not including item levels gained from upgrades. There is currently no API to get the item level including upgrades/bonuses.
|
||||
5 itemMinLevel Number The minimum level required to use the item, 0 meaning no level requirement.
|
||||
6 itemType String The type of the item: Armor, Weapon, Quest, Key, etc.
|
||||
7 itemSubType String The sub-type of the item: Enchanting, Cloth, Sword, etc. See itemType.
|
||||
8 itemStackCount Number How many of the item per stack: 20 for Runecloth, 1 for weapon, 100 for Alterac Ram Hide, etc.
|
||||
9 itemEquipLoc String The type of inventory equipment location in which the item may be equipped, or "" if it can't be equippable. The string returned is also the name of a global string variable e.g. if "INVTYPE_WEAPONMAINHAND" is returned, _G["INVTYPE_WEAPONMAINHAND"] will be the localized, displayable name of the location.
|
||||
10 iconFileDataID Number The FileDataID for the icon texture for the item.
|
||||
11 itemSellPrice Number The price, in copper, a vendor is willing to pay for this item, 0 for items that cannot be sold.
|
||||
12 itemClassID Number This is the numerical value that determines the string to display for 'itemType'.
|
||||
13 itemSubClassID Number This is the numerical value that determines the string to display for 'itemSubType'
|
||||
14 bindType Number Item binding type: 0 - none; 1 - on pickup; 2 - on equip; 3 - on use; 4 - quest.
|
||||
15 expacID Number
|
||||
16 itemSetID Number
|
||||
17 isCraftingReagent bool
|
||||
--]]
|
||||
-- ItemLink Constants
|
||||
local i_Name=1
|
||||
local i_Link=2
|
||||
local i_Rarity=3
|
||||
local i_Quality=3
|
||||
local i_Level=4
|
||||
local i_MinLevel =5
|
||||
local i_ClassName=6
|
||||
local i_SubClassName=7
|
||||
local i_StackCount=8
|
||||
local i_EquipLoc=9
|
||||
local i_TextureId=10
|
||||
local i_SellPrice=11
|
||||
local i_ClassID=12
|
||||
local i_SubClass_ID=13
|
||||
local i_unk1=14
|
||||
local i_unk2=15
|
||||
local i_unk3=16
|
||||
local i_unk4=17
|
||||
|
||||
|
||||
do
|
||||
local oGetItemInfo=GetItemInfo
|
||||
lib.itemcache=lib.itemcache or
|
||||
setmetatable({miss=0,tot=0},{
|
||||
__index=function(table,key)
|
||||
if (not key) then return "" end
|
||||
if (key=="miss") then return 0 end
|
||||
if (key=="tot") then return 0 end
|
||||
local cached={oGetItemInfo(key)}
|
||||
if #cached==0 then return nil end
|
||||
local itemLink=cached[2]
|
||||
if not itemLink then return nil end
|
||||
local itemID=lib:GetItemID(itemLink)
|
||||
local quality=cached[3]
|
||||
local cacheIt=true
|
||||
if quality==LE_ITEM_QUALITY_ARTIFACT then
|
||||
local relic1, relic2, relic3 = select(4,strsplit(':', itemLink))
|
||||
if relic1 and relic1 ~= '' and not oGetItemInfo(relic1) then cacheIt = false end
|
||||
if relic2 and relic2 ~= '' and not oGetItemInfo(relic2) then cacheIt = false end
|
||||
if relic3 and relic3 ~= '' and not oGetItemInfo(relic3) then cacheIt = false end
|
||||
end
|
||||
cached.englishClass=GetItemClassInfo(cached[12])
|
||||
cached.englishSubClass=GetItemSubClassInfo(cached[12],cached[13])
|
||||
if cacheIt then
|
||||
rawset(table,key,cached)
|
||||
end
|
||||
table.miss=table.miss+1
|
||||
return cached
|
||||
end
|
||||
|
||||
})
|
||||
end
|
||||
local cache=lib.itemcache
|
||||
local function CachedGetItemInfo(key,index)
|
||||
if not key then return nil end
|
||||
index=index or 1
|
||||
cache.tot=cache.tot+1
|
||||
local cached=cache[key]
|
||||
if cached and type(cached)=='table' then
|
||||
return select(index,unpack(cached))
|
||||
else
|
||||
rawset(cache,key,nil) -- voiding broken cache entry
|
||||
end
|
||||
end
|
||||
|
||||
local upgradeTable = {
|
||||
[ 1] = { upgrade = 1, max = 1, ilevel = 8 },
|
||||
[373] = { upgrade = 1, max = 3, ilevel = 4 },
|
||||
[374] = { upgrade = 2, max = 3, ilevel = 8 },
|
||||
[375] = { upgrade = 1, max = 3, ilevel = 4 },
|
||||
[376] = { upgrade = 2, max = 3, ilevel = 4 },
|
||||
[377] = { upgrade = 3, max = 3, ilevel = 4 },
|
||||
[378] = { ilevel = 7 },
|
||||
[379] = { upgrade = 1, max = 2, ilevel = 4 },
|
||||
[380] = { upgrade = 2, max = 2, ilevel = 4 },
|
||||
[445] = { upgrade = 0, max = 2, ilevel = 0 },
|
||||
[446] = { upgrade = 1, max = 2, ilevel = 4 },
|
||||
[447] = { upgrade = 2, max = 2, ilevel = 8 },
|
||||
[451] = { upgrade = 0, max = 1, ilevel = 0 },
|
||||
[452] = { upgrade = 1, max = 1, ilevel = 8 },
|
||||
[453] = { upgrade = 0, max = 2, ilevel = 0 },
|
||||
[454] = { upgrade = 1, max = 2, ilevel = 4 },
|
||||
[455] = { upgrade = 2, max = 2, ilevel = 8 },
|
||||
[456] = { upgrade = 0, max = 1, ilevel = 0 },
|
||||
[457] = { upgrade = 1, max = 1, ilevel = 8 },
|
||||
[458] = { upgrade = 0, max = 4, ilevel = 0 },
|
||||
[459] = { upgrade = 1, max = 4, ilevel = 4 },
|
||||
[460] = { upgrade = 2, max = 4, ilevel = 8 },
|
||||
[461] = { upgrade = 3, max = 4, ilevel = 12 },
|
||||
[462] = { upgrade = 4, max = 4, ilevel = 16 },
|
||||
[465] = { upgrade = 0, max = 2, ilevel = 0 },
|
||||
[466] = { upgrade = 1, max = 2, ilevel = 4 },
|
||||
[467] = { upgrade = 2, max = 2, ilevel = 8 },
|
||||
[468] = { upgrade = 0, max = 4, ilevel = 0 },
|
||||
[469] = { upgrade = 1, max = 4, ilevel = 4 },
|
||||
[470] = { upgrade = 2, max = 4, ilevel = 8 },
|
||||
[471] = { upgrade = 3, max = 4, ilevel = 12 },
|
||||
[472] = { upgrade = 4, max = 4, ilevel = 16 },
|
||||
[491] = { upgrade = 0, max = 4, ilevel = 0 },
|
||||
[492] = { upgrade = 1, max = 4, ilevel = 4 },
|
||||
[493] = { upgrade = 2, max = 4, ilevel = 8 },
|
||||
[494] = { upgrade = 0, max = 6, ilevel = 0 },
|
||||
[495] = { upgrade = 1, max = 6, ilevel = 4 },
|
||||
[496] = { upgrade = 2, max = 6, ilevel = 8 },
|
||||
[497] = { upgrade = 3, max = 6, ilevel = 12 },
|
||||
[498] = { upgrade = 4, max = 6, ilevel = 16 },
|
||||
[503] = { upgrade = 3, max = 3, ilevel = 1 },
|
||||
[504] = { upgrade = 3, max = 4, ilevel = 12 },
|
||||
[505] = { upgrade = 4, max = 4, ilevel = 16 },
|
||||
[506] = { upgrade = 5, max = 6, ilevel = 20 },
|
||||
[507] = { upgrade = 6, max = 6, ilevel = 24 },
|
||||
[529] = { upgrade = 0, max = 2, ilevel = 0 },
|
||||
[530] = { upgrade = 1, max = 2, ilevel = 5 },
|
||||
[531] = { upgrade = 2, max = 2, ilevel = 10 },
|
||||
[535] = { upgrade = 1, max = 3, ilevel = 15 },
|
||||
[536] = { upgrade = 2, max = 3, ilevel = 30 },
|
||||
[537] = { upgrade = 3, max = 3, ilevel = 45 },
|
||||
[538] = { upgrade = 0, max = 3, ilevel = 0 },
|
||||
|
||||
}
|
||||
do
|
||||
local stub = { ilevel = 0 }
|
||||
setmetatable(upgradeTable, { __index = function(t, key)
|
||||
return stub
|
||||
end})
|
||||
end
|
||||
-- Tooltip Scanning stuff
|
||||
local itemLevelPattern = _G.ITEM_LEVEL:gsub("%%d", "(%%d+)")
|
||||
local soulboundPattern = _G.ITEM_SOULBOUND
|
||||
local boePattern=_G.ITEM_BIND_ON_EQUIP
|
||||
local bopPattern=_G.ITEM_BIND_ON_PICKUP
|
||||
local boaPattern1=_G.ITEM_BIND_TO_BNETACCOUNT
|
||||
local boaPattern2=_G.ITEM_BNETACCOUNTBOUND
|
||||
local patterns={
|
||||
[soulboundPattern]="soulbound",
|
||||
[boePattern]="boe",
|
||||
[bopPattern]="bop",
|
||||
[boaPattern1]="boa",
|
||||
[boaPattern2]="boa",
|
||||
}
|
||||
|
||||
local scanningTooltip
|
||||
local anchor
|
||||
lib.tipCache = lib.tipCache or setmetatable({},{__index=function(table,key) return {} end})
|
||||
local tipCache = lib.tipCache
|
||||
local emptytable={}
|
||||
|
||||
local function ScanTip(itemLink,itemLevel,show)
|
||||
if type(itemLink)=="number" then
|
||||
itemLink=CachedGetItemInfo(itemLink,2)
|
||||
if not itemLink then return emptytable end
|
||||
end
|
||||
if type(tipCache[itemLink].ilevel)=="nil"then -- or not tipCache[itemLink].cached then
|
||||
local cacheIt=true
|
||||
if not scanningTooltip then
|
||||
anchor=CreateFrame("Frame")
|
||||
anchor:Hide()
|
||||
scanningTooltip = _G.CreateFrame("GameTooltip", "LibItemUpgradeInfoTooltip", nil, "GameTooltipTemplate")
|
||||
end
|
||||
--scanningTooltip:ClearLines()
|
||||
GameTooltip_SetDefaultAnchor(scanningTooltip,anchor)
|
||||
local itemString=itemLink:match("|H(.-)|h")
|
||||
local rc,message=pcall(scanningTooltip.SetHyperlink,scanningTooltip,itemString)
|
||||
if (not rc) then
|
||||
return emptytable
|
||||
end
|
||||
scanningTooltip:Show()
|
||||
local quality,_,_,class,subclass,_,_,_,_,classIndex,subclassIndex=CachedGetItemInfo(itemLink,3)
|
||||
|
||||
-- line 1 is the item name
|
||||
-- line 2 may be the item level, or it may be a modifier like "Heroic"
|
||||
-- check up to line 6 just in case
|
||||
local ilevel,soulbound,bop,boe,boa,heirloom
|
||||
if quality==LE_ITEM_QUALITY_ARTIFACT and itemLevel then
|
||||
local relic1, relic2, relic3 = select(4,strsplit(':', itemLink))
|
||||
if relic1 and relic1 ~= '' and not CachedGetItemInfo(relic1) then cacheIt = false end
|
||||
if relic2 and relic2 ~= '' and not CachedGetItemInfo(relic2) then cacheIt = false end
|
||||
if relic3 and relic3 ~= '' and not CachedGetItemInfo(relic3) then cacheIt = false end
|
||||
ilevel=itemLevel
|
||||
end
|
||||
if show then
|
||||
for i=1,12 do
|
||||
local l, ltext = _G["LibItemUpgradeInfoTooltipTextLeft"..i], nil
|
||||
local r, rtext = _G["LibItemUpgradeInfoTooltipTextRight"..i], nil
|
||||
if l then
|
||||
ltext=l:GetText()
|
||||
rtext=r:GetText()
|
||||
_G.print(i,ltext,' - ',rtext)
|
||||
end
|
||||
end
|
||||
end
|
||||
tipCache[itemLink]={
|
||||
ilevel=nil,
|
||||
soulbound=nil,
|
||||
bop=nil,
|
||||
boe=nil,
|
||||
boa=nil,
|
||||
cached=cacheIt
|
||||
}
|
||||
local c=tipCache[itemLink]
|
||||
for i = 2, 6 do
|
||||
local label, text = _G["LibItemUpgradeInfoTooltipTextLeft"..i], nil
|
||||
if label then text=label:GetText() end
|
||||
if text then
|
||||
if show then _G.print("|cFFFFFF00".. text .. "|r") end
|
||||
if c.ilevel==nil then c.ilevel = tonumber(text:match(itemLevelPattern)) end
|
||||
for pattern,key in pairs(patterns) do
|
||||
if type(c[key])=="nil" then
|
||||
if text:find(pattern) then
|
||||
if show then _G.print(text , "matched",pattern) end
|
||||
c[key]=true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
c.ilevel=c.ilevel or itemLevel
|
||||
itemLevel=GetDetailedItemLevelInfo(itemLink)
|
||||
if type(c.ilevel)=="number" then
|
||||
c.ilevel=math.max(c.ilevel,itemLevel)
|
||||
else
|
||||
c.ilevel=itemLevel
|
||||
end
|
||||
|
||||
scanningTooltip:Hide()
|
||||
end
|
||||
return tipCache[itemLink]
|
||||
end
|
||||
|
||||
|
||||
-- GetUpgradeID(itemString)
|
||||
--
|
||||
-- Arguments:
|
||||
-- itemString - String - An itemLink or itemString denoting the item
|
||||
--
|
||||
-- Returns:
|
||||
-- Number - The upgrade ID (possibly 0), or nil if the input is invalid or
|
||||
-- does not contain upgrade info
|
||||
function lib:GetUpgradeID(itemString)
|
||||
if type(itemString)~="string" then return end
|
||||
local itemString = itemString:match("item[%-?%d:]+") or ""-- Standardize itemlink to itemstring
|
||||
local instaid, _, numBonuses, affixes = select(12, strsplit(":", itemString, 15))
|
||||
instaid=tonumber(instaid) or 7
|
||||
numBonuses=tonumber(numBonuses) or 0
|
||||
if instaid >0 and (instaid-4)%8==0 then
|
||||
return tonumber((select(numBonuses + 1, strsplit(":", affixes))))
|
||||
end
|
||||
end
|
||||
|
||||
-- GetCurrentUpgrade(id)
|
||||
--
|
||||
-- Returns the current upgrade level of the item, e.g. 1 for a 1/2 item.
|
||||
--
|
||||
-- Arguments:
|
||||
-- id - Number - The upgrade ID of the item (obtained via GetUpgradeID())
|
||||
--
|
||||
-- Returns:
|
||||
-- Number - The current upgrade level of the item. Returns nil if the item
|
||||
-- cannot be upgraded
|
||||
function lib:GetCurrentUpgrade(id)
|
||||
return upgradeTable[id].upgrade
|
||||
end
|
||||
|
||||
-- GetMaximumUpgrade(id)
|
||||
--
|
||||
-- Returns the maximum upgrade level of the item, e.g. 2 for a 1/2 item.
|
||||
--
|
||||
-- Arguments:
|
||||
-- id - Number - The upgrade ID of the item (obtained via GetUpgradeID())
|
||||
--
|
||||
-- Returns:
|
||||
-- Number - The maximum upgrade level of the item. Returns nil if the item
|
||||
-- cannot be upgraded
|
||||
function lib:GetMaximumUpgrade(id)
|
||||
return upgradeTable[id].max
|
||||
end
|
||||
|
||||
-- GetItemLevelUpgrade(id)
|
||||
--
|
||||
-- Returns the item level increase that this upgrade is worth, e.g. 4 for a
|
||||
-- 1/2 item or 8 for a 2/2 item.
|
||||
--
|
||||
-- Arguments:
|
||||
-- id - Number - The upgrade ID of the item (obtained via GetUpgradeID())
|
||||
--
|
||||
-- Returns:
|
||||
-- Number - The item level increase of the item. Returns 0 if the item
|
||||
-- cannot be or has not been upgraded
|
||||
function lib:GetItemLevelUpgrade(id)
|
||||
return upgradeTable[id].ilevel
|
||||
end
|
||||
|
||||
-- GetItemUpgradeInfo(itemString)
|
||||
--
|
||||
-- Returns the current upgrade level, maximum upgrade level, and item level
|
||||
-- increase for an item.
|
||||
--
|
||||
-- Arguments:
|
||||
-- itemString - String - An itemLink or itemString denoting the item
|
||||
--
|
||||
-- Returns if the item can be upgraded:
|
||||
-- Number - The current upgrade level of the item
|
||||
-- Number - The maximum upgrade level of the item
|
||||
-- Number - The item level increase of the item
|
||||
-- or if the item cannot be upgraded:
|
||||
-- nil
|
||||
-- nil
|
||||
-- 0
|
||||
-- or if the item is invalid or does not contain upgrade info:
|
||||
-- nil
|
||||
function lib:GetItemUpgradeInfo(itemString)
|
||||
local id = self:GetUpgradeID(itemString)
|
||||
if id then
|
||||
local cur = self:GetCurrentUpgrade(id)
|
||||
local max = self:GetMaximumUpgrade(id)
|
||||
local delta = self:GetItemLevelUpgrade(id)
|
||||
return cur, max, delta
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
-- GetHeirloomTrueLevel(itemString)
|
||||
--
|
||||
-- Returns the true item level for an heirloom (actually, returns the true level for any adapting item)
|
||||
--
|
||||
-- Arguments:
|
||||
-- itemString - String - An itemLink or itemString denoting the item
|
||||
--
|
||||
-- Returns:
|
||||
-- Number, Boolean - The true item level of the item. If the item is not
|
||||
-- an heirloom, or an error occurs when trying to scan the
|
||||
-- item tooltip, the second return value is false. Otherwise
|
||||
-- the second return value is true. If the input is invalid,
|
||||
-- (nil, false) is returned.
|
||||
-- Convert the ITEM_LEVEL constant into a pattern for our use
|
||||
function lib:GetHeirloomTrueLevel(itemString)
|
||||
if type(itemString) ~= "string" then return nil,false end
|
||||
local _, itemLink, rarity, itemLevel = CachedGetItemInfo(itemString)
|
||||
if (not itemLink) then
|
||||
return nil,false
|
||||
end
|
||||
local rc=ScanTip(itemLink,itemLevel)
|
||||
if rc.ilevel then
|
||||
return rc.ilevel,true
|
||||
end
|
||||
return itemLevel, false
|
||||
end
|
||||
|
||||
-- GetUpgradedItemLevel(itemString)
|
||||
--
|
||||
-- Returns the true item level of the item, including upgrades and heirlooms.
|
||||
--
|
||||
-- Arguments:
|
||||
-- itemString - String - An itemLink or itemString denoting the item
|
||||
--
|
||||
-- Returns:
|
||||
-- Number - The true item level of the item, or nil if the input is invalid
|
||||
function lib:GetUpgradedItemLevel(itemString)
|
||||
-- check for heirlooms first
|
||||
local ilvl, isTrue = self:GetHeirloomTrueLevel(itemString)
|
||||
if isTrue then
|
||||
return ilvl
|
||||
end
|
||||
-- not an heirloom? fall back to the regular item logic
|
||||
local id = self:GetUpgradeID(itemString)
|
||||
if ilvl and id then
|
||||
ilvl = ilvl + self:GetItemLevelUpgrade(id)
|
||||
end
|
||||
return ilvl
|
||||
end
|
||||
|
||||
-- IsBop(itemString)
|
||||
--
|
||||
-- Check an item for Bind On Pickup.
|
||||
--
|
||||
-- Arguments:
|
||||
-- itemString - String - An itemLink or itemString denoting the item
|
||||
--
|
||||
-- Returns:
|
||||
-- Boolean - True if Bind On Pickup
|
||||
|
||||
function lib:IsBop(itemString)
|
||||
local rc=ScanTip(itemString)
|
||||
return rc.bop
|
||||
end
|
||||
-- IsBoe(itemString)
|
||||
--
|
||||
-- Check an item for Bind On Equip.
|
||||
--
|
||||
-- Arguments:
|
||||
-- itemString - String - An itemLink or itemString denoting the item
|
||||
--
|
||||
-- Returns:
|
||||
-- Boolean - True if Bind On Equip
|
||||
|
||||
function lib:IsBoe(itemString)
|
||||
local rc=ScanTip(itemString)
|
||||
return rc.boe
|
||||
end
|
||||
-- IsBoa(itemString)
|
||||
--
|
||||
-- Check an item for Bind On Aaccount
|
||||
--
|
||||
-- Arguments:
|
||||
-- itemString - String - An itemLink or itemString denoting the item
|
||||
--
|
||||
-- Returns:
|
||||
-- Boolean - True if Bind On Equip
|
||||
|
||||
function lib:IsBoa(itemString)
|
||||
local rc=ScanTip(itemString)
|
||||
return rc.boa
|
||||
end
|
||||
|
||||
-- IsArtifact(itemString)
|
||||
--
|
||||
-- Check an item for Heirloom
|
||||
--
|
||||
-- Arguments:
|
||||
-- itemString - String - An itemLink or itemString denoting the item
|
||||
--
|
||||
-- Returns:
|
||||
-- Boolean - True if Artifact
|
||||
|
||||
function lib:IsArtifact(itemString)
|
||||
return CachedGetItemInfo(itemString,i_Quality)==LE_ITEM_QUALITY_ARTIFACT
|
||||
end
|
||||
|
||||
-- GetClassInfoIsHeirloom(itemString)
|
||||
--
|
||||
-- Retrieve class and subclass
|
||||
--
|
||||
-- Arguments:
|
||||
-- itemString - String - An itemLink or itemString denoting the item
|
||||
--
|
||||
-- Returns:
|
||||
-- class,subclass
|
||||
|
||||
|
||||
function lib:GetClassInfo(itemString)
|
||||
local rc=ScantTip(itemString)
|
||||
return rc.class,rc.subclass
|
||||
end
|
||||
|
||||
|
||||
-- IsHeirloom(itemString)
|
||||
--
|
||||
-- Check an item for Heirloom
|
||||
--
|
||||
-- Arguments:
|
||||
-- itemString - String - An itemLink or itemString denoting the item
|
||||
--
|
||||
-- Returns:
|
||||
-- Boolean - True if Heirloom
|
||||
|
||||
function lib:IsHeirloom(itemString)
|
||||
return CachedGetItemInfo(itemString,i_Quality) ==LE_ITEM_QUALITY_HEIRLOOM
|
||||
end
|
||||
---
|
||||
-- Parses an itemlink and returns itemId without calling API again
|
||||
-- @param #lib self
|
||||
-- @param #string itemlink
|
||||
-- @return #number itemId or 0
|
||||
function lib:GetItemID(itemlink)
|
||||
if (type(itemlink)=="string") then
|
||||
local itemid,context=GetItemInfoFromHyperlink(itemlink)
|
||||
return tonumber(itemid) or 0
|
||||
--return tonumber(itemlink:match("Hitem:(%d+):")) or 0
|
||||
else
|
||||
return 0
|
||||
end
|
||||
end
|
||||
|
||||
---
|
||||
--
|
||||
-- Returns a caching version of GetItemInfo. Can be used to override the original one.
|
||||
-- Adds a second parameter to directly retrieving a specific value
|
||||
-- (Note: internally uses select so it's actually like calling select(n,GetItemInfo(itemID))
|
||||
--
|
||||
-- Arguments:
|
||||
-- self #lib self
|
||||
--
|
||||
-- Returns:
|
||||
-- #function The new function
|
||||
|
||||
--@do-not-package--
|
||||
local slots={
|
||||
INVSLOT_AMMO = INVSLOT_AMMO,
|
||||
INVSLOT_HEAD = INVSLOT_HEAD,
|
||||
INVSLOT_NECK = INVSLOT_NECK,
|
||||
INVSLOT_SHOULDER = INVSLOT_SHOULDER,
|
||||
INVSLOT_BODY = INVSLOT_BODY,
|
||||
INVSLOT_CHEST = INVSLOT_CHEST,
|
||||
INVSLOT_WAIST = INVSLOT_WAIST,
|
||||
INVSLOT_LEGS = INVSLOT_LEGS,
|
||||
INVSLOT_FEET = INVSLOT_FEET,
|
||||
INVSLOT_WRIST = INVSLOT_WRIST,
|
||||
INVSLOT_HAND = INVSLOT_HAND,
|
||||
INVSLOT_FINGER1 = INVSLOT_FINGER1,
|
||||
INVSLOT_FINGER2 = INVSLOT_FINGER2,
|
||||
INVSLOT_TRINKET1 = INVSLOT_TRINKET1,
|
||||
INVSLOT_TRINKET2 = INVSLOT_TRINKET2,
|
||||
INVSLOT_BACK = INVSLOT_BACK,
|
||||
INVSLOT_MAINHAND = INVSLOT_MAINHAND,
|
||||
INVSLOT_OFFHAND = INVSLOT_OFFHAND,
|
||||
INVSLOT_RANGED = INVSLOT_RANGED,
|
||||
INVSLOT_TABARD = INVSLOT_TABARD,
|
||||
}
|
||||
local INVSLOT_FIRST_EQUIPPED = INVSLOT_FIRST_EQUIPPED;
|
||||
local INVSLOT_LAST_EQUIPPED = INVSLOT_LAST_EQUIPPED
|
||||
_G.SLASH_CHECKSLOT1="/checkslot"
|
||||
SlashCmdList['CHECKSLOT'] = function(args,chatframe)
|
||||
_G.print(args)
|
||||
local slot=strsplit(' ',args)
|
||||
if not slot or slot=="" then
|
||||
DevTools_Dump(slots)
|
||||
return
|
||||
end
|
||||
slot=tonumber(slot)
|
||||
local itemlink=GetInventoryItemLink("player",slot)
|
||||
if itemlink then
|
||||
for k,v in pairs(slots) do
|
||||
if slot==v then _G.print("Item in " , k) break end
|
||||
end
|
||||
_G.print(itemlink)
|
||||
DevTools_Dump({GetDetailedItemLevelInfo(itemlink)})
|
||||
print(itemlink)
|
||||
_G.print(lib:ScanTip(itemlink))
|
||||
end
|
||||
end
|
||||
function lib:ScanTip(itemLink)
|
||||
--self.itemcache[itemLink]=nil
|
||||
self.tipCache[itemLink]=nil
|
||||
local GameTooltip=_G.LibItemUpgradeInfoTooltip
|
||||
if GameTooltip then
|
||||
GameTooltip_SetDefaultAnchor(GameTooltip, UIParent)
|
||||
GameTooltip:SetHyperlink(itemLink)
|
||||
GameTooltip:Show()
|
||||
end
|
||||
return ScanTip(itemLink,100,true)
|
||||
end
|
||||
function lib:GetCachingGetItemInfo()
|
||||
return CachedGetItemInfo
|
||||
end
|
||||
function lib:GetCacheStats()
|
||||
local c=lib.itemcache
|
||||
local h=c.tot-c.miss
|
||||
local perc=( h>0) and h/c.tot*100 or 0
|
||||
return c.miss,h,perc
|
||||
end
|
||||
function lib:GetCache()
|
||||
return lib.itemcache
|
||||
end
|
||||
function lib:CleanCache()
|
||||
return wipe(lib.itemcache)
|
||||
end
|
||||
|
||||
--[===========[ ]===========]
|
||||
--[===[ Debug utilities ]===]
|
||||
--[===========[ ]===========]
|
||||
|
||||
local function compareTables(t1, t2)
|
||||
local seen = {}
|
||||
for k, v1 in pairs(t1) do
|
||||
seen[k] = true
|
||||
local v2 = rawget(t2, k)
|
||||
if not v2 then return false end
|
||||
if type(v1) ~= type(v2) then return false end
|
||||
if type(v1) == "table" then
|
||||
if not compareTables(v1, v2) then return false end
|
||||
elseif v1 ~= v2 then return false end
|
||||
end
|
||||
for k in pairs(t2) do
|
||||
if not seen[k] then return false end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
-- prints the table rows in red and green
|
||||
-- omits the lead { and the trailing }
|
||||
local function printDiffTable(t1, t2)
|
||||
local keys, seen = {}, {}
|
||||
for k in pairs(t1) do
|
||||
keys[#keys+1] = k
|
||||
seen[k] = true
|
||||
end
|
||||
for k in pairs(t2) do
|
||||
if not seen[k] then
|
||||
keys[#keys+1] = k
|
||||
end
|
||||
end
|
||||
table.sort(keys)
|
||||
local function formatTable(t)
|
||||
local comps = {}
|
||||
for k, v in pairs(t) do
|
||||
comps[#comps+1] = ("%s = %d"):format(k, v)
|
||||
end
|
||||
return "{ " .. table.concat(comps, ", ") .. " }"
|
||||
end
|
||||
for _, k in ipairs(keys) do
|
||||
local v1, v2 = rawget(t1, k), rawget(t2, k)
|
||||
local equal
|
||||
if type(v1) == "table" and type(v2) == "table" then equal = compareTables(v1, v2)
|
||||
else equal = v1 == v2 end
|
||||
if not equal then
|
||||
if v1 then
|
||||
pp(("|cffff0000 [%d] = %s,|r"):format(k, formatTable(v1)))
|
||||
end
|
||||
if v2 then
|
||||
pp(("|cff00ff00 [%d] = %s,|r"):format(k, formatTable(v2)))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Scans the first 10000 upgrade IDs
|
||||
-- Run this with /run LibStub:GetLibrary("LibItemUpgradeInfo-1.0"):_CheckUpgradeTable()
|
||||
-- If you don't have Aspirant's Staff of Harmony cached it may error out, just try again.
|
||||
do
|
||||
local debugFrame
|
||||
local worker
|
||||
local newTable
|
||||
local debugTooltip
|
||||
function lib:_CheckUpgradeTable(itemLink)
|
||||
if worker then
|
||||
pp("|cffff0000LibItemUpgradeInfo-1.0: upgrade check already in progress")
|
||||
return
|
||||
end
|
||||
if not debugFrame then
|
||||
debugFrame = _G.CreateFrame("frame")
|
||||
debugFrame:Hide()
|
||||
debugFrame:SetScript("OnUpdate", function()
|
||||
local ok, result, count, max = pcall(worker)
|
||||
if not ok or result then
|
||||
debugFrame:Hide()
|
||||
worker = nil
|
||||
end
|
||||
if not ok then
|
||||
pp("|cffff0000LibItemUpgradeInfo-1.0 error: " .. result .. "|r")
|
||||
elseif result then
|
||||
pp("LibItemUpgradeInfo-1.0: scan complete")
|
||||
if compareTables(upgradeTable, newTable) then
|
||||
pp("LibItemUpgradeInfo-1.0: |cff00ff00No changes|r")
|
||||
else
|
||||
pp("LibItemUpgradeInfo-1.0: |cffff0000New table:|r {")
|
||||
printDiffTable(upgradeTable, newTable)
|
||||
pp("}")
|
||||
end
|
||||
else
|
||||
pp("LibItemUpgradeInfo-1.0: scanning " .. count .. "/" .. max)
|
||||
end
|
||||
end)
|
||||
end
|
||||
if not debugTooltip then
|
||||
debugTooltip = _G.CreateFrame("GameTooltip", "LibItemUpgradeInfoDebugTooltip", nil, "GameTooltipTemplate")
|
||||
debugTooltip:SetOwner(_G.WorldFrame, "ANCHOR_NONE")
|
||||
end
|
||||
newTable = {}
|
||||
--local itemLink = "|cff0070dd|Hitem:89551:0:0:0:0:0:0:0:90:253:0:0:1:0|h[Aspirant's Staff of Harmony]|h|r"
|
||||
local itemLink = itemLink or "|cff0070dd|Hitem:89551:0:0:0:0:0:0:0:100:253:4:0:0:0|h[Aspirant's Staff of Harmony]|h|r"
|
||||
-- Livello è il 9,upgradeid il 14. Al decimo posto, un valore che deve essere 4 o 4+n *8) per far scattare l'uso dell'upgradeid
|
||||
local itemLevel = select(4, _G.GetItemInfo(itemLink))
|
||||
assert(itemLevel, "Can't find item level for itemLink")
|
||||
local count, max, batchsize = 0, 10000, 200
|
||||
worker = function()
|
||||
for i = count, math.min(max, count+batchsize) do
|
||||
local link = itemLink:gsub("%d+|h", i.."|h")
|
||||
debugTooltip:ClearLines()
|
||||
debugTooltip:SetHyperlink(link)
|
||||
local upgrade, max
|
||||
local curLevel, maxLevel = _G.LibItemUpgradeInfoDebugTooltipTextLeft3:GetText():match("^Upgrade Level: (%d+)/(%d+)")
|
||||
local ilvl = tonumber(_G.LibItemUpgradeInfoDebugTooltipTextLeft2:GetText():match("Item Level (%d+)"))
|
||||
if not ilvl then
|
||||
ilvl = tonumber(_G.LibItemUpgradeInfoDebugTooltipTextLeft3:GetText():match("Item Level (%d+)"))
|
||||
end
|
||||
assert(ilvl ~= nil, "Can't find ItemLevel in tooltip: " .. _G.LibItemUpgradeInfoDebugTooltipTextLeft2:GetText())
|
||||
if curLevel or maxLevel or ilvl ~= itemLevel then
|
||||
newTable[i] = { upgrade = tonumber(curLevel), max = tonumber(maxLevel), ilevel = ilvl - itemLevel }
|
||||
end
|
||||
end
|
||||
count = count + batchsize
|
||||
return (count > max), count, max
|
||||
end
|
||||
debugFrame:Show()
|
||||
end
|
||||
end
|
||||
--@end-do-not-package--
|
||||
|
||||
-- vim: set noet sw=4 ts=4:
|
||||
@@ -1,9 +0,0 @@
|
||||
## Interface: 80000
|
||||
## Title: Lib: ItemUpgradeInfo-1.0
|
||||
## Notes: Database of item upgrade IDs
|
||||
## Author: eridius
|
||||
## Version: Release-80000-30 70200
|
||||
## X-Revision: bb6dcff
|
||||
## X-Category: Library
|
||||
|
||||
LibItemUpgradeInfo-1.0.xml
|
||||
@@ -1,4 +0,0 @@
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/..\FrameXML\UI.xsd">
|
||||
<Script file="LibStub\LibStub.lua"/>
|
||||
<Script file="Core.lua"/>
|
||||
</Ui>
|
||||
@@ -1,51 +0,0 @@
|
||||
-- $Id: LibStub.lua 76 2007-09-03 01:50:17Z mikk $
|
||||
-- LibStub is a simple versioning stub meant for use in Libraries. http://www.wowace.com/wiki/LibStub for more info
|
||||
-- LibStub is hereby placed in the Public Domain
|
||||
-- Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke
|
||||
local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2 -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS!
|
||||
local LibStub = _G[LIBSTUB_MAJOR]
|
||||
|
||||
-- Check to see is this version of the stub is obsolete
|
||||
if not LibStub or LibStub.minor < LIBSTUB_MINOR then
|
||||
LibStub = LibStub or {libs = {}, minors = {} }
|
||||
_G[LIBSTUB_MAJOR] = LibStub
|
||||
LibStub.minor = LIBSTUB_MINOR
|
||||
|
||||
-- LibStub:NewLibrary(major, minor)
|
||||
-- major (string) - the major version of the library
|
||||
-- minor (string or number ) - the minor version of the library
|
||||
--
|
||||
-- returns nil if a newer or same version of the lib is already present
|
||||
-- returns empty library object or old library object if upgrade is needed
|
||||
function LibStub:NewLibrary(major, minor)
|
||||
assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)")
|
||||
minor = assert(tonumber(strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.")
|
||||
|
||||
local oldminor = self.minors[major]
|
||||
if oldminor and oldminor >= minor then return nil end
|
||||
self.minors[major], self.libs[major] = minor, self.libs[major] or {}
|
||||
return self.libs[major], oldminor
|
||||
end
|
||||
|
||||
-- LibStub:GetLibrary(major, [silent])
|
||||
-- major (string) - the major version of the library
|
||||
-- silent (boolean) - if true, library is optional, silently return nil if its not found
|
||||
--
|
||||
-- throws an error if the library can not be found (except silent is set)
|
||||
-- returns the library object if found
|
||||
function LibStub:GetLibrary(major, silent)
|
||||
if not self.libs[major] and not silent then
|
||||
error(("Cannot find a library instance of %q."):format(tostring(major)), 2)
|
||||
end
|
||||
return self.libs[major], self.minors[major]
|
||||
end
|
||||
|
||||
-- LibStub:IterateLibraries()
|
||||
--
|
||||
-- Returns an iterator for the currently registered libraries
|
||||
function LibStub:IterateLibraries()
|
||||
return pairs(self.libs)
|
||||
end
|
||||
|
||||
setmetatable(LibStub, { __call = LibStub.GetLibrary })
|
||||
end
|
||||
@@ -1,9 +0,0 @@
|
||||
## Interface: 70200
|
||||
## Title: Lib: LibStub
|
||||
## Notes: Universal Library Stub
|
||||
## Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel
|
||||
## X-Website: http://www.wowace.com/addons/libstub/
|
||||
## X-Category: Library
|
||||
## X-License: Public Domain
|
||||
|
||||
LibStub.lua
|
||||
@@ -1,41 +0,0 @@
|
||||
debugstack = debug.traceback
|
||||
strmatch = string.match
|
||||
|
||||
loadfile("../LibStub.lua")()
|
||||
|
||||
local lib, oldMinor = LibStub:NewLibrary("Pants", 1) -- make a new thingy
|
||||
assert(lib) -- should return the library table
|
||||
assert(not oldMinor) -- should not return the old minor, since it didn't exist
|
||||
|
||||
-- the following is to create data and then be able to check if the same data exists after the fact
|
||||
function lib:MyMethod()
|
||||
end
|
||||
local MyMethod = lib.MyMethod
|
||||
lib.MyTable = {}
|
||||
local MyTable = lib.MyTable
|
||||
|
||||
local newLib, newOldMinor = LibStub:NewLibrary("Pants", 1) -- try to register a library with the same version, should silently fail
|
||||
assert(not newLib) -- should not return since out of date
|
||||
|
||||
local newLib, newOldMinor = LibStub:NewLibrary("Pants", 0) -- try to register a library with a previous, should silently fail
|
||||
assert(not newLib) -- should not return since out of date
|
||||
|
||||
local newLib, newOldMinor = LibStub:NewLibrary("Pants", 2) -- register a new version
|
||||
assert(newLib) -- library table
|
||||
assert(rawequal(newLib, lib)) -- should be the same reference as the previous
|
||||
assert(newOldMinor == 1) -- should return the minor version of the previous version
|
||||
|
||||
assert(rawequal(lib.MyMethod, MyMethod)) -- verify that values were saved
|
||||
assert(rawequal(lib.MyTable, MyTable)) -- verify that values were saved
|
||||
|
||||
local newLib, newOldMinor = LibStub:NewLibrary("Pants", "Blah 3 Blah") -- register a new version with a string minor version (instead of a number)
|
||||
assert(newLib) -- library table
|
||||
assert(newOldMinor == 2) -- previous version was 2
|
||||
|
||||
local newLib, newOldMinor = LibStub:NewLibrary("Pants", "Blah 4 and please ignore 15 Blah") -- register a new version with a string minor version (instead of a number)
|
||||
assert(newLib)
|
||||
assert(newOldMinor == 3) -- previous version was 3 (even though it gave a string)
|
||||
|
||||
local newLib, newOldMinor = LibStub:NewLibrary("Pants", 5) -- register a new library, using a normal number instead of a string
|
||||
assert(newLib)
|
||||
assert(newOldMinor == 4) -- previous version was 4 (even though it gave a string)
|
||||
@@ -1,27 +0,0 @@
|
||||
debugstack = debug.traceback
|
||||
strmatch = string.match
|
||||
|
||||
loadfile("../LibStub.lua")()
|
||||
|
||||
for major, library in LibStub:IterateLibraries() do
|
||||
-- check that MyLib doesn't exist yet, by iterating through all the libraries
|
||||
assert(major ~= "MyLib")
|
||||
end
|
||||
|
||||
assert(not LibStub:GetLibrary("MyLib", true)) -- check that MyLib doesn't exist yet by direct checking
|
||||
assert(not pcall(LibStub.GetLibrary, LibStub, "MyLib")) -- don't silently fail, thus it should raise an error.
|
||||
local lib = LibStub:NewLibrary("MyLib", 1) -- create the lib
|
||||
assert(lib) -- check it exists
|
||||
assert(rawequal(LibStub:GetLibrary("MyLib"), lib)) -- verify that :GetLibrary("MyLib") properly equals the lib reference
|
||||
|
||||
assert(LibStub:NewLibrary("MyLib", 2)) -- create a new version
|
||||
|
||||
local count=0
|
||||
for major, library in LibStub:IterateLibraries() do
|
||||
-- check that MyLib exists somewhere in the libraries, by iterating through all the libraries
|
||||
if major == "MyLib" then -- we found it!
|
||||
count = count +1
|
||||
assert(rawequal(library, lib)) -- verify that the references are equal
|
||||
end
|
||||
end
|
||||
assert(count == 1) -- verify that we actually found it, and only once
|
||||
@@ -1,14 +0,0 @@
|
||||
debugstack = debug.traceback
|
||||
strmatch = string.match
|
||||
|
||||
loadfile("../LibStub.lua")()
|
||||
|
||||
local proxy = newproxy() -- non-string
|
||||
|
||||
assert(not pcall(LibStub.NewLibrary, LibStub, proxy, 1)) -- should error, proxy is not a string, it's userdata
|
||||
local success, ret = pcall(LibStub.GetLibrary, proxy, true)
|
||||
assert(not success or not ret) -- either error because proxy is not a string or because it's not actually registered.
|
||||
|
||||
assert(not pcall(LibStub.NewLibrary, LibStub, "Something", "No number in here")) -- should error, minor has no string in it.
|
||||
|
||||
assert(not LibStub:GetLibrary("Something", true)) -- shouldn't've created it from the above statement
|
||||
@@ -1,41 +0,0 @@
|
||||
debugstack = debug.traceback
|
||||
strmatch = string.match
|
||||
|
||||
loadfile("../LibStub.lua")()
|
||||
|
||||
|
||||
-- Pretend like loaded libstub is old and doesn't have :IterateLibraries
|
||||
assert(LibStub.minor)
|
||||
LibStub.minor = LibStub.minor - 0.0001
|
||||
LibStub.IterateLibraries = nil
|
||||
|
||||
loadfile("../LibStub.lua")()
|
||||
|
||||
assert(type(LibStub.IterateLibraries)=="function")
|
||||
|
||||
|
||||
-- Now pretend that we're the same version -- :IterateLibraries should NOT be re-created
|
||||
LibStub.IterateLibraries = 123
|
||||
|
||||
loadfile("../LibStub.lua")()
|
||||
|
||||
assert(LibStub.IterateLibraries == 123)
|
||||
|
||||
|
||||
-- Now pretend that a newer version is loaded -- :IterateLibraries should NOT be re-created
|
||||
LibStub.minor = LibStub.minor + 0.0001
|
||||
|
||||
loadfile("../LibStub.lua")()
|
||||
|
||||
assert(LibStub.IterateLibraries == 123)
|
||||
|
||||
|
||||
-- Again with a huge number
|
||||
LibStub.minor = LibStub.minor + 1234567890
|
||||
|
||||
loadfile("../LibStub.lua")()
|
||||
|
||||
assert(LibStub.IterateLibraries == 123)
|
||||
|
||||
|
||||
print("OK")
|
||||
@@ -13,10 +13,7 @@
|
||||
<Script file="LibDBIcon-1.0\LibDBIcon-1.0.lua"/>
|
||||
<Script file="LibGraph-2.0\LibGraph-2.0.lua"/>
|
||||
<Script file="LibWindow-1.1\LibWindow-1.1.lua"/>
|
||||
<Include file="LibCompress\lib.xml"/>
|
||||
<Include file="LibDeflate\lib.xml"/>
|
||||
<Include file="LibItemUpgradeInfo-1.0\LibItemUpgradeInfo-1.0.xml"/>
|
||||
<!-- <Include file="LibGroupInSpecT-1.1\lib.xml"/> temp disabled due to classic-->
|
||||
<Include file="LibOpenRaid\lib.xml"/>
|
||||
<Include file="DF\load.xml"/>
|
||||
<Include file="LibTranslit\LibTranslit-1.0.xml"/>
|
||||
|
||||
+3
-53
@@ -10,16 +10,6 @@ local GetNumGroupMembers = GetNumGroupMembers
|
||||
|
||||
local CONST_INSPECT_ACHIEVEMENT_DISTANCE = 1 --Compare Achievements, 28 yards
|
||||
|
||||
local ItemUpgradeInfo = LibStub ("LibItemUpgradeInfo-1.0")
|
||||
--local LibGroupInSpecT = LibStub ("LibGroupInSpecT-1.1") --disabled due to classic wow
|
||||
local ItemUpgradeInfo
|
||||
local LibGroupInSpecT
|
||||
|
||||
if (DetailsFramework.IsTimewalkWoW()) then
|
||||
ItemUpgradeInfo = false
|
||||
LibGroupInSpecT = false
|
||||
end
|
||||
|
||||
local storageDebug = false --remember to turn this to false!
|
||||
local store_instances = _detalhes.InstancesToStoreData
|
||||
|
||||
@@ -1921,13 +1911,8 @@ function ilvl_core:CalcItemLevel (unitid, guid, shout)
|
||||
if (item) then
|
||||
local _, _, itemRarity, iLevel, _, _, _, _, equipSlot = GetItemInfo (item)
|
||||
if (iLevel) then
|
||||
if (ItemUpgradeInfo) then
|
||||
local ilvl = ItemUpgradeInfo:GetUpgradedItemLevel (item)
|
||||
item_level = item_level + (ilvl or iLevel)
|
||||
else
|
||||
item_level = item_level + iLevel
|
||||
end
|
||||
|
||||
item_level = item_level + iLevel
|
||||
|
||||
--> 16 = main hand 17 = off hand
|
||||
--> if using a two-hand, ignore the off hand slot
|
||||
if (equip_id == 16 and two_hand [equipSlot]) then
|
||||
@@ -2301,36 +2286,6 @@ function _detalhes:GetSpecFromSerial (guid)
|
||||
return _detalhes.cached_specs [guid]
|
||||
end
|
||||
|
||||
if (LibGroupInSpecT) then
|
||||
function _detalhes:LibGroupInSpecT_UpdateReceived (event, guid, unitid, info)
|
||||
--> update talents
|
||||
local talents = _detalhes.cached_talents [guid] or {}
|
||||
local i = 1
|
||||
for talentId, _ in pairs (info.talents) do
|
||||
talents [i] = talentId
|
||||
i = i + 1
|
||||
end
|
||||
_detalhes.cached_talents [guid] = talents
|
||||
|
||||
if (_detalhes.debug) then
|
||||
_detalhes:Msg ("(debug) received GroupInSpecT_Update from user", guid)
|
||||
end
|
||||
|
||||
--> update spec
|
||||
if (info.global_spec_id and info.global_spec_id ~= 0) then
|
||||
if (not _detalhes.class_specs_coords [info.global_spec_id]) then
|
||||
print ("Details! Spec Id Invalid:", info.global_spec_id, info.name)
|
||||
else
|
||||
_detalhes.cached_specs [guid] = info.global_spec_id
|
||||
end
|
||||
end
|
||||
|
||||
--print ("LibGroupInSpecT Received from", info.name, info.global_spec_id)
|
||||
end
|
||||
LibGroupInSpecT.RegisterCallback (_detalhes, "GroupInSpecT_Update", "LibGroupInSpecT_UpdateReceived")
|
||||
end
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------------------------------------------------------------------
|
||||
--compress data
|
||||
|
||||
@@ -2511,12 +2466,7 @@ if (DetailsFramework.IsTBCWow()) then
|
||||
if (item) then
|
||||
local _, _, itemRarity, iLevel, _, _, _, _, equipSlot = GetItemInfo(item)
|
||||
if (iLevel) then
|
||||
if (ItemUpgradeInfo) then
|
||||
local ilvl = ItemUpgradeInfo:GetUpgradedItemLevel (item)
|
||||
item_level = item_level + (ilvl or iLevel)
|
||||
else
|
||||
item_level = item_level + iLevel
|
||||
end
|
||||
item_level = item_level + iLevel
|
||||
|
||||
--> 16 = main hand 17 = off hand
|
||||
--> if using a two-hand, ignore the off hand slot
|
||||
|
||||
+2
-11
@@ -1168,8 +1168,6 @@ function SlashCmdList.DETAILS (msg, editbox)
|
||||
["INVTYPE_RANGEDRIGHT"] = true,
|
||||
}
|
||||
|
||||
local ItemUpgradeInfo = LibStub ("LibItemUpgradeInfo-1.0")
|
||||
|
||||
_detalhes:Msg ("======== Item Level Debug ========")
|
||||
|
||||
for equip_id = 1, 17 do
|
||||
@@ -1178,15 +1176,8 @@ function SlashCmdList.DETAILS (msg, editbox)
|
||||
if (item) then
|
||||
local _, _, itemRarity, iLevel, _, _, _, _, equipSlot = GetItemInfo (item)
|
||||
if (iLevel) then
|
||||
if (ItemUpgradeInfo) then
|
||||
local ilvl = ItemUpgradeInfo:GetUpgradedItemLevel (item)
|
||||
item_level = item_level + (ilvl or iLevel)
|
||||
print (ilvl, item)
|
||||
else
|
||||
item_level = item_level + iLevel
|
||||
print (iLevel, item)
|
||||
end
|
||||
|
||||
item_level = item_level + iLevel
|
||||
print (iLevel, item)
|
||||
--> 16 = main hand 17 = off hand
|
||||
--> if using a two-hand, ignore the off hand slot
|
||||
if (equip_id == 16 and two_hand [equipSlot]) then
|
||||
|
||||
Reference in New Issue
Block a user