Skip to content
Joseph edited this page Oct 13, 2019 · 6 revisions

Please note that this wiki is for the old 'cycle' framework. This page will be updated once the 'flat' framework is further developed.

Requirements

  • An installation of scalu
  • A text or code editor you feel comfortable using
  • Enable the developer console in your options menu

The Fundamentals

It's important that new users already understand the very basics of Source scripting before moving on to more advanced topics. If you are already well versed in how scripting works, feel free to skip this section.

To execute a script, open your console (usually with the ~ key on English keyboards) and type exec [scriptname]. This will execute any script by that name in your cfg directory. Source games automatically execute a script called autoexec upon loading, so any scripts you want to run automatically at startup should be put in there. For example, if I wanted to run scalu at startup, I'd edit autoexec.cfg (or create it if it doesn't exist), put in exec scalu as a line, then save it.

There is really only one command that really matters for making arithmetic possible: the alias command. The alias command works how you think it would; alias ties a long string of commands to a shorter custom command. Say you want to practice rocket jumping in TF2. Instead of hitting the "~" key and typing

sv_cheats 1; hurtme -9999999

every time you want to practice, you might instead put

alias rj "sv_cheats 1; hurtme -9999999"

in a script. Now, you only need to type

rj

to set cheats to 1 and give yourself health. Note that commands are executed sequentially and are seperated by the ; operator.

Note that alias itself is just like any other command in Source. Therefore

alias a "alias a hurtme -100"

is a valid command. This command points a to the string "alias a hurtme -100". If you type a into the console, a will execute the string and rewrite itself to execute hurtme -100. If you type a again, it will just execute hurtme -100 again. This is key, as this reveals that aliases can rewrite themselves and other aliases.

It's impossible for this guide to list all of the quirks and conventions of scripting; look here for a more in-depth guide to basic scripting:

https://wiki.teamfortress.com/wiki/Scripting https://www.reddit.com/r/tf2scripthelp/wiki/index

Registers and State

The Source console provides no way to manipulate or store numbers, normally. However, we can manipulate and store aliases. Therefore, in order to store numbers, we create chains of self-rewriting aliases (internally called rotaries) that work to create a register, or a variable. It's actually not that important for you, the enduser, to understand how they work, except to know their size. Registers, by default, are 8 bit signed variables. Therefore, they store all numbers between -128 and 127.

Since registers are laborious to construct, a script called vbuilder.py can write them automatically, with custom names and bit sizes. However, scalu provides a few pre-generated registers by default: r1, r2, and r3.

Constants

Constants are structurally similar to registers, but lack the ability to be automatically overwritten. The first 16 integers are stored as constants in the form: c0, c1, c2, c3, ...., c9, ca, cb, cc, cd, ce, cf.

Instructions

Instructions tell the interface what to do. They come in two types: register instructions, and conditional instructions. Register instructions include add, dump, and bxor. They take between 0 and 2 arguments, and typically manipulate registers with no effect on the "outside" world. Conditional instructions (such as zero, equal, and gt) typically do not manipulate registers, and instead conditionally execute other blocks of script.

All instructions make use of ptrs (pointers) to know what arguments they're working with. These pointers "point" at the only register interface endusers should worry about, the name of the register. Using add as an example:

alias add_ptr1 r1
alias add_ptr2 r2
add

The script above will target r1 (register 1) as its first argument, r2 as its second argument, and will then add them together. Note that register instructions will only ever change the value of the first argument. For anyone familiar with x86 assembly, this resembles Intel syntax. Therefore, the r1 has been increased by r2, and r2 remains unchanged.

Conditional instructions work similarly, but have additional arguments. Using equal as an example

alias equal_ptr1 r1
alias equal_ptr2 c7
alias equal_rettrue yourfunction
alias equal_retfalse yourotherfunction

rettrue and retfalse represent branching depending on whether or not the function is true or false. If register 1 and 2 are equal, rettrue is executed. If not, retfalse is executed. This is where scalu interacts with the outside world, and where you hook in the commands and aliases you want executed.

The Cutting Edge

The sections above are all that is needed to have a solid grasp on using this interface. This section is dedicated to quirks you might encounter as you use the interface

  • Using the same argument twice (r1 and r1, or c4 and c4) will work as expected.

  • If you use vbuilder.py to create new registers, there's a few things to keep in mind. Instructions can handle any word size (you can make all your registers and constants 10 bits or 100 bits, if you so please), however, they expect constant word size; 16 bit is incompatible with 8 bit, etc.

Clone this wiki locally