Scripting Tutorial

From Cube Wiki
Revision as of 16:59, 12 December 2014 by Admin (Talk | contribs)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Basics

Configuration

You are already writing CubeScript when you edit your autoexec.cfg.

name "my name"

This is a primitive CubeScript block. Its parts are a command and and a parameter, or an argument.

name will take one argument. It will then try to set your player's name to the value of the argument; restraints of the current engine build apply (such as the maximum length).

Ingame

When you've found out about more commands, via the documentation, even just having glanced at their names, will be helpful to you with coming up with some on-the-fly scripting.

Learn to use the console. Try out combining calls on-the-fly. One of the first CubeScript structures useful for this can be

loop I N BODY

// for example as in
loop a 3 [ entproperty (+ $a 1) +42 ]

Stuff gets saved to config.cfg, you can copy snippets of useful CubeScript to some file for later use.

After a session

Regularly paste your personal scripting -- stuff you aliased on the fly that was saved to config.cfg -- into your autoexec.cfg -- that way they'll always be up-to-date once the engine fires up!

And don't forget to be quick about moving config.cfg to something like my_config.cfg; to compare to working backups and/or salvage scores and scripting/values from it!

Keybindings

Remember: editbind will override a bind when in edit mode.

Beware of binding keys that are already bound by the default configuration -- unless you're sure you know what you're doing. Check data/defaults.cfg for this.

Aliases

You define blocks of actions by defining an alias for them.

//old style:
alias aNAME $aVALUE
//new style:
aNAME = $aVALUE

The modifier alias

if you look at the modifier demo you'll see some powerful ways to control your setup. Before you do look at it you might like to understand the way it works, from the bottom up. The details of where exactly something occurs have been omitted, as this is trivial to reconstruct.

bind MOUSE4 [ universaldelta +1 ]
bind MOUSE5 [ universaldelta -1 ]

universaldelta is now our handle on the scrollwheel of our mouse. This in turn gets bound to an internal modifier alias, you change this modifier by binding keys to certain settings, these in turn need to be defined as special aliases to be parsed.

// echo 5 or 1, depending on _RCTRL, our flag
bind "O" [ if ( = $_RCTRL 1) [ echo 5 ] [ echo 1 ] ]

// set the _RCTRL flag while key "right control" is being pressed, off when released.
bind "RCTRL" [ _RCTRL = 1; onrelease [ _RCTRL = 0 ] ]

// initialize the _RCTRL flag before ever parsing $_RCTRL
// the CubeScript block for bind "O" hasn't been parsed at this point yet...
// ...someone would need to press that key first
"_RCTRL" = [0]

This code will make your right control key be a sort of x1 / x5 switch, for the 'O'-key just a simple echo,

bind "M"  [ domodifier 128 ]

delta_game_128 = [
  echo (concat "DG_128:" (if (= $_RCTRL 1) [echo (* 5 @arg1) ] [echo (* 1 @arg1)]))
]

try pressing M and turning your wheel, now RCTRL+M and MW -- are you getting the hang of it?

Now look at the modifier demo and find out, why your x1 / x5 doesn't work in editmode and how you can quickly make it work.

Common errors

A common cause for errors is forgetting spaces around the equals sign in CubeScript's mathematical operations' style! In both variants the $aVALUE represents any valid CubeScript block. Examples:

Want to handle a script with a simple parameter toggle?

my_value = 1
bind N [ my_value = 5; onrelease [ my_value = 1 ] ]
my_script = [ if (= $my_value 1) [ echo regular ] [ echo modified ] ]
bind M [ my_script ]

Modifier demo

Want to handle a script with +X/-X input via mousewheel?

delta_game_42 = [echo we got $arg1 as param "(game)"]
delta_edit_42 = [echo we got $arg1 as param "(edit)"]
bind KP_5 = [domodifier 42]
editbind KP_5 = [domodifier 42]

Parameter demo

To clarify parameter passing -- usage of a zero value or no value at all shouldn't confuse your scripts!

param_script = [
        info = ""
        loop p 4 [
            cax = (+ $p 1)
            can = (concatword "arg" $cax)
            cav = (getalias $can)
            if (= $cav 0) [ cav = "(null)" ]
            info = (concat $info "  " (concatword $cax ":") $cav)
        ]
        // echo "1:" $arg1 "2:" $arg2 "3:" $arg3
        if (= $arg1 1) [
            echo "yes :" $info
        ] [
            echo "no :" $info
        ]
    ]

    param_script 0 1 2 3
    param_script 1
    param_script 4 3 2 1
    param_script


Triggering Action

For SP maps you can have trigger entities do scripting commands whenever the player touches the entity.

The basic concept is to create aliases like

level_trigger_123 = [ echo "You triggered #123" ]

This would be executed when the player crosses the space of any trigger-entity with first param 123.

Triggers

Sauerbraten can trigger special scripting for you, when an SP player crosses the space of one of your trigger entities. Note that triggers only work in SP mode!

Historical development associates a carrot model with triggers, but any mapmodel can be used (or none at all).

Each trigger has it's index -- entproperty 0. You may have multiple entities with the same index though.

Triggering another trigger will not always do exactly what you want ATM, development toward that angle is under way!

See this: MapTriggerTest.zip [6.7K] A map and its CFG. to learn how to implement a basic secret's counter. There is also a secret's counter in "Episode 1" and other maps contain other scripting that you might like to use. You should also check out stuff you liked in somebody else's map and in their CFG to work out how they did it. To see how to trigger doors look at the map "door_demo" included with sauerbraten.