DICE PACKS BUNDLE
Page 14 of 68 First ... 4 12 13 14 15 16 24 64 ... Last
  1. #131
    GKEnialb's Avatar
    Join Date
    Jul 2017
    Location
    Castle Rock, CO
    Posts
    621
    it seems to calculate a more "real" distance since halving both smaller legs tends to generate a much further distance than the real hypotenuse.
    I see your point, but that's also what happens in the 2D calculations as well - going diagonally 500 feet is 707 feet mathematically but 750 feet with the 3.5/PFRPG movement rules. They did that for simplicity, not for accuracy (and 5E goes even further). I'd prefer to follow that spirit and a quick search on people asking that question in a tabletop setting seems to agree with the formula I have. That being said, I'm easy - if there's enough of a request for a different method, I'd entertain it (at the risk of annoying people who like it as it is).

  2. #132
    Quote Originally Posted by GKEnialb View Post
    I see your point, but that's also what happens in the 2D calculations as well - going diagonally 500 feet is 707 feet mathematically but 750 feet with the 3.5/PFRPG movement rules. They did that for simplicity, not for accuracy (and 5E goes even further). I'd prefer to follow that spirit and a quick search on people asking that question in a tabletop setting seems to agree with the formula I have. That being said, I'm easy - if there's enough of a request for a different method, I'd entertain it (at the risk of annoying people who like it as it is).
    Of course, that makes sense. I got stuck last night with the idea that the real distance was the same as pathfinder distance diagonally, which is only correct for small distances. I understand it now, and since 99% of pathfinder rules are written for 2 dimensions we dont actually have good 3d measurement rules 😃.

    And thank you for your other answers, I am new to lua, and new to the fantasy grounds code.

    I will test this out later today, but it sounds like it is correct now. Thank you everybody.

  3. #133
    Well, I still think the problem is that the function getDistanceBetween does not take into account the token size at all. It only measures distances between token mid points.
    The combat modifier extension calls the function getDistanceBetween when you make a ranged attack.
    I added a Debug.chat in your code to see what distance gets returned. Look in the chat. As you can see it does not take into account token size when it returns the distance. And the distance returned is not the same as the measured distance with the "targeting function". The targeting function when measuring does something else than call the function getDistanceBetween to take into account token size.

    See screenshot for details. The bug is there even with "standard" sized tokens.
    Attached Images Attached Images

  4. #134
    It does look like token size is taken into account for pointers but not for getDistanceBetween. However, I think this might be consistent with how FG normally handles the getDistanceBetween function?
    It's all a bit vague anyway since we don't know how tall creatures are.
    Last edited by bmos; May 4th, 2021 at 12:07.

  5. #135
    MoonWizard described how the getDistanceBetween() function works in this post. https://www.fantasygrounds.com/forum...l=1#post576016

    So calculation is NOT done from center of token to center of token, but instead its done from center of grid square to center of grid square. whichever two grid squares within the token's space are closest.

    For a visual representation of how it works, in this image the PC outlined in purple is targeting each of the NPCs. The distance calculation is done from the center of the purple square, to the center of each of the green squares. The green squares represent the closest grid square to the purple square.

    For support with any of my extensions, visit my #mattekure-stuff channel on Rob2e's discord https://discord.gg/rob2e

  6. #136
    SoxMax's Avatar
    Join Date
    Mar 2021
    Location
    Massachusetts, USA
    Posts
    186
    I had a thought last night about sizes and why you need to do the fuzzy search. I was unfortunately right, it has to do with which square the targeting pointer is on with larger creatures. I've slightly updated my size multiplier code to account for this. Basically anything over 3 * GameSystem.getDistanceUnitsPerGrid() in size needs to be fuzzy matched.
    Code:
    local nSpace = DB.getValue(ctNode, "space");
    local distancePerGrid = GameSystem.getDistanceUnitsPerGrid()
    sizeMultiplier = ((nSpace / distancePerGrid) - 1)  * 0.5
    if nSpace > distancePerGrid * 3 then
    	bExact = false
    end

  7. #137
    Quote Originally Posted by SoxMax View Post
    I had a thought last night about sizes and why you need to do the fuzzy search. I was unfortunately right, it has to do with which square the targeting pointer is on with larger creatures. I've slightly updated my size multiplier code to account for this. Basically anything over 3 * GameSystem.getDistanceUnitsPerGrid() in size needs to be fuzzy matched.
    Code:
    local nSpace = DB.getValue(ctNode, "space");
    local distancePerGrid = GameSystem.getDistanceUnitsPerGrid()
    sizeMultiplier = ((nSpace / distancePerGrid) - 1)  * 0.5
    if nSpace > distancePerGrid * 3 then
    	bExact = false
    end
    GameSystem.getDistanceUnitsPerGrid() will work for most maps, but FGU now has the ability to override that value per map. You would want to check for an override to that value in the image. The dB node would be "distancebaseunit"
    For support with any of my extensions, visit my #mattekure-stuff channel on Rob2e's discord https://discord.gg/rob2e

  8. #138
    Quote Originally Posted by mattekure View Post
    GameSystem.getDistanceUnitsPerGrid() will work for most maps, but FGU now has the ability to override that value per map. You would want to check for an override to that value in the image. The dB node would be "distancebaseunit"
    I think this should do it. I have consolidated these calls to a single function so that it is easier to modify them in one place. It includes the bExact code posted by SoxMax as well, but not the proposed distance calculation change.

    Code:
    ----------------------
    -- CUSTOM ADDITIONS --
    ----------------------
    
    local function getImageSettings()
    	local gridsize = getGridSize()
    	local units = DB.getValue(getDatabaseNode(), "distancebaseunit") or getDistanceBaseUnits()
    	local suffix = getDistanceSuffix()
    	local diagmult = getDistanceDiagMult() or Interface.getDistanceDiagMult()
    
    	-- Debug.chat(gridsize, units, suffix, diagmult)
    	return gridsize, units, suffix, diagmult
    end
    
    local function getDistanceBetween(sourceToken, targetToken)
    	if not sourceToken or not targetToken then
    		return
    	end
    	
    	local gridsize, units, _, _ = getImageSettings()
    	
    	local startz = 0
    	local endz = 0
    
    	local ctNodeOrigin = CombatManager.getCTFromToken(sourceToken)
    	if ctNodeOrigin then
    		startz = TokenHeight.getHeight(ctNodeOrigin) * gridsize / units
    	
    		local ctNodeTarget = CombatManager.getCTFromToken(targetToken)
    		if ctNodeTarget then
    			endz = TokenHeight.getHeight(ctNodeTarget) * gridsize / units
    		end
    	end
    	
    	local startx, starty = sourceToken.getPosition()
    	local endx, endy = targetToken.getPosition()
    
    	return distanceBetween(startx,starty,startz,endx,endy,endz)
    end
    
    function onInit()
    	if super and super.onInit() then
    		super.onInit()
    	end
    
    	Token.getDistanceBetween = getDistanceBetween
    end
    
    -- Distance between two locations in 3 dimensions.
    local function distanceBetween(startx,starty,startz,endx,endy,endz,bSquare)
    	local gridsize, units, suffix, diagmult = getImageSettings()
    
    	local totalDistance = 0
    	local dx = math.abs(endx-startx)
    	local dy = math.abs(endy-starty)
    	local dz = math.abs(endz-startz)
    
    	if bSquare then
    		local hyp = math.sqrt((dx^2)+(dy^2)+(dz^2))
    		totalDistance = (hyp / gridsize)* units * 2
    	else
    		if diagmult == 1 then
    			-- Just a max of each dimension
    			local longestLeg = math.max(dx, dy, dz)		
    			totalDistance = math.floor(longestLeg/gridsize+0.5)*units
    		elseif diagmult == 0 then
    			-- Get 3D distance directly
    			local hyp = math.sqrt((dx^2)+(dy^2)+(dz^2))
    			totalDistance = (hyp / gridsize)* units
    		else 	
    			-- You get full amount of the longest path and half from each of the others
    			local straight = math.max(dx, dy, dz)
    			local diagonal = 0
    			if straight == dx then
    				diagonal = math.floor((math.ceil(dy/gridsize) + math.ceil(dz/gridsize)) / 2) * gridsize
    			elseif straight == dy then
    				diagonal = math.floor((math.ceil(dx/gridsize) + math.ceil(dz/gridsize)) / 2) * gridsize
    			else	
    				diagonal = math.floor((math.ceil(dx/gridsize) + math.ceil(dy/gridsize)) / 2) * gridsize
    			end
    			totalDistance = math.floor((straight + diagonal) / gridsize)
    			totalDistance = totalDistance * units
    		end
    	end
    
    	return totalDistance
    end
    
    function onMeasurePointer(pixellength,pointertype,startx,starty,endx,endy)
    	local gridsize, units, suffix, diagmult = getImageSettings()
    	if not (gridsize and units and suffix and diagmult) then return; end
    	local bSquare = false
    	if pointertype == "rectangle" then
    		bSquare = true
    	end
    
    	local startz = 0
    	local endz = 0
    
    	local ctNodeOrigin = getCTNodeAt(startx,starty,gridsize)
    	if ctNodeOrigin then
    		local ctNodeTarget = getCTNodeAt(endx,endy,gridsize)
    
    		if ctNodeTarget then
    			startz = TokenHeight.getHeight(ctNodeOrigin) * gridsize / units
    			endz = TokenHeight.getHeight(ctNodeTarget) * gridsize / units
    		end
    	end
    
    	local distance = distanceBetween(startx,starty,startz,endx,endy,endz,bSquare)
    	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 .. suffix
    	end
    end
    
    function getCTNodeAt(basex, basey, gridsize)
    	local allTokens = getTokens()
    	for _, oneToken in pairs(allTokens) do
    		local x,y = oneToken.getPosition()
    		local ctNode = CombatManager.getCTFromToken(oneToken)
    		local bExact = true
    		local sizeMultiplier = 0
    
    		-- bmos / SoxMax supporting other rulesets	
    		local nSpace = DB.getValue(ctNode, "space");
    		local distancePerGrid = GameSystem.getDistanceUnitsPerGrid()
    		sizeMultiplier = ((nSpace / distancePerGrid) - 1)  * 0.5
    		if nSpace > distancePerGrid * 3 then
    			bExact = false
    		end
    		
    		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 bFound then
    			return ctNode
    		end
        end
    end
    
    function exactMatch(startx, starty, endx, endy, sizeMultiplier, gridsize)
    	local equal = false
    
    	local modx = endx
    	local mody = endy
    	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		
    	if modx == startx and mody == starty then
    		equal = true
    	end
    
    	return equal
    end
    
    function matchWithinSize(startx, starty, endx, endy, sizeMultiplier, gridsize)
    	local equal = false
    
    	local modx = endx
    	local mody = endy
    	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		
    
    	if startx >= lowerBoundx and startx <= upperBoundx and starty >= lowerBoundy and starty <= upperBoundy then
    		equal = true
    	end
    
    	return equal
    end
    the image settings could alternately be called onInit and then set script-wide variables so that they don't have to be re-checked over and over (although then it would not pick up changes live so I think the solution I have set up here is best).
    Last edited by bmos; May 4th, 2021 at 18:15.

  9. #139
    For some reason, making the map full screen/"sending to background" seems to make the distance calculation revert to original smiteworks version.
    Is anyone else noticing this? I don't recall seeing it discussed here.

    EDIT: It looks like there are other windowclass names for images sent to background or full screen. Probably the extension.xml file needs to have a change made so that image.lua is used in all these places.
    EDIT3: You can use this in extension.xml instead of the current windowclass merge you're using to replace image.lua:
    Code:
    		<template name="image_record_step">
    			<imagecontrol name="image" merge="join">
    				<script file="campaign/scripts/image.lua" />
    			</imagecontrol>
    		</template>
    Last edited by bmos; May 4th, 2021 at 17:03.

  10. #140
    GKEnialb's Avatar
    Join Date
    Jul 2017
    Location
    Castle Rock, CO
    Posts
    621
    Wow, great discussion and super helpful updates. I've folded it all into the extension (made a minor mod to use bmos's updates in the SoxMax code with mattekure's suggestion) and released v3.2. Tried it with the various sizes and seems to work fine, but the off-nominal cases is where all the bugs are lurking. Svandal is the expert at finding those! Hopefully now it'll work. (oh, I should have paid more attention to your screenshot - I'll check to see why onMeasurePointer and getDistanceBetween are giving different results. Presumably they're getting different starting locations for the same tokens).

Page 14 of 68 First ... 4 12 13 14 15 16 24 64 ... 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