[code] EXIL : Wall Jump

Today we gonna discuss about the walljump function that I used in my project.
First, I’m not the original creator of this code, I found it on the official UDK forum, here : http://forums.epicgames.com/showthread.php?t=751172 and I have changed it a little after. Currently my walljump code cannot be used more than 3 times. After 3 times, the player must land (touch) the ground for reset the limit.

The limit

The 3 times limit is handled by the original function CheckJumpOrDuck already created in the PlayerController class. In my player controller I have simply changed it :

function CheckJumpOrDuck()
{
	if ( Pawn == None )
	{
		return;
	}
	if ( bDoubleJump && (bUpdating || ((EXILAcrobaticPawn(Pawn) != None) && UTPawn(Pawn).CanDoubleJump())) )
	{
		//UTPawn(Pawn).DoDoubleJump( bUpdating );
		if (maxJumpCount <= maxJumpLimitCurrent /*&& pIsInJumpVolume*/)
		{
			EXILAcrobaticPawn(Pawn).DoWallJump( bUpdating );
			maxJumpCount++;
		}
	}
    else if ( bPressedJump )
	{
		if (Pawn.Physics == PHYS_Falling)
		{
			if (maxJumpCount <= maxJumpLimitCurrent /*&& pIsInJumpVolume*/)
			{
				EXILAcrobaticPawn(Pawn).DoWallJump( bUpdating );
				maxJumpCount++;
			}
		}
		else
		{
			maxJumpCount = 0;
			EXILAcrobaticPawn(Pawn).AirControlReset();
			Pawn.DoJump( bUpdating );
		}
	}
	if ( Pawn.Physics != PHYS_Falling && Pawn.bCanCrouch )
	{
		// crouch if pressing duck
		Pawn.ShouldCrouch(bDuck != 0);
	}
}


As you can see, I don’t perform the classic doubleJump from the default class with the UDK, instead I call my walljump function. The maxJumpCount variable is used to store the number of walljumped already performed. When this variable reach 3, the player can’t jump anymore. I reset to 0 this variable when the player is not in Air (phys_falling).

The walljump

Located in the pawn (for an easier access to pawn’s variables, but you can put the walljump function into the playercontroller class), the code looks like this :

function bool DoWallJump( bool bUpdating )
{
	local Vector HitLocation, HitNormal, End, Start;
	local Actor HitActor;
	
	//Perform trace
	Start = Location + (Vector(Rotation) * GetCollisionRadius()/2);
	End = Start + (vector(Rotation) * GetCollisionRadius() * 2.5);
	HitActor = Trace(HitLocation, HitNormal, End, Start, true,);
	`Log("Player try to jump on " @ HitActor);
	
	//check on what we want to jump, we jump only on world surfaces
	if (HitActor == WorldInfo || HitActor.isA('StaticMeshActor'))
	{
		`Log("-Player jump on the wall !");
		
		self.FaceRotation(rotator(HitNormal), GlobalDeltatime);
		Controller.SetRotation( rotator(HitNormal) );
		
		if( HitNormal.Y != 0)
			HitNormal.Y *= WallJumpBoostXY;
		else if(HitNormal.X != 0)
			HitNormal.X *= WallJumpBoostXY;
			
		Velocity = HitNormal;
		
		//PlayerController(Controller).PlaySound(playerSoundWallJump, false, true);

		Velocity.Z = JumpZ + WallJumpBoostZ;

		return true;
	}
	
	return false;
}

The operation is very simple, first we do a trace to be sure that the pawn is in front of a wall. With this trace we get the normal of the wall that we use to do the jump.
The “if” is used to be sure that we jump on a wall (worldinfo = bsp surface) or on a static mesh. Then in my case I change the rotation of the pawn and the camera with the normal vector and after I do the jump with updating the velocity of the pawn. My variable WallJumpBoostXY is just a number that I can change in the defaultproperties.

With this code we only jump perpendicularly of the wall (like I want for my game) but if you want to jump with the same angle as you were going to the wall, you must do this :

		if (HitNormal.X != 0)
		{
			Velocity.X = HitNormal.X * WallJumpBoostXY;
		}

		if (HitNormal.Y != 0)
		{
			Velocity.Y = HitNormal.Y * WallJumpBoostXY;
		}

Et voilĂ  !