2.0.4.4 update (#269)
* 2.0.4.4 update Fix v3 item api debug script Implement hellfire (discombob disallow not happening yet) * Fix boiling blood implementation slightly more intuitive also, janky first pass implementation for hellfire * Atree default update Allow sliders to specify a default value, for puppet and boiling blood for now * Fix rainbow def display on items and build stats Calculate into raw def correctly * Atree backend improvements Allow major ids to have dependencies Implement cherry bomb new ver. (wooo replace_spell just works out of the box!) Add comments to atree.js * Fix name of normal items don't you love it when wynn api makes breaking changes for no reason * Misc bugfix Reckless abandon req Tempest new damage ID in search * Fix major id search and temblor desc * Fix blockers on mage * Fix flaming uppercut implementation * Force base dps display to display less digits * Tomes finally pulling from the API but still with alias feature enabled! * Lootrun tomes (finally?) cool? maybe? * Fix beachside set set bonus --------- Co-authored-by: hppeng <hppeng>
This commit is contained in:
parent
4147bd813e
commit
dec0a95279
43 changed files with 119163 additions and 116154 deletions
File diff suppressed because one or more lines are too long
|
@ -827,6 +827,30 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-auto rounded">
|
||||
<div class="row h-100 dark-shadow rounded" id='lootrunTome1-dropdown'>
|
||||
<div class="col-auto g-0 rounded-end my-auto text-center scaled-item-icon" id="lootrunTome1-img-loc">
|
||||
<div id="lootrunTome1-img" class="img-fluid rounded tome-image"></div>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<div class="row row-cols-1 h-100 align-items-center">
|
||||
<div class="col scaled-font fw-bold gx-3">
|
||||
Lootrun
|
||||
</div>
|
||||
<div class="col scaled-font fw-bold gx-3">
|
||||
Tome
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col g-0 rounded">
|
||||
<div class="row row-cols-1 h-100 align-items-center">
|
||||
<div class="col d-flex justify-content-end">
|
||||
<input class="equipment-input border-dark text-light dark-10 rounded scaled-font form-control form-control-sm" id="lootrunTome1-choice" name="lootrunTome1-choice" placeholder="No Tome" value=""/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class = "col dark-6 rounded-bottom my-3 my-xl-1" id = "atree-dropdown" style = "display:none;">
|
||||
|
@ -1328,5 +1352,11 @@
|
|||
<script type="text/javascript" src="../js/builder/builder_graph.js"></script>
|
||||
<script type="text/javascript" src="../js/builder/builder.js"></script>
|
||||
<!--script type="text/javascript" src="../js/builder/optimize.js"></script-->
|
||||
<!--div id="graph_body" style="max-width: 100%; height: 100vh">
|
||||
<button id="saveButton">JANKY Export SVG</button>
|
||||
<a id="saveLink">savelink</a>
|
||||
</div>
|
||||
<script src="https://d3js.org/d3.v7.js"></script>
|
||||
<script type="text/javascript" src="../js/debug/render_compute_graph.js"></script-->
|
||||
</body>
|
||||
</html>
|
||||
|
|
177467
clean.json
177467
clean.json
File diff suppressed because it is too large
Load diff
File diff suppressed because one or more lines are too long
0
data/2.0.3.1/majid.json
Executable file → Normal file
0
data/2.0.3.1/majid.json
Executable file → Normal file
0
data/2.0.4.1/majid.json
Executable file → Normal file
0
data/2.0.4.1/majid.json
Executable file → Normal file
0
data/2.0.4.3/majid.json
Executable file → Normal file
0
data/2.0.4.3/majid.json
Executable file → Normal file
1
data/2.0.4.4/atree.json
Normal file
1
data/2.0.4.4/atree.json
Normal file
File diff suppressed because one or more lines are too long
1
data/2.0.4.4/ingreds.json
Normal file
1
data/2.0.4.4/ingreds.json
Normal file
File diff suppressed because one or more lines are too long
1
data/2.0.4.4/items.json
Normal file
1
data/2.0.4.4/items.json
Normal file
File diff suppressed because one or more lines are too long
1
data/2.0.4.4/majid.json
Normal file
1
data/2.0.4.4/majid.json
Normal file
File diff suppressed because one or more lines are too long
1
data/2.0.4.4/recipes.json
Normal file
1
data/2.0.4.4/recipes.json
Normal file
File diff suppressed because one or more lines are too long
1387
data/2.0.4.4/tomes.json
Normal file
1387
data/2.0.4.4/tomes.json
Normal file
File diff suppressed because it is too large
Load diff
53216
ingreds_clean.json
53216
ingreds_clean.json
File diff suppressed because it is too large
Load diff
File diff suppressed because one or more lines are too long
|
@ -56,6 +56,7 @@
|
|||
</div>
|
||||
<script type="text/javascript" src="/js/utils.js"></script>
|
||||
<script type="text/javascript" src="/js/build_utils.js"></script>
|
||||
<script type="text/javascript" src="/js/builder/build_encode_decode.js"></script>
|
||||
<script type="text/javascript" src="/js/icons.js"></script>
|
||||
<script type="text/javascript" src="/js/damage_calc.js"></script>
|
||||
<script type="text/javascript" src="/js/powders.js"></script>
|
||||
|
|
|
@ -152,7 +152,7 @@
|
|||
['waterDmg%', 'number', ['waterDam%', 'wDmg%', 'wDam%', 'wDamPct'], 'The bonus water damage modifier on an item.'],
|
||||
['fireDmg%', 'number', ['fireDam%', 'fDmg%', 'fDam%', 'fDamPct'], 'The bonus fire damage modifier on an item.'],
|
||||
['airDmg%', 'number', ['airDam%', 'aDmg%', 'aDam%', 'aDamPct'], 'The bonus air damage modifier on an item.'],
|
||||
['sumDmg%', 'number', ['sumDam%', 'totalDmg%', 'totalDam%', 'sumDamPct', 'totalDamPct'], 'The sum of the bonus elemental damage modifiers on an item.'],
|
||||
//['sumDmg%', 'number', ['sumDam%', 'totalDmg%', 'totalDam%', 'sumDamPct', 'totalDamPct'], 'The sum of the bonus elemental damage modifiers on an item.'],
|
||||
['meleeDmg', 'number', ['meleeDam', 'meleeDmg%', 'meleeDam%', 'mdPct'], 'The bonus main-attack damage modifier on an item.'],
|
||||
['meleeNeutralDmg', 'number', ['meleeRawDam', 'meleeNeutralDmg', 'meleeNeutralDam', 'mdRaw'], 'The neutral main-attack damage on an item.'],
|
||||
['spellDmg', 'number', ['spellDam', 'spellDmg%', 'spellDam%', 'sdPct'], 'The bonus spell damage modifier on an item.'],
|
||||
|
|
|
@ -60,7 +60,15 @@ const armorTypes = [ "helmet", "chestplate", "leggings", "boots" ];
|
|||
const accessoryTypes = [ "ring", "bracelet", "necklace" ];
|
||||
const weaponTypes = [ "wand", "spear", "bow", "dagger", "relik" ];
|
||||
const consumableTypes = [ "potion", "scroll", "food"];
|
||||
const tome_types = ['weaponTome', 'armorTome', 'guildTome'];
|
||||
const tome_types = ['weaponTome', 'armorTome', 'guildTome', 'lootrunTome', 'gatherXpTome', 'dungeonXpTome', 'mobXpTome'];
|
||||
const tome_type_map = new Map([["weaponTome", "Weapon Tome"],
|
||||
["armorTome", "Armor Tome"],
|
||||
["guildTome", "Guild Tome"],
|
||||
["gatherXpTome", "Gather XP Tome"],
|
||||
["dungeonXpTome", "Dungeon XP Tome"],
|
||||
["mobXpTome", "Slaying XP Tome"],
|
||||
]);
|
||||
|
||||
const attackSpeeds = ["SUPER_SLOW", "VERY_SLOW", "SLOW", "NORMAL", "FAST", "VERY_FAST", "SUPER_FAST"];
|
||||
const baseDamageMultiplier = [ 0.51, 0.83, 1.5, 2.05, 2.5, 3.1, 4.3 ];
|
||||
//0.51, 0.82, 1.50, 2.05, 2.50, 3.11, 4.27
|
||||
|
|
|
@ -76,22 +76,23 @@ raw_stat: {
|
|||
bonuses: List[stat_bonus]
|
||||
}
|
||||
stat_bonus: {
|
||||
"type": "stat" | "prop",
|
||||
"abil": Optional[int],
|
||||
"name": str,
|
||||
"value": float
|
||||
type: "stat" | "prop",
|
||||
abil: Optional[int],
|
||||
name: str,
|
||||
value: float
|
||||
}
|
||||
stat_scaling: {
|
||||
"type": "stat_scaling",
|
||||
"slider": bool,
|
||||
type: "stat_scaling",
|
||||
slider: bool,
|
||||
positive: bool // True to keep stat above 0. False to ignore floor. Default: True for normal, False for scaling
|
||||
"slider_name": Optional[str],
|
||||
"slider_step": Optional[float],
|
||||
round: Optional[bool] // Control floor behavior. True for stats and false for slider by default
|
||||
behavior: Optional[str] // One of: "merge", "modify". default: merge
|
||||
slider_name: Optional[str],
|
||||
slider_step: Optional[float],
|
||||
round: Optional[bool] // Control floor behavior. True for stats and false for slider by default
|
||||
behavior: Optional[str] // One of: "merge", "modify". default: merge
|
||||
// merge: add if exist, make new part if not exist
|
||||
// modify: change existing part, by incrementing properties. do nothing if not exist
|
||||
slider_max: Optional[float] // affected by behavior
|
||||
slider_max: Optional[int] // affected by behavior
|
||||
slider_default: Optional[int] // affected by behavior
|
||||
inputs: Optional[list[scaling_target]] // List of things to scale. Omit this if using slider
|
||||
|
||||
output: Optional[scaling_target | List[scaling_target]] // One of the following:
|
||||
|
@ -99,12 +100,12 @@ stat_scaling: {
|
|||
// 2. List of scaling targets (all scaled the same)
|
||||
// 3. Omitted. no output (useful for modifying slider only without input or output)
|
||||
scaling: Optional[list[float]] // One float for each input. Sums into output.
|
||||
max: float
|
||||
max: float // Hardcap on this effect (slider value * slider_step). Can be negative if scaling is negative
|
||||
}
|
||||
scaling_target: {
|
||||
"type": "stat" | "prop",
|
||||
"abil": Optional[int],
|
||||
"name": str
|
||||
type: "stat" | "prop",
|
||||
abil: Optional[int],
|
||||
name: str
|
||||
}
|
||||
*/
|
||||
|
||||
|
@ -476,14 +477,42 @@ const atree_merge = new (class extends ComputeNode {
|
|||
merge_abil(node.ability);
|
||||
}
|
||||
|
||||
// Apply major IDs.
|
||||
const build_class = wep_to_class.get(build.weapon.statMap.get("type"));
|
||||
for (const major_id_name of build.statMap.get("activeMajorIDs")) {
|
||||
|
||||
// Sometimes, something silly happens and we haven't implemented a major ID that
|
||||
// exists. This makes sure we don't try to apply unimplemented major IDs.
|
||||
//
|
||||
// `major_ids` is a global map loaded from data json.
|
||||
if (major_id_name in major_ids) {
|
||||
|
||||
// A major ID can have multiple abilities, specified as atree nodes,
|
||||
// as part of its effects. Apply each of them.
|
||||
for (const abil of major_ids[major_id_name].abilities) {
|
||||
if (abil["class"] === build_class) { merge_abil(abil); }
|
||||
|
||||
// But only the ones that match the current class.
|
||||
if (abil["class"] === build_class) {
|
||||
|
||||
// Major IDs can have ability dependencies.
|
||||
// By default they are always on.
|
||||
if (abil.dependencies !== undefined) {
|
||||
|
||||
let dep_satisfied = true;
|
||||
for (const dep_id of abil.dependencies) {
|
||||
if (!atree_state.get(dep_id).active) {
|
||||
dep_satisfied = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!dep_satisfied) { continue; }
|
||||
}
|
||||
merge_abil(abil);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
console.log(abils_merged)
|
||||
return abils_merged;
|
||||
}
|
||||
})().link_to(atree_node, 'atree').link_to(atree_state_node, 'atree-state').link_to(atree_validate, 'atree-errors');
|
||||
|
@ -540,20 +569,17 @@ const atree_make_interactives = new (class extends ComputeNode {
|
|||
for (let i = 0; i < k; ++i) {
|
||||
for (const [effect, abil_id, ability] of to_process) {
|
||||
if (effect['type'] === "stat_scaling" && effect['slider'] === true) {
|
||||
const { slider_name, behavior = 'merge', slider_max, slider_step } = effect;
|
||||
const { slider_name, behavior = 'merge', slider_max = 0, slider_step, slider_default = 0 } = 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 {
|
||||
unprocessed.push([effect, abil_id, ability]);
|
||||
}
|
||||
const slider_info = slider_map.get(slider_name);
|
||||
slider_info.max += slider_max;
|
||||
slider_info.default_val += slider_default;
|
||||
}
|
||||
else if (behavior === 'merge') {
|
||||
slider_map.set(slider_name, {
|
||||
label_name: slider_name+' ('+ability.display_name+')',
|
||||
max: slider_max,
|
||||
default_val: slider_default,
|
||||
step: slider_step,
|
||||
id: "ability-slider"+ability.id,
|
||||
//color: effect['slider_color'] TODO: add colors to json
|
||||
|
|
|
@ -3589,7 +3589,7 @@ const atrees = {
|
|||
},
|
||||
"properties": {
|
||||
"duration": 3,
|
||||
"tick": 0.6
|
||||
"rate": 1.66666666666666666666666666666
|
||||
},
|
||||
"effects": [
|
||||
{
|
||||
|
@ -3604,9 +3604,7 @@ const atrees = {
|
|||
},
|
||||
{
|
||||
"name": "DPS",
|
||||
"hits": {
|
||||
"Damage Tick": 1.66666666666666666666666666666
|
||||
}
|
||||
"hits": { "Damage Tick": "Uppercut.rate" }
|
||||
},
|
||||
{
|
||||
"name": "Total Damage",
|
||||
|
@ -3846,7 +3844,7 @@ const atrees = {
|
|||
},
|
||||
{
|
||||
"display_name": "Counter",
|
||||
"desc": "When dodging a nearby enemy attack, get 30% chance to instantly attack back",
|
||||
"desc": "Gain a 30% chance to take no damage and instantly attack back when dodging an enemy attack with Agility.",
|
||||
"archetype": "Battle Monk",
|
||||
"parents": ["Aerodynamics", "Cheaper Uppercut", "Manachism"],
|
||||
"dependencies": [],
|
||||
|
@ -3990,7 +3988,7 @@ const atrees = {
|
|||
},
|
||||
{
|
||||
"display_name": "Sacred Surge",
|
||||
"desc": "Gain the ability to unleash a Sacred Surge. Whenever any of your spells or abilities are triggered, increase your holy power by 1%. Bash and Uppercut will spend 20% of Sacred Surge to smite enemies with holy energy, dealing extra damage.",
|
||||
"desc": "Gain the ability to unleash a Sacred Surge. Whenever any of your spells or abilities are triggered, increase your holy power by 1%. Bash and Uppercut will spend 25% of Sacred Surge to smite enemies with holy energy, dealing extra damage.",
|
||||
"archetype": "Paladin",
|
||||
"archetype_req": 5,
|
||||
"parents": ["Stronger Mantle", "Provoke"],
|
||||
|
@ -4031,14 +4029,23 @@ const atrees = {
|
|||
"col": 1,
|
||||
"icon": "node_1"
|
||||
},
|
||||
"properties": {},
|
||||
"properties": {
|
||||
"duration": 3,
|
||||
"rate": 2.5
|
||||
},
|
||||
"effects": [
|
||||
{
|
||||
"type": "add_spell_prop",
|
||||
"base_spell": 1,
|
||||
"target_part": "Boiling Blood",
|
||||
"target_part": "Boiling Blood Tick",
|
||||
"cost": 0,
|
||||
"multipliers": [25, 0, 0, 0, 5, 0]
|
||||
},
|
||||
{
|
||||
"type": "add_spell_prop",
|
||||
"base_spell": 1,
|
||||
"target_part": "Boiling Blood DPS",
|
||||
"hits": { "Boiling Blood Tick": "Bash.rate" }
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -4542,7 +4549,7 @@ const atrees = {
|
|||
"type": "add_spell_prop",
|
||||
"base_spell": 4,
|
||||
"target_part": "Total Damage",
|
||||
"hits": { "Tempest": 3 }
|
||||
"hits": { "Tempest Total Damage": 1 }
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -5856,7 +5863,8 @@ const atrees = {
|
|||
"dependencies": [ "Heal" ],
|
||||
"blockers": [
|
||||
"Larger Heal",
|
||||
"Orphion's Pulse"
|
||||
"Orphion's Pulse",
|
||||
"Timelock"
|
||||
],
|
||||
"cost": 2,
|
||||
"display": {
|
||||
|
@ -7258,7 +7266,7 @@ const atrees = {
|
|||
"More Winded II"
|
||||
],
|
||||
"dependencies": [],
|
||||
"blockers": [],
|
||||
"blockers": ["Arcane Transfer"],
|
||||
"cost": 2,
|
||||
"display": {
|
||||
"row": 34,
|
||||
|
@ -8088,15 +8096,9 @@ const atrees = {
|
|||
{
|
||||
"type": "add_spell_prop",
|
||||
"base_spell": 4,
|
||||
"behavior": "modify",
|
||||
"target_part": "Per Tick",
|
||||
"multipliers": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
10,
|
||||
0
|
||||
]
|
||||
"multipliers": [0, 0, 0, 0, 10, 0]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -8320,23 +8322,16 @@ const atrees = {
|
|||
{
|
||||
"type": "add_spell_prop",
|
||||
"base_spell": 4,
|
||||
"behavior": "modify",
|
||||
"target_part": "Total Damage",
|
||||
"hits": {
|
||||
"Per Bomb": 2
|
||||
}
|
||||
"hits": { "Per Bomb": 2 }
|
||||
},
|
||||
{
|
||||
"type": "add_spell_prop",
|
||||
"base_spell": 4,
|
||||
"behavior": "modify",
|
||||
"target_part": "Per Tick",
|
||||
"multipliers": [
|
||||
-10,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
"multipliers": [ -10, 0, 0, 0, 0, 0 ]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -8869,13 +8864,17 @@ const atrees = {
|
|||
"type": "stat",
|
||||
"name": "damMult.EchoCast:4.Per Tick"
|
||||
},
|
||||
{
|
||||
"type": "stat",
|
||||
"name": "damMult.EchoCast:4.Single Bomb"
|
||||
},
|
||||
{
|
||||
"type": "stat",
|
||||
"name": "damMult.EchoCast:6.Per Shuriken"
|
||||
}
|
||||
],
|
||||
"scaling": [
|
||||
100, 100, 100, 100, 100, 100, 100
|
||||
100
|
||||
]
|
||||
}
|
||||
]
|
||||
|
@ -10626,6 +10625,7 @@ const atrees = {
|
|||
"slider_name": "Active Puppets",
|
||||
"slider_step": 1,
|
||||
"slider_max": 3,
|
||||
"slider_default": 3,
|
||||
"output": [
|
||||
{
|
||||
"type": "prop",
|
||||
|
@ -10835,6 +10835,7 @@ const atrees = {
|
|||
"slider": true,
|
||||
"slider_name": "Active Puppets",
|
||||
"slider_max": 1,
|
||||
"slider_default": 1,
|
||||
"output": [
|
||||
{
|
||||
"type": "prop",
|
||||
|
@ -11001,7 +11002,7 @@ const atrees = {
|
|||
"bonuses": [
|
||||
{
|
||||
"type": "stat",
|
||||
"name": "damMult.Bullwhip:5.Puppet Hit",
|
||||
"name": "damMult.Bullwhip:6.Puppet Hit",
|
||||
"value": 20
|
||||
},
|
||||
{
|
||||
|
@ -11034,6 +11035,7 @@ const atrees = {
|
|||
"slider": true,
|
||||
"slider_name": "Active Puppets",
|
||||
"slider_max": 2,
|
||||
"slider_default": 2,
|
||||
"output": [
|
||||
{
|
||||
"type": "prop",
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -34,7 +34,8 @@ const wynn_version_names = [
|
|||
'2.0.2.3',
|
||||
'2.0.3.1',
|
||||
'2.0.4.1',
|
||||
'2.0.4.3'
|
||||
'2.0.4.3',
|
||||
'2.0.4.4'
|
||||
];
|
||||
const WYNN_VERSION_LATEST = wynn_version_names.length - 1;
|
||||
// Default to the newest version.
|
||||
|
@ -66,7 +67,7 @@ async function parse_hash(url_tag) {
|
|||
}
|
||||
//default values
|
||||
let equipment = [null, null, null, null, null, null, null, null, null];
|
||||
let tomes = [null, null, null, null, null, null, null];
|
||||
let tomes = [null, null, null, null, null, null, null, null];
|
||||
let powdering = ["", "", "", "", ""];
|
||||
let info = url_tag.split("_");
|
||||
let version = info[0];
|
||||
|
@ -151,7 +152,7 @@ async function parse_hash(url_tag) {
|
|||
}
|
||||
data_str = info_str.slice(start_idx);
|
||||
}
|
||||
else if (version_number <= 8) {
|
||||
else if (version_number <= 9) {
|
||||
let info_str = data_str;
|
||||
let start_idx = 0;
|
||||
for (let i = 0; i < 9; ++i ) {
|
||||
|
@ -192,7 +193,7 @@ async function parse_hash(url_tag) {
|
|||
let powder_info = data_str.slice(10);
|
||||
let res = parsePowdering(powder_info);
|
||||
powdering = res[0];
|
||||
} else if (version_number <= 8){
|
||||
} else if (version_number <= 9){
|
||||
level = Base64.toInt(data_str.slice(10,12));
|
||||
setValue("level-choice",level);
|
||||
save_skp = true;
|
||||
|
@ -211,7 +212,7 @@ async function parse_hash(url_tag) {
|
|||
if (version_number >= 6) {
|
||||
//tome values do not appear in anything before v6.
|
||||
if (version_number < 8) {
|
||||
for (let i in tomes) {
|
||||
for (let i = 0; i < 7; ++i) {
|
||||
let tome_str = data_str.charAt(i);
|
||||
let tome_name = getTomeNameFromID(Base64.toInt(tome_str));
|
||||
setValue(tomeInputs[i], tome_name);
|
||||
|
@ -220,7 +221,16 @@ async function parse_hash(url_tag) {
|
|||
}
|
||||
else {
|
||||
// 2chr tome encoding to allow for more tomes.
|
||||
for (let i in tomes) {
|
||||
|
||||
// Lootrun tome was added in v9.
|
||||
let num_tomes = 7;
|
||||
if (version_number <= 8) {
|
||||
num_tomes = 7;
|
||||
}
|
||||
else {
|
||||
num_tomes = 8;
|
||||
}
|
||||
for (let i = 0; i < num_tomes; ++i) {
|
||||
let tome_str = data_str.slice(2*i, 2*i+2);
|
||||
let tome_name = getTomeNameFromID(Base64.toInt(tome_str));
|
||||
setValue(tomeInputs[i], tome_name);
|
||||
|
@ -257,7 +267,8 @@ function encodeBuild(build, powders, skillpoints, atree, atree_state) {
|
|||
//V6 encoding - Tomes
|
||||
//V7 encoding - ATree
|
||||
//V8 encoding - wynn version
|
||||
build_version = 8;
|
||||
//V9 encoding - lootrun tome
|
||||
build_version = 9;
|
||||
build_string = "";
|
||||
tome_string = "";
|
||||
|
||||
|
|
|
@ -60,6 +60,7 @@ let tome_fields = [
|
|||
"armorTome3",
|
||||
"armorTome4",
|
||||
"guildTome1",
|
||||
"lootrunTome1"
|
||||
]
|
||||
let equipment_names = [
|
||||
"Helmet",
|
||||
|
@ -99,7 +100,7 @@ let armor_keys = ['helmet', 'chestplate', 'leggings', 'boots'];
|
|||
let accessory_keys= ['ring1', 'ring2', 'bracelet', 'necklace'];
|
||||
let powderable_keys = ['helmet', 'chestplate', 'leggings', 'boots', 'weapon'];
|
||||
let equipment_keys = ['helmet', 'chestplate', 'leggings', 'boots', 'ring1', 'ring2', 'bracelet', 'necklace', 'weapon'];
|
||||
let tome_keys = ['weaponTome1', 'weaponTome2', 'armorTome1', 'armorTome2', 'armorTome3', 'armorTome4', 'guildTome1'];
|
||||
let tome_keys = ['weaponTome1', 'weaponTome2', 'armorTome1', 'armorTome2', 'armorTome3', 'armorTome4', 'guildTome1', 'lootrunTome1'];
|
||||
|
||||
let spell_disp = ['build-melee-stats', 'spell0-info', 'spell1-info', 'spell2-info', 'spell3-info'];
|
||||
let other_disp = ['build-order', 'set-info', 'int-info'];
|
||||
|
|
|
@ -413,8 +413,10 @@ class BuildAssembleNode extends ComputeNode {
|
|||
input_map.get('armorTome2'),
|
||||
input_map.get('armorTome3'),
|
||||
input_map.get('armorTome4'),
|
||||
input_map.get('guildTome1')
|
||||
input_map.get('guildTome1'),
|
||||
input_map.get('lootrunTome1')
|
||||
];
|
||||
console.log(equipments);
|
||||
let weapon = input_map.get('weapon');
|
||||
let level = parseInt(input_map.get('level-input'));
|
||||
if (isNaN(level)) {
|
||||
|
@ -537,7 +539,7 @@ function getDefenseStats(stats) {
|
|||
//eledefs - TODO POWDERS
|
||||
let eledefs = [0, 0, 0, 0, 0];
|
||||
for(const i in skp_elements){ //kinda jank but ok
|
||||
eledefs[i] = rawToPct(stats.get(skp_elements[i] + "Def"), stats.get(skp_elements[i] + "DefPct")/100.);
|
||||
eledefs[i] = rawToPct(stats.get(skp_elements[i] + "Def"), (stats.get(skp_elements[i] + "DefPct") + stats.get("rDefPct"))/100.);
|
||||
}
|
||||
defenseStats.push(eledefs);
|
||||
|
||||
|
@ -1072,7 +1074,7 @@ function builder_graph_init(save_skp) {
|
|||
build_node.link_to(item_input, eq);
|
||||
}
|
||||
|
||||
for (const [eq, none_item] of zip2(tome_fields, [none_tomes[0], none_tomes[0], none_tomes[1], none_tomes[1], none_tomes[1], none_tomes[1], none_tomes[2]])) {
|
||||
for (const [eq, none_item] of zip2(tome_fields, [none_tomes[0], none_tomes[0], none_tomes[1], none_tomes[1], none_tomes[1], none_tomes[1], none_tomes[2], none_tomes[3]])) {
|
||||
let input_field = document.getElementById(eq+"-choice");
|
||||
let item_image = document.getElementById(eq+"-img");
|
||||
|
||||
|
|
|
@ -160,24 +160,31 @@
|
|||
},
|
||||
"CHERRY_BOMBS": {
|
||||
"displayName": "Cherry Bombs",
|
||||
"description": "Your Smoke Bombs explode instantly, and increase their Neutral Damage by +90%",
|
||||
"description": "Turn Smoke Bomb into three firecrackers that fly farther, tighter, and deal high damage instantly",
|
||||
"abilities": [{
|
||||
"class": "Assassin",
|
||||
"base_abil": "Smoke Bomb",
|
||||
"effects": [
|
||||
{
|
||||
"type": "add_spell_prop",
|
||||
"base_spell": 4,
|
||||
"target_part": "Per Tick",
|
||||
"multipliers": [ 90, 0, 0, 0, 0, 0 ]
|
||||
},
|
||||
{
|
||||
"type": "add_spell_prop",
|
||||
"base_spell": 4,
|
||||
"target_part": "Per Bomb",
|
||||
"hits": { "Per Tick": -9 }
|
||||
}
|
||||
]
|
||||
"effects": [{
|
||||
"type": "replace_spell",
|
||||
"name": "Cherry Bomb",
|
||||
"cost": 35,
|
||||
"base_spell": 4,
|
||||
"display": "Total Damage",
|
||||
"parts": [
|
||||
{
|
||||
"name": "Single Bomb",
|
||||
"type": "damage",
|
||||
"multipliers": [95, 40, 0, 0, 0, 40]
|
||||
},
|
||||
{
|
||||
"name": "Total Damage",
|
||||
"type": "total",
|
||||
"hits": {
|
||||
"Single Bomb": 3
|
||||
}
|
||||
}
|
||||
]
|
||||
}]
|
||||
}]
|
||||
},
|
||||
"FREERUNNER": {
|
||||
|
@ -230,7 +237,7 @@
|
|||
},
|
||||
"TEMBLOR": {
|
||||
"displayName": "Temblor",
|
||||
"description": "Bash gains +1 Area of Effect and is 20% faster.",
|
||||
"description": "Bash gains +1 Area of Effect and is 25% faster.",
|
||||
"abilities": [{
|
||||
"class": "Warrior",
|
||||
"base_abil": "Bash",
|
||||
|
@ -240,31 +247,25 @@
|
|||
},
|
||||
"RECKLESS_ABANDON": {
|
||||
"displayName": "Reckless Abandon",
|
||||
"description": "Tempest deals +15% Fire damage and gains one additional charge. War Scream no longer grants a defence bonus.",
|
||||
"description": "Sacrifice War Scream's defense bonus to give Tempest two extra hits, extra damage, and extra speed",
|
||||
"abilities": [{
|
||||
"class": "Warrior",
|
||||
"base_abil": "War Scream",
|
||||
"dependencies": [ "Tempest" ],
|
||||
"effects": [
|
||||
{
|
||||
"type": "add_spell_prop",
|
||||
"base_spell": 4,
|
||||
"target_part": "Tempest",
|
||||
"behavior": "modify",
|
||||
"multipliers": [0, 0, 0, 0, 15, 0]
|
||||
"multipliers": [0, 5, 0, 0, 15, 5]
|
||||
},
|
||||
{
|
||||
"type": "add_spell_prop",
|
||||
"base_spell": 4,
|
||||
"target_part": "Tempest Total Damage",
|
||||
"behavior": "modify",
|
||||
"hits": { "Tempest": 1 }
|
||||
},
|
||||
{
|
||||
"type": "add_spell_prop",
|
||||
"base_spell": 4,
|
||||
"target_part": "Total Damage",
|
||||
"behavior": "modify",
|
||||
"hits": { "Tempest": 1 }
|
||||
"hits": { "Tempest": 2 }
|
||||
}
|
||||
]
|
||||
}]
|
||||
|
@ -528,5 +529,73 @@
|
|||
"displayName": "Windsurf",
|
||||
"description":"Righting Reflex lasts twice as long and is affected stronger by movement speed",
|
||||
"abilities": []
|
||||
},
|
||||
"HELLFIRE": {
|
||||
"displayName": "Hellfire",
|
||||
"description":"Boiling Blood has no cooldown, is stronger, and does not slow. Cuts Bash's power and disables Discombobulate",
|
||||
"abilities": [{
|
||||
"class": "Warrior",
|
||||
"base_abil": "Bash",
|
||||
"dependencies": [ "Boiling Blood" ],
|
||||
"properties": {
|
||||
"rate": 0.8333333333333333333333333333,
|
||||
"num_bloods": 0
|
||||
},
|
||||
"effects": [
|
||||
{
|
||||
"type": "add_spell_prop",
|
||||
"base_spell": 1,
|
||||
"target_part": "Single Hit",
|
||||
"behavior": "modify",
|
||||
"multipliers": [ -85, -30, 0, 0, 0, 0 ]
|
||||
},
|
||||
{
|
||||
"type": "add_spell_prop",
|
||||
"base_spell": 1,
|
||||
"target_part": "Boiling Blood Tick",
|
||||
"behavior": "modify",
|
||||
"multipliers": [ -25, 0, 0, 0, 30, 0 ]
|
||||
},
|
||||
{
|
||||
"type": "add_spell_prop",
|
||||
"base_spell": 1,
|
||||
"target_part": "Boiling Blood DPS (Total)",
|
||||
"behavior": "merge",
|
||||
"display": "Boiling Blood DPS (Total)",
|
||||
"hits": { "Boiling Blood DPS": "Bash.num_bloods" }
|
||||
},
|
||||
{
|
||||
"type": "stat_scaling",
|
||||
"slider": true,
|
||||
"slider_name": "Boiling Blood Stacks",
|
||||
"slider_step": 1,
|
||||
"slider_max": 20,
|
||||
"slider_default": 4,
|
||||
"output": [
|
||||
{
|
||||
"type": "prop",
|
||||
"abil": "Bash",
|
||||
"name": "num_bloods"
|
||||
}
|
||||
],
|
||||
"scaling": [1]
|
||||
},
|
||||
{
|
||||
"type": "stat_scaling",
|
||||
"slider": true,
|
||||
"behavior": "modify",
|
||||
"slider_name": "Hits dealt",
|
||||
"output": [
|
||||
{ "type": "stat", "name": "nDamAddMin" }, { "type": "stat", "name": "nDamAddMax" },
|
||||
{ "type": "stat", "name": "eDamAddMin" }, { "type": "stat", "name": "eDamAddMax" },
|
||||
{ "type": "stat", "name": "tDamAddMin" }, { "type": "stat", "name": "tDamAddMax" },
|
||||
{ "type": "stat", "name": "wDamAddMin" }, { "type": "stat", "name": "wDamAddMax" },
|
||||
{ "type": "stat", "name": "fDamAddMin" }, { "type": "stat", "name": "fDamAddMax" },
|
||||
{ "type": "stat", "name": "aDamAddMin" }, { "type": "stat", "name": "aDamAddMax" }
|
||||
],
|
||||
"scaling": [-5]
|
||||
}
|
||||
]
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -180,7 +180,6 @@ class Craft{
|
|||
/* Change certain IDs based on material tier.
|
||||
healthOrDamage changes.
|
||||
duration and durability change. (but not basicDuration)
|
||||
|
||||
*/
|
||||
let matmult = 1;
|
||||
let tierToMult = [0,1,1.25,1.4];
|
||||
|
|
|
@ -466,7 +466,6 @@ function displayExpandedItem(item, parent_id){
|
|||
if (item.get("tier") && item.get("tier") !== " ") {
|
||||
let item_desc_elem = make_elem("div", ["col", item.get("tier")]);
|
||||
if (tome_types.includes(item.get("type"))) {
|
||||
tome_type_map = new Map([["weaponTome", "Weapon Tome"],["armorTome", "Armor Tome"],["guildTome", "Guild Tome"]]);
|
||||
item_desc_elem.textContent = item.get("tier")+" "+tome_type_map.get(item.get("type"));
|
||||
} else {
|
||||
item_desc_elem.textContent = item.get("tier")+" "+item.get("type");
|
||||
|
@ -496,7 +495,7 @@ function displayExpandedItem(item, parent_id){
|
|||
base_dps_elem.textContent = "Base DPS: "+base_dps_min.toFixed(3)+"\u279c"+base_dps_max.toFixed(3);
|
||||
}
|
||||
else {
|
||||
base_dps_elem.textContent = "Base DPS: "+(total_damages);
|
||||
base_dps_elem.textContent = "Base DPS: "+(total_damages.toFixed(3));
|
||||
}
|
||||
parent_div.append(make_elem("p"), base_dps_elem);
|
||||
}
|
||||
|
@ -1181,14 +1180,6 @@ function displayDefenseStats(parent_elem, statMap, insertSummary){
|
|||
boost.classList.add(eledefs[i] >= 0 ? "positive" : "negative");
|
||||
boost.classList.add("col");
|
||||
boost.classList.add("text-end");
|
||||
|
||||
let defRaw = statMap.get(skp_elements[i]+"Def");
|
||||
let defPct = (statMap.get(skp_elements[i]+"DefPct") + statMap.get('rDefPct'))/100;
|
||||
if (defRaw < 0) {
|
||||
defPct >= 0 ? defPct = "- " + defPct: defPct = "+ " + defPct;
|
||||
} else {
|
||||
defPct >= 0 ? defPct = "+ " + defPct: defPct = "- " + defPct;
|
||||
}
|
||||
eledefElemRow.appendChild(boost);
|
||||
|
||||
if (insertSummary) {
|
||||
|
|
|
@ -335,7 +335,9 @@ let build_detailed_display_commands = [
|
|||
"fMdPct", "wMdPct", "aMdPct", "tMdPct", "eMdPct",
|
||||
"fDamRaw", "wDamRaw", "aDamRaw", "tDamRaw", "eDamRaw",
|
||||
"fDamPct", "wDamPct", "aDamPct", "tDamPct", "eDamPct",
|
||||
"fDefPct", "wDefPct", "aDefPct", "tDefPct", "eDefPct",
|
||||
"!elemental",
|
||||
"rDefPct",
|
||||
"spPct1", "spRaw1", "spPct2", "spRaw2", "spPct3", "spRaw3", "spPct4", "spRaw4",
|
||||
"atkTier",
|
||||
"poison",
|
||||
|
@ -429,6 +431,8 @@ let sq2_item_display_commands = [
|
|||
"fDamPct", "wDamPct", "aDamPct", "tDamPct", "eDamPct",
|
||||
"fDefPct", "wDefPct", "aDefPct", "tDefPct", "eDefPct",
|
||||
"!elemental",
|
||||
"rDefPct",
|
||||
|
||||
"spPct1", "spRaw1", "spPct2", "spRaw2", "spPct3", "spRaw3", "spPct4", "spRaw4",
|
||||
"sprint", "sprintReg",
|
||||
"jh",
|
||||
|
|
|
@ -60,7 +60,8 @@ function toggleAmps(button_id) {
|
|||
|
||||
|
||||
(async function() {
|
||||
let load_promises = [ load_init() ];
|
||||
let latest_ver_name = wynn_version_names[WYNN_VERSION_LATEST];
|
||||
let load_promises = [ load_init(), load_major_id_data(latest_ver_name) ];
|
||||
await Promise.all(load_promises);
|
||||
init_itempage();
|
||||
})();
|
||||
|
|
414
js/item_display.js
Normal file
414
js/item_display.js
Normal file
|
@ -0,0 +1,414 @@
|
|||
/*
|
||||
* File for display commands specific to the single item page.
|
||||
*/
|
||||
|
||||
/** Displays the ID costs of an item
|
||||
*
|
||||
* @param {String} elemID - the id of the parent element.
|
||||
* @param {Map} item - the statMap of an item.
|
||||
*/
|
||||
function displayIDCosts(elemID, item) {
|
||||
let parent_elem = document.getElementById(elemID);
|
||||
let tier = item.get("tier");
|
||||
if ( (item.has("fixID") && item.get("fixID")) || ["Normal","Crafted","Custom","none", " ",].includes(item.get("tier"))) {
|
||||
return;
|
||||
} else {
|
||||
/** Returns the number of inventory slots minimum an amount of emeralds would take up + the configuration of doing so.
|
||||
* Returns an array of [invSpace, E, EB, LE, Stx LE]
|
||||
*
|
||||
* @param {number} ems - the total numerical value of emeralds to compact.
|
||||
*/
|
||||
function emsToInvSpace(ems) {
|
||||
let stx = Math.floor(ems/262144);
|
||||
ems -= stx*4096*64;
|
||||
let LE = Math.floor(ems/4096);
|
||||
ems -= LE*4096;
|
||||
let EB = Math.floor(ems/64);
|
||||
ems -= EB*64;
|
||||
let e = ems;
|
||||
return [ stx + Math.ceil(LE/64) + Math.ceil(EB/64) + Math.ceil(e/64) , e, EB, LE, stx];
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param {String} tier - item tier
|
||||
* @param {Number} lvl - item level
|
||||
*/
|
||||
function getIDCost(tier, lvl) {
|
||||
switch (tier) {
|
||||
case "Unique":
|
||||
return Math.round(0.5*lvl + 3);
|
||||
case "Rare":
|
||||
return Math.round(1.2*lvl + 8);
|
||||
case "Legendary":
|
||||
return Math.round(4.5*lvl + 12);
|
||||
case "Fabled":
|
||||
return Math.round(12*lvl + 26);
|
||||
case "Mythic":
|
||||
return Math.round(18*lvl + 90);
|
||||
case "Set":
|
||||
return Math.round(1.5*lvl + 8)
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
parent_elem.style = "display: visible";
|
||||
let lvl = item.get("lvl");
|
||||
if (typeof(lvl) === "string") { lvl = parseFloat(lvl); }
|
||||
|
||||
let title_elem = document.createElement("p");
|
||||
title_elem.classList.add("smalltitle");
|
||||
title_elem.style.color = "white";
|
||||
title_elem.textContent = "Identification Costs";
|
||||
parent_elem.appendChild(title_elem);
|
||||
parent_elem.appendChild(document.createElement("br"));
|
||||
|
||||
let grid_item = document.createElement("div");
|
||||
grid_item.style.display = "flex";
|
||||
grid_item.style.flexDirection = "rows";
|
||||
grid_item.style.flexWrap = "wrap";
|
||||
grid_item.style.gap = "5px";
|
||||
parent_elem.appendChild(grid_item);
|
||||
|
||||
let IDcost = getIDCost(tier, lvl);
|
||||
let initIDcost = IDcost;
|
||||
let invSpace = emsToInvSpace(IDcost);
|
||||
let rerolls = 0;
|
||||
|
||||
while(invSpace[0] <= 28 && IDcost > 0) {
|
||||
let container = document.createElement("div");
|
||||
container.classList.add("container");
|
||||
container.style = "grid-item-" + (rerolls+1);
|
||||
container.style.maxWidth = "max(120px, 15%)";
|
||||
|
||||
let container_title = document.createElement("p");
|
||||
container_title.style.color = "white";
|
||||
if (rerolls == 0) {
|
||||
container_title.textContent = "Initial ID Cost: ";
|
||||
} else {
|
||||
container_title.textContent = "Reroll to [" + (rerolls+1) + "] Cost:";
|
||||
}
|
||||
container.appendChild(container_title);
|
||||
let total_cost_container = document.createElement("p");
|
||||
let total_cost_number = document.createElement("b");
|
||||
total_cost_number.classList.add("Set");
|
||||
total_cost_number.textContent = IDcost + " ";
|
||||
let total_cost_suffix = document.createElement("b");
|
||||
total_cost_suffix.textContent = "emeralds."
|
||||
total_cost_container.appendChild(total_cost_number);
|
||||
total_cost_container.appendChild(total_cost_suffix);
|
||||
container.appendChild(total_cost_container);
|
||||
|
||||
let OR = document.createElement("p");
|
||||
OR.classList.add("center");
|
||||
OR.textContent = "OR";
|
||||
container.appendChild(OR);
|
||||
|
||||
let esuffixes = ["", "emeralds.", "EB.", "LE.", "stacks of LE."];
|
||||
for (let i = 4; i > 0; i--) {
|
||||
let n_container = document.createElement("p");
|
||||
let n_number = document.createElement("b");
|
||||
n_number.classList.add("Set");
|
||||
n_number.textContent = invSpace[i] + " ";
|
||||
let n_suffix = document.createElement("b");
|
||||
n_suffix.textContent = esuffixes[i];
|
||||
n_container.appendChild(n_number);
|
||||
n_container.appendChild(n_suffix);
|
||||
container.appendChild(n_container);
|
||||
}
|
||||
grid_item.appendChild(container);
|
||||
|
||||
rerolls += 1;
|
||||
IDcost = Math.round(initIDcost * (5 ** rerolls));
|
||||
invSpace = emsToInvSpace(IDcost);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Displays Additional Info for
|
||||
*
|
||||
* @param {String} elemID - the parent element's id
|
||||
* @param {Map} item - the statMap of the item
|
||||
* @returns
|
||||
*/
|
||||
function displayAdditionalInfo(elemID, item) {
|
||||
let parent_elem = document.getElementById(elemID);
|
||||
parent_elem.classList.add("left");
|
||||
|
||||
let droptype_elem = document.createElement("div");
|
||||
droptype_elem.classList.add("container");
|
||||
droptype_elem.style.marginBottom = "5px";
|
||||
droptype_elem.textContent = "Drop type: " + (item.has("drop") ? item.get("drop"): "NEVER");
|
||||
parent_elem.appendChild(droptype_elem);
|
||||
|
||||
let warning_elem = document.createElement("div");
|
||||
warning_elem.classList.add("container");
|
||||
warning_elem.style.marginBottom ="5px";
|
||||
warning_elem.textContent = "This page is incomplete. Will work on it later.";
|
||||
parent_elem.appendChild(warning_elem);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/** Displays the individual probabilities of each possible value of each rollable ID for this item.
|
||||
*
|
||||
* @param {String} parent_id the document id of the parent element
|
||||
* @param {String} item expandedItem object
|
||||
* @param {String} amp the level of corkian amplifier used. 0 means no amp, 1 means Corkian Amplifier I, etc. [0,3]
|
||||
*/
|
||||
function displayIDProbabilities(parent_id, item, amp) {
|
||||
if (item.has("fixID") && item.get("fixID")) {return}
|
||||
let parent_elem = document.getElementById(parent_id);
|
||||
parent_elem.style.display = "";
|
||||
parent_elem.innerHTML = "";
|
||||
let title_elem = document.createElement("p");
|
||||
title_elem.textContent = "Identification Probabilities";
|
||||
title_elem.id = "ID_PROB_TITLE";
|
||||
title_elem.classList.add("Legendary");
|
||||
title_elem.classList.add("title");
|
||||
parent_elem.appendChild(title_elem);
|
||||
|
||||
let disclaimer_elem = document.createElement("p");
|
||||
disclaimer_elem.textContent = "IDs are rolled on a uniform distribution. A chance of 0% means that either the minimum or maximum possible multiplier must be rolled to get this value."
|
||||
parent_elem.appendChild(disclaimer_elem);
|
||||
|
||||
let amp_row = document.createElement("p");
|
||||
amp_row.id = "amp_row";
|
||||
let amp_text = document.createElement("b");
|
||||
amp_text.textContent = "Corkian Amplifier Used: "
|
||||
amp_row.appendChild(amp_text);
|
||||
let amp_1 = document.createElement("button");
|
||||
amp_1.id = "cork_amp_1";
|
||||
amp_1.textContent = "I";
|
||||
amp_row.appendChild(amp_1);
|
||||
let amp_2 = document.createElement("button");
|
||||
amp_2.id = "cork_amp_2";
|
||||
amp_2.textContent = "II";
|
||||
amp_row.appendChild(amp_2);
|
||||
let amp_3 = document.createElement("button");
|
||||
amp_3.id = "cork_amp_3";
|
||||
amp_3.textContent = "III";
|
||||
amp_row.appendChild(amp_3);
|
||||
amp_1.addEventListener("click", (event) => {toggleAmps(1)});
|
||||
amp_2.addEventListener("click", (event) => {toggleAmps(2)});
|
||||
amp_3.addEventListener("click", (event) => {toggleAmps(3)});
|
||||
parent_elem.appendChild(amp_row);
|
||||
|
||||
if (amp != 0) {toggleButton("cork_amp_" + amp)}
|
||||
|
||||
let item_name = item.get("displayName");
|
||||
console.log(itemMap.get(item_name))
|
||||
|
||||
let table_elem = document.createElement("table");
|
||||
parent_elem.appendChild(table_elem);
|
||||
for (const [id,val] of Object.entries(itemMap.get(item_name))) {
|
||||
if (rolledIDs.includes(id)) {
|
||||
if (!item.get("maxRolls").get(id)) { continue; }
|
||||
let min = item.get("minRolls").get(id);
|
||||
let max = item.get("maxRolls").get(id);
|
||||
//Apply corkian amps
|
||||
if (val > 0) {
|
||||
let base = itemMap.get(item_name)[id];
|
||||
if (reversedIDs.includes(id)) {max = Math.max( Math.round((0.3 + 0.05*amp) * base), 1)}
|
||||
else {min = Math.max( Math.round((0.3 + 0.05*amp) * base), 1)}
|
||||
}
|
||||
|
||||
let row_title = document.createElement("tr");
|
||||
//row_title.style.textAlign = "left";
|
||||
let title_left = document.createElement("td");
|
||||
let left_elem = document.createElement("p");
|
||||
let left_val_title = document.createElement("b");
|
||||
let left_val_elem = document.createElement("b");
|
||||
title_left.style.textAlign = "left";
|
||||
left_val_title.textContent = idPrefixes[id] + "Base ";
|
||||
left_val_elem.textContent = val + idSuffixes[id];
|
||||
if (val > 0 == !reversedIDs.includes(id)) {
|
||||
left_val_elem.classList.add("positive");
|
||||
} else if (val > 0 == reversedIDs.includes(id)) {
|
||||
left_val_elem.classList.add("negative");
|
||||
}
|
||||
left_elem.appendChild(left_val_title);
|
||||
left_elem.appendChild(left_val_elem);
|
||||
title_left.appendChild(left_elem);
|
||||
row_title.appendChild(title_left);
|
||||
|
||||
let title_right = document.createElement("td");
|
||||
let title_right_text = document.createElement("b");
|
||||
title_right.style.textAlign = "left";
|
||||
title_right_text.textContent = "[ " + min + idSuffixes[id] + ", " + max + idSuffixes[id] + " ]";
|
||||
if ( (min > 0 && max > 0 && !reversedIDs.includes(id)) || (min < 0 && max < 0 && reversedIDs.includes(id)) ) {
|
||||
title_right_text.classList.add("positive");
|
||||
} else if ( (min < 0 && max < 0 && !reversedIDs.includes(id)) || (min > 0 && max > 0 && reversedIDs.includes(id)) ) {
|
||||
title_right_text.classList.add("negative");
|
||||
}
|
||||
title_right.appendChild(title_right_text);
|
||||
|
||||
let title_input = document.createElement("td");
|
||||
let title_input_slider = document.createElement("input");
|
||||
title_input_slider.type = "range";
|
||||
title_input_slider.id = id+"-slider";
|
||||
if (!reversedIDs.includes(id)) {
|
||||
title_input_slider.step = 1;
|
||||
title_input_slider.min = `${min}`;
|
||||
title_input_slider.max = `${max}`;
|
||||
title_input_slider.value = `${max}`;
|
||||
} else {
|
||||
title_input_slider.step = 1;
|
||||
title_input_slider.min = `${-1*min}`;
|
||||
title_input_slider.max = `${-1*max}`;
|
||||
title_input_slider.value = `${-1*max}`;
|
||||
}
|
||||
let title_input_textbox = document.createElement("input");
|
||||
title_input_textbox.type = "text";
|
||||
title_input_textbox.value = `${max}`;
|
||||
title_input_textbox.id = id+"-textbox";
|
||||
title_input_textbox.classList.add("small-input");
|
||||
title_input.appendChild(title_input_slider);
|
||||
title_input.appendChild(title_input_textbox);
|
||||
|
||||
row_title.appendChild(title_left);
|
||||
row_title.appendChild(title_right);
|
||||
row_title.appendChild(title_input);
|
||||
|
||||
let row_chances = document.createElement("tr");
|
||||
let chance_cdf = document.createElement("td");
|
||||
let chance_pdf = document.createElement("td");
|
||||
let cdf_p = document.createElement("p");
|
||||
cdf_p.id = id+"-cdf";
|
||||
let pdf_p = document.createElement("p");
|
||||
pdf_p.id = id+"-pdf";
|
||||
|
||||
chance_cdf.appendChild(cdf_p);
|
||||
chance_pdf.appendChild(pdf_p);
|
||||
row_chances.appendChild(chance_cdf);
|
||||
row_chances.appendChild(chance_pdf);
|
||||
|
||||
table_elem.appendChild(row_title);
|
||||
table_elem.appendChild(row_chances);
|
||||
|
||||
|
||||
|
||||
stringPDF(id, max, val, amp); //val is base roll
|
||||
stringCDF(id, max, val, amp); //val is base roll
|
||||
title_input_slider.addEventListener("change", (event) => {
|
||||
let id_name = event.target.id.split("-")[0];
|
||||
let textbox_elem = document.getElementById(id_name+"-textbox");
|
||||
|
||||
if (reversedIDs.includes(id_name)) {
|
||||
if (event.target.value < -1*min) { event.target.value = -1*min}
|
||||
if (event.target.value > -1*max) { event.target.value = -1*max}
|
||||
stringPDF(id_name, -1*event.target.value, val, amp); //val is base roll
|
||||
stringCDF(id_name, -1*event.target.value, val, amp); //val is base roll
|
||||
} else {
|
||||
if (event.target.value < min) { event.target.value = min}
|
||||
if (event.target.value > max) { event.target.value = max}
|
||||
stringPDF(id_name, 1*event.target.value, val, amp); //val is base roll
|
||||
stringCDF(id_name, 1*event.target.value, val, amp); //val is base roll
|
||||
}
|
||||
|
||||
if (textbox_elem && textbox_elem.value !== event.target.value) {
|
||||
if (reversedIDs.includes(id_name)) {
|
||||
textbox_elem.value = -event.target.value;
|
||||
} else {
|
||||
textbox_elem.value = event.target.value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
title_input_textbox.addEventListener("change", (event) => {
|
||||
let id_name = event.target.id.split("-")[0];
|
||||
if (reversedIDs.includes(id_name)) {
|
||||
if (event.target.value > min) { event.target.value = min}
|
||||
if (event.target.value < max) { event.target.value = max}
|
||||
} else {
|
||||
if (event.target.value < min) { event.target.value = min}
|
||||
if (event.target.value > max) { event.target.value = max}
|
||||
}
|
||||
let slider_elem = document.getElementById(id_name+"-slider");
|
||||
if (slider_elem.value !== event.target.value) {
|
||||
slider_elem.value = -event.target.value;
|
||||
}
|
||||
|
||||
stringPDF(id_name, 1*event.target.value, val, amp);
|
||||
stringCDF(id_name, 1*event.target.value, val, amp);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//helper functions. id - the string of the id's name, val - the value of the id, base - the base value of the item for this id
|
||||
function stringPDF(id,val,base,amp) {
|
||||
/** [0.3b,1.3b] positive normal
|
||||
* [1.3b,0.3b] positive reversed
|
||||
* [1.3b,0.7b] negative normal
|
||||
* [0.7b,1.3b] negative reversed
|
||||
*
|
||||
* [0.3, 1.3] minr, maxr [0.3b, 1.3b] min, max
|
||||
* the minr/maxr decimal roll that corresponds to val -> minround, maxround
|
||||
*/
|
||||
let p; let min; let max; let minr; let maxr; let minround; let maxround;
|
||||
if (base > 0) {
|
||||
minr = 0.3 + 0.05*amp; maxr = 1.3;
|
||||
min = Math.max(1, Math.round(minr*base)); max = Math.max(1, Math.round(maxr*base));
|
||||
minround = (min == max) ? (minr) : ( Math.max(minr, (val-0.5) / base) );
|
||||
maxround = (min == max) ? (maxr) : ( Math.min(maxr, (val+0.5) / base) );
|
||||
} else {
|
||||
minr = 1.3; maxr = 0.7;
|
||||
min = Math.min(-1, Math.round(minr*base)); max = Math.min(-1, Math.round(maxr*base));
|
||||
minround = (min == max) ? (minr) : ( Math.min(minr, (val-0.5) / base) );
|
||||
maxround = (min == max) ? (maxr) : ( Math.max(maxr, (val+0.5) / base) );
|
||||
}
|
||||
|
||||
p = Math.abs(maxround-minround)/Math.abs(maxr-minr)*100;
|
||||
p = p.toFixed(3);
|
||||
|
||||
let b1 = document.createElement("b");
|
||||
b1.textContent = "Roll exactly ";
|
||||
let b2 = document.createElement("b");
|
||||
b2.textContent = val + idSuffixes[id];
|
||||
if (val > 0 == !reversedIDs.includes(id)) {b2.classList.add("positive")}
|
||||
if (val > 0 == reversedIDs.includes(id)) {b2.classList.add("negative")}
|
||||
let b3 = document.createElement("b");
|
||||
b3.textContent = ": " + p + "%";
|
||||
document.getElementById(id + "-pdf").innerHTML = "";
|
||||
document.getElementById(id + "-pdf").appendChild(b1);
|
||||
document.getElementById(id + "-pdf").appendChild(b2);
|
||||
document.getElementById(id + "-pdf").appendChild(b3);
|
||||
}
|
||||
|
||||
function stringCDF(id,val,base,amp) {
|
||||
let p; let min; let max; let minr; let maxr; let minround; let maxround;
|
||||
if (base > 0) {
|
||||
minr = 0.3 + 0.05*amp; maxr = 1.3;
|
||||
min = Math.max(1, Math.round(minr*base)); max = Math.max(1, Math.round(maxr*base));
|
||||
minround = (min == max) ? (minr) : ( Math.max(minr, (val-0.5) / base) );
|
||||
maxround = (min == max) ? (maxr) : ( Math.min(maxr, (val+0.5) / base) );
|
||||
} else {
|
||||
minr = 1.3; maxr = 0.7;
|
||||
min = Math.min(-1, Math.round(minr*base)); max = Math.min(-1, Math.round(maxr*base));
|
||||
minround = (min == max) ? (minr) : ( Math.min(minr, (val-0.5) / base) );
|
||||
maxround = (min == max) ? (maxr) : ( Math.max(maxr, (val+0.5) / base) );
|
||||
}
|
||||
|
||||
if (reversedIDs.includes(id)) {
|
||||
p = Math.abs(minr-maxround)/Math.abs(maxr-minr)*100;
|
||||
} else {
|
||||
p = Math.abs(maxr-minround)/Math.abs(maxr-minr)*100;
|
||||
}
|
||||
p = p.toFixed(3);
|
||||
|
||||
let b1 = document.createElement("b");
|
||||
b1.textContent = "Roll ";
|
||||
let b2 = document.createElement("b");
|
||||
b2.textContent = val + idSuffixes[id];
|
||||
if (val > 0 == !reversedIDs.includes(id)) {b2.classList.add("positive")}
|
||||
if (val > 0 == reversedIDs.includes(id)) {b2.classList.add("negative")}
|
||||
let b3 = document.createElement("b");
|
||||
b3.textContent= " or better: " + p + "%";
|
||||
document.getElementById(id + "-cdf").innerHTML = "";
|
||||
document.getElementById(id + "-cdf").appendChild(b1);
|
||||
document.getElementById(id + "-cdf").appendChild(b2);
|
||||
document.getElementById(id + "-cdf").appendChild(b3);
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
const DB_VERSION = 130;
|
||||
const DB_VERSION = 133;
|
||||
// @See https://github.com/mdn/learning-area/blob/master/javascript/apis/client-side-storage/indexeddb/video-store/index.jsA
|
||||
|
||||
let db;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const ING_DB_VERSION = 31;
|
||||
const ING_DB_VERSION = 32;
|
||||
|
||||
// @See https://github.com/mdn/learning-area/blob/master/javascript/apis/client-side-storage/indexeddb/video-store/index.js
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const TOME_DB_VERSION = 7;
|
||||
const TOME_DB_VERSION = 8;
|
||||
// @See https://github.com/mdn/learning-area/blob/master/javascript/apis/client-side-storage/indexeddb/video-store/index.jsA
|
||||
|
||||
let tdb;
|
||||
|
@ -136,7 +136,8 @@ async function load_tome_init() {
|
|||
const none_tomes_info = [
|
||||
["tome", "weaponTome", "No Weapon Tome"],
|
||||
["tome", "armorTome", "No Armor Tome"],
|
||||
["tome", "guildTome", "No Guild Tome"]
|
||||
["tome", "guildTome", "No Guild Tome"],
|
||||
["tome", "lootrunTome", "No Lootrun Tome"]
|
||||
];
|
||||
let none_tomes;
|
||||
|
||||
|
@ -152,7 +153,7 @@ function init_tome_maps() {
|
|||
}
|
||||
|
||||
none_tomes = [];
|
||||
for (let i = 0; i < 3; i++) {
|
||||
for (let i = 0; i < 4; i++) {
|
||||
let tome = Object();
|
||||
tome.slots = 0;
|
||||
tome.category = none_tomes_info[i][0];
|
||||
|
|
37
js/query.js
37
js/query.js
|
@ -77,6 +77,8 @@ const itemQueryProps = (function() {
|
|||
const tierIndices = { Normal: 0, Unique: 1, Set: 2, Rare: 3, Legendary: 4, Fabled: 5, Mythic: 6 };
|
||||
prop(['rarityname', 'raritystr', 'tiername', 'tierstr'], 'string', (i, ie) => i.tier);
|
||||
prop(['rarity', 'tier'], 'number', (i, ie) => tierIndices[i.tier]);
|
||||
prop(['majid', 'majorid'], 'string', (i, ie) => ((i.majorIds || [""])[0] || ""));
|
||||
prop(['majids', 'majorids'], 'number', (i, ie) => (i.majorIds || []).length);
|
||||
|
||||
prop(['level', 'lvl', 'combatlevel', 'combatlvl'], 'number', (i, ie) => i.lvl);
|
||||
prop(['strmin', 'strreq'], 'number', (i, ie) => i.strReq);
|
||||
|
@ -106,13 +108,43 @@ const itemQueryProps = (function() {
|
|||
maxId(['waterdmg%', 'waterdam%', 'wdmg%', 'wdam%', 'wdampct'], 'wDamPct');
|
||||
maxId(['firedmg%', 'firedam%', 'fdmg%', 'fdam%', 'fdampct'], 'fDamPct');
|
||||
maxId(['airdmg%', 'airdam%', 'admg%', 'adam%', 'adampct'], 'aDamPct');
|
||||
sum(['sumdmg%', 'sumdam%', 'totaldmg%', 'totaldam%', 'sumdampct', 'totaldampct'], props.edampct, props.tdampct, props.wdampct, props.fdampct, props.adampct);
|
||||
//sum(['sumdmg%', 'sumdam%', 'totaldmg%', 'totaldam%', 'sumdampct', 'totaldampct'], props.edampct, props.tdampct, props.wdampct, props.fdampct, props.adampct);
|
||||
|
||||
maxId(['mainatkdmg', 'mainatkdam', 'mainatkdmg%', 'mainatkdam%', 'meleedmg', 'meleedam', 'meleedmg%', 'meleedam%', 'mdpct'], 'mdPct');
|
||||
maxId(['emdpct'], 'eMdPct');
|
||||
maxId(['tmdpct'], 'tMdPct');
|
||||
maxId(['wmdpct'], 'wMdPct');
|
||||
maxId(['fmdpct'], 'fMdPct');
|
||||
maxId(['amdpct'], 'aMdPct');
|
||||
maxId(['nmdpct'], 'nMdPct');
|
||||
maxId(['rmdpct'], 'rMdPct');
|
||||
|
||||
maxId(['mainatkrawdmg', 'mainatkrawdam', 'mainatkneutraldmg', 'mainatkneutraldam', 'meleerawdmg', 'meleerawdam', 'meleeneutraldmg', 'meleeneutraldam', 'mdraw'], 'mdRaw');
|
||||
maxId(['emdraw'], 'eMdRaw');
|
||||
maxId(['tmdraw'], 'tMdRaw');
|
||||
maxId(['wmdraw'], 'wMdRaw');
|
||||
maxId(['fmdraw'], 'fMdRaw');
|
||||
maxId(['amdraw'], 'aMdRaw');
|
||||
maxId(['nmdraw'], 'nMdRaw');
|
||||
maxId(['rmdraw'], 'rMdRaw');
|
||||
|
||||
maxId(['spelldmg', 'spelldam', 'spelldmg%', 'spelldam%', 'sdpct'], 'sdPct');
|
||||
maxId(['esdpct'], 'eSdPct');
|
||||
maxId(['tsdpct'], 'tSdPct');
|
||||
maxId(['wsdpct'], 'wSdPct');
|
||||
maxId(['fsdpct'], 'fSdPct');
|
||||
maxId(['asdpct'], 'aSdPct');
|
||||
maxId(['nsdpct'], 'nSdPct');
|
||||
maxId(['rsdpct'], 'rSdPct');
|
||||
|
||||
maxId(['spellrawdmg', 'spellrawdam', 'spellneutraldmg', 'spellneutraldam', 'sdraw'], 'sdRaw');
|
||||
maxId(['rainbowraw'], 'rSdRaw');
|
||||
maxId(['esdraw'], 'eSdRaw');
|
||||
maxId(['tsdraw'], 'tSdRaw');
|
||||
maxId(['wsdraw'], 'wSdRaw');
|
||||
maxId(['fsdraw'], 'fSdRaw');
|
||||
maxId(['asdraw'], 'aSdRaw');
|
||||
maxId(['nsdraw'], 'nSdRaw');
|
||||
maxId(['rainbowraw', 'rsdraw'], 'rSdRaw');
|
||||
|
||||
const atkSpdIndices = { SUPER_SLOW: -3, VERY_SLOW: -2, SLOW: -1, NORMAL: 0, FAST: 1, VERY_FAST: 2, SUPER_FAST: 3 };
|
||||
prop(['attackspeed', 'atkspd'], 'string', (i, ie) => i.atkSpd ? atkSpdIndices[i.atkSpd] : 0);
|
||||
|
@ -131,6 +163,7 @@ const itemQueryProps = (function() {
|
|||
maxId(['waterdef%', 'wdef%', 'wdefpct'], 'wDefPct');
|
||||
maxId(['firedef%', 'fdef%', 'fdefpct'], 'fDefPct');
|
||||
maxId(['airdef%', 'adef%', 'adefpct'], 'aDefPct');
|
||||
maxId(['eledef%', 'rdef%', 'rdefpct'], 'rDefPct');
|
||||
sum(['sumdef%', 'totaldef%', 'sumdefpct', 'totaldefpct'], props.edefpct, props.tdefpct, props.wdefpct, props.fdefpct, props.adefpct);
|
||||
|
||||
prop(['health', 'hp'], 'number', (i, ie) => i.hp || 0);
|
||||
|
|
|
@ -206,6 +206,7 @@ class ExprField {
|
|||
try {
|
||||
this.output = this.compiler(this.text);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
this.errorText.innerText = e.message;
|
||||
this.output = null;
|
||||
}
|
||||
|
@ -303,6 +304,7 @@ function init_items_adv() {
|
|||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
searchFilterField.errorText.innerText = e.message;
|
||||
return;
|
||||
}
|
||||
|
@ -320,6 +322,7 @@ function init_items_adv() {
|
|||
}
|
||||
});
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
searchSortField.errorText.innerText = e.message;
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -6,71 +6,73 @@ given [atree_constants.js] .js form of the Ability Tree with reference as string
|
|||
"""
|
||||
import json
|
||||
|
||||
def translate_id(id_data, atree_data):
|
||||
def translate_spell_part(id_data, part):
|
||||
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[abil_id])+'.'+propname
|
||||
|
||||
def translate_effect(id_data, effect):
|
||||
if effect["type"] == "raw_stat":
|
||||
for bonus in effect["bonuses"]:
|
||||
if "abil" in bonus and bonus["abil"] in id_data:
|
||||
bonus["abil"] = id_data[bonus["abil"]]
|
||||
elif effect["type"] == "replace_spell":
|
||||
for part in effect['parts']:
|
||||
translate_spell_part(id_data, part)
|
||||
elif effect["type"] == "add_spell_prop":
|
||||
translate_spell_part(id_data, effect)
|
||||
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:
|
||||
_input["abil"] = id_data[_input["abil"]]
|
||||
if "output" in effect:
|
||||
if isinstance(effect["output"], list):
|
||||
for output in effect["output"]:
|
||||
if "abil" in output and output["abil"] in id_data:
|
||||
output["abil"] = id_data[output["abil"]]
|
||||
else:
|
||||
if "abil" in effect["output"] and effect["output"]["abil"] in id_data:
|
||||
effect["output"]["abil"] = id_data[effect["output"]["abil"]]
|
||||
|
||||
def translate_abil(id_data, abil, tree=True):
|
||||
def translate(path, ref):
|
||||
ref_dict = abil
|
||||
for x in path:
|
||||
ref_dict = ref_dict[x]
|
||||
ref_dict[ref] = id_data[ref_dict[ref]]
|
||||
|
||||
for optional_key in ["parents", "dependencies", "blockers"]:
|
||||
if optional_key not in abil:
|
||||
if tree:
|
||||
print(f"WARNING: atree node missing required key [{optional_key}]")
|
||||
continue
|
||||
for ref in range(len(abil[optional_key])):
|
||||
translate([optional_key], ref)
|
||||
|
||||
if "base_abil" in abil:
|
||||
base_abil_name = abil["base_abil"]
|
||||
if base_abil_name in id_data:
|
||||
translate([], "base_abil")
|
||||
|
||||
if "effects" not in abil:
|
||||
print("WARNING: abil missing 'effects' tag")
|
||||
print(abil)
|
||||
abil["effects"] = []
|
||||
for effect in abil["effects"]:
|
||||
translate_effect(id_data, effect)
|
||||
|
||||
def translate_all(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 abil in info:
|
||||
abil["id"] = id_data[_class][abil["display_name"]]
|
||||
translate_abil(id_data[_class], abil)
|
||||
|
||||
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"] == "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":
|
||||
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 "output" in effect:
|
||||
if isinstance(effect["output"], list):
|
||||
for output in effect["output"]:
|
||||
if "abil" in output and output["abil"] in id_data[_class]:
|
||||
output["abil"] = id_data[_class][output["abil"]]
|
||||
else:
|
||||
if "abil" in effect["output"] and effect["output"]["abil"] in id_data[_class]:
|
||||
effect["output"]["abil"] = id_data[_class][effect["output"]["abil"]]
|
||||
|
||||
abilDict = {}
|
||||
with open("atree_constants.js") as f:
|
||||
|
@ -87,15 +89,14 @@ with open("atree_constants.js") as f:
|
|||
with open("atree_ids.json", "w", encoding='utf-8') as id_dest:
|
||||
json.dump(abilDict, id_dest, ensure_ascii=False, indent=4)
|
||||
|
||||
translate_id(abilDict, data)
|
||||
translate_all(abilDict, data)
|
||||
|
||||
with open("major_ids_clean.json") as maj_id_file:
|
||||
maj_id_dat = json.load(maj_id_file)
|
||||
for k, v in maj_id_dat.items():
|
||||
for abil in v['abilities']:
|
||||
clazz = abil['class']
|
||||
base_abil = abil['base_abil']
|
||||
abil['base_abil'] = abilDict[clazz][base_abil]
|
||||
translate_abil(abilDict[clazz], abil, tree=False)
|
||||
with open("major_ids_min.json", "w", encoding='utf-8') as maj_id_out:
|
||||
json.dump(maj_id_dat, maj_id_out, ensure_ascii=False, separators=(',', ':'))
|
||||
|
||||
|
|
|
@ -3868,5 +3868,7 @@
|
|||
"Scarlet Wynnter Sweater": 3866,
|
||||
"Orange Wynnter Sweater": 3867,
|
||||
"Pine Wynnter Sweater": 3868,
|
||||
"Indigo Wynnter Sweater": 3869
|
||||
"Indigo Wynnter Sweater": 3869,
|
||||
"Air In A Can": 3870,
|
||||
"Iosis": 3871
|
||||
}
|
|
@ -42,6 +42,7 @@
|
|||
"airSpellDamage",
|
||||
"poison",
|
||||
"elementalDamage",
|
||||
"healingEfficiency",
|
||||
"raw4thSpellCost",
|
||||
"raw2ndSpellCost",
|
||||
"sprintRegen",
|
||||
|
@ -51,7 +52,6 @@
|
|||
"elementalSpellDamage",
|
||||
"rawNeutralSpellDamage",
|
||||
"4thSpellCost",
|
||||
"healingEfficiency",
|
||||
"knockback",
|
||||
"waterSpellDamage",
|
||||
"fireSpellDamage",
|
||||
|
@ -72,6 +72,7 @@
|
|||
"earthMainAttackDamage",
|
||||
"rawFireSpellDamage",
|
||||
"rawElementalSpellDamage",
|
||||
"healing",
|
||||
"rawElementalMainAttackDamage",
|
||||
"airMainAttackDamage",
|
||||
"thunderMainAttackDamage",
|
||||
|
@ -86,7 +87,8 @@
|
|||
"lootQuality",
|
||||
"gatherXpBonus",
|
||||
"gatherSpeed",
|
||||
"rawWaterMainAttackDamage"
|
||||
"rawWaterMainAttackDamage",
|
||||
"rawEarthMainAttackDamage"
|
||||
],
|
||||
"majorIds": [
|
||||
"Divine Honor",
|
||||
|
@ -121,6 +123,7 @@
|
|||
"Festive Spirit",
|
||||
"Freerunner",
|
||||
"Hawkeye",
|
||||
"Temblor",
|
||||
"Windsurf",
|
||||
"Juggle",
|
||||
"Roving Assassin",
|
||||
|
@ -130,8 +133,8 @@
|
|||
"Heart of the Pack",
|
||||
"Coagulate",
|
||||
"Guardian",
|
||||
"Hellfire",
|
||||
"Overwhelm",
|
||||
"Temblor",
|
||||
"Lunge",
|
||||
"Madness"
|
||||
],
|
||||
|
|
|
@ -28,7 +28,7 @@ if __name__ == "__main__":
|
|||
with open(local_metadata_file, 'r') as infile:
|
||||
metadata_check = json.load(infile)
|
||||
|
||||
checklist = set(x for x in translate_mappings.keys())
|
||||
checklist = set(x for x in translate_mappings['identifications'].keys())
|
||||
debug(f"Checking {len(checklist)} identifications")
|
||||
n = 0
|
||||
for identification in metadata_check['identifications']:
|
||||
|
|
|
@ -1,4 +1,26 @@
|
|||
{
|
||||
"tome": {
|
||||
"name": "displayName",
|
||||
"internalName": "name",
|
||||
"tier": "CAPS;tier",
|
||||
"material": "DELETE;",
|
||||
"base": "UNWRAP;tome.base",
|
||||
"dropMeta": "DELETE;",
|
||||
"identifications": "UNWRAP;identifications",
|
||||
"requirements": "UNWRAP;requirements",
|
||||
"raidReward": "DELETE;",
|
||||
"dropRestriction": "drop",
|
||||
"restrictions": "restrict",
|
||||
"tomeType": "type",
|
||||
"tomeVariant": "DELETE;"
|
||||
},
|
||||
"tome.base": {
|
||||
"gatheringXP": "tomeGatherXP",
|
||||
"slayingXP": "tomeXP",
|
||||
"dungeonXP": "tomeDungeonXP",
|
||||
"defenceToMobs": "defMobs",
|
||||
"damageToMobs": "damMobs"
|
||||
},
|
||||
"ingredient": {
|
||||
"name": "displayName",
|
||||
"internalName": "name",
|
||||
|
@ -80,7 +102,8 @@
|
|||
"dexterity": "dexReq",
|
||||
"intelligence": "intReq",
|
||||
"agility": "agiReq",
|
||||
"defence": "defReq"
|
||||
"defence": "defReq",
|
||||
"tomeSeeking": "DELETE;"
|
||||
},
|
||||
"identifications": {
|
||||
"healthRegen": "hprPct",
|
||||
|
|
|
@ -101,6 +101,15 @@ def recursive_translate(entry, result, path, translate_single):
|
|||
return result
|
||||
|
||||
armor_types = ['helmet', 'chestplate', 'leggings', 'boots']
|
||||
tome_type_translation = {
|
||||
'gatheringxp': 'gatherXpTome',
|
||||
'dungeonxp': 'dungeonXpTome',
|
||||
'slayingxp': 'mobXpTome',
|
||||
'guildtome': 'guildTome',
|
||||
'mobdefence': 'armorTome',
|
||||
'mobdamage': 'weaponTome',
|
||||
'lootrun': 'lootrunTome',
|
||||
}
|
||||
|
||||
def translate_entry(entry):
|
||||
"""
|
||||
|
@ -133,7 +142,13 @@ def translate_entry(entry):
|
|||
#return recursive_translate(entry, {}, "ing"), "ingredient"
|
||||
if "tomeType" in entry:
|
||||
# only tomes have this field.
|
||||
return None, "tome"
|
||||
print(entry)
|
||||
res = recursive_translate(entry, {}, "tome", translate_single_item)
|
||||
res['category'] = 'tome'
|
||||
res['fixID'] = False
|
||||
res['type'] = tome_type_translation[res['type']]
|
||||
print(res)
|
||||
return res, "tome"
|
||||
if "craftable" in entry:
|
||||
return None, "material"
|
||||
|
||||
|
@ -144,11 +159,15 @@ with open("id_map.json", "r") as id_map_file:
|
|||
id_map = json.load(id_map_file)
|
||||
used_ids = set([v for k, v in id_map.items()])
|
||||
max_id = 0
|
||||
|
||||
with open("ing_map.json","r") as ing_map_file:
|
||||
ing_map = json.load(ing_map_file)
|
||||
with open("../tome_map.json","r") as tome_map_file:
|
||||
tome_map = json.load(tome_map_file)
|
||||
|
||||
items = []
|
||||
ingreds = []
|
||||
tomes = []
|
||||
for name, entry in api_data.items():
|
||||
entry['name'] = name
|
||||
res, entry_type = translate_entry(entry)
|
||||
|
@ -160,26 +179,39 @@ for name, entry in api_data.items():
|
|||
items.append(res)
|
||||
elif entry_type == 'ingredient':
|
||||
ingreds.append(res)
|
||||
elif entry_type == 'tome':
|
||||
tomes.append(res)
|
||||
|
||||
with open("../clean.json", "r") as oldfile:
|
||||
old_data = json.load(oldfile)
|
||||
old_items = old_data['items']
|
||||
with open("../ingreds_clean.json", "r") as ingfile:
|
||||
old_ingreds = json.load(ingfile)
|
||||
with open("../tomes.json", "r") as tomefile:
|
||||
old_tome_data = json.load(tomefile)
|
||||
old_tomes = old_tome_data['tomes']
|
||||
|
||||
known_item_names = set()
|
||||
known_ingred_names = set()
|
||||
known_tome_names = set()
|
||||
for item in items:
|
||||
known_item_names.add(item["name"])
|
||||
for ingred in ingreds:
|
||||
known_ingred_names.add(ingred["name"])
|
||||
for tome in tomes:
|
||||
known_tome_names.add(tome["name"])
|
||||
|
||||
tome_value_map = {}
|
||||
for item in old_items:
|
||||
if item["name"] not in known_item_names:
|
||||
print(f'Unknown old item: {item["name"]}!!!')
|
||||
for ingred in old_ingreds:
|
||||
if ingred["name"] not in known_ingred_names:
|
||||
print(f'Unknown old ingred: {ingred["name"]}!!!')
|
||||
for tome in old_tomes:
|
||||
if tome["name"] not in known_tome_names:
|
||||
print(f'Unknown old tome: {tome["name"]}!!!')
|
||||
tome_value_map[tome['name']] = tome
|
||||
|
||||
# TODO hack pull the major id file
|
||||
major_ids_filename = "../js/builder/major_ids_clean.json"
|
||||
|
@ -188,9 +220,11 @@ with open(major_ids_filename, 'r') as major_ids_file:
|
|||
major_ids_reverse_map = { v['displayName'] : k for k, v in major_ids_map.items() }
|
||||
|
||||
for item in items:
|
||||
# HACKY ITEM FIXES!
|
||||
# NOTE: HACKY ITEM FIXES!
|
||||
if 'majorIds' in item:
|
||||
item['majorIds'] = [ major_ids_reverse_map[item['majorIds']['name']] ]
|
||||
if item['tier'] == 'Common':
|
||||
item['tier'] = 'Normal'
|
||||
|
||||
if not (item["name"] in id_map):
|
||||
while max_id in used_ids:
|
||||
|
@ -214,9 +248,21 @@ for ingred in ingreds:
|
|||
if not (ingred["name"] in ing_map):
|
||||
new_id = len(ing_map)
|
||||
ing_map[ingred["name"]] = new_id
|
||||
print(f'New item: {item["name"]} (id: {new_id})')
|
||||
print(f'New ingred: {ingred["name"]} (id: {new_id})')
|
||||
ingred["id"] = ing_map[ingred["name"]]
|
||||
|
||||
for tome in tomes:
|
||||
if not (tome['name'] in tome_map):
|
||||
new_id = len(tome_map)
|
||||
tome_map[tome['name']] = new_id
|
||||
print(f'New tome: {tome["name"]} (id: {new_id})')
|
||||
tome['alias'] = 'NO_ALIAS'
|
||||
else:
|
||||
old_tome = tome_value_map[tome['name']]
|
||||
if 'alias' in old_tome:
|
||||
tome['alias'] = old_tome['alias']
|
||||
tome['id'] = tome_map[tome['name']]
|
||||
|
||||
#write items back into data
|
||||
old_data["items"] = items
|
||||
|
||||
|
@ -225,6 +271,8 @@ with open("id_map.json","w") as id_map_file:
|
|||
json.dump(id_map, id_map_file, indent=2)
|
||||
with open("ing_map.json","w") as ing_map_file:
|
||||
json.dump(ing_map, ing_map_file, indent=2)
|
||||
with open("../tome_map.json","w") as tome_map_file:
|
||||
json.dump(tome_map, tome_map_file, indent=2)
|
||||
|
||||
|
||||
#write the data back to the outfile
|
||||
|
@ -234,3 +282,5 @@ with open('item_out.json', "w+") as out_file:
|
|||
with open('ing_out.json', "w+") as out_file:
|
||||
json.dump(ingreds, out_file, ensure_ascii=False, separators=(',', ':'))
|
||||
|
||||
with open('tome_out.json', "w+") as out_file:
|
||||
json.dump({'tomes': tomes}, out_file, ensure_ascii=False, separators=(',', ':'))
|
||||
|
|
|
@ -71,5 +71,22 @@
|
|||
"Abyssal Tome of Weapon Mastery III": 72,
|
||||
"Infernal Tome of Weapon Mastery III": 73,
|
||||
"Cyclonic Tome of Weapon Mastery III": 74,
|
||||
"Astral Tome of Weapon Mastery III": 75
|
||||
}
|
||||
"Astral Tome of Weapon Mastery III": 75,
|
||||
"Tome of Gathering Mastery III": 73,
|
||||
"Mastermind's Tome of Lootrun Mastery": 74,
|
||||
"Tome of Armour Mastery I": 75,
|
||||
"Pickpocket's Tome of Lootrun Mastery": 76,
|
||||
"Tome of Slaying Mastery III": 77,
|
||||
"Tome of Slaying Mastery I": 78,
|
||||
"Tome of Gathering Mastery I": 79,
|
||||
"Scoundrel's Tome of Lootrun Mastery": 80,
|
||||
"Spelunker's Tome of Lootrun Mastery": 81,
|
||||
"Tome of Slaying Mastery II": 82,
|
||||
"Tome of Dungeoneering Mastery II": 83,
|
||||
"Tome of Gathering Mastery II": 84,
|
||||
"Tome of Dungeoneering Mastery I": 85,
|
||||
"Manipulator's Tome of Lootrun Mastery": 86,
|
||||
"Plunderer's Tome of Lootrun Mastery": 87,
|
||||
"Thief's Tome of Lootrun Mastery": 88,
|
||||
"Tome of Dungeoneering Mastery III": 89
|
||||
}
|
2160
tomes.json
2160
tomes.json
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue