Fantasy Grounds Merchandise
Page 15 of 68 First ... 5 13 14 15 16 17 25 65 ... Last
  1. #141
    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).
    Last edited by bmos; May 4th, 2021 at 18:52.

  2. #142
    GKEnialb's Avatar
    Join Date
    Jul 2017
    Location
    Castle Rock, CO
    Posts
    622
    Awesome. I spent a while looking into it and went the hardcoding route once my brain started hurting too much...

  3. #143
    Kelrugem's Avatar
    Join Date
    Sep 2018
    Location
    Göttingen (Germany)
    Posts
    4,477
    Quote Originally Posted by bmos View Post
    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).
    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 )

  4. #144
    Quote Originally Posted by Kelrugem View Post
    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()"

  5. #145
    Kelrugem's Avatar
    Join Date
    Sep 2018
    Location
    Göttingen (Germany)
    Posts
    4,477
    Quote Originally Posted by bmos View Post
    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.
    ah, I see

  6. #146
    SoxMax's Avatar
    Join Date
    Mar 2021
    Location
    Massachusetts, USA
    Posts
    186
    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

  7. #147
    Quote Originally Posted by SoxMax View Post
    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.
    Last edited by bmos; May 4th, 2021 at 22:38.

  8. #148
    GKEnialb's Avatar
    Join Date
    Jul 2017
    Location
    Castle Rock, CO
    Posts
    622
    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.

  9. #149
    GKEnialb's Avatar
    Join Date
    Jul 2017
    Location
    Castle Rock, CO
    Posts
    622
    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:

    Not the Closest.png

    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...
    Last edited by GKEnialb; May 5th, 2021 at 04:43.

  10. #150
    4E
    Token Height 3.2
    Aura-Effects .10

    New Campaign, no other extensions.

    I get this error on token move.



    Removing Token Height removes the error.

Page 15 of 68 First ... 5 13 14 15 16 17 25 65 ... Last

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Refer a Friend

Log in

Log in