Merge pull request #173 from downthecrop/droptable-tool-rewrite

Rewrite droptable tool in VueJS
This commit is contained in:
Ryan 2022-09-27 18:17:28 +10:00 committed by GitHub
commit d7bc702660
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 451 additions and 1324 deletions

View File

@ -1,2 +0,0 @@
# 2009-Droptables
https://downthecrop.github.io/2009-droptables

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,7 @@
body{
body {
margin: 10px !important;
}
.stage {
display: flex;
justify-content: center;
@ -9,124 +10,81 @@ body{
padding: 2rem 0;
margin: 0 -5%;
overflow: hidden;
}
}
.stat-data{
.stat-data {
background-color: #605443;
color: white;
text-align: center;
}
.dot-pulse {
position: relative;
left: -9999px;
width: 10px;
height: 10px;
border-radius: 5px;
background-color: #9880ff;
color: #9880ff;
box-shadow: 9999px 0 0 -5px #9880ff;
animation: dotPulse 1.5s infinite linear;
animation-delay: .25s;
}
.dot-pulse::before, .dot-pulse::after {
content: '';
display: inline-block;
position: absolute;
top: 0;
width: 10px;
height: 10px;
border-radius: 5px;
background-color: #9880ff;
color: #9880ff;
}
.dot-pulse::before {
box-shadow: 9984px 0 0 -5px #9880ff;
animation: dotPulseBefore 1.5s infinite linear;
animation-delay: 0s;
}
.dot-pulse::after {
box-shadow: 10014px 0 0 -5px #9880ff;
animation: dotPulseAfter 1.5s infinite linear;
animation-delay: .5s;
}
@keyframes dotPulseBefore {
0% {
box-shadow: 9984px 0 0 -5px #9880ff;
}
30% {
box-shadow: 9984px 0 0 2px #9880ff;
}
60%, 100% {
box-shadow: 9984px 0 0 -5px #9880ff;
}
}
@keyframes dotPulse {
0% {
box-shadow: 9999px 0 0 -5px #9880ff;
}
30% {
box-shadow: 9999px 0 0 2px #9880ff;
}
60%, 100% {
box-shadow: 9999px 0 0 -5px #9880ff;
}
}
@keyframes dotPulseAfter {
0% {
box-shadow: 10014px 0 0 -5px #9880ff;
}
30% {
box-shadow: 10014px 0 0 2px #9880ff;
}
60%, 100% {
box-shadow: 10014px 0 0 -5px #9880ff;
}
}
td{
td {
border: 1px solid #94866d;
background-color: #e2dbc8;
padding: 10px !important;
text-align: center;
}
table {
border-collapse: collapse;
}
tbody{
tbody {
margin: auto;
width: 100%;
display: table;
}
.debug-hide{
.debug-hide {
display: none;
}
.debug-show{
.debug-show {
display: block;
}
.debug-show p{
.debug-show p {
display: block;
max-width: 75%;
overflow-x: auto;
}
.always{
.always {
background-color: #AFEEEE;
}
.common{
.common {
background-color: #56E156;
}
.uncommon{
.uncommon {
background-color: #FFED4C;
}
.rare{
.rare {
background-color: #FF863C;
}
.veryrare{
.veryrare {
background-color: #FF6262;
}
.hover-link img{
.hover-link img {
margin-top: 0px !important;
padding-left: 10px;
display: "inline";
}
#app {
padding: 40px;
}
.npcIds {
display: block;
max-width: 75%;
overflow-x: auto;
}
.centered {
text-align: center;
}

View File

@ -2,15 +2,7 @@
title: Drop Tables
layout: guide
---
<script src=".././js/jquery-3.6.0.min.js"></script>
<script src=".././js/common.js"></script>
<script src=".././js/bynpc.js"></script>
<link rel="stylesheet" href=".././css/style.css">
<style>
#navhome{
margin-top: 0px !important;
}
</style>
<link rel="stylesheet" href="../css/style.css">
<div id="content">
<div id="rule">
<div class="sectionHeader">
@ -34,28 +26,12 @@ layout: guide
<div class="bottomleftshad">
<div class="bottomrightshad">
<!-- CONTENT HERE -->
<div class="links"><a href=".././drop-table/">Drop Tables</a> | <a href=".././item-source/">Item Sources</a> | <a href=".././item-data/">Item Data</a></div>
<div id="wrapper" style="padding-bottom: 40px;">
<center>
<div class="headings">
<span class="headertitleleft"><span class="headertitleright" id="search">Drop Tables</span></span>
</div>
<input style="width:50%;"class="form-control input-lg" placeholder="NPC/Monster Name"
onkeyup="search(this);"></input>
<center>
<p>Notes: RDT Slot = Rare Drop Table <a href=".././rdt.html">(link)</a>, Summoning Charms are rolled separately <input type="checkbox" id="debug-toggle" name="debug"><lable>Show ID's</lable></p>
</center>
</center>
<div class="loading" style="display: none;">
<div class="stage">
<h1>Loading JSON</h1>
</div>
<div class="stage">
<div class="dot-pulse"></div>
</div>
</div>
<div id="dcontent" style="margin:auto;width: 80%;"></div>
</div>
<div id="app"></div>
<script type="module">
import { createApp } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.prod.js'
import MyComponent from '../searchtool.js'
createApp(MyComponent).mount('#app')
</script>
</div>
</div>
</div>

View File

@ -1,75 +0,0 @@
---
title: Item Data
layout: guide
---
<script src=".././js/jquery-3.6.0.min.js"></script>
<script src=".././js/common.js"></script>
<script src=".././js/itemdata.js"></script>
<link rel="stylesheet" href=".././css/style.css">
<style>
#navhome{
margin-top: 0px !important;
}
</style>
<div id="content">
<div id="rule">
<div class="sectionHeader">
<div class="left">
<div class="right">
<h1 class="plaque_medium">
{{ page.title }}
</h1>
</div>
</div>
<div class="section">
<div class="article_theme_1">
<div class="article">
<div class="topshadow">
<div class="bottomborder">
<div class="leftshadow">
<div class="rightshadow">
<div class="leftcorner">
<div class="rightcorner">
<div class="bottombordershad">
<div class="bottomleftshad">
<div class="bottomrightshad">
<!-- CONTENT HERE -->
<div class="links"><a href="../drop-table/">Drop Tables</a> | <a href="../item-source/">Item Sources</a> | <a href="../item-data/">Item Data</a></div>
<div id="wrapper" style="padding-bottom: 40px;">
<center>
<div class="headings">
<span class="headertitleleft"><span class="headertitleright" id="search">Item Data</span></span>
</div>
<input style="width:50%;"class="form-control input-lg" placeholder="Item Name"
onkeyup="search(this);"></input>
<p>
<input type="checkbox" id="debug-toggle" name="debug">
<lable>Show ALL Attributes</lable>
</p>
</center>
<div class="loading" style="display: none;">
<div class="stage">
<h1>Loading JSON</h1>
</div>
<div class="stage">
<div class="dot-pulse"></div>
</div>
</div>
<div id="dcontent" style="margin:auto;width: 80%;"></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<br class="clear">
</div>
</div>

View File

@ -1,74 +0,0 @@
---
title: Item Sources
layout: guide
---
<script src=".././js/jquery-3.6.0.min.js"></script>
<script src=".././js/common.js"></script>
<script src=".././js/byitem.js"></script>
<link rel="stylesheet" href=".././css/style.css">
<style>
#navhome{
margin-top: 0px !important;
}
</style>
<div id="content">
<div id="rule">
<div class="sectionHeader">
<div class="left">
<div class="right">
<h1 class="plaque_medium">
{{ page.title }}
</h1>
</div>
</div>
<div class="section">
<div class="article_theme_1">
<div class="article">
<div class="topshadow">
<div class="bottomborder">
<div class="leftshadow">
<div class="rightshadow">
<div class="leftcorner">
<div class="rightcorner">
<div class="bottombordershad">
<div class="bottomleftshad">
<div class="bottomrightshad">
<!-- CONTENT HERE -->
<div class="links"><a href="../drop-table/">Drop Tables</a> | <a href="../item-source/">Item Sources</a> | <a href="../item-data/">Item Data</a></div>
<div id="wrapper" style="padding-bottom: 40px;">
<center>
<div class="headings">
<span class="headertitleleft"><span class="headertitleright" id="search">Item Sources</span></span>
</div>
<input style="width:50%;"class="form-control input-lg" placeholder="Item Name"
onkeyup="search(this);"></input>
<center>
<p>Notes: RDT Slot = Rare Drop Table <a href="../rdt.html">(link)</a>, Summoning Charms are rolled separately <input type="checkbox" id="debug-toggle" name="debug"><lable>Show ID's</lable></p>
</center>
</center>
<div class="loading" style="display: none;">
<div class="stage">
<h1>Loading JSON</h1>
</div>
<div class="stage">
<div class="dot-pulse"></div>
</div>
</div>
<div id="dcontent" style="margin:auto;width: 80%;"></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<br class="clear">
</div>
</div>

View File

@ -1,174 +0,0 @@
let npcNameMap = {}
let items = {}
class npcObject {
constructor(ids, name) {
this.ids = ids;
this.name = name;
this.totalWeight = 0
this.default = []
this.main = []
}
}
// our json data is out of sync.
function itemErrorMessage(npc,item){
console.log("Error with npc",npc," drop id: ",item)
console.log("update this tools json/item_config.json")
}
function newDisplayItem(name, id, min, max, weight, totalWeight) {
let row = $("<tr>")
let icon = $("<img>").attr('src', iconURL(id))
let itemName = $("<td>").text(getItemName(id))
let npcName = $("<td>").text(name)
let amount = $("<td>").text((min != max) ? min + "-" + max : min)
let debug = $("<div>").text("id: " + id).addClass(debugClass)
let rarity = ""
// Weights
if (weight != -1) {
let percent = (weight / totalWeight) * 100
rarity = $("<td>").text("1/" + (+parseFloat(100 / percent).toFixed(2).replace(/(\.0+|0+)$/, '')))
.prop('title', parseFloat((percent).toFixed(2)) + "%")
.attr('data-value', parseFloat((percent).toFixed(2)))
.addClass(rarityStyle(percent))
} else {
rarity = $("<td>").text("Always").addClass(rarityStyle(100))
.attr('data-value', parseFloat(100))
}
return row.append(npcName).append($("<td>").append(icon)).append(itemName.append(debug)).append(amount).append(rarity)[0]
}
function spaceToUnder(str) {
return str.replaceAll(' ', '_').toLowerCase()
}
function mapNPCItem(drops) {
for (const npc of drops) {
let name = npcNameMap[npc.ids.split(",")[0]]
let npcObj = new npcObject(npc.ids, name)
// Add default drops
npc['default'].forEach(drop => {
if(getItemName(drop.id) == undefined){
itemErrorMessage(npc,drop.id)
return
}
let name = spaceToUnder(getItemName(drop.id))
if (items[name])
items[name] += ("," + npc['ids'])
else
items[name] = npc['ids']
drop.weight = -1
npcObj.default.push(drop)
npcObj[name] = [drop]
})
// Normal drops
npc['main'].forEach(drop => {
if(getItemName(drop.id) == undefined){
itemErrorMessage(npc,drop.id)
return
}
let name = spaceToUnder(getItemName(drop.id))
npcObj.totalWeight += parseFloat(drop.weight)
if (items[name])
items[name] += ("," + npc['ids'])
else
items[name] = npc['ids']
npcObj.main.push(drop)
if (npcObj[name])
npcObj[name].push(drop)
else
npcObj[name] = [drop]
})
allNPCs[name] = npcObj
}
}
function mapNPCNames(npcs) {
Object.keys(npcs).forEach(npcName => {
npcs[npcName].split(",").every(id => npcNameMap[id] = npcName)
})
}
function search(e) {
let input = spaceToUnder(e.value)
let table = document.getElementById("dcontent")
table.innerHTML = ""
Object.keys(items).forEach(itemName => {
let itemDisplay = $("<tbody>")
if (input.length > 3 && itemName.includes(input)) {
console.log(input + " is like " + itemName)
let npcName = ""
let npcIDs = items[spaceToUnder(itemName)].split(",")
for (const npc of npcIDs) {
if (npcNameMap[npc] && npcNameMap[npc] != npcName) {
npcName = npcNameMap[npc]
if (allNPCs[npcName][itemName]) {
// For monsters dropping the same ID in different ways (count) increment index
try {
for (const item of allNPCs[npcName][itemName]) {
itemDisplay.append(newDisplayItem(npcName, item.id, item.minAmount, item.maxAmount, item.weight, allNPCs[npcName].totalWeight))
}
} catch (e) {
console.log("error in" + e)
}
}
}
}
if (itemDisplay[0].childElementCount > 0) {
let h1 = $("<h1>").addClass("hover-link").append($("<div>").text(prettyName(itemName)))
.on('mouseenter', function () {
$(this).text(prettyName(itemName)).append($("<img>").attr('src', ".././img/items/link.png"))
})
.on('click', function () {
window.location = window.location.toString().split('?')[0] + "?" + this.innerText
})
.on('mouseleave', function () {
$(this).find($("img")).remove()
})
table.appendChild($("<div>").append(h1)
.append($("<div>")
.addClass(debugClass)
.append($("<p>")
.text("NPC ids: " + npcIDs)))[0])
itemDisplay.on('click', function (e) {
e = e.currentTarget
// Classname is used to track the sorting direction
let sortOrder = (e.className === 'true');
e.className = 'true'
sortByRarity(e, !sortOrder)
})
table.append(itemDisplay[0])
}
}
});
}
window.addEventListener('load', () => {
let timeout = 0;
let checkExist = setInterval(function () {
if (allDrops != undefined && allNPCs != undefined && allItems != undefined) {
clearInterval(checkExist);
mapNPCNames(allNPCs)
mapNPCItem(allDrops)
searchURLString()
}
checkTimeout(timeout++)
}, 100);
});

View File

@ -1,118 +0,0 @@
function genDropMap(dropTable) {
for (let i = 0; i < dropTable.length; i += 1) {
dropTable[i]['ids'].split(",").forEach(id => {
dropMap[id] = i
})
}
}
function newDisplayItem(id, min, max, weight, totalWeight) {
let row = $("<tr></tr>")
let icon = $("<img>").attr('src', iconURL(id))
let itemName = $("<td>").text(getItemName(id))
let amount = $("<td>").text((min != max) ? min + "-" + max : min)
let debug = $("<div>").text("id: " + id).addClass(debugClass)
let rarity = ""
// Weights
if (weight != -1) {
let percent = (weight / totalWeight) * 100
rarity = $("<td>").text("1/" + (+parseFloat(100 / percent).toFixed(2).replace(/(\.0+|0+)$/, '')))
.prop('title', parseFloat((percent).toFixed(2)) + "%")
.attr('data-value', parseFloat((percent).toFixed(2)))
.addClass(rarityStyle(percent))
} else {
rarity = $("<td>").text("Always").addClass(rarityStyle(100))
.attr('data-value', parseFloat(100))
}
return row.append($("<td>").append(icon)).append(itemName.append(debug)).append(amount).append(rarity)[0]
}
function search(input) {
let searchStr = removeSpaces(input.value)
let table = document.getElementById("dcontent")
table.innerHTML = ""
//Search for matching ID
Object.keys(allNPCs).forEach(npcName => {
if (searchStr.length > 2 && removeSpaces(npcName).includes(searchStr)) {
console.log(searchStr + " is like " + npcName)
let npcEntry = $("<tbody>")
let npcIds = allNPCs[npcName].split(",")
let dropGIndex = null
let matched = false;
for(const id of npcIds){
if (!matched && dropMap[id]) {
dropGIndex = dropMap[id]
// Guaranteed / 'default' drops
for (let j = 0; j < allDrops[dropGIndex]['default'].length; j += 1) {
let id = allDrops[dropGIndex]['default'][j]["id"]
let min = allDrops[dropGIndex]['default'][j]["minAmount"]
let max = allDrops[dropGIndex]['default'][j]["maxAmount"]
npcEntry.append(newDisplayItem(id, min, max, -1, -1))
}
// Calculate combined/total weight of all normal drops
let totalWeight = 0.0
for (let j = 0; j < allDrops[dropGIndex]['main'].length; j += 1) {
totalWeight += parseFloat(allDrops[dropGIndex]['main'][j]["weight"])
}
// Normal drops
for (let j = 0; j < allDrops[dropGIndex]['main'].length; j += 1) {
let id = allDrops[dropGIndex]['main'][j]["id"]
let min = allDrops[dropGIndex]['main'][j]["minAmount"]
let max = allDrops[dropGIndex]['main'][j]["maxAmount"]
let weight = parseFloat(allDrops[dropGIndex]['main'][j]["weight"])
npcEntry.append(newDisplayItem(id, min, max, weight, totalWeight))
}
matched = true;
}
}
if (npcEntry[0].childElementCount > 0) {
let h1 = $("<h1>").addClass("hover-link").append($("<div>").text(npcName))
.on('mouseenter', function () {
$(this).text(npcName).append($("<img>").attr('src', ".././img/items/link.png"))
})
.on('click', function () {
window.location = window.location.toString().split('?')[0] + "?" + this.innerText
})
.on('mouseleave', function () {
$(this).find($("img")).remove()
})
table.appendChild($("<div>").append(h1)
.append($("<div>")
.addClass(debugClass)
.append($("<p>")
.text("ids: " + allNPCs[npcName])))[0])
npcEntry.on('click', function (e) {
e = e.currentTarget
// Classname is used to track the sorting direction
let sortOrder = (e.className === 'true');
e.className = 'true'
sortByRarity(e, !sortOrder)
})
table.appendChild(npcEntry[0])
}
}
})
}
window.addEventListener('load', () => {
let timeout = 0
let load = setInterval(function () {
if (allDrops && allNPCs && allItems) {
clearInterval(load)
genDropMap(allDrops)
searchURLString()
}
checkTimeout(timeout++)
}, 100)
})

View File

@ -1,174 +0,0 @@
let debugClass = "debug-hide"
let allNPCs = null
let allItems = null
let allDrops = null
let dropMap = {}
function sortByRarity(table, order) {
let switching = true;
let shouldSwitch = false;
let c = 0;
while (switching) {
switching = false
rows = table.rows;
let last = rows[0].getElementsByTagName("TD").length - 1
for (i = 0; i < (rows.length - 1); i++) {
c += 1
let x = rows[i].getElementsByTagName("TD")[last];
let y = rows[i + 1].getElementsByTagName("TD")[last];
let xval = parseFloat(x.getAttribute("data-value"));
let yval = parseFloat(y.getAttribute("data-value"));
if (!order) {
// We are already in order. Just invert the table.
$(table).each(function(){
var list = $(this).children('tr');
$(this).html(list.get().reverse())
});
break;
} else {
if (xval < yval) {
shouldSwitch = true
break;
}
}
shouldSwitch = false;
}
if (shouldSwitch) {
rows[i].parentNode.insertBefore(rows[i + 1], rows[i]);
switching = true;
}
}
console.log("Sorted in: ",c," steps")
}
function iconURL(id) {
switch (parseInt(id)) {
case 0:
return ".././img/items/nothing.png"
case 1:
//Clue Scroll (easy)
return ".././img/items/2677.png"
case 5733:
//Clue Scroll (medium)
return ".././img/items/2801.png"
case 12070:
//Clue Scroll (hard)
return ".././img/items/2722.png"
default:
return ".././img/items/" + id + ".png"
}
}
function getItemName(id) {
return allItems[id]
}
function rarityStyle(percent) {
if (percent > 99.99)
return "always"
if (percent > 4)
return "common"
if (percent > 1)
return "uncommon"
if (percent > 0.1)
return "rare"
return "veryrare"
}
function prettyName(name) {
let formatted = ""
let parts = name.split("_")
let i = 0
while (i < parts.length) {
let part = parts[i]
formatted += part[0].toUpperCase() + part.substring(1)
i += 1
if (i < parts.length)
formatted += " "
}
return formatted
}
function removeSpaces(str) {
return str.replaceAll(' ', '').toLowerCase()
}
window.addEventListener('load', () => {
async function getNPCIds() {
const response = await fetch('.././json/npc_config.json');
return await response.json();
}
async function getItemIds() {
const response = await fetch('.././json/item_config.json');
return await response.json();
}
async function getDrops() {
// Mirror fetches changes every 15 minutes from Gitlab
const response = await fetch('https://downthecrop.github.io/2009scape-mirror/Server/data/configs/drop_tables.json');
return await response.json();
}
// Fetch JSONS
getItemIds().then(j => {
// Edge cases
j["0"] = "Nothing"
j["12070"] = "Clue Scroll (hard)"
j["5733"] = "Clue Scroll (medium)"
j["1"] = "Clue Scroll (easy)"
allItems = j
})
getNPCIds().then(j => allNPCs = j)
getDrops().then(j => allDrops = j)
// Restore Debug option
if (localStorage.getItem('debug') === 'true') {
document.getElementById("debug-toggle").checked = true;
debugClass = "debug-show"
}
// Toggle Item and NPC ids
document.getElementById("debug-toggle").addEventListener("change", function () {
if (this.checked) {
const debug = document.querySelectorAll('.debug-hide');
debugClass = "debug-show"
debug.forEach(element => {
element.className = debugClass;
});
}
else {
const debug = document.querySelectorAll('.debug-show');
debugClass = "debug-hide"
debug.forEach(element => {
element.className = debugClass;
});
}
localStorage.setItem('debug', this.checked);
})
})
function checkTimeout(sec) {
// If loading JSONs takes longer than 600ms, show 'Loading JSON' message
// refresh the page on a 10 second timeout.
if (sec > 6) {
document.getElementsByClassName("loading")[0].setAttribute("style", "display:block;")
} else if (sec > 60) {
window.location.reload
}
}
function searchURLString() {
// Clear loading JSON message
document.getElementsByClassName("loading")[0].setAttribute("style", "display:none;")
// Load directly linked monster/item if there is a search
if (window.location.search) {
document.getElementsByTagName("input")[0].value = window.location.search.substring(1).replaceAll("%20", " ").replace(/%27/g, "'")
search(document.getElementsByTagName("input")[0])
}
}

View File

@ -1,162 +0,0 @@
let itemData
let duplicates = []
let filteredKeys = ["durability", "remove_head", "absorb", "bonuses", "archery_ticket_price",
"attack_anims", "attack_audios", "weapon_interface",
"walk_anim", "turn90cw_anim", "turn90ccw_anim", "run_anim", "stand_turn_anim", "turn180_anim",
"stand_anim", "stand_turn_anim", "render_anim","defence_anim"]
function newDisplayItem(itemObj) {
let debugState = (debugClass == "debug-show") ? true : false;
let row = $("<tr>")
let icon = $("<img>").attr('src', iconURL(itemObj.id))
let itemName = $("<td>").text(itemObj.name).append(icon)
let about = $("<td style='text-align:left;'>")
for (const [key, value] of Object.entries(itemObj)) {
// Filter some known values we don't care about
if (debugState) {
about.append($("<tr>").append(`<b>${key}</b>: ${value}`))
} else if (!filteredKeys.includes(key)) {
about.append($("<tr>").append(`<b>${key}</b>: ${value}`))
}
}
// Bonuses Order
// Attack: Stab, Slash, Crush, Magic, Ranged
// Defensive: Stab, Slash, Crush, Magic, Ranged, Summoning
// Other: Strength, Prayer
if (itemObj.bonuses) {
let stats = itemObj.bonuses.split(",")
let aStab = stats[0]
let aSlash = stats[1]
let aCrush = stats[2]
let aMagic = stats[3]
let aRanged = stats[4]
let dStab = stats[5]
let dSlash = stats[6]
let dCrush = stats[7]
let dMagic = stats[8]
let dRanged = stats[9]
let dSummoning = stats[10]
let strength = stats[11]
let prayer = stats[12]
let magicStr = stats[13]
let rangedStr = stats[14]
let attackBonusIcons = $("<tbody>").append($("<tr>"))
.append($("<td>").append($("<img>").attr('src', iconURL(1207))))
.append($("<td>").append($("<img>").attr('src', iconURL(1325))))
.append($("<td>").append($("<img>").attr('src', iconURL(1339))))
.append($("<td>").append($("<img>").attr('src', ".././img/alt/magic.png")))
.append($("<td>").append($("<img>").attr('src', ".././img/alt/ranged.png")))
let defenseBonusIcons = $("<tbody>").append($("<tr>"))
.append($("<td>").append($("<img>").attr('src', iconURL(1207))))
.append($("<td>").append($("<img>").attr('src', iconURL(1325))))
.append($("<td>").append($("<img>").attr('src', iconURL(1339))))
.append($("<td>").append($("<img>").attr('src', ".././img/alt/magic.png")))
.append($("<td>").append($("<img>").attr('src', ".././img/alt/ranged.png")))
.append($("<td>").append($("<img>").attr('src', ".././img/alt/summoning.png")))
let otherBonusIcons = $("<tbody>").append($("<tr>"))
.append($("<td>").append($("<img>").attr('src', ".././img/alt/Strength_icon.png")))
.append($("<td>").append($("<img>").attr('src', ".././img/alt/RangedStrength.png")))
.append($("<td>").append($("<img>").attr('src', ".././img/alt/MagicStrength.png")))
.append($("<td>").append($("<img>").attr('src', ".././img/alt/Prayer_icon.png")))
let attackBonus = $("<tr>")
.append($("<td>").append(aStab))
.append($("<td>").append(aSlash))
.append($("<td>").append(aCrush))
.append($("<td>").append(aMagic))
.append($("<td>").append(aRanged))
let defenseBonus = $("<tr>")
.append($("<td>").append(dStab))
.append($("<td>").append(dSlash))
.append($("<td>").append(dCrush))
.append($("<td>").append(dMagic))
.append($("<td>").append(dRanged))
.append($("<td>").append(dSummoning))
let otherBonus = $("<tr>")
.append($("<td>").append(strength))
.append($("<td>").append(rangedStr))
.append($("<td>").append(magicStr))
.append($("<td>").append(prayer))
row.append($("<div>").text("Attack bonuses").attr('class', 'stat-data'))
row.append(attackBonusIcons.append(attackBonus))
row.append($("<div>").text("Defense bonuses").attr('class', 'stat-data'))
row.append(defenseBonusIcons.append(defenseBonus))
row.append($("<div>").text("Other bonuses").attr('class', 'stat-data'))
row.append(otherBonusIcons.append(otherBonus))
}
return row.append(itemName).append(about)[0]
}
function spaceToUnder(str) {
return str.replaceAll(' ', '_').toLowerCase()
}
function search(e) {
let input = spaceToUnder(e.value)
let table = document.getElementById("dcontent")
table.innerHTML = ""
console.log(input)
for (const item of itemData) {
let itemDisplay = $("<tbody>")
if (input.length > 3 && spaceToUnder(item.name).includes(input)) {
console.log(input + " is like " + item.name)
if (duplicates.indexOf(item.id) == -1)
itemDisplay.append(newDisplayItem(item))
let h1 = $("<h1>").addClass("hover-link").append($("<div>").text(prettyName(item.name)))
.on('mouseenter', function () {
$(this).text(prettyName(item.name)).append($("<img>").attr('src', ".././img/items/link.png"))
})
.on('click', function () {
window.location = window.location.toString().split('?')[0] + "?" + this.innerText
})
.on('mouseleave', function () {
$(this).find($("img")).remove()
})
if (itemDisplay[0].innerHTML != "") {
table.appendChild($("<div>").append(h1)[0])
table.append(itemDisplay[0])
}
}
}
}
window.addEventListener('load', () => {
let timeout = 0;
async function getItems() {
// Mirror fetches changes every 15 minutes from Gitlab
const response = await fetch('https://downthecrop.github.io/2009scape-mirror/Server/data/configs/item_configs.json');
itemData = await response.json();
}
getItems();
let checkExist = setInterval(function () {
if (itemData != undefined) {
let checked = []
for (item of itemData) {
if (checked.indexOf(item.name) != -1) {
duplicates.push(item.id)
}
checked.push(item.name)
}
clearInterval(checkExist);
searchURLString()
}
checkTimeout(timeout++)
}, 100);
});

File diff suppressed because one or more lines are too long

View File

@ -1,177 +0,0 @@
/*
* This file doesn't use the common.js functions
* which makes it a mess. Tread carefully.
*/
var dropG
var itemG
var debugClass = "debug"
function sortTable(t){
for (i in t.path){
if(t.path[i].tagName == "TBODY"){
let sortOrder = true
if(t.path[i].className != undefined){
sortOrder = (t.path[i].className === 'true');
}
sortByRarity(t.path[i],!sortOrder)
}
}
}
function sortByRarity(table,order){
table.className = order
switching = true;
while (switching) {
switching = false;
rows = table.rows;
for (i = 0; i < (rows.length - 1); i++) {
shouldSwitch = false;
x = rows[i].getElementsByTagName("TD")[3];
y = rows[i + 1].getElementsByTagName("TD")[3];
// Splt at '/' and divide
let xEval = x.innerText.split('/')
xEval = parseFloat(xEval[0]/xEval[1])
let yEval = y.innerText.split('/')
yEval = parseFloat(yEval[0]/yEval[1])
if (order>0){
// Rarest LAST
if (xEval < yEval) {
shouldSwitch = true;
break;
}
}
else {
// Rarest FIRST
if (xEval > yEval) {
shouldSwitch = true;
break;
}
}
}
if (shouldSwitch) {
rows[i].parentNode.insertBefore(rows[i + 1], rows[i]);
switching = true;
}
}
}
function fillRDT(){
// creates a <table> element and a <tbody> element
var tblBody = document.createElement("tbody");
// Get the combined weight of everything for later
// Iterating the loop 2 times.. maybe don't do this at home.
let totalWeight = 0.0;
for (let j = 0; j < dropG.length; j += 1){
totalWeight += parseFloat(dropG[j]["weight"])
}
// Droptable Items
for (let j = 0; j < dropG.length; j += 1){
var row = document.createElement("tr");
var cell = document.createElement("td");
// Icon Cell
const itemIcon = document.createElement("img");
itemIcon.src = "./img/items/" + dropG[j]["id"] + ".png"
cell.appendChild(itemIcon);
row.appendChild(cell)
// Item Name Cell
var cell = document.createElement("td");
var cellText = document.createTextNode(itemG[dropG[j]["id"]]);
var debugDiv = document.createElement('div');
var debugText = document.createTextNode("id: "+dropG[j]["id"]);
debugDiv.className = debugClass
debugDiv.appendChild(debugText)
cell.appendChild(cellText);
cell.appendChild(debugDiv);
row.append(cell)
// Quantity
var cell = document.createElement("td");
if (dropG[j]["minAmt"] != dropG[j]["maxAmt"]){
amount = dropG[j]["minAmt"] + "-" + dropG[j]["maxAmt"]
} else {
amount = dropG[j]["minAmt"]
}
var cellText = document.createTextNode(amount);
cell.appendChild(cellText);
row.append(cell)
// Rarity
let weight = parseFloat(dropG[j]["weight"])
var cell = document.createElement("td");
var chance = (weight/totalWeight)*100
// Remove trailing zeros (Tried a bunch of stuff and couldn't get it out without)
var cellText = document.createTextNode("1/"+(+parseFloat(100/chance).toFixed(2).replace(/(\.0+|0+)$/, '')));
if (chance > 99.99){
cell.className = "always"
} else if (chance > 4){
cell.className = "common"
} else if (chance > 1) {
cell.className = "uncommon"
} else if (chance > 0.1){
cell.className = "rare"
} else {
cell.className = "veryrare"
}
cell.title = parseFloat((chance).toFixed(2)) + "%"
cell.appendChild(cellText);
row.append(cell)
// Append the TD items to the Row
tblBody.appendChild(row);
}
if (tblBody.innerText){
let h1 = document.createElement("h1")
let debugDiv = document.createElement('div')
debugDiv.className = debugClass
var debugText = document.createElement('p');
debugDiv.appendChild(debugText)
table.appendChild(h1)
table.appendChild(debugDiv)
sortByRarity(tblBody,true)
tblBody.addEventListener('click', function(e){
sortTable(e)
})
document.getElementById("table").appendChild(tblBody)
}
}
window.addEventListener('load', (event) => {
async function getItemIds() {
const response = await fetch('./json/item_config.json');
return await response.json();
}
async function getDrops() {
const response = await fetch('./json/rdt.json');
return await response.json();
}
// Fetch JSONS
function main(){
getItemIds().then(itemJ => {itemG = itemJ})
getDrops().then(dropJ => {dropG = dropJ})
}
main();
//Loading GUI
let counter = 0;
let checkExist = setInterval(function () {
if (dropG != undefined && itemG != undefined) {
clearInterval(checkExist);
document.getElementsByClassName("loading")[0].setAttribute("style","display:none;")
fillRDT();
}
if (counter > 6)
document.getElementsByClassName("loading")[0].setAttribute("style","display:block;")
counter += 1;
}, 100);
});

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,164 +0,0 @@
[
{
"id": "995",
"minAmt": "3000",
"maxAmt": "3000",
"weight": "12"
},
{
"id": "1452",
"minAmt": "1",
"maxAmt": "1",
"weight": "7"
},
{
"id": "1462",
"minAmt": "1",
"maxAmt": "1",
"weight": "7"
},
{
"id": "886",
"minAmt": "150",
"maxAmt": "150",
"weight": "10"
},
{
"id": "443",
"minAmt": "100",
"maxAmt": "100",
"weight": "7"
},
{
"id": "2363",
"minAmt": "1",
"maxAmt": "1",
"weight": "7"
},
{
"id": "1623",
"minAmt": "1",
"maxAmt": "1",
"weight": "12"
},
{
"id": "1621",
"minAmt": "1",
"maxAmt": "1",
"weight": "10"
},
{
"id": "1619",
"minAmt": "1",
"maxAmt": "1",
"weight": "8"
},
{
"id": "1617",
"minAmt": "1",
"maxAmt": "1",
"weight": "7"
},
{
"id": "1615",
"minAmt": "1",
"maxAmt": "1",
"weight": "5"
},
{
"id": "560",
"minAmt": "45",
"maxAmt": "45",
"weight": "6"
},
{
"id": "563",
"minAmt": "45",
"maxAmt": "45",
"weight": "6"
},
{
"id": "561",
"minAmt": "67",
"maxAmt": "67",
"weight": "6"
},
{
"id": "892",
"minAmt": "42",
"maxAmt": "42",
"weight": "6"
},
{
"id": "1319",
"minAmt": "1",
"maxAmt": "1",
"weight": "7"
},
{
"id": "1373",
"minAmt": "1",
"maxAmt": "1",
"weight": "7"
},
{
"id": "1185",
"minAmt": "1",
"maxAmt": "1",
"weight": "7"
},
{
"id": "829",
"minAmt": "20",
"maxAmt": "20",
"weight": "6"
},
{
"id": "830",
"minAmt": "5",
"maxAmt": "5",
"weight": "4"
},
{
"id": "987",
"minAmt": "1",
"maxAmt": "1",
"weight": "7"
},
{
"id": "985",
"minAmt": "1",
"maxAmt": "1",
"weight": "7"
},
{
"id": "1149",
"minAmt": "1",
"maxAmt": "1",
"weight": "3"
},
{
"id": "1201",
"minAmt": "1",
"maxAmt": "1",
"weight": "4"
},
{
"id": "1247",
"minAmt": "1",
"maxAmt": "1",
"weight": "1"
},
{
"id": "2366",
"minAmt": "1",
"maxAmt": "1",
"weight": "1"
},
{
"id": "1249",
"minAmt": "1",
"maxAmt": "1",
"weight": "1"
}
]

View File

@ -1,17 +0,0 @@
import json
with open('item_configs.json') as f:
data = json.load(f)
n = {}
i = 0
while i < len(data):
print(data[i]['id'])
if 'name' in data[i]:
n[data[i]['id']] = data[i]['name']
i += 1
with open("item_config.json", "w") as outfile:
json.dump(n, outfile)

View File

@ -1,25 +0,0 @@
'''
Rip only the required information from the
source json to make things load faster
'''
import json
with open('npc_configs.json') as f:
data = json.load(f)
n = {}
i = 0
while i < len(data):
print(data[i]['id'])
if 'name' in data[i]:
if n.get(data[i]['name']):
n[data[i]['name']] = n[data[i]['name']] + "," + data[i]['id']
else:
n[data[i]['name']] = data[i]['id']
i += 1
with open("npc_config.json", "w") as outfile:
json.dump(n, outfile)

View File

@ -1,20 +0,0 @@
import wget
import pathlib
#url = "https://wegame.gtimg.com/g.26-r.c2d3c/helper/lol/assis/images/resources/champions/"
#url = "https://wegame.gtimg.com/g.26-r.c2d3c/helper/lol/assis/images/resources/items/"
#url = "https://wegame.gtimg.com/g.26-r.c2d3c/helper/lol/assis/images/resources/summonability/"
url = "https://www.osrsbox.com/osrsbox-db/items-icons/"
path = str(pathlib.Path(__file__).parent.absolute())+"/items-icons/"
#i = 515
i = 100
#z = 0
while (i < 20000):
print(i)
try:
wget.download(url+str(i)+'.png', path+str(i)+'.png')
except:
print("error")
i += 1

View File

@ -2,8 +2,6 @@
title: Rare Drop Table
layout: guide
---
<script src="./js/jquery-3.6.0.min.js"></script>
<script src="./js/rdt.js"></script>
<link rel="stylesheet" href="./css/style.css">
<style>
#navhome{
@ -32,25 +30,17 @@ layout: guide
<div class="bottombordershad">
<div class="bottomleftshad">
<div class="bottomrightshad">
<!-- CONTENT HERE -->
<div class="links"><a href="./drop-table/">Drop Tables</a> | <a href="./item-source/">Item Sources</a> | <a href="./item-data/">Item Data</a></div>
<div id="wrapper" style="padding-bottom: 40px;">
<center>
<div class="headings">
<span class="headertitleleft"><span class="headertitleright" id="search">Rare Drop Table</span></span>
</div>
<p>Notes: The data on this page may become outdated.</p>
</center>
<div class="loading" style="display: none;">
<div class="stage">
<h1>Loading JSON</h1>
</div>
<div class="stage">
<div class="dot-pulse"></div>
</div>
</div>
<div id="table" style="margin:auto;width: 80%;"></div>
</div>
<center>
<br>
<br>
<div class="headings">
<span class="headertitleleft"><span class="headertitleright" id="search">Rare Drop Table</span></span>
</div>
<p>Notes: The data on this page may become outdated.</p>
</center>
<div id="table" style="margin:auto;width: 80%;"><h1></h1><table style="width:100%;"><tbody class="true"><tr><td><img src="./img/items/995.png"></td><td>Coins<div class="debug">id: 995</div></td><td>3000</td><td class="common" title="7.02%">1/14.25</td></tr><tr><td><img src="./img/items/1623.png"></td><td>Uncut sapphire<div class="debug">id: 1623</div></td><td>1</td><td class="common" title="7.02%">1/14.25</td></tr><tr><td><img src="./img/items/886.png"></td><td>Steel arrow<div class="debug">id: 886</div></td><td>150</td><td class="common" title="5.85%">1/17.1</td></tr><tr><td><img src="./img/items/1621.png"></td><td>Uncut emerald<div class="debug">id: 1621</div></td><td>1</td><td class="common" title="5.85%">1/17.1</td></tr><tr><td><img src="./img/items/1619.png"></td><td>Uncut ruby<div class="debug">id: 1619</div></td><td>1</td><td class="common" title="4.68%">1/21.38</td></tr><tr><td><img src="./img/items/1452.png"></td><td>Chaos talisman<div class="debug">id: 1452</div></td><td>1</td><td class="common" title="4.09%">1/24.43</td></tr><tr><td><img src="./img/items/1462.png"></td><td>Nature talisman<div class="debug">id: 1462</div></td><td>1</td><td class="common" title="4.09%">1/24.43</td></tr><tr><td><img src="./img/items/443.png"></td><td>Silver ore<div class="debug">id: 443</div></td><td>100</td><td class="common" title="4.09%">1/24.43</td></tr><tr><td><img src="./img/items/2363.png"></td><td>Runite bar<div class="debug">id: 2363</div></td><td>1</td><td class="common" title="4.09%">1/24.43</td></tr><tr><td><img src="./img/items/1617.png"></td><td>Uncut diamond<div class="debug">id: 1617</div></td><td>1</td><td class="common" title="4.09%">1/24.43</td></tr><tr><td><img src="./img/items/1319.png"></td><td>Rune 2h sword<div class="debug">id: 1319</div></td><td>1</td><td class="common" title="4.09%">1/24.43</td></tr><tr><td><img src="./img/items/1373.png"></td><td>Rune battleaxe<div class="debug">id: 1373</div></td><td>1</td><td class="common" title="4.09%">1/24.43</td></tr><tr><td><img src="./img/items/1185.png"></td><td>Rune sq shield<div class="debug">id: 1185</div></td><td>1</td><td class="common" title="4.09%">1/24.43</td></tr><tr><td><img src="./img/items/987.png"></td><td>Loop half of a key<div class="debug">id: 987</div></td><td>1</td><td class="common" title="4.09%">1/24.43</td></tr><tr><td><img src="./img/items/985.png"></td><td>Tooth half of a key<div class="debug">id: 985</div></td><td>1</td><td class="common" title="4.09%">1/24.43</td></tr><tr><td><img src="./img/items/560.png"></td><td>Death rune<div class="debug">id: 560</div></td><td>45</td><td class="uncommon" title="3.51%">1/28.5</td></tr><tr><td><img src="./img/items/563.png"></td><td>Law rune<div class="debug">id: 563</div></td><td>45</td><td class="uncommon" title="3.51%">1/28.5</td></tr><tr><td><img src="./img/items/561.png"></td><td>Nature rune<div class="debug">id: 561</div></td><td>67</td><td class="uncommon" title="3.51%">1/28.5</td></tr><tr><td><img src="./img/items/892.png"></td><td>Rune arrow<div class="debug">id: 892</div></td><td>42</td><td class="uncommon" title="3.51%">1/28.5</td></tr><tr><td><img src="./img/items/829.png"></td><td>Adamant javelin<div class="debug">id: 829</div></td><td>20</td><td class="uncommon" title="3.51%">1/28.5</td></tr><tr><td><img src="./img/items/1615.png"></td><td>Dragonstone<div class="debug">id: 1615</div></td><td>1</td><td class="uncommon" title="2.92%">1/34.2</td></tr><tr><td><img src="./img/items/830.png"></td><td>Rune javelin<div class="debug">id: 830</div></td><td>5</td><td class="uncommon" title="2.34%">1/42.75</td></tr><tr><td><img src="./img/items/1201.png"></td><td>Rune kiteshield<div class="debug">id: 1201</div></td><td>1</td><td class="uncommon" title="2.34%">1/42.75</td></tr><tr><td><img src="./img/items/1149.png"></td><td>Dragon med helm<div class="debug">id: 1149</div></td><td>1</td><td class="uncommon" title="1.75%">1/57</td></tr><tr><td><img src="./img/items/1247.png"></td><td>Rune spear<div class="debug">id: 1247</div></td><td>1</td><td class="rare" title="0.58%">1/171</td></tr><tr><td><img src="./img/items/2366.png"></td><td>Shield left half<div class="debug">id: 2366</div></td><td>1</td><td class="rare" title="0.58%">1/171</td></tr><tr><td><img src="./img/items/1249.png"></td><td>Dragon spear<div class="debug">id: 1249</div></td><td>1</td><td class="rare" title="0.58%">1/171</td></tr></tbody></table></div>
</div>
</div>
</div>
</div>
@ -64,6 +54,5 @@ layout: guide
</div>
</div>
</div>
<br class="clear">
</div>
</div>

View File

@ -0,0 +1,396 @@
export default {
template: `
<div v-if="dropTables && itemConfigs">
<div class="centered">
<input type="radio" v-model="pick" value="Drop Tables" checked />Drop Tables
<input type="radio" v-model="pick" value="Item Sources" />Item Sources
<input type="radio" v-model="pick" value="Item Data" />Item Data
<br>
<div class="headings">
<span class="headertitleleft"><span class="headertitleright" id="search">{{pick}}</span></span>
</div>
<br>
<input v-model="input" style="width:50%;" placeholder="NPC/Item Name">
<p>Notes: RDT Slot = Rare Drop Table <a href=".././rdt.html">(link)</a>, Summoning Charms are rolled separately</p>
<br>
</div>
<!-- NPC Droptables (bynpc) -->
<div v-if="pick == 'Drop Tables'">
<div v-for="npc in searchResults">
<h1>{{ npc.name }}</h1>
<p class="npcIds">NPC ids: {{ npc.ids }}</p>
<tbody>
<tr v-for="item in npc.items">
<td><img :src=iconURL(item.id)></td>
<td>{{item.name}} <br> id: {{item.id}}</td>
<td @click="sortAmount(npc)">
{{item.amount}}
<br>
<p style="font-size:12px">
{{item.expectedQuantity}}
</p>
</td>
<td :class=item.rarityStyle @click="sortFractional(npc)">{{item.fractional}}</td>
</tr>
</tbody>
</div>
</div>
<div v-if="pick == 'Item Sources'">
<!-- Item Sources (byitem) -->
<div v-for="item in searchResults">
<h1>{{ item.name }}</h1>
<p class="npcIds">NPC ids: {{ item.ids }}</p>
<tbody>
<tr v-for="npc in item.items">
<td>{{npc.name}}</td>
<td><img :src=iconURL(npc.id)></td>
<td>{{item.name}} <br> id: {{npc.id}}</td>
<td @click="sortAmount(item)">
{{npc.amount}}
<br>
<p style="font-size:12px">
{{npc.expectedQuantity}}
</p>
</td>
<td :class=npc.rarityStyle @click="sortFractional(item)">{{npc.fractional}}</td>
</tr>
</tbody>
</div>
</div>
<div v-if="pick == 'Item Data'">
<!-- Item Data (itemstats) -->
<div v-for="item in searchResults">
<h1>{{ item.name }}</h1>
<p class="npcIds">Item id: {{ item.id }}</p>
<tbody>
<tr>
<td v-if="item.bonuses" :set="bonus = getBonuses(item)">
<div class="stat-data">Attack bonuses</div>
<tbody>
<tr></tr>
<td><img src=".././img/items/1207.png"></td>
<td><img src=".././img/items/1325.png"></td>
<td><img src=".././img/items/1339.png"></td>
<td><img src=".././img/alt/magic.png"></td>
<td><img src=".././img/alt/ranged.png"></td>
<tr>
<td>{{bonus.aStab}}</td>
<td>{{bonus.aSlash}}</td>
<td>{{bonus.aCrush}}</td>
<td>{{bonus.aMagic}}</td>
<td>{{bonus.aRanged}}</td>
</tr>
</tbody>
<div class="stat-data">Defense bonuses</div>
<tbody>
<tr></tr>
<td><img src=".././img/items/1207.png"></td>
<td><img src=".././img/items/1325.png"></td>
<td><img src=".././img/items/1339.png"></td>
<td><img src=".././img/alt/magic.png"></td>
<td><img src=".././img/alt/ranged.png"></td>
<td><img src=".././img/alt/summoning.png"></td>
<tr>
<td>{{bonus.dStab}}</td>
<td>{{bonus.dSlash}}</td>
<td>{{bonus.dCrush}}</td>
<td>{{bonus.dMagic}}</td>
<td>{{bonus.dRanged}}</td>
<td>{{bonus.dSummoning}}</td>
</tr>
</tbody>
<div class="stat-data">Other bonuses</div>
<tbody>
<tr></tr>
<td><img src=".././img/alt/Strength_icon.png"></td>
<td><img src=".././img/alt/RangedStrength.png"></td>
<td><img src=".././img/alt/MagicStrength.png"></td>
<td><img src=".././img/alt/Prayer_icon.png"></td>
<tr>
<td>{{bonus.strength}}</td>
<td>{{bonus.rangedStr}}</td>
<td>{{bonus.magicStr}}</td>
<td>{{bonus.prayer}}</td>
</tr>
</tbody>
</td>
<td>{{item.name}} <img :src=iconURL(item.id)></td>
<td>
<p v-for="prop in dumpKeys(item)" style="text-align:left;margin:0;"><b>{{prop.key}}</b> {{prop.val}}</p>
</td>
</tr>
</tbody>
</div>
</div>
</div>
<div v-else>
<div class="centered">
<p>Loading JSON..</p>
</div>
</div>
`,
data() {
return {
dropTables: null,
itemConfigs: null,
itemIdToName: {},
npcObjects: {},
npcIdToName: {},
itemSourceNPCIds: {},
input: "",
pick: "Drop Tables",
searchResults: [],
}
},
methods: {
dumpKeys(item) {
const list = []
for (const [key, value] of Object.entries(item)) {
list.push({ key: key, val: value })
}
return list
},
getBonuses(item) {
const stats = item.bonuses.split(",")
return {
aStab: stats[0],
aSlash: stats[1],
aCrush: stats[2],
aMagic: stats[3],
aRanged: stats[4],
dStab: stats[5],
dSlash: stats[6],
dCrush: stats[7],
dMagic: stats[8],
dRanged: stats[9],
dSummoning: stats[10],
strength: stats[11],
prayer: stats[12],
magicStr: stats[13],
rangedStr: stats[14],
}
},
iconURL(id) {
switch (id) {
case 0: return "../img/items/nothing.png";
case 1: return "../img/items/2677.png"; //Clue Scroll (easy)
case 5733: return "../img/items/2801.png"; //Clue Scroll (medium)
case 12070: return "../img/items/2722.png"; //Clue Scroll (hard)
default: return "../img/items/" + id + ".png"
}
},
sortFractional(d) {
d.fractionSorted = !d.fractionSorted
if (d.fractionSorted) d.items.sort((a, b) => a.rarity - b.rarity);
else d.items.sort((a, b) => b.rarity - a.rarity);
},
sortAmount(d) {
d.amountSorted = !d.amountSorted
if (!d.amountSorted) d.items.sort((a, b) => a.maxAmount - b.maxAmount);
else d.items.sort((a, b) => b.maxAmount - a.maxAmount);
},
spaceToUnder(str) {
return str.replaceAll(' ', '_').toLowerCase()
},
search(input) {
this.searchResults = []
class Result {
constructor(name, ids) {
this.name = name;
this.ids = ids;
this.items = [];
}
}
class DisplayItem {
constructor(id, name, min, max, weight, totalWeight) {
this.percent = (weight / totalWeight) * 100;
this.id = parseInt(id);
this.name = name;
this.minAmount = parseInt(min);
this.maxAmount = parseInt(max);
this.amount = (min != max) ? min + "-" + max : min;
this.weight = weight;
this.totalWeight = totalWeight;
this.fractional = this.getFractional();
this.rarity = (this.weight != -1) ? parseFloat((this.percent).toFixed(2)) : 100;
this.rarityStyle = this.getStyle();
this.expectedQuantity = this.getExpectedQuantity();
}
getStyle() {
if (this.rarity > 99.99) return "always"
if (this.rarity > 4) return "common"
if (this.rarity > 1) return "uncommon"
if (this.rarity > 0.1) return "rare"
return "veryrare"
}
getFractional() {
if (this.weight === -1) return "Always"
return "1/" + (+parseFloat(100 / this.percent).toFixed(2).replace(/(\.0+|0+)$/, ''))
}
getExpectedQuantity() {
let t = 0;
const range = Array(this.maxAmount - this.minAmount + 1).fill(1).map((x, y) => this.minAmount + y);
return ((range.reduce((a, b) => a + b, t) / range.length * (this.rarity / 100))).toFixed(2)
}
}
if (input.length > 2) {
const searchTerm = this.spaceToUnder(input)
if (this.pick == "Item Sources") {
// byitem.js
Object.keys(this.itemSourceNPCIds).forEach(itemName => {
if (itemName.includes(searchTerm)) {
console.log(searchTerm + " is like item: " + itemName)
let npcName = ""
let npcIds = this.itemSourceNPCIds[this.spaceToUnder(itemName)]
const result = new Result(null, npcIds)
for (const id of npcIds.split(",")) {
if (this.npcIdToName[id] && this.npcIdToName[id] != npcName) {
npcName = this.npcIdToName[id]
if (this.npcObjects[npcName]) {
try {
for (const item of this.npcObjects[npcName][itemName]) {
if (result.name == null) result.name = item.name
result.items.push(new DisplayItem(item.id, npcName, item.minAmount, item.maxAmount, item.weight, this.npcObjects[npcName].totalWeight))
}
} catch (e) {
console.log("error in" + e)
}
}
}
}
this.searchResults.push(result)
}
})
} else if (this.pick == "Drop Tables") {
// bynpc.js
Object.keys(this.npcObjects).forEach(npcName => {
if (this.spaceToUnder(npcName).includes(searchTerm)) {
console.log(searchTerm + " is like npc: " + npcName)
const result = new Result(npcName, this.npcObjects[npcName].ids)
// Guaranteed / 'default' drops
for (const drop of this.npcObjects[npcName].default) {
result.items.push(new DisplayItem(drop.id, drop.name, drop.minAmount, drop.maxAmount, -1, -1))
}
// Normal / 'main' drops
for (const drop of this.npcObjects[npcName].main) {
result.items.push(new DisplayItem(drop.id, drop.name, drop.minAmount, drop.maxAmount, drop.weight, this.npcObjects[npcName].totalWeight))
}
this.searchResults.push(result)
}
})
} else if (this.pick == "Item Data") {
// itemdata.js
for (const item of this.itemConfigs) {
if (this.spaceToUnder(item.name).includes(searchTerm)) {
console.log(searchTerm + " is like itemData: " + item.name)
this.searchResults.push(item)
}
}
}
}
}
},
watch: {
input() { this.search(this.input) },
pick() { this.search(this.input) }
},
created() {
// Proxy is used because GitLAB has CORS restrictions while GitHUB doesn't.
// this is refreshed every 15 minutes. If it's out of sync ping @downthecrop
const PROXY = "https://downthecrop.github.io/2009scape-mirror/Server/data/configs/"
fetch(PROXY + "npc_configs.json").then(r => r.json()).then(npc_configs => {
for (const npc of npc_configs) {
this.npcIdToName[npc.id] = npc.name;
}
});
fetch(PROXY + "drop_tables.json").then(r => r.json()).then(drop_tables => this.dropTables = drop_tables);
fetch(PROXY + "item_configs.json").then(r => r.json()).then(item_configs => {
// Create a dictionary of item ids to item names
for (const item of item_configs) {
this.itemIdToName[item.id] = item.name
}
// Edge cases where an itemId is being used outside of its original name.
// eg 5733 is "Rotten potato" but is instead a medium clue.
this.itemIdToName["0"] = "Nothing"
this.itemIdToName["12070"] = "Clue Scroll (hard)"
this.itemIdToName["5733"] = "Clue Scroll (medium)"
this.itemIdToName["1"] = "Clue Scroll (easy)"
this.itemConfigs = item_configs;
})
let checkInterval = setInterval(() => {
if (this.itemConfigs && this.dropTables) {
clearInterval(checkInterval);
// Create an NPC object for each npc in the droptable
class NPCObject {
constructor(ids, name) {
this.ids = ids;
this.name = name;
this.totalWeight = 0
this.default = []
this.main = []
}
}
for (const npc of this.dropTables) {
let npcName = this.npcIdToName[npc.ids.split(",")[0]]
if (npcName === undefined) continue;
let npcObj = new NPCObject(npc.ids, npcName)
if (this.npcObjects[npcName]) {
console.log("Duplicate NPC:", npcName, " id: ", npc.ids)
npcName = npcName + npc.ids.split(",")[0]
}
// Add Guaranteed / default drops
npc['default'].forEach(drop => {
let itemName = this.spaceToUnder(this.itemIdToName[drop.id])
if (this.itemSourceNPCIds[itemName]) {
// Add the ids of the current NPC to item sourcelist of this drop
this.itemSourceNPCIds[itemName] += `,${npc['ids']}`
} else {
// This is the first NPC dropping this item.
this.itemSourceNPCIds[itemName] = npc['ids']
}
drop.weight = -1
drop.name = this.itemIdToName[drop.id]
npcObj.default.push(drop)
if (npcObj[itemName]) {
npcObj[itemName].push(drop)
} else {
npcObj[itemName] = [drop]
}
})
// Add Normal / main drops
npc['main'].forEach(drop => {
let itemName = this.spaceToUnder(this.itemIdToName[drop.id])
npcObj.totalWeight += parseFloat(drop.weight)
if (this.itemSourceNPCIds[itemName]) {
// Add the ids of the current NPC to item sourcelist of this drop
this.itemSourceNPCIds[itemName] += `,${npc['ids']}`
}
else {
// This is the first NPC dropping this item.
this.itemSourceNPCIds[itemName] = npc['ids']
}
drop.name = this.itemIdToName[drop.id]
npcObj.main.push(drop)
if (npcObj[itemName]) {
npcObj[itemName].push(drop)
} else {
npcObj[itemName] = [drop]
}
})
this.npcObjects[npcName] = npcObj
}
}
}, 100)
}
}