Custom Wishes

From DragonMineZ Wiki

Custom wishes change what a dragon grants when it is summoned, entirely with JSON and no Java. Wish JSON lives in two different places, depending on what you are trying to do:

Goal Where Format
Override the wish list of a dragon (Shenron, Porunga or an add-on dragon) on one world. <world save>/dragonminez/wishes/<dragon_id>.json A plain JSON array of wish objects.
Ship a new dragon, or wishes as part of a distributable pack. An add-on pack (folder or .zip) under <game dir>/dragonballs/ A JSON object with dragon and wishes fields.

Both formats use the same wish objects underneath; only the outer wrapper differs. Standard datapacks are not read for dragons or wishes: use an add-on pack instead. For how players summon dragons and pick wishes, see Dragons and Wishes.

How the wish lists are merged

  1. Wish lists from add-on packs are loaded first (one list per dragon).
  2. Every known dragon without a list gets an empty one.
  3. Each file in <world save>/dragonminez/wishes/ then replaces the whole list of the dragon named by its filename.

Base fields of every wish

{
  "type": "attributes",
  "name": "wish.shenron.attributes.name",
  "description": "wish.shenron.attributes.desc",
  "amount": 100
}
Field Type What it does
type String One of the wish types below.
name String Translation key for the wish's display name.
description String Translation key for the wish's description.
repeatable Boolean Optional. Dragons that grant several wishes (Porunga) let a player pick the same wish more than once per summon. Set it to false to allow the wish only once. When it is absent, the wish is repeatable.

Source: Wish.java (base class), WishTypeAdapterFactory.java (mapping from type to class).

Wish types

type Extra fields What it does
item_list_wish items: list of item objects Grants one or more items described as typed item objects (see below). Example: { "type": "item_list_wish", "name": "wish.shenron.senzu.name", "description": "wish.shenron.senzu.desc", "items": [{ "itemType": "generic_item", "itemId": "dragonminez:senzu_bean", "count": 16 }] }
item itemId, count Grants one item stack. Example: { "type": "item", "name": "...", "description": "...", "itemId": "dragonminez:senzu_bean", "count": 16 }
multi_wish items: list of { "a": "<item_id>", "b": <count> } Grants several item stacks. Example: { "type": "multi_wish", "name": "...", "description": "...", "items": [{ "a": "dragonminez:kikono_shard", "b": 32 }, { "a": "minecraft:iron_ingot", "b": 64 }] }
attributes amount Grants amount Attributes, split into Attribute Points and the TP those points would cost the player right now (see Stats and Attributes). The default Power Boost wishes use it. Example: { "type": "attributes", "name": "...", "description": "...", "amount": 100 }
attributepoints amount Grants amount Attribute Points only. Example: { "type": "attributepoints", "name": "...", "description": "...", "amount": 50 }
tps amount Grants a fixed amount of Training Points. Example: { "type": "tps", "name": "...", "description": "...", "amount": 5000 }
skill skill, level Raises a skill to at least level, for example { "type": "skill", "name": "...", "description": "...", "skill": "kaioken", "level": 2 }. Ignored if the player is already at that level.
command commands: string array, where %player% is replaced with the player's name Runs commands. Example: { "type": "command", "name": "...", "description": "...", "commands": ["effect give %player% minecraft:regeneration 60 1"] }
revive maxTargets (default 1) Truly revives up to maxTargets dead players, chosen in the wish screen. See Otherworld.
passivereset None Resets racial passive skill bonuses (Zenkai, Assimilation and Absorption).
recustomize None Opens the character customization screen.
relocatestats None Lets the player redistribute their spent stat points.
changedifficulty None Lets the player pick their story difficulty again.
resetstory None Resets all story quest progress.

item_list_wish is what the default wishes use. Each entry of items is a typed item object, so a wish can also grant enchanted gear, potions or trimmed armor:

{
  "type": "item_list_wish",
  "name": "wish.shenron.strongest.name",
  "description": "wish.shenron.strongest.desc",
  "items": [
    { "itemType": "enchanted_item", "itemId": "minecraft:diamond_sword", "count": 1, "enchantments": { "minecraft:sharpness": 5 } },
    { "itemType": "potion", "itemId": "minecraft:potion", "count": 1, "potion": "minecraft:strong_healing" }
  ]
}

The fields of each item object (generic_item, enchanted_item, enchanted_book, potion, splash_potion, lingering_potion, tipped_arrow, trimmed_armor) are listed on Custom Quests.

Source: the classes under src/main/java/com/dragonminez/common/wish/wishes/, and the dispatch table in WishTypeAdapterFactory.java.

Overriding a dragon's wishes

Drop a file named after the dragon's id in <world save>/dragonminez/wishes/, for example shenron.json or porunga.json. It is a plain array, with no wrapper object:

[
  {
    "type": "item_list_wish",
    "name": "wish.shenron.senzu.name",
    "description": "wish.shenron.senzu.desc",
    "items": [ { "itemType": "generic_item", "itemId": "dragonminez:senzu_bean", "count": 16 } ]
  },
  {
    "type": "attributes",
    "name": "wish.shenron.attributes.name",
    "description": "wish.shenron.attributes.desc",
    "amount": 100
  },
  {
    "type": "revive",
    "name": "wish.shenron.revive.name",
    "description": "wish.shenron.revive.desc",
    "maxTargets": 3
  }
]
The file replaces the whole list This file completely replaces that dragon's wish list; it is not added on top of the add-on pack wishes. If you only want to add one wish and keep the rest, copy the dragon's full existing wish list first and then add yours to it.

If shenron.json or porunga.json don't exist yet, DragonMineZ creates them with the default wish list the first time wishes load, so you always have a working example to start from. Any other filename you create here sets the wish list of that dragon id; it only shows up if a dragon with that id exists (see Adding a new dragon).

Every wish is checked when the file loads: an unknown type or an unknown key is reported in the JSON load report. A file that fails to parse (broken JSON, an invalid item object) is skipped as a whole and reported, so the dragon keeps its add-on pack wishes until you fix it.

Source: WishManager.loadWishes() and loadWishConfig().

Adding a new dragon

A wish override file alone only works for a dragon id that already has a dragon definition (entity, ball set and summon rules). A new dragon, ball set or radar comes from an add-on pack under <game dir>/dragonballs/: a folder or a .zip file with this layout:

<pack_name>/
  definitions/
    dragon.json
    ballset.json
    radar.json
    wishes.json
  assets/
    dragon.json
    ballset.json
    radar.json

Packs are loaded in alphabetical order and merge over the built-in definitions by id: a pack whose dragon.json uses an existing dragon id overrides that dragon's definition. Dragons, ball sets and radars register their entity, blocks and items when the game starts, so new ones need a game restart. See Locating Specific Folders for the full folder map.

Dragon definition

definitions/dragon.json:

{
  "id": "my_dragon",
  "entity_registry_name": "my_dragon",
  "entity_width": 3.0,
  "entity_height": 17.0,
  "dimensions": ["minecraft:overworld"],
  "ball_set": "my_ball_set",
  "wish_screen_id": "my_dragon",
  "wish_count": 1,
  "asset_definition": "my_dragon"
}
Field What it does
id Dragon id.
entity_registry_name Registry name of the dragon entity (dragonminez:<name>). Keep it equal to id: summoning looks the entity up by the dragon id.
entity_width, entity_height Entity size.
dimensions Dimensions the dragon can be summoned in.
ball_set Id of the ball set that summons it.
wish_screen_id Id of the wish list the dragon offers (the dragon value in wishes.json and the filename of a per-world override).
wish_count How many wishes are granted per summon.
asset_definition Optional id of an assets/dragon.json entry (id, renderer_type, model, texture, animation).

Ball set definition

definitions/ballset.json takes these keys: id, dimensions, copies (default 5), spawn_range, summon_radius (how close the other balls must be to the one you right-click), blocks (star number to block registry name), asset_definition, display_name and natural_spawn (optional, default true).

  • A set is complete when every star listed in blocks is placed within summon_radius, so a set doesn't have to have seven balls.
  • With "natural_spawn": false, the set's balls are never scattered around the world (not at world start, not after a wish, not by /dmzdragonballs): they only exist if you hand them out yourself, for example as quest or world boss rewards.

Radar definition

definitions/radar.json takes these keys: id, item_registry_name, dimensions, ball_set, tooltip_key, ranges, recipe_definition, chip_item, cpu_item, chip_model_item, cpu_model_item, asset_definition and display_name. A radar with chip_item and cpu_item and no recipe_definition gets a crafting recipe from those two items. See Dragon Radar for the built-in radar.

Pack wish list

definitions/wishes.json uses a wrapper object. This is the add-on pack format, different from the per-world array format above:

{
  "dragon": "my_dragon",
  "wishes": [
    { "type": "tps", "name": "wish.my_dragon.tps.name", "description": "wish.my_dragon.tps.desc", "amount": 5000 }
  ]
}

Every key in these files is checked against the lists above, and unknown keys are reported in the JSON load report.

Source: DragonBallPackManager.java, DragonDefinition.java, DragonBallSetDefinition.java, DragonRadarDefinition.java, DragonWishRegistry.java.

Translation keys

The convention is wish.<dragon_id>.<wish_key>.name / wish.<dragon_id>.<wish_key>.desc, for example wish.shenron.senzu.name. Add these keys to your en_us.json or to your own language file. Custom translations merge with the Crowdin ones in the same way as for custom races.

Reload and validate

  1. Save your wish override files under <world save>/dragonminez/wishes/, or your add-on pack under <game dir>/dragonballs/.
  2. Validate the JSON syntax (see How to JSON).
  3. For per-world overrides, run /dmzreload wishes (or /dmzreload all); see Reloading and Updating Changes. Wish lists inside add-on packs are read again by the vanilla /reload; run /dmzreload wishes afterwards so the per-world overrides are applied on top again. New dragons, ball sets and radars need a full restart.
  4. Summon the dragon in game and check that the wish list matches what you expect.