Scope
Designed for snipers :)

Here's a new idea. What about having an item, a 'scope', which, when used, will zoom in + out.
This is mainly for all you class-based freaks, (me included :) so you can have a realistic item for zooming which is only given to one or two classes.

Add in the
blue code and take out any pink code.

First, we should add the item to the itemlist in g_items.c - go down to the itemlist[] decleration and add this item somewhere in the middle:

/* item_scope - added by nobody */
    {
        "item_scope",
        Pickup_Powerup,
        Use_Scope,
        NULL,
        NULL,
        "items/pkup.wav",
        "models/items/silencer/tris.md2", EF_ROTATE,
        NULL,
        "p_silencer",
        "Scope",
        2,
        60,
        NULL,
        IT_POWERUP,
        0,
        NULL,
        0,
        ""
    },

That should seem simple enough :)
We need to create the Use_Scope function. This will zoom in and out for us. Go down to the bottom of the file and insert this:

/*
=================
Use_Scope
=================
*/
void Use_Scope (edict_t *ent, gitem_t *item)
{
    if (ent->client->ps.fov != 90)
    {
        ent->client->ps.fov = 90;
        ent->client->pers.zoom = false;
        return;
    }

    ent->client->ps.fov = 30;
    ent->client->pers.zoom = true;
}

This function simply says, "Am I not at normal zoom? If not, set to normal zoom and leave. If I am at normal zoom, set to zoomed in."
That should make some sense. Anyone who has played Quake II a bit should know about FOV commands.

Open up g_local.h. Search for "client_persistant_t" (without the quotes!)

"client_persistant_t" is one of the client data structures. You should be able to see this because there is some values determining the ammo limits, inventory, health etc. Insert the following code at the bottom:

// client data that stays across multiple level loads
typedef struct
{
    char userinfo[MAX_INFO_STRING];
    char netname[16];
    int hand;

    qboolean connected; // a loadgame will leave valid entities that
    // just don't have a connection yet

    // values saved and restored from edicts when changing levels
    int health;
    int max_health;
    int savedFlags;

    int selected_item;
    int inventory[MAX_ITEMS];

    // ammo capacities
    int max_bullets;
    int max_shells;
    int max_rockets;
    int max_grenades;
    int max_cells;
    int max_slugs;

    gitem_t *weapon;
    gitem_t *lastweapon;

    int power_cubes; // used for tracking the cubes in coop games
    int score; // for calculating total unit score in coop games

    int game_helpchanged;
    int helpchanged;

    qboolean spectator; // client is a spectator

    qboolean zoom; // are we zoomed in?
} client_persistant_t;

This simply creates a value which can be set to true or false. We will use this value to make sure no FOV commands are being used, execpt when the user has used a scope.
While we're at it, go down to the bottom of the file. We need to declare the Use_Scope function so every other file can use it. Insert this:

void Use_Scope (edict_t *ent, gitem_t *item);

If you compile now, you should find that nothing has changed. But wait! Go to the console, (type ~) and type "give scope". You should find a new item in your inventory. Use it, and you should find that you can zoom in and out!
But there is a few more things to do. We want the player to have this straight away, and we want to make sure everybody cannot zoom unless they are using the scope!

Open up p_client.c. This is our last file that we need to change.
Search down for "ClientThink". This function is called every frame, and this is where we will check for people not using the scope. Insert the highlighted code:

void ClientThink (edict_t *ent, usercmd_t *ucmd)
{
    gclient_t    *client;
    edict_t    *other;
    int        i, j;
    pmove_t    pm;

    if (!ent->client->pers.zoom || (ent->client->pers.zoom && ent->client->ps.fov != 30) )
    {
        ent->client->ps.fov = 90;
        ent->client->pers.zoom = false;
    }

    ...

Now! We're almost done. Now all we need to do is to give the player a scope on startup.
If anyone is doing a class-based system, then remember that you can give this item to whichever class you like!

Go back to the start of p_client.c, and search for "InitClientPersistant". This is the function that gives you a blaster, sets health, ammo limits, etc. Go to here and insert the lines below between the memset function and the give blaster data.

/*
==============
InitClientPersistant

This is only called when the game first initializes in single player,
but is called after each death and level change in deathmatch
==============
*/
void InitClientPersistant (gclient_t *client)
{
    gitem_t *item;

    memset (&client->pers, 0, sizeof(client->pers));

    item = FindItem("Scope");
    client->pers.selected_item = ITEM_INDEX(item);
    client->pers.inventory[client->pers.selected_item] = 1;

    item = FindItem("Blaster");
    client->pers.selected_item = ITEM_INDEX(item);
    client->pers.inventory[client->pers.selected_item] = 1;

    client->pers.weapon = item;

    client->pers.health = 100;
    client->pers.max_health = 100;

    client->pers.max_bullets = 200;
    client->pers.max_shells = 100;
    client->pers.max_rockets = 50;
    client->pers.max_grenades = 50;
    client->pers.max_cells = 200;
    client->pers.max_slugs = 50;

    client->pers.connected = true;
}

There you have it! A brand-new scope that's easy for beginners, and that can be used easily for all you class-based freaks!
Thankyou for listening! That's my first tutorial, expect new ones soon!

Tutorial by (nobody)
Quake Style - Tutorials