// ==UserScript==
// @name Torn Christmas Town D-Pad
// @namespace https://torn.com
// @version 2.1
// @description Adds an 8-direction D-pad controller for navigating Christmas Town
// @author ANITABURN
// @match https://www.torn.com/christmas_town.php*
// @grant GM_addStyle
// @license MIT
// @downloadURL https://update.greasyfork.icu/scripts/559521/Torn%20Christmas%20Town%20D-Pad.user.js
// @updateURL https://update.greasyfork.icu/scripts/559521/Torn%20Christmas%20Town%20D-Pad.meta.js
// ==/UserScript==
(function() {
'use strict';
function triggerKeyEvent(key, type) {
const event = new KeyboardEvent(type, {
key: key,
code: key,
keyCode: { 'ArrowUp': 38, 'ArrowDown': 40, 'ArrowLeft': 37, 'ArrowRight': 39 }[key],
bubbles: true,
cancelable: true,
composed: true
});
document.dispatchEvent(event);
}
const directionKeys = {
'left-top': ['ArrowLeft', 'ArrowUp'],
'top': ['ArrowUp'],
'right-top': ['ArrowRight', 'ArrowUp'],
'left': ['ArrowLeft'],
'right': ['ArrowRight'],
'left-bottom': ['ArrowLeft', 'ArrowDown'],
'bottom': ['ArrowDown'],
'right-bottom': ['ArrowRight', 'ArrowDown']
};
GM_addStyle(`
.ct-dpad-container {
display: flex;
justify-content: center;
align-items: center;
padding: 10px;
background: linear-gradient(180deg, #333 0%, #333 100%);
border-top: 1px solid #333;
}
.ct-dpad {
display: grid;
grid-template-columns: 42px 42px 42px;
grid-template-rows: 42px 42px 42px;
gap: 6px;
}
.ct-dpad-btn {
width: 42px;
height: 42px;
border: none;
border-radius: 6px;
background: linear-gradient(180deg, #666 0%, #666 100%);
color: #fff;
font-size: 16px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 2px 4px rgba(0,0,0,0.3), inset 0 1px 0 rgba(255,255,255,0.2);
user-select: none;
opacity: 0.9;
}
.ct-dpad-btn:active {
opacity: 1.0;
background: linear-gradient(180deg, #666 0%, #666 100%);
}
.ct-dpad-btn svg {
width: 22px;
height: 22px;
fill: currentColor;
}
.ct-dpad-btn.ct-dpad-center {
visibility: hidden;
}
.ct-dpad-left-top { grid-column: 1; grid-row: 1; }
.ct-dpad-top { grid-column: 2; grid-row: 1; }
.ct-dpad-right-top { grid-column: 3; grid-row: 1; }
.ct-dpad-left { grid-column: 1; grid-row: 2; }
.ct-dpad-center { grid-column: 2; grid-row: 2; }
.ct-dpad-right { grid-column: 3; grid-row: 2; }
.ct-dpad-left-bottom { grid-column: 1; grid-row: 3; }
.ct-dpad-bottom { grid-column: 2; grid-row: 3; }
.ct-dpad-right-bottom { grid-column: 3; grid-row: 3; }
`);
function createDpad() {
const container = document.createElement('div');
container.className = 'ct-dpad-container';
const dpad = document.createElement('div');
dpad.className = 'ct-dpad';
const arrows = {
'left-top': ``,
'top': ``,
'right-top': ``,
'left': ``,
'right': ``,
'left-bottom': ``,
'bottom': ``,
'right-bottom': ``
};
const directions = [
'left-top', 'top', 'right-top',
'left', 'center', 'right',
'left-bottom', 'bottom', 'right-bottom'
];
directions.forEach(dir => {
const btn = document.createElement('div');
btn.className = `ct-dpad-btn ct-dpad-${dir}`;
if (dir !== 'center') {
btn.innerHTML = arrows[dir];
const keys = directionKeys[dir];
btn.addEventListener('touchstart', (e) => {
e.preventDefault();
keys.forEach(key => triggerKeyEvent(key, 'keydown'));
});
btn.addEventListener('touchend', (e) => {
e.preventDefault();
keys.forEach(key => triggerKeyEvent(key, 'keyup'));
});
btn.addEventListener('mousedown', () => {
keys.forEach(key => triggerKeyEvent(key, 'keydown'));
});
btn.addEventListener('mouseup', () => {
keys.forEach(key => triggerKeyEvent(key, 'keyup'));
});
btn.addEventListener('mouseleave', () => {
keys.forEach(key => triggerKeyEvent(key, 'keyup'));
});
}
dpad.appendChild(btn);
});
container.appendChild(dpad);
return container;
}
function insertDpad() {
const itemsContainer = document.querySelector('.items-container.itemsContainer___HEW8n') ||
document.querySelector('.items-container');
if (itemsContainer && !document.querySelector('.ct-dpad-container')) {
const dpad = createDpad();
itemsContainer.parentNode.insertBefore(dpad, itemsContainer);
console.log('[CT D-Pad] D-pad inserted successfully');
}
}
function init() {
insertDpad();
const observer = new MutationObserver(() => {
if (!document.querySelector('.ct-dpad-container')) {
insertDpad();
}
});
observer.observe(document.body, {
childList: true,
subtree: true
});
let attempts = 0;
const interval = setInterval(() => {
if (document.querySelector('.ct-dpad-container') || attempts > 20) {
clearInterval(interval);
} else {
insertDpad();
attempts++;
}
}, 500);
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
})();