VERC: Making A Player Fly Last edited 6 months ago2019-04-21 12:26:21 UTC by Penguinboy Penguinboy

A note from the editor
This article made use of text colouring to differentiate between "existing" code and "new" code. This colouring is not possible on TWHL, so it's a good idea to refer back to the original archived article (see the end of the page) if you're not sure.
This is a tutorial teaching you how to make a flying system in half-life. This is my first real tutorial. Thanks to Mr. Pinstripe Suit for the code. Lets start shall we?

Ok start by going to const.h around line 80 You should see
#define MOVETYPE_FOLLOW    12
#define MOVETYPE_PUSHSTEP    13
Add:
#define MOVETYPE_NEW_FLY    14
This Will be our new flying move type.

Ok Now close that and open pm_shared.h. You should see:
char PM_FindTextureType( char *name );
Add:
void PM_NewFly (void);
Close that and open pm_shared.c. Go to the end and add
void PM_NewFly(void)
{

}
Now go to somewhere around line 1320 and copy all of the code from PM_WaterMove into PM_NewFly(void). Now look in your new function and you should see code like this
// Sinking after no other movement occurs
if (!pmove->cmd.forwardmove && !pmove->cmd.sidemove && !pmove->cmd.upmove)
    wishvel[2] -= 60;// drift towards bottom
else  // Go straight up by upmove amount.
    wishvel[2] += pmove->cmd.upmove;
Either comment this out or delete it because we dont want our player "sinking" because hes not in water hes in the air.

Now under that you should see:
wishspeed *= .8;
Change to:
wishspeed *= .9;
This way hes goes at 90% of full speed instead of 80%.

Now go to PM_Physics_Toss() at about line 2440 and you should see:
if ( pmove->movetype != MOVETYPE_FLY &&
    pmove->movetype != MOVETYPE_BOUNCEMISSILE &&
    pmove->movetype != MOVETYPE_FLYMISSILE)
        PM_AddGravity ();
Change it to:
if ( pmove->movetype != MOVETYPE_FLY &&
    pmove->movetype != MOVETYPE_BOUNCEMISSILE &&
    pmove->movetype != MOVETYPE_FLYMISSILE  &&
    pmove->movetype != MOVETYPE_NEW_FLY)
        PM_AddGravity ();
This way it doesnt add gravity to the player making him fall.

Now go to PM_PlayerMove() at around line 3085 and you should see:
if ( pLadder )
{
    PM_LadderMove( pLadder );
}
else if ( pmove->movetype != MOVETYPE_WALK &&
    pmove->movetype != MOVETYPE_NOCLIP)
{
    // Clear ladder stuff unless player is noclipping
    //  it will be set immediately again next frame if necessary
    pmove->movetype = MOVETYPE_WALK;
}
Change to:
if ( pLadder )
{
    PM_LadderMove( pLadder );
}
else if ( pmove->movetype != MOVETYPE_WALK &&
    pmove->movetype != MOVETYPE_NOCLIP &&
    pmove->movetype != MOVETYPE_NEW_FLY)
{
    // Clear ladder stuff unless player is noclipping
    //  it will be set immediately again next frame if necessary
    pmove->movetype = MOVETYPE_WALK;
}
Ok now go down till you see:
switch ( pmove->movetype )
{
    default:
        pmove->Con_DPrintf("Bogus pmove player movetype %i on (%i) 0=cl 1=sv", pmove->movetype, pmove->server);
            break;

    case MOVETYPE_NONE:
            break;
    ...
Now add ours:
switch ( pmove->movetype )
{
    default:
        pmove->Con_DPrintf("Bogus pmove player movetype %i on (%i) 0=cl 1=sv", pmove->movetype, pmove->server);
            break;

    case MOVETYPE_NONE:
        break;

    case MOVETYPE_NEW_FLY:
        PM_NewFly();
        break;
Ok so now whenever it checks to see what movement type the player is if its our new fly it sends it to the new fly function.

So now to make a player fly you would just set pev->movetype = MOVETYPE_NEW_FLY

Heres how you would use it if you wanted a button bound to make you fly or walk (warning this part is not cut and paste! You do need to think a little),

Go to client.cpp then go down to client command around line 355 and you should see something in there like:
else if ( FStrEq(pcmd, "use" ) )
{
    GetClassPtr((CBasePlayer *)pev)->SelectItem((char *)CMD_ARGV(1));
}
Now add something like this:
else if (FStrEq(pcmd, "startfly" ) )
{
    if (GetClassPtr((CBasePlayer *)pev)->IsFlying)
    {
        ALERT ( at_console, "Damn gravity!" );
        GetClassPtr((CBasePlayer *)pev)->IsFlying = false;
        GetClassPtr((CBasePlayer *)pev)->BeginFly();
    }
    else if (!(GetClassPtr((CBasePlayer *)pev)->IsFlying))
    {
        if (GetClassPtr((CBasePlayer *)pev)->m_iEP > 1500)
        {
            GetClassPtr((CBasePlayer *)pev)->pev->velocity.z += 20;
            ALERT ( at_console, "Look Im flying!" );
            GetClassPtr((CBasePlayer *)pev)->IsFlying = true;
            GetClassPtr((CBasePlayer *)pev)->BeginFly();
        }
        else
        {
            ClientPrint( &pEntity->v, HUD_PRINTCENTER, "Need 1500 EP to fly" );
        }
    }
}
Then the function getting called I have in the player.cpp
void CBasePlayer::BeginFly( void )
{
    if(IsFlying)
    {
        pev->movetype = MOVETYPE_NEW_FLY;
        ClearBits (pev->flags , FL_ONGROUND);
        SetBits (pev->flags, FL_FLY);
        pev->gravity = 0.000;
    }
    else
    {
        pev->movetype = MOVETYPE_WALK;
        SetBits (pev->flags , FL_ONGROUND);
        ClearBits (pev->flags, FL_FLY);
        pev->gravity = 1;
    }
}
So up there it checks if he's flying and if he's not it makes him fly. If hes flying it makes him walk. That extra else is to check if he has enough Expirence points. Now I dont think you have that in your mod but its just there to show you some uses. Well thats about it a lot less harder then I thought it would be. Well really its just a hack but works good.

Any questions or suggestions should be sent to : gimli@jrrclan.com
This article was originally published on the Valve Editing Resource Collective (VERC).
TWHL only archives articles from defunct websites. For more information on TWHL's archiving efforts, please visit the TWHL Archiving Project page.

Comments

You must log in to post a comment. You can login or register a new account.