Wynn versioning method (#238)
* 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>
This commit is contained in:
parent
ba1f23e7ab
commit
2561feb621
30 changed files with 35583 additions and 32047 deletions
File diff suppressed because one or more lines are too long
|
@ -1313,13 +1313,12 @@
|
||||||
<script type="text/javascript" src="../js/load_tome.js"></script>
|
<script type="text/javascript" src="../js/load_tome.js"></script>
|
||||||
<script type="text/javascript" src="../js/custom.js"></script>
|
<script type="text/javascript" src="../js/custom.js"></script>
|
||||||
<script type="text/javascript" src="../js/craft.js"></script>
|
<script type="text/javascript" src="../js/craft.js"></script>
|
||||||
<script type="text/javascript" src="../js/builder/atree_constants_min.js"></script>
|
|
||||||
<script type="text/javascript" src="../js/builder/build.js"></script>
|
<script type="text/javascript" src="../js/builder/build.js"></script>
|
||||||
<script type="text/javascript" src="../js/builder/builder_constants.js"></script>
|
<script type="text/javascript" src="../js/builder/builder_constants.js"></script>
|
||||||
<script type="text/javascript" src="../js/builder/build_encode_decode.js"></script>
|
<script type="text/javascript" src="../js/builder/build_encode_decode.js"></script>
|
||||||
<script type="text/javascript" src="../js/builder/atree.js"></script>
|
<script type="text/javascript" src="../js/builder/atree.js"></script>
|
||||||
<script type="text/javascript" src="../js/builder/builder.js"></script>
|
|
||||||
<script type="text/javascript" src="../js/builder/builder_graph.js"></script>
|
<script type="text/javascript" src="../js/builder/builder_graph.js"></script>
|
||||||
|
<script type="text/javascript" src="../js/builder/builder.js"></script>
|
||||||
<!--script type="text/javascript" src="../js/builder/optimize.js"></script-->
|
<!--script type="text/javascript" src="../js/builder/optimize.js"></script-->
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
62740
clean.json
62740
clean.json
File diff suppressed because it is too large
Load diff
File diff suppressed because one or more lines are too long
1
data/2.0.1.1/atree.json
Normal file
1
data/2.0.1.1/atree.json
Normal file
File diff suppressed because one or more lines are too long
1
data/2.0.1.1/ingreds.json
Normal file
1
data/2.0.1.1/ingreds.json
Normal file
File diff suppressed because one or more lines are too long
1
data/2.0.1.1/items.json
Normal file
1
data/2.0.1.1/items.json
Normal file
File diff suppressed because one or more lines are too long
809
data/2.0.1.1/tomes.json
Normal file
809
data/2.0.1.1/tomes.json
Normal file
|
@ -0,0 +1,809 @@
|
||||||
|
{
|
||||||
|
"tomes": [
|
||||||
|
{
|
||||||
|
"name": "Retaliating Tome of Armour Mastery I",
|
||||||
|
"tier": "Fabled",
|
||||||
|
"type": "armorTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 60,
|
||||||
|
"defmobs": 3,
|
||||||
|
"thorns": 6,
|
||||||
|
"ref": 6,
|
||||||
|
"hpBonus": 120,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 0,
|
||||||
|
"alias": "Thorns I"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Retaliating Tome of Armour Mastery II",
|
||||||
|
"tier": "Fabled",
|
||||||
|
"type": "armorTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 100,
|
||||||
|
"defMobs": 5,
|
||||||
|
"thorns": 8,
|
||||||
|
"ref": 8,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 1,
|
||||||
|
"alias": "Thorns II"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Destructive Tome of Armour Mastery I",
|
||||||
|
"tier": "Fabled",
|
||||||
|
"type": "armorTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 60,
|
||||||
|
"defMobs": 3,
|
||||||
|
"exploding": 5,
|
||||||
|
"mdPct": 5,
|
||||||
|
"hpBonus": 120,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 2,
|
||||||
|
"alias": "Melee I"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Destructive Tome of Armour Mastery II",
|
||||||
|
"tier": "Fabled",
|
||||||
|
"type": "armorTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 100,
|
||||||
|
"defMobs": 5,
|
||||||
|
"exploding": 6,
|
||||||
|
"mdPct": 6,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 3,
|
||||||
|
"alias": "Melee II"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Sorcerer's Tome of Armour Mastery I",
|
||||||
|
"tier": "Fabled",
|
||||||
|
"type": "armorTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 60,
|
||||||
|
"defMobs": 3,
|
||||||
|
"sdPct": 5,
|
||||||
|
"hpBonus": 120,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 4,
|
||||||
|
"alias": "Spell Damage I"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Sorcerer's Tome of Armour Mastery II",
|
||||||
|
"tier": "Fabled",
|
||||||
|
"type": "armorTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 100,
|
||||||
|
"defMobs": 5,
|
||||||
|
"sdPct": 6,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 5,
|
||||||
|
"alias": "Spell Damage II"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Everlasting Tome of Armour Mastery I",
|
||||||
|
"tier": "Fabled",
|
||||||
|
"type": "armorTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 60,
|
||||||
|
"defMobs": 3,
|
||||||
|
"hprRaw": 15,
|
||||||
|
"hpBonus": 120,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 6,
|
||||||
|
"alias": "Health Regen I"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Everlasting Tome of Armour Mastery II",
|
||||||
|
"tier": "Fabled",
|
||||||
|
"type": "armorTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 100,
|
||||||
|
"defMobs": 5,
|
||||||
|
"hprRaw": 60,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 7,
|
||||||
|
"alias": "Health Regen II"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Vampiric Tome of Armour Mastery I",
|
||||||
|
"tier": "Fabled",
|
||||||
|
"type": "armorTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 60,
|
||||||
|
"defMobs": 3,
|
||||||
|
"ls": 25,
|
||||||
|
"hpBonus": 120,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 8,
|
||||||
|
"alias": "Life Steal I"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Vampiric Tome of Armour Mastery II",
|
||||||
|
"tier": "Fabled",
|
||||||
|
"type": "armorTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 100,
|
||||||
|
"defMobs": 5,
|
||||||
|
"ls": 85,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 9,
|
||||||
|
"alias": "Life Steal II"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Greedy Tome of Armour Mastery I",
|
||||||
|
"tier": "Fabled",
|
||||||
|
"type": "armorTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 60,
|
||||||
|
"defMobs": 3,
|
||||||
|
"lb": 5,
|
||||||
|
"hpBonus": 120,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 10,
|
||||||
|
"alias": "Loot Bonus I"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Greedy Tome of Armour Mastery II",
|
||||||
|
"tier": "Fabled",
|
||||||
|
"type": "armorTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 100,
|
||||||
|
"defMobs": 5,
|
||||||
|
"lb": 6,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 11,
|
||||||
|
"alias": "Loot Bonus II"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Weightless Tome of Armour Mastery I",
|
||||||
|
"tier": "Fabled",
|
||||||
|
"type": "armorTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 60,
|
||||||
|
"defMobs": 3,
|
||||||
|
"spd": 5,
|
||||||
|
"hpBonus": 120,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 12,
|
||||||
|
"alias": "Walk Speed I"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Weightless Tome of Armour Mastery II",
|
||||||
|
"tier": "Fabled",
|
||||||
|
"type": "armorTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 100,
|
||||||
|
"defMobs": 5,
|
||||||
|
"spd": 6,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 13,
|
||||||
|
"alias": "Walk Speed II"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Blooming Tome of Armour Mastery II",
|
||||||
|
"tier": "Mythic",
|
||||||
|
"type": "armorTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 100,
|
||||||
|
"defMobs": 8,
|
||||||
|
"eDefPct": 10,
|
||||||
|
"hpBonus": 150,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 14,
|
||||||
|
"alias": "Earth Defense II"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Pulsing Tome of Armour Mastery II",
|
||||||
|
"tier": "Mythic",
|
||||||
|
"type": "armorTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 100,
|
||||||
|
"defMobs": 8,
|
||||||
|
"tDefPct": 10,
|
||||||
|
"hpBonus": 150,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 15,
|
||||||
|
"alias": "Thunder Defense II"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Oceanic Tome of Armour Mastery II",
|
||||||
|
"tier": "Mythic",
|
||||||
|
"type": "armorTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 100,
|
||||||
|
"defMobs": 8,
|
||||||
|
"wDefPct": 10,
|
||||||
|
"hpBonus": 150,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 16,
|
||||||
|
"alias": "Water Defense II"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Courageous Tome of Armour Mastery II",
|
||||||
|
"tier": "Mythic",
|
||||||
|
"type": "armorTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 100,
|
||||||
|
"defMobs": 8,
|
||||||
|
"fDefPct": 10,
|
||||||
|
"hpBonus": 150,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 17,
|
||||||
|
"alias": "Fire Defense II"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Clouded Tome of Armour Mastery II",
|
||||||
|
"tier": "Mythic",
|
||||||
|
"type": "armorTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 100,
|
||||||
|
"defMobs": 8,
|
||||||
|
"aDefPct": 10,
|
||||||
|
"hpBonus": 150,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 18,
|
||||||
|
"alias": "Air Defense II"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Radiant Tome of Armour Mastery II",
|
||||||
|
"tier": "Mythic",
|
||||||
|
"type": "armorTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 100,
|
||||||
|
"defMobs": 8,
|
||||||
|
"eDefPct": 6,
|
||||||
|
"tDefPct": 6,
|
||||||
|
"wDefPct": 6,
|
||||||
|
"fDefPct": 6,
|
||||||
|
"aDefPct": 6,
|
||||||
|
"hpBonus": 150,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 19,
|
||||||
|
"alias": "Rainbow Defense II"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Tome of Weapon Mastery I",
|
||||||
|
"tier": "Legendary",
|
||||||
|
"type": "weaponTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 60,
|
||||||
|
"damMobs": 6,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 20,
|
||||||
|
"alias": "Weapon Mastery I"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Earthbound Tome of Weapon Mastery I",
|
||||||
|
"tier": "Fabled",
|
||||||
|
"type": "weaponTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 80,
|
||||||
|
"damMobs": 7,
|
||||||
|
"str": 3,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 21,
|
||||||
|
"alias": "Strength I"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Earthbound Tome of Weapon Mastery II",
|
||||||
|
"tier": "Fabled",
|
||||||
|
"type": "weaponTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 80,
|
||||||
|
"damMobs": 8,
|
||||||
|
"str": 3,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 22,
|
||||||
|
"alias": "Strength II"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Nimble Tome of Weapon Mastery I",
|
||||||
|
"tier": "Fabled",
|
||||||
|
"type": "weaponTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 80,
|
||||||
|
"damMobs": 7,
|
||||||
|
"dex": 3,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 23,
|
||||||
|
"alias": "Dexterity I"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Nimble Tome of Weapon Mastery II",
|
||||||
|
"tier": "Fabled",
|
||||||
|
"type": "weaponTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 80,
|
||||||
|
"damMobs": 8,
|
||||||
|
"dex": 3,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 24,
|
||||||
|
"alias": "Dexterity II"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Mystical Tome of Weapon Mastery I",
|
||||||
|
"tier": "Fabled",
|
||||||
|
"type": "weaponTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 80,
|
||||||
|
"damMobs": 7,
|
||||||
|
"int": 3,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 25,
|
||||||
|
"alias": "Intelligence I"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Mystical Tome of Weapon Mastery II",
|
||||||
|
"tier": "Fabled",
|
||||||
|
"type": "weaponTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 80,
|
||||||
|
"damMobs": 8,
|
||||||
|
"int": 3,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 26,
|
||||||
|
"alias": "Intelligence II"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Warding Tome of Weapon Mastery I",
|
||||||
|
"tier": "Fabled",
|
||||||
|
"type": "weaponTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 80,
|
||||||
|
"damMobs": 7,
|
||||||
|
"def": 3,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 27,
|
||||||
|
"alias": "Defense I"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Warding Tome of Weapon Mastery II",
|
||||||
|
"tier": "Fabled",
|
||||||
|
"type": "weaponTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 80,
|
||||||
|
"damMobs": 8,
|
||||||
|
"def": 3,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 28,
|
||||||
|
"alias": "Defense II"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Athletic Tome of Weapon Mastery I",
|
||||||
|
"tier": "Fabled",
|
||||||
|
"type": "weaponTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 80,
|
||||||
|
"damMobs": 7,
|
||||||
|
"agi": 3,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 29,
|
||||||
|
"alias": "Agility I"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Athletic Tome of Weapon Mastery II",
|
||||||
|
"tier": "Fabled",
|
||||||
|
"type": "weaponTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 80,
|
||||||
|
"damMobs": 8,
|
||||||
|
"agi": 3,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 30,
|
||||||
|
"alias": "Agility II"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Cosmic Tome of Weapon Mastery I",
|
||||||
|
"tier": "Fabled",
|
||||||
|
"type": "weaponTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 80,
|
||||||
|
"damMobs": 7,
|
||||||
|
"str": 1,
|
||||||
|
"dex": 1,
|
||||||
|
"int": 1,
|
||||||
|
"def": 1,
|
||||||
|
"agi": 1,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 31,
|
||||||
|
"alias": "Rainbow Skillpoint I"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Cosmic Tome of Weapon Mastery II",
|
||||||
|
"tier": "Fabled",
|
||||||
|
"type": "weaponTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 80,
|
||||||
|
"damMobs": 8,
|
||||||
|
"str": 1,
|
||||||
|
"dex": 1,
|
||||||
|
"int": 1,
|
||||||
|
"def": 1,
|
||||||
|
"agi": 1,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 32,
|
||||||
|
"alias": "Rainbow Skillpoint II"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Seismic Tome of Weapon Mastery II",
|
||||||
|
"tier": "Mythic",
|
||||||
|
"type": "weaponTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 80,
|
||||||
|
"damMobs": 12,
|
||||||
|
"eDamPct": 7,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 33,
|
||||||
|
"alias": "Earth Damage II"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Voltaic Tome of Weapon Mastery II",
|
||||||
|
"tier": "Mythic",
|
||||||
|
"type": "weaponTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 80,
|
||||||
|
"damMobs": 12,
|
||||||
|
"tDamPct": 7,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 34,
|
||||||
|
"alias": "Thunder Damage II"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Abyssal Tome of Weapon Mastery II",
|
||||||
|
"tier": "Mythic",
|
||||||
|
"type": "weaponTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 80,
|
||||||
|
"damMobs": 12,
|
||||||
|
"wDamPct": 7,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 35,
|
||||||
|
"alias": "Water Damage II"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Infernal Tome of Weapon Mastery II",
|
||||||
|
"tier": "Mythic",
|
||||||
|
"type": "weaponTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 80,
|
||||||
|
"damMobs": 12,
|
||||||
|
"fDamPct": 7,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 36,
|
||||||
|
"alias": "Fire Damage II"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Cyclonic Tome of Weapon Mastery II",
|
||||||
|
"tier": "Mythic",
|
||||||
|
"type": "weaponTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 80,
|
||||||
|
"damMobs": 12,
|
||||||
|
"aDamPct": 7,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 37,
|
||||||
|
"alias": "Air Damage II"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Astral Tome of Weapon Mastery II",
|
||||||
|
"tier": "Mythic",
|
||||||
|
"type": "weaponTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 80,
|
||||||
|
"damMobs": 12,
|
||||||
|
"eDamPct": 6,
|
||||||
|
"tDamPct": 6,
|
||||||
|
"wDamPct": 6,
|
||||||
|
"fDamPct": 6,
|
||||||
|
"aDamPct": 6,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 38,
|
||||||
|
"alias": "Rainbow Damage II"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Brute's Tome of Allegiance",
|
||||||
|
"tier": "Legendary",
|
||||||
|
"type": "guildTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Untradable",
|
||||||
|
"lvl": 100,
|
||||||
|
"str": 3,
|
||||||
|
"eDamPct": 2,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 39,
|
||||||
|
"alias": "Strength"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Sadist's Tome of Allegiance",
|
||||||
|
"tier": "Legendary",
|
||||||
|
"type": "guildTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Untradable",
|
||||||
|
"lvl": 100,
|
||||||
|
"dex": 3,
|
||||||
|
"tDamPct": 2,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 40,
|
||||||
|
"alias": "Dexterity"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Mastermind's Tome of Allegiance",
|
||||||
|
"tier": "Legendary",
|
||||||
|
"type": "guildTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Untradable",
|
||||||
|
"lvl": 100,
|
||||||
|
"int": 3,
|
||||||
|
"wDamPct": 2,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 41,
|
||||||
|
"alias": "Intelligence"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Arsonist's Tome of Allegiance",
|
||||||
|
"tier": "Legendary",
|
||||||
|
"type": "guildTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Untradable",
|
||||||
|
"lvl": 100,
|
||||||
|
"def": 3,
|
||||||
|
"fDamPct": 2,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 42,
|
||||||
|
"alias": "Defense"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Ghost's Tome of Allegiance",
|
||||||
|
"tier": "Legendary",
|
||||||
|
"type": "guildTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Untradable",
|
||||||
|
"lvl": 100,
|
||||||
|
"agi": 3,
|
||||||
|
"aDamPct": 2,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 43,
|
||||||
|
"alias": "Agility"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Psychopath's Tome of Allegiance",
|
||||||
|
"tier": "Legendary",
|
||||||
|
"type": "guildTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Untradable",
|
||||||
|
"lvl": 100,
|
||||||
|
"str": 2,
|
||||||
|
"dex": 2,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 44,
|
||||||
|
"alias": "ET"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Loner's Tome of Allegiance",
|
||||||
|
"tier": "Legendary",
|
||||||
|
"type": "guildTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Untradable",
|
||||||
|
"lvl": 100,
|
||||||
|
"str": 2,
|
||||||
|
"int": 2,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 45,
|
||||||
|
"alias": "EW"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Warlock's Tome of Allegiance",
|
||||||
|
"tier": "Legendary",
|
||||||
|
"type": "guildTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Untradable",
|
||||||
|
"lvl": 100,
|
||||||
|
"dex": 2,
|
||||||
|
"int": 2,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 46,
|
||||||
|
"alias": "TW"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Destroyer's Tome of Allegiance",
|
||||||
|
"tier": "Legendary",
|
||||||
|
"type": "guildTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Untradable",
|
||||||
|
"lvl": 100,
|
||||||
|
"str": 2,
|
||||||
|
"def": 2,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 47,
|
||||||
|
"alias": "EF"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Devil's Tome of Allegiance",
|
||||||
|
"tier": "Legendary",
|
||||||
|
"type": "guildTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Untradable",
|
||||||
|
"lvl": 100,
|
||||||
|
"dex": 2,
|
||||||
|
"def": 2,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 48,
|
||||||
|
"alias": "TF"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Alchemist's Tome of Allegiance",
|
||||||
|
"tier": "Legendary",
|
||||||
|
"type": "guildTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Untradable",
|
||||||
|
"lvl": 100,
|
||||||
|
"int": 2,
|
||||||
|
"def": 2,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 49,
|
||||||
|
"alias": "WF"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Barbarian's Tome of Allegiance",
|
||||||
|
"tier": "Legendary",
|
||||||
|
"type": "guildTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Untradable",
|
||||||
|
"lvl": 100,
|
||||||
|
"str": 2,
|
||||||
|
"agi": 2,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 50,
|
||||||
|
"alias": "EA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Freelancer's Tome of Allegiance",
|
||||||
|
"tier": "Legendary",
|
||||||
|
"type": "guildTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Untradable",
|
||||||
|
"lvl": 100,
|
||||||
|
"dex": 2,
|
||||||
|
"agi": 2,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 51,
|
||||||
|
"alias": "TA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Sycophant's Tome of Allegiance",
|
||||||
|
"tier": "Legendary",
|
||||||
|
"type": "guildTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Untradable",
|
||||||
|
"lvl": 100,
|
||||||
|
"int": 2,
|
||||||
|
"agi": 2,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 52,
|
||||||
|
"alias": "WA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Fanatic's Tome of Allegiance",
|
||||||
|
"tier": "Legendary",
|
||||||
|
"type": "guildTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Untradable",
|
||||||
|
"lvl": 100,
|
||||||
|
"def": 2,
|
||||||
|
"agi": 2,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 53,
|
||||||
|
"alias": "FA"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Assimilator's Tome of Allegiance",
|
||||||
|
"tier": "Legendary",
|
||||||
|
"type": "guildTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Untradable",
|
||||||
|
"lvl": 100,
|
||||||
|
"str": 1,
|
||||||
|
"dex": 1,
|
||||||
|
"int": 1,
|
||||||
|
"def": 1,
|
||||||
|
"agi": 1,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 54,
|
||||||
|
"alias": "Rainbow"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
1
data/2.0.1.2/atree.json
Normal file
1
data/2.0.1.2/atree.json
Normal file
File diff suppressed because one or more lines are too long
1
data/2.0.1.2/ingreds.json
Normal file
1
data/2.0.1.2/ingreds.json
Normal file
File diff suppressed because one or more lines are too long
1
data/2.0.1.2/items.json
Normal file
1
data/2.0.1.2/items.json
Normal file
File diff suppressed because one or more lines are too long
1069
data/2.0.1.2/tomes.json
Normal file
1069
data/2.0.1.2/tomes.json
Normal file
File diff suppressed because it is too large
Load diff
|
@ -143,11 +143,82 @@
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<p>
|
<p>
|
||||||
All build links will end in "#[version number]_[build hash]".
|
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>
|
||||||
|
<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">
|
<div class="row section" title="Version 6">
|
||||||
<p>
|
<p>
|
||||||
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.
|
Version 6 was made to account for the desire to save tomes in a build.
|
||||||
</p>
|
</p>
|
||||||
<div class = "row section" title = "Example 1: With Tomes">
|
<div class = "row section" title = "Example 1: With Tomes">
|
||||||
<code class="full-width">
|
<code class="full-width">
|
||||||
|
|
1545
ingreds_clean.json
1545
ingreds_clean.json
File diff suppressed because it is too large
Load diff
File diff suppressed because one or more lines are too long
|
@ -18,6 +18,7 @@ atree_node: {
|
||||||
desc: str
|
desc: str
|
||||||
archetype: Optional[str] // not present or empty string = no arch
|
archetype: Optional[str] // not present or empty string = no arch
|
||||||
archetype_req: Optional[int] // default: 0
|
archetype_req: Optional[int] // default: 0
|
||||||
|
req_archetype: Optional[str] // what the req is for if no archetype defined... maybe clean up this data format later...?
|
||||||
base_abil: Optional[int] // Modify another abil? poorly defined...
|
base_abil: Optional[int] // Modify another abil? poorly defined...
|
||||||
parents: List[int]
|
parents: List[int]
|
||||||
dependencies: List[int] // Hard reqs
|
dependencies: List[int] // Hard reqs
|
||||||
|
@ -107,6 +108,21 @@ scaling_target: {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
// Space for big json data
|
||||||
|
let atrees;
|
||||||
|
let atree_load_complete = false;
|
||||||
|
/*
|
||||||
|
* Load atree info remote DB (aka a big json file).
|
||||||
|
*/
|
||||||
|
async function load_atree_data(version_str) {
|
||||||
|
let getUrl = window.location;
|
||||||
|
let baseUrl = `${getUrl.protocol}//${getUrl.host}/`;
|
||||||
|
// No random string -- we want to use caching
|
||||||
|
let url = `${baseUrl}/data/${version_str}/atree.json`;
|
||||||
|
atrees = await (await fetch(url)).json();
|
||||||
|
atree_load_complete = true;
|
||||||
|
}
|
||||||
|
|
||||||
const elem_mastery_abil = { display_name: "Elemental Mastery", id: 998, properties: {}, effects: [] };
|
const elem_mastery_abil = { display_name: "Elemental Mastery", id: 998, properties: {}, effects: [] };
|
||||||
|
|
||||||
// TODO: Range numbers
|
// TODO: Range numbers
|
||||||
|
@ -276,12 +292,17 @@ function abil_can_activate(atree_node, atree_state, reachable, archetype_count,
|
||||||
if (!node_reachable) {
|
if (!node_reachable) {
|
||||||
return [false, false, 'not reachable'];
|
return [false, false, 'not reachable'];
|
||||||
}
|
}
|
||||||
if ('archetype' in ability && ability.archetype !== "") {
|
if ('archetype_req' in ability && ability.archetype_req !== 0) {
|
||||||
if ('archetype_req' in ability && ability.archetype_req !== 0) {
|
let req_archetype;
|
||||||
const others = (archetype_count.get(ability.archetype) || 0);
|
if ('req_archetype' in ability && ability.req_archetype !== "") {
|
||||||
if (others < ability.archetype_req) {
|
req_archetype = ability.req_archetype;
|
||||||
return [false, false, ability.archetype+': '+others+' < '+ability.archetype_req];
|
}
|
||||||
}
|
else {
|
||||||
|
req_archetype = ability.archetype;
|
||||||
|
}
|
||||||
|
const others = (archetype_count.get(req_archetype) || 0);
|
||||||
|
if (others < ability.archetype_req) {
|
||||||
|
return [false, false, req_archetype+': '+others+' < '+ability.archetype_req];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ability.cost > points_remain) {
|
if (ability.cost > points_remain) {
|
||||||
|
@ -1259,7 +1280,8 @@ function generateTooltip(container, node_elem, ability, atree_map) {
|
||||||
// calculate if requirements are satisfied
|
// calculate if requirements are satisfied
|
||||||
let apUsed = 0;
|
let apUsed = 0;
|
||||||
let maxAP = parseInt(document.getElementById("active_AP_cap").innerHTML);
|
let maxAP = parseInt(document.getElementById("active_AP_cap").innerHTML);
|
||||||
let archChosen = 0;
|
let arch_chosen = 0;
|
||||||
|
const node_arch = ability.req_archetype || ability.archetype;
|
||||||
let satisfiedDependencies = [];
|
let satisfiedDependencies = [];
|
||||||
let blockedBy = [];
|
let blockedBy = [];
|
||||||
for (let [id, node_wrap] of atree_map.entries()) {
|
for (let [id, node_wrap] of atree_map.entries()) {
|
||||||
|
@ -1267,8 +1289,8 @@ function generateTooltip(container, node_elem, ability, atree_map) {
|
||||||
continue; // we don't want to count abilities that are not selected, and an ability should not count towards itself
|
continue; // we don't want to count abilities that are not selected, and an ability should not count towards itself
|
||||||
}
|
}
|
||||||
apUsed += node_wrap.ability.cost;
|
apUsed += node_wrap.ability.cost;
|
||||||
if (node_wrap.ability.archetype == ability.archetype) {
|
if (node_wrap.ability.archetype == node_arch) {
|
||||||
archChosen++;
|
arch_chosen++;
|
||||||
}
|
}
|
||||||
if (ability.dependencies.includes(id)) {
|
if (ability.dependencies.includes(id)) {
|
||||||
satisfiedDependencies.push(id);
|
satisfiedDependencies.push(id);
|
||||||
|
@ -1292,15 +1314,21 @@ function generateTooltip(container, node_elem, ability, atree_map) {
|
||||||
container.appendChild(cost);
|
container.appendChild(cost);
|
||||||
|
|
||||||
// archetype req
|
// archetype req
|
||||||
if (ability.archetype_req > 0 && ability.archetype != null) {
|
if (ability.archetype_req > 0) {
|
||||||
let archReq = make_elem("p", ["scaled-font", "my-0", "mx-1"], {});
|
let arch_req = make_elem("p", ["scaled-font", "my-0", "mx-1"], {});
|
||||||
if (archChosen >= ability.archetype_req) {
|
if ('req_archetype' in ability && ability.req_archetype !== "") {
|
||||||
archReq.innerHTML = reqYes;
|
req_archetype = ability.req_archetype;
|
||||||
} else {
|
|
||||||
archReq.innerHTML = reqNo;
|
|
||||||
}
|
}
|
||||||
archReq.innerHTML += "<span class = 'mc-gray'>Min " + ability.archetype + " Archetype:</span> " + archChosen + "<span class = 'mc-gray'>/" + ability.archetype_req;
|
else {
|
||||||
container.appendChild(archReq);
|
req_archetype = ability.archetype;
|
||||||
|
}
|
||||||
|
if (arch_chosen >= ability.archetype_req) {
|
||||||
|
arch_req.innerHTML = reqYes;
|
||||||
|
} else {
|
||||||
|
arch_req.innerHTML = reqNo;
|
||||||
|
}
|
||||||
|
arch_req.innerHTML += "<span class = 'mc-gray'>Min " + req_archetype+ " Archetype:</span> " + arch_chosen + "<span class = 'mc-gray'>/" + ability.archetype_req;
|
||||||
|
container.appendChild(arch_req);
|
||||||
}
|
}
|
||||||
|
|
||||||
// dependencies
|
// dependencies
|
||||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because one or more lines are too long
|
@ -27,128 +27,200 @@ function parsePowdering(powder_info) {
|
||||||
}
|
}
|
||||||
|
|
||||||
let atree_data = null;
|
let atree_data = null;
|
||||||
|
const wynn_version_names = [
|
||||||
|
'2.0.1.1',
|
||||||
|
'2.0.1.2'
|
||||||
|
];
|
||||||
|
const WYNN_VERSION_LATEST = wynn_version_names.length - 1;
|
||||||
|
// Default to the newest version.
|
||||||
|
let wynn_version_id = WYNN_VERSION_LATEST;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Populate fields based on url, and calculate build.
|
* Populate fields based on url, and calculate build.
|
||||||
|
* TODO: THIS CODE IS GOD AWFUL result of being lazy
|
||||||
|
* fix all the slice() and break into functions or do something about it... its inefficient, ugly and error prone
|
||||||
*/
|
*/
|
||||||
function decodeBuild(url_tag) {
|
async function parse_hash(url_tag) {
|
||||||
if (url_tag) {
|
const default_load_promises = [ load_atree_data(wynn_version_names[WYNN_VERSION_LATEST]),
|
||||||
//default values
|
load_init(), load_ing_init(), load_tome_init() ];
|
||||||
let equipment = [null, null, null, null, null, null, null, null, null];
|
if (!url_tag) {
|
||||||
let tomes = [null, null, null, null, null, null, null];
|
await Promise.all(default_load_promises);
|
||||||
let powdering = ["", "", "", "", ""];
|
return;
|
||||||
let info = url_tag.split("_");
|
}
|
||||||
let version = info[0];
|
//default values
|
||||||
let save_skp = false;
|
let equipment = [null, null, null, null, null, null, null, null, null];
|
||||||
let skillpoints = [0, 0, 0, 0, 0];
|
let tomes = [null, null, null, null, null, null, null];
|
||||||
let level = 106;
|
let powdering = ["", "", "", "", ""];
|
||||||
|
let info = url_tag.split("_");
|
||||||
|
let version = info[0];
|
||||||
|
let save_skp = false;
|
||||||
|
let skillpoints = [0, 0, 0, 0, 0];
|
||||||
|
let level = 106;
|
||||||
|
|
||||||
let version_number = parseInt(version)
|
let version_number = parseInt(version);
|
||||||
//equipment (items)
|
let data_str = info[1];
|
||||||
// TODO: use filters
|
if (version_number >= 8) {
|
||||||
if (version_number < 4) {
|
// parse query parameters
|
||||||
let equipments = info[1];
|
// https://stackoverflow.com/questions/901115/how-can-i-get-query-string-values-in-javascript
|
||||||
for (let i = 0; i < 9; ++i ) {
|
const url_params = new URLSearchParams(window.location.search);
|
||||||
let equipment_str = equipments.slice(i*3,i*3+3);
|
const version_id = url_params.get('v');
|
||||||
|
wynn_version_id = parseInt(version_id);
|
||||||
|
if (isNaN(wynn_version_id) || wynn_version_id > WYNN_VERSION_LATEST || wynn_version_id < 0) {
|
||||||
|
// TODO: maybe make the NAN try to use the human readable version?
|
||||||
|
// NOTE: Failing silently... do we want to raise a loud error?
|
||||||
|
console.log("Explicit version not found or invalid, using latest version");
|
||||||
|
wynn_version_id = WYNN_VERSION_LATEST;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log(`Build link for wynn version ${wynn_version_id} (${wynn_version_names[wynn_version_id]})`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Change the default to oldest. (A time before v8)
|
||||||
|
wynn_version_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// the deal with this is because old versions should default to 0 (oldest wynn item version), and v8+ defaults to latest.
|
||||||
|
// its ugly... but i think this is the behavior we want...
|
||||||
|
if (wynn_version_id != WYNN_VERSION_LATEST) {
|
||||||
|
// force reload item database and such.
|
||||||
|
// TODO MUST: display a warning showing older version!
|
||||||
|
const msg = 'This build was created in an older version of wynncraft '
|
||||||
|
+ `(${wynn_version_names[wynn_version_id]} < ${wynn_version_names[WYNN_VERSION_LATEST]}). `
|
||||||
|
+ 'Would you like to update to the latest version? Updating may break the build and ability tree.';
|
||||||
|
|
||||||
|
if (confirm(msg)) {
|
||||||
|
wynn_version_id = WYNN_VERSION_LATEST;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
version_name = wynn_version_names[wynn_version_id];
|
||||||
|
const load_promises = [ load_atree_data(version_name),
|
||||||
|
load_old_version(version_name),
|
||||||
|
load_ings_old_version(version_name),
|
||||||
|
load_tome_old_version(version_name) ];
|
||||||
|
console.log("Loading old version data...", version_name)
|
||||||
|
await Promise.all(load_promises);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (wynn_version_id == WYNN_VERSION_LATEST) {
|
||||||
|
await Promise.all(default_load_promises);
|
||||||
|
}
|
||||||
|
|
||||||
|
//equipment (items)
|
||||||
|
// TODO: use filters
|
||||||
|
if (version_number < 4) {
|
||||||
|
let equipments = info[1];
|
||||||
|
for (let i = 0; i < 9; ++i ) {
|
||||||
|
let equipment_str = equipments.slice(i*3,i*3+3);
|
||||||
|
equipment[i] = getItemNameFromID(Base64.toInt(equipment_str));
|
||||||
|
}
|
||||||
|
data_str = equipments.slice(27);
|
||||||
|
}
|
||||||
|
else if (version_number == 4) {
|
||||||
|
let info_str = data_str;
|
||||||
|
let start_idx = 0;
|
||||||
|
for (let i = 0; i < 9; ++i ) {
|
||||||
|
if (info_str.charAt(start_idx) === "-") {
|
||||||
|
equipment[i] = "CR-"+info_str.slice(start_idx+1, start_idx+18);
|
||||||
|
start_idx += 18;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let equipment_str = info_str.slice(start_idx, start_idx+3);
|
||||||
equipment[i] = getItemNameFromID(Base64.toInt(equipment_str));
|
equipment[i] = getItemNameFromID(Base64.toInt(equipment_str));
|
||||||
|
start_idx += 3;
|
||||||
}
|
}
|
||||||
info[1] = equipments.slice(27);
|
|
||||||
}
|
}
|
||||||
else if (version_number == 4) {
|
data_str = info_str.slice(start_idx);
|
||||||
let info_str = info[1];
|
}
|
||||||
let start_idx = 0;
|
else if (version_number <= 8) {
|
||||||
for (let i = 0; i < 9; ++i ) {
|
let info_str = data_str;
|
||||||
if (info_str.charAt(start_idx) === "-") {
|
let start_idx = 0;
|
||||||
equipment[i] = "CR-"+info_str.slice(start_idx+1, start_idx+18);
|
for (let i = 0; i < 9; ++i ) {
|
||||||
start_idx += 18;
|
if (info_str.slice(start_idx,start_idx+3) === "CR-") {
|
||||||
}
|
equipment[i] = info_str.slice(start_idx, start_idx+20);
|
||||||
else {
|
start_idx += 20;
|
||||||
let equipment_str = info_str.slice(start_idx, start_idx+3);
|
} else if (info_str.slice(start_idx+3,start_idx+6) === "CI-") {
|
||||||
equipment[i] = getItemNameFromID(Base64.toInt(equipment_str));
|
let len = Base64.toInt(info_str.slice(start_idx,start_idx+3));
|
||||||
start_idx += 3;
|
equipment[i] = info_str.slice(start_idx+3,start_idx+3+len);
|
||||||
}
|
start_idx += (3+len);
|
||||||
|
} else {
|
||||||
|
let equipment_str = info_str.slice(start_idx, start_idx+3);
|
||||||
|
equipment[i] = getItemNameFromID(Base64.toInt(equipment_str));
|
||||||
|
start_idx += 3;
|
||||||
}
|
}
|
||||||
info[1] = info_str.slice(start_idx);
|
|
||||||
}
|
}
|
||||||
else if (version_number <= 7) {
|
data_str = info_str.slice(start_idx);
|
||||||
let info_str = info[1];
|
}
|
||||||
let start_idx = 0;
|
//constant in all versions
|
||||||
for (let i = 0; i < 9; ++i ) {
|
for (let i in equipment) {
|
||||||
if (info_str.slice(start_idx,start_idx+3) === "CR-") {
|
setValue(equipment_inputs[i], equipment[i]);
|
||||||
equipment[i] = info_str.slice(start_idx, start_idx+20);
|
}
|
||||||
start_idx += 20;
|
|
||||||
} else if (info_str.slice(start_idx+3,start_idx+6) === "CI-") {
|
//level, skill point assignments, and powdering
|
||||||
let len = Base64.toInt(info_str.slice(start_idx,start_idx+3));
|
if (version_number == 1) {
|
||||||
equipment[i] = info_str.slice(start_idx+3,start_idx+3+len);
|
let powder_info = data_str;
|
||||||
start_idx += (3+len);
|
let res = parsePowdering(powder_info);
|
||||||
} else {
|
powdering = res[0];
|
||||||
let equipment_str = info_str.slice(start_idx, start_idx+3);
|
} else if (version_number == 2) {
|
||||||
equipment[i] = getItemNameFromID(Base64.toInt(equipment_str));
|
save_skp = true;
|
||||||
start_idx += 3;
|
let skillpoint_info = data_str.slice(0, 10);
|
||||||
}
|
for (let i = 0; i < 5; ++i ) {
|
||||||
}
|
skillpoints[i] = Base64.toIntSigned(skillpoint_info.slice(i*2,i*2+2));
|
||||||
info[1] = info_str.slice(start_idx);
|
|
||||||
}
|
|
||||||
//constant in all versions
|
|
||||||
for (let i in equipment) {
|
|
||||||
setValue(equipment_inputs[i], equipment[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//level, skill point assignments, and powdering
|
let powder_info = data_str.slice(10);
|
||||||
if (version_number == 1) {
|
let res = parsePowdering(powder_info);
|
||||||
let powder_info = info[1];
|
powdering = res[0];
|
||||||
let res = parsePowdering(powder_info);
|
} else if (version_number <= 8){
|
||||||
powdering = res[0];
|
level = Base64.toInt(data_str.slice(10,12));
|
||||||
} else if (version_number == 2) {
|
setValue("level-choice",level);
|
||||||
save_skp = true;
|
save_skp = true;
|
||||||
let skillpoint_info = info[1].slice(0, 10);
|
let skillpoint_info = data_str.slice(0, 10);
|
||||||
for (let i = 0; i < 5; ++i ) {
|
for (let i = 0; i < 5; ++i ) {
|
||||||
skillpoints[i] = Base64.toIntSigned(skillpoint_info.slice(i*2,i*2+2));
|
skillpoints[i] = Base64.toIntSigned(skillpoint_info.slice(i*2,i*2+2));
|
||||||
}
|
|
||||||
|
|
||||||
let powder_info = info[1].slice(10);
|
|
||||||
let res = parsePowdering(powder_info);
|
|
||||||
powdering = res[0];
|
|
||||||
} else if (version_number <= 7){
|
|
||||||
level = Base64.toInt(info[1].slice(10,12));
|
|
||||||
setValue("level-choice",level);
|
|
||||||
save_skp = true;
|
|
||||||
let skillpoint_info = info[1].slice(0, 10);
|
|
||||||
for (let i = 0; i < 5; ++i ) {
|
|
||||||
skillpoints[i] = Base64.toIntSigned(skillpoint_info.slice(i*2,i*2+2));
|
|
||||||
}
|
|
||||||
|
|
||||||
let powder_info = info[1].slice(12);
|
|
||||||
|
|
||||||
let res = parsePowdering(powder_info);
|
|
||||||
powdering = res[0];
|
|
||||||
info[1] = res[1];
|
|
||||||
}
|
}
|
||||||
// Tomes.
|
|
||||||
if (version >= 6) {
|
let powder_info = data_str.slice(12);
|
||||||
//tome values do not appear in anything before v6.
|
|
||||||
|
let res = parsePowdering(powder_info);
|
||||||
|
powdering = res[0];
|
||||||
|
data_str = res[1];
|
||||||
|
}
|
||||||
|
// Tomes.
|
||||||
|
if (version_number >= 6) {
|
||||||
|
//tome values do not appear in anything before v6.
|
||||||
|
if (version_number < 8) {
|
||||||
for (let i in tomes) {
|
for (let i in tomes) {
|
||||||
let tome_str = info[1].charAt(i);
|
let tome_str = data_str.charAt(i);
|
||||||
let tome_name = getTomeNameFromID(Base64.toInt(tome_str));
|
let tome_name = getTomeNameFromID(Base64.toInt(tome_str));
|
||||||
setValue(tomeInputs[i], tome_name);
|
setValue(tomeInputs[i], tome_name);
|
||||||
}
|
}
|
||||||
info[1] = info[1].slice(7);
|
data_str = data_str.slice(7);
|
||||||
}
|
|
||||||
|
|
||||||
if (version >= 7) {
|
|
||||||
// ugly af. only works since its the last thing. will be fixed with binary decode
|
|
||||||
atree_data = new BitVector(info[1]);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
atree_data = null;
|
// 2chr tome encoding to allow for more tomes.
|
||||||
|
for (let i in tomes) {
|
||||||
|
let tome_str = data_str.slice(2*i, 2*i+2);
|
||||||
|
let tome_name = getTomeNameFromID(Base64.toInt(tome_str));
|
||||||
|
setValue(tomeInputs[i], tome_name);
|
||||||
|
}
|
||||||
|
data_str = data_str.slice(14);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (let i in powder_inputs) {
|
if (version_number >= 7) {
|
||||||
setValue(powder_inputs[i], powdering[i]);
|
// ugly af. only works since its the last thing. will be fixed with binary decode
|
||||||
}
|
atree_data = new BitVector(data_str);
|
||||||
for (let i in skillpoints) {
|
}
|
||||||
setValue(skp_order[i] + "-skp", skillpoints[i]);
|
else {
|
||||||
}
|
atree_data = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i in powder_inputs) {
|
||||||
|
setValue(powder_inputs[i], powdering[i]);
|
||||||
|
}
|
||||||
|
for (let i in skillpoints) {
|
||||||
|
setValue(skp_order[i] + "-skp", skillpoints[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,7 +233,8 @@ function encodeBuild(build, powders, skillpoints, atree, atree_state) {
|
||||||
|
|
||||||
//V6 encoding - Tomes
|
//V6 encoding - Tomes
|
||||||
//V7 encoding - ATree
|
//V7 encoding - ATree
|
||||||
build_version = 5;
|
//V8 encoding - wynn version
|
||||||
|
build_version = 8;
|
||||||
build_string = "";
|
build_string = "";
|
||||||
tome_string = "";
|
tome_string = "";
|
||||||
|
|
||||||
|
@ -169,16 +242,16 @@ function encodeBuild(build, powders, skillpoints, atree, atree_state) {
|
||||||
if (item.statMap.get("custom")) {
|
if (item.statMap.get("custom")) {
|
||||||
let custom = "CI-"+encodeCustom(item, true);
|
let custom = "CI-"+encodeCustom(item, true);
|
||||||
build_string += Base64.fromIntN(custom.length, 3) + custom;
|
build_string += Base64.fromIntN(custom.length, 3) + custom;
|
||||||
build_version = Math.max(build_version, 5);
|
//build_version = Math.max(build_version, 5);
|
||||||
} else if (item.statMap.get("crafted")) {
|
} else if (item.statMap.get("crafted")) {
|
||||||
build_string += "CR-"+encodeCraft(item);
|
build_string += "CR-"+encodeCraft(item);
|
||||||
} else if (item.statMap.get("category") === "tome") {
|
} else if (item.statMap.get("category") === "tome") {
|
||||||
let tome_id = item.statMap.get("id");
|
let tome_id = item.statMap.get("id");
|
||||||
if (tome_id <= 60) {
|
if (tome_id <= 60) {
|
||||||
// valid normal tome. ID 61-63 is for NONE tomes.
|
// valid normal tome. ID 61-63 is for NONE tomes.
|
||||||
build_version = Math.max(build_version, 6);
|
//build_version = Math.max(build_version, 6);
|
||||||
}
|
}
|
||||||
tome_string += Base64.fromIntN(tome_id, 1);
|
tome_string += Base64.fromIntN(tome_id, 2);
|
||||||
} else {
|
} else {
|
||||||
build_string += Base64.fromIntN(item.statMap.get("id"), 3);
|
build_string += Base64.fromIntN(item.statMap.get("id"), 3);
|
||||||
}
|
}
|
||||||
|
@ -206,7 +279,7 @@ function encodeBuild(build, powders, skillpoints, atree, atree_state) {
|
||||||
build_string += tome_string;
|
build_string += tome_string;
|
||||||
|
|
||||||
if (atree.length > 0 && atree_state.get(atree[0].ability.id).active) {
|
if (atree.length > 0 && atree_state.get(atree[0].ability.id).active) {
|
||||||
build_version = Math.max(build_version, 7);
|
//build_version = Math.max(build_version, 7);
|
||||||
const bitvec = encode_atree(atree, atree_state);
|
const bitvec = encode_atree(atree, atree_state);
|
||||||
build_string += bitvec.toB64();
|
build_string += bitvec.toB64();
|
||||||
}
|
}
|
||||||
|
@ -215,14 +288,18 @@ function encodeBuild(build, powders, skillpoints, atree, atree_state) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function get_full_url() {
|
||||||
|
return `${url_base}?v=${wynn_version_id.toString()}${location.hash}`
|
||||||
|
}
|
||||||
|
|
||||||
function copyBuild() {
|
function copyBuild() {
|
||||||
copyTextToClipboard(url_base+location.hash);
|
copyTextToClipboard();
|
||||||
document.getElementById("copy-button").textContent = "Copied!";
|
document.getElementById("copy-button").textContent = "Copied!";
|
||||||
}
|
}
|
||||||
|
|
||||||
function shareBuild(build) {
|
function shareBuild(build) {
|
||||||
if (build) {
|
if (build) {
|
||||||
let text = url_base+location.hash+"\n"+
|
let text = url_base+'?v='+wynn_version_id.toString()+location.hash+"\n"+
|
||||||
"WynnBuilder build:\n"+
|
"WynnBuilder build:\n"+
|
||||||
"> "+build.items[0].statMap.get("displayName")+"\n"+
|
"> "+build.items[0].statMap.get("displayName")+"\n"+
|
||||||
"> "+build.items[1].statMap.get("displayName")+"\n"+
|
"> "+build.items[1].statMap.get("displayName")+"\n"+
|
||||||
|
|
|
@ -47,6 +47,8 @@ function loadBuild() {
|
||||||
let saveName = document.getElementById("build-name").value;
|
let saveName = document.getElementById("build-name").value;
|
||||||
|
|
||||||
if (Object.keys(savedBuilds).includes(saveName)) {
|
if (Object.keys(savedBuilds).includes(saveName)) {
|
||||||
|
// NOTE: this is broken since decodeBuild is async func.
|
||||||
|
// Doubly broken because of versioning... lets just kill this for now
|
||||||
decodeBuild(savedBuilds[saveName])
|
decodeBuild(savedBuilds[saveName])
|
||||||
document.getElementById("loaded-error").textContent = "";
|
document.getElementById("loaded-error").textContent = "";
|
||||||
document.getElementById("loaded-build").textContent = "Build loaded";
|
document.getElementById("loaded-build").textContent = "Build loaded";
|
||||||
|
@ -305,9 +307,8 @@ function collapse_element(elmnt) {
|
||||||
document.querySelector(elmnt).style.removeProperty('display');
|
document.querySelector(elmnt).style.removeProperty('display');
|
||||||
}
|
}
|
||||||
|
|
||||||
function init() {
|
async function init() {
|
||||||
console.log("builder.js init");
|
console.log("builder.js init");
|
||||||
init_autocomplete();
|
|
||||||
|
|
||||||
// Other "main" stuff
|
// Other "main" stuff
|
||||||
// Spell dropdowns
|
// Spell dropdowns
|
||||||
|
@ -329,34 +330,41 @@ function init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Masonry setup
|
// Masonry setup
|
||||||
let masonry = Macy({
|
try {
|
||||||
container: "#masonry-container",
|
let masonry = Macy({
|
||||||
columns: 1,
|
container: "#masonry-container",
|
||||||
mobileFirst: true,
|
columns: 1,
|
||||||
breakAt: {
|
mobileFirst: true,
|
||||||
1200: 4,
|
breakAt: {
|
||||||
},
|
1200: 4,
|
||||||
margin: {
|
},
|
||||||
x: 20,
|
margin: {
|
||||||
y: 20,
|
x: 20,
|
||||||
}
|
y: 20,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
});
|
let search_masonry = Macy({
|
||||||
|
container: "#search-results",
|
||||||
let search_masonry = Macy({
|
columns: 1,
|
||||||
container: "#search-results",
|
mobileFirst: true,
|
||||||
columns: 1,
|
breakAt: {
|
||||||
mobileFirst: true,
|
1200: 4,
|
||||||
breakAt: {
|
},
|
||||||
1200: 4,
|
margin: {
|
||||||
},
|
x: 20,
|
||||||
margin: {
|
y: 20,
|
||||||
x: 20,
|
}
|
||||||
y: 20,
|
});
|
||||||
}
|
} catch (e) {
|
||||||
|
console.log("Could not initialize macy components. Maybe you're offline?");
|
||||||
});
|
}
|
||||||
decodeBuild(url_tag);
|
await parse_hash(url_tag);
|
||||||
|
try {
|
||||||
|
init_autocomplete();
|
||||||
|
} catch (e) {
|
||||||
|
console.log("Could not initialize autocomplete. Maybe you're offline?");
|
||||||
|
}
|
||||||
builder_graph_init();
|
builder_graph_init();
|
||||||
for (const item_node of item_nodes) {
|
for (const item_node of item_nodes) {
|
||||||
if (item_node.get_value() === null) {
|
if (item_node.get_value() === null) {
|
||||||
|
@ -364,6 +372,7 @@ function init() {
|
||||||
if (confirm('One or more items failed to load correctly. This could be due to a corrupted build link, or (more likely) a database load failure. Would you like to reload?')) {
|
if (confirm('One or more items failed to load correctly. This could be due to a corrupted build link, or (more likely) a database load failure. Would you like to reload?')) {
|
||||||
hardReload();
|
hardReload();
|
||||||
}
|
}
|
||||||
|
console.log(item_node);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -375,7 +384,5 @@ window.onerror = function(message, source, lineno, colno, error) {
|
||||||
};
|
};
|
||||||
|
|
||||||
(async function() {
|
(async function() {
|
||||||
let load_promises = [ load_init(), load_ing_init(), load_tome_init() ];
|
await init();
|
||||||
await Promise.all(load_promises);
|
|
||||||
init();
|
|
||||||
})();
|
})();
|
||||||
|
|
26
js/load.js
26
js/load.js
|
@ -1,4 +1,4 @@
|
||||||
const DB_VERSION = 117;
|
const DB_VERSION = 118;
|
||||||
// @See https://github.com/mdn/learning-area/blob/master/javascript/apis/client-side-storage/indexeddb/video-store/index.jsA
|
// @See https://github.com/mdn/learning-area/blob/master/javascript/apis/client-side-storage/indexeddb/video-store/index.jsA
|
||||||
|
|
||||||
let db;
|
let db;
|
||||||
|
@ -92,13 +92,31 @@ function clean_item(item) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function load_old_version(version_str) {
|
||||||
|
load_in_progress = true;
|
||||||
|
let getUrl = window.location;
|
||||||
|
let baseUrl = `${getUrl.protocol}//${getUrl.host}/`;
|
||||||
|
// No random string -- we want to use caching
|
||||||
|
let url = `${baseUrl}/data/${version_str}/items.json`;
|
||||||
|
let result = await (await fetch(url)).json();
|
||||||
|
items = result.items;
|
||||||
|
for (const item of items) {
|
||||||
|
clean_item(item);
|
||||||
|
}
|
||||||
|
let sets_ = result.sets;
|
||||||
|
for (const set in sets_) {
|
||||||
|
sets.set(set, sets_[set]);
|
||||||
|
}
|
||||||
|
init_maps();
|
||||||
|
load_complete = true;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Load item set from remote DB (aka a big json file). Calls init() on success.
|
* Load item set from remote DB (aka a big json file). Calls init() on success.
|
||||||
*/
|
*/
|
||||||
async function load() {
|
async function load() {
|
||||||
|
|
||||||
let getUrl = window.location;
|
let getUrl = window.location;
|
||||||
let baseUrl = getUrl.protocol + "//" + getUrl.host + "/";// + getUrl.pathname.split('/')[1];
|
let baseUrl = `${getUrl.protocol}//${getUrl.host}/`;
|
||||||
// "Random" string to prevent caching!
|
// "Random" string to prevent caching!
|
||||||
let url = baseUrl + "/compress.json?"+new Date();
|
let url = baseUrl + "/compress.json?"+new Date();
|
||||||
let result = await (await fetch(url)).json();
|
let result = await (await fetch(url)).json();
|
||||||
|
@ -150,7 +168,7 @@ async function load_init() {
|
||||||
console.log("Skipping load...")
|
console.log("Skipping load...")
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
load_in_progress = true
|
load_in_progress = true;
|
||||||
if (reload) {
|
if (reload) {
|
||||||
console.log("Using new data...")
|
console.log("Using new data...")
|
||||||
await load();
|
await load();
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
const ING_DB_VERSION = 18;
|
const ING_DB_VERSION = 19;
|
||||||
|
|
||||||
// @See https://github.com/mdn/learning-area/blob/master/javascript/apis/client-side-storage/indexeddb/video-store/index.js
|
// @See https://github.com/mdn/learning-area/blob/master/javascript/apis/client-side-storage/indexeddb/video-store/index.js
|
||||||
|
|
||||||
|
@ -59,22 +59,41 @@ function clean_ing(ing) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function load_ings_old_version(version_str) {
|
||||||
|
iload_in_progress = true;
|
||||||
|
let getUrl = window.location;
|
||||||
|
let baseUrl = `${getUrl.protocol}//${getUrl.host}/`;
|
||||||
|
// No random string -- we want to use caching
|
||||||
|
let url = `${baseUrl}/data/${version_str}/ingreds.json`;
|
||||||
|
let result = await (await fetch(url)).json();
|
||||||
|
ings = result;
|
||||||
|
for (const id in ings) {
|
||||||
|
clean_ing(ings[id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
url = baseUrl + "/recipes_compress.json";
|
||||||
|
result = await (await fetch(url)).json();
|
||||||
|
recipes = result.recipes;
|
||||||
|
|
||||||
|
init_maps();
|
||||||
|
iload_complete = true;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Load item set from remote DB (aka a big json file). Calls init() on success.
|
* Load item set from remote DB (aka a big json file). Calls init() on success.
|
||||||
*/
|
*/
|
||||||
async function load_ings() {
|
async function load_ings() {
|
||||||
|
|
||||||
let getUrl = window.location;
|
let getUrl = window.location;
|
||||||
let baseUrl = getUrl.protocol + "//" + getUrl.host + "/";// + getUrl.pathname.split('/')[1];
|
let baseUrl = `${getUrl.protocol}//${getUrl.host}/`;
|
||||||
// "Random" string to prevent caching!
|
// "Random" string to prevent caching!
|
||||||
let url = baseUrl + "/ingreds_compress.json?"+new Date();
|
let url = baseUrl + "/ingreds_compress.json?"+new Date();
|
||||||
url = url.replace(/\w+.html/, "") ;
|
|
||||||
let result = await (await fetch(url)).json();
|
let result = await (await fetch(url)).json();
|
||||||
|
|
||||||
result = await (await fetch(url)).json();
|
result = await (await fetch(url)).json();
|
||||||
ings = result;
|
ings = result;
|
||||||
|
|
||||||
url = url.replace("/ingreds_compress.json", "/recipes_compress.json");
|
url = baseUrl + "/recipes_compress.json?"+new Date();
|
||||||
result = await (await fetch(url)).json();
|
result = await (await fetch(url)).json();
|
||||||
recipes = result.recipes;
|
recipes = result.recipes;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
const TOME_DB_VERSION = 5;
|
const TOME_DB_VERSION = 6;
|
||||||
// @See https://github.com/mdn/learning-area/blob/master/javascript/apis/client-side-storage/indexeddb/video-store/index.jsA
|
// @See https://github.com/mdn/learning-area/blob/master/javascript/apis/client-side-storage/indexeddb/video-store/index.jsA
|
||||||
|
|
||||||
let tdb;
|
let tdb;
|
||||||
|
@ -34,13 +34,27 @@ async function load_tome_local() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function load_tome_old_version(version_str) {
|
||||||
|
tload_in_progress = true;
|
||||||
|
let getUrl = window.location;
|
||||||
|
let baseUrl = `${getUrl.protocol}//${getUrl.host}/`;
|
||||||
|
// No random string -- we want to use caching
|
||||||
|
let url = `${baseUrl}/data/${version_str}/tomes.json`;
|
||||||
|
let result = await (await fetch(url)).json();
|
||||||
|
tomes = result.tomes;
|
||||||
|
for (const tome of tomes) {
|
||||||
|
//dependency on clean_item in load.js
|
||||||
|
clean_item(tome);
|
||||||
|
}
|
||||||
|
init_tome_maps();
|
||||||
|
tload_complete = true;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* Load tome set from remote DB (json). Calls init() on success.
|
* Load tome set from remote DB (json). Calls init() on success.
|
||||||
*/
|
*/
|
||||||
async function load_tome() {
|
async function load_tome() {
|
||||||
|
|
||||||
let getUrl = window.location;
|
let getUrl = window.location;
|
||||||
let baseUrl = getUrl.protocol + "//" + getUrl.host + "/";// + getUrl.pathname.split('/')[1];
|
let baseUrl = `${getUrl.protocol}//${getUrl.host}/`;
|
||||||
// "Random" string to prevent caching!
|
// "Random" string to prevent caching!
|
||||||
let url = baseUrl + "/tomes.json?"+new Date();
|
let url = baseUrl + "/tomes.json?"+new Date();
|
||||||
let result = await (await fetch(url)).json();
|
let result = await (await fetch(url)).json();
|
||||||
|
|
|
@ -3647,10 +3647,6 @@
|
||||||
"Mask of the Spirits": 3649,
|
"Mask of the Spirits": 3649,
|
||||||
"Inhibitor": 3650,
|
"Inhibitor": 3650,
|
||||||
"Spear of Testiness": 3651,
|
"Spear of Testiness": 3651,
|
||||||
"Blue Wynnter Sweater": 3648,
|
|
||||||
"Green Wynnter Sweater": 3649,
|
|
||||||
"Purple Wynnter Sweater": 3650,
|
|
||||||
"Red Wynnter Sweater": 3651,
|
|
||||||
"Snowtread Boots": 3652,
|
"Snowtread Boots": 3652,
|
||||||
"White Wynnter Sweater": 3653,
|
"White Wynnter Sweater": 3653,
|
||||||
"Keratoconus": 3579,
|
"Keratoconus": 3579,
|
||||||
|
@ -3768,5 +3764,35 @@
|
||||||
"Sharpened Seaglass": 3762,
|
"Sharpened Seaglass": 3762,
|
||||||
"Storyteller": 3763,
|
"Storyteller": 3763,
|
||||||
"Midnight Sun": 3764,
|
"Midnight Sun": 3764,
|
||||||
"Lachesism": 3765
|
"Lachesism": 3765,
|
||||||
|
"Bison Tipper": 3766,
|
||||||
|
"Decaying Headdress": 3767,
|
||||||
|
"Despondence": 3768,
|
||||||
|
"Expedition's End": 3769,
|
||||||
|
"Fire Sword Style-2": 3770,
|
||||||
|
"Black Wynnter Sweater": 3771,
|
||||||
|
"Brown Wynnter Sweater": 3772,
|
||||||
|
"Cerulean Wynnter Sweater": 3773,
|
||||||
|
"Pink Wynnter Sweater": 3774,
|
||||||
|
"Yellow Wynnter Sweater": 3775,
|
||||||
|
"Poison-Tipped Poleaxe": 3776,
|
||||||
|
"Compliance": 3777,
|
||||||
|
"Dispersion": 3778,
|
||||||
|
"Obstinance": 3779,
|
||||||
|
"Succession": 3780,
|
||||||
|
"Continuum": 3781,
|
||||||
|
"Divergence": 3782,
|
||||||
|
"Aleph Null": 3783,
|
||||||
|
"Fractal": 3784,
|
||||||
|
"Nonexistence": 3785,
|
||||||
|
"Infinitesimal": 3786,
|
||||||
|
"Recursion": 3787,
|
||||||
|
"Soul Ink": 3788,
|
||||||
|
"Swimmer Net": 3789,
|
||||||
|
"Unusual": 3790,
|
||||||
|
"Santa Earmuffs": 3791,
|
||||||
|
"Blue Wynnter Sweater": 3792,
|
||||||
|
"Green Wynnter Sweater": 3793,
|
||||||
|
"Purple Wynnter Sweater": 3794,
|
||||||
|
"Red Wynnter Sweater": 3795
|
||||||
}
|
}
|
|
@ -717,5 +717,18 @@
|
||||||
"Windswept Roots": 705,
|
"Windswept Roots": 705,
|
||||||
"Yale Leather": 706,
|
"Yale Leather": 706,
|
||||||
"Contraband Hibiscus": 717,
|
"Contraband Hibiscus": 717,
|
||||||
"Myocardial Leg": 718
|
"Myocardial Leg": 718,
|
||||||
|
"Broken Ram Horn": 719,
|
||||||
|
"Climber's Padding": 720,
|
||||||
|
"Rusty Spurs": 721,
|
||||||
|
"Sheep Hoof": 722,
|
||||||
|
"Consecrated Ivory": 723,
|
||||||
|
"Intermittenstirrups": 724,
|
||||||
|
"Natural Nitrates": 725,
|
||||||
|
"Pigman Ivory": 726,
|
||||||
|
"Runner's Bandages": 727,
|
||||||
|
"Blazing Stimulants": 728,
|
||||||
|
"Icy Crampons": 729,
|
||||||
|
"Sanctified Sheep Soul": 730,
|
||||||
|
"Solcrystal Horn": 731
|
||||||
}
|
}
|
|
@ -5,3 +5,5 @@ Version 3: http://localhost:8000/#3_0250px0uX0K50K20OK0OJ00A0Qe1z+m21001M1g00001
|
||||||
Version 3: http://localhost:8000/#3_0K60iv0CE0Qt0BK0BK0K40Jc0uG160V050o1L1g00001003C6
|
Version 3: http://localhost:8000/#3_0K60iv0CE0Qt0BK0BK0K40Jc0uG160V050o1L1g00001003C6
|
||||||
Version 4: http://localhost:8000/#4_-1+W+W+W+W+W+W9g91-1+W+W+W+W+W+W9d91-1+W+W+W+W+W+W9i9--1+W+W+W+W+W+W9a91-1+W+W+W+W+W+W9m91-1+W+W+W+W+W+W9m91-1+W+W+W+W+W+W9c91-1+W+W+W+W+W+W9n91-1+W+W+W+W+W+W9q9100000000001g000010036C
|
Version 4: http://localhost:8000/#4_-1+W+W+W+W+W+W9g91-1+W+W+W+W+W+W9d91-1+W+W+W+W+W+W9i9--1+W+W+W+W+W+W9a91-1+W+W+W+W+W+W9m91-1+W+W+W+W+W+W9m91-1+W+W+W+W+W+W9c91-1+W+W+W+W+W+W9n91-1+W+W+W+W+W+W9q9100000000001g000010036C
|
||||||
Version 5 (CI): http://localhost:8000/index.html#5_0lS0JX0u50tv00nCI-10000MFlipped%20Lapis%20Ring0200540M01010V010m0K20OL0og00-CI-110230401030570A07287-3530F40M0201d0c07287-3530w023zu100202e-Y0i211q-Y1g00000
|
Version 5 (CI): http://localhost:8000/index.html#5_0lS0JX0u50tv00nCI-10000MFlipped%20Lapis%20Ring0200540M01010V010m0K20OL0og00-CI-110230401030570A07287-3530F40M0201d0c07287-3530w023zu100202e-Y0i211q-Y1g00000
|
||||||
|
Version 6: (tomes): https://localhost:8000/builder/#6_02509-0p00Qj0K2CR-19i7n9i7n9C7J9m910T40Ji0R1-t+f1k-P2W1g00001007lUbW51I6p
|
||||||
|
Version 7 (atree): http://localhost:8000/builder/#7_0ZP0iv0uR0Lg00502C0K40uY0BE161a+W0o161g00001001Z6zz++++--6l-VU6
|
BIN
regression_tests/v6.png
Executable file
BIN
regression_tests/v6.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 128 KiB |
BIN
regression_tests/v7.png
Executable file
BIN
regression_tests/v7.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 304 KiB |
|
@ -53,5 +53,23 @@
|
||||||
"Freelancer's Tome of Allegiance": 51,
|
"Freelancer's Tome of Allegiance": 51,
|
||||||
"Sycophant's Tome of Allegiance": 52,
|
"Sycophant's Tome of Allegiance": 52,
|
||||||
"Fanatic's Tome of Allegiance": 53,
|
"Fanatic's Tome of Allegiance": 53,
|
||||||
"Assimilator's Tome of Allegiance": 54
|
"Assimilator's Tome of Allegiance": 54,
|
||||||
|
"Ephemeral Tome of Weapon Mastery I": 55,
|
||||||
|
"Ephemeral Tome of Weapon Mastery II": 56,
|
||||||
|
"Ephemeral Tome of Weapon Mastery III": 57,
|
||||||
|
"Harvester's Tome of Weapon Mastery I": 58,
|
||||||
|
"Harvester's Tome of Weapon Mastery II": 59,
|
||||||
|
"Harvester's Tome of Weapon Mastery III": 60,
|
||||||
|
"Earthbound Tome of Weapon Mastery III": 64,
|
||||||
|
"Nimble Tome of Weapon Mastery III": 65,
|
||||||
|
"Mystical Tome of Weapon Mastery III": 66,
|
||||||
|
"Warding Tome of Weapon Mastery III": 67,
|
||||||
|
"Athletic Tome of Weapon Mastery III": 68,
|
||||||
|
"Cosmic Tome of Weapon Mastery III": 69,
|
||||||
|
"Seismic Tome of Weapon Mastery III": 70,
|
||||||
|
"Voltaic Tome of Weapon Mastery III": 71,
|
||||||
|
"Abyssal Tome of Weapon Mastery III": 72,
|
||||||
|
"Infernal Tome of Weapon Mastery III": 73,
|
||||||
|
"Cyclonic Tome of Weapon Mastery III": 74,
|
||||||
|
"Astral Tome of Weapon Mastery III": 75
|
||||||
}
|
}
|
272
tomes.json
272
tomes.json
|
@ -321,7 +321,7 @@
|
||||||
"category": "tome",
|
"category": "tome",
|
||||||
"drop": "never",
|
"drop": "never",
|
||||||
"restrict": "Soulbound Item",
|
"restrict": "Soulbound Item",
|
||||||
"lvl": 80,
|
"lvl": 60,
|
||||||
"damMobs": 7,
|
"damMobs": 7,
|
||||||
"str": 3,
|
"str": 3,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
|
@ -349,7 +349,7 @@
|
||||||
"category": "tome",
|
"category": "tome",
|
||||||
"drop": "never",
|
"drop": "never",
|
||||||
"restrict": "Soulbound Item",
|
"restrict": "Soulbound Item",
|
||||||
"lvl": 80,
|
"lvl": 60,
|
||||||
"damMobs": 7,
|
"damMobs": 7,
|
||||||
"dex": 3,
|
"dex": 3,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
|
@ -377,7 +377,7 @@
|
||||||
"category": "tome",
|
"category": "tome",
|
||||||
"drop": "never",
|
"drop": "never",
|
||||||
"restrict": "Soulbound Item",
|
"restrict": "Soulbound Item",
|
||||||
"lvl": 80,
|
"lvl": 60,
|
||||||
"damMobs": 7,
|
"damMobs": 7,
|
||||||
"int": 3,
|
"int": 3,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
|
@ -405,7 +405,7 @@
|
||||||
"category": "tome",
|
"category": "tome",
|
||||||
"drop": "never",
|
"drop": "never",
|
||||||
"restrict": "Soulbound Item",
|
"restrict": "Soulbound Item",
|
||||||
"lvl": 80,
|
"lvl": 60,
|
||||||
"damMobs": 7,
|
"damMobs": 7,
|
||||||
"def": 3,
|
"def": 3,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
|
@ -433,7 +433,7 @@
|
||||||
"category": "tome",
|
"category": "tome",
|
||||||
"drop": "never",
|
"drop": "never",
|
||||||
"restrict": "Soulbound Item",
|
"restrict": "Soulbound Item",
|
||||||
"lvl": 80,
|
"lvl": 60,
|
||||||
"damMobs": 7,
|
"damMobs": 7,
|
||||||
"agi": 3,
|
"agi": 3,
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
|
@ -461,7 +461,7 @@
|
||||||
"category": "tome",
|
"category": "tome",
|
||||||
"drop": "never",
|
"drop": "never",
|
||||||
"restrict": "Soulbound Item",
|
"restrict": "Soulbound Item",
|
||||||
"lvl": 80,
|
"lvl": 60,
|
||||||
"damMobs": 7,
|
"damMobs": 7,
|
||||||
"str": 1,
|
"str": 1,
|
||||||
"dex": 1,
|
"dex": 1,
|
||||||
|
@ -804,6 +804,266 @@
|
||||||
"fixID": false,
|
"fixID": false,
|
||||||
"id": 54,
|
"id": 54,
|
||||||
"alias": "Rainbow"
|
"alias": "Rainbow"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Ephemeral Tome of Weapon Mastery I",
|
||||||
|
"tier": "Fabled",
|
||||||
|
"type": "weaponTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 60,
|
||||||
|
"damMobs": 7,
|
||||||
|
"mr": 1,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 55,
|
||||||
|
"alias": "Mana Regen I"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Ephemeral Tome of Weapon Mastery II",
|
||||||
|
"tier": "Fabled",
|
||||||
|
"type": "weaponTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 80,
|
||||||
|
"damMobs": 8,
|
||||||
|
"mr": 1,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 56,
|
||||||
|
"alias": "Mana Regen II"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Ephemeral Tome of Weapon Mastery III",
|
||||||
|
"tier": "Fabled",
|
||||||
|
"type": "weaponTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 105,
|
||||||
|
"damMobs": 13,
|
||||||
|
"mr": 1,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 57,
|
||||||
|
"alias": "Mana Regen III"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Harvester's Tome of Weapon Mastery I",
|
||||||
|
"tier": "Fabled",
|
||||||
|
"type": "weaponTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 60,
|
||||||
|
"damMobs": 7,
|
||||||
|
"ms": 1,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 58,
|
||||||
|
"alias": "Mana Steal I"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Harvester's Tome of Weapon Mastery II",
|
||||||
|
"tier": "Fabled",
|
||||||
|
"type": "weaponTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 80,
|
||||||
|
"damMobs": 8,
|
||||||
|
"ms": 1,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 59,
|
||||||
|
"alias": "Mana Steal II"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Harvester's Tome of Weapon Mastery III",
|
||||||
|
"tier": "Fabled",
|
||||||
|
"type": "weaponTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 105,
|
||||||
|
"damMobs": 13,
|
||||||
|
"ms": 1,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 60,
|
||||||
|
"alias": "Mana Steal III"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Earthbound Tome of Weapon Mastery III",
|
||||||
|
"tier": "Fabled",
|
||||||
|
"type": "weaponTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 105,
|
||||||
|
"damMobs": 13,
|
||||||
|
"str": 3,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 64,
|
||||||
|
"alias": "Strength III"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Nimble Tome of Weapon Mastery III",
|
||||||
|
"tier": "Fabled",
|
||||||
|
"type": "weaponTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 105,
|
||||||
|
"damMobs": 13,
|
||||||
|
"dex": 3,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 65,
|
||||||
|
"alias": "Dexterity III"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Mystical Tome of Weapon Mastery III",
|
||||||
|
"tier": "Fabled",
|
||||||
|
"type": "weaponTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 105,
|
||||||
|
"damMobs": 13,
|
||||||
|
"int": 3,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 66,
|
||||||
|
"alias": "Intelligence III"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Warding Tome of Weapon Mastery III",
|
||||||
|
"tier": "Fabled",
|
||||||
|
"type": "weaponTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 105,
|
||||||
|
"damMobs": 13,
|
||||||
|
"def": 3,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 67,
|
||||||
|
"alias": "Defense III"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Athletic Tome of Weapon Mastery III",
|
||||||
|
"tier": "Fabled",
|
||||||
|
"type": "weaponTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 105,
|
||||||
|
"damMobs": 13,
|
||||||
|
"agi": 3,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 68,
|
||||||
|
"alias": "Agility III"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Cosmic Tome of Weapon Mastery III",
|
||||||
|
"tier": "Fabled",
|
||||||
|
"type": "weaponTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 105,
|
||||||
|
"damMobs": 13,
|
||||||
|
"str": 1,
|
||||||
|
"dex": 1,
|
||||||
|
"int": 1,
|
||||||
|
"def": 1,
|
||||||
|
"agi": 1,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 69,
|
||||||
|
"alias": "Rainbow Skillpoint III"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Seismic Tome of Weapon Mastery III",
|
||||||
|
"tier": "Mythic",
|
||||||
|
"type": "weaponTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 105,
|
||||||
|
"damMobs": 16,
|
||||||
|
"eDamPct": 8,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 70,
|
||||||
|
"alias": "Earth Damage III"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Voltaic Tome of Weapon Mastery III",
|
||||||
|
"tier": "Mythic",
|
||||||
|
"type": "weaponTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 105,
|
||||||
|
"damMobs": 16,
|
||||||
|
"tDamPct": 8,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 71,
|
||||||
|
"alias": "Thunder Damage III"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Abyssal Tome of Weapon Mastery III",
|
||||||
|
"tier": "Mythic",
|
||||||
|
"type": "weaponTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 105,
|
||||||
|
"damMobs": 16,
|
||||||
|
"wDamPct": 8,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 72,
|
||||||
|
"alias": "Water Damage III"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Infernal Tome of Weapon Mastery III",
|
||||||
|
"tier": "Mythic",
|
||||||
|
"type": "weaponTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 105,
|
||||||
|
"damMobs": 16,
|
||||||
|
"fDamPct": 8,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 73,
|
||||||
|
"alias": "Fire Damage III"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Cyclonic Tome of Weapon Mastery III",
|
||||||
|
"tier": "Mythic",
|
||||||
|
"type": "weaponTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 105,
|
||||||
|
"damMobs": 16,
|
||||||
|
"aDamPct": 8,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 74,
|
||||||
|
"alias": "Air Damage III"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Astral Tome of Weapon Mastery III",
|
||||||
|
"tier": "Mythic",
|
||||||
|
"type": "weaponTome",
|
||||||
|
"category": "tome",
|
||||||
|
"drop": "never",
|
||||||
|
"restrict": "Soulbound Item",
|
||||||
|
"lvl": 105,
|
||||||
|
"damMobs": 16,
|
||||||
|
"eDamPct": 7,
|
||||||
|
"tDamPct": 7,
|
||||||
|
"wDamPct": 7,
|
||||||
|
"fDamPct": 7,
|
||||||
|
"aDamPct": 7,
|
||||||
|
"fixID": false,
|
||||||
|
"id": 75,
|
||||||
|
"alias": "Rainbow Damage III"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue