→Common Errors: added invalid json format error to troubleshooting section |
m typo fix |
||
(60 intermediate revisions by 6 users not shown) | |||
Line 3: | Line 3: | ||
This can be used to create custom challenges to play through yourself or share with others. The more details defined in a plandomizer, the less the randomizer interferes, though the randomizer will still verify whether it is beatable based on the logic settings, and if it is logically impossible it will refuse to generate a seed. | This can be used to create custom challenges to play through yourself or share with others. The more details defined in a plandomizer, the less the randomizer interferes, though the randomizer will still verify whether it is beatable based on the logic settings, and if it is logically impossible it will refuse to generate a seed. | ||
There is a [https://ootrandomizer.com/plandoMaker beta GUI for Plandomizer on the website] that can help you with simpler plandomizer ideas, however to truly grasp the power of plandomizer you will have to modify a distribution file yourself. '''''Warning:''' This is a beta feature and frequently generates JSON files with issues that must be fixed in a text editor prior to use. Please visit the | <!--There is a [https://ootrandomizer.com/plandoMaker beta GUI for Plandomizer on the website] that can help you with simpler plandomizer ideas, however to truly grasp the power of plandomizer you will have to modify a distribution file yourself. '''''Warning:''' This is a beta feature and frequently generates JSON files with issues that must be fixed in a text editor prior to use. Please visit the {{discord|plando-support}} channel in the {{discord}} for help resolving these errors. --> | ||
The plandoMaker site is currently not available, so you will have to modify a distribution file yourself. For any confusion, please visit the {{discord|plando-support}} channel in the {{discord}} for help resolving issues. | |||
{{collapsible list code style | |||
|Deliver Letter | |||
|Sell Big Poe | |||
|Milk | |||
|<!--Skull Mask | |||
|Spooky Mask | |||
|Keaton Mask | |||
|Bunny Hood | |||
|Mask of Truth | |||
|Goron Mask | |||
|Zora Mask | |||
|Gerudo Mask | |||
|Zeldas Letter | |||
|Location: HC Zeldas Letter--> | |||
|title=The following items are not assignable, despite appearing in the items lists. Other items may not be assignable depending on the settings chosen.}} | |||
These items and location are used internally by the logic to handle new item locations becoming available. They are not meant to be used in a plando. | |||
== Using a Plandomizer Distribution File on the Generator == | == Using a Plandomizer Distribution File on the Generator == | ||
Line 25: | Line 42: | ||
=== The Dictionary "Terms" === | === The Dictionary "Terms" === | ||
Within the base dictionary there are many terms, such as <samp>:version</samp>, <samp>file_hash</samp>, and <samp>locations</samp>. If you are viewing a spoiler log you'll notice some of these terms start with a <kbd>:</kbd>. These terms are ignored when Plandomizer is used and are autogenerated by the randomizer. When you are creating a distribution file yourself you can delete these terms. | Within the base dictionary there are many terms, such as <samp>:version</samp>, <samp>file_hash</samp>, and <samp>locations</samp>. If you are viewing a spoiler log you'll notice some of these terms start with a <kbd>:</kbd>. These terms are ignored when Plandomizer is used and are autogenerated by the randomizer. When you are creating a distribution file yourself you can delete these terms (or take advantage of this mechanic to put in comments between sections, but note that it cannot be used within {} sections such as Locations or Entrances). | ||
Terms are followed by a <kbd>:</kbd> and then some spaces, then their definitions. | Terms are followed by a <kbd>:</kbd> and then some spaces, then their definitions. | ||
Line 47: | Line 64: | ||
==== Hash Icons ==== | ==== Hash Icons ==== | ||
{{collapsible list code style | |||
|'Deku Stick' | |||
|'Deku Nut' | |||
|'Bow' | |||
|'Slingshot' | |||
|'Fairy Ocarina' | |||
|'Bombchu' | |||
|'Longshot' | |||
|'Boomerang' | |||
|'Lens of Truth' | |||
|'Beans' | |||
|'Megaton Hammer' | |||
|'Bottled Fish' | |||
|'Bottled Milk' | |||
|'Mask of Truth' | |||
|'SOLD OUT' | |||
|'Cucco' | |||
|'Mushroom' | |||
|'Saw' | |||
|'Frog' | |||
|'Master Sword' | |||
|'Mirror Shield' | |||
|'Kokiri Tunic' | |||
|'Hover Boots' | |||
|'Silver Gauntlets' | |||
|'Gold Scale' | |||
|'Stone of Agony' | |||
|'Skull Token' | |||
|'Heart Container' | |||
|'Boss Key' | |||
|'Compass' | |||
|'Map' | |||
|'Big Magic' | |||
|title=Expand to view the full list of valid hash icons for the current version of the randomizer.}} | |||
==== Examples ==== | ==== Examples ==== | ||
'''Set all 5 icons to Deku Nut''': | '''Set all 5 icons to Deku Nut''': | ||
{{json example| | |||
"file_hash": ["Deku Nut", "Deku Nut", "Deku Nut", "Deku Nut", "Deku Nut"] | "file_hash": ["Deku Nut", "Deku Nut", "Deku Nut", "Deku Nut", "Deku Nut"] | ||
}} | |||
'''Set only the first icon to Deku Nut''': | '''Set only the first icon to Deku Nut''': | ||
{{json example| | |||
"file_hash": ["Deku Nut", null, null, null, null] | "file_hash": ["Deku Nut", null, null, null, null] | ||
}} | |||
or | or | ||
{{json example| | |||
"file_hash": ["Deku Nut"] | "file_hash": ["Deku Nut"] | ||
}} | |||
'''Set only the last icon to Deku Nut''': | '''Set only the last icon to Deku Nut''': | ||
{{json example| | |||
"file_hash": [null, null, null, null, "Deku Nut"] | "file_hash": [null, null, null, null, "Deku Nut"] | ||
}} | |||
=== Settings === | === Settings === | ||
Line 124: | Line 139: | ||
==== Examples ==== | ==== Examples ==== | ||
'''Start with full wallet without Max Rupees setting''': | '''Start with full wallet without Max Rupees setting''': | ||
{{json example| | |||
"starting_items": { | "starting_items": { | ||
"Rupees": 99 | "Rupees": 99 | ||
} | } | ||
}} | |||
'''Start with all shields''': | '''Start with all shields''': | ||
{{json example| | |||
"starting_items": { | "starting_items": { | ||
"Deku Shield": 1, | "Deku Shield": 1, | ||
Line 137: | Line 152: | ||
"Mirror Shiled": 1 | "Mirror Shiled": 1 | ||
} | } | ||
}} | |||
'''Please note there are two starting item sections''', this section refers to the one after randomized_settings in a spoiler log. The starting items, starting equipment, and starting songs sections within the settings section have a different format, but as listing what falls under each here would be a long section, please instead generate a spoiler log using the GUI to see where items need to be listed. | |||
'''NOTE''': In current dev versions, the starting items sections have been unified into the one under the settings dictionary. Make sure to place your starting items dictionary inside the settings dictionary for it to work. | |||
=== Item Pool === | === Item Pool === | ||
Line 150: | Line 169: | ||
==== Examples ==== | ==== Examples ==== | ||
'''Set Mirror Shield to have 3 copies placed in the world''': | '''Set Mirror Shield to have 3 copies placed in the world''': | ||
{{json example| | |||
"item_pool": { | "item_pool": { | ||
"Mirror Shield": 3 | "Mirror Shield": 3 | ||
} | } | ||
}} | |||
or | or | ||
{{json example| | |||
"item_pool": { | "item_pool": { | ||
"Mirror Shield": { | "Mirror Shield": { | ||
Line 163: | Line 182: | ||
} | } | ||
} | } | ||
}} | |||
'''Add 3 Deku Shields to place in the world in addition to the ones already in the base pool''': | '''Add 3 Deku Shields to place in the world in addition to the ones already in the base pool''': | ||
{{json example| | |||
"item_pool": { | "item_pool": { | ||
"Deku Shield": { | "Deku Shield": { | ||
Line 173: | Line 192: | ||
} | } | ||
} | } | ||
}} | |||
=== Dungeons === | === Dungeons === | ||
Line 182: | Line 201: | ||
==== Examples ==== | ==== Examples ==== | ||
'''Set only Deku Tree to mq''': | '''Set only Deku Tree to mq''': | ||
{{json example| | |||
"dungeons": { | "dungeons": { | ||
"Deku Tree": "mq" | "Deku Tree": "mq" | ||
} | } | ||
}} | |||
'''Set only Spirit Temple to vanilla, because you don't want to learn the second version of spirit logic''': | '''Set only Spirit Temple to vanilla, because you don't want to learn the second version of spirit logic''': | ||
{{json example| | |||
"dungeons": { | "dungeons": { | ||
"Spirit Temple": "vanilla" | "Spirit Temple": "vanilla" | ||
} | } | ||
}} | |||
'''Set Dodongo's Cavern to random''': | '''Set Dodongo's Cavern to random''': | ||
{{json example| | |||
"dungeons": { | "dungeons": { | ||
"Dodongos Cavern": "random" | "Dodongos Cavern": "random" | ||
} | } | ||
}} | |||
=== Trials === | === Trials === | ||
Line 209: | Line 228: | ||
==== Examples ==== | ==== Examples ==== | ||
'''Set forest, fire, and water trials as inactive''': | '''Set forest, fire, and water trials as inactive''': | ||
{{json example| | |||
"trials": { | "trials": { | ||
"Forest": "inactive", | "Forest": "inactive", | ||
Line 215: | Line 234: | ||
"Water": "inactive" | "Water": "inactive" | ||
} | } | ||
}} | |||
'''Set light trial to active, ensuring that 3 strength upgrades are required for fighting Ganon''': | '''Set light trial to active, ensuring that 3 strength upgrades are required for fighting Ganon''': | ||
{{json example| | |||
"trials": { | "trials": { | ||
"Light": "active" | "Light": "active" | ||
} | } | ||
}} | |||
'''Set water trial to random''': | '''Set water trial to random''': | ||
{{json example| | |||
"trials": { | "trials": { | ||
"Water": "random" | "Water": "random" | ||
} | } | ||
}} | |||
=== Entrances === | === Entrances === | ||
Line 239: | Line 258: | ||
==== Examples ==== | ==== Examples ==== | ||
'''Set Deku Tree entrance to Gerudo Training | '''Set Deku Tree entrance to Gerudo Training Ground''': | ||
{{json example| | |||
"entrances": { | "entrances": { | ||
"Outside Deku Tree -> Deku Tree Lobby": "Gerudo Training | "KF Outside Deku Tree -> Deku Tree Lobby": {"region": "Gerudo Training Ground Lobby", "from": "Gerudo Fortress"} | ||
} | } | ||
}} | |||
'''Set Hyrule Castle exit from Market to Lon Lon Ranch main entrance''': | '''Set Hyrule Castle exit from Market to Lon Lon Ranch main entrance''': | ||
{{json example| | |||
"entrances": { | "entrances": { | ||
" | "Market -> Castle Grounds": { | ||
"region": "Lon Lon Ranch", | "region": "Lon Lon Ranch", | ||
"from": "Hyrule Field" | "from": "Hyrule Field" | ||
} | } | ||
} | } | ||
}} | |||
=== Locations === | === Locations === | ||
This dictionary handles what is probably the main feature of plandomizer. You can assign items to any location in the game world here. Which locations are available are heavily influenced by | This dictionary handles what is probably the main feature of plandomizer. You can assign items to any location in the game world here. Which locations are available are heavily influenced by the settings chosen, so ensure you have the proper settings set. | ||
The term is the name of the location. The definition is either: | The term is the name of the location. The definition is either: | ||
* A string of an item to place there | * A string of an item to place there. | ||
* A list containing multiple items to randomly choose from to place there | * A list containing multiple items to randomly choose from to place there. | ||
* A dictionary containing the term <var>item</var> containing one of the above two bullet points. | * A dictionary containing the term <var>item</var> containing one of the above two bullet points. | ||
** If making a multiworld plandomizer: the term <var>player</var> with the world number value of the player the item belongs to. | ** If making a multiworld plandomizer: the term <var>player</var> with the world number value of the player the item belongs to. | ||
** If the location is a shop: the term <var>price</var> with the rupee number value the item should cost. ''You cannot set scrub prices using plandomizer'' | ** If the location is a shop: the term <var>price</var> with the rupee number value the item should cost. ''You cannot set scrub prices using plandomizer'' | ||
** If the item can be an ice trap: the term <var>model</var> set to a string of the item model it should appear as in the overworld. | ** If the item can be an ice trap: the term <var>model</var> set to a string of the item model it should appear as in the overworld. | ||
Item names can also take advantage of the wildcard <kbd><samp>*</kbd></samp> and the not indicator <kbd><samp>!</kbd></samp>. | |||
For example, this will guarantee Link starts with a medallion, Spirit Temple will always have a stone, and one of the shields can be found in Mido's House. | |||
{{json example| | |||
"locations": { | |||
"Links Pocket": "*Medallion", | |||
"Twinrova": "!*Medallion", | |||
"KF Midos Top Left Chest": "*Shield" | |||
} | |||
}} | |||
==== Shop Location Numbers ==== | ==== Shop Location Numbers ==== | ||
Line 275: | Line 307: | ||
When using 4 items shopsanity, you can now use all 4 numbers 5-8 for all of the left side items. | When using 4 items shopsanity, you can now use all 4 numbers 5-8 for all of the left side items. | ||
==== Shop Location Prices ==== | |||
When defining a shop location, rather than simply assigning a string of the item name to the location, you must define a dictionary with the properties item (a string of the item name) and price (a number). So for example, a shop item location will look something like this: | |||
{{json example| | |||
"KF Shop Item 7": { | |||
"item": "Light Arrows", | |||
"price": 40 | |||
}, | |||
}} | |||
If you try to set a price higher than 999, it will simply be capped to 999 so it won't be impossible to buy. However, you can actually plando negative prices, which will give the player the absolute value of the price. So if you plando a shop item to be -10 rupees, the player will be able to purchase it with any wallet size and it will give them 10 rupees. Due to reasons related to the binary numbers used to represent the prices in-game, the lowest possible price is -32768. | |||
==== Special Item Groups ==== | ==== Special Item Groups ==== | ||
There are shortcut terms you can use for certain items when using plandomizer. They start with the <kbd>#</kbd> character. The ones that should work fine are: | There are shortcut terms you can use for certain items when using plandomizer. They start with the <kbd>#</kbd> character. The ones that should work fine are: | ||
< | {{collapsible list code style | ||
#Bottle - Places a bottle and randomly chooses a contents for it | |<nowiki>#</nowiki>Bottle - Places a bottle and randomly chooses a contents for it | ||
#Junk - Places a junk item (used by exclude locations) | |#Junk - Places a junk item (used by exclude locations) | ||
#AdultTrade - Places the adult trade item without specifying which one | |#AdultTrade - Places the adult trade item without specifying which one | ||
</ | |title=The ones that should work fine: | ||
|expand=yes | |||
}} | |||
{{-}} | |||
{{collapsible list code style | |||
|<nowiki>#</nowiki>Vanilla - Places whatever was on that location in the original game. Also applies to MQ locations. | |||
|#MajorItem - Places a settings-dependent major item at that location. | |||
|#Song - Places a song item | |||
|#NonWarpSong - Places non warp song item | |||
|#WarpSong - Places a warp song item | |||
|#JunkSong - Places Serenade or Prelude in non-entrance randomizer. | |||
|#Spell - Places one of the three spells | |||
|#Shield - Deku or Hylian. Doesn't include Mirror. | |||
|#HealthUpgrade - Heart Container or Piece of Heart | |||
|title=If you are feeling a little bit more daring, you can try: | |||
|expand=yes | |||
}} | |||
All of these should work, but only the first list have been extensively tested. | |||
You can also define your own, custom item groups by adding a <code>custom_groups</code> dictionary to your plando. Within this dictionary you can define groups which contain a list of item names in brackets, and then use those group names as you would with other item groups. | |||
Here is such an example, which will place a random sword in Mido's top left chest and a small key for water or shadow temple in his top right chest: | |||
{{json example| | |||
{ | |||
"custom_groups": { | |||
"CustomList1": [ "Kokiri Sword", "Biggoron Sword", "Giants Knife" ], | |||
# | "CustomList2": [ "Small Key (Water Temple)", "Small Key (Shadow Temple)" ] | ||
# | }, | ||
"locations": { | |||
"KF Midos Top Left Chest": "#CustomList1", | |||
"KF Midos Top Right Chest": "#CustomList2" | |||
} | |||
} | |||
}} | |||
Note that currently patterns do not work on custom groups (so, for example, you cannot do <code>!#CustomList1</code>) and custom groups cannot be nested. | |||
==== Examples ==== | ==== Examples ==== | ||
'''Ready to fight Ganon after Mido's''': | '''Ready to fight Ganon after Mido's''': | ||
{{json example| | |||
"locations": { | "locations": { | ||
" | "KF Midos Top Left Chest": "Bow", | ||
" | "KF Midos Top Right Chest": "Magic Meter", | ||
" | "KF Midos Bottom Left Chest": "Light Arrows", | ||
" | "KF Midos Bottom Right Chest": "Ice Trap" | ||
} | } | ||
}} | |||
'''Bottles in Mido's''': | '''Bottles in Mido's''': | ||
{{json example| | |||
"locations": { | "locations": { | ||
" | "KF Midos Top Left Chest": "#Bottle", | ||
" | "KF Midos Top Right Chest": "#Bottle", | ||
" | "KF Midos Bottom Left Chest": "#Bottle", | ||
" | "KF Midos Bottom Right Chest": "#Bottle" | ||
} | } | ||
}} | |||
'''One step to fighting Ganon in the Kokiri Sword chest''': | '''One step to fighting Ganon in the Kokiri Sword chest''': | ||
{{json example| | |||
"locations": { | "locations": { | ||
"Kokiri Sword Chest": ["Bow", "Magic Meter", "Light Arrows"] | "KF Kokiri Sword Chest": ["Bow", "Magic Meter", "Light Arrows"] | ||
} | } | ||
}} | |||
'''Setting shopsanity 1 item in Kokiri Shop to Ice Trap posing as Light Arrows''': | '''Setting shopsanity 1 item in Kokiri Shop to Ice Trap posing as Light Arrows''': | ||
{{json example| | |||
"locations": { | "locations": { | ||
" | "KF Shop Item 7": { | ||
"item": "Ice Trap", | "item": "Ice Trap", | ||
"price": 60, | "price": 60, | ||
Line 333: | Line 398: | ||
} | } | ||
} | } | ||
}} | |||
'''Place player 2's Light Arrows in player 1's Kokiri Sword chest''': | '''Place player 2's Light Arrows in player 1's Kokiri Sword chest''': | ||
{{json example| | |||
"locations": { | "locations": { | ||
"World 1": { | "World 1": { | ||
"Kokiri Sword Chest": { | "KF Kokiri Sword Chest": { | ||
"item": "Light Arrows", | "item": "Light Arrows", | ||
"player": 2 | "player": 2 | ||
Line 345: | Line 410: | ||
} | } | ||
} | } | ||
}} | |||
=== Hint Distribution Files === | === Hint Distribution Files === | ||
Line 351: | Line 416: | ||
Hint distribution file format is similar to the old hard-coded dictionaries, plus new keys to offer finer control of different hint groups. The goal of this change is to facilitate easier sharing and updating of custom hint distributions for the different racing tournaments. An example with the Tournament distribution is provided below. | Hint distribution file format is similar to the old hard-coded dictionaries, plus new keys to offer finer control of different hint groups. The goal of this change is to facilitate easier sharing and updating of custom hint distributions for the different racing tournaments. An example with the Tournament distribution is provided below. | ||
{{json example| | |||
{ | |||
"name": "tournament", | |||
"gui_name": "Tournament", | |||
"description": "Hint Distribution for the S5 Tournament. 5 Goal Hints, 3 Barren Hints, 5 Sometimes hints, 7 Always hints (including skull mask).", | |||
"add_locations": [{ "location": "Deku Theater Skull Mask", "types": ["always"]}], | |||
"remove_locations": [{"location": "Ganons Castle Shadow Trial Golden Gauntlets Chest", "types": "sometimes"}], | |||
"add_items": [], | |||
"remove_items": [{ "item": "Zeldas Lullaby", "types": ["goal"]}], | |||
"dungeons_woth_limit": 2, | |||
"dungeons_barren_limit": 1, | |||
"named_items_required": true, | |||
"vague_named_items": false, | |||
"use_default_goals": true, | |||
"distribution": { | |||
"trial": {"order": 1, "weight": 0.0, "fixed": 0, "copies": 2}, | |||
"always": {"order": 2, "weight": 0.0, "fixed": 0, "copies": 2}, | |||
"goal": {"order": 3, "weight": 0.0, "fixed": 5, "copies": 2}, | |||
"barren": {"order": 4, "weight": 0.0, "fixed": 3, "copies": 2}, | |||
"entrance": {"order": 5, "weight": 0.0, "fixed": 4, "copies": 2}, | |||
"sometimes": {"order": 6, "weight": 0.0, "fixed": 100, "copies": 2}, | |||
"random": {"order": 7, "weight": 9.0, "fixed": 0, "copies": 2}, | |||
"item": {"order": 0, "weight": 0.0, "fixed": 0, "copies": 2}, | |||
"song": {"order": 0, "weight": 0.0, "fixed": 0, "copies": 2}, | |||
"overworld": {"order": 0, "weight": 0.0, "fixed": 0, "copies": 2}, | |||
"dungeon": {"order": 0, "weight": 0.0, "fixed": 0, "copies": 2}, | |||
"junk": {"order": 0, "weight": 0.0, "fixed": 0, "copies": 2}, | |||
} | "named-item": {"order": 8, "weight": 0.0, "fixed": 0, "copies": 2}, | ||
} | "woth": {"order": 0, "weight": 0.0, "fixed": 0, "copies": 2} | ||
}, | |||
"groups": [], | |||
"disabled": [] | |||
} | |||
}} | |||
GUI names and tooltip descriptions are now defined with each distribution file. Tooltips are automatically parsed to add line returns as needed for the GUI. | GUI names and tooltip descriptions are now defined with each distribution file. Tooltips are automatically parsed to add line returns as needed for the GUI. | ||
Line 401: | Line 471: | ||
Four new lists are provided to include or exclude hinted locations from different hint groups, as specified by the location name or filled item name. As seen in the tournament distribution, the <code>add_locations</code> key can be used to force a given location to be hinted by adding it to the <code>always</code> hint type. Locations can be added to (or removed from) any hint type. Likewise, the item keys allow for adding or removing locations to be hinted based on what items they contain. For example, to remove all songs from being hinted as way of the hero, the following would be utilized: | Four new lists are provided to include or exclude hinted locations from different hint groups, as specified by the location name or filled item name. As seen in the tournament distribution, the <code>add_locations</code> key can be used to force a given location to be hinted by adding it to the <code>always</code> hint type. Locations can be added to (or removed from) any hint type. Likewise, the item keys allow for adding or removing locations to be hinted based on what items they contain. For example, to remove all songs from being hinted as way of the hero, the following would be utilized: | ||
{{json example| | |||
{ | "remove_items": [ | ||
{ | { "item": "Zeldas Lullaby", "types": ["woth"] }, | ||
{ | { "item": "Eponas Song", "types": ["woth"] }, | ||
{ | { "item": "Sarias Song", "types": ["woth"] }, | ||
{ | { "item": "Suns Song", "types": ["woth"] }, | ||
{ | { "item": "Song of Time", "types": ["woth"] }, | ||
{ | { "item": "Song of Storms", "types": ["woth"] }, | ||
{ | { "item": "Minuet of Forest", "types": ["woth"] }, | ||
{ | { "item": "Bolero of Fire", "types": ["woth"] }, | ||
{ | { "item": "Serenade of Water", "types": ["woth"] }, | ||
{ | { "item": "Requiem of Spirit", "types": ["woth"] }, | ||
{ | { "item": "Nocturne of Shadow", "types": ["woth"] }, | ||
] | { "item": "Prelude of Light", "types": ["woth"] } | ||
] | |||
}} | |||
Alternately, if songsanity is disabled, the song locations could be removed from the <code>woth</code> hint type to achieve the same effect. | Alternately, if songsanity is disabled, the song locations could be removed from the <code>woth</code> hint type to achieve the same effect. | ||
Barren hints | Way of the Hero and Barren hints cannot have locations added via `add_locations`. Additionally, Barren hints cannot be removed via `remove_locations`. This is to prevent situations where required items are in hinted barren areas. Using the song example again, a foolish Song of Storms that leads to a required item in Bottom of the Well would be confusing to players unfamiliar with the setting. Excluding from way of the hero means it won’t be hinted, not that the game is actively lying to you. | ||
Barren hints can be added or removed from consideration for specific items via the <code>add_items</code> and <code>remove_items</code> lists. This affects not just hints, but also the <code>:barren_regions</code> list in the spoiler log. In contrast, way of the hero items will still be listed in the <code>:woth_locations</code> section regardless of hint distribution changes. Forced barren items that are logically required still show up in the <code>:woth_locations</code> list if required by the seed. | Barren hints can be added or removed from consideration for specific items via the <code>add_items</code> and <code>remove_items</code> lists. This affects not just hints, but also the <code>:barren_regions</code> list in the spoiler log. In contrast, way of the hero items will still be listed in the <code>:woth_locations</code> section regardless of hint distribution changes. Forced barren items that are logically required still show up in the <code>:woth_locations</code> list if required by the seed. | ||
Line 424: | Line 496: | ||
The <code>hint_dist_user</code> setting takes a hint distribution dictionary as defined by the built-in hint distribution files. If specified, it overrides the GUI-selected hint distribution. Internally, the distribution is defined as <code>custom</code>. | The <code>hint_dist_user</code> setting takes a hint distribution dictionary as defined by the built-in hint distribution files. If specified, it overrides the GUI-selected hint distribution. Internally, the distribution is defined as <code>custom</code>. | ||
==== Custom Goals ==== | |||
As of version 6.0.111, the '''goal''' hint type can use built-in goals for the bridge, Ganon's Castle Boss Key, and Trials conditions as well as custom goals defined in the hint distribution. Custom goals use the <code>custom_goals</code> key inside a custom hint distribution as shown in the example below. | |||
{{json example| | |||
{ | |||
"settings": { | |||
"hint_dist_user": { | |||
... | |||
"custom_goals": [ | |||
{ | |||
"category": "all_items", | |||
"priority": 1, | |||
"minimum_goals": 4, | |||
"lock_entrances": ["Ganons Castle Grounds -> Ganons Castle Lobby"], | |||
"goals": [ | |||
{ | |||
"name": "memes", | |||
"hint_text": "path of memes", | |||
"color": "Light Blue", | |||
"items": [ | |||
{"name": "Ice Arrows", "quantity": 2, "minimum": 1, "hintable": true}, | |||
{"name": "Double Defense", "quantity": 2, "minimum": 1, "hintable": true}, | |||
{"name": "Stone of Agony", "quantity": 2, "minimum": 1, "hintable": true}, | |||
{"name": "Nayrus Love", "quantity": 2, "minimum": 1, "hintable": true} | |||
] | |||
} | |||
] | |||
} | |||
], | |||
... | |||
} | |||
} | |||
} | |||
}} | |||
===== '''Category Definition''' ===== | |||
Both goal categories and individual goals can be defined. Goals can be assigned to existing default categories by setting the `category` key to one of the following: | |||
* '''rainbow_bridge''' - Includes goals for dungeon rewards or skulltula tokens. Not active with open bridge. | |||
* '''ganon_bosskey''' - Includes goals for dungeon rewards, skulltula tokens, or Ganon's Boss Key directly. Not active with the boss key removed or vanilla. | |||
* '''trials''' - Includes path to the Tower goal for any enabled trials. Only active with non-zero trials | |||
* '''triforce_hunt''' - Includes path of gold goal for Triforce Pieces. Only active when Triforce Hunt is enabled | |||
* '''ganon''' - Equivalent to way of the hero. Only active with open bridge and Ganon's Castle Boss Key removed/vanilla and zero trials. | |||
===== '''Category Priority''' ===== | |||
Custom goals follow the same category priority rules as default goals. A custom goal in the <code>ganon_bosskey</code> category will not include items that are part of the bridge category. A custom category with a priority between the <code>bridge</code> and <code>ganon_bosskey</code> categories will not include items from the <code>bridge</code> category, and the <code>ganon_bosskey</code> category will not include items from <code>bridge</code> or the custom category. Caution should be used adding custom categories before or in the middle of default categories for this reason. If a custom category has the same priority as a default goal, a required item can be included for goals in both categories. Default priorities are: | |||
* '''rainbow_bridge''' - 10 | |||
* '''ganon_bosskey''' - 20 for dungeon rewards/tokens, 30 for keysanity variants | |||
* '''trials''' - 30 | |||
* '''triforce_hunt''' - 30 | |||
* '''ganon''' - 30 | |||
===== '''Category Minimum Goals''' ===== | |||
Minimum goals determine if the overall category objective is fulfilled. For example, the <code>bridge</code> category has a minimum requirement of however many dungeon rewards are needed to spawn the bridge to Ganon's Castle. If there are not enough obtainable goals in the world, the category objective is not fulfilled and goal hints will not be generated for that category. This system is available to custom goal categories with the <code>minimum_goals</code> key. | |||
===== '''Category Entrance Locks''' ===== | |||
Entrances between regions can be disconnected to artificially restrict world access for a category. This was designed primarily for the rainbow bridge to only hint goals reachable without access to Ganon's Castle. The system can be used with custom goal categories by listing entrances to lock in the <code>lock_entrances</code> key. Entrance names use the syntax "Region A -> Region B", where the different regions are named in the logic files. This has only been tested with overworld entrances, but should work with dungeon internal entrances as well. | |||
It is not possible to change default goal category entrance locks. | |||
===== '''Goal Definition''' ===== | |||
All goal names must be unique within a category. Goal names are only used internally. The <code>hint_text</code> key defines how the goal is presented in the spoiler log and in hints. Default goals use the convention "path to <X>". | |||
Goal colors change how the path is colored. The hinted area with the required item will always be light blue. | |||
{{collapsible list code style | |||
|White | |||
|Red | |||
|Green | |||
|Blue | |||
|Light Blue | |||
|Pink | |||
|Yellow | |||
|Black | |||
|title=Valid colors are: | |||
|expand=yes | |||
}} | |||
Required item definition can include any number of items for each goal. Each item has four keys: | |||
* name - Item name as defined in <code>ItemList.py</code> | |||
* quantity - Maximum possible items to complete the goal | |||
* minimum - Minimum possible items to complete the goal | |||
* hintable - Whether or not this item can be directly hinted, or only items required to obtain this item. In both cases required items are a possibility for hints. | |||
The <code>quantity</code> key must be equal to or greater than the <code>minimum</code> key. The <code>minimum</code> key cannot be zero. The randomizer will consider a goal valid for hints if the all minimum items are reachable. It will attempt to hint items required for all copies of this item up to the maximum <code>quantity</code>, but will automatically reduce the <code>quantity</code> to the maximum reachable copies in beatable only or with a category lock defined. | |||
Required items for goals must be major items. Rupees and heart containers are not major items and will cause the goal to always be unobtainable and thus unhintable. | |||
==== Example Plando ==== | ==== Example Plando ==== | ||
Line 463: | Line 631: | ||
At least 1 junk hint will be added due to the odd number of remaining stones. | At least 1 junk hint will be added due to the odd number of remaining stones. | ||
{{json example| | |||
{ | |||
"settings": { | |||
"item_hints": [ | |||
"Lens of Truth" | |||
], | ], | ||
"hint_dist_user": { | |||
"name": "custom", | |||
"gui_name": "Plando Test Hint Distribution", | |||
"description": "for debugging", | |||
"add_locations": [ | |||
{ "location": "LH Sun", "types": ["always"], "text": "those who #blot out the sun# will find" }, | |||
{ "location": "Deku Theater Skull Mask", "types": ["always"] } | |||
], | |||
"remove_locations": [ | |||
{ "location": "ZR Frogs Ocarina Game", "types": ["always"] }, | |||
{ "location": "Kak 40 Gold Skulltula Reward", "types": ["always"] } | |||
], | |||
"add_items": [ | |||
{ "item": "Zeldas Lullaby", "types": ["always"] }, | |||
{ "item": "Rutos Letter", "types": ["barren"] } | |||
], | |||
"remove_items": [ | |||
{ "item": "Eponas Song", "types": ["woth", "sometimes"] }, | |||
{ "item": "Sarias Song", "types": ["woth", "sometimes"] }, | |||
{ "item": "Suns Song", "types": ["woth", "sometimes"] }, | |||
{ "item": "Song of Time", "types": ["woth", "sometimes"] }, | |||
{ "item": "Song of Storms", "types": ["woth", "sometimes"] }, | |||
{ "item": "Minuet of Forest", "types": ["woth", "sometimes"] }, | |||
{ "item": "Bolero of Fire", "types": ["woth", "sometimes"] }, | |||
{ "item": "Serenade of Water", "types": ["woth", "sometimes"] }, | |||
{ "item": "Requiem of Spirit", "types": ["woth", "sometimes"] }, | |||
{ "item": "Nocturne of Shadow", "types": ["woth", "sometimes"] }, | |||
{ "item": "Prelude of Light", "types": ["woth", "sometimes"] }, | |||
{ "item": "Biggoron Sword", "types": ["barren"] } | |||
], | |||
"dungeons_woth_limit": 2, | |||
"dungeons_barren_limit": 1, | |||
"named_items_required": "True", | |||
"distribution": { | |||
"trial": {"order": 1, "weight": 0.0, "fixed": 0, "copies": 2}, | |||
"always": {"order": 2, "weight": 0.0, "fixed": 0, "copies": 2}, | |||
"woth": {"order": 3, "weight": 0.0, "fixed": 3, "copies": 2}, | |||
"barren": {"order": 4, "weight": 0.0, "fixed": 2, "copies": 1}, | |||
"entrance": {"order": 5, "weight": 0.0, "fixed": 4, "copies": 2}, | |||
"sometimes": {"order": 6, "weight": 0.0, "fixed": 5, "copies": 1}, | |||
"random": {"order": 7, "weight": 0.5, "fixed": 0, "copies": 2}, | |||
"item": {"order": 8, "weight": 1.0, "fixed": 0, "copies": 2}, | |||
"song": {"order": 9, "weight": 2.0, "fixed": 0, "copies": 2}, | |||
"overworld": {"order": 10, "weight": 3.0, "fixed": 0, "copies": 2}, | |||
"dungeon": {"order": 11, "weight": 1.0, "fixed": 0, "copies": 2}, | |||
"junk": {"order": 12, "weight": 0.5, "fixed": 0, "copies": 1}, | |||
"named-item": {"order": 13, "weight": 0.0, "fixed": 0, "copies": 2} | |||
} | |||
} | } | ||
}, | |||
"randomized_settings": {}, | |||
"starting_items": {}, | |||
"item_pool": {}, | |||
"entrances": {}, | |||
"locations": { | |||
"OGC Great Fairy Reward": "Rutos Letter", | |||
"Wasteland Chest": "Biggoron Sword" | |||
} | } | ||
} | } | ||
} | }} | ||
==== Item Hints for Bingo ==== | ==== Item Hints for Bingo ==== | ||
Line 543: | Line 713: | ||
* Modifies the item pool to contain 3 empty bottles, one of which will be hinted. | * Modifies the item pool to contain 3 empty bottles, one of which will be hinted. | ||
{{json example| | |||
{ | |||
"settings": { | |||
"item_hints": [ | |||
"Progressive Strength Upgrade", | |||
"Progressive Strength Upgrade", | |||
"Lens of Truth", | |||
"Bottle" | |||
] | ] | ||
}, | }, | ||
"randomized_settings": {}, | |||
"starting_items": {}, | |||
"item_pool": { | |||
"Bottle": 3 | |||
}, | }, | ||
"entrances": {}, | |||
"locations": {} | |||
} | } | ||
}} | |||
=== Gossip Stones === | === Gossip Stones and Other Text Boxes === | ||
Plandomizer can also alter the text of Gossip Stones and as of v6.2.28 of nearly all other text boxes in the game. This is a very powerful and flexible feature, but keep in mind that the Randomizer cannot check for (hint) logic if you plando Gossip Stones. In other words, '''Custom-made hints can be false and should therefore be constructed carefully'''. This feature has not been tested extensively for other text boxes, but it seems to work for all text boxes that the Randomizer doesn't already alter itself. For example, you cannot change the text boxes for receiving Small Keys or Gold Skulltula Tokens. However, be very cautious of altering text boxes that chain to others or lead into an action as these can easily cause softlocks if those actions are not accounted for. | |||
When plandoing text boxes, the term is the name of the Gossip Stone or the [https://wiki.cloudmodding.com/oot/Text_IDs Text ID] when changing other text boxes. The names of Gossip Stones can be found [https://github.com/TestRunnerSRL/OoT-Randomizer/blob/Dev/Hints.py here] or in the <kbd>gossip_stones</kbd> section of an old Spoiler Log. The Text IDs can be found [https://wiki.cloudmodding.com/oot/Text_IDs here]. Click on the appropriate ID List and search for the vanilla text using <kbd>CTRL</kbd> + <kbd>F</kbd> to find the correct ID number. Changing the text of Gossip Stones using the Text ID will not work. You have to use the Gossip Stone name for that. | |||
The definition is a dictionary with the term <var>text</var>. | |||
* Multiple text boxes can be assigned to a single Gossip Stone/sign/NPC/etc. by separating the strings with <kbd>^</kbd>. However, this is not strictly required as the randomizer will automatically break up strings that are too long for a single text box. '''Warning''': Really long texts (1200+ characters) will have negative side effects ranging from graphical issues to hard crashes, so don't make your text too long, or test them if you do. Keep in mind that this character limit appears to be significantly lower on N64 than on emulator or Wii VC. | |||
* Any text you surround with <kbd>#</kbd> can also be colored. If you wish to do this add another term to the inner dictionary with the term <var>colors</var> and set it to a list containing strings of the colors you wish to use. You can have multiple groups of text surrounded by <kbd>#</kbd> and each one can be a different color. | * Any text you surround with <kbd>#</kbd> can also be colored. If you wish to do this add another term to the inner dictionary with the term <var>colors</var> and set it to a list containing strings of the colors you wish to use. You can have multiple groups of text surrounded by <kbd>#</kbd> and each one can be a different color. | ||
==== | {{collapsible list code style | ||
< | |White | ||
|Red | |||
|Green | |||
|Blue | |||
|Light Blue | |||
|Pink | |||
|Yellow | |||
|Black | |||
|title=Valid colors: | |||
</ | |expand=yes | ||
}} | |||
When plandoing Gossip Stones, the Randomizer will replace available hints in reverse priority order. (As of version 7.1.51, this now works in proper listed order.) | |||
==== Special Characters ==== | |||
You can also use some special characters within your custom text boxes. In terms of normal characters, you can use within your hint text the following just by putting them within the string as usual: À, Á, Â, Ä, Ç, È, É, Ê, Ë, Ï, Ô, Ö, Ù, Û, Ü, the lowercase versions of all previous characters, and ß. | |||
You can also specify codes for special, in-game button characters using Unicode values. Reference the following table for the value for each button character, and then it can be specified within your hint text with \u00xx, where xx is the value from the table. For example, the <kbd>A</kbd> button has a value of <kbd>9F</kbd>, so it would be printed using <kbd>\u009F</kbd> within your text box. [https://i.imgur.com/sfbnKF6.png Here] you can see what these characters look like in-game. | |||
{| class="wikitable" | |||
|- | |||
| Code || 9F || A0 || A1 || A2 || A3 || A4 || A5 || A6 || A7 || A8 || A9 || AA | |||
|- | |||
| Button Displayed || A || B || C || L || R || Z || C-up || C-down || C-left || C-right || Down arrow || Joystick | |||
|} | |||
==== Sound Effects ==== | |||
Each text box can be equipped with a sound effect. The full list of sound effect IDs can be found [https://wiki.cloudmodding.com/oot/Sound_Effect_Ids here], but it takes a little bit of work to convert them to the correct format. Sound effects are designated by <kbd>${12 x8 yy}</kbd>, where <kbd>x</kbd> is the "Bank" as indicated on CloudModding and <kbd>yy</kbd> is the sound number within the bank. The <kbd>8</kbd> must be swapped for <kbd>9</kbd> if the sound number is greater than <kbd>FF</kbd> (i.e. if it has 3 characters on CloudModding). | |||
'''Warning''': Looping sounds will not stop until Link leaves the area or dies, so it's recommended to avoid these sounds. | |||
Only one sound effect will play per Text ID. If you want a single source of text boxes (e.g. a Gossip Stone) to play a sound effect on every single text box, then you will need to chain text boxes together. This is done by putting <kbd>${07 xx xx}</kbd>, where <kbd>xx xx</kbd> is the Text ID of another text box, at the end of a text box. Then, you'll want to make a new <kbd>gossip_stones</kbd> entry that uses this Text ID as the term. You can chain that entry into a new one and keep chaining until you are satisfied. It is highly recommended to take a look at the example of chaining text boxes down below. | |||
The Text ID values from <kbd>05 00</kbd> to <kbd>05 60</kbd> (in hexadecimal numbers) have been reserved for text box chaining by Plandomakers. Other Text IDs could be in use by the Randomizer either currently or in the future, so in order to future-proof your Plando it is highly encouraged to stay within this range of 96 different Text IDs. Using values already in use by the Randomizer would result in the Randomizer overwriting your text boxes with its own. Keep in mind that chaining text boxes is only required for having multiple sound effects tied to a single source of text boxes. If you just want additional text boxes without sound effects, then you can achieve this far easier with the <kbd>^</kbd> character. | |||
==== Control Codes ==== | |||
Control Codes allow text boxes to be chained together or ensure actions occur after text boxes. | |||
The <kbd>${07 xx xx}</kbd> explained in the Sound Effects section is the control code to link to other text boxes. Some text boxes require this when they are replaced For example, Link the Goron's first text upon standing up is <kbd>$3032</kbd>. If this text ID is replaced, it must end with <kbd>${07 30 33}</kbd> in order to link to the "Boohoo" text which will allow the interaction to continue so his item can be received. | |||
The control code <kbd>${0B}</kbd> is required for text boxes that lead into the game performing an action. For example, minigame NPC dialogue which leads into the start of the game must end with this. There is not currently a comprehensive list of dialogue that requires this, so we recommend testing all custom dialogue in game before releasing a plando to others. Examples of a few IDs that require this are 4086, 6040, and 71AF. | |||
To print the current in-game time in a text box, use <kbd>${1F}</kbd>. | |||
==== Examples ==== | ==== Examples ==== | ||
'''Just white text''': | '''Just white text''': | ||
{{json example| | |||
"gossip_stones": { | "gossip_stones": { | ||
" | "DMC (Bombable Wall)": { | ||
"text": "It's hot in here!" | "text": "It's hot in here!" | ||
} | } | ||
} | } | ||
}} | |||
'''Colored text''': | '''Colored text''': | ||
{{json example| | |||
"gossip_stones": { | "gossip_stones": { | ||
" | "DMC (Bombable Wall)": { | ||
"text": "They say #Luigi# was put in this game instead of Super #Mario# 64", | "text": "They say #Luigi# was put in this game instead of Super #Mario# 64", | ||
"colors": ["Green", "Red"] | "colors": ["Green", "Red"] | ||
} | } | ||
} | } | ||
}} | |||
'''Helpful Tutorial Message''': | |||
{{json example| | |||
"gossip_stones": { | |||
"KF (Outside Storms)": { "text": "To target, press \u00A4" } | |||
} | |||
}} | |||
'''Appreciation''': | |||
{{json example| | |||
"gossip_stones": { | |||
"KF (Deku Tree Right)": { "text": "Dampé is a pretty cool guy." } | |||
} | |||
}} | |||
'''Sound Effects and Current Time Added''': | |||
{{json example| | |||
"gossip_stones": { | |||
"ToT (Left)": { "text": "The time is ${1F}.^${12 28 df}The cow goes moo." }, | |||
"ToT (Left-Center)": { "text": "${12 39 C7}Ganondorf laughs maniacally." } | |||
} | |||
}} | |||
'''Sign in Front of Bottom of the Well''': | |||
{{json example| | |||
"gossip_stones": { | |||
"$0307": {"text": "Is this magic?"} | |||
} | |||
}} | |||
'''Chaining Text Boxes with the Sign in Front of the Exit from Kokiri Forest to Hyrule Field''': | |||
{{json example| | |||
"gossip_stones": { | |||
"$0320": {"text": "${12 68 7a}Hey kids, want to learn how to chain text IDs?${07 04 60}"}, | |||
"$0460": {"text": "${12 68 7a}Chained ID 1${07 04 61}"}, | |||
"$0461": {"text": "${12 68 7a}Chained ID 2"} | |||
} | |||
}} | |||
=== Cosmetics and Sounds === | === Cosmetics and Sounds === | ||
Line 617: | Line 864: | ||
'''Set the tunic colors using hex values''': | '''Set the tunic colors using hex values''': | ||
{{json example| | |||
{ | { | ||
"settings": { | "settings": { | ||
Line 625: | Line 872: | ||
} | } | ||
} | } | ||
}} | |||
'''Set tunic colors using built-in color options''': | '''Set tunic colors using built-in color options''': | ||
{{json example| | |||
{ | { | ||
"settings": { | "settings": { | ||
Line 636: | Line 883: | ||
} | } | ||
} | } | ||
}} | |||
'''Set rainbow sword trail with a duration of 1 second''': | '''Set rainbow sword trail with a duration of 1 second''': | ||
{{json example| | |||
{ | { | ||
"settings": { | "settings": { | ||
Line 647: | Line 894: | ||
} | } | ||
} | } | ||
}} | |||
==== Sounds ==== | ==== Sounds ==== | ||
To set sound effects, choose the sound you want to use as the value (right column) and the event when it plays as the key (left column). [https://github.com/TestRunnerSRL/OoT-Randomizer/blob/Dev/Sounds.py A list of sounds effects can be found here]. Valid strings for the plandomizer file are found in the <samp>keyword</samp> column. For vanilla sound effects choose <code>default</code>, except for <samp>sfx_low_hp</samp> and <samp>sfx_ocarina</samp> where the vanilla sounds are called <code>soft-beep</code> and <code>ocarina</code> respectively. | To set sound effects, choose the sound you want to use as the value (right column) and the event when it plays as the key (left column). [https://github.com/TestRunnerSRL/OoT-Randomizer/blob/Dev/Sounds.py A list of sounds effects can be found here] (use the <samp>keyword</samp> column). Valid strings for the plandomizer file are found in the <samp>keyword</samp> column. For vanilla sound effects choose <code>default</code>, except for <samp>sfx_low_hp</samp> and <samp>sfx_ocarina</samp> where the vanilla sounds are called <code>soft-beep</code> and <code>ocarina</code> respectively. <samp>completely-random</samp>, <samp>random-ear-safe</samp>, <samp>random-choice</samp>, and <samp>none</samp> are also valid choices. | ||
To set background music, choose the location where you want the music to be played as the key (left column) and the music that will be played as the corresponding value (right column). [https://github.com/TestRunnerSRL/OoT-Randomizer/blob/Dev/Music.py A list of valid strings can be found here]. Note that these strings are valid both as key and value. Use <code>None</code> for no background music. | To set background music, choose the location where you want the music to be played as the key (left column) and the music that will be played as the corresponding value (right column). [https://github.com/TestRunnerSRL/OoT-Randomizer/blob/Dev/Music.py A list of valid strings can be found here]. Note that these strings are valid both as key and value. Use <code>None</code> for no background music. | ||
Line 658: | Line 905: | ||
'''Set sound effects''': | '''Set sound effects''': | ||
{{json example| | |||
{ | { | ||
"settings": { | "settings": { | ||
Line 667: | Line 914: | ||
"sfx_menu_select": "talon-snore", | "sfx_menu_select": "talon-snore", | ||
"sfx_horse_neigh": "default", | "sfx_horse_neigh": "default", | ||
"sfx_nightfall": " | "sfx_nightfall": "completely-random", | ||
"sfx_hover_boots": "child-owo", | "sfx_hover_boots": "child-owo", | ||
"sfx_ocarina": "malon" | "sfx_ocarina": "malon" | ||
} | } | ||
} | } | ||
}} | |||
'''Set background music''': | '''Set background music''': | ||
{{json example| | |||
{ | { | ||
"bgm": { | "bgm": { | ||
Line 683: | Line 930: | ||
} | } | ||
} | } | ||
</ | }} | ||
It is also possible to plando [https://wiki.ootrandomizer.com/index.php?title=Readme#Custom_Music_and_Fanfares custom music]. In this case what you insert as the track name is whatever is on the first line of the <kbd><samp>.meta</samp></kbd> file (open with any text editor). (As of v7.1.123 this <kbd><samp>.meta</samp></kbd> file will be packed with the <kbd><samp>.seq</samp></kbd> inside a <kbd><samp>.ootrs</samp></kbd> file.) If you are having trouble accessing this <kbd><samp>.meta</samp></kbd> file, the file name of the <kbd><samp>.seq</samp></kbd> or <kbd><samp>.ootrs</samp></kbd> should also work (but is not guaranteed to). If this is done incorrectly, then the randomizer will skip the song and not output an error message. This means that some other track will be placed there instead without your knowledge. | |||
=== Plando Exclusive Features === | |||
As of v6.1 there is a setting that can only be changed through the use of Plandomizer. | |||
==== Light Arrows Cutscene Condition ==== | |||
This is a setting that determines what the condition is for triggering the Light Arrows Cutscene (LACS) event. This was originally made a setting so that Ganon's Boss Key could be placed here with the condition being, for example, a certain number of dungeon rewards. This would allow players to have the Rainbow Bridge open from the start for early access to Ganon's Castle while still locking Ganondorf behind a certain condition. Now that Ganon's Boss Key can be given to the player anywhere, this setting is no longer needed and was made to be Plando-only rather than removed completely. | |||
To use this setting, add the following to the settings dictionary of the Plando file: | |||
{{json example| | |||
"lacs_condition": "X", | |||
}} | |||
where valid settings for <code>X</code> are <code>Stones</code>, <code>Medallions</code>, <code>Dungeons</code>, <code>Tokens</code> and <code>Hearts</code> (hearts v6.2.76 onwards). If you wish for the LACS condition to remain vanilla, then simply don't add anything to your Plando file as vanilla is the default setting. Finally, you'll want to add the following line: | |||
{{json example| | |||
"lacs_stones/medallions/dungeons/tokens/hearts": Y, | |||
}} | |||
Where <code>Y</code> is a number (note the lack of quotation marks) and where you should choose <code>lacs_medallions/stones/dungeons/tokens/hearts</code> as appropriate (so <code>lacs_stones</code> if you picked Spiritual Stones as your condition, <code>lacs_medallions</code> if you picked Medallions etc.). Hearts are in units of full hearts (= Heart Containers) and not in units of quarters of hearts (= Pieces of Heart). Keep in mind that the last line of the settings dictionary should '''not''' have a comma at the end, so remove it if appropriate. | |||
==== Examples ==== | |||
'''Set the LACS condition to be 69 Gold Skulltula Tokens''': | |||
{{json example| | |||
{ | |||
"settings": { | |||
"lacs_condition": "Tokens", | |||
"lacs_tokens": 69 | |||
} | |||
} | |||
}} | |||
==== Password Locked Seeds ==== | |||
This is a setting for creating a password lock on seeds. The password must be entered before the save can be started for the first time. It will consist of a sequence of 6 button presses, using the A and C button, and can be found near the top of the spoiler log. You cannot use this to define a specific password. | |||
To use this setting, add the following to the settings dictionary of the Plando file: | |||
{{json example| | |||
"password_lock": true | |||
}} | |||
==== Example ==== | |||
For altering no other settings, just to enable a password, this is a complete plando: | |||
{{json example| | |||
{ | |||
"settings": { | |||
"password_lock": true | |||
} | |||
} | |||
}} | |||
== Common Errors == | == Common Errors == | ||
Line 698: | Line 994: | ||
Sometimes this is just bad luck and you have to try generating again, but if you continuously get the same exact error messages over and over, you most likely need to modify your settings or where items are placed in the world. Think carefully about what logical problems your settings and item placements might have. Refer to the [https://github.com/TestRunnerSRL/OoT-Randomizer/tree/master/data/World Release logic files] or the [https://github.com/TestRunnerSRL/OoT-Randomizer/tree/Dev/data/World Dev logic files] depending on which one you are using to try to help find any you have forgotten. | Sometimes this is just bad luck and you have to try generating again, but if you continuously get the same exact error messages over and over, you most likely need to modify your settings or where items are placed in the world. Think carefully about what logical problems your settings and item placements might have. Refer to the [https://github.com/TestRunnerSRL/OoT-Randomizer/tree/master/data/World Release logic files] or the [https://github.com/TestRunnerSRL/OoT-Randomizer/tree/Dev/data/World Dev logic files] depending on which one you are using to try to help find any you have forgotten. | ||
Of course you can always come to the | Of course you can always come to the {{discord|plando-support}} channel on the {{discord}} to ask for help if you're feeling stuck. We can usually point you in the right direction or find the exact issue causing the error. | ||
=== Cannot Choose From An Empty Sequence === | === Cannot Choose From An Empty Sequence === |
Latest revision as of 19:44, 29 September 2024
Plandomizer, often shortened to just Plando, permits total control over item placement. You can place a specific item on any location and locations not specified will be filled following the normal algorithm. Using a .json format text file, referred to as a distribution file when using plandomizer, most aspects of the randomizer can be overwritten.
This can be used to create custom challenges to play through yourself or share with others. The more details defined in a plandomizer, the less the randomizer interferes, though the randomizer will still verify whether it is beatable based on the logic settings, and if it is logically impossible it will refuse to generate a seed.
The plandoMaker site is currently not available, so you will have to modify a distribution file yourself. For any confusion, please visit the #plando-support channel in the Ocarina of Time Randomizer Discord for help resolving issues.
These items and location are used internally by the logic to handle new item locations becoming available. They are not meant to be used in a plando.
Using a Plandomizer Distribution File on the Generator
Plandomizer's distribution file text box is hidden by default. To enable it go to ROM Options on the generator and turn on the Enable Plandomizer (Optional) setting. Then use the Browse button next to the new text box to find your Plandomizer distribution .json file.
Opening and Editing a Distribution File
Distributions are just normal text files using the .json extension instead of the .txt extension. They can be opened in any text editor that will open .txt files. Even Notepad, TextEdit, and gedit can open these files. The extension is only to help let you know that text within is expected to look a certain way.
Distribution File Format
JSON is a common format used for data that both a human and a computer are intended to read. It's a fairly picky format so it is a good idea to use a text editor that can tell you if you did something wrong through syntax highlighting. Visual Studio Code is such a text editor, and as it is cross-platform and used by many people in the community. It is the one we recommend you use if you go down this path. Alternatively, a validator such as JSONLint can check formatting, if you prefer a text editor without syntax highlighting. A validator may also help identify issues which are harder to understand in VSCode.
The randomizer generator on the website will also display an error if you try to use a distribution file that is not in the proper JSON format. You may wish to use this, JSONLint, and VSCode all together to figure out how to fix any formatting problems.
Understanding a Distribution File
When generating a seed with a spoiler log, that spoiler log is actually a distribution file itself. It can be used directly to generate the exact same seed. Because of this, you can take a look at a spoiler log to help you get familiar with the types of things that can be changed, and how to format the distribution file.
Since a distribution file is in JSON format, it's somewhat rigid about how things can be written.
The Base Dictionary
First, a distribution file starts with a { opening curly brace, and ends with a } closing curly brace. Everything you define must be placed between these braces. These braces mark a Dictionary or an associative array, and while that link has a lot of useful information, you don't really have to understand it. Think of a dictionary data structure like you would a dictionary in the real world. You have a term, then you have the definition of that term. As this is the base dictionary, you don't write a term as the code that reads the JSON file creates its own term for this dictionary.
The Dictionary "Terms"
Within the base dictionary there are many terms, such as :version, file_hash, and locations. If you are viewing a spoiler log you'll notice some of these terms start with a :. These terms are ignored when Plandomizer is used and are autogenerated by the randomizer. When you are creating a distribution file yourself you can delete these terms (or take advantage of this mechanic to put in comments between sections, but note that it cannot be used within {} sections such as Locations or Entrances).
Terms are followed by a : and then some spaces, then their definitions.
Definitions that start and end with " are Strings. They are just text you write, but it is important that they are between quotes.
Definitions starting with [ an open bracket and ending with a ] closing bracket are called Lists. In a distribution file lists will usually only contain strings. However, with other types of JSON files you could see them containing other data structures such as dictionaries, or other lists.
The rest of the definitions are just more dictionaries with their own terms that have definitions. These are the only data structures that you have to keep in mind, and generally they are already defined properly in the spoiler log for you so you can just modify them how you see fit. Just ensure you don't accidentally remove the symbols that go before and after the term.
The Most Common Format/Syntax Issue
You'll notice that each of these terms is followed at the very end by a , comma, except the very last one. This is probably the most common mistake someone will make when making their own distribution file. Each term needs to be separated by a comma, but the last one cannot have a comma after it. This is true for strings inside of lists, and lists, strings, and other dictionaries within a dictionary as well. If you are getting a syntax error, you probably added a comma you shouldn't have, or removed one you need. The generator will tell you that your JSON is invalid if you try to use a distribution file with one of these errors.
What Can Plandomizer Affect
Plandomizer can affect an enormous amount of the resulting seed. Everything from inconsequential things like the File Hash, to the Settings the randomizer uses to fill the world, and even specifically set items in locations that the world fill algorithm will have to work around.
File Hash
The file hash is the 5 icons that are displayed at the top of the file select screen. You can set these to any valid HASH_ICON.
You can set the file_hash definition to a list of up to 5 hash icons. If you do not want to specify an icon for a set position you can either set it to the value null, or if it is after all the ones you do want to set you can just not include it.
Hash Icons
Examples
Set all 5 icons to Deku Nut:
"file_hash": ["Deku Nut", "Deku Nut", "Deku Nut", "Deku Nut", "Deku Nut"]
Set only the first icon to Deku Nut:
"file_hash": ["Deku Nut", null, null, null, null]
or
"file_hash": ["Deku Nut"]
Set only the last icon to Deku Nut:
"file_hash": [null, null, null, null, "Deku Nut"]
Settings
This is a dictionary defining the rules that the randomizer uses to fill the world. Any settings you set here will override the ones set in the GUI. That also means that you can leave some settings out of this dictionary and the person using your distribution file to create a seed can have a small amount of customization they can apply in case they need a little more additional help, or perhaps want to increase the difficulty a little bit.
It is not recommended to set these manually. Instead, you should go to the beta plandomizer maker on the website. You can set all the settings you want on the first tab, then create the JSON file. From here you can copy the settings dictionary from that file into this file and remove any settings you don't want to enforce. Alternatively, if you only want a few settings to be enforced, you can copy only the settings you want from the dictionary in that other JSON file into the settings dictionary in your settings file.
There are two major issues with creating the settings dictionary entirely manually:
- If you mistype, or the name of a setting changes between versions, you will not get an error. The randomizer will just ignore this issue entirely.
- The process of figuring out the proper name for a setting, and the various values it can hold is tedious.
If you still think you want to try this method, the file in the source code you want to look at to see all this necessary information is SettingsList.py. This is a 3000 line monstrosity that isn't very useful if you're not already pretty familiar with the settings you are looking for in the first place. Each setting has a name that you have to use for a definition inside of the settings dictionary. Then various other variables within the option's object in the settings list file are used to determine what possible definitions you want to use for that setting.
Just using the plandomizer maker on the website is highly recommended over putting yourself through this experience.
Starting Items
The starting items dictionary lets you define what items a player starts with, and how many of them. This includes both items you find in the world, and consumables you would pick up such as ammo and bombs. Any items you start with will be replaced by junk in the item pool. Songs placed here will force an item to be on one of the song locations even if shuffle_song_items is not set. This will completely override the starting items set on the randomizer generator GUI.
The term is the item you want to start with. The definition is how many of that item you want to start with. The number is not a string and should not be put in quotes.
Examples
Start with full wallet without Max Rupees setting:
"starting_items": { "Rupees": 99 }
Start with all shields:
"starting_items": { "Deku Shield": 1, "Hylian Shield": 1, "Mirror Shiled": 1 }
Please note there are two starting item sections, this section refers to the one after randomized_settings in a spoiler log. The starting items, starting equipment, and starting songs sections within the settings section have a different format, but as listing what falls under each here would be a long section, please instead generate a spoiler log using the GUI to see where items need to be listed.
NOTE: In current dev versions, the starting items sections have been unified into the one under the settings dictionary. Make sure to place your starting items dictionary inside the settings dictionary for it to work.
Item Pool
This is a dictionary defining every item possible to place in the world. It is highly recommended that you do not set every possible item to a value in this dictionary. Primarily junk items because the randomizer often needs to generate new junk, but will not change any value you manually place in the item pool. This would make your plandomizer very rigid and can cause various issues if you try changing settings that change what, and how many items you start with, or that are available in the base pool.
You can also specify if you want to add to the base number, remove from the base number, or set the base number for the item. The default is to set the value. If you want to use the other options you'll need to set the definition to be another dictionary.
The term is the item you want to specify the number of in the pool. The definition is either:
- The number of that item you want in the pool
- A dictionary with a term of type set to any of the strings "add", "remove", or "set" and a term of count set to the number to modify by.
Examples
Set Mirror Shield to have 3 copies placed in the world:
"item_pool": { "Mirror Shield": 3 }
or
"item_pool": { "Mirror Shield": { "type": "set", "count": 3 } }
Add 3 Deku Shields to place in the world in addition to the ones already in the base pool:
"item_pool": { "Deku Shield": { "type": "add", "count": 3 } }
Dungeons
This dictionary lets you define which dungeons are vanilla and which are mq (master quest). You will have to set the number of MQ dungeons setting to match at least whatever master quest dungeons you define here. However, you do not have to define all of the dungeons and the rest will be defined by the randomizer generator instead.
The term is the name of the dungeon. The definitions is either the string "vanilla", the string "mq", or the string "random".
Examples
Set only Deku Tree to mq:
"dungeons": { "Deku Tree": "mq" }
Set only Spirit Temple to vanilla, because you don't want to learn the second version of spirit logic:
"dungeons": { "Spirit Temple": "vanilla" }
Set Dodongo's Cavern to random:
"dungeons": { "Dodongos Cavern": "random" }
Trials
You will define which trials are active and which ones are inactive in this dictionary. You will have to set the number of trials to match at least the trials you define here. However, you do not have to define all of the trials and the rest will be defined by the randomizer generator instead.
The term is the name of the trial. The definition is either the string "active", the string "inactive", or the string "random".
Examples
Set forest, fire, and water trials as inactive:
"trials": { "Forest": "inactive", "Fire": "inactive", "Water": "inactive" }
Set light trial to active, ensuring that 3 strength upgrades are required for fighting Ganon:
"trials": { "Light": "active" }
Set water trial to random:
"trials": { "Water": "random" }
Entrances
This dictionary defines how different entrances are linked together when using entrance randomizer. Entrances must be shuffled among their respective groups so you cannot use plandomizer to force a mixed entrance pool seed. You may wish to generate a entrance randomizer seed and use its spoiler log to ensure you use the correct names for the locations.
The term is the loading zone you pass through. The definition is:
- For Dungeons and Interiors: a string with the name of the location you end up at
- For Overworld: a dictionary with a term of region set to a string of the overworld region it leads to and a term of from set to a string of the loading zone in that region that you will appear out of.
Examples
Set Deku Tree entrance to Gerudo Training Ground:
"entrances": { "KF Outside Deku Tree -> Deku Tree Lobby": {"region": "Gerudo Training Ground Lobby", "from": "Gerudo Fortress"} }
Set Hyrule Castle exit from Market to Lon Lon Ranch main entrance:
"entrances": { "Market -> Castle Grounds": { "region": "Lon Lon Ranch", "from": "Hyrule Field" } }
Locations
This dictionary handles what is probably the main feature of plandomizer. You can assign items to any location in the game world here. Which locations are available are heavily influenced by the settings chosen, so ensure you have the proper settings set.
The term is the name of the location. The definition is either:
- A string of an item to place there.
- A list containing multiple items to randomly choose from to place there.
- A dictionary containing the term item containing one of the above two bullet points.
- If making a multiworld plandomizer: the term player with the world number value of the player the item belongs to.
- If the location is a shop: the term price with the rupee number value the item should cost. You cannot set scrub prices using plandomizer
- If the item can be an ice trap: the term model set to a string of the item model it should appear as in the overworld.
Item names can also take advantage of the wildcard * and the not indicator !.
For example, this will guarantee Link starts with a medallion, Spirit Temple will always have a stone, and one of the shields can be found in Mido's House.
"locations": { "Links Pocket": "*Medallion", "Twinrova": "!*Medallion", "KF Midos Top Left Chest": "*Shield" }
Shop Location Numbers
Due to the odd way the shop items are stored in the game files, using shopsanity item placement is not very intuitive.
When using 1 item shopsanity, the number you use is 7 and is the bottom left item on the left side.
When using 2 items shopsanity, you also have number 5 which is the bottom right item on the left side.
When using 3 items shopsanity, you add on the number 8 which is the top left item on the left side.
When using 4 items shopsanity, you can now use all 4 numbers 5-8 for all of the left side items.
Shop Location Prices
When defining a shop location, rather than simply assigning a string of the item name to the location, you must define a dictionary with the properties item (a string of the item name) and price (a number). So for example, a shop item location will look something like this:
"KF Shop Item 7": { "item": "Light Arrows", "price": 40 },
If you try to set a price higher than 999, it will simply be capped to 999 so it won't be impossible to buy. However, you can actually plando negative prices, which will give the player the absolute value of the price. So if you plando a shop item to be -10 rupees, the player will be able to purchase it with any wallet size and it will give them 10 rupees. Due to reasons related to the binary numbers used to represent the prices in-game, the lowest possible price is -32768.
Special Item Groups
There are shortcut terms you can use for certain items when using plandomizer. They start with the # character. The ones that should work fine are:
All of these should work, but only the first list have been extensively tested.
You can also define your own, custom item groups by adding a custom_groups
dictionary to your plando. Within this dictionary you can define groups which contain a list of item names in brackets, and then use those group names as you would with other item groups.
Here is such an example, which will place a random sword in Mido's top left chest and a small key for water or shadow temple in his top right chest:
{ "custom_groups": { "CustomList1": [ "Kokiri Sword", "Biggoron Sword", "Giants Knife" ], "CustomList2": [ "Small Key (Water Temple)", "Small Key (Shadow Temple)" ] }, "locations": { "KF Midos Top Left Chest": "#CustomList1", "KF Midos Top Right Chest": "#CustomList2" } }
Note that currently patterns do not work on custom groups (so, for example, you cannot do !#CustomList1
) and custom groups cannot be nested.
Examples
Ready to fight Ganon after Mido's:
"locations": { "KF Midos Top Left Chest": "Bow", "KF Midos Top Right Chest": "Magic Meter", "KF Midos Bottom Left Chest": "Light Arrows", "KF Midos Bottom Right Chest": "Ice Trap" }
Bottles in Mido's:
"locations": { "KF Midos Top Left Chest": "#Bottle", "KF Midos Top Right Chest": "#Bottle", "KF Midos Bottom Left Chest": "#Bottle", "KF Midos Bottom Right Chest": "#Bottle" }
One step to fighting Ganon in the Kokiri Sword chest:
"locations": { "KF Kokiri Sword Chest": ["Bow", "Magic Meter", "Light Arrows"] }
Setting shopsanity 1 item in Kokiri Shop to Ice Trap posing as Light Arrows:
"locations": { "KF Shop Item 7": { "item": "Ice Trap", "price": 60, "model": "Light Arrows" } }
Place player 2's Light Arrows in player 1's Kokiri Sword chest:
"locations": { "World 1": { "KF Kokiri Sword Chest": { "item": "Light Arrows", "player": 2 } } }
Hint Distribution Files
Hint distribution file format is similar to the old hard-coded dictionaries, plus new keys to offer finer control of different hint groups. The goal of this change is to facilitate easier sharing and updating of custom hint distributions for the different racing tournaments. An example with the Tournament distribution is provided below.
{ "name": "tournament", "gui_name": "Tournament", "description": "Hint Distribution for the S5 Tournament. 5 Goal Hints, 3 Barren Hints, 5 Sometimes hints, 7 Always hints (including skull mask).", "add_locations": [{ "location": "Deku Theater Skull Mask", "types": ["always"]}], "remove_locations": [{"location": "Ganons Castle Shadow Trial Golden Gauntlets Chest", "types": "sometimes"}], "add_items": [], "remove_items": [{ "item": "Zeldas Lullaby", "types": ["goal"]}], "dungeons_woth_limit": 2, "dungeons_barren_limit": 1, "named_items_required": true, "vague_named_items": false, "use_default_goals": true, "distribution": { "trial": {"order": 1, "weight": 0.0, "fixed": 0, "copies": 2}, "always": {"order": 2, "weight": 0.0, "fixed": 0, "copies": 2}, "goal": {"order": 3, "weight": 0.0, "fixed": 5, "copies": 2}, "barren": {"order": 4, "weight": 0.0, "fixed": 3, "copies": 2}, "entrance": {"order": 5, "weight": 0.0, "fixed": 4, "copies": 2}, "sometimes": {"order": 6, "weight": 0.0, "fixed": 100, "copies": 2}, "random": {"order": 7, "weight": 9.0, "fixed": 0, "copies": 2}, "item": {"order": 0, "weight": 0.0, "fixed": 0, "copies": 2}, "song": {"order": 0, "weight": 0.0, "fixed": 0, "copies": 2}, "overworld": {"order": 0, "weight": 0.0, "fixed": 0, "copies": 2}, "dungeon": {"order": 0, "weight": 0.0, "fixed": 0, "copies": 2}, "junk": {"order": 0, "weight": 0.0, "fixed": 0, "copies": 2}, "named-item": {"order": 8, "weight": 0.0, "fixed": 0, "copies": 2}, "woth": {"order": 0, "weight": 0.0, "fixed": 0, "copies": 2} }, "groups": [], "disabled": [] }
GUI names and tooltip descriptions are now defined with each distribution file. Tooltips are automatically parsed to add line returns as needed for the GUI.
Hint Type Distribution
The distribution
key is a similar format to the previous dictionary. Each hint group must be listed with the following keys:
order
: Integer to sort hint types from smallest to largestweight
: Same as hint type weight in balanced and similar hint distributionsfixed
: Same as tournament distribution number of hints per worldcopies
: Same as count per hint in predefined distributions
Tournament-style fixed hints and weighted-style hints are defined together in the same distribution. Fixed hints are rolled first. Any remaining gossip stones are filled from a random choice of hint types with assigned weights. Checks exist to make sure there are enough gossip stones left for a given random hint type count per hint. Fixed hints do not have this safeguard and rely on the user not to overfill them. Using the tournament distribution as an example, fixed hints are rolled according to the defined order and fixed number. If any gossip stones remain, the random
hint group is rolled as part of the weighted hint types (in this case the only one, so it is guaranteed upon exhaustion of all sometimes hints). Other built-in hint types with no fixed hints have non-zero orders for all types and weights equal to the old style weight, and all types have a fixed
value of 0
.
Dungeon Limits
Dungeon way of the hero and barren limitations are moved out of the hint generation functions into the distribution files. Values are identical in all built-in distributions except very_strong
, which has a limit of 40
for both (equivalent to no limit).
Hint Type Requirements and Exclusions
Four new lists are provided to include or exclude hinted locations from different hint groups, as specified by the location name or filled item name. As seen in the tournament distribution, the add_locations
key can be used to force a given location to be hinted by adding it to the always
hint type. Locations can be added to (or removed from) any hint type. Likewise, the item keys allow for adding or removing locations to be hinted based on what items they contain. For example, to remove all songs from being hinted as way of the hero, the following would be utilized:
"remove_items": [ { "item": "Zeldas Lullaby", "types": ["woth"] }, { "item": "Eponas Song", "types": ["woth"] }, { "item": "Sarias Song", "types": ["woth"] }, { "item": "Suns Song", "types": ["woth"] }, { "item": "Song of Time", "types": ["woth"] }, { "item": "Song of Storms", "types": ["woth"] }, { "item": "Minuet of Forest", "types": ["woth"] }, { "item": "Bolero of Fire", "types": ["woth"] }, { "item": "Serenade of Water", "types": ["woth"] }, { "item": "Requiem of Spirit", "types": ["woth"] }, { "item": "Nocturne of Shadow", "types": ["woth"] }, { "item": "Prelude of Light", "types": ["woth"] } ]
Alternately, if songsanity is disabled, the song locations could be removed from the woth
hint type to achieve the same effect.
Way of the Hero and Barren hints cannot have locations added via `add_locations`. Additionally, Barren hints cannot be removed via `remove_locations`. This is to prevent situations where required items are in hinted barren areas. Using the song example again, a foolish Song of Storms that leads to a required item in Bottom of the Well would be confusing to players unfamiliar with the setting. Excluding from way of the hero means it won’t be hinted, not that the game is actively lying to you.
Barren hints can be added or removed from consideration for specific items via the add_items
and remove_items
lists. This affects not just hints, but also the :barren_regions
list in the spoiler log. In contrast, way of the hero items will still be listed in the :woth_locations
section regardless of hint distribution changes. Forced barren items that are logically required still show up in the :woth_locations
list if required by the seed.
Plando Support
The hint_dist_user
setting takes a hint distribution dictionary as defined by the built-in hint distribution files. If specified, it overrides the GUI-selected hint distribution. Internally, the distribution is defined as custom
.
Custom Goals
As of version 6.0.111, the goal hint type can use built-in goals for the bridge, Ganon's Castle Boss Key, and Trials conditions as well as custom goals defined in the hint distribution. Custom goals use the custom_goals
key inside a custom hint distribution as shown in the example below.
{ "settings": { "hint_dist_user": { ... "custom_goals": [ { "category": "all_items", "priority": 1, "minimum_goals": 4, "lock_entrances": ["Ganons Castle Grounds -> Ganons Castle Lobby"], "goals": [ { "name": "memes", "hint_text": "path of memes", "color": "Light Blue", "items": [ {"name": "Ice Arrows", "quantity": 2, "minimum": 1, "hintable": true}, {"name": "Double Defense", "quantity": 2, "minimum": 1, "hintable": true}, {"name": "Stone of Agony", "quantity": 2, "minimum": 1, "hintable": true}, {"name": "Nayrus Love", "quantity": 2, "minimum": 1, "hintable": true} ] } ] } ], ... } } }
Category Definition
Both goal categories and individual goals can be defined. Goals can be assigned to existing default categories by setting the `category` key to one of the following:
- rainbow_bridge - Includes goals for dungeon rewards or skulltula tokens. Not active with open bridge.
- ganon_bosskey - Includes goals for dungeon rewards, skulltula tokens, or Ganon's Boss Key directly. Not active with the boss key removed or vanilla.
- trials - Includes path to the Tower goal for any enabled trials. Only active with non-zero trials
- triforce_hunt - Includes path of gold goal for Triforce Pieces. Only active when Triforce Hunt is enabled
- ganon - Equivalent to way of the hero. Only active with open bridge and Ganon's Castle Boss Key removed/vanilla and zero trials.
Category Priority
Custom goals follow the same category priority rules as default goals. A custom goal in the ganon_bosskey
category will not include items that are part of the bridge category. A custom category with a priority between the bridge
and ganon_bosskey
categories will not include items from the bridge
category, and the ganon_bosskey
category will not include items from bridge
or the custom category. Caution should be used adding custom categories before or in the middle of default categories for this reason. If a custom category has the same priority as a default goal, a required item can be included for goals in both categories. Default priorities are:
- rainbow_bridge - 10
- ganon_bosskey - 20 for dungeon rewards/tokens, 30 for keysanity variants
- trials - 30
- triforce_hunt - 30
- ganon - 30
Category Minimum Goals
Minimum goals determine if the overall category objective is fulfilled. For example, the bridge
category has a minimum requirement of however many dungeon rewards are needed to spawn the bridge to Ganon's Castle. If there are not enough obtainable goals in the world, the category objective is not fulfilled and goal hints will not be generated for that category. This system is available to custom goal categories with the minimum_goals
key.
Category Entrance Locks
Entrances between regions can be disconnected to artificially restrict world access for a category. This was designed primarily for the rainbow bridge to only hint goals reachable without access to Ganon's Castle. The system can be used with custom goal categories by listing entrances to lock in the lock_entrances
key. Entrance names use the syntax "Region A -> Region B", where the different regions are named in the logic files. This has only been tested with overworld entrances, but should work with dungeon internal entrances as well.
It is not possible to change default goal category entrance locks.
Goal Definition
All goal names must be unique within a category. Goal names are only used internally. The hint_text
key defines how the goal is presented in the spoiler log and in hints. Default goals use the convention "path to <X>".
Goal colors change how the path is colored. The hinted area with the required item will always be light blue.
Required item definition can include any number of items for each goal. Each item has four keys:
- name - Item name as defined in
ItemList.py
- quantity - Maximum possible items to complete the goal
- minimum - Minimum possible items to complete the goal
- hintable - Whether or not this item can be directly hinted, or only items required to obtain this item. In both cases required items are a possibility for hints.
The quantity
key must be equal to or greater than the minimum
key. The minimum
key cannot be zero. The randomizer will consider a goal valid for hints if the all minimum items are reachable. It will attempt to hint items required for all copies of this item up to the maximum quantity
, but will automatically reduce the quantity
to the maximum reachable copies in beatable only or with a category lock defined.
Required items for goals must be major items. Rupees and heart containers are not major items and will cause the goal to always be unobtainable and thus unhintable.
Example Plando
The attached plando
- Requires a “random”-type location hint for the location containing Lens of Truth
- Adds shooting the sun in Lake Hylia as an always hint with custom text
- Removes Frog Ocarina Game and 40 Skulls as always hints
- Keeps other “conditional” always hints from Standard weekly settings, including Skull Mask
- Adds the location with Zelda’s Lullaby as an always hint
- Removes all other song locations from way of the hero and sometimes hint types
- Forces Rutos Letter to be considered foolish, and places it outside Ganon’s Castle to verify
- Excludes Biggoron Sword from foolish hints, and places it in the Haunted Wasteland to verify
and applies a custom hint distribution as follows:
Fixed Hints
(in order)
- Always and Trials hints at 2 stones/hint
- 1 Named Item hint for Lens of Truth at 2 stones/hint (as required by
named_items_required
) - 3 Way of the Hero hints at 2 stones/hint
- 2 Foolish hints at 1 stone/hint
- 4 Entrance hints at 2 stones/hint
- 5 Sometimes hints at 1 stone/hint
Weighted Hints
On weekly settings, this is 27-29 gossip stones filled, depending on if Zelda’s Lullaby is on Ocarina of Time. The remaining 11-13 stones draw hints from weighted hint types as follows:
- Random (0.5 weight, 2 stones/hint)
- Item (1.0 weight, 2 stones/hint)
- Song (2.0 weight, 2 stones/hint)
- Overworld (3.0 weight, 2 stones/hint)
- Dungeon (1.0 weight, 2 stones/hint)
- Junk (0.5 weight, 1 stone/hint)
At least 1 junk hint will be added due to the odd number of remaining stones.
{ "settings": { "item_hints": [ "Lens of Truth" ], "hint_dist_user": { "name": "custom", "gui_name": "Plando Test Hint Distribution", "description": "for debugging", "add_locations": [ { "location": "LH Sun", "types": ["always"], "text": "those who #blot out the sun# will find" }, { "location": "Deku Theater Skull Mask", "types": ["always"] } ], "remove_locations": [ { "location": "ZR Frogs Ocarina Game", "types": ["always"] }, { "location": "Kak 40 Gold Skulltula Reward", "types": ["always"] } ], "add_items": [ { "item": "Zeldas Lullaby", "types": ["always"] }, { "item": "Rutos Letter", "types": ["barren"] } ], "remove_items": [ { "item": "Eponas Song", "types": ["woth", "sometimes"] }, { "item": "Sarias Song", "types": ["woth", "sometimes"] }, { "item": "Suns Song", "types": ["woth", "sometimes"] }, { "item": "Song of Time", "types": ["woth", "sometimes"] }, { "item": "Song of Storms", "types": ["woth", "sometimes"] }, { "item": "Minuet of Forest", "types": ["woth", "sometimes"] }, { "item": "Bolero of Fire", "types": ["woth", "sometimes"] }, { "item": "Serenade of Water", "types": ["woth", "sometimes"] }, { "item": "Requiem of Spirit", "types": ["woth", "sometimes"] }, { "item": "Nocturne of Shadow", "types": ["woth", "sometimes"] }, { "item": "Prelude of Light", "types": ["woth", "sometimes"] }, { "item": "Biggoron Sword", "types": ["barren"] } ], "dungeons_woth_limit": 2, "dungeons_barren_limit": 1, "named_items_required": "True", "distribution": { "trial": {"order": 1, "weight": 0.0, "fixed": 0, "copies": 2}, "always": {"order": 2, "weight": 0.0, "fixed": 0, "copies": 2}, "woth": {"order": 3, "weight": 0.0, "fixed": 3, "copies": 2}, "barren": {"order": 4, "weight": 0.0, "fixed": 2, "copies": 1}, "entrance": {"order": 5, "weight": 0.0, "fixed": 4, "copies": 2}, "sometimes": {"order": 6, "weight": 0.0, "fixed": 5, "copies": 1}, "random": {"order": 7, "weight": 0.5, "fixed": 0, "copies": 2}, "item": {"order": 8, "weight": 1.0, "fixed": 0, "copies": 2}, "song": {"order": 9, "weight": 2.0, "fixed": 0, "copies": 2}, "overworld": {"order": 10, "weight": 3.0, "fixed": 0, "copies": 2}, "dungeon": {"order": 11, "weight": 1.0, "fixed": 0, "copies": 2}, "junk": {"order": 12, "weight": 0.5, "fixed": 0, "copies": 1}, "named-item": {"order": 13, "weight": 0.0, "fixed": 0, "copies": 2} } } }, "randomized_settings": {}, "starting_items": {}, "item_pool": {}, "entrances": {}, "locations": { "OGC Great Fairy Reward": "Rutos Letter", "Wasteland Chest": "Biggoron Sword" } }
Item Hints for Bingo
The item_hints
plando setting contains a list of items as named in ItemList.py to be added as “random” location hints. This is outside of the hint distribution setting. Built-in hint distributions assume copies per hint is the same as the sometimes category equivalent of the original distribution. The named_items_required
hint distribution key controls if named item hints are treated as always hints. In contrast to always hints, an error will be thrown if any required named item hint cannot be placed.
Plando or third party hint distribution files can specify fixed or weighted named-item
group hints if named_items_required
is false.
Note that add_items
provides similar functionality to the item_hints
plando key if an item is added to the always
group. The reason for duplication of this feature is to provide an easier interface for Bingo races desiring hinted tile goals without building a whole hint distribution from scratch.
Example Bingo Plando
The example plando below:
- Requires two separate strength upgrades to be hinted
- Requires Lens of Truth to be hinted
- Modifies the item pool to contain 3 empty bottles, one of which will be hinted.
{ "settings": { "item_hints": [ "Progressive Strength Upgrade", "Progressive Strength Upgrade", "Lens of Truth", "Bottle" ] }, "randomized_settings": {}, "starting_items": {}, "item_pool": { "Bottle": 3 }, "entrances": {}, "locations": {} }
Gossip Stones and Other Text Boxes
Plandomizer can also alter the text of Gossip Stones and as of v6.2.28 of nearly all other text boxes in the game. This is a very powerful and flexible feature, but keep in mind that the Randomizer cannot check for (hint) logic if you plando Gossip Stones. In other words, Custom-made hints can be false and should therefore be constructed carefully. This feature has not been tested extensively for other text boxes, but it seems to work for all text boxes that the Randomizer doesn't already alter itself. For example, you cannot change the text boxes for receiving Small Keys or Gold Skulltula Tokens. However, be very cautious of altering text boxes that chain to others or lead into an action as these can easily cause softlocks if those actions are not accounted for.
When plandoing text boxes, the term is the name of the Gossip Stone or the Text ID when changing other text boxes. The names of Gossip Stones can be found here or in the gossip_stones section of an old Spoiler Log. The Text IDs can be found here. Click on the appropriate ID List and search for the vanilla text using CTRL + F to find the correct ID number. Changing the text of Gossip Stones using the Text ID will not work. You have to use the Gossip Stone name for that.
The definition is a dictionary with the term text.
- Multiple text boxes can be assigned to a single Gossip Stone/sign/NPC/etc. by separating the strings with ^. However, this is not strictly required as the randomizer will automatically break up strings that are too long for a single text box. Warning: Really long texts (1200+ characters) will have negative side effects ranging from graphical issues to hard crashes, so don't make your text too long, or test them if you do. Keep in mind that this character limit appears to be significantly lower on N64 than on emulator or Wii VC.
- Any text you surround with # can also be colored. If you wish to do this add another term to the inner dictionary with the term colors and set it to a list containing strings of the colors you wish to use. You can have multiple groups of text surrounded by # and each one can be a different color.
When plandoing Gossip Stones, the Randomizer will replace available hints in reverse priority order. (As of version 7.1.51, this now works in proper listed order.)
Special Characters
You can also use some special characters within your custom text boxes. In terms of normal characters, you can use within your hint text the following just by putting them within the string as usual: À, Á, Â, Ä, Ç, È, É, Ê, Ë, Ï, Ô, Ö, Ù, Û, Ü, the lowercase versions of all previous characters, and ß.
You can also specify codes for special, in-game button characters using Unicode values. Reference the following table for the value for each button character, and then it can be specified within your hint text with \u00xx, where xx is the value from the table. For example, the A button has a value of 9F, so it would be printed using \u009F within your text box. Here you can see what these characters look like in-game.
Code | 9F | A0 | A1 | A2 | A3 | A4 | A5 | A6 | A7 | A8 | A9 | AA |
Button Displayed | A | B | C | L | R | Z | C-up | C-down | C-left | C-right | Down arrow | Joystick |
Sound Effects
Each text box can be equipped with a sound effect. The full list of sound effect IDs can be found here, but it takes a little bit of work to convert them to the correct format. Sound effects are designated by ${12 x8 yy}, where x is the "Bank" as indicated on CloudModding and yy is the sound number within the bank. The 8 must be swapped for 9 if the sound number is greater than FF (i.e. if it has 3 characters on CloudModding).
Warning: Looping sounds will not stop until Link leaves the area or dies, so it's recommended to avoid these sounds.
Only one sound effect will play per Text ID. If you want a single source of text boxes (e.g. a Gossip Stone) to play a sound effect on every single text box, then you will need to chain text boxes together. This is done by putting ${07 xx xx}, where xx xx is the Text ID of another text box, at the end of a text box. Then, you'll want to make a new gossip_stones entry that uses this Text ID as the term. You can chain that entry into a new one and keep chaining until you are satisfied. It is highly recommended to take a look at the example of chaining text boxes down below.
The Text ID values from 05 00 to 05 60 (in hexadecimal numbers) have been reserved for text box chaining by Plandomakers. Other Text IDs could be in use by the Randomizer either currently or in the future, so in order to future-proof your Plando it is highly encouraged to stay within this range of 96 different Text IDs. Using values already in use by the Randomizer would result in the Randomizer overwriting your text boxes with its own. Keep in mind that chaining text boxes is only required for having multiple sound effects tied to a single source of text boxes. If you just want additional text boxes without sound effects, then you can achieve this far easier with the ^ character.
Control Codes
Control Codes allow text boxes to be chained together or ensure actions occur after text boxes.
The ${07 xx xx} explained in the Sound Effects section is the control code to link to other text boxes. Some text boxes require this when they are replaced For example, Link the Goron's first text upon standing up is $3032. If this text ID is replaced, it must end with ${07 30 33} in order to link to the "Boohoo" text which will allow the interaction to continue so his item can be received.
The control code ${0B} is required for text boxes that lead into the game performing an action. For example, minigame NPC dialogue which leads into the start of the game must end with this. There is not currently a comprehensive list of dialogue that requires this, so we recommend testing all custom dialogue in game before releasing a plando to others. Examples of a few IDs that require this are 4086, 6040, and 71AF.
To print the current in-game time in a text box, use ${1F}.
Examples
Just white text:
"gossip_stones": { "DMC (Bombable Wall)": { "text": "It's hot in here!" } }
Colored text:
"gossip_stones": { "DMC (Bombable Wall)": { "text": "They say #Luigi# was put in this game instead of Super #Mario# 64", "colors": ["Green", "Red"] } }
Helpful Tutorial Message:
"gossip_stones": { "KF (Outside Storms)": { "text": "To target, press \u00A4" } }
Appreciation:
"gossip_stones": { "KF (Deku Tree Right)": { "text": "Dampé is a pretty cool guy." } }
Sound Effects and Current Time Added:
"gossip_stones": { "ToT (Left)": { "text": "The time is ${1F}.^${12 28 df}The cow goes moo." }, "ToT (Left-Center)": { "text": "${12 39 C7}Ganondorf laughs maniacally." } }
Sign in Front of Bottom of the Well:
"gossip_stones": { "$0307": {"text": "Is this magic?"} }
Chaining Text Boxes with the Sign in Front of the Exit from Kokiri Forest to Hyrule Field:
"gossip_stones": { "$0320": {"text": "${12 68 7a}Hey kids, want to learn how to chain text IDs?${07 04 60}"}, "$0460": {"text": "${12 68 7a}Chained ID 1${07 04 61}"}, "$0461": {"text": "${12 68 7a}Chained ID 2"} }
Cosmetics and Sounds
As of version 6.0 users can select both their cosmetics and sounds with a cosmetics plandomizer file. Just like how the spoiler log syntax is used to create a plandomizer file for locations, entrances, etcetera, the cosmetics log syntax is used to create a cosmetics plandomizer file. This plandomizer file has to be inserted separately, because cosmetics and sounds are typically (re-)applied after the patching process. Make sure that the file is saved as a .json file. To insert a cosmetics plando, toggle Enable Cosmetics Plandomizer (Advanced) on the ROM Options tab and insert it in the field that will appear below. Note; if you also toggled Enable Plandomizer (Advanced), then there will be two fields.
Cosmetics
Note: Custom cosmetics colors can be chosen through the GUI as well, so it is not needed to specify these in the plandomizer.
There are two ways in which you can plandomize cosmetics. The first is to specify colors through hex values. This gives you the freedom to select any color in the color spectrum for any of the cosmetics options. The second method is to use presets built into the randomizer. These are the options found in the dropdown bars in the GUI and include options such as "Kokiri Green", "Random Choice" and "Magenta". Keep in mind that each cosmetic option has its own set of preset colors and that they can't be used interchangeably. For example, tunics have the preset color "Majora Purple", but gauntlets do not, so that color cannot be set for gauntlets unless you specify hex values. Because of this limitation it is recommended that users specify hex values. The hex values associated with the preset colors can be found here. The correct formatting for the plandomizer file is to take the three double-character codes that follow an "x" and put them next to each other in the order in which they appear, preceded by a "#". For example the hex value for "Kokiri Green" in the correct format is #1E691B
. It's case-insensitive and the order matters.
Some cosmetics can be made to cycle through the colors of the rainbow. This cannot be done with hex values and must be specified using the "Rainbow" preset. This is currently only supported for Navi, Bombchu trail, Boomerang trail and Sword trail cosmetics.
The sword trail duration option is unique in that you don't specify a string but an integer. This integer denotes for how many frames the sword trail will linger with the presets being "Default" (= 4), "Long" (= 10), "Very Long" (= 15) and "Lightsaber" (= 20). Normal gameplay is 20 frames per second, so "Lightsaber" will leave a trail for roughly 1 second. This integer can be set higher than 20, but you can expect lag if the number is set extremely high.
Examples
Set the tunic colors using hex values:
{ "settings": { "kokiri_color": "#ffffff", "goron_color": "#1E691B", "zora_color": "#AAaaAA" } }
Set tunic colors using built-in color options:
{ "settings": { "kokiri_color": "Goron Red", "goron_color": "Majora Purple", "zora_color": "Completely Random" } }
Set rainbow sword trail with a duration of 1 second:
{ "settings": { "sword_trail_color_inner": "Rainbow", "sword_trail_color_outer": "Rainbow", "sword_trail_duration": 20 } }
Sounds
To set sound effects, choose the sound you want to use as the value (right column) and the event when it plays as the key (left column). A list of sounds effects can be found here (use the keyword column). Valid strings for the plandomizer file are found in the keyword column. For vanilla sound effects choose default
, except for sfx_low_hp and sfx_ocarina where the vanilla sounds are called soft-beep
and ocarina
respectively. completely-random, random-ear-safe, random-choice, and none are also valid choices.
To set background music, choose the location where you want the music to be played as the key (left column) and the music that will be played as the corresponding value (right column). A list of valid strings can be found here. Note that these strings are valid both as key and value. Use None
for no background music.
Examples
Set sound effects:
{ "settings": { "sfx_low_hp": "soft-beep", "sfx_navi_overworld": "bow-twang", "sfx_navi_enemy": "navi-hey", "sfx_menu_cursor": "ruto-wiggle", "sfx_menu_select": "talon-snore", "sfx_horse_neigh": "default", "sfx_nightfall": "completely-random", "sfx_hover_boots": "child-owo", "sfx_ocarina": "malon" } }
Set background music:
{ "bgm": { "Hyrule Field": "None", "Temple of Time": "Shop", "Gerudo Valley": "Ingo Theme" } }
It is also possible to plando custom music. In this case what you insert as the track name is whatever is on the first line of the .meta file (open with any text editor). (As of v7.1.123 this .meta file will be packed with the .seq inside a .ootrs file.) If you are having trouble accessing this .meta file, the file name of the .seq or .ootrs should also work (but is not guaranteed to). If this is done incorrectly, then the randomizer will skip the song and not output an error message. This means that some other track will be placed there instead without your knowledge.
Plando Exclusive Features
As of v6.1 there is a setting that can only be changed through the use of Plandomizer.
Light Arrows Cutscene Condition
This is a setting that determines what the condition is for triggering the Light Arrows Cutscene (LACS) event. This was originally made a setting so that Ganon's Boss Key could be placed here with the condition being, for example, a certain number of dungeon rewards. This would allow players to have the Rainbow Bridge open from the start for early access to Ganon's Castle while still locking Ganondorf behind a certain condition. Now that Ganon's Boss Key can be given to the player anywhere, this setting is no longer needed and was made to be Plando-only rather than removed completely.
To use this setting, add the following to the settings dictionary of the Plando file:
"lacs_condition": "X",
where valid settings for X
are Stones
, Medallions
, Dungeons
, Tokens
and Hearts
(hearts v6.2.76 onwards). If you wish for the LACS condition to remain vanilla, then simply don't add anything to your Plando file as vanilla is the default setting. Finally, you'll want to add the following line:
"lacs_stones/medallions/dungeons/tokens/hearts": Y,
Where Y
is a number (note the lack of quotation marks) and where you should choose lacs_medallions/stones/dungeons/tokens/hearts
as appropriate (so lacs_stones
if you picked Spiritual Stones as your condition, lacs_medallions
if you picked Medallions etc.). Hearts are in units of full hearts (= Heart Containers) and not in units of quarters of hearts (= Pieces of Heart). Keep in mind that the last line of the settings dictionary should not have a comma at the end, so remove it if appropriate.
Examples
Set the LACS condition to be 69 Gold Skulltula Tokens:
{ "settings": { "lacs_condition": "Tokens", "lacs_tokens": 69 } }
Password Locked Seeds
This is a setting for creating a password lock on seeds. The password must be entered before the save can be started for the first time. It will consist of a sequence of 6 button presses, using the A and C button, and can be found near the top of the spoiler log. You cannot use this to define a specific password.
To use this setting, add the following to the settings dictionary of the Plando file:
"password_lock": true
Example
For altering no other settings, just to enable a password, this is a complete plando:
{ "settings": { "password_lock": true } }
Common Errors
You're very likely to run into many errors while trying to make a plandomizer. These explanations should help you with some of the more cryptic ones. You can also narrow down the source of the error code by running small sections of the original plandomizer at a time until you get the error message.
Not A Valid JSON Format
Game Unbeatable
The randomizer generator could not place items following your defined settings. You've created a situation that is not logically possible to complete.
Sometimes this is just bad luck and you have to try generating again, but if you continuously get the same exact error messages over and over, you most likely need to modify your settings or where items are placed in the world. Think carefully about what logical problems your settings and item placements might have. Refer to the Release logic files or the Dev logic files depending on which one you are using to try to help find any you have forgotten.
Of course you can always come to the #plando-support channel on the Ocarina of Time Randomizer Discord to ask for help if you're feeling stuck. We can usually point you in the right direction or find the exact issue causing the error.
Cannot Choose From An Empty Sequence
This means that an item in your locations dictionary was not spelled correctly (e.g. Light Arrow instead of Light Arrows).
My Plandomized Track Is Not Playing
Make sure that there are no spelling errors. If you're using custom music, then make sure that you are using the track name that is inside the .meta
file.