// ==UserScript==
// @name Veyra - Reaction Farm
// @namespace http://tampermonkey.net/
// @version 1.7
// @description Auto farm reactions with stamina/farm HUD
// @match https://demonicscans.org/title/*/chapter/*
// @icon https://www.google.com/s2/favicons?sz=64&domain=demonicscans.org
// @grant none
// ==/UserScript==
(function() {
'use strict';
let isPaused = false;
let scriptStopped = false;
// --- HUD Setup ---
const hud = document.createElement("div");
hud.style.position = "fixed";
hud.style.bottom = "10px";
hud.style.right = "10px";
hud.style.background = "rgba(0,0,0,0.8)";
hud.style.color = "lime";
hud.style.fontSize = "14px";
hud.style.fontFamily = "monospace";
hud.style.padding = "8px 12px";
hud.style.borderRadius = "8px";
hud.style.zIndex = "99999";
hud.style.lineHeight = "1.5em";
hud.innerHTML = `
<div id="hud-status">⏳ Loading...</div>
<button id="hud-toggle" style="
margin-top:6px;
padding:4px 8px;
font-size:12px;
border:none;
border-radius:5px;
cursor:pointer;
">⏸ Pause</button>
`;
document.body.appendChild(hud);
const statusEl = document.getElementById("hud-status");
const toggleBtn = document.getElementById("hud-toggle");
toggleBtn.addEventListener("click", () => {
console.log("toggleBtn clicked - changing pause state");
isPaused = !isPaused;
toggleBtn.textContent = isPaused ? "▶ Resume" : "⏸ Pause";
hud.style.color = isPaused ? "yellow" : "lime";
console.log("toggleBtn finished - isPaused =", isPaused);
});
function getStamina() {
console.log("getStamina() start");
let staminaEl = document.evaluate(
'//*[@id="discuscontainer"]/div[1]/div[1]/div[2]/span[1]/span',
document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
if (!staminaEl) {
console.log("getStamina() end - element not found");
return null;
}
let [current, max] = staminaEl.innerText.split('/').map(s => parseInt(s.trim()));
console.log("getStamina() end - current:", current, "max:", max);
return { current, max };
}
function getFarm() {
console.log("getFarm() start");
let farmEl = document.evaluate(
'//*[@id="discuscontainer"]/div[1]/div[1]/div[2]/span[2]/span',
document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
if (!farmEl) {
console.log("getFarm() end - element not found");
return null;
}
let [current, max] = farmEl.innerText.split('/').map(s => parseInt(s.replace(/,/g, '').trim(), 10));
console.log("getFarm() end - current:", current, "max:", max);
return { current, max };
}
function updateHUD() {
console.log("updateHUD() start");
let staminaEl = document.evaluate(
'//*[@id="discuscontainer"]/div[1]/div[1]/div[2]/span[1]/span',
document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null
).singleNodeValue;
let farmEl = document.evaluate(
'//*[@id="discuscontainer"]/div[1]/div[1]/div[2]/span[2]/span',
document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null
).singleNodeValue;
let staminaText = staminaEl ? staminaEl.innerText.trim() : "0/0";
let farmText = farmEl ? farmEl.innerText.trim() : "0/0";
statusEl.innerText = `⚡ Stamina: ${staminaText}\n🌾 Farm: ${farmText}`;
console.log("updateHUD() end - HUD updated");
}
function checkLimits() {
console.log("checkLimits() start");
let stamina = getStamina();
let farm = getFarm();
if (!stamina || !farm) {
console.log("checkLimits() end - stamina or farm not found");
return false;
}
if (isPaused) {
console.log("⏸️ checkLimits() end - manually paused");
return false;
}
if (stamina.max - stamina.current <= 30) {
console.log("⏸️ checkLimits() end - stamina near limit:", stamina.current, "/", stamina.max);
hud.style.color = "orange";
return false;
}
if (farm.current >= farm.max) {
console.log("⏸️ checkLimits() end - farm limit reached:", farm.current, "/", farm.max);
hud.style.color = "red";
scriptStopped = true;
return false;
}
hud.style.color = "lime";
console.log("checkLimits() end - all limits okay");
return true;
}
function clickReaction() {
console.log("clickReaction() start");
let reaction = document.evaluate(
'/html/body/div[5]/center/div/div[1]/div[3]/div[1]',
document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
if (reaction) {
reaction.scrollIntoView();
reaction.click();
console.log("✅ clickReaction() end - clicked reaction on", window.location.href);
} else {
console.log("⚠️ clickReaction() end - reaction not found on", window.location.href);
}
}
function goNextPage() {
console.log("goNextPage() start");
let nextBtn = document.querySelector("body > div.chapter-info > div > a.nextchap");
if (nextBtn) {
console.log("➡️ goNextPage() end - navigating to next chapter:", nextBtn.href);
window.location.href = nextBtn.href;
} else {
console.log("❌ goNextPage() end - next button not found, stopping script");
statusEl.innerText = "❌ Next button not found. Stopping script.";
scriptStopped = true;
}
}
function run() {
console.log("run() start");
updateHUD();
if (!checkLimits()) {
if (scriptStopped) {
console.log("run() end - script stopped");
return;
}
console.log("run() paused, will retry in 5s");
setTimeout(run, 5000);
return;
}
clickReaction();
setTimeout(() => {
goNextPage();
console.log("run() end");
}, 1500);
}
window.addEventListener('load', () => {
console.log("Window loaded - starting script");
setTimeout(run, 2000);
});
})();