Nextbot PathFollower:Compute() generator doesn't work?

Here is part from nextbot code from RunBehaviour coroutine:


path:Compute( self, pos, function( area, fromArea, ladder, elevator, length )
	if ( !IsValid( fromArea ) ) then

		// first area in path, no cost
		return 0

	else

		if ( !self.loco:IsAreaTraversable( area ) ) then
			// our locomotor says we can't move here
			return -1
		end

		// compute distance traveled along path so far
		local dist = 0

		if ( IsValid( ladder ) ) then
			dist = ladder:GetLength()
		elseif ( length > 0 ) then
			// optimization to avoid recomputing length
			dist = length
		else
			dist = ( area:GetCenter() - fromArea:GetCenter() ):GetLength()
		end

		local cost = dist + fromArea:GetCostSoFar()

		// check height change
		local deltaZ = fromArea:ComputeAdjacentConnectionHeightChange( area )
		if ( deltaZ >= 18 ) then
			// Involves jumping, skip it
			return -1
		elseif ( deltaZ < -self.loco:GetDeathDropHeight() ) then
			// too far to drop
			return -1
		end

		return cost
	end
end )

Basically, I want path generator NOT to create path where jumping is needed and use alternative path that don’t need jumping. But for some reasons, it still creates path with jumps. What am I doing wrong?

well the first problem is you’re making a new function every time you run the path:Compute()
[lua]
local function pathComputeFunc(…)
// do stuff
end

function ENT:RunBehaviour()
path:Compute(self,pos, pathComputeFunc)
end
[/lua]

The second problem probably has something to do with an alternative path not existing?
What i’m saying is, perhaps post some information about how you’ve debugged this.

How do you know for certain the path contains jumps?

Have you added any debug code to check what’s happening in these cases? (ex. if(deltaZ >= 18) then print(“foundjump”) end)

How are you sure there are alternative routes that don’t require jumping?
Or for that matter, how do you know you’ve even got a complete path to your destination?


path:Compute(self,pos, pathComputeFunc)

attempt to index global ‘self’ (a nil value)

Needs to be inside an ENT: function.


function ENT:RunBehaviour()

self is used in OOP: http://lua-users.org/wiki/ObjectOrientationTutorial
Crash course:


function ENT:AFunction()
// self works in here. The "ENT:" part sets the "self" to the entity this runs on. Like: Entity:AFunction()
end

function mahrandomfunction()
//self doesn't work here .. there is no "ENT:" part to refere to.
end

// self doesn't work here .. this is outside any functions.


Tried that. What is odd is that I did put print( area, fromArea, ladder, elevator, length ) inside of this function to see variables, and all of them always were nil.

[editline]8th November 2017[/editline]

Solved. I needed to check area attributes along with height deltas.

So, I made it as separate nextbot function:


function ENT:ComputePath( path, pos )
	if not path then
		print( self, "ENT:ComputePath", "path not provided!" )
	elseif not pos then
		print( self, "ENT:ComputePath", "pos not provided!" )
	else
		local function generator( area, fromArea, ladder, elevator, length )
			if ( !IsValid( fromArea ) ) then
				-- first area in path, no cost
				return 0
			else

				if ( !self.loco:IsAreaTraversable( area ) ) then
					-- our locomotor says we can't move here
					return -1
				end

				-- compute distance traveled along path so far
				local dist = 0

				if ( IsValid( ladder ) ) then
					dist = ladder:GetLength()
				elseif ( length > 0 ) then
					-- optimization to avoid recomputing length
					dist = length
				else
					dist = ( area:GetCenter() - fromArea:GetCenter() ):GetLength()
				end

				local cost = dist + fromArea:GetCostSoFar()

				-- check height change
				local deltaZ = fromArea:ComputeAdjacentConnectionHeightChange( area )
				if ( deltaZ >= 18 ) then
					if ( deltaZ >= 48 ) then
						-- too high to reach
						return -1
					end

					-- jumping is slower than flat ground
					local jumpPenalty = 666
					cost = cost + jumpPenalty * dist
				elseif ( deltaZ < -self.loco:GetDeathDropHeight() ) then
					-- too far to drop
					return -1
				end

				local attributes = fromArea:GetAttributes()

				if bit.band( attributes, NAV_MESH_JUMP ) > 0 then
					-- jumping is slower than flat ground
					-- return -1
					local jumpPenalty = 666
					cost = cost + jumpPenalty * dist
				end

				if bit.band( attributes, NAV_MESH_CROUCH ) > 0 then
					-- crouching is slower than running
					local crouchPenalty = 5
					cost = cost + crouchPenalty * dist
				end

				return cost
            end
		end
		path:Compute( self, pos, generator )
	end
end

and used self:ComputePath( path, pos ) instead of path:Compute(). Thanks for tip of debugging and dumb rating.

P.S. Never use it outside of coroutine…