home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Hot Shareware 32
/
hot34.iso
/
ficheros
/
VDUKE
/
CONEDIT.ZIP
/
CONEDIT.FAQ
Wrap
Text File
|
1996-12-28
|
64KB
|
1,754 lines
Release date: 12/27/1996 12:55
--- CON Editing FAQ ---
version 2.0
by
Joris B. Weimar
--------------------------------------------------------------------------
INDEX
--------------------------------------------------------------------------
1) Information
1.1 Who wrote this FAQ and some general info
1.2 Where did the author get the information?
1.3 What's new?
2) CON building blocks
2.1 What's a state?
2.2 What's an action?
2.3 What's an ai?
2.4 What's an actor?
2.5 What's an useractor?
2.6 What is an 'if' construction?
2.7 The complete primitive list
2.8 Predefined states
2.9 Known .CON bugs
3) Examples
3.1 Example 1: Make the atomic health sprite pulsating
3.2 Example 2: Make your own Duke Bot
4) General CON overview
4.1 DEFS.CON
4.2 USER.CON
4.3 GAME.CON
5) Appendix
5.1 What I would like to know
5.2 Contributers/Thank you's
5.3 Update and info
5.4 Where to get this FAQ
--------------------------------------------------------------------------
1.1 Who wrote this FAQ and some general info
--------------------------------------------------------------------------
This FAQ was written by Joris Weimar also known as 'antiwin'. I'm a huge
fan of Duke Nukem and until recently I didn't do anything with the CON
files other then change some simple values such as MAXPLAYERHEALTH etc.
After some of the primitives you will notice a sign like this "[PP]".
This will mean the primitive or functionallity is only available in
Plutonium Pak. PP is short for Plutonium Pak (do'h!).
I must admit that I'm don't know everything on .CON hacking but I know
when *I* knew nothing about it I wanted to get every information I could.
So here it is. Whenever I searched the net for a CON FAQ I _always_ got
the same FAQ. I hope this FAQ will go furhter into subjects that that FAQ
(you surely now which FAQ I'm reffering to) brought up. I'm asking you
friendly to keep the name of this FAQ 'CONEDIT.FAQ' or 'CONEDIT.ZIP' when
zipped. This to eliminate confusion.
If you have any questions, tips, corrections or comments about this FAQ
you can reach me via e-mail at antiwin@worldonline.nl. You can also call me
at +31 (0)70 3520655.
--------------------------------------------------------------------------
1.2 Were did the author get the information?
--------------------------------------------------------------------------
Well, I _did_ learn something from the FAQ by Ben Cantrick. But most of
the stuff I found out by myself by just trying, trying and trying. I re-
wrote the entire code for the pigcop. It's still buggy and there are still
some things that I don't comprehense. But he sure has gotten tougher.
You'll find an PigCop-to-Duke example in this FAQ. Ok, now lets get on
with the good stuff.
--------------------------------------------------------------------------
1.3 What's new?
--------------------------------------------------------------------------
* version 0.1ß
- First release.
* version 0.2
- Changed the index
- Added some more primitives
* version 0.3
- Expanded the PigCop example
- Fixed some misspellings :-)
* version 0.4
- Expanded the PigCop example
- Added 'Contributor/Thank you's' part
- Added 'Where to get this FAQ' part
* version 0.5
- Added 'Predefined states' part
- Removed those 'line-drawing' chars for Windows compatiblity
* version 0.6
- Changed pigcop into duke :-)
- Fixed several code pigs
* version 0.7
- Removed pigcop example
- Started a new more simpler example
* version 0.8
- Update the new example
- Rename keywords to primitives
- Added 5 new primitives
- Documented a few unknown primitives
* version 0.9 - 1.1
- never released
* version 2.0
- New example
- Added new Plutonium Pak primitives
--------------------------------------------------------------------------
2.1 What's a state?
--------------------------------------------------------------------------
A state is a subroutine. Whenever you call a state he executes that
function and return to where you called it.
Example:
state saysecretplace // Start a state definition
quote 9 // Some code
ends // End of state (return to caller)
This is a state (subroutine). Whenever you call it it executes the code
contained in it. In this example that would be the command 'quote' which
prints a text on screen. 9 is the defined in USER.CON (definequote) as
"A SECRET PLACE!". Now we must call it from somewhere:
state saysecretplace // execute the state, thus printing "A SECRET PLACE!"
You can call a state from within a state like this:
state test2 // State test2 definition
quote 9
ends // End of state
state test1 // State test2 definition
state test2 // Call the test2 state
ends // End of state
Now to print the quote on screen do this:
state test1
or ofcourse this (this does it directly while the above example first
calles another state):
state test2
Now he will print "A SECRET PLACE!". You may think to yourself: "hmmm... I
can understand this but where do I put it in the .CON". Well, I'll get to
that later.
--------------------------------------------------------------------------
2.2 What's an action?
--------------------------------------------------------------------------
An action is used to give a group of sprites a name. Usually this group
of sprites is animated. The structure of the action command is:
action <name> <startframenum> <numframes> <type> <incvalue> <delay>
<name> = This can be any string up to 64 characters long.
<startframenum> = starting frame number. Note: this number is rela-
tive to the main sprite of the actor. If you want
the pigcop to look like the atomic health you need
to give the starting frame a number of -1900 since
the pigcop main character is 2000 and the atomic
health is 100
<numframes> = Number of frames in action group.
<type> = This value determines wether the picture is onesided
(looks the same no matter what angle you
see it from) or 3D. When 3D every sprite will contain
actually 5 sprites. One seen from upfront, one from the
back, one sideways and two from resp. 45 degr. and 135
degr. The other three angles are created from the other
sprites by flipping the x-coordinates. Give <type> a
value of 1 to make it onesided. 5 makes it 3D. I don't
know if there are any other legal values but I wouldn't
bet on it. One possible value could be 8 though. I'm not
sure, but when this value is used I guess the expects
there to be 8 sprites for each frame (45,90,135degr etc.)
<incvalue> = This is the incrementing value. Negative values are
allowed.
<delay> = This determines how long each frame lasts. Bigger values
lets the frame take longer.
Example:
action ATOMIC 0 15 1 1 10
Ok, this _is_ still kind of complex but you'll get to use this stuff in
a minute.
--------------------------------------------------------------------------
2.3 What's an ai?
--------------------------------------------------------------------------
An ai is some sort of definition of a state of an actor. Here's the struc-
ture:
ai <ainame> <action> <speed> <aitype>
<ainame> = Just a string to identify it for later use.
<action> = action group id. This is the group of frames
the actor will cycle through as he is using this ai
function.
<speed> = Rate of movement of character when using this ai
function. It seems that <speed> must be a value
defined by move (move WALKSPEED 100). Negative
values are allowed.
<aitype> = Determines type of ai. The ai types are already
programmed in the game so you can't change these.
Some of the legal types are:
seekplayer: The actor will walk up to the _nearest_
player.
fleeenemy: The actor will run away from a player.
faceplayer: The actor will point his crosshair at
you thus facing you.
faceplayersmart: The actor will point his crosshair
a little bit next to you in the direction
that you're heading. Kind of smart, isn't
it.
dodgebullet: Evasion manouvre.
randomangle: Change actors direction to a random
angle when it hits the wall. Or walk
up to the player when actor is being
shot at.
You can more than one ai at the same time by listing
them: randomangle dodgebullet etc.
When you want the actor to use an ai function do it like this:
ai <name>
where <name> is the same as <ainame> explained above.
--------------------------------------------------------------------------
2.4 What's an actor?
--------------------------------------------------------------------------
Everything that has vertices (drawn in build) is _not_ an actor. So walls,
floors, elevators, doors are _not_ actors. Every sprite has the potential
of being an actor. Some examples are:
Duke, Pigcop, Medicalkit, Health, RPG sprite etc...
The structure of the actor command is:
actor <initialspritenum> <strength> <action> <speed> <aifunction>
<initialspritenum> = This number is the tile number (as in build, editart)
from which all actions that this actor can do are
relative. For a PIGCOP this value is PIGCOP which is
defined (in USER.CON) to be 2000. If you look in build
at location 2000 you'll see the PIGCOP character.
<strength> = This value tells the game how much damage it can take.
If you give this parameter a value of 0 the actor can
not be destroyed (bummer).
<action> = The action number refers to an action group as de-
scribed above. Regarding to monsters this is usally
some kind of initial action group. He is just standing
and doing nothing.
<speed> = Speed is the rate of movement this character has, if
the character doesn't move give this a value of 0 or
don't give this value at all.
<aifunction> = His initial ai routine. With monsters this is usually
a still standing monster waiting for someone to discover
him. You can read the defenition of ai in the section
above.
The actor code is the main code of a character. It's structure goes like
this:
actor ... (describer above)
// The code contained hereign is the main code of the character. Each time
// (frame) this code gets called!
enda // End of Actor
As I heard from "StratonAce" we can not add new actors. We can replace
other actors by removing the old code and placing in our. "StratonAce"
also informed me that this restriction is possibly removed with the
upcoming Plutonium Pak version of Duke (1.4)
--------------------------------------------------------------------------
2.5 What's an useractor? [PP]
--------------------------------------------------------------------------
The useractor command is new to PP. It allows people to create their
own actors in PP without having to replace old ones. It's almost exactly
the same as a conventional actor with a few exeptions. For example,
enemies created with the useractor command will not shoot straight and
their size might not always be proportional (like the bug in BUILD).
The structure of the actor command is:
useractor <type> <initialspritenum> <strength> <action> <speed> <aifunction>
<type> = This tells PP the type of actor you want to create.
The legal values are 'enemystayput', 'enemy' and
'notenemy'. Explenations follow:
enemy = The actor's code will not be executed until
approximatly 1 second after the player has
spotted the actor.
notenemy = The actor's code will not be executed until
the player has spotted the actor.
enemystayput = The actor's code will not be executed until
approximatly 1 second after the player has
spotted the actor AND the actor's code will
not be executed if the player is not in sight.
<initialspritenum> = This number is the tile number (as in build, editart)
from which all actions that this actor can do are
relative. For a PIGCOP this value is PIGCOP which is
defined (in USER.CON) to be 2000. If you look in build
at location 2000 you'll see the PIGCOP character.
<strength> = This value tells the game how much damage it can take.
If you give this parameter a value of 0 the actor can
not be destroyed (bummer).
<action> = The action number refers to an action group as de-
scribed above. Regarding to monsters this is usally
some kind of initial action group. He is just standing
and doing nothing.
<speed> = Speed is the rate of movement this character has, if
the character doesn't move give this a value of 0 or
don't give this value at all.
<aifunction> = His initial ai routine. With monsters this is usually
--------------------------------------------------------------------------
2.6 What's an 'if' construction?
--------------------------------------------------------------------------
Okay, this is really the power of any programming language. In many
occasions you want to execute some code (listed below, 2.6) IF some-
thing is true, or IF something is false. You also want something ELSE
to be executed if the condition is false:
IF I AM HUNGRY
EAT A SANDWICH
ELSE
WaiT UNTIL LATER
Well, now to get a bit more in Dukes direction, this is some code of
my new Pig Cop. He fires a SHRINKER, but only when you're not on ste-
roids because when you use steroids you won't shrink (you knew that,
right?):
ifp ponsteroids
shoot SHOTGUN
else
shoot SHRINKER
in PSEUDO code that is:
if duke is on steroids
shoot him with the shotgun
or else
shoot him with the shrinker
If you didn't know the 'ifp ponsteroids' and 'shoot' command yet, don't
worry. They are all listed below. Ofcourse you may want to execute MORE
than one function. Then you'll have to use the braces '{' and '}'.
ifp ponsteroids
{
shoot SHOTGUN
sound SHOTGUN_FIRE
}
else
{
shoot SHRINKER
sound SHRINKER_FIRE
}
You see that all the code between the two braces is considered as ONE
function.
--------------------------------------------------------------------------
2.7 The complete primitive list
--------------------------------------------------------------------------
Now, you're wondering, what kind of code can I put in these actors and
STATEs. Well, you already saw one of them: QUOTE. That's ofcourse not
enough to create a character like for example a PigCop. Ok, here are
the most important functions:
// = Everything on the line after the '//' will
be ignored.
/* ... */ = Everything between the '/*' and the '*/' will
be ignored.
action <actiongroup> = Assign sprite animation group to current
actor. See definition above.
actor ... = See definition above.
addammo <weapon> <amount> = Add the given number of ammo to the player.
He does not get the weapon if he hasn't got
it. The legal values are describer in USER.CON
addphealth <amount> = Add the value <amount> to the players health.
When playing with more than one player I suspect
the closest one will be effected. This goes for
all player related functions.
addinventory <item> <amnt> = Add <amount> to the item <item>. The legal
values for <item> can be seen with the
'ifpinventory' function.
ai <name> = Let current actor use the ai function <name> from
now on.
addstrength = Adds strength to the current actor.
addweapon <weap> <ammo> = Gives nearest duke weapon <weap> with an initial
amount of ammo equal to <ammo>.
Legal weapons are:
- HANDBOMB_WEAPON
- RPG_WEAPON
- SHOTGUN_WEAPON
- PISTOL_WEAPON
- TRIPBOMB_WEAPON
- CHAINGUN_WEAPON
- SHRINKER_WEAPON
- FREEZE_WEAPON
- DEVISTATOR_WEAPON
break = Immediatly leave a STATE or actor.
clipdist <value> = I have no idea ;)
count <num> = Sets the counter to <num>. I believe the game
gives every actor its own counter since this
function could heavily mess up the timer of
other actors
cactor <actor> = Call the code of the actor identified by
<actor>
cstat <mask> = With this function you can do some nice tricks.
This is used to change some actor settings for
the current actor. Some of the legal values are:
1 = Make sprite blockable ("B" in BUILD)
2 = make actor 'see-through'.
4 = flip sprite around x-axis.
8 = flip sprite around y-axis.
16 = Draw him as wall texture (vert. flat)
32 = Draw him as floor texture (hor. flat)
64 = Make sprite one sided.
128 = Half submerged.
256 = Make sprite solid ("H" in BUILD)
32768 = Invisible
To use more than one setting add the values
together (264 = solid+upsidedown, 256+8).
cstator <mask> = Same as cstat, but it keeps doesn't reset
all the previous settings. It just adds the
ones you specify. A bit like the 'or' in
several programming languages.
debris <actiongrp> <amount> = Causes debris to fly all over the place.
<actiongrp> is the sprite animation used for
the debris. Legal values seem to be 'SCRAP1'
and 'SCRAP2'. The higher the amount the more
debris. 2 seems to be a reasonable value. But
it's up to you.
debug <value> = Prints a <value> on screen. This value will
be printed in the ULGY standard font and duke
will not try to save the background. I don't
now what forms <value> can take.
define <string> <value> = Defines a value as a string. This way you can
use the string instead of the number (easier to
remember). The Duke3D compiler will replace every
occurance of <string> with <value>
definequote <value> <string> = Binds a string to a number. The string can now
be displayed by using the 'quote' primitive.
defineskillname <value> <s> = Defines the string 's' associated with the
difficulty level 'value'. 0 is easy and 3
is hard.
[PP]
definelevelname <ep> <lev>
<mapname>
<par time>
<3drealms> = Defines a level where the episode number is
'ep' the level number if 'lev' the mapname
is 'mapname' the partime is 'par time' and
3drealms' time is '3drealms'.
definesound <value> <filename>
<begin pitch>
<end pitch>
<priority>
<flags> <volume> = Binds the sound file 'filename' to 'value' and
tells the game the sound may be pitched from
'begin pitch' to 'end pitch'. The sound priority
is 'priority' and the type of sound is defined
in 'flags'. Volume is the volume adjustment.
definevolumename <ep> <name> = Defines title for each episode. 'ep' is the
episode number and 'name' is the name it will
get.
[PP]
enda = End of actor code marker.
endofgame <number> = Ends the game. I'm not sure what <number> means
but 52 is used to end level 3 (BOSS2).
ends = End of state code marker.
fall = Let the current actor fall until it hits a
surface.
gamestartup ... = This is the main function which 'starts' the
game. It gets all the hardcoded values passed
as parameters. The values it gets passed can not
be changed during gameplay.
getlastpal = Sets the palette of the current actor back
to the color before the last change.
guts <actiongrp> <amount> = Same as debris but then for bodyparts. Legal
values for <actiongrp> seem to be:
- JIBS(1 to 5)
- HEADJIB/LEGJIB/ARMJIB (trooper parts)
- LIZMANARM1/LIZMANLEG1 (lizman parts)
- DUKETORSO/DUKELEG/DUKEGUN (duke parts)
<amount> determines the amount of guts to fly.
globalsound = Play sound that can be heard everywhere in the
map.
hitradius <c> <1> <2> <3> <4>= Make an explosion (not the actual animation but
just the damage). <c> is the radius. <4> is how
much damage is done in first quarter of circle
seen from inside to outside.
<3> is how much damage is done in second quarter
of circle etc.
ifactornotstayput = (not sure) Test if the current actor already
'activated', where 'activated' means spotted
by a player or he has spotted the player.
It seems that an actors code isn't executed
at all until one of the above events occur.
You can notice this in the game. If you
create a map where an actor (ie. health) is
lifted into the sky, he doens't fall down to
the ground until you spot it!
ifactor <actorid> = Checks if current actor was called with cactor
by <actorid>
ifaction <actionnum> = Test if the current actor is executing the
giving <actionnum>. <actionnum> is defined
by the action primitive, remember?
ifactioncount <number> = Tests if the actors has display <number> frames
since the last call to resetactioncount
ifai <ainame> = Tests if the current actor is using the ai
function <ainame> which was defined with the
'ai' primitive.
ifangdiffl <angle> = If the angle between the current actor and duke
is less than <angle> it returns true. 360 degrees
is 2048.
ifangdiffg <angle> = If the angle between the current actor and duke
is less than <angle> it returns false. 360 degrees
is 2048.
ifawayfromwall = Returns false when actor is on a wall-line.
This would be a line that can be seen in
BUILD.EXE. I don't know the actual use for
this.
ifbulletnear = Tests if a bullet is near the current actor.
This is a nice one because you can use it like
this:
ifbulletnear
ai AIRUNAWAYFROMBULLET
Okay, maybe you don't understand this yet, but
I'll explain it later. For now, let's say this
code means:
If there is a bullet nearby then go into another
ai function that makes the actor runaway with high
speed (fleeenemy aifunction).
ifcansee = Tests if the current actor can see duke. It
also seems to have another function.
It seems as if you need to call this function
to give an actor a new position to walk to when
using the seekenemy and some other ai functions.
If you don't call this when using that ai function
he will just walk up to your previous position
and just stop there!
ifcanseetarget = Tests if the current actor can see duke. I'm not
about this one though.
ifcanshoottarget = Tests if the current actor can shoot his
target. I don't know what 'can shoot' means.
ifceilingdistg <num> = Tests if the distance to the ceiling is greater
than <num>
ifceilingdistl <num> = Tests if the distance to the ceiling is less
than <num>
ifcount <num> = Tests if the number of frame (I don't actually
know how long a frame takes) is reached. These
are not action frames so they are not limited
to one actor. See it as some sort of global
counter.
ifdead = Checks if actor has no health left. Good thing
to call after he has been hit with a weapon. If
he was and he's dead you need to remove the actor
from the map (killit).
iffloordistg <num> = Same as 'ifceilingdistg' but now for the floor.
iffloordistl <num> = Same as 'ifceilingdistl' but now for the floor.
ifgotweaponce <num> = Seems to test if a player has a particular weapon.
The weapon tested would be the current actor.
This code would logicaly only appear in weapon
actors such as RPGSPRITE.
I'm not sure what the <num>'s use is. The values
passed in the real CONs where 0 and 1. (?)
ifhitspace = Checks if duke is hitting the spacebar.
ifhitweapon = Tests if the current actor has been hit by a
weapon. Use 'ifwasweapon' to check which weapon
it was.
ifgapzl <num> = Tests if the distance between the floor and
the ceiling at the actor's location is less than
<num>.
ifinspace = Checks if current player is in space. 'space'
means when the floor/ceiling is parralaxed and
the texture is one of the space-textures.
ifinwater = Tests if the current actor is in the water.
ifinouterspace = Tests if the current actor is in outer space?
ifonwater = Same as 'ininwater', but then for 'on' the water.
ifmove <name> = Tests if variable <name> is greater than 0. (not sure)
ifnosounds = Tests if a sound is playing.
ifnotmoving = Tests if the current actor is moving. Not sure
about this one.
ifspawnedby <actor> = Checks if the actor who spawned the current
actor is equal to <actor>
ifspritepal <num> = Tests if the palette of the current actor is
equal to <num>
ifsquished = Tests if the current actor has been squished.
ifoutside = Tests if player is outside. A player is outside
when he is in a room with parralaxing on!
ifp <type> = Tests if the player (when I say player I always
mean Duke, but you knew that, right?) is doing
<type> where type can be:
pstanding = Duke is standing
pwalking = Duke is walking
prunning = Duke is running
pducking = Duke is ducking
pfalling = Duke is falling
pjumping = Duke is jumping
phigher = Duke is higher than the cur. actor?
pwalkingback = Duke is walking backwards
prunningback = Duke is running backwards
pkicking = Duke is kicking (ass)
pshrunk = Duke is a smurf (shrunken)
pjetpack = Duke is flying (jetpack)
ponsteroids = Duke is using his steroids
ponground = Duke has his both feet on the ground
palive = Duke hasn't died yet
pdead = Duke has been exterminated
pfacing = Duke is facing the current actor
You can test for more things at the same time.
'ifp prunning pwalking' returns true when either
of the two is true.
ifpdistl <number> = Tests if the players (nearest player) distance
if less than <number>. 1024 appears to
be the largest grid in BUILD.
ifpdistg <number> = Same as ifpdistl but he now tests if the
distance is greater.
ifphealthl <num> = Tests if the players health is less than
<number>.
ifphealthg <num> = Tests if the players health is greater than
<number>.
ifpinventory <item> <amount> = Tests if the nearest player has less than
<amount> left of item <item> where item can
be:
- GET_STEROIDS
- GET_HEATS
- GET_BOOTS
- GET_SHIELD
- GET_SCUBA
- GET_HOLODUKE
- GET_JETPACK
- GET_FIRSTAID
- GET_ACCESS (when using this the amount seems
to be a bitlist of cards we have
0 = no cards 1 = blue card etc...)
ifrespawn = Tests if the monster-respawn-mode is on. If
so, the actor needs to respawn after RESPAWN
TIME.
ifrnd <num> = This is a randomize function. <num> is the
chance you give it to be true. If <num> is
256 it wil be always true and 128 50% of the
times. If you want less chance than 1/256 you
need to use two ifrnd's like this:
ifrnd 1
ifrnd 128
// This code gets executed 1/512.
ifsquished = Tests if the current actor has been squished
(shrunken and stepped on).
ifstrength <num> = Tests if current actor has <num> strength left.
ifwasweapon = Tests what weapon the actor has been hit by.
include <filename> = Includes <filename> in the compiling process.
killit = Removes the current actor from the map. The
won't be called anymore.
lotsofglass <amount> = Animate glass that breaks as if a window
has broken. <amount> determines the ehhh...
amount of glass. 30 seems to be a reasonable
value.
mail = Spawn some mail?
mikesnd = Plays the microphone sound...
money <num> = Spawns <num> dollar bills.
move <name> <v1> <v2> = Give <name> a value of <v1> and a optional
value of <v2>. When the variable is used to
define the speed of an actor the second
variable is used for vertical speed. This
way you can simulate a character to use a
jetpack. I've also seen <v1> and <v2> to
be given ai function. What the meaning of
that is I'm not entirely sure. If you change
the velocity of an actor during it's code
it will automaticly update.
music <ep> <m1> <m2> ... = Defines MIDI music for each episode where
'ep' is the episode number and m1, m2 etc.
are the individual music files for each
level.
nullop = nullop equals '{ }'. Now you can say:
ifspritepal 1 nullop else { quote 1 }
instead of ifspritepal 1 { } else { quote 1 }
operate = Let's the current actor operate. If a door
is nearby the door will open. This is a nice
function for a clever actor. This actor could
open a door where you fled through. You would
have something like this in your main code:
ifrnd 1 operate
You _don't_ want to operate every time because
the second time you operate the door closes
again.
palfrom <begin> <end> <del> = Change palette to color <begin> and then to
<end> and then back to normal again (I think?).
0 or 32 = Green
16 = Red
paper = Spawn some paper?
pstomp = Player will look down and step on the near
actor (if one is near)
pkick = Player will kick. Good to call from an actor
who has been frozen. First do:
'ifp pfacing' then 'ifpdistl FROZENQUICKKICKDIST'
then 'pkick'.
quote <num> = Print quote <num> on screen. All quotes are
defined in USER.CON.
resetactioncount = This resets the counter that counts how many
frames of the current actor have been exectuted.
The speed of actioncount is determined by the
<delay> parameter in the action structure.
resetcount = This resets the global count. This is the counter
that is not bound to a given actor but count at
the same rate for every actor
I believe the counter increments every 3/100th
of a second.
resetplayer = Resets the player in a multiplayer game and
places him at one of the APLAYER locations.
respawnhitag = This code seems to spawn the actors that need
to be spawned when the current actor dies. An
example of this would be the dancing girls in
the bar in E1L2.
shoot <weapon> = Let's the current actor shoot with <weapon>.
Legal values for weapons are defined in USER.CON.
The direction in which the actor shoots is de-
termined by the AI function of the actor. If it
is 'faceplayer' he will obviously shoot at the
player. But if you have 'seekplayer' as AI function
the actor may be heading to the player but since
he doesn't go straight to him he can easily miss.
Some of the weapons are (these names are also used
for ifwasweapon):
SHRINKSPARK,
SHOTGUN,
RPG,
CHAINGUN,
FREEZEBLAST,
KNEE,
SPIT,
FIRELASTER,
HEAVYHBOMB,
BOUNCEMINE,
MORTER,
DEVISTATORBLAST and
TRIPBOMB.
sizeat <x> <y> = Makes the current actor <x> times smaller in
x-direction and <y> times smaller in y-direction.
The difference between sizeat and sizeto is that
sizeat makes the change immediatly while sizeto
resizes the actor graduatly.
sizeto <x> <y> = Makes the current actor <x> times smaller in
x-direction and <y> times smaller in y-direction.
sleeptime <time> = Makes the current actor sleep for <time> counts?
sound <soundnum> = Play a sound. The soundnumbers are defined in
USER.CON.
soundonce <soundnum> = I think when using this sound, it will not
be activated again until it is finished.
spawn <actor> = Bring a new actor into the map defined by
<actor> There seems to be once special
<actor> (there may be more) which has a
unique effect on the current actor. When
you spawn 'FRAMEEFFECT1' the current actor
while blur. This effect can be seen when
an actor is shrinking or a player is on
steroids.
spritepal <num> = Changes palette number of sprite. Legal values
are:
1 = Blue
4 = Dark
6 = Night vision Green
7 = Yellow (sort of)
8 = Green
10 = Red
19 = Red as a tomato
22 = Almost normal
state <statename> = Enter a state named <statename> and return
from it. If this line is put out of any
actor or state code it is interpreted as
a state definition.
stopsound <sound> = Stops to play the sound 'sound'. Good for ending
long sound effects when they have no use anymore.
strength <num> = This function changes the strength of the current
actor in <num>
tossweapon = Let's duke spawn his currently selected weapon
with a 50% chance. This code gets called when
Duke dies.
wackplayer = Tilt the screen. As if you're struck by lightning.
--------------------------------------------------------------------------
2.8 Predefined states
--------------------------------------------------------------------------
Here's a list of states that are already defined in GAME.CON. You can
ofcourse alter these but here's a list of some of them (call these
state like this: 'state <name>') :
- genericshrunkcode
Shrink actor and stomp if within correct distance
- blimbhitstate
Make explosion. Spawn debris, kill actor and some other stuff...
- rats
Generate some rats.
- headhitstate
Gets called when player is being hurt bad.
- burningstate
Lites the current actor on fire.
- steamcode
Update steam sprite (subtract health from player who is near etc.)
- burningbarrelcode
Code for a burning barral (duh!)
- get_code
Gets an item and prepares it for respawn if neccesary.
- randgetweapsnds
Plays a random sound when called such as 'Groovy' or 'Come get some' etc.
- getweaponcode
Gets the current weapon and prepares it for respawn if neccesary.
- respawnit
Respawns the item in multiplayer game.
- firestate
Updates flames and checks if duke is burning himself etc.
- jib_sounds
Plays one of those nice sound like 'What a mess' or 'Let god sort them out'.
- standard_jibs
Spawns some random bodyparts.
- femcode
Takes care of the females in duke. Kill them or let them show their boobs.
- killme
Lets woman say "kiiillll meeee...." when duke hits space near her.
- tipme
Lets duke give woman a dollar bill and say 'Wanna dance' or 'Shake it baby'.
- troop_body_jibs
Spawns some trooper body parts.
- liz_body_jibs
Spawns some lizard body parts.
- delete_enemy
Deletes the current actor (removes it from the map).
- standard_pjibs
Spawns some duke body parts.
Ok, that's it for now.
--------------------------------------------------------------------------
2.9 Known .CON bugs
--------------------------------------------------------------------------
I added this section since I discovered a bug. I'll bet there will be
more.
bug 1:
This 'if' construction...
ifcansee
ifai AIDUKEWANTTOSTOMP
{
}
else
ai AIDUKEWANTTOSTOMP
...should be equal to...
ifcansee
{
ifai AIDUKEWANTTOSTOMP
{
}
else
ai AIDUKEWANTTOSTOMP
}
... but it isn't. In the first case the 'else' part always gets
executed. _Huge_ bug.
I don't know if it's a bug or not but it sure is strange. When you give a
character like a pigcop a huge amount of strength like 4500 then he will
move like thunder when you hit him with a RPG.
--------------------------------------------------------------------------
3.1 Example 2: Make the atomic health sprite pulsating
--------------------------------------------------------------------------
Okay, we're gonna make the atomice health sprite pulsate between
visibility and invisibility graduatly. Ought to look pretty cool!
(under construction... sorry)
--------------------------------------------------------------------------
3.2 Example 2: Make your own Duke Bot
--------------------------------------------------------------------------
The example in the last couple of versions of this FAQ was getting a
little complex for some of you guys. It even had some huge bugs in
it. But here's a new example and I'm keeping it as clear as possible.
We're gonna try to create a new Duke character. This character will
eventually do the following:
- when at a distance he will either fire some rockets or
run up to you
- when near he will shoot a shrinker ray at you
- when you're shrunken he'll stomp you
- when you shrink him he will shrink
when you freeze him he will freeze
when you kill him he will die
- when he's hit he'll yell or shoot an RPG :-)
- when you shoot at him he will flee
Ok, but how would we go about this. First we need to replace a character
with our new character. I think our PIGCOP will do fine.
Now remove all the PigCop code. These are the lines
'action APIGWALK ...' to the line just before 'action ABOSS1WALK ...'.
I also recommend creating a one roomed sector with just one pigcop
in it so you can check the code out easy.
Whenever you see this: '*CHECK*' you can check the code out in your map.
First we're gonna define the basics of our character. We need to set up
an action group of Duke standing:
action DUKESTAND -595 1 5 1 1
Since the PIGCOP standing sprite is tile number 2030 and the Duke standing
sprite is 1405. We need to use -595 since all the sprites must be relative
to 2000 (PIGCOP).
And we need the main actor code ofcourse:
define DUKESTRENGTH 200
actor PIGCOP DUKESTRENGTH DUKESTAND faceplayer
// Drop the character until it hits a surface.
fall
enda
*CHECK*
Now we want him to go look for us so we'll have to define a sprite group
(action) of duke running.
action DUKERUN -575 4 5 1 10
and a speed at which he runs:
move DUKERUNSPEED 240
And NOW we need to define ourselfs an AI function of a duke how is looking
for us:
ai AIDUKESEEKPLAYER DUKERUN DUKERUNSPEED seekplayer
Now we need to add the following code to the actor code (right after 'fall')
// Are we still standing?
ifaction DUKESTAND
// Yep, so now start looking for player
ai AIDUKESEEKPLAYER
*CHECK*
Now duke runs, but strangly enough not to you. That's because we need to
call the ifcansee { } function? to update dukes vision. You can place the
ifcansee { } right after the fall line in the actor code and then check
again. Remove this code afterwards however since we don't need it to be
_there_. Now we're gonna create a state (put this, like actions, ai's and
move's outside the actor code)...
state dukeseekplayer
ends
... with no code in it yet. This state needs to be called whenever we are
in the seeking ai. So put this in the actor code _after_ the 'ai AIDUKE
SEEKPLAYER' line:
ifai AIDUKESEEKPLAYER
state dukeseekplayer
So now if we are in the seekplayer ai the dukeseekplayer will be called!
Now we're gonna add the following: if dukes near the player he'll start
to fire shrinker rays. Put this code into the dukeseekplayer state:
// Can we see the player
ifcansee
{
// Is player near?
ifpdistl 5000
// Can we shoot the target?
ifcanshoottarget
// Go into shooting ai
ai AIDUKESHOOTFROMCLOSE
}
So you'll see we'll have to define a new AI function AIDUKESHOOTFROMCLOSE.
ai AIDUKESHOOTFROMCLOSE DUKERUN DUKERUNSPEED faceplayer
And we'll need to add this part to the actor code after the 'state dukeseek...'
line:
ifai AIDUKESHOOTFROMCLOSE
state dukeseekplayer
So you see that we use the same state when he shooting. Obviously we need
something in the dukeseekplayer state to identify wether duke is seeking
or shooting. Add this before the 'ifcansee' line in the duke seekplayer
state:
// Are we shooting?
ifai AIDUKESHOOTFROMCLOSE
{
// Can we see him?
ifcansee
{
// Is he still close?
ifpdistl 6000
{
// Can we shoot our target?
ifcanshoottarget
// Only shoot every 10 counts
ifcount 10
{
resetcount
shoot SHRINKER
sound SHRINKER_FIRE
}
}
else
// No we are not close anymore so seek him.
ai AIDUKESEEKPLAYER
}
else
// We can't see him anymore so seek him.
ai AIDUKESEEKPLAYER
// We don't want to rest of the state to be executed so
// directly return
break
}
*CHECK*
Wooow. We got ourselfs a mad duke running after us shooting shrinker
rays. Isn't that great. But hey, when we're shrunken he keeps shooting
at us? Ok, lets fix that. We want duke to go into another ai function
when he has shrunken us.
ai AIDUKEWANTTOSTOMP DUKERUN DUKERUNSPEED seekplayer
Now add this code to the main actor code right before the 'ifai
AIDUKESEEKPLAYER' line:
ifp pshrunk
{
// Are we already wanting to stomp?
ifai AIDUKEWANTTOSTOMP
{
}
else
// No so do it.
ai AIDUKEWANTTOSTOMP
}
and add the following after the 'ifai AIDUKESHOOTFROMCLOSE state
dukeseekplayer' line:
ifai AIDUKEWANTTOSTOMP
{
// If he's already dead we've got nothing to do.
ifp pdead
{
}
else
state dukewanttostomp
}
Now we're gonna define the state:
state dukewanttostomp
// Is he still shrunken?
ifp pshrunk
{
// Can we see him?
ifcansee
{
// Is he near enough to stomp?
ifpdistl SQUISHABLEDISTANCE
{
// Kill him by subtracting 400 health (ought to be enough)
addphealth -400
// A nice sound
sound SQUISHED
// Some flying body parts
state standard_pjibs
state standard_pjibs
// Yet another nice sound
sound DUKE_KILLED4
}
}
}
// He is not shrunken anymore
else
ai AIDUKESEEKPLAYER
ends
Ok, only this time, and this time only, I'll give you all we got now:
// --------------
define DUKESTRENGTH 200
action DUKESTAND -595 1 5 1 1
action DUKERUN -575 4 5 1 10
move DUKERUNSPEED 240
ai AIDUKESEEKPLAYER DUKERUN DUKERUNSPEED seekplayer
ai AIDUKESHOOTFROMCLOSE DUKERUN DUKERUNSPEED faceplayer
ai AIDUKEWANTTOSTOMP DUKERUN DUKERUNSPEED seekplayer
state dukeseekplayer
ifai AIDUKESHOOTFROMCLOSE
{
ifcansee
{
ifpdistl 6000
{
ifcanshoottarget
ifcount 10
{
resetcount
shoot SHRINKER
sound SHRINKER_FIRE
}
}
else
ai AIDUKESEEKPLAYER
}
else
ai AIDUKESEEKPLAYER
break
}
ifcansee
{
ifpdistl 5000
ifcanshoottarget
ai AIDUKESHOOTFROMCLOSE
}
ends
state dukewanttostomp
ifp pshrunk
{
ifcansee
{
ifpdistl SQUISHABLEDISTANCE
{
addphealth -400
sound SQUISHED
state standard_pjibs
state standard_pjibs
sound DUKE_KILLED4
}
}
}
else
ai AIDUKESEEKPLAYER
ends
actor PIGCOP MAXPLAYERHEALTH DUKESTAND faceplayer
fall
ifaction DUKESTAND
ai AIDUKESEEKPLAYER
ifp pshrunk
{
ifai AIDUKEWANTTOSTOMP
{
}
else
ai AIDUKEWANTTOSTOMP
}
ifai AIDUKESEEKPLAYER
state dukeseekplayer
ifai AIDUKESHOOTFROMCLOSE
state dukeseekplayer
ifai AIDUKEWANTTOSTOMP
{
ifp pdead
{
}
else
state dukewanttostomp
}
enda
// --------------
*CHECK*
Well, he shoots and he kills. That's my kind of duke. Now, we're gonna
add the part were he shoots rockets from a distance. Yeah!
Ok, this code needs to be put in the dukeseekplayer state. In this state
we test if the distance is near (ifpdistl 5000). If it's true (he IS near)
then - if we can shoot the target - we go into the AIDUKESHOOTCLOSE ai
function. What we need to do is add an else like this:
The code was:
ifcansee
{
ifpdistl 5000
ifcanshoottarget
ai AIDUKESHOOTFROMCLOSE
}
the code gets to be:
ifcansee
{
ifpdistl 5000
{
ifcanshoottarget
ai AIDUKESHOOTFROMCLOSE
}
else
{
// Once in a while
ifrnd 1
{
// start shooting rockets
ai AIDUKESHOOTROCKET
break
}
}
}
Yep. A new ai function:
move DUKESLOWSPEED 50
action DUKECRAWL -509 3 5 1 30
ai AIDUKESHOOTROCKET DUKECRAWL DUKESLOWSPEED faceplayer
And now add this code after the 'ifai AIDUKESHOOTFROMCLOSE
state dukeseekplayer' line:
ifai AIDUKESHOOTROCKET
state dukeshootrocket
Now we'll define the state:
state dukeshootrocket
// Can we see duke?
ifcansee
{
// Is he still far away?
ifpdistg 8000
{
// Can we shoot the target?
ifcanshoottarget
{
// Only shoot once in the 20 counts
ifcount 20
{
// Start counting all over again.
resetcount
shoot RPG
sound RPG_SHOOT
}
}
}
// No he's getting closer
else
ai AIDUKESEEKPLAYER
}
// Can't see him anymore so go find him.
else
ai AIDUKESEEKPLAYER
ends
Wooow. When at a distance, if some cases he will start shooting RPG's.
What a guy! Now we're gonna teach him to dodge bullets when they're
near.
So yet another ai function:
ai AIDUKEDODGEBULLET DUKECRAWL DUKERUN fleeenemy
Put this is the main actor code before 'ifp pshrunk':
// Is a bullet nearby?
ifbulletnear
// Yep, so evade it.
ai AIDUKEDODGEBULLET
And put this also in the actor code but after 'state dukeshootrocket':
// If evasion ai is active
ifai AIDUKEDOGDEBULLET
{
// Are we done (use evasion for 5 counts, ought to be enough)
ifcount 5
{
// We're done. So go back to seekplayer
ai AIDUKESEEKPLAYER
// Reset counter
resetcount
// We're done.
break
}
}
Wow. He evades rockets and stuff. Groovy. Ok, now we have given him a
chance to survive so we're gonna write to stuff that gets executed when
he is hurt and/or killed. First we need to define an ai and an action
group of duke getting hurt!
action DUKEPAIN -489 1 1 1 10
// DUKESTOPPED = 0
move DUKESTOPPED
ai AIDUKEBEINGHURT DUKEPAIN DUKESTOPPED faceplayer
Now add this code to the main actor code right before the 'ifbulletnear'
code:
ifai AIDUKEBEINGHURT
{
state dukebeinghurt
break
}
ifhitweapon
{
ai AIDUKEBEINGHURT
break
}
Now here's the dukebeinghurt state:
state dukebeinghurt
ifdead
{
// Play nice sound
sound SQUISHED
// Play a death sound
ifrnd 128
sound DUKE_KILLED4
else
sound DUKE_DEAD
// Some body parts
state standard_pjibs
state standard_pjibs
killit
}
else
{
// No he wasn't dead yet so play a randomly chosen
// hurt sound.
ifrnd 64
sound DUKE_LONGTERM_PAIN2
else
ifrnd 64
sound DUKE_LONGTERM_PAIN3
else
ifrnd 64
sound DUKE_LONGTERM_PAIN4
else
ifrnd 64
sound DUKE_LONGTERM_PAIN5
}
// After two frames go back to seeking mode again.
ifactioncount 2
ai AIDUKESEEKPLAYER
ends
Ok, if duke gets shot with a gun he also explodes. So what? The dying
animation doesn't work because this is _actually_ a pigcop. And pigcops
die differently. Sorry. Now you can kill him easily by just shooting
at him. I want him to - sometimes - shoot back with a RPG if he
is being hit.
This needs to be done in the hurt part where all the ifrnd 64's are.
The code now is:
else
{
// No he wasn't dead yet so play a randomly chosen
// hurt sound.
ifrnd 64
sound DUKE_LONGTERM_PAIN2
else
ifrnd 64
sound DUKE_LONGTERM_PAIN3
else
ifrnd 64
sound DUKE_LONGTERM_PAIN4
else
ifrnd 64
sound DUKE_LONGTERM_PAIN5
}
and the code gets to be:
{
// No he wasn't dead yet so play a randomly chosen
// hurt sound.
ifrnd 64
sound DUKE_LONGTERM_PAIN2
else
ifrnd 64
sound DUKE_LONGTERM_PAIN3
else
ifrnd 64
sound DUKE_LONGTERM_PAIN4
else
ifrnd 64
sound DUKE_LONGTERM_PAIN5
// 25% chance he shoots when being hurt
ifrnd 64
{
// Only shoot every 3 counts.
ifcount 3
{
resetcount
shoot RPG
sound RPG_SHOOT
}
}
}
Ok, now we only need two things until we're done. The possibility to shrink
him and the possibility to freeze him. You're on your own from now on...
... so figure this out yourself. Check the code of other actors to see how
it's done. If you still have any questions you can always mail me at
antiwin@worldonline.nl
--------------------------------------------------------------------------
4.1 DEFS.CON (overview)
--------------------------------------------------------------------------
DEFS.CON is the CON file in which all defines are done. This way
you can name a tile or sound by name instead of number. It is
included by GAME.CON
--------------------------------------------------------------------------
4.2 USER.CON (overview)
--------------------------------------------------------------------------
In USER.CON all sorts of defines are done. All levels and sounds are
defined here. Also other game effects like respawning time etc. are
declared here. It is included by GAME.CON
--------------------------------------------------------------------------
4.3 GAME.CON (overview)
--------------------------------------------------------------------------
This is the main CON file. It gets compiled first. It includes DEFS.CON
and USER.CON first. In this CON file all the actor code is located. You
could put actor code in the USER.CON but it looks better if you keep it
all in GAME.CON.
--------------------------------------------------------------------------
5.1 What *I* would like to know
--------------------------------------------------------------------------
Here's a list of things I would like to know. So if you do, _please_
mail me.
- Is there someone who would like to help me maintain this FAQ? Knowledge
of CON hacking is required ofcourse.
- Why is 'ifcansee' needed to let seekplayer and other ai function work
properly?
- Explenation of some of the ai functions.
- What does ifnotmoving do in fact? Is this neccesary due to a bug
in the ai functions?
--------------------------------------------------------------------------
5.2 Contributers/Thank you's
--------------------------------------------------------------------------
I want to thank:
- Reptile ( reptile@worldaccess.nl <http://www.worldaccess.nl/~reptile> )
- Linkers ( linkers@dds.nl, <http://huizen.dds.nl/~linkers> )
for introducing me to Duke Nukem 3D as it is the funest game I've ever
seen (yeah, that also means more fun than Quake!).
--------------------------------------------------------------------------
5.3 Update and info
--------------------------------------------------------------------------
An update of this FAQ will come within a week of release. I hope all of
you guys will send me lots of mail within that week, so I can make the
FAQ better. Also, I want to say, that even if it sounds that I know every-
thing, I know I don't. Please don't blame me for saying things that are
incorrect. The right thing to do is to mail me and correct me. It will be
corrected in the FAQ right away. Also there are some things, I'd like to
know more about. So if you have any info and CON hacking, don't hesitate
to mail me at antiwin@worldonline.nl
--------------------------------------------------------------------------
5.4 Where to get this FAQ
--------------------------------------------------------------------------
I hope you can soon download this FAQ from many Duke 3D sites. An update
of this FAQ is posted _at least_ once a week in the following newsgroups:
alt.games alt.games.apogee alt.games.duke3d