sepgp = AceLibrary("AceAddon-2.0"):new("AceConsole-2.0", "AceHook-2.1", "AceDB-2.0", "AceDebug-2.0", "AceEvent-2.0", "AceModuleCore-2.0", "FuBarPlugin-2.0") sepgp:SetModuleMixins("AceDebug-2.0") local D = AceLibrary("Dewdrop-2.0") local BZ = AceLibrary("Babble-Zone-2.2") local playerName = (UnitName("player")) local shooty_basegp = 135 local shooty_baseaward_ep = 100 local shooty_decay = 0.85 local shooty_max = 5000 local shooty_timeout = 45 local shooty_maxloglines = 300 local shooty_reservechan = "Reserves" local shooty_reservecall = string.format("{shootyepgp}Type \"+\" in this channel if on main, or \"+\" if on alt within %dsec.",shooty_timeout) local shooty_reserveanswer = "^(%+)(%a*)$" local out = "|cff9664c8shootyepgp:|r %s" local lastUpdate = 0 local needInit = true local admin local shooty_debugchat local running_check,running_bid local partyUnit,raidUnit = {},{} local reserves_blacklist,bids_blacklist = {},{} do for i=1,40 do raidUnit[i] = "raid"..i end for i=1,4 do partyUnit[i] = "party"..i end end sepgp.reserves = {} sepgp.timer = CreateFrame("Frame") sepgp.timer.cd_text = "" sepgp.timer:Hide() sepgp.timer:SetScript("OnUpdate",function() sepgp.OnUpdate(this,arg1) end) sepgp.bids_main,sepgp.bids_off,sepgp.bid_item = {},{},{} function sepgp:OnInitialize() -- ADDON_LOADED (1) unless LoD if sepgp_saychannel == nil then sepgp_saychannel = "GUILD" end if sepgp_decay == nil then sepgp_decay = shooty_decay end if sepgp_progress == nil then sepgp_progress = "T1" end if sepgp_discount == nil then sepgp_discount = 0.25 end if sepgp_log == nil then sepgp_log = {} end sepgp.extratip = CreateFrame("GameTooltip","shootyepgp_tooltip",UIParent,"GameTooltipTemplate") end function sepgp:AceEvent_FullyInitialized() -- SYNTHETIC EVENT, later than PLAYER_LOGIN, PLAYER_ENTERING_WORLD (3) for i=1,NUM_CHAT_WINDOWS do local tab = getglobal("ChatFrame"..i.."Tab") local cf = getglobal("ChatFrame"..i) local tabName = tab:GetText() if tab ~= nil and (string.lower(tabName) == "debug") then shooty_debugchat = cf ChatFrame_RemoveAllMessageGroups(shooty_debugchat) shooty_debugchat:SetMaxLines(1024) break end end if (not sepgp_main) or (sepgp_main == "") then StaticPopup_Show("SHOOTY_EPGP_SET_MAIN") end if not self:IsEventScheduled("shootyepgpChannelInit") then self:ScheduleEvent("shootyepgpChannelInit",self.getReserveStatus,2,self) end -- if pfUI loaded, skin the extra tooltip if (pfUI) and pfUI.api and pfUI.api.CreateBackdrop and pfUI_config and pfUI_config.tooltip and pfUI_config.tooltip.alpha then pfUI.api.CreateBackdrop(sepgp.extratip,nil,nil,pfUI_config.tooltip.alpha) end -- hook tooltip to add our GP values sepgp:TipHook() -- make tablets closable with ESC for i=1,4 do table.insert(UISpecialFrames,string.format("Tablet20DetachedFrame%d",i)) end end function sepgp:OnEnable() -- PLAYER_LOGIN (2) sepgp:RegisterEvent("GUILD_ROSTER_UPDATE",function() if (arg1) then -- member join /leave self:SetRefresh(true) end end) sepgp:RegisterEvent("RAID_ROSTER_UPDATE",function() self:SetRefresh(true) end) sepgp:RegisterEvent("PARTY_MEMBERS_CHANGED",function() self:SetRefresh(true) end) sepgp:RegisterEvent("CHAT_MSG_RAID","captureLootCall") sepgp:RegisterEvent("CHAT_MSG_RAID_LEADER","captureLootCall") sepgp:RegisterEvent("CHAT_MSG_RAID_WARNING","captureLootCall") sepgp:RegisterEvent("CHAT_MSG_WHISPER","captureBid") if (IsInGuild()) then if (GetNumGuildMembers()==0) then GuildRoster() end end if AceLibrary("AceEvent-2.0"):IsFullyInitialized() then self:AceEvent_FullyInitialized() else self:RegisterEvent("AceEvent_FullyInitialized") end end function sepgp:OnMenuRequest() D:FeedAceOptionsTable(self:buildMenu()) end function sepgp:TipHook() self:SecureHook(GameTooltip, "SetBagItem", function(this, bag, slot) sepgp:AddDataToTooltip(GameTooltip, GetContainerItemLink(bag, slot)) end ) -- we leave it in for now so they can check if they were billed the correct GP self:SecureHook(GameTooltip, "SetLootItem", function(this, slot) sepgp:AddDataToTooltip(GameTooltip, GetLootSlotLink(slot)) end ) self:SecureHook(GameTooltip, "SetLootRollItem", function(this, id) sepgp:AddDataToTooltip(GameTooltip, GetLootRollItemLink(id)) end ) self:SecureHook("SetItemRef", function(link, name, button) if (link and name and ItemRefTooltip) then if (strsub(link, 1, 6) ~= "Player") then if (ItemRefTooltip:IsVisible()) then if (not DressUpFrame:IsVisible()) then sepgp:AddDataToTooltip(ItemRefTooltip, link) end ItemRefTooltip.isDisplayDone = nil end end end end ) self:HookScript(GameTooltip, "OnHide", function() if sepgp.extratip:IsVisible() then sepgp.extratip:Hide() end self.hooks[GameTooltip]["OnHide"]() end ) self:HookScript(ItemRefTooltip, "OnHide", function() if sepgp.extratip:IsVisible() then sepgp.extratip:Hide() end self.hooks[ItemRefTooltip]["OnHide"]() end ) end function sepgp:getReserveStatus() if (IsInGuild()) then local guildName = (GetGuildInfo("player")) if (guildName) and guildName ~= "" then sepgp_reservechannel = string.format("%sReserves",(string.gsub(guildName," ",""))) end end if sepgp_reservechannel == nil then sepgp_reservechannel = shooty_reservechan end local reservesChannelID = tonumber((GetChannelName(sepgp_reservechannel))) if (reservesChannelID) and (reservesChannelID ~= 0) then sepgp:reservesToggle(true) end end function sepgp:AddDataToTooltip(tooltip,itemlink,itemstring) local price if (itemstring) then price = sepgp_prices:GetPrice(itemstring,sepgp_progress) elseif (itemlink) then price = sepgp_prices:GetPrice(itemlink,sepgp_progress) end if not price then return end local textRight = string.format("cost:|cff32cd32%d|r offspec:|cff20b2aa%d|r",price,math.floor(price*sepgp_discount)) if (tooltip:NumLines() < 29) then tooltip:AddLine(" ") tooltip:AddDoubleLine("|cff9664c8shootyepgp|r",textRight) tooltip:Show() else sepgp.extratip:ClearLines() sepgp.extratip:SetOwner(tooltip,"ANCHOR_NONE") sepgp.extratip:ClearAllPoints() sepgp.extratip:SetPoint("TOPLEFT", tooltip, "BOTTOMLEFT", 0, -5) sepgp.extratip:SetPoint("TOPRIGHT", tooltip, "BOTTOMRIGHT", 0, -5) sepgp.extratip:AddDoubleLine("|cff9664c8shootyepgp|r",textRight) sepgp.extratip:Show() end end function sepgp:OnUpdate(elapsed) sepgp.timer.count_down = sepgp.timer.count_down - elapsed lastUpdate = lastUpdate + elapsed if sepgp.timer.count_down <= 0 then running_check = nil sepgp.timer:Hide() sepgp.timer.cd_text = "|cffff0000Finished|r" sepgp_reserves:Refresh() else sepgp.timer.cd_text = string.format("|cff00ff00%02d|r|cffffffffsec|r",sepgp.timer.count_down) end if lastUpdate > 0.5 then lastUpdate = 0 sepgp_reserves:Refresh() end end ------------------- -- Communication ------------------- function sepgp:flashFrame(frame) local tabFlash = getglobal(frame:GetName().."TabFlash") if ( not frame.isDocked or (frame == SELECTED_DOCK_FRAME) or UIFrameIsFlashing(tabFlash) ) then return end tabFlash:Show() UIFrameFlash(tabFlash, 0.25, 0.25, 60, nil, 0.5, 0.5) end function sepgp:debugPrint(msg) if (shooty_debugchat) then shooty_debugchat:AddMessage(string.format(out,msg)) sepgp:flashFrame(shooty_debugchat) else sepgp:defaultPrint(msg) end end function sepgp:defaultPrint(msg) if not DEFAULT_CHAT_FRAME:IsVisible() then FCF_SelectDockFrame(DEFAULT_CHAT_FRAME) end DEFAULT_CHAT_FRAME:AddMessage(string.format(out,msg)) end function sepgp:simpleSay(msg) SendChatMessage(string.format("shootyepgp: %s",msg), sepgp_saychannel) end function sepgp:adminSay(msg) -- API is broken on Elysium -- local g_listen, g_speak, officer_listen, officer_speak, g_promote, g_demote, g_invite, g_remove, set_gmotd, set_publicnote, view_officernote, edit_officernote, set_guildinfo = GuildControlGetRankFlags() -- if (officer_speak) then SendChatMessage(string.format("shootyepgp: %s",msg),"OFFICER") -- end end --------------------- -- EPGP Operations --------------------- function sepgp:init_notes(guild_index,note,officernote) if not tonumber(note) or (tonumber(note) < 0) then GuildRosterSetPublicNote(guild_index,0) end if not tonumber(officernote) or (tonumber(officernote) < shooty_basegp) then GuildRosterSetOfficerNote(guild_index,shooty_basegp) end end function sepgp:update_ep(getname,ep) for i = 1, GetNumGuildMembers(1) do local name, _, _, _, class, _, note, officernote, _, _ = GetGuildRosterInfo(i) if (name==getname) then sepgp:init_notes(i,note,officernote) GuildRosterSetPublicNote(i,ep) end end end function sepgp:update_gp(getname,gp) for i = 1, GetNumGuildMembers(1) do local name, _, _, _, class, _, note, officernote, _, _ = GetGuildRosterInfo(i) if (name==getname) then sepgp:init_notes(i,note,officernote) GuildRosterSetOfficerNote(i,gp) end end end function sepgp:get_ep(getname,note) -- gets ep by name or note if (note) then if tonumber(note)==nil then return 0 end end for i = 1, GetNumGuildMembers(1) do local name, _, _, _, class, _, note, officernote, _, _ = GetGuildRosterInfo(i) if tonumber(note)==nil then note=0 end if (name==getname) then return tonumber(note) end end return(0) end function sepgp:get_gp(getname,officernote) -- gets gp by name or officernote if (officernote) then if tonumber(officernote)==nil then return shooty_basegp end end for i = 1, GetNumGuildMembers(1) do local name, _, _, _, class, _, note, officernote, _, _ = GetGuildRosterInfo(i) if tonumber(officernote)==nil then officernote=shooty_basegp end if (name==getname) then return tonumber(officernote) end end return(shooty_basegp) end function sepgp:award_raid_ep(ep) -- awards ep to raid members in zone if GetNumRaidMembers()>0 then sepgp:simpleSay(string.format("Giving %d ep to all raidmembers",ep)) self:addToLog(string.format("Giving %d ep to all raidmembers",ep)) for i = 1, GetNumRaidMembers(true) do local name, rank, subgroup, level, class, fileName, zone, online, isDead = GetRaidRosterInfo(i) sepgp:givename_ep(name,ep) end else UIErrorsFrame:AddMessage("You aren't in a raid dummy",1,0,0)end end function sepgp:award_reserve_ep(ep) -- awards ep to reserve list if table.getn(sepgp.shooty_reserves) > 0 then sepgp:simpleSay(string.format("Giving %d ep to active reserves",ep)) self:addToLog(string.format("Giving %d ep to active reserves",ep)) for i, name in ipairs(sepgp.shooty_reserves) do sepgp:givename_ep(name,ep) end sepgp.reserves = {} reserves_blacklist = {} end end function sepgp:givename_ep(getname,ep) -- awards ep to a single character if not (admin()) then return end sepgp:debugPrint(string.format("Giving %d ep to %s",ep,getname)) ep = ep + sepgp:get_ep(getname) sepgp:update_ep(getname,ep) end function sepgp:givename_gp(getname,gp) -- assigns gp to a single character if not (admin()) then return end sepgp:debugPrint(string.format("Giving %d gp to %s",gp,getname)) local oldgp = sepgp:get_gp(getname) local newgp = gp + oldgp sepgp:adminSay(string.format("Awarding %d GP to %s. (Previous: %d, New: %d)",gp,getname,oldgp,newgp)) self:addToLog(string.format("Awarding %d GP to %s. (Previous: %d, New: %d)",gp,getname,oldgp,newgp)) sepgp:update_gp(getname,newgp) end function sepgp:decay_epgp() -- decays entire roster's ep and gp if not (admin()) then return end for i = 1, GetNumGuildMembers(1) do local name,_,_,_,class,_,ep,gp,_,_ = GetGuildRosterInfo(i) ep = tonumber(ep) gp = tonumber(gp) if ep == nil then else ep = math.max(0,sepgp:num_round(ep*sepgp_decay)) GuildRosterSetPublicNote(i,ep) gp = math.max(shooty_basegp,sepgp:num_round(gp*sepgp_decay)) GuildRosterSetOfficerNote(i,gp) end end local msg = string.format("All EP and GP decayed by %d%%",(1-sepgp_decay)*100) sepgp:simpleSay(msg) if not (sepgp_saychannel=="OFFICER") then sepgp:adminSay(msg) end self:addToLog(msg) end function sepgp:gp_reset() if (IsGuildLeader()) then for i = 1, GetNumGuildMembers(1) do GuildRosterSetOfficerNote(i, shooty_basegp) end sepgp:debugPrint(string.format("All GP has been reset to %d.",shooty_basegp)) self:adminSay(string.format("All GP has been reset to %d.",shooty_basegp)) self:addToLog(string.format("All GP has been reset to %d.",shooty_basegp)) end end --------- -- Menu --------- local T = AceLibrary("Tablet-2.0") sepgp.defaultMinimapPosition = 180 sepgp.cannotDetachTooltip = true sepgp.tooltipHiddenWhenEmpty = false sepgp.hasIcon = "Interface\\Icons\\INV_Misc_Orb_04" function sepgp:OnTooltipUpdate() local hint = "|cffffff00Click|r to toggle Standings.%s \n|cffffff00Right-Click|r for Options." if (admin()) then hint = string.format(hint," \n|cffffff00Ctrl+Click|r to toggle Reserves. \n|cffffff00Alt+Click|r to toggle Bids. \n|cffffff00Shift+Click|r to toggle Logs.") else hint = string.format(hint,"") end T:SetHint(hint) end function sepgp:OnClick() local is_admin = admin() if (IsControlKeyDown() and is_admin) then sepgp_reserves:Toggle() elseif (IsAltKeyDown() and is_admin) then sepgp_bids:Toggle() elseif (IsShiftKeyDown() and is_admin) then sepgp_logs:Toggle() else sepgp_standings:Toggle() end end function sepgp:SetRefresh(flag) needRefresh = flag if (flag) then sepgp_standings:Refresh() end end function sepgp:buildRosterTable() local g, r = { }, { } local numGuildMembers = GetNumGuildMembers(1) if (sepgp_raidonly) and GetNumRaidMembers() > 0 then for i = 1, GetNumRaidMembers(true) do local name, rank, subgroup, level, class, fileName, zone, online, isDead = GetRaidRosterInfo(i) r[name] = true end end for i = 1, numGuildMembers do local member_name,_,_,_,class,_,ep,gp,_,_ = GetGuildRosterInfo(i) if (sepgp_raidonly) and next(r) then if r[member_name] then table.insert(g,{["name"]=member_name,["class"]=class}) end else table.insert(g,{["name"]=member_name,["class"]=class}) end end return g end function sepgp:buildClassMemberTable(roster,epgp) local desc,usage if epgp == "ep" then desc = "Account EPs to %s." usage = "" elseif epgp == "gp" then desc = "Account GPs to %s." usage = "" end local c = { } for i,member in ipairs(roster) do local class,name = member.class, member.name if c[class] == nil then c[class] = { } c[class].type = "group" c[class].name = class c[class].desc = class .. " members" c[class].hidden = function() return not (admin()) end c[class].args = { } end if c[class].args[name] == nil then c[class].args[name] = { } c[class].args[name].type = "text" c[class].args[name].name = name c[class].args[name].desc = string.format(desc,name) c[class].args[name].usage = usage if epgp == "ep" then c[class].args[name].get = "suggestedAwardEP" c[class].args[name].set = function(v) sepgp:givename_ep(name, tonumber(v)) end elseif epgp == "gp" then c[class].args[name].get = false c[class].args[name].set = function(v) sepgp:givename_gp(name, tonumber(v)) end end c[class].args[name].validate = function(v) return (type(v) == "number" or tonumber(v)) and tonumber(v) < shooty_max end end end return c end local options function sepgp:buildMenu() if not (options) then options = { type = "group", desc = "shootyepgp options", handler = self, args = { } } options.args["ep"] = { type = "group", name = "+EPs to Member", desc = "Account EPs for member.", order = 10, hidden = function() return not (admin()) end, } options.args["ep_raid"] = { type = "text", name = "+EPs to Raid", desc = "Award EPs to all raid members.", order = 20, get = "suggestedAwardEP", set = function(v) sepgp:award_raid_ep(tonumber(v)) end, usage = "", hidden = function() return not (admin()) end, validate = function(v) local n = tonumber(v) return n and n >= 0 and n < shooty_max end } options.args["gp"] = { type = "group", name = "+GPs to Member", desc = "Account GPs for member.", order = 30, hidden = function() return not (admin()) end, } options.args["ep_reserves"] = { type = "text", name = "+EPs to Reserves", desc = "Award EPs to all active Reserves.", order = 40, get = "suggestedAwardEP", set = function(v) sepgp:award_reserve_ep(tonumber(v)) end, usage = "", hidden = function() return not (admin()) end, validate = function(v) local n = tonumber(v) return n and n >= 0 and n < shooty_max end } options.args["reserves"] = { type = "toggle", name = "Enable Reserves", desc = "Participate in Standby Raiders List.\n|cffff0000Requires Main Character Name.|r", order = 50, get = function() return (sepgp.reservesChannelID ~= nil) and (sepgp.reservesChannelID ~= 0) end, set = function(v) sepgp:reservesToggle(v) end, disabled = function() return (sepgp_main == nil) end } options.args["afkcheck_reserves"] = { type = "execute", name = "AFK Check Reserves", desc = "AFK Check Reserves List", order = 60, hidden = function() return not (admin()) end, func = function() sepgp:afkcheck_reserves() end } options.args["set_main"] = { type = "text", name = "Set Main", desc = "Set your Main Character for Reserve List.", order = 70, usage = "", get = function() return sepgp_main end, set = function(v) sepgp_main = (sepgp:verifyGuildMember(v)) end, } options.args["raid_only"] = { type = "toggle", name = "Raid Only", desc = "Only show members in raid.", order = 80, get = function() return not not sepgp_raidonly end, set = function(v) sepgp_raidonly = not sepgp_raidonly sepgp:SetRefresh(true) end, } options.args["progress_tier"] = { type = "text", name = "Raid Progress", desc = "Highest Tier the Guild is raiding.\nUsed to adjust GP Prices.", order = 90, get = function() return sepgp_progress end, set = function(v) sepgp_progress = v sepgp_bids:Refresh() end, validate = { ["T3"]="4.Naxxramas", ["T2.5"]="3.Temple of Ahn\'Qiraj", ["T2"]="2.Blackwing Lair", ["T1"]="1.Molten Core"}, } options.args["report_channel"] = { type = "text", name = "Reporting channel", desc = "Channel used by reporting functions.", order = 95, hidden = function() return not (admin()) end, get = function() return sepgp_saychannel end, set = function(v) sepgp_saychannel = v end, validate = { "PARTY", "RAID", "GUILD", "OFFICER" }, } options.args["decay"] = { type = "execute", name = "Decay EPGP", desc = string.format("Decays all EPGP by %d%%",(1-(sepgp_decay or shooty_decay))*100), order = 100, hidden = function() return not (admin()) end, func = function() sepgp:decay_epgp() end } options.args["set_decay"] = { type = "range", name = "Set Decay %", desc = "Set Decay percentage (Admin only).", order = 110, usage = "", get = function() return (1.0-sepgp_decay) end, set = function(v) sepgp_decay = (1 - v) end, min = 0.01, max = 0.5, step = 0.01, bigStep = 0.05, isPercent = true, hidden = function() return not (admin()) end, } options.args["set_discount"] = { type = "range", name = "Offspec Price %", desc = "Set Offspec / Resistance Items GP Percent.", order = 115, get = function() return sepgp_discount end, set = function(v) sepgp_discount = v end, min = 0, max = 1, step = 0.05, isPercent = true } options.args["reset"] = { type = "execute", name = "Reset GP", desc = string.format("gives everybody %d basic GP (Admin only).",shooty_basegp), order = 120, hidden = function() return not (IsGuildLeader()) end, func = function() StaticPopup_Show("SHOOTY_EPGP_CONFIRM_RESET_GP") end } end if (needInit) or (needRefresh) then local members = sepgp:buildRosterTable() self:debugPrint(string.format("Scanning %d members for EP/GP data. (%s)",table.getn(members),(sepgp_raidonly and "Raid" or "Full"))) options.args["ep"].args = sepgp:buildClassMemberTable(members,"ep") options.args["gp"].args = sepgp:buildClassMemberTable(members,"gp") if (needInit) then needInit = false end if (needRefresh) then needRefresh = false end end return options end --------------- -- Reserves --------------- function sepgp:reservesToggle(flag) local reservesChannelID = tonumber((GetChannelName(sepgp_reservechannel))) if (flag) then -- we want in if (reservesChannelID) and reservesChannelID ~= 0 then sepgp.reservesChannelID = reservesChannelID if not self:IsEventRegistered("CHAT_MSG_CHANNEL") then sepgp:RegisterEvent("CHAT_MSG_CHANNEL","captureReserveChatter") end return true else sepgp:RegisterEvent("CHAT_MSG_CHANNEL_NOTICE","reservesChannelChange") JoinChannelByName(sepgp_reservechannel) return end else -- we want out if (reservesChannelID) and reservesChannelID ~= 0 then sepgp:RegisterEvent("CHAT_MSG_CHANNEL_NOTICE","reservesChannelChange") LeaveChannelByName(sepgp_reservechannel) return else if sepgp:IsEventRegistered("CHAT_MSG_CHANNEL") then sepgp:UnregisterEvent("CHAT_MSG_CHANNEL") end return false end end end function sepgp:reservesChannelChange(msg,_,_,_,_,_,_,_,channel) if (msg) and (channel) and (channel == sepgp_reservechannel) then if msg == "YOU_JOINED" then sepgp.reservesChannelID = tonumber((GetChannelName(sepgp_reservechannel))) RemoveChatWindowChannel(DEFAULT_CHAT_FRAME:GetID(), sepgp_reservechannel) sepgp:RegisterEvent("CHAT_MSG_CHANNEL","captureReserveChatter") elseif msg == "YOU_LEFT" then sepgp.reservesChannelID = nil if sepgp:IsEventRegistered("CHAT_MSG_CHANNEL") then sepgp:UnregisterEvent("CHAT_MSG_CHANNEL") end end sepgp:UnregisterEvent("CHAT_MSG_CHANNEL_NOTICE") D:Close() end end function sepgp:afkcheck_reserves() if (running_check) then return end if sepgp.reservesChannelID ~= nil and ((GetChannelName(sepgp.reservesChannelID)) == sepgp.reservesChannelID) then reserves_blacklist = {} sepgp.reserves = {} running_check = true sepgp.timer.count_down = shooty_timeout sepgp.timer:Show() SendChatMessage(shooty_reservecall,"CHANNEL",nil,sepgp.reservesChannelID) sepgp_reserves:Toggle(true) end end function sepgp:sendReserverResponce() if sepgp.reservesChannelID ~= nil then if (sepgp_main) then if sepgp_main == playerName then SendChatMessage("+","CHANNEL",nil,sepgp.reservesChannelID) else SendChatMessage(string.format("+%s",sepgp_main),"CHANNEL",nil,sepgp.reservesChannelID) end end end end function sepgp:captureReserveChatter(text, sender, _, _, _, _, _, _, channel) if not (channel) or not (channel == sepgp_reservechannel) then return end local reserve, reserve_class, reserve_rank, reserve_alt = nil,nil,nil,nil local r,_,rdy,name = string.find(text,shooty_reserveanswer) if (r) and (running_check) then if (rdy) then if (name) and (name ~= "") then if (not sepgp:inRaid(name)) then reserve, reserve_class, reserve_rank = sepgp:verifyGuildMember(name) if reserve ~= sender then reserve_alt = sender end end else if (not sepgp:inRaid(sender)) then reserve, reserve_class, reserve_rank = sepgp:verifyGuildMember(sender) end end if reserve and reserve_class and reserve_rank then if reserve_alt then if not reserves_blacklist[reserve_alt] then reserves_blacklist[reserve_alt] = true table.insert(sepgp.reserves,{reserve,reserve_class,reserve_rank,reserve_alt}) else sepgp:defaultPrint(string.format("|cffff0000%s|r trying to add %s to Reserves, but has already added a member. Discarding!",reserve_alt,reserve)) end else if not reserves_blacklist[reserve] then reserves_blacklist[reserve] = true table.insert(sepgp.reserves,{reserve,reserve_class,reserve_rank}) else sepgp:defaultPrint(string.format("|cffff0000%s|r has already been added to Reserves. Discarding!",reserve)) end end end end return end local q = string.find(text,"^{shootyepgp}Type") if (q) and not (running_check) then if (not UnitInRaid("player")) or (not sepgp:inRaid(sender)) then StaticPopup_Show("SHOOTY_EPGP_RESERVE_AFKCHECK_RESPONCE") end end end --------- -- Bids --------- local lootCall = {} lootCall.whisp = { "^(w)[%s%p%c]+.+",".+[%s%p%c]+(w)$",".+[%s%p%c]+(w)[%s%p%c]+.*",".*[%s%p%c]+(w)[%s%p%c]+.+", "^(whisper)[%s%p%c]+.+",".+[%s%p%c]+(whisper)$",".+[%s%p%c]+(whisper)[%s%p%c]+.*",".*[%s%p%c]+(whisper)[%s%p%c]+.+", ".+[%s%p%c]+(bid)[%s%p%c]*.*",".*[%s%p%c]*(bid)[%s%p%c]+.+" } lootCall.ms = { ".+(%+).*",".*(%+).+", "^(ms)[%s%p%c]+.+",".+[%s%p%c]+(ms)$",".+[%s%p%c]+(ms)[%s%p%c]+.*",".*[%s%p%c]+(ms)[%s%p%c]+.+", ".+(mainspec).*",".*(mainspec).+" } lootCall.os = { ".+(%-).*",".*(%-).+", "^(os)[%s%p%c]+.+",".+[%s%p%c]+(os)$",".+[%s%p%c]+(os)[%s%p%c]+.*",".*[%s%p%c]+(os)[%s%p%c]+.+", ".+(offspec).*",".*(offspec).+" } lootCall.bs = { -- blacklist "^(roll)[%s%p%c]+.+",".+[%s%p%c]+(roll)$",".*[%s%p%c]+(roll)[%s%p%c]+.*" } function sepgp:captureLootCall(text, sender) if not (IsRaidLeader() or self:lootMaster()) then return end if not sender == playerName then return end if not (string.find(text, "|Hitem:", 1, true)) then return end local linkstriptext, count = string.gsub(text,"|c%x+|H[eimt:%d]+|h%[[%w%s',%-]+%]|h|r"," ; ") if count > 1 then return end local lowtext = string.lower(linkstriptext) local whisperkw_found, mskw_found, oskw_found, link_found, blacklist_found for _,f in ipairs(lootCall.bs) do blacklist_found = string.find(lowtext,f) if (blacklist_found) then return end end local _, itemLink, itemColor, itemString, itemName for _,f in ipairs(lootCall.whisp) do whisperkw_found = string.find(lowtext,f) if (whisperkw_found) then break end end for _,f in ipairs(lootCall.ms) do mskw_found = string.find(lowtext,f) if (mskw_found) then break end end for _,f in ipairs(lootCall.os) do oskw_found = string.find(lowtext,f) if (oskw_found) then break end end if (whisperkw_found) or (mskw_found) or (oskw_found) then _,_,itemLink = string.find(text,"(|c%x+|H[eimt:%d]+|h%[[%w%s',%-]+%]|h|r)") if (itemLink) and (itemLink ~= "") then link_found, _, itemColor, itemString, itemName = string.find(itemLink, "^(|c%x+)|H(.+)|h(%[.+%])") end if (link_found) then self:clearBids() sepgp.bid_item.link = itemString sepgp.bid_item.linkFull = itemLink sepgp.bid_item.name = string.format("%s%s|r",itemColor,itemName) self:ScheduleEvent("shootyepgpBidTimeout",self.clearBids,360,self) running_bid = true self:debugPrint("Capturing Bids for 6min.") sepgp_bids:Toggle(true) end end end local lootBid = {} lootBid.ms = {"(%+)",".+(%+).*",".*(%+).+",".*(%+).*","(ms)"} lootBid.os = {"(%-)",".+(%-).*",".*(%-).+",".*(%-).*","(os)"} function sepgp:captureBid(text, sender) if not (running_bid) then return end if not (IsRaidLeader() or self:lootMaster()) then return end if not sepgp.bid_item.link then return end local mskw_found,oskw_found local lowtext = string.lower(text) for _,f in ipairs(lootBid.ms) do mskw_found = string.find(text,f) if (mskw_found) then break end end for _,f in ipairs(lootBid.os) do oskw_found = string.find(text,f) if (oskw_found) then break end end if (mskw_found) or (oskw_found) then if self:inRaid(sender) then if bids_blacklist[sender] == nil then for i = 1, GetNumGuildMembers(1) do local name, _, _, _, class, _, note, officernote, _, _ = GetGuildRosterInfo(i) if name == sender then local ep = self:get_ep(name,note) local gp = self:get_gp(name,officernote) if (mskw_found) then bids_blacklist[sender] = true table.insert(sepgp.bids_main,{name,class,ep,gp,ep/gp}) elseif (oskw_found) then bids_blacklist[sender] = true table.insert(sepgp.bids_off,{name,class,ep,gp,ep/gp}) end sepgp_bids:Toggle(true) sepgp_bids:Refresh() return end end end end end end function sepgp:clearBids() sepgp:defaultPrint("clearBids") sepgp.bid_item = {} sepgp.bids_main = {} sepgp.bids_off = {} bids_blacklist = {} if self:IsEventScheduled("shootyepgpBidTimeout") then self:CancelScheduledEvent("shootyepgpBidTimeout") end running_bid = false sepgp_bids:Refresh() end ------------ -- Logging ------------ function sepgp:addToLog(line,skipTime) local over = table.getn(sepgp_log)-shooty_maxloglines+1 if over > 0 then for i=1,over do table.remove(sepgp_log,1) end end local timestamp if (skipTime) then timestamp = "" else timestamp = date("%b/%d %H:%M:%S") end table.insert(sepgp_log,{timestamp,line}) end ------------ -- Utility ------------ function sepgp:num_round(i) return math.floor(i+0.5) end function sepgp:verifyGuildMember(name) for i=1,GetNumGuildMembers(1) do local g_name, g_rank, g_rankIndex, g_level, g_class, g_zone, g_note, g_officernote, g_online = GetGuildRosterInfo(i) if (string.lower(name) == string.lower(g_name)) and (tonumber(g_level) == MAX_PLAYER_LEVEL) then return g_name, g_class, g_rank end end if (name) and name ~= "" then sepgp:defaultPrint(string.format("%s not found in the guild or not max level!",name)) end return end function sepgp:inRaid(name) for i=1,GetNumRaidMembers() do if name == (UnitName(raidUnit[i])) then return true end end return false end function sepgp:lootMaster() local method, lootmasterID = GetLootMethod() if method == "master" and lootmasterID == 0 then return true else return false end end local raidZones = {["Molten Core"]="T1",["Onyxia\'s Lair"]="T1.5",["Blackwing Lair"]="T2",["Ahn'Qiraj"]="T2.5",["Naxxramas"]="T3"} local zone_multipliers = { ["T3"] = {["T3"]=1,["T2.5"]=0.75,["T2"]=0.5,["T1.5"]=0.25,["T1"]=0.25}, ["T2.5"] = {["T3"]=1,["T2.5"]=1,["T2"]=0.7,["T1.5"]=0.4,["T1"]=0.4}, ["T2"] = {["T3"]=1,["T2.5"]=1,["T2"]=1,["T1.5"]=0.5,["T1"]=0.5}, ["T1"] = {["T3"]=1,["T2.5"]=1,["T2"]=1,["T1.5"]=1,["T1"]=1} } function sepgp:suggestedAwardEP() local currentTier, zoneEN, zoneLoc, checkTier, multiplier local inInstance, instanceType = IsInInstance() if (inInstance == nil) or (instanceType ~= nil and instanceType == "none") then currentTier = "T1.5" end if (inInstance) and (instanceType == "raid") then zoneLoc = GetRealZoneText() if (BZ:HasReverseTranslation(zoneLoc)) then zoneEN = BZ:GetReverseTranslation(zoneLoc) checkTier = raidZones[zoneEN] if (checkTier) then currentTier = checkTier end end end if not currentTier then return shooty_baseaward_ep else multiplier = zone_multipliers[sepgp_progress][currentTier] end if (multiplier) then return multiplier*shooty_baseaward_ep else return shooty_baseaward_ep end end admin = function() return (CanEditOfficerNote() and CanEditPublicNote()) end ------------- -- Dialogs ------------- StaticPopupDialogs["SHOOTY_EPGP_SET_MAIN"] = { text = "Set your main to be able to participate in Reserve List EPGP Checks.", button1 = TEXT(ACCEPT), button2 = TEXT(CANCEL), hasEditBox = 1, maxLetters = 12, OnAccept = function() local editBox = getglobal(this:GetParent():GetName().."EditBox") sepgp_main = sepgp:verifyGuildMember(editBox:GetText()) end, OnShow = function() getglobal(this:GetName().."EditBox"):SetText(sepgp_main or "") getglobal(this:GetName().."EditBox"):SetFocus() end, OnHide = function() if ( ChatFrameEditBox:IsVisible() ) then ChatFrameEditBox:SetFocus() end getglobal(this:GetName().."EditBox"):SetText("") end, EditBoxOnEnterPressed = function() local editBox = getglobal(this:GetParent():GetName().."EditBox") sepgp_main = sepgp:verifyGuildMember(editBox:GetText()) this:GetParent():Hide() end, EditBoxOnEscapePressed = function() this:GetParent():Hide() end, timeout = 0, exclusive = 1, whileDead = 1, hideOnEscape = 1 } StaticPopupDialogs["SHOOTY_EPGP_RESERVE_AFKCHECK_RESPONCE"] = { text = "Reserves: AFKCheck. Are you available?", button1 = TEXT(YES), button2 = TEXT(NO), OnAccept = function() sepgp:sendReserverResponce() end, timeout = shooty_timeout, exclusive = 1, showAlert = 1, whileDead = 1, hideOnEscape = 1 } StaticPopupDialogs["SHOOTY_EPGP_CONFIRM_RESET_GP"] = { text = "|cffff0000Are you sure you want to Reset ALL GP?|r", button1 = TEXT(OKAY), button2 = TEXT(CANCEL), OnAccept = function() sepgp:gp_reset() end, timeout = 0, whileDead = 1, exclusive = 1, showAlert = 1, hideOnEscape = 1 };