Merge branch 'atree' into atree_active_box

This commit is contained in:
hppeng 2022-07-06 11:39:11 -07:00
commit fdaad6931b
36 changed files with 2395 additions and 1867 deletions

1
.gitignore vendored
View file

@ -1,5 +1,6 @@
*.swp
*.bat
*.json
sets/
.idea/

View file

@ -27,6 +27,7 @@
<a href = "/wynnfo/index.html"><img src = "../media/icons/new/book.png" alt = "Wynnfo" title = "WynnCrafter"><b>WynnCrafter</b></a>
<a 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-fluid py-1 vh-100">
<div class = "row">

View file

@ -48,6 +48,7 @@
<a onclick = "document.querySelector('#search-container').style.display = '';"><img src="../media/icons/new/searcher.png" alt="" title="Item Search"><b>WynnAtlas Mini</b></a>
<a 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-fluid me-4" style="max-width: 95%; display: none">
<div class="row h-100 gx-lg-5 gy-3 mx-2 mx-lg-3 py-3">

View file

@ -48,8 +48,13 @@
<a onclick = "document.querySelector('#search-container').style.display = '';"><img src="../media/icons/new/searcher.png" alt="" title="Item Search"><b>WynnAtlas Mini</b></a>
<a 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-fluid me-4" style="max-width: 95%;">
<!-- REMOVE THIS DIV AT SOME POINT. -->
<div class = "row scaled-font mx-auto" id = "discord-banner-dev">
<div class = "col text-center item-title">Join the <a class = "link" href = "https://discord.gg/CGavnAnerv" target = "_blank">discord</a> today to suggest new features, submit bug reports, and hangout/talk to devs!</div>
</div>
<div class="row h-100 gx-lg-5 gy-3 mx-2 mx-lg-3 py-3">
<div class="col-xl-6">
<div class="row row-cols-1 mb-3 gy-4">
@ -1270,20 +1275,7 @@
</div>
<div id="all-spells-display" class="row row-cols-1 gy-3 text-center scaled-font pe-0">
<div class = "col pe-0">
<div class = "col spell-display spell-expand dark-5 rounded dark-shadow pt-2 border border-dark" id="spell0-infoAvg">spell1</div>
<div class = "col spell-display dark-5 rounded dark-shadow py-2" id = "spell0-info" style="display: none;">Spell 1</div>
</div>
<div class = "col pe-0">
<div class = "col spell-display spell-expand dark-5 rounded dark-shadow pt-2 border border-dark" id="spell1-infoAvg">spell2</div>
<div class = "col spell-display dark-5 rounded dark-shadow py-2" id = "spell1-info" style="display: none;">Spell 2</div>
</div>
<div class = "col pe-0">
<div class = "col spell-display spell-expand dark-5 rounded dark-shadow pt-2 border border-dark" id="spell2-infoAvg">spell3</div>
<div class = "col spell-display dark-5 rounded dark-shadow py-2" id = "spell2-info" style="display: none;">Spell 3</div>
</div>
<div class = "col pe-0">
<div class = "col spell-display spell-expand dark-5 rounded dark-shadow pt-2 border border-dark" id="spell3-infoAvg">spell4</div>
<div class = "col spell-display dark-5 rounded dark-shadow py-2" id = "spell3-info" style="display: none;">Spell 4</div>
<div class = "col spell-display spell-expand dark-5 rounded dark-shadow pt-2 border border-dark" id="spell0-infoAvg">Input a weapon to see abilities!</div>
</div>
</div>
<div class = "col">

3107
clean.json

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

View file

@ -29,6 +29,7 @@
<a href = "../wynnfo/"><img src = "../media/icons/new/book.png" alt = "Wynnfo" title = "Wynnfo"><b>Wynnfo</b></a>
<a 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 py-5 vh-100 mx-0 mx-lg-auto">
<div class = "col">

View file

@ -497,4 +497,11 @@ a:hover {
border-radius:50%;
-moz-border-radius:50%;
-webkit-border-radius:50%;
}
.hppeng{
color: #20c2b6;
}
.ferricles{
color: #5be553;
}

View file

@ -31,6 +31,7 @@
<a href = "../wynnfo/"><img src = "../media/icons/new/book.png" alt = "Wynnfo" title = "Wynnfo"><b>Wynnfo</b></a>
<a 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 row py-5 vh-100 mx-0 mx-lg-auto scaled-font">
<div class = "col-lg-3 col-sm-12">

View file

@ -43,6 +43,7 @@
<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">

View file

@ -30,6 +30,7 @@
<a href = "../wynnfo/"><img src = "../media/icons/new/book.png" alt = "Wynnfo" title = "Wynnfo"><b>Wynnfo</b></a>
<a 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 py-5 vh-100 mx-0 mx-lg-auto scaled-font">

View file

@ -29,6 +29,7 @@
<a href = "../wynnfo/"><img src = "../media/icons/new/book.png" alt = "Wynnfo" title = "Wynnfo"><b>Wynnfo</b></a>
<a 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 py-5 vh-100 mx-0 mx-lg-auto scaled-font">
<div class = "col">

View file

@ -30,6 +30,7 @@
<a href = "/wynnfo/index.html"><img src = "../media/icons/new/book.png" alt = "Wynnfo" title = "WynnCrafter"><b>WynnCrafter</b></a>
<a 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 py-5 vh-100 mx-0 mx-lg-auto scaled-font">
<div class = "col">

View file

@ -33,6 +33,7 @@
<a href = "../wynnfo/"><img src = "../media/icons/new/book.png" alt = "Wynnfo" title = "WynnCrafter"><b>WynnCrafter</b></a>
<a 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>
<main>
<div class="full-width text-center">

View file

@ -0,0 +1,5 @@
How to convert:
1. edit `atree_constants.js`
2. run `python3 ../py_script/atree-generateID.py
3. check that the site still works

View file

@ -39,6 +39,9 @@ add_spell_prop: {
base_spell: int // spell identifier
target_part: Optional[str] // Part of the spell to modify. Can be not present/empty for ex. cost modifier.
// If target part does not exist, a new part is created.
behavior: Optional[str] // One of: "merge", "modify". default: merge
// merge: add if exist, make new part if not exist
// modify: change existing part. do nothing if not exist
cost: Optional[int] // change to spellcost
multipliers: Optional[array[float, 6]] // Additive changes to spellmult (for damage spell)
power: Optional[float] // Additive change to healing power (for heal spell)
@ -57,6 +60,9 @@ raw_stat: {
type: "raw_stat"
toggle: Optional[bool | str] // default: false; true means create anon. toggle,
// string value means bind to (or create) named button
behavior: Optional[str] // One of: "merge", "modify". default: merge
// merge: add if exist, make new part if not exist
// modify: change existing part. do nothing if not exist
bonuses: List[stat_bonus]
}
stat_bonus: {
@ -135,7 +141,7 @@ const atree_node = new (class extends ComputeNode {
const [player_class] = input_map.values(); // Extract values, pattern match it into size one list and bind to first element
const atree_raw = atrees[player_class];
if (!atree_raw) return null;
if (!atree_raw) return [];
let atree_map = new Map();
let atree_head;
@ -287,7 +293,7 @@ const atree_merge = new (class extends ComputeNode {
}
return abils_merged;
}
})().link_to(atree_node, 'atree').link_to(atree_state_node, 'atree-state'); // TODO: THIS IS WRONG!!!!! Need one "collect" node...
})().link_to(atree_node, 'atree').link_to(atree_state_node, 'atree-state');
/**
* Validate ability tree.
@ -302,6 +308,8 @@ const atree_validate = new (class extends ComputeNode {
const atree_state = input_map.get('atree-state');
const atree_order = input_map.get('atree');
if (atree_order.length == 0) { return [0, ['no atree data']]; }
let errors = [];
let reachable = new Map();
atree_dfs_mark(atree_order[0], atree_state, reachable);
@ -452,7 +460,7 @@ const atree_collect_spells = new (class extends ComputeNode {
has_spell_def = true;
// replace_spell just replaces all (defined) aspects.
for (const key in effect) {
ret_spell[key] = effect[key];
ret_spell[key] = deepcopy(effect[key]);
}
}
}
@ -465,9 +473,9 @@ const atree_collect_spells = new (class extends ComputeNode {
// Already handled above.
continue;
case 'add_spell_prop': {
const { base_spell, target_part = null, cost = 0} = effect;
const { base_spell, target_part = null, cost = 0, behavior = 'merge'} = effect;
if (base_spell !== base_spell_id) { continue; } // TODO: redundant? if we assume abils only affect one spell
ret_spell.cost += cost;
// TODO: unjankify this... if ('cost' in ret_spell) { ret_spell.cost += cost; }
if (target_part === null) {
continue;
@ -497,7 +505,7 @@ const atree_collect_spells = new (class extends ComputeNode {
break;
}
}
if (!found_part) { // add part.
if (!found_part && behavior === 'merge') { // add part. if behavior is merge
let spell_part = deepcopy(effect);
spell_part.name = target_part; // has some extra fields but whatever
ret_spell.parts.push(spell_part);
@ -534,6 +542,51 @@ const atree_collect_spells = new (class extends ComputeNode {
}
})().link_to(atree_merge, 'atree-merged');
const atree_stats = new (class extends ComputeNode {
constructor() { super('atree-stats-collector'); }
compute_func(input_map) {
if (input_map.size !== 1) { throw "AbilityTreeCollectStats accepts exactly one input (atree-merged)"; }
const [atree_merged] = input_map.values(); // Extract values, pattern match it into size one list and bind to first element
let ret_effects = new Map();
for (const [abil_id, abil] of atree_merged.entries()) {
if (abil.effects.length == 0) { continue; }
for (const effect of abil.effects) {
switch (effect.type) {
case 'stat_scaling':
// TODO: handle
continue;
case 'raw_stat':
// TODO: toggles...
for (const bonus of effect.bonuses) {
const { type, name, abil = "", value } = bonus;
// TODO: prop
if (type === "stat") {
if (ret_effects.has(name)) { ret_effects.set(name, ret_effects.get(name) + value); }
else { ret_effects.set(name, value); }
}
}
continue;
case 'add_spell_prop':
// TODO unjankify....
// costs are converted to raw cost ID
const { base_spell, cost = 0} = effect;
if (cost) {
const key = "spRaw"+base_spell;
if (ret_effects.has(key)) { ret_effects.set(key, ret_effects.get(key) + cost); }
else { ret_effects.set(key, cost); }
}
continue;
}
}
}
console.log(ret_effects);
return ret_effects;
}
})().link_to(atree_merge, 'atree-merged');
/**
* Construct compute nodes to link builder items and edit IDs to the appropriate display outputs.

View file

@ -9,7 +9,8 @@ const atrees = {
"cost": 1,
"display": {
"row": 9,
"col": 6
"col": 6,
"icon": "node_4"
},
"properties": {
"charges": 2,
@ -49,7 +50,8 @@ const atrees = {
"cost": 1,
"display": {
"row": 7,
"col": 4
"col": 4,
"icon": "node_4"
},
"properties": {
"aoe": 0,
@ -73,7 +75,8 @@ const atrees = {
"cost": 1,
"display": {
"row": 0,
"col": 4
"col": 4,
"icon": "node_4"
},
"properties": {
"aoe": 4.5,
@ -111,7 +114,8 @@ const atrees = {
"cost": 1,
"display": {
"row": 4,
"col": 4
"col": 4,
"icon": "node_1"
},
"properties": {},
"effects": [
@ -139,7 +143,8 @@ const atrees = {
"cost": 2,
"display": {
"row": 16,
"col": 6
"col": 6,
"icon": "node_1"
},
"properties": {
"aoe": 0.8,
@ -170,7 +175,7 @@ const atrees = {
"dependencies": ["Arrow Storm"],
"blockers": [],
"cost": 2,
"display": { "row": 16, "col": 8 },
"display": { "row": 16, "col": 8, "icon": "node_1"},
"properties": {
"aoe": 2,
"duration": 5
@ -199,7 +204,7 @@ const atrees = {
"dependencies": ["Arrow Storm"],
"blockers": ["Phantom Ray"],
"cost": 2,
"display": { "row": 15, "col": 2 },
"display": { "row": 15, "col": 2, "icon": "node_1"},
"properties": {},
"effects": [
{
@ -223,7 +228,7 @@ const atrees = {
"dependencies": [],
"blockers": [],
"cost": 1,
"display": { "row": 9, "col": 2 },
"display": { "row": 9, "col": 2, "icon": "node_4"},
"properties": { "range": 16 },
"effects": [
{
@ -262,15 +267,16 @@ const atrees = {
"blockers": [],
"cost": 2,
"display": {
"row": 19,
"col": 1
"row": 19,
"col": 1,
"icon": "node_3"
},
"properties": {
"range": 4,
"duration": 60,
"shots": 8,
"count": 2
},
"range": 4,
"duration": 60,
"shots": 8,
"charges": 2
},
"effects": [
{
"type": "replace_spell",
@ -311,7 +317,8 @@ const atrees = {
"cost": 1,
"display": {
"row": 10,
"col": 1
"col": 1,
"icon": "node_0"
},
"properties": {
"aoe": 8,
@ -341,7 +348,8 @@ const atrees = {
"cost": 2,
"display": {
"row": 19,
"col": 8
"col": 8,
"icon": "node_3"
},
"properties": {
"aoe": 7,
@ -366,7 +374,8 @@ const atrees = {
"cost": 2,
"display": {
"row": 21,
"col": 1
"col": 1,
"icon": "node_1"
},
"properties": {},
"effects": [
@ -404,7 +413,8 @@ const atrees = {
"cost": 2,
"display": {
"row": 21,
"col": 5
"col": 5,
"icon": "node_2"
},
"properties": {
"range": 26
@ -423,7 +433,8 @@ const atrees = {
"cost": 2,
"display": {
"row": 22,
"col": 6
"col": 6,
"icon": "node_1"
},
"properties": {},
"effects": [
@ -446,7 +457,8 @@ const atrees = {
"cost": 2,
"display": {
"row": 25,
"col": 4
"col": 4,
"icon": "node_2"
},
"properties": {
"range": 64,
@ -480,7 +492,7 @@ const atrees = {
"dependencies": [],
"blockers": [],
"cost": 2,
"display": { "row": 26, "col": 1 },
"display": { "row": 26, "col": 1, "icon": "node_1"},
"properties": {
"aoe": 4
},
@ -513,7 +525,7 @@ const atrees = {
"dependencies": ["Fire Creep"],
"blockers": [],
"cost": 1,
"display": { "row": 26, "col": 5 },
"display": { "row": 26, "col": 5, "icon": "node_1"},
"properties": {
"duration": 2,
"aoe": 0.4
@ -536,7 +548,7 @@ const atrees = {
"dependencies": [],
"blockers": [],
"cost": 2,
"display": { "row": 28, "col": 0 },
"display": { "row": 28, "col": 0, "icon": "node_1"},
"properties": {
"cooldown": 2
},
@ -552,7 +564,7 @@ const atrees = {
"dependencies": ["Arrow Bomb"],
"blockers": [],
"cost": 2,
"display": { "row": 28, "col": 4 },
"display": { "row": 28, "col": 4, "icon": "node_1"},
"properties": {
"gravity": 0
},
@ -566,21 +578,22 @@ const atrees = {
},
{
"display_name": "Mana Trap",
"desc": "Your Traps will give you 4 Mana per second when you stay close to them.",
"desc": "Your Traps will give you 2.85 Mana per second when you stay close to them.",
"archetype": "Trapper",
"archetype_req": 5,
"base_abil": "Arrow Bomb",
"parents": ["More Traps", "Better Arrow Shield"],
"dependencies": ["Fire Creep"],
"dependencies": [],
"blockers": [],
"cost": 2,
"display": {
"row": 28,
"col": 8
"col": 8,
"icon": "node_3"
},
"properties": {
"range": 12,
"manaRegen": 4
"range": 16,
"manaRegen": 2.85
},
"effects": [
{
@ -602,7 +615,8 @@ const atrees = {
"cost": 2,
"display": {
"row": 31,
"col": 0
"col": 0,
"icon": "node_1"
},
"properties": {},
"effects": [
@ -630,7 +644,7 @@ const atrees = {
"dependencies": ["Focus"],
"blockers": [],
"cost": 2,
"display": { "row": 31, "col": 5 },
"display": { "row": 31, "col": 5, "icon": "node_2"},
"properties": {},
"effects": []
},
@ -644,7 +658,7 @@ const atrees = {
"dependencies": ["Arrow Shield"],
"blockers": [],
"cost": 2,
"display": { "row": 32, "col": 7 },
"display": { "row": 32, "col": 7, "icon": "node_2"},
"properties": {},
"effects": [
{
@ -665,7 +679,7 @@ const atrees = {
"dependencies": [],
"blockers": ["Phantom Ray"],
"cost": 2,
"display": { "row": 33, "col": 0 },
"display": { "row": 33, "col": 0, "icon": "node_3"},
"properties": {},
"effects": [
{
@ -684,7 +698,7 @@ const atrees = {
"dependencies": ["Fierce Stomp"],
"blockers": [],
"cost": 2,
"display": { "row": 37, "col": 1 },
"display": { "row": 37, "col": 1, "icon": "node_1"},
"properties": {},
"effects": [
{
@ -721,7 +735,8 @@ const atrees = {
"cost": 2,
"display": {
"row": 37,
"col": 4
"col": 4,
"icon": "node_3"
},
"properties": {},
"effects": [
@ -755,7 +770,7 @@ const atrees = {
"dependencies": [],
"blockers": [],
"cost": 2,
"display": { "row": 37, "col": 7 },
"display": { "row": 37, "col": 7, "icon": "node_2"},
"properties": {
"aoe": 2
},
@ -783,7 +798,7 @@ const atrees = {
"dependencies": ["Basaltic Trap"],
"blockers": [],
"cost": 2,
"display": { "row": 38, "col": 6 },
"display": {"row": 38, "col": 6, "icon": "node_1"},
"properties": {
"attackSpeed": 0.2
},
@ -815,7 +830,8 @@ const atrees = {
"cost": 2,
"display": {
"row": 39,
"col": 2
"col": 2,
"icon": "node_2"
},
"properties": {
"range": 2.5,
@ -833,7 +849,7 @@ const atrees = {
"dependencies": ["Guardian Angels"],
"blockers": [],
"cost": 2,
"display": { "row": 40, "col": 1 },
"display": { "row": 40, "col": 1, "icon": "node_3"},
"properties": {
"range": 8,
"shots": 5
@ -863,7 +879,7 @@ const atrees = {
"dependencies": ["Basaltic Trap"],
"blockers": [],
"cost": 2,
"display": { "row": 40, "col": 7 },
"display": {"row": 40, "col": 7, "icon": "node_3"},
"properties": {},
"effects": [
{
@ -900,7 +916,7 @@ const atrees = {
"dependencies": [],
"blockers": [],
"cost": 1,
"display": { "row": 2, "col": 4 },
"display": { "row": 2, "col": 4, "icon": "node_0"},
"properties": {},
"effects": [
{
@ -923,7 +939,7 @@ const atrees = {
"dependencies": [],
"blockers": [],
"cost": 1,
"display": { "row": 2, "col": 6 },
"display": {"row": 2, "col": 6, "icon": "node_0"},
"properties": {},
"effects": [
{
@ -941,7 +957,7 @@ const atrees = {
"dependencies": [],
"blockers": [],
"cost": 1,
"display": { "row": 21, "col": 3 },
"display": {"row": 21, "col": 3, "icon": "node_0"},
"properties": {},
"effects": [
{
@ -1176,7 +1192,7 @@ const atrees = {
"type": "add_spell_prop",
"base_spell": 4,
"target_part": "Total Damage",
"hits": { "Shield Damage": 2 }
"hits": { "Shield Damage": 2, "Single Bow": 2 }
},
{
"type": "raw_stat",
@ -1288,6 +1304,7 @@ const atrees = {
"type": "add_spell_prop",
"base_spell": 3,
"target_part": "Arrow Shield",
"behavior": "modify",
"multipliers": [40, 0, 0, 0, 0, 0]
},
{
@ -1295,6 +1312,7 @@ const atrees = {
"bonuses": [{
"type": "prop",
"abil": "Arrow Shield",
"behavior": "modify",
"name": "aoe",
"value": 1
}]
@ -1661,7 +1679,7 @@ const atrees = {
"display": {
"row": 19,
"col": 4,
"icon": "node_2"
"icon": "node_3"
},
"properties": {},
"effects": [{
@ -1840,7 +1858,7 @@ const atrees = {
"display": {
"row": 17,
"col": 2,
"icon": "node_0"
"icon": "node_1"
},
"properties": {},
"effects": [{
@ -2183,7 +2201,7 @@ const atrees = {
"type": "stat",
"name": "spd"
},
"scaling": [1, 1],
"scaling": [2, 2],
"max": 20
}
]
@ -2456,7 +2474,7 @@ const atrees = {
{
"display_name": "Fire Mastery",
"desc": "Increases base damage from all Earth attacks",
"desc": "Increases base damage from all Fire attacks",
"archetype": "Paladin",
"archetype_req": 0,
"parents": ["War Scream"],
@ -2577,12 +2595,7 @@ const atrees = {
"base_spell": 3,
"target_part": "Uppercut",
"cost": -10,
"multipliers": [-70, 0, 0, 0, 0, 0]
},
{
"type": "convert_spell_conv",
"target_part": "all",
"conversion": "Water"
"multipliers": [-70, 0, 0, 30, 0, 0]
}
]
},
@ -2668,6 +2681,8 @@ const atrees = {
{
"display_name": "Iron Lungs",
"desc": "War Scream deals more damage",
"archetype": "Paladin",
"archetype_req": 0,
"base_abil": "War Scream",
"parents": ["Flyby Jab", "Flaming Uppercut"],
"dependencies": [],
@ -2939,13 +2954,13 @@ const atrees = {
"col": 6,
"icon": "node_1"
},
"properties": {},
"properties": {"attackRate": 2},
"effects": [
{
"type": "add_spell_prop",
"base_spell": 4,
"target_part": "Air Shout",
"multipliers": [20, 0, 0, 0, 0, 5]
"multipliers": [40, 0, 0, 0, 0, 10]
}
]
},
@ -3008,7 +3023,7 @@ const atrees = {
"type": "add_spell_prop",
"base_spell": 2,
"target_part": "Flying Kick",
"multipliers": [120, 0, 0, 10, 0, 20]
"multipliers": [150, 0, 0, 20, 0, 30]
},
{
"type": "add_spell_prop",
@ -3288,7 +3303,7 @@ const atrees = {
"base_spell": 2,
"target_part": "Collide",
"cost": 0,
"multipliers": [100, 0, 0, 0, 50, 0]
"multipliers": [150, 0, 0, 0, 50, 0]
},
{
"type": "add_spell_prop",
@ -3303,7 +3318,7 @@ const atrees = {
"display_name": "Rejuvenating Skin",
"desc": "Regain back 30% of the damage you take as healing over 30s",
"archetype": "Paladin",
"archetype_req": 0,
"archetype_req": 5,
"parents": ["Burning Heart", "Stronger Bash"],
"dependencies": [],
"blockers": [],
@ -3764,8 +3779,8 @@ const atrees = {
{ "type": "stat", "name": "fDamAddMin" }, { "type": "stat", "name": "fDamAddMax" },
{ "type": "stat", "name": "aDamAddMin" }, { "type": "stat", "name": "aDamAddMax" }
],
"scaling": [2],
"max": 50
"scaling": [3],
"max": 80
}
]
},

File diff suppressed because one or more lines are too long

View file

@ -200,7 +200,7 @@ function encodeBuild(build, powders, skillpoints, atree, atree_state) {
}
build_string += tome_string;
if (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);
const bitvec = encode_atree(atree, atree_state);
build_string += bitvec.toB64();

View file

@ -15,6 +15,11 @@ function skillPointsToPercentage(skp){
//return clamp((-0.0000000066695* Math.pow(Math.E, -0.00924033 * skp + 18.9) + 1.0771), 0.00, 0.808);
}
// WYNN2: Skillpoint max scaling. Intel is cost reduction
const skillpoint_final_mult = [1, 1, 0.5, 0.867, 0.951];
// intel damage and water%
const skillpoint_damage_mult = [1, 1, 1, 0.867, 0.951];
/*Turns the input amount of levels into skillpoints available.
*
* @param level - the integer level count to be converted

View file

@ -51,7 +51,7 @@ let boosts_node = new (class extends ComputeNode {
}
let res = new Map();
res.set('damageMultiplier', 1+damage_boost);
res.set('defMultiplier', 1+def_boost);
res.set('defMultiplier', 1-def_boost);
return res;
}
})().update();
@ -181,7 +181,8 @@ class ItemInputNode extends InputNode {
if (item) {
if (powdering !== undefined) {
item.statMap.set('powders', powdering);
const max_slots = item.statMap.get('slots');
item.statMap.set('powders', powdering.slice(0, max_slots));
}
let type_match;
if (this.category == 'weapon') {
@ -502,8 +503,8 @@ class SpellSelectNode extends ComputeNode {
*/
function getDefenseStats(stats) {
let defenseStats = [];
let def_pct = skillPointsToPercentage(stats.get('def'));
let agi_pct = skillPointsToPercentage(stats.get('agi'));
let def_pct = skillPointsToPercentage(stats.get('def')) * skillpoint_final_mult[3];
let agi_pct = skillPointsToPercentage(stats.get('agi')) * skillpoint_final_mult[4];
//total hp
let totalHp = stats.get("hp") + stats.get("hpBonus");
if (totalHp < 5) totalHp = 5;
@ -511,7 +512,10 @@ function getDefenseStats(stats) {
//EHP
let ehp = [totalHp, totalHp];
let defMult = (2 - stats.get("classDef")) * stats.get("defMultiplier");
ehp[0] /= (1-def_pct)*(1-agi_pct)*defMult;
// newehp = oldehp / [0.1 * A(x) + (1 - A(x)) * (1 - D(x))]
ehp[0] = ehp[0] / (0.1*agi_pct + (1-agi_pct) * (1-def_pct));
ehp[0] /= defMult;
// ehp[0] /= (1-def_pct)*(1-agi_pct)*defMult;
ehp[1] /= (1-def_pct)*defMult;
defenseStats.push(ehp);
//HPR
@ -610,6 +614,7 @@ class SpellDamageCalcNode extends ComputeNode {
const dam_res_keys = ['normal_min', 'normal_max', 'normal_total', 'crit_min', 'crit_max', 'crit_total'];
for (const [subpart_name, hits] of Object.entries(part.hits)) {
const subpart = spell_result_map.get(subpart_name);
if (!subpart) { continue; }
if (spell_result.type) {
if (subpart.type !== spell_result.type) {
throw "SpellCalc total subpart type mismatch";
@ -769,7 +774,7 @@ class DisplayBuildWarningsNode extends ComputeNode {
setValue(skp_order[i] + "-skp", skillpoints[i]);
let linebreak = document.createElement("br");
linebreak.classList.add("itemp");
setText(skp_order[i] + "-skp-pct", (skillPointsToPercentage(skillpoints[i])*100).toFixed(1).concat(skp_effects[i]));
setText(skp_order[i] + "-skp-pct", (skillPointsToPercentage(skillpoints[i])*100*skillpoint_final_mult[i]).toFixed(1).concat(skp_effects[i]));
document.getElementById(skp_order[i]+"-warnings").textContent = ''
if (assigned > 100) {
let skp_warning = document.createElement("p");
@ -1101,6 +1106,7 @@ function builder_graph_init() {
atree_merge.link_to(build_node, 'build');
atree_graph_creator = new AbilityTreeEnsureNodesNode(build_node, stat_agg_node)
.link_to(atree_collect_spells, 'spells');
stat_agg_node.link_to(atree_stats, 'atree-stats');
build_encode_node.link_to(atree_node, 'atree').link_to(atree_state_node, 'atree-state');

View file

@ -44,14 +44,16 @@ function init_crafter() {
try {
document.getElementById("recipe-choice").addEventListener("change", (event) => {
updateMaterials();
updateCraftedImage();
calculateCraftSchedule();
});
document.getElementById("recipe-choice").addEventListener("oninput", (event) => {
updateCraftedImage();
});
document.getElementById("level-choice").addEventListener("change", (event) => {
updateMaterials();
calculateCraftSchedule();
});
document.getElementById("recipe-choice").setAttribute("oninput", "updateCraftedImage()");
document.getElementById("recipe-choice").setAttribute("change", "updateCraftedImage()");
for (let i = 1; i < 4; ++i) {
document.getElementById("mat-1-"+i).setAttribute("onclick", document.getElementById("mat-1-"+i).getAttribute("onclick") + "; calculateCraftSchedule();");
@ -177,7 +179,7 @@ function calculateCraft() {
//Display Craft Stats
// displayCraftStats(player_craft, "craft-stats");
let mock_item = player_craft.statMap;
apply_weapon_powders(mock_item);
if (mock_item.get('category') === 'weapon') { apply_weapon_powders(mock_item) };
displayExpandedItem(mock_item, "craft-stats");
//Display Ingredients' Stats

View file

@ -66,6 +66,7 @@ function calculateSpellDamage(stats, weapon, conversions, use_spell_damage, igno
total_convert += conv_frac
}
}
total_convert += conversions[0]/100;
// Also theres prop and rainbow!!
const damage_elements = ['n'].concat(skp_elements); // netwfa
@ -94,8 +95,9 @@ function calculateSpellDamage(stats, weapon, conversions, use_spell_damage, igno
}
// 5.1: %boost application
let skill_boost = [0]; // no neutral skillpoint booster
for (const skp of skp_order) {
skill_boost.push(skillPointsToPercentage(stats.get(skp)));
for (let i in skp_order) {
const skp = skp_order[i];
skill_boost.push(skillPointsToPercentage(stats.get(skp)) * skillpoint_damage_mult[i]);
}
let static_boost = (stats.get(specific_boost_str.toLowerCase()+'Pct') + stats.get('damPct')) / 100;
@ -131,7 +133,7 @@ function calculateSpellDamage(stats, weapon, conversions, use_spell_damage, igno
let min_boost = raw_boost;
let max_boost = raw_boost;
if (total_max > 0) { // TODO: what about total negative all raw?
if (total_elem_min > 0) {
if (total_min > 0) {
min_boost += (damages_obj[0] / total_min) * prop_raw;
}
max_boost += (damages_obj[1] / total_max) * prop_raw;

View file

@ -1572,7 +1572,7 @@ function getSpellCost(stats, spell) {
function getBaseSpellCost(stats, spell) {
// old intelligence:
let cost = spell.cost; //Math.ceil(spell.cost * (1 - skillPointsToPercentage(stats.get('int'))));
let cost = Math.ceil(spell.cost * (1 - skillPointsToPercentage(stats.get('int')) * skillpoint_final_mult[2]));
cost += stats.get("spRaw"+spell.base_spell);
return Math.floor(cost * (1 + stats.get("spPct"+spell.base_spell) / 100));
}

View file

@ -1,4 +1,4 @@
const DB_VERSION = 90;
const DB_VERSION = 93;
// @See https://github.com/mdn/learning-area/blob/master/javascript/apis/client-side-storage/indexeddb/video-store/index.jsA
let db;

View file

@ -169,14 +169,14 @@ function calc_weapon_powder(weapon, damageBases) {
let min_diff = Math.min(neutralRemainingRaw[0], conversionRatio * neutralBase[0]);
let max_diff = Math.min(neutralRemainingRaw[1], conversionRatio * neutralBase[1]);
//damages[element+1][0] = Math.floor(round_near(damages[element+1][0] + min_diff));
//damages[element+1][1] = Math.floor(round_near(damages[element+1][1] + max_diff));
//neutralRemainingRaw[0] = Math.floor(round_near(neutralRemainingRaw[0] - min_diff));
//neutralRemainingRaw[1] = Math.floor(round_near(neutralRemainingRaw[1] - max_diff));
damages[element+1][0] += min_diff;
damages[element+1][1] += max_diff;
neutralRemainingRaw[0] -= min_diff;
neutralRemainingRaw[1] -= max_diff;
damages[element+1][0] = Math.floor(round_near(damages[element+1][0] + min_diff));
damages[element+1][1] = Math.floor(round_near(damages[element+1][1] + max_diff));
neutralRemainingRaw[0] = Math.floor(round_near(neutralRemainingRaw[0] - min_diff));
neutralRemainingRaw[1] = Math.floor(round_near(neutralRemainingRaw[1] - max_diff));
//damages[element+1][0] += min_diff;
//damages[element+1][1] += max_diff;
//neutralRemainingRaw[0] -= min_diff;
//neutralRemainingRaw[1] -= max_diff;
}
damages[element+1][0] += powder.min;
damages[element+1][1] += powder.max;

View file

@ -43,6 +43,7 @@
<a href = "../wynnfo/"><img src = "../media/icons/new/book.png" alt = "Wynnfo" title = "Wynnfo"><b>Wynnfo</b></a>
<a 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 row py-5 vh-100 mx-0 mx-lg-auto scaled-font">

BIN
media/icons/discord.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

349
normalize.css vendored
View file

@ -1,349 +0,0 @@
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */
/* Document
========================================================================== */
/**
* 1. Correct the line height in all browsers.
* 2. Prevent adjustments of font size after orientation changes in iOS.
*/
html {
line-height: 1.15; /* 1 */
-webkit-text-size-adjust: 100%; /* 2 */
}
/* Sections
========================================================================== */
/**
* Remove the margin in all browsers.
*/
body {
margin: 0;
}
/**
* Render the `main` element consistently in IE.
*/
main {
display: block;
}
/**
* Correct the font size and margin on `h1` elements within `section` and
* `article` contexts in Chrome, Firefox, and Safari.
*/
h1 {
font-size: 2em;
margin: 0.67em 0;
}
/* Grouping content
========================================================================== */
/**
* 1. Add the correct box sizing in Firefox.
* 2. Show the overflow in Edge and IE.
*/
hr {
box-sizing: content-box; /* 1 */
height: 0; /* 1 */
overflow: visible; /* 2 */
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
pre {
font-family: monospace, monospace; /* 1 */
font-size: 1em; /* 2 */
}
/* Text-level semantics
========================================================================== */
/**
* Remove the gray background on active links in IE 10.
*/
a {
background-color: transparent;
}
/**
* 1. Remove the bottom border in Chrome 57-
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
*/
abbr[title] {
border-bottom: none; /* 1 */
text-decoration: underline; /* 2 */
text-decoration: underline dotted; /* 2 */
}
/**
* Add the correct font weight in Chrome, Edge, and Safari.
*/
b,
strong {
font-weight: bolder;
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
code,
kbd,
samp {
font-family: monospace, monospace; /* 1 */
font-size: 1em; /* 2 */
}
/**
* Add the correct font size in all browsers.
*/
small {
font-size: 80%;
}
/**
* Prevent `sub` and `sup` elements from affecting the line height in
* all browsers.
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
/* Embedded content
========================================================================== */
/**
* Remove the border on images inside links in IE 10.
*/
img {
border-style: none;
}
/* Forms
========================================================================== */
/**
* 1. Change the font styles in all browsers.
* 2. Remove the margin in Firefox and Safari.
*/
button,
input,
optgroup,
select,
textarea {
font-family: inherit; /* 1 */
font-size: 100%; /* 1 */
line-height: 1.15; /* 1 */
margin: 0; /* 2 */
}
/**
* Show the overflow in IE.
* 1. Show the overflow in Edge.
*/
button,
input { /* 1 */
overflow: visible;
}
/**
* Remove the inheritance of text transform in Edge, Firefox, and IE.
* 1. Remove the inheritance of text transform in Firefox.
*/
button,
select { /* 1 */
text-transform: none;
}
/**
* Correct the inability to style clickable types in iOS and Safari.
*/
button,
[type="button"],
[type="reset"],
[type="submit"] {
-webkit-appearance: button;
}
/**
* Remove the inner border and padding in Firefox.
*/
button::-moz-focus-inner,
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner {
border-style: none;
padding: 0;
}
/**
* Restore the focus styles unset by the previous rule.
*/
button:-moz-focusring,
[type="button"]:-moz-focusring,
[type="reset"]:-moz-focusring,
[type="submit"]:-moz-focusring {
outline: 1px dotted ButtonText;
}
/**
* Correct the padding in Firefox.
*/
fieldset {
padding: 0.35em 0.75em 0.625em;
}
/**
* 1. Correct the text wrapping in Edge and IE.
* 2. Correct the color inheritance from `fieldset` elements in IE.
* 3. Remove the padding so developers are not caught out when they zero out
* `fieldset` elements in all browsers.
*/
legend {
box-sizing: border-box; /* 1 */
color: inherit; /* 2 */
display: table; /* 1 */
max-width: 100%; /* 1 */
padding: 0; /* 3 */
white-space: normal; /* 1 */
}
/**
* Add the correct vertical alignment in Chrome, Firefox, and Opera.
*/
progress {
vertical-align: baseline;
}
/**
* Remove the default vertical scrollbar in IE 10+.
*/
textarea {
overflow: auto;
}
/**
* 1. Add the correct box sizing in IE 10.
* 2. Remove the padding in IE 10.
*/
[type="checkbox"],
[type="radio"] {
box-sizing: border-box; /* 1 */
padding: 0; /* 2 */
}
/**
* Correct the cursor style of increment and decrement buttons in Chrome.
*/
[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
height: auto;
}
/**
* 1. Correct the odd appearance in Chrome and Safari.
* 2. Correct the outline style in Safari.
*/
[type="search"] {
-webkit-appearance: textfield; /* 1 */
outline-offset: -2px; /* 2 */
}
/**
* Remove the inner padding in Chrome and Safari on macOS.
*/
[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
/**
* 1. Correct the inability to style clickable types in iOS and Safari.
* 2. Change font properties to `inherit` in Safari.
*/
::-webkit-file-upload-button {
-webkit-appearance: button; /* 1 */
font: inherit; /* 2 */
}
/* Interactive
========================================================================== */
/*
* Add the correct display in Edge, IE 10+, and Firefox.
*/
details {
display: block;
}
/*
* Add the correct display in all browsers.
*/
summary {
display: list-item;
}
/* Misc
========================================================================== */
/**
* Add the correct display in IE 10+.
*/
template {
display: none;
}
/**
* Add the correct display in IE 10.
*/
[hidden] {
display: none;
}

View file

@ -13,52 +13,54 @@ with open("atree_ids.json") as f:
with open("atree_constants.json") as f:
atree_data = json.loads(f.read())
for _class, info in atree_data.items():
def translate(path, ref):
ref_dict = info
for x in path:
ref_dict = ref_dict[x]
ref_dict[ref] = id_data[_class][ref_dict[ref]]
for abil in range(len(info)):
info[abil]["id"] = id_data[_class][info[abil]["display_name"]]
for ref in range(len(info[abil]["parents"])):
translate([abil, "parents"], ref)
def translate_id(id_data, atree_data):
for _class, info in atree_data.items():
def translate(path, ref):
ref_dict = info
for x in path:
ref_dict = ref_dict[x]
ref_dict[ref] = id_data[_class][ref_dict[ref]]
for abil in range(len(info)):
info[abil]["id"] = id_data[_class][info[abil]["display_name"]]
for ref in range(len(info[abil]["parents"])):
translate([abil, "parents"], ref)
for ref in range(len(info[abil]["dependencies"])):
translate([abil, "dependencies"], ref)
for ref in range(len(info[abil]["dependencies"])):
translate([abil, "dependencies"], ref)
for ref in range(len(info[abil]["blockers"])):
translate([abil, "blockers"], ref)
for ref in range(len(info[abil]["blockers"])):
translate([abil, "blockers"], ref)
if "base_abil" in info[abil]:
base_abil_name = info[abil]["base_abil"]
if base_abil_name in id_data[_class]:
translate([abil], "base_abil")
if "base_abil" in info[abil]:
base_abil_name = info[abil]["base_abil"]
if base_abil_name in id_data[_class]:
translate([abil], "base_abil")
if "effects" not in info[abil]:
print("WARNING: abil missing 'effects' tag")
print(info[abil])
info[abil]["effects"] = []
for effect in info[abil]["effects"]:
if effect["type"] == "raw_stat":
for bonus in effect["bonuses"]:
if "abil" in bonus and bonus["abil"] in id_data[_class]:
bonus["abil"] = id_data[_class][bonus["abil"]]
if "effects" not in info[abil]:
print("WARNING: abil missing 'effects' tag")
print(info[abil])
info[abil]["effects"] = []
for effect in info[abil]["effects"]:
if effect["type"] == "raw_stat":
for bonus in effect["bonuses"]:
if "abil" in bonus and bonus["abil"] in id_data[_class]:
bonus["abil"] = id_data[_class][bonus["abil"]]
elif effect["type"] == "stat_scaling":
if "inputs" in effect: # Might not exist for sliders
for _input in effect["inputs"]:
if "abil" in _input and _input["abil"] in id_data[_class]:
_input["abil"] = id_data[_class][_input["abil"]]
if isinstance(effect["output"], list):
for output in effect["output"]:
if "abil" in output and output["abil"] in id_data[_class]:
output["abil"] = id_data[_class][output["abil"]]
else:
if "abil" in effect["output"] and effect["output"]["abil"] in id_data[_class]:
effect["output"]["abil"] = id_data[_class][effect["output"]["abil"]]
elif effect["type"] == "stat_scaling":
if "inputs" in effect: # Might not exist for sliders
for _input in effect["inputs"]:
if "abil" in _input and _input["abil"] in id_data[_class]:
_input["abil"] = id_data[_class][_input["abil"]]
if isinstance(effect["output"], list):
for output in effect["output"]:
if "abil" in output and output["abil"] in id_data[_class]:
output["abil"] = id_data[_class][output["abil"]]
else:
if "abil" in effect["output"] and effect["output"]["abil"] in id_data[_class]:
effect["output"]["abil"] = id_data[_class][effect["output"]["abil"]]
translate_id(id_data, atree_data)
with open('atree_constants_idfied.json', 'w', encoding='utf-8') as abil_dest:
json.dump(atree_data, abil_dest, ensure_ascii=False, indent=4)

View file

@ -6,6 +6,53 @@ given [atree_constants.js] .js form of the Ability Tree with reference as string
"""
import json
def translate_id(id_data, atree_data):
for _class, info in atree_data.items():
def translate(path, ref):
ref_dict = info
for x in path:
ref_dict = ref_dict[x]
ref_dict[ref] = id_data[_class][ref_dict[ref]]
for abil in range(len(info)):
info[abil]["id"] = id_data[_class][info[abil]["display_name"]]
for ref in range(len(info[abil]["parents"])):
translate([abil, "parents"], ref)
for ref in range(len(info[abil]["dependencies"])):
translate([abil, "dependencies"], ref)
for ref in range(len(info[abil]["blockers"])):
translate([abil, "blockers"], ref)
if "base_abil" in info[abil]:
base_abil_name = info[abil]["base_abil"]
if base_abil_name in id_data[_class]:
translate([abil], "base_abil")
if "effects" not in info[abil]:
print("WARNING: abil missing 'effects' tag")
print(info[abil])
info[abil]["effects"] = []
for effect in info[abil]["effects"]:
if effect["type"] == "raw_stat":
for bonus in effect["bonuses"]:
if "abil" in bonus and bonus["abil"] in id_data[_class]:
bonus["abil"] = id_data[_class][bonus["abil"]]
elif effect["type"] == "stat_scaling":
if "inputs" in effect: # Might not exist for sliders
for _input in effect["inputs"]:
if "abil" in _input and _input["abil"] in id_data[_class]:
_input["abil"] = id_data[_class][_input["abil"]]
if isinstance(effect["output"], list):
for output in effect["output"]:
if "abil" in output and output["abil"] in id_data[_class]:
output["abil"] = id_data[_class][output["abil"]]
else:
if "abil" in effect["output"] and effect["output"]["abil"] in id_data[_class]:
effect["output"]["abil"] = id_data[_class][effect["output"]["abil"]]
abilDict = {}
with open("atree_constants.js") as f:
data = f.read()
@ -21,17 +68,7 @@ with open("atree_constants.js") as f:
with open("atree_ids.json", "w", encoding='utf-8') as id_dest:
json.dump(abilDict, id_dest, ensure_ascii=False, indent=4)
for classType, info in data.items():
for abil in range(len(info)):
info[abil]["id"] = abilDict[classType][info[abil]["display_name"]]
for ref in range(len(info[abil]["parents"])):
info[abil]["parents"][ref] = abilDict[classType][info[abil]["parents"][ref]]
for ref in range(len(info[abil]["dependencies"])):
info[abil]["dependencies"][ref] = abilDict[classType][info[abil]["dependencies"][ref]]
for ref in range(len(info[abil]["blockers"])):
info[abil]["blockers"][ref] = abilDict[classType][info[abil]["blockers"][ref]]
translate_id(abilDict, data)
data_str = json.dumps(data, ensure_ascii=False, separators=(',', ':'))
data_str = "const atrees=" + data_str

100
py_script/items_common.py Normal file
View file

@ -0,0 +1,100 @@
translate_mappings = {
#"name": "name",
#"displayName": "displayName",
#"tier": "tier",
#"set": "set",
"sockets": "slots",
#"type": "type",
#"armorType": "armorType", (deleted)
"armorColor": "color", #(deleted)
"addedLore": "lore", #(deleted)
#"material": "material", (deleted)
"dropType": "drop",
#"quest": "quest",
"restrictions": "restrict",
"damage": "nDam",
"fireDamage": "fDam",
"waterDamage": "wDam",
"airDamage": "aDam",
"thunderDamage": "tDam",
"earthDamage": "eDam",
"attackSpeed": "atkSpd",
"health": "hp",
"fireDefense": "fDef",
"waterDefense": "wDef",
"airDefense": "aDef",
"thunderDefense": "tDef",
"earthDefense": "eDef",
"level": "lvl",
"classRequirement": "classReq",
"strength": "strReq",
"dexterity": "dexReq",
"intelligence": "intReq",
"agility": "agiReq",
"defense": "defReq",
"healthRegen": "hprPct",
"manaRegen": "mr",
"spellDamage": "sdPct",
"damageBonus": "mdPct",
"lifeSteal": "ls",
"manaSteal": "ms",
"xpBonus": "xpb",
"lootBonus": "lb",
"reflection": "ref",
"strengthPoints": "str",
"dexterityPoints": "dex",
"intelligencePoints": "int",
"agilityPoints": "agi",
"defensePoints": "def",
#"thorns": "thorns",
"exploding": "expd",
"speed": "spd",
"attackSpeedBonus": "atkTier",
#"poison": "poison",
"healthBonus": "hpBonus",
"soulPoints": "spRegen",
"emeraldStealing": "eSteal",
"healthRegenRaw": "hprRaw",
"spellDamageRaw": "sdRaw",
"damageBonusRaw": "mdRaw",
"bonusFireDamage": "fDamPct",
"bonusWaterDamage": "wDamPct",
"bonusAirDamage": "aDamPct",
"bonusThunderDamage": "tDamPct",
"bonusEarthDamage": "eDamPct",
"bonusFireDefense": "fDefPct",
"bonusWaterDefense": "wDefPct",
"bonusAirDefense": "aDefPct",
"bonusThunderDefense": "tDefPct",
"bonusEarthDefense": "eDefPct",
"accessoryType": "type",
"identified": "fixID",
#"skin": "skin",
#"category": "category",
"spellCostPct1": "spPct1",
"spellCostRaw1": "spRaw1",
"spellCostPct2": "spPct2",
"spellCostRaw2": "spRaw2",
"spellCostPct3": "spPct3",
"spellCostRaw3": "spRaw3",
"spellCostPct4": "spPct4",
"spellCostRaw4": "spRaw4",
"rainbowSpellDamageRaw": "rainbowRaw",
#"sprint": "sprint",
"sprintRegen": "sprintReg",
"jumpHeight": "jh",
"lootQuality": "lq",
"gatherXpBonus": "gXp",
"gatherSpeed": "gSpd",
}
delete_keys = [
#"addedLore",
#"skin",
#"armorType",
#"armorColor",
#"material"
]

23
py_script/merge.json Normal file
View file

@ -0,0 +1,23 @@
{"items": [
{"name":"Keratoconus","type":"helmet","level":101,"tier":"Legendary","sockets":3,"majorIds":[],"intelligence":65,"agility":65,"intelligencePoints":15,"defensePoints":-10,"health":3900,"thunderDefense":-150,"fireDefense":-150,"airDefense":250,"tDamPct-base":-40,"wDamPct-base":30,"aDamPct-base":35,"hprPct-base":-50,"mr-base":8,"spRaw4-base":-4,"category":"armor","displayName":"Keratoconus","bonusThunderDamage":-40,"bonusWaterDamage":30,"bonusAirDamage":35,"healthRegen":-50,"manaRegen":8,"spellCostRaw4":-4,"identified":false},
{"name":"Wanderlust","type":"chestplate","level":103,"tier":"Legendary","sockets":2,"majorIds":[],"dexterity":45,"agility":55,"health":3500,"thunderDefense":75,"waterDefense":100,"fireDefense":-75,"airDefense":100,"wDamPct-base":20,"aDamPct-base":30,"sdRaw-base":208,"hprPct-base":-15,"ms-base":-11,"ls-base":230,"spd-base":25,"category":"armor","displayName":"Wanderlust","bonusWaterDamage":20,"bonusAirDamage":30,"spellDamageRaw":208,"healthRegen":-15,"manaSteal":-12,"lifeSteal":230,"speed":25,"identified":false},
{"name":"Anaerobic","type":"leggings","level":104,"tier":"Legendary","majorIds":[],"strength":60,"agility":60,"strengthPoints":12,"health":3850,"earthDefense":100,"waterDefense":-150,"airDefense":100,"eDamPct-base":24,"aDamPct-base":32,"atkTier-base":-1,"mr-base":8,"ref-base":48,"spRaw1-base":-5,"category":"armor","displayName":"Anaerobic","bonusEarthDamage":24,"bonusAirDamage":32,"attackSpeedBonus":-1,"manaRegen":8,"reflection":48,"spellCostRaw1":-8,"identified":false},
{"name":"Danse Macabre","type":"relik","level":102,"tier":"Rare","sockets":1,"majorIds":[],"classRequirement":"Shaman","dexterity":55,"defense":50,"damage":"0-0","earthDamage":"0-0","thunderDamage":"24-214","waterDamage":"0-0","fireDamage":"97-141","airDamage":"0-0","attackSpeed":"VERY_FAST","sdRaw-base":184,"atkTier-base":1,"hpBonus-base":-1150,"hprPct-base":-204,"ms-base":13,"spRaw1-base":-7,"category":"weapon","displayName":"Danse Macabre","basedps":238,"spellDamageRaw":184,"attackSpeedBonus":1,"healthBonus":-1150,"healthRegen":-204,"manaSteal":13,"spellCostRaw1":-7,"identified":false},
{"name":"Darkness's Dogma","type":"bow","level":103,"tier":"Rare","sockets":3,"majorIds":[],"classRequirement":"Archer","intelligence":60,"defense":50,"damage":"0-0","earthDamage":"0-0","thunderDamage":"0-0","waterDamage":"600-650","fireDamage":"550-700","airDamage":"0-0","attackSpeed":"SUPER_SLOW","hpBonus-base":1500,"wDefPct-base":-50,"fDefPct-base":-50,"ms-base":13,"ls-base":-700,"ref-base":25,"category":"weapon","displayName":"Darkness's Dogma","basedps":1250,"healthBonus":1500,"bonusWaterDefense":-50,"bonusFireDefense":-50,"manaSteal":13,"lifeSteal":-700,"reflection":25,"identified":false},
{"name":"Frameshift","type":"wand","level":104,"tier":"Rare","sockets":3,"majorIds":[],"classRequirement":"Mage","strength":40,"defense":60,"defensePoints":20,"damage":"0-0","earthDamage":"150-210","thunderDamage":"0-0","waterDamage":"0-0","fireDamage":"160-200","airDamage":"0-0","attackSpeed":"VERY_SLOW","wDamPct-base":-30,"mdPct-base":25,"mr-base":7,"ls-base":380,"spRaw1-base":-4,"category":"weapon","displayName":"Frameshift","basedps":360,"bonusWaterDamage":-30,"damageBonus":25,"manaRegen":7,"lifeSteal":380,"spellCostRaw1":-4,"identified":false},
{"name":"Helminth","type":"spear","level":102,"tier":"Rare","sockets":2,"majorIds":[],"classRequirement":"Warrior","dexterity":65,"damage":"0-0","earthDamage":"0-0","thunderDamage":"1-199","waterDamage":"0-0","fireDamage":"0-0","airDamage":"0-0","attackSpeed":"SUPER_FAST","tDamPct-base":20,"atkTier-base":1,"hpBonus-base":-1250,"wDefPct-base":-35,"aDefPct-base":-35,"ls-base":500,"category":"weapon","displayName":"Helminth","basedps":100,"bonusThunderDamage":20,"attackSpeedBonus":1,"healthBonus":-1250,"bonusWaterDefense":-35,"bonusAirDefense":-35,"lifeSteal":500,"identified":false},
{"name":"Lanternfly Leg","type":"dagger","level":101,"tier":"Rare","sockets":3,"majorIds":[],"classRequirement":"Assassin","defense":50,"agility":50,"damage":"150-210","earthDamage":"0-0","thunderDamage":"0-0","waterDamage":"0-0","fireDamage":"0-0","airDamage":"0-0","attackSpeed":"FAST","fDamPct-base":23,"aDamPct-base":23,"hpBonus-base":1000,"jh-base":1,"spd-base":30,"spRaw2-base":-2,"category":"weapon","displayName":"Lanternfly Leg","basedps":180,"bonusFireDamage":23,"bonusAirDamage":23,"healthBonus":1000,"jumpHeight":1,"speed":30,"spellCostRaw2":-4,"identified":false},
{"name":"Dissonance","type":"helmet","level":103,"tier":"Unique","sockets":2,"majorIds":[],"dexterity":50,"intelligence":50,"health":3050,"thunderDefense":100,"waterDefense":100,"airDefense":-175,"tDamPct-base":12,"wDamPct-base":20,"sdPct-base":20,"ls-base":-275,"spd-base":-20,"sprint-base":20,"lb-base":20,"category":"armor","displayName":"Dissonance","bonusThunderDamage":12,"bonusWaterDamage":20,"spellDamage":20,"lifeSteal":-275,"speed":-20,"sprint":20,"lootBonus":20,"identified":false},
{"name":"Roridula","type":"chestplate","level":104,"tier":"Unique","sockets":2,"majorIds":[],"strength":55,"intelligence":55,"strengthPoints":10,"health":3675,"earthDefense":150,"fireDefense":-150,"tDamPct-base":-30,"wDamPct-base":25,"ms-base":8,"spd-base":15,"spPct4-base":14,"xpb-base":25,"category":"armor","displayName":"Roridula","bonusThunderDamage":-30,"bonusWaterDamage":25,"manaSteal":8,"speed":15,"spellCostPct4":14,"xpBonus":25,"identified":false},
{"name":"Atomizer","type":"leggings","level":102,"tier":"Unique","sockets":3,"majorIds":[],"agility":75,"agilityPoints":8,"health":3450,"waterDefense":120,"fireDefense":120,"airDefense":200,"poison-base":600,"wDefPct-base":31,"fDefPct-base":31,"hprPct-base":37,"thorns-base":25,"jh-base":1,"category":"armor","displayName":"Atomizer","poison":600,"bonusWaterDefense":31,"bonusFireDefense":31,"healthRegen":37,"thorns":25,"jumpHeight":1,"identified":false},
{"name":"Wasteland Azalea","type":"boots","level":101,"tier":"Unique","sockets":3,"majorIds":[],"strength":45,"agility":50,"health":2750,"earthDefense":75,"fireDefense":-75,"eDamPct-base":25,"aDamPct-base":25,"sdRaw-base":140,"atkTier-base":-1,"poison-base":500,"sprint-base":-15,"spRaw3-base":-6,"category":"armor","displayName":"Wasteland Azalea","bonusEarthDamage":25,"bonusAirDamage":25,"spellDamageRaw":140,"attackSpeedBonus":-1,"poison":500,"sprint":-15,"spellCostRaw3":-6,"identified":false},
{"name":"Tranquility","type":"ring","level":101,"tier":"Unique","majorIds":[],"dexterity":45,"intelligence":45,"strengthPoints":-3,"dexterityPoints":-3,"health":550,"waterDefense":50,"fireDefense":50,"sdPct-base":5,"hprPct-base":17,"spd-base":-7,"category":"accessory","displayName":"Tranquility","spellDamage":5,"healthRegen":17,"speed":-7,"identified":false},
{"name":"Misalignment","type":"bracelet","level":101,"tier":"Unique","majorIds":[],"strength":35,"dexterity":45,"dexterityPoints":3,"intelligencePoints":3,"eDamPct-base":6,"tDamPct-base":6,"wDamPct-base":10,"mr-base":3,"category":"accessory","displayName":"Misalignment","bonusEarthDamage":6,"bonusThunderDamage":6,"bonusWaterDamage":10,"manaRegen":3,"identified":false},
{"name":"Grafted Eyestalk","type":"necklace","level":101,"tier":"Unique","majorIds":[],"defense":40,"agility":40,"defensePoints":5,"agilityPoints":5,"health":-600,"earthDefense":-40,"thunderDefense":-40,"sdPct-base":8,"hprPct-base":-11,"spRaw1-base":-1,"category":"accessory","displayName":"Grafted Eyestalk","spellDamage":8,"healthRegen":-12,"spellCostRaw1":-1,"identified":false},
{"name":"Forbearance","type":"ring","level":105,"tier":"Fabled","majorIds":[],"dexterity":60,"intelligence":60,"dexterityPoints":6,"intelligencePoints":6,"tDamPct-base":-15,"wDamPct-base":-15,"mr-base":4,"ls-base":120,"category":"accessory","displayName":"Forbearance","bonusThunderDamage":-15,"bonusWaterDamage":-15,"manaRegen":4,"lifeSteal":120,"identified":false},
{"name":"Ingress","type":"ring","level":105,"tier":"Fabled","majorIds":[],"strength":55,"agility":55,"dexterityPoints":4,"intelligencePoints":2,"defensePoints":4,"earthDefense":55,"airDefense":55,"eDamPct-base":8,"aDamPct-base":8,"sdRaw-base":55,"category":"accessory","displayName":"Ingress","bonusEarthDamage":8,"bonusAirDamage":8,"spellDamageRaw":55,"identified":false},
{"name":"Breakthrough","type":"bracelet","level":105,"tier":"Fabled","majorIds":[],"intelligence":45,"agility":45,"strengthPoints":-4,"dexterityPoints":-4,"defensePoints":-6,"earthDefense":-45,"thunderDefense":-45,"fireDefense":-30,"sdPct-base":13,"sdRaw-base":75,"ms-base":6,"spRaw2-base":-4,"category":"accessory","displayName":"Breakthrough","spellDamage":13,"spellDamageRaw":75,"manaSteal":6,"spellCostRaw2":-4,"identified":false},
{"name":"Detachment","type":"bracelet","level":105,"tier":"Fabled","majorIds":[],"dexterity":55,"agility":60,"thunderDefense":60,"airDefense":60,"mdRaw-base":-85,"sdRaw-base":-65,"spd-base":13,"spPct4-base":-13,"category":"accessory","displayName":"Detachment","damageBonusRaw":-85,"spellDamageRaw":-65,"speed":13,"spellCostPct4":-13,"identified":false},
{"name":"Exhibition","type":"necklace","level":105,"tier":"Fabled","majorIds":[],"intelligence":80,"earthDefense":-30,"thunderDefense":-30,"waterDefense":60,"fireDefense":-30,"airDefense":-30,"mr-base":-4,"spRaw1-base":-2,"spRaw2-base":-2,"spRaw3-base":-2,"spRaw4-base":-2,"category":"accessory","displayName":"Exhibition","manaRegen":-4,"spellCostRaw1":-2,"spellCostRaw2":-2,"spellCostRaw3":-2,"spellCostRaw4":-2,"identified":false},
{"name":"Simulacrum","type":"necklace","level":105,"tier":"Fabled","majorIds":[],"strength":55,"defense":45,"health":-800,"earthDefense":-70,"fireDefense":-90,"sdRaw-base":150,"hprRaw-base":-150,"mr-base":5,"spd-base":8,"category":"accessory","displayName":"Simulacrum","spellDamageRaw":150,"healthRegenRaw":-150,"manaRegen":5,"speed":8,"identified":false}
]}

124
py_script/merge_items.py Normal file
View file

@ -0,0 +1,124 @@
"""
Used to process the raw item data pulled from the API.
Usage:
- python process_items.py [infile] [outfile]
OR
- python process_items.py [infile and outfile]
"""
import json
import sys
import os
import base64
import argparse
from items_common import translate_mappings, delete_keys
parser = argparse.ArgumentParser(description="Process raw pulled item data.")
parser.add_argument('infile', help='input file to read data from')
parser.add_argument('outfile', help='output file to dump clean data into')
args = parser.parse_args()
infile, outfile = args.infile, args.outfile
with open(infile, "r") as in_file:
data = json.loads(in_file.read())
items = data["items"]
if "request" in data:
del data["request"]
with open("./clean.json", "r") as oldfile:
old_data = json.load(oldfile)
old_items = old_data['items']
id_map = {item["name"]: item["id"] for item in old_items}
with open("id_map_tmp.json", "r") as idmap_file:
id_map = json.load(idmap_file)
used_ids = set([v for k, v in id_map.items()])
max_id = 0
known_item_names = set()
for item in items:
known_item_names.add(item["name"])
# TEMP wynn2 migration
# note: 10x'd
mul_keys = {
"spPct1": 7,
"spPct2": 7,
"spPct3": 7,
"spPct4": 7,
"spRaw1": 50,
"spRaw2": 50,
"spRaw3": 50,
"spRaw4": 50,
"mr": 50,
"ms": 50
}
remap_items = []
#old_items_map = dict()
import math
for item in old_items:
for k, v in mul_keys.items():
if k in item:
# SUPER JANKY ROUNDING
tentimes = round(item[k] * v)
rem = tentimes % 10
val = math.floor(round(tentimes / 10))
if rem >= 5:
val += 1
item[k] = val
if "remapID" in item:
remap_items.append(item)
elif item["name"] not in known_item_names:
items.append(item)
#print(f'Unknown old item: {item["name"]}!!!')
#old_items_map[item["name"]] = item
for item in items:
for key in delete_keys:
if key in item:
del item[key]
for k in list(item.keys()):
if (item[k] == 0 or item[k] is None):
del item[k]
for k, v in translate_mappings.items():
if k in item:
item[v] = item[k]
del item[k]
if not (item["name"] in id_map):
while max_id in used_ids:
max_id += 1
used_ids.add(max_id)
id_map[item["name"]] = max_id
print(f'New item: {item["name"]} (id: {max_id})')
item["id"] = id_map[item["name"]]
item["type"] = item["type"].lower()
if "displayName" in item:
item_name = item["displayName"]
else:
item_name = item["name"]
items.extend(remap_items)
#write items back into data
data["items"] = items
data["sets"] = old_data["sets"]
#save id map
with open("id_map_tmp.json","w") as id_mapfile:
json.dump(id_map, id_mapfile, indent=2)
#write the data back to the outfile
with open(outfile, "w+") as out_file:
json.dump(data, out_file)

View file

@ -15,6 +15,7 @@ import sys
import os
import base64
import argparse
from items_common import translate_mappings, delete_keys
parser = argparse.ArgumentParser(description="Process raw pulled item data.")
parser.add_argument('infile', help='input file to read data from')
@ -30,108 +31,6 @@ items = data["items"]
if "request" in data:
del data["request"]
translate_mappings = {
#"name": "name",
#"displayName": "displayName",
#"tier": "tier",
#"set": "set",
"sockets": "slots",
#"type": "type",
#"armorType": "armorType", (deleted)
"armorColor": "color", #(deleted)
"addedLore": "lore", #(deleted)
#"material": "material", (deleted)
"dropType": "drop",
#"quest": "quest",
"restrictions": "restrict",
"damage": "nDam",
"fireDamage": "fDam",
"waterDamage": "wDam",
"airDamage": "aDam",
"thunderDamage": "tDam",
"earthDamage": "eDam",
"attackSpeed": "atkSpd",
"health": "hp",
"fireDefense": "fDef",
"waterDefense": "wDef",
"airDefense": "aDef",
"thunderDefense": "tDef",
"earthDefense": "eDef",
"level": "lvl",
"classRequirement": "classReq",
"strength": "strReq",
"dexterity": "dexReq",
"intelligence": "intReq",
"agility": "agiReq",
"defense": "defReq",
"healthRegen": "hprPct",
"manaRegen": "mr",
"spellDamage": "sdPct",
"damageBonus": "mdPct",
"lifeSteal": "ls",
"manaSteal": "ms",
"xpBonus": "xpb",
"lootBonus": "lb",
"reflection": "ref",
"strengthPoints": "str",
"dexterityPoints": "dex",
"intelligencePoints": "int",
"agilityPoints": "agi",
"defensePoints": "def",
#"thorns": "thorns",
"exploding": "expd",
"speed": "spd",
"attackSpeedBonus": "atkTier",
#"poison": "poison",
"healthBonus": "hpBonus",
"soulPoints": "spRegen",
"emeraldStealing": "eSteal",
"healthRegenRaw": "hprRaw",
"spellDamageRaw": "sdRaw",
"damageBonusRaw": "mdRaw",
"bonusFireDamage": "fDamPct",
"bonusWaterDamage": "wDamPct",
"bonusAirDamage": "aDamPct",
"bonusThunderDamage": "tDamPct",
"bonusEarthDamage": "eDamPct",
"bonusFireDefense": "fDefPct",
"bonusWaterDefense": "wDefPct",
"bonusAirDefense": "aDefPct",
"bonusThunderDefense": "tDefPct",
"bonusEarthDefense": "eDefPct",
"accessoryType": "type",
"identified": "fixID",
#"skin": "skin",
#"category": "category",
"spellCostPct1": "spPct1",
"spellCostRaw1": "spRaw1",
"spellCostPct2": "spPct2",
"spellCostRaw2": "spRaw2",
"spellCostPct3": "spPct3",
"spellCostRaw3": "spRaw3",
"spellCostPct4": "spPct4",
"spellCostRaw4": "spRaw4",
"rainbowSpellDamageRaw": "rainbowRaw",
#"sprint": "sprint",
"sprintRegen": "sprintReg",
"jumpHeight": "jh",
"lootQuality": "lq",
"gatherXpBonus": "gXp",
"gatherSpeed": "gSpd",
}
delete_keys = [
#"addedLore",
#"skin",
#"armorType",
#"armorColor",
#"material"
]
with open("../clean.json", "r") as oldfile:
old_data = json.load(oldfile)
old_items = old_data['items']
@ -188,6 +87,8 @@ items.extend(remap_items)
#write items back into data
data["items"] = items
data["sets"] = old_data["sets"]
#save id map
with open("id_map.json","w") as id_mapfile:
json.dump(id_map, id_mapfile, indent=2)

View file

@ -29,6 +29,7 @@
<a href = ""><img src = "../media/icons/new/book.png" alt = "Wynnfo" title = "Wynnfo"><b>Wynnfo</b></a>
<a 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 py-5 vh-100 mx-0 mx-lg-auto scaled-font" id = "main">
<div class = "row item-title">Welcome!</div>