Difference between revisions of "Basics of Scripting"

From X-Moto
Jump to: navigation, search
(General)
(General)
Line 202: Line 202:
 
If some action doens't work but doesn't crash either try using Game.Message("debug") to see if the script is ever even executed. In X-Moto scripts the '''script must be in an ''[http://wiki.xmoto.tuxfamily.org/index.php?title=Scripting_Dictionary#Event event]''''' otherwise the script is never executed.
 
If some action doens't work but doesn't crash either try using Game.Message("debug") to see if the script is ever even executed. In X-Moto scripts the '''script must be in an ''[http://wiki.xmoto.tuxfamily.org/index.php?title=Scripting_Dictionary#Event event]''''' otherwise the script is never executed.
  
If you get an error with '''line number''' then to find the exact line, count the script's lines '''ignoring all empty lines''', that is how you should be able to find the correct line, since the script parser removes empty lines before executing the script.
+
If you get an error with '''line number''' then to find the exact line, '''count''' the script's lines '''ignoring all empty lines''', that is how you should be able to find the correct line, since the script parser removes empty lines before executing the script.
  
 
== Err. SetDynamicBlockTranslation crashes ==
 
== Err. SetDynamicBlockTranslation crashes ==

Revision as of 10:59, 22 June 2009

Introduction

This tutorial explains how to write clean script and how to make some things. Please see the Dictionary for more information about each keywords.

Clean Script

I've seen horrible scripts. So I decided to make a style guideline here.

Indent

Indenting your script makes it much more readable. Compare the following scripts:

function lol()
if wut==1 then
if lolwut==2 then
Game.KillPlayer()
end
end
end

and

function lol()
    if wut==1 then
        if lolwut==2 then
            Game.KillPlayer()
        end
    end
end

Makes it easier to see if you forget an end for example. ;-)

Comments

You should comment your script so that someone who could be interested how this is done could understand the script, but don't comment too much because that makes the script messy.

...
if somevar==2 then -- here we see if the player plaaplaaplaa...
...

Other

You can use ";" to join lines without linechange

This is okay:

zone1={};visited1=0"

But do not connect too many lines.

Please, do not put if and then on separate lines

if somevar!=something
then
...

Instead:

if lol==1 then
...

Using the () in the if is optional:

if(lol==1)then
...

How-To Section

Here we collect how to scripts. like "How-to make an elevator?" or "How-to make a jump button?"

You can't download example levels because this wiki doesn't allow me to upload .lvl files anymore: "This file contains HTML or script code that may be erroneously be interpreted by a web browser.". I know it sucks. It's just xml with some lua.

How-to make an elevator?

What we need:

  • a dynamic block
  • the block id must be "blockele1"
  • a zone, id "zoneele1"

The Script:

zoneele1={}
function zoneele1.OnEnter() -- when we enter the zoneele it starts the elevator.
    h=10 --height (how much up we go)
    speed=2000 -- how long it takes to go there (speed depends on the h)
    wait=200 -- how long to wait before starting the elevator (200=2s)
    Game.SetDynamicBlockTranslation("blockele1",0,h,speed,wait,wait+(speed/2))
end

You can edit the variables to fit your needs. Here you can download an example level: Media:elevator.lvl

How-to make a jump key?

This is easy, it can be done purely with script.

function OnLoad()
    Game.SetKeyHook("J","Jump") -- bind the J key to the Jump function below
    return true
end
function Jump()
    Game.AddForceToPlayer(0,10000,0,10,0)
end

With that script the player can cheat and jump even when on air. We want the player only to be allowed to jump when on ground again. So we need a variable to see if the player has jumped already:

hasjumped=true --you can use 1 as well
function OnLoad()
    Game.SetKeyHook("J","Jump") -- bind the J key to the Jump function below
    return true
end
function Jump()
    if hasjumped==false then
        hasjumped=true
        Game.AddForceToPlayer(0,10000,0,10,0)
    end
end
function OnWheel2Touchs(bStatus) --rearwheel
    if bStatus==1 then -- only when touching not when leaving the ground
        hasjumped=false --we touch the ground so we must be jumped.
    end
end

Here you can download an example level: Media:jump.lvl

How-to make zoom buttons?

Zooming is somewhat easy, but it recuires some script to do, I have this old piece of script I got from Lothar's level, I've changed it to be more configurable. You can use it as it is, just remember to leave the comments about the creators of the script there :)

--original script by Lothar
--upgraded by Tuhoojabotti 18.12.2008

--settings
zoomlevel = 1 --default zoom
blockzoom = 0 --enable/disable zoom 0=enabled
zoominbutton="I" 
zoomoutbutton="O"
maxzoomout=4 --strokes
maxzoomin=0 --strokes
step=0.05 --amount of zoom per stroke

function OnLoad()
	Game.Message("Press "..zoominbutton.." to zoom in")
	Game.Message("Press "..zoomoutbutton.." to zoom out")
	Game.SetKeyHook(zoominbutton, "ZoomIn")
	Game.SetKeyHook(zoomoutbutton, "ZoomOut")
	return true
end

function ZoomIn()
	if zoomlevel==maxzoomin then
			Game.ClearMessages()
			Game.Message("Can't zoom in any further.")
	else
		if blockzoom==0 then
			Game.CameraZoom(step)
			zoomlevel = zoomlevel-1
		end
	end
end

function ZoomOut()
	if zoomlevel==maxzoomout then
		Game.ClearMessages()
		Game.Message("Can't zoom out any further.")
	else
		if blockzoom==0 then
			Game.CameraZoom(-step)
			zoomlevel = zoomlevel+1
		end
	end
end

How-to make readable signs?

You need:

  • Entities, like: sign1, sign2, sign3, ...
  • Zones, like: signz1, signz2, signz3, ...
  • a variable to hold the sign texts; SignText=""
  • and a keyhook for the Read function

Zones:

SignText="No signs here..."
signz1={}--;signz2={};signz3={};...

function OnLoad()
   Game.Message("Hello, you can read signs with 'R' key.")
   Game.SetKeyHook("R","Read")
   return true
end

function Read() --read teh sign
    Game.Message(SignText)
end

--repeat this for all zones...
function signz1.OnEnter()
    SignText="This is the Sign1 it says: plaaplaaplaplapal..."
end
function signz1.OnLeave() --this is optional
    SignText="No signs here..."
end
--end repeat block

Somewhat easier way is to use Entity.Touch() event, which doesn't have leave support, but then you can dump the zones.
Entities:

SignText="No signs here..."
sign1={}--;sign2={};sign3={};...

function OnLoad()
   Game.Message("Hello, you can read signs with 'R' key.")
   Game.SetKeyHook("R","Read")
   return true
end

function Read() --read teh sign
    Game.Message(SignText)
end

--repeat this for all entities...
function sign1.Touch()
    SignText="This is the Sign1 it says: plaaplaaplaplapal..."
end
--end repeat block

Debugging

General

Basically debugging means figuring out what makes the script behave unwanted ways or fix crashing. It is a good way to comment lines which you think makes the script crash and then start uncommenting then line by line till you find the crash spot, then try to figure out what is wrong:

  • typo (spelling error)
  • invalid parameter in function call
  • block not existing
  • block not dynamic
  • dynamic block in wrong layer

If some action doens't work but doesn't crash either try using Game.Message("debug") to see if the script is ever even executed. In X-Moto scripts the script must be in an event otherwise the script is never executed.

If you get an error with line number then to find the exact line, count the script's lines ignoring all empty lines, that is how you should be able to find the correct line, since the script parser removes empty lines before executing the script.

Err. SetDynamicBlockTranslation crashes

Check that blocks all blocks are dynamic and in the main layer. Also look for typos in script. If the level has 2 or more main layers then the block must be in the original main layer.

Err. Zone.OnEnter fails

Is the zone defined at the start of the level like: Zone={}? X-Moto don't know to call the OnEnter function if you haven't defined it.