Added a raid loot information window for masterlooter.

Added alt-click to bid call BoE in bags for masterlooter.
Added a popup to assign GP directly to loot recipients when they loot items. Esc or click Remind Me Later to defer.
Added addon communication (requires v3.18+) for pushing notifications of EPGP actions to members.
This commit is contained in:
Road-block
2017-10-29 16:11:32 +02:00
parent e1fcfbd548
commit 5bdf4a6e5a
9 changed files with 1133 additions and 107 deletions
+343
View File
@@ -0,0 +1,343 @@
--[[
Name: Deformat-2.0
Revision: $Rev: 6804 $
Author(s): ckknight (ckknight@gmail.com)
Website: http://ckknight.wowinterface.com/
Documentation: http://wiki.wowace.com/index.php/Deformat-2.0
SVN: http://svn.wowace.com/root/trunk/Deformat/Deformat-2.0
Description: A library to deformat format strings.
Dependencies: AceLibrary
]]
local MAJOR_VERSION = "Deformat-2.0"
local MINOR_VERSION = "$Revision: 6804 $"
if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary") end
if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end
local Deformat = {}
do
local sequences = {
["%d*d"] = "%%-?%%d+",
["s"] = ".+",
["[fg]"] = "%%-?%%d+%%.%%d+",
["%%%.%d[fg]"] = "%%-?%%d+%%.?%%d*",
["c"] = ".",
}
local curries = {}
local function doNothing(item)
return item
end
local v = {}
local function concat(a1, a2, a3, a4, a5)
local left, right
if not a2 then
return a1
elseif not a3 then
left, right = a1, a2
elseif not a4 then
return concat(concat(a1, a2), a3)
elseif not a5 then
return concat(concat(concat(a1, a2), a3), a4)
else
return concat(concat(concat(concat(a1, a2), a3), a4), a5)
end
if not string.find(left, "%%1%$") and not string.find(right, "%%1%$") then
return left .. right
elseif not string.find(right, "%%1%$") then
local i
for j = 9, 1, -1 do
if string.find(left, "%%" .. j .. "%$") then
i = j
break
end
end
while true do
local first
local firstPat
for x, y in pairs(sequences) do
local i = string.find(right, "%%" .. x)
if not first or (i and i < first) then
first = i
firstPat = x
end
end
if not first then
break
end
i = i + 1
right = string.gsub(right, "%%(" .. firstPat .. ")", "%%" .. i .. "$%1")
end
return left .. right
elseif not string.find(left, "%%1%$") then
local i = 1
while true do
local first
local firstPat
for x, y in pairs(sequences) do
local i = string.find(left, "%%" .. x)
if not first or (i and i < first) then
first = i
firstPat = x
end
end
if not first then
break
end
i = i + 1
left = string.gsub(left, "%%(" .. firstPat .. ")", "%%" .. i .. "$%1")
end
return concat(left, right)
else
local i
for j = 9, 1, -1 do
if string.find(left, "%%" .. j .. "%$") then
i = j
break
end
end
local j
for k = 9, 1, -1 do
if string.find(right, "%%" .. k .. "%$") then
j = k
break
end
end
for k = j, 1, -1 do
right = string.gsub(right, "%%" .. k .. "%$", "%%" .. k + i .. "%$")
end
return left .. right
end
end
local function Curry(a1, a2, a3, a4, a5)
local pattern = concat(a1, a2, a3, a4, a5)
if not string.find(pattern, "%%1%$") then
local unpattern = string.gsub(pattern, "([%(%)%.%*%+%-%[%]%?%^%$%%])", "%%%1")
local f = {}
local i = 0
while true do
local first
local firstPat
for x, y in pairs(sequences) do
local i = string.find(unpattern, "%%%%" .. x)
if not first or (i and i < first) then
first = i
firstPat = x
end
end
if not first then
break
end
unpattern = string.gsub(unpattern, "%%%%" .. firstPat, "(" .. sequences[firstPat] .. ")", 1)
i = i + 1
if firstPat == "c" or firstPat == "s" then
table.insert(f, doNothing)
else
table.insert(f, tonumber)
end
end
unpattern = "^" .. unpattern .. "$"
local _,alpha, bravo, charlie, delta, echo, foxtrot, golf, hotel, india
if i == 0 then
return
elseif i == 1 then
return function(text)
_,_,alpha = string.find(text, unpattern)
if alpha then
return f[1](alpha)
end
end
elseif i == 2 then
return function(text)
_,_,alpha, bravo = string.find(text, unpattern)
if alpha then
return f[1](alpha), f[2](bravo)
end
end
elseif i == 3 then
return function(text)
_,_,alpha, bravo, charlie = string.find(text, unpattern)
if alpha then
return f[1](alpha), f[2](bravo), f[3](charlie)
end
end
elseif i == 4 then
return function(text)
_,_,alpha, bravo, charlie, delta = string.find(text, unpattern)
if alpha then
return f[1](alpha), f[2](bravo), f[3](charlie), f[4](delta)
end
end
elseif i == 5 then
return function(text)
_,_,alpha, bravo, charlie, delta, echo = string.find(text, unpattern)
if alpha then
return f[1](alpha), f[2](bravo), f[3](charlie), f[4](delta), f[5](echo)
end
end
elseif i == 6 then
return function(text)
_,_,alpha, bravo, charlie, delta, echo, foxtrot = string.find(text, unpattern)
if alpha then
return f[1](alpha), f[2](bravo), f[3](charlie), f[4](delta), f[5](echo), f[6](foxtrot)
end
end
elseif i == 7 then
return function(text)
_,_,alpha, bravo, charlie, delta, echo, foxtrot, golf = string.find(text, unpattern)
if alpha then
return f[1](alpha), f[2](bravo), f[3](charlie), f[4](delta), f[5](echo), f[6](foxtrot), f[7](golf)
end
end
elseif i == 8 then
return function(text)
_,_,alpha, bravo, charlie, delta, echo, foxtrot, golf, hotel = string.find(text, unpattern)
if alpha then
return f[1](alpha), f[2](bravo), f[3](charlie), f[4](delta), f[5](echo), f[6](foxtrot), f[7](golf), f[8](hotel)
end
end
else
return function(text)
_,_,alpha, bravo, charlie, delta, echo, foxtrot, golf, hotel, india = string.find(text, unpattern)
if alpha then
return f[1](alpha), f[2](bravo), f[3](charlie), f[4](delta), f[5](echo), f[6](foxtrot), f[7](golf), f[8](hotel), f[9](india)
end
end
end
else
local o = {}
local f = {}
local unpattern = string.gsub(pattern, "([%(%)%.%*%+%-%[%]%?%^%$%%])", "%%%1")
local i = 1
while true do
local pat
for x, y in pairs(sequences) do
if not pat and string.find(unpattern, "%%%%" .. i .. "%%%$" .. x) then
pat = x
break
end
end
if not pat then
break
end
unpattern = string.gsub(unpattern, "%%%%" .. i .. "%%%$" .. pat, "(" .. sequences[pat] .. ")", 1)
if pat == "c" or pat == "s" then
table.insert(f, doNothing)
else
table.insert(f, tonumber)
end
i = i + 1
end
i = 1
string.gsub(pattern, "%%(%d)%$", function(w) o[i] = tonumber(w); i = i + 1; end)
v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9] = nil
for x, y in pairs(f) do
v[x] = f[y]
end
for x, y in pairs(v) do
f[x] = v[x]
end
unpattern = "^" .. unpattern .. "$"
i = i - 1
if i == 0 then
return function(text)
return
end
elseif i == 1 then
return function(text)
_,_,v[1] = string.find(text, unpattern)
if v[1] then
return f[1](v[1])
end
end
elseif i == 2 then
return function(text)
_,_,v[1],v[2] = string.find(text, unpattern)
if v[1] then
return f[1](v[o[1]]), f[2](v[o[2]])
end
end
elseif i == 3 then
return function(text)
_,_,v[1],v[2],v[3] = string.find(text, unpattern)
if v[1] then
return f[1](v[o[1]]), f[2](v[o[2]]), f[3](v[o[3]])
end
end
elseif i == 4 then
return function(text)
_,_,v[1],v[2],v[3],v[4] = string.find(text, unpattern)
if v[1] then
return f[1](v[o[1]]), f[2](v[o[2]]), f[3](v[o[3]]), f[4](v[o[4]])
end
end
elseif i == 5 then
return function(text)
_,_,v[1],v[2],v[3],v[4],v[5] = string.find(text, unpattern)
if v[1] then
return f[1](v[o[1]]), f[2](v[o[2]]), f[3](v[o[3]]), f[4](v[o[4]]), f[5](v[o[5]])
end
end
elseif i == 6 then
return function(text)
_,_,v[1],v[2],v[3],v[4],v[5],v[6] = string.find(text, unpattern)
if v[1] then
return f[1](v[o[1]]), f[2](v[o[2]]), f[3](v[o[3]]), f[4](v[o[4]]), f[5](v[o[5]]), f[6](v[o[6]])
end
end
elseif i == 7 then
return function(text)
_,_,v[1],v[2],v[3],v[4],v[5],v[6],v[7] = string.find(text, unpattern)
if v[1] then
return f[1](v[o[1]]), f[2](v[o[2]]), f[3](v[o[3]]), f[4](v[o[4]]), f[5](v[o[5]]), f[6](v[o[6]]), f[7](v[o[7]])
end
end
elseif i == 8 then
return function(text)
_,_,v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8] = string.find(text, unpattern)
if v[1] then
return f[1](v[o[1]]), f[2](v[o[2]]), f[3](v[o[3]]), f[4](v[o[4]]), f[5](v[o[5]]), f[6](v[o[6]]), f[7](v[o[7]]), f[8](v[o[8]])
end
end
else
return function(text)
_,_,v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9] = string.find(text, unpattern)
if v[1] then
return f[1](v[o[1]]), f[2](v[o[2]]), f[3](v[o[3]]), f[4](v[o[4]]), f[5](v[o[5]]), f[6](v[o[6]]), f[7](v[o[7]]), f[8](v[o[8]]), f[9](v[o[9]])
end
end
end
end
end
function Deformat:Deformat(text, a1, a2, a3, a4, a5)
self:argCheck(text, 2, "string")
self:argCheck(a1, 3, "string")
local pattern = a1
if a5 then
pattern = a1 .. a2 .. a3 .. a4 .. a5
elseif a4 then
pattern = a1 .. a2 .. a3 .. a4
elseif a3 then
pattern = a1 .. a2 .. a3
elseif a2 then
pattern = a1 .. a2
end
if curries[pattern] == nil then
curries[pattern] = Curry(a1, a2, a3, a4, a5)
end
return curries[pattern](text)
end
end
local mt = getmetatable(Deformat) or {}
mt.__call = Deformat.Deformat
setmetatable(Deformat, mt)
AceLibrary:Register(Deformat, MAJOR_VERSION, MINOR_VERSION)
Deformat = nil
+220
View File
@@ -0,0 +1,220 @@
--[[
Name: Gratuity-2.0
Revision: $Rev: 11053 $
Author: Tekkub Stoutwrithe (tekkub@gmail.com)
Website: http://wiki.wowace.com/index.php/GratuityLib
Documentation: http://wiki.wowace.com/index.php/Gratuity-2.0_API_Documentation
SVN: svn://svn.wowace.com/root/trunk/GratuityLib/Gratuity-2.0
Description: Tooltip parsing library
Dependencies: AceLibrary, (optional) Compost-2.0, (optional) Deformat-2.0
]]
local vmajor, vminor = "Gratuity-2.0", "$Revision: 11053 $"
if not AceLibrary then error(vmajor .. " requires AceLibrary.") end
if not AceLibrary:IsNewVersion(vmajor, vminor) then return end
local lib = {}
local methods = {
"SetBagItem", "SetAction", "SetAuctionItem", "SetAuctionSellItem", "SetBuybackItem",
"SetCraftItem", "SetCraftSpell", "SetHyperlink", "SetInboxItem", "SetInventoryItem",
"SetLootItem", "SetLootRollItem", "SetMerchantItem", "SetPetAction", "SetPlayerBuff",
"SetQuestItem", "SetQuestLogItem", "SetQuestRewardSpell", "SetSendMailItem", "SetShapeshift",
"SetSpell", "SetTalent", "SetTrackingSpell", "SetTradePlayerItem", "SetTradeSkillItem", "SetTradeTargetItem",
"SetTrainerService", "SetUnit", "SetUnitBuff", "SetUnitDebuff",
}
-- Activate a new instance of this library
local function activate(self, oldLib, oldDeactivate)
if oldLib then self.vars = oldLib.vars
else
self.vars = {}
self:CreateTooltip()
end
self:CreateSetMethods()
if oldDeactivate then oldDeactivate(oldLib) end
end
function lib:InitCompost()
if not self.vars.compost and AceLibrary:HasInstance("Compost-2.0") then self.vars.compost = AceLibrary("Compost-2.0") end
end
function lib:CreateTooltip()
local tt = CreateFrame("GameTooltip")
self.vars.tooltip = tt
tt:SetOwner(tt, "ANCHOR_NONE")
-- tooltip:SetParent()
self.vars.Llines, self.vars.Rlines = {}, {}
for i=1,30 do
self.vars.Llines[i], self.vars.Rlines[i] = tt:CreateFontString(), tt:CreateFontString()
self.vars.Llines[i]:SetFontObject(GameFontNormal)
self.vars.Rlines[i]:SetFontObject(GameFontNormal)
tt:AddFontStrings(self.vars.Llines[i], self.vars.Rlines[i])
end
end
-- Clears the tooltip completely, none of this "erase left, hide right" crap blizzard does
function lib:Erase()
self.vars.tooltip:ClearLines() -- Ensures tooltip's NumLines is reset
for i=1,30 do self.vars.Rlines[i]:SetText() end -- Clear text from right side (ClearLines only hides them)
if not self.vars.tooltip:IsOwned(self.vars.tooltip) then self.vars.tooltip:SetOwner(self.vars.tooltip, "ANCHOR_NONE") end
self:assert(self.vars.tooltip:IsOwned(self.vars.tooltip), "Gratuity's tooltip is not scanable")
end
-- Get the number of lines
-- Arg: endln - If passed and tooltip's NumLines is higher, endln is returned back
function lib:NumLines(endln)
local num = self.vars.tooltip:NumLines()
return endln and num > endln and endln or num or 0
end
local FindDefault = function(str, pattern)
return string.find(str, pattern);
end;
local FindExact = function(str, pattern)
if (str == pattern) then
return string.find(str, pattern);
end;
end;
-- If text is found on tooltip then results of string.find are returned
-- Args:
-- txt - The text string to find
-- startln - First tooltip line to check, default 1
-- endln - Last line to test, default 30
-- ignoreleft / ignoreright - Causes text on one side of the tooltip to be ignored
-- exact - the compare will be an exact match vs the default behaviour of
function lib:Find(txt, startln, endln, ignoreleft, ignoreright, exact)
local searchFunction = FindDefault;
if (exact == true) then
searchFunction = FindExact;
end;
self:argCheck(txt, 2, "string", "number")
local t1, t2 = type(startln or 1), type(self:NumLines(endln))
if (t1 ~= "number" or t2 ~= "number") then print(t1, t2, (startln or 1),self:NumLines(endln)) end
for i=(startln or 1),self:NumLines(endln) do
if not ignoreleft then
local txtl = self.vars.Llines[i]:GetText()
if (txtl and searchFunction(txtl, txt)) then return string.find(txtl, txt) end
end
if not ignoreright then
local txtr = self.vars.Rlines[i]:GetText()
if (txtr and searchFunction(txtr, txt)) then return string.find(txtr, txt) end
end
end
end
-- Calls Find many times.
-- Args are passed directly to Find, t1-t10 replace the txt arg
-- Returns Find results for the first match found, if any
function lib:MultiFind(startln, endln, ignoreleft, ignoreright, t1,t2,t3,t4,t5,t6,t7,t8,t9,t10)
self:argCheck(t1, 6, "string", "number")
if t1 and self:Find(t1, startln, endln, ignoreleft, ignoreright) then return self:Find(t1, startln, endln, ignoreleft, ignoreright)
elseif t2 then return self:MultiFind(startln, endln, ignoreleft, ignoreright, t2,t3,t4,t5,t6,t7,t8,t9,t10) end
end
local deformat
-- If text is found on tooltip then results of deformat:Deformat are returned
-- Args:
-- txt - The text string to deformat and serach for
-- startln - First tooltip line to check, default 1
-- endln - Last line to test, default 30
-- ignoreleft / ignoreright - Causes text on one side of the tooltip to be ignored
function lib:FindDeformat(txt, startln, endln, ignoreleft, ignoreright)
self:argCheck(txt, 2, "string", "number")
if not deformat then
self:assert(AceLibrary:HasInstance("Deformat-2.0"), "FindDeformat requires Deformat-2.0 to be available")
deformat = AceLibrary("Deformat-2.0")
end
for i=(startln or 1),self:NumLines(endln) do
if not ignoreleft then
local txtl = self.vars.Llines[i]:GetText()
if (txtl and deformat(txtl, txt)) then return deformat(txtl, txt) end
end
if not ignoreright then
local txtr = self.vars.Rlines[i]:GetText()
if (txtr and deformat(txtr, txt)) then return deformat(txtr, txt) end
end
end
end
-- Returns a table of strings pulled from the tooltip, or nil if no strings in tooltip
-- Args:
-- startln - First tooltip line to check, default 1
-- endln - Last line to test, default 30
-- ignoreleft / ignoreright - Causes text on one side of the tooltip to be ignored
function lib:GetText(startln, endln, ignoreleft, ignoreright)
self:InitCompost()
local retval
for i=(startln or 1),(endln or 30) do
local txtl, txtr
if not ignoreleft then txtl = self.vars.Llines[i]:GetText() end
if not ignoreright then txtr = self.vars.Rlines[i]:GetText() end
if txtl or txtr then
if not retval then retval = self.vars.compost and self.vars.compost:Acquire() or {} end
local t = self.vars.compost and self.vars.compost:Acquire(txtl, txtr) or {txtl, txtr}
table.insert(retval, t)
end
end
return retval
end
-- Returns the text from a specific line (both left and right unless second arg is true)
-- Args:
-- line - the line number you wish to retrieve
-- getright - if passed the right line will be returned, if not the left will be returned
function lib:GetLine(line, getright)
self:argCheck(line, 2, "number")
if self.vars.tooltip:NumLines() < line then return end
if getright then return self.vars.Rlines[line] and self.vars.Rlines[line]:GetText()
elseif self.vars.Llines[line] then
return self.vars.Llines[line]:GetText(), self.vars.Rlines[line]:GetText()
end
end
-----------------------------------
-- Set tooltip methods --
-----------------------------------
-- These methods are designed to immitate the GameTooltip API
local testmethods = {
SetAction = function(id) return HasAction(id) end,
}
local gettrue = function() return true end
function lib:CreateSetMethods()
for _,m in pairs(methods) do
local meth = m
local func = testmethods[meth] or gettrue
self[meth] = function(self,a1,a2,a3,a4)
self:Erase()
if not func(a1,a2,a3,a4) then return end
return self:pcall(self.vars.tooltip[meth], self.vars.tooltip,a1,a2,a3,a4) end
end
end
--------------------------------
-- Load this bitch! --
--------------------------------
AceLibrary:Register(lib, vmajor, vminor, activate)
lib = nil
+1 -1
View File
@@ -40,7 +40,7 @@ end
function sepgp_bids:setHideScript()
local detachedFrame, tablet
for i=1,4 do
for i=1,5 do
tablet = getglobal(string.format("Tablet20DetachedFrame%d",i))
if tablet and tablet.owner ~= nil and tablet.owner == "sepgp_bids" then
if not (tablet:GetScript("OnHide")) then
+1 -1
View File
@@ -45,7 +45,7 @@ end
function sepgp_logs:setHideScript()
local detachedFrame, tablet
for i=1,4 do
for i=1,5 do
tablet = getglobal(string.format("Tablet20DetachedFrame%d",i))
if tablet and tablet.owner ~= nil and tablet.owner == "sepgp_logs" then
if not (tablet:GetScript("OnHide")) then
+110
View File
@@ -0,0 +1,110 @@
local T = AceLibrary("Tablet-2.0")
local D = AceLibrary("Dewdrop-2.0")
local C = AceLibrary("Crayon-2.0")
local BC = AceLibrary("Babble-Class-2.2")
sepgp_loot = sepgp:NewModule("sepgp_loot", "AceDB-2.0")
function sepgp_loot:OnEnable()
if not T:IsRegistered("sepgp_loot") then
T:Register("sepgp_loot",
"children", function()
T:SetTitle("shootyepgp loot info")
self:OnTooltipUpdate()
end,
"showTitleWhenDetached", true,
"showHintWhenDetached", true,
"cantAttach", true,
"menu", function()
D:AddLine(
"text", "Refresh",
"tooltipText", "Refresh window",
"func", function() sepgp_loot:Refresh() end
)
D:AddLine(
"text", "Clear",
"tooltipText", "Clear Loot.",
"func", function() sepgp_looted = {} sepgp_loot:Refresh() end
)
end
)
end
if not T:IsAttached("sepgp_loot") then
T:Open("sepgp_loot")
end
end
function sepgp_loot:OnDisable()
T:Close("sepgp_loot")
end
function sepgp_loot:Refresh()
T:Refresh("sepgp_loot")
end
function sepgp_loot:setHideScript()
local detachedFrame, tablet
for i=1,5 do
tablet = getglobal(string.format("Tablet20DetachedFrame%d",i))
if tablet and tablet.owner ~= nil and tablet.owner == "sepgp_loot" then
if not (tablet:GetScript("OnHide")) then
tablet:SetScript("OnHide",function()
if not T:IsAttached("sepgp_loot") then
T:Attach("sepgp_loot")
this:SetScript("OnHide",nil)
end
end)
end
end
end
end
function sepgp_loot:Toggle(forceShow)
if T:IsAttached("sepgp_loot") then
T:Detach("sepgp_loot")
if (T:IsLocked("sepgp_loot")) then
T:ToggleLocked("sepgp_loot")
end
self:setHideScript()
elseif (forceShow) then
sepgp_loot:Refresh()
else
T:Attach("sepgp_loot")
end
end
function sepgp_loot:BuildLootTable()
table.sort(sepgp_looted, function(a,b)
if (a[1] ~= b[1]) then return a[1] > b[1]
else return a[2] > b[2] end
end)
return sepgp_looted
end
function sepgp_loot:OnClickItem(data)
end
function sepgp_loot:OnTooltipUpdate()
local cat = T:AddCategory(
"columns", 5,
"text", C:Orange("Time"), "child_textR", 1, "child_textG", 1, "child_textB", 1, "child_justify", "LEFT",
"text2", C:Orange("Item"), "child_text2R", 1, "child_text2G", 1, "child_text2B", 0, "child_justify2", "LEFT",
"text3", C:Orange("Binds"), "child_text3R", 0, "child_text3G", 1, "child_text3B", 0, "child_justify3", "CENTER",
"text4", C:Orange("Looter"), "child_text4R", 0, "child_text4G", 1, "child_text4B", 0, "child_justify4", "RIGHT",
"text5", C:Orange("GP Action"), "child_text5R", 0, "child_text5G", 1, "child_text5B", 0, "child_justify5", "RIGHT"
)
local t = self:BuildLootTable()
for i = 1, table.getn(t) do
local timestamp,player,player_color,itemLink,bind,price,off_price,action = unpack(t[i])
cat:AddLine(
"text", timestamp,
"text2", itemLink,
"text3", bind,
"text4", player_color,
"text5", action--,
-- "func", "OnClickItem", "arg1", self, "arg2", t[i]
)
end
end
+1 -1
View File
@@ -40,7 +40,7 @@ end
function sepgp_reserves:setHideScript()
local detachedFrame, tablet
for i=1,4 do
for i=1,5 do
tablet = getglobal(string.format("Tablet20DetachedFrame%d",i))
if tablet and tablet.owner ~= nil and tablet.owner == "sepgp_reserves" then
if not (tablet:GetScript("OnHide")) then
+446 -96
View File
@@ -3,13 +3,24 @@ sepgp:SetModuleMixins("AceDebug-2.0")
local D = AceLibrary("Dewdrop-2.0")
local BZ = AceLibrary("Babble-Zone-2.2")
local C = AceLibrary("Crayon-2.0")
local BC = AceLibrary("Babble-Class-2.2")
local DF = AceLibrary("Deformat-2.0")
local G = AceLibrary("Gratuity-2.0")
sepgp.VARS = {
basegp = 135,
baseaward_ep = 100,
decay = 0.85,
max = 5000,
timeout = 45,
maxloglines = 500
maxloglines = 500,
prefix = "SEPGP_PREFIX",
bop = C:Red("BoP"),
boe = C:Yellow("BoE"),
nobid = C:White("NoBind"),
msgp = "Mainspec GP",
osgp = "Offspec GP",
bankde = "Bank-D/E",
reminder = C:Red("Unassigned")
}
local playerName = (UnitName("player"))
local shooty_reservechan = "Reserves"
@@ -39,21 +50,22 @@ do
hexColorQuality[ITEM_QUALITY_COLORS[i].hex] = i
end
end
-- TODO:
-- 2. Implement an Import facility to mirror Export.
sepgp.reserves = {}
sepgp.bids_main,sepgp.bids_off,sepgp.bid_item = {},{},{}
sepgp.timer = CreateFrame("Frame")
sepgp.timer.cd_text = ""
sepgp.timer:Hide()
sepgp.timer:SetScript("OnUpdate",function() sepgp.OnUpdate(this,arg1) end)
sepgp.bids_main,sepgp.bids_off,sepgp.bid_item = {},{},{}
function sepgp:OnInitialize() -- ADDON_LOADED (1) unless LoD
if sepgp_saychannel == nil then sepgp_saychannel = "GUILD" end
if sepgp_decay == nil then sepgp_decay = sepgp.VARS.decay end
if sepgp_progress == nil then sepgp_progress = "T1" end
if sepgp_discount == nil then sepgp_discount = 0.25 end
if sepgp_log == nil then sepgp_log = {} end
if sepgp_looted == nil then sepgp_looted = {} end
sepgp.extratip = CreateFrame("GameTooltip","shootyepgp_tooltip",UIParent,"GameTooltipTemplate")
end
@@ -87,36 +99,42 @@ function sepgp:AceEvent_FullyInitialized() -- SYNTHETIC EVENT, later than PLAYER
-- hook SetItemRef to parse our client bid links
self:Hook("SetItemRef")
-- hook tooltip to add our GP values
sepgp:TipHook()
self:TipHook()
-- hook LootFrameItem_OnClick to add our own click handlers for bid calls
self:SecureHook("LootFrameItem_OnClick")
-- hook ContainerFrameItemButton_OnClick to add our own click handlers for bid calls
self:Hook("ContainerFrameItemButton_OnClick")
-- hook pfUI loot module :(
if pfUI ~= nil and pfUI.loot ~= nil and type(pfUI.loot.UpdateLootFrame) == "function" then
self:SecureHook(pfUI.loot, "UpdateLootFrame", "pfUI_UpdateLootFrame")
end
-- make tablets closable with ESC
for i=1,4 do
for i=1,5 do
table.insert(UISpecialFrames,string.format("Tablet20DetachedFrame%d",i))
end
sepgp:RegisterChatCommand({"/shooty","/sepgp","/shootyepgp"},function() sepgp_standings:Toggle() end)
self:RegisterChatCommand({"/shooty","/sepgp","/shootyepgp"},function() sepgp_standings:Toggle() end)
end
function sepgp:OnEnable() -- PLAYER_LOGIN (2)
sepgp:RegisterEvent("GUILD_ROSTER_UPDATE",function()
self:RegisterEvent("GUILD_ROSTER_UPDATE",function()
if (arg1) then -- member join /leave
self:SetRefresh(true)
end
end)
sepgp:RegisterEvent("RAID_ROSTER_UPDATE",function()
self:RegisterEvent("RAID_ROSTER_UPDATE",function()
self:SetRefresh(true)
end)
sepgp:RegisterEvent("PARTY_MEMBERS_CHANGED",function()
self:RegisterEvent("PARTY_MEMBERS_CHANGED",function()
self:SetRefresh(true)
end)
sepgp:RegisterEvent("CHAT_MSG_RAID","captureLootCall")
sepgp:RegisterEvent("CHAT_MSG_RAID_LEADER","captureLootCall")
sepgp:RegisterEvent("CHAT_MSG_RAID_WARNING","captureLootCall")
sepgp:RegisterEvent("CHAT_MSG_WHISPER","captureBid")
self:RegisterEvent("CHAT_MSG_RAID","captureLootCall")
self:RegisterEvent("CHAT_MSG_RAID_LEADER","captureLootCall")
self:RegisterEvent("CHAT_MSG_RAID_WARNING","captureLootCall")
self:RegisterEvent("CHAT_MSG_WHISPER","captureBid")
self:RegisterEvent("CHAT_MSG_ADDON","addonComms")
self:RegisterEvent("CHAT_MSG_LOOT","captureLoot")
self:RegisterEvent("TRADE_PLAYER_ITEM_CHANGED","tradeLoot")
self:RegisterEvent("TRADE_ACCEPT_UPDATE","tradeLoot")
if (IsInGuild()) then
if (GetNumGuildMembers()==0) then
@@ -138,9 +156,19 @@ end
function sepgp:TipHook()
self:SecureHook(GameTooltip, "SetBagItem", function(this, bag, slot)
sepgp:AddDataToTooltip(GameTooltip, GetContainerItemLink(bag, slot))
local itemLink = GetContainerItemLink(bag, slot)
local ml_tip
if (itemLink) then
local is_master = (sepgp:lootMaster()) and true or nil
local link_found, _, itemColor, itemString, itemName = string.find(itemLink, "^(|c%x+)|H(.+)|h(%[.+%])")
if (link_found) then
local bind = self:itemBinding(itemString) or ""
ml_tip = is_master and bind == sepgp.VARS.boe
end
end
sepgp:AddDataToTooltip(GameTooltip, itemLink, nil, ml_tip)
end
) -- we leave it in for now so they can check if they were billed the correct GP
)
self:SecureHook(GameTooltip, "SetLootItem", function(this, slot)
local is_master = (sepgp:lootMaster()) and true or nil
sepgp:AddDataToTooltip(GameTooltip, GetLootSlotLink(slot), nil, is_master)
@@ -172,7 +200,7 @@ function sepgp:delayedInit()
if sepgp_reservechannel == nil then sepgp_reservechannel = shooty_reservechan end
local reservesChannelID = tonumber((GetChannelName(sepgp_reservechannel)))
if (reservesChannelID) and (reservesChannelID ~= 0) then
sepgp:reservesToggle(true)
self:reservesToggle(true)
end
-- migrate EPGP storage if needed
local _,_,major_ver = string.find((GetAddOnMetadata("shootyepgp","Version")),"^(%d+)%.[%d%.%-]+$")
@@ -203,12 +231,12 @@ function sepgp:AddDataToTooltip(tooltip,itemlink,itemstring,is_master)
else
line_limit = 29
end
local ep,gp = (sepgp:get_ep_v3(playerName) or 0), (sepgp:get_gp_v3(playerName) or sepgp.VARS.basegp)
local ep,gp = (self:get_ep_v3(playerName) or 0), (self:get_gp_v3(playerName) or sepgp.VARS.basegp)
local off_price = math.floor(price*sepgp_discount)
local pr,new_pr,new_pr_off = ep/gp, ep/(gp+price), ep/(gp+off_price)
local pr_delta = new_pr - pr
local pr_delta_off = new_pr_off - pr
local textRight = string.format("cost:|cff32cd32%d|r (|cffff0000%.02f|r |cffff7f00pr|r) offspec:|cff20b2aa%d|r (|cffff0000%.02f|r |cffff7f00pr|r)",price,new_pr,off_price,new_pr_off)
local textRight = string.format("gp:|cff32cd32%d|r(|cffff0000%.02f|r|cffff7f00pr|r) os:|cff20b2aa%d|r(|cffff0000%.02f|r|cffff7f00pr|r)",price,new_pr,off_price,new_pr_off)
if (tooltip:NumLines() < line_limit) then
tooltip:AddLine(" ")
tooltip:AddDoubleLine("|cff9664c8shootyepgp|r",textRight)
@@ -221,8 +249,9 @@ function sepgp:AddDataToTooltip(tooltip,itemlink,itemstring,is_master)
sepgp.extratip:SetOwner(tooltip,"ANCHOR_NONE")
sepgp.extratip:ClearAllPoints()
sepgp.extratip:SetPoint("TOPLEFT", tooltip, "BOTTOMLEFT", 0, -5)
sepgp.extratip:SetPoint("TOPRIGHT", tooltip, "BOTTOMRIGHT", 0, -5)
sepgp.extratip:AddDoubleLine("|cff9664c8shootyepgp|r",textRight)
--sepgp.extratip:SetPoint("TOPRIGHT", tooltip, "BOTTOMRIGHT", 0, -5)
sepgp.extratip:SetText("|cff9664c8shootyepgp|r")
sepgp.extratip:AddLine(textRight)
if (is_master) then
sepgp.extratip:AddDoubleLine(left1,right1)
end
@@ -275,7 +304,7 @@ function sepgp:SetItemRef(link, name, button)
else
bid = nil
end
if not sepgp:inRaid(masterlooter) then
if not self:inRaid(masterlooter) then
masterlooter = nil
end
if (bid and masterlooter) then
@@ -288,7 +317,7 @@ function sepgp:SetItemRef(link, name, button)
if (strsub(link, 1, 4) == "item") then
if (ItemRefTooltip:IsVisible()) then
if (not DressUpFrame:IsVisible()) then
sepgp:AddDataToTooltip(ItemRefTooltip, link)
self:AddDataToTooltip(ItemRefTooltip, link)
end
ItemRefTooltip.isDisplayDone = nil
end
@@ -297,8 +326,9 @@ function sepgp:SetItemRef(link, name, button)
end
function sepgp:LootFrameItem_OnClick(button,data)
if not IsAltKeyDown() then return end
if not UnitInRaid("player") then return end
if not sepgp:lootMaster() then return end
if not self:lootMaster() then return end
local slot, quality
if data ~= nil then
slot,quality = data:GetID(), data.quality
@@ -311,24 +341,56 @@ function sepgp:LootFrameItem_OnClick(button,data)
end
end
if LootSlotIsItem(slot) and quality >= 3 then
if (IsAltKeyDown()) then
local itemLink = GetLootSlotLink(slot)
if (itemLink) then
if button == "LeftButton" then
self:widestAudience(string.format("Whisper + for %s (mainspec)",itemLink))
--SendChatMessage(string.format("Whisper + for %s (mainspec)",itemLink),"RAID")
elseif button == "RightButton" then
self:widestAudience(string.format("Whisper - for %s (offspec)",itemLink))
--SendChatMessage(string.format("Whisper - for %s (offspec)",itemLink),"RAID")
elseif button == "MiddleButton" then
self:widestAudience(string.format("Whisper + or - for %s",itemLink))
--SendChatMessage(string.format("Whisper + or - for %s",itemLink),"RAID")
end
local itemLink = GetLootSlotLink(slot)
if (itemLink) then
if button == "LeftButton" then
self:widestAudience(string.format("Whisper + for %s (mainspec)",itemLink))
elseif button == "RightButton" then
self:widestAudience(string.format("Whisper - for %s (offspec)",itemLink))
elseif button == "MiddleButton" then
self:widestAudience(string.format("Whisper + or - for %s",itemLink))
end
end
end
end
function sepgp:ContainerFrameItemButton_OnClick(button,ignoreModifiers)
if not IsAltKeyDown() then
return self.hooks["ContainerFrameItemButton_OnClick"](button,ignoreModifiers)
end
if not UnitInRaid("player") then
return self.hooks["ContainerFrameItemButton_OnClick"](button,ignoreModifiers)
end
if not self:lootMaster() then
return self.hooks["ContainerFrameItemButton_OnClick"](button,ignoreModifiers)
end
if not (this._hasExtraClicks) then
this:RegisterForClicks("LeftButtonUp","RightButtonUp","MiddleButtonUp")
this._hasExtraClicks = true
end
local bag,slot = this:GetParent():GetID(), this:GetID()
local itemLink = GetContainerItemLink(bag, slot)
if (itemLink) then
local link_found, _, itemColor, itemString, itemName = string.find(itemLink, "^(|c%x+)|H(.+)|h(%[.+%])")
if (link_found) then
local bind = self:itemBinding(itemString) or ""
if (bind == self.VARS.boe) then
if button == "LeftButton" then
self:widestAudience(string.format("Whisper + for %s (mainspec)",itemLink))
return
elseif button == "RightButton" then
self:widestAudience(string.format("Whisper - for %s (offspec)",itemLink))
return
elseif button == "MiddleButton" then
self:widestAudience(string.format("Whisper + or - for %s",itemLink))
return
end
end
end
end
return self.hooks["ContainerFrameItemButton_OnClick"](button,ignoreModifiers)
end
function sepgp:pfUI_UpdateLootFrame()
for slotid, pflootitem in pairs(pfUI.loot.slots) do
if not self:IsHooked(pflootitem,"OnClick") then
@@ -356,9 +418,9 @@ end
function sepgp:debugPrint(msg)
if (shooty_debugchat) then
shooty_debugchat:AddMessage(string.format(out,msg))
sepgp:flashFrame(shooty_debugchat)
self:flashFrame(shooty_debugchat)
else
sepgp:defaultPrint(msg)
self:defaultPrint(msg)
end
end
@@ -429,6 +491,45 @@ function sepgp:widestAudience(msg)
SendChatMessage(msg, channel)
end
function sepgp:addonMessage(message,channel,sender)
SendAddonMessage(self.VARS.prefix,message,channel,sender)
end
function sepgp:addonComms(prefix,message,channel,sender)
if not prefix == self.VARS.prefix then return end -- we don't care for messages from other addons
if sender == playerName then return end -- we don't care for messages from ourselves
if not self:verifyGuildMember(sender,true) then return end -- only accept messages from guild members
local who,what,amount
for name,epgp,change in string.gfind(message,"([^;]+);([^;]+);([^;]+)") do
who=name
what=epgp
amount=tonumber(change)
end
if (who) and (what) and (amount) then
local msg
if who == playerName then
if what == "EP" then
if amount < 0 then
msg = string.format("You have received a %d EP penalty.",amount)
else
msg = string.format("You have been awarded %d EP.",amount)
end
elseif what == "GP" then
msg = string.format("You have gained %d GP.",amount)
end
elseif who == "ALL" and what == "DECAY" then
msg = string.format("%s%% decay to EP and GP.",amount)
elseif who == "RAID" and what == "AWARD" then
msg = string.format("%d EP awarded to Raid.",amount)
end
if msg and msg~="" then
self:defaultPrint(msg)
local report = self:my_epgp()
self:defaultPrint(report)
end
end
end
---------------------
-- EPGP Operations
---------------------
@@ -455,7 +556,7 @@ function sepgp:init_notes_v3(guild_index,name,officernote)
return officernote
end
function sepgp:update_epgp_v3(ep,gp,guild_index,name,officernote)
function sepgp:update_epgp_v3(ep,gp,guild_index,name,officernote,special_action)
officernote = self:init_notes_v3(guild_index,name,officernote)
local newnote
if (ep) then
@@ -485,7 +586,7 @@ function sepgp:update_ep_v2(getname,ep)
for i = 1, GetNumGuildMembers(1) do
local name, _, _, _, class, _, note, officernote, _, _ = GetGuildRosterInfo(i)
if (name==getname) then
sepgp:init_notes_v2(i,note,officernote)
self:init_notes_v2(i,note,officernote)
GuildRosterSetPublicNote(i,ep)
end
end
@@ -504,7 +605,7 @@ function sepgp:update_gp_v2(getname,gp)
for i = 1, GetNumGuildMembers(1) do
local name, _, _, _, class, _, note, officernote, _, _ = GetGuildRosterInfo(i)
if (name==getname) then
sepgp:init_notes_v2(i,note,officernote)
self:init_notes_v2(i,note,officernote)
GuildRosterSetOfficerNote(i,gp,true)
end
end
@@ -571,22 +672,27 @@ end
function sepgp:award_raid_ep(ep) -- awards ep to raid members in zone
if GetNumRaidMembers()>0 then
sepgp:simpleSay(string.format("Giving %d ep to all raidmembers",ep))
self:addToLog(string.format("Giving %d ep to all raidmembers",ep))
for i = 1, GetNumRaidMembers(true) do
local name, rank, subgroup, level, class, fileName, zone, online, isDead = GetRaidRosterInfo(i)
sepgp:givename_ep(name,ep)
self:givename_ep(name,ep)
end
self:simpleSay(string.format("Giving %d ep to all raidmembers",ep))
self:addToLog(string.format("Giving %d ep to all raidmembers",ep))
local addonMsg = string.format("RAID;AWARD;%s",ep)
self:addonMessage(addonMsg,"RAID")
else UIErrorsFrame:AddMessage("You aren't in a raid dummy",1,0,0)end
end
function sepgp:award_reserve_ep(ep) -- awards ep to reserve list
if table.getn(sepgp.shooty_reserves) > 0 then
sepgp:simpleSay(string.format("Giving %d ep to active reserves",ep))
self:addToLog(string.format("Giving %d ep to active reserves",ep))
for i, name in ipairs(sepgp.shooty_reserves) do
sepgp:givename_ep(name,ep)
if table.getn(sepgp.reserves) > 0 then
for i, reserve in ipairs(sepgp.reserves) do
local name, class, rank, alt = unpack(reserve[i])
self:givename_ep(name,ep)
end
self:simpleSay(string.format("Giving %d ep to active reserves",ep))
self:addToLog(string.format("Giving %d ep to active reserves",ep))
local addonMsg = string.format("RESERVES;AWARD;%s",ep)
self:addonMessage(addonMsg,"GUILD")
sepgp.reserves = {}
reserves_blacklist = {}
end
@@ -594,25 +700,29 @@ end
function sepgp:givename_ep(getname,ep) -- awards ep to a single character
if not (admin()) then return end
sepgp:debugPrint(string.format("Giving %d ep to %s",ep,getname))
if ep < 0 then -- inform admins of penalties
local newep = ep + (self:get_ep_v3(getname) or 0) --DONE: update v3
self:update_ep_v3(getname,newep) --DONE: update v3
self:debugPrint(string.format("Giving %d ep to %s",ep,getname))
if ep < 0 then -- inform admins and victim of penalties
local msg = string.format("%s EP Penalty to %s.",ep,getname)
sepgp:adminSay(msg)
self:adminSay(msg)
self:addToLog(msg)
end
ep = ep + (sepgp:get_ep_v3(getname) or 0) --DONE: update v3
sepgp:update_ep_v3(getname,ep) --DONE: update v3
local addonMsg = string.format("%s;%s;%s",getname,"EP",ep)
self:addonMessage(addonMsg,"GUILD")
end
end
function sepgp:givename_gp(getname,gp) -- assigns gp to a single character
if not (admin()) then return end
sepgp:debugPrint(string.format("Giving %d gp to %s",gp,getname))
local oldgp = (sepgp:get_gp_v3(getname) or sepgp.VARS.basegp) --DONE: update v3
local oldgp = (self:get_gp_v3(getname) or sepgp.VARS.basegp) --DONE: update v3
local newgp = gp + oldgp
self:update_gp_v3(getname,newgp) --DONE: update v3
self:debugPrint(string.format("Giving %d gp to %s",gp,getname))
local msg = string.format("Awarding %d GP to %s. (Previous: %d, New: %d)",gp,getname,oldgp,math.max(sepgp.VARS.basegp,newgp))
sepgp:adminSay(msg)
self:adminSay(msg)
self:addToLog(msg)
sepgp:update_gp_v3(getname,newgp) --DONE: update v3
local addonMsg = string.format("%s;%s;%s",getname,"GP",gp)
self:addonMessage(addonMsg,"GUILD")
end
function sepgp:decay_epgp_v2() -- decays entire roster's ep and gp
@@ -628,16 +738,16 @@ function sepgp:decay_epgp_v2() -- decays entire roster's ep and gp
self:debugPrint(msg)
self:adminSay(msg)
else
ep = math.max(0,sepgp:num_round(ep*sepgp_decay))
ep = math.max(0,self:num_round(ep*sepgp_decay))
GuildRosterSetPublicNote(i,ep)
gp = math.max(sepgp.VARS.basegp,sepgp:num_round(gp*sepgp_decay))
gp = math.max(sepgp.VARS.basegp,self:num_round(gp*sepgp_decay))
GuildRosterSetOfficerNote(i,gp,true)
end
end
end
local msg = string.format("All EP and GP decayed by %d%%",(1-sepgp_decay)*100)
sepgp:simpleSay(msg)
if not (sepgp_saychannel=="OFFICER") then sepgp:adminSay(msg) end
self:simpleSay(msg)
if not (sepgp_saychannel=="OFFICER") then self:adminSay(msg) end
self:addToLog(msg)
end
@@ -647,14 +757,16 @@ function sepgp:decay_epgp_v3()
local name,_,_,_,class,_,note,officernote,_,_ = GetGuildRosterInfo(i)
local ep,gp = self:get_ep_v3(name,officernote), self:get_gp_v3(name,officernote)
if (ep and gp) then
ep = sepgp:num_round(ep*sepgp_decay)
gp = sepgp:num_round(gp*sepgp_decay)
sepgp:update_epgp_v3(ep,gp,i,name,officernote)
ep = self:num_round(ep*sepgp_decay)
gp = self:num_round(gp*sepgp_decay)
self:update_epgp_v3(ep,gp,i,name,officernote)
end
end
local msg = string.format("All EP and GP decayed by %s%%",(1-sepgp_decay)*100)
sepgp:simpleSay(msg)
if not (sepgp_saychannel=="OFFICER") then sepgp:adminSay(msg) end
self:simpleSay(msg)
if not (sepgp_saychannel=="OFFICER") then self:adminSay(msg) end
local addonMsg = string.format("ALL;DECAY;%s",(1-(sepgp_decay or sepgp.VARS.decay))*100)
self:addonMessage(addonMsg,"GUILD")
self:addToLog(msg)
end
@@ -663,7 +775,7 @@ function sepgp:gp_reset_v2()
for i = 1, GetNumGuildMembers(1) do
GuildRosterSetOfficerNote(i, sepgp.VARS.basegp,true)
end
sepgp:debugPrint(string.format("All GP has been reset to %d.",sepgp.VARS.basegp))
self:debugPrint(string.format("All GP has been reset to %d.",sepgp.VARS.basegp))
self:adminSay(string.format("All GP has been reset to %d.",sepgp.VARS.basegp))
self:addToLog(string.format("All GP has been reset to %d.",sepgp.VARS.basegp))
end
@@ -675,16 +787,23 @@ function sepgp:gp_reset_v3()
local name,_,_,_,class,_,note,officernote,_,_ = GetGuildRosterInfo(i)
local ep,gp = self:get_ep_v3(name,officernote), self:get_gp_v3(name,officernote)
if (ep and gp) then
sepgp:update_epgp_v3(0,sepgp.VARS.basegp,i,name,officernote)
self:update_epgp_v3(0,sepgp.VARS.basegp,i,name,officernote)
end
end
local msg = "All EP and GP has been reset to 0/%d."
sepgp:debugPrint(string.format(msg,sepgp.VARS.basegp))
self:debugPrint(string.format(msg,sepgp.VARS.basegp))
self:adminSay(string.format(msg,sepgp.VARS.basegp))
self:addToLog(string.format(msg,sepgp.VARS.basegp))
end
end
function sepgp:my_epgp()
local ep,gp = (self:get_ep_v3(playerName) or 0), (self:get_gp_v3(playerName) or sepgp.VARS.basegp)
local pr = ep/gp
local msg = string.format("You now have: %d EP %d GP |cffffff00%.03f|r|cffff7f00PR|r.", ep,gp,pr)
return msg
end
---------
-- Menu
---------
@@ -698,7 +817,7 @@ sepgp.hasIcon = "Interface\\Icons\\INV_Misc_Orb_04"
function sepgp:OnTooltipUpdate()
local hint = "|cffffff00Click|r to toggle Standings.%s \n|cffffff00Right-Click|r for Options."
if (admin()) then
hint = string.format(hint," \n|cffffff00Ctrl+Click|r to toggle Reserves. \n|cffffff00Alt+Click|r to toggle Bids. \n|cffffff00Shift+Click|r to toggle Logs.")
hint = string.format(hint," \n|cffffff00Ctrl+Click|r to toggle Reserves. \n|cffffff00Alt+Click|r to toggle Bids. \n|cffffff00Shift+Click|r to toggle Loot. \n|cffffff00Ctrl+Shift+Click|r to toggle Logs.")
else
hint = string.format(hint,"")
end
@@ -712,6 +831,8 @@ function sepgp:OnClick()
elseif (IsAltKeyDown() and is_admin) then
sepgp_bids:Toggle()
elseif (IsShiftKeyDown() and is_admin) then
sepgp_loot:Toggle()
elseif (IsShiftKeyDown() and IsControlKeyDown() and is_admin) then
sepgp_logs:Toggle()
else
sepgp_standings:Toggle()
@@ -960,22 +1081,22 @@ function sepgp:reservesToggle(flag)
if (reservesChannelID) and reservesChannelID ~= 0 then
sepgp.reservesChannelID = reservesChannelID
if not self:IsEventRegistered("CHAT_MSG_CHANNEL") then
sepgp:RegisterEvent("CHAT_MSG_CHANNEL","captureReserveChatter")
self:RegisterEvent("CHAT_MSG_CHANNEL","captureReserveChatter")
end
return true
else
sepgp:RegisterEvent("CHAT_MSG_CHANNEL_NOTICE","reservesChannelChange")
self:RegisterEvent("CHAT_MSG_CHANNEL_NOTICE","reservesChannelChange")
JoinChannelByName(sepgp_reservechannel)
return
end
else -- we want out
if (reservesChannelID) and reservesChannelID ~= 0 then
sepgp:RegisterEvent("CHAT_MSG_CHANNEL_NOTICE","reservesChannelChange")
self:RegisterEvent("CHAT_MSG_CHANNEL_NOTICE","reservesChannelChange")
LeaveChannelByName(sepgp_reservechannel)
return
else
if sepgp:IsEventRegistered("CHAT_MSG_CHANNEL") then
sepgp:UnregisterEvent("CHAT_MSG_CHANNEL")
if self:IsEventRegistered("CHAT_MSG_CHANNEL") then
self:UnregisterEvent("CHAT_MSG_CHANNEL")
end
return false
end
@@ -987,14 +1108,14 @@ function sepgp:reservesChannelChange(msg,_,_,_,_,_,_,_,channel)
if msg == "YOU_JOINED" then
sepgp.reservesChannelID = tonumber((GetChannelName(sepgp_reservechannel)))
RemoveChatWindowChannel(DEFAULT_CHAT_FRAME:GetID(), sepgp_reservechannel)
sepgp:RegisterEvent("CHAT_MSG_CHANNEL","captureReserveChatter")
self:RegisterEvent("CHAT_MSG_CHANNEL","captureReserveChatter")
elseif msg == "YOU_LEFT" then
sepgp.reservesChannelID = nil
if sepgp:IsEventRegistered("CHAT_MSG_CHANNEL") then
sepgp:UnregisterEvent("CHAT_MSG_CHANNEL")
if self:IsEventRegistered("CHAT_MSG_CHANNEL") then
self:UnregisterEvent("CHAT_MSG_CHANNEL")
end
end
sepgp:UnregisterEvent("CHAT_MSG_CHANNEL_NOTICE")
self:UnregisterEvent("CHAT_MSG_CHANNEL_NOTICE")
D:Close()
end
end
@@ -1031,15 +1152,15 @@ function sepgp:captureReserveChatter(text, sender, _, _, _, _, _, _, channel)
if (r) and (running_check) then
if (rdy) then
if (name) and (name ~= "") then
if (not sepgp:inRaid(name)) then
reserve, reserve_class, reserve_rank = sepgp:verifyGuildMember(name)
if (not self:inRaid(name)) then
reserve, reserve_class, reserve_rank = self:verifyGuildMember(name)
if reserve ~= sender then
reserve_alt = sender
end
end
else
if (not sepgp:inRaid(sender)) then
reserve, reserve_class, reserve_rank = sepgp:verifyGuildMember(sender)
if (not self:inRaid(sender)) then
reserve, reserve_class, reserve_rank = self:verifyGuildMember(sender)
end
end
if reserve and reserve_class and reserve_rank then
@@ -1048,14 +1169,14 @@ function sepgp:captureReserveChatter(text, sender, _, _, _, _, _, _, channel)
reserves_blacklist[reserve_alt] = true
table.insert(sepgp.reserves,{reserve,reserve_class,reserve_rank,reserve_alt})
else
sepgp:defaultPrint(string.format("|cffff0000%s|r trying to add %s to Reserves, but has already added a member. Discarding!",reserve_alt,reserve))
self:defaultPrint(string.format("|cffff0000%s|r trying to add %s to Reserves, but has already added a member. Discarding!",reserve_alt,reserve))
end
else
if not reserves_blacklist[reserve] then
reserves_blacklist[reserve] = true
table.insert(sepgp.reserves,{reserve,reserve_class,reserve_rank})
else
sepgp:defaultPrint(string.format("|cffff0000%s|r has already been added to Reserves. Discarding!",reserve))
self:defaultPrint(string.format("|cffff0000%s|r has already been added to Reserves. Discarding!",reserve))
end
end
end
@@ -1064,7 +1185,7 @@ function sepgp:captureReserveChatter(text, sender, _, _, _, _, _, _, channel)
end
local q = string.find(text,"^{shootyepgp}Type")
if (q) and not (running_check) then
if (not UnitInRaid("player")) or (not sepgp:inRaid(sender)) then
if (not UnitInRaid("player")) or (not self:inRaid(sender)) then
StaticPopup_Show("SHOOTY_EPGP_RESERVE_AFKCHECK_RESPONCE")
end
end
@@ -1133,7 +1254,7 @@ function sepgp:captureLootCall(text, sender)
self:debugPrint("Capturing Bids for 5min.")
sepgp_bids:Toggle(true)
end
sepgp:bidPrint(itemLink,sender,mskw_found,oskw_found,whisperkw_found)
self:bidPrint(itemLink,sender,mskw_found,oskw_found,whisperkw_found)
end
end
end
@@ -1182,7 +1303,7 @@ end
function sepgp:clearBids(reset)
if reset~=nil then
sepgp:debugPrint("Clearing old Bids")
self:debugPrint("Clearing old Bids")
end
sepgp.bid_item = {}
sepgp.bids_main = {}
@@ -1196,10 +1317,150 @@ function sepgp:clearBids(reset)
sepgp_bids:Refresh()
end
----------------
-- Loot Tracker
----------------
-- test: "You receive loot: \124cffa335ee\124Hitem:16866:0:0:0\124h[Helm of Might]\124h\124r."
-- test: "Raerlas receives loot: \124cffa335ee\124Hitem:16846:0:0:0\124h[Giantstalker's Helmet]\124h\124r."
sepgp.loot_index = {
time=1,
player=2,
player_c=3,
item=4,
bind=5,
price=6,
off_price=7,
action=8,
update=9
}
function sepgp:captureLoot(message)
if not (UnitInRaid("player") and self:lootMaster()) then return end
local who,what,amount,player,itemLink
who,what,amount = DF:Deformat(message,LOOT_ITEM_MULTIPLE)
if (amount) then -- skip multiples / stacks
else
player, itemLink = DF:Deformat(message,LOOT_ITEM)
end
who,what,amount = YOU, DF:Deformat(message,LOOT_ITEM_SELF_MULTIPLE)
if (amount) then -- skip multiples / stacks
else
if not (player and itemLink) then
player, itemLink = YOU, DF:Deformat(message,LOOT_ITEM_SELF)
end
end
if not (player and itemLink) then return end
local link_found, _, itemColor, itemString, itemName = string.find(itemLink, "^(|c%x+)|H(.+)|h(%[.+%])")
if player and itemLink and link_found then
local bind = self:itemBinding(itemString)
if not (bind) then return end
local price = sepgp_prices:GetPrice(itemString,sepgp_progress)
if not (price) or price == 0 then
return
end
local class,_
if player == YOU then
class = UnitClass("player") -- localized
else
_, class = self:verifyGuildMember(player,true) -- localized
end
if not (class) then return end
local player_color = C:Colorize(BC:GetHexColor(class),player)
local off_price = math.floor(price*sepgp_discount)
local quality = hexColorQuality[itemColor] or -1
local timestamp = date("%b/%d %H:%M:%S")
local data = {[self.loot_index.time]=timestamp,[self.loot_index.player]=player,[self.loot_index.player_c]=player_color,[self.loot_index.item]=itemLink,[self.loot_index.bind]=bind,[self.loot_index.price]=price,[self.loot_index.off_price]=off_price}
local dialog = StaticPopup_Show("SHOOTY_EPGP_AUTO_GEARPOINTS",data[self.loot_index.player_c],data[self.loot_index.item],data)
if (dialog) then
dialog.data = data
end
end
end
function sepgp:findLootReminder(itemLink)
for i,data in ipairs(sepgp_looted) do
if data[self.loot_index.item] == itemLink --[[and data[self.loot_index.action] == self.VARS.reminder]] then
return data
end
end
end
function sepgp:tradeLoot(playerState,targetState)
if not (UnitInRaid("player") and self:lootMaster()) then return end
if (playerState ~= nil and targetState ~= nil) and playerState == 1 and targetState == 1 then
local itemLink
for id=1,MAX_TRADABLE_ITEMS do
itemLink = GetTradePlayerItemLink(id)
if (itemLink) then
break
end
end
if (itemLink) then
local link_found, _, itemColor, itemString, itemName = string.find(itemLink, "^(|c%x+)|H(.+)|h(%[.+%])")
if (link_found) then
local price = sepgp_prices:GetPrice(itemString,sepgp_progress)
if not (price) or price == 0 then
return
end
local bind = self:itemBinding(itemString)
if (not bind) or (bind ~= self.VARS.boe) then return end
if UnitExists("target") and UnitIsPlayer("target") and UnitCanCooperate("target") and (not UnitIsUnit("player","target")) then
local tradeTarget = UnitName("target")
local _, class = self:verifyGuildMember(tradeTarget,true)
if not (class) then return end
local target_color = C:Colorize(BC:GetHexColor(class),tradeTarget)
local timestamp = date("%b/%d %H:%M:%S")
local data = self:findLootReminder(itemLink) -- verify that it updates the data in the referenced table and not creating a copy
if (data) then
data[self.loot_index.time] = timestamp
data[self.loot_index.player] = tradeTarget
data[self.loot_index.player_c] = target_color
data[self.loot_index.update] = 1
local dialog = StaticPopup_Show("SHOOTY_EPGP_AUTO_GEARPOINTS",data[self.loot_index.player_c],data[self.loot_index.item],data)
if (dialog) then
dialog.data = data
end
end
end
end
end
end
end
sepgp.item_bind_patterns = {
CRAFT = "("..ITEM_SPELL_TRIGGER_ONUSE..")",
BOP = "("..ITEM_BIND_ON_PICKUP..")",
QUEST = "("..ITEM_BIND_QUEST..")",
BOU = "("..ITEM_BIND_ON_EQUIP..")",
BOE = "("..ITEM_BIND_ON_USE..")"
}
function sepgp:itemBinding(item)
G:SetHyperlink(item)
if G:Find(self.item_bind_patterns.CRAFT,2,4,nil,true) then
else
if G:Find(self.item_bind_patterns.BOP,2,4,nil,true) then
return sepgp.VARS.bop
elseif G:Find(self.item_bind_patterns.QUEST,2,4,nil,true) then
return sepgp.VARS.bop
elseif G:Find(self.item_bind_patterns.BOE,2,4,nil,true) then
return sepgp.VARS.boe
elseif G:Find(self.item_bind_patterns.BOU,2,4,nil,true) then
return sepgp.VARS.boe
else
return sepgp.VARS.nobind
end
end
return
end
function sepgp:addOrUpdateLoot(data,update)
if not (update) then
table.insert(sepgp_looted,data)
end
end
------------
-- Logging
------------
function sepgp:addToLog(line,skipTime)
local over = table.getn(sepgp_log)-sepgp.VARS.maxloglines+1
if over > 0 then
@@ -1223,15 +1484,15 @@ function sepgp:num_round(i)
return math.floor(i+0.5)
end
function sepgp:verifyGuildMember(name)
function sepgp:verifyGuildMember(name,silent)
for i=1,GetNumGuildMembers(1) do
local g_name, g_rank, g_rankIndex, g_level, g_class, g_zone, g_note, g_officernote, g_online = GetGuildRosterInfo(i)
if (string.lower(name) == string.lower(g_name)) and (tonumber(g_level) == MAX_PLAYER_LEVEL) then
return g_name, g_class, g_rank
end
end
if (name) and name ~= "" then
sepgp:defaultPrint(string.format("%s not found in the guild or not max level!",name))
if (name) and name ~= "" and not (silent) then
self:defaultPrint(string.format("%s not found in the guild or not max level!",name))
end
return
end
@@ -1304,6 +1565,7 @@ end
-------------
-- Dialogs
-------------
StaticPopupDialogs["SHOOTY_EPGP_SET_MAIN"] = {
text = "Set your main to be able to participate in Reserve List EPGP Checks.",
button1 = TEXT(ACCEPT),
@@ -1362,4 +1624,92 @@ StaticPopupDialogs["SHOOTY_EPGP_CONFIRM_RESET"] = {
exclusive = 1,
showAlert = 1,
hideOnEscape = 1
};
}
local sepgp_auto_gp_menu = {
--{text = "Choose an Action", isTitle = true},
{text = "Add MainSpec GP", func = function()
local dialog = StaticPopup_FindVisible("SHOOTY_EPGP_AUTO_GEARPOINTS")
if (dialog) then
local data = dialog.data
local player, price = data[sepgp.loot_index.player], data[sepgp.loot_index.price]
sepgp:givename_gp((player==YOU and playerName or player),price)
data[sepgp.loot_index.action] = sepgp.VARS.msgp
local update = data[sepgp.loot_index.update] ~= nil
sepgp:addOrUpdateLoot(data,update)
StaticPopup_Hide("SHOOTY_EPGP_AUTO_GEARPOINTS")
sepgp_loot:Refresh()
end
end},
{text = "Add OffSpec GP", func = function()
local dialog = StaticPopup_FindVisible("SHOOTY_EPGP_AUTO_GEARPOINTS")
if (dialog) then
local data = dialog.data
local player, off_price = data[sepgp.loot_index.player], data[sepgp.loot_index.off_price]
sepgp:givename_gp((player==YOU and playerName or player),off_price)
data[sepgp.loot_index.action] = sepgp.VARS.osgp
local update = data[sepgp.loot_index.update] ~= nil
sepgp:addOrUpdateLoot(data,update)
StaticPopup_Hide("SHOOTY_EPGP_AUTO_GEARPOINTS")
sepgp_loot:Refresh()
end
end},
{text = "Bank or D/E", func = function()
local dialog = StaticPopup_FindVisible("SHOOTY_EPGP_AUTO_GEARPOINTS")
if (dialog) then
local data = dialog.data
data[sepgp.loot_index.action] = sepgp.VARS.bankde
local update = data[sepgp.loot_index.update] ~= nil
sepgp:addOrUpdateLoot(data,update)
StaticPopup_Hide("SHOOTY_EPGP_AUTO_GEARPOINTS")
sepgp_loot:Refresh()
end
end}
}
StaticPopupDialogs["SHOOTY_EPGP_AUTO_GEARPOINTS"] = {
text = "%s looted %s. What do you want to do?",
button1 = "GP Actions",
button2 = "Remind me Later",
OnAccept = function()
sepgp:EasyMenu(sepgp_auto_gp_menu, this:GetParent().menuFrame, this, 0, 0, "MENU")
return true
end,
OnCancel = function(data,reason)
if reason == "override" or reason == "clicked" then
data[sepgp.loot_index.action] = sepgp.VARS.reminder
local update = data[sepgp.loot_index.update] ~= nil
sepgp:addOrUpdateLoot(data,update)
sepgp_loot:Refresh()
return
elseif reason == "timeout" then
return
end
end,
OnShow = function()
this.menuFrame = this.menuFrame or CreateFrame("Frame", "sepgp_auto_gp_menuframe", UIParent, "UIDropDownMenuTemplate")
end,
OnHide = function()
CloseDropDownMenus()
end,
timeout = 0,
exclusive = 1,
whileDead = 0,
hideOnEscape = 1
}
function sepgp:EasyMenu(menuList, menuFrame, anchor, x, y, displayMode)
if ( displayMode == "MENU" ) then
menuFrame.displayMode = displayMode
end
UIDropDownMenu_Initialize(menuFrame, function() sepgp:EasyMenu_Initialize(level, menuList) end, displayMode, nil, menuList)
ToggleDropDownMenu(1, nil, menuFrame, anchor, x, y, menuList)
end
function sepgp:EasyMenu_Initialize(level, menuList)
for index = 1, table.getn( menuList ) do
value = menuList[index]
if (value.text) then
value.index = index;
UIDropDownMenu_AddButton( value, level );
end
end
end
+10 -7
View File
@@ -2,11 +2,11 @@
## Title: shootyepgp
## Notes: Effort Points/Gear Points Loot System
## Author: Roadblock
## X-Credits: shooty for original version
## Version: 3.16
## X-Credits: shooty
## Version: 3.17
## OptionalDeps: Ace2
## SavedVariables: sepgp_saychannel,sepgp_groupbyclass,sepgp_raidonly,sepgp_decay,sepgp_reservechannel,sepgp_main,sepgp_progress,sepgp_discount
## SavedVariablesPerCharacter: sepgp_log, sepgp_dbver
## SavedVariablesPerCharacter: sepgp_log, sepgp_dbver, sepgp_looted
Libs\AceLibrary\AceLibrary.lua
Libs\AceOO-2.0\AceOO-2.0.lua
@@ -19,18 +19,21 @@ Libs\AceDB-2.0\AceDB-2.0.lua
Libs\AceDebug-2.0\AceDebug-2.0.lua
Libs\AceLocale-2.2\AceLocale-2.2.lua
Libs\Deformat-2.0\Deformat-2.0.lua
Libs\Babble-Class-2.2\Babble-Class-2.2.lua
Libs\Babble-Zone-2.2\Babble-Zone-2.2.lua
Libs\Crayon-2.0\Crayon-2.0.lua
Libs\Compost-2.0\Compost-2.0.lua
Libs\Dewdrop-2.0\Dewdrop-2.0.lua
Libs\FuBarPlugin-2.0\FuBarPlugin-2.0.lua
Libs\Tablet-2.0\Tablet-2.0.lua
Libs\Gratuity-2.0\Gratuity-2.0.lua
Libs\FuBarPlugin-2.0\FuBarPlugin-2.0.lua
shootyepgp.lua
migrations.lua
standings.lua
reserves.lua
bids.lua
prices.lua
standings.lua
bids.lua
loot.lua
reserves.lua
logs.lua
+1 -1
View File
@@ -124,7 +124,7 @@ end
function sepgp_standings:setHideScript()
local detachedFrame, tablet
for i=1,4 do
for i=1,5 do
tablet = getglobal(string.format("Tablet20DetachedFrame%d",i))
if tablet and tablet.owner ~= nil and tablet.owner == "sepgp_standings" then
if not (tablet:GetScript("OnHide")) then