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 values
typedef enum
{
MOVETYPE_NONE,		// never moves
MOVETYPE_NOCLIP,		// origin and angles change with no interaction
MOVETYPE_PUSH,		// no clip to world, push on box contact
MOVETYPE_STOP,		// no clip to world, stops on box contact

MOVETYPE_WALK,		// gravity
MOVETYPE_STEP,		// gravity, special edge handling
MOVETYPE_FLY,
MOVETYPE_TOSS,		// gravity
MOVETYPE_FLYMISSILE,	// extra size to monsters
MOVETYPE_BOUNCE,		// STEVE added a comma here
MOVETYPE_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,
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 or IE 3