Costs, Conditions & Variables
Previous: Cast Modes & Channeling · Next: Scripts
This page covers the cost a skill must pay before it's cast, the prerequisites for whether it can be cast, and finally how to pass data through to MythicMobs and scale by level. Four blocks of content:
| Block | Field | Purpose |
|---|---|---|
| 💧 Resource cost | resource.<key> | Spend a resource pool such as mana |
| 🩸 Health / hunger cost | cost.health / cost.hunger | Blood-sacrifice playstyle, spending vanilla health / hunger |
| ✅ Declarative conditions | conditions | A set of "cast only if satisfied" checks |
| 📦 Variables & levels | variables / levels | Pass to MM, scale by level |
🖼️ [Image placeholder] A gate-order diagram for one cast (resource → blood sacrifice → condition → fire) · suggested
assets/cost-gate-flow.png
💧 Resource Cost resource.<key>
The most common one is mana mana:
resource:
mana: 15 # deducts 15 mana when the cast succeeds; if insufficient, the cast is blocked with a notice⚠️ Important: resource pools like
manawill eventually be managed by QinhClass (QC); for now it's a temporary placeholder. QS currently manages this number temporarily through its ownPlayerSkillProfilecost seam (channel costs also reuse the same seam, rather than building a second pool). When QC takes over, only this one spot changes; theresource.manayou write now won't need to change.
A resource's initial value / cap is in the resources.* section of config.yml:
config.yml key | Default | Meaning |
|---|---|---|
resources.default_mana | 100.0 | Player's initial mana |
resources.max_mana | 100.0 | Mana cap |
🩸 Health / Hunger Cost (Blood Sacrifice)
cost.health and cost.hunger deduct vanilla attributes, not the mana pool above. The blood-sacrifice playstyle (using health as a resource) relies on these.
| Field | Unit / rule |
|---|---|
cost.health | Deducts health, half a heart = 1. Can't cast when health ≤ this value; after deduction it floors at 0.5 (won't kill yourself) |
cost.hunger | Deducts hunger |
cost:
health: 4.0 # deducts 2 hearts; can't cast when health ≤ 4, leaves at least 0.5 after deduction
hunger: 2 # deducts 1 hunger bar💡 A blood-sacrifice skill can omit the
resourcesection entirely—relying purely on health as the cost. Below is a pure blood-sacrifice example.
Full example: a blood-sacrifice skill (pure health cost, no mana)
id: blood_nova
display: "&4血祭新星"
meta:
category: combat
type: active
rank: rare
trigger:
primary: SHIFT_RIGHT_CLICK
state:
required: IDLE
graph:
entry: blood_nova
execution:
mythic_skill: blood_nova
type: active
max_level: 1
cooldown:
base: 5000
# Pure blood sacrifice: no resource section, only deducts health and hunger
cost:
health: 6.0 # deducts 3 hearts (can't cast when health ≤ 6)
hunger: 3 # also deducts 1.5 hunger bars
variables:
element: blood # passed to MM, <skill.var.element> = blood✅ Declarative Conditions conditions
conditions is a list of strings that must all be satisfied to cast. For simple "can I cast it or not" checks this is enough, with no scripting needed.
conditions:
- "player_level:>=5" # level ≥ 5
- "player_health_pct:>=50" # health percentage ≥ 50
- "player_in_world:world" # in the main worldSyntax rules
- Written as
key:value, where the value can carry a comparator:>=<===!=><=(no comparator defaults to=). - An empty list = no restriction (anyone can cast).
- An unknown key is always true—a misspelled key name won't lock the skill, that line just has no effect.
Full table of condition keys
| Key | Value / description |
|---|---|
player_level | Player level |
player_health | Absolute health value |
player_health_pct | Health percentage (0–100) |
player_food | Hunger value |
player_in_world | World name |
player_has_permission | Permission node |
player_gamemode | SURVIVAL / CREATIVE / ADVENTURE / SPECTATOR |
player_sneaking | Boolean (true/false/1/yes) |
player_sprinting | Boolean |
player_on_fire | Boolean |
player_on_ground | Boolean |
player_y | Y coordinate |
has_target | Whether there is a target (passive target / crosshair target) |
target_type | Target entity type, e.g. ZOMBIE |
target_distance | Distance to the target |
Full example: a multi-condition skill (castable only under specific circumstances)
id: execute_strike
display: "&c处决斩"
meta:
category: combat
type: active
trigger:
primary: LEFT_CLICK
state:
required: IDLE
graph:
entry: execute_strike
execution:
mythic_skill: execute_strike
type: active
cooldown:
base: 4000
target: NEAREST # auto-lock the nearest target
conditions:
- "player_level:>=10" # this playstyle unlocks at level 10
- "player_sneaking:true" # must be sneaking (charging up the execution)
- "has_target:true" # must have a target
- "target_type:ZOMBIE" # only against zombies
- "target_distance:<=4" # within 4 blocks (point-blank)
- "player_gamemode:SURVIVAL" # not usable in creative modeIf any one condition isn't satisfied, QS blocks the cast and gives the corresponding notice, deducting no resources.
For more complex checks (combining multiple values, calling external data) use the
pre_jsscript, see Scripts.
📦 Variables variables (pass-through to MM)
variables.<key> passes any value through to the MM skill, which the MM side reads with <skill.var.key>.
variables:
element: fire # in MM, <skill.var.element> reads "fire"
power: "2.5"Besides what you write, QS also auto-injects these variables (MM reads them all with <skill.var.key>):
| Auto variable | Meaning |
|---|---|
mode | Trigger mode |
source | Trigger source |
slot | Skill slot (-1 when there's no slot, e.g. the command bridge) |
playerName | Player name (on the MM side it's playerName, not player) |
origin | Fixed as QinhSkills |
logicOnly | Fixed as true (marks a logic-layer-only call) |
toggle_state | Toggle skill state on/off (only for toggle skills) |
⚠️ Two easy-to-get-wrong spots (verified against the source code):
- The
variables:/levels.params:keys you write appear in MM as-is, with no prefix—variables.element→<skill.var.element>,levels.params.power→<skill.var.power>. (Only in the scriptctxdo they carry thevar_prefix; don't mix the two conventions.)- The MM side can't get
playerorlevel: use<skill.var.playerName>for the player name; the skill level is not injected into MM (it's only available in the script viactx.get("level")). To scale values by level in MM, pass a parameter (such aspower) vialevels.params:and read it with<skill.var.power>.
For the full explanation of MM receiving variables (including
@Target/@Trigger), see Integrating with MythicMobs.
📈 Level Scaling levels.N
levels.<level>.{cooldown_ms, resource, params} lets a skill override values by the player's level in that skill (1 to max_level).
cooldown_ms: the cooldown at that level.resource: the resource cost at that level.params: the parameters at that level, also passed through to MM (MM reads with<skill.var.power>).
Merge rule (SkillParamResolver): if the level has it, use the level's value; if not, use the top-level default—so you only need to write the few items in levels that "change with level."
Full example: cooldown decreasing + power increasing
id: fire_lance
display: "&c烈焰长矛"
meta:
category: combat
type: active
trigger:
primary: RIGHT_CLICK
state:
required: IDLE
graph:
entry: fire_lance
execution:
mythic_skill: fire_lance
type: active
max_level: 3
# Top-level defaults (used for any level / field not overridden in levels)
cooldown:
base: 5000
resource:
mana: 20
variables:
element: fire
levels:
1:
cooldown_ms: 5000 # level 1: 5-second cooldown
resource: { mana: 20 } # deducts 20 mana
params: { power: "1.0" } # power=1.0 → MM uses <skill.var.power> to scale damage
2:
cooldown_ms: 4000 # level 2: cooldown drops to 4 seconds
resource: { mana: 18 }
params: { power: "1.5" } # higher damage
3:
cooldown_ms: 3000 # level 3: 3-second cooldown (strongest)
resource: { mana: 15 } # cost is actually lower
params: { power: "2.2" }On the MM side, just multiply <skill.var.power> into the damage formula, and QS will feed in the corresponding power based on the player's level.
Set a player's level:
/qs level <skill> <level> [player], see Commands & Permissions.
🔗 How These Values Are Read in Scripts
If you wrote pre_js/post_js scripts, all the variables above can be read with ctx.get(key)—mind the prefixes:
| Source | Key in the script |
|---|---|
variables.<key> (skill variables) | Add the var_ prefix, e.g. ctx.get("var_element") |
levels.params.<key> (level parameters) | Add the param_ prefix, e.g. ctx.get("param_power") |
| Auto variables (mode/source/level…) | Read directly, e.g. ctx.get("level") |
For scripts see Scripts.
📚 Continue Reading
- Scripts — use JS for complex logic that
conditionscan't express - Cooldowns, Charges, GCD & Conflicts — cooldowns / charges / GCD / conflict groups
- Configuration File — global config like
resources.*mana caps - Integrating with MythicMobs — how MM reads
<skill.var.*>