Kzeroko KTM2

Morph power and attribute data

Morph power fields, skill metadata, form eligibility, attribute profiles and resource reload behaviour.

Updated Sep 30, 2026 11 min read

Morph powers select a form and its actions; attribute profiles modify the wearer during chosen phases. This page defines the authored fields and reload behaviour, with runtime extension contracts linked separately.

Where the files live

Morph powers use data/<namespace>/powers/<path>.json; attribute profiles use data/<namespace>/morph_attributes/<path>.json. The relative path defines each resource ID. Powers must also be granted through the pack’s origin or other power-grant mechanism. The power’s id chooses an already registered skill execution; writing a new identifier does not create that execution.

Player-control forms include this mod’s base NPC family and entity types in isekaiexpansion:morph_player_rigs. Those forms retain player controls and replace both authored mouse abilities with isekaiexpansion:none. Only opt a third-party humanoid into that tag when its renderer supports the player-rig contract.

Minimal example

To override the existing fox power, place this at data/isekaiorigins/powers/kitsune_active_fox_form.json. It uses the already registered execution and ability IDs; this file alone does not grant the power.

{
  "type": "isekaiorigins:morphing_skill",
  "id": "isekaiexpansion:kitsune_active_fox_form",
  "meta": {
    "max_level": 1,
    "cooldown": "240",
    "energy": "0"
  },
  "entity_type": "minecraft:fox",
  "primary_ability": "isekaiexpansion:entity_primary",
  "secondary_ability": "isekaiexpansion:kitsune_fox_pounce",
  "transition_ticks": 18
}

An independent profile at data/example/morph_attributes/fox_speed.json adds a speed modifier to players in the active fox form:

{
  "forms": [
    "minecraft:fox"
  ],
  "phases": [
    "ACTIVE"
  ],
  "modifiers": [
    {
      "attribute": "minecraft:generic.movement_speed",
      "operation": "multiply_total",
      "value": 0.2,
      "scale": {
        "attribute": "isekaiexpansion:dexterity",
        "factor": 0.002,
        "max": 0.1
      }
    }
  ]
}

For this example the modifier amount is 0.2 + min(0.1, dexterity × 0.002). The upper clamp applies only to the scaled term. This profile stacks with the shipped fox profile; use the shipped profile’s resource ID if replacement is intended.

Fields

Morph power

FieldTypeDefaultWhat it does
typeidentifierrequiredUse isekaiorigins:morphing_skill.
categorystringORIGINExact uppercase NONE, LEARNED, ORIGIN, CLASS, PROFESSION or ULTIMATE; unknown or differently cased values fail.
ididentifierrequiredRegistered execution ID, distinct from the power file ID. A new JSON ID does not register behaviour.
metaobjectrequiredLevel series described below; cooldown and energy are required.
entity_typeidentifierrequiredTarget must resolve to a living entity at activation. Missing/nonliving types reject the morph.
primary_abilityidentifierrequiredPrimary slot execution. Entity-specific overrides can replace it; unknown ability IDs have no resolved action.
secondary_abilityidentifierrequiredSecondary slot execution, with the same override rules. isekaiexpansion:none explicitly rejects use.
skin_ididentifierabsentOptional dedicated texture selector. An explicit missing skin does not fall through to the default entity override texture.
transition_ticksint18Clamped to at least 4; used separately for entering and exiting. No upper clamp.
duration_ticksint0How long the settled form lasts, in ticks. 0 lasts until the player returns; negative values clamp to 0. No upper clamp.
morph_ableobjectabsentParsed as the shared policy below, but ignored by this morphing subtype. Use on regular triggerable/ultimate powers.
sound_ididentifierabsentOptional accepted-trigger sound; unresolved sound events are skipped.
animation_ididentifierabsentOptional player-animation resource requested after an accepted trigger; parsing does not validate the animation asset.
effekobjectabsentOptional effect on accepted trigger; see nested fields below.
disablerobjectabsentOptional temporary action restrictions on accepted trigger.

The morph power fixes its side to active; it has no authorable side field.

A positive duration_ticks makes the form timed, the same way a talisman form is timed. The clock starts once the form finishes entering, so 1200 gives 1200 ticks (60 seconds) in the settled form and the transitions run outside it. When the time runs out the form returns on its own and the power’s cooldown starts, as after a manual return. A player with no room to stand stays in the form until there is room, and is told so once. The morph panel’s bar drains while a timed form runs, and the skill screen lists the duration.

Level metadata

FieldTypeDefaultWhat it does
max_levelintrequired1–256, finite and integral. Numeric strings are rejected.
cooldownstring seriesrequiredNonnegative integer ticks through 2147483647. Entering a form does not use it: entry starts a fixed 60-tick (3-second) settle lock that ability haste does not shorten. A successful return, or a timed form running out, starts the configured value adjusted by ability haste.
energystring seriesrequiredNonnegative integer astral-energy cost through 2147483647. Charged only on accepted triggers, including an accepted return; creative bypasses payment.
<custom_key>string seriesabsentHandler-defined values. At most 256 series, keys match [a-z][a-z0-9_]*, length at most 64; max_level is reserved.

Each series is a slash-delimited string containing either one finite number for every level or exactly max_level numbers. "10/20/30" has 3 entries; blank entries, nonfinite values and the wrong count fail. Values are trimmed before numeric parsing. Lookups clamp the requested level into the supported range. Additional valid keys are retained, but only a consuming handler gives them behaviour.

Core ability metadata uses these optional series:

FieldTypeDefaultWhat it does
pounce_velocitynumber series1.15Fox pounce horizontal speed; no handler range clamp.
pounce_damagenumber series4.0Fox pounce base fire damage.
pounce_coefficientnumber series0.55Fox pounce fire-power coefficient.
foxfire_multipliernumber series1.45Pounce multiplier when an attached foxfire is consumed.
secondary_cooldowninteger serieshandler-dependentFox pounce 100, warden sonic boom 200, witch healing potion 120 ticks.
primary_cadenceinteger series18Warden primary cadence; runtime cadence is at least 1 tick.
melee_damagenumber seriesform attack damage, at least 1Warden melee override; explicitly supplied values have no handler range clamp.
sonic_damagenumber series10Warden sonic damage override.
primary_potion_cooldowninteger series30Witch offensive potion cooldown.
native_hold_ticksinteger series30Saints Dragons power-bar native action hold; clamped to at least 1.

Integer lookups use the handler fallback for fractional or out-of-int-range values. Accepted ability cooldowns clamp negative values to 0. Other custom series only require finite values at parse time; choose physically meaningful values for velocity and damage.

Eligibility and trigger effects

FieldTypeDefaultWhat it does
morph_able.normal_formbooleantrueAllow the skill outside a morph.
morph_able.entity_typesidentifier array[]Exact form whitelist; empty allows every active morph. Duplicates collapse; tags are not accepted as substitutes.
effek.ididentifierabsentEffect resource ID. Supply one when enabling effek; the optional default is not a usable effect declaration.
effek.bindbooleanfalseBind the effect to the triggering entity.
effek.to_headbooleanfalseUse head binding for a bound effect.
effek.offsetvector(0, 0, 0)Offset passed to the effect builder; no local range clamp.
effek.scalefloat0Scale forwarded to the effect builder; this serializer does not clamp it. See the effect builder’s validation contract.
disabler.duration_ticksint0Restrictions apply only when positive; no upper clamp here.
disabler.use_itembooleanfalseTemporarily block item use.
disabler.attackbooleanfalseTemporarily block attacks.
disabler.movebooleanfalseTemporarily block movement.
disabler.jumpbooleanfalseTemporarily block jumping.

For regular isekaiorigins:triggerable_skill and isekaiorigins:ultimate_skill, omitting morph_able permits only normal form. An empty object permits normal form and every active morph; an explicit entity_types list restricts active forms. Ordinary skills remain blocked during entry/exit regardless of that policy. The morphing subtype stays eligible so its owning skill can request a return, but other checks can still reject the request. A return pressed during the settle lock is refused like any power on cooldown, so the earliest return comes 60 ticks (3 seconds) after entry.

Sound, animation, effect and action restrictions run after the execution accepts. For effect asset and builder details, see Effekseer integration.

Attribute profile

FieldTypeDefaultWhat it does
formsidentifier / identifier array[]Exact target entity types; at least one form or form tag is required. Invalid identifiers fail the file.
form_tagsidentifier / identifier array[]Entity-type tags without #; combined with forms using OR. No match contributes nothing.
phasesstring / string array["ACTIVE"]Case-insensitive NONE, ENTERING, ACTIVE, EXITING; no whitespace trimming. Missing or empty uses ACTIVE; invalid name fails. NONE parses but runtime applies no modifiers in that phase.
priorityint0Ascending sort, then profile ID; all matches apply, not only the highest priority.
modifiersobject array[]Must contain at least one modifier. A malformed entry fails the whole file.
modifiers[].attributeidentifierrequiredTarget player attribute. A valid but unregistered ID, or an attribute absent on the player, is skipped during application.
modifiers[].operationstringadditionCase-insensitive, no trimming. Add: addition / add / add_value; base multiplier: multiply_base / multiply_base_value; total multiplier: multiply_total / multiply / multiply_total_value. Unknown values fail.
modifiers[].valuedouble0Constant contribution; no range or finite-value check in this parser.
modifiers[].scaleobjectabsentOptional attribute-derived contribution added to value. Explicit null is invalid.
scale.attributeidentifierrequiredSource player attribute. Missing registry entry or player instance makes the entire scaled contribution 0, including offset.
scale.factordouble1Multiplier of the current source attribute value.
scale.offsetdouble0Added after multiplication and before clamping.
scale.mindouble−1.7976931348623157e308Lower bound on the scaled contribution only. Reversed min/max are swapped.
scale.maxdouble1.7976931348623157e308Upper bound on the scaled contribution only; does not clamp constant value. No explicit finite check.

The amount is value + clamp(source_attribute × factor + offset, min, max). Scaling reads the player’s current effective attribute, including currently installed modifiers. It is evaluated before old morph modifiers are removed, so a source affected by another morph modifier can feed back into the next refresh. This is not a dependency graph or a continuously recalculated formula.

All matching profiles contribute temporary player modifiers. Stable modifier identity derives from profile ID and array index, so identical attribute entries at different indices remain separate contributions. Priority orders resolution; it does not suppress other profiles. Attributes missing from the player are skipped.

Validation

Attribute roots must be objects. Selectors accept a primitive converted to text or an array of text-convertible entries; object/null shapes fail. Use strings deliberately: numeric primitives can become valid-looking identifiers. Invalid phases, operations, required IDs or modifier objects reject the entire profile. Unknown fields are ignored. A failed profile is logged and skipped while the registry is replaced by the successfully parsed set; its previous value is not retained.

An attribute profile requires both a nonempty selector set and a nonempty modifier list. Valid but unmatched forms/tags simply produce no modifiers. Attribute numeric fields have no explicit finite-value or gameplay-range validation.

Power construction rejects invalid category or metadata values and requires the fields marked above. Entity and ability availability is resolved later. A morph needs a living target, free space for its dimensions and a player who is not riding. Returning requires standing-player clearance. A rejected morph execution does not spend its trigger cost or apply its trigger effects. A successful return can use the same energy cost as entry; zero-cost return is not implied.

Entity-specific ability overrides take precedence over authored IDs. The built-in warden and witch overrides choose their respective primary and secondary actions; isekaiexpansion:none in a power does not suppress an installed entity override. Dedicated variants can own a form’s texture and bypass generic morph texture overrides.

Reloading

Attribute profiles reload with server data packs. On a successful reload, online players’ temporary modifiers are refreshed; phase changes, join and respawn also refresh them. Source-attribute changes alone do not trigger a refresh, and the component does not recalculate scaling every tick. Leaving the form removes its applied modifiers.

Power definitions follow the installed power loader. The active morph stores its resolved form and ability IDs; do not assume editing a power rewrites an already running form. Re-enter after reloading when checking changes.

Textures are client resources. Without skin_id, the candidate is assets/isekaiexpansion/textures/morphs/entities/<entity-namespace>/<entity-path>.png; with it, the candidate is assets/isekaiexpansion/textures/morphs/skins/<skin-namespace>/<skin-path>.png. A missing candidate leaves normal renderer texturing in place. Reload client resources after changing PNGs; JSON does not define native form variants.