Post tutorial RSS Doom Source Code Tutorial 11

Modding The Monsters in Doom Part 4 - The Imp. In this article we give the imp extra powers and turn him into a super imp.

Posted by on - Basic Client Side Coding

Doom Source Code Tutorial 11
Game: Doom or Doom2
Level: Basic.
Objective: Understand the basics of the Imp's states, attacks and characteristics.
Resources required: VC++ 2008 Express Edition; source code for Doom (tested with Doomsday ver 1.9.0-beta6.9 and chocolate doom).

Introduction: Anybody who played doom knows that this character populates almost every map in the game and you either hated him or... hated him. Its most powerful asset in addition to its abundance in numbers and melee attack is its ability to throw fireballs at the player from great distances with deadly accuracy. Today we are going to make a variety of changes to our beloved Imp .We shall substantially enhance his capabilities even further and turn him into a super Imp.
Procedure:1. Let's start with his fire ball, there are at least three things we can modify here and they are all easy to implement:
a. The speed of his missiles,
b. The damage or hit points of each shot, and
c. The type of missiles used.

2. Let's begin as usual by looking at the attributes and properties in the relevant file entry. First to check out is TROOPSHOT (again notice that Troop is used and not Imp). Here is the one for jdoom from the file objects.ded:

Thing {
DoomEd number = -1;
Spawn state = "TBALL1";
See state = "NULL";
Pain state = "NULL";
Melee state = "NULL";
Missile state = "NULL";Death state = "TBALLX1";
Xdeath state = "NULL";
Raise state = "NULL";
See sound = "firsht";
Attack sound = "None";
Pain sound = "None";
Death sound = "firxpl";
Active sound = "None";
Reaction time = 8;
Spawn health = 1000;
Speed = 10;
Radius = 6;
Height = 8;
Mass = 100;
Damage = 3;
Flags = brightexplode | dropoff | missile | noblockmap | nogravity | brightshadow;
Flags2 = noteleport;

The one for chocolate doom is in info.c and has basically the same data:

-1, // doomednum
S_TBALL1, // spawnstate
1000, // spawnhealth
S_NULL, // seestate
sfx_firsht, // seesound
8, // reactiontime
sfx_None, // attacksound
S_NULL, // painstate
0, // painchance
sfx_None, // painsound
S_NULL, // meleestate
S_NULL, // missilestate
S_TBALLX1, // deathstate
S_NULL, // xdeathstate
sfx_firxpl, // deathsound
10*FRACUNIT, // speed
6*FRACUNIT, // radius
8*FRACUNIT, // height
100, // mass
3, // damage
sfx_None, // activesound
S_NULL // raisestate

You can see that the "normal" missile speed set for the imp's fire ball in doom is 10 and the amount of damage is set at 3. You may also observe that all the entries that do not apply to this object is either set as NULL or given a high fixed number as in the case of "spawn health" for example.
3. Now to change the speed of the fire ball go to the file g_game.c for jdoom and add this to the usual place, just before where it says //<-- KLUDGE as shown below:

// <-- KLUDGE
And for chocolate doom in info.c under MT_TROOPSHOT:

sfx_firxpl, // deathsound
x*FRACUNIT, // speed , substitute 30 for x for fast missiles

Where x is your desired speed for the fire ball .Notice the use of FRACUNIT in chocolate doom above ;this is the unit format used by ID Softwareto measure distances in a map.
4. At this stage, I should point out an important aspect about the peculiarities of the doom engine. There is a limit to how high you can set the value of x, as if you go beyond a certain upper limit ,the engine starts to behave erratically and the ball will never hit the target. The highest speed tested by me and found to be most suitable is 30. At the other extreme the slowest speed is 1 ,this value will make the imp's balls almost float . Therefore you ‘ll do better to replace x with 30 and build your mod. Now the speed should be nearly 3 times faster than normal with the same accuracy. Try other speeds just to check this out for yourself.
5. Now set the damage rate to a different value. I suggest 30 ,combined with high speed, that should kill most players with one shot. Again you may change these values in the usual way:

MOBJINFO[MT_TROOPSHOT].damage = 30; //for jdoom, add it next to the one for speed above
30*FRACUNIT, // damage for chocolate doom

6. How about changing the type of missile thrown by this monster. You have a variety of choices as before when we modded the Demon. Rockets and skulls are absolutely out of the question, far too dangerous, believe me. If you are doing this for Doom2 then the most appropriate missile should be the skeleton's rockets or the Fatso's missiles, but then it's a matter of your choice. Let's use the plazma balls as they are available in both games. First scroll to the actual Imp's states entry in objects.ded and take a look at the 3 attack states:

State {ID = "TROO_ATK1";
Sprite = "TROO";
Frame = 4;
Tics = 8;
Action = "A_FaceTarget";
Next state = "TROO_ATK2";
State {
Sprite = "TROO";
Frame = 5;
Tics = 8;
Action = "A_FaceTarget";
Next state = "TROO_ATK3";

State {
Sprite = "TROO";
Frame = 6;
Tics = 6;
Action = "A_TroopAttack";
Next state = "TROO_RUN1";

7. The attack action function for this actor is called A_TroopAttack ...and not A_ImpAttack you may observe. Let's inspect the defintion for this one, find it in p_enemy.c :

void A_TroopAttack (mobj_t* actor)
int damage;
if (!actor->target)
A_FaceTarget (actor);
if (P_CheckMeleeRange (actor))
S_StartSound (actor, sfx_claw);
damage = (P_Random()%8+1)*3;
P_DamageMobj (actor->target, actor, actor, damage);
// launch a missile
P_SpawnMissile (actor, actor->target, MT_TROOPSHOT);

Of course we already know that the Imp has 2 modes of attack , and having already done tutorial 10, I am not going to repeat anything here. So in order to change the type of missile shot by the Imp simply replace the Map Thing parameter MT_TROOPSHOT with MT_PLASMA in the P_SpawnMissile function above .That should do it for both ports. Careful now the speed and damage rate has now been changed to that of the plasma ball,it's not the imp's fire ball anymore. It's your choice to change these figures back !

P_SpawnMissile (actor, actor->target, MT_PLASMA); // note: choco doom

8. However,to make a really super imp we'll do better if we could give him something more than just fast and deadly plazma balls to shoot us with. Let's have a go at equipping him with the ability to auto-fire so he could wipe out his enemies with a barrage of missiles. This should be easy since we have already done this favor to the sergeant by adding a refire function . Let's do the same to the Imp.
9. First we must define a new function A_TroopRefire in p_enemy.c, which is just a re-named copy of A_SposRefire action function for the sergeant in tutorial 9 , here it is for choco doom:

//new troop refire

void A_TroopRefire (mobj_t* actor)
if (P_Random () < 40)
P_SetMobjState (actor, actor->info->seestate);
A_FaceTarget (actor);
if (!actor->target
|| actor->target->health <= 0 // use logical ||
|| !P_CheckSight (actor, actor->target) )
P_SetMobjState (actor, actor->info->seestate);

And for jdoom:

void C_DECL A_TroopRefire(mobj_t* actor)
if(P_Random() < 40)
P_MobjChangeState(actor, P_GetState(actor->type, SN_SEE));
if (!actor->target || actor->target->health <= 0 ||
!P_CheckSight(actor, actor->target))
P_MobjChangeState(actor, P_GetState(actor->type, SN_SEE));
10. Do not forget to declare these functions; in chocolate doom do it at the top of info.c:
void A_TroopAttack();
void A_TroopRefire(); //new
void A_SargAttack();
void A_HeadAttack();

and for jdoom add it to the header file acfnlink.h as shown below:
void C_DECL A_XScream();
void A_TroopRefire(); // new function declared

11 . Next important step is to add pointers to these action functions in the relevant states . For jdoom add the following lines to g_game.c , just next to those for damage and speed as shown:

MOBJINFO[MT_TROOPSHOT].damage = 30; //for jdoom, add it next to the one for speed above
STATES[S_TROO_ATK2].action = A_TroopAttack;
STATES[S_TROO_ATK3].action = A_TroopRefire;
// <-- KLUDGE

16. And for chocolate doom insert A_TroopRefire in the structure in info.c in place of "A_TroopAttack" as shown below. Do not forget to replace the second A_FaceTarget function with A_TroopAttack in S_TROO_ATK2 , and replace S_TROO_RUN1 with S_TROO_ATK2 in S_TROO_ATK3 to form a closed refire loop (I hope this color code does no confusion to all of us!):

This is the original:
{SPR_TROO,4,8,{A_FaceTarget},S_TROO_ATK2,0,0}, // S_TROO_ATK1
{SPR_TROO,5,8,{A_FaceTarget},S_TROO_ATK3,0,0}, // S_TROO_ATK2
{SPR_TROO,6,6,{ A_TroopAttack },S_TROO_RUN1,0,0}, // S_TROO_ATK3

This is the modded final one:
{SPR_TROO,4,8,{A_FaceTarget},S_TROO_ATK2,0,0}, // S_TROO_ATK1
{SPR_TROO,5,8,{A_TroopAttack},S_TROO_ATK3,0,0}, // S_TROO_ATK2
{SPR_TROO,6,6,{A_TroopRefire},S_TROO_ATK2,0,0}, // S_TROO_ATK3
17. Now build your mod and go combat your new Imps. I doubted it if you could survive any level now, unless you armed yourself with the modded weapons from earlier tutorials. Enjoy the mayhem.
A note to my newbie friends: Think about learning new skills which can help you to replace the graphics and sprites for these new super monsters and modded weapons we have been doing in these articles so far. There are a lot of tutorials and tools waiting for you out there . Use Slade, Slumped or XWE to change the images of your new enemies before you make new mods or levels. There are plenty of fantastic and brilliantly designed sprites and sounds for your monsters and weapons available. I recommend you pay a visit to by clicking here if you do not already know. It is the best for doom graphics as it has plenty of resources specially made for these purposes, check it out.
Bye for now.
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.