Author: Geza Beladi
The first part of this tutorial
will have you pointing your laser sight (actually, it's a meat ball) around the map.
The second part will involve you creating a new laser sight 'model'... essentially a
little red dot. So grab a compiler and a model editor before entering.
Preliminaries
Moving the lasersight around
Create a lasersight model
Note for non-MSVC users
And that's it... Thanks again to Geza Beladi for the code.
This site, and all content and graphics displayed on it,
Difficulty: Easy/Medium
Hi there ! SumFuka here, I'm writing up a tutorial for the code that Geza sent in to me,
thanks mate ! This one is interesting and quite fun. Have you ever seen predator ?
Do you remember the part when one of the army guys is hunting the predator, and
then he sees the little red dot moving over his face ? Then the predator blows
him away ? Well... here goes.
Now open up g_cmds.c and edit the very bottom of the file and edit it to look like this : // common data blocks
moveinfo_t moveinfo;
monsterinfo_t monsterinfo;
// STEVE
edict_t *lasersight;
};
void LaserSightThink (edict_t *self);
void SP_LaserSight(edict_t *self);
The big Kahuna else if (Q_stricmp (cmd, "laser") == 0)
SP_LaserSight (ent);
else
gi.cprintf (ent, PRINT_HIGH, "Bad command: %s\n", cmd);
}
Spawning a lasersight entity// laser sight patch, by Geza Beladi
#include "g_local.h"
/*----------------------------------------
SP_LaserSight
Create/remove the laser sight entity
-----------------------------------------*/
#define lss self->lasersight
void SP_LaserSight(edict_t *self) {
vec3_t start,forward,right,end;
if ( lss ) {
G_FreeEdict(lss);
lss = NULL;
gi.bprintf (PRINT_HIGH, "lasersight off.");
return;
}
gi.bprintf (PRINT_HIGH, "lasersight on.");
AngleVectors (self->client->v_angle, forward, right, NULL);
VectorSet(end,100 , 0, 0);
G_ProjectSource (self->s.origin, end, forward, right, start);
lss = G_Spawn ();
lss->owner = self;
lss->movetype = MOVETYPE_NOCLIP;
lss->solid = SOLID_NOT;
lss->classname = "lasersight";
// lss->s.modelindex = gi.modelindex ("put/your/own/model/here.md2");
lss->s.modelindex = gi.modelindex ("models/objects/gibs/sm_meat/tris.md2");
lss->s.skinnum = 0;
lss->s.renderfx |= RF_FULLBRIGHT;
lss->think = LaserSightThink;
lss->nextthink = level.time + 0.1;
}
/*---------------------------------------------
LaserSightThink
Updates the sights position, angle, and shape
tests if the lasersight entity exists. If it does (i.e. lss is not NULL) then
G_FreeEdict is called (which destroys the lasersight model). If it doesn't (lss is NULL)
then a model is created. I have used the sm_meat model (a small meat gib) so that you can
use this patch 'out of the box', but it looks kinda silly. Simply substitute your own
model in this function. The only thing really non-standard here is that the 'nextthink'
function is 0.1 seconds into the future. This means that the 'lasersight' function
is called every 0.1 seconds... probably not very 'net friendly' in a 70 player game,
but hey. if ( lss ) {
Now, the gi.trace function returns a 'trace_t' structure. That means, it returns an array
of stuff describing what happened with the trace, including : AngleVectors (self->owner->client->v_angle, forward, right, up);
VectorSet(offset,24 , 6, self->owner->viewheight-7);
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 is 1.0, we didn't find anything directly in front of us within a range of 8192
units. If tr.fraction is less than 1.0, we did, so we back the endpos back a little so the
lasersight appears just in front of the target (not IN the target).
These lines check to see if the target is a monster or a player, and change to a
different skin if so. This is only applicable if you use your own lasersight model,
and give it a second skin for when a target is aquired. The second line checks that
the entity can take damage (i.e. is not dead) and is not ourselves. if ((tr.ent->svflags & SVF_MONSTER) || (tr.ent->client)){
if ((tr.ent->takedamage) && (tr.ent != self->owner)) {
This lines up the angles of the model to be 'in line' with the target surface,
and finally moves our lasersight (or piece of meat) to the correct position.
The last lines ensure the lasersight will think again, and soon.
vectoangles(tr.plane.normal,self->s.angles);
VectorCopy(tr.endpos,self->s.origin);
are ©opyrighted to the
Quake DeveLS
team. All rights received.
Got a suggestion? Comment? Question? Hate mail?
Send it
to us!
Oh yeah, this site is best viewed in 16 Bit or higher, with the resolution on
800*600.
Thanks to
Planet Quake for there great help and support with hosting.
Best viewed with Netscape
4