Merge branch 'atree' into atree_active_box
This commit is contained in:
commit
fdaad6931b
36 changed files with 2395 additions and 1867 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,5 +1,6 @@
|
||||||
*.swp
|
*.swp
|
||||||
*.bat
|
*.bat
|
||||||
|
*.json
|
||||||
sets/
|
sets/
|
||||||
|
|
||||||
.idea/
|
.idea/
|
||||||
|
|
|
@ -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 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>
|
<a onclick = "toggleIcons()"><img src = "../media/icons/new/reload.png" alt = "" title = "Swap items on page"><b>Swap Icon Style</b></a>
|
||||||
<hr/>
|
<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>
|
||||||
<div class="container-fluid py-1 vh-100">
|
<div class="container-fluid py-1 vh-100">
|
||||||
<div class = "row">
|
<div class = "row">
|
||||||
|
|
|
@ -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 = "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>
|
<a onclick = "toggleIcons()"><img src = "../media/icons/new/reload.png" alt = "" title = "Swap items on page"><b>Swap Icon Style</b></a>
|
||||||
<hr/>
|
<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>
|
||||||
<div class="container-fluid me-4" style="max-width: 95%; display: none">
|
<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">
|
<div class="row h-100 gx-lg-5 gy-3 mx-2 mx-lg-3 py-3">
|
||||||
|
|
|
@ -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 = "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>
|
<a onclick = "toggleIcons()"><img src = "../media/icons/new/reload.png" alt = "" title = "Swap items on page"><b>Swap Icon Style</b></a>
|
||||||
<hr/>
|
<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>
|
||||||
<div class="container-fluid me-4" style="max-width: 95%;">
|
<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="row h-100 gx-lg-5 gy-3 mx-2 mx-lg-3 py-3">
|
||||||
<div class="col-xl-6">
|
<div class="col-xl-6">
|
||||||
<div class="row row-cols-1 mb-3 gy-4">
|
<div class="row row-cols-1 mb-3 gy-4">
|
||||||
|
@ -1270,20 +1275,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div id="all-spells-display" class="row row-cols-1 gy-3 text-center scaled-font pe-0">
|
<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 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 spell-expand dark-5 rounded dark-shadow pt-2 border border-dark" id="spell0-infoAvg">Input a weapon to see abilities!</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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class = "col">
|
<div class = "col">
|
||||||
|
|
3105
clean.json
3105
clean.json
File diff suppressed because it is too large
Load diff
File diff suppressed because one or more lines are too long
|
@ -29,6 +29,7 @@
|
||||||
<a href = "../wynnfo/"><img src = "../media/icons/new/book.png" alt = "Wynnfo" title = "Wynnfo"><b>Wynnfo</b></a>
|
<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>
|
<a onclick = "toggleIcons()"><img src = "../media/icons/new/reload.png" alt = "" title = "Swap items on page"><b>Swap Icon Style</b></a>
|
||||||
<hr/>
|
<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>
|
||||||
<div class = "container py-5 vh-100 mx-0 mx-lg-auto">
|
<div class = "container py-5 vh-100 mx-0 mx-lg-auto">
|
||||||
<div class = "col">
|
<div class = "col">
|
||||||
|
|
|
@ -498,3 +498,10 @@ a:hover {
|
||||||
-moz-border-radius:50%;
|
-moz-border-radius:50%;
|
||||||
-webkit-border-radius:50%;
|
-webkit-border-radius:50%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.hppeng{
|
||||||
|
color: #20c2b6;
|
||||||
|
}
|
||||||
|
.ferricles{
|
||||||
|
color: #5be553;
|
||||||
|
}
|
|
@ -31,6 +31,7 @@
|
||||||
<a href = "../wynnfo/"><img src = "../media/icons/new/book.png" alt = "Wynnfo" title = "Wynnfo"><b>Wynnfo</b></a>
|
<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>
|
<a onclick = "toggleIcons()"><img src = "../media/icons/new/reload.png" alt = "" title = "Swap items on page"><b>Swap Icon Style</b></a>
|
||||||
<hr/>
|
<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>
|
||||||
<div class = "container row py-5 vh-100 mx-0 mx-lg-auto scaled-font">
|
<div class = "container row py-5 vh-100 mx-0 mx-lg-auto scaled-font">
|
||||||
<div class = "col-lg-3 col-sm-12">
|
<div class = "col-lg-3 col-sm-12">
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
<a href="" onclick="toggleIcons()"><img src="../media/icons/new/reload.png" alt=""
|
<a href="" onclick="toggleIcons()"><img src="../media/icons/new/reload.png" alt=""
|
||||||
title="Swap items on page"><b>Swap Icon Style</b></a>
|
title="Swap items on page"><b>Swap Icon Style</b></a>
|
||||||
<hr />
|
<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>
|
||||||
<div class="container text-light px-5 scaled-font">
|
<div class="container text-light px-5 scaled-font">
|
||||||
<div class="row justify-content-center page-title">
|
<div class="row justify-content-center page-title">
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
<a href = "../wynnfo/"><img src = "../media/icons/new/book.png" alt = "Wynnfo" title = "Wynnfo"><b>Wynnfo</b></a>
|
<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>
|
<a onclick = "toggleIcons()"><img src = "../media/icons/new/reload.png" alt = "" title = "Swap items on page"><b>Swap Icon Style</b></a>
|
||||||
<hr/>
|
<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>
|
||||||
|
|
||||||
<div class = "container py-5 vh-100 mx-0 mx-lg-auto scaled-font">
|
<div class = "container py-5 vh-100 mx-0 mx-lg-auto scaled-font">
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
<a href = "../wynnfo/"><img src = "../media/icons/new/book.png" alt = "Wynnfo" title = "Wynnfo"><b>Wynnfo</b></a>
|
<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>
|
<a onclick = "toggleIcons()"><img src = "../media/icons/new/reload.png" alt = "" title = "Swap items on page"><b>Swap Icon Style</b></a>
|
||||||
<hr/>
|
<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>
|
||||||
<div class = "container py-5 vh-100 mx-0 mx-lg-auto scaled-font">
|
<div class = "container py-5 vh-100 mx-0 mx-lg-auto scaled-font">
|
||||||
<div class = "col">
|
<div class = "col">
|
||||||
|
|
|
@ -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 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>
|
<a onclick = "toggleIcons()"><img src = "../media/icons/new/reload.png" alt = "" title = "Swap items on page"><b>Swap Icon Style</b></a>
|
||||||
<hr/>
|
<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>
|
||||||
<div class = "container py-5 vh-100 mx-0 mx-lg-auto scaled-font">
|
<div class = "container py-5 vh-100 mx-0 mx-lg-auto scaled-font">
|
||||||
<div class = "col">
|
<div class = "col">
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
<a href = "../wynnfo/"><img src = "../media/icons/new/book.png" alt = "Wynnfo" title = "WynnCrafter"><b>WynnCrafter</b></a>
|
<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>
|
<a onclick = "toggleIcons()"><img src = "../media/icons/new/reload.png" alt = "" title = "Swap items on page"><b>Swap Icon Style</b></a>
|
||||||
<hr/>
|
<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>
|
||||||
<main>
|
<main>
|
||||||
<div class="full-width text-center">
|
<div class="full-width text-center">
|
||||||
|
|
5
js/README_atree_constants.md
Normal file
5
js/README_atree_constants.md
Normal 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
|
65
js/atree.js
65
js/atree.js
|
@ -39,6 +39,9 @@ add_spell_prop: {
|
||||||
base_spell: int // spell identifier
|
base_spell: int // spell identifier
|
||||||
target_part: Optional[str] // Part of the spell to modify. Can be not present/empty for ex. cost modifier.
|
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.
|
// 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
|
cost: Optional[int] // change to spellcost
|
||||||
multipliers: Optional[array[float, 6]] // Additive changes to spellmult (for damage spell)
|
multipliers: Optional[array[float, 6]] // Additive changes to spellmult (for damage spell)
|
||||||
power: Optional[float] // Additive change to healing power (for heal spell)
|
power: Optional[float] // Additive change to healing power (for heal spell)
|
||||||
|
@ -57,6 +60,9 @@ raw_stat: {
|
||||||
type: "raw_stat"
|
type: "raw_stat"
|
||||||
toggle: Optional[bool | str] // default: false; true means create anon. toggle,
|
toggle: Optional[bool | str] // default: false; true means create anon. toggle,
|
||||||
// string value means bind to (or create) named button
|
// 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]
|
bonuses: List[stat_bonus]
|
||||||
}
|
}
|
||||||
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 [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];
|
const atree_raw = atrees[player_class];
|
||||||
if (!atree_raw) return null;
|
if (!atree_raw) return [];
|
||||||
|
|
||||||
let atree_map = new Map();
|
let atree_map = new Map();
|
||||||
let atree_head;
|
let atree_head;
|
||||||
|
@ -287,7 +293,7 @@ const atree_merge = new (class extends ComputeNode {
|
||||||
}
|
}
|
||||||
return abils_merged;
|
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.
|
* Validate ability tree.
|
||||||
|
@ -302,6 +308,8 @@ const atree_validate = new (class extends ComputeNode {
|
||||||
const atree_state = input_map.get('atree-state');
|
const atree_state = input_map.get('atree-state');
|
||||||
const atree_order = input_map.get('atree');
|
const atree_order = input_map.get('atree');
|
||||||
|
|
||||||
|
if (atree_order.length == 0) { return [0, ['no atree data']]; }
|
||||||
|
|
||||||
let errors = [];
|
let errors = [];
|
||||||
let reachable = new Map();
|
let reachable = new Map();
|
||||||
atree_dfs_mark(atree_order[0], atree_state, reachable);
|
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;
|
has_spell_def = true;
|
||||||
// replace_spell just replaces all (defined) aspects.
|
// replace_spell just replaces all (defined) aspects.
|
||||||
for (const key in effect) {
|
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.
|
// Already handled above.
|
||||||
continue;
|
continue;
|
||||||
case 'add_spell_prop': {
|
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
|
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) {
|
if (target_part === null) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -497,7 +505,7 @@ const atree_collect_spells = new (class extends ComputeNode {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found_part) { // add part.
|
if (!found_part && behavior === 'merge') { // add part. if behavior is merge
|
||||||
let spell_part = deepcopy(effect);
|
let spell_part = deepcopy(effect);
|
||||||
spell_part.name = target_part; // has some extra fields but whatever
|
spell_part.name = target_part; // has some extra fields but whatever
|
||||||
ret_spell.parts.push(spell_part);
|
ret_spell.parts.push(spell_part);
|
||||||
|
@ -534,6 +542,51 @@ const atree_collect_spells = new (class extends ComputeNode {
|
||||||
}
|
}
|
||||||
})().link_to(atree_merge, 'atree-merged');
|
})().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.
|
* Construct compute nodes to link builder items and edit IDs to the appropriate display outputs.
|
||||||
|
|
|
@ -9,7 +9,8 @@ const atrees = {
|
||||||
"cost": 1,
|
"cost": 1,
|
||||||
"display": {
|
"display": {
|
||||||
"row": 9,
|
"row": 9,
|
||||||
"col": 6
|
"col": 6,
|
||||||
|
"icon": "node_4"
|
||||||
},
|
},
|
||||||
"properties": {
|
"properties": {
|
||||||
"charges": 2,
|
"charges": 2,
|
||||||
|
@ -49,7 +50,8 @@ const atrees = {
|
||||||
"cost": 1,
|
"cost": 1,
|
||||||
"display": {
|
"display": {
|
||||||
"row": 7,
|
"row": 7,
|
||||||
"col": 4
|
"col": 4,
|
||||||
|
"icon": "node_4"
|
||||||
},
|
},
|
||||||
"properties": {
|
"properties": {
|
||||||
"aoe": 0,
|
"aoe": 0,
|
||||||
|
@ -73,7 +75,8 @@ const atrees = {
|
||||||
"cost": 1,
|
"cost": 1,
|
||||||
"display": {
|
"display": {
|
||||||
"row": 0,
|
"row": 0,
|
||||||
"col": 4
|
"col": 4,
|
||||||
|
"icon": "node_4"
|
||||||
},
|
},
|
||||||
"properties": {
|
"properties": {
|
||||||
"aoe": 4.5,
|
"aoe": 4.5,
|
||||||
|
@ -111,7 +114,8 @@ const atrees = {
|
||||||
"cost": 1,
|
"cost": 1,
|
||||||
"display": {
|
"display": {
|
||||||
"row": 4,
|
"row": 4,
|
||||||
"col": 4
|
"col": 4,
|
||||||
|
"icon": "node_1"
|
||||||
},
|
},
|
||||||
"properties": {},
|
"properties": {},
|
||||||
"effects": [
|
"effects": [
|
||||||
|
@ -139,7 +143,8 @@ const atrees = {
|
||||||
"cost": 2,
|
"cost": 2,
|
||||||
"display": {
|
"display": {
|
||||||
"row": 16,
|
"row": 16,
|
||||||
"col": 6
|
"col": 6,
|
||||||
|
"icon": "node_1"
|
||||||
},
|
},
|
||||||
"properties": {
|
"properties": {
|
||||||
"aoe": 0.8,
|
"aoe": 0.8,
|
||||||
|
@ -170,7 +175,7 @@ const atrees = {
|
||||||
"dependencies": ["Arrow Storm"],
|
"dependencies": ["Arrow Storm"],
|
||||||
"blockers": [],
|
"blockers": [],
|
||||||
"cost": 2,
|
"cost": 2,
|
||||||
"display": { "row": 16, "col": 8 },
|
"display": { "row": 16, "col": 8, "icon": "node_1"},
|
||||||
"properties": {
|
"properties": {
|
||||||
"aoe": 2,
|
"aoe": 2,
|
||||||
"duration": 5
|
"duration": 5
|
||||||
|
@ -199,7 +204,7 @@ const atrees = {
|
||||||
"dependencies": ["Arrow Storm"],
|
"dependencies": ["Arrow Storm"],
|
||||||
"blockers": ["Phantom Ray"],
|
"blockers": ["Phantom Ray"],
|
||||||
"cost": 2,
|
"cost": 2,
|
||||||
"display": { "row": 15, "col": 2 },
|
"display": { "row": 15, "col": 2, "icon": "node_1"},
|
||||||
"properties": {},
|
"properties": {},
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
|
@ -223,7 +228,7 @@ const atrees = {
|
||||||
"dependencies": [],
|
"dependencies": [],
|
||||||
"blockers": [],
|
"blockers": [],
|
||||||
"cost": 1,
|
"cost": 1,
|
||||||
"display": { "row": 9, "col": 2 },
|
"display": { "row": 9, "col": 2, "icon": "node_4"},
|
||||||
"properties": { "range": 16 },
|
"properties": { "range": 16 },
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
|
@ -262,15 +267,16 @@ const atrees = {
|
||||||
"blockers": [],
|
"blockers": [],
|
||||||
"cost": 2,
|
"cost": 2,
|
||||||
"display": {
|
"display": {
|
||||||
"row": 19,
|
"row": 19,
|
||||||
"col": 1
|
"col": 1,
|
||||||
|
"icon": "node_3"
|
||||||
},
|
},
|
||||||
"properties": {
|
"properties": {
|
||||||
"range": 4,
|
"range": 4,
|
||||||
"duration": 60,
|
"duration": 60,
|
||||||
"shots": 8,
|
"shots": 8,
|
||||||
"count": 2
|
"charges": 2
|
||||||
},
|
},
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"type": "replace_spell",
|
"type": "replace_spell",
|
||||||
|
@ -311,7 +317,8 @@ const atrees = {
|
||||||
"cost": 1,
|
"cost": 1,
|
||||||
"display": {
|
"display": {
|
||||||
"row": 10,
|
"row": 10,
|
||||||
"col": 1
|
"col": 1,
|
||||||
|
"icon": "node_0"
|
||||||
},
|
},
|
||||||
"properties": {
|
"properties": {
|
||||||
"aoe": 8,
|
"aoe": 8,
|
||||||
|
@ -341,7 +348,8 @@ const atrees = {
|
||||||
"cost": 2,
|
"cost": 2,
|
||||||
"display": {
|
"display": {
|
||||||
"row": 19,
|
"row": 19,
|
||||||
"col": 8
|
"col": 8,
|
||||||
|
"icon": "node_3"
|
||||||
},
|
},
|
||||||
"properties": {
|
"properties": {
|
||||||
"aoe": 7,
|
"aoe": 7,
|
||||||
|
@ -366,7 +374,8 @@ const atrees = {
|
||||||
"cost": 2,
|
"cost": 2,
|
||||||
"display": {
|
"display": {
|
||||||
"row": 21,
|
"row": 21,
|
||||||
"col": 1
|
"col": 1,
|
||||||
|
"icon": "node_1"
|
||||||
},
|
},
|
||||||
"properties": {},
|
"properties": {},
|
||||||
"effects": [
|
"effects": [
|
||||||
|
@ -404,7 +413,8 @@ const atrees = {
|
||||||
"cost": 2,
|
"cost": 2,
|
||||||
"display": {
|
"display": {
|
||||||
"row": 21,
|
"row": 21,
|
||||||
"col": 5
|
"col": 5,
|
||||||
|
"icon": "node_2"
|
||||||
},
|
},
|
||||||
"properties": {
|
"properties": {
|
||||||
"range": 26
|
"range": 26
|
||||||
|
@ -423,7 +433,8 @@ const atrees = {
|
||||||
"cost": 2,
|
"cost": 2,
|
||||||
"display": {
|
"display": {
|
||||||
"row": 22,
|
"row": 22,
|
||||||
"col": 6
|
"col": 6,
|
||||||
|
"icon": "node_1"
|
||||||
},
|
},
|
||||||
"properties": {},
|
"properties": {},
|
||||||
"effects": [
|
"effects": [
|
||||||
|
@ -446,7 +457,8 @@ const atrees = {
|
||||||
"cost": 2,
|
"cost": 2,
|
||||||
"display": {
|
"display": {
|
||||||
"row": 25,
|
"row": 25,
|
||||||
"col": 4
|
"col": 4,
|
||||||
|
"icon": "node_2"
|
||||||
},
|
},
|
||||||
"properties": {
|
"properties": {
|
||||||
"range": 64,
|
"range": 64,
|
||||||
|
@ -480,7 +492,7 @@ const atrees = {
|
||||||
"dependencies": [],
|
"dependencies": [],
|
||||||
"blockers": [],
|
"blockers": [],
|
||||||
"cost": 2,
|
"cost": 2,
|
||||||
"display": { "row": 26, "col": 1 },
|
"display": { "row": 26, "col": 1, "icon": "node_1"},
|
||||||
"properties": {
|
"properties": {
|
||||||
"aoe": 4
|
"aoe": 4
|
||||||
},
|
},
|
||||||
|
@ -513,7 +525,7 @@ const atrees = {
|
||||||
"dependencies": ["Fire Creep"],
|
"dependencies": ["Fire Creep"],
|
||||||
"blockers": [],
|
"blockers": [],
|
||||||
"cost": 1,
|
"cost": 1,
|
||||||
"display": { "row": 26, "col": 5 },
|
"display": { "row": 26, "col": 5, "icon": "node_1"},
|
||||||
"properties": {
|
"properties": {
|
||||||
"duration": 2,
|
"duration": 2,
|
||||||
"aoe": 0.4
|
"aoe": 0.4
|
||||||
|
@ -536,7 +548,7 @@ const atrees = {
|
||||||
"dependencies": [],
|
"dependencies": [],
|
||||||
"blockers": [],
|
"blockers": [],
|
||||||
"cost": 2,
|
"cost": 2,
|
||||||
"display": { "row": 28, "col": 0 },
|
"display": { "row": 28, "col": 0, "icon": "node_1"},
|
||||||
"properties": {
|
"properties": {
|
||||||
"cooldown": 2
|
"cooldown": 2
|
||||||
},
|
},
|
||||||
|
@ -552,7 +564,7 @@ const atrees = {
|
||||||
"dependencies": ["Arrow Bomb"],
|
"dependencies": ["Arrow Bomb"],
|
||||||
"blockers": [],
|
"blockers": [],
|
||||||
"cost": 2,
|
"cost": 2,
|
||||||
"display": { "row": 28, "col": 4 },
|
"display": { "row": 28, "col": 4, "icon": "node_1"},
|
||||||
"properties": {
|
"properties": {
|
||||||
"gravity": 0
|
"gravity": 0
|
||||||
},
|
},
|
||||||
|
@ -566,21 +578,22 @@ const atrees = {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"display_name": "Mana Trap",
|
"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": "Trapper",
|
||||||
"archetype_req": 5,
|
"archetype_req": 5,
|
||||||
"base_abil": "Arrow Bomb",
|
"base_abil": "Arrow Bomb",
|
||||||
"parents": ["More Traps", "Better Arrow Shield"],
|
"parents": ["More Traps", "Better Arrow Shield"],
|
||||||
"dependencies": ["Fire Creep"],
|
"dependencies": [],
|
||||||
"blockers": [],
|
"blockers": [],
|
||||||
"cost": 2,
|
"cost": 2,
|
||||||
"display": {
|
"display": {
|
||||||
"row": 28,
|
"row": 28,
|
||||||
"col": 8
|
"col": 8,
|
||||||
|
"icon": "node_3"
|
||||||
},
|
},
|
||||||
"properties": {
|
"properties": {
|
||||||
"range": 12,
|
"range": 16,
|
||||||
"manaRegen": 4
|
"manaRegen": 2.85
|
||||||
},
|
},
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
|
@ -602,7 +615,8 @@ const atrees = {
|
||||||
"cost": 2,
|
"cost": 2,
|
||||||
"display": {
|
"display": {
|
||||||
"row": 31,
|
"row": 31,
|
||||||
"col": 0
|
"col": 0,
|
||||||
|
"icon": "node_1"
|
||||||
},
|
},
|
||||||
"properties": {},
|
"properties": {},
|
||||||
"effects": [
|
"effects": [
|
||||||
|
@ -630,7 +644,7 @@ const atrees = {
|
||||||
"dependencies": ["Focus"],
|
"dependencies": ["Focus"],
|
||||||
"blockers": [],
|
"blockers": [],
|
||||||
"cost": 2,
|
"cost": 2,
|
||||||
"display": { "row": 31, "col": 5 },
|
"display": { "row": 31, "col": 5, "icon": "node_2"},
|
||||||
"properties": {},
|
"properties": {},
|
||||||
"effects": []
|
"effects": []
|
||||||
},
|
},
|
||||||
|
@ -644,7 +658,7 @@ const atrees = {
|
||||||
"dependencies": ["Arrow Shield"],
|
"dependencies": ["Arrow Shield"],
|
||||||
"blockers": [],
|
"blockers": [],
|
||||||
"cost": 2,
|
"cost": 2,
|
||||||
"display": { "row": 32, "col": 7 },
|
"display": { "row": 32, "col": 7, "icon": "node_2"},
|
||||||
"properties": {},
|
"properties": {},
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
|
@ -665,7 +679,7 @@ const atrees = {
|
||||||
"dependencies": [],
|
"dependencies": [],
|
||||||
"blockers": ["Phantom Ray"],
|
"blockers": ["Phantom Ray"],
|
||||||
"cost": 2,
|
"cost": 2,
|
||||||
"display": { "row": 33, "col": 0 },
|
"display": { "row": 33, "col": 0, "icon": "node_3"},
|
||||||
"properties": {},
|
"properties": {},
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
|
@ -684,7 +698,7 @@ const atrees = {
|
||||||
"dependencies": ["Fierce Stomp"],
|
"dependencies": ["Fierce Stomp"],
|
||||||
"blockers": [],
|
"blockers": [],
|
||||||
"cost": 2,
|
"cost": 2,
|
||||||
"display": { "row": 37, "col": 1 },
|
"display": { "row": 37, "col": 1, "icon": "node_1"},
|
||||||
"properties": {},
|
"properties": {},
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
|
@ -721,7 +735,8 @@ const atrees = {
|
||||||
"cost": 2,
|
"cost": 2,
|
||||||
"display": {
|
"display": {
|
||||||
"row": 37,
|
"row": 37,
|
||||||
"col": 4
|
"col": 4,
|
||||||
|
"icon": "node_3"
|
||||||
},
|
},
|
||||||
"properties": {},
|
"properties": {},
|
||||||
"effects": [
|
"effects": [
|
||||||
|
@ -755,7 +770,7 @@ const atrees = {
|
||||||
"dependencies": [],
|
"dependencies": [],
|
||||||
"blockers": [],
|
"blockers": [],
|
||||||
"cost": 2,
|
"cost": 2,
|
||||||
"display": { "row": 37, "col": 7 },
|
"display": { "row": 37, "col": 7, "icon": "node_2"},
|
||||||
"properties": {
|
"properties": {
|
||||||
"aoe": 2
|
"aoe": 2
|
||||||
},
|
},
|
||||||
|
@ -783,7 +798,7 @@ const atrees = {
|
||||||
"dependencies": ["Basaltic Trap"],
|
"dependencies": ["Basaltic Trap"],
|
||||||
"blockers": [],
|
"blockers": [],
|
||||||
"cost": 2,
|
"cost": 2,
|
||||||
"display": { "row": 38, "col": 6 },
|
"display": {"row": 38, "col": 6, "icon": "node_1"},
|
||||||
"properties": {
|
"properties": {
|
||||||
"attackSpeed": 0.2
|
"attackSpeed": 0.2
|
||||||
},
|
},
|
||||||
|
@ -815,7 +830,8 @@ const atrees = {
|
||||||
"cost": 2,
|
"cost": 2,
|
||||||
"display": {
|
"display": {
|
||||||
"row": 39,
|
"row": 39,
|
||||||
"col": 2
|
"col": 2,
|
||||||
|
"icon": "node_2"
|
||||||
},
|
},
|
||||||
"properties": {
|
"properties": {
|
||||||
"range": 2.5,
|
"range": 2.5,
|
||||||
|
@ -833,7 +849,7 @@ const atrees = {
|
||||||
"dependencies": ["Guardian Angels"],
|
"dependencies": ["Guardian Angels"],
|
||||||
"blockers": [],
|
"blockers": [],
|
||||||
"cost": 2,
|
"cost": 2,
|
||||||
"display": { "row": 40, "col": 1 },
|
"display": { "row": 40, "col": 1, "icon": "node_3"},
|
||||||
"properties": {
|
"properties": {
|
||||||
"range": 8,
|
"range": 8,
|
||||||
"shots": 5
|
"shots": 5
|
||||||
|
@ -863,7 +879,7 @@ const atrees = {
|
||||||
"dependencies": ["Basaltic Trap"],
|
"dependencies": ["Basaltic Trap"],
|
||||||
"blockers": [],
|
"blockers": [],
|
||||||
"cost": 2,
|
"cost": 2,
|
||||||
"display": { "row": 40, "col": 7 },
|
"display": {"row": 40, "col": 7, "icon": "node_3"},
|
||||||
"properties": {},
|
"properties": {},
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
|
@ -900,7 +916,7 @@ const atrees = {
|
||||||
"dependencies": [],
|
"dependencies": [],
|
||||||
"blockers": [],
|
"blockers": [],
|
||||||
"cost": 1,
|
"cost": 1,
|
||||||
"display": { "row": 2, "col": 4 },
|
"display": { "row": 2, "col": 4, "icon": "node_0"},
|
||||||
"properties": {},
|
"properties": {},
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
|
@ -923,7 +939,7 @@ const atrees = {
|
||||||
"dependencies": [],
|
"dependencies": [],
|
||||||
"blockers": [],
|
"blockers": [],
|
||||||
"cost": 1,
|
"cost": 1,
|
||||||
"display": { "row": 2, "col": 6 },
|
"display": {"row": 2, "col": 6, "icon": "node_0"},
|
||||||
"properties": {},
|
"properties": {},
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
|
@ -941,7 +957,7 @@ const atrees = {
|
||||||
"dependencies": [],
|
"dependencies": [],
|
||||||
"blockers": [],
|
"blockers": [],
|
||||||
"cost": 1,
|
"cost": 1,
|
||||||
"display": { "row": 21, "col": 3 },
|
"display": {"row": 21, "col": 3, "icon": "node_0"},
|
||||||
"properties": {},
|
"properties": {},
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
|
@ -1176,7 +1192,7 @@ const atrees = {
|
||||||
"type": "add_spell_prop",
|
"type": "add_spell_prop",
|
||||||
"base_spell": 4,
|
"base_spell": 4,
|
||||||
"target_part": "Total Damage",
|
"target_part": "Total Damage",
|
||||||
"hits": { "Shield Damage": 2 }
|
"hits": { "Shield Damage": 2, "Single Bow": 2 }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "raw_stat",
|
"type": "raw_stat",
|
||||||
|
@ -1288,6 +1304,7 @@ const atrees = {
|
||||||
"type": "add_spell_prop",
|
"type": "add_spell_prop",
|
||||||
"base_spell": 3,
|
"base_spell": 3,
|
||||||
"target_part": "Arrow Shield",
|
"target_part": "Arrow Shield",
|
||||||
|
"behavior": "modify",
|
||||||
"multipliers": [40, 0, 0, 0, 0, 0]
|
"multipliers": [40, 0, 0, 0, 0, 0]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1295,6 +1312,7 @@ const atrees = {
|
||||||
"bonuses": [{
|
"bonuses": [{
|
||||||
"type": "prop",
|
"type": "prop",
|
||||||
"abil": "Arrow Shield",
|
"abil": "Arrow Shield",
|
||||||
|
"behavior": "modify",
|
||||||
"name": "aoe",
|
"name": "aoe",
|
||||||
"value": 1
|
"value": 1
|
||||||
}]
|
}]
|
||||||
|
@ -1661,7 +1679,7 @@ const atrees = {
|
||||||
"display": {
|
"display": {
|
||||||
"row": 19,
|
"row": 19,
|
||||||
"col": 4,
|
"col": 4,
|
||||||
"icon": "node_2"
|
"icon": "node_3"
|
||||||
},
|
},
|
||||||
"properties": {},
|
"properties": {},
|
||||||
"effects": [{
|
"effects": [{
|
||||||
|
@ -1840,7 +1858,7 @@ const atrees = {
|
||||||
"display": {
|
"display": {
|
||||||
"row": 17,
|
"row": 17,
|
||||||
"col": 2,
|
"col": 2,
|
||||||
"icon": "node_0"
|
"icon": "node_1"
|
||||||
},
|
},
|
||||||
"properties": {},
|
"properties": {},
|
||||||
"effects": [{
|
"effects": [{
|
||||||
|
@ -2183,7 +2201,7 @@ const atrees = {
|
||||||
"type": "stat",
|
"type": "stat",
|
||||||
"name": "spd"
|
"name": "spd"
|
||||||
},
|
},
|
||||||
"scaling": [1, 1],
|
"scaling": [2, 2],
|
||||||
"max": 20
|
"max": 20
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -2456,7 +2474,7 @@ const atrees = {
|
||||||
|
|
||||||
{
|
{
|
||||||
"display_name": "Fire Mastery",
|
"display_name": "Fire Mastery",
|
||||||
"desc": "Increases base damage from all Earth attacks",
|
"desc": "Increases base damage from all Fire attacks",
|
||||||
"archetype": "Paladin",
|
"archetype": "Paladin",
|
||||||
"archetype_req": 0,
|
"archetype_req": 0,
|
||||||
"parents": ["War Scream"],
|
"parents": ["War Scream"],
|
||||||
|
@ -2577,12 +2595,7 @@ const atrees = {
|
||||||
"base_spell": 3,
|
"base_spell": 3,
|
||||||
"target_part": "Uppercut",
|
"target_part": "Uppercut",
|
||||||
"cost": -10,
|
"cost": -10,
|
||||||
"multipliers": [-70, 0, 0, 0, 0, 0]
|
"multipliers": [-70, 0, 0, 30, 0, 0]
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "convert_spell_conv",
|
|
||||||
"target_part": "all",
|
|
||||||
"conversion": "Water"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -2668,6 +2681,8 @@ const atrees = {
|
||||||
{
|
{
|
||||||
"display_name": "Iron Lungs",
|
"display_name": "Iron Lungs",
|
||||||
"desc": "War Scream deals more damage",
|
"desc": "War Scream deals more damage",
|
||||||
|
"archetype": "Paladin",
|
||||||
|
"archetype_req": 0,
|
||||||
"base_abil": "War Scream",
|
"base_abil": "War Scream",
|
||||||
"parents": ["Flyby Jab", "Flaming Uppercut"],
|
"parents": ["Flyby Jab", "Flaming Uppercut"],
|
||||||
"dependencies": [],
|
"dependencies": [],
|
||||||
|
@ -2939,13 +2954,13 @@ const atrees = {
|
||||||
"col": 6,
|
"col": 6,
|
||||||
"icon": "node_1"
|
"icon": "node_1"
|
||||||
},
|
},
|
||||||
"properties": {},
|
"properties": {"attackRate": 2},
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"type": "add_spell_prop",
|
"type": "add_spell_prop",
|
||||||
"base_spell": 4,
|
"base_spell": 4,
|
||||||
"target_part": "Air Shout",
|
"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",
|
"type": "add_spell_prop",
|
||||||
"base_spell": 2,
|
"base_spell": 2,
|
||||||
"target_part": "Flying Kick",
|
"target_part": "Flying Kick",
|
||||||
"multipliers": [120, 0, 0, 10, 0, 20]
|
"multipliers": [150, 0, 0, 20, 0, 30]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "add_spell_prop",
|
"type": "add_spell_prop",
|
||||||
|
@ -3288,7 +3303,7 @@ const atrees = {
|
||||||
"base_spell": 2,
|
"base_spell": 2,
|
||||||
"target_part": "Collide",
|
"target_part": "Collide",
|
||||||
"cost": 0,
|
"cost": 0,
|
||||||
"multipliers": [100, 0, 0, 0, 50, 0]
|
"multipliers": [150, 0, 0, 0, 50, 0]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "add_spell_prop",
|
"type": "add_spell_prop",
|
||||||
|
@ -3303,7 +3318,7 @@ const atrees = {
|
||||||
"display_name": "Rejuvenating Skin",
|
"display_name": "Rejuvenating Skin",
|
||||||
"desc": "Regain back 30% of the damage you take as healing over 30s",
|
"desc": "Regain back 30% of the damage you take as healing over 30s",
|
||||||
"archetype": "Paladin",
|
"archetype": "Paladin",
|
||||||
"archetype_req": 0,
|
"archetype_req": 5,
|
||||||
"parents": ["Burning Heart", "Stronger Bash"],
|
"parents": ["Burning Heart", "Stronger Bash"],
|
||||||
"dependencies": [],
|
"dependencies": [],
|
||||||
"blockers": [],
|
"blockers": [],
|
||||||
|
@ -3764,8 +3779,8 @@ const atrees = {
|
||||||
{ "type": "stat", "name": "fDamAddMin" }, { "type": "stat", "name": "fDamAddMax" },
|
{ "type": "stat", "name": "fDamAddMin" }, { "type": "stat", "name": "fDamAddMax" },
|
||||||
{ "type": "stat", "name": "aDamAddMin" }, { "type": "stat", "name": "aDamAddMax" }
|
{ "type": "stat", "name": "aDamAddMin" }, { "type": "stat", "name": "aDamAddMax" }
|
||||||
],
|
],
|
||||||
"scaling": [2],
|
"scaling": [3],
|
||||||
"max": 50
|
"max": 80
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -200,7 +200,7 @@ function encodeBuild(build, powders, skillpoints, atree, atree_state) {
|
||||||
}
|
}
|
||||||
build_string += tome_string;
|
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);
|
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();
|
||||||
|
|
|
@ -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);
|
//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.
|
/*Turns the input amount of levels into skillpoints available.
|
||||||
*
|
*
|
||||||
* @param level - the integer level count to be converted
|
* @param level - the integer level count to be converted
|
||||||
|
|
|
@ -51,7 +51,7 @@ let boosts_node = new (class extends ComputeNode {
|
||||||
}
|
}
|
||||||
let res = new Map();
|
let res = new Map();
|
||||||
res.set('damageMultiplier', 1+damage_boost);
|
res.set('damageMultiplier', 1+damage_boost);
|
||||||
res.set('defMultiplier', 1+def_boost);
|
res.set('defMultiplier', 1-def_boost);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
})().update();
|
})().update();
|
||||||
|
@ -181,7 +181,8 @@ class ItemInputNode extends InputNode {
|
||||||
|
|
||||||
if (item) {
|
if (item) {
|
||||||
if (powdering !== undefined) {
|
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;
|
let type_match;
|
||||||
if (this.category == 'weapon') {
|
if (this.category == 'weapon') {
|
||||||
|
@ -502,8 +503,8 @@ class SpellSelectNode extends ComputeNode {
|
||||||
*/
|
*/
|
||||||
function getDefenseStats(stats) {
|
function getDefenseStats(stats) {
|
||||||
let defenseStats = [];
|
let defenseStats = [];
|
||||||
let def_pct = skillPointsToPercentage(stats.get('def'));
|
let def_pct = skillPointsToPercentage(stats.get('def')) * skillpoint_final_mult[3];
|
||||||
let agi_pct = skillPointsToPercentage(stats.get('agi'));
|
let agi_pct = skillPointsToPercentage(stats.get('agi')) * skillpoint_final_mult[4];
|
||||||
//total hp
|
//total hp
|
||||||
let totalHp = stats.get("hp") + stats.get("hpBonus");
|
let totalHp = stats.get("hp") + stats.get("hpBonus");
|
||||||
if (totalHp < 5) totalHp = 5;
|
if (totalHp < 5) totalHp = 5;
|
||||||
|
@ -511,7 +512,10 @@ function getDefenseStats(stats) {
|
||||||
//EHP
|
//EHP
|
||||||
let ehp = [totalHp, totalHp];
|
let ehp = [totalHp, totalHp];
|
||||||
let defMult = (2 - stats.get("classDef")) * stats.get("defMultiplier");
|
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;
|
ehp[1] /= (1-def_pct)*defMult;
|
||||||
defenseStats.push(ehp);
|
defenseStats.push(ehp);
|
||||||
//HPR
|
//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'];
|
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)) {
|
for (const [subpart_name, hits] of Object.entries(part.hits)) {
|
||||||
const subpart = spell_result_map.get(subpart_name);
|
const subpart = spell_result_map.get(subpart_name);
|
||||||
|
if (!subpart) { continue; }
|
||||||
if (spell_result.type) {
|
if (spell_result.type) {
|
||||||
if (subpart.type !== spell_result.type) {
|
if (subpart.type !== spell_result.type) {
|
||||||
throw "SpellCalc total subpart type mismatch";
|
throw "SpellCalc total subpart type mismatch";
|
||||||
|
@ -769,7 +774,7 @@ class DisplayBuildWarningsNode extends ComputeNode {
|
||||||
setValue(skp_order[i] + "-skp", skillpoints[i]);
|
setValue(skp_order[i] + "-skp", skillpoints[i]);
|
||||||
let linebreak = document.createElement("br");
|
let linebreak = document.createElement("br");
|
||||||
linebreak.classList.add("itemp");
|
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 = ''
|
document.getElementById(skp_order[i]+"-warnings").textContent = ''
|
||||||
if (assigned > 100) {
|
if (assigned > 100) {
|
||||||
let skp_warning = document.createElement("p");
|
let skp_warning = document.createElement("p");
|
||||||
|
@ -1101,6 +1106,7 @@ function builder_graph_init() {
|
||||||
atree_merge.link_to(build_node, 'build');
|
atree_merge.link_to(build_node, 'build');
|
||||||
atree_graph_creator = new AbilityTreeEnsureNodesNode(build_node, stat_agg_node)
|
atree_graph_creator = new AbilityTreeEnsureNodesNode(build_node, stat_agg_node)
|
||||||
.link_to(atree_collect_spells, 'spells');
|
.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');
|
build_encode_node.link_to(atree_node, 'atree').link_to(atree_state_node, 'atree-state');
|
||||||
|
|
||||||
|
|
|
@ -44,14 +44,16 @@ function init_crafter() {
|
||||||
try {
|
try {
|
||||||
document.getElementById("recipe-choice").addEventListener("change", (event) => {
|
document.getElementById("recipe-choice").addEventListener("change", (event) => {
|
||||||
updateMaterials();
|
updateMaterials();
|
||||||
|
updateCraftedImage();
|
||||||
calculateCraftSchedule();
|
calculateCraftSchedule();
|
||||||
});
|
});
|
||||||
|
document.getElementById("recipe-choice").addEventListener("oninput", (event) => {
|
||||||
|
updateCraftedImage();
|
||||||
|
});
|
||||||
document.getElementById("level-choice").addEventListener("change", (event) => {
|
document.getElementById("level-choice").addEventListener("change", (event) => {
|
||||||
updateMaterials();
|
updateMaterials();
|
||||||
calculateCraftSchedule();
|
calculateCraftSchedule();
|
||||||
});
|
});
|
||||||
document.getElementById("recipe-choice").setAttribute("oninput", "updateCraftedImage()");
|
|
||||||
document.getElementById("recipe-choice").setAttribute("change", "updateCraftedImage()");
|
|
||||||
|
|
||||||
for (let i = 1; i < 4; ++i) {
|
for (let i = 1; i < 4; ++i) {
|
||||||
document.getElementById("mat-1-"+i).setAttribute("onclick", document.getElementById("mat-1-"+i).getAttribute("onclick") + "; calculateCraftSchedule();");
|
document.getElementById("mat-1-"+i).setAttribute("onclick", document.getElementById("mat-1-"+i).getAttribute("onclick") + "; calculateCraftSchedule();");
|
||||||
|
@ -177,7 +179,7 @@ function calculateCraft() {
|
||||||
//Display Craft Stats
|
//Display Craft Stats
|
||||||
// displayCraftStats(player_craft, "craft-stats");
|
// displayCraftStats(player_craft, "craft-stats");
|
||||||
let mock_item = player_craft.statMap;
|
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");
|
displayExpandedItem(mock_item, "craft-stats");
|
||||||
|
|
||||||
//Display Ingredients' Stats
|
//Display Ingredients' Stats
|
||||||
|
|
|
@ -66,6 +66,7 @@ function calculateSpellDamage(stats, weapon, conversions, use_spell_damage, igno
|
||||||
total_convert += conv_frac
|
total_convert += conv_frac
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
total_convert += conversions[0]/100;
|
||||||
|
|
||||||
// Also theres prop and rainbow!!
|
// Also theres prop and rainbow!!
|
||||||
const damage_elements = ['n'].concat(skp_elements); // netwfa
|
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
|
// 5.1: %boost application
|
||||||
let skill_boost = [0]; // no neutral skillpoint booster
|
let skill_boost = [0]; // no neutral skillpoint booster
|
||||||
for (const skp of skp_order) {
|
for (let i in skp_order) {
|
||||||
skill_boost.push(skillPointsToPercentage(stats.get(skp)));
|
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;
|
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 min_boost = raw_boost;
|
||||||
let max_boost = raw_boost;
|
let max_boost = raw_boost;
|
||||||
if (total_max > 0) { // TODO: what about total negative all raw?
|
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;
|
min_boost += (damages_obj[0] / total_min) * prop_raw;
|
||||||
}
|
}
|
||||||
max_boost += (damages_obj[1] / total_max) * prop_raw;
|
max_boost += (damages_obj[1] / total_max) * prop_raw;
|
||||||
|
|
|
@ -1572,7 +1572,7 @@ function getSpellCost(stats, spell) {
|
||||||
|
|
||||||
function getBaseSpellCost(stats, spell) {
|
function getBaseSpellCost(stats, spell) {
|
||||||
// old intelligence:
|
// 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);
|
cost += stats.get("spRaw"+spell.base_spell);
|
||||||
return Math.floor(cost * (1 + stats.get("spPct"+spell.base_spell) / 100));
|
return Math.floor(cost * (1 + stats.get("spPct"+spell.base_spell) / 100));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
// @See https://github.com/mdn/learning-area/blob/master/javascript/apis/client-side-storage/indexeddb/video-store/index.jsA
|
||||||
|
|
||||||
let db;
|
let db;
|
||||||
|
|
|
@ -169,14 +169,14 @@ function calc_weapon_powder(weapon, damageBases) {
|
||||||
let min_diff = Math.min(neutralRemainingRaw[0], conversionRatio * neutralBase[0]);
|
let min_diff = Math.min(neutralRemainingRaw[0], conversionRatio * neutralBase[0]);
|
||||||
let max_diff = Math.min(neutralRemainingRaw[1], conversionRatio * neutralBase[1]);
|
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][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));
|
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[0] = Math.floor(round_near(neutralRemainingRaw[0] - min_diff));
|
||||||
//neutralRemainingRaw[1] = Math.floor(round_near(neutralRemainingRaw[1] - max_diff));
|
neutralRemainingRaw[1] = Math.floor(round_near(neutralRemainingRaw[1] - max_diff));
|
||||||
damages[element+1][0] += min_diff;
|
//damages[element+1][0] += min_diff;
|
||||||
damages[element+1][1] += max_diff;
|
//damages[element+1][1] += max_diff;
|
||||||
neutralRemainingRaw[0] -= min_diff;
|
//neutralRemainingRaw[0] -= min_diff;
|
||||||
neutralRemainingRaw[1] -= max_diff;
|
//neutralRemainingRaw[1] -= max_diff;
|
||||||
}
|
}
|
||||||
damages[element+1][0] += powder.min;
|
damages[element+1][0] += powder.min;
|
||||||
damages[element+1][1] += powder.max;
|
damages[element+1][1] += powder.max;
|
||||||
|
|
|
@ -43,6 +43,7 @@
|
||||||
<a href = "../wynnfo/"><img src = "../media/icons/new/book.png" alt = "Wynnfo" title = "Wynnfo"><b>Wynnfo</b></a>
|
<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>
|
<a onclick = "toggleIcons()"><img src = "../media/icons/new/reload.png" alt = "" title = "Swap items on page"><b>Swap Icon Style</b></a>
|
||||||
<hr/>
|
<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>
|
||||||
|
|
||||||
<div class = "container row py-5 vh-100 mx-0 mx-lg-auto scaled-font">
|
<div class = "container row py-5 vh-100 mx-0 mx-lg-auto scaled-font">
|
||||||
|
|
BIN
media/icons/discord.png
Normal file
BIN
media/icons/discord.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.9 KiB |
349
normalize.css
vendored
349
normalize.css
vendored
|
@ -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;
|
|
||||||
}
|
|
|
@ -13,52 +13,54 @@ with open("atree_ids.json") as f:
|
||||||
with open("atree_constants.json") as f:
|
with open("atree_constants.json") as f:
|
||||||
atree_data = json.loads(f.read())
|
atree_data = json.loads(f.read())
|
||||||
|
|
||||||
for _class, info in atree_data.items():
|
def translate_id(id_data, atree_data):
|
||||||
def translate(path, ref):
|
for _class, info in atree_data.items():
|
||||||
ref_dict = info
|
def translate(path, ref):
|
||||||
for x in path:
|
ref_dict = info
|
||||||
ref_dict = ref_dict[x]
|
for x in path:
|
||||||
ref_dict[ref] = id_data[_class][ref_dict[ref]]
|
ref_dict = ref_dict[x]
|
||||||
|
ref_dict[ref] = id_data[_class][ref_dict[ref]]
|
||||||
|
|
||||||
for abil in range(len(info)):
|
for abil in range(len(info)):
|
||||||
info[abil]["id"] = id_data[_class][info[abil]["display_name"]]
|
info[abil]["id"] = id_data[_class][info[abil]["display_name"]]
|
||||||
for ref in range(len(info[abil]["parents"])):
|
for ref in range(len(info[abil]["parents"])):
|
||||||
translate([abil, "parents"], ref)
|
translate([abil, "parents"], ref)
|
||||||
|
|
||||||
for ref in range(len(info[abil]["dependencies"])):
|
for ref in range(len(info[abil]["dependencies"])):
|
||||||
translate([abil, "dependencies"], ref)
|
translate([abil, "dependencies"], ref)
|
||||||
|
|
||||||
for ref in range(len(info[abil]["blockers"])):
|
for ref in range(len(info[abil]["blockers"])):
|
||||||
translate([abil, "blockers"], ref)
|
translate([abil, "blockers"], ref)
|
||||||
|
|
||||||
if "base_abil" in info[abil]:
|
if "base_abil" in info[abil]:
|
||||||
base_abil_name = info[abil]["base_abil"]
|
base_abil_name = info[abil]["base_abil"]
|
||||||
if base_abil_name in id_data[_class]:
|
if base_abil_name in id_data[_class]:
|
||||||
translate([abil], "base_abil")
|
translate([abil], "base_abil")
|
||||||
|
|
||||||
if "effects" not in info[abil]:
|
if "effects" not in info[abil]:
|
||||||
print("WARNING: abil missing 'effects' tag")
|
print("WARNING: abil missing 'effects' tag")
|
||||||
print(info[abil])
|
print(info[abil])
|
||||||
info[abil]["effects"] = []
|
info[abil]["effects"] = []
|
||||||
for effect in info[abil]["effects"]:
|
for effect in info[abil]["effects"]:
|
||||||
if effect["type"] == "raw_stat":
|
if effect["type"] == "raw_stat":
|
||||||
for bonus in effect["bonuses"]:
|
for bonus in effect["bonuses"]:
|
||||||
if "abil" in bonus and bonus["abil"] in id_data[_class]:
|
if "abil" in bonus and bonus["abil"] in id_data[_class]:
|
||||||
bonus["abil"] = id_data[_class][bonus["abil"]]
|
bonus["abil"] = id_data[_class][bonus["abil"]]
|
||||||
|
|
||||||
elif effect["type"] == "stat_scaling":
|
elif effect["type"] == "stat_scaling":
|
||||||
if "inputs" in effect: # Might not exist for sliders
|
if "inputs" in effect: # Might not exist for sliders
|
||||||
for _input in effect["inputs"]:
|
for _input in effect["inputs"]:
|
||||||
if "abil" in _input and _input["abil"] in id_data[_class]:
|
if "abil" in _input and _input["abil"] in id_data[_class]:
|
||||||
_input["abil"] = id_data[_class][_input["abil"]]
|
_input["abil"] = id_data[_class][_input["abil"]]
|
||||||
if isinstance(effect["output"], list):
|
if isinstance(effect["output"], list):
|
||||||
for output in effect["output"]:
|
for output in effect["output"]:
|
||||||
if "abil" in output and output["abil"] in id_data[_class]:
|
if "abil" in output and output["abil"] in id_data[_class]:
|
||||||
output["abil"] = id_data[_class][output["abil"]]
|
output["abil"] = id_data[_class][output["abil"]]
|
||||||
else:
|
else:
|
||||||
if "abil" in effect["output"] and effect["output"]["abil"] in id_data[_class]:
|
if "abil" in effect["output"] and effect["output"]["abil"] in id_data[_class]:
|
||||||
effect["output"]["abil"] = id_data[_class][effect["output"]["abil"]]
|
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:
|
with open('atree_constants_idfied.json', 'w', encoding='utf-8') as abil_dest:
|
||||||
json.dump(atree_data, abil_dest, ensure_ascii=False, indent=4)
|
json.dump(atree_data, abil_dest, ensure_ascii=False, indent=4)
|
||||||
|
|
|
@ -6,6 +6,53 @@ given [atree_constants.js] .js form of the Ability Tree with reference as string
|
||||||
"""
|
"""
|
||||||
import json
|
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 = {}
|
abilDict = {}
|
||||||
with open("atree_constants.js") as f:
|
with open("atree_constants.js") as f:
|
||||||
data = f.read()
|
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:
|
with open("atree_ids.json", "w", encoding='utf-8') as id_dest:
|
||||||
json.dump(abilDict, id_dest, ensure_ascii=False, indent=4)
|
json.dump(abilDict, id_dest, ensure_ascii=False, indent=4)
|
||||||
|
|
||||||
for classType, info in data.items():
|
translate_id(abilDict, data)
|
||||||
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]]
|
|
||||||
|
|
||||||
data_str = json.dumps(data, ensure_ascii=False, separators=(',', ':'))
|
data_str = json.dumps(data, ensure_ascii=False, separators=(',', ':'))
|
||||||
data_str = "const atrees=" + data_str
|
data_str = "const atrees=" + data_str
|
||||||
|
|
100
py_script/items_common.py
Normal file
100
py_script/items_common.py
Normal 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
23
py_script/merge.json
Normal 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
124
py_script/merge_items.py
Normal 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)
|
||||||
|
|
|
@ -15,6 +15,7 @@ import sys
|
||||||
import os
|
import os
|
||||||
import base64
|
import base64
|
||||||
import argparse
|
import argparse
|
||||||
|
from items_common import translate_mappings, delete_keys
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(description="Process raw pulled item data.")
|
parser = argparse.ArgumentParser(description="Process raw pulled item data.")
|
||||||
parser.add_argument('infile', help='input file to read data from')
|
parser.add_argument('infile', help='input file to read data from')
|
||||||
|
@ -30,108 +31,6 @@ items = data["items"]
|
||||||
if "request" in data:
|
if "request" in data:
|
||||||
del data["request"]
|
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:
|
with open("../clean.json", "r") as oldfile:
|
||||||
old_data = json.load(oldfile)
|
old_data = json.load(oldfile)
|
||||||
old_items = old_data['items']
|
old_items = old_data['items']
|
||||||
|
@ -188,6 +87,8 @@ items.extend(remap_items)
|
||||||
#write items back into data
|
#write items back into data
|
||||||
data["items"] = items
|
data["items"] = items
|
||||||
|
|
||||||
|
data["sets"] = old_data["sets"]
|
||||||
|
|
||||||
#save id map
|
#save id map
|
||||||
with open("id_map.json","w") as id_mapfile:
|
with open("id_map.json","w") as id_mapfile:
|
||||||
json.dump(id_map, id_mapfile, indent=2)
|
json.dump(id_map, id_mapfile, indent=2)
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
<a href = ""><img src = "../media/icons/new/book.png" alt = "Wynnfo" title = "Wynnfo"><b>Wynnfo</b></a>
|
<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>
|
<a onclick = "toggleIcons()"><img src = "../media/icons/new/reload.png" alt = "" title = "Swap items on page"><b>Swap Icon Style</b></a>
|
||||||
<hr/>
|
<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>
|
||||||
<div class = "container py-5 vh-100 mx-0 mx-lg-auto scaled-font" id = "main">
|
<div class = "container py-5 vh-100 mx-0 mx-lg-auto scaled-font" id = "main">
|
||||||
<div class = "row item-title">Welcome!</div>
|
<div class = "row item-title">Welcome!</div>
|
||||||
|
|
Loading…
Reference in a new issue