Climbing up the walls.

  • Two Factor Authentication is now available on BeyondUnreal Forums. To configure it, visit your Profile and look for the "Two Step Verification" option on the left side. We can send codes via email (may be slower) or you can set up any TOTP Authenticator app on your phone (Authy, Google Authenticator, etc) to deliver codes. It is highly recommended that you configure this to keep your account safe.

Payback

Ive got a big stick
Nov 21, 2002
94
0
0
ahl.action-web.net
Im sure Im missing something here... I've written a state to make the player climb a wall if its under a certain height. My check for the height of the wall works, but the actual climb doesnt move the player. They just freeze on the spot.

As you can see below, its an extension of player climbing, with the main difference being that I have a check to see if they are over the wall, and a bit of debug to show the new acceleration. When I move forward the debug displays newaccel = 0,0,6000. I also set the pawns physics to Phys_Ladder before I send the pawn to the PlayerWallClimbing state.

But the pawn never moves. Can anyone tell me why :(?

Code:
// player is climbing a wall
state PlayerWallClimbing extends PlayerClimbing
{
ignores SeePlayer, HearNoise, Bump;

    function PlayerMove( float DeltaTime )
    {
        local vector X,Y,Z, NewAccel, ClimbDir, TraceDir, TraceStart, TraceEnd;
        local eDoubleClickDir DoubleClickMove;
        local rotator OldRotation, ViewRotation;
        local bool  bSaveJump;

        GetAxes(Rotation,X,Y,Z);
        ClimbDir = vect(0,0,1);

        NewAccel = aForward*ClimbDir;  // do I really want to use aforward?

        ClientMessage("newAccel = "$ NewAccel);

        if ( VSize(NewAccel) < 1.0 )
            NewAccel = vect(0,0,0);

        GetAxes(Pawn.Rotation,X,Y,Z);
    	TraceDir = X;
		TraceStart = Location - vect(0,0,-40);
		TraceEnd = TraceStart + TraceDir*8.0;

   	    // We need to trace along the feet here
		// To see if they've climbed as high as necessary.
		if (!FastTrace(TraceStart, TraceEnd))
           GotoState('PlayerWalking');

        ViewRotation = Rotation;

        // Update rotation.
        SetRotation(ViewRotation);
        OldRotation = Rotation;
        UpdateRotation(DeltaTime, 1);

        if ( Role < ROLE_Authority ) // then save this move and replicate it
            ReplicateMove(DeltaTime, NewAccel, DoubleClickMove, OldRotation - Rotation);
        else
            ProcessMove(DeltaTime, NewAccel, DoubleClickMove, OldRotation - Rotation);
        bPressedJump = bSaveJump;
    }
}
 

Sir_Brizz

Administrator
Staff member
Feb 3, 2000
26,020
83
48
i think he means heaving themselves up onto the top of a wall, not actually walking on the wall.
 

Payback

Ive got a big stick
Nov 21, 2002
94
0
0
ahl.action-web.net
Brizz is right. I mean heaving yourself over a wall rather than running along it. However, I've modified my code to use the spidering state, and that now pushes me up the wall.

Code:
// player is climbing ladder
state PlayerWallClimbing extends PlayerSpidering
{
ignores SeePlayer, HearNoise, Bump;

    function ProcessMove(float DeltaTime, vector NewAccel, eDoubleClickDir DoubleClickMove, rotator DeltaRot)
    {
        local vector OldAccel;

        OldAccel = Pawn.Acceleration;
        Pawn.Acceleration = NewAccel;

//        ClientMessage("newAccel = "$ Pawn.Acceleration);

        if ( bPressedJump )
        {
            Pawn.DoJump(bUpdating);
            if ( Pawn.Physics == PHYS_Falling )
                GotoState('PlayerWalking');
        }
    }

    function UpdateRotation(float DeltaTime, float maxPitch)
    {
      local rotator newRotation, ViewRotation;

      if ( bInterpolating || ((Pawn != None) && Pawn.bInterpolating) )
      {
        ViewShake(deltaTime);
        return;
      }

    // Added FreeCam control for better view control
      if (bFreeCam == True)
      {
        if (bFreeCamZoom == True)
        {
            CameraDeltaRad += DeltaTime * 0.25 * aLookUp;
        }
        else if (bFreeCamSwivel == True)
        {
            CameraSwivel.Yaw += 16.0 * DeltaTime * aTurn;
            CameraSwivel.Pitch += 16.0 * DeltaTime * aLookUp;
        }
        else
        {
            CameraDeltaRotation.Yaw += 32.0 * DeltaTime * aTurn;
            CameraDeltaRotation.Pitch += 32.0 * DeltaTime * aLookUp;
        }
      }
      else
      {
        ViewRotation = Rotation;

		if(Pawn != None && Pawn.Physics != PHYS_Flying) // mmmmm
		{
			// Ensure we are not setting the pawn to a rotation beyond its desired
			if(	Pawn.DesiredRotation.Roll < 65535 &&
				(ViewRotation.Roll < Pawn.DesiredRotation.Roll || ViewRotation.Roll > 0))
				ViewRotation.Roll = 0;
			else if( Pawn.DesiredRotation.Roll > 0 &&
				(ViewRotation.Roll > Pawn.DesiredRotation.Roll || ViewRotation.Roll < 65535))
				ViewRotation.Roll = 0;
		}

        DesiredRotation = ViewRotation; //save old rotation

        if ( bTurnToNearest != 0 )
            TurnTowardNearestEnemy();
        else if ( bTurn180 != 0 )
            TurnAround();
        else
        {
            TurnTarget = None;
            bRotateToDesired = false;
            bSetTurnRot = false;
            ViewRotation.Yaw += 32.0 * DeltaTime * aTurn;
            ViewRotation.Pitch += 32.0 * DeltaTime * aLookUp;
        }
        ViewRotation.Pitch = LimitPitch(ViewRotation.Pitch); //amb

        SetRotation(ViewRotation);

        ViewShake(deltaTime);
        ViewFlash(deltaTime);

        NewRotation = ViewRotation;
        //NewRotation.Roll = Rotation.Roll;

        if ( !bRotateToDesired && (Pawn != None) && (!bFreeCamera || !bBehindView) )
            Pawn.FaceRotation(NewRotation, deltatime);
      }
    }

    function PlayerMove( float DeltaTime )
    {
        local vector X,Y,Z, NewAccel, TraceDir, TraceStart, TraceEnd;
        local vector HitNormal, HitLocation;
        local eDoubleClickDir DoubleClickMove;
        local rotator OldRotation, ViewRotation;
        local bool  bSaveJump, bClear;
        local actor hitTarget;

        GetAxes(Pawn.Rotation,X,Y,Z);

        NewAccel = vect(0,0,10); //aForward*ClimbDir;  // do I really want to use aforward?

//        ClientMessage("newAccel = "$ Pawn.Velocity);

/*        if ( VSize(NewAccel) < 1.0 )
            NewAccel = vect(0,0,0);*/

     	TraceDir = X;
		TraceStart = Pawn.Location + vect(0,0,-70)+ TraceDir*CollisionRadius;
		TraceEnd = TraceStart + TraceDir*8.0;

        HitTarget = Trace( HitLocation, HitNormal,TraceEnd, TraceStart, true);
        if (HitTarget == none)
            bClear = true;
        else
            bClear = false;

		ClientMessage("Trace = "$  bClear $" @ "$ TraceStart);

   	    // We need to trace along the feet here
		// To see if they've climbed as high as necessary.
		if (bClear)
           GotoState('PlayerWalking');

        ViewRotation = Rotation;

        // Update rotation.
        SetRotation(ViewRotation);
        OldRotation = Rotation;
        UpdateRotation(DeltaTime, 1);

        if ( Role < ROLE_Authority ) // then save this move and replicate it
            ReplicateMove(DeltaTime, NewAccel, DoubleClickMove, OldRotation - Rotation);
        else
            ProcessMove(DeltaTime, NewAccel, DoubleClickMove, OldRotation - Rotation);
        bPressedJump = bSaveJump;
    }

    function BeginState()
    {
        GetAxes(Rotation,ViewX,ViewY,ViewZ);
        DoubleClickDir = DCLICK_None;
        Pawn.ShouldCrouch(false);
        bPressedJump = false;
        if (Pawn.Physics != PHYS_Falling)
            Pawn.SetPhysics(PHYS_Spider);
        GroundPitch = 0;
        Pawn.bCrawler = true;
    }

    function EndState()
    {
        GroundPitch = 0;
        if ( Pawn != None )
        {
            Pawn.ShouldCrouch(false);
            Pawn.bCrawler = Pawn.Default.bCrawler;
        }
    }
}

I now have two problems. The first is that if you are looking up, the trace in the playermove function returns true, but if you are looking straight forward, the function returns false. This means that you cant climb the wall whilst looking up and down. Again Im not sure what Im doing wrong as I thought it would be a straight trace out from the pawn. I've tried setting the TraceDir.Z to 0, but that had no effect.

The other problem I have is that the pawn rotates to the ground they are on, so once they are over the wall and onto a roof, the pawn rotates to be parallel to the roof. I know this is because Im now using the spider state, but I've overridden the UpdateRotation so I thought that should be keeping the pawn level.
 
Last edited:

BlackHornet

Global Warzone Project Leader
Apr 24, 2002
76
0
0
43
Aachen - Germany
www.hornet-maps.de
i got it....here my solutions suggestion.....

remember i write a TC and so i modified Pawn + Playercontroller

Code:
in Pawn class

function HitWall( vector HitNormal, actor HitWall )
{
	local Vector StartTrace, EndTrace;
	local bool result;

	if(Physics==PHYS_Falling && !Controller.IsInState('PlayerWallClimbing') )
	{
		if( (FastTrace(Location + vect(0,0,1)*CollisionHeight/2 + normal(vector(Rotation))*1.5*CollisionRadius, 
			Location + vect(0,0,1)*CollisionHeight/2 + normal(vector(Rotation))*1.5*CollisionRadius)) &&
		    (!FastTrace(Location - vect(0,0,1)*CollisionHeight + normal(vector(Rotation))*1.5*CollisionRadius, 
			Location - vect(0,0,1)*CollisionHeight + normal(vector(Rotation))*1.5*CollisionRadius)) )
			Controller.GoToState('PlayerWallClimbing');
	}
}

defaultproperties
{
    .....
    bDirectHitWall=true
}

Code:
in PlayerController class

state PlayerWallClimbing
{
	ignores SeePlayer, HearNoise, Bump;

	function ProcessMove(float DeltaTime, vector NewAccel, eDoubleClickDir DoubleClickMove, rotator DeltaRot)
	{
		local vector OldAccel;

		if((FastTrace(Pawn.Location - vect(0,0,1)*Pawn.CollisionHeight + normal(vector(Pawn.Rotation))*1.5*Pawn.CollisionRadius, 
			Pawn.Location - vect(0,0,1)*Pawn.CollisionHeight)) )
		{
			Pawn.SetPhysics(PHYS_Falling);
			GoToState('PlayerWalking');
		}
		else if ( VSize(NewAccel) <= 0 )
		{
			Pawn.SetPhysics(PHYS_Falling);
			GotoState('PlayerWalking');
		}
		OldAccel = Pawn.Acceleration;
		Pawn.Acceleration = NewAccel;
		Pawn.Velocity = 150.0*vect(0,0,1);
	}

	function PlayerMove( float DeltaTime )
	{
		local vector NewAccel, HitLoc, HitNorm;
		local eDoubleClickDir DoubleClickMove;
		local rotator OldRotation, ViewRotation;
		local bool  bSaveJump;

		if (aForward>0)
			NewAccel = aForward*vect(0,0,1);
		else if(VSize(NewAccel) == 0)
			NewAccel = vect(0,0,0);

		ViewRotation = Rotation;

			 // Update rotation.
		SetRotation(ViewRotation);
		OldRotation = Rotation;
		UpdateRotation(DeltaTime, 1);

		if ( Role < ROLE_Authority ) // then save this move and replicate it
			ReplicateMove(DeltaTime, NewAccel, DoubleClickMove, OldRotation - Rotation);
		else
			ProcessMove(DeltaTime, NewAccel, DoubleClickMove, OldRotation - Rotation);
		bPressedJump = bSaveJump;
	}

	function bool NotifyLanded(vector HitNormal)
	{
		GotoState(Pawn.LandMovementState);
		return bUpdating;
	}
Begin:
	Pawn.SetPhysics(PHYS_Walking);
}

Known Issues:
- Only work with real worldgeometrie cause of the simple FastTrace
- Constant climbingspeed

Every other bug is welcome
 
Last edited:

Payback

Ive got a big stick
Nov 21, 2002
94
0
0
ahl.action-web.net
When you say "I got it" does that mean you are no longer having the online replication/movement problem and that this is fully working code apart from the two bugs you outlined?

And am I correct in thinking that the way to exit your state is to check the foot height of the pawn to see if there is an object infront of it, and if there isnt, then you leave the state and let them fall onto the ledge?
 

BlackHornet

Global Warzone Project Leader
Apr 24, 2002
76
0
0
43
Aachen - Germany
www.hornet-maps.de
Payback said:
When you say "I got it" does that mean you are no longer having the online replication/movement problem and that this is fully working code apart from the two bugs you outlined?

And am I correct in thinking that the way to exit your state is to check the foot height of the pawn to see if there is an object infront of it, and if there isnt, then you leave the state and let them fall onto the ledge?

1. Yes, the player is moving smooth and properly

2. Yes, your right.
When the pawn wants to get into the state two conditions has to be met.
1st: At foot height there must be a WorldGeometrie
2nd: At head height there must be a nothing, so you can climb up.

(maybe more conditions will be improve the situations if the pawn is allowed to climb or not).
The moment im exiting the state if at foot height the WorldGeometrie is no longer.

Simply works on 90 degrees edges and cuboid brushes the moment, but can improves now.