2011-05-30 14:21:33 -04:00
|
|
|
local core = LibStub("AceAddon-3.0"):GetAddon("AllTheLittleThings")
|
2011-09-03 16:17:41 -04:00
|
|
|
local mod = core:NewModule("PotionMail", "AceEvent-3.0", "AceTimer-3.0", "AceHook-3.0")
|
2011-05-30 18:13:08 -04:00
|
|
|
local db
|
2011-05-30 14:21:33 -04:00
|
|
|
|
|
|
|
local defaults = {
|
2011-09-03 16:17:41 -04:00
|
|
|
mailQueue = {}, -- used to store potion information per character
|
2011-05-30 14:21:33 -04:00
|
|
|
}
|
|
|
|
local options = {
|
|
|
|
}
|
|
|
|
|
|
|
|
local potList = {
|
|
|
|
["a"] = 58146, -- Golemblood
|
|
|
|
["b"] = 58145, -- Tol'vir
|
|
|
|
["c"] = 58090, -- Earthen
|
|
|
|
["d"] = 58091, -- Volcanic
|
|
|
|
["e"] = 57194, -- Concentration
|
|
|
|
["f"] = 57192, -- Mythical
|
|
|
|
}
|
2011-07-03 03:12:00 -04:00
|
|
|
local guildColors = {} -- for printing names in color
|
2011-09-03 16:17:41 -04:00
|
|
|
local currentSender -- the current person you are sending to
|
2011-05-30 14:21:33 -04:00
|
|
|
|
|
|
|
function mod:OnInitialize()
|
2011-09-03 16:17:41 -04:00
|
|
|
self:RegisterOptions(options, defaults, function(d) db=d end)
|
2011-05-30 18:13:08 -04:00
|
|
|
self:RegisterSlashCommand("AddPotions", "pots")
|
2011-07-03 03:12:00 -04:00
|
|
|
self:RegisterSlashCommand("PrintPotions", "pp")
|
2011-09-03 16:17:41 -04:00
|
|
|
self:RegisterSlashCommand("ClearPotions", "cp")
|
2011-05-30 14:21:33 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
function mod:OnEnable()
|
2011-09-03 16:17:41 -04:00
|
|
|
-- We use MAIL_SUCCESS instead of MAIL_SEND_SUCCESS because the latter fires on ClearSendMail() which we call
|
|
|
|
self:RegisterEvent("MAIL_SUCCESS", "MailQueueCheck");
|
2011-05-30 14:38:32 -04:00
|
|
|
self:RegisterEvent("MAIL_SHOW", "MailQueueCheck");
|
2011-09-03 16:17:41 -04:00
|
|
|
self:RegisterEvent("MAIL_CLOSED", function() currentSender = nil end); -- clear the sender
|
|
|
|
self:Hook("SendMail", true)
|
|
|
|
|
|
|
|
self:CacheGuild()
|
2011-05-30 14:21:33 -04:00
|
|
|
end
|
|
|
|
|
2011-09-03 16:17:41 -04:00
|
|
|
function mod:CacheGuild()
|
2011-05-30 14:21:33 -04:00
|
|
|
-- get all guild members
|
|
|
|
for i=1,GetNumGuildMembers() do
|
|
|
|
local name, rank = GetGuildRosterInfo(i)
|
|
|
|
name = name:lower()
|
|
|
|
if rank == "Member" or rank == "Officer" or rank == "Guild Master" then
|
2011-09-03 16:17:41 -04:00
|
|
|
guildColors[name] = RAID_CLASS_COLORS[select(11, GetGuildRosterInfo(i))]
|
|
|
|
if db.mailQueue[name] == nil then
|
|
|
|
db.mailQueue[name] = {}
|
2011-05-30 14:21:33 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2011-09-03 16:17:41 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
function mod:AddPotions(msg)
|
|
|
|
-- Call again in case we removed some during potion distribution and added later
|
|
|
|
self:CacheGuild()
|
|
|
|
|
2011-05-30 14:21:33 -04:00
|
|
|
-- parse
|
|
|
|
msg:gsub("([^%d%s]+)(%d+)(%w)", function(name, ct, type)
|
|
|
|
local typeRef = potList[type]
|
|
|
|
name = name:lower()
|
|
|
|
ct = tonumber(ct)
|
|
|
|
if typeRef and ct then
|
2011-09-03 16:17:41 -04:00
|
|
|
for i,_ in pairs(db.mailQueue) do
|
2011-05-30 14:21:33 -04:00
|
|
|
if i:match("^"..name) then
|
2011-09-03 16:17:41 -04:00
|
|
|
db.mailQueue[i][typeRef] = ct
|
2011-07-03 03:12:00 -04:00
|
|
|
-- print(format("Queued %dx %s for %s", ct, self:Link(typeRef), i))
|
2011-05-30 14:21:33 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
end
|
|
|
|
|
|
|
|
--[[ Things to do here still:
|
|
|
|
- consumables.php: group names together in slash args
|
|
|
|
- consumables.php: split slash by pots?
|
|
|
|
- if we don't have mats for this player, move to end of queue
|
|
|
|
- use a flag of sorts to keep track of who was moved and who was not; reset flags on... mailbox close? this way we don't keep going through the queue over and over at the end
|
|
|
|
- change data structure to numerical array (so we can move to the end)
|
|
|
|
- change subject line to include amount
|
|
|
|
- the lowercase first letter bugs me
|
|
|
|
- do check when parsing slash command to make sure there are no ambiguous targets (Eternal/Eternity)
|
|
|
|
- compress slash command more:
|
|
|
|
limit to first 4 letters (chir40d, chir->chira)? 3 may be possible but has higher collisions
|
|
|
|
allow for chaining (chira40d2e6f - 40d, 2e, 6f)?
|
|
|
|
include length of name after characters *in hex* (chi540d - "chira" has length of 5)
|
|
|
|
- re-consolidate stacks at the end of the queue
|
|
|
|
- add a command to display how much left of each is needed vs how much you have
|
|
|
|
]]
|
|
|
|
local mailQueueTimer
|
2011-09-03 16:17:41 -04:00
|
|
|
function mod:MailQueueCheck(caller)
|
|
|
|
-- First do some preliminary checks
|
2011-05-30 14:21:33 -04:00
|
|
|
if caller == "MAIL_SUCCESS" then
|
|
|
|
-- MAIL_SUCCESS fires on open too, so going to make sure we're looking at a Send Mail screen
|
|
|
|
if MailFrame.selectedTab ~= 2 then
|
|
|
|
return
|
|
|
|
end
|
2011-09-03 16:17:41 -04:00
|
|
|
|
|
|
|
-- if we have a currentSender, remove them from the queue
|
|
|
|
if currentSender then
|
|
|
|
db.mailQueue[currentSender] = nil
|
|
|
|
end
|
2011-05-30 14:21:33 -04:00
|
|
|
end
|
2011-09-03 16:17:41 -04:00
|
|
|
|
|
|
|
-- Get our potion
|
|
|
|
local name,data = next(db.mailQueue)
|
|
|
|
if not data then
|
|
|
|
return -- no need to process queue
|
|
|
|
end
|
|
|
|
|
|
|
|
-- check to make sure there are more than 0 left
|
|
|
|
local done = true
|
|
|
|
for _,n in pairs(data) do
|
|
|
|
if n > 0 then
|
|
|
|
done = false
|
|
|
|
break
|
|
|
|
end
|
|
|
|
end
|
|
|
|
-- if there are none left, delete and re-call
|
|
|
|
if done then
|
|
|
|
db.mailQueue[name] = nil
|
|
|
|
self:MailQueueCheck(caller)
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
local delay = 0.5
|
2011-05-30 14:21:33 -04:00
|
|
|
if mailQueueTimer then
|
|
|
|
self:CancelTimer(mailQueueTimer, true)
|
|
|
|
end
|
|
|
|
-- slight pause to allow for items to disappear
|
|
|
|
mailQueueTimer = self:ScheduleTimer(function()
|
|
|
|
do
|
2011-07-03 03:12:00 -04:00
|
|
|
-- self:Print(caller)
|
2011-05-30 14:21:33 -04:00
|
|
|
-- return
|
|
|
|
end
|
|
|
|
|
|
|
|
-- find all slots for splitting onto
|
|
|
|
local emptySlots = {}
|
|
|
|
for bag=0,NUM_BAG_SLOTS do
|
|
|
|
local free = GetContainerFreeSlots(bag)
|
|
|
|
for _,slot in ipairs(free) do
|
|
|
|
table.insert(emptySlots, bag*100+slot)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
-- need to keep track of what to push to Send Mail window when the item lock clears
|
|
|
|
local pushQueue = {}
|
|
|
|
local checkItemLock = function(_, bagID, slotID)
|
|
|
|
local globalID = bagID*100+slotID
|
2011-07-03 03:12:00 -04:00
|
|
|
-- self:Print("ITEM_LOCK_CHANGED fired", globalID)
|
2011-05-30 14:21:33 -04:00
|
|
|
if pushQueue[globalID] then
|
|
|
|
local _, _, locked = GetContainerItemInfo(bagID, slotID)
|
|
|
|
if not locked then
|
|
|
|
PickupContainerItem(bagID, slotID)
|
|
|
|
ClickSendMailItemButton()
|
|
|
|
pushQueue[globalID] = nil
|
|
|
|
|
|
|
|
-- if our queue is empty
|
|
|
|
if not next(pushQueue) then
|
|
|
|
self:UnregisterEvent("ITEM_LOCK_CHANGED")
|
2011-07-03 03:12:00 -04:00
|
|
|
-- self:Print("Unregistering ITEM_LOCK_CHANGED")
|
2011-05-30 14:21:33 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
local initializeQueue = function()
|
|
|
|
self:RegisterEvent("ITEM_LOCK_CHANGED", checkItemLock)
|
2011-07-03 03:12:00 -04:00
|
|
|
-- self:Print("Registering ITEM_LOCK_CHANGED")
|
2011-05-30 14:21:33 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
-- swap tabs if we need to
|
|
|
|
if MailFrame.selectedTab ~= 2 then
|
|
|
|
MailFrameTab_OnClick(MailFrame, 2)
|
|
|
|
end
|
|
|
|
ClearSendMail()
|
|
|
|
|
|
|
|
-- set name
|
|
|
|
SendMailNameEditBox:SetText(name)
|
|
|
|
|
|
|
|
-- fill out shit
|
|
|
|
for item,ct in pairs(data) do
|
2011-07-03 03:12:00 -04:00
|
|
|
-- print("--------- NEXT ITEM:", item)
|
2011-05-30 14:21:33 -04:00
|
|
|
if ct > 0 then
|
|
|
|
local inv = GetItemCount(item)
|
2011-07-03 03:12:00 -04:00
|
|
|
-- print("Checking item count:", inv, ct, inv<ct)
|
2011-05-30 14:21:33 -04:00
|
|
|
if inv < ct then
|
|
|
|
-- we don't have enough. abort.
|
2011-07-03 03:12:00 -04:00
|
|
|
self:Print(format("We don't have enough %s for %s. Needed %d; have %d.", self:Link(item), name, ct, inv))
|
2011-05-30 14:21:33 -04:00
|
|
|
ClearSendMail()
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
-- find container slot with item
|
|
|
|
for bag=0,NUM_BAG_SLOTS do
|
|
|
|
-- check if we're done
|
|
|
|
if ct > 0 then
|
|
|
|
for slot=1,GetContainerNumSlots(bag) do
|
|
|
|
-- make sure the item we want is this slot
|
|
|
|
if GetContainerItemID(bag, slot) == item then
|
|
|
|
local _, slotCt, locked = GetContainerItemInfo(bag, slot)
|
2011-07-03 03:12:00 -04:00
|
|
|
-- print("LOOP", GetItemInfo("item:"..item), slotCt, "/", ct, locked)
|
2011-05-30 14:21:33 -04:00
|
|
|
if locked then
|
|
|
|
-- the item is locked for whatever reason. abort?
|
2011-09-03 16:17:41 -04:00
|
|
|
self:Print(format("%s in bag %d, slot %d is locked.", self:Link(item), bag, slot))
|
2011-05-30 14:21:33 -04:00
|
|
|
return
|
|
|
|
else
|
|
|
|
-- if item too many; find empty spot to dump extras
|
|
|
|
if slotCt > ct then
|
|
|
|
-- check to make sure we can split
|
|
|
|
if #emptySlots == 0 then
|
2011-07-03 03:12:00 -04:00
|
|
|
-- print("Not enough bag space to split. Aborting.")
|
2011-05-30 14:21:33 -04:00
|
|
|
ClearSendMail()
|
2011-05-30 18:13:08 -04:00
|
|
|
mod:CancelAllTimers()
|
2011-05-30 14:21:33 -04:00
|
|
|
return
|
|
|
|
end
|
|
|
|
-- pop empty slot off the list
|
|
|
|
local extraSpace = table.remove(emptySlots)
|
|
|
|
local extraBag, extraSlot = floor(extraSpace/100), extraSpace % 100
|
|
|
|
-- split and place
|
2011-07-03 03:12:00 -04:00
|
|
|
-- print("splitting", bag, slot, slotCt-ct)
|
2011-05-30 14:21:33 -04:00
|
|
|
SplitContainerItem(bag, slot, slotCt-ct)
|
2011-07-03 03:12:00 -04:00
|
|
|
-- print("extras at", extraBag, extraSlot)
|
2011-05-30 14:21:33 -04:00
|
|
|
PickupContainerItem(extraBag, extraSlot) -- place
|
|
|
|
|
|
|
|
-- check when lock is clear
|
|
|
|
if not next(pushQueue) then
|
|
|
|
initializeQueue()
|
|
|
|
end
|
|
|
|
pushQueue[bag*100+slot] = true -- register source as push target
|
|
|
|
ct = 0
|
|
|
|
break
|
|
|
|
else
|
|
|
|
-- item should have enough
|
2011-07-03 03:12:00 -04:00
|
|
|
-- print("adding to mail", bag, slot, ct, slotCt, ct-slotCt)
|
2011-05-30 14:21:33 -04:00
|
|
|
PickupContainerItem(bag, slot)
|
|
|
|
ClickSendMailItemButton()
|
|
|
|
ct = ct - slotCt
|
2011-07-03 03:12:00 -04:00
|
|
|
-- print("and after", ct)
|
2011-05-30 14:21:33 -04:00
|
|
|
if ct == 0 then
|
|
|
|
break
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
-- click send
|
2011-09-03 16:17:41 -04:00
|
|
|
currentSender = name
|
2011-05-30 14:21:33 -04:00
|
|
|
-- self:ScheduleTimer(function()
|
2011-09-03 16:17:41 -04:00
|
|
|
-- db.mailQueue[name] = nil
|
2011-05-30 14:21:33 -04:00
|
|
|
-- ClearSendMail()
|
|
|
|
-- self:MailQueueCheck()
|
|
|
|
-- end, 5)
|
|
|
|
|
|
|
|
mailQueueTimer = nil
|
|
|
|
end, delay)
|
|
|
|
end
|
|
|
|
|
2011-07-03 03:12:00 -04:00
|
|
|
function mod:PrintPotions()
|
2011-09-03 16:17:41 -04:00
|
|
|
local totals = {}
|
|
|
|
for name,details in pairs(db.mailQueue) do
|
2011-07-03 03:12:00 -04:00
|
|
|
print(("|cff%02x%02x%02x%s|r:"):format(guildColors[name].r*255, guildColors[name].g*255, guildColors[name].b*255, name:gsub("^(.)(.*)$", function(f, rest)
|
|
|
|
return string.upper(f) .. rest
|
|
|
|
end)))
|
|
|
|
for pot,n in pairs(details) do
|
|
|
|
print((" %s: %d"):format(self:Link(pot, true), n))
|
2011-09-03 16:17:41 -04:00
|
|
|
totals[pot] = (totals[pot] or 0) + n
|
2011-07-03 03:12:00 -04:00
|
|
|
end
|
|
|
|
end
|
2011-09-03 16:17:41 -04:00
|
|
|
|
|
|
|
if not next(totals) then
|
|
|
|
self:Print("Potion queue is empty")
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
-- print totals and what we have in bags
|
|
|
|
print("Total:")
|
|
|
|
for pot,n in pairs(totals) do
|
|
|
|
local have = GetItemCount(pot)
|
|
|
|
print((" %s: |cff%s%d / %d|r"):format(self:Link(pot, true), have >= n and "00ff00" or "ff0000", have, n))
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function mod:ClearPotions()
|
|
|
|
db.mailQueue = {}
|
2011-07-03 03:12:00 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
function mod:Link(id, icon)
|
|
|
|
icon = icon and ("|T%s:0|t"):format((select(10, GetItemInfo(id)))) or ""
|
|
|
|
return ("%s|Hitem:%d|h[%s]|h"):format(icon, id, (GetItemInfo(id)))
|
|
|
|
end
|
2011-09-03 16:17:41 -04:00
|
|
|
|
|
|
|
-- Double check when we try to send that we are sending to our auto-person,
|
|
|
|
-- otherwise it was not part of this addon and should not be removed from the
|
|
|
|
-- queue
|
|
|
|
function mod:SendMail(recipient)
|
|
|
|
if currentSender and recipient:lower() ~= currentSender:lower() then
|
|
|
|
currentSender = nil
|
|
|
|
end
|
|
|
|
end
|