Physique (physique)
File location: data/<namespace>/mxt/physique/<path>.json
A physique hands out bonuses that stand apart from elements: vanilla attributes, abilities and two damage multipliers. Who gets it and when is decided by holder_condition, so prerequisites such as "a fire physique only once you hold a fire root" are written here. Physique and element are two paths that never meet - the element half belongs to Spirit Root.
| Field | Type | Default | Description |
|---|---|---|---|
attribute_modifiers | Attribute modifier entry array | [] | Vanilla attribute bonuses independent of spirit roots. |
granted_abilities | Array of ability ids or #tags | [] | Granted abilities. |
holder_condition | EntityCondition | mxt:always | The holder condition checked before granting. |
exclusive_tags | Identifier array | [] | Mutual exclusion tags. |
quality | Quality id | none | Optional. This physique's own grade: the physique stone carrying this definition reads at it, and it is also the tier named beside the physique in the info panel and /mxt physique list. |
allow_stacking | Boolean | false | Whether the same physique may stack. |
damage_dealt_multiplier | NumberProvider | 1 | Damage the holder deals is multiplied by this in layer one of damage settlement. |
damage_taken_multiplier | NumberProvider | 1 | Damage the holder takes is multiplied by this in layer two of the pipeline. |
An attribute_modifiers entry writes attribute plus the vanilla modifier's id/amount/operation; when an entry fills in value, the value is recalculated every tick from the entity context by a formula instead.
holder_condition can combine mxt:has_spirit_root and mxt:has_physique to express a prerequisite spirit root or prerequisite physique.
quality names a tier in mxt:quality and may be left out. The info panel's physique row reads "definition name · quality name" in its tooltip, and with no quality that part is left out entirely (it never shows -); /mxt physique list shows - when there is no tier. An mxt:quality component on the stack wins; with no quality here this layer answers nothing and resolution continues to the default_quality registry.
// data/example/mxt/physique/innate_sword_bone.json
{
"attribute_modifiers": [
{ "attribute": "minecraft:attack_damage", "id": "example:physique/sword_bone", "amount": 2, "operation": "add_value" }
],
"granted_abilities": ["example:sword_intent"],
"exclusive_tags": ["example:physique/skeletal"],
"quality": "example:epic",
"damage_dealt_multiplier": "1 + 0.05 * realm_rank",
"damage_taken_multiplier": 0.9
}
Element Fields Are Ignored
"A physique carries no element" is a boundary drawn by the field table above, not by a load-time check. A physique reads only the keys listed in that table, so writing the following into a physique definition neither fails nor does anything:
element, elements, element_affinity, element_tags, element_ability_modifier, conflicting_elements, relations, overcomes, adapted_to, damage_types, attachment_decay, damage_attachment, aura_type, cultivation_multiplier.
The reason is a practical one: decoding a definition reads only the keys it was told about and ignores everything else. A physique that "looks like it has elements but actually carries nothing" therefore keeps running quietly: check your key names against the table above and do not expect the loader to catch them for you. Writing into the wrong registry (putting a physique in mxt/spirit_root/, or the other way round) is equally silent.
The Two Damage Multipliers
They are the seam that lets a physique talk about combat without talking about elements: the numbers themselves have nothing to do with elements, and the two layers of damage settlement read them separately - layer one reads the attacker's damage_dealt_multiplier, layer two reads the target's damage_taken_multiplier.
- The multiplier is evaluated in the holder's own formula context, so how much this body takes does not depend on who is asking; a
valueformula can read thecaster_*family of variables. 0is a legal value (immunity, or hitting for nothing). Written as a number it is validated as finite and non-negative while loading; a negative or non-finite value produced by a formula contributes nothing.- Several active physiques multiply, because each one is an independent source.
- They do not enter the formula context: only the pipeline reads them, so there is no chance for the data pack to multiply them a second time. The only multiplier a formula can read is
damage_multiplier, which already contains the element affinity share — do not multiply another one in.
Holding and Switching Off
Granting and removing both go through entity actions: mxt:grant_physique and mxt:remove_physique (the spirit root side is mxt:grant_spirit_root and mxt:remove_spirit_root). Whether one is held is tested with the entity condition mxt:has_physique (spirit roots use mxt:has_spirit_root); the script side is MxtPhysiques (spirit roots use MxtSpiritRoots) and the administrator side is /mxt physique (spirit roots use /mxt spirit_root).
The mod also ships a physique item, mxt:physique: the mxt:physique component on the stack names the physique it grants, and right-clicking grants it — through the same check the actions and the command use, so "already held" (only while allow_stacking is false), an unmet holder_condition and an exclusive-tag conflict are all refused as usual, with the attributes, abilities and both damage multipliers recalculated on the spot. A grant spends one item and creative mode spends none; a refusal leaves the item in hand and says why, while a bare item with no component only says which physique it fails to name. Take one with /give @s mxt:physique[mxt:physique="example:sword_bone"], or use /picker mxt:physique — one row per physique definition, each already carrying the component. That is the item's use path, which is a different thing from the switch below.
A physique that is already held can be switched off without being lost: once it is off, its attribute modifiers, granted abilities and both damage multipliers all stop applying, but it is still "held" (mxt:has_physique still answers true, and it can still be removed normally). That state lives in the spirit_identity attachment, so it is saved and synchronised with the entity.
Switching off has no player-facing entry point (no keybind and no screen): the operation is the script-side MxtPhysiques.setEnabled, or the administrator command /mxt physique enable|disable. That is a different question from taking the definition out of the data pack: the switch only governs the one entry that was switched off, and that entry is still held, while removing the definition takes it out of the registry entirely (write neoforge:conditions, see Disabling a Definition).