Page 1 of 1

Wallhang / Wallclimb

Posted: Mon Sep 28, 2026 12:55 pm
by Archive-Poster
This code allows a player to climb/crawl through walls. Also when the player stop while climbing, he will be stuck to the wall and will not fall.

Code: Select all

//Two global variables. First tells us if the player is above ground and stuck to the wall.
//Second finds the origin of the player when he is near a wall.

new g_bfStuckToWall;
new Float:g_flWallOrigin[33];

#define stickPlayer(%1)            g_bfStuckToWall |= (1 << (%1 & 31))
#define unstickPlayer(%1)        g_bfStuckToWall &= ~(1 << (%1 & 31))
#define isStuck(%1)                g_bfStuckToWall & (1 << (%1 & 31)) 

Code: Select all

//Register touch to find if player is touching a wall.
//Register prethink to create wallclimb when conditions are proper.

register_touch("worldspawn","player","Touch_Climb");
register_touch("func_brush","player","Touch_Climb");
register_touch("func_breakable","player","Touch_Climb");
register_forward(FM_PlayerPreThink, "Forward_PlayerPreThink", 0); 

Code: Select all

public Touch_Climb(Ent,id)
{
    //If player is touching a wall then we find it's origin

    pev(id,pev_origin,g_flWallOrigin[id]);
        
    return PLUGIN_HANDLED;
} 

Code: Select all

public Forward_PlayerPreThink(id)
{
    //If player is dead then ignore.
    
    if(!is_user_alive(id))
        return;
        
    static iButton[33], iCrawlSpeed;
    
    //Get button that player is using as well as the speed he is supposed to move on the wall.
    //I left iCrawlSpeed as a get_pcvar_num so you can register a cvar for that.
    
    iButton[id] = get_user_button(id);
    iCrawlSpeed = get_pcvar_num(YOU_CVAR);

    if(iButton[id] & IN_USE)
    {
        //Here we have three matrices holding the origin of the player, previous origin and velocity.
        
        static Float:fOrigin[33][3];
        static Float:fOriginOld[33][3];
        static Float:fVelocity[33][3];
        
        //Get user origin.
        
        pev(id,pev_origin,fOrigin[id]);
        
        //If he is far from the wall then return.
        
        if(get_distance_f(fOrigin[id],g_flWallOrigin[id]) > 10.0)
            return;
        
        //If holding iButton and moving forward
        
        if(iButton[id] & IN_FORWARD)
        {
            //Check if player is stuck to wall.
            switch(isStuck(id)){
                
                //If not them make him move.
                case 0:{
                    velocity_by_aim(id,iCrawlSpeed,fVelocity[id]);
                    set_pev(id,pev_velocity,fVelocity[id]);
                }
                
                //If yes then unstuck him.
                default:{
                    unstickPlayer(id);
                }
            }
        }
        
        //If holding iButton and moving back
        
        else if(iButton[id] & IN_BACK)
        {
            switch(isStuck(id)){
                case 0:{
                    velocity_by_aim(id,-iCrawlSpeed,fVelocity[id]);
                    set_pev(id,pev_velocity,fVelocity[id]);
                }
                            
                default:{
                    unstickPlayer(id);
                }
            }
        }
        
        else if(iButton[id])
        {
            //If Player is holding iButton but not moving, then g_bStuckToWall = true
            //and previous origin will now always be equal to current.
            
            switch(isStuck(id)){
                case 0:{
                    fOriginOld[id] = fOrigin[id];
                    stickPlayer(id);
                }
            }
            
            //Set his velocity to zero.
            velocity_by_aim(id,0,fVelocity[id]);
            set_pev(id,pev_velocity,fVelocity[id]);
            
            //if the diference between previous and current origins are small, then set
            //set player's new origin as previous
            
            if(get_distance_f(fOrigin[id],fOriginOld[id]) <= 10){
                set_pev(id,pev_origin,fOriginOld[id]);
            }
        }
    }
}