BBE/Calc Fields
Calc fields, known internally as BBE, are formulae strings that are evaluated at run-time. It is a powerful tool that allows code functions to use custom inputs.
What does BBE stand for? Nobody knows! Some guesses are Binary Bytecode Evaluator, Binary Big Endian, and Big Bad Evaluator.
Examples
For example, this BBE string is how the Zakarum enemies calculate their healing skill percent: "15+5*lvl". This evaluates to 15 plus 5 times the skill level.
Another example, this is how Sorceress Charged Bolts calculates the amount of missiles to spawn: "min(24,ln12)". This takes the minumum value between 24 and the linear function of the skill's parameter 1 and 2 based on skill level.
Lets get crazier, this is how Barbarian Stun calculates its damage synergy: "skill('Bash'.blvl)*par8". This evaluates to the current base skill level of Bash multiplied by Stun's parameter 8.
It can get pretty nuts, like the HP % of Necromancer Clay Golem: "(100+(par1 * (lvl - 1)))*(100+skill('Golem Mastery'.ln12) + (skill('BloodGolem'.blvl)*skill('BloodGolem'.par8)))/100-100." I won't explain that one but trust that it works!
Operators
These common math operators are available in BBE formulae:
| Operator | Description |
|---|---|
| + | Addition |
| - | Subtraction Negative |
| * | Multiplication |
| / | Division |
| ^ | Power |
| ( and ) | Parenthesis |
These operators can be used as conditions:
| Operator | Description |
|---|---|
| ? and : | Ternary. Format is as follows: (condition) ? (if true) : (if false). |
| < | Less than |
| <= | Less than or equal to |
| > | Greater than |
| >= | Greater than or equal to |
| == | Equal to |
| != | Not equal to |
In BBE, 0 is false and not-0 is true. You can get creative and use * as an "and" operator and + as an "or" operator. For example, "1 * 0 * 1" is always 0, so that's effectively an "and". "1 + 0 + 1" is always 2, so that's effectively an "or".
Scopes and Identifiers
There are a few scopes of BBE functions. These scopes can have identifiers, which are text that reperesent a value. For example, "blvl" or "hpa1". A full reference of what identifiers are available to a scope can be seen in their corresponding txt file.
When writing a BBE formulae, it is important to know that file you're writing it in, as that will influence the base behavior of that formulae. For example, if I am writing a formula in skills.txt, the base scope will be a "skill" scope, meaning I can input skill identifiers without calling the "skill" function (described later).
| Scope | Identifiers | Base Behavior |
|---|---|---|
| Skill | skillcalc.txt | Accepts a constant number or a skill identifier. |
| Missile | misscalc.txt | Accepts a constant number or a missile identifier. |
| Item | No identifiers | Accepts a constant number. |
| Monster | No identifiers | Accepts a constant number. |
| Treasure Class | No identifiers | Accepts a constant number. |
Functions
There are a few functions available to BBE formulae.
Functions might have parameters, and those parameters will be separated by either a comma ',' or a period '.'. If a comma is used, the following paramter can either be a constant (ex. '5') or an identifier (ex. 'lvl'). If a period is used, the following parameter is always treated as a constant. You might be thinking, "thats weird, functions like 'skill' use a period followed by an identifier. This is because some functions have custom parameter handling that forces them to be identifiers. It is best practice to always use the syntax in the "Usage" section below.
| Function | Usage | Description | |
|---|---|---|---|
| min | min(a,b) |
Gets the minimum between two inputs. | |
| max | max(a,b) |
Gets the maximum between two inputs. | |
| rand | rand(a,b) |
Gets a random value between two inputs. | |
| skill | skill('Skill Name'.identifier) |
Gets an identifier for a skill based on the unit's level in that skill. | |
| miss | miss('Missile Name'.identifier) |
Gets an identifier for a missile. | |
| stat | stat('Stat Name'.parameter) |
Gets the stat value on the unit. Valid paramters are: "accr": The accrued value between all sources. "base": The base value. "mod": Same as "accr". The intention here might have been the modified value from the base. |
|
| sklvl | sklvl('Skill Name'.identifierToGetLevel.identifier) |
Gets an identifier for a skill at a specified level. The specified level must be an identifier of the base BBE scope. | |
| sksrc | sksrc('Skill Name'.identifier) |
Gets an identifier for a skill based on the source unit's level in that skill. The source unit is the same unit used for the "skill" function for skill, missile, item, and treasure class scope BBEs. For monster scope BBEs it is a unit that is passed in by the caller, usually the caster of a skill. | |
| cond | cond('Condition Name', parameter(optional)) |
Evaluates a condition, returning either 0 for false or 1 for true. See Conditions. |
Conditions
As mentioned earlier, one of the functions available is the Condition, or "cond", function. Conditions, like Identifiers, are strings that tie to code. Unlike Identifiers, these always return either 0 for false or 1 for true and may be called from anywhere.
The list of available conditions is as follows:
| Condition | Usage | Description | Parameters |
|---|---|---|---|
| IsType | cond('IsType', param) |
Check if a unit is a certain type. The unit checked is the main one for the scope. |
|
| IsClass | cond('IsClass', param) |
Check if a unit is a certain class. The unit checked is the main one for the scope. |
|
| Desecrated | cond('Desecrated') |
Check if a unit is a considered desecrated (aka terrorized). If the unit is a monster, check if it is desecrated. If the unit is a player, check if it is inside a desecrated level. If the main unit of the scope is a missile or item, we check its source unit instead. | |
| Difficulty | cond('Difficulty', param) |
Check if the game is set to a specific difficulty level. If the main unit of the scope is a missile or item, we check its source unit (owner) instead. |
|
| MonsterTestElite | cond('MonsterTestElite', param) |
Check if a unit is a certain monster elite type. If the main unit of the scope is a missile or item, we check its source unit instead. If the unit is a player, return false. |
|
| ItemIsType | cond('ItemIsType', param) |
Check if an item is a certain item type. The unit checked must be an item. | Item type code (ex. shie) |
| ItemIsModType | cond('ItemIsModType', param) |
Check if an item is a certain mod type. The unit checked must be an item. |
|