Post tutorial Report RSS Ejecting Shells

This Mini-Tutorial will show you how to add ejecting brass to your Quake2 mods. This is quite easy, and does not involve much. I will also show you the basics of adding new cvars to be able to change what is there, are what will now show up!

Posted by on - Basic Client Side Coding

[page=Introduction]
Hello again!

Just like many of my tutorials, we will be adding on to files already made. It is easy to make your own files, but I find it easier to find my stuff in normal files (Really!)

Anyways, let's get started!

[page=Adding the function]

Alright, head over to g_misc, after OR before ThrowClientHead.

add this in:

void MachShell (edict_t *self, char *gibname, int damage, int type)
{
	edict_t *gib;
	vec3_t	vd;
	vec3_t	origin;
	vec3_t	size;
	float	vscale;

	gib = G_Spawn();

	gibname = "models/weapons/shell/tris.md2";

	VectorScale (self->size, 1.0, size);
	VectorAdd (self->absmin, size, origin);
	gib->s.origin[0] = origin[0] + crandom() * size[0];
	gib->s.origin[1] = origin[1] + crandom() * size[1];
	gib->s.origin[2] = origin[2] + crandom() * size[2];

	gi.setmodel (gib, gibname);
	gib->solid = SOLID_NOT;
	gib->flags |= FL_NO_KNOCKBACK;
    gib->movetype = MOVETYPE_BOUNCE;
	vscale = 1.0;
	VelocityForDamage (damage, vd);
	VectorMA (self->velocity, vscale, vd, gib->velocity);
	ClipGibVelocity (gib);
	gib->avelocity[0] = random()*600;
	gib->avelocity[1] = random()*600;
	gib->avelocity[2] = random()*600;

	gib->think = G_FreeEdict;
	gib->nextthink = level.time + 2 + random()*3;

	gi.linkentity (gib);
}

It has a very good similarity to ThrowGib eh?
Now, it's pretty obvious how this works. It is throwing whatever model is defined at Gibname out, just like it would gibs.

That was very simple, eh? Nothing else is needed! Let's go on to making a cvar for this now ;)

[page=Cvars: Basic Understanding]

What does Cvar stand for? Cvar means Console Variable, and is usually only available to the server admin.

Why only the server admin? Well say you had a Cvar to turn weapons off.. you don't want clients turning it back on in the middle of a match!

How easy are they to do? With a good understanding of HOW to use them, you should have NO PROBLEM!

First, go to G_local, and find this

// store latched cvars here that we want to get at often
	int			maxclients;
	int			maxentities;

add this underneath:

// we need this too.. we don't want shells overflowing the server!
	int         shelloff;

Same file, go down lower to find:

extern	cvar_t	*sv_cheats;
extern	cvar_t	*maxclients;
extern	cvar_t	*maxspectators;

add this underneath:

extern  cvar_t  *shelloff;

Now, we're going to g_main

find these:

cvar_t	*spectator_password;
cvar_t	*needpass;
cvar_t	*maxclients;

underneath, in a similar manor to the above, add:

cvar_t  *shelloff;

Now, to g_save

find this:

deathmatch = gi.cvar ("deathmatch", "0", CVAR_LATCH);

Add this:

//make sure Shelloff is default to on, so they are defaulted to being off..
	shelloff = gi.cvar ("shelloff", "1", CVAR_SERVERINFO | CVAR_LATCH);

Go lower, find:

// initialize all clients for this game
	game.maxclients = maxclients->value;
	game.clients = gi.TagMalloc (game.maxclients * sizeof(game.clients[0]), TAG_GAME);
	globals.num_edicts = game.maxclients+1;

add:

game.shelloff = shelloff->value;

There we go! We have successfully added our own cvar. In the game, type "shelloff", and it will say "shelloff" is "1".

That's not all though! Now, we must revisit our shell code..

[page=MachShell revisit!]

If you're just tuning in, please read the first two pages ;)

Now, let's make it so that if shelloff is 1, the shells will not show!

Find this in your shell code:

edict_t *gib;
	vec3_t	vd;
	vec3_t	origin;
	vec3_t	size;
	float	vscale;

	gib = G_Spawn();

In between that, add this, so the code there will look like this:

edict_t *gib;
	vec3_t	vd;
	vec3_t	origin;
	vec3_t	size;
	float	vscale;

	if (shelloff->value)
		return;

	gib = G_Spawn();

There! Now, if shelloff->value is 0, no more shells for you!

You could make a function for a shotgun shell too, to make it look different per gun, but you've gotta have the model! You don't want a gun that shoots gibs off, do you?!

Paril('s mini tutorials)
{Realism IS a factor}

Post comment Comments
sidsback
sidsback - - 1 comments

what an intence read, i cant program at all ,but im gonna learn about it ,i`ll get back to you in a month and show you what i`ve l
earnt

Reply Good karma Bad karma+1 vote
farbin
farbin - - 3 comments

While I was happy to find this tutorial and enjoy a good challenge,I found that it did not work "Out-Of-The-Box".
So, I though that I would share my findings.

1.) There needs to be the following line in g_local.h so that the function can be found by other parts of the program:

after this ....

//
// g_misc.c
//
void ThrowHead (edict_t *self, char *gibname, int damage, int type);
void ThrowClientHead (edict_t *self, int damage);
void ThrowGib (edict_t *self, char *gibname, int damage, int type);

add this ...

// ejecting shells
void MachShell (edict_t *self, char *gibname, int damage, int type);

2.) In p_weapon.c, in the function void Machinegun_Fire (edict_t *ent), (somewhere near the end of that function) there should be some way to let the program know that you want the machine gun to spew out the shells. I added this (although not sure if the placement is in the exact spot it should be):

after this ...

PlayerNoise(ent, start, PNOISE_WEAPON);

add this ...

// ejecting shells
MachShell (ent, "models/weapons/shell/tris.md2", damage, GIB_ORGANIC);

3.) and since I specified what model to use in the above line, I removed ...

//gibname = "models/weapons/shell/tris.md2";

from the function ...
void MachShell (edict_t *self, char *gibname, int damage, int type

Compile and watch the shells fly.
Thanks for the mental workout. I got to know the code a little better.

farbin

Reply Good karma Bad karma+2 votes
Paril Author
Paril - - 24 comments

I only gave the beef. You had to make the rest yourself, but thanks :)

Reply Good karma+1 vote
Post a comment

Your comment will be anonymous unless you join the community. Or sign in with your social account: