You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

280 lines
7.4 KiB

local lib = LibStub:NewLibrary("LootEvents", "1.2")
if not lib then return nil end
local print = print
local GetItemInfo = C_Item and C_Item.GetItemInfo or GetItemInfo
--[[// Usage
Callbacks recieve (event, chat_event, ...)
LootEvents:RegisterLootCallback(func)
event: 'item'
player_name, item_link, num_items
event: 'coin'
player_name, total_copper, coin_string
event: 'currency'
currency, num_currency
event: 'crafted'
item_link, num_items
LootEvents:RegisterGroupCallback(func)
Triggers func when "Group" loot mode events are recieved
event: 'selected'
item_link, player_name, roll_type
event: 'rolled'
item_link, player_name, roll_type, roll_number
event: 'won'
item_link, player_name
event: 'allpass'
item_link
--]]
-- Callback handling
lib.callbacks = lib.callbacks or { loot = {}, group = {} }
local lootcb, groupcb = lib.callbacks.loot, lib.callbacks.group
local need_loot = next(lootcb) and true or false
local need_group = next(groupcb) and true or false
function lib:RegisterLootCallback(func)
table.insert(lootcb, func)
need_loot = true
end
function lib:RegisterGroupCallback(func)
table.insert(groupcb, func)
need_group = true
end
local current_pattern = nil
local function trigger_loot(event, ...)
for _, func in ipairs(lootcb) do
func(event, current_pattern, ...)
end
end
local activerolls = 0
local function trigger_group(event, ...)
for _, func in ipairs(groupcb) do
func(event, current_pattern, ...)
end
if event == 'won' or event == 'allpass' then
activerolls = max(0, activerolls - 1)
end
end
-- Catch latent rolls
if IsInGroup() then
for i=1,200 do
local time = GetLootRollTimeLeft(i)
if time > 0 then
activerolls = activerolls + 1
end
end
end
local Deformat = XLoot.Deformat
local loot_patterns, group_patterns, unsortedloot, currentsort
-- Chatmsg handler
local sort, group = table.sort
local function sort_func(a, b)
return a[group] < b[group]
end
local function Handler(text)
if need_group and activerolls > 0 then
-- Move through the patterns one by one, match against the message
for k, v in ipairs(group_patterns) do
local m1, m2, m3, m4 = Deformat(text, v[1])
-- Match was found, call the handler with all captured values
if m1 then
current_pattern = v[3]
return v[2](m1, m2, m3, m4)
end
end
end
if need_loot then
-- Match string against our patterns
for i, v in ipairs(loot_patterns) do
local m1, m2, m3, m4 = Deformat(text, v[1])
-- Match found, add to counter and call pattern's handler
if m1 then
current_pattern = v[1]
return v[2](m1, m2, m3, m4)
end
end
end
end
-- Invert gold patterns
local function invert(pstr)
return pstr:gsub("%%d", "(%1+)")
end
local cg = invert(GOLD_AMOUNT)
local cs = invert(SILVER_AMOUNT)
local cc = invert(COPPER_AMOUNT)
-- Parse coin strings (Really?)
local function ParseCoinString(tstr)
local g = tstr:match(cg) or 0
local s = tstr:match(cs) or 0
local c = tstr:match(cc) or 0
return g*10000+s*100+c
end
-- Event handling
if lib.frame then
lib.frame:SetScript("OnEvent", function() return nil end)
end
lib.frame = CreateFrame("Frame")
local f = lib.frame
local events = {}
f:SetScript("OnEvent", function(_, e, ...) if events[e] then events[e](...) end end)
local function event(e, func)
f:RegisterEvent(e)
events[e] = func
end
event("CHAT_MSG_LOOT", Handler)
event("CHAT_MSG_MONEY", Handler)
event("CHAT_MSG_CURRENCY", Handler)
-- Incriment and deincement rolls to only match while there is a roll happening
event("START_LOOT_ROLL", function()
activerolls = activerolls + 1
end)
-- 2 second delay needed?
local max = math.max
event("CANCEL_LOOT_ROLL", function()
--activerolls = max(0, activerolls - 1)
end)
local player = UnitName('player')
--// LOOT PATTERNS
loot_patterns = { }
do
local function handler(str, func)
assert(_G[str], "String does not exist", str)
table.insert(loot_patterns, { _G[str], func, str })
end
-- Loot triggers
local function loot(who, what, num)
trigger_loot('item', who, what, num or 1)
end
local function loot_self(what, num)
trigger_loot('item', player, what, num or 1)
end
local function coin(who, str)
trigger_loot('coin', who, ParseCoinString(str), str)
end
local function coin_self(str)
trigger_loot('coin', player, ParseCoinString(str), str)
end
-- Add item patterns
handler('LOOT_ITEM_PUSHED_SELF_MULTIPLE', loot_self)
handler('LOOT_ITEM_PUSHED_SELF', loot_self)
handler('LOOT_ITEM_SELF_MULTIPLE', loot_self)
-- Account for Russian locale using the same string for LOOT_MONEY as LOOT_ITEM_SELF
if GetLocale() == "ruRU" then
handler('LOOT_ITEM_SELF', function(what)
if not what:match("|H") then -- No link, match coins
coin_self(what)
else
loot_self(what)
end
end)
else
handler('LOOT_ITEM_SELF', loot_self)
handler('YOU_LOOT_MONEY_GUILD', coin_self)
handler('YOU_LOOT_MONEY', coin_self)
end
handler('LOOT_ITEM_MULTIPLE', loot)
handler('LOOT_ITEM', loot)
-- Add coin patterns
handler('LOOT_MONEY', coin)
handler('LOOT_MONEY_SPLIT_GUILD', coin_self)
handler('LOOT_MONEY_SPLIT', coin_self)
-- Currency patterns
local function currency(link, num)
trigger_loot('currency', link:match('currency:(%d+)'), num or 1)
end
handler('CURRENCY_GAINED_MULTIPLE', currency)
handler('CURRENCY_GAINED', currency)
-- Self crafting
local function crafted(what, num)
trigger_loot('crafted', what, num or 1)
end
handler('LOOT_ITEM_CREATED_SELF_MULTIPLE', crafted)
handler('LOOT_ITEM_CREATED_SELF', crafted)
handler('LOOT_ITEM_REFUND_MULTIPLE', loot_self)
handler('LOOT_ITEM_REFUND', loot_self)
handler('LOOT_MONEY_REFUND', coin_self)
handler('LOOT_ITEM_WHILE_PLAYER_INELIGIBLE', loot)
end
--// GROUP PATTERNS
group_patterns = { }
do
-- Base handler function. Checks argument types, adds to handler table (Presorted)
-- The pattern is stored as the first key, and the function to be called in the second
local function handler(str, func)
table.insert(group_patterns, { _G[str], func, str })
end
-- Roll selected handler (You select Greed for XXXX, etc)
local function selected(str, rtype, own)
handler(str, function(who, item)
if own then
item, who = who, player
end
trigger_group('selected', item, who, rtype)
end)
end
-- Rolled handler (XXXX roll - # by xxxxx, etc)
local function rolled(str, rtype, own)
handler(str, function(roll, item, who)
trigger_group('rolled', item, (own or who == YOU) and player or who, rtype, tonumber(roll))
end)
end
-- Add handlers using construct functions, ordered specifically
selected('LOOT_ROLL_DISENCHANT', 'disenchant')
selected('LOOT_ROLL_GREED', 'greed')
selected('LOOT_ROLL_NEED', 'need')
selected('LOOT_ROLL_DISENCHANT_SELF', 'disenchant', true)
selected('LOOT_ROLL_GREED_SELF', 'greed', true)
selected('LOOT_ROLL_NEED_SELF', 'need', true)
selected('LOOT_ROLL_PASSED_AUTO', 'pass')
selected('LOOT_ROLL_PASSED_AUTO_FEMALE', 'pass')
selected('LOOT_ROLL_PASSED_SELF_AUTO', 'pass', true)
handler('LOOT_ROLL_ALL_PASSED', function(item) trigger_group('allpass', item) end)
selected('LOOT_ROLL_PASSED_SELF', 'pass', true)
selected('LOOT_ROLL_PASSED', 'pass')
rolled('LOOT_ROLL_ROLLED_DE', 'disenchant')
rolled('LOOT_ROLL_ROLLED_GREED', 'greed')
rolled('LOOT_ROLL_ROLLED_NEED', 'need')
rolled('LOOT_ROLL_ROLLED_NEED_ROLE_BONUS', 'need')
handler('LOOT_ROLL_YOU_WON', function(item) trigger_group('won', item, player) end)
handler('LOOT_ROLL_WON', function(who, item) trigger_group('won', item, who == YOU and player or who) end)
end