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.
Gear-granted ability upgrades are a different surface: see Ability authoring: gear grants (the ItemAbilityGrants/ type) for an item that hands a player a whole ability, rather than a stat.
Everything on this page is authored onto an item id, so every copy carries it. To roll stats onto one particular item a player already owns - an anvil ritual, a stamped reward, a rolled drop - see Rolled Stats & Stamping. It draws from the same stat ids catalogued below.
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.
Prefer a content pack: author one file per item under Server/Item/Items/ inside a pack folder, zip it, and drop the .zip into your server Mods/ folder. Building the zip.
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
3 ids per school - two attacker-side ids (PERCENT and FLAT) and one victim-side resist id - 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 for that school, granted attacker-side. |
MMO_BonusFlat_<School> | EntityStat (flat) | optional | Flat damage bonus, composed before the percent multiply, attacker-side. |
MMO_SchoolResist_<School> | EntityStat (percent) | optional | Percent resistance to that school, granted victim-side - whatever grants it (armor, weapon enhancement, mastery) sums on this one channel, and the engine applies the matching resistance while it is worn. |
Valid <School> values (9): Fire, Ice, Lightning, Water, Arcane, Void, Poison, Life, Physical. Full ids, e.g. MMO_Bonus_Fire, MMO_BonusFlat_Void, MMO_SchoolResist_Poison. Poison is the toxin school, an overlay over the vanilla Poison damage cause rather than a mapped essence. Life is the drain and lifesteal school, so gear granting MMO_Bonus_Life scales soul-draining and vampiric hits. Physical is the broadest of the set: it is the school of every plain weapon strike and of any hit that names no school at all, and its resist id also covers the vanilla Slashing, Bludgeoning and Projectile causes that fold into it, so MMO_SchoolResist_Physical is what a general-purpose breastplate wants rather than a per-element channel. See the damage-school roster for the full list and which abilities carry each one.
An armor piece granting native per-school resistance:
"Armor": { "StatModifiers": { "MMO_SchoolResist_Fire": [ { "Amount": 4, "CalculationType": "Additive" } ] } }Ability channels (gear-reachable ability numbers)
7 global, not-per-skill ids fold flat additive bonuses into the SAME per-cast number an ability body's own ParamKeys already compose through - see Ability authoring: numbers for the body-side half of this fold.
| Field | Type | Default | Description |
|---|---|---|---|
MMO_AbilityRange | world units | optional | Flat additive range bonus. Folds onto a body node's distance ParamKey. |
MMO_AbilityRadius | world units | optional | Flat additive radius bonus (a selection or zone geometry: MmoSelect Sphere/Cone, MmoZone.Radius). Folds onto a body node's radius ParamKey. |
MMO_AbilityDamageRadius | world units | optional | Flat additive damage-splash radius bonus (MmoDamage/MmoBeam radius, MmoDash hit radius). Folds onto a body node's damageRadius ParamKey. |
MMO_AbilityDuration | milliseconds | optional | Flat additive duration bonus. Folds onto a body node's durationMs ParamKey. |
MMO_AbilityCostReduction | resource units | optional | Flat cost reduction, subtracted from the ability-level cost; the Cost.json Min: 0 clamp floors the result so it can never refund. Folds onto a body node's cost ParamKey. |
MMO_AbilityIFrames | milliseconds | optional | Flat additive i-frame duration bonus. Folds onto a body node's iframesDurationMs ParamKey. |
MMO_AbilityPierce | pierce count | optional | Flat additive pierce-count bonus. Folds onto a body node's pierceCount ParamKey. |
Every channel ships base Max 0: additive-first authoring only
Multiplicative-only StaticModifier on a base-0 channel folds to 0 * x = 0 and is silently inert - nothing errors, the item just does nothing. Author these as Additive. Each is also capped by the server's own bound under Server/MMOSkillTree/ModifierClamps/, which the owner can tighten further in mods/mmoskilltree/ability-clamps.json, so a stacked pack cannot push a number past what the server intends.A ring granting bonus ability radius:
"Armor": { "StatModifiers": { "MMO_AbilityRadius": [ { "Amount": 1.5, "CalculationType": "Additive" } ] } }Per-skill stats
12 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. |
MMO_CooldownReduction_<SkillId> | EntityStat | optional | Family CooldownReduction. Global sibling: MMO_CooldownReduction. |
MMO_Level_<SkillId> | EntityStat | optional | Family Level - read-only, not gear-grantable. Global sibling: none - read-only, mirrors the skill's own level. |
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. MMO_Level_<SkillId> is the odd one out: it mirrors the skill's own level rather than anything gear can grant, and is what a Requires factor reads to gate on a skill level.
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>, every MMO_SchoolResist_<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. |
Ability channels (MMO_Ability*) | exception | optional | Raw units (world units, milliseconds, resource units, pierce count) - 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.Target defaults to Max (shown in the worked examples below); 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 filled in, with no authorable escape. A stat-bearing tool authored the weapon way can never mine hard blocks.A tool authors its stats as an ordinary native Utility.StatModifiers block instead, with Usable and Compatible left unset (both default to false). That is a stat surface with no side effects, because the engine never applies a utility block for an item that is merely held; the mod applies it while the tool is in hand:
"Utility": {
"StatModifiers": {
"MMO_Luck_MINING": [ { "Amount": 10, "CalculationType": "Additive" } ]
}
}Every stat id on this page works here, with the same whole-percent-point convention as an Armor or Weapon block.
Client tooltips do not auto-row a held tool's utility stats, so the mod generates the stat text into the item's description at runtime, one colored line per additive modifier, and the number lives only in the asset instead of being duplicated into language text. Author your flavor prose on the server.items.<Id>.description.base key; the item JSON's own Description field still points at the plain server.items.<Id>.description key. Author server.items.<Id>.description yourself if you want full manual control: boot packs load before the generated text, and the first writer of a key wins. See Which .lang file does my key go in? for why the prefix is server. here.
{
"TranslationProperties": { "Name": "server.items.Example_Tool_Pickaxe_Fortune.name",
"Description": "server.items.Example_Tool_Pickaxe_Fortune.description" },
"Parent": "Tool_Pickaxe_Iron",
"Utility": {
"StatModifiers": {
"MMO_Luck_MINING": [ { "Target": "Max", "CalculationType": "Additive", "Amount": 10 } ]
}
},
"Quality": "Uncommon",
"ItemLevel": 20
}An offhand or utility-slot accessory is not a held tool
Usable: true uses the same Utility.StatModifiers block, but gets no generated stat lines: the engine applies it natively and the client already rows it in the tooltip's own stats section, so generated lines would print everything twice. Only its .description.base prose is written through, and an accessory without that prose gets no generated description at all.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 tag, not a stat
Everything above grants stat bonuses through a native stats block. A separate raw tag, MMO_Weapon_Type, does a different job for weapons: it grants no stat at all, 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 (12 ids per skill, the 12 families times every active skill) are generated at runtime, at server start and again 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": "server.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, a whole-percent lifesteal bonus, and native Void resistance:
{
"TranslationProperties": { "Name": "server.items.My_Vampiric_Chestplate.name" },
"Parent": "Armor_Chest_Iron",
"Armor": {
"StatModifiers": {
"MMO_Defense": [ { "Amount": 5, "CalculationType": "Additive" } ],
"MMO_Lifesteal": [ { "Amount": 3, "CalculationType": "Additive" } ],
"MMO_SchoolResist_Void": [ { "Amount": 4, "CalculationType": "Additive" } ]
}
},
"Quality": "Epic",
"ItemLevel": 55
}A custom tool
Grants bonus mining luck and bonus mining XP through a utility stats block - never a Weapon block, which would zero its mining power:
{
"TranslationProperties": { "Name": "server.items.My_Lucky_Pickaxe.name",
"Description": "server.items.My_Lucky_Pickaxe.description" },
"Parent": "Tool_Pickaxe_Steel",
"Utility": {
"StatModifiers": {
"MMO_Luck_MINING": [ { "Amount": 15, "CalculationType": "Additive" } ],
"MMO_BonusXp_MINING": [ { "Amount": 10, "CalculationType": "Additive" } ]
}
},
"Quality": "Rare",
"ItemLevel": 40
}