Merge branch 'dev'

This commit is contained in:
b 2021-01-26 03:17:35 -06:00
commit 75a061975b
12 changed files with 324 additions and 184 deletions

View file

@ -210,7 +210,6 @@ class Build{
errors.push("Level is not a string or number."); errors.push("Level is not a string or number.");
} }
document.getElementById("level-choice").value = this.level; document.getElementById("level-choice").value = this.level;
this.level = 106;
this.availableSkillpoints = levelToSkillPoints(this.level); this.availableSkillpoints = levelToSkillPoints(this.level);
this.equipment = [ this.helmet, this.chestplate, this.leggings, this.boots, this.ring1, this.ring2, this.bracelet, this.necklace ]; this.equipment = [ this.helmet, this.chestplate, this.leggings, this.boots, this.ring1, this.ring2, this.bracelet, this.necklace ];

View file

@ -439,6 +439,7 @@ function calculateBuild(save_skp, skp){
} }
console.log(equipment); console.log(equipment);
console.log(document.getElementById("level-choice").value);
player_build = new Build(document.getElementById("level-choice").value, equipment, powderings, new Map(), errors); player_build = new Build(document.getElementById("level-choice").value, equipment, powderings, new Map(), errors);
for (let i of document.getElementsByClassName("hide-container-block")) { for (let i of document.getElementsByClassName("hide-container-block")) {
@ -763,7 +764,6 @@ function calculateBuildStats() {
let remainingSkpTitle = document.createElement("b"); let remainingSkpTitle = document.createElement("b");
remainingSkpTitle.textContent = "Assigned " + player_build.assigned_skillpoints + " skillpoints. Remaining skillpoints: "; remainingSkpTitle.textContent = "Assigned " + player_build.assigned_skillpoints + " skillpoints. Remaining skillpoints: ";
let remainingSkpContent = document.createElement("b"); let remainingSkpContent = document.createElement("b");
//remainingSkpContent.textContent = "" + (levelToSkillPoints(player_build.level) - player_build.assigned_skillpoints < 0 ? "< 0" : levelToSkillPoints(player_build.level) - player_build.assigned_skillpoints);
remainingSkpContent.textContent = "" + (levelToSkillPoints(player_build.level) - player_build.assigned_skillpoints); remainingSkpContent.textContent = "" + (levelToSkillPoints(player_build.level) - player_build.assigned_skillpoints);
remainingSkpContent.classList.add(levelToSkillPoints(player_build.level) - player_build.assigned_skillpoints < 0 ? "negative" : "positive"); remainingSkpContent.classList.add(levelToSkillPoints(player_build.level) - player_build.assigned_skillpoints < 0 ? "negative" : "positive");
@ -792,7 +792,7 @@ function calculateBuildStats() {
lvlWarning = document.createElement("p"); lvlWarning = document.createElement("p");
lvlWarning.classList.add("itemp"); lvlWarning.classList.add("itemp");
lvlWarning.classList.add("warning"); lvlWarning.classList.add("warning");
lvlWarning.textContent = "WARNING: A level 50 player cannot use some piece(s) of this build." lvlWarning.textContent = "WARNING: A level " + player_build.level + " player cannot use some piece(s) of this build."
} }
let baditem = document.createElement("p"); let baditem = document.createElement("p");
baditem.classList.add("nocolor"); baditem.classList.add("nocolor");

File diff suppressed because one or more lines are too long

View file

@ -28,12 +28,12 @@
<img src = "/media/icons/crafter.png" class = "left linkoptions headericon"> <img src = "/media/icons/crafter.png" class = "left linkoptions headericon">
</img> </img>
<div class = "tooltiptext center">WynnCrafter</div> <div class = "tooltiptext center">WynnCrafter</div>
</a> </a-->
<a href = "./items.html" class = "nomarginp iconlink tooltip"> <a href = "./items.html" class = "nomarginp iconlink tooltip">
<img src = "/media/icons/searcher.png" class = "left linkoptions headericon"> <img src = "/media/icons/searcher.png" class = "left linkoptions headericon">
</img> </img>
<div class = "tooltiptext center">WynnAtlas</div> <div class = "tooltiptext center">WynnAtlas</div>
</a--> </a>
</div> </div>
<div class = "headercenter"> <div class = "headercenter">
<div > <div >

View file

@ -1,21 +0,0 @@
.items {
grid-column: 1;
padding: 0%;
display: grid;
grid-template-columns: repeat(auto-fill, 1fr);
width: 100%;
gap: 5px;
}
.itemsearch {
padding: 0%;
display: grid;
grid-template-columns: 1fr;
width: 100%;
gap: 5px;
grid-template-rows: masonry;
}
.search {
grid-column: 1;
}

View file

@ -1,24 +0,0 @@
.items {
grid-column: 2;
padding: 0%;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
width: 100%;
gap: 5px;
grid-template-rows: masonry;
}
.itemsearch {
padding: 0%;
display: grid;
grid-template-columns: 1fr 4fr;
width: 100%;
gap: 5px;
}
.search {
grid-column: 1;
position: sticky;
margin-bottom: auto;
top: 10px;
}

View file

@ -9,6 +9,7 @@
<link href="https://fonts.googleapis.com/css2?family=Nunito&display=swap" rel="stylesheet"> <link href="https://fonts.googleapis.com/css2?family=Nunito&display=swap" rel="stylesheet">
<link rel="stylesheet" href="styles.css"> <link rel="stylesheet" href="styles.css">
<link rel="stylesheet" href="items.css">
<link rel="stylesheet" media="screen and (min-width: 1100px)" href="items-wide.css"/> <link rel="stylesheet" media="screen and (min-width: 1100px)" href="items-wide.css"/>
<link rel="stylesheet" media="screen and (max-width: 1099px)" href="items-narrow.css"/> <link rel="stylesheet" media="screen and (max-width: 1099px)" href="items-narrow.css"/>
<link rel="icon" href="favicon.png"> <link rel="icon" href="favicon.png">
@ -24,11 +25,11 @@
</img> </img>
<div class = "tooltiptext center">WynnBuilder</div> <div class = "tooltiptext center">WynnBuilder</div>
</a> </a>
<a href = "./crafter.html" class = "nomarginp iconlink tooltip"> <!--a href = "./crafter.html" class = "nomarginp iconlink tooltip">
<img src = "/media/icons/crafter.png" class = "left linkoptions headericon"> <img src = "/media/icons/crafter.png" class = "left linkoptions headericon">
</img> </img>
<div class = "tooltiptext center">WynnCrafter</div> <div class = "tooltiptext center">WynnCrafter</div>
</a> </a-->
<a href = "./items.html" class = "nomarginp iconlink tooltip"> <a href = "./items.html" class = "nomarginp iconlink tooltip">
<img src = "/media/icons/searcher.png" class = "left linkoptions headericon"> <img src = "/media/icons/searcher.png" class = "left linkoptions headericon">
</img> </img>
@ -48,26 +49,86 @@
<br> <br>
<br> <br>
<div class="itemsearch"> <div class="itemsearch">
<div class="search"> <div class="searchbox">
<div class="center" id="credits"> <div class="left">
<a href="translations.txt" class="link">CLICK FOR ID mapping</a> <label for="name-choice">Name:</label><br>
<input class="searchinput" type="text" id="name-choice" name="name-choice" placeholder="Item name (case insensitive)" tabindex="1"/>
<p class="error"></p>
</div>
<div class="left">
<label for="category-choice">Category:</label><br>
<input class="searchinput" list="category-items" id="category-choice" name="category-choice" placeholder="ALL" tabindex="2"/>
<datalist id="category-items">
<option value="ALL">
<option value="armor">
<option value="helmet">
<option value="chestplate">
<option value="leggings">
<option value="boots">
<option value="accessory">
<option value="ring">
<option value="bracelet">
<option value="necklace">
<option value="weapon">
<option value="wand">
<option value="spear">
<option value="bow">
<option value="dagger">
<option value="relik">
</datalist>
<p class="error"></p>
</div>
<div class="left">
<label for="rarity-choice">Rarity:</label><br>
<input class="searchinput" list="rarity-items" id="rarity-choice" name="rarity-choice" placeholder="ANY" tabindex="3"/>
<datalist id="rarity-items">
<option value="ANY">
<option value="Normal">
<option value="Unique">
<option value="Rare">
<option value="Legendary">
<option value="Fabled">
<option value="Mythic">
<option value="Sane">
</datalist>
<p class="error"></p>
</div>
<div class="left">
<label for="level-choice">Level:</label><br>
<input class="searchinput" type="text" id="level-choice" name="level-choice" value="1-106" tabindex="4"/>
<p class="error"></p>
</div>
<datalist id="filter-items">
</datalist>
<div class="left">
<label for="filter1-choice">Filter 1:</label><br>
<input class="searchinput" list="filter-items" id="filter1-choice" name="filter1-choice" placeholder="ANY" tabindex="5"/>
<p class="error"></p>
</div>
<div class="left">
<label for="filter2-choice">Filter 2:</label><br>
<input class="searchinput" list="filter-items" id="filter2-choice" name="filter2-choice" placeholder="ANY" tabindex="6"/>
<p class="error"></p>
</div>
<div class="left">
<label for="filter3-choice">Filter 3:</label><br>
<input class="searchinput" list="filter-items" id="filter3-choice" name="filter3-choice" placeholder="ANY" tabindex="7"/>
<p class="error"></p>
</div>
<div class="left">
<label for="filter4-choice">Filter 4:</label><br>
<input class="searchinput" list="filter-items" id="filter4-choice" name="filter4-choice" placeholder="ANY" tabindex="8"/>
<p class="error"></p>
</div>
<div class="right" style="grid-column:1/span 2">
<button class = "button" id = "search-button" onclick = "doItemSearch()" tabindex="9">
Search!
</button>
</div>
<div id="summary" class="left" style="grid-column:3/span 2">
Hello!
</div> </div>
<p>Basic Dumb JSON search</p>
<p>Query types:</p>
<p>name, type, category, stat</p>
<textarea name="query-json" id="query-json" cols="25" rows="25" tabindex="1">
[
{
"queryType": "name",
"value": ""
}
]
</textarea>
<br>
<button class = "button" id = "search-button" onclick = "doItemSearch()" tabindex="2">
Search Items
</button>
<p id="summary">hello</p>
</div> </div>
<div class="center items" id="main"> <div class="center items" id="main">
</div> </div>

162
items.js
View file

@ -1,4 +1,123 @@
const translate_mappings = {
//"Name": "name",
//"Display Name": "displayName",
//"tier"Tier": ",
//"Set": "set",
"Powder Slots": "slots",
//"Type": "type",
//"armorType", (deleted)
//"color", (deleted)
//"lore", (deleted)
//"material", (deleted)
"Drop type": "drop",
"Quest requirement": "quest",
"Restriction": "restrict",
//"Base Neutral Damage": "nDam",
//"Base Fire Damage": "fDam",
//"Base Water Damage": "wDam",
//"Base Air Damage": "aDam",
//"Base Thunder Damage": "tDam",
//"Base Earth Damage": "eDam",
//"Base Attack Speed": "atkSpd",
"Health": "hp",
"Raw Fire Defense": "fDef",
"Raw Water Defense": "wDef",
"Raw Air Defense": "aDef",
"Raw Thunder Defense": "tDef",
"Raw Earth Defense": "eDef",
"Combat Level": "lvl",
//"Class Requirement": "classReq",
"Req Strength": "strReq",
"Req Dexterity": "dexReq",
"Req Intelligence": "intReq",
"Req Agility": "agiReq",
"Req Defense": "defReq",
"% Health Regen": "hprPct",
"Mana Regen": "mr",
"% Spell Damage": "sdPct",
"% Melee Damage": "mdPct",
"Life Steal": "ls",
"Mana Steal": "ms",
"XP Bonus": "xpb",
"Loot Bonus": "lb",
"Reflection": "ref",
"Strength": "str",
"Dexterity": "dex",
"Intelligence": "int",
"Agility": "agi",
"Defense": "def",
"Thorns": "thorns",
"Exploding": "expd",
"Walk Speed": "spd",
"Attack Speed Bonus": "atkTier",
"Poison": "poison",
"Health Bonus": "hpBonus",
"Soul Point Regen": "spRegen",
"Stealing": "eSteal",
"Raw Health Regen": "hprRaw",
"Raw Spell": "sdRaw",
"Raw Melee": "mdRaw",
"% Fire Damage": "fDamPct",
"% Water Damage": "wDamPct",
"% Air Damage": "aDamPct",
"% Thunder Damage": "tDamPct",
"% Earth Damage": "eDamPct",
"% Fire Defense": "fDefPct",
"% Water Defense": "wDefPct",
"% Air Defense": "aDefPct",
"% Thunder Defense": "tDefPct",
"% Earth Defense": "eDefPct",
"Fixed IDs": "fixID",
"Custom Skin": "skin",
//"Item Category": "category",
"1st Spell Cost %": "spPct1",
"1st Spell Cost Raw": "spRaw1",
"2nd Spell Cost %": "spPct2",
"2nd Spell Cost Raw": "spRaw2",
"3rd Spell Cost %": "spPct3",
"3rd Spell Cost Raw": "spRaw3",
"4th Spell Cost %": "spPct4",
"4th Spell Cost Raw": "spRaw4",
"Rainbow Spell Damage": "rainbowRaw",
"Sprint": "sprint",
"Sprint Regen": "sprintReg",
"Jump Height": "jh",
"Loot Quality": "lq",
"Gather XP Bonus": "gXp",
"Gather Speed Bonus": "gSpd",
};
const special_mappings = {
"Sum (skill points)": new SumQuery(["str", "dex", "int", "def", "agi"]),
"Sum (Mana Sustain)": new SumQuery(["mr", "ms"]),
"Sum (Life Sustain)": new SumQuery(["hpr", "ls"]),
"Sum (Health + Health Bonus)": new SumQuery(["hp", "hpBonus"]),
"No Req Strength": new NegateQuery("strReq"),
"No Req Dexterity": new NegateQuery("dexReq"),
"No Req Intelligence": new NegateQuery("intReq"),
"No Req Agility": new NegateQuery("agiReq"),
"No Req Defense": new NegateQuery("defReq"),
};
let itemFilters = document.getElementById("filter-items");
for (let x in translate_mappings) {
let el = document.createElement("option");
el.value = x;
itemFilters.appendChild(el);
}
for (let x in special_mappings) {
let el = document.createElement("option");
el.value = x;
itemFilters.appendChild(el);
}
let itemTypes = [ "helmet", "chestplate", "leggings", "boots", "ring", "bracelet", "necklace", "wand", "spear", "bow", "dagger", "relik" ];
let itemCategories = [ "armor", "accessory", "weapon" ];
function applyQuery(items, query) { function applyQuery(items, query) {
return items.filter(query.filter, query).sort(query.compare); return items.filter(query.filter, query).sort(query.compare);
} }
@ -17,12 +136,47 @@ function displayItems(items_copy) {
function doItemSearch() { function doItemSearch() {
window.scrollTo(0, 0); window.scrollTo(0, 0);
let input_json = document.getElementById("query-json").value; let queries = [];
let input = JSON.parse(input_json); queries.push(new NameQuery(document.getElementById("name-choice").value));
let categoryOrType = document.getElementById("category-choice").value;
if (itemTypes.includes(categoryOrType)) {
queries.push(new IdMatchQuery("type", categoryOrType));
}
else if (itemCategories.includes(categoryOrType)) {
queries.push(new IdMatchQuery("category", categoryOrType));
}
let rarity = document.getElementById("rarity-choice").value;
if (rarity) {
if (rarity === "ANY") {
}
else {
queries.push(new IdMatchQuery("tier", rarity));
}
}
let level_dat = document.getElementById("level-choice").value.split("-");
queries.push(new LevelRangeQuery(parseInt(level_dat[0]), parseInt(level_dat[1])));
for (let i = 1; i <= 4; ++i) {
let raw_dat = document.getElementById("filter"+i+"-choice").value;
let filter_dat = translate_mappings[raw_dat];
if (filter_dat !== undefined) {
queries.push(new IdQuery(filter_dat));
continue;
}
filter_dat = special_mappings[raw_dat];
if (filter_dat !== undefined) {
queries.push(filter_dat);
continue;
}
}
let items_copy = items.slice(); let items_copy = items.slice();
document.getElementById("main").textContent = ""; document.getElementById("main").textContent = "";
for (const _query of input) { for (const query of queries) {
const query = queryTypeMap.get(_query.queryType)(_query.value, _query.value2);
items_copy = applyQuery(items_copy, query); items_copy = applyQuery(items_copy, query);
} }
document.getElementById("summary").textContent = items_copy.length + " results." document.getElementById("summary").textContent = items_copy.length + " results."

View file

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

View file

@ -14,33 +14,30 @@ class NameQuery {
} }
queryTypeMap.set("name", function(s) { return new NameQuery(s); } ); queryTypeMap.set("name", function(s) { return new NameQuery(s); } );
class TypeQuery { class LevelRangeQuery {
constructor(type) { this.type = type; } constructor(min, max) { this.min = min; this.max = max; }
filter(item) { filter(item) {
if (item.remapID === undefined) { if (item.remapID === undefined) {
return (item.type === this.type); return (item.lvl <= this.max && item.lvl >= this.min);
} }
return false; return false;
} }
compare(a, b) { return a < b; } compare(a, b) { return a > b; }
} }
queryTypeMap.set("type", function(s) { return new TypeQuery(s); } );
class CategoryQuery { class NegateQuery {
constructor(category) { this.category = category; } constructor(id) {
this.id = id;
filter(item) { this.compare = function(a, b) { return 0; };
if (item.remapID === undefined) {
return (item.category === this.category);
}
return false;
} }
compare(a, b) { return a < b; } filter(item) {
return (!(this.id in item)) || (item[this.id] == 0);
}
} }
queryTypeMap.set("category", function(s) { return new CategoryQuery(s); } ); queryTypeMap.set("null", function(s) { return new IdQuery(s); } );
class IdQuery { class IdQuery {
constructor(id) { constructor(id) {
@ -55,3 +52,34 @@ class IdQuery {
} }
} }
queryTypeMap.set("stat", function(s) { return new IdQuery(s); } ); queryTypeMap.set("stat", function(s) { return new IdQuery(s); } );
class IdMatchQuery {
constructor(id, value) {
this.id = id;
this.value = value;
this.compare = function(a, b) {
return 0;
};
}
filter(item) {
return (this.id in item) && (item[this.id] == this.value);
}
}
class SumQuery {
constructor(ids) {
this.compare = function(a, b) {
let balance = 0;
for (const id of ids) {
if (a[id]) { balance -= a[id]; }
if (b[id]) { balance += b[id]; }
}
return balance;
};
}
filter(item) {
return true;
}
}

View file

@ -5,6 +5,18 @@
flex-direction: row; flex-direction: row;
justify-content: center; justify-content: center;
} }
.error {
color: red;
top: 30px;
font-size: 10px;
padding: 0;
margin: 0;
height: 5px;
font-family: 'Nunito', sans-serif;
white-space: nowrap;
}
.headericon { .headericon {
/* JANK FIX IF CAN */ /* JANK FIX IF CAN */
max-height: 48px; max-height: 48px;

View file

@ -70943,77 +70943,37 @@
"drop": "NORMAL" "drop": "NORMAL"
}, },
{ {
"name": "Enduzskam",
"tier": "Unique", "tier": "Unique",
"type": "boots", "type": "boots",
"name": "Enduzskam",
"displayName": "Enduzskam",
"set": null, "set": null,
"quest": null, "quest": null,
"poison": 0,
"thorns": 0,
"sprint": 0,
"category": "armor",
"slots": 2,
"drop": "NORMAL",
"hp": 1950,
"fDef": 0,
"wDef": 50,
"aDef": 0,
"tDef": 80,
"eDef": -90,
"lvl": 83,
"classReq": null, "classReq": null,
"fixID": false,
"strReq": 0, "strReq": 0,
"dexReq": 45, "dexReq": 35,
"intReq": 45, "intReq": 35,
"agiReq": 0,
"defReq": 0, "defReq": 0,
"hprPct": 0, "agiReq": 0,
"mr": 1, "category": "armor",
"sdPct": 7, "lvl": 83,
"mdPct": 0, "hp": 1950,
"ls": 0, "eDef": -90,
"ms": 0, "tDef": 80,
"xpb": 0, "wDef": 50,
"lb": 0, "slots": 2,
"ref": 0,
"str": 0, "str": 0,
"dex": 4, "dex": 9,
"int": 0, "int": 0,
"agi": 0,
"def": 0, "def": 0,
"expd": 0, "agi": 0,
"spd": 0, "mr": 1,
"atkTier": 0, "sdPct": 14,
"hpBonus": 0,
"spRegen": 0,
"eSteal": 0,
"hprRaw": 0,
"sdRaw": 0,
"mdRaw": 0,
"fDamPct": 0,
"wDamPct": 12,
"aDamPct": 0,
"tDamPct": 16,
"eDamPct": -14, "eDamPct": -14,
"fDefPct": 0, "tDamPct": 16,
"wDefPct": 0, "wDamPct": 12,
"aDefPct": 0,
"tDefPct": 0,
"eDefPct": -10, "eDefPct": -10,
"spPct1": 0,
"spRaw1": 0,
"spPct2": 0,
"spRaw2": 0,
"spPct3": 0,
"spRaw3": 0,
"spPct4": 0,
"spRaw4": 0,
"rainbowRaw": 0,
"sprintReg": 0,
"jh": 0,
"lq": 0,
"gXp": 0,
"gSpd": 0,
"id": 986 "id": 986
}, },
{ {
@ -256754,38 +256714,9 @@
"remapID": 586 "remapID": 586
}, },
{ {
"tier": "Unique", "id": 3592,
"type": "boots", "name": "3592",
"name": "Enduzkam", "remapID": 986
"displayName": "Enduzkam",
"set": null,
"quest": null,
"classReq": null,
"fixID": false,
"strReq": 0,
"dexReq": 35,
"intReq": 35,
"defReq": 0,
"agiReq": 0,
"category": "armor",
"lvl": 83,
"hp": 1950,
"eDef": -90,
"tDef": 80,
"wDef": 50,
"slots": 2,
"str": 0,
"dex": 9,
"int": 0,
"def": 0,
"agi": 0,
"mr": 1,
"sdPct": 14,
"eDamPct": -14,
"tDamPct": 16,
"wDamPct": 12,
"eDefPct": -10,
"id": 3592
}, },
{ {
"tier": "Unique", "tier": "Unique",
@ -258891,7 +258822,7 @@
"displayName": "Cursed Jackboots" "displayName": "Cursed Jackboots"
}, },
{ {
"displayName": "Cinfras Souvenir T-Shirt", "name": "Cinfras Souvenir T-Shirt",
"tier": "Normal", "tier": "Normal",
"type": "chestplate", "type": "chestplate",
"set": null, "set": null,