WoWInterface

WoWInterface (https://www.wowinterface.com/forums/index.php)
-   WoD Beta archived threads (https://www.wowinterface.com/forums/forumdisplay.php?f=151)
-   -   Division by zero for XP (https://www.wowinterface.com/forums/showthread.php?t=49603)

liquidbase 08-08-14 05:36 PM

Division by zero for XP
 
Hi @all

I use for my XP display the following lines:

Lua Code:
  1. local function GetPlayerXP()
  2.     return UnitXP("player"), UnitXPMax("player")
  3. end

and

Lua Code:
  1. local XP, maxXP = GetPlayerXP()
  2. local restXP = GetXPExhaustion()
  3. local percXP = math.floor((XP / maxXP) * 100)

The last line gives rise to the error mentioned in the thread title. The funny thing here is that I use the same script on the live server and it works there. Also on the Beta server, the correct values ​​are calculated and shown what you see on the screenshot below.

The error also occurs only at login and at each subsequent reload it exists not even. My question now is ... Do I have a mistake, I do not see the forest for the trees or Blizzard has an error return values​​?

Thanks in advance for all input.

greetz
liquid

Torhal 08-08-14 05:54 PM

They've done this for the past few betas - I believe it's so they can optimize the default UI; cut out any instances of division-by-zero that are otherwise handled (likely less efficiently) by the live version's Lua parser. Division by zero is, after all, something most programmers code against, not for.

liquidbase 08-08-14 06:08 PM

So then it would simply wait and see what is no satisfactory answer :(

Torhal 08-08-14 06:56 PM

Lua Code:
  1. local percXP = (XP == 0) and 0 or math.floor((XP / maxXP) * 100)

liquidbase 08-08-14 07:22 PM

Thanks Torhal to solve the problem with this idea I did not come. I should just take a break :o

SDPhantom 08-08-14 07:26 PM

Shouldn't that be (maxXP == 0)?

liquidbase 08-08-14 07:32 PM

Could be netter. I will test it :)
Thanks for all help!

SDPhantom 08-08-14 07:59 PM

Quote:

Originally Posted by Torhal (Post 295055)
They've done this for the past few betas - I believe it's so they can optimize the default UI; cut out any instances of division-by-zero that are otherwise handled (likely less efficiently) by the live version's Lua parser. Division by zero is, after all, something most programmers code against, not for.

Lua is one of the few languages that makes use of the full IEEE 754 specification for floating point numbers by allowing the casting of divide-by-zero into signed infinity. Whether this is natively done by the computer's floating point processor or trapped and substituted for by the Lua interpreter, it would be much faster since the execution lies in C code rather than forcing the check through the interpreter itself.


Their decision to force Lua to throw division-by-zero errors was to make it act more like C.
Quote:

Originally Posted by Bashiok
This is an intended change to keep the lua engine in line with changes to our game engine.


Seerah 08-08-14 08:23 PM

I'm curious why you have the extra function and function call and aren't just doing this?

Lua Code:
  1. local XP, maxMP = UnitXP("player"), UnitXPMax("player")

Torhal 08-08-14 10:49 PM

Quote:

Originally Posted by SDPhantom (Post 295060)
Shouldn't that be (maxXP == 0)?

I wouldn't see why - no matter your level, the maximum experience for that level would certainly be above 0. However, at level 1, with no experience gained...

SDPhantom 08-08-14 11:08 PM

It happened, otherwise the error would've never been thrown. The code as-is can already handle if XP is zero, but not maxXP.

Torhal 08-09-14 12:57 AM

Quote:

Originally Posted by SDPhantom (Post 295081)
It happened, otherwise the error would've never been thrown. The code as-is can already handle if XP is zero, but not maxXP.

Meh. This is what I get for skimming. Whatever - I set him on the right path, at least. I hope. Damn!

liquidbase 08-09-14 02:26 PM

@Seerah
You're right. The function is a relict from the old script within the UI I had only copied.

@Torhal
Thanks to you it works fine :)

@SDPhantom
with (maxXP == 0) the script throw a error if I want to display the value in a tooltip because of the nil-value.

Phanx 08-09-14 09:36 PM

Quote:

Originally Posted by liquidbase (Post 295104)
with (maxXP == 0) the script throw a error if I want to display the value in a tooltip because of the nil-value.

So wrap the whole thing in a check to make sure the maxXP isn't zero, and skip doing anything with XP in that case, since there's no valid information to show.

If you need help with specific changes, you'll have to show your code.

SDPhantom 08-10-14 01:06 PM

Quote:

Originally Posted by liquidbase (Post 295104)
with (maxXP == 0) the script throw a error if I want to display the value in a tooltip because of the nil-value.

If you're combining both mine and Torhal's conditions, there may be unexpected results depending on how you write it. It will need to look like this.
Code:

local percXP = (maxXP == 0) and 0 or math.floor((XP / maxXP) * 100)
Otherwise, I don't see how it's possible that a nil can pass through without throwing another error at this line.



If you post your entire code, we'll be able to help better and may catch problems that you might not see.

liquidbase 08-10-14 06:40 PM

Sorry for the late response.
The error occurs on line 89 if the character has no rested experience. Without (maxXP == 0) the script works as should. And the problem is not "nil" (my mistake in the interpretation) but it is a boolean instead of strings returned. With the expression the script throws the following error:

Lua Code:
  1. DuffedUI-8.0015\modules\misc\experience.lua:89: bad argument #4 to "format" (string expected, got boolean)
  2. <in C code>
  3. DuffedUI-8.0015\modules\misc\experience.lua:89: in function <DuffedUI\modules\misc\experience.lua:67>
  4.  
  5. Locals:
  6. XP = 0
  7. maxXP = 0
  8. restXP = nil
  9. percXP = true
  10. (*temporary) = <function> defined =[C]:-1
  11. (*temporary) = mouseFrame_Text {
  12.  0 = <userdata>
  13. }
  14. IsMaxLevel = <function> defined @Interface\AddOns\DuffedUI\modules\misc\experience.lua:20
  15. xpBar = Experience_xpBar {
  16.  0 = <userdata>
  17.  lockShow = 0
  18. }
  19. restedxpBar = Experience_restedxpBar {
  20.  0 = <userdata>
  21.  lockShow = 0
  22. }
  23. repBar = Experience_repBar {
  24.  0 = <userdata>
  25.  lockShow = 0
  26. }
  27. barHeight = 10
  28. backdrop = Experience_Backdrop {
  29.  0 = <userdata>
  30.  backdrop = <unnamed> {
  31.  }
  32. }
  33. Text = mouseFrame_Text {
  34.  0 = <userdata>
  35. }

Thanks for all help, you guys are great :)

Complete Script:
Lua Code:
  1. local D, C, L = unpack(select(2, ...))
  2.  
  3. local barHeight, barWidth = 10, 378
  4. local font, fontsize, flags = C["media"].font, 11, "THINOUTLINE"
  5. local barTex, flatTex = C["media"].normTex
  6. local color = RAID_CLASS_COLORS[D.Class]
  7. local FactionInfo = {
  8.     [1] = {{ 170/255, 70/255,  70/255 }, "Hated", "FFaa4646"},
  9.     [2] = {{ 170/255, 70/255,  70/255 }, "Hostile", "FFaa4646"},
  10.     [3] = {{ 170/255, 70/255,  70/255 }, "Unfriendly", "FFaa4646"},
  11.     [4] = {{ 200/255, 180/255, 100/255 }, "Neutral", "FFc8b464"},
  12.     [5] = {{ 75/255,  175/255, 75/255 }, "Friendly", "FF4baf4b"},
  13.     [6] = {{ 75/255,  175/255, 75/255 }, "Honored", "FF4baf4b"},
  14.     [7] = {{ 75/255,  175/255, 75/255 }, "Revered", "FF4baf4b"},
  15.     [8] = {{ 155/255,  255/255, 155/255 }, "Exalted","FF9bff9b"},
  16. }
  17.  
  18. function colorize(r) return FactionInfo[r][3] end
  19.  
  20. local function IsMaxLevel()
  21.     if UnitLevel("player") == MAX_PLAYER_LEVEL then
  22.         return true
  23.     end
  24. end
  25.  
  26. local backdrop = CreateFrame("Frame", "Experience_Backdrop", UIParent)
  27. backdrop:Size(barWidth, barHeight)
  28. backdrop:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", 7, 178)
  29. backdrop:SetBackdropColor(C["general"].backdropcolor)
  30. backdrop:SetBackdropBorderColor(C["general"].backdropcolor)
  31. backdrop:CreateBackdrop()
  32.  
  33. local xpBar = CreateFrame("StatusBar",  "Experience_xpBar", backdrop, "TextStatusBar")
  34. xpBar:SetWidth(barWidth)
  35. xpBar:SetHeight(GetWatchedFactionInfo() and (barHeight) or barHeight)
  36. xpBar:SetPoint("TOP", backdrop,"TOP", 0, 0)
  37. xpBar:SetStatusBarTexture(barTex)
  38. if C["general"].classcolor then xpBar:SetStatusBarColor(color.r, color.g, color.b) else xpBar:SetStatusBarColor(31/255, 41/255, 130/255) end
  39.  
  40. local restedxpBar = CreateFrame("StatusBar", "Experience_restedxpBar", backdrop, "TextStatusBar")
  41. restedxpBar:SetHeight(GetWatchedFactionInfo() and (barHeight) or barHeight)
  42. restedxpBar:SetWidth(barWidth)
  43. restedxpBar:SetPoint("TOP", backdrop, "TOP", 0, 0)
  44. restedxpBar:SetStatusBarTexture(barTex)
  45. restedxpBar:Hide()
  46.  
  47. local repBar = CreateFrame("StatusBar", "Experience_repBar", backdrop, "TextStatusBar")
  48. repBar:SetWidth(barWidth)
  49. repBar:SetHeight(IsMaxLevel() and barHeight - 0 or 0)
  50. repBar:SetPoint("BOTTOM", backdrop, "BOTTOM", 0, 0)
  51. repBar:SetStatusBarTexture(barTex)
  52.  
  53. local mouseFrame = CreateFrame("Frame", "Experience_mouseFrame", backdrop)
  54. mouseFrame:SetAllPoints(backdrop)
  55. mouseFrame:EnableMouse(true)
  56.  
  57. local Text = mouseFrame:CreateFontString("mouseFrame_Text", "OVERLAY")
  58. Text:SetFont(font, fontsize, flags)
  59. Text:SetPoint("CENTER", mouseFrame, "CENTER", 0, 0)
  60.  
  61. backdrop:SetFrameLevel(0)
  62. restedxpBar:SetFrameLevel(1)
  63. repBar:SetFrameLevel(2)
  64. xpBar:SetFrameLevel(2)
  65. mouseFrame:SetFrameLevel(3)
  66.  
  67. local function updateStatus()
  68.     local XP, maxXP, restXP = UnitXP("player"), UnitXPMax("player"), GetXPExhaustion()
  69.     local percXP = ((XP == 0) and (maxXP == 0)) or (math.floor((XP / maxXP) * 100))
  70.  
  71.     if IsMaxLevel() then
  72.         xpBar:Hide()
  73.         restedxpBar:Hide()
  74.         repBar:SetHeight(barHeight)
  75.         if not GetWatchedFactionInfo() then backdrop:Hide() else backdrop:Show() end
  76.     else
  77.         xpBar:SetMinMaxValues(min(0, XP), maxXP)
  78.         xpBar:SetValue(XP)
  79.  
  80.         if restXP then
  81.             Text:SetText(format("%s/%s (%s%%|cffb3e1ff+%d%%|r)", D.ShortValue(XP), D.ShortValue(maxXP), percXP, restXP / maxXP * 100))
  82.             restedxpBar:Show()
  83.             local r, g, b = color.r, color.g, color.b
  84.             restedxpBar:SetStatusBarColor(r, g, b, .40)
  85.             restedxpBar:SetMinMaxValues(min(0, XP), maxXP)
  86.             restedxpBar:SetValue(XP + restXP)
  87.         else
  88.             restedxpBar:Hide()
  89.             Text:SetText(format("%s/%s (%s%%)", D.ShortValue(XP), D.ShortValue(maxXP), percXP))
  90.         end
  91.  
  92.         if GetWatchedFactionInfo() then
  93.             xpBar:SetHeight(barHeight)
  94.             restedxpBar:SetHeight(barHeight)
  95.             repBar:SetHeight(2)
  96.             repBar:Show()
  97.         else
  98.             xpBar:SetHeight(barHeight)
  99.             restedxpBar:SetHeight(barHeight)
  100.             repBar:Hide()
  101.         end
  102.     end
  103.  
  104.     if GetWatchedFactionInfo() then
  105.         local name, rank, minRep, maxRep, value = GetWatchedFactionInfo()
  106.         repBar:SetMinMaxValues(minRep, maxRep)
  107.         repBar:SetValue(value)
  108.         repBar:SetStatusBarColor(unpack(FactionInfo[rank][1]))
  109.         Text:SetText(format("%d / %d (%d%%)", value - minRep, maxRep - minRep, (value - minRep) / (maxRep - minRep) * 100))
  110.     end
  111.  
  112.     mouseFrame:SetScript("OnEnter", function()
  113.         GameTooltip:SetOwner(mouseFrame, "ANCHOR_BOTTOMLEFT", -3, barHeight)
  114.         GameTooltip:ClearLines()
  115.         if not IsMaxLevel() then
  116.             GameTooltip:AddLine("Experience:")
  117.             GameTooltip:AddLine(string.format("XP: %s/%s (%d%%)", D.CommaValue(XP), D.CommaValue(maxXP), (XP / maxXP) * 100))
  118.             GameTooltip:AddLine(string.format("Remaining: %s", D.CommaValue(maxXP - XP)))
  119.             if restXP then GameTooltip:AddLine(string.format("|cffb3e1ffRested: %s (%d%%)", D.CommaValue(restXP), restXP / maxXP * 100)) end
  120.         end
  121.         if GetWatchedFactionInfo() then
  122.             local name, rank, min, max, value = GetWatchedFactionInfo()
  123.             if not IsMaxLevel() then GameTooltip:AddLine(" ") end
  124.             GameTooltip:AddLine(string.format("Reputation: %s", name))
  125.             GameTooltip:AddLine(string.format("Standing: |c"..colorize(rank) .. "%s|r", FactionInfo[rank][2]))
  126.             GameTooltip:AddLine(string.format("Rep: %s/%s (%d%%)", D.CommaValue(value - min), D.CommaValue(max - min), (value - min)/(max - min) * 100))
  127.             GameTooltip:AddLine(string.format("Remaining: %s", D.CommaValue(max - value)))
  128.         end
  129.         GameTooltip:Show()
  130.     end)
  131.     mouseFrame:SetScript("OnLeave", function() GameTooltip:Hide() end)
  132. end
  133.  
  134. local frame = CreateFrame("Frame",nil,UIParent)
  135. frame:RegisterEvent("PLAYER_LEVEL_UP")
  136. frame:RegisterEvent("PLAYER_XP_UPDATE")
  137. frame:RegisterEvent("UPDATE_EXHAUSTION")
  138. frame:RegisterEvent("CHAT_MSG_COMBAT_FACTION_CHANGE")
  139. frame:RegisterEvent("UPDATE_FACTION")
  140. frame:RegisterEvent("PLAYER_ENTERING_WORLD")
  141. frame:SetScript("OnEvent", updateStatus)

Seerah 08-10-14 07:30 PM

Do what SDPhantom says.

Phanx 08-11-14 02:19 AM

Quote:

Originally Posted by liquidbase (Post 295160)
local XP, maxXP, restXP = UnitXP("player"), UnitXPMax("player"), GetXPExhaustion()
local percXP = ((XP == 0) and (maxXP == 0)) or (math.floor((XP / maxXP) * 100))

That second line is the problem; I don't think it's doing what you think it's doing. What you wrote is the equivalent of this:

Code:

if XP == 0 and maxXP == 0 then
    percXP = true
else
    percXP = floor(XP / maxXP * 100)
end

SDPhantom's suggestion will prevent the error from showing up, but I'd suggest doing this instead:

Code:

local XP, maxXP, restXP = UnitXP("player"), UnitXPMax("player"), GetXPExhaustion()
if not maxXP or maxXP == 0 then return end
local percXP = floor(XP / maxXP * 100)

There's no point in going on with the rest of your display logic if you don't have any valid information to display, or you just end up displaying wrong information.

liquidbase 08-11-14 04:57 AM

Done it Phanx.
Thanks for all the input :)


All times are GMT -6. The time now is 12:52 AM.

vBulletin © 2024, Jelsoft Enterprises Ltd
© 2004 - 2022 MMOUI