|
QuakeZone MOD Coding Tutorials
|
|
|
Introduction Pre-requisites Code Notes Exercises |
|
| Introduction |
|
|
Related Links
18 Team Weapon Enhancements Quakestyle's tutorials (for flashlight) Inside3D's tutorials (for auto-aiming) QDevel's tutorials (for wall-piercing railguns) |
This tutorial shows you how to add a laser sight to your weapons. You know the kind of thing, the little red dot that appears on your opponent's chest micro- seconds before you frag them. This is probably very similar to the laser sight tutorial on QDevels, but that uses a small gib model whereas I use the flashlight model with a red glow effect to give a more realistic effect. The observant amongst you will note that this tutorial is extremely similar to Quakestyle's flashlight tutorial, in fact so similar as to be almost identical, and this is indeed the case. This tutorial goes a bit further and adds some enhancements to the laser sight. In team rocket, a rail gun can replace rocket launchers in my team weapon enhancement, and I wanted to make sure I could create corresponding Tech enhancements to the railgun. The "multi" and "accelerator" techs were obvious enough, and were similar changes as I made for rockets. For the "homing" Tech, I made railguns auto-aiming (see Inside3D's tutorial on how to do that). So when homing mode is operative, the laser sight is operative and will land on any opponents standing in front of you. For the "blister" Tech, I implemented the QDevel's wall-piercing railgun. This means that the laser sight can target opponents in front but out of sight, and the red dot appears on the wall indicating their position. Lethal. For team weapon enhancement, I only wanted to make the laser sight work on the railgun.
There is an optional change therefore to show how to activate/de-activate the laser sight when a player
switches team, or the host changes team weapons.
|
| Pre-requisites |
|
|
| Code |
|
|
g_local.h Add the following lines as indicated: 1. Add the following lines to structure client_persistant_t: // PJT - laser sight <-- start of insert qboolean homing_state; // PJT - used to activate laser sight qboolean blister_state; // PJT - used to activate wall piercing (optional) // PJT <-- end of insert 2. Add the following line to the of structure edict_s: edict_t *lasersight; // PJT - auto-aim rail - laser sight p_client.c Add the following lines to the start of player_die:
// PJT - lasersight
if ( self->lasersight )
{
G_FreeEdict(self->lasersight);
self->lasersight = NULL;
}
// PJT
Add the following 2 new procedures to the end of the file. Read the notes in
the comments about activating auto-aiming for the laser sight in lasersight_think:
/*
===============
lasersight_think
===============
*/
void lasersight_think (edict_t *self)
{
vec3_t start,end,endp,offset;
vec3_t forward,right,up;
trace_t tr;
// Note: comment out the following line if auto-aiming is required
AngleVectors (self->owner->client->v_angle, forward, right, up);
// Note: uncomment the following line if auto-aiming is required
// mod_GetLeadoffVec(self->owner, self->owner->s.origin, 5000, 1000, false, forward);
VectorSet(offset,0 , 0, self->owner->viewheight-10);
G_ProjectSource (self->owner->s.origin, offset, forward, right, start);
VectorMA(start,8192,forward,end);
tr = gi.trace (start,NULL,NULL, end,self->owner,CONTENTS_SOLID|CONTENTS_MONSTER|CONTENTS_DEADMONSTER);
if (tr.fraction != 1)
{
VectorMA(tr.endpos,-4,forward,endp);
VectorCopy(endp,tr.endpos);
}
if ((tr.ent->svflags & SVF_MONSTER) || (tr.ent->client))
{
if ((tr.ent->takedamage) && (tr.ent != self->owner))
{
self->s.skinnum = 1;
}
}
else
self->s.skinnum = 0;
vectoangles(tr.plane.normal,self->s.angles);
VectorCopy(tr.endpos,self->s.origin);
gi.linkentity (self);
self->nextthink = level.time + 0.1;
}
/*
===============
lasersight_make
===============
*/
void lasersight_make(edict_t *self)
{
vec3_t start,forward,right,end;
if ( self->lasersight )
{
G_FreeEdict(self->lasersight);
self->lasersight = NULL;
return;
}
AngleVectors (self->client->v_angle, forward, right, NULL);
VectorSet(end,100 , 0, 0);
G_ProjectSource (self->s.origin, end, forward, right, start);
self->lasersight = G_Spawn ();
self->lasersight->owner = self;
self->lasersight->movetype = MOVETYPE_NOCLIP;
self->lasersight->solid = SOLID_NOT;
self->lasersight->classname = "lasersight";
self->lasersight->s.modelindex = gi.modelindex ("models/objects/flash/tris.md2");
self->lasersight->s.skinnum = 0;
self->lasersight->s.renderfx = RF_SHELL_RED; // make positron rockets red.
self->lasersight->s.effects |= EF_COLOR_SHELL;
self->lasersight->s.effects |= 0x10000000;//transparency
// self->flashlight->s.effects |= EF_HYPERBLASTER; // original flashlight tutorial
self->lasersight->think = lasersight_think;
self->lasersight->nextthink = level.time + 0.1;
}
// PJT
If you have installed the team weapon mode, add the following lines to the end
of procedure AssignWeapon:
// PJT rail laser sight
// 1. deactivate for rocket teams
if ( (self->client->resp.teamrail == 0) && self->lasersight )
{
G_FreeEdict(self->lasersight);
self->lasersight = NULL;
return;
}
// 2. activate for rail teams if required
if ( (self->client->resp.teamrail == 1) && self->client->pers.homing_state && !self->lasersight)
lasersight_make(self);
// PJT
g_cmds.c Add the following lines to ClientCommand as indicated: // PJT - enable laser sight <-- start of insert else if (Q_stricmp (cmd, "homing") == 0) Cmd_Homing_f (ent); // PJT <-- end of insert // PJT - enable wall piercing <-- start of insert (optional) else if (Q_stricmp (cmd, "blister_on") == 0) Cmd_Blister_on_f (ent); // PJT <-- end of insertThen insert the following new procedures:
//PJT - activate auto-aiming
/*
=================
Cmd_Homing_f
CCH: whole new function for adjusting homing missile state
=================
*/
void Cmd_Homing_f (edict_t *ent)
{
int i;
// uncomment following lines if yuo need a pick-up first
// PJT - tech pickups
// if (!ent->client->pers.inventory[ITEM_INDEX(FindItem("Homing Tech"))])
// {
// gi.cprintf (ent, PRINT_HIGH, "Homing Tech required.\n");
// return;
// }
// PJT
i = ent->client->pers.homing_state;
switch (i)
{
case 1:
ent->client->pers.homing_state = 0;
break;
case 0:
default:
ent->client->pers.homing_state = 1;
break;
}
// PJT - rail homing laser sight
if (ent->client->resp.teamrail == 1)
lasersight_make(ent);
// PJT
}
// PJT
//PJT activate wall-piercing railgun
/*
=================
Cmd_Blister_on_f
PJT: whole new function for adjusting blister missile state
=================
*/
void Cmd_Blister_on_f (edict_t *ent)
{
int i;
// uncomment following lines if yuo require a pick-up first
// PJT - tech pickups
//if (!ent->client->pers.inventory[ITEM_INDEX(FindItem("Blister tech"))])
//{
// gi.cprintf (ent, PRINT_HIGH, "Blister Tech required.\n");
// return;
//}
// PJT
i = ent->client->pers.blister_state;
switch (i)
{
case 1:
ent->client->pers.blister_state = 0;
break;
case 0:
default:
ent->client->pers.blister_state = 1;
break;
}
}
// PJT
p_weapon.c If you have implemented Inside3D's auto-aiming tutorial, and have also added wall piercing slugs, amend procedure mod_GetLeadoffVec as follows:
while (other) { // PJT <-- locate this line
// PJT following line amended
if (((other->svflags & SVF_MONSTER) || (strcmp(other->classname, "LaserDrone") == 0) || other->client)
&& other->health>0 && other!=self) { /*might have to modify these*/
// PJT - target out of sight opponents for wall-piercing railgun
if (infront(self, other))
if ( (visible(self, other) && !self->client->pers.blister_state) ||
self->client->pers.blister_state)
{
// PJT
|
| Notes |
|
|
g_local.h
p_client.c
g_cmds.c
p_weapon.c
|
| Exercises |
|
|