comparison core.lua @ 151:42dd3076baaf

Initial attempt at tracking bonus rolls and non-loot items. Add more loot-catching patterns, and generalize them a little more. Bonus rolls are tracked by default, non-loot stuff is not. Bonus rolls don't seem to be working, but non-loot definitely is. (It may be that the patterns for bonus rolls are not actually used by the game client, or rather, that the game client does not issue those events for bonus rolls which are not your own. I have yet to win a bonus roll since implementing the code, but one person in LFR claimed to win a bonus item which simply wasn't visible to me at all. More data needed.)
author Farmbuyer of US-Kilrogg <farmbuyer@gmail.com>
date Fri, 09 Jan 2015 19:14:56 -0500
parents 63bda09d88fe
children
comparison
equal deleted inserted replaced
150:63bda09d88fe 151:42dd3076baaf
146 ['chatty_on_remote_changes'] = false, 146 ['chatty_on_remote_changes'] = false,
147 ['chatty_on_local_changes'] = false, 147 ['chatty_on_local_changes'] = false,
148 ['chatty_on_changes_frame'] = 1, 148 ['chatty_on_changes_frame'] = 1,
149 ['itemfilter'] = {}, 149 ['itemfilter'] = {},
150 ['itemvault'] = {}, 150 ['itemvault'] = {},
151 ['track_bonusrolls'] = true,
152 ['track_nonloot'] = false,
151 } } 153 } }
152 local virgin = "First time loaded? Hi! Use the /ouroloot command" 154 local virgin = "First time loaded? Hi! Use the /ouroloot command"
153 .." to show the main display. You should probably browse the instructions" 155 .." to show the main display. You should probably browse the instructions"
154 .." if you've never used this before; %s to display the help window. This" 156 .." if you've never used this before; %s to display the help window. This"
155 .." welcome message will not intrude again." 157 .." welcome message will not intrude again."
180 local my_name = UnitName('player') 182 local my_name = UnitName('player')
181 local comm_cleanup_ttl = 4 -- seconds in the communications cache 183 local comm_cleanup_ttl = 4 -- seconds in the communications cache
182 local version_large = nil -- defaults to 1, possibly changed by version 184 local version_large = nil -- defaults to 1, possibly changed by version
183 local timestamp_fmt_unique = '%Y/%m/%dT%H:%M:%S' 185 local timestamp_fmt_unique = '%Y/%m/%dT%H:%M:%S'
184 local timestamp_fmt_history = '%Y/%m/%d %H:%M:%S' 186 local timestamp_fmt_history = '%Y/%m/%d %H:%M:%S'
185 local g_LOOT_ITEM_ss, g_LOOT_ITEM_MULTIPLE_sss, g_LOOT_ITEM_SELF_s
186 local g_LOOT_ITEM_SELF_MULTIPLE_ss, g_LOOT_ITEM_WHILE_PLAYER_INELIGIBLE_ss
187 187
188 188
189 ------ Addon member data 189 ------ Addon member data
190 local flib = LibStub("LibFarmbuyer") 190 local flib = LibStub("LibFarmbuyer")
191 addon.author_debug = flib.author_debug 191 addon.author_debug = flib.author_debug
399 local GetNumGroupMembers = GetNumGroupMembers 399 local GetNumGroupMembers = GetNumGroupMembers
400 local IsInRaid = IsInRaid 400 local IsInRaid = IsInRaid
401 -- En masse forward decls of symbols defined inside local blocks 401 -- En masse forward decls of symbols defined inside local blocks
402 local _register_bossmod, makedate, create_new_cache, _init, _log, _do_loot_metas 402 local _register_bossmod, makedate, create_new_cache, _init, _log, _do_loot_metas
403 local _history_by_loot_id, _setup_unique_replace, _unavoidable_collision 403 local _history_by_loot_id, _setup_unique_replace, _unavoidable_collision
404 local _notify_about_change, _LFR_suppressing, _add_loot_disposition 404 local _notify_about_change, _LFR_suppressing, _add_loot_disposition, _grok
405 405
406 -- Try to extract numbers from the .toc "Version" and munge them into an 406 -- Try to extract numbers from the .toc "Version" and munge them into an
407 -- integral form for comparison. The result doesn't need to be meaningful as 407 -- integral form for comparison. The result doesn't need to be meaningful as
408 -- long as we can reliably feed two of them to "<" and get useful answers. 408 -- long as we can reliably feed two of them to "<" and get useful answers.
409 -- 409 --
867 _init(self) 867 _init(self)
868 self.dprint('flow', "version strings:", version_large, self.revision, self.status_text) 868 self.dprint('flow', "version strings:", version_large, self.revision, self.status_text)
869 g_gui = self.gui_state_pointer 869 g_gui = self.gui_state_pointer
870 self.gui_state_pointer = nil 870 self.gui_state_pointer = nil
871 self.load_assert = nil 871 self.load_assert = nil
872
873 --[[
874 The loot format patterns of interest, changed into relatively tight string
875 match patterns. Done during initialization rather than at load-time
876 against the slim chance that one of the non-US "delocalizers" needs to
877 adjust the global patterns before we transform them.
878 ]]
879 local function ss (m) return m:gsub('%.$','%%.'):gsub('%%s','(.+)') end
880 local function ssd (m) return m:gsub('%.$','%%.'):gsub('%%s','(.+)'):gsub('x%%d','(x%%d+)') end
881 local function s (m) return m:gsub('%.$','%%.'):gsub('%%s','(.+)') end
882 local function sd (m) return m:gsub('%.$','%%.'):gsub('%%s','(.+)'):gsub('x%%d','(x%%d+)') end
883
884 local loot_patterns = {
885 -- LOOT_ITEM = "%s receives loot: %s." --> (.+) receives loot: (.+)%.
886 -- LOOT_ITEM_BONUS_ROLL = "%s receives bonus loot: %s." --> (.+) receives bonus loot: (.+)%.
887 -- LOOT_ITEM_PUSHED = "%s receives item: %s." --> (.+) receives item: (.+)%.
888 ['LOOT_ss'] = ss(_G.LOOT_ITEM),
889 ['BONUS_ss'] = ss(_G.LOOT_ITEM_BONUS_ROLL),
890 ['ITEM_ss'] = ss(_G.LOOT_ITEM_PUSHED),
891
892 -- LOOT_ITEM_MULTIPLE = "%s receives loot: %sx%d." --> (.+) receives loot: (.+)(x%d+)%.
893 -- LOOT_ITEM_BONUS_ROLL_MULTIPLE = "%s receives bonus loot: %sx%d." --> (.+) receives bonus loot: (.+)(x%d+)%.
894 -- LOOT_ITEM_PUSHED_MULTIPLE = "%s receives item: %sx%d." --> (.+) receives item: (.+)(x%d+)%.
895 ['LOOT_MULTIPLE_ssd'] = ssd(_G.LOOT_ITEM_MULTIPLE),
896 ['BONUS_MULTIPLE_ssd'] = ssd(_G.LOOT_ITEM_BONUS_ROLL_MULTIPLE),
897 ['ITEM_MULTIPLE_ssd'] = ssd(_G.LOOT_ITEM_PUSHED_MULTIPLE),
898
899 -- LOOT_ITEM_SELF = "You receive loot: %s." --> You receive loot: (.+)%.
900 -- LOOT_ITEM_BONUS_ROLL_SELF = "You receive bonus loot: %s." --> You receive bonus loot: (.+)%.
901 -- LOOT_ITEM_PUSHED_SELF = "You receive item: %s." --> You receive item: (.+)%.
902 ['LOOT_SELF_s'] = s(_G.LOOT_ITEM_SELF),
903 ['BONUS_SELF_s'] = s(_G.LOOT_ITEM_BONUS_ROLL_SELF),
904 ['ITEM_SELF_s'] = s(_G.LOOT_ITEM_PUSHED_SELF),
905
906 -- LOOT_ITEM_SELF_MULTIPLE = "You receive loot: %sx%d." --> You receive loot: (.+)(x%d+)%.
907 -- LOOT_ITEM_BONUS_ROLL_SELF_MULTIPLE = "You receive bonus loot: %sx%d." --> You receive bonus loot: (.+)(x%d+)%.
908 -- LOOT_ITEM_PUSHED_SELF_MULTIPLE = "You receive item: %sx%d." --> You receive item: (.+)(x%d+)%.
909 ['LOOT_SELF_MULTIPLE_sd'] = sd(_G.LOOT_ITEM_SELF_MULTIPLE),
910 ['BONUS_SELF_MULTIPLE_sd'] = sd(_G.LOOT_ITEM_BONUS_ROLL_SELF_MULTIPLE),
911 ['ITEM_SELF_MULTIPLE_sd'] = sd(_G.LOOT_ITEM_PUSHED_SELF_MULTIPLE),
912
913 -- LOOT_ITEM_WHILE_PLAYER_INELIGIBLE is mostly the same as LOOT_ITEM with
914 -- an inline texture and no full stop. The punctuation in the texture
915 -- path causes fits while matching, so just make that a wildcard rather
916 -- than trying to escape it all.
917 ['LOOT_WHILE_PLAYER_INELIGIBLE_ss'] =
918 _G.LOOT_ITEM_WHILE_PLAYER_INELIGIBLE:gsub('\124T%S*\124t','\124T%%S*\124t'):gsub('%%s','(.+)'),
919 }
920 _grok = setfenv (_grok, loot_patterns)
921 for k,v in pairs(loot_patterns) do
922 self.dprint('loot', "Loot pattern", k, "set to", v)
923 end
924
872 self.OnInitialize = nil -- free up ALL the things! 925 self.OnInitialize = nil -- free up ALL the things!
873 end 926 end
874 927
875 function addon:OnEnable() 928 function addon:OnEnable()
876 self:RegisterEvent("PLAYER_LOGOUT") 929 self:RegisterEvent("PLAYER_LOGOUT")
962 self:Print("Error registering '%s' as a keybinding, check spelling!", 1015 self:Print("Error registering '%s' as a keybinding, check spelling!",
963 opts.keybinding_text) 1016 opts.keybinding_text)
964 end 1017 end
965 break 1018 break
966 end 1019 end
967
968 --[[
969 The five loot format patterns of interest, changed into relatively tight
970 string match patterns. Done at enable-time rather than load-time against
971 the slim chance that one of the non-US "delocalizers" needs to mess with
972 the global patterns before we transform them.
973
974 The SELF patterns can be replaced with LOOT_ITEM_PUSHED_SELF[_MULTIPLE] to
975 trigger on 'receive item' instead, which would detect extracting stuff
976 from mail, or s/PUSHED/CREATED/ for things like healthstones and guild
977 cauldron flasks.
978 ]]
979
980 -- LOOT_ITEM = "%s receives loot: %s." --> (.+) receives loot: (.+)%.
981 g_LOOT_ITEM_ss = LOOT_ITEM:gsub('%.$','%%.'):gsub('%%s','(.+)')
982
983 -- LOOT_ITEM_MULTIPLE = "%s receives loot: %sx%d." --> (.+) receives loot: (.+)(x%d+)%.
984 g_LOOT_ITEM_MULTIPLE_sss = LOOT_ITEM_MULTIPLE:gsub('%.$','%%.'):gsub('%%s','(.+)'):gsub('x%%d','(x%%d+)')
985
986 -- LOOT_ITEM_SELF = "You receive loot: %s." --> You receive loot: (.+)%.
987 g_LOOT_ITEM_SELF_s = LOOT_ITEM_SELF:gsub('%.$','%%.'):gsub('%%s','(.+)')
988
989 -- LOOT_ITEM_SELF_MULTIPLE = "You receive loot: %sx%d." --> You receive loot: (.+)(x%d+)%.
990 g_LOOT_ITEM_SELF_MULTIPLE_ss = LOOT_ITEM_SELF_MULTIPLE:gsub('%.$','%%.'):gsub('%%s','(.+)'):gsub('x%%d','(x%%d+)')
991
992 -- LOOT_ITEM_WHILE_PLAYER_INELIGIBLE is mostly the same as LOOT_ITEM with
993 -- an inline texture and no full stop. The punctuation in the texture
994 -- path causes fits while matching, so just make that a wildcard rather
995 -- than trying to escape it all.
996 g_LOOT_ITEM_WHILE_PLAYER_INELIGIBLE_ss = LOOT_ITEM_WHILE_PLAYER_INELIGIBLE:
997 gsub('\124T%S*\124t','\124T%%S*\124t'):gsub('%%s','(.+)')
998 1020
999 --[[ 1021 --[[
1000 Throw in the default disposition types. This could be called during load 1022 Throw in the default disposition types. This could be called during load
1001 were it not for the need to talk to the GUI data (not set up yet). 1023 were it not for the need to talk to the GUI data (not set up yet).
1002 1024
1690 break 1712 break
1691 end 1713 end
1692 end 1714 end
1693 1715
1694 if (self.rebroadcast and (not from)) and not local_override then 1716 if (self.rebroadcast and (not from)) and not local_override then
1695 self:vbroadcast('loot', recipient, unique, itemstring, count) 1717 self:vbroadcast('loot', recipient, unique, itemstring, count, extratext)
1696 end 1718 end
1697 if (not self.enabled) and (not local_override) then break end 1719 if (not self.enabled) and (not local_override) then break end
1698 1720
1699 local oldersig = recipient .. iname .. (count or "") 1721 local oldersig = recipient .. iname .. (count or "")
1700 local signature, seenit 1722 local signature, seenit
1782 "> added to cache as candidate", #candidates) 1804 "> added to cache as candidate", #candidates)
1783 end 1805 end
1784 break 1806 break
1785 end 1807 end
1786 self.dprint('loot',"<<"..prefix, "out") 1808 self.dprint('loot',"<<"..prefix, "out")
1787 return ret1, ret2 1809 return ret1, ret2 -- FIXME mostly garbage
1810 end
1811
1812 local match = string.match
1813 _grok = function (msg, bonus_p, item_p)
1814 local person, itemlink, count, extra
1815 while true do
1816 extra = "loot"
1817 -- test in most likely order: other people get more loot than you do
1818 person, itemlink, count = match (msg, LOOT_MULTIPLE_ssd); if person then break end
1819 person, itemlink = match (msg, LOOT_ss); if person then break end
1820 -- Could only do this if in an LFR... but the restriction
1821 -- might apply elsewhere soon enough.
1822 person, itemlink = match (msg, LOOT_WHILE_PLAYER_INELIGIBLE_ss); if person then break end
1823
1824 -- other people get more bonus loot than you do, too
1825 if bonus_p then
1826 extra = "bonus"
1827 person, itemlink, count = match (msg, BONUS_MULTIPLE_ssd); if person then break end
1828 person, itemlink = match (msg, BONUS_ss); if person then break end
1829 end
1830
1831 -- i can haz cheezburgr?
1832 extra = "loot"
1833 itemlink, count = match (msg, LOOT_SELF_MULTIPLE_sd); if itemlink then break end
1834 itemlink = match (msg, LOOT_SELF_s); if itemlink then break end
1835
1836 -- getting stuff out of the mailbox, the salvage boxes, etc
1837 if item_p then
1838 extra = "item"
1839 person, itemlink, count = match (msg, ITEM_MULTIPLE_ssd); if person then break end
1840 person, itemlink = match (msg, ITEM_ss); if person then break end
1841 itemlink, count = match (msg, ITEM_SELF_MULTIPLE_sd); if itemlink then break end
1842 itemlink = match (msg, ITEM_SELF_s); if itemlink then break end
1843 end
1844 break
1845 end
1846 return person, itemlink, count, extra
1788 end 1847 end
1789 1848
1790 -- Returns the index of the resulting new loot entry, or nil after 1849 -- Returns the index of the resulting new loot entry, or nil after
1791 -- displaying any errors. 1850 -- displaying any errors.
1792 local match = string.match
1793 function addon:CHAT_MSG_LOOT (event, ...) 1851 function addon:CHAT_MSG_LOOT (event, ...)
1794 if (not self.rebroadcast) and (not self.enabled) and (event ~= "manual") then return end 1852 if (not self.rebroadcast) and (not self.enabled) and (event ~= "manual") then return end
1795 1853
1796 if event == "CHAT_MSG_LOOT" then 1854 if event == "CHAT_MSG_LOOT" then
1797 local msg = ... 1855 local msg = ...
1798 local person, itemlink, count
1799 --ChatFrame2:AddMessage("original string: >"..(msg:gsub("\124","\124\124")).."<") 1856 --ChatFrame2:AddMessage("original string: >"..(msg:gsub("\124","\124\124")).."<")
1800 1857 self.dprint('loot', "CHAT_MSG_LOOT, message is >"..(msg:gsub("\124","\124\124")).."<")
1801 -- test in most likely order: other people get more loot than "you" do 1858
1802 person, itemlink, count = match(msg,g_LOOT_ITEM_MULTIPLE_sss) 1859 local person, itemlink, count, extra = _grok (msg, opts.track_bonusrolls, opts.track_nonloot)
1803 if not person then
1804 person, itemlink = match(msg,g_LOOT_ITEM_ss)
1805 end
1806 if not person then
1807 -- Could only do this text if in an LFR... but the restriction
1808 -- might apply elsewhere soon enough.
1809 person, itemlink = match(msg,g_LOOT_ITEM_WHILE_PLAYER_INELIGIBLE_ss)
1810 end
1811 if not person then
1812 itemlink, count = match(msg,g_LOOT_ITEM_SELF_MULTIPLE_ss)
1813 if not itemlink then
1814 itemlink = match(msg,g_LOOT_ITEM_SELF_s)
1815 end
1816 end
1817 1860
1818 if not itemlink then return end -- "PlayerX selected Greed", etc, not looting 1861 if not itemlink then return end -- "PlayerX selected Greed", etc, not looting
1819 self.dprint('loot', "CHAT_MSG_LOOT, person is", person, 1862 self.dprint('loot', "CHAT_MSG_LOOT, person is", person,
1820 ", itemlink is", itemlink, ", count is", count) 1863 ", itemlink is", itemlink, ", count is", count, "extra is", extra)
1864 extra = (extra == "bonus") and [[Bonus roll!]] or
1865 ((extra == "item") and [[Non-loot]] or nil) or
1866 nil
1821 1867
1822 -- Name might be colorized, remove the highlighting 1868 -- Name might be colorized, remove the highlighting
1823 if person then 1869 if person then
1824 person = match(person,"|c%x%x%x%x%x%x%x%x(%S+)") or person 1870 person = match(person,"|c%x%x%x%x%x%x%x%x(%S+)") or person
1825 else 1871 else
1826 person = my_name -- UNIT_YOU / You 1872 person = my_name -- UNIT_YOU / You
1827 end 1873 end
1828 1874
1829 return _do_loot (self, --[[override=]]false, person, --[[unique=]]nil, 1875 return _do_loot (self, --[[override=]]false, person, --[[unique=]]nil,
1830 match(itemlink,"item[%-?%d:]+"), count) 1876 match(itemlink,"item[%-?%d:]+"), count, --[[from=]]nil, extra)
1831 1877
1832 elseif event == "broadcast" then 1878 elseif event == "broadcast" then
1833 return _do_loot (self, --[[override=]]false, ...) 1879 return _do_loot (self, --[[override=]]false, ...)
1834 1880
1835 elseif event == "manual" then 1881 elseif event == "manual" then