This is a documentation for Board Game Arena: play board games online !

SandboxScripts: Difference between revisions

From Board Game Arena
Jump to navigation Jump to search
Line 241: Line 241:
== Trigger most common game actions ==
== Trigger most common game actions ==


===moveTo($id, $target, $path=array() )===
=== moveTo( $id, $target, $path=array() ) ===


Move element to specified target id (eventually following path defined by an array of other element ids)
Move element to specified target id (eventually following path defined by an array of other element ids)

Revision as of 14:55, 17 May 2018

This is the reference of functions you can call from your Sandbox scripts.

Javascript

BGA Sandbox scripts are written in Javascript.

Using Javascript, you can write scripts to automate moves for your Sandbox games & provide rules reinforcement.

Important : in the opposite of the most common usage of Javascript, Sandbox scripts are executed on server side.

BGA API

To interact with your BGA Sandbox game, we provide you an API.

With this API, you can get properties values of game elements from the current game situation, modify them and/or trigger the game actions (ex : move this element here, flip this card, and so on).

Quick start

Hello World Script

From Sandbox editor "interface view" tab, select an element, and access to its property (top right icon).

Go to "Scripts (advanced)" section.

In front of "When this element is clicked", enter "onMyClick".

Close the window. Go to "script view" tab.

Enter the following :

function onMyClick( element_id )
{
   bga.log("Hello world! You just clicked on element " + element_id + ". Congrats!");
}

Save & publish your project, starts a test session, click on the previous element : your message appears in the log on the right!

Top useful tips

  • You don't have to save&publish from the Sandbox editor for each modification of your script : each time you save your script (control+S), the script used for all test sessions is updated. Note that the production version on BGA is of course NOT updated until you explicitly save&publish again your project.
  • Alternatively to bga.log(), you can use bga.exit( "my message" ) to debug your script. With bga.exit, the script execution immediately stops and all previous game changes are cancelled, so this is very practical to try and retry an action until your script is fine.
  • We advise you to develop first a full playable version of the game without the scripts, and THEN to script it.
  • On Board Game Arena, players have come to expect fully implemented games with all rules enforced. So even if it's technically possible not to script the full game and to implement the game only partially, in most cases we'll publish only fully scripted games :)

Functions you can use in your Sandbox scripts

Debugging functions

bga.trace( txt / obj )

Write something immediately in the BGA log (on the right of the screen).

This is the most practical way to debug your script :)

Important : bga.trace is for debugging purpose only and won't be displayed on production.

Note : you can also pass an object in parameter. This will dump the content of this object in the log.

Note : in the opposite of bga.log, bga.trace is NOT cancelled if the game action failed (after a call to bga.cancel or bga.error). This makes bga.trace very practical to debug a game action that failed, and for this reason you should probably NEVER use bga.log for debugging purpose.


 // Example : write "Hello world" in the log
 bga.trace( "Hello world" );
 // Example : dump an associative array in the log
 bga.trace( { mykey: 'myvalue', another_key: 'another_value' } );

bga.exit( txt / obj )

Stop the script immediately, display the "txt" messages and cancel (ie : rollback) on every previous API call except bga.trace :

ALL previous BGA api call are canceled and there will be no visible changes on the interface (ex : no moves, no visible property changes, ...). Only "bga.trace" API commands are kept so you can debug.

bga.exit is very practical when you want to repeat a game action again and again to debug it : with a call to bga.exit at the end of your script, you make sure that your game situation will be kept unchanged after each test.

 // Example :
 bga.exit( "My script is stopped by this call" );
 // Example with dumping a javascript variable
 bga.exit( my_variable_to_dump );

Cancelling a game action

bga.cancel( txt )

This is the function to use when a player is doing something against game rules.

The text message in parameter will be displayed to this player as a "red message", so he/she can understand the rule.

All previous BGA api call are cancelled, and there will be no visible changes on the interface.

  // Example :
  bga.cancel( _("You cannot move this piece here") );

Note : most of the time, you should wrap your text inside a _() translation marker to make this string translatable.

bga.error( text )

This is the function to use when some unexpected error happens in your script.

The text message will be displayed to user, with mention "Unexpected error". The player will be incited to fill a bug report. The purpose of the message is to help you to identify the bug.

All previous BGA api call are cancelled, and there will be no visible changes on the interface.

  // Example :
  if( card_picked === null )
  {
      bga.error( "Cannot find a card to pick !" );
  }

Note : you should NEVER wrap text inside bga.error with _() translation marker, because unexpected error should not be translate (so you can eventually recognize them when reported by players in bug report).

Game log (history)

bga.log( txt, (optional) args )

Write something in the BGA log on the right.

 // Example : simple log
 bga.log( _("A new round starts") );

You may add arguments to your log, like this :

 // Example: log with argument to display a card name.
 //          In this example, variable "event_name" is specified afterwards.
 //          Note that using this, game translators only have to translate one "Event XXX is triggered" string for all possible events.
 bga.log( _("Event ${event_name} is triggered"), {  event_name: _( "Armageddon" ) } ) );

Note that argument "player_name" is ALWAYS pre-set with the name of the current player, so you can use it immediately.

 // Example :
 bga.log( _("${player_name} draw a card from the deck") );

bga.speechBubble( target, text, (optional) args, (optional) delay, (optional) duration, (optional) size )

Display a "speech bubble", attached to the specified target, containing the specified text.

You can use "args" to customize text exactly like with bga.log.

delay : milliseconds to wait before displaying the speech bubble (default : 0). duration : how long to show the speech bubble in milliseconds (default : 3000). size : size of the text in percent (default: 100)

 // Example :
 bga.speechBubble( _("I play ${nbr} cards"), { nbr : 4 }, 0 );
 bga.speechBubble( _("Good for you!"), { }, 2000 );

bga.displayScoring( target, color, score )

Display an animated temporary "score number", attached to the specified target.

"color" should be the color of the player who is scoring for that target.

Get / search game elements and their properties

bga.getElement( selector, (optional) fields )

Allow you to retrieve informations about one game element specified using "selector" argument.

Return null if no element is found.

Note : getElement throw an error if several elements matches the selector. If you want to retrieve several elements, you should use "getElements" instead of "getElement".

The following examples are showing all the possible use of bga.getElement :

 // Basic example :
 
 // Retrieve the ID of a game element using its name ("Deck")
 var deck_id = bga.getElement( { name: "Deck" } );
 // Return : 1234  
 // Examples using "field" parameter :
 
 // Retrieve a specific property from a game element using its name ("Deck")
 var deck_id = bga.getElement( { name: "Deck" }, 'x' );
 // Return : 20
 
 // Retrieve several properties from the previous element
 var deck_properties = bga.getElement( { name: "Deck" }, ['name','id','parent', 'x','y','canShuffle'] );
 // Return : { name:'Deck', id:1234, parent:4321, x: 20, y:50, canShuffle: true }
 
 // Note : as you can see, getElement returns:
 //        _ the element ID by default, or
 //        _ a single value if you request a single field, or
 //        _ an object if you request several fields
 // Examples using different "selector" paramter
 
 // Retrieve an element name from its id
 var deck_name = bga.getElement( { id: 1234 }, ['name'] );
 // Return : "Deck"
 // Retrieve the last child element of another element
 // Here, we are requesting for elements who has element with ID=1234 (Deck) as their parent
 // Note the use of "limit:1" which allows us to retrieve only 1 element.
 var first_card_on_deck_id = bga.getElement( { parent: 1234, limit:1 } );
 //


bga.getElements( selector, (optional) fields )

Returns an object holding the properties of the elements matching the selector.

 // Basic example: unselect all selected elements
 bga.removeStyle( bga.getElements( {tag: 'sbstyle_selected'}), 'selected' );

bga.getElementsArray( selector, (optional) fields )

Returns an array of all elements matching the selector, holding the required properties.

 // Basic example: get id of selected element
 var selected_tokens = bga.getElementsArray( {tag: 'sbstyle_selected' } );
 var token_id = null;
 if (selected_tokens.length > 0) {
     token_id = selected_tokens[0];
 }
 return token_id;
 // Classic example: get array of elements and iterate over it
 var all_cells = bga.getElementsArray( {tag: 'CELL'}, ['id','name','tags'] );
 for (var i=0; i<all_cells.length; i++) {
    // ... process each cell ...
 }

Utility methods

bga.isOn( element_id, parent_id )

Return true if "element_id" is a descendant of "parent_id" (ie : if element_id game element has been placed on parent_id game element).

 // Example :
 if( bga.isOn( bga.getElementIfByName( 'Turn counter' ), bga.getElementIfByName( 'Turn 6' ) )
 {
    // Trigger game end
 }

Trigger most common game actions

moveTo( $id, $target, $path=array() )

Move element to specified target id (eventually following path defined by an array of other element ids)

The exact destination of element depends on target's "howToArrange" property ("How elements are arranged on it?" : spreaded/deck/...).

 // Example :
 bga.moveTo( bga.getElementIdByName( 'Turn counter' ), bga.getElementIdByName( 'Turn 3' ) );

Other functions

pause( milliseconds )

Pause the client interface during a specified number of milliseconds.

If you do not use bga.pause, all Sandbox game actions are executed immediately and synchronously.

 // Example :
 bga.log( "1" );    // Will be displayed immediately on the log
 bga.pause( 3000 ); // pause during 3 seconds
 bga.log( "2" );    // Will be displayed after the 3 second on the log
 bga.log( "3" );    // Will be displayed right after the previous one, without delay.


Tips : if you want to execute several consecutive "moveTo", you should "bga.pause" between them, otherwise your element will move directly to the final destination.