IR Goggles

You'll notice everybody while using these because everyone glows red!

I made this tutorial up quickly because, frankly, I don't like powerups or anything which are not items. So I decided to convert Psykotik's old tutorial to something more... class-oriented. Enjoy.
Add in the
blue code and take out any pink code. Pay attention to anything in green.

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_irgoggles - added by nobody */
    {
        "item_irgoggles",
        Pickup_Powerup,
        Use_IRGoggles,
        NULL,
        NULL,
        "items/pkup.wav",
        "models/ammo/nuke/tris.md2", EF_ROTATE,
        NULL,
        "k_comhead",
        "IR Goggles",
        2,
        60,
        NULL,
        IT_POWERUP,
        0,
        NULL,
        0,
        ""
    },

Next. We need to define a function which is called "Use_IRGoggles".
Go down to the bottom of the file, and add this function. Noticing any similarity to the
Scope tutorial yet?? :)

/*
=================
Use_IRGoggles
=================
*/
void Use_IRGoggles (edict_t *ent, gitem_t *item)
{
    if (ent->client->goggles) // we're on
    {
        ent->client->goggles = 0;
        ent->client->ps.rdflags &= ~RDF_IRGOGGLES;
    }
    else // we're off
    {
        ent->client->goggles = 1;
        ent->client->ps.rdflags |= RDF_IRGOGGLES;
    }
}

Next, we need a forward declaration for this function. Stick this line down at the bottom of g_local.h. This allows the function to be used before it is technically declared.

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

That set up the item and command for the goggles, toggling the ent->client->goggles variable and setting the RDF_IRGOGGLES flag as necessary.
Now we need to set up the drain of cells on the goggles. Open up the
p_client.c file and go down into ClientThink. Right before the line "gi.linkentity(ent);" add the following:

   // PSY: GOGGLES DRAIN
   if (ent->client->goggles)
   {
       if (ent->client->pers.inventory[ITEM_INDEX(FindItem("Cells"))] >= 1)
       {
           ent->client->goggledrain++;
           if (ent->client->goggledrain == 10)
           {
               ent->client->pers.inventory[ITEM_INDEX(FindItem("Cells"))] -= 1;
               ent->client->goggledrain = 0;
           }
       }
       else
       {
           ent->client->ps.rdflags &= ~RDF_IRGOGGLES;
           ent->client->goggles = 0;
       }
   }

This handles the goggle drain. You need one more block of code, to make the players visible to the Infrared scanning. Go into p_view.c and find G_SetClientEffects(). Go down right before the line "if (ent->powerarmor_time > level.time)":

   if (!(ent->s.renderfx & RF_IR_VISIBLE))
       ent->s.renderfx |= RF_IR_VISIBLE;

This ensures that the player is always visible (even dead) to IR. The final thing you need to do is go into g_local.h and add in two new client variables into the gclient_s structure, after the line "qboolean update_chase;" insert the following:

// this structure is cleared on each PutClientInServer(),
// except for 'client->pers'
struct gclient_s
{
    // known to server
    player_state_t ps; // communicated by server to clients
    int ping;

    ...

    edict_t *chase_target; // player we are chasing
    qboolean update_chase; // need to update chase info?

    int goggles;
    int goggledrain;

};

And, finally - insert this code into InitClientPersistant, which is in p_client.c.

/*
==============
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("IR Goggles");
    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;
}

And that's it! IR goggles! Enjoy!

Tutorial by Psykotik, with a item-based rework from (nobody)
Quake Style - Tutorials