Gear Stats: MMO_* Item Stats
Grant any of the mod's tracked stats from a plain item Armor or Weapon block - the same native mechanism a vanilla stat like Health already uses, no plugin code needed
The mod registers one native Hytale EntityStat per scalar it tracks, under the MMO_* id prefix. Because these are real EntityStats, any item's Armor or Weapon block can grant them through a StatModifiers entry - the exact same field a vanilla item uses to grant Health or Stamina. Authoring a gear stat needs no AbilityMod, no reward, and no plugin code at all.
Server/Item/Items/<Id>.jsonItem/Items/This is the native Hytale item schema, not an MMOSkillTree-custom asset type - see hytale-shared-source/HytaleAssets/Schema/ for the official codec contract. The MMO_* stat ids themselves are Java-registered (EntityStat definitions, code-only); the item JSON that references them is plain pack content.
Global stats (not skill/school-scoped)
12 ids, none of them tied to a specific skill or damage school.
| Field | Type | Default | Description |
|---|---|---|---|
MMO_Defense | EntityStat | optional | Writer-backed (the skill tree / mastery also write here). |
MMO_CritChance | EntityStat | optional | Writer-backed. |
MMO_CritMultiplier | EntityStat | optional | Base-only (base max 1.5). Raw multiplier scale, not whole-percent - see the convention note below. |
MMO_Lifesteal | EntityStat | optional | Writer-backed. |
MMO_LifestealFlat | EntityStat | optional | Writer-backed. Absolute (raw), not whole-percent. |
MMO_ComboDamage | EntityStat | optional | Writer-backed. |
MMO_ComboDamageFlat | EntityStat | optional | Writer-backed. Absolute (raw). |
MMO_FallDamageReduction | EntityStat | optional | Writer-backed. |
MMO_EffectDuration | EntityStat | optional | Writer-backed. |
MMO_CooldownReduction | EntityStat | optional | Writer-backed. |
MMO_Luck | EntityStat | optional | Writer-backed. |
MMO_BonusXp | EntityStat | optional | Writer-backed. |
Per-school stats
One PERCENT id and one FLAT id per school, all base-only (empty by default until an item grants them). Flat composes into the base before the percent multiply: (base + flat) * (1 + percent).
| Field | Type | Default | Description |
|---|---|---|---|
MMO_Bonus_<School> | EntityStat (percent) | optional | Percent damage bonus against/for that school. |
MMO_BonusFlat_<School> | EntityStat (flat) | optional | Flat damage bonus, composed before the percent multiply. |
Valid <School> values (six): Fire, Ice, Lightning, Water, Arcane, Void. Full ids, e.g. MMO_Bonus_Fire, MMO_BonusFlat_Void. See Damage schools for how an ability's Cause ties into these same six schools.
Per-skill stats
10 channels per skill, registered at runtime for every active skill (built-in or added via custom-skills.json). Id shape is always MMO_<Family>_<SkillId>.
| Field | Type | Default | Description |
|---|---|---|---|
MMO_Damage_<SkillId> | EntityStat | optional | Family Damage. Global sibling: none - always per-skill. |
MMO_DamageFlat_<SkillId> | EntityStat | optional | Family DamageFlat. Global sibling: none - always per-skill. |
MMO_CritChance_<SkillId> | EntityStat | optional | Family CritChance. Global sibling: MMO_CritChance. |
MMO_CritMultiplier_<SkillId> | EntityStat | optional | Family CritMultiplier. Global sibling: MMO_CritMultiplier. |
MMO_Lifesteal_<SkillId> | EntityStat | optional | Family Lifesteal. Global sibling: MMO_Lifesteal. |
MMO_LifestealFlat_<SkillId> | EntityStat | optional | Family LifestealFlat. Global sibling: MMO_LifestealFlat. |
MMO_ComboDamage_<SkillId> | EntityStat | optional | Family ComboDamage. Global sibling: none. |
MMO_ComboDamageFlat_<SkillId> | EntityStat | optional | Family ComboDamageFlat. Global sibling: none. |
MMO_Luck_<SkillId> | EntityStat | optional | Family Luck. Global sibling: MMO_Luck. |
MMO_BonusXp_<SkillId> | EntityStat | optional | Family BonusXp. Global sibling: MMO_BonusXp. |
Example: MMO_Damage_SWORDS, MMO_Luck_MINING, MMO_BonusXp_FISHING. MMO_Damage_<SkillId> scales both plain weapon swings and any ability whose damage resolves to that combat skill (ability XpRouting.Skills first, held-weapon fallback second) - it is not scoped to plain swings only.
The whole-percent-point convention
Every PERCENT-family StatModifiers amount is authored in whole percent points: a +10% bonus is "Amount": 10, never 0.10. This covers every global writer-backed stat, every MMO_Bonus_<School>, and every per-skill PERCENT channel.
"Armor": { "StatModifiers": { "MMO_Bonus_Fire": [ { "Amount": 10, "CalculationType": "Additive" } ] } }| Field | Type | Default | Description |
|---|---|---|---|
MMO_CritMultiplier(_<SkillId>) | exception | optional | Raw multiplier units on the same whole-number scale: 50 = +0.5x added to the 1.5x base. Not a percent-point. |
MMO_*Flat* (any family) | exception | optional | Absolute values, authored exactly like any raw stat - not whole-percent-point. |
Health / Mana / vanilla stats | exception | optional | Stay authored exactly as before this convention existed. |
DamageResistance is a different convention entirely
DamageResistance uses engine fractions (e.g. 0.25 = 25%, CalculationType: "Percent"). Do not apply the whole-percent-point rule to it - that rule is MMO_*-specific.ModifierTarget defaults to Max; CalculationType for StatModifiers is Additive / Multiplicative only (Percent belongs to DamageResistance, a different enum).
The Parent full-object-replace trap
Armor/Weapon is a whole-object replace, not a per-field merge
Armor/Weapon block entirely still inherits the parent's block by reference - but the moment you author Armor/Weapon at all, even to add one line, you must restate the whole object (its existing DamageResistance, StatModifiers, EntityStatsToClear, ...) or you silently drop everything else the parent granted.Real example of the trap avoided (a Weapon_Sword_Steel child item). The vanilla parent's Weapon block (inherited from Template_Weapon_Sword) carries the sword's signature-charge mechanic - the child copies that verbatim and adds one new MMO_Damage_SWORDS line instead of replacing the block outright:
"Weapon": {
"EntityStatsToClear": ["SignatureEnergy"],
"StatModifiers": {
"SignatureEnergy": [ { "Amount": 20, "CalculationType": "Additive" } ],
"MMO_Damage_SWORDS": [ { "Amount": 10, "CalculationType": "Additive" } ]
}
}A pack cannot ship a Parent-inheriting item that partially overrides Armor/Weapon - this is a structural limitation of native Parent inheritance, not a missing MMOSkillTree feature.
Held tools: the one exception
Never a Weapon block on a tool
Weapon block is non-null (source- proven in BlockHarvestUtils.getSpecPowerDamageBlock, no authorable escape). A stat-bearing tool authored the weapon way can never mine hard blocks.A tool instead authors the mod's raw-tag channel, MMO_Tool_Stats, on the item's Tags block:
"Tags": { "MMO_Tool_Stats": [ "MMO_Luck_MINING:10" ] }Entries are "<StatId>:<points>" strings (whole percent points), read while the item is held. Only the MMO_Luck_* and MMO_BonusXp_* channels consume this tag - other stat ids placed in it are inert.
Client tooltips do not auto-row tag stats (that is a StatModifiers-only surface), so a runtime generator (ToolStatDescriptionGenerator) appends a colored +<points>-style stat line into the item's description at runtime. Author flavor prose on the new items.<Id>.description.base key - the item JSON's own Description field still points at the plain items.<Id>.description key. Authoring description directly yourself instead fully overrides the generated value (first-writer-wins; boot packs load before the generator's runtime pack).
{
"TranslationProperties": { "Name": "server.items.Example_Tool_Pickaxe_Fortune.name",
"Description": "server.items.Example_Tool_Pickaxe_Fortune.description" },
"Parent": "Tool_Pickaxe_Iron",
"Tags": { "MMO_Tool_Stats": [ "MMO_Luck_MINING:10" ] },
"Quality": "Uncommon",
"ItemLevel": 20
}The block-tool gate is an id substring match
Tool_Pickaxe_ (or the matching family substring for other tool types) - a case-sensitive id-substring match, no Tags/Categories fallback. In the example above this comes for free from the Tool_Pickaxe_Iron parent id.MMO_Weapon_Type: a different tag entirely
MMO_Tool_Stats grants stat bonuses. A separate tag, MMO_Weapon_Type, does the opposite job for weapons: it does not grant any stat, it only routes combat XP to a skill when a custom weapon's item id does not match any xp-maps.json pattern for its family.
"Tags": { "MMO_Weapon_Type": [ "SWORDS" ] }Full field reference, matching rules, and troubleshooting: see Weapon Skill Tags. Values there are skill ids; the first registered match wins.
Tooltip labels
The closed Hytale client names an item's stat tooltip line via itemTooltip.stats.<StatId> in the client lang namespace (client.lang, not mmoskilltree.lang) - a missing matching key falls back to printing the raw stat id.
- All 12 global
MMO_*stat labels ship inclient.langfor all 9 locales. - Per-skill labels (10 ids per skill, the 10 families times every active skill) are runtime-generated by
StatTooltipLangGeneratorat plugin start and on any skill-roster change - a disabled, renamed, or newly-added skill never needs a hand-edited label. - A pack or owner overrides any generated label (or supplies a localized custom-skill name) by shipping its own
client.langwith the same key (boot packs load first, first-writer-wins).
Worked examples
A custom sword
Grants extra sword-skill damage plus a flat fire bonus, on top of the vanilla parent's own block:
{
"TranslationProperties": { "Name": "mypack.items.My_Ember_Blade.name" },
"Parent": "Weapon_Sword_Steel",
"Weapon": {
"EntityStatsToClear": ["SignatureEnergy"],
"StatModifiers": {
"SignatureEnergy": [ { "Amount": 20, "CalculationType": "Additive" } ],
"MMO_Damage_SWORDS": [ { "Amount": 12, "CalculationType": "Additive" } ],
"MMO_BonusFlat_Fire": [ { "Amount": 5, "CalculationType": "Additive" } ]
}
},
"Quality": "Rare",
"ItemLevel": 45
}A custom armor piece
Grants a defense bonus and a whole-percent lifesteal bonus:
{
"TranslationProperties": { "Name": "mypack.items.My_Vampiric_Chestplate.name" },
"Parent": "Armor_Chest_Iron",
"Armor": {
"StatModifiers": {
"MMO_Defense": [ { "Amount": 5, "CalculationType": "Additive" } ],
"MMO_Lifesteal": [ { "Amount": 3, "CalculationType": "Additive" } ]
}
},
"Quality": "Epic",
"ItemLevel": 55
}A custom tool
Grants bonus mining luck via the tag channel - never a Weapon block, which would zero its mining power:
{
"TranslationProperties": { "Name": "mypack.items.My_Lucky_Pickaxe.name",
"Description": "mypack.items.My_Lucky_Pickaxe.description" },
"Parent": "Tool_Pickaxe_Steel",
"Tags": { "MMO_Tool_Stats": [ "MMO_Luck_MINING:15", "MMO_BonusXp_MINING:10" ] },
"Quality": "Rare",
"ItemLevel": 40
}