2561feb621
* Update tomes.json with 2.0 tomes Added the 18 new weapon tomes coming in update 2.0. Also fixed fabled t1 weapon tomes having level 80 instead of 60. * Update tome_map.json with 2.0 tomes Added the 18 new weapon tomes coming in update 2.0. * Add missing regression tests * Encode and decode V8, initial files * Adding shortcut load use json directly meme * Dummy data for 2.0.1.2 (same as 2.0.1.1) update documentation slightly * Tier 3 tomes, and update files from api .... tech debt... when binary encode * Change versioning system to use query instead of hash hopefully less breaking change; also just prettier * More misc bugfix Fix race condition in builder graph load Fix loading empty hash Add boundless set tag and set bonus Update mage atree * Data files for wynn version 2.0.1.2, and updated atree const json * Add ability for nodes to have (single) archetype req but no archetype Possibly we want to make a more general req system * Finish inputting rest of the atree changes hopefully * Minify index.html * Add tree decoding pseudocode to dev/index.html * Update V8 docs * Style fixes, bump db versions * missing... semicolons... Co-authored-by: FrozenEarth <39888817+FrozenEarth-git@users.noreply.github.com> Co-authored-by: hppeng <hppeng>
1036 lines
71 KiB
HTML
1036 lines
71 KiB
HTML
<!DOCTYPE html>
|
|
<html scroll-behavior="smooth">
|
|
|
|
<head>
|
|
<title>WynnBuilder Dev</title>
|
|
<link rel="icon" href="../media/icons/new/atlas64.png">
|
|
<link rel="manifest" href="manifest.json">
|
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=.45, user-scalable=no">
|
|
|
|
<!-- nunito font, copying wynnbuilder, which is copying wynndata -->
|
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
<link href="https://fonts.googleapis.com/css2?family=Nunito&display=swap" rel="stylesheet">
|
|
|
|
<link href="https://fonts.googleapis.com/css2?family=Nunito&display=swap" rel="stylesheet">
|
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet"
|
|
integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
|
|
|
|
<link rel="stylesheet"
|
|
href="https://cdn.jsdelivr.net/npm/@tarekraafat/autocomplete.js@10.2.6/dist/css/autoComplete.min.css">
|
|
|
|
|
|
<link rel="stylesheet" href="../css/sq2bs.css">
|
|
<link rel="stylesheet" href="../css/sidebar.css">
|
|
<link rel="stylesheet" href="../css/wynnstyles.css">
|
|
<link rel="stylesheet" href="../css/dev.css">
|
|
</head>
|
|
|
|
<body id="body" class="all" style="overflow-y: scroll">
|
|
<div id="main-sidebar" class="sidebar dark-7 dark-shadow">
|
|
<a href="../builder/"><img src="../media/icons/new/builder.png" alt="WynnBuilder"
|
|
title="WynnBuilder"><b>WynnBuilder</b></a>
|
|
<a href="../crafter/"><img src="../media/icons/new/crafter.png" alt="WynnCrafter"
|
|
title="WynnCrafter"><b>WynnCrafter</b></a>
|
|
<a href="../items/"><img src="../media/icons/new/searcher.png" alt="WynnAtlas"
|
|
title="WynnAtlas"><b>WynnAtlas</b></a>
|
|
<a href="../custom/"><img src="../media/icons/new/custom.png" alt="WynnCustom"
|
|
title="WynnCustom"><b>WynnCustom</b></a>
|
|
<a href="../map/"><img src="../media/icons/new/compass.png" alt="WynnGPS" title="WynnGPS"><b>WynnGPS</b></a>
|
|
<a href="../wynnfo/"><img src="../media/icons/new/book.png" alt="Wynnfo"
|
|
title="WynnCrafter"><b>WynnCrafter</b></a>
|
|
<a href="" onclick="toggleIcons()"><img src="../media/icons/new/reload.png" alt=""
|
|
title="Swap items on page"><b>Swap Icon Style</b></a>
|
|
<hr />
|
|
<a href = "https://discord.gg/CGavnAnerv" target = "_blank"><img src = "../media/icons/discord.png" alt = "WB Discord" title = "WB Discord"><b>WB Discord</b></a>
|
|
</div>
|
|
<div class="container text-light px-5 scaled-font">
|
|
<div class="row justify-content-center page-title">
|
|
Wynnbuilder Developer Page
|
|
</div>
|
|
<div class="row">
|
|
Welcome to the Wynnbuilder page for developers! Here we provide documentation and specifications for our
|
|
website. Read through these sections to learn more about how WynnBuilder works!
|
|
</div>
|
|
<div class="row section" title="Decoding WynnBuilder links">
|
|
<p>
|
|
This section is about the encoding schemes Wynnbuilder uses for its various saveable items (builds,
|
|
crafted items, and custom items).
|
|
</p>
|
|
<p>
|
|
We use a Base 64 (B64) encode/decode system in most shareable links. It would be quite clunky to put a
|
|
bunch of numbers (the data we save and read) into one link. To save some space, we compress the
|
|
base 10 numerical alphabet into a custom B64 alphabet.
|
|
</p>
|
|
<div class="row section" title="WB Base 64 (B64)">
|
|
<p>
|
|
The Wynnbuilder B64 character table:
|
|
</p>
|
|
<pre class="full-width">
|
|
0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+-
|
|
^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
|
|
| | | | | | | | | | | | |
|
|
0 5 10 15 20 25 30 35 40 45 50 55 60 </pre>
|
|
<p>
|
|
The B64 encoding of a number (in the 0 to 63 range) is equal to the character at the index
|
|
within the above string.
|
|
</p>
|
|
<p>
|
|
For example, if we have a set of items with id numbers in the range [<number>0</number>,
|
|
<number>10000</number>], we need at most 3 B64 characters to encode any of these items
|
|
in the link! The item of id <number>1337</number> corresponds to the B64 hash <code>0Kv</code>:
|
|
<math>1337 = 0 * 4096 + 20 * 64 + 57</math>, <number>0</number> maps to <code>0</code>,
|
|
<number>20</number> maps to <code>K</code>, and <number>57</number> maps to <code>v</code>.
|
|
</p>
|
|
<p>
|
|
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).
|
|
</p>
|
|
<p>
|
|
Things that should be interpreted as <b>signed</b> are:
|
|
</p>
|
|
<ul class = "indent">
|
|
<li>Skill Points</li>
|
|
<li>Any numerical identification value for custom items</li>
|
|
</ul>
|
|
<p>
|
|
Things that should be interpreted as <b>unsigned</b> are:
|
|
</p>
|
|
<ul class = "indent">
|
|
<li>Item ID numbers</li>
|
|
<li>Tome ID numbers</li>
|
|
<li>Build Level</li>
|
|
<li>Ingredient ID numbers</li>
|
|
<li>Recipe ID numbers</li>
|
|
<li>Powder numbers</li>
|
|
</ul>
|
|
</div>
|
|
<p>
|
|
Now that we understand the B64 system, we can move on to the way builds, crafted items, and custom items are stored in links.
|
|
</p>
|
|
<div class="row section" title="Builds">
|
|
<p>
|
|
First, what do we need in order to encode an entire build?
|
|
</p>
|
|
<p>
|
|
Wynnbuilder mainly runs calculations for damages and defense. Therefore, we need:
|
|
</p>
|
|
<ul class="indent">
|
|
<li>The build's items (equipment, tomes)</li>
|
|
<li>The skill points distributed by the user (and user level)</li>
|
|
<li>Item powderings</li>
|
|
</ul>
|
|
<p>
|
|
Wynnbuilder assigns each item in the Wynncraft item pool to a unique ID number.
|
|
<!-- For example, the bracelet <b class="atlas">Atlas</b>
|
|
has an id number of <number>167</number>. We can then store all of a build's item pool items in a link with the items' id numbers. A
|
|
similar idea is used for skill points and powders. However, we know how many different skills there are already (5), so we can encode
|
|
the user's assignment of skill points in 5 numbers. With powders, it's a little different. There are 31 "states" of powder: 1 for no
|
|
powder and then 5 elements with 6 tiers of powder for each element. We will know how many available powder slots we have based on our
|
|
equipment. We can then put all of these numbers in a specific order (after running B64 encoding) to get our build link. -->
|
|
</p>
|
|
<div class = "row section" title = "ID number specifics">
|
|
<p>
|
|
For items, you can download the item DB here: <a href = "../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).
|
|
</p>
|
|
<p>
|
|
For tomes, you can download the tome DB here: <a href = "../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.
|
|
</p>
|
|
<p>
|
|
For powders: id numbers <number>1</number> through <number>30</number> map to Earth I, Earth II, ..., Earth VI,
|
|
etc. in the order Earth, Thunder, Water, Fire, Air. 0 is the id number for no powder.
|
|
</p>
|
|
|
|
</div>
|
|
<p>
|
|
All build links starting from Version 8 may look like "?v=[wynn version number]#[version number]_[build hash]".
|
|
The query section is optional.
|
|
</p>
|
|
<p>
|
|
All build links older than Version 8 look like "#[version number]_[build hash]".
|
|
</p>
|
|
<div class="row section" title="Version 8">
|
|
<p>
|
|
Version 8 was made to account for an oversight made when designing the tome encoding, and to signal the beginning of versions that support wynn version history. Version 8 and higher links may start with a query indicating the wynn version to use.
|
|
</p>
|
|
<p>
|
|
Additionally, Version 8 uses 2 characters instead of 1 character to encode the ID of each tome. (The IDs representing NONE tomes does not change.)
|
|
</p>
|
|
</div>
|
|
<div class="row section" title="Version 7">
|
|
<p>
|
|
Version 7 was made to account for ability trees in wynncraft 2.0. Version 7 introduces a new field at the end of the build hash, for ability tree data. Atree data is compressed using a depth first search algorithm into a binary blob, which is then base-64 encoded and appended to the V6 hash. The binry blob is decompressed by using the corresponding traversal.
|
|
</p>
|
|
<p>
|
|
The tree structure defining the ability tree can be found in a json file (by default, <code>js/builder/atree_constants_min.json</code>). The file defines connections between the ability tree nodes: Each node has an unordered list of parent nodes, and an ordered list of child nodes.
|
|
</p>
|
|
<p>
|
|
A reference implementation of the encoding/decoding algorithms can be found in <code>js/builder/build_encode_decode.js</code>. A pseudocode description of the algorithms is given here:
|
|
</p>
|
|
<code style="white-space: pre">
|
|
// Encode an ability tree configuration into a binary blob.
|
|
// NOTE: this algorithm only works for "connected" (valid) ability trees.
|
|
// Its behavior is not well defined otherwise.
|
|
//
|
|
// Parameters:
|
|
// tree_data: Object containing ability tree structure.
|
|
// tree_state: Object containing info about which abilities are selected.
|
|
function encode(tree_data, tree_state):
|
|
|
|
return_vector = BitVector()
|
|
visited = Set()
|
|
|
|
function recursive_traverse(head_node):
|
|
for each child of head_node, in order:
|
|
if child is not in visited:
|
|
add child to visited set
|
|
if tree_state.is_active(child):
|
|
append bit 1 to return_vector
|
|
recursive_traverse(child)
|
|
else:
|
|
append bit 0 to return_vector
|
|
|
|
recursive_traverse(tree_data.root)
|
|
return return_vector
|
|
|
|
// Decode a binary blob into an ability tree configuration
|
|
//
|
|
// Parameters:
|
|
// tree_data: Object containing ability tree structure.
|
|
// tree_state: Object containing info about which abilities are selected.
|
|
// tree_bitvector: raw binary data, accessed one bit at a time
|
|
function decode(tree_data, tree_state, tree_bitvector):
|
|
|
|
i = 0
|
|
visited = Set()
|
|
|
|
function recursive_traverse(head_node):
|
|
for each child of head_node, in order:
|
|
if child is not in visited:
|
|
add child to visited set
|
|
if tree_bitvector[i]:
|
|
child.active = True
|
|
recursive_traverse(child)
|
|
else:
|
|
child.active = False
|
|
i = i + 1
|
|
</code>
|
|
</div>
|
|
<div class="row section" title="Version 6">
|
|
<p>
|
|
Version 6 was made to account for the desire to save tomes in a build.
|
|
</p>
|
|
<div class = "row section" title = "Example 1: With Tomes">
|
|
<code class="full-width">
|
|
https://hppeng-wynn.github.io/builder/#6_06W2SH0D40Qq2SK2SL02d0og0Qi191V-E0i2C1g0000100nZ6ZU6FCDo
|
|
</code>
|
|
<p>
|
|
Build hash format:
|
|
</p>
|
|
<ul class = "indent">
|
|
<li>
|
|
<number>9</number> items from <code>idMap</code> (<number>3</number> B64 characters each):
|
|
<code>06W</code>,
|
|
<code>2SH</code>,
|
|
<code>0D4</code>,
|
|
<code>0Qq</code>,
|
|
<code>2SK</code>,
|
|
<code>2SL</code>,
|
|
<code>02d</code>,
|
|
<code>0og</code>,
|
|
<code>0Qi</code>
|
|
</li>
|
|
<li>
|
|
<number>5</number> skill point totals (<number>2</number> B64 characters each):
|
|
<code>19</code>,
|
|
<code>1V</code>,
|
|
<code>-E</code>,
|
|
<code>0i</code>,
|
|
<code>2C</code>
|
|
</li>
|
|
<li>
|
|
<number>1</number> player level (<number>2</number> B64 characters):
|
|
<code>1g</code>
|
|
</li>
|
|
<li>
|
|
A <b>variable</b> number of powder "blocks" (<number>5</number> B64 characters which give us <number>6</number> powders per block).
|
|
<ul class = "indent">
|
|
<li>For each of the 5 powderable equipment fields [helmet, chestplate, leggings, boots, weapon], we will have the following:</li>
|
|
<li><number>1</number> B64 character that says that we need <number>n</number> blocks for this item.</li>
|
|
<li><number>n</number> blocks of <number>5</number> B64 characters.</li>
|
|
<li>
|
|
Since there are 4 <code>0</code>s (B64 0 = 0 unsigned) in this example, we have no powders on any of the armor piece (no blocks).
|
|
</li>
|
|
<li>
|
|
Then, we have <code>1</code> (B64 1 = 1 unsigned). There is 1 block of powders to decode for the weapon item. That is <code>00nZ6</code>.
|
|
</li>
|
|
<ul class = "indent">
|
|
<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>
|
|
<ul class = "indent">
|
|
<li>The order of tomes listed is [2x weapon tome, 4x armor tome, 1x guild tome].</li>
|
|
</ul>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="row section" title="Version 5">
|
|
<p>
|
|
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>
|
|
<div class = "row section" title = "Example 1: With Custom Item">
|
|
<code class = "full-width">
|
|
https://hppeng-wynn.github.io/builder/#5_06W00mCI-10000JCustom%20Chestplate0220510G020Fe0M0201a0D40Qq2SK2SL02d0og0Qi191V-E0i2C1g0000100nZ6zz++++-
|
|
</code>
|
|
<p>
|
|
Build Hash format:
|
|
</p>
|
|
<ul class = "indent">
|
|
<li>
|
|
<number>9</number> items from <code>idMap</code> (<number>3</number> B64 characters each):
|
|
<code>06W</code>,
|
|
<code>00m</code> (with the custom item <code>CI-10000JCustom%20Chestplate0220510G020Fe0M0201a</code>),
|
|
<code>0D4</code>,
|
|
<code>0Qq</code>,
|
|
<code>2SK</code>,
|
|
<code>2SL</code>,
|
|
<code>02d</code>,
|
|
<code>0og</code>,
|
|
<code>0Qi</code>
|
|
<ul class = "indent">
|
|
<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>Further details on parsing and loading this custom item are in the Custom Item section.</li>
|
|
</ul>
|
|
</li>
|
|
<li>
|
|
<number>5</number> skill point totals (<number>2</number> B64 characters each):
|
|
<code>19</code>,
|
|
<code>1V</code>,
|
|
<code>-E</code>,
|
|
<code>0i</code>,
|
|
<code>2C</code>
|
|
</li>
|
|
<li>
|
|
<number>1</number> player level (<number>2</number> B64 characters):
|
|
<code>1g</code>
|
|
</li>
|
|
<li>
|
|
A <b>variable</b> number of powder "blocks" (<number>5</number> B64 characters which give us <number>6</number> powders per block).
|
|
<ul class = "indent">
|
|
<li>For each of the 5 powderable equipment fields [helmet, chestplate, leggings, boots, weapon], we will have the following:</li>
|
|
<li><number>1</number> B64 character that says that we need <number>n</number> blocks for this item.</li>
|
|
<li><number>n</number> blocks of <number>5</number> B64 characters.</li>
|
|
<li>
|
|
Since there are 4 <code>0</code>s (B64 0 = 0 unsigned) in this example, we have no powders on any of the armor piece (no blocks).
|
|
</li>
|
|
<li>
|
|
Then, we have <code>1</code> (B64 1 = 1 unsigned). There is 1 block of powders to decode for the weapon item. That is <code>00nZ6</code>.
|
|
</li>
|
|
<ul class = "indent">
|
|
<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.
|
|
</p>
|
|
</div>
|
|
<div class="row section" title="Version 4">
|
|
<p>
|
|
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>
|
|
<div class = "row section" title = "Example 1: No Crafted Items">
|
|
<code class = "full-width">
|
|
https://hppeng-wynn.github.io/builder/#4_06W2SH0D40Qq2SK2SL02d0og0Qi191V-E0i2C1g0000100nZ6zz++++-
|
|
</code>
|
|
<p>
|
|
Build Hash format:
|
|
</p>
|
|
<ul class = "indent">
|
|
<li>
|
|
<number>9</number> items from <code>idMap</code> (<number>3</number> N64 characters each):
|
|
<code>06W</code>,
|
|
<code>2SH</code>,
|
|
<code>0D4</code>,
|
|
<code>0Qq</code>,
|
|
<code>2SK</code>,
|
|
<code>2SL</code>,
|
|
<code>02d</code>,
|
|
<code>0og</code>,
|
|
<code>0Qi</code>
|
|
</li>
|
|
<li>
|
|
<number>5</number> skill point totals (<number>2</number> B64 characters each):
|
|
<code>19</code>,
|
|
<code>1V</code>,
|
|
<code>-E</code>,
|
|
<code>0i</code>,
|
|
<code>2C</code>
|
|
</li>
|
|
<li>
|
|
<number>1</number> player level (<number>2</number> B64 characters):
|
|
<code>1g</code>
|
|
</li>
|
|
<li>
|
|
A <b>variable</b> number of powder "blocks" (<number>5</number> B64 characters which give us <number>6</number> powders per block).
|
|
<ul class = "indent">
|
|
<li>For each of the 5 powderable equipment fields [helmet, chestplate, leggings, boots, weapon], we will have the following:</li>
|
|
<li><number>1</number> B64 character that says that we need <number>n</number> blocks for this item.</li>
|
|
<li><number>n</number> blocks of <number>5</number> B64 characters.</li>
|
|
<li>
|
|
Since there are 4 <code>0</code>s (B64 0 = 0 unsigned) in this example, we have no powders on any of the armor piece (no blocks).
|
|
</li>
|
|
<li>
|
|
Then, we have <code>1</code> (B64 1 = 1 unsigned). There is 1 block of powders to decode for the weapon item. That is <code>00nZ6</code>.
|
|
</li>
|
|
<ul class = "indent">
|
|
<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>
|
|
<div class = "row section" title = "Example 2: With Crafted Items">
|
|
<code class = "full-width">
|
|
https://hppeng-wynn.github.io/builder/#4_06WCR-1628i8v8v94948f210D40Qq2SK2SL02d0og0Qi1Q1V-E0l2C1g0000100nZ6zz++++-
|
|
</code>
|
|
<p>
|
|
Build Hash format:
|
|
</p>
|
|
<ul class = "indent">
|
|
<li>
|
|
<number>9</number> items from <code>idMap</code> (<number>3</number> B64 characters each):
|
|
<code>06W</code>,
|
|
<code>CR-1628i8v8v94948f21</code>,
|
|
<code>0D4</code>,
|
|
<code>0Qq</code>,
|
|
<code>2SK</code>,
|
|
<code>2SL</code>,
|
|
<code>02d</code>,
|
|
<code>0og</code>,
|
|
<code>0Qi</code>
|
|
<ul class = "indent">
|
|
<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>Further details on parsing and loading this custom item are in the Crafted Item section.</li>
|
|
</ul>
|
|
</li>
|
|
<li>
|
|
<number>5</number> skill point totals (<number>2</number> B64 characters each):
|
|
<code>19</code>,
|
|
<code>1V</code>,
|
|
<code>-E</code>,
|
|
<code>0i</code>,
|
|
<code>2C</code>
|
|
</li>
|
|
<li>
|
|
<number>1</number> player level (<number>2</number> B64 characters):
|
|
<code>1g</code>
|
|
</li>
|
|
<li>
|
|
A <b>variable</b> number of powder "blocks" (<number>5</number> B64 characters which give us <number>6</number> powders per block).
|
|
<ul class = "indent">
|
|
<li>For each of the 5 powderable equipment fields [helmet, chestplate, leggings, boots, weapon], we will have the following:</li>
|
|
<li><number>1</number> B64 character that says that we need <number>n</number> blocks for this item.</li>
|
|
<li><number>n</number> blocks of <number>5</number> B64 characters.</li>
|
|
<li>
|
|
Since there are 4 <code>0</code>s (B64 0 = 0 unsigned) in this example, we have no powders on any of the armor piece (no blocks).
|
|
</li>
|
|
<li>
|
|
Then, we have <code>1</code> (B64 1 = 1 unsigned). There is 1 block of powders to decode for the weapon item. That is <code>00nZ6</code>.
|
|
</li>
|
|
<ul class = "indent">
|
|
<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.
|
|
</p>
|
|
</div>
|
|
<div class="row section" title="Version 3">
|
|
<p>
|
|
Version 3 encoding added the ability to save build level.
|
|
</p>
|
|
<div class = "row section" title = "Example">
|
|
<code class="full-width">
|
|
https://hppeng-wynn.github.io/builder/#3_06W2SH0D40Qq2SK2SL02d0og0Qi191V-E0i2C1g0000100nZ6
|
|
</code>
|
|
<p>
|
|
Build hash format:
|
|
</p>
|
|
<ul class = "indent">
|
|
<li>
|
|
<number>9</number> items from <code>idMap</code> (<number>3</number> B64 characters each):
|
|
<code>06W</code>,
|
|
<code>2SH</code>,
|
|
<code>0D4</code>,
|
|
<code>0Qq</code>,
|
|
<code>2SK</code>,
|
|
<code>2SL</code>,
|
|
<code>02d</code>,
|
|
<code>0og</code>,
|
|
<code>0Qi</code>
|
|
</li>
|
|
<li>
|
|
<number>5</number> skill point totals (<number>2</number> B64 characters each):
|
|
<code>19</code>,
|
|
<code>1V</code>,
|
|
<code>-E</code>,
|
|
<code>0i</code>,
|
|
<code>2C</code>
|
|
</li>
|
|
<li>
|
|
<number>1</number> player level (<number>2</number> B64 characters):
|
|
<code>1g</code>
|
|
</li>
|
|
<li>
|
|
A <b>variable</b> number of powder "blocks" (<number>5</number> B64 characters which give us <number>6</number> powders per block).
|
|
<ul class = "indent">
|
|
<li>For each of the 5 powderable equipment fields [helmet, chestplate, leggings, boots, weapon], we will have the following:</li>
|
|
<li><number>1</number> B64 character that says that we need <number>n</number> blocks for this item.</li>
|
|
<li><number>n</number> blocks of <number>5</number> B64 characters.</li>
|
|
<li>
|
|
Since there are 4 <code>0</code>s (B64 0 = 0 unsigned) in this example, we have no powders on any of the armor piece (no blocks).
|
|
</li>
|
|
<li>
|
|
Then, we have <code>1</code> (B64 1 = 1 unsigned). There is 1 block of powders to decode for the weapon item. That is <code>00nZ6</code>.
|
|
</li>
|
|
<ul class = "indent">
|
|
<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>
|
|
</div>
|
|
<div class="row section" title="Version 2">
|
|
<p>
|
|
Version 2 encoding added the ability to save skill point info.
|
|
</p>
|
|
<div class = "row section" title = "Example">
|
|
<code class="full-width">
|
|
https://hppeng-wynn.github.io/builder/#2_06W2SH0D40Qq2SK2SL02d0og0Qi191V-E0i2C0000100nZ6
|
|
</code>
|
|
<p>
|
|
Build hash format:
|
|
</p>
|
|
<ul class = "indent">
|
|
<li>
|
|
<number>9</number> items from <code>idMap</code> (<number>3</number> B64 characters each):
|
|
<code>06W</code>,
|
|
<code>2SH</code>,
|
|
<code>0D4</code>,
|
|
<code>0Qq</code>,
|
|
<code>2SK</code>,
|
|
<code>2SL</code>,
|
|
<code>02d</code>,
|
|
<code>0og</code>,
|
|
<code>0Qi</code>
|
|
</li>
|
|
<li>
|
|
<number>5</number> skill point totals (<number>2</number> B64 characters each):
|
|
<code>19</code>,
|
|
<code>1V</code>,
|
|
<code>-E</code>,
|
|
<code>0i</code>,
|
|
<code>2C</code>
|
|
</li>
|
|
<li>
|
|
A <b>variable</b> number of powder "blocks" (<number>5</number> B64 characters which give us <number>6</number> powders per block).
|
|
<ul class = "indent">
|
|
<li>For each of the 5 powderable equipment fields [helmet, chestplate, leggings, boots, weapon], we will have the following:</li>
|
|
<li><number>1</number> B64 character that says that we need <number>n</number> blocks for this item.</li>
|
|
<li><number>n</number> blocks of <number>5</number> B64 characters.</li>
|
|
<li>
|
|
Since there are 4 <code>0</code>s (B64 0 = 0 unsigned) in this example, we have no powders on any of the armor piece (no blocks).
|
|
</li>
|
|
<li>
|
|
Then, we have <code>1</code> (B64 1 = 1 unsigned). There is 1 block of powders to decode for the weapon item. That is <code>00nZ6</code>.
|
|
</li>
|
|
<ul class = "indent">
|
|
<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>
|
|
</div>
|
|
<div class="row section" title="Version 1">
|
|
<p>
|
|
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.
|
|
</p>
|
|
<div class = "row section" title = "Example">
|
|
<code class="full-width">
|
|
https://hppeng-wynn.github.io/builder/#1_06W2SH0D40Qq2SK2SL02d0og0Qi0000100nZ6
|
|
</code>
|
|
<p>
|
|
Build hash format:
|
|
</p>
|
|
<ul class = "indent">
|
|
<li>
|
|
<number>9</number> items from <code>idMap</code> (<number>3</number> B64 characters each):
|
|
<code>06W</code>,
|
|
<code>2SH</code>,
|
|
<code>0D4</code>,
|
|
<code>0Qq</code>,
|
|
<code>2SK</code>,
|
|
<code>2SL</code>,
|
|
<code>02d</code>,
|
|
<code>0og</code>,
|
|
<code>0Qi</code>
|
|
</li>
|
|
<li>
|
|
A <b>variable</b> number of powder "blocks" (<number>5</number> B64 characters which give us <number>6</number> powders per block).
|
|
<ul class = "indent">
|
|
<li>For each of the 5 powderable equipment fields [helmet, chestplate, leggings, boots, weapon], we will have the following:</li>
|
|
<li><number>1</number> B64 character that says that we need <number>n</number> blocks for this item.</li>
|
|
<li><number>n</number> blocks of <number>5</number> B64 characters.</li>
|
|
<li>
|
|
Since there are 4 <code>0</code>s (B64 0 = 0 unsigned) in this example, we have no powders on any of the armor piece (no blocks).
|
|
</li>
|
|
<li>
|
|
Then, we have <code>1</code> (B64 1 = 1 unsigned). There is 1 block of powders to decode for the weapon item. That is <code>00nZ6</code>.
|
|
</li>
|
|
<ul class = "indent">
|
|
<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>
|
|
</div>
|
|
|
|
</div>
|
|
<div class="row section" title="Crafted Items">
|
|
<p>
|
|
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>
|
|
<ul class = "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>
|
|
<div class = "row section" title = "ID number specifics">
|
|
<p>
|
|
For ingredients, you can download the ingredient id map here: <a href = "../ing_map.json" target = "_blank">ing_map.json</a>. The ID number for No Ingredient is 4000.
|
|
</p>
|
|
<p>
|
|
For recipes, you can download the recipe id map here: <a href = "../recipe_map.json" target = "_blank">recipe_map.json</a> or the recipe DB here: <a href = "recipes_clean.json" target = "_blank">recipes_clean.json</a>.
|
|
</p>
|
|
</div>
|
|
|
|
<div class = "row section" title = "Version 1">
|
|
<p>
|
|
This is the first version of crafted item encoding. Crafted Items are always stored in a constant number of B64 characters.
|
|
</p>
|
|
<div class = "row section" title = "Example - Crafted Item">
|
|
<p>
|
|
This example shows how to parse a crafted item hash.
|
|
</p>
|
|
<code class = "full-width">
|
|
CR-1628i8v8v94948f21
|
|
</code>
|
|
<p>
|
|
Crafted item hash format:
|
|
</p>
|
|
<ul class = "indent">
|
|
<li><number>3</number> characters to denote item type as crafted: <code>CR-</code> (always)</li>
|
|
<li><number>1</number> character for encoding version: <code>1</code> </li>
|
|
<li><number>6</number> ingredient IDs (<number>2</number> B64 characters each):
|
|
<code>62</code>,
|
|
<code>8i</code>,
|
|
<code>8v</code>,
|
|
<code>8v</code>,
|
|
<code>94</code>,
|
|
<code>94</code>
|
|
</li>
|
|
<li><number>2</number> B64 characters for recipe ID: <code>8f</code></li>
|
|
<li><number>1</number> character to encode material tiers: <code>2</code>
|
|
<ul class = "indent">
|
|
<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>
|
|
</ul>
|
|
</li>
|
|
<li><number>1</number> character to encode attack speed: <code>1</code>
|
|
<ul class = "indent">
|
|
<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>
|
|
</ul>
|
|
</li>
|
|
</ul>
|
|
|
|
<p>
|
|
You may need to parse a crafted item from a wynnbuilder crafter link.
|
|
</p>
|
|
<code class = "full-width">
|
|
https://hppeng-wynn.github.io/crafter/#1628i8v8v94948f21
|
|
</code>
|
|
<p>
|
|
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.
|
|
</p>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
<div class="row section" title="Custom Items">
|
|
<p>
|
|
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".
|
|
</p>
|
|
<div class = "row section" title = "Version 1">
|
|
<p>This is the first version of custom item encoding and decoding.</p>
|
|
<p>You will need the full array of item identification saving order and all non-rolled identifications (ex: name). View them below.</p>
|
|
<div class = "row section" title = "Important Arrays">
|
|
<p> ID saving order: <code>ci_save_order = ["name", "lore", "tier", "set", "slots", "type", "material", "drop", "quest", "nDam", "fDam", "wDam", "aDam", "tDam", "eDam", "atkSpd", "hp", "fDef", "wDef", "aDef", "tDef", "eDef", "lvl", "classReq", "strReq", "dexReq", "intReq", "defReq", "agiReq","str", "dex", "int", "agi", "def", "id", "skillpoints", "reqs", "nDam_", "fDam_", "wDam_", "aDam_", "tDam_", "eDam_", "majorIds", "hprPct", "mr", "sdPct", "mdPct", "ls", "ms", "xpb", "lb", "ref", "thorns", "expd", "spd", "atkTier", "poison", "hpBonus", "spRegen", "eSteal", "hprRaw", "sdRaw", "mdRaw", "fDamPct", "wDamPct", "aDamPct", "tDamPct", "eDamPct", "fDefPct", "wDefPct", "aDefPct", "tDefPct", "eDefPct", "spPct1", "spRaw1", "spPct2", "spRaw2", "spPct3", "spRaw3", "spPct4", "spRaw4", "rainbowRaw", "sprint", "sprintReg", "jh", "lq", "gXp", "gSpd","durability","duration","charges"];</code> </p>
|
|
<p> Non-rolled string IDs: <code>nonRolled_strings = ["name", "lore", "tier", "set", "type", "material", "drop", "quest", "majorIds", "classReq", "atkSpd", "displayName", "nDam", "fDam", "wDam", "aDam", "tDam", "eDam", "nDam_", "fDam_", "wDam_", "aDam_", "tDam_", "eDam_", "durability", "duration"];</code></p>
|
|
<p> Rolled IDs: <code>rolledIDs = ["hprPct", "mr", "sdPct", "mdPct", "ls", "ms", "xpb", "lb", "ref", "thorns", "expd", "spd", "atkTier", "poison", "hpBonus", "spRegen", "eSteal", "hprRaw", "sdRaw", "mdRaw", "fDamPct", "wDamPct", "aDamPct", "tDamPct", "eDamPct", "fDefPct", "wDefPct", "aDefPct", "tDefPct", "eDefPct", "spPct1", "spRaw1", "spPct2", "spRaw2", "spPct3", "spRaw3", "spPct4", "spRaw4", "rainbowRaw", "sprint", "sprintReg", "jh", "lq", "gXp", "gSpd"];</code></p>
|
|
<p> Non-rolled IDs: <code>nonRolledIDs = ["name", "lore", "displayName", "tier", "set", "slots", "type", "material", "drop", "quest", "restrict", "nDam", "fDam", "wDam", "aDam", "tDam", "eDam", "atkSpd", "hp", "fDef", "wDef", "aDef", "tDef", "eDef", "lvl", "classReq", "strReq", "dexReq", "intReq", "defReq", "agiReq", "str", "dex", "int", "agi", "def", "fixID", "category", "id", "skillpoints", "reqs", "nDam_", "fDam_", "wDam_", "aDam_", "tDam_", "eDam_", "majorIds"];</code></p>
|
|
<p> Tiers: <code>tiers = ["Normal", "Unique", "Rare", "Legendary", "Fabled", "Mythic", "Set", "Crafted"]</code></p>
|
|
<p> Types: <code>types = [ "helmet", "chestplate", "leggings", "boots", "ring", "bracelet", "necklace", "wand", "spear", "bow", "dagger", "relik", "potion", "scroll", "food"];</code></p>
|
|
<p> Attack Speeds: <code>attackSpeeds = ["SUPER_SLOW", "VERY_SLOW", "SLOW", "NORMAL", "FAST", "VERY_FAST", "SUPER_FAST"];</code></p>
|
|
<p> Class Requirements: <code>classes = ["Warrior", "Assassin", "Mage", "Archer", "Shaman"]</code> </p>
|
|
</div>
|
|
|
|
<div class = "row section" title = "Example">
|
|
<p>
|
|
Here's an example of a custom item hash.
|
|
</p>
|
|
<code class = "full-width">
|
|
CI-10000HMeta%20Chestplate010Gbest%20in%20slot0240401030510G0302SG0H020Fe0I020Fe0J020Fe0K020Fe0L020Fe0M0201Y0i0200U220z0204iKK150200U22160200U22170200U22180200U22190200U22
|
|
</code>
|
|
<p>
|
|
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>
|
|
<ul class = "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:
|
|
<ul class = "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").
|
|
<ul class = "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.
|
|
<ul class = "indent">
|
|
<li>Rolled IDs (with non-fixed IDs):
|
|
<ul class = "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:
|
|
<ul class = "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.
|
|
<ul class = "indent">
|
|
<li>"CI-" constant portion</li>
|
|
<li>Encoding version number: <code>1</code></li>
|
|
<li>Fixed IDs: <code>0</code> (non-fixed IDs)</li>
|
|
<li><code>000HMeta%20Chestplate</code>
|
|
<ul class = "indent">
|
|
<li>ID name: <code>00</code> ("name")</li>
|
|
<li>ID value length: <code>0H</code> (<number>17</number>)</li>
|
|
<li>ID value: <code>Meta%20Chestplate</code> ("Meta Chestplate")</li>
|
|
</ul>
|
|
</li>
|
|
<li><code>010Gbest%20in%20slot</code>
|
|
<ul class = "indent">
|
|
<li>ID name: <code>01</code> ("lore")</li>
|
|
<li>ID value length: <code>0G</code> (<number>16</number>)</li>
|
|
<li>ID value: <code>best%20in%20slot</code> ("best in slot")</li>
|
|
</ul>
|
|
</li>
|
|
<li><code>024</code>
|
|
<ul class = "indent">
|
|
<li>ID name: <code>02</code> ("tier")</li>
|
|
<li>ID value length: None (exception) </li>
|
|
<li>ID value: <code>4</code> (tiers[4] = "Fabled")</li>
|
|
</ul>
|
|
</li>
|
|
<li><code>040103</code>
|
|
<ul class = "indent">
|
|
<li>ID name: <code>04</code> ("slots")</li>
|
|
<li>ID value length: <code>01</code> (<number>1</number>)</li>
|
|
<li>ID sign: <code>0</code> (positive)</li>
|
|
<li>ID value: <code>3</code> (<number>3</number>)</li>
|
|
</ul>
|
|
</li>
|
|
<li><code>051</code>
|
|
<ul class = "indent">
|
|
<li>ID name: <code>05</code> ("type")</li>
|
|
<li>ID value length: None (exception)</li>
|
|
<li>ID value: <code>1</code> (types[1] = "chestplate")</li>
|
|
</ul>
|
|
</li>
|
|
<li><code>0G0302SG</code>
|
|
<ul class = "indent">
|
|
<li>ID name: <code>0G</code> ("hp")</li>
|
|
<li>ID value length: <code>03</code> (<number>3</number>) </li>
|
|
<li>ID sign: <code>0</code> (positive)</li>
|
|
<li>ID value: <code>2SG</code> (<number>10000</number>)</li>
|
|
</ul>
|
|
</li>
|
|
<li><code>0H020Fe</code>
|
|
<ul class = "indent">
|
|
<li>ID name: <code>0H</code> ("fDef")</li>
|
|
<li>ID value length: <code>02</code> (<number>2</number>) </li>
|
|
<li>ID sign: <code>0</code> (positive)</li>
|
|
<li>ID value: <code>Fe</code> (<number>1000</number>)</li>
|
|
</ul>
|
|
</li>
|
|
<li><code>0I020Fe</code>
|
|
<ul class = "indent">
|
|
<li>ID name: <code>0I</code> ("wDef")</li>
|
|
<li>ID value length: <code>02</code> (<number>2</number>) </li>
|
|
<li>ID sign: <code>0</code> (positive)</li>
|
|
<li>ID value: <code>Fe</code> (<number>1000</number>)</li>
|
|
</ul>
|
|
</li>
|
|
<li><code>0J020Fe</code>
|
|
<ul class = "indent">
|
|
<li>ID name: <code>0J</code> ("aDef")</li>
|
|
<li>ID value length: <code>02</code> (<number>2</number>) </li>
|
|
<li>ID sign: <code>0</code> (positive)</li>
|
|
<li>ID value: <code>Fe</code> (<number>1000</number>)</li>
|
|
</ul>
|
|
</li>
|
|
<li><code>0K020Fe</code>
|
|
<ul class = "indent">
|
|
<li>ID name: <code>0K</code> ("tDef")</li>
|
|
<li>ID value length: <code>02</code> (<number>2</number>) </li>
|
|
<li>ID sign: <code>0</code> (positive)</li>
|
|
<li>ID value: <code>Fe</code> (<number>1000</number>)</li>
|
|
</ul>
|
|
</li>
|
|
<li><code>0L020Fe</code>
|
|
<ul class = "indent">
|
|
<li>ID name: <code>0L</code> ("eDef")</li>
|
|
<li>ID value length: <code>02</code> (<number>2</number>) </li>
|
|
<li>ID sign: <code>0</code> (positive)</li>
|
|
<li>ID value: <code>Fe</code> (<number>1000</number>)</li>
|
|
</ul>
|
|
</li>
|
|
<li><code>0M0201Y</code>
|
|
<ul class = "indent">
|
|
<li>ID name: <code>0M</code> ("lvl")</li>
|
|
<li>ID value length: <code>02</code> (<number>2</number>) </li>
|
|
<li>ID sign: <code>0</code> (positive)</li>
|
|
<li>ID value: <code>1Y</code> (<number>98</number>)</li>
|
|
</ul>
|
|
</li>
|
|
<li><code>0i0200U22</code>
|
|
<ul class = "indent">
|
|
<li>ID name: <code>0i</code> ("hprPct")</li>
|
|
<li>ID value length: <code>02</code> (<number>2</number>) </li>
|
|
<li>ID sign: <code>0</code> (both positive)</li>
|
|
<li>ID value minimum: <code>0U</code> (<number>30</number>)</li>
|
|
<li>ID value maximum: <code>22</code> (<number>130</number>)</li>
|
|
</ul>
|
|
</li>
|
|
<li><code>0z0204iKK</code>
|
|
<ul class = "indent">
|
|
<li>ID name: <code>0z</code> ("hprRaw")</li>
|
|
<li>ID value length: <code>02</code> (<number>2</number>) </li>
|
|
<li>ID sign: <code>0</code> (both positive)</li>
|
|
<li>ID value minimum: <code>4i</code> (<number>300</number>)</li>
|
|
<li>ID value maximum: <code>KK</code> (<number>1300</number>)</li>
|
|
</ul>
|
|
</li>
|
|
<li><code>0z0204iKK</code>
|
|
<ul class = "indent">
|
|
<li>ID name: <code>0z</code> ("hprRaw")</li>
|
|
<li>ID value length: <code>02</code> (<number>2</number>) </li>
|
|
<li>ID sign: <code>0</code> (both positive)</li>
|
|
<li>ID value minimum: <code>4i</code> (<number>300</number>)</li>
|
|
<li>ID value maximum: <code>KK</code> (<number>1300</number>)</li>
|
|
</ul>
|
|
</li>
|
|
<li><code>150200U22</code>
|
|
<ul class = "indent">
|
|
<li>ID name: <code>15</code> ("fDefPct")</li>
|
|
<li>ID value length: <code>02</code> (<number>2</number>) </li>
|
|
<li>ID sign: <code>0</code> (both positive)</li>
|
|
<li>ID value minimum: <code>0U</code> (<number>30</number>)</li>
|
|
<li>ID value maximum: <code>22</code> (<number>130</number>)</li>
|
|
</ul>
|
|
</li>
|
|
<li><code>160200U22</code>
|
|
<ul class = "indent">
|
|
<li>ID name: <code>16</code> ("wDefPct")</li>
|
|
<li>ID value length: <code>02</code> (<number>2</number>) </li>
|
|
<li>ID sign: <code>0</code> (both positive)</li>
|
|
<li>ID value minimum: <code>0U</code> (<number>30</number>)</li>
|
|
<li>ID value maximum: <code>22</code> (<number>130</number>)</li>
|
|
</ul>
|
|
</li>
|
|
<li><code>170200U22</code>
|
|
<ul class = "indent">
|
|
<li>ID name: <code>17</code> ("aDefPct")</li>
|
|
<li>ID value length: <code>02</code> (<number>2</number>) </li>
|
|
<li>ID sign: <code>0</code> (both positive)</li>
|
|
<li>ID value minimum: <code>0U</code> (<number>30</number>)</li>
|
|
<li>ID value maximum: <code>22</code> (<number>130</number>)</li>
|
|
</ul>
|
|
</li>
|
|
<li><code>180200U22</code>
|
|
<ul class = "indent">
|
|
<li>ID name: <code>18</code> ("tDefPct")</li>
|
|
<li>ID value length: <code>02</code> (<number>2</number>) </li>
|
|
<li>ID sign: <code>0</code> (both positive)</li>
|
|
<li>ID value minimum: <code>0U</code> (<number>30</number>)</li>
|
|
<li>ID value maximum: <code>22</code> (<number>130</number>)</li>
|
|
</ul>
|
|
</li>
|
|
<li><code>190200U22</code>
|
|
<ul class = "indent">
|
|
<li>ID name: <code>19</code> ("eDefPct")</li>
|
|
<li>ID value length: <code>02</code> (<number>2</number>) </li>
|
|
<li>ID sign: <code>0</code> (both positive)</li>
|
|
<li>ID value minimum: <code>0U</code> (<number>30</number>)</li>
|
|
<li>ID value maximum: <code>22</code> (<number>130</number>)</li>
|
|
</ul>
|
|
</li>
|
|
</ul>
|
|
</li>
|
|
</ul>
|
|
<!-- TODO -->
|
|
|
|
<p>
|
|
You may need to parse a custom item from a Wynnbuilder customizer link.
|
|
</p>
|
|
<code class = "full-width">
|
|
hppeng-wynn.github.io/custom/#10000HMeta%20Chestplate010Gbest%20in%20slot0240401030510G0302SG0H020Fe0I020Fe0J020Fe0K020Fe0L020Fe0M0201Y0i0200U220z0204iKK150200U22160200U22170200U22180200U22190200U22
|
|
</code>
|
|
<p>
|
|
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.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<p>
|
|
Last updated: 30 May 2022
|
|
</p>
|
|
</div>
|
|
<div class="row section" title="Wynnbuilder Internals (compute graph)">
|
|
<p>
|
|
This section is about how Wynnbuilder's main builder page processes user input and calculates results.
|
|
Might be useful if you want to script wynnbuilder or extend it! Or for wynnbuilder developers (internal docs).
|
|
</p>
|
|
<div class="row section" title="Why?">
|
|
<p>
|
|
Modeling wynnbuilder's internal computations as a directed graph has a few advantages:
|
|
</p>
|
|
<ul class = "indent">
|
|
<li>Each compute "node" is small(er); easier to debug.</li>
|
|
<li>Information flow is specified explicitly (easier to debug).</li>
|
|
<li>Easy to build caching for arbitrary computations (only calculate what u need)</li>
|
|
<li>Stateless builder! Abstract the entire builder as a chain of function calls</li>
|
|
<li>Makes for pretty pictures</li>
|
|
</ul>
|
|
</div>
|
|
<div class="row section" title="TODO ComputeNode details">
|
|
TODO
|
|
</div>
|
|
<p>
|
|
An overview of wynnbuilder's internal structure can be seen <a href = "./compute_graph.svg" target = "_blank">here</a>. Arrows indicate flow of information.
|
|
Colors correspond roughly as follows:
|
|
</p>
|
|
<img src="./builder_colorcode.png"/>
|
|
<p>
|
|
The overall logic flow is as follows:
|
|
<ul class = "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:
|
|
<ul class = "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>
|
|
<div class="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.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<!-- <div class="row section" title="Test Section">
|
|
</div> -->
|
|
</div>
|
|
<script type="text/javascript" src="../js/dev.js"></script>
|
|
<script type="text/javascript" src="../js/icons.js"></script>
|
|
</body>
|
|
|
|
</html>
|