
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