Author: SumFuka
Difficulty: Easy/Medium

// STEVE added this function
void ThrowVomit (edict_t *ent, vec3_t mouth_pos, vec3_t forward, vec3_t right, vec3_t player_vel)
{
edict_t *gib;
gib = G_Spawn();
gi.setmodel (gib, "models/objects/gibs/sm_meat/tris.md2");
gib->solid = SOLID_NOT;
gib->s.effects |= EF_GIB;
gib->flags |= FL_NO_KNOCKBACK;
gib->takedamage = DAMAGE_YES;
gib->die = gib_die;
gib->movetype = MOVETYPE_TOSS;
gib->touch = gib_touch;
// start the gib from out mouth, moving at a forwards velocity
VectorCopy (mouth_pos, gib->s.origin);
VectorScale (forward, 120 + crandom()*40, gib->velocity);
VectorAdd (player_vel, gib->velocity, gib->velocity);
// add a random left-right component to the vomit velocity
VectorScale (right, crandom()*20, right);
VectorAdd (right, gib->velocity, gib->velocity);
gib->avelocity[0] = random()*600;
gib->avelocity[1] = random()*600;
gib->avelocity[2] = random()*600;
gib->think = G_FreeEdict;
gib->nextthink = level.time + 10 + random()*10;
gi.linkentity (gib);
}
This function expects 5 parameters : the player that is throwing up
(ent), the location of their mouth (mouth_pos), vectors forward and
to the right of the player, and the player's velocity.
Spawning an entity in the world
The next few lines set the various properties of the entity, for example, the solid property is 'SOLID_NOT', meaning it does not actually hinder the player's movement in the same way that a barrel does if you walk into it (you'd need a pretty big pile of gibs, but in theory you could block a whole hallway if you threw up a really BIG of 'em).
The other properties in capital letters are CONSTANTS, most of these are defined in q_shared.h. Look at line 503 in q_shared.h... EF_GIB and all the other entity effects are defined here. Have a look at the other types of constants in this file, the comments explain alot about what is available for you to program in the quake2 world.
The gib->die = gib_die line says that when the gib dies, the gib_die function (from g_misc.c) will be called. Similarly for gib_touch.
The VectorCopy line sets the origin of the gib entity to start at the player's mouth. The next VectorScale line gives the gib a velocity of 120 (plus a random amount plus or minus 40) directly forwards from the player. The VectorAdd line adds the player's velocity to the gib velocity, without this we could not do projectile vomiting (taking a runup and seeing how far you can throw your vomit.... yech.)
The second VectorScale line multiplies the 'right' vector by a random amount between -20 and +20. We add this to the gib vector to give it a sideways velocity.
Next we set the x,y,z components of the angular velocity for the gib (avelocity is a vector, so avelocity[0] is the x component). In case you haven't guessed already, crandom() returns a floating point number between -1 and 1 (centered random).
gib->think = G_FreeEdict; is an interesting line. It says that when the gib 'thinks' that it should call the G_FreeEdict function, and remove itself. And it thinks after 10 or so seconds from when it is created. Now remember that my code here is based on the ThrowGib function written (I assume) by John Carmack. Give him all the compliments for this awesome code !
the linkentity function puts the entity into the gameworld.
Let's use the ThrowVomit function !
// THROWUP.H // main function void ThrowUpNow(edict_t *self); // utility function in g_misc.c void ThrowVomit (edict_t *ent, vec3_t mouth_pos, vec3_t forward, vec3_t right, vec3_t player_vel);Now go to throwup.c, and edit the last few lines of ThrowUpNow so that it looks like this :
// also do a spewing sound
gi.sound (self, CHAN_VOICE, gi.soundindex("misc/udeath.wav"), 1, ATTN_NORM, 0);
// cough up some gibs.
for (i = 0; i<3; i++) {
ThrowVomit (self, mouth_pos, forward, right, self->velocity);
}
// every now and again, cough up MEGA vomit
if (random() < 0.1)
{
for (i = 0; i<10; i++) {
ThrowVomit (self, mouth_pos, forward, right, self->velocity);
}
}
}
Vomit, Chuck, Hurl.Same drill as in tutorial 7 : to use this mod, compile the gamex86.dll and go into quake2. Now type this at the console :
bind h "give throwup"Now hit h and run around throwing up all over your friends... and this time you have chunky bits ! (no carrots though...)
Next week, let's do something less disgusting...
Tutorial by SumFuka
|
This site, and all content and graphics displayed
on it, |