--[[ ############################################################################## _____/\\\\\\\\\\\____/\\\________/\\\__/\\\________/\\\__/\\\\\\\\\\\_ # ___/\\\/////////\\\_\/\\\_______\/\\\_\/\\\_______\/\\\_\/////\\\///__ # __\//\\\______\///__\//\\\______/\\\__\/\\\_______\/\\\_____\/\\\_____ # ___\////\\\__________\//\\\____/\\\___\/\\\_______\/\\\_____\/\\\_____ # ______\////\\\________\//\\\__/\\\____\/\\\_______\/\\\_____\/\\\_____ # _________\////\\\______\//\\\/\\\_____\/\\\_______\/\\\_____\/\\\_____ # __/\\\______\//\\\______\//\\\\\______\//\\\______/\\\______\/\\\_____ # _\///\\\\\\\\\\\/________\//\\\________\///\\\\\\\\\/____/\\\\\\\\\\\_# ___\///////////___________\///___________\/////////_____\///////////_# ############################################################################## S U P E R - V I L L A I N - U I By: Munglunch # ############################################################################## ########################################################## LOCALIZED LUA FUNCTIONS ########################################################## ]]-- --[[ GLOBALS ]]-- local _G = _G; local unpack = _G.unpack; local select = _G.select; local assert = _G.assert; --[[ ########################################################## GET ADDON DATA ########################################################## ]]-- local SuperVillain, L = unpack(select(2, ...)); local MOD = SuperVillain.Registry:Expose('SVUnit'); local _, ns = ... local oUF_SuperVillain = ns.oUF --[[ MUNGLUNCH's FASTER ASSERT FUNCTION ]]-- local assert = enforce; assert(oUF_SuperVillain, "SVUI was unable to locate oUF."); local LSM = LibStub("LibSharedMedia-3.0"); --[[ ########################################################## LOCAL FUNCTIONS ########################################################## ]]-- local HEALTH_ANIM_FILE = [[Interface\Addons\SVUI\assets\artwork\Unitframe\UNIT-HEALTH-ANIMATION]]; local DEAD_MODEL_FILE = [[Spells\Monk_travelingmist_missile.m2]]; local Anim_OnUpdate = function(self) local parent = self.parent local coord = self._coords; parent:SetTexCoord(coord[1],coord[2],coord[3],coord[4]) end; local Anim_OnPlay = function(self) local parent = self.parent parent:SetAlpha(1) if not parent:IsShown() then parent:Show() end end; local Anim_OnStop = function(self) local parent = self.parent parent:SetAlpha(0) if parent:IsShown() then parent:Hide() end end; local function SetNewAnimation(frame, animType, parent) local anim = frame:CreateAnimation(animType, subType) anim.parent = parent return anim end local function SetAnim(frame, parent) local speed = 0.08 frame.anim = frame:CreateAnimationGroup("Sprite") frame.anim.parent = parent; frame.anim:SetScript("OnPlay", Anim_OnPlay) frame.anim:SetScript("OnFinished", Anim_OnStop) frame.anim:SetScript("OnStop", Anim_OnStop) frame.anim[1] = SetNewAnimation(frame.anim, "Translation", frame) frame.anim[1]:SetOrder(1) frame.anim[1]:SetDuration(speed) frame.anim[1]._coords = {0,0.5,0,0.25} frame.anim[1]:SetScript("OnUpdate", Anim_OnUpdate) frame.anim[2] = SetNewAnimation(frame.anim, "Translation", frame) frame.anim[2]:SetOrder(2) frame.anim[2]:SetDuration(speed) frame.anim[2]._coords = {0.5,1,0,0.25} frame.anim[2]:SetScript("OnUpdate", Anim_OnUpdate) frame.anim[3] = SetNewAnimation(frame.anim, "Translation", frame) frame.anim[3]:SetOrder(3) frame.anim[3]:SetDuration(speed) frame.anim[3]._coords = {0,0.5,0.25,0.5} frame.anim[3]:SetScript("OnUpdate", Anim_OnUpdate) frame.anim[4] = SetNewAnimation(frame.anim, "Translation", frame) frame.anim[4]:SetOrder(4) frame.anim[4]:SetDuration(speed) frame.anim[4]._coords = {0.5,1,0.25,0.5} frame.anim[4]:SetScript("OnUpdate", Anim_OnUpdate) frame.anim[5] = SetNewAnimation(frame.anim, "Translation", frame) frame.anim[5]:SetOrder(5) frame.anim[5]:SetDuration(speed) frame.anim[5]._coords = {0,0.5,0.5,0.75} frame.anim[5]:SetScript("OnUpdate", Anim_OnUpdate) frame.anim[6] = SetNewAnimation(frame.anim, "Translation", frame) frame.anim[6]:SetOrder(6) frame.anim[6]:SetDuration(speed) frame.anim[6]._coords = {0.5,1,0.5,0.75} frame.anim[6]:SetScript("OnUpdate", Anim_OnUpdate) frame.anim[7] = SetNewAnimation(frame.anim, "Translation", frame) frame.anim[7]:SetOrder(7) frame.anim[7]:SetDuration(speed) frame.anim[7]._coords = {0,0.5,0.75,1} frame.anim[7]:SetScript("OnUpdate", Anim_OnUpdate) frame.anim[8] = SetNewAnimation(frame.anim, "Translation", frame) frame.anim[8]:SetOrder(8) frame.anim[8]:SetDuration(speed) frame.anim[8]._coords = {0.5,1,0.75,1} frame.anim[8]:SetScript("OnUpdate", Anim_OnUpdate) frame.anim:SetLooping("REPEAT") end local function updateFrequentUpdates(self) local health = self.Health if health.frequentUpdates and not self:IsEventRegistered("UNIT_HEALTH_FREQUENT") then if GetCVarBool("predictedHealth") ~= 1 then SetCVar("predictedHealth", 1) end self:RegisterEvent('UNIT_HEALTH_FREQUENT', Path) if self:IsEventRegistered("UNIT_HEALTH") then self:UnregisterEvent("UNIT_HEALTH", Path) end elseif not self:IsEventRegistered("UNIT_HEALTH") then self:RegisterEvent('UNIT_HEALTH', Path) if self:IsEventRegistered("UNIT_HEALTH_FREQUENT") then self:UnregisterEvent("UNIT_HEALTH_FREQUENT", Path) end end end local CustomUpdate = function(self, event, unit) if(self.unit ~= unit) or not unit then return end local health = self.Health local min, max = UnitHealth(unit), UnitHealthMax(unit) local disconnected = not UnitIsConnected(unit) local invisible = ((min == max) or UnitIsDeadOrGhost(unit) or disconnected); local tapped = (UnitIsTapped(unit) and (not UnitIsTappedByPlayer(unit))); if health.fillInverted then health:SetReverseFill(true) end health:SetMinMaxValues(-max, 0) health:SetValue(-min) health.disconnected = disconnected if health.frequentUpdates ~= health.__frequentUpdates then health.__frequentUpdates = health.frequentUpdates updateFrequentUpdates(self) end local bg = health.bg; local mu = (min / max); if(invisible or not health.overlayAnimation) then health.animation[1].anim:Stop() health.animation[1]:SetAlpha(0) end if(invisible) then health:SetStatusBarColor(0.6,0.4,1,0.5) health.animation[1]:SetVertexColor(0.8,0.3,1,0.4) elseif(health.colorOverlay) then local t = health.colors.health health:SetStatusBarColor(t[1], t[2], t[3], 0.9) else health:SetStatusBarColor(1, 0.25 * mu, 0, 0.85) health.animation[1]:SetVertexColor(1, 0.1 * mu, 0, 0.5) end if(bg) then bg:SetVertexColor(0,0,0,0) end if(health.overlayAnimation and not invisible) then if(mu <= 0.25) then health.animation[1]:SetAlpha(1) health.animation[1].anim:Play() else health.animation[1].anim:Stop() health.animation[1]:SetAlpha(0) end end if self.ResurrectIcon then self.ResurrectIcon:SetAlpha(min == 0 and 1 or 0) end; if self.isForced then local current = random(1,max) health:SetValue(-current) end; -- local portrait = self.Portrait -- if(portrait and portrait:IsObjectType'Model') then -- if(UnitIsDeadOrGhost(unit) and not portrait.isdead) then -- portrait:SetCamDistanceScale(1) -- portrait:SetPortraitZoom(0) -- portrait:SetPosition(4,-1,1) -- portrait:ClearModel() -- portrait:SetModel(DEAD_MODEL_FILE) -- portrait.isdead = true -- portrait.guid = nil -- elseif(not UnitIsDeadOrGhost(unit) and portrait.isdead == true) then -- portrait.isdead = nil -- MOD.Update3DPortrait(self, event, unit) -- end -- end end; local Update = function(self, event, unit) if(self.unit ~= unit) or not unit then return end local health = self.Health local min, max = UnitHealth(unit), UnitHealthMax(unit) local disconnected = not UnitIsConnected(unit) if health.fillInverted then health:SetReverseFill(true) end health:SetMinMaxValues(0, max) if(disconnected) then health:SetValue(max) else health:SetValue(min) end health.disconnected = disconnected if health.frequentUpdates ~= health.__frequentUpdates then health.__frequentUpdates = health.frequentUpdates updateFrequentUpdates(self) end local bg = health.bg; local db = self:GetParent().db or SuperVillain.db.SVUnit; local r, g, b, t, t2; if(health.colorTapping and not UnitPlayerControlled(unit) and UnitIsTapped(unit) and not UnitIsTappedByPlayer(unit) and not UnitIsTappedByAllThreatList(unit)) then t = health.colors.tapped elseif(health.colorDisconnected and not UnitIsConnected(unit)) then t = health.colors.disconnected elseif(health.colorClass and UnitIsPlayer(unit)) or (health.colorClassNPC and not UnitIsPlayer(unit)) or (health.colorClassPet and UnitPlayerControlled(unit) and not UnitIsPlayer(unit)) then local _, class = UnitClass(unit) local tmp = oUF_SuperVillain.colors.class[class] or health.colors.health t = {(tmp[1] * 0.75),(tmp[2] * 0.75),(tmp[3] * 0.75)} if(bg and db.classbackdrop and UnitIsPlayer(unit)) then t2 = t end elseif(health.colorReaction and UnitReaction(unit, 'player')) then t = oUF_SuperVillain.colors.reaction[UnitReaction(unit, "player")] if(bg and db.classbackdrop and not UnitIsPlayer(unit) and UnitReaction(unit, "player")) then t2 = t end elseif(health.colorSmooth) then r, g, b = oUF_SuperVillain.ColorGradient(min, max, unpack(health.smoothGradient or oUF_SuperVillain.colors.smooth)) elseif(health.colorHealth) then t = health.colors.health end if(t) then r, g, b = t[1], t[2], t[3] end if(b) then if(db.healthclass == true and db.colorhealthbyvalue == true or db.colorhealthbyvalue and self.isForced and not(UnitIsTapped(unit) and not UnitIsTappedByPlayer(unit))) then r, g, b = oUF_SuperVillain.ColorGradient(min,max,1,0,0,1,1,0,r,g,b) end health:SetStatusBarColor(r, g, b) if(bg) then local mu = bg.multiplier or 1 if(t2) then r, g, b = t2[1], t2[2], t2[3] end bg:SetVertexColor(r * mu, g * mu, b * mu) end end if self.ResurrectIcon then self.ResurrectIcon:SetAlpha(min == 0 and 1 or 0) end; if self.isForced then min = random(1,max) health:SetValue(min) end; if self.db and self.db.gridMode then health:SetOrientation("VERTICAL") end; local portrait = self.Portrait if(portrait and portrait:IsObjectType'Model') then if(UnitIsDeadOrGhost(unit) and not portrait.isdead) then portrait:SetCamDistanceScale(1) portrait:SetPortraitZoom(0) portrait:SetPosition(4,-1,1) portrait:ClearModel() portrait:SetModel(DEAD_MODEL_FILE) portrait.isdead = true portrait.guid = nil elseif(not UnitIsDeadOrGhost(unit) and portrait.isdead == true) then portrait.isdead = nil MOD.Update3DPortrait(self, event, unit) end end end --[[ ########################################################## BUILD FUNCTION ########################################################## ]]-- function MOD:CreateHealthBar(frame, hasbg, text, reverse) local healthBar = CreateFrame("StatusBar", nil, frame) healthBar:SetFrameStrata("LOW") healthBar:SetFrameLevel(4) healthBar.colors = {} healthBar.colors.health = oUF_SuperVillain.colors.health healthBar.colors.tapped = oUF_SuperVillain.colors.tapped healthBar.colors.disconnected = oUF_SuperVillain.colors.disconnected healthBar:SetStatusBarTexture(SuperVillain.Media.bar.default) if hasbg then healthBar.bg = healthBar:CreateTexture(nil, "BORDER") healthBar.bg:SetAllPoints() healthBar.bg:SetTexture(SuperVillain.Media.bar.gradient) healthBar.bg:SetVertexColor(0.4, 0.1, 0.1) healthBar.bg.multiplier = 0.25 end; local flasher = CreateFrame("Frame", nil, frame) flasher:SetFrameLevel(3) flasher:SetAllPoints(healthBar) flasher[1] = flasher:CreateTexture(nil, "OVERLAY", nil, 1) flasher[1]:SetTexture(HEALTH_ANIM_FILE) flasher[1]:SetTexCoord(0, 0.5, 0, 0.25) flasher[1]:SetVertexColor(1, 0.3, 0.1, 0.5) flasher[1]:SetBlendMode("ADD") flasher[1]:SetAllPoints(flasher) SetAnim(flasher[1], flasher) flasher:Hide() if text then healthBar.value = healthBar:CreateFontString(nil, "OVERLAY") healthBar.value.db = "health" MOD:SetUnitFont(healthBar.value) healthBar.value:SetParent(frame.InfoPanel) local offset = reverse and 2 or -2; local direction = reverse and "LEFT" or "RIGHT"; healthBar.value:Point(direction, healthBar, direction, offset, 0) end; healthBar.animation = flasher healthBar.noupdate = false; healthBar.fillInverted = reverse; healthBar.colorTapping = true; healthBar.colorDisconnected = true healthBar.Override = Update; return healthBar end; function MOD:RefreshHealthBar(frame) if(frame.db and frame.db.portrait) then local db = frame.db.portrait local useOverlayHealth = (db.enable and db.overlay); if useOverlayHealth then frame.Health:SetStatusBarTexture(SuperVillain.Media.bar.default) frame.Health.Override = CustomUpdate; else frame.Health:SetStatusBarTexture(LSM:Fetch("statusbar", MOD.db.statusbar)) frame.Health.Override = Update; end end; end