Jump to content

BSL:Manual: Difference between revisions

996 bytes removed ,  26 November 2017
→‎if: the previous fix of using a setter function was not only unneeded, but bare bool references do not work in Windows; recommending global variable instead
(improving instructions on function calling; correcting "some_function" to "prepare_fight")
(→‎if: the previous fix of using a setter function was not only unneeded, but bare bool references do not work in Windows; recommending global variable instead)
Line 169: Line 169:
That indentation on "spawn_considered" is misleading; when glancing at this code, you might expect that "spawn_considered" only is changed if "a" is greater than zero. It could be the script's writer really did want that line to be subject to the "if" statement, but he forgot to add braces. Always using braces around an "if" statement's body, even when it's one line long, will prevent that mistake.
That indentation on "spawn_considered" is misleading; when glancing at this code, you might expect that "spawn_considered" only is changed if "a" is greater than zero. It could be the script's writer really did want that line to be subject to the "if" statement, but he forgot to add braces. Always using braces around an "if" statement's body, even when it's one line long, will prevent that mistake.


Unfortunately, even if the programmer added braces around the two lines above, they would not run as intended. That's because, even ''with'' braces, BSL does not always respect scope for blocks of code under "if" statements; for instance, a "return" statement will fire even when the surrounding "if" condition is false (see [[#Flow interrupt|Flow interrupt]] for an example). An even more alarming example of bad scoping is this:
Unfortunately, even ''with'' braces, BSL does not always respect scope for blocks of code under "if" statements; for instance, a "return" statement will fire even when the surrounding "if" condition is false (see [[#Flow interrupt|Flow interrupt]] for an example). An even more alarming example of bad scoping is this:


  func void broken_if(void)
  func void broken_if(void)
Line 180: Line 180:
       one_equals_two = true; # ...this will still run
       one_equals_two = true; # ...this will still run
   
   
     if (one_equals_two)
     if (one_equals_two eq true)
       dprint("Uh-oh.");
       dprint("Uh-oh.");
     else
     else
Line 186: Line 186:
  }
  }


Bungie West was aware of this bug, and would work around it in Oni's level scripting by making a global variable and then calling a function to modify that variable. This works because function calls will not fire out of scope:
Bungie West was aware of this bug, and avoided it by never setting variables under "if" statements. However, you can safely do so as long as you use a global variable. For some reason, assigning a global variable under an "if" will not fire out of scope:


  var bool one_equals_two;
  var bool one_equals_two = false;
   
   
  func void fixed_if(void)
  func void fixed_if(void)
Line 194: Line 194:
     var int one = 1;
     var int one = 1;
     var int two = 2;
     var int two = 2;
    set_oet(false);
   
   
     if (one eq two)
     if (one eq two)
       set_oet(true);
       one_equals_two = true;
   
   
     if (one_equals_two)
     if (one_equals_two eq true)
      dprint("Uh-oh.");
    else
      dprint("Phew.");
}
func void set_oet(bool input)
{
    one_equals_two = input;
}
 
Another workaround to this bug is too avoid local variables and boolean variables (as both seem to be buggy by default), so instead of using local variables you should use global variables and instead of boolean variables you should use int variables. The int variables can act as boolean values, you can use 1 to "true and 0 to "false".
 
Here's the code above working without the conditions bug, using the workaround with global variables and int variable acting as boolean:
 
var int one = 1;
var int two = 2;
var int one_equals_two = 0;
func void fixed_if(void)
{
   
    if (one eq two) # this condition will evaluate to false, but...
      one_equals_two = 1; # ...now this DOES'T run! Yeahhh!
    if (one_equals_two eq 1)
       dprint("Uh-oh.");
       dprint("Uh-oh.");
     else
     else
Line 237: Line 211:
  }
  }


If you want to express the opposite of some condition, you can use the "!" operator (pronounced "not", and also unused by Bungie West). The following two statements have the same meaning:
Another unused feature of BSL is that you can express the opposite of some condition by using the "!" operator (pronounced "not"). The following two statements have the same meaning:
 
  if (!one_equals_two)
  if (!(one_equals_two eq true))
  if (one_equals_two eq false)
  if (one_equals_two eq false)
There's no functional need for the "!"; it just saves space.


====else====
====else====