Difference between revisions of "Expressions"
(→Functions: IsMatchText function, and some particle vars) |
(→Variables: Added DLC_INSTALLED_ARMORSANDSKINS, DLC_INSTALLED_OMENROAD, and MOD_ACTIVE.modId lines) |
||
Line 206: | Line 206: | ||
|- | |- | ||
| NOT_FAMILY_WITH || NOT_FAMILY_WITH.hook || 0 if the current target is family with the given target, 1 otherwise. || NOT_FAMILY_WITH.hook is equivalent to (1 - FAMILY_WITH.hook) | | NOT_FAMILY_WITH || NOT_FAMILY_WITH.hook || 0 if the current target is family with the given target, 1 otherwise. || NOT_FAMILY_WITH.hook is equivalent to (1 - FAMILY_WITH.hook) | ||
|- | |||
|DLC_INSTALLED_ARMORSANDSKINS | |||
| | |||
|1 if the player has the Armors and Skins DLC enabled, 0 otherwise | |||
| | |||
|- | |||
|DLC_INSTALLED_OMENROAD | |||
| | |||
|1 if the player has the Omenroad DLC enabled, 0 otherwise | |||
| | |||
|- | |||
|MOD_ACTIVE.modId | |||
|MOD_ACTIVE.myCoolMod | |||
|1 if the mod with the given id is active | |||
|Useful if your mod has dependencies or differences based on other mods | |||
|} | |} | ||
Latest revision as of 09:29, 5 September 2024
Most places that require you to enter a value (when making Effects, most commonly) do so through the use of Expressions. These can be made up of regular numbers, addition, subtraction, multiplication, and division, in addition to the functions and variables listed below.
Functions
function | example | returns | explanation/usage |
---|---|---|---|
abs(x) | abs(-5) | 5 | The absolute value of the input value |
atan2(x, y) | toDegrees(atan2(1, 1)) | 45 | atan2 of the given x, y position. (Converts a vector into an angle in radians) |
boolean(x) | boolean(5) | 1 | Returns 0 if the given expression evaluates to 0, 1 otherwise |
ceil(x) | ceil(2.7) | 3 | Rounds up |
floor(x) | floor(2.7) | 2 | Rounds down |
round(x) | round(2.7) | 3 | Rounds to nearest |
max(x, y, z...) | max(2, 3, 8, 6) | 8 | Returns the max of any number of parameters |
min(x, y, z...) | min(2, 3, 8, 6) | 2 | Returns the min of any number of parameters |
pow(x, e) | pow(2, 3) | 8 | Returns the first parameter to the power of the second parameter |
sqrt(x) | sqrt(16) | 4 | Returns the square root |
sin(x) | sin(3.14/2) | 1 | |
cos(x) | cos(3.14/2) | 0 | |
sign(x) | sign(5) | 1 | Returns the signum; zero if the argument is zero, 1 if the argument is greater than zero, -1 if the argument is less than zero. |
smoothstep(x) | smoothstep(0.75) | 0.84 | Given a number between 0 and 1, returns that number put into the smoothstep function (x*x*(3-2*x)) |
smootherstep(x) | smootherstep(0.75) | 0.89 | Given a number between 0 and 1, returns that number put into the smootherstep function (x*x*x*(10+x*(6*x-15))) |
isMatch(x, y, z...) | isMatch(5+2, 7) | 1 | Returns 1 if all given parameters equal the same value, 0 otherwise. |
isMatchText(a, b...) | isMatchText(_PARAM_, value) | 1 | Returns 1 if all given parameters equal the same text string, 0 otherwise. (Useful for checking a parameter against another string) |
length(x, y, [z]) | length(5, 5) | 7.071 | Returns the length (magnitude) of a given Vector2 or Vector3 |
lerp(a, b, t) | lerp(0, 100, 0.8) | 80 | Linearly interpolates between a and b by t (where t is clamped to 0 - 1), where t=0 returns a, t=1 returns b, and t=0.5 returns a value 50% of the way from a to b, etc. |
greaterThan(a, b) | greaterThan(5, 7) | 0 | Returns 1 if a is greater than b, 0 otherwise |
lessThan(a, b) | lessThan(5, 7) | 1 | Returns 1 if a is less than b, 0 otherwise |
between(x, min, max) | between(5+1, 2, 7) | 1 | Returns 1 if x is between min and max (or is equal to min or max), 0 otherwise |
if(x, pass, fail) | if(1, 25, 30) | 25 | Returns pass value if x is non-zero, returns fail value otherwise (if fail value is omitted, will return 0 instead) |
toDegrees(angle) | toDegrees(3.14/2) | 89.95 | Converts angle in radians to degrees |
toRadians(angle) | toRadians(90) | 1.57 (Approx. Pi/2) | Converts angle in degrees to radians |
Variables
variable | example | returns | explanation/usage |
---|---|---|---|
EVENT_ROLL | A number between 1 and 100 | Used in choice target tests, in the Chose Outcome, generally seen together with roll_one, roll_two, roll_three, etc. expressions | |
IS_FLANKING | 1 if flanking, 0 otherwise | If this event contains attack info (e.g. a DAMAGE_ROLL, DAMAGE_ROLL_INCOMING, DAMAGE_ROLL_AFTER_ARMOR), returns whether or not the attack is flanking. | |
THIS_ASPECT | The integer value of this event's parent aspect | If this event has a parent aspect, returns the value of that aspect. | |
TOWN_POPULATION_LIMIT | The population limit for all towns (200) | ||
RECRUIT_COST_ADJUSTMENT | -1 if company size < 3, 0 if >= 3, 1 if >= 6, 2 if >= 8, 3 if >= 10 | Adjustment for recruit cost based on company size. This is used to make recruits cheaper if you have fewer of them, and more expensive if you have more. | |
RECRUIT_ENCOUNTER_SCORE_OFFSET | If chapter 1, returns 0.5 if company size=3, 2 if size=2, 4 if size=1. If chapter > 1, returns 0.5 if company size=4, 2 if size=3, 4 if size=2, 9 if size=1. Returns 0 otherwise. | An offset for recruit encounters that makes it so the encounter is more likely to happen if you have a smaller company. This is used in events that give you recruits. | |
isDefender | isDefender.hero | 1 if the given role is the current defender of an AttackRoll Outcome, 0 otherwise | Generally used if you want different damage for one enemy in an attack than for others. (See how fireleash works, dealing half damage to defenders that aren't on the target tile) |
RESOURCE | RESOURCE.legacyPoints | The amount of the given resource | Can be used to find the amount of any resource: legacyPoints, heartwoods, hides, ingots, fabrics, and spellthreads |
COUNT | COUNT.target | How many matches were made for the given target | Often used in the effect.info.aiPriority field to make give AOE attacks higher priority if they hit more targets. Also used in the Damage Outcome for multi-target abilities, to divide stunt chance among the targets. |
EXISTS | EXISTS.target | 1 if at least one match was made for the given target, 0 otherwise | |
ASPECT_PARAM0 | self.ASPECT_PARAM0.extraDamageAspect | The value of the nth parameter | Tries to get a parameter value from an aspect on a given role. This can be done for up to a 9th parameter (ASPECT_PARAM0, ASPECT_PARAM1, etc.) |
ITEM_CATEGORY | weapon.ITEM_CATEGORY.bow | 1 if the given item is of the given category (bow, sword, spear, etc), 0 otherwise | |
WEAPON_TIER | WEAPON_TIER.weapon | The tier of the given weapon, or -1 if there isn't one or it isn't a weapon | |
ITEM_TIER | item.ITEM_TIER | The tier of the given item, or -1 if there isn't one or it isn't an item | |
hasItem | hero.hasItem.spearBone | 1 if the given role has (or is) an item with the given item id, 0 otherwise | |
canEquip | hero.canEquip.item | 1 if the given role can equip the second role, 0 otherwise | |
TURN_NUMBER | TURN_NUMBER | The current mission turn number | |
SEASON | SEASON | The current season (1=Winter, 2=Spring, 3=Summer, 4=Fall) | Generally, you'll want to do something like isMatch(SEASON, 1) to check if it's Winter |
YEAR | YEAR | The current year | |
DAY_OF_MONTH | DAY_OF_MONTH | day of the current season | |
distanceTo | target.distanceTo.targetTile | In a mission, the distance between two roles (can be entities or tiles) | Used to calculate the extra damage dealt from knockback attacks, and certain other edge cases like making sure the Thrixl Thrusk is still in range to attack again after its first attack (e.g. if the defender has Riposte and a knockback weapon) |
ticksPerTurn | 2 | Used along with timeCostPerStep for movement abilities | |
SIZE | source.SIZE | Number of tiles a mission entity takes up, or its max footprint dimension | Used in Splinterblast to give larger objects greater AOE |
AGE_IN_YEARS | The age of the current target. | ||
MIN_ATTACK_RANGE | self.MIN_ATTACK_RANGE | The minimum range at which the given target can attack. | Used for movement abilities to determine whether to show the dotted-line attack suggestion. |
MAX_ATTACK_RANGE | self.MAX_ATTACK_RANGE | The maximum range at which the given target can attack. | Used for movement abilities to determine whether to show the dotted-line attack suggestion. |
MAX_MELEE_ATTACK_RANGE | self.MAX_MELEE_ATTACK_RANGE | The maximum range at which the given target can melee attack. | Used for guarding abilities to show range feedback. |
POSITION_X | self.POSITION_X | The x position (tile) of the unit on the mission map | |
POSITION_Y | self.POSITION_Y | The y position (tile) of the unit on the mission map | |
maxValue | self.maxValue.gorgonCorruptedTileRel | The maximum value of any aspects the given target has starting with the given string | |
totalValue | self.totalValue.myParameterizedAspect | The total value of any aspects the given target has starting with the given string | |
HAS_FRIEND | 1 if the current target has a friend, 0 otherwise | Used in events when we want to match a target that has a friend | |
HAS_LOVER | 1 if the current target has a lover, 0 otherwise | Used in events when we want to match a target that has a lover | |
HAS_RIVAL | 1 if the current target has a rival, 0 otherwise | Used in events when we want to match a target that has a rival | |
HAS_FAMILY | 1 if the current target has family (a parent, child, grandparent, etc), 0 otherwise | ||
HAS_PARENT | 1 if the current target has a parent, 0 otherwise | ||
HAS_CHILD | 1 if the current target has a child, 0 otherwise | ||
HAS_SIBLING | 1 if the current target has a sibling, 0 otherwise | ||
HAS_[relationship]_IN_PARTY | HAS_LOVER_IN_PARTY | "_IN_PARTY" can be added to any of the above, to specify that the related unit must be in the party role. 1 if there is such a unit, 0 otherwise | Useful for events that involve lovers, rivals, etc because we want to match a hero that has a valid lover first; if we match a hero with a lover not in the party first, the event will just fail and won't be picked |
CAN_FORM_ROMANCE | 1 if the current target can form a romance (no existing lover, no npc lover, not a skeleton, doesn't have random romances disabled), 0 otherwise | ||
LEVEL | self.LEVEL | The level of the given hero target, or 0 if none | Generally used in abilities when we want the ability's power to scale with level |
IS_LEGACY_HERO | self.IS_LEGACY_HERO | 1 if the hero is a legacy hero, 0 otherwise | |
THREAT_STRENGTH | foes.THREAT_STRENGTH | The full "strength", or number of cards, of a threat | Used to show threat strength in attackSite blurb |
THREAT_STRENGTH_FROM_INFESTATION | The strength being added to a threat from infested tiles | ||
THREAT_STRENGTH_FROM_EXTRA_CHAPTER_CARDS | The strength being added to a threat from extra chapter cards, added during the interval | ||
THREAT_STRENGTH_FROM_INCURSION_SIZE | The strength being added to a threat from the incursion size | ||
THREAT_STRENGTH_BASE | The base threat strength, not including strength from infestations or extra chapter cards | ||
THREAT_CALAMITIES | foes.THREAT_CALAMITIES | The number of calamity cards that have been drawn for the given threat. (Useful if you have an event that takes away a calamity, and you want to be sure it'll be able to) | |
THREAT_MONSTER_CARDS | number of monster cards in the mission | ||
NUM_ENEMIES | The number of enemies in the current mission | ||
MISSIONPLAN_HAS_TAG | MISSIONPLAN_HAS_TAG.forbidSpirits | 1 if the current mission plan has the given tag, 0 otherwise | Currently used in Omenroad to determine if fights are boss fights or if spirits are forbidden |
CHAPTER | chapter or dungeon page number | ||
DIFFICULTY_COMBAT | combat difficulty (1-4) | Often useful along with if and isMatch functions, e.g. if(isMatch(DIFFICULTY_COMBAT,1),8) would return 8 on storyteller difficulty | |
DIFFICULTY_OVERLAND | overland difficulty (1-4) | ||
IS_DUNGEONMODE | are we currently in dungeonmode (Omenroad)? | ||
IS_DUNGEONMODE_CHALLENGE | are we currently in dungeonmode (Omenroad), and a challenge run (where peril and odes are enabled)? | ||
SCENERY_ID | target.SCENERY_ID.ovenOn | 1 if the scenery has the given id, 0 otherwise | |
OVERLAND_TILE_DISTANCE_TO_CLOSEST_HERO | Distance from this overland tile to the nearest hero | Specifically used when building a bridge or pass to an inaccessible tile, to decide where to build it | |
raw | raw.POTENCY | The raw stat (a float, not converted to an integer) | |
CAN_ROMANCE | CAN_ROMANCE.hook | 1 if the current target can romance the given target, 0 otherwise | Must be mutually attracted, not already have lovers, and non-family |
CAN_ROMANCE_LOOSE | CAN_ROMANCE_LOOSE.hook | 1 if the current target can romance the given target, 0 otherwise | a looser check for romance. Checks family and forbidden romance (e.g. skeleton), but ignores existing relationships, forbidRandomRomances, and attraction |
CAN_RIVAL | CAN_RIVAL.hook | 1 if the current target can be rivals with the given target, 0 otherwise | Must not already have rivals |
SHIP_WITH | SHIP_WITH.hook | The tier of the relationship between the current target and the given target | This can be any kind of relationship; lovers, rivals, or friends |
FRIEND_WITH | FRIEND_WITH.hook | The tier of the friendship between the current target and the given target, 0 if not friends | |
LOVER_WITH | LOVER_WITH.hook | The tier of the romance between the current target and the given target, 0 if not lovers | |
RIVAL_WITH | RIVAL_WITH.hook | The tier of the rivalry between the current target and the given target, 0 if not rivals | |
FAMILY_WITH | FAMILY_WITH.hook | 1 if the current target is family with the given target, 0 otherwise | |
PARENT_OF | PARENT_OF.hook | 1 if the current target is the parent of the given target, 0 otherwise | |
CHILD_OF | CHILD_OF.hook | 1 if the current target is the child of the given target, 0 otherwise | |
SIBLING_OF | SIBLING_OF.hook | 1 if the current target is a sibling of the given target, 0 otherwise | |
NOT_FAMILY_WITH | NOT_FAMILY_WITH.hook | 0 if the current target is family with the given target, 1 otherwise. | NOT_FAMILY_WITH.hook is equivalent to (1 - FAMILY_WITH.hook) |
DLC_INSTALLED_ARMORSANDSKINS | 1 if the player has the Armors and Skins DLC enabled, 0 otherwise | ||
DLC_INSTALLED_OMENROAD | 1 if the player has the Omenroad DLC enabled, 0 otherwise | ||
MOD_ACTIVE.modId | MOD_ACTIVE.myCoolMod | 1 if the mod with the given id is active | Useful if your mod has dependencies or differences based on other mods |
Interpolation and Easing Functions
Two or more values can be interpolated between in the form of progress~{a|b|c|...} where progress is a value from 0-1, with 0 returning the starting value, 1 returning the final value, and anything in between interpolating between values. For example:
life~{0|0.5:0.9|1} life~{10:0|20:1} life~{0:0|inOutSine:10:1}
("life" is the most commonly used progress value, as this is commonly used for particle effects, but any value can be used, and this can be used for more than particles)
Each section can have up to two numbers and one easing function:
empty --> interpolate all values, no easing ## --> y value, interpolate x ##:## --> x, y, no easing ##:ease --> y, easing ease --> easing function, interpolate x and y ease:## --> easing and y, interpolate x ease:##:## --> easing, x, y ##:ease:## --> x, easing, y ##:##:ease --> x, y, easing
For example, this expression could be used on the alpha channel in a SetColor particle rule: life~{0|0.1:1|0.9:0.5|0} Which would cause the particle to fade from invisible to fully visible in the first 1/10 of the particle's life, then fade to half visibility for most of its life, then at 90% of the way through its life, start fading back to invisible. (Adding easing functions to the expression could be useful to make the transitions look smoother)
The available easing functions are as follows, each having an in, out, and inOut version (e.g. inQuad, outQuad, inOutQuad)
none, Quad, Cubic, Quart, Quint, Circ, Sine, Expo, Back, Bounce, Elastic
Particle Variables
There are a number of variables that are specific to working with particles
variable | explanation/usage |
---|---|
Particles | |
life | Percent of the particle's life it has existed for (time/killTime) |
time | How long (in seconds) this particle has existed for |
killTime | The kill time of this particle |
x/y/z | The x/y/z position of the particle relative to the emitter |
vx/vy/vz | The x/y/z velocity of the particle |
rotation | Particle sprite rotation in degrees |
r/g/b/a | The red/green/blue/alpha color of the particle |
size | The scale of the particle |
particleNumber | What number particle this is (loops up to the emitter budget) |
offset_V(x) | Get the data V from a different particle, whose particleNumber is at the given offset x. For example, offset_rotation(-1) would get the rotation of the previous particle. Can be useful for particle "chains", where you want each particle to face the previous one, etc. Note that a negative offset is usually a better choice, since a positive offset will be using data from 1 frame behind for the next particle |
particleNumData_V(x) | Get the data V from a different particle, whose particleNumber is at the given number x. For example, offset_z(0) would get the z position of the first particle. In general, if you have one "main" particle you want other particles to act in response to, you may want to set an EmitterVar to store the particleNumber of the main particle, which can then be used for the number x |
Emitter | |
e.life | Percent of the emitter's life it has existed for (e.time/emitter lifetime) |
e.time | How long (in seconds) this emitter has been on this loop for (resets on loop) |
e.totalTime | How long total (in seconds) this emitter has existed |
e.position.x/y/z | Position1 x, y, and z |
e.position2.x/y/z | Position2 x, y, and z |
e.dx/dy/dz | Position offset between position 1 and 2 (e.position2.x - e.position.x, etc) |
e.length | Distance between position1 and position2 |
e.budget/size | Number of particles this emitter is allotted |
e.loopCounter | Number of loops this emitter has gone through |
e.facingDirection | Returns 1 if position2 is to the right of position, returns -1 if it's to the left. Useful if you want to rotate something clockwise or counterclockwise depending on the direction it's used in, for example |
Global | |
healthBarZ | The z position of the associated unit's healthbar (useful for making particles that go by a unit's head) |
screenScale | UI scale, equal to 1 at a "default" scale. Useful for UI particles, which should often get bigger along with the UI. |
UIGain | Equal to 0.48/exposure - Multiply by color to make a particle have a similarly appearing brightness on both dark and bright maps. Useful for in-world UI particles, which we want to be readable at all times. |
thisScriptCount | Number of times this script is being used. Useful for reducing certain particles (like fire smoke) if there's a lot of it onscreen |
tileIsVisible | Returns 1 if the tile at the particle's x,y position is visible to the player (not in fog of war), 0 otherwise. Useful for reducing particles in areas that are in fog of war, for performance reasons. |
dt | Time (in seconds) since the last frame |
ATTACK_COLOR.r/g/b | The highlight color used by attack abilities (default red, user customizable) |
ATTACK_SECONDARY_COLOR.r/g/b | The highlight color used by secondary attack abilities (default orange, user customizable) |
INTERACT_COLOR.r/g/b | The highlight color used by interact abilities (default blue, user customizable) |