All I'm still looking at currently is how to get the suffix from GameSystem.xml.
It would allow getting rid of the 4E suffix override (and further improve support for more rulesets).
Printable View
All I'm still looking at currently is how to get the suffix from GameSystem.xml.
It would allow getting rid of the 4E suffix override (and further improve support for more rulesets).
Awesome. I spent a while looking into it and went the hardcoding route once my brain started hurting too much...
For the suffix stuff etc., I'd rather use the sidebar of an image (grid mode), where one can overwrite the typical increment and the suffix of range indicators :) Then one can even adjust that kind of stuff ingame :) (I have some prototype for that in my height extension, not uploaded yet; I can try to find that prototype if you want to add such things :) )
Certainly. That is the primary source using getDistanceSuffix(), but I like to configure each of those variables to fallback to the gamesystem file values if it doesn't get them from the image sidebar.
I did this with "local diagmult = getDistanceDiagMult() or Interface.getDistanceDiagMult()"
To account for the problem in getDistanceBetween I tried experimenting with a new way of generating the distances which is more reliant on the built in methods. This generates a pretty good result, but gets wonky when height is the primary distance between targets. It does have the advantage however of also overwriting the imagecontrol getDistanceBetween making it consistent with the Token.getDistanceBetween function.
Code:----------------------
-- CUSTOM ADDITIONS --
----------------------
local function exactMatch(startx, starty, endx, endy, sizeMultiplier, gridsize)
local equal = false
local modx = endx
local mody = endy
-- Debug.console(modx, startx, mody, starty)
if modx > startx then
modx = modx - gridsize * sizeMultiplier
elseif modx < startx then
modx = modx + gridsize * sizeMultiplier
end
if mody > starty then
mody = mody - gridsize * sizeMultiplier
elseif mody < starty then
mody = mody + gridsize * sizeMultiplier
end
-- Debug.console(modx, startx, mody, starty)
if modx == startx and mody == starty then
equal = true
end
return equal
end
local function matchWithinSize(startx, starty, endx, endy, sizeMultiplier, gridsize)
local equal = false
local lowerBoundx = endx
local lowerBoundy = endy
local upperBoundx = endx
local upperBoundy = endy
if endx > startx then
lowerBoundx = endx - gridsize * sizeMultiplier
elseif endx < startx then
upperBoundx = endx + gridsize * sizeMultiplier
end
if endy > starty then
lowerBoundy = endy - gridsize * sizeMultiplier
elseif endy < starty then
upperBoundy = upperBoundy + gridsize * sizeMultiplier
end
-- Debug.console(lowerBoundx, startx, upperBoundx, lowerBoundy, starty, upperBoundy)
if startx >= lowerBoundx and startx <= upperBoundx and starty >= lowerBoundy and starty <= upperBoundy then
equal = true
end
return equal
end
local function getCTNodeAt(basex, basey)
-- Debug.console("start getCTNodeAt")
local allTokens = getTokens()
for _, oneToken in pairs(allTokens) do
local x,y = oneToken.getPosition()
local ctNode = CombatManager.getCTFromToken(oneToken)
local bExact = true
local nSpace = DB.getValue(ctNode, "space");
local distancePerGrid = GameSystem.getDistanceUnitsPerGrid()
local sizeMultiplier = ((nSpace / distancePerGrid) - 1) * 0.5
if nSpace > distancePerGrid * 3 then
bExact = false
end
local gridsize = getGridSize()
local bFound = false
if bExact then
bFound = exactMatch(basex, basey, x, y, sizeMultiplier, gridsize)
else
bFound = matchWithinSize(basex, basey, x, y, sizeMultiplier, gridsize)
end
-- if sizeMultiplier > 0 then
-- local exactMatch = exactMatch(basex, basey, x, y, sizeMultiplier, gridsize)
-- local matchWithinSize = matchWithinSize(basex, basey, x, y, sizeMultiplier, gridsize)
-- Debug.console(ctNode, "sizeMultiplier", sizeMultiplier, "gridsize", gridsize)
-- Debug.console("exactMatch", exactMatch, "matchWithinSize", matchWithinSize)
-- end
if bFound then
return ctNode
end
end
end
local function calculate3dDistance(flatDistance, heightDistance)
local distancePerGrid = GameSystem.getDistanceUnitsPerGrid()
local diagMult = getDistanceDiagMult()
local totalDistance = flatDistance
if diagMult == 0 then
totalDistance = math.sqrt((flatDistance ^ 2) + (heightDistance ^ 2))
elseif diagMult == 1 then
totalDistance = math.max(flatDistance, heightDistance)
else
if flatDistance > heightDistance then
totalDistance = flatDistance + heightDistance * (diagMult - 1)
else
totalDistance = heightDistance + flatDistance * (diagMult - 1)
end
totalDistance = math.ceil(totalDistance / distancePerGrid) * distancePerGrid
end
Debug.chat(totalDistance)
return totalDistance
end
local getDistanceBetweenTokens_orig
local function getDistanceBetweenTokens(sourceToken, targetToken)
local flatDistance = getDistanceBetweenTokens_orig(sourceToken, targetToken)
if not flatDistance then
return nil
end
local sourceHeight = 0
local targetHeight = 0
local ctNodeOrigin = CombatManager.getCTFromToken(sourceToken)
if ctNodeOrigin then
sourceHeight = TokenHeight.getHeight(ctNodeOrigin)
local ctNodeTarget = CombatManager.getCTFromToken(targetToken)
if ctNodeTarget then
targetHeight = TokenHeight.getHeight(ctNodeTarget)
end
end
local heightDistance = math.abs(sourceHeight - targetHeight)
return calculate3dDistance(flatDistance, heightDistance)
end
function getDistanceBetween(source, target)
-- Debug.console("getDistanceBetween")
-- Debug.console("types", type(source), type(target))
if type(source) == "tokeninstance" and type(target) == "tokeninstance" then
return getDistanceBetweenTokens(source, target)
end
local flatDistance = super.getDistanceBetween(source, target)
if not flatDistance then
return nil
end
local sourceHeight = 0
local targetHeight = 0
local ctNodeOrigin = getCTNodeAt(source.x, source.y)
if ctNodeOrigin then
sourceHeight = TokenHeight.getHeight(ctNodeOrigin)
local ctNodeTarget = getCTNodeAt(target.x, target.y)
if ctNodeTarget then
targetHeight = TokenHeight.getHeight(ctNodeTarget)
end
end
local heightDistance = math.abs(sourceHeight - targetHeight)
return calculate3dDistance(flatDistance, heightDistance)
end
function onMeasurePointer(pixellength,pointertype,startx,starty,endx,endy)
local distance = getDistanceBetween({x = startx, y = starty}, {x = endx, y = endy})
if distance == 0 then
return ""
else
local stringDistance = nil
if diagMult == 0 then
stringDistance = string.format("%.1f", distance)
else
stringDistance = string.format("%.0f", distance)
end
return stringDistance .. getDistanceSuffix()
end
end
function onInit()
if super and super.onInit() then
super.onInit()
end
getDistanceBetweenTokens_orig = Token.getDistanceBetween
Token.getDistanceBetween = getDistanceBetweenTokens
end
I suggested that same approach around v1.9 (that's why getDistanceBetweenTokens_orig was there) but GKEnialb wanted to do it all in a single function rather than calling the original function.
I actually think that was the right call since otherwise different formulas are being used (which is causing the weirdness you mention when height is the primary differentiator). Supposedly the original function being called there is similar to this.
Yeah, I appreciate the thought Soxmax, but I don't think it'll work with horizontal being calculated separately from vertical. There are some other interesting things in what you posted, though, so I'll play with something in between.
Sorry, Svandal, I do see that getDistanceBetween doesn't work right for tokens larger than one square - you were absolutely right that it's just using the center and that it doesn't match the arrow. I had figured that since both onMeasurePointer and getDistanceBetween were both calling distanceBetween, they must be getting the same result, but didn't think about the fact that getDistanceBetween starts with tokens instead of coordinates (and getting the position of those tokens returns the center). The good news is that I know how to fix it - just have to find the square in the large target closest to the other (as mattekure points out in post 135). I'll have a fix shortly.
* Well, "shortly" may not be too accurate. I implemented finding the closest square, but apparently that's not exactly how it works. I think it takes the line between the center of each token and finds the furthest square of each token along that line. Looking at this image:
Attachment 46366
The closest square is in red and is 20' away (with the variant/3.5/PFRPG counting). However, the old getDistanceBetween (and the logic I use in the arrow) both come up with 25', which would be true if the square directly south of the red square was chosen. Not sure that I like that, but better to make it match what the core comes up with...
4E
Token Height 3.2
Aura-Effects .10
New Campaign, no other extensions.
I get this error on token move.
https://i.imgur.com/ABGKEFO.png
Removing Token Height removes the error.