diff --git a/modules/PlayerHealth.lua b/modules/PlayerHealth.lua index ce5210d..b981523 100644 --- a/modules/PlayerHealth.lua +++ b/modules/PlayerHealth.lua @@ -4,6 +4,8 @@ local PlayerHealth = AceOO.Class(IceUnitBar) PlayerHealth.prototype.resting = nil +local configMode = false + -- Constructor -- function PlayerHealth.prototype:init() PlayerHealth.super.prototype.init(self, "PlayerHealth", "player") @@ -22,6 +24,22 @@ function PlayerHealth.prototype:GetDefaultSettings() settings["lowerText"] = "[FractionalHP:HPColor:Bracket]" settings["allowMouseInteraction"] = true + settings["showStatusIcon"] = true + settings["statusIconOffset"] = {x=110, y=0} + settings["statusIconScale"] = 1 + + settings["showLeaderIcon"] = true + settings["leaderIconOffset"] = {x=135, y=15} + settings["leaderIconScale"] = 0.9 + + settings["showLootMasterIcon"] = true + settings["lootMasterIconOffset"] = {x=100, y=-20} + settings["lootMasterIconScale"] = 0.9 + + settings["showPvPIcon"] = true + settings["PvPIconOffset"] = {x=95, y=-40} + settings["PvPIconScale"] = 0.9 + return settings end @@ -31,9 +49,22 @@ function PlayerHealth.prototype:Enable(core) self:RegisterEvent("UNIT_HEALTH", "Update") self:RegisterEvent("UNIT_MAXHEALTH", "Update") - + + self:RegisterEvent("PLAYER_ENTERING_WORLD", "EnteringWorld") + self:RegisterEvent("PLAYER_UPDATE_RESTING", "Resting") - self:RegisterEvent("PLAYER_ENTERING_WORLD", "Resting") + + self:RegisterEvent("PLAYER_REGEN_ENABLED", "CheckCombat") + self:RegisterEvent("PLAYER_REGEN_DISABLED", "CheckCombat") + + self:RegisterEvent("PARTY_LEADER_CHANGED", "CheckLeader") + self:RegisterEvent("PARTY_MEMBERS_CHANGED", "CheckLeader") + + self:RegisterEvent("PARTY_LOOT_METHOD_CHANGED", "CheckLootMaster") + + self:RegisterEvent("UPDATE_FACTION", "CheckPvP") + self:RegisterEvent("PLAYER_FLAGS_CHANGED", "CheckPvP") + self:RegisterEvent("UNIT_FACTION", "CheckPvP") if (self.moduleSettings.hideBlizz) then self:HideBlizz() @@ -120,6 +151,328 @@ function PlayerHealth.prototype:GetOptions() usage = '', order = 43 } + + opts["iconSettings"] = + { + type = 'group', + name = '|c' .. self.configColor .. 'Icon Settings|r', + desc = 'Settings related to icons', + disabled = function() + return not self.moduleSettings.enabled + end, + args = { + iconConfigMode = { + type = "toggle", + name = "Icon config mode", + desc = "With this enabled, all icons draw so you can configure their placement\n\nNote: the combat and status icons are actually the same texture so you'll only see combat in config mode (unless you're already resting)", + get = function() + return configMode + end, + set = function(v) + configMode = v + self:EnteringWorld() + end, + order = 5 + }, + + statusIcon = { + type = "toggle", + name = "Show status icon", + desc = "Whether or not to show the status icon (resting/combat) above this bar", + get = function() + return self.moduleSettings.showStatusIcon + end, + set = function(value) + self.moduleSettings.showStatusIcon = value + self:Resting() + self:CheckCombat() + end, + disabled = function() + return not self.moduleSettings.enabled + end, + order = 10 + }, + statusIconOffsetX = { + type = "range", + name = "Status Icon Horizontal Offset", + desc = "How much to offset the status icon (resting/combat) from the bar horizontally", + min = 0, + max = 250, + step = 1, + get = function() + return self.moduleSettings.statusIconOffset['x'] + end, + set = function(v) + self.moduleSettings.statusIconOffset['x'] = v + self:SetTexLoc(self.frame.statusIcon, self.moduleSettings.statusIconOffset['x'], self.moduleSettings.statusIconOffset['y']) + end, + disabled = function() + return not self.moduleSettings.enabled or not self.moduleSettings.showStatusIcon + end, + order = 11 + }, + statusIconOffsetY = { + type = "range", + name = "Status Icon Vertical Offset", + desc = "How much to offset the status icon (resting/combat) from the bar vertically", + min = -300, + max = 50, + step = 1, + get = function() + return self.moduleSettings.statusIconOffset['y'] + end, + set = function(v) + self.moduleSettings.statusIconOffset['y'] = v + self:SetTexLoc(self.frame.statusIcon, self.moduleSettings.statusIconOffset['x'], self.moduleSettings.statusIconOffset['y']) + end, + disabled = function() + return not self.moduleSettings.enabled or not self.moduleSettings.showStatusIcon + end, + order = 12 + }, + statusIconScale = { + type = "range", + name = "Status Icon Scale", + desc = "How much to scale the status icon", + min = 0.05, + max = 2, + step = 0.05, + get = function() + return self.moduleSettings.statusIconScale + end, + set = function(v) + self.moduleSettings.statusIconScale = v + self:SetTexScale(self.frame.statusIcon, 20, 20, v) + end, + disabled = function() + return not self.moduleSettings.enabled or not self.moduleSettings.showStatusIcon + end, + order = 13 + }, + + leaderIcon = { + type = "toggle", + name = "Show leader icon", + desc = "Whether or not to show the party leader icon above this bar", + get = function() + return self.moduleSettings.showLeaderIcon + end, + set = function(value) + self.moduleSettings.showLeaderIcon = value + self:CheckLeader() + end, + disabled = function() + return not self.moduleSettings.enabled + end, + order = 20 + }, + leaderIconOffsetX = { + type = "range", + name = "Leader Icon Horizontal Offset", + desc = "How much to offset the leader icon from the bar horizontally", + min = 0, + max = 250, + step = 1, + get = function() + return self.moduleSettings.leaderIconOffset['x'] + end, + set = function(v) + self.moduleSettings.leaderIconOffset['x'] = v + self:SetTexLoc(self.frame.leaderIcon, self.moduleSettings.leaderIconOffset['x'], self.moduleSettings.leaderIconOffset['y']) + end, + disabled = function() + return not self.moduleSettings.enabled or not self.moduleSettings.showLeaderIcon + end, + order = 21 + }, + leaderIconOffsetY = { + type = "range", + name = "Leader Icon Vertical Offset", + desc = "How much to offset the leader icon from the bar vertically", + min = -300, + max = 50, + step = 1, + get = function() + return self.moduleSettings.leaderIconOffset['y'] + end, + set = function(v) + self.moduleSettings.leaderIconOffset['y'] = v + self:SetTexLoc(self.frame.leaderIcon, self.moduleSettings.leaderIconOffset['x'], self.moduleSettings.leaderIconOffset['y']) + end, + disabled = function() + return not self.moduleSettings.enabled or not self.moduleSettings.showLeaderIcon + end, + order = 22 + }, + leaderIconScale = { + type = "range", + name = "Leader Icon Scale", + desc = "How much to scale the leader icon", + min = 0.05, + max = 2, + step = 0.05, + get = function() + return self.moduleSettings.leaderIconScale + end, + set = function(v) + self.moduleSettings.leaderIconScale = v + self:SetTexScale(self.frame.leaderIcon, 20, 20, v) + end, + disabled = function() + return not self.moduleSettings.enabled or not self.moduleSettings.showLeaderIcon + end, + order = 23 + }, + + lootMasterIcon = { + type = "toggle", + name = "Show loot master icon", + desc = "Whether or not to show the loot master icon", + get = function() + return self.moduleSettings.showLootMasterIcon + end, + set = function(value) + self.moduleSettings.showLootMasterIcon = value + self:CheckLootMaster() + end, + disabled = function() + return not self.moduleSettings.enabled + end, + order = 30 + }, + lootMasterIconOffsetX = { + type = "range", + name = "Loot Master Icon Horizontal Offset", + desc = "How much to offset the loot master icon from the bar horizontally", + min = 0, + max = 250, + step = 1, + get = function() + return self.moduleSettings.lootMasterIconOffset['x'] + end, + set = function(v) + self.moduleSettings.lootMasterIconOffset['x'] = v + self:SetTexLoc(self.frame.lootMasterIcon, self.moduleSettings.lootMasterIconOffset['x'], self.moduleSettings.lootMasterIconOffset['y']) + end, + disabled = function() + return not self.moduleSettings.enabled or not self.moduleSettings.showLootMasterIcon + end, + order = 31 + }, + lootMasterIconOffsetY = { + type = "range", + name = "Loot Master Icon Vertical Offset", + desc = "How much to offset the loot master icon from the bar vertically", + min = -300, + max = 50, + step = 1, + get = function() + return self.moduleSettings.lootMasterIconOffset['y'] + end, + set = function(v) + self.moduleSettings.lootMasterIconOffset['y'] = v + self:SetTexLoc(self.frame.lootMasterIcon, self.moduleSettings.lootMasterIconOffset['x'], self.moduleSettings.lootMasterIconOffset['y']) + end, + disabled = function() + return not self.moduleSettings.enabled or not self.moduleSettings.showLootMasterIcon + end, + order = 32 + }, + lootMasterIconScale = { + type = "range", + name = "Loot Master Icon Scale", + desc = "How much to scale the loot master icon", + min = 0.05, + max = 2, + step = 0.05, + get = function() + return self.moduleSettings.lootMasterIconScale + end, + set = function(v) + self.moduleSettings.lootMasterIconScale = v + self:SetTexScale(self.frame.lootMasterIcon, 20, 20, v) + end, + disabled = function() + return not self.moduleSettings.enabled or not self.moduleSettings.showLootMasterIcon + end, + order = 33 + }, + + PvPIcon = { + type = "toggle", + name = "Show PvP icon", + desc = "Whether or not to show the PvP icon", + get = function() + return self.moduleSettings.showPvPIcon + end, + set = function(value) + self.moduleSettings.showPvPIcon = value + self:CheckPvP() + end, + disabled = function() + return not self.moduleSettings.enabled + end, + order = 40 + }, + PvPIconOffsetX = { + type = "range", + name = "PvP Icon Horizontal Offset", + desc = "How much to offset the PvP icon from the bar horizontally", + min = 0, + max = 250, + step = 1, + get = function() + return self.moduleSettings.PvPIconOffset['x'] + end, + set = function(v) + self.moduleSettings.PvPIconOffset['x'] = v + self:SetTexLoc(self.frame.PvPIcon, self.moduleSettings.PvPIconOffset['x'], self.moduleSettings.PvPIconOffset['y']) + end, + disabled = function() + return not self.moduleSettings.enabled or not self.moduleSettings.showPvPIcon + end, + order = 41 + }, + PvPIconOffsetY = { + type = "range", + name = "PvP Icon Vertical Offset", + desc = "How much to offset the PvP icon from the bar vertically", + min = -300, + max = 50, + step = 1, + get = function() + return self.moduleSettings.PvPIconOffset['y'] + end, + set = function(v) + self.moduleSettings.PvPIconOffset['y'] = v + self:SetTexLoc(self.frame.PvPIcon, self.moduleSettings.PvPIconOffset['x'], self.moduleSettings.PvPIconOffset['y']) + end, + disabled = function() + return not self.moduleSettings.enabled or not self.moduleSettings.showPvPIcon + end, + order = 42 + }, + PvPIconScale = { + type = "range", + name = "PvP Icon Scale", + desc = "How much to scale the PvP icon", + min = 0.05, + max = 2, + step = 0.05, + get = function() + return self.moduleSettings.PvPIconScale + end, + set = function(v) + self.moduleSettings.PvPIconScale = v + self:SetTexScale(self.frame.PvPIcon, 20, 20, v) + end, + disabled = function() + return not self.moduleSettings.enabled or not self.moduleSettings.showPvPIcon + end, + order = 43 + } + } + } return opts end @@ -171,9 +524,119 @@ function PlayerHealth.prototype:CreateBackground(redraw) end +function PlayerHealth.prototype:EnteringWorld() + self:Resting() + self:CheckCombat() + self:CheckLeader() + self:CheckPvP() +end + + function PlayerHealth.prototype:Resting() self.resting = IsResting() self:Update(self.unit) + + if (self.resting) then + if self.moduleSettings.showStatusIcon and not self.frame.statusIcon then + self.frame.statusIcon = self:CreateTexCoord(self.frame.statusIcon, "Interface\\CharacterFrame\\UI-StateIcon", 20, 20, + self.moduleSettings.statusIconScale, 0.0625, 0.4475, 0.0625, 0.4375) + self:SetTexLoc(self.frame.statusIcon, self.moduleSettings.statusIconOffset['x'], self.moduleSettings.statusIconOffset['y']) + elseif not self.moduleSettings.showStatusIcon and self.frame.statusIcon and not UnitAffectingCombat(self.unit) then + self.frame.statusIcon = self:DestroyTexFrame(self.frame.statusIcon) + end + else + if not UnitAffectingCombat and self.frame.statusIcon then + self.frame.statusIcon = self:DestroyTexFrame(self.frame.statusIcon) + end + end +end + + +function PlayerHealth.prototype:CheckCombat() + if UnitAffectingCombat(self.unit) or configMode then + if (configMode or self.moduleSettings.showStatusIcon) and not self.frame.statusIcon then + self.frame.statusIcon = self:CreateTexCoord(self.frame.statusIcon, "Interface\\CharacterFrame\\UI-StateIcon", 20, 20, + self.moduleSettings.statusIconScale, 0.5625, 0.9375, 0.0625, 0.4375) + self:SetTexLoc(self.frame.statusIcon, self.moduleSettings.statusIconOffset['x'], self.moduleSettings.statusIconOffset['y']) + elseif not configMode and not self.resting and not self.moduleSettings.showStatusIcon and self.frame.statusIcon then + self.frame.statusIcon = self:DestroyTexFrame(self.frame.statusIcon) + end + else + if not self.resting and self.frame.statusIcon then + self.frame.statusIcon = self:DestroyTexFrame(self.frame.statusIcon) + end + end +end + + +function PlayerHealth.prototype:CheckLeader() + if configMode or IsPartyLeader() then + if (configMode or self.moduleSettings.showLeaderIcon) and not self.frame.leaderIcon then + self.frame.leaderIcon = self:CreateTexCoord(self.frame.leaderIcon, "Interface\\GroupFrame\\UI-Group-LeaderIcon", 20, 20, + self.moduleSettings.leaderIconScale, 0, 1, 0, 1) + self:SetTexLoc(self.frame.leaderIcon, self.moduleSettings.leaderIconOffset['x'], self.moduleSettings.leaderIconOffset['y']) + elseif not configMode and not self.moduleSettings.showLeaderIcon and self.frame.leaderIcon then + self.frame.leaderIcon = self:DestroyTexFrame(self.frame.leaderIcon) + end + else + if self.frame.leaderIcon then + self.frame.leaderIcon = self:DestroyTexFrame(self.frame.leaderIcon) + end + end + + self:CheckLootMaster() +end + + +function PlayerHealth.prototype:CheckLootMaster() + local _, lootmaster = GetLootMethod() + if configMode or lootmaster == 0 then + if (configMode or self.moduleSettings.showLootMasterIcon) and not self.frame.lootMasterIcon then + self.frame.lootMasterIcon = self:CreateTexCoord(self.frame.lootMasterIcon, "Interface\\GroupFrame\\UI-Group-MasterLooter", 20, 20, + self.moduleSettings.lootMasterIconScale, 0, 1, 0, 1) + self:SetTexLoc(self.frame.lootMasterIcon, self.moduleSettings.lootMasterIconOffset['x'], self.moduleSettings.lootMasterIconOffset['y']) + elseif not configMode and not self.moduleSettings.showLootMasterIcon and self.frame.lootMasterIcon then + self.frame.lootMasterIcon = self:DestroyTexFrame(self.frame.lootMasterIcon) + end + else + if self.frame.lootMasterIcon then + self.frame.lootMasterIcon = self:DestroyTexFrame(self.frame.lootMasterIcon) + end + end +end + + +function PlayerHealth.prototype:CheckPvP() + local pvpMode = nil + local minx, maxx, miny, maxy + + if configMode or UnitIsPVPFreeForAll(self.unit) then + pvpMode = "FFA" + + minx, maxx, miny, maxy = 0.05, 0.605, 0.015, 0.57 + elseif UnitIsPVP(self.unit) then + pvpMode = UnitFactionGroup(self.unit) + + if pvpMode == "Alliance" then + minx, maxx, miny, maxy = 0.07, 0.58, 0.06, 0.57 + else + minx, maxx, miny, maxy = 0.08, 0.58, 0.045, 0.545 + end + end + + if pvpMode then + if (configMode or self.moduleSettings.showPvPIcon) and not self.frame.PvPIcon then + self.frame.PvPIcon = self:CreateTexCoord(self.frame.PvPIcon, "Interface\\TargetingFrame\\UI-PVP-"..pvpMode, 20, 20, + self.moduleSettings.PvPIconScale, minx, maxx, miny, maxy) + self:SetTexLoc(self.frame.PvPIcon, self.moduleSettings.PvPIconOffset['x'], self.moduleSettings.PvPIconOffset['y']) + elseif not configMode and not self.moduleSettings.showPvPIcon and self.frame.PvPIcon then + self.frame.PvPIcon = self:DestroyTexFrame(self.frame.PvPIcon) + end + else + if self.frame.PvPIcon then + self.frame.PvPIcon = self:DestroyTexFrame(self.frame.PvPIcon) + end + end end @@ -211,6 +674,35 @@ function PlayerHealth.prototype:Update(unit) end +function PlayerHealth.prototype:CreateTexCoord(texframe, icon, width, height, scale, left, right, top, bottom) + texframe = self.frame:CreateTexture(nil, "BACKGROUND") + texframe:SetTexture(icon) + texframe:SetTexCoord(left, right, top, bottom) + self:SetTexScale(texframe, width, height, scale) + + return texframe +end + + +function PlayerHealth.prototype:SetTexLoc(texframe, xpos, ypos, anchorFrom, anchorTo) + texframe:ClearAllPoints() + texframe:SetPoint(anchorFrom and anchorFrom or "TOPLEFT", self.frame, anchorTo and anchorTo or "TOPLEFT", xpos, ypos) +end + + +function PlayerHealth.prototype:SetTexScale(texframe, width, height, scale) + texframe:SetWidth(width * scale) + texframe:SetHeight(height * scale) +end + + +function PlayerHealth.prototype:DestroyTexFrame(texframe) + texframe:SetTexture(nil) + texframe:Hide() + texframe:ClearAllPoints() + + return nil +end function PlayerHealth.prototype:ShowBlizz()