Besiege Wiki
Advertisement
Besiege Wiki

Besiege's Level Logic allows writing to variables with one event. However, it does not allow directly reading from variables for anything other than comparisons in a single event.

The SetGet logical system (designed by Nice Name) provides one-event functionality for reading variables for transformations, calculations, and more.

Reading and Writing[]

Writing to a variable is easy; only one "Modify Variable" event is necessary.

To read from a variable, however, the only way to do so is by repeatedly decreasing the variable by 1 and performing an action until the variable reaches 0; this is a loop (and all programming languages have them in some form). In this way, a number of actions will be performed equal to the variable's value.

   On Variable “i > 0”
       (Place your logic here)
       Modify Variable “i - 1”

This operation is destructive; the value of the variable will be lost in reading it.

To recover the value, the loop will increase another variable (CopyA) in the opposite direction. At the end of the loop, CopyA will contain the original value, and another loop will be run to reset the variable to the original value.

   On Variable “i > 0”
       (Place your logic here)
           Deactivate
               Variable “CopyA + 1”
           Activate 
       Variable “i - 1”

The "Deactivate" and "Activate" events prevent event triggers checking CopyA from triggering while the loop is running.

Applications[]

Some examples of what the system can be used for:

  • Moving entities - a "Transform Entity" event in the loop will move the entity by a distance equal to the variable's value.
    • For example: if the "Transform Entity" event moves the entity by 1 metre in a direction, and i is 35, then the SetGet system will move it 35 metres.
  • Calculations - a "Modify Variable" event allows for duplicating and multiplying variables.
    • Setting the "Modify Variable" event to (+ 1) will set the output variable to i + 1.
    • SetGet v6 itself cannot multiply numbers, but you can build a multiplier with it. Example level: Multiplier v6

Digit System[]

It's not all fun and games, though; Besiege will not run single-frame loops for more than 37 steps (for performance or game-crashing reasons).

To overcome this, a base-38 digit system is required, and it should automatically carry over to the next digit group. We will call the first digit group “DG1" (Digit Group #1).

In order to not trigger the read system while writing, the object is deactivated - no event triggers checking DG1 will be triggered, which means that the carry system will not work. A second variable (SG1) solely for this purpose is required to make it work, which is set equal to DG1:

   On Variable “SG1 > 37”
           Deactivate
               Variable “DG2 + 1”
               Variable “DG1 - 37”
           Activate
       Variable “SG2 + 1”
       Variable “SG1 - 37”

Once SG1 exceeds 37, DG1 will carry over to DG2. This allows the carry system to work without triggering events checking DG1.

Due to needing digit groups, the system cannot handle infinite values; it does have limits, and it will break when those are exceeded (with two digit groups, the limit is 37 x 38 (1406)).

To handle this, the input must be clamped. This is achieved by tracking the input with a variable "limit"; if limit reaches the assigned bounds (±1406), it will cancel input.

   On Variable “limit > 1406”
       Variable “SG - 1”

On writing, the input (SG) is fed into SG1, DG1, and DG2, triggering the carry system as necessary.

   On Variable “SG > 0”
       Variable “limit + 1”
           Deactivate
               Variable “DG1 + 1”
           Activate
       Variable “SG1 + 1”
       Variable “SG - 1”

It is possible to add more digit groups, if you know what you're doing and/or have need of it.

Usage[]

To start reading:

       Variable “DG1 + 0”

This triggers the loops checking DG1, which are all disabled during input processing.

To start writing:

       Modify Variable “SG + (-37 < i < 37)”

This starts input processing. The input must be between -37 and +37 for a single event, to avoid crashing the program.

Logic Overview[]

Bringing the above sections together, the complete program is outlined below:

SetGet v6
   On Variable “SG >0”
       Variable “limit +1”
           Deactivate
               Variable “DG1 +1”
           Activate
       Variable “SG1 +1”
       Variable “SG -1”
   
   On Variable “SG <0”
       Variable “limit -1”
           Deactivate
               Variable “DG1 -1”
           Activate
       Variable “SG1 -1”
       Variable “SG +1”

Set Section[]

Input is handled by this block.
SG is the input variable, and is processed into SG1/DG1 and SG2/DG2.
SG1 and SG2 are used by the carry system during input, to avoid interference with the read system.
DG1 and DG2 are used by the read system.
limit is used by the limit section to clamp the input to something the system can handle.

   On Variable “SG1 >37”
           Deactivate
               Variable “DG2 +1”
               Variable “DG1 -37”
           Activate
       Variable “SG2 +1”
       Variable “SG1 -37”
   
   On Variable “SG1 <-37”
           Deactivate
               Variable “DG2 -1"
               Variable “DG1 +37”
           Activate
       Variable “SG2 -1”
       Variable “SG1 +37”

Carry Section[]

Since loops can only be run 37 times, a base-38 number system is required.
Here, if SG1/DG1 exceeds 37, it will be reset and carried over to SG2/DG2.

   On Variable “limit >1406”
       Variable “SG -1”
   
   On Variable “limit <-1406”
       Variable “SG +1”

Limit Section[]

This clamps the input value to something the system can handle.
This SetGet system has two digit groups, with a maximum value of ±1407 (38 x 37). If you add more digit groups, changing this limit is necessary.

   On Variable “DG1 > 0”
       (Add logic here: One action)
           Deactivate
               Variable “dg1 + 1”
           Activate
       Variable “DG1 - 1”
   
   On Variable “DG1 < 0”
       (Add logic here: One action)
           Deactivate
               Variable “dg1 - 1”
           Activate
       Variable “DG1 + 1”
   
   On Variable “DG1 = 0”
       Variable “DG2 + 0”
   
   On Variable “DG2 > 0”
       (Add logic here: 37 actions)
           Deactivate
               Variable “dg2 + 1”
           Activate
       Variable “DG2 - 1”
   
   On Variable “DG2 < 0"
       (Add logic here: 37 actions)
           Deactivate
               Variable “dg2 - 1”
           Activate
       Variable “DG2 + 1”
   
   On Variable “DG2 = 0”
       Variable “dg1 + 0”

Get Section[]

This section runs the read loops.
DG1 represents the first digit of the base-38 value, DG2 represents the second digit, and so on.
Therefore, the logic in the DG1 loops should reflect one action, and the logic in the DG2 loops should reflect 37 actions, and so on.

The lowercase dg1 and dg2 store the original values of DG1 and DG2, as the read operation is destructive.

   On Variable “dg1 >0”
           Deactivate
               Variable “DG1 +1”
           Activate
       Variable “dg1 -1”
   
   On Variable “dg1 <0”
           Deactivate
               Variable “DG1 -1”
           Activate
       Variable “dg1 +1”
   
   On Variable “dg1 =0”
       Variable “dg2 +0”
   
   On Variable “dg2 >0”
           Deactivate
               Variable “DG2 +1”
           Activate
       Variable “dg2 -1”
   
   On Variable “dg2 <0”
           Deactivate
               Variable “DG2 -1”
           Activate
       Variable “dg2 +1”
   
   On Variable “dg2 =0”
       (End logic; add other events as necessary to connect other systems)

Reset Section[]

This resets DG1/DG2 after the read loop has completed.
This section is effectively the previous section in reverse and without read actions.

References[]

Steam Workshop :: SetGet v6
Steam Guide :: SetGet v6
SetGet v6 Logic Diagram

Advertisement