/branches
## Interface: 20400 |
## LoadOnDemand: 1 |
## Title: Lib: MobHealth-4.0 |
## Notes: Estimates a mob's health |
## Author: ckknight |
## X-Credits: neronix |
## X-eMail: ckknight@gmail.com |
## Version: 1.0 |
## X-Category: Library |
## SavedVariables: LibMobHealth40DB, LibMobHealth40Opt |
## X-License: LGPL v2.1 |
LibStub\LibStub.lua |
lib.xml |
-- LibStub is a simple versioning stub meant for use in Libraries. http://www.wowace.com/wiki/LibStub for more info |
-- LibStub is hereby placed in the Public Domain Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke |
local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2 -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS! |
local LibStub = _G[LIBSTUB_MAJOR] |
if not LibStub or LibStub.minor < LIBSTUB_MINOR then |
LibStub = LibStub or {libs = {}, minors = {} } |
_G[LIBSTUB_MAJOR] = LibStub |
LibStub.minor = LIBSTUB_MINOR |
function LibStub:NewLibrary(major, minor) |
assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)") |
minor = assert(tonumber(strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.") |
local oldminor = self.minors[major] |
if oldminor and oldminor >= minor then return nil end |
self.minors[major], self.libs[major] = minor, self.libs[major] or {} |
return self.libs[major], oldminor |
end |
function LibStub:GetLibrary(major, silent) |
if not self.libs[major] and not silent then |
error(("Cannot find a library instance of %q."):format(tostring(major)), 2) |
end |
return self.libs[major], self.minors[major] |
end |
function LibStub:IterateLibraries() return pairs(self.libs) end |
setmetatable(LibStub, { __call = LibStub.GetLibrary }) |
end |
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ |
..\FrameXML\UI.xsd"> |
<Script file="LibMobHealth-4.0.lua" /> |
</Ui> |
--[[ |
Name: LibMobHealth-4.0 |
Revision: $Rev: 68090 $ |
Author: Cameron Kenneth Knight (ckknight@gmail.com) |
Inspired By: MobHealth3 by Neronix |
Website: http://www.wowace.com/ |
Description: Estimate a mob's health |
License: LGPL v2.1 |
]] |
local MAJOR_VERSION = "LibMobHealth-4.0" |
local MINOR_VERSION = tonumber(("$Revision: 68090 $"):match("%d+")) or 0 |
-- #AUTODOC_NAMESPACE lib |
local lib, oldMinor = LibStub:NewLibrary(MAJOR_VERSION, MINOR_VERSION) |
if not lib then |
return |
end |
local oldLib |
if oldMinor then |
oldLib = {} |
for k,v in pairs(lib) do |
oldLib[k] = v |
lib[k] = nil |
end |
end |
local _G = _G |
local UnitLevel = _G.UnitLevel |
local UnitIsPlayer = _G.UnitIsPlayer |
local UnitPlayerControlled = _G.UnitPlayerControlled |
local UnitName = _G.UnitName |
local UnitHealth = _G.UnitHealth |
local UnitHealthMax = _G.UnitHealthMax |
local UnitIsFriend = _G.UnitIsFriend |
local UnitIsDead = _G.UnitIsDead |
local UnitCanAttack = _G.UnitCanAttack |
local math_floor = _G.math.floor |
local setmetatable = _G.setmetatable |
local type = _G.type |
local pairs = _G.pairs |
local next = _G.next |
local frame |
if oldLib then |
frame = oldLib.frame |
frame:UnregisterAllEvents() |
frame:SetScript("OnEvent", nil) |
frame:SetScript("OnUpdate", nil) |
_G.LibMobHealth40DB = nil |
else |
frame = _G.CreateFrame("Frame", MAJOR_VERSION .. "_Frame") |
end |
frame:RegisterEvent("UNIT_COMBAT") |
frame:RegisterEvent("PLAYER_TARGET_CHANGED") |
frame:RegisterEvent("PLAYER_FOCUS_CHANGED") |
frame:RegisterEvent("UNIT_HEALTH") |
frame:RegisterEvent("ADDON_LOADED") |
frame:RegisterEvent("PLAYER_LOGIN") |
frame:SetScript("OnEvent", function(this, event, ...) |
this[event](lib, ...) |
end) |
local mt = {__index = function(self, key) |
if key == nil then |
return nil |
end |
local t = {} |
self[key] = t |
return t |
end} |
local data = oldLib and oldLib.data |
if data then |
setmetatable(data, nil) |
if not data.pc then |
local npc, pc, pet, legacy = { {}, {}, {} }, {}, {}, {} |
for k, v in pairs(data) do |
legacy[k] = v |
data[k] = nil |
end |
data.npc = npc |
setmetatable(npc[1], mt) |
setmetatable(npc[2], mt) |
setmetatable(npc[3], mt) |
data.pc = setmetatable(pc, mt) |
data.pet = setmetatable(pet, mt) |
data.legacy = setmetatable(legacy, mt) |
elseif not rawget(data.npc, 1) or not rawget(data.npc, 2) or not rawget(data.npc, 3) then |
data.npc = { setmetatable({}), setmetatable({}), setmetatable({}) } |
end |
else |
data = { |
npc = { setmetatable({}, mt), setmetatable({}, mt), setmetatable({}, mt), }, |
pc = setmetatable({}, mt), |
pet = setmetatable({}, mt), |
legacy = setmetatable({}, mt) |
} |
end |
lib.data = data -- stores the maximum health of mobs that will actually be shown to the user |
data.revision = MINOR_VERSION |
local accumulatedHP = {setmetatable({}, mt), setmetatable({}, mt), setmetatable({}, mt)} -- Keeps Damage-taken data for mobs that we've actually poked during this session |
local accumulatedPercent = {setmetatable({}, mt), setmetatable({}, mt), setmetatable({}, mt)} -- Keeps Percentage-taken data for mobs that we've actually poked during this session |
local calculationUnneeded = {setmetatable({}, mt), setmetatable({}, mt), setmetatable({}, mt)} -- Keeps a list of things that don't need calculation (e.g. Beast Lore'd mobs) |
local currentAccumulatedHP = { target = nil, focus = nil } |
local currentAccumulatedPercent = { target = nil, focus = nil } |
local currentName = { target = nil, focus = nil } |
local currentLevel = { target = nil, focus = nil } |
local recentDamage = { target = nil, focus = nil } |
local lastPercent = { target = nil, focus = nil } |
_G.hash_SlashCmdList["LIBMOBHEALTHFOUR"] = nil |
_G.SlashCmdList["LIBMOBHEALTHFOUR"] = nil |
function frame:ADDON_LOADED(name) |
if name == MAJOR_VERSION then |
-- if we're not an embedded library, then use a saved variable |
frame:RegisterEvent("PLAYER_LOGOUT") |
if type(_G.LibMobHealth40DB) == "table" then |
data = _G.LibMobHealth40DB |
if not data.pc then |
local npc, pc, pet, legacy = { {}, {}, {} }, {}, {}, {} |
for k, v in pairs(data) do |
legacy[k] = v |
data[k] = nil |
end |
data.npc = npc |
data.pc = pc |
data.pet = pet |
data.legacy = legacy |
elseif not rawget(data.npc, 1) or not rawget(data.npc, 2) or not rawget(data.npc, 3) then |
if not data.legacy then |
data.legacy = {} |
end |
for k, v in pairs(data.npc) do |
data.legacy[k] = v |
data.npc[k] = nil |
end |
data.npc = { {}, {}, {} } |
end |
setmetatable(data.npc[1], mt) |
setmetatable(data.npc[2], mt) |
setmetatable(data.npc[3], mt) |
setmetatable(data.pc, mt) |
setmetatable(data.pet, mt) |
if not data.legacy then |
data.legacy = {} |
end |
setmetatable(data.legacy, mt) |
lib.data = data |
else |
_G.LibMobHealth40DB = data |
end |
local options = _G.LibMobHealth40Opt |
if type(options) ~= "table" then |
options = { |
save = true, |
prune = 1000, |
} |
_G.LibMobHealth40Opt = options |
end |
if type(options.save) ~= "boolean" then |
options.save = true |
end |
if type(options.prune) ~= "number" then |
options.prune = 1000 |
end |
_G.hash_SlashCmdList["LIBMOBHEALTHFOUR"] = nil |
_G.SlashCmdList["LIBMOBHEALTHFOUR"] = function(text) |
text = text:lower():trim() |
local alpha, bravo = text:match("^([^%s]+)%s+(.*)$") |
if not alpha then |
alpha = text |
end |
if alpha == "" or alpha == "help" then |
DEFAULT_CHAT_FRAME:AddMessage(("|cffffff7f%s|r"):format(MAJOR_VERSION)) |
DEFAULT_CHAT_FRAME:AddMessage((" - |cffffff7f%s|r [%s] - %s"):format("save", options.save and "|cff00ff00On|r" or "|cffff0000Off|r", "whether to save mob health data")) |
DEFAULT_CHAT_FRAME:AddMessage((" - |cffffff7f%s|r [%s] - %s"):format("prune", options.prune == 0 and "|cffff0000Off|r" or "|cff00ff00" .. options.prune .. "|r", "how many data points until data is pruned, 0 means no pruning")) |
elseif alpha == "save" then |
options.save = not options.save |
DEFAULT_CHAT_FRAME:AddMessage(("|cffffff7f%s|r"):format(MAJOR_VERSION)) |
DEFAULT_CHAT_FRAME:AddMessage((" - |cffffff7f%s|r [%s]"):format("save", options.save and "|cff00ff00On|r" or "|cffff0000Off|r")) |
elseif alpha == "prune" then |
local bravo_num = tonumber(bravo) |
if bravo_num then |
options.prune = math.floor(bravo_num+0.5) |
DEFAULT_CHAT_FRAME:AddMessage(("|cffffff7f%s|r"):format(MAJOR_VERSION)) |
DEFAULT_CHAT_FRAME:AddMessage((" - |cffffff7f%s|r [%s]"):format("prune", options.prune == 0 and "|cffff0000Off|r" or "|cff00ff00" .. options.prune .. "|r")) |
else |
DEFAULT_CHAT_FRAME:AddMessage(("|cffffff7f%s|r - prune must take a number, %q is not a number"):format(MAJOR_VERSION, bravo or "")) |
end |
else |
DEFAULT_CHAT_FRAME:AddMessage(("|cffffff7f%s|r - unknown command %q"):format(MAJOR_VERSION, alpha)) |
end |
end |
_G.SLASH_LIBMOBHEALTHFOUR1 = "/lmh4" |
_G.SLASH_LIBMOBHEALTHFOUR2 = "/lmh" |
_G.SLASH_LIBMOBHEALTHFOUR3 = "/libmobhealth4" |
_G.SLASH_LIBMOBHEALTHFOUR4 = "/libmobhealth" |
function frame:PLAYER_LOGOUT() |
if not options.save then |
_G.LibMobHealth40DB = nil |
return |
end |
local count = 0 |
setmetatable(data.npc, nil) |
setmetatable(data.npc[1], nil) |
setmetatable(data.npc[2], nil) |
setmetatable(data.npc[3], nil) |
setmetatable(data.pc, nil) |
setmetatable(data.pet, nil) |
setmetatable(data.legacy, nil) |
for difficulty = 1, 3 do |
for k, v in pairs(data.npc[difficulty]) do |
if not next(v) then |
data.npc[difficulty][k] = nil |
else |
for _ in pairs(v) do |
count = count + 1 |
end |
end |
end |
end |
for _, kind in ipairs({ 'pc', 'pet', 'legacy' }) do |
for k,v in pairs(data[kind]) do |
if not next(v) then |
data[kind][k] = nil |
else |
for _ in pairs(v) do |
count = count + 1 |
end |
end |
end |
end |
if not next(data.legacy) then |
data.legacy = nil |
end |
local prune = options.prune |
if not prune or prune <= 0 then |
return |
end |
if count <= prune then |
return |
end |
if data.legacy then |
-- prune all legacy data |
for level, d in pairs(data.legacy) do |
for mob in pairs(d) do |
d[mob] = nil |
count = count - 1 |
end |
data.legacy[level] = nil |
end |
if count <= prune then |
return |
end |
end |
-- let's try to only have one mob-level, don't have duplicates for each level, since they can be estimated, and for players/pets, this will get rid of old data |
for difficulty = 1, 3 do |
local mobs = {} |
for level, d in pairs(data.npc[difficulty]) do |
for mob, health in pairs(d) do |
if mobs[mob] then |
d[mob] = nil |
count = count - 1 |
end |
mobs[mob] = level |
end |
if next(d) == nil then |
data.npc[difficulty][level] = nil |
end |
end |
end |
for _, kind in ipairs({ 'pc', 'pet' }) do |
local mobs = {} |
for level, d in pairs(data[kind]) do |
for mob, health in pairs(d) do |
if mobs[mob] then |
d[mob] = nil |
count = count - 1 |
end |
mobs[mob] = level |
end |
if next(d) == nil then |
data[kind][level] = nil |
end |
end |
end |
if count <= prune then |
return |
end |
-- still too much data, let's get rid of low-level non-bosses until we're at `prune` |
local playerLevel = UnitLevel("player") |
local maxLevel = playerLevel*3/4 |
if maxLevel > playerLevel - 5 then |
maxLevel = playerLevel - 5 |
end |
for level = 1, maxLevel do |
for difficulty = 1, 3 do |
local d = data.npc[difficulty][level] |
if d then |
for mob, health in pairs(d) do |
d[mob] = nil |
count = count - 1 |
end |
data.npc[difficulty][level] = nil |
if count <= prune then |
return |
end |
end |
end |
for _, kind in ipairs({ 'pet', 'pc' }) do |
local d = data[kind][level] |
if d then |
for mob, health in pairs(d) do |
d[mob] = nil |
count = count - 1 |
end |
data[kind][level] = nil |
if count <= prune then |
return |
end |
end |
end |
end |
end |
end |
frame:UnregisterEvent("ADDON_LOADED") |
frame.ADDON_LOADED = nil |
if IsLoggedIn() then |
frame.PLAYER_LOGIN(self) |
end |
end |
function frame:PLAYER_LOGIN() |
if type(_G.MobHealth3DB) == "table" then |
for index, value in pairs(_G.MobHealth3DB) do |
if type(index) == "string" and type(value) == "number" then |
local name, level = index:match("^(.+):(%-?%d+)$") |
if name then |
level = level+0 |
if not data.legacy[level][name] then |
data.legacy[level][name] = value |
end |
end |
end |
end |
end |
frame:UnregisterEvent("PLAYER_LOGIN") |
frame.PLAYER_LOGIN = nil |
end |
function frame:UNIT_COMBAT(unit, _, _, damage) |
if (unit ~= "target" and unit ~= "focus") or not currentAccumulatedHP[unit] then |
return |
end |
recentDamage[unit] = recentDamage[unit] + damage |
end |
local function PLAYER_unit_CHANGED(unit) |
if not UnitCanAttack("player", unit) or UnitIsDead(unit) or UnitIsFriend("player", unit) then |
-- don't store data on friends and dead men tell no tales |
currentAccumulatedHP[unit] = nil |
currentAccumulatedPercent[unit] = nil |
return |
end |
local name, server = UnitName(unit) |
if server and server ~= "" then |
name = name .. "-" .. server |
end |
local isPlayer = UnitIsPlayer(unit) |
local isPet = UnitPlayerControlled(unit) and not isPlayer -- some owners name their pets the same name as other people, because they're think they're funny. They're not. |
currentName[unit] = name |
local level = UnitLevel(unit) |
currentLevel[unit] = level |
recentDamage[unit] = 0 |
lastPercent[unit] = UnitHealth(unit) |
local difficulty = 1 |
if not isPlayer and not isPet then |
difficulty = GetInstanceDifficulty() |
end |
currentAccumulatedHP[unit] = accumulatedHP[difficulty][level][name] |
currentAccumulatedPercent[unit] = accumulatedPercent[difficulty][level][name] |
if not isPlayer and not isPet then |
-- Mob |
if not currentAccumulatedHP[unit] then |
local saved = data.npc[difficulty][level][name] |
if saved then |
-- We claim that the saved value is worth 100% |
accumulatedHP[difficulty][level][name] = saved |
accumulatedPercent[difficulty][level][name] = 100 |
else |
-- Nothing previously known. Start fresh. |
accumulatedHP[difficulty][level][name] = 0 |
accumulatedPercent[difficulty][level][name] = 0 |
end |
currentAccumulatedHP[unit] = accumulatedHP[difficulty][level][name] |
currentAccumulatedPercent[unit] = accumulatedPercent[difficulty][level][name] |
end |
if currentAccumulatedPercent[unit] > 200 then |
-- keep accumulated percentage below 200% in case we hit mobs with different hp |
currentAccumulatedHP[unit] = currentAccumulatedHP[unit] / currentAccumulatedPercent[unit] * 100 |
currentAccumulatedPercent[unit] = 100 |
end |
else |
-- Player health can change a lot. Different gear, buffs, etc.. we only assume that we've seen 10% knocked off players previously |
if not currentAccumulatedHP[unit] then |
local saved = data[isPet and 'pet' or 'pc'][level][name] |
if saved then |
-- We claim that the saved value is worth 10% |
accumulatedHP[difficulty][level][name] = saved/10 |
accumulatedPercent[difficulty][level][name] = 10 |
else |
accumulatedHP[difficulty][level][name] = 0 |
accumulatedPercent[difficulty][level][name] = 0 |
end |
currentAccumulatedHP[unit] = accumulatedHP[difficulty][level][name] |
currentAccumulatedPercent[unit] = accumulatedPercent[difficulty][level][name] |
end |
if currentAccumulatedPercent[unit] > 10 then |
currentAccumulatedHP[unit] = currentAccumulatedHP[unit] / currentAccumulatedPercent[unit] * 10 |
currentAccumulatedPercent[unit] = 10 |
end |
end |
end |
function frame:PLAYER_TARGET_CHANGED() |
PLAYER_unit_CHANGED("target") |
end |
function frame:PLAYER_FOCUS_CHANGED() |
PLAYER_unit_CHANGED("focus") |
end |
function frame:UNIT_HEALTH(unit) |
if (unit ~= "target" and unit ~= "focus") or not currentAccumulatedHP[unit] then |
return |
end |
local current = UnitHealth(unit) |
if unit == "focus" and UnitIsUnit("target", "focus") then |
-- don't want to double-accumulate |
recentDamage[unit] = 0 |
lastPercent[unit] = current |
return |
end |
local max = UnitHealthMax(unit) |
local name = currentName[unit] |
local level = currentLevel[unit] |
local difficulty = 1 |
local kind |
if UnitIsPlayer(unit) then |
kind = 'pc' |
elseif UnitPlayerControlled(unit) then |
kind = 'pet' |
else |
kind = 'npc' |
difficulty = GetInstanceDifficulty() |
end |
if calculationUnneeded[difficulty][level][name] then |
return |
elseif current == 0 then |
-- possibly targetting/focusing a dead person |
elseif max ~= 100 then |
-- beast lore, don't need to calculate. |
if kind == 'npc' then |
data.npc[difficulty][level][name] = max |
else |
data[kind][level][name] = max |
end |
calculationUnneeded[difficulty][level][name] = true |
elseif current > lastPercent[unit] or lastPercent[unit] > 100 then |
-- it healed, so let's reset our ephemeral calculations |
lastPercent[unit] = current |
recentDamage[unit] = 0 |
elseif recentDamage[unit] > 0 then |
if current ~= lastPercent[unit] then |
currentAccumulatedHP[unit] = currentAccumulatedHP[unit] + recentDamage[unit] |
currentAccumulatedPercent[unit] = currentAccumulatedPercent[unit] + (lastPercent[unit] - current) |
recentDamage[unit] = 0 |
lastPercent[unit] = current |
if currentAccumulatedPercent[unit] >= 10 then |
local num = currentAccumulatedHP[unit] / currentAccumulatedPercent[unit] * 100 |
if kind == 'npc' then |
data.npc[difficulty][level][name] = num |
else |
data[kind][level][name] = num |
end |
end |
end |
end |
end |
local function guessAtMaxHealth(name, level, kind, difficulty, known) |
-- if we have data on a mob of the same name but a different level, check within two levels and guess from there. |
if not kind then |
return guessAtMaxHealth(name, level, 'npc', GetInstanceDifficulty()) or guessAtMaxHealth(name, level, 'pc') or guessAtMaxHealth(name, level, 'pet') or guessAtMaxHealth(name, level, 'legacy') |
elseif not difficulty then |
difficulty = 1 |
end |
if kind == 'npc' then |
local value = data.npc[difficulty][level][name] |
if value or level <= 0 or known then |
return value |
end |
if level > 1 then |
value = data.npc[difficulty][level - 1][name] |
if value then |
return value * level/(level - 1) |
end |
end |
value = data.npc[difficulty][level + 1][name] |
if value then |
return value * level/(level + 1) |
end |
if level > 2 then |
value = data.npc[difficulty][level - 2][name] |
if value then |
return value * level/(level - 2) |
end |
end |
value = data.npc[difficulty][level + 2][name] |
if value then |
return value * level/(level + 2) |
end |
else |
local value = data[kind][level][name] |
if value or level <= 0 or known then |
return value |
end |
if level > 1 then |
value = data[kind][level - 1][name] |
if value then |
return value * level/(level - 1) |
end |
end |
value = data[kind][level + 1][name] |
if value then |
return value * level/(level + 1) |
end |
if level > 2 then |
value = data[kind][level - 2][name] |
if value then |
return value * level/(level - 2) |
end |
end |
value = data[kind][level + 2][name] |
if value then |
return value * level/(level + 2) |
end |
end |
return nil |
end |
--[[ |
Arguments: |
string - name of the unit in question in the form of "Someguy", "Someguy-Some Realm" |
number - level of the unit in question |
string - kind of unit, can be "npc", "pc", "pet" |
[optional] number - difficulty of the unit, only applies to "npc". see http://wowwiki.com/API_GetInstanceDifficulty for details. Can be 1, 2, or 3. 1 by default. |
[optional] boolean - whether not to guess at the mob's health based on other levels of said mob. |
Returns: |
number or nil - the maximum health of the unit or nil if unknown |
Example: |
local hp = LibStub("LibMobHealth-4.0"):GetMaxHP("Young Wolf", 2) |
]] |
function lib:GetMaxHP(name, level, kind, difficulty, known) |
local value = guessAtMaxHealth(name, level, kind, difficulty, known) |
if value then |
return math_floor(value + 0.5) |
else |
return nil |
end |
end |
--[[ |
Arguments: |
string - a unit ID |
Returns: |
number, boolean - the maximum health of the unit, whether the health is known or not |
Example: |
local maxhp, found = LibStub("LibMobHealth-4.0"):GetUnitMaxHP("target") |
]] |
function lib:GetUnitMaxHP(unit) |
local max = UnitHealthMax(unit) |
if max ~= 100 then |
return max, true |
end |
local name, server = UnitName(unit) |
if server and server ~= "" then |
name = name .. "-" .. server |
end |
local level = UnitLevel(unit) |
local kind |
local difficulty = 1 |
if UnitIsPlayer(unit) then |
kind = 'pc' |
elseif UnitPlayerControlled(unit) then |
kind = 'pet' |
else |
kind = 'npc' |
difficulty = GetInstanceDifficulty() |
end |
local value = guessAtMaxHealth(name, level, kind, difficulty) |
if value then |
return math_floor(value + 0.5), true |
else |
return max, false |
end |
end |
--[[ |
Arguments: |
string - a unit ID |
Returns: |
number, boolean - the current health of the unit, whether the health is known or not |
Example: |
local curhp, found = LibStub("LibMobHealth-4.0"):GetUnitCurrentHP("target") |
]] |
function lib:GetUnitCurrentHP(unit) |
local current, max = UnitHealth(unit), UnitHealthMax(unit) |
if max ~= 100 then |
return current, true |
end |
local name, server = UnitName(unit) |
if server and server ~= "" then |
name = name .. "-" .. server |
end |
local level = UnitLevel(unit) |
local kind |
local difficulty = 1 |
if UnitIsPlayer(unit) then |
kind = 'pc' |
elseif UnitPlayerControlled(unit) then |
kind = 'pet' |
else |
kind = 'npc' |
difficulty = GetInstanceDifficulty() |
end |
local value = guessAtMaxHealth(name, level, kind, difficulty) |
if value then |
return math_floor(current/max * value + 0.5), true |
else |
return current, false |
end |
end |
--[[ |
Arguments: |
string - a unit ID |
Returns: |
number, number, boolean - the current health of the unit, the maximum health of the unit, whether the health is known or not |
Example: |
local curhp, maxhp, found = LibStub("LibMobHealth-4.0"):GetUnitHealth("target") |
]] |
function lib:GetUnitHealth(unit) |
local current, max = UnitHealth(unit), UnitHealthMax(unit) |
if max ~= 100 then |
return current, max, true |
end |
local name, server = UnitName(unit) |
if server and server ~= "" then |
name = name .. "-" .. server |
end |
local level = UnitLevel(unit) |
local kind |
local difficulty = 1 |
if UnitIsPlayer(unit) then |
kind = 'pc' |
elseif UnitPlayerControlled(unit) then |
kind = 'pet' |
else |
kind = 'npc' |
difficulty = GetInstanceDifficulty() |
end |
local value = guessAtMaxHealth(name, level, kind, difficulty) |
if value then |
return math_floor(current/max * value + 0.5), math_floor(value + 0.5), true |
else |
return current, max, false |
end |
end |
## Interface: 20400 |
## Author: Pazrael of Silvermoon |
## Title: oUF Pazrael |
## Notes: Custom layout based on Lily |
## RequiredDeps: oUF |
## OptionalDeps: oUF_Banzai, oUF_DruidMana, oUF_CombatFeedback, oUF_DebuffHighlight, oUF_ReadyCheck, oUF_Voice, LibMobHealth-4.0 |
## X-Category: UnitFrame |
libs\LibMobHealth-4.0\LibStub\LibStub.lua |
libs\LibMobHealth-4.0\LibMobHealth-4.0.lua |
oUF_Pazrael.lua |
----------------------------------------------------------------------------------------------- |
-- oUF_Pazrael an oUF layout based on the appearence of p3lim with some major overhauls |
-- Based on oUF by Haste. |
----------------------------------------------------------------------------------------------- |
-- Functions for changing elements -- |
local castBar = false -- enable castbar support |
local partyRaid = false -- enable party-style raid |
-- Stylistic Elements -- |
-- Start of optimization |
local LibMobHealth = LibStub("LibMobHealth-4.0") |
local pazcolors = { |
[0] = { r = .35, g = .35, b = .45, a = 1}, -- Status Bar |
[1] = { r = .25, g = .25, b = .25, a = .25}, -- Status Bar BG |
[2] = { r = 0, g = 0, b = 0, a = 1}, -- Frame BGa |
[3] = { r = .5, g = .5, b = .5, a = .3}, -- Highlight |
[4] = { r = .33, g = .59, b = .33, a = 1} -- CastBar Safe |
} |
-- Function declarations -- |
local classification = { --Level Formatting Array |
["worldboss"] = "%s Boss", |
["rareelite"] = "%s+ Rare", |
["elite"] = " %s+", |
["rare"] = " %s Rare", |
["normal"] = "%s", |
["trivial"] = "%s", |
} |
local function updateColor(self, element, unit, func) -- unified frame coloring |
local color |
local _, class = UnitClass(unit) |
if(UnitIsTapped(unit) and not UnitIsTappedByPlayer(unit) or not UnitIsConnected(unit)) then |
color = self.colors.tapped |
elseif(UnitIsPlayer(unit)) then |
color = self.colors.class[class] |
else |
if(UnitIsFriend(unit, "player") or UnitLevel(unit) < 0) then |
color = self.colors.reaction[UnitReaction(unit, 'player')] |
else |
color = GetDifficultyColor(UnitLevel(unit)) |
element[func](element, color.r, color.g, color.b) |
return self |
end |
end |
if(color) then |
element[func](element, color[1], color[2], color[3]) |
end |
end |
local menu = function(self) -- Drop down menu for frames |
if(self.unit:sub(1, -2) == "party" or self.unit:sub(1, -2) == "partypet") then |
ToggleDropDownMenu(1, nil, _G["PartyMemberFrame"..self.id.."DropDown"], "cursor", 0, 0) |
elseif(_G[self.unit:gsub("(.)", string.upper, 1).."FrameDropDown"]) then |
ToggleDropDownMenu(1, nil, _G[self.unit:gsub("(.)", string.upper, 1).."FrameDropDown"], "cursor", 0, 0) |
end |
end |
local setFontString = function(parent, fontStyle, fontHeight) -- default font settings |
local fs = parent:CreateFontString(nil, "OVERLAY") |
fs:SetFontObject(fontStyle) |
fs:SetShadowColor(0,0,0) |
fs:SetShadowOffset(0.8, -0.8) |
fs:SetTextColor(1,1,1) |
fs:SetJustifyH("LEFT") |
return fs |
end |
local function OverrideUpdateName(self, event, unit) --Name Update Function |
if(self.unit == unit) then |
local name = UnitName(unit) |
local lvl = UnitLevel(unit) |
if lvl < 0 then lvl = "??" end |
if string.len(name) > 15 then name = name:sub(1,15).."..." end |
if(unit == 'player' or unit == 'pet') then |
self.Name:Hide() |
elseif unit == "target" then |
updateColor(self, self.Name, unit, 'SetTextColor') |
self.Name:SetText('|cffFFFFFF' .. name .. '|r' .. ' ' .. format(classification[UnitClassification(unit)], lvl)) |
else |
self.Name:Show() |
if(self:GetParent():GetName():match"oUF_Raid") then |
if string.len(name) > 4 then name = name:sub(1,4) end |
if (UnitIsDead(unit) or UnitIsGhost(unit)) then |
self.Name:Hide() |
end |
end |
self.Name:SetText(name) |
end |
end |
end |
local number = function(n) |
if n <= 9999 then return n end |
if n >= 1000000 then |
return string.format("%.1fm", n/1000000) |
elseif n >= 10000 then |
return string.format("%.1fk", n/1000) |
end |
end |
local function PostUpdateHealth(self, event, unit, bar, min, max) |
local curhp, maxhp = LibMobHealth:GetUnitHealth(unit) |
local d = floor(curhp/maxhp*100) |
if(UnitIsDead(unit)) then |
bar:SetValue(0) |
bar.value:SetText("Dead") |
elseif(UnitIsGhost(unit)) then |
bar:SetValue(0) |
bar.value:SetText("Ghost") |
elseif(not UnitIsConnected(unit)) then |
bar.value:SetText("Offline") |
else |
if(unit=="player") then |
if(min~=max) then |
bar.value:SetFormattedText("|cffff8080%s|r |cff0090ff/|r %d|cff0090ff%%|r", number(min-max), floor(min/max*100)) |
else |
bar.value:SetText(number(max)) |
end |
elseif(unit=="pet" or unit=="focus" or unit=="focustarget" or unit=="targettarget") then |
if(max==100) then |
if(min~=max) then |
bar.value:SetText(d.."%") |
else |
bar.value:SetText() |
end |
elseif(min~=max) then |
bar.value:SetText(d.."%") |
else |
bar.value:SetFormattedText("|cffAF5050%s|r", number(max)) |
end |
elseif(self:GetParent():GetName()=="oUF_Party") then |
if(min~=max) then |
bar.value:SetFormattedText("|cffAF5050%s|r", number(min-max), floor(min/max*100)) |
else |
bar.value:SetText() |
end |
elseif(self:GetParent():GetName():sub(1,8)=="oUF_Raid") then |
if(min~=max) then |
bar.value:SetFormattedText("|cffAF5050%s|r", floor(min/max*100)) |
else |
bar.value:SetText() |
end |
else |
if(max==100) then |
if(unit=="target" and not UnitIsPlayer("target")) then |
bar.value:SetFormattedText("%s (%d|cff0090ff%%|r)", number(curhp), number(floor(curhp/maxhp*100))) |
else |
bar.value:SetFormattedText("%s|cff0090ff%%", number(min)) |
end |
else |
bar.value:SetFormattedText("%s |cff0090ff/|r %s", number(min), number(max)) |
end |
end |
end |
if((UnitIsTapped(unit) and not(UnitIsTappedByPlayer(unit))) or not(UnitIsConnected(unit))) then |
bar:SetStatusBarColor(0.6, 0.6, 0.6) |
elseif(self:GetParent():GetName():match"oUF_Raid") then |
updateColor(self, self.Health, unit, 'SetStatusBarColor') |
else |
bar:SetStatusBarColor(pazcolors[0].r, pazcolors[0].g, pazcolors[0].b, pazcolors[0].a) |
end |
self.UNIT_NAME_UPDATE(self, event, unit) |
end |
local function PostUpdatePower(self, event, unit, bar, min, max) |
if(self:GetParent():GetName():match"oUF_Raid") then |
self.Power.colorPower = true |
end |
if(not bar.value) then return end |
if(not UnitIsPlayer(unit)) then |
bar.value:SetText() |
else |
if(min==0) then |
bar.value:SetText() |
elseif(not UnitIsConnected(unit)) then |
bar.value:SetText() |
elseif(unit=="player") then |
color = self.colors.power[UnitPowerType(unit)] |
if(color) then bar.value:SetTextColor(color[1], color[2], color[3]) end |
if(min~=max) then |
bar.value:SetText(number(max-(max-min))) |
else |
bar.value:SetText(number(max)) |
end |
else |
if(min~=max) then |
bar.value:SetFormattedText("%s|cff0090ff - ", number(max-(max-min))) |
else |
bar.value:SetFormattedText("%s|cff0090ff - ", number(max)) |
end |
end |
end |
self.UNIT_NAME_UPDATE(self, event, unit) |
end |
local function PostCreateAuraIcon(self, button, icons, index, debuff) |
icons.showDebuffType = true |
button.cd:SetReverse() |
button.icon:SetTexCoord(0.07, 0.93, 0.07, 0.93) |
button.overlay:SetTexture('Interface\\AddOns\\oUF_Pazrael\\textures\\border') |
button.overlay:SetTexCoord(0.0, 1.0, 0.0, 1.0) |
button.overlay.Hide = function(self) self:SetVertexColor(pazcolors[0].r, pazcolors[0].g, pazcolors[0].b, pazcolors[0].a) end |
end |
local function styleFunc(self, unit) |
local _, class = UnitClass('player') |
self.menu = menu -- enable menus |
self:SetScript("OnEnter", UnitFrame_OnEnter) |
self:SetScript("OnLeave", UnitFrame_OnLeave) |
self:RegisterForClicks("anyup") -- enable mouse click intercept |
self:SetAttribute("*type2", "menu") |
self:SetBackdrop({bgFile="Interface\\Tooltips\\UI-Tooltip-Background", insets ={left = -1, right = -1, top = -1, bottom = -1}}) -- backdrop for frame using settings |
self:SetBackdropColor(pazcolors[2].r, pazcolors[2].g, pazcolors[2].b, pazcolors[2].a) -- backdrop color |
self.Health = CreateFrame("StatusBar", nil, self) -- Healthbar |
self.Health:SetHeight(22) |
self.Health:SetStatusBarTexture("Interface\\AddOns\\oUF_Pazrael\\textures\\Minimalist") |
if not(unit) then self.Health:SetFrameLevel(2) else self.Health:SetFrameLevel(1) end |
self.Health:SetPoint("TOPLEFT") |
self.Health:SetPoint("TOPRIGHT") |
self.Health.bg = self.Health:CreateTexture(nil, "BORDER") -- Healthbar Background |
self.Health.bg:SetAllPoints(self.Health) |
self.Health.bg:SetTexture("Interface\\AddOns\\oUF_Pazrael\\textures\\Minimalist") |
self.Health.bg:SetVertexColor(pazcolors[1].r, pazcolors[1].g, pazcolors[1].b, pazcolors[1].a) |
self.Health.value = setFontString(self.Health, GameFontNormalSmall, 10) -- Healthbar Text |
self.Health.value:SetPoint("RIGHT", -2, 0) |
self.Highlight = self:CreateTexture(nil, "HIGHLIGHT") --Mouse-over Highlighting |
self.Highlight:SetTexture(pazcolors[3].r, pazcolors[3].g, pazcolors[3].b, pazcolors[3].a) |
self.Highlight:SetBlendMode("ADD") |
self.Highlight:SetAllPoints(self.Health) |
self.Power = CreateFrame("StatusBar", nil, self) -- Powerbar |
self.Power:SetHeight(unit and 5 or 2) |
self.Power:SetStatusBarTexture("Interface\\AddOns\\oUF_Pazrael\\textures\\Minimalist") |
self.Power:SetPoint("LEFT") |
self.Power:SetPoint("RIGHT") |
self.Power:SetPoint("TOP", self.Health, "BOTTOM", 0, -1) |
self.Power.colorTapping = true |
self.Power.colorDisconnected = true |
self.Power.colorClass = true |
self.Power.colorReaction = true |
self.Power.bg = self.Power:CreateTexture(nil, "BORDER") -- Powerbar Background |
self.Power.bg:SetAllPoints(self.Power) |
self.Power.bg:SetTexture("Interface\\AddOns\\oUF_Pazrael\\textures\\Minimalist") |
self.Power.bg:SetAlpha(0.3) |
self.Name = setFontString(self.Health, GameFontNormalSmall, 10) |
self.Name:SetPoint("LEFT", 2, 0) |
self.Leader = self.Health:CreateTexture(nil, 'OVERLAY') --Leader Icon |
self.Leader:SetHeight(16) |
self.Leader:SetWidth(16) |
self.Leader:SetPoint('TOPLEFT', self, 0, 8) |
self.Leader:SetTexture('Interface\\GroupFrame\\UI-Group-LeaderIcon') |
self.RaidIcon = self.Health:CreateTexture(nil, "OVERLAY") --Raid Icons |
self.RaidIcon:SetHeight(16) |
self.RaidIcon:SetWidth(16) |
self.RaidIcon:SetPoint("TOP", self, 0, 8) |
self.RaidIcon:SetTexture("Interface\\TargetingFrame\\UI-RaidTargetingIcons") |
self.PvP = self.Power:CreateTexture(nil, "OVERLAY") |
self.PvP:SetPoint("CENTER", self.Health, "LEFT", 2, -5) |
self.PvP:SetHeight(25) |
self.PvP:SetWidth(25) |
if(unit=="player") then |
self.Power.value = setFontString(self.Power, GameFontNormalSmall, 10) |
self.Power.value:SetPoint("LEFT", self.Health, "LEFT", 2, 0) |
self.Spark = self.Power:CreateTexture(nil, "OVERLAY") |
self.Spark:SetTexture("Interface\\CastingBar\\UI-CastingBar-Spark") |
self.Spark:SetBlendMode("ADD") |
self.Spark:SetHeight(self.Power:GetHeight() * 2) |
self.Spark:SetWidth(self.Power:GetHeight() * 2) |
self.Spark.manatick = true |
self.ignoreBanzai = true |
if(class == "DRUID") then -- Druid Bar Support |
self.DruidMana = CreateFrame('StatusBar', nil, self) |
self.DruidMana:SetPoint("BOTTOMRIGHT", self.Power, "TOPRIGHT") |
self.DruidMana:SetPoint("BOTTOMLEFT", self.Power, "TOPLEFT") |
self.DruidMana:SetStatusBarTexture("Interface\\AddOns\\oUF_Pazrael\\textures\\Minimalist") |
self.DruidMana:SetStatusBarColor(0.3, 0.3, 1) |
self.DruidMana:SetHeight(1.35) |
self.DruidMana.text = setFontString(self.DruidMana, GameFontNormalSmall, 10) |
self.DruidMana.text:SetPoint("CENTER", 0, 7) |
end |
if(class == "DEATHKNIGHT") then |
RuneFrame:SetParent(self) |
RuneFrame:SetScale(0.75) |
RuneFrame:SetPoint("TOPLEFT", self, "BOTTOMLEFT",0 , -3) |
end |
self.CombatIcon = self.Health:CreateTexture(nil, 'OVERLAY') |
self.CombatIcon:SetPoint('CENTER', self, 'BOTTOMRIGHT', -1, -2) |
self.CombatIcon:SetHeight(14) |
self.CombatIcon:SetWidth(14) |
self.CombatIcon:SetTexture('Interface\\CharacterFrame\\UI-StateIcon') |
self.CombatIcon:SetTexCoord(0.58, 0.90, 0.08, 0.41) |
self.Combat = self.CombatIcon |
self.RestingIcon = self.Health:CreateTexture(nil, 'OVERLAY') |
self.RestingIcon:SetPoint('CENTER', self, 'TOPRIGHT', -1, -2) |
self.RestingIcon:SetHeight(14) |
self.RestingIcon:SetWidth(14) |
self.RestingIcon:SetTexture('Interface\\CharacterFrame\\UI-StateIcon') |
self.RestingIcon:SetTexCoord(0.09, 0.43, 0.08, 0.42) |
self.Resting = self.RestingIcon |
elseif(unit == 'target') then |
self.Power.value = setFontString(self.Power, GameFontNormalSmall, 10) |
self.Power.value:SetPoint("RIGHT", self.Health.value, "LEFT", 2, 0) |
if(class == "ROGUE" or class == "DRUID") then |
self.CPoints = setFontString(self, ChatFontSmall, 38) |
self.CPoints:SetPoint("RIGHT", self, "LEFT", -9, 3) |
self.CPoints:SetJustifyH("RIGHT") |
end |
self.Buffs = CreateFrame("Frame", nil, self) |
self.Buffs.spacing = 5.3 |
self.Buffs:SetHeight(self.Health:GetHeight() -3) |
self.Buffs:SetWidth(230/1.2) |
self.Buffs:SetPoint("TOPLEFT", self, "TOPRIGHT", 4, -1) |
self.Buffs.initialAnchor = "TOPLEFT" |
self.Buffs["growth-y"] = "DOWN" |
self.Buffs.size = math.floor(self.Buffs:GetHeight()) |
self.Debuffs = CreateFrame("Frame", nil, self) |
self.Debuffs.spacing = 5.3 |
self.Debuffs:SetHeight(self.Health:GetHeight() -3) |
self.Debuffs:SetWidth(230) |
self.Debuffs:SetPoint("TOPLEFT", self, "BOTTOMLEFT", 1, -5) |
self.Debuffs.initialAnchor = "TOPLEFT" |
self.Debuffs["growth-y"] = "DOWN" |
self.Debuffs.size = math.floor(self.Debuffs:GetHeight()) |
self.Debuffs.num = 9 |
elseif(unit=='pet')then |
if(class == 'HUNTER') then |
self.Power.colorHappiness = true |
self:RegisterEvent('UNIT_HAPPINESS') |
self.UNIT_HAPPINESS = self.UNIT_MANA |
else |
self.Power.colorPower = true |
end |
self.Buffs = CreateFrame("Frame", nil, self) |
self.Buffs.spacing = 5.3 |
self.Buffs:SetHeight(self.Health:GetHeight() -3) |
self.Buffs:SetWidth(230/1.2) |
self.Buffs:SetPoint("TOPRIGHT", self, "TOPLEFT", -4, -1) |
self.Buffs["growth-x"] = "LEFT" |
self.Buffs["growth-y"] = "UP" |
self.Buffs.initialAnchor = "TOPRIGHT" |
self.Buffs.size = math.floor(self.Buffs:GetHeight()) |
self.Debuffs = CreateFrame("Frame", nil, self) |
self.Debuffs.spacing = 5.3 |
self.Debuffs:SetHeight(self.Health:GetHeight() -3) |
self.Debuffs:SetWidth(230) |
self.Debuffs:SetPoint("TOPLEFT", self, "BOTTOMLEFT", 1, -5) |
self.Debuffs.initialAnchor = "TOPLEFT" |
self.Debuffs["growth-y"] = "DOWN" |
self.Debuffs.size = math.floor(self.Debuffs:GetHeight()) |
self.Debuffs.num = 6 |
elseif(unit=='focus' or unit=='focustarget' or unit=='targettarget') then |
self.Debuffs = CreateFrame("Frame", nil, self) -- Debuff Layout |
self.Debuffs.spacing = 5.3 |
self.Debuffs.size = (21 - 3) |
self.Debuffs:SetWidth(self.Debuffs.size * 4) |
self.Debuffs:SetHeight(self.Debuffs.size) |
self.Debuffs.num = 3 |
if(unit=='focus' or unit =='focustarget') then |
self.Debuffs:SetPoint("LEFT", self, "RIGHT", 3, 0) |
self.Debuffs.initialAnchor = "TOPLEFT" |
self.Debuffs["growth-x"] = "RIGHT" |
else |
self.Debuffs:SetPoint("RIGHT", self, "LEFT", -3, 0) |
self.Debuffs["growth-x"] = "LEFT" |
self.Debuffs.initialAnchor = "TOPRIGHT" |
end |
end |
if(not unit) then |
self.outsideRangeAlpha = 0.4 |
self.inRangeAlpha = 1.0 |
self.Range = true |
self.ReadyCheck = self.Health:CreateTexture(nil, 'OVERLAY') |
self.ReadyCheck:SetPoint('TOPRIGHT', self, 0, 8) |
self.ReadyCheck:SetHeight(16) |
self.ReadyCheck:SetWidth(16) |
end |
if castBar and (unit=="player" or unit=="target") then |
self.Castbar = CreateFrame("StatusBar") |
self.Castbar:SetBackdrop({bgFile="Interface\\Tooltips\\UI-Tooltip-Background", insets ={left = -1, right = -1, top = -1, bottom = -1}}) |
self.Castbar:SetBackdropColor(pazcolors[2].r, pazcolors[2].g, pazcolors[2].b, pazcolors[2].a) |
self.Castbar:SetWidth(230) |
self.Castbar:SetHeight(10) |
self.Castbar:SetStatusBarTexture("Interface\\AddOns\\oUF_Pazrael\\textures\\Minimalist") |
self.Castbar:SetStatusBarColor(pazcolors[0].r, pazcolors[0].g, pazcolors[0].b, pazcolors[0].a) |
self.Castbar:SetParent(self) |
self.Castbar:SetPoint("TOP", 0, 12) |
self.Castbar:SetMinMaxValues(1, 100) |
self.Castbar:SetValue(1) |
self.Castbar:Hide() |
self.Castbar.SetStatusBarColor = function(self) end |
self.Castbar.bg = self.Castbar:CreateTexture(nil, "BORDER") |
self.Castbar.bg:SetAllPoints(self.Castbar) |
self.Castbar.bg:SetTexture("Interface\\AddOns\\oUF_Pazrael\\textures\\Minimalist") |
self.Castbar.bg:SetVertexColor(pazcolors[1].r, pazcolors[1].g, pazcolors[1].b, pazcolors[1].a ) |
self.Castbar.bg.SetVertexColor = function(self) end |
self.Castbar.casttime = self.Castbar:CreateFontString(nil, "OVERLAY") |
self.Castbar.casttime:SetPoint("RIGHT", self.Castbar, -2, 0) |
self.Castbar.casttime:SetFontObject(GameFontNormalSmall) |
self.Castbar.casttime:SetTextColor(1, 1, 1) |
self.Castbar.casttime:SetJustifyH("RIGHT") |
self.Castbar.text = self.Castbar:CreateFontString(nil, "OVERLAY") |
self.Castbar.text:SetPoint("LEFT", self.Castbar, 2, 0) |
self.Castbar.text:SetWidth(230) |
self.Castbar.text:SetFontObject(GameFontNormalSmall) |
self.Castbar.text:SetTextColor(1, 1, 1) |
self.Castbar.text:SetJustifyH"LEFT" |
self.Castbar.safezone = self.Castbar:CreateTexture(nil,"ARTWORK") |
self.Castbar.safezone = self.Castbar:CreateTexture(nil,"ARTWORK") |
self.Castbar.safezone:SetTexture("Interface\\AddOns\\oUF_Pazrael\\textures\\Minimalist") |
self.Castbar.safezone:SetVertexColor(pazcolors[4].r, pazcolors[4].g, pazcolors[4].b, pazcolors[4].a) |
self.Castbar.safezone:SetPoint("TOPRIGHT") |
self.Castbar.safezone:SetPoint("BOTTOMRIGHT") |
end |
self.DebuffHighlightBackdrop = true |
self.DebuffHighlightFilter = true |
if(unit == 'player' or unit == 'target') then |
self.CombatFeedbackText = setFontString(self.Health, GameFontNormalSmall, 18, 'OUTLINE') |
self.CombatFeedbackText:SetPoint('CENTER', self.Health, 'CENTER', 0, 0) |
self:SetAttribute('initial-height', 28) |
self:SetAttribute('initial-width', 230) |
self.Health:SetHeight(22) |
self.Power:SetHeight(5) |
elseif(unit == 'pet') then |
self:SetAttribute('initial-height', 28) |
self:SetAttribute('initial-width', 130) |
self.Health:SetHeight(22) |
self.Power:SetHeight(5) |
elseif(self:GetParent():GetName():match"oUF_Raid") then |
self:SetAttribute('initial-height', 24) |
self:SetAttribute('initial-width', 50) |
self.Health:SetHeight(21) |
self.Power:SetHeight(2) |
else |
self:SetAttribute('initial-height', 21) |
self:SetAttribute('initial-width', 130) |
self.Health:SetHeight(17.5) |
self.Power:SetHeight(2) |
end |
self.UNIT_NAME_UPDATE = OverrideUpdateName |
self.PostCreateAuraIcon = PostCreateAuraIcon |
self.PostUpdateHealth = PostUpdateHealth |
self.PostUpdatePower = PostUpdatePower |
return self |
end |
oUF:RegisterSubTypeMapping('UNIT_LEVEL') |
oUF:RegisterStyle('Pazrael', styleFunc) |
oUF:SetActiveStyle('Pazrael') |
oUF:Spawn('player'):SetPoint('CENTER', UIParent, -150, -225) |
oUF:Spawn('pet'):SetPoint('RIGHT', oUF.units.player, 'LEFT', -25, 0) |
oUF:Spawn('target'):SetPoint('CENTER', UIParent, 150, -225) |
oUF:Spawn('targettarget'):SetPoint('BOTTOMRIGHT', oUF.units.target, 'TOPRIGHT', 0, 14) |
oUF:Spawn('focus'):SetPoint('BOTTOMLEFT', oUF.units.player, 'TOPLEFT', 0, 14) |
if select(2, UnitClass('player')) == 'DEATHKNIGHT' then |
oUF:Spawn('focustarget'):SetPoint('TOPLEFT', oUF.units.player, 'BOTTOMLEFT',0, -21) |
else |
oUF:Spawn('focustarget'):SetPoint('TOPLEFT', oUF.units.player, 'BOTTOMLEFT',0, -14) |
end |
local party = oUF:Spawn("header", "oUF_Party") |
party:SetPoint("TOPLEFT", 15, -15) |
party:SetAttribute("yOffset", -5) |
party:Show() |
local partyToggle = CreateFrame("Frame") |
if partyRaid then |
partyToggle:SetScript("OnEvent", function(self) |
if(InCombatLockdown()) then self:RegisterEvent("PLAYER_REGEN_ENABLED") |
else self:UnregisterEvent("PLAYER_REGEN_ENABLED") |
if(GetNumRaidMembers() > 0) then |
party:SetAttribute("showRaid", true) |
party:SetAttribute("showParty", false) |
elseif(GetNumPartyMembers() > 0) then |
party:SetAttribute("showRaid", false) |
party:SetAttribute("showParty", true) |
end |
end |
end) |
else |
partyToggle:SetScript("OnEvent", function(self) |
if(InCombatLockdown()) then self:RegisterEvent("PLAYER_REGEN_ENABLED") |
else self:UnregisterEvent("PLAYER_REGEN_ENABLED") |
if(GetNumRaidMembers() > 0) then |
party:Hide() |
elseif(GetNumPartyMembers() > 0) then |
party:SetAttribute("showParty", true) |
party:Show() |
end |
end |
end) |
local last = {} |
for i = 1, 8 do |
local raid = oUF:Spawn("header", "oUF_Raid"..i) |
raid:SetManyAttributes("groupFilter", tostring(i), "showRaid", true, "yOffSet", -8) |
table.insert(last, raid) |
if(i==1) then |
raid:SetPoint("TOPLEFT", UIParent, "TOPLEFT", 15, -15) |
else |
raid:SetPoint("TOPLEFT", last[i-1], "TOPRIGHT", 8, 0) |
end |
raid:Show() |
end |
end |
partyToggle:RegisterEvent("PARTY_MEMBERS_CHANGED") |
partyToggle:RegisterEvent("PARTY_LEADER_CHANGED") |
partyToggle:RegisterEvent("RAID_ROSTER_UPDATE") |
partyToggle:RegisterEvent("PLAYER_LOGIN") |