// ==UserScript==
// @name Dice Color RNG Predictor
// @namespace http://tampermonkey.net/
// @version 1.3
// @description Persistent RNG dice color predictor with dark purple UI
// @author theo
// @match https://www.online-dice.com/roll-color-dice/3/*
// @include https://www.online-dice.com/*
// @grant GM_addStyle
// @grant GM_setValue
// @grant GM_getValue
// @description join our discord https://discord.gg/MuUCebSYSD
// ==/UserScript==
(function() {
'use strict';
// Check if we've already injected the UI
if (document.getElementById('dicePredictorContainer')) {
return;
}
// Dark purple UI styles
const css = `
#dicePredictorContainer {
position: fixed;
top: 20px;
right: 20px;
width: 320px;
background-color: #2a0a3a;
border: 2px solid #8a2be2;
border-radius: 10px;
padding: 15px;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
color: #e6d5ff;
z-index: 9999;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.5);
}
#dicePredictorTitle {
font-size: 18px;
font-weight: bold;
margin-bottom: 15px;
text-align: center;
color: #b388ff;
border-bottom: 1px solid #8a2be2;
padding-bottom: 8px;
position: relative;
}
.discord-icon {
position: absolute;
right: 0;
top: 0;
width: 24px;
height: 24px;
cursor: pointer;
transition: transform 0.2s;
}
.discord-icon:hover {
transform: scale(1.1);
}
/* [Rest of your existing CSS remains exactly the same] */
`;
// Add styles to head
GM_addStyle(css);
// Color definitions
const COLORS = {
'red': '#ff5252',
'orange': '#ff9800',
'yellow': '#ffeb3b',
'green': '#0f9d58',
'blue': '#4285f4',
'purple': '#9c27b0'
};
// Color names for display
const COLOR_NAMES = {
'red': 'Red',
'orange': 'Orange',
'yellow': 'Yellow',
'green': 'Green',
'blue': 'Blue',
'purple': 'Purple'
};
// Create container for our predictor
function createUI() {
const container = document.createElement('div');
container.id = 'dicePredictorContainer';
container.innerHTML = `
<div id="dicePredictorTitle">
Dice Color RNG Predictor
<svg class="discord-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 127.14 96.36">
<path fill="#5865F2" d="M107.7,8.07A105.15,105.15,0,0,0,81.47,0a72.06,72.06,0,0,0-3.36,6.83A97.68,97.68,0,0,0,49,6.83,72.37,72.37,0,0,0,45.64,0,105.89,105.89,0,0,0,19.39,8.09C2.79,32.65-1.71,56.6.54,80.21h0A105.73,105.73,0,0,0,32.71,96.36,77.7,77.7,0,0,0,39.6,85.25a68.42,68.42,0,0,1-10.85-5.18c.91-.66,1.8-1.34,2.66-2a75.57,75.57,0,0,0,64.32,0c.87.71,1.76,1.39,2.66,2a68.68,68.68,0,0,1-10.87,5.19,77,77,0,0,0,6.89,11.1A105.25,105.25,0,0,0,126.6,80.22h0C129.24,52.84,122.09,29.11,107.7,8.07ZM42.45,65.69C36.18,65.69,31,60,31,53s5-12.74,11.43-12.74S54,46,53.89,53,48.84,65.69,42.45,65.69Zm42.24,0C78.41,65.69,73.25,60,73.25,53s5-12.74,11.44-12.74S96.23,46,96.12,53,91.08,65.69,84.69,65.69Z"/>
</svg>
</div>
<div class="inputSection">
<label class="inputLabel" for="dice1Color">First Dice Color:</label>
<select class="colorSelect" id="dice1Color">
${Object.entries(COLORS).map(([value, color]) =>
`<option value="${value}">${COLOR_NAMES[value]}</option>`
).join('')}
</select>
<label class="inputLabel" for="dice2Color">Second Dice Color:</label>
<select class="colorSelect" id="dice2Color">
${Object.entries(COLORS).map(([value, color]) =>
`<option value="${value}">${COLOR_NAMES[value]}</option>`
).join('')}
</select>
<label class="inputLabel" for="dice3Color">Third Dice Color:</label>
<select class="colorSelect" id="dice3Color">
${Object.entries(COLORS).map(([value, color]) =>
`<option value="${value}">${COLOR_NAMES[value]}</option>`
).join('')}
</select>
<button id="predictButton">Generate Random Prediction</button>
</div>
<div id="predictionResult">
<div id="predictionText">Random prediction will appear here</div>
<div id="nextColorPrediction">?</div>
</div>
<div id="historyTitle">Prediction History</div>
<div id="historyList"></div>
`;
// Add to body
document.body.appendChild(container);
// Add click handler for Discord icon
document.querySelector('.discord-icon').addEventListener('click', () => {
window.open('https://discord.gg/MuUCebSYSD', '_blank');
});
// Load saved state
loadState();
// Set up predict button
document.getElementById('predictButton').addEventListener('click', makeRandomPrediction);
}
// [Rest of your existing functions remain exactly the same]
// Save current state
function saveState() {
const state = {
dice1: document.getElementById('dice1Color').value,
dice2: document.getElementById('dice2Color').value,
dice3: document.getElementById('dice3Color').value,
history: predictionHistory
};
GM_setValue('dicePredictorState', JSON.stringify(state));
}
// Load saved state
function loadState() {
const savedState = GM_getValue('dicePredictorState');
if (savedState) {
try {
const state = JSON.parse(savedState);
// Restore dropdown values
document.getElementById('dice1Color').value = state.dice1;
document.getElementById('dice2Color').value = state.dice2;
document.getElementById('dice3Color').value = state.dice3;
// Restore history
predictionHistory = state.history || [];
updateHistoryDisplay();
} catch (e) {
console.error('Failed to load state:', e);
}
}
}
// Track history of predictions
let predictionHistory = [];
const MAX_HISTORY = 15;
// Pure RNG prediction
function makeRandomPrediction() {
const color1 = document.getElementById('dice1Color').value;
const color2 = document.getElementById('dice2Color').value;
const color3 = document.getElementById('dice3Color').value;
const currentColors = [color1, color2, color3];
const allColors = Object.keys(COLORS);
const prediction = allColors[Math.floor(Math.random() * allColors.length)];
// Update prediction display
const predictionElement = document.getElementById('nextColorPrediction');
predictionElement.textContent = COLOR_NAMES[prediction];
predictionElement.style.backgroundColor = COLORS[prediction];
predictionElement.style.color = (prediction === 'yellow') ? '#000' : '#fff';
// Add to history
const time = new Date().toLocaleTimeString();
const historyEntry = {
time: time,
colors: currentColors,
prediction: prediction
};
predictionHistory.unshift(historyEntry);
if (predictionHistory.length > MAX_HISTORY) {
predictionHistory.pop();
}
updateHistoryDisplay();
saveState();
}
// Update history display
function updateHistoryDisplay() {
const historyList = document.getElementById('historyList');
if (!historyList) return;
historyList.innerHTML = '';
if (predictionHistory.length === 0) {
historyList.innerHTML = '<div style="text-align: center; color: #ba55d3; padding: 10px;">No predictions yet</div>';
return;
}
predictionHistory.forEach((entry, index) => {
const historyItem = document.createElement('div');
historyItem.className = 'historyItem';
historyItem.innerHTML = `
<div class="historyTime">${index + 1}. ${entry.time}</div>
<div class="historyColors">
${entry.colors.map(color => `
<div class="colorBox" style="background-color: ${COLORS[color]}; color: ${(color === 'yellow') ? '#000' : '#fff'}">
${COLOR_NAMES[color]}
</div>
`).join('')}
</div>
<div class="historyPrediction">
<span>Prediction:</span>
<div class="colorBox" style="background-color: ${COLORS[entry.prediction]}; color: ${(entry.prediction === 'yellow') ? '#000' : '#fff'}">
${COLOR_NAMES[entry.prediction]}
</div>
</div>
`;
historyList.appendChild(historyItem);
});
}
// Initialize with random selections
function randomizeInputs() {
const colors = Object.keys(COLORS);
document.getElementById('dice1Color').value = colors[Math.floor(Math.random() * colors.length)];
document.getElementById('dice2Color').value = colors[Math.floor(Math.random() * colors.length)];
document.getElementById('dice3Color').value = colors[Math.floor(Math.random() * colors.length)];
}
// Create the UI
createUI();
// Set up mutation observer to re-inject UI if removed
const observer = new MutationObserver(function(mutations) {
if (!document.getElementById('dicePredictorContainer')) {
createUI();
}
});
observer.observe(document.body, {
childList: true,
subtree: true
});
// Save state before page unload
window.addEventListener('beforeunload', saveState);
})();