
Quake DeveLS - Bouncy Gun
Author: SumFuka
Difficulty: Easy
Do you remember in star
wars when Luke and Han and Chewy have just rescued Princess Leia and they are
in the garbage compactor ? Then Han fires a blaster at the door but it
richochets around the room, bouncing from wall to wall ? Can you see where I'm
coming from ?
![]()
Triple blaster bolts, ricocheting off walls.
(Just call this the Corridor Of Death...)
A new
movetype: 'MOVETYPE_FLYRICOCHET'
First we're going to add a
new 'MOVETYPE'. Lets call it MOVETYPE_FLYRICOCHET. Open up g_local.h and change
the 'typedef enum' structure starting on line 166 (which defines all the
movetypes) to look like below :
// edict->movetype valuestypedef enum{MOVETYPE_NONE, // never movesMOVETYPE_NOCLIP, // origin and angles change with no interactionMOVETYPE_PUSH, // no clip to world, push on box contactMOVETYPE_STOP, // no clip to world, stops on box contact MOVETYPE_WALK, // gravityMOVETYPE_STEP, // gravity, special edge handlingMOVETYPE_FLY,MOVETYPE_TOSS, // gravityMOVETYPE_FLYMISSILE, // extra size to monstersMOVETYPE_BOUNCE, // STEVE added a comma hereMOVETYPE_FLYRICOCHET // STEVE added this so bolts can bounce off walls !} movetype_t;
Changing the blaster bolt behaviour.
Now open up g_weapon.c.
Man I love this file. Go to line 305 and find this section of code :
gi.WriteByte (svc_temp_entity); gi.WriteByte (TE_BLASTER); gi.WritePosition (self->s.origin); if (!plane) gi.WriteDir (vec3_origin); else gi.WriteDir (plane->normal); gi.multicast (self->s.origin, MULTICAST_PVS);
Now add a
'return;' ABOVE that section of code, it should look something like this :
// STEVE: return here, we don't want the blast to die when it hits a wall... return; // code below not used : gi.WriteByte (svc_temp_entity); gi.WriteByte (TE_BLASTER); gi.WritePosition (self->s.origin); if (!plane) gi.WriteDir (vec3_origin); else gi.WriteDir (plane->normal); gi.multicast (self->s.origin, MULTICAST_PVS);
Now find
the fire_blaster function and change line 330 from this :
bolt->movetype = MOVETYPE_FLYMISSILE;
to this :
bolt->movetype = MOVETYPE_FLYRICOCHET;
Changing
the game physics: 'MOVETYPE_FLYRICOCHET'
Open g_phys.c and go to
line 675. Change this :
// add gravity if (ent->movetype != MOVETYPE_FLY && ent->movetype != MOVETYPE_FLYMISSILE SV_AddGravity (ent);
to this :
// add gravity if (ent->movetype != MOVETYPE_FLY && ent->movetype != MOVETYPE_FLYMISSILE && ent->movetype != MOVETYPE_FLYRICOCHET) // STEVE SV_AddGravity (ent);
That ensures that gravity
does not affect things that are 'MOVETYPE_FLYRICOCHET' Now on line 692 change
this :
if (ent->movetype == MOVETYPE_BOUNCE) backoff = 1.5; else backoff = 1;
to this :
if (ent->movetype == MOVETYPE_FLYRICOCHET) backoff = 2; //steve else if (ent->movetype == MOVETYPE_BOUNCE) backoff = 1.5; else backoff = 1;
We are
saying here that a missile of type 'fly ricochet' will bounce off walls with
equal and opposite velocity (in contrast to a grenade which, for example,
bounces off a wall with half off it's previous velocity).
Making the
bolt face the direction it travels
Now find line 700 that
looks like this :
ClipVelocity (ent->velocity, trace.plane.normal, ent->velocity, backoff);
and insert
these lines below it :
// STEVE... added this part to re-align the entity's angles after
// it bounces off a wall. Simply set its angles to its velocity vector. if (ent->movetype == MOVETYPE_FLYRICOCHET) { vectoangles (ent->velocity, ent->s.angles); }
This step
ensures that when a blaster bolt (which is movetype 'MOVETYPE_FLYRICOCHET')
bounces off a wall, the bolt actually faces the direction it is now travelling.
Bolts look VERY strange when they bounce backwards off a wall and are pointed
at weird angles !
Now go to line 709 and
change this :
if (trace.plane.normal[2] > 0.7 )
{ if (ent->velocity[2] < 60 || ent->movetype != MOVETYPE_BOUNCE ) { ent->groundentity = trace.ent; ent->groundentity_linkcount = trace.ent->linkcount; VectorCopy (vec3_origin, ent->velocity); VectorCopy (vec3_origin, ent->avelocity); } }
to this :
// stop if on ground STEVE changed next line so bolts dont 'stop' on the ground
if (trace.plane.normal[2] > 0.7 && ent->movetype != MOVETYPE_FLYRICOCHET) { if (ent->velocity[2] < 60 || ent->movetype != MOVETYPE_BOUNCE ) { ent->groundentity = trace.ent; ent->groundentity_linkcount = trace.ent->linkcount; VectorCopy (vec3_origin, ent->velocity); VectorCopy (vec3_origin, ent->avelocity); } }
The 'if
(trace.plane.normal[2] > 0.7)' bit is designed to detect if a missile object
(such as a grenade) is bouncing at an angle that is very close to the floor.
Watch when you throw a grenade, and it will bounce 2 or 3 times, then come to
rest. This code is what makes the grenade stop moving and sit still on the
ground (rather than bouncing infinitely with smaller and smaller bounces).
Anyway with this effect on our blaster bolts 'stick' to the walls if they hit
the wall at a very small angle. We turn this off with the '&&
ent->movetype != MOVETYPE_FLYRICOCHET' bit.
One last
thing...
Still in g_phys.c, go to
the G_RunEntity function. Change this section of code :
case MOVETYPE_TOSS: case MOVETYPE_BOUNCE: case MOVETYPE_FLY: case MOVETYPE_FLYMISSILE: SV_Physics_Toss (ent); break;
to look
like this :
case MOVETYPE_TOSS: case MOVETYPE_BOUNCE: case MOVETYPE_FLY: case MOVETYPE_FLYMISSILE: case MOVETYPE_FLYRICOCHET: // New SV_Physics_Toss (ent); break;
That
simply adds our new missile type to the physics processing code, without doing
this the game would complain about an 'invalid movement type'.
Rock and
Roll(tm) !
Now you can shoot around
corners... cool eh ? Take the HyperBlaster and go for a ride in godmode.
Next week... Lets play
'laser tag', but with real lasers...
Tutorial by SumFuka
|
This
site, and all content and graphics displayed on it, |