Bonus Drops
The lucky find in a broken block and the extra a killed mob is worth
Overview
A bonus drop is something extra a moment hands over on top of whatever the game already gives for it: the lucky find in a broken block, the bonus a killed mob is worth. New in 1.6.0: one table answers for both, because the question is the same either way - which row covers this name, how likely is the moment, and what does it hand over.
Nothing here replaces vanilla loot. A block still drops what it drops and a mob still drops what it drops; a bonus row spills its own reward beside that, at the broken block or at the corpse. A game update that re-tunes the base tables re-tunes them underneath you and your bonus keeps working.
mods/mmoskilltree/bonus-drops.jsonShipped rows live in the jar and content packs ship theirs under Server/MMOSkillTree/BonusDrops/*.json. The owner file overrides any of them by name, one field at a time.
Replaces luck-loot.json and mob-drops.json
bonus-drops.json on the first start after upgrading, with every override carried across and the old files backed up. See What happens when you upgrade.What a row looks like
A row is one file, and the filename is its name (its id). A pack ships rows at Server/MMOSkillTree/BonusDrops/<Name>.json; a server owner writes the same body into bonus-drops.json under that name.
// Server/MMOSkillTree/BonusDrops/Dragon_Hoard.json
{
"When": { "Kind": "KillMob", "Match": "*Dragon*" },
"Chance": {
"Base": 5.0,
"Factors": [ { "Factor": "hytale:stat", "Param": "MMO_Luck", "Weight": 0.2 } ],
"Clamp": { "Min": 0.0, "Max": 20.0 }
},
"Loot": { "Rolls": [ { "Grants": { "DropLists": [ "My_Dragon_Hoard" ] } } ] },
"Notify": { "Enabled": true }
}| Field | Type | Default | Description |
|---|---|---|---|
When.Kind | - | optional | Which moment the row answers for: BreakBlock when a player breaks a block, KillMob when a player kills a mob. A row naming no moment never fires and is named in the content audit. |
When.Match | - | optional | Which block or mob, as a name pattern (see Name patterns). Leave it out to cover everything in that moment. |
Chance | - | optional | Whether the bonus moment fires at all, as a percent formula. Optional; each moment has its own default (see The odds). |
Loot | - | optional | What the moment hands over: Lootables (shared table names), Rolls written inline, or both. A roll's Grants takes Items, DropLists (native item drop lists), Commands and Rewards. |
Notify | - | optional | The on-screen note when a bonus actually lands. Off unless the row asks for it, on both moments. See Telling the player. |
Enabled | - | optional | false takes the row out of the table entirely. |
The four things a roll can hand over
DropListsspills a native item drop list where the moment happened, exactly the way the base game spills its own loot.Itemshands named items over, for an exact stack rather than a rolled table.Commandsruns console commands. Placeholders name what the moment knows:{player}and{block}on a break row,{player},{mob}and{tier}on a kill row.{tier}resolves empty unless a companion mod attributes a rarity to the kill; the optional MMO Mob Scaling companion mod does, so with it installed a scaled kill's{tier}reads the mob's rarity (such asLegendary) and an unscaled kill's stays empty. A drop chance that weighs the mob is still written through its factors (see Reading what another mod knows), not this placeholder.Rewardspays the player through the shared reward vocabulary (XP, currency, an item, a boost token, and anything another installed mod contributes).
Each roll inside Loot carries its own Chance and Conditions too, so one row can hold a common drop and a rare one side by side.
Only a player's kill counts
KillMob row.Name patterns
When.Match speaks the same name grammar the per-world Where block and a dialogue world scope speak, so a pattern means one thing everywhere. Case is ignored.
| Pattern | Matches | Reads as |
|---|---|---|
Ore_Coal | Ore_Coal and nothing else | exactly |
Ore_* | Ore_Coal, Ore_Iron_Basalt | starting with |
*_Cracked | Ore_Iron_Basalt_Cracked | ending with |
*Trork* | Trork, Trork_Chieftain, Zone1_Trork_Bruiser | anywhere in the name |
* | everything in that moment | the catch-all |
Where several rows match one name, the row pinning down the most characters wins: an exact pattern first, then the longest literal core, then the bare *. So *Trork* covers the family while a second row naming *Trork_Chieftain* takes over for that one mob, and neither file has to know about the other. Two equally specific patterns keep the first one folded. Anything more selective than a name belongs in a roll's own Conditions, never in the pattern.
The odds
Chance is a percent formula: a Base plus each factor's reading multiplied by its Weight, held inside an optional Clamp. Every number is a whole percent point.
"Chance": {
"Base": 2.0,
"Factors": [ { "Factor": "hytale:stat", "Param": "MMO_Luck", "Weight": 0.2 } ],
"Clamp": { "Min": 0.0, "Max": 6.0 }
}That reads as: 2% to start, rising with the killer's own Luck, never past 6%. Use MMO_Luck_MINING (or any other skill) as the Param to read a single skill's luck instead, and drop the Factors list entirely for a flat chance.
What an unwritten Chance means
Each moment carries its own default, so the two read the way an author expects:
| Moment | A row with no Chance |
|---|---|
BreakBlock | is as likely as the player's own summed luck - the MMO_Luck and MMO_Luck_<SKILL> channels the skill tree, mastery, gear and item enhancements all feed |
KillMob | always fires, leaving the odds entirely to the rolls inside it |
Reading what another mod knows
A chance formula (and a roll's Conditions) can weigh anything the installed mods publish. With the optional MMO Mob Scaling companion mod installed, five more readings become citable, all about the mob the moment happened to:
| Factor | Reads |
|---|---|
mmomobscaling:mob_rarity_tier | the mob's place on the rarity ladder: 0 for a plain mob, one step per authored tier |
mmomobscaling:mob_rarity | Param is a rarity name; 1 when the mob is exactly that tier, 0 otherwise |
mmomobscaling:mob_affix | Param is an affix name; 1 when the mob carries it, 0 otherwise |
mmomobscaling:mob_difficulty | the mob's frozen difficulty number |
mmomobscaling:region_power | the tracked player power in the region the moment happened in |
{ "When": { "Kind": "KillMob", "Match": "*Trork*" },
"Loot": { "Rolls": [
{ "Conditions": [ { "Factor": "mmomobscaling:mob_rarity_tier", "Min": 2 } ],
"Chance": { "Base": 20.0,
"Factors": [ { "Factor": "mmomobscaling:mob_difficulty", "Weight": 2.0 } ],
"Clamp": { "Max": 60.0 } },
"Grants": { "DropLists": [ "My_Elite_Trork_Hoard" ] } } ] } }On a server without that mod nothing answers those names, so the condition stays shut and a formula term adds zero: one authored file is correct everywhere, with no dependency in either direction. /mmoconfig validate names a reading nothing answers to as a warning, so a typo is visible rather than silent.
A row that hands nothing over is a deliberate hole
Naming a pattern and granting no Loot is how "this one gives nothing" is said. Because the most specific pattern wins, an empty row for *Ore_Iron_Basalt_Cracked* stops a broader *Ore_Iron_* row covering that block, while every other iron variant keeps its bonus.
{ "When": { "Kind": "BreakBlock", "Match": "*Ore_Iron_Basalt_Cracked*" } }That is different from "Enabled": false, which takes the row out of the table entirely and lets the broader pattern cover the block again.
Telling the player
Notify puts a short message on screen when a bonus actually lands. Leave it on for something rare and turn it off for anything frequent, or a bonus stops reading as one.
| Field | Type | Default | Description |
|---|---|---|---|
Enabled | - | optional | Whether the note shows at all. Off unless the row asks. |
Color | - | optional | The note's colour. |
Icon | - | optional | The icon shown beside it. |
TitleKey / SubtitleKey | - | optional | Translation keys, never literal text. Leave them out for the built-in wording. See Localization. |
Re-tuning a shipped row
Name the row in mods/mmoskilltree/bonus-drops.json and write only the parts you want changed; the body merges field by field over the shipped one.
{
"schemaVersion": 1,
"drops": {
"Mmo_Trork_Kill": { "Enabled": false },
"Mmo_Ore_Copper": { "Chance": { "Base": 2.0 } },
"Mmo_Vortex_Charm": "__DISABLED__"
}
}{"Enabled": false}switches a row off without erasing its pattern.- A
Lootblock alone re-tunes what it hands over and leaves everything else as shipped. - The one-word
"__DISABLED__"in place of the whole body is the shorthand for switching one off. - A name nothing ships decodes on its own, so you can also add a brand-new row from this file alone, with no content pack at all.
Precedence is the ordinary one: built-in defaults, then packs, then your owner file.
What ships in the box
A full set of rows ships with the mod, and every one of them is overridable by name:
- Ten ore families (
Mmo_Ore_Copper,Mmo_Ore_Iron,Mmo_Ore_Silver,Mmo_Ore_Gold,Mmo_Ore_Mithril,Mmo_Ore_Cobalt,Mmo_Ore_Thorium,Mmo_Ore_Adamantite,Mmo_Ore_Onyxium,Mmo_Ore_Prisma) - a lucky break hands over one extra ore, with noChanceblock, so the odds are the breaker's own luck. - Four cracked-ore holes (
Mmo_Ore_Iron_Basalt_Cracked,Mmo_Ore_Cobalt_Slate_Cracked,Mmo_Ore_Thorium_Mud_Cracked,Mmo_Ore_Adamantite_Magma_Cracked) - named, granting nothing, so those variants are carved out of their family row. Mmo_Trork_Kill- a luck-scaled kill bonus, enabled by default. A server that wants it off writes{"drops": {"Mmo_Trork_Kill": {"Enabled": false}}}.Mmo_Vortex_Charm- a rare charm from a gem block, with the full chance formula written out.
Each shipped file carries comments that double as the authoring tutorial for its half of the surface, so opening one in the jar is the fastest way to see a working row.
What happens when you upgrade
On the first start after upgrading, luck-loot.json and mob-drops.json are folded into bonus-drops.json automatically:
- Every override is carried across. A row that named a drop still names it, a row that stated its own odds still states them, and a pattern switched off is still switched off.
- Bare keys become anywhere-in-the-name patterns. An old key was a plain substring, so
Trorkis carried across as*Trork*to keep covering exactly what it covered. - One start-up line per converted row names what it became.
- Both old files are backed up, moved into a timestamped
backup/copy rather than deleted, and a row already present inbonus-drops.jsonis never overwritten. - The shipped row ids are all one
Mmo_convention (Mmo_Ore_Adamantite,Mmo_Vortex_Charm,Mmo_Trork_Kill, and the rest). An owner override still keyed by a row's older id is re-filed under the id that row answers to now, before the file fold above even runs, with one start-up line per re-keyed row. If you have also written the current id yourself, that body wins and the older one is left in place with a line naming the clash, so nothing decides between your two versions for you. - The read-only
_reference/defaults-luck-loot.jsonecho retires with them; the built-in luck rows are readable assets in the jar instead.
Packs need re-authoring
Server/MMOSkillTree/LuckLoot/ and Server/MMOSkillTree/MobDrops/ pack folders are gone, along with their LuckLoot and MobDrops pack control keys. A pack ships bonus rows at Server/MMOSkillTree/BonusDrops/ instead. The Migration Converter converts a pack's files for you, and /mmomigrate --action=pack reports what an installed pack still carries.Checking your work
| Command | What it does |
|---|---|
/mmoconfig diff --args=luck | Lists your bonus-drop overrides by name, with the body you actually wrote. drops and all answer the same way. |
/mmoconfig validate | Audits the whole table (see the findings below). |
/mmoconfig export / import | The config key is bonus-drops. Since 1.6.0 It replaced the old luck-loot key. |
/mmoconfig reload | Re-reads the owner file without a restart. |
The audit and the start-up check report:
- a row naming no moment
- an owner body that cannot be read
- a pattern with a wildcard in the middle
- a row-level chance that can never rise off zero
- a factor name nothing answers to
- a row that hands nothing over (as information - it may well be a deliberate hole)
- two rows pinning down the same literal core in one moment
Trimming does not apply here
/mmoconfig trim strips redundant XP overrides only. The bonus-drop owner layer overrides a shipped row field by field rather than restating it whole, so there is nothing redundant for a trim to find.Shipping rows in a content pack
Prefer a content pack: author one file per row under Server/MMOSkillTree/BonusDrops/ inside a pack folder, zip it, and drop the .zip into your server Mods/ folder. Building the zip.
mods/mmoskilltree/bonus-drops.json stays the quick per-server tweak that always wins.
A pack re-tunes another pack's row by re-authoring its name, or by naming a file with a top-level "Parent": "<name>" and restating one field.
Cross-pack composition happens through shared loot tables: a row's Loot.Lootables names a table under Server/ZiggfreedCommon/Lootables/, and a second pack enriches that table by authoring its own with "ContributesTo" pointing at it, never touching your files. Removing that pack removes exactly what it added.
// your pack
{ "When": { "Kind": "BreakBlock", "Match": "*Log_*" },
"Loot": { "Lootables": [ "forest_finds" ] } }
// somebody else's pack, enriching it
{ "ContributesTo": "forest_finds",
"Rolls": [ { "Chance": { "Base": 25.0 },
"Grants": { "Items": [ { "Item": "Ingredient_Resin" } ] } } ] }(Base is a percent, so 25.0 is a one-in-four resin drop; leave the Chance group off entirely for a roll that always fires. The roll shape itself - Conditions, Chance, Grants, Ladder, Cue - is documented once on Shared Schemas.)
Full authoring reference: Content pack asset types and the shared library's content paths. When you only want to retune a single shipped row on your own server, mods/mmoskilltree/bonus-drops.json is the quick-tweak alternative to a pack.
Related
- Mob Drop Commands - the simpler kill-only surface, still separate, consulted first for a kill.
- Skill trees - where a player's luck comes from.
- Elite mobs - what replaced the removed built-in tier system, and how to gate a bonus on it.