The REAL Lithium Offhand Grappling Hook!

     This tutorial will show you how to add the actual Lithium offhand grappling hook to your source.  Before we start I must mention that this is originally from the Vanilla CTF source, not Lithium.  Credit goes to James Abbatiello for this wonderful piece of code.

Please note that this tutorial shows how to add the hook to the 3.20 source with MSVC 5.0 or higher.  It is untested with other compilers like LCC, GCC, or Borland.

Let's get started!  Add all the blue code and pay attention to anything in green.

 

1.  Download and add the p_hook.c and p_hook.h files to your project.

2.  Open up g_local.h. Add the following to the end of the
gclient_s structure:

    int             hook_state;
    edict_t        *hook;
   
Now add this to the end of the
edict_s structure:

    edict_t             *laser;

Lastly add this Means Of Death define to the other MODS. Make sure the number following it hasn't been used by a MOD already there.

    #define MOD_GRAPPLE             34

3. Open up p_view.c and go to the P_FallingDamage function. Find these lines:

    // never take falling damage if completely underwater
    if (ent->waterlevel == 3)
        return;

And add these just below them:

    if (ent->client->hook_state == HOOK_ON)
        return;

Now add this #define to the top, below the one for g_local.h:

    #include "p_hook.h"

4. Next open up p_client.c. Now add this #define to the top, below the one for g_local.h:

    #include "p_hook.h"

Go to the player_die function and add this near the tossplayerweapon call:

    hook_reset(self->client->hook);

Now go to the clientobituary function and find these lines:

    case MOD_HELD_GRENADE:
        message = "feels";
        message2 = "'s pain";
        break;
    case MOD_TELEFRAG:
        message = "tried to invade";
        message2 = "'s personal space";
        break;

Add these lines right below those:

    case MOD_GRAPPLE:
        message = "was caught by";
        message2 = "'s grapple";
        break;

Next go to the clientbegindeathmatch function. Add these lines:

    gi.WriteByte (svc_stufftext);
    gi.WriteString ("alias +hook \"cmd hook\"\n");
    gi.unicast(ent, true);

    gi.WriteByte (svc_stufftext);
    gi.WriteString ("alias -hook \"cmd unhook\"\n");
    gi.unicast(ent, true);

Go to the clientdisconnect function and add this:

    hook_reset(ent->client->hook);

Now go to the clientthink function. At the top below the "client = ent->client;" line add this:

    if ((client->hook_state == HOOK_ON) && client->hook)
        hook_service(client->hook);

Next find this line halfway through clientthink:

    client->ps.pmove.gravity = sv_gravity->value;

Replace it with this:

    if (client->hook_state == HOOK_ON)
        client->ps.pmove.gravity = 0;
    else
        client->ps.pmove.gravity = sv_gravity->value;

Now add this to the end of the clientthink function:

    if ((client->hook_state == HOOK_ON) && (VectorLength(ent->velocity) < 10)) {
        client->ps.pmove.pm_flags |= PMF_NO_PREDICTION;
    } else {
        client->ps.pmove.pm_flags &= ~PMF_NO_PREDICTION;
    }

5. Open up g_cmds.c and add this to the clientcommand function:

    else if (Q_stricmp (cmd, "hook") == 0)
    {
        hook_fire (ent);
    }
    else if (Q_stricmp (cmd, "unhook") == 0)
    {
        if (ent->client->hook)
            hook_reset(ent->client->hook);
    }

Now add this #define to the top, below the one for g_local.h:

    #include "p_hook.h"


6. That's it! Bind a key to
+hook and you have a top quality offhand grappling hook. You can change the color of the beam within p_hook.c if you look hard enough :-)

Original grappling hook code by James Abbatiello

Tutorial by Willi