// ==UserScript==
// @name Bulk Join Raids
// @version 1.2
// @license MIT
// @namespace https://greasyfork.org/users/1159361
// @description UI for selecting and joining raids by difficulty with a draggable button
// @author Zaregoto_Gaming
// @match https://play.dragonsofthevoid.com/*
// @exclude https://play.dragonsofthevoid.com/#/login
// @grant none
// ==/UserScript==
(function() {
'use strict';
const raidMap = {
"r.lesser-tree-ent": "Lesser Tree Ent",
"r.superior-watcher": "Superior Watcher",
"r.elven-rangers": "Elven Rangers",
"r.greater-ent": "Greater Ent",
"r.sand-wyrm": "Sand Wyrm",
"r.corrupted-golem": "Corrupted Golem",
"r.naga-risaldar": "Naga Risaldar",
"r.galeohog": "Galeohog",
"r.naga-karamati": "Naga Karamati",
"r.jagar-the-red": "Jagar the Red",
"r.rotting-fen-lure": "Rotting Fen Lure",
"r.sentry-ghoul": "Sentry Ghoul",
"r.fallen-naga-subedar": "Fallen Naga Subedar",
"r.bone-dragon": "Bone Dragon"
};
const difficulties = ["easy", "hard", "legendary"];
function loadSettings() {
return JSON.parse(localStorage.getItem('autojoinRaidSettings')) || {};
}
function saveSettings(settings) {
localStorage.setItem('autojoinRaidSettings', JSON.stringify(settings));
}
function loadButtonPosition() {
return JSON.parse(localStorage.getItem('autojoinButtonPosition')) || { top: '40px', left: '10px' };
}
function saveButtonPosition(position) {
localStorage.setItem('autojoinButtonPosition', JSON.stringify(position));
}
function makeDraggable(element) {
let offsetX, offsetY, isDragging = false;
element.addEventListener('mousedown', (e) => {
isDragging = true;
offsetX = e.clientX - element.getBoundingClientRect().left;
offsetY = e.clientY - element.getBoundingClientRect().top;
element.style.cursor = 'grabbing';
});
document.addEventListener('mousemove', (e) => {
if (!isDragging) return;
let newX = e.clientX - offsetX;
let newY = e.clientY - offsetY;
newX = Math.max(0, Math.min(window.innerWidth - element.offsetWidth, newX));
newY = Math.max(0, Math.min(window.innerHeight - element.offsetHeight, newY));
element.style.top = `${newY}px`;
element.style.left = `${newX}px`;
element.style.right = 'auto';
});
document.addEventListener('mouseup', () => {
if (!isDragging) return;
isDragging = false;
element.style.cursor = 'grab';
saveButtonPosition({ top: element.style.top, left: element.style.left });
});
}
function createUI(button) {
const settings = loadSettings();
const ui = document.createElement("div");
ui.id = "autojoin-ui";
ui.style.position = "fixed";
ui.style.background = "#fff";
ui.style.padding = "10px";
ui.style.border = "1px solid black";
ui.style.borderRadius = "8px";
ui.style.boxShadow = "0 2px 6px rgba(0,0,0,0.2)";
ui.style.zIndex = "1000";
ui.style.maxHeight = "400px";
ui.style.overflowY = "auto";
const buttonRect = button.getBoundingClientRect();
ui.style.top = `${Math.min(window.innerHeight - 410, buttonRect.bottom + window.scrollY)}px`;
ui.style.left = `${Math.min(window.innerWidth - 300, buttonRect.left + window.scrollX)}px`;
const title = document.createElement("div");
title.innerHTML = `<strong>Bulk Join Settings</strong>`;
ui.appendChild(title);
const runButton = document.createElement("button");
runButton.textContent = "Join Selected Raids";
runButton.style.margin = "8px 0 12px 0";
runButton.onclick = joinSelectedRaids;
ui.appendChild(runButton);
Object.entries(raidMap).forEach(([id, name]) => {
const nameLabel = document.createElement("div");
nameLabel.textContent = name;
nameLabel.style.fontWeight = "bold";
ui.appendChild(nameLabel);
difficulties.forEach(diff => {
const checkbox = document.createElement("input");
checkbox.type = "checkbox";
checkbox.checked = settings[id]?.includes(diff) || false;
checkbox.onchange = () => {
if (!settings[id]) settings[id] = [];
if (checkbox.checked) {
if (!settings[id].includes(diff)) settings[id].push(diff);
} else {
settings[id] = settings[id].filter(d => d !== diff);
}
saveSettings(settings);
};
ui.appendChild(checkbox);
ui.appendChild(document.createTextNode(" " + diff.charAt(0).toUpperCase() + diff.slice(1)));
ui.appendChild(document.createElement("br"));
});
ui.appendChild(document.createElement("hr"));
});
document.body.appendChild(ui);
const customJoinTitle = document.createElement("div");
customJoinTitle.innerHTML = `<strong>Join by Paste:</strong>`;
ui.appendChild(customJoinTitle);
const textArea = document.createElement("textarea");
textArea.rows = 10;
textArea.cols = 40;
textArea.placeholder = "Paste lines like:\njoinraid,6aca59f3..., Corrupted Golem hard";
textArea.style.width = "100%";
textArea.style.marginBottom = "6px";
ui.appendChild(textArea);
const submitKeysButton = document.createElement("button");
submitKeysButton.textContent = "Join from Paste";
submitKeysButton.onclick = async () => {
const token = localStorage.token;
const lines = textArea.value.trim().split("\n");
const joinKeys = [];
for (let line of lines) {
const match = line.match(/^joinraid,([a-f0-9\-]+)/i);
if (match) {
joinKeys.push(match[1]);
}
}
let success = 0;
for (let key of joinKeys) {
try {
await joinraid(key, token);
success++;
} catch (e) {
console.error("Failed to join:", key, e);
}
}
alert(`Attempted to join ${joinKeys.length} raids. Successful: ${success}`);
};
ui.appendChild(submitKeysButton);
}
function addToggleButton() {
const button = document.createElement("button");
button.textContent = "⚔️ Bulk Join";
button.style.position = "fixed";
button.style.zIndex = "1001";
button.style.cursor = "grab";
const pos = loadButtonPosition();
button.style.top = pos.top;
button.style.left = pos.left;
button.onclick = () => {
const existingUI = document.getElementById("autojoin-ui");
if (existingUI) {
existingUI.remove();
} else {
createUI(button);
}
};
document.body.appendChild(button);
makeDraggable(button);
}
async function joinSelectedRaids() {
const token = localStorage.token;
const settings = loadSettings();
const publicRaids = await getpublicraids(token);
const activeRaids = await getactiveraids(token);
const toJoin = publicRaids.filter(raid => {
if (raid.health < 1000) return false;
if (activeRaids.some(r => r.id === raid.id)) return false;
return settings[raid.raidXmlId]?.includes(raid.difficulty);
});
let count = 0;
for (let raid of toJoin) {
await joinraid(raid.joinkey, token);
count++;
}
alert("Joined " + count + " raids");
}
async function getpublicraids(token) {
const res = await fetch("https://api.dragonsofthevoid.com/api/raid/public", {
headers: { authorization: token }
});
return res.json();
}
async function getactiveraids(token) {
const res = await fetch("https://api.dragonsofthevoid.com/api/raid/active", {
headers: { authorization: token }
});
return res.json();
}
async function joinraid(joinkey, token) {
const res = await fetch("https://api.dragonsofthevoid.com/api/raid/join/" + joinkey, {
headers: { authorization: token }
});
return res.json();
}
window.addEventListener("load", () => {
addToggleButton();
});
})();