← LegendQuest ReForged

Write your own content

Races, classes, skills and feats are all data. Two front doors, one schema: YAML for server owners at config/legendquest/, JSON for datapacks and mods at data/<pack>/legendquest/.

The restart rule, before anything else. Races, classes, skills and feats are frozen registries - like vanilla enchantments, they load once when the world starts. /reload refreshes item tags and messages.yml only, so content changes need a server restart. Ops get a chat notice saying exactly this when someone reloads. The classic symptom of forgetting: your edit "did nothing".

A YAML file with a built-in entry's name overrides it - the whole file replaces the entry, so copy the original and edit rather than writing a fragment. YAML registers as legendquest:<name>; JSON registers as <pack>:<name>.

All times everywhere are milliseconds (1000 = 1s), as in every original LegendQuest doc. cooldown: 6 is six thousandths of a second, and the panel will cheerfully show you a skill with no cooldown.

Races

A self-contained race.

name: Dwarf
plural: Dwarves
chat_tag: "[Dw]"
description: "Stone remembers them."
size: 1.4
base_health: 24
base_mana: 6
mana_per_second: 0.6
base_speed: 0.18
statmods:
  con: 2
  chr: -1
groups:
  - Humanoid
  - Stout
  - Dwarven
skill_points: 10
skill_points_per_level: 0.2
allow_enchanting: false
disallowed_weapons: ["#legendquest:mage_weapons"]
attributes:
  minecraft:armor_toughness: { base: 1.0, per_level: 0.05 }
smith_refund: 0.2
skills:
  legendquest:stone_skin:
    level: 8
levels:
  10: { hp: 2 }
  25: { con: 1 }
The Dwarf race page in the in-game Players Handbook
That file, as players read it. The handbook page is generated from the data - nothing to write twice.
Field Default Meaning
name (required) Display name.
plural (none) "Dwarves", for text that needs it.
chat_tag (none) Short tag for chat prefixes.
description (none) One-liner for pickers and tooltips.
long_description (none) The handbook page's second paragraph.
size 1.8 Visual scale in blocks of height - 1.8 is a vanilla player. Hobbits are 1.1.
base_health 20.0 Max health before class and level bonuses.
base_mana 10.0 Mana pool before class bonuses.
mana_per_second 1.0 Regen.
base_speed 0.2 Old-scale walking speed: 0.2 is normal, 0.4 twice as fast.
statmods all 0 str / dex / con / int / wis / chr adjustments to the rolled statline.
groups [] Trait groups (Arcane, Wild, Stout, …) - free-form strings that class allowed_groups and feat gates match against.
frequency 100 Relative population weight. Parsed, consumed by nothing yet - reserved for future NPC population rolls.
default false The starting race players hold before choosing. Exactly one race should say so.
perm (none) Permission node that locks this entry, LuckPerms-friendly.
allow_crafting … allow_taming true Station gates - six booleans. A deny from any source wins.
allowed_weapons … disallowed_armour (no statement) Proficiencies - see Gear below.
skills {} What this race teaches - see Granting skills.
skill_points 0 Starting skill points.
skill_points_per_level 0 Fractional accrual is fine: 0.25 is one point every 4 levels.
levels {} Milestone rewards - see Level rewards.
xp_adjust_kill / _mine / _smelt 0 Percentage tweak to class XP from that source; race and class adjustments sum.
attributes, enchant_rebate, smith_refund, gold_tool_mana - Boons - see below.

Classes

Growth, and who may take it.

Classes share the race schema's identity, statmods, gear rules, skills, levels and boons, and add growth (how the class scales the race's base numbers) and eligibility (who may take it, and whether it sits in the main or sub slot).

name: Warlord
description: "Somebody has to point the sword."
health_mod: 4
health_per_level: 0.5
mana_bonus: 0
statmods: { str: 1, chr: 1 }
allowed_groups: [Humanoid]
requires_one: [legendquest:fighter, legendquest:ranger]
main_only: true
skills:
  legendquest:rally:
    level: 5

Stat modifiers from main and sub class combine by the original plugin's rule, kept for balance continuity: same sign, the larger magnitude wins; opposite signs, they sum.

Field Default Meaning
health_mod 0 Flat health on top of the race's base.
health_per_level 0 Health growth per character level.
mana_bonus 0 Flat mana on top of the race's pool.
mana_per_level 0 Mana growth per level.
mana_per_second 0 Extra regen, added to the race's.
speed_mod 0 Added to the race's base_speed.
allowed_races [] Explicit race ids that may take this class.
allowed_groups [] Trait groups that may. Either list matching opens the door; both empty = open to all.
requires [] Classes that must ALL be mastered (max level) first.
requires_one [] Classes of which ANY ONE mastered suffices.
main_only / sub_only false Restrict which slot the class may occupy.
default false The starting class (Citizen).
titles {} Rank names by level - see below.

Titled ranks

A class can name what a character is called at a given level, as distinct from what they can do. A key is the level a title starts at, and it holds until the next one up:

"titles": {
  "1": "Squire",
  "25": "Man-at-Arms",
  "50": "Knight",
  "100": "Champion",
  "140": "Lord"
}

A blank title is treated as no title, which is how a class opts out of the bottom band - "Squire" is worth having, "Level 1 Citizen" is not. Titles feed the nameplate ({title}) and, where Standards is installed, decorate chat too - entirely optional, and everything above works exactly the same without it.

Skills

Purely data. Behaviour comes from composed effects.

A skill's effects list runs in order, and each entry picks its own target.

name: Blink
description: "Elsewhere, immediately."
icon: minecraft:ender_pearl
type: active
cooldown: 6000
mana_cost: 5
effects:
  - { type: "legendquest:teleport", max_range: 24 }
A skill's handbook page showing cost, cooldown and what it does
Cost, cooldown and effects are all read back out of the data, so a skill explains itself.
Field Default Meaning
name (required) Display name.
description (none) Tooltip and handbook text.
icon minecraft:enchanted_book Item id drawn in the panel and HUD. A plain string on purpose: a typo'd icon falls back to the book instead of failing the world load.
type active active (player fires it), passive (always on, re-applied on a tick), triggered (fires from combat events).
buildup 0 ms of wind-up before the effects land - telegraphed casting.
delay 0 ms between buildup and landing.
duration 0 ms the skill counts as active (drives the HUD's green to amber to red bar and the 5-second fade warning).
cooldown 0 ms after that before it is ready again. Phases run READY, BUILDING, DELAYED, ACTIVE, COOLDOWN.
mana_cost 0 Mana per use.
karma_cost 0 Karma spent per use.
karma_required 0 Positive: karma must be at least this. Negative: must be at least this evil.
karma_reward 0 Karma granted on use - casting Darkness should probably cost your soul something.
consumes / consumes_qty (none) / 1 An item eaten per use.
xp 0 Class XP awarded on a successful use.
trigger (none) For triggered skills - see below.
passive_interval 3000 ms between re-applications of a passive's effects.
effects [] The list that IS the skill.

Triggers: trigger: { on: melee_hit, chance: 25.0 }. on is one of melee_hit (you land a hit; trigger target is the victim), hurt (you take damage; target is the attacker), kill (target is the victim), or fall (landing, before damage applies). chance is a percentage, default 100.

Targets

Who or where an effect lands.

Most effects take a target block, with a sensible per-effect default so simple YAML stays simple.

Kind Meaning
self The caster.
looking_at The living entity in the crosshair, within range (default 16).
nearby Every living entity within radius (default 4) of the caster, not the caster.
trigger The other party of the trigger event - the mob you hit, the thing that hurt you.
party The caster AND party members within range, defaulting to the party XP-share range, so songs and blessings reach exactly as far as shared glory does. No party = just the caster.

Effects

The 14 built-in effect types.

Compose freely. New types come from skill-pack mods - see writing a skill pack.

Effect Options
legendquest:damage amount (required), target (default looking_at). Magic damage.
legendquest:heal amount (required), target (default self). Hearts and heart particles.
legendquest:potion_effect effect (required), duration (ms, default 5000), amplifier (0), particles (true - set false on always-on passives, nobody wants to live in a lava lamp), show_icon (true), target (self). The workhorse for auras, hexes, songs and passives.
legendquest:leap power (1.5), lift (0.6). Launch the caster along their look.
legendquest:teleport max_range (32). Blink to the looked-at block, with portal particles and the enderman noise.
legendquest:lightning visual_only (false - true is all flash, no damage), target (looking_at).
legendquest:summon entity (required), count (1), target (looking_at).
legendquest:message text (required), action_bar (true; false = chat). & colours supported.
legendquest:ignite duration (ms, 5000), target (looking_at).
legendquest:give_item item (required), count (1). Overflow drops at the caster's feet.
legendquest:sound sound (required), volume (1.0), pitch (1.0), stop_after (ms, 0 = let it ring). stop_after exists because a music disc outlives any skill by minutes - the Bard's Battle Hymn plays Pigstep with stop_after matching its duration, and the cut is a vanilla stop-sound packet, so it works on vanilla clients too.
legendquest:particle_line particle (minecraft:end_rod), per_block (density, 4), target (looking_at). The visual language of "I cast a thing at you".
legendquest:projectile entity (required), speed (1.5), power (1, fireballs only). Fireballs get their real constructors; anything else spawns with speed as straight velocity.
legendquest:run_command command (required), undo_command (none), duration (ms until the undo runs). The old permskills, modernised: run any command under LegendQuest's costs and cooldowns. Runs as the caster with gamemaster permission, output silenced; %player% expands to their name. Temp flight is exactly command + undo_command + duration.

The shared parts

Grants, level rewards, gear and boons.

Granting skills

Races, classes and feats all grant skills the same way - a map from skill id to the terms of the grant: level (default 0), cost in skill points (default 0 = automatic), and an optional karma_min / karma_max soul band.

skills:
  legendquest:holy_light:
    level: 12       # character level required
    cost: 0         # skill points to buy; 0 = free at level
    karma_min: 50   # only the good may hold the light...
  legendquest:darkness:
    level: 12
    karma_max: -50  # ...and only the wicked may quench it.

Karma bands make paired good/evil choices real: grant both sides to one class and each character can only ever hold one. Drifting out of a band suspends the skill - greyed with a purple [soul] note, unusable, skipped when cycling the loadout - rather than refunding it. Redemption and corruption both do exactly what they say, in both directions.

Level rewards

Milestone bonuses, cumulative up to the player's current level. Keys are levels; values are what arrives. hp, mana, sp (skill points), manaregen and stats: { str: … } all work.

levels:
  10: { hp: 5 }
  50: { dex: 1, hp: 5 }
  100: { hp: 5, mana: 5, sp: 5, manaregen: 2.5 }

Boons

The balancing weights behind flavourful restrictions - innate perks a race, class or feat grants just by being what it is. Race and class boons stack additively.

attributes:
  minecraft:armor_toughness: { base: 1.0, per_level: 0.05 }
  minecraft:luck: { base: 0.5 }
enchant_rebate: 1      # XP levels handed back after enchanting
smith_refund: 0.2      # chance to recover a material when crafting gear
gold_tool_mana: 0.5    # golden tools harvest like netherite, per-block mana cost

attributes takes any attribute id, including other mods', with a flat base and an optional per_level ramp. Ids are deliberately not codec-validated: a typo costs you the boon, not the world load.

Gear and stations

Six fields control proficiency: allowed_weapons, disallowed_weapons, allowed_tools, disallowed_tools, allowed_armour, disallowed_armour.

allowed_weapons: "#legendquest:mage_weapons"            # tag form: ONE string
allowed_tools: ["minecraft:bow", "minecraft:crossbow"]  # list form: ids only

A tag is only legal in the bare string form. Each field takes either a single item tag as a string or a list of item ids - a tag inside a list fails registry load, because vanilla's registry-list codec rejects it. Need a tag plus extra ids? Make a datapack item tag that includes both (tags may contain other tags) and reference that.

The semantics are the original plugin's, worth restating because they are subtle:

  • An absent allowed list is no statement - nothing is restricted by it.
  • If any source (race, main class, sub class, feat) makes a statement for a slot, the union of statements becomes the allowlist and everything else on the master list is denied.
  • disallowed_* always wins, even against another source's allow.
  • Only items on the proficiency master lists are ever checked - stone and iron tools stay open to everyone, and clutter never fumbles.

Getting it wrong hurts, never confiscates: wrong weapons hit like fists (fumble), wrong tools dig slow, wrong armour slows and tires. Stations are six booleans, all defaulting to true - allow_crafting, allow_smelting, allow_brewing, allow_enchanting, allow_repairing, allow_taming. A deny from any source wins, and the handbook prints barred stations on every race and class page.

Feats

A purchasable bundle of character.

Bought with skill points, and it reuses every engine above - boons for passives, gear rules for proficiencies, skill grants for actives. One file can say "+1 toughness", "may wear heavy armour" or "learns Blink", or all three, with zero new code. This is what makes two level-10 elf fighters different people.

name: Toughness
description: "Hard to put down."
icon: minecraft:shield
cost: 8
level: 5
requires: [legendquest:battle_hardened]
allowed_groups: [Humanoid]
attributes:
  minecraft:max_health: { base: 4 }
Field Default Meaning
name (required) Display name.
description (none) Handbook prose.
icon minecraft:nether_star Panel and handbook icon.
cost 5 Skill points.
level 0 Minimum character level.
karma_min / karma_max (unbounded) Soul band; drifting out suspends the feat's benefits, exactly like skill grants.
requires [] Feat chain - all listed feats must be owned first.
allowed_races / allowed_groups / allowed_classes [] Eligibility; empty = everyone.
attributes / enchant_rebate / smith_refund / gold_tool_mana - Boons.
skills {} Skill grants.
allowed_* / disallowed_* (no statement) Gear proficiencies.

Traps worth knowing about

The five that cost an afternoon.

Content needs a restart; text does not

Registries freeze at world load. /reload covers item tags and messages.yml only. The classic symptom of forgetting is that your YAML edit "did nothing".

A parse error can pass the server and still kill the client

A registry parse error can boot the server fine and then fail the client's world load. If a fresh entry crashes people on join, suspect the newest data file, not the network.

A tag cannot go inside a list

Gear proficiency fields take either one tag as a bare string or a list of plain ids. A tag inside a list fails registry load. The README example was wrong about this once.

Bare-string particles only work for simple particles

minecraft:dust and friends carry options and need vanilla's object form.

Some fields are codec-validated and some are not

consumes, effect, entity, item and sound ARE validated - a typo fails the entry at load. icon and boon attributes deliberately are not, and fail soft.

Milliseconds, everywhere

cooldown: 6 is six thousandths of a second, and the panel will cheerfully show you a skill with no cooldown.

Packing a datapack ZIP? pack.mcmeta and data/ must sit at the zip root. Wrap them in a folder and Minecraft ignores the pack with no error and no log line at all.