This is a tutorial by Ziggy Gnarly that describes how to make a friendly monster using DDF.
This tutorial expands on the previous tutorial on making a new
creature using DDF. In this example, we'll make a friendly creature
that uses multiple attacks to aid you in your missions.
The female player from Quake 2 is going to be your friendly creature
(she must dig your retro style, your cream boots or your motorcycle
helmet - or perhaps it's just your animal magnetism) In any case, you
are gonna be very happy that she's on your side!
Initially, we'll need to go through the same steps involved with
making a normal doom monster. As in the other tutorials, I'm assuming
that you are somewhat familiar with doom editing - and that you know
how to make sounds, graphics and understand how to use Wintex and make
a WAD file.
Our first step is to create some new sounds for our female player.
This is important, since doom isn't exactly brimming with appropriate
sounds for a female character.
1) Create the new sounds for it:
-a pain sound called QFPAIN
-a death sound called QFDIE1
-a second death sound QFDIE2
2) Import and name them in new WAD using Wintex:
You'll need to add a DS to the front of each sound
-DSQFPAIN
-DSQFDIE1
-DSQFDIE2
All digital sounds MUST be called DS[name]. You can have 6 character
names total. Like DSSPINDN for example.
3) We need to define the sounds, so open EDGE's existing
SOUNDS.DDF, PAGE DOWN to the bottom to add new stuff:
Anything that appears after // is a comment, ex: // THIS IS A COMMENT.
DDF doesn't pay attention to upper or lower case, but I use upper
cause it looks better.
Add the following:
[Q2FDIE1] // sound's name, used in other DDF files
LUMP_NAME="DSQFDIE1"; // lump name in the WAD
PRIORITY=60; // medium level priority
BITS=8;
[Q2FDIE2]
LUMP_NAME="DSQFDIE2";
PRIORITY=60;
BITS=8;
[Q2FPAIN]
LUMP="DSQFPAIN";
PRIORITY=60;
BITS=8;
I should just note that the sounds.ddf file is very important. It is
quite easy to add your sound files to your WAD, and use those sounds
in your attacks.ddf and things.ddf. However, if you don't identify the
sounds in sounds.ddf, then EDGE won't be able to find or play your new
sounds.
4) We now need to define the attack for the new creature, so
open EDGE's existing ATTACKS.DDF, PAGE DOWN to the bottom to add new
stuff.
This attack is going to make our character fire dual plasma bolts at
any unfortunate monsters who get in the way...These bolts will be
tracers - e.g they will lock onto and follow the target. To make the
dual attack, we will make both a left and a right attack, using the X
OFFSET value.
Add the following:
[QF_TRACKER_L] // left attack
ATTACKTYPE=PROJECTILE;
HEIGHT=8;
RADIUS=11;
DAMAGE_RANGE=8;
DAMAGE_MULTI=10;
ATTACK_HEIGHT=32;
X_OFFSET=-30; // attack moves 30 units to left
SPEED=10;
TRANSLUCENCY=0.40; // somewhat see through
NO_TRACE_CHANCE=0%; // always traces target, 100 never traces
TOO_CLOSE_RANGE=196; // will move to closecombat if target gets close
PROJECTILE_SPECIAL=NOBLOCKMAP, MISSILE, DROPOFF, NOGRAVITY;
PUFF=PUFF;
// used for smoke trail
ATTACK_SPECIAL=SMOKING_TRACER; // sets a smoke trail. Calls puff animation to trail behind projectile
LAUNCH_SOUND=PLASMA;
DEATH_SOUND=FIRXPL;
STATES(IDLE)=
PLSS:A:2:BRIGHT:TRACER, // sets projectile to track target
PLSS:B:2:BRIGHT:TRACER;
STATES(DEATH)=
PLSE:A:4:BRIGHT:NOTHING,
PLSE:B:4:BRIGHT:NOTHING,
PLSE:C:4:BRIGHT:NOTHING,
PLSE:D:4:BRIGHT:NOTHING,
PLSE:E:4:BRIGHT:NOTHING,#REMOVE; // makes explosion disappear
We'll now add the right attack - which will be identical, except for
the X value which will offset the attack to the right.
[QF_TRACKER_R]
ATTACKTYPE=PROJECTILE;
HEIGHT=8;
RADIUS=11;
DAMAGE_RANGE=8;
DAMAGE_MULTI=10;
ATTACK_HEIGHT=32;
X_OFFSET=30; // projectile launches from the right
SPEED=10;
TRANSLUCENCY=0.40;
NO_TRACE_CHANCE=0%;
TOO_CLOSE_RANGE=196;
PROJECTILE_SPECIAL=NOBLOCKMAP, MISSILE, DROPOFF, NOGRAVITY;
PUFF=PUFF;
ATTACK_SPECIAL=SMOKING_TRACER;
LAUNCH_SOUND=PLASMA;
DEATH_SOUND=FIRXPL;
STATES(IDLE)=PLSS:A:2:BRIGHT:TRACER, // makes projectile trace target
PLSS:B:2:BRIGHT:TRACER;
STATES(DEATH)=PLSE:A:4:BRIGHT:NOTHING,
PLSE:B:4:BRIGHT:NOTHING,
PLSE:C:4:BRIGHT:NOTHING,
PLSE:D:4:BRIGHT:NOTHING,
PLSE:E:4:BRIGHT:NOTHING,#REMOVE;
Surprisingly, the see through plasma bolt with a yellowish smoking
trail looks surprisingly cool...(at least in my humble opinion - and
hey, I'm the poor bastard taking ages to write this thing, so you'll
just have to play along. OK?)
Quick warning #1: be very careful when using left and right attacks.
When making this tutorial, I accidentally set the offset of both
missiles to 30....with predictably bad results.
As the next step, we'll also give the friendly quake female a
closecombat attack - just in case she ends up fighting in a confined
space.
[QF_CLOSECOMBAT]
ATTACKTYPE=CLOSECOMBAT;
DAMAGE_RANGE=8;
DAMAGE_MULTI=4;
ATTACKRANGE=96; // small value, but must be larger than the monster's radius
ATTACK_SPECIAL=NEED_SIGHT,FACE_TARGET; // must be able to see target, and will always face target during attack
5) We now need to create our creature sprites, and projectile sprites:
As our friendly monster uses the existing plasma gun bolts, these
won't have to be added to our custom wad, so we'll simply concentrate
on doing the character sprites. We will need a number of sprites for
our new creature:
-the creature walking / chase states
-the creature attack states
-the creature pain states
-the creature death states
-the creature overkill states
All monsters have 8 'views' or rotations (if you open up the doom or
doom2 wad using wintex, you'll see that all monsters can be viewed
from a number of different angles) Some monsters, like the former
humans, only have 5 frames while monsters like the cyberdemon have a
full 8 frames) In the case of five framed monsters, the frames that
show the monster facing front left, left and back left are
automatically mirrored to create the views as seen from the right. See
the Wintex documentation for more information.
What you need to remember is that you must name your sprites using a
four letter description, followed by either:
A1, A2A8, A3A7, A4A6, A5
(for sprites that can be mirrored)
or
A1, A2, A3, A4, A5, A6, A7, A8
(for sprites that are asymmetric, and cannot be mirrored)
* As we already know, the letter A means that these would be the first
graphics displayed in an animation. You will have to change this value
as appropriate.
You should also note that only walking, firing and pain states have
rotations. The death and overkill frames have no rotations, and are
identical no matter what angle they are seen from. Consequently, they
have a four character name suffixed with a frame character, and a zero
(e.g G0, H0, I0)
6) We will need to import our character animation into the WAD
file that we already have our sounds in, and name them as
such:
-All sprites will have the 4 character name Q2FM
-the walking / chase states are frames A to D.
format is A1, A2A8, A3A7, A4A6, A5
-the attack states are frames E and F.
format is E1, E2E8, E3E7, E4E6, E5
-the pain state is frame G.
format is G1, G2G8, G3G7, G4G6, G5
-the death states are frames H to N.
format is H0, I0, J0 etc
-the overkill states are frames O to W.
format is O0, P0, Q0 etc
In EDGE, it is possible to add as many animation frames as you desire.
In this example, the firing sequence is frames E and F (which is all
that was possible with doom) However, such limits don't apply with
DDF. if you wished, you could make a firing sequence that spanned 3, 4
or as many frames as you wished.
7) We now have all our graphics and sounds, so we now need to
make our monster code. Open EDGE's existing THINGS.DDF, PAGE DOWN to
the bottom to add new stuff.
The code will vary considerably from the monster made in tutorial #2.
Firstly, this monster has three seperate attacks which we will have to
manage. We will also have to add some different action pointers so
that our friendly monster will attack other monsters (rather than
us!)
Add the following (no word wrap either):
[Q2FEMALE:888] // thing's name and number (used by map editor)
SPAWNHEALTH=80; // starting health
REACTION_TIME=0.1; // she will move and fire quickly after spotting a monster
RADIUS=20;
HEIGHT=56;
SPEED=12; // quite a bit quicker than other monsters)
MASS=80; // slimmer than the average marine!
PAINCHANCE=50%; // 0% means monster never goes into pain, 100% is always
SPECIAL=SOLID,SHOOTABLE; // monster will block you, and can be shot. Note that we don't use count_as_kill
MINATTACK_CHANCE=60%; // chance that the monster will move or shoot.
1% = move, 100% = shoot
CASTORDER=19; // monster can be seen in cast list at end of map30 in doom2
BLOOD=BLOOD; // when shot, the monster will use the animation 'blood', defined in things.ddf
SIDE=1; // this means that the friendly monster will support player 1.
This tag is vital - without it the friendly monster won't attack
anything. Possible values are 1, 2, 4 , 8, 16, 32, 64 and 128 - which
represent player 1 to 8 respectively. These numbers can be combined,
so side=6 would mean the creature would support player 2 and 3.
PALETTE_REMAP=PLAYER_DULL_RED; // changes green clothes to red...
DROPITEM=CELLS; // drops plasma cells when killed
RESPAWN_EFFECT=RESPAWN_FLASH; // uses the animation respawn_flash when respawns
ACTIVE_SOUND=POSACT; // used by former human
DEATH_SOUND="QFDIE?"; // question mark is a wildcard. If sounds with the prefix QMDIE exist, one will be chosen at random
PAIN_SOUND=QFPAIN;
SIGHTING_SOUND="POSIT?"; // when the creature sees you
RANGE_ATTACK=QF_TRACKER_L; // calls our previously defined attacks
SPARE_ATTACK=QF_TRACKER_R;
CLOSE_ATTACK=QF_CLOSECOMBAT;
STATES(IDLE)=
Q2FM:A:3:NORMAL:SUPPORT_MEANDER, // support_meander makes monster attack enemy monsters
Q2FM:A:3:NORMAL:SUPPORT_MEANDER,
Q2FM:B:3:NORMAL:SUPPORT_MEANDER,
Q2FM:B:3:NORMAL:SUPPORT_MEANDER,
Q2FM:C:3:NORMAL:SUPPORT_MEANDER,
Q2FM:C:3:NORMAL:SUPPORT_MEANDER,
Q2FM:D:3:NORMAL:SUPPORT_MEANDER,
Q2FM:D:3:NORMAL:SUPPORT_MEANDER;
STATES(CHASE)=
Q2FM:A:4:NORMAL:CHASE, // chase directs monster to pursue targets
Q2FM:A:4:NORMAL:CHASE,
Q2FM:B:4:NORMAL:CHASE,
Q2FM:B:4:NORMAL:CHASE,
Q2FM:C:4:NORMAL:CHASE,
Q2FM:C:4:NORMAL:CHASE,
Q2FM:D:4:NORMAL:CHASE,
Q2FM:D:4:NORMAL:CHASE;
STATES(MELEE)=
Q2FM:E:10:NORMAL:FACETARGET,
Q2FM:F:6:BRIGHT:CLOSE_COMBAT,
Q2FM:E:6:BRIGHT:CLOSE_COMBAT,
Q2FM:F:2:NORMAL:REFIRE_CHECK, #CHASE; // goes to chase states
STATES(MISSILE)=
Q2FM:E:10:NORMAL:FACETARGET,
Q2FM:F:6:BRIGHT:RANGE_ATTACK, // fire left attack
Q2FM:E:6:NORMAL:NOTHING,
Q2FM:F:6:BRIGHT:SPARE_ATTACK, // fire right attack
Q2FM:F:2:NORMAL:REFIRE_CHECK, #MISSILE:1; // loops back to frame 1 of missile_states. Refire check makes the monster check if the target has moved or died...
STATES(PAIN)=
Q2FM:G:3:NORMAL:NOTHING,
Q2FM:G:3:NORMAL:MAKEPAINSOUND,#CHASE; // plays QMPAIN
STATES(DEATH)=
Q2FM:H:5:NORMAL:NOTHING,
Q2FM:I:5:NORMAL:MAKEDEATHSOUND, // plays QMDIE1 or QMDIE2
Q2FM:J:5:NORMAL:MAKEDEAD, // monster is now dead and cannot react to anything
Q2FM:K:5:NORMAL:NOTHING,
Q2FM:L:5:NORMAL:NOTHING,
Q2FM:M:5:NORMAL:NOTHING,
Q2FM:N:-1:NORMAL:NOTHING;
STATES(OVERKILL)=
Q2FM:O:5:NORMAL:NOTHING,
Q2FM:P:5:NORMAL:MAKEOVERKILLSOUND, // plays slop sound
Q2FM:Q:5:NORMAL:MAKEDEAD,
Q2FM:R:5:NORMAL:NOTHING,
Q2FM:S:5:NORMAL:NOTHING,
Q2FM:T:5:NORMAL:NOTHING,
Q2FM:U:5:NORMAL:NOTHING,
Q2FM:V:5:NORMAL:NOTHING,
Q2FM:W:-1:NORMAL:NOTHING;
STATES(RESPAWN)=
Q2FM:N:5:NORMAL:NOTHING,
Q2FM:M:5:NORMAL:NOTHING,
Q2FM:L:5:NORMAL:NOTHING,
Q2FM:K:5:NORMAL:NOTHING,
Q2FM:J:5:NORMAL:NOTHING,
Q2FM:I:5:NORMAL:NOTHING,
Q2FM:H:5:NORMAL:NOTHING,#CHASE;
Now, the frames work as such:
[state]=[4 letter sprite name]:[frame letter]:[duration of the frame]:[light level NORMAL or BRIGHT]:[action];
Remember to close the lines with a semi-colon ";". Commas indicate to
continue the loop.
The #CHASE statement 'forces' the creature to go back to it's chasing
states after certain actions take place. You can also use #DEATH,
#PAIN, #MISSILE and #IDLE.
Because our friendly monster has a closecombat attack, we've included
MELEE_STATES, and the action pointer CLOSE_COMBAT.
Click here for a comprehensive
description of all possible actions that can be used with a creature.
At this point, you've done almost everything necessary to get your
creature working. We have the our sounds and graphics in the wad, the
sounds have been defined, attacks coded, and the creature is coded.
All we have to do now is get the monster to appear in the game.
There are 2 basic ways of doing this. The easiest way is to simply
comment out an existing monster (e.g the chaingunner) and then give
your monster the same mapnumber as the chaingunner. This means that
your monster will automatically appear whenever the chaingunner
previously appeared in a map. If you choose this method, be very
careful not to duplicate mapnumbers - otherwise you'll run into all
kinds of problems - as EDGE won't be able to work out which creature
to use.
The second method is to fool around with your map editor. Most good
map editors have a means of adding new or custom items - so read the
documentation that came with the map editor for more info. The
advantage of this method is that you can keep all the old doom
monsters, while introducing new monsters to make things more
challenging!
But before you charge off to kill your new creature, you'll have to
use Wintex or DeuSF to append all sprites to your WAD file with the
sounds and sprites, then run EDGE as such:
edge -file [wadname].wad
That's it!
A neat way of using new creatures is to make copies of the DDF files
and place the ones that you are editing in a new directory. That way,
you can refer to the original DDF files as necessary, and use your
custom DDF files to play with your new creature in the game.
If you do this, you'll need to run it as such:
edge -ddf [directory where you store your DDF files] -file [wadname].wad
Now that you've read this far, you should be getting good at all this
ddf stuff. However, if there is a particular subject that you think
is worthy of a DDF tutorial, then send me an email and I'll see what I
can do.
back to top
DDF docs written by Andy Baker and Ziggy Gnarly, with updates by Andrew Apted.
Site design by Fanatic (with graphics and modifications by Ziggy Gnarly). Problems with the docs, errors and comments should be directed to the EDGE team.
© EDGE Team 1998, 1999, 2000.