--[[ 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