Untitled diff

Created Diff never expires
42 removals
Lines
Total
Removed
Words
Total
Removed
To continue using this feature, upgrade to
Diffchecker logo
Diffchecker Pro
892 lines
35 additions
Lines
Total
Added
Words
Total
Added
To continue using this feature, upgrade to
Diffchecker logo
Diffchecker Pro
883 lines
--[[
--[[
ToDo:
ToDo:
- Move more Group Functionality to here
- Move more Group Functionality to here
* Autoscan
* Autoscan
* SIL_Group:GroupType();
* SIL_Group:GroupType();
- On UpdateGroup if there is no data do a rough scan
- On UpdateGroup if there is no data do a rough scan
- Group methods within this file
- Group methods within this file
- Better way to hooking tooltips
- Better way to hooking tooltips
-
-
]]
]]


local L = LibStub("AceLocale-3.0"):GetLocale("SimpleILevel", true);
local L = LibStub("AceLocale-3.0"):GetLocale("SimpleILevel", true);


-- Start SIL
-- Start SIL
SIL = LibStub("AceAddon-3.0"):NewAddon(L.core.name, "AceEvent-3.0", "AceConsole-3.0", "AceTimer-3.0");
SIL = LibStub("AceAddon-3.0"):NewAddon(L.core.name, "AceEvent-3.0", "AceConsole-3.0", "AceTimer-3.0");
SIL.category = GetAddOnMetadata("SimpleILevel", "X-Category");
SIL.category = GetAddOnMetadata("SimpleILevel", "X-Category");
SIL.version = GetAddOnMetadata("SimpleILevel", "Version");
SIL.version = GetAddOnMetadata("SimpleILevel", "Version");
SIL.versionMajor = 3; -- Used for cache DB versioning
SIL.versionMajor = 3; -- Used for cache DB versioning
SIL.versionRev = 'r251'; -- Used for version information
SIL.versionRev = 'r251'; -- Used for version information
SIL.action = {}; -- DB of unitGUID->function to run when a update comes through
SIL.action = {}; -- DB of unitGUID->function to run when a update comes through
SIL.hooks = {}; -- List of hooks in [type][] = function;
SIL.hooks = {}; -- List of hooks in [type][] = function;
SIL.autoscan = 0; -- time() value of last autoscan, must be more then 1sec
SIL.autoscan = 0; -- time() value of last autoscan, must be more then 1sec
SIL.lastScan = {}; -- target = time();
SIL.lastScan = {}; -- target = time();
SIL.grayScore = 7; -- Number of items to consider gray/aprox
SIL.grayScore = 7; -- Number of items to consider gray/aprox
SIL.ldbAuto = false; -- AceTimer for LDB
SIL.ldbAuto = false; -- AceTimer for LDB
SIL.menu = false; -- Menu frame
SIL.menu = false; -- Menu frame
SIL.menuItems = { -- Table for the dropdown menu
SIL.menuItems = { -- Table for the dropdown menu
top = {},
top = {},
middle = {},
middle = {},
bottom = {},
bottom = {},
};
};
SIL.modules = {}; -- Modules
SIL.modules = {}; -- Modules
SIL.group = {}; -- Group Members by guid
SIL.group = {}; -- Group Members by guid
--SIL.L = L; -- Non-local locals
--SIL.L = L; -- Non-local locals


-- Load Libs
-- Load Libs
SIL.aceConfig = LibStub:GetLibrary("AceConfig-3.0");
SIL.aceConfig = LibStub:GetLibrary("AceConfig-3.0");
SIL.aceConfigDialog = LibStub:GetLibrary("AceConfigDialog-3.0");
SIL.aceConfigDialog = LibStub:GetLibrary("AceConfigDialog-3.0");
SIL.inspect = LibStub:GetLibrary("LibInspect");
SIL.inspect = LibStub:GetLibrary("LibInspect");
SIL.ldb = LibStub:GetLibrary("LibDataBroker-1.1");
SIL.ldb = LibStub:GetLibrary("LibDataBroker-1.1");
SIL.ldbIcon = LibStub:GetLibrary("LibDBIcon-1.0");
SIL.ldbIcon = LibStub:GetLibrary("LibDBIcon-1.0");
SIL.callback = LibStub("CallbackHandler-1.0"):New(SIL);
SIL.callback = LibStub("CallbackHandler-1.0"):New(SIL);
SIL.itemUpgrade = LibStub("LibItemUpgradeInfo-1.0");
SIL.itemUpgrade = LibStub("LibItemUpgradeInfo-1.0");


-- OnLoad
-- OnLoad
function SIL:OnInitialize()
function SIL:OnInitialize()


-- Make sure everything is ok with the db
-- Make sure everything is ok with the db
if not SIL_CacheGUID or type(SIL_CacheGUID) ~= 'table' then SIL_CacheGUID = {}; end
if not SIL_CacheGUID or type(SIL_CacheGUID) ~= 'table' then SIL_CacheGUID = {}; end
-- Tell the player we are being loaded
-- Tell the player we are being loaded
self:Print(format(L.core.load, self.version));
self:Print(format(L.core.load, self.version));
self:ModulesProcess();
self:ModulesProcess();
-- Load settings
-- Load settings
self.db = LibStub("AceDB-3.0"):New("SIL_Settings", SIL_Defaults, true);
self.db = LibStub("AceDB-3.0"):New("SIL_Settings", SIL_Defaults, true);
self:UpdateSettings();
self:UpdateSettings();
-- Set Up LDB
-- Set Up LDB
local ldbObj = {
local ldbObj = {
type = "data source",
type = "data source",
icon = "Interface\\Icons\\inv_misc_armorkit_24",
icon = "Interface\\Icons\\inv_misc_armorkit_24",
label = L.core.name,
label = L.core.name,
text = 'n/a',
text = 'n/a',
category = self.category,
category = self.category,
version = self.version,
version = self.version,
OnClick = function(...) SIL:MenuOpen(...); end,
OnClick = function(...) SIL:MenuOpen(...); end,
OnTooltipShow = function(tt)
OnTooltipShow = function(tt)
if SIL:GetLDB() and SIL.ldb.text then
if SIL:GetLDB() and SIL.ldb.text then
tt:AddLine(SIL.ldb.text);
tt:AddLine(SIL.ldb.text);
end
end
tt:AddLine(L.core.minimapClick);
tt:AddLine(L.core.minimapClick);
tt:AddLine(L.core.minimapClickDrag);
tt:AddLine(L.core.minimapClickDrag);
end,
end,
};
};
-- Set back to a launcher if text is off
-- Set back to a launcher if text is off
if not self:GetLDB() then
if not self:GetLDB() then
ldbObj.type = 'launcher';
ldbObj.type = 'launcher';
ldbObj.text = nil;
ldbObj.text = nil;
end
end
-- Start LDB
-- Start LDB
self.ldb = self.ldb:NewDataObject(L.core.name, ldbObj);
self.ldb = self.ldb:NewDataObject(L.core.name, ldbObj);
self.ldbUpdated = 0;
self.ldbUpdated = 0;
self.ldbLable = '';
self.ldbLable = '';
-- Start the minimap icon
-- Start the minimap icon
self.ldbIcon:Register(L.core.name, self.ldb, self.db.global.minimap);
self.ldbIcon:Register(L.core.name, self.ldb, self.db.global.minimap);
-- Register Options
-- Register Options
SIL_Options.args.purge.desc = format(L.core.options.purgeDesc, self:GetPurge() / 24);
SIL_Options.args.purge.desc = format(L.core.options.purgeDesc, self:GetPurge() / 24);
self.aceConfig:RegisterOptionsTable(L.core.name, SIL_Options, {"sil", "silev", "simpleilevel"});
self.aceConfig:RegisterOptionsTable(L.core.name, SIL_Options, {"sil", "silev", "simpleilevel"});
self.aceConfigDialog:AddToBlizOptions(L.core.name);
self.aceConfigDialog:AddToBlizOptions(L.core.name);
-- Add Hooks
-- Add Hooks
self.inspect:AddHook(L.core.name, 'items', function(...) SIL:ProcessInspect(...); end);
self.inspect:AddHook(L.core.name, 'items', function(...) SIL:ProcessInspect(...); end);
GameTooltip:HookScript("OnTooltipSetUnit", function(...) SIL:TooltipHook(...); end);
GameTooltip:HookScript("OnTooltipSetUnit", function(...) SIL:TooltipHook(...); end);
self:Autoscan(self:GetAutoscan());
self:Autoscan(self:GetAutoscan());
-- Events
-- Events
self:RegisterEvent("PLAYER_TARGET_CHANGED", function() if CanInspect('target') then SIL:GetScoreTarget('target'); end end);
self:RegisterEvent("PLAYER_TARGET_CHANGED", function() if CanInspect('target') then SIL:GetScoreTarget('target'); end end);
self:RegisterEvent("PLAYER_EQUIPMENT_CHANGED", function() SIL:StartScore('player'); end);
self:RegisterEvent("PLAYER_EQUIPMENT_CHANGED", function() SIL:StartScore('player'); end);
self:RegisterEvent("PLAYER_ENTERING_WORLD", function() SIL:UpdateLDB(); end);
self:RegisterEvent("PLAYER_ENTERING_WORLD", function() SIL:UpdateLDB(); end);
self:RegisterEvent("GROUP_ROSTER_UPDATE", function() SIL:UpdateGroup() end);
self:RegisterEvent("GROUP_ROSTER_UPDATE", function() SIL:UpdateGroup() end);
self:RegisterEvent("UPDATE_MOUSEOVER_UNIT", function()
self:RegisterEvent("UPDATE_MOUSEOVER_UNIT", function()
if SIL:GetMouseOver() and CanInspect('mouseover') then
if SIL:GetMouseOver() and CanInspect('mouseover') then
SIL:Debug('mouseover', UnitName('mouseover'));
SIL:Debug('mouseover', UnitName('mouseover'));
SIL:GetScoreTarget('mouseover');
SIL:GetScoreTarget('mouseover');
end
end
SIL:ShowTooltip();
SIL:ShowTooltip();
end);
end);
-- Add to Paperdoll
-- Add to Paperdoll
if self:GetPaperdoll() then
if self:GetPaperdoll() then
self:RegisterPaperdoll();
self:RegisterPaperdoll();
end
end
-- GuildMemberInfo
-- GuildMemberInfo
if GMI then
if GMI then
GMI:Register("SimpleILevel", {
GMI:Register("SimpleILevel", {
lines = {
lines = {
SimpleILevel = {
SimpleILevel = {
label = L.core.name,
label = L.core.name,
default = 'n/a',
default = 'n/a',
callback = function(name) return SIL:GMICallback(name); end,
callback = function(name) return SIL:GMICallback(name); end,
},
},
},
},
});
});
end
end
-- Clear the cache
-- Clear the cache
self:AutoPurge(true);
self:AutoPurge(true);
-- Build the menu
-- Build the menu
self:MenuInitialize();
self:MenuInitialize();
-- Get working on a score for the player
-- Get working on a score for the player
self:StartScore('player');
self:StartScore('player');
self:LDBSetAuto();
self:LDBSetAuto();
self:UpdateLDB(); -- This may cause excesive loading time...
self:UpdateLDB(); -- This may cause excesive loading time...
-- Process modules
-- Process modules
self:ModulesLoad();
self:ModulesLoad();
-- Localization Notice
-- Localization Notice
if GetLocale() == 'itIT' or GetLocale() == 'esMX' or GetLocale() == 'esES' then
if GetLocale() == 'itIT' or GetLocale() == 'esMX' or GetLocale() == 'esES' then
self:Print("Help Localize Simple iLevel! http://j.mp/localSIL")
self:Print("Help Localize Simple iLevel! http://j.mp/localSIL")
end
end
end
end


-- Make sure the database is the latest version
-- Make sure the database is the latest version
function SIL:UpdateSettings()
function SIL:UpdateSettings()
if self.db.global.version == self.versionMajor then
if self.db.global.version == self.versionMajor then
-- Same version
-- Same version
elseif self.db.global.version > 2.4 and self.db.global.version < 2.5 then
elseif self.db.global.version > 2.4 and self.db.global.version < 2.5 then
for guid,info in pairs(SIL_CacheGUID) do
for guid,info in pairs(SIL_CacheGUID) do
SIL_CacheGUID[guid].guid = nil;
SIL_CacheGUID[guid].guid = nil;
end
end
elseif self.db.global.version < 2.4 then
elseif self.db.global.version < 2.4 then
for guid,info in pairs(SIL_CacheGUID) do
for guid,info in pairs(SIL_CacheGUID) do
SIL_CacheGUID[guid].total = nil;
SIL_CacheGUID[guid].total = nil;
SIL_CacheGUID[guid].tooltip = nil;
SIL_CacheGUID[guid].tooltip = nil;
SIL_CacheGUID[guid].level = 85; --ASSuME
SIL_CacheGUID[guid].level = 85; --ASSuME
--SIL_CacheGUID[guid].guid = guid;
--SIL_CacheGUID[guid].guid = guid;
end
end
end
end
-- Update version information
-- Update version information
self.db.global.version = self.versionMajor;
self.db.global.version = self.versionMajor;
end
end


function SIL:AutoPurge(silent)
function SIL:AutoPurge(silent)
if self:GetPurge() > 0 then
if self:GetPurge() > 0 then
local count = self:PurgeCache(self:GetPurge());
local count = self:PurgeCache(self:GetPurge());
if not silent then
if not silent then
self:Print(format(L.core.purgeNotification, count));
self:Print(format(L.core.purgeNotification, count));
end
end
return count;
return count;
else
else
if not silent then
if not silent then
self:Print(L.core.purgeNotificationFalse);
self:Print(L.core.purgeNotificationFalse);
end
end
return false;
return false;
end
end
end
end


function SIL:PurgeCache(hours)
function SIL:PurgeCache(hours)
if tonumber(hours) then
if tonumber(hours) then
local maxAge = time() - (tonumber(hours) * 3600);
local maxAge = time() - (tonumber(hours) * 3600);
local count = 0;
local count = 0;
for guid,info in pairs(SIL_CacheGUID) do
for guid,info in pairs(SIL_CacheGUID) do
if type(info.time) == "number" and info.time < maxAge then
if type(info.time) == "number" and info.time < maxAge then
SIL_CacheGUID[guid] = nil;
SIL_CacheGUID[guid] = nil;
count = 1 + count;
count = 1 + count;
self:RunHooks('purge', guid);
self:RunHooks('purge', guid);
end
end
end
end
return count;
return count;
else
else
return false;
return false;
end
end
end
end


function SIL:AddHook(hookType, callback)
function SIL:AddHook(hookType, callback)
local hookType = strlower(hookType);
local hookType = strlower(hookType);
if not self.hooks[hookType] then
if not self.hooks[hookType] then
self.hooks[hookType] = {};
self.hooks[hookType] = {};
end
end
table.insert(self.hooks[hookType], callback);
table.insert(self.hooks[hookType], callback);
end
end


function SIL:RunHooks(hookType, ...)
function SIL:RunHooks(hookType, ...)
local r = {};
local r = {};
if self.hooks[hookType] then
if self.hooks[hookType] then
for i,callback in pairs(self.hooks[hookType]) do
for i,callback in pairs(self.hooks[hookType]) do
local ret = callback(...);
local ret = callback(...);
if ret then
if ret then
table.insert(r, callback(...));
table.insert(r, callback(...));
end
end
end
end
if #r > 0 then
if #r > 0 then
return r;
return r;
else
else
return true;
return true;
end
end
else
else
return false;
return false;
end
end
end
end


--[[
--[[
Event Handlers
Event Handlers
]]
]]
function SIL:UNIT_INVENTORY_CHANGED(e, unitID)
function SIL:UNIT_INVENTORY_CHANGED(e, unitID)
--print('UNIT_INVENTORY_CHANGED');
--print('UNIT_INVENTORY_CHANGED');
if InCombatLockdown() then return end
if InCombatLockdown() then return end
if unitID and CanInspect(unitID) and not UnitIsUnit('player', unitID) and self.autoscan ~= time() then
if unitID and CanInspect(unitID) and not UnitIsUnit('player', unitID) and self.autoscan ~= time() then
self.autoscan = time();
self.autoscan = time();
self:StartScore(unitID);
self:StartScore(unitID);
end
end
end
end


-- Used to hook the tooltip to avoid the full tooltip function
-- Used to hook the tooltip to avoid the full tooltip function
function SIL:TooltipHook()
function SIL:TooltipHook()
local name, unit = GameTooltip:GetUnit();
local name, unit = GameTooltip:GetUnit();
local guid = false;
local guid = false;
if unit then
if unit then
guid = UnitGUID(unit);
guid = UnitGUID(unit);
elseif name then
elseif name then
guid = self:NameToGUID(name);
guid = self:NameToGUID(name);
end
end
if self:IsGUID(guid, 'Player') then
if self:IsGUID(guid, 'Player') then
self:ShowTooltip(guid);
self:ShowTooltip(guid);
end
end
end
end


function SIL:Autoscan(toggle)
function SIL:Autoscan(toggle)
if toggle then
if toggle then
self:RegisterEvent("UNIT_INVENTORY_CHANGED");
self:RegisterEvent("UNIT_INVENTORY_CHANGED");
else
else
self:UnregisterEvent("UNIT_INVENTORY_CHANGED");
self:UnregisterEvent("UNIT_INVENTORY_CHANGED");
end
end
self.db.global.autoscan = toggle;
self.db.global.autoscan = toggle;
end
end


--[[
--[[


Slash Handlers
Slash Handlers
]]
]]
-- Reset the settings
-- Reset the settings
function SIL:SlashReset()
function SIL:SlashReset()
self:Print(L.core.slashClear);
self:Print(L.core.slashClear);
self.db:RegisterDefaults(SIL_Defaults);
self.db:RegisterDefaults(SIL_Defaults);
self.db:ResetDB('Default');
self.db:ResetDB('Default');
self:SetMinimap(true);
self:SetMinimap(true);
-- Clear the cache
-- Clear the cache
SIL_CacheGUID = {};
SIL_CacheGUID = {};
self:GetScoreTarget('player', true);
self:GetScoreTarget('player', true);
-- Update version information
-- Update version information
self.db.global.version = self.versionMajor;
self.db.global.version = self.versionMajor;
self:RunHooks('clear');
self:RunHooks('clear');
end
end


function SIL:SlashGet(name)
function SIL:SlashGet(name)
-- Get score by name
-- Get score by name
if name and not (name == '' or name == 'target') then
if name and not (name == '' or name == 'target') then
local score, age, items = self:GetScoreName(name);
local score, age, items = self:GetScoreName(name);
if score then
if score then
local name = self:Cache(self:NameToGUID(name), 'name')
local name = self:Cache(self:NameToGUID(name), 'name')
self:Print(format(L.core.slashGetScore, name, self:FormatScore(score, items), self:AgeToText(age)));
self:Print(format(L.core.slashGetScore, name, self:FormatScore(score, items), self:AgeToText(age)));
-- Nothing :(
-- Nothing :(
else
else
self:Print(format(L.core.slashGetScoreFalse, name));
self:Print(format(L.core.slashGetScoreFalse, name));
end
end
-- no name but we can inspect the current target
-- no name but we can inspect the current target
elseif CanInspect('target') then
elseif CanInspect('target') then
self:SlashTarget();
self:SlashTarget();
-- why do you ask so much of me but make no sence
-- why do you ask so much of me but make no sence
else
else
self:Print(L.core.slashTargetScoreFalse);
self:Print(L.core.slashTargetScoreFalse);
end
end
end
end


function SIL:SlashTarget()
function SIL:SlashTarget()
self:StartScore('target', function(...) SIL:SlashTargetPrint(...); end);
self:StartScore('target', function(...) SIL:SlashTargetPrint(...); end);
end
end


function SIL:SlashTargetPrint(guid, score, items, age)
function SIL:SlashTargetPrint(guid, score, items, age)
if guid and score then
if guid and score then
local name = self:GUIDtoName(guid);
local name = self:GUIDtoName(guid);
if name then
if name then
self:Print(format(L.core.slashTargetScore, name, self:FormatScore(score, items)));
self:Print(format(L.core.slashTargetScore, name, self:FormatScore(score, items)));
else
else
self:Debug("No name for guid", guid, "score", score, items, age);
self:Debug("No name for guid", guid, "score", score, items, age);
end
end
else
else
self:Print(L.core.slashTargetScoreFalse);
self:Print(L.core.slashTargetScoreFalse);
end
end
end
end


--[[
--[[


Basic Functions
Basic Functions


]]
]]
function SIL:GUIDtoName(guid)
function SIL:GUIDtoName(guid)
if guid and self:IsGUID(guid, 'Player') and self:Cache(guid) then
if guid and self:IsGUID(guid, 'Player') and self:Cache(guid) then
return self:Cache(guid, 'name'), self:Cache(guid, 'realm');
return self:Cache(guid, 'name'), self:Cache(guid, 'realm');
else
else
return false;
return false;
end
end
end
end


function SIL:NameToGUID(name, realm)
function SIL:NameToGUID(name, realm)
if not name then return false end
if not name then return false end
-- Try and get the realm from the name-realm
-- Try and get the realm from the name-realm
if not realm then
if not realm then
name, realm = strsplit('-', name, 2);
name, realm = strsplit('-', name, 2);
end
end
-- If no realm then set it to current realm
-- If no realm then set it to current realm
if not realm or realm == '' then
if not realm or realm == '' then
realm = GetRealmName();
realm = GetRealmName();
end
end
if name then
if name then
name = strlower(name);
name = strlower(name);
local likely = false;
local likely = false;
for guid,info in pairs(SIL_CacheGUID) do
for guid,info in pairs(SIL_CacheGUID) do
if strlower(info.name) == name and info.realm == realm then
if strlower(info.name) == name and info.realm == realm then
return guid;
return guid;
elseif strlower(info.name) == name then
elseif strlower(info.name) == name then
likely = guid;
likely = guid;
end
end
end
end
if likely then
if likely then
return likely;
return likely;
end
end
end
end
return false;
return false;
end
end


-- Get a GUID from just about anything
-- Get a GUID from just about anything
function SIL:GetGUID(target)
function SIL:GetGUID(target)
if target then
if target then
if tonumber(target) then
if tonumber(target) then
return target;
return target;
elseif UnitGUID(target) then
elseif UnitGUID(target) then
return UnitGUID(target);
return UnitGUID(target);
else
else
return SIL:NameToGUID(target);
return SIL:NameToGUID(target);
end
end
else
else
return false;
return false;
end
end
end
end


-- Clear score
-- Clear score
function SIL:ClearScore(target)
function SIL:ClearScore(target)
local guid = self:GetGUID(target);
local guid = self:GetGUID(target);
if SIL_CacheGUID[guid] then
if SIL_CacheGUID[guid] then
SIL_CacheGUID[guid].score = false;
SIL_CacheGUID[guid].score = false;
SIL_CacheGUID[guid].items = false;
SIL_CacheGUID[guid].items = false;
SIL_CacheGUID[guid].time = false;
SIL_CacheGUID[guid].time = false;
self:RunHooks('purge', guid);
self:RunHooks('purge', guid);
return true;
return true;
else
else
return false;
return false;
end
end
end;
end;


function SIL:AgeToText(age, color)
function SIL:AgeToText(age, color)
if type(color) == 'nil' then color = true; end
if type(color) == 'nil' then color = true; end
local hex = "00ff00";
local hex = "00ff00";
if type(age) == 'number' then
if type(age) == 'number' then
if age > 86400 then
if age > 86400 then
age = self:Round(age / 86400, 2);
age = self:Round(age / 86400, 2);
str = L.core.ageDays;
str = L.core.ageDays;
hex = "ff0000";
hex = "ff0000";
elseif age > 3600 then
elseif age > 3600 then
age = self:Round(age / 3600, 1);
age = self:Round(age / 3600, 1);
str = L.core.ageHours;
str = L.core.ageHours;
hex = "33ccff";
hex = "33ccff";
elseif age > 60 then
elseif age > 60 then
age = self:Round(age / 60, 1);
age = self:Round(age / 60, 1);
str = L.core.ageMinutes;
str = L.core.ageMinutes;
hex = "00ff00";
hex = "00ff00";
else
else
age = age;
age = age;
str = L.core.ageSeconds;
str = L.core.ageSeconds;
hex = "00ff00";
hex = "00ff00";
end
end
if color and self:GetColorScore() then
if color and self:GetColorScore() then
return format(str, '|cFF'..hex..age..'|r');
return format(str, '|cFF'..hex..age..'|r');
else
else
return format(str, age);
return format(str, age);
end
end
else
else
return 'n/a';
return 'n/a';
end
end
end
end


-- print a message to channel or whisper player/channel
-- print a message to channel or whisper player/channel
function SIL:PrintTo(message, channel, to)
function SIL:PrintTo(message, channel, to)
if channel == "print" or channel == "SYSTEM" then
if channel == "print" or channel == "SYSTEM" then
self:Print(message);
self:Print(message);
elseif channel == "WHISPER" then
elseif channel == "WHISPER" then
SendChatMessage(message, 'WHISPER', nil, to);
SendChatMessage(message, 'WHISPER', nil, to);
elseif channel == "CHANNEL" then
elseif channel == "CHANNEL" then
SendChatMessage(message, 'CHANNEL', nil, to);
SendChatMessage(message, 'CHANNEL', nil, to);
elseif channel then
elseif channel then
SendChatMessage(message, channel);
SendChatMessage(message, channel);
else
else
self:Print(message);
self:Print(message);
end
end
end
end


function SIL:Debug(...)
function SIL:Debug(...)
if SIL.db.char.debug then
if SIL.db.char.debug then
print('|cFFFF0000SIL Debug:|r ', ...);
print('|cFFFF0000SIL Debug:|r ', ...);
end
end
end
end


--[[
--[[


Core Functionality
Core Functionality
]]
]]
-- Get someones score
-- Get someones score
function SIL:GetScore(guid, attemptUpdate, target, callback)
function SIL:GetScore(guid, attemptUpdate, target, callback)
if not self:IsGUID(guid, 'Player') then return false; end
if not self:IsGUID(guid, 'Player') then return false; end
if self:Cache(guid) and self:Cache(guid, 'score') then
if self:Cache(guid) and self:Cache(guid, 'score') then
local score = self:Cache(guid, 'score');
local score = self:Cache(guid, 'score');
local age = self:Cache(guid, 'age') or time();
local age = self:Cache(guid, 'age') or time();
local items = self:Cache(guid, 'items');
local items = self:Cache(guid, 'items');
local startScore = nil;
local startScore = nil;
-- If a target was passed and we are over age
-- If a target was passed and we are over age
if target and (attemptUpdate or self:GetAge() < age) and self.autoscan ~= time() then
if target and (attemptUpdate or self:GetAge() < age) and self.autoscan ~= time() then
startScore = self:StartScore(target, callback);
startScore = self:StartScore(target, callback);
end
end
return score, age, items, startScore;
return score, age, items, startScore;
else
else
-- If a target was passed
-- If a target was passed
if target then
if target then
self:StartScore(target);
self:StartScore(target);
end
end
return false;
return false;
end
end
end
end


-- Wrapers for get score, more specialized code may come
-- Wrapers for get score, more specialized code may come
function SIL:GetScoreName(name, realm)
function SIL:GetScoreName(name, realm)
local guid = self:NameToGUID(name, realm);
local guid = self:NameToGUID(name, realm);
return self:GetScore(guid);
return self:GetScore(guid);
end
end


function SIL:GetScoreTarget(target, force, callback)
function SIL:GetScoreTarget(target, force, callback)
local guid = UnitGUID(target);
local guid = UnitGUID(target);
return self:GetScore(guid, force, target, callback);
return self:GetScore(guid, force, target, callback);
end
end


function SIL:GetScoreGUID(guid)
function SIL:GetScoreGUID(guid)
return self:GetScore(guid);
return self:GetScore(guid);
end
end


-- Request items to update a score
-- Request items to update a score
function SIL:StartScore(target, callback)
function SIL:StartScore(target, callback)
if InCombatLockdown() or not CanInspect(target) then
if InCombatLockdown() or not CanInspect(target) then
if callback then callback(false, target); end
if callback then callback(false, target); end
return false;
return false;
end
end
self.autoscan = time();
self.autoscan = time();
local guid = self:AddPlayer(target);
local guid = self:AddPlayer(target);
if not self.lastScan[target] or self.lastScan[target] ~= time() then
if not self.lastScan[target] or self.lastScan[target] ~= time() then
if guid then
if guid then
self.action[guid] = callback;
self.action[guid] = callback;
self.lastScan[target] = time();
self.lastScan[target] = time();
local canInspect = self.inspect:RequestItems(target, true);
local canInspect = self.inspect:RequestItems(target, true);
if not canInspect and callback then
if not canInspect and callback then
callback(false, target);
callback(false, target);
else
else
return true;
return true;
end
end
end
end
end
end
if callback then callback(false, target); end
if callback then callback(false, target); end
return false;
return false;
end
end


function SIL:ProcessInspect(guid, data, age)
function SIL:ProcessInspect(guid, data, age)
if guid and self:Cache(guid) and type(data) == 'table' and type(data.items) == 'table' then
if guid and self:Cache(guid) and type(data) == 'table' and type(data.items) == 'table' then
local totalScore, totalItems = self:GearSum(data.items, self:Cache(guid, 'level'));
local totalScore, totalItems = self:GearSum(data.items, self:Cache(guid, 'level'));
if totalItems and 0 < totalItems then
if totalItems and 0 < totalItems then
-- Update the DB
-- Update the DB
local score = totalScore / totalItems;
local score = totalScore / totalItems;
self:SetScore(guid, score, totalItems, age)
self:SetScore(guid, score, totalItems, age)
-- Update LDB
-- Update LDB
if self:GetLDB() and guid == UnitGUID('player') then
if self:GetLDB() and guid == UnitGUID('player') then
self:UpdateLDB(true);
self:UpdateLDB(true);
else
else
self:UpdateLDB(false);
self:UpdateLDB(false);
end
end
-- Run Hooks
-- Run Hooks
self:RunHooks('inspect', guid, score, totalItems, age, data.items);
self:RunHooks('inspect', guid, score, totalItems, age, data.items);
-- Run any callbacks for this event
-- Run any callbacks for this event
if self.action[guid] then
if self.action[guid] then
self.action[guid](guid, score, totalItems, age, data.items, self:Cache(guid, 'target'));
self.action[guid](guid, score, totalItems, age, data.items, self:Cache(guid, 'target'));
self.action[guid] = false;
self.action[guid] = false;
end
end
-- Update the Tooltip
-- Update the Tooltip
self:ShowTooltip();
self:ShowTooltip();
return true;
return true;
end
end
end
end
end
end


function SIL:GearSum(items, level)
function SIL:GearSum(items, level)
if items and level and type(items) == 'table' then
if items and level and type(items) == 'table' then
local totalItems = 0;
local totalItems = 0;
local totalScore = 0;
local totalScore = 0;
local mainhandArtifactIlvlCache = 0;
local offhandAtifactIlvlCache=0;
for i,itemLink in pairs(items) do
for i,itemLink in pairs(items) do
if itemLink and not ( i == INVSLOT_BODY or i == INVSLOT_RANGED or i == INVSLOT_TABARD ) then
if itemLink and not ( i == INVSLOT_BODY or i == INVSLOT_RANGED or i == INVSLOT_TABARD ) then
-- local name, link, itemRarity , itemLevel = GetItemInfo(itemLink);
local name, link, itemRarity , _ = GetItemInfo(itemLink);
local itemLevel = self.itemUpgrade:GetUpgradedItemLevel(itemLink);
local itemLevel = self.itemUpgrade:GetUpgradedItemLevel(itemLink);


--- print(i, itemLevel, itemLink);
-- print(i, itemLevel, itemLink, itemRarity);
if itemLevel then
if itemLevel then
-- Fix for OH Artifact (always calculated as 750 ilvl)
-- Fix for heirlooms
if itemRarity == 6 then
if itemRarity == 7 then
--Cache MH Artifact ilvl if higher
itemLevel = self:Heirloom(level, itemLink);
if i == INVSLOT_MAINHAND then
end
mainhandArtifactIlvlCache = itemLevel;
end
--Cache OH Artifact ilvl if higher
if i == INVSLOT_OFFHAND then
offhandAtifactIlvlCache = itemLevel
end
end
totalItems = totalItems + 1;
totalItems = totalItems + 1;
totalScore = totalScore + itemLevel;
totalScore = totalScore + itemLevel;
end
end
end
end
end
end
-- Fix for MH Artifact
if mainhandArtifactIlvlCache > offhandAtifactIlvlCache and totalItems == 16 then
totalScore = totalScore - offhandAtifactIlvlCache + mainhandArtifactIlvlCache;
end
-- Fix for OH Artifact
if mainhandArtifactIlvlCache < offhandAtifactIlvlCache and totalItems == 16 then
totalScore = totalScore + offhandAtifactIlvlCache - mainhandArtifactIlvlCache;
end
--Fix for 2H Artifact
if totalItems == 15 then
totalScore = totalScore + mainhandArtifactIlvlCache;
totalItems = totalItems + 1;
end
return totalScore, totalItems;
return totalScore, totalItems;
else
else
return false;
return false;
end
end
end
end


-- Thanks to Ro of Hyjal-US http://us.battle.net/wow/en/forum/topic/7199032730#9
-- Thanks to Ro of Hyjal-US http://us.battle.net/wow/en/forum/topic/7199032730#9
function SIL:GetActualItemLevelOld(link)
function SIL:GetActualItemLevelOld(link)
-- Updated for 5.4.8
-- Updated for 5.4.8
local levelAdjust={ -- 11th item:id field and level adjustment
local levelAdjust={ -- 11th item:id field and level adjustment
["0"]=0,["1"]=8,["373"]=4,["374"]=8,["375"]=4,["376"]=4,
["0"]=0,["1"]=8,["373"]=4,["374"]=8,["375"]=4,["376"]=4,
["377"]=4,["379"]=4,["380"]=4,["445"]=0,["446"]=4,["447"]=8,
["377"]=4,["379"]=4,["380"]=4,["445"]=0,["446"]=4,["447"]=8,
["451"]=0,["452"]=8,["453"]=0,["454"]=4,["455"]=8,["456"]=0,
["451"]=0,["452"]=8,["453"]=0,["454"]=4,["455"]=8,["456"]=0,
["457"]=8,["458"]=0,["459"]=4,["460"]=8,["461"]=12,["462"]=16,
["457"]=8,["458"]=0,["459"]=4,["460"]=8,["461"]=12,["462"]=16,
["465"]=0,["466"]=4,["467"]=8,["469"]=4,["470"]=8,["471"]=12,
["465"]=0,["466"]=4,["467"]=8,["469"]=4,["470"]=8,["471"]=12,
["472"]=16,["491"]=0,["492"]=4,["493"]=8,["494"]=4,["495"]=8,
["472"]=16,["491"]=0,["492"]=4,["493"]=8,["494"]=4,["495"]=8,
["496"]=8,["497"]=12,["498"]=16,["504"]=12,["505"]=16,["506"]=20,
["496"]=8,["497"]=12,["498"]=16,["504"]=12,["505"]=16,["506"]=20,
["507"]=24,
["507"]=24,
}
}
local baseLevel = select(4,GetItemInfo(link))
local baseLevel = select(4,GetItemInfo(link))
local upgrade = link:match(":(%d+)\124h%[")
local upgrade = link:match(":(%d+)\124h%[")
if baseLevel and upgrade and levelAdjust[upgrade] then
if baseLevel and upgrade and levelAdjust[upgrade] then
local newLevel = baseLevel + levelAdjust[upgrade];
local newLevel = baseLevel + levelAdjust[upgrade];
return newLevel
return newLevel
else
else
return baseLevel
return baseLevel
end
end
end
end


-- /run for i=1,25 do t='raid'..i; if UnitExists(t) then print(i, UnitName(t), CanInspect(t), SIL:RoughScore(t)); end end
-- /run for i=1,25 do t='raid'..i; if UnitExists(t) then print(i, UnitName(t), CanInspect(t), SIL:RoughScore(t)); end end
function SIL:RoughScore(target)
function SIL:RoughScore(target)
if not target then return false; end
if not target then return false; end
if not CanInspect(target) then return false; end
if not CanInspect(target) then return false; end
-- Get stuff in order
-- Get stuff in order
local guid = self:AddPlayer(target)
local guid = self:AddPlayer(target)
self.inspect:AddCharacter(target);
self.inspect:AddCharacter(target);
NotifyInspect(target);
NotifyInspect(target);
-- Get items and sum
-- Get items and sum
local items = self.inspect:GetItems(target);
local items = self.inspect:GetItems(target);
local totalScore, totalItems = self:GearSum(items, UnitLevel(target));
local totalScore, totalItems = self:GearSum(items, UnitLevel(target));
if totalItems and totalItems > 0 then
if totalItems and totalItems > 0 then
local score = totalScore / totalItems;
local score = totalScore / totalItems;
-- self:Debug('SIL:RoughScore', UnitName(target), score, totalItems);
-- self:Debug('SIL:RoughScore', UnitName(target), score, totalItems);
-- Set a score even tho its crap
-- Set a score even tho its crap
if guid and self:Cache(guid) and (not self:Cache(guid, 'score') or self:Cache(guid, 'items') < totalItems) then
if guid and self:Cache(guid) and (not self:Cache(guid, 'score') or self:Cache(guid, 'items') < totalItems) then
self:SetScore(guid, score, 1, self:GetAge() + 1);
self:SetScore(guid, score, 1, self:GetAge() + 1);
end
end
return score, 1, self:GetAge() + 1;
return score, 1, self:GetAge() + 1;
else
else
return false;
return false;
end
end
end
end


-- Start or update the DB for a player
-- Start or update the DB for a player
function SIL:AddPlayer(target)
function SIL:AddPlayer(target)
local guid = UnitGUID(target);
local guid = UnitGUID(target);
if guid then
if guid then
local name, realm = UnitName(target);
local name, realm = UnitName(target);
local className, class = UnitClass(target);
local className, class = UnitClass(target);
local level = UnitLevel(target);
local level = UnitLevel(target);
if not realm then
if not realm then
realm = GetRealmName();
realm = GetRealmName();
end
end
if name and realm and class and level then
if name and realm and class and level then
-- Start a table for them
-- Start a table for them
if not SIL_CacheGUID[guid] then
if not SIL_CacheGUID[guid] then
SIL_CacheGUID[guid] = {};
SIL_CacheGUID[guid] = {};
end
end
SIL_CacheGUID[guid].name = name;
SIL_CacheGUID[guid].name = name;
SIL_CacheGUID[guid].realm = realm;
SIL_CacheGUID[guid].realm = realm;
SIL_CacheGUID[guid].class = class;
SIL_CacheGUID[guid].class = class;
SIL_CacheGUID[guid].level = level;
SIL_CacheGUID[guid].level = level;
SIL_CacheGUID[guid].target = target;
SIL_CacheGUID[guid].target = target;
if not SIL_CacheGUID[guid].score or SIL_CacheGUID[guid].score == 0 then
if not SIL_CacheGUID[guid].score or SIL_CacheGUID[guid].score == 0 then
SIL_CacheGUID[guid].score = false;
SIL_CacheGUID[guid].score = false;
SIL_CacheGUID[guid].items = false;
SIL_CacheGUID[guid].items = false;
SIL_CacheGUID[guid].time = false;
SIL_CacheGUID[guid].time = false;
end
end
return guid;
return guid;
else
else
return false;
return false;
end
end
else
else
return false;
return false;
end
end
end
end


function SIL:SetScore(guid, score, items, age)
function SIL:SetScore(guid, score, items, age)
local t = age;
local t = age;
if age and type(age) == 'number' and age < 86400 then
if age and type(age) == 'number' and age < 86400 then
t = time() - age;
t = time() - age;
end
end
SIL_CacheGUID[guid].score = score;
SIL_CacheGUID[guid].score = score;
SIL_CacheGUID[guid].items = items;
SIL_CacheGUID[guid].items = items;
SIL_CacheGUID[guid].time = t;
SIL_CacheGUID[guid].time = t;
self:Debug("SetScore", self:GUIDtoName(guid), self:FormatScore(score, items), items, age)
self:Debug("SetScore", self:GUIDtoName(guid), self:FormatScore(score, items), items, age)
end
end


-- Get a relative iLevel on Heirlooms
-- Get a relative iLevel on Heirlooms
function SIL:Heirloom(level, itemLink)
function SIL:Heirloom(level, itemLink)
--[[
--[[
Here is how I came to the level 81-85 bracket
Here is how I came to the level 81-85 bracket
200 = level of 80 instance gear
200 = level of 80 instance gear
333 = level of 85 instance gear
333 = level of 85 instance gear
333 - 200 = 133 iLevels / 5 levels = 26.6 iLevel per level
333 - 200 = 133 iLevels / 5 levels = 26.6 iLevel per level
so then that means for a level 83
so then that means for a level 83
83 - 80 = 3 * 26.6 = 79.8 + 200 = 279.8 iLevel
83 - 80 = 3 * 26.6 = 79.8 + 200 = 279.8 iLevel
]]
]]
-- Check for Wrath Heirlooms that max at 80
-- Check for Wrath Heirlooms that max at 80
if level > 80 then
if level > 80 then
local _, _, _, _, itemId = string.find(itemLink, "|?c?f?f?(%x*)|?H?([^:]*):?(%d+):?(%d*):?(%d*):?(%d*):?(%d*):?(%d*):?(%-?%d*):?(%-?%d*):?(%d*):?(%d*)|?h?%[?([^%[%]]*)%]?|?h?|?r?");
local _, _, _, _, itemId = string.find(itemLink, "|?c?f?f?(%x*)|?H?([^:]*):?(%d+):?(%d*):?(%d*):?(%d*):?(%d*):?(%d*):?(%-?%d*):?(%-?%d*):?(%d*):?(%d*)|?h?%[?([^%[%]]*)%]?|?h?|?r?");
itemId = tonumber(itemId);
itemId = tonumber(itemId);
-- Downgrade it to 80 if found
-- Downgrade it to 80 if found
for k,iid in pairs(SIL_Heirlooms[80]) do
for k,iid in pairs(SIL_Heirlooms[80]) do
if iid == itemId then
if iid == itemId then
level = 80;
level = 80;
end
end
end
end
-- There are currently no 1-90 Heirlooms
-- There are currently no 1-90 Heirlooms
if level > 85 then
if level > 85 then
level = 85
level = 85
end
end
end
end
if level > 80 then
if level > 80 then
return (( level - 80) * 26.6) + 200;
return (( level - 80) * 26.6) + 200;
elseif level > 70 then
elseif level > 70 then
return (( level - 70) * 10) + 100;
return (( level - 70) * 10) + 100;
elseif level > 60 then
elseif level > 60 then
return (( level - 60) * 4) + 60;
return (( level - 60) * 4) + 60;
else
else
return level;
return level;
end
end
end
end


-- Format the score for color and round it to xxx.x
-- Format the score for color and round it to xxx.x
function SIL:FormatScore(score, items, color)
function SIL:FormatScore(score, items, color)
if not items then items = self.grayScore + 1; end
if not items then items = self.grayScore + 1; end
if type(color) == 'nil' then color = true; end
if type(color) == 'nil' then color = true; end
if score < 0 then score = 0; end -- Ticket #29, thanks Torsin
if score < 0 then score = 0; end -- Ticket #29, thanks Torsin
if tonumber(score) and tonumber(items) then
if tonumber(score) and tonumber(items) then
local scoreR
local scoreR
if self:GetRoundScore() then
if self:GetRoundScore() then
scoreR = self:Round(tonumber(score), 0);
scoreR = self:Round(tonumber(score), 0);
else
else
scoreR = self:Round(tonumber(score), 1);
scoreR = self:Round(tonumber(score), 1);
end
end
if color then
if color then
local hexColor = self:ColorScore(score, items);
local hexColor = self:ColorScore(score, items);
return '|cFF'..hexColor..scoreR..'|r';
return '|cFF'..hexColor..scoreR..'|r';
else
else
return scoreR;
return scoreR;
end
end
else
else
return 'n/a';
return 'n/a';
end
end
end
end


-- Return the hex, r, g, b of a score
-- Return the hex, r, g, b of a score
function SIL:ColorScore(score, items)
function SIL:ColorScore(score, items)
-- There are some missing items so gray
-- There are some missing items so gray
if items and items <= self.grayScore then
if items and items <= self.grayScore then
return self:RGBtoHex(0.5,0.5,0.5), 0.5,0.5,0.5;
return self:RGBtoHex(0.5,0.5,0.5), 0.5,0.5,0.5;
end
end
if not self:GetColorScore() then
if not self:GetColorScore() then
return self:RGBtoHex(1,1,1), 1,1,1;
return self:RGBtoHex(1,1,1), 1,1,1;
end
end
-- Default to white
-- Default to white
local r,g,b = 1,1,1;
local r,g,b = 1,1,1;
local found = false;
local found = false;
for i,maxScore in pairs(SIL_ColorIndex) do
for i,maxScore in pairs(SIL_ColorIndex) do
if score < maxScore and not found then
if score < maxScore and not found then
local colors = SIL_Colors[maxScore];
local colors = SIL_Colors[maxScore];
local baseColors = SIL_Colors[colors.p];
local baseColors = SIL_Colors[colors.p];
local steps = maxScore - colors.p;
local steps = maxScore - colors.p;
local scoreDiff = score - colors.p;
local scoreDiff = score - colors.p;
local diffR = (baseColors.r - colors.r) / 255;
local diffR = (baseColors.r - colors.r) / 255;
local diffG = (baseColors.g - colors.g) / 255;
local diffG = (baseColors.g - colors.g) / 255;
local diffB = (baseColors.b - colors.b) / 255;
local diffB = (baseColors.b - colors.b) / 255;
local diffStepR = diffR / steps;
local diffStepR = diffR / steps;
local diffStepG = diffG / steps;
local diffStepG = diffG / steps;
local diffStepB = diffB / steps;
local diffStepB = diffB / steps;
local scoreDiffR = scoreDiff * diffStepR;
local scoreDiffR = scoreDiff * diffStepR;
local scoreDiffG = scoreDiff * diffStepG;
local scoreDiffG = scoreDiff * diffStepG;
local scoreDiffB = scoreDiff * diffStepB;
local scoreDiffB = scoreDiff * diffStepB;
r = (baseColors.r / 255) - scoreDiffR;
r = (baseColors.r / 255) - scoreDiffR;
g = (baseColors.g / 255) - scoreDiffG;
g = (baseColors.g / 255) - scoreDiffG;
b = (baseColors.b / 255) - scoreDiffB;
b = (baseColors.b / 255) - scoreDiffB;
found = true;
found = true;
end
end
end
end
-- Nothing was found so max
-- Nothing was found so max
if not found then
if not found then
r = SIL_Colors[1000].r;
r = SIL_Colors[1000].r;
g = SIL_Colors[1000].g;
g = SIL_Colors[1000].g;
b = SIL_Colors[1000].b;
b = SIL_Colors[1000].b;
end
end
local hex = self:RGBtoHex(r,g,b);
local hex = self:RGBtoHex(r,g,b);
return hex, r, g, b;
return hex, r, g, b;
end
end


function SIL:ShowTooltip(guid)
function SIL:ShowTooltip(guid)
if InCombatLockdown() and not self:GetTTCombat() then return end
if InCombatLockdown() and not self:GetTTC
if not guid then
guid = UnitGUID("mouseover");
end
local score, age, items = self:GetScoreGUID(guid);
if score then
-- Build the tooltip text
local textLeft = '|cFF216bff'..L.core.ttLeft..'|r ';
local textRight = self:FormatScore(score, items, true);
local textAdvanced = format(L.core.ttAdvanced, self:AgeToText(age, true));
self:AddTooltipText(textLeft, textRight, textAdvanced);
-- Run Hooks
self:RunHooks('tooltip', guid);
return true;
else
return false;
end
end

-- Add lines to the tooltip, testLeft must be the same
function SIL:AddTooltipText(textLeft, textRight, textAdvanced, textAdvancedRight)
-- Loop tooltip text to check if its alredy there
local ttLines = GameTooltip:NumLines();
local ttUpdated = f