Quake Style - Quake 3 Tutorials
New Game Styles - Banning items and setting starting weapons
I think the title sums it up!

This is code for banning weapons, ammo, etc, and also starting weapon code, straight from my beta of MatchMod 2000.

Feel free to alter it or whatever you need to do, so that you can use it - it covers adding cvars and adding a "dmflags type setup".

Here goes ...

Cvars.. gotta love em :)
In game\g_local.h add this to bottom of the vmCvars_t 's:

// banned weapons/items/ammo/runes
extern vmCvar_t	weapflags;
extern vmCvar_t	banned_items;
extern vmCvar_t	ammoflags;
extern vmCvar_t	runeflags;
// starting weapons
extern vmCvar_t	start_weapons;


in game\g_main.c add this to the list of the vmCvar_t 's:

// banned weapons/items/ammo/runes
vmCvar_t	weapflags;
vmCvar_t	banned_items;
vmCvar_t	ammoflags;
vmCvar_t	runeflags;
// starting weapons
vmCvar_t	start_weapons;


Still in game\g_main.c, insert this code in the cvar database: (search for the existing yellow code to find this quickly)

	// banned weapons/items/ammo/runes
	{ &weapflags, "weapflags", "0", 0, 0, qfalse },
	{ &banned_items, "banned_items", "0", 0, 0, qfalse },
	{ &ammoflags, "ammoflags", "0", 0, 0, qfalse },
	{ &runeflags, "runeflags", "0", 0, 0, qfalse },
	// starting weapons
	{ &start_weapons, "start_weapons", "2", 0, 0, qfalse }, // force start with machinegun!
	{ &g_allowVote, "g_allowVote", "1", 0, 0, qfalse }

Now, open up game\g_spawn.c and look in the function qboolean G_CallSpawn( gentity_t *ent ). Add these lines straight after the definitions:

	if (weapflags.integer)
	{
		if ((((int)(weapflags.integer) & 1) && (Q_stricmp(ent->classname, "weapon_gauntlet")==0)) ||
		    (((int)(weapflags.integer) & 2) && (Q_stricmp(ent->classname, "weapon_shotgun")==0)) ||
		    (((int)(weapflags.integer) & 4) && (Q_stricmp(ent->classname, "weapon_grenadelauncher")==0)) ||
		    (((int)(weapflags.integer) & 8) && (Q_stricmp(ent->classname, "weapon_rocketlauncher")==0)) ||
		    (((int)(weapflags.integer) & 16) && (Q_stricmp(ent->classname, "weapon_lightning")==0)) ||
		    (((int)(weapflags.integer) & 32) && (Q_stricmp(ent->classname, "weapon_railgun")==0)) ||
		    (((int)(weapflags.integer) & 64) && (Q_stricmp(ent->classname, "weapon_plasmagun")==0)) ||
		    (((int)(weapflags.integer) & 128) && (Q_stricmp(ent->classname, "weapon_bfg")==0))) 
			return qfalse;
	}

	if (banned_items.integer)
	{
		if ((((int)(banned_items.integer) & 1) && (Q_stricmp(ent->classname, "item_armor_shard")==0)) ||
		    (((int)(banned_items.integer) & 2) && (Q_stricmp(ent->classname, "item_armor_combat")==0)) ||
		    (((int)(banned_items.integer) & 4) && (Q_stricmp(ent->classname, "item_armor_body")==0)) ||
		    (((int)(banned_items.integer) & 8) && (Q_stricmp(ent->classname, "item_health_small")==0)) ||
		    (((int)(banned_items.integer) & 16) && (Q_stricmp(ent->classname, "item_health")==0)) ||
		    (((int)(banned_items.integer) & 32) && (Q_stricmp(ent->classname, "item_health_large")==0)) ||
		    (((int)(banned_items.integer) & 64) && (Q_stricmp(ent->classname, "item_health_mega")==0)) ||
		    (((int)(banned_items.integer) & 128) && (Q_stricmp(ent->classname, "holdable_teleporter")==0)) ||
		    (((int)(banned_items.integer) & 256) && (Q_stricmp(ent->classname, "holdable_medkit")==0)) ||
		    (((int)(banned_items.integer) & 512) && (Q_stricmp(ent->classname, "item_quad")==0)) ||
		    (((int)(banned_items.integer) & 1024) && (Q_stricmp(ent->classname, "item_enviro")==0)))
			return qfalse;
	}
 
	if (ammoflags.integer)
	{
		if ((((int)(ammoflags.integer) & 1) && (Q_stricmp(ent->classname, "ammo_shells")==0)) ||
		    (((int)(ammoflags.integer) & 2) && (Q_stricmp(ent->classname, "ammo_bullets")==0)) ||
		    (((int)(ammoflags.integer) & 4) && (Q_stricmp(ent->classname, "ammo_grenades")==0)) ||
		    (((int)(ammoflags.integer) & 8) && (Q_stricmp(ent->classname, "ammo_cells")==0)) ||
		    (((int)(ammoflags.integer) & 16) && (Q_stricmp(ent->classname, "ammo_lightning")==0)) ||
		    (((int)(ammoflags.integer) & 32) && (Q_stricmp(ent->classname, "ammo_rockets")==0)) ||
		    (((int)(ammoflags.integer) & 64) && (Q_stricmp(ent->classname, "ammo_bfg")==0)))
			return qfalse;
	}
 
	if (runeflags.integer)
	{
		if ((((int)(runeflags.integer) & 1) && (Q_stricmp(ent->classname, "item_haste")==0)) ||
		    (((int)(runeflags.integer) & 2) && (Q_stricmp(ent->classname, "item_invis")==0)) ||
		    (((int)(runeflags.integer) & 4) && (Q_stricmp(ent->classname, "item_regen")==0)) ||
		    (((int)(runeflags.integer) & 8) && (Q_stricmp(ent->classname, "item_flight")==0)))
			return qfalse;
	}


NOTE: You can ban anything you want. Look above, and see each number being checked on the integer value of that particular cvar.

EG's:
If you wanted to ban both the grenade launcher and the lightening gun, you would type "/weapflags 20".
If you wanted to ban quad damage, you would type "/banned_items 512".
If you wanted to ban BFG ammo, you would type "/ammoflags 64".
If you wanted to ban the haste and flight runes, you would type "/runeflags 9".

Hopefully that makes sense. If you see above, you can see each flag being checked on each cvar, just add the number it checks to your cvar and it should be enabled.Well anyway that might not be too helpful, but aslong as you are relatively familiar to the Quake 2 dmflags system, you should get it.

Now, to initialize starting weapons. Add this function above the ClientSpawn function in game\g_client.c:

// Starting Weapons
void CheckStartItems(gentity_t *ent)
{
	gclient_t *client;
	client = ent->client;
 
	if ((int)(start_weapons.integer) & 1) 
	{
		client->ps.stats[STAT_WEAPONS] |= ( 1 << WP_SHOTGUN );
		client->ps.ammo[WP_SHOTGUN] = 10;
	}

	if ((int)(start_weapons.integer) & 2) 
	{
		client->ps.stats[STAT_WEAPONS] |= ( 1 << WP_MACHINEGUN );
		if ( g_gametype.integer == GT_TEAM ) 
			client->ps.ammo[WP_MACHINEGUN] = 50;
		else 
			client->ps.ammo[WP_MACHINEGUN] = 100;
	}

	if ((int)(start_weapons.integer) & 4) 
	{
		client->ps.stats[STAT_WEAPONS] |= ( 1 << WP_GRENADE_LAUNCHER );
		client->ps.ammo[WP_GRENADE_LAUNCHER] = 5;
	}

	if ((int)(start_weapons.integer) & 8) 
	{
		client->ps.stats[STAT_WEAPONS] |= ( 1 << WP_ROCKET_LAUNCHER );
		client->ps.ammo[WP_ROCKET_LAUNCHER] = 5; 
	}

	if ((int)(start_weapons.integer) & 16) 
	{
		client->ps.stats[STAT_WEAPONS] |= ( 1 << WP_LIGHTNING );
		client->ps.ammo[WP_LIGHTNING] = 60; 
	}

	if ((int)(start_weapons.integer) & 32) 
	{
		client->ps.stats[STAT_WEAPONS] |= ( 1 << WP_RAILGUN );
		client->ps.ammo[WP_RAILGUN] = 10; 
	}

	if ((int)(start_weapons.integer) & 64) 
	{
		client->ps.stats[STAT_WEAPONS] |= ( 1 << WP_PLASMAGUN );
		client->ps.ammo[WP_PLASMAGUN] = 30; 
	}

	if ((int)(start_weapons.integer) & 128) 
	{
		client->ps.stats[STAT_WEAPONS] |= ( 1 << WP_BFG );
		client->ps.ammo[WP_BFG] = 15; 
	}
}


Now, in ClientSpawn replace:

	client->ps.stats[STAT_WEAPONS] = ( 1 << WP_MACHINEGUN );
	if ( g_gametype.integer == GT_TEAM ) {
		client->ps.ammo[WP_MACHINEGUN] = 50;
	} else {
		client->ps.ammo[WP_MACHINEGUN] = 100;
	}


With this:

	CheckStartItems(ent);


That's it. Hopefully you can understand how the cvar's work *grin*
If not, well, have a better look. You can proabably see up the top of the code what numbers need to be added to that particular cvar to enable/disable certain things.

If you are running a normal server, make sure "start_weapons" is set to 2, so everybody will start with the machinegun. (everybody will defaultly start with the gauntlet!)

-- Credits:
   Tutorial by RaVeN
   Return to QS Tutorials

-- Important:
   If you do use something from QuakeStyle in your mod, please give us credit.
   Our code is copyrighted, but we give permission to everyone to use it in any way they see fit, as long as we are recognized.