Per-World Rules

Scope XP, abilities, combat, and skills per world

Overview

Per-World Rules let a server owner change how MMO Skill Tree behaves in a specific world, matched by world name. A rule can scale or switch off XP, turn off the whole ability layer (and its on-screen HUDs), switch weapon combat to vanilla, and disable specific skills. It is built for a lobby, a story instance, or a dungeon world that should not earn the same XP and bonuses as the open world.

Override configmods/mmoskilltree/world-rules.json

Content packs ship rules under Server/MMOSkillTree/WorldRules/*.json.

defaults<pack<owner

Choosing the Worlds a Rule Applies To

Every rule picks its worlds with a Where block Since 1.6.0. It has three axes, and a rule can use any combination of them:

AxisWhat it takes
MatchA list of world-name patterns. A bare word is an exact world name; a * at the start, the end, or both widens it
GameplayConfigA list of the world's own stable gameplay-config keys. This is the reliable way to catch an instance family, because a live instance world is named with a generated suffix while its config key never changes
ExcludeMatchName patterns, same grammar as Match, that reject a world even when a positive axis matched it. It never matches a world on its own, so a Where carrying only ExcludeMatch matches nothing

The same name grammar bonus drops and dialogue world scopes use:

  • Exact name - "Lobby" matches only the world named Lobby
  • Prefix - a trailing *, e.g. "Dungeon_01_*", matches a whole family of instanced worlds (Dungeon_01_a3f9, Dungeon_01_77b2, etc.)
  • Suffix - a leading *, e.g. "*_Arena", matches any world NAME ENDING in that text
  • Contains - leading AND trailing *, e.g. "*Dungeon*", matches any world name containing that text anywhere
  • Bare "*" - a catch-all default applied to any world with no more specific match
  • No rule - a world that matches nothing is fully unrestricted (full MMO)

Matching is case-insensitive, and * is the only metacharacter (only meaningful at the ends of the pattern). Both axes are scored on one precedence ladder, so two rules pointing at the same world are always ordered. Exact wins outright. Otherwise, among every prefix/suffix/contains rule that matches, the one with the longest literal core wins regardless of which of the three forms it is (a longer suffix core beats a shorter prefix core); ties break toward the more anchored form (prefix, then suffix, then contains). The bare "*" catch-all only applies when no prefix/suffix/contains rule matches, and the built-in unrestricted default applies when nothing matches at all.

The old flat Match string is retired

A rule used to carry a single "Match": "Lobby" string at the top level. That key is no longer read: a rule still carrying it matches no world at all, and gets one start-up warning per rule quoting the old value and printing the replacement to paste. Rewrite "Match": "Lobby" as "Where": { "Match": ["Lobby"] }. Editing and saving that rule from the World Rules admin page also fixes it: the save rewrites a flat Match into Where.Match for you (a bare string becomes a one-element array), so opening a broken rule and saving it again is enough.

Named world selectors are gone too

There is one world vocabulary now, and a Where carries its own patterns. If you wrote "Names": ["<selector>"] anywhere, replace it with the patterns that selector held: "Match": ["default"] for the ordinary world (a bare word is an exact name), "GameplayConfig": ["ForgottenTemple"] for an instance family, or a "Match": ["*Token_*"] pattern for a name-token family. If your main world is not called default, override the rule that names it. /mmomigrate converts this file for you.

Instanced worlds need suffix or contains, not prefix

A generated/instanced world (a raid arena, a per-party dungeon copy) usually carries BOTH a fixed prefix AND a random suffix, e.g. Dungeon_01_a3f9. A prefix-only rule like "Dungeon_01_*" still works there since the prefix is fixed, but a world whose variable part comes FIRST (a random-prefixed, fixed-suffix instance) needs a suffix pattern ("*_Dungeon_01") or a contains pattern to match at all. This was the actual 1.5.1 fix: some instanced-world naming schemes could not be matched by prefix alone.

What a Rule Controls

The gameplay knobs live in one nested Rules block - WHAT applies in the matched worlds, beside the top-level WHERE (Where) and WHETHER (Enabled, the rule's own on/off switch the World Rules admin page toggles). All six are optional and independently composable:

FieldTypeDefaultDescription
XpMultiplier-optionalScales all skill XP gained in the world. 1.0 is unchanged, 0.0 turns XP off entirely, 0.5 halves it, 2.0 doubles it. A negative value is clamped to 0.0.
AbilitiesEnabled-optionalOne combined switch for the whole ability layer. When false, ability casting is blocked silently (the cast item just behaves like a normal item, with no per-keypress nagging) and the ability-cooldown and quest-tracker HUDs are hidden.
CombatBonusesEnabled-optionalThe MMO weapon-combat layer fed by skill-tree nodes and mastery (crit, lifesteal, flat and percent damage, combo finisher, defense and fall reduction). When false, weapon combat runs vanilla in the world (base damage only). Ability casting and XP are untouched.
StatBonusesEnabled1.5.1-optionalIndependent from CombatBonusesEnabled: strips a player's persistent stat modifiers (skill-tree STAT_HEALTH/ STAT_STAMINA/STAT_MANA rewards, mastery stat sacrifices, class passives) on world entry and restores them on exit. Default true. Where CombatBonusesEnabled only affects damage-time math, this affects standing max-HP/stamina/mana and similar persistent grants.
DisabledSkills-optionalSkill ids whose XP is blocked in the world, on top of any globally disabled skills. A deny-list that only restricts further; it can never re-enable a globally disabled skill.
EnabledSkills-optionalAn optional XP allow-list. When non-empty, only these skill ids gain XP in the world and every other skill is treated as disabled. Empty means there is no allow-list.
* required

File Structure

The file is a master switch plus a map of named rules. Each rule is keyed by a name of your choosing (its Where block is what actually picks the worlds):

{
  "schemaVersion": 1,
  "enabled": true,
  "rules": {
    "lobby": {
      "Where": { "Match": ["Lobby"] },
      "Rules": {
        "XpMultiplier": 0.0,
        "AbilitiesEnabled": false,
        "CombatBonusesEnabled": false,
        "StatBonusesEnabled": false
      }
    },
    "dungeons": {
      "Where": { "Match": ["Dungeon_01_*"] },
      "Rules": { "XpMultiplier": 2.0, "DisabledSkills": ["mining", "woodcutting"] }
    },
    "arena_instances": {
      "Where": { "Match": ["*_Arena"], "ExcludeMatch": ["*_Arena_Lobby"] },
      "Rules": {
        "EnabledSkills": ["artillery", "defense"],
        "AbilitiesEnabled": false,
        "CombatBonusesEnabled": false
      }
    },
    "temple": {
      "Where": { "GameplayConfig": ["ForgottenTemple"] },
      "Rules": { "XpMultiplier": 1.5 }
    }
  }
}

The flat 1.5.x spelling still works, with a warning

A rule that still authors the six knobs flat at its top level (the 1.5.x shape, no Rules wrapper) keeps working this release: the server reads the flat leaves and logs one warning per rule naming the nested group to move them into, and where a knob is authored both ways the nested one wins. The Migration Converter and /mmomigrate --action=owner both make the move for you.
  • schemaVersion - Config format version (do not change)
  • enabled - Master kill-switch. When false, every world resolves to the unrestricted default and no rule applies
  • rules - Your named rules, keyed by id

The matching rules for that example: the Lobby world earns no XP, casts no abilities, fights with vanilla weapons, and strips persistent stat bonuses. Any Dungeon_01_ instance world doubles XP but trains neither Mining nor Woodcutting. Any world whose name ENDS in _Arena (matched by the suffix pattern, so it covers generated arena instances regardless of prefix) is a combat sandbox - only Artillery and Defense gain XP, with abilities and combat bonuses off - except the arena lobby, which the exclusion rejects. Any world built from the ForgottenTemple gameplay config earns half again as much XP, however its live instance happens to be named. Every other world is unaffected.

Omitting Fields

Every knob in the Rules block is optional and defaults to the unrestricted value, so a rule only needs to spell out what it changes:

  • XpMultiplier - defaults to 1.0 (unchanged)
  • AbilitiesEnabled - defaults to true
  • CombatBonusesEnabled - defaults to true
  • StatBonusesEnabled - defaults to true
  • DisabledSkills / EnabledSkills - default to empty (no restriction)

Skill ids are case-insensitive and use the internal id, not the display label. The in-game "Block" skill, for example, is defense in config. Disabling a skill blocks only its XP gain in that world; existing levels and unlocks are untouched.

Shipping rules in a content pack

Prefer a content pack: author one file per rule under Server/MMOSkillTree/WorldRules/ inside a pack folder, zip it, and drop the .zip into your server Mods/ folder. Building the zip.

mods/mmoskilltree/world-rules.json stays the quick per-server tweak that always wins.

// Server/MMOSkillTree/WorldRules/Dungeons.json
{
  "Where": { "Match": ["Dungeon_01_*"] },
  "Rules": { "XpMultiplier": 2.0, "DisabledSkills": ["mining", "woodcutting"] }
}

Precedence is the ordinary one: built-in defaults, then packs, then your owner file.

Validation

Run /mmoconfig validate to audit your rules. The world_rules domain flags a blank or duplicate pattern, an unknown id in a disabled or allowed skill list, and a skill listed in both EnabledSkills and DisabledSkills (the deny-list wins in that case). Two more findings cover the Where block itself: a rule matching none of the loaded worlds, and a rule with an exclusion but no positive axis. A clean validate means every world resolves to the rule you intended.

Best Practices

  • Use a Name_* prefix for any world that spawns with a random suffix (instances, raid arenas, generated dungeons) so one rule covers the whole family at once
  • For a pure lobby or hub, set XpMultiplier to 0.0 and both toggles to false so it stays quiet and cosmetic
  • Prefer EnabledSkills over a long DisabledSkills when only a couple of skills should be active - "only Artillery and Defense" is two ids instead of a deny-list of every other skill
  • Toggle enabled to false to disable all per-world rules at once without deleting them, then back on to restore
  • Back up world-rules.json before major changes