Mercurial > wow > ouroloot
comparison core.lua @ 125:a9cf9b2fbf9b
- Fix interactions with AddonLoader.
- Plugins get a :Print with a clickable prefix, with overrideable behaviors.
- 'Deactivate' event gets a [wrapper around] current raiders table.
- Fix sorting bug in player history data.
- Smarter status line text when viewing unfiltered history.
- Do not disable history regeneration button when current history is empty.
- :BuildMainDisplay can handle the CLI args now.
| author | Farmbuyer of US-Kilrogg <farmbuyer@gmail.com> |
|---|---|
| date | Sun, 19 Aug 2012 21:08:59 -0400 |
| parents | fb4bda3ad05c |
| children | dc39ce56a62d |
comparison
equal
deleted
inserted
replaced
| 124:1a248faf1a3b | 125:a9cf9b2fbf9b |
|---|---|
| 19 - online 'online', 'offline', 'no_longer' [no longer in raid group] | 19 - online 'online', 'offline', 'no_longer' [no longer in raid group] |
| 20 [both of these next two fields use time_t values:] | 20 [both of these next two fields use time_t values:] |
| 21 - join time player joined the raid (or first time we've seen them) | 21 - join time player joined the raid (or first time we've seen them) |
| 22 - leave time player left the raid (or time we've left the raid, if | 22 - leave time player left the raid (or time we've left the raid, if |
| 23 'online' is not 'no_longer') | 23 'online' is not 'no_longer') |
| 24 - needinfo true if haven't yet gotten close enough to player to request | |
| 25 unit data; SHOULD be missing | |
| 24 | 26 |
| 25 Common g_loot entry indices: | 27 Common g_loot entry indices: |
| 26 - kind time/boss/loot | 28 - kind time/boss/loot |
| 27 - hour 0-23, on the *physical instance server*, not the realm server | 29 - hour 0-23, on the *physical instance server*, not the realm server |
| 28 - minute 0-59, ditto | 30 - minute 0-59, ditto |
| 442 -- COLOR can be ITEM_QUALITY_* or a formatting string ("|cff...") | 444 -- COLOR can be ITEM_QUALITY_* or a formatting string ("|cff...") |
| 443 -- FUNC can be "MethodName", "tab_title", or a function | 445 -- FUNC can be "MethodName", "tab_title", or a function |
| 444 -- | 446 -- |
| 445 -- Returns an opaque token and a matching number. Calling tostring() on | 447 -- Returns an opaque token and a matching number. Calling tostring() on |
| 446 -- the token will yield a formatted clickable string that can be displayed | 448 -- the token will yield a formatted clickable string that can be displayed |
| 447 -- in chat. The MethodName and raw function callbacks will both be | 449 -- in local chat. Clicking a tab_title hyperlink opens the GUI to that |
| 448 -- passed the addon table and the same matching number. | 450 -- tab; the MethodName and raw function callbacks will be passed the addon |
| 451 -- table, the same matching number, and the mouse button (ala OnClick) as | |
| 452 -- arguments. | |
| 449 -- | 453 -- |
| 450 -- This is largely an excuse to fool around with Lua data constructs. | 454 -- This is largely an excuse to fool around with Lua data constructs. |
| 451 function addon.format_hypertext (text, color, func) | 455 function addon.format_hypertext (text, color, func) |
| 452 local ret = newproxy(base) | 456 local ret = newproxy(base) |
| 453 local num = #text_map + 1 | 457 local num = #text_map + 1 |
| 471 DEFAULT_CHAT_FRAME:HookScript("OnHyperlinkClick", function(self, link, fullstring, mousebutton) | 475 DEFAULT_CHAT_FRAME:HookScript("OnHyperlinkClick", function(self, link, fullstring, mousebutton) |
| 472 local ltype, arg = strsplit(":",link) | 476 local ltype, arg = strsplit(":",link) |
| 473 if ltype ~= "OuroLoot" then return end | 477 if ltype ~= "OuroLoot" then return end |
| 474 arg = tonumber(arg) | 478 arg = tonumber(arg) |
| 475 local f = func_map[text_map[arg]] | 479 local f = func_map[text_map[arg]] |
| 476 if type(f) == 'function' then | 480 local t = type(f) |
| 477 f (addon, arg) | 481 if t == 'string' then |
| 478 elseif type(f) == 'string' then | |
| 479 if type(addon[f]) == 'function' then | 482 if type(addon[f]) == 'function' then |
| 480 addon[f](addon,arg) -- method name | 483 addon[f](addon,arg,mousebutton) -- method |
| 481 else | 484 else |
| 482 addon:BuildMainDisplay(f) -- tab title fragment | 485 addon:BuildMainDisplay(f) -- tab title fragment |
| 483 end | 486 end |
| 487 elseif t == 'function' then | |
| 488 f (addon, arg, mousebutton) | |
| 484 end | 489 end |
| 485 end) | 490 end) |
| 486 | 491 |
| 487 local old = ItemRefTooltip.SetHyperlink | 492 local old = ItemRefTooltip.SetHyperlink |
| 488 function ItemRefTooltip:SetHyperlink (link, ...) | 493 function ItemRefTooltip:SetHyperlink (link, ...) |
| 752 -- relogging during a raid and already have collected loot data | 757 -- relogging during a raid and already have collected loot data |
| 753 local OuroLootSV = OuroLootSV | 758 local OuroLootSV = OuroLootSV |
| 754 g_restore_p = OuroLootSV ~= nil | 759 g_restore_p = OuroLootSV ~= nil |
| 755 self.dprint('flow', "oninit sets restore as", g_restore_p) | 760 self.dprint('flow', "oninit sets restore as", g_restore_p) |
| 756 | 761 |
| 757 -- Primarily for plugins, but can be of use to me also... | 762 -- Primarily for plugins, but can be of use to me also... LCALLBACK |
| 758 self.callbacks = LibStub("CallbackHandler-1.0"):New(self) | 763 self.callbacks = LibStub("CallbackHandler-1.0"):New(self) |
| 759 --function self.callbacks:OnUsed (target_aka_self, eventname) end | 764 --function self.callbacks:OnUsed (target_aka_self, eventname) end |
| 760 --function self.callbacks:OnUnused (target_aka_self, eventname) end | 765 --function self.callbacks:OnUnused (target_aka_self, eventname) end |
| 761 | 766 |
| 762 if _G.OuroLootOptsDB == nil then | 767 if _G.OuroLootOptsDB == nil then |
| 868 | 873 |
| 869 function addon:OnEnable() | 874 function addon:OnEnable() |
| 870 self:RegisterEvent("PLAYER_LOGOUT") | 875 self:RegisterEvent("PLAYER_LOGOUT") |
| 871 self:RegisterEvent(RAID_ROSTER_UPDATE_EVENT,"RAID_ROSTER_UPDATE") | 876 self:RegisterEvent(RAID_ROSTER_UPDATE_EVENT,"RAID_ROSTER_UPDATE") |
| 872 | 877 |
| 873 -- Cribbed from Talented. I like the way jerry thinks: the first string | 878 -- This Print cribbed from Talented. I like the way jerry thinks: the |
| 874 -- argument can be a format spec for the remainder of the arguments. | 879 -- first string argument can be a format spec for the remainder of the |
| 875 -- AceConsole:Printf isn't used because we can't specify a prefix without | 880 -- arguments. AceConsole:Printf isn't used because we can't specify a |
| 876 -- jumping through ridonkulous hoops. The part about overriding :Print | 881 -- prefix without jumping through ridonkulous hoops. |
| 877 -- with a version using prefix hyperlinks is my fault. | 882 -- |
| 883 -- Everything dealing with a prefix hyperlink is my fault. | |
| 878 -- | 884 -- |
| 879 -- CFPrint added instead of the usual Print testing of the first arg for | 885 -- CFPrint added instead of the usual Print testing of the first arg for |
| 880 -- frame-ness, which would slow down all printing and only rarely be useful. | 886 -- frame-ness, which would slow down all printing and only rarely be useful. |
| 881 -- | 887 -- |
| 882 -- There is no ITEM_QUALITY_LEGENDARY constant. Sigh. | 888 -- There is no ITEM_QUALITY_LEGENDARY constant. Sigh. |
| 1010 Stick something in the Blizzard addons options list, where most users | 1016 Stick something in the Blizzard addons options list, where most users |
| 1011 will probably look these days. Try to be conservative about needless | 1017 will probably look these days. Try to be conservative about needless |
| 1012 frame creation. | 1018 frame creation. |
| 1013 ]] | 1019 ]] |
| 1014 local bliz = CreateFrame("Frame") | 1020 local bliz = CreateFrame("Frame") |
| 1015 bliz.name = "Ouro Loot" | 1021 bliz.name = "Ouro Loot" -- must match X-LoadOn-InterfaceOptions |
| 1022 if AddonLoader then | |
| 1023 AddonLoader:RemoveInterfaceOptions(bliz.name) | |
| 1024 end | |
| 1016 bliz:SetScript("OnShow", function(_b) | 1025 bliz:SetScript("OnShow", function(_b) |
| 1017 local button = CreateFrame("Button",nil,_b,"UIPanelButtonTemplate") | 1026 local button = CreateFrame("Button",nil,_b,"UIPanelButtonTemplate") |
| 1018 button:SetWidth(150) | 1027 button:SetWidth(150) |
| 1019 button:SetHeight(22) | 1028 button:SetHeight(22) |
| 1020 button:SetScript("OnClick", function() | 1029 button:SetScript("OnClick", function() |
| 1021 InterfaceOptionsFrameCancel:Click() | 1030 InterfaceOptionsFrameCancel:Click() |
| 1022 HideUIPanel(GameMenuFrame) | 1031 HideUIPanel(GameMenuFrame) |
| 1023 addon:OpenMainDisplayToTab"Options" | 1032 addon:BuildMainDisplay('opt') |
| 1024 end) | 1033 end) |
| 1025 button:SetText('"/ouroloot opt"') | 1034 button:SetText('"/ouroloot options"') |
| 1026 button:SetPoint("TOPLEFT",20,-20) | 1035 button:SetPoint("TOPLEFT",20,-20) |
| 1027 _b:SetScript("OnShow",nil) | 1036 _b:SetScript("OnShow",nil) |
| 1028 end) | 1037 end) |
| 1029 InterfaceOptions_AddCategory(bliz) | 1038 InterfaceOptions_AddCategory(bliz) |
| 1030 | 1039 |
| 1046 Module support (aka plugins). Field names with special meanings: | 1055 Module support (aka plugins). Field names with special meanings: |
| 1047 - option_defaults: (IN) Standard AceDB-style table. Use a profiles key! | 1056 - option_defaults: (IN) Standard AceDB-style table. Use a profiles key! |
| 1048 - db: (OUT) AceDB object, set during init. | 1057 - db: (OUT) AceDB object, set during init. |
| 1049 - opts: (OUT) Pointer to plugin's "db.profile" subtable. | 1058 - opts: (OUT) Pointer to plugin's "db.profile" subtable. |
| 1050 | 1059 |
| 1051 OnInitialize, [default_]OnEnable, register_text_generator, register_tab_control | 1060 Inherited unchanged: |
| 1052 are all inherited. | 1061 |
| 1062 Inherited module variants: | |
| 1063 - OnInitialize, OnEnable | |
| 1064 - register_text_generator, register_tab_control: also flag plugin as | |
| 1065 a text-generating module in main addon | |
| 1053 ]] | 1066 ]] |
| 1054 local prototype = {} | 1067 local prototype = {} |
| 1055 local registry | 1068 local textgen_registry, chat_prefixes, chat_codes |
| 1056 | 1069 |
| 1057 -- By default, no plugins. First one in sets up code for any after. | 1070 -- By default, no plugins. First one in sets up code for any after. |
| 1058 addon.get_plugin = flib.nullfunc | 1071 addon.get_textgen_plugin = flib.nullfunc |
| 1059 | 1072 |
| 1060 -- Fires before the plugin's own OnEnable (inherited or otherwise). | 1073 -- Called as part of NewModule, after embedding and metas are done. |
| 1074 -- Mostly this is one-time setup stuff that we don't need until a plugin | |
| 1075 -- is actually built. | |
| 1061 function addon:OnModuleCreated (plugin) | 1076 function addon:OnModuleCreated (plugin) |
| 1062 if not registry then | 1077 textgen_registry, chat_prefixes, chat_codes = {}, {}, {} |
| 1063 registry = {} | 1078 addon.get_textgen_plugin = function(a,t) |
| 1064 addon.get_plugin = function(a,t) return registry[t] end | 1079 return textgen_registry[t] |
| 1065 prototype.register_text_generator = function(p,t,...) | 1080 end |
| 1066 registry[t] = p | 1081 prototype.register_text_generator = function(p,t,...) |
| 1067 return addon:register_text_generator(t,...) | 1082 textgen_registry[t] = p |
| 1068 end | 1083 return addon:register_text_generator(t,...) |
| 1069 prototype.register_tab_control = function(p,t,...) | 1084 end |
| 1070 registry[t] = p | 1085 prototype.register_tab_control = function(p,t,...) |
| 1071 return addon:register_tab_control(t,...) | 1086 textgen_registry[t] = p |
| 1072 end | 1087 return addon:register_tab_control(t,...) |
| 1073 end | 1088 end |
| 1074 end | 1089 |
| 1075 | 1090 function addon:ModulePrefixClick (codenum, mousebutton) |
| 1076 local function module_OnInit (plugin) | 1091 local plugin = assert(chat_codes[codenum]) |
| 1092 if not plugin:IsEnabled() then return end | |
| 1093 if mousebutton == 'LeftButton' then | |
| 1094 if plugin.PrefixLeftClick then | |
| 1095 plugin:PrefixLeftClick(codenum) | |
| 1096 else | |
| 1097 self:BuildMainDisplay() | |
| 1098 end | |
| 1099 elseif mousebutton == 'RightButton' then | |
| 1100 local uniqueval = plugin.name | |
| 1101 if plugin.PrefixRightClick then | |
| 1102 uniqueval = plugin:PrefixRightClick(codenum) | |
| 1103 end | |
| 1104 self:BuildMainDisplay('opt',uniqueval) | |
| 1105 end | |
| 1106 end | |
| 1107 function addon:OnModuleCreated (plugin) | |
| 1108 local token, code = self.format_hypertext (plugin.moduleName, | |
| 1109 --[[heirloom]]7, "ModulePrefixClick") | |
| 1110 chat_prefixes[plugin] = token | |
| 1111 chat_codes[code] = plugin | |
| 1112 -- remove the libraries' embedded pointers so that the prototype | |
| 1113 -- can be inherited | |
| 1114 plugin.Print = nil | |
| 1115 end | |
| 1116 | |
| 1117 return self:OnModuleCreated(plugin) | |
| 1118 end | |
| 1119 | |
| 1120 function prototype.OnInitialize (plugin) | |
| 1077 if plugin.option_defaults then | 1121 if plugin.option_defaults then |
| 1078 plugin.db = addon.db:RegisterNamespace (plugin.moduleName, plugin.option_defaults) | 1122 plugin.db = addon.db:RegisterNamespace (plugin.moduleName, plugin.option_defaults) |
| 1079 plugin.opts = plugin.db.profile | 1123 plugin.opts = plugin.db.profile |
| 1080 --plugin:SetEnabledState(plugin.db.profile.enabled) if that flag is needed later | 1124 --plugin:SetEnabledState(plugin.db.profile.enabled) if that flag is needed later |
| 1081 end | 1125 end |
| 1082 end | 1126 end |
| 1083 | 1127 |
| 1084 local function module_OnEnable (plugin) | 1128 --function prototype.OnEnable (plugin) |
| 1085 end | 1129 --end |
| 1086 | 1130 |
| 1087 local function module_GetOption (plugin, info) | 1131 function prototype.GetOption (plugin, info) |
| 1088 local name = info[#info] | 1132 local name = info[#info] |
| 1089 return plugin.db.profile[name] | 1133 return plugin.db.profile[name] |
| 1090 end | 1134 end |
| 1091 local function module_SetOption (plugin, info, value) | 1135 function prototype.SetOption (plugin, info, value) |
| 1092 local name = info[#info] | 1136 local name = info[#info] |
| 1093 plugin.db.profile[name] = value | 1137 plugin.db.profile[name] = value |
| 1094 local arg = info.arg | 1138 local arg = info.arg |
| 1095 if type(arg) == 'function' then | 1139 if type(arg) == 'function' then |
| 1096 plugin[arg](plugin,info) | 1140 plugin[arg](plugin,info) |
| 1097 end | 1141 end |
| 1098 end | 1142 end |
| 1099 | 1143 |
| 1100 prototype.OnInitialize = module_OnInit | 1144 -- may eventually just rework the main print routines and inherit all 3 |
| 1101 prototype.OnEnable = module_OnEnable | 1145 function prototype.Print (plugin, str, ...) |
| 1102 prototype.default_OnEnable = module_OnEnable | 1146 local AC = LibStub("AceConsole-3.0") |
| 1103 prototype.GetOption = module_GetOption | 1147 local ps = tostring(chat_prefixes[plugin]) |
| 1104 prototype.SetOption = module_SetOption | 1148 if type(str) == 'string' and str:find("%", nil, --[[plainmatch=]]true) then |
| 1149 return AC:Print (ps, str:format(...)) | |
| 1150 else | |
| 1151 return AC:Print (ps, str, ...) | |
| 1152 end | |
| 1153 end | |
| 1105 | 1154 |
| 1106 addon:SetDefaultModuleLibraries("AceConsole-3.0") | 1155 addon:SetDefaultModuleLibraries("AceConsole-3.0") |
| 1107 addon:SetDefaultModulePrototype(prototype) | 1156 addon:SetDefaultModulePrototype(prototype) |
| 1108 | 1157 |
| 1109 local err = [[Module '%s' cannot register itself because it failed a required condition: '%s']] | 1158 local err = [[Module '%s' cannot register itself because it failed a required condition: '%s']] |
| 1137 | 1186 |
| 1138 'Activate', enabled_p, rebroadcast_p, threshold | 1187 'Activate', enabled_p, rebroadcast_p, threshold |
| 1139 The two boolean predicates are self-explanatory. The threshold is an | 1188 The two boolean predicates are self-explanatory. The threshold is an |
| 1140 ITEM_QUALITY_* constant integer. | 1189 ITEM_QUALITY_* constant integer. |
| 1141 | 1190 |
| 1142 'Deactivate' | 1191 'Deactivate', raiderdata |
| 1143 After all system events have been unregistered. | 1192 After all system events have been unregistered. Argument is a holder of |
| 1193 the current g_loot.raiders table (in 'raidersnap'). | |
| 1144 | 1194 |
| 1145 'Reset' | 1195 'Reset' |
| 1146 Clicking "Clear Loot", after all data manipulation is finished. | 1196 Clicking "Clear Loot", after all data manipulation is finished. |
| 1147 | 1197 |
| 1148 'NewBoss', boss | 1198 'NewBoss', boss |
| 1928 self.rebroadcast = false | 1978 self.rebroadcast = false |
| 1929 self:UnregisterEvent(RAID_ROSTER_UPDATE_EVENT) | 1979 self:UnregisterEvent(RAID_ROSTER_UPDATE_EVENT) |
| 1930 self:UnregisterEvent("PLAYER_ENTERING_WORLD") | 1980 self:UnregisterEvent("PLAYER_ENTERING_WORLD") |
| 1931 self:UnregisterEvent("CHAT_MSG_LOOT") | 1981 self:UnregisterEvent("CHAT_MSG_LOOT") |
| 1932 _LFR_suppressing = nil | 1982 _LFR_suppressing = nil |
| 1933 self:Fire ('Deactivate') | 1983 -- Passing .raiders directly doesn't work with a proxy (again, WTB Lua |
| 1984 -- 5.2 and its __pairs iterators). Give it the same structure as a boss | |
| 1985 -- entry instead. | |
| 1986 self:Fire ('Deactivate', { raidersnap = g_loot.raiders }) | |
| 1934 self:Print("Deactivated.") | 1987 self:Print("Deactivated.") |
| 1935 end | 1988 end |
| 1936 | 1989 |
| 1937 function addon:Clear(verbose_p) | 1990 function addon:Clear(verbose_p) |
| 1938 local repopup, st | 1991 local repopup, st |
| 3055 -- formatted timestamp. This is expensive, and destructive for P.unique. | 3108 -- formatted timestamp. This is expensive, and destructive for P.unique. |
| 3056 local function compare_timestamps (L, R) | 3109 local function compare_timestamps (L, R) |
| 3057 return L > R -- reverse of normal order, newest first | 3110 return L > R -- reverse of normal order, newest first |
| 3058 end | 3111 end |
| 3059 local function sort_player (p) | 3112 local function sort_player (p) |
| 3060 local new_uniques, uniques_bywhen, when_array = new(), new(), new() | 3113 local new_uniques, uniques_bywhen, when_array = {}, new(), new() |
| 3061 for u,tstamp in pairs(p.when) do | 3114 for u,tstamp in pairs(p.when) do |
| 3062 uniques_bywhen[tstamp] = u | 3115 uniques_bywhen[tstamp] = u |
| 3063 when_array[#when_array+1] = tstamp | 3116 when_array[#when_array+1] = tstamp |
| 3064 end | 3117 end |
| 3065 table.sort (when_array, compare_timestamps) | 3118 table.sort (when_array, compare_timestamps) |
| 3066 for i,tstamp in ipairs(when_array) do | 3119 for i,tstamp in ipairs(when_array) do |
| 3067 new_uniques[i] = uniques_bywhen[tstamp] | 3120 new_uniques[i] = uniques_bywhen[tstamp] |
| 3068 end | 3121 end |
| 3069 p.unique = new_uniques | 3122 p.unique = new_uniques |
| 3070 del(new_uniques) del(uniques_bywhen) del(when_array) | 3123 del(uniques_bywhen) |
| 3124 del(when_array) | |
| 3071 end | 3125 end |
| 3072 | 3126 |
| 3073 function addon:repair_history_integrity() | 3127 function addon:repair_history_integrity() |
| 3074 local rcount, pcount, hcount, errors = 0, 0, 0, 0 | 3128 local rcount, pcount, hcount, errors = 0, 0, 0, 0 |
| 3075 local empties_to_delete = {} | 3129 local empties_to_delete = {} |
