Okay, what we are going to be doing:
1. Overhauling the Weapon System to slightly resemble the one from
Half-Life.
2. This is largly a cut-and-paste tutorial. If you want to learn
from this, I suggest you have a least a basic understanding of
QuakeC, then you should be able to see what's going on in the code.
What advantage will this give us?
2. The ability to have up to a total of about 24 different
weapons. (8 categories are supported by the regular iD1 quake HUD)
This should be enough for even the most gun heavy mod, if you need
even more than this, you may want to consider implimenting altfires.
The downsides?
1. Console give cheat doesn't work on weapons.
(Will still work for ammo and health though)
2. Frikbot will require some modification to it's weapon handling
code for it to use them right. (this goes without saying anyway)
For the purposes of this tutorial, I will only explain the bare minimum needed.
Also note that this code follows a sort of Half-Life
weapon categories system. (i.e. weapons belong to a group)
You will have to provide your own gfx and whatnot to set the hud up
the way you want. (i.e. handgun group, shotgun group, etc.)
Start with Progs106 source code.
In Defs.qc at the very bottom add:
Code: Select all
.float weapon2;
.float items3;
float IT3_AXE = 1;
float IT3_SHOTGUN = 2;
float IT3_SUPER_SHOTGUN = 4;
float IT3_NAILGUN = 8;
float IT3_SUPER_NAILGUN = 16;
float IT3_GRENADE_LAUNCHER = 32;
float IT3_ROCKET_LAUNCHER = 64;
float IT3_LIGHTNING = 128;
float IT3_NEWWEAPON = 256;
// Additional bitflags availible
float IT3_NEWWEAPON2 = 512;
float IT3_NEWWEAPON3 = 1024;
float IT3_NEWWEAPON4 = 2048;
float IT3_NEWWEAPON5 = 4096;
float IT3_NEWWEAPON6 = 8192;
float IT3_NEWWEAPON7 = 16384;
float IT3_NEWWEAPON8 = 32768;
float IT3_NEWWEAPON9 = 65536;
float IT3_NEWWEAPON10 = 131072;
float IT3_NEWWEAPON11 = 262144;
float IT3_NEWWEAPON12 = 524288;
float IT3_NEWWEAPON13 = 1048576;
float IT3_NEWWEAPON14 = 2097152;
float IT3_NEWWEAPON15 = 4194304;
float IT3_NEWWEAPON16 = 8388608;
Note that I have redundantly defined the original eight weapons here
in addition to a new one for use with the new system. This is
because there may be instances where you could pick up a new weapon
that belongs to a certain category, but the icon for the group would
never show up on your HUD unless you had the first weapon of the
group already!
Now, .float weapon2 will allow us to store whether or not we are
currently using our new weapon. (or even the original weapons!)
We will use a spawnparm for this later so that quake will remember
for us whether or not the IT3_NEWWEAPON was selected.
We will assume for this tutorial that IT3_NEWWEAPON belongs to the
super shotgun group. (Even though it will be a copy of the nailgun.)
.float items3 will allow us to store whether or not we have said
old / new weapon(s). This will use a spawnparm for level changes.
float IT3_NEWWEAPON = 256 defines what bit said weapon will have in
storage.
Feel free to rename any or all of the *_NEWWEAPON** bitflags defined
above for your new weapons once you have a proper understanding of
this tutorial.
Now, save defs.qc and open client.qc.
At the bottom of SetChangeParms add:
Code: Select all
parm10 = self.items3; // items3
parm11 = self.weapon2; // remember what weapon you use between levels
Code: Select all
parm10 = IT3_SHOTGUN | IT3_AXE;
parm11 = IT3_SHOTGUN | IT3_AXE;
Code: Select all
self.items3 = parm10;
self.weapon2 = parm11;
NOTE: You will need to modify ClientObituary later to properly print
player obituaries when being killed with a weapon. This exercise is
left up to the reader.
Save client.qc, open weapons.qc.
Go to W_FireSpikes and replace this:
Code: Select all
if (self.ammo_nails >= 2 && self.weapon == IT_SUPER_NAILGUN)
Code: Select all
if (self.ammo_nails >= 2 && self.weapon == IT_SUPER_NAILGUN &&
(self.weapon2 & IT_SUPER_NAILGUN))
This is a fix for the SNG to ensure that if we ever put any new
weapons into the SNG category that might use nails, it won't eat
two rounds of ammo a pop unless it really IS the SNG being used.
Go to W_SetCurrentAmmo and replace the whole function with the following:
Code: Select all
void() W_SetCurrentAmmo =
{
player_run (); // get out of any weapon firing states
self.items = self.items - ( self.items & (IT_SHELLS | IT_NAILS | IT_ROCKETS | IT_CELLS) );
if (self.weapon == IT_AXE)
{
// Check to see what weapon we are using in this subcategory.
// Note that this is the only weapon here.
if(self.weapon2 & IT3_AXE)
{
self.currentammo = 0;
self.weaponmodel = "progs/v_axe.mdl";
self.weaponframe = 0;
}
}
else if (self.weapon == IT_SHOTGUN)
{
// Check to see what weapon we are using in this subcategory.
// Again only weapon here.
if(self.weapon2 & IT3_SHOTGUN)
{
self.currentammo = self.ammo_shells;
self.weaponmodel = "progs/v_shot.mdl";
self.weaponframe = 0;
self.items = self.items | IT_SHELLS;
}
}
else if (self.weapon == IT_SUPER_SHOTGUN)
{
// Check to see what weapon we are using in this subcategory.
// Note that this group is what IT3_NEWWEAPON belongs to.
if(self.weapon2 & IT3_SUPER_SHOTGUN)
{
self.currentammo = self.ammo_shells;
self.weaponmodel = "progs/v_shot2.mdl";
self.weaponframe = 0;
self.items = self.items | IT_SHELLS;
}
else if(self.weapon2 & IT3_NEWWEAPON) // This is new weapon
{
self.currentammo = self.ammo_nails;
self.weaponmodel = "progs/v_nail.mdl";
self.weaponframe = 0;
self.items = self.items | IT_NAILS;
}
}
else if (self.weapon == IT_NAILGUN)
{
// Check to see what weapon we are using in this subcategory.
// This like the melee and low tier group, this is the only
// weapon here.
if(self.weapon2 & IT3_NAILGUN)
{
self.currentammo = self.ammo_nails;
self.weaponmodel = "progs/v_nail.mdl";
self.weaponframe = 0;
self.items = self.items | IT_NAILS;
}
}
else if (self.weapon == IT_SUPER_NAILGUN)
{
// Check to see what weapon we are using in this subcategory.
// There are more to go...
if(self.weapon2 & IT3_SUPER_NAILGUN)
{
self.currentammo = self.ammo_nails;
self.weaponmodel = "progs/v_nail2.mdl";
self.weaponframe = 0;
self.items = self.items | IT_NAILS;
}
}
else if (self.weapon == IT_GRENADE_LAUNCHER)
{
// Check to see what weapon we are using in this subcategory.
// Only two more to go...
if(self.weapon2 & IT3_GRENADE_LAUNCHER)
{
self.currentammo = self.ammo_rockets;
self.weaponmodel = "progs/v_rock.mdl";
self.weaponframe = 0;
self.items = self.items | IT_ROCKETS;
}
}
else if (self.weapon == IT_ROCKET_LAUNCHER)
{
// Check to see what weapon we are using in this subcategory.
// Only one more to go...
if(self.weapon2 & IT3_ROCKET_LAUNCHER)
{
self.currentammo = self.ammo_rockets;
self.weaponmodel = "progs/v_rock2.mdl";
self.weaponframe = 0;
self.items = self.items | IT_ROCKETS;
}
}
else if(self.weapon == IT_LIGHTNING)
{
// Check to see what weapon we are using in this subcategory.
// Sequence completed!
if(self.weapon2 & IT3_LIGHTNING)
{
self.currentammo = self.ammo_cells;
self.weaponmodel = "progs/v_light.mdl";
self.weaponframe = 0;
self.items = self.items | IT_CELLS;
}
}
else
{
self.currentammo = 0;
self.weaponmodel = "";
self.weaponframe = 0;
}
};
selected your old / new weapon(s). Read the comments, they should be
fairly self explanatory.
Next go to W_BestWeapon and replace with this:
Code: Select all
float() W_BestWeapon =
{
local float it;
// since .items3 is where all weapons are held check that instead.
it = self.items3;
if (self.waterlevel <= 1 && self.ammo_cells >= 1 && (it & IT3_LIGHTNING) )
{
// Set lightning gun as weapon to use.
self.weapon2 = self.weapon2 | IT3_LIGHTNING;
// Sets lightning group (exotic) icon as active.
return IT_LIGHTNING;
}
if(self.ammo_nails >= 2 && (it & IT3_SUPER_NAILGUN) )
{
// Set SNG as weapon to use.
self.weapon2 = self.weapon2 | IT3_SUPER_NAILGUN;
// Sets SNG (Heavy weapons / minigun) Group icon as active.
return IT_SUPER_NAILGUN;
}
if(self.ammo_nails >= 1 && (it & IT3_NAILGUN) )
{
// Set Nailgun as weapon to use
self.weapon2 = self.weapon2 | IT3_NAILGUN;
// Set NG (Machinegun / Assault Rifle) Group icon as active.
return IT_NAILGUN;
}
// new weapon takes priority over SSG if nails are present.
if(self.ammo_nails >= 1 && (it & IT3_NEWWEAPON) )
{
// Set new weapon as weapon to use
self.weapon2 = self.weapon2 | IT3_NEWWEAPON;
// Because new weapon is part of SSG Group,
// set SSG (Shotgun / FlakCannon) group icon as active
return IT_SUPER_SHOTGUN;
}
if(self.ammo_shells >= 2 && (it & IT3_SUPER_SHOTGUN) )
{
// Set Super Shotgun as weapon to use
self.weapon2 = self.weapon2 | IT3_SUPER_SHOTGUN;
// Set SSG (Shotgun / FlakCannon) group icon as active
return IT_SUPER_SHOTGUN;
}
if(self.ammo_shells >= 1 && (it & IT3_SHOTGUN) )
{
// Set Shotgun as weapon to use
self.weapon2 = self.weapon2 | IT3_SHOTGUN;
// Set Wimpy (Pistol / .410 Shotshell) group icon as active.
return IT_SHOTGUN;
}
// If none of the above, set to Axe as weapon to use.
self.weapon2 = self.weapon2 | IT3_AXE;
// Set Axe (melee) group icon as active...Or rather, that's what
// I'd like to say. Melee doesn't HAVE a group icon on the HUD!
return IT_AXE;
};
Move on to W_CheckNoAmmo and change this:
Code: Select all
if (self.weapon == IT_AXE)
return TRUE;
Code: Select all
// Fix to ensure that any ammo based melees are properly caught
if (self.weapon == IT_AXE && (self.weapon2 & IT3_AXE))
return TRUE;
melee weapon ammo.
Now go to W_Attack and replace with this:
Code: Select all
void() W_Attack =
{
local float r;
if (!W_CheckNoAmmo ())
return;
makevectors (self.v_angle); // calculate forward angle for velocity
self.show_hostile = time + 1; // wake monsters up
if (self.weapon == IT_AXE)
{
// Check to see if your using the axe, if so...AX ATTACK!!11!!
if(self.weapon2 & IT3_AXE)
{
sound (self, CHAN_WEAPON, "weapons/ax1.wav", 1, ATTN_NORM);
r = random();
if (r < 0.25)
player_axe1 ();
else if (r<0.5)
player_axeb1 ();
else if (r<0.75)
player_axec1 ();
else
player_axed1 ();
self.attack_finished = time + 0.5;
}
}
else if (self.weapon == IT_SHOTGUN)
{
// Don't get to excited. After all, this shotgun seems so weak
// that you could have it misfire in your face several times
// and only leave you with a small cut on your face. =P
if(self.weapon2 & IT3_SHOTGUN)
{
player_shot1 ();
W_FireShotgun ();
self.attack_finished = time + 0.5;
}
}
else if (self.weapon == IT_SUPER_SHOTGUN)
{
// The only *real* shotgun in Quake, IMO. And then only just
// barely. =P
if(self.weapon2 & IT3_SUPER_SHOTGUN)
{
player_shot1 ();
W_FireSuperShotgun ();
self.attack_finished = time + 0.7;
}
else if(self.weapon2 & IT3_NEWWEAPON) // If using New Weapon, fire!
{
// Nailgun redundancy. What? You expected something fancy?
player_nail1();
}
}
else if (self.weapon == IT_NAILGUN)
{
// Wimpy pincushion gun. AKA Shambler tickler.
if(self.weapon2 & IT3_NAILGUN)
{
player_nail1 ();
}
}
else if (self.weapon == IT_SUPER_NAILGUN)
{
// More dangerous pincushion gun. Decent if it held more ammo.
if(self.weapon2 & IT3_SUPER_NAILGUN)
{
player_nail1 ();
}
}
else if (self.weapon == IT_GRENADE_LAUNCHER)
{
// Finally something decent.
if(self.weapon2 & IT3_GRENADE_LAUNCHER)
{
player_rocket1();
W_FireGrenade();
self.attack_finished = time + 0.6;
}
}
else if (self.weapon == IT_ROCKET_LAUNCHER)
{
// Groovy.
if(self.weapon2 & IT3_ROCKET_LAUNCHER)
{
player_rocket1();
W_FireRocket();
self.attack_finished = time + 0.8;
}
}
else if (self.weapon == IT_LIGHTNING)
{
// The famous "don't use while taking a bath" gun. XD
if(self.weapon2 & IT3_LIGHTNING)
{
player_light1();
self.attack_finished = time + 0.1;
sound (self, CHAN_AUTO, "weapons/lstart.wav", 1, ATTN_NORM);
}
}
};
after all.

Replace W_ChangeWeapon with this:
Code: Select all
void() W_ChangeWeapon =
{
local float it, am, fl, fl2;
// As with bestweapon, check .items3 NOT .items.
it = self.items3;
am = 0;
if (self.impulse == 1)
{
// melee category
fl = IT_AXE;
// Chop Chop.
fl2 = IT3_AXE;
}
else if (self.impulse == 2)
{
// Wimpy Category
fl = IT_SHOTGUN;
// reach out and tickle somebody.
fl2 = IT3_SHOTGUN;
// if no shells, no tickle.
if (self.ammo_shells < 1)
am = 1;
}
else if (self.impulse == 3)
{
// Note that we check here because there's more than one weapon here!
// First if we are already using the super shotgun, change to our
// new weapon!
if((self.weapon2 & IT3_SUPER_SHOTGUN) && self.weapon == IT_SUPER_SHOTGUN)
{
// remove the super shotgun bit from weapon2.
if(self.items3 & IT3_NEWWEAPON)
self.weapon2 = self.weapon2 - (self.weapon2 & IT3_SUPER_SHOTGUN);
// Shotgun / FlakCannon group.
fl = IT_SUPER_SHOTGUN;
// Nailgun. Yeah yeah, I'm lazy.
fl2 = IT3_NEWWEAPON;
// No nails, no prickly from newweapon.
if (self.ammo_nails < 1)
am = 1;
}
else if((self.weapon2 & IT3_NEWWEAPON) && self.weapon == IT_SUPER_SHOTGUN)
{
// Shotgun / FlakCannon group.
fl = IT_SUPER_SHOTGUN;
// Boomstick, never get sucked into a strange time portal without it.
fl2 = IT3_SUPER_SHOTGUN;
// Needs two shells for happy time.
if (self.ammo_shells < 2)
am = 1;
}
else if(self.weapon2 & IT3_NEWWEAPON)
{
// Shotgun / FlakCannon group.
fl = IT_SUPER_SHOTGUN;
// Nailgun. Yeah yeah, I'm lazy.
fl2 = IT3_NEWWEAPON;
// No nails, no prickly from newweapon.
if (self.ammo_nails < 1)
am = 1;
}
else
{
// Shotgun / FlakCannon group.
fl = IT_SUPER_SHOTGUN;
// Boomstick, never get sucked into a strange time portal without it.
fl2 = IT3_SUPER_SHOTGUN;
// Needs two shells for happy time.
if (self.ammo_shells < 2)
am = 1;
}
}
else if (self.impulse == 4)
{
// Machinegun group
fl = IT_NAILGUN;
// Lesser Pricklegun
fl2 = IT3_NAILGUN;
// Mmmm, Pointy.
if (self.ammo_nails < 1)
am = 1;
}
else if (self.impulse == 5)
{
// Heavy / Minigun group
fl = IT_SUPER_NAILGUN;
// Greater Pricklegun
fl2 = IT3_SUPER_NAILGUN;
// Loves to eat ammo like popcorn
if (self.ammo_nails < 2)
am = 1;
}
else if (self.impulse == 6)
{
// Explosives group
fl = IT_GRENADE_LAUNCHER;
// Grenade. Wonder if it's legal for deer hunting?.
fl2 = IT3_GRENADE_LAUNCHER;
// No rockets, no boom.
if (self.ammo_rockets < 1)
am = 1;
}
else if (self.impulse == 7)
{
// Anti-Tank Heavy Weapons group
fl = IT_ROCKET_LAUNCHER;
// "Oh boy! It's Clobberin' time!" - Duke Nukem, ZER0:H0UR
fl2 = IT3_ROCKET_LAUNCHER;
// Please use only specified factory rocket ammo for best results.
if (self.ammo_rockets < 1)
am = 1;
}
else if (self.impulse == 8)
{
// Lightning (Exotic) group
fl = IT_LIGHTNING;
// How DOES the quakeguy carry around all those heavy car batteries? =P
fl2 = IT3_LIGHTNING;
// God this thing must suck energy down like crazy.
if (self.ammo_cells < 1)
am = 1;
}
self.impulse = 0;
if (!(self.items3 & fl2))
{ // don't have the weapon or the ammo
sprint (self, "no weapon. \n");
return;
}
if (am)
{ // don't have the ammo
sprint (self, "not enough ammo. \n");
return;
}
//
// set weapon, set ammo
//
self.weapon = fl;
self.weapon2 = self.weapon2 | fl2;
W_SetCurrentAmmo ();
};
CycleWeaponCommand and CycleWeaponReverseCommand with the following:
Code: Select all
void() CheatCommand =
{
if (deathmatch || coop)
return;
self.ammo_rockets = 100;
self.ammo_nails = 200;
self.ammo_shells = 100;
self.ammo_cells = 200;
self.items = self.items |
IT_AXE |
IT_SHOTGUN |
IT_SUPER_SHOTGUN |
IT_NAILGUN |
IT_SUPER_NAILGUN |
IT_GRENADE_LAUNCHER |
IT_ROCKET_LAUNCHER |
IT_LIGHTNING |
IT_KEY1 | IT_KEY2;
self.items3 = self.items3 |
IT3_AXE |
IT3_SHOTGUN |
IT3_SUPER_SHOTGUN |
IT3_NAILGUN |
IT3_SUPER_NAILGUN |
IT3_GRENADE_LAUNCHER |
IT3_ROCKET_LAUNCHER |
IT3_LIGHTNING |
IT3_NEWWEAPON;
self.weapon = IT_ROCKET_LAUNCHER;
self.weapon2 = self.weapon2 | IT3_ROCKET_LAUNCHER;
self.impulse = 0;
W_SetCurrentAmmo ();
};
/*
============
CycleWeaponCommand
Go to the next weapon with ammo
============
*/
void() CycleWeaponCommand =
{
local float it, am, wp;
// Check items3 instead of items.
it = self.items3;
self.impulse = 0;
while (1)
{
am = 0;
// Only one weapon in this group. See SSG Group for
// multiple weapons in a group.
if (self.weapon == IT_LIGHTNING)
{
// up a category.
self.weapon = IT_AXE;
// This sets RL
self.weapon2 = self.weapon2 | IT3_AXE;
// weapon to check for
wp = IT3_AXE;
}
else if (self.weapon == IT_ROCKET_LAUNCHER)
{
self.weapon = IT_LIGHTNING;
self.weapon2 = self.weapon2 | IT3_LIGHTNING;
wp = IT3_LIGHTNING;
if (self.ammo_cells < 1)
am = 1;
}
else if (self.weapon == IT_GRENADE_LAUNCHER)
{
// See above.
self.weapon = IT_ROCKET_LAUNCHER;
// I'm gonna quit typing these now.
self.weapon2 = self.weapon2 = IT3_ROCKET_LAUNCHER;
// weapon to check for
wp = IT3_ROCKET_LAUNCHER;
if (self.ammo_rockets < 1)
am = 1;
}
else if (self.weapon == IT_SUPER_NAILGUN)
{
self.weapon = IT_GRENADE_LAUNCHER;
self.weapon2 = IT3_GRENADE_LAUNCHER;
wp = IT3_GRENADE_LAUNCHER;
if (self.ammo_rockets < 1)
am = 1;
}
else if (self.weapon == IT_NAILGUN)
{
self.weapon = IT_SUPER_NAILGUN;
self.weapon2 = self.weapon2 | IT3_SUPER_NAILGUN;
wp = IT3_SUPER_NAILGUN;
if(self.ammo_nails < 2)
am = 1;
}
else if (self.weapon == IT_SUPER_SHOTGUN)
{
// Okay, lets check to see if we gots IT3_NEWWEAPON
if((it & IT3_NEWWEAPON) && !(self.weapon2 & IT3_NEWWEAPON))
{
self.weapon = IT_SUPER_SHOTGUN;
if(self.weapon2 & IT3_SUPER_SHOTGUN)
self.weapon2 = self.weapon2 - (self.weapon2 & IT3_SUPER_SHOTGUN);
self.weapon2 = self.weapon2 | IT3_NEWWEAPON;
wp = IT3_NEWWEAPON;
if(self.ammo_nails < 1)
am = 1;
}
else // if not then try nailgun.
{
self.weapon = IT_NAILGUN;
self.weapon2 = self.weapon2 | IT3_NAILGUN;
wp = IT3_NAILGUN;
if (self.ammo_nails < 1)
am = 1;
}
}
else if (self.weapon == IT_SHOTGUN)
{
self.weapon = IT_SUPER_SHOTGUN;
// Okay, lets check to see if we gots IT3_NEWWEAPON
// if so, clear the bit so we can go for SSG.
if(self.weapon2 & IT3_NEWWEAPON)
self.weapon2 = self.weapon2 - (self.weapon2 & IT3_NEWWEAPON);
self.weapon2 = self.weapon2 | IT3_SUPER_SHOTGUN;
wp = IT3_SUPER_SHOTGUN;
if(self.ammo_shells < 2)
am = 1;
}
else if (self.weapon == IT_AXE)
{
self.weapon = IT_SHOTGUN;
self.weapon2 = self.weapon2 | IT3_SHOTGUN;
wp = IT3_SHOTGUN;
if (self.ammo_shells < 1)
am = 1;
}
if ( (it & wp) && am == 0)
{
W_SetCurrentAmmo ();
return;
}
}
};
/*
============
CycleWeaponReverseCommand
Go to the prev weapon with ammo
============
*/
void() CycleWeaponReverseCommand =
{
local float it, am, wp;
// Check items3 instead of items.
it = self.items3;
self.impulse = 0;
while (1)
{
am = 0;
// Only one weapon in this group. See SSG Group for
// multiple weapons in a group.
if (self.weapon == IT_LIGHTNING)
{
// Down a category.
self.weapon = IT_ROCKET_LAUNCHER;
// This sets RL
self.weapon2 = self.weapon2 | IT3_ROCKET_LAUNCHER;
// weapon to check for
wp = IT3_ROCKET_LAUNCHER;
// Don't forget to check for ammo.
if (self.ammo_rockets < 1)
am = 1;
}
else if (self.weapon == IT_ROCKET_LAUNCHER)
{
// Down yet another category
self.weapon = IT_GRENADE_LAUNCHER;
// This sets GL
self.weapon2 = self.weapon2 | IT3_GRENADE_LAUNCHER;
// weapon to check for
wp = IT3_GRENADE_LAUNCHER;
// Need Ammos.
if (self.ammo_rockets < 1)
am = 1;
}
else if (self.weapon == IT_GRENADE_LAUNCHER)
{
// See above.
self.weapon = IT_SUPER_NAILGUN;
// I'm gonna quit typing these now.
self.weapon2 = self.weapon2 = IT3_SUPER_NAILGUN;
// weapon to check for
wp = IT3_SUPER_NAILGUN;
if (self.ammo_nails < 2)
am = 1;
}
else if (self.weapon == IT_SUPER_NAILGUN)
{
self.weapon = IT_NAILGUN;
self.weapon2 = IT3_NAILGUN;
wp = IT3_NAILGUN;
if (self.ammo_nails < 1)
am = 1;
}
else if (self.weapon == IT_NAILGUN)
{
self.weapon = IT_SUPER_SHOTGUN;
// Okay, lets check to see if we gots IT3_NEWWEAPON
if(it & IT3_NEWWEAPON)
{
if(self.weapon2 & IT3_SUPER_SHOTGUN)
self.weapon2 = self.weapon2 - (self.weapon2 & IT3_SUPER_SHOTGUN);
self.weapon2 = self.weapon2 | IT3_NEWWEAPON;
wp = IT3_NEWWEAPON;
if(self.ammo_nails < 1)
am = 1;
}
else // if not then try super shotgun.
{
self.weapon2 = self.weapon2 | IT3_SUPER_SHOTGUN;
wp = IT3_SUPER_SHOTGUN;
if (self.ammo_shells < 2)
am = 1;
}
}
else if (self.weapon == IT_SUPER_SHOTGUN)
{
// Okay, lets check to see if we gots IT3_NEWWEAPON
if(self.weapon2 & IT3_NEWWEAPON)
{
self.weapon2 = self.weapon2 - (self.weapon2 & IT3_NEWWEAPON);
self.weapon2 = self.weapon2 | IT3_SUPER_SHOTGUN;
wp = IT3_SUPER_SHOTGUN;
if(self.ammo_shells < 2)
am = 1;
}
else // if not then try next weapon down.
{
self.weapon = IT_SHOTGUN;
self.weapon2 = self.weapon2 | IT3_SHOTGUN;
wp = IT3_SHOTGUN;
if (self.ammo_shells < 1)
am = 1;
}
}
else if (self.weapon == IT_SHOTGUN)
{
self.weapon = IT_AXE;
self.weapon2 = self.weapon2 | IT3_AXE;
wp = IT3_AXE;
}
else if (self.weapon == IT_AXE)
{
self.weapon = IT_LIGHTNING;
self.weapon2 = self.weapon2 | IT3_LIGHTNING;
wp = IT3_LIGHTNING;
if (self.ammo_cells < 1)
am = 1;
}
if ( (it & wp) && am == 0)
{
W_SetCurrentAmmo ();
return;
}
}
};
Code: Select all
// Testing cheat to see if new weapon stuff works.
if(self.impulse == 47)
{
self.ammo_nails = self.ammo_nails + 30;
self.items = self.items | IT_SUPER_SHOTGUN;
self.items3 = self.items3 | IT3_NEWWEAPON;
self.weapon2 = self.weapon2 | IT3_NEWWEAPON;
}
Replace RankForWeapon and Deathmatch_Weapon with this:
Code: Select all
float(float w) RankForWeapon =
{
if (w == IT3_LIGHTNING)
return 1;
if (w == IT3_ROCKET_LAUNCHER)
return 2;
if (w == IT3_SUPER_NAILGUN)
return 3;
if (w == IT3_GRENADE_LAUNCHER)
return 4;
// New weapon in priority rankings.
if (w == IT3_NEWWEAPON)
return 5;
if (w == IT3_SUPER_SHOTGUN)
return 6;
if (w == IT3_NAILGUN)
return 7;
return 8;
};
/*
=============
DRS
Weapon_Better
Change from current weapon to new weapon if it's better.
=============
*/
void(float oldcategory, float new, float category) Weapon_Better =
{
local float oldweapon, or, nr;
// extract weapon info from .weapon2 depending on what category
if(oldcategory == IT_AXE)
{
oldweapon = IT3_AXE;
}
else if(oldcategory == IT_SHOTGUN)
{
oldweapon = IT3_SHOTGUN;
}
else if(oldcategory == IT_SUPER_SHOTGUN)
{
if(self.weapon2 & IT3_SUPER_SHOTGUN)
oldweapon = IT3_SHOTGUN;
else if(self.weapon2 & IT3_NEWWEAPON)
oldweapon = IT3_NEWWEAPON;
}
else if(oldcategory == IT_NAILGUN)
{
oldweapon = IT3_NAILGUN;
}
else if(oldcategory == IT_SUPER_NAILGUN)
{
oldweapon = IT3_SUPER_NAILGUN;
}
else if(oldcategory == IT_GRENADE_LAUNCHER)
{
oldweapon = IT3_GRENADE_LAUNCHER;
}
else if(oldcategory == IT_ROCKET_LAUNCHER)
{
oldweapon = IT3_ROCKET_LAUNCHER;
}
else if(oldcategory == IT_LIGHTNING)
{
oldweapon = IT3_LIGHTNING;
}
// change self.weapon if desired
or = RankForWeapon (oldweapon);
nr = RankForWeapon (new);
if ( nr < or )
{
// Set to category
self.weapon = category;
// Need to do some case handling for categories with more than one
// weapon
// if player is using the super shotgun, remove the bitflag.
if(new == IT3_NEWWEAPON && (self.weapon2 & IT3_SUPER_SHOTGUN))
self.weapon2 = self.weapon2 - (self.weapon2 & IT3_SUPER_SHOTGUN);
// set weapon2 bitflag.
self.weapon2 = self.weapon2 | new;
}
};
Code: Select all
void() weapon_touch =
{
local float hadammo, category, new, old, gotit;
local entity stemp;
local float leave;
if (!(other.flags & FL_CLIENT))
return;
if (deathmatch == 2 || coop)
leave = 1;
else
leave = 0;
if (self.classname == "weapon_nailgun")
{
if (leave && (other.items3 & IT3_NAILGUN) )
return;
hadammo = other.ammo_nails;
new = IT3_NAILGUN;
category = IT_NAILGUN;
other.ammo_nails = other.ammo_nails + 30;
}
else if (self.classname == "weapon_supernailgun")
{
if (leave && (other.items3 & IT3_SUPER_NAILGUN) )
return;
hadammo = other.ammo_rockets;
new = IT3_SUPER_NAILGUN;
category = IT_SUPER_NAILGUN;
other.ammo_nails = other.ammo_nails + 30;
}
else if (self.classname == "weapon_supershotgun")
{
if (leave && (other.items3 & IT3_SUPER_SHOTGUN) )
return;
hadammo = other.ammo_rockets;
new = IT3_SUPER_SHOTGUN;
category = IT_SUPER_SHOTGUN;
other.ammo_shells = other.ammo_shells + 5;
}
else if (self.classname == "weapon_rocketlauncher")
{
if (leave && (other.items3 & IT3_ROCKET_LAUNCHER) )
return;
hadammo = other.ammo_rockets;
new = IT3_ROCKET_LAUNCHER;
category = IT_ROCKET_LAUNCHER;
other.ammo_rockets = other.ammo_rockets + 5;
}
else if (self.classname == "weapon_grenadelauncher")
{
if (leave && (other.items3 & IT3_GRENADE_LAUNCHER) )
return;
hadammo = other.ammo_rockets;
new = IT3_GRENADE_LAUNCHER;
category = IT_GRENADE_LAUNCHER;
other.ammo_rockets = other.ammo_rockets + 5;
}
else if (self.classname == "weapon_lightning")
{
if (leave && (other.items3 & IT3_LIGHTNING) )
return;
hadammo = other.ammo_rockets;
new = IT3_LIGHTNING;
category = IT_LIGHTNING;
other.ammo_cells = other.ammo_cells + 15;
}
else if (self.classname == "weapon_newweapon") // new weapon
{
if (leave && (other.items3 & IT3_NEWWEAPON) )
return;
hadammo = other.ammo_rockets;
// What weapon
new = IT3_NEWWEAPON;
// What category
category = IT_SUPER_SHOTGUN;
other.ammo_nails = other.ammo_nails + 30;
}
else
objerror ("weapon_touch: unknown classname");
sprint (other, "You got the ");
sprint (other, self.netname);
sprint (other, "\n");
// weapon touch sound
sound (other, CHAN_ITEM, "weapons/pkup.wav", 1, ATTN_NORM);
stuffcmd (other, "bf\n");
bound_other_ammo ();
// change to the weapon
old = other.weapon;
if(other.items3 & new)
gotit = TRUE;
other.items3 = other.items3 | new;
stemp = self;
self = other;
self.items = self.items | category;
if(!gotit)
Weapon_Better (old, new, category);
W_SetCurrentAmmo();
self = stemp;
if (leave)
return;
// remove it in single player, or setup for respawning in deathmatch
self.model = string_null;
self.solid = SOLID_NOT;
if (deathmatch == 1)
self.nextthink = time + 30;
self.think = SUB_regen;
activator = other;
SUB_UseTargets(); // fire all targets / killtargets
};
Code: Select all
/*QUAKED weapon_newweapon (0 .5 .8) (-16 -16 0) (16 16 32)
DRS: New Weapon entity for map testing purposes.
*/
void() weapon_newweapon =
{
precache_model ("progs/g_nail.mdl");
setmodel (self, "progs/g_nail.mdl");
self.weapon = IT_SUPER_SHOTGUN; // Doesn't do anything.
// meet the new weapon, same as old weapon (nailgun)=P
self.netname = "New Weapon";
self.touch = weapon_touch;
setsize (self, '-16 -16 0', '16 16 56');
StartItem ();
};
Code: Select all
void() BackpackTouch =
{
local string s;
local float best, old, new, category, gotit;
local entity stemp;
local float acount;
if (other.classname != "player")
return;
if (other.health <= 0)
return;
acount = 0;
sprint (other, "You get ");
category = self.items;
if (self.items)
if ((other.items3 & self.weapon2) == 0)
{
other.items = other.items | self.items;
acount = 1;
sprint (other, "the ");
sprint (other, self.netname);
}
// if the player was using his best weapon, change up to the new one if better
// stemp = self;
// self = other;
// best = W_BestWeapon();
// self = stemp;
// change weapons
other.ammo_shells = other.ammo_shells + self.ammo_shells;
other.ammo_nails = other.ammo_nails + self.ammo_nails;
other.ammo_rockets = other.ammo_rockets + self.ammo_rockets;
other.ammo_cells = other.ammo_cells + self.ammo_cells;
new = self.weapon2;
if (!new)
new = other.weapon2;
old = other.weapon;
if(other.items3 & new)
gotit = TRUE;
other.items3 = other.items3 | new;
bound_other_ammo ();
if (self.ammo_shells)
{
if (acount)
sprint(other, ", ");
acount = 1;
s = ftos(self.ammo_shells);
sprint (other, s);
sprint (other, " shells");
}
if (self.ammo_nails)
{
if (acount)
sprint(other, ", ");
acount = 1;
s = ftos(self.ammo_nails);
sprint (other, s);
sprint (other, " nails");
}
if (self.ammo_rockets)
{
if (acount)
sprint(other, ", ");
acount = 1;
s = ftos(self.ammo_rockets);
sprint (other, s);
sprint (other, " rockets");
}
if (self.ammo_cells)
{
if (acount)
sprint(other, ", ");
acount = 1;
s = ftos(self.ammo_cells);
sprint (other, s);
sprint (other, " cells");
}
sprint (other, "\n");
// backpack touch sound
sound (other, CHAN_ITEM, "weapons/lock4.wav", 1, ATTN_NORM);
stuffcmd (other, "bf\n");
// remove the backpack, change self to the player
remove(self);
self = other;
// change to the weapon
// if (!deathmatch)
// self.weapon = new;
// else
if(!gotit)
Weapon_Better (old, new, category);
W_SetCurrentAmmo ();
};
/*
===============
DropBackpack
===============
*/
void() DropBackpack =
{
local entity item;
if (!(self.ammo_shells + self.ammo_nails + self.ammo_rockets + self.ammo_cells))
return; // nothing in it
item = spawn();
item.origin = self.origin - '0 0 24';
item.items = self.weapon;
if (item.items == IT_AXE)
{
item.weapon2 = IT3_AXE;
item.netname = "Axe";
}
else if (item.items == IT_SHOTGUN)
{
item.weapon2 = IT3_SHOTGUN;
item.netname = "Shotgun";
}
else if (item.items == IT_SUPER_SHOTGUN)
{
if(self.weapon2 & IT3_NEWWEAPON)
{
item.weapon2 = IT3_NEWWEAPON;
item.netname = "NewWeapon";
}
else
{
item.weapon2 = IT3_SUPER_SHOTGUN;
item.netname = "Double-barrelled Shotgun";
}
}
else if (item.items == IT_NAILGUN)
{
item.weapon2 = IT3_NAILGUN;
item.netname = "Nailgun";
}
else if (item.items == IT_SUPER_NAILGUN)
{
item.weapon2 = IT3_SUPER_NAILGUN;
item.netname = "Super Nailgun";
}
else if (item.items == IT_GRENADE_LAUNCHER)
{
item.weapon2 = IT3_GRENADE_LAUNCHER;
item.netname = "Grenade Launcher";
}
else if (item.items == IT_ROCKET_LAUNCHER)
{
item.weapon2 = IT3_ROCKET_LAUNCHER;
item.netname = "Rocket Launcher";
}
else if (item.items == IT_LIGHTNING)
{
item.weapon2 = IT3_LIGHTNING;
item.netname = "Thunderbolt";
}
else
item.netname = "";
item.ammo_shells = self.ammo_shells;
item.ammo_nails = self.ammo_nails;
item.ammo_rockets = self.ammo_rockets;
item.ammo_cells = self.ammo_cells;
item.velocity_z = 300;
item.velocity_x = -100 + (random() * 200);
item.velocity_y = -100 + (random() * 200);
item.flags = FL_ITEM;
item.solid = SOLID_TRIGGER;
item.movetype = MOVETYPE_TOSS;
setmodel (item, "progs/backpack.mdl");
setsize (item, '-16 -16 0', '16 16 56');
item.touch = BackpackTouch;
item.nextthink = time + 120; // remove after 2 minutes
item.think = SUB_Remove;
};
make a map, add weapon_newweapon to it then run it through quake, or
just run quake with your favorite map and use the impulse 47 cheat.
(Just don't forget to take it out later, because in DM this cheat will
work. And that would be bad.)
Read and experiment with the code above. Then go forth and make super
insano-weapon mods!