Mercurial > wow > ouroloot
comparison core.lua @ 76:124da015c4a2
- Some more debugging aids (logging error/assert, auto-enable of testing
panel, reminder of GOP history mode)
- Move (finally!) hypertext handling code out to each call site.
- Fix some bugs in previous alpha code.
- Initial-but-mostly-tested code to handle items that have a "unique" field
which are in fact always the same (for example, elementium gem cluster).
Still need to test the case in which a remote tracker sees them first.
- The rest of the variable-cutoff history cleanup.
| author | Farmbuyer of US-Kilrogg <farmbuyer@gmail.com> |
|---|---|
| date | Fri, 08 Jun 2012 08:05:37 +0000 |
| parents | 32eb24fb2ebf |
| children | a07c9dd79f3a |
comparison
equal
deleted
inserted
replaced
| 75:676fb79a4ae2 | 76:124da015c4a2 |
|---|---|
| 91 entire package and rewrote the loot tracker module from scratch. Many of the | 91 entire package and rewrote the loot tracker module from scratch. Many of the |
| 92 variable/function naming conventions (sv_*, g_*, and family) stayed across the | 92 variable/function naming conventions (sv_*, g_*, and family) stayed across the |
| 93 rewrite. | 93 rewrite. |
| 94 | 94 |
| 95 Some variables are needlessly initialized to nil just to look uniform and | 95 Some variables are needlessly initialized to nil just to look uniform and |
| 96 serve as a reminder. | 96 serve as a spelling reminder. |
| 97 | 97 |
| 98 ]==] | 98 ]==] |
| 99 | 99 |
| 100 ------ Saved variables | 100 ------ Saved variables |
| 101 OuroLootSV = nil -- possible copy of g_loot | 101 OuroLootSV = nil -- possible copy of g_loot |
| 141 .." welcome message will not intrude again." | 141 .." welcome message will not intrude again." |
| 142 local newer_warning = "A newer version has been released. You can %s to display" | 142 local newer_warning = "A newer version has been released. You can %s to display" |
| 143 .." a download URL for copy-and-pasting. You can %s to ping other raiders" | 143 .." a download URL for copy-and-pasting. You can %s to ping other raiders" |
| 144 .." for their installed versions (same as '/ouroloot ping' or clicking the" | 144 .." for their installed versions (same as '/ouroloot ping' or clicking the" |
| 145 .." 'Ping!' button on the options panel)." | 145 .." 'Ping!' button on the options panel)." |
| 146 local unique_collision = "|cffff1010%s:|r Item '%s' was carrying unique tag <" | 146 local unique_collision = "|cffff1010%s:|r Item '%s' was carrying unique tag " |
| 147 ..">, but that was already in use! (New sender was '%s', previous cache " | 147 .."<%s>, but that was already in use! (New sender was '%s', previous cache " |
| 148 .."entry was <%s/%s>.) This may require a live human to figure out; the " | 148 .."entry was <%s/%s>.) This may require a live human to figure out; the " |
| 149 .."loot in question has not been stored." | 149 .."loot in question has not been stored." |
| 150 local remote_chatty = "|cff00ff00%s|r changed %d/%s from %s%s|r to %s%s|r" | 150 local remote_chatty = "|cff00ff00%s|r changed %d/%s from %s%s|r to %s%s|r" |
| 151 local qualnames = { | 151 local qualnames = { |
| 152 ['gray'] = 0, ['grey'] = 0, ['poor'] = 0, ['trash'] = 0, | 152 ['gray'] = 0, ['grey'] = 0, ['poor'] = 0, ['trash'] = 0, |
| 157 ['legendary'] = 5, ['orange'] = 5, | 157 ['legendary'] = 5, ['orange'] = 5, |
| 158 ['artifact'] = 6, | 158 ['artifact'] = 6, |
| 159 --['heirloom'] = 7, | 159 --['heirloom'] = 7, |
| 160 } | 160 } |
| 161 local my_name = UnitName('player') | 161 local my_name = UnitName('player') |
| 162 local comm_cleanup_ttl = 4 -- seconds in the cache | 162 local comm_cleanup_ttl = 4 -- seconds in the communications cache |
| 163 local revision_large = nil -- defaults to 1, possibly changed by revision | 163 local revision_large = nil -- defaults to 1, possibly changed by revision |
| 164 local g_LOOT_ITEM_ss, g_LOOT_ITEM_MULTIPLE_sss, g_LOOT_ITEM_SELF_s, g_LOOT_ITEM_SELF_MULTIPLE_ss | 164 local g_LOOT_ITEM_ss, g_LOOT_ITEM_MULTIPLE_sss, g_LOOT_ITEM_SELF_s, g_LOOT_ITEM_SELF_MULTIPLE_ss |
| 165 | 165 |
| 166 | 166 |
| 167 ------ Addon member data | 167 ------ Addon member data |
| 186 end | 186 end |
| 187 end | 187 end |
| 188 | 188 |
| 189 DEBUG_PRINT = false | 189 DEBUG_PRINT = false |
| 190 debug = { | 190 debug = { |
| 191 comm = false, | 191 comm = false, |
| 192 loot = false, | 192 loot = false, |
| 193 flow = false, | 193 flow = false, |
| 194 notraid = false, | 194 notraid = false, |
| 195 cache = false, | 195 cache = false, |
| 196 alsolog = false, | 196 alsolog = false, |
| 197 } | 197 } |
| 198 -- This looks ugly, but it factors out the load-time decisions from | 198 -- This looks ugly, but it factors out the load-time decisions from |
| 199 -- the run-time ones. Args to [dp]print are concatenated with spaces. | 199 -- the run-time ones. Args to [dp]print are concatenated with spaces. |
| 200 if tekdebug then | 200 if tekdebug then |
| 201 function dprint (t,...) | 201 function dprint (t,...) |
| 226 end | 226 end |
| 227 else | 227 else |
| 228 pprint = flib.nullfunc | 228 pprint = flib.nullfunc |
| 229 end | 229 end |
| 230 | 230 |
| 231 -- The same observable behavior as the Lua builtins, but with slightly | |
| 232 -- different hardcoded strings and, more importantly, implicit logging. | |
| 233 function error(txt,lvl) | |
| 234 pprint('ERROR()', txt) | |
| 235 pprint('DEBUGSTACK()', _G.debugstack()) | |
| 236 _G.error(txt,lvl) | |
| 237 end | |
| 238 function assert(cond,msg,...) | |
| 239 if cond then | |
| 240 return cond,msg,... | |
| 241 else | |
| 242 error('ASSERT() FAILED: '..tostring(msg or 'nil')) | |
| 243 end | |
| 244 end | |
| 245 | |
| 231 enabled = false | 246 enabled = false |
| 232 rebroadcast = false | 247 rebroadcast = false |
| 233 display = nil -- display frame, when visible | 248 display = nil -- reference to display frame iff visible |
| 234 loot_clean = nil -- index of last GUI entry with known-current visual data | 249 loot_clean = nil -- index of last GUI entry with known-current visual data |
| 235 sender_list = {active={},names={}} -- this should be reworked | |
| 236 threshold = debug.loot and 0 or 3 -- rare by default | 250 threshold = debug.loot and 0 or 3 -- rare by default |
| 237 sharder = nil -- name of person whose loot is marked as shards | 251 sharder = nil -- name of person whose loot is marked as shards |
| 238 | 252 |
| 239 -- The rest is also used in the GUI: | 253 -- The rest is also used in the GUI: |
| 240 | 254 |
| 255 sender_list = {active={},names={}} -- this should be reworked | |
| 241 popped = nil -- non-nil when reminder has been shown, actual value unimportant | 256 popped = nil -- non-nil when reminder has been shown, actual value unimportant |
| 242 | 257 |
| 243 bossmod_registered = nil | 258 bossmod_registered = nil |
| 244 bossmods = {} | 259 bossmods = {} |
| 245 | 260 |
| 246 requesting = nil -- for prompting for additional rebroadcasters | 261 requesting = nil -- prompting for additional rebroadcasters |
| 247 | 262 |
| 248 -- don't use NUM_ITEM_QUALITIES as the upper bound unless we expect heirlooms to show up | 263 -- don't use NUM_ITEM_QUALITIES as the upper loop bound unless we expect |
| 249 thresholds = {} | 264 -- heirlooms to show up |
| 265 thresholds = {} | |
| 250 for i = 0,6 do | 266 for i = 0,6 do |
| 251 thresholds[i] = _G.ITEM_QUALITY_COLORS[i].hex .. _G["ITEM_QUALITY"..i.."_DESC"] .. "|r" | 267 thresholds[i] = _G.ITEM_QUALITY_COLORS[i].hex .. _G["ITEM_QUALITY"..i.."_DESC"] .. "|r" |
| 252 end | 268 end |
| 253 | 269 |
| 254 _G.setfenv (1, _G) | 270 _G.setfenv (1, _G) |
| 265 msg = msg or "load-time assertion failed!" | 281 msg = msg or "load-time assertion failed!" |
| 266 self.NOLOAD = msg | 282 self.NOLOAD = msg |
| 267 self:Printf([[|cffff1010ERROR:|r <|cff00ff00%s|r> Ouro Loot cannot finish loading. You will need to type |cff30adff%s|r once these problems are resolved, and try again.]], msg, _G.SLASH_RELOAD1) | 283 self:Printf([[|cffff1010ERROR:|r <|cff00ff00%s|r> Ouro Loot cannot finish loading. You will need to type |cff30adff%s|r once these problems are resolved, and try again.]], msg, _G.SLASH_RELOAD1) |
| 268 SLASH_ACECONSOLE_OUROLOOT1 = nil | 284 SLASH_ACECONSOLE_OUROLOOT1 = nil |
| 269 SLASH_ACECONSOLE_OUROLOOT2 = nil | 285 SLASH_ACECONSOLE_OUROLOOT2 = nil |
| 270 _G.error (msg, --[[level=]]2) | 286 self.error (msg, --[[level=]]2) |
| 271 end | 287 end |
| 272 | 288 |
| 273 -- Seriously? ORLY? | 289 -- Seriously? ORLY? |
| 274 -- YARLY. Go ahead and guess what was involved in tracking this down. If | 290 -- YARLY. Go ahead and guess what was involved in tracking this down. If |
| 275 -- more such effects are added in the future, the "id==xxxxx" will need to | 291 -- more such effects are added in the future, the "id==xxxxx" will need to |
| 291 | 307 |
| 292 | 308 |
| 293 ------ Globals | 309 ------ Globals |
| 294 local g_loot = nil | 310 local g_loot = nil |
| 295 local g_restore_p = nil | 311 local g_restore_p = nil |
| 296 local g_wafer_thin = nil -- for prompting for additional rebroadcasters | 312 local g_wafer_thin = nil -- prompting for additional rebroadcasters |
| 297 local g_today = nil -- "today" entry in g_loot | 313 local g_today = nil -- "today" entry in g_loot |
| 298 local g_boss_signpost = nil | 314 local g_boss_signpost = nil |
| 299 local g_seeing_oldsigs = nil | 315 local g_seeing_oldsigs = nil |
| 300 local g_uniques = nil -- memoization of unique loot events | 316 local g_uniques = nil -- memoization of unique loot events |
| 317 local g_unique_replace = nil | |
| 301 local opts = nil | 318 local opts = nil |
| 319 | |
| 320 local error = addon.error | |
| 321 local assert = addon.assert | |
| 302 | 322 |
| 303 -- for speeding up local loads, not because I think _G will change | 323 -- for speeding up local loads, not because I think _G will change |
| 304 local _G = _G | 324 local _G = _G |
| 305 local type = _G.type | 325 local type = _G.type |
| 306 local select = _G.select | 326 local select = _G.select |
| 314 | 334 |
| 315 local pprint, tabledump = addon.pprint, flib.tabledump | 335 local pprint, tabledump = addon.pprint, flib.tabledump |
| 316 local CopyTable, GetNumRaidMembers = _G.CopyTable, _G.GetNumRaidMembers | 336 local CopyTable, GetNumRaidMembers = _G.CopyTable, _G.GetNumRaidMembers |
| 317 -- En masse forward decls of symbols defined inside local blocks | 337 -- En masse forward decls of symbols defined inside local blocks |
| 318 local _register_bossmod, makedate, create_new_cache, _init, _log | 338 local _register_bossmod, makedate, create_new_cache, _init, _log |
| 319 local _history_by_loot_id, _notify_about_remote | 339 local _history_by_loot_id, _notify_about_remote, _setup_unique_replace |
| 320 | 340 |
| 321 -- Try to extract numbers from the .toc "Version" and munge them into an | 341 -- Try to extract numbers from the .toc "Version" and munge them into an |
| 322 -- integral form for comparison. The result doesn't need to be meaningful as | 342 -- integral form for comparison. The result doesn't need to be meaningful as |
| 323 -- long as we can reliably feed two of them to "<" and get useful answers. | 343 -- long as we can reliably feed two of them to "<" and get useful answers. |
| 324 -- | 344 -- |
| 340 revision_large = math.max(r,1) | 360 revision_large = math.max(r,1) |
| 341 end | 361 end |
| 342 | 362 |
| 343 -- Hypertext support, inspired by DBM broadcast pizza timers | 363 -- Hypertext support, inspired by DBM broadcast pizza timers |
| 344 do | 364 do |
| 345 local hypertext_format_str = "|HOuroRaid:%s|h%s[%s]|r|h" | 365 local hypertext_format_str = "|HOuroLoot:%d|h%s[%s]|r|h" |
| 366 local func_map = {} --_G.setmetatable({}, {__mode = 'k'}) | |
| 367 local text_map = {} --_G.setmetatable({}, {__mode = 'kv'}) | |
| 368 local base = _G.newproxy(true) | |
| 369 _G.getmetatable(base).__tostring = function(ud) return text_map[ud] end | |
| 370 --@debug@ | |
| 371 -- collecting these tokens is an interesting micro-optimization but not yet | |
| 372 _G.getmetatable(base).__gc = function(ud) | |
| 373 print("Collecting hyperlink object <",tostring(ud),">") | |
| 374 end | |
| 375 --@end-debug@ | |
| 376 | |
| 377 -- TEXT will automatically be surrounded by brackets | |
| 378 -- COLOR can be ITEM_QUALITY_* or a formatting string ("|cff...") | |
| 379 -- FUNC can be "MethodName", "tab_title", or a function | |
| 380 -- | |
| 381 -- Returns an obaque token. Calling tostring() on the token will yield a | |
| 382 -- formatted clickable string that can be displayed in chat. This is | |
| 383 -- largely an excuse to fool around with Lua data constructs. | |
| 384 function addon.format_hypertext (text, color, func) | |
| 385 local ret = _G.newproxy(base) | |
| 386 local num = #text_map + 1 | |
| 387 text_map[ret] = hypertext_format_str:format (num, | |
| 388 type(color)=='number' and ITEM_QUALITY_COLORS[color].hex or color, | |
| 389 text) | |
| 390 text_map[num] = ret | |
| 391 func_map[ret] = func | |
| 392 return ret | |
| 393 end | |
| 394 | |
| 395 --[[ | |
| 396 link: OuroLoot:n | |
| 397 fullstring: |HOuroLoot:n|h|cff.....[foo]|r|h | |
| 398 mousebutton: "LeftButton", "MiddleButton", "RightButton" | |
| 399 | |
| 400 amusingly, print()'ing the fullstring below as a debugging aid yields | |
| 401 another clickable link, yay data reproducability | |
| 402 ]] | |
| 346 local strsplit = _G.strsplit | 403 local strsplit = _G.strsplit |
| 347 | 404 DEFAULT_CHAT_FRAME:HookScript("OnHyperlinkClick", function(self, link, fullstring, mousebutton) |
| 348 -- TEXT will automatically be surrounded by brackets | |
| 349 -- COLOR can be item quality code or a hex string | |
| 350 function addon.format_hypertext (code, text, color) | |
| 351 return hypertext_format_str:format (code, | |
| 352 type(color)=='number' and ITEM_QUALITY_COLORS[color].hex or color, | |
| 353 text) | |
| 354 end | |
| 355 | |
| 356 DEFAULT_CHAT_FRAME:HookScript("OnHyperlinkClick", function(self, link, string, mousebutton) | |
| 357 local ltype, arg = strsplit(":",link) | 405 local ltype, arg = strsplit(":",link) |
| 358 if ltype ~= "OuroRaid" then return end | 406 if ltype ~= "OuroLoot" then return end |
| 359 -- XXX this is crap, redo this as a dispatch table with code at the call site | 407 local f = func_map[text_map[tonumber(arg)]] |
| 360 if arg == 'openloot' then | 408 if type(f) == 'function' then |
| 361 addon:BuildMainDisplay() | 409 f() |
| 362 elseif arg == 'popupurl' then | 410 elseif type(f) == 'string' then |
| 363 -- Sadly, this is not generated by the packager, so hardcode it for now. | 411 if type(addon[f]) == 'function' then |
| 364 -- The 'data' field is handled differently for onshow than for other callbacks. | 412 addon[f](addon) -- method name |
| 365 StaticPopup_Show("OUROL_URL", --[[text_arg1=]]nil, --[[text_arg2=]]nil, | 413 else |
| 366 --[[data=]][[http://www.curse.com/addons/wow/ouroloot]]) | 414 addon:BuildMainDisplay(f) -- tab title fragment |
| 367 elseif arg == 'doping' then | 415 end |
| 368 addon:DoPing() | |
| 369 elseif arg == 'help' then | |
| 370 addon:BuildMainDisplay('help') | |
| 371 elseif arg == 'bcaston' then | |
| 372 if not addon.rebroadcast then | |
| 373 addon:Activate(nil,true) | |
| 374 end | |
| 375 addon:broadcast('bcast_responder') | |
| 376 elseif arg == 'waferthin' then -- mint? it's wafer thin! | |
| 377 g_wafer_thin = true -- fuck off, I'm full | |
| 378 addon:broadcast('bcast_denied') -- remove once tested | |
| 379 elseif arg == 'reload' then | |
| 380 addon:BuildMainDisplay('opt') | |
| 381 end | 416 end |
| 382 end) | 417 end) |
| 383 | 418 |
| 384 local old = ItemRefTooltip.SetHyperlink | 419 local old = ItemRefTooltip.SetHyperlink |
| 385 function ItemRefTooltip:SetHyperlink (link, ...) | 420 function ItemRefTooltip:SetHyperlink (link, ...) |
| 386 if link:match("^OuroRaid") then return end | 421 if link:match("^OuroLoot") then return end |
| 387 return old (self, link, ...) | 422 return old (self, link, ...) |
| 388 end | 423 end |
| 389 end | 424 end |
| 390 | 425 |
| 391 do | 426 do |
| 414 if typeof == "none" then return name, MAX_RAID_MEMBERS end | 449 if typeof == "none" then return name, MAX_RAID_MEMBERS end |
| 415 -- diffstr is "5 Player", "10 Player (Heroic)", etc. ugh. | 450 -- diffstr is "5 Player", "10 Player (Heroic)", etc. ugh. |
| 416 if (GetLFGMode()) and (GetLFGModeType() == 'raid') then | 451 if (GetLFGMode()) and (GetLFGModeType() == 'raid') then |
| 417 t,r = 'LFR', 25 | 452 t,r = 'LFR', 25 |
| 418 elseif diffcode == 1 then | 453 elseif diffcode == 1 then |
| 419 t,r = (GetNumRaidMembers()>0) and "10",10 or "5",5 | 454 if GetNumRaidMembers() > 0 then |
| 455 t,r = "10",10 | |
| 456 else | |
| 457 t,r = "5",5 | |
| 458 end | |
| 420 elseif diffcode == 2 then | 459 elseif diffcode == 2 then |
| 421 t,r = (GetNumRaidMembers()>0) and "25",25 or "5h",5 | 460 if GetNumRaidMembers() > 0 then |
| 461 t,r = "25",25 | |
| 462 else | |
| 463 t,r = "5h",5 | |
| 464 end | |
| 422 elseif diffcode == 3 then | 465 elseif diffcode == 3 then |
| 423 t,r = "10h", 10 | 466 t,r = "10h", 10 |
| 424 elseif diffcode == 4 then | 467 elseif diffcode == 4 then |
| 425 t,r = "25h", 25 | 468 t,r = "25h", 25 |
| 426 end | 469 end |
| 570 end | 613 end |
| 571 end | 614 end |
| 572 local function _test (cache, x) | 615 local function _test (cache, x) |
| 573 -- FIXME This can return false positives, if called after the onloop | 616 -- FIXME This can return false positives, if called after the onloop |
| 574 -- fifo has been removed but before the GC has removed the weak entry. | 617 -- fifo has been removed but before the GC has removed the weak entry. |
| 575 -- What to do, what to do... | 618 -- What to do, what to do... try forcing a GC during alldone. |
| 576 return cache.hash[x] ~= nil | 619 return cache.hash[x] ~= nil |
| 577 end | 620 end |
| 578 | 621 |
| 579 function create_new_cache (name, ttl, on_alldone) | 622 function create_new_cache (name, ttl, on_alldone) |
| 580 -- setting OnFinished for cleanup fires at the end of each inner loop, | 623 -- setting OnFinished for cleanup fires at the end of each inner loop, |
| 581 -- with no 'requested' argument to distinguish cases. thus, on_alldone. | 624 -- with no 'requested' argument to distinguish cases. thus, on_alldone. |
| 625 -- FWIW, on_alldone is passed this table as its sole argument: | |
| 582 local c = { | 626 local c = { |
| 583 ttl = ttl, | 627 ttl = ttl, |
| 584 name = name, | 628 name = name, |
| 585 add = _add, | 629 add = _add, |
| 586 test = _test, | 630 test = _test, |
| 610 g_restore_p = OuroLootSV ~= nil | 654 g_restore_p = OuroLootSV ~= nil |
| 611 self.dprint('flow', "oninit sets restore as", g_restore_p) | 655 self.dprint('flow', "oninit sets restore as", g_restore_p) |
| 612 | 656 |
| 613 if _G.OuroLootSV_opts == nil then | 657 if _G.OuroLootSV_opts == nil then |
| 614 _G.OuroLootSV_opts = {} | 658 _G.OuroLootSV_opts = {} |
| 659 local vclick = self.format_hypertext ([[click here]], ITEM_QUALITY_UNCOMMON, 'help') | |
| 615 self:ScheduleTimer(function(s) | 660 self:ScheduleTimer(function(s) |
| 616 s:Print(virgin, s.format_hypertext('help',"click here",ITEM_QUALITY_UNCOMMON)) | 661 s:Print(virgin, tostring(vclick)) |
| 617 virgin = nil | 662 virgin = nil |
| 618 end,10,self) | 663 end,10,self) |
| 619 else | 664 else |
| 620 virgin = nil | 665 virgin = nil |
| 621 end | 666 end |
| 693 loot.unique = loot.id .. ' ' .. loot.when | 738 loot.unique = loot.id .. ' ' .. loot.when |
| 694 end | 739 end |
| 695 end | 740 end |
| 696 end | 741 end |
| 697 -- format 3 to format 4 was a major revamp of per-player data | 742 -- format 3 to format 4 was a major revamp of per-player data |
| 698 self:_uplift_history_format(player,rname) | 743 self:_uplift_history_format(player) |
| 699 end | 744 end |
| 700 end | 745 end |
| 701 end | 746 end |
| 702 self._uplift_history_format = nil | 747 self._uplift_history_format = nil |
| 703 --OuroLootSV_hist = nil | 748 --OuroLootSV_hist = nil |
| 801 -- frame-ness, which would slow down all printing and only rarely be useful. | 846 -- frame-ness, which would slow down all printing and only rarely be useful. |
| 802 -- | 847 -- |
| 803 -- There is no ITEM_QUALITY_LEGENDARY constant. Sigh. | 848 -- There is no ITEM_QUALITY_LEGENDARY constant. Sigh. |
| 804 do | 849 do |
| 805 local AC = LibStub("AceConsole-3.0") | 850 local AC = LibStub("AceConsole-3.0") |
| 806 local chat_prefix = self.format_hypertext('openloot',"Ouro Loot",--[[legendary]]5) | 851 local chat_prefix = self.format_hypertext ("Ouro Loot", --[[legendary]]5, |
| 852 --[[empty -> nil -> main tab]]'') | |
| 853 local chat_prefix_s = tostring(chat_prefix) | |
| 807 function addon:Print (str, ...) | 854 function addon:Print (str, ...) |
| 808 if type(str) == 'string' and str:find("%", nil, --[[plainmatch=]]true) then | 855 if type(str) == 'string' and str:find("%", nil, --[[plainmatch=]]true) then |
| 809 return AC:Print (chat_prefix, str:format(...)) | 856 return AC:Print (chat_prefix_s, str:format(...)) |
| 810 else | 857 else |
| 811 return AC:Print (chat_prefix, str, ...) | 858 return AC:Print (chat_prefix_s, str, ...) |
| 812 end | 859 end |
| 813 end | 860 end |
| 814 function addon:CFPrint (frame, str, ...) | 861 function addon:CFPrint (frame, str, ...) |
| 815 assert(type(frame)=='table' and frame.AddMessage) | 862 assert(type(frame)=='table' and frame.AddMessage) |
| 816 if type(str) == 'string' and str:find("%", nil, --[[plainmatch=]]true) then | 863 if type(str) == 'string' and str:find("%", nil, --[[plainmatch=]]true) then |
| 817 return AC:Print (frame, chat_prefix, str:format(...)) | 864 return AC:Print (frame, chat_prefix_s, str:format(...)) |
| 818 else | 865 else |
| 819 return AC:Print (frame, chat_prefix, str, ...) | 866 return AC:Print (frame, chat_prefix_s, str, ...) |
| 820 end | 867 end |
| 821 end | 868 end |
| 822 end | 869 end |
| 823 | 870 |
| 824 while opts.keybinding do | 871 while opts.keybinding do |
| 825 if InCombatLockdown() then | 872 if InCombatLockdown() then |
| 873 local reload = self.format_hypertext ([[the options tab]], | |
| 874 ITEM_QUALITY_UNCOMMON, 'opt') | |
| 826 self:Print("Cannot create '%s' as a keybinding while in combat!", | 875 self:Print("Cannot create '%s' as a keybinding while in combat!", |
| 827 opts.keybinding_text) | 876 opts.keybinding_text) |
| 828 self:Print("The rest of the addon will continue to work, but you will need to reload out of combat to get the keybinding. Either type /reload or use the button on %s in the lower right.", self.format_hypertext('reload',"the options tab",ITEM_QUALITY_UNCOMMON)) | 877 self:Print("The rest of the addon will continue to work, but you will need to reload out of combat to get the keybinding. Either type /reload or use the button on %s in the lower right.", |
| 878 tostring(reload)) | |
| 829 break | 879 break |
| 830 end | 880 end |
| 831 | 881 |
| 832 KeyBindingFrame_LoadUI() | 882 KeyBindingFrame_LoadUI() |
| 833 local btn = CreateFrame("Button", "OuroLootBindingOpen", nil, "SecureActionButtonTemplate") | 883 local btn = CreateFrame("Button", "OuroLootBindingOpen", nil, "SecureActionButtonTemplate") |
| 856 | 906 |
| 857 The SELF variants can be replaced with LOOT_ITEM_PUSHED_SELF[_MULTIPLE] to | 907 The SELF variants can be replaced with LOOT_ITEM_PUSHED_SELF[_MULTIPLE] to |
| 858 trigger on 'receive item' instead, which would detect extracting stuff | 908 trigger on 'receive item' instead, which would detect extracting stuff |
| 859 from mail, or s/PUSHED/CREATED/ for things like healthstones and guild | 909 from mail, or s/PUSHED/CREATED/ for things like healthstones and guild |
| 860 cauldron flasks. | 910 cauldron flasks. |
| 911 | |
| 912 ??? do something with LOOT_ITEM_WHILE_PLAYER_INELIGIBLE for locked LFRs? | |
| 861 ]] | 913 ]] |
| 862 | 914 |
| 863 -- LOOT_ITEM = "%s receives loot: %s." --> (.+) receives loot: (.+)%. | 915 -- LOOT_ITEM = "%s receives loot: %s." --> (.+) receives loot: (.+)%. |
| 864 g_LOOT_ITEM_ss = _G.LOOT_ITEM:gsub('%.$','%%.'):gsub('%%s','(.+)') | 916 g_LOOT_ITEM_ss = _G.LOOT_ITEM:gsub('%.$','%%.'):gsub('%%s','(.+)') |
| 865 | 917 |
| 1198 instance=addon.latest_instance, duration=0, | 1250 instance=addon.latest_instance, duration=0, |
| 1199 raidersnap=ss, maxsize=max | 1251 raidersnap=ss, maxsize=max |
| 1200 }) | 1252 }) |
| 1201 end | 1253 end |
| 1202 | 1254 |
| 1255 -- Alert other trackers that unique tag EXISTING in subsequent 'casts | |
| 1256 -- should be replaced by REPLACE instead. If multiple players all saw | |
| 1257 -- the same loot event, this will cause a flurry of cross-improvs. | |
| 1258 local function _announce_unique_improvisation (existing, replace) | |
| 1259 if not g_unique_replace then _setup_unique_replace() end | |
| 1260 g_unique_replace.new_entry (g_unique_replace.me, existing, replace, 'improv') | |
| 1261 addon:vbroadcast('improv', g_unique_replace.me, existing, replace) | |
| 1262 end | |
| 1263 | |
| 1203 local random = _G.math.random | 1264 local random = _G.math.random |
| 1204 local function many_uniques_handle_it (u, check_p) | 1265 local function _many_uniques_handle_it (u, prefix) |
| 1205 if u and check_p then | 1266 if u then |
| 1206 -- Check and alert for an existing value. | 1267 -- Check and alert for an existing value. |
| 1207 u = tostring(u) | 1268 u = tostring(u) |
| 1208 if g_uniques[u].history ~= g_uniques.NOTFOUND then | 1269 if g_uniques[u].history ~= g_uniques.NOTFOUND then |
| 1209 return nil, u | 1270 if not g_unique_replace then _setup_unique_replace() end |
| 1271 local maybe = g_unique_replace.get_previous_replacement (u) | |
| 1272 if maybe then | |
| 1273 addon.dprint('loot',"previous replaced tag ("..u | |
| 1274 ..") with ("..maybe.."), using that instead") | |
| 1275 return false, u, maybe | |
| 1276 end | |
| 1277 local can_replace_p,improv = _many_uniques_handle_it (nil, 'c') | |
| 1278 if can_replace_p then | |
| 1279 _announce_unique_improvisation (u, improv) | |
| 1280 return false, u, improv | |
| 1281 end | |
| 1282 return false, u | |
| 1210 end | 1283 end |
| 1211 addon.dprint('loot',"verified unique tag ("..u..")") | 1284 addon.dprint('loot',"verified unique tag ("..u..")") |
| 1212 else | 1285 else |
| 1213 -- Need to *find* an unused value. For now use a range of | 1286 -- Need to *find* an unused value. For now use a range of |
| 1214 -- J*10^4 where J is Jenny's Constant. Thank you, xkcd.com/1047. | 1287 -- J*10^4 where J is Jenny's Constant. Thank you, xkcd.com/1047. |
| 1288 prefix = prefix or 'n' | |
| 1215 repeat | 1289 repeat |
| 1216 u = 'n' .. random(8675309) | 1290 u = prefix .. random(8675309) |
| 1217 until g_uniques:TEST(u).history ~= g_uniques.NOTFOUND | 1291 until g_uniques:TEST(u).history == g_uniques.NOTFOUND |
| 1218 addon.dprint('loot',"created unique tag", u) | 1292 addon.dprint('loot',"created unique tag ("..u..")") |
| 1219 end | 1293 end |
| 1220 return true, u | 1294 return true, u |
| 1221 end | 1295 end |
| 1222 | 1296 |
| 1223 -- Recent loot cache | 1297 -- Recent loot cache |
| 1224 local candidates = {} | 1298 local candidates = {} |
| 1225 local sigmap = {} | 1299 local sigmap = {} |
| 1226 _G.sigmap = sigmap | |
| 1227 local function preempt_older_signature (oldersig, newersig) | 1300 local function preempt_older_signature (oldersig, newersig) |
| 1228 local origin = candidates[oldersig] and candidates[oldersig].from | 1301 --pprint("preempt", oldersig, "::", newersig) |
| 1302 local origin = candidates[oldersig] and candidates[oldersig].bcast_from | |
| 1303 --pprint("preempt", "candidate", candidates[oldersig], "bcast:", origin) | |
| 1229 if origin and g_seeing_oldsigs[origin] then | 1304 if origin and g_seeing_oldsigs[origin] then |
| 1230 -- replace entry from older client with this newer one | 1305 -- replace entry from older client with this newer one |
| 1231 candidates[oldersig] = nil | 1306 candidates[oldersig] = nil |
| 1232 addon.dprint('cache', "preempting signature <", oldersig, "> from", origin) | 1307 addon.dprint('loot', "preempting signature <", oldersig, "> from", origin) |
| 1233 end | 1308 end |
| 1234 return false | 1309 return false |
| 1235 end | 1310 end |
| 1236 | 1311 |
| 1237 local function prefer_local_loots (cache) | 1312 local function prefer_local_loots (cache) |
| 1251 if (loot.disposition ~= 'shard') | 1326 if (loot.disposition ~= 'shard') |
| 1252 and (loot.disposition ~= 'gvault') | 1327 and (loot.disposition ~= 'gvault') |
| 1253 and (not addon.history_suppress) | 1328 and (not addon.history_suppress) |
| 1254 then | 1329 then |
| 1255 addon:_addHistoryEntry(looti) | 1330 addon:_addHistoryEntry(looti) |
| 1331 elseif #loot.unique > 0 then | |
| 1332 g_uniques[loot.unique] = -- stub entry | |
| 1333 { loot = looti, history = g_uniques.NOTFOUND } | |
| 1256 end | 1334 end |
| 1257 end | 1335 end |
| 1258 end | 1336 end |
| 1259 | 1337 |
| 1260 if addon.display then | 1338 if addon.display then |
| 1283 itemid, "C:", count, "frm:", from, "ex:", extratext, "q:", iquality) | 1361 itemid, "C:", count, "frm:", from, "ex:", extratext, "q:", iquality) |
| 1284 | 1362 |
| 1285 itemid = tonumber(ilink:match("item:(%d+)") or 0) | 1363 itemid = tonumber(ilink:match("item:(%d+)") or 0) |
| 1286 | 1364 |
| 1287 -- This is only a 'while' to make jumping out of it easy. | 1365 -- This is only a 'while' to make jumping out of it easy. |
| 1288 local i, unique_okay, ret1, ret2 | 1366 local i, unique_okay, replacement, ret1, ret2 |
| 1289 while local_override | 1367 while local_override |
| 1290 or ((iquality >= self.threshold) and not opts.itemfilter[itemid]) | 1368 or ((iquality >= self.threshold) and not opts.itemfilter[itemid]) |
| 1291 do | 1369 do |
| 1292 unique_okay, unique = many_uniques_handle_it (unique, not local_override) | 1370 unique_okay, unique, replacement = |
| 1371 _many_uniques_handle_it ((not local_override) and unique) | |
| 1293 if not unique_okay then | 1372 if not unique_okay then |
| 1294 i = g_uniques[unique] | 1373 if replacement then |
| 1295 local err = unique_collision:format (ERROR_CAPS, iname, unique, | 1374 -- collision, but we've generated a placeholder for now |
| 1296 tostring(from), tostring(i.loot), tostring(i.history)) | 1375 -- and broadcast the fact |
| 1297 self:Print(err) | 1376 self.dprint('loot', "substituting", unique, "with", replacement) |
| 1298 _G.PlaySound("igQuestFailed", "master") | 1377 else |
| 1299 -- Make sure this is logged one way or another | 1378 i = g_uniques[unique] |
| 1300 ;(self.debug.loot and self.dprint or pprint)('loot', "COLLISION", prefix, err); | 1379 local err = unique_collision:format (ERROR_CAPS, iname, unique, |
| 1301 ret1, ret2 = nil, err | 1380 tostring(from), tostring(i.loot), tostring(i.history)) |
| 1302 break | 1381 self:Print(err) |
| 1382 _G.PlaySoundFile ([[Interface\AddOns\Ouro_Loot\sfrr.ogg]], "master") | |
| 1383 -- Make sure this is logged one way or another | |
| 1384 ;(self.debug.loot and self.dprint or pprint)('loot', "COLLISION", prefix, err); | |
| 1385 ret1, ret2 = nil, err | |
| 1386 break | |
| 1387 end | |
| 1303 end | 1388 end |
| 1304 | 1389 |
| 1305 if (self.rebroadcast and (not from)) and not local_override then | 1390 if (self.rebroadcast and (not from)) and not local_override then |
| 1306 self:vbroadcast('loot', recipient, unique, itemid, count) | 1391 self:vbroadcast('loot', recipient, unique, itemid, count) |
| 1307 end | 1392 end |
| 1310 local oldersig = recipient .. iname .. (count or "") | 1395 local oldersig = recipient .. iname .. (count or "") |
| 1311 local signature, seenit | 1396 local signature, seenit |
| 1312 if #unique > 0 then | 1397 if #unique > 0 then |
| 1313 -- newer case | 1398 -- newer case |
| 1314 signature = unique .. oldersig | 1399 signature = unique .. oldersig |
| 1400 --pprint("newer", "mapping older <", oldersig, "> to newer <", signature, ">") | |
| 1315 sigmap[oldersig] = signature | 1401 sigmap[oldersig] = signature |
| 1316 seenit = from and (recent_loot:test(signature) | 1402 --pprint("newer", "testing recent for", signature, "yields", recent_loot:test(signature)) |
| 1403 seenit = (from and recent_loot:test(signature)) | |
| 1317 -- The following clause is what handles older 'casts arriving | 1404 -- The following clause is what handles older 'casts arriving |
| 1318 -- earlier. All this is tested inside-out to maximize short | 1405 -- earlier. All this is tested inside-out to maximize short |
| 1319 -- circuit avaluation. | 1406 -- circuit evaluation; the preempt function always returns |
| 1320 or (g_seeing_oldsigs and preempt_older_signature(oldersig,signature))) | 1407 -- false to force seenit off. |
| 1408 or (g_seeing_oldsigs and preempt_older_signature(oldersig,signature)) | |
| 1321 else | 1409 else |
| 1322 -- older case, only remote | 1410 -- older case, only remote |
| 1323 assert(from) | 1411 assert(from) |
| 1324 signature = sigmap[oldersig] or oldersig | 1412 signature = sigmap[oldersig] or oldersig |
| 1413 --pprint("older", "testing signature will be", signature) | |
| 1325 seenit = recent_loot:test(signature) | 1414 seenit = recent_loot:test(signature) |
| 1326 end | 1415 end |
| 1327 | 1416 |
| 1328 if seenit then | 1417 if seenit then |
| 1329 self.dprint('cache', "remote", prefix, "<", signature, | 1418 self.dprint('cache', "remote", prefix, "<", signature, |
| 1340 quality = iquality, | 1429 quality = iquality, |
| 1341 itemname = iname, | 1430 itemname = iname, |
| 1342 id = itemid, | 1431 id = itemid, |
| 1343 itemlink = ilink, | 1432 itemlink = ilink, |
| 1344 itexture = itexture, | 1433 itexture = itexture, |
| 1345 unique = unique, | 1434 unique = replacement or unique, |
| 1346 count = (count and count ~= "") and count or nil, | 1435 count = (count and count ~= "") and count or nil, |
| 1347 bcast_from = from, | 1436 bcast_from = from, |
| 1348 extratext = extratext, | 1437 extratext = extratext, |
| 1349 variant = self:is_variant_item(ilink), | 1438 variant = self:is_variant_item(ilink), |
| 1350 } | 1439 } |
| 1366 if (i.disposition ~= 'shard') | 1455 if (i.disposition ~= 'shard') |
| 1367 and (i.disposition ~= 'gvault') | 1456 and (i.disposition ~= 'gvault') |
| 1368 and (not self.history_suppress) | 1457 and (not self.history_suppress) |
| 1369 then | 1458 then |
| 1370 self:_addHistoryEntry(looti) | 1459 self:_addHistoryEntry(looti) |
| 1460 else | |
| 1461 g_uniques[i.unique] = -- stub entry | |
| 1462 { loot = looti, history = g_uniques.NOTFOUND } | |
| 1371 end | 1463 end |
| 1372 ret1 = looti -- return value mostly for gui's manual entry | 1464 ret1 = looti -- return value mostly for gui's manual entry |
| 1465 self.dprint('loot', "manual", looti) | |
| 1373 else | 1466 else |
| 1374 recent_loot:add(signature) | 1467 recent_loot:add(signature) |
| 1375 candidates[signature] = i | 1468 candidates[signature] = i |
| 1376 tinsert (candidates, signature) | 1469 tinsert (candidates, signature) |
| 1377 self.dprint('cache', prefix, "<", signature, | 1470 self.dprint('cache', prefix, "<", signature, |
| 1446 ------ Slash command handler | 1539 ------ Slash command handler |
| 1447 -- Thought about breaking this up into a table-driven dispatcher. But | 1540 -- Thought about breaking this up into a table-driven dispatcher. But |
| 1448 -- that would result in a pile of teensy functions, most of which would | 1541 -- that would result in a pile of teensy functions, most of which would |
| 1449 -- never be called. Too much overhead. (2.0: Most of these removed now | 1542 -- never be called. Too much overhead. (2.0: Most of these removed now |
| 1450 -- that GUI is in place.) | 1543 -- that GUI is in place.) |
| 1451 function addon:OnSlash (txt) --, editbox) | 1544 do |
| 1452 txt = strtrim(txt:lower()) | 1545 local green_help_link = addon.format_hypertext ([[Click here]], |
| 1453 local cmd, arg = "" | 1546 ITEM_QUALITY_UNCOMMON, 'help') |
| 1454 do | 1547 function addon:OnSlash (txt) --, editbox) |
| 1455 local s,e = txt:find("^%a+") | 1548 txt = strtrim(txt:lower()) |
| 1456 if s then | 1549 local cmd, arg = "" |
| 1457 cmd = txt:sub(s,e) | 1550 do |
| 1458 s = txt:find("%S", e+2) | 1551 local s,e = txt:find("^%a+") |
| 1459 if s then arg = txt:sub(s,-1) end | 1552 if s then |
| 1460 end | 1553 cmd = txt:sub(s,e) |
| 1461 end | 1554 s = txt:find("%S", e+2) |
| 1462 | 1555 if s then arg = txt:sub(s,-1) end |
| 1463 if cmd == "" then | 1556 end |
| 1464 if InCombatLockdown() then | 1557 end |
| 1465 return self:Print("Shouldn't display window in combat.") | 1558 |
| 1559 if cmd == "" then | |
| 1560 if InCombatLockdown() then | |
| 1561 return self:Print("Shouldn't display window in combat.") | |
| 1562 else | |
| 1563 return self:BuildMainDisplay() | |
| 1564 end | |
| 1565 | |
| 1566 elseif cmd:find("^thre") then | |
| 1567 self:SetThreshold(arg) | |
| 1568 | |
| 1569 elseif cmd == "on" then self:Activate(arg) | |
| 1570 elseif cmd == "off" then self:Deactivate() | |
| 1571 elseif cmd == "broadcast" or cmd == "bcast" then self:Activate(nil,true) | |
| 1572 | |
| 1573 elseif cmd == "toggle" then | |
| 1574 if self.display then | |
| 1575 self.display:Hide() | |
| 1576 else | |
| 1577 return self:BuildMainDisplay() | |
| 1578 end | |
| 1579 | |
| 1580 elseif cmd == "fake" then -- maybe comment this out for real users | |
| 1581 self:_mark_boss_kill (self._addBossEntry{ | |
| 1582 kind='boss',reason='kill',bossname="Baron Steamroller",duration=0 | |
| 1583 }) | |
| 1584 self:CHAT_MSG_LOOT ('manual', my_name, 54797) | |
| 1585 if self.display then | |
| 1586 self:redisplay() | |
| 1587 end | |
| 1588 self:Print "Baron Steamroller has been slain. Congratulations on your rug." | |
| 1589 | |
| 1590 elseif cmd == "debug" then | |
| 1591 if arg then | |
| 1592 self.debug[arg] = not self.debug[arg] | |
| 1593 _G.print(arg,self.debug[arg]) | |
| 1594 if self.debug[arg] then self.DEBUG_PRINT = true end | |
| 1595 else | |
| 1596 self.DEBUG_PRINT = not self.DEBUG_PRINT | |
| 1597 end | |
| 1598 | |
| 1599 elseif cmd == "save" and arg and arg:len() > 0 then | |
| 1600 self:save_saveas(arg) | |
| 1601 elseif cmd == "list" then | |
| 1602 self:save_list() | |
| 1603 elseif cmd == "restore" and arg and arg:len() > 0 then | |
| 1604 self:save_restore(tonumber(arg)) | |
| 1605 elseif cmd == "delete" and arg and arg:len() > 0 then | |
| 1606 self:save_delete(tonumber(arg)) | |
| 1607 | |
| 1608 elseif cmd == "help" then | |
| 1609 self:BuildMainDisplay('help') | |
| 1610 elseif cmd == "ping" then | |
| 1611 self:DoPing() | |
| 1612 | |
| 1613 elseif cmd == "fixcache" then | |
| 1614 self:do_item_cache_fixup() | |
| 1615 | |
| 1466 else | 1616 else |
| 1467 return self:BuildMainDisplay() | 1617 if self:OpenMainDisplayToTab(cmd) then |
| 1468 end | 1618 return |
| 1469 | 1619 end |
| 1470 elseif cmd:find("^thre") then | 1620 self:Print("Unknown command '%s'. %s to see the help window.", |
| 1471 self:SetThreshold(arg) | 1621 cmd, tostring(green_help_link)) |
| 1472 | 1622 end |
| 1473 elseif cmd == "on" then self:Activate(arg) | |
| 1474 elseif cmd == "off" then self:Deactivate() | |
| 1475 elseif cmd == "broadcast" or cmd == "bcast" then self:Activate(nil,true) | |
| 1476 | |
| 1477 elseif cmd == "toggle" then | |
| 1478 if self.display then | |
| 1479 self.display:Hide() | |
| 1480 else | |
| 1481 return self:BuildMainDisplay() | |
| 1482 end | |
| 1483 | |
| 1484 elseif cmd == "fake" then -- maybe comment this out for real users | |
| 1485 self:_mark_boss_kill (self._addBossEntry{ | |
| 1486 kind='boss',reason='kill',bossname="Baron Steamroller",duration=0 | |
| 1487 }) | |
| 1488 self:CHAT_MSG_LOOT ('manual', my_name, 54797) | |
| 1489 if self.display then | |
| 1490 self:redisplay() | |
| 1491 end | |
| 1492 self:Print "Baron Steamroller has been slain. Congratulations on your rug." | |
| 1493 | |
| 1494 elseif cmd == "debug" then | |
| 1495 if arg then | |
| 1496 self.debug[arg] = not self.debug[arg] | |
| 1497 _G.print(arg,self.debug[arg]) | |
| 1498 if self.debug[arg] then self.DEBUG_PRINT = true end | |
| 1499 else | |
| 1500 self.DEBUG_PRINT = not self.DEBUG_PRINT | |
| 1501 end | |
| 1502 | |
| 1503 elseif cmd == "save" and arg and arg:len() > 0 then | |
| 1504 self:save_saveas(arg) | |
| 1505 elseif cmd == "list" then | |
| 1506 self:save_list() | |
| 1507 elseif cmd == "restore" and arg and arg:len() > 0 then | |
| 1508 self:save_restore(tonumber(arg)) | |
| 1509 elseif cmd == "delete" and arg and arg:len() > 0 then | |
| 1510 self:save_delete(tonumber(arg)) | |
| 1511 | |
| 1512 elseif cmd == "help" then | |
| 1513 self:BuildMainDisplay('help') | |
| 1514 elseif cmd == "ping" then | |
| 1515 self:DoPing() | |
| 1516 | |
| 1517 elseif cmd == "fixcache" then | |
| 1518 self:do_item_cache_fixup() | |
| 1519 | |
| 1520 else | |
| 1521 if self:OpenMainDisplayToTab(cmd) then | |
| 1522 return | |
| 1523 end | |
| 1524 self:Print("Unknown command '%s'. %s to see the help window.", | |
| 1525 cmd, self.format_hypertext('help',"Click here",ITEM_QUALITY_UNCOMMON)) | |
| 1526 end | 1623 end |
| 1527 end | 1624 end |
| 1528 | 1625 |
| 1529 function addon:SetThreshold (arg, quiet_p) | 1626 function addon:SetThreshold (arg, quiet_p) |
| 1530 local q = tonumber(arg) | 1627 local q = tonumber(arg) |
| 1531 if q then | 1628 if q then |
| 1532 q = math.floor(q+0.001) | 1629 q = math.floor(q+0.1) |
| 1533 if q<0 or q>6 then | 1630 if q<0 or q>6 then |
| 1534 return self:Print("Threshold must be 0-6.") | 1631 return self:Print("Threshold must be 0-6.") |
| 1535 end | 1632 end |
| 1536 else | 1633 else |
| 1537 q = qualnames[arg] | 1634 q = qualnames[arg] |
| 1553 self.popped = true | 1650 self.popped = true |
| 1554 if GetNumRaidMembers() > 0 then | 1651 if GetNumRaidMembers() > 0 then |
| 1555 self.dprint('flow', ">:Activate calling RRU") | 1652 self.dprint('flow', ">:Activate calling RRU") |
| 1556 self:RAID_ROSTER_UPDATE("Activate") | 1653 self:RAID_ROSTER_UPDATE("Activate") |
| 1557 elseif self.debug.notraid then | 1654 elseif self.debug.notraid then |
| 1558 self.dprint('flow', ">:Activate registering loot and bossmods") | 1655 self.dprint('flow', ">:(notraid) Activate registering loot and bossmods") |
| 1559 self:RegisterEvent("CHAT_MSG_LOOT") | 1656 self:RegisterEvent("CHAT_MSG_LOOT") |
| 1560 _register_bossmod(self) | 1657 _register_bossmod(self) |
| 1561 elseif g_restore_p then | 1658 elseif g_restore_p then |
| 1562 g_restore_p = nil | 1659 g_restore_p = nil |
| 1563 self.popped = nil -- get the reminder if later joining a raid | 1660 self.popped = nil -- get the reminder if later joining a raid |
| 1624 | 1721 |
| 1625 | 1722 |
| 1626 ------ Behind the scenes routines | 1723 ------ Behind the scenes routines |
| 1627 -- Semi-experimental debugging aid. | 1724 -- Semi-experimental debugging aid. |
| 1628 do | 1725 do |
| 1629 -- Putting _log local to here can result in this sequence: | 1726 -- Declaring _log as local to here can result in this sequence: |
| 1630 -- 1) logging happens, followed by reload or logout/login | 1727 -- 1) logging happens, followed by reload or logout/login |
| 1631 -- 2) _log points to SV_log | 1728 -- 2) _log points to SV_log |
| 1632 -- 3) VARIABLES_LOADED replaces SV_log pointer with restored version | 1729 -- 3) VARIABLES_LOADED replaces SV_log pointer with restored version |
| 1633 -- 4) logging happens to _log table (now with no other references) | 1730 -- 4) logging happens to _log table (now with no other references) |
| 1634 -- 5) at logout, nothing new has been entered in the table being saved | 1731 -- 5) at logout, nothing new has been entered in the table being saved |
| 1705 to_text = "normal" | 1802 to_text = "normal" |
| 1706 end | 1803 end |
| 1707 to_color = addon.disposition_colors[e.disposition or "normal"].hex | 1804 to_color = addon.disposition_colors[e.disposition or "normal"].hex |
| 1708 end | 1805 end |
| 1709 | 1806 |
| 1807 addon.dprint ('loot', "notifying:", sender, index, | |
| 1808 e.itemlink, from_color, from_text, to_color, to_text) | |
| 1710 addon:CFPrint (remote_change_chatframe, remote_chatty, sender, index, | 1809 addon:CFPrint (remote_change_chatframe, remote_chatty, sender, index, |
| 1711 e.itemlink, from_color, from_text, to_color, to_text) | 1810 e.itemlink, from_color, from_text, to_color, to_text) |
| 1712 end | 1811 end |
| 1713 end | 1812 end |
| 1714 | 1813 |
| 1753 elseif otherrev < revision_large then | 1852 elseif otherrev < revision_large then |
| 1754 self.dprint('comm', "ours is newer, notifying") | 1853 self.dprint('comm', "ours is newer, notifying") |
| 1755 self:broadcast('revcheck',revision_large) | 1854 self:broadcast('revcheck',revision_large) |
| 1756 | 1855 |
| 1757 else | 1856 else |
| 1758 self.dprint('comm', "ours is older, yammering") | 1857 self.dprint('comm', "ours is older, (possibly) yammering") |
| 1759 if newer_warning then | 1858 if newer_warning then |
| 1760 self:Print(newer_warning, | 1859 local pop = addon.format_hypertext ([[click here]], ITEM_QUALITY_UNCOMMON, |
| 1761 self.format_hypertext('popupurl',"click here",ITEM_QUALITY_UNCOMMON), | 1860 function() |
| 1762 self.format_hypertext('doping',"click here",ITEM_QUALITY_UNCOMMON)) | 1861 -- Sadly, this is not generated by the packager, so hardcode it for now. |
| 1862 -- The 'data' field is handled differently for onshow than for other callbacks. | |
| 1863 StaticPopup_Show("OUROL_URL", --[[text_arg1=]]nil, --[[text_arg2=]]nil, | |
| 1864 --[[data=]][[http://www.curse.com/addons/wow/ouroloot]]) | |
| 1865 end) | |
| 1866 local ping = addon.format_hypertext ([[click here]], ITEM_QUALITY_UNCOMMON, 'DoPing') | |
| 1867 self:Print(newer_warning, tostring(pop), tostring(ping)) | |
| 1763 newer_warning = nil | 1868 newer_warning = nil |
| 1764 end | 1869 end |
| 1765 end | 1870 end |
| 1766 end | 1871 end |
| 1767 | 1872 |
| 2016 end | 2121 end |
| 2017 | 2122 |
| 2018 function addon:register_boss_mod (name, registration_func, deregistration_func) | 2123 function addon:register_boss_mod (name, registration_func, deregistration_func) |
| 2019 assert(type(name)=='string') | 2124 assert(type(name)=='string') |
| 2020 assert(type(registration_func)=='function') | 2125 assert(type(registration_func)=='function') |
| 2021 if deregistration_func ~= nil then assert(type(deregistration_func)=='function') end | 2126 if deregistration_func ~= nil then |
| 2127 assert(type(deregistration_func)=='function') | |
| 2128 end | |
| 2022 self.bossmods[#self.bossmods+1] = { | 2129 self.bossmods[#self.bossmods+1] = { |
| 2023 n = name, | 2130 n = name, |
| 2024 r = registration_func, | 2131 r = registration_func, |
| 2025 d = deregistration_func, | 2132 d = deregistration_func, |
| 2026 } | 2133 } |
| 2233 e.cache_miss = nil | 2340 e.cache_miss = nil |
| 2234 if e.unique then | 2341 if e.unique then |
| 2235 local gu = g_uniques[e.unique] | 2342 local gu = g_uniques[e.unique] |
| 2236 local player_i, player_h, hist_i = _history_by_loot_id (e.unique, "fixcache") | 2343 local player_i, player_h, hist_i = _history_by_loot_id (e.unique, "fixcache") |
| 2237 if gu.loot ~= i then -- is this an actual problem? | 2344 if gu.loot ~= i then -- is this an actual problem? |
| 2238 pprint('loot', ("Unique value '%s' had iterator value %d but g_uniques index %s."):format(e.unique,i,tostring(gu.loot))) | 2345 pprint ('loot', |
| 2346 ("Unique value '%s' had iterator value %d but g_uniques index %s."): | |
| 2347 format(e.unique,i,tostring(gu.loot))) | |
| 2239 end | 2348 end |
| 2240 if player_i then | 2349 if player_i then |
| 2241 player_h.id[e.unique] = e.id | 2350 player_h.id[e.unique] = e.id |
| 2242 msg = [[ Entry %d (and history) patched up with %s.]] | 2351 msg = [[ Entry %d (and history) patched up with %s.]] |
| 2243 end | 2352 end |
| 2246 end | 2355 end |
| 2247 break | 2356 break |
| 2248 end end | 2357 end end |
| 2249 | 2358 |
| 2250 self:Print("...finished. Found %d |4entry:entries; with weird data.", numfound) | 2359 self:Print("...finished. Found %d |4entry:entries; with weird data.", numfound) |
| 2360 end | |
| 2361 | |
| 2362 do | |
| 2363 local gur | |
| 2364 | |
| 2365 -- Strictly speaking, we'd want to handle individual 'exist' entries | |
| 2366 -- as they expire, rather then waiting for all of them to expire and then | |
| 2367 -- doing them as a group. But, if there're more than one of these per | |
| 2368 -- boss, something else is funky anyhow and certainly not a hurry. | |
| 2369 local function fixup_unique_replacements() | |
| 2370 --print("replacements fixup happening!") | |
| 2371 --tabledump(g_unique_replace.replacements) | |
| 2372 --_G.GRR = g_unique_replace.replacements | |
| 2373 for exist,info in pairs(gur.replacements) do | |
| 2374 local winning_index = 1 | |
| 2375 local winner = info[1] | |
| 2376 info[1] = nil | |
| 2377 pprint('improv', "fixup for", exist, "starting with", winner[1], | |
| 2378 "with", winner[2], "out of", #info, "total entries") | |
| 2379 -- Lowest player GUID wins. Seniority gotta count for something. | |
| 2380 for i = 2, #info do | |
| 2381 if winner[1] <= info[i][1] then | |
| 2382 pprint('improv', "champ wins against", i, info[i][1]) | |
| 2383 flib.del(info[i]) | |
| 2384 else | |
| 2385 pprint('improv', "challenger wins with", i, info[i][1]) | |
| 2386 flib.del(winner) | |
| 2387 winner = info[i] | |
| 2388 winning_index = i | |
| 2389 end | |
| 2390 info[i] = nil | |
| 2391 end | |
| 2392 pprint('improv', "final:", winner[1], winner[2]) | |
| 2393 --[[ | |
| 2394 A: winner was generated locally | |
| 2395 >g_loot and history already has the replacement value | |
| 2396 >winning_index == 1 | |
| 2397 B: winner was generated remotely | |
| 2398 >need to scan and replace | |
| 2399 ]] | |
| 2400 if winning_index ~= 1 then | |
| 2401 --XXX still needs to be debugged: | |
| 2402 local cache = g_uniques[exist] | |
| 2403 local looti = assert(cache.loot) -- can't possibly be missing... | |
| 2404 if g_loot[looti].unique ~= exist then | |
| 2405 pprint('improv', "WTF. entry", looti, | |
| 2406 "does not match original unique tag! instead", | |
| 2407 g_loot[looti].unique) | |
| 2408 else | |
| 2409 pprint('improv', "found and replaced loot entry", looti) | |
| 2410 g_loot[looti].unique = winner[2] | |
| 2411 end | |
| 2412 local hi,ui = cache.history, cache.history_may | |
| 2413 if hi ~= g_uniques.NOTFOUND then | |
| 2414 local hist = addon.history[hi] | |
| 2415 if ui and hist.unique[ui] == exist then | |
| 2416 -- ui is valid | |
| 2417 else | |
| 2418 ui = nil | |
| 2419 for i,ui2 in ipairs(hist.unique) do | |
| 2420 if ui2 == exist then | |
| 2421 ui = i | |
| 2422 break | |
| 2423 end | |
| 2424 end | |
| 2425 end | |
| 2426 if ui then | |
| 2427 pprint('improv', "found and replacing history entry", hi, | |
| 2428 ui, hist.name) | |
| 2429 hist.when[winner[2]] = hist.when[exist] | |
| 2430 hist.id[winner[2]] = hist.id[exist] | |
| 2431 hist.count[winner[2]] = hist.count[exist] | |
| 2432 hist.unique[ui] = winner[2] | |
| 2433 hist.when[exist] = nil | |
| 2434 hist.id[exist] = nil | |
| 2435 hist.count[exist] = nil | |
| 2436 end | |
| 2437 end | |
| 2438 end | |
| 2439 pprint('improv', "finished with", exist, "into", winner[2]) | |
| 2440 flib.del(winner) | |
| 2441 flib.del(info) | |
| 2442 gur.replacements[exist] = nil | |
| 2443 end | |
| 2444 end | |
| 2445 | |
| 2446 local function new_entry (id, exist, repl, is_local) | |
| 2447 pprint('improv', "new_entry", id, exist, repl, is_local) | |
| 2448 gur.replacements[exist] = gur.replacements[exist] or flib.new() | |
| 2449 tinsert (gur.replacements[exist], flib.new (tonumber(id), repl)) | |
| 2450 if is_local then | |
| 2451 gur.replacements[exist].LOCAL = repl | |
| 2452 end | |
| 2453 gur.cache:add (exist) | |
| 2454 end | |
| 2455 | |
| 2456 local function get_previous_replacement (exist) | |
| 2457 local l = gur.replacements[exist] | |
| 2458 if l and l.LOCAL then | |
| 2459 pprint('improv', "check for previous", exist, "returns valid", | |
| 2460 l.LOCAL) | |
| 2461 return l.LOCAL | |
| 2462 end | |
| 2463 pprint('improv', "check for previous", exist, "returns nil") | |
| 2464 end | |
| 2465 | |
| 2466 function _setup_unique_replace () | |
| 2467 gur = {} | |
| 2468 gur.cache = create_new_cache ('improv', 10, fixup_unique_replacements) | |
| 2469 gur.me = tonumber(_G.UnitGUID('player'):sub(-7),16) | |
| 2470 gur.replacements = {} | |
| 2471 gur.new_entry = new_entry | |
| 2472 gur.get_previous_replacement = get_previous_replacement | |
| 2473 g_unique_replace = gur | |
| 2474 _setup_unique_replace = nil | |
| 2475 end | |
| 2251 end | 2476 end |
| 2252 | 2477 |
| 2253 | 2478 |
| 2254 ------ Saved texts | 2479 ------ Saved texts |
| 2255 function addon:check_saved_table(silent_p) | 2480 function addon:check_saved_table(silent_p) |
| 2343 -- [2] = { ......., [count = "x3"] } -- previous loot | 2568 -- [2] = { ......., [count = "x3"] } -- previous loot |
| 2344 -- which was much easier to manipulate, but had a ton of memory overhead. | 2569 -- which was much easier to manipulate, but had a ton of memory overhead. |
| 2345 do | 2570 do |
| 2346 -- Sorts a player's history from newest to oldest, according to the | 2571 -- Sorts a player's history from newest to oldest, according to the |
| 2347 -- formatted timestamp. This is expensive, and destructive for P.unique. | 2572 -- formatted timestamp. This is expensive, and destructive for P.unique. |
| 2573 local function compare_timestamps (L, R) | |
| 2574 return L > R -- reverse of normal order, newest first | |
| 2575 end | |
| 2348 local function sort_player (p) | 2576 local function sort_player (p) |
| 2349 local new_uniques, uniques_bywhen, when_array = {}, {}, {} | 2577 local new_uniques, uniques_bywhen, when_array = {}, {}, {} |
| 2350 for u,tstamp in pairs(p.when) do | 2578 for u,tstamp in pairs(p.when) do |
| 2351 uniques_bywhen[tstamp] = u | 2579 uniques_bywhen[tstamp] = u |
| 2352 when_array[#when_array+1] = tstamp | 2580 when_array[#when_array+1] = tstamp |
| 2353 end | 2581 end |
| 2354 _G.table.sort(when_array) | 2582 _G.table.sort (when_array, compare_timestamps) |
| 2355 for i,tstamp in ipairs(when_array) do | 2583 for i,tstamp in ipairs(when_array) do |
| 2356 new_uniques[i] = uniques_bywhen[tstamp] | 2584 new_uniques[i] = uniques_bywhen[tstamp] |
| 2357 end | 2585 end |
| 2358 p.unique = new_uniques | 2586 p.unique = new_uniques |
| 2359 end | 2587 end |
| 2360 | 2588 |
| 2361 -- Possibly called during login. Cleared when no longer needed. | 2589 -- Possibly called during login. Cleared when no longer needed. |
| 2362 -- Rewrites a PLAYER table from format 3 to format 4. | 2590 -- Rewrites a PLAYER table from format 3 to format 4. |
| 2363 function addon:_uplift_history_format (player, realmname) | 2591 function addon:_uplift_history_format (player) |
| 2364 local unique, when, id, count = {}, {}, {}, {} | 2592 local unique, when, id, count = {}, {}, {}, {} |
| 2365 local name = player.name | 2593 local name = player.name |
| 2366 | 2594 |
| 2367 for i,h in ipairs(player) do | 2595 for i,h in ipairs(player) do |
| 2368 local U = h.unique | 2596 local U = h.unique |
| 2375 wipe(player) | 2603 wipe(player) |
| 2376 player.name = name | 2604 player.name = name |
| 2377 player.id, player.when, player.unique, player.count = | 2605 player.id, player.when, player.unique, player.count = |
| 2378 id, when, unique, count | 2606 id, when, unique, count |
| 2379 end | 2607 end |
| 2608 | |
| 2380 function addon:_cache_history_uniques() | 2609 function addon:_cache_history_uniques() |
| 2381 UpdateAddOnMemoryUsage() | 2610 UpdateAddOnMemoryUsage() |
| 2382 local before = GetAddOnMemoryUsage(nametag) | 2611 local before = GetAddOnMemoryUsage(nametag) |
| 2383 local trouble | 2612 local trouble |
| 2384 local count = 0 | 2613 local count = 0 |
| 2396 elseif e.disposition == 'shard' or e.disposition == 'gvault' then | 2625 elseif e.disposition == 'shard' or e.disposition == 'gvault' then |
| 2397 g_uniques[e.unique] = { loot = i, history = g_uniques.NOTFOUND } | 2626 g_uniques[e.unique] = { loot = i, history = g_uniques.NOTFOUND } |
| 2398 count = count + 1 | 2627 count = count + 1 |
| 2399 --print("Active loot", i, "INSERTED with tag", e.unique, "as", e.disposition) | 2628 --print("Active loot", i, "INSERTED with tag", e.unique, "as", e.disposition) |
| 2400 else | 2629 else |
| 2401 hmmm = "wonked data ("..i.."/"..tostring(e.unique)..") in precache loop!" | 2630 hmmm = "active data not found in history ("..i.."/"..tostring(e.unique) |
| 2402 pprint(hmmm) | 2631 ..") in precache loop! trying to fixup for this session" |
| 2632 pprint(hmmm) -- more? | |
| 2403 -- try to simply fix up errors as we go | 2633 -- try to simply fix up errors as we go |
| 2404 g_uniques[e.unique] = { loot = i, history = g_uniques.NOTFOUND } | 2634 g_uniques[e.unique] = { loot = i, history = g_uniques.NOTFOUND } |
| 2405 trouble = true | 2635 --trouble = true |
| 2406 end | 2636 end |
| 2407 else | 2637 else |
| 2408 trouble = true | 2638 trouble = true |
| 2409 pprint('loot', "ERROR precache loop found bad unique tag!", | 2639 pprint('loot', "ERROR precache loop found bad unique tag!", |
| 2410 i, "tag", tostring(e.unique), "from?", tostring(e.bcast_from)) | 2640 i, "tag", tostring(e.unique), "from?", tostring(e.bcast_from)) |
| 2515 for i,h in ipairs(self.history) do | 2745 for i,h in ipairs(self.history) do |
| 2516 sort_player(h) | 2746 sort_player(h) |
| 2517 end | 2747 end |
| 2518 end | 2748 end |
| 2519 | 2749 |
| 2520 -- Clears all but latest entry for each player. | 2750 -- Clears all but the most recent HOWMANY (optional, default 1) entries |
| 2521 function addon:preen_history (realmname) | 2751 -- for each player on REALMNAME. |
| 2752 -- This function's name is the legacy of the orignal fsck(8) "-p" option, | |
| 2753 -- which has a similar feel. | |
| 2754 function addon:preen_history (realmname, howmany) | |
| 2522 local r = assert(realmname) | 2755 local r = assert(realmname) |
| 2756 howmany = tonumber(howmany) or 1 | |
| 2757 if type(self.history_all[r]) ~= 'table' then | |
| 2758 return | |
| 2759 end | |
| 2523 g_uniques:RESET() | 2760 g_uniques:RESET() |
| 2524 for i,h in ipairs(self.history) do | 2761 for i,h in ipairs(self.history_all[r]) do |
| 2525 -- This is going to do horrible things to memory. The subtables | 2762 -- This is going to do horrible things to memory. The subtables |
| 2526 -- after this step would be large and sparse, with no good way | 2763 -- after this step would be large and sparse, with no good way |
| 2527 -- of shrinking the allocation... | 2764 -- of shrinking the allocation... |
| 2528 sort_player(h) | 2765 sort_player(h) |
| 2529 -- ...so it's better in the long run to discard them. | 2766 -- ...so it's better in the long run to discard them. |
| 2530 local U = h.unique[1] | 2767 local new_unique, new_id, new_when, new_count = {}, {}, {}, {} |
| 2531 h.unique = { U } | 2768 for ui = 1, howmany do |
| 2532 h.id = { [U] = h.id[U] } | 2769 local U = h.unique[ui] |
| 2533 h.when = { [U] = h.when[U] } | 2770 if not U then break end |
| 2534 h.count = { [U] = h.count[U] } | 2771 new_unique[ui] = U |
| 2772 new_id[U] = h.id[U] | |
| 2773 new_when[U] = h.when[U] | |
| 2774 new_count[U] = h.count[U] | |
| 2775 end | |
| 2776 h.unique, h.id, h.when, h.count = | |
| 2777 new_unique, new_id, new_when, new_count | |
| 2535 end | 2778 end |
| 2536 end | 2779 end |
| 2537 | 2780 |
| 2538 -- Given a unique tag OR an entry in a g_loot table, looks up the | 2781 -- Given a unique tag OR an entry in a g_loot table, looks up the |
| 2539 -- corresponding history entry. Returns the player's index and history | 2782 -- corresponding history entry. Returns the player's index and history |
| 2742 index = tonumber(cache.loot) | 2985 index = tonumber(cache.loot) |
| 2743 e = g_loot[index] | 2986 e = g_loot[index] |
| 2744 end | 2987 end |
| 2745 | 2988 |
| 2746 else | 2989 else |
| 2747 return -- silently ignore newer cases from newer clients | 2990 return -- silently ignore future cases from future clients |
| 2748 end | 2991 end |
| 2749 | 2992 |
| 2750 if self.debug.loot then | 2993 if self.debug.loot then |
| 2751 local m = ("Re-mark index %d(pre-unique %s) with id %d from '%s' to '%s'."): | 2994 local m = ("Re-mark index %d(pre-unique %s) with id %d from '%s' to '%s'."): |
| 2752 format(index, unique, id, tostring(olddisp), tostring(newdisp)) | 2995 format(index, unique, id, tostring(olddisp), tostring(newdisp)) |
| 2753 self.dprint('loot', m) | 2996 self.dprint('loot', m) |
| 2754 if sender == my_name then | 2997 if sender == my_name then |
| 2755 self.dprint('loot',"(Returning early from double self-mark.)") | 2998 self.dprint('loot',"(Returning early from debug mode's double self-mark.)") |
| 2756 return index | 2999 return index |
| 2757 end | 3000 end |
| 2758 end | 3001 end |
| 2759 | 3002 |
| 2760 if not e then | 3003 if not e then |
| 2778 | 3021 |
| 2779 ------ Player communication | 3022 ------ Player communication |
| 2780 do | 3023 do |
| 2781 local select, tconcat, strsplit, unpack = select, table.concat, strsplit, unpack | 3024 local select, tconcat, strsplit, unpack = select, table.concat, strsplit, unpack |
| 2782 --[[ old way: repeated string concatenations, BAD | 3025 --[[ old way: repeated string concatenations, BAD |
| 2783 new way: new table on every call, BAD | 3026 new way: new table on every broadcast, BAD |
| 2784 local msg = ... | 3027 local msg = ... |
| 2785 for i = 2, select('#',...) do | 3028 for i = 2, select('#',...) do |
| 2786 msg = msg .. '\a' .. (select(i,...) or "") | 3029 msg = msg .. '\a' .. (select(i,...) or "") |
| 2787 end | 3030 end |
| 2788 return msg | 3031 return msg |
| 2842 OCR_funcs.revcheck = function (sender, _, revlarge) | 3085 OCR_funcs.revcheck = function (sender, _, revlarge) |
| 2843 addon.dprint('comm', "revcheck, sender", sender) | 3086 addon.dprint('comm', "revcheck, sender", sender) |
| 2844 addon:_check_revision (revlarge) | 3087 addon:_check_revision (revlarge) |
| 2845 end | 3088 end |
| 2846 | 3089 |
| 3090 OCR_funcs['17improv'] = function (sender, _, senderid, existing, replace) | |
| 3091 addon.dprint('comm', "DOTimprov/17, sender", sender, "id", senderid, | |
| 3092 "existing", existing, "replace", replace) | |
| 3093 if not g_unique_replace then _setup_unique_replace() end | |
| 3094 g_unique_replace.new_entry (senderid, existing, replace) | |
| 3095 end | |
| 3096 | |
| 2847 OCR_funcs['17mark'] = function (sender, _, unique, item, old, new) | 3097 OCR_funcs['17mark'] = function (sender, _, unique, item, old, new) |
| 2848 addon.dprint('comm', "DOTmark/17, sender", sender, "unique", unique, | 3098 addon.dprint('comm', "DOTmark/17, sender", sender, "unique", unique, |
| 2849 "item", item, "from old", old, "to new", new) | 3099 "item", item, "from old", old, "to new", new) |
| 2850 local index = addon:loot_mark_disposition ("remote", sender, unique, item, old, new) | 3100 local index = addon:loot_mark_disposition ("remote", sender, unique, item, old, new) |
| 2851 --if not addon.enabled then return end -- hmm | 3101 --if not addon.enabled then return end -- hmm |
| 2888 adduser (sender, nil, true) | 3138 adduser (sender, nil, true) |
| 2889 addon:on_boss_broadcast (reason, bossname, instancetag, maxsize) | 3139 addon:on_boss_broadcast (reason, bossname, instancetag, maxsize) |
| 2890 end | 3140 end |
| 2891 OCR_funcs['17boss'] = OCR_funcs['16boss'] | 3141 OCR_funcs['17boss'] = OCR_funcs['16boss'] |
| 2892 | 3142 |
| 3143 local bcast_on = addon.format_hypertext ([[the red pill]], '|cffff4040', | |
| 3144 function() | |
| 3145 if not addon.rebroadcast then | |
| 3146 addon:Activate(nil,true) | |
| 3147 end | |
| 3148 addon:broadcast('bcast_responder') | |
| 3149 end) | |
| 3150 local waferthin = addon.format_hypertext ([[the blue pill]], '|cff0070dd', | |
| 3151 function() | |
| 3152 g_wafer_thin = true -- mint? it's wafer thin! | |
| 3153 addon:broadcast('bcast_denied') -- fuck off, I'm full | |
| 3154 end) | |
| 2893 OCR_funcs.bcast_req = function (sender) | 3155 OCR_funcs.bcast_req = function (sender) |
| 2894 if addon.debug.comm or ((not g_wafer_thin) and (not addon.rebroadcast)) | 3156 if addon.debug.comm or ((not g_wafer_thin) and (not addon.rebroadcast)) |
| 2895 then | 3157 then |
| 2896 addon:Print("%s has requested additional broadcasters! Choose %s to enable rebroadcasting, or %s to remain off and also ignore rebroadcast requests for as long as you're logged in.", | 3158 addon:Print("%s has requested additional broadcasters! Choose %s to enable rebroadcasting, or %s to remain off and also ignore rebroadcast requests for as long as you're logged in.", |
| 2897 sender, | 3159 sender, |
| 2898 addon.format_hypertext('bcaston',"the red pill",'|cffff4040'), | 3160 tostring(bcast_on), |
| 2899 addon.format_hypertext('waferthin',"the blue pill",'|cff0070dd')) | 3161 tostring(waferthin)) |
| 2900 end | 3162 end |
| 2901 addon.popped = true | 3163 addon.popped = true |
| 2902 end | 3164 end |
| 2903 | 3165 |
| 2904 OCR_funcs.bcast_responder = function (sender) | 3166 OCR_funcs.bcast_responder = function (sender) |
