Diff
checker
텍스트
텍스트
이미지
문서
Excel
폴더
Legal
Enterprise
데스크톱
요금제
로그인
데스크톱 앱 다운로드
텍스트 비교
두 텍스트 파일의 차이점을 찾아보세요
도구
기록
실시간 편집
변경 없는 행 숨기기
줄바꿈 비활성화
레이아웃
나란히 보기
합쳐 보기
비교 단위
스마트
단어
글자
구문 강조
언어 선택
제외
텍스트 변환
첫 변경으로
수정
Diffchecker Desktop
가장 안전하게 Diffchecker를 사용하는 방법. 데스크톱 앱을 사용하면 비교 데이터가 외부로 전송되지 않습니다!
데스크톱 앱 받기
Untitled diff
생성일
10년 전
비교 결과 만료 없음
초기화
내보내기
공유
설명
41 삭제
행
총
삭제
글자
총
삭제
이 기능을 계속 사용하려면 업그레이드해 주세요
Diff
checker
Pro
요금제 보기
892 행
복사
33 추가
행
총
추가
글자
총
추가
이 기능을 계속 사용하려면 업그레이드해 주세요
Diff
checker
Pro
요금제 보기
883 행
복사
--[[
--[[
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:GetTTC
ombat() 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
저장된 비교 결과
원본
파일 열기
--[[ ToDo: - Move more Group Functionality to here * Autoscan * SIL_Group:GroupType(); - On UpdateGroup if there is no data do a rough scan - Group methods within this file - Better way to hooking tooltips - ]] local L = LibStub("AceLocale-3.0"):GetLocale("SimpleILevel", true); -- Start SIL 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.version = GetAddOnMetadata("SimpleILevel", "Version"); SIL.versionMajor = 3; -- Used for cache DB versioning SIL.versionRev = 'r251'; -- Used for version information SIL.action = {}; -- DB of unitGUID->function to run when a update comes through SIL.hooks = {}; -- List of hooks in [type][] = function; SIL.autoscan = 0; -- time() value of last autoscan, must be more then 1sec SIL.lastScan = {}; -- target = time(); SIL.grayScore = 7; -- Number of items to consider gray/aprox SIL.ldbAuto = false; -- AceTimer for LDB SIL.menu = false; -- Menu frame SIL.menuItems = { -- Table for the dropdown menu top = {}, middle = {}, bottom = {}, }; SIL.modules = {}; -- Modules SIL.group = {}; -- Group Members by guid --SIL.L = L; -- Non-local locals -- Load Libs SIL.aceConfig = LibStub:GetLibrary("AceConfig-3.0"); SIL.aceConfigDialog = LibStub:GetLibrary("AceConfigDialog-3.0"); SIL.inspect = LibStub:GetLibrary("LibInspect"); SIL.ldb = LibStub:GetLibrary("LibDataBroker-1.1"); SIL.ldbIcon = LibStub:GetLibrary("LibDBIcon-1.0"); SIL.callback = LibStub("CallbackHandler-1.0"):New(SIL); SIL.itemUpgrade = LibStub("LibItemUpgradeInfo-1.0"); -- OnLoad function SIL:OnInitialize() -- Make sure everything is ok with the db if not SIL_CacheGUID or type(SIL_CacheGUID) ~= 'table' then SIL_CacheGUID = {}; end -- Tell the player we are being loaded self:Print(format(L.core.load, self.version)); self:ModulesProcess(); -- Load settings self.db = LibStub("AceDB-3.0"):New("SIL_Settings", SIL_Defaults, true); self:UpdateSettings(); -- Set Up LDB local ldbObj = { type = "data source", icon = "Interface\\Icons\\inv_misc_armorkit_24", label = L.core.name, text = 'n/a', category = self.category, version = self.version, OnClick = function(...) SIL:MenuOpen(...); end, OnTooltipShow = function(tt) if SIL:GetLDB() and SIL.ldb.text then tt:AddLine(SIL.ldb.text); end tt:AddLine(L.core.minimapClick); tt:AddLine(L.core.minimapClickDrag); end, }; -- Set back to a launcher if text is off if not self:GetLDB() then ldbObj.type = 'launcher'; ldbObj.text = nil; end -- Start LDB self.ldb = self.ldb:NewDataObject(L.core.name, ldbObj); self.ldbUpdated = 0; self.ldbLable = ''; -- Start the minimap icon self.ldbIcon:Register(L.core.name, self.ldb, self.db.global.minimap); -- Register Options 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.aceConfigDialog:AddToBlizOptions(L.core.name); -- Add Hooks self.inspect:AddHook(L.core.name, 'items', function(...) SIL:ProcessInspect(...); end); GameTooltip:HookScript("OnTooltipSetUnit", function(...) SIL:TooltipHook(...); end); self:Autoscan(self:GetAutoscan()); -- Events 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_ENTERING_WORLD", function() SIL:UpdateLDB(); end); self:RegisterEvent("GROUP_ROSTER_UPDATE", function() SIL:UpdateGroup() end); self:RegisterEvent("UPDATE_MOUSEOVER_UNIT", function() if SIL:GetMouseOver() and CanInspect('mouseover') then SIL:Debug('mouseover', UnitName('mouseover')); SIL:GetScoreTarget('mouseover'); end SIL:ShowTooltip(); end); -- Add to Paperdoll if self:GetPaperdoll() then self:RegisterPaperdoll(); end -- GuildMemberInfo if GMI then GMI:Register("SimpleILevel", { lines = { SimpleILevel = { label = L.core.name, default = 'n/a', callback = function(name) return SIL:GMICallback(name); end, }, }, }); end -- Clear the cache self:AutoPurge(true); -- Build the menu self:MenuInitialize(); -- Get working on a score for the player self:StartScore('player'); self:LDBSetAuto(); self:UpdateLDB(); -- This may cause excesive loading time... -- Process modules self:ModulesLoad(); -- Localization Notice if GetLocale() == 'itIT' or GetLocale() == 'esMX' or GetLocale() == 'esES' then self:Print("Help Localize Simple iLevel! http://j.mp/localSIL") end end -- Make sure the database is the latest version function SIL:UpdateSettings() if self.db.global.version == self.versionMajor then -- Same version elseif self.db.global.version > 2.4 and self.db.global.version < 2.5 then for guid,info in pairs(SIL_CacheGUID) do SIL_CacheGUID[guid].guid = nil; end elseif self.db.global.version < 2.4 then for guid,info in pairs(SIL_CacheGUID) do SIL_CacheGUID[guid].total = nil; SIL_CacheGUID[guid].tooltip = nil; SIL_CacheGUID[guid].level = 85; --ASSuME --SIL_CacheGUID[guid].guid = guid; end end -- Update version information self.db.global.version = self.versionMajor; end function SIL:AutoPurge(silent) if self:GetPurge() > 0 then local count = self:PurgeCache(self:GetPurge()); if not silent then self:Print(format(L.core.purgeNotification, count)); end return count; else if not silent then self:Print(L.core.purgeNotificationFalse); end return false; end end function SIL:PurgeCache(hours) if tonumber(hours) then local maxAge = time() - (tonumber(hours) * 3600); local count = 0; for guid,info in pairs(SIL_CacheGUID) do if type(info.time) == "number" and info.time < maxAge then SIL_CacheGUID[guid] = nil; count = 1 + count; self:RunHooks('purge', guid); end end return count; else return false; end end function SIL:AddHook(hookType, callback) local hookType = strlower(hookType); if not self.hooks[hookType] then self.hooks[hookType] = {}; end table.insert(self.hooks[hookType], callback); end function SIL:RunHooks(hookType, ...) local r = {}; if self.hooks[hookType] then for i,callback in pairs(self.hooks[hookType]) do local ret = callback(...); if ret then table.insert(r, callback(...)); end end if #r > 0 then return r; else return true; end else return false; end end --[[ Event Handlers ]] function SIL:UNIT_INVENTORY_CHANGED(e, unitID) --print('UNIT_INVENTORY_CHANGED'); if InCombatLockdown() then return end if unitID and CanInspect(unitID) and not UnitIsUnit('player', unitID) and self.autoscan ~= time() then self.autoscan = time(); self:StartScore(unitID); end end -- Used to hook the tooltip to avoid the full tooltip function function SIL:TooltipHook() local name, unit = GameTooltip:GetUnit(); local guid = false; if unit then guid = UnitGUID(unit); elseif name then guid = self:NameToGUID(name); end if self:IsGUID(guid, 'Player') then self:ShowTooltip(guid); end end function SIL:Autoscan(toggle) if toggle then self:RegisterEvent("UNIT_INVENTORY_CHANGED"); else self:UnregisterEvent("UNIT_INVENTORY_CHANGED"); end self.db.global.autoscan = toggle; end --[[ Slash Handlers ]] -- Reset the settings function SIL:SlashReset() self:Print(L.core.slashClear); self.db:RegisterDefaults(SIL_Defaults); self.db:ResetDB('Default'); self:SetMinimap(true); -- Clear the cache SIL_CacheGUID = {}; self:GetScoreTarget('player', true); -- Update version information self.db.global.version = self.versionMajor; self:RunHooks('clear'); end function SIL:SlashGet(name) -- Get score by name if name and not (name == '' or name == 'target') then local score, age, items = self:GetScoreName(name); if score then local name = self:Cache(self:NameToGUID(name), 'name') self:Print(format(L.core.slashGetScore, name, self:FormatScore(score, items), self:AgeToText(age))); -- Nothing :( else self:Print(format(L.core.slashGetScoreFalse, name)); end -- no name but we can inspect the current target elseif CanInspect('target') then self:SlashTarget(); -- why do you ask so much of me but make no sence else self:Print(L.core.slashTargetScoreFalse); end end function SIL:SlashTarget() self:StartScore('target', function(...) SIL:SlashTargetPrint(...); end); end function SIL:SlashTargetPrint(guid, score, items, age) if guid and score then local name = self:GUIDtoName(guid); if name then self:Print(format(L.core.slashTargetScore, name, self:FormatScore(score, items))); else self:Debug("No name for guid", guid, "score", score, items, age); end else self:Print(L.core.slashTargetScoreFalse); end end --[[ Basic Functions ]] function SIL:GUIDtoName(guid) if guid and self:IsGUID(guid, 'Player') and self:Cache(guid) then return self:Cache(guid, 'name'), self:Cache(guid, 'realm'); else return false; end end function SIL:NameToGUID(name, realm) if not name then return false end -- Try and get the realm from the name-realm if not realm then name, realm = strsplit('-', name, 2); end -- If no realm then set it to current realm if not realm or realm == '' then realm = GetRealmName(); end if name then name = strlower(name); local likely = false; for guid,info in pairs(SIL_CacheGUID) do if strlower(info.name) == name and info.realm == realm then return guid; elseif strlower(info.name) == name then likely = guid; end end if likely then return likely; end end return false; end -- Get a GUID from just about anything function SIL:GetGUID(target) if target then if tonumber(target) then return target; elseif UnitGUID(target) then return UnitGUID(target); else return SIL:NameToGUID(target); end else return false; end end -- Clear score function SIL:ClearScore(target) local guid = self:GetGUID(target); if SIL_CacheGUID[guid] then SIL_CacheGUID[guid].score = false; SIL_CacheGUID[guid].items = false; SIL_CacheGUID[guid].time = false; self:RunHooks('purge', guid); return true; else return false; end end; function SIL:AgeToText(age, color) if type(color) == 'nil' then color = true; end local hex = "00ff00"; if type(age) == 'number' then if age > 86400 then age = self:Round(age / 86400, 2); str = L.core.ageDays; hex = "ff0000"; elseif age > 3600 then age = self:Round(age / 3600, 1); str = L.core.ageHours; hex = "33ccff"; elseif age > 60 then age = self:Round(age / 60, 1); str = L.core.ageMinutes; hex = "00ff00"; else age = age; str = L.core.ageSeconds; hex = "00ff00"; end if color and self:GetColorScore() then return format(str, '|cFF'..hex..age..'|r'); else return format(str, age); end else return 'n/a'; end end -- print a message to channel or whisper player/channel function SIL:PrintTo(message, channel, to) if channel == "print" or channel == "SYSTEM" then self:Print(message); elseif channel == "WHISPER" then SendChatMessage(message, 'WHISPER', nil, to); elseif channel == "CHANNEL" then SendChatMessage(message, 'CHANNEL', nil, to); elseif channel then SendChatMessage(message, channel); else self:Print(message); end end function SIL:Debug(...) if SIL.db.char.debug then print('|cFFFF0000SIL Debug:|r ', ...); end end --[[ Core Functionality ]] -- Get someones score function SIL:GetScore(guid, attemptUpdate, target, callback) if not self:IsGUID(guid, 'Player') then return false; end if self:Cache(guid) and self:Cache(guid, 'score') then local score = self:Cache(guid, 'score'); local age = self:Cache(guid, 'age') or time(); local items = self:Cache(guid, 'items'); local startScore = nil; -- If a target was passed and we are over age if target and (attemptUpdate or self:GetAge() < age) and self.autoscan ~= time() then startScore = self:StartScore(target, callback); end return score, age, items, startScore; else -- If a target was passed if target then self:StartScore(target); end return false; end end -- Wrapers for get score, more specialized code may come function SIL:GetScoreName(name, realm) local guid = self:NameToGUID(name, realm); return self:GetScore(guid); end function SIL:GetScoreTarget(target, force, callback) local guid = UnitGUID(target); return self:GetScore(guid, force, target, callback); end function SIL:GetScoreGUID(guid) return self:GetScore(guid); end -- Request items to update a score function SIL:StartScore(target, callback) if InCombatLockdown() or not CanInspect(target) then if callback then callback(false, target); end return false; end self.autoscan = time(); local guid = self:AddPlayer(target); if not self.lastScan[target] or self.lastScan[target] ~= time() then if guid then self.action[guid] = callback; self.lastScan[target] = time(); local canInspect = self.inspect:RequestItems(target, true); if not canInspect and callback then callback(false, target); else return true; end end end if callback then callback(false, target); end return false; end function SIL:ProcessInspect(guid, data, age) 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')); if totalItems and 0 < totalItems then -- Update the DB local score = totalScore / totalItems; self:SetScore(guid, score, totalItems, age) -- Update LDB if self:GetLDB() and guid == UnitGUID('player') then self:UpdateLDB(true); else self:UpdateLDB(false); end -- Run Hooks self:RunHooks('inspect', guid, score, totalItems, age, data.items); -- Run any callbacks for this event if self.action[guid] then self.action[guid](guid, score, totalItems, age, data.items, self:Cache(guid, 'target')); self.action[guid] = false; end -- Update the Tooltip self:ShowTooltip(); return true; end end end function SIL:GearSum(items, level) if items and level and type(items) == 'table' then local totalItems = 0; local totalScore = 0; for i,itemLink in pairs(items) do if itemLink and not ( i == INVSLOT_BODY or i == INVSLOT_RANGED or i == INVSLOT_TABARD ) then -- local name, link, itemRarity , itemLevel = GetItemInfo(itemLink); local itemLevel = self.itemUpgrade:GetUpgradedItemLevel(itemLink); --- print(i, itemLevel, itemLink); if itemLevel then -- Fix for heirlooms if itemRarity == 7 then itemLevel = self:Heirloom(level, itemLink); end totalItems = totalItems + 1; totalScore = totalScore + itemLevel; end end end return totalScore, totalItems; else return false; end end -- Thanks to Ro of Hyjal-US http://us.battle.net/wow/en/forum/topic/7199032730#9 function SIL:GetActualItemLevelOld(link) -- Updated for 5.4.8 local levelAdjust={ -- 11th item:id field and level adjustment ["0"]=0,["1"]=8,["373"]=4,["374"]=8,["375"]=4,["376"]=4, ["377"]=4,["379"]=4,["380"]=4,["445"]=0,["446"]=4,["447"]=8, ["451"]=0,["452"]=8,["453"]=0,["454"]=4,["455"]=8,["456"]=0, ["457"]=8,["458"]=0,["459"]=4,["460"]=8,["461"]=12,["462"]=16, ["465"]=0,["466"]=4,["467"]=8,["469"]=4,["470"]=8,["471"]=12, ["472"]=16,["491"]=0,["492"]=4,["493"]=8,["494"]=4,["495"]=8, ["496"]=8,["497"]=12,["498"]=16,["504"]=12,["505"]=16,["506"]=20, ["507"]=24, } local baseLevel = select(4,GetItemInfo(link)) local upgrade = link:match(":(%d+)\124h%[") if baseLevel and upgrade and levelAdjust[upgrade] then local newLevel = baseLevel + levelAdjust[upgrade]; return newLevel else return baseLevel 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) if not target then return false; end if not CanInspect(target) then return false; end -- Get stuff in order local guid = self:AddPlayer(target) self.inspect:AddCharacter(target); NotifyInspect(target); -- Get items and sum local items = self.inspect:GetItems(target); local totalScore, totalItems = self:GearSum(items, UnitLevel(target)); if totalItems and totalItems > 0 then local score = totalScore / totalItems; -- self:Debug('SIL:RoughScore', UnitName(target), score, totalItems); -- 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 self:SetScore(guid, score, 1, self:GetAge() + 1); end return score, 1, self:GetAge() + 1; else return false; end end -- Start or update the DB for a player function SIL:AddPlayer(target) local guid = UnitGUID(target); if guid then local name, realm = UnitName(target); local className, class = UnitClass(target); local level = UnitLevel(target); if not realm then realm = GetRealmName(); end if name and realm and class and level then -- Start a table for them if not SIL_CacheGUID[guid] then SIL_CacheGUID[guid] = {}; end SIL_CacheGUID[guid].name = name; SIL_CacheGUID[guid].realm = realm; SIL_CacheGUID[guid].class = class; SIL_CacheGUID[guid].level = level; SIL_CacheGUID[guid].target = target; if not SIL_CacheGUID[guid].score or SIL_CacheGUID[guid].score == 0 then SIL_CacheGUID[guid].score = false; SIL_CacheGUID[guid].items = false; SIL_CacheGUID[guid].time = false; end return guid; else return false; end else return false; end end function SIL:SetScore(guid, score, items, age) local t = age; if age and type(age) == 'number' and age < 86400 then t = time() - age; end SIL_CacheGUID[guid].score = score; SIL_CacheGUID[guid].items = items; SIL_CacheGUID[guid].time = t; self:Debug("SetScore", self:GUIDtoName(guid), self:FormatScore(score, items), items, age) end -- Get a relative iLevel on Heirlooms function SIL:Heirloom(level, itemLink) --[[ Here is how I came to the level 81-85 bracket 200 = level of 80 instance gear 333 = level of 85 instance gear 333 - 200 = 133 iLevels / 5 levels = 26.6 iLevel per level so then that means for a level 83 83 - 80 = 3 * 26.6 = 79.8 + 200 = 279.8 iLevel ]] -- Check for Wrath Heirlooms that max at 80 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?"); itemId = tonumber(itemId); -- Downgrade it to 80 if found for k,iid in pairs(SIL_Heirlooms[80]) do if iid == itemId then level = 80; end end -- There are currently no 1-90 Heirlooms if level > 85 then level = 85 end end if level > 80 then return (( level - 80) * 26.6) + 200; elseif level > 70 then return (( level - 70) * 10) + 100; elseif level > 60 then return (( level - 60) * 4) + 60; else return level; end end -- Format the score for color and round it to xxx.x function SIL:FormatScore(score, items, color) if not items then items = self.grayScore + 1; end if type(color) == 'nil' then color = true; end if score < 0 then score = 0; end -- Ticket #29, thanks Torsin if tonumber(score) and tonumber(items) then local scoreR if self:GetRoundScore() then scoreR = self:Round(tonumber(score), 0); else scoreR = self:Round(tonumber(score), 1); end if color then local hexColor = self:ColorScore(score, items); return '|cFF'..hexColor..scoreR..'|r'; else return scoreR; end else return 'n/a'; end end -- Return the hex, r, g, b of a score function SIL:ColorScore(score, items) -- There are some missing items so gray if items and items <= self.grayScore then return self:RGBtoHex(0.5,0.5,0.5), 0.5,0.5,0.5; end if not self:GetColorScore() then return self:RGBtoHex(1,1,1), 1,1,1; end -- Default to white local r,g,b = 1,1,1; local found = false; for i,maxScore in pairs(SIL_ColorIndex) do if score < maxScore and not found then local colors = SIL_Colors[maxScore]; local baseColors = SIL_Colors[colors.p]; local steps = maxScore - colors.p; local scoreDiff = score - colors.p; local diffR = (baseColors.r - colors.r) / 255; local diffG = (baseColors.g - colors.g) / 255; local diffB = (baseColors.b - colors.b) / 255; local diffStepR = diffR / steps; local diffStepG = diffG / steps; local diffStepB = diffB / steps; local scoreDiffR = scoreDiff * diffStepR; local scoreDiffG = scoreDiff * diffStepG; local scoreDiffB = scoreDiff * diffStepB; r = (baseColors.r / 255) - scoreDiffR; g = (baseColors.g / 255) - scoreDiffG; b = (baseColors.b / 255) - scoreDiffB; found = true; end end -- Nothing was found so max if not found then r = SIL_Colors[1000].r; g = SIL_Colors[1000].g; b = SIL_Colors[1000].b; end local hex = self:RGBtoHex(r,g,b); return hex, r, g, b; end function SIL:ShowTooltip(guid) if InCombatLockdown() and not self:GetTTCombat() then return end 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 = false; for i = 1,ttLines do -- If the static text matches if _G["GameTooltipTextLeft"..i]:GetText() == textLeft then -- Update the text _G["GameTooltipTextLeft"..i]:SetText(textLeft); _G["GameTooltipTextRight"..i]:SetText(textRight); GameTooltip:Show(); -- Update the advanced info too if self.db.global.advanced and textAdvanced then if textAdvancedRight then _G["GameTooltipTextLeft"..i]:SetText(textAdvanced); _G["GameTooltipTextRight"..i]:SetText(textAdvancedRight); else _G["GameTooltipTextLeft"..i+1]:SetText(textAdvanced); end GameTooltip:Show(); end -- Remember that we have updated the tool tip so we won't again ttUpdated = true; break; end end -- Tooltip is new if not ttUpdated then GameTooltip:AddDoubleLine(textLeft, textRight); GameTooltip:Show(); if self.db.global.advanced and textAdvanced then if textAdvancedRight then GameTooltip:AddDoubleLine(textAdvanced, textAdvancedRight); else GameTooltip:AddLine(textAdvanced); end GameTooltip:Show(); end end end function SIL:UpdatePaperDollFrame(statFrame, unit) local score, age, items = self:GetScoreTarget(unit, true); local formated = self:FormatScore(score, items, false); PaperDollFrame_SetLabelAndText(statFrame, L.core.name, formated, false); statFrame.tooltip = HIGHLIGHT_FONT_COLOR_CODE..L.core.name..FONT_COLOR_CODE_CLOSE; statFrame.tooltip2 = L.core.scoreDesc; statFrame:Show(); end --[[ Setters, Getter and Togglers ]] -- Set function SIL:SetAdvanced(v) self.db.global.advanced = v; end function SIL:SetLabel(v) self.db.global.showLabel = v; self:UpdateLDB(); end function SIL:SetAutoscan(v) self.db.global.autoscan = v; self:Autoscan(v); end function SIL:SetAge(seconds) self.db.global.age = seconds; end function SIL:SetLDBlabel(v) self.db.global.ldbLabel = v; self:UpdateLDB(true); end function SIL:SetLDBrefresh(v) self.db.global.ldbRefresh = v; self:LDBSetAuto() end function SIL:SetTTCombat(v) self.db.global.ttCombat = v; end function SIL:SetColorScore(v) self.db.global.color = v; end function SIL:SetRoundScore(v) self.db.global.round = v; end function SIL:SetMouseOver(v) self.db.global.mouseover = v; end function SIL:SetDebug(v) self.db.char.debug = v; end -- Get function SIL:GetAdvanced() return self.db.global.advanced; end function SIL:GetMinimap() return not self.db.global.minimap.hide; end function SIL:GetAutoscan() return self.db.global.autoscan; end function SIL:GetPaperdoll() return self.db.global.cinfo; end function SIL:GetAge() return self.db.global.age; end function SIL:GetPurge() return self.db.global.purge; end function SIL:GetLabel() return self.db.global.showLabel; end function SIL:GetLDB() return self.db.global.ldbText; end function SIL:GetLDBlabel() return self.db.global.ldbLabel; end function SIL:GetLDBrefresh() return self.db.global.ldbRefresh; end function SIL:GetTTCombat() return self.db.global.ttCombat; end function SIL:GetColorScore() return self.db.global.color; end function SIL:GetRoundScore() return self.db.global.round; end function SIL:GetMouseOver() return self.db.global.mouseover; end function SIL:GetModule(m) return self.db.char.module[m]; end function SIL:GetDebug(m) return self.db.char.debug; end -- Toggle function SIL:ToggleAdvanced() self:SetAdvanced(not self:GetAdvanced()); end function SIL:ToggleMinimap() self:SetMinimap(not self:GetMinimap()); end function SIL:ToggleAutoscan() self:SetAutoscan(not self:GetAutoscan()); end function SIL:TogglePaperdoll() self:SetPaperdoll(not self:GetPaperdoll()); end function SIL:ToggleLabel() self:SetLabel(not self:GetLabel()); end function SIL:ToggleLDBlabel() self:SetLDBlabel(not self:GetLDBlabel()); end function SIL:ToggleTTCombat() self:SetTTCombat(not self:GetTTCombat()); end function SIL:ToggleColorScore() self:SetColorScore(not self:GetColorScore()); end function SIL:ToggleRoundScore() self:SetRoundScore(not self:GetRoundScore()); end function SIL:ToggleMouseOver() self:SetMouseOver(not self:GetMouseOver()); end function SIL:ToggleColorScore(m) self:SetModule(m, not self:GetModule(m)); end function SIL:ToggleDebug(m) self:SetDebug(not self:GetDebug()); end -- Advanced sets function SIL:SetPurge(hours) self.db.global.purge = hours; SIL_Options.args.purge.desc = format(L.core.options.purgeDesc, self.db.global.purge / 24); end function SIL:SetMinimap(v) self.db.global.minimap.hide = not v; if not v then self.ldbIcon:Hide(L.core.name); else self.ldbIcon:Show(L.core.name); end end function SIL:SetPaperdoll(v) self.db.global.cinfo = v; if v then self:RegisterPaperdoll() else self:UnregisterPaperdoll() end end function SIL:SetLDB(v) self.db.global.ldbText = v; if v then --self:RegisterEvent("GROUP_ROSTER_UPDATE"); self.ldb.type = 'data source'; else --self:UnregisterEvent("GROUP_ROSTER_UPDATE"); self.ldb.type = 'launcher'; self.ldb.text = nil; end self:UpdateLDB(true); end function SIL:SetModule(m, v) self.db.char.module[m] = v; if v then self:ModuleLoad(m); end end --[[ GUI Functions ]] -- Open the options window function SIL:ShowOptions() -- Not using this until a paramiter is added to open expanded -- InterfaceOptionsFrame_OpenToCategory(L.core.name); for i,element in pairs(INTERFACEOPTIONS_ADDONCATEGORIES) do if element.name == L.core.name then if not InterfaceOptionsFrame:IsShown() then InterfaceOptionsFrame_Show(); InterfaceOptionsFrameTab2:Click(); end for i,button in pairs(InterfaceOptionsFrameAddOns.buttons) do if button.element == element then InterfaceOptionsListButton_OnClick(button); -- Expand if element.hasChildren and element.collapsed then OptionsListButtonToggle_OnClick(button.toggle); end -- Hide anything else that is open elseif button.element and type(button.element.collapsed) == 'boolean' and not button.element.collapsed then OptionsListButtonToggle_OnClick(button.toggle); end end end end end function SIL:UpdateLDB(force, auto) if self:GetLDB() then local label = UnitName('player'); if SIL_Group then groupType,label = SIL_Group:GroupType(); end -- Do we really need to update LDB? if force or label ~= self.ldbLable or (self.ldbUpdated + self:GetLDBrefresh()) < time() then local text = 'n/a'; local _, itype = GetInstanceInfo(); if (itype == 'pvp' or itype == 'arena') and SIL_Resil then local groupPercent = SIL_Resil:GroupSum(); groupPercent = SIL_Resil:FormatPercent(groupPercent, true); text = groupPercent; if SIL_Group then local groupScore = SIL_Group:GroupScore(); groupScore = self:FormatScore(groupScore, self.grayScore + 1, true); text = groupScore..' '..text; end elseif SIL_Group then local groupScore = SIL_Group:GroupScore() text = self:FormatScore(groupScore, 16, true); elseif UnitGUID('player') then local score, age, items = self:GetScoreTarget('player'); text = self:FormatScore(score, items, true); end self:UpdateLDBText(label, text) end else self.ldb.type = 'launcher'; self.ldb.text = nil; end end function SIL:UpdateLDBText(label, text) if not self:GetLDB() then return false; end -- Add the label if self:GetLDBlabel() then text = label..": "..text; end self.ldb.text = text; self.ldbUpdated = time(); self.ldbLable = label; end function SIL:LDBSetAuto() if self.ldbAuto then self:CancelTimer(self.ldbAuto, true); end self.ldbAuto = self:ScheduleRepeatingTimer(function() if not InCombatLockdown() then SIL:Debug('Auto LDB...'); SIL:UpdateLDB(false, true); end end, self:GetLDBrefresh()); end function SIL:GMICallback(name) local score, age, items = self:GetScoreName(name); if score and tonumber(score) and 0 < score then return self:FormatScore(score, items, false); else return 'n/a'; end end function SIL:Cache(guid, what) if not guid and not self:IsGUID(guid, 'Player') then return false end if SIL_CacheGUID[guid] and what then if what == 'age' then if SIL_CacheGUID[guid].time then return time() - SIL_CacheGUID[guid].time; else return nil; end else return SIL_CacheGUID[guid][what]; end elseif SIL_CacheGUID[guid] then return true; else return false; end end function SIL:IsGUID(guid, type) if not guid then return false end if not type then type = 'player' end local gType, gGuid = strsplit('-', guid, 2); if strlower(type) == strlower(gType) then return true else return false end end function SIL:UpdateGroup() self.group = {}; local playerGUID = self:AddPlayer('player'); table.insert(self.group, playerGUID); if UnitInBattleground('player') or UnitInRaid('player') then for i=1,MAX_RAID_MEMBERS do local target = 'raid'..i; local guid = self:AddPlayer(target); if guid and guid ~= playerGUID then table.insert(self.group, guid); if not self:Cache(guid, 'score') then self:RoughScore(target); end end end elseif GetNumSubgroupMembers() > 0 then for i=1,MAX_PARTY_MEMBERS do local target = 'party'..i; local guid = self:AddPlayer(target); if guid then table.insert(self.group, guid); if not self:Cache(guid, 'score') then self:RoughScore(target); end end end end end function SIL:GroupDest(dest, to) local valid = false; local color = false; if not dest then dest = "SYSTEM"; valid = true; end if dest == '' then dest = "SYSTEM"; valid = true; end dest = string.upper(dest); -- Some short codes, should be a table if dest == 'P' then dest = 'PARTY'; valid = true; end if dest == 'R' then dest = 'RAID'; valid = true; end if dest == 'BG' then dest = 'BATTLEGROUND'; valid = true; end if dest == 'G' then dest = 'GUILD'; valid = true; end if dest == 'U' then dest = 'GROUP'; valid = true; end if dest == 'A' then dest = 'GROUP'; valid = true; end if dest == 'O' then dest = 'OFFICER'; valid = true; end if dest == 'S' then dest = 'SAY'; valid = true; end if dest == 'T' then dest = 'WHISPER'; valid = true; end if dest == 'W' then dest = 'WHISPER'; valid = true; end if dest == 'TELL' then dest = 'WHISPER'; valid = true; end if dest == 'C' then dest = 'CHANNEL'; valid = true; end if dest == 'I' then dest = 'INSTANCE_CHAT'; valid = true; end -- Find out if its a valid dest for fixed,loc in pairs(SIL_Channels) do if dest == string.upper(loc) then dest = fixed; valid = true; elseif dest == string.upper(fixed) then dest = fixed; valid = true; end end -- Default to system if not valid then dest = "SYSTEM"; end -- Figure out GROUP if dest == 'GROUP' and IsInGroup() then if UnitInBattleground("player") then dest = 'BATTLEGROUND'; elseif IsInGroup(LE_PARTY_CATEGORY_INSTANCE) then dest = 'INSTANCE_CHAT'; elseif UnitInRaid("player") then dest = 'RAID'; elseif IsInGroup(LE_PARTY_CATEGORY_HOME) then dest = 'PARTY'; else dest = 'SAY'; end end if dest == "SYSTEM" then color = true; end return dest, to, color; end function SIL:RegisterPaperdoll() if not self:GetPaperdoll() then return false; end table.insert(PAPERDOLL_STATCATEGORIES[1].stats, { stat = 'SIL', }); PAPERDOLL_STATINFO['SIL'] = { updateFunc = function(...) SIL:UpdatePaperDollFrame(...); end }; end function SIL:UnregisterPaperdoll() if self:GetPaperdoll() then return false; end table.foreach(PAPERDOLL_STATCATEGORIES[1].stats, function(k, v) if v.stat == 'SIL' then table.remove(PAPERDOLL_STATCATEGORIES[1].stats, k); end end); PAPERDOLL_STATINFO['SIL'] = { updateFunc = function(...) return false; end }; end
수정본
파일 열기
--[[ ToDo: - Move more Group Functionality to here * Autoscan * SIL_Group:GroupType(); - On UpdateGroup if there is no data do a rough scan - Group methods within this file - Better way to hooking tooltips - ]] local L = LibStub("AceLocale-3.0"):GetLocale("SimpleILevel", true); -- Start SIL 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.version = GetAddOnMetadata("SimpleILevel", "Version"); SIL.versionMajor = 3; -- Used for cache DB versioning SIL.versionRev = 'r251'; -- Used for version information SIL.action = {}; -- DB of unitGUID->function to run when a update comes through SIL.hooks = {}; -- List of hooks in [type][] = function; SIL.autoscan = 0; -- time() value of last autoscan, must be more then 1sec SIL.lastScan = {}; -- target = time(); SIL.grayScore = 7; -- Number of items to consider gray/aprox SIL.ldbAuto = false; -- AceTimer for LDB SIL.menu = false; -- Menu frame SIL.menuItems = { -- Table for the dropdown menu top = {}, middle = {}, bottom = {}, }; SIL.modules = {}; -- Modules SIL.group = {}; -- Group Members by guid --SIL.L = L; -- Non-local locals -- Load Libs SIL.aceConfig = LibStub:GetLibrary("AceConfig-3.0"); SIL.aceConfigDialog = LibStub:GetLibrary("AceConfigDialog-3.0"); SIL.inspect = LibStub:GetLibrary("LibInspect"); SIL.ldb = LibStub:GetLibrary("LibDataBroker-1.1"); SIL.ldbIcon = LibStub:GetLibrary("LibDBIcon-1.0"); SIL.callback = LibStub("CallbackHandler-1.0"):New(SIL); SIL.itemUpgrade = LibStub("LibItemUpgradeInfo-1.0"); -- OnLoad function SIL:OnInitialize() -- Make sure everything is ok with the db if not SIL_CacheGUID or type(SIL_CacheGUID) ~= 'table' then SIL_CacheGUID = {}; end -- Tell the player we are being loaded self:Print(format(L.core.load, self.version)); self:ModulesProcess(); -- Load settings self.db = LibStub("AceDB-3.0"):New("SIL_Settings", SIL_Defaults, true); self:UpdateSettings(); -- Set Up LDB local ldbObj = { type = "data source", icon = "Interface\\Icons\\inv_misc_armorkit_24", label = L.core.name, text = 'n/a', category = self.category, version = self.version, OnClick = function(...) SIL:MenuOpen(...); end, OnTooltipShow = function(tt) if SIL:GetLDB() and SIL.ldb.text then tt:AddLine(SIL.ldb.text); end tt:AddLine(L.core.minimapClick); tt:AddLine(L.core.minimapClickDrag); end, }; -- Set back to a launcher if text is off if not self:GetLDB() then ldbObj.type = 'launcher'; ldbObj.text = nil; end -- Start LDB self.ldb = self.ldb:NewDataObject(L.core.name, ldbObj); self.ldbUpdated = 0; self.ldbLable = ''; -- Start the minimap icon self.ldbIcon:Register(L.core.name, self.ldb, self.db.global.minimap); -- Register Options 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.aceConfigDialog:AddToBlizOptions(L.core.name); -- Add Hooks self.inspect:AddHook(L.core.name, 'items', function(...) SIL:ProcessInspect(...); end); GameTooltip:HookScript("OnTooltipSetUnit", function(...) SIL:TooltipHook(...); end); self:Autoscan(self:GetAutoscan()); -- Events 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_ENTERING_WORLD", function() SIL:UpdateLDB(); end); self:RegisterEvent("GROUP_ROSTER_UPDATE", function() SIL:UpdateGroup() end); self:RegisterEvent("UPDATE_MOUSEOVER_UNIT", function() if SIL:GetMouseOver() and CanInspect('mouseover') then SIL:Debug('mouseover', UnitName('mouseover')); SIL:GetScoreTarget('mouseover'); end SIL:ShowTooltip(); end); -- Add to Paperdoll if self:GetPaperdoll() then self:RegisterPaperdoll(); end -- GuildMemberInfo if GMI then GMI:Register("SimpleILevel", { lines = { SimpleILevel = { label = L.core.name, default = 'n/a', callback = function(name) return SIL:GMICallback(name); end, }, }, }); end -- Clear the cache self:AutoPurge(true); -- Build the menu self:MenuInitialize(); -- Get working on a score for the player self:StartScore('player'); self:LDBSetAuto(); self:UpdateLDB(); -- This may cause excesive loading time... -- Process modules self:ModulesLoad(); -- Localization Notice if GetLocale() == 'itIT' or GetLocale() == 'esMX' or GetLocale() == 'esES' then self:Print("Help Localize Simple iLevel! http://j.mp/localSIL") end end -- Make sure the database is the latest version function SIL:UpdateSettings() if self.db.global.version == self.versionMajor then -- Same version elseif self.db.global.version > 2.4 and self.db.global.version < 2.5 then for guid,info in pairs(SIL_CacheGUID) do SIL_CacheGUID[guid].guid = nil; end elseif self.db.global.version < 2.4 then for guid,info in pairs(SIL_CacheGUID) do SIL_CacheGUID[guid].total = nil; SIL_CacheGUID[guid].tooltip = nil; SIL_CacheGUID[guid].level = 85; --ASSuME --SIL_CacheGUID[guid].guid = guid; end end -- Update version information self.db.global.version = self.versionMajor; end function SIL:AutoPurge(silent) if self:GetPurge() > 0 then local count = self:PurgeCache(self:GetPurge()); if not silent then self:Print(format(L.core.purgeNotification, count)); end return count; else if not silent then self:Print(L.core.purgeNotificationFalse); end return false; end end function SIL:PurgeCache(hours) if tonumber(hours) then local maxAge = time() - (tonumber(hours) * 3600); local count = 0; for guid,info in pairs(SIL_CacheGUID) do if type(info.time) == "number" and info.time < maxAge then SIL_CacheGUID[guid] = nil; count = 1 + count; self:RunHooks('purge', guid); end end return count; else return false; end end function SIL:AddHook(hookType, callback) local hookType = strlower(hookType); if not self.hooks[hookType] then self.hooks[hookType] = {}; end table.insert(self.hooks[hookType], callback); end function SIL:RunHooks(hookType, ...) local r = {}; if self.hooks[hookType] then for i,callback in pairs(self.hooks[hookType]) do local ret = callback(...); if ret then table.insert(r, callback(...)); end end if #r > 0 then return r; else return true; end else return false; end end --[[ Event Handlers ]] function SIL:UNIT_INVENTORY_CHANGED(e, unitID) --print('UNIT_INVENTORY_CHANGED'); if InCombatLockdown() then return end if unitID and CanInspect(unitID) and not UnitIsUnit('player', unitID) and self.autoscan ~= time() then self.autoscan = time(); self:StartScore(unitID); end end -- Used to hook the tooltip to avoid the full tooltip function function SIL:TooltipHook() local name, unit = GameTooltip:GetUnit(); local guid = false; if unit then guid = UnitGUID(unit); elseif name then guid = self:NameToGUID(name); end if self:IsGUID(guid, 'Player') then self:ShowTooltip(guid); end end function SIL:Autoscan(toggle) if toggle then self:RegisterEvent("UNIT_INVENTORY_CHANGED"); else self:UnregisterEvent("UNIT_INVENTORY_CHANGED"); end self.db.global.autoscan = toggle; end --[[ Slash Handlers ]] -- Reset the settings function SIL:SlashReset() self:Print(L.core.slashClear); self.db:RegisterDefaults(SIL_Defaults); self.db:ResetDB('Default'); self:SetMinimap(true); -- Clear the cache SIL_CacheGUID = {}; self:GetScoreTarget('player', true); -- Update version information self.db.global.version = self.versionMajor; self:RunHooks('clear'); end function SIL:SlashGet(name) -- Get score by name if name and not (name == '' or name == 'target') then local score, age, items = self:GetScoreName(name); if score then local name = self:Cache(self:NameToGUID(name), 'name') self:Print(format(L.core.slashGetScore, name, self:FormatScore(score, items), self:AgeToText(age))); -- Nothing :( else self:Print(format(L.core.slashGetScoreFalse, name)); end -- no name but we can inspect the current target elseif CanInspect('target') then self:SlashTarget(); -- why do you ask so much of me but make no sence else self:Print(L.core.slashTargetScoreFalse); end end function SIL:SlashTarget() self:StartScore('target', function(...) SIL:SlashTargetPrint(...); end); end function SIL:SlashTargetPrint(guid, score, items, age) if guid and score then local name = self:GUIDtoName(guid); if name then self:Print(format(L.core.slashTargetScore, name, self:FormatScore(score, items))); else self:Debug("No name for guid", guid, "score", score, items, age); end else self:Print(L.core.slashTargetScoreFalse); end end --[[ Basic Functions ]] function SIL:GUIDtoName(guid) if guid and self:IsGUID(guid, 'Player') and self:Cache(guid) then return self:Cache(guid, 'name'), self:Cache(guid, 'realm'); else return false; end end function SIL:NameToGUID(name, realm) if not name then return false end -- Try and get the realm from the name-realm if not realm then name, realm = strsplit('-', name, 2); end -- If no realm then set it to current realm if not realm or realm == '' then realm = GetRealmName(); end if name then name = strlower(name); local likely = false; for guid,info in pairs(SIL_CacheGUID) do if strlower(info.name) == name and info.realm == realm then return guid; elseif strlower(info.name) == name then likely = guid; end end if likely then return likely; end end return false; end -- Get a GUID from just about anything function SIL:GetGUID(target) if target then if tonumber(target) then return target; elseif UnitGUID(target) then return UnitGUID(target); else return SIL:NameToGUID(target); end else return false; end end -- Clear score function SIL:ClearScore(target) local guid = self:GetGUID(target); if SIL_CacheGUID[guid] then SIL_CacheGUID[guid].score = false; SIL_CacheGUID[guid].items = false; SIL_CacheGUID[guid].time = false; self:RunHooks('purge', guid); return true; else return false; end end; function SIL:AgeToText(age, color) if type(color) == 'nil' then color = true; end local hex = "00ff00"; if type(age) == 'number' then if age > 86400 then age = self:Round(age / 86400, 2); str = L.core.ageDays; hex = "ff0000"; elseif age > 3600 then age = self:Round(age / 3600, 1); str = L.core.ageHours; hex = "33ccff"; elseif age > 60 then age = self:Round(age / 60, 1); str = L.core.ageMinutes; hex = "00ff00"; else age = age; str = L.core.ageSeconds; hex = "00ff00"; end if color and self:GetColorScore() then return format(str, '|cFF'..hex..age..'|r'); else return format(str, age); end else return 'n/a'; end end -- print a message to channel or whisper player/channel function SIL:PrintTo(message, channel, to) if channel == "print" or channel == "SYSTEM" then self:Print(message); elseif channel == "WHISPER" then SendChatMessage(message, 'WHISPER', nil, to); elseif channel == "CHANNEL" then SendChatMessage(message, 'CHANNEL', nil, to); elseif channel then SendChatMessage(message, channel); else self:Print(message); end end function SIL:Debug(...) if SIL.db.char.debug then print('|cFFFF0000SIL Debug:|r ', ...); end end --[[ Core Functionality ]] -- Get someones score function SIL:GetScore(guid, attemptUpdate, target, callback) if not self:IsGUID(guid, 'Player') then return false; end if self:Cache(guid) and self:Cache(guid, 'score') then local score = self:Cache(guid, 'score'); local age = self:Cache(guid, 'age') or time(); local items = self:Cache(guid, 'items'); local startScore = nil; -- If a target was passed and we are over age if target and (attemptUpdate or self:GetAge() < age) and self.autoscan ~= time() then startScore = self:StartScore(target, callback); end return score, age, items, startScore; else -- If a target was passed if target then self:StartScore(target); end return false; end end -- Wrapers for get score, more specialized code may come function SIL:GetScoreName(name, realm) local guid = self:NameToGUID(name, realm); return self:GetScore(guid); end function SIL:GetScoreTarget(target, force, callback) local guid = UnitGUID(target); return self:GetScore(guid, force, target, callback); end function SIL:GetScoreGUID(guid) return self:GetScore(guid); end -- Request items to update a score function SIL:StartScore(target, callback) if InCombatLockdown() or not CanInspect(target) then if callback then callback(false, target); end return false; end self.autoscan = time(); local guid = self:AddPlayer(target); if not self.lastScan[target] or self.lastScan[target] ~= time() then if guid then self.action[guid] = callback; self.lastScan[target] = time(); local canInspect = self.inspect:RequestItems(target, true); if not canInspect and callback then callback(false, target); else return true; end end end if callback then callback(false, target); end return false; end function SIL:ProcessInspect(guid, data, age) 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')); if totalItems and 0 < totalItems then -- Update the DB local score = totalScore / totalItems; self:SetScore(guid, score, totalItems, age) -- Update LDB if self:GetLDB() and guid == UnitGUID('player') then self:UpdateLDB(true); else self:UpdateLDB(false); end -- Run Hooks self:RunHooks('inspect', guid, score, totalItems, age, data.items); -- Run any callbacks for this event if self.action[guid] then self.action[guid](guid, score, totalItems, age, data.items, self:Cache(guid, 'target')); self.action[guid] = false; end -- Update the Tooltip self:ShowTooltip(); return true; end end end function SIL:GearSum(items, level) if items and level and type(items) == 'table' then local totalItems = 0; local totalScore = 0; local mainhandArtifactIlvlCache = 0; local offhandAtifactIlvlCache=0; for i,itemLink in pairs(items) do if itemLink and not ( i == INVSLOT_BODY or i == INVSLOT_RANGED or i == INVSLOT_TABARD ) then local name, link, itemRarity , _ = GetItemInfo(itemLink); local itemLevel = self.itemUpgrade:GetUpgradedItemLevel(itemLink); -- print(i, itemLevel, itemLink, itemRarity); if itemLevel then -- Fix for OH Artifact (always calculated as 750 ilvl) if itemRarity == 6 then --Cache MH Artifact ilvl if higher if i == INVSLOT_MAINHAND then mainhandArtifactIlvlCache = itemLevel; end --Cache OH Artifact ilvl if higher if i == INVSLOT_OFFHAND then offhandAtifactIlvlCache = itemLevel end end totalItems = totalItems + 1; totalScore = totalScore + itemLevel; 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; else return false; end end -- Thanks to Ro of Hyjal-US http://us.battle.net/wow/en/forum/topic/7199032730#9 function SIL:GetActualItemLevelOld(link) -- Updated for 5.4.8 local levelAdjust={ -- 11th item:id field and level adjustment ["0"]=0,["1"]=8,["373"]=4,["374"]=8,["375"]=4,["376"]=4, ["377"]=4,["379"]=4,["380"]=4,["445"]=0,["446"]=4,["447"]=8, ["451"]=0,["452"]=8,["453"]=0,["454"]=4,["455"]=8,["456"]=0, ["457"]=8,["458"]=0,["459"]=4,["460"]=8,["461"]=12,["462"]=16, ["465"]=0,["466"]=4,["467"]=8,["469"]=4,["470"]=8,["471"]=12, ["472"]=16,["491"]=0,["492"]=4,["493"]=8,["494"]=4,["495"]=8, ["496"]=8,["497"]=12,["498"]=16,["504"]=12,["505"]=16,["506"]=20, ["507"]=24, } local baseLevel = select(4,GetItemInfo(link)) local upgrade = link:match(":(%d+)\124h%[") if baseLevel and upgrade and levelAdjust[upgrade] then local newLevel = baseLevel + levelAdjust[upgrade]; return newLevel else return baseLevel 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) if not target then return false; end if not CanInspect(target) then return false; end -- Get stuff in order local guid = self:AddPlayer(target) self.inspect:AddCharacter(target); NotifyInspect(target); -- Get items and sum local items = self.inspect:GetItems(target); local totalScore, totalItems = self:GearSum(items, UnitLevel(target)); if totalItems and totalItems > 0 then local score = totalScore / totalItems; -- self:Debug('SIL:RoughScore', UnitName(target), score, totalItems); -- 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 self:SetScore(guid, score, 1, self:GetAge() + 1); end return score, 1, self:GetAge() + 1; else return false; end end -- Start or update the DB for a player function SIL:AddPlayer(target) local guid = UnitGUID(target); if guid then local name, realm = UnitName(target); local className, class = UnitClass(target); local level = UnitLevel(target); if not realm then realm = GetRealmName(); end if name and realm and class and level then -- Start a table for them if not SIL_CacheGUID[guid] then SIL_CacheGUID[guid] = {}; end SIL_CacheGUID[guid].name = name; SIL_CacheGUID[guid].realm = realm; SIL_CacheGUID[guid].class = class; SIL_CacheGUID[guid].level = level; SIL_CacheGUID[guid].target = target; if not SIL_CacheGUID[guid].score or SIL_CacheGUID[guid].score == 0 then SIL_CacheGUID[guid].score = false; SIL_CacheGUID[guid].items = false; SIL_CacheGUID[guid].time = false; end return guid; else return false; end else return false; end end function SIL:SetScore(guid, score, items, age) local t = age; if age and type(age) == 'number' and age < 86400 then t = time() - age; end SIL_CacheGUID[guid].score = score; SIL_CacheGUID[guid].items = items; SIL_CacheGUID[guid].time = t; self:Debug("SetScore", self:GUIDtoName(guid), self:FormatScore(score, items), items, age) end -- Get a relative iLevel on Heirlooms function SIL:Heirloom(level, itemLink) --[[ Here is how I came to the level 81-85 bracket 200 = level of 80 instance gear 333 = level of 85 instance gear 333 - 200 = 133 iLevels / 5 levels = 26.6 iLevel per level so then that means for a level 83 83 - 80 = 3 * 26.6 = 79.8 + 200 = 279.8 iLevel ]] -- Check for Wrath Heirlooms that max at 80 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?"); itemId = tonumber(itemId); -- Downgrade it to 80 if found for k,iid in pairs(SIL_Heirlooms[80]) do if iid == itemId then level = 80; end end -- There are currently no 1-90 Heirlooms if level > 85 then level = 85 end end if level > 80 then return (( level - 80) * 26.6) + 200; elseif level > 70 then return (( level - 70) * 10) + 100; elseif level > 60 then return (( level - 60) * 4) + 60; else return level; end end -- Format the score for color and round it to xxx.x function SIL:FormatScore(score, items, color) if not items then items = self.grayScore + 1; end if type(color) == 'nil' then color = true; end if score < 0 then score = 0; end -- Ticket #29, thanks Torsin if tonumber(score) and tonumber(items) then local scoreR if self:GetRoundScore() then scoreR = self:Round(tonumber(score), 0); else scoreR = self:Round(tonumber(score), 1); end if color then local hexColor = self:ColorScore(score, items); return '|cFF'..hexColor..scoreR..'|r'; else return scoreR; end else return 'n/a'; end end -- Return the hex, r, g, b of a score function SIL:ColorScore(score, items) -- There are some missing items so gray if items and items <= self.grayScore then return self:RGBtoHex(0.5,0.5,0.5), 0.5,0.5,0.5; end if not self:GetColorScore() then return self:RGBtoHex(1,1,1), 1,1,1; end -- Default to white local r,g,b = 1,1,1; local found = false; for i,maxScore in pairs(SIL_ColorIndex) do if score < maxScore and not found then local colors = SIL_Colors[maxScore]; local baseColors = SIL_Colors[colors.p]; local steps = maxScore - colors.p; local scoreDiff = score - colors.p; local diffR = (baseColors.r - colors.r) / 255; local diffG = (baseColors.g - colors.g) / 255; local diffB = (baseColors.b - colors.b) / 255; local diffStepR = diffR / steps; local diffStepG = diffG / steps; local diffStepB = diffB / steps; local scoreDiffR = scoreDiff * diffStepR; local scoreDiffG = scoreDiff * diffStepG; local scoreDiffB = scoreDiff * diffStepB; r = (baseColors.r / 255) - scoreDiffR; g = (baseColors.g / 255) - scoreDiffG; b = (baseColors.b / 255) - scoreDiffB; found = true; end end -- Nothing was found so max if not found then r = SIL_Colors[1000].r; g = SIL_Colors[1000].g; b = SIL_Colors[1000].b; end local hex = self:RGBtoHex(r,g,b); return hex, r, g, b; end function SIL:ShowTooltip(guid) if InCombatLockdown() and not self:GetTTCombat() then return end 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 = false; for i = 1,ttLines do -- If the static text matches if _G["GameTooltipTextLeft"..i]:GetText() == textLeft then -- Update the text _G["GameTooltipTextLeft"..i]:SetText(textLeft); _G["GameTooltipTextRight"..i]:SetText(textRight); GameTooltip:Show(); -- Update the advanced info too if self.db.global.advanced and textAdvanced then if textAdvancedRight then _G["GameTooltipTextLeft"..i]:SetText(textAdvanced); _G["GameTooltipTextRight"..i]:SetText(textAdvancedRight); else _G["GameTooltipTextLeft"..i+1]:SetText(textAdvanced); end GameTooltip:Show(); end -- Remember that we have updated the tool tip so we won't again ttUpdated = true; break; end end -- Tooltip is new if not ttUpdated then GameTooltip:AddDoubleLine(textLeft, textRight); GameTooltip:Show(); if self.db.global.advanced and textAdvanced then if textAdvancedRight then GameTooltip:AddDoubleLine(textAdvanced, textAdvancedRight); else GameTooltip:AddLine(textAdvanced); end GameTooltip:Show(); end end end function SIL:UpdatePaperDollFrame(statFrame, unit) local score, age, items = self:GetScoreTarget(unit, true); local formated = self:FormatScore(score, items, false); PaperDollFrame_SetLabelAndText(statFrame, L.core.name, formated, false); statFrame.tooltip = HIGHLIGHT_FONT_COLOR_CODE..L.core.name..FONT_COLOR_CODE_CLOSE; statFrame.tooltip2 = L.core.scoreDesc; statFrame:Show(); end --[[ Setters, Getter and Togglers ]] -- Set function SIL:SetAdvanced(v) self.db.global.advanced = v; end function SIL:SetLabel(v) self.db.global.showLabel = v; self:UpdateLDB(); end function SIL:SetAutoscan(v) self.db.global.autoscan = v; self:Autoscan(v); end function SIL:SetAge(seconds) self.db.global.age = seconds; end function SIL:SetLDBlabel(v) self.db.global.ldbLabel = v; self:UpdateLDB(true); end function SIL:SetLDBrefresh(v) self.db.global.ldbRefresh = v; self:LDBSetAuto() end function SIL:SetTTCombat(v) self.db.global.ttCombat = v; end function SIL:SetColorScore(v) self.db.global.color = v; end function SIL:SetRoundScore(v) self.db.global.round = v; end function SIL:SetMouseOver(v) self.db.global.mouseover = v; end function SIL:SetDebug(v) self.db.char.debug = v; end -- Get function SIL:GetAdvanced() return self.db.global.advanced; end function SIL:GetMinimap() return not self.db.global.minimap.hide; end function SIL:GetAutoscan() return self.db.global.autoscan; end function SIL:GetPaperdoll() return self.db.global.cinfo; end function SIL:GetAge() return self.db.global.age; end function SIL:GetPurge() return self.db.global.purge; end function SIL:GetLabel() return self.db.global.showLabel; end function SIL:GetLDB() return self.db.global.ldbText; end function SIL:GetLDBlabel() return self.db.global.ldbLabel; end function SIL:GetLDBrefresh() return self.db.global.ldbRefresh; end function SIL:GetTTCombat() return self.db.global.ttCombat; end function SIL:GetColorScore() return self.db.global.color; end function SIL:GetRoundScore() return self.db.global.round; end function SIL:GetMouseOver() return self.db.global.mouseover; end function SIL:GetModule(m) return self.db.char.module[m]; end function SIL:GetDebug(m) return self.db.char.debug; end -- Toggle function SIL:ToggleAdvanced() self:SetAdvanced(not self:GetAdvanced()); end function SIL:ToggleMinimap() self:SetMinimap(not self:GetMinimap()); end function SIL:ToggleAutoscan() self:SetAutoscan(not self:GetAutoscan()); end function SIL:TogglePaperdoll() self:SetPaperdoll(not self:GetPaperdoll()); end function SIL:ToggleLabel() self:SetLabel(not self:GetLabel()); end function SIL:ToggleLDBlabel() self:SetLDBlabel(not self:GetLDBlabel()); end function SIL:ToggleTTCombat() self:SetTTCombat(not self:GetTTCombat()); end function SIL:ToggleColorScore() self:SetColorScore(not self:GetColorScore()); end function SIL:ToggleRoundScore() self:SetRoundScore(not self:GetRoundScore()); end function SIL:ToggleMouseOver() self:SetMouseOver(not self:GetMouseOver()); end function SIL:ToggleColorScore(m) self:SetModule(m, not self:GetModule(m)); end function SIL:ToggleDebug(m) self:SetDebug(not self:GetDebug()); end -- Advanced sets function SIL:SetPurge(hours) self.db.global.purge = hours; SIL_Options.args.purge.desc = format(L.core.options.purgeDesc, self.db.global.purge / 24); end function SIL:SetMinimap(v) self.db.global.minimap.hide = not v; if not v then self.ldbIcon:Hide(L.core.name); else self.ldbIcon:Show(L.core.name); end end function SIL:SetPaperdoll(v) self.db.global.cinfo = v; if v then self:RegisterPaperdoll() else self:UnregisterPaperdoll() end end function SIL:SetLDB(v) self.db.global.ldbText = v; if v then --self:RegisterEvent("GROUP_ROSTER_UPDATE"); self.ldb.type = 'data source'; else --self:UnregisterEvent("GROUP_ROSTER_UPDATE"); self.ldb.type = 'launcher'; self.ldb.text = nil; end self:UpdateLDB(true); end function SIL:SetModule(m, v) self.db.char.module[m] = v; if v then self:ModuleLoad(m); end end --[[ GUI Functions ]] -- Open the options window function SIL:ShowOptions() -- Not using this until a paramiter is added to open expanded -- InterfaceOptionsFrame_OpenToCategory(L.core.name); for i,element in pairs(INTERFACEOPTIONS_ADDONCATEGORIES) do if element.name == L.core.name then if not InterfaceOptionsFrame:IsShown() then InterfaceOptionsFrame_Show(); InterfaceOptionsFrameTab2:Click(); end for i,button in pairs(InterfaceOptionsFrameAddOns.buttons) do if button.element == element then InterfaceOptionsListButton_OnClick(button); -- Expand if element.hasChildren and element.collapsed then OptionsListButtonToggle_OnClick(button.toggle); end -- Hide anything else that is open elseif button.element and type(button.element.collapsed) == 'boolean' and not button.element.collapsed then OptionsListButtonToggle_OnClick(button.toggle); end end end end end function SIL:UpdateLDB(force, auto) if self:GetLDB() then local label = UnitName('player'); if SIL_Group then groupType,label = SIL_Group:GroupType(); end -- Do we really need to update LDB? if force or label ~= self.ldbLable or (self.ldbUpdated + self:GetLDBrefresh()) < time() then local text = 'n/a'; local _, itype = GetInstanceInfo(); if (itype == 'pvp' or itype == 'arena') and SIL_Resil then local groupPercent = SIL_Resil:GroupSum(); groupPercent = SIL_Resil:FormatPercent(groupPercent, true); text = groupPercent; if SIL_Group then local groupScore = SIL_Group:GroupScore(); groupScore = self:FormatScore(groupScore, self.grayScore + 1, true); text = groupScore..' '..text; end elseif SIL_Group then local groupScore = SIL_Group:GroupScore() text = self:FormatScore(groupScore, 16, true); elseif UnitGUID('player') then local score, age, items = self:GetScoreTarget('player'); text = self:FormatScore(score, items, true); end self:UpdateLDBText(label, text) end else self.ldb.type = 'launcher'; self.ldb.text = nil; end end function SIL:UpdateLDBText(label, text) if not self:GetLDB() then return false; end -- Add the label if self:GetLDBlabel() then text = label..": "..text; end self.ldb.text = text; self.ldbUpdated = time(); self.ldbLable = label; end function SIL:LDBSetAuto() if self.ldbAuto then self:CancelTimer(self.ldbAuto, true); end self.ldbAuto = self:ScheduleRepeatingTimer(function() if not InCombatLockdown() then SIL:Debug('Auto LDB...'); SIL:UpdateLDB(false, true); end end, self:GetLDBrefresh()); end function SIL:GMICallback(name) local score, age, items = self:GetScoreName(name); if score and tonumber(score) and 0 < score then return self:FormatScore(score, items, false); else return 'n/a'; end end function SIL:Cache(guid, what) if not guid and not self:IsGUID(guid, 'Player') then return false end if SIL_CacheGUID[guid] and what then if what == 'age' then if SIL_CacheGUID[guid].time then return time() - SIL_CacheGUID[guid].time; else return nil; end else return SIL_CacheGUID[guid][what]; end elseif SIL_CacheGUID[guid] then return true; else return false; end end function SIL:IsGUID(guid, type) if not guid then return false end if not type then type = 'player' end local gType, gGuid = strsplit('-', guid, 2); if strlower(type) == strlower(gType) then return true else return false end end function SIL:UpdateGroup() self.group = {}; local playerGUID = self:AddPlayer('player'); table.insert(self.group, playerGUID); if UnitInBattleground('player') or UnitInRaid('player') then for i=1,MAX_RAID_MEMBERS do local target = 'raid'..i; local guid = self:AddPlayer(target); if guid and guid ~= playerGUID then table.insert(self.group, guid); if not self:Cache(guid, 'score') then self:RoughScore(target); end end end elseif GetNumSubgroupMembers() > 0 then for i=1,MAX_PARTY_MEMBERS do local target = 'party'..i; local guid = self:AddPlayer(target); if guid then table.insert(self.group, guid); if not self:Cache(guid, 'score') then self:RoughScore(target); end end end end end function SIL:GroupDest(dest, to) local valid = false; local color = false; if not dest then dest = "SYSTEM"; valid = true; end if dest == '' then dest = "SYSTEM"; valid = true; end dest = string.upper(dest); -- Some short codes, should be a table if dest == 'P' then dest = 'PARTY'; valid = true; end if dest == 'R' then dest = 'RAID'; valid = true; end if dest == 'BG' then dest = 'BATTLEGROUND'; valid = true; end if dest == 'G' then dest = 'GUILD'; valid = true; end if dest == 'U' then dest = 'GROUP'; valid = true; end if dest == 'A' then dest = 'GROUP'; valid = true; end if dest == 'O' then dest = 'OFFICER'; valid = true; end if dest == 'S' then dest = 'SAY'; valid = true; end if dest == 'T' then dest = 'WHISPER'; valid = true; end if dest == 'W' then dest = 'WHISPER'; valid = true; end if dest == 'TELL' then dest = 'WHISPER'; valid = true; end if dest == 'C' then dest = 'CHANNEL'; valid = true; end if dest == 'I' then dest = 'INSTANCE_CHAT'; valid = true; end -- Find out if its a valid dest for fixed,loc in pairs(SIL_Channels) do if dest == string.upper(loc) then dest = fixed; valid = true; elseif dest == string.upper(fixed) then dest = fixed; valid = true; end end -- Default to system if not valid then dest = "SYSTEM"; end -- Figure out GROUP if dest == 'GROUP' and IsInGroup() then if UnitInBattleground("player") then dest = 'BATTLEGROUND'; elseif IsInGroup(LE_PARTY_CATEGORY_INSTANCE) then dest = 'INSTANCE_CHAT'; elseif UnitInRaid("player") then dest = 'RAID'; elseif IsInGroup(LE_PARTY_CATEGORY_HOME) then dest = 'PARTY'; else dest = 'SAY'; end end if dest == "SYSTEM" then color = true; end return dest, to, color; end function SIL:RegisterPaperdoll() if not self:GetPaperdoll() then return false; end table.insert(PAPERDOLL_STATCATEGORIES[1].stats, { stat = 'SIL', }); PAPERDOLL_STATINFO['SIL'] = { updateFunc = function(...) SIL:UpdatePaperDollFrame(...); end }; end function SIL:UnregisterPaperdoll() if self:GetPaperdoll() then return false; end table.foreach(PAPERDOLL_STATCATEGORIES[1].stats, function(k, v) if v.stat == 'SIL' then table.remove(PAPERDOLL_STATCATEGORIES[1].stats, k); end end); PAPERDOLL_STATINFO['SIL'] = { updateFunc = function(...) return false; end }; end
비교하기