Skip to content

Tutorial 3: Creating a Friendly Creature

dashodanger edited this page Dec 14, 2021 · 1 revision

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 an enemy 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-Classics's existing DDFSFX, 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

[Q2FDIE2]
LUMP_NAME="DSQFDIE2";
PRIORITY=60;

[Q2FPAIN]
LUMP="DSQFPAIN";
PRIORITY=60;

I should just note that the DDFSFX lump is very important. It is quite easy to add your sound files to your WAD, and use those sounds in your DDFATK and DDFTHING definitions. However, if you don't identify the sounds in DDFSFX, then EDGE-Classic 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-Classics's existing DDFATK, 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.VAL=8;
DAMAGE.MAX=80;
ATTACK_HEIGHT=32;
X_OFFSET=-30; // attack moves 30 units to left
SPEED=10;
TRANSLUCENCY=40%; // somewhat see through
NO_TRACE_CHANCE=0%; // always traces target, 100 never traces
TOO_CLOSE_RANGE=196; // will move to close combat 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
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.VAL=8;
DAMAGE.MAX=80;
ATTACK_HEIGHT=32;
X_OFFSET=30; // projectile launches from the right
SPEED=10;
TRANSLUCENCY=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, // 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;

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.VAL=8;
DAMAGE.MAX=32;
ATTACKRANGE=96; // small value, but <u>must</u> 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-Classic, 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-Classics's existing DDFTHING, 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 DDFTHING
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 <U>and</U> 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_ATTACK,
                Q2FM:E:6:BRIGHT:CLOSE_ATTACK,
                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 its chasing states after certain actions take place. You can also use #DEATH, #PAIN, #MISSILE and #IDLE.

Because our friendly monster has a close combat attack, we've included MELEE_STATES, and the action pointer CLOSE_COMBAT.

Check the "DDF Attacks" section in the sidebar 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 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 map number as the chaingunner. This means that your monster will automatically appear whenever the chain gunner previously appeared in a map.

If you choose this method, be very careful not to duplicate map numbers - otherwise you'll run into all kinds of problems - as EDGE-Classic 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-Classic as such:

edge-classic.exe -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-classic.exe -ddf [directory where you store your DDF files] -file [wadname].wad


DDF docs written by Andy Baker and Ziggy Gnarly, with updates by Andrew Apted, Andy Brewood and Luke Brennan. © EDGE Team, et al. 1998 - 2021.

Home

EDGE-Classic Mod Downloads

COAL

DDF     Introduction
    Animations
    Attacks
    Colormaps
    Flats
    Fonts
    Games
    Images
    Languages
    Levels
    Lines and Sectors
    Playlist
    Sounds
    Styles
    Switches
    Things
    Weapons
RTS     Introduction
    Conditions
    Directives
    Flow Control
    Level Commands
    Maps and Triggers
    Properties
    Thing Commands
    Tips and Menus
Tutorials     Creating a Weapon
    Creating an Enemy
    Creating a Friendly Creature

Compiling EDGE-Classic

Clone this wiki locally