
                             Eternity Engine
			SMMU Features Editing Guide

                            Updated 09-26-00

[1-1] Overview
--------------
SMMU is based upon the MBF sources, and therefore contains support
for all standard BOOM and MBF linedef and sector types, 'dehacked' lumps,
etc. Basically anything they can do, SMMU can do.

SMMU also contains further support for a number of extra linedef
types which will only work with it.

[1-2] The level header
----------------------
By 'the level header', I mean the wad resource which starts a level.
For example, the level headers for all the original doom levels were
all in the format "mapxy" or "exmy".

In SMMU, the level header can take any name, for example, the SMMU
'start map' has the name "start". Levels with nonstandard names can
be accessed from the console using the "map" command: eg "map start".

Additionally, SMMU automatically detects new levels loaded from wads
and will start on the appropriate level when the 'new game' option
is chosen from the main menu

[1-3] The level info lump
-------------------------
In original doom, the level header resource was empty: it was always
0 bytes long. This is not to say that it _had_ to be 0 bytes long:
any data in the level header was simply ignored.

In SMMU, the level header is used to hold information about the level.
The format is a simple ascii text file, similar in style to the '.ini'
files which are found in a typical windows directory.

There are a number of sections which hold different types of information,
each begins with a different section header:
        - [level info] : holds information about the level: the name,
                par time, etc. See section [2].
        - [console commands] : anything put in this section will be
                considered a console command and executed when the
                level is loaded.
        - [scripts] : FraggleScript Scripts to be run in the level.
                See [3]
        - [finale text] : Holds text to be displayed after completing the
                level. As used in original doom to show how the story
                develops.

Comments may begin with a '#', ';' or '//'

[2-1] The level info section
----------------------------
The level info section described in section [1-3] contains certain 
information about the level. This is in the format:
        variable = value

Legal variables are:

Variable name		Description
--------------------------------------------------
levelpic		Name of a graphic resource containing the level name
			to be displayed in intermission screens

levelname		The name of the level

partime			The par time (time it should take to finish the
			level) in seconds

music			Name of the music resource to be played in the level
			(eg. 'fragme' will play 'd_fragme')

skyname			Name of a resource containing the sky for the
			'f_sky1' flat

creator			Your name (user can find the value of this by
			typing 'creator' at the console')

interpic		graphic to be displayed in the intermission screen

nextlevel		The name of the resource starting the next level
			(eg. 'nextlevel=map01' will take the player to map01
			after finishing this level)

gravity			Gravity in the level as a percentage of normal

inter-backdrop		For intermission 'story' text screens, this allows
			you to specify a 320x200 resource or flat to be
			displayed in the background

The following are new to the Eternity Engine:

altskyname		An alternate sky texture to be drawn during
			lightning flashes. This is used only if
			lightning is set to on. If lightning is on and
			this is unspecified, no sky animation will
			occur (which looks very odd indeed)

lightning		Set to either "true" or "false" -- true will
			cause globalized random light flashes in all
			sky sectors along with a crack of thunder. If
			you need to have flashing in non-sky sectors,
			use the BOOM ceiling light transfer linedef.
			This is not supported through sector types as
			it is in Hexen as there is no need.

colormap		Set to any valid colormap lump. This colormap
			will be swapped for the normal COLORMAP for
			this level and used globally. Note that the
			underwater portions of deepwater sectors can
			still be given their own colormaps.

sky2name		Set to any valid single-patch texture name to
			activate the use of double skies. This texture
			will be drawn normally, and the normal sky
			will be drawn over it leaving out black 
			(RGB 0,0,0) pixels, letting it show through.

skydelta		An integer value specifying how many pixels
			per game tic the normal sky texture should
			scroll

sky2delta		An integer value specifying how many pixels
			per game tic the sky 2 texture should scroll.

 - Per-Level Sound Replacement -
sound-swtchn		Name of sound to use for switch pressing
sound-swtchx		Name of sound to use for switch release
sound-stnmov		Name of sound to use for a moving plat
sound-pstop		Name of sound to use for a stopping plat
sound-bdcls		Name of sound to use for closing blazing door
sound-bdopn		Name of sound to use for opening blazing door
sound-dorcls		Name of sound to use for closing normal door
sound-doropn		Name of sound to use for opening normal door
sound-pstart		Name of sound to use for a starting plat

_example_ A typical level info section

[level info]
levelname = chadders' lair
partime = 200
music = d_cheese
creator = Edwin Chadwick 'chadders'
nextlevel = chad2

This sets a number of settings, but uses the default interpic and sky.
The automap shows the level name 'chadders lair', and the par time is
200 seconds (3:20). The music 'd_cheese' is used, and when the player
exits the level, play advances to the next map, 'chad2'.

[3] Scripting
=============
SMMU allows scripting using the 'FraggleScript' scripting language.
Unlike scripting in other ports, FraggleScript scripts do not need
to be compiled. FraggleScript has a format almost identical to that
of C. You merely place the script code into the level info file under
a section titled [scripts].

The documentation provided here is currently very limited and you
probably only find it useful if you already have knowledge of C.

Additional documentation will be available later.

[3-1] FraggleScript linedef types
---------------------------------

Walk triggers
272             -- WR start script (script number specified by sector tag)
273             -- WR as 270 but one-direction only
274             -- W1 as 270
275             -- W1 as 271

Switch triggers
276             -- SR start script (script number specified by sector tag)
277             -- S1 as 274

Shoot triggers
278             -- GR start script
279             -- G1 as 276

[3-2] FraggleScript Functions
-----------------------------

Note: As of Eternity v3.29 public beta 1 this list is out of date.
Numerous functions are available not listed here, and some of these
functions have new or different parameters. Documentation will be
available soon.

//      Standard functions:

break()                 -- jump out of current loop
continue()              -- jump to start of next loop
return()                -- exit script
goto(label)             -- jump to a label in the script
include(lump)           -- read the contents of a lump

print(mess, mess, ...)  -- print a message to the console
rnd()                   -- return a random number from 0 to 255
input()                 -- get input from the user (not implemented in doom)
beep()                  -- make a beeping sound
clock()                 -- get the current time (100 clocks = 1 second)
startscript(scriptnum)  -- start off a new instance of a script
scriptrunning(scriptnum) -- returns 1 if script scriptnum is currently
                            running

// Wait functions

wait(n)                 -- delay for n clocks (1 clock = 1/100 second)
tagwait(n)              -- wait for all sectors w/tag n to stop moving
scriptwait(n)           -- wait for all instances of script n to finish

//      player:         (some functions default to triggering player)
//              eg. 

consoleplayer    [variable]    -- player controlled from this computer
displayplayer    [variable]    -- player being viewed
playerobj([player])            -- the mobj controlled by a player
playername([player])           -- players name
playermsg(player, mess, ...)   -- message to a particular player
playertip(player, mess, ...)   -- centremsg to certain player
playeringame(player)           -- player in game?
                                                                        
//      sector:

floorheight(sectag)            -- get floor height of sector
floorheight(sectag, newval)    -- set floor height
movefloor(sectag, newheight, [speed])
                               -- gradual move floor height

floortext(sectag)              -- floor texture in sector
  * Alias: floortexture
floortext(sectag, newtexture)  -- set floor texture
  * Alias: floortexture

ceilheight                     -- as floor height
  * Alias: ceilingheight
moveceil                       -- as movefloor 
  * Alias: moveceiling
ceiltext                       -- as for floortext
  * Alias: ceilingtexture

lightlevel(sectag) -- get lightlevel
lightlevel(sectag, newval)     -- set lightlevel
fadelight(sectag, newval, [speed]) -- fade lightlevel to new value

colormap(sectag)               -- get colormap used in sector
colormap(sectag, newmap)       -- set colormap in sector

*special                       -- get/set special sector type

//      mobj:   (defaults to trigger object on some funcs)

trigger   [variable]       -- object which triggered script
spawn(type,x,y,[angle])    -- spawn object
removeobj(obj)             -- remove object
kill([obj])                -- kill object
teleport([obj], tag)       -- teleport object
silentteleport([obj], tag) -- silent teleport object
player([obj])              -- playernum of mobj's controlling player
damageobj([obj])           -- damage an object
objsector([obj])           -- sector tag of sector object is in
objflag(flagnum)          -- get flagnum of trigger object
objflag(obj, flagnum)     -- get flagnum of object
objflag(obj, flagnum, newval) -- set flag of obj
objhealth([obj])           -- object health
objangle([obj])            -- angle a thing is facing
objx([obj])                -- x co-ordinate of thing
objy([obj])                -- y co-ordinate of thing
objz([obj])                -- z co-ordinate of thing
pushobj(obj, angle, force) -- apply momentum to a thing

//      messaging:

tip(mess, mess, ...)       -- centre-of-screen message
message(mess,mess,..)      -- normal message

//      cameras:

setcamera(obj,[angle])     -- switch to an alternative camera view
clearcamera()              -- switch off camera

//      levels:

exitlevel()                -- same as console command
changehublevel(levelname, sectag)
                           -- go to another level in the hub. See [3-4]
*changelevel               -- like 'map' command

//      sound: (lump is string w/o 'ds' eg. "frad" = DSFRAD lump)

startsound(thing, lump)    -- start sound at a thing
startsectorsound(sectag, lump) -- start sound in sector

//      trig functions:

pointtoangle(x1,y1,x2,y2)  -- angle of one position from another
pointtodist(x1,y1,x2,y2)   -- distance between two points

//      other:

zoom     [variable]        -- zoom in

=== New to Eternity ===

The following functions are new to the Eternity Engine:

setfriction(tagnum, value)        -- set sector friction
  * Note that value should be equal to the length of the linedef
    you would normally use to achieve the same friction value:
    value < 100 => mud
    value > 100 => ice

objflag2(flagnum)          	-- get flags2 num of trigger object
objflag2(obj, flagnum)     	-- get flags2 num of object
objflag2(obj, flagnum, newval) 	-- set flags2 of obj

spawnshot(type, source, target, facetarget)
 - type = type of mobj to fire, required
 - source = mobj that should fire shot. If set to NULL, the object
	    that triggered this script will fire the object
 - target = mobj that should be fired at. If set to NULL, the source
	    mobj will fire the shot at its current target.
 - facetarget = a boolean integer value -- set to FACETARGET if the
		source should face its target before firing, else set
		to NOFACETARGET and the mobj will not do so.
 
 This function is rather powerful, and is chiefly meant for use inside
 thing scripts (not yet supported in this version).

checklife(mobj) -- a simple way to check whether something is alive
		   returns 1 if alive, 0 if dead or no longer present
		   on level

setlineblocking(linetag, blocking)
 Sets the lines in question to either block all solid objects, or
 to let them pass. This function will have no effect on one-sided 
 linedefs.
 
 - linetag = the tag number of lines to change -- all lines with this
	     tag will be altered
 - blocking = boolean value, set to NOBLOCK to clear blocking flag,
	      set to BLOCK to set the line as blocking

setlinetexture(linetag, side, texture, position)
 This function can be used to change any texture on all of the tagged
 linedefs
 
 - linetag = tag number of lines to change
 - side    = side of lines to change, use SIDE_FRONT for the 1st side 
	     or SIDE_BACK for the 2nd side (if the 2nd side does not
	     exist, this function will stop execution)
 - texture = string, the texture to set the side of the line in 
	     question to, use "-" for no texture.
 - position = which texture on the side to change, upper, middle, or
	      lower, use constants TEXTURE_TOP, TEXTURE_MIDDLE, and
	      TEXTURE_BOTTOM for ease of use

// suggestions for new functions:
// haleyjd@hotmail.com

[3-3] Some useful info
----------------------
FraggleScript is similar in syntax to C, but with some marked differences:

   - for() loops in c done like this:
        for(i=0; i<40; i++)
     are done like this:
        for(i=0, i<40, i++)
   - Some C keywords are implemented in FraggleScript as functions, eg

        return;          becomes           return();
        break;           becomes           break();
        goto label;      becomes           goto(label);

   - WAD lumps can be included, similar to the #include preprocessor command
     using the "include" function, eg:

        include("things.h");

     includes the wad lump named "things.h"

   - There are only 4 types of variable:

        int -- an integer number
        string -- a string value. Unlike in C, you can implicitly compare
                  strings with other strings without the need for the
                  "strcmp" function and set them without the need for
                  "strcpy"
        mobj -- An object on the map. You can set these by thing number or
                by from a returned value from a function, eg:

                mobj mo;
                mo = 3;           // set to thing number 3 on the map
                mo = spawn(IMP, 50, 50);  // spawn an imp and keep it in mo

                note: mobj is NOT the same as int!
        const -- use to hold constants, eg:
                const enemy_name="imp";
                const num_walls=5;

Individual scripts are defined in FraggleScript using the "script" keyword.
You must number each individual script, eg:

        script 1
        {
           ... commands in script ...
        }
        script 2
        {
           ... commands in script ... 
        }
        etc.

Variables declared outside any script are 'global' and can be accessed by
any script. You can also make _limited_ function calls in the global area
which will be run when the level starts. However I would advise you to
restrain yourself to the 'include' and 'startscript' functions only.
If you want to do anything more complex, place it in a seperate script
and run it using the 'startscript' function.

[3-4] Hubs
----------

NOTE: Hubs are temporarily disabled in Eternity v3.29 public beta 1.

[4] Thing options
=================

[4-1] Directions
----------------
In original doom, you could place things in levels, but their directions
were rounded down to the nearest 45 degrees. However, in SMMU you can
specify any angle right down to the nearest degree.

This does not require any kind of change in wad format. The original
system allowed you to specify angles that were not 45 degree 'aligned'.
However these were simply rounded down. SMMU has greater accuracy so you
can specify any angle.

[4-2] Intermission cameras
--------------------------
SMMU allows you to change the background in intermission screens but I
have also devised a more advanced system that allows you to see a view of
the after you have left it. If you place a thing of type 5003 in the level,
when you get to the intermission screen you will see a view from that
point rather than the standard 'still' background.

Placing more than one camera in a level works, also. If you make more
than one camera, one of them is simply chosen at random.

[5] Other
---------

[5-1] Swirly flats
------------------
The console variable 'r_swirl', when set to 1, will stop all animated flats
from animating and instead give them a 'swirling' effect similar to the
quake water effect. However, this affects all flats and for some animated
flats it doesn't look right.

You can specify when to use the 'swirl' effect on individual animated flats
using the boom 'animated' resource. You can use the SWANTBLS.EXE program to
create your own set of animated flats. If the delay between flat frames is
set greater than 65535, that flat will be given the swirl effect.

[5-2] Sector Flags
------------------
Boom once promised two extra sector flags, if you look in boomref.txt:

  Bits 10 and 11 are not implemented yet, but are reserved for use in
  sound control. Bit 10 will suppress all sounds within the sector,
  while bit 11 will disable any sounds due to floor or ceiling motion
  by the sector.

Anyway, looking at some levels, I found particularly annoying the way that
3-D bridges 'clunked' when you walked over them. So I decided to implement
the sector flags which the boom team planned to implement. You may now use
bits 10 and 11 in your wads as you please.

