WoWInterface SVN RaidWatch2

[/] [trunk/] [RaidWatch/] [RaidWatch_Logger/] [RaidWatch_Logger.lua] - Rev 22

Compare with Previous | Blame | View Log

-- TODO: Localize this data
--[[
        Mostly a copy of transcriptor, with changes to the formating.
--]]
local mod = LibStub("AceAddon-3.0"):NewAddon("RaidWatch2_Logger", "AceEvent-3.0", "AceConsole-3.0")
local RW = LibStub("AceAddon-3.0"):GetAddon("Raid Watch")
local party = RW.Party

local logName = ""
local activeLog = {}
local insert = table.insert
local fmt = string.format
local logStartTime = nil

local AL = LibStub("AceLocale-3.0")
local L = AL:GetLocale("RaidWatch2_Logger")

-- Format is : [time] areaid/dungeon@difficulty (rev)
local logNameFormat = "[%s] %d/%s@%s-%d (r%d)"
local lineFormat = "<%s> %s"
local totalFormat = "[%s] %s"
local eventsToTrack = {
        "PLAYER_REGEN_DISABLED",
        "PLAYER_REGEN_ENABLED",
        "CHAT_MSG_MONSTER_EMOTE",
        "CHAT_MSG_MONSTER_SAY",
        "CHAT_MSG_MONSTER_WHISPER",
        "CHAT_MSG_MONSTER_YELL",
        "CHAT_MSG_RAID_WARNING",
        "CHAT_MSG_RAID_BOSS_EMOTE",
        "CHAT_MSG_RAID_BOSS_WHISPER",
        "PLAYER_TARGET_CHANGED",
        "UNIT_SPELLCAST_START",
        "UNIT_SPELLCAST_STOP",
        "UNIT_SPELLCAST_SUCCEEDED",
        "UNIT_SPELLCAST_INTERRUPTED",
        "UNIT_SPELLCAST_CHANNEL_START",
        "UNIT_SPELLCAST_CHANNEL_STOP",
        "UPDATE_WORLD_STATES",
        "WORLD_STATE_UI_TIMER_UPDATE",
        "COMBAT_LOG_EVENT_UNFILTERED",
        "INSTANCE_ENCOUNTER_ENGAGE_UNIT",       
}
local aliases = {
        ["COMBAT_LOG_EVENT_UNFILTERED"] = "CLEU",
        ["PLAYER_REGEN_DISABLED"] = "REGEN_DISABLED",
        ["PLAYER_REGEN_ENABLED"] = "REGEN_ENABLED",
        ["CHAT_MSG_MONSTER_EMOTE"] = "MONSTER_EMOTE",
        ["CHAT_MSG_MONSTER_SAY"] = "MONSTER_SAY",
        ["CHAT_MSG_MONSTER_WHISPER"] = "MONSTER_WHISPER",
        ["CHAT_MSG_MONSTER_YELL"] = "MONSTER_YELL",
        ["CHAT_MSG_RAID_WARNING"] = "RAID_WARNING",
        ["CHAT_MSG_RAID_BOSS_EMOTE"] = "RAID_BOSS_EMOTE",
        ["CHAT_MSG_RAID_BOSS_WHISPER"] = "RAID_BOSS_WHISPER",
        ["UNIT_SPELLCAST_START"] = "CAST_START",
        ["UNIT_SPELLCAST_STOP"] = "CAST_STOP",
        ["UNIT_SPELLCAST_SUCCEEDED"] = "CAST_SUCCEEDED",
        ["UNIT_SPELLCAST_INTERRUPTED"] = "CAST_INTERRUPTED",
        ["UNIT_SPELLCAST_CHANNEL_START"] = "CAST_CHANNEL_START",
        ["UNIT_SPELLCAST_CHANNEL_STOP"] = "CAST_CHANNEL_STOP",
        ["UNIT_SPELLCAST_INTERRUPTIBLE"] = "CAST_INTERRUPTIBLE",
        ["UNIT_SPELLCAST_NOT_INTERRUPTIBLE"] = "CAST_NOT_INTERRUPTIBLE",
        ["INSTANCE_ENCOUNTER_ENGAGE_UNIT"] = "ENGAGE",
        ["WORLD_STATE_UI_TIMER_UPDATE"] = "WORLD_TIMER",
        ["UPDATE_WORLD_STATES"] = "WORLD_STATE",
}
local menu = {}
local popupFrame = CreateFrame("Frame", "RaidWatch2LoggerMenu", eventFrame, "UIDropDownMenuTemplate")
local function openMenu(frame)
        EasyMenu(menu, popupFrame, frame, 20, 4, "MENU")
end
local function strjoin(delimiter, ...)
        local ret = nil
        for i = 1, select("#", ...) do
                ret = (ret or "") .. tostring((select(i, ...))) .. ":"
        end
        return ret
end

local default = {
        profile = {
                Minimap = {
                        hide = true,
                }
        }
}

function mod:OnInitialize()
        
        local db = LibStub("AceDB-3.0"):New("RaidWatch2LoggerDB", default, "Default")
        self.db = db.profile
        self.db.Minimap = self.db.Minimap or {}
        self.db.Log = self.db.Log or {}
        self.db.IgnoredEvents = self.db.IgnoredEvents or {}
        self.db.version = 1
        self.logging = false
end

function mod:OnEnable()
        self:RegisterChatCommand("rwlog", "SlashHandler")
        for i, v in next, eventsToTrack do
                table.insert(menu, {
                        text = v,
                        tooltipTitle = v,
                        tooltipText = L["Disable logging of %s events."]:format(v),
                        func = function() mod.db.IgnoredEvents[v] = not mod.db.IgnoredEvents[v] end,
                        checked = function() return mod.db.IgnoredEvents[v] end,
                })
        end
        self:SetUpLDB()
end

function mod:ClearLog()
        if self.logging then
                print(L["Stop the log before trying to clear it."])
        else
                print(L["Clearing log."])
                self.db.Log = {}
                self.db.IgnoredEvents = {}
        end
        
end

-- TODO move to thier own functions
local sh = {}
function mod.UPDATE_WORLD_STATES()
        local ret = nil
        for i = 1, GetNumWorldStateUI() do
                local m = strjoin(":", GetWorldStateUIInfo(i))
                if m and m:trim() ~= "0:" then
                        ret = (ret or "") .. "|" .. m
                end
        end
        return ret
end
mod.WORLD_STATE_UI_TIMER_UPDATE = mod.UPDATE_WORLD_STATES
function mod.COMBAT_LOG_EVENT_UNFILTERED(_, ...) return strjoin(":", ...) end
function mod.PLAYER_REGEN_DISABLED() return " *START* " end
function mod.PLAYER_REGEN_ENABLED() return " *END* " end
function mod.UNIT_SPELLCAST_STOP(unit) return UnitName(unit) end
mod.UNIT_SPELLCAST_CHANNEL_STOP = mod.UNIT_SPELLCAST_STOP
mod.UNIT_SPELLCAST_INTERRUPTED = mod.UNIT_SPELLCAST_STOP

function mod.PLAYER_TARGET_CHANGED()
        if UnitExists("target") and not UnitInRaid("target") then
                local level = UnitLevel("target") or "nil"
                local reaction = "Hostile"
                if UnitIsFriend("target", "player") then reaction = "Friendly" end
                local classification = UnitClassification("target") or "nil"
                local creatureType = UnitCreatureType("target") or "nil"
                local typeclass
                if classification == "normal" then typeclass = creatureType else typeclass = (classification.." "..creatureType) end
                local name = UnitName("target") or "nil"
                local mobid = "nil"
                local guid = UnitGUID("target")
                if guid then
                        mobid = tonumber(guid:sub(7, 10), 16)
                end
                return (fmt("[%s|%s|%s]:[%s|%s|%s]", tostring(level), tostring(reaction), tostring(typeclass), tostring(name), tostring(guid), tostring(mobid)))
        end
end
function mod.UNIT_SPELLCAST_START(unit)
        local spell, rank, displayName, icon, startTime, endTime = UnitCastingInfo(unit)
        if not spell then return end
        local time = ((endTime - startTime) / 1000)
        return fmt("[%s][%s][%s][%s][%s][%s]", UnitName(unit), tostring(spell), tostring(rank), tostring(displayName), tostring(icon), tostring(time))
end
function mod.UNIT_SPELLCAST_CHANNEL_START(unit)
        local spell, rank, displayName, icon, startTime, endTime = UnitChannelInfo(unit)
        if not spell then return end
        local time = ((endTime - startTime) / 1000)
        return fmt("[%s][%s][%s][%s][%s][%s]", UnitName(unit), tostring(spell), tostring(rank), tostring(displayName), tostring(icon), tostring(time))
end

function mod.CHAT_MSG_RAID_BOSS_EMOTE(...)
        local message, sender, _,_,target,_,_,_,_,_,_ = ...
        -- scan party to fin the send
        local bossGUID
        for _, player in pairs(party.group) do
                if UnitName(player.id.."target") == sender then
                        bossGUID = UnitGUID(player.id.."target")
                end
        end
        health = -1
        if bossGUID then
                health = UnitHealth(bossGUID) / UnitHealthMax(bossGUID)
                health = math.floor(100 * health)
        end
        -- if we could find the target, record the health at the time of the yell.
        return fmt("%s:%s:%s:%d",message,sender,target,health)
end
mod.CHAT_MSG_MONSTER_EMOTE = mod.CHAT_MSG_RAID_BOSS_EMOTE
mod.CHAT_MSG_MONSTER_SAY = mod.CHAT_MSG_RAID_BOSS_EMOTE
mod.CHAT_MSG_MONSTER_YELL = mod.CHAT_MSG_RAID_BOSS_EMOTE
mod.CHAT_MSG_MONSTER_WHISPER = mod.CHAT_MSG_RAID_BOSS_EMOTE
mod.CHAT_MSG_RAID_BOSS_WHISPER = mod.CHAT_MSG_RAID_BOSS_EMOTE
mod.CHAT_MSG_RAID_WARNING = mod.CHAT_MSG_RAID_BOSS_EMOTE


function mod.UNIT_SPELLCAST_SUCCEEDED(unit, ...) return strjoin(":", UnitName(unit), ...) end

function mod:EventHandler(event,...)
        if self.db.IgnoredEvents[event] then return end
        local line = nil
        if self[event] and event:find("^UNIT_SPELLCAST") then
                local unit = ...
                if not UnitExists(unit) or UnitInRaid(unit) or UnitInParty(unit) or UnitIsFriend("player", unit) then return end
                line = self[event](...)
        elseif self[event] then
                line = self[event](...)
        else
                line = strjoin(":", ...)
        end
        if type(line) ~= "string" or line:len() < 5 then return end
        local e = aliases[event] or event
        local t = GetTime() - logStartTime
        insert(activeLog.total, lineFormat:format(fmt("%.1f", t), totalFormat:format(e, line)))
        -- We only have CLEU in the total log, it's way too much information to log twice.
        if event == "COMBAT_LOG_EVENT_UNFILTERED" then return end
        if type(activeLog[e]) ~= "table" then activeLog[e] = {} end
        insert(activeLog[e], lineFormat:format(fmt("%.1f", t), line))
end

function mod:StopLog()
        self.logging = false
        self.ldbojb.icon = [[Interface\Icons\INV_Misc_Book_14.blp]]
        self.ldbojb.text = L["Raid Watch2 Loggger |cff696969Idle|r"]
        self:UnregisterAllEvents()
end

function mod:StartLog(silent)
        if self.logging then return nil end
        self.logging = true
        self.ldbojb.icon = [[Interface\Icons\INV_Misc_Note_04.blp]]
        self.ldbojb.text = L["Raid Watch 2 Logger |cffFF0000Recording|r"]
        logStartTime = GetTime()
        local name, itype, difficulty, difficultyName,  maxPlayers, playerDifficulty, isDynamicInstance  = GetInstanceInfo()
        logName = logNameFormat:format(date("%H:%M:%S"), GetCurrentMapAreaID(), GetRealZoneText(), itype, difficulty, revision or 1)
        if type(self.db.Log[logName]) ~= "table" then self.db.Log[logName] = {} end
        if type(self.db.IgnoredEvents) ~= "table" then self.db.IgnoredEvents = {} end
        activeLog = self.db.Log[logName]
        if type(activeLog.total) ~= "table" then activeLog.total = {} end
        for i, event in next, eventsToTrack do
                self:RegisterEvent(event,"EventHandler")
        end
end

function mod:SlashHandler(input, button, ...)
        local LI = LibStub("LibDBIcon-1.0",true)
        if input == "" then
                if self.logging then
                        mod:StopLog()
                else
                        mod:StartLog()
                end
        elseif input == "clear" then
                mod:ClearLog()
        elseif input == "show" then
                mod.db.Minimap.hide = false
                if LI then
                        LI:Show("RW2Log")
                end
        elseif input == "hide" then
                mod.db.Minimap.hide = true
                if LI then
                        LI:Hide("RW2Log")
                end
        end
end

function mod:SetUpLDB()
        local LDB = LibStub("LibDataBroker-1.1")
        if not LDB then print("NO LDB") end
        local l = LDB:NewDataObject("RW2Log")
        l.type = "data source"
        l.icon = [[Interface\Icons\INV_Misc_Book_14.blp]]
        l.tocname = "RaidWatch_Logger"
        l.text = L["Raid Watch2 Loggger |cff696969Idle|r"]
        l.OnClick = function(self, button)
                if button == "LeftButton"  then
                        if IsAltKeyDown() then
                                mod:ClearLog()
                        else
                                if not mod.logging then
                                        mod:StartLog()
                                elseif mod.logging then
                                        mod:StopLog()
                                end
                        end
                elseif button == "RightButton" then
                        openMenu(self)
                end
        end
        l.OnTooltipShow = function(tt)
                if mod.logging then
                        tt:AddLine(logName, 1, 1, 1, 1)
                else
                        tt:AddLine(L["|cff696969Idle|r"], 1, 1, 1, 1)
                end
                tt:AddLine(" ")
                tt:AddLine(L["|cffeda55fClick|r to start or stop transcribing. |cffeda55fRight-Click|r to configure events. |cffeda55fAlt-Left Click|r to clear all stored transcripts."], 0.2, 1, 0.2, 1)
        end
        local LibDBIcon = LibStub("LibDBIcon-1.0")
        if not LibDBIcon then return end
        LibDBIcon:Register("RW2Log", l, mod.db.Minimap)
        self.ldbojb = l
end

Compare with Previous | Blame