About
Downloads
Register/Buy
Help and FAQ

Manual
Screenshots
Reviews/Media
User Forums
User Contributed
Developer Support
Thanks to...


About
Downloads
Register/Buy
Screenshots
User Forums
FAQ

Free Stuff
CaSTaway
Kronos
Zot!
Columbo
B.o.R.
GuineaPig
GP32
Telnet BBS
ZGrab
ZQuake
DevFAQ
All

Message Board
Support and Contact
Home


ZOT Homepage

Join the mailing list, see other resources for working with Zot, find other peoples levels or just hang out...

Zot!

ZOT Configuration Reference Guide

Introduction
Lifecycle
Game Styles
Artwork
Starting Guide
Config file overview
Config file syntax and declaration order
Config file reference guide
Engine variables reference guide
AI Types
Tips and Samples
Sample Zot config files

ZOT Introduction

The ZOT-Engine is a reasonably generic tile based game engine designed with the goal of enablind creation of simple "Action RPGs" and "Action Puzzle Games", in the grain of Gauntlet, Sokobon, Time Bandits, and maybe even simple forms of Zelda or early Final Fantasy's. Its a moving target with the engine being designed for making a number of games that I've been wanting to for a long time...

NOTE that as ZOT grows, its config file will change, but I will try to keep the documentation halfway right :)

-- Jeff

ZOT 0.19 Engine Lifecycle

  1. Run Zot!
  2. Finds a Zot directory; starts zotlog.txt within it, if a desktop platform
  3. Parse Zot/config.txt -- this first config.txt is just a minimal one, to load up and define a font, and specify artwork to use for game picker skin
  4. Look for Zot subdirectories; each entry that doesn't have a dot in it is assumed to be a game directory, and is listed in the game Picker
  5. Show picker and artwork; allow player to pick a game
  6. Change directory into the games directory
  7. Load up config.txt for this game (which may in turn pull in other config files, etc)
  8. Run the engine until player or system requests exeunt
  9. Finish.

Supported Game Styles

This is not an exhaustive list.. certainly although I don't say we can do "Bomberman" style games, you very much can since Bomberman is just a limited tilemap with sprites on top... very much within the domain of things Zot! can manage. However, that said, Zot! was designed with a few game types in mind, so is probably better at them than some other styles of game. (ie: Zot! will not likely be good for making Street Fighter style games in.)

  • Top-down action puzzlers; think Gauntlet, original Zelda or Final Fantasy's, Time Bandits .. action or simple-RPG games.
  • Platform run-and-jumpers; think Mario, Great Guina Sisters, etc.
  • Rotate-and-thruster; think Asteroids/Blasteroids, etc.

Really, Zot is just an engine that knows how to draw tiled images in a background, with sprites and transparencies on top of it. So any game you can think of like that, with lots of smaller sprites instead of a few giant sprites, should be within the realm of the doable.

Zot! is a general purpose engine, which means its always a work in progress. You will likely need new Triggers or Actions or engine features (AI modules, weapon attack types, etc) that the engine does not support, or doesn't quite do what you need. Feel free to just ask .. maybe its already covered and you overlooked it, or maybe a feature can be done through other means, or maybe I need to build it. At earlier Zot stages, most things will need to be built in...

How to configure for each style

Note that it is trivial to change between the different playstyles, since in essence we're just altering how the player does his thing.

  • Top down free movement; this is the default behaviour. If player has no "option velocity" active in his sprite config, this is what will be going on.
  • Platformer; just add "option velocity" to player's sprite definition, and it will now be effected by gravity and friction. You will want to set up the world variables to have gravity and friction .. so the player drops to the platform, and so he slides a little (but not too much!) for your game. You might as how to define gravity etc... simply use a trigger that fires off when the level loads, and has variable-set actions to set up all the goods.
  • Asteroids; add both "option velocity" and "option angles". You will also *need* a "anim_spritedef" section for "angles", so the engine will have all the pre-rotated artwork; if you specify "option angles" and then no angles section, the results are undefined. (maybe it'll crash, who knows?). Gravity and such apply in this mode of course.

As you can see, you can just leave those options in the config and comment them out (put "#" at the line beginning) to turn them on or off and experiment.

Starting Guide

I believe Zotscript is relatively easy to get into (though it can take some work to get to the advanced parts for sure!), though it can be intimidating to look at for the first time due to the sheer variety of options and statements available. To try and make it a little easier to climb into for the first time, here are some basic pointers..

  • You can probably just copy the "nil" gamelet from the dev kit and have a basic empty gamelet going in seconds!
  • For making new artwork, or converting artowkr, you'll need some graphics program that speaks PCX and TGA, since those are the only two that Zot currently handles. (Because they're simple formats, so keeps the engine small; I built a module to load PNG artwork and the application quadrupled in size.. just for loading PNGs! When its a handheld application, size is to be avoided, so there you go.) I suggest using The Gimp for Windows or Linux.
  • When you start hacking away at your first config.txt you'll want to keep it simple -- don't bite off too much all at once or you'll just hang yourself :) Start adding to it like this perhaps..
    1. First add in a couple of images in your image-list block. You'll want at least an image for the player artwork, and an image for the first tile, and I think you need the first image for the font as well if you expect any text to show up. To keep it easy, keep the player artwork separate from the tile artwork, though you do not have to. ie: A tile art coudl be any image in PCX or TGA format that is at least 16x16 big, though 16x16 exactly is better :)
    2. Define at least one basic "tile" definition; it needn't be anything fancy.. just:
      tile	.
      name	floor
      image	myimage
      tile	end
      	
    3. Define your basic tilemap for the first level; a tilemap must be at least 15x15 or so to keep the devices happy, but you could create something all empty using your first tile, like this. Remember you need to specify a width and height first, and then provide one 'row' for each of the height. The '@' is defined below!
      tilemap	level1
      width	15
      height	15
      row	...............
      row	...............
      row	...............
      row	...............
      row	...............
      row	...............
      row	...............
      row	...............
      row	...............
      row	...............
      row	...............
      row	.......@.......
      row	...............
      row	...............
      row	...............
      tilemap	end
      	
    4. Define the player sprite; you can copy it from another sample config file. It has to have at least a "still" animation in it, though you can add all the directions in if you like.
    5. Make sure to have a tiledef with "option starthere" in it, so that the engine knows where to start the player. So add a second tile definition like this:
      tile	.
      name	floor
      image	myimage
      option	starthere
      tile	end
      	
  • You can break things up into multiple config files, but you do not have to; its just as easy (especially when starting out!) to just have the one config. Since you must always have a config.txt for your game, you might as well start with... config.txt :)
  • Some sprite definitions are required for the engine to run at all so be careful to include them, somewhere, in your config :) For instance, you must have a sprite whose id is player, or the engine won't know what to display. You can copy it from any of the sample configs to get going, though remember to copy any required artwork! Furthermore, if you want to fire, you must have a sprite id of arrow in there somewhere, unless you define a change-weapon action that fires off right when the game begins, to specify another sprite that is the weapon! If you plan on using explosions, remember that they have sprite names they need for the components of the fire (See the AI for the explosions for details.)

Artwork

Artwork is pretty simple, but theres a few basic rules. I'm not honouring fancy or recent file formats.. they tend to be very complex to build and have a million variations and options.. PNG support tripled the size of the application! As of Zot 013 only supports Targa (TGA) and PCX, each with different features..

PCX
  • Always 'fast' (as fast as sprites can be)
  • Must be 8bpp (not 16bpp or 24bpp) -- each image has its own palette space though, so each image can have its own 8bpp palette
  • Since PCX has no alpha channel, use a pixel value of RGB(123,123,123) to make it 100% transparent (see through)
  • Use a pixel colour of RGB(222,111,222) to darken the existing screen pixel (like an alpha-darken effect)
TGA
  • Targa optionally carries an alpha channel; without alpha, its just as fast as PCX above; with an alpha channel, it is much slower so should be used sparingly.. can easily cost a few FPS for each sprite!
  • 32bpp is ideal (RGB 8bpp each, plus 8bit alpha)
  • Alpha channel is blending/transparency -- using dark with alpha to darken background; use light with alpha to lighten. Use whatever colours you like and optional alpha for cool blending and shading and tinting effects...

ZOT 0.10 Config File Overview

config.txt is the default loaded config; to keep things 'simpler' for the level designer, I've broken out another config file and called it 'preconfig.txt'; config.txt includes a directive first-thing that causes ZOT to load preconfig.txt, and thus essentially preconfig.txt gets loaded first, and then config.txt's main body gets loaded. With this in mind, I make careful choices of where to put things..

  • preconfig.txt -- contain "models" and "archetypes" -- these are abstract descriptions of things that will be reused on each game floor. For instance, you would define a generic monster here, so that you could use it in multiple floors without having to redefine it. This keeps the level designers from having to look at monster definitions all the time, keeps the config for each floor down in file size, and provides a nice split.
  • config.txt -- contains "physical real world objects" -- so while you might define a monster in preconfig.txt, you would tell the engine to create a copy of that monster at coordinate 10,20 (say) in config.txt; you define the tilemaps and tile definitions in the config.txt, since they are real world things unique to a given floor.

So the rule becomes.. if its a definition of something you intend to re-use .. a toolbox object.. you put it in a preconfig.txt type file; if its somethign that belongs on a single level, like a tile or map definition, it goes in a level config such as config.txt.

ZOT Config Syntax and Declaration Order

The syntax of the configuration file is fairly flexible, but the engine interprets it very carefully, so you must be careful to conform.

The config file is a line based key/value pair file, with comments. This means..

  • You DO NOT end lines with anything (like a semicolon, etc)
  • Every option is KEY and VALUE
  • Spacing before and after each key/value is IGNORED
  • Comments can begin anywhere, but finish the line
  • Order of key/value pairs is usually not relevent
  • Order of groups IS relevent
  • Spacing is spaces, tabs and other junk
  • Non-spacing counts as key/value!
  • Case tends NOT to matter
  • Multiword Values may be quoted

Example Good Lines:

somekey		somevalue	# tab between key and value
  somekey	somevalue	# indented child item just for us puny humans
  anotherkey anothervalkue	# spacing between key/value is ignored..
  fookey		foovalue  # spacing irrelevent
# comment can begin line        # comments can begin anywhere
somekey		somevalue	# comments can begin at end of line
say		"hello friend"  # multiword 'value'
	

Most OBJECTs in the config are not a single key/value pairing, though several engine options are; for instance, one might specify the starting level with a single key/value pair, but defining a monster is a block of some 5-20 key/value pairs (each one with its own line in the config), all grouped within a sprite-start and sprite-end pair. See the reference guide for details...

Order of Declarations

Note that for most references, something must 'exist' (be declared and loaded) before you refer to it; ie: You must use an image-list to load up and name images, before referring to the image in tiles, sprites, etc. But some objects can refer to things that do not yet exist, for convenience of writing the configuration file..

  • A sprite can refer to a generator that is not yet declared
  • A tile can refer to a conveyer that does not yet exist
  • A tile can refer to a door that does not yet exist
  • A tile can refer to a wayout that does not yet exist
  • A tile can refer to a button that does not yet exist
  • An action-group can be defined later; an action can refer to "action-group 10" before action group 10 is defined. This can be a handy way to work around that some actoins depend on things being created, that you've not yet defined in the config. Then after they're defined, have an action group that refers to them.
  • Everything else requires the object to exist before being referred to

ZOT Config File Reference Guide

ZOT is almost entirely driven by configuration files, so this is the real meat of the engine.

  1. Directives
  2. Variables
  3. Image-list
  4. Fonts
  5. Sprites
  6. Tiles
  7. Complex or Special Tiles
  8. Text Menus
  9. Triggers
  10. Events
  11. Actions

Directives

A directive is a key/value pair that is not within a larger block. ie: Its not part of a sprite definition.. it just says what level to start at, and thats it.

  • "config-read" instructs ZOT to go read another config, and then when finished, to come back and finish this one. Avoid circular references on your own :) ex: config-read preconfig.txt
  • "post-message" instructs ZOT to post a message to the screen right away; when the game world draws, the message will be right there. A good way to put some quick credits or level titles onto the screen. NOTE -- be sure to quote multiwords. ex: post-message "Demo Level". See the post-message action for details of formatting.
  • "startmap" -- specifies the tilemap the player will begin in in this config-set. ex: startmap mainfloor
  • "score VARNAME" -- identify variable as being a player Score; the Zot engine will do something with it, such as display it in the screen corner.
  • "health VARNAME" -- identify variable as being a player Health variable; the engine doesn't care about it, but it will display it somehow or another.

Variables

Variables are in essence holders of numbers. You can create, set or read them. (Creating a variable occurs just by referring to it in a read or write.) There are two kinds of variables -- special engine variables, and user-land variables.

  • "engine variables" are variables in the engine itself; you can read or set them (some are read only, some are write only, and some are read-and-write), and usually something will occur when you do so. ie: The player location is an engine variable.. you can use it in a trigger to make something occur if near the player, say, or write to them to move the player.
  • "user variables" are variables you make for your own purposes... you can name them whatever you want pretty much. Just read or write to a variable to create it.

There are a few rules to note..

  • Engine variables begin with "_" (underscore). You cannot make variables that begin with underscore, or Bad Things will happen.
  • User variables must begin with a letter. If they begin with anything else, Bad Things will happen.

image-list

An image-list block has the engine load up a series of artwork files and associate them to a name that can be referred to in all other sections of the configuration; ie: instead of referring to "house_white_32px.pcx", you would use the image-list to load it up as "house" and use it thereafter. This is the only way to get images into the engine.

image-list start
bluebrick   bluebrick.pcx       # basic 16x16 blue floor tile
brownbrick  brwnbrick.pcx
floorgreen  floorgr.pcx
image-list end
	

The image-list can also accept a few basic transformations; put them on the line after the filename for them to kick in. Note that the alpha layer (if present) is also transformed :) (Zot engine v013 or later only!)

image-list start
floorgreen  floorgr.pcx  rotate90
image-list end
	

Possible transformations are:

  • rotate90 -- rotate the image 90deg (counterclockwise)
  • rotate180 -- rotate the image 180deg
  • rotate270 -- rotate the image 90deg (clockwise)
  • flipx -- flip the image left over right (across the Y axis)
  • flipy -- flip the image top over bottom (across the X axis)
  • rotate### -- you can now do arbitrary rotations; for example, "rotate230" will rotate 230 degrees for you; note that using the arbitrary rotator hits the load time a touch, especially for larger images.

Fonts

The font-block defines a font for later use by the engine.

offset_x and offset_y define the beginning of the image data in the artwork; char_offset_x is the spacing between characters in the artwork, while kern_offset_x specifies the spacing to use between characters when they are rendered (kern_offset_y specifies the spacing to be used between lines). image defines the artwork to use (previously loaded by an image-list). Lastly, the charmap lists the characters in the font, in order.. it is used by the engine to find the characters to display them.

font            fpsfont
offset_x        1
offset_y        1
char_offset_x   10
kern_offset_x   9
kern_offset_y   9
image           skeefont
charmap         "! #$%&'[]*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRST" # etc
font            end
	

Sprites

The sprite-block defines a sprite 'model'; nothing is added into the game world, but you can turn this sprite model into one or more sprites easily in another section of the configuration.

The 'sprite' word's value is the name of the sprite, used forever after to refer to this model. The name is only used for displaying the name of the sprite if we ever need to do that. order is used for render order -- its a value from 1 through 3 inclusive, and the "1"'s are drawn first with the "3"'s drawn last. If you want to draw rooftops or treetops or transparent catwalks above the level, you would use large order-3 sprites to do it. speed is the walking speed of the sprite.

AI is the 'intelligence' function used to make the sprite do things. For instance, you can set up "mob_wander" which simply guides the sprite to wander randomly around the area. "mob_robotron" on the other hand makes the sprite attempt to move directly towards the player, always. You can (as of ZOT 0.10) specify two kinds of AI -- one for "always" and one for "when player is near"; you then specify the number of tiles that define "near".

image_width and image_height define the clipping of the artwork. width and height define the size of the 'body' -- the substantial part of the sprite. You can also use offset_x and offset_y to specify the location of the body within the sprite itself. So for instance, it is cool to specify a large sprite, and then make the body a smaller square within it; also, specify the body to be a little down from the top using an offset_y, so that the "head" of the sprite can go onto walls etc (since the body is the part that impacts for collision test sake); this gives it an isometric appearance since the head goes over the wall...

Sprites are animated; as such, you must specify at least one animation state, though you can specify many animation states (one for each state the AI function can be in); most sprites care only about movement direction states, so they MUST have a state for "still" (standing still), but can also have state for "up" (while moving up), or "upright" while moving up and right, etc. All 9 directions are covered, of course. An animation block is by state, and can have anim_steps (number of steps in the animation before going back to frame-zero), anim_offset_x and anim_offset_y (the number of pixels to move over for each frame of animation) and anim_image (the name of the artwork to obtain animation frames from). "anim_shift_y" is how far to go down in the artwork to find this animation set. (ie: So you can have X going across for animaiton frames, and shift-y to go down to find alternate sets of animation; thus define one artwork file for all animation for a given sprite!)

sprite states are (as of ZOT 0.10): still, up, down, left, right, upleft, upright, downleft, downright, inactive, angles

The special states work as follows:

  • "inactive"; specify an "inactive" count in the sprite, as follows: "inactive 100"; that says that after 100 ticks of doing no movement, the sprite will become bored and switch to the inactive state if he has one. Then add in a anim_statedef for "inactive" which sets up the steps and artwork for the inactive state. Thus, after awhile, the sprite can be animated to look bored...
  • "angles"; See "option angles" above in the play modes description to know more; at any rate, you can say "anim_statedef angles ##" (where ## is a number) to auto-create a pile of statedefs, one for each facing of the mentioned artwork. This is mostly for "Asteroids" thruster style of play. The ## indicates the number of faces to create -- ie: You could say "anim_statedef angles 32" to create 32 sides .. a very smooth rotation; or use '4' if you like.. doesn't matter to Zot! Note that the sprite will not be in thruster mode unless you specify "option angles" and "option velocity" for the sprite. In effect, "anim_spritedef angles ##" creates ## statedef's for you, called "angle1" through "angle##"; as of 019.2 you cannot override these states but a later version of Zot will let you override these auto-created statedef's, or simply define them yourself; you would override them if you wish to use alternate artwork for specific or all rotations, in case you wanted to add shadows or the like that pure auto-rotation won't achieve. Statedef details in the angles state will be applied to all auto-generated angle statedefs. (ie: Saying "anim_steps 1" in an "angles" statedef will set them all to "anim_statedef 1", so if you override the auto-states, do them after the "angles" definition! (And if you "option velocity" without "option angles", it'll run in platformer style mode instead of thruster mode)
    option velocity
    option angles
    # rotation setup
    anim_statedef   angles  32  # include number of angles; default is 8!
    anim_steps	1	    # 1 artworks in artwork file
    

"anim_steps" may have an option line in it; "option once" will make that animation occur only once (not repeat). Only applies to sprites.. not conveyers, etc.

The sprite-block ends with a 'sprite' keyword.

sprite          baba	    # name of sprite for later use
name            baba	    # display name of sprite if we ever display it
order           1           # spr. order is 1..3 (start at 1, 3 is drawn last)
speed           3
# AI details
ai              mob_wander    # the AI to use
ainear          mob_robotron  # the AI to use when player is "near"
near            3           # 7 tiles away is "near"
# dimensions; artwork dimensions and sprite body dimensions!
image_width     16
image_height    16
width           16
height          16
#
# while standing still
anim_statedef   still       # if engine needs a missing state, first state used
anim_steps      5           # 7 artworks in pcx file
anim_offset_x   25          # artwork is 25px offset from last step
anim_image      pointyplus  # use this image for animating this state
#
sprite          end
	

NOTE that sprites have options you can turn on and off; options available to sprites are:

  • "option pushable" -- if present, this sprite will get pushed when a player bumps into it; the player is able to push the sprite any which way, though it never allows the sprite to move in a way he can't normally move (ie: If the sprite bumps into a wall or other sprite, it just won't push any more); ex: pushable walls
  • "option carryable" -- if present, this sprite will be taken out of the world and put into the players inventory when bumped into by the player. ex: keys for doors
  • "option indestructable" -- if present, the player's shot does not damage this object; the players shot will simply stop, as if it hit a wall. ex: for keys, so you don't destroy them...
  • "option airborne" -- if present, the sprite's movement is not impacted by floor based effects (as of ZOT 0.10, this means conveyer-belts). ex: players shot "arrow" sprite.. it doesn't make sense for players shot to get altered by flying over a conveyer belt..
  • "option impassable" -- if present, sprite cannot be walked through; if not present, sprite is like a ghost.. you can go right through it. (Any mob can go through it). ex: Maybe set a bouncy fireball so it goes through the player, hitting him and keeping going. But most sprites should be impassable.
  • "option ethereal" -- a sprite marked ethereal can *always* enter another sprite (though it still cannot enter impassable tiles); ex: fireballs -- you want them to fly a constant path, maybe using mob_bounce to bounce around. They should go through player and mobs, so make them ethereal; you could leave the option off, and then they bounce off players :) You may want to make fireballs indestructable too..
  • "option nostill" -- the sprite will start in Still state of course, but this option prevents it from returning to the still state; ie: Once it stops moving, it'll stay in the same state if the player lets go of controls; normally he would, for example, return to the still state.

Other keywords..

  • "start_direction DIRNAME" -- suggest to the AI that it begins in that direction; ex: mob_bounce needs this.

Tiles

A 'tile' is a building block of the world; it is re-used, though can be unique for the really interesting squares on the map. For instance, you would define a tile to represent a common floor square, with some pretty floor tile artwork. You would then assign this same tile to most squares on the map. This is done for efficiency sake.. rather than us store a giant 2000 by 2000 pixel map, we store a map of tiles, and most tiles are just references to the same tile object. This is how we have very large maps playable on very low powered devices. (A 'tilemap', detailed later, is how you build up the world based on tiles.)

Your basic tile, for a floor or wall, is simply defined:

# a sample floor tile
tile            x		# tile is called "x" in tilemap
name            floor		# name if we ever display it
image           floorgreen	# artwork to use
tile            end		# end of tile def
	

So the most basic tile definition is very short; the most important parts are the "x" above and the image; the "x" is the name of the tile and must be a single character. To draw a row of this tile in the tilemap, you would just say "xxxxx" to put 5 of these tiles onto the map.

NOTE the size of a tile is built into the game engine; it is changable only by Codejedi, but for efficiency and to allow complex artwork and walkways etc, we've chosen a tile-size of 16 pixels square. Before you run away in fear of making hundreds of little tiles of a large piece of artwork, note that the options below allow you to use larger pieces of artwork and have the engine split it up dynamicly for you, so you can have large artworks on your tilemap easily.

Here is a sample wall tile:

tile            N		# call it "N"
name            northwall	# display name
image           brownbrick	# artwork
option          impassable	# make it a wall
tile            end		# end
	

Note that the only difference here is we just added an option to the tile, and this option says this tile is not enterable by sprites or player. Thus, it is conceptually a wall.

The usual artwork options exist: offset_x and offset_y allow you to specify the offset to the tile in question, within the great artwork body. The main reason to use offsets is to allow you to draw a piece of artwork (say) 48x16, and then be able to refer to the left part as a tile, the middle part as a tile, and the right part as a tile. Quite handy. Check out autotile below which is a HUGE TIMESAVER.

Example: It could be handy to draw all the wall artwork in a single artwork file; then you could use offsets to specify where in the artwork each wall tile is. This lets the artist have it much easier (one file rather than dozens), and the level designer need only specify the coordinates of the specific tiles artwork.

Options available are:

  • "option impassable" (watch the spelling!) -- an impassable tile cannot be entered by anything. Its like a wall. (This is a conveniance function that is the same as doing all 4 option_impassable_directions)
  • "option impassable_up", "option impassable_down", "option impassable_left" and "option impassable_right"; the direction refers to where the sprite is coming from; ie: impassable_down says this tile cannot be entered from the down-side.
  • "option autotile" -- SUPER USEFULL. If you draw a piece of artwork that is larger than one tile, but wish to display it, you would have to manually specify all the offset_x's to get to each piece of it, and make a number of tiles. Autotile lets the engine do it FOR YOU. Ex: If you made a doorway that is 32x16 pixels (2 tiles across, 1 tile tall), then you could manually create a tile 'l' (left), and another tile 'r' (right), and 'right' would have to have "offset_x 16" to tell it to use the right-half of the artwork. INSTEAD, you would just define one tile (call it 'd' for door, say), and mark it with "option autotile". Then in the tilemap you can refer to "d<" instead of "lr"; "d" would be the tile you defined (the left half, since no "offset_x"), and the "<" is a special symbol that uses autotile to determine that this is the "next tile over" which would be the right half. So you can define a loooong piece of artwork like this "a<<<<<<<<" and define only one 4 line tile in the config to do it. SEXY!

Complex or Special Tiles

Most tiles are just plain ordinary unanimated background tiles.. the player runs over them, or into them, but they don't really do anything fancy.

Some tiles are interesting -- wayout tiles can transport a player to another floor, while door tiles block the players passage while closed, etc. These tiles are further described here..

Complex tiles are tiles that "do something" other than just sit there or apply flags against the player. For instance, a 'door' tile is really a fancy tile than can exist in one of several states at any given time. A wayout tile is one that shifts the player from one map to another, and is also animated so it can do stuff.

Note that usually you tie a regular tile to a complex tile reference; this lets us do thing slike have 5 tiles that all point to a single (say) door tile reference; opening the door will be reflected in all referring tiles, for instance. Make multiple buttons work together (change one, they all change) for example if you want to, and tie groups of conveyers together..

NOTE: Yes you can construct much of these tiles via complex trigger/action scripting but it is better to use the built in mechanisms for both performnce reasons, and the fact the engine can Do the Right Thing with them.

NOTE: Yes, you can use these tiles for other than the intended purpose; a door tile is really just a multi-state tile, and a wayout is an animated exit tile.. but you needn't exit the player anywhere. If you want an animated tile, use a conveyer say or wayout and away you go :)

TIP: A conveyer needn't look like a conveyer; you could dress it up like water and use it for urrent, say..

Here are the types of complex tiles..

  • Button (multiple states with action on state change)
  • Door (multiple states gadget)
  • Wayout (animated, allows for player map change)
  • Conveyer (animated, can push player around)
  • Mob Generator (is actually a sprite; see mob_generator AI!)

Each complex tile is detailed below..


Button

A button is a gadget that can be in one of a few different states. Since you use artwork of your choice for each state, it needn't *look* like a button .. it could look like any gadget you want, such as a lever, a pressure plate, a fountain, or anything else. A button can be activated by the player just entering the tile, or you can require the player to press the action button on his controls. Thus, a pressure plate is (for example) just a two-state button that is triggered on player entry, while a wall mounted switch is a two state object that is toggled by the player pressing his action button. When activated, a button changes state (and thus can use alternate artwork to look different) and fires off an Action (which can in turn fire off an Action Group).

Configuring is easy; you need to make a button object in your config, and then you need to associate one (or more!) tiles to it. ie: You might associate multiple tiles to the button object, so that adjusting the button in one place impacts it in other places as well. Note that the tiledef does not need an artwork setting.. the buttons artwork is used instead. Note that the tile can refer to a button that does not yet exist, if it wants to.. the tile can be defined before the button.

Note that a button can have 4 states: alpha, beta, delta, sigma

You should specify the beginning state, and for each state you should specify which the next state is when changing; ie: When you activate the alpha state, does it go to the beta state? And when going from beta state, does it go back to alpha state?

A button state can have an Action mentioned; this Action will be fired off when the state is .. 'exitted'. ie: When player enters it or hits his action button, as the button dictates, the states Action will fire off.

A note about Actions and buttons: Note that usually buttons are defined before a tilemap (floor) is, so you might wonder how to have a button do a "goto-floor", since you cna't set up a goto-floor when the floor is not yet defined. In this case, set up an action to invoke an action-group, and that action-group includes goto-floor command... and the action-group is defined AFTER the tilemap! hoho!

A typical boring button setup might be:

# define a tiledef that happens to refer to a button
# notice.. no artwork is defined for the tiledef
tile		b
name		buttondoorx
button		1	    # associate with button-1
tile		end

# create a button object; note its button '1' mentioned above
# notice each state has an artwork defined for it
# notice you specify the state to begin in!
# a button has at max 4 states
# notice that "toggle_door" is a special built in Action, but you can
#   specify actual Actions to invoke, to do all sorts of crazy things
# notice you can specify the statee to change to when this state becomes
#  activated
button		1	    # a lever is the same as a button w/ alt. artwork
state		alpha	    # state to begin in
anim_state	alpha
  anim_image	buttongr
  toggle_door	1	    # action to take on exit of state
  option	trigger_entry
  exit_state	beta	    # state to go to after this one
anim_state	beta
  anim_image	buttonor
  exit_state	alpha
  toggle_door	1
  option	trigger_entry
button		end
	

Text menus (dialog, talk trees, etc)

As of Zot 014 this is still WIP, but seems to be working well. The basics are.. a text menu tree is popped up by a Trigger, and offers some text and options, where picking an option fires off an Action(s).

text-menu	10
preamble	"Welcome to this menu; blah blah blah, blah blah rant."
"Open the door"	end-dialog
"Quit"	        goto-menu 5
text-menu	end

In essence, there are few options though more will be added hopefully (such as hints to show a character portrait while talking, etc); namely, you need to include a 'preamble' with a quoted value which is the text menus main text. The system will word wrap it as appropriate to fit the screen. Other than preamble, you need to supply 1 or more options, which are quoted text keys, with the value(s) being action(s) to take when that option is selected. See the section on Actions for a discussion of actions that can be assigned, but typically you could open another text menu to continue the discussion, or you could close the dialog and return to the game.

NOTE: The default artwork to show the selection is an image named "textsel"

NOTE: As of Zot GBAX edition, up to 10 option entries are allowed in a textmenu.

Additional options:

  • "avatar-image IMAGENAME" -- show a textmenu with a little picture to its left side; textmenu is offset to the right enough not to collide with the image. Good for showing a picture of someone/something the textmenu is dialoging or describing.
  • "avatar-name" -- name an avatar image; shows up under the image.

Triggers

A trigger is a set of required conditions, along with an action request to perform when the conditions are all met. An Action of course can be an Action Group and thus the trigger could result in several things going off. An example might be to require that the trigger watches for a player entering a certain square, while also carrying a certain item, causing something to occur. Note that there are interesting Actions like turning on or off a trigger, or setting variables.. so you could require that player goes to a certain area which invokes a trigger to set a variable, and have another trigger that awaits player to show up somewhere while having that variable set, and thus require the player to go to one place before going to another, etc. A lot of flexibility is granted here!

NOTE that there is a special class of triggers known as "Events". See them below!

NOTE that with Triggers and Actions you can reconstuct some other primitives of the engine.. for instance, you could implement triggers and actions to facilitate Exits/Wayouts, or Doors, or Buttons. It is usually better to use the built in systems, however, since they already have animation, state saving and all the goodies worked into them. Triggers and Actions are usually used for defining things the engine doesn't already do :)

You can combine many triggers, but one action; that action can invoke an action group however, so in effect you can have many trigger criterion, and many actions as a result of the matching of all criterion.

trigger		1
on-player-entry	5,6                  # when player enters 5,6
on-floor	mainfloor            # and on floor 'mainfloor'
action		action-group 10	     # perform a group of actions
trigger		end
	

The trigger criterions are:

  • on-player-entry (requires argument of x,y for coordinate) -- satisfied only when player is in square
  • on-floor (argument of floor name .. the tilemap name) -- only satisfied if player is on the mentioned floor
  • on-variable-equals (requires two arguments; variable name and value that satisfies the trigger). ex: "on-variable-equals foobar 5"
  • on-variable-lt (requires var name, value); less than.
  • on-variable-gt (requires var name, value); greater than.
  • on-variable-ne (requires var name, value); not-equal to.
  • on-no-sprite (requires floorname spritename); example: "on-no-sprite mainfloor orangekey"; this lets you say to do something if all of a monster has been destroyed, say.
  • on-pickup-sprite (requires spritename); example is "on-pickup-sprite orangekey". You can use this trigger to make a message or chage variables or goto floors etc, when the player picks up something.

You can also specify some options to triggers..

  • "option continuous" -- normally a trigger can get activated and then it will not be activatable again until it becomes unactive. (ie: Once it matches, it stays matched and does not re-match). With this option it matches, fires off, and then unmatches so that it can match again next check. This is slightly higher load of course, but good for continuous effects like damage-by-time traps, etc.
  • "option disabled" -- disables the trigger. This is useful because you might have an action set up which later enables it (or disables it again, etc).
  • "option onceonly" -- stops trigger processing after this trigger. Allows one trigger to catch an event (say), and then halt processing before another trigger also processes it.

Events

An Event is a special kind of trigger that occurs in real-time during world processing. Thats hard to think about, but its for things like damage -- if one object runs into another object, it has to be dealt with immediately, since (1) one of them may die or otherwise impact the world .. mob changes direction, etc., or (2) thats the only time we know what object hit what other object.

So if one mob (for example) runs into another mob, a "collision" event is generated immediately, all event-triggers are checked for handling this type of event, and then the world continues. Since you can have a lot of these (hundreds of mobs walking into each other for example) it is best to keep the resulting actions simple and not length, but you can do whatever you like.

An event is just a trigger that has a "when-" clause within it; it should likely also have other "on-" trigger clauses in it as well!

Event clauses:

  • "when-collide " -- to make an event for one mob running into another. (ie: A robot walking into a player works fine!). The action (or group) invoked as a result of this event has _from and _into special variables defined.
  • "when-dies " -- to make something happen when a mob dies. Not player, since player death ends the game :) Special variable _mob is defined during the duration of this event.
  • "when-ltezero " -- to make something occur when a mob-variable goes to (or less than) zero. _mob special variable is defined during this event. ex: "when-ltezero player health"

Actions

An action is a 'transformation' you can cause in the world; usually an action is the result of a Trigger, or perhaps a Text Menu item being picked. For instance, you may configure a Trigger to watch for some event to occur, and when those event conditions are met, that an Action will be fired off. So the Trigger is the "watch" condition while the "Action" is the "result of the trigger. You "enter the door" and "as a result, the pie hits you in the face" :)

NOTE that there are two kinds of actions really.. a single "action" which is something specific, like "open the door number 17", and also "action groups" which is a collection of actions. So you may want a text menu to simply end the dialog and return to the game (a single Action), or you may want the text menu to cause a monster to be created, a door to be opened, and player to get some score. This would be an Action Group, and the text menu would refer to an action that launches the group as a whole.

NOTE: ZOT is currently being built to allow no more than 10 actions in each action-group, but its possible to invoke action-groups from within action groups..

action-group	10
post-message	"Welcome to 6,5" 3
post-message	"Second action.. after Welcome" 3
goto-text	1
action-group	end
	

The available actions are:

  • "goto-text" -- argument is ID of text menu to display.
  • "end-dialog" -- no argument; end text menu session.
  • "action-group" -- argument is ID of action-group to invoke.
  • "post-message" -- argument is quoted string to display. Note that variables can be embedded in the string.. use "$varname" to do so. As such, use "$$" to put a single dollar-sign into the string, since otherwise a single dollarsign begins a variable expansion. You may use variables side by side, ie: "$var1$var2". Ex: "something '$myvar' foo" will come out as say "something '2' foo".
  • "variable-add" -- argument of variable name and value to add to it when activated
  • "variable-sub" -- argument of variable name and value to subtract to it when activated. This function may be appled to a mob during an event trigger: ex: "variable-sub _from.myhealth 10"
  • "variable-set" -- argument of variable name and value to set it to when activated
  • "trigger-change" -- argument is trigger ID and one of: '0' is disable trigger, '1' is enable trigger, 'toggle' is toggle trigger. Use this action to turn a trigger to enabled or disabled.
  • "goto-floor" -- argument is name of floor; note, this most be defined after the floor has been defined in a tilemap. You could define an action that invokes an action-group, and then after the floor is defined define the action-group with the goto-floor in it. "action goto-floor 2ndfloor".
  • "make-sprite" -- argument is spritename and x,y coordinate (in tiles); ex: "make-sprite baba 3,5". Attaching this to a on-entry button allows you to have a pressure plate that spills out monsters say... or a textmenu option that creates a mob to talk to, etc. As of GBAX edition, make-sprite can use _from or _into as location, meaning it copies the location from the referenced mob.
  • "kill" -- only usable during an event trigger; as of ZotGBAX only the when-ltezero event trigger supports it. Use "action kill _mob" in the action or action-group fired off by the event.
  • "end-game"; kills the application.
  • "script"; A powerful Action that lets a trigger, button, door, etc fire off a Zotscript script. The action requires two arguments.. the script-name, and the function-name. Example: "action script myscript myfunction"

ZOT AI Types

Each sprite must have at least one AI's chosen for it; the AI is the "behaviour" the sprite takes while active in the game world.

The player must be 'player'. Sprite definitions should usually use the mob_ series of AIs.

Many AI's have options you can set. You can also use 'near' to define an AI for when player is near, and when player is not near; ex: Set a mob to wander randomly, then robotron him when he approaches. Or run form player when he nears, but otherwise act as a mobile generator :)

  • mob_arrow -- moves in a straight line, removes itself and enemy on impact.
  • nil -- does nothing on its own
  • player -- does nothing on its own
  • mob_robotron -- always move directly towards player; will throw when-collide events when bumping into player or mob.
  • mob_generator -- wants to create new mobs (see generators)
  • mod_wander -- wander randomly; will throw when-collide events when bumping into player or mob.
  • mob_flee -- always move directly away from player
  • mob_bounce -- move straight, reverse direction on impact
  • mob_animonce -- no intelligence, but animate once and then kill self. You should use "option once" in the anim-steps definition, so that it can actually qualify for this. This was used in ZotGBAX for example to make a floating damage indicator above impacted sprite.
  • mob_guard -- stand where created; if away from this spot, uses robotron logic to move back to that spot. For example, can use ainear to have mob go towards player, and if player gets too far away the mob_guard will then return to spot. However, shooting the mob will make him robotron the player. Note that for guard->attack mode to occur, guard must have a variable "health" so it knows its gone down.

Engine Variables Reference Guide

The ZOT engine includes a number of internal variables; some of these can be read, or written to, or both.

For mob-specific variables, see below.

All internal variables begin with an underscore ( "_" ). When you create your own variables you can name them whatever you want.. as long as they do not begin with an underscore. Those are reserved.

Engine variables may be entirely useless, or may do cool things.. its entirely up to what you want to do :)

  • "_player_speed" -- read and write. Setting it adjusts the players speed. A player default speed is defined in the configuration (say, preconfig.txt in the default ZOT setup). You can do math to it.. say, add 1 when a player picks up "speed boots" by using a trigger, for example.. (and then subtract 1 when player loses speed boots, say.)
  • "_player_x" "_player_y" -- read and write. Player location.. setting it will teleport the player. Not usually a good idea, since you don't know whats there.. but if you make a map area that monsters can't go into or the like, it makes a good candidate..
  • "_player_dirmask" -- write-only. Setting it limits the players input buttons. (ie: There are 6 inputs.. the 4 directions and the fire and action button.) The bits are: left(1), right(2), up(4), down(8), fire(16), action(32). ie: The default mask is hex=3F which is all flags allowed. By limiting it to say decimal=3 you limit the player to left and right only. The value must be in DECIMAL.
  • "_ticks_since_begin" -- read/write; When the engine starts up this is 0; for each world tick (not player ticks, which happen twice as often) this increments by 1. You can read it, or set it if you wish to alter it. ie: You could do a trigger on this to have some pre-game initialization, for example, or do periodic events.
  • "_world_gravity_x" and "_world_gravity_y"; Can be negative. Adjust these to put forces against the player sprite. ie: A _world_gravity_y of "1" will push the player down 1 thrust unit each tick. "-1" would push the player up the screen! You can therefore have gravity in any arbitrary direction and strength using these two variables. An example is in a platformer.. player jumps, and then comes back down to his platform; if he runs off a platform, he falls to the next one down. This is gravity. (Requires "option velocity")
  • "_world_friction_x" and "_world_friction_y"; These are similar to gravity, but they converge on zero. (ie: Gravity can take a positive velocity and eventually make it negative; friction just reduces it to zero, stopping the player.) An example is a platformer.. player runs for a bit, and when he lets go of the controls, his sprite slows to a stop (but doens't stop immediately.) (Requires "option velocity")
  • "_player_jumpvelocity_y"; 175 is default. When player pushes "up" on controls, and is in "option velocity" (but not angles) mode, he'll thrust up. This variable controls the amount of thrust (or the height of the jump). The jump height is relative to this variable against the current gravity and friction. (Requires "option velocity")
  • "_player_movevelocity" (default 7); change this to change how much thrust the player exerts when trying to move. This is only useful when "option velocity" is active.

Mob-variables

Variables created inside of a sprite-block are attached to the sprite definition, and whenever that sprite is created into a mob, the variables will be copied into it. As such, this lets you create variables that belong to the player or mobs, with each mob having its own set. Perfect for health, etc!

"variable myhealth 100"

Tips and Samples

A ghostly cathedral or graveyard could easily be simulates thusly:

  • In ZOT 0.11 you can flag a sprite as "ethereal", meaning it can go through other sprites, always. (Sprites marked "impassable" as of 0.11 are not normally enterable, but if you forget to mark them impassable, things can enter it, but it cannot go through other things unless it is also ethereal) So, say you want a graveyard or other ghostly place where the monsters can come through the walls, but the player cannot? Simply make the walls out of sprites (using the same artwork as walls normally would), and flag the monsters as ethereal.. the mobs will then walk through the walls, and the player.. will not. Note that there is a performance hit here, since we'd be using sprites for walls.. meaning, the tile underneath would be rendered, and then the sprite... so double the cost for each tile. Framerates could suffer, so use sprite-walls sparingly!

Or how about a vertical shooter level?

  • A conveyer square need not *look* like a conveyer; it could just use floor tile artwork and no animation. Simply set a whole area of map as conveyer that looks like "shooter background" (floor, outer space, whatever), and the player will be constantly pushed in the direction and speed you've set for the conveyer. Then you place mobs with limited "vision" at points in the level.. such as setting them to "nil" AI until player is "near", and set up a suitable "near" setting. So the player will be forced along at a constant speed, and can fire at incoming enemies. Thats it.. a simple rudimentary shooter :)

If you want something to occur every few times, you can use variables: See this example below -- trigger ID 2 increments a variable every time player enters its square. Trigger ID 1 will only fire off when player enters the square and the variable is equal to 5; when it fires off, it shows a dialog, but also sets the variable vack to zero(0), so that it can go off again.. Thus you can see the action-group ID 10 goes off every 5 times the player walks by it.

action-group	10
goto-text	1			# show a message/dialog tree
variable-set	foobar 0
action-group	end

trigger		1
on-player-entry	5,6
on-floor	mainfloor
on-variable-equals	foobar	5
action		action-group 10		# do stuff
trigger		end

trigger		2
on-player-entry	5,6
on-floor	mainfloor
action		variable-add foobar 1
trigger		end

Sample Zot config files

Some sample simple config files are here:

Zot 0.1.5c: config.txt and preconfig.txt

Send email to Jeff Mitchell at support@codejedi.com