Quake DeveLS - Impulse 69 Revisited

Author: Patrick Wagstrom(Pridkett)
Difficulty: Easy

One would have thought that after all of the fun that Capture The Flag was for Quake that one of the most simple functions from it would have been included in Quake 2, the beloved impulse 69. The command that allowed one key to be pressed to launch a rocket and swap back to whatever weapon was being used before. Well, Quake 2 didn't have one so after about 20 minutes of coding I was able to make this one.

Note:
Text in red = Quake II's code
Text in blue = Our code
Text in gray = Comments

First we open up one of the most useful files in the game: g_cmds.c. This is the file that holds all of the information about commands and what do with them. Then we add a really simple function to the top of the file:


//::Pridkett
/*
===============
int lastWeapon(int)
===============
*/
int lastWeapon(int a)
{
	static int lWeapon;		//Last weapon used
	static int lWeapon2;		//The current weapon
	if (a != -1) {
		lWeapon=lWeapon2;	
		lWeapon2=a;
	}	
	return lWeapon;
}
//!Pridkett

This is the function that is used to store the information on the last weapon. It has two static variables, meaning they stay when the function exits. It takes a parameter and returns another. The parameter is the new weapon. In Quake 2 the weapons are items 7-16. When a value of -1 is passed, it tells the function to retain the current values but return the last weapon used.

Now that this function is done, we make the fucntion actually work. Quake 2 simplified this with the use commmand. So lets look at the section of code that handles that:


/*==================
Cmd_Use_f
Use an inventory item
==================*/
void Cmd_Use_f (edict_t *ent)
{
	int			index;
	gitem_t		*it;
	char		*s;

	s = gi.args();
	it = FindItem (s);
	//::Pridkett
	if (Q_stricmp(s,"prevweap") == 0) 
	{
		it = GetItemByIndex(lastWeapon(-1));
		lastWeapon(ITEM_INDEX(it));
	}
	//!Pridkett
	
	if (!it)
	{
		gi.cprintf (ent, PRINT_HIGH, "unknown item: %s\n", s);
		return;
	}
	index = ITEM_INDEX(it);
	if (!ent->client->pers.inventory[index])
	{
		gi.cprintf (ent, PRINT_HIGH, "Out of item: %s\n", s);
		return;
	}

	it->use (ent, it);

	//::Pridkett
	if (ITEM_INDEX(it) > 6 && ITEM_INDEX(it) < 17 && Q_stricmp(s,"prevweap") != 0) lastWeapon(ITEM_INDEX(it));
	//!Pridkett

}

What this does it is check to see if the string sent was "prevweap" and if it was, then set the g_item "it" to the item that was the last weapon. Then at the bottom is the code that updates the weapons functions. If the index of the g_item "it" is from 7 to 16 and the prevweap command was not called then it updates the lastWeapon variables.

Now we need to make it work for when you are scrolling through your weapons using weapnext and weapprev. So we open those functions and once again have some fun. Find the following section in your Cmd_WeapNext_f and Cmd_WeapPrev_f functions:


	if (cl->pers.weapon == it)
			return;	// successful

And replace both of them with this:


		if (cl->pers.weapon == it) 

		//::Pridkett
		{
			lastWeapon(ITEM_INDEX(it));
			//!Pridkett
			return;	// successful
			
			//::Pridkett
		}
		//!Pridkett

Now you should be able to bind a key to "use prevweap" and the switch two weapons far apart and use only one key to switch back. A nice script could be:

Alias RocketShot "use Rocket Launcher; +attack; wait; use prevweap"

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