A GUI tool containing a macro, click keybinds, themes, joysticks, etc.
// ==UserScript==
// @name Dominum Macro
// @namespace http://tampermonkey.net/
// @version 1.0
// @description A GUI tool containing a macro, click keybinds, themes, joysticks, etc.
// @author DominumNetwork
// @license MIT
// @match *://*/*
// @grant none
// ==/UserScript==
(function () {
'use strict';
const isTop = window === window.top;
const InputSimulator = {
getCenter(el) { const rect = el.getBoundingClientRect(); return { x: rect.left + rect.width / 2, y: rect.top + rect.height / 2 }; },
dispatchTouch(action, x, y, pointerId) {
let el = document.elementFromPoint(x, y);
if (isTop && el && el.tagName === 'IFRAME') {
let rect = el.getBoundingClientRect();
let relativeX = x - rect.left;
let relativeY = y - rect.top;
try {
el.contentWindow.postMessage({ icos: true, type: 'touch', action: action, x: relativeX, y: relativeY, pointerId: pointerId }, '*');
} catch(e) {}
return;
}
el = el || document.body;
let type = action === 'down' ? 'pointerdown' : 'pointerup';
el.dispatchEvent(new PointerEvent(type, { pointerId: pointerId, pointerType: 'touch', clientX: x, clientY: y, bubbles: true, cancelable: true, view: window, isPrimary: pointerId === 1 }));
let mType = action === 'down' ? 'mousedown' : 'mouseup';
el.dispatchEvent(new MouseEvent(mType, { clientX: x, clientY: y, bubbles: true, cancelable: true, view: window }));
if (action === 'up') el.dispatchEvent(new MouseEvent('click', { clientX: x, clientY: y, bubbles: true, cancelable: true }));
},
dispatchKey(type, key) {
let code = 'Key' + key.toUpperCase(); if (key.startsWith('Arrow')) code = key; if (key === 'Space') code = 'Space';
document.dispatchEvent(new KeyboardEvent(type, { key: key, code: code, keyCode: key.charCodeAt(0) || 0, bubbles: true, cancelable: true, composed: true }));
if (isTop) {
document.querySelectorAll('iframe').forEach(ifr => {
try { ifr.contentWindow.postMessage({ icos: true, type: 'key', action: type, key: key }, '*'); } catch(e){}
});
}
}
};
if (!isTop) {
window.addEventListener('message', (e) => {
if (!e.data || !e.data.icos) return;
if (e.data.type === 'touch') {
InputSimulator.dispatchTouch(e.data.action, e.data.x, e.data.y, e.data.pointerId);
} else if (e.data.type === 'key') {
let code = 'Key' + e.data.key.toUpperCase(); if (e.data.key.startsWith('Arrow')) code = e.data.key; if (e.data.key === 'Space') code = 'Space';
document.dispatchEvent(new KeyboardEvent(e.data.action, { key: e.data.key, code: code, keyCode: e.data.key.charCodeAt(0) || 0, bubbles: true, cancelable: true, composed: true }));
}
});
return;
}
const css = `
:root { --icos-bg: rgba(20, 22, 28, 0.85); --icos-bg-solid: #14161c; --icos-header: rgba(35, 38, 48, 0.95); --icos-border: rgba(255, 255, 255, 0.1); --icos-accent: #00e6b8; --icos-text: #e0e0e0; --icos-text-muted: #888; --icos-danger: #ff4a4a; --icos-success: #4aff80; --icos-radius: 12px; --icos-font: 'Inter', 'Segoe UI', system-ui, sans-serif; --icos-shadow: 0 16px 40px rgba(0, 0, 0, 0.6); --icos-blur: blur(12px); }
[data-icos-theme="light"] { --icos-bg: rgba(245, 245, 250, 0.9); --icos-bg-solid: #f5f5fa; --icos-header: #ffffff; --icos-border: rgba(0, 0, 0, 0.1); --icos-accent: #0066ff; --icos-text: #1a1a24; --icos-text-muted: #666; }
[data-icos-theme="cyberpunk"] { --icos-bg: rgba(9, 2, 16, 0.9); --icos-bg-solid: #090210; --icos-header: #fcee0a; --icos-border: #00ff00; --icos-accent: #ff003c; --icos-text: #00ff00; --icos-text-muted: #008800; --icos-danger: #ff0000; }
[data-icos-theme="synthwave"] { --icos-bg: rgba(36, 17, 54, 0.9); --icos-bg-solid: #241136; --icos-header: #ff00a0; --icos-border: #00e5ff; --icos-accent: #00e5ff; --icos-text: #ffb8ff; }
[data-icos-theme="hacker"] { --icos-bg: rgba(0, 0, 0, 0.9); --icos-bg-solid: #000000; --icos-header: #001100; --icos-border: #00ff00; --icos-accent: #00ff00; --icos-text: #00ff00; --icos-text-muted: #005500; }
[data-icos-theme="dracula"] { --icos-bg: rgba(40, 42, 54, 0.9); --icos-bg-solid: #282a36; --icos-header: #44475a; --icos-border: #6272a4; --icos-accent: #ff79c6; --icos-text: #f8f8f2; }
[data-icos-theme="nord"] { --icos-bg: rgba(46, 52, 64, 0.9); --icos-bg-solid: #2e3440; --icos-header: #3b4252; --icos-border: #4c566a; --icos-accent: #88c0d0; --icos-text: #eceff4; }
[data-icos-theme="monokai"] { --icos-bg: rgba(39, 40, 34, 0.9); --icos-bg-solid: #272822; --icos-header: #3e3d32; --icos-border: #75715e; --icos-accent: #a6e22e; --icos-text: #f8f8f2; }
[data-icos-theme="gruvbox"] { --icos-bg: rgba(40, 40, 40, 0.9); --icos-bg-solid: #282828; --icos-header: #3c3836; --icos-border: #504945; --icos-accent: #fabd2f; --icos-text: #ebdbb2; }
[data-icos-theme="oceanic"] { --icos-bg: rgba(15, 28, 46, 0.9); --icos-bg-solid: #0f1c2e; --icos-header: #1f3a5f; --icos-border: #375a7f; --icos-accent: #00b4d8; --icos-text: #caf0f8; }
[data-icos-theme="crimson"] { --icos-bg: rgba(20, 0, 0, 0.9); --icos-bg-solid: #140000; --icos-header: #330000; --icos-border: #660000; --icos-accent: #ff0000; --icos-text: #ffcccc; }
[data-icos-theme="amethyst"] { --icos-bg: rgba(26, 15, 46, 0.9); --icos-bg-solid: #1a0f2e; --icos-header: #2d1a4d; --icos-border: #4a2b80; --icos-accent: #b366ff; --icos-text: #e6ccff; }
[data-icos-theme="bumblebee"] { --icos-bg: rgba(20, 20, 20, 0.9); --icos-bg-solid: #141414; --icos-header: #ffd700; --icos-border: #cca800; --icos-accent: #ffea00; --icos-text: #ffffff; --icos-text-muted: #aaaaaa; }
[data-icos-theme="neon_tokyo"] { --icos-bg: rgba(10, 10, 20, 0.9); --icos-bg-solid: #0a0a14; --icos-header: #1a1a3a; --icos-border: #ff00ff; --icos-accent: #00ffff; --icos-text: #ffffff; }
[data-icos-theme="midnight"] { --icos-bg: rgba(0, 0, 0, 0.95); --icos-bg-solid: #000000; --icos-header: #111111; --icos-border: #333333; --icos-accent: #ffffff; --icos-text: #ffffff; }
[data-icos-theme="forest"] { --icos-bg: rgba(10, 26, 15, 0.9); --icos-bg-solid: #0a1a0f; --icos-header: #14331d; --icos-border: #265935; --icos-accent: #4ade80; --icos-text: #dcfce7; }
[data-icos-theme="sunset"] { --icos-bg: rgba(46, 20, 30, 0.9); --icos-bg-solid: #2e141e; --icos-header: #5c273d; --icos-border: #8a3a5c; --icos-accent: #ff7b54; --icos-text: #ffe0d6; }
@keyframes icos-fade-in { from { opacity: 0; transform: translateY(-10px) scale(0.98); } to { opacity: 1; transform: translateY(0) scale(1); } }
@keyframes icos-slide-up { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } }
@keyframes icos-rgb-border { 0% { background-position: 0% 50%; } 100% { background-position: 200% 50%; } }
#icos-root { position: fixed; top: 20px; right: 20px; z-index: 9999999; width: 380px; max-height: 85vh; display: flex; flex-direction: column; border-radius: var(--icos-radius); font-family: var(--icos-font); box-shadow: var(--icos-shadow); transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1); animation: icos-fade-in 0.4s ease-out; box-sizing: border-box; user-select: none; }
#icos-root.icos-minimized { height: 46px !important; min-height: 46px !important; overflow: hidden; width: 250px; }
#icos-root.icos-hidden { opacity: 0; pointer-events: none; transform: scale(0.95); }
#icos-root.icos-perf * { animation: none !important; transition: none !important; backdrop-filter: none !important; box-shadow: none !important; text-shadow: none !important; }
#icos-root.icos-perf .icos-rgb-wrapper { display: none !important; }
#icos-root.icos-perf #icos-inner { background: var(--icos-bg-solid) !important; }
.icos-rgb-wrapper { position: absolute; top: -2px; left: -2px; right: -2px; bottom: -2px; background: linear-gradient(90deg, #ff0000, #ff7f00, #ffff00, #00ff00, #0000ff, #4b0082, #9400d3, #ff0000); background-size: 200% 100%; border-radius: calc(var(--icos-radius) + 2px); z-index: -1; animation: icos-rgb-border 3s linear infinite; opacity: 0; transition: opacity 0.4s ease; }
#icos-root.rgb-active .icos-rgb-wrapper { opacity: 1; }
#icos-inner { background: var(--icos-bg); backdrop-filter: var(--icos-blur); -webkit-backdrop-filter: var(--icos-blur); border-radius: var(--icos-radius); display: flex; flex-direction: column; height: 100%; width: 100%; border: 1px solid var(--icos-border); overflow: hidden; }
#icos-header { background: var(--icos-header); color: var(--icos-text); padding: 12px 16px; cursor: move; display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid var(--icos-border); flex-shrink: 0; height: 46px; box-sizing: border-box; }
.icos-header-title { font-weight: 700; font-size: 14px; display: flex; align-items: center; gap: 8px; }
.icos-header-controls { display: flex; gap: 10px; }
.icos-btn-icon { background: none; border: none; color: var(--icos-text-muted); cursor: pointer; font-size: 16px; padding: 2px; transition: 0.2s; display: flex; align-items: center; justify-content: center; }
.icos-btn-icon:hover { color: var(--icos-text); transform: scale(1.1); }
.icos-btn-icon.close:hover { color: var(--icos-danger); }
#icos-body { padding: 16px; overflow-y: auto; overflow-x: hidden; flex-grow: 1; display: flex; flex-direction: column; gap: 20px; }
#icos-body::-webkit-scrollbar { width: 6px; }
#icos-body::-webkit-scrollbar-track { background: transparent; }
#icos-body::-webkit-scrollbar-thumb { background: var(--icos-border); border-radius: 10px; }
#icos-body::-webkit-scrollbar-thumb:hover { background: var(--icos-accent); }
.icos-section { background: rgba(0,0,0,0.2); border: 1px solid var(--icos-border); border-radius: 8px; padding: 14px; position: relative; }
[data-icos-theme="light"] .icos-section { background: rgba(255,255,255,0.5); }
.icos-section-title { font-size: 11px; text-transform: uppercase; letter-spacing: 1px; color: var(--icos-accent); margin: 0 0 12px 0; font-weight: 800; }
.icos-row { display: flex; gap: 8px; margin-bottom: 8px; align-items: center; }
.icos-input { background: rgba(0,0,0,0.3); border: 1px solid var(--icos-border); color: var(--icos-text); padding: 8px 12px; border-radius: 6px; font-family: var(--icos-font); font-size: 13px; outline: none; transition: 0.2s; width: 100%; box-sizing: border-box; text-align: center; font-weight: 600; }
[data-icos-theme="light"] .icos-input { background: #fff; }
.icos-input:focus { border-color: var(--icos-accent); box-shadow: 0 0 8px rgba(0, 230, 184, 0.3); }
.icos-select { background: rgba(0,0,0,0.3); border: 1px solid var(--icos-border); color: var(--icos-text); padding: 8px; border-radius: 6px; font-family: var(--icos-font); width: 100%; outline: none; cursor: pointer; }
.icos-btn { background: var(--icos-header); border: 1px solid var(--icos-border); color: var(--icos-text); padding: 8px 16px; border-radius: 6px; font-family: var(--icos-font); font-size: 13px; font-weight: 600; cursor: pointer; transition: all 0.2s; text-align: center; outline: none; display: flex; align-items: center; justify-content: center; gap: 6px; }
.icos-btn:hover { background: var(--icos-accent); color: var(--icos-bg-solid); border-color: var(--icos-accent); }
.icos-btn:active { transform: scale(0.96); }
.icos-btn-primary { background: rgba(0, 230, 184, 0.1); border-color: var(--icos-accent); color: var(--icos-accent); }
.icos-btn-primary:hover { background: var(--icos-accent); color: var(--icos-bg-solid); }
.icos-btn-danger { color: var(--icos-danger); border-color: rgba(255, 74, 74, 0.3); }
.icos-btn-danger:hover { background: var(--icos-danger); color: #fff; border-color: var(--icos-danger); }
.icos-marker { position: fixed; z-index: 999998; width: 34px; height: 34px; background: rgba(0, 230, 184, 0.15); border: 2px solid var(--icos-accent); border-radius: 50%; display: flex; justify-content: center; align-items: center; color: var(--icos-text); font-family: var(--icos-font); font-weight: 800; font-size: 14px; text-shadow: 0 2px 4px rgba(0,0,0,0.8); cursor: move; user-select: none; transform: translate(-50%, -50%); backdrop-filter: blur(2px); box-shadow: 0 0 15px rgba(0, 230, 184, 0.3); transition: border-color 0.2s, box-shadow 0.2s; }
.icos-marker.active { background: var(--icos-accent); color: var(--icos-bg-solid); text-shadow: none; box-shadow: 0 0 20px var(--icos-accent); transform: translate(-50%, -50%) scale(0.9); }
.icos-marker::after { content: '✛'; position: absolute; color: white; opacity: 0.3; font-size: 12px; pointer-events:none; }
.icos-joystick-container { position: fixed; z-index: 999997; width: 140px; height: 140px; border-radius: 50%; background: rgba(0, 0, 0, 0.4); border: 2px solid var(--icos-border); backdrop-filter: blur(4px); box-shadow: 0 10px 30px rgba(0,0,0,0.5); display: flex; justify-content: center; align-items: center; transition: opacity 0.3s; }
.icos-joystick-header { position: absolute; top: -30px; left: 50%; transform: translateX(-50%); background: var(--icos-header); color: var(--icos-text); font-size: 10px; padding: 4px 10px; border-radius: 12px; border: 1px solid var(--icos-border); cursor: move; white-space: nowrap; font-weight: 700; letter-spacing: 1px; }
.icos-joystick-knob { width: 48px; height: 48px; border-radius: 50%; background: var(--icos-accent); position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); cursor: pointer; box-shadow: inset 0 -4px 10px rgba(0,0,0,0.3), 0 5px 15px rgba(0, 230, 184, 0.4); transition: transform 0.1s ease-out, background 0.2s; }
.icos-joystick-knob:active { background: #fff; box-shadow: 0 0 20px #fff; }
.icos-joy-config { background: rgba(0,0,0,0.1); border-radius: 6px; padding: 10px; margin-bottom: 10px; border: 1px dashed var(--icos-border); }
#icos-toast-container { position: fixed; bottom: 20px; right: 20px; z-index: 9999999; display: flex; flex-direction: column; gap: 10px; pointer-events: none; }
.icos-toast { background: var(--icos-header); color: var(--icos-text); padding: 10px 16px; border-radius: 8px; border-left: 4px solid var(--icos-accent); font-family: var(--icos-font); font-size: 13px; box-shadow: var(--icos-shadow); animation: icos-slide-up 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275); }
.icos-hint { font-size: 11px; color: var(--icos-text-muted); margin-top: -4px; margin-bottom: 8px; display: block; }
.icos-flex-between { display: flex; justify-content: space-between; align-items: center; }
`;
const styleTag = document.createElement('style'); styleTag.innerHTML = css; document.head.appendChild(styleTag);
const STATE = { theme: 'dark', rgbEnabled: false, minimized: false, hidden: false, perfMode: false, isRecordingMacro: false, macroData: [], macroStart: 0, macroTimers: [], heldKeys: new Set(), joysticksHidden: false };
const uid = () => Math.random().toString(36).substr(2, 9);
const Toast = {
container: null,
init() { this.container = document.createElement('div'); this.container.id = 'icos-toast-container'; document.body.appendChild(this.container); },
show(msg, color = 'var(--icos-accent)') {
if (!this.container) this.init(); const el = document.createElement('div'); el.className = 'icos-toast'; el.style.borderLeftColor = color; el.innerText = msg; this.container.appendChild(el);
setTimeout(() => { el.style.opacity = '0'; el.style.transform = 'translateY(20px)'; el.style.transition = 'all 0.3s'; setTimeout(() => el.remove(), 300); }, 3000);
}
};
class Draggable {
constructor(element, handle, isCenterAnchored = false) {
this.element = element; this.handle = handle || element; this.isCenterAnchored = isCenterAnchored; this.isDragging = false; this.xOffset = 0; this.yOffset = 0;
this.handle.addEventListener("mousedown", this.dragStart.bind(this)); window.addEventListener("mouseup", this.dragEnd.bind(this)); window.addEventListener("mousemove", this.drag.bind(this));
}
dragStart(e) {
if (e.target.tagName === 'INPUT' || e.target.tagName === 'BUTTON') return;
const rect = this.element.getBoundingClientRect();
if (this.isCenterAnchored) { this.xOffset = e.clientX - (rect.left + rect.width / 2); this.yOffset = e.clientY - (rect.top + rect.height / 2); } else { this.xOffset = e.clientX - rect.left; this.yOffset = e.clientY - rect.top; }
if (e.target === this.handle || this.handle.contains(e.target)) { this.isDragging = true; document.body.style.userSelect = 'none'; }
}
dragEnd() { this.isDragging = false; document.body.style.userSelect = ''; }
drag(e) {
if (!this.isDragging) return; e.preventDefault(); let newX = e.clientX - this.xOffset, newY = e.clientY - this.yOffset;
if (this.isCenterAnchored) { this.element.style.left = `${newX}px`; this.element.style.top = `${newY}px`; this.element.style.transform = `translate(-50%, -50%)`; } else { this.element.style.left = `${newX}px`; this.element.style.top = `${newY}px`; this.element.style.right = 'auto'; }
}
}
class BindManager {
constructor(listElement) { this.listEl = listElement; this.binds = []; this.pointerCounter = 100; }
addBind() {
const id = uid(); const pointerId = this.pointerCounter++;
const marker = document.createElement('div'); marker.className = 'icos-marker'; marker.style.left = `${window.innerWidth / 2}px`; marker.style.top = `${window.innerHeight / 2}px`; marker.innerText = '•';
document.body.appendChild(marker); new Draggable(marker, marker, true);
const row = document.createElement('div'); row.className = 'icos-row'; row.id = `bind-row-${id}`;
row.innerHTML = `<input type="text" class="icos-input" placeholder="Press Key..." maxlength="15" style="width: 70%; text-transform: uppercase;"><button class="icos-btn icos-btn-danger" style="width: 30%;">✖</button>`;
const input = row.querySelector('input');
input.addEventListener('keydown', (e) => { e.preventDefault(); const key = e.key === ' ' ? 'Space' : e.key; input.value = key.toUpperCase(); marker.innerText = key.toUpperCase(); const b = this.binds.find(x => x.id === id); if (b) b.key = key; });
row.querySelector('button').addEventListener('click', () => { row.remove(); marker.remove(); this.binds = this.binds.filter(x => x.id !== id); Toast.show('Bind removed.', 'var(--icos-danger)'); });
this.listEl.appendChild(row); this.binds.push({ id: id, pointerId: pointerId, key: '', marker: marker }); Toast.show('New target created.');
}
hideMarkers() { this.binds.forEach(b => b.marker.style.display = 'none'); }
showMarkers() { if(STATE.hidden) return; this.binds.forEach(b => b.marker.style.display = 'flex'); }
handleKeyDown(key) { const bind = this.binds.find(b => b.key.toLowerCase() === key.toLowerCase()); if (bind) { bind.marker.classList.add('active'); this.hideMarkers(); const pos = InputSimulator.getCenter(bind.marker); this.showMarkers(); InputSimulator.dispatchTouch('down', pos.x, pos.y, bind.pointerId); } }
handleKeyUp(key) { const bind = this.binds.find(b => b.key.toLowerCase() === key.toLowerCase()); if (bind) { bind.marker.classList.remove('active'); this.hideMarkers(); const pos = InputSimulator.getCenter(bind.marker); this.showMarkers(); InputSimulator.dispatchTouch('up', pos.x, pos.y, bind.pointerId); } }
}
class JoystickManager {
constructor(listElement) { this.listEl = listElement; this.joysticks = []; }
addJoystick() {
const id = uid(); const wrapper = document.createElement('div'); wrapper.className = 'icos-joystick-container'; wrapper.id = `joy-wrap-${id}`; wrapper.style.left = '100px'; wrapper.style.top = '100px';
wrapper.innerHTML = `<div class="icos-joystick-header">JOYSTICK</div><div class="icos-joystick-knob"></div>`; document.body.appendChild(wrapper);
const header = wrapper.querySelector('.icos-joystick-header'), knob = wrapper.querySelector('.icos-joystick-knob'); new Draggable(wrapper, header, false);
const config = document.createElement('div'); config.className = 'icos-joy-config'; config.id = `joy-conf-${id}`;
config.innerHTML = `<div class="icos-flex-between" style="margin-bottom:8px;"><span style="font-size:12px; font-weight:bold; color:var(--icos-accent);">Joystick Unit</span><button class="icos-btn icos-btn-icon close">✖</button></div><div class="icos-row"><input type="text" class="icos-input j-n" placeholder="N" value="ArrowUp"><input type="text" class="icos-input j-s" placeholder="S" value="ArrowDown"></div><div class="icos-row"><input type="text" class="icos-input j-w" placeholder="W" value="ArrowLeft"><input type="text" class="icos-input j-e" placeholder="E" value="ArrowRight"></div>`;
config.querySelector('.close').onclick = () => { wrapper.remove(); config.remove(); this.joysticks = this.joysticks.filter(j => j.id !== id); Toast.show('Joystick destroyed.', 'var(--icos-danger)'); };
this.listEl.appendChild(config);
const joyData = { id: id, wrapper: wrapper, knob: knob, configUI: config, binds: { N: 'ArrowUp', S: 'ArrowDown', W: 'ArrowLeft', E: 'ArrowRight' }, activeKeys: new Set(), isDragging: false, center: {x:0, y:0} };
['n', 's', 'w', 'e'].forEach(dir => { config.querySelector(`.j-${dir}`).addEventListener('input', (e) => { joyData.binds[dir.toUpperCase()] = e.target.value; }); });
joyData.updateVisualFromHardware = () => { if (joyData.isDragging) return; const R = wrapper.getBoundingClientRect().width / 2; const MAX_TRAVEL = R * 0.8; let dx = 0, dy = 0; if (STATE.heldKeys.has(joyData.binds.N)) dy -= 1; if (STATE.heldKeys.has(joyData.binds.S)) dy += 1; if (STATE.heldKeys.has(joyData.binds.W)) dx -= 1; if (STATE.heldKeys.has(joyData.binds.E)) dx += 1; if (dx !== 0 && dy !== 0) { const norm = Math.sqrt(0.5); dx *= norm; dy *= norm; } knob.style.transform = `translate(calc(-50% + ${dx * MAX_TRAVEL}px), calc(-50% + ${dy * MAX_TRAVEL}px))`; };
knob.addEventListener('mousedown', (e) => { joyData.isDragging = true; const rect = wrapper.getBoundingClientRect(); joyData.center = { x: rect.left + rect.width/2, y: rect.top + rect.height/2 }; document.body.style.userSelect = 'none'; e.stopPropagation(); });
window.addEventListener('mouseup', () => { if (joyData.isDragging) { joyData.isDragging = false; knob.style.transform = `translate(-50%, -50%)`; document.body.style.userSelect = ''; joyData.activeKeys.forEach(k => InputSimulator.dispatchKey('keyup', k)); joyData.activeKeys.clear(); } });
window.addEventListener('mousemove', (e) => {
if (!joyData.isDragging) return; const R = wrapper.getBoundingClientRect().width / 2; let dx = e.clientX - joyData.center.x, dy = e.clientY - joyData.center.y, dist = Math.sqrt(dx*dx + dy*dy), angle = Math.atan2(dy, dx);
if (dist > R) { dx = Math.cos(angle) * R; dy = Math.sin(angle) * R; dist = R; } knob.style.transform = `translate(calc(-50% + ${dx}px), calc(-50% + ${dy}px))`;
if (dist > R * 0.25) {
let deg = angle * (180 / Math.PI); if (deg < 0) deg += 360; let targetKeys = new Set();
if (deg >= 337.5 || deg < 22.5) targetKeys.add(joyData.binds.E); else if (deg >= 22.5 && deg < 67.5) { targetKeys.add(joyData.binds.E); targetKeys.add(joyData.binds.S); } else if (deg >= 67.5 && deg < 112.5) targetKeys.add(joyData.binds.S); else if (deg >= 112.5 && deg < 157.5) { targetKeys.add(joyData.binds.S); targetKeys.add(joyData.binds.W); } else if (deg >= 157.5 && deg < 202.5) targetKeys.add(joyData.binds.W); else if (deg >= 202.5 && deg < 247.5) { targetKeys.add(joyData.binds.W); targetKeys.add(joyData.binds.N); } else if (deg >= 247.5 && deg < 292.5) targetKeys.add(joyData.binds.N); else if (deg >= 292.5 && deg < 337.5) { targetKeys.add(joyData.binds.N); targetKeys.add(joyData.binds.E); }
joyData.activeKeys.forEach(k => { if (!targetKeys.has(k)) InputSimulator.dispatchKey('keyup', k); }); targetKeys.forEach(k => { if (!joyData.activeKeys.has(k)) InputSimulator.dispatchKey('keydown', k); }); joyData.activeKeys = targetKeys;
} else { joyData.activeKeys.forEach(k => InputSimulator.dispatchKey('keyup', k)); joyData.activeKeys.clear(); }
});
this.joysticks.push(joyData); Toast.show('Joystick generated.');
}
toggleVisibility() { STATE.joysticksHidden = !STATE.joysticksHidden; this.joysticks.forEach(j => { j.wrapper.style.display = STATE.joysticksHidden ? 'none' : 'flex'; }); Toast.show(STATE.joysticksHidden ? 'Joysticks hidden' : 'Joysticks revealed'); }
syncAllHardwareVisuals() { this.joysticks.forEach(j => j.updateVisualFromHardware()); }
}
const root = document.createElement('div'); root.id = 'icos-root';
root.innerHTML = `
<div class="icos-rgb-wrapper"></div>
<div id="icos-inner">
<div id="icos-header"><div class="icos-header-title"><span style="font-size:16px;">⚡</span> Dominum Macro V1</div><div class="icos-header-controls"><button id="icos-btn-min" class="icos-btn-icon" title="Minimize">🗕</button><button id="icos-btn-close" class="icos-btn-icon close" title="Close">✖</button></div></div>
<div id="icos-body">
<div class="icos-section"><h3 class="icos-section-title">System Themes</h3><div class="icos-row"><select id="icos-theme-sel" class="icos-select" style="flex: 2;"><option value="dark">Dark Matter</option><option value="light">Light Clean</option><option value="cyberpunk">Cyberpunk 2077</option><option value="synthwave">Synthwave</option><option value="hacker">Hacker (Matrix)</option><option value="dracula">Dracula</option><option value="nord">Nord</option><option value="monokai">Monokai</option><option value="gruvbox">Gruvbox</option><option value="oceanic">Oceanic</option><option value="crimson">Crimson</option><option value="amethyst">Amethyst</option><option value="bumblebee">Bumblebee</option><option value="neon_tokyo">Neon Tokyo</option><option value="midnight">Midnight</option><option value="forest">Forest</option><option value="sunset">Sunset</option></select><button id="icos-perf-btn" class="icos-btn" style="flex: 1; font-size: 11px;">Perf Mode</button><button id="icos-rgb-btn" class="icos-btn" style="flex: 1; font-size: 11px;">RGB Off</button></div><span class="icos-hint" style="margin-top:4px;">Press <b>\`</b> (Backtick) to hide/show this panel in-game.</span></div>
<div class="icos-section"><h3 class="icos-section-title">Click Keybinds</h3><div id="icos-binds-container" style="margin-bottom: 10px; display:flex; flex-direction:column; gap:5px;"></div><button id="icos-add-bind-btn" class="icos-btn icos-btn-primary" style="width: 100%;">+ Spawn Target Marker</button></div>
<div class="icos-section"><div class="icos-flex-between" style="margin-bottom:12px;"><h3 class="icos-section-title" style="margin:0;">Joysticks</h3><button id="icos-hide-joy-btn" class="icos-btn" style="padding:4px 8px; font-size:11px;">Toggle Vis</button></div><div id="icos-joysticks-container"></div><button id="icos-add-joy-btn" class="icos-btn icos-btn-primary" style="width: 100%;">+ Spawn Joystick Unit</button></div>
<div class="icos-section"><h3 class="icos-section-title">Macro (WIP, Might not work)</h3><span class="icos-hint">Records physical keys and physical mouse clicks globally.</span><div class="icos-row"><button id="icos-mac-rec" class="icos-btn" style="flex:1;">⏺ Record</button><button id="icos-mac-play" class="icos-btn" style="flex:1;">▶ Play</button></div><button id="icos-mac-clear" class="icos-btn icos-btn-danger" style="width:100%; margin-top:4px;">⏹ Clear Memory</button><div id="icos-mac-status" style="margin-top:10px; font-size:12px; color:var(--icos-accent); text-align:center; font-family:monospace;">Memory: 0 events</div></div>
</div>
</div>
`;
document.body.appendChild(root); Toast.init();
const bindManager = new BindManager(document.getElementById('icos-binds-container')), joyManager = new JoystickManager(document.getElementById('icos-joysticks-container')); new Draggable(root, document.getElementById('icos-header'), false);
document.getElementById('icos-btn-close').onclick = () => { root.style.display = 'none'; Toast.show('Input Core shutdown.', 'var(--icos-danger)'); };
document.getElementById('icos-btn-min').onclick = () => { STATE.minimized = !STATE.minimized; STATE.minimized ? (root.classList.add('icos-minimized'), document.getElementById('icos-btn-min').innerText = '🗖') : (root.classList.remove('icos-minimized'), document.getElementById('icos-btn-min').innerText = '🗕'); };
document.getElementById('icos-theme-sel').onchange = (e) => { STATE.theme = e.target.value; root.setAttribute('data-icos-theme', STATE.theme); Toast.show(`Theme: ${STATE.theme}`); };
document.getElementById('icos-perf-btn').onclick = () => { STATE.perfMode = !STATE.perfMode; if(STATE.perfMode) { root.classList.add('icos-perf'); document.getElementById('icos-perf-btn').style.color = 'var(--icos-accent)'; Toast.show('Performance Mode ON', 'var(--icos-success)'); } else { root.classList.remove('icos-perf'); document.getElementById('icos-perf-btn').style.color = ''; Toast.show('Performance Mode OFF'); } };
document.getElementById('icos-rgb-btn').onclick = () => { STATE.rgbEnabled = !STATE.rgbEnabled; STATE.rgbEnabled ? (root.classList.add('rgb-active'), document.getElementById('icos-rgb-btn').innerText = 'RGB On', document.getElementById('icos-rgb-btn').style.color = 'var(--icos-accent)') : (root.classList.remove('rgb-active'), document.getElementById('icos-rgb-btn').innerText = 'RGB Off', document.getElementById('icos-rgb-btn').style.color = ''); };
document.getElementById('icos-add-bind-btn').onclick = () => bindManager.addBind(); document.getElementById('icos-add-joy-btn').onclick = () => joyManager.addJoystick(); document.getElementById('icos-hide-joy-btn').onclick = () => joyManager.toggleVisibility();
const recBtn = document.getElementById('icos-mac-rec'), playBtn = document.getElementById('icos-mac-play'), statTxt = document.getElementById('icos-mac-status');
recBtn.onclick = () => { if (STATE.isRecordingMacro) { STATE.isRecordingMacro = false; recBtn.innerText = '⏺ Record'; recBtn.style.color = ''; recBtn.style.borderColor = ''; statTxt.innerText = `Memory: ${STATE.macroData.length} events loaded`; Toast.show('Macro saved.'); } else { STATE.macroData = []; STATE.macroStart = Date.now(); STATE.isRecordingMacro = true; recBtn.innerText = '⏹ Stop Rec'; recBtn.style.color = 'var(--icos-danger)'; recBtn.style.borderColor = 'var(--icos-danger)'; statTxt.innerText = 'Recording...'; Toast.show('Recording started...', 'var(--icos-danger)'); } };
playBtn.onclick = () => { if (STATE.macroData.length === 0 || STATE.isRecordingMacro) return; statTxt.innerText = 'Executing Macro...'; STATE.macroTimers.forEach(clearTimeout); STATE.macroTimers = []; STATE.macroData.forEach((action, idx) => { let to = setTimeout(() => { if (action.type === 'keydown' || action.type === 'keyup') InputSimulator.dispatchKey(action.type, action.code); else if (action.type === 'mousedown' || action.type === 'mouseup') InputSimulator.dispatchTouch(action.type === 'mousedown' ? 'down' : 'up', action.x, action.y, 999); if (idx === STATE.macroData.length - 1) { statTxt.innerText = `Memory: ${STATE.macroData.length} events loaded`; Toast.show('Macro finished.'); } }, action.time); STATE.macroTimers.push(to); }); Toast.show('Playing macro...'); };
document.getElementById('icos-mac-clear').onclick = () => { STATE.macroData = []; STATE.macroTimers.forEach(clearTimeout); statTxt.innerText = 'Memory: 0 events'; Toast.show('Memory cleared.', 'var(--icos-danger)'); };
window.addEventListener('keydown', (e) => {
if (e.key === '`' && e.target.tagName !== 'INPUT') { STATE.hidden = !STATE.hidden; STATE.hidden ? (root.classList.add('icos-hidden'), bindManager.binds.forEach(b => b.marker.style.display = 'none')) : (root.classList.remove('icos-hidden'), bindManager.binds.forEach(b => b.marker.style.display = 'flex')); return; }
if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') return;
if (!STATE.heldKeys.has(e.key)) { STATE.heldKeys.add(e.key); bindManager.handleKeyDown(e.key); joyManager.syncAllHardwareVisuals(); }
if (STATE.isRecordingMacro && !STATE.heldKeys.has('mac_'+e.key)) { STATE.heldKeys.add('mac_'+e.key); STATE.macroData.push({ time: Date.now() - STATE.macroStart, type: 'keydown', code: e.key }); statTxt.innerText = `Recording... [${STATE.macroData.length}]`; }
});
window.addEventListener('keyup', (e) => {
if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') return;
STATE.heldKeys.delete(e.key); bindManager.handleKeyUp(e.key); joyManager.syncAllHardwareVisuals();
if (STATE.isRecordingMacro) { STATE.heldKeys.delete('mac_'+e.key); STATE.macroData.push({ time: Date.now() - STATE.macroStart, type: 'keyup', code: e.key }); statTxt.innerText = `Recording... [${STATE.macroData.length}]`; }
});
window.addEventListener('mousedown', (e) => { if (e.target.closest('#icos-root') || e.target.closest('.icos-joystick-container') || e.target.closest('.icos-marker')) return; if (STATE.isRecordingMacro) STATE.macroData.push({ time: Date.now() - STATE.macroStart, type: 'mousedown', x: e.clientX, y: e.clientY }); });
window.addEventListener('mouseup', (e) => { if (e.target.closest('#icos-root') || e.target.closest('.icos-joystick-container') || e.target.closest('.icos-marker')) return; if (STATE.isRecordingMacro) STATE.macroData.push({ time: Date.now() - STATE.macroStart, type: 'mouseup', x: e.clientX, y: e.clientY }); });
setTimeout(() => { Toast.show('Dominum Macro Initialized. Press ` to hide UI.', 'var(--icos-success)'); }, 500);
})();