vanilla-wow-addons – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 --[[ MailTo: Mailbox management system,
2 Written by Vincent of Blackhand, (copyright (c) 2005-2006 by D.A.Down)
3  
4 Version history:
5 1.10 - WoW 1.11 update.
6 1.9.7 - Added money counting to open mail window.
7 1.9.6 - Fixed mailbox close on walk-away bug.
8 1.9.5 - Updated French localization (from Assutourix).
9 1.9.4 - Fixed '/mtl' searches that included a '-'.
10 1.9.3 - Fixed problem with sendee name getting erased.
11 1.9.2 - Added 'coin' option for including g/s/c in money.
12 1.9.1 - Split received cash into sales and refunds
13 1.9 - Added recieved item/money logging option (per char).
14 1.8.8 - Added '/mtn' to check for newly delivered mail.
15 1.8.7 - Fixed duplicate money counting.
16 1.8.6 - Added configurable expiration times.
17 1.8.5 - Makes sure New Mail icon is hidden when empty.
18 1.8.4 - Added color-coded item count to Inbox menu names.
19 1.8.3 - Converted Inbox server menu to 2 levels.
20 1.8.2 - Added "(possible new mail)" expiration
21 1.8.1 - Fixed right-click on chat playername problem.
22 1.8 - WoW 1.10 update.
23 1.7.5 - Auction shift right-click now sells 1 from stack.
24 1.7.4 - Added remove character to inbox list.
25 1.7.3 - auto-add of new character to sendee list.
26 1.7.2 - Always selects the sendee name.
27 1.7.1 - Added shading to color-code inbox items.
28 1.7 - Added /mtn command to list new inbox items.
29 1.6.3 - Shift right-click on empty inv. does AH recipe search.
30 1.6.2 - Fixed chat click reference.
31 1.6.1 - Added link support to locate command.
32 1.6 - WoW 1.9 update.
33 1.5.1 - Added auction search for chat right-click.
34 1.5 - Added locate command for inbox and CV items.
35 1.4.4 - Added total cash received on mailboc close.
36 1.4.3 - Fix for dynamic auction loading in WoW 1.8
37 1.4.2 - Added check for missing log field.
38 1.4.1 - Fixed error on sender being deleted.
39 1.4 - Added right-click support for Trade window.
40 1.3.1 - Fixed notification bug for non-alt. sendee.
41 1.3 - Added 'From' and 'Expires' to MT inbox tooltip.
42 1.2.2 - Right-click fix, delivery updates empty inbox.
43 1.2.1 - WoW 1.7 update.
44 1.2 - Delivered alt. mail is added to MailTo inbox.
45 1.1.3 - Added server option to MailTo inbox.
46 1.1.2 - Added options to disable right-click features.
47 1.1.1 - Added server name to log entries.
48 1.1 - Added support for AIOI, enhanced auction right-click.
49 1.0.1 - Cleaned up inbox tooltip and right-click.
50 1.0 - Added mail Inbox summary window, key bindings.
51 0.8.8 - Added /mailfrom command, formatted money.
52 0.8.7 - RightClick on inbox item to retrieve or delete empty.
53 0.8.6 - Shift-RightClick on item sends to current sendee.
54 0.8.5 - Added options for button position and no 'ding'.
55 0.8.4 - Enhanced inbox tooltip of attachment or message.
56 0.8.3 - (1600), uses current chat window, auction right-click.
57 0.8.2 - Login expiration check, Chinese localizaion.
58 0.8.1 - French localization bug-fix.
59 0.8 - Inbox package expiration.
60 0.7 - Package tracking, limited MailMod support.
61 0.6 - French localization, send item right-click.
62 0.5.1 - German localization.
63 0.5 - Initial public release.
64 ]]
65  
66 -- Local
67 local FCr = "|cffff4040" -- Red
68 local FCy = "|cffffff10" -- Yellow
69 local FCo = "|cffff8040" -- Orange
70 local FCg = "|cff50c050" -- Green
71 local FCs = "|cffe0e0e0" -- silver
72 local FCw = "|cffffffff" -- White
73 local FCe = "|r" -- End
74 local TCr = {r=0.85, g=0.25, b=0.25}
75 local TCy = {r=0.85, g=0.85, b=0.25}
76 local TCg = {r=0.25, g=0.85, b=0.25}
77 local TCw = {r=1.00, g=1.00, b=1.00}
78 local MailTo_Selected, MailTo_Name, MailTo_SavedName
79 local Server,Player,Mail,Mail_server,Mail_name,Cash
80 local Startup,MailCount,Last_Click = true,false,0
81 local DELAY = 61*60 -- item delivery delay
82 local DAY = 24*60*60
83 local MAIL_DAYS = 30
84 local MAIL_EXP = MAIL_DAYS*DAY
85 local COD_EXP = 3*DAY
86 local defIcon = "Interface\\Icons\\INV_Misc_Note_01.blp"
87 local QmkIcon = "Interface\\Icons\\INV_Misc_QuestionMark"
88 local function EXP(code) return DAY*(MailTo_Option[code] or MAILTO_DAYS[code]) end
89 -- GetTime rollover ~ 4.5 days
90  
91 -- Global
92 MailTo_Sendee = {}
93 MailTo_Inbox = {}
94 MailTo_List = {}
95 MailTo_Mail = {}
96 MailTo_Log = {}
97 MailTo_Option = {}
98 MailTo_Time = 0
99  
100 local function print(msg)
101 SELECTED_CHAT_FRAME:AddMessage("MailTo: "..msg, 0.0, 0.9, 0.9)
102 end
103  
104 local function sorted_index(table)
105 local index = {}
106 for key in table do tinsert(index,key) end
107 sort(index)
108 return index
109 end
110  
111 -- Convert money to gold/silver/copper
112 local function add2d(str,fc,n,c)
113 if MailTo_Option.nocoin then c = ''
114 elseif n==0 and str~='' then return str end
115 if n==0 and not str then return end
116 if not str or str=='' then return fc..tostring(n)..c end
117 return format("%s%s%02d%s",str,fc,n,c)
118 end
119  
120 local function gsc(n)
121 local str = add2d(nil,FCy,floor(n/10000),'g')
122 str = add2d(str,FCs,mod(floor(n/100),100),'s')
123 str = add2d(str or '',FCo,mod(n,100),'c')
124 return str..FCe
125 end
126  
127 function MailTo_Init()
128 if(MailTo_Option.nologin) then Startup = false end
129 MailTo_Timer(8)
130 UIPanelWindows["MailTo_InFrame"] = {area="left", pushable=9}
131 -- add our chat command
132 SlashCmdList["MAILTO"] = MailTo_command
133 SLASH_MAILTO1 = "/mailto"
134 SLASH_MAILTO2 = "/mt"
135 SlashCmdList["MAILTOEX"] = MailTo_expire
136 SLASH_MAILTOEX1 = "/mtex"
137 SlashCmdList["MAILTOLOC"] = MailTo_locate
138 SLASH_MAILTOLOC1 = "/mtl"
139 SlashCmdList["MAILTONEW"] = MailTo_new
140 SLASH_MAILTONEW1 = "/mtn"
141 SlashCmdList["MAILFROM"] = MailFrom_command
142 SLASH_MAILFROM1 = "/mailfrom"
143 SLASH_MAILFROM2 = "/mf"
144 SlashCmdList["INBOX"] = MailTo_inbox
145 SLASH_INBOX1 = "/inbox"
146 Player = UnitName("player")
147 Server = GetCVar("realmName")
148 if(MailTo_Inbox[Server]) then
149 if(not MailTo_Inbox[Server][Player] and not MailTo_InList(Player)) then
150 MailTo_ListAdd(Player)
151 end
152 else MailTo_Inbox[Server]={} end
153 if(not MailTo_List[Server]) then MailTo_List[Server]={} end
154 if(not MailTo_Mail[Server]) then MailTo_Mail[Server]={} end
155 local ix = next(MailTo_Mail)
156 if(next(MailTo_Mail,ix)) then
157 MailTo_InFrameServerButton:Show()
158 MailTo_InFrameServerButton:SetChecked(MailTo_Option.server)
159 end
160 Mail = MailTo_Mail[Server]
161 MailTo_SavedName = MailTo_Sendee[Server]
162 MailTo_InFrame_DropDown.displayMode = "MENU"
163 MailToDropDownMenu.displayMode = "MENU"
164 -- hook inventory item use
165 MailTo_InvUse_Save = UseContainerItem
166 UseContainerItem = MailTo_InvUse
167 -- hook send mail name select
168 MailTo_SendName_Save = SendMailNameEditBox:GetScript('OnEditFocusGained')
169 SendMailNameEditBox:SetScript('OnEditFocusGained',MailTo_SendName)
170 -- hook send mail
171 MailTo_SendMail_Save = SendMailFrame_SendMail
172 SendMailFrame_SendMail = MailTo_SendMail
173 -- hook Inbox mouseover
174 MailTo_InboxItem_Save = InboxFrameItem_OnEnter
175 InboxFrameItem_OnEnter = MailTo_InboxItem
176 -- hook Inbox click
177 MailTo_InboxItem_OnClick_Save = InboxFrame_OnClick
178 InboxFrame_OnClick = MailTo_InboxItem_OnClick
179 -- hook Inbox money click
180 MailTo_InboxMoney_OnClick_Save = OpenMailMoneyButton:GetScript('OnClick')
181 OpenMailMoneyButton:SetScript('OnClick',MailTo_InboxMoney_OnClick)
182 -- hook Chat OnCLick
183 MailTo_ChatOnClick_Save = ChatFrame_OnHyperlinkShow
184 ChatFrame_OnHyperlinkShow = MailTo_ChatOnClick
185 -- hook MailMod
186 MailTo_MailMod_Save = MailFrameTab_OnClick
187 MailFrameTab_OnClick = MailTo_MailMod
188 -- Window position of MailTo button
189 if(GetLocale()=="frFR" or GetLocale()=='deDE' or MailTo_Option.pos) then
190 local pos = MailTo_Option.pos and MailTo_Option.pos or -12
191 MailToDropDownMenu:SetPoint("RIGHT","SendMailNameEditBox","RIGHT",pos,0)
192 end
193 end
194  
195 -- Add to tooltip if money is involved
196 local function tip_money(money)
197 if(money>0) then
198 GameTooltip:AddLine(ENCLOSED_MONEY)
199 SetTooltipMoney(GameTooltip,money)
200 elseif(money<0) then
201 GameTooltip:AddLine(COD_AMOUNT,1,0.3,0.3)
202 SetTooltipMoney(GameTooltip,-money)
203 end
204 end
205  
206 -- Handle Inbox mouseover
207 function MailTo_InboxItem()
208 MailTo_InboxItem_Save()
209 local item,icon,from,sub,money,cod,dl,hi,read = GetInboxHeaderInfo(this.index)
210 GameTooltip:SetOwner(this, "ANCHOR_RIGHT")
211 if(IsControlKeyDown() or read and not item) then
212 GameTooltip:SetText(sub)
213 local text = GetInboxText(this.index)
214 if(text) then GameTooltip:AddLine(text,1,1,1,1) end
215 local iType,item,buyer,bid,bo,dep,cut = GetInboxInvoiceInfo(this.index)
216 if(iType=='seller') then
217 GameTooltip:AddLine(format(MAILTO_SALE,buyer,item,gsc(bid),gsc(bid-cut)),1,1,1)
218 end
219 elseif(item) then
220 GameTooltip:SetInboxItem(this.index)
221 end
222 if(money>0) then tip_money(money)
223 elseif(cod>0) then tip_money(-cod) end
224 GameTooltip:Show()
225 end
226  
227 -- Handle Inbox click
228 local function Count_Cash(from,sub,money)
229 Cash.total = Cash.total+money
230 if strfind(sub,MAILTO_OUTBID) or strfind(sub,MAILTO_CANCEL) then
231 Cash.refund = Cash.refund+money
232 elseif strfind(sub,MAILTO_SOLD) then
233 Cash.sales = Cash.sales+money
234 else Cash.other = Cash.other+money end
235 print(format(MAILTO_RECEIVED,gsc(money),from,sub))
236 end
237  
238 function MailTo_InboxItem_OnClick(ix)
239 if(arg1=="RightButton") then
240 local item,icon,from,sub,money,cod,dl,hi,read = GetInboxHeaderInfo(ix)
241 if(not from) then from = '?'; end
242 local delete = InboxItemCanDelete(ix)
243 local single = not IsAltKeyDown()
244 local skip
245 if(money>0) then
246 GetInboxText(ix) -- force read to access invoice
247 CheckInbox()
248 if not read then Count_Cash(from,sub,money) end
249 local iType,item,buyer,bid,bo,dep,cut = GetInboxInvoiceInfo(ix)
250 if(iType=='seller') then
251 print(format(MAILTO_SALE,buyer,item,gsc(bid),gsc(bid-cut)))
252 end
253 if(delete) then GetInboxText(ix) end
254 TakeInboxMoney(ix)
255 if(single) then skip = true end
256 end
257 if(item and not skip) then
258 item,hi,dl = GetInboxItem(ix)
259 print(format(MAILTO_RECEIVED,item,from,sub))
260 if(delete) then GetInboxText(ix) end
261 TakeInboxItem(ix)
262 if(single) then skip = true end
263 end
264 local text,str,flag = GetInboxText(ix);
265 if not skip and (read or not flag) then DeleteInboxItem(ix) end
266 if read or not MailTo_ReceivedLog then return end
267 if money==0 and not item or strfind(from,' ') then return end
268 local log = format("%s,%d,%s,%d,%s",from,money,item or '',dl,sub)
269 print('MailTo_ReceivedLog: '..log)
270 MailTo_ReceivedLog[time()] = log
271 else MailTo_InboxItem_OnClick_Save(ix) end
272 end
273  
274 function MailTo_InboxMoney_OnClick()
275 if OpenMailFrame.money then
276 local item,icon,from,sub,money = GetInboxHeaderInfo(InboxFrame.openMailID)
277 Count_Cash(from,sub,money)
278 end
279 MailTo_InboxMoney_OnClick_Save()
280 end
281  
282 -- Handle auction browse searching
283 local function AuctionSearch(link)
284 if MailTo_Option.noauction then return end
285 if not AuctionFrameBrowse or not AuctionFrameBrowse:IsVisible() then return end
286 if link and not strfind(link,"item:") then return end
287 BrowseMinLevel:SetText('')
288 BrowseMaxLevel:SetText('')
289 UIDropDownMenu_SetText('',BrowseDropDown)
290 UIDropDownMenu_SetSelectedName(BrowseDropDown)
291 local name,il,ir,iml,class,sub
292 if link then
293 local i,j,name = strfind(link,"%[(.+)%]")
294 BrowseName:SetText(name)
295 BrowseName:HighlightText(0,-1)
296 IsUsableCheckButton:SetChecked(false)
297 if(MailTo_Option.noshift or not IsShiftKeyDown()) then return 1 end
298 local i,j,item = strfind(link,"(item:%d+:%d+:%d+:%d+)")
299 name,il,ir,iml,class,sub = GetItemInfo(item)
300 else
301 BrowseName:SetText('')
302 IsUsableCheckButton:SetChecked(true)
303 if(MailTo_Option.noshift or not IsShiftKeyDown()) then return 1 end
304 class = 'Recipe'; sub = class
305 end
306 AuctionFrameBrowse.selectedClass = class
307 for ix,name in CLASS_FILTERS do
308 if name==class then
309 AuctionFrameBrowse.selectedClassIndex = ix
310 i = ix
311 break
312 end
313 end
314 if class~=sub then
315 AuctionFrameBrowse.selectedSubclass = HIGHLIGHT_FONT_COLOR_CODE..sub..FONT_COLOR_CODE_CLOSE
316 for ix,name in {GetAuctionItemSubClasses(i)} do
317 if name==sub then
318 AuctionFrameBrowse.selectedSubclassIndex = ix
319 break
320 end
321 end
322 else
323 AuctionFrameBrowse.selectedSubclass = nil
324 AuctionFrameBrowse.selectedSubclassIndex = nil
325 end
326 AuctionFrameBrowse.selectedInvtype = nil
327 AuctionFrameBrowse.selectedInvtypeIndex = nil
328 AuctionFrameFilters_Update()
329 BrowseSearchButton:Click()
330 return 1
331 end
332  
333 -- Handle Chat OnClick events
334 function MailTo_ChatOnClick(item,link,button)
335 if button=="RightButton" and not IsControlKeyDown() and not IsAltKeyDown() then
336 if AuctionSearch(link) then return end
337 end
338 MailTo_ChatOnClick_Save(item,link,button)
339 end
340  
341 -- Handle Inventory Use events
342 function MailTo_InvUse(ParentID,ItemID)
343 if(not CursorHasItem() and not IsControlKeyDown() and not IsAltKeyDown() and not MailTo_Option.noclick) then
344 if(GetTime()-Last_Click<0.5) then return end
345 Last_Click = GetTime()
346 local doshift = IsShiftKeyDown() and not MailTo_Option.noshift
347 if(SendMailFrame:IsVisible()) then
348 PickupContainerItem(ParentID,ItemID)
349 ClickSendMailItemButton()
350 if(doshift) then
351 SendMailMailButton:Click()
352 this:Enable()
353 end
354 return
355 end
356 if(TradeFrame:IsVisible()and not MailTo_Option.notrade) then
357 PickupContainerItem(ParentID,ItemID)
358 local slot = TradeFrame_GetAvailableSlot()
359 if slot then ClickTradeButton(slot) end
360 return
361 end
362 if((AuctionFrameAuctions and AuctionFrameAuctions:IsVisible()) and not MailTo_Option.noauction) then
363 if doshift then
364 for slot = 1,16 do
365 if(not GetContainerItemInfo(0,slot)) then
366 SplitContainerItem(ParentID,ItemID,1)
367 PickupContainerItem(0,slot)
368 MailTo_Slot = slot
369 return
370 end
371 end
372 print(MAILTO_BACKPACK)
373 return
374 end
375 PickupContainerItem(ParentID,ItemID)
376 ClickAuctionSellItemButton()
377 return
378 end
379 if AuctionSearch(GetContainerItemLink(ParentID,ItemID)) then return end
380 end
381 MailTo_InvUse_Save(ParentID,ItemID)
382 end
383  
384 function MailTo_SendName()
385 if(MailTo_SendName_Save) then MailTo_SendName_Save() end
386 local sendee = SendMailNameEditBox:GetText()
387 if(MailTo_SavedName and (not sendee or sendee=="")) then
388 SendMailNameEditBox:SetText(MailTo_SavedName)
389 SendMailNameEditBox:HighlightText(0,-1)
390 SendMailNameEditBox:ClearFocus()
391 return
392 end
393 SendMailNameEditBox:HighlightText(0,-1)
394 MailTo_SavedName = sendee
395 end
396  
397 -- Handle clicks on the Send button
398 function MailTo_SendMail()
399 MailTo_SavedName = SendMailNameEditBox:GetText()
400 local name,tex,nr = GetSendMailItem()
401 if(name) then
402 local log = {to=MailTo_SavedName,from=Player,sv=Server,item=name,date=date(),due=GetTime()+DELAY}
403 if(Mail[MailTo_SavedName]) then
404 log.tex = tex
405 log.sub = SendMailSubjectEditBox:GetText()
406 log.nr = nr
407 local copper = MoneyInputFrame_GetCopper(SendMailMoney)
408 if(SendMailCODButton:GetChecked()) then copper = -copper; end
409 log.mon = copper;
410 end
411 log.cod = SendMailCODButton:GetChecked()
412 if(MailTo_Time==0) then MailTo_Timer(DELAY) end
413 table.insert(MailTo_Log,log)
414 elseif(Mail[MailTo_SavedName]) then
415 local copper = MoneyInputFrame_GetCopper(SendMailMoney)
416 if(SendMailCODButton:GetChecked()) then copper = -copper; end
417 name = SendMailSubjectEditBox:GetText()
418 local mail = {mon=copper,from=Player,exp=time()+MAIL_EXP,name=name,new=1}
419 tinsert(Mail[MailTo_SavedName],1,mail)
420 end
421 MailTo_Sendee[Server] = MailTo_SavedName
422 SendMailNameEditBox:ClearFocus()
423 MailTo_SendMail_Save()
424 end
425  
426 function MailTo_MailMod(tab)
427 if(not tab) then tab = this:GetID() end
428 if(tab==3 and CT_MailNameEditBox and MailTo_SavedName) then
429 CT_MailNameEditBox:SetText(MailTo_SavedName)
430 CT_MailNameEditBox:HighlightText(0,-1)
431 end
432 MailTo_MailMod_Save(tab)
433 end
434  
435 -- Process events
436 function MailTo_Event(event)
437 if event=="BAG_UPDATE" then
438 if(MailTo_Slot) then
439 PickupContainerItem(0,MailTo_Slot)
440 ClickAuctionSellItemButton()
441 MailTo_Slot = nil
442 end
443 return
444 end
445 if event=="MAIL_SHOW" then
446 Cash = {total=0,sales=0,refund=0,other=0}
447 HideUIPanel(MailTo_InFrame)
448 return
449 end
450 if event=="MAIL_CLOSED" then
451 if(MailCount and Cash.total>0) then
452 print(format(MAILTO_CASH,gsc(Cash.total),gsc(Cash.sales),gsc(Cash.refund),gsc(Cash.other)))
453 end
454 MailCount = nil
455 return
456 end
457 local nbr = GetInboxNumItems()
458 if event~="MAIL_INBOX_UPDATE" or MailCount==nbr then return end
459 MailCount = nbr
460 local nbr = GetInboxNumItems()
461 local days = MAIL_DAYS
462 local exp = floor(time()+days*DAY)
463 local inbox = {pkg=0,exp=exp}
464 local mail = {}
465 if(nbr>0) then
466 local pkg,from,desc,mny,nm,tx,nr = 0
467 local pi,si,sndr,sub,mon,cod,left,item
468 for i = 1,nbr do
469 pi,si,sndr,sub,mon,cod,left,item = GetInboxHeaderInfo(i)
470 if(cod>0) then mon = -cod; end
471 if(item and left<=days) then
472 nm,tx,nr = GetInboxItem(i)
473 pkg=i; days=left; from=sndr; desc=sub; mny=mon
474 end
475 if(not pi and si~=defIcon) then pi = si end
476 exp = floor(time()+left*DAY)
477 mail[i] = {tex=pi; name=sub; from=sndr; mon=mon; nr=nr; exp=exp}
478 end
479 if(pkg>0) then
480 exp = floor(time()+days*DAY)
481 inbox = {pkg=pkg; from=from; desc=desc; mon=mny; exp=exp}
482 end
483 else MiniMapMailFrame:Hide() end
484 Mail[Player] = mail
485 MailTo_Inbox[Server][Player] = inbox
486 end
487  
488 -- Handle our /mailto commands
489 function MailTo_command(msg)
490 if msg=='' then
491 if(table.getn(MailTo_Log)==0) then
492 print(MAILTO_LOGEMPTY)
493 return
494 end
495 MailTo_CheckLog(true)
496 return
497 end
498 if MAILTO_OPTION[msg] then
499 local option = MAILTO_OPTION[msg]
500 MailTo_Option[option.flag] = not MailTo_Option[option.flag]
501 print(format(MailTo_Option[option.flag] and MAILTO_OFF or MAILTO_ON,option.name))
502 return
503 end
504 if msg=="log" then
505 MailTo_ReceivedLog = not MailTo_ReceivedLog and {} or nil
506 print(format(MailTo_ReceivedLog and MAILTO_ON or MAILTO_OFF,'MailTo_ReceivedLog'))
507 return
508 end
509 if msg=="clear" then
510 MailTo_List[Server] = {}
511 print(MAILTO_CLEARED)
512 return
513 end
514 local _,_,pos = strfind(msg,"pos (%-?%d+)")
515 if(pos) then
516 print("pos = "..pos)
517 MailTo_Option.pos = pos
518 MailToDropDownMenu:SetPoint("RIGHT","SendMailNameEditBox","RIGHT",pos,0)
519 return
520 end
521 if msg~="list" then
522 print(FCr..MAILTO_UNDEFINED..msg)
523 return
524 end
525 local list = ''
526 for i,name in MailTo_List[Server] do
527 if list~='' then list = list..', ' end
528 list = list..name
529 end
530 if list=='' then print(FCr..MAILTO_LISTEMPTY)
531 else print(list) end
532 end
533  
534 -- Handle our /mailfrom commands
535 function MailFrom_command(msg)
536 local i,j,from,desc
537 if(msg and msg~='') then
538 i,j,from = strfind(msg,"^(%a+)$")
539 if(not from) then
540 i,j,from,desc = strfind(msg,"^(%a+) (.+)$")
541 end
542 end
543 if not from then print(FCr..MAILTO_NONAME) return end
544 if not desc then print(FCr..MAILTO_NODESC) return end
545 local log = {from=from,to=Player,sv=Server,item=desc,sub=desc,mon=0,date=date(),due=GetTime()+DELAY}
546 if(MailTo_Time==0) then MailTo_Timer(DELAY) end
547 table.insert(MailTo_Log,log)
548 MailTo_Format(log)
549 end
550  
551 -- Handle our /mtex commands
552 function MailTo_expire(msg)
553 local _,_,word,days,hr = strfind(msg,"(%l+) (%d+)(h?)")
554 if(word and MAILTO_DAYS[word]) then
555 MailTo_Option[word] = days/(hr=='h' and 24 or 1)
556 print(format(MAILTO_TIME,word,SecondsToTime(MailTo_Option[word]*DAY)))
557 elseif(msg=="all" or msg=="active" or msg=="soon" or msg=="expired") then
558 local cnt = 0
559 for server,list in MailTo_Inbox do
560 for player,inbox in list do
561 if(msg=="all" or inbox.pkg>0 and (msg=="active" or
562 msg=="soon" and inbox.exp-time()<EXP'soon' or
563 msg=="expired" and inbox.exp-time()<1)) then
564 MailTo_exp_msg(inbox,player,server)
565 cnt = cnt+1
566 end
567 end
568 end
569 if cnt==0 then print(MAILTO_NOTFOUND) end
570 elseif msg=="server" then
571 for player,inbox in MailTo_Inbox[Server] do
572 MailTo_exp_msg(inbox,player)
573 end
574 else MailTo_exp_msg(MailTo_Inbox[Server][Player]) end
575 end
576  
577 -- Check for soon to expire messages
578 function MailTo_CheckEx()
579 for server,list in MailTo_Inbox do
580 for player,inbox in list do
581 if(inbox and inbox.pkg>0 and inbox.exp-time()<EXP'warn') then
582 MailTo_exp_msg(inbox,player,server)
583 end
584 end
585 end
586 end
587  
588 -- Format the expired message
589 function MailTo_exp_msg(inbox,to,server)
590 local msg
591 if not inbox then print(FCr..MAILTO_NODATA) return end
592 local exp = inbox.exp and inbox.exp-time() or MAIL_EXP
593 if(inbox.pkg==0 and exp>EXP'new') then msg = MAILTO_NOITEMS
594 else
595 local desc = inbox.desc or MAILTO_NEWMAIL
596 local from = inbox.from or '?'
597 msg = format(MAILTO_INBOX, inbox.pkg, desc, from)
598 if exp<EXP'short' then msg = msg..FCr
599 elseif exp<EXP'long' then msg = msg..FCy end
600 if exp<1 then msg = msg..MAILTO_EXPIRED
601 else msg = msg..MAILTO_EXPIRES..SecondsToTime(exp) end
602 end
603 if to then msg = to..": "..msg end
604 if server then msg = server..":"..msg end
605 print(msg)
606 end
607  
608 -- Handle /inbox command
609 function MailTo_inbox(name,server)
610 if name=='' then
611 if(MailTo_InFrame:IsVisible()) then
612 HideUIPanel(MailTo_InFrame)
613 return
614 else name = Player end
615 end
616 if server==nil then server = Server end
617 if MailFrame:IsVisible() then print(FCr..MAILTO_MAILOPEN)
618 elseif(not MailTo_Mail[server]) then print(FCr.."Server not found.")
619 elseif(not MailTo_Mail[server][name]) then print(FCr..MAILTO_MAILCHECK)
620 else
621 Mail_name,Mail_server = name,server
622 UIDropDownMenu_SetWidth(90,MailTo_InFrame_DropDown)
623 UIDropDownMenu_Initialize(MailTo_InFrame_DropDown,MailTo_InFrame_Init,nil,1)
624 UIDropDownMenu_SetText(Mail_name,MailTo_InFrame_DropDown)
625 MailTo_InFrame_Fill()
626 SetCenterFrame(MailTo_InFrame,true)
627 end
628 end
629  
630 local function setColor(tex,exp,new)
631 local tc
632 exp = exp-time()
633 if exp<EXP'short' then tc = TCr
634 elseif exp<EXP'long' then tc = TCy
635 else tc = new and TCg or TCw end
636 tex:SetVertexColor(tc.r,tc.g,tc.b)
637 end
638  
639 function MailTo_InFrame_Fill()
640 local mail = MailTo_Mail[Mail_server][Mail_name]
641 local n = getn(mail)
642 local cn,rn,button,tex,exp,tc = 1,1
643 for i = 1,56 do
644 button = getglobal("MailTo_InFrameCol"..cn.."Item"..rn)
645 if i<=n then
646 button.mail = mail[i]
647 tex = mail[i].tex
648 if not tex then
649 if(mail[i].mon and mail[i].mon>0) then tex = GetCoinIcon(mail[i].mon)
650 else tex = defIcon end
651 end
652 SetItemButtonTexture(button,tex)
653 tex = getglobal("MailTo_InFrameCol"..cn.."Item"..rn.."IconTexture")
654 setColor(tex,mail[i].exp,mail[i].new)
655 else
656 exp = MailTo_Inbox[Mail_server][Mail_name].exp
657 if i==1 and exp and exp-time()<EXP'icon' then
658 SetItemButtonTexture(button,QmkIcon)
659 button.mail = {name=MAILTO_EMPTYNEW, exp=exp}
660 setColor(MailTo_InFrameCol1Item1IconTexture,exp,true)
661 else SetItemButtonTexture(button,''); button.mail = nil end
662 end
663 cn = cn+1
664 if cn>7 then cn=1; rn=rn+1 end
665 end
666 end
667  
668 function AC_Server_OnClick()
669 MailTo_Option.server = MailTo_InFrameServerButton:GetChecked()
670 end
671  
672 local function InFrame_Select()
673 HideDropDownMenu(1)
674 local value = this.value
675 if value then
676 if(Mail_name==value.n and Mail_server==value.s) then return end
677 Mail_name,Mail_server = value.n,value.s;
678 UIDropDownMenu_SetText(Mail_name,MailTo_InFrame_DropDown)
679 MailTo_InFrame_Fill()
680 end
681 end
682  
683 function MailTo_InFrame_Remove()
684 local name = this.value
685 MailTo_Inbox[name.s][name.n] = nil
686 if(not next(MailTo_Inbox[name.s])) then MailTo_Inbox[name.s] = nil; end
687 MailTo_Mail[name.s][name.n] = nil
688 if(not next(MailTo_Mail[name.s])) then MailTo_Mail[name.s] = nil; end
689 for i,n in MailTo_List[Server] do
690 if n==name.n then
691 tremove(MailTo_List[Server],i)
692 break
693 end
694 end
695 if(not next(MailTo_List[value.s])) then MailTo_List[name.s] = nil; end
696 print(format(MAILTO_REMOVE2,name.n,name.s))
697 HideUIPanel(MailTo_InFrame)
698 end
699  
700 local function add_names(server,count,level)
701 local Mail,Inbox,text,fc,exp = MailTo_Mail[server],MailTo_Inbox[server]
702 for ix2,name in sorted_index(Mail) do
703 count = count + 1
704 if count>UIDROPDOWNMENU_MAXBUTTONS then return end
705 fc = ''
706 exp = Inbox[name].exp
707 if exp then
708 exp = exp-time()
709 if exp<EXP'short' then fc = FCr
710 elseif exp<EXP'long' then fc = FCy
711 elseif Inbox[name].pkg>0 then
712 if Mail[name][1].new then fc = FCg end
713 elseif exp<EXP'icon' then fc = FCg end
714 end
715 text = name..fc..' ('..getn(Mail[name])..')'
716 info = {text=text;value={n=name,s=server};func=InFrame_Select}
717 if(name==Mail_name and server==Mail_server) then info.checked = 1 end
718 UIDropDownMenu_AddButton(info,level)
719 end
720 return count;
721 end
722  
723 function MailTo_InFrame_Init(level)
724 if level>1 then
725 add_names(this:GetParent().value,0,2)
726 return
727 end
728 local count = 0
729 if(Server~=Mail_server or Player~=Mail_name) then
730 local info = {notCheckable=1,func=MailTo_InFrame_Remove}
731 info.value = {n=Mail_name,s=Mail_server}
732 info.text = string.format(MAILTO_F_REMOVE,Mail_name)
733 UIDropDownMenu_AddButton(info)
734 count = 1
735 end
736 if MailTo_Option.server then
737 for ix,server in sorted_index(MailTo_Mail) do
738 count = count + 1;
739 if count>UIDROPDOWNMENU_MAXBUTTONS-1 then return end
740 info = {text=server;value=server;notClickable=1;hasArrow=1}
741 if server==Mail_server then info.checked = 1 end
742 UIDropDownMenu_AddButton(info)
743 end
744 else add_names(Server,count) end
745 end
746  
747 -- Mouseover of MailTo inbox
748 function MailTo_InFrame_OnEnter()
749 local mail = this.mail
750 if not mail then return end
751 local name,money = mail.name, mail.mon
752 if(money==0 and not name) then return end -- sanity
753 GameTooltip:SetOwner(this, "ANCHOR_RIGHT")
754 if(not IsShiftKeyDown() or not mail.link) then
755 if name then GameTooltip:SetText(name,1,1,1) end
756 if mail.from then GameTooltip:AddLine(MAILTO_FROM..mail.from) end
757 if money then tip_money(money) end
758 if mail.exp then
759 local exp = mail.exp-time()
760 local c = exp<EXP'short' and {1,0,0} or exp<EXP'long' and {1,1,0} or {0,1,0}
761 if(exp<1) then GameTooltip:AddLine(MAILTO_EXPIRED2,1,0,0)
762 else GameTooltip:AddLine(MAILTO_EXPIRES2..SecondsToTime(exp),c[1],c[2],c[3]) end
763 end
764 else GameTooltip:SetHyperlink(mail.link) end
765 GameTooltip:Show()
766 end
767  
768 function MailTo_DropDown_OnLoad()
769 this.tooltip = MAILTO_TOOLTIP
770 UIDropDownMenu_Initialize(this:GetParent(), MailTo_ToList_Init)
771 UIDropDownMenu_SetAnchor(0, 0, this:GetParent(), "TOPRIGHT", this:GetName(), "BOTTOMRIGHT")
772 end
773  
774 function MailTo_ToList_Init()
775 local info = {value=0,notCheckable=1};
776 MailTo_Name = SendMailNameEditBox:GetText();
777 if MailTo_Name~='' then
778 MailTo_Selected = MailTo_InList(MailTo_Name)
779 if MailTo_Selected then
780 info.text = string.format(MAILTO_F_REMOVE,MailTo_Name)
781 info.func = MailTo_ListRemove
782 elseif(table.getn(MailTo_List[Server])<UIDROPDOWNMENU_MAXBUTTONS) then
783 info.text = string.format(MAILTO_F_ADD,MailTo_Name)
784 info.func = MailTo_ListAdd
785 else
786 info = nil
787 print(FCr..MAILTO_LISTFULL)
788 end
789 if info then UIDropDownMenu_AddButton(info) end
790 end
791 for key,name in MailTo_List[Server] do
792 info = {text=name,value=key,func=MailTo_ListSelect}
793 if(key==MailTo_Selected) then info.checked = 1; end
794 UIDropDownMenu_AddButton(info)
795 end
796 end
797  
798 function MailTo_ListSelect()
799 local value = this.value;
800 if value then
801 MailTo_SavedName = MailTo_List[Server][value]
802 SendMailNameEditBox:SetText(MailTo_SavedName)
803 SendMailNameEditBox:HighlightText(0,-1)
804 SendMailSubjectEditBox:SetFocus()
805 end
806 end
807  
808 function MailTo_ListAdd(name)
809 if not name then name = MailTo_Name; end
810 tinsert(MailTo_List[Server],name)
811 sort(MailTo_List[Server])
812 print(name..MAILTO_ADDED)
813 end
814  
815 function MailTo_ListRemove()
816 tremove(MailTo_List[Server],MailTo_Selected)
817 print(MailTo_Name..MAILTO_REMOVED)
818 end
819  
820 function MailTo_InList(MCname)
821 local LCname = string.lower(MCname)
822 for key,name in MailTo_List[Server] do
823 if LCname==string.lower(name) then return key; end
824 end
825 end
826  
827 function MailTo_CheckLog(all,nodn)
828 local found,mail,exp = false
829 for i = getn(MailTo_Log),1,-1 do
830 local now,log = GetTime(),MailTo_Log[i]
831 if log.due>now+DELAY then log.due = now; end -- Sanity!
832 if log.due<now then
833 if not nodn then
834 found = true
835 MailTo_Format(log)
836 end
837 if(log.sv and log.to and MailTo_Mail[log.sv][log.to]) then
838 exp = time() + (log.cod and COD_EXP or MAIL_EXP);
839 mail = {tex=log.tex; name=log.sub; from=log.from; mon=log.mon; exp=exp; nr=log.nr; new=1}
840 tinsert(MailTo_Mail[log.sv][log.to],1,mail)
841 if(MailTo_Inbox[log.sv][log.to].pkg==0) then
842 MailTo_Inbox[log.sv][log.to] = {pkg=1; from=log.from; desc=log.sub; mon=log.mon; exp=exp}
843 end
844 end
845 tremove(MailTo_Log,i)
846 elseif(all or Startup and log.sv==Server and (log.to==Player or log.from==Player)) then
847 MailTo_Format(MailTo_Log[i])
848 end
849 end
850 if Startup then MailTo_CheckEx() end
851 Startup = false
852 return found
853 end
854  
855 function MailTo_Timer(secs)
856 MailTo_Time = secs
857 MailTo_Frame:Show() -- Start the timer
858 end
859  
860 function MailTo_OnUpdate(dt)
861 MailTo_Time = MailTo_Time-dt
862 if MailTo_Time>0 then return end
863 if MailTo_CheckLog(nil,MailTo_Option.alert) and not MailTo_Option.noding then
864 PlaySound("AuctionWindowOpen")
865 end
866 local log = MailTo_Log[1]
867 if log then
868 MailTo_Timer(log.due-GetTime())
869 else
870 MailTo_Frame:Hide() -- Stop the timer
871 MailTo_Time = 0
872 end
873 end
874  
875 function MailTo_Format(log)
876 local ss = log.sv==nil or log.sv==Server
877 local to = ss and log.to==Player and FCy..MAILTO_YOU..FCe or log.to
878 local from = ss and log.from==Player and FCy..MAILTO_YOU..FCe or log.from
879 local now,due = GetTime()
880 if log.due>now then
881 local min = math.ceil((log.due-now)/60)
882 due = format(MAILTO_DUE,min)
883 else due = FCg..MAILTO_DELIVERED; end
884 local item = FCw..log.item..FCe
885 if log.sv and log.sv~=Server then
886 item = '('..log.sv..') '..item
887 end
888 print(format(MAILTO_SENT,item,to,from,due))
889 end
890  
891 local lcs
892  
893 local function LocList(player,loc,list)
894 local txt = ''
895 for name,nr in list do
896 if txt~='' then txt = txt..', ' end
897 txt = txt..name..'='..nr
898 end
899 if txt~='' then print(format("%s(%s%s%s): %s",player,FCy,loc,FCe,txt)) end
900 end
901  
902 local function BagList(bag,cnt,list)
903 local name,nr
904 for i = 1,cnt do
905 if bag[i] and bag[i].L then
906 name = GetItemInfo(bag[i].L)
907 if(name and strfind(strlower(name),lcs,1,true)) then
908 nr = bag[i].C or 1
909 if list[name] then nr = nr+list[name] end
910 list[name] = nr
911 end
912 end
913 end
914 return list
915 end
916  
917 function MailTo_locate(str)
918 if str=='' then print(MAILTO_NONAME); return end
919 local i,j,id,name = strfind(str,"item:(%d+):.+%[(.+)%]")
920 if name then str = name; end
921 lcs = strlower(str)
922 local list,s,e,name,txt,nr,CV,data,inbox;
923 if CharactersViewerProfile then CV = CharactersViewerProfile[Server] end
924 print(FCw..format(MAILTO_LOCATE,lcs))
925 for x,player in sorted_index(Mail) do
926 inbox = Mail[player]
927 list = {}
928 for ix,data in inbox do
929 name = data.name
930 s,e,txt,nr = strfind(name,"^(.+) %((%d+)%)$")
931 if s then name = txt; end
932 if data.nr then nr = data.nr end
933 if nr then
934 if strfind(strlower(name),lcs,1,true) then
935 if list[name] then nr = nr+list[name] end
936 list[name] = tonumber(nr)
937 end
938 end
939 end
940 LocList(player,MAILTO_MAIL,list)
941 if CV and CV[player] then
942 data = CV[player]
943 list = {};
944 for ix,bag in data.Bag do
945 list = BagList(bag,bag.size,list)
946 end
947 LocList(player,MAILTO_INV,list)
948 if data.Bank then
949 list = {}
950 for ix,bag in data.Bank do
951 if type(bag)=='table' then
952 nr = ix=='Main' and 24 or bag.size;
953 list = BagList(bag,nr,list)
954 end
955 end
956 end
957 LocList(player,MAILTO_BANK,list)
958 end
959 end
960 end
961  
962 -- Check for new mail
963 local function print_new(mail,server)
964 local nr = 0
965 local svr = server and '('..server..') ' or ''
966 for name,inbox in mail do
967 for i,item in inbox do
968 if item.new then
969 print(format(MAILTO_NEW,svr,item.name,item.from,name))
970 nr = nr+1
971 end
972 end
973 end
974 return nr
975 end
976  
977 function MailTo_new(msg)
978 local nr = 0
979 if msg=='all' then
980 for server,mail in MailTo_Mail do
981 nr = nr+print_new(mail,server)
982 end
983 else nr = print_new(MailTo_Mail[Server]) end
984 if nr==0 then print(MAILTO_NONEW) end
985 end