|
QuakeZone MOD Coding Tutorials
|
|
|
Introduction Code Notes Exercises |
|
| Introduction |
|
|
This tutorial describes how to create earthquake rockets. Select earthquake rockets, fire into the floor or wall, wait a few seconds and....hey, presto, an earthquake you created. Note that the earthquake code is taken (with thanks!) from a Quakestyle tutorial - go to the Tutorials Links page and follow the link to the Quakestyle Tutorials page. This code requires that Nuclear Rockets tutorial (or at least the parts that allow different rocket
types) to have already been done.
|
| Code |
|
|
g_local.h Add the following cvar server variables at the indicated place: extern cvar_t *sv_maplist; // <-- insert lines after here // PJT - quake rockets extern cvar_t *sv_qkdelay; // time between rocket impact and start of quake extern cvar_t *sv_qkduration; // minimum duration of quake extern cvar_t *sv_qkradius; // radius of quake extern cvar_t *sv_qkrichter; // amplitude of quake (10.0 = velocity 1000) // PJTAt the end of the edict_s structure, add the following lines: int quake_timer; // PJT - quake rockets - timer for quake duration int quake_wait; // PJT - quake rockets - timer for playing sound g_weapon.c Add the following variables to the top of the file, after the #include statement: // PJT - quake rockets cvar_t *sv_qkdelay; // see g_local.h for definitions cvar_t *sv_qkduration; cvar_t *sv_qkradius; cvar_t *sv_qkrichter; // PJTAdd the following new procedure just before the procedure rocket_touch:
// PJT - quake rocket
void rocket_think_quake (edict_t *self)
{
int i;
edict_t *ent;
vec3_t v;
// remove rocket if timer expired
if (level.time > self->quake_timer)
{
G_FreeEdict (ent);
return;
}
// update sound
if (self->quake_wait < level.time)
{
gi.positioned_sound(self->s.origin, self, CHAN_AUTO, gi.soundindex("world/quake.wav"), 1.0, ATTN_NONE, 0);
self->quake_wait = level.time + 0.5;
}
// shake all clients
for(i=0;i < game.maxclients;i++)
{
// retrieve entity
ent=g_edicts+i+1;
// ignore if not active, or in air
if (!G_ClientInGame(ent)) continue;
if (!ent->groundentity) continue;
// ignore if out of range
sv_qkradius = gi.cvar ("sv_qkradius", "1000", 0);
VectorSubtract (ent->s.origin, self->s.origin, v);
if (VectorLength(v) > sv_qkradius->value) continue;
// random velocity
sv_qkrichter = gi.cvar ("sv_qkrichter", "10", 0);
ent->groundentity = NULL;
ent->velocity[0] += crandom()*(sv_qkrichter->value*100);
ent->velocity[1] += crandom()*(sv_qkrichter->value*100);
ent->velocity[2] = (sv_qkrichter->value*100)*(100.0/ent->mass);
}
// next think
self->nextthink = level.time + 0.1;
self->think = rocket_think_quake;
}
// PJT
Add the following new procedure just after the procedure rocket_touch:
// PJT - earthquake rockets
/*
=================
rocket_touch_quake
=================
*/
void rocket_touch_quake (edict_t *ent, edict_t *other, cplane_t *plane, csurface_t *surf)
{
// can damage owner!!
if (other == ent->owner)
return;
// remove if hits sky
if (surf && (surf->flags & SURF_SKY))
{
G_FreeEdict (ent);
return;
}
// normal explosion if hits player
if (other->client)
{
rocket_touch(ent, other, plane, surf);
return;
}
// normal explosion if hots decoy
if (Q_stricmp(other->classname, "decoy") == 0)
{
rocket_touch(ent, other, plane, surf);
return;
}
// Quake Rockets only if activated by real Player..
if (G_EntExists(ent->owner))
{
sv_qkdelay = gi.cvar ("sv_qkdelay", "5", 0);
sv_qkduration = gi.cvar ("sv_qkduration", "10", 0);
VectorClear (ent->velocity);
ent->quake_timer = level.time + sv_qkdelay->value +
sv_qkduration->value +(random()*sv_qkduration->value);
ent->nextthink = level.time + sv_qkdelay->value;
ent->think = rocket_think_quake;
ent->s.sound = 0;
return;
}
G_FreeEdict (ent);
}
// PJT
Insert the earthquake rocket code into procedure fire_rocket, in the code added in the
Nuclear Rocket tutorial, as indicated:
rocket->owner = self;
// PJT - determine rocket type
if (self->client)
{
rocket->touch = rocket_touch;
switch(self->client->pers.nuke_state)
{
case 0: // standard
rocket->touch = rocket_touch;
break;
case 1: // nukes
// nke code here
break;
case 2: // zylon gas
// zylon gas code here
break;
case 3: // positron rockets
// positron rocket code here
break;
// PJT <-- earthquake rocket code starts here
case 4: // PJT - earthquake rockets
rocket->touch = rocket_touch_quake;
rocket->s.renderfx = RF_SHELL_RED + RF_SHELL_GREEN; // make positron rockets yellow
rocket->s.effects |= EF_COLOR_SHELL;
break;
// PJT <-- end of earthquake rocket code
}
}
else
rocket->touch = rocket_touch;
// PJT
p_weapon.c Within procedure Rocket_Count (which was created in the Nuclear Rockets tutorial) insert the earthquake rockets code as indicated:
switch (ent->client->pers.nuke_state)
{
......
case 3:
...
break;
// PJT <-- earthquake rockets code starts here
case 4: // earthquake rockets
count = 10;
break;
// PJT <-- end of insert
}
g_cmds.c Within procedure Cmd_Nukes_f (which was created in the Nuclear Rockets tutorial) insert the earthquake rockets code as indicated:
switch (i)
{
case 0: // standard rockets
.......
case 3: // positron rockets
break;
// PJT <-- eathquake rockets code starts here
case 4: // earthquake rockets
break;
// PJT <-- end of insert
}
cmds.cfg Add the following server commands to your .cfg file: set sv_qkdelay 5 set sv_qkduration 10 set sv_qkradius 1000 set sv_qkrichter 5.0 |
| Notes |
|
|
g_local.h
g_weapon.c
p_weapon.c
g_cmds.c
cmds.cfg
|
| Exercises |
|
|