Welcome to the first entry of my FAQ (Frequently Asked Questions) series. These will teach you how to do things which are frequently asked about on the forums. A big thank you goes out to Ensiform and redsaurus, who helped me with the editing process of the tutorial.
Important Note: You must compile the engine as well as the DLLs in order to do this.
Important Note 2: You are limited to 32 weapons, no more.
Important Note 3: This will render your game non-backwards compatible with savegames and connectivity.
You'll need: A weapon model, icon, effects, and sounds. You can use preexisting models and so forth, but it obviously isn't as cool as a new weapon!
With that being said, let's dive in..I'm going to be creating a new weapon called the T-21 Light Repeating Blaster.
First, we'll want to actually get our source code set up and run a test compile. I'll assume that you've already done this, and you have some basic understanding of how the compile process works.
Next up, we're going to bg_weapons.h. Right at the top of the file, we're going to do our first modification.
typedef enum {
WP_NONE,
WP_STUN_BATON,
WP_MELEE,
WP_SABER,
WP_BRYAR_PISTOL,
WP_BLASTER,
WP_DISRUPTOR,
WP_BOWCASTER,
WP_REPEATER,
WP_DEMP2,
WP_FLECHETTE,
WP_ROCKET_LAUNCHER,
WP_THERMAL,
WP_TRIP_MINE,
WP_DET_PACK,
WP_CONCUSSION,
WP_BRYAR_OLD,
WP_EMPLACED_GUN,
WP_TURRET,
// WP_GAUNTLET,
// WP_MACHINEGUN, // Bryar
// WP_SHOTGUN, // Blaster
// WP_GRENADE_LAUNCHER, // Thermal
// WP_LIGHTNING, //
// WP_RAILGUN, //
// WP_GRAPPLING_HOOK,
WP_NUM_WEAPONS
} weapon_t;
We're going to add our own little entry here. For the purpose of my example, we're going to do it like this:
typedef enum {
WP_NONE,
WP_STUN_BATON,
WP_MELEE,
WP_SABER,
WP_BRYAR_PISTOL,
WP_BLASTER,
WP_DISRUPTOR,
WP_BOWCASTER,
WP_REPEATER,
WP_DEMP2,
WP_FLECHETTE,
WP_ROCKET_LAUNCHER,
WP_THERMAL,
WP_TRIP_MINE,
WP_DET_PACK,
WP_CONCUSSION,
WP_T21, // this is my new addition
WP_BRYAR_OLD,
WP_EMPLACED_GUN,
WP_TURRET,
// WP_GAUNTLET,
// WP_MACHINEGUN, // Bryar
// WP_SHOTGUN, // Blaster
// WP_GRENADE_LAUNCHER, // Thermal
// WP_LIGHTNING, //
// WP_RAILGUN, //
// WP_GRAPPLING_HOOK,
WP_NUM_WEAPONS
} weapon_t;
The reason we put it before WP_BRYAR_OLD is because WP_BRYAR_OLD is always the last selectable weapon in the game, unless you change some other code around. We like shortcuts!
Next up, take a look at q_shared.h. We'll need to change MAX_WEAPONS.
#define MAX_WEAPONS 19
to
#define MAX_WEAPONS 32 // one time change to change the weapon limit to 32
Now we get to modify some fun bits of code. Anyone who has used weapons.dat will be sorta familiar with this chunk of code. This is weaponData, which in SP is defined in weapons.dat. This step is easy enough. We need to add a new entry here for our weapon. Open up bg_weapons.c, and just before:
{ // WP_BRYAR_OLD,
Add in this new entry:
{ // WP_T21,
// "T21 Light Repeater", // char classname[32]; // Spawning name
AMMO_BLASTER, // int ammoIndex; // Index to proper ammo slot
40, // int ammoLow; // Count when ammo is low
20, // int energyPerShot; // Amount of energy used per shot
2000, // int fireTime; // Amount of time between firings
8192, // int range; // Range of weapon
2, // int altEnergyPerShot; // Amount of energy used for alt-fire
120, // int altFireTime; // Amount of time between alt-firings
8192, // int altRange; // Range of alt-fire
0, // int chargeSubTime; // ms interval for subtracting ammo during charge
0, // int altChargeSubTime; // above for secondary
0, // int chargeSub; // amount to subtract during charge on each interval
0, //int altChargeSub; // above for secondary
0, // int maxCharge; // stop subtracting once charged for this many ms
0 // int altMaxCharge; // above for secondary
},
Next up, we'll want to take a look at bg_misc.c. In the array,
int WeaponReadyAnim[WP_NUM_WEAPONS] =
we'll want to add a reference to our own animation here. So right after the line that reads:
TORSO_WEAPONREADY3,//WP_CONCUSSION
We'll want to add something like this:
TORSO_WEAPONREADY3,//WP_T21
Do the same for WeaponReadyLegsAnim and WeaponAttackAnim.
OpenJK note: You'll want to make sure that BASE_COMPAT is undefined, or that the #ifdef blocks around this chunk of code is removed:
#ifndef BASE_COMPAT
//JAC: Raven forgot the Concussion's firing animation
BOTH_ATTACK3,//WP_CONCUSSION,
#endif // BASE_COMPAT
Otherwise, your weapon might have weird firing anims. Blame the raven.
Further on down the file, there's a really big array called bg_itemlist. Basically, we need to add a new entry to this array. So, just before this line:
/*QUAKED weapon_blaster (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
*/
Add some code that looks something like this:
/*QUAKED weapon_t21 (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
New T21 weapon
*/
{
"weapon_t21",
"sound/weapons/w_pkup.wav",
{ "models/weapons2/briar_pistol/briar_pistol_w.glm", // CHANGE THIS PATH TO THE WEAPON MODEL
0, 0, 0},
/* view */ "models/weapons2/briar_pistol/briar_pistol.md3", // CHANGE THIS PATH TO THE FIRST PERSON MODEL
/* icon */ "gfx/hud/w_icon_briar",//"gfx/hud/w_icon_rifle", // CHANGE THIS PATH TO THE ICON PATH
/* pickup */// "T21 Light Repeating Blaster",
100, // Amount of ammo to start with?
IT_WEAPON,
WP_T21,
/* precache */ "",
/* sounds */ "",
"@SP_INGAME_T21" // description
},
We're done with bg_misc.c, so you can go ahead and close it. The next thing we're going to do is make our weapon usable in Siege mode. This is a piece of cake. Open bg_saga.c and just before:
ENUM2STRING(WP_BRYAR_OLD),
add:
ENUM2STRING(WP_T21),
Optional: If you want your weapon to add scorch marks to people, go into cg_event.c. Find this line of code:
case WP_BRYAR_OLD:
And add this line of code right after it:
case WP_T21:
Here comes another fun bit of code. We're going to now alter the code that handles all the effects of the weapon, such as the bullet impacts and so forth. Open up cg_weaponinit.c, and cg_local.h.
First things first, we need to add a few definitions. In cg_local.h, we need to add the following lines of code, somewhere in cgEffects_t, such as right after the line that says "// BLASTER":
// T21
fxHandle_t t21ShotEffect;
fxHandle_t t21WallImpactEffect;
fxHandle_t t21FleshImpactEffect;
fxHandle_t t21DroidImpactEffect;
Next, we'll need to get into cg_weaponinit.c. Right after:
case WP_SABER:
MAKERGB( weaponInfo->flashDlightColor, 0.6f, 0.6f, 1.0f );
weaponInfo->firingSound = trap_S_RegisterSound( "sound/weapons/saber/saberhum1.wav" );
weaponInfo->missileModel = trap_R_RegisterModel( "models/weapons2/saber/saber_w.glm" );
break;
Add this:
case WP_T21:
weaponInfo->selectSound = trap_S_RegisterSound("sound/weapons/bryar/select.wav"); // CHANGE ME
weaponInfo->flashSound[0] = trap_S_RegisterSound( "sound/weapons/bryar/fire.wav"); // CHANGE ME
weaponInfo->firingSound = NULL_SOUND;
weaponInfo->chargeSound = NULL_SOUND;
weaponInfo->muzzleEffect = trap_FX_RegisterEffect( "bryar/muzzle_flash" ); // CHANGE ME
weaponInfo->missileModel = NULL_HANDLE;
weaponInfo->missileSound = NULL_SOUND;
weaponInfo->missileDlight = 0;
//weaponInfo->missileDlightColor= {0,0,0};
weaponInfo->missileHitSound = NULL_SOUND;
weaponInfo->missileTrailFunc = FX_T21ProjectileThink;
weaponInfo->altFlashSound[0] = trap_S_RegisterSound( "sound/weapons/bryar/alt_fire.wav"); // CHANGE ME
weaponInfo->altFiringSound = NULL_SOUND;
weaponInfo->altChargeSound = NULL_SOUND;
weaponInfo->altMuzzleEffect = trap_FX_RegisterEffect( "bryar/muzzle_flash" ); // CHANGE ME
weaponInfo->altMissileModel = NULL_HANDLE;
weaponInfo->altMissileSound = NULL_SOUND;
weaponInfo->altMissileDlight = 0;
//weaponInfo->altMissileDlightColor= {0,0,0};
weaponInfo->altMissileHitSound = NULL_SOUND;
weaponInfo->altMissileTrailFunc = FX_T21AltProjectileThink;
cgs.effects.t21ShotEffect = trap_FX_RegisterEffect( "bryar/shot" );
cgs.effects.t21WallImpactEffect = trap_FX_RegisterEffect( "bryar/wall_impact" );
cgs.effects.t21FleshImpactEffect = trap_FX_RegisterEffect( "bryar/flesh_impact" );
cgs.effects.t21DroidImpactEffect = trap_FX_RegisterEffect( "bryar/droid_impact" );
break;
In this next step, you have a bit of choice. You can either create your own file, called fx_t21.c, in the cgame folder, or you can hijack an existing fx_ file, like how the concussion rifle does it. Either way, you'll need to make sure that fx_local.h is #include'd, and that you add a new function called FX_T21ProjectileThink and FX_T21AltProjectileThink. Make sure you add a declaration in fx_local.h for this function, and that the function is similar to other FX_ projectile thinking functions, such as FX_BryarProjectileThink. You'll also need to add a FX_T21ProjectileHitPlayer and FX_T21ProjectileHitWall, and make sure they're used in a similar fashion as FX_BryarHitPlayer and FX_BryarHitWall, respectively.
One last step. We need to actually define the behavior of the gun when it fires! This is more simple than it sounds. In g_weapon.c, after:
case WP_BRYAR_OLD:
WP_FireBryarPistol( ent, altFire );
break;
Add something which looks like:
case WP_T21:
WP_FireT21( ent, altFire );
break;
WP_FireT21 can do whatever you want it to do. This is the main meat of your weapon, this is what makes it do what it does. There's plenty of examples to base your work off of. I personally think that the Blaster Rifle and bowcaster are two good weapons to base it off of, as they're fairly simple and don't involve any sort of charging mechanics.
Recommended Comments
There are no comments to display.
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now