Origins: Powerful Powers
» Variables in Origins fields, commands and scoreboardsPage 9 of 17

Variables in Origins fields, commands and scoreboards

Ways to connect variables to the rest of the game:

You want to…Use
Put a variable into any field of an Origins action or condition: a command, a velocity, an effect duration, a compare_towith_variables
Use variables in chat, command blocks or functions/opp with
Read a scoreboard score in code, for example a value shared by a teamScoreboard.get
Read what item is in a slot: a vanilla slot, or one of your origins:inventory powers, for you or the other entityItem.id and Item.count
Feed a number to a power field that's read continuously, such as a modifiervariable_bar + the modifier's resource

With variables

origins-powerful-powers:with_variablesentity action, bi-entity action, entity condition, bi-entity condition

Wraps any Origins action or condition. Any string value inside it can contain ${expression}. Each time it runs, the placeholders are filled in for this entity and Origins reads the result.

FieldTypeDefaultDescription
actionEntity action type (or bi-entity action type)required in the action versionsThe action to run
conditionEntity condition type (or bi-entity condition type)required in the condition versionsThe condition to check

Placeholder rules:

  • The whole string is one placeholder, like "${speed}". It becomes a real JSON number, boolean or string, so it can fill number and true/false fields.
  • A placeholder inside text, like "say I have ${coins} coins", is converted to text the way Java does ("" + coins). A double prints as 3.0, a long without an L.
  • $${ is a literal ${.
  • Inside ${…} goes one read-only expression: ${coins / 100}, ${(int) (mana * 20)}, ${tier.toUpperCase()}, ${x >= 25 ? "green" : "gray"}, ${Scoreboard.get("kills")}. String literals inside can contain }.
  • Bi-entity versions: ${other.name} reads the target and ${self.name} the actor.
  • Inside a for_each_read loop: ${value}, ${index} and ${size} read the current element (page 11).

A number into origins:add_velocity: launch upward with a strength stored in double jumpPower.

json
{
  "type": "origins-powerful-powers:with_variables",
  "action": {
    "type": "origins:add_velocity",
    "y": "${jumpPower * 0.1}",
    "space": "world"
  }
}

A String into origins:execute_command:

json
{
  "type": "origins-powerful-powers:with_variables",
  "action": {
    "type": "origins:execute_command",
    "command": "title @s actionbar {\"text\":\"${rank}: ${mana}/${maxMana} mana\"}"
  }
}

Numbers into an effect. Cast to int for whole-number fields.

json
{
  "type": "origins-powerful-powers:with_variables",
  "action": {
    "type": "origins:apply_effect",
    "effect": {
      "effect": "minecraft:speed",
      "duration": "${(int) (mana * 20)}",
      "amplifier": "${Math.min(level, 4)}"
    }
  }
}

A condition with a threshold from a variable: true while the food level is below the player's hungerLine.

json
{
  "type": "origins-powerful-powers:with_variables",
  "condition": {
    "type": "origins:food_level",
    "comparison": "<",
    "compare_to": "${hungerLine}"
  }
}

Bi-entity: damage the target by its own bounty variable.

json
{
  "type": "origins:action_on_hit",
  "bientity_action": {
    "type": "origins-powerful-powers:with_variables",
    "action": {
      "type": "origins:target_action",
      "action": {
        "type": "origins:damage",
        "amount": "${(float) other.bounty}",
        "damage_type": "minecraft:magic"
      }
    }
  }
}

Things to know:

  • Some mistakes only show up when the action runs. A syntax error inside ${…} fails the pack load. Origins reads the wrapped action after the values are filled in, so a wrong field name or value type is logged the first time it runs (prefixed [variables] with_variables:) and the action does nothing. A condition that fails this way counts as false.
  • Decimals are cut off in whole-number fields like duration, so 2.9 becomes 2. Round in the expression for rounding.
  • Quotes in String variables. A String is inserted as it is. A " inside a tellraw JSON text breaks that JSON. Use name.replace("\"", "'") in the expression when that can happen.
  • Caching. Origins reads each distinct filled-in result once and keeps it, up to 64 per with_variables. A value that changes every tick (a double that never repeats) makes the action re-read every time, which is slower. Round values in actions that run every tick.

/opp with

For chat, command blocks and .mcfunction files, put opp with <targets> in front of any command:

mcfunction
opp with @s title @s actionbar {"text":"${rank}: ${mana}/${maxMana} mana"}
opp with @a[tag=saver] scoreboard players set @s bank ${(int) coins}
opp with @s tellraw @s {"text":"${history.size()} payouts so far"}
  • Each target's own values. For every target, ${…} is filled from that target's variables and lists. The command then runs as that target, like execute as, so @s is the target. Position, dimension and permission level stay those of whoever ran /opp with. For the target's position, use opp with @a execute at @s run ….
  • Everything becomes text. Every placeholder uses Java's text conversion. ${d} for a double prints 3.0, so write ${(int) d} where a command needs a whole number. $${ is a literal ${.
  • Plain quotes inside ${…}. The placeholder is replaced before the command runs, so write its quotes plainly, even inside JSON text: title @s actionbar {"text":"${Scoreboard.get("#bank", "team_bank")}"}. In power JSON, the whole command is a JSON string, so every " there is written \".
  • All or nothing. Every target is filled in before any command runs. If one fails (an unknown variable, a wrong type, a typo inside ${…}), nothing runs and /opp with fails with the reason.
  • Result. The sum of the commands' results, so execute store result score @s x run opp with @s … works for one target.
  • Permission level 2, like the other /opp commands. Functions and command blocks have it.

Scoreboard

Code can read scores anywhere it runs: execute code, expression conditions, modify_variable values, for_each code and ${…}.

CallReturns
Scoreboard.get(objective)intthis entity's score in objective
Scoreboard.get(holder, objective)intthe score of any holder: a player name, or a fake name like #bank
Scoreboard.has(objective)booleanwhether this entity has a score in objective
Scoreboard.has(holder, objective)booleanwhether holder has a score in objective
java
teamBank = Scoreboard.get("#bank", "team_bank");
kills = Scoreboard.get("kills");
bonus = Scoreboard.has("#event", "active") ? Scoreboard.get("#event", "active") * 10 : 0;
  • A missing score is an error, as with vanilla's /scoreboard players get. An action stops there, and a condition is false. An unknown objective is an error too. Check with Scoreboard.has first when a score may be unset.
  • "This entity" is the power holder (in bi-entity code, the actor), by its scoreboard name: a player's name, or the UUID for other entities. The bi-entity target's score is unreachable this way.
  • Holders are exact names. Selectors like @s or @p fail here.
  • It only reads. To write a score, run a command with the value, using /opp with or with_variables + execute_command, as below.
  • Field initializers can't use it, because they run when the pack loads, before a world exists.

Shared values through scoreboards. A team bank kept on the fake player #bank:

json
{
  "type": "origins:and",
  "actions": [
    {
      "type": "origins-powerful-powers:with_variables",
      "action": {
        "type": "origins:execute_command",
        "command": "scoreboard players add #bank team_bank ${Math.min(coins, 10)}"
      }
    },
    {
      "type": "origins-powerful-powers:execute",
      "code": "coins -= Math.min(coins, 10);"
    }
  ]
}

This deposits up to 10 of your coins. Anyone can check the shared total with Scoreboard.get("#bank", "team_bank"), for example in an expression condition or a HUD message.

Attributes into variables. Store an attribute in a score, then read it:

mcfunction
execute as @a store result score @s sprint run attribute @s origins-powerful-powers:sprint_ticks get
java
longestSprint = Math.max(longestSprint, Scoreboard.get("sprint"));

Power fields: variable bar and modifier resource

Power fields, like a modify_jump modifier, are read when the power is granted, so with_variables can't reach them. For a number a power uses continuously, link the variable with a variable_bar and put the bar's id in the modifier's resource field. Origins then uses the bar's value as the modifier's value.

Example: bonus damage equal to an int rage variable, linked through a variable bar with the id mypack:rage_bar:

json
{
  "type": "origins:modify_damage_dealt",
  "modifier": {
    "operation": "add_base_early",
    "value": 0,
    "resource": "mypack:rage_bar"
  }
}

This works for any power that takes an Origins modifier: modify_damage_dealt, modify_damage_taken, modify_jump, modify_break_speed, conditioned_attribute, and so on. A bar is a whole number, so store fractions scaled (such as int speedPercent) and pick an operation to match.