UnitFrame.lua

UnitFrame.lua (9.0.2.37176; unchanged since 9.0.2.36665)
  1. PowerBarColor = {};
  2. PowerBarColor["MANA"] = { r = 0.00, g = 0.00, b = 1.00 };
  3. PowerBarColor["RAGE"] = { r = 1.00, g = 0.00, b = 0.00, fullPowerAnim=true };
  4. PowerBarColor["FOCUS"] = { r = 1.00, g = 0.50, b = 0.25, fullPowerAnim=true };
  5. PowerBarColor["ENERGY"] = { r = 1.00, g = 1.00, b = 0.00, fullPowerAnim=true };
  6. PowerBarColor["COMBO_POINTS"] = { r = 1.00, g = 0.96, b = 0.41 };
  7. PowerBarColor["RUNES"] = { r = 0.50, g = 0.50, b = 0.50 };
  8. PowerBarColor["RUNIC_POWER"] = { r = 0.00, g = 0.82, b = 1.00 };
  9. PowerBarColor["SOUL_SHARDS"] = { r = 0.50, g = 0.32, b = 0.55 };
  10. PowerBarColor["LUNAR_POWER"] = { r = 0.30, g = 0.52, b = 0.90, atlas="_Druid-LunarBar" };
  11. PowerBarColor["HOLY_POWER"] = { r = 0.95, g = 0.90, b = 0.60 };
  12. PowerBarColor["MAELSTROM"] = { r = 0.00, g = 0.50, b = 1.00, atlas = "_Shaman-MaelstromBar", fullPowerAnim=true };
  13. PowerBarColor["INSANITY"] = { r = 0.40, g = 0, b = 0.80, atlas = "_Priest-InsanityBar"};
  14. PowerBarColor["CHI"] = { r = 0.71, g = 1.0, b = 0.92 };
  15. PowerBarColor["ARCANE_CHARGES"] = { r = 0.1, g = 0.1, b = 0.98 };
  16. PowerBarColor["FURY"] = { r = 0.788, g = 0.259, b = 0.992, atlas = "_DemonHunter-DemonicFuryBar", fullPowerAnim=true };
  17. PowerBarColor["PAIN"] = { r = 255/255, g = 156/255, b = 0, atlas = "_DemonHunter-DemonicPainBar", fullPowerAnim=true };
  18. -- vehicle colors
  19. PowerBarColor["AMMOSLOT"] = { r = 0.80, g = 0.60, b = 0.00 };
  20. PowerBarColor["FUEL"] = { r = 0.0, g = 0.55, b = 0.5 };
  21. PowerBarColor["STAGGER"] = { {r = 0.52, g = 1.0, b = 0.52}, {r = 1.0, g = 0.98, b = 0.72}, {r = 1.0, g = 0.42, b = 0.42},};
  22. -- these are mostly needed for a fallback case (in case the code tries to index a power token that is missing from the table,
  23. -- it will try to index by power type instead)
  24. PowerBarColor[0] = PowerBarColor["MANA"];
  25. PowerBarColor[1] = PowerBarColor["RAGE"];
  26. PowerBarColor[2] = PowerBarColor["FOCUS"];
  27. PowerBarColor[3] = PowerBarColor["ENERGY"];
  28. PowerBarColor[4] = PowerBarColor["CHI"];
  29. PowerBarColor[5] = PowerBarColor["RUNES"];
  30. PowerBarColor[6] = PowerBarColor["RUNIC_POWER"];
  31. PowerBarColor[7] = PowerBarColor["SOUL_SHARDS"];
  32. PowerBarColor[8] = PowerBarColor["LUNAR_POWER"];
  33. PowerBarColor[9] = PowerBarColor["HOLY_POWER"];
  34. PowerBarColor[11] = PowerBarColor["MAELSTROM"];
  35. PowerBarColor[13] = PowerBarColor["INSANITY"];
  36. PowerBarColor[17] = PowerBarColor["FURY"];
  37. PowerBarColor[18] = PowerBarColor["PAIN"];
  38. function GetPowerBarColor(powerType)
  39. return PowerBarColor[powerType];
  40. end
  41. --[[
  42. This system uses "update" functions as OnUpdate, and OnEvent handlers.
  43. This "Initialize" function registers the events to handle.
  44. The "update" function is set as the OnEvent handler (although they do not parse the event),
  45. as well as run from the parent's update handler.
  46. TT: I had to make the spellbar system differ from the norm.
  47. I needed a seperate OnUpdate and OnEvent handlers. And needed to parse the event.
  48. ]]--
  49. function UnitFrame_Initialize (self, unit, name, portrait, healthbar, healthtext, manabar, manatext, threatIndicator, threatFeedbackUnit, threatNumericIndicator,
  50. myHealPredictionBar, otherHealPredictionBar, totalAbsorbBar, totalAbsorbBarOverlay, overAbsorbGlow, overHealAbsorbGlow, healAbsorbBar, healAbsorbBarLeftShadow,
  51. healAbsorbBarRightShadow, myManaCostPredictionBar)
  52. self.unit = unit;
  53. self.name = name;
  54. self.portrait = portrait;
  55. self.healthbar = healthbar;
  56. self.manabar = manabar;
  57. self.threatIndicator = threatIndicator;
  58. self.threatNumericIndicator = threatNumericIndicator;
  59. self.myHealPredictionBar = myHealPredictionBar;
  60. self.otherHealPredictionBar = otherHealPredictionBar
  61. self.totalAbsorbBar = totalAbsorbBar;
  62. self.totalAbsorbBarOverlay = totalAbsorbBarOverlay;
  63. self.overAbsorbGlow = overAbsorbGlow;
  64. self.overHealAbsorbGlow = overHealAbsorbGlow;
  65. self.healAbsorbBar = healAbsorbBar;
  66. self.healAbsorbBarLeftShadow = healAbsorbBarLeftShadow;
  67. self.healAbsorbBarRightShadow = healAbsorbBarRightShadow;
  68. self.myManaCostPredictionBar = myManaCostPredictionBar;
  69. if ( self.myHealPredictionBar ) then
  70. self.myHealPredictionBar:ClearAllPoints();
  71. end
  72. if ( self.otherHealPredictionBar ) then
  73. self.otherHealPredictionBar:ClearAllPoints();
  74. end
  75. if ( self.totalAbsorbBar ) then
  76. self.totalAbsorbBar:ClearAllPoints();
  77. end
  78. if ( self.myManaCostPredictionBar ) then
  79. self.myManaCostPredictionBar:ClearAllPoints();
  80. end
  81. if ( self.totalAbsorbBarOverlay ) then
  82. self.totalAbsorbBar.overlay = self.totalAbsorbBarOverlay;
  83. self.totalAbsorbBarOverlay:SetAllPoints(self.totalAbsorbBar);
  84. self.totalAbsorbBarOverlay.tileSize = 32;
  85. end
  86. if ( self.overAbsorbGlow ) then
  87. self.overAbsorbGlow:ClearAllPoints();
  88. self.overAbsorbGlow:SetPoint("TOPLEFT", self.healthbar, "TOPRIGHT", -7, 0);
  89. self.overAbsorbGlow:SetPoint("BOTTOMLEFT", self.healthbar, "BOTTOMRIGHT", -7, 0);
  90. end
  91. if ( self.healAbsorbBar ) then
  92. self.healAbsorbBar:ClearAllPoints();
  93. self.healAbsorbBar:SetTexture("Interface\\RaidFrame\\Absorb-Fill", true, true);
  94. end
  95. if ( self.overHealAbsorbGlow ) then
  96. self.overHealAbsorbGlow:ClearAllPoints();
  97. self.overHealAbsorbGlow:SetPoint("BOTTOMRIGHT", self.healthbar, "BOTTOMLEFT", 7, 0);
  98. self.overHealAbsorbGlow:SetPoint("TOPRIGHT", self.healthbar, "TOPLEFT", 7, 0);
  99. end
  100. if ( healAbsorbBarLeftShadow ) then
  101. self.healAbsorbBarLeftShadow:ClearAllPoints();
  102. end
  103. if ( healAbsorbBarRightShadow ) then
  104. self.healAbsorbBarRightShadow:ClearAllPoints();
  105. end
  106. if (self.healthbar) then
  107. self.healthbar.capNumericDisplay = true;
  108. end
  109. if (self.manabar) then
  110. self.manabar.capNumericDisplay = true;
  111. end
  112. UnitFrameHealthBar_Initialize(unit, healthbar, healthtext, true);
  113. UnitFrameManaBar_Initialize(unit, manabar, manatext, (unit == "player" or unit == "pet" or unit == "vehicle" or unit == "target" or unit == "focus"));
  114. UnitFrameThreatIndicator_Initialize(unit, self, threatFeedbackUnit);
  115. UnitFrame_Update(self);
  116. self:RegisterForClicks("LeftButtonUp", "RightButtonUp");
  117. self:RegisterEvent("UNIT_NAME_UPDATE");
  118. self:RegisterEvent("UNIT_DISPLAYPOWER");
  119. self:RegisterEvent("UNIT_PORTRAIT_UPDATE")
  120. self:RegisterEvent("PORTRAITS_UPDATED");
  121. if ( self.healAbsorbBar ) then
  122. self:RegisterUnitEvent("UNIT_HEAL_ABSORB_AMOUNT_CHANGED", unit);
  123. end
  124. if ( self.myHealPredictionBar ) then
  125. self:RegisterUnitEvent("UNIT_MAXHEALTH", unit);
  126. self:RegisterUnitEvent("UNIT_HEAL_PREDICTION", unit);
  127. end
  128. if ( self.totalAbsorbBar ) then
  129. self:RegisterUnitEvent("UNIT_ABSORB_AMOUNT_CHANGED", unit);
  130. end
  131. if ( self.myManaCostPredictionBar ) then
  132. self:RegisterUnitEvent("UNIT_SPELLCAST_START", unit);
  133. self:RegisterUnitEvent("UNIT_SPELLCAST_STOP", unit);
  134. self:RegisterUnitEvent("UNIT_SPELLCAST_FAILED", unit);
  135. self:RegisterUnitEvent("UNIT_SPELLCAST_SUCCEEDED", unit);
  136. end
  137. end
  138. function UnitFrame_SetUnit (self, unit, healthbar, manabar)
  139. -- update unit events if unit changes
  140. if ( self.unit ~= unit ) then
  141. if ( self.myHealPredictionBar ) then
  142. self:RegisterUnitEvent("UNIT_MAXHEALTH", unit);
  143. self:RegisterUnitEvent("UNIT_HEAL_PREDICTION", unit);
  144. end
  145. if ( self.totalAbsorbBar ) then
  146. self:RegisterUnitEvent("UNIT_ABSORB_AMOUNT_CHANGED", unit);
  147. end
  148. if ( not healthbar.frequentUpdates ) then
  149. healthbar:RegisterUnitEvent("UNIT_HEALTH", unit);
  150. end
  151. if ( manabar and not manabar.frequentUpdates ) then
  152. UnitFrameManaBar_RegisterDefaultEvents(manabar);
  153. end
  154. healthbar:RegisterUnitEvent("UNIT_MAXHEALTH", unit);
  155. if ( self.PlayerFrameHealthBarAnimatedLoss ) then
  156. self.PlayerFrameHealthBarAnimatedLoss:SetUnitHealthBar(unit, healthbar);
  157. end
  158. end
  159. self.unit = unit;
  160. UnitFrameHealthBar_SetUnit(healthbar, unit)
  161. if ( manabar ) then --Party Pet frames don't have a mana bar.
  162. manabar.unit = unit;
  163. end
  164. self:SetAttribute("unit", unit);
  165. securecall("UnitFrame_Update", self);
  166. end
  167. function UnitFrame_Update (self, isParty)
  168. if (self.name) then
  169. local name;
  170. if ( self.overrideName ) then
  171. name = self.overrideName;
  172. else
  173. name = self.unit;
  174. end
  175. if (isParty) then
  176. self.name:SetText(GetUnitName(name, true));
  177. else
  178. self.name:SetText(GetUnitName(name));
  179. end
  180. end
  181. UnitFramePortrait_Update(self);
  182. UnitFrameHealthBar_Update(self.healthbar, self.unit);
  183. UnitFrameManaBar_Update(self.manabar, self.unit);
  184. UnitFrame_UpdateThreatIndicator(self.threatIndicator, self.threatNumericIndicator);
  185. UnitFrameHealPredictionBars_UpdateMax(self);
  186. UnitFrameHealPredictionBars_Update(self);
  187. UnitFrameManaCostPredictionBars_Update(self);
  188. end
  189. function UnitFramePortrait_Update (self)
  190. if ( self.portrait ) then
  191. SetPortraitTexture(self.portrait, self.unit);
  192. end
  193. end
  194. function UnitFrame_OnEvent(self, event, ...)
  195. local eventUnit = ...
  196. local unit = self.unit;
  197. if ( eventUnit == unit ) then
  198. if ( event == "UNIT_NAME_UPDATE" ) then
  199. self.name:SetText(GetUnitName(unit));
  200. elseif ( event == "UNIT_PORTRAIT_UPDATE" ) then
  201. UnitFramePortrait_Update(self);
  202. elseif ( event == "UNIT_DISPLAYPOWER" ) then
  203. if ( self.manabar ) then
  204. UnitFrameManaBar_UpdateType(self.manabar);
  205. end
  206. elseif ( event == "UNIT_MAXHEALTH" ) then
  207. UnitFrameHealPredictionBars_UpdateMax(self);
  208. UnitFrameHealPredictionBars_Update(self);
  209. elseif ( event == "UNIT_HEAL_PREDICTION" ) then
  210. UnitFrameHealPredictionBars_Update(self);
  211. elseif ( event == "UNIT_ABSORB_AMOUNT_CHANGED" ) then
  212. UnitFrameHealPredictionBars_Update(self);
  213. elseif ( event == "UNIT_HEAL_ABSORB_AMOUNT_CHANGED" ) then
  214. UnitFrameHealPredictionBars_Update(self);
  215. elseif ( event == "UNIT_SPELLCAST_START" or event == "UNIT_SPELLCAST_STOP" or event == "UNIT_SPELLCAST_FAILED" or event == "UNIT_SPELLCAST_SUCCEEDED" ) then
  216. local name, text, texture, startTime, endTime, isTradeSkill, castID, notInterruptible, spellID = UnitCastingInfo(unit);
  217. UnitFrameManaCostPredictionBars_Update(self, event == "UNIT_SPELLCAST_START", startTime, endTime, spellID);
  218. end
  219. elseif ( event == "PORTRAITS_UPDATED" ) then
  220. UnitFramePortrait_Update(self);
  221. end
  222. end
  223. function UnitFrameHealPredictionBars_UpdateMax(self)
  224. if ( not self.myHealPredictionBar ) then
  225. return;
  226. end
  227. UnitFrameHealPredictionBars_Update(self);
  228. end
  229. function UnitFrameHealPredictionBars_UpdateSize(self)
  230. if ( not self.myHealPredictionBar or not self.otherHealPredictionBar ) then
  231. return;
  232. end
  233. UnitFrameHealPredictionBars_Update(self);
  234. end
  235. --WARNING: This function is very similar to the function CompactUnitFrame_UpdateHealPrediction in CompactUnitFrame.lua.
  236. --If you are making changes here, it is possible you may want to make changes there as well.
  237. local MAX_INCOMING_HEAL_OVERFLOW = 1.0;
  238. function UnitFrameHealPredictionBars_Update(frame)
  239. if ( not frame.myHealPredictionBar ) then
  240. return;
  241. end
  242. local _, maxHealth = frame.healthbar:GetMinMaxValues();
  243. local health = frame.healthbar:GetValue();
  244. if ( maxHealth <= 0 ) then
  245. return;
  246. end
  247. local myIncomingHeal = UnitGetIncomingHeals(frame.unit, "player") or 0;
  248. local allIncomingHeal = UnitGetIncomingHeals(frame.unit) or 0;
  249. local totalAbsorb = UnitGetTotalAbsorbs(frame.unit) or 0;
  250. local myCurrentHealAbsorb = 0;
  251. if ( frame.healAbsorbBar ) then
  252. myCurrentHealAbsorb = UnitGetTotalHealAbsorbs(frame.unit) or 0;
  253. --We don't fill outside the health bar with healAbsorbs. Instead, an overHealAbsorbGlow is shown.
  254. if ( health < myCurrentHealAbsorb ) then
  255. frame.overHealAbsorbGlow:Show();
  256. myCurrentHealAbsorb = health;
  257. else
  258. frame.overHealAbsorbGlow:Hide();
  259. end
  260. end
  261. --See how far we're going over the health bar and make sure we don't go too far out of the frame.
  262. if ( health - myCurrentHealAbsorb + allIncomingHeal > maxHealth * MAX_INCOMING_HEAL_OVERFLOW ) then
  263. allIncomingHeal = maxHealth * MAX_INCOMING_HEAL_OVERFLOW - health + myCurrentHealAbsorb;
  264. end
  265. local otherIncomingHeal = 0;
  266. --Split up incoming heals.
  267. if ( allIncomingHeal >= myIncomingHeal ) then
  268. otherIncomingHeal = allIncomingHeal - myIncomingHeal;
  269. else
  270. myIncomingHeal = allIncomingHeal;
  271. end
  272. --We don't fill outside the the health bar with absorbs. Instead, an overAbsorbGlow is shown.
  273. local overAbsorb = false;
  274. if ( health - myCurrentHealAbsorb + allIncomingHeal + totalAbsorb >= maxHealth or health + totalAbsorb >= maxHealth ) then
  275. if ( totalAbsorb > 0 ) then
  276. overAbsorb = true;
  277. end
  278. if ( allIncomingHeal > myCurrentHealAbsorb ) then
  279. totalAbsorb = max(0,maxHealth - (health - myCurrentHealAbsorb + allIncomingHeal));
  280. else
  281. totalAbsorb = max(0,maxHealth - health);
  282. end
  283. end
  284. if ( overAbsorb ) then
  285. frame.overAbsorbGlow:Show();
  286. else
  287. frame.overAbsorbGlow:Hide();
  288. end
  289. local healthTexture = frame.healthbar:GetStatusBarTexture();
  290. local myCurrentHealAbsorbPercent = 0;
  291. local healAbsorbTexture = nil;
  292. if ( frame.healAbsorbBar ) then
  293. myCurrentHealAbsorbPercent = myCurrentHealAbsorb / maxHealth;
  294. --If allIncomingHeal is greater than myCurrentHealAbsorb, then the current
  295. --heal absorb will be completely overlayed by the incoming heals so we don't show it.
  296. if ( myCurrentHealAbsorb > allIncomingHeal ) then
  297. local shownHealAbsorb = myCurrentHealAbsorb - allIncomingHeal;
  298. local shownHealAbsorbPercent = shownHealAbsorb / maxHealth;
  299. healAbsorbTexture = UnitFrameUtil_UpdateFillBar(frame, healthTexture, frame.healAbsorbBar, shownHealAbsorb, -shownHealAbsorbPercent);
  300. --If there are incoming heals the left shadow would be overlayed by the incoming heals
  301. --so it isn't shown.
  302. if ( allIncomingHeal > 0 ) then
  303. frame.healAbsorbBarLeftShadow:Hide();
  304. else
  305. frame.healAbsorbBarLeftShadow:SetPoint("TOPLEFT", healAbsorbTexture, "TOPLEFT", 0, 0);
  306. frame.healAbsorbBarLeftShadow:SetPoint("BOTTOMLEFT", healAbsorbTexture, "BOTTOMLEFT", 0, 0);
  307. frame.healAbsorbBarLeftShadow:Show();
  308. end
  309. -- The right shadow is only shown if there are absorbs on the health bar.
  310. if ( totalAbsorb > 0 ) then
  311. frame.healAbsorbBarRightShadow:SetPoint("TOPLEFT", healAbsorbTexture, "TOPRIGHT", -8, 0);
  312. frame.healAbsorbBarRightShadow:SetPoint("BOTTOMLEFT", healAbsorbTexture, "BOTTOMRIGHT", -8, 0);
  313. frame.healAbsorbBarRightShadow:Show();
  314. else
  315. frame.healAbsorbBarRightShadow:Hide();
  316. end
  317. else
  318. frame.healAbsorbBar:Hide();
  319. frame.healAbsorbBarLeftShadow:Hide();
  320. frame.healAbsorbBarRightShadow:Hide();
  321. end
  322. end
  323. --Show myIncomingHeal on the health bar.
  324. local incomingHealTexture = UnitFrameUtil_UpdateFillBar(frame, healthTexture, frame.myHealPredictionBar, myIncomingHeal, -myCurrentHealAbsorbPercent);
  325. --Append otherIncomingHeal on the health bar
  326. if (myIncomingHeal > 0) then
  327. incomingHealTexture = UnitFrameUtil_UpdateFillBar(frame, incomingHealTexture, frame.otherHealPredictionBar, otherIncomingHeal);
  328. else
  329. incomingHealTexture = UnitFrameUtil_UpdateFillBar(frame, healthTexture, frame.otherHealPredictionBar, otherIncomingHeal, -myCurrentHealAbsorbPercent);
  330. end
  331. --Append absorbs to the correct section of the health bar.
  332. local appendTexture = nil;
  333. if ( healAbsorbTexture ) then
  334. --If there is a healAbsorb part shown, append the absorb to the end of that.
  335. appendTexture = healAbsorbTexture;
  336. else
  337. --Otherwise, append the absorb to the end of the the incomingHeals part;
  338. appendTexture = incomingHealTexture;
  339. end
  340. UnitFrameUtil_UpdateFillBar(frame, appendTexture, frame.totalAbsorbBar, totalAbsorb)
  341. end
  342. function UnitFrameManaCostPredictionBars_Update(frame, isStarting, startTime, endTime, spellID)
  343. if (not frame.manabar or not frame.myManaCostPredictionBar) then
  344. return;
  345. end
  346. local cost = 0;
  347. if (not isStarting or startTime == endTime) then
  348. local currentSpellID = select(9, UnitCastingInfo(frame.unit));
  349. if(currentSpellID and frame.predictedPowerCost) then --if we're currently casting something with a power cost, then whatever cast
  350. cost = frame.predictedPowerCost; --just finished was allowed while casting, don't reset the original cast
  351. else
  352. frame.predictedPowerCost = nil;
  353. end
  354. else
  355. local costTable = GetSpellPowerCost(spellID);
  356. for _, costInfo in pairs(costTable) do
  357. if (costInfo.type == frame.manabar.powerType) then
  358. cost = costInfo.cost;
  359. break;
  360. end
  361. end
  362. frame.predictedPowerCost = cost;
  363. end
  364. local manaBarTexture = frame.manabar:GetStatusBarTexture();
  365. UnitFrameManaBar_Update(frame.manabar, frame.unit);
  366. UnitFrameUtil_UpdateManaFillBar(frame, manaBarTexture, frame.myManaCostPredictionBar, cost);
  367. end
  368. --WARNING: This function is very similar to the function CompactUnitFrameUtil_UpdateFillBar in CompactUnitFrame.lua.
  369. --If you are making changes here, it is possible you may want to make changes there as well.
  370. function UnitFrameUtil_UpdateFillBarBase(frame, realbar, previousTexture, bar, amount, barOffsetXPercent)
  371. if ( amount == 0 ) then
  372. bar:Hide();
  373. if ( bar.overlay ) then
  374. bar.overlay:Hide();
  375. end
  376. return previousTexture;
  377. end
  378. local barOffsetX = 0;
  379. if ( barOffsetXPercent ) then
  380. local realbarSizeX = realbar:GetWidth();
  381. barOffsetX = realbarSizeX * barOffsetXPercent;
  382. end
  383. bar:SetPoint("TOPLEFT", previousTexture, "TOPRIGHT", barOffsetX, 0);
  384. bar:SetPoint("BOTTOMLEFT", previousTexture, "BOTTOMRIGHT", barOffsetX, 0);
  385. local totalWidth, totalHeight = realbar:GetSize();
  386. local _, totalMax = realbar:GetMinMaxValues();
  387. local barSize = (amount / totalMax) * totalWidth;
  388. bar:SetWidth(barSize);
  389. bar:Show();
  390. if ( bar.overlay ) then
  391. bar.overlay:SetTexCoord(0, barSize / bar.overlay.tileSize, 0, totalHeight / bar.overlay.tileSize);
  392. bar.overlay:Show();
  393. end
  394. return bar;
  395. end
  396. function UnitFrameUtil_UpdateFillBar(frame, previousTexture, bar, amount, barOffsetXPercent)
  397. return UnitFrameUtil_UpdateFillBarBase(frame, frame.healthbar, previousTexture, bar, amount, barOffsetXPercent);
  398. end
  399. function UnitFrameUtil_UpdateManaFillBar(frame, previousTexture, bar, amount, barOffsetXPercent)
  400. return UnitFrameUtil_UpdateFillBarBase(frame, frame.manabar, previousTexture, bar, amount, barOffsetXPercent);
  401. end
  402. function UnitFrame_OnEnter (self)
  403. UnitFrame_UpdateTooltip(self);
  404. end
  405. function UnitFrame_OnLeave (self)
  406. self.UpdateTooltip = nil;
  407. GameTooltip:FadeOut();
  408. end
  409. function UnitFrame_UpdateTooltip (self)
  410. GameTooltip_SetDefaultAnchor(GameTooltip, self);
  411. if ( GameTooltip:SetUnit(self.unit, self.hideStatusOnTooltip) ) then
  412. self.UpdateTooltip = UnitFrame_UpdateTooltip;
  413. else
  414. self.UpdateTooltip = nil;
  415. end
  416. local r, g, b = GameTooltip_UnitColor(self.unit);
  417. GameTooltipTextLeft1:SetTextColor(r, g, b);
  418. end
  419. function UnitFrameManaBar_UpdateType (manaBar)
  420. if ( not manaBar ) then
  421. return;
  422. end
  423. local unitFrame = manaBar:GetParent();
  424. local powerType, powerToken, altR, altG, altB = UnitPowerType(manaBar.unit);
  425. local prefix = _G[powerToken];
  426. local info = PowerBarColor[powerToken];
  427. if ( info ) then
  428. if ( not manaBar.lockColor ) then
  429. local playerDeadOrGhost = (manaBar.unit == "player" and (UnitIsDead("player") or UnitIsGhost("player")));
  430. if ( info.atlas ) then
  431. manaBar:SetStatusBarAtlas(info.atlas);
  432. manaBar:SetStatusBarColor(1, 1, 1);
  433. manaBar:GetStatusBarTexture():SetDesaturated(playerDeadOrGhost);
  434. manaBar:GetStatusBarTexture():SetAlpha(playerDeadOrGhost and 0.5 or 1);
  435. else
  436. manaBar:SetStatusBarTexture("Interface\\TargetingFrame\\UI-StatusBar");
  437. if ( playerDeadOrGhost ) then
  438. manaBar:SetStatusBarColor(0.6, 0.6, 0.6, 0.5);
  439. else
  440. manaBar:SetStatusBarColor(info.r, info.g, info.b);
  441. end
  442. end
  443. if ( manaBar.FeedbackFrame ) then
  444. manaBar.FeedbackFrame:Initialize(info, manaBar.unit, powerType);
  445. end
  446. if ( manaBar.FullPowerFrame ) then
  447. manaBar.FullPowerFrame:Initialize(info.fullPowerAnim);
  448. end
  449. end
  450. else
  451. if ( not altR) then
  452. -- couldn't find a power token entry...default to indexing by power type or just mana if we don't have that either
  453. info = PowerBarColor[powerType] or PowerBarColor["MANA"];
  454. else
  455. if ( not manaBar.lockColor ) then
  456. manaBar:SetStatusBarColor(altR, altG, altB);
  457. end
  458. end
  459. end
  460. if ( manaBar.powerType ~= powerType or manaBar.powerType ~= powerType ) then
  461. manaBar.powerType = powerType;
  462. manaBar.powerToken = powerToken;
  463. if ( manaBar.FullPowerFrame ) then
  464. manaBar.FullPowerFrame:RemoveAnims();
  465. end
  466. if manaBar.FeedbackFrame then
  467. manaBar.FeedbackFrame:StopFeedbackAnim();
  468. end
  469. manaBar.currValue = UnitPower("player", powerType);
  470. if unitFrame.myManaCostPredictionBar then
  471. unitFrame.myManaCostPredictionBar:Hide();
  472. end
  473. unitFrame.predictedPowerCost = 0;
  474. end
  475. -- Update the manabar text
  476. if ( not unitFrame.noTextPrefix ) then
  477. SetTextStatusBarTextPrefix(manaBar, prefix);
  478. end
  479. TextStatusBar_UpdateTextString(manaBar);
  480. -- Setup newbie tooltip
  481. if ( manaBar.unit ~= "pet") then
  482. if ( unitFrame:GetName() == "PlayerFrame" ) then
  483. manaBar.tooltipTitle = prefix;
  484. manaBar.tooltipText = _G["NEWBIE_TOOLTIP_MANABAR_"..powerType];
  485. else
  486. manaBar.tooltipTitle = nil;
  487. manaBar.tooltipText = nil;
  488. end
  489. end
  490. end
  491. function UnitFrameHealthBar_Initialize (unit, statusbar, statustext, frequentUpdates)
  492. if ( not statusbar ) then
  493. return;
  494. end
  495. statusbar.unit = unit;
  496. SetTextStatusBarText(statusbar, statustext);
  497. statusbar.frequentUpdates = frequentUpdates;
  498. if ( frequentUpdates ) then
  499. statusbar:RegisterEvent("VARIABLES_LOADED");
  500. end
  501. UnitFrameHealthBar_RefreshUpdateEvent(statusbar);
  502. statusbar:RegisterUnitEvent("UNIT_MAXHEALTH", unit);
  503. statusbar:SetScript("OnEvent", UnitFrameHealthBar_OnEvent);
  504. -- Setup newbie tooltip
  505. if ( statusbar and (statusbar:GetParent() == PlayerFrame) ) then
  506. statusbar.tooltipTitle = HEALTH;
  507. statusbar.tooltipText = NEWBIE_TOOLTIP_HEALTHBAR;
  508. else
  509. statusbar.tooltipTitle = nil;
  510. statusbar.tooltipText = nil;
  511. end
  512. end
  513. function UnitFrameHealthBar_RefreshUpdateEvent(self)
  514. if ( GetCVarBool("predictedHealth") and self.frequentUpdates ) then
  515. self:SetScript("OnUpdate", UnitFrameHealthBar_OnUpdate);
  516. self:UnregisterEvent("UNIT_HEALTH");
  517. else
  518. self:SetScript("OnUpdate", nil);
  519. self:RegisterUnitEvent("UNIT_HEALTH", self.unit);
  520. end
  521. end
  522. function UnitFrameHealthBar_SetUnit(self, unit)
  523. self.unit = unit;
  524. UnitFrameHealthBar_RefreshUpdateEvent(self);
  525. end
  526. function UnitFrameHealthBar_OnEvent(self, event, ...)
  527. if ( event == "CVAR_UPDATE" ) then
  528. TextStatusBar_OnEvent(self, event, ...);
  529. elseif ( event == "VARIABLES_LOADED" ) then
  530. self:UnregisterEvent("VARIABLES_LOADED");
  531. UnitFrameHealthBar_RefreshUpdateEvent(self);
  532. elseif self:IsShown() then
  533. if ( not self.ignoreNoUnit or UnitGUID(self.unit) ) then
  534. UnitFrameHealthBar_Update(self, ...);
  535. end
  536. end
  537. end
  538. AnimatedHealthLossMixin = {};
  539. function AnimatedHealthLossMixin:OnLoad()
  540. self:SetStatusBarColor(1, 0, 0, 1);
  541. self:SetDuration(.25);
  542. self:SetStartDelay(.1);
  543. self:SetPauseDelay(.05);
  544. self:SetPostponeDelay(.05);
  545. end
  546. function AnimatedHealthLossMixin:SetDuration(duration)
  547. self.animationDuration = duration or 0;
  548. end
  549. function AnimatedHealthLossMixin:SetStartDelay(delay)
  550. self.animationStartDelay = delay or 0;
  551. end
  552. function AnimatedHealthLossMixin:SetPauseDelay(delay)
  553. self.animationPauseDelay = delay or 0;
  554. end
  555. function AnimatedHealthLossMixin:SetPostponeDelay(delay)
  556. self.animationPostponeDelay = delay or 0;
  557. end
  558. function AnimatedHealthLossMixin:SetUnitHealthBar(unit, healthBar)
  559. if self.unit ~= unit then
  560. healthBar.AnimatedLossBar = self;
  561. self.unit = unit;
  562. self:SetAllPoints(healthBar);
  563. self:UpdateHealthMinMax();
  564. end
  565. end
  566. function AnimatedHealthLossMixin:UpdateHealthMinMax()
  567. local maxValue = UnitHealthMax(self.unit);
  568. self:SetMinMaxValues(0, maxValue);
  569. end
  570. function AnimatedHealthLossMixin:GetHealthLossAnimationData(currentHealth, previousHealth)
  571. if self.animationStartTime then
  572. local totalElapsedTime = GetTime() - self.animationStartTime;
  573. if totalElapsedTime > 0 then
  574. local animCompletePercent = totalElapsedTime / self.animationDuration;
  575. if animCompletePercent < 1 and previousHealth > currentHealth then
  576. local healthDelta = previousHealth - currentHealth;
  577. local animatedLossAmount = previousHealth - (animCompletePercent * healthDelta);
  578. return animatedLossAmount, animCompletePercent;
  579. end
  580. else
  581. return previousHealth, 0;
  582. end
  583. end
  584. return 0, 1; -- Animated loss amount is 0, and the animation is fully complete.
  585. end
  586. function AnimatedHealthLossMixin:CancelAnimation()
  587. self:Hide();
  588. self.animationStartTime = nil;
  589. self.animationCompletePercent = nil;
  590. end
  591. function AnimatedHealthLossMixin:BeginAnimation(value)
  592. self.animationStartValue = value;
  593. self.animationStartTime = GetTime() + self.animationStartDelay;
  594. self.animationCompletePercent = 0;
  595. self:Show();
  596. self:SetValue(self.animationStartValue);
  597. end
  598. function AnimatedHealthLossMixin:PostponeStartTime()
  599. self.animationStartTime = self.animationStartTime + self.animationPostponeDelay;
  600. end
  601. function AnimatedHealthLossMixin:UpdateHealth(currentHealth, previousHealth)
  602. local delta = currentHealth - previousHealth;
  603. local hasLoss = delta < 0;
  604. local hasBegun = self.animationStartTime ~= nil;
  605. local isAnimating = hasBegun and self.animationCompletePercent > 0;
  606. if hasLoss and not hasBegun then
  607. self:BeginAnimation(previousHealth);
  608. elseif hasLoss and hasBegun and not isAnimating then
  609. self:PostponeStartTime();
  610. elseif hasLoss and isAnimating then
  611. -- Reset the starting value of the health to what the animated loss bar was when the new incoming damage happened
  612. -- and pause briefly when new damage occurs.
  613. self.animationStartValue = self:GetHealthLossAnimationData(previousHealth, self.animationStartValue);
  614. self.animationStartTime = GetTime() + self.animationPauseDelay;
  615. elseif not hasLoss and hasBegun and currentHealth >= self.animationStartValue then
  616. self:CancelAnimation();
  617. end
  618. end
  619. function AnimatedHealthLossMixin:UpdateLossAnimation(currentHealth)
  620. local totalAbsorb = UnitGetTotalAbsorbs(self.unit) or 0;
  621. if totalAbsorb > 0 then
  622. self:CancelAnimation();
  623. end
  624. if self.animationStartTime then
  625. local animationValue, animationCompletePercent = self:GetHealthLossAnimationData(currentHealth, self.animationStartValue);
  626. self.animationCompletePercent = animationCompletePercent;
  627. if animationCompletePercent >= 1 then
  628. self:CancelAnimation();
  629. else
  630. self:SetValue(animationValue);
  631. end
  632. end
  633. end
  634. function UnitFrameHealthBar_OnUpdate(self)
  635. if ( not self.disconnected and not self.lockValues) then
  636. local currValue = UnitHealth(self.unit);
  637. local animatedLossBar = self.AnimatedLossBar;
  638. if ( currValue ~= self.currValue ) then
  639. if ( not self.ignoreNoUnit or UnitGUID(self.unit) ) then
  640. if animatedLossBar then
  641. animatedLossBar:UpdateHealth(currValue, self.currValue);
  642. end
  643. self:SetValue(currValue);
  644. self.currValue = currValue;
  645. TextStatusBar_UpdateTextString(self);
  646. UnitFrameHealPredictionBars_Update(self:GetParent());
  647. end
  648. end
  649. if animatedLossBar then
  650. animatedLossBar:UpdateLossAnimation(currValue);
  651. end
  652. end
  653. end
  654. function UnitFrameHealthBar_Update(statusbar, unit)
  655. if ( not statusbar or statusbar.lockValues ) then
  656. return;
  657. end
  658. if ( unit == statusbar.unit ) then
  659. local maxValue = UnitHealthMax(unit);
  660. -- Safety check to make sure we never get an empty bar.
  661. statusbar.forceHideText = false;
  662. if ( maxValue == 0 ) then
  663. maxValue = 1;
  664. statusbar.forceHideText = true;
  665. end
  666. statusbar:SetMinMaxValues(0, maxValue);
  667. if statusbar.AnimatedLossBar then
  668. statusbar.AnimatedLossBar:UpdateHealthMinMax();
  669. end
  670. statusbar.disconnected = not UnitIsConnected(unit);
  671. if ( statusbar.disconnected ) then
  672. if ( not statusbar.lockColor ) then
  673. statusbar:SetStatusBarColor(0.5, 0.5, 0.5);
  674. end
  675. statusbar:SetValue(maxValue);
  676. statusbar.currValue = maxValue;
  677. else
  678. local currValue = UnitHealth(unit);
  679. if ( not statusbar.lockColor ) then
  680. statusbar:SetStatusBarColor(0.0, 1.0, 0.0);
  681. end
  682. statusbar:SetValue(currValue);
  683. statusbar.currValue = currValue;
  684. end
  685. end
  686. TextStatusBar_UpdateTextString(statusbar);
  687. UnitFrameHealPredictionBars_Update(statusbar:GetParent());
  688. end
  689. function UnitFrameHealthBar_OnValueChanged(self, value)
  690. TextStatusBar_OnValueChanged(self, value);
  691. HealthBar_OnValueChanged(self, value);
  692. end
  693. function UnitFrameManaBar_UnregisterDefaultEvents(self)
  694. self:UnregisterEvent("UNIT_POWER_UPDATE");
  695. end
  696. function UnitFrameManaBar_RegisterDefaultEvents(self)
  697. self:RegisterUnitEvent("UNIT_POWER_UPDATE", self.unit);
  698. end
  699. function UnitFrameManaBar_Initialize (unit, statusbar, statustext, frequentUpdates)
  700. if ( not statusbar ) then
  701. return;
  702. end
  703. statusbar.unit = unit;
  704. statusbar.texture = statusbar:GetStatusBarTexture();
  705. SetTextStatusBarText(statusbar, statustext);
  706. statusbar.frequentUpdates = frequentUpdates;
  707. if ( frequentUpdates ) then
  708. statusbar:RegisterEvent("VARIABLES_LOADED");
  709. end
  710. if ( frequentUpdates ) then
  711. statusbar:SetScript("OnUpdate", UnitFrameManaBar_OnUpdate);
  712. else
  713. UnitFrameManaBar_RegisterDefaultEvents(statusbar);
  714. end
  715. statusbar:RegisterEvent("UNIT_DISPLAYPOWER");
  716. statusbar:RegisterUnitEvent("UNIT_MAXPOWER", unit);
  717. if ( statusbar.unit == "player" ) then
  718. statusbar:RegisterEvent("PLAYER_DEAD");
  719. statusbar:RegisterEvent("PLAYER_ALIVE");
  720. statusbar:RegisterEvent("PLAYER_UNGHOST");
  721. end
  722. statusbar:SetScript("OnEvent", UnitFrameManaBar_OnEvent);
  723. end
  724. function UnitFrameManaBar_OnEvent(self, event, ...)
  725. if ( event == "CVAR_UPDATE" ) then
  726. TextStatusBar_OnEvent(self, event, ...);
  727. elseif ( event == "VARIABLES_LOADED" ) then
  728. self:UnregisterEvent("VARIABLES_LOADED");
  729. if ( self.frequentUpdates ) then
  730. self:SetScript("OnUpdate", UnitFrameManaBar_OnUpdate);
  731. UnitFrameManaBar_UnregisterDefaultEvents(self);
  732. else
  733. UnitFrameManaBar_RegisterDefaultEvents(self);
  734. self:SetScript("OnUpdate", nil);
  735. end
  736. elseif ( event == "PLAYER_ALIVE" or event == "PLAYER_DEAD" or event == "PLAYER_UNGHOST" ) then
  737. UnitFrameManaBar_UpdateType(self);
  738. else
  739. if ( not self.ignoreNoUnit or UnitGUID(self.unit) ) then
  740. UnitFrameManaBar_Update(self, ...);
  741. end
  742. end
  743. end
  744. function UnitFrameManaBar_OnUpdate(self)
  745. if ( not self.disconnected and not self.lockValues ) then
  746. local predictedCost = self:GetParent().predictedPowerCost;
  747. local currValue = UnitPower(self.unit, self.powerType);
  748. if (predictedCost) then
  749. currValue = currValue - predictedCost;
  750. end
  751. if ( currValue ~= self.currValue or self.forceUpdate ) then
  752. self.forceUpdate = nil;
  753. if ( not self.ignoreNoUnit or UnitGUID(self.unit) ) then
  754. if ( self.FeedbackFrame ) then
  755. -- Only show anim if change is more than 10%
  756. local oldValue = self.currValue or 0;
  757. if ( self.FeedbackFrame.maxValue ~= 0 and math.abs(currValue - oldValue) / self.FeedbackFrame.maxValue > 0.1 ) then
  758. self.FeedbackFrame:StartFeedbackAnim(oldValue, currValue);
  759. end
  760. end
  761. if ( self.FullPowerFrame and self.FullPowerFrame.active ) then
  762. self.FullPowerFrame:StartAnimIfFull(self.currValue or 0, currValue);
  763. end
  764. self:SetValue(currValue);
  765. self.currValue = currValue;
  766. TextStatusBar_UpdateTextString(self);
  767. end
  768. end
  769. end
  770. end
  771. function UnitFrameManaBar_Update(statusbar, unit)
  772. if ( not statusbar or statusbar.lockValues ) then
  773. return;
  774. end
  775. if ( unit == statusbar.unit ) then
  776. -- be sure to update the power type before grabbing the max power!
  777. UnitFrameManaBar_UpdateType(statusbar);
  778. local maxValue = UnitPowerMax(unit, statusbar.powerType);
  779. statusbar:SetMinMaxValues(0, maxValue);
  780. statusbar.disconnected = not UnitIsConnected(unit);
  781. if ( statusbar.disconnected ) then
  782. statusbar:SetValue(maxValue);
  783. statusbar.currValue = maxValue;
  784. if ( not statusbar.lockColor ) then
  785. statusbar:SetStatusBarColor(0.5, 0.5, 0.5);
  786. end
  787. else
  788. local predictedCost = statusbar:GetParent().predictedPowerCost;
  789. local currValue = UnitPower(unit, statusbar.powerType);
  790. if (predictedCost) then
  791. currValue = currValue - predictedCost;
  792. end
  793. if ( statusbar.FullPowerFrame ) then
  794. statusbar.FullPowerFrame:SetMaxValue(maxValue);
  795. end
  796. statusbar:SetValue(currValue);
  797. statusbar.forceUpdate = true;
  798. end
  799. end
  800. TextStatusBar_UpdateTextString(statusbar);
  801. end
  802. function UnitFrameThreatIndicator_Initialize(unit, unitFrame, feedbackUnit)
  803. local indicator = unitFrame.threatIndicator;
  804. if ( not indicator ) then
  805. return;
  806. end
  807. indicator.unit = unit;
  808. indicator.feedbackUnit = feedbackUnit or unit;
  809. unitFrame:RegisterEvent("UNIT_THREAT_SITUATION_UPDATE");
  810. if ( unitFrame.OnEvent == nil ) then
  811. unitFrame.OnEvent = unitFrame:GetScript("OnEvent") or false;
  812. end
  813. unitFrame:SetScript("OnEvent", UnitFrameThreatIndicator_OnEvent);
  814. end
  815. function UnitFrameThreatIndicator_OnEvent(self, event, ...)
  816. if ( self.OnEvent ) then
  817. self.OnEvent(self, event, ...);
  818. end
  819. if ( event == "UNIT_THREAT_SITUATION_UPDATE" ) then
  820. UnitFrame_UpdateThreatIndicator(self.threatIndicator, self.threatNumericIndicator,...);
  821. end
  822. end
  823. function UnitFrame_UpdateThreatIndicator(indicator, numericIndicator, unit)
  824. if ( not indicator ) then
  825. return;
  826. end
  827. if ( not unit or unit == indicator.feedbackUnit ) then
  828. local status;
  829. if ( indicator.feedbackUnit ~= indicator.unit ) then
  830. status = UnitThreatSituation(indicator.feedbackUnit, indicator.unit);
  831. else
  832. status = UnitThreatSituation(indicator.feedbackUnit);
  833. end
  834. if ( IsThreatWarningEnabled() ) then
  835. if (status and status > 0) then
  836. indicator:SetVertexColor(GetThreatStatusColor(status));
  837. indicator:Show();
  838. else
  839. indicator:Hide();
  840. end
  841. if ( numericIndicator ) then
  842. if ( ShowNumericThreat() and not (UnitClassification(indicator.unit) == "minus") ) then
  843. local isTanking, status, percentage, rawPercentage = UnitDetailedThreatSituation(indicator.feedbackUnit, indicator.unit);
  844. local display = rawPercentage;
  845. if ( isTanking ) then
  846. display = UnitThreatPercentageOfLead(indicator.feedbackUnit, indicator.unit);
  847. end
  848. if ( display and display ~= 0 ) then
  849. numericIndicator.text:SetText(format("%1.0f", display).."%");
  850. numericIndicator.bg:SetVertexColor(GetThreatStatusColor(status));
  851. numericIndicator:Show();
  852. else
  853. numericIndicator:Hide();
  854. end
  855. else
  856. numericIndicator:Hide();
  857. end
  858. end
  859. else
  860. indicator:Hide();
  861. if ( numericIndicator ) then
  862. numericIndicator:Hide();
  863. end
  864. end
  865. end
  866. end
  867. function GetUnitName(unit, showServerName)
  868. local name, server = UnitName(unit);
  869. local relationship = UnitRealmRelationship(unit);
  870. if ( server and server ~= "" ) then
  871. if ( showServerName ) then
  872. return name.."-"..server;
  873. else
  874. if (relationship == LE_REALM_RELATION_VIRTUAL) then
  875. return name;
  876. else
  877. return name..FOREIGN_SERVER_LABEL;
  878. end
  879. end
  880. else
  881. return name;
  882. end
  883. end
  884. function ShowNumericThreat()
  885. if ( GetCVar("threatShowNumeric") == "1" ) then
  886. return true;
  887. else
  888. return false;
  889. end
  890. end