Author: SumFuka
Difficulty: Medium

A new command
void Cmd_Give_f (edict_t *ent)
{
char *name;
gitem_t *it;
int index;
int i;
qboolean give_all;
// STEVE added this bit.
if (Q_stricmp(gi.argv(1), "throwup") == 0)
{
// throw up !
ThrowUpNow (ent);
return;
}
...
Now let's create the blueprint for what we are going to program : create
a new text file called throwup.h in the same directory as all the
other .c and .h files... enter these few lines :
// THROWUP.H // main function void ThrowUpNow(edict_t *self);As you can see, the blueprint is very simple, and we are only defining one new function. Create our new source file, throwup.c and enter the following code fragments :
// THROWUP.C by SumFuka
#include "g_local.h"
#include "throwup.h"
// this function makes you throw up
void ThrowUpNow(edict_t *self)
{
// use some local vector variables to work with
vec3_t forward, right;
vec3_t mouth_pos, spew_vector;
float rnum;
int i;
This is the top of our c file, and we have first included g_local.h (the game
blueprint) and throwup.h (the throwup blueprint). Next we have defined our
ThrowUpNow function, which takes an entity (self) as it's only parameter.
Some local variables are declared at the top of the function.
// set the spew vector, based on the client's view angle AngleVectors (self->client->v_angle, forward, right, NULL);The AngleVectors function sets vectors for us that are directly forward, and directly to the right of where we are facing in the game (the client vangle is an input parameter to this function, forward and right are output parameters. NULL means that we are not supplying a forth parameter).
// Make the spew originate from our mouth VectorScale (forward, 24, mouth_pos); VectorAdd (mouth_pos, self->s.origin, mouth_pos); mouth_pos[2] += self->viewheight;Next we define a mouth_pos vector, which is 24 units forward of our player's origin, and at their viewheight (i.e. the middle of the screen from the player's viewpoint).
// Make the spew come forwards out of our mouth. VectorScale (forward, 24, spew_vector);Above we have made a 'spew vector' that is travelling directly forwards from us, at a speed of 24 units per timeframe.
// BLOOD ! (copied from SpawnDamage function) gi.WriteByte (svc_temp_entity); gi.WriteByte (TE_BLOOD); gi.WritePosition (mouth_pos); gi.WriteDir (spew_vector); gi.multicast (mouth_pos, MULTICAST_PVS);Next we have created a 'temporary entity' of blood. Temporary entities are the little effects you can see in the game such as blood sprays, blaster sparks (when they hit a wall) or bullet marks on the walls. The communications protocol for creating a temporary entity in the game world is this :
// say something cool rnum = random(); if (rnum < 0.2) gi.bprintf (PRINT_MEDIUM, "Retch !\n"); else if (rnum < 0.4) gi.bprintf (PRINT_MEDIUM, "...Vomit...\n"); else if (rnum < 0.6) gi.bprintf (PRINT_MEDIUM, "Chunder.\n"); else if (rnum < 0.8) gi.bprintf (PRINT_MEDIUM, "Chuck. chuck. chuck.\n"); else gi.bprintf (PRINT_MEDIUM, "Hmmmmff hmmmf hhhuuuuuuurrrrrllll.\n");The code above randomly chooses something to say....
// make a painful sound rnum = random(); if (rnum < 0.125) gi.sound (self, CHAN_BODY, SexedSoundIndex(self, "gurp1"), 1, ATTN_NORM, 0); else if (rnum < 0.25) gi.sound (self, CHAN_BODY, SexedSoundIndex(self, "gurp2"), 1, ATTN_NORM, 0); else if (rnum < 0.375) gi.sound (self, CHAN_BODY, SexedSoundIndex(self, "pain50_1"), 1, ATTN_NORM, 0); else if (rnum < 0.5) gi.sound (self, CHAN_BODY, SexedSoundIndex(self, "pain50_2"), 1, ATTN_NORM, 0); else if (rnum < 0.625) gi.sound (self, CHAN_BODY, SexedSoundIndex(self, "pain75_1"), 1, ATTN_NORM, 0); else if (rnum < 0.75) gi.sound (self, CHAN_BODY, SexedSoundIndex(self, "pain75_2"), 1, ATTN_NORM, 0); else if (rnum < 0.875) gi.sound (self, CHAN_BODY, SexedSoundIndex(self, "pain100_1"), 1, ATTN_NORM, 0); else gi.sound (self, CHAN_BODY, SexedSoundIndex(self, "pain100_2"), 1, ATTN_NORM, 0);We randomly make a painful sound here. The sexed sound index will choose the correct sound for the player's sex. For example, "player/male/gurp1.wav" or "player/female/gurp1.wav". We are playing the pain sound on the 'BODY' sound channel. Here are all the sound channels (from g_shared.h, don't type this bit in) :
#define CHAN_AUTO 0
#define CHAN_WEAPON 1
#define CHAN_VOICE 2
#define CHAN_ITEM 3
#define CHAN_BODY 4
You can actually play sounds on any channel up to 7, I believe. A sound played on the same channel as a previous sound will stop that sound... to 'mix' sounds you must play them on different channels, or use CHAN_AUTO which will try to find a free channel (but will not play it if no channels are free).
// also do a spewing sound
gi.sound (self, CHAN_VOICE, gi.soundindex("misc/udeath.wav"), 1, ATTN_NORM, 0);
}
That's the end of throwup.c, save it now ! The last like makes a sound that
sounds very chunder-like. Notice how it is on a different sound channel to the
previous pain sound, so they should be heard together ok.
Vomit, Chuck, Hurl.
bind h "give throwup"Now hit h and run around throwing up all over your friends...
Next week, let's actually cough up some gibs !
Tutorial by SumFuka
|
This site, and all content and graphics displayed
on it, |