Post tutorial RSS Doom Source Code Tutorial 2

The doom1 game does not include the super shotgun. This tutorial will show you one way of giving the normal shotgun in doom1 the functionality of the super shotgun.

Posted by on - Basic Client Side Coding

Tutorial 2
Level: easy.
Objective: turn the shotgun in Doom 1 into a super shotgun.
Resources Required: Visual C++, Doom source code (Doomsday 1.8.6 or Chocolate doom).
Introduction: for most newbies setting off to modify the source code of an FPS game, the first thing they usually want to do is change the weapons' behavior. This can be very easy to implement and its impact on the game play is substantial. These changes may include the amount of damage that these weapons inflect, the firing rate and the accuracy of each shot. In this tutorial we will focus on the damage rate.As this tutorial is aimed at beginners, it may be necessary in places to skip through certain statements in the code for at least 2 reasons:
a.They do not directly impact on what we are trying to modify.
b.They involve advanced programming techniques that may require from the reader some pre-requisite knowledge of either coding or how the game works.
We therefore do not want to put you off the subject, but to encourage you and lead you step by step to build your confidence. Believe me, once you get the hang of it, this coding business can become very addictive, and rewarding too. You will be on your way to become a skilled modder making better TC's and maps. So here we go:
Procedure:
1.Start your compiler and open the file named p_pspr.c in doomsday source code folder and use search from the menu bar to locate the function shown below :

void C_DECL A_FireShotgun(player_t *player, pspdef_t * psp)
{
int i;
S_StartSound(sfx_shotgn, player->plr->mo);
P_SetMobjState(player->plr->mo, S_PLAY_ATK2);
//player->ammo[weaponinfo[player->readyweapon].ammo]--;
P_ShotAmmo(player);
P_SetPsprite(player, ps_flash, weaponinfo[player->readyweapon].flashstate);
player->update |= PSF_AMMO;
if(IS_CLIENT)
return;
P_BulletSlope(player->plr->mo);
for(i = 0; i < 7; i++)
P_GunShot(player->plr->mo, false);
}

2.This is the function responsible for firing the shotgun. As I said earlier, we will skip for the time being the statements that deal with sound and graphics amongst other things which we do not intend to change in this mod.Pay attention to the last line in red,the function "P_GunShot" ,this is the one we need to examine in detail. Do a quick search for the definition of this function, in doomsday it is located in the same file some 40 lines above. Here it is:

void P_GunShot(mobj_t *mo, boolean accurate)
{
angle_t angle;
int damage;
damage = 5 * (P_Random() % 3 + 1);
angle = mo->angle;
if(!accurate)
angle += (P_Random() - P_Random()) << 18;
P_LineAttack(mo, angle, MISSILERANGE, bulletslope, damage);
}

3.The first line defines a variable called angle of special type "angle_t " which is defined by "id" somewhere else in the code,do not worry about that for now, just accept that angle refers to the direction to which the gun is aiming. The second line defines an integer variable for calculating the damage in line 3.Look carefully at line 3 ,This one computes the amount of damage for one single shot, but it does that at a random rate, so that each shot varies in strength from the previous one. Take it from me, the random function P_Random() in combination with % (modulo not percentage) operator generates a random value between 0 and 2 each time you fire your gun.This function is used throughout the source code to simulate real action. With simple mathematics you get a total damage rate of either 5, 10 or 15 points for your shot. Further, this same random element is introduced in line 6 to control the accuracy of your shot. The angle of aim is modified in a horizontal direction at random, right or left ,depending on whether the result of the calculation in this expression is positive or negative.
4.The function P_LineAttack is an important one. It fires one single pellet of lead testing at the same time for aim, clear path to target, bullet slope ...etc. It is also used for the pistol and the chain gun as we shall see later.
5. Going back to our shotgun function, you can now see clearly what is happening. We have a loop that calls the PGunShot function 7 times in a row, each time firing in a slightly different direction right or left with varying damage rate. This explains why you see 7 bullet marks with random spacing every time you shoot at a wall from some distance. Its bigger brother, the super shotgun fires about 3 times as much lead in one go, therefore the damage rate is 3 folds.
6.On with our mod; armed with the above knowledge we can now make the shotgun as powerful as the super shotgun. We are not going to re-invent the wheel here, we will just "borrow" the necessary code from the super shotgun function (find it right below, in the same file, named A_FireShotgun2).Our modified block of code will now look like this ( new lines are in red):

void C_DECL A_FireShotgun(player_t *player, pspdef_t * psp)

{
int i;

angle_t angle;

int damage;

S_StartSound(sfx_shotgn, player->plr->mo);

P_SetMobjState(player->plr->mo, S_PLAY_ATK2);

P_ShotAmmo(player);

P_SetPsprite(player, ps_flash, weaponinfo[player->readyweapon].flashstate);

player->update |= PSF_AMMO;

if(IS_CLIENT)

return;

P_BulletSlope(player->plr->mo);

for(i = 0; i < 20; i++)

{
damage = 5 * (P_Random() % 3 + 1);

angle = player->plr->mo->angle;

angle += (P_Random() - P_Random()) << 19;

P_LineAttack(player->plr->mo, angle, MISSILERANGE,

bulletslope + ((P_Random() - P_Random()) << 5), damage);

}

}


7.Pay special attention to the random variation in the bullet slope in the last line, this causes the shots now to vary their position in the vertical direction too, hence increasing the spread of lead. You may also change the damage rate here if you like, set that to a reasonable value, bear in mind that the power has already been increased by 3 times, example:

damage = 8 * (P_Random() % 3 + 1);

8.Now copy and paste the above block of code, compile the whole thing and try your mod.

Note
1: If you are doing this for doom2, I suggest you reduce the number of pellets to 10 or 12 or you will end up with 2 super shotguns, except that the modded one uses just one shell and takes half as long to re-load .Do not go over the top with the amount of damage you select, a large value will be capped if you go over the set limit.This will swamp the random element in the equation anyway and will make your shotgun ridiculously too powerful upsetting the balance of weapons and enemies in the game.

Note
2: The shotgun function used in risen3d has already been changed for you by the source port developer and includes the P_GunShot function, but the same principles apply. As always pay special attention to the variation in code between the various ports we use in these artcles or the ones you may wish to mod for.
Now we can go on to turn our shotgun into a sniper rifle or even a machine gun, but we do not want to jump the gun (no pun intended!) ,not yet anyway. We need first to understand how the mechanism of weapons animation and re-firing works in Doom. We will cover this in another tutorial. We have to stop right now as this tutorial is getting rather lengthy. See you next time.
Happy modding
Adam.

Return to Tutorials Page.

Post a comment
Sign in or join with:

Only registered members can share their thoughts. So come on! Join the community today (totally free - or sign in with your social account on the right) and join in the conversation.