WoWInterface SVN EventAnnouncer

[/] [trunk/] [EventAnnouncer.lua] - Rev 3

Compare with Previous | Blame | View Log

EventAnnouncer = LibStub("AceAddon-3.0"):NewAddon("EventAnnouncer", "AceEvent-3.0", "AceConsole-3.0", "AceTimer-3.0")

local RED = "|cffff4040"
local GREEN = "|cff40cd40"

function EventAnnouncer:OnInitialize()
        self.db = LibStub("AceDB-3.0"):New("EventAnnouncerDB", self:GetDefaults(), true)
        self.options = self:GetOptions()
        self.options.args.Profiles = LibStub("AceDBOptions-3.0"):GetOptionsTable(self.db)
        self.options.args.Profiles.disabled = function() return not self.db.profile.enabled end
        
        LibStub("AceConfig-3.0"):RegisterOptionsTable("EventAnnouncer", self.options)
        
        self.optionsFrame = LibStub("AceConfigDialog-3.0"):AddToBlizOptions("EventAnnouncer", "Event Announcer")

        self:RegisterChatCommand("ea", "Command")
        
        self.playerName = UnitName("player")
        self.guildThrottleTimer = {}
        self.pending = {}
        
        self.db.Test = "Dit is een test"
        self.db.Guild = {}
        self.db.Guild["Test data"] = {
                [0] = COLOR_HORDE,
                [1] = COLOR_ALLIANCE,
        }
        
        
        self:Print("Initialized")
end

function EventAnnouncer:OnEnable()
        self:RegisterEventConditional("ACHIEVEMENT_EARNED", (self.db.profile.events.ownachievement or self.db.profile.events.guildachievement))
        self:RegisterEventConditional("CHAT_MSG_GUILD_ACHIEVEMENT", self.db.profile.events.guildmemberachievement)
        self:RegisterEventConditional("CHAT_MSG_SKILL", self.db.profile.events.skills)
        self:RegisterEventConditional("PLAYER_LEVEL_UP", self.db.profile.events.levelup)
        self:RegisterEventConditional("PET_BATTLE_LEVEL_CHANGED", self.db.profile.events.battlepetlevelup)
        self:RegisterEventConditional("UNIT_GUILD_LEVEL", self.db.profile.events.guildachievement)
        self:RegisterEventConditional("CHAT_MSG_SYSTEM", (self.db.profile.events.guildchanges or self.db.profile.events.faction))
        
        -- Special case: during logon we cannot query the guild name at this point yet
        self:RegisterEventConditional("GUILD_ROSTER_UPDATE", IsInGuild() and self.currentGuild == nil)

        self:Debug("Enabled")
end

function EventAnnouncer:RegisterEventConditional(event, condition)
        if condition then
                self:RegisterEvent(event)
                self:Debug(GREEN .. event)
        end
end


function EventAnnouncer:OnDisable()
        self:UnregisterEvent("ACHIEVEMENT_EARNED")
        self:UnregisterEvent("PLAYER_LEVEL_UP")
        self:UnregisterEvent("PET_BATTLE_LEVEL_CHANGED")
        self:UnregisterEvent("UNIT_GUILD_LEVEL")
        self:UnregisterEvent("CHAT_MSG_GUILD_ACHIEVEMENT")
        self:UnregisterEvent("CHAT_MSG_SKILL")
        self:UnregisterEvent("CHAT_MSG_SYSTEM")
        self:Debug("Disabled")
end

function EventAnnouncer:ApplySettings()
        self:OnDisable()
        self:OnEnable()
end



function EventAnnouncer:GUILD_ROSTER_UPDATE()
        self.currentGuild = GetGuildInfo("player")
        self:Debug(string.format("Current guild name retrieved:%s", self.currentGuild or "(null)"))
        self:UnregisterEvent("GUILD_ROSTER_UPDATE")
end

function EventAnnouncer:ACHIEVEMENT_EARNED(event, id)
        local isGuildAchievement = select(12, GetAchievementInfo(id))
        if isGuildAchievement then
                if self.db.profile.events.guildachievement then
                        self:AnnounceGuildAchievement(GetGuildInfo("player"), GetAchievementLink(id))
                end
        else
                if self.db.profile.events.ownachievement then
                        self:AnnounceAchievement(self.playerName, GetAchievementLink(id))
                end
        end
end

function EventAnnouncer:CHAT_MSG_GUILD_ACHIEVEMENT(event, msg, playername)

        -- Parse chat message to extract achievement string
        -- (.*) has earned the achievement (.*)!
        local pattern = self:FormatToPattern(ACHIEVEMENT_BROADCAST)
        local _, _, player, achievement = string.find(msg, pattern)
        if not achievement then
                self:Debug("Error: failed to parse ["..msg.."]")
                return
        end

        -- Filter friends, only if configured
        if self.db.profile.events.friendsonly and not self:IsFriend(playername) then
                self:Debug("Skipping, ["..playername.."] is not on friend list")
                return
        end
        
        -- Parse achievement string to extract id
        local _, _, id = string.find(achievement, "|Hachievement:(%d*):")
        if not id then
                self:Debug("Error: failed to parse ["..achievement.."]")
                return
        end
        id = tonumber(id)
        
        -- Stop any throttle timer associated with this achievement
        if self.guildThrottleTimer[id] then
                self:CancelTimer(self.guildThrottleTimer[id], true)
        end
        
        -- Create a new table for this achievement if it didn't exist
        if not self.pending[id] then
                self.pending[id] = {}
                -- And add the clickable link as first entry
                table.insert(self.pending[id], achievement)
        end
        
        -- Append player name to table
        table.insert(self.pending[id], playername)
        
        -- Schedule a flush table timer
        self.guildThrottleTimer[id] = self:ScheduleTimer("Flushguildmemberachievements", self.db.profile.guildThrottleDelay, id)
end


function EventAnnouncer:Flushguildmemberachievements(flushid)

        -- Grab (and remove) clickable achievement link from table
        local achievement = table.remove(self.pending[flushid], 1)

        -- Announce the achievement
        self:AnnounceMultiAchievement(self.pending[flushid], achievement)
        
        -- Clear the table
        self.pending[flushid] = table.wipe(self.pending[flushid])
        
        -- Remove table & timer
        self.guildThrottleTimer[flushid] = nil
        self.pending[flushid] = nil
end

function EventAnnouncer:CHAT_MSG_SKILL(event, msg)
        
        -- You have gained the %s skill
        local pattern1 = self:FormatToPattern(ERR_SKILL_GAINED_S)
        local _, _, skillName = string.find(msg, pattern1)
        if skillName then
                self:AnnounceSkillNew(self.playerName, skillName)
        end
        
        -- Your skill in %s has increased to %d.
        local pattern2 = self:FormatToPattern(ERR_SKILL_UP_SI)
        local _, _, skillName, skillLevel = string.find(msg, pattern2)
        if skillName then
                local milestone = 75
                if EventAnnouncer:IsWeaponSkill(skillName) then
                        milestone = 50
                        skillName = string.format("weapon skill %s", skillName)
                end
                self:Debug("Skill ["..skillName.."] Milestone ["..milestone.."]")
                if skillLevel % milestone == 0 then
                        self:AnnounceSkillMilestone(self.playerName, skillName, skillLevel)
                end
        end
        
end

function EventAnnouncer:PET_BATTLE_LEVEL_CHANGED(event, activePlayer, activePetSlot, newLevel)
        if (activePlayer == LE_BATTLE_PET_ALLY) then
                local petID, _, _ = C_PetJournal.GetPetLoadOutInfo(activePetSlot);
                
                -- speciesID, customName, petLevel, xp, maxXp, displayID, name, petIcon 
        local speciesID, customName, _, _, _, _, name, _ = C_PetJournal.GetPetInfoByPetID(petID);
        
                self:AnnounceBattlePetLevel(self.playerName, name, customName, newLevel, abName)
        end
        
end

function EventAnnouncer:PLAYER_LEVEL_UP(event, lvl)
        --if (lvl > 9) then
                self:AnnounceLevel(self.playerName, lvl)
        --end
end

function EventAnnouncer:UNIT_GUILD_LEVEL(event, unit, lvl)
                if unit == "player" then
                        self:AnnounceGuildLevel(GetGuildInfo(unit), lvl)
                end
end


function EventAnnouncer:CHAT_MSG_SYSTEM(event, msg)
        local pattern
        
        --self:Debug("CHAT_MSG_SYSTEM: "..msg)
        
        if self.db.profile.events.guildchanges then
        
                -- |Hplayer:%s|h[%s]|h invites you to join %s.
                pattern = self:FormatToPattern(ERR_INVITED_TO_GUILD_SSS)
                local _, _, _, _, joinguild = string.find(msg, pattern)
                if joinguild then
                        self.invitedGuild = joinguild
                        self:Debug("Invite received, about to join guild " .. joinguild)
                        return
                end     

                -- %s has joined the guild.
                pattern = self:FormatToPattern(ERR_GUILD_JOIN_S)
                local _, _, invitee = string.find(msg, pattern)
                if invitee == self.playerName then
                        self.currentGuild = self.invitedGuild
                        self:AnnounceGuildChange(self.playerName, "joined", self.currentGuild)
                        return
                end     
                
                -- %s has left the guild.
                pattern = self:FormatToPattern(ERR_GUILD_LEAVE_S)
                local _, _, leaver = string.find(msg, pattern)
                if leaver == self.playerName then
                        self:AnnounceGuildChange(self.playerName, "left", self.currentGuild)
                        self.currentGuild = nil
                        return
                end
        
          -- %s has been kicked out of the guild by %s.
                pattern = self:FormatToPattern(ERR_GUILD_REMOVE_SS)
                local _, _, victim = string.find(msg, pattern)
                if victim == self.playerName then
                        self:AnnounceGuildChange(self.playerName, "was kicked from", self.currentGuild)
                        self.currentGuild = nil
                        return
                end
                
                -- Congratulations, you are a founding member of %s!
                pattern = self:FormatToPattern(ERR_GUILD_FOUNDER_S)
                local _, _, newguild = string.find(msg, pattern)
                if (newguild) then
                        self.currentGuild = newguild
                        self:AnnounceGuildChange(self.playerName, "created", self.currentGuild)
                        return
                end
        end
        
        if self.db.profile.events.faction then
                -- You are now %s with %s.
                pattern = self:FormatToPattern(FACTION_STANDING_CHANGED)
                local _, _, standing, factionName = string.find(msg, pattern)
                if standing then
                        self:AnnounceFaction(self.playerName, standing, factionName)
                        return
                end
        end
end


-- From FizzWidget's FactionFriend
function EventAnnouncer:FormatToPattern(formatString)
        local patternString = formatString;
        
        patternString = string.gsub(patternString, "%%%d+%$([diouXxfgbcsq])", "%%%1"); -- reordering specifiers (e.g. %2$s) stripped    
        patternString = string.gsub(patternString, "([%$%(%)%.%[%]%*%+%-%?%^])", "%%%1"); -- convert regex special characters
        patternString = string.gsub(patternString, "%%c", "(.)"); -- %c to (.)
        patternString = string.gsub(patternString, "%%s", "(.+)"); -- %s to (.+)
        patternString = string.gsub(patternString, "%%[du]", "(%%d+)"); -- %d to (%d+)
        patternString = string.gsub(patternString, "%%([gf])", "(%%d+%%.*%%d*)"); -- %g or %f to (%d+%.*%d*)
                
        return patternString;
end

function EventAnnouncer:IsFriend(player)
        local name
        -- Check for regular characters
        for i = 1, GetNumFriends() do
                name = GetFriendInfo(i)
                if name == player then
                        self:Debug("IsFriend: " .. player .. " is a normal friend")
                        return true
                end
        end
        
        -- Check for real-id friends
        for i = 1, BNGetNumFriends() do
                for j = 1, BNGetNumFriendToons(i) do
                        _, toonName, client, realmName = BNGetFriendToonInfo(i, j)
                        if client == BNET_CLIENT_WOW and toonName == player and realmName == GetRealmName() then
                                self:Debug("IsFriend: " .. player .. " is a real-id friend")
                                return true
                        end
                end
        end
        return false
end

local weaponSkills = { "Axes", "Bows", "Crossbows", "Daggers", "Guns", "Maces", "Swords", "Staves", "Unarmed", "Defense", "Polearms", "Two-Handed Swords", "Two-Handed Maces", "Two-Handed Axes" }
function EventAnnouncer:IsWeaponSkill(skill)
    for k, val in pairs(weaponSkills) do 
        if val == skill then 
            return true
        end 
    end 
    return false 
end

function EventAnnouncer:AnnounceAchievement(who, what)
        self:BroadcastMessage( string.format("%s earned by %s", what, who) )
end

function EventAnnouncer:AnnounceGuildAchievement(who, what)
        self:BroadcastMessage( string.format("%s earned by guild [%s]", what, who) )
end

function EventAnnouncer:AnnounceMultiAchievement(who, what)
        local txt
        if table.getn(who) > self.db.profile.guildMaxNames then
                local cutoff = math.max(self.db.profile.guildMaxNames - 2, 1)
                txt = table.concat(who, ", ", 1, cutoff) .. " and " .. (table.getn(who) - cutoff) .. " more"
        else
                txt = table.concat(who, ", ")
        end
        self:BroadcastMessage( string.format("%s earned by %s", what, txt) )
end

function EventAnnouncer:AnnounceFaction(who, what, withwhom)
        if withwhom == GetGuildInfo("player") then
                self:BroadcastMessage( string.format("%s just hit %s with guild [%s]", who, what, withwhom) )
        else
                self:BroadcastMessage( string.format("%s just hit %s with %s", who, what, withwhom) )
        end
end

function EventAnnouncer:AnnounceSkillNew(who, what)
        self:BroadcastMessage( string.format("%s just gained the %s skill", who, what) )
end

function EventAnnouncer:AnnounceSkillMilestone(who, what, howhigh)
        self:BroadcastMessage( string.format("%s levelled %s to %d", who, what, howhigh) )
end

function EventAnnouncer:AnnounceLevel(who, whatlevel)
        self:BroadcastMessage( string.format("Ding! %s has reached level %d", who, whatlevel) )
end

function EventAnnouncer:AnnounceGuildLevel(whatguild, whatlevel)
        self:BroadcastMessage( string.format("Ding! Guild [%s] reached level %d", whatguild, whatlevel) )
end

function EventAnnouncer:AnnounceBattlePetLevel(who, petname, customname, whatlevel)
        local fullpetname = petname
        if customname then
                fullpetname = string.format("%s the %s", customname, petname)
        end
        self:BroadcastMessage( string.format("Ding! %s's battle pet [%s] reached level %d", who, fullpetname, whatlevel) )
end


function EventAnnouncer:AnnounceGuildChange(who, didwhat, whatguild)
  if (whatguild ~= nil) then
        self:BroadcastMessage( string.format("%s %s the guild [%s]", who, didwhat, whatguild) )
  else
          self:BroadcastMessage( string.format("%s %s some guild", who, didwhat) )
  end
end


function EventAnnouncer:BroadcastMessage(msg)
        if self.db.profile.output.guild then
                SendChatMessage(msg, "GUILD")
        end
        
        if self.db.profile.output.self then
                self:Print(msg)
        end
        
        for key, val in pairs(self.db.profile.output.channel) do
                if val then
                        local chnr = GetChannelName(key)
                        if chnr then
                                SendChatMessage(msg, "CHANNEL", nil, chnr)
                        end
                end
        end
end



----- DEBUGGING
function EventAnnouncer:Debug(msg)
        if self.db.profile.debug then
                self:Print("[DEBUG] ".. msg.."|r")
        end
end


function EventAnnouncer:test1()
        self:ACHIEVEMENT_EARNED("DUMMY", 412)
end
function EventAnnouncer:test2()
        local msg = string.format(FACTION_STANDING_INCREASED, "Argent Dawn", 1500)
        self:CHAT_MSG_COMBAT_FACTION_CHANGE("DUMMY", msg)
end
function EventAnnouncer:test3(n,i)
        local name
        local id
        if n then
                name = n
        else
                name = "Testplayer"
        end
        if i then
                id = i
        else
                id = 412
        end
        
        local msg = string.format("%s has earned the achievement %s!", name, GetAchievementLink(id))
        self:CHAT_MSG_GUILD_ACHIEVEMENT("DUMMY", msg, name)
end



function EventAnnouncer:Command(param)
        --if param == "config" then
                        InterfaceOptionsFrame_OpenToCategory(self.optionsFrame)
        --end
end

----- CONFIG

function EventAnnouncer:GetDefaults()
-- declare defaults to be used in the DB
        return {
                profile = {
                        debug = false,
                        enabled = true,
                        guildThrottleDelay = 1,
                        guildMaxNames = 8,
                        events = {
                                ownachievement = true,
                                guildachievement = true,
                                guildmemberachievement = false,
                                friendsonly = true,
                                faction = true,
                                skills = true,
                                quest = true,
                                levelup = true,
                                battlepetlevelup = true,
                                guildchanges = true,
                        },
                        output = {
                                guild = false,
                                self = false,
                                channel = { },
                        },
                }
        }
end

function EventAnnouncer:GetOptions()
        return {
                name = "Event Announcer",
                type = "group",
                args = {
                        enabled = {
                                name = "Enabled",
                                desc = "Enable or disable the addon",
                                type = "toggle",
                                order = 1,
                                get = function(key) return self.db.profile.enabled end,
                                set = function(key, value)
                                        self.db.profile.enabled = value
                                        if self.db.profile.enabled then
                                                self:Enable()
                                        else
                                                self:Disable()
                                        end
                                end,
                        },
                        debug = {
                                name = "Debug",
                                desc = "Enable or disable debug output",
                                type = "toggle",
                                order = 2,
                                get = function(key) return self.db.profile.debug end,
                                set = function(key, value) self.db.profile.debug = value end,
                        },
                        events = {
                                name = "Events",
                                type = "group",
                                disabled = function() return not self.db.profile.enabled end,
                                get = function(key) return self.db.profile.events[key.arg] end,
                                set = function(key, value)
                                        self.db.profile.events[key.arg] = value
                                        if self.db.profile.enabled then
                                                self:ApplySettings()
                                        end
                                end,
                                args = {
                                        ownachievement = {
                                                name = "Own achievements",
                                                desc = "Send an alert when you gain an achievement",
                                                order = 1,
                                                type = "toggle",
                                                width = "full",
                                                arg = "ownachievement",
                                        },
                                        guildachievement = {
                                          name = "Guild achievements",
                                          desc = "Send an alert when your guild gains an achievement or level",
                                          order = 2,
                                          type = "toggle",
                                          width = "full",
                                          arg = "guildachievement",
                                        },                                      
                                        guildmemberachievement = {
                                                name = "Guildmember achievements",
                                                desc = "Send an alert when anyone in your guild gains an achievement",
                                                order = 3,
                                                type = "toggle",
                                                width = "full",
                                                arg = "guildmemberachievement",
                                        },
                                        friendsonly = {
                                                name = "...but friends only",
                                                desc = "Limit the alerts on guildmember achievements to friends only",
                                                disabled = function() return not ( self.db.profile.events.guildmemberachievement and self.db.profile.enabled ) end,
                                                order = 4,
                                                type = "toggle",
                                                width = "full",
                                                arg = "friendsonly",
                                        },
                                        faction = {
                                                name = "Faction standing changes",
                                                desc = "Send an alert when your status with any faction changes",
                                                order = 5,
                                                type = "toggle",
                                                width = "full",
                                                arg = "faction",
                                        },
                                        skills = {
                                                name = "Skill/Tradeskill milestones",
                                                desc = "Send an alert when you gain a new skill or reach a milestone",
                                                order = 6,
                                                type = "toggle",
                                                width = "full",
                                                arg = "skills",
                                        },
                                        levelup = {
                                                name = "Level-ups",
                                                desc = "Send an alert when you gain a level",
                                                order = 7,
                                                type = "toggle",
                                                width = "full",
                                                arg = "levelup",
                                        },
                                        battlepetlevelup = {
                                                name = "Battle pet level-ups",
                                                desc = "Send an alert when your battle pet gains a level",
                                                order = 8,
                                                type = "toggle",
                                                width = "full",
                                                arg = "battlepetlevelup",
                                        },                                      
                                        guildchanges = {
                                                name = "Guild joins/quits",
                                                desc = "Send an alert when you join or leave a guild",
                                                order = 9,
                                                type = "toggle",
                                                width = "full",
                                                arg = "guildchanges",
                                        },
                                },                              
                        },
                        output = {
                                name = "Output",
                                type = "group",
                                disabled = function() return not self.db.profile.enabled end,
                                get = function(key) return self.db.profile.output[key.arg] end,
                                set = function(key, value) self.db.profile.output[key.arg] = value end,
                                args = {
                                        self = {
                                                name = "Chat frame",
                                                desc = "Outputs a message to the default chat frame",
                                                order = 1,
                                                type = "toggle",
                                                arg = "self",
                                                width = "full",
                                        },
                                        guild = {
                                                name = "Guild",
                                                desc = "Sends a message to guild chat",
                                                order = 2,
                                                confirm = true,
                                                confirmText = "This could cause a lot of spam in guild chat, are you sure you want this?",
                                                type = "toggle",
                                                arg = "guild",
                                                width = "full",
                                        },
                                        custom = {
                                                name = "Custom channel",
                                                order = 3,
                                                type = "multiselect",
                                                width = "full",
                                                values = function()
                                                        return self:GetCustomChannelList()
                                                end,
                                                get = function(info, nr)
                                                        local _,name = GetChannelName(nr)
                                                        return self:IsChannelEnabled(name)
                                                end,
                                                set = function(info, nr, value)
                                                        local _,name = GetChannelName(nr)
                                                        self:EnableChannel(name, value)
                                                end,
                                        },
                                },
                        },
                },
        }
end

function EventAnnouncer:GetCustomChannelList()
        local channels = { GetChannelList() }
        local out = {}
        for i = 1, table.getn(channels), 2 do
                out[channels[i]] = channels[i] .. ". " .. channels[i+1]
        end
        return out
end

function EventAnnouncer:IsChannelEnabled(name)
        return self.db.profile.output.channel[name]
end

function EventAnnouncer:EnableChannel(name, value)
        if value and not self.db.profile.output.channel[name] then
                self.db.profile.output.channel[name] = true
        elseif not value and self.db.profile.output.channel[name] then
                self.db.profile.output.channel[name] = false
        end
end

Compare with Previous | Blame