SetGet

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:

```
   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”

```
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.

```
   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”

```
Since loops can only be run 37 times, a base-38 number system is required.

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

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

```
This clamps the input value to something the system can handle.

```
   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”

```
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.

```
   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)*

```
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