aggixx

Untitled

Aug 14th, 2016
255
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 36.67 KB | None | 0 0
  1. local A = FALoot;
  2. local U = A.util;
  3. local SD = A.sData;
  4. local PD = A.pData;
  5. local O = A.options;
  6. local E = A.events;
  7. local AM = A.addonMessages;
  8. local CM = A.chatMessages;
  9. local F = A.functions;
  10. local UI = A.UI;
  11. local C = A.commands;
  12.  
  13. -- Call Libraries
  14. local ScrollingTable = LibStub("ScrollingTable");
  15.  
  16. -- Init some tables
  17. SD.table_itemQuery = {};
  18. SD.table_items = {};
  19. SD.table_icons = {};
  20.  
  21. -- Init "items" functions subtable
  22. F.items = {};
  23.  
  24. -- Init some item window variables
  25. local itemWindowSelection = nil;
  26. local bidAmount = nil;
  27.  
  28. -- Init mob loot blacklist
  29. local hasBeenLooted = {};
  30.  
  31. SD.difficultyLevelDeltas = {
  32. [1798] = 15,
  33. [1799] = 30,
  34. };
  35.  
  36. --[[ ==========================================================================
  37. GUI Creation
  38. ========================================================================== --]]
  39.  
  40. local function createGUI()
  41. UI.itemWindow = {};
  42.  
  43. -- Create the main frame
  44. local frame = CreateFrame("frame", "FALootFrame", UIParent)
  45. frame:EnableMouse(true);
  46. frame:SetMovable(true);
  47. frame:SetMovable(true);
  48. frame:SetFrameStrata("FULLSCREEN_DIALOG");
  49. frame:SetBackdrop({
  50. bgFile = "Interface\\DialogFrame\\UI-DialogBox-Background",
  51. edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border",
  52. tile = true, tileSize = 32, edgeSize = 32,
  53. insets = { left = 8, right = 8, top = 8, bottom = 8 }
  54. });
  55. frame:SetBackdropColor(0, 0, 0, 1);
  56. frame:SetToplevel(true);
  57. frame:SetWidth(500);
  58. frame:SetHeight(270);
  59. frame:SetPoint("CENTER");
  60. frame:Hide();
  61. frame:SetScript("OnShow", function()
  62. E.Trigger("ITEM_UPDATE");
  63. end);
  64.  
  65. UI.itemWindow.frame = frame;
  66.  
  67. -- Create the frame that holds the icons
  68. local iconFrame = CreateFrame("frame", frame:GetName().."IconFrame", frame);
  69. iconFrame:SetHeight(40);
  70. iconFrame:SetWidth(500);
  71. iconFrame:SetPoint("TOP", frame, "TOP", 0, -30);
  72. iconFrame:Show();
  73.  
  74. UI.itemWindow.iconFrame = iconFrame;
  75.  
  76. -- Populate the iconFrame with icons
  77. for i=1,PD.maxIcons do
  78. local f = CreateFrame("frame", iconFrame:GetName().."Icon"..tostring(i), iconFrame);
  79. f:SetWidth(40);
  80. f:SetHeight(40);
  81. f:Hide();
  82. f.texture = f:CreateTexture(f:GetName().."Texture");
  83. f.texture:SetWidth(40);
  84. f.texture:SetHeight(40);
  85. f.texture:SetAllPoints(f);
  86.  
  87. SD.table_icons[i] = f;
  88. end
  89.  
  90. -- Create the scrollingTable
  91. local scrollingTable = ScrollingTable:CreateST({
  92. {
  93. ["name"] = "Item",
  94. ["width"] = 187,
  95. ["align"] = "LEFT",
  96. ["color"] = { ["r"] = 1.0, ["g"] = 1.0, ["b"] = 1.0, ["a"] = 1.0 },
  97. ["defaultsort"] = "asc",
  98. },
  99. {
  100. ["name"] = "Prop.",
  101. ["width"] = 40,
  102. ["align"] = "LEFT",
  103. ["color"] = { ["r"] = 1.0, ["g"] = 1.0, ["b"] = 1.0, ["a"] = 1.0 },
  104. ["defaultsort"] = "asc",
  105. },
  106. {
  107. ["name"] = "Status",
  108. ["width"] = 60,
  109. ["align"] = "LEFT",
  110. ["color"] = { ["r"] = 1.0, ["g"] = 1.0, ["b"] = 1.0, ["a"] = 1.0 },
  111. ["defaultsort"] = "dsc",
  112. },
  113. {
  114. ["name"] = "Winner(s)",
  115. ["width"] = 120,
  116. ["align"] = "LEFT",
  117. ["color"] = { ["r"] = 1.0, ["g"] = 1.0, ["b"] = 1.0, ["a"] = 1.0 },
  118. ["defaultsort"] = "dsc",
  119. }
  120. }, 8, nil, {["r"] = 0, ["g"] = 1, ["b"] = 0, ["a"] = 0.3}, frame);
  121. scrollingTable:EnableSelection(true);
  122. scrollingTable.frame:SetPoint("TOP", iconFrame, "BOTTOM", 0, -20);
  123. scrollingTable.frame:SetScale(1.1);
  124.  
  125. -- Setup onclick to trigger an ITEMWINDOW_SELECT_UPDATE event
  126. scrollingTable:RegisterEvents({
  127. ["OnClick"] = function(rowFrame, cellFrame, data, cols, row, realrow, column, scrollingTable, ...)
  128. -- if the user clicked on a content cell
  129. if row and realrow then
  130. -- if the row clicked is already the one selected
  131. if scrollingTable:GetSelection() == realrow then
  132. -- then deselect the row
  133. scrollingTable:ClearSelection();
  134. -- then trigger an event
  135. E.Trigger("ITEMWINDOW_SELECT_UPDATE");
  136. else
  137. -- else select the row
  138. scrollingTable:SetSelection(realrow);
  139.  
  140. -- determine then item's id
  141. local j = 0;
  142. local item;
  143. for i, v in pairs(SD.table_items) do
  144. j = j + 1;
  145. if j == realrow then
  146. item = i;
  147. break;
  148. end
  149. end
  150. U.debug("Clicked: "..item..", "..SD.table_items[item]["itemLink"], 2);
  151.  
  152. -- then trigger an event
  153. E.Trigger("ITEMWINDOW_SELECT_UPDATE", item);
  154. end
  155.  
  156. -- and override the default handler
  157. return true;
  158. end
  159. end,
  160. });
  161.  
  162. UI.itemWindow.scrollingTable = scrollingTable;
  163.  
  164. -- Create the "Close" button
  165. local closeButton = CreateFrame("Button", frame:GetName().."CloseButton", frame, "UIPanelButtonTemplate")
  166. closeButton:SetPoint("BOTTOMRIGHT", -27, 17)
  167. closeButton:SetHeight(20)
  168. closeButton:SetWidth(80)
  169. closeButton:SetText(CLOSE)
  170. closeButton:SetScript("OnClick", function(self)
  171. self:GetParent():Hide();
  172. end);
  173.  
  174. UI.itemWindow.closeButton = closeButton;
  175.  
  176. -- Create the "Bid" button
  177. local bidButton = CreateFrame("Button", frame:GetName().."BidButton", frame, "UIPanelButtonTemplate")
  178. bidButton:SetPoint("BOTTOMRIGHT", closeButton, "BOTTOMLEFT", -5, 0)
  179. bidButton:SetHeight(20)
  180. bidButton:SetWidth(80)
  181. bidButton:SetText("Bid")
  182. bidButton:SetScript("OnClick", function(self, event)
  183. local id = scrollingTable:GetSelection()
  184. local j, itemLink, itemString = 0;
  185. for i, v in pairs(SD.table_items) do
  186. j = j + 1;
  187. if j == id then
  188. itemLink, itemString = v["itemLink"], i;
  189. break;
  190. end
  191. end
  192. bidPrompt = coroutine.create(function(self)
  193. U.debug("Bid recieved, resuming coroutine.", 1)
  194. local bid = bidAmount;
  195. if bid < 30 and bid ~= 10 and bid ~= 20 then
  196. U.debug("You must bid 10, 20, 30, or a value greater than 30. Your bid has been cancelled.")
  197. return
  198. end
  199. if bid % 2 ~= 0 then
  200. bid = math.floor(bid)
  201. if bid % 2 == 1 then
  202. bid = bid - 1
  203. end
  204. U.debug("You are not allowed to bid odd numbers or non-integers. Your bid has been rounded down to the nearest even integer.")
  205. end
  206. F.items.bid(itemString, bid);
  207. end)
  208. StaticPopupDialogs["FALOOT_BID"]["text"] = "How much would you like to bid for "..itemLink.."?";
  209. StaticPopup_Show("FALOOT_BID");
  210. U.debug("Querying for bid, coroutine paused.", 1);
  211. end);
  212. bidButton:Disable();
  213.  
  214. UI.itemWindow.bidButton = bidButton;
  215.  
  216. -- Create the background of the Status Bar
  217. local statusbg = CreateFrame("Button", frame:GetName().."StatusBar", frame)
  218. statusbg:SetPoint("BOTTOMLEFT", 15, 15)
  219. statusbg:SetPoint("BOTTOMRIGHT", -197, 15)
  220. statusbg:SetHeight(24)
  221. statusbg:SetBackdrop({
  222. bgFile = "Interface\\ChatFrame\\ChatFrameBackground",
  223. edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
  224. tile = true, tileSize = 16, edgeSize = 16,
  225. insets = { left = 3, right = 3, top = 5, bottom = 3 }
  226. })
  227. statusbg:SetBackdropColor(0.1,0.1,0.1)
  228. statusbg:SetBackdropBorderColor(0.4,0.4,0.4)
  229.  
  230. -- Create the text of the Status Bar
  231. local statusText = statusbg:CreateFontString(statusbg:GetName().."Text", "OVERLAY", "GameFontNormal")
  232. statusText:SetPoint("TOPLEFT", 7, -2)
  233. statusText:SetPoint("BOTTOMRIGHT", -7, 2)
  234. statusText:SetHeight(20)
  235. statusText:SetJustifyH("LEFT")
  236. statusText:SetText("")
  237.  
  238. UI.itemWindow.status = statusText;
  239.  
  240. -- Create the background of the title
  241. local titlebg = frame:CreateTexture(frame:GetName().."TitleBackground", "OVERLAY")
  242. titlebg:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header")
  243. titlebg:SetTexCoord(0.31, 0.67, 0, 0.63)
  244. titlebg:SetPoint("TOP", 0, 12)
  245. titlebg:SetHeight(40)
  246.  
  247. -- Create the title frame
  248. local title = CreateFrame("Frame", frame:GetName().."TitleMover", frame)
  249. title:EnableMouse(true)
  250. title:SetScript("OnMouseDown", function(frame)
  251. frame:GetParent():StartMoving()
  252. end)
  253. title:SetScript("OnMouseUp", function(frame)
  254. frame:GetParent():StopMovingOrSizing()
  255. end)
  256. title:SetAllPoints(titlebg)
  257.  
  258. -- Create the text of the title
  259. local titletext = title:CreateFontString(frame:GetName().."TitleText", "OVERLAY", "GameFontNormal")
  260. titletext:SetPoint("TOP", titlebg, "TOP", 0, -14)
  261. titletext:SetText("FA Loot");
  262.  
  263. titlebg:SetWidth((titletext:GetWidth() or 0) + 10)
  264.  
  265. -- Create the title background left edge
  266. local titlebg_l = frame:CreateTexture(frame:GetName().."TitleEdgeLeft", "OVERLAY")
  267. titlebg_l:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header")
  268. titlebg_l:SetTexCoord(0.21, 0.31, 0, 0.63)
  269. titlebg_l:SetPoint("RIGHT", titlebg, "LEFT")
  270. titlebg_l:SetWidth(30)
  271. titlebg_l:SetHeight(40)
  272.  
  273. -- Create the title background right edge
  274. local titlebg_r = frame:CreateTexture(frame:GetName().."TitleEdgeRight", "OVERLAY")
  275. titlebg_r:SetTexture("Interface\\DialogFrame\\UI-DialogBox-Header")
  276. titlebg_r:SetTexCoord(0.67, 0.77, 0, 0.63)
  277. titlebg_r:SetPoint("LEFT", titlebg, "RIGHT")
  278. titlebg_r:SetWidth(30)
  279. titlebg_r:SetHeight(40)
  280. end
  281.  
  282. local function setStatus()
  283. local bidding, rolling, only = 0, 0;
  284. for itemString, v in pairs(SD.table_items) do
  285. if SD.table_items[itemString]["bidStatus"] and SD.table_items[itemString]["status"] ~= "Ended" then
  286. only = itemString;
  287. if SD.table_items[itemString]["bidStatus"] == "Bid" then
  288. bidding = bidding + 1;
  289. elseif SD.table_items[itemString]["bidStatus"] == "Roll" then
  290. rolling = rolling + 1;
  291. end
  292. end
  293. end
  294.  
  295. if bidding + rolling == 0 then
  296. UI.itemWindow.status:SetText("");
  297. elseif bidding + rolling == 1 then
  298. local verb = "";
  299. if bidding > 0 then
  300. verb = "bid"
  301. else
  302. verb = "roll"
  303. end
  304. UI.itemWindow.status:SetText("Waiting to " .. verb .. " on " .. SD.table_items[only]["displayName"] .. ".")
  305. else
  306. if bidding > 0 and rolling > 0 then
  307. local plural1, plural2 = "", "";
  308. if bidding > 1 then
  309. plural1 = "s";
  310. end
  311. if rolling > 1 then
  312. plural2 = "s";
  313. end
  314. UI.itemWindow.status:SetText("Waiting to bid on " .. bidding .. " item" .. plural1 .. " and roll on " .. rolling .. " item" .. plural2 .. ".");
  315. elseif bidding > 0 then
  316. UI.itemWindow.status:SetText("Waiting to bid on " .. bidding .. " items.");
  317. else
  318. UI.itemWindow.status:SetText("Waiting to roll on " .. rolling .. " items.");
  319. end
  320. end
  321. end
  322.  
  323. --[[ ==========================================================================
  324. Helper Functions
  325. ========================================================================== --]]
  326.  
  327. local function generateIcons()
  328. local lasticon = nil -- reference value for anchoring to the most recently constructed icon
  329. local firsticon = nil -- reference value for anchoring the first constructed icon
  330. local k = 0 -- this variable contains the number of the icon we're currently constructing, necessary because we need to be able to create multiple icons per entry in the table
  331.  
  332. -- loop through the table of icons and reset everything
  333. for i=1,PD.maxIcons do
  334. SD.table_icons[i]:Hide()
  335. SD.table_icons[i]:ClearAllPoints()
  336. SD.table_icons[i]:SetScript("OnEnter", nil)
  337. SD.table_icons[i]:SetScript("OnLeave", nil)
  338. end
  339.  
  340. -- loop through each row of data
  341. for i, v in pairs(SD.table_items) do
  342. for j=1,v["quantity"] do
  343. -- if we're constructing an icon number that's higher than what we're setup to display then just skip it
  344. if k < #SD.table_icons then
  345. -- increment k by 1 before starting to construct
  346. k = k + 1;
  347.  
  348. -- set the texture of the icon
  349. SD.table_icons[k].texture:SetTexture(v.textureId);
  350.  
  351. -- set the icon's scripts
  352. SD.table_icons[k]:SetScript("OnEnter", function(self, button)
  353. -- store what row was selected so we can restore it later
  354. itemWindowSelection = UI.itemWindow.scrollingTable:GetSelection() or 0;
  355.  
  356. -- retrieve the row id that corresponds to the icon we're mousedover
  357. local row = 0;
  358. for l, w in pairs(SD.table_items) do
  359. row = row + 1;
  360. if i == l then
  361. -- select the row that correlates to the icon
  362. UI.itemWindow.scrollingTable:SetSelection(row);
  363. break;
  364. end
  365. end
  366.  
  367. --tooltip stuff
  368. GameTooltip:SetOwner(self, "ANCHOR_CURSOR")
  369. GameTooltip:SetHyperlink(v["tooltipItemLink"])
  370. F.history.setTooltip(i);
  371.  
  372. GameTooltip:Show()
  373. end)
  374.  
  375. SD.table_icons[k]:SetScript("OnLeave", function(self, button)
  376. -- restore the row that was selected before we mousedover this icon
  377. UI.itemWindow.scrollingTable:SetSelection(itemWindowSelection);
  378. itemWindowSelection = nil;
  379.  
  380. GameTooltip:Hide();
  381. end)
  382.  
  383. SD.table_icons[k]:SetScript("OnMouseUp", function(self, button)
  384. if button == "LeftButton" then -- left click: Selects the clicked row
  385. if IsModifiedClick("CHATLINK") then
  386. ChatEdit_InsertLink(v["itemLink"])
  387. elseif IsModifiedClick("DRESSUP") then
  388. DressUpItemLink(v["itemLink"])
  389. else
  390. -- retrieve the row id that corresponds to the icon we're mousedover
  391. local row = 0;
  392. for l, w in pairs(SD.table_items) do
  393. row = row + 1;
  394. if i == l then
  395. -- set iconSelect so that after the user finishes mousing over icons
  396. -- the row corresponding to this one gets selected
  397. itemWindowSelection = row;
  398. E.Trigger("ITEMWINDOW_SELECT_UPDATE", l);
  399. break;
  400. end
  401. end
  402. end
  403. elseif button == "RightButton" then -- right click: Ends the item, for everyone in raid if you have assist, otherwise only locally.
  404. endPrompt = coroutine.create( function()
  405. U.debug("Ending item "..v["itemLink"]..".", 1);
  406. if UnitIsGroupAssistant("PLAYER") or UnitIsGroupLeader("PLAYER") then
  407. F.sendMessage("RAID", nil, true, "end", i);
  408. end
  409. F.items.finish(i);
  410. end)
  411. if UnitIsGroupAssistant("PLAYER") or UnitIsGroupLeader("PLAYER") then
  412. StaticPopupDialogs["FALOOT_END"]["text"] = "Are you sure you want to manually end "..v["itemLink"].." for all players in the raid?";
  413. else
  414. StaticPopupDialogs["FALOOT_END"]["text"] = "Are you sure you want to manually end "..v["itemLink"].."?";
  415. end
  416. StaticPopup_Show("FALOOT_END");
  417. end
  418. end)
  419.  
  420. -- if this isn't the first icon then anchor it to the previous icon
  421. if lasticon then
  422. SD.table_icons[k]:SetPoint("LEFT", lasticon, "RIGHT", 1, 0)
  423. end
  424. -- show the icon we just constructed
  425. SD.table_icons[k]:Show()
  426. -- set the icon we just constructed as the most recently constructed icon
  427. lasticon = SD.table_icons[k];
  428. end
  429. end
  430. end
  431.  
  432. -- anchor the first icon in the row so that the row is centered in the window
  433. SD.table_icons[1]:SetPoint("LEFT", UI.itemWindow.iconFrame, "LEFT", (501-(k*(40+1)))/2, 0)
  434. end
  435.  
  436. --[[ ==========================================================================
  437. Static Popup Dialogs
  438. ========================================================================== --]]
  439.  
  440. StaticPopupDialogs["FALOOT_BID"] = {
  441. text = "How much would you like to bid?",
  442. button1 = "Bid",
  443. button2 = CANCEL,
  444. timeout = 0,
  445. whileDead = true,
  446. OnAccept = function(self)
  447. bidAmount = tonumber(self.editBox:GetText());
  448. coroutine.resume(bidPrompt);
  449. end,
  450. OnShow = function(self)
  451. self.editBox:SetText("");
  452. self.editBox:SetNumeric(true);
  453. self.editBox:SetScript("OnEnterPressed", function(self)
  454. bidAmount = tonumber(self:GetText());
  455. coroutine.resume(bidPrompt);
  456. StaticPopup_Hide("FALOOT_BID");
  457. end);
  458. self.editBox:SetScript("OnEscapePressed", function(self)
  459. StaticPopup_Hide("FALOOT_BID");
  460. end);
  461. end,
  462. hasEditBox = true,
  463. preferredIndex = STATICPOPUPS_NUMDIALOGS,
  464. }
  465.  
  466. StaticPopupDialogs["FALOOT_END"] = {
  467. text = "Are you sure you want to manually end this item for all players in the raid?",
  468. button1 = YES,
  469. button2 = CANCEL,
  470. timeout = 0,
  471. whileDead = true,
  472. hideOnEscape = true,
  473. OnAccept = function()
  474. coroutine.resume(endPrompt)
  475. end,
  476. enterClicksFirstButton = 1,
  477. preferredIndex = STATICPOPUPS_NUMDIALOGS,
  478. }
  479.  
  480. --[[ ==========================================================================
  481. Item Functions
  482. ========================================================================== --]]
  483.  
  484. -- === items.add() ==========================================================
  485.  
  486. F.items.add = function(itemString, checkCache)
  487. U.debug("itemAdd(), itemString = "..itemString, 1);
  488. -- itemString must be a string!
  489. if type(itemString) ~= "string" then
  490. U.debug("itemAdd was passed a non-string value!", 1);
  491. return;
  492. end
  493.  
  494. local itemLink = U.ItemLinkAssemble(itemString);
  495.  
  496. -- caching stuff
  497. if itemLink then
  498. U.debug("Item is cached, continuing.", 1);
  499. for i=1,#SD.table_itemQuery do
  500. if SD.table_itemQuery[i] == itemString then
  501. table.remove(SD.table_itemQuery, i)
  502. break
  503. end
  504. end
  505. else
  506. if not checkCache then
  507. U.debug("Item is not cached, requesting item info from server.", 1);
  508. table.insert(SD.table_itemQuery, itemString);
  509. else
  510. U.debug("Item is not cached, aborting.", 1);
  511. end
  512. return;
  513. end
  514.  
  515. -- check if item passes the filter
  516. if not U.checkFilters(itemString, true) then
  517. U.debug(itemString.." did not pass the item filter.", 2);
  518. return;
  519. end
  520.  
  521. if SD.table_items[itemString] then
  522. SD.table_items[itemString]["quantity"] = SD.table_items[itemString]["quantity"] + 1;
  523. local _, _, _, iLevel, _, _, _, _, _, texture = GetItemInfo(itemLink);
  524. local displayName = itemLink
  525. if SD.table_items[itemString]["quantity"] > 1 then
  526. displayName = displayName .. " x" .. SD.table_items[itemString]["quantity"];
  527. end
  528. SD.table_items[itemString]["displayName"] = displayName;
  529. else
  530. local _, _, _, iLevel, _, _, _, _, _, texture = GetItemInfo(itemLink);
  531. local displayName = itemLink
  532. SD.table_items[itemString] = {
  533. ["quantity"] = 1,
  534. ["displayName"] = displayName,
  535. ["itemLink"] = itemLink,
  536. ["textureId"] = GetItemIcon(itemLink),
  537. ["currentValue"] = 30,
  538. ["winners"] = {},
  539. ["tooltipItemLink"] = itemLink,
  540. }
  541.  
  542. if SD.authedMissingItems and SD.authedMissingItems[itemString] then
  543. SD.table_items[itemString].host = SD.authedMissingItems[itemString];
  544. SD.authedMissingItems[itemString] = nil;
  545. end
  546. end
  547.  
  548. if not UI.itemWindow.frame:IsShown() then
  549. if UnitAffectingCombat("PLAYER") then
  550. showAfterCombat = true
  551. U.debug(itemLink.." was found but the player is in combat.");
  552. else
  553. UI.itemWindow.frame:Show()
  554. end
  555. end
  556.  
  557. --[[ Don't call ITEM_UPDATE here, leave that up to the place where
  558. this method is called from for efficiency's sake --]]
  559.  
  560. return true
  561. end
  562.  
  563. -- === items.bid() ============================================================
  564.  
  565. F.items.bid = function(itemString, bid)
  566. bid = tonumber(bid)
  567. U.debug("FALoot:itemBid("..itemString..", "..bid..")", 1)
  568. if not SD.table_items[itemString] then
  569. U.debug("Item not found! Aborting.", 1);
  570. return;
  571. end
  572.  
  573. SD.table_items[itemString]["bid"] = bid;
  574. SD.table_items[itemString]["bidStatus"] = "Bid";
  575. U.debug("items.bid(): Queued bid for "..SD.table_items[itemString]["itemLink"]..".", 1);
  576.  
  577. -- Process the new bid, triggering a status text refresh if necessary.
  578. if not F.items.processBids() then
  579. E.Trigger("ITEMWINDOW_STATUS_TEXT_UPDATE");
  580. end
  581. end
  582.  
  583. -- === items.processBids() ====================================================
  584.  
  585. F.items.processBids = function()
  586. local needsRefresh = false;
  587.  
  588. for itemString, v in pairs(SD.table_items) do
  589. if SD.table_items[itemString]["bidStatus"] and SD.table_items[itemString]["host"] and ((v["currentValue"] == 30 and v["bid"] >= 30) or v["currentValue"] == v["bid"]) then
  590. if v["bidStatus"] == "Bid" and v["status"] == "Tells" then
  591. SendChatMessage(tostring(v["bid"]), "WHISPER", nil, v["host"]);
  592. SD.table_items[itemString]["bidStatus"] = "Roll";
  593. U.debug("items.processBids(): Bid and queued roll for "..SD.table_items[itemString]["itemLink"]..".", 1);
  594. needsRefresh = true;
  595. elseif v["bidStatus"] == "Roll" and v["status"] == "Rolls" then
  596. F.items.roll(v["bid"]);
  597. SD.table_items[itemString]["bidStatus"] = nil;
  598. U.debug("items.processBids(): Rolled for "..SD.table_items[itemString]["itemLink"]..".", 1);
  599. needsRefresh = true;
  600. end
  601. end
  602. end
  603.  
  604. if needsRefresh then
  605. E.Trigger("ITEMWINDOW_STATUS_TEXT_UPDATE");
  606. end
  607.  
  608. return needsRefresh;
  609. end
  610.  
  611. -- === items.finish() ============================================================
  612.  
  613. F.items.finish = function(itemString)
  614. if not type(itemString) == "string" then
  615. error('Usage: items.finish("itemString")');
  616. elseif not SD.table_items[itemString] then
  617. return;
  618. end
  619.  
  620. SD.table_items[itemString]["status"] = "Ended";
  621.  
  622. if SD.tellsInProgress and SD.tellsInProgress == itemString then
  623. SD.tellsInProgress = nil;
  624. UI.tellsWindow.frame:Hide();
  625. end
  626.  
  627. if SD.authedMissingItems then
  628. SD.authedMissingItems[itemString] = nil;
  629. end
  630.  
  631. C_Timer.After(PD.expTime, function()
  632. if SD.table_items[itemString] and SD.table_items[itemString]["status"] == "Ended" then
  633. SD.table_items[itemString] = nil;
  634. E.Trigger("ITEM_UPDATE");
  635. end
  636. end);
  637.  
  638. E.Trigger("ITEM_UPDATE");
  639. E.Trigger("ITEMWINDOW_STATUS_TEXT_UPDATE");
  640. end
  641.  
  642. -- === items.addWinner() ======================================================
  643.  
  644. F.items.addWinner = function(itemString, winner, bid)
  645. if not (itemString and winner and bid) then
  646. U.debug("Input not valid, aborting.", 1);
  647. return;
  648. elseif not SD.table_items[itemString] then
  649. U.debug(itemString.." is not a valid active item!", 1);
  650. return;
  651. end
  652.  
  653. -- check if the player was the winner of the item
  654. if winner == SD.PLAYER_NAME then
  655. U.debug("The player won an item!", 1);
  656. LootWonAlertFrame_ShowAlert(SD.table_items[itemString]["itemLink"], 1, LOOT_ROLL_TYPE_NEED, bid.." DKP");
  657. end
  658.  
  659. -- create a table entry for that pricepoint
  660. if not SD.table_items[itemString]["winners"][bid] then
  661. SD.table_items[itemString]["winners"][bid] = {};
  662. end
  663.  
  664. -- insert this event into the winners table
  665. table.insert(SD.table_items[itemString]["winners"][bid], winner);
  666.  
  667. -- if # of winners >= item quantity then auto end the item
  668. local numWinners = 0;
  669. for j, v in pairs(SD.table_items[itemString]["winners"]) do
  670. numWinners = numWinners + #v;
  671. end
  672. U.debug("numWinners = "..numWinners, 3);
  673. if numWinners >= SD.table_items[itemString]["quantity"] then
  674. F.items.finish(itemString);
  675. end
  676. end
  677.  
  678. -- === items.roll() ===========================================================
  679.  
  680. F.items.roll = function(value)
  681. value = tonumber(value);
  682.  
  683. if value % 1 ~= 0 then
  684. U.debug("You are not allowed to bid non-integers. Your bid has been rounded down to the nearest even integer.");
  685. value = math.floor(value);
  686. if value % 2 == 1 then
  687. value = value - 1;
  688. end
  689. elseif value % 2 ~= 0 then
  690. U.debug("You are not allowed to bid odd numbers. Your bid has been rounded down to the nearest even number.");
  691. value = value - (value % 2);
  692. end
  693.  
  694. if value > 30 then
  695. RandomRoll((value-30)/2, ((value-30)/2)+30)
  696. elseif value == 30 or value == 20 or value == 10 then
  697. RandomRoll(1, value)
  698. else
  699. U.debug("Invalid roll value!")
  700. end
  701. end
  702.  
  703. C.Register("roll", function(value)
  704. if not (value and type(tonumber(value)) == "number") then
  705. U.debug('Invalid arguments for "roll" command, the correct format is "/fa roll x", eg: "/fa roll 90".');
  706. return;
  707. end
  708. F.items.roll(value);
  709. end, "x -- rolls on an item for x DKP.");
  710.  
  711. --[[ ==========================================================================
  712. FALoot Events
  713. ========================================================================== --]]
  714.  
  715. -- === GUI Initiator ==========================================================
  716.  
  717. E.Register("PLAYER_LOGIN", function()
  718. createGUI();
  719. end);
  720.  
  721. -- === Status Bar Updater =====================================================
  722.  
  723. E.Register("ITEMWINDOW_STATUS_TEXT_UPDATE", setStatus);
  724.  
  725. -- === Item Table Updater =====================================================
  726.  
  727. E.Register("ITEM_UPDATE", function(itemString)
  728. local t = {};
  729.  
  730. for i, v in pairs(SD.table_items) do
  731. -- create status string
  732. local statusString, statusColor = "", {["r"] = 1, ["g"] = 1, ["b"] = 1, ["a"] = 1};
  733. if v["status"] == "Ended" then
  734. statusString = v["status"];
  735. statusColor = {["r"] = 0.5, ["g"] = 0.5, ["b"] = 0.5, ["a"] = 1};
  736. elseif v["status"] == "Tells" then
  737. statusString = v["currentValue"].." ("..v["status"]..")";
  738. statusColor = {["r"] = 0, ["g"] = 1, ["b"] = 0, ["a"] = 1}
  739. elseif v["status"] == "Rolls" then
  740. statusString = v["currentValue"].." ("..v["status"]..")";
  741. statusColor = {["r"] = 1, ["g"] = 0, ["b"] = 0, ["a"] = 1};
  742. elseif not v["status"] or v["status"] == "" then
  743. statusString = v["currentValue"];
  744. statusColor = {["r"] = 0.5, ["g"] = 0.5, ["b"] = 0.5, ["a"] = 1};
  745. end
  746.  
  747. -- create winner string
  748. local winnerString = "";
  749. for j, w in pairs(v["winners"]) do
  750. if winnerString ~= "" then
  751. winnerString = winnerString .. ", ";
  752. end
  753. local subString = "";
  754. for k=1,#w do
  755. if subString ~= "" then
  756. subString = subString .. " & ";
  757. end
  758. local shortName = w[k];
  759. -- Remove realm suffix for display
  760. if string.match(shortName, "^(.-)%-.+") then
  761. shortName = string.match(shortName, "^(.-)%-.+");
  762. end
  763. subString = subString .. shortName;
  764. end
  765. winnerString = winnerString .. subString .. " (" .. j .. ")";
  766. end
  767.  
  768. -- create bonus string
  769. local upgradeStr = "";
  770. local socketStr = "";
  771. local tertiaryStr = "";
  772. local score = 0;
  773. local netLevels = 0;
  774. local bonuses = string.match(i, "%d+:%d+:([0-9:]+)");
  775. if bonuses then
  776. for bonus in string.gmatch(bonuses, "%d+") do
  777. bonus = tonumber(bonus);
  778. if bonus > 1472 and bonus <= 1672 then -- Upgraded Item Level
  779. netLevels = netLevels + tostring(bonus-1472);
  780. elseif bonus == 565 then -- Socket
  781. socketStr = "!";
  782. score = score + 10;
  783. elseif bonus >= 40 and bonus <= 43 then -- Tertiary
  784. tertiaryStr = "*";
  785. score = score + 1;
  786. elseif SD.difficultyLevelDeltas[bonus] then
  787. netLevels = netLevels - SD.difficultyLevelDeltas[bonus];
  788. end
  789. end
  790. end
  791.  
  792. if netLevels > 0 then
  793. upgradeStr = "+" .. netLevels;
  794. score = score + netLevels;
  795. end
  796.  
  797. local bonusString = upgradeStr .. socketStr .. tertiaryStr;
  798. local bonusColor;
  799. if score >= 15 then
  800. bonusColor = { ["r"] = 1.0, ["g"] = 0.502, ["b"] = 0, ["a"] = 1.0 };
  801. elseif score >= 10 then
  802. bonusColor = { ["r"] = 0.69, ["g"] = 0.282, ["b"] = 0.973, ["a"] = 1.0 };
  803. elseif score >= 5 then
  804. bonusColor = { ["r"] = 0, ["g"] = 0.502, ["b"] = 1.0, ["a"] = 1.0 };
  805. else
  806. bonusColor = { ["r"] = 1.0, ["g"] = 1.0, ["b"] = 1.0, ["a"] = 1.0 };
  807. end
  808.  
  809. -- insert assembled data into table
  810. table.insert(t, {
  811. ["cols"] = {
  812. {
  813. ["value"] = v["displayName"],
  814. ["color"] = { ["r"] = 1.0, ["g"] = 1.0, ["b"] = 1.0, ["a"] = 1.0 },
  815. },
  816. {
  817. ["value"] = bonusString,
  818. ["color"] = bonusColor,
  819. },
  820. {
  821. ["value"] = statusString,
  822. ["color"] = statusColor,
  823. },
  824. {
  825. ["value"] = winnerString,
  826. ["color"] = { ["r"] = 1.0, ["g"] = 1.0, ["b"] = 1.0, ["a"] = 1.0 },
  827. },
  828. },
  829. ["color"] = { ["r"] = 1.0, ["g"] = 1.0, ["b"] = 1.0, ["a"] = 1.0 },
  830. })
  831. end
  832.  
  833. UI.itemWindow.scrollingTable:SetData(t, false);
  834. generateIcons();
  835.  
  836. if UI.itemWindow.tellsButton then
  837. if #t >= 8 then
  838. UI.itemWindow.tellsButton:ClearAllPoints();
  839. UI.itemWindow.tellsButton:SetPoint("TOP", UI.itemWindow.bidButton, "BOTTOM");
  840. else
  841. UI.itemWindow.tellsButton:ClearAllPoints();
  842. UI.itemWindow.tellsButton:SetPoint("BOTTOM", UI.itemWindow.bidButton, "TOP");
  843. end
  844. end
  845.  
  846. if SD.tellsInProgress and SD.tellsInProgress == itemString then
  847. E.Trigger("TELLSWINDOW_UPDATE");
  848. end
  849. F.items.processBids();
  850. end);
  851.  
  852. -- === Item Select Reaction ===================================================
  853.  
  854. E.Register("ITEMWINDOW_SELECT_UPDATE", function(item)
  855. if item then
  856. if UI.itemWindow.tellsButton then
  857. if (not SD.table_items[item]["status"] or SD.table_items[item]["status"] == "") and not SD.tellsInProgress and not SD.pendingPostRequest then
  858. --U.debug("Status of entry #"..id..' is "'..(v["status"] or "")..'".', 1);
  859. UI.itemWindow.tellsButton:Enable();
  860. else
  861. UI.itemWindow.tellsButton:Disable();
  862. end
  863. end
  864.  
  865. -- TODO: make this only enable if the item can be bid on
  866. UI.itemWindow.bidButton:Enable();
  867. else
  868. UI.itemWindow.tellsButton:Disable();
  869. UI.itemWindow.bidButton:Disable();
  870. end
  871. end)
  872.  
  873. -- === Item End Msg Handler ===================================================
  874.  
  875. AM.Register("end", function(channel, sender, item)
  876. F.items.finish(item);
  877. end);
  878.  
  879. -- === Loot Msg Handler =======================================================
  880.  
  881. AM.Register("loot", function(channel, sender, loot)
  882. if not A.isEnabled() then
  883. return;
  884. end
  885.  
  886. -- check data integrity
  887. for i, v in pairs(loot) do
  888. if not (v["checkSum"] and v["checkSum"] == #v) then
  889. error("Loot data recieved via an addon message failed the integrity check.");
  890. end
  891. end
  892.  
  893. for i, v in pairs(loot) do
  894. if not hasBeenLooted[i] then
  895. for j=1,#v do
  896. U.debug("Added "..v[j].." to the loot window via addon message.", 2);
  897. F.items.add(v[j]);
  898. end
  899. hasBeenLooted[i] = true;
  900. else
  901. U.debug(i.." has already been looted.", 2);
  902. end
  903. end
  904.  
  905. E.Trigger("ITEM_UPDATE");
  906. end);
  907.  
  908. -- Item Winner Msg handler ====================================================
  909.  
  910. AM.Register("itemWinner", function(channel, sender, itemString, winner, bid, cST)
  911. F.items.addWinner(itemString, winner, bid, cST);
  912. end);
  913.  
  914. -- === Item Status handler ====================================================
  915.  
  916. CM.Register("RAID", function(sender, msg)
  917. local rank = 0;
  918.  
  919. if PD.debugOn == 0 then
  920. for i=1,40 do
  921. local name, currentRank = U.GetRaidRosterInfo(i);
  922. if name == sender then
  923. rank = currentRank;
  924. break;
  925. end
  926. end
  927. end
  928.  
  929. if not (PD.debugOn > 0 or rank > 0) then
  930. return;
  931. end
  932.  
  933. local linkless, replaces = string.gsub(msg, SD.HYPERLINK_PATTERN, "");
  934.  
  935. if replaces == 1 then -- if the number of item links in the message is exactly 1 then we should process it
  936. local itemLink = string.match(msg, SD.HYPERLINK_PATTERN); -- retrieve itemLink from the message
  937. local itemString = U.ItemLinkStrip(itemLink);
  938. msg = string.gsub(msg, "x%d+", ""); -- remove any "x2" or "x3"s from the string
  939. if not msg then
  940. return;
  941. end
  942. local value = string.match(msg, "]|h|r%s*(.+)"); -- take anything else after the link and any following spaces as the value
  943. if not value then
  944. return;
  945. end
  946. value = string.gsub(value, "%s+", " "); -- replace any double spaces with a single space
  947. if not value then
  948. return;
  949. end
  950. value = string.lower(value);
  951.  
  952. if SD.table_items[itemString] then
  953. if not SD.table_items[itemString]["host"] then
  954. SD.table_items[itemString]["host"] = sender;
  955. end
  956.  
  957. if string.match(value, "roll") then
  958. SD.table_items[itemString]["status"] = "Rolls";
  959. elseif string.match(value, "[321]0") then
  960. SD.table_items[itemString]["currentValue"] = tonumber(string.match(value, "[321]0"));
  961. SD.table_items[itemString]["status"] = "Tells";
  962. end
  963.  
  964. E.Trigger("ITEM_UPDATE", itemString);
  965. --FALoot:checkBids(); --TODO
  966. else
  967. U.debug("Hyperlink is not in item table.", 2);
  968. end
  969. end
  970. end);
  971.  
  972. -- === DE'd Item Ender ========================================================
  973.  
  974. CM.Register("CHANNEL", function(sender, msg, channel)
  975. if string.lower(channel) ~= "aspects" then
  976. return;
  977. end
  978. if not msg then
  979. return;
  980. end
  981.  
  982. local itemLink = string.match(msg, SD.HYPERLINK_PATTERN);
  983. if not itemLink then
  984. return;
  985. end
  986.  
  987. local itemString = U.ItemLinkStrip(itemLink);
  988. local msg = string.gsub(msg, SD.HYPERLINK_PATTERN, ""); -- now remove the link
  989. if not msg or msg == "" then
  990. return;
  991. end
  992. local msg = string.lower(msg) -- put in lower case
  993. local msg = " "..string.gsub(msg, "[/,]", " ").." "
  994. if string.match(msg, " d%s?e ") or string.match(msg, " disenchant ") then
  995. if UnitIsGroupAssistant("PLAYER") or UnitIsGroupLeader("PLAYER") then
  996. F.sendMessage("RAID", nil, true, "end", itemString);
  997. end
  998. F.items.finish(itemString);
  999. end
  1000. end);
  1001.  
  1002. --[[ ==========================================================================
  1003. API Events
  1004. ========================================================================== --]]
  1005.  
  1006. local eventFrame, events = CreateFrame("Frame"), {}
  1007.  
  1008. -- === Loot Comm Handler ======================================================
  1009.  
  1010. function events:LOOT_READY(...)
  1011. if not A.isEnabled() then
  1012. return;
  1013. end
  1014.  
  1015. local loot = {} -- create a temporary table to organize the loot on the mob
  1016.  
  1017. for i=1,GetNumLootItems() do -- loop through all items in the window
  1018. local sourceInfo = {GetLootSourceInfo(i)}
  1019. for j=1,#sourceInfo/2 do
  1020. local mobID = sourceInfo[j*2-1] -- retrieve GUID of the mob that holds the item
  1021. if mobID and not hasBeenLooted[mobID] and not string.match(mobID, "^Item") then -- ignore items from sources that have already been looted or from item-based sources
  1022. if not loot[mobID] then
  1023. loot[mobID] = {};
  1024. end
  1025. local item = GetLootSlotLink(i);
  1026. if item then
  1027. local itemString = U.ItemLinkStrip(item);
  1028. if itemString and U.checkFilters(itemString) then
  1029. for l=1,max(sourceInfo[j*2], 1) do -- repeat the insert if there is multiple of the item in that slot.
  1030. -- max() is there to remedy the bug with GetLootSourceInfo returning incorrect (0) values.
  1031. -- GetLootSourceInfo may also return multiple quantity when there is actually only
  1032. -- one of the item, but there's not much we can do about that.
  1033. table.insert(loot[mobID], itemString);
  1034. end
  1035. end
  1036. end
  1037. end
  1038. end
  1039. end
  1040.  
  1041. local empty = true;
  1042. -- prune enemies with no loot
  1043. for i, v in pairs(loot) do
  1044. if #v == 0 then
  1045. loot[i] = nil;
  1046. else
  1047. empty = false;
  1048. end
  1049. end
  1050.  
  1051. -- stop now if there's no loot
  1052. if empty then
  1053. return;
  1054. end
  1055.  
  1056. -- add an item count for each GUID so that other clients may verify data integrity
  1057. for i, v in pairs(loot) do
  1058. loot[i]["checkSum"] = #v;
  1059. end
  1060.  
  1061. U.debug(loot, 3);
  1062.  
  1063. -- check data integrity
  1064. for i, v in pairs(loot) do
  1065. if not (v["checkSum"] and v["checkSum"] == #v) then
  1066. error("Self assembled loot data failed the integrity check.");
  1067. end
  1068. end
  1069.  
  1070. -- send addon message to tell others to add this to their window
  1071. F.sendMessage("RAID", nil, true, "loot", loot);
  1072.  
  1073. for i, v in pairs(loot) do
  1074. for j=1,#v do
  1075. -- we can assume that everything in the table is not on the HBL
  1076. F.items.add(v[j])
  1077. end
  1078. hasBeenLooted[i] = true;
  1079. end
  1080.  
  1081. E.Trigger("ITEM_UPDATE");
  1082. end
  1083.  
  1084. -- === Item Cache manager =====================================================
  1085.  
  1086. function events:GET_ITEM_INFO_RECEIVED()
  1087. local limit, itemAdded = #SD.table_itemQuery;
  1088. for i=limit,1,-1 do
  1089. local result = F.items.add(SD.table_itemQuery[i], true);
  1090. if result and not itemAdded then
  1091. itemAdded = result;
  1092. end
  1093. end
  1094. end
  1095.  
  1096. function events:PLAYER_REGEN_ENABLED()
  1097. if showAfterCombat then
  1098. UI.itemWindow.frame:Show();
  1099. showAfterCombat = nil;
  1100. end
  1101. end
  1102.  
  1103. eventFrame:SetScript("OnEvent", function(self, event, ...)
  1104. events[event](self, ...) -- call one of the functions above
  1105. end)
  1106. for k, v in pairs(events) do
  1107. eventFrame:RegisterEvent(k) -- Register all events for which handlers have been defined
  1108. end
Advertisement
Add Comment
Please, Sign In to add comment