
              ,s$$$s, ,$$$s    $$$$ $$$$     $$$,,%$$s   s$$%,
             sSS' `S'  $$$`    $%$$ $$$$     $$$ `$$$$   $$$$
             $S$,      $$$$   ,$$$' `$$$,   ,$$$  $$$$   $$S$
              T$$ls,   S%S$$_,$$S$   $S$$,_$$S$S  %$$S   %$$$
             ,  `~SS|  $$$`$$$'$$S   $$S`$$$'$$$  $$S$, ,$S$$
             $$, .$$)  $$$  ^  $$$   $$$  ^  $$%  `%$$$%$$$$'
             `$$$$$'  ,$$$$    $$$. .MWS    $$$$,  `%%$$$$%'

                          "Smack My Marine Up"

                            Editing for SMMU
                            ----------------
                            Updated 17-12-99

[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

_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.
However, you can visit one of the following sites:
                http://smmu.frad.org/
                http://smmuediting.cjb.net/
which give useful information on programming in FraggleScript.

[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
-----------------------------

//    Doom FraggleScript functions.
//      subject to change. functions marked with '*' not yet implemeted

//      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
floortext(sectag, newtexture)  -- set floor texture

ceilheight                     -- as floor height
moveceil                       -- as movefloor 
ceiltext                       -- as for floortext

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
*friction                      -- get/set sector friction

//      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
objflags(flagnum)          -- get flagnum of trigger object
objflags(obj, flagnum)     -- get flagnum of object
objflags(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


// suggestions for new functions: email me
// <sfraggle@sfrag.free-online.co.uk>

[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
----------
FraggleScript now includes support for 'hubs': ie. when you have several
levels that you can travel between. While you are on one level the other
levels you have been to are stored as savegames until they are needed.

The 'changehublevel' function allows for 'seamless' travel between levels
in a hub. To use this, you must have a sector in both of the levels
you want to travel between which acts as a 'bridge'. These two sectors
must be of identical size and shape. You must give them both the same
sector tag. You can then use the changehublevel function to travel
between the two levels:

   changehublevel(levelname, sectag);

where levelname is the name of the level to travel to and sectag is the
tag number of the 'bridge' sectors.

It is possible in FraggleScript to 'share' variables between levels in
a hub using the 'hub' keyword. To create a shared variable, simply
place the 'hub' keyword in front of the variable you want to create:

   hub int shared_var;   // can be accessed by all levels in the hub
   hub string shared_str;  // a shared string

   int local_var;        // this can only be accessed by this level

It is advised that you define the shared variables in every level in
the hub which needs them or put all the shared variables (including
'hub' again) in a seperate wad lump and have all of the levels
include it with the 'include' function.

See hubtest.wad for an example hub.

[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.

