vanilla-wow-addons – Rev 1

Subversion Repositories:
Rev:
--[[

        Name:           MobHealth2
        Version:        2.6
        Author:         Wyv (wyv@wp.pl)
        Description:    Displays health value for mobs.
                        Original version by Telo.
        URL:            http://www.curse-gaming.com/mod.php?addid=1087
                        http://ui.worldofwar.net/ui.php?id=681
                        http://www.wowinterface.com/downloads/fileinfo.php?id=3938
                        
]]


-- Current target data
local lTargetData;

-- table of event handlers
local lEventHandler = {};

local COLOR_BLUE        = "|c009090FF";
local COLOR_WHITE       = "|c00FFFFFF";
local TITLE             = "|c003060FFMobHealth2"..COLOR_WHITE;

--------------------------------------------------------------------------------------------------
-- external functions for macros / scripts
--   - return value:
--     * (current hp or max hp) if a mob is selected and it's health is known
--     * 0 otherwise
--------------------------------------------------------------------------------------------------

function MobHealth_GetTargetCurHP()
        if ( lTargetData ) then
                return math.floor(lTargetData.currentHealthPercent * lTargetData.PPP + 0.5);
        end     
end

function MobHealth_GetTargetMaxHP()
        if ( lTargetData ) then
                return math.floor(100 * lTargetData.PPP + 0.5);
        end             
end

--------------------------------------------------------------------------------------------------
-- external functions for macros / scripts
--   - return value:
--     curHP, maxHP = MobHealth_GetUnitHP(unit)
--     curHP and maxHP equal 0 if unknown
--     (for unit = "target" or unit = "mouseover" etc.)
--     (please use MobHealth_GetTargetCurHP / MaxHP if you are always intrested in unit="target"
--     (they are faster)
--------------------------------------------------------------------------------------------------

--------------------------------------------------------------------------------------------------
-- Internal functions
--   - all MobHealthDB access functions are left intact for compatiblity
--   - MobHealth is no longer local (but it's not a recomended way to access mob health - even tho
--     it's better than using MobHealthDB directly)
--------------------------------------------------------------------------------------------------

function MobHealth_PPP(index)
        if ( index and MobHealthDB[index] ) then
                local s, e;
                local pts;
                local pct;
                
                s, e, pts, pct = string.find(MobHealthDB[index], "^(%d+)/(%d+)$");
                if ( pts and pct ) then
                        pts = pts + 0;
                        pct = pct + 0;
                        if ( pct ~= 0 ) then
                                return pts / pct;
                        end
                end
        end
        return 0;
end

local function MobHealth_Pts(index)
        if ( index and MobHealthDB[index] ) then
                local s, e;
                local val;
                
                s, e, val = string.find(MobHealthDB[index], "^(%d+)/");
                
                if ( val ) then
                        return val + 0;
                end
        end
        return 0;
end

local function MobHealth_Pct(index)
        if ( index and MobHealthDB[index] ) then
                local s, e;
                local val;
                
                s, e, val = string.find(MobHealthDB[index], "/(%d+)$");
                
                if ( val ) then
                        return val + 0;
                end
        end
        return 0;
end

local function MobHealth_Set(index, pts, pct)
        if ( index ) then
                if ( pts ) then
                        pts = pts + 0;
                else
                        pts = 0;
                end
                if ( pct ) then
                        pct = pct + 0;
                else
                        pct = 0;
                end
                if ( pts == 0 and pct == 0 ) then
                        MobHealthDB[index] = nil;
                else
                        MobHealthDB[index] = pts.."/"..pct;
                end
        end
end



local function MobHealthPlayer_Pts(index)
        if ( index and MobHealthPlayerDB[index] ) then
                local s, e;
                local val;
                
                s, e, val = string.find(MobHealthPlayerDB[index], "^(%d+)/");
                
                if ( val ) then
                        return val + 0;
                end
        end
        return 0;
end

local function MobHealthPlayer_Pct(index)
        if ( index and MobHealthPlayerDB[index] ) then
                local s, e;
                local val;
                
                s, e, val = string.find(MobHealthPlayerDB[index], "/(%d+)$");
                
                if ( val ) then
                        return val + 0;
                end
        end
        return 0;
end

local function MobHealthPlayer_Set(index, pts, pct)
        if ( index ) then
                if ( pts ) then
                        pts = pts + 0;
                else
                        pts = 0;
                end
                if ( pct ) then
                        pct = pct + 0;
                else
                        pct = 0;
                end
                if ( pts == 0 and pct == 0 ) then
                        MobHealthPlayerDB[index] = nil;
                else
                        MobHealthPlayerDB[index] = pts.."/"..pct;
                end
        end
end

local function MobHealth_Display(currentPct, index)
        local field = getglobal("MobHealthText");
        local text = "";
        
        if ( field ) then
                if ( lTargetData and lTargetData.PPP > 0 ) then
                        local maxhp;
                        if (not MobHealthConfig["unstablemax"] and lTargetData.maxHP) then
                                maxhp = lTargetData.maxHP;
                        else
                                maxhp = (100 * lTargetData.PPP) + 0.5;
                        end
                        if ( currentPct ) then
                                text = string.format("%d / %d", (currentPct * lTargetData.PPP) + 0.5, maxhp);
                        else
                                text = string.format("??? / %d", maxhp);
                        end

                end
                field:SetText(text);
        end
end

local function MobHealth_SetPos(pos)
        MobHealthFrame:SetPoint("TOP", "TargetFrameHealthBar", "BOTTOM", -2, tonumber(pos) );
        DEFAULT_CHAT_FRAME:AddMessage(TITLE.." position set to "..pos);
end

local function MobHealth_VariablesLoaded()
        if (not MobHealthDB ) then
                MobHealthDB = { };
        else
                local index, value;
                
                for index, value in MobHealthDB do
                        -- Convert the old-style data into the newer, more compact form
                        if( type(value) == "table" ) then
                                MobHealth_Set(index, value.damPts, value.damPct);
                        end
                end
        end
        
        if (not MobHealthConfig ) then
                MobHealthConfig = {};
        elseif (MobHealthConfig["position"]) then
                MobHealth_SetPos(MobHealthConfig["position"]);
        end

        if (not MobHealthPlayerDB) then
                MobHealthPlayerDB = {};
        end

end

local function MobHealth_Reset()
        DEFAULT_CHAT_FRAME:AddMessage(TITLE.." reseting database");
        MobHealthDB = {};
        MobHealthConfig = {};
        MobHealthPlayerDB = {}; -- this is not saved variable
end

local function MobHealth_ClearTargetData()
        if (lTargetData) then
                DEFAULT_CHAT_FRAME:AddMessage(TITLE.." reseting data for "..lTargetData.index);
                lTargetData.PPP = 0;
                lTargetData.firstBattle = true;
                lTargetData.totalDamagePoints = 0;
                lTargetData.totalChangeHP = 0;
                lTargetData.maxHP = nil;

                MobHealth_Display(nil, nil);

                if (lTargetData.mob) then
                        MobHealthDB[lTargetData.index] = nil;
                else
                        MobHealthPlayerDB[lTargetData.index] = nil;
                end
        else
                DEFAULT_CHAT_FRAME:AddMessage(TITLE.." no target with hp information in DB found.");
        end

end


function MobHealth_CMD(msg)
        local _, _, cmd, arg1 = string.find(msg, "(%w+)[ ]?([-%w]*)"); 

        if (cmd == "pos") then
                if (arg1 ~= "") then
                        MobHealthConfig["position"] = arg1;
                        MobHealth_SetPos(arg1);
                else
                        DEFAULT_CHAT_FRAME:AddMessage("You need to specify position: /mobhealth2 pos [position]");
                end
        elseif (cmd == "stablemax") then
                MobHealthConfig["unstablemax"] = nil;
                DEFAULT_CHAT_FRAME:AddMessage(TITLE.." using stable max HP display");
        elseif (cmd == "unstablemax") then
                MobHealthConfig["unstablemax"] = true;
                DEFAULT_CHAT_FRAME:AddMessage(TITLE.." using unstable max HP display");
        elseif (cmd == "reset" and arg1 == "all") then
                MobHealth_Reset();
        elseif (cmd == "reset" or cmd == "del" or cmd == "delete" or cmd == "rem" or cmd == "remove" or cmd == "clear") then
                MobHealth_ClearTargetData();
        else
                DEFAULT_CHAT_FRAME:AddMessage(TITLE.." commands:");
                DEFAULT_CHAT_FRAME:AddMessage(COLOR_BLUE.."  /mobhealth2 pos [position]");
                DEFAULT_CHAT_FRAME:AddMessage(COLOR_WHITE.."    set position to [position]");
                DEFAULT_CHAT_FRAME:AddMessage(COLOR_WHITE.."    (relative to target frame, default 22, negatives also work)");
                DEFAULT_CHAT_FRAME:AddMessage(COLOR_BLUE.."  /mobhealth2 stablemax");
                DEFAULT_CHAT_FRAME:AddMessage(COLOR_WHITE.."    updates Max mob HP less often (only in first battle with mob");
                DEFAULT_CHAT_FRAME:AddMessage(COLOR_WHITE.."    and between battles)");
                DEFAULT_CHAT_FRAME:AddMessage(COLOR_BLUE.."  /mobhealth2 unstablemax");
                DEFAULT_CHAT_FRAME:AddMessage(COLOR_WHITE.."    always updates Max mob HP");
                DEFAULT_CHAT_FRAME:AddMessage(COLOR_BLUE.."  /mobhealth2 reset all");
                DEFAULT_CHAT_FRAME:AddMessage(COLOR_WHITE.."    clears whole database!");
                DEFAULT_CHAT_FRAME:AddMessage(COLOR_BLUE.."  /mobhealth2 reset/del/delete/rem/remove/clear");
                DEFAULT_CHAT_FRAME:AddMessage(COLOR_WHITE.."    clear data for current target");
        end
end

function MobHealth_SaveTargetData()
        if (lTargetData) then
                if( lTargetData.PPP > 0 and lTargetData.totalChangeHP < 10000 ) then
                        if (lTargetData.mob) then
                                MobHealth_Set(lTargetData.index, lTargetData.totalDamagePoints, lTargetData.totalChangeHP);
                        else
                                MobHealthPlayer_Set(lTargetData.index, lTargetData.totalDamagePoints, lTargetData.totalChangeHP);
                        end
                end
        end     
end

--------------------------------------------------------------------------------------------------
-- OnFoo functions
--------------------------------------------------------------------------------------------------

function MobHealth_OnLoad()
        for key,value in lEventHandler do
                -- DEFAULT_CHAT_FRAME:AddMessage("Registering "..key);
                this:RegisterEvent(key);
        end

        SlashCmdList["MOBHEALTH2"] = MobHealth_CMD;

        SLASH_MOBHEALTH21 = "/mobhealth2";

end

function MobHealth_OnEvent(event)
        -- DEFAULT_CHAT_FRAME:AddMessage("Event: "..event)
        if (lEventHandler[event]) then
                lEventHandler[event](arg1, arg2, arg3, arg4);
        end
end

--------------------------------------------------------------------------------------------------
-- Event handlers
--------------------------------------------------------------------------------------------------

lEventHandler["VARIABLES_LOADED"] = function ()
        MobHealth_VariablesLoaded();    
end

lEventHandler["UNIT_HEALTH"] = function ()
        if (arg1 == "target") then
                MobHealth_Display(nil, nil);
                if( lTargetData ) then
                        local health = UnitHealth("target");
                        if( health and health ~= 0 ) then
                                local change = lTargetData.currentHealthPercent - health;
                                local damage = lTargetData.tempDamagePoints;
                                if( change > 0 and damage > 0 ) then
                                        lTargetData.totalDamagePoints = lTargetData.totalDamagePoints + damage;
                                        lTargetData.totalChangeHP = lTargetData.totalChangeHP + change;

                                        if( lTargetData.totalChangeHP ~= 0 and lTargetData.totalDamagePoints ~= 0 ) then
                                                lTargetData.PPP = lTargetData.totalDamagePoints / lTargetData.totalChangeHP;
                                        end

                                        if (lTargetData.firstBattle) then
                                                -- this is needed for other addons reading directly from DB
                                                MobHealth_SaveTargetData()
                                        end

                                        lTargetData.tempDamagePoints = 0;

                                elseif ( change ~= 0 ) then -- could be negative so let's be safe
                                        lTargetData.tempDamagePoints = 0;
                                end

                                lTargetData.currentHealthPercent = health;

                                MobHealth_Display(health, lTargetData.index);
                        end
                end
        end
end

lEventHandler["UNIT_COMBAT"] = function ()
        if( lTargetData and arg1 == "target" ) then
                lTargetData.tempDamagePoints = lTargetData.tempDamagePoints + arg4;
        end
end

lEventHandler["PLAYER_TARGET_CHANGED"] = function ()
        if (lTargetData) then
                -- we have old target, so we should update it's HP in database
                MobHealth_SaveTargetData();
        end

        local name = UnitName("target");
        if( name ) then
                if( UnitCanAttack("player", "target") and not UnitIsDead("target") and not UnitIsFriend("player", "target") ) then
                        -- Attackable, alive, non-player target
                        lTargetData = { };
                        lTargetData.name = name;
                        lTargetData.level = UnitLevel("target");
                        lTargetData.currentHealthPercent = UnitHealth("target");
                        lTargetData.tempDamagePoints = 0;

                        if (UnitIsPlayer("target") ) then
                                lTargetData.player = true;
                                lTargetData.index = lTargetData.name;
                                lTargetData.totalDamagePoints = MobHealthPlayer_Pts(lTargetData.index);
                                lTargetData.totalChangeHP = MobHealthPlayer_Pct(lTargetData.index);
                        else
                                lTargetData.mob = true;
                                lTargetData.index = lTargetData.name..":"..lTargetData.level;
                                lTargetData.totalDamagePoints = MobHealth_Pts(lTargetData.index);
                                lTargetData.totalChangeHP = MobHealth_Pct(lTargetData.index);
                        end

                        
                        if( lTargetData.totalChangeHP ~= 0 and lTargetData.totalDamagePoints ~= 0 ) then
                                lTargetData.PPP = lTargetData.totalDamagePoints / lTargetData.totalChangeHP;
                        else
                                lTargetData.PPP = 0;
                        end

                        if (lTargetData.totalChangeHP == 0) then
                                -- first battle with mob/player
                                lTargetData.firstBattle = true;
                        else
                                lTargetData.maxHP = math.floor(lTargetData.PPP * 100 + 0.5);
                        end

                        MobHealth_Display(lTargetData.currentHealthPercent, lTargetData.index);
                        return;
                end
        end

        -- Unusable target
        lTargetData = nil;

        MobHealth_Display(nil, nil);
end