BSL:Introduction: Difference between revisions

From OniGalore
Jump to navigation Jump to search
(Introduction is now explicitly aimed at the experienced coder who just wants the short story, not the long story at BSL:Manual)
(correcting info on "else if"; comments info belongs under "Syntax"; +links to sections mentioned in Manual and this page; added warning about scope bug)
Line 1: Line 1:
This page gives a brief look at BSL for those with scripting or programming experience. For those familiar with a typical procedural language like C, BSL's syntax and concepts will be very familiar, but BSL's feature set is stripped down to a degree that is simpler than even most scripting languages. For details on any aspect of the language, look at the [[BSL:Manual|Manual]] page.
This page gives a brief look at [[BSL]], Oni's scripting language, for those with scripting or programming experience. For those familiar with a typical procedural language like C, BSL's syntax and concepts will be very familiar, but BSL's feature set is stripped down to a degree that is simpler than even most scripting languages. For details on any aspect of the language, look at [[BSL:Manual]].
{{TOClimit|2}}
{{TOClimit|2}}
==Comments==
Comments are marked with the pound sign:
var int a = 0; # this global is also modified in my_cutscenes.bsl
==Files==
==Files==
When Oni loads a level, it also loads and parses all .bsl files in the folder in [[IGMD]] which contains that level's scripts (the name of the folder being specified by the level's [[ONLV]] resource). Like C, the code automatically begins running with the function called "main", regardless of which .bsl file it is found in (Oni's scripts always place it in a file called *_main.bsl).
When Oni loads a level, it also loads and parses all .bsl files in the folder in [[IGMD]] which contains that level's scripts (the name of the folder being specified by the level's [[ONLV]] resource). Like C, the code automatically begins running with the function called "main", regardless of which .bsl file it is found in (Oni's scripts always place it in a file called *_main.bsl).


Note that the optional [[IGMD/global|global]] folder is also loaded for all levels, but any function found in a .bsl file there will be stranded and only accessible by console unless you edit a function in some level's existing BSL file so that it calls your global function.
Note that the optional [[IGMD/global|global]] folder is also loaded for all levels, but any function found in a .bsl file in global/ will be stranded, only accessible by [[Developer Mode|developer console]], unless you edit a function in some level's existing BSL file so that it calls your global function.


==Syntax==
==Syntax==
===Statements===
BSL supports strong and weak syntax in some ways. Here's a typical statement:
BSL supports strong and weak syntax in some ways. Here's a typical statement:


Line 46: Line 42:
  }
  }


Notice that parentheses are always needed with "if" statements and semicolons are always needed on variable declarations. Note that using the strong syntax avoids certain weird aspects of BSL (see the Manual's "Old vs. new syntax" section for details).
Notice that parentheses are always needed with "if" statements and semicolons are always needed on variable declarations. Note that using the strong syntax avoids certain weird aspects of BSL (see the Manual's [[BSL:Manual#Old vs. new syntax|Old vs. new syntax]] section for details).
 
===Comments===
Comments are marked with the pound sign:
 
var int a = 0; # this global is also modified in my_cutscenes.bsl


==Reserved words==
==Reserved words==
Line 61: Line 62:


===Conditional===
===Conditional===
You can make use of the standard if-else statement, and "if" can take multiple conditions:
BSL supports standard if/else statements, and you can use "and" and "or" to test compound conditions:


  if ((a < b) and (c > d))
  if ((a < b) and (c > d))
  {
  {
     # ...
     ...
}
else if (a < 0)
{
    ...
  }
  }
  else
  else
  {
  {
     # ...
     ...
  }
  }


There is no else-if statement.
Beware of a bug in BSL where variable assignments under an "if" statement will fire even when the "if" condition is false. See the Manual page's [[BSL:Manual#Conditional|Conditional]] section for details.


===Flow interrupt===
===Flow interrupt===
There is no "goto" statement in BSL, nor any loop controls like "continue" or "break" (since there are no proper loops!). There's a "return" keyword in BSL, but you can't use it except at the end of the function because of a bug in BSL that will fire a "return" inside of an "if" statement regardless of whether the statement evaluates to true or false. So you only use "return" to return data, not to exit early (see "Functions" below).
There is no "goto" statement in BSL, nor any loop controls like "continue" or "break" (since there are no proper loops!). There's a "return" keyword in BSL, but you can't use it except at the end of the function because of a bug in BSL that will fire a "return" inside of an "if" statement regardless of whether the statement evaluates to true or false. So you only use "return" to return data, not to exit early (see the [[#Functions|Functions]] section).


There's also a "sleep" command that pauses BSL execution; you pass it a number in ticks:
There's also a "sleep" command that pauses BSL execution; you pass it a number in ticks:
Line 82: Line 87:


===Loop===
===Loop===
There's no loop keyword like "for" or "while" in BSL, but you can kind of get a loop using one of two methods. First, you can call a function recursively, but BSL has a short stack, so don't expect to get more than four levels deep. If you just want a loop and not recursion, then you can avoid recursion by sleeping for a tick or so and then forking the recursive call. See [[BSL:Snippets]] for an example that also makes up for the missing multiply operator in BSL.
There's no loop keyword like "for" or "while" in BSL, but you can kind of get a loop using one of two methods. First, you can call a function recursively, but BSL has a short stack, so don't expect to get more than four levels deep. If you just want a loop and not recursion, then you can avoid recursion and the related stack limitation by "sleep"ing for a tick or more, and then "fork"ing the call that would otherwise be recursive. See [[BSL:Snippets]] for an example that also makes up for the missing multiply operator in BSL.


Second, you could use schedule-repeat-every:
Second, you could use schedule-repeat-every:
Line 88: Line 93:
  schedule some_function() repeat 50 every 20;
  schedule some_function() repeat 50 every 20;


Just be aware that the BSL will continue executing without waiting for this loop to stop.
Just be aware that the BSL will continue executing without waiting for this loop to finish.


===Multi-threading===
===Multi-threading===
BSL doesn't have robust multi-threading, but you can sort of hack your own solution using "fork" or "schedule". Please see the Manual's section called "Concurrency" for examples.
BSL doesn't have robust multi-threading, but you can sort of hack your own solution using "fork" or "schedule". Please see the Manual's [[BSL:Manual#Concurrency|Concurrency]] section for examples.


==Operators==
==Operators==
Line 104: Line 109:
  and or !
  and or !


But you'll note that there is no operator for multiplying or dividing. See the [[BSL:Snippets]] page for a cheap hack for multiplication.
But you'll note that there is no operator for multiplying or dividing. You'll need to create your own loop with addition and subtraction to perform that kind of math.


==Data types==
==Data types==
Line 112: Line 117:
  var int a = 1;
  var int a = 1;


The "int" type is signed 32-bit. See the Manual's "Data types" section to learn about various limitations with math between types in BSL.
The "int" type is signed 32-bit. See the Manual's [[BSL:Manual#Data types|Data types]] section to learn about various limitations with math between types in BSL.


==Functions==
==Functions==
Line 121: Line 126:
  {
  {
     ...
     ...
     return count;
     return(count);
  }
  }


Once again, please see the Manual's "Functions" section to learn about concurrent and recursive calling.
Once again, please see the Manual's [[BSL:Manual#Functions|Functions]] section to learn about concurrent and recursive calling.


==Variables==
==Variables==
Line 135: Line 140:
  var int y;
  var int y;


In the second case, "y" is set automatically initialized to zero.
In the second case, "y" is automatically initialized to zero.


Variables can have global scope, if declared outside of a function.
Variables can have global scope, if declared outside of a function.


==Built-in functions and variables==
==Built-in functions and variables==
Like any game, Oni provides access to a number of hardcoded functions and global variables that can be used to write level scripts. They are listed [[BSL:Reference|here]], and grouped by common task in the [[:Category:Scripting tasks|Scripting tasks]] category.
Like any game, Oni provides access to a number of hardcoded functions and global variables that can be used to write level scripts. They are listed on [[BSL:Reference]], and grouped by common task in the [[:Category:Scripting tasks|Scripting tasks]] category.


[[Category:BSL docs]]
[[Category:BSL docs]]

Revision as of 23:23, 6 December 2015

This page gives a brief look at BSL, Oni's scripting language, for those with scripting or programming experience. For those familiar with a typical procedural language like C, BSL's syntax and concepts will be very familiar, but BSL's feature set is stripped down to a degree that is simpler than even most scripting languages. For details on any aspect of the language, look at BSL:Manual.

Files

When Oni loads a level, it also loads and parses all .bsl files in the folder in IGMD which contains that level's scripts (the name of the folder being specified by the level's ONLV resource). Like C, the code automatically begins running with the function called "main", regardless of which .bsl file it is found in (Oni's scripts always place it in a file called *_main.bsl).

Note that the optional global folder is also loaded for all levels, but any function found in a .bsl file in global/ will be stranded, only accessible by developer console, unless you edit a function in some level's existing BSL file so that it calls your global function.

Syntax

Statements

BSL supports strong and weak syntax in some ways. Here's a typical statement:

dmsg("Hello");

You can omit the semicolon, parentheses, and also the quotes if your string doesn't have any spaces in it:

dmsg Hello

Similarly, here's the formal syntax for a snippet of code:

func void some_function(void)
{
   var int a;
   a = 4;
   sleep(60);
   if (a eq 4)
   {
      dprint("Hello");
   }
}

The same code would look like this in the weak syntax:

func void some_function(void)
{
   var int a;
   a = 4
   sleep 60
   if (a eq 4)
   {
      dprint "Hello"
   }
}

Notice that parentheses are always needed with "if" statements and semicolons are always needed on variable declarations. Note that using the strong syntax avoids certain weird aspects of BSL (see the Manual's Old vs. new syntax section for details).

Comments

Comments are marked with the pound sign:

var int a = 0; # this global is also modified in my_cutscenes.bsl

Reserved words

Declaration

You always need to use "var" when declaring a variable and "func" when defining a function:

var int a = 0;
func int get_enemy_count(void)

Functions do not need to be defined or declared before they can be called, unlike in C.

Type specification

BSL does not support weak typing. You need to specify your types when making declarations, as seen in the above examples. You can choose from "bool", "int", "float" (rarely useful because of BSL's limited math operations), and "string". As with C, you use "void" to mean "no type" when defining functions.

Conditional

BSL supports standard if/else statements, and you can use "and" and "or" to test compound conditions:

if ((a < b) and (c > d))
{
   ...
}
else if (a < 0)
{
   ...
}
else
{
   ...
}

Beware of a bug in BSL where variable assignments under an "if" statement will fire even when the "if" condition is false. See the Manual page's Conditional section for details.

Flow interrupt

There is no "goto" statement in BSL, nor any loop controls like "continue" or "break" (since there are no proper loops!). There's a "return" keyword in BSL, but you can't use it except at the end of the function because of a bug in BSL that will fire a "return" inside of an "if" statement regardless of whether the statement evaluates to true or false. So you only use "return" to return data, not to exit early (see the Functions section).

There's also a "sleep" command that pauses BSL execution; you pass it a number in ticks:

sleep(60); # wait for one second

Loop

There's no loop keyword like "for" or "while" in BSL, but you can kind of get a loop using one of two methods. First, you can call a function recursively, but BSL has a short stack, so don't expect to get more than four levels deep. If you just want a loop and not recursion, then you can avoid recursion and the related stack limitation by "sleep"ing for a tick or more, and then "fork"ing the call that would otherwise be recursive. See BSL:Snippets for an example that also makes up for the missing multiply operator in BSL.

Second, you could use schedule-repeat-every:

schedule some_function() repeat 50 every 20;

Just be aware that the BSL will continue executing without waiting for this loop to finish.

Multi-threading

BSL doesn't have robust multi-threading, but you can sort of hack your own solution using "fork" or "schedule". Please see the Manual's Concurrency section for examples.

Operators

Like some other languages, BSL differentiates between checking for equivalency ("eq") and setting equivalency ("="):

if (counter eq 3) ...
i = 4;

BSL's operators are pretty standard stuff:

+ -
eq ne < > <= >=
and or !

But you'll note that there is no operator for multiplying or dividing. You'll need to create your own loop with addition and subtraction to perform that kind of math.

Data types

You can choose from "void" (when defining a function), "bool", "int", "float", and "string":

func void something(void)
var int a = 1;

The "int" type is signed 32-bit. See the Manual's Data types section to learn about various limitations with math between types in BSL.

Functions

As mentioned above, functions do not need to be declared or defined before they are called. Defining and calling a function looks exactly like C, except for the "func" keyword:

a = get_enemy_count(false);
func int get_enemy_count(bool count_dead) { ... return(count); }

Once again, please see the Manual's Functions section to learn about concurrent and recursive calling.

Variables

As usual, variables can be explicitly initialized:

var int y = 9;

or not:

var int y;

In the second case, "y" is automatically initialized to zero.

Variables can have global scope, if declared outside of a function.

Built-in functions and variables

Like any game, Oni provides access to a number of hardcoded functions and global variables that can be used to write level scripts. They are listed on BSL:Reference, and grouped by common task in the Scripting tasks category.