Floating moon notepad for war targets & reminders
// ==UserScript==
// @name Moon Lust Note Pad
// @namespace https://www.torn.com
// @version 1.3
// @description Floating moon notepad for war targets & reminders
// @author You
// @match https://www.torn.com/*
// @grant GM_addStyle
// ==/UserScript==
(function() {
'use strict';
GM_addStyle(`
#moon-lust-icon {
position: fixed;
top: 150px;
left: 50px;
z-index: 999999;
cursor: move;
user-select: none;
filter: drop-shadow(0 0 8px #000);
}
.moon-container {
width: 68px;
height: 68px;
background: radial-gradient(circle at 40% 40%, #f4f4f4, #c5c5c5 40%, #a8a8a8);
border-radius: 50%;
border: 3px solid #3a0000;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
box-shadow: 0 4px 12px rgba(0,0,0,0.6),
inset 0 0 15px #fff,
inset -10px -10px 20px rgba(0,0,0,0.4);
color: #3a0000;
font-family: Georgia, serif;
text-align: center;
line-height: 1;
}
.moon-container span { font-size: 42px; margin-bottom: -4px; }
.moon-container .label {
font-size: 9px;
letter-spacing: 1.5px;
font-weight: bold;
text-transform: uppercase;
margin-top: 2px;
}
#moon-lust-modal {
display: none;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 1000000;
width: 640px;
height: 560px;
background: linear-gradient(#3a0000, #1f0000);
border: 14px solid #1f0000;
border-radius: 8px;
box-shadow: 0 0 30px rgba(0,0,0,0.9),
inset 0 0 80px rgba(139,0,0,0.3);
overflow: hidden;
animation: bookOpen 0.5s ease-out forwards;
}
@keyframes bookOpen {
from { opacity: 0; transform: translate(-50%, -50%) scale(0.7) rotate(-8deg); }
to { opacity: 1; transform: translate(-50%, -50%) scale(1) rotate(0deg); }
}
#moon-lust-modal::before {
content: '';
position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
background: radial-gradient(circle at 30% 20%, rgba(255,255,255,0.12) 0%, transparent 50%),
linear-gradient(#f5e8c7 0%, #f0d9a8 100%);
opacity: 0.94;
z-index: 1;
box-shadow: inset 0 0 60px rgba(0,0,0,0.5);
}
#moon-lust-modal::after {
content: '';
position: absolute;
top: -20px; left: 50%;
width: 6px; height: 40px;
background: linear-gradient(transparent, #8B0000, #5c0000);
animation: bloodDrip 4s linear infinite;
z-index: 3; opacity: 0.6;
box-shadow: 0 0 8px #8B0000;
}
@keyframes bloodDrip { 0% { transform: translateY(-30px); } 100% { transform: translateY(620px); } }
.blood-drip {
position: absolute;
width: 4px; height: 25px;
background: #8B0000;
animation: bloodDrip2 3.5s linear infinite;
z-index: 3; opacity: 0.4;
}
.modal-content {
position: relative;
z-index: 2;
height: 100%;
padding: 20px;
display: flex;
flex-direction: column;
color: #8B0000;
font-family: Georgia, serif;
box-sizing: border-box;
}
.modal-header {
display: flex; justify-content: space-between; align-items: center;
margin-bottom: 15px; border-bottom: 3px solid #8B0000; padding-bottom: 8px;
}
.modal-header h1 {
font-size: 28px; margin: 0; color: #8B0000;
text-shadow: 2px 2px 4px #3a0000; letter-spacing: 2px;
}
.close-btn { font-size: 32px; cursor: pointer; color: #8B0000; }
.close-btn:hover { color: #5c0000; }
.tabs { display: flex; margin-bottom: 15px; border-bottom: 2px solid #8B0000; }
.tab {
padding: 10px 22px; cursor: pointer; font-size: 17px;
background: #f5e8c7; border: 3px solid #8B0000; border-bottom: none;
border-radius: 8px 8px 0 0; margin-right: 4px; position: relative;
}
.tab.active { background: #f0d9a8; font-weight: bold; }
.tab-badge {
position: absolute; top: -8px; right: -8px;
background: #5c0000; color: #f5e8c7; font-size: 11px;
padding: 1px 6px; border-radius: 50%; border: 2px solid #3a0000;
}
.tab-content {
flex: 1; background: #f5e8c7; border: 3px solid #8B0000;
padding: 15px; border-radius: 0 8px 8px 8px;
overflow-y: auto; box-shadow: inset 0 0 30px rgba(0,0,0,0.3);
}
.add-row { display: flex; gap: 8px; margin-bottom: 12px; }
.add-row input {
flex: 1; padding: 9px; border: 2px solid #8B0000;
background: #fffef0; font-family: Georgia, serif; font-size: 15px;
}
.add-btn {
padding: 9px 18px; background: #8B0000; color: #f5e8c7;
border: 2px solid #3a0000; cursor: pointer; font-weight: bold;
}
ul { list-style: none; padding: 0; margin: 0; }
li {
padding: 9px 12px; background: #fffef0; margin-bottom: 6px;
border: 2px solid #8B0000; display: flex; align-items: center;
font-size: 16px; gap: 10px;
}
li.done { opacity: 0.75; }
li.done span.text { text-decoration: line-through; color: #5c0000; }
.checkbox {
width: 18px; height: 18px; border: 2px solid #8B0000;
background: #fff; cursor: pointer; flex-shrink: 0;
display: flex; align-items: center; justify-content: center;
font-size: 14px;
}
.delete-btn { margin-left: auto; color: #8B0000; cursor: pointer; font-size: 19px; }
.clear-btn {
margin-top: 12px; padding: 7px 16px;
background: #8B0000; color: #f5e8c7;
border: 2px solid #3a0000; cursor: pointer; float: right;
}
li.editing { padding: 4px; }
li.editing input {
flex: 1; background: #fffef0; border: 2px solid #5c0000;
color: #8B0000; font-family: Georgia, serif;
}
/* Resize handles */
.resize-handle {
position: absolute; z-index: 1000001; background: transparent;
}
.n { top: -4px; left: 0; right: 0; height: 8px; cursor: ns-resize; }
.s { bottom: -4px; left: 0; right: 0; height: 8px; cursor: ns-resize; }
.e { right: -4px; top: 0; bottom: 0; width: 8px; cursor: ew-resize; }
.w { left: -4px; top: 0; bottom: 0; width: 8px; cursor: ew-resize; }
.nw { top: -6px; left: -6px; width: 12px; height: 12px; cursor: nwse-resize; }
.ne { top: -6px; right: -6px; width: 12px; height: 12px; cursor: nesw-resize; }
.sw { bottom: -6px; left: -6px; width: 12px; height: 12px; cursor: nesw-resize; }
.se { bottom: -6px; right: -6px; width: 12px; height: 12px; cursor: nwse-resize; }
`);
// ==================== FLOATING MOON ====================
const icon = document.createElement('div');
icon.id = 'moon-lust-icon';
icon.innerHTML = `<div class="moon-container"><span>🌕</span><div class="label">MOON LUST</div></div>`;
document.body.appendChild(icon);
// Load position
let savedPos = localStorage.getItem('moonlust_position');
if (savedPos) {
const pos = JSON.parse(savedPos);
icon.style.top = pos.top + 'px';
icon.style.left = pos.left + 'px';
}
// Draggable icon
let isDraggingIcon = false;
let offsetX, offsetY;
icon.addEventListener('mousedown', e => {
isDraggingIcon = true;
offsetX = e.clientX - icon.getBoundingClientRect().left;
offsetY = e.clientY - icon.getBoundingClientRect().top;
icon.style.transition = 'none';
});
document.addEventListener('mousemove', e => {
if (isDraggingIcon) {
let t = Math.max(0, Math.min(e.clientY - offsetY, window.innerHeight - 80));
let l = Math.max(0, Math.min(e.clientX - offsetX, window.innerWidth - 80));
icon.style.top = t + 'px';
icon.style.left = l + 'px';
}
});
document.addEventListener('mouseup', () => {
if (isDraggingIcon) {
isDraggingIcon = false;
icon.style.transition = 'top 0.2s, left 0.2s';
localStorage.setItem('moonlust_position', JSON.stringify({
top: parseFloat(icon.style.top),
left: parseFloat(icon.style.left)
}));
}
});
// ==================== MODAL ====================
const modal = document.createElement('div');
modal.id = 'moon-lust-modal';
modal.innerHTML = `
<div class="modal-content">
<div class="modal-header">
<h1>🌕 MOON LUST NOTE PAD</h1>
<div class="close-btn">✕</div>
</div>
<div class="tabs">
<div class="tab active" data-tab="war">War List <span class="tab-badge" id="badge-war">0</span></div>
<div class="tab" data-tab="reminders">Reminders <span class="tab-badge" id="badge-reminders">0</span></div>
<div class="tab" data-tab="notes">Quick Notes <span class="tab-badge" id="badge-notes">0</span></div>
</div>
<div id="war-content" class="tab-content">
<div class="add-row"><input type="text" id="war-input" placeholder="Player name or ID"><button class="add-btn">ADD</button></div>
<ul id="war-list"></ul>
<button class="clear-btn">CLEAR ALL WAR LIST</button>
</div>
<div id="reminders-content" class="tab-content" style="display:none;">
<div class="add-row"><input type="text" id="reminder-input" placeholder="Reminder text"><button class="add-btn">ADD</button></div>
<ul id="reminder-list"></ul>
<button class="clear-btn">CLEAR ALL REMINDERS</button>
</div>
<div id="notes-content" class="tab-content" style="display:none;">
<div class="add-row"><input type="text" id="note-input" placeholder="Quick note..."><button class="add-btn">ADD</button></div>
<ul id="note-list"></ul>
<button class="clear-btn">CLEAR ALL NOTES</button>
</div>
</div>
<!-- Resize handles -->
<div class="resize-handle n" data-dir="n"></div>
<div class="resize-handle s" data-dir="s"></div>
<div class="resize-handle e" data-dir="e"></div>
<div class="resize-handle w" data-dir="w"></div>
<div class="resize-handle nw" data-dir="nw"></div>
<div class="resize-handle ne" data-dir="ne"></div>
<div class="resize-handle sw" data-dir="sw"></div>
<div class="resize-handle se" data-dir="se"></div>
`;
document.body.appendChild(modal);
// Load saved size
modal.style.width = (localStorage.getItem('moonlust_width') || 640) + 'px';
modal.style.height = (localStorage.getItem('moonlust_height') || 560) + 'px';
// Extra blood drips
for (let i = 0; i < 3; i++) {
const drip = document.createElement('div');
drip.className = 'blood-drip';
drip.style.left = (35 + i * 22) + '%';
drip.style.animationDelay = (i * 0.6) + 's';
modal.appendChild(drip);
}
// Tab switching
const tabs = modal.querySelectorAll('.tab');
const contents = {
war: modal.querySelector('#war-content'),
reminders: modal.querySelector('#reminders-content'),
notes: modal.querySelector('#notes-content')
};
tabs.forEach(tab => tab.addEventListener('click', () => {
tabs.forEach(t => t.classList.remove('active'));
tab.classList.add('active');
Object.keys(contents).forEach(k => contents[k].style.display = (tab.dataset.tab === k) ? 'block' : 'none');
}));
// Data
let warListData = JSON.parse(localStorage.getItem('moonlust_warlist')) || [];
let reminderListData = JSON.parse(localStorage.getItem('moonlust_reminders')) || [];
let noteListData = JSON.parse(localStorage.getItem('moonlust_notes')) || [];
function updateBadges() {
modal.querySelector('#badge-war').textContent = warListData.length;
modal.querySelector('#badge-reminders').textContent = reminderListData.length;
modal.querySelector('#badge-notes').textContent = noteListData.length;
}
function renderWarList() {
const ul = modal.querySelector('#war-list'); ul.innerHTML = '';
warListData.forEach((item, i) => {
const li = document.createElement('li');
li.innerHTML = `${item}<span class="delete-btn" data-index="${i}" data-tab="war">✕</span>`;
li.dataset.index = i; li.dataset.tab = 'war';
ul.appendChild(li);
});
updateBadges();
}
function renderReminderList() {
const ul = modal.querySelector('#reminder-list'); ul.innerHTML = '';
reminderListData.forEach((item, i) => {
const li = document.createElement('li');
li.className = item.done ? 'done' : '';
li.innerHTML = `
<div class="checkbox" data-index="${i}">${item.done ? '✔' : ''}</div>
<span class="text">${item.text}</span>
<span class="delete-btn" data-index="${i}" data-tab="reminders">✕</span>
`;
li.dataset.index = i; li.dataset.tab = 'reminders';
ul.appendChild(li);
});
updateBadges();
}
function renderNoteList() {
const ul = modal.querySelector('#note-list'); ul.innerHTML = '';
noteListData.forEach((item, i) => {
const li = document.createElement('li');
li.innerHTML = `${item}<span class="delete-btn" data-index="${i}" data-tab="notes">✕</span>`;
li.dataset.index = i; li.dataset.tab = 'notes';
ul.appendChild(li);
});
updateBadges();
}
// Add functions
function addWar() {
const input = modal.querySelector('#war-input');
if (input.value.trim()) { warListData.unshift(input.value.trim()); localStorage.setItem('moonlust_warlist', JSON.stringify(warListData)); renderWarList(); input.value = ''; }
}
function addReminder() {
const input = modal.querySelector('#reminder-input');
if (input.value.trim()) { reminderListData.unshift({text: input.value.trim(), done: false}); localStorage.setItem('moonlust_reminders', JSON.stringify(reminderListData)); renderReminderList(); input.value = ''; }
}
function addNote() {
const input = modal.querySelector('#note-input');
if (input.value.trim()) { noteListData.unshift(input.value.trim()); localStorage.setItem('moonlust_notes', JSON.stringify(noteListData)); renderNoteList(); input.value = ''; }
}
// Click handlers
modal.addEventListener('click', e => {
if (e.target.classList.contains('checkbox')) {
const idx = parseInt(e.target.dataset.index);
reminderListData[idx].done = !reminderListData[idx].done;
localStorage.setItem('moonlust_reminders', JSON.stringify(reminderListData));
renderReminderList();
}
if (e.target.classList.contains('delete-btn')) {
const idx = parseInt(e.target.dataset.index);
const tab = e.target.dataset.tab;
if (tab === 'war') { warListData.splice(idx, 1); localStorage.setItem('moonlust_warlist', JSON.stringify(warListData)); renderWarList(); }
else if (tab === 'reminders') { reminderListData.splice(idx, 1); localStorage.setItem('moonlust_reminders', JSON.stringify(reminderListData)); renderReminderList(); }
else if (tab === 'notes') { noteListData.splice(idx, 1); localStorage.setItem('moonlust_notes', JSON.stringify(noteListData)); renderNoteList(); }
}
if (e.target.textContent.includes('CLEAR ALL WAR')) { warListData = []; localStorage.setItem('moonlust_warlist', '[]'); renderWarList(); }
if (e.target.textContent.includes('CLEAR ALL REMINDERS')) { reminderListData = []; localStorage.setItem('moonlust_reminders', '[]'); renderReminderList(); }
if (e.target.textContent.includes('CLEAR ALL NOTES')) { noteListData = []; localStorage.setItem('moonlust_notes', '[]'); renderNoteList(); }
});
// Double-click to edit
modal.addEventListener('dblclick', e => {
let li = e.target.closest('li');
if (!li) return;
const tab = li.dataset.tab;
const idx = parseInt(li.dataset.index);
const input = document.createElement('input');
input.value = tab === 'war' ? warListData[idx] : (tab === 'notes' ? noteListData[idx] : reminderListData[idx].text);
li.classList.add('editing');
li.innerHTML = '';
li.appendChild(input);
input.focus();
input.select();
const save = () => {
const newVal = input.value.trim();
if (newVal) {
if (tab === 'war') warListData[idx] = newVal;
else if (tab === 'notes') noteListData[idx] = newVal;
else reminderListData[idx].text = newVal;
localStorage.setItem('moonlust_' + tab, JSON.stringify(tab === 'war' ? warListData : tab === 'notes' ? noteListData : reminderListData));
}
if (tab === 'war') renderWarList();
else if (tab === 'notes') renderNoteList();
else renderReminderList();
};
input.addEventListener('blur', save);
input.addEventListener('keypress', ev => { if (ev.key === 'Enter') save(); });
});
// Resize
let isResizing = false, startX, startY, startW, startH, resizeDir;
modal.addEventListener('mousedown', e => {
const handle = e.target.closest('.resize-handle');
if (handle) {
isResizing = true;
resizeDir = handle.dataset.dir;
startX = e.clientX; startY = e.clientY;
startW = modal.offsetWidth; startH = modal.offsetHeight;
e.stopImmediatePropagation();
}
});
document.addEventListener('mousemove', e => {
if (!isResizing) return;
let newW = startW, newH = startH;
if (resizeDir.includes('e')) newW = Math.max(380, startW + (e.clientX - startX));
if (resizeDir.includes('w')) newW = Math.max(380, startW - (e.clientX - startX));
if (resizeDir.includes('s')) newH = Math.max(320, startH + (e.clientY - startY));
if (resizeDir.includes('n')) newH = Math.max(320, startH - (e.clientY - startY));
modal.style.width = newW + 'px';
modal.style.height = newH + 'px';
});
document.addEventListener('mouseup', () => {
if (isResizing) {
isResizing = false;
localStorage.setItem('moonlust_width', modal.offsetWidth);
localStorage.setItem('moonlust_height', modal.offsetHeight);
}
});
// Open modal on icon click
icon.addEventListener('click', e => {
if (isDraggingIcon) return;
renderWarList();
renderReminderList();
renderNoteList();
modal.style.display = 'block';
});
modal.querySelector('.close-btn').addEventListener('click', () => modal.style.display = 'none');
// Enter key support
modal.addEventListener('keypress', e => {
if (e.key === 'Enter') {
const active = modal.querySelector('.tab.active').dataset.tab;
if (active === 'war') addWar();
else if (active === 'reminders') addReminder();
else if (active === 'notes') addNote();
}
});
modal.querySelectorAll('.add-btn').forEach(btn => {
btn.addEventListener('click', () => {
const active = modal.querySelector('.tab.active').dataset.tab;
if (active === 'war') addWar();
else if (active === 'reminders') addReminder();
else if (active === 'notes') addNote();
});
});
console.log('%c🌕 Moon Lust Note Pad v1.3 - fully working + resizable', 'color:#8B0000; font-family:Georgia');
})();