Ŀ
                           The CON-file Tutor 1.0                           
                                written by                                  
                        Joris Weimar & Sidney Linkers                       
                       4th Dimension, Copyright(c)1997                      

 Index 


1. Information

    1.1 About the authors
    1.2 Legal stuff
    1.3 Where to get it?
    1.4 Knowledge expected of reader

2. CON file overview

    2.1 What are CON files?
    2.2 How do CON files work?
    2.3 Why are there three CON files?
    2.4 The DEFS and USER CON file structure
    2.5 The GAME.CON file structure




Ŀ
 1. General information 


1.1 About the authors

    This document was written by Joris Weimar (antiwin@worldonline.nl)
    and Sidney Linker (linkers@dds.nl). Because so many people asked us
    how to edit the CONs we decided to make a CON tutorial. One was already
    written by me (Joris), but it was still hard to understand. We've tried
    to keep this tutorial as simple as possible. If you still have a hard
    time understanding some of the stuff in here, please let us know what
    you are having trouble with. Send your comments to the above mentioned
    e-mail addresses.

1.2 Legal stuff

    You are not allowed to commercially exploit this tutorial in any way
    without written permission by the authors. We take no responsibility
    whatsoever for any damage cause by this tutorial.

1.3 Where to get it?

    This document can be found on our very own Duke 3D site
    '4th Dimension' at http//:www.casema.net/~slinkers. If you want to put
    this tutorial on your own page feel free to do so. Just as long as you
    leave this document and all its components together and untouched.


1.4 Knowledge expected of reader

    Although this document is kept as simple as possible, we do expect
    you to have some knowledge:

    - Know how to edit a text file
    - Know how to make a simple map with sprites
    - Programming knowledge (not required but comes in handy)

Ŀ
 2. CON file overview 


2.1 What are CON files?

         To offer more than just gameplay, most games nowadays include
    features to edit various settings in the game. The first thing you
    think of is a map-editor like BUILD. This program allows you to make
    your own custom maps for Duke Nukem. Okay, with this program you can
    make maps but what about monsters, ammo and weapons? Those things can
    not be altered through BUILD. This is where the CONs come in. The CON
    files are files in which monsters, 'weapons' and items are defined. You
    can find them in your Duke 3D directory listing by the names of 'GAME.CON',
    'USER.CON' and 'DEFS.CON'. By editing the CON files you can alter the way
    monsters behave, the amount of health duke starts with and other things.
        What we will teach you in this document, is how to alter the CON
    files to create your own monsters, items and other cool stuff. You will
    get to see that CON programming is not like any other programming
    language. It is very primitive and it doesn't give you much freedom.
    Other than those disadvantadges the CON files are very fun to edit;)

2.2 How do CON files work?

    You might have noticed that when duke starts he says:

Compiling: 'GAME.CON'.
Including: 'DEFS.CON'.
Including: 'USER.CON'.

    While you see these lines the game is busy compiling the CON files.
    That means he is converting the CON files (which are textfiles) to
    his own format (probably directly exectuble code). While he is doing
    this he also checks for errors (spelling errors and other things I
    will get to in a minute). In these CON files ALL the monsters and
    items you see are defined. Here's a simplified overview of a CON
    file (GAME.CON):

    **PIGCOP definition**
    when you see a player start shooting
    when you get shot at, check if you are dead
    if you are dead, show the player you are dying
    if you get frozen, turn blue and break if the player kicks you
    **end of PIGCOP definition**

    **MEDICALKIT definition**
    is the player walking near me?
    does he already have the medical kit?
    no, then give it to the player
    and kill myself (remove myself from the map since I'm not supposed
                     to be here anymore)
    **end of MEDICALKIT definition**

    As you can see, every actor (monster, item) has code attached to it.
    Let's say we have a usermap with only a pigcop and a medical kit in
    it. What the game would do is execute the code for the pigcop and
    the medicalkit about 32 times a second. So the medical kit would check
    those conditions described above 32 times a second.


2.3 Why are there three CON files?

    The only reason that there are three CON files is because it's easier
    to read that way. If you wanted, you could make one CON files out of
    those three. But the CON file would get very big that way, thus hard
    to read. What Duke 3D does is use the GAME.CON file. This file happens
    to have these lines in them:

    include DEFS.CON
    include USER.CON

    When it encounters such a line in a CON file the game will read in that
    file too. You can not include a CON file WITHIN an included file. So you
    can not use the 'include' line in DEFS.CON or USER.CON since those files
    are already included.

2.4 The DEFS and USER CON file structure

    A CON file consists of keywords. Keywords are seperated by spaces, tabs
    or cr's (new line character, Carriage Return). If you wanted to, you could
    make the CON file consist of ONE line. This would make it awfully hard to
    read though ;)
       Let's begin with the simplest keyword: 'define'. 'define' is a keyword
    which allows you to associate a number with a piece of text:

    define NUMBEROFPLANETS 9

    The textstring must begin with 'A-Z' and can be no longer than 32 characters.
    The string may contain (after the first character) alphabetic characters, an
    underscore and numeric characters. The keyword 'define' must be in lowercase
    or else the game won't recognize it.
    This keyword is very usefull since it lets you bind a number to a string.
    This way you don't have to remember the number, just the string. Also when
    a value is used very often, a define can come in handy too. Lets say you have
    a value that describes how fast EACH monster could walk. If you want to change
    this value, you have to go through every monster's code to change this value.
    If you use a define for this...

    define MAXMONSTERSPEED 100

    ... and you use MAXMONSTERSPEED in every monster's code instead of the value,
    you only have to change the line above to effect all the code.
    When you look at the DEFS.CON file, you see alot of defines. This can be
    seen as the define CON file. Most of the defines are made in here.
    USER.CON also counts alot of defines. The number of ammo each weapon can
    carry, the maximum player health and other things are defined here.
    I will now introduce five keywords. These keywords are very similar
    to 'define' but they define different things:

    definequote <number> <text>
    definelevelname <episode number> <level number> <filename> <par-time>
                    <3drealms time> <level title>

    definevolumename <episode number> <episode title>
    defineskillname <skill level> <text>
    definesound <alias> <filename> <minpitch> <maxpitch> <priority> <techvar>
                <volume>

    Examples:

    definequote      150 HELLO THIS IS A TEST
    definelevelname  0 0 E1L1.MAP 00:00 00:00 HOLLYWOOD HOLOCAUST
    definevolumename 2 SHRAPNEL CITY
    defineskillname  3 DAMN I'M GOOD
    definesound      KICK_HIT kickhit.voc 0 0 4 0 0

    The last keyword (definesound) requires that the 'alias' (KICK_HIT in
    this example) is previously defined with the 'define' keyword:

    define           KICK_HIT 400
    definesound      KICK_HIT kickhit.voc 0 0 4 0 0

    These defines don't seem to be usefull now, but they will be later on.
    I'll give you a little preview in how they are used:

    [definequote]

    Within an actor's code (the code that gets executed 32 times per second
    for every actor in the map) you can have a piece of code like this:

    quote 150

    When the game encouters this line (during gameplay) he will do the
    following:

     - check which piece of text belongs to the number '150'. We defined
       quote 150 to be 'THIS IS A TEST' (described above).
     - Display this piece of text on top of your screen.

    This keyword is used, for example, in the Medical Kit actor. Once the
    medical kit actor gives you the medical kit he uses the quote keyword
    to display 'PORTABLE MEDKIT' on top of your screen.

    [definesound]

    Once a sound is correctly defined it can be played like this:

    sound <alias>

    So if we have a sound defined that has the name 'KICK_HIT'. You would
    do this to play the sound:

    sound KICK_HIT

    I have now explained all the keywords in USER.CON expect for two. I will
    get to them now:

    music <episode> <midifilename for level1> <midifilename for level2> etc.

    This will assign a midi file to a certain level in a certain episode.
    The last thing you will need to know are these 'keywords':

    // and /*

    '//' is used to put in comments in your code. Whenever the game encounters
    such a keyword it will skip the line from there and move on to the next.
    If you want to use multiple line comments use the /* and */:

    /*
    this is all comment
    this is comment too
    */

    This pretty much explains the DEFS and USER.CON ;)
        You might've seen me use the word 'filename' a few times. When the
    game wants to play the 'KICK_HIT' sound for example, he will see that
    the sound is located in 'kickhit.voc' as described above. But hey, you
    say, there IS no file called kickhit.voc in my duke3d directory. That's
    right. To keep your duke3d directory as clean as possible, Duke 3d uses
    group files to store their files in. Whenever the game searches for a
    file it will first try to locate it in the group file. If it's not there
    he will look in the duke 3d directory. If on the other hand the file IS
    in the group file but ALSO in the duk3d directory, he will use the one
    in the duke3d directory instead.


2.5 The GAME.CON file structure

    The code you see in GAME.CON is a whole lot more complex than the code
    in DEFS and USER.CON. I will try to explain it as good as possible.
    All of the Duke3D actors are defined in this CON file. A simple 'define'
    is not going to be enough anymore though. Here are the 5 most important
    keywords in the GAME.CON file:

    state <statename>
    action <actionname> <firstsprite> <nrsprite> <numviewangles> <incremental>
           <delay>
    move  <variable> <x-speed> <y-speed>
    ai <ainame> <action> <speed> <aifunction>
    actor <actorname> <strength> <initialaction> <initialai>
    useractor <actortype> <actorname> <strength> <initialaction> <initialai>

    I'll explain all of them:

    [state]

    A state can be seen as a subroutine. You can put code in a state and
    if you want to execute the code just call the state. A state if very
    usefull if you use the same piece of code often. A state must be closed
    with an 'ends' keyword. I'll give you an example of a state:

    state just_a_test  // define a state called 'just_a_test'
    quote 150          // display a quote on screen
    sound KICK_HIT     // make the kicking sound
    ends               // end of state definition

    Later on, when you have created your own actor (which code get executed
    every 32 times a second) you can the state by typing this:

    // other code...

    state just_a_test  // call the state 'just_a_test' end return when you
                       // are done

    // the code continues here after state has been executed...

    An example of an existing state is 'standard_jibs'. This state spawns
    (generates) various body parts. This code is needed very often (in almost
    every monster) so 3DREALMS made it a state (I ripped out some code to
    make it look easy, for now):

    state standard_jibs // beginning of standard_jibs state
    guts JIBS2 1        // spawn some jibs
    guts JIBS3 2        // some more
    guts JIBS4 3        // more
    guts JIBS5 2        // yet another jib
    guts JIBS6 3        // ah, what the heck, let's throw in some more ;)
    state jib_sounds    // call another state called jib_sounds...
                        // this state plays various sounds
                        // once the state is executed it will continue in
                        // here again
    ends                // end of state (execution continues where this state
                        // was called from)

    Don't worry about the 'guts' keyword yet. I'll explain that later on.
    Now for the next keyword.

    [action]

    This is a difficult one to understand. This keyword defines an ACTION
    group. This action group represents an animation. Duke walking is an
    action, the atomic health uses an action (the atoms moving around the
    center). You can see an action as a group sprites bundled. Let's say
    we have three sprites, the first sprite is a wheel, the second sprite
    the same wheel but then turned 120 degrees and the third one also the
    same wheel but then 240 degrees turned. If you see this in an animation
    you would see the wheel turning. So let's define our wheel-action:

    action OUR_WHEEL 50 3 1 1 20
    (only the first parameter is required, the rest is optional)

    We called our animation sequence OUR_WHEEL. So from now on, we can refer
    to this animation as OUR_WHEEL. An action is always used with an actor.
    That means an actor ALWAYS has a animation sequence it shows. This is what
    you see in the game. For example, when the PIGCOP is shooting he is using
    his SHOOTING animation. You can find the sprites of this animation in BUILD
    when you pick a texture (using the key 'V').
         The second parameter is the first sprite number in the animation. This
    number is RELATIVE to the actors number. Every actor has a number, these
    numbers are defined in DEFS.CON. For example, the PIGCOP is number 2000.
    When you go to BUILD and check out sprite number 2000 you will see it's the
    PIGCOP. So the second parameter in the action keyword determines the FIRST
    sprite number in the animation sequence RELATIVE to the actors number. So
    if we were to use this action in the PIGCOP actor (we would not ofcourse,
    because it would like kinda weird if the PIGCOP turned into a wheel all of
    a sudden) the first sprite number in this action would be 2050 because 50
    is our relative number and 2000 is our actor number. 2000 + 50 = 2050 ;)
         The third parameter tells the game how many frames the animation has.
    Well, our wheel has three frames, so we fill in the number three here.
         The fourth parameter is a difficult one to understand. You will need
    some background information to understand it. Duke 3D uses a special tech-
    nique to simulate 3d-actors while displaying 2d-sprites. To simulate this,
    duke3d displays a different frame for each angle you can view him in. To
    limit the number of sprites, duke3d uses (DOOM uses the same technique)
    8 angles. So every frame for a monster actually consists of 8 sprites.
    The first one will be used for if you look at him frontup, the second
    one for if you view him in about 45 degrees, the second one in 90 degrees
    etc. Although DOOM uses 8 sprites Duke3D doesn't. Duke3d uses 5 sprites
    instead. What it does is make double use of the 2nd and 3rd sprite. It
    uses them as 6th and 7th sprite too since these sprites are mirror
    images (he turns the sprite around, in x-direction). This has one downside
    though, sprites are always simetrical around their x-axes. If you make
    your own actor this doens't have to be though. You can tell the game you
    want to use 8 view angles for your sprite. Hell, you can even use 16
    view angles for your sprite to make it really smooth (it takes up alot
    of memory though). To get back to the action sprite, we entered a '1'
    as the number of viewangles. That means there's only one viewanlge so no
    matter what angle you look it at, it always looks the same. The medicalkit
    for example uses a animation-action with only one viewangle. That's why
    you see the medicalkit facing you no matter what angle you're viewing
    it in. This is the value we used too.
         The fifth parameter indicates the stepsize. This determines which
    sprite should be next. If you give this a number of '1' the next sprite
    number will be one heigher. If you, for example, entered a 'numviewangles'
    of 5 it will actually increase the number by 5 since 5 sprites are used
    by this frame.
         The sixth parameter is the delay time between each sprite. How bigger
    this value is how longer each frame lasts.

    [move]

    Move is used to assign a speed to a name. These names will be used
    in keywords described later on.

    move ROCKETSPEED 0 -200

    (only the first parameter is required, the rest is optional)
    This would assign an upwards speed of 200 and a horizonal speed of
    0 to a variable called ROCKETSPEED

    [ai]

    Like actions, ai's also belong to actors. AI stands for Artificial
    Intelligence. With this keyword you can define an AI function for an
    actor. You can make the actor use that AI function. Actually, all an
    actor does is executing ai-functions (most of them anyways). For example,
    the PIGCOP uses a shooting ai, seeking ai, dying ai etc.

    Let's define our own AI:

    ai OUR_OWN_AI OUR_WHEEL ROCKETSPEED faceplayer

    (only the first parameter is required, the rest is optional)
    I'll go through all of the parameters.

    OUR_OWN_AI is the name we give it. Whenever we want to assign this
    ai to our actor we just have to type:

    ai OUR_OWN_AI

    And our actor will use it. When using this AI it will use the
    OUR_WHEEL animation-sequence and it will move with the speed
    defined as ROCKETSPEED. Now for the actual movement. How will
    the actor behave? The last parameter is the movement type. Here
    are some of the types:

    faceplayer:      The actor will point straight at the NEAREST player
    fleeenemy:       The actor will point away from the NEAREST player
    dodgebullet:     The actor will try to dodge bullets
    seekplayer:      The actor will seek the NEAREST player intelligently (not really;)
    faceplayerslow:  The actor will point straight at the player but will update it's heading
                     only about once a second.
    faceplayersmart: The actor will point at the direction the player is GOING to be if
                     the player stays moving with the same speed and direction he does now.
    geth             Keep your horizontal direction
    getv             Keep your vertical direction


    There are a few more but these are the most important ones. You can
    use multiple movement types at once by listing them.

    ai OUR_OWN_AI OUR_WHEEL ROCKETSPEED geth getv // keep moving in the direction
                                                  // (vertical and horizontal) you are
                                                  // pointed at


    All these movement types do to an actor, is POINT them into a certain
    direction. The fact that they have a 'velocity' (determined by the third
    parameter) will cause them to actually MOVE.
    Okay, now we will discuss the MOST important keyword there is!

    [actor]

    Everything in the game that DOES something (elevators, switches
    and other things controlable in BUILD exluded) is an actor. A monster
    is an actor, as is an item like the RPG (the ammo sprite), health boxes
    and other stuff. Let's define our own:
    (only the first parameter is required, the rest is optional)

    actor OUR_OWN_ACTOR OUR_ACTOR_STRENGTH OUR_WHEEL OUR_OWN_AI

    // the actor code comes in here

    enda

    We've just created our own actor (well, sort of;). The name of the
    actor is OUR_OWN_ACTOR. There's one bug though. You MUST define the
    OUR_OWN_ACTOR number before making it an actor so this is the correct
    version:

    define OUR_OWN_ACTOR 3585

    actor OUR_OWN_ACTOR OUR_ACTOR_STRENGTH OUR_WHEEL OUR_OWN_AI

    // the actor code comes in here

    enda

    The actor number is now 3585. This means if we put a sprite number
    3585 in a map. The code above (which currently does nothing) would
    be executed 32 times a second.

    [useractor]

    The useractor command works 'almost' exactly the same as the actor
    command with the difference that there's an extra parameter (it has
    a few other differences but these are very technical).

    useractor enemy OUR_OWN_ACTOR OUR_ACTOR_STRENGTH OUR_WHEEL OUR_OWN_AI

    The second parameter (enemy) tells the game what kind of actor it is.
    There are three types:

    enemy:        This means the code in the actor doesn't get executed
                  until the actor spots you (with about a two second
                  delay)
    notenemy:     This means the code in the actor gets executed from the
                  moment the game (map) gets started
    enemystayput: This means that if the actor moves, he can not leave his
                  sector.


    Okay, let's do something 'practicle'. Let's make a quick actor that
    does nothing else then putting a quote on your screen:

    --- CUT ---

    define      OURACTOR 105
    definequote 150 THIS IS A TEST

    useractor notenemy OURACTOR

    quote 150

    enda

    --- CUT ---

    Put this code at the end of your GAME.CON. Then place a sprite '105'
    in a map (just a simple one sectored map) and run the map with duke.
    A few seconds after the map starts you will see our quote on your
    screen. The quote will stay on your screen until you quit. Usually a
    quote dissapears after a while but because our quote gets called
    over and over again (32 times a second), the quote stays on your screen.
    Try it out!

    The reason I did not define an action and ai is because this actor
    does not need it. So, if he doesn't need it, you can just leave it
    out.


Have fun!

This document was last updated on Thursday, February 20, 1997 12:54 AM.
Copyright(c)1997 by Joris Weimar & Sidney Linkers, 4th Dimension
