Shaman atree + schema augmentation (#196)

* Beginnings of shaman atree

* Fix aura parents

* Day's work (ft. frozenearth and endistic)

* More incremental work -- finish another two pages i think, or one

* One more page to go on shaman atree

* Fix missing archetype on overseer and fix regeneration to be not 100% heal per tick

* Just missing 4 abils at the bottom hopefully

* Fix typos in display

* Fix archetype req for chant of the fanatic

* Shaman atree complete

except fluid healing doesn't work yet

* Add comments, fix some misc. formatting related stuffs

* Misc. patch

Fix rebound interaction
Fix translations for newly added target parts
Fix tree misc. connection/archetype missing bugs

Co-authored-by: hppeng <hppeng>
This commit is contained in:
hppeng-wynn 2022-08-11 03:13:53 -07:00 committed by GitHub
parent 755def77f3
commit fb1077de7e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 2671 additions and 533 deletions

View file

@ -36,20 +36,71 @@
<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> <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 id="mobile-navbar" class="navbar dark-5 dark-shadow fixed-top d-lg-none pb-0" style="display: none">
<div class="container-fluid scaled-font justify-content-center" style="height: 5vh;">
<div class="navbar-brand mx-auto scaled-font" style="height: 100%;">
<img src="../media/icons/new/builder.png" alt="" style="height: 100%;">
<span>WynnBuilder</span>
</div>
<button class="btn dropdown-toggle dark-2 px-4 text-white scaled-font border-dark border-3" onclick="toggle_tab('mobile-navbar-dropdown');"></button>
</div>
<div class="container-fluid scaled-font dark-3 px-3 py-3" id="mobile-navbar-dropdown" style="display: none;">
<a href="../builder/" class="w-100 mb-3 text-white" style="height: 5vh; text-decoration: none;">
<img src="../media/icons/new/builder.png" alt="" style="height: 100%;">
<span>WynnBuilder</span>
</a>
<a href="../crafter/" class="w-100 mb-3 text-white" style="height: 5vh; text-decoration: none;">
<img src="../media/icons/new/crafter.png" alt="" style="height: 100%;">
<span>WynnCrafter</span>
</a>
<a href="../items/" class="w-100 mb-3 text-white" style="height: 5vh; text-decoration: none;">
<img src="../media/icons/new/searcher.png" alt="" style="height: 100%;">
<span>WynnAtlas</span>
</a>
<a href="../custom/" class="w-100 mb-3 text-white" style="height: 5vh; text-decoration: none;">
<img src="../media/icons/new/custom.png" alt="" style="height: 100%;">
<span>WynnCustom</span>
</a>
<a href="../map/" class="w-100 mb-3 text-white" style="height: 5vh; text-decoration: none;">
<img src="../media/icons/new/compass.png" alt="" style="height: 100%;">
<span>WynnGPS</span>
</a>
<a href="../wynnfo/" class="w-100 mb-3 text-white" style="height: 5vh; text-decoration: none;">
<img src="../media/icons/new/book.png" alt="" style="height: 100%;">
<span>WynnFo</span>
</a>
<a onclick = "toggleIcons()" class="w-100 mb-3 text-white" style="height: 5vh; text-decoration: none;">
<img src="../media/icons/new/reload.png" alt="" style="height: 100%;">
<span>Swap Icon Style</span>
</a>
<a href="https://discord.gg/CGavnAnerv" class="w-100 mb-3 text-white" style="height: 5vh; text-decoration: none;">
<img src="../media/icons/discord.png" alt="" style="height: 100%;">
<span>Discord</span>
</a>
</div>
</div>
<div class="container-fluid overall-box mt-lg-2" style="margin-top: 6vh; display: none">
<!-- REMOVE THIS DIV AT SOME POINT. --> <!-- REMOVE THIS DIV AT SOME POINT. -->
<div class = "row scaled-font mx-auto" id = "discord-banner-dev"> <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 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>
<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 gx-0">
<div class="col-xl-6"> <div class="col-xl-6">
<div class="row row-cols-1 mb-3 gy-4"> <div class="row my-2 dark-6 rounded text-center g-0 px-3 d-flex d-lg-none">
<div class="col"> <div class="col">
<div class="row row-cols-1 row-cols-xl-2 rounded gy-4 gx-5 justify-content-center"> <p class="fake-button scaled-font mb-0 selected-btn" id="equipment-inputs-btn" onclick="show_tab('equipment-inputs', ['equipment-inputs', 'adjust-id'])">Equipments</p>
<div class="col-auto rounded order-xl-0 order-0"> </div>
<div class="row h-100 dark-shadow dark-6 rounded" id="helmet-dropdown"> <div class="col">
<p class="fake-button scaled-font mb-0" id="adjust-id-btn" onclick="show_tab('adjust-id', ['equipment-inputs', 'adjust-id'])">Ability Tree</p>
</div>
</div>
<div class="row row-cols-1 mb-3 gy-4" id="equipment-inputs">
<div class="col">
<div class="row row-cols-1 row-cols-xl-2 dark-shadow dark-6 justify-content-center equipment-input rounded gy-3 gy-lg-0 mt-auto">
<div class="col-auto rounded order-xl-0 order-0 my-0">
<div class="row h-100 px-1" id="helmet-dropdown">
<div class="col-auto px-lg-1 g-0 dark-7 rounded-end my-auto text-center scaled-item-icon" id="helmet-img-loc"> <div class="col-auto px-lg-1 g-0 dark-7 rounded-end my-auto text-center scaled-item-icon" id="helmet-img-loc">
<img id="helmet-img" class="img-fluid rounded" src="../media/items/new/generic-helmet.png"> <div id="helmet-img" class="img-fluid rounded item-display-new-toggleable" style="background-image: url('../media/items/new.png'); background-position: 45.45454545454546% 0;"></div>
</div> </div>
<div class="col-3"> <div class="col-3">
<div class="row row-cols-1 h-100 align-items-center"> <div class="row row-cols-1 h-100 align-items-center">
@ -73,10 +124,10 @@
</div> </div>
</div> </div>
</div> </div>
<div class="col-auto order-xl-0 order-1"> <div class="col-auto order-xl-0 order-1 my-0">
<div class="row h-100 dark-shadow dark-6 rounded" id="ring1-dropdown"> <div class="row h-100 px-1" id="ring1-dropdown">
<div class="col-auto px-lg-1 g-0 dark-7 rounded-end my-auto text-center scaled-item-icon" id="ring1-img-loc"> <div class="col-auto px-lg-1 g-0 dark-7 rounded-end my-auto text-center scaled-item-icon" id="ring1-img-loc">
<img id="ring1-img" class="img-fluid rounded" src="../media/items/new/generic-ring.png"> <div id="ring1-img" class="img-fluid rounded item-display-new-toggleable" style="background-image: url('../media/items/new.png'); background-position: 81.81818181818181% 0;"></div>
</div> </div>
<div class="col-3"> <div class="col-3">
<div class="row row-cols-1 h-100 align-items-center"> <div class="row row-cols-1 h-100 align-items-center">
@ -94,16 +145,15 @@
<input class="equipment-input text-light form-control" id="ring1-choice" name="ring1-choice" placeholder="No ring" value="" tabindex="2"/> <input class="equipment-input text-light form-control" id="ring1-choice" name="ring1-choice" placeholder="No ring" value="" tabindex="2"/>
</div> </div>
<div class="col d-flex justify-content-end" style="height: 100%;"> <div class="col d-flex justify-content-end" style="height: 100%;">
<!-- <input class="equipment-input text-light form-control" type="text" id="ring1-powder" name="ring1-powder" placeholder="no powders" tabindex="2"/> -->
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="col-auto order-xl-0 order-0"> <div class="col-auto order-xl-0 order-0">
<div class="row h-100 dark-shadow dark-6 rounded" id="chestplate-dropdown"> <div class="row h-100 px-1" id="chestplate-dropdown">
<div class="col-auto px-lg-1 g-0 dark-7 rounded-end my-auto text-center scaled-item-icon" id="chestplate-img-loc"> <div class="col-auto px-lg-1 g-0 dark-7 rounded-end my-auto text-center scaled-item-icon" id="chestplate-img-loc">
<img id="chestplate-img" class="img-fluid rounded" src="../media/items/new/generic-chestplate.png"> <div id="chestplate-img" class="img-fluid rounded item-display-new-toggleable" style="background-image: url('../media/items/new.png'); background-position: 54.54545454545454% 0;"></div>
</div> </div>
<div class="col-3"> <div class="col-3">
<div class="row row-cols-1 h-100 align-items-center"> <div class="row row-cols-1 h-100 align-items-center">
@ -128,9 +178,9 @@
</div> </div>
</div> </div>
<div class="col-auto order-xl-0 order-1"> <div class="col-auto order-xl-0 order-1">
<div class="row h-100 dark-shadow dark-6 rounded" id="ring2-dropdown"> <div class="row h-100 px-1" id="ring2-dropdown">
<div class="col-auto px-lg-1 g-0 dark-7 rounded-end my-auto text-center scaled-item-icon" id="ring2-img-loc"> <div class="col-auto px-lg-1 g-0 dark-7 rounded-end my-auto text-center scaled-item-icon" id="ring2-img-loc">
<img id="ring2-img" class="img-fluid rounded" src="../media/items/new/generic-ring.png"> <div id="ring2-img" class="img-fluid rounded item-display-new-toggleable" style="background-image: url('../media/items/new.png'); background-position: 81.81818181818181% 0;"></div>
</div> </div>
<div class="col-3"> <div class="col-3">
<div class="row row-cols-1 h-100 align-items-center"> <div class="row row-cols-1 h-100 align-items-center">
@ -154,9 +204,9 @@
</div> </div>
</div> </div>
<div class="col-auto order-xl-0 order-0"> <div class="col-auto order-xl-0 order-0">
<div class="row h-100 dark-shadow dark-6 rounded" id="leggings-dropdown"> <div class="row h-100 px-1" id="leggings-dropdown">
<div class="col-auto px-lg-1 g-0 dark-7 rounded-end my-auto text-center scaled-item-icon" id="leggings-img-loc"> <div class="col-auto px-lg-1 g-0 dark-7 rounded-end my-auto text-center scaled-item-icon" id="leggings-img-loc">
<img id="leggings-img" class="img-fluid rounded" src="../media/items/new/generic-leggings.png"> <div id="leggings-img" class="img-fluid rounded item-display-new-toggleable" style="background-image: url('../media/items/new.png'); background-position: 63.63636363636363% 0;"></div>
</div> </div>
<div class="col-3"> <div class="col-3">
<div class="row row-cols-1 h-100 align-items-center"> <div class="row row-cols-1 h-100 align-items-center">
@ -181,9 +231,9 @@
</div> </div>
</div> </div>
<div class="col-auto order-xl-0 order-1"> <div class="col-auto order-xl-0 order-1">
<div class="row h-100 dark-shadow dark-6 rounded" id="bracelet-dropdown"> <div class="row h-100 px-1" id="bracelet-dropdown">
<div class="col-auto px-lg-1 g-0 dark-7 rounded-end my-auto text-center scaled-item-icon" id="bracelet-img-loc"> <div class="col-auto px-lg-1 g-0 dark-7 rounded-end my-auto text-center scaled-item-icon" id="bracelet-img-loc">
<img id="bracelet-img" class="img-fluid rounded" src="../media/items/new/generic-bracelet.png"> <div id="bracelet-img" class="img-fluid rounded item-display-new-toggleable" style="background-image: url('../media/items/new.png'); background-position: 90.90909090909092% 0;"></div>
</div> </div>
<div class="col-3"> <div class="col-3">
<div class="row row-cols-1 h-100 align-items-center"> <div class="row row-cols-1 h-100 align-items-center">
@ -208,9 +258,9 @@
</div> </div>
</div> </div>
<div class="col-auto order-xl-0 order-0"> <div class="col-auto order-xl-0 order-0">
<div class="row h-100 dark-shadow dark-6 rounded" id="boots-dropdown"> <div class="row h-100 px-1" id="boots-dropdown">
<div class="col-auto px-lg-1 g-0 dark-7 rounded-end my-auto text-center scaled-item-icon" id="boots-img-loc"> <div class="col-auto px-lg-1 g-0 dark-7 rounded-end my-auto text-center scaled-item-icon" id="boots-img-loc">
<img id="boots-img" class="img-fluid rounded" src="../media/items/new/generic-boots.png"> <div id="boots-img" class="img-fluid rounded item-display-new-toggleable" style="background-image: url('../media/items/new.png'); background-position: 72.72727272727272% 0;"></div>
</div> </div>
<div class="col-3"> <div class="col-3">
<div class="row row-cols-1 h-100 align-items-center"> <div class="row row-cols-1 h-100 align-items-center">
@ -235,9 +285,9 @@
</div> </div>
</div> </div>
<div class="col-auto order-xl-0 order-1"> <div class="col-auto order-xl-0 order-1">
<div class="row h-100 dark-shadow dark-6 rounded" id="necklace-dropdown"> <div class="row h-100 px-1" id="necklace-dropdown">
<div class="col-auto px-lg-1 g-0 dark-7 rounded-end my-auto text-center scaled-item-icon" id="necklace-img-loc"> <div class="col-auto px-lg-1 g-0 dark-7 rounded-end my-auto text-center scaled-item-icon" id="necklace-img-loc">
<img id="necklace-img" class="img-fluid rounded" src="../media/items/new/generic-necklace.png"> <div id="necklace-img" class="img-fluid rounded item-display-new-toggleable" style="background-image: url('../media/items/new.png'); background-position: 100% 0;"></div>
</div> </div>
<div class="col-3"> <div class="col-3">
<div class="row row-cols-1 h-100 align-items-center"> <div class="row row-cols-1 h-100 align-items-center">
@ -261,9 +311,9 @@
</div> </div>
</div> </div>
<div class="col-auto order-xl-0 order-1"> <div class="col-auto order-xl-0 order-1">
<div class="row h-100 dark-shadow dark-6 rounded" id='weapon-dropdown'> <div class="row h-auto px-1" id='weapon-dropdown'>
<div class="col-auto px-lg-1 g-0 dark-7 rounded-end my-auto text-center scaled-item-icon" id="weapon-img-loc"> <div class="col-auto px-lg-1 g-0 dark-7 rounded-end my-auto text-center scaled-item-icon" id="weapon-img-loc">
<img id="weapon-img" class="img-fluid rounded" src="../media/items/new/generic-dagger.png"> <div id="weapon-img" class="img-fluid rounded item-display-new-toggleable" style = "background-image: url('../media/items/new.png');"></div>
</div> </div>
<div class="col-3"> <div class="col-3">
<div class="row row-cols-1 h-100 align-items-center"> <div class="row row-cols-1 h-100 align-items-center">
@ -287,29 +337,25 @@
</div> </div>
</div> </div>
</div> </div>
<div class="col-auto order-xl-0 order-1"> <div class="col-auto order-xl-0 order-1 level-input">
<div class="row h-100 dark-shadow dark-6 rounded"> <div class="row h-100 px-1">
<div class="col"> <div class="col">
<div class="row align-items-center"> <div class="row align-items-center justify-content-left">
<div class="col-3 text-nowrap fw-bold scaled-font"> <div class="col-auto text-nowrap fw-bold scaled-font">
Level: Level:
</div> </div>
<div class="col d-flex justify-content-end"> <div class="col d-flex px-1">
<input class="equipment-input text-light form-control form-control-sm" id="level-choice" name="level-choice" value="106" placeholder="Build level" value="" tabindex="2"/> <input class="equipment-input text-light form-control form-control-sm" id="level-choice" name="level-choice" value="106" placeholder="Build level" value="" tabindex="2"/>
</div> </div>
<div class="col-auto px-1 text-nowrap scaled-font"> <div class="col-auto px-1 scaled-font">
<button class="button fw-bold text-light dark-5 scaled-font rounded" id="reset-button" onclick="resetFields()">Reset</button> <button class="button py-0 fw-bold text-light dark-5 scaled-font rounded" id="reset-button" onclick="resetFields()">Reset</button>
</div> </div>
</div> </div>
<div class="row align-items-center justify-content-center my-1"> <div class="row align-items-left justify-content-left my-1">
<div class="row align-items-center"> <button class="col-auto mx-1 px-1 py-0 border-info text-light dark-5 scaled-font rounded fake-button"
<div class="col-auto px-1 text-nowrap scaled-font"> id=copy-button onclick="copyBuild()">Copy short</button>
<button class="border-dark text-light dark-5 scaled-font rounded" id=copy-button onclick="copyBuild()">Copy short</button> <button class="col-auto mx-1 px-1 py-0 border-info text-light dark-5 scaled-font rounded fake-button"
</div> id=share-button onclick="shareBuild(player_build)">Copy for sharing</button>
<div class="col-auto px-1 text-nowrap scaled-font">
<button class="border-dark text-light dark-5 scaled-font rounded" id=share-button onclick="shareBuild(player_build)">Copy for sharing</button>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -390,12 +436,9 @@
</div> </div>
</div> </div>
</div> </div>
<div class="col-12 text-center gx-2">
<button class = "button fw-bold text-light dark-5 rounded scaled-font" id = "optimize-strdex" onclick = "optimizeStrDex()">Optimize Str/Dex</button>
</div>
</div> </div>
</div> </div>
<div class="col text-center"> <div class="col text-center py-1">
<div id="summary-box"></div> <div id="summary-box"></div>
<div id="err-box"></div> <div id="err-box"></div>
<div id="stack-box"></div> <div id="stack-box"></div>
@ -407,188 +450,187 @@
</div> </div>
</div> </div>
</div> </div>
<div class="col mb-1 text-center scaled-font dark-5 rounded dark-shadow">
<div class="row row-cols-1 justify-content-center">
<div class="col fw-bold dark-4 rounded-top">
Active boosts
</div>
<div class="col">
<button class="button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id="warscream-boost" onclick="update_boosts('warscream-boost')">
War Scream
</button>
<button class="button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id="ragnarokkr-boost" onclick="update_boosts('ragnarokkr-boost')">
Ragnarokkr (+30%)
</button>
<button class="button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id="yourtotem-boost" onclick="update_boosts('yourtotem-boost')">
Your Totem (+35%)
</button>
<button class="button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id="allytotem-boost" onclick="update_boosts('allytotem-boost')">
Ally Totem (+15%)
</button>
<button class="button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id="fortitude-boost" onclick="update_boosts('fortitude-boost')">
Fortitude (+60%)
</button>
</div>
<div class="col" id="boost-toggles">
</div>
</div>
<div class="row row-cols-1 justify-content-center" id="boost-sliders">
</div>
</div>
<div class="col mb-1">
<div class="row row-cols-1 rounded text-center dark-5 scaled-font">
<div class="row p-0 m-0 text-nowrap">
<div id = "str-boost-btn" class="col eDam dark-4u fake-button elem-boost" onclick="show_tab('str-boost', ['str-boost', 'dex-boost', 'int-boost', 'def-boost', 'agi-boost'])">
Earth
</div>
<div id = "dex-boost-btn" class="col tDam dark-4u fake-button elem-boost" onclick="show_tab('dex-boost', ['str-boost', 'dex-boost', 'int-boost', 'def-boost', 'agi-boost'])">
Thunder
</div>
<div id = "int-boost-btn" class="col wDam dark-4u fake-button elem-boost" onclick="show_tab('int-boost', ['str-boost', 'dex-boost', 'int-boost', 'def-boost', 'agi-boost'])">
Water
</div>
<div id = "def-boost-btn" class="col fDam dark-4u fake-button elem-boost" onclick="show_tab('def-boost', ['str-boost', 'dex-boost', 'int-boost', 'def-boost', 'agi-boost'])">
Fire
</div>
<div id = "agi-boost-btn" class="col aDam dark-4u fake-button elem-boost" onclick="show_tab('agi-boost', ['str-boost', 'dex-boost', 'int-boost', 'def-boost', 'agi-boost'])">
Air
</div>
</div>
<div class="row row-cols-1 p-0 m-0" id="str-boost" style="display: none;">
<div class="col eDam dark-5">
Quake (Active)
</div>
<div class="col skp-tooltip dark-6 rounded-bottom my-3 my-xl-1" >
<button class = "button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id = "Quake-1" onclick = "updatePowderSpecials('Quake-1')">
Lv.4 [e4e4]
</button>
<button class = "button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id = "Quake-2" onclick = "updatePowderSpecials('Quake-2')">
Lv.4.5 [e5e4]
</button>
<button class = "button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id = "Quake-3" onclick = "updatePowderSpecials('Quake-3')">
Lv.5 [e5e5]
</button>
<button class = "button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id = "Quake-4" onclick = "updatePowderSpecials('Quake-4')">
Lv.5.5 [e6e5]
</button>
<button class = "button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id = "Quake-5" onclick = "updatePowderSpecials('Quake-5')">
Lv.6 [e6e6]
</button>
</div>
<div class="col eDam">
Rage (Passive)
</div>
</div>
<div class="row row-cols-1 p-0 m-0" id="dex-boost" style="display: none;">
<div class="col tDam dark-5">
Chain Lightning (Active)
</div>
<div class="col skp-tooltip dark-6 rounded-bottom my-3 my-xl-1">
<button class = "button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id = "Chain_Lightning-1" onclick = "updatePowderSpecials('Chain_Lightning-1')">
Lv.4 [t4t4]
</button>
<button class = "button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id = "Chain_Lightning-2" onclick = "updatePowderSpecials('Chain_Lightning-2')">
Lv.4.5 [t5t4]
</button>
<button class = "button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id = "Chain_Lightning-3" onclick = "updatePowderSpecials('Chain_Lightning-3')">
Lv.5 [t5t5]
</button>
<button class = "button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id = "Chain_Lightning-4" onclick = "updatePowderSpecials('Chain_Lightning-4')">
Lv.5.5 [t6t5]
</button>
<button class = "button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id = "Chain_Lightning-5" onclick = "updatePowderSpecials('Chain_Lightning-5')">
Lv.6 [t6t6]
</button>
</div>
<div class="col tDam">
Kill Streak (Passive)
</div>
</div>
<div class="row row-cols-1 p-0 m-0" id="int-boost">
<div class="col wDam dark-5">
Curse (Active)
</div>
<div class="col skp-tooltip dark-6 rounded-bottom my-3 my-xl-1">
<button class = "button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id = "Curse-1" onclick = "updatePowderSpecials('Curse-1')">
Lv.4 [w4w4]
</button>
<button class = "button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id = "Curse-2" onclick = "updatePowderSpecials('Curse-2')">
Lv.4.5 [w5w4]
</button>
<button class = "button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id = "Curse-3" onclick = "updatePowderSpecials('Curse-3')">
Lv.5 [w5w5]
</button>
<button class = "button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id = "Curse-4" onclick = "updatePowderSpecials('Curse-4')">
Lv.5.5 [w6w5]
</button>
<button class = "button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id = "Curse-5" onclick = "updatePowderSpecials('Curse-5')">
Lv.6 [w6w6]
</button>
</div>
<div class="col wDam">
Concentration (Passive)
</div>
</div>
<div class="row row-cols-1 p-0 m-0" id="def-boost" style="display: none;">
<div class="col fDam dark-5">
Courage (Active)
</div>
<div class="col skp-tooltip dark-6 rounded-bottom my-3 my-xl-1">
<button class = "button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id = "Courage-1" onclick = "updatePowderSpecials('Courage-1')">
Lv.4 [f4f4]
</button>
<button class = "button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id = "Courage-2" onclick = "updatePowderSpecials('Courage-2')">
Lv.4.5 [f5f4]
</button>
<button class = "button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id = "Courage-3" onclick = "updatePowderSpecials('Courage-3')">
Lv.5 [f5f5]
</button>
<button class = "button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id = "Courage-4" onclick = "updatePowderSpecials('Courage-4')">
Lv.5.5 [f6f5]
</button>
<button class = "button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id = "Courage-5" onclick = "updatePowderSpecials('Courage-5')">
Lv.6 [f6f6]
</button>
</div>
<div class="col fDam">
Endurance (Passive)
</div>
</div>
<div class="row row-cols-1 p-0 m-0" id="agi-boost" style="display: none;">
<div class="col aDam dark-5">
Wind Prison (Active)
</div>
<div class="col skp-tooltip dark-6 rounded-bottom my-3 my-xl-1">
<button class = "button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id = "Wind_Prison-1" onclick = "updatePowderSpecials('Wind_Prison-1')">
Lv.4 [a4a4]
</button>
<button class = "button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id = "Wind_Prison-2" onclick = "updatePowderSpecials('Wind_Prison-2')">
Lv.4.5 [a5a4]
</button>
<button class = "button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id = "Wind_Prison-3" onclick = "updatePowderSpecials('Wind_Prison-3')">
Lv.5 [a5a5]
</button>
<button class = "button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id = "Wind_Prison-4" onclick = "updatePowderSpecials('Wind_Prison-4')">
Lv.5.5 [a6a5]
</button>
<button class = "button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id = "Wind_Prison-5" onclick = "updatePowderSpecials('Wind_Prison-5')">
Lv.6 [a6a6]
</button>
</div>
<div class="col aDam">
Dodge (Passive)
</div>
</div>
</div>
</div>
</div>
<div class="row row-cols-1 d-lg-flex" id="adjust-id" style="display: none;">
<div class="col"> <div class="col">
<div class="row row-cols-1 gy-4"> <div class="row row-cols-1 gy-3">
<div class="col mb-1 text-center scaled-font dark-5 rounded dark-shadow">
<div class="row row-cols-1 justify-content-center">
<div class="col fw-bold dark-4 rounded-top">
Active boosts
</div>
<div class="col">
<button class="button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id="vanish-boost" onclick="update_boosts('vanish-boost')">
Vanish (+80%)
</button>
<button class="button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id="warscream-boost" onclick="update_boosts('warscream-boost')">
War Scream
</button>
<button class="button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id="ragnarokkr-boost" onclick="update_boosts('ragnarokkr-boost')">
Ragnarokkr (+30%)
</button>
<button class="button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id="yourtotem-boost" onclick="update_boosts('yourtotem-boost')">
Your Totem (+35%)
</button>
<button class="button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id="allytotem-boost" onclick="update_boosts('allytotem-boost')">
Ally Totem (+15%)
</button>
<button class="button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id="fortitude-boost" onclick="update_boosts('fortitude-boost')">
Fortitude (+60%)
</button>
</div>
<div class="col" id="boost-toggles">
</div>
</div>
<div class="row row-cols-1 justify-content-center" id="boost-sliders">
</div>
</div>
<div class="col mb-1">
<div class="row row-cols-1 rounded text-center dark-5 scaled-font">
<div class="row p-0 m-0 text-nowrap">
<div id = "str-boost-tab" class="col eDam dark-4u fake-button elem-boost" onclick="toggle_boost_tab('str')">
Earth
</div>
<div id = "dex-boost-tab" class="col tDam dark-4u fake-button elem-boost" onclick="toggle_boost_tab('dex')">
Thunder
</div>
<div id = "int-boost-tab" class="col wDam dark-4u fake-button elem-boost" onclick="toggle_boost_tab('int')">
Water
</div>
<div id = "def-boost-tab" class="col fDam dark-4u fake-button elem-boost" onclick="toggle_boost_tab('def')">
Fire
</div>
<div id = "agi-boost-tab" class="col aDam dark-4u fake-button elem-boost" onclick="toggle_boost_tab('agi')">
Air
</div>
</div>
<div class="row row-cols-1 p-0 m-0" id="str-boost" style="display: none;">
<div class="col eDam dark-5">
Quake (Active)
</div>
<div class="col skp-tooltip dark-6 rounded-bottom my-3 my-xl-1" >
<button class = "button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id = "Quake-1" onclick = "updatePowderSpecials('Quake-1')">
Lv.4 [e4e4]
</button>
<button class = "button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id = "Quake-2" onclick = "updatePowderSpecials('Quake-2')">
Lv.4.5 [e5e4]
</button>
<button class = "button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id = "Quake-3" onclick = "updatePowderSpecials('Quake-3')">
Lv.5 [e5e5]
</button>
<button class = "button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id = "Quake-4" onclick = "updatePowderSpecials('Quake-4')">
Lv.5.5 [e6e5]
</button>
<button class = "button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id = "Quake-5" onclick = "updatePowderSpecials('Quake-5')">
Lv.6 [e6e6]
</button>
</div>
<div class="col eDam">
Rage (Passive)
</div>
</div>
<div class="row row-cols-1 p-0 m-0" id="dex-boost" style="display: none;">
<div class="col tDam dark-5">
Chain Lightning (Active)
</div>
<div class="col skp-tooltip dark-6 rounded-bottom my-3 my-xl-1">
<button class = "button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id = "Chain_Lightning-1" onclick = "updatePowderSpecials('Chain_Lightning-1')">
Lv.4 [t4t4]
</button>
<button class = "button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id = "Chain_Lightning-2" onclick = "updatePowderSpecials('Chain_Lightning-2')">
Lv.4.5 [t5t4]
</button>
<button class = "button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id = "Chain_Lightning-3" onclick = "updatePowderSpecials('Chain_Lightning-3')">
Lv.5 [t5t5]
</button>
<button class = "button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id = "Chain_Lightning-4" onclick = "updatePowderSpecials('Chain_Lightning-4')">
Lv.5.5 [t6t5]
</button>
<button class = "button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id = "Chain_Lightning-5" onclick = "updatePowderSpecials('Chain_Lightning-5')">
Lv.6 [t6t6]
</button>
</div>
<div class="col tDam">
Kill Streak (Passive)
</div>
</div>
<div class="row row-cols-1 p-0 m-0" id="int-boost">
<div class="col wDam dark-5">
Curse (Active)
</div>
<div class="col skp-tooltip dark-6 rounded-bottom my-3 my-xl-1">
<button class = "button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id = "Curse-1" onclick = "updatePowderSpecials('Curse-1')">
Lv.4 [w4w4]
</button>
<button class = "button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id = "Curse-2" onclick = "updatePowderSpecials('Curse-2')">
Lv.4.5 [w5w4]
</button>
<button class = "button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id = "Curse-3" onclick = "updatePowderSpecials('Curse-3')">
Lv.5 [w5w5]
</button>
<button class = "button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id = "Curse-4" onclick = "updatePowderSpecials('Curse-4')">
Lv.5.5 [w6w5]
</button>
<button class = "button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id = "Curse-5" onclick = "updatePowderSpecials('Curse-5')">
Lv.6 [w6w6]
</button>
</div>
<div class="col wDam">
Concentration (Passive)
</div>
</div>
<div class="row row-cols-1 p-0 m-0" id="def-boost" style="display: none;">
<div class="col fDam dark-5">
Courage (Active)
</div>
<div class="col skp-tooltip dark-6 rounded-bottom my-3 my-xl-1">
<button class = "button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id = "Courage-1" onclick = "updatePowderSpecials('Courage-1')">
Lv.4 [f4f4]
</button>
<button class = "button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id = "Courage-2" onclick = "updatePowderSpecials('Courage-2')">
Lv.4.5 [f5f4]
</button>
<button class = "button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id = "Courage-3" onclick = "updatePowderSpecials('Courage-3')">
Lv.5 [f5f5]
</button>
<button class = "button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id = "Courage-4" onclick = "updatePowderSpecials('Courage-4')">
Lv.5.5 [f6f5]
</button>
<button class = "button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id = "Courage-5" onclick = "updatePowderSpecials('Courage-5')">
Lv.6 [f6f6]
</button>
</div>
<div class="col fDam">
Endurance (Passive)
</div>
</div>
<div class="row row-cols-1 p-0 m-0" id="agi-boost" style="display: none;">
<div class="col aDam dark-5">
Wind Prison (Active)
</div>
<div class="col skp-tooltip dark-6 rounded-bottom my-3 my-xl-1">
<button class = "button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id = "Wind_Prison-1" onclick = "updatePowderSpecials('Wind_Prison-1')">
Lv.4 [a4a4]
</button>
<button class = "button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id = "Wind_Prison-2" onclick = "updatePowderSpecials('Wind_Prison-2')">
Lv.4.5 [a5a4]
</button>
<button class = "button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id = "Wind_Prison-3" onclick = "updatePowderSpecials('Wind_Prison-3')">
Lv.5 [a5a5]
</button>
<button class = "button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id = "Wind_Prison-4" onclick = "updatePowderSpecials('Wind_Prison-4')">
Lv.5.5 [a6a5]
</button>
<button class = "button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id = "Wind_Prison-5" onclick = "updatePowderSpecials('Wind_Prison-5')">
Lv.6 [a6a6]
</button>
</div>
<div class="col aDam">
Dodge (Passive)
</div>
</div>
</div>
</div>
<div class="col mb-1"> <div class="col mb-1">
<div class="row row-cols-1 row-cols-1 text-center scaled-font dark-5 rounded dark-shadow"> <div class="row row-cols-1 row-cols-1 text-center scaled-font dark-5 rounded dark-shadow">
<div class="col fw-bold dark-4 rounded-top"> <div class="col fw-bold dark-4 rounded-top">
@ -620,7 +662,7 @@
<div class="col-auto rounded"> <div class="col-auto rounded">
<div class="row h-100 dark-shadow rounded" id='weaponTome1-dropdown'> <div class="row h-100 dark-shadow rounded" id='weaponTome1-dropdown'>
<div class="col-auto g-0 rounded-end my-auto text-center scaled-item-icon" id="weaponTome1-img-loc"> <div class="col-auto g-0 rounded-end my-auto text-center scaled-item-icon" id="weaponTome1-img-loc">
<img id="weaponTome1-img" class="img-fluid rounded" src="../media/items/new/generic-weaponTome.png"> <div id="weaponTome1-img" class="img-fluid rounded tome-image"></div>
</div> </div>
<div class="col-3"> <div class="col-3">
<div class="row row-cols-1 h-100 align-items-center"> <div class="row row-cols-1 h-100 align-items-center">
@ -644,7 +686,7 @@
<div class="col-auto rounded"> <div class="col-auto rounded">
<div class="row h-100 dark-shadow rounded" id='weaponTome2-dropdown'> <div class="row h-100 dark-shadow rounded" id='weaponTome2-dropdown'>
<div class="col-auto g-0 rounded-end my-auto text-center scaled-item-icon" id="weaponTome2-img-loc"> <div class="col-auto g-0 rounded-end my-auto text-center scaled-item-icon" id="weaponTome2-img-loc">
<img id="weaponTome2-img" class="img-fluid rounded" src="../media/items/new/generic-weaponTome.png"> <div id="weaponTome2-img" class="img-fluid rounded tome-image"></div>
</div> </div>
<div class="col-3"> <div class="col-3">
<div class="row row-cols-1 h-100 align-items-center"> <div class="row row-cols-1 h-100 align-items-center">
@ -668,7 +710,7 @@
<div class="col-auto rounded"> <div class="col-auto rounded">
<div class="row h-100 dark-shadow rounded" id='armorTome1-dropdown'> <div class="row h-100 dark-shadow rounded" id='armorTome1-dropdown'>
<div class="col-auto g-0 rounded-end my-auto text-center scaled-item-icon" id="armorTome1-img-loc"> <div class="col-auto g-0 rounded-end my-auto text-center scaled-item-icon" id="armorTome1-img-loc">
<img id="armorTome1-img" class="img-fluid rounded" src="../media/items/new/generic-armorTome.png"> <div id="armorTome1-img" class="img-fluid rounded tome-image"></div>
</div> </div>
<div class="col-3"> <div class="col-3">
<div class="row row-cols-1 h-100 align-items-center"> <div class="row row-cols-1 h-100 align-items-center">
@ -692,7 +734,7 @@
<div class="col-auto rounded"> <div class="col-auto rounded">
<div class="row h-100 dark-shadow rounded" id='armorTome2-dropdown'> <div class="row h-100 dark-shadow rounded" id='armorTome2-dropdown'>
<div class="col-auto g-0 rounded-end my-auto text-center scaled-item-icon" id="armorTome2-img-loc"> <div class="col-auto g-0 rounded-end my-auto text-center scaled-item-icon" id="armorTome2-img-loc">
<img id="armorTome2-img" class="img-fluid rounded" src="../media/items/new/generic-armorTome.png"> <div id="armorTome2-img" class="img-fluid rounded tome-image"></div>
</div> </div>
<div class="col-3"> <div class="col-3">
<div class="row row-cols-1 h-100 align-items-center"> <div class="row row-cols-1 h-100 align-items-center">
@ -716,7 +758,7 @@
<div class="col-auto rounded"> <div class="col-auto rounded">
<div class="row h-100 dark-shadow rounded" id='armorTome3-dropdown'> <div class="row h-100 dark-shadow rounded" id='armorTome3-dropdown'>
<div class="col-auto g-0 rounded-end my-auto text-center scaled-item-icon" id="armorTome3-img-loc"> <div class="col-auto g-0 rounded-end my-auto text-center scaled-item-icon" id="armorTome3-img-loc">
<img id="armorTome3-img" class="img-fluid rounded" src="../media/items/new/generic-armorTome.png"> <div id="armorTome3-img" class="img-fluid rounded tome-image"></div>
</div> </div>
<div class="col-3"> <div class="col-3">
<div class="row row-cols-1 h-100 align-items-center"> <div class="row row-cols-1 h-100 align-items-center">
@ -740,7 +782,7 @@
<div class="col-auto rounded"> <div class="col-auto rounded">
<div class="row h-100 dark-shadow rounded" id='armorTome4-dropdown'> <div class="row h-100 dark-shadow rounded" id='armorTome4-dropdown'>
<div class="col-auto g-0 rounded-end my-auto text-center scaled-item-icon" id="armorTome4-img-loc"> <div class="col-auto g-0 rounded-end my-auto text-center scaled-item-icon" id="armorTome4-img-loc">
<img id="armorTome4-img" class="img-fluid rounded" src="../media/items/new/generic-armorTome.png"> <div id="armorTome4-img" class="img-fluid rounded tome-image"></div>
</div> </div>
<div class="col-3"> <div class="col-3">
<div class="row row-cols-1 h-100 align-items-center"> <div class="row row-cols-1 h-100 align-items-center">
@ -764,7 +806,7 @@
<div class="col-auto rounded"> <div class="col-auto rounded">
<div class="row h-100 dark-shadow rounded" id='guildTome1-dropdown'> <div class="row h-100 dark-shadow rounded" id='guildTome1-dropdown'>
<div class="col-auto g-0 rounded-end my-auto text-center scaled-item-icon" id="guildTome1-img-loc"> <div class="col-auto g-0 rounded-end my-auto text-center scaled-item-icon" id="guildTome1-img-loc">
<img id="guildTome1-img" class="img-fluid rounded" src="../media/items/new/generic-guildTome.png"> <div id="guildTome1-img" class="img-fluid rounded tome-image"></div>
</div> </div>
<div class="col-3"> <div class="col-3">
<div class="row row-cols-1 h-100 align-items-center"> <div class="row row-cols-1 h-100 align-items-center">
@ -789,7 +831,7 @@
</div> </div>
<div class = "col dark-6 rounded-bottom my-3 my-xl-1" id = "atree-dropdown" style = "display:none;"> <div class = "col dark-6 rounded-bottom my-3 my-xl-1" id = "atree-dropdown" style = "display:none;">
<div class="row row-cols-1 row-cols-xl-2"> <div class="row row-cols-1 row-cols-xl-2">
<div class="col border border-semi-light rounded dark-9 hide-scroll" id="atree-ui" style="height: 90vh; overflow-y: auto; overflow-x: hidden;"> <div class="col border border-semi-light rounded dark-9 hide-scroll" id="atree-ui" style="height: 90vh; overflow-y: auto;">
</div> </div>
<div class="col mx-auto" style="height: 90vh; overflow-y: auto;" id="atree-rhs"> <div class="col mx-auto" style="height: 90vh; overflow-y: auto;" id="atree-rhs">
@ -1131,24 +1173,20 @@
</div> </div>
</div> </div>
</div> </div>
<div class="col-xl-3 mb-3"> <div class="col-xl-3 mb-3 order-2 order-lg-0">
<div class="row row-cols-1 rounded dark-shadow dark-6 scaled-font"> <div class="row row-cols-1 rounded dark-shadow dark-6 scaled-font">
<div class="col rounded-top"> <div class="col rounded-top">
<div class="row"> <div class="row">
<div id="tab-offensive-btn" class="col-4 text-center fake-button border-bottom border-dark rounded-top dark-4u border border-2 border-dark-7" onclick="show_tab('offensive-stats')"> <div id="detailed-stats-btn" class="col text-center fake-button border-bottom border-dark rounded-top dark-4u border border-2 border-dark-7" onclick="show_tab('detailed-stats', ['detailed-stats', 'summary-stats'])">
Offense Detailed
</div> </div>
<div id="tab-defensive-btn" class="col-4 text-center fake-button border-bottom border-dark rounded-top dark-4u border border-2 border-dark-7" onclick="show_tab('defensive-stats')"> <div id="summary-stats-btn" class="col text-center fake-button border-bottom border-dark rounded-top dark-4u border border-2 border-dark-7 selected-btn" onclick="show_tab('summary-stats', ['detailed-stats', 'summary-stats'])">
Defense Summary
</div>
<div id="tab-overall-btn" class="col-4 text-center fake-button border-bottom border-dark rounded-top dark-4u border border-2 border-dark-7 selected-btn" onclick="show_tab('overall-stats')">
Overall
</div> </div>
</div> </div>
</div> </div>
<div style="display: none;" id="offensive-stats" class="col text-nowrap"></div> <div style="display: none;" id="detailed-stats" class="col text-nowrap"></div>
<div style="display: none;" id="defensive-stats" class="col text-nowrap"></div> <div id="summary-stats" class="col text-nowrap"></div>
<div id="overall-stats" class="col text-nowrap"></div>
</div> </div>
</div> </div>
<div class="col-xl-3 mb-3 px-0"> <div class="col-xl-3 mb-3 px-0">
@ -1263,8 +1301,7 @@
<script type="text/javascript" src="../js/build_utils.js"></script> <script type="text/javascript" src="../js/build_utils.js"></script>
<script type="text/javascript" src="../js/computation_graph.js"></script> <script type="text/javascript" src="../js/computation_graph.js"></script>
<script type="text/javascript">COMPUTE_GRAPH_DEBUG=true;</script> <script type="text/javascript">COMPUTE_GRAPH_DEBUG=true;</script>
<!-- <script type="text/javascript" src="../js/icons.js"></script> --> <script type="text/javascript" src="../js/icons.js"></script>
<script type="text/javascript" src="../js/sq2icons.js"></script>
<script type="text/javascript" src="../js/powders.js"></script> <script type="text/javascript" src="../js/powders.js"></script>
<script type="text/javascript" src="../js/skillpoints.js"></script> <script type="text/javascript" src="../js/skillpoints.js"></script>
<script type="text/javascript" src="../js/damage_calc.js"></script> <script type="text/javascript" src="../js/damage_calc.js"></script>

File diff suppressed because one or more lines are too long

View file

@ -463,11 +463,8 @@
<button class="button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id="ragnarokkr-boost" onclick="update_boosts('ragnarokkr-boost')"> <button class="button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id="ragnarokkr-boost" onclick="update_boosts('ragnarokkr-boost')">
Ragnarokkr (+30%) Ragnarokkr (+30%)
</button> </button>
<button class="button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id="yourtotem-boost" onclick="update_boosts('yourtotem-boost')"> <button class="button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id="totem-boost" onclick="update_boosts('totem-boost')">
Your Totem (+35%) Vengeful Spirit (+20%)
</button>
<button class="button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id="allytotem-boost" onclick="update_boosts('allytotem-boost')">
Ally Totem (+15%)
</button> </button>
<button class="button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id="fortitude-boost" onclick="update_boosts('fortitude-boost')"> <button class="button-boost m-1 border-0 text-white dark-8u dark-shadow-sm" id="fortitude-boost" onclick="update_boosts('fortitude-boost')">
Fortitude (+60%) Fortitude (+60%)

View file

@ -50,7 +50,10 @@ add_spell_prop: {
cost: Optional[int] // change to spellcost. If the spell is not spell 1-4, this must be left empty. cost: Optional[int] // change to spellcost. If the spell is not spell 1-4, this must be left empty.
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)
hits: Optional[Map[str, float]] // Additive changes to hits (for total entry)
hits: Optional[Map[str, Union[str, float]]] // Additive changes to hits (for total entry)
// Can either be a raw value number, or a reference
// of the format <ability_id>.propname
display: Optional[str] // Optional change to the displayed entry. Replaces old display: Optional[str] // Optional change to the displayed entry. Replaces old
} }
@ -191,8 +194,8 @@ const atree_node = new (class extends ComputeNode {
atree_topo_sort.push(node); atree_topo_sort.push(node);
} }
} }
console.log("Approximate topological order ability tree:"); //console.log("Approximate topological order ability tree:");
console.log(atree_topo_sort); //console.log(atree_topo_sort);
return atree_topo_sort; return atree_topo_sort;
} }
})(); })();
@ -285,7 +288,10 @@ const atree_merge = new (class extends ComputeNode {
base_abil.subparts.push(abil.id); base_abil.subparts.push(abil.id);
base_abil.effects = base_abil.effects.concat(abil.effects); base_abil.effects = base_abil.effects.concat(abil.effects);
for (let propname in abil.properties) { for (let propname in abil.properties) {
base_abil[propname] = abil[propname]; if (propname in base_abil.properties) {
base_abil.properties[propname] += abil.properties[propname];
}
else { base_abil.properties[propname] = abil.properties[propname]; }
} }
} }
// do nothing otherwise. // do nothing otherwise.
@ -448,6 +454,207 @@ const atree_validate = new (class extends ComputeNode {
} }
})().link_to(atree_node, 'atree').link_to(atree_state_node, 'atree-state'); })().link_to(atree_node, 'atree').link_to(atree_state_node, 'atree-state');
/**
* Make interactive elements (sliders, buttons)
*
* Signature: AbilityActiveUINode(atree-merged: MergedATree) => Map<str, slider_info>
*
* ElemState: {
* value: int // value for sliders; 0-1 for toggles
* }
*/
const atree_make_interactives = new (class extends ComputeNode {
constructor() { super('atree-make-interactives'); }
compute_func(input_map) {
const merged_abils = input_map.get('atree-merged');
const atree_order = input_map.get('atree-order');
const boost_slider_parent = document.getElementById("boost-sliders");
const boost_toggle_parent = document.getElementById("boost-toggles");
boost_slider_parent.innerHTML = "";
boost_toggle_parent.innerHTML = "";
/**
* slider_info
* label_name: str,
* max: int,
* step: int,
* id: str,
* abil: atree_node
* slider: html element
* }
*/
// Map<str, slider_info>
const slider_map = new Map();
const button_map = new Map();
// first, pull out all the sliders and toggles.
for (const [abil_id, ability] of merged_abils.entries()) {
for (const effect of ability.effects) {
if (effect['type'] === "stat_scaling" && effect['slider'] === true) {
const { slider_name, slider_behavior = 'merge', slider_max, slider_step } = effect;
if (slider_map.has(slider_name)) {
if (slider_max !== undefined) {
const slider_info = slider_map.get(slider_name);
slider_info.max += slider_max;
}
}
else if (slider_behavior === 'merge') {
slider_map.set(slider_name, {
label_name: slider_name+' ('+ability.display_name+')',
max: slider_max,
step: slider_step,
id: "ability-slider"+ability.id,
//color: effect['slider_color'] TODO: add colors to json
abil: ability
});
}
}
if (effect['type'] === "raw_stat" && effect['toggle']) {
const { toggle: toggle_name } = effect;
button_map.set(toggle_name, {
abil: ability
});
}
}
}
// next, render the sliders and toggles onto the abilities.
for (const [slider_name, slider_info] of slider_map.entries()) {
let slider_container = gen_slider_labeled(slider_info);
boost_slider_parent.appendChild(slider_container);
slider_info.slider = document.getElementById(slider_info.id);
slider_info.slider.addEventListener("change", (e) => atree_scaling.mark_dirty().update());
}
for (const [button_name, button_info] of button_map.entries()) {
let button = make_elem('button', ["button-boost", "border-0", "text-white", "dark-8u", "dark-shadow-sm", "m-1"], {
id: button_info.abil.id,
textContent: button_name
});
button.addEventListener("click", (e) => {
if (button.classList.contains("toggleOn")) {
button.classList.remove("toggleOn");
} else {
button.classList.add("toggleOn");
}
atree_scaling.mark_dirty().update()
});
button_info.button = button;
boost_toggle_parent.appendChild(button);
}
return [slider_map, button_map];
}
})().link_to(atree_node, 'atree-order').link_to(atree_merge, 'atree-merged');
/**
* Scaling stats from ability tree.
* Return StatMap of added stats,
*
* Signature: AbilityTreeScalingNode(atree-merged: MergedATree, scale-scats: StatMap,
* atree-interactive: [Map<str, slider_info>, Map<str, button_info>]) => (ATree, StatMap)
*/
const atree_scaling = new (class extends ComputeNode {
constructor() { super('atree-scaling-collector'); }
compute_func(input_map) {
const atree_merged = input_map.get('atree-merged');
const pre_scale_stats = input_map.get('scale-stats');
const [slider_map, button_map] = input_map.get('atree-interactive');
const atree_edit = new Map();
for (const [abil_id, abil] of atree_merged.entries()) {
atree_edit.set(abil_id, deepcopy(abil));
}
let ret_effects = new Map();
// Apply a stat bonus.
function apply_bonus(bonus_info, value) {
const { type, name, abil = null} = bonus_info;
if (type === 'stat') {
merge_stat(ret_effects, name, value);
} else if (type === 'prop') {
const merge_abil = atree_edit.get(abil);
merge_abil.properties[name] += value;
}
}
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 'raw_stat':
if (effect.toggle) {
const button = button_map.get(effect.toggle).button;
if (!button.classList.contains("toggleOn")) { continue; }
for (const bonus of effect.bonuses) {
apply_bonus(bonus, bonus.value);
}
} else {
for (const bonus of effect.bonuses) {
// Stat was applied earlier...
if (bonus.type === 'stat') { continue; }
apply_bonus(bonus, bonus.value);
}
}
continue;
case 'stat_scaling':
let total = 0;
const {slider = false, scaling = [0]} = effect;
let { positive = true, round = true } = effect;
if (slider) {
const slider_val = slider_map.get(effect.slider_name).slider.value;
total = parseInt(slider_val) * scaling[0];
round = false;
positive = false;
}
else {
// TODO: type: prop?
for (const [_scaling, input] of zip2(scaling, effect.inputs)) {
total += _scaling * pre_scale_stats.get(input.name);
}
}
if ('output' in effect) { // sometimes nodes will modify slider without having effect.
if (round) { total = Math.floor(round_near(total)); }
if (positive && total < 0) { total = 0; } // Normal stat scaling will not go negative.
if ('max' in effect && total > effect.max) { total = effect.max; }
if (Array.isArray(effect.output)) {
for (const output of effect.output) {
apply_bonus(output, total);
}
}
else {
apply_bonus(effect.output, total);
}
}
continue;
}
}
}
return [atree_edit, ret_effects];
}
})().link_to(atree_merge, 'atree-merged').link_to(atree_make_interactives, 'atree-interactive');
/**
* These following two nodes are just boilerplate that breaks down the scaling node.
*/
const atree_scaling_tree = new (class extends ComputeNode {
constructor() { super('atree-scaling-tree'); }
compute_func(input_map) {
const [[tree, stats]] = input_map.values();
return tree;
}
})().link_to(atree_scaling, 'atree-scaling');
const atree_scaling_stats = new (class extends ComputeNode {
constructor() { super('atree-scaling-stats'); }
compute_func(input_map) {
const [[tree, stats]] = input_map.values();
return stats;
}
})().link_to(atree_scaling, 'atree-scaling');
/** /**
* Render ability tree. * Render ability tree.
* Return map of id -> corresponding html element. * Return map of id -> corresponding html element.
@ -506,7 +713,8 @@ const atree_render_active = new (class extends ComputeNode {
} }
return ret_map; return ret_map;
} }
})().link_to(atree_node, 'atree-order').link_to(atree_merge, 'atree-merged').link_to(atree_validate, 'atree-errors'); })().link_to(atree_node, 'atree-order').link_to(atree_scaling_tree, 'atree-merged').link_to(atree_validate, 'atree-errors');
/** /**
* Collect spells from abilities. * Collect spells from abilities.
@ -521,13 +729,29 @@ const atree_collect_spells = new (class extends ComputeNode {
const [hard_error, errors] = input_map.get('atree-errors'); const [hard_error, errors] = input_map.get('atree-errors');
if (hard_error) { return []; } if (hard_error) { return []; }
/**
* Parse out "parametrized entries".
* Straight replace.
*
* Format: ability_id.propname
*/
function translate(v) {
if (typeof v === 'string') {
const [id_str, propname] = v.split('.');
const id = parseInt(id_str);
const ret = atree_merged.get(id).properties[propname];
return ret;
}
return v;
}
let ret_spells = new Map(); let ret_spells = new Map();
for (const [abil_id, abil] of atree_merged.entries()) { for (const [abil_id, abil] of atree_merged.entries()) {
// TODO: Possibly, make a better way for detecting "spell abilities"? // TODO: Possibly, make a better way for detecting "spell abilities"?
for (const effect of abil.effects) { for (const effect of abil.effects) {
if (effect.type === 'replace_spell') { if (effect.type === 'replace_spell') {
// replace_spell just replaces all (defined) aspects. // replace_spell just replaces all (defined) aspects.
const ret_spell = ret_spells.get(effect.base_spell); let ret_spell = ret_spells.get(effect.base_spell);
if (ret_spell) { if (ret_spell) {
// NOTE: do not mutate results of previous steps! // NOTE: do not mutate results of previous steps!
for (const key in effect) { for (const key in effect) {
@ -535,7 +759,15 @@ const atree_collect_spells = new (class extends ComputeNode {
} }
} }
else { else {
ret_spells.set(effect.base_spell, deepcopy(effect)); ret_spell = deepcopy(effect);
ret_spells.set(effect.base_spell, ret_spell);
}
for (const part of ret_spell.parts) {
if ('hits' in part) {
for (const idx in part.hits) {
part.hits[idx] = translate(part.hits[idx]);
}
}
} }
} }
} }
@ -572,7 +804,8 @@ const atree_collect_spells = new (class extends ComputeNode {
part.power += effect.power; part.power += effect.power;
} }
else if ('hits' in effect) { else if ('hits' in effect) {
for (const [idx, v] of Object.entries(effect.hits)) { // looks kinda similar to multipliers case... hmm... can we unify all of these three? (make healpower a list) for (const [idx, _v] of Object.entries(effect.hits)) { // looks kinda similar to multipliers case... hmm... can we unify all of these three? (make healpower a list)
let v = translate(_v);
if (idx in part.hits) { part.hits[idx] += v; } if (idx in part.hits) { part.hits[idx] += v; }
else { part.hits[idx] = v; } else { part.hits[idx] = v; }
} }
@ -586,6 +819,11 @@ const atree_collect_spells = new (class extends ComputeNode {
if (!found_part && behavior === 'merge') { // add part. if behavior is merge 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
if ('hits' in spell_part) {
for (const idx in spell_part.hits) {
spell_part.hits[idx] = translate(spell_part.hits[idx]);
}
}
ret_spell.parts.push(spell_part); ret_spell.parts.push(spell_part);
} }
if ('display' in effect) { if ('display' in effect) {
@ -617,185 +855,16 @@ const atree_collect_spells = new (class extends ComputeNode {
} }
return ret_spells; return ret_spells;
} }
})().link_to(atree_merge, 'atree-merged').link_to(atree_validate, 'atree-errors'); })().link_to(atree_scaling_tree, 'atree-merged').link_to(atree_validate, 'atree-errors');
/** /**
* Make interactive elements (sliders, buttons) * Collect raw stats from ability tree.
*
* Signature: AbilityActiveUINode(atree-merged: MergedATree) => Map<str, slider_info>
*
* ElemState: {
* value: int // value for sliders; 0-1 for toggles
* }
*/
const atree_make_interactives = new (class extends ComputeNode {
constructor() { super('atree-make-interactives'); }
compute_func(input_map) {
const merged_abils = input_map.get('atree-merged');
const atree_order = input_map.get('atree-order');
const atree_html = input_map.get('atree-elements');
document.getElementById("boost-sliders").innerHTML = "";
document.getElementById("boost-toggles").innerHTML = "";
/**
* slider_info
* label_name: str,
* max: int,
* step: int,
* id: str,
* abil: atree_node
* slider: html element
* }
*/
// Map<str, slider_info>
const slider_map = new Map();
const button_map = new Map();
// first, pull out all the sliders and toggles.
for (const [abil_id, ability] of merged_abils.entries()) {
for (const effect of ability.effects) {
if (effect['type'] === "stat_scaling" && effect['slider'] === true) {
const { slider_name, slider_behavior = 'merge', slider_max, slider_step } = effect;
if (slider_map.has(slider_name)) {
if (slider_max !== undefined) {
const slider_info = slider_map.get(slider_name);
slider_info.max += slider_max;
}
}
else if (slider_behavior === 'merge') {
slider_map.set(slider_name, {
label_name: slider_name+' ('+ability.display_name+')',
max: slider_max,
step: slider_step,
id: "ability-slider"+ability.id,
//color: effect['slider_color'] TODO: add colors to json
abil: ability
});
}
}
if (effect['type'] === "raw_stat" && effect['toggle']) {
const { toggle: toggle_name } = effect;
button_map.set(toggle_name, {
abil: ability
});
}
}
}
// next, render the sliders and toggles onto the abilities.
for (const [slider_name, slider_info] of slider_map.entries()) {
let slider_container = gen_slider_labeled(slider_info);
document.getElementById("boost-sliders").appendChild(slider_container);
slider_info.slider = document.getElementById(slider_info.id);
slider_info.slider.addEventListener("change", (e) => atree_scaling.mark_dirty().update());
}
for (const [button_name, button_info] of button_map.entries()) {
let button = make_elem('button', ["button-boost", "border-0", "text-white", "dark-8u", "dark-shadow-sm", "m-1"], {
id: button_info.abil.id,
textContent: button_name
});
button.addEventListener("click", (e) => {
if (button.classList.contains("toggleOn")) {
button.classList.remove("toggleOn");
} else {
button.classList.add("toggleOn");
}
atree_scaling.mark_dirty().update()
});
button_info.button = button;
document.getElementById("boost-toggles").appendChild(button);
}
return [slider_map, button_map];
}
})().link_to(atree_node, 'atree-order').link_to(atree_merge, 'atree-merged').link_to(atree_render_active, 'atree-elements');
/**
* Scaling stats from ability tree.
* Return StatMap of added stats,
*
* Signature: AbilityTreeScalingNode(atree-merged: MergedATree, scale-scats: StatMap,
* atree-interactive: [Map<str, slider_info>, Map<str, button_info>]) => StatMap
*/
const atree_scaling = new (class extends ComputeNode {
constructor() { super('atree-scaling-collector'); }
compute_func(input_map) {
const atree_merged = input_map.get('atree-merged');
const pre_scale_stats = input_map.get('scale-stats');
const [slider_map, button_map] = input_map.get('atree-interactive');
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 'raw_stat':
// TODO: toggles...
if (effect.toggle) {
const button = button_map.get(effect.toggle).button;
if (!button.classList.contains("toggleOn")) { continue; }
for (const bonus of effect.bonuses) {
const { type, name, abil = "", value } = bonus;
// TODO: prop
if (type === "stat") {
merge_stat(ret_effects, name, value);
}
}
}
continue;
case 'stat_scaling':
let total = 0;
const {slider = false, scaling = [0]} = effect;
let { positive = true, round = true } = effect;
if (slider) {
const slider_val = slider_map.get(effect.slider_name).slider.value;
total = parseInt(slider_val) * scaling[0];
round = false;
positive = false;
}
else {
// TODO: type: prop?
for (const [_scaling, input] of zip2(scaling, effect.inputs)) {
total += _scaling * pre_scale_stats.get(input.name);
}
}
if ('output' in effect) { // sometimes nodes will modify slider without having effect.
if (round) { total = Math.floor(round_near(total)); }
if (positive && total < 0) { total = 0; } // Normal stat scaling will not go negative.
if ('max' in effect && total > effect.max) { total = effect.max; }
if (Array.isArray(effect.output)) {
for (const output of effect.output) {
if (output.type === 'stat') { // TODO: prop
merge_stat(ret_effects, output.name, total);
}
}
}
else {
if (effect.output.type === 'stat') {
merge_stat(ret_effects, effect.output.name, total);
}
}
}
continue;
}
}
}
return ret_effects;
}
})().link_to(atree_merge, 'atree-merged').link_to(atree_make_interactives, 'atree-interactive');
/**
* Collect stats from ability tree.
* Return StatMap of added stats. * Return StatMap of added stats.
* *
* Signature: AbilityTreeStatsNode(atree-merged: MergedATree) => StatMap * Signature: AbilityTreeStatsNode(atree-merged: MergedATree) => StatMap
*/ */
const atree_stats = new (class extends ComputeNode { const atree_raw_stats = new (class extends ComputeNode {
constructor() { super('atree-stats-collector'); } constructor() { super('atree-raw-stats-collector'); }
compute_func(input_map) { compute_func(input_map) {
const atree_merged = input_map.get('atree-merged'); const atree_merged = input_map.get('atree-merged');

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

View file

@ -17,6 +17,8 @@ let armor_powder_node = new (class extends ComputeNode {
} }
})(); })();
const damageMultipliers = new Map([ ["totem", .2], ["warscream", 0.0], ["ragnarokkr", 0.30], ["fortitude", 0.60] ]);
let boosts_node = new (class extends ComputeNode { let boosts_node = new (class extends ComputeNode {
constructor() { super('builder-boost-input'); } constructor() { super('builder-boost-input'); }
@ -887,6 +889,17 @@ class EditableIDSetterNode extends ComputeNode {
} }
} }
/**
* Overriding this to bridge the transparent gap.
*/
mark_dirty(dirty_state=2) {
super.mark_dirty(dirty_state);
for (const node of this.notify_nodes) {
node.mark_dirty(dirty_state);
}
return this;
}
notify() { notify() {
this.mark_dirty(); this.mark_dirty();
this.update(); this.update();
@ -1068,10 +1081,10 @@ function builder_graph_init() {
// These two are defined in `atree.js` // These two are defined in `atree.js`
atree_node.link_to(class_node, 'player-class'); atree_node.link_to(class_node, 'player-class');
atree_merge.link_to(class_node, 'player-class'); atree_merge.link_to(class_node, 'player-class');
pre_scale_agg_node.link_to(atree_stats, 'atree-raw-stats'); pre_scale_agg_node.link_to(atree_raw_stats, 'atree-raw-stats');
atree_scaling.link_to(pre_scale_agg_node, 'scale-stats'); atree_scaling.link_to(pre_scale_agg_node, 'scale-stats');
stat_agg_node.link_to(pre_scale_agg_node, 'pre-scaling'); stat_agg_node.link_to(pre_scale_agg_node, 'pre-scaling');
stat_agg_node.link_to(atree_scaling, 'atree-scaling'); stat_agg_node.link_to(atree_scaling_stats, 'atree-scaling');
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');

View file

@ -1,6 +1,6 @@
let all_nodes = new Set(); let all_nodes = new Set();
let node_debug_stack = []; let node_debug_stack = [];
let COMPUTE_GRAPH_DEBUG = false; let COMPUTE_GRAPH_DEBUG = true;
class ComputeNode { class ComputeNode {
/** /**
* Make a generic compute node. * Make a generic compute node.
@ -15,7 +15,7 @@ class ComputeNode {
this.value = null; this.value = null;
this.name = name; this.name = name;
this.update_task = null; this.update_task = null;
this.fail_cb = false; // Set to true to force updates even if parent failed. this.fail_cb = false; // Set to true to force updates even if parent failed
this.dirty = 2; // 3 states: this.dirty = 2; // 3 states:
// 2: dirty // 2: dirty
// 1: possibly dirty // 1: possibly dirty
@ -39,6 +39,13 @@ class ComputeNode {
if (this.dirty == 2) { if (this.dirty == 2) {
let calc_inputs = new Map(); let calc_inputs = new Map();
for (const input of this.inputs) { for (const input of this.inputs) {
if (input.dirty) {
if (COMPUTE_GRAPH_DEBUG) {
console.log(node_debug_stack);
console.log(this);
}
throw "Invalid compute graph state!";
}
calc_inputs.set(this.input_translation.get(input.name), input.value); calc_inputs.set(this.input_translation.get(input.name), input.value);
} }
this.value = this.compute_func(calc_inputs); this.value = this.compute_func(calc_inputs);
@ -213,7 +220,7 @@ class PrintNode extends ComputeNode {
* *
* Signature: InputNode() => str * Signature: InputNode() => str
*/ */
class InputNode extends ComputeNode { class InputNode extends ValueCheckComputeNode {
constructor(name, input_field) { constructor(name, input_field) {
super(name); super(name);
this.input_field = input_field; this.input_field = input_field;

View file

@ -2,8 +2,6 @@
* File implementing core damage calculation logic. * File implementing core damage calculation logic.
*/ */
const damageMultipliers = new Map([ ["allytotem", .15], ["yourtotem", .35], ["warscream", 0.00], ["ragnarokkr", 0.30], ["fortitude", 0.60] ]);
function get_base_dps(item) { function get_base_dps(item) {
const attack_speed_mult = baseDamageMultiplier[attackSpeeds.indexOf(item.get("atkSpd"))]; const attack_speed_mult = baseDamageMultiplier[attackSpeeds.indexOf(item.get("atkSpd"))];
//SUPER JANK @HPP PLS FIX //SUPER JANK @HPP PLS FIX
@ -260,8 +258,9 @@ spell_heal: {
spell_total: { spell_total: {
name: str != "total" Name of the part. name: str != "total" Name of the part.
type: "total" [TODO: DEPRECATED/REMOVE] flag signaling what type of part it is. Can infer from fields type: "total" [TODO: DEPRECATED/REMOVE] flag signaling what type of part it is. Can infer from fields
hits: Map[str, num] Keys are other part names, numbers are the multipliers. Undefined behavior if subparts hits: Map[str, Union[str, num]] Keys are other part names, numbers are the multipliers. Undefined behavior if subparts
are not the same type of spell. Can only pull from spells defined before it. are not the same type of spell. Can only pull from spells defined before it.
Alternatively, a property reference of the format <ability_id>.propname
} }

View file

@ -39,7 +39,25 @@ def translate_id(id_data, atree_data):
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"] == "replace_spell":
for part in effect['parts']:
if 'hits' in part: # Translate parametrized hits...
hits_mapping = part['hits']
keys = list(hits_mapping.keys())
for k in keys:
v = hits_mapping[k]
if isinstance(v, str):
abil_id, propname = v.split('.')
hits_mapping[k] = str(id_data[_class][abil_id])+'.'+propname
elif effect["type"] == "add_spell_prop":
if 'hits' in effect: # Translate parametrized hits...
hits_mapping = effect['hits']
keys = list(hits_mapping.keys())
for k in keys:
v = hits_mapping[k]
if isinstance(v, str):
abil_id, propname = v.split('.')
hits_mapping[k] = str(id_data[_class][abil_id])+'.'+propname
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"]: