Decoding is a little different. We can either interpret the B64 string as a <b>signed</b> or <b>unsigned</b> number (signed: using 2s complement binary).
For items, you can download the item DB here: <ahref ="../clean.json"target ="_blank">clean.json</a>. Each item has an id value that can be put in a map. The NoneItem ID numbers start at 10000 in the canonical order: [helmet, chestplate, leggings, boots, ring 1, ring 2, bracelet, necklace, weapon] (No Weapon has an id of 10008).
For tomes, you can download the tome DB here: <ahref ="../tome_map.json"target ="_blank">tome_map.json</a>. The NoneTome ID numbers start at 61 in the order [no weapon tome, no armor tome, no guild tome] so that we can store tome IDs in 1 B64 character.
Version 6 was made to account for the desire to save tomes in a build. As of the last version of this documentation, version 6 is used for encoding whenever there are tomes in the build.
</p>
<divclass ="row section"title ="Example 1: With Tomes">
<li>The unsigned equivalent of <code>00nZ6</code> in binary is 30 <b>binary</b> bits long (omitted). Each section of 5 bits directly corresponds to an powder ID.</li>
</ul>
</ul>
</li>
<li>
<number>7</number> tomes (<number>1</number> character each):
<code>ZU6FCDo</code>
<ulclass ="indent">
<li>The order of tomes listed is [2x weapon tome, 4x armor tome, 1x guild tome].</li>
Version 5 was made to allow for the ability to save custom items. To learn the specifics about custom item encoding, refer to the Custom Items section.
</p>
<p>
As of the last version of this documentation, version 5 is only used for encoding when there are custom items (and no tomes) in the build.
</p>
<divclass ="row section"title ="Example 1: With Custom Item">
<li>Starting in this version, to encode a custom item we substitute in the length of the full hash of a custom item ("CI-[gibberish]") in <number>3</number> B64 characters for the item ID, followed by the full hash.</li>
<li>When decoding build links of this version or higher, you must check whether or not the 3 characters after the current item are "CI-". If they are, the current 3 characters are the B64 representation of the unsigned length of the custom item hash (<math>n</math>), in characters. Then the next <math>n</math> characters make up the full custom item hash.</li>
<li>No existing item has an item ID of "CI-" in B64, so we can define a special case check for this "id number".</li>
<li>The unsigned equivalent of <code>00nZ6</code> in binary is 30 <b>binary</b> bits long (omitted). Each section of 5 bits directly corresponds to an powder ID.</li>
</ul>
</ul>
</li>
</ul>
</div>
<p>
It is possible that version 5 links will have an extra tome section at the end like above (see: Version 6 section). We ignore this in decoding.
Version 4 was made to allow for the ability to save crafted items. To learn the specifics about crafted item encoding, refer to the Crafted Items section.
</p>
<p>
As of the last version of this documentation, version 4 is the default version and is used when there are no custom items or tomes in the build.
</p>
<divclass ="row section"title ="Example 1: No Crafted Items">
<li>The unsigned equivalent of <code>00nZ6</code> in binary is 30 <b>binary</b> bits long (omitted). Each section of 5 bits directly corresponds to an powder ID.</li>
</ul>
</ul>
</li>
</ul>
</div>
<divclass ="row section"title ="Example 2: With Crafted Items">
<li>Starting in this version, you can substitute in the full hash of a crafted item ("CR-[gibberish]") for the 3-character hash of an item pool item.</li>
<li>The way we can tell that an item is a crafted item is when the 3-character hash of the 'item' is "CR-". No existing item has an item ID of "CR-" in B64, so we can define a special case check for this "id number".</li>
<li>The unsigned equivalent of <code>00nZ6</code> in binary is 30 <b>binary</b> bits long (omitted). Each section of 5 bits directly corresponds to an powder ID.</li>
</ul>
</ul>
</li>
</ul>
</div>
<p>
It is possible that version 4 links will have an extra tome string like above (see: Version 6 section) after the powders. You can ignore this in decoding.
<li>The unsigned equivalent of <code>00nZ6</code> in binary is 30 <b>binary</b> bits long (omitted). Each section of 5 bits directly corresponds to an powder ID.</li>
<li>The unsigned equivalent of <code>00nZ6</code> in binary is 30 <b>binary</b> bits long (omitted). Each section of 5 bits directly corresponds to an powder ID.</li>
Version 1 is the very first encoding version by Wynnbuilder. It allows for saving all equipment (armors, accessories, weapon) and powders put on that equipment.
<li>The unsigned equivalent of <code>00nZ6</code> in binary is 30 <b>binary</b> bits long (omitted). Each section of 5 bits directly corresponds to an powder ID.</li>
This section is about how to decode crafted items. To view an example of a crafted item in a build, check out <b>Builds > Version 4</b>.
</p>
<p>
Crafted items always start with "CR-" so that they are, as an entire category, distinguishable from item pool items. The ingredients and materials that make up the crafted item are stored in the rest of the "hash".
</p>
<p>
To encode all the info about a crafted item, we need:
</p>
<ulclass ="indent">
<li>Ingredient Data</li>
<li>Recipe Data</li>
<li>Crafting Material Tiers</li>
<li>Attack Speed (for weapons)</li>
</ul>
<p>
Wynnbuilder assigns each ingredient and recipe to a unique ID number.
</p>
<divclass ="row section"title ="ID number specifics">
For ingredients, you can download the ingredient id map here: <ahref ="../ing_map.json"target ="_blank">ing_map.json</a>. The ID number for No Ingredient is 4000.
For recipes, you can download the recipe id map here: <ahref ="../recipe_map.json"target ="_blank">recipe_map.json</a> or the recipe DB here: <ahref ="recipes_clean.json"target ="_blank">recipes_clean.json</a>.
<li>There are 2 material tiers to decode. The ordering of materials is determined by their order within the corresponding recipe object held in the db.</li>
<li>The material tier character (from here on <math>t</math>) is in the range [<number>1</number>, <number>9</number>]. </li>
<li>Mat 1's tier is equal to <math>t % 3</math> except when this yields 0, in which case it becomes 3.</li>
<li>Mat 2's tier is equal to ceil(<math> (t - 0.5) / 3</math>).</li>
<li>The integer after doing unsigned decoding from the B64 character denotes the index within the following array: [SLOW, NORMAL, FAST]. B64 <code>1</code> maps to the unsigned integer <number>1</number>, meaning that the attack speed of this crafted item would be NORMAL if it were a weapon.</li>
<li>Note: although only weapons will have attack speed, we decided to include the character in all crafted item hashes to keep a constant hash length.</li>
We can simply take the string after the octothorpe/hash tag (#), tack on "CR-" in front of this string, and arrive at the full hash for the crafted item in question. Decode using the same logic as the previous example.
This section is about how to decode custom items. To view an example of a custom item in a build, check out <b>Builds > Version 5</b>.
</p>
<p>
Custom items always start with "CI-" so that they are, as an entire category, distinguishable from item pool items. The stats and values that make up the custom item are stored in the rest of the "hash".
Given a custom item hash, we will in general continue to parse through many identifications and their values until we reach the end of the custom item hash.
</p>
<p>
Custom item hash format:
</p>
<ulclass ="indent">
<li><number>1</number> B64 character denoting encoding/decoding version number: <code>1</code></li>
<li><number>1</number> character denoting whether or not this item has fixed IDs: <code>0</code>. (0 for no fixed IDs, 1 for fixed IDs)</li>
<li>A series of encoded identifications, each taking a variable number of characters. For every ID, we have to save:
<ulclass ="indent">
<li><number>2</number> B64 characters that represent the identification ID (its index in the CI save order array). </li>
<li><number>2</number> B64 characters that represent the length <math>len</math> of the value of the identification.</li>
<li>A variable number characters to encode the value of the identification.
<li>For string-valued identifications (in the non-rolled strings array), we do not use any encoding for the value. The next <number>len</number> characters of the custom item hash is the raw value of the identification (before substituting space for "%20").
<ulclass ="indent">
<li>Exception: for the identifications <code>tier</code>, <code>type</code>, <code>atkSpd</code>, and <code>classReq</code>, there is no string used. They are encoded as a numerical value representing an index in a pre-defined array (check the Important Arrays section above). They also do not use the earlier-specified 2 characters to store length; instead, they each use only 1 B64 character to store their index in their corresponding arrays.</li>
</ul>
</li>
<li>For numerical-valued identifications, encoding depends on the fixed ID value from before.
<ulclass ="indent">
<li>Rolled IDs (with non-fixed IDs):
<ulclass ="indent">
<li><number>1</number> character to denote the sign of the min and max values: 0 for both positive, 1 for negative min and positive max, 2 for positive min and negative max, and 3 for both negative.</li>
<li><number>len</number> B64 characters that represent the unsigned <b>minimum</b> value of the identification.</li>
<li><number>len</number> B64 characters that represent the unsigned <b>maximum</b> value of the identification.</li>
</ul>
</li>
<li>Rolled IDs (with fixed IDs) and Non-Rolled IDs:
<ulclass ="indent">
<li><number>1</number> character (binary bit) to denote the sign of the value (0 positive, 1 negative).</li>
<li><number>len</number> B64 characters that represent the unsigned value of the identification.</li>
</ul>
</li>
</ul>
</li>
</li>
</ul>
</li>
<li>To finish the example, we'll go through all the actual identifications of the provided custom item.
Similar to crafted items, the part of the link after the "#" is the rest of the custom item after the "CI-" constant portion. You may need to convert all "%20" to spaces manually.
</p>
<p>
Details on reading custom items in build links are provided in the Decoding WB links > Builds section.
An overview of wynnbuilder's internal structure can be seen <ahref ="./compute_graph.svg"target ="_blank">here</a>. Arrows indicate flow of information.
Colors correspond roughly as follows:
</p>
<imgsrc="./builder_colorcode.png"/>
<p>
The overall logic flow is as follows:
<ulclass ="indent">
<li>Item and Powder inputs are parsed. Powders are applied to items.</li>
<li>Items and level information are combined to make a build.</li>
<li>Information from input fields for skill points and edit IDs is collected into an ID bonuses table.</li>
<li>Information about active powder specials, strength boosts, etc. are collected into their own ID tables.</li>
<li>All of the above tables are merged with the build's stats table to produce the "Final" ID bonus table.</li>
<li>Which spell variant (think: major id) to use for each of the 4 spells is computed based on the build.</li>
<li>Spell damage is calculated, using the merged stat table, spell info, and weapon info.</li>
</ul>
</p>
<p>
Outputs are computed as follows:
<ulclass ="indent">
<li>Input box highlights are computed from the items produced by item input box nodes.</li>
<li>Item display is computed from item input boxes.</li>
<li>Build hash/URL is computed from the build, and skillpoint assignment.</li>
<li>Spell damage is displayed based on calculated spell damage results.</li>
<li>Build stats are displayed by builder-stats-display (this same node also displays a bunch of stuff at the bottom of the screen...)</li>
</ul>
</p>
<divclass="row section"title="Gotchas">
<p>
The build sets default skillpoints and edited IDs automatically, whenever a build item/level is updated.
This is done using "soft links" by two nodes shown in red (builder-skillpoint-setter and builder-id-setter).
</p>
<p>
A soft link is where something goes and manually marks nodes dirty and calls their update methods.
This is useful for these cases because the skillpoints and editable ID fields usually take their value from
user input, but in some cases we want to programatically set them.
</p>
<p>
For example another soft link (not shown) is used to implement the reset button.