Content Types & Merging

What packs can extend, and how pack content combines with the defaults and the server owner's files

How merging works

  • By id, additive. Each content entry has an id. A pack entry with a new id adds content; an entry whose id already exists overrides it. If two packs define the same id, the last-loaded pack wins.
  • The server owner always wins. Content the owner authored locally (their own files under mods/mmoskilltree/) is never overridden or dropped by a pack.
  • Defaults < pack < owner. Packs override the plugin's built-in defaults, but not the owner's explicit customizations.

Add vs. replace (the Control file)

By default a pack adds to existing content. To make a pack replace the built-in defaults for a content type (e.g. a total-conversion quest pack), include a control file at Server/MMOSkillTree/Control/<YourPackName>.json:

{
  "Name": "MyMmoPack",
  "Quests": "replace",
  "Achievements": "add"
}

replace drops the plugin's default content for that type and uses the pack's instead, but the server owner's own authored content is still kept and still wins. The Name must match your manifest Name.

Valid type keys (PascalCase, like all asset JSON keys): Quests, Achievements, XpMaps, MobKillXp, LuckLoot, ItemRequirements, ActionRequirements, BoostTemplates, Masteries, Currencies, CommandRewards, Classes, UIThemes, BountyBoards, ShopEntries, ShopPools, Shops, ShopTemplates, Dialogues, QuestGivers, Abilities, PowerLevel. If your pack ships templates, also add the matching template store (MasteryTemplates, QuestTemplates, AchievementTemplates, CommandRewardTemplates, ClassTemplates, DialogueTemplates) as "add". Ability Mods (AbilityMods/) have no dedicated Control key - a pack simply ships the folder.

Feature gating (requiresFeatures)

Quests and achievements can declare a dependency on one or more server features. When any listed feature is disabled, the entry is hidden everywhere - it does not appear in the UI, accrues no progress, and cannot be claimed. Re-enable the feature (config flip + server restart) and the entry returns.

{
  "Name": "mastery_tithe",
  "Payload": {
    "id": "mastery_tithe",
    "displayName": "Mastery Tithe",
    "requiresFeatures": ["mastery"],
    "objectives": [ { "id": "kill", "type": "KILL_ENTITY", "target": "*", "amount": 10 } ],
    "rewards":   [ { "type": "CURRENCY", "currencyId": "mastery_point", "amount": 1 } ]
  }
}
Feature idGates on
masteryMastery system enabled
abilities (alias active_abilities)Active abilities enabled
currency (alias currencies)Currency system enabled
xp_tokens (alias tokens)XP tokens enabled
command_rewardsCommand rewards enabled
item_requirementsItem requirements enabled
action_requirementsAction requirements enabled
bounty (alias bounties)Bounty Board enabled and at least one board loaded
shop (aliases tokenshop, token_shop)Token Shop enabled and stocked
spawn_hub (aliases hubnpc, hub_npc)Adventurer's Guide hub NPC enabled
questgivers (alias quest_givers)Quest-giver NPC roles enabled and at least one defined
taming (alias tamework)Taming integration active (Alec's Animal Husbandry)

No elite_mobs feature id

The built-in Elite Mobs system was removed in 1.5.0, and elite_mobs/elites is not a registered feature id - authoring requiresFeatures: ["elite_mobs"]fails closed (unknown id, entry hidden forever, a one-time startup warning). Open-world mob difficulty now comes from the optional companion mod MMO Mob Scaling, configured separately and not reachable through this gate.
  • Lenient parse. Either a bare string ("mastery") or an array is accepted.
  • AND-combined. When multiple ids are listed, the entry is hidden if any one is off.
  • Templates inherit. A template's requiresFeatures applies to every entry that extends it; a concrete entry can override it (or set [] to ungate).
  • Unknown ids fail closed. An unrecognized feature id hides the entry and logs a one-time Unknown feature id warning at server start.

File formats

All content lives under Server/MMOSkillTree/<Type>/. Files may be nested in subfolders freely. Two payload styles are used.

Per-entry "payload" types

One file per entry; the asset key is derived from the filename (e.g. dragon_hunt.json dragon_hunt), and the top-level Name field echoes that key. Payload is the entry as a nested JSON object.

TypeFolderPayloadDocs
QuestsQuests/A single quest objectQuests config
AchievementsAchievements/A single achievement objectAchievements
MasteriesMasteries/A single mastery-track objectMasteries
CurrenciesCurrencies/A single currency-definition objectbelow
Abilities (1.6.0)Abilities/A single ability definition (Identity / Cooldown / Cost / Effects / Presentation / ...)Ability authoring
Ability Mods (1.6.0)AbilityMods/A grantable improvement to an existing ability (TargetAbility + Modifiers)Ability Mods
Power Level (1.5.0)PowerLevel/Formula-tuning for the power-level pillars/clamp/modes consumed by MMO Mob ScalingPower Level
Bounty boardsBountyBoards/A single bounty-board definition (rotation pool + accept gates)Bounty Board
Shop entriesShopEntries/A single shop offer (cost + unified reward payout)Shop
Shop poolsShopPools/A single rotating shop poolShop
ShopsShops/A single shop / board definitionShop
DialoguesDialogues/A single branching NPC dialogue tree, attached to a quest giver by idDialogues
Quest giversQuestGivers/A single quest-giver NPC role: spawn placement, appearance, and the dialogue it attachesQuest Givers
Classes (Future)Classes/A single class-definition objectbelow
UI Themes (Future)UIThemes/A theme palette + per-class accents + optional template overrides-

Dialogues and quest givers are independent - a pack can ship a QuestGiver that falls back to the plain NPC quest list with no custom Dialogue, or a Dialogue attached from spawn-hub.json instead of a quest giver.

Ability precedence (unique to this type)

Abilities are the one content type with a full three-layer fold, all through the SAME codec:

defaults<pack<owner
  1. Defaults - the 91 jar-shipped abilities at Server/MMOSkillTree/Abilities/*.json.
  2. Pack - a pack file at the same path with a matching id overrides the default entirely, unless it uses Parent to overlay just a few fields.
  3. Owner - mods/mmoskilltree/ability-overrides.json folds last, per-leaf (the same overlay semantics as Parent: overriding one field never nulls out the rest).

abilities.json is retired

The legacy JSON-blob override format at mods/mmoskilltree/abilities.json was a hard break in 1.6.0. Any file found there at startup is moved to mods/mmoskilltree/backup/ with a warning and never read again. Re-author ability tuning in ability-overrides.json instead - see Ability authoring.
The in-game pack-management view, showing loaded packs and how many entries each contributes per content type.
The in-game pack-management view, showing loaded packs and how many entries each contributes per content type.

Per-pack "map" types

One file per pack; Name is your pack name and Payload is the config's natural map.

TypeFolderPayload shapeDocs
XP mapsXpMaps/{ "SKILL": { "pattern": value } }XP Values
Mob-kill XPMobKillXp/{ "MobPattern": value }Mob Kill XP
Luck lootLuckLoot/{ "BlockPattern": "ItemId" }Luck
Item requirementsItemRequirements/{ "ItemPattern": { …override… } }Item Requirements
Action requirementsActionRequirements/{ "blockTool": {…}, "mobWeapon": {…} }Item Requirements
Boost templatesBoostTemplates/{ "templateId": { "multiplier": … } }XP Boosts
Command rewardsCommandRewards/{ "<SKILL|TOTAL|GLOBAL_SKILL>": { "<level>": [ … ] } }Command Rewards
// Server/MMOSkillTree/XpMaps/MyMmoPack.json
{
  "Name": "MyMmoPack",
  "Payload": { "MINING": { "Ore_Adamantite": 25.0 } }
}

Masteries

A mastery track targets a skill (skill:MINING) or an ability (ability:fireball) and lists purchasable nodes. Each node has an id, tier, cost (a currency map plus optional raw items and an optional stat sacrifice), and modifiers. Repeatable Eternal nodes set maxPurchases: -1 with costScaling. See the player-facing Mastery guide for how this looks in-game.

// Server/MMOSkillTree/Masteries/Mining_Mastery.json
{
  "Name": "Mining_Mastery",
  "Payload": {
    "target": "skill:MINING",
    "displayName": "Mining Mastery",
    "refundPercent": 50,
    "requirements": { "skillLevels": [ { "skill": "MINING", "level": 5 } ] },
    "nodes": [
      {
        "id": "min_t1", "tier": 1, "displayName": "Mining Mastery I",
        "cost": {
          "combine": "all",
          "currencies": { "mastery_point": 2, "life_essence": 500 },
          "items": [ { "id": "Ingredient_Crystal_Blue", "count": 1 } ]
        },
        "modifiers": [ { "shape": "PERCENT", "key": "lootMultiplier", "value": 0.03, "targetSkill": "MINING" } ]
      },
      {
        "id": "min_eternal", "tier": 9, "displayName": "Mining Mastery: Eternal",
        "maxPurchases": -1,
        "costScaling": { "mode": "EXPONENTIAL", "multiplier": 1.1 },
        "cost": { "combine": "all", "currencies": { "mastery_point": 1, "life_essence": 200 } },
        "modifiers": [ { "shape": "PERCENT", "key": "lootMultiplier", "value": 0.005, "targetSkill": "MINING" } ]
      }
    ]
  }
}

Currencies

Currencies come in two flavors. Counter-backed currencies are a number stored on the player (no inventory item) - set iconItemId for the display icon and leave hytaleItemId unset. Item-backed currencies wrap a real Hytale item - set hytaleItemId to the item id. The currency id is the filename, lowercased. See the player-facing Currencies guide.

// Counter-backed - Server/MMOSkillTree/Currencies/Mastery_Point.json
{
  "Name": "Mastery_Point",
  "Payload": {
    "displayName": "Mastery Points",
    "iconItemId": "Ingredient_Crystal_Purple",
    "color": "#c08aff",
    "cap": 0,
    "showOnSidebar": true,
    "showOnMasteryPage": true
  }
}

// Item-backed - Server/MMOSkillTree/Currencies/Life_Essence.json
{
  "Name": "Life_Essence",
  "Payload": {
    "displayName": "Life Essence",
    "hytaleItemId": "Ingredient_Life_Essence",
    "color": "#a7e0a7",
    "cap": 0
  }
}

Grant currency from quests/achievements (CURRENCY reward), from command rewards, or from the admin command. Always use the named-arg form:

/mmocurrency give --player={player} --currency=mastery_point --amount=1

Classes (Future)

The Class System is a future, unreleased feature; the schema below documents the planned content shape. The plugin ships no built-in classes, and without a class pack the class system stays dormant. A class definition carries base grants applied while the class is selected, plus additive advancements (ranks) unlocked by meeting prerequisites.

FieldTypeNotes
displayName / flavor / description / iconstringUI surface; icon is a Hytale item id.
unlockRequirementsPrerequisiteGroupGate selection (quests, skill levels, total level, achievements, currency). Empty = freely selectable.
switchPolicySwitchPolicyPer-class override of the global switch cost/cooldown.
baseGrantsClassGrantsApplied while the class is selected.
advancementsClassAdvancement[]Additive ranks; grants deep-merge over base.

ClassGrants (used by base and each advancement):

FieldNotes
xpMultipliersmap of skill → multiplier (0.0 = no XP, 1.25 = +25%).
abilityWhitelist / abilityBlacklistGate which abilities are usable. Blacklist always wins.
masteryWhitelist / masteryBlacklistGate mastery purchases (by trackId or trackId:nodeId).
skillRewardWhitelist / skillRewardBlacklistGate skill-tree reward claims.
passiveRewardsSkillRewards applied while the class is active.
startingItems / startingMasteryNodes / classQuestsGranted/unlocked on selection.

SwitchPolicy defaults: firstSwitchFree: true, costCurrencyId: "mastery_points", costAmount: 100, cooldownMs: 24h, escalationMultiplier: 1.0, permanentLock: false. Build classes from a template - see Template Extension.

Export as Pack

The in-game Export as Pack tool generates a correctly-formatted pack from your current server content - the recommended starting point, since it emits valid filenames, Name echoes, and Payload shapes for you. The /mmopacks admin command lists and inspects loaded packs (/mmopacks --action=list); exporting is driven by the Export as Pack tool, not a bare /mmopacks export subcommand.