vanilla-wow-addons – Rev 1

Subversion Repositories:
Rev:

--[[ KLH Threatmeter KLHTM_RaidGui.lua

Lukon Mod 2: Part of the replacement for Gui.lua and Tables.lua. 
Controls the GUI for the raid threat section of KLH ThreatMeter. 
See also KTM_Gui.xml, KTM_Gui.lua.
--]]

local mod = klhtm
local me = { }
mod.guiraid = me


-- The number of rows defined in New_Frame.xml
local Max_Rows = 20;
KLHTM_MaxRaidRows = Max_Rows;

-- If the top threat value is greater than 150% of aggro gain when no master target is set
-- then the threat100 reference value is set to the top threat value. This prevents very
-- large %threat values when mobs use secondary targetting abilities.
local Max_Aggro_Ratio = 1.5

-- Local references to some Gui variables
local options = KLHTM_GuiOptions;
local gui = KLHTM_Gui;
local sizes = KLHTM_GuiSizes;
local state = KLHTM_GuiState;
local heights = KLHTM_GuiHeights;



------------------------------------------------------------------------------
-- Sets up the instance variable "gui.raid". It contains data on the GUI
-- components in the raid threat frame.
------------------------------------------------------------------------------
function KLHTM_CreateRaidTable()
        
        gui.raid = {
                ["frame"] = KLHTM_RaidFrame,
                ["line"] = KLHTM_RaidFrameLine, -- dividing line between title bar and frame
                ["head"] = { -- column headers
                        ["name"] = {
                                ["frame"] = KLHTM_RaidFrameHeaderName,
                                ["text"] = KLHTM_RaidFrameHeaderNameText,
                                ["width"] = 90,
                                ["colour"] = {["r"] = 1.0, ["g"] = 1.0, ["b"] = 1.0},
                                ["vis"] = function() return (options.raid.columnVis.name) end,
                        },
                        ["threat"] = {
                                ["frame"] = KLHTM_RaidFrameHeaderThreat,
                                ["text"] = KLHTM_RaidFrameHeaderThreatText,
                                ["width"] = 45,
                                ["colour"] = {["r"] = 1.0, ["g"] = 1.0, ["b"] = 1.0},
                                ["vis"] = function() return (options.raid.columnVis.threat) end,
                        },
                        ["pc"] = {
                                ["frame"] = KLHTM_RaidFrameHeaderPercentThreat,
                                ["text"] = KLHTM_RaidFrameHeaderPercentThreatText,
                                ["width"] = 40,
                                ["colour"] = {["r"] = 1.0, ["g"] = 1.0, ["b"] = 1.0},
                                ["vis"] = function() return (options.raid.columnVis.pc) end,
                        },
                },
                ["rows"] = {},
                ["bottom"] = { -- bottom bar
                        ["frame"] = KLHTM_RaidFrameBottom,
                        ["line"] = KLHTM_RaidFrameBottomLine, -- dividing line between frame and bottom bar
                        ["tdef"] = {
                                ["frame"] = KLHTM_RaidFrameBottomThreatDefecit,
                                ["text"] = KLHTM_RaidFrameBottomThreatDefecitText,
                                ["width"] = 40,
                        },
                        ["targ"] = {
                                ["frame"] = KLHTM_RaidFrameBottomMasterTarget,
                                ["text"] = KLHTM_RaidFrameBottomMasterTargetText,
                                --["width"] = 50,
                                -- should take up whatever remaining space there is
                        },
                },
        };
        
        for x = 1 , Max_Rows do
                gui.raid.rows[x] = {
                        ["frame"] = getglobal("KLHTM_RaidFrameRow" .. x),
                        ["name"] = {
                                ["frame"] = getglobal("KLHTM_RaidFrameRow" .. x .. "Name"),
                                ["text"] = getglobal("KLHTM_RaidFrameRow" .. x .. "NameText"),
                        },
                        ["threat"] = {
                                ["frame"] = getglobal("KLHTM_RaidFrameRow" .. x .. "Threat"),
                                ["text"] = getglobal("KLHTM_RaidFrameRow" .. x .. "ThreatText"),
                        },
                        ["pc"] = {
                                ["frame"] = getglobal("KLHTM_RaidFrameRow" .. x .. "PercentThreat"),
                                ["text"] = getglobal("KLHTM_RaidFrameRow" .. x .. "PercentThreatText"),
                        },
                        ["bar"] = getglobal("KLHTM_RaidFrameRow" .. x .. "Bar"),
                };
        end
end


------------------------------------------------------------------------------
-- Applies Gui component properties that are not specified in the XML
------------------------------------------------------------------------------
function KLHTM_SetupRaidGui()
        
        -- headers
        for index, header in gui.raid.head do
                header.text:SetText(mod.string.get("gui", "raid", "head", index));
                header.frame:SetHeight(heights.header);
                KLHTM_AddOutline(header.text);
                KLHTM_LocaliseStringWidth(header);
                
                for _, row in gui.raid.rows do
                        row[index].text:SetTextColor(header.colour.r, header.colour.g, header.colour.b);
                        row[index].frame:SetHeight(heights.data);
                        KLHTM_AddOutline(row[index].text);
                end
        end
        
        -- rows
        for _, row in gui.raid.rows do
                row.frame:SetHeight(heights.data);
        end
        
        -- botton bar
        gui.raid.bottom.frame:SetHeight(heights.data);
        gui.raid.bottom.tdef.frame:SetHeight(heights.data);
        gui.raid.bottom.targ.frame:SetHeight(heights.data);
end


------------------------------------------------------------------------------
-- Sets the default options for displaying the main window and title bar strings
-- when the raid view is selected.
------------------------------------------------------------------------------
function KLHTM_SetDefaultRaidOptions()
        
        options.raid = {
                -- column visibility
                ["columnVis"] = {
                        ["name"] = true,
                        ["threat"] = true,
                        ["pc"] = true,
                },
                -- title bar string visibility
                ["stringVis"] = {
                        ["rank"] = false,
                        ["pc"] = false,
                        ["tdef"] = false,
                },
                -- max number of rows to show
                ["rows"] = 10,
                -- if true, rows with 0 threat are not shown
                ["hideZeroRows"] = true,
                -- if true, the raid window will shrink if there are fewer data rows
                -- than the specified in ["rows"]. Otherwise empty rows will be shown.
                ["resize"] = false,
                -- if true, numbers 10,000 or greater are abbreviated with "k"
                ["abbreviate"] = false,
                -- if true, a virtual player "aggro gain" is shown
                ["showAggroGain"] = true,
                -- if true, the bottom bar will not be shown
                ["hideBottomBar"] = false,
        };
end


------------------------------------------------------------------------------
-- Updates the visibility of columns the raid table and the bottom bar. The
-- contents are not rendered here. The frame width is stored in sizes.self.x.
-- Should be called: 
--
-- a) when the column visibility changes
-- b) when the number of rows to be drawn changes
------------------------------------------------------------------------------
function KLHTM_UpdateRaidFrame()
        
        sizes.raid.x = 0;
        
        for column, header in gui.raid.head do
                -- header
                if (header.vis()) then
                        header.frame:SetWidth(header.width);
                        sizes.raid.x = sizes.raid.x + header.width;
                        header.frame:Show();
                else
                        header.frame:Hide();
                        header.frame:SetWidth(0.1);
                end
                -- rows
                for index, row in gui.raid.rows do
                        if (header.vis()) then
                                row[column].frame:SetWidth(header.width);
                                row[column].frame:Show();
                        else
                                row[column].frame:Hide();
                                row[column].frame:SetWidth(0.1);
                        end
                end
        end
        
        for _, row in gui.raid.rows do
                row.frame:SetWidth(sizes.raid.x);
        end
        
        -- bottom bar
        gui.raid.bottom.tdef.frame:SetWidth(gui.raid.bottom.tdef.width);
        -- do we need this now that we have dual anchors?
        gui.raid.bottom.targ.text:SetWidth(gui.raid.bottom.targ.frame:GetWidth());
        
        if (options.raid.hideBottomBar) then
                gui.raid.bottom.frame:Hide();
        else
                gui.raid.bottom.frame:Show();
        end
end


------------------------------------------------------------------------------
-- Draws the minimised title bar strings present in the raid view.
------------------------------------------------------------------------------
function KLHTM_DrawRaidStrings(raidData, playerCount, threat100)
        
        -- update title bar strings
        local userThreat = mod.table.raiddata[UnitName("player")];
        if userThreat == nil then
                userThreat = 0
        end
        
        -- threat defecit (todo: colours?)
        local defecit = threat100 - userThreat;
        if (options.raid.abbreviate) then
                defecit = KLHTM_Abbreviate(defecit);
        end
        
        -- threat rank
        local userRank = 1;
        for _, data in raidData do
                if (data.threat > userThreat) then
                        userRank = userRank + 1;
                end
        end
        
        if (threat100 == 0) then
                gui.title.string.tdef.text:SetText("0");
                gui.title.string.pc.text:SetText("0%");
                gui.title.string.rank.text:SetText("-/" .. playerCount);
        else
                gui.title.string.tdef.text:SetText(defecit);
                gui.title.string.pc.text:SetText(math.floor(userThreat * 100 / threat100 + 0.5) .. "%");
                gui.title.string.rank.text:SetText(userRank .. "/" .. playerCount);
        end
end


------------------------------------------------------------------------------
-- Draws raid the bottom bar strings
--
-- [data] - the sorted threat data
-- [threat100] - ??

-- help i am broken.
------------------------------------------------------------------------------
function KLHTM_DrawRaidBottom(data, threat100, playerCount, userThreat)
        
        -- master target
        if (mod.boss.mastertarget ~= nil) then
                gui.raid.bottom.targ.text:SetText(mod.boss.mastertarget);
        else
                gui.raid.bottom.targ.text:SetText("");
        end
        
        -- new threat defecit ... maybe... 
        if (false) then
                if ((mod.boss.mastertarget ~= nil) and (mod.boss.mttruetarget ~= nil) and
                        (mod.tables.raiddata[mod.boss.mttruetarget] ~= nil)) then
                        -- there is an active, valid master target and targettarget
                        
                        if (mod.boss.mttruetarget == UnitName("player")) then
                                -- we are the MT. either someone above us, or below us
                        end
                end
        end
        
        
        
        -- threat defecit. Several options here. (a) we are MT, show distance to no2. 
        -- (b) we are dps, show defecit from MT \ aggro gain. (c) all zero.
        -- How do we know what threat100 is referring to?
        
        local defecit = threat100 - userThreat;
        if (defecit == 0) then
                defecit = "";
        elseif (options.raid.abbreviate) then
                defecit = KLHTM_Abbreviate(defecit);
        end
        gui.raid.bottom.tdef.text:SetText(defecit);
        
        
        
end


-- used by GetRaidData(). Defined at the class level to reduce memory use.
local GetRaidData_data;
------------------------------------------------------------------------------
-- Makes a copy of the raid threat data from KLHTM_RaidData for use by 
-- KLHTM_DrawRaidFrame and performs some processing.
--
-- returns:
-- [data] - the sorted threat data (with zero-pruning only),
-- [playerCount] - the number of preporting players (virtual and real),
-- [threat100] - the reference value for %max threat calculations
------------------------------------------------------------------------------
function KLHTM_GetRaidData()
        
        local data = GetRaidData_data;
        
        if (data == nil) then
                data = {};
                -- 50: 40 players + room for "virtual players" eg aggro gain
                for x = 1, 50 do 
                        data[x] = {["name"] = "", ["threat"] = 0, ["pc"] = 0,};
                end
                
                GetRaidData_data = data
        end
        
        -- check for aggro gain
        if (options.raid.showAggroGain) then
                mod.boss.updateaggrogain()
        else
                mod.table.raiddata[mod.string.get("misc", "aggrogain")] = nil;
        end
        
        -- copy data over
        local rowCount = 0; -- the number of rows to be rendered
        local playerCount = 0; -- the number of players found
        
        for player, threat in mod.table.raiddata do
                playerCount = playerCount + 1;
                
                -- omit "zero rows" if necessary
                if (not(options.raid.hideZeroRows and (threat == 0))) then
                        rowCount = rowCount + 1;
                        data[rowCount].name = player;
                        data[rowCount].threat = threat;
                end
        end
        table.setn(data, rowCount);
        
        table.sort(data, function(a,b) return a.threat > b.threat; end); 
        
        -- determine the %threat reference value
        -- this part is highly suspect. Need the updated boss module, then a recode
        -- of the threat100 and related calculations.
        local threat100; local aggro;
        
        if (rowCount == 0) then
                -- there is no data availible
                threat100 = 0;
        else
                if (options.raid.showAggroGain == false) then
                        -- ignore aggro gain. Wrong!
                        threat100 = data[1].threat;
                else
                        -- use MT if possible, or targettarget
                        if (mod.boss.mastertarget == nil) then
                                aggro = mod.table.raiddata[mod.string.get("misc", "aggrogain")];
                        else
                                aggro = mod.table.raiddata[mod.boss.mttruetarget];
                        end
                        -- ignore unreasonable threat100 values
                        if ((aggro == nil) or (aggro * Max_Aggro_Ratio < data[1].threat)) then
                                threat100 = data[1].threat;
                        else
                                threat100 = aggro;
                        end
                end
        end
        
        return data, playerCount, threat100;
end


------------------------------------------------------------------------------
-- Updates the raid threat window (if maximised) and title bar raid strings.
-- Updates the raid threat data. A copy of KLHTM_RaidData is made, and processed.
-- If minimised, KLHTM_DrawRaidStrings is called. Otherwise all the strings in
-- the raid frame are redrawn.
------------------------------------------------------------------------------
function KLHTM_DrawRaidFrame()
        
        local data, playerCount, threat100 = KLHTM_GetRaidData();
        
        if (state.min) then
                KLHTM_DrawRaidStrings(data, playerCount, threat100);
                return;
        end
        
        local userThreat = mod.table.raiddata[UnitName("player")];
        if (userThreat == nil) then
                -- seems to happen at initialisation
                userThreat = 0;
        end
        
        -- make sure the user is visible (user may not show up with 0 threat)
        if (table.getn(data) > options.raid.rows) then
                if (userThreat < data[options.raid.rows].threat) then
                        data[options.raid.rows].name = UnitName("player");
                        data[options.raid.rows].threat = userThreat;
                end
                
                -- ignore rows that won't be drawn from here on
                table.setn(data, options.raid.rows);
        end
        
        -- calculate % threat
        for x = 1, table.getn(data) do
                if (threat100 == 0) then
                        data[x].pc = 0;
                else
                        data[x].pc = math.floor(data[x].threat / threat100 * 100);
                end
        end

        -- bar reference width (max threat)
        local barRef;
        if ((data[1] ~= nil) and (data[1].threat ~= 0)) then
                barRef = sizes.raid.x / data[1].threat;
        end
        
        -- render the rows
        for row = 1, table.getn(data) do
                for index, value in data[row] do
                        if (options.raid.abbreviate) then
                                gui.raid.rows[row][index].text:SetText(KLHTM_Abbreviate(value));
                        else
                                gui.raid.rows[row][index].text:SetText(value);
                        end
                end
                -- bars
                if ((barRef == nil) or (data[row].threat == 0)) then
                        gui.raid.rows[row].bar:Hide();
                else
                        local colours = KLHTM_GetClassColours(data[row].name);
                        gui.raid.rows[row].bar:SetWidth(data[row].threat * barRef);
                        gui.raid.rows[row].bar:SetVertexColor(colours.r, colours.g, colours.b);
                        gui.raid.rows[row].bar:Show();
                end
                gui.raid.rows[row].frame:Show();
        end
        
        -- bottom bar
        if (options.raid.hideBottomBar ~= true) then
                KLHTM_DrawRaidBottom(data, threat100, playerCount, userThreat);
        end

        -- hide empty rows
        for row = table.getn(data) + 1, Max_Rows do
                gui.raid.rows[row].frame:Hide();
        end
        
        -- resize frame
        if (options.raid.resize) then
                sizes.raid.y = heights.header + heights.data * table.getn(data);
        else
                sizes.raid.y = heights.header + heights.data * options.raid.rows;
        end
        
        if (options.raid.hideBottomBar ~= true) then
                sizes.raid.y = sizes.raid.y + heights.data + 2;
        end
        
        -- 14: (5 + 1) * 2 for the insets plus a gap. 
        -- Then 2 each for the title-header, header-data and (optional) data-bottom gaps.
        sizes.frame.y = sizes.raid.y + sizes.title.y + 14;
        gui.frame:SetHeight(sizes.frame.y);
end


-- used to unlocalise class names
local _classes = {"warrior", "druid", "priest", "shaman", "mage", "warlock", "rogue", "hunter", "paladin"}

------------------------------------------------------------------------------
-- Returns the class colours of the specified player
--
-- [return]: A table with .r, .g, .b values from 0 to 1.
------------------------------------------------------------------------------
function KLHTM_GetClassColours(playerName)
        
        local className;
        
        -- apply pre-defined colours
        if (playerName == UnitName("player")) then
                return {["r"] = 1.0, ["g"] = 0, ["b"] = 0};
        end
        
        if (playerName == mod.string.get("misc", "aggrogain")) then
                return {["r"] = 0, ["g"] = 0, ["b"] = 1.0};
        end
        
        className = mod.table.raidclasses[playerName];
        
        if (className == nil) then
                -- the player's class isnt stored in our table, rebuild it.
                if mod.out.checktrace("info", me, "raidcolours") then
                        mod.out.printtrace(string.format("Updating class entry for %s.", playerName));
                end
                
                mod.table.redoraidclasses();
                className = mod.table.raidclasses[playerName];
        end
        
        if (className == nil) then
                -- class name could not be found. Seems to be due to people who have left
                -- the raid group?
                if mod.out.checktrace("warning", me, "raidcolours") then
                        mod.out.printtrace(string.format("Updating class entry for %s.", playerName))
                end
                
                mod.table.raidclasses[playerName] = "";
                className = "";
        end
        
        className = string.upper(className)
        
        if (className == "") then
                return {["r"] = 0.5, ["g"] = 0.5, ["b"] = 0.5};
        else
                return RAID_CLASS_COLORS[className];
        end
end


------------------------------------------------------------------------------
-- Called when the user mouses over a raid string
------------------------------------------------------------------------------
function KLHTM_RaidString_OnEnter(name)
        
        if (name == "targ") then
                if (mod.boss.mastertarget ~= nil) then
                        
                        local text = string.format(mod.string.get("gui", "raid", "stringlong", name),
                                mod.boss.mastertarget); 
                                
                        text = string.format("|cffffc900%s\n|r%s",
                                mod.string.get("gui", "raid", "stringshort", name), text);

                        GameTooltip:SetOwner(this, "ANCHOR_BOTTOMRIGHT", -100, 0);
                        GameTooltip:SetText(text, 1.0, 1.0, 1.0, 1, 1);
                        GameTooltip:Show();
                        gui.raid.bottom[name].text:SetTextColor(1.0, 0.82, 0);
                end
        end
        
        -- threat defecit text disabled for the moment
end

function KLHTM_RaidString_OnLeave(name)
        gui.raid.bottom[name].text:SetTextColor(1.0, 1.0, 1.0);
        GameTooltip:Hide();
end

Generated by GNU Enscript 1.6.5.90.