View Full Version : FGU lua math and function wierdness
SilentRuin
December 13th, 2022, 17:45
I have two questions on how these things are possible, and how to resolve them (hopefully).
Question 1:
I have a lua file that does some math - then compares that to get a true false result....
Debug.console(v.x*v.x + v.y*v.y);
Debug.console(radius^2);
Debug.console(v.x*v.x + v.y*v.y <= radius^2);
return v.x*v.x + v.y*v.y <= radius^2;
The results will be
#49760288
#49760288
bFALSE
Now I tried a bunch of stuff to get around this thinking "oh I'm just not seeing a truncated float number in the print" so I tried...
math.floor(v.x*v.x + v.y*v.y) <= math.floor(radius^2)
and also tried separating out each side into its own local variable and just doing "a <= b" - still it would appear the values printed were the same but would not come back true consistently (sometimes they would return true with same print values in other measurements of different map token distances - it was bizarre).
This seems less likely to happen on other maps with smaller grid sizes or with medium tokens. Any idea how to resolve this or why it happens?
Any ideas on what causes this or how to resolve it?
Question 2:
I have the following code:
local nDistance = Token.getDistanceBetween(TokenInstanceA, TokenInstanceB);
Debug.console(nDistance);
The results in both the below screen shots is
#5
The problem is that the results do NOT always match what is shown on the map target distance pointer.
Here is screen shot of match (don't get me started on the tiny distance text - it seems to vary and I have no pattern on why)
55450
And here is screen shot of it not matching when I move the token slightly further away
55451
This can be easily duplicated on any map when you have grid locking and move a 1/2 square away.
Thus endeth my questions. I await enlightenment.
Moon Wizard
December 13th, 2022, 21:42
Question 1: No idea. My guess would be floating point differences; though I would expect the math.floor to address as you mentioned. Sort of curious that the numbers you are working with are generating numbers with whole numbers greater than 49m, which means that v.x and v.y are around 5000 each. As far as I know, the numbers in the Debug output aren't rounded, so it looks like you're already getting rounded numbers.
Question 2: Not sure without a specific example/extension showing what you are trying to do. Perhaps the event you are triggering on is happening before the actual token movement?
Regards,
JPG
SilentRuin
December 13th, 2022, 22:18
Question 1: No idea. My guess would be floating point differences; though I would expect the math.floor to address as you mentioned. Sort of curious that the numbers you are working with are generating numbers with whole numbers greater than 49m, which means that v.x and v.y are around 5000 each. As far as I know, the numbers in the Debug output aren't rounded, so it looks like you're already getting rounded numbers.
Question 2: Not sure without a specific example/extension showing what you are trying to do. Perhaps the event you are triggering on is happening before the actual token movement?
Regards,
JPG
Yeah Question 1 is probably a lost cause - I just added a KLUDGE factor to the radius and force it to work. However, Question 2 if it worked would resolve anything outside of the expected range - except the half square issue.
To duplicate is super simple. Do the exact Token.getDistanceBetween call I made (or use the imagecontrol one its the same result) and simply see when you move one token next to another - it will be 5ft. And move it a 1/2 square away it will STILL be 5 ft. While the targeting indicator as shown in the images I gave shows it as 10ft. These are different values for a 1/2 square. There is something different between the Token.getDistanceBetween rounding (as its always to the nearest 5ft it appears) and whatever is used to do the target indicator distance. Only looking at your code (no access for me) would show you what that difference is. Any map/any extension that does this call and compares with the target indicator distance will show you the difference in nearest 5ft and they are different. Which is bad. I would expect the code function to do the same rounding up that the target indicator does.
And this has nothing to do with movement. The tokens are where they are shown - static.
Moon Wizard
December 14th, 2022, 16:16
For question #2, I just built an example extension, and it appears to work fine (attached). The extension triggers on token move, and spits out current position and position/distance of all targets. In the future, please provide a simple extension showing the issue with minimum number of steps; along with steps/pictures to show the exact steps to follow.
For question #1, I'm going to guess that the problem is that you are mixing operators. (i.e. x*x vs. radius^2) Try x*x and radius*radius instead. Otherwise, you'll need to provide the input values for any further investigation.
Regards,
JPG
SilentRuin
December 14th, 2022, 17:18
For question #2, I just built an example extension, and it appears to work fine (attached). The extension triggers on token move, and spits out current position and position/distance of all targets. In the future, please provide a simple extension showing the issue with minimum number of steps; along with steps/pictures to show the exact steps to follow.
I did give details in the screen shots. First I had to add the 5E ruleset or your test .ext did not show up in my list (or I missed it). Then I brought up the same project and it gave the EXACT same results in your output as I showed you. As I moved - the distance stated it was #5 and for the first 1/2 square etc. as I described away from target (see screenshots again) the target pointer distance was 10ft. This is NOT the same thing. And your .ext showed the same thing I saw. Not sure what else to tell you. You have no screen shot showing your stuff. Here is mine when I move it 1/2 square away from target. Your stuff says #5 - the target line says 10ft - not the same.
Before Move
55458
After Move
55459
It's incorrect with your extension. The rounding off is different they should not be. As I said you'd have to look at your internal code to see why that is as I can't see that.
For question #1, I'm going to guess that the problem is that you are mixing operators. (i.e. x*x vs. radius^2) Try x*x and radius*radius instead. Otherwise, you'll need to provide the input values for any further investigation.
Yeah trying this /test with the number gives it working - and as I said even I get it working sometimes. As I worked around this with a KLUDGE factor added in I'm just going to chalk this one up to a mystery as I'm not sure how me assigning each side to its only value then doing the comparison would somehow mix an operator (that was one thing I stated I tried).
SilentRuin
December 14th, 2022, 17:25
But I am using extensions... (sigh) - one of them is doing this I bet.
SilentRuin
December 14th, 2022, 17:27
Yep - not you guys my bad. I'll have to trial and error to see what is doing this. I have my suspicions.
SilentRuin
December 14th, 2022, 17:31
There was a time I never used anyone's extensions but mine so I always knew what was going on and how to resolve it fast... though now I use 3 external ones.
Token Height... I'm coming for you!:pirate:
LordEntrails
December 14th, 2022, 17:36
There was a time I never used anyone's extensions but mine so I always knew what was going on and how to resolve it fast... though now I use 3 external ones.
Token Height... I'm coming for you!:pirate:
Someone once told me; extensions = risk
*duck & cover!*
SilentRuin
December 14th, 2022, 17:41
Someone once told me; extensions = risk
*duck & cover!*
Yeah I was so buried in the Question 1 math part of this thread I just assumed (made an *** of myself) that the other was pure FGU. I mean it was a new function call I'd never seen before - who could be messing with it already in extension land? (sigh)
Never assume :(
GKEnialb
December 16th, 2022, 18:35
@Moon Wizard, is there any chance you could share the equation FGU uses to determine the endx, endy coordinates passed into onMeasurePointer? It's not the midpoint of the target and it's not the closest coordinates to the origin based upon the bounding box containing the target depending upon its size, but seemingly something in between. Unsuccessfully trying to replicate that so I could take the third dimension into account is what led to Token Height causing SilentRuin's question 2.
As an example, if I have a medium sized origin at 675,275 and a large sized target (space = 15) at 800,275, the endx,endy sent to onMeasurePointer is 750,275 (with a grid size of 50 and units of 5). I would have expected the x coordinate of the target to either be 800 (the midpoint and have onMeasurePointer figure it out) or 725 (the closest point to the target, using midpoint X - space * gridsize / units / 2 = 800 - 15 * 50 / 5 / 2 = 725).
Moon Wizard
December 16th, 2022, 20:19
Every token has a "grid size" characteristic (1x1, 2x2, 3x3, ...). When calculating the distance between a token and another point/token; the token's "distance point" is calculated as the center of the nearest grid square in the grid size of the token where the grid size is centered on the token center point. All of this calculation is done in the the client, not in Lua; so I don't have a Lua implementation of it.
Regards,
JPG
GKEnialb
December 16th, 2022, 21:40
Awesome - thanks for the quick response. I'm pretty sure I understand that and can recreate. Hopefully I can implement before silentruin catches up to me... ;)
SilentRuin
December 16th, 2022, 23:08
Awesome - thanks for the quick response. I'm pretty sure I understand that and can recreate. Hopefully I can implement before silentruin catches up to me... ;)
To slow to catch up, I think I've made a release (sometimes 2) for almost all my extensions this week - plus debugged token height by accident and added stuff I wanted to auras... I kick Moon with some false claim then he leaps in to chase ;)
Now I have one more death indicators thing to figure out and I'm done. All these things came up to annoy me in my Monday night SW5E game with an assistant GM controlling a bunch of hostile NPCS against a bunch of players controlling a bunch of friendly NPCs - and then mines and insuring when a vehicle blows up at end of its turn near a mine (but foot soldiers don't) that it turns into a flaming wreck icon and the mine turns into a crater and... point being... NO CHASING ;)
GKEnialb
December 17th, 2022, 00:46
Whew, I can stop running then.
@Moon Wizard, one more question. The reduction of calls to onMeasurePointer in 4.3.1 was great (and means I can probably delete a lot of code that silentruin helped write to do that manually). But now I have a problem where I can't get the measurement arrow to update programmatically. I used to jiggle the coordinates by one pixel after adjusting the height, which forced onMeasurePointer to be called and the arrow was updated. That doesn't work anymore. Do you know of any way I can force onMeasurePointer to be called programmatically?
SilentRuin
December 17th, 2022, 01:17
Whew, I can stop running then.
@Moon Wizard, one more question. The reduction of calls to onMeasurePointer in 4.3.1 was great (and means I can probably delete a lot of code that silentruin helped write to do that manually). But now I have a problem where I can't get the measurement arrow to update programmatically. I used to jiggle the coordinates by one pixel after adjusting the height, which forced onMeasurePointer to be called and the arrow was updated. That doesn't work anymore. Do you know of any way I can force onMeasurePointer to be called programmatically?
I complained about onMeasurepointer spamming to much and it was fixed. Likely jiggling 1 pixel is not enough - I'd experiment with more than that. Maybe
local nDU = GameSystem.getDistanceUnitsPerGrid() * 0.5;
That way its 1/2 a block - as most of this stuff is per block on displayed measurement I'd start with that.
GKEnialb
December 17th, 2022, 01:19
I complained about onMeasurepointer spamming to much and it was fixed. Likely jiggling 1 pixel is not enough - I'd experiment with more than that.
I did +/-50 with no luck as well. But I have to move it right back, of course, so maybe it's smart enough to recognize that as not actually moving...
GKEnialb
December 18th, 2022, 00:10
Whew, I can stop running then.
@Moon Wizard, one more question. The reduction of calls to onMeasurePointer in 4.3.1 was great (and means I can probably delete a lot of code that silentruin helped write to do that manually). But now I have a problem where I can't get the measurement arrow to update programmatically. I used to jiggle the coordinates by one pixel after adjusting the height, which forced onMeasurePointer to be called and the arrow was updated. That doesn't work anymore. Do you know of any way I can force onMeasurePointer to be called programmatically?
To follow up on this, I can call onMeasurePointer manually and get the right answer, but it doesn't update the text of the pointer (presumably whatever calls onMeasurePointer in real life is what sets the pointer text with whatever value gets returned by onMeasurePointer). So it goes back to whether I can trigger a refresh of the pointers programmatically or if some other trick may work. Any suggestions?
GKEnialb
December 21st, 2022, 01:30
To follow up on this, I can call onMeasurePointer manually and get the right answer, but it doesn't update the text of the pointer (presumably whatever calls onMeasurePointer in real life is what sets the pointer text with whatever value gets returned by onMeasurePointer). So it goes back to whether I can trigger a refresh of the pointers programmatically or if some other trick may work. Any suggestions?
@Moon Wizard, I also tried calling Token.onMove when I adjust the height, to no avail. Any other possible way to trigger a targeting arrow update after 4.3.1? Sorry for being a pest about this...
Moon Wizard
December 21st, 2022, 05:58
There is no mechanism to tell the client to update like that. Potentially a jiggle (move 1 pixel and then back)?
JPG
SilentRuin
December 21st, 2022, 06:36
There is no mechanism to tell the client to update like that. Potentially a jiggle (move 1 pixel and then back)?
JPG
Not sure this is relevant but AURA just got a make over and part of that was to speed it up. It was processing a ridiculous amount of trivial onMove's and now only processes if it has moved from last reported position more than 1/2 a grid unit (Kluding where it will err on the side of processing).
Here is the crappy kludge that helped speed up the massive campaigns I run... (also carrier will soon be doing this same thing - prints showed both AURA and Carrier were receiving an insane amount of moves on certain maps)
local TokenMoveArray = {}
local function tokenMovedEnough(token)
-- cleanup after every 20 tokens received - we are not looking for perfect just trimming down processing time
if #TokenMoveArray >= 20 then TokenMoveArray = {} end
local imageControl = ImageManager.getImageControl(token, false)
if imageControl then
local x, y = token.getPosition()
for i = 1, #TokenMoveArray, 1 do
if token == TokenMoveArray[i].token and imageControl == TokenMoveArray[i].imageControl then
-- Determine if moved more than 1/2 the grid unit
local nGridSize = imageControl.getGridSize() * 0.5
if (x - TokenMoveArray[i].x) ^ 2 + (y - TokenMoveArray[i].y) ^ 2 < nGridSize * nGridSize then return false end
table.remove(TokenMoveArray, i)
break
end
end
table.insert(TokenMoveArray, { token = token, imageControl = imageControl, x = x, y = y })
else
return false
end
return true
end
local onMove = nil
local function auraOnMove(tokenMap, ...)
if onMove then onMove(tokenMap, ...) end
local nodeCT = CombatManager.getCTFromToken(tokenMap)
if Session.IsHost and nodeCT then
if tokenMovedEnough(tokenMap) then
local rActor = ActorManager.resolveActor(nodeCT)
if rActor then
-- Debug.chat("onMove aura update", tokenMap)
notifyTokenMove(tokenMap)
end
end
end
end
Side Note: I ran this on map with 100 tokens at least and never hit that 20 limit and some of the carriers had 6 guys moving as one. Like I said the 20 is to err on the safe side.
GKEnialb
December 21st, 2022, 14:01
Thanks. The jiggle was how I forced it to update prior to 4.3.1, but it no longer works. Tried upping the jiggle from 1 pixel to 1 square and back, but to no avail. Any chance we could get something added in the future to force a redraw (like an invalidate call)?
GKEnialb
December 24th, 2022, 01:47
Okay, found a workaround, which is far from elegant but seems to work. The jiggle back and forth right next to each other doesn't work but moving the token by one pixel (not back again) does. On the next adjustment to height, I move it back, which updates the arrow again. So basically, if token is centered on a half-square grid, move it by one. If not, move it back to be centered. Had to snap to the center in my distance calculation, but not a bad thing to do. So looks a bit odd but all the behavior is correct, so not too bad. Would still be great to be able to force a pointer update, though.
Powered by vBulletin® Version 4.2.1 Copyright © 2026 vBulletin Solutions, Inc. All rights reserved.