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

Zotscript is the scripting language component of Zot; for the Zot main page, see here:

Zot!

ZOTScript Reference Guide

Introduction (and Hello World)
The Language (how to construct scripts)
Entry Points (what functions are needed in your scripts and when)
Development and Debugging (process, zotlog, etc.)
Function Reference (what functions you may call to effect the world)
Gotchas (Thinks to watch)
Credits
Sample Scripts

ZOTScript Introduction

Zot is a reasonably general "2d tile game engine", designed to make building simple games easy and fast, with the option to grow to larger games. Zotscript is the extension language that Zot provides the developer so that Zot can be extended without going after the Zot engine itself. For example, the engine provides a limited number of "AI modules" (behaviours for sprites), though with Zotscript the developer should be able to define an AI to fit his needs, without going to the low level engine code.

Hello World

'Hello World' is the canonicle first job in every programming language. Here I will contrast 'C' and Zotscript:

	// 'C' version for text console
	#include 
	int main ( int argc, char *argv[] ) {
		printf ( "Hello World!\n" );
		return ( 0 );
	}
	
	// Zotscript version, graphical
	public postRender() {
		post_message ( "Hello World!", HUD_DURATION_LONG );
	}
	

Both are similar, but you will notice a couple of interesting things:

  • main() is not needed as in C version
  • #include is not needed as in C version (all functions are always available)
  • postRender() is called by the Zot engine where as a C program is usually in control
  • postRender() is declared "public" so the engine knows it is callable; if it is not marked public, then the outside engine doesn't know about its existance

ZOTScript Language

	new var;
	for ( var = 0; var < 10; var++ ) {
		// do things
	}
	
	new var = 3;
	while ( var ) {
		// do things
		var--;
	}
	
	if ( var stuff ) {
		// do things
	}
	
	function_name ( arg1, arg2 ) {
		// do things
		return ( value );
	}
	

Glossary:

  • A sprite is a definition ... a blue-print. It exists to describe what a mob will look like when it is in the world. (For example, 10 cars on the street are all makes of the Integra model. Likewise, you might have 10 knights wlaking about, but they're all a single Knight-sprite model. A sprite has a behaviour, artwork, etc, but does not exist in the world.
  • A mob is a currently 'living' sprite -- it knows what kind of sprite it is so can look up to its sprite to figure out what to do. A mob has a location in the world, some current variables, and other unique things.

Basic Concepts:

  • Scripts do not remember anything between invocations; if you need the script to remember something, stick it into a mobs variable, or a global variable!

ZOTScript Entry-Points

An entry point is where the script begins execution. Normally in a C program, the code always begins running at main() for example, so thats where you initialize things and start doing useful work. Zotscript tends not to be in the driver's seat however, and is instead called upon to do certain things over time from the main Zot engine. When the Zot engine calls into your script, it calls various functions and thus those functions are all potential entry-points, instead of just main().

NOTE: Some Zot builds allow your script to drive the entire engine and thus be in total control, with the engine working for you. To be discussed later.

The number of entry points will grow over time.

Current entry points are:

  • main() - returns a success or failure, takes no arguments

    main() is called while the configuration game file is being loaded. In particular, after the script is 'compiled' and made ready for use, main() is called purely as a test for the script. In general it can return any number it wants and this is noted in the zotlog; if the script failed to compile then this execution will fail and all sorts of logging will ensue to help debug the situation.

    It is conceivable to do real work during this invocation, but it is frowned upon since the config file is not fully parsed -- ie: if the script occurs halfway down the config, and a map is defined later, then the script may not refer to the map since it does not exist yet. However, the script could perhaps do one-time setting of global variables and other work, if it really wanted to.

    Example:

    	script killer
    	// ...
    	// script stuff
    	// ...
    	main() {
    	  return ( 37 ); // some number, anything will due
    	}
    	// ...
    	script end
    	
  • mobAI() - return kill-state, takes no arguments

    mobAI() is called if a script is associated to a sprite definition for AI, and if it is present, and if the sprite as "mob_script" as its AI. You provide this function if you wish to make a custom AI for a sprite, such as if you wish to make a Pacman ghost work like it should -- you cannot use mob_wander since the ghost would move randomly (sometimes backtracking) while a Pacman ghost needs to only move forward, left, or right, but never backwards. Simply script up an AI and name if mobAI()!

    NOTE: The script may return AIok (0) or AIdelete (1) -- if AIdelete is returned, then the sprite in question is 'killed'

    Example:

    	script killer
    	// ...
    	// script stuff
    	// ...
    	mobAI() {
    	  // stuff
    	  new id = mob_this();
    	  mob_move ( id, dirUp, 3 ); // move 3 up
    	}
    	// ...
    	script end
    
    	sprite	knight
    	// sprite definition
    	// ...
    	ai              mob_script killer
    	// ...
    	// sprite definition
    	sprite  end
    	
  • playerAI - no return, no arguments

    playerAI() is called if a script is associated to the player, and is present, and if the mob_script AI is used. This is much like mobAI(), and allows you to supply custom player behaviour. Zot will by default perform lots of player handling, such as allowing 8-way movement, managing firing and device activation.. however, if you set up the player sprite with a mob_script, then the player control is entirely up to you .. if the player presses Up, and your game allows up movement, you'd better handle it :)

    Example:

    	script playerbrain
    	// ...
    	// script stuff
    	// ...
    	playerAI() {
    	  // stuff
    	}
    	// ...
    	script end
    
    	sprite	player
    	// sprite definition
    	// ...
    	ai              mob_script playerbrain
    	// ...
    	// sprite definition
    	sprite  end
    	
  • resetLevel - no return, no arguments

    resetLevel() is called if the script is associated to a tilemap and is present. If not specified, Zot will of course follow its normal rules, which is to re-pop all sprites and reset the player to the "option starthere" (usually '@') tile in the tilemap. resetLevel() is called once to initialize the level, and once after player dies, and is thus useful for creating or killing sprites, moving the player to the starting or continue locations, or other once-per-life or once-per-level housecleaning.

    Example:

    	script fooboo
    	// ...
    	// script stuff
    	// ...
    	resetLevel() {
    	  // stuff
    	}
    	// ...
    	script end
    
    	tilemap Level1
    	// tilemap definition
    	// ...
    	script fooboo
    	// ...
    	// tilemap definition
    	tilemap  end
    	
  • postRender - no return, no arguments

    postRender() is called after all rendering has been performed, if the script is associated to the current tilemap. The Zot engine will render tiles and sprites and watnot automatically, but should you wish to make an overlay or apply some extra darkening or blending or test, this is the place to do it. For example, if you wish to render some statics or scores in the top left, just pop it into this function. Another powerful use for this could be a menu system to begin play, or after the player completes an area .. make a tilemap that shows a background or some buttons, using postRender() to move a highlight around or the like. Powerful stuff.

    Example:

    	script fooboo
    	// ...
    	// script stuff
    	// ...
    	postRender() {
    	  // stuff
    	}
    	// ...
    	script end
    
    	tilemap Level1
    	// tilemap definition
    	// ...
    	script fooboo
    	// ...
    	// tilemap definition
    	tilemap  end
    	

ZOTScript Development and Debugging

Watch your zotlog :)

ZOTScript Functions and Constants

The scripting language is one thing, but you cannot impact or find out about the 'world' without calling the Zotscript API functions. To move a mob, you call the mob_move() function for instance, and you'd see below to find this out.

Since there are so many possible functions, they've been organized into sections. A function name begins with its section name, to keep things easier... "get_x" isn't nearly as descriptive as "mob_get_x()", and hence is located in the "mob" section of functions. However, some functions return or take a magic number, and to make this easier to remember these magic numbers have been named. For instance, you would say "mob_move ( ..., dirUp, ... );" -- where dirUp is actually just a number, but dirUp is so much more meaningfull than just the number "4".

Constants

These are used for the mob_move() function, if not others.

	dirLeft
	dirRight
	dirUp
	dirDown
	

These are used for last_block_type(), after calling mob_move(). See mob_that() as well.

	blockNone
	blockImpassable
	blockMobile
	

Global Functions

global_get ( name[] )

Returns the numeric value of the named global variable. This is a normal Zot variable, and so is available to all Zot config triggers/actions/etc, as well as all Zot scripts. It retains its value until the Zot engine quits.

global_set ( name[], value )

Sets the value of the named global variable.

Mob Functions

mob_this()

Returns the mob-ID of the currently running mob; this is only valid during a mobAI() entry point call (and anything called by that entry point of course.); typically this is used to do something to, or query values from, the current mob, so that you can do something useful in the AI. Since a script does not remember anything between invocations, it is common to store values into the mob's particular variable list, or global variables.

mob_that()

Returns the mob-ID of the mob last bumped into during a mob_move() invocation. mob_move() will return how far a mob moved, but if it moved shorter than it wanted to you can find out what it ran into using mob_that(). What did the running into is mob_this().

mob_move ( id, direction, distance )

Attempt to move a mob in a given direction. Pass in the mob-ID of the move to move, the direction (such as dirUp, dirLeft, etc, see Constants above), and the distance to attempt to move (in pixels). The function will return the number of pixels actually moved -- this number could be less than what you requested if the mob runs into a wall or another mob (something flagged as impassable). Should you wish to find out what kidn of impact it was (into a wall or mob), see last_block_type() below in Utilities.

mob_move_towards ( id, x, y, distance )

Attempt to move a mob straight towards the specify world coordinate. Pass in the mob-ID of the move to move, the pixel coordinate and the distance to attempt to move (in pixels). The function will return the number of pixels actually moved -- this number could be less than what you requested if the mob runs into a wall or another mob (something flagged as impassable). Should you wish to find out what kidn of impact it was (into a wall or mob), see last_block_type() below in Utilities. (Available in Zot 047 and later.)

mob_get ( id, name[] )

Return the value of a mob's variable. (Similar to global_get but for the mob's personal variables.

mob_set ( id, name[], value )

Set the value of a mob's personal variable.

mob_make ( name[], x, y )

Pop a mob into the world; specify the Sprite name to clone and the (x,y) coordinate in the world for it to appear at. The mob will simply appear there, so it is best to have it appear not on top of a wall or other mob, but that'll work fine if it does.

mob_kill ( id )

Flag a mob as having been killed; after the frame has completed, the engine will remove it for you.

mob_first ( pri )

Return the mob-ID of the first mob at the specified priority level, or 0 if none.

mob_last ( pri )

Return the mob-ID of the last mob at th specified priority level of 0 if none.

mob_after ( id )

Return the mob-ID of the mob after the id provided or 0 if no more. Given mob_first() and mob_after() one can go through all the mobs if they need to. Useful for killing all the living mobs, or scanning for variables, or moving them all, or other tricks.

mob_get_x ( id )

Return the specified mobs x-coordinate in the world.

mob_get_y ( id )

Return the specified mobs y-coordinate in the world.

mob_set_x ( id, x )

Set the mob's x-coordinate -- the mob is not "moved" per se, just teleports. ie: It could appear on top of a wall or mob and doesn't care or report impacts.

mob_set_y ( id, y )

Set the mob's y-coordinate -- the mob is not "moved" per se, just teleports. ie: It could appear on top of a wall or mob and doesn't care or report impacts.

mob_set_xy ( id, x, y )

Set the mob's (x,y)-coordinates -- the mob is not "moved" per se, just teleports. ie: It could appear on top of a wall or mob and doesn't care or report impacts.

mob_set_sprite ( id, sprite-id )

Set the given mob-ID with the specified sprite-ID. This should let you alter the behaviour (etc) of a mob, without going through and mob_kill()ing it and then mob_make()ing it over again, so you keep your variables etc.

mob_get_sprite_id ( id )

From the given mob-ID, pluck its sprite-ID; could be useful to tell what type of sprite a mob is, or maybe for copying it from one mob to another (like some clone monster perhaps?)

mob_at_xy ( x, y, except-mob-ID, greedy )

Returns a mob-ID or 0 if no match. Appeared in 046 and later.

This function tries to locate a mob at the given world coordinates (in pixels, not tiles). If you specify a except-mob-ID then that mob will be ignored instead of being matched, or you may specify 0 for except-mob-ID to match anything. (It is handy to pass the player mob-ID here, if you don't wish to select the player.) 'greedy' may be 0 or 1 -- 0 means non-greedy, which is slightly faster and goes by mob-center-point, while 1 means 'greedy' and is more accurate but a little slower, and goes by checking all mob corner points for contact with the tile in question. It is usually not necessary to use greedy mode.

	public playerAI () {
		new pid = player_mob_id();
		new mob; // mob at the player location?

		mob = mob_at_xy ( mob_get_x ( pid ), mob_get_y ( pid ),
				  pid /* except player */,
				  0 /* non-greedy */ );

		if ( mob ) {
			// do something with given mob
		} else {
			// do something when no mob found
		}

	}
	

Sprite Functions

sprite_get_id ( name )

Return the sprite-ID of the named sprite. (Remember a sprite is the description of a moving unit, while the actual unit in the world is the Mob. A mob has location, hitpoints, etc, while a sprite merely details behaviour, appearance, etc.)
NOTE: This function is useful with mob_set_sprite() to alter the behaviour/appearance/etc of a given mob, without killing it and making a new sprite in its place. This should work... ;)

Player Functions

player_mob_id()

A player is also a mob on the map, and so this obtains his mob-ID. Be careful when killing all mobs in the world, say, since the player could be one of them :)

player_key_left()

Returns non-zero if the player is pressing Left.

player_key_right()

Returns non-zero if the player is pressing Right.

player_key_up()

Returns non-zero if the player is pressing Up.

player_key_down()

Returns non-zero if the player is pressing Down.

player_key_fire1()

Returns non-zero if the player is pressing Fire.

player_key_fire2()

Returns non-zero if the player is pressing Action.

Utility Functions

post_message ( message[], duration )

Post a message to the current floating message queue (the messages that appear in the middle of the display.) Note that many messages may be posted, but only a few will be shown at a time. Each message will last for a period of seconds you specify. See some Constants for some suggested durations.

random ( min, max )

Return a random number between (inclusive) the two provided numbers.

px_to_tile ( px )

Convert a pixel coordinate to the equivalent tile coordinate. (ie: Tile 1 is pixels 0 through 15, since each tile is 16 pixels wide.)

tile_to_px ( tile )

Convert a tile coordinate to pixel coordinate.

ticks()

Return the current "tick" counter; there are a few hundred ticks per second, so this is the unit of time Zot engine uses to know some time has passed; useful to ensure some action doesn't occur too many times in a row.. ie: A player cannot unless 500 shots per second, so you may wish to stuff some variables somewhere som you can see how many shots the player has fired recently, or ensure the player fires a few moments after his last fire, etc.

last_block_type()

Returns blockNone, blockImpassable, blockMobile depending on what occurred last mob_move().

script_call_simple ( script[], func[] )

Invoke the named function in the named script. No arguments can be passed.

goto_floor ( name[] )

Attempt to switch the player to the named floor. resetLevel() will be called in that floor.

distance_between_mobs ( id1, id2 )

(Returns -1 if one of the mob-IDs is bad.) Returns the distance in pixels between these two mobs. (Always a +ve number.)

distance_between_mob_and_tile ( id1, tx, ty )

(Returns -1 if the mob-ID is bad.) Returns the distance in pixels between mob and the tile (always a +ve number.) Note that the tile is identified in tile coordinates. If the tile coordinate is outside of the map, the behaviour is undefined.

distance_between_mob_and_tile ( id1, tx, ty )

(Returns -1 if the mob-ID is bad.) Returns the distance in pixels between mob and the tile (always a +ve number.) Note that the tile is identified in tile coordinates. If the tile coordinate is outside of the map, the behaviour is undefined.

distance_between_tiles ( tx1, ty1, tx2, ty2 )

Returns the distance in pixels between the two tiles (always a +ve number.) Note that the tiles are identified in tile coordinates. If the tile coordinates are outside of the map, the behaviour is undefined.

distance_between_xy ( x1, y1, x2, y2 )

Returns the distance in pixels between the two world coordinates (always a +ve number.) Note that the coordinates are identified in pixel coordinates. If the pixel coordinates are outside of the map, the behaviour is undefined.

Device Functions

device_get_width()

Return the screen's width on the device.

device_get_height()

Return the screen's height on the device.

Surface Functions

surface_get_bb_id()

Get the surface-ID of the backbuffer -- the buffer about the be copied to the display screen. This is useful in the postRender() function to draw onto the display after the main Zot engine has already done its drawing.

Font Functions

font_get_id ( name[] )

Get the font-ID of the named font.

Image Functions

image_get_id ( name[] )

Get the image-ID of the named image.

image_has_alpha ( id )

Return non-zero if the image has an alpha channel currently, or 0 if no alpha.

image_set_alpha ( id, alpha )

Set the alpha channel of the whole image; specify -1 to delete the alpha channel, or some number from 0 through 255 to set the alpha level. Good for doing fade-outs and fade-ins.

image_load ( name, filename )

Just like the image loader block in the zot config; given a filename and name, it'll try and load the image and associate to that name. The image-id is returned, or 0 on failure. Handy for loading images as needed, rather than right up front... use this for very large images which could eat up RAM. (Zot 046 or later)

image_unload ( image-ID )

Given a working image-ID, it is unloaded from memory. Good for ditching large images and freeing up the memory. (Zot 046 or later)

Audio Functions

audio_get_id ( name )

Get the audio-ID of the named sample from your config.txt

audio_play ( id )

Play the specified audio-ID wav file.

Draw Functions

draw_font ( surfid, fontid, text[], x, y )

Draw some text onto the surface at the specified coordinates.

draw_image_noclip ( surfid, imageid, x, y, trans )

Simple image drawing -- just render the image at the specified location; if trans is 0, just draws the whole image as solid. If trans is 1, draw the image but support a simple RGB(123,123,123) transparency colour index. If trans is 2, then is an alpha layer trans (use only on images that have an alpha layer!)

draw_rect_darken ( surfid, x, y, w, h )

Darken the specified region on the surface.

draw_rect_set ( surfid, c, x, y, w, h )

Fill the specified region with the colour.

draw_image_noclip_32 ( surfid, imageid, x, y )

Like draw_image_noclip(), but only for solid images, and only images whose sizes are multiples of 4. Renders much faster.

Map Functions

map_get_tile ( tx, ty )

Takes a tile coordinate x and y (not in pixels!) and returns the tile-ID of the tile there. If you pick coords off the map, the behaviour is not defined. The tile-ID is actually the one character identifier of the tile. (Version 046 and later.)

map_set_tile ( tx, ty, tile-ID )

Changes the tile in the map to the specified tile-ID. If its a bad tile-ID or coordinate off the map, the behaviour is undefined (ie: not good ;). The tile-ID is actually the one character identifer of the tile from the config. (Version 046 and later)

Gotchas

In no particular order..

  • Comment type (as of version 046)
  •         script myscript # my script
            // my script
            script end
    
            Notice the commenting; zot-config uses # for comments (it always
    has); zotscript uses the C-like // to begin a comment. Why are they
    different? Because I'm an idiot. I'll have to add // to zot-config so its
    consistent.
    
            For now, don't put // comment on the "script" begin/end lines,
    since they're part of zot-config and thus need #; but *within* the script
    itself, you use // for comments.
    	
  • Always have a main() in there
  •         When Zot loads a script, it calls the main() function *once*; if
    it runs, then Zot assumes the script is halfway working and will keep
    it; if iot cannot run main(), it'll assume something is wrong and likely
    ignore the script, as well as produce a list of compile errors and
    warnings.
    
            main() doesn't have to do anything..
    
            main() {
                    return ( 0 );
            }
    
            Or even..
    
            main(){}
    
            But it should be present. You can also use it for 1-time variable
    setup.
    	
  • 'public' versus 'private'
  • If you want to put a mobAI or playerAI in a script, then it
    must begin with "public", since thats the magic word that tells the engine
    that Zot can call it (versus a private function only your script can
    call).
    
            public playerAI () {
                    // do stuff
            }
    
            myfunc() {
                    // do stuff
            }
    
            With these two, Zot can call playerAI, but it cannot call
    myfunc; however, playerAI *can* call myfunc.
    
            This is for several reasons..
            o) It keeps things faster, since the Zot engine only knows about
    the public functions, so it doesn't have to concern itself with hidden
    ones
            o) It means you can make a script and you control which functions
    may be called from the outside. playerAI is obviously meant to be called
    from outside, but myfunc() may be only useful to playerAI, so doon't make
    it public.
            o) You can have one script call another, or a Zot Trigger->Action
    call a script; these can call only public functions
    	
  • Arguments to functions
  •         o) Watch your argument types; most functions take an ID, such as a
    mob-ID or a sprite-ID or audio-ID.. but some take a string.
    
            ie: You check the zot function reference for post_message() ansd
    see that it takes..
    
            post_message ( string[], number );
    
            The "[]" means string.
    
            So you call it like: post_message ( "hello", 3 );
    
            If you call it with.. post_message ( 10, 3 ) then it will fail to
    compile.
    	
  • Getting your script invoked
  • 	Each script is invoked once, always, when loaded.. the "main()"
    	function is called. This is how the engine knows the script is
    	working (see above.)
    
    	However, if you want your mmobAI or playerAI to be called, you'll
    	have to attach the script to a mob...
    
    	ai	mob_script	myscript
    
    	This line in a sprite definition says to use mob_script built-in
    	AI for the mob, and mob_script only knows how to call a script
    	you specify, so you use that to bridge from the sprite definition
    	over to a script definition.
    
    	A postRender function is simiolar.. it only gets invoked if your
    	tilemap wants it to, so you add a "script" line into your tilemap
    	to identify the script.
    
    	tilemap	mymap
    	# stuff
    	script	myscript
    	tilemap end
    
    	Remember, your 'entry point' (Zot called) functions must be
    	made 'public' (see above.)
    	
  • Variable lifespan
  • 	These rules will be second nature, but may catch you the first time..
    
    	1) Global variables live forever (between script invocations)
    	2) Mob variables live with the mob (between script invocations, but
    	   if a mob is killed, his variables go with him of course.)
            3) Zotscript variables live only as long as their enclosing block
    	   is running (once your script exits, its gone!)
    
    	This means that any time you wish to store something for later
    	use (next time a script is called, or to another script), you have
    	to stuff it into a global or mob variable.
    
    	For things like mob health, strength, speed or whatever, use a mob
    	variable so that every mob can be different; if its a value thats
    	shared among all objects, or doesn't matter.. make it a global.
    
    	So within a script use Zotscript variables:
    
    	new x;
    	for ( x = 0; x < 10; x++ ) {
    		// this will run 10 times
    	}
    
    	But if you need to store a value for later, stuff it away..
    
    	global_set ( "variable-name", x );
    
    	Then later, you can get it back:
    
    	new x = global_get ( "variable-name" );
    	
  • Don't forget the "script end" to finish the script
  • 	A script is begun with "script name" where name is the name you're
    	assigning to it as a whole; this name you'll use later to attach the
    	script to mobs and such. You must also finish the script block with
    	a "script end" line, since Zot config blocks always begin and end.
    	The script itself must be between the script begin and script end,
    	and follows the Zotscript rules.
    	
  • Zotscript will be forgiving of some things.. not others
  •         - You can end a line with a ; like in C, but most of the time you
    don't have to.. its a good idea, but if you forget, it'll just *assume*
    one for you :)
    
            - On the other hand, if you "new myvar" to make a variable, but
    never use it, it'll bitch, since it won't let you waste memory. (Zot is
    anal asheck about memory usage, to make your gamelewt work on smaller
    platforms)
    	

Credits

Later versions of Zot have some wonderful parts of the Small language pulled in. Great stuff!

Sample Scripts

Send email to Jeff Mitchell at support@codejedi.com