// ==UserScript== // @name Training School Tools // @namespace neopets // @version 2021.01.14 // @description try to take over the world! // @author wtmeow // @match http://www.neopets.com/pirates/academy.phtml?type=status* // @match http://www.neopets.com/island/training.phtml?type=status* // @match http://www.neopets.com/island/fight_training.phtml?type=status* // @require https://code.jquery.com/jquery-3.5.1.min.js // @downloadURL none // ==/UserScript== const PIN = "4365"; // set to "0" if you don't have PIN enabled for SDB const url = location.href; const itemID = { "One Dubloon Coin" : "12755", "Two Dubloon Coin" : "12756", "Five Dubloon Coin" : "12757", "Mau Codestone" : "7458", "Tai-Kai Codestone" : "7459", "Lu Codestone" : "7460", "Vo Codestone" : "7461", "Eo Codestone" : "7462", "Main Codestone" : "7463", "Zei Codestone" : "7464", "Orn Codestone" : "7465", "Har Codestone" : "7466", "Bri Codestone" : "7467", "Mag Codestone" : "22208", "Vux Codestone" : "22209", "Cui Codestone" : "22210", "Kew Codestone" : "22211", "Sho Codestone" : "22212", "Zed Codestone" : "22213" }; const process_url = location.pathname.replace(/\/(?!.+\/)/g, "/process_"); // Get list of all pets and stats let stats = {}; $("b").filter(function () { return this.innerHTML.includes(" (Level ") }).each(function (index, element) { const petName = $(element).text().split(" (Level")[0]; stats[petName] = {}; $(element).parent().parent().next().find("b").each(function (index2, element2) { const stat = $(element2).text(); switch (index2) { case 0: // Lvl stats[petName]["Lvl"] = parseInt(stat); break; case 1: // Str stats[petName]["Str"] = parseInt(stat); break; case 2: // Def stats[petName]["Def"] = parseInt(stat); break; case 3: // Mov stats[petName]["Mov"] = parseInt(stat); break; case 4: // Hp stats[petName]["Hp"] = parseInt(stat.split("/")[1]); break; case 5: return false; default: return false; } }); }); // Add floating div $(``).appendTo("body"); $("#floating-hide").on("click", function () { $("#quick-links").hide(300); $("#quick-links-show").show(300); }); $("#floating-show").on("click", function () { $("#quick-links-show").hide(300); $("#quick-links").show(300); }); // Add table $("b:contains('Current Course Status')").after(` `); // Create quick course table let tableRows = ``; for (let pet in stats) { const thisPet = stats[pet]; const withinLvlRange = url.includes("island/fight_training") || // Only pets >= Lv250 will appear on the page anyway url.includes("island/training") && thisPet["Lvl"] <= 250 || url.includes("pirates/academy") && thisPet["Lvl"] <= 40; if ($(`b:contains(${pet})`).text().includes("is not on a course") && withinLvlRange === true) { tableRows += ` ${pet}
${thisPet["Lvl"]}
${thisPet["Str"]}
${thisPet["Def"]}
${thisPet["Mov"]}
${thisPet["Hp"]}`; } } if (tableRows !== ``) { $("#courseTable").show(); $("#tableHeader").after(tableRows); $("#checkall input").each(function (index, element) { const $this = $(element); const stat = $this.attr("class").split("-")[1]; $this.on("change", function () { if ($this.prop("checked")) { $(":radio").filter(function () { return this.value === stat; }).each(function () { $(this).prop("checked", true); }); } }); }); $("#reset-all").on("click", function () { $(".courses :radio").each(function (index, element) { $(element).prop("checked", false); }); }); $("#train-all").on("click", function () { $(".courses input").each(function (index, element) { $(element).prop("disabled", true); // disable all radio buttons }); let training = []; $(".courses tbody").find("input:checked:not([name='checkall'])").each(function (index, element) { const pet = $(element).attr("name").split("-")[1]; const stat = $(element).val(); training.push([pet, stat]); }); (async () => { print(`[1 / ${training.length}]

Processing...`) for (let i = 0; i < training.length; i++) { const pet = training[i][0]; const stat = training[i][1]; const result = await startCourse(pet, stat); console.log(result); print(`[${i + 1} / ${training.length}]

${result["Pet"]} (${result["Course"]}) :

${result["Status"]}`); } location.reload(); })(); }); } // Replace complete course button const forms = $("form[action*='process_']"); // get all available "Complete course!" forms for (let i = 0; i < forms.length; i++) { let petName = forms.eq(i).find("input[name='pet_name']").val(); let completeButton = forms.eq(i).find(":submit[value='Complete Course!']"); completeButton.replaceWith(``); $(`#complete-${petName}`).on("click", function () { $(this).prop("disabled", true); completeCourse(this, petName); }); } // Add button to get dubloons/codestones from SDB // codestone $("a[href*='_training.phtml?type=pay&pet_name=']").each(function (index, element) { //let petName = $(element).attr("href").split("&pet_name=")[1]; let $p = $(element).next("p"); $p.before('
'); }); // dubloon $("b:contains(' Dubloon Coin')").each(function (index, element) { $(element).parent().parent().before(''); }); // Handler $(".getItems").each(function (index, element) { $(element).on("click", function () { $(this).prop("disabled", true); let items = []; if (url.includes("/island/")) { $(element).next("p").find("b:contains('Codestone')").each(function (index, element) { const codestone = $(element).text(); items.push(codestone); }); } if (url.includes("/pirates/")) { const dubloon = $(element).parentsUntil("table").eq(2).find("b").text(); items.push(dubloon); } (async () => $(this).html(await getItemsFromSDB(items)))(); }); }); /******************************** * * All quick links * ********************************/ // Get all items let getAllItems = []; $(".getItems").each(function (index, element) { // Codestones if (url.includes("/island/")) { $(element).next("p").find("b:contains('Codestone')").each(function (index2, element2) { const codestone = $(element2).text(); getAllItems.push(codestone); }); } // Dubloons if (url.includes("/pirates/")) { // wip } }); $("#getAll-button").on("click", function () { if (!getAllItems.length) { window.alert("No items to retrieve!"); return false; } $(this).prop("disabled", true); let printItems = {}; for (let i = 0; i < getAllItems.length; i++) { if (!printItems[getAllItems[i]]) { printItems[getAllItems[i]] = 0; } printItems[getAllItems[i]]++; } const itemList = JSON.stringify(printItems).replace(/,/g, "
").replace(/[{}"']/g, "").replace(/:(\d)/g, " (x$1)"); (async () => { $(this).html(await getItemsFromSDB(getAllItems)); print(`[${$("#nst").html().replace(/ NST/g, "")}]
Retrieved items:

${itemList}`); })(); }); // Complete all courses $("#completeAll-button").on("click", function () { if (!$(".completeButton").length) { window.alert("No courses to complete!"); return false; } $(this).prop("disabled", true); $(".completeButton").each(function (index, element) { const pet = $(element).attr("id").split("-")[1]; (async () => { const status = await completeCourse(element, pet); //print(); })(); }); }); // Pay all courses $("#payAll-button").on("click", function () { let payees = []; if (url.includes("/island/")) { $("a[href*='process_training']").each(function (index, element) { const pet = $(element).attr("href").split("name=")[1]; payees.push(pet); }); } else if (url.includes("/pirates/academy")) { $(":submit[value='Pay']").each(function (index, element) { const pet = $(element).prev().prev().val(); payees.push(pet); }); } if (payees.length) { $(this).prop("disabled", true); (async () => { for (let i = 0; i < payees.length; i++) { const pet = payees[i]; print(`[${i + 1} / ${payees.length}]

${pet} (Paying...)`); const status = await payCourse(pet); print(`[${i + 1} / ${payees.length}]

${pet} (${status})`); } location.replace(url); })(); } }); /******************************** * * Functions * *******************************/ function print(data) { $("#floating-results").html(`


${data}`); } function payCourse(pet) { return new Promise(resolve => { $.ajax({ type : "GET", url : `${process_url}?type=pay&pet_name=${pet}`, success : data => { resolve(`Success`); }, error : data => { resolve(`Error`); } }); }) } function completeCourse(element, pet) { const $this = $(element); $.ajax({ type : "POST", url : process_url, // async : false, data : { "type" : "complete", "pet_name" : pet }, success : (data, status) => { let stat = data.match(/increased (\w+)/)[1] || "error"; let bonus = data.includes("SUPER BONUS") ? parseInt(data.match(/SUPER BONUS - You went up (\d+) points/)[1]) : 1; console.log({ "pet" : pet, "status" : status, "stat" : stat, "bonus" : bonus }); let result = stat === "error" ? "error" : `Course complete!

+${bonus} ${stat}

`; $this.parent().parent().html(result); if (document.getElementById(`repeat-${pet}`)) { $(`#repeat-${pet}`).on("click", function () { $(this).prop("disabled", true); (async () => { const result = await startCourse(pet, stat); $(this).html(result["Status"]); setTimeout(function () { location.replace(url); }, 1000); })(); }); } } }); } function startCourse(pet, course) { return new Promise(resolve => { setTimeout(() => { $.ajax({ type : "POST", url : process_url, // async : false, data : { "type" : "start", "course_type" : course, "pet_name" : pet }, success : data => { let error = data.includes("Error:") ? `Error: ${data.split("Error: ")[1].split("")[0]}` : "Successful"; resolve({ "Pet" : pet, "Course" : course, "Status" : error }); } }); }, 1500); }) } function getItemsFromSDB(array) { return new Promise(resolve => { console.log(array); let postData = {}; let itemCount = {}; for (let i = 0; i < array.length; i++) { let id = itemID[array[i]]; if (!itemCount[id]) { itemCount[id] = 0; } itemCount[id]++; } for (let item in itemCount) { if (itemCount[item] > 0) { postData[`back_to_inv[${item}]`] = itemCount[item]; } } postData["category"] = "0"; postData["offset"] = "0"; if (PIN && PIN !== "0") { postData["pin"] = PIN.toString(); } $.ajax({ type : "POST", url : "/process_safetydeposit.phtml?checksub=scan", // async : false, data : postData, success : data => { let error = data.includes("Error:") ? `Error: ${data.split("Error: ")[1].split("")[0]}` : "Successful"; resolve(error); } }); }) }