Advertisement
Guest User

SimpleILevel.lua

a guest
Oct 17th, 2016
172
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 39.00 KB | None | 0 0
  1. --[[
  2. ToDo:
  3. - Move more Group Functionality to here
  4. * Autoscan
  5. * SIL_Group:GroupType();
  6. - On UpdateGroup if there is no data do a rough scan
  7. - Group methods within this file
  8. - Better way to hooking tooltips
  9. -
  10. ]]
  11.  
  12. local L = LibStub("AceLocale-3.0"):GetLocale("SimpleILevel", true);
  13.  
  14. -- Start SIL
  15. SIL = LibStub("AceAddon-3.0"):NewAddon(L.core.name, "AceEvent-3.0", "AceConsole-3.0", "AceTimer-3.0");
  16. SIL.category = GetAddOnMetadata("SimpleILevel", "X-Category");
  17. SIL.version = GetAddOnMetadata("SimpleILevel", "Version");
  18. SIL.versionMajor = 3; -- Used for cache DB versioning
  19. SIL.versionRev = 'r253'; -- Used for version information
  20. SIL.action = {}; -- DB of unitGUID->function to run when a update comes through
  21. SIL.hooks = {}; -- List of hooks in [type][] = function;
  22. SIL.autoscan = 0; -- time() value of last autoscan, must be more then 1sec
  23. SIL.lastScan = {}; -- target = time();
  24. SIL.grayScore = 7; -- Number of items to consider gray/aprox
  25. SIL.ldbAuto = false; -- AceTimer for LDB
  26. SIL.menu = false; -- Menu frame
  27. SIL.menuItems = { -- Table for the dropdown menu
  28. top = {},
  29. middle = {},
  30. bottom = {},
  31. };
  32. SIL.modules = {}; -- Modules
  33. SIL.group = {}; -- Group Members by guid
  34. --SIL.L = L; -- Non-local locals
  35.  
  36. -- Load Libs
  37. SIL.aceConfig = LibStub:GetLibrary("AceConfig-3.0");
  38. SIL.aceConfigDialog = LibStub:GetLibrary("AceConfigDialog-3.0");
  39. SIL.inspect = LibStub:GetLibrary("LibInspect");
  40. SIL.ldb = LibStub:GetLibrary("LibDataBroker-1.1");
  41. SIL.ldbIcon = LibStub:GetLibrary("LibDBIcon-1.0");
  42. SIL.callback = LibStub("CallbackHandler-1.0"):New(SIL);
  43. SIL.itemUpgrade = LibStub("LibItemUpgradeInfo-1.0");
  44.  
  45. -- OnLoad
  46. function SIL:OnInitialize()
  47.  
  48. -- Make sure everything is ok with the db
  49. if not SIL_CacheGUID or type(SIL_CacheGUID) ~= 'table' then SIL_CacheGUID = {}; end
  50.  
  51. -- Tell the player we are being loaded
  52. self:Print(format(L.core.load, self.version));
  53. self:ModulesProcess();
  54.  
  55. -- Load settings
  56. self.db = LibStub("AceDB-3.0"):New("SIL_Settings", SIL_Defaults, true);
  57. self:UpdateSettings();
  58.  
  59. -- Set Up LDB
  60. local ldbObj = {
  61. type = "data source",
  62. icon = "Interface\\Icons\\inv_misc_armorkit_24",
  63. label = L.core.name,
  64. text = 'n/a',
  65. category = self.category,
  66. version = self.version,
  67. OnClick = function(...) SIL:MenuOpen(...); end,
  68. OnTooltipShow = function(tt)
  69. if SIL:GetLDB() and SIL.ldb.text then
  70. tt:AddLine(SIL.ldb.text);
  71. end
  72.  
  73. tt:AddLine(L.core.minimapClick);
  74. tt:AddLine(L.core.minimapClickDrag);
  75. end,
  76. };
  77.  
  78. -- Set back to a launcher if text is off
  79. if not self:GetLDB() then
  80. ldbObj.type = 'launcher';
  81. ldbObj.text = nil;
  82. end
  83.  
  84. -- Start LDB
  85. self.ldb = self.ldb:NewDataObject(L.core.name, ldbObj);
  86. self.ldbUpdated = 0;
  87. self.ldbLable = '';
  88.  
  89. -- Start the minimap icon
  90. self.ldbIcon:Register(L.core.name, self.ldb, self.db.global.minimap);
  91.  
  92. -- Register Options
  93. SIL_Options.args.purge.desc = format(L.core.options.purgeDesc, self:GetPurge() / 24);
  94. self.aceConfig:RegisterOptionsTable(L.core.name, SIL_Options, {"sil", "silev", "simpleilevel"});
  95. self.aceConfigDialog:AddToBlizOptions(L.core.name);
  96.  
  97. -- Add Hooks
  98. self.inspect:AddHook(L.core.name, 'items', function(...) SIL:ProcessInspect(...); end);
  99. GameTooltip:HookScript("OnTooltipSetUnit", function(...) SIL:TooltipHook(...); end);
  100. self:Autoscan(self:GetAutoscan());
  101.  
  102. -- Events
  103. self:RegisterEvent("PLAYER_TARGET_CHANGED", function() if CanInspect('target') then SIL:GetScoreTarget('target'); end end);
  104. self:RegisterEvent("PLAYER_EQUIPMENT_CHANGED", function() SIL:StartScore('player'); end);
  105. self:RegisterEvent("PLAYER_ENTERING_WORLD", function() SIL:UpdateLDB(); end);
  106. self:RegisterEvent("GROUP_ROSTER_UPDATE", function() SIL:UpdateGroup() end);
  107. self:RegisterEvent("UPDATE_MOUSEOVER_UNIT", function()
  108. if SIL:GetMouseOver() and CanInspect('mouseover') then
  109. SIL:Debug('mouseover', UnitName('mouseover'));
  110. SIL:GetScoreTarget('mouseover');
  111. end
  112. SIL:ShowTooltip();
  113. end);
  114.  
  115. -- Add to Paperdoll
  116. if self:GetPaperdoll() then
  117. self:RegisterPaperdoll();
  118. end
  119.  
  120. -- GuildMemberInfo
  121. if GMI then
  122. GMI:Register("SimpleILevel", {
  123. lines = {
  124. SimpleILevel = {
  125. label = L.core.name,
  126. default = 'n/a',
  127. callback = function(name) return SIL:GMICallback(name); end,
  128. },
  129. },
  130. });
  131. end
  132.  
  133. -- Clear the cache
  134. self:AutoPurge(true);
  135.  
  136. -- Build the menu
  137. self:MenuInitialize();
  138.  
  139. -- Get working on a score for the player
  140. self:StartScore('player');
  141. self:LDBSetAuto();
  142. self:UpdateLDB(); -- This may cause excesive loading time...
  143.  
  144. -- Process modules
  145. self:ModulesLoad();
  146.  
  147. -- Localization Notice
  148. if GetLocale() == 'itIT' or GetLocale() == 'esMX' or GetLocale() == 'esES' then
  149. self:Print("Help Localize Simple iLevel! http://j.mp/localSIL")
  150. end
  151. end
  152.  
  153. -- Make sure the database is the latest version
  154. function SIL:UpdateSettings()
  155.  
  156. if self.db.global.version == self.versionMajor then
  157. -- Same version
  158. elseif self.db.global.version > 2.4 and self.db.global.version < 2.5 then
  159. for guid,info in pairs(SIL_CacheGUID) do
  160. SIL_CacheGUID[guid].guid = nil;
  161. end
  162. elseif self.db.global.version < 2.4 then
  163. for guid,info in pairs(SIL_CacheGUID) do
  164. SIL_CacheGUID[guid].total = nil;
  165. SIL_CacheGUID[guid].tooltip = nil;
  166.  
  167. SIL_CacheGUID[guid].level = 85; --ASSuME
  168. --SIL_CacheGUID[guid].guid = guid;
  169. end
  170. end
  171.  
  172. -- Update version information
  173. self.db.global.version = self.versionMajor;
  174. end
  175.  
  176. function SIL:AutoPurge(silent)
  177. if self:GetPurge() > 0 then
  178. local count = self:PurgeCache(self:GetPurge());
  179.  
  180. if not silent then
  181. self:Print(format(L.core.purgeNotification, count));
  182. end
  183.  
  184. return count;
  185. else
  186. if not silent then
  187. self:Print(L.core.purgeNotificationFalse);
  188. end
  189.  
  190. return false;
  191. end
  192. end
  193.  
  194. function SIL:PurgeCache(hours)
  195. if tonumber(hours) then
  196. local maxAge = time() - (tonumber(hours) * 3600);
  197. local count = 0;
  198.  
  199. for guid,info in pairs(SIL_CacheGUID) do
  200. if type(info.time) == "number" and info.time < maxAge then
  201. SIL_CacheGUID[guid] = nil;
  202. count = 1 + count;
  203.  
  204. self:RunHooks('purge', guid);
  205. end
  206. end
  207.  
  208. return count;
  209. else
  210. return false;
  211. end
  212. end
  213.  
  214. function SIL:AddHook(hookType, callback)
  215. local hookType = strlower(hookType);
  216.  
  217. if not self.hooks[hookType] then
  218. self.hooks[hookType] = {};
  219. end
  220.  
  221. table.insert(self.hooks[hookType], callback);
  222. end
  223.  
  224. function SIL:RunHooks(hookType, ...)
  225. local r = {};
  226.  
  227. if self.hooks[hookType] then
  228. for i,callback in pairs(self.hooks[hookType]) do
  229. local ret = callback(...);
  230.  
  231. if ret then
  232. table.insert(r, callback(...));
  233. end
  234. end
  235.  
  236. if #r > 0 then
  237. return r;
  238. else
  239. return true;
  240. end
  241. else
  242. return false;
  243. end
  244. end
  245.  
  246. --[[
  247.  
  248. Event Handlers
  249.  
  250. ]]
  251. function SIL:UNIT_INVENTORY_CHANGED(e, unitID)
  252. --print('UNIT_INVENTORY_CHANGED');
  253. if InCombatLockdown() then return end
  254.  
  255. if unitID and CanInspect(unitID) and not UnitIsUnit('player', unitID) and self.autoscan ~= time() then
  256. self.autoscan = time();
  257.  
  258. self:StartScore(unitID);
  259. end
  260. end
  261.  
  262. -- Used to hook the tooltip to avoid the full tooltip function
  263. function SIL:TooltipHook()
  264. local name, unit = GameTooltip:GetUnit();
  265. local guid = false;
  266.  
  267. if unit then
  268. guid = UnitGUID(unit);
  269. elseif name then
  270. guid = self:NameToGUID(name);
  271. end
  272.  
  273. if self:IsGUID(guid, 'Player') then
  274. self:ShowTooltip(guid);
  275. end
  276. end
  277.  
  278. function SIL:Autoscan(toggle)
  279. if toggle then
  280. self:RegisterEvent("UNIT_INVENTORY_CHANGED");
  281. else
  282. self:UnregisterEvent("UNIT_INVENTORY_CHANGED");
  283. end
  284.  
  285. self.db.global.autoscan = toggle;
  286. end
  287.  
  288. --[[
  289.  
  290. Slash Handlers
  291.  
  292. ]]
  293. -- Reset the settings
  294. function SIL:SlashReset()
  295. self:Print(L.core.slashClear);
  296. self.db:RegisterDefaults(SIL_Defaults);
  297. self.db:ResetDB('Default');
  298. self:SetMinimap(true);
  299.  
  300. -- Clear the cache
  301. SIL_CacheGUID = {};
  302. self:GetScoreTarget('player', true);
  303.  
  304. -- Update version information
  305. self.db.global.version = self.versionMajor;
  306.  
  307. self:RunHooks('clear');
  308. end
  309.  
  310. function SIL:SlashGet(name)
  311.  
  312. -- Get score by name
  313. if name and not (name == '' or name == 'target') then
  314. local score, age, items = self:GetScoreName(name);
  315.  
  316. if score then
  317. local name = self:Cache(self:NameToGUID(name), 'name')
  318.  
  319. self:Print(format(L.core.slashGetScore, name, self:FormatScore(score, items), self:AgeToText(age)));
  320.  
  321. -- Nothing :(
  322. else
  323. self:Print(format(L.core.slashGetScoreFalse, name));
  324. end
  325.  
  326. -- no name but we can inspect the current target
  327. elseif CanInspect('target') then
  328. self:SlashTarget();
  329.  
  330. -- why do you ask so much of me but make no sence
  331. else
  332. self:Print(L.core.slashTargetScoreFalse);
  333. end
  334. end
  335.  
  336. function SIL:SlashTarget()
  337. self:StartScore('target', function(...) SIL:SlashTargetPrint(...); end);
  338. end
  339.  
  340. function SIL:SlashTargetPrint(guid, score, items, age)
  341. if guid and score then
  342. local name = self:GUIDtoName(guid);
  343.  
  344. if name then
  345. self:Print(format(L.core.slashTargetScore, name, self:FormatScore(score, items)));
  346. else
  347. self:Debug("No name for guid", guid, "score", score, items, age);
  348. end
  349. else
  350. self:Print(L.core.slashTargetScoreFalse);
  351. end
  352. end
  353.  
  354. --[[
  355.  
  356. Basic Functions
  357.  
  358. ]]
  359. function SIL:GUIDtoName(guid)
  360. if guid and self:IsGUID(guid, 'Player') and self:Cache(guid) then
  361. return self:Cache(guid, 'name'), self:Cache(guid, 'realm');
  362. else
  363. return false;
  364. end
  365. end
  366.  
  367. function SIL:NameToGUID(name, realm)
  368. if not name then return false end
  369.  
  370. -- Try and get the realm from the name-realm
  371. if not realm then
  372. name, realm = strsplit('-', name, 2);
  373. end
  374.  
  375. -- If no realm then set it to current realm
  376. if not realm or realm == '' then
  377. realm = GetRealmName();
  378. end
  379.  
  380. if name then
  381. name = strlower(name);
  382. local likely = false;
  383.  
  384. for guid,info in pairs(SIL_CacheGUID) do
  385. if strlower(info.name) == name and info.realm == realm then
  386. return guid;
  387. elseif strlower(info.name) == name then
  388. likely = guid;
  389. end
  390. end
  391.  
  392. if likely then
  393. return likely;
  394. end
  395. end
  396.  
  397. return false;
  398. end
  399.  
  400. -- Get a GUID from just about anything
  401. function SIL:GetGUID(target)
  402. if target then
  403. if tonumber(target) then
  404. return target;
  405. elseif UnitGUID(target) then
  406. return UnitGUID(target);
  407. else
  408. return SIL:NameToGUID(target);
  409. end
  410. else
  411. return false;
  412. end
  413. end
  414.  
  415. -- Clear score
  416. function SIL:ClearScore(target)
  417. local guid = self:GetGUID(target);
  418.  
  419. if SIL_CacheGUID[guid] then
  420. SIL_CacheGUID[guid].score = false;
  421. SIL_CacheGUID[guid].items = false;
  422. SIL_CacheGUID[guid].time = false;
  423.  
  424. self:RunHooks('purge', guid);
  425.  
  426. return true;
  427. else
  428. return false;
  429. end
  430. end;
  431.  
  432. function SIL:AgeToText(age, color)
  433. if type(color) == 'nil' then color = true; end
  434. local hex = "00ff00";
  435.  
  436. if type(age) == 'number' then
  437. if age > 86400 then
  438. age = self:Round(age / 86400, 2);
  439. str = L.core.ageDays;
  440. hex = "ff0000";
  441. elseif age > 3600 then
  442. age = self:Round(age / 3600, 1);
  443. str = L.core.ageHours;
  444. hex = "33ccff";
  445. elseif age > 60 then
  446. age = self:Round(age / 60, 1);
  447. str = L.core.ageMinutes;
  448. hex = "00ff00";
  449. else
  450. age = age;
  451. str = L.core.ageSeconds;
  452. hex = "00ff00";
  453. end
  454.  
  455. if color and self:GetColorScore() then
  456. return format(str, '|cFF'..hex..age..'|r');
  457. else
  458. return format(str, age);
  459. end
  460. else
  461. return 'n/a';
  462. end
  463. end
  464.  
  465. -- print a message to channel or whisper player/channel
  466. function SIL:PrintTo(message, channel, to)
  467. if channel == "print" or channel == "SYSTEM" then
  468. self:Print(message);
  469. elseif channel == "WHISPER" then
  470. SendChatMessage(message, 'WHISPER', nil, to);
  471. elseif channel == "CHANNEL" then
  472. SendChatMessage(message, 'CHANNEL', nil, to);
  473. elseif channel then
  474. SendChatMessage(message, channel);
  475. else
  476. self:Print(message);
  477. end
  478. end
  479.  
  480. function SIL:Debug(...)
  481. if SIL.db.char.debug then
  482. print('|cFFFF0000SIL Debug:|r ', ...);
  483. end
  484. end
  485.  
  486. --[[
  487.  
  488. Core Functionality
  489.  
  490. ]]
  491. -- Get someones score
  492. function SIL:GetScore(guid, attemptUpdate, target, callback)
  493. if not self:IsGUID(guid, 'Player') then return false; end
  494.  
  495. if self:Cache(guid) and self:Cache(guid, 'score') then
  496. local score = self:Cache(guid, 'score');
  497. local age = self:Cache(guid, 'age') or time();
  498. local items = self:Cache(guid, 'items');
  499. local startScore = nil;
  500.  
  501. -- If a target was passed and we are over age
  502. if target and (attemptUpdate or self:GetAge() < age) and self.autoscan ~= time() then
  503. startScore = self:StartScore(target, callback);
  504. end
  505.  
  506. return score, age, items, startScore;
  507. else
  508.  
  509. -- If a target was passed
  510. if target then
  511. self:StartScore(target);
  512. end
  513.  
  514. return false;
  515. end
  516. end
  517.  
  518. -- Wrapers for get score, more specialized code may come
  519. function SIL:GetScoreName(name, realm)
  520. local guid = self:NameToGUID(name, realm);
  521. return self:GetScore(guid);
  522. end
  523.  
  524. function SIL:GetScoreTarget(target, force, callback)
  525. local guid = UnitGUID(target);
  526. return self:GetScore(guid, force, target, callback);
  527. end
  528.  
  529. function SIL:GetScoreGUID(guid)
  530. return self:GetScore(guid);
  531. end
  532.  
  533. -- Request items to update a score
  534. function SIL:StartScore(target, callback)
  535. if InCombatLockdown() or not CanInspect(target) then
  536. if callback then callback(false, target); end
  537. return false;
  538. end
  539.  
  540. self.autoscan = time();
  541. local guid = self:AddPlayer(target);
  542.  
  543. if not self.lastScan[target] or self.lastScan[target] ~= time() then
  544. if guid then
  545. self.action[guid] = callback;
  546. self.lastScan[target] = time();
  547.  
  548. local canInspect = self.inspect:RequestItems(target, true);
  549.  
  550. if not canInspect and callback then
  551. callback(false, target);
  552. else
  553. return true;
  554. end
  555. end
  556. end
  557.  
  558. if callback then callback(false, target); end
  559. return false;
  560. end
  561.  
  562. function SIL:ProcessInspect(guid, data, age)
  563. if guid and self:Cache(guid) and type(data) == 'table' and type(data.items) == 'table' then
  564.  
  565. local totalScore, totalItems = self:GearSum(data.items, self:Cache(guid, 'level'));
  566.  
  567. if totalItems and 0 < totalItems then
  568.  
  569. -- Update the DB
  570. local score = totalScore / totalItems;
  571. self:SetScore(guid, score, totalItems, age)
  572.  
  573. -- Update LDB
  574. if self:GetLDB() and guid == UnitGUID('player') then
  575. self:UpdateLDB(true);
  576. else
  577. self:UpdateLDB(false);
  578. end
  579.  
  580. -- Run Hooks
  581. self:RunHooks('inspect', guid, score, totalItems, age, data.items);
  582.  
  583. -- Run any callbacks for this event
  584. if self.action[guid] then
  585. self.action[guid](guid, score, totalItems, age, data.items, self:Cache(guid, 'target'));
  586. self.action[guid] = false;
  587. end
  588.  
  589. -- Update the Tooltip
  590. self:ShowTooltip();
  591.  
  592. return true;
  593. end
  594. end
  595. end
  596.  
  597. function SIL:GearSum(items, level)
  598. if items and level and type(items) == 'table' then
  599. local totalItems = 0;
  600. local totalScore = 0;
  601. local mainhandArtifactIlvlCache = 0;
  602. local offhandAtifactIlvlCache=0;
  603. for i,itemLink in pairs(items) do
  604. if itemLink and not ( i == INVSLOT_BODY or i == INVSLOT_RANGED or i == INVSLOT_TABARD ) then
  605. local name, link, itemRarity , _ = GetItemInfo(itemLink);
  606. local itemLevel = self.itemUpgrade:GetUpgradedItemLevel(itemLink);
  607. -- print(i, itemLevel, itemLink, itemRarity);
  608. if itemLevel then
  609. -- Fix for OH Artifact (always calculated as 750 ilvl)
  610. if itemRarity == 6 then
  611. --Cache MH Artifact ilvl if higher
  612. if i == INVSLOT_MAINHAND then
  613. mainhandArtifactIlvlCache = itemLevel;
  614. end
  615. --Cache OH Artifact ilvl if higher
  616. if i == INVSLOT_OFFHAND then
  617. offhandAtifactIlvlCache = itemLevel
  618. end
  619. end
  620. totalItems = totalItems + 1;
  621. totalScore = totalScore + itemLevel;
  622. end
  623. end
  624. end
  625. -- Fix for MH Artifact
  626. if mainhandArtifactIlvlCache > offhandAtifactIlvlCache and totalItems == 16 then
  627. totalScore = totalScore - offhandAtifactIlvlCache + mainhandArtifactIlvlCache;
  628. end
  629. -- Fix for OH Artifact
  630. if mainhandArtifactIlvlCache < offhandAtifactIlvlCache and totalItems == 16 then
  631. totalScore = totalScore + offhandAtifactIlvlCache - mainhandArtifactIlvlCache;
  632. end
  633. --Fix for 2H Artifact
  634. if totalItems == 15 then
  635. totalScore = totalScore + mainhandArtifactIlvlCache;
  636. totalItems = totalItems + 1;
  637. end
  638. return totalScore, totalItems;
  639. else
  640. return false;
  641. end
  642. end
  643.  
  644. -- Thanks to Ro of Hyjal-US http://us.battle.net/wow/en/forum/topic/7199032730#9
  645. function SIL:GetActualItemLevelOld(link)
  646. -- Updated for 5.4.8
  647. local levelAdjust={ -- 11th item:id field and level adjustment
  648. ["0"]=0,["1"]=8,["373"]=4,["374"]=8,["375"]=4,["376"]=4,
  649. ["377"]=4,["379"]=4,["380"]=4,["445"]=0,["446"]=4,["447"]=8,
  650. ["451"]=0,["452"]=8,["453"]=0,["454"]=4,["455"]=8,["456"]=0,
  651. ["457"]=8,["458"]=0,["459"]=4,["460"]=8,["461"]=12,["462"]=16,
  652. ["465"]=0,["466"]=4,["467"]=8,["469"]=4,["470"]=8,["471"]=12,
  653. ["472"]=16,["491"]=0,["492"]=4,["493"]=8,["494"]=4,["495"]=8,
  654. ["496"]=8,["497"]=12,["498"]=16,["504"]=12,["505"]=16,["506"]=20,
  655. ["507"]=24,
  656. }
  657. local baseLevel = select(4,GetItemInfo(link))
  658. local upgrade = link:match(":(%d+)\124h%[")
  659. if baseLevel and upgrade and levelAdjust[upgrade] then
  660. local newLevel = baseLevel + levelAdjust[upgrade];
  661. return newLevel
  662. else
  663. return baseLevel
  664. end
  665. end
  666.  
  667. -- /run for i=1,25 do t='raid'..i; if UnitExists(t) then print(i, UnitName(t), CanInspect(t), SIL:RoughScore(t)); end end
  668. function SIL:RoughScore(target)
  669. if not target then return false; end
  670. if not CanInspect(target) then return false; end
  671.  
  672. -- Get stuff in order
  673. local guid = self:AddPlayer(target)
  674. self.inspect:AddCharacter(target);
  675. NotifyInspect(target);
  676.  
  677. -- Get items and sum
  678. local items = self.inspect:GetItems(target);
  679. local totalScore, totalItems = self:GearSum(items, UnitLevel(target));
  680.  
  681. if totalItems and totalItems > 0 then
  682. local score = totalScore / totalItems;
  683. -- self:Debug('SIL:RoughScore', UnitName(target), score, totalItems);
  684.  
  685. -- Set a score even tho its crap
  686. if guid and self:Cache(guid) and (not self:Cache(guid, 'score') or self:Cache(guid, 'items') < totalItems) then
  687. self:SetScore(guid, score, 1, self:GetAge() + 1);
  688. end
  689.  
  690. return score, 1, self:GetAge() + 1;
  691. else
  692. return false;
  693. end
  694. end
  695.  
  696. -- Start or update the DB for a player
  697. function SIL:AddPlayer(target)
  698. local guid = UnitGUID(target);
  699.  
  700. if guid then
  701. local name, realm = UnitName(target);
  702. local className, class = UnitClass(target);
  703. local level = UnitLevel(target);
  704.  
  705. if not realm then
  706. realm = GetRealmName();
  707. end
  708.  
  709. if name and realm and class and level then
  710.  
  711. -- Start a table for them
  712. if not SIL_CacheGUID[guid] then
  713. SIL_CacheGUID[guid] = {};
  714. end
  715.  
  716. SIL_CacheGUID[guid].name = name;
  717. SIL_CacheGUID[guid].realm = realm;
  718. SIL_CacheGUID[guid].class = class;
  719. SIL_CacheGUID[guid].level = level;
  720. SIL_CacheGUID[guid].target = target;
  721.  
  722. if not SIL_CacheGUID[guid].score or SIL_CacheGUID[guid].score == 0 then
  723. SIL_CacheGUID[guid].score = false;
  724. SIL_CacheGUID[guid].items = false;
  725. SIL_CacheGUID[guid].time = false;
  726. end
  727.  
  728. return guid;
  729. else
  730. return false;
  731. end
  732. else
  733. return false;
  734. end
  735. end
  736.  
  737. function SIL:SetScore(guid, score, items, age)
  738. local t = age;
  739.  
  740. if age and type(age) == 'number' and age < 86400 then
  741. t = time() - age;
  742. end
  743.  
  744. SIL_CacheGUID[guid].score = score;
  745. SIL_CacheGUID[guid].items = items;
  746. SIL_CacheGUID[guid].time = t;
  747. self:Debug("SetScore", self:GUIDtoName(guid), self:FormatScore(score, items), items, age)
  748. end
  749.  
  750. -- Get a relative iLevel on Heirlooms
  751. function SIL:Heirloom(level, itemLink)
  752. --[[
  753. Here is how I came to the level 81-85 bracket
  754. 200 = level of 80 instance gear
  755. 333 = level of 85 instance gear
  756. 333 - 200 = 133 iLevels / 5 levels = 26.6 iLevel per level
  757. so then that means for a level 83
  758. 83 - 80 = 3 * 26.6 = 79.8 + 200 = 279.8 iLevel
  759. ]]
  760.  
  761. -- Check for Wrath Heirlooms that max at 80
  762. if level > 80 then
  763. local _, _, _, _, itemId = string.find(itemLink, "|?c?f?f?(%x*)|?H?([^:]*):?(%d+):?(%d*):?(%d*):?(%d*):?(%d*):?(%d*):?(%-?%d*):?(%-?%d*):?(%d*):?(%d*)|?h?%[?([^%[%]]*)%]?|?h?|?r?");
  764. itemId = tonumber(itemId);
  765.  
  766. -- Downgrade it to 80 if found
  767. for k,iid in pairs(SIL_Heirlooms[80]) do
  768. if iid == itemId then
  769. level = 80;
  770. end
  771. end
  772.  
  773. -- There are currently no 1-90 Heirlooms
  774. if level > 85 then
  775. level = 85
  776. end
  777. end
  778.  
  779. if level > 80 then
  780. return (( level - 80) * 26.6) + 200;
  781. elseif level > 70 then
  782. return (( level - 70) * 10) + 100;
  783. elseif level > 60 then
  784. return (( level - 60) * 4) + 60;
  785. else
  786. return level;
  787. end
  788. end
  789.  
  790. -- Format the score for color and round it to xxx.x
  791. function SIL:FormatScore(score, items, color)
  792. if not items then items = self.grayScore + 1; end
  793. if type(color) == 'nil' then color = true; end
  794. if score < 0 then score = 0; end -- Ticket #29, thanks Torsin
  795.  
  796. if tonumber(score) and tonumber(items) then
  797. local scoreR
  798.  
  799. if self:GetRoundScore() then
  800. scoreR = self:Round(tonumber(score), 0);
  801. else
  802. scoreR = self:Round(tonumber(score), 1);
  803. end
  804.  
  805. if color then
  806. local hexColor = self:ColorScore(score, items);
  807.  
  808.  
  809.  
  810. return '|cFF'..hexColor..scoreR..'|r';
  811. else
  812. return scoreR;
  813. end
  814. else
  815. return 'n/a';
  816. end
  817. end
  818.  
  819. -- Return the hex, r, g, b of a score
  820. function SIL:ColorScore(score, items)
  821.  
  822. -- There are some missing items so gray
  823. if items and items <= self.grayScore then
  824. return self:RGBtoHex(0.5,0.5,0.5), 0.5,0.5,0.5;
  825. end
  826.  
  827. if not self:GetColorScore() then
  828. return self:RGBtoHex(1,1,1), 1,1,1;
  829. end
  830.  
  831. -- Default to white
  832. local r,g,b = 1,1,1;
  833.  
  834. local found = false;
  835.  
  836. for i,maxScore in pairs(SIL_ColorIndex) do
  837. if score < maxScore and not found then
  838. local colors = SIL_Colors[maxScore];
  839. local baseColors = SIL_Colors[colors.p];
  840.  
  841. local steps = maxScore - colors.p;
  842. local scoreDiff = score - colors.p;
  843.  
  844. local diffR = (baseColors.r - colors.r) / 255;
  845. local diffG = (baseColors.g - colors.g) / 255;
  846. local diffB = (baseColors.b - colors.b) / 255;
  847.  
  848. local diffStepR = diffR / steps;
  849. local diffStepG = diffG / steps;
  850. local diffStepB = diffB / steps;
  851.  
  852. local scoreDiffR = scoreDiff * diffStepR;
  853. local scoreDiffG = scoreDiff * diffStepG;
  854. local scoreDiffB = scoreDiff * diffStepB;
  855.  
  856. r = (baseColors.r / 255) - scoreDiffR;
  857. g = (baseColors.g / 255) - scoreDiffG;
  858. b = (baseColors.b / 255) - scoreDiffB;
  859.  
  860. found = true;
  861. end
  862. end
  863.  
  864. -- Nothing was found so max
  865. if not found then
  866. r = SIL_Colors[1000].r;
  867. g = SIL_Colors[1000].g;
  868. b = SIL_Colors[1000].b;
  869. end
  870.  
  871. local hex = self:RGBtoHex(r,g,b);
  872. return hex, r, g, b;
  873. end
  874.  
  875. function SIL:ShowTooltip(guid)
  876. if InCombatLockdown() and not self:GetTTCombat() then return end
  877.  
  878. if not guid then
  879. guid = UnitGUID("mouseover");
  880. end
  881.  
  882. local score, age, items = self:GetScoreGUID(guid);
  883.  
  884. if score then
  885.  
  886. -- Build the tooltip text
  887. local textLeft = '|cFF216bff'..L.core.ttLeft..'|r ';
  888. local textRight = self:FormatScore(score, items, true);
  889.  
  890. local textAdvanced = format(L.core.ttAdvanced, self:AgeToText(age, true));
  891.  
  892. self:AddTooltipText(textLeft, textRight, textAdvanced);
  893.  
  894. -- Run Hooks
  895. self:RunHooks('tooltip', guid);
  896.  
  897. return true;
  898. else
  899. return false;
  900. end
  901. end
  902.  
  903. -- Add lines to the tooltip, testLeft must be the same
  904. function SIL:AddTooltipText(textLeft, textRight, textAdvanced, textAdvancedRight)
  905.  
  906. -- Loop tooltip text to check if its alredy there
  907. local ttLines = GameTooltip:NumLines();
  908. local ttUpdated = false;
  909.  
  910. for i = 1,ttLines do
  911.  
  912. -- If the static text matches
  913. if _G["GameTooltipTextLeft"..i]:GetText() == textLeft then
  914.  
  915. -- Update the text
  916. _G["GameTooltipTextLeft"..i]:SetText(textLeft);
  917. _G["GameTooltipTextRight"..i]:SetText(textRight);
  918. GameTooltip:Show();
  919.  
  920. -- Update the advanced info too
  921. if self.db.global.advanced and textAdvanced then
  922.  
  923. if textAdvancedRight then
  924. _G["GameTooltipTextLeft"..i]:SetText(textAdvanced);
  925. _G["GameTooltipTextRight"..i]:SetText(textAdvancedRight);
  926. else
  927. _G["GameTooltipTextLeft"..i+1]:SetText(textAdvanced);
  928. end
  929.  
  930. GameTooltip:Show();
  931. end
  932.  
  933. -- Remember that we have updated the tool tip so we won't again
  934. ttUpdated = true;
  935. break;
  936. end
  937. end
  938.  
  939. -- Tooltip is new
  940. if not ttUpdated then
  941.  
  942. GameTooltip:AddDoubleLine(textLeft, textRight);
  943. GameTooltip:Show();
  944.  
  945. if self.db.global.advanced and textAdvanced then
  946. if textAdvancedRight then
  947. GameTooltip:AddDoubleLine(textAdvanced, textAdvancedRight);
  948. else
  949. GameTooltip:AddLine(textAdvanced);
  950. end
  951.  
  952. GameTooltip:Show();
  953. end
  954. end
  955. end
  956.  
  957. function SIL:UpdatePaperDollFrame(statFrame, unit)
  958. local score, age, items = self:GetScoreTarget(unit, true);
  959. local formated = self:FormatScore(score, items, false);
  960.  
  961. PaperDollFrame_SetLabelAndText(statFrame, L.core.name, formated, false);
  962. statFrame.tooltip = HIGHLIGHT_FONT_COLOR_CODE..L.core.name..FONT_COLOR_CODE_CLOSE;
  963. statFrame.tooltip2 = L.core.scoreDesc;
  964.  
  965. statFrame:Show();
  966. end
  967.  
  968. --[[
  969.  
  970. Setters, Getter and Togglers
  971.  
  972. ]]
  973.  
  974. -- Set
  975. function SIL:SetAdvanced(v) self.db.global.advanced = v; end
  976. function SIL:SetLabel(v) self.db.global.showLabel = v; self:UpdateLDB(); end
  977. function SIL:SetAutoscan(v) self.db.global.autoscan = v; self:Autoscan(v); end
  978. function SIL:SetAge(seconds) self.db.global.age = seconds; end
  979. function SIL:SetLDBlabel(v) self.db.global.ldbLabel = v; self:UpdateLDB(true); end
  980. function SIL:SetLDBrefresh(v) self.db.global.ldbRefresh = v; self:LDBSetAuto() end
  981. function SIL:SetTTCombat(v) self.db.global.ttCombat = v; end
  982. function SIL:SetColorScore(v) self.db.global.color = v; end
  983. function SIL:SetRoundScore(v) self.db.global.round = v; end
  984. function SIL:SetMouseOver(v) self.db.global.mouseover = v; end
  985. function SIL:SetDebug(v) self.db.char.debug = v; end
  986.  
  987. -- Get
  988. function SIL:GetAdvanced() return self.db.global.advanced; end
  989. function SIL:GetMinimap() return not self.db.global.minimap.hide; end
  990. function SIL:GetAutoscan() return self.db.global.autoscan; end
  991. function SIL:GetPaperdoll() return self.db.global.cinfo; end
  992. function SIL:GetAge() return self.db.global.age; end
  993. function SIL:GetPurge() return self.db.global.purge; end
  994. function SIL:GetLabel() return self.db.global.showLabel; end
  995. function SIL:GetLDB() return self.db.global.ldbText; end
  996. function SIL:GetLDBlabel() return self.db.global.ldbLabel; end
  997. function SIL:GetLDBrefresh() return self.db.global.ldbRefresh; end
  998. function SIL:GetTTCombat() return self.db.global.ttCombat; end
  999. function SIL:GetColorScore() return self.db.global.color; end
  1000. function SIL:GetRoundScore() return self.db.global.round; end
  1001. function SIL:GetMouseOver() return self.db.global.mouseover; end
  1002. function SIL:GetModule(m) return self.db.char.module[m]; end
  1003. function SIL:GetDebug(m) return self.db.char.debug; end
  1004.  
  1005. -- Toggle
  1006. function SIL:ToggleAdvanced() self:SetAdvanced(not self:GetAdvanced()); end
  1007. function SIL:ToggleMinimap() self:SetMinimap(not self:GetMinimap()); end
  1008. function SIL:ToggleAutoscan() self:SetAutoscan(not self:GetAutoscan()); end
  1009. function SIL:TogglePaperdoll() self:SetPaperdoll(not self:GetPaperdoll()); end
  1010. function SIL:ToggleLabel() self:SetLabel(not self:GetLabel()); end
  1011. function SIL:ToggleLDBlabel() self:SetLDBlabel(not self:GetLDBlabel()); end
  1012. function SIL:ToggleTTCombat() self:SetTTCombat(not self:GetTTCombat()); end
  1013. function SIL:ToggleColorScore() self:SetColorScore(not self:GetColorScore()); end
  1014. function SIL:ToggleRoundScore() self:SetRoundScore(not self:GetRoundScore()); end
  1015. function SIL:ToggleMouseOver() self:SetMouseOver(not self:GetMouseOver()); end
  1016. function SIL:ToggleColorScore(m) self:SetModule(m, not self:GetModule(m)); end
  1017. function SIL:ToggleDebug(m) self:SetDebug(not self:GetDebug()); end
  1018.  
  1019. -- Advanced sets
  1020. function SIL:SetPurge(hours)
  1021. self.db.global.purge = hours;
  1022. SIL_Options.args.purge.desc = format(L.core.options.purgeDesc, self.db.global.purge / 24);
  1023. end
  1024.  
  1025. function SIL:SetMinimap(v)
  1026. self.db.global.minimap.hide = not v;
  1027.  
  1028. if not v then
  1029. self.ldbIcon:Hide(L.core.name);
  1030. else
  1031. self.ldbIcon:Show(L.core.name);
  1032. end
  1033. end
  1034.  
  1035. function SIL:SetPaperdoll(v)
  1036. self.db.global.cinfo = v;
  1037.  
  1038. if v then
  1039. self:RegisterPaperdoll()
  1040. else
  1041. self:UnregisterPaperdoll()
  1042. end
  1043. end
  1044.  
  1045. function SIL:SetLDB(v)
  1046. self.db.global.ldbText = v;
  1047.  
  1048. if v then
  1049. --self:RegisterEvent("GROUP_ROSTER_UPDATE");
  1050. self.ldb.type = 'data source';
  1051. else
  1052. --self:UnregisterEvent("GROUP_ROSTER_UPDATE");
  1053. self.ldb.type = 'launcher';
  1054. self.ldb.text = nil;
  1055. end
  1056.  
  1057. self:UpdateLDB(true);
  1058. end
  1059.  
  1060. function SIL:SetModule(m, v)
  1061. self.db.char.module[m] = v;
  1062.  
  1063. if v then
  1064. self:ModuleLoad(m);
  1065. end
  1066. end
  1067.  
  1068. --[[
  1069.  
  1070. GUI Functions
  1071.  
  1072. ]]
  1073.  
  1074. -- Open the options window
  1075. function SIL:ShowOptions()
  1076. -- Not using this until a paramiter is added to open expanded
  1077. -- InterfaceOptionsFrame_OpenToCategory(L.core.name);
  1078.  
  1079. for i,element in pairs(INTERFACEOPTIONS_ADDONCATEGORIES) do
  1080. if element.name == L.core.name then
  1081. if not InterfaceOptionsFrame:IsShown() then
  1082. InterfaceOptionsFrame_Show();
  1083. InterfaceOptionsFrameTab2:Click();
  1084. end
  1085.  
  1086. for i,button in pairs(InterfaceOptionsFrameAddOns.buttons) do
  1087. if button.element == element then
  1088. InterfaceOptionsListButton_OnClick(button);
  1089.  
  1090. -- Expand
  1091. if element.hasChildren and element.collapsed then
  1092. OptionsListButtonToggle_OnClick(button.toggle);
  1093. end
  1094.  
  1095. -- Hide anything else that is open
  1096. elseif button.element and type(button.element.collapsed) == 'boolean' and not button.element.collapsed then
  1097. OptionsListButtonToggle_OnClick(button.toggle);
  1098. end
  1099. end
  1100. end
  1101. end
  1102. end
  1103.  
  1104. function SIL:UpdateLDB(force, auto)
  1105.  
  1106. if self:GetLDB() then
  1107. local label = UnitName('player');
  1108.  
  1109. if SIL_Group then
  1110. groupType,label = SIL_Group:GroupType();
  1111. end
  1112.  
  1113. -- Do we really need to update LDB?
  1114. if force or label ~= self.ldbLable or (self.ldbUpdated + self:GetLDBrefresh()) < time() then
  1115.  
  1116. local text = 'n/a';
  1117. local _, itype = GetInstanceInfo();
  1118.  
  1119. if (itype == 'pvp' or itype == 'arena') and SIL_Resil then
  1120. local groupPercent = SIL_Resil:GroupSum();
  1121. groupPercent = SIL_Resil:FormatPercent(groupPercent, true);
  1122. text = groupPercent;
  1123.  
  1124. if SIL_Group then
  1125. local groupScore = SIL_Group:GroupScore();
  1126. groupScore = self:FormatScore(groupScore, self.grayScore + 1, true);
  1127. text = groupScore..' '..text;
  1128. end
  1129. elseif SIL_Group then
  1130. local groupScore = SIL_Group:GroupScore()
  1131. text = self:FormatScore(groupScore, 16, true);
  1132. elseif UnitGUID('player') then
  1133. local score, age, items = self:GetScoreTarget('player');
  1134. text = self:FormatScore(score, items, true);
  1135. end
  1136.  
  1137. self:UpdateLDBText(label, text)
  1138. end
  1139. else
  1140. self.ldb.type = 'launcher';
  1141. self.ldb.text = nil;
  1142. end
  1143. end
  1144.  
  1145. function SIL:UpdateLDBText(label, text)
  1146. if not self:GetLDB() then return false; end
  1147.  
  1148. -- Add the label
  1149. if self:GetLDBlabel() then
  1150. text = label..": "..text;
  1151. end
  1152.  
  1153. self.ldb.text = text;
  1154. self.ldbUpdated = time();
  1155. self.ldbLable = label;
  1156. end
  1157.  
  1158. function SIL:LDBSetAuto()
  1159. if self.ldbAuto then
  1160. self:CancelTimer(self.ldbAuto, true);
  1161. end
  1162.  
  1163. self.ldbAuto = self:ScheduleRepeatingTimer(function()
  1164. if not InCombatLockdown() then
  1165. SIL:Debug('Auto LDB...');
  1166. SIL:UpdateLDB(false, true);
  1167. end
  1168. end, self:GetLDBrefresh());
  1169. end
  1170.  
  1171. function SIL:GMICallback(name)
  1172. local score, age, items = self:GetScoreName(name);
  1173.  
  1174. if score and tonumber(score) and 0 < score then
  1175. return self:FormatScore(score, items, false);
  1176. else
  1177. return 'n/a';
  1178. end
  1179. end
  1180.  
  1181. function SIL:Cache(guid, what)
  1182. if not guid and not self:IsGUID(guid, 'Player') then return false end
  1183.  
  1184. if SIL_CacheGUID[guid] and what then
  1185. if what == 'age' then
  1186. if SIL_CacheGUID[guid].time then
  1187. return time() - SIL_CacheGUID[guid].time;
  1188. else
  1189. return nil;
  1190. end
  1191. else
  1192. return SIL_CacheGUID[guid][what];
  1193. end
  1194. elseif SIL_CacheGUID[guid] then
  1195. return true;
  1196. else
  1197. return false;
  1198. end
  1199. end
  1200.  
  1201. function SIL:IsGUID(guid, type)
  1202. if not guid then return false end
  1203. if not type then type = 'player' end
  1204.  
  1205. local gType, gGuid = strsplit('-', guid, 2);
  1206.  
  1207. if strlower(type) == strlower(gType) then
  1208. return true
  1209. else
  1210. return false
  1211. end
  1212. end
  1213.  
  1214. function SIL:UpdateGroup()
  1215. self.group = {};
  1216.  
  1217. local playerGUID = self:AddPlayer('player');
  1218. table.insert(self.group, playerGUID);
  1219.  
  1220. if UnitInBattleground('player') or UnitInRaid('player') then
  1221. for i=1,MAX_RAID_MEMBERS do
  1222. local target = 'raid'..i;
  1223. local guid = self:AddPlayer(target);
  1224.  
  1225. if guid and guid ~= playerGUID then
  1226. table.insert(self.group, guid);
  1227.  
  1228. if not self:Cache(guid, 'score') then
  1229. self:RoughScore(target);
  1230. end
  1231. end
  1232. end
  1233. elseif GetNumSubgroupMembers() > 0 then
  1234. for i=1,MAX_PARTY_MEMBERS do
  1235. local target = 'party'..i;
  1236. local guid = self:AddPlayer(target);
  1237.  
  1238. if guid then
  1239. table.insert(self.group, guid);
  1240.  
  1241. if not self:Cache(guid, 'score') then
  1242. self:RoughScore(target);
  1243. end
  1244. end
  1245. end
  1246. end
  1247. end
  1248.  
  1249. function SIL:GroupDest(dest, to)
  1250. local valid = false;
  1251. local color = false;
  1252.  
  1253. if not dest then dest = "SYSTEM"; valid = true; end
  1254. if dest == '' then dest = "SYSTEM"; valid = true; end
  1255. dest = string.upper(dest);
  1256.  
  1257. -- Some short codes, should be a table
  1258. if dest == 'P' then dest = 'PARTY'; valid = true; end
  1259. if dest == 'R' then dest = 'RAID'; valid = true; end
  1260. if dest == 'BG' then dest = 'BATTLEGROUND'; valid = true; end
  1261. if dest == 'G' then dest = 'GUILD'; valid = true; end
  1262. if dest == 'U' then dest = 'GROUP'; valid = true; end
  1263. if dest == 'A' then dest = 'GROUP'; valid = true; end
  1264. if dest == 'O' then dest = 'OFFICER'; valid = true; end
  1265. if dest == 'S' then dest = 'SAY'; valid = true; end
  1266. if dest == 'T' then dest = 'WHISPER'; valid = true; end
  1267. if dest == 'W' then dest = 'WHISPER'; valid = true; end
  1268. if dest == 'TELL' then dest = 'WHISPER'; valid = true; end
  1269. if dest == 'C' then dest = 'CHANNEL'; valid = true; end
  1270. if dest == 'I' then dest = 'INSTANCE_CHAT'; valid = true; end
  1271.  
  1272. -- Find out if its a valid dest
  1273. for fixed,loc in pairs(SIL_Channels) do
  1274. if dest == string.upper(loc) then
  1275. dest = fixed;
  1276. valid = true;
  1277. elseif dest == string.upper(fixed) then
  1278. dest = fixed;
  1279. valid = true;
  1280. end
  1281. end
  1282.  
  1283. -- Default to system
  1284. if not valid then
  1285. dest = "SYSTEM";
  1286. end
  1287.  
  1288. -- Figure out GROUP
  1289. if dest == 'GROUP' and IsInGroup() then
  1290. if UnitInBattleground("player") then
  1291. dest = 'BATTLEGROUND';
  1292. elseif IsInGroup(LE_PARTY_CATEGORY_INSTANCE) then
  1293. dest = 'INSTANCE_CHAT';
  1294. elseif UnitInRaid("player") then
  1295. dest = 'RAID';
  1296. elseif IsInGroup(LE_PARTY_CATEGORY_HOME) then
  1297. dest = 'PARTY';
  1298. else
  1299. dest = 'SAY';
  1300. end
  1301. end
  1302.  
  1303. if dest == "SYSTEM" then
  1304. color = true;
  1305. end
  1306.  
  1307. return dest, to, color;
  1308. end
  1309.  
  1310. function SIL:RegisterPaperdoll()
  1311. if not self:GetPaperdoll() then return false; end
  1312.  
  1313. table.insert(PAPERDOLL_STATCATEGORIES[1].stats, {
  1314. stat = 'SIL',
  1315. });
  1316. PAPERDOLL_STATINFO['SIL'] = { updateFunc = function(...) SIL:UpdatePaperDollFrame(...); end };
  1317. end
  1318.  
  1319. function SIL:UnregisterPaperdoll()
  1320. if self:GetPaperdoll() then return false; end
  1321.  
  1322. table.foreach(PAPERDOLL_STATCATEGORIES[1].stats, function(k, v)
  1323. if v.stat == 'SIL' then
  1324. table.remove(PAPERDOLL_STATCATEGORIES[1].stats, k);
  1325. end
  1326. end);
  1327.  
  1328. PAPERDOLL_STATINFO['SIL'] = { updateFunc = function(...) return false; end };
  1329. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement