// ==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
$(`
Hide
Quick links
`).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);
}
});
})
}